uidex 0.3.0 → 0.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.
@@ -35,11 +35,16 @@ interface Route {
35
35
  path: string;
36
36
  page: string;
37
37
  }
38
+ interface FlowStep {
39
+ entityId: string;
40
+ action?: string;
41
+ }
38
42
  interface Flow {
39
43
  kind: "flow";
40
44
  id: string;
41
45
  loc: Location;
42
46
  touches: string[];
47
+ steps: FlowStep[];
43
48
  }
44
49
  interface Page extends EntityWithMetaBase {
45
50
  kind: "page";
@@ -278,15 +283,16 @@ interface FeedbackResult {
278
283
  sequenceNumber: number;
279
284
  externalLink?: FeedbackExternalLink;
280
285
  }
281
- interface IngestConfigEpic {
286
+ interface IngestConfigIssue {
287
+ id: string;
282
288
  key: string;
283
289
  summary: string;
284
- status: string;
290
+ issueType: string;
285
291
  }
286
292
  interface IngestConfig {
287
293
  hasJira: boolean;
288
294
  integrationId?: string;
289
- epics?: IngestConfigEpic[];
295
+ parentIssues?: IngestConfigIssue[];
290
296
  }
291
297
  /**
292
298
  * Generic so third-party adapters (e.g. `uidex-cloud`) can plug in their own
@@ -296,6 +302,12 @@ interface IngestConfig {
296
302
  */
297
303
  interface CloudAdapter<TPayload = FeedbackPayload, TResult = FeedbackResult, TIntegrations = {
298
304
  getConfig(): Promise<IngestConfig>;
305
+ /**
306
+ * Synchronous read of the eagerly-fetched config. Returns `null` until the
307
+ * initial fetch resolves; views that need a sync answer (e.g. detail
308
+ * actions deciding whether to surface a Jira button) read this.
309
+ */
310
+ getCachedConfig(): IngestConfig | null;
299
311
  }> {
300
312
  readonly feedback: {
301
313
  submit(payload: TPayload): Promise<TResult>;
@@ -327,6 +339,7 @@ interface OverlayShowOptions {
327
339
  borderStyle?: string;
328
340
  borderWidth?: number;
329
341
  fillOpacity?: number;
342
+ backdrop?: boolean;
330
343
  }
331
344
 
332
345
  type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
@@ -365,6 +378,8 @@ interface ListItem {
365
378
  leading?: () => Node;
366
379
  /** Raw data attribute tag appended to the row (for test/e2e hooks). */
367
380
  tag?: string;
381
+ /** Contextual actions surfaced in the footer popup when this row is highlighted. */
382
+ actions?: readonly ShellAction[];
368
383
  }
369
384
  interface DetailSurface {
370
385
  kind: "detail";
@@ -405,19 +420,21 @@ type DetailAction = (DetailActionBase & {
405
420
  }) | (DetailActionBase & {
406
421
  run: (ctx: DetailActionRunContext) => void | Promise<void>;
407
422
  });
408
- type DetailActionIcon = "copy" | "message-circle" | "chevron-down" | "target";
423
+ type DetailActionIcon = "copy" | "camera" | "message-circle-warning" | "chevron-down" | "highlighter" | "ticket-plus" | "view";
409
424
  interface DetailActionRunContext {
410
425
  setLabel(next: string, durationMs?: number): void;
411
426
  }
427
+ interface ResolvedFlowStep {
428
+ ordinal: number;
429
+ entity: Entity;
430
+ action?: string;
431
+ }
412
432
  type DetailSection = {
413
433
  id: "description";
414
434
  text: string;
415
435
  } | {
416
436
  id: "acceptance";
417
437
  items: readonly string[];
418
- } | {
419
- id: "scopes";
420
- scopes: readonly string[];
421
438
  } | {
422
439
  id: "composes";
423
440
  label: string;
@@ -435,7 +452,10 @@ type DetailSection = {
435
452
  } | {
436
453
  id: "touches";
437
454
  entities: readonly Entity[];
438
- unresolved: readonly string[];
455
+ filterable?: boolean;
456
+ } | {
457
+ id: "steps";
458
+ steps: readonly ResolvedFlowStep[];
439
459
  filterable?: boolean;
440
460
  } | {
441
461
  id: "routes";
@@ -454,6 +474,11 @@ interface FormSurface {
454
474
  * routed to the matching `<FieldError>` and submission is skipped.
455
475
  */
456
476
  schema?: StandardSchemaV1<Record<string, unknown>>;
477
+ /**
478
+ * Promise resolving to a base64 screenshot data URL. When provided, the
479
+ * form renderer shows a thumbnail preview above the fields.
480
+ */
481
+ screenshotPreview?: Promise<string | null>;
457
482
  }
458
483
  /**
459
484
  * Minimal StandardSchemaV1 surface — kept inline so the SDK doesn't need a
@@ -550,6 +575,8 @@ interface ViewPalette {
550
575
  }
551
576
  interface ViewDirectory {
552
577
  list(): readonly View[];
578
+ recents(): readonly EntityRef[];
579
+ favorites(): readonly EntityRef[];
553
580
  }
554
581
  interface ViewPushTarget {
555
582
  id: string;
@@ -575,6 +602,10 @@ interface ViewContext {
575
602
  navigate: (ref: EntityRef) => void;
576
603
  /** Pin the overlay to `ref` until the user presses Esc. */
577
604
  pinHighlight: (ref: EntityRef) => void;
605
+ /** Toggle favorite status for an entity ref. */
606
+ toggleFavorite: (ref: EntityRef) => void;
607
+ /** Check if an entity ref is favorited. */
608
+ isFavorite: (ref: EntityRef) => boolean;
578
609
  /** Shell-owned search input. The shell dispatches its value into the active surface. */
579
610
  searchInput: HTMLInputElement;
580
611
  /** Drives the Surface's singleton overlay from inside a custom surface. */
@@ -605,6 +636,7 @@ interface ShellAction {
605
636
  id: string;
606
637
  label: string;
607
638
  shortcut?: string;
639
+ icon?: () => Node;
608
640
  perform: () => void | Promise<void>;
609
641
  intent?: ShellActionIntent;
610
642
  }
@@ -627,6 +659,15 @@ interface View {
627
659
  surface: (ctx: ViewContext) => ViewSurface;
628
660
  }
629
661
 
662
+ interface PaletteShortcut {
663
+ /** The key value (e.g. "k", "j", ";"). Matched case-insensitively. */
664
+ key: string;
665
+ /** Require Cmd (Mac) / Ctrl (Win/Linux). Default: true. */
666
+ mod?: boolean;
667
+ /** Require Shift. Default: false. */
668
+ shift?: boolean;
669
+ }
670
+
630
671
  interface ViewRegistrar {
631
672
  register(view: View): void;
632
673
  unregister(id: string): void;
@@ -634,6 +675,10 @@ interface ViewRegistrar {
634
675
  get(id: string): View | undefined;
635
676
  findMatch(ref: EntityRef): View | null;
636
677
  navigate(ref: EntityRef): void;
678
+ recents(): readonly EntityRef[];
679
+ favorites(): readonly EntityRef[];
680
+ toggleFavorite(ref: EntityRef): void;
681
+ isFavorite(ref: EntityRef): boolean;
637
682
  }
638
683
 
639
684
  interface CreateUidexOptions {
@@ -655,6 +700,8 @@ interface CreateUidexOptions {
655
700
  * an options object to override either channel.
656
701
  */
657
702
  ingest?: IngestOptions | null;
703
+ /** Keyboard shortcut for the command palette. Defaults to Cmd+K / Ctrl+K. */
704
+ shortcut?: PaletteShortcut;
658
705
  }
659
706
  interface Uidex {
660
707
  mount(target?: Element): void;
@@ -35,11 +35,16 @@ interface Route {
35
35
  path: string;
36
36
  page: string;
37
37
  }
38
+ interface FlowStep {
39
+ entityId: string;
40
+ action?: string;
41
+ }
38
42
  interface Flow {
39
43
  kind: "flow";
40
44
  id: string;
41
45
  loc: Location;
42
46
  touches: string[];
47
+ steps: FlowStep[];
43
48
  }
44
49
  interface Page extends EntityWithMetaBase {
45
50
  kind: "page";
@@ -278,15 +283,16 @@ interface FeedbackResult {
278
283
  sequenceNumber: number;
279
284
  externalLink?: FeedbackExternalLink;
280
285
  }
281
- interface IngestConfigEpic {
286
+ interface IngestConfigIssue {
287
+ id: string;
282
288
  key: string;
283
289
  summary: string;
284
- status: string;
290
+ issueType: string;
285
291
  }
286
292
  interface IngestConfig {
287
293
  hasJira: boolean;
288
294
  integrationId?: string;
289
- epics?: IngestConfigEpic[];
295
+ parentIssues?: IngestConfigIssue[];
290
296
  }
291
297
  /**
292
298
  * Generic so third-party adapters (e.g. `uidex-cloud`) can plug in their own
@@ -296,6 +302,12 @@ interface IngestConfig {
296
302
  */
297
303
  interface CloudAdapter<TPayload = FeedbackPayload, TResult = FeedbackResult, TIntegrations = {
298
304
  getConfig(): Promise<IngestConfig>;
305
+ /**
306
+ * Synchronous read of the eagerly-fetched config. Returns `null` until the
307
+ * initial fetch resolves; views that need a sync answer (e.g. detail
308
+ * actions deciding whether to surface a Jira button) read this.
309
+ */
310
+ getCachedConfig(): IngestConfig | null;
299
311
  }> {
300
312
  readonly feedback: {
301
313
  submit(payload: TPayload): Promise<TResult>;
@@ -327,6 +339,7 @@ interface OverlayShowOptions {
327
339
  borderStyle?: string;
328
340
  borderWidth?: number;
329
341
  fillOpacity?: number;
342
+ backdrop?: boolean;
330
343
  }
331
344
 
332
345
  type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
@@ -365,6 +378,8 @@ interface ListItem {
365
378
  leading?: () => Node;
366
379
  /** Raw data attribute tag appended to the row (for test/e2e hooks). */
367
380
  tag?: string;
381
+ /** Contextual actions surfaced in the footer popup when this row is highlighted. */
382
+ actions?: readonly ShellAction[];
368
383
  }
369
384
  interface DetailSurface {
370
385
  kind: "detail";
@@ -405,19 +420,21 @@ type DetailAction = (DetailActionBase & {
405
420
  }) | (DetailActionBase & {
406
421
  run: (ctx: DetailActionRunContext) => void | Promise<void>;
407
422
  });
408
- type DetailActionIcon = "copy" | "message-circle" | "chevron-down" | "target";
423
+ type DetailActionIcon = "copy" | "camera" | "message-circle-warning" | "chevron-down" | "highlighter" | "ticket-plus" | "view";
409
424
  interface DetailActionRunContext {
410
425
  setLabel(next: string, durationMs?: number): void;
411
426
  }
427
+ interface ResolvedFlowStep {
428
+ ordinal: number;
429
+ entity: Entity;
430
+ action?: string;
431
+ }
412
432
  type DetailSection = {
413
433
  id: "description";
414
434
  text: string;
415
435
  } | {
416
436
  id: "acceptance";
417
437
  items: readonly string[];
418
- } | {
419
- id: "scopes";
420
- scopes: readonly string[];
421
438
  } | {
422
439
  id: "composes";
423
440
  label: string;
@@ -435,7 +452,10 @@ type DetailSection = {
435
452
  } | {
436
453
  id: "touches";
437
454
  entities: readonly Entity[];
438
- unresolved: readonly string[];
455
+ filterable?: boolean;
456
+ } | {
457
+ id: "steps";
458
+ steps: readonly ResolvedFlowStep[];
439
459
  filterable?: boolean;
440
460
  } | {
441
461
  id: "routes";
@@ -454,6 +474,11 @@ interface FormSurface {
454
474
  * routed to the matching `<FieldError>` and submission is skipped.
455
475
  */
456
476
  schema?: StandardSchemaV1<Record<string, unknown>>;
477
+ /**
478
+ * Promise resolving to a base64 screenshot data URL. When provided, the
479
+ * form renderer shows a thumbnail preview above the fields.
480
+ */
481
+ screenshotPreview?: Promise<string | null>;
457
482
  }
458
483
  /**
459
484
  * Minimal StandardSchemaV1 surface — kept inline so the SDK doesn't need a
@@ -550,6 +575,8 @@ interface ViewPalette {
550
575
  }
551
576
  interface ViewDirectory {
552
577
  list(): readonly View[];
578
+ recents(): readonly EntityRef[];
579
+ favorites(): readonly EntityRef[];
553
580
  }
554
581
  interface ViewPushTarget {
555
582
  id: string;
@@ -575,6 +602,10 @@ interface ViewContext {
575
602
  navigate: (ref: EntityRef) => void;
576
603
  /** Pin the overlay to `ref` until the user presses Esc. */
577
604
  pinHighlight: (ref: EntityRef) => void;
605
+ /** Toggle favorite status for an entity ref. */
606
+ toggleFavorite: (ref: EntityRef) => void;
607
+ /** Check if an entity ref is favorited. */
608
+ isFavorite: (ref: EntityRef) => boolean;
578
609
  /** Shell-owned search input. The shell dispatches its value into the active surface. */
579
610
  searchInput: HTMLInputElement;
580
611
  /** Drives the Surface's singleton overlay from inside a custom surface. */
@@ -605,6 +636,7 @@ interface ShellAction {
605
636
  id: string;
606
637
  label: string;
607
638
  shortcut?: string;
639
+ icon?: () => Node;
608
640
  perform: () => void | Promise<void>;
609
641
  intent?: ShellActionIntent;
610
642
  }
@@ -627,6 +659,15 @@ interface View {
627
659
  surface: (ctx: ViewContext) => ViewSurface;
628
660
  }
629
661
 
662
+ interface PaletteShortcut {
663
+ /** The key value (e.g. "k", "j", ";"). Matched case-insensitively. */
664
+ key: string;
665
+ /** Require Cmd (Mac) / Ctrl (Win/Linux). Default: true. */
666
+ mod?: boolean;
667
+ /** Require Shift. Default: false. */
668
+ shift?: boolean;
669
+ }
670
+
630
671
  interface ViewRegistrar {
631
672
  register(view: View): void;
632
673
  unregister(id: string): void;
@@ -634,6 +675,10 @@ interface ViewRegistrar {
634
675
  get(id: string): View | undefined;
635
676
  findMatch(ref: EntityRef): View | null;
636
677
  navigate(ref: EntityRef): void;
678
+ recents(): readonly EntityRef[];
679
+ favorites(): readonly EntityRef[];
680
+ toggleFavorite(ref: EntityRef): void;
681
+ isFavorite(ref: EntityRef): boolean;
637
682
  }
638
683
 
639
684
  interface CreateUidexOptions {
@@ -655,6 +700,8 @@ interface CreateUidexOptions {
655
700
  * an options object to override either channel.
656
701
  */
657
702
  ingest?: IngestOptions | null;
703
+ /** Keyboard shortcut for the command palette. Defaults to Cmd+K / Ctrl+K. */
704
+ shortcut?: PaletteShortcut;
658
705
  }
659
706
  interface Uidex {
660
707
  mount(target?: Element): void;