@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.
- package/lib/components/billing/BillableAccountSelect.d.ts +35 -0
- package/lib/components/billing/BillableAccountSelect.js +340 -0
- package/lib/components/billing/index.d.ts +1 -0
- package/lib/components/billing/index.js +5 -0
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/principal/Principal.d.ts +37 -0
- package/lib/components/principal/Principal.js +54 -0
- package/lib/components/principal/PrincipalAvatar.d.ts +10 -0
- package/lib/components/principal/PrincipalAvatar.js +55 -0
- package/lib/components/principal/PrincipalBadge.d.ts +20 -0
- package/lib/components/principal/PrincipalBadge.js +208 -0
- package/lib/components/principal/PrincipalBanner.d.ts +7 -0
- package/lib/components/principal/PrincipalBanner.js +84 -0
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +23 -0
- package/lib/components/principal/PrincipalDetailsOverlay.js +86 -0
- package/lib/components/principal/PrincipalSwitcherMenu.d.ts +14 -0
- package/lib/components/principal/PrincipalSwitcherMenu.js +287 -0
- package/lib/components/principal/index.d.ts +7 -0
- package/lib/components/principal/index.js +10 -0
- package/lib/components/sharing/ShareAccessComponent.d.ts +18 -0
- package/lib/components/sharing/ShareAccessComponent.js +1368 -0
- package/lib/components/sharing/SharingEditor.d.ts +20 -0
- package/lib/components/sharing/SharingEditor.js +65 -0
- package/lib/components/sharing/index.d.ts +9 -0
- package/lib/components/sharing/index.js +12 -0
- package/lib/hooks/index.d.ts +5 -0
- package/lib/hooks/index.js +5 -0
- package/lib/hooks/useBillableAccountStore.d.ts +31 -0
- package/lib/hooks/useBillableAccountStore.js +53 -0
- package/lib/hooks/usePrincipalStore.d.ts +41 -0
- package/lib/hooks/usePrincipalStore.js +101 -0
- package/lib/hooks/useSelectedBillableAccount.d.ts +14 -0
- package/lib/hooks/useSelectedBillableAccount.js +36 -0
- package/lib/hooks/useSelectedPrincipal.d.ts +17 -0
- package/lib/hooks/useSelectedPrincipal.js +29 -0
- package/lib/hooks/useUsageRefreshStore.d.ts +8 -0
- package/lib/hooks/useUsageRefreshStore.js +16 -0
- package/lib/utils/Handles.d.ts +3 -0
- package/lib/utils/Handles.js +53 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/package.json +1 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type SharingAccessLevel = 'view' | 'update' | 'execute';
|
|
2
|
+
export type SharingLevelPayload = {
|
|
3
|
+
userUids?: string[];
|
|
4
|
+
teamUids?: string[];
|
|
5
|
+
organizationUids?: string[];
|
|
6
|
+
};
|
|
7
|
+
export type SharingPayload = {
|
|
8
|
+
access?: Partial<Record<SharingAccessLevel, SharingLevelPayload>>;
|
|
9
|
+
};
|
|
10
|
+
export declare const EMPTY_SHARING_PAYLOAD: SharingPayload;
|
|
11
|
+
export type SharingEditorProps = {
|
|
12
|
+
value: SharingPayload;
|
|
13
|
+
onChange: (next: SharingPayload) => void;
|
|
14
|
+
label?: string;
|
|
15
|
+
caption?: string;
|
|
16
|
+
rows?: number;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare function SharingEditor({ value, onChange, label, caption, rows, disabled, }: SharingEditorProps): JSX.Element;
|
|
20
|
+
export default SharingEditor;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* SharingEditor — inline editor for the sharing payload shape used by
|
|
8
|
+
* `ShareAccessComponent` ACL endpoints.
|
|
9
|
+
*
|
|
10
|
+
* Unlike `ShareAccessComponent` (which is bound to a server-side resource
|
|
11
|
+
* via `requestUrl`), this component edits a free-form
|
|
12
|
+
* `{ access: { view/update/execute: { userUids, teamUids, organizationUids } } }`
|
|
13
|
+
* blob in memory. It is intended for "create" flows where the resource does
|
|
14
|
+
* not yet exist and the sharing payload must be POSTed alongside the rest of
|
|
15
|
+
* the configuration.
|
|
16
|
+
*
|
|
17
|
+
* This is a scaffold: it currently exposes a structured JSON editor with
|
|
18
|
+
* validation and the canonical default shape. Future iterations can replace
|
|
19
|
+
* the textarea with the same principal-picker UI used by
|
|
20
|
+
* `ShareAccessComponent`.
|
|
21
|
+
*/
|
|
22
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
23
|
+
import { Box } from '@datalayer/primer-addons';
|
|
24
|
+
import { FormControl, Text, Textarea } from '@primer/react';
|
|
25
|
+
export const EMPTY_SHARING_PAYLOAD = {
|
|
26
|
+
access: {
|
|
27
|
+
view: { userUids: [], teamUids: [], organizationUids: [] },
|
|
28
|
+
update: { userUids: [], teamUids: [], organizationUids: [] },
|
|
29
|
+
execute: { userUids: [], teamUids: [], organizationUids: [] },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const stringify = (value) => {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.stringify(value ?? {}, null, 2);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return '{}';
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
export function SharingEditor({ value, onChange, label = 'Sharing', caption = 'Edit the sharing payload. Each access level (view/update/execute) can grant access to user, team, and organization UIDs.', rows = 10, disabled = false, }) {
|
|
41
|
+
const initial = useMemo(() => stringify(value), [value]);
|
|
42
|
+
const [raw, setRaw] = useState(initial);
|
|
43
|
+
const [error, setError] = useState(null);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setRaw(stringify(value));
|
|
46
|
+
}, [value]);
|
|
47
|
+
return (_jsxs(FormControl, { disabled: disabled, children: [_jsx(FormControl.Label, { children: label }), _jsx(Textarea, { rows: rows, value: raw, onChange: event => {
|
|
48
|
+
const next = event.target.value;
|
|
49
|
+
setRaw(next);
|
|
50
|
+
if (!next.trim()) {
|
|
51
|
+
setError(null);
|
|
52
|
+
onChange({});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(next);
|
|
57
|
+
setError(null);
|
|
58
|
+
onChange(parsed);
|
|
59
|
+
}
|
|
60
|
+
catch (reason) {
|
|
61
|
+
setError(reason?.message || 'Invalid JSON');
|
|
62
|
+
}
|
|
63
|
+
}, sx: { width: '100%', fontFamily: 'mono' } }), _jsx(FormControl.Caption, { children: caption }), error && (_jsx(Box, { sx: { mt: 1 }, children: _jsx(Text, { sx: { color: 'danger.fg', fontSize: 1 }, children: error }) }))] }));
|
|
64
|
+
}
|
|
65
|
+
export default SharingEditor;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../principal/Principal';
|
|
2
|
+
export * from '../principal/PrincipalAvatar';
|
|
3
|
+
export * from '../principal/PrincipalBadge';
|
|
4
|
+
export * from '../principal/PrincipalBanner';
|
|
5
|
+
export { buildPrincipalProfilePath, PrincipalDetailsOverlay, } from '../principal/PrincipalDetailsOverlay';
|
|
6
|
+
export type { PrincipalDetailsOverlayProps } from '../principal/PrincipalDetailsOverlay';
|
|
7
|
+
export * from '../principal/PrincipalSwitcherMenu';
|
|
8
|
+
export * from './ShareAccessComponent';
|
|
9
|
+
export * from './SharingEditor';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
export * from '../principal/Principal.js';
|
|
6
|
+
export * from '../principal/PrincipalAvatar.js';
|
|
7
|
+
export * from '../principal/PrincipalBadge.js';
|
|
8
|
+
export * from '../principal/PrincipalBanner.js';
|
|
9
|
+
export { buildPrincipalProfilePath, PrincipalDetailsOverlay, } from '../principal/PrincipalDetailsOverlay.js';
|
|
10
|
+
export * from '../principal/PrincipalSwitcherMenu.js';
|
|
11
|
+
export * from './ShareAccessComponent.js';
|
|
12
|
+
export * from './SharingEditor.js';
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -28,5 +28,10 @@ export * from './useUser';
|
|
|
28
28
|
export * from './useProjects';
|
|
29
29
|
export * from './useProjectStore';
|
|
30
30
|
export * from './useMobile';
|
|
31
|
+
export * from './useUsageRefreshStore';
|
|
32
|
+
export * from './usePrincipalStore';
|
|
33
|
+
export * from './useBillableAccountStore';
|
|
34
|
+
export * from './useSelectedPrincipal';
|
|
35
|
+
export * from './useSelectedBillableAccount';
|
|
31
36
|
export * from './useVisibilityObserver';
|
|
32
37
|
export * from './useWindowSize';
|
package/lib/hooks/index.js
CHANGED
|
@@ -33,5 +33,10 @@ export * from './useUser.js';
|
|
|
33
33
|
export * from './useProjects.js';
|
|
34
34
|
export * from './useProjectStore.js';
|
|
35
35
|
export * from './useMobile.js';
|
|
36
|
+
export * from './useUsageRefreshStore.js';
|
|
37
|
+
export * from './usePrincipalStore.js';
|
|
38
|
+
export * from './useBillableAccountStore.js';
|
|
39
|
+
export * from './useSelectedPrincipal.js';
|
|
40
|
+
export * from './useSelectedBillableAccount.js';
|
|
36
41
|
export * from './useVisibilityObserver.js';
|
|
37
42
|
export * from './useWindowSize.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind of billable account currently in scope.
|
|
3
|
+
*
|
|
4
|
+
* An account is the *billable* principal — only users and organizations
|
|
5
|
+
* are accounts. Teams are NOT accounts; when a team is the selected
|
|
6
|
+
* principal, the billable account is the team's parent organization.
|
|
7
|
+
*/
|
|
8
|
+
export type BillableAccountKind = 'user' | 'organization';
|
|
9
|
+
export type BillableAccountState = {
|
|
10
|
+
billableAccountKind: BillableAccountKind;
|
|
11
|
+
billableAccountUid?: string;
|
|
12
|
+
billableAccountHandle?: string;
|
|
13
|
+
setBillableAccount: (args: {
|
|
14
|
+
kind: BillableAccountKind;
|
|
15
|
+
uid: string;
|
|
16
|
+
handle: string;
|
|
17
|
+
}) => void;
|
|
18
|
+
resetBillableAccount: () => void;
|
|
19
|
+
};
|
|
20
|
+
export declare const useBillableAccountStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<BillableAccountState>, "persist"> & {
|
|
21
|
+
persist: {
|
|
22
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<BillableAccountState, unknown>>) => void;
|
|
23
|
+
clearStorage: () => void;
|
|
24
|
+
rehydrate: () => Promise<void> | void;
|
|
25
|
+
hasHydrated: () => boolean;
|
|
26
|
+
onHydrate: (fn: (state: BillableAccountState) => void) => () => void;
|
|
27
|
+
onFinishHydration: (fn: (state: BillableAccountState) => void) => () => void;
|
|
28
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<BillableAccountState, unknown>>;
|
|
29
|
+
};
|
|
30
|
+
}>;
|
|
31
|
+
export default useBillableAccountStore;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { create } from 'zustand';
|
|
6
|
+
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
7
|
+
import { useUsageRefreshStore } from './useUsageRefreshStore.js';
|
|
8
|
+
export const useBillableAccountStore = create()(persist(set => ({
|
|
9
|
+
billableAccountKind: 'user',
|
|
10
|
+
billableAccountUid: undefined,
|
|
11
|
+
billableAccountHandle: undefined,
|
|
12
|
+
setBillableAccount: ({ kind, uid, handle }) => set(state => {
|
|
13
|
+
const unchanged = state.billableAccountKind === kind &&
|
|
14
|
+
state.billableAccountUid === uid &&
|
|
15
|
+
state.billableAccountHandle === handle;
|
|
16
|
+
if (unchanged) {
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
19
|
+
useUsageRefreshStore
|
|
20
|
+
.getState()
|
|
21
|
+
.requestUsageRefresh('billable-account-changed');
|
|
22
|
+
return {
|
|
23
|
+
billableAccountKind: kind,
|
|
24
|
+
billableAccountUid: uid,
|
|
25
|
+
billableAccountHandle: handle,
|
|
26
|
+
};
|
|
27
|
+
}),
|
|
28
|
+
resetBillableAccount: () => set(state => {
|
|
29
|
+
const unchanged = state.billableAccountKind === 'user' &&
|
|
30
|
+
state.billableAccountUid === undefined &&
|
|
31
|
+
state.billableAccountHandle === undefined;
|
|
32
|
+
if (unchanged) {
|
|
33
|
+
return state;
|
|
34
|
+
}
|
|
35
|
+
useUsageRefreshStore
|
|
36
|
+
.getState()
|
|
37
|
+
.requestUsageRefresh('billable-account-reset');
|
|
38
|
+
return {
|
|
39
|
+
billableAccountKind: 'user',
|
|
40
|
+
billableAccountUid: undefined,
|
|
41
|
+
billableAccountHandle: undefined,
|
|
42
|
+
};
|
|
43
|
+
}),
|
|
44
|
+
}), {
|
|
45
|
+
name: 'datalayer-billable-account',
|
|
46
|
+
storage: createJSONStorage(() => localStorage),
|
|
47
|
+
partialize: state => ({
|
|
48
|
+
billableAccountKind: state.billableAccountKind,
|
|
49
|
+
billableAccountUid: state.billableAccountUid,
|
|
50
|
+
billableAccountHandle: state.billableAccountHandle,
|
|
51
|
+
}),
|
|
52
|
+
}));
|
|
53
|
+
export default useBillableAccountStore;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind of principal currently selected in the Principal Switcher.
|
|
3
|
+
*
|
|
4
|
+
* A principal is the entity used for *UI scoping* — visibility, creation,
|
|
5
|
+
* and sharing of artifacts. Only user / organization / team are principals.
|
|
6
|
+
* Agents are NOT principals (an agent is owned by an account).
|
|
7
|
+
*/
|
|
8
|
+
export type PrincipalKind = 'user' | 'organization' | 'team';
|
|
9
|
+
export type PrincipalState = {
|
|
10
|
+
/** Kind of the currently selected principal. */
|
|
11
|
+
selectedPrincipalKind: PrincipalKind;
|
|
12
|
+
/** UID of the selected principal (user UID, org UID, or team UID). */
|
|
13
|
+
selectedPrincipalUid?: string;
|
|
14
|
+
/** Handle of the selected principal. */
|
|
15
|
+
selectedPrincipalHandle?: string;
|
|
16
|
+
/** Parent organization UID — set only when `selectedPrincipalKind === 'team'`. */
|
|
17
|
+
selectedTeamParentOrganizationUid?: string;
|
|
18
|
+
/** Parent organization handle — set only when `selectedPrincipalKind === 'team'`. */
|
|
19
|
+
selectedTeamParentOrganizationHandle?: string;
|
|
20
|
+
selectUserPrincipal: (uid: string, handle: string) => void;
|
|
21
|
+
selectOrganizationPrincipal: (uid: string, handle: string) => void;
|
|
22
|
+
selectTeamPrincipal: (args: {
|
|
23
|
+
teamUid: string;
|
|
24
|
+
teamHandle: string;
|
|
25
|
+
organizationUid: string;
|
|
26
|
+
organizationHandle: string;
|
|
27
|
+
}) => void;
|
|
28
|
+
resetPrincipal: () => void;
|
|
29
|
+
};
|
|
30
|
+
export declare const usePrincipalStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<PrincipalState>, "persist"> & {
|
|
31
|
+
persist: {
|
|
32
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<PrincipalState, unknown>>) => void;
|
|
33
|
+
clearStorage: () => void;
|
|
34
|
+
rehydrate: () => Promise<void> | void;
|
|
35
|
+
hasHydrated: () => boolean;
|
|
36
|
+
onHydrate: (fn: (state: PrincipalState) => void) => () => void;
|
|
37
|
+
onFinishHydration: (fn: (state: PrincipalState) => void) => () => void;
|
|
38
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<PrincipalState, unknown>>;
|
|
39
|
+
};
|
|
40
|
+
}>;
|
|
41
|
+
export default usePrincipalStore;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { create } from 'zustand';
|
|
6
|
+
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
7
|
+
import { useUsageRefreshStore } from './useUsageRefreshStore.js';
|
|
8
|
+
export const usePrincipalStore = create()(persist(set => ({
|
|
9
|
+
selectedPrincipalKind: 'user',
|
|
10
|
+
selectedPrincipalUid: undefined,
|
|
11
|
+
selectedPrincipalHandle: undefined,
|
|
12
|
+
selectedTeamParentOrganizationUid: undefined,
|
|
13
|
+
selectedTeamParentOrganizationHandle: undefined,
|
|
14
|
+
selectUserPrincipal: (uid, handle) => set(state => {
|
|
15
|
+
const unchanged = state.selectedPrincipalKind === 'user' &&
|
|
16
|
+
state.selectedPrincipalUid === uid &&
|
|
17
|
+
state.selectedPrincipalHandle === handle;
|
|
18
|
+
if (unchanged) {
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
useUsageRefreshStore
|
|
22
|
+
.getState()
|
|
23
|
+
.requestUsageRefresh('principal-user-changed');
|
|
24
|
+
return {
|
|
25
|
+
selectedPrincipalKind: 'user',
|
|
26
|
+
selectedPrincipalUid: uid,
|
|
27
|
+
selectedPrincipalHandle: handle,
|
|
28
|
+
selectedTeamParentOrganizationUid: undefined,
|
|
29
|
+
selectedTeamParentOrganizationHandle: undefined,
|
|
30
|
+
};
|
|
31
|
+
}),
|
|
32
|
+
selectOrganizationPrincipal: (uid, handle) => set(state => {
|
|
33
|
+
const unchanged = state.selectedPrincipalKind === 'organization' &&
|
|
34
|
+
state.selectedPrincipalUid === uid &&
|
|
35
|
+
state.selectedPrincipalHandle === handle;
|
|
36
|
+
if (unchanged) {
|
|
37
|
+
return state;
|
|
38
|
+
}
|
|
39
|
+
useUsageRefreshStore
|
|
40
|
+
.getState()
|
|
41
|
+
.requestUsageRefresh('principal-organization-changed');
|
|
42
|
+
return {
|
|
43
|
+
selectedPrincipalKind: 'organization',
|
|
44
|
+
selectedPrincipalUid: uid,
|
|
45
|
+
selectedPrincipalHandle: handle,
|
|
46
|
+
selectedTeamParentOrganizationUid: undefined,
|
|
47
|
+
selectedTeamParentOrganizationHandle: undefined,
|
|
48
|
+
};
|
|
49
|
+
}),
|
|
50
|
+
selectTeamPrincipal: ({ teamUid, teamHandle, organizationUid, organizationHandle, }) => set(state => {
|
|
51
|
+
const unchanged = state.selectedPrincipalKind === 'team' &&
|
|
52
|
+
state.selectedPrincipalUid === teamUid &&
|
|
53
|
+
state.selectedPrincipalHandle === teamHandle &&
|
|
54
|
+
state.selectedTeamParentOrganizationUid === organizationUid &&
|
|
55
|
+
state.selectedTeamParentOrganizationHandle === organizationHandle;
|
|
56
|
+
if (unchanged) {
|
|
57
|
+
return state;
|
|
58
|
+
}
|
|
59
|
+
useUsageRefreshStore
|
|
60
|
+
.getState()
|
|
61
|
+
.requestUsageRefresh('principal-team-changed');
|
|
62
|
+
return {
|
|
63
|
+
selectedPrincipalKind: 'team',
|
|
64
|
+
selectedPrincipalUid: teamUid,
|
|
65
|
+
selectedPrincipalHandle: teamHandle,
|
|
66
|
+
selectedTeamParentOrganizationUid: organizationUid,
|
|
67
|
+
selectedTeamParentOrganizationHandle: organizationHandle,
|
|
68
|
+
};
|
|
69
|
+
}),
|
|
70
|
+
resetPrincipal: () => set(state => {
|
|
71
|
+
const unchanged = state.selectedPrincipalKind === 'user' &&
|
|
72
|
+
state.selectedPrincipalUid === undefined &&
|
|
73
|
+
state.selectedPrincipalHandle === undefined &&
|
|
74
|
+
state.selectedTeamParentOrganizationUid === undefined &&
|
|
75
|
+
state.selectedTeamParentOrganizationHandle === undefined;
|
|
76
|
+
if (unchanged) {
|
|
77
|
+
return state;
|
|
78
|
+
}
|
|
79
|
+
useUsageRefreshStore
|
|
80
|
+
.getState()
|
|
81
|
+
.requestUsageRefresh('principal-reset');
|
|
82
|
+
return {
|
|
83
|
+
selectedPrincipalKind: 'user',
|
|
84
|
+
selectedPrincipalUid: undefined,
|
|
85
|
+
selectedPrincipalHandle: undefined,
|
|
86
|
+
selectedTeamParentOrganizationUid: undefined,
|
|
87
|
+
selectedTeamParentOrganizationHandle: undefined,
|
|
88
|
+
};
|
|
89
|
+
}),
|
|
90
|
+
}), {
|
|
91
|
+
name: 'datalayer-principal',
|
|
92
|
+
storage: createJSONStorage(() => localStorage),
|
|
93
|
+
partialize: state => ({
|
|
94
|
+
selectedPrincipalKind: state.selectedPrincipalKind,
|
|
95
|
+
selectedPrincipalUid: state.selectedPrincipalUid,
|
|
96
|
+
selectedPrincipalHandle: state.selectedPrincipalHandle,
|
|
97
|
+
selectedTeamParentOrganizationUid: state.selectedTeamParentOrganizationUid,
|
|
98
|
+
selectedTeamParentOrganizationHandle: state.selectedTeamParentOrganizationHandle,
|
|
99
|
+
}),
|
|
100
|
+
}));
|
|
101
|
+
export default usePrincipalStore;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only selector for the currently scoped billable account.
|
|
3
|
+
*
|
|
4
|
+
* Use this for billing, quotas, plans, credits, agents, and runtime capacity.
|
|
5
|
+
* For visibility/creation/sharing scope, use {@link useSelectedPrincipal}.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useSelectedBillableAccount(): {
|
|
8
|
+
billableAccountKind: string;
|
|
9
|
+
billableAccountUid: string | undefined;
|
|
10
|
+
billableAccountHandle: string | undefined;
|
|
11
|
+
isUserAccount: boolean;
|
|
12
|
+
isOrganizationAccount: boolean;
|
|
13
|
+
};
|
|
14
|
+
export default useSelectedBillableAccount;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { useBillableAccountStore } from './useBillableAccountStore.js';
|
|
6
|
+
import { useSelectedPrincipal } from './useSelectedPrincipal.js';
|
|
7
|
+
/**
|
|
8
|
+
* Read-only selector for the currently scoped billable account.
|
|
9
|
+
*
|
|
10
|
+
* Use this for billing, quotas, plans, credits, agents, and runtime capacity.
|
|
11
|
+
* For visibility/creation/sharing scope, use {@link useSelectedPrincipal}.
|
|
12
|
+
*/
|
|
13
|
+
export function useSelectedBillableAccount() {
|
|
14
|
+
const persistedUid = useBillableAccountStore(state => state.billableAccountUid);
|
|
15
|
+
const persistedHandle = useBillableAccountStore(state => state.billableAccountHandle);
|
|
16
|
+
const { selectedPrincipalKind, selectedPrincipalUid, selectedPrincipalHandle, selectedTeamParentOrganizationUid, selectedTeamParentOrganizationHandle, } = useSelectedPrincipal();
|
|
17
|
+
const billableAccountKind = selectedPrincipalKind === 'team'
|
|
18
|
+
? 'organization'
|
|
19
|
+
: selectedPrincipalKind === 'organization'
|
|
20
|
+
? 'organization'
|
|
21
|
+
: 'user';
|
|
22
|
+
const billableAccountUid = selectedPrincipalKind === 'team'
|
|
23
|
+
? selectedTeamParentOrganizationUid || persistedUid
|
|
24
|
+
: selectedPrincipalUid || persistedUid;
|
|
25
|
+
const billableAccountHandle = selectedPrincipalKind === 'team'
|
|
26
|
+
? selectedTeamParentOrganizationHandle || persistedHandle
|
|
27
|
+
: selectedPrincipalHandle || persistedHandle;
|
|
28
|
+
return {
|
|
29
|
+
billableAccountKind,
|
|
30
|
+
billableAccountUid,
|
|
31
|
+
billableAccountHandle,
|
|
32
|
+
isUserAccount: billableAccountKind === 'user',
|
|
33
|
+
isOrganizationAccount: billableAccountKind === 'organization',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export default useSelectedBillableAccount;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only selector for the currently selected principal (UI scope).
|
|
3
|
+
*
|
|
4
|
+
* Use this for visibility, creation, and sharing of artifacts.
|
|
5
|
+
* For billing, quotas, plans, and agents, use {@link useSelectedBillableAccount}.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useSelectedPrincipal(): {
|
|
8
|
+
selectedPrincipalKind: import("./usePrincipalStore").PrincipalKind;
|
|
9
|
+
selectedPrincipalUid: string | undefined;
|
|
10
|
+
selectedPrincipalHandle: string | undefined;
|
|
11
|
+
selectedTeamParentOrganizationUid: string | undefined;
|
|
12
|
+
selectedTeamParentOrganizationHandle: string | undefined;
|
|
13
|
+
isUserSelected: boolean;
|
|
14
|
+
isOrganizationSelected: boolean;
|
|
15
|
+
isTeamSelected: boolean;
|
|
16
|
+
};
|
|
17
|
+
export default useSelectedPrincipal;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { usePrincipalStore } from './usePrincipalStore.js';
|
|
6
|
+
/**
|
|
7
|
+
* Read-only selector for the currently selected principal (UI scope).
|
|
8
|
+
*
|
|
9
|
+
* Use this for visibility, creation, and sharing of artifacts.
|
|
10
|
+
* For billing, quotas, plans, and agents, use {@link useSelectedBillableAccount}.
|
|
11
|
+
*/
|
|
12
|
+
export function useSelectedPrincipal() {
|
|
13
|
+
const selectedPrincipalKind = usePrincipalStore(state => state.selectedPrincipalKind);
|
|
14
|
+
const selectedPrincipalUid = usePrincipalStore(state => state.selectedPrincipalUid);
|
|
15
|
+
const selectedPrincipalHandle = usePrincipalStore(state => state.selectedPrincipalHandle);
|
|
16
|
+
const selectedTeamParentOrganizationUid = usePrincipalStore(state => state.selectedTeamParentOrganizationUid);
|
|
17
|
+
const selectedTeamParentOrganizationHandle = usePrincipalStore(state => state.selectedTeamParentOrganizationHandle);
|
|
18
|
+
return {
|
|
19
|
+
selectedPrincipalKind,
|
|
20
|
+
selectedPrincipalUid,
|
|
21
|
+
selectedPrincipalHandle,
|
|
22
|
+
selectedTeamParentOrganizationUid,
|
|
23
|
+
selectedTeamParentOrganizationHandle,
|
|
24
|
+
isUserSelected: selectedPrincipalKind === 'user',
|
|
25
|
+
isOrganizationSelected: selectedPrincipalKind === 'organization',
|
|
26
|
+
isTeamSelected: selectedPrincipalKind === 'team',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export default useSelectedPrincipal;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type UsageRefreshState = {
|
|
2
|
+
refreshToken: number;
|
|
3
|
+
lastReason?: string;
|
|
4
|
+
lastRequestedAt?: number;
|
|
5
|
+
requestUsageRefresh: (reason?: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const useUsageRefreshStore: import("zustand").UseBoundStore<import("zustand").StoreApi<UsageRefreshState>>;
|
|
8
|
+
export default useUsageRefreshStore;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { create } from 'zustand';
|
|
6
|
+
export const useUsageRefreshStore = create()(set => ({
|
|
7
|
+
refreshToken: 0,
|
|
8
|
+
lastReason: undefined,
|
|
9
|
+
lastRequestedAt: undefined,
|
|
10
|
+
requestUsageRefresh: (reason) => set(state => ({
|
|
11
|
+
refreshToken: state.refreshToken + 1,
|
|
12
|
+
lastReason: reason,
|
|
13
|
+
lastRequestedAt: Date.now(),
|
|
14
|
+
})),
|
|
15
|
+
}));
|
|
16
|
+
export default useUsageRefreshStore;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
const EXT_URN_PREFIX = 'urn:dla:iam:ext::';
|
|
6
|
+
export function isExternalUrnHandle(handle) {
|
|
7
|
+
const normalized = (handle || '').trim().toLowerCase();
|
|
8
|
+
return normalized.startsWith(EXT_URN_PREFIX);
|
|
9
|
+
}
|
|
10
|
+
export function formatFriendlyHandle(handle) {
|
|
11
|
+
const normalizedHandle = (handle || '').trim();
|
|
12
|
+
if (!normalizedHandle) {
|
|
13
|
+
return 'unknown';
|
|
14
|
+
}
|
|
15
|
+
if (!isExternalUrnHandle(normalizedHandle)) {
|
|
16
|
+
return normalizedHandle;
|
|
17
|
+
}
|
|
18
|
+
const externalId = normalizedHandle.slice(EXT_URN_PREFIX.length);
|
|
19
|
+
const [providerRaw, ...restParts] = externalId.split(':');
|
|
20
|
+
const provider = (providerRaw || '').toLowerCase();
|
|
21
|
+
const providerLabel = provider === 'github'
|
|
22
|
+
? 'GitHub'
|
|
23
|
+
: provider === 'google'
|
|
24
|
+
? 'Google'
|
|
25
|
+
: providerRaw || 'External';
|
|
26
|
+
const identifier = restParts.join(':').trim();
|
|
27
|
+
if (!identifier) {
|
|
28
|
+
return providerLabel;
|
|
29
|
+
}
|
|
30
|
+
const shortIdentifier = identifier.length > 18 ? `${identifier.slice(0, 15)}...` : identifier;
|
|
31
|
+
return `${providerLabel} ${shortIdentifier}`;
|
|
32
|
+
}
|
|
33
|
+
export function normalizeHandleFromName(value) {
|
|
34
|
+
const source = String(value || '').trim();
|
|
35
|
+
if (!source) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
const transliterated = source
|
|
39
|
+
.replace(/ß/g, 'ss')
|
|
40
|
+
.replace(/æ/gi, 'ae')
|
|
41
|
+
.replace(/œ/gi, 'oe')
|
|
42
|
+
.replace(/ø/gi, 'o')
|
|
43
|
+
.replace(/đ/gi, 'd')
|
|
44
|
+
.replace(/þ/gi, 'th')
|
|
45
|
+
.replace(/ł/gi, 'l')
|
|
46
|
+
.normalize('NFKD')
|
|
47
|
+
.replace(/[\u0300-\u036f]/g, '');
|
|
48
|
+
return transliterated
|
|
49
|
+
.toLowerCase()
|
|
50
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
51
|
+
.replace(/^-+|-+$/g, '')
|
|
52
|
+
.replace(/-{2,}/g, '-');
|
|
53
|
+
}
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -147,7 +147,6 @@
|
|
|
147
147
|
"diff": "^8.0.2",
|
|
148
148
|
"echarts": "^5.5.0",
|
|
149
149
|
"echarts-for-react": "^3.0.2",
|
|
150
|
-
"fuse.js": "^7.0.0",
|
|
151
150
|
"html2canvas": "^1.4.1",
|
|
152
151
|
"jwt-decode": "^2.2.0",
|
|
153
152
|
"localforage": "^1.10.0",
|
|
@@ -169,7 +168,6 @@
|
|
|
169
168
|
"ulid": "^2.3.0",
|
|
170
169
|
"unique-names-generator": "^4.7.1",
|
|
171
170
|
"usehooks-ts": "^2.9.1",
|
|
172
|
-
"user": "^0.0.0",
|
|
173
171
|
"uuid": "^13.0.0",
|
|
174
172
|
"validator": "^13.7.0",
|
|
175
173
|
"zod": "^4.1.13",
|