@datalayer/core 1.2.18 → 1.2.20

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 (228) 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.d.ts +10 -11
  6. package/lib/components/avatars/UserAvatar.js +23 -52
  7. package/lib/components/avatars/UserProfileAvatar.js +1 -1
  8. package/lib/components/avatars/avatarChoice.d.ts +42 -0
  9. package/lib/components/avatars/avatarChoice.js +65 -0
  10. package/lib/components/avatars/index.d.ts +1 -0
  11. package/lib/components/avatars/index.js +1 -0
  12. package/lib/components/billing/BillingEntitySelect.js +6 -48
  13. package/lib/components/checkout/StripeCheckout.js +33 -217
  14. package/lib/components/collaboration/LiveEditorCollaborators.d.ts +3 -4
  15. package/lib/components/collaboration/LiveEditorCollaborators.js +7 -5
  16. package/lib/components/contents/ContentSourceCard.js +2 -11
  17. package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +1 -1
  18. package/lib/components/contents/HomeFolderObjectsBrowser.js +11 -35
  19. package/lib/components/display/CenteredSpinner.js +1 -6
  20. package/lib/components/display/DatalayerBox.js +2 -14
  21. package/lib/components/emoji/faceEmojis.js +48 -0
  22. package/lib/components/emoji/fluent/loaders.js +46 -0
  23. package/lib/components/emoji/fluent/svg/1f30a.d.ts +2 -0
  24. package/lib/components/emoji/fluent/svg/1f30a.js +5 -0
  25. package/lib/components/emoji/fluent/svg/1f310.d.ts +2 -0
  26. package/lib/components/emoji/fluent/svg/1f310.js +5 -0
  27. package/lib/components/emoji/fluent/svg/1f324.d.ts +2 -0
  28. package/lib/components/emoji/fluent/svg/1f324.js +5 -0
  29. package/lib/components/emoji/fluent/svg/1f326.d.ts +2 -0
  30. package/lib/components/emoji/fluent/svg/1f326.js +5 -0
  31. package/lib/components/emoji/fluent/svg/1f327.d.ts +2 -0
  32. package/lib/components/emoji/fluent/svg/1f327.js +5 -0
  33. package/lib/components/emoji/fluent/svg/1f33e.d.ts +2 -0
  34. package/lib/components/emoji/fluent/svg/1f33e.js +5 -0
  35. package/lib/components/emoji/fluent/svg/1f372.d.ts +2 -0
  36. package/lib/components/emoji/fluent/svg/1f372.js +5 -0
  37. package/lib/components/emoji/fluent/svg/1f373.d.ts +2 -0
  38. package/lib/components/emoji/fluent/svg/1f373.js +5 -0
  39. package/lib/components/emoji/fluent/svg/1f39b.d.ts +2 -0
  40. package/lib/components/emoji/fluent/svg/1f39b.js +5 -0
  41. package/lib/components/emoji/fluent/svg/1f3ab.d.ts +2 -0
  42. package/lib/components/emoji/fluent/svg/1f3ab.js +5 -0
  43. package/lib/components/emoji/fluent/svg/1f41b.d.ts +2 -0
  44. package/lib/components/emoji/fluent/svg/1f41b.js +5 -0
  45. package/lib/components/emoji/fluent/svg/1f441.d.ts +2 -0
  46. package/lib/components/emoji/fluent/svg/1f441.js +5 -0
  47. package/lib/components/emoji/fluent/svg/1f465.d.ts +2 -0
  48. package/lib/components/emoji/fluent/svg/1f465.js +5 -0
  49. package/lib/components/emoji/fluent/svg/1f4b9.d.ts +2 -0
  50. package/lib/components/emoji/fluent/svg/1f4b9.js +5 -0
  51. package/lib/components/emoji/fluent/svg/1f4be.d.ts +2 -0
  52. package/lib/components/emoji/fluent/svg/1f4be.js +5 -0
  53. package/lib/components/emoji/fluent/svg/1f4c1.d.ts +2 -0
  54. package/lib/components/emoji/fluent/svg/1f4c1.js +5 -0
  55. package/lib/components/emoji/fluent/svg/1f4c2.d.ts +2 -0
  56. package/lib/components/emoji/fluent/svg/1f4c2.js +5 -0
  57. package/lib/components/emoji/fluent/svg/1f4c4.d.ts +2 -0
  58. package/lib/components/emoji/fluent/svg/1f4c4.js +5 -0
  59. package/lib/components/emoji/fluent/svg/1f4d3.d.ts +2 -0
  60. package/lib/components/emoji/fluent/svg/1f4d3.js +5 -0
  61. package/lib/components/emoji/fluent/svg/1f4d6.d.ts +2 -0
  62. package/lib/components/emoji/fluent/svg/1f4d6.js +5 -0
  63. package/lib/components/emoji/fluent/svg/1f4dc.d.ts +2 -0
  64. package/lib/components/emoji/fluent/svg/1f4dc.js +5 -0
  65. package/lib/components/emoji/fluent/svg/1f4e1.d.ts +2 -0
  66. package/lib/components/emoji/fluent/svg/1f4e1.js +5 -0
  67. package/lib/components/emoji/fluent/svg/1f4e2.d.ts +2 -0
  68. package/lib/components/emoji/fluent/svg/1f4e2.js +5 -0
  69. package/lib/components/emoji/fluent/svg/1f4e7.d.ts +2 -0
  70. package/lib/components/emoji/fluent/svg/1f4e7.js +5 -0
  71. package/lib/components/emoji/fluent/svg/1f500.d.ts +2 -0
  72. package/lib/components/emoji/fluent/svg/1f500.js +5 -0
  73. package/lib/components/emoji/fluent/svg/1f501.d.ts +2 -0
  74. package/lib/components/emoji/fluent/svg/1f501.js +5 -0
  75. package/lib/components/emoji/fluent/svg/1f504.d.ts +2 -0
  76. package/lib/components/emoji/fluent/svg/1f504.js +5 -0
  77. package/lib/components/emoji/fluent/svg/1f52d.d.ts +2 -0
  78. package/lib/components/emoji/fluent/svg/1f52d.js +5 -0
  79. package/lib/components/emoji/fluent/svg/1f552.d.ts +2 -0
  80. package/lib/components/emoji/fluent/svg/1f552.js +5 -0
  81. package/lib/components/emoji/fluent/svg/1f58b.d.ts +2 -0
  82. package/lib/components/emoji/fluent/svg/1f58b.js +5 -0
  83. package/lib/components/emoji/fluent/svg/1f5b2.d.ts +2 -0
  84. package/lib/components/emoji/fluent/svg/1f5b2.js +5 -0
  85. package/lib/components/emoji/fluent/svg/1f5c3.d.ts +2 -0
  86. package/lib/components/emoji/fluent/svg/1f5c3.js +5 -0
  87. package/lib/components/emoji/fluent/svg/1f5d1.d.ts +2 -0
  88. package/lib/components/emoji/fluent/svg/1f5d1.js +5 -0
  89. package/lib/components/emoji/fluent/svg/1f5dc.d.ts +2 -0
  90. package/lib/components/emoji/fluent/svg/1f5dc.js +5 -0
  91. package/lib/components/emoji/fluent/svg/1f604.d.ts +2 -0
  92. package/lib/components/emoji/fluent/svg/1f604.js +5 -0
  93. package/lib/components/emoji/fluent/svg/1f917.d.ts +2 -0
  94. package/lib/components/emoji/fluent/svg/1f917.js +5 -0
  95. package/lib/components/emoji/fluent/svg/1f9d1-200d-2696.d.ts +2 -0
  96. package/lib/components/emoji/fluent/svg/1f9d1-200d-2696.js +5 -0
  97. package/lib/components/emoji/fluent/svg/1fa79.d.ts +2 -0
  98. package/lib/components/emoji/fluent/svg/1fa79.js +5 -0
  99. package/lib/components/emoji/fluent/svg/1fa9d.d.ts +2 -0
  100. package/lib/components/emoji/fluent/svg/1fa9d.js +5 -0
  101. package/lib/components/emoji/fluent/svg/1fa9f.d.ts +2 -0
  102. package/lib/components/emoji/fluent/svg/1fa9f.js +5 -0
  103. package/lib/components/emoji/fluent/svg/23f3.d.ts +2 -0
  104. package/lib/components/emoji/fluent/svg/23f3.js +5 -0
  105. package/lib/components/emoji/fluent/svg/2611.d.ts +2 -0
  106. package/lib/components/emoji/fluent/svg/2611.js +5 -0
  107. package/lib/components/emoji/fluent/svg/2702.d.ts +2 -0
  108. package/lib/components/emoji/fluent/svg/2702.js +5 -0
  109. package/lib/components/emoji/fluent/svg/270f.d.ts +2 -0
  110. package/lib/components/emoji/fluent/svg/270f.js +5 -0
  111. package/lib/components/emoji/fluent/svg/2728.d.ts +2 -0
  112. package/lib/components/emoji/fluent/svg/2728.js +5 -0
  113. package/lib/components/emoji/fluent/svg/2b1c.d.ts +2 -0
  114. package/lib/components/emoji/fluent/svg/2b1c.js +5 -0
  115. package/lib/components/flashes/FlashClosable.js +2 -17
  116. package/lib/components/mcp/ClientBadge.js +1 -1
  117. package/lib/components/mcp/McpErrorBlankslate.js +1 -1
  118. package/lib/components/mcp/ScopeList.js +1 -1
  119. package/lib/components/notebooks/JupyterNotebook.js +1 -2
  120. package/lib/components/principal/Principal.js +2 -10
  121. package/lib/components/principal/PrincipalAppearance.d.ts +24 -1
  122. package/lib/components/principal/PrincipalAppearance.js +107 -80
  123. package/lib/components/principal/PrincipalAvatar.d.ts +5 -7
  124. package/lib/components/principal/PrincipalAvatar.js +12 -38
  125. package/lib/components/principal/PrincipalBadge.js +3 -13
  126. package/lib/components/principal/PrincipalBanner.js +4 -32
  127. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +4 -7
  128. package/lib/components/principal/PrincipalDetailsOverlay.js +8 -24
  129. package/lib/components/principal/PrincipalHoverCard.js +15 -18
  130. package/lib/components/principal/PrincipalSwitcherMenu.js +15 -83
  131. package/lib/components/progress/ConsumptionBar.js +1 -1
  132. package/lib/components/sharing/ShareAccessComponent.js +21 -229
  133. package/lib/components/sharing/SharingEditor.js +1 -1
  134. package/lib/components/spaces/SpaceDetailsOverlay.js +4 -35
  135. package/lib/components/spaces/SpaceDisplay.js +1 -8
  136. package/lib/components/storage/ContentsBrowser.js +3 -26
  137. package/lib/components/storage/ContentsTable.js +4 -23
  138. package/lib/components/students/StudentResultCircle.js +7 -29
  139. package/lib/components/timeline/Timeline.js +4 -36
  140. package/lib/hooks/layouts/LayoutBackdrop.js +2 -1
  141. package/lib/hooks/layouts/LayoutScreencapture.js +1 -1
  142. package/lib/hooks/libraryApp.d.ts +6 -1
  143. package/lib/hooks/libraryApp.js +10 -1
  144. package/lib/hooks/unlinkIAMProvider.d.ts +22 -0
  145. package/lib/hooks/unlinkIAMProvider.js +24 -0
  146. package/lib/hooks/useAuthorization.js +6 -1
  147. package/lib/hooks/useCache.d.ts +8 -1
  148. package/lib/hooks/useCache.js +35 -4
  149. package/lib/hooks/useNavigate.js +8 -2
  150. package/lib/mocks/components/FlashMock.js +3 -8
  151. package/lib/mocks/views/DashboardMock.js +6 -72
  152. package/lib/mocks/views/FormMock.js +3 -2
  153. package/lib/mocks/views/TableMock.js +3 -2
  154. package/lib/mocks/views/WipMock.js +2 -1
  155. package/lib/models/IAMProviderLinked.d.ts +9 -0
  156. package/lib/models/IAMProviderLinked.js +34 -5
  157. package/lib/models/McpTask.d.ts +18 -1
  158. package/lib/models/McpTask.js +15 -0
  159. package/lib/models/Person.d.ts +9 -0
  160. package/lib/models/Person.js +23 -0
  161. package/lib/models/Profile.d.ts +2 -2
  162. package/lib/models/User.js +5 -12
  163. package/lib/models/UserOnboarding.d.ts +9 -0
  164. package/lib/models/UserOnboarding.js +33 -0
  165. package/lib/otel/views/OtelLive.js +4 -62
  166. package/lib/otel/views/OtelLiveSpans.js +4 -29
  167. package/lib/otel/views/OtelLogsList.js +13 -64
  168. package/lib/otel/views/OtelMetricsChart.js +4 -19
  169. package/lib/otel/views/OtelMetricsList.js +8 -77
  170. package/lib/otel/views/OtelSearchBar.js +3 -12
  171. package/lib/otel/views/OtelSpanDetail.js +9 -79
  172. package/lib/otel/views/OtelSpanTree.js +7 -57
  173. package/lib/otel/views/OtelSqlView.js +5 -99
  174. package/lib/otel/views/OtelSystemView.js +4 -34
  175. package/lib/otel/views/OtelTimeline.js +7 -37
  176. package/lib/otel/views/OtelTimelineRangeSlider.js +7 -140
  177. package/lib/otel/views/OtelTracesList.js +12 -76
  178. package/lib/portable/index.d.ts +9 -0
  179. package/lib/portable/index.js +14 -0
  180. package/lib/portable/states.d.ts +39 -0
  181. package/lib/portable/states.js +71 -0
  182. package/lib/state/substates/NavigationState.d.ts +10 -6
  183. package/lib/state/substates/NavigationState.js +18 -8
  184. package/lib/views/api-keys/APIKeyEdit.js +2 -11
  185. package/lib/views/api-keys/APIKeyNew.js +3 -19
  186. package/lib/views/api-keys/APIKeys.js +6 -11
  187. package/lib/views/api-keys/APIKeysStandalone.js +1 -1
  188. package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
  189. package/lib/views/datasources/DatasourceDetail.js +24 -17
  190. package/lib/views/datasources/DatasourceNew.js +2 -6
  191. package/lib/views/datasources/Datasources.js +2 -14
  192. package/lib/views/iam/SignInSimple.js +8 -64
  193. package/lib/views/mcp/AdmittedClients.js +3 -16
  194. package/lib/views/mcp/AlertDestinations.js +3 -11
  195. package/lib/views/mcp/AlertRules.js +4 -9
  196. package/lib/views/mcp/ApprovalQueue.js +5 -22
  197. package/lib/views/mcp/AuditLog.js +7 -44
  198. package/lib/views/mcp/ConnectedAgents.js +1 -6
  199. package/lib/views/mcp/EnterpriseConsole.js +11 -24
  200. package/lib/views/mcp/IdentityProviders.js +7 -31
  201. package/lib/views/mcp/McpDashboard.js +15 -31
  202. package/lib/views/mcp/McpHome.js +8 -55
  203. package/lib/views/mcp/McpObservability.js +14 -86
  204. package/lib/views/mcp/NotebookRuns.js +6 -13
  205. package/lib/views/mcp/OrganizationPolicy.js +3 -9
  206. package/lib/views/mcp/OrganizationUsage.js +5 -12
  207. package/lib/views/mcp/PersonalPolicy.js +3 -3
  208. package/lib/views/mcp/Policies.js +6 -47
  209. package/lib/views/mcp/PolicyForm.js +1 -9
  210. package/lib/views/mcp/PolicyHistory.js +2 -8
  211. package/lib/views/mcp/RunDetail.d.ts +1 -1
  212. package/lib/views/mcp/RunDetail.js +7 -26
  213. package/lib/views/mcp/ScimProvisioning.js +4 -16
  214. package/lib/views/mcp/ServiceAgents.js +4 -17
  215. package/lib/views/mcp/TeamPolicies.js +7 -19
  216. package/lib/views/mcp/ToolAccess.js +16 -23
  217. package/lib/views/mcp/TraceTimeline.js +8 -23
  218. package/lib/views/otel/DashboardView.js +2 -2
  219. package/lib/views/otel/LogsView.js +2 -2
  220. package/lib/views/otel/MetricsView.js +2 -2
  221. package/lib/views/otel/OtelHeader.js +6 -40
  222. package/lib/views/otel/SqlView.js +2 -2
  223. package/lib/views/otel/SystemView.js +2 -2
  224. package/lib/views/otel/TracesView.js +2 -2
  225. package/lib/views/profile/UserBadge.js +6 -98
  226. package/lib/views/secrets/SecretEdit.js +2 -11
  227. package/lib/views/secrets/SecretNew.js +1 -1
  228. package/package.json +1 -1
@@ -3,36 +3,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  * Copyright (c) 2023-2025 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
- import { Box, Link, Text, LabelGroup, Label, ActionMenu, ActionList, } from '@primer/react';
6
+ import { Box } from '@datalayer/primer-addons';
7
+ import { Link, Text, LabelGroup, Label, ActionMenu, ActionList, } from '@primer/react';
7
8
  import { ArrowRightIcon, CloudIcon, StarIcon, DotFillIcon, RepoForkedIcon, LinkIcon, } from '@primer/octicons-react';
8
9
  import { ReactJsIcon } from '@datalayer/icons-react';
9
10
  import { lazyWithPreload, WithSuspense } from '../../utils/index.js';
10
11
  import { ECHART_MOCK_1, ECHART_MOCK_2, ECHART_MOCK_3, FlashMock, } from '../../mocks/index.js';
11
12
  const ReactECharts = WithSuspense(lazyWithPreload(() => import('echarts-for-react')), true);
12
13
  export const DashboardMock = () => {
13
- return (_jsxs(_Fragment, { children: [_jsx(Box, { mb: 3, children: _jsx(FlashMock, {}) }), _jsxs(Box, { sx: {
14
- display: 'grid',
15
- gridTemplateColumns: '1fr 1fr 1fr',
16
- gap: 4,
17
- }, children: [_jsxs(Box, { sx: {
18
- gridColumn: '1 / 3',
19
- minHeight: '200px',
20
- }, children: [_jsxs(Box, { sx: {
21
- display: 'flex',
22
- alignItems: 'center',
23
- justifyContent: 'space-between',
24
- paddingRight: 4,
25
- }, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "My latest work" }), _jsxs(Link, { children: ["View all work", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { sx: {
26
- display: 'grid',
27
- gridTemplateColumns: '1fr 1fr',
28
- gap: 4,
29
- }, children: [_jsxs(Box, { sx: {
30
- borderColor: 'border.default',
31
- borderStyle: 'solid',
32
- borderWidth: '1',
33
- borderRadius: '2',
34
- padding: 4,
35
- }, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["clouder ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", sx: { color: 'fg.subtle', fontWeight: 'semibold' }, children: [_jsx(CloudIcon
14
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { mb: 3, children: _jsx(FlashMock, {}) }), _jsxs(Box, { display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 4, children: [_jsxs(Box, { gridColumn: "1 / 3", minHeight: "200px", children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", paddingRight: 4, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "My latest work" }), _jsxs(Link, { children: ["View all work", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4, children: [_jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", padding: 4, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["clouder ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", sx: { color: 'fg.subtle', fontWeight: 'semibold' }, children: [_jsx(CloudIcon
36
15
  // sx={{ margin: "0 4px" }}
37
16
  , {}), "Create, manage and share Kubernetes clusters."] }), _jsxs(LabelGroup, { sx: { paddingTop: 2, paddingBottom: 2 }, children: [_jsx(Label, { variant: "accent", children: "Kubernetes" }), _jsx(Label, { variant: "accent", children: "cloud" }), _jsx(Label, { variant: "accent", children: "kubernets-cluster" }), _jsx(Label, { variant: "accent", children: "datalayer" })] }), _jsxs(Text, { as: "p", sx: {
38
17
  color: 'fg.subtle',
@@ -47,13 +26,7 @@ export const DashboardMock = () => {
47
26
  // sx={{ marginRight: 1, marginBottom: "3px" }}
48
27
  , {}), "3"] }), _jsxs(Text, { children: [_jsx(StarIcon
49
28
  // sx={{ marginRight: 1, marginBottom: "3px" }}
50
- , {}), "11"] })] })] }), _jsxs(Box, { sx: {
51
- borderColor: 'border.default',
52
- borderStyle: 'solid',
53
- borderWidth: '1',
54
- borderRadius: '2',
55
- padding: 4,
56
- }, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["jupyter-ui ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", children: [_jsx(ReactJsIcon, { style: { margin: '0 4px' } }), "React.js components 100% compatible with Jupyter.", ' ', _jsx(Link, { href: "https://jupyter-ui-storybook.datalayer.tech", children: "https://jupyter-ui-storybook.datalayer.tech" })] }), _jsxs(LabelGroup, { sx: { paddingTop: 2, paddingBottom: 2 }, children: [_jsx(Label, { variant: "accent", children: "data-science" }), _jsx(Label, { variant: "accent", children: "data" }), _jsx(Label, { variant: "accent", children: "ui" }), _jsx(Label, { variant: "accent", children: "jupyter" }), _jsx(Label, { children: "+4" })] }), _jsxs(Text, { as: "p", sx: {
29
+ , {}), "11"] })] })] }), _jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", padding: 4, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["jupyter-ui ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", children: [_jsx(ReactJsIcon, { style: { margin: '0 4px' } }), "React.js components 100% compatible with Jupyter.", ' ', _jsx(Link, { href: "https://jupyter-ui-storybook.datalayer.tech", children: "https://jupyter-ui-storybook.datalayer.tech" })] }), _jsxs(LabelGroup, { sx: { paddingTop: 2, paddingBottom: 2 }, children: [_jsx(Label, { variant: "accent", children: "data-science" }), _jsx(Label, { variant: "accent", children: "data" }), _jsx(Label, { variant: "accent", children: "ui" }), _jsx(Label, { variant: "accent", children: "jupyter" }), _jsx(Label, { children: "+4" })] }), _jsxs(Text, { as: "p", sx: {
57
30
  color: 'fg.subtle',
58
31
  '> *': { paddingLeft: 1, paddingRight: 1 },
59
32
  }, children: [_jsxs(Text, { children: [_jsx(DotFillIcon
@@ -68,51 +41,12 @@ export const DashboardMock = () => {
68
41
  // sx={{ marginRight: 1, marginBottom: "3px" }}
69
42
  , {}), "3"] }), _jsxs(Text, { children: [_jsx(StarIcon
70
43
  // sx={{ marginRight: 1, marginBottom: "3px" }}
71
- , {}), "11"] })] })] })] })] }), _jsxs(Box, { sx: {
72
- gridColumn: '3 / 4',
73
- gridRow: '1 / 3',
74
- minHeight: '200px',
75
- }, children: [_jsxs(Box, { sx: {
76
- display: 'flex',
77
- alignItems: 'center',
78
- justifyContent: 'space-between',
79
- paddingRight: 4,
80
- }, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Usage" }), _jsxs(Link, { children: ["More Usage", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { sx: {
81
- borderColor: 'border.default',
82
- borderStyle: 'solid',
83
- borderWidth: '1',
84
- borderRadius: '2',
85
- padding: 4,
86
- }, children: [_jsxs(Box, { sx: {
87
- display: 'inline-flex',
88
- flexDirection: 'row',
89
- alignItems: 'center',
90
- }, children: [_jsx(Text, { as: "h3", sx: { marginRight: '20px' }, children: "Kernels Activity" }), _jsxs(ActionMenu, { children: [_jsxs(ActionMenu.Button, { children: [_jsx(Box, { sx: { color: 'fg.muted', display: 'inline-block' }, children: "View:" }), ' ', 'All kernels'] }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { selectionVariant: "single", children: _jsx(ActionList.Item, { selected: true, children: "All kernels" }) }) })] })] }), _jsx(Text, { as: "h3", children: "Credits usage" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Amount today" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Balance yesterday" }), _jsx(Text, { as: "h3", children: "Last invoice" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle', fontSize: '3', fontWeight: 'bold' }, children: "$216" })] })] }), _jsxs(Box, { sx: {
91
- gridColumn: '1 / 3',
92
- minHeight: '200px',
93
- }, children: [_jsxs(Box, { sx: {
94
- display: 'flex',
95
- alignItems: 'center',
96
- justifyContent: 'space-between',
97
- paddingRight: 4,
98
- }, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Trending Notebooks" }), _jsxs(Link, { children: ["All Notebooks", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { sx: {
99
- borderColor: 'border.default',
100
- borderStyle: 'solid',
101
- borderWidth: '1',
102
- borderRadius: '2',
103
- display: 'grid',
104
- gridTemplateColumns: '1fr 1fr',
44
+ , {}), "11"] })] })] })] })] }), _jsxs(Box, { gridColumn: "3 / 4", gridRow: "1 / 3", minHeight: "200px", children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", paddingRight: 4, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Usage" }), _jsxs(Link, { children: ["More Usage", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", padding: 4, children: [_jsxs(Box, { display: "inline-flex", flexDirection: "row", alignItems: "center", children: [_jsx(Text, { as: "h3", sx: { marginRight: '20px' }, children: "Kernels Activity" }), _jsxs(ActionMenu, { children: [_jsxs(ActionMenu.Button, { children: [_jsx(Box, { color: "fg.muted", display: "inline-block", children: "View:" }), ' ', 'All kernels'] }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { selectionVariant: "single", children: _jsx(ActionList.Item, { selected: true, children: "All kernels" }) }) })] })] }), _jsx(Text, { as: "h3", children: "Credits usage" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Amount today" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Balance yesterday" }), _jsx(Text, { as: "h3", children: "Last invoice" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle', fontSize: '3', fontWeight: 'bold' }, children: "$216" })] })] }), _jsxs(Box, { gridColumn: "1 / 3", minHeight: "200px", children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", paddingRight: 4, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Trending Notebooks" }), _jsxs(Link, { children: ["All Notebooks", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", display: "grid", gridTemplateColumns: "1fr 1fr", sx: {
105
45
  '> :not(:last-child)': {
106
46
  borderRightColor: 'border.default',
107
47
  borderRightStyle: 'solid',
108
48
  borderRightWidth: '1',
109
49
  },
110
- }, children: [_jsxs(Box, { sx: {
111
- padding: 4,
112
- }, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { sx: { height: '300px', maxWidth: '380px' }, children: [_jsx(ReactECharts, { option: ECHART_MOCK_1 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { sx: {
113
- padding: 4,
114
- }, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { sx: { height: '300px', maxWidth: '380px' }, children: [_jsx(ReactECharts, { option: ECHART_MOCK_3 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { sx: {
115
- padding: 4,
116
- }, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { sx: { height: '300px', maxWidth: '380px' }, children: [_jsx(ReactECharts, { option: ECHART_MOCK_2 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] })] })] })] })] }));
50
+ }, children: [_jsxs(Box, { padding: 4, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { height: "300px", maxWidth: "380px", children: [_jsx(ReactECharts, { option: ECHART_MOCK_1 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { padding: 4, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { height: "300px", maxWidth: "380px", children: [_jsx(ReactECharts, { option: ECHART_MOCK_3 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { padding: 4, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { height: "300px", maxWidth: "380px", children: [_jsx(ReactECharts, { option: ECHART_MOCK_2 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] })] })] })] })] }));
117
51
  };
118
52
  export default DashboardMock;
@@ -4,7 +4,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
6
  import { useState } from 'react';
7
- import { Box, FormControl, TextInputWithTokens, Autocomplete, Select, Textarea, Heading, } from '@primer/react';
7
+ import { Box } from '@datalayer/primer-addons';
8
+ import { FormControl, TextInputWithTokens, Autocomplete, Select, Textarea, Heading, } from '@primer/react';
8
9
  export const FormMock = (props) => {
9
10
  const { title } = props;
10
11
  const [tokens, setTokens] = useState([
@@ -15,7 +16,7 @@ export const FormMock = (props) => {
15
16
  const onTokenRemove = tokenId => {
16
17
  setTokens(tokens.filter(token => token.id !== tokenId));
17
18
  };
18
- return (_jsxs(Box, { display: "grid", sx: { gap: 3 }, children: [_jsx(Heading, { children: title }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "TextInputWithTokens" }), _jsx(TextInputWithTokens, { onTokenRemove: onTokenRemove, tokens: tokens })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Autocomplete" }), _jsxs(Autocomplete, { children: [_jsx(Autocomplete.Input, { block: true }), _jsx(Autocomplete.Overlay, { children: _jsx(Autocomplete.Menu, { items: [
19
+ return (_jsxs(Box, { display: "grid", gap: 3, children: [_jsx(Heading, { children: title }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "TextInputWithTokens" }), _jsx(TextInputWithTokens, { onTokenRemove: onTokenRemove, tokens: tokens })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Autocomplete" }), _jsxs(Autocomplete, { children: [_jsx(Autocomplete.Input, { block: true }), _jsx(Autocomplete.Overlay, { children: _jsx(Autocomplete.Menu, { items: [
19
20
  { text: 'css', id: '0' },
20
21
  { text: 'css-in-js', id: '1' },
21
22
  { text: 'styled-system', id: '2' },
@@ -3,7 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  * Copyright (c) 2023-2025 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
- import { Box, LabelGroup, ActionMenu, ActionList, IconButton, Label, RelativeTime, } from '@primer/react';
6
+ import { Box } from '@datalayer/primer-addons';
7
+ import { LabelGroup, ActionMenu, ActionList, IconButton, Label, RelativeTime, } from '@primer/react';
7
8
  import { Table, DataTable } from '@primer/react/experimental';
8
9
  import { KebabHorizontalIcon, DownloadIcon } from '@primer/octicons-react';
9
10
  import { VisuallyHidden } from './../../components/display/index.js';
@@ -101,7 +102,7 @@ function uppercase(input) {
101
102
  }
102
103
  export const TableMock = (props) => {
103
104
  const { title } = props;
104
- return (_jsx(Box, { display: "grid", sx: { gap: 3 }, children: _jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h2", id: "repositories", children: title }), _jsx(Table.Subtitle, { as: "p", id: "repositories-subtitle", children: "A subtitle could appear here to give extra context to the data." }), _jsx(DataTable, { "aria-labelledby": "repositories", "aria-describedby": "repositories-subtitle", data: data, columns: [
105
+ return (_jsx(Box, { display: "grid", gap: 3, children: _jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h2", id: "repositories", children: title }), _jsx(Table.Subtitle, { as: "p", id: "repositories-subtitle", children: "A subtitle could appear here to give extra context to the data." }), _jsx(DataTable, { "aria-labelledby": "repositories", "aria-describedby": "repositories-subtitle", data: data, columns: [
105
106
  {
106
107
  header: 'Repository',
107
108
  field: 'name',
@@ -3,7 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  * Copyright (c) 2023-2025 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
- import { Box, PageHeader, Flash, PageLayout } from '@primer/react';
6
+ import { Box } from '@datalayer/primer-addons';
7
+ import { PageHeader, Flash, PageLayout } from '@primer/react';
7
8
  import { ConstructionIcon } from '@datalayer/icons-react';
8
9
  export const WipMock = (props) => {
9
10
  const { title } = props;
@@ -1,6 +1,15 @@
1
1
  import { JSONObject } from '@lumino/coreutils';
2
2
  import { IIAMProviderName } from './IAMProvidersSpecs';
3
+ /**
4
+ * One `iam_providers` child of the user IAM returns (whoami, login): its
5
+ * Solr fields `iam_provider_name_s`, `linked_account_s`,
6
+ * `linked_account_url_s`, `linked_account_id_s`.
7
+ */
3
8
  export declare function asIAMProviderLinked(iamProvider: any): IIAMProviderLinked;
9
+ /** Whether the user has linked this provider in IAM. */
10
+ export declare function hasLinkedIAMProvider(user: {
11
+ iamProviders?: Array<IIAMProviderLinked>;
12
+ } | null | undefined, name: IIAMProviderName): boolean;
4
13
  export type IIAMProviderLinked = {
5
14
  iamProviderName: IIAMProviderName;
6
15
  linkedAccount: JSONObject;
@@ -2,12 +2,41 @@
2
2
  * Copyright (c) 2023-2025 Datalayer, Inc.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
+ /**
6
+ * The account a provider returned, as IAM keeps it in `linked_account_s`.
7
+ * GitHub, Google and LinkedIn keep a JSON object; Bluesky and X keep a plain
8
+ * handle, which is no object to read, so it reads as `{}`.
9
+ */
10
+ function linkedAccountOf(raw) {
11
+ if (typeof raw !== 'string' || raw.trim() === '') {
12
+ return {};
13
+ }
14
+ try {
15
+ const parsed = JSON.parse(raw);
16
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
17
+ ? parsed
18
+ : {};
19
+ }
20
+ catch {
21
+ return {};
22
+ }
23
+ }
24
+ /**
25
+ * One `iam_providers` child of the user IAM returns (whoami, login): its
26
+ * Solr fields `iam_provider_name_s`, `linked_account_s`,
27
+ * `linked_account_url_s`, `linked_account_id_s`.
28
+ */
5
29
  export function asIAMProviderLinked(iamProvider) {
6
- const info = iamProvider.linkedAccount.replaceAll("'", '"');
7
30
  return {
8
- iamProviderName: iamProvider.iam_ProviderName,
9
- linkedAccount: JSON.parse(info === '' ? '{}' : info),
10
- linkedAccountUrl: iamProvider.linkedAccountUrl,
11
- linkedAccountId: iamProvider.linkedAccountId,
31
+ iamProviderName: String(iamProvider.iam_provider_name_s ?? '')
32
+ .trim()
33
+ .toLowerCase(),
34
+ linkedAccount: linkedAccountOf(iamProvider.linked_account_s),
35
+ linkedAccountUrl: iamProvider.linked_account_url_s ?? '',
36
+ linkedAccountId: iamProvider.linked_account_id_s ?? '',
12
37
  };
13
38
  }
39
+ /** Whether the user has linked this provider in IAM. */
40
+ export function hasLinkedIAMProvider(user, name) {
41
+ return (user?.iamProviders ?? []).some(p => p.iamProviderName === name);
42
+ }
@@ -58,7 +58,12 @@ export interface McpTask {
58
58
  pollIntervalMs?: number | null;
59
59
  /** The `CallToolResult` for small results; a resource URI otherwise. */
60
60
  result?: McpCallToolResult | string | null;
61
- error?: string | null;
61
+ /**
62
+ * Why it failed, as the server keeps it: an object — empty while nothing
63
+ * failed, else its `reason`, and where one applies the `code`, the `step`
64
+ * and what the resource was doing.
65
+ */
66
+ error?: McpTaskError | null;
62
67
  traceId?: string | null;
63
68
  workflowEngine?: McpWorkflowEngine | null;
64
69
  /** Always the task uid, so a retried start cannot create a second execution. */
@@ -92,3 +97,15 @@ export interface McpTaskEvent {
92
97
  /** The statuses from which nothing more happens. */
93
98
  export declare const MCP_TERMINAL_TASK_STATUSES: ReadonlySet<McpTaskStatus>;
94
99
  export declare const isMcpTaskTerminal: (status: McpTaskStatus) => boolean;
100
+ /** A task's failure, as the server keeps it (camel-cased like the rest). */
101
+ export type McpTaskError = {
102
+ reason?: string;
103
+ code?: string;
104
+ step?: string;
105
+ [key: string]: unknown;
106
+ };
107
+ /**
108
+ * Why a task failed, in a line: its reason, after its code where it has one;
109
+ * `null` when the server's object says nothing — an empty one is no failure.
110
+ */
111
+ export declare const taskFailureOf: (error: McpTaskError | null | undefined) => string | null;
@@ -5,3 +5,18 @@
5
5
  /** The statuses from which nothing more happens. */
6
6
  export const MCP_TERMINAL_TASK_STATUSES = new Set(['completed', 'failed', 'cancelled']);
7
7
  export const isMcpTaskTerminal = (status) => MCP_TERMINAL_TASK_STATUSES.has(status);
8
+ /**
9
+ * Why a task failed, in a line: its reason, after its code where it has one;
10
+ * `null` when the server's object says nothing — an empty one is no failure.
11
+ */
12
+ export const taskFailureOf = (error) => {
13
+ if (!error || Object.keys(error).length === 0) {
14
+ return null;
15
+ }
16
+ const reason = typeof error.reason === 'string' ? error.reason : null;
17
+ const code = typeof error.code === 'string' ? error.code : null;
18
+ if (reason) {
19
+ return code ? `${code}: ${reason}` : reason;
20
+ }
21
+ return code ?? JSON.stringify(error);
22
+ };
@@ -0,0 +1,9 @@
1
+ /** The signed-in person, as a shell needs one. */
2
+ export type Person = {
3
+ uid: string;
4
+ handle: string;
5
+ displayName: string;
6
+ avatarIcon?: string;
7
+ };
8
+ /** The person in IAM's `GET /api/iam/v1/me` answer (`me`); undefined without a uid and a handle. */
9
+ export declare function personOf(raw: unknown): Person | undefined;
@@ -0,0 +1,23 @@
1
+ /*
2
+ * Copyright (c) 2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /** The person in IAM's `GET /api/iam/v1/me` answer (`me`); undefined without a uid and a handle. */
6
+ export function personOf(raw) {
7
+ if (!raw || typeof raw !== 'object') {
8
+ return undefined;
9
+ }
10
+ const user = raw;
11
+ const handle = typeof user.handle_s === 'string' ? user.handle_s : '';
12
+ const uid = typeof user.uid === 'string' ? user.uid : '';
13
+ if (!handle || !uid) {
14
+ return undefined;
15
+ }
16
+ const names = [user.first_name_t, user.last_name_t].filter((part) => typeof part === 'string' && part.trim() !== '');
17
+ return {
18
+ uid,
19
+ handle,
20
+ displayName: names.length ? names.join(' ') : handle,
21
+ avatarIcon: typeof user.avatar_icon_s === 'string' ? user.avatar_icon_s : undefined,
22
+ };
23
+ }
@@ -34,8 +34,8 @@ export interface Profile {
34
34
  avatar_url_s?: string;
35
35
  avatar_icon_s?: string;
36
36
  banner_s?: string;
37
- /** Onboarding state as JSON string */
38
- onboarding_s?: string;
37
+ /** Onboarding state: the child IAM keeps on the user (read by `userOnboardingOf`). */
38
+ onboarding?: Record<string, unknown>;
39
39
  /** New password request timestamp */
40
40
  new_password_request_ts_dt?: string | null;
41
41
  /** New password confirmation timestamp */
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { asDisplayName, namesAsInitials, toFriendlyName } from '../utils/index.js';
6
6
  import { asIAMProviderLinked } from './IAMProviderLinked.js';
7
- import { BOOTSTRAP_USER_ONBOARDING } from './UserOnboarding.js';
7
+ import { userOnboardingOf } from './UserOnboarding.js';
8
8
  import { UserSettings } from './UserSettings.js';
9
9
  import { asUserEvent } from './UserEvent.js';
10
10
  export const ANONYMOUS_USER = undefined;
@@ -76,20 +76,13 @@ export class User {
76
76
  this.credits = u.credits_i ? Number(u.credits_i) : 0;
77
77
  this.creditsCustomerId = u.stripe_customer_id_s;
78
78
  this.roles = u.roles_ss ?? [];
79
- let iamProviders = [];
80
- try {
81
- iamProviders = (u.iam_providers ?? []).map(iamProvider => asIAMProviderLinked(iamProvider));
82
- }
83
- catch (e) {
84
- // no-op for backwards compatibility.
85
- }
86
- this.iamProviders = iamProviders;
79
+ // IAM sends one linked provider as an object, several as a list.
80
+ const rawIAMProviders = u.iam_providers ?? [];
81
+ this.iamProviders = (Array.isArray(rawIAMProviders) ? rawIAMProviders : [rawIAMProviders]).map(asIAMProviderLinked);
87
82
  this.settings = new UserSettings(u.settings ?? {});
88
83
  this.unsubscribedFromOutbounds = u.unsubscribed_from_outbounds_b ?? false;
89
84
  this.mfaUrl = u.mfa_url_s;
90
- this.onboarding = u.onboarding_s
91
- ? JSON.parse(u.onboarding_s)
92
- : BOOTSTRAP_USER_ONBOARDING;
85
+ this.onboarding = userOnboardingOf(u.onboarding);
93
86
  this.linkedContactId = u.linked_contact_uid;
94
87
  this.subscription = u.subscription;
95
88
  let events = u.events ?? [];
@@ -12,3 +12,12 @@ export type IUserOnboarding = {
12
12
  position: IOnboardingPosition;
13
13
  tours: IOnboardingTours;
14
14
  };
15
+ /**
16
+ * The user's onboarding, as IAM keeps it: a child of the user whose fields
17
+ * say the guide's position (`position_s`), each client's progress
18
+ * (`client_<client>_i`) and each tour's status (`tour_<tour>_status_s`), over
19
+ * what nothing has said yet. Read from the old `onboarding_s` string, a
20
+ * status saved since was never seen: the welcome tour started again on every
21
+ * load and was saved again (13 October 2026).
22
+ */
23
+ export declare const userOnboardingOf: (child: unknown) => IUserOnboarding;
@@ -17,3 +17,36 @@ export const BOOTSTRAP_USER_ONBOARDING = {
17
17
  },
18
18
  },
19
19
  };
20
+ /**
21
+ * The user's onboarding, as IAM keeps it: a child of the user whose fields
22
+ * say the guide's position (`position_s`), each client's progress
23
+ * (`client_<client>_i`) and each tour's status (`tour_<tour>_status_s`), over
24
+ * what nothing has said yet. Read from the old `onboarding_s` string, a
25
+ * status saved since was never seen: the welcome tour started again on every
26
+ * load and was saved again (13 October 2026).
27
+ */
28
+ export const userOnboardingOf = (child) => {
29
+ const stored = (Array.isArray(child) ? child[0] : child);
30
+ const onboarding = {
31
+ clients: { ...BOOTSTRAP_USER_ONBOARDING.clients },
32
+ position: BOOTSTRAP_USER_ONBOARDING.position,
33
+ tours: { ...BOOTSTRAP_USER_ONBOARDING.tours },
34
+ };
35
+ if (!stored || typeof stored !== 'object') {
36
+ return onboarding;
37
+ }
38
+ if (typeof stored.position_s === 'string') {
39
+ onboarding.position = stored.position_s;
40
+ }
41
+ for (const [key, value] of Object.entries(stored)) {
42
+ const client = /^client_(.+)_i$/.exec(key)?.[1];
43
+ if (client && typeof value === 'number') {
44
+ onboarding.clients[client] = value;
45
+ }
46
+ const tour = /^tour_(.+)_status_s$/.exec(key)?.[1];
47
+ if (tour && typeof value === 'string') {
48
+ onboarding.tours[tour] = { status: value };
49
+ }
50
+ }
51
+ return onboarding;
52
+ };
@@ -13,7 +13,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
13
13
  * @module otel/OtelLive
14
14
  */
15
15
  import { useState, useCallback, useMemo, useEffect, useRef, } from 'react';
16
- import { Box, Text, Button, Label } from '@primer/react';
16
+ import { Box } from '@datalayer/primer-addons';
17
+ import { Text, Button, Label } from '@primer/react';
17
18
  import { GitBranchIcon, ClockIcon } from '@primer/octicons-react';
18
19
  import { getOtelConsumeUrl } from '../../state/substates/CoreState.js';
19
20
  import { useOtelTraces, useOtelTrace, useOtelLogs, useOtelMetrics, useOtelServices, useOtelWebSocket, } from '../hooks/index.js';
@@ -287,70 +288,11 @@ export const OtelLive = ({ baseUrl = getOtelConsumeUrl(), wsBaseUrl, token, auto
287
288
  return ts >= s && ts <= e;
288
289
  });
289
290
  }, [metrics, isRangeActive, rangeStart, rangeEnd]);
290
- return (_jsxs(Box, { sx: {
291
- display: 'flex',
292
- flexDirection: 'column',
293
- flex: 1,
294
- minHeight: 0,
295
- height: '100%',
296
- color: 'fg.default',
297
- bg: 'canvas.default',
298
- border: '1px solid',
299
- borderColor: 'border.default',
300
- borderRadius: 2,
301
- overflow: 'hidden',
302
- }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 0 }, children: [_jsx(Box, { sx: { flex: 1 }, children: _jsx(OtelSearchBar, { signal: signal, onSignalChange: setSignal, services: effectiveServices, selectedService: service, onServiceChange: setService, query: query, onQueryChange: setQuery, onRefresh: handleRefresh, loading: signal === 'traces'
291
+ return (_jsxs(Box, { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, height: "100%", color: "fg.default", bg: "canvas.default", border: "1px solid", borderColor: "border.default", borderRadius: 2, overflow: "hidden", children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 0, children: [_jsx(Box, { flex: 1, children: _jsx(OtelSearchBar, { signal: signal, onSignalChange: setSignal, services: effectiveServices, selectedService: service, onServiceChange: setService, query: query, onQueryChange: setQuery, onRefresh: handleRefresh, loading: signal === 'traces'
303
292
  ? tracesLoading
304
293
  : signal === 'logs'
305
294
  ? logsLoading
306
- : metricsLoading }) }), _jsx(Box, { sx: { pr: 2, flexShrink: 0 }, children: _jsx(Label, { variant: wsConnected ? 'success' : 'secondary', size: "small", children: wsConnected ? '● Live' : '○ Polling' }) })] }), timelineBounds && rangeStart && rangeEnd && (_jsx(Box, { sx: {
307
- px: 3,
308
- pt: 2,
309
- pb: 1,
310
- borderBottom: '1px solid',
311
- borderColor: 'border.default',
312
- bg: 'canvas.subtle',
313
- flexShrink: 0,
314
- position: 'relative',
315
- zIndex: 0,
316
- }, children: _jsx(OtelTimelineRangeSlider, { timelineStart: timelineBounds.start, timelineEnd: timelineBounds.end, selectedStart: rangeStart, selectedEnd: rangeEnd, onRangeChange: handleRangeChange, histogram: histogram, height: 48, tickCount: 6 }) })), _jsxs(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: [_jsxs(Box, { sx: {
317
- display: 'flex',
318
- flexDirection: 'column',
319
- flex: hasDetail ? '0 0 55%' : '1 1 100%',
320
- minHeight: 0,
321
- overflow: 'hidden',
322
- }, children: [signal === 'traces' && (_jsx(OtelTracesList, { spans: filteredTraces, loading: tracesLoading, selectedSpanId: selectedSpan?.span_id, onSelectSpan: handleSpanSelect })), signal === 'logs' && (_jsx(OtelLogsList, { logs: filteredLogs, loading: logsLoading, selectedLogIndex: selectedLogIdx, onSelectLog: handleLogSelect })), signal === 'metrics' && (_jsx(OtelMetricsList, { metrics: filteredMetrics, loading: metricsLoading }))] }), hasDetail && (_jsxs(Box, { sx: {
323
- flex: '0 0 45%',
324
- minHeight: 0,
325
- overflow: 'auto',
326
- borderLeft: '1px solid',
327
- borderColor: 'border.default',
328
- }, children: [signal === 'traces' && selectedSpan && (_jsx(OtelSpanDetail, { span: selectedSpan, traceSpans: traceSpans ?? undefined, onClose: handleCloseDetail })), signal === 'logs' && selectedLogIdx !== null && logs && (_jsxs(Box, { sx: { p: 3 }, children: [_jsxs(Box, { sx: {
329
- display: 'flex',
330
- justifyContent: 'space-between',
331
- mb: 3,
332
- }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 2 }, children: "Log Detail" }), _jsx(Button, { size: "small", variant: "invisible", onClick: handleCloseDetail, children: "\u2715" })] }), _jsx(Box, { as: "pre", sx: {
333
- m: 0,
334
- fontSize: 1,
335
- fontFamily: 'mono',
336
- whiteSpace: 'pre-wrap',
337
- wordBreak: 'break-word',
338
- }, children: JSON.stringify(logs[selectedLogIdx], null, 2) })] }))] }))] }), signal === 'traces' && selectedSpan && spanTree.length > 0 && (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
339
- display: 'flex',
340
- gap: 1,
341
- px: 3,
342
- py: 1,
343
- bg: 'canvas.subtle',
344
- borderTop: '1px solid',
345
- borderColor: 'border.default',
346
- flexShrink: 0,
347
- }, children: [_jsx(Button, { size: "small", variant: bottomPane === 'timeline' ? 'primary' : 'invisible', leadingVisual: ClockIcon, onClick: () => toggleBottomPane('timeline'), children: "Timeline" }), _jsx(Button, { size: "small", variant: bottomPane === 'tree' ? 'primary' : 'invisible', leadingVisual: GitBranchIcon, onClick: () => toggleBottomPane('tree'), children: "Span Tree" })] }), bottomPane && (_jsxs(Box, { sx: {
348
- height: 260,
349
- overflow: 'auto',
350
- borderTop: '1px solid',
351
- borderColor: 'border.default',
352
- flexShrink: 0,
353
- }, children: [bottomPane === 'timeline' && (_jsx(OtelTimeline, { spans: traceSpans ?? [], selectedSpanId: selectedSpan?.span_id, onSelectSpan: handleSpanSelect })), bottomPane === 'tree' && (_jsx(OtelSpanTree, { spans: spanTree, selectedSpanId: selectedSpan?.span_id, onSelectSpan: handleSpanSelect, defaultExpandDepth: 3 }))] }))] }))] }));
295
+ : metricsLoading }) }), _jsx(Box, { pr: 2, flexShrink: 0, children: _jsx(Label, { variant: wsConnected ? 'success' : 'secondary', size: "small", children: wsConnected ? '● Live' : '○ Polling' }) })] }), timelineBounds && rangeStart && rangeEnd && (_jsx(Box, { px: 3, pt: 2, pb: 1, borderBottom: "1px solid", borderColor: "border.default", bg: "canvas.subtle", flexShrink: 0, position: "relative", zIndex: 0, children: _jsx(OtelTimelineRangeSlider, { timelineStart: timelineBounds.start, timelineEnd: timelineBounds.end, selectedStart: rangeStart, selectedEnd: rangeEnd, onRangeChange: handleRangeChange, histogram: histogram, height: 48, tickCount: 6 }) })), _jsxs(Box, { display: "flex", flex: 1, minHeight: 0, overflow: "hidden", children: [_jsxs(Box, { display: "flex", flexDirection: "column", flex: hasDetail ? '0 0 55%' : '1 1 100%', minHeight: 0, overflow: "hidden", children: [signal === 'traces' && (_jsx(OtelTracesList, { spans: filteredTraces, loading: tracesLoading, selectedSpanId: selectedSpan?.span_id, onSelectSpan: handleSpanSelect })), signal === 'logs' && (_jsx(OtelLogsList, { logs: filteredLogs, loading: logsLoading, selectedLogIndex: selectedLogIdx, onSelectLog: handleLogSelect })), signal === 'metrics' && (_jsx(OtelMetricsList, { metrics: filteredMetrics, loading: metricsLoading }))] }), hasDetail && (_jsxs(Box, { flex: "0 0 45%", minHeight: 0, overflow: "auto", borderLeft: "1px solid", borderColor: "border.default", children: [signal === 'traces' && selectedSpan && (_jsx(OtelSpanDetail, { span: selectedSpan, traceSpans: traceSpans ?? undefined, onClose: handleCloseDetail })), signal === 'logs' && selectedLogIdx !== null && logs && (_jsxs(Box, { p: 3, children: [_jsxs(Box, { display: "flex", justifyContent: "space-between", mb: 3, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 2 }, children: "Log Detail" }), _jsx(Button, { size: "small", variant: "invisible", onClick: handleCloseDetail, children: "\u2715" })] }), _jsx(Box, { as: "pre", m: 0, fontSize: 1, fontFamily: "mono", whiteSpace: "pre-wrap", wordBreak: "break-word", children: JSON.stringify(logs[selectedLogIdx], null, 2) })] }))] }))] }), signal === 'traces' && selectedSpan && spanTree.length > 0 && (_jsxs(_Fragment, { children: [_jsxs(Box, { display: "flex", gap: 1, px: 3, py: 1, bg: "canvas.subtle", borderTop: "1px solid", borderColor: "border.default", flexShrink: 0, children: [_jsx(Button, { size: "small", variant: bottomPane === 'timeline' ? 'primary' : 'invisible', leadingVisual: ClockIcon, onClick: () => toggleBottomPane('timeline'), children: "Timeline" }), _jsx(Button, { size: "small", variant: bottomPane === 'tree' ? 'primary' : 'invisible', leadingVisual: GitBranchIcon, onClick: () => toggleBottomPane('tree'), children: "Span Tree" })] }), bottomPane && (_jsxs(Box, { height: 260, overflow: "auto", borderTop: "1px solid", borderColor: "border.default", flexShrink: 0, children: [bottomPane === 'timeline' && (_jsx(OtelTimeline, { spans: traceSpans ?? [], selectedSpanId: selectedSpan?.span_id, onSelectSpan: handleSpanSelect })), bottomPane === 'tree' && (_jsx(OtelSpanTree, { spans: spanTree, selectedSpanId: selectedSpan?.span_id, onSelectSpan: handleSpanSelect, defaultExpandDepth: 3 }))] }))] }))] }));
354
296
  };
355
297
  // ── Client-side filter helpers ──────────────────────────────────────
356
298
  function filterSpans(spans, q) {
@@ -16,7 +16,8 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
16
16
  * @module otel/views/OtelLiveSpans
17
17
  */
18
18
  import { useMemo, useState } from 'react';
19
- import { ActionList, ActionMenu, Box, Button, Text } from '@primer/react';
19
+ import { Box } from '@datalayer/primer-addons';
20
+ import { ActionList, ActionMenu, Button, Text } from '@primer/react';
20
21
  import { DownloadIcon, PauseIcon, PlayIcon, TrashIcon, } from '@primer/octicons-react';
21
22
  import { toMs } from '../utils.js';
22
23
  import { spansOfService } from '../live/filter.js';
@@ -93,22 +94,7 @@ export const OtelLiveSpans = ({ tracer, spans: given, service, facets = DEFAULT_
93
94
  ? everything.filter(span => span.trace_id === selectedSpan.trace_id)
94
95
  : [], [everything, selectedSpan]);
95
96
  const side = detailPlacement === 'side' && !compact;
96
- return (_jsxs(Box, { "data-otel-live-spans": "", sx: {
97
- border: '1px solid',
98
- borderColor: 'border.default',
99
- borderRadius: 2,
100
- bg: 'canvas.default',
101
- color: 'fg.default',
102
- minWidth: 0,
103
- }, children: [_jsxs(Box, { role: "toolbar", "aria-label": label, sx: {
104
- display: 'flex',
105
- flexWrap: 'wrap',
106
- gap: 2,
107
- alignItems: 'center',
108
- p: 2,
109
- borderBottom: '1px solid',
110
- borderColor: 'border.default',
111
- }, children: [facets.map((facet, index) => (_jsx(FacetMenu, { facet: facet, options: options[index] ?? [], selected: selected[index] ?? new Set(), onChange: next => setSelected(prev => facets.map((_, at) => at === index ? next : (prev[at] ?? new Set()))) }, facet.label))), _jsx(Box, { sx: { flex: 1 } }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-otel-span-count": "", children: [rows.length === shown.length
97
+ return (_jsxs(Box, { "data-otel-live-spans": "", border: "1px solid", borderColor: "border.default", borderRadius: 2, bg: "canvas.default", color: "fg.default", minWidth: 0, children: [_jsxs(Box, { role: "toolbar", "aria-label": label, display: "flex", flexWrap: "wrap", gap: 2, alignItems: "center", p: 2, borderBottom: "1px solid", borderColor: "border.default", children: [facets.map((facet, index) => (_jsx(FacetMenu, { facet: facet, options: options[index] ?? [], selected: selected[index] ?? new Set(), onChange: next => setSelected(prev => facets.map((_, at) => at === index ? next : (prev[at] ?? new Set()))) }, facet.label))), _jsx(Box, { flex: 1 }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-otel-span-count": "", children: [rows.length === shown.length
112
98
  ? `${rows.length} ${rows.length === 1 ? 'span' : 'spans'}`
113
99
  : `${rows.length} of ${shown.length}`, waiting > 0 ? ` · ${waiting} new` : ''] }), _jsx(Button, { size: "small", leadingVisual: held ? PlayIcon : PauseIcon, "aria-pressed": held !== null, onClick: () => setHeld(held ? null : recorded), "data-otel-pause": "", children: held ? 'Resume' : 'Pause' }), _jsx(Button, { size: "small", leadingVisual: TrashIcon, onClick: () => {
114
100
  setHeld(null);
@@ -123,17 +109,6 @@ export const OtelLiveSpans = ({ tracer, spans: given, service, facets = DEFAULT_
123
109
  }, "data-otel-clear": "", children: "Clear" }), _jsx(Button, { size: "small", leadingVisual: DownloadIcon, disabled: !recorded.length, onClick: () => download(exportName, {
124
110
  exportedAt: new Date().toISOString(),
125
111
  spans: [...recorded],
126
- }), "data-otel-export": "", children: "Export" })] }), _jsxs(Box, { sx: {
127
- display: side ? 'grid' : 'block',
128
- gridTemplateColumns: side
129
- ? 'minmax(0, 3fr) minmax(0, 2fr)'
130
- : undefined,
131
- }, children: [_jsx(Box, { sx: { maxHeight, overflowY: 'auto', minWidth: 0 }, children: _jsx(OtelTracesList, { spans: rows, selectedSpanId: selectedSpanId, onSelectSpan: span => setSelectedSpanId(span.span_id), emptyText: emptyText, compact: compact, defaultExpanded: true, renderSpanMark: renderSpanMark, describeSpan: describeSpan }) }), selectedSpan && (_jsx(Box, { "data-otel-live-detail": "", sx: {
132
- maxHeight,
133
- overflowY: 'auto',
134
- minWidth: 0,
135
- borderTop: side ? 'none' : '1px solid',
136
- borderColor: 'border.default',
137
- }, children: _jsx(OtelSpanDetail, { span: selectedSpan, traceSpans: traceSpans, onClose: () => setSelectedSpanId(null) }) }))] })] }));
112
+ }), "data-otel-export": "", children: "Export" })] }), _jsxs(Box, { display: side ? 'grid' : 'block', gridTemplateColumns: side ? 'minmax(0, 3fr) minmax(0, 2fr)' : undefined, children: [_jsx(Box, { maxHeight: maxHeight, overflowY: "auto", minWidth: 0, children: _jsx(OtelTracesList, { spans: rows, selectedSpanId: selectedSpanId, onSelectSpan: span => setSelectedSpanId(span.span_id), emptyText: emptyText, compact: compact, defaultExpanded: true, renderSpanMark: renderSpanMark, describeSpan: describeSpan }) }), selectedSpan && (_jsx(Box, { "data-otel-live-detail": "", maxHeight: maxHeight, overflowY: "auto", minWidth: 0, borderTop: side ? 'none' : '1px solid', borderColor: "border.default", children: _jsx(OtelSpanDetail, { span: selectedSpan, traceSpans: traceSpans, onClose: () => setSelectedSpanId(null) }) }))] })] }));
138
113
  };
139
114
  export default OtelLiveSpans;