@sybilion/uilib 1.2.6 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/assets/standalone-global.css +12 -11
  2. package/dist/esm/components/ui/Logo/Logo.js +7 -2
  3. package/dist/esm/components/ui/Logo/Logo.styl.js +1 -1
  4. package/dist/esm/components/ui/NavUserHeader/NavUserHeader.js +4 -2
  5. package/dist/esm/components/widgets/SignInPage/SignInPage.js +25 -0
  6. package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.js +8 -0
  7. package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl.js +7 -0
  8. package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthLayout.js +16 -0
  9. package/dist/esm/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl.js +7 -0
  10. package/dist/esm/components/widgets/SybilionSignInPanel/SybilionSignInPanel.js +11 -0
  11. package/dist/esm/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl.js +7 -0
  12. package/dist/esm/docs/contexts/theme-context.js +14 -0
  13. package/dist/esm/docs/lib/theme.js +23 -0
  14. package/dist/esm/index.js +4 -0
  15. package/dist/esm/types/src/components/ui/Logo/Logo.d.ts +5 -0
  16. package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.d.ts +1 -1
  17. package/dist/esm/types/src/components/ui/NavUserHeader/NavUserHeader.types.d.ts +0 -4
  18. package/dist/esm/types/src/components/widgets/SignInPage/SignInPage.d.ts +10 -0
  19. package/dist/esm/types/src/components/widgets/SignInPage/index.d.ts +1 -0
  20. package/dist/esm/types/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.d.ts +1 -0
  21. package/dist/esm/types/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.d.ts +14 -0
  22. package/dist/esm/types/src/components/widgets/SybilionAuthLayout/index.d.ts +2 -0
  23. package/dist/esm/types/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.d.ts +11 -0
  24. package/dist/esm/types/src/components/widgets/SybilionSignInPanel/index.d.ts +1 -0
  25. package/dist/esm/types/src/docs/contexts/theme-context.d.ts +1 -0
  26. package/dist/esm/types/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.constants.d.ts +7 -0
  27. package/dist/esm/types/src/index.d.ts +3 -0
  28. package/docs/standalone-apps.md +38 -0
  29. package/package.json +4 -2
  30. package/src/assets/logo.svg +3 -0
  31. package/src/assets/sybilion_bg.svg +8 -0
  32. package/src/components/ui/Logo/Logo.styl +2 -0
  33. package/src/components/ui/Logo/Logo.tsx +12 -1
  34. package/src/components/ui/NavUserHeader/NavUserHeader.tsx +15 -17
  35. package/src/components/ui/NavUserHeader/NavUserHeader.types.ts +0 -4
  36. package/src/components/widgets/SignInPage/SignInPage.tsx +84 -0
  37. package/src/components/widgets/SignInPage/index.ts +1 -0
  38. package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl +26 -0
  39. package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.styl.d.ts +2 -0
  40. package/src/components/widgets/SybilionAuthLayout/SybilionAuthHeadline.tsx +18 -0
  41. package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl +79 -0
  42. package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.styl.d.ts +2 -0
  43. package/src/components/widgets/SybilionAuthLayout/SybilionAuthLayout.tsx +64 -0
  44. package/src/components/widgets/SybilionAuthLayout/index.ts +6 -0
  45. package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl +48 -0
  46. package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.styl.d.ts +2 -0
  47. package/src/components/widgets/SybilionSignInPanel/SybilionSignInPanel.tsx +59 -0
  48. package/src/components/widgets/SybilionSignInPanel/index.ts +4 -0
  49. package/src/docs/config/webpack.config.js +4 -3
  50. package/src/docs/contexts/theme-context.tsx +14 -1
  51. package/src/docs/pages/NavUserHeaderPage.tsx +1 -20
  52. package/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.constants.ts +444 -0
  53. package/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.tsx +9 -456
  54. package/src/index.ts +3 -0
@@ -0,0 +1,84 @@
1
+ import type { RedirectLoginOptions } from '@auth0/auth0-react';
2
+
3
+ import {
4
+ SybilionAuthLayout,
5
+ type SybilionAuthLayoutProps,
6
+ } from '#uilib/components/widgets/SybilionAuthLayout';
7
+ import { useSybilionAuth } from '#uilib/sybilion-auth/SybilionAuthProvider';
8
+
9
+ import {
10
+ SybilionSignInPanel,
11
+ type SybilionSignInPanelProps,
12
+ } from '../SybilionSignInPanel';
13
+
14
+ export type SignInPageProps = Pick<
15
+ SybilionAuthLayoutProps,
16
+ 'heroBackgroundUrl' | 'logoSize' | 'containerClassName'
17
+ > &
18
+ Pick<
19
+ SybilionSignInPanelProps,
20
+ | 'forgotPasswordTo'
21
+ | 'releasesTo'
22
+ | 'versionLabel'
23
+ | 'primaryButtonLabel'
24
+ | 'connectingLabel'
25
+ > & {
26
+ title?: string;
27
+ subtitle?: string;
28
+ /** Extra Auth0 `loginWithRedirect` options; merged with default sign-in params. */
29
+ loginRedirectOptions?: RedirectLoginOptions;
30
+ };
31
+
32
+ const DEFAULT_TITLE = 'Sign In';
33
+ const DEFAULT_SUBTITLE =
34
+ 'To get access authenticate through google or your email.';
35
+
36
+ export function SignInPage({
37
+ title = DEFAULT_TITLE,
38
+ subtitle = DEFAULT_SUBTITLE,
39
+ forgotPasswordTo = '/forgot-password',
40
+ releasesTo = '/releases',
41
+ versionLabel,
42
+ primaryButtonLabel,
43
+ connectingLabel,
44
+ loginRedirectOptions,
45
+ heroBackgroundUrl,
46
+ logoSize,
47
+ containerClassName,
48
+ }: SignInPageProps) {
49
+ const { error, loginWithRedirect, isLoading } = useSybilionAuth();
50
+
51
+ const handleSignIn = () =>
52
+ loginWithRedirect({
53
+ ...loginRedirectOptions,
54
+ authorizationParams: {
55
+ prompt: 'login',
56
+ screen_hint: 'login',
57
+ ...(typeof window !== 'undefined'
58
+ ? { origin: window.location.origin }
59
+ : {}),
60
+ ...loginRedirectOptions?.authorizationParams,
61
+ },
62
+ });
63
+
64
+ return (
65
+ <SybilionAuthLayout
66
+ title={title}
67
+ subtitle={subtitle}
68
+ heroBackgroundUrl={heroBackgroundUrl}
69
+ logoSize={logoSize}
70
+ containerClassName={containerClassName}
71
+ >
72
+ <SybilionSignInPanel
73
+ onSignIn={handleSignIn}
74
+ isSigningIn={isLoading}
75
+ error={error}
76
+ forgotPasswordTo={forgotPasswordTo}
77
+ releasesTo={releasesTo}
78
+ versionLabel={versionLabel}
79
+ primaryButtonLabel={primaryButtonLabel}
80
+ connectingLabel={connectingLabel}
81
+ />
82
+ </SybilionAuthLayout>
83
+ );
84
+ }
@@ -0,0 +1 @@
1
+ export { SignInPage, type SignInPageProps } from './SignInPage';
@@ -0,0 +1,26 @@
1
+ .root
2
+ display flex
3
+ flex-direction column
4
+ justify-content center
5
+ align-items center
6
+ width 100%
7
+ padding 64px 48px
8
+ position relative
9
+ z-index 10
10
+ height 100%
11
+ font-family var(--font-family-heading)
12
+ font-weight 300
13
+ text-shadow 0 0 2px var(--background)
14
+
15
+ .headline
16
+ font-size 40px
17
+ line-height 48px
18
+ text-align left
19
+ width 100%
20
+ max-width 480px
21
+
22
+ .headlineParagraph
23
+ margin 0
24
+
25
+ .headlineCyan
26
+ color #27d1ef
@@ -0,0 +1,2 @@
1
+ const mod: { [cls: string]: string };
2
+ export default mod;
@@ -0,0 +1,18 @@
1
+ import S from './SybilionAuthHeadline.styl';
2
+
3
+ export function SybilionAuthHeadline() {
4
+ return (
5
+ <div className={S.root}>
6
+ <div className={S.headline}>
7
+ <p className={S.headlineParagraph}>
8
+ <span>External volatility</span>
9
+ <span></span>
10
+ </p>
11
+ <p className={S.headlineParagraph}>turned into</p>
12
+ <p className={S.headlineParagraph}>
13
+ <span className={S.headlineCyan}>confident decisions</span>
14
+ </p>
15
+ </div>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,79 @@
1
+ .root
2
+ height 100vh
3
+ display flex
4
+ width 100%
5
+
6
+ .leftPanel
7
+ display none
8
+
9
+ @media (min-width: 768px)
10
+ display flex
11
+ width 50%
12
+ position relative
13
+ overflow hidden
14
+ background-color var(--secondary)
15
+ border-top-left-radius var(--p-6)
16
+ border-bottom-left-radius var(--p-6)
17
+ border-top-right-radius var(--p-1)
18
+ border-bottom-right-radius var(--p-1)
19
+
20
+ :global(.dark) &
21
+ background-color var(--page-color-alpha-800)
22
+
23
+ .bgImage
24
+ position absolute
25
+ bottom 0
26
+ left 0
27
+ width 300px
28
+ height 300px
29
+ background-size contain
30
+ background-repeat no-repeat
31
+ background-position left bottom
32
+
33
+ .logoContainer
34
+ z-index 10
35
+ position absolute
36
+ top 0
37
+ left 0
38
+ display flex
39
+ align-items center
40
+ min-height 94px
41
+ padding 16px 48px
42
+
43
+ .logo
44
+ width 24px
45
+ height 24px
46
+
47
+ .rightPanel
48
+ flex 1
49
+ background-color var(--background)
50
+ display flex
51
+ flex-direction column
52
+ justify-content center
53
+ align-items center
54
+ padding 48px 64px
55
+
56
+ .formContainer
57
+ // position relative
58
+ max-width 480px
59
+ width 100%
60
+
61
+ .header
62
+ margin-bottom 36px
63
+
64
+ .title
65
+ font-family var(--font-family-heading)
66
+ font-weight normal
67
+ font-size 30px
68
+ line-height 42px
69
+ margin 0
70
+ margin-bottom 6px
71
+ color var(--foreground)
72
+
73
+ .subtitle
74
+ font-size 14px
75
+ color var(--muted-foreground)
76
+ line-height 16px
77
+ margin 0
78
+ font-family 'Manrope', sans-serif
79
+ font-weight 500
@@ -0,0 +1,2 @@
1
+ const mod: { [cls: string]: string };
2
+ export default mod;
@@ -0,0 +1,64 @@
1
+ import cn from 'classnames';
2
+ import type { ReactNode } from 'react';
3
+
4
+ import { Logo } from '#uilib/components/ui/Logo/Logo';
5
+ import type { LogoSize } from '#uilib/components/ui/Logo/Logo.types';
6
+
7
+ import { SybilionAuthHeadline } from './SybilionAuthHeadline';
8
+ import S from './SybilionAuthLayout.styl';
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
+ export type SybilionAuthLayoutProps = {
15
+ title: string;
16
+ subtitle?: string;
17
+ children: ReactNode;
18
+ logoSize?: LogoSize;
19
+ containerClassName?: string;
20
+ /** Public URL for the hero watermark SVG (default {@link SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL}). */
21
+ heroBackgroundUrl?: string;
22
+ };
23
+
24
+ export function SybilionAuthLayout({
25
+ title,
26
+ subtitle,
27
+ children,
28
+ logoSize,
29
+ containerClassName,
30
+ heroBackgroundUrl = SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL,
31
+ }: SybilionAuthLayoutProps) {
32
+ const bg = heroBackgroundUrl
33
+ ? `url(${JSON.stringify(heroBackgroundUrl)})`
34
+ : 'none';
35
+
36
+ return (
37
+ <div className={S.root}>
38
+ <div className={S.leftPanel}>
39
+ <div
40
+ className={S.bgImage}
41
+ style={{ backgroundImage: bg }}
42
+ aria-hidden
43
+ />
44
+
45
+ <div className={S.logoContainer}>
46
+ <Logo className={S.logo} size={logoSize} />
47
+ </div>
48
+
49
+ <SybilionAuthHeadline />
50
+ </div>
51
+
52
+ <div className={S.rightPanel}>
53
+ <div className={cn(S.formContainer, containerClassName)}>
54
+ <div className={S.header}>
55
+ <h1 className={S.title}>{title}</h1>
56
+ {subtitle && <p className={S.subtitle}>{subtitle}</p>}
57
+ </div>
58
+
59
+ {children}
60
+ </div>
61
+ </div>
62
+ </div>
63
+ );
64
+ }
@@ -0,0 +1,6 @@
1
+ export {
2
+ SybilionAuthLayout,
3
+ SYBILION_STANDALONE_AUTH_HERO_BG_PUBLIC_URL,
4
+ type SybilionAuthLayoutProps,
5
+ } from './SybilionAuthLayout';
6
+ export { SybilionAuthHeadline } from './SybilionAuthHeadline';
@@ -0,0 +1,48 @@
1
+ .socialButtonContainer
2
+ display flex
3
+ width 100%
4
+ gap 10px
5
+ margin-bottom 10px
6
+
7
+ .socialButton
8
+ flex 1
9
+ height 48px
10
+ padding 14px 16px
11
+ font-size 14px
12
+ font-weight 600
13
+ border-radius 14px
14
+ border 1px solid var(--border)
15
+
16
+ .errorMessage
17
+ color red
18
+ padding 10px
19
+ font-size 14px
20
+ margin-bottom 10px
21
+
22
+ .forgotPassword
23
+ text-align right
24
+ margin-bottom 24px
25
+
26
+ .forgotPasswordLink
27
+ color var(--primary)
28
+ text-decoration none
29
+ font-size 14px
30
+ font-family 'Manrope', sans-serif
31
+ font-weight 500
32
+ transition opacity 0.2s
33
+
34
+ &:hover
35
+ opacity 0.8
36
+
37
+ .version
38
+ display block
39
+ margin-top var(--p-8)
40
+ padding-bottom var(--p-2)
41
+ width 100%
42
+ box-sizing border-box
43
+ text-align center
44
+ font-size 14px
45
+ color var(--muted-foreground)
46
+ opacity 0.5
47
+ transition opacity 0.3s ease-out
48
+ white-space nowrap
@@ -0,0 +1,2 @@
1
+ const mod: { [cls: string]: string };
2
+ export default mod;
@@ -0,0 +1,59 @@
1
+ import { Link } from 'react-router-dom';
2
+
3
+ import { Button } from '#uilib/components/ui/Button';
4
+
5
+ import S from './SybilionSignInPanel.styl';
6
+
7
+ export type SybilionSignInPanelProps = {
8
+ onSignIn: () => void | Promise<void>;
9
+ isSigningIn?: boolean;
10
+ error?: string | null;
11
+ forgotPasswordTo: string;
12
+ releasesTo?: string;
13
+ versionLabel?: string;
14
+ primaryButtonLabel?: string;
15
+ connectingLabel?: string;
16
+ };
17
+
18
+ export function SybilionSignInPanel({
19
+ onSignIn,
20
+ isSigningIn = false,
21
+ error,
22
+ forgotPasswordTo,
23
+ releasesTo,
24
+ versionLabel,
25
+ primaryButtonLabel = 'Sign-in',
26
+ connectingLabel = 'Connecting...',
27
+ }: SybilionSignInPanelProps) {
28
+ const signingIn = Boolean(isSigningIn);
29
+
30
+ return (
31
+ <>
32
+ <div className={S.socialButtonContainer}>
33
+ <Button
34
+ variant="outline"
35
+ type="button"
36
+ className={S.socialButton}
37
+ onClick={() => void onSignIn()}
38
+ disabled={signingIn}
39
+ >
40
+ {signingIn ? connectingLabel : primaryButtonLabel}
41
+ </Button>
42
+ </div>
43
+
44
+ {error ? <div className={S.errorMessage}>{error}</div> : null}
45
+
46
+ <div className={S.forgotPassword}>
47
+ <Link to={forgotPasswordTo} className={S.forgotPasswordLink}>
48
+ Forgot password?
49
+ </Link>
50
+ </div>
51
+
52
+ {releasesTo && versionLabel ? (
53
+ <Link className={S.version} to={releasesTo}>
54
+ v{versionLabel}
55
+ </Link>
56
+ ) : null}
57
+ </>
58
+ );
59
+ }
@@ -0,0 +1,4 @@
1
+ export {
2
+ SybilionSignInPanel,
3
+ type SybilionSignInPanelProps,
4
+ } from './SybilionSignInPanel';
@@ -20,6 +20,7 @@ const FaviconWebpackPlugin = require('favicons-webpack-plugin');
20
20
  const pkg = require('../../../package.json');
21
21
 
22
22
  const themeStyl = pathResolve(paths.src, 'theme.styl');
23
+ const logoSvgPath = pathResolve(paths.assets, 'logo.svg');
23
24
 
24
25
  export default (env, argv) => {
25
26
  const isDev = argv.mode === 'development';
@@ -148,7 +149,7 @@ export default (env, argv) => {
148
149
  noErrorOnMissing: true,
149
150
  },
150
151
  {
151
- from: `${paths.assets}/logo.svg`,
152
+ from: logoSvgPath,
152
153
  to: paths.build,
153
154
  noErrorOnMissing: true,
154
155
  },
@@ -175,9 +176,9 @@ export default (env, argv) => {
175
176
  minifyURLs: true,
176
177
  },
177
178
  }),
178
- existsSync(`${paths.assets}/logo.svg`) &&
179
+ existsSync(logoSvgPath) &&
179
180
  new FaviconWebpackPlugin({
180
- logo: `${paths.assets}/logo.svg`,
181
+ logo: logoSvgPath,
181
182
  mode: 'webapp',
182
183
  devMode: 'webapp',
183
184
  favicons: {
@@ -1,4 +1,10 @@
1
- import { createContext, useContext, useEffect, useState } from 'react';
1
+ import {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useState,
7
+ } from 'react';
2
8
 
3
9
  import { Theme as ThemeRoot } from '@homecode/ui';
4
10
 
@@ -10,10 +16,12 @@ const ThemeContext = createContext<{
10
16
  theme: ThemeMode;
11
17
  isDarkMode: boolean;
12
18
  setTheme: (theme: ThemeMode) => void;
19
+ toggleTheme: () => void;
13
20
  }>({
14
21
  theme: 'light',
15
22
  isDarkMode: false,
16
23
  setTheme: () => {},
24
+ toggleTheme: () => {},
17
25
  });
18
26
 
19
27
  export function ThemeProvider({ children }: { children: React.ReactNode }) {
@@ -25,6 +33,10 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
25
33
  getThemeConfig(theme === 'dark'),
26
34
  );
27
35
 
36
+ const toggleTheme = useCallback(() => {
37
+ setTheme(theme === 'dark' ? 'light' : 'dark');
38
+ }, [theme, setTheme]);
39
+
28
40
  useEffect(() => {
29
41
  setCurrThemeConfig(getThemeConfig(theme === 'dark'));
30
42
  }, [theme]);
@@ -44,6 +56,7 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
44
56
  theme,
45
57
  isDarkMode: theme === 'dark',
46
58
  setTheme,
59
+ toggleTheme,
47
60
  }}
48
61
  >
49
62
  <ThemeRoot config={currThemeConfig} />
@@ -1,5 +1,3 @@
1
- import { useCallback, useEffect, useState } from 'react';
2
-
3
1
  import { DropdownMenuItem } from '#uilib/components/ui/DropdownMenu';
4
2
  import { NavUserHeader } from '#uilib/components/ui/NavUserHeader';
5
3
  import { PageContentSection } from '#uilib/components/ui/Page';
@@ -9,19 +7,6 @@ import { AppPageHeader } from '../components/AppPageHeader/AppPageHeader';
9
7
  import { DocsHeaderActions } from '../docsHeaderActions';
10
8
 
11
9
  export default function NavUserHeaderPage() {
12
- const [theme, setTheme] = useState<'light' | 'dark'>('light');
13
-
14
- useEffect(() => {
15
- document.documentElement.dataset.theme = theme;
16
- return () => {
17
- delete document.documentElement.dataset.theme;
18
- };
19
- }, [theme]);
20
-
21
- const onThemeToggle = useCallback(() => {
22
- setTheme(t => (t === 'dark' ? 'light' : 'dark'));
23
- }, []);
24
-
25
10
  const customMenuItems = (
26
11
  <>
27
12
  <DropdownMenuItem>
@@ -40,7 +25,7 @@ export default function NavUserHeaderPage() {
40
25
  <AppPageHeader
41
26
  breadcrumbs={[{ label: 'NavUserHeader' }]}
42
27
  title="NavUserHeader"
43
- subheader="User menu with label, custom rows, theme toggle, and logout."
28
+ subheader="User menu with label, custom rows, theme toggle (docs ThemeProvider), and logout."
44
29
  actions={<DocsHeaderActions />}
45
30
  />
46
31
  <PageContentSection
@@ -56,8 +41,6 @@ export default function NavUserHeaderPage() {
56
41
  email: 'demo@sybilion.io',
57
42
  avatar: '',
58
43
  }}
59
- theme={theme}
60
- onThemeToggle={onThemeToggle}
61
44
  onLogout={() => {
62
45
  console.info('[docs] logout');
63
46
  }}
@@ -75,8 +58,6 @@ export default function NavUserHeaderPage() {
75
58
  email: 'compact@sybilion.io',
76
59
  avatar: '',
77
60
  }}
78
- theme={theme}
79
- onThemeToggle={onThemeToggle}
80
61
  onLogout={() => {
81
62
  console.info('[docs] logout compact');
82
63
  }}