@servicetitan/navigation 3.2.0 → 4.0.0

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 (94) hide show
  1. package/dist/components/header-navigation/header-navigation-content.d.ts +7 -0
  2. package/dist/components/header-navigation/header-navigation-content.d.ts.map +1 -1
  3. package/dist/components/header-navigation/header-navigation-content.js +8 -7
  4. package/dist/components/header-navigation/header-navigation-content.js.map +1 -1
  5. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts +3 -2
  6. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-extra.stories.js +6 -20
  8. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
  9. package/dist/components/header-navigation/header-navigation-links.d.ts +5 -3
  10. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
  11. package/dist/components/header-navigation/header-navigation-links.js +12 -6
  12. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  13. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts +1 -0
  14. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
  15. package/dist/components/header-navigation/header-navigation-stacked.stories.js +4 -23
  16. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
  17. package/dist/components/header-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
  18. package/dist/components/header-navigation/header-navigation-tiny.stories.js +11 -7
  19. package/dist/components/header-navigation/header-navigation-tiny.stories.js.map +1 -1
  20. package/dist/components/header-navigation/header-navigation.d.ts.map +1 -1
  21. package/dist/components/header-navigation/header-navigation.js +17 -5
  22. package/dist/components/header-navigation/header-navigation.js.map +1 -1
  23. package/dist/components/header-navigation/header-navigation.module.less +25 -0
  24. package/dist/components/header-navigation/header-navigation.stories.d.ts +1 -0
  25. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  26. package/dist/components/header-navigation/header-navigation.stories.js +5 -24
  27. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  28. package/dist/components/layout.stories.d.ts +1 -0
  29. package/dist/components/layout.stories.d.ts.map +1 -1
  30. package/dist/components/layout.stories.js +2 -0
  31. package/dist/components/layout.stories.js.map +1 -1
  32. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +2 -8
  33. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -1
  34. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js +5 -43
  35. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js.map +1 -1
  36. package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.d.ts +9 -0
  37. package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.d.ts.map +1 -0
  38. package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.js +13 -0
  39. package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.js.map +1 -0
  40. package/dist/components/profile-dropdown/profile-dropdown.d.ts +2 -1
  41. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  42. package/dist/components/profile-dropdown/profile-dropdown.js +16 -7
  43. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  44. package/dist/components/profile-dropdown/profile-dropdown.module.less +7 -1
  45. package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts +9 -8
  46. package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts.map +1 -1
  47. package/dist/components/profile-dropdown/profile-dropdown.stories.js +39 -39
  48. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  49. package/dist/components/side-navigation/side-navigation.d.ts +1 -12
  50. package/dist/components/side-navigation/side-navigation.d.ts.map +1 -1
  51. package/dist/components/side-navigation/side-navigation.js +10 -24
  52. package/dist/components/side-navigation/side-navigation.js.map +1 -1
  53. package/dist/components/side-navigation/side-navigation.module.less +26 -20
  54. package/dist/components/side-navigation/side-navigation.stories.d.ts +3 -3
  55. package/dist/components/side-navigation/side-navigation.stories.d.ts.map +1 -1
  56. package/dist/components/side-navigation/side-navigation.stories.js +2 -23
  57. package/dist/components/side-navigation/side-navigation.stories.js.map +1 -1
  58. package/dist/test/data-stories.module.less +6 -0
  59. package/dist/test/data.stories.d.ts +26 -0
  60. package/dist/test/data.stories.d.ts.map +1 -0
  61. package/dist/test/data.stories.js +150 -0
  62. package/dist/test/data.stories.js.map +1 -0
  63. package/dist/utils/navigation-context.d.ts +5 -2
  64. package/dist/utils/navigation-context.d.ts.map +1 -1
  65. package/dist/utils/navigation-context.js +20 -5
  66. package/dist/utils/navigation-context.js.map +1 -1
  67. package/dist/utils/navigation.d.ts +5 -0
  68. package/dist/utils/navigation.d.ts.map +1 -1
  69. package/package.json +12 -12
  70. package/src/components/header-navigation/header-navigation-content.tsx +39 -11
  71. package/src/components/header-navigation/header-navigation-extra.stories.tsx +24 -21
  72. package/src/components/header-navigation/header-navigation-links.tsx +36 -8
  73. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +16 -66
  74. package/src/components/header-navigation/header-navigation-tiny.stories.tsx +37 -41
  75. package/src/components/header-navigation/header-navigation.module.less +25 -0
  76. package/src/components/header-navigation/header-navigation.module.less.d.ts +2 -0
  77. package/src/components/header-navigation/header-navigation.stories.tsx +18 -67
  78. package/src/components/header-navigation/header-navigation.tsx +45 -8
  79. package/src/components/layout.stories.tsx +2 -0
  80. package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +7 -170
  81. package/src/components/profile-dropdown/profile-dropdown-tiny.stories.tsx +15 -0
  82. package/src/components/profile-dropdown/profile-dropdown.module.less +7 -1
  83. package/src/components/profile-dropdown/profile-dropdown.module.less.d.ts +1 -0
  84. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +106 -129
  85. package/src/components/profile-dropdown/profile-dropdown.tsx +32 -8
  86. package/src/components/side-navigation/side-navigation.module.less +26 -20
  87. package/src/components/side-navigation/side-navigation.module.less.d.ts +2 -3
  88. package/src/components/side-navigation/side-navigation.stories.tsx +3 -52
  89. package/src/components/side-navigation/side-navigation.tsx +71 -124
  90. package/src/test/data-stories.module.less +6 -0
  91. package/src/test/data-stories.module.less.d.ts +3 -0
  92. package/src/test/data.stories.tsx +220 -0
  93. package/src/utils/navigation-context.tsx +15 -10
  94. package/src/utils/navigation.ts +7 -0
@@ -1,15 +1,12 @@
1
- import { BodyText, Divider, Eyebrow, Icon, Popover, Stack } from '@servicetitan/design-system';
1
+ import { Icon } from '@servicetitan/anvil2';
2
+ import SvgCollapse from '@servicetitan/anvil2/assets/icons/st/gnav_menu_collapse.svg';
3
+ import SvgExpand from '@servicetitan/anvil2/assets/icons/st/gnav_menu_expand.svg';
2
4
  import classNames from 'classnames';
3
- import { FC, Fragment, PropsWithChildren, useState } from 'react';
5
+ import { FC, Fragment } from 'react';
4
6
  import { HeaderNavigationItemData, NavLinkComponentProps } from '../../utils/navigation';
5
- import {
6
- DefaultNavLinkComponent,
7
- NavLinkContext,
8
- useNavLink,
9
- } from '../../utils/navigation-context';
7
+ import { DefaultNavLinkComponent } from '../../utils/navigation-context';
10
8
  import { withTooltip } from '../../utils/with-tooltip';
11
9
  import { CounterTag } from '../counter-tag';
12
- import { IconSideExpanded, IconSideOptions, IconSideSlim } from './icons';
13
10
  import * as Styles from './side-navigation.module.less';
14
11
 
15
12
  export interface SideNavigationProps {
@@ -39,48 +36,57 @@ export const SideNavigation: FC<SideNavigationProps> = ({
39
36
  onExpandedChange,
40
37
  }) => {
41
38
  return (
42
- <NavLinkContext.Provider value={navigationComponent}>
43
- <div
44
- className={classNames(
45
- Styles.sideNav,
46
- expanded ? Styles.sideNavExpanded : Styles.sideNavSlim,
47
- className
48
- )}
49
- id={id}
50
- data-cy="side-navigation"
51
- >
52
- {!!itemsTop?.length && (
53
- <Fragment>
54
- <div className={Styles.sideNavTop} data-cy="navigation-items-top">
55
- {itemsTop.map(item => (
56
- <SideNavigationItem key={item.id} expanded={expanded} {...item} />
57
- ))}
58
- </div>
59
- <div className={Styles.divider} />
60
- </Fragment>
61
- )}
62
- <div className={Styles.sideNavContent} data-cy="navigation-items">
63
- {items?.map(item => (
64
- <SideNavigationItem key={item.id} expanded={expanded} {...item} />
65
- ))}
66
- </div>
67
- <div className={Styles.sideNavBottom}>
68
- <SideNavigationOptionsToggle
39
+ <div
40
+ className={classNames(
41
+ Styles.sideNav,
42
+ expanded ? Styles.sideNavExpanded : Styles.sideNavSlim,
43
+ className
44
+ )}
45
+ id={id}
46
+ data-cy="side-navigation"
47
+ >
48
+ {!!itemsTop?.length && (
49
+ <Fragment>
50
+ <div className={Styles.sideNavTop} data-cy="navigation-items-top">
51
+ {itemsTop.map(item => (
52
+ <SideNavigationItem
53
+ key={item.id}
54
+ expanded={expanded}
55
+ navigationComponent={navigationComponent}
56
+ {...item}
57
+ />
58
+ ))}
59
+ </div>
60
+ <div className={Styles.divider} />
61
+ </Fragment>
62
+ )}
63
+ <div className={Styles.sideNavContent} data-cy="navigation-items">
64
+ {items?.map(item => (
65
+ <SideNavigationItem
66
+ key={item.id}
69
67
  expanded={expanded}
70
- onExpandedChange={onExpandedChange}
68
+ navigationComponent={navigationComponent}
69
+ {...item}
71
70
  />
72
- </div>
71
+ ))}
73
72
  </div>
74
- </NavLinkContext.Provider>
73
+ <div className={Styles.sideNavBottom}>
74
+ <SideNavigationOptionsToggle
75
+ expanded={expanded}
76
+ onExpandedChange={onExpandedChange}
77
+ />
78
+ </div>
79
+ </div>
75
80
  );
76
81
  };
77
82
 
78
83
  interface SideNavigationItemProps extends HeaderNavigationItemData {
84
+ navigationComponent: FC<NavLinkComponentProps>;
79
85
  expanded?: boolean;
80
86
  }
81
87
 
82
88
  /** Side Navigation menu item */
83
- export const SideNavigationItem: FC<SideNavigationItemProps> = ({
89
+ const SideNavigationItem: FC<SideNavigationItemProps> = ({
84
90
  id,
85
91
  to,
86
92
  title,
@@ -89,13 +95,12 @@ export const SideNavigationItem: FC<SideNavigationItemProps> = ({
89
95
  className,
90
96
  iconClassName,
91
97
  iconComponent: IconComponent,
92
- iconName,
98
+ icon,
99
+ iconActive,
93
100
  isActive,
101
+ navigationComponent: NavigationComponent,
94
102
  expanded,
95
103
  }) => {
96
- const NavigationComponent = useNavLink();
97
- const iconClass = classNames(Styles.navigationIcon, iconClassName);
98
-
99
104
  return withTooltip(
100
105
  <NavigationComponent
101
106
  data-cy={`navigation-item-${id}`}
@@ -105,25 +110,41 @@ export const SideNavigationItem: FC<SideNavigationItemProps> = ({
105
110
  title={hint}
106
111
  className={classNames(Styles.navigationItem, className, {
107
112
  [Styles.navigationItemActive]: isActive === true,
113
+ [Styles.navigationItemIconState]: !!icon && !!iconActive,
108
114
  })}
109
115
  isActive={typeof isActive === 'function' ? isActive : undefined}
110
116
  activeClassName={Styles.navigationItemActive}
111
117
  >
112
118
  {IconComponent ? (
113
- <i className={iconClass}>
119
+ <i className={classNames(Styles.navigationIcon, iconClassName)}>
114
120
  <IconComponent />
115
121
  </i>
116
- ) : iconName ? (
117
- <Icon name={iconName} className={iconClass} />
118
122
  ) : (
119
- <i className={iconClass} />
123
+ <Fragment>
124
+ {icon && (
125
+ <Icon
126
+ svg={icon}
127
+ className={classNames(Styles.navigationIcon, iconClassName)}
128
+ />
129
+ )}
130
+ {iconActive && (
131
+ <Icon
132
+ svg={iconActive}
133
+ className={classNames(
134
+ Styles.navigationIcon,
135
+ Styles.navigationIconActive,
136
+ iconClassName
137
+ )}
138
+ />
139
+ )}
140
+ </Fragment>
120
141
  )}
121
142
 
122
143
  {!!expanded && <span className={Styles.navigationItemText}>{title}</span>}
123
144
  {!!counter && <CounterTag data={counter} className={Styles.navigationItemCounter} />}
124
145
  </NavigationComponent>,
125
146
  expanded ? undefined : title,
126
- 'r'
147
+ 'right'
127
148
  );
128
149
  };
129
150
 
@@ -140,85 +161,11 @@ export const SideNavigationOptionsToggle: FC<{
140
161
  onClick={() => onExpandedChange(!expanded)}
141
162
  >
142
163
  <div className={Styles.optionsIcon}>
143
- <IconSideOptions expanded={expanded} />
164
+ <Icon svg={expanded ? SvgCollapse : SvgExpand} />
144
165
  </div>
145
166
 
146
167
  {!!expanded && <span className={Styles.optionsItemText}>Collapse Menu</span>}
147
168
  </div>,
148
169
  expanded ? undefined : 'Expand Menu',
149
- 'r'
150
- );
151
-
152
- /** Side Navigation options popover */
153
- export const SideNavigationOptionsPopover: FC<
154
- PropsWithChildren<{
155
- expanded?: boolean;
156
- onExpandedChange(expanded: boolean): void;
157
- }>
158
- > = ({ children, expanded, onExpandedChange }) => {
159
- const [open, setOpen] = useState(false);
160
-
161
- const onExpand = () => {
162
- setOpen(false);
163
- onExpandedChange(true);
164
- };
165
- const onCollapse = () => {
166
- setOpen(false);
167
- onExpandedChange(false);
168
- };
169
-
170
- return (
171
- <Popover
172
- className="bg-neutral-30"
173
- trigger={children}
174
- direction="tr"
175
- onClickOutside={() => setOpen(false)}
176
- open={open}
177
- padding="s"
178
- width="xs"
179
- >
180
- <Eyebrow className="p-l-2">menu options</Eyebrow>
181
- <SideNavigationOptionsItem
182
- active={!expanded}
183
- icon={IconSideSlim}
184
- title="Slim"
185
- onClick={onCollapse}
186
- />
187
- <SideNavigationOptionsItem
188
- active={!!expanded}
189
- icon={IconSideExpanded}
190
- title="Expanded"
191
- onClick={onExpand}
192
- />
193
-
194
- <Divider className="m-x-half m-y-1" />
195
-
196
- <SideNavigationOptionsItem
197
- active={false}
198
- icon={expanded ? IconSideExpanded : IconSideSlim}
199
- title={expanded ? 'Expanded' : 'Slim'}
200
- />
201
- </Popover>
170
+ 'right'
202
171
  );
203
- };
204
-
205
- const SideNavigationOptionsItem: FC<{
206
- active: boolean;
207
- icon: FC;
208
- title: string;
209
- onClick?: () => void;
210
- }> = ({ active, onClick, title, icon: IconComponent }) => (
211
- <Stack
212
- className={classNames(
213
- active ? Styles.optionsPopoverItemActive : Styles.optionsPopoverItemInactive,
214
- 'p-y-1 p-x-2',
215
- { [Styles.optionsPopoverItemClickable]: onClick && !active }
216
- )}
217
- alignItems="center"
218
- onClick={!active && onClick}
219
- >
220
- <IconComponent />
221
- <BodyText className="c-inherit m-l-1 flex-grow-1 flex-basis-0">{title}</BodyText>
222
- {active && <Icon name="check" />}
223
- </Stack>
224
- );
@@ -0,0 +1,6 @@
1
+ // temp fix to reset incorrect coloring from anvil2
2
+ .fix-icons {
3
+ :global(span[data-anv='icon'] > svg > path) {
4
+ fill: inherit !important;
5
+ }
6
+ }
@@ -0,0 +1,3 @@
1
+ export const __esModule: true;
2
+ export const fixIcons: string;
3
+
@@ -0,0 +1,220 @@
1
+ import { AnvilProvider } from '@servicetitan/anvil2';
2
+ import SvgPhone from '@servicetitan/anvil2/assets/icons/material/round/phone_disabled.svg';
3
+ import SvgPhoneActive from '@servicetitan/anvil2/assets/icons/material/round/phone_enabled.svg';
4
+ import SvgAccountingActive from '@servicetitan/anvil2/assets/icons/st/gnav_accounting_active.svg';
5
+ import SvgAccounting from '@servicetitan/anvil2/assets/icons/st/gnav_accounting_inactive.svg';
6
+ import SvgCallsActive from '@servicetitan/anvil2/assets/icons/st/gnav_calls_active.svg';
7
+ import SvgCalls from '@servicetitan/anvil2/assets/icons/st/gnav_calls_inactive.svg';
8
+ import SvgDashboardActive from '@servicetitan/anvil2/assets/icons/st/gnav_dashboard_active.svg';
9
+ import SvgDashboard from '@servicetitan/anvil2/assets/icons/st/gnav_dashboard_inactive.svg';
10
+ import SvgDispatchActive from '@servicetitan/anvil2/assets/icons/st/gnav_dispatch_active.svg';
11
+ import SvgDispatch from '@servicetitan/anvil2/assets/icons/st/gnav_dispatch_inactive.svg';
12
+ import SvgFleetProActive from '@servicetitan/anvil2/assets/icons/st/gnav_fleet_pro_active.svg';
13
+ import SvgFleetPro from '@servicetitan/anvil2/assets/icons/st/gnav_fleet_pro_inactive.svg';
14
+ import SvgFollowUpActive from '@servicetitan/anvil2/assets/icons/st/gnav_follow_up_active.svg';
15
+ import SvgFollowUp from '@servicetitan/anvil2/assets/icons/st/gnav_follow_up_inactive.svg';
16
+ import SvgInventoryActive from '@servicetitan/anvil2/assets/icons/st/gnav_inventory_active.svg';
17
+ import SvgInventory from '@servicetitan/anvil2/assets/icons/st/gnav_inventory_inactive.svg';
18
+ import SvgMarketingActive from '@servicetitan/anvil2/assets/icons/st/gnav_marketing_active.svg';
19
+ import SvgMarketing from '@servicetitan/anvil2/assets/icons/st/gnav_marketing_inactive.svg';
20
+ import SvgPosActive from '@servicetitan/anvil2/assets/icons/st/gnav_pos_active.svg';
21
+ import SvgPos from '@servicetitan/anvil2/assets/icons/st/gnav_pos_inactive.svg';
22
+ import SvgPriceBookActive from '@servicetitan/anvil2/assets/icons/st/gnav_pricebook_active.svg';
23
+ import SvgPriceBook from '@servicetitan/anvil2/assets/icons/st/gnav_pricebook_inactive.svg';
24
+ import SvgProjectsActive from '@servicetitan/anvil2/assets/icons/st/gnav_projects_active.svg';
25
+ import SvgProjects from '@servicetitan/anvil2/assets/icons/st/gnav_projects_inactive.svg';
26
+ import SvgReportsActive from '@servicetitan/anvil2/assets/icons/st/gnav_reports_active.svg';
27
+ import SvgReports from '@servicetitan/anvil2/assets/icons/st/gnav_reports_inactive.svg';
28
+ import SvgScheduleActive from '@servicetitan/anvil2/assets/icons/st/gnav_schedule_active.svg';
29
+ import SvgSchedule from '@servicetitan/anvil2/assets/icons/st/gnav_schedule_inactive.svg';
30
+ import SvgTasksActive from '@servicetitan/anvil2/assets/icons/st/gnav_tasks_active.svg';
31
+ import SvgTasks from '@servicetitan/anvil2/assets/icons/st/gnav_tasks_inactive.svg';
32
+
33
+ import { Popover } from '@servicetitan/design-system';
34
+
35
+ import classNames from 'classnames';
36
+ import { forwardRef, useState } from 'react';
37
+ // needed only for storybook and added in root dependencies
38
+ // eslint-disable-next-line import/no-extraneous-dependencies
39
+ import { MemoryRouter, useHistory, useLocation } from 'react-router-dom';
40
+ import { HeaderNavigationTrigger } from '../components/header-navigation';
41
+ import { HeaderNavigationItemData, NavLinkComponentProps } from '../utils/navigation';
42
+ import * as Styles from './data-stories.module.less';
43
+
44
+ export const NavLinkMock = forwardRef<any, NavLinkComponentProps>(
45
+ ({ to, children, activeClassName, className, isActive, ...rest }, ref) => {
46
+ const history = useHistory();
47
+ const location = useLocation();
48
+ const linkActive = location.pathname.replace('/', '') === to;
49
+
50
+ return (
51
+ <a
52
+ {...rest}
53
+ className={classNames(className, linkActive ? activeClassName : '')}
54
+ href={to}
55
+ onClick={e => {
56
+ e.preventDefault();
57
+
58
+ if (!to.startsWith('http')) {
59
+ history.push(to);
60
+ }
61
+ }}
62
+ ref={ref}
63
+ >
64
+ {children}
65
+ </a>
66
+ );
67
+ }
68
+ );
69
+
70
+ export const withMemoryRouter = (Story: any) => (
71
+ <MemoryRouter>
72
+ <Story />
73
+ </MemoryRouter>
74
+ );
75
+
76
+ export const withAnvil = (Story: any) => (
77
+ <AnvilProvider className={Styles.fixIcons}>
78
+ <Story />
79
+ </AnvilProvider>
80
+ );
81
+
82
+ export const InventoryIcon = () => (
83
+ <svg width="20" xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24" fill="currentColor">
84
+ <polyline points="-288,400.9 -282,404.3 -282,397.6 -288,394.2 -288,400.9 " />
85
+ <path d="M-272,401.5c0,0.4-0.2,0.7-0.5,0.9l-7.9,4.4c-0.2,0.1-0.4,0.2-0.6,0.2s-0.4-0.1-0.6-0.2l-7.9-4.4c-0.3-0.2-0.5-0.5-0.5-0.9v-9c0-0.4,0.2-0.7,0.5-0.9l7.9-4.4c0.2-0.1,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l7.9,4.4c0.3,0.2,0.5,0.5,0.5,0.9V401.5 M-287,392.5 l6,3.4l5.9-3.3l-5.9-3.4L-287,392.5 M-274,400.9v-6.7l-6,3.4v6.7L-274,400.9z" />
86
+ </svg>
87
+ );
88
+
89
+ export const SearchIcon = () => (
90
+ <svg
91
+ width="1em"
92
+ height="1em"
93
+ viewBox="0 0 24 24"
94
+ fill="none"
95
+ xmlns="http://www.w3.org/2000/svg"
96
+ >
97
+ <g transform="translate(0,4)">
98
+ <path
99
+ d="M0 15.7992V13.9992H12V15.7992H0ZM0 9.49922V7.69922H6V9.49922H0ZM0 3.19922V1.39922H6V3.19922H0ZM22.74 15.7992L17.94 10.9992C17.42 11.3992 16.86 11.6992 16.26 11.8992C15.66 12.0992 15.04 12.1992 14.4 12.1992C12.74 12.1992 11.325 11.6142 10.155 10.4442C8.985 9.27422 8.4 7.85922 8.4 6.19922C8.4 4.53922 8.985 3.12422 10.155 1.95422C11.325 0.784219 12.74 0.199219 14.4 0.199219C16.06 0.199219 17.475 0.784219 18.645 1.95422C19.815 3.12422 20.4 4.53922 20.4 6.19922C20.4 6.83922 20.3 7.45922 20.1 8.05922C19.9 8.65922 19.6 9.21922 19.2 9.73922L24 14.5392L22.74 15.7992ZM14.393 10.3992C15.5577 10.3992 16.55 9.99157 17.37 9.17627C18.19 8.36099 18.6 7.37099 18.6 6.20627C18.6 5.04157 18.1923 4.04922 17.377 3.22922C16.5618 2.40922 15.5718 1.99922 14.407 1.99922C13.2423 1.99922 12.25 2.40687 11.43 3.22217C10.61 4.03745 10.2 5.02745 10.2 6.19217C10.2 7.35687 10.6077 8.34922 11.423 9.16922C12.2382 9.98922 13.2282 10.3992 14.393 10.3992Z"
100
+ fill="white"
101
+ />
102
+ </g>
103
+ </svg>
104
+ );
105
+
106
+ const getItem = (
107
+ id: string,
108
+ data: Partial<HeaderNavigationItemData>
109
+ ): HeaderNavigationItemData => ({
110
+ id,
111
+ to: id,
112
+ title: id[0].toUpperCase() + id.substring(1),
113
+ hint: id,
114
+ icon: undefined,
115
+ iconActive: undefined,
116
+ ...(data ?? {}),
117
+ });
118
+
119
+ export const items = {
120
+ calendar: getItem('calendar', {
121
+ iconName: 'event',
122
+ icon: SvgSchedule,
123
+ iconActive: SvgScheduleActive,
124
+ }),
125
+ calls: getItem('calls', {
126
+ iconName: 'local_phone',
127
+ icon: SvgCalls,
128
+ iconActive: SvgCallsActive,
129
+ counter: 12,
130
+ }),
131
+ dashboard: getItem('dashboard', {
132
+ iconName: 'odometer',
133
+ icon: SvgDashboard,
134
+ iconActive: SvgDashboardActive,
135
+ }),
136
+ dispatch: getItem('dispatch', {
137
+ iconName: 'location_disabled',
138
+ icon: SvgDispatch,
139
+ iconActive: SvgDispatchActive,
140
+ counter: 1,
141
+ }),
142
+ fleet: getItem('fleet', {
143
+ iconName: 'fleet-pro',
144
+ icon: SvgFleetPro,
145
+ iconActive: SvgFleetProActive,
146
+ title: 'Fleet Pro',
147
+ }),
148
+ followUps: getItem('followUps', {
149
+ iconName: 'flag',
150
+ icon: SvgFollowUp,
151
+ iconActive: SvgFollowUpActive,
152
+ title: 'Follow Ups',
153
+ }),
154
+ inventory: getItem('inventory', {
155
+ iconName: 'toys',
156
+ icon: SvgInventory,
157
+ iconActive: SvgInventoryActive,
158
+ }),
159
+ purchasing: getItem('purchasing', { iconComponent: InventoryIcon }),
160
+ accounting: getItem('accounting', {
161
+ iconName: 'assignment',
162
+ icon: SvgAccounting,
163
+ iconActive: SvgAccountingActive,
164
+ }),
165
+ marketing: getItem('marketing', {
166
+ iconName: 'bullhorn',
167
+ icon: SvgMarketing,
168
+ iconActive: SvgMarketingActive,
169
+ }),
170
+ priceBook: getItem('priceBook', {
171
+ iconName: 'book',
172
+ icon: SvgPriceBook,
173
+ iconActive: SvgPriceBookActive,
174
+ }),
175
+ pointOfSale: getItem('pointOfSale', {
176
+ iconName: 'cash-register',
177
+ icon: SvgPos,
178
+ iconActive: SvgPosActive,
179
+ }),
180
+ projects: getItem('projects', {
181
+ iconName: 'folder_special',
182
+ icon: SvgProjects,
183
+ iconActive: SvgProjectsActive,
184
+ }),
185
+ reports: getItem('reports', {
186
+ iconName: 'folder_special',
187
+ icon: SvgReports,
188
+ iconActive: SvgReportsActive,
189
+ }),
190
+ tasks: getItem('tasks', {
191
+ iconName: 'format_list_bulleted',
192
+ icon: SvgTasks,
193
+ iconActive: SvgTasksActive,
194
+ }),
195
+ };
196
+
197
+ export const CallsNavigationTrigger = () => {
198
+ const [open, setOpen] = useState(false);
199
+
200
+ return (
201
+ <Popover
202
+ open={open}
203
+ onClickOutside={() => setOpen(false)}
204
+ direction="bl"
205
+ trigger={
206
+ <HeaderNavigationTrigger
207
+ id="dialpad"
208
+ iconName="phone"
209
+ counter={2}
210
+ icon={SvgPhone}
211
+ iconActive={SvgPhoneActive}
212
+ onClick={() => setOpen(!open)}
213
+ isActive={open}
214
+ />
215
+ }
216
+ >
217
+ calls content
218
+ </Popover>
219
+ );
220
+ };
@@ -1,13 +1,18 @@
1
- import { FC, createContext, useContext } from 'react';
2
- import { NavLink } from 'react-router-dom';
1
+ import { FC, createContext } from 'react';
3
2
  import { NavLinkComponentProps } from './navigation';
4
3
 
5
- export const DefaultNavLinkComponent: FC<NavLinkComponentProps> = props => (
6
- <NavLink
7
- {...props}
8
- isActive={props.isActive && ((_, { pathname }) => props.isActive!(pathname))}
9
- />
10
- );
4
+ export const DefaultNavLinkComponent: FC<NavLinkComponentProps> = ({
5
+ children,
6
+ activeClassName,
7
+ isActive,
8
+ ...props
9
+ }) => <a {...props}>{children}</a>;
11
10
 
12
- export const NavLinkContext = createContext(DefaultNavLinkComponent);
13
- export const useNavLink = () => useContext(NavLinkContext);
11
+ export interface NavigationContextType {
12
+ NavigationComponent: FC<NavLinkComponentProps>;
13
+ isLegacy: boolean;
14
+ }
15
+ export const NavigationContext = createContext<NavigationContextType>({
16
+ NavigationComponent: DefaultNavLinkComponent,
17
+ isLegacy: false,
18
+ });
@@ -1,3 +1,4 @@
1
+ import { IconProps } from '@servicetitan/anvil2';
1
2
  import { IconPropsStrict } from '@servicetitan/design-system';
2
3
  import { FC, HTMLAttributeAnchorTarget, ReactNode } from 'react';
3
4
  import { CounterTagPropsType } from '../components/counter-tag';
@@ -27,6 +28,12 @@ export interface HeaderNavigationItemData {
27
28
  /** anvil's icon name of item */
28
29
  iconName?: IconPropsStrict['name'];
29
30
 
31
+ /** svg icon (anvil2) of inactive item */
32
+ icon: IconProps['svg'] | undefined;
33
+
34
+ /** svg icon (anvil2) of active item */
35
+ iconActive: IconProps['svg'] | undefined;
36
+
30
37
  /** icon component of item (<svg />) */
31
38
  iconComponent?: FC;
32
39