@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
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { ActionMenu, Box, Button, Label, Text, ThemeProvider, } from '@primer/react';
2
+ import { Box } from '@datalayer/primer-addons';
3
+ import { ActionMenu, Button, Label, Text, ThemeProvider } from '@primer/react';
3
4
  import { SpaceIcon } from '@primer/octicons-react';
4
5
  import { useNavigate } from '../../hooks/index.js';
5
6
  import { buildSpaceDetailsPath } from './spaceDisplayModel.js';
@@ -31,22 +32,7 @@ export function SpaceDetailsCard({ uid, displayName, handle, accountHandle, desc
31
32
  const address = normalizedAccount && normalizedHandle
32
33
  ? `@${normalizedAccount}/${normalizedHandle}`
33
34
  : normalizedHandle;
34
- return (_jsxs(Box, { sx: { display: 'grid', gap: 3, p: 4, minWidth: 360 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Box, { "aria-hidden": "true", sx: {
35
- display: 'inline-flex',
36
- alignItems: 'center',
37
- justifyContent: 'center',
38
- width: 40,
39
- height: 40,
40
- flexShrink: 0,
41
- borderRadius: 2,
42
- bg: 'accent.subtle',
43
- color: 'accent.fg',
44
- }, children: _jsx(SpaceIcon, { size: 20 }) }), _jsxs(Box, { sx: { display: 'grid', gap: 0.5, minWidth: 0 }, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: normalizedDisplayName }), address ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: address })) : null] })] }), _jsxs(Box, { sx: {
45
- display: 'grid',
46
- gridTemplateColumns: '110px 1fr',
47
- gap: 1,
48
- alignItems: 'baseline',
49
- }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Kind" }), _jsx(Text, { sx: { fontSize: 1 }, children: "space" }), normalizedHandle ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedHandle })] })) : null, normalizedAccount ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Account" }), _jsxs(Text, { sx: { fontSize: 1 }, children: ["@", normalizedAccount] })] })) : null, normalize(variant) ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Variant" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(variant) })] })) : null, typeof isPublic === 'boolean' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Visibility" }), _jsx(Label, { size: "small", variant: isPublic ? 'success' : 'secondary', sx: { justifySelf: 'start', width: 'fit-content' }, children: isPublic ? 'Public' : 'Private' })] })) : null, _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Description" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(description) || 'N/A' }), normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null] }), _jsx(Box, { sx: { display: 'flex', justifyContent: 'flex-end', gap: 2 }, children: _jsx(Button, { size: "small", onClick: go, disabled: !targetPath, children: "View Space" }) })] }));
35
+ return (_jsxs(Box, { display: "grid", gap: 3, p: 4, minWidth: 360, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(Box, { "aria-hidden": "true", display: "inline-flex", alignItems: "center", justifyContent: "center", width: 40, height: 40, flexShrink: 0, borderRadius: 2, bg: "accent.subtle", color: "accent.fg", children: _jsx(SpaceIcon, { size: 20 }) }), _jsxs(Box, { display: "grid", gap: 0.5, minWidth: 0, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: normalizedDisplayName }), address ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: address })) : null] })] }), _jsxs(Box, { display: "grid", gridTemplateColumns: "110px 1fr", gap: 1, alignItems: "baseline", children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Kind" }), _jsx(Text, { sx: { fontSize: 1 }, children: "space" }), normalizedHandle ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedHandle })] })) : null, normalizedAccount ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Account" }), _jsxs(Text, { sx: { fontSize: 1 }, children: ["@", normalizedAccount] })] })) : null, normalize(variant) ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Variant" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(variant) })] })) : null, typeof isPublic === 'boolean' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Visibility" }), _jsx(Label, { size: "small", variant: isPublic ? 'success' : 'secondary', sx: { justifySelf: 'start', width: 'fit-content' }, children: isPublic ? 'Public' : 'Private' })] })) : null, _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Description" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalize(description) || 'N/A' }), normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null] }), _jsx(Box, { display: "flex", justifyContent: "flex-end", gap: 2, children: _jsx(Button, { size: "small", onClick: go, disabled: !targetPath, children: "View Space" }) })] }));
50
36
  }
51
37
  /**
52
38
  * A space's details, shown from a click on its name.
@@ -58,23 +44,6 @@ export function SpaceDetailsOverlay(props) {
58
44
  normalize(props.handle) ||
59
45
  normalize(props.uid) ||
60
46
  'Space';
61
- return (_jsx(ThemeProvider, { children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button", title: normalizedDisplayName, sx: {
62
- fontWeight: 'semibold',
63
- color: 'accent.fg',
64
- textDecoration: 'underline',
65
- background: 'transparent',
66
- border: 0,
67
- padding: 0,
68
- margin: 0,
69
- cursor: 'pointer',
70
- maxWidth: '100%',
71
- overflow: 'hidden',
72
- textOverflow: 'ellipsis',
73
- whiteSpace: 'nowrap',
74
- textAlign: 'left',
75
- ':hover': {
76
- textDecoration: 'underline',
77
- },
78
- }, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(SpaceDetailsCard, { ...props }) })] }) }));
47
+ return (_jsx(ThemeProvider, { children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button", title: normalizedDisplayName, fontWeight: "semibold", color: "accent.fg", textDecoration: "underline", background: "transparent", border: 0, padding: 0, margin: 0, cursor: "pointer", maxWidth: "100%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", textAlign: "left", hover: { textDecoration: 'underline' }, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(SpaceDetailsCard, { ...props }) })] }) }));
79
48
  }
80
49
  export default SpaceDetailsOverlay;
@@ -80,13 +80,6 @@ export const SpaceDisplay = ({ space, showIcon = true, iconSize = 16, gap = 1, p
80
80
  Boolean(givenRootId || String(itemUid || '').trim());
81
81
  return (_jsx(Text, { sx: { color: 'fg.muted', ...sx }, children: waiting ? '…' : emptyText }));
82
82
  }
83
- return (_jsxs(Box, { sx: {
84
- display: 'inline-flex',
85
- alignItems: 'center',
86
- gap,
87
- minWidth: 0,
88
- maxWidth: '100%',
89
- ...sx,
90
- }, children: [showIcon ? (_jsx(Box, { as: "span", "aria-hidden": "true", sx: { display: 'inline-flex', color: 'fg.muted', flexShrink: 0 }, children: _jsx(SpaceIcon, { size: iconSize }) })) : null, _jsx(SpaceDetailsOverlay, { uid: resolved.uid, displayName: resolved.displayName, handle: resolved.handle, accountHandle: resolved.accountHandle, description: resolved.description, variant: resolved.variant, isPublic: resolved.isPublic, onNavigate: onNavigate })] }));
83
+ return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: gap, minWidth: 0, maxWidth: "100%", sx: sx, children: [showIcon ? (_jsx(Box, { as: "span", "aria-hidden": "true", display: "inline-flex", color: "fg.muted", flexShrink: 0, children: _jsx(SpaceIcon, { size: iconSize }) })) : null, _jsx(SpaceDetailsOverlay, { uid: resolved.uid, displayName: resolved.displayName, handle: resolved.handle, accountHandle: resolved.accountHandle, description: resolved.description, variant: resolved.variant, isPublic: resolved.isPublic, onNavigate: onNavigate })] }));
91
84
  };
92
85
  export default SpaceDisplay;
@@ -41,7 +41,7 @@ export function ContentsBrowser(props) {
41
41
  // caller that has not resolved its sandbox yet must not appear to have.
42
42
  const contents = props.contents ?? (mock ? CONTENTS_BROWSER_MOCK_MANAGER : undefined);
43
43
  if (!contents) {
44
- return (_jsxs(Box, { sx: { p: 3 }, children: [title, _jsx(Text, { sx: { display: 'block', color: 'fg.muted', fontSize: 1, mt: 2 }, children: "No filesystem is connected." })] }));
44
+ return (_jsxs(Box, { p: 3, children: [title, _jsx(Text, { sx: { display: 'block', color: 'fg.muted', fontSize: 1, mt: 2 }, children: "No filesystem is connected." })] }));
45
45
  }
46
46
  return (_jsx(ConnectedContentsBrowser, { ...props, contents: contents, mock: mock, title: title }));
47
47
  }
@@ -292,32 +292,9 @@ const ConnectedContentsBrowser = (props) => {
292
292
  const onSelect = useCallback((item, refresh) => {
293
293
  setSelectedItem(item.path === selectedItem?.path ? null : { ...item, refresh });
294
294
  }, [selectedItem]);
295
- return (_jsxs(Box, { sx: {
296
- display: 'grid',
297
- gridTemplateAreas: `"header" "content"`,
298
- overflow: 'hidden',
299
- }, children: [_jsxs(Box, { sx: {
300
- gridArea: 'header',
301
- display: 'flex',
302
- alignItems: 'center',
303
- minWidth: 0,
304
- overflow: 'hidden',
305
- }, children: [_jsx(Box, { sx: { flex: '1 1 auto', minWidth: 0, overflow: 'hidden' }, children: title }), _jsxs(Box, { sx: {
306
- display: 'flex',
307
- flexDirection: 'row',
308
- alignItems: 'center',
309
- flexWrap: 'nowrap',
310
- flexShrink: 0,
311
- }, children: [_jsx(SegmentedControl, { "aria-label": "Contents view", size: "small", onChange: index => {
295
+ return (_jsxs(Box, { display: "grid", gridTemplateAreas: '"header" "content"', overflow: "hidden", children: [_jsxs(Box, { gridArea: "header", display: "flex", alignItems: "center", minWidth: 0, overflow: "hidden", children: [_jsx(Box, { flex: "1 1 auto", minWidth: 0, overflow: "hidden", children: title }), _jsxs(Box, { display: "flex", flexDirection: "row", alignItems: "center", flexWrap: "nowrap", flexShrink: 0, children: [_jsx(SegmentedControl, { "aria-label": "Contents view", size: "small", onChange: index => {
312
296
  changeView(CONTENTS_BROWSER_VIEWS[index].value);
313
- }, children: CONTENTS_BROWSER_VIEWS.map(candidate => (_jsx(SegmentedControl.IconButton, { icon: candidate.icon, "aria-label": candidate.label, selected: candidate.value === view }, candidate.value))) }), _jsx(IconButton, { variant: "invisible", "aria-label": 'Refresh contents browser.', title: 'Refresh contents browser.', icon: SyncIcon, onClick: refreshView, disabled: mock }), !mock && (_jsx(UploadIconButton, { label: 'Upload a file', multiple: true, upload: upload }))] })] }), isLoading ? (_jsx(Box, { sx: {
314
- gridArea: 'content',
315
- display: 'flex',
316
- alignItems: 'center',
317
- justifyContent: 'center',
318
- minHeight: '40px',
319
- height: '100vh',
320
- }, children: _jsx(Spinner, {}) })) : (_jsxs(Box, { sx: { gridArea: 'content' }, children: [view === 'table' ? (folderItems === null && !isFolderLoading ? (_jsx(Blankslate, { children: _jsx(Blankslate.Heading, { children: "No contents" }) })) : (_jsx(ContentsTable, { path: folderPath, items: folderItems ?? [], current: selectedItem, loading: isFolderLoading, onNavigate: navigateTo, onSelect: item => {
297
+ }, children: CONTENTS_BROWSER_VIEWS.map(candidate => (_jsx(SegmentedControl.IconButton, { icon: candidate.icon, "aria-label": candidate.label, selected: candidate.value === view }, candidate.value))) }), _jsx(IconButton, { variant: "invisible", "aria-label": 'Refresh contents browser.', title: 'Refresh contents browser.', icon: SyncIcon, onClick: refreshView, disabled: mock }), !mock && (_jsx(UploadIconButton, { label: 'Upload a file', multiple: true, upload: upload }))] })] }), isLoading ? (_jsx(Box, { gridArea: "content", display: "flex", alignItems: "center", justifyContent: "center", minHeight: "40px", height: "100vh", children: _jsx(Spinner, {}) })) : (_jsxs(Box, { gridArea: "content", children: [view === 'table' ? (folderItems === null && !isFolderLoading ? (_jsx(Blankslate, { children: _jsx(Blankslate.Heading, { children: "No contents" }) })) : (_jsx(ContentsTable, { path: folderPath, items: folderItems ?? [], current: selectedItem, loading: isFolderLoading, onNavigate: navigateTo, onSelect: item => {
321
298
  onSelect(item, refreshFolder);
322
299
  }, onContextMenu: onContextMenu }))) : children ? (_jsx(TreeView, { children: children?.map(child => {
323
300
  return child.type === 'directory' ? (_jsx(DirectoryItem, { item: child, contents: contents, current: selectedItem, documentRegistry: documentRegistry, onContextMenu: onContextMenu, onSelect: onSelect }, child.name)) : (_jsx(TreeItem, { item: child, current: selectedItem?.path === child.path, onSelect: item => {
@@ -63,7 +63,7 @@ function ParentRow(props) {
63
63
  event.preventDefault();
64
64
  goUp();
65
65
  }
66
- }, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(FileDirectoryIcon, {}), _jsx("span", { children: ".." })] }) }), _jsx(Table.Cell, {}), _jsx(Table.Cell, {})] }));
66
+ }, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(FileDirectoryIcon, {}), _jsx("span", { children: ".." })] }) }), _jsx(Table.Cell, {}), _jsx(Table.Cell, {})] }));
67
67
  }
68
68
  /**
69
69
  * A folder or file row.
@@ -92,7 +92,7 @@ function ContentsRow(props) {
92
92
  onSelect(item);
93
93
  }
94
94
  onContextMenu(ref);
95
- }, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { ref: ref, sx: { display: 'flex', alignItems: 'center', gap: 2, minWidth: 0 }, children: [isDirectory ? (_jsx(FileDirectoryFillIcon, {})) : icon ? (_jsx(icon.react, { tag: 'span' })) : (_jsx(FileIcon, {})), _jsx("span", { style: {
95
+ }, children: [_jsx(Table.Cell, { scope: "row", children: _jsxs(Box, { ref: ref, display: "flex", alignItems: "center", gap: 2, minWidth: 0, children: [isDirectory ? (_jsx(FileDirectoryFillIcon, {})) : icon ? (_jsx(icon.react, { tag: 'span' })) : (_jsx(FileIcon, {})), _jsx("span", { style: {
96
96
  overflow: 'hidden',
97
97
  textOverflow: 'ellipsis',
98
98
  whiteSpace: 'nowrap',
@@ -108,27 +108,8 @@ export function ContentsTable(props) {
108
108
  const { path, items, current, loading = false, onNavigate, onSelect, onContextMenu, } = props;
109
109
  const segments = pathSegments(path);
110
110
  const label = path ? `Contents of ${path}` : 'Contents of the root folder';
111
- return (_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(Box, { sx: {
112
- display: 'flex',
113
- alignItems: 'center',
114
- gap: 2,
115
- minWidth: 0,
116
- overflow: 'hidden',
117
- }, children: _jsxs(Box, { role: "navigation", "aria-label": "Folder path", sx: {
118
- display: 'flex',
119
- alignItems: 'center',
120
- flexWrap: 'wrap',
121
- gap: 1,
122
- minWidth: 0,
123
- fontSize: 1,
124
- }, children: [_jsx(PathSegment, { name: "/", path: "", current: segments.length === 0, title: "Go to the root folder.", onNavigate: onNavigate }), segments.map((segment, index) => (_jsxs(Fragment, { children: [index > 0 && _jsx(Text, { sx: { color: 'fg.muted' }, children: "/" }), _jsx(PathSegment, { name: segment.name, path: segment.path, current: index === segments.length - 1, title: index === segments.length - 1
111
+ return (_jsxs(Box, { display: "flex", flexDirection: "column", gap: 2, children: [_jsx(Box, { display: "flex", alignItems: "center", gap: 2, minWidth: 0, overflow: "hidden", children: _jsxs(Box, { role: "navigation", "aria-label": "Folder path", display: "flex", alignItems: "center", flexWrap: "wrap", gap: 1, minWidth: 0, fontSize: 1, children: [_jsx(PathSegment, { name: "/", path: "", current: segments.length === 0, title: "Go to the root folder.", onNavigate: onNavigate }), segments.map((segment, index) => (_jsxs(Fragment, { children: [index > 0 && _jsx(Text, { sx: { color: 'fg.muted' }, children: "/" }), _jsx(PathSegment, { name: segment.name, path: segment.path, current: index === segments.length - 1, title: index === segments.length - 1
125
112
  ? `Reload ${segment.path}`
126
- : `Go to ${segment.path}`, onNavigate: onNavigate })] }, segment.path)))] }) }), loading ? (_jsx(Box, { sx: {
127
- display: 'flex',
128
- alignItems: 'center',
129
- justifyContent: 'center',
130
- minHeight: '40px',
131
- padding: 3,
132
- }, children: _jsx(Spinner, { "aria-label": "Loading folder\u2026" }) })) : (_jsx(Table.Container, { children: _jsxs(Table, { "aria-label": label, cellPadding: "condensed", gridTemplateColumns: "minmax(0, 1fr) max-content max-content", children: [_jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.Header, { children: "Name" }), _jsx(Table.Header, { children: "Last modified" }), _jsx(Table.Header, { align: "end", children: "Size" })] }) }), _jsxs(Table.Body, { children: [path && (_jsx(ParentRow, { path: PathExt.dirname(path), onNavigate: onNavigate })), items.map(item => (_jsx(ContentsRow, { item: item, current: item.path === current?.path, onNavigate: onNavigate, onSelect: onSelect, onContextMenu: onContextMenu }, item.path)))] })] }) }))] }));
113
+ : `Go to ${segment.path}`, onNavigate: onNavigate })] }, segment.path)))] }) }), loading ? (_jsx(Box, { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "40px", padding: 3, children: _jsx(Spinner, { "aria-label": "Loading folder\u2026" }) })) : (_jsx(Table.Container, { children: _jsxs(Table, { "aria-label": label, cellPadding: "condensed", gridTemplateColumns: "minmax(0, 1fr) max-content max-content", children: [_jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.Header, { children: "Name" }), _jsx(Table.Header, { children: "Last modified" }), _jsx(Table.Header, { align: "end", children: "Size" })] }) }), _jsxs(Table.Body, { children: [path && (_jsx(ParentRow, { path: PathExt.dirname(path), onNavigate: onNavigate })), items.map(item => (_jsx(ContentsRow, { item: item, current: item.path === current?.path, onNavigate: onNavigate, onSelect: onSelect, onContextMenu: onContextMenu }, item.path)))] })] }) }))] }));
133
114
  }
134
115
  export default ContentsTable;
@@ -26,34 +26,12 @@ export const StudentResultCircle = (props) => {
26
26
  }, onMouseDown: event => {
27
27
  event.preventDefault();
28
28
  event.stopPropagation();
29
- }, sx: {
30
- display: 'inline-block',
31
- flex: 'none',
32
- appearance: 'none',
33
- p: 0,
34
- bg: 'transparent',
35
- cursor: 'default',
36
- lineHeight: 0,
37
- border: 'none',
38
- outline: 'none',
39
- }, children: _jsx(Box, { as: "span", role: "img", "aria-hidden": true, sx: {
40
- display: 'inline-block',
41
- flex: 'none',
42
- width: '14px',
43
- height: '14px',
44
- borderRadius: 3,
45
- ml: 1,
46
- pointerEvents: 'auto',
47
- boxSizing: 'border-box',
48
- backgroundColor: isNone
49
- ? 'transparent'
50
- : status === 'pass'
51
- ? okColor
52
- : status === 'partial'
53
- ? partialColor
54
- : nokColor,
55
- border: isNone ? '1px solid' : 'none',
56
- borderColor: isNone ? 'border.default' : 'transparent',
57
- } }) }) }));
29
+ }, display: "inline-block", flex: "none", appearance: "none", p: 0, bg: "transparent", cursor: "default", lineHeight: 0, border: "none", outline: "none", children: _jsx(Box, { as: "span", role: "img", "aria-hidden": true, display: "inline-block", flex: "none", width: "14px", height: "14px", borderRadius: 3, ml: 1, pointerEvents: "auto", boxSizing: "border-box", backgroundColor: isNone
30
+ ? 'transparent'
31
+ : status === 'pass'
32
+ ? okColor
33
+ : status === 'partial'
34
+ ? partialColor
35
+ : nokColor, border: isNone ? '1px solid' : 'none', borderColor: isNone ? 'border.default' : 'transparent' }) }) }));
58
36
  };
59
37
  export default StudentResultCircle;
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from '@primer/react';
2
+ import { Box } from '@datalayer/primer-addons';
3
+ import { Text } from '@primer/react';
3
4
  const statusStyles = {
4
5
  done: {
5
6
  dotBackground: 'success.emphasis',
@@ -42,44 +43,11 @@ export const Timeline = ({ items, renderTimestamp }) => {
42
43
  if (!items.length) {
43
44
  return null;
44
45
  }
45
- return (_jsx(Box, { sx: {
46
- overflowX: 'auto',
47
- pb: 1,
48
- }, children: _jsx(Box, { sx: {
49
- display: 'flex',
50
- alignItems: 'stretch',
51
- minWidth: 'max-content',
52
- }, children: items.map((item, index) => {
46
+ return (_jsx(Box, { overflowX: "auto", pb: 1, children: _jsx(Box, { display: "flex", alignItems: "stretch", minWidth: "max-content", children: items.map((item, index) => {
53
47
  const status = item.status || 'neutral';
54
48
  const style = statusStyles[status];
55
49
  const hasNext = index < items.length - 1;
56
- return (_jsxs(Box, { sx: {
57
- display: 'flex',
58
- flexDirection: 'column',
59
- minWidth: 220,
60
- flex: hasNext ? '0 0 220px' : '0 0 auto',
61
- pr: hasNext ? 0 : 1,
62
- }, children: [_jsxs(Box, { sx: {
63
- display: 'flex',
64
- alignItems: 'center',
65
- minHeight: 28,
66
- mb: 2,
67
- }, children: [_jsx(Box, { sx: {
68
- width: 16,
69
- height: 16,
70
- borderRadius: '50%',
71
- border: '2px solid',
72
- borderColor: style.dotBorder,
73
- bg: style.dotBackground,
74
- boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.2)',
75
- } }), hasNext ? (_jsx(Box, { sx: {
76
- flex: 1,
77
- height: 4,
78
- ml: 2,
79
- mr: 2,
80
- borderRadius: 999,
81
- bg: style.lineColor,
82
- } })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
50
+ return (_jsxs(Box, { display: "flex", flexDirection: "column", minWidth: 220, flex: hasNext ? '0 0 220px' : '0 0 auto', pr: hasNext ? 0 : 1, children: [_jsxs(Box, { display: "flex", alignItems: "center", minHeight: 28, mb: 2, children: [_jsx(Box, { width: 16, height: 16, borderRadius: "50%", border: "2px solid", borderColor: style.dotBorder, bg: style.dotBackground, boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.2)" }), hasNext ? (_jsx(Box, { flex: 1, height: 4, ml: 2, mr: 2, borderRadius: 999, bg: style.lineColor })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
83
51
  fontSize: 0,
84
52
  color: 'fg.muted',
85
53
  mb: item.subtitle ? 1 : 0,
@@ -4,7 +4,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
6
  import { useEffect } from 'react';
7
- import { Heading, Box, Spinner } from '@primer/react';
7
+ import { Box } from '@datalayer/primer-addons';
8
+ import { Heading, Spinner } from '@primer/react';
8
9
  import { useBackdrop } from '../index.js';
9
10
  import { useLayoutStore } from '../../state/index.js';
10
11
  const BackdropContent = (props) => {
@@ -4,7 +4,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
6
  import { useEffect } from 'react';
7
- import { Box } from '@primer/react';
7
+ import { Box } from '@datalayer/primer-addons';
8
8
  import { useScreencapture, useToast } from '../index.js';
9
9
  import { lazyWithPreload, WithSuspense } from '../../utils/index.js';
10
10
  import { useLayoutStore } from '../../state/index.js';
@@ -6,7 +6,10 @@
6
6
  * projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
7
7
  * and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
8
8
  * that runs live can be tried before it is cloned: not a decision, and naming
9
- * the agent it runs on.
9
+ * the agent it runs on. One of Datalayer's examples, published from the
10
+ * catalogue, also says which (`catalogue_example_s`), beside `publisher_s:
11
+ * datalayer` — the Library projects both only for an item of the `datalayer`
12
+ * organization's spaces whose metadata says `catalogueExample` (STUDIO E-10).
10
13
  *
11
14
  * @module hooks/libraryApp
12
15
  */
@@ -30,6 +33,8 @@ export type LibraryAppFields = {
30
33
  appKind?: LibraryAppKind;
31
34
  /** Whether it can be tried before it is cloned. */
32
35
  runsLive: boolean;
36
+ /** The example of the catalogue it is, when it is one of Datalayer's. */
37
+ catalogueExample?: string;
33
38
  };
34
39
  /** The face `face_s` carries; a value that is not a face's JSON is refused. */
35
40
  export declare function libraryAppFaceOf(value: unknown): LibraryAppFace | undefined;
@@ -10,7 +10,10 @@
10
10
  * projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
11
11
  * and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
12
12
  * that runs live can be tried before it is cloned: not a decision, and naming
13
- * the agent it runs on.
13
+ * the agent it runs on. One of Datalayer's examples, published from the
14
+ * catalogue, also says which (`catalogue_example_s`), beside `publisher_s:
15
+ * datalayer` — the Library projects both only for an item of the `datalayer`
16
+ * organization's spaces whose metadata says `catalogueExample` (STUDIO E-10).
14
17
  *
15
18
  * @module hooks/libraryApp
16
19
  */
@@ -50,10 +53,16 @@ export function libraryAppFieldsOf(raw) {
50
53
  !LIBRARY_APP_KINDS.includes(kind)) {
51
54
  throw new Error(`An app's kind is not one of ${LIBRARY_APP_KINDS}: ${String(kind)}`);
52
55
  }
56
+ const example = raw.catalogue_example_s;
57
+ if (example !== undefined &&
58
+ (typeof example !== 'string' || example.trim() === '')) {
59
+ throw new Error(`An app's example is not an example's id: ${String(example)}`);
60
+ }
53
61
  const face = libraryAppFaceOf(raw.face_s);
54
62
  return {
55
63
  ...(face ? { face } : {}),
56
64
  ...(kind ? { appKind: kind } : {}),
57
65
  runsLive: raw.runs_live_b === true,
66
+ ...(example ? { catalogueExample: example } : {}),
58
67
  };
59
68
  }
@@ -0,0 +1,22 @@
1
+ import type { IIAMProviderName } from '../models/IAMProvidersSpecs';
2
+ /** What `requestDatalayer` resolves: on failure, `success: false` and IAM's sentence. */
3
+ type UnlinkResponse = {
4
+ success?: boolean;
5
+ message?: string;
6
+ };
7
+ type Request = (request: {
8
+ url: string;
9
+ method: 'DELETE';
10
+ notifyOnError: false;
11
+ }) => Promise<UnlinkResponse>;
12
+ /**
13
+ * Unlink a provider from the signed-in account
14
+ * (`DELETE /api/iam/v1/me/providers/{provider}`).
15
+ *
16
+ * IAM answers 409 when the provider is the account's only way to sign in and
17
+ * 404 when it is not linked; either way its sentence is thrown as the error's
18
+ * message for the page to show, and nothing is toasted. On success `refresh`
19
+ * reads the user again before this resolves.
20
+ */
21
+ export declare function unlinkIAMProvider(request: Request, iamUrl: string, provider: IIAMProviderName, refresh: () => Promise<void>): Promise<void>;
22
+ export {};
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Unlink a provider from the signed-in account
7
+ * (`DELETE /api/iam/v1/me/providers/{provider}`).
8
+ *
9
+ * IAM answers 409 when the provider is the account's only way to sign in and
10
+ * 404 when it is not linked; either way its sentence is thrown as the error's
11
+ * message for the page to show, and nothing is toasted. On success `refresh`
12
+ * reads the user again before this resolves.
13
+ */
14
+ export async function unlinkIAMProvider(request, iamUrl, provider, refresh) {
15
+ const response = await request({
16
+ url: `${iamUrl}/api/iam/v1/me/providers/${encodeURIComponent(provider)}`,
17
+ method: 'DELETE',
18
+ notifyOnError: false,
19
+ });
20
+ if (!response?.success) {
21
+ throw new Error(response?.message || `The ${provider} account could not be unlinked.`);
22
+ }
23
+ await refresh();
24
+ }
@@ -35,8 +35,13 @@ export const useAuthorization = () => {
35
35
  const checkIsPlatformMember = (user) => {
36
36
  return user.roles.includes(PlatformRoles.Member.handle);
37
37
  };
38
+ /**
39
+ * Whether the user sees the features that are not released yet: a Platform
40
+ * Features Previewer, or a Platform Admin — an admin previews everything.
41
+ */
38
42
  const checkIsPlatformFeaturesPreviewer = (user) => {
39
- return user.roles.includes(PlatformRoles.FeaturesPreviewer.handle);
43
+ return (user.roles.includes(PlatformRoles.FeaturesPreviewer.handle) ||
44
+ checkIsPlatformAdmin(user));
40
45
  };
41
46
  const checkIsPlatformUsageReviewer = (user) => {
42
47
  return user.roles.includes(PlatformRoles.UsageReviewer.handle);
@@ -33,7 +33,7 @@
33
33
  * ```
34
34
  */
35
35
  import { QueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
36
- import { IAnyOrganization, IContact, IIAMToken, IOrganization, ISchool, ISecret, IStudent, ITeam, IUser, IUserOnboarding, IUserSettings } from '../models';
36
+ import { IAnyOrganization, IContact, IIAMProviderName, IIAMToken, IOrganization, ISchool, ISecret, IStudent, ITeam, IUser, IUserOnboarding, IUserSettings } from '../models';
37
37
  type IAnySpace = any;
38
38
  export type CacheProps = {
39
39
  loginRoute?: string;
@@ -486,6 +486,7 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
486
486
  useGetGitHubProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
487
487
  useGetGoogleProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
488
488
  useGetLinkedinProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, void, unknown>;
489
+ useUnlinkIAMProvider: () => import("@tanstack/react-query").UseMutationResult<void, Error, IIAMProviderName, unknown>;
489
490
  usePostLinkedinShare: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
490
491
  postText: string;
491
492
  }, unknown>;
@@ -1015,6 +1016,12 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
1015
1016
  useSecrets: (options?: {
1016
1017
  principalUid?: string;
1017
1018
  principalKind?: "personal" | "organization" | "team";
1019
+ } & {
1020
+ /**
1021
+ * `false` reads nothing: a page a visitor opens signed out, whose 401
1022
+ * would otherwise send them to the sign-in.
1023
+ */
1024
+ enabled?: boolean;
1018
1025
  }) => import("@tanstack/react-query").UseQueryResult<any, Error>;
1019
1026
  useCreateSecret: (options?: {
1020
1027
  principalUid?: string;
@@ -40,6 +40,7 @@ import { useQuery, useQueries, useMutation, useQueryClient, } from '@tanstack/re
40
40
  import { BOOTSTRAP_USER_ONBOARDING, asContact, asInvite, asOrganization, asSecret, asTeam, asToken, asUser, } from '../models/index.js';
41
41
  import { asSpace } from './cacheConverters.js';
42
42
  import { libraryAppFieldsOf } from './libraryApp.js';
43
+ import { unlinkIAMProvider } from './unlinkIAMProvider.js';
43
44
  import { useCoreStore, useIAMStore, profileStore } from '../state/index.js';
44
45
  import { asDisplayName, namesAsInitials, asArray } from '../utils/index.js';
45
46
  import { useDatalayer } from './useDatalayer.js';
@@ -2853,6 +2854,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2853
2854
  },
2854
2855
  ...DEFAULT_QUERY_OPTIONS,
2855
2856
  refetchOnMount: true, // Override to refetch when stale after invalidation
2857
+ enabled: options?.enabled ?? true,
2856
2858
  });
2857
2859
  };
2858
2860
  /**
@@ -5740,14 +5742,17 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
5740
5742
  });
5741
5743
  };
5742
5744
  /**
5743
- * Confirm password change with token
5745
+ * Confirm password change with the token the reset email carried. The
5746
+ * handle and token travel in the body, never in the URL: paths are written
5747
+ * to access logs.
5744
5748
  */
5745
5749
  const useConfirmPasswordWithToken = () => {
5746
5750
  return useMutation({
5747
5751
  mutationFn: async ({ userHandle, token, }) => {
5748
5752
  return requestDatalayer({
5749
- url: `${configuration.iamUrl}/api/iam/v1/password/confirm/users/${userHandle}/tokens/${token}`,
5750
- method: 'PUT',
5753
+ url: `${configuration.iamUrl}/api/iam/v1/password-reset/confirm`,
5754
+ method: 'POST',
5755
+ body: { handle: userHandle, token },
5751
5756
  });
5752
5757
  },
5753
5758
  });
@@ -7273,13 +7278,38 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
7273
7278
  },
7274
7279
  });
7275
7280
  };
7276
- /** Get the server-connected LinkedIn profile. */
7281
+ /**
7282
+ * Unlink a provider (github, google, linkedin, x) from the signed-in
7283
+ * account; IAM deletes the link and the tokens it holds for it.
7284
+ *
7285
+ * IAM's refusal (409: the provider is the account's only way to sign in)
7286
+ * is the error's message, for the page to show: nothing is toasted. On
7287
+ * success the signed-in user is read again, so the settings pages and the
7288
+ * header's provider icons follow its linked providers.
7289
+ */
7290
+ const useUnlinkIAMProvider = () => {
7291
+ const iamStore = useIAMStore();
7292
+ return useMutation({
7293
+ mutationFn: async (provider) => unlinkIAMProvider(requestDatalayer, configuration.iamUrl, provider, async () => {
7294
+ queryClient.invalidateQueries({ queryKey: queryKeys.auth.me() });
7295
+ await iamStore.refreshUser();
7296
+ }),
7297
+ });
7298
+ };
7299
+ /**
7300
+ * Get the server-connected LinkedIn profile.
7301
+ *
7302
+ * IAM answers 404 when no LinkedIn posting account is connected: a state
7303
+ * the caller shows (a link button), never an error toast. The resolved
7304
+ * response then carries `success: false`, `status` and `message`.
7305
+ */
7277
7306
  const useGetLinkedinProfile = () => {
7278
7307
  return useMutation({
7279
7308
  mutationFn: async () => {
7280
7309
  return requestDatalayer({
7281
7310
  url: `${configuration.iamUrl}/api/iam/v1/social/linkedin/profile`,
7282
7311
  method: 'GET',
7312
+ notifyOnError: false,
7283
7313
  });
7284
7314
  },
7285
7315
  });
@@ -8426,6 +8456,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
8426
8456
  useGetGitHubProfile,
8427
8457
  useGetGoogleProfile,
8428
8458
  useGetLinkedinProfile,
8459
+ useUnlinkIAMProvider,
8429
8460
  usePostLinkedinShare,
8430
8461
  usePostLinkedinShareWithUpload,
8431
8462
  useGetBlueskyConnection,
@@ -25,6 +25,7 @@
25
25
  import { useCallback, useMemo } from 'react';
26
26
  import { useLayoutStore } from '../state/index.js';
27
27
  import { navigationStore } from '../state/substates/NavigationState.js';
28
+ import { iamStore } from '../state/substates/IAMState.js';
28
29
  import { createNativeNavigate } from '../navigation/adapters/native.js';
29
30
  // Import React Router hooks from our wrapper
30
31
  import { useNavigateRR } from '../navigation/adapters/react-router.js';
@@ -133,8 +134,13 @@ export const useNavigate = () => {
133
134
  document.body.scrollTop = 0;
134
135
  }
135
136
  // Where the reader is now, for the shell they are in. A new tab and a
136
- // step back through history are both already past by here.
137
- navigationStore.getState().rememberRoute(to);
137
+ // step back through history are both already past by here. Only for
138
+ // somebody signed in: the shells are theirs, and a page a visitor read
139
+ // signed out (`/features`) would otherwise come back as the Platform's
140
+ // last page after they sign in.
141
+ if (iamStore.getState().user) {
142
+ navigationStore.getState().rememberRoute(to);
143
+ }
138
144
  if (rrNavigate) {
139
145
  rrNavigate(to, { replace: options.replace, state: options.state });
140
146
  return;
@@ -4,16 +4,11 @@ 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 { AlertIcon } from '@primer/octicons-react';
7
- import { Box, Button, Flash } from '@primer/react';
7
+ import { Box } from '@datalayer/primer-addons';
8
+ import { Button, Flash } from '@primer/react';
8
9
  import { useNavigate } from '../../hooks/index.js';
9
10
  export const FlashMock = () => {
10
11
  const navigate = useNavigate();
11
- return (_jsx(Flash, { variant: "warning", style: { marginBottom: 10 }, children: _jsxs(Box, { sx: {
12
- display: 'flex',
13
- alignItems: 'center',
14
- justifyContent: 'space-between',
15
- gap: 3,
16
- width: '100%',
17
- }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, {}), _jsx("span", { children: "This is placeholder content. Contact us to learn more about this feature." })] }), _jsx(Button, { size: "small", onClick: () => navigate('/contact'), children: "Contact Us" })] }) }));
12
+ return (_jsx(Flash, { variant: "warning", style: { marginBottom: 10 }, children: _jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 3, width: "100%", children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(AlertIcon, {}), _jsx("span", { children: "This is placeholder content. Contact us to learn more about this feature." })] }), _jsx(Button, { size: "small", onClick: () => navigate('/contact'), children: "Contact Us" })] }) }));
18
13
  };
19
14
  export default FlashMock;