@sybilion/uilib 1.2.8 → 1.2.10
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/dist/esm/components/ui/NavUserHeader/NavUserHeader.js +8 -3
- package/dist/esm/components/widgets/SignInPage/SignInPage.js +25 -0
- package/dist/esm/components/widgets/SybilionAppHeader/SybilionAppHeader.js +2 -2
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.js +8 -0
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl.js +7 -0
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthLayout.js +16 -0
- package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl.js +7 -0
- package/dist/esm/components/widgets/SybilionSignInPanel/SybilionSignInPanel.js +11 -0
- package/dist/esm/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl.js +7 -0
- package/dist/esm/contexts/theme-context.js +44 -0
- package/dist/esm/docs/lib/theme.js +35 -3
- package/dist/esm/index.js +6 -0
- 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/SignInPage/SignInPage.d.ts +10 -0
- package/dist/esm/types/src/components/widgets/SignInPage/index.d.ts +1 -0
- package/dist/esm/types/src/components/widgets/SybilionAppHeader/SybilionAppHeader.d.ts +5 -1
- package/dist/esm/types/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.d.ts +1 -0
- package/dist/esm/types/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.d.ts +14 -0
- package/dist/esm/types/src/components/widgets/SybilionAuthLayout/index.d.ts +2 -0
- package/dist/esm/types/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.d.ts +11 -0
- package/dist/esm/types/src/components/widgets/SybilionSignInPanel/index.d.ts +1 -0
- 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/index.d.ts +5 -0
- package/docs/standalone-apps.md +58 -37
- package/package.json +3 -2
- package/src/assets/sybilion_bg.svg +8 -0
- package/src/components/ui/NavUserHeader/NavUserHeader.tsx +10 -2
- package/src/components/ui/NavUserHeader/NavUserHeader.types.ts +3 -0
- package/src/components/widgets/SignInPage/SignInPage.tsx +84 -0
- package/src/components/widgets/SignInPage/index.ts +1 -0
- package/src/components/widgets/SybilionAppHeader/SybilionAppHeader.tsx +8 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl +26 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl.d.ts +2 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.tsx +18 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl +79 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl.d.ts +2 -0
- package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.tsx +64 -0
- package/src/components/widgets/SybilionAuthLayout/index.ts +6 -0
- package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl +51 -0
- package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl.d.ts +2 -0
- package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.tsx +59 -0
- package/src/components/widgets/SybilionSignInPanel/index.ts +4 -0
- package/src/contexts/theme-context.tsx +106 -0
- package/src/docs/App/ThemeToggle.tsx +1 -1
- 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 +1 -1
- package/src/index.ts +5 -0
- package/dist/esm/docs/contexts/theme-context.js +0 -14
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import { useTheme } from '../../../
|
|
3
|
+
import { useTheme } from '../../../contexts/theme-context.js';
|
|
4
4
|
import { UserCircleIcon, SunIcon, MoonIcon, SignOutIcon } from '@phosphor-icons/react';
|
|
5
5
|
import { ChevronDownIcon } from 'lucide-react';
|
|
6
6
|
import { Avatar } from '../Avatar/Avatar.js';
|
|
@@ -9,8 +9,13 @@ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLab
|
|
|
9
9
|
import { Image } from '../Image/Image.js';
|
|
10
10
|
import S from './NavUserHeader.styl.js';
|
|
11
11
|
|
|
12
|
-
function NavUserHeader({ variant = 'default', isLoading = false, isAuthenticated, user = null, menuItems, onLogout, signInSlot, onSignInClick, }) {
|
|
13
|
-
const
|
|
12
|
+
function NavUserHeader({ variant = 'default', isLoading = false, isAuthenticated, user = null, menuItems, onLogout, signInSlot, onSignInClick, theme: themeFromHost, onThemeToggle: onThemeToggleFromHost, }) {
|
|
13
|
+
const docsTheme = useTheme();
|
|
14
|
+
const hostControlsTheme = themeFromHost !== undefined && onThemeToggleFromHost !== undefined;
|
|
15
|
+
const theme = hostControlsTheme ? themeFromHost : docsTheme.theme;
|
|
16
|
+
const toggleTheme = hostControlsTheme
|
|
17
|
+
? onThemeToggleFromHost
|
|
18
|
+
: docsTheme.toggleTheme;
|
|
14
19
|
const authenticated = isAuthenticated ?? true;
|
|
15
20
|
const avatarUrl = user?.avatar ?? '';
|
|
16
21
|
const userName = user?.name ?? '';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { SybilionAuthLayout } from '../SybilionAuthLayout/SybilionAuthLayout.js';
|
|
3
|
+
import '../SybilionAuthLayout/SybilionAuthHeadline.styl.js';
|
|
4
|
+
import { useSybilionAuth } from '../../../sybilion-auth/SybilionAuthProvider.js';
|
|
5
|
+
import { SybilionSignInPanel } from '../SybilionSignInPanel/SybilionSignInPanel.js';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_TITLE = 'Sign In';
|
|
8
|
+
const DEFAULT_SUBTITLE = 'To get access authenticate through google or your email.';
|
|
9
|
+
function SignInPage({ title = DEFAULT_TITLE, subtitle = DEFAULT_SUBTITLE, forgotPasswordTo = '/forgot-password', releasesTo = '/releases', versionLabel, primaryButtonLabel, connectingLabel, loginRedirectOptions, heroBackgroundUrl, logoSize, containerClassName, }) {
|
|
10
|
+
const { error, loginWithRedirect, isLoading } = useSybilionAuth();
|
|
11
|
+
const handleSignIn = () => loginWithRedirect({
|
|
12
|
+
...loginRedirectOptions,
|
|
13
|
+
authorizationParams: {
|
|
14
|
+
prompt: 'login',
|
|
15
|
+
screen_hint: 'login',
|
|
16
|
+
...(typeof window !== 'undefined'
|
|
17
|
+
? { origin: window.location.origin }
|
|
18
|
+
: {}),
|
|
19
|
+
...loginRedirectOptions?.authorizationParams,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
return (jsx(SybilionAuthLayout, { title: title, subtitle: subtitle, heroBackgroundUrl: heroBackgroundUrl, logoSize: logoSize, containerClassName: containerClassName, children: jsx(SybilionSignInPanel, { onSignIn: handleSignIn, isSigningIn: isLoading, error: error, forgotPasswordTo: forgotPasswordTo, releasesTo: releasesTo, versionLabel: versionLabel, primaryButtonLabel: primaryButtonLabel, connectingLabel: connectingLabel }) }));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { SignInPage };
|
|
@@ -11,8 +11,8 @@ import '@phosphor-icons/react';
|
|
|
11
11
|
import 'lucide-react';
|
|
12
12
|
import S from './SybilionAppHeader.styl.js';
|
|
13
13
|
|
|
14
|
-
function SybilionAppHeader({ pageHeaderId, actionsAnchorId = PAGE_HEADER_ACTIONS_ID, actionsAnchorClassName, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }) {
|
|
15
|
-
return (jsxs(AppHeaderPortal, { pageHeaderId: pageHeaderId, children: [jsx("div", { className: cn(S.logoArea, welcomeBannerOffset && S.logoAreaWithBanner, logoAreaClassName), children: jsx(Link, { to: "/", className: S.logoLink, children: logo ?? jsx(Logo, { size: "md", "aria-hidden": true }) }) }), jsx(WorkspaceAppSwitcher, { pathname: pathname, onNavigate: onNavigate, authenticated: authenticated, defaultApps: defaultApps, appsStorageKey: appsStorageKey }), jsx(Gap, {}),
|
|
14
|
+
function SybilionAppHeader({ pageHeaderId, actionsAnchorId = PAGE_HEADER_ACTIONS_ID, actionsAnchorClassName, actionsStart, actionsEnd, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }) {
|
|
15
|
+
return (jsxs(AppHeaderPortal, { pageHeaderId: pageHeaderId, children: [jsx("div", { className: cn(S.logoArea, welcomeBannerOffset && S.logoAreaWithBanner, logoAreaClassName), children: jsx(Link, { to: "/", className: S.logoLink, children: logo ?? jsx(Logo, { size: "md", "aria-hidden": true }) }) }), jsx(WorkspaceAppSwitcher, { pathname: pathname, onNavigate: onNavigate, authenticated: authenticated, defaultApps: defaultApps, appsStorageKey: appsStorageKey }), jsx(Gap, {}), jsxs("div", { id: actionsAnchorId, className: cn(S.actionsAnchor, actionsAnchorClassName), children: [actionsStart, jsx(NavUserHeader, { ...navUserHeaderProps }), actionsEnd] })] }));
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export { SybilionAppHeader };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import S from './SybilionAuthHeadline.styl.js';
|
|
3
|
+
|
|
4
|
+
function SybilionAuthHeadline() {
|
|
5
|
+
return (jsx("div", { className: S.root, children: jsxs("div", { className: S.headline, children: [jsxs("p", { className: S.headlineParagraph, children: [jsx("span", { children: "External volatility" }), jsx("span", {})] }), jsx("p", { className: S.headlineParagraph, children: "turned into" }), jsx("p", { className: S.headlineParagraph, children: jsx("span", { className: S.headlineCyan, children: "confident decisions" }) })] }) }));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { SybilionAuthHeadline };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
|
|
3
|
+
var css_248z = ".SybilionAuthHeadline_root__iExEN{align-items:center;display:flex;flex-direction:column;font-family:var(--font-family-heading);font-weight:300;height:100%;justify-content:center;padding:64px 48px;position:relative;text-shadow:0 0 2px var(--background);width:100%;z-index:10}.SybilionAuthHeadline_headline__pkjEh{font-size:40px;line-height:48px;max-width:480px;text-align:left;width:100%}.SybilionAuthHeadline_headlineParagraph__jeOTl{margin:0}.SybilionAuthHeadline_headlineCyan__26sg2{color:#27d1ef}";
|
|
4
|
+
var S = {"root":"SybilionAuthHeadline_root__iExEN","headline":"SybilionAuthHeadline_headline__pkjEh","headlineParagraph":"SybilionAuthHeadline_headlineParagraph__jeOTl","headlineCyan":"SybilionAuthHeadline_headlineCyan__26sg2"};
|
|
5
|
+
styleInject(css_248z);
|
|
6
|
+
|
|
7
|
+
export { S as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { Logo } from '../../ui/Logo/Logo.js';
|
|
4
|
+
import { SybilionAuthHeadline } from './SybilionAuthHeadline.js';
|
|
5
|
+
import S from './SybilionAuthLayout.styl.js';
|
|
6
|
+
|
|
7
|
+
/** Same convention as {@link SYBILION_STANDALONE_LOGO_PUBLIC_URL}: copy `sybilion-bg.svg` from the package into `public/`. */
|
|
8
|
+
const SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL = '/sybilion_bg.svg';
|
|
9
|
+
function SybilionAuthLayout({ title, subtitle, children, logoSize, containerClassName, heroBackgroundUrl = SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL, }) {
|
|
10
|
+
const bg = heroBackgroundUrl
|
|
11
|
+
? `url(${JSON.stringify(heroBackgroundUrl)})`
|
|
12
|
+
: 'none';
|
|
13
|
+
return (jsxs("div", { className: S.root, children: [jsxs("div", { className: S.leftPanel, children: [jsx("div", { className: S.bgImage, style: { backgroundImage: bg }, "aria-hidden": true }), jsx("div", { className: S.logoContainer, children: jsx(Logo, { className: S.logo, size: logoSize }) }), jsx(SybilionAuthHeadline, {})] }), jsx("div", { className: S.rightPanel, children: jsxs("div", { className: cn(S.formContainer, containerClassName), children: [jsxs("div", { className: S.header, children: [jsx("h1", { className: S.title, children: title }), subtitle && jsx("p", { className: S.subtitle, children: subtitle })] }), children] }) })] }));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL, SybilionAuthLayout };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
|
|
3
|
+
var css_248z = ".SybilionAuthLayout_root__jM5q5{display:flex;height:100vh;width:100%}.SybilionAuthLayout_leftPanel__MoyRZ{display:none}@media (min-width:768px){.SybilionAuthLayout_leftPanel__MoyRZ{background-color:var(--secondary);border-bottom-left-radius:var(--p-6);border-bottom-right-radius:var(--p-1);border-top-left-radius:var(--p-6);border-top-right-radius:var(--p-1);display:flex;overflow:hidden;position:relative;width:50%}.dark .SybilionAuthLayout_leftPanel__MoyRZ{background-color:var(--page-color-alpha-800)}}.SybilionAuthLayout_bgImage__LvCav{background-position:0 100%;background-repeat:no-repeat;background-size:contain;bottom:0;height:300px;left:0;position:absolute;width:300px}.SybilionAuthLayout_logoContainer__jR7Dw{align-items:center;display:flex;left:0;min-height:94px;padding:16px 48px;position:absolute;top:0;z-index:10}.SybilionAuthLayout_logo__LxBpo{height:24px;width:24px}.SybilionAuthLayout_rightPanel__pKcYC{align-items:center;background-color:var(--background);display:flex;flex:1;flex-direction:column;justify-content:center;padding:48px 64px}.SybilionAuthLayout_formContainer__xMCFZ{max-width:480px;width:100%}.SybilionAuthLayout_header__OOsdf{margin-bottom:36px}.SybilionAuthLayout_title__iYcZD{color:var(--foreground);font-family:var(--font-family-heading);font-size:30px;font-weight:400;line-height:42px;margin:0 0 6px}.SybilionAuthLayout_subtitle__sWv5p{color:var(--muted-foreground);font-family:Manrope,sans-serif;font-size:14px;font-weight:500;line-height:16px;margin:0}";
|
|
4
|
+
var S = {"root":"SybilionAuthLayout_root__jM5q5","leftPanel":"SybilionAuthLayout_leftPanel__MoyRZ","bgImage":"SybilionAuthLayout_bgImage__LvCav","logoContainer":"SybilionAuthLayout_logoContainer__jR7Dw","logo":"SybilionAuthLayout_logo__LxBpo","rightPanel":"SybilionAuthLayout_rightPanel__pKcYC","formContainer":"SybilionAuthLayout_formContainer__xMCFZ","header":"SybilionAuthLayout_header__OOsdf","title":"SybilionAuthLayout_title__iYcZD","subtitle":"SybilionAuthLayout_subtitle__sWv5p"};
|
|
5
|
+
styleInject(css_248z);
|
|
6
|
+
|
|
7
|
+
export { S as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Link } from 'react-router-dom';
|
|
3
|
+
import { Button } from '../../ui/Button/Button.js';
|
|
4
|
+
import S from './SybilionSignInPanel.styl.js';
|
|
5
|
+
|
|
6
|
+
function SybilionSignInPanel({ onSignIn, isSigningIn = false, error, forgotPasswordTo, releasesTo, versionLabel, primaryButtonLabel = 'Sign-in', connectingLabel = 'Connecting...', }) {
|
|
7
|
+
const signingIn = Boolean(isSigningIn);
|
|
8
|
+
return (jsxs(Fragment, { children: [jsx("div", { className: S.socialButtonContainer, children: jsx(Button, { variant: "outline", type: "button", className: S.socialButton, onClick: () => void onSignIn(), disabled: signingIn, children: signingIn ? connectingLabel : primaryButtonLabel }) }), error ? jsx("div", { className: S.errorMessage, children: error }) : null, jsx("div", { className: S.forgotPassword, children: jsx(Link, { to: forgotPasswordTo, className: S.forgotPasswordLink, children: "Forgot password?" }) }), releasesTo && versionLabel ? (jsxs(Link, { className: S.version, to: releasesTo, children: ["v", versionLabel] })) : null] }));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { SybilionSignInPanel };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
|
|
3
|
+
var css_248z = ".SybilionSignInPanel_socialButtonContainer__lKNpp{display:flex;gap:10px;margin-bottom:10px;width:100%}.SybilionSignInPanel_socialButton__TqlKb{border:1px solid var(--border);border-radius:14px;flex:1;font-size:14px;font-weight:600;height:48px;padding:14px 16px}.SybilionSignInPanel_errorMessage__o8Q-m{color:red;font-size:14px;margin-bottom:10px;padding:10px}.SybilionSignInPanel_forgotPassword__47q20{margin-bottom:24px;text-align:right}.SybilionSignInPanel_forgotPasswordLink__lOJCv{color:var(--primary);font-family:Manrope,sans-serif;font-size:14px;font-weight:500;text-decoration:none;transition:opacity .2s}.SybilionSignInPanel_forgotPasswordLink__lOJCv:hover{opacity:.8}.SybilionSignInPanel_version__d5KAz{bottom:0;box-sizing:border-box;color:var(--muted-foreground);display:block;font-size:14px;margin-top:var(--p-8);opacity:.5;padding-bottom:var(--p-2);position:absolute;right:0;text-align:center;transition:opacity .3s ease-out;white-space:nowrap;width:50%}";
|
|
4
|
+
var S = {"socialButtonContainer":"SybilionSignInPanel_socialButtonContainer__lKNpp","socialButton":"SybilionSignInPanel_socialButton__TqlKb","errorMessage":"SybilionSignInPanel_errorMessage__o8Q-m","forgotPassword":"SybilionSignInPanel_forgotPassword__47q20","forgotPasswordLink":"SybilionSignInPanel_forgotPasswordLink__lOJCv","version":"SybilionSignInPanel_version__d5KAz"};
|
|
5
|
+
styleInject(css_248z);
|
|
6
|
+
|
|
7
|
+
export { S as default };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useMemo, useState, useCallback, useEffect, useContext } from 'react';
|
|
3
|
+
import { Theme } from '@homecode/ui';
|
|
4
|
+
import { getThemeConfig } from '../docs/lib/theme.js';
|
|
5
|
+
|
|
6
|
+
const ThemeContext = createContext({
|
|
7
|
+
theme: 'light',
|
|
8
|
+
isDarkMode: false,
|
|
9
|
+
setTheme: () => { },
|
|
10
|
+
toggleTheme: () => { },
|
|
11
|
+
});
|
|
12
|
+
function ThemeProvider({ children, allowLocalStorage = true, activeColor, getThemeConfig: getThemeConfigProp, }) {
|
|
13
|
+
const getThemeConfig$1 = getThemeConfigProp ?? getThemeConfig;
|
|
14
|
+
const themeConfigOptions = useMemo(() => ({ activeColor }), [activeColor]);
|
|
15
|
+
const [theme, setTheme] = useState(() => {
|
|
16
|
+
return localStorage.getItem('theme') || 'light';
|
|
17
|
+
});
|
|
18
|
+
const [currThemeConfig, setCurrThemeConfig] = useState(() => getThemeConfig$1(theme === 'dark', themeConfigOptions));
|
|
19
|
+
const toggleTheme = useCallback(() => {
|
|
20
|
+
setTheme(t => (t === 'dark' ? 'light' : 'dark'));
|
|
21
|
+
}, []);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
setCurrThemeConfig(getThemeConfig$1(theme === 'dark', themeConfigOptions));
|
|
24
|
+
}, [theme, getThemeConfig$1, themeConfigOptions]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const root = document.documentElement;
|
|
27
|
+
const effectiveTheme = theme;
|
|
28
|
+
root.classList.remove('light', 'dark');
|
|
29
|
+
root.classList.add(effectiveTheme);
|
|
30
|
+
if (allowLocalStorage) {
|
|
31
|
+
localStorage.setItem('theme', theme);
|
|
32
|
+
}
|
|
33
|
+
}, [theme, allowLocalStorage]);
|
|
34
|
+
const value = useMemo(() => ({
|
|
35
|
+
theme,
|
|
36
|
+
isDarkMode: theme === 'dark',
|
|
37
|
+
setTheme,
|
|
38
|
+
toggleTheme,
|
|
39
|
+
}), [theme, toggleTheme]);
|
|
40
|
+
return (jsxs(ThemeContext.Provider, { value: value, children: [jsx(Theme, { config: currThemeConfig }), children] }));
|
|
41
|
+
}
|
|
42
|
+
const useTheme = () => useContext(ThemeContext);
|
|
43
|
+
|
|
44
|
+
export { ThemeProvider, useTheme };
|
|
@@ -2,8 +2,10 @@ import { ThemeHelpers, ThemeDefaults } from '@homecode/ui';
|
|
|
2
2
|
|
|
3
3
|
const { colors, getColors, getConfig } = ThemeDefaults;
|
|
4
4
|
getColors();
|
|
5
|
-
getConfig();
|
|
6
|
-
|
|
5
|
+
const defaultConfig = getConfig();
|
|
6
|
+
const alphaMods = [0, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
|
|
7
|
+
const DEFAULT_THEME_ACTIVE_COLOR = '#9c59ff';
|
|
8
|
+
const colorsConfig = {
|
|
7
9
|
light: {
|
|
8
10
|
...ThemeHelpers.colorsConfigToVars({
|
|
9
11
|
...getColors({
|
|
@@ -20,4 +22,34 @@ getConfig();
|
|
|
20
22
|
}),
|
|
21
23
|
}),
|
|
22
24
|
},
|
|
23
|
-
}
|
|
25
|
+
};
|
|
26
|
+
function getThemeConfig(isDarkTheme, options) {
|
|
27
|
+
const activeColor = options?.activeColor ?? DEFAULT_THEME_ACTIVE_COLOR;
|
|
28
|
+
return {
|
|
29
|
+
...defaultConfig,
|
|
30
|
+
...colorsConfig[isDarkTheme ? 'dark' : 'light'],
|
|
31
|
+
...ThemeHelpers.colorsConfigToVars({
|
|
32
|
+
active: {
|
|
33
|
+
color: activeColor,
|
|
34
|
+
mods: {
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
alpha: alphaMods,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
danger: {
|
|
40
|
+
color: '#ee0000',
|
|
41
|
+
mods: {
|
|
42
|
+
alpha: alphaMods,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
warning: {
|
|
46
|
+
color: '#ffa500',
|
|
47
|
+
mods: {
|
|
48
|
+
alpha: alphaMods,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { DEFAULT_THEME_ACTIVE_COLOR, colorsConfig, getThemeConfig };
|
package/dist/esm/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { ThemeProvider, useTheme } from './contexts/theme-context.js';
|
|
2
|
+
export { DEFAULT_THEME_ACTIVE_COLOR } from './docs/lib/theme.js';
|
|
1
3
|
export { SybilionAuthProvider, createSybilionApiFetch, getSybilionApiOriginFromSdk, sybilionApiFetch, useSybilionApiFetch, useSybilionAuth } from './sybilion-auth/SybilionAuthProvider.js';
|
|
2
4
|
export { SYBILION_AUTH_LOGIN_PATH, normalizeApiBaseUrl } from './sybilion-auth/authPaths.js';
|
|
3
5
|
export { exchangeAuth0AccessTokenForSybilionJwt } from './sybilion-auth/exchangeSybilionToken.js';
|
|
@@ -86,6 +88,10 @@ export { findWorkspaceAppByPathname, workspaceAppSlugPath } from './components/u
|
|
|
86
88
|
export { SidebarDatasetsItemsGrouped } from './components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.js';
|
|
87
89
|
export { groupSidebarDatasets } from './components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.js';
|
|
88
90
|
export { SybilionAppHeader } from './components/widgets/SybilionAppHeader/SybilionAppHeader.js';
|
|
91
|
+
export { SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL, SybilionAuthLayout } from './components/widgets/SybilionAuthLayout/SybilionAuthLayout.js';
|
|
92
|
+
export { SybilionAuthHeadline } from './components/widgets/SybilionAuthLayout/SybilionAuthHeadline.js';
|
|
93
|
+
export { SybilionSignInPanel } from './components/widgets/SybilionSignInPanel/SybilionSignInPanel.js';
|
|
94
|
+
export { SignInPage } from './components/widgets/SignInPage/SignInPage.js';
|
|
89
95
|
export { ChartTooltipItem } from './components/ui/Chart/components/ChartTooltipItem.js';
|
|
90
96
|
export { ChartLegendItem } from './components/ui/Chart/components/ChartLegendItem.js';
|
|
91
97
|
export { CustomChartLegend } from './components/ui/Chart/components/CustomChartLegend/CustomChartLegend.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { NavUserHeaderProps } from './NavUserHeader.types';
|
|
2
|
-
export declare function NavUserHeader({ variant, isLoading, isAuthenticated, user, menuItems, onLogout, signInSlot, onSignInClick, }: NavUserHeaderProps): string | number | bigint | true | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode>> | import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function NavUserHeader({ variant, isLoading, isAuthenticated, user, menuItems, onLogout, signInSlot, onSignInClick, theme: themeFromHost, onThemeToggle: onThemeToggleFromHost, }: NavUserHeaderProps): string | number | bigint | true | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode>> | import("react/jsx-runtime").JSX.Element;
|
|
@@ -18,4 +18,7 @@ export type NavUserHeaderProps = {
|
|
|
18
18
|
/** Replaces default “Log in” control when signed out. */
|
|
19
19
|
signInSlot?: ReactNode;
|
|
20
20
|
onSignInClick?: () => void;
|
|
21
|
+
/** When both are set, theme row uses these instead of uilib `ThemeProvider` context. */
|
|
22
|
+
theme?: 'light' | 'dark';
|
|
23
|
+
onThemeToggle?: () => void;
|
|
21
24
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RedirectLoginOptions } from '@auth0/auth0-react';
|
|
2
|
+
import { type SybilionAuthLayoutProps } from '#uilib/components/widgets/SybilionAuthLayout';
|
|
3
|
+
import { type SybilionSignInPanelProps } from '../SybilionSignInPanel';
|
|
4
|
+
export type SignInPageProps = Pick<SybilionAuthLayoutProps, 'heroBackgroundUrl' | 'logoSize' | 'containerClassName'> & Pick<SybilionSignInPanelProps, 'forgotPasswordTo' | 'releasesTo' | 'versionLabel' | 'primaryButtonLabel' | 'connectingLabel'> & {
|
|
5
|
+
title?: string;
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
/** Extra Auth0 `loginWithRedirect` options; merged with default sign-in params. */
|
|
8
|
+
loginRedirectOptions?: RedirectLoginOptions;
|
|
9
|
+
};
|
|
10
|
+
export declare function SignInPage({ title, subtitle, forgotPasswordTo, releasesTo, versionLabel, primaryButtonLabel, connectingLabel, loginRedirectOptions, heroBackgroundUrl, logoSize, containerClassName, }: SignInPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SignInPage, type SignInPageProps } from './SignInPage';
|
|
@@ -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;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function SybilionAuthHeadline(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
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
|
+
export type SybilionAuthLayoutProps = {
|
|
6
|
+
title: string;
|
|
7
|
+
subtitle?: string;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
logoSize?: LogoSize;
|
|
10
|
+
containerClassName?: string;
|
|
11
|
+
/** Public URL for the hero watermark SVG (default {@link SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL}). */
|
|
12
|
+
heroBackgroundUrl?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function SybilionAuthLayout({ title, subtitle, children, logoSize, containerClassName, heroBackgroundUrl, }: SybilionAuthLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type SybilionSignInPanelProps = {
|
|
2
|
+
onSignIn: () => void | Promise<void>;
|
|
3
|
+
isSigningIn?: boolean;
|
|
4
|
+
error?: string | null;
|
|
5
|
+
forgotPasswordTo: string;
|
|
6
|
+
releasesTo?: string;
|
|
7
|
+
versionLabel?: string;
|
|
8
|
+
primaryButtonLabel?: string;
|
|
9
|
+
connectingLabel?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function SybilionSignInPanel({ onSignIn, isSigningIn, error, forgotPasswordTo, releasesTo, versionLabel, primaryButtonLabel, connectingLabel, }: SybilionSignInPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SybilionSignInPanel, type SybilionSignInPanelProps, } from './SybilionSignInPanel';
|
|
@@ -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;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export * from './contexts/theme-context';
|
|
2
|
+
export { DEFAULT_THEME_ACTIVE_COLOR } from './docs/lib/theme';
|
|
1
3
|
export * from './sybilion-auth';
|
|
2
4
|
export * from './types/sybilionDatasetSnapshots';
|
|
3
5
|
export * from './contexts/chat-context';
|
|
@@ -58,3 +60,6 @@ export * from './components/ui/VimeoEmbed';
|
|
|
58
60
|
export * from './components/ui/WorkspaceAppSwitcher';
|
|
59
61
|
export * from './components/widgets/SidebarDatasetsItemsGrouped';
|
|
60
62
|
export * from './components/widgets/SybilionAppHeader';
|
|
63
|
+
export * from './components/widgets/SybilionAuthLayout';
|
|
64
|
+
export * from './components/widgets/SybilionSignInPanel';
|
|
65
|
+
export * from './components/widgets/SignInPage';
|
package/docs/standalone-apps.md
CHANGED
|
@@ -40,15 +40,17 @@ Import tokens/fonts once (typically `src/main.tsx`):
|
|
|
40
40
|
import '@sybilion/uilib/standalone-global.css';
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
### Branding (
|
|
43
|
+
### Branding (static SVGs + optional tab icon)
|
|
44
44
|
|
|
45
|
-
**Header:** **`
|
|
45
|
+
**Header + auth hero:** Copy packaged SVGs into **`public/`** so **`Logo`** (**`SYBILION_STANDALONE_LOGO_PUBLIC_URL`** → **`/logo.svg`**) and **`SybilionAuthLayout`** (**`SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL`** → **`/sybilion_bg.svg`**) resolve at runtime. Package paths: **`@sybilion/uilib/logo.svg`**, **`@sybilion/uilib/sybilion-bg.svg`**.
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
mkdir -p public
|
|
48
|
+
mkdir -p public \
|
|
49
|
+
&& cp node_modules/@sybilion/uilib/logo.svg public/logo.svg \
|
|
50
|
+
&& cp node_modules/@sybilion/uilib/sybilion-bg.svg public/sybilion_bg.svg
|
|
49
51
|
```
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
Logo source in the package: **`src/assets/logo.svg`** (**cyan** glyph).
|
|
52
54
|
|
|
53
55
|
**Browser tab (optional):** The favicon (tiny icon next to the tab title) and the document title come from **`index.html`**, not from React. **`Logo`** does not set them. To replace Vite’s default tab icon with the package logo, add **`href="/logo.svg"`** — same as **`SYBILION_STANDALONE_LOGO_PUBLIC_URL`** from **`@sybilion/uilib`** — plus **`<title>`** in **`index.html`** `<head>`:
|
|
54
56
|
|
|
@@ -266,6 +268,20 @@ useEffect(() => {
|
|
|
266
268
|
|
|
267
269
|
Pass `user` (or `null` while loading with `isLoading` on `NavUserHeader`) and `isAuthenticated` to `SybilionAppHeader`.
|
|
268
270
|
|
|
271
|
+
### Sign-in page (unauthenticated)
|
|
272
|
+
|
|
273
|
+
Agents building the Auth0 entry route:
|
|
274
|
+
|
|
275
|
+
1. **Public assets:** Same **`public/`** SVG setup as §1 _Branding (static SVGs + optional tab icon)_ (**`/sybilion_bg.svg`** for **`SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL`** / **`SybilionAuthLayout`**).
|
|
276
|
+
|
|
277
|
+
2. **Routing:** Register **`/sign-in`** (and your Auth0 **`/callback`** route if applicable) **outside** **`AppLayout`** — full viewport auth chrome must not sit under **`AppShell`** / sidebar / **`SybilionAppHeader`**. Pattern: top-level `<Routes>` with `<Route path="/sign-in" … />` as a sibling of the branch that renders **`AppLayout`**, both wrapped by **`SybilionAuthProvider`** (§3).
|
|
278
|
+
|
|
279
|
+
3. **Composition:**
|
|
280
|
+
- **`SignInPage`** (`@sybilion/uilib`) — drop-in when **`SybilionAuthProvider`** wraps the tree. Calls **`useSybilionAuth`**. **`loginWithRedirect`** merges defaults (`prompt`, `screen_hint`, `origin`) with optional **`loginRedirectOptions`** / **`authorizationParams`** for tenant-specific **`connection`** or audiences.
|
|
281
|
+
- **Custom:** compose **`SybilionAuthLayout`** + **`SybilionSignInPanel`** and wire **`loginWithRedirect`** yourself from **`useSybilionAuth`**.
|
|
282
|
+
|
|
283
|
+
4. **Footer chip:** Pass **`versionLabel`** into **`SignInPage`** (or **`SybilionSignInPanel`**) when you want **`v…`** linked to **`releasesTo`** (default **`/releases`**).
|
|
284
|
+
|
|
269
285
|
## 4. Layout (AppShell)
|
|
270
286
|
|
|
271
287
|
With §2 `sybilionSdk` and §3 `AppProviders` / `SybilionAuthProvider` defined, compose routing + shell so Auth0 callbacks and JWT-backed hooks wrap the whole UI.
|
|
@@ -376,7 +392,11 @@ Wire **`authenticated`**, **`user`** / **`isAuthenticated`**, **`theme`** / **`o
|
|
|
376
392
|
|
|
377
393
|
#### Sidebar (`AppSidebar.tsx`)
|
|
378
394
|
|
|
379
|
-
App-specific sidebar component — keeps the navigation surface out of `AppLayout` so the shell stays generic.
|
|
395
|
+
App-specific sidebar component — keeps the navigation surface out of `AppLayout` so the shell stays generic.
|
|
396
|
+
|
|
397
|
+
**One sidebar group (default):** Standalone apps use **a single `SidebarGroup`** for the whole sidebar menu unless the **product owner explicitly asks** for another section separated into its own group. **`SidebarDatasetsItemsGrouped`** ([`src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.tsx`](../../src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.tsx)) already renders **one** outer `SidebarGroup` — put primary routes (Home, Datasets, …) in **`preItems`** or **`postItems`** so nav and dataset rows share that group instead of wrapping routes in a separate **`SidebarGroup`** above/below the widget. Apps without datasets: one **`SidebarGroup`** + **`SidebarMenu`** / **`SidebarMenuItem`** only.
|
|
398
|
+
|
|
399
|
+
Collapsible dataset clusters + nested rows: demo **`src/docs/pages/SidebarDatasetsItemsGroupedPage.tsx`** (slug **`sidebar-datasets-items-grouped`**). Other primitives: **`Sidebar`** + **`SidebarContent`** + **`SidebarMenu*`**.
|
|
380
400
|
|
|
381
401
|
```tsx
|
|
382
402
|
import { useEffect, useState } from 'react';
|
|
@@ -387,8 +407,6 @@ import {
|
|
|
387
407
|
SidebarContent,
|
|
388
408
|
SidebarDatasetsItemsGrouped,
|
|
389
409
|
type SidebarDatasetsItemsGroupedDataset,
|
|
390
|
-
SidebarGroup,
|
|
391
|
-
SidebarMenu,
|
|
392
410
|
SidebarMenuButton,
|
|
393
411
|
SidebarMenuItem,
|
|
394
412
|
} from '@sybilion/uilib';
|
|
@@ -411,27 +429,26 @@ export function AppSidebar() {
|
|
|
411
429
|
return (
|
|
412
430
|
<Sidebar variant="inset" collapsible="offcanvas">
|
|
413
431
|
<SidebarContent>
|
|
414
|
-
<SidebarGroup>
|
|
415
|
-
<SidebarMenu>
|
|
416
|
-
<SidebarMenuItem>
|
|
417
|
-
<SidebarMenuButton asChild>
|
|
418
|
-
<NavLink to="/" end>
|
|
419
|
-
Home
|
|
420
|
-
</NavLink>
|
|
421
|
-
</SidebarMenuButton>
|
|
422
|
-
</SidebarMenuItem>
|
|
423
|
-
<SidebarMenuItem>
|
|
424
|
-
<SidebarMenuButton asChild>
|
|
425
|
-
<NavLink to="/datasets">Datasets</NavLink>
|
|
426
|
-
</SidebarMenuButton>
|
|
427
|
-
</SidebarMenuItem>
|
|
428
|
-
</SidebarMenu>
|
|
429
|
-
</SidebarGroup>
|
|
430
|
-
|
|
431
432
|
<SidebarDatasetsItemsGrouped
|
|
432
433
|
groupBy="regions"
|
|
433
434
|
datasets={datasets}
|
|
434
435
|
selectedDatasetId={selectedDatasetId}
|
|
436
|
+
preItems={
|
|
437
|
+
<>
|
|
438
|
+
<SidebarMenuItem>
|
|
439
|
+
<SidebarMenuButton asChild>
|
|
440
|
+
<NavLink to="/" end>
|
|
441
|
+
Home
|
|
442
|
+
</NavLink>
|
|
443
|
+
</SidebarMenuButton>
|
|
444
|
+
</SidebarMenuItem>
|
|
445
|
+
<SidebarMenuItem>
|
|
446
|
+
<SidebarMenuButton asChild>
|
|
447
|
+
<NavLink to="/datasets">Datasets</NavLink>
|
|
448
|
+
</SidebarMenuButton>
|
|
449
|
+
</SidebarMenuItem>
|
|
450
|
+
</>
|
|
451
|
+
}
|
|
435
452
|
onDatasetClick={id => {
|
|
436
453
|
setSelectedDatasetId(id);
|
|
437
454
|
navigate(`/datasets/${id}`);
|
|
@@ -488,18 +505,19 @@ Composition: `PageScroll` → `AppShell` → `AppSidebar` → `AppShellMainConte
|
|
|
488
505
|
|
|
489
506
|
### Greenfield checklist (agents)
|
|
490
507
|
|
|
491
|
-
| Step | Deliverable
|
|
492
|
-
| ------------------ |
|
|
493
|
-
| React / router | **`react`**, **`react-dom`**, **`react-router-dom`**, **`@auth0/auth0-react`** (and **`vite`** if applicable) aligned with **`@sybilion/uilib`** **`package.json`** — §1 _React ecosystem versions_.
|
|
494
|
-
| Env files | **`.env.example`** (committed) + **`.env`** locally; **`PORT=3000`** recommended for Auth0 test tenant; **`VITE_*`** as in §1 table.
|
|
495
|
-
| Scripts | **`package.json`** includes mandatory **`dev`** (e.g. `"vite"`); optional **`build`**, **`preview`**.
|
|
496
|
-
| Vite proxy | **`vite.config.ts`** spreads **`sybilionStandaloneViteDev({ mode })`**; SDK **`baseUrl`** empty in dev (§2).
|
|
497
|
-
| Files | `src/libs/sybilion-sdk.ts`, `AppProviders.tsx`, `AppLayout.tsx`, `AppSidebar.tsx`, `App.tsx`, `main.tsx`, route pages under e.g. `src/pages/`.
|
|
498
|
-
| Branding | **`public/logo.svg`**
|
|
499
|
-
|
|
|
500
|
-
|
|
|
501
|
-
|
|
|
502
|
-
|
|
|
508
|
+
| Step | Deliverable |
|
|
509
|
+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
510
|
+
| React / router | **`react`**, **`react-dom`**, **`react-router-dom`**, **`@auth0/auth0-react`** (and **`vite`** if applicable) aligned with **`@sybilion/uilib`** **`package.json`** — §1 _React ecosystem versions_. |
|
|
511
|
+
| Env files | **`.env.example`** (committed) + **`.env`** locally; **`PORT=3000`** recommended for Auth0 test tenant; **`VITE_*`** as in §1 table. |
|
|
512
|
+
| Scripts | **`package.json`** includes mandatory **`dev`** (e.g. `"vite"`); optional **`build`**, **`preview`**. |
|
|
513
|
+
| Vite proxy | **`vite.config.ts`** spreads **`sybilionStandaloneViteDev({ mode })`**; SDK **`baseUrl`** empty in dev (§2). |
|
|
514
|
+
| Files | `src/libs/sybilion-sdk.ts`, `AppProviders.tsx`, `AppLayout.tsx`, `AppSidebar.tsx`, `App.tsx`, `main.tsx`, route pages under e.g. `src/pages/`. |
|
|
515
|
+
| Branding | §1 _Branding_: **`public/logo.svg`** + **`public/sybilion_bg.svg`** (one **`mkdir` + two `cp`** block). **`index.html`**: `<title>`; optional **`<link rel="icon">`** for tab icon. |
|
|
516
|
+
| Sign-in | §3 _Sign-in page (unauthenticated)_: **`SignInPage`** or **`SybilionAuthLayout`** + **`SybilionSignInPanel`**; **`/sign-in`** not inside **`AppLayout`**; **`SybilionAuthProvider`** wraps router. |
|
|
517
|
+
| Pages + UI | **§4 Route page body** (mandatory stack) + **Discovering** (barrel-first; bespoke markup only when no export fits). |
|
|
518
|
+
| Auth0 | SPA callback / logout URLs + allowed web origins → **`http://localhost:<PORT>`** for local dev and deploy URLs (and previews). |
|
|
519
|
+
| API | **Dev:** proxy handles API traffic (no browser CORS to API). **Prod:** Sybilion backend **CORS** → your deploy `Origin`, unless API is same-origin. |
|
|
520
|
+
| Go (if applicable) | Server proxies **`/api`** to Sybilion; SPA dev **`baseUrl`** stays `''` when same-origin. |
|
|
503
521
|
|
|
504
522
|
### Glossary (high-use pieces)
|
|
505
523
|
|
|
@@ -513,12 +531,15 @@ Composition: `PageScroll` → `AppShell` → `AppSidebar` → `AppShellMainConte
|
|
|
513
531
|
| `NavUserHeader` | Header user menu (avatar, account, theme, logout). |
|
|
514
532
|
| `Sidebar`, `SidebarProvider` | Collapsible rail + context (`@sybilion/uilib`). Wrap `SidebarProvider` above `AppLayout`; render `Sidebar` inside `AppShell` (usually via `AppSidebar`). |
|
|
515
533
|
| `AppSidebar` | App-specific component (`src/AppSidebar.tsx`) composing `Sidebar` + nav links + product widgets. Keeps `AppLayout` generic. |
|
|
516
|
-
| `SidebarDatasetsItemsGrouped` |
|
|
534
|
+
| `SidebarDatasetsItemsGrouped` | Single-sidebar-group widget: **`preItems`** / **`postItems`** for main nav + collapsible dataset groups (`regions` / `target_type` / `categories`) + **`onDatasetClick`**. Prefer this over stacking multiple **`SidebarGroup`** blocks unless explicitly requested. Source: **`src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.tsx`**. |
|
|
517
535
|
| `SidebarTrigger` | Toggle sidebar visibility (especially mobile / `offcanvas`). |
|
|
518
536
|
| `PageFooter` | Standard footer; requires `versionLink` + `versionLabel`. |
|
|
519
537
|
| `Gap` | Spacing primitive between flex children. |
|
|
520
538
|
| `PageHeader`, `PageContent`, `PageContentSection`, … | **§4 Route page body** (roles, `breadcrumbSidebarTrigger`, example). Same barrel also has `PageTabs`, `PageColumns`, `SectionHeader`, `PageEmptyCanvas`, … |
|
|
521
539
|
| `SybilionAuthProvider` | Auth0 + Sybilion JWT (§3). |
|
|
540
|
+
| `SignInPage` | Full sign-in route using **`SybilionAuthLayout`** + **`SybilionSignInPanel`** + **`useSybilionAuth`**; §3 sign-in subsection. |
|
|
541
|
+
| `SybilionAuthLayout` | Split-view auth chrome (hero + form column); optional **`heroBackgroundUrl`** (default **`/sybilion_bg.svg`**). |
|
|
542
|
+
| `SybilionSignInPanel` | Presentational primary button, error line, forgot-password link, optional version link; §3 sign-in subsection. |
|
|
522
543
|
| `useSybilionAuth` | User session + login/logout under provider. |
|
|
523
544
|
| `useSybilionApiFetch` | Authenticated `fetch` using stored JWT. |
|
|
524
545
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sybilion/uilib",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"description": "Sybilion Design System — React UI components (Webpack + Stylus)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"import": "./dist/standalone/vite-sybilion-standalone-dev.js",
|
|
37
37
|
"default": "./dist/standalone/vite-sybilion-standalone-dev.js"
|
|
38
38
|
},
|
|
39
|
-
"./logo.svg": "./src/assets/logo.svg"
|
|
39
|
+
"./logo.svg": "./src/assets/logo.svg",
|
|
40
|
+
"./sybilion-bg.svg": "./src/assets/sybilion_bg.svg"
|
|
40
41
|
},
|
|
41
42
|
"files": [
|
|
42
43
|
"assets",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg width="312" height="309" viewBox="0 0 312 309" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect x="268.707" y="206.636" width="43.2928" height="57.7237" fill="#8EE9F7"/>
|
|
3
|
+
<rect width="43.2928" height="57.7237" transform="matrix(4.37114e-08 -1 -1 -4.37114e-08 106.365 43.848)" fill="#8EE9F7"/>
|
|
4
|
+
<rect x="268.707" y="206.639" width="57.7237" height="104.624" transform="rotate(180 268.707 206.639)" fill="#8EE9F7"/>
|
|
5
|
+
<rect x="48.6343" y="43.848" width="57.7237" height="104.624" transform="rotate(90 48.6343 43.848)" fill="#8EE9F7"/>
|
|
6
|
+
<rect width="57.7237" height="104.624" transform="matrix(-4.37114e-08 1 1 4.37114e-08 106.365 43.848)" fill="#8EE9F7"/>
|
|
7
|
+
<rect width="57.7237" height="104.624" transform="matrix(-1 0 0 1 268.707 264.36)" fill="#8EE9F7"/>
|
|
8
|
+
</svg>
|