@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.
- package/dist/components/header-navigation/header-navigation-content.d.ts +7 -0
- package/dist/components/header-navigation/header-navigation-content.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-content.js +8 -7
- package/dist/components/header-navigation/header-navigation-content.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.d.ts +3 -2
- package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.js +6 -20
- package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.d.ts +5 -3
- package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.js +12 -6
- package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts +1 -0
- package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.js +4 -23
- package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-tiny.stories.js +11 -7
- package/dist/components/header-navigation/header-navigation-tiny.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.js +17 -5
- package/dist/components/header-navigation/header-navigation.js.map +1 -1
- package/dist/components/header-navigation/header-navigation.module.less +25 -0
- package/dist/components/header-navigation/header-navigation.stories.d.ts +1 -0
- package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.stories.js +5 -24
- package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
- package/dist/components/layout.stories.d.ts +1 -0
- package/dist/components/layout.stories.d.ts.map +1 -1
- package/dist/components/layout.stories.js +2 -0
- package/dist/components/layout.stories.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +2 -8
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js +5 -43
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.d.ts +9 -0
- package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.d.ts.map +1 -0
- package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.js +13 -0
- package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.js.map +1 -0
- package/dist/components/profile-dropdown/profile-dropdown.d.ts +2 -1
- package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.js +16 -7
- package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.module.less +7 -1
- package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts +9 -8
- package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.stories.js +39 -39
- package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
- package/dist/components/side-navigation/side-navigation.d.ts +1 -12
- package/dist/components/side-navigation/side-navigation.d.ts.map +1 -1
- package/dist/components/side-navigation/side-navigation.js +10 -24
- package/dist/components/side-navigation/side-navigation.js.map +1 -1
- package/dist/components/side-navigation/side-navigation.module.less +26 -20
- package/dist/components/side-navigation/side-navigation.stories.d.ts +3 -3
- package/dist/components/side-navigation/side-navigation.stories.d.ts.map +1 -1
- package/dist/components/side-navigation/side-navigation.stories.js +2 -23
- package/dist/components/side-navigation/side-navigation.stories.js.map +1 -1
- package/dist/test/data-stories.module.less +6 -0
- package/dist/test/data.stories.d.ts +26 -0
- package/dist/test/data.stories.d.ts.map +1 -0
- package/dist/test/data.stories.js +150 -0
- package/dist/test/data.stories.js.map +1 -0
- package/dist/utils/navigation-context.d.ts +5 -2
- package/dist/utils/navigation-context.d.ts.map +1 -1
- package/dist/utils/navigation-context.js +20 -5
- package/dist/utils/navigation-context.js.map +1 -1
- package/dist/utils/navigation.d.ts +5 -0
- package/dist/utils/navigation.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/components/header-navigation/header-navigation-content.tsx +39 -11
- package/src/components/header-navigation/header-navigation-extra.stories.tsx +24 -21
- package/src/components/header-navigation/header-navigation-links.tsx +36 -8
- package/src/components/header-navigation/header-navigation-stacked.stories.tsx +16 -66
- package/src/components/header-navigation/header-navigation-tiny.stories.tsx +37 -41
- package/src/components/header-navigation/header-navigation.module.less +25 -0
- package/src/components/header-navigation/header-navigation.module.less.d.ts +2 -0
- package/src/components/header-navigation/header-navigation.stories.tsx +18 -67
- package/src/components/header-navigation/header-navigation.tsx +45 -8
- package/src/components/layout.stories.tsx +2 -0
- package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +7 -170
- package/src/components/profile-dropdown/profile-dropdown-tiny.stories.tsx +15 -0
- package/src/components/profile-dropdown/profile-dropdown.module.less +7 -1
- package/src/components/profile-dropdown/profile-dropdown.module.less.d.ts +1 -0
- package/src/components/profile-dropdown/profile-dropdown.stories.tsx +106 -129
- package/src/components/profile-dropdown/profile-dropdown.tsx +32 -8
- package/src/components/side-navigation/side-navigation.module.less +26 -20
- package/src/components/side-navigation/side-navigation.module.less.d.ts +2 -3
- package/src/components/side-navigation/side-navigation.stories.tsx +3 -52
- package/src/components/side-navigation/side-navigation.tsx +71 -124
- package/src/test/data-stories.module.less +6 -0
- package/src/test/data-stories.module.less.d.ts +3 -0
- package/src/test/data.stories.tsx +220 -0
- package/src/utils/navigation-context.tsx +15 -10
- package/src/utils/navigation.ts +7 -0
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<
|
|
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
|
-
|
|
68
|
+
navigationComponent={navigationComponent}
|
|
69
|
+
{...item}
|
|
71
70
|
/>
|
|
72
|
-
|
|
71
|
+
))}
|
|
73
72
|
</div>
|
|
74
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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={
|
|
119
|
+
<i className={classNames(Styles.navigationIcon, iconClassName)}>
|
|
114
120
|
<IconComponent />
|
|
115
121
|
</i>
|
|
116
|
-
) : iconName ? (
|
|
117
|
-
<Icon name={iconName} className={iconClass} />
|
|
118
122
|
) : (
|
|
119
|
-
<
|
|
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
|
-
'
|
|
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
|
-
<
|
|
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
|
-
'
|
|
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,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
|
|
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> =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
13
|
-
|
|
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
|
+
});
|
package/src/utils/navigation.ts
CHANGED
|
@@ -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
|
|