@visin/frontend-core 0.1.7 → 0.1.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 (29) hide show
  1. package/dist/components/AppLayout/AppLayout.d.ts +40 -0
  2. package/dist/components/AppLayout/AppLayout.d.ts.map +1 -0
  3. package/dist/components/AppLayout/AppLayout.js +108 -0
  4. package/dist/components/AppLayout/AppLayout.js.map +1 -0
  5. package/dist/components/AppLayout/index.d.ts +3 -0
  6. package/dist/components/AppLayout/index.d.ts.map +1 -0
  7. package/dist/components/AppLayout/index.js +2 -0
  8. package/dist/components/AppLayout/index.js.map +1 -0
  9. package/dist/components/LoginRedirect/LoginRedirect.d.ts +21 -0
  10. package/dist/components/LoginRedirect/LoginRedirect.d.ts.map +1 -0
  11. package/dist/components/LoginRedirect/LoginRedirect.js +57 -0
  12. package/dist/components/LoginRedirect/LoginRedirect.js.map +1 -0
  13. package/dist/components/LoginRedirect/index.d.ts +3 -0
  14. package/dist/components/LoginRedirect/index.d.ts.map +1 -0
  15. package/dist/components/LoginRedirect/index.js +2 -0
  16. package/dist/components/LoginRedirect/index.js.map +1 -0
  17. package/dist/components/ProtectedRoute/ProtectedRoute.d.ts +23 -0
  18. package/dist/components/ProtectedRoute/ProtectedRoute.d.ts.map +1 -0
  19. package/dist/components/ProtectedRoute/ProtectedRoute.js +33 -0
  20. package/dist/components/ProtectedRoute/ProtectedRoute.js.map +1 -0
  21. package/dist/components/ProtectedRoute/index.d.ts +3 -0
  22. package/dist/components/ProtectedRoute/index.d.ts.map +1 -0
  23. package/dist/components/ProtectedRoute/index.js +2 -0
  24. package/dist/components/ProtectedRoute/index.js.map +1 -0
  25. package/dist/index.d.ts +6 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -0
  28. package/dist/index.js.map +1 -1
  29. package/package.json +5 -2
@@ -0,0 +1,40 @@
1
+ import { ReactNode } from 'react';
2
+ export interface AppLayoutNavItem {
3
+ text: string;
4
+ icon: ReactNode;
5
+ path: string;
6
+ }
7
+ export interface AppLayoutFooterLink {
8
+ text: string;
9
+ icon: ReactNode;
10
+ href: string;
11
+ }
12
+ export interface AppLayoutUser {
13
+ name?: string;
14
+ email?: string;
15
+ picture?: string;
16
+ }
17
+ export interface AppLayoutProps {
18
+ children: ReactNode;
19
+ /** Shown in the mobile app bar and as the fallback desktop page title. */
20
+ appName: string;
21
+ /** Static description shown under the desktop page title. */
22
+ subtitle: string;
23
+ navItems: AppLayoutNavItem[];
24
+ user: AppLayoutUser | null;
25
+ onLogout: () => void;
26
+ /** Optional link pinned below the nav list, e.g. "Back to Vision". */
27
+ footerLink?: AppLayoutFooterLink;
28
+ /** Max width of the centered content column. Defaults to 800. */
29
+ maxContentWidth?: number;
30
+ }
31
+ /**
32
+ * Shared sidebar/appbar shell used by the account and label fronts: fixed
33
+ * dark drawer with nav items, mobile temporary drawer, avatar menu with
34
+ * logout, and a centered content column with a page title derived from the
35
+ * active nav item. vision-front's collapsible-drawer layout has different
36
+ * enough behavior (login/logout dual state, no page-title header) that it
37
+ * stays a standalone component rather than forcing it through these props.
38
+ */
39
+ export declare function AppLayout({ children, appName, subtitle, navItems, user, onLogout, footerLink, maxContentWidth }: AppLayoutProps): import("react").JSX.Element;
40
+ //# sourceMappingURL=AppLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/components/AppLayout/AppLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwB,MAAM,OAAO,CAAC;AA0BxD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,eAAqB,EACtB,EAAE,cAAc,+BAiQhB"}
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Drawer, List, Typography, Divider, ListItem, ListItemButton, ListItemIcon, ListItemText, Avatar, Menu, MenuItem, useTheme, CssBaseline, AppBar, Toolbar, IconButton } from '@mui/material';
4
+ import { alpha } from '@mui/material/styles';
5
+ import { Menu as MenuIcon, Logout, Person } from '@mui/icons-material';
6
+ import { Link, useLocation } from 'react-router-dom';
7
+ const DRAWER_WIDTH = 260;
8
+ /**
9
+ * Shared sidebar/appbar shell used by the account and label fronts: fixed
10
+ * dark drawer with nav items, mobile temporary drawer, avatar menu with
11
+ * logout, and a centered content column with a page title derived from the
12
+ * active nav item. vision-front's collapsible-drawer layout has different
13
+ * enough behavior (login/logout dual state, no page-title header) that it
14
+ * stays a standalone component rather than forcing it through these props.
15
+ */
16
+ export function AppLayout({ children, appName, subtitle, navItems, user, onLogout, footerLink, maxContentWidth = 800 }) {
17
+ const location = useLocation();
18
+ const theme = useTheme();
19
+ const [anchorElUser, setAnchorElUser] = useState(null);
20
+ const [mobileOpen, setMobileOpen] = useState(false);
21
+ const handleDrawerToggle = () => setMobileOpen(!mobileOpen);
22
+ const handleOpenUserMenu = (event) => setAnchorElUser(event.currentTarget);
23
+ const handleCloseUserMenu = () => setAnchorElUser(null);
24
+ // An exact match always wins; a prefix match only counts if no other nav
25
+ // item is an exact match for the current path (avoids '/jobs' lighting up
26
+ // while on '/jobs/new').
27
+ const isActive = (path) => location.pathname === path ||
28
+ (location.pathname.startsWith(path + '/') &&
29
+ !navItems.some((item) => item.path !== path && item.path === location.pathname));
30
+ const activeItem = navItems.find((item) => isActive(item.path));
31
+ const drawer = (_jsxs(Box, { sx: { height: '100%', display: 'flex', flexDirection: 'column', bgcolor: '#111827', color: '#fff' }, children: [_jsxs(Box, { sx: { p: 3, display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Box, { component: "img", src: "/logo.svg", alt: "Visin Logo", sx: { width: 32, height: 32 } }), _jsx(Typography, { variant: "h6", sx: { fontWeight: 700, color: 'inherit', letterSpacing: '-0.5px' }, children: "Visin" })] }), _jsx(List, { sx: { px: 2, flexGrow: 1 }, children: navItems.map((item) => {
32
+ const active = isActive(item.path);
33
+ return (_jsx(ListItem, { disablePadding: true, sx: { mb: 0.5 }, children: _jsxs(ListItemButton, { component: Link, to: item.path, selected: active, onClick: () => setMobileOpen(false), sx: {
34
+ borderRadius: 2,
35
+ py: 1.2,
36
+ color: 'rgba(255,255,255,0.7)',
37
+ '&.Mui-selected': {
38
+ bgcolor: alpha(theme.palette.primary.main, 0.15),
39
+ color: theme.palette.primary.light,
40
+ '&:hover': {
41
+ bgcolor: alpha(theme.palette.primary.main, 0.25)
42
+ },
43
+ '& .MuiListItemIcon-root': {
44
+ color: theme.palette.primary.light
45
+ }
46
+ },
47
+ '&:hover': {
48
+ bgcolor: 'rgba(255,255,255,0.05)',
49
+ color: '#fff',
50
+ '& .MuiListItemIcon-root': {
51
+ color: '#fff'
52
+ }
53
+ }
54
+ }, children: [_jsx(ListItemIcon, { sx: { minWidth: 40, color: active ? 'inherit' : 'rgba(255,255,255,0.5)' }, children: item.icon }), _jsx(ListItemText, { primary: item.text, slotProps: {
55
+ primary: { sx: { fontWeight: active ? 600 : 500, fontSize: '0.925rem' } }
56
+ } })] }) }, item.text));
57
+ }) }), footerLink && (_jsxs(_Fragment, { children: [_jsx(Divider, { sx: { mx: 2, opacity: 0.1, bgcolor: 'rgba(255,255,255,0.1)' } }), _jsx(List, { sx: { px: 2, py: 2 }, children: _jsx(ListItem, { disablePadding: true, children: _jsxs(ListItemButton, { component: "a", href: footerLink.href, sx: {
58
+ borderRadius: 2,
59
+ py: 1.2,
60
+ color: 'rgba(255,255,255,0.5)',
61
+ '&:hover': {
62
+ bgcolor: 'rgba(255,255,255,0.05)',
63
+ color: '#fff',
64
+ '& .MuiListItemIcon-root': {
65
+ color: '#fff'
66
+ }
67
+ }
68
+ }, children: [_jsx(ListItemIcon, { sx: { minWidth: 40, color: 'inherit' }, children: footerLink.icon }), _jsx(ListItemText, { primary: footerLink.text, slotProps: { primary: { sx: { fontWeight: 500, fontSize: '0.925rem' } } } })] }) }) })] }))] }));
69
+ return (_jsxs(Box, { sx: { display: 'flex', minHeight: '100vh', bgcolor: 'background.default' }, children: [_jsx(CssBaseline, {}), _jsx(AppBar, { position: "fixed", sx: {
70
+ display: { sm: 'none' },
71
+ bgcolor: '#111827',
72
+ color: '#fff',
73
+ boxShadow: 'none',
74
+ borderBottom: '1px solid rgba(255,255,255,0.1)'
75
+ }, children: _jsxs(Toolbar, { children: [_jsx(IconButton, { color: "inherit", "aria-label": "open drawer", edge: "start", onClick: handleDrawerToggle, sx: { mr: 2 }, children: _jsx(MenuIcon, {}) }), _jsx(Typography, { variant: "h6", noWrap: true, component: "div", sx: { fontWeight: 700, flexGrow: 1 }, children: appName }), _jsx(Avatar, { src: user?.picture, sx: { width: 32, height: 32, border: '1px solid rgba(255,255,255,0.1)' }, onClick: handleOpenUserMenu })] }) }), _jsxs(Box, { component: "nav", sx: { width: { sm: DRAWER_WIDTH }, flexShrink: { sm: 0 } }, children: [_jsx(Drawer, { variant: "temporary", open: mobileOpen, onClose: handleDrawerToggle, ModalProps: { keepMounted: true }, sx: {
76
+ display: { xs: 'block', sm: 'none' },
77
+ '& .MuiDrawer-paper': {
78
+ boxSizing: 'border-box',
79
+ width: DRAWER_WIDTH,
80
+ borderRight: 'none',
81
+ bgcolor: '#111827',
82
+ color: '#fff'
83
+ }
84
+ }, children: drawer }), _jsx(Drawer, { variant: "permanent", sx: {
85
+ display: { xs: 'none', sm: 'block' },
86
+ '& .MuiDrawer-paper': {
87
+ boxSizing: 'border-box',
88
+ width: DRAWER_WIDTH,
89
+ borderRight: '1px solid rgba(255,255,255,0.1)',
90
+ bgcolor: '#111827',
91
+ color: '#fff'
92
+ }
93
+ }, open: true, children: drawer })] }), _jsx(Box, { component: "main", sx: {
94
+ flexGrow: 1,
95
+ p: { xs: 2, sm: 4, md: 8 },
96
+ width: { sm: `calc(100% - ${DRAWER_WIDTH}px)` },
97
+ mt: { xs: 7, sm: 0 },
98
+ display: 'flex',
99
+ flexDirection: 'column',
100
+ alignItems: 'center'
101
+ }, children: _jsxs(Box, { sx: { width: '100%', maxWidth: maxContentWidth }, children: [_jsxs(Box, { sx: { display: { xs: 'none', sm: 'flex' }, justifyContent: 'space-between', alignItems: 'center', mb: 8 }, children: [_jsxs(Box, { children: [_jsx(Typography, { variant: "h4", sx: { fontWeight: 700, letterSpacing: '-1px', mb: 1 }, children: activeItem?.text || appName }), _jsx(Typography, { variant: "body1", sx: { color: 'text.secondary' }, children: subtitle })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsxs(Box, { sx: { textAlign: 'right' }, children: [_jsx(Typography, { variant: "subtitle2", sx: { fontWeight: 600 }, children: user?.name || 'User' }), _jsx(Typography, { variant: "caption", sx: { color: 'text.secondary' }, children: user?.email })] }), _jsx(IconButton, { onClick: handleOpenUserMenu, sx: { p: 0.5, border: '1px solid', borderColor: 'divider' }, children: _jsx(Avatar, { src: user?.picture, sx: { width: 40, height: 40 }, children: _jsx(Person, {}) }) }), _jsxs(Menu, { anchorEl: anchorElUser, open: Boolean(anchorElUser), onClose: handleCloseUserMenu, transformOrigin: { horizontal: 'right', vertical: 'top' }, anchorOrigin: { horizontal: 'right', vertical: 'bottom' }, slotProps: {
102
+ paper: { sx: { mt: 1.5, minWidth: 200, borderRadius: 2, boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)' } }
103
+ }, children: [_jsxs(Box, { sx: { px: 2, py: 1.5 }, children: [_jsx(Typography, { variant: "subtitle2", noWrap: true, children: user?.name }), _jsx(Typography, { variant: "caption", noWrap: true, sx: { color: 'text.secondary' }, children: user?.email })] }), _jsx(Divider, {}), _jsxs(MenuItem, { onClick: () => {
104
+ handleCloseUserMenu();
105
+ onLogout();
106
+ }, sx: { py: 1.5 }, children: [_jsx(ListItemIcon, { children: _jsx(Logout, { fontSize: "small" }) }), "Logout"] })] })] })] }), children] }) })] }));
107
+ }
108
+ //# sourceMappingURL=AppLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppLayout.js","sourceRoot":"","sources":["../../../src/components/AppLayout/AppLayout.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { AppLayout } from './AppLayout';
2
+ export type { AppLayoutProps, AppLayoutNavItem, AppLayoutFooterLink, AppLayoutUser } from './AppLayout';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/AppLayout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { AppLayout } from './AppLayout';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/AppLayout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { AuthContextValue } from '../../auth/AuthProvider';
2
+ /** The slice of `useAuth()` a LoginRedirect needs. */
3
+ export type LoginRedirectAuth = Pick<AuthContextValue, 'refresh' | 'login'>;
4
+ export interface LoginRedirectOptions {
5
+ /**
6
+ * Where to send a successfully authenticated user. Each front's default
7
+ * route differs (`/account` vs. `/jobs`), and getting this wrong sends the
8
+ * user to a route the app doesn't have — so it's required, not defaulted.
9
+ */
10
+ redirectTo: string;
11
+ }
12
+ /**
13
+ * Builds the landing component for the post-login return URL: it re-runs the
14
+ * session check, then either navigates to the app's default route or shows a
15
+ * retry card.
16
+ *
17
+ * Takes `useAuth` as an argument for the same reason as
18
+ * `createProtectedRoute` — each front owns its own auth context instance.
19
+ */
20
+ export declare function createLoginRedirect(useAuth: () => LoginRedirectAuth, { redirectTo }: LoginRedirectOptions): () => import("react").JSX.Element;
21
+ //# sourceMappingURL=LoginRedirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginRedirect.d.ts","sourceRoot":"","sources":["../../../src/components/LoginRedirect/LoginRedirect.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,iBAAiB,EAAE,EAAE,UAAU,EAAE,EAAE,oBAAoB,qCA+DzG"}
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { useNavigate } from 'react-router-dom';
4
+ import { Box, Typography, Button, Paper } from '@mui/material';
5
+ import { ErrorOutlined } from '@mui/icons-material';
6
+ import { Loader } from '../Loader';
7
+ /**
8
+ * Builds the landing component for the post-login return URL: it re-runs the
9
+ * session check, then either navigates to the app's default route or shows a
10
+ * retry card.
11
+ *
12
+ * Takes `useAuth` as an argument for the same reason as
13
+ * `createProtectedRoute` — each front owns its own auth context instance.
14
+ */
15
+ export function createLoginRedirect(useAuth, { redirectTo }) {
16
+ return function LoginRedirect() {
17
+ const navigate = useNavigate();
18
+ const { refresh, login } = useAuth();
19
+ const [error, setError] = useState(null);
20
+ useEffect(() => {
21
+ const checkAuth = async () => {
22
+ try {
23
+ const result = await refresh();
24
+ if (result.authenticated) {
25
+ navigate(redirectTo, { replace: true });
26
+ }
27
+ else {
28
+ setError('Authentication failed. Please try logging in again.');
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error('Auth check failed:', error);
33
+ setError('Authentication check failed. Please try logging in again.');
34
+ }
35
+ };
36
+ checkAuth();
37
+ }, [navigate, refresh]);
38
+ if (error) {
39
+ return (_jsx(Box, { sx: {
40
+ display: 'flex',
41
+ alignItems: 'center',
42
+ justifyContent: 'center',
43
+ height: '100vh',
44
+ bgcolor: 'background.default',
45
+ p: 3
46
+ }, children: _jsxs(Paper, { variant: "outlined", sx: {
47
+ p: 4,
48
+ maxWidth: 400,
49
+ textAlign: 'center',
50
+ borderRadius: 3,
51
+ borderColor: 'divider'
52
+ }, children: [_jsx(ErrorOutlined, { sx: { fontSize: 48, color: 'error.main', mb: 2 } }), _jsx(Typography, { variant: "h5", gutterBottom: true, sx: { fontWeight: 700 }, children: "Login Error" }), _jsx(Typography, { variant: "body2", sx: { color: 'text.secondary', mb: 3 }, children: error }), _jsx(Button, { variant: "contained", fullWidth: true, onClick: () => login(), sx: { borderRadius: 2, py: 1.2 }, children: "Try Login Again" })] }) }));
53
+ }
54
+ return _jsx(Loader, { message: "Checking authentication..." });
55
+ };
56
+ }
57
+ //# sourceMappingURL=LoginRedirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginRedirect.js","sourceRoot":"","sources":["../../../src/components/LoginRedirect/LoginRedirect.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAenC;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgC,EAAE,EAAE,UAAU,EAAwB;IACxG,OAAO,SAAS,aAAa;QAC3B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC;QACrC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;QAExD,SAAS,CAAC,GAAG,EAAE;YACb,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;gBAC3B,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC;oBAC/B,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;wBACzB,QAAQ,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC1C,CAAC;yBAAM,CAAC;wBACN,QAAQ,CAAC,qDAAqD,CAAC,CAAC;oBAClE,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;oBAC3C,QAAQ,CAAC,2DAA2D,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC,CAAC;YAEF,SAAS,EAAE,CAAC;QACd,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAExB,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CACL,KAAC,GAAG,IACF,EAAE,EAAE;oBACF,OAAO,EAAE,MAAM;oBACf,UAAU,EAAE,QAAQ;oBACpB,cAAc,EAAE,QAAQ;oBACxB,MAAM,EAAE,OAAO;oBACf,OAAO,EAAE,oBAAoB;oBAC7B,CAAC,EAAE,CAAC;iBACL,YAED,MAAC,KAAK,IACJ,OAAO,EAAC,UAAU,EAClB,EAAE,EAAE;wBACF,CAAC,EAAE,CAAC;wBACJ,QAAQ,EAAE,GAAG;wBACb,SAAS,EAAE,QAAQ;wBACnB,YAAY,EAAE,CAAC;wBACf,WAAW,EAAE,SAAS;qBACvB,aAED,KAAC,aAAa,IAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,EAAE,GAAI,EACnE,KAAC,UAAU,IAAC,OAAO,EAAC,IAAI,EAAC,YAAY,QAAC,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,4BAEhD,EACb,KAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC,EAAE,YAC/D,KAAK,GACK,EACb,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,SAAS,QAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,gCAErF,IACH,GACJ,CACP,CAAC;QACJ,CAAC;QAED,OAAO,KAAC,MAAM,IAAC,OAAO,EAAC,4BAA4B,GAAG,CAAC;IACzD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { createLoginRedirect } from './LoginRedirect';
2
+ export type { LoginRedirectAuth, LoginRedirectOptions } from './LoginRedirect';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/LoginRedirect/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createLoginRedirect } from './LoginRedirect';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LoginRedirect/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { AuthContextValue } from '../../auth/AuthProvider';
3
+ /**
4
+ * The slice of `useAuth()` a ProtectedRoute needs. Narrower than
5
+ * `AuthContextValue` so a consumer can pass any compatible hook.
6
+ */
7
+ export type ProtectedRouteAuth = Pick<AuthContextValue, 'isAuthenticated' | 'isLoading' | 'login'>;
8
+ export interface ProtectedRouteProps {
9
+ children: ReactNode;
10
+ }
11
+ /**
12
+ * Builds a route guard that redirects to the login page when the session
13
+ * check comes back unauthenticated, and renders its children otherwise.
14
+ *
15
+ * Takes `useAuth` as an argument rather than importing a context: each front
16
+ * builds its own context via `createAuthContext(authService)`, so a context
17
+ * imported inside this lib would be a different, always-empty one. A factory
18
+ * (rather than a `useAuth` prop) keeps the call sites unchanged —
19
+ * `<ProtectedRoute>...</ProtectedRoute>` — and keeps the hook call
20
+ * unconditional, as the rules of hooks require.
21
+ */
22
+ export declare function createProtectedRoute(useAuth: () => ProtectedRouteAuth): ({ children }: ProtectedRouteProps) => import("react").JSX.Element;
23
+ //# sourceMappingURL=ProtectedRoute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.d.ts","sourceRoot":"","sources":["../../../src/components/ProtectedRoute/ProtectedRoute.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC;AAEnG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,kBAAkB,IACrC,cAAc,mBAAmB,iCAoBjE"}
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { Loader } from '../Loader';
4
+ /**
5
+ * Builds a route guard that redirects to the login page when the session
6
+ * check comes back unauthenticated, and renders its children otherwise.
7
+ *
8
+ * Takes `useAuth` as an argument rather than importing a context: each front
9
+ * builds its own context via `createAuthContext(authService)`, so a context
10
+ * imported inside this lib would be a different, always-empty one. A factory
11
+ * (rather than a `useAuth` prop) keeps the call sites unchanged —
12
+ * `<ProtectedRoute>...</ProtectedRoute>` — and keeps the hook call
13
+ * unconditional, as the rules of hooks require.
14
+ */
15
+ export function createProtectedRoute(useAuth) {
16
+ return function ProtectedRoute({ children }) {
17
+ const { isAuthenticated, isLoading, login } = useAuth();
18
+ useEffect(() => {
19
+ if (!isLoading && !isAuthenticated) {
20
+ login();
21
+ }
22
+ }, [isLoading, isAuthenticated, login]);
23
+ if (isLoading) {
24
+ return _jsx(Loader, { message: "Checking authentication..." });
25
+ }
26
+ if (!isAuthenticated) {
27
+ // login() above navigates away; this is what shows during that beat.
28
+ return _jsx("div", { children: "Redirecting to login..." });
29
+ }
30
+ return _jsx(_Fragment, { children: children });
31
+ };
32
+ }
33
+ //# sourceMappingURL=ProtectedRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.js","sourceRoot":"","sources":["../../../src/components/ProtectedRoute/ProtectedRoute.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAanC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAiC;IACpE,OAAO,SAAS,cAAc,CAAC,EAAE,QAAQ,EAAuB;QAC9D,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC;QAExD,SAAS,CAAC,GAAG,EAAE;YACb,IAAI,CAAC,SAAS,IAAI,CAAC,eAAe,EAAE,CAAC;gBACnC,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC;QAExC,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,KAAC,MAAM,IAAC,OAAO,EAAC,4BAA4B,GAAG,CAAC;QACzD,CAAC;QAED,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,qEAAqE;YACrE,OAAO,oDAAkC,CAAC;QAC5C,CAAC;QAED,OAAO,4BAAG,QAAQ,GAAI,CAAC;IACzB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { createProtectedRoute } from './ProtectedRoute';
2
+ export type { ProtectedRouteProps, ProtectedRouteAuth } from './ProtectedRoute';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ProtectedRoute/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createProtectedRoute } from './ProtectedRoute';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ProtectedRoute/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,12 @@ export { Loader } from './components/Loader';
4
4
  export type { LoaderProps } from './components/Loader';
5
5
  export { ErrorPage } from './components/ErrorPage';
6
6
  export type { ErrorPageProps } from './components/ErrorPage';
7
+ export { AppLayout } from './components/AppLayout';
8
+ export type { AppLayoutProps, AppLayoutNavItem, AppLayoutFooterLink, AppLayoutUser } from './components/AppLayout';
9
+ export { createProtectedRoute } from './components/ProtectedRoute';
10
+ export type { ProtectedRouteProps, ProtectedRouteAuth } from './components/ProtectedRoute';
11
+ export { createLoginRedirect } from './components/LoginRedirect';
12
+ export type { LoginRedirectAuth, LoginRedirectOptions } from './components/LoginRedirect';
7
13
  export { createAuthService } from './auth/authService';
8
14
  export type { AuthService, AuthServiceOptions, AuthUser, AuthCheckResult } from './auth/authService';
9
15
  export { createAuthContext } from './auth/AuthProvider';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAE1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/index.js CHANGED
@@ -2,6 +2,9 @@
2
2
  export { createApiClient, ApiError } from './apiClient';
3
3
  export { Loader } from './components/Loader';
4
4
  export { ErrorPage } from './components/ErrorPage';
5
+ export { AppLayout } from './components/AppLayout';
6
+ export { createProtectedRoute } from './components/ProtectedRoute';
7
+ export { createLoginRedirect } from './components/LoginRedirect';
5
8
  export { createAuthService } from './auth/authService';
6
9
  export { createAuthContext } from './auth/AuthProvider';
7
10
  export { createConfigProvider } from './config/createConfigProvider';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visin/frontend-core",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Shared frontend auth/API-client logic for Visin frontends",
5
5
  "author": "Toomas Tahves",
6
6
  "license": "MIT",
@@ -18,6 +18,7 @@
18
18
  "scripts": {
19
19
  "build": "tsc",
20
20
  "clean": "rm -rf dist",
21
+ "prepare": "npm run build",
21
22
  "prepublishOnly": "npm run clean && npm run build",
22
23
  "release": "standard-version && npm run build && npm publish --access public",
23
24
  "release:beta": "standard-version --prerelease beta && npm run build && npm publish --access public --tag beta",
@@ -36,7 +37,8 @@
36
37
  "peerDependencies": {
37
38
  "@mui/icons-material": "^9.2.0",
38
39
  "@mui/material": "^9.2.0",
39
- "react": "^19.2.7"
40
+ "react": "^19.2.7",
41
+ "react-router-dom": "^7.18.1"
40
42
  },
41
43
  "devDependencies": {
42
44
  "@eslint/js": "^10.0.1",
@@ -51,6 +53,7 @@
51
53
  "jsdom": "^29.1.1",
52
54
  "react": "^19.2.7",
53
55
  "react-dom": "^19.2.7",
56
+ "react-router-dom": "^7.18.1",
54
57
  "standard-version": "^9.5.0",
55
58
  "typescript": "^6.0.3",
56
59
  "typescript-eslint": "^8.62.1",