@servicetitan/navigation 8.1.7 → 8.2.1

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 (33) hide show
  1. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
  2. package/dist/components/header-navigation/header-navigation-links.js +1 -1
  3. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  4. package/dist/components/layout.stories.d.ts +1 -0
  5. package/dist/components/layout.stories.d.ts.map +1 -1
  6. package/dist/components/layout.stories.js +6 -2
  7. package/dist/components/layout.stories.js.map +1 -1
  8. package/dist/components/left-navigation/header-navigation-tiny.stories.js +1 -1
  9. package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
  10. package/dist/components/left-navigation/side-navigation.d.ts.map +1 -1
  11. package/dist/components/left-navigation/side-navigation.js +40 -5
  12. package/dist/components/left-navigation/side-navigation.js.map +1 -1
  13. package/dist/components/left-navigation/side-navigation.module.less +119 -2
  14. package/dist/components/left-navigation/side-navigation.stories.d.ts +1 -0
  15. package/dist/components/left-navigation/side-navigation.stories.d.ts.map +1 -1
  16. package/dist/components/left-navigation/side-navigation.stories.js +19 -2
  17. package/dist/components/left-navigation/side-navigation.stories.js.map +1 -1
  18. package/dist/test/data.d.ts +4 -0
  19. package/dist/test/data.d.ts.map +1 -1
  20. package/dist/test/data.js +83 -7
  21. package/dist/test/data.js.map +1 -1
  22. package/dist/utils/navigation.d.ts +23 -9
  23. package/dist/utils/navigation.d.ts.map +1 -1
  24. package/package.json +2 -2
  25. package/src/components/header-navigation/header-navigation-links.tsx +2 -0
  26. package/src/components/layout.stories.tsx +19 -1
  27. package/src/components/left-navigation/header-navigation-tiny.stories.tsx +1 -1
  28. package/src/components/left-navigation/side-navigation.module.less +119 -2
  29. package/src/components/left-navigation/side-navigation.module.less.d.ts +7 -0
  30. package/src/components/left-navigation/side-navigation.stories.tsx +33 -2
  31. package/src/components/left-navigation/side-navigation.tsx +173 -13
  32. package/src/test/data.tsx +99 -8
  33. package/src/utils/navigation.ts +31 -13
package/src/test/data.tsx CHANGED
@@ -30,7 +30,7 @@ import SvgSchedule from '@servicetitan/anvil2/assets/icons/st/gnav_schedule_inac
30
30
  import SvgTasksActive from '@servicetitan/anvil2/assets/icons/st/gnav_tasks_active.svg';
31
31
  import SvgTasks from '@servicetitan/anvil2/assets/icons/st/gnav_tasks_inactive.svg';
32
32
 
33
- import { Popover } from '@servicetitan/design-system';
33
+ import { BodyText, Popover } from '@servicetitan/design-system';
34
34
 
35
35
  import classNames from 'classnames';
36
36
  import { forwardRef, useState } from 'react';
@@ -38,7 +38,12 @@ import { forwardRef, useState } from 'react';
38
38
  // eslint-disable-next-line import/no-extraneous-dependencies
39
39
  import { MemoryRouter, useHistory, useLocation } from 'react-router-dom';
40
40
  import { HeaderNavigationTrigger } from '../components/links';
41
- import { HeaderNavigationItemData, NavLinkComponentProps } from '../utils/navigation';
41
+ import {
42
+ HeaderNavigationItemData,
43
+ HeaderNavigationItemLinkProps,
44
+ HeaderNavigationItemSubmenuGroup,
45
+ NavLinkComponentProps,
46
+ } from '../utils/navigation';
42
47
  import { NavigationComponentContext } from '../utils/navigation-context';
43
48
  import * as Styles from './data-stories.module.less';
44
49
 
@@ -46,20 +51,21 @@ export const NavLinkMock = forwardRef<any, NavLinkComponentProps>(
46
51
  ({ to, children, activeClassName, className, isActive, ...rest }, ref) => {
47
52
  const history = useHistory();
48
53
  const location = useLocation();
49
- const linkActive = location.pathname.replace('/', '') === to;
54
+ const linkActive = location.pathname.startsWith(to);
50
55
 
51
56
  return (
52
57
  <a
53
58
  {...rest}
54
- className={classNames(className, linkActive ? activeClassName : '')}
55
- href={to}
56
59
  onClick={e => {
57
60
  e.preventDefault();
61
+ e.stopPropagation();
58
62
 
59
63
  if (!to.startsWith('http')) {
60
- history.push(to);
64
+ history.replace(to);
61
65
  }
62
66
  }}
67
+ className={classNames(className, linkActive ? activeClassName : '')}
68
+ href={to}
63
69
  ref={ref}
64
70
  >
65
71
  {children}
@@ -68,6 +74,12 @@ export const NavLinkMock = forwardRef<any, NavLinkComponentProps>(
68
74
  }
69
75
  );
70
76
 
77
+ export const LocationInfo = () => {
78
+ const location = useLocation();
79
+
80
+ return <BodyText>current location - {location.pathname}</BodyText>;
81
+ };
82
+
71
83
  export const withMemoryRouter = (Story: any) => (
72
84
  <MemoryRouter>
73
85
  <NavigationComponentContext.Provider value={NavLinkMock}>
@@ -111,12 +123,42 @@ const getItem = (
111
123
  data: Partial<HeaderNavigationItemData>
112
124
  ): HeaderNavigationItemData => ({
113
125
  id,
114
- to: id,
126
+ to: '/' + id,
115
127
  title: id[0].toUpperCase() + id.substring(1),
116
128
  hint: id,
117
129
  icon: undefined,
118
130
  iconActive: undefined,
119
131
  ...(data ?? {}),
132
+ submenu: data.submenu
133
+ ? {
134
+ ...data.submenu,
135
+ groups: data.submenu.groups.map(group => ({
136
+ ...group,
137
+ links: group.links.map(link => ({
138
+ ...link,
139
+ to: `/${id}/${link.to}`,
140
+ })),
141
+ })),
142
+ }
143
+ : undefined,
144
+ });
145
+
146
+ const getSubItem = (
147
+ id: string,
148
+ data: Partial<HeaderNavigationItemLinkProps>
149
+ ): HeaderNavigationItemLinkProps => ({
150
+ id,
151
+ to: id,
152
+ title: id[0].toUpperCase() + id.substring(1),
153
+ ...(data ?? {}),
154
+ });
155
+
156
+ const getGroup = (
157
+ title: string,
158
+ links: HeaderNavigationItemLinkProps[]
159
+ ): HeaderNavigationItemSubmenuGroup => ({
160
+ title,
161
+ links,
120
162
  });
121
163
 
122
164
  export const items = {
@@ -159,23 +201,72 @@ export const items = {
159
201
  iconActive: SvgFollowUpActive,
160
202
  title: 'Follow Up',
161
203
  }),
204
+ followUpsWithSubmenu: getItem('followUps', {
205
+ iconName: 'flag',
206
+ icon: SvgFollowUp,
207
+ iconActive: SvgFollowUpActive,
208
+ title: 'Follow Up',
209
+ submenu: {
210
+ groups: [
211
+ getGroup('', [
212
+ getSubItem('estimates', { title: 'Unsold Estimates' }),
213
+ getSubItem('sold', { title: 'Sold Estimates' }),
214
+ getSubItem('surveys', { title: 'Surveys' }),
215
+ ]),
216
+ ],
217
+ },
218
+ }),
162
219
  inventory: getItem('inventory', {
163
220
  iconName: 'toys',
164
221
  icon: SvgInventory,
165
222
  iconActive: SvgInventoryActive,
166
223
  }),
167
224
  purchasing: getItem('purchasing', { iconComponent: InventoryIcon }),
225
+ purchasingWithSubmenu: getItem('purchasing', {
226
+ iconName: 'toys',
227
+ icon: SvgInventory,
228
+ iconActive: SvgInventoryActive,
229
+ submenu: {
230
+ groups: [
231
+ getGroup('Purchase', [
232
+ getSubItem('repl', { title: 'Replenishment' }),
233
+ getSubItem('orders', { title: 'Purchase Orders' }),
234
+ getSubItem('receipts', { title: 'Receipts' }),
235
+ getSubItem('returns', { title: 'Returns' }),
236
+ ]),
237
+ ],
238
+ },
239
+ }),
168
240
  accounting: getItem('accounting', {
169
241
  iconName: 'assignment',
170
242
  icon: SvgAccounting,
171
243
  iconActive: SvgAccountingActive,
172
244
  }),
245
+ accountingWithSubmenu: getItem('accounting', {
246
+ iconName: 'assignment',
247
+ icon: SvgAccounting,
248
+ iconActive: SvgAccountingActive,
249
+ submenu: {
250
+ groups: [
251
+ getGroup('Accounts Receivable', [
252
+ getSubItem('ar', { title: 'AR Management' }),
253
+ getSubItem('export', { title: 'Batch/Export Transactions' }),
254
+ getSubItem('invoices', { title: 'Invoices' }),
255
+ getSubItem('payments', { title: 'Customer Payments' }),
256
+ getSubItem('deposits', { title: 'Bank Deposits' }),
257
+ ]),
258
+ getGroup('Accounts Payable', [getSubItem('bills', { title: 'Bills' })]),
259
+ getGroup('Financing', [getSubItem('dashboard', { title: 'Dashboard' })]),
260
+ getGroup('Others', [getSubItem('at', { title: 'Accounting Audit Trail' })]),
261
+ ],
262
+ },
263
+ }),
173
264
  marketing: getItem('marketing', {
174
265
  iconName: 'bullhorn',
175
266
  icon: SvgMarketing,
176
267
  iconActive: SvgMarketingActive,
177
268
  }),
178
- priceBook: getItem('priceBook', {
269
+ priceBook: getItem('pricebook', {
179
270
  iconName: 'book',
180
271
  icon: SvgPriceBook,
181
272
  iconActive: SvgPriceBookActive,
@@ -3,22 +3,10 @@ import { IconPropsStrict } from '@servicetitan/design-system';
3
3
  import { FC, HTMLAttributeAnchorTarget, ReactNode } from 'react';
4
4
  import { CounterTagPropsType } from '../components/counter-tag';
5
5
 
6
- export interface HeaderNavigationItemData {
7
- /** link id */
8
- id: string;
9
-
10
- /** link href */
11
- to: string;
12
-
13
- /** link title */
14
- title: string;
15
-
6
+ export interface HeaderNavigationItemData extends HeaderNavigationItemLinkProps {
16
7
  /** link description */
17
8
  hint: string;
18
9
 
19
- /** callback to return active state. By default, it compares link href with current pathname */
20
- isActive?: boolean | ((pathname: string) => boolean);
21
-
22
10
  /** flag if the link is not shown (based on FG and/or user permissions) */
23
11
  isHidden?: boolean;
24
12
 
@@ -42,6 +30,36 @@ export interface HeaderNavigationItemData {
42
30
 
43
31
  /** class name of link item */
44
32
  className?: string;
33
+
34
+ /** optional submenu of link item */
35
+ submenu?: HeaderNavigationItemSubmenu;
36
+ }
37
+
38
+ export interface HeaderNavigationItemLinkProps {
39
+ /** link id */
40
+ id: string;
41
+
42
+ /** link href */
43
+ to: string;
44
+
45
+ /** link title */
46
+ title: string;
47
+
48
+ /** callback to return active state. By default, it compares link href with current pathname */
49
+ isActive?: boolean | ((pathname: string) => boolean);
50
+ }
51
+
52
+ export interface HeaderNavigationItemSubmenu {
53
+ /** submenu groups */
54
+ groups: HeaderNavigationItemSubmenuGroup[];
55
+ }
56
+
57
+ export interface HeaderNavigationItemSubmenuGroup {
58
+ /** submenu group title */
59
+ title: string;
60
+
61
+ /** submenu group links */
62
+ links: HeaderNavigationItemLinkProps[];
45
63
  }
46
64
 
47
65
  export interface NavLinkComponentPropsStrict {