@workflow/web-shared 5.0.0-beta.20 → 5.0.0-beta.22

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 (39) hide show
  1. package/dist/components/index.d.ts +1 -0
  2. package/dist/components/index.d.ts.map +1 -1
  3. package/dist/components/index.js +2 -1
  4. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts +5 -0
  5. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts.map +1 -0
  6. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.js +55 -0
  7. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  8. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
  9. package/dist/components/new-trace-viewer/trace-viewer.js +4 -4
  10. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  11. package/dist/components/sidebar/attribute-panel.js +4 -1
  12. package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
  13. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  14. package/dist/components/sidebar/copyable-data-block.js +2 -2
  15. package/dist/components/ui/data-inspector.d.ts +6 -6
  16. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  17. package/dist/components/ui/data-inspector.js +234 -91
  18. package/dist/components/ui/data-inspector.styles.d.ts +29 -0
  19. package/dist/components/ui/data-inspector.styles.d.ts.map +1 -0
  20. package/dist/components/ui/data-inspector.styles.js +95 -0
  21. package/dist/components/ui/kbd.d.ts +9 -5
  22. package/dist/components/ui/kbd.d.ts.map +1 -1
  23. package/dist/components/ui/kbd.js +22 -3
  24. package/dist/lib/hydration.js +3 -3
  25. package/package.json +3 -4
  26. package/src/components/index.ts +1 -0
  27. package/src/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  28. package/src/components/new-trace-viewer/components/trace-shortcut-helper.tsx +116 -0
  29. package/src/components/new-trace-viewer/trace-viewer.tsx +9 -4
  30. package/src/components/sidebar/attribute-panel.tsx +4 -0
  31. package/src/components/sidebar/copyable-data-block.tsx +1 -1
  32. package/src/components/ui/data-inspector.styles.ts +96 -0
  33. package/src/components/ui/data-inspector.tsx +492 -186
  34. package/src/components/ui/kbd.tsx +33 -11
  35. package/src/lib/hydration.ts +2 -2
  36. package/dist/components/ui/inspector-theme.d.ts +0 -95
  37. package/dist/components/ui/inspector-theme.d.ts.map +0 -1
  38. package/dist/components/ui/inspector-theme.js +0 -82
  39. package/src/components/ui/inspector-theme.ts +0 -110
@@ -39,6 +39,7 @@ import {
39
39
  TooltipTrigger,
40
40
  } from '../ui/tooltip';
41
41
  import EventList from './components/event-list';
42
+ import { TraceShortcutHelper } from './components/trace-shortcut-helper';
42
43
  import { ROW_HEIGHT_PX, scrollRowIntoView } from './components/use-row-window';
43
44
  import { SplitPane } from './components/split-pane';
44
45
  import {
@@ -460,7 +461,6 @@ function NewTraceViewerContent({
460
461
  if (e.key === 'Escape') {
461
462
  handleClearActiveSpan();
462
463
  } else if (e.key === 'Alt') {
463
- e.preventDefault();
464
464
  setAltHeld(true);
465
465
  } else if (e.key === 'j' || e.key === 'k') {
466
466
  handleSidebarNavKey(e);
@@ -648,7 +648,7 @@ function NewTraceViewerContent({
648
648
  <div
649
649
  data-pane="pane-root"
650
650
  data-has-detail={activeSpan ? '' : undefined}
651
- className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,360px,100%)]"
651
+ className="relative grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,360px,100%)]"
652
652
  >
653
653
  <div
654
654
  id="trace-parent"
@@ -683,9 +683,9 @@ function NewTraceViewerContent({
683
683
  onClick={() => setSearchQuery('')}
684
684
  className="-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex"
685
685
  >
686
- <kbd className="inline-flex h-5 min-h-5 min-w-5 items-center justify-center rounded border border-gray-alpha-400 bg-background-100 px-1 font-sans text-[13px] font-medium leading-[1.7em] text-gray-900">
686
+ <Kbd variant="outline" size="search">
687
687
  Esc
688
- </kbd>
688
+ </Kbd>
689
689
  </button>
690
690
  )}
691
691
  </div>
@@ -838,6 +838,11 @@ function NewTraceViewerContent({
838
838
  </div>
839
839
  </aside>
840
840
  ) : null}
841
+
842
+ <TraceShortcutHelper
843
+ hasMultipleSpans={trace.spans.length > 1}
844
+ reducedMotion={reducedMotion}
845
+ />
841
846
  </div>
842
847
  );
843
848
  }
@@ -218,6 +218,7 @@ type AttributeKey =
218
218
  | keyof WorkflowRun
219
219
  | keyof Hook
220
220
  | keyof Event
221
+ | 'occurredAt'
221
222
  | 'moduleSpecifier'
222
223
  | 'eventData'
223
224
  | 'resumeAt'
@@ -252,6 +253,7 @@ const attributeOrder: AttributeKey[] = [
252
253
  'projectId',
253
254
  'environment',
254
255
  'executionContext',
256
+ 'occurredAt',
255
257
  'createdAt',
256
258
  'startedAt',
257
259
  'updatedAt',
@@ -292,6 +294,7 @@ const attributeDisplayNames: Partial<Record<AttributeKey, string>> = {
292
294
  deploymentId: 'Deployment ID',
293
295
  specVersion: 'Spec Version',
294
296
  workflowCoreVersion: '@workflow/core version',
297
+ occurredAt: 'Occurred',
295
298
  createdAt: 'Created',
296
299
  startedAt: 'Started',
297
300
  updatedAt: 'Updated',
@@ -417,6 +420,7 @@ const attributeToDisplayFn: Record<
417
420
  return <RunAttributesCard attributes={value as Record<string, string>} />;
418
421
  },
419
422
  // Dates — wrapped with TimestampTooltip showing UTC/local + relative time
423
+ occurredAt: timestampWithTooltipOrNull,
420
424
  createdAt: timestampWithTooltipOrNull,
421
425
  startedAt: timestampWithTooltipOrNull,
422
426
  updatedAt: (_value: unknown) => null,
@@ -44,7 +44,7 @@ export function EncryptedDataBlock() {
44
44
  );
45
45
  }
46
46
 
47
- const serializeForClipboard = (value: unknown): string => {
47
+ export const serializeForClipboard = (value: unknown): string => {
48
48
  if (typeof value === 'string') return value;
49
49
  if (
50
50
  typeof value === 'number' ||
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Class names and styles for the data inspector tree.
3
+ *
4
+ * Kept out of the component module for readability. The CSS is injected via a
5
+ * React 19 hoistable `<style>` (see DataInspector), so it stays bundler-agnostic
6
+ * for every consumer. Colors use theme-aware `--ds-*` tokens that adapt to
7
+ * light/dark automatically, so no per-theme overrides are needed.
8
+ */
9
+
10
+ export const CLS = {
11
+ container: 'wf-json-view',
12
+ child: 'wf-json-child',
13
+ childFields: 'wf-json-child-fields',
14
+ label: 'wf-json-label',
15
+ clickableLabel: 'wf-json-clickable-label',
16
+ punctuation: 'wf-json-punctuation',
17
+ className: 'wf-json-classname',
18
+ expandIcon: 'wf-json-expand-icon',
19
+ collapseIcon: 'wf-json-collapse-icon',
20
+ collapsedContent: 'wf-json-collapsed-content',
21
+ string: 'wf-json-string',
22
+ number: 'wf-json-number',
23
+ boolean: 'wf-json-boolean',
24
+ null: 'wf-json-null',
25
+ undefined: 'wf-json-undefined',
26
+ date: 'wf-json-date',
27
+ regexp: 'wf-json-regexp',
28
+ } as const;
29
+
30
+ export const JSON_VIEW_STYLES = `
31
+ .${CLS.container} {
32
+ display: inline;
33
+ font-family: var(--font-mono);
34
+ font-size: 13px;
35
+ line-height: 20px;
36
+ margin: 0;
37
+ padding: 0;
38
+ background: transparent;
39
+ color: var(--ds-gray-1000);
40
+ white-space: pre-wrap;
41
+ word-wrap: break-word;
42
+ }
43
+ .${CLS.container} > .${CLS.child} > ul { padding-left: 0ch; }
44
+ .${CLS.container} > .${CLS.child} { padding-left: 1.5ch; }
45
+ .${CLS.child} { display: block; margin: 0; padding: 0 0 0 2ch; }
46
+ .${CLS.child}:hover:not(:has(.${CLS.child}:hover)):not(:has(.${CLS.child} ~ .${CLS.child})) {
47
+ background-color: var(--ds-gray-alpha-100);
48
+ border-radius: 4px;
49
+ }
50
+ .${CLS.childFields} { margin: 0; padding: 0; list-style: none; }
51
+ .${CLS.label}, .${CLS.clickableLabel} {
52
+ color: var(--ds-pink-900);
53
+ font-weight: 400;
54
+ margin-right: 1ch;
55
+ }
56
+ .${CLS.clickableLabel} { cursor: pointer; }
57
+ .${CLS.punctuation} { color: var(--ds-gray-1000); }
58
+ .${CLS.className} { font-style: italic; color: var(--ds-gray-900); margin-right: 1ch; }
59
+ .${CLS.string} { color: var(--ds-green-900); }
60
+ .${CLS.number} { color: var(--ds-blue-900); }
61
+ .${CLS.boolean} { color: var(--ds-amber-900); }
62
+ .${CLS.null}, .${CLS.undefined} { color: var(--ds-gray-900); }
63
+ .${CLS.date} { color: var(--ds-pink-900); }
64
+ .${CLS.regexp} { color: var(--ds-purple-900); }
65
+ .${CLS.container} > .${CLS.child} > .${CLS.expandIcon},
66
+ .${CLS.container} > .${CLS.child} > .${CLS.collapseIcon} { margin-left: -1.5ch; }
67
+ .${CLS.expandIcon}, .${CLS.collapseIcon} {
68
+ appearance: none;
69
+ background: none;
70
+ border: 0;
71
+ padding: 0;
72
+ font: inherit;
73
+ vertical-align: baseline;
74
+ cursor: pointer;
75
+ display: inline-block;
76
+ margin-right: 0ch;
77
+ margin-left: -1.5ch;
78
+ color: var(--ds-gray-500);
79
+ user-select: none;
80
+ outline: none;
81
+ }
82
+ .${CLS.expandIcon}::after {
83
+ content: '\\25B8';
84
+ margin-right: 0.5ch;
85
+ transform: translateY(-0.5px);
86
+ display: block;
87
+ }
88
+ .${CLS.collapseIcon}::after { content: '\\25BE'; margin-right: 0.5ch; }
89
+ .${CLS.expandIcon}:hover, .${CLS.collapseIcon}:hover,
90
+ .${CLS.child}:has(> .${CLS.clickableLabel}:hover) > .${CLS.expandIcon},
91
+ .${CLS.child}:has(> .${CLS.clickableLabel}:hover) > .${CLS.collapseIcon} {
92
+ color: var(--ds-gray-1000);
93
+ }
94
+ .${CLS.collapsedContent} { color: var(--ds-gray-900); }
95
+ .${CLS.collapsedContent}::after { content: '...'; }
96
+ `;