@sybilion/uilib 1.2.9 → 1.2.11
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/README.md +10 -7
- package/dist/esm/components/ui/AppHeader/AppHeader.styl.js +1 -1
- package/dist/esm/components/ui/Logo/Logo.js +2 -1
- package/dist/esm/components/ui/NavUserHeader/NavUserHeader.js +19 -6
- package/dist/esm/components/ui/NavUserHeader/NavUserHeader.styl.js +2 -2
- package/dist/esm/components/ui/Sidebar/Sidebar.styl.js +1 -1
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.js +8 -2
- package/dist/esm/components/widgets/SignInPage/SignInPage.js +2 -2
- package/dist/esm/components/widgets/SybilionAppHeader/SybilionAppHeader.js +2 -2
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl.js +1 -1
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthLayout.js +3 -8
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl.js +2 -2
- package/dist/esm/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl.js +1 -1
- package/dist/esm/contexts/theme-context.js +44 -0
- package/dist/esm/docs/lib/theme.js +35 -3
- package/dist/esm/index.js +3 -1
- package/dist/esm/sybilion-auth/SybilionAuthProvider.js +23 -10
- package/dist/esm/types/src/components/ui/Logo/Logo.d.ts +2 -1
- package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.d.ts +1 -1
- package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.types.d.ts +3 -0
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.d.ts +4 -1
- package/dist/esm/types/src/components/widgets/SignInPage/SignInPage.d.ts +2 -2
- package/dist/esm/types/src/components/widgets/SybilionAppHeader/SybilionAppHeader.d.ts +5 -1
- package/dist/esm/types/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.d.ts +2 -5
- package/dist/esm/types/src/components/widgets/SybilionAuthLayout/index.d.ts +1 -1
- package/dist/esm/types/src/contexts/theme-context.d.ts +20 -0
- package/dist/esm/types/src/docs/contexts/theme-context.d.ts +1 -10
- package/dist/esm/types/src/docs/lib/theme.d.ts +5 -1
- package/dist/esm/types/src/docs/pages/SybilionAuthLayoutPage.d.ts +1 -0
- package/dist/esm/types/src/index.d.ts +2 -0
- package/dist/esm/types/src/sybilion-auth/SybilionAuthProvider.d.ts +10 -1
- package/package.json +2 -4
- package/src/components/ui/AppHeader/AppHeader.styl +2 -0
- package/src/components/ui/Logo/Logo.tsx +2 -1
- package/src/components/ui/NavUserHeader/NavUserHeader.styl +2 -20
- package/src/components/ui/NavUserHeader/NavUserHeader.styl.d.ts +0 -3
- package/src/components/ui/NavUserHeader/NavUserHeader.tsx +40 -30
- package/src/components/ui/NavUserHeader/NavUserHeader.types.ts +3 -0
- package/src/components/ui/Sidebar/Sidebar.styl +2 -2
- package/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.tsx +14 -3
- package/src/components/widgets/SignInPage/SignInPage.tsx +1 -3
- package/src/components/widgets/SybilionAppHeader/SybilionAppHeader.tsx +8 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl +2 -2
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl.d.ts +10 -2
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl +20 -9
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl.d.ts +16 -2
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.tsx +4 -17
- package/src/components/widgets/SybilionAuthLayout/index.ts +0 -1
- package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl +3 -0
- package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl.d.ts +12 -2
- package/src/contexts/theme-context.tsx +106 -0
- package/src/docs/App/ThemeToggle.tsx +1 -1
- package/src/docs/DocsShell.tsx +16 -7
- package/src/docs/components/DocsSidebar/DocsSidebar.tsx +1 -0
- package/src/docs/contexts/theme-context.tsx +8 -68
- package/src/docs/index.tsx +1 -1
- package/src/docs/lib/theme.ts +13 -2
- package/src/docs/pages/ChartAreaInteractivePage.tsx +2 -2
- package/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.styl +1 -1
- package/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.tsx +5 -4
- package/src/docs/pages/SybilionAuthLayoutPage.tsx +47 -0
- package/src/docs/registry.ts +3 -3
- package/src/index.ts +2 -0
- package/src/sybilion-auth/SybilionAuthProvider.tsx +34 -8
- package/assets/standalone-global.css +0 -257
- package/dist/esm/docs/contexts/theme-context.js +0 -14
- package/dist/esm/types/src/docs/pages/SybilionAuthProviderPage.d.ts +0 -1
- package/docs/standalone-apps.md +0 -552
- package/src/docs/pages/SybilionAuthProviderPage.tsx +0 -40
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { RedirectLoginOptions } from '@auth0/auth0-react';
|
|
2
2
|
import { type SybilionAuthLayoutProps } from '#uilib/components/widgets/SybilionAuthLayout';
|
|
3
3
|
import { type SybilionSignInPanelProps } from '../SybilionSignInPanel';
|
|
4
|
-
export type SignInPageProps = Pick<SybilionAuthLayoutProps, '
|
|
4
|
+
export type SignInPageProps = Pick<SybilionAuthLayoutProps, 'logoSize' | 'containerClassName'> & Pick<SybilionSignInPanelProps, 'forgotPasswordTo' | 'releasesTo' | 'versionLabel' | 'primaryButtonLabel' | 'connectingLabel'> & {
|
|
5
5
|
title?: string;
|
|
6
6
|
subtitle?: string;
|
|
7
7
|
/** Extra Auth0 `loginWithRedirect` options; merged with default sign-in params. */
|
|
8
8
|
loginRedirectOptions?: RedirectLoginOptions;
|
|
9
9
|
};
|
|
10
|
-
export declare function SignInPage({ title, subtitle, forgotPasswordTo, releasesTo, versionLabel, primaryButtonLabel, connectingLabel, loginRedirectOptions,
|
|
10
|
+
export declare function SignInPage({ title, subtitle, forgotPasswordTo, releasesTo, versionLabel, primaryButtonLabel, connectingLabel, loginRedirectOptions, logoSize, containerClassName, }: SignInPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -5,10 +5,14 @@ export type SybilionAppHeaderProps = WorkspaceAppSwitcherProps & NavUserHeaderPr
|
|
|
5
5
|
pageHeaderId?: string;
|
|
6
6
|
actionsAnchorId?: string;
|
|
7
7
|
actionsAnchorClassName?: string;
|
|
8
|
+
/** Renders before `NavUserHeader` inside the page actions anchor (e.g. impersonation). */
|
|
9
|
+
actionsStart?: ReactNode;
|
|
10
|
+
/** Renders after `NavUserHeader` inside the page actions anchor (e.g. notifications). */
|
|
11
|
+
actionsEnd?: ReactNode;
|
|
8
12
|
/** Branded markup; omit for default lucide tile + «Sybilion». */
|
|
9
13
|
logo?: ReactNode;
|
|
10
14
|
logoAreaClassName?: string;
|
|
11
15
|
/** Applies vertical offset when a welcome banner consumes top space (CSS `--welcome-banner-height` on shell). */
|
|
12
16
|
welcomeBannerOffset?: boolean;
|
|
13
17
|
};
|
|
14
|
-
export declare function SybilionAppHeader({ pageHeaderId, actionsAnchorId, actionsAnchorClassName, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }: SybilionAppHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare function SybilionAppHeader({ pageHeaderId, actionsAnchorId, actionsAnchorClassName, actionsStart, actionsEnd, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }: SybilionAppHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { LogoSize } from '#uilib/components/ui/Logo/Logo.types';
|
|
3
|
-
/** Same convention as {@link SYBILION_STANDALONE_LOGO_PUBLIC_URL}: copy `sybilion-bg.svg` from the package into `public/`. */
|
|
4
|
-
export declare const SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL: "/sybilion_bg.svg";
|
|
5
3
|
export type SybilionAuthLayoutProps = {
|
|
6
4
|
title: string;
|
|
7
5
|
subtitle?: string;
|
|
8
6
|
children: ReactNode;
|
|
9
7
|
logoSize?: LogoSize;
|
|
10
8
|
containerClassName?: string;
|
|
11
|
-
|
|
12
|
-
heroBackgroundUrl?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
13
10
|
};
|
|
14
|
-
export declare function SybilionAuthLayout({ title, subtitle, children, logoSize, containerClassName,
|
|
11
|
+
export declare function SybilionAuthLayout({ title, subtitle, children, logoSize, containerClassName, style, }: SybilionAuthLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { SybilionAuthLayout,
|
|
1
|
+
export { SybilionAuthLayout, type SybilionAuthLayoutProps, } from './SybilionAuthLayout';
|
|
2
2
|
export { SybilionAuthHeadline } from './SybilionAuthHeadline';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getThemeConfig as defaultGetThemeConfig, type GetThemeConfigOptions } from '#uilib/docs/lib/theme';
|
|
2
|
+
export type ThemeMode = 'light' | 'dark';
|
|
3
|
+
export type GetThemeConfigFn = (isDarkTheme: boolean, options?: GetThemeConfigOptions) => ReturnType<typeof defaultGetThemeConfig>;
|
|
4
|
+
export type { GetThemeConfigOptions };
|
|
5
|
+
export type ThemeProviderProps = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
/** When false, DOM classes still update but theme is not persisted to `localStorage`. */
|
|
8
|
+
allowLocalStorage?: boolean;
|
|
9
|
+
/** Override docs default active/accent token (`DEFAULT_THEME_ACTIVE_COLOR`). Passed into `getThemeConfig`. */
|
|
10
|
+
activeColor?: string;
|
|
11
|
+
/** Homecode theme config; defaults to uilib docs palette. */
|
|
12
|
+
getThemeConfig?: GetThemeConfigFn;
|
|
13
|
+
};
|
|
14
|
+
export declare function ThemeProvider({ children, allowLocalStorage, activeColor, getThemeConfig: getThemeConfigProp, }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare const useTheme: () => {
|
|
16
|
+
theme: ThemeMode;
|
|
17
|
+
isDarkMode: boolean;
|
|
18
|
+
setTheme: (theme: ThemeMode) => void;
|
|
19
|
+
toggleTheme: () => void;
|
|
20
|
+
};
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
export type ThemeMode
|
|
2
|
-
export declare function ThemeProvider({ children }: {
|
|
3
|
-
children: React.ReactNode;
|
|
4
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
5
|
-
export declare const useTheme: () => {
|
|
6
|
-
theme: ThemeMode;
|
|
7
|
-
isDarkMode: boolean;
|
|
8
|
-
setTheme: (theme: ThemeMode) => void;
|
|
9
|
-
toggleTheme: () => void;
|
|
10
|
-
};
|
|
1
|
+
export { ThemeProvider, useTheme, type GetThemeConfigFn, type GetThemeConfigOptions, type ThemeMode, type ThemeProviderProps, } from '#uilib/contexts/theme-context';
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
export declare const DEFAULT_THEME_ACTIVE_COLOR = "#9c59ff";
|
|
2
|
+
export type GetThemeConfigOptions = {
|
|
3
|
+
activeColor?: string;
|
|
4
|
+
};
|
|
1
5
|
export declare const colorsConfig: {
|
|
2
6
|
light: {};
|
|
3
7
|
dark: {};
|
|
4
8
|
};
|
|
5
|
-
export declare function getThemeConfig(isDarkTheme: boolean): any;
|
|
9
|
+
export declare function getThemeConfig(isDarkTheme: boolean, options?: GetThemeConfigOptions): any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function SybilionAuthLayoutPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -19,7 +19,16 @@ export type SybilionAuthProviderProps = {
|
|
|
19
19
|
redirect_uri?: string;
|
|
20
20
|
};
|
|
21
21
|
sybilionTokenStorageKey?: string;
|
|
22
|
+
/**
|
|
23
|
+
* When set, passed to Auth0 `logout({ logoutParams: { returnTo } })` if
|
|
24
|
+
* {@link SybilionAuthProviderProps.useFederatedLogout} is true.
|
|
25
|
+
*/
|
|
22
26
|
logoutReturnTo?: string;
|
|
27
|
+
/**
|
|
28
|
+
* If true, redirect to Auth0 `/v2/logout` (clears IdP session). Default false matches
|
|
29
|
+
* sybilion-client: local session clear only, no redirect (`openUrl: false`).
|
|
30
|
+
*/
|
|
31
|
+
useFederatedLogout?: boolean;
|
|
23
32
|
};
|
|
24
33
|
export type SybilionAuthContextValue = {
|
|
25
34
|
apiBaseUrl: string;
|
|
@@ -39,4 +48,4 @@ export declare function sybilionApiFetch(apiBaseUrl: string, bearerToken: string
|
|
|
39
48
|
export declare function createSybilionApiFetch(apiBaseUrl: string, getSybilionAccessToken: () => Promise<string | null>): (path: string, init?: RequestInit) => Promise<Response>;
|
|
40
49
|
/** Authenticated fetch using {@link useSybilionAuth} context. */
|
|
41
50
|
export declare function useSybilionApiFetch(): (path: string, init?: RequestInit) => Promise<Response>;
|
|
42
|
-
export declare function SybilionAuthProvider({ children, sdk, auth0Domain, auth0ClientId, redirectUri, authorizationParams, sybilionTokenStorageKey, logoutReturnTo, }: SybilionAuthProviderProps): JSX.Element;
|
|
51
|
+
export declare function SybilionAuthProvider({ children, sdk, auth0Domain, auth0ClientId, redirectUri, authorizationParams, sybilionTokenStorageKey, logoutReturnTo, useFederatedLogout, }: SybilionAuthProviderProps): JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sybilion/uilib",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.11",
|
|
4
4
|
"description": "Sybilion Design System — React UI components (Webpack + Stylus)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -30,14 +30,12 @@
|
|
|
30
30
|
"default": "./src/index.ts"
|
|
31
31
|
},
|
|
32
32
|
"./src/*": "./src/*",
|
|
33
|
-
"./standalone-global.css": "./assets/standalone-global.css",
|
|
34
33
|
"./vite-standalone-dev": {
|
|
35
34
|
"types": "./dist/standalone/vite-sybilion-standalone-dev.d.ts",
|
|
36
35
|
"import": "./dist/standalone/vite-sybilion-standalone-dev.js",
|
|
37
36
|
"default": "./dist/standalone/vite-sybilion-standalone-dev.js"
|
|
38
37
|
},
|
|
39
|
-
"./logo.svg": "./src/assets/logo.svg"
|
|
40
|
-
"./sybilion-bg.svg": "./src/assets/sybilion_bg.svg"
|
|
38
|
+
"./logo.svg": "./src/assets/logo.svg"
|
|
41
39
|
},
|
|
42
40
|
"files": [
|
|
43
41
|
"assets",
|
|
@@ -5,7 +5,8 @@ import type { LogoProps } from './Logo.types';
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
|
|
8
|
-
* to `public/logo.svg` (
|
|
8
|
+
* to `public/logo.svg` (Sybilion app template README documents postinstall copies).
|
|
9
|
+
* Same path as the favicon `<link href>`.
|
|
9
10
|
*/
|
|
10
11
|
export const SYBILION_STANDALONE_LOGO_PUBLIC_URL = '/logo.svg' as const;
|
|
11
12
|
|
|
@@ -67,10 +67,12 @@
|
|
|
67
67
|
|
|
68
68
|
.userInfo
|
|
69
69
|
display flex
|
|
70
|
+
flex 1
|
|
70
71
|
flex-direction column
|
|
71
72
|
align-items flex-start
|
|
72
73
|
text-align left
|
|
73
74
|
gap 0.25rem
|
|
75
|
+
min-width 0
|
|
74
76
|
|
|
75
77
|
.userName
|
|
76
78
|
font-size var(--text-sm)
|
|
@@ -98,26 +100,6 @@
|
|
|
98
100
|
text-align left
|
|
99
101
|
font-size 0.875rem
|
|
100
102
|
|
|
101
|
-
.userDetails
|
|
102
|
-
display grid
|
|
103
|
-
flex 1
|
|
104
|
-
text-align left
|
|
105
|
-
font-size 0.875rem
|
|
106
|
-
line-height 1.25
|
|
107
|
-
|
|
108
|
-
.userDetailName
|
|
109
|
-
text-overflow ellipsis
|
|
110
|
-
overflow hidden
|
|
111
|
-
white-space nowrap
|
|
112
|
-
font-weight 500
|
|
113
|
-
|
|
114
|
-
.userDetailEmail
|
|
115
|
-
color var(--color-muted-foreground)
|
|
116
|
-
text-overflow ellipsis
|
|
117
|
-
overflow hidden
|
|
118
|
-
white-space nowrap
|
|
119
|
-
font-size 0.75rem
|
|
120
|
-
|
|
121
103
|
@keyframes pulse
|
|
122
104
|
0%, 100%
|
|
123
105
|
opacity 1
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
|
+
import { useMemo } from 'react';
|
|
2
3
|
|
|
3
|
-
import { useTheme } from '#uilib/
|
|
4
|
+
import { useTheme } from '#uilib/contexts/theme-context';
|
|
4
5
|
import {
|
|
5
6
|
MoonIcon,
|
|
6
7
|
SignOutIcon,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
} from '@phosphor-icons/react';
|
|
10
11
|
import { ChevronDownIcon } from 'lucide-react';
|
|
11
12
|
|
|
12
|
-
import { Avatar } from '../Avatar';
|
|
13
|
+
import { Avatar, AvatarFallback, AvatarImage } from '../Avatar';
|
|
13
14
|
import { Button } from '../Button';
|
|
14
15
|
import {
|
|
15
16
|
DropdownMenu,
|
|
@@ -20,7 +21,6 @@ import {
|
|
|
20
21
|
DropdownMenuSeparator,
|
|
21
22
|
DropdownMenuTrigger,
|
|
22
23
|
} from '../DropdownMenu';
|
|
23
|
-
import { Image } from '../Image';
|
|
24
24
|
import S from './NavUserHeader.styl';
|
|
25
25
|
import type { NavUserHeaderProps } from './NavUserHeader.types';
|
|
26
26
|
|
|
@@ -33,14 +33,46 @@ export function NavUserHeader({
|
|
|
33
33
|
onLogout,
|
|
34
34
|
signInSlot,
|
|
35
35
|
onSignInClick,
|
|
36
|
+
theme: themeFromHost,
|
|
37
|
+
onThemeToggle: onThemeToggleFromHost,
|
|
36
38
|
}: NavUserHeaderProps) {
|
|
37
|
-
const
|
|
39
|
+
const docsTheme = useTheme();
|
|
40
|
+
const hostControlsTheme =
|
|
41
|
+
themeFromHost !== undefined && onThemeToggleFromHost !== undefined;
|
|
42
|
+
const theme = hostControlsTheme ? themeFromHost : docsTheme.theme;
|
|
43
|
+
const toggleTheme = hostControlsTheme
|
|
44
|
+
? onThemeToggleFromHost
|
|
45
|
+
: docsTheme.toggleTheme;
|
|
38
46
|
const authenticated = isAuthenticated ?? true;
|
|
39
47
|
|
|
40
48
|
const avatarUrl = user?.avatar ?? '';
|
|
41
49
|
const userName = user?.name ?? '';
|
|
42
50
|
const userEmail = user?.email ?? '';
|
|
43
51
|
|
|
52
|
+
const avatar = useMemo(() => {
|
|
53
|
+
const initials = userName
|
|
54
|
+
.split(' ')
|
|
55
|
+
.map(name => name.charAt(0))
|
|
56
|
+
.join('');
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Avatar className={S.avatar}>
|
|
60
|
+
<AvatarImage src={avatarUrl || undefined} alt={userName} />
|
|
61
|
+
<AvatarFallback>{initials}</AvatarFallback>
|
|
62
|
+
</Avatar>
|
|
63
|
+
);
|
|
64
|
+
}, [avatarUrl, userName]);
|
|
65
|
+
|
|
66
|
+
const userIdentity = useMemo(
|
|
67
|
+
() => (
|
|
68
|
+
<div className={S.userInfo}>
|
|
69
|
+
<span className={`${S.userName} ph-no-capture`}>{userName}</span>
|
|
70
|
+
<span className={S.userEmail}>{userEmail}</span>
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
[userEmail, userName],
|
|
74
|
+
);
|
|
75
|
+
|
|
44
76
|
if (isLoading) {
|
|
45
77
|
return (
|
|
46
78
|
<Button variant="ghost" size="sm" disabled className={S.loadingButton}>
|
|
@@ -76,21 +108,10 @@ export function NavUserHeader({
|
|
|
76
108
|
size="sm"
|
|
77
109
|
className={cn(S.userButton, variant === 'compact' && S.compact)}
|
|
78
110
|
>
|
|
79
|
-
|
|
80
|
-
<Image
|
|
81
|
-
url={avatarUrl}
|
|
82
|
-
alt={userName}
|
|
83
|
-
fallback={<div className={S.avatarFallback} />}
|
|
84
|
-
/>
|
|
85
|
-
</Avatar>
|
|
111
|
+
{avatar}
|
|
86
112
|
{variant === 'default' && (
|
|
87
113
|
<>
|
|
88
|
-
|
|
89
|
-
<span className={`${S.userName} ph-no-capture`}>
|
|
90
|
-
{userName}
|
|
91
|
-
</span>
|
|
92
|
-
<span className={S.userEmail}>{userEmail}</span>
|
|
93
|
-
</div>
|
|
114
|
+
{userIdentity}
|
|
94
115
|
<ChevronDownIcon className={S.iconSm} />
|
|
95
116
|
</>
|
|
96
117
|
)}
|
|
@@ -103,19 +124,8 @@ export function NavUserHeader({
|
|
|
103
124
|
>
|
|
104
125
|
<DropdownMenuLabel className={S.userLabel}>
|
|
105
126
|
<div className={S.userLabelContent}>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
url={avatarUrl}
|
|
109
|
-
alt={userName}
|
|
110
|
-
fallback={<div className={S.avatarFallback} />}
|
|
111
|
-
/>
|
|
112
|
-
</Avatar>
|
|
113
|
-
<div className={S.userDetails}>
|
|
114
|
-
<span className={`${S.userDetailName} ph-no-capture`}>
|
|
115
|
-
{userName}
|
|
116
|
-
</span>
|
|
117
|
-
<span className={S.userDetailEmail}>{userEmail}</span>
|
|
118
|
-
</div>
|
|
127
|
+
{avatar}
|
|
128
|
+
{userIdentity}
|
|
119
129
|
</div>
|
|
120
130
|
</DropdownMenuLabel>
|
|
121
131
|
<DropdownMenuSeparator />
|
|
@@ -20,4 +20,7 @@ export type NavUserHeaderProps = {
|
|
|
20
20
|
/** Replaces default “Log in” control when signed out. */
|
|
21
21
|
signInSlot?: ReactNode;
|
|
22
22
|
onSignInClick?: () => void;
|
|
23
|
+
/** When both are set, theme row uses these instead of uilib `ThemeProvider` context. */
|
|
24
|
+
theme?: 'light' | 'dark';
|
|
25
|
+
onThemeToggle?: () => void;
|
|
23
26
|
};
|
|
@@ -193,7 +193,6 @@
|
|
|
193
193
|
.sidebarContent
|
|
194
194
|
position absolute
|
|
195
195
|
display flex
|
|
196
|
-
min-height 0
|
|
197
196
|
flex 1
|
|
198
197
|
flex-direction column
|
|
199
198
|
gap var(--p-16)
|
|
@@ -201,7 +200,8 @@
|
|
|
201
200
|
|
|
202
201
|
width 100%
|
|
203
202
|
height 100vh
|
|
204
|
-
|
|
203
|
+
min-height 0
|
|
204
|
+
max-height 100%
|
|
205
205
|
|
|
206
206
|
@media (min-width MOBILE)
|
|
207
207
|
height calc(100vh - var(--gap-top))
|
|
@@ -26,7 +26,10 @@ export type SidebarDatasetsItemsGroupedProps = {
|
|
|
26
26
|
postItems?: React.ReactNode;
|
|
27
27
|
selectedDatasetId?: number;
|
|
28
28
|
onDatasetClick?: (datasetId: number) => void;
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* When set, expanded state resets to this list whenever `grouped` changes.
|
|
31
|
+
* Omit: start collapsed; any group containing `selectedDatasetId` opens (toggle still adds more).
|
|
32
|
+
*/
|
|
30
33
|
defaultExpandedGroupNames?: string[];
|
|
31
34
|
className?: string;
|
|
32
35
|
};
|
|
@@ -46,15 +49,23 @@ export function SidebarDatasetsItemsGrouped({
|
|
|
46
49
|
[datasets, groupBy],
|
|
47
50
|
);
|
|
48
51
|
|
|
52
|
+
/** Content key — inline `[]` must not retrigger reset every render (new array ref). */
|
|
53
|
+
const defaultExpandedKey =
|
|
54
|
+
defaultExpandedGroupNames === undefined
|
|
55
|
+
? '__smart__'
|
|
56
|
+
: defaultExpandedGroupNames.join('\0');
|
|
57
|
+
|
|
49
58
|
const [expanded, setExpanded] = useState<Set<string>>(new Set());
|
|
50
59
|
|
|
51
60
|
useEffect(() => {
|
|
52
61
|
if (defaultExpandedGroupNames !== undefined) {
|
|
53
62
|
setExpanded(new Set(defaultExpandedGroupNames));
|
|
54
63
|
} else {
|
|
55
|
-
setExpanded(new Set(
|
|
64
|
+
setExpanded(new Set());
|
|
56
65
|
}
|
|
57
|
-
|
|
66
|
+
// Intentionally `defaultExpandedKey` not `defaultExpandedGroupNames` (reference stability).
|
|
67
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- key encodes array contents
|
|
68
|
+
}, [grouped, defaultExpandedKey]);
|
|
58
69
|
|
|
59
70
|
useEffect(() => {
|
|
60
71
|
if (selectedDatasetId == null) return;
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
|
|
14
14
|
export type SignInPageProps = Pick<
|
|
15
15
|
SybilionAuthLayoutProps,
|
|
16
|
-
'
|
|
16
|
+
'logoSize' | 'containerClassName'
|
|
17
17
|
> &
|
|
18
18
|
Pick<
|
|
19
19
|
SybilionSignInPanelProps,
|
|
@@ -42,7 +42,6 @@ export function SignInPage({
|
|
|
42
42
|
primaryButtonLabel,
|
|
43
43
|
connectingLabel,
|
|
44
44
|
loginRedirectOptions,
|
|
45
|
-
heroBackgroundUrl,
|
|
46
45
|
logoSize,
|
|
47
46
|
containerClassName,
|
|
48
47
|
}: SignInPageProps) {
|
|
@@ -65,7 +64,6 @@ export function SignInPage({
|
|
|
65
64
|
<SybilionAuthLayout
|
|
66
65
|
title={title}
|
|
67
66
|
subtitle={subtitle}
|
|
68
|
-
heroBackgroundUrl={heroBackgroundUrl}
|
|
69
67
|
logoSize={logoSize}
|
|
70
68
|
containerClassName={containerClassName}
|
|
71
69
|
>
|
|
@@ -20,6 +20,10 @@ export type SybilionAppHeaderProps = WorkspaceAppSwitcherProps &
|
|
|
20
20
|
pageHeaderId?: string;
|
|
21
21
|
actionsAnchorId?: string;
|
|
22
22
|
actionsAnchorClassName?: string;
|
|
23
|
+
/** Renders before `NavUserHeader` inside the page actions anchor (e.g. impersonation). */
|
|
24
|
+
actionsStart?: ReactNode;
|
|
25
|
+
/** Renders after `NavUserHeader` inside the page actions anchor (e.g. notifications). */
|
|
26
|
+
actionsEnd?: ReactNode;
|
|
23
27
|
/** Branded markup; omit for default lucide tile + «Sybilion». */
|
|
24
28
|
logo?: ReactNode;
|
|
25
29
|
logoAreaClassName?: string;
|
|
@@ -31,6 +35,8 @@ export function SybilionAppHeader({
|
|
|
31
35
|
pageHeaderId,
|
|
32
36
|
actionsAnchorId = PAGE_HEADER_ACTIONS_ID,
|
|
33
37
|
actionsAnchorClassName,
|
|
38
|
+
actionsStart,
|
|
39
|
+
actionsEnd,
|
|
34
40
|
pathname,
|
|
35
41
|
onNavigate,
|
|
36
42
|
authenticated,
|
|
@@ -67,7 +73,9 @@ export function SybilionAppHeader({
|
|
|
67
73
|
id={actionsAnchorId}
|
|
68
74
|
className={cn(S.actionsAnchor, actionsAnchorClassName)}
|
|
69
75
|
>
|
|
76
|
+
{actionsStart}
|
|
70
77
|
<NavUserHeader {...navUserHeaderProps} />
|
|
78
|
+
{actionsEnd}
|
|
71
79
|
</div>
|
|
72
80
|
</AppHeaderPortal>
|
|
73
81
|
);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
height 100%
|
|
11
11
|
font-family var(--font-family-heading)
|
|
12
12
|
font-weight 300
|
|
13
|
-
text-shadow 0 0
|
|
13
|
+
text-shadow 0 0 7px var(--background)
|
|
14
14
|
|
|
15
15
|
.headline
|
|
16
16
|
font-size 40px
|
|
@@ -23,4 +23,4 @@
|
|
|
23
23
|
margin 0
|
|
24
24
|
|
|
25
25
|
.headlineCyan
|
|
26
|
-
color
|
|
26
|
+
color var(--brand-color)
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// This file is automatically generated.
|
|
2
|
+
// Please do not change this file!
|
|
3
|
+
interface CssExports {
|
|
4
|
+
'headline': string;
|
|
5
|
+
'headlineCyan': string;
|
|
6
|
+
'headlineParagraph': string;
|
|
7
|
+
'root': string;
|
|
8
|
+
}
|
|
9
|
+
export const cssExports: CssExports;
|
|
10
|
+
export default cssExports;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
height 100vh
|
|
3
3
|
display flex
|
|
4
4
|
width 100%
|
|
5
|
+
background-color var(--background)
|
|
5
6
|
|
|
6
7
|
.leftPanel
|
|
7
8
|
display none
|
|
@@ -9,6 +10,8 @@
|
|
|
9
10
|
@media (min-width: 768px)
|
|
10
11
|
display flex
|
|
11
12
|
width 50%
|
|
13
|
+
height calc(100% - var(--p-6))
|
|
14
|
+
margin var(--p-3) 0 var(--p-3) var(--p-3)
|
|
12
15
|
position relative
|
|
13
16
|
overflow hidden
|
|
14
17
|
background-color var(--secondary)
|
|
@@ -20,15 +23,23 @@
|
|
|
20
23
|
:global(.dark) &
|
|
21
24
|
background-color var(--page-color-alpha-800)
|
|
22
25
|
|
|
23
|
-
.
|
|
26
|
+
// ~500px graphic, -200px offset → ~300px (~60%) visible inside panel (clipped by .leftPanel overflow)
|
|
27
|
+
.heroWatermark
|
|
24
28
|
position absolute
|
|
25
|
-
bottom
|
|
26
|
-
left
|
|
27
|
-
width
|
|
28
|
-
height
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
bottom -180px
|
|
30
|
+
left -180px
|
|
31
|
+
width 500px
|
|
32
|
+
height 500px
|
|
33
|
+
align-items flex-end
|
|
34
|
+
justify-content flex-start
|
|
35
|
+
gap 0
|
|
36
|
+
pointer-events none
|
|
37
|
+
|
|
38
|
+
img
|
|
39
|
+
width 100% !important
|
|
40
|
+
height 100% !important
|
|
41
|
+
object-fit contain
|
|
42
|
+
object-position left bottom
|
|
32
43
|
|
|
33
44
|
.logoContainer
|
|
34
45
|
z-index 10
|
|
@@ -45,8 +56,8 @@
|
|
|
45
56
|
height 24px
|
|
46
57
|
|
|
47
58
|
.rightPanel
|
|
59
|
+
position relative
|
|
48
60
|
flex 1
|
|
49
|
-
background-color var(--background)
|
|
50
61
|
display flex
|
|
51
62
|
flex-direction column
|
|
52
63
|
justify-content center
|
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// This file is automatically generated.
|
|
2
|
+
// Please do not change this file!
|
|
3
|
+
interface CssExports {
|
|
4
|
+
'formContainer': string;
|
|
5
|
+
'header': string;
|
|
6
|
+
'heroWatermark': string;
|
|
7
|
+
'leftPanel': string;
|
|
8
|
+
'logo': string;
|
|
9
|
+
'logoContainer': string;
|
|
10
|
+
'rightPanel': string;
|
|
11
|
+
'root': string;
|
|
12
|
+
'subtitle': string;
|
|
13
|
+
'title': string;
|
|
14
|
+
}
|
|
15
|
+
export const cssExports: CssExports;
|
|
16
|
+
export default cssExports;
|
|
@@ -7,18 +7,13 @@ import type { LogoSize } from '#uilib/components/ui/Logo/Logo.types';
|
|
|
7
7
|
import { SybilionAuthHeadline } from './SybilionAuthHeadline';
|
|
8
8
|
import S from './SybilionAuthLayout.styl';
|
|
9
9
|
|
|
10
|
-
/** Same convention as {@link SYBILION_STANDALONE_LOGO_PUBLIC_URL}: copy `sybilion-bg.svg` from the package into `public/`. */
|
|
11
|
-
export const SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL =
|
|
12
|
-
'/sybilion_bg.svg' as const;
|
|
13
|
-
|
|
14
10
|
export type SybilionAuthLayoutProps = {
|
|
15
11
|
title: string;
|
|
16
12
|
subtitle?: string;
|
|
17
13
|
children: ReactNode;
|
|
18
14
|
logoSize?: LogoSize;
|
|
19
15
|
containerClassName?: string;
|
|
20
|
-
|
|
21
|
-
heroBackgroundUrl?: string;
|
|
16
|
+
style?: React.CSSProperties;
|
|
22
17
|
};
|
|
23
18
|
|
|
24
19
|
export function SybilionAuthLayout({
|
|
@@ -27,20 +22,12 @@ export function SybilionAuthLayout({
|
|
|
27
22
|
children,
|
|
28
23
|
logoSize,
|
|
29
24
|
containerClassName,
|
|
30
|
-
|
|
25
|
+
style,
|
|
31
26
|
}: SybilionAuthLayoutProps) {
|
|
32
|
-
const bg = heroBackgroundUrl
|
|
33
|
-
? `url(${JSON.stringify(heroBackgroundUrl)})`
|
|
34
|
-
: 'none';
|
|
35
|
-
|
|
36
27
|
return (
|
|
37
|
-
<div className={S.root}>
|
|
28
|
+
<div className={S.root} style={style}>
|
|
38
29
|
<div className={S.leftPanel}>
|
|
39
|
-
<
|
|
40
|
-
className={S.bgImage}
|
|
41
|
-
style={{ backgroundImage: bg }}
|
|
42
|
-
aria-hidden
|
|
43
|
-
/>
|
|
30
|
+
<Logo showText={false} className={S.heroWatermark} aria-hidden />
|
|
44
31
|
|
|
45
32
|
<div className={S.logoContainer}>
|
|
46
33
|
<Logo className={S.logo} size={logoSize} />
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// This file is automatically generated.
|
|
2
|
+
// Please do not change this file!
|
|
3
|
+
interface CssExports {
|
|
4
|
+
'errorMessage': string;
|
|
5
|
+
'forgotPassword': string;
|
|
6
|
+
'forgotPasswordLink': string;
|
|
7
|
+
'socialButton': string;
|
|
8
|
+
'socialButtonContainer': string;
|
|
9
|
+
'version': string;
|
|
10
|
+
}
|
|
11
|
+
export const cssExports: CssExports;
|
|
12
|
+
export default cssExports;
|