@smartbooks-ai/layout 0.1.0 → 0.1.2

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 (37) hide show
  1. package/dist/components/PageWithMenuLayout/AppsSelect/index.d.ts +8 -0
  2. package/dist/components/PageWithMenuLayout/AppsSelect/index.d.ts.map +1 -0
  3. package/dist/components/PageWithMenuLayout/AppsSelect/index.js +24 -0
  4. package/dist/components/PageWithMenuLayout/AppsSelect/styles.d.ts +31 -0
  5. package/dist/components/PageWithMenuLayout/AppsSelect/styles.d.ts.map +1 -0
  6. package/dist/components/PageWithMenuLayout/AppsSelect/styles.js +77 -0
  7. package/dist/components/PageWithMenuLayout/{AppSelect → CompanySelect}/index.d.ts +1 -1
  8. package/dist/components/PageWithMenuLayout/CompanySelect/index.d.ts.map +1 -0
  9. package/dist/components/PageWithMenuLayout/{AppSelect → CompanySelect}/index.js +1 -1
  10. package/dist/components/PageWithMenuLayout/CompanySelect/styles.d.ts.map +1 -0
  11. package/dist/components/PageWithMenuLayout/PageWithMenuLayout.d.ts +3 -1
  12. package/dist/components/PageWithMenuLayout/PageWithMenuLayout.d.ts.map +1 -1
  13. package/dist/components/PageWithMenuLayout/PageWithMenuLayout.js +18 -6
  14. package/dist/components/PageWithMenuLayout/index.d.ts +2 -1
  15. package/dist/components/PageWithMenuLayout/index.d.ts.map +1 -1
  16. package/dist/components/PageWithMenuLayout/index.js +2 -1
  17. package/dist/components/PageWithMenuLayout/styles.d.ts +4 -0
  18. package/dist/components/PageWithMenuLayout/styles.d.ts.map +1 -1
  19. package/dist/components/PageWithMenuLayout/styles.js +13 -0
  20. package/dist/components/PageWithMenuLayout/useMenuToggle.d.ts.map +1 -1
  21. package/dist/components/PageWithMenuLayout/useMenuToggle.js +2 -1
  22. package/dist/hooks/index.d.ts +1 -0
  23. package/dist/hooks/index.d.ts.map +1 -1
  24. package/dist/hooks/index.js +1 -0
  25. package/dist/hooks/useLocalStorage.d.ts +12 -0
  26. package/dist/hooks/useLocalStorage.d.ts.map +1 -0
  27. package/dist/hooks/useLocalStorage.js +86 -0
  28. package/dist/theme/font.d.ts +1 -0
  29. package/dist/theme/font.d.ts.map +1 -1
  30. package/dist/theme/font.js +1 -0
  31. package/dist/theme/index.d.ts.map +1 -1
  32. package/dist/theme/index.js +1 -1
  33. package/package.json +2 -2
  34. package/dist/components/PageWithMenuLayout/AppSelect/index.d.ts.map +0 -1
  35. package/dist/components/PageWithMenuLayout/AppSelect/styles.d.ts.map +0 -1
  36. /package/dist/components/PageWithMenuLayout/{AppSelect → CompanySelect}/styles.d.ts +0 -0
  37. /package/dist/components/PageWithMenuLayout/{AppSelect → CompanySelect}/styles.js +0 -0
@@ -0,0 +1,8 @@
1
+ import type { App } from '@smartbooks-ai/api-client';
2
+ type Props = {
3
+ applications: App[];
4
+ isExpanded: boolean;
5
+ };
6
+ export declare const AppsSelect: React.FC<Props>;
7
+ export {};
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/PageWithMenuLayout/AppsSelect/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAIrD,KAAK,KAAK,GAAG;IACX,YAAY,EAAE,GAAG,EAAE,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAyDtC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import AppsIcon from '@mui/icons-material/Apps';
4
+ import * as Styled from './styles';
5
+ export const AppsSelect = ({ applications }) => {
6
+ const [anchorEl, setAnchorEl] = useState(null);
7
+ const handleAppClick = (app) => {
8
+ window.open(app.url, '_blank');
9
+ setAnchorEl(null);
10
+ };
11
+ return (_jsxs(_Fragment, { children: [_jsx(Styled.AppsIconButton, { size: "small", title: "App Launcher", onClick: (event) => {
12
+ setAnchorEl(event.currentTarget);
13
+ }, children: _jsx(AppsIcon, {}) }), _jsx(Styled.Popover, { open: Boolean(anchorEl), anchorEl: anchorEl, onClose: () => setAnchorEl(null), anchorPosition: anchorEl
14
+ ? {
15
+ left: 0,
16
+ top: anchorEl.getBoundingClientRect().bottom + 8,
17
+ }
18
+ : undefined, anchorReference: "anchorPosition", transformOrigin: {
19
+ vertical: 'top',
20
+ horizontal: 'left',
21
+ }, children: _jsx(Styled.AppsGrid, { children: applications.map((app) => {
22
+ return (_jsx(Styled.AppCard, { elevation: 0, children: _jsxs(Styled.AppCardActionArea, { onClick: () => handleAppClick(app), children: [_jsx(Styled.AppIcon, { children: app.icon && (_jsx("img", { src: app.icon, alt: "", style: { width: '100%', height: '100%', objectFit: 'contain' } })) }), _jsx(Styled.AppTitle, { children: app.description })] }) }, app.url));
23
+ }) }) })] }));
24
+ };
@@ -0,0 +1,31 @@
1
+ export declare const AppsIconButton: import("@emotion/styled").StyledComponent<import("@mui/material").IconButtonOwnProps & Omit<import("@mui/material").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
2
+ ref?: ((instance: HTMLButtonElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLButtonElement> | null | undefined;
3
+ }, "style" | "className" | "classes" | "tabIndex" | "color" | "children" | "sx" | "disabled" | "action" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "loading" | "loadingIndicator" | "size" | "edge"> & {
4
+ theme?: import("@emotion/react").Theme;
5
+ }, {}, {}>;
6
+ export declare const Popover: import("@emotion/styled").StyledComponent<import("@mui/material").PopoverProps & {
7
+ theme?: import("@emotion/react").Theme;
8
+ }, {}, {}>;
9
+ export declare const AppsGrid: import("@emotion/styled").StyledComponent<{
10
+ theme?: import("@emotion/react").Theme;
11
+ as?: React.ElementType;
12
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
13
+ export declare const AppCard: import("@emotion/styled").StyledComponent<import("@mui/material").CardOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
14
+ ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
15
+ }, "style" | "className" | "classes" | "children" | "sx" | "variant" | "elevation" | "square" | "raised"> & {
16
+ theme?: import("@emotion/react").Theme;
17
+ }, {}, {}>;
18
+ export declare const AppCardActionArea: import("@emotion/styled").StyledComponent<import("@mui/material").CardActionAreaOwnProps & import("@mui/material").CardActionAreaSlotsAndSlotProps & Omit<import("@mui/material").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
19
+ ref?: ((instance: HTMLButtonElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLButtonElement> | null | undefined;
20
+ }, "style" | "className" | "classes" | "tabIndex" | "children" | "sx" | "slots" | "slotProps" | "disabled" | "action" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef"> & {
21
+ theme?: import("@emotion/react").Theme;
22
+ }, {}, {}>;
23
+ export declare const AppIcon: import("@emotion/styled").StyledComponent<{
24
+ theme?: import("@emotion/react").Theme;
25
+ as?: React.ElementType;
26
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
27
+ export declare const AppTitle: import("@emotion/styled").StyledComponent<{
28
+ theme?: import("@emotion/react").Theme;
29
+ as?: React.ElementType;
30
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
31
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/PageWithMenuLayout/AppsSelect/styles.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,cAAc;;;;UAI1B,CAAC;AAEF,eAAO,MAAM,OAAO;;UAcnB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;yGAMpB,CAAC;AAEF,eAAO,MAAM,OAAO;;;;UASnB,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;UAW7B,CAAC;AAEF,eAAO,MAAM,OAAO;;;yGAenB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;yGAKpB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import styled from '@emotion/styled';
2
+ import MuiCard from '@mui/material/Card';
3
+ import MuiCardActionArea from '@mui/material/CardActionArea';
4
+ import MuiIconButton from '@mui/material/IconButton';
5
+ import MuiPopover from '@mui/material/Popover';
6
+ import { rem } from 'polished';
7
+ export const AppsIconButton = styled(MuiIconButton) `
8
+ font-size: 1rem;
9
+
10
+ color: ${({ theme }) => theme.my.colors.text.white};
11
+ `;
12
+ export const Popover = styled(MuiPopover) `
13
+ /* stylelint-disable-next-line selector-class-pattern */
14
+ .MuiPopover-paper {
15
+ left: 0 !important;
16
+
17
+ max-width: 90vw;
18
+
19
+ padding: ${({ theme }) => theme.my.spacing.lg};
20
+ margin: 0 !important;
21
+
22
+ border: 0.0625rem solid #20244a;
23
+ border-radius: ${({ theme }) => theme.my.radius.lg};
24
+ box-shadow: 0 0.5rem 2rem rgb(0 0 0 / 50%);
25
+ }
26
+ `;
27
+ export const AppsGrid = styled.div `
28
+ display: grid;
29
+
30
+ grid-template-columns: repeat(3, 1fr);
31
+
32
+ gap: ${({ theme }) => theme.my.spacing.sm};
33
+ `;
34
+ export const AppCard = styled(MuiCard) `
35
+ background-color: transparent;
36
+ border-radius: ${({ theme }) => theme.my.radius.md};
37
+
38
+ transition: background-color 0.2s;
39
+
40
+ &:hover {
41
+ background-color: ${({ theme }) => theme.my.colors.background.hover};
42
+ }
43
+ `;
44
+ export const AppCardActionArea = styled(MuiCardActionArea) `
45
+ display: flex;
46
+
47
+ flex-direction: column;
48
+
49
+ align-items: center;
50
+ justify-content: center;
51
+
52
+ height: 100%;
53
+
54
+ padding: ${({ theme }) => theme.my.spacing.md};
55
+ `;
56
+ export const AppIcon = styled.div `
57
+ display: flex;
58
+
59
+ align-items: center;
60
+ justify-content: center;
61
+
62
+ width: ${rem(40)};
63
+ height: ${rem(40)};
64
+
65
+ margin-bottom: ${({ theme }) => theme.my.spacing.xs};
66
+
67
+ svg {
68
+ width: 100%;
69
+ height: 100%;
70
+ }
71
+ `;
72
+ export const AppTitle = styled.div `
73
+ font-weight: 500;
74
+
75
+ text-align: center;
76
+ overflow-wrap: break-word;
77
+ `;
@@ -6,6 +6,6 @@ type Props = {
6
6
  profile: UserProfile | null;
7
7
  onCompanyClicked: (company: AvailableCompany) => Promise<void>;
8
8
  };
9
- export declare const AppSelect: React.FC<Props>;
9
+ export declare const CompanySelect: React.FC<Props>;
10
10
  export {};
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/PageWithMenuLayout/CompanySelect/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAI7D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAI5D,KAAK,KAAK,GAAG;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA8CzC,CAAC"}
@@ -3,7 +3,7 @@ import { useMemo } from 'react';
3
3
  import * as Styled from './styles';
4
4
  import { MenuSelect } from '../MenuSelect';
5
5
  import { MultiSubscriptionsMenuItems } from '../MultiSubscriptionsMenuItems';
6
- export const AppSelect = ({ companyCode, isExpanded, profile, onCompanyClicked }) => {
6
+ export const CompanySelect = ({ companyCode, isExpanded, profile, onCompanyClicked }) => {
7
7
  const tenants = profile?.allowedTenants;
8
8
  const tenantsWithCompanies = useMemo(() => tenants?.filter(({ companies }) => companies.length > 0) ?? [], [tenants]);
9
9
  const currentCompany = companyCode ? profile?.allowedCompanies.find(({ code }) => code === companyCode) : undefined;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/PageWithMenuLayout/CompanySelect/styles.ts"],"names":[],"mappings":"AAMA,KAAK,KAAK,GAAG;IACX,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AACF,eAAO,MAAM,cAAc;;;;kBAuB1B,CAAC"}
@@ -1,4 +1,4 @@
1
- import { AvailableCompany } from '@smartbooks-ai/api-client';
1
+ import { App, AvailableCompany } from '@smartbooks-ai/api-client';
2
2
  import { MenuStructure } from './types';
3
3
  import { UserProfile } from '../../security/UserProfile';
4
4
  export type PageWithMenuLayoutProps = {
@@ -9,6 +9,8 @@ export type PageWithMenuLayoutProps = {
9
9
  switchToCompany: (company: AvailableCompany) => Promise<void>;
10
10
  logout: () => void;
11
11
  additionalOutletContent?: React.ReactNode;
12
+ applicationTitle?: string;
13
+ applications?: App[];
12
14
  };
13
15
  export declare const PageWithMenuLayout: React.FC<PageWithMenuLayoutProps>;
14
16
  //# sourceMappingURL=PageWithMenuLayout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageWithMenuLayout.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/PageWithMenuLayout.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAQ7D,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,MAAM,MAAM,uBAAuB,GAAG;IACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,aAAa,CAAC;IAC1B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,uBAAuB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3C,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAyEhE,CAAC"}
1
+ {"version":3,"file":"PageWithMenuLayout.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/PageWithMenuLayout.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAalE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIxC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,MAAM,MAAM,uBAAuB,GAAG;IACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,aAAa,CAAC;IAC1B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,uBAAuB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAqGhE,CAAC"}
@@ -1,15 +1,27 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
2
+ import { useEffect } from 'react';
2
3
  import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft';
3
4
  import Fade from '@mui/material/Fade';
5
+ import IconButton from '@mui/material/IconButton';
4
6
  import MenuList from '@mui/material/MenuList';
5
7
  import { createPortal } from 'react-dom';
6
- import { NavLink, Outlet } from 'react-router';
7
- import LogoHeaderImage from './LogoHeaderImage';
8
- import LogoHeaderText from './LogoHeaderText';
9
- import { AppSelect, MenuItemWithChildren, UserProfileSelect } from './index';
8
+ import { NavLink, Outlet, useNavigate } from 'react-router';
9
+ import { AppsSelect, CompanySelect, LogoHeaderImage, LogoHeaderText, MenuItemWithChildren, UserProfileSelect, } from './index';
10
10
  import * as Styled from './styles';
11
11
  import { useMenuToggle } from './useMenuToggle';
12
- export const PageWithMenuLayout = ({ resolvedCompanyCode, topMenu, bottomMenu, profile, switchToCompany, logout, additionalOutletContent, }) => {
12
+ import { useLocalStorage } from '../../hooks';
13
+ export const PageWithMenuLayout = ({ resolvedCompanyCode, topMenu, bottomMenu, profile, switchToCompany, logout, additionalOutletContent, applicationTitle, applications, }) => {
13
14
  const { isExpanded, openMenu, toggleIsExpanded } = useMenuToggle();
14
- return (_jsxs(_Fragment, { children: [_jsx(Styled.LockMenuButton, { onClick: toggleIsExpanded, isExpanded: isExpanded, children: _jsx(KeyboardArrowLeftIcon, { fontSize: "inherit" }) }), createPortal(_jsxs(Styled.Drawer, { open: isExpanded, variant: "permanent", children: [_jsxs(Styled.Header, { children: [_jsx(Styled.LogoContainer, { children: _jsx(NavLink, { to: "/", children: _jsx(LogoHeaderImage, { height: 24, style: { display: 'block' } }) }) }), _jsx(Fade, { in: isExpanded, children: _jsx(NavLink, { to: "/", children: _jsx(LogoHeaderText, { height: 12 }) }) })] }), _jsx(AppSelect, { companyCode: resolvedCompanyCode, isExpanded: isExpanded, profile: profile, onCompanyClicked: switchToCompany }), _jsx(Styled.TopMenuList, { children: topMenu?.map((firstLevelItem) => (_jsx(MenuItemWithChildren, { menuItem: firstLevelItem, isMenuOpen: isExpanded, openMenu: openMenu }, firstLevelItem.title))) }), _jsx(MenuList, { disablePadding: true, children: bottomMenu?.map((firstLevelItem) => (_jsx(MenuItemWithChildren, { menuItem: firstLevelItem, isMenuOpen: isExpanded, openMenu: openMenu }, firstLevelItem.title))) }), _jsx(UserProfileSelect, { isTextVisible: isExpanded, profile: profile, logout: logout })] }), document.body), _jsxs(Styled.Main, { isLocked: isExpanded, children: [_jsx(Outlet, {}), additionalOutletContent] })] }));
15
+ const navigate = useNavigate();
16
+ const [displayAppsLauncherLocalStorage, setDisplayAppsLauncherLocalStorage] = useLocalStorage('header.displayAppsLauncher', false);
17
+ useEffect(() => {
18
+ if (applications) {
19
+ setDisplayAppsLauncherLocalStorage(applications.length > 0);
20
+ }
21
+ }, [applications, setDisplayAppsLauncherLocalStorage]);
22
+ const hasApplications = applications !== undefined && applications.length > 0;
23
+ const showAppsLauncher = hasApplications || displayAppsLauncherLocalStorage;
24
+ return (_jsxs(_Fragment, { children: [_jsx(Styled.LockMenuButton, { onClick: toggleIsExpanded, isExpanded: isExpanded, children: _jsx(KeyboardArrowLeftIcon, { fontSize: "inherit" }) }), createPortal(_jsxs(Styled.Drawer, { open: isExpanded, variant: "permanent", children: [_jsxs(Styled.Header, { children: [showAppsLauncher ? (_jsx(AppsSelect, { applications: applications ?? [], isExpanded: isExpanded })) : (_jsx(IconButton, { size: "small", title: "Home", onClick: () => {
25
+ navigate('/');
26
+ }, children: _jsx(LogoHeaderImage, { height: 24, style: { display: 'block' } }) })), _jsx(Fade, { in: isExpanded, children: _jsx(NavLink, { to: "/", children: applicationTitle ? (_jsx(Styled.SmartBooksTitle, { children: applicationTitle })) : (_jsx(LogoHeaderText, { height: 12 })) }) })] }), _jsx(CompanySelect, { companyCode: resolvedCompanyCode, isExpanded: isExpanded, profile: profile, onCompanyClicked: switchToCompany }), _jsx(Styled.TopMenuList, { children: topMenu?.map((firstLevelItem) => (_jsx(MenuItemWithChildren, { menuItem: firstLevelItem, isMenuOpen: isExpanded, openMenu: openMenu }, firstLevelItem.title))) }), _jsx(MenuList, { disablePadding: true, children: bottomMenu?.map((firstLevelItem) => (_jsx(MenuItemWithChildren, { menuItem: firstLevelItem, isMenuOpen: isExpanded, openMenu: openMenu }, firstLevelItem.title))) }), _jsx(UserProfileSelect, { isTextVisible: isExpanded, profile: profile, logout: logout })] }), document.body), _jsxs(Styled.Main, { isLocked: isExpanded, children: [_jsx(Outlet, {}), additionalOutletContent] })] }));
15
27
  };
@@ -1,8 +1,9 @@
1
- export { AppSelect } from './AppSelect';
1
+ export { CompanySelect } from './CompanySelect';
2
2
  export { MenuSelect } from './MenuSelect';
3
3
  export { MultiSubscriptionsMenuItems } from './MultiSubscriptionsMenuItems';
4
4
  export { MenuItemWithChildren } from './MenuItemWithChildren/MenuItemWithChildren';
5
5
  export { UserProfileSelect } from './UserProfileSelect';
6
+ export { AppsSelect } from './AppsSelect';
6
7
  export { PageWithMenuLayout } from './PageWithMenuLayout';
7
8
  export { default as LogoHeaderImage } from './LogoHeaderImage';
8
9
  export { default as LogoHeaderText } from './LogoHeaderText';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,8 +1,9 @@
1
- export { AppSelect } from './AppSelect';
1
+ export { CompanySelect } from './CompanySelect';
2
2
  export { MenuSelect } from './MenuSelect';
3
3
  export { MultiSubscriptionsMenuItems } from './MultiSubscriptionsMenuItems';
4
4
  export { MenuItemWithChildren } from './MenuItemWithChildren/MenuItemWithChildren';
5
5
  export { UserProfileSelect } from './UserProfileSelect';
6
+ export { AppsSelect } from './AppsSelect';
6
7
  export { PageWithMenuLayout } from './PageWithMenuLayout';
7
8
  export { default as LogoHeaderImage } from './LogoHeaderImage';
8
9
  export { default as LogoHeaderText } from './LogoHeaderText';
@@ -22,6 +22,10 @@ export declare const TopMenuList: import("@emotion/styled").StyledComponent<impo
22
22
  }, keyof import("@mui/material/OverridableComponent").CommonProps | "autoFocus" | "children" | "sx" | "variant" | "dense" | "disablePadding" | "subheader" | "autoFocusItem" | "disabledItemsFocusable" | "disableListWrap"> & {
23
23
  theme?: import("@emotion/react").Theme;
24
24
  }, {}, {}>;
25
+ export declare const SmartBooksTitle: import("@emotion/styled").StyledComponent<{
26
+ theme?: import("@emotion/react").Theme;
27
+ as?: React.ElementType;
28
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
25
29
  type MainProps = {
26
30
  isLocked: boolean;
27
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/styles.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,MAAM;;UAgBlB,CAAC;AAEF,eAAO,MAAM,MAAM;;;yGAYlB,CAAC;AAEF,eAAO,MAAM,aAAa;;;yGAQzB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AACF,eAAO,MAAM,cAAc;;;;gCA2B1B,CAAC;AAEF,eAAO,MAAM,WAAW;;;;UASvB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,eAAO,MAAM,IAAI;;;qHAUhB,CAAC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/styles.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,MAAM;;UAgBlB,CAAC;AAEF,eAAO,MAAM,MAAM;;;yGAalB,CAAC;AAEF,eAAO,MAAM,aAAa;;;yGAQzB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AACF,eAAO,MAAM,cAAc;;;;gCA2B1B,CAAC;AAEF,eAAO,MAAM,WAAW;;;;UASvB,CAAC;AAEF,eAAO,MAAM,eAAe;;;yGAU3B,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,eAAO,MAAM,IAAI;;;qHAUhB,CAAC"}
@@ -3,6 +3,7 @@ import styled from '@emotion/styled';
3
3
  import MuiDrawer, { drawerClasses } from '@mui/material/Drawer';
4
4
  import MuiIconButton from '@mui/material/IconButton';
5
5
  import MenuList from '@mui/material/MenuList';
6
+ import { OPEN_SANS_FONT_FAMILY } from '../../theme/font';
6
7
  import { shouldNotForwardPropsWithKeys } from '../../utils/shouldNotForwardPropsWithKeys';
7
8
  const drawerOpenWidthRem = 15.625;
8
9
  const drawerClosedWidthRem = 3.75;
@@ -28,6 +29,7 @@ export const Header = styled.div `
28
29
 
29
30
  column-gap: ${({ theme }) => theme.my.spacing.xxs};
30
31
  align-items: center;
32
+ justify-content: left;
31
33
 
32
34
  width: max-content;
33
35
  min-width: 100%;
@@ -78,6 +80,17 @@ export const TopMenuList = styled(MenuList) `
78
80
 
79
81
  overflow: hidden auto;
80
82
  `;
83
+ export const SmartBooksTitle = styled.div `
84
+ margin-top: ${({ theme }) => theme.my.spacing.xxxs};
85
+
86
+ font-family: ${OPEN_SANS_FONT_FAMILY};
87
+ font-size: 1rem;
88
+ font-weight: bold;
89
+
90
+ color: ${({ theme }) => theme.my.colors.text.white};
91
+
92
+ text-transform: uppercase;
93
+ `;
81
94
  export const Main = styled('div', shouldNotForwardPropsWithKeys(['isLocked'])) `
82
95
  position: relative;
83
96
 
@@ -1 +1 @@
1
- {"version":3,"file":"useMenuToggle.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/useMenuToggle.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa;;;;CAczB,CAAC"}
1
+ {"version":3,"file":"useMenuToggle.d.ts","sourceRoot":"","sources":["../../../src/components/PageWithMenuLayout/useMenuToggle.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,aAAa;;;;CAczB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useMemo } from 'react';
2
- import { useProfile, useToggle } from '@smartbooks-ai/layout';
2
+ import { useToggle } from '../../hooks';
3
+ import { useProfile } from '../../security/ProfileContext';
3
4
  export const useMenuToggle = () => {
4
5
  const { value: isExpanded, toggle: toggleIsExpanded, switchOn: openMenu, switchOff: closeMenu } = useToggle(true);
5
6
  const { profile } = useProfile();
@@ -1,3 +1,4 @@
1
1
  export { useIsAuthorized } from './useIsAuthorized';
2
+ export { useLocalStorage } from './useLocalStorage';
2
3
  export { useToggle } from './useToggle';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { useIsAuthorized } from './useIsAuthorized';
2
+ export { useLocalStorage } from './useLocalStorage';
2
3
  export { useToggle } from './useToggle';
@@ -0,0 +1,12 @@
1
+ type Serializer<T> = (object: T | undefined) => string;
2
+ type Parser<T> = (val: string) => T | undefined;
3
+ type Setter<T> = React.Dispatch<React.SetStateAction<T | undefined>>;
4
+ type Options<T> = Partial<{
5
+ serializer: Serializer<T>;
6
+ parser: Parser<T>;
7
+ logger: (error: unknown) => void;
8
+ syncData: boolean;
9
+ }>;
10
+ declare function useLocalStorage<T>(key: string, defaultValue: T, options?: Options<T>): [T, Setter<T>];
11
+ export { useLocalStorage };
12
+ //# sourceMappingURL=useLocalStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLocalStorage.d.ts","sourceRoot":"","sources":["../../src/hooks/useLocalStorage.ts"],"names":[],"mappings":"AAGA,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,KAAK,MAAM,CAAC;AACvD,KAAK,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC;AAChD,KAAK,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AAErE,KAAK,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC;IACxB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAClB,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC,CAAC;AAEH,iBAAS,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AA6FhG,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,86 @@
1
+ // https://github.com/nas5w/use-local-storage/blob/main/src/index.ts
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ function useLocalStorage(key, defaultValue, options) {
4
+ const opts = useMemo(() => {
5
+ return {
6
+ serializer: JSON.stringify,
7
+ parser: JSON.parse,
8
+ logger: console.log,
9
+ syncData: true,
10
+ ...options,
11
+ };
12
+ }, [options]);
13
+ const { serializer, parser, logger, syncData } = opts;
14
+ const rawValueRef = useRef(null);
15
+ const [value, setValue] = useState(() => {
16
+ if (typeof window === 'undefined')
17
+ return defaultValue;
18
+ try {
19
+ rawValueRef.current = window.localStorage.getItem(key);
20
+ const res = rawValueRef.current ? parser(rawValueRef.current) : defaultValue;
21
+ return res;
22
+ }
23
+ catch (e) {
24
+ logger(e);
25
+ return defaultValue;
26
+ }
27
+ });
28
+ useEffect(() => {
29
+ if (typeof window === 'undefined')
30
+ return;
31
+ const updateLocalStorage = () => {
32
+ // Browser ONLY dispatch storage events to other tabs, NOT current tab.
33
+ // We need to manually dispatch storage event for current tab
34
+ if (value !== undefined) {
35
+ const newValue = serializer(value);
36
+ const oldValue = rawValueRef.current;
37
+ rawValueRef.current = newValue;
38
+ window.localStorage.setItem(key, newValue);
39
+ window.dispatchEvent(new StorageEvent('storage', {
40
+ storageArea: window.localStorage,
41
+ url: window.location.href,
42
+ key,
43
+ newValue,
44
+ oldValue,
45
+ }));
46
+ }
47
+ else {
48
+ window.localStorage.removeItem(key);
49
+ window.dispatchEvent(new StorageEvent('storage', {
50
+ storageArea: window.localStorage,
51
+ url: window.location.href,
52
+ key,
53
+ }));
54
+ }
55
+ };
56
+ try {
57
+ updateLocalStorage();
58
+ }
59
+ catch (e) {
60
+ logger(e);
61
+ }
62
+ }, [value, key, serializer, rawValueRef, logger]);
63
+ useEffect(() => {
64
+ if (!syncData)
65
+ return;
66
+ const handleStorageChange = (e) => {
67
+ if (e.key !== key || e.storageArea !== window.localStorage)
68
+ return;
69
+ try {
70
+ if (e.newValue !== rawValueRef.current) {
71
+ rawValueRef.current = e.newValue;
72
+ setValue(e.newValue ? parser(e.newValue) : undefined);
73
+ }
74
+ }
75
+ catch (e) {
76
+ logger(e);
77
+ }
78
+ };
79
+ if (typeof window === 'undefined')
80
+ return;
81
+ window.addEventListener('storage', handleStorageChange);
82
+ return () => window.removeEventListener('storage', handleStorageChange);
83
+ }, [key, syncData, parser, rawValueRef, logger]);
84
+ return [value, setValue];
85
+ }
86
+ export { useLocalStorage };
@@ -1,4 +1,5 @@
1
1
  import { Theme } from '@emotion/react';
2
2
  export declare const FONT_FAMILY = "Arial, sans-serif";
3
+ export declare const OPEN_SANS_FONT_FAMILY = "Open Sans, Arial, sans-serif";
3
4
  export declare const font: Theme['my']['font'];
4
5
  //# sourceMappingURL=font.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../../src/theme/font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAE/C,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAsBpC,CAAC"}
1
+ {"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../../src/theme/font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAC/C,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAEpE,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAsBpC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export const FONT_FAMILY = 'Arial, sans-serif';
2
+ export const OPEN_SANS_FONT_FAMILY = 'Open Sans, Arial, sans-serif';
2
3
  export const font = {
3
4
  h1: ` 600 1.5rem/2 ${FONT_FAMILY}`,
4
5
  h2: ` 700 1.25rem/1.75 ${FONT_FAMILY}`,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.tsx"],"names":[],"mappings":"AAoNA,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,iBAAiB,oDAc3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.tsx"],"names":[],"mappings":"AAqNA,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,iBAAiB,oDAc3D"}
@@ -39,7 +39,7 @@ const muiTheme = {
39
39
  MuiCssBaseline: {
40
40
  styleOverrides: {
41
41
  a: css `
42
- color: '#000000';
42
+ color: #000;
43
43
 
44
44
  text-decoration: none;
45
45
  `,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "smartbooks",
3
3
  "dependencies": {
4
- "@smartbooks-ai/api-client": "0.1.0",
4
+ "@smartbooks-ai/api-client": "0.1.2",
5
5
  "use-resize-observer": "^9.1.0"
6
6
  },
7
7
  "devDependencies": {
@@ -51,5 +51,5 @@
51
51
  },
52
52
  "type": "module",
53
53
  "types": "./dist/index.d.ts",
54
- "version": "0.1.0"
54
+ "version": "0.1.2"
55
55
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/PageWithMenuLayout/AppSelect/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAI7D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAI5D,KAAK,KAAK,GAAG;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA8CrC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../src/components/PageWithMenuLayout/AppSelect/styles.ts"],"names":[],"mappings":"AAMA,KAAK,KAAK,GAAG;IACX,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AACF,eAAO,MAAM,cAAc;;;;kBAuB1B,CAAC"}