@datalayer/core 1.2.18 → 1.2.19

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 (107) hide show
  1. package/lib/cli-login.js +5 -51
  2. package/lib/components/anonymous/AnonymousKeyExpired.js +1 -15
  3. package/lib/components/anonymous/AnonymousKeyTimer.js +5 -15
  4. package/lib/components/auth/SignIn.js +2 -2
  5. package/lib/components/avatars/UserAvatar.js +3 -27
  6. package/lib/components/billing/BillingEntitySelect.js +6 -48
  7. package/lib/components/checkout/StripeCheckout.js +33 -217
  8. package/lib/components/contents/ContentSourceCard.js +2 -11
  9. package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +1 -1
  10. package/lib/components/contents/HomeFolderObjectsBrowser.js +11 -35
  11. package/lib/components/display/CenteredSpinner.js +1 -6
  12. package/lib/components/display/DatalayerBox.js +2 -14
  13. package/lib/components/flashes/FlashClosable.js +2 -17
  14. package/lib/components/mcp/ClientBadge.js +1 -1
  15. package/lib/components/mcp/McpErrorBlankslate.js +1 -1
  16. package/lib/components/mcp/ScopeList.js +1 -1
  17. package/lib/components/notebooks/JupyterNotebook.js +1 -2
  18. package/lib/components/principal/Principal.js +2 -10
  19. package/lib/components/principal/PrincipalAppearance.js +19 -63
  20. package/lib/components/principal/PrincipalAvatar.js +5 -25
  21. package/lib/components/principal/PrincipalBadge.js +3 -13
  22. package/lib/components/principal/PrincipalBanner.js +4 -32
  23. package/lib/components/principal/PrincipalDetailsOverlay.js +7 -23
  24. package/lib/components/principal/PrincipalHoverCard.js +15 -18
  25. package/lib/components/principal/PrincipalSwitcherMenu.js +15 -83
  26. package/lib/components/progress/ConsumptionBar.js +1 -1
  27. package/lib/components/sharing/ShareAccessComponent.js +21 -229
  28. package/lib/components/sharing/SharingEditor.js +1 -1
  29. package/lib/components/spaces/SpaceDetailsOverlay.js +4 -35
  30. package/lib/components/spaces/SpaceDisplay.js +1 -8
  31. package/lib/components/storage/ContentsBrowser.js +3 -26
  32. package/lib/components/storage/ContentsTable.js +4 -23
  33. package/lib/components/students/StudentResultCircle.js +7 -29
  34. package/lib/components/timeline/Timeline.js +4 -36
  35. package/lib/hooks/layouts/LayoutBackdrop.js +2 -1
  36. package/lib/hooks/layouts/LayoutScreencapture.js +1 -1
  37. package/lib/hooks/libraryApp.d.ts +6 -1
  38. package/lib/hooks/libraryApp.js +10 -1
  39. package/lib/hooks/useAuthorization.js +6 -1
  40. package/lib/mocks/components/FlashMock.js +3 -8
  41. package/lib/mocks/views/DashboardMock.js +6 -72
  42. package/lib/mocks/views/FormMock.js +3 -2
  43. package/lib/mocks/views/TableMock.js +3 -2
  44. package/lib/mocks/views/WipMock.js +2 -1
  45. package/lib/models/Person.d.ts +9 -0
  46. package/lib/models/Person.js +23 -0
  47. package/lib/otel/views/OtelLive.js +4 -62
  48. package/lib/otel/views/OtelLiveSpans.js +4 -29
  49. package/lib/otel/views/OtelLogsList.js +13 -64
  50. package/lib/otel/views/OtelMetricsChart.js +4 -19
  51. package/lib/otel/views/OtelMetricsList.js +8 -77
  52. package/lib/otel/views/OtelSearchBar.js +3 -12
  53. package/lib/otel/views/OtelSpanDetail.js +9 -79
  54. package/lib/otel/views/OtelSpanTree.js +7 -57
  55. package/lib/otel/views/OtelSqlView.js +5 -99
  56. package/lib/otel/views/OtelSystemView.js +4 -34
  57. package/lib/otel/views/OtelTimeline.js +7 -37
  58. package/lib/otel/views/OtelTimelineRangeSlider.js +7 -140
  59. package/lib/otel/views/OtelTracesList.js +12 -76
  60. package/lib/portable/index.d.ts +8 -0
  61. package/lib/portable/index.js +12 -0
  62. package/lib/state/substates/NavigationState.d.ts +6 -4
  63. package/lib/state/substates/NavigationState.js +6 -5
  64. package/lib/views/api-keys/APIKeyEdit.js +2 -11
  65. package/lib/views/api-keys/APIKeyNew.js +3 -19
  66. package/lib/views/api-keys/APIKeys.js +6 -11
  67. package/lib/views/api-keys/APIKeysStandalone.js +1 -1
  68. package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
  69. package/lib/views/datasources/DatasourceDetail.js +24 -17
  70. package/lib/views/datasources/DatasourceNew.js +2 -6
  71. package/lib/views/datasources/Datasources.js +2 -14
  72. package/lib/views/iam/SignInSimple.js +8 -64
  73. package/lib/views/mcp/AdmittedClients.js +3 -16
  74. package/lib/views/mcp/AlertDestinations.js +2 -10
  75. package/lib/views/mcp/AlertRules.js +4 -9
  76. package/lib/views/mcp/ApprovalQueue.js +4 -21
  77. package/lib/views/mcp/AuditLog.js +7 -44
  78. package/lib/views/mcp/ConnectedAgents.js +1 -6
  79. package/lib/views/mcp/EnterpriseConsole.js +10 -23
  80. package/lib/views/mcp/IdentityProviders.js +7 -31
  81. package/lib/views/mcp/McpDashboard.js +14 -30
  82. package/lib/views/mcp/McpHome.js +7 -54
  83. package/lib/views/mcp/McpObservability.js +13 -85
  84. package/lib/views/mcp/NotebookRuns.js +5 -12
  85. package/lib/views/mcp/OrganizationPolicy.js +3 -9
  86. package/lib/views/mcp/OrganizationUsage.js +4 -11
  87. package/lib/views/mcp/PersonalPolicy.js +3 -3
  88. package/lib/views/mcp/Policies.js +5 -46
  89. package/lib/views/mcp/PolicyForm.js +1 -9
  90. package/lib/views/mcp/PolicyHistory.js +2 -8
  91. package/lib/views/mcp/RunDetail.js +3 -25
  92. package/lib/views/mcp/ScimProvisioning.js +3 -15
  93. package/lib/views/mcp/ServiceAgents.js +4 -17
  94. package/lib/views/mcp/TeamPolicies.js +7 -19
  95. package/lib/views/mcp/ToolAccess.js +15 -22
  96. package/lib/views/mcp/TraceTimeline.js +8 -23
  97. package/lib/views/otel/DashboardView.js +2 -2
  98. package/lib/views/otel/LogsView.js +2 -2
  99. package/lib/views/otel/MetricsView.js +2 -2
  100. package/lib/views/otel/OtelHeader.js +6 -40
  101. package/lib/views/otel/SqlView.js +2 -2
  102. package/lib/views/otel/SystemView.js +2 -2
  103. package/lib/views/otel/TracesView.js +2 -2
  104. package/lib/views/profile/UserBadge.js +6 -98
  105. package/lib/views/secrets/SecretEdit.js +2 -11
  106. package/lib/views/secrets/SecretNew.js +1 -1
  107. package/package.json +1 -1
@@ -12,56 +12,28 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  * @module otel/OtelLogsList
13
13
  */
14
14
  import React, { useState } from 'react';
15
- import { Box, Text, Label, Spinner } from '@primer/react';
15
+ import { Box } from '@datalayer/primer-addons';
16
+ import { Text, Label, Spinner } from '@primer/react';
16
17
  import { Blankslate } from '@primer/react/experimental';
17
18
  import { LogIcon } from '@primer/octicons-react';
18
19
  import { formatTime, severityVariant } from '../utils.js';
19
20
  // ── helpers ─────────────────────────────────────────────────────────
20
21
  /** Severity badge using Primer Label, centered in its grid cell. */
21
- const Severity = ({ text }) => (_jsx(Box, { sx: { display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx(Label, { size: "small", variant: severityVariant(text), children: text }) }));
22
+ const Severity = ({ text }) => (_jsx(Box, { display: "flex", alignItems: "center", justifyContent: "center", children: _jsx(Label, { size: "small", variant: severityVariant(text), children: text }) }));
22
23
  /** Expandable row detail for a single log record. */
23
- const LogDetail = ({ log }) => (_jsxs(Box, { sx: {
24
- gridColumn: '1 / -1',
25
- bg: 'canvas.subtle',
26
- borderBottom: '1px solid',
27
- borderColor: 'border.default',
28
- p: 3,
29
- }, children: [_jsxs(Box, { sx: { mb: 2 }, children: [_jsx(Text, { sx: {
24
+ const LogDetail = ({ log }) => (_jsxs(Box, { gridColumn: "1 / -1", bg: "canvas.subtle", borderBottom: "1px solid", borderColor: "border.default", p: 3, children: [_jsxs(Box, { mb: 2, children: [_jsx(Text, { sx: {
30
25
  fontSize: 0,
31
26
  fontWeight: 'bold',
32
27
  color: 'fg.muted',
33
28
  display: 'block',
34
29
  mb: 1,
35
- }, children: "Body" }), _jsx(Box, { as: "pre", sx: {
36
- fontSize: 1,
37
- fontFamily: 'mono',
38
- whiteSpace: 'pre-wrap',
39
- wordBreak: 'break-word',
40
- m: 0,
41
- bg: 'canvas.default',
42
- border: '1px solid',
43
- borderColor: 'border.default',
44
- borderRadius: 2,
45
- p: 2,
46
- }, children: log.body })] }), log.trace_id && (_jsxs(Box, { sx: { display: 'flex', gap: 3, mb: 2 }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontWeight: 'bold' }, children: "trace_id" }), _jsx(Text, { sx: { fontFamily: 'mono', fontSize: 0 }, children: log.trace_id }), log.span_id && (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontWeight: 'bold' }, children: "span_id" }), _jsx(Text, { sx: { fontFamily: 'mono', fontSize: 0 }, children: log.span_id })] }))] })), log.attributes && Object.keys(log.attributes).length > 0 && (_jsxs(Box, { children: [_jsx(Text, { sx: {
30
+ }, children: "Body" }), _jsx(Box, { as: "pre", fontSize: 1, fontFamily: "mono", whiteSpace: "pre-wrap", wordBreak: "break-word", m: 0, bg: "canvas.default", border: "1px solid", borderColor: "border.default", borderRadius: 2, p: 2, children: log.body })] }), log.trace_id && (_jsxs(Box, { display: "flex", gap: 3, mb: 2, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontWeight: 'bold' }, children: "trace_id" }), _jsx(Text, { sx: { fontFamily: 'mono', fontSize: 0 }, children: log.trace_id }), log.span_id && (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontWeight: 'bold' }, children: "span_id" }), _jsx(Text, { sx: { fontFamily: 'mono', fontSize: 0 }, children: log.span_id })] }))] })), log.attributes && Object.keys(log.attributes).length > 0 && (_jsxs(Box, { children: [_jsx(Text, { sx: {
47
31
  fontSize: 0,
48
32
  fontWeight: 'bold',
49
33
  color: 'fg.muted',
50
34
  display: 'block',
51
35
  mb: 1,
52
- }, children: "Attributes" }), _jsx(Box, { sx: {
53
- bg: 'canvas.default',
54
- border: '1px solid',
55
- borderColor: 'border.default',
56
- borderRadius: 2,
57
- p: 2,
58
- }, children: Object.entries(log.attributes).map(([k, v]) => (_jsxs(Box, { sx: {
59
- display: 'flex',
60
- gap: 2,
61
- py: 1,
62
- borderBottom: '1px solid',
63
- borderColor: 'border.muted',
64
- }, children: [_jsx(Text, { sx: {
36
+ }, children: "Attributes" }), _jsx(Box, { bg: "canvas.default", border: "1px solid", borderColor: "border.default", borderRadius: 2, p: 2, children: Object.entries(log.attributes).map(([k, v]) => (_jsxs(Box, { display: "flex", gap: 2, py: 1, borderBottom: "1px solid", borderColor: "border.muted", children: [_jsx(Text, { sx: {
65
37
  color: 'accent.fg',
66
38
  fontSize: 0,
67
39
  fontFamily: 'mono',
@@ -76,23 +48,12 @@ export const OtelLogsList = ({ logs, loading, selectedLogIndex, onSelectLog, })
76
48
  const [expandedIdx, setExpandedIdx] = useState(null);
77
49
  const colTemplate = '140px 80px 160px 1fr';
78
50
  if (loading && logs.length === 0) {
79
- return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', p: 5 }, children: _jsx(Spinner, { size: "medium" }) }));
51
+ return (_jsx(Box, { display: "flex", justifyContent: "center", p: 5, children: _jsx(Spinner, { size: "medium" }) }));
80
52
  }
81
53
  if (!loading && logs.length === 0) {
82
54
  return (_jsxs(Blankslate, { children: [_jsx(Blankslate.Visual, { children: _jsx(LogIcon, { size: 24 }) }), _jsx(Blankslate.Heading, { children: "No log records found" }), _jsx(Blankslate.Description, { children: "Send some log data first." })] }));
83
55
  }
84
- return (_jsxs(Box, { sx: { flex: 1, minHeight: 0, overflow: 'auto' }, children: [_jsx(Box, { sx: {
85
- display: 'grid',
86
- gridTemplateColumns: colTemplate,
87
- bg: 'canvas.subtle',
88
- borderBottom: '2px solid',
89
- borderColor: 'border.default',
90
- px: 3,
91
- py: 1,
92
- position: 'sticky',
93
- top: 0,
94
- zIndex: 1,
95
- }, children: ['Time', 'Severity', 'Service', 'Body'].map(h => (_jsx(Text, { sx: {
56
+ return (_jsxs(Box, { flex: 1, minHeight: 0, overflow: "auto", children: [_jsx(Box, { display: "grid", gridTemplateColumns: colTemplate, bg: "canvas.subtle", borderBottom: "2px solid", borderColor: "border.default", px: 3, py: 1, position: "sticky", top: 0, zIndex: 1, children: ['Time', 'Severity', 'Service', 'Body'].map(h => (_jsx(Text, { sx: {
96
57
  fontSize: 0,
97
58
  fontWeight: 'bold',
98
59
  color: 'fg.muted',
@@ -102,23 +63,11 @@ export const OtelLogsList = ({ logs, loading, selectedLogIndex, onSelectLog, })
102
63
  }, children: h }, h))) }), logs.map((log, idx) => {
103
64
  const selected = idx === selectedLogIndex;
104
65
  const expanded = idx === expandedIdx;
105
- return (_jsxs(React.Fragment, { children: [_jsxs(Box, { sx: {
106
- display: 'grid',
107
- gridTemplateColumns: colTemplate,
108
- px: 3,
109
- py: '5px',
110
- borderBottom: '1px solid',
111
- borderColor: 'border.muted',
112
- cursor: 'pointer',
113
- bg: selected
114
- ? 'accent.subtle'
115
- : expanded
116
- ? 'canvas.subtle'
117
- : 'canvas.default',
118
- ':hover': {
119
- bg: selected || expanded ? undefined : 'canvas.subtle',
120
- },
121
- }, onClick: () => {
66
+ return (_jsxs(React.Fragment, { children: [_jsxs(Box, { display: "grid", gridTemplateColumns: colTemplate, px: 3, py: "5px", borderBottom: "1px solid", borderColor: "border.muted", cursor: "pointer", bg: selected
67
+ ? 'accent.subtle'
68
+ : expanded
69
+ ? 'canvas.subtle'
70
+ : 'canvas.default', hover: { bg: selected || expanded ? undefined : 'canvas.subtle' }, onClick: () => {
122
71
  setExpandedIdx(expanded ? null : idx);
123
72
  onSelectLog?.(log, idx);
124
73
  }, children: [_jsx(Text, { sx: { fontSize: 1, fontFamily: 'mono', color: 'fg.default' }, children: formatTime(log.timestamp) }), _jsx(Severity, { text: log.severity_text }), _jsx(Text, { sx: {
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as echarts from 'echarts';
3
3
  import ReactECharts from 'echarts-for-react';
4
- import { Box, Text, Label } from '@primer/react';
4
+ import { Box } from '@datalayer/primer-addons';
5
+ import { Text, Label } from '@primer/react';
5
6
  // ── Gradient palette ────────────────────────────────────────────────
6
7
  const SERIES_COLORS = [
7
8
  {
@@ -269,30 +270,14 @@ export const OtelMetricsChart = ({ metrics, height = 240, }) => {
269
270
  const byType = groupByType(metrics);
270
271
  // Sort types in a stable, user-friendly order.
271
272
  const sortedTypes = [...byType.keys()].sort((a, b) => (TYPE_ORDER[a] ?? 99) - (TYPE_ORDER[b] ?? 99));
272
- return (_jsx(Box, { sx: {
273
- display: 'grid',
274
- gridTemplateColumns: '1fr 1fr',
275
- gap: 2,
276
- }, children: sortedTypes.map(mtype => {
273
+ return (_jsx(Box, { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 2, children: sortedTypes.map(mtype => {
277
274
  const nameMap = byType.get(mtype);
278
275
  const option = buildOption(mtype, nameMap);
279
276
  const stats = computeStats(nameMap);
280
277
  const durationMs = stats.startTs !== null && stats.endTs !== null
281
278
  ? stats.endTs - stats.startTs
282
279
  : null;
283
- return (_jsxs(Box, { children: [_jsxs(Box, { sx: {
284
- display: 'flex',
285
- alignItems: 'center',
286
- gap: 2,
287
- px: 1,
288
- mb: 1,
289
- }, children: [_jsx(Label, { size: "small", variant: typeVariant(mtype), children: mtype }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', color: 'fg.muted' }, children: typeTitle(mtype) }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["(", [...nameMap.keys()].join(', '), ")"] })] }), _jsxs(Box, { sx: {
290
- display: 'flex',
291
- alignItems: 'center',
292
- gap: 3,
293
- px: 1,
294
- mb: 1,
295
- }, children: [_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'bold', color: 'fg.default' }, children: "Sum:" }), ' ', stats.total.toLocaleString(undefined, {
280
+ return (_jsxs(Box, { children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 1, mb: 1, children: [_jsx(Label, { size: "small", variant: typeVariant(mtype), children: mtype }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', color: 'fg.muted' }, children: typeTitle(mtype) }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["(", [...nameMap.keys()].join(', '), ")"] })] }), _jsxs(Box, { display: "flex", alignItems: "center", gap: 3, px: 1, mb: 1, children: [_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'bold', color: 'fg.default' }, children: "Sum:" }), ' ', stats.total.toLocaleString(undefined, {
296
281
  maximumFractionDigits: 4,
297
282
  })] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'bold', color: 'fg.default' }, children: "Points:" }), ' ', stats.count] }), stats.startTs !== null && stats.endTs !== null && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'bold', color: 'fg.default' }, children: "Interval:" }), ' ', formatTs(stats.startTs), " \u2192 ", formatTs(stats.endTs), durationMs !== null && durationMs > 0 && (_jsxs(Text, { as: "span", sx: { color: 'fg.subtle' }, children: [' ', "(", formatDuration(durationMs), ")"] }))] }))] }), _jsx(ReactECharts, { echarts: echarts, option: option, style: { width: '100%', height: `${height}px` }, notMerge: true })] }, mtype));
298
283
  }) }));
@@ -12,7 +12,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  * @module otel/OtelMetricsList
13
13
  */
14
14
  import { useMemo, useState } from 'react';
15
- import { Box, Text, Label, Spinner, CounterLabel, SegmentedControl, } from '@primer/react';
15
+ import { Box } from '@datalayer/primer-addons';
16
+ import { Text, Label, Spinner, CounterLabel, SegmentedControl, } from '@primer/react';
16
17
  import { Blankslate } from '@primer/react/experimental';
17
18
  import { MeterIcon, ChevronDownIcon, ChevronRightIcon, GraphIcon, TableIcon, } from '@primer/octicons-react';
18
19
  import { formatTime } from '../utils.js';
@@ -70,27 +71,7 @@ const MetricGroup = ({ name, points }) => {
70
71
  const endTs = timestamps.length > 0 ? Math.max(...timestamps) : null;
71
72
  return { min, max, avg, latest, startTs, endTs };
72
73
  }, [points]);
73
- return (_jsxs(Box, { sx: {
74
- borderBottom: '1px solid',
75
- borderColor: 'border.default',
76
- }, children: [_jsxs(Box, { onClick: () => setExpanded(!expanded), sx: {
77
- display: 'grid',
78
- gridTemplateColumns: '20px 1fr auto auto auto auto',
79
- gap: 3,
80
- alignItems: 'center',
81
- px: 3,
82
- py: 2,
83
- cursor: 'pointer',
84
- ':hover': { bg: 'canvas.subtle' },
85
- }, children: [expanded ? (_jsx(ChevronDownIcon, { size: 16 })) : (_jsx(ChevronRightIcon, { size: 16 })), _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 0 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1 }, children: name }), first?.metric_type && (_jsx(Label, { size: "small", variant: typeVariant(first.metric_type), children: first.metric_type })), first?.unit && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["(", first.unit, ")"] }))] }), stats.startTs !== null && stats.endTs !== null && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle', fontFamily: 'mono' }, children: [formatTime(new Date(stats.startTs).toISOString()), stats.startTs !== stats.endTs && (_jsxs(_Fragment, { children: [" \u2192 ", formatTime(new Date(stats.endTs).toISOString())] }))] }))] }), _jsxs(Box, { sx: { textAlign: 'right' }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "latest" }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', fontFamily: 'mono', ml: 1 }, children: formatValue(stats.latest, first?.unit) })] }), _jsxs(Box, { sx: { textAlign: 'right' }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "avg" }), _jsx(Text, { sx: { fontSize: 1, fontFamily: 'mono', ml: 1 }, children: stats.avg.toFixed(2) })] }), _jsxs(Box, { sx: { textAlign: 'right' }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "min/max" }), _jsxs(Text, { sx: { fontSize: 1, fontFamily: 'mono', ml: 1 }, children: [stats.min.toFixed(1), "\u2013", stats.max.toFixed(1)] })] }), _jsx(CounterLabel, { children: points.length })] }), expanded && (_jsxs(Box, { sx: { bg: 'canvas.subtle' }, children: [_jsxs(Box, { sx: {
86
- display: 'grid',
87
- gridTemplateColumns: '20px 180px 1fr 140px 160px',
88
- gap: 3,
89
- px: 3,
90
- py: 1,
91
- borderTop: '1px solid',
92
- borderColor: 'border.muted',
93
- }, children: [_jsx(Box, {}), _jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: "Time" }), _jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: "Service" }), _jsx(Text, { sx: {
74
+ return (_jsxs(Box, { borderBottom: "1px solid", borderColor: "border.default", children: [_jsxs(Box, { onClick: () => setExpanded(!expanded), display: "grid", gridTemplateColumns: "20px 1fr auto auto auto auto", gap: 3, alignItems: "center", px: 3, py: 2, cursor: "pointer", hover: { bg: 'canvas.subtle' }, children: [expanded ? (_jsx(ChevronDownIcon, { size: 16 })) : (_jsx(ChevronRightIcon, { size: 16 })), _jsxs(Box, { display: "flex", flexDirection: "column", gap: 0, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1 }, children: name }), first?.metric_type && (_jsx(Label, { size: "small", variant: typeVariant(first.metric_type), children: first.metric_type })), first?.unit && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["(", first.unit, ")"] }))] }), stats.startTs !== null && stats.endTs !== null && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle', fontFamily: 'mono' }, children: [formatTime(new Date(stats.startTs).toISOString()), stats.startTs !== stats.endTs && (_jsxs(_Fragment, { children: [" \u2192 ", formatTime(new Date(stats.endTs).toISOString())] }))] }))] }), _jsxs(Box, { textAlign: "right", children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "latest" }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', fontFamily: 'mono', ml: 1 }, children: formatValue(stats.latest, first?.unit) })] }), _jsxs(Box, { textAlign: "right", children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "avg" }), _jsx(Text, { sx: { fontSize: 1, fontFamily: 'mono', ml: 1 }, children: stats.avg.toFixed(2) })] }), _jsxs(Box, { textAlign: "right", children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "min/max" }), _jsxs(Text, { sx: { fontSize: 1, fontFamily: 'mono', ml: 1 }, children: [stats.min.toFixed(1), "\u2013", stats.max.toFixed(1)] })] }), _jsx(CounterLabel, { children: points.length })] }), expanded && (_jsxs(Box, { bg: "canvas.subtle", children: [_jsxs(Box, { display: "grid", gridTemplateColumns: "20px 180px 1fr 140px 160px", gap: 3, px: 3, py: 1, borderTop: "1px solid", borderColor: "border.muted", children: [_jsx(Box, {}), _jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: "Time" }), _jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: "Service" }), _jsx(Text, { sx: {
94
75
  fontSize: 0,
95
76
  fontWeight: 'bold',
96
77
  color: 'fg.muted',
@@ -108,31 +89,15 @@ const MetricRow = ({ metric }) => {
108
89
  const attrCount = metric.attributes
109
90
  ? Object.keys(metric.attributes).length
110
91
  : 0;
111
- return (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
112
- display: 'grid',
113
- gridTemplateColumns: '20px 180px 1fr 140px 160px',
114
- gap: 3,
115
- alignItems: 'center',
116
- px: 3,
117
- py: 1,
118
- borderTop: '1px solid',
119
- borderColor: 'border.muted',
120
- ':hover': { bg: 'canvas.inset' },
121
- }, children: [_jsx(Box, {}), _jsx(Text, { sx: { fontSize: 0, fontFamily: 'mono', color: 'fg.muted' }, children: formatTime(metric.timestamp) }), _jsx(Text, { sx: { fontSize: 0 }, children: metric.service_name }), _jsx(Text, { sx: {
92
+ return (_jsxs(_Fragment, { children: [_jsxs(Box, { display: "grid", gridTemplateColumns: "20px 180px 1fr 140px 160px", gap: 3, alignItems: "center", px: 3, py: 1, borderTop: "1px solid", borderColor: "border.muted", hover: { bg: 'canvas.inset' }, children: [_jsx(Box, {}), _jsx(Text, { sx: { fontSize: 0, fontFamily: 'mono', color: 'fg.muted' }, children: formatTime(metric.timestamp) }), _jsx(Text, { sx: { fontSize: 0 }, children: metric.service_name }), _jsx(Text, { sx: {
122
93
  fontSize: 1,
123
94
  fontFamily: 'mono',
124
95
  fontWeight: 'bold',
125
96
  textAlign: 'right',
126
- }, children: formatValue(metric.value, metric.unit) }), _jsx(Box, { sx: { textAlign: 'right' }, children: attrCount > 0 ? (_jsxs(Label, { size: "small", variant: "secondary", onClick: (e) => {
97
+ }, children: formatValue(metric.value, metric.unit) }), _jsx(Box, { textAlign: "right", children: attrCount > 0 ? (_jsxs(Label, { size: "small", variant: "secondary", onClick: (e) => {
127
98
  e.stopPropagation();
128
99
  setShowAttrs(!showAttrs);
129
- }, sx: { cursor: 'pointer' }, children: [attrCount, " attr", attrCount !== 1 ? 's' : ''] })) : (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "\u2014" })) })] }), showAttrs && metric.attributes && (_jsx(Box, { sx: { px: 5, py: 2, bg: 'canvas.inset' }, children: _jsx(Box, { as: "pre", sx: {
130
- m: 0,
131
- fontSize: 0,
132
- fontFamily: 'mono',
133
- whiteSpace: 'pre-wrap',
134
- wordBreak: 'break-word',
135
- }, children: JSON.stringify(metric.attributes, null, 2) }) }))] }));
100
+ }, sx: { cursor: 'pointer' }, children: [attrCount, " attr", attrCount !== 1 ? 's' : ''] })) : (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "\u2014" })) })] }), showAttrs && metric.attributes && (_jsx(Box, { px: 5, py: 2, bg: "canvas.inset", children: _jsx(Box, { as: "pre", m: 0, fontSize: 0, fontFamily: "mono", whiteSpace: "pre-wrap", wordBreak: "break-word", children: JSON.stringify(metric.attributes, null, 2) }) }))] }));
136
101
  };
137
102
  // ── OtelMetricsList ─────────────────────────────────────────────────
138
103
  const COOKIE_KEY = 'otel_metrics_view';
@@ -163,46 +128,12 @@ export const OtelMetricsList = ({ metrics, loading = false, }) => {
163
128
  };
164
129
  const grouped = useMemo(() => groupByName(metrics), [metrics]);
165
130
  if (loading) {
166
- return (_jsx(Box, { sx: {
167
- display: 'flex',
168
- justifyContent: 'center',
169
- alignItems: 'center',
170
- p: 5,
171
- }, children: _jsx(Spinner, { size: "medium" }) }));
131
+ return (_jsx(Box, { display: "flex", justifyContent: "center", alignItems: "center", p: 5, children: _jsx(Spinner, { size: "medium" }) }));
172
132
  }
173
133
  if (metrics.length === 0) {
174
134
  return (_jsxs(Blankslate, { children: [_jsx(Blankslate.Visual, { children: _jsx(MeterIcon, { size: 20 }) }), _jsx(Blankslate.Heading, { children: "No metrics yet" }), _jsx(Blankslate.Description, { children: "Generate some metrics or adjust the filters above." })] }));
175
135
  }
176
- return (_jsxs(Box, { sx: {
177
- display: 'flex',
178
- flexDirection: 'column',
179
- flex: 1,
180
- minHeight: 0,
181
- overflow: 'hidden',
182
- }, children: [_jsx(Box, { sx: {
183
- flexShrink: 0,
184
- display: 'flex',
185
- alignItems: 'center',
186
- justifyContent: 'flex-end',
187
- px: 3,
188
- py: 2,
189
- bg: 'canvas.subtle',
190
- borderBottom: '1px solid',
191
- borderColor: 'border.default',
192
- zIndex: 0,
193
- }, children: _jsxs(SegmentedControl, { "aria-label": "Metrics view", size: "small", onChange: (idx) => handleViewChange(idx === 0 ? 'chart' : 'table'), children: [_jsx(SegmentedControl.IconButton, { icon: GraphIcon, "aria-label": "Chart", selected: view === 'chart' }), _jsx(SegmentedControl.IconButton, { icon: TableIcon, "aria-label": "Table", selected: view === 'table' })] }) }), _jsx(Box, { sx: { flex: 1, minHeight: 0, overflow: 'auto' }, children: view === 'chart' ? (_jsx(Box, { sx: { px: 3, py: 2 }, children: _jsx(OtelMetricsChart, { metrics: metrics, height: 280 }) })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
194
- display: 'grid',
195
- gridTemplateColumns: '20px 1fr auto auto auto auto',
196
- gap: 3,
197
- px: 3,
198
- py: 1,
199
- bg: 'canvas.subtle',
200
- borderBottom: '2px solid',
201
- borderColor: 'border.default',
202
- position: 'sticky',
203
- top: 0,
204
- zIndex: 1,
205
- }, children: [_jsx(Box, {}), ['Metric Name', 'Latest', 'Average', 'Min/Max', 'Points'].map((h, i) => (_jsx(Text, { sx: {
136
+ return (_jsxs(Box, { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, overflow: "hidden", children: [_jsx(Box, { flexShrink: 0, display: "flex", alignItems: "center", justifyContent: "flex-end", px: 3, py: 2, bg: "canvas.subtle", borderBottom: "1px solid", borderColor: "border.default", zIndex: 0, children: _jsxs(SegmentedControl, { "aria-label": "Metrics view", size: "small", onChange: (idx) => handleViewChange(idx === 0 ? 'chart' : 'table'), children: [_jsx(SegmentedControl.IconButton, { icon: GraphIcon, "aria-label": "Chart", selected: view === 'chart' }), _jsx(SegmentedControl.IconButton, { icon: TableIcon, "aria-label": "Table", selected: view === 'table' })] }) }), _jsx(Box, { flex: 1, minHeight: 0, overflow: "auto", children: view === 'chart' ? (_jsx(Box, { px: 3, py: 2, children: _jsx(OtelMetricsChart, { metrics: metrics, height: 280 }) })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { display: "grid", gridTemplateColumns: "20px 1fr auto auto auto auto", gap: 3, px: 3, py: 1, bg: "canvas.subtle", borderBottom: "2px solid", borderColor: "border.default", position: "sticky", top: 0, zIndex: 1, children: [_jsx(Box, {}), ['Metric Name', 'Latest', 'Average', 'Min/Max', 'Points'].map((h, i) => (_jsx(Text, { sx: {
206
137
  fontSize: 0,
207
138
  fontWeight: 'bold',
208
139
  color: 'fg.muted',
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, SegmentedControl, ActionMenu, ActionList, TextInput, Button, } from '@primer/react';
2
+ import { Box } from '@datalayer/primer-addons';
3
+ import { SegmentedControl, ActionMenu, ActionList, TextInput, Button, } from '@primer/react';
3
4
  import { SyncIcon, SearchIcon } from '@primer/octicons-react';
4
5
  const SIGNALS = [
5
6
  { value: 'traces', label: 'Traces' },
@@ -8,15 +9,5 @@ const SIGNALS = [
8
9
  ];
9
10
  export const OtelSearchBar = ({ signal, onSignalChange, services, selectedService, onServiceChange, query, onQueryChange, onRefresh, loading, }) => {
10
11
  const safeServices = Array.isArray(services) ? services : [];
11
- return (_jsxs(Box, { sx: {
12
- display: 'flex',
13
- alignItems: 'center',
14
- gap: 2,
15
- px: 3,
16
- py: 2,
17
- bg: 'canvas.subtle',
18
- borderBottom: '1px solid',
19
- borderColor: 'border.default',
20
- flexWrap: 'wrap',
21
- }, children: [_jsx(SegmentedControl, { "aria-label": "Signal type", size: "small", onChange: idx => onSignalChange(SIGNALS[idx].value), children: SIGNALS.map(s => (_jsx(SegmentedControl.Button, { selected: s.value === signal, "aria-label": s.label, children: s.label }, s.value))) }), _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { size: "small", variant: "invisible", children: selectedService || 'All services' }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsxs(ActionList, { selectionVariant: "single", children: [_jsx(ActionList.Item, { selected: selectedService === '', onSelect: () => onServiceChange(''), children: "All services" }), safeServices.length > 0 && _jsx(ActionList.Divider, {}), safeServices.map(svc => (_jsx(ActionList.Item, { selected: selectedService === svc, onSelect: () => onServiceChange(svc), children: svc }, svc)))] }) })] }), _jsx(Box, { sx: { flex: 1, minWidth: 180 }, children: _jsx(TextInput, { leadingVisual: SearchIcon, value: query, onChange: e => onQueryChange(e.target.value), placeholder: "Search spans, logs, metrics\u2026", size: "small", block: true, "aria-label": "Search telemetry" }) }), onRefresh && (_jsx(Button, { size: "small", leadingVisual: SyncIcon, onClick: onRefresh, disabled: loading, "aria-label": "Refresh", children: "Refresh" }))] }));
12
+ return (_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 2, bg: "canvas.subtle", borderBottom: "1px solid", borderColor: "border.default", flexWrap: "wrap", children: [_jsx(SegmentedControl, { "aria-label": "Signal type", size: "small", onChange: idx => onSignalChange(SIGNALS[idx].value), children: SIGNALS.map(s => (_jsx(SegmentedControl.Button, { selected: s.value === signal, "aria-label": s.label, children: s.label }, s.value))) }), _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { size: "small", variant: "invisible", children: selectedService || 'All services' }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsxs(ActionList, { selectionVariant: "single", children: [_jsx(ActionList.Item, { selected: selectedService === '', onSelect: () => onServiceChange(''), children: "All services" }), safeServices.length > 0 && _jsx(ActionList.Divider, {}), safeServices.map(svc => (_jsx(ActionList.Item, { selected: selectedService === svc, onSelect: () => onServiceChange(svc), children: svc }, svc)))] }) })] }), _jsx(Box, { flex: 1, minWidth: 180, children: _jsx(TextInput, { leadingVisual: SearchIcon, value: query, onChange: e => onQueryChange(e.target.value), placeholder: "Search spans, logs, metrics\u2026", size: "small", block: true, "aria-label": "Search telemetry" }) }), onRefresh && (_jsx(Button, { size: "small", leadingVisual: SyncIcon, onClick: onRefresh, disabled: loading, "aria-label": "Refresh", children: "Refresh" }))] }));
22
13
  };
@@ -12,7 +12,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  * @module otel/OtelSpanDetail
13
13
  */
14
14
  import { useMemo, useState } from 'react';
15
- import { Box, Text, IconButton, UnderlineNav, CounterLabel, Label, } from '@primer/react';
15
+ import { Box } from '@datalayer/primer-addons';
16
+ import { Text, IconButton, UnderlineNav, CounterLabel, Label, } from '@primer/react';
16
17
  import { XIcon, ChevronDownIcon, ChevronRightIcon, } from '@primer/octicons-react';
17
18
  import { formatDuration, buildSpanTree } from '../utils.js';
18
19
  import { OtelSpanTree } from './OtelSpanTree.js';
@@ -21,13 +22,7 @@ import { OtelSpanTree } from './OtelSpanTree.js';
21
22
  const MetadataRow = ({ label, value, mono = false }) => {
22
23
  if (value === undefined || value === null || value === '')
23
24
  return null;
24
- return (_jsxs(Box, { sx: {
25
- display: 'flex',
26
- py: 1,
27
- borderBottom: '1px solid',
28
- borderColor: 'border.muted',
29
- gap: 2,
30
- }, children: [_jsx(Text, { sx: {
25
+ return (_jsxs(Box, { display: "flex", py: 1, borderBottom: "1px solid", borderColor: "border.muted", gap: 2, children: [_jsx(Text, { sx: {
31
26
  width: 140,
32
27
  minWidth: 140,
33
28
  color: 'fg.muted',
@@ -44,22 +39,7 @@ const CollapsibleSection = ({ title, data, defaultOpen = false }) => {
44
39
  const [open, setOpen] = useState(defaultOpen);
45
40
  if (!data || Object.keys(data).length === 0)
46
41
  return null;
47
- return (_jsxs(Box, { sx: { mt: 3 }, children: [_jsxs(Box, { sx: {
48
- display: 'flex',
49
- alignItems: 'center',
50
- gap: 1,
51
- cursor: 'pointer',
52
- py: 1,
53
- userSelect: 'none',
54
- }, onClick: () => setOpen(!open), children: [open ? _jsx(ChevronDownIcon, { size: 16 }) : _jsx(ChevronRightIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: title }), _jsx(CounterLabel, { children: Object.keys(data).length })] }), open && (_jsx(Box, { sx: {
55
- bg: 'canvas.subtle',
56
- borderRadius: 2,
57
- border: '1px solid',
58
- borderColor: 'border.default',
59
- p: 2,
60
- mt: 1,
61
- overflowX: 'auto',
62
- }, children: Object.entries(data).map(([key, val]) => (_jsx(AttributeRow, { attrKey: key, value: val, depth: 0 }, key))) }))] }));
42
+ return (_jsxs(Box, { mt: 3, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, cursor: "pointer", py: 1, userSelect: "none", onClick: () => setOpen(!open), children: [open ? _jsx(ChevronDownIcon, { size: 16 }) : _jsx(ChevronRightIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: title }), _jsx(CounterLabel, { children: Object.keys(data).length })] }), open && (_jsx(Box, { bg: "canvas.subtle", borderRadius: 2, border: "1px solid", borderColor: "border.default", p: 2, mt: 1, overflowX: "auto", children: Object.entries(data).map(([key, val]) => (_jsx(AttributeRow, { attrKey: key, value: val, depth: 0 }, key))) }))] }));
63
43
  };
64
44
  /**
65
45
  * A value as the detail unfolds it: JSON text of an object or an array (the
@@ -87,24 +67,7 @@ const AttributeRow = ({ attrKey, value: given, depth }) => {
87
67
  const isObject = typeof value === 'object' && value !== null && !Array.isArray(value);
88
68
  const isArray = Array.isArray(value);
89
69
  const isNested = isObject || isArray;
90
- return (_jsxs(Box, { sx: {
91
- borderBottom: depth === 0 ? '1px solid' : 'none',
92
- borderColor: 'border.muted',
93
- pb: depth === 0 ? 1 : 0,
94
- mb: depth === 0 ? 1 : 0,
95
- }, children: [_jsxs(Box, { sx: {
96
- display: 'flex',
97
- gap: 2,
98
- py: 1,
99
- pl: depth * 16 + 'px',
100
- alignItems: 'flex-start',
101
- }, children: [isNested ? (_jsx(Box, { sx: {
102
- cursor: 'pointer',
103
- color: 'fg.muted',
104
- userSelect: 'none',
105
- width: 16,
106
- flexShrink: 0,
107
- }, onClick: () => setOpen(!open), children: open ? (_jsx(ChevronDownIcon, { size: 12 })) : (_jsx(ChevronRightIcon, { size: 12 })) })) : (_jsx(Box, { sx: { width: 16, flexShrink: 0 } })), _jsx(Text, { sx: {
70
+ return (_jsxs(Box, { borderBottom: depth === 0 ? '1px solid' : 'none', borderColor: "border.muted", pb: depth === 0 ? 1 : 0, mb: depth === 0 ? 1 : 0, children: [_jsxs(Box, { display: "flex", gap: 2, py: 1, pl: depth * 16 + 'px', alignItems: "flex-start", children: [isNested ? (_jsx(Box, { cursor: "pointer", color: "fg.muted", userSelect: "none", width: 16, flexShrink: 0, onClick: () => setOpen(!open), children: open ? (_jsx(ChevronDownIcon, { size: 12 })) : (_jsx(ChevronRightIcon, { size: 12 })) })) : (_jsx(Box, { width: 16, flexShrink: 0 })), _jsx(Text, { sx: {
108
71
  color: 'accent.fg',
109
72
  fontSize: 1,
110
73
  fontFamily: 'mono',
@@ -127,7 +90,7 @@ const AttributeRow = ({ attrKey, value: given, depth }) => {
127
90
  export const OtelSpanDetail = ({ span, traceSpans, onClose, }) => {
128
91
  const [activeTab, setActiveTab] = useState('details');
129
92
  if (!span) {
130
- return (_jsx(Box, { sx: { p: 5, color: 'fg.muted', textAlign: 'center' }, children: _jsx(Text, { children: "Select a span to view details." }) }));
93
+ return (_jsx(Box, { p: 5, color: "fg.muted", textAlign: "center", children: _jsx(Text, { children: "Select a span to view details." }) }));
131
94
  }
132
95
  // Separate gen_ai attributes from other attributes
133
96
  const genAiAttrs = {};
@@ -144,49 +107,16 @@ export const OtelSpanDetail = ({ span, traceSpans, onClose, }) => {
144
107
  }
145
108
  // Build tree from traceSpans for tree tab
146
109
  const tree = traceSpans && traceSpans.length > 0 ? buildSpanTree(traceSpans) : undefined;
147
- return (_jsxs(Box, { sx: {
148
- height: '100%',
149
- overflow: 'auto',
150
- borderLeft: '1px solid',
151
- borderColor: 'border.default',
152
- bg: 'canvas.default',
153
- display: 'flex',
154
- flexDirection: 'column',
155
- }, children: [_jsxs(Box, { sx: {
156
- px: 3,
157
- py: 2,
158
- borderBottom: '1px solid',
159
- borderColor: 'border.default',
160
- display: 'flex',
161
- justifyContent: 'space-between',
162
- alignItems: 'center',
163
- bg: 'canvas.subtle',
164
- flexShrink: 0,
165
- }, children: [_jsx(Text, { sx: { fontSize: 2, fontWeight: 'bold' }, children: span.span_name }), onClose && (_jsx(IconButton, { icon: XIcon, "aria-label": "Close detail panel", variant: "invisible", size: "small", onClick: onClose }))] }), _jsxs(UnderlineNav, { "aria-label": "Span detail tabs", children: [_jsx(UnderlineNav.Item, { "aria-current": activeTab === 'details' ? 'page' : undefined, onClick: () => setActiveTab('details'), children: "Details" }), tree && (_jsx(UnderlineNav.Item, { "aria-current": activeTab === 'tree' ? 'page' : undefined, onClick: () => setActiveTab('tree'), children: "Trace Tree" })), _jsx(UnderlineNav.Item, { "aria-current": activeTab === 'raw' ? 'page' : undefined, onClick: () => setActiveTab('raw'), children: "Raw Data" })] }), _jsxs(Box, { sx: { flex: 1, overflow: 'auto' }, children: [activeTab === 'details' && (_jsxs(Box, { sx: { p: 3 }, children: [_jsx(MetadataRow, { label: "span_name", value: span.span_name }), _jsx(MetadataRow, { label: "service_name", value: span.service_name }), _jsx(MetadataRow, { label: "otel_scope_name", value: span.otel_scope_name }), _jsx(MetadataRow, { label: "kind", value: span.kind }), _jsx(MetadataRow, { label: "trace_id", value: span.trace_id, mono: true }), _jsx(MetadataRow, { label: "span_id", value: span.span_id, mono: true }), _jsx(MetadataRow, { label: "parent_span_id", value: span.parent_span_id, mono: true }), _jsx(MetadataRow, { label: "duration", value: formatDuration(span.duration_ms) }), _jsx(MetadataRow, { label: "start_time", value: span.start_time, mono: true }), _jsx(MetadataRow, { label: "end_time", value: span.end_time, mono: true }), _jsx(MetadataRow, { label: "status_code", value: span.status_code }), _jsx(MetadataRow, { label: "status_message", value: span.status_message }), _jsx(CollapsibleSection, { title: "Arguments", data: genAiAttrs, defaultOpen: Object.keys(genAiAttrs).length > 0 }), _jsx(CollapsibleSection, { title: "Attributes", data: otherAttrs }), span.events && span.events.length > 0 && (_jsxs(Box, { sx: { mt: 3 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1 }, children: "Events" }), _jsx(CounterLabel, { children: span.events.length })] }), span.events.map((ev, idx) => (_jsxs(Box, { sx: {
166
- bg: 'canvas.subtle',
167
- borderRadius: 2,
168
- border: '1px solid',
169
- borderColor: 'border.default',
170
- p: 2,
171
- mt: 2,
172
- }, children: [_jsxs(Box, { sx: { display: 'flex', gap: 2 }, children: [_jsx(Label, { children: ev.name }), _jsx(Text, { sx: {
110
+ return (_jsxs(Box, { height: "100%", overflow: "auto", borderLeft: "1px solid", borderColor: "border.default", bg: "canvas.default", display: "flex", flexDirection: "column", children: [_jsxs(Box, { px: 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", display: "flex", justifyContent: "space-between", alignItems: "center", bg: "canvas.subtle", flexShrink: 0, children: [_jsx(Text, { sx: { fontSize: 2, fontWeight: 'bold' }, children: span.span_name }), onClose && (_jsx(IconButton, { icon: XIcon, "aria-label": "Close detail panel", variant: "invisible", size: "small", onClick: onClose }))] }), _jsxs(UnderlineNav, { "aria-label": "Span detail tabs", children: [_jsx(UnderlineNav.Item, { "aria-current": activeTab === 'details' ? 'page' : undefined, onClick: () => setActiveTab('details'), children: "Details" }), tree && (_jsx(UnderlineNav.Item, { "aria-current": activeTab === 'tree' ? 'page' : undefined, onClick: () => setActiveTab('tree'), children: "Trace Tree" })), _jsx(UnderlineNav.Item, { "aria-current": activeTab === 'raw' ? 'page' : undefined, onClick: () => setActiveTab('raw'), children: "Raw Data" })] }), _jsxs(Box, { flex: 1, overflow: "auto", children: [activeTab === 'details' && (_jsxs(Box, { p: 3, children: [_jsx(MetadataRow, { label: "span_name", value: span.span_name }), _jsx(MetadataRow, { label: "service_name", value: span.service_name }), _jsx(MetadataRow, { label: "otel_scope_name", value: span.otel_scope_name }), _jsx(MetadataRow, { label: "kind", value: span.kind }), _jsx(MetadataRow, { label: "trace_id", value: span.trace_id, mono: true }), _jsx(MetadataRow, { label: "span_id", value: span.span_id, mono: true }), _jsx(MetadataRow, { label: "parent_span_id", value: span.parent_span_id, mono: true }), _jsx(MetadataRow, { label: "duration", value: formatDuration(span.duration_ms) }), _jsx(MetadataRow, { label: "start_time", value: span.start_time, mono: true }), _jsx(MetadataRow, { label: "end_time", value: span.end_time, mono: true }), _jsx(MetadataRow, { label: "status_code", value: span.status_code }), _jsx(MetadataRow, { label: "status_message", value: span.status_message }), _jsx(CollapsibleSection, { title: "Arguments", data: genAiAttrs, defaultOpen: Object.keys(genAiAttrs).length > 0 }), _jsx(CollapsibleSection, { title: "Attributes", data: otherAttrs }), span.events && span.events.length > 0 && (_jsxs(Box, { mt: 3, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1 }, children: "Events" }), _jsx(CounterLabel, { children: span.events.length })] }), span.events.map((ev, idx) => (_jsxs(Box, { bg: "canvas.subtle", borderRadius: 2, border: "1px solid", borderColor: "border.default", p: 2, mt: 2, children: [_jsxs(Box, { display: "flex", gap: 2, children: [_jsx(Label, { children: ev.name }), _jsx(Text, { sx: {
173
111
  fontSize: 0,
174
112
  color: 'fg.muted',
175
113
  fontFamily: 'mono',
176
- }, children: ev.timestamp })] }), ev.attributes && Object.keys(ev.attributes).length > 0 && (_jsx(Box, { sx: { mt: 1 }, children: Object.entries(ev.attributes).map(([k, v]) => (_jsx(AttributeRow, { attrKey: k, value: v, depth: 0 }, k))) }))] }, idx)))] })), span.links && span.links.length > 0 && (_jsxs(Box, { sx: { mt: 3 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1 }, children: "Links" }), _jsx(CounterLabel, { children: span.links.length })] }), span.links.map((link, idx) => (_jsxs(Text, { sx: {
114
+ }, children: ev.timestamp })] }), ev.attributes && Object.keys(ev.attributes).length > 0 && (_jsx(Box, { mt: 1, children: Object.entries(ev.attributes).map(([k, v]) => (_jsx(AttributeRow, { attrKey: k, value: v, depth: 0 }, k))) }))] }, idx)))] })), span.links && span.links.length > 0 && (_jsxs(Box, { mt: 3, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1 }, children: "Links" }), _jsx(CounterLabel, { children: span.links.length })] }), span.links.map((link, idx) => (_jsxs(Text, { sx: {
177
115
  display: 'block',
178
116
  fontSize: 1,
179
117
  fontFamily: 'mono',
180
118
  py: 1,
181
119
  borderBottom: '1px solid',
182
120
  borderColor: 'border.muted',
183
- }, children: ["trace: ", link.trace_id, " \u2192 span: ", link.span_id] }, idx)))] }))] })), activeTab === 'tree' && tree && (_jsx(OtelSpanTree, { spans: tree, selectedSpanId: span.span_id, defaultExpandDepth: 4 })), activeTab === 'raw' && (_jsx(Box, { as: "pre", sx: {
184
- p: 3,
185
- fontSize: 0,
186
- fontFamily: 'mono',
187
- whiteSpace: 'pre-wrap',
188
- wordBreak: 'break-word',
189
- m: 0,
190
- bg: 'canvas.subtle',
191
- }, children: JSON.stringify(span, null, 2) }))] })] }));
121
+ }, children: ["trace: ", link.trace_id, " \u2192 span: ", link.span_id] }, idx)))] }))] })), activeTab === 'tree' && tree && (_jsx(OtelSpanTree, { spans: tree, selectedSpanId: span.span_id, defaultExpandDepth: 4 })), activeTab === 'raw' && (_jsx(Box, { as: "pre", p: 3, fontSize: 0, fontFamily: "mono", whiteSpace: "pre-wrap", wordBreak: "break-word", m: 0, bg: "canvas.subtle", children: JSON.stringify(span, null, 2) }))] })] }));
192
122
  };
@@ -12,7 +12,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  * @module otel/OtelSpanTree
13
13
  */
14
14
  import { useState, useMemo, useCallback } from 'react';
15
- import { Box, Text } from '@primer/react';
15
+ import { Box } from '@datalayer/primer-addons';
16
+ import { Text } from '@primer/react';
16
17
  import { ChevronDownIcon, ChevronRightIcon } from '@primer/octicons-react';
17
18
  import { formatDuration, serviceColor, toMs } from '../utils.js';
18
19
  const INDENT_PX = 20;
@@ -23,61 +24,18 @@ const SpanNode = ({ span, depth, selectedSpanId, onSelectSpan, expandedIds, togg
23
24
  const color = serviceColor(span.service_name);
24
25
  const startPct = ((toMs(span.start_time) - traceMinTime) / traceDuration) * 100;
25
26
  const widthPct = Math.max(((span.duration_ms || 0) / traceDuration) * 100, 0.5);
26
- return (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
27
- display: 'flex',
28
- alignItems: 'center',
29
- height: 28,
30
- pl: `${depth * INDENT_PX}px`,
31
- pr: 2,
32
- cursor: 'pointer',
33
- bg: isSelected ? 'accent.subtle' : 'canvas.default',
34
- borderBottom: '1px solid',
35
- borderColor: 'border.muted',
36
- ':hover': {
37
- bg: isSelected ? 'accent.subtle' : 'canvas.subtle',
38
- },
39
- }, onClick: () => onSelectSpan?.(span), children: [_jsx(Box, { sx: {
40
- width: 20,
41
- textAlign: 'center',
42
- color: 'fg.muted',
43
- userSelect: 'none',
44
- flexShrink: 0,
45
- cursor: hasChildren ? 'pointer' : 'default',
46
- }, onClick: e => {
27
+ return (_jsxs(_Fragment, { children: [_jsxs(Box, { display: "flex", alignItems: "center", height: 28, pl: `${depth * INDENT_PX}px`, pr: 2, cursor: "pointer", bg: isSelected ? 'accent.subtle' : 'canvas.default', borderBottom: "1px solid", borderColor: "border.muted", hover: { bg: isSelected ? 'accent.subtle' : 'canvas.subtle' }, onClick: () => onSelectSpan?.(span), children: [_jsx(Box, { width: 20, textAlign: "center", color: "fg.muted", userSelect: "none", flexShrink: 0, cursor: hasChildren ? 'pointer' : 'default', onClick: e => {
47
28
  e.stopPropagation();
48
29
  if (hasChildren)
49
30
  toggleExpanded(span.span_id);
50
- }, children: hasChildren ? (isExpanded ? (_jsx(ChevronDownIcon, { size: 12 })) : (_jsx(ChevronRightIcon, { size: 12 }))) : (_jsx(Text, { sx: { color: 'fg.subtle', fontSize: 0 }, children: "\u00B7" })) }), _jsx(Box, { sx: {
51
- width: 8,
52
- height: 8,
53
- borderRadius: '50%',
54
- bg: color,
55
- flexShrink: 0,
56
- mr: 1,
57
- } }), _jsx(Text, { sx: {
31
+ }, children: hasChildren ? (isExpanded ? (_jsx(ChevronDownIcon, { size: 12 })) : (_jsx(ChevronRightIcon, { size: 12 }))) : (_jsx(Text, { sx: { color: 'fg.subtle', fontSize: 0 }, children: "\u00B7" })) }), _jsx(Box, { width: 8, height: 8, borderRadius: "50%", bg: color, flexShrink: 0, mr: 1 }), _jsx(Text, { sx: {
58
32
  flex: '0 0 200px',
59
33
  overflow: 'hidden',
60
34
  textOverflow: 'ellipsis',
61
35
  whiteSpace: 'nowrap',
62
36
  fontSize: 1,
63
37
  fontWeight: isSelected ? 'bold' : 'normal',
64
- }, title: `${span.service_name} / ${span.span_name}`, children: span.span_name }), _jsx(Box, { sx: {
65
- flex: 1,
66
- position: 'relative',
67
- height: 12,
68
- bg: 'canvas.subtle',
69
- borderRadius: 1,
70
- mx: 2,
71
- overflow: 'hidden',
72
- }, children: _jsx(Box, { sx: {
73
- position: 'absolute',
74
- left: `${startPct}%`,
75
- width: `${widthPct}%`,
76
- height: '100%',
77
- bg: color,
78
- borderRadius: 1,
79
- opacity: isSelected ? 1 : 0.7,
80
- } }) }), _jsx(Text, { sx: {
38
+ }, title: `${span.service_name} / ${span.span_name}`, children: span.span_name }), _jsx(Box, { flex: 1, position: "relative", height: 12, bg: "canvas.subtle", borderRadius: 1, mx: 2, overflow: "hidden", children: _jsx(Box, { position: "absolute", left: `${startPct}%`, width: `${widthPct}%`, height: "100%", bg: color, borderRadius: 1, opacity: isSelected ? 1 : 0.7 }) }), _jsx(Text, { sx: {
81
39
  minWidth: 60,
82
40
  textAlign: 'right',
83
41
  fontSize: 0,
@@ -139,17 +97,9 @@ export const OtelSpanTree = ({ spans, selectedSpanId, onSelectSpan, defaultExpan
139
97
  return { traceMinTime: min, traceDuration: max - min || 1 };
140
98
  }, [spans]);
141
99
  if (spans.length === 0) {
142
- return (_jsx(Box, { sx: { p: 3, color: 'fg.muted', textAlign: 'center' }, children: _jsx(Text, { children: "No span tree to display." }) }));
100
+ return (_jsx(Box, { p: 3, color: "fg.muted", textAlign: "center", children: _jsx(Text, { children: "No span tree to display." }) }));
143
101
  }
144
- return (_jsxs(Box, { sx: { width: '100%', overflow: 'auto' }, children: [_jsxs(Box, { sx: {
145
- display: 'flex',
146
- alignItems: 'center',
147
- height: 28,
148
- px: 2,
149
- borderBottom: '2px solid',
150
- borderColor: 'border.default',
151
- bg: 'canvas.subtle',
152
- }, children: [_jsx(Box, { sx: { width: 20 } }), _jsx(Box, { sx: { width: 8, mr: 1 } }), _jsx(Text, { sx: {
102
+ return (_jsxs(Box, { width: "100%", overflow: "auto", children: [_jsxs(Box, { display: "flex", alignItems: "center", height: 28, px: 2, borderBottom: "2px solid", borderColor: "border.default", bg: "canvas.subtle", children: [_jsx(Box, { width: 20 }), _jsx(Box, { width: 8, mr: 1 }), _jsx(Text, { sx: {
153
103
  flex: '0 0 200px',
154
104
  fontSize: 0,
155
105
  fontWeight: 'bold',