@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.
- package/lib/cli-login.js +5 -51
- package/lib/components/anonymous/AnonymousKeyExpired.js +1 -15
- package/lib/components/anonymous/AnonymousKeyTimer.js +5 -15
- package/lib/components/auth/SignIn.js +2 -2
- package/lib/components/avatars/UserAvatar.d.ts +10 -11
- package/lib/components/avatars/UserAvatar.js +23 -52
- package/lib/components/avatars/UserProfileAvatar.js +1 -1
- package/lib/components/avatars/avatarChoice.d.ts +42 -0
- package/lib/components/avatars/avatarChoice.js +65 -0
- package/lib/components/avatars/index.d.ts +1 -0
- package/lib/components/avatars/index.js +1 -0
- package/lib/components/billing/BillingEntitySelect.js +6 -48
- package/lib/components/checkout/StripeCheckout.js +33 -217
- package/lib/components/collaboration/LiveEditorCollaborators.d.ts +3 -4
- package/lib/components/collaboration/LiveEditorCollaborators.js +7 -5
- package/lib/components/contents/ContentSourceCard.js +2 -11
- package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +1 -1
- package/lib/components/contents/HomeFolderObjectsBrowser.js +11 -35
- package/lib/components/display/CenteredSpinner.js +1 -6
- package/lib/components/display/DatalayerBox.js +2 -14
- package/lib/components/emoji/faceEmojis.js +48 -0
- package/lib/components/emoji/fluent/loaders.js +46 -0
- package/lib/components/emoji/fluent/svg/1f30a.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f30a.js +5 -0
- package/lib/components/emoji/fluent/svg/1f310.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f310.js +5 -0
- package/lib/components/emoji/fluent/svg/1f324.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f324.js +5 -0
- package/lib/components/emoji/fluent/svg/1f326.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f326.js +5 -0
- package/lib/components/emoji/fluent/svg/1f327.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f327.js +5 -0
- package/lib/components/emoji/fluent/svg/1f33e.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f33e.js +5 -0
- package/lib/components/emoji/fluent/svg/1f372.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f372.js +5 -0
- package/lib/components/emoji/fluent/svg/1f373.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f373.js +5 -0
- package/lib/components/emoji/fluent/svg/1f39b.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f39b.js +5 -0
- package/lib/components/emoji/fluent/svg/1f3ab.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f3ab.js +5 -0
- package/lib/components/emoji/fluent/svg/1f41b.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f41b.js +5 -0
- package/lib/components/emoji/fluent/svg/1f441.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f441.js +5 -0
- package/lib/components/emoji/fluent/svg/1f465.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f465.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4b9.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4b9.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4be.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4be.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4c1.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4c1.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4c2.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4c2.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4c4.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4c4.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4d3.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4d3.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4d6.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4d6.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4dc.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4dc.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4e1.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4e1.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4e2.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4e2.js +5 -0
- package/lib/components/emoji/fluent/svg/1f4e7.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f4e7.js +5 -0
- package/lib/components/emoji/fluent/svg/1f500.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f500.js +5 -0
- package/lib/components/emoji/fluent/svg/1f501.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f501.js +5 -0
- package/lib/components/emoji/fluent/svg/1f504.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f504.js +5 -0
- package/lib/components/emoji/fluent/svg/1f52d.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f52d.js +5 -0
- package/lib/components/emoji/fluent/svg/1f552.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f552.js +5 -0
- package/lib/components/emoji/fluent/svg/1f58b.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f58b.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5b2.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5b2.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5c3.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5c3.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5d1.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5d1.js +5 -0
- package/lib/components/emoji/fluent/svg/1f5dc.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f5dc.js +5 -0
- package/lib/components/emoji/fluent/svg/1f604.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f604.js +5 -0
- package/lib/components/emoji/fluent/svg/1f917.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f917.js +5 -0
- package/lib/components/emoji/fluent/svg/1f9d1-200d-2696.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1f9d1-200d-2696.js +5 -0
- package/lib/components/emoji/fluent/svg/1fa79.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1fa79.js +5 -0
- package/lib/components/emoji/fluent/svg/1fa9d.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1fa9d.js +5 -0
- package/lib/components/emoji/fluent/svg/1fa9f.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/1fa9f.js +5 -0
- package/lib/components/emoji/fluent/svg/23f3.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/23f3.js +5 -0
- package/lib/components/emoji/fluent/svg/2611.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2611.js +5 -0
- package/lib/components/emoji/fluent/svg/2702.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2702.js +5 -0
- package/lib/components/emoji/fluent/svg/270f.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/270f.js +5 -0
- package/lib/components/emoji/fluent/svg/2728.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2728.js +5 -0
- package/lib/components/emoji/fluent/svg/2b1c.d.ts +2 -0
- package/lib/components/emoji/fluent/svg/2b1c.js +5 -0
- package/lib/components/flashes/FlashClosable.js +2 -17
- package/lib/components/mcp/ClientBadge.js +1 -1
- package/lib/components/mcp/McpErrorBlankslate.js +1 -1
- package/lib/components/mcp/ScopeList.js +1 -1
- package/lib/components/notebooks/JupyterNotebook.js +1 -2
- package/lib/components/principal/Principal.js +2 -10
- package/lib/components/principal/PrincipalAppearance.d.ts +24 -1
- package/lib/components/principal/PrincipalAppearance.js +107 -80
- package/lib/components/principal/PrincipalAvatar.d.ts +5 -7
- package/lib/components/principal/PrincipalAvatar.js +12 -38
- package/lib/components/principal/PrincipalBadge.js +3 -13
- package/lib/components/principal/PrincipalBanner.js +4 -32
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +4 -7
- package/lib/components/principal/PrincipalDetailsOverlay.js +8 -24
- package/lib/components/principal/PrincipalHoverCard.js +15 -18
- package/lib/components/principal/PrincipalSwitcherMenu.js +15 -83
- package/lib/components/progress/ConsumptionBar.js +1 -1
- package/lib/components/sharing/ShareAccessComponent.js +21 -229
- package/lib/components/sharing/SharingEditor.js +1 -1
- package/lib/components/spaces/SpaceDetailsOverlay.js +4 -35
- package/lib/components/spaces/SpaceDisplay.js +1 -8
- package/lib/components/storage/ContentsBrowser.js +3 -26
- package/lib/components/storage/ContentsTable.js +4 -23
- package/lib/components/students/StudentResultCircle.js +7 -29
- package/lib/components/timeline/Timeline.js +4 -36
- package/lib/hooks/layouts/LayoutBackdrop.js +2 -1
- package/lib/hooks/layouts/LayoutScreencapture.js +1 -1
- package/lib/hooks/libraryApp.d.ts +6 -1
- package/lib/hooks/libraryApp.js +10 -1
- package/lib/hooks/unlinkIAMProvider.d.ts +22 -0
- package/lib/hooks/unlinkIAMProvider.js +24 -0
- package/lib/hooks/useAuthorization.js +6 -1
- package/lib/hooks/useCache.d.ts +8 -1
- package/lib/hooks/useCache.js +35 -4
- package/lib/hooks/useNavigate.js +8 -2
- package/lib/mocks/components/FlashMock.js +3 -8
- package/lib/mocks/views/DashboardMock.js +6 -72
- package/lib/mocks/views/FormMock.js +3 -2
- package/lib/mocks/views/TableMock.js +3 -2
- package/lib/mocks/views/WipMock.js +2 -1
- package/lib/models/IAMProviderLinked.d.ts +9 -0
- package/lib/models/IAMProviderLinked.js +34 -5
- package/lib/models/McpTask.d.ts +18 -1
- package/lib/models/McpTask.js +15 -0
- package/lib/models/Person.d.ts +9 -0
- package/lib/models/Person.js +23 -0
- package/lib/models/Profile.d.ts +2 -2
- package/lib/models/User.js +5 -12
- package/lib/models/UserOnboarding.d.ts +9 -0
- package/lib/models/UserOnboarding.js +33 -0
- package/lib/otel/views/OtelLive.js +4 -62
- package/lib/otel/views/OtelLiveSpans.js +4 -29
- package/lib/otel/views/OtelLogsList.js +13 -64
- package/lib/otel/views/OtelMetricsChart.js +4 -19
- package/lib/otel/views/OtelMetricsList.js +8 -77
- package/lib/otel/views/OtelSearchBar.js +3 -12
- package/lib/otel/views/OtelSpanDetail.js +9 -79
- package/lib/otel/views/OtelSpanTree.js +7 -57
- package/lib/otel/views/OtelSqlView.js +5 -99
- package/lib/otel/views/OtelSystemView.js +4 -34
- package/lib/otel/views/OtelTimeline.js +7 -37
- package/lib/otel/views/OtelTimelineRangeSlider.js +7 -140
- package/lib/otel/views/OtelTracesList.js +12 -76
- package/lib/portable/index.d.ts +9 -0
- package/lib/portable/index.js +14 -0
- package/lib/portable/states.d.ts +39 -0
- package/lib/portable/states.js +71 -0
- package/lib/state/substates/NavigationState.d.ts +10 -6
- package/lib/state/substates/NavigationState.js +18 -8
- package/lib/views/api-keys/APIKeyEdit.js +2 -11
- package/lib/views/api-keys/APIKeyNew.js +3 -19
- package/lib/views/api-keys/APIKeys.js +6 -11
- package/lib/views/api-keys/APIKeysStandalone.js +1 -1
- package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
- package/lib/views/datasources/DatasourceDetail.js +24 -17
- package/lib/views/datasources/DatasourceNew.js +2 -6
- package/lib/views/datasources/Datasources.js +2 -14
- package/lib/views/iam/SignInSimple.js +8 -64
- package/lib/views/mcp/AdmittedClients.js +3 -16
- package/lib/views/mcp/AlertDestinations.js +3 -11
- package/lib/views/mcp/AlertRules.js +4 -9
- package/lib/views/mcp/ApprovalQueue.js +5 -22
- package/lib/views/mcp/AuditLog.js +7 -44
- package/lib/views/mcp/ConnectedAgents.js +1 -6
- package/lib/views/mcp/EnterpriseConsole.js +11 -24
- package/lib/views/mcp/IdentityProviders.js +7 -31
- package/lib/views/mcp/McpDashboard.js +15 -31
- package/lib/views/mcp/McpHome.js +8 -55
- package/lib/views/mcp/McpObservability.js +14 -86
- package/lib/views/mcp/NotebookRuns.js +6 -13
- package/lib/views/mcp/OrganizationPolicy.js +3 -9
- package/lib/views/mcp/OrganizationUsage.js +5 -12
- package/lib/views/mcp/PersonalPolicy.js +3 -3
- package/lib/views/mcp/Policies.js +6 -47
- package/lib/views/mcp/PolicyForm.js +1 -9
- package/lib/views/mcp/PolicyHistory.js +2 -8
- package/lib/views/mcp/RunDetail.d.ts +1 -1
- package/lib/views/mcp/RunDetail.js +7 -26
- package/lib/views/mcp/ScimProvisioning.js +4 -16
- package/lib/views/mcp/ServiceAgents.js +4 -17
- package/lib/views/mcp/TeamPolicies.js +7 -19
- package/lib/views/mcp/ToolAccess.js +16 -23
- package/lib/views/mcp/TraceTimeline.js +8 -23
- package/lib/views/otel/DashboardView.js +2 -2
- package/lib/views/otel/LogsView.js +2 -2
- package/lib/views/otel/MetricsView.js +2 -2
- package/lib/views/otel/OtelHeader.js +6 -40
- package/lib/views/otel/SqlView.js +2 -2
- package/lib/views/otel/SystemView.js +2 -2
- package/lib/views/otel/TracesView.js +2 -2
- package/lib/views/profile/UserBadge.js +6 -98
- package/lib/views/secrets/SecretEdit.js +2 -11
- package/lib/views/secrets/SecretNew.js +1 -1
- package/package.json +1 -1
|
@@ -226,9 +226,7 @@ export const Principal = ({ principal, isAdmin = false, avatarSize = 20, gap = 2
|
|
|
226
226
|
hydratedEntity?.avatarUrl ||
|
|
227
227
|
cachedPrincipal?.avatarUrl ||
|
|
228
228
|
undefined,
|
|
229
|
-
avatarIcon: principal.avatarIcon ||
|
|
230
|
-
hydratedEntity?.avatarIcon ||
|
|
231
|
-
undefined,
|
|
229
|
+
avatarIcon: principal.avatarIcon || hydratedEntity?.avatarIcon || undefined,
|
|
232
230
|
banner: principal.banner || hydratedEntity?.banner || undefined,
|
|
233
231
|
firstName: principal.firstName ||
|
|
234
232
|
hydratedEntity?.firstName ||
|
|
@@ -290,12 +288,6 @@ export const Principal = ({ principal, isAdmin = false, avatarSize = 20, gap = 2
|
|
|
290
288
|
resolvedIsPublic,
|
|
291
289
|
upsertCachedPrincipal,
|
|
292
290
|
]);
|
|
293
|
-
return (_jsxs(Box, { sx: {
|
|
294
|
-
display: 'inline-flex',
|
|
295
|
-
alignItems: 'center',
|
|
296
|
-
gap,
|
|
297
|
-
minWidth: 0,
|
|
298
|
-
...sx,
|
|
299
|
-
}, children: [_jsx(PrincipalAvatar, { kind: resolvedPrincipal.kind, avatarUrl: resolvedPrincipal.avatarUrl, avatarIcon: resolvedPrincipal.avatarIcon, alt: resolvedPrincipal.displayName, size: avatarSize, square: square }), _jsx(PrincipalDetailsOverlay, { kind: resolvedPrincipal.kind, uid: resolvedPrincipal.uid, displayName: resolvedPrincipal.displayName, name: resolvedPrincipal.name, description: resolvedPrincipal.description, handle: resolvedPrincipal.handle, accountHandle: resolvedPrincipal.accountHandle, firstName: resolvedPrincipal.firstName, lastName: resolvedPrincipal.lastName, email: resolvedPrincipal.email, origin: resolvedPrincipal.origin, avatarUrl: resolvedPrincipal.avatarUrl, avatarIcon: resolvedPrincipal.avatarIcon, organizationName: teamOrganizationNameResolved, memberCount: teamMemberCount, isPublic: resolvedIsPublic, isAdmin: isAdmin })] }));
|
|
291
|
+
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: gap, minWidth: 0, sx: sx, children: [_jsx(PrincipalAvatar, { kind: resolvedPrincipal.kind, avatarUrl: resolvedPrincipal.avatarUrl, avatar: resolvedPrincipal.avatarIcon, alt: resolvedPrincipal.displayName, size: avatarSize, square: square }), _jsx(PrincipalDetailsOverlay, { kind: resolvedPrincipal.kind, uid: resolvedPrincipal.uid, displayName: resolvedPrincipal.displayName, name: resolvedPrincipal.name, description: resolvedPrincipal.description, handle: resolvedPrincipal.handle, accountHandle: resolvedPrincipal.accountHandle, firstName: resolvedPrincipal.firstName, lastName: resolvedPrincipal.lastName, email: resolvedPrincipal.email, origin: resolvedPrincipal.origin, avatarUrl: resolvedPrincipal.avatarUrl, avatar: resolvedPrincipal.avatarIcon, organizationName: teamOrganizationNameResolved, memberCount: teamMemberCount, isPublic: resolvedIsPublic, isAdmin: isAdmin })] }));
|
|
300
292
|
};
|
|
301
293
|
export default Principal;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
2
|
import { type ComponentType, type SVGProps } from 'react';
|
|
3
|
+
import { type AvatarChoice } from '../avatars/avatarChoice';
|
|
3
4
|
/**
|
|
4
5
|
* Who a principal is: a person, an organization, a team — or a service
|
|
5
6
|
* principal, the one a deployed LOOP application acts in its own name through
|
|
@@ -114,7 +115,29 @@ export declare const PRINCIPAL_BANNERS: readonly [{
|
|
|
114
115
|
readonly Component: ComponentType<any>;
|
|
115
116
|
}];
|
|
116
117
|
export declare function getPrincipalBannerForSeed(seed: string): string;
|
|
117
|
-
|
|
118
|
+
/** The names of the avatar set: the icons an avatar may be. */
|
|
119
|
+
export declare const PRINCIPAL_AVATAR_ICON_NAMES: ReadonlySet<string>;
|
|
120
|
+
/** The avatar a kept value names; throws `AvatarRefused` for anything else. */
|
|
121
|
+
export declare function parsePrincipalAvatar(value: string): AvatarChoice;
|
|
122
|
+
/**
|
|
123
|
+
* The avatar a kept value names, or `undefined` when there is none or it is
|
|
124
|
+
* refused — said once on the console, in its sentence: a picture that cannot
|
|
125
|
+
* be drawn is drawn as no choice, never as a broken page.
|
|
126
|
+
*/
|
|
127
|
+
export declare function principalAvatarOf(value: string | undefined): AvatarChoice | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* The drawing of a chosen avatar — an emoji or an icon of the set, by its
|
|
130
|
+
* kept value — on nothing: whatever holds it gives it its disc
|
|
131
|
+
* (`UserAvatar`, `PrincipalAvatar`, an application's face). `null` for no
|
|
132
|
+
* choice, or a refused one.
|
|
133
|
+
*/
|
|
134
|
+
export declare function ChosenAvatar({ avatar, size, label, }: {
|
|
135
|
+
avatar: string | undefined;
|
|
136
|
+
/** Its edge, in pixels. */
|
|
137
|
+
size: number;
|
|
138
|
+
/** What it is called for a screen reader; empty, it is decoration. */
|
|
139
|
+
label?: string;
|
|
140
|
+
}): JSX.Element | null;
|
|
118
141
|
export declare function PrincipalBannerImage({ banner, height, }: {
|
|
119
142
|
banner?: string;
|
|
120
143
|
height?: number;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Suspense, lazy, useEffect, useState, } from 'react';
|
|
3
|
-
import { Box,
|
|
3
|
+
import { Box, useColorPalette } from '@datalayer/primer-addons';
|
|
4
|
+
import { Button, SegmentedControl, Text, Tooltip } from '@primer/react';
|
|
4
5
|
import { Dialog } from '@primer/react/experimental';
|
|
6
|
+
import { AvatarRefused, emojiAvatar, iconAvatar, parseAvatar, } from '../avatars/avatarChoice.js';
|
|
7
|
+
import { FACE_EMOJIS } from '../emoji/faceEmojis.js';
|
|
8
|
+
import { FluentEmoji } from '../emoji/FluentEmoji.js';
|
|
5
9
|
/**
|
|
6
10
|
* An avatar icon, fetched the first time it is drawn.
|
|
7
11
|
*
|
|
@@ -576,20 +580,59 @@ export function getPrincipalBannerForSeed(seed) {
|
|
|
576
580
|
}
|
|
577
581
|
return PRINCIPAL_BANNERS[Math.abs(hash) % PRINCIPAL_BANNERS.length].name;
|
|
578
582
|
}
|
|
579
|
-
|
|
580
|
-
|
|
583
|
+
/** The names of the avatar set: the icons an avatar may be. */
|
|
584
|
+
export const PRINCIPAL_AVATAR_ICON_NAMES = new Set(PRINCIPAL_AVATAR_ICONS.map(option => option.name));
|
|
585
|
+
/** The avatar a kept value names; throws `AvatarRefused` for anything else. */
|
|
586
|
+
export function parsePrincipalAvatar(value) {
|
|
587
|
+
return parseAvatar(value, PRINCIPAL_AVATAR_ICON_NAMES);
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* The avatar a kept value names, or `undefined` when there is none or it is
|
|
591
|
+
* refused — said once on the console, in its sentence: a picture that cannot
|
|
592
|
+
* be drawn is drawn as no choice, never as a broken page.
|
|
593
|
+
*/
|
|
594
|
+
export function principalAvatarOf(value) {
|
|
595
|
+
if (!value) {
|
|
596
|
+
return undefined;
|
|
597
|
+
}
|
|
598
|
+
try {
|
|
599
|
+
return parsePrincipalAvatar(value);
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
if (error instanceof AvatarRefused) {
|
|
603
|
+
console.error(`Avatar refused: ${error.message}`);
|
|
604
|
+
return undefined;
|
|
605
|
+
}
|
|
606
|
+
throw error;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* The drawing of a chosen avatar — an emoji or an icon of the set, by its
|
|
611
|
+
* kept value — on nothing: whatever holds it gives it its disc
|
|
612
|
+
* (`UserAvatar`, `PrincipalAvatar`, an application's face). `null` for no
|
|
613
|
+
* choice, or a refused one.
|
|
614
|
+
*/
|
|
615
|
+
export function ChosenAvatar({ avatar, size, label = '', }) {
|
|
616
|
+
const choice = principalAvatarOf(avatar);
|
|
617
|
+
if (!choice) {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
if (choice.kind === 'emoji') {
|
|
621
|
+
return _jsx(FluentEmoji, { emoji: choice.emoji, size: size, label: label });
|
|
622
|
+
}
|
|
623
|
+
const Icon = PRINCIPAL_AVATAR_ICONS.find(option => option.name === choice.name).Icon;
|
|
624
|
+
// The plain icon, coloured by the theme — never the `colored` variant,
|
|
625
|
+
// whose fixed palette belongs to the emoji it is drawn from.
|
|
626
|
+
return (_jsx(Icon, { size: size, themed: true, colormode: true, "aria-label": label || undefined, "aria-hidden": label ? undefined : true }));
|
|
581
627
|
}
|
|
582
628
|
export function PrincipalBannerImage({ banner, height = 180, }) {
|
|
583
629
|
const Banner = PRINCIPAL_BANNERS.find(option => option.name === banner)?.Component;
|
|
584
630
|
if (!Banner)
|
|
585
631
|
return null;
|
|
586
|
-
return (_jsx(Box, { sx: {
|
|
632
|
+
return (_jsx(Box, { overflow: "hidden", borderRadius: 2, bg: "canvas.subtle", sx: {
|
|
587
633
|
position: 'relative',
|
|
588
634
|
width: '100%',
|
|
589
635
|
height,
|
|
590
|
-
overflow: 'hidden',
|
|
591
|
-
borderRadius: 2,
|
|
592
|
-
bg: 'canvas.subtle',
|
|
593
636
|
'& > svg': {
|
|
594
637
|
position: 'absolute',
|
|
595
638
|
inset: 0,
|
|
@@ -603,8 +646,26 @@ export function PrincipalBannerImage({ banner, height = 180, }) {
|
|
|
603
646
|
}
|
|
604
647
|
export function PrincipalAvatarPicker({ value, onChange, disabled = false, }) {
|
|
605
648
|
const [open, setOpen] = useState(false);
|
|
606
|
-
const
|
|
607
|
-
|
|
649
|
+
const chosen = principalAvatarOf(value);
|
|
650
|
+
// The colour a chosen avatar is drawn in (`UserAvatar`'s `--datalayer-icon-fg`):
|
|
651
|
+
// the icons are offered as they will look.
|
|
652
|
+
const palette = useColorPalette();
|
|
653
|
+
// The tab the dialog opens on: what is chosen, the icons when nothing is.
|
|
654
|
+
const [tab, setTab] = useState(chosen?.kind === 'emoji' ? 'emoji' : 'icons');
|
|
655
|
+
const choose = (next) => {
|
|
656
|
+
onChange(next);
|
|
657
|
+
setOpen(false);
|
|
658
|
+
};
|
|
659
|
+
const selectedLabel = chosen?.kind === 'emoji'
|
|
660
|
+
? chosen.emoji
|
|
661
|
+
: chosen
|
|
662
|
+
? PRINCIPAL_AVATAR_ICONS.find(option => option.name === chosen.name)
|
|
663
|
+
?.label
|
|
664
|
+
: undefined;
|
|
665
|
+
return (_jsxs(_Fragment, { children: [_jsx(Button, { type: "button", disabled: disabled, onClick: () => {
|
|
666
|
+
setTab(chosen?.kind === 'emoji' ? 'emoji' : 'icons');
|
|
667
|
+
setOpen(true);
|
|
668
|
+
}, leadingVisual: chosen ? () => _jsx(ChosenAvatar, { avatar: value, size: 16 }) : undefined, children: selectedLabel ? `Change Avatar (${selectedLabel})` : 'Choose Avatar' }), open ? (_jsxs(Dialog, { title: "Choose an Avatar", onClose: () => setOpen(false),
|
|
608
669
|
// The widest the dialog names — 640px — which is what it falls
|
|
609
670
|
// back to should the width below ever stop applying.
|
|
610
671
|
width: "xlarge",
|
|
@@ -624,62 +685,49 @@ export function PrincipalAvatarPicker({ value, onChange, disabled = false, }) {
|
|
|
624
685
|
width: 'min(1080px, calc(100vw - 32px))',
|
|
625
686
|
maxWidth: 'none',
|
|
626
687
|
},
|
|
627
|
-
}, children: _jsx(Box, {
|
|
628
|
-
|
|
688
|
+
}, children: [_jsxs(SegmentedControl, { "aria-label": "Avatar kind", sx: { mb: 3 }, onChange: index => setTab(index === 0 ? 'emoji' : 'icons'), children: [_jsx(SegmentedControl.Button, { selected: tab === 'emoji', children: "Emoji" }), _jsx(SegmentedControl.Button, { selected: tab === 'icons', children: "Icons" })] }), tab === 'emoji' ? (_jsx(Box, { display: "grid", gridTemplateColumns: [
|
|
689
|
+
'repeat(6, minmax(0, 1fr))',
|
|
690
|
+
'repeat(12, minmax(0, 1fr))',
|
|
691
|
+
], gap: 2, children: FACE_EMOJIS.map(emoji => {
|
|
692
|
+
const next = emojiAvatar(emoji);
|
|
693
|
+
const pressed = value === next;
|
|
694
|
+
return (_jsx(Box, { as: "button", type: "button", "aria-label": emoji, "aria-pressed": pressed, onClick: () => choose(next), display: "flex", alignItems: "center", justifyContent: "center", height: 72, width: "100%", p: 0, appearance: "none", cursor: "pointer", border: "1px solid", borderRadius: 2, borderColor: pressed ? 'accent.emphasis' : 'border.default', bg: pressed ? 'accent.subtle' : 'canvas.default', hover: { borderColor: 'accent.emphasis' }, children: _jsx(FluentEmoji, { emoji: emoji, size: 44, label: "" }) }, emoji));
|
|
695
|
+
}) })) : null, tab === 'icons' ? (_jsx(Box, { style: { '--datalayer-icon-fg': palette.primary }, display: "grid",
|
|
629
696
|
// Twelve to a line, whatever the dialog is wide: the columns
|
|
630
697
|
// share it evenly and `minmax(0, …)` lets them shrink under
|
|
631
698
|
// their content, which a long name would otherwise widen.
|
|
632
699
|
gridTemplateColumns: [
|
|
633
700
|
'repeat(6, minmax(0, 1fr))',
|
|
634
701
|
'repeat(12, minmax(0, 1fr))',
|
|
635
|
-
],
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
bg: value === name ? 'accent.subtle' : 'canvas.default',
|
|
658
|
-
':hover': { borderColor: 'accent.emphasis' },
|
|
659
|
-
}, children: [_jsx(Box, { sx: {
|
|
660
|
-
height: 72,
|
|
661
|
-
display: 'flex',
|
|
662
|
-
alignItems: 'center',
|
|
663
|
-
justifyContent: 'center',
|
|
664
|
-
}, children: _jsx(Icon, { size: 52, themed: true, colormode: true }) }), _jsx(Text, { sx: {
|
|
665
|
-
display: 'block',
|
|
666
|
-
px: 2,
|
|
667
|
-
py: 1,
|
|
668
|
-
fontSize: 0,
|
|
669
|
-
textAlign: 'center',
|
|
670
|
-
// A name too long for the card is cut rather than
|
|
671
|
-
// stretching the grid it sits in.
|
|
672
|
-
overflow: 'hidden',
|
|
673
|
-
textOverflow: 'ellipsis',
|
|
674
|
-
whiteSpace: 'nowrap',
|
|
675
|
-
}, children: label })] }) }, name))) }) })) : null] }));
|
|
702
|
+
], gap: 2, children: PRINCIPAL_AVATAR_ICONS.map(({ name, label, description, Icon }) => (
|
|
703
|
+
// A button drawn as a card rather than a Primer `Button`: the
|
|
704
|
+
// avatar is named under it, as the banners are under theirs.
|
|
705
|
+
// The name under a card is clipped when it is long, and a
|
|
706
|
+
// picture says only so much: the tooltip gives the whole name
|
|
707
|
+
// and what the picture is of.
|
|
708
|
+
_jsx(Tooltip, { text: description ? `${label} — ${description}` : label, direction: "n", children: _jsxs(Box, { as: "button", type: "button", "aria-label": description ? `${label} — ${description}` : label, "aria-pressed": value === iconAvatar(name), onClick: () => choose(iconAvatar(name)), display: "block", width: "100%", p: 0, overflow: "hidden", appearance: "none", color: "fg.default", cursor: "pointer", border: "1px solid", borderRadius: 2, borderColor: value === iconAvatar(name)
|
|
709
|
+
? 'accent.emphasis'
|
|
710
|
+
: 'border.default', bg: value === iconAvatar(name)
|
|
711
|
+
? 'accent.subtle'
|
|
712
|
+
: 'canvas.default', hover: { borderColor: 'accent.emphasis' }, children: [_jsx(Box, { height: 72, display: "flex", alignItems: "center", justifyContent: "center", children: _jsx(Icon, { size: 52, themed: true, colormode: true }) }), _jsx(Text, { sx: {
|
|
713
|
+
display: 'block',
|
|
714
|
+
px: 2,
|
|
715
|
+
py: 1,
|
|
716
|
+
fontSize: 0,
|
|
717
|
+
textAlign: 'center',
|
|
718
|
+
// A name too long for the card is cut rather than
|
|
719
|
+
// stretching the grid it sits in.
|
|
720
|
+
overflow: 'hidden',
|
|
721
|
+
textOverflow: 'ellipsis',
|
|
722
|
+
whiteSpace: 'nowrap',
|
|
723
|
+
}, children: label })] }) }, name))) })) : null] })) : null] }));
|
|
676
724
|
}
|
|
677
725
|
export function PrincipalBannerPicker({ value, onChange, disabled = false, showPreview = true, }) {
|
|
678
726
|
const [open, setOpen] = useState(false);
|
|
679
727
|
const [selectedName, setSelectedName] = useState(value);
|
|
680
728
|
useEffect(() => setSelectedName(value), [value]);
|
|
681
729
|
const selected = PRINCIPAL_BANNERS.find(option => option.name === selectedName);
|
|
682
|
-
return (_jsxs(_Fragment, { children: [showPreview && selected ? (_jsx(Box, {
|
|
730
|
+
return (_jsxs(_Fragment, { children: [showPreview && selected ? (_jsx(Box, { mb: 2, children: _jsx(PrincipalBannerImage, { banner: selected.name, height: 120 }) })) : null, _jsx(Button, { type: "button", disabled: disabled, onClick: () => setOpen(true), children: selected ? `Change Banner (${selected.label})` : 'Choose Banner' }), open ? (_jsx(Dialog, { title: "Choose a Banner", onClose: () => setOpen(false), width: "xlarge",
|
|
683
731
|
// Under `&&` for the reason given on the avatar picker: a plain
|
|
684
732
|
// `sx` ties with the named width and may lose to it.
|
|
685
733
|
sx: {
|
|
@@ -687,38 +735,17 @@ export function PrincipalBannerPicker({ value, onChange, disabled = false, showP
|
|
|
687
735
|
width: 'min(960px, calc(100vw - 32px))',
|
|
688
736
|
maxWidth: 'none',
|
|
689
737
|
},
|
|
690
|
-
}, children: _jsx(Box, {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
gridTemplateColumns: ['1fr', 'repeat(4, minmax(0, 1fr))'],
|
|
696
|
-
gap: 3,
|
|
697
|
-
}, children: PRINCIPAL_BANNERS.map(({ name, label, Component }) => (_jsxs(Box, { as: "button", type: "button", "aria-label": label, "aria-pressed": selectedName === name, onClick: () => {
|
|
738
|
+
}, children: _jsx(Box, { display: "grid",
|
|
739
|
+
// Four to a row, so a banner is seen against its neighbours
|
|
740
|
+
// rather than one at a time; one column on a narrow overlay,
|
|
741
|
+
// where four would be four slivers.
|
|
742
|
+
gridTemplateColumns: ['1fr', 'repeat(4, minmax(0, 1fr))'], gap: 3, children: PRINCIPAL_BANNERS.map(({ name, label, Component }) => (_jsxs(Box, { as: "button", type: "button", "aria-label": label, "aria-pressed": selectedName === name, onClick: () => {
|
|
698
743
|
setSelectedName(name);
|
|
699
744
|
onChange(name);
|
|
700
745
|
setOpen(false);
|
|
701
|
-
}, sx: {
|
|
702
|
-
display: 'block',
|
|
703
|
-
width: '100%',
|
|
704
|
-
p: 0,
|
|
705
|
-
overflow: 'hidden',
|
|
706
|
-
appearance: 'none',
|
|
707
|
-
color: 'fg.default',
|
|
708
|
-
cursor: 'pointer',
|
|
709
|
-
border: '1px solid',
|
|
710
|
-
borderRadius: 2,
|
|
711
|
-
borderColor: selectedName === name
|
|
712
|
-
? 'accent.emphasis'
|
|
713
|
-
: 'border.default',
|
|
714
|
-
bg: selectedName === name ? 'accent.subtle' : 'canvas.default',
|
|
715
|
-
textAlign: 'left',
|
|
716
|
-
':hover': { borderColor: 'accent.emphasis' },
|
|
717
|
-
}, children: [_jsx(Box, { sx: {
|
|
746
|
+
}, display: "block", width: "100%", p: 0, overflow: "hidden", appearance: "none", color: "fg.default", cursor: "pointer", border: "1px solid", borderRadius: 2, borderColor: selectedName === name ? 'accent.emphasis' : 'border.default', bg: selectedName === name ? 'accent.subtle' : 'canvas.default', textAlign: "left", hover: { borderColor: 'accent.emphasis' }, children: [_jsx(Box, { aspectRatio: "3 / 1", overflow: "hidden", sx: {
|
|
718
747
|
position: 'relative',
|
|
719
748
|
width: '100%',
|
|
720
|
-
aspectRatio: '3 / 1',
|
|
721
|
-
overflow: 'hidden',
|
|
722
749
|
'& > svg': {
|
|
723
750
|
position: 'absolute',
|
|
724
751
|
inset: 0,
|
|
@@ -4,14 +4,12 @@ export type PrincipalAvatarKind = PrincipalType;
|
|
|
4
4
|
export type PrincipalAvatarProps = {
|
|
5
5
|
kind: PrincipalAvatarKind;
|
|
6
6
|
avatarUrl?: string;
|
|
7
|
-
avatarIcon?: string;
|
|
8
7
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* personal-shaped seat in every roster it appears in today.
|
|
8
|
+
* The chosen avatar, as it is kept: `emoji:…` or
|
|
9
|
+
* `@datalayer/icons-react:…` (`components/avatars/avatarChoice`). An
|
|
10
|
+
* agent's face is its emoji, as `emoji:…`.
|
|
13
11
|
*/
|
|
14
|
-
|
|
12
|
+
avatar?: string;
|
|
15
13
|
alt?: string;
|
|
16
14
|
size?: number;
|
|
17
15
|
square?: boolean;
|
|
@@ -24,5 +22,5 @@ export type PrincipalAvatarProps = {
|
|
|
24
22
|
ring?: boolean;
|
|
25
23
|
className?: string;
|
|
26
24
|
};
|
|
27
|
-
export declare function PrincipalAvatar({ kind, avatarUrl,
|
|
25
|
+
export declare function PrincipalAvatar({ kind, avatarUrl, avatar, alt, size, square, ring, className, }: PrincipalAvatarProps): JSX.Element;
|
|
28
26
|
export default PrincipalAvatar;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { EntityAvatar } from '@datalayer/primer-addons';
|
|
3
3
|
import { OrganizationIcon, PeopleIcon } from '@primer/octicons-react';
|
|
4
4
|
import { UserAvatar } from '../avatars/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { ChosenAvatar, principalAvatarOf, } from './PrincipalAppearance.js';
|
|
6
6
|
function getFallbackIconSize(size) {
|
|
7
7
|
return Math.max(12, Math.round(size * 0.62));
|
|
8
8
|
}
|
|
9
|
-
export function PrincipalAvatar({ kind, avatarUrl,
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
// was asked for — see `UserAvatar`, which draws its ring the same way.
|
|
13
|
-
const ringSx = ring
|
|
14
|
-
? { boxShadow: '0 0 0 1px var(--borderColor-default, currentColor)' }
|
|
15
|
-
: undefined;
|
|
9
|
+
export function PrincipalAvatar({ kind, avatarUrl, avatar, alt, size = 20, square = false, ring = false, className, }) {
|
|
10
|
+
const chosen = principalAvatarOf(avatar);
|
|
11
|
+
const shape = square ? 'rounded' : 'circle';
|
|
16
12
|
/*
|
|
17
13
|
* A person is drawn by `UserAvatar`, whatever they wear.
|
|
18
14
|
*
|
|
@@ -25,37 +21,15 @@ export function PrincipalAvatar({ kind, avatarUrl, avatarIcon, avatarEmoji, alt,
|
|
|
25
21
|
// A service principal — an application's — is drawn as a person is: its
|
|
26
22
|
// chosen avatar, or its emoji, on the same disc (LOOP I-07).
|
|
27
23
|
if (kind === 'personal' || kind === 'service') {
|
|
28
|
-
return (_jsx(UserAvatar, { avatarUrl: avatarUrl,
|
|
24
|
+
return (_jsx(UserAvatar, { avatarUrl: avatarUrl, avatar: avatar, size: size, square: square, iconSize: getFallbackIconSize(size), ring: ring, className: className }));
|
|
29
25
|
}
|
|
30
|
-
if (
|
|
31
|
-
return (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
alignItems: 'center',
|
|
36
|
-
justifyContent: 'center',
|
|
37
|
-
overflow: 'hidden',
|
|
38
|
-
borderRadius: square ? 2 : '50%',
|
|
39
|
-
// The disc of `UserAvatar`, for the same reason: the shape is what
|
|
40
|
-
// says "avatar", and an icon drawn on nothing shows none of it.
|
|
41
|
-
bg: 'accent.subtle',
|
|
42
|
-
...ringSx,
|
|
43
|
-
}, "aria-label": alt || `${kind} avatar`, children: _jsx(SelectedIcon, { size: getFallbackIconSize(size), themed: true, colormode: true }) }));
|
|
26
|
+
if (chosen) {
|
|
27
|
+
return (
|
|
28
|
+
// The disc of `UserAvatar`, for the same reason: the shape is what says
|
|
29
|
+
// "avatar", and an icon drawn on nothing shows none of it.
|
|
30
|
+
_jsx(EntityAvatar, { className: className, size: size, shape: shape, ring: ring, alt: alt || `${kind} avatar`, children: _jsx(ChosenAvatar, { avatar: avatar, size: getFallbackIconSize(size) }) }));
|
|
44
31
|
}
|
|
45
|
-
const iconSize = getFallbackIconSize(size);
|
|
46
|
-
const borderRadius = square ? 2 : '50%';
|
|
47
32
|
const Icon = kind === 'team' ? PeopleIcon : OrganizationIcon;
|
|
48
|
-
return (_jsx(
|
|
49
|
-
width: size,
|
|
50
|
-
height: size,
|
|
51
|
-
display: 'inline-flex',
|
|
52
|
-
alignItems: 'center',
|
|
53
|
-
justifyContent: 'center',
|
|
54
|
-
bg: 'canvas.subtle',
|
|
55
|
-
borderRadius,
|
|
56
|
-
border: '1px solid',
|
|
57
|
-
borderColor: 'border.default',
|
|
58
|
-
...ringSx,
|
|
59
|
-
}, "aria-label": alt || (kind === 'team' ? 'Team' : 'Organization'), children: _jsx(Icon, { size: iconSize }) }));
|
|
33
|
+
return (_jsx(EntityAvatar, { className: className, size: size, shape: shape, ring: ring, ground: "canvas", alt: alt || (kind === 'team' ? 'Team' : 'Organization'), children: _jsx(Icon, { size: getFallbackIconSize(size) }) }));
|
|
60
34
|
}
|
|
61
35
|
export default PrincipalAvatar;
|
|
@@ -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 { useMemo } from 'react';
|
|
7
|
-
import { Box
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
|
+
import { Label, Text } from '@primer/react';
|
|
8
9
|
import { useCache } from '../../hooks/index.js';
|
|
9
10
|
import { useIAMStore } from '../../state/substates/index.js';
|
|
10
11
|
import { useSelectedPrincipal } from '../../hooks/useSelectedPrincipal.js';
|
|
@@ -220,17 +221,6 @@ export const PrincipalBadge = ({ principal: providedPrincipal, showPrincipalLabe
|
|
|
220
221
|
resolvedOrganization?.avatarIcon,
|
|
221
222
|
resolvedUser?.origin,
|
|
222
223
|
]);
|
|
223
|
-
return (_jsxs(Box, { sx: {
|
|
224
|
-
display: 'inline-flex',
|
|
225
|
-
alignItems: 'center',
|
|
226
|
-
gap: 2,
|
|
227
|
-
px: 2,
|
|
228
|
-
py: 1,
|
|
229
|
-
border: '1px solid',
|
|
230
|
-
borderColor: 'border.default',
|
|
231
|
-
borderRadius: 2,
|
|
232
|
-
bg: 'canvas.subtle',
|
|
233
|
-
...sx,
|
|
234
|
-
}, children: [showPrincipalLabel && (_jsx(Label, { size: "small", variant: "accent", children: principalLabel })), showApplyingToText && (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Applying to" })), _jsx(Principal, { principal: principal, isAdmin: isAdmin }), showOriginLabel && principal.origin && (_jsx(Label, { size: "small", variant: "secondary", children: principal.origin }))] }));
|
|
224
|
+
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", gap: 2, px: 2, py: 1, border: "1px solid", borderColor: "border.default", borderRadius: 2, bg: "canvas.subtle", sx: sx, children: [showPrincipalLabel && (_jsx(Label, { size: "small", variant: "accent", children: principalLabel })), showApplyingToText && (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Applying to" })), _jsx(Principal, { principal: principal, isAdmin: isAdmin }), showOriginLabel && principal.origin && (_jsx(Label, { size: "small", variant: "secondary", children: principal.origin }))] }));
|
|
235
225
|
};
|
|
236
226
|
export default PrincipalBadge;
|
|
@@ -8,7 +8,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* (user, organization, or team) with a colored visual so a user
|
|
9
9
|
* can immediately see which principal a settings page applies to.
|
|
10
10
|
*/
|
|
11
|
-
import { Box
|
|
11
|
+
import { Box } from '@datalayer/primer-addons';
|
|
12
|
+
import { Label, Text } from '@primer/react';
|
|
12
13
|
import { OrganizationIcon, PeopleIcon, PersonIcon, } from '@primer/octicons-react';
|
|
13
14
|
import { useSelectedPrincipal } from '../../hooks/useSelectedPrincipal.js';
|
|
14
15
|
import { useIAMStore } from '../../state/substates/index.js';
|
|
@@ -39,33 +40,7 @@ export const PrincipalBanner = ({ caption, rightContent, }) => {
|
|
|
39
40
|
? 'attention.muted'
|
|
40
41
|
: 'accent.muted';
|
|
41
42
|
const fg = isOrganization ? 'done.fg' : isTeam ? 'attention.fg' : 'accent.fg';
|
|
42
|
-
return (_jsxs(Box, { sx: {
|
|
43
|
-
display: 'flex',
|
|
44
|
-
alignItems: 'center',
|
|
45
|
-
gap: 3,
|
|
46
|
-
p: 3,
|
|
47
|
-
border: '1px solid',
|
|
48
|
-
borderColor,
|
|
49
|
-
borderRadius: 2,
|
|
50
|
-
bg,
|
|
51
|
-
}, children: [_jsx(Box, { sx: {
|
|
52
|
-
width: 40,
|
|
53
|
-
height: 40,
|
|
54
|
-
display: 'flex',
|
|
55
|
-
alignItems: 'center',
|
|
56
|
-
justifyContent: 'center',
|
|
57
|
-
borderRadius: '50%',
|
|
58
|
-
bg: 'canvas.default',
|
|
59
|
-
border: '1px solid',
|
|
60
|
-
borderColor,
|
|
61
|
-
color: fg,
|
|
62
|
-
flex: '0 0 auto',
|
|
63
|
-
}, children: _jsx(Icon, { size: 20 }) }), _jsxs(Box, { sx: { minWidth: 0, flex: 1 }, children: [_jsxs(Box, { sx: {
|
|
64
|
-
display: 'flex',
|
|
65
|
-
alignItems: 'center',
|
|
66
|
-
gap: 2,
|
|
67
|
-
flexWrap: 'wrap',
|
|
68
|
-
}, children: [_jsx(Text, { sx: {
|
|
43
|
+
return (_jsxs(Box, { display: "flex", alignItems: "center", gap: 3, p: 3, border: "1px solid", borderColor: borderColor, borderRadius: 2, bg: bg, children: [_jsx(Box, { width: 40, height: 40, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", bg: "canvas.default", border: "1px solid", borderColor: borderColor, color: fg, flex: "0 0 auto", children: _jsx(Icon, { size: 20 }) }), _jsxs(Box, { minWidth: 0, flex: 1, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, flexWrap: "wrap", children: [_jsx(Text, { sx: {
|
|
69
44
|
color: 'fg.muted',
|
|
70
45
|
fontSize: 0,
|
|
71
46
|
textTransform: 'uppercase',
|
|
@@ -76,9 +51,6 @@ export const PrincipalBanner = ({ caption, rightContent, }) => {
|
|
|
76
51
|
? 'Organization'
|
|
77
52
|
: isTeam
|
|
78
53
|
? 'Team'
|
|
79
|
-
: 'User' }), caption && (_jsx(Text, { as: "p", sx: { m: 0, mt: 1, color: 'fg.muted', fontSize: 1 }, children: caption }))] }), rightContent ? (_jsx(Box, {
|
|
80
|
-
flex: ['1 1 100%', '0 0 auto'],
|
|
81
|
-
width: ['100%', 'min(640px, 58%)'],
|
|
82
|
-
}, children: rightContent })) : null] }));
|
|
54
|
+
: 'User' }), caption && (_jsx(Text, { as: "p", sx: { m: 0, mt: 1, color: 'fg.muted', fontSize: 1 }, children: caption }))] }), rightContent ? (_jsx(Box, { flex: ['1 1 100%', '0 0 auto'], width: ['100%', 'min(640px, 58%)'], children: rightContent })) : null] }));
|
|
83
55
|
};
|
|
84
56
|
export default PrincipalBanner;
|
|
@@ -14,14 +14,11 @@ export type PrincipalDetailsOverlayProps = {
|
|
|
14
14
|
email?: string;
|
|
15
15
|
origin?: string;
|
|
16
16
|
avatarUrl?: string;
|
|
17
|
-
avatarIcon?: string;
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `avatarIcon` since the emoji is its real identity here, not a
|
|
22
|
-
* placeholder standing in for one.
|
|
18
|
+
* The chosen avatar, as it is kept: `emoji:…` (an agent's face is its
|
|
19
|
+
* emoji) or `@datalayer/icons-react:…`.
|
|
23
20
|
*/
|
|
24
|
-
|
|
21
|
+
avatar?: string;
|
|
25
22
|
/** Team-specific: parent organization display name. */
|
|
26
23
|
organizationName?: string;
|
|
27
24
|
/** Team-specific: number of members. */
|
|
@@ -59,7 +56,7 @@ export declare function buildPrincipalProfilePath({ kind, uid, handle, accountHa
|
|
|
59
56
|
* anchored on an avatar ({@link PrincipalHoverCard}) both render this, so
|
|
60
57
|
* the two never drift.
|
|
61
58
|
*/
|
|
62
|
-
export declare function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl,
|
|
59
|
+
export declare function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl, avatar, organizationName, memberCount, isPublic, isAdmin, onNavigate, }: PrincipalDetailsOverlayProps): JSX.Element;
|
|
63
60
|
/**
|
|
64
61
|
* A principal's details, shown from a click on their name.
|
|
65
62
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { Box } from '@datalayer/primer-addons';
|
|
3
|
+
import { ActionMenu, Button, Label, Text, ThemeProvider } from '@primer/react';
|
|
3
4
|
import { useNavigate } from '../../hooks/index.js';
|
|
4
5
|
import { PrincipalAvatar } from './PrincipalAvatar.js';
|
|
5
6
|
import { displayHandleText } from '../display/DisplayHandle.js';
|
|
@@ -88,7 +89,7 @@ export function buildPrincipalProfilePath({ kind, uid, handle, accountHandle, is
|
|
|
88
89
|
* anchored on an avatar ({@link PrincipalHoverCard}) both render this, so
|
|
89
90
|
* the two never drift.
|
|
90
91
|
*/
|
|
91
|
-
export function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl,
|
|
92
|
+
export function PrincipalDetailsCard({ kind, uid, displayName, name, description, handle, accountHandle, firstName, lastName, email, origin, avatarUrl, avatar, organizationName, memberCount, isPublic, isAdmin = false, onNavigate, }) {
|
|
92
93
|
const navigate = useNavigate();
|
|
93
94
|
// Where a profile or organization link goes: the router of this subtree,
|
|
94
95
|
// unless the caller knows of one that can actually serve it — see
|
|
@@ -139,18 +140,13 @@ export function PrincipalDetailsCard({ kind, uid, displayName, name, description
|
|
|
139
140
|
const organizationPath = teamOrganizationHandle
|
|
140
141
|
? `/${teamOrganizationHandle.replace(/^@+/, '')}`
|
|
141
142
|
: '';
|
|
142
|
-
return (_jsxs(Box, {
|
|
143
|
+
return (_jsxs(Box, { display: "grid", gap: 3, p: 4, minWidth: 420, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(PrincipalAvatar, { kind: kind, avatarUrl: avatarUrl, avatar: avatar, alt: normalizedDisplayName, size: 40,
|
|
143
144
|
// The card sets the avatar on its own ground, the same colour
|
|
144
145
|
// the avatar itself is on: without an edge of its own it has
|
|
145
146
|
// no visible shape at all. Round, and ringed.
|
|
146
|
-
square: false, ring: true }), _jsxs(Box, {
|
|
147
|
+
square: false, ring: true }), _jsxs(Box, { display: "grid", gap: 0.5, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: normalizedDisplayName }), kind === 'team' ? (teamHandleOnly ? (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: [displayHandleText(teamHandleOnly), teamOrganizationHandle
|
|
147
148
|
? ` · @${teamOrganizationHandle.replace(/^@+/, '')}`
|
|
148
|
-
: ''] })) : null) : resolvedHandle ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: displayHandleText(resolvedHandle) })) : null] })] }), _jsxs(Box, { sx: {
|
|
149
|
-
display: 'grid',
|
|
150
|
-
gridTemplateColumns: '110px 1fr',
|
|
151
|
-
gap: 1,
|
|
152
|
-
alignItems: 'baseline',
|
|
153
|
-
}, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Kind" }), _jsx(Text, { sx: { fontSize: 1 }, children: kind }), resolvedHandle && kind !== 'team' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsx(Text, { sx: { fontSize: 1 }, children: displayHandleText(resolvedHandle) })] })) : null, normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null, kind === 'personal' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "First name" }), _jsx(Text, { sx: { fontSize: 1 }, children: firstName || 'N/A' }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Last name" }), _jsx(Text, { sx: { fontSize: 1 }, children: lastName || 'N/A' }), email ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Email" }), _jsx(Text, { sx: { fontSize: 1 }, children: email })] })) : null, _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Origin" }), _jsx(Label, { size: "small", variant: "secondary", title: normalizedOrigin, sx: {
|
|
149
|
+
: ''] })) : null) : resolvedHandle ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: displayHandleText(resolvedHandle) })) : 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: kind }), resolvedHandle && kind !== 'team' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsx(Text, { sx: { fontSize: 1 }, children: displayHandleText(resolvedHandle) })] })) : null, normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null, kind === 'personal' ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "First name" }), _jsx(Text, { sx: { fontSize: 1 }, children: firstName || 'N/A' }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Last name" }), _jsx(Text, { sx: { fontSize: 1 }, children: lastName || 'N/A' }), email ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Email" }), _jsx(Text, { sx: { fontSize: 1 }, children: email })] })) : null, _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Origin" }), _jsx(Label, { size: "small", variant: "secondary", title: normalizedOrigin, sx: {
|
|
154
150
|
justifySelf: 'start',
|
|
155
151
|
width: 'fit-content',
|
|
156
152
|
maxWidth: '100%',
|
|
@@ -166,7 +162,7 @@ export function PrincipalDetailsCard({ kind, uid, displayName, name, description
|
|
|
166
162
|
overflow: 'hidden',
|
|
167
163
|
textOverflow: 'ellipsis',
|
|
168
164
|
whiteSpace: 'nowrap',
|
|
169
|
-
}, children: normalizedOrigin })] }))] }), _jsxs(Box, {
|
|
165
|
+
}, children: normalizedOrigin })] }))] }), _jsxs(Box, { display: "flex", justifyContent: "flex-end", gap: 2, children: [kind === 'team' && organizationPath ? (_jsx(Button, { size: "small", variant: "invisible", onClick: () => go(organizationPath), children: "View Organization" })) : null, _jsx(Button, { size: "small", onClick: () => go(targetPath), disabled: !targetPath, children: "View Profile" })] })] }));
|
|
170
166
|
}
|
|
171
167
|
/**
|
|
172
168
|
* A principal's details, shown from a click on their name.
|
|
@@ -179,18 +175,6 @@ export function PrincipalDetailsOverlay(props) {
|
|
|
179
175
|
normalize(props.handle) ||
|
|
180
176
|
normalize(props.uid) ||
|
|
181
177
|
'Principal';
|
|
182
|
-
return (_jsx(ThemeProvider, { children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button",
|
|
183
|
-
fontWeight: 'semibold',
|
|
184
|
-
color: 'accent.fg',
|
|
185
|
-
textDecoration: 'underline',
|
|
186
|
-
background: 'transparent',
|
|
187
|
-
border: 0,
|
|
188
|
-
padding: 0,
|
|
189
|
-
margin: 0,
|
|
190
|
-
cursor: 'pointer',
|
|
191
|
-
':hover': {
|
|
192
|
-
textDecoration: 'underline',
|
|
193
|
-
},
|
|
194
|
-
}, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(PrincipalDetailsCard, { ...props }) })] }) }));
|
|
178
|
+
return (_jsx(ThemeProvider, { children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button", fontWeight: "semibold", color: "accent.fg", textDecoration: "underline", background: "transparent", border: 0, padding: 0, margin: 0, cursor: "pointer", hover: { textDecoration: 'underline' }, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsx(PrincipalDetailsCard, { ...props }) })] }) }));
|
|
195
179
|
}
|
|
196
180
|
export default PrincipalDetailsOverlay;
|