@servicetitan/navigation 9.0.1 → 9.1.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 (53) hide show
  1. package/dist/components/counter-tag.d.ts +1 -4
  2. package/dist/components/counter-tag.d.ts.map +1 -1
  3. package/dist/components/counter-tag.js.map +1 -1
  4. package/dist/components/left-navigation/index.d.ts +2 -0
  5. package/dist/components/left-navigation/index.d.ts.map +1 -1
  6. package/dist/components/left-navigation/index.js +2 -0
  7. package/dist/components/left-navigation/index.js.map +1 -1
  8. package/dist/components/left-navigation/interface-internal.d.ts +10 -0
  9. package/dist/components/left-navigation/interface-internal.d.ts.map +1 -0
  10. package/dist/components/left-navigation/interface-internal.js +2 -0
  11. package/dist/components/left-navigation/interface-internal.js.map +1 -0
  12. package/dist/components/left-navigation/interface.d.ts +11 -0
  13. package/dist/components/left-navigation/interface.d.ts.map +1 -0
  14. package/dist/components/left-navigation/interface.js +2 -0
  15. package/dist/components/left-navigation/interface.js.map +1 -0
  16. package/dist/components/left-navigation/side-navigation-links-internal.d.ts +23 -0
  17. package/dist/components/left-navigation/side-navigation-links-internal.d.ts.map +1 -0
  18. package/dist/components/left-navigation/side-navigation-links-internal.js +29 -0
  19. package/dist/components/left-navigation/side-navigation-links-internal.js.map +1 -0
  20. package/dist/components/left-navigation/side-navigation-links.d.ts +7 -0
  21. package/dist/components/left-navigation/side-navigation-links.d.ts.map +1 -0
  22. package/dist/components/left-navigation/side-navigation-links.js +20 -0
  23. package/dist/components/left-navigation/side-navigation-links.js.map +1 -0
  24. package/dist/components/left-navigation/side-navigation.d.ts +3 -11
  25. package/dist/components/left-navigation/side-navigation.d.ts.map +1 -1
  26. package/dist/components/left-navigation/side-navigation.js +12 -26
  27. package/dist/components/left-navigation/side-navigation.js.map +1 -1
  28. package/dist/components/left-navigation/side-navigation.module.less +11 -4
  29. package/dist/components/left-navigation/side-navigation.stories.d.ts +1 -0
  30. package/dist/components/left-navigation/side-navigation.stories.d.ts.map +1 -1
  31. package/dist/components/left-navigation/side-navigation.stories.js +22 -3
  32. package/dist/components/left-navigation/side-navigation.stories.js.map +1 -1
  33. package/dist/utils/counter-tag.d.ts +8 -0
  34. package/dist/utils/counter-tag.d.ts.map +1 -0
  35. package/dist/utils/counter-tag.js +2 -0
  36. package/dist/utils/counter-tag.js.map +1 -0
  37. package/dist/utils/side-nav.d.ts +3 -0
  38. package/dist/utils/side-nav.d.ts.map +1 -0
  39. package/dist/utils/side-nav.js +27 -0
  40. package/dist/utils/side-nav.js.map +1 -0
  41. package/package.json +2 -2
  42. package/src/components/counter-tag.tsx +1 -5
  43. package/src/components/left-navigation/index.ts +2 -0
  44. package/src/components/left-navigation/interface-internal.ts +11 -0
  45. package/src/components/left-navigation/interface.ts +13 -0
  46. package/src/components/left-navigation/side-navigation-links-internal.tsx +128 -0
  47. package/src/components/left-navigation/side-navigation-links.tsx +39 -0
  48. package/src/components/left-navigation/side-navigation.module.less +11 -4
  49. package/src/components/left-navigation/side-navigation.module.less.d.ts +2 -1
  50. package/src/components/left-navigation/side-navigation.stories.tsx +56 -3
  51. package/src/components/left-navigation/side-navigation.tsx +29 -124
  52. package/src/utils/counter-tag.ts +11 -0
  53. package/src/utils/side-nav.ts +34 -0
@@ -0,0 +1,11 @@
1
+ import { FC } from 'react';
2
+ import { NavLinkComponentProps } from '../../utils/navigation';
3
+ import { SideNavigationExpandedState } from './interface';
4
+
5
+ export interface NavigationComponentProps {
6
+ navigationComponent: FC<NavLinkComponentProps>;
7
+ }
8
+
9
+ export interface SideNavigationExpandedProps {
10
+ expanded?: SideNavigationExpandedState;
11
+ }
@@ -0,0 +1,13 @@
1
+ import { HeaderNavigationItemData } from '../../utils/navigation';
2
+
3
+ export interface SideNavigationExpandedState {
4
+ bar: boolean;
5
+ submenus?: string[];
6
+ }
7
+
8
+ export interface SideNavigationLinkProps
9
+ extends Omit<HeaderNavigationItemData, 'iconName' | 'submenu'> {}
10
+ export interface SideNavigationTriggerProps
11
+ extends Omit<SideNavigationLinkProps, 'to' | 'isActive'> {
12
+ isActive?: boolean;
13
+ }
@@ -0,0 +1,128 @@
1
+ import { Icon } from '@servicetitan/anvil2';
2
+ import SvgGroupCollapse from '@servicetitan/anvil2/assets/icons/material/round/expand_less.svg';
3
+ import SvgGroupExpand from '@servicetitan/anvil2/assets/icons/material/round/expand_more.svg';
4
+
5
+ import classNames from 'classnames';
6
+ import { FC, Fragment } from 'react';
7
+ import { HeaderNavigationItemData } from '../../utils/navigation';
8
+ import { CounterTag } from '../counter-tag';
9
+ import { SideNavigationTriggerProps } from './interface';
10
+ import { NavigationComponentProps, SideNavigationExpandedProps } from './interface-internal';
11
+ import * as Styles from './side-navigation.module.less';
12
+
13
+ export interface InternalSideNavigationItemContentProps
14
+ extends Omit<HeaderNavigationItemData, 'iconName' | 'to' | ''> {
15
+ submenuExpanded: boolean | undefined;
16
+ }
17
+
18
+ export const InternalSideNavigationItemContent: FC<InternalSideNavigationItemContentProps> = ({
19
+ icon,
20
+ iconActive,
21
+ iconClassName,
22
+ iconComponent: IconComponent,
23
+ tag,
24
+ title,
25
+ submenuExpanded,
26
+ }) => (
27
+ <Fragment>
28
+ <div className={Styles.navigationItemIconWrapper}>
29
+ {IconComponent ? (
30
+ <i className={classNames(Styles.navigationIcon, iconClassName)}>
31
+ <IconComponent />
32
+ </i>
33
+ ) : (
34
+ <Fragment>
35
+ {icon && (
36
+ <Icon
37
+ svg={icon}
38
+ className={classNames(
39
+ Styles.navigationIcon,
40
+ Styles.navigationIconInactive,
41
+ iconClassName
42
+ )}
43
+ />
44
+ )}
45
+ {iconActive && (
46
+ <Icon
47
+ svg={iconActive}
48
+ className={classNames(
49
+ Styles.navigationIcon,
50
+ Styles.navigationIconActive,
51
+ iconClassName
52
+ )}
53
+ />
54
+ )}
55
+ </Fragment>
56
+ )}
57
+
58
+ <div className={Styles.navigationItemTextExpanded}>{title}</div>
59
+ {!!tag && <CounterTag data={tag} className={Styles.navigationItemCounter} />}
60
+ {typeof submenuExpanded === 'boolean' && (
61
+ <Icon
62
+ svg={submenuExpanded ? SvgGroupCollapse : SvgGroupExpand}
63
+ className={Styles.navigationItemGroupToggle}
64
+ />
65
+ )}
66
+ </div>
67
+
68
+ <div
69
+ className={classNames(Styles.navigationItemTextCollapsed, {
70
+ [Styles.navigationItemTextSmall]: title.length >= 10,
71
+ })}
72
+ >
73
+ {title}
74
+ </div>
75
+ </Fragment>
76
+ );
77
+
78
+ export interface InternalSideNavigationLinkProps
79
+ extends Omit<HeaderNavigationItemData, 'iconName'>,
80
+ NavigationComponentProps,
81
+ SideNavigationExpandedProps {
82
+ submenuExpanded: boolean | undefined;
83
+ dataPrefix?: string;
84
+ }
85
+
86
+ export const internalNavigationContentContainerProps = ({
87
+ className,
88
+ icon,
89
+ iconActive,
90
+ iconComponent,
91
+ id,
92
+ isActive,
93
+ prefix,
94
+ }: Omit<SideNavigationTriggerProps, 'isActive'> & { prefix: string; isActive?: any }) => ({
95
+ 'data-cy': `${prefix}-${id}`,
96
+ 'data-pendo': `${prefix}-${id}`,
97
+ 'className': classNames(Styles.navigationItem, className, {
98
+ [Styles.navigationItemActive]: isActive === true,
99
+ [Styles.navigationItemIconSwitch]: !!icon && !!iconActive && !iconComponent,
100
+ }),
101
+ });
102
+
103
+ /** Side Navigation menu item (for internal usage) */
104
+ export const InternalSideNavigationLink: FC<InternalSideNavigationLinkProps> = ({
105
+ to,
106
+ className,
107
+ dataPrefix,
108
+ isActive,
109
+ navigationComponent: NavigationComponent,
110
+ submenuExpanded,
111
+ ...props
112
+ }) => {
113
+ return (
114
+ <NavigationComponent
115
+ {...internalNavigationContentContainerProps({
116
+ ...props,
117
+ prefix: dataPrefix ?? 'navigation-item',
118
+ className,
119
+ isActive,
120
+ })}
121
+ to={to}
122
+ isActive={typeof isActive === 'function' ? isActive : undefined}
123
+ activeClassName={Styles.navigationItemActive}
124
+ >
125
+ <InternalSideNavigationItemContent submenuExpanded={submenuExpanded} {...props} />
126
+ </NavigationComponent>
127
+ );
128
+ };
@@ -0,0 +1,39 @@
1
+ import classNames from 'classnames';
2
+ import { FC, useContext } from 'react';
3
+ import { NavigationComponentContext } from '../../utils/navigation-context';
4
+ import { SideNavigationLinkProps, SideNavigationTriggerProps } from './interface';
5
+ import {
6
+ InternalSideNavigationItemContent,
7
+ InternalSideNavigationLink,
8
+ internalNavigationContentContainerProps,
9
+ } from './side-navigation-links-internal';
10
+
11
+ /** Side Navigation menu link */
12
+ export const SideNavigationLink: FC<SideNavigationLinkProps> = props => {
13
+ const NavigationComponent = useContext(NavigationComponentContext);
14
+
15
+ return (
16
+ <InternalSideNavigationLink
17
+ {...props}
18
+ navigationComponent={NavigationComponent}
19
+ submenuExpanded={undefined}
20
+ dataPrefix="navigation-link"
21
+ />
22
+ );
23
+ };
24
+
25
+ /** Side Navigation menu link */
26
+ export const SideNavigationTrigger: FC<SideNavigationTriggerProps> = props => {
27
+ return (
28
+ <div
29
+ {...internalNavigationContentContainerProps({
30
+ ...props,
31
+ prefix: 'navigation-trigger',
32
+ className: classNames(props.className, 'cursor-pointer'),
33
+ isActive: props.isActive,
34
+ })}
35
+ >
36
+ <InternalSideNavigationItemContent submenuExpanded={undefined} {...props} />
37
+ </div>
38
+ );
39
+ };
@@ -44,7 +44,10 @@
44
44
  padding: @spacing-half;
45
45
  }
46
46
 
47
- .navigation-item-text {
47
+ .navigation-item-text-expanded {
48
+ display: none;
49
+ }
50
+ .navigation-item-text-collapsed {
48
51
  font-family: @base-font-family;
49
52
  font-size: 11px;
50
53
  line-height: 11px;
@@ -52,7 +55,7 @@
52
55
  text-align: center;
53
56
  }
54
57
 
55
- .navigation-item-text.navigation-item-text-small {
58
+ .navigation-item-text-collapsed.navigation-item-text-small {
56
59
  font-size: 10.5px;
57
60
  }
58
61
  }
@@ -81,13 +84,17 @@
81
84
  padding: @spacing-1 @spacing-half;
82
85
  }
83
86
 
84
- .navigation-item-text {
87
+ .navigation-item-text-expanded {
85
88
  font-family: @base-font-family;
86
89
  font-size: @typescale-3;
87
90
  padding-left: @spacing-1;
88
91
  flex: 1;
89
92
  }
90
93
 
94
+ .navigation-item-text-collapsed {
95
+ display: none;
96
+ }
97
+
91
98
  .navigation-item-counter {
92
99
  margin-right: @spacing-1;
93
100
  }
@@ -190,7 +197,7 @@
190
197
  }
191
198
 
192
199
  .navigation-item-counter {
193
- color: @color-white;
200
+ color: @color-black;
194
201
  font-weight: @font-weight-semibold;
195
202
  min-width: 12px !important;
196
203
  min-height: 12px !important;
@@ -9,7 +9,8 @@ export const navigationItemCounter: string;
9
9
  export const navigationItemGroupToggle: string;
10
10
  export const navigationItemIconSwitch: string;
11
11
  export const navigationItemIconWrapper: string;
12
- export const navigationItemText: string;
12
+ export const navigationItemTextCollapsed: string;
13
+ export const navigationItemTextExpanded: string;
13
14
  export const navigationItemTextSmall: string;
14
15
  export const optionsIcon: string;
15
16
  export const optionsIconWrapper: string;
@@ -1,5 +1,6 @@
1
+ import { Popover } from '@servicetitan/anvil2';
1
2
  import { Page } from '@servicetitan/design-system';
2
- import { ComponentType, useState } from 'react';
3
+ import { ComponentType, Fragment, useState } from 'react';
3
4
  import {
4
5
  LocationInfo,
5
6
  items,
@@ -7,7 +8,12 @@ import {
7
8
  withDefaultRedirects,
8
9
  withMemoryRouter,
9
10
  } from '../../test/data';
10
- import { SideNavigation, SideNavigationExpandedState } from './';
11
+ import {
12
+ SideNavigation,
13
+ SideNavigationExpandedState,
14
+ SideNavigationLink,
15
+ SideNavigationTrigger,
16
+ } from './';
11
17
 
12
18
  const layout = (Story: ComponentType) => {
13
19
  return (
@@ -50,7 +56,7 @@ export const DefaultSideNavigation = () => {
50
56
  items.pointOfSale,
51
57
  items.reports,
52
58
  ]}
53
- itemsTop={[items.tasks]}
59
+ itemsTop={<SideNavigationLink {...items.tasks} />}
54
60
  />
55
61
  );
56
62
  };
@@ -106,3 +112,50 @@ export const SideNavigationWithSubmenu = () => {
106
112
  />
107
113
  );
108
114
  };
115
+
116
+ const SideLinkWithPopover = () => {
117
+ return (
118
+ <Popover placement="right" openOnHover>
119
+ <Popover.Trigger>
120
+ {props => (
121
+ <div {...props}>
122
+ <SideNavigationTrigger {...items.marketing} isActive={false} />
123
+ </div>
124
+ )}
125
+ </Popover.Trigger>
126
+ <Popover.Content>popover content</Popover.Content>
127
+ </Popover>
128
+ );
129
+ };
130
+
131
+ export const SideNavigationWithCustomTopElements = () => {
132
+ const [expanded, setExpanded] = useState<SideNavigationExpandedState | undefined>(undefined);
133
+ return (
134
+ <SideNavigation
135
+ expanded={expanded}
136
+ onExpandedChange={setExpanded}
137
+ items={[
138
+ items.dashboard,
139
+ items.schedule,
140
+ items.dispatch,
141
+
142
+ items.accountingWithSubmenu,
143
+ items.purchasingWithSubmenu,
144
+
145
+ items.followUpsWithSubmenu,
146
+ items.reports,
147
+ items.marketing,
148
+ items.priceBook,
149
+
150
+ items.projects,
151
+ ]}
152
+ itemsTop={
153
+ <Fragment>
154
+ <SideNavigationLink {...items.calls} />
155
+ <SideNavigationLink {...items.tasks} />
156
+ <SideLinkWithPopover />
157
+ </Fragment>
158
+ }
159
+ />
160
+ );
161
+ };
@@ -1,6 +1,4 @@
1
1
  import { Icon, Popover, PopoverTriggerProps, Text } from '@servicetitan/anvil2';
2
- import SvgGroupCollapse from '@servicetitan/anvil2/assets/icons/material/round/expand_less.svg';
3
- import SvgGroupExpand from '@servicetitan/anvil2/assets/icons/material/round/expand_more.svg';
4
2
  import SvgCollapse from '@servicetitan/anvil2/assets/icons/st/gnav_menu_collapse.svg';
5
3
  import SvgExpand from '@servicetitan/anvil2/assets/icons/st/gnav_menu_expand.svg';
6
4
  import { Collapsible, Headline } from '@servicetitan/design-system';
@@ -12,6 +10,7 @@ import {
12
10
  Fragment,
13
11
  MouseEvent,
14
12
  ReactElement,
13
+ ReactNode,
15
14
  useCallback,
16
15
  useContext,
17
16
  } from 'react';
@@ -19,18 +18,16 @@ import {
19
18
  HeaderNavigationItemData,
20
19
  HeaderNavigationItemSubmenu,
21
20
  HeaderNavigationItemSubmenuLink,
22
- NavLinkComponentProps,
23
21
  } from '../../utils/navigation';
24
22
  import { NavigationComponentContext } from '../../utils/navigation-context';
23
+ import { getSubmenuGroupTag } from '../../utils/side-nav';
25
24
  import { CounterTag } from '../counter-tag';
25
+ import { SideNavigationExpandedState } from './interface';
26
+ import { NavigationComponentProps, SideNavigationExpandedProps } from './interface-internal';
27
+ import { InternalSideNavigationLink } from './side-navigation-links-internal';
26
28
  import * as Styles from './side-navigation.module.less';
27
29
  import { withTooltip } from './with-tooltip';
28
30
 
29
- export interface SideNavigationExpandedState {
30
- bar: boolean;
31
- submenus?: string[];
32
- }
33
-
34
31
  export interface SideNavigationProps {
35
32
  /** container class name */
36
33
  className?: string;
@@ -39,7 +36,7 @@ export interface SideNavigationProps {
39
36
  /** main navigation items */
40
37
  items?: HeaderNavigationItemData[];
41
38
  /** top navigation items */
42
- itemsTop?: HeaderNavigationItemData[];
39
+ itemsTop?: ReactNode;
43
40
  /** is menu expanded */
44
41
  expanded?: SideNavigationExpandedState;
45
42
  /** expand change handler */
@@ -65,17 +62,10 @@ export const SideNavigation: FC<SideNavigationProps> = ({
65
62
  id={id}
66
63
  data-cy="side-navigation"
67
64
  >
68
- {!!itemsTop?.length && (
65
+ {!!itemsTop && (
69
66
  <Fragment>
70
67
  <div className={Styles.sideNavTop} data-cy="navigation-items-top">
71
- {itemsTop.map(item => (
72
- <SideNavigationItem
73
- key={item.id}
74
- expanded={expanded}
75
- navigationComponent={NavigationComponent}
76
- {...item}
77
- />
78
- ))}
68
+ {itemsTop}
79
69
  </div>
80
70
  <div className={Styles.divider} />
81
71
  </Fragment>
@@ -91,9 +81,9 @@ export const SideNavigation: FC<SideNavigationProps> = ({
91
81
  {...item}
92
82
  />
93
83
  ) : (
94
- <SideNavigationItem
84
+ <InternalSideNavigationLink
95
85
  key={item.id}
96
- expanded={expanded}
86
+ submenuExpanded={undefined}
97
87
  navigationComponent={NavigationComponent}
98
88
  {...item}
99
89
  />
@@ -111,113 +101,22 @@ export const SideNavigation: FC<SideNavigationProps> = ({
111
101
  );
112
102
  };
113
103
 
114
- interface NavigationComponentProps {
115
- navigationComponent: FC<NavLinkComponentProps>;
116
- }
117
-
118
- interface SideNavigationItemProps extends HeaderNavigationItemData, NavigationComponentProps {
119
- expanded?: SideNavigationExpandedState;
120
- }
121
-
122
- /** Side Navigation menu item */
123
- const SideNavigationItem: FC<SideNavigationItemProps> = ({
124
- id,
125
- to,
126
- title,
127
- className,
128
- iconClassName,
129
- iconComponent: IconComponent,
130
- icon,
131
- iconActive,
132
- isActive,
133
- navigationComponent: NavigationComponent,
134
- tag,
135
- expanded,
136
- submenu,
137
- }) => {
138
- const iconSwitch = !!icon && !!iconActive && !IconComponent;
139
- const hasSubmenu = !!submenu;
140
-
141
- return (
142
- <NavigationComponent
143
- data-cy={`navigation-item-${id}`}
144
- data-pendo={`navigation-item-${id}`}
145
- key={id}
146
- to={to}
147
- className={classNames(Styles.navigationItem, className, {
148
- [Styles.navigationItemActive]: isActive === true,
149
- [Styles.navigationItemIconSwitch]: iconSwitch,
150
- })}
151
- isActive={typeof isActive === 'function' ? isActive : undefined}
152
- activeClassName={Styles.navigationItemActive}
153
- >
154
- <div className={Styles.navigationItemIconWrapper}>
155
- {IconComponent ? (
156
- <i className={classNames(Styles.navigationIcon, iconClassName)}>
157
- <IconComponent />
158
- </i>
159
- ) : (
160
- <Fragment>
161
- {icon && (
162
- <Icon
163
- svg={icon}
164
- className={classNames(
165
- Styles.navigationIcon,
166
- Styles.navigationIconInactive,
167
- iconClassName
168
- )}
169
- />
170
- )}
171
- {iconActive && (
172
- <Icon
173
- svg={iconActive}
174
- className={classNames(
175
- Styles.navigationIcon,
176
- Styles.navigationIconActive,
177
- iconClassName
178
- )}
179
- />
180
- )}
181
- </Fragment>
182
- )}
183
-
184
- {!!expanded?.bar && <div className={Styles.navigationItemText}>{title}</div>}
185
- {!!tag && <CounterTag data={tag} className={Styles.navigationItemCounter} />}
186
- {hasSubmenu && !!expanded?.bar && (
187
- <Icon
188
- svg={expanded?.submenus?.includes(id) ? SvgGroupCollapse : SvgGroupExpand}
189
- className={Styles.navigationItemGroupToggle}
190
- />
191
- )}
192
- </div>
193
-
194
- {!expanded?.bar && (
195
- <div
196
- className={classNames(Styles.navigationItemText, {
197
- [Styles.navigationItemTextSmall]: title.length >= 10,
198
- })}
199
- >
200
- {title}
201
- </div>
202
- )}
203
- </NavigationComponent>
204
- );
205
- };
206
-
207
104
  const submenuPopoverStyles = { '--background-color-strong': '#24323C' } as CSSProperties;
208
105
 
209
106
  /** Side Navigation menu item */
210
107
  const SideNavigationGroupItem: FC<
211
- SideNavigationItemProps & {
212
- onExpandedChange: undefined | ((expanded: SideNavigationExpandedState) => void);
213
- }
108
+ HeaderNavigationItemData &
109
+ SideNavigationExpandedProps &
110
+ NavigationComponentProps & {
111
+ onExpandedChange: undefined | ((expanded: SideNavigationExpandedState) => void);
112
+ }
214
113
  > = ({ onExpandedChange, ...props }) => {
114
+ const isSubmenuExpanded = props.expanded?.submenus?.includes(props.id) ?? false;
215
115
  const triggerClick = useCallback(
216
116
  (e: MouseEvent<HTMLDivElement>) => {
217
117
  e.stopPropagation();
218
118
  e.preventDefault();
219
119
 
220
- const isSubmenuExpanded = props.expanded?.submenus?.includes(props.id);
221
120
  onExpandedChange?.({
222
121
  bar: !!props.expanded?.bar,
223
122
  submenus: [
@@ -226,17 +125,19 @@ const SideNavigationGroupItem: FC<
226
125
  ],
227
126
  });
228
127
  },
229
- [props.id, props.expanded, onExpandedChange]
128
+ [props.id, props.expanded, isSubmenuExpanded, onExpandedChange]
230
129
  );
231
130
 
232
- const tag = props.submenu?.groups.some(group => group.links.some(link => !!link.tag))
233
- ? true
234
- : props.tag;
131
+ const tag = getSubmenuGroupTag(props.submenu, props.tag);
235
132
 
236
133
  return props.expanded?.bar ? (
237
134
  <Fragment>
238
135
  <div onClickCapture={triggerClick}>
239
- <SideNavigationItem {...props} tag={tag} />
136
+ <InternalSideNavigationLink
137
+ {...props}
138
+ submenuExpanded={isSubmenuExpanded}
139
+ tag={tag}
140
+ />
240
141
  </div>
241
142
  <Collapsible open={props.expanded?.submenus?.includes(props.id)} animate>
242
143
  <div className={Styles.submenu}>
@@ -252,7 +153,11 @@ const SideNavigationGroupItem: FC<
252
153
  <Popover.Trigger>
253
154
  {(triggerProps: PopoverTriggerProps) => (
254
155
  <div {...triggerProps}>
255
- <SideNavigationItem {...props} tag={tag} />
156
+ <InternalSideNavigationLink
157
+ {...props}
158
+ submenuExpanded={undefined}
159
+ tag={tag}
160
+ />
256
161
  </div>
257
162
  )}
258
163
  </Popover.Trigger>
@@ -329,7 +234,7 @@ const SideNavigationGroupLink: FC<HeaderNavigationItemSubmenuLink & NavigationCo
329
234
  };
330
235
 
331
236
  /** Side Navigation options toggle */
332
- export const SideNavigationOptionsToggle: FC<{
237
+ const SideNavigationOptionsToggle: FC<{
333
238
  expanded?: SideNavigationExpandedState;
334
239
  onExpandedChange?(expanded: SideNavigationExpandedState): void;
335
240
  }> = ({ expanded, onExpandedChange }) =>
@@ -0,0 +1,11 @@
1
+ import { CounterTagProps } from '../components/counter-tag';
2
+
3
+ export interface CounterTagPropsStrict {
4
+ value: number | boolean;
5
+ className?: string;
6
+ }
7
+
8
+ export type CounterTagType = boolean | number | CounterTagProps;
9
+
10
+ export const isCounterPropsObject = (tag?: CounterTagType): tag is CounterTagProps =>
11
+ !!tag && (tag as any).value !== undefined;
@@ -0,0 +1,34 @@
1
+ import { isCounterPropsObject } from './counter-tag';
2
+ import { HeaderNavigationItemData, HeaderNavigationItemSubmenu } from './navigation';
3
+
4
+ export function getSubmenuGroupTag(
5
+ submenu: HeaderNavigationItemSubmenu | undefined,
6
+ defaultTag: HeaderNavigationItemData['tag']
7
+ ): HeaderNavigationItemData['tag'] {
8
+ if (!submenu) {
9
+ return defaultTag;
10
+ }
11
+
12
+ let tagValue: number | boolean | undefined = undefined;
13
+
14
+ for (const group of submenu.groups) {
15
+ for (const link of group.links) {
16
+ const ltv: number | boolean | undefined = isCounterPropsObject(link.tag)
17
+ ? link.tag.value
18
+ : link.tag;
19
+
20
+ if (ltv) {
21
+ if (typeof ltv === 'number') {
22
+ if (typeof tagValue !== 'number') {
23
+ tagValue = 0;
24
+ }
25
+ tagValue += ltv;
26
+ } else if (typeof tagValue !== 'number') {
27
+ tagValue = true;
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ return tagValue ?? defaultTag;
34
+ }