@datalayer/core 1.0.21 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/lib/components/billing/BillableAccountSelect.d.ts +35 -0
  2. package/lib/components/billing/BillableAccountSelect.js +340 -0
  3. package/lib/components/billing/index.d.ts +1 -0
  4. package/lib/components/billing/index.js +5 -0
  5. package/lib/components/index.d.ts +2 -0
  6. package/lib/components/index.js +2 -0
  7. package/lib/components/principal/Principal.d.ts +37 -0
  8. package/lib/components/principal/Principal.js +54 -0
  9. package/lib/components/principal/PrincipalAvatar.d.ts +10 -0
  10. package/lib/components/principal/PrincipalAvatar.js +55 -0
  11. package/lib/components/principal/PrincipalBadge.d.ts +20 -0
  12. package/lib/components/principal/PrincipalBadge.js +208 -0
  13. package/lib/components/principal/PrincipalBanner.d.ts +7 -0
  14. package/lib/components/principal/PrincipalBanner.js +84 -0
  15. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +23 -0
  16. package/lib/components/principal/PrincipalDetailsOverlay.js +86 -0
  17. package/lib/components/principal/PrincipalSwitcherMenu.d.ts +14 -0
  18. package/lib/components/principal/PrincipalSwitcherMenu.js +287 -0
  19. package/lib/components/principal/index.d.ts +7 -0
  20. package/lib/components/principal/index.js +10 -0
  21. package/lib/components/sharing/ShareAccessComponent.d.ts +18 -0
  22. package/lib/components/sharing/ShareAccessComponent.js +1368 -0
  23. package/lib/components/sharing/SharingEditor.d.ts +20 -0
  24. package/lib/components/sharing/SharingEditor.js +65 -0
  25. package/lib/components/sharing/index.d.ts +9 -0
  26. package/lib/components/sharing/index.js +12 -0
  27. package/lib/hooks/index.d.ts +5 -0
  28. package/lib/hooks/index.js +5 -0
  29. package/lib/hooks/useBillableAccountStore.d.ts +31 -0
  30. package/lib/hooks/useBillableAccountStore.js +53 -0
  31. package/lib/hooks/usePrincipalStore.d.ts +41 -0
  32. package/lib/hooks/usePrincipalStore.js +101 -0
  33. package/lib/hooks/useSelectedBillableAccount.d.ts +14 -0
  34. package/lib/hooks/useSelectedBillableAccount.js +36 -0
  35. package/lib/hooks/useSelectedPrincipal.d.ts +17 -0
  36. package/lib/hooks/useSelectedPrincipal.js +29 -0
  37. package/lib/hooks/useUsageRefreshStore.d.ts +8 -0
  38. package/lib/hooks/useUsageRefreshStore.js +16 -0
  39. package/lib/utils/Handles.d.ts +3 -0
  40. package/lib/utils/Handles.js +53 -0
  41. package/lib/utils/index.d.ts +1 -0
  42. package/lib/utils/index.js +1 -0
  43. package/package.json +1 -3
@@ -0,0 +1,208 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ import { useMemo } from 'react';
7
+ import { Box, Label, Text } from '@primer/react';
8
+ import { useCache } from '../../hooks/index.js';
9
+ import { useIAMStore } from '../../state/substates/index.js';
10
+ import { useSelectedPrincipal } from '../../hooks/useSelectedPrincipal.js';
11
+ import { formatFriendlyHandle } from '../../utils/Handles.js';
12
+ import { Principal } from './Principal.js';
13
+ function normalizeUserOrigin(originRaw) {
14
+ const value = (originRaw || '').trim();
15
+ if (!value) {
16
+ return undefined;
17
+ }
18
+ const lower = value.toLowerCase();
19
+ if (lower === 'github') {
20
+ return 'GitHub';
21
+ }
22
+ if (lower === 'google') {
23
+ return 'Google';
24
+ }
25
+ if (lower === 'linkedin') {
26
+ return 'LinkedIn';
27
+ }
28
+ if (lower === 'microsoft') {
29
+ return 'Microsoft';
30
+ }
31
+ if (lower === 'datalayer') {
32
+ return 'Datalayer';
33
+ }
34
+ return value;
35
+ }
36
+ /**
37
+ * PrincipalBadge — small inline pill that displays a resolved principal
38
+ * (user / organization / team). Falls back to the currently selected
39
+ * principal when no explicit `principal` prop is supplied.
40
+ */
41
+ export const PrincipalBadge = ({ principal: providedPrincipal, showPrincipalLabel = true, showApplyingToText = true, showOriginLabel = true, principalLabel = 'Principal', isAdmin = false, sx, } = {}) => {
42
+ const { user } = useIAMStore();
43
+ const { selectedPrincipalKind, selectedPrincipalUid, selectedPrincipalHandle, selectedTeamParentOrganizationHandle, } = useSelectedPrincipal();
44
+ const { useUser, useOrganization } = useCache();
45
+ const basePrincipal = useMemo(() => {
46
+ if (providedPrincipal) {
47
+ return {
48
+ ...providedPrincipal,
49
+ displayName: providedPrincipal.displayName ||
50
+ providedPrincipal.handle ||
51
+ providedPrincipal.uid ||
52
+ 'Principal',
53
+ };
54
+ }
55
+ if (selectedPrincipalKind === 'organization') {
56
+ return {
57
+ kind: 'organization',
58
+ uid: selectedPrincipalUid,
59
+ handle: selectedPrincipalHandle,
60
+ accountHandle: selectedPrincipalHandle,
61
+ displayName: selectedPrincipalHandle
62
+ ? `@${formatFriendlyHandle(selectedPrincipalHandle)}`
63
+ : 'Organization',
64
+ origin: 'Datalayer',
65
+ };
66
+ }
67
+ if (selectedPrincipalKind === 'team') {
68
+ const teamHandle = selectedPrincipalHandle || 'team';
69
+ const orgHandle = selectedTeamParentOrganizationHandle || 'organization';
70
+ return {
71
+ kind: 'team',
72
+ uid: selectedPrincipalUid,
73
+ handle: `${orgHandle}/${teamHandle}`,
74
+ accountHandle: teamHandle,
75
+ displayName: `@${formatFriendlyHandle(orgHandle)}/${formatFriendlyHandle(teamHandle)}`,
76
+ origin: 'Datalayer',
77
+ };
78
+ }
79
+ const fullName = [user?.firstName, user?.lastName]
80
+ .filter(Boolean)
81
+ .join(' ')
82
+ .trim();
83
+ const resolvedHandle = user?.handle || selectedPrincipalHandle;
84
+ const fallbackHandle = resolvedHandle
85
+ ? `@${formatFriendlyHandle(resolvedHandle)}`
86
+ : '@me';
87
+ return {
88
+ kind: 'user',
89
+ uid: user?.id || selectedPrincipalUid,
90
+ displayName: fullName || fallbackHandle,
91
+ handle: resolvedHandle,
92
+ accountHandle: resolvedHandle,
93
+ firstName: user?.firstName,
94
+ lastName: user?.lastName,
95
+ email: user?.email,
96
+ avatarUrl: user?.avatarUrl,
97
+ origin: normalizeUserOrigin(user?.origin),
98
+ };
99
+ }, [
100
+ providedPrincipal,
101
+ selectedPrincipalKind,
102
+ selectedPrincipalUid,
103
+ selectedPrincipalHandle,
104
+ selectedTeamParentOrganizationHandle,
105
+ user?.id,
106
+ user?.origin,
107
+ user?.handle,
108
+ user?.firstName,
109
+ user?.lastName,
110
+ user?.email,
111
+ user?.avatarUrl,
112
+ ]);
113
+ const userLookupUid = basePrincipal.kind === 'user' ? String(basePrincipal.uid || '') : '';
114
+ const organizationLookupUid = basePrincipal.kind === 'organization'
115
+ ? String(basePrincipal.uid || '')
116
+ : '';
117
+ const { data: resolvedUser } = useUser(userLookupUid);
118
+ const { data: resolvedOrganization } = useOrganization(organizationLookupUid);
119
+ const principal = useMemo(() => {
120
+ if (basePrincipal.kind === 'organization') {
121
+ const resolvedHandle = resolvedOrganization?.handle ||
122
+ basePrincipal.handle ||
123
+ basePrincipal.accountHandle;
124
+ const normalizedHandle = resolvedHandle
125
+ ? formatFriendlyHandle(resolvedHandle)
126
+ : 'organization';
127
+ return {
128
+ kind: 'organization',
129
+ uid: basePrincipal.uid,
130
+ displayName: resolvedOrganization?.name ||
131
+ basePrincipal.displayName ||
132
+ `@${normalizedHandle}`,
133
+ handle: resolvedHandle,
134
+ accountHandle: resolvedHandle,
135
+ origin: basePrincipal.origin || 'Datalayer',
136
+ };
137
+ }
138
+ if (basePrincipal.kind === 'team') {
139
+ return {
140
+ kind: 'team',
141
+ uid: basePrincipal.uid,
142
+ displayName: basePrincipal.displayName ||
143
+ basePrincipal.handle ||
144
+ basePrincipal.uid ||
145
+ 'Team',
146
+ handle: basePrincipal.handle,
147
+ accountHandle: basePrincipal.accountHandle,
148
+ avatarUrl: basePrincipal.avatarUrl,
149
+ origin: basePrincipal.origin,
150
+ };
151
+ }
152
+ const fullName = [
153
+ resolvedUser?.firstName || basePrincipal.firstName,
154
+ resolvedUser?.lastName || basePrincipal.lastName,
155
+ ]
156
+ .filter(Boolean)
157
+ .join(' ')
158
+ .trim();
159
+ const resolvedHandle = resolvedUser?.handle ||
160
+ basePrincipal.handle ||
161
+ basePrincipal.accountHandle;
162
+ const fallbackHandle = resolvedHandle
163
+ ? `@${formatFriendlyHandle(resolvedHandle)}`
164
+ : '@me';
165
+ const resolvedDisplayName = resolvedUser?.displayName ||
166
+ basePrincipal.displayName ||
167
+ fullName ||
168
+ fallbackHandle;
169
+ const origin = normalizeUserOrigin(resolvedUser?.origin || basePrincipal.origin);
170
+ return {
171
+ kind: 'user',
172
+ uid: resolvedUser?.uid || basePrincipal.uid,
173
+ displayName: resolvedDisplayName,
174
+ handle: resolvedHandle,
175
+ accountHandle: resolvedHandle,
176
+ firstName: resolvedUser?.firstName || basePrincipal.firstName,
177
+ lastName: resolvedUser?.lastName || basePrincipal.lastName,
178
+ email: resolvedUser?.email || basePrincipal.email,
179
+ avatarUrl: resolvedUser?.avatarUrl || basePrincipal.avatarUrl,
180
+ origin,
181
+ };
182
+ }, [
183
+ basePrincipal,
184
+ resolvedOrganization?.name,
185
+ resolvedOrganization?.handle,
186
+ resolvedUser?.uid,
187
+ resolvedUser?.displayName,
188
+ resolvedUser?.handle,
189
+ resolvedUser?.firstName,
190
+ resolvedUser?.lastName,
191
+ resolvedUser?.email,
192
+ resolvedUser?.avatarUrl,
193
+ resolvedUser?.origin,
194
+ ]);
195
+ return (_jsxs(Box, { sx: {
196
+ display: 'inline-flex',
197
+ alignItems: 'center',
198
+ gap: 2,
199
+ px: 2,
200
+ py: 1,
201
+ border: '1px solid',
202
+ borderColor: 'border.default',
203
+ borderRadius: 2,
204
+ bg: 'canvas.subtle',
205
+ ...sx,
206
+ }, 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 }))] }));
207
+ };
208
+ export default PrincipalBadge;
@@ -0,0 +1,7 @@
1
+ import type { ReactNode } from 'react';
2
+ export type PrincipalBannerProps = {
3
+ caption?: string;
4
+ rightContent?: ReactNode;
5
+ };
6
+ export declare const PrincipalBanner: ({ caption, rightContent, }: PrincipalBannerProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default PrincipalBanner;
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * PrincipalBanner — displays the currently selected principal
8
+ * (user, organization, or team) with a colored visual so a user
9
+ * can immediately see which principal a settings page applies to.
10
+ */
11
+ import { Box, Label, Text } from '@primer/react';
12
+ import { OrganizationIcon, PeopleIcon, PersonIcon, } from '@primer/octicons-react';
13
+ import { useSelectedPrincipal } from '../../hooks/useSelectedPrincipal.js';
14
+ import { useIAMStore } from '../../state/substates/index.js';
15
+ export const PrincipalBanner = ({ caption, rightContent, }) => {
16
+ const { user } = useIAMStore();
17
+ const { selectedPrincipalKind, selectedPrincipalHandle, selectedTeamParentOrganizationHandle, } = useSelectedPrincipal();
18
+ const isOrganization = selectedPrincipalKind === 'organization';
19
+ const isTeam = selectedPrincipalKind === 'team';
20
+ const handle = isOrganization
21
+ ? selectedPrincipalHandle || ''
22
+ : isTeam
23
+ ? `${selectedTeamParentOrganizationHandle || 'organization'}/${selectedPrincipalHandle || 'team'}`
24
+ : user?.handle || selectedPrincipalHandle || '';
25
+ const Icon = isOrganization
26
+ ? OrganizationIcon
27
+ : isTeam
28
+ ? PeopleIcon
29
+ : PersonIcon;
30
+ const accent = isOrganization ? 'done' : isTeam ? 'attention' : 'accent';
31
+ const bg = isOrganization
32
+ ? 'done.subtle'
33
+ : isTeam
34
+ ? 'attention.subtle'
35
+ : 'accent.subtle';
36
+ const borderColor = isOrganization
37
+ ? 'done.muted'
38
+ : isTeam
39
+ ? 'attention.muted'
40
+ : 'accent.muted';
41
+ 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: {
69
+ color: 'fg.muted',
70
+ fontSize: 0,
71
+ textTransform: 'uppercase',
72
+ letterSpacing: '0.04em',
73
+ }, children: "Principal" }), _jsx(Label, { variant: accent, children: isOrganization ? 'Organization' : isTeam ? 'Team' : 'User' })] }), _jsx(Text, { as: "p", sx: { m: 0, mt: 1, fontWeight: 600, color: 'fg.default' }, children: handle
74
+ ? `@${handle}`
75
+ : isOrganization
76
+ ? 'Organization'
77
+ : isTeam
78
+ ? 'Team'
79
+ : 'User' }), caption && (_jsx(Text, { as: "p", sx: { m: 0, mt: 1, color: 'fg.muted', fontSize: 1 }, children: caption }))] }), rightContent ? (_jsx(Box, { sx: {
80
+ flex: ['1 1 100%', '0 0 auto'],
81
+ width: ['100%', 'min(640px, 58%)'],
82
+ }, children: rightContent })) : null] }));
83
+ };
84
+ export default PrincipalBanner;
@@ -0,0 +1,23 @@
1
+ export type PrincipalKind = 'user' | 'team' | 'organization';
2
+ export type PrincipalDetailsOverlayProps = {
3
+ kind: PrincipalKind;
4
+ uid?: string;
5
+ displayName: string;
6
+ handle?: string;
7
+ accountHandle?: string;
8
+ firstName?: string;
9
+ lastName?: string;
10
+ email?: string;
11
+ origin?: string;
12
+ avatarUrl?: string;
13
+ isAdmin?: boolean;
14
+ };
15
+ export declare function buildPrincipalProfilePath({ kind, uid, handle, accountHandle, isAdmin, }: {
16
+ kind: PrincipalKind;
17
+ uid?: string;
18
+ handle?: string;
19
+ accountHandle?: string;
20
+ isAdmin?: boolean;
21
+ }): string | null;
22
+ export declare function PrincipalDetailsOverlay({ kind, uid, displayName, handle, accountHandle, firstName, lastName, email, origin, avatarUrl, isAdmin, }: PrincipalDetailsOverlayProps): JSX.Element;
23
+ export default PrincipalDetailsOverlay;
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ import { ActionMenu, Box, Button, Text } from '@primer/react';
7
+ import { useNavigate } from '../../hooks/index.js';
8
+ import { PrincipalAvatar } from './PrincipalAvatar.js';
9
+ function normalize(value) {
10
+ return (value || '').trim();
11
+ }
12
+ export function buildPrincipalProfilePath({ kind, uid, handle, accountHandle, isAdmin, }) {
13
+ const normalizedUid = normalize(uid);
14
+ const normalizedHandle = normalize(handle);
15
+ const normalizedAccountHandle = normalize(accountHandle);
16
+ const safeHandle = normalizedHandle && normalizedHandle !== normalizedUid
17
+ ? normalizedHandle
18
+ : '';
19
+ if (kind === 'user') {
20
+ if (isAdmin && normalizedUid) {
21
+ return `/admin/management/iam/users/${normalizedUid}`;
22
+ }
23
+ if (safeHandle) {
24
+ return `/${safeHandle}`;
25
+ }
26
+ return null;
27
+ }
28
+ if (kind === 'team') {
29
+ if (normalizedAccountHandle && safeHandle) {
30
+ return `/${normalizedAccountHandle}/team/${safeHandle}`;
31
+ }
32
+ if (safeHandle.includes('/')) {
33
+ const [orgHandle, teamHandle] = safeHandle.split('/', 2);
34
+ if (orgHandle && teamHandle) {
35
+ return `/${orgHandle}/team/${teamHandle}`;
36
+ }
37
+ }
38
+ if (safeHandle) {
39
+ return `/datalayer/team/${safeHandle}`;
40
+ }
41
+ return null;
42
+ }
43
+ if (safeHandle) {
44
+ return `/${safeHandle}`;
45
+ }
46
+ return null;
47
+ }
48
+ export function PrincipalDetailsOverlay({ kind, uid, displayName, handle, accountHandle, firstName, lastName, email, origin, avatarUrl, isAdmin = false, }) {
49
+ const navigate = useNavigate();
50
+ const normalizedDisplayName = normalize(displayName) ||
51
+ normalize(handle) ||
52
+ normalize(uid) ||
53
+ 'Principal';
54
+ const normalizedHandle = normalize(handle);
55
+ const normalizedUid = normalize(uid);
56
+ const targetPath = buildPrincipalProfilePath({
57
+ kind,
58
+ uid: normalizedUid,
59
+ handle: normalizedHandle,
60
+ accountHandle,
61
+ isAdmin,
62
+ });
63
+ return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Box, { as: "button", type: "button", sx: {
64
+ fontWeight: 'semibold',
65
+ color: 'accent.fg',
66
+ textDecoration: 'underline',
67
+ background: 'transparent',
68
+ border: 0,
69
+ padding: 0,
70
+ margin: 0,
71
+ cursor: 'pointer',
72
+ ':hover': {
73
+ textDecoration: 'underline',
74
+ },
75
+ }, children: normalizedDisplayName }) }), _jsx(ActionMenu.Overlay, { width: "large", children: _jsxs(Box, { sx: { display: 'grid', gap: 3, p: 4, minWidth: 420 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(PrincipalAvatar, { kind: kind, avatarUrl: avatarUrl, alt: normalizedDisplayName, size: 40 }), _jsxs(Box, { sx: { display: 'grid', gap: 0.5 }, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: normalizedDisplayName }), normalizedHandle ? (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["@", normalizedHandle] })) : null] })] }), _jsxs(Box, { sx: {
76
+ display: 'grid',
77
+ gridTemplateColumns: '110px 1fr',
78
+ gap: 1,
79
+ alignItems: 'baseline',
80
+ }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Type" }), _jsx(Text, { sx: { fontSize: 1 }, children: kind }), normalizedHandle ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Handle" }), _jsxs(Text, { sx: { fontSize: 1 }, children: ["@", normalizedHandle] })] })) : null, normalizedUid ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "UID" }), _jsx(Text, { sx: { fontSize: 1 }, children: normalizedUid })] })) : null, kind === 'user' ? (_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' }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Origin" }), _jsx(Text, { sx: { fontSize: 1 }, children: origin || 'Datalayer' }), email ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Email" }), _jsx(Text, { sx: { fontSize: 1 }, children: email })] })) : null] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Origin" }), _jsx(Text, { sx: { fontSize: 1 }, children: origin || 'Datalayer' })] }))] }), _jsx(Box, { sx: { display: 'flex', justifyContent: 'flex-end' }, children: _jsx(Button, { size: "small", onClick: () => {
81
+ if (targetPath) {
82
+ navigate(targetPath);
83
+ }
84
+ }, disabled: !targetPath, children: "View profile" }) })] }) })] }));
85
+ }
86
+ export default PrincipalDetailsOverlay;
@@ -0,0 +1,14 @@
1
+ export type PrincipalSwitcherMenuProps = {
2
+ maxLabelChars?: number;
3
+ fullWidth?: boolean;
4
+ showClosedBorder?: boolean;
5
+ };
6
+ /**
7
+ * PrincipalSwitcherMenu — the *only* component allowed to write to the
8
+ * principal store and the billable account store. It keeps both stores in
9
+ * sync per the rule:
10
+ * - selecting a user/org principal → billable account = same user/org
11
+ * - selecting a team principal → billable account = the team's parent org
12
+ */
13
+ export declare function PrincipalSwitcherMenu({ maxLabelChars, fullWidth, showClosedBorder, }: PrincipalSwitcherMenuProps): JSX.Element;
14
+ export default PrincipalSwitcherMenu;