@servicetitan/navigation 9.2.0 → 10.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/counter-tag.d.ts +4 -4
- package/dist/components/counter-tag.d.ts.map +1 -1
- package/dist/components/counter-tag.js +2 -8
- package/dist/components/counter-tag.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-content.d.ts +3 -3
- package/dist/components/header-navigation/header-navigation-content.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-content.js +3 -2
- package/dist/components/header-navigation/header-navigation-content.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.js +3 -3
- package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.d.ts +1 -1
- package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.js +5 -4
- package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.js +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation.d.ts +1 -1
- package/dist/components/header-navigation/header-navigation.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.js.map +1 -1
- package/dist/components/header-navigation/header-navigation.stories.js +1 -1
- package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
- package/dist/components/header-navigation/with-tooltip.d.ts +1 -1
- package/dist/components/left-navigation/header-navigation-tiny-links.d.ts +3 -3
- package/dist/components/left-navigation/header-navigation-tiny-links.d.ts.map +1 -1
- package/dist/components/left-navigation/header-navigation-tiny-links.js +5 -4
- package/dist/components/left-navigation/header-navigation-tiny-links.js.map +1 -1
- package/dist/components/left-navigation/header-navigation-tiny.stories.js +2 -2
- package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
- package/dist/components/left-navigation/interface-internal.d.ts +1 -1
- package/dist/components/left-navigation/interface-internal.d.ts.map +1 -1
- package/dist/components/left-navigation/interface.d.ts +2 -2
- package/dist/components/left-navigation/interface.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation-links-internal.d.ts +7 -4
- package/dist/components/left-navigation/side-navigation-links-internal.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation-links-internal.js.map +1 -1
- package/dist/components/left-navigation/side-navigation-links.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation-links.js +3 -2
- package/dist/components/left-navigation/side-navigation-links.js.map +1 -1
- package/dist/components/left-navigation/side-navigation.d.ts +2 -2
- package/dist/components/left-navigation/side-navigation.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation.js +6 -6
- package/dist/components/left-navigation/side-navigation.js.map +1 -1
- package/dist/components/links.d.ts +1 -1
- package/dist/components/links.d.ts.map +1 -1
- package/dist/components/links.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.d.ts +3 -2
- package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.js +3 -2
- package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.stories.js +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/test/data.d.ts +2 -1
- package/dist/test/data.d.ts.map +1 -1
- package/dist/test/data.js +10 -7
- package/dist/test/data.js.map +1 -1
- package/dist/utils/counter-tag.d.ts +3 -6
- package/dist/utils/counter-tag.d.ts.map +1 -1
- package/dist/utils/counter-tag.js +1 -1
- package/dist/utils/counter-tag.js.map +1 -1
- package/dist/utils/navigation-context.d.ts +13 -2
- package/dist/utils/navigation-context.d.ts.map +1 -1
- package/dist/utils/navigation-context.js.map +1 -1
- package/dist/utils/navigation-legacy.d.ts +86 -0
- package/dist/utils/navigation-legacy.d.ts.map +1 -0
- package/dist/utils/navigation-legacy.js +2 -0
- package/dist/utils/navigation-legacy.js.map +1 -0
- package/dist/utils/navigation.d.ts +15 -76
- package/dist/utils/navigation.d.ts.map +1 -1
- package/dist/utils/side-nav.d.ts +5 -2
- package/dist/utils/side-nav.d.ts.map +1 -1
- package/dist/utils/side-nav.js +6 -5
- package/dist/utils/side-nav.js.map +1 -1
- package/package.json +2 -2
- package/src/components/counter-tag.tsx +10 -21
- package/src/components/header-navigation/header-navigation-content.tsx +6 -4
- package/src/components/header-navigation/header-navigation-extra.stories.tsx +3 -3
- package/src/components/header-navigation/header-navigation-links.tsx +9 -3
- package/src/components/header-navigation/header-navigation-stacked.stories.tsx +2 -2
- package/src/components/header-navigation/header-navigation.stories.tsx +2 -2
- package/src/components/header-navigation/header-navigation.tsx +1 -1
- package/src/components/left-navigation/header-navigation-tiny-links.tsx +11 -5
- package/src/components/left-navigation/header-navigation-tiny.stories.tsx +2 -2
- package/src/components/left-navigation/interface-internal.ts +1 -1
- package/src/components/left-navigation/interface.ts +2 -3
- package/src/components/left-navigation/side-navigation-links-internal.tsx +7 -5
- package/src/components/left-navigation/side-navigation-links.tsx +7 -1
- package/src/components/left-navigation/side-navigation.tsx +16 -11
- package/src/components/links.tsx +4 -1
- package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -1
- package/src/components/profile-dropdown/profile-dropdown.tsx +10 -3
- package/src/index.ts +6 -1
- package/src/test/data.tsx +17 -18
- package/src/utils/counter-tag.ts +3 -9
- package/src/utils/navigation-context.tsx +15 -2
- package/src/utils/navigation-legacy.ts +104 -0
- package/src/utils/navigation.ts +15 -85
- package/src/utils/side-nav.ts +17 -9
|
@@ -17,12 +17,12 @@ import {
|
|
|
17
17
|
useMemo,
|
|
18
18
|
} from 'react';
|
|
19
19
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
NavigationItemData,
|
|
21
|
+
NavigationSubmenuData,
|
|
22
|
+
NavigationSubmenuItemData,
|
|
23
23
|
} from '../../utils/navigation';
|
|
24
24
|
import { NavigationComponentContext } from '../../utils/navigation-context';
|
|
25
|
-
import { getSubmenuGroupTag } from '../../utils/side-nav';
|
|
25
|
+
import { getCounterTag, getSubmenuGroupTag } from '../../utils/side-nav';
|
|
26
26
|
import { CounterTag } from '../counter-tag';
|
|
27
27
|
import {
|
|
28
28
|
SideNavigationExpandedState,
|
|
@@ -44,7 +44,7 @@ export interface SideNavigationProps {
|
|
|
44
44
|
/** container id */
|
|
45
45
|
id?: string;
|
|
46
46
|
/** main navigation items */
|
|
47
|
-
items?:
|
|
47
|
+
items?: NavigationItemData[];
|
|
48
48
|
/** additional components */
|
|
49
49
|
children?: OptionalChildren<SideNavigationTopProps>;
|
|
50
50
|
/** is menu expanded */
|
|
@@ -119,6 +119,7 @@ function SideNavigationElement({
|
|
|
119
119
|
submenuExpanded={undefined}
|
|
120
120
|
navigationComponent={NavigationComponent}
|
|
121
121
|
{...item}
|
|
122
|
+
tag={getCounterTag(item.counter, item.tag)}
|
|
122
123
|
/>
|
|
123
124
|
)
|
|
124
125
|
)}
|
|
@@ -155,7 +156,7 @@ const SideNavigationTop: FC<SideNavigationTopProps> = SideNavigationTopElement;
|
|
|
155
156
|
|
|
156
157
|
/** Side Navigation menu item */
|
|
157
158
|
const SideNavigationGroupItem: FC<
|
|
158
|
-
|
|
159
|
+
NavigationItemData &
|
|
159
160
|
SideNavigationExpandedProps &
|
|
160
161
|
NavigationComponentProps & {
|
|
161
162
|
onExpandedChange: undefined | ((expanded: SideNavigationExpandedState) => void);
|
|
@@ -178,7 +179,7 @@ const SideNavigationGroupItem: FC<
|
|
|
178
179
|
[props.id, props.expanded, isSubmenuExpanded, onExpandedChange]
|
|
179
180
|
);
|
|
180
181
|
|
|
181
|
-
const tag = getSubmenuGroupTag(props.submenu, props.tag);
|
|
182
|
+
const tag = getSubmenuGroupTag(props.submenu, getCounterTag(props.counter, props.tag));
|
|
182
183
|
const context = useContext(SideNavigationContext);
|
|
183
184
|
|
|
184
185
|
return props.expanded?.bar ? (
|
|
@@ -226,7 +227,7 @@ const SideNavigationGroupItem: FC<
|
|
|
226
227
|
</Popover>
|
|
227
228
|
);
|
|
228
229
|
};
|
|
229
|
-
const SideNavigationGroupContent: FC<
|
|
230
|
+
const SideNavigationGroupContent: FC<NavigationSubmenuData & NavigationComponentProps> = ({
|
|
230
231
|
groups,
|
|
231
232
|
navigationComponent,
|
|
232
233
|
}) => {
|
|
@@ -258,8 +259,9 @@ const SideNavigationGroupContent: FC<HeaderNavigationItemSubmenu & NavigationCom
|
|
|
258
259
|
</Fragment>
|
|
259
260
|
);
|
|
260
261
|
};
|
|
261
|
-
const SideNavigationGroupLink: FC<
|
|
262
|
+
const SideNavigationGroupLink: FC<NavigationSubmenuItemData & NavigationComponentProps> = ({
|
|
262
263
|
id,
|
|
264
|
+
counter,
|
|
263
265
|
tag,
|
|
264
266
|
title,
|
|
265
267
|
to,
|
|
@@ -279,7 +281,7 @@ const SideNavigationGroupLink: FC<HeaderNavigationItemSubmenuLink & NavigationCo
|
|
|
279
281
|
activeClassName={Styles.submenuLinkActive}
|
|
280
282
|
>
|
|
281
283
|
<span>{title}</span>
|
|
282
|
-
|
|
284
|
+
<CounterTag data={getCounterTag(counter, tag)} className={Styles.submenuLinkCounter} />
|
|
283
285
|
</NavigationComponent>
|
|
284
286
|
);
|
|
285
287
|
};
|
|
@@ -299,7 +301,10 @@ const SideNavigationOptionsToggle: FC<{
|
|
|
299
301
|
}
|
|
300
302
|
>
|
|
301
303
|
<div className={Styles.optionsIconWrapper}>
|
|
302
|
-
<Icon
|
|
304
|
+
<Icon
|
|
305
|
+
className={Styles.optionsIcon}
|
|
306
|
+
svg={expanded?.bar ? SvgCollapse : SvgExpand}
|
|
307
|
+
/>
|
|
303
308
|
</div>
|
|
304
309
|
|
|
305
310
|
{!!expanded?.bar && <span className={Styles.optionsItemText}>Collapse Menu</span>}
|
package/src/components/links.tsx
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { FC, useContext } from 'react';
|
|
2
|
-
import { HeaderNavigationLinkProps, HeaderNavigationTriggerProps } from '../utils/navigation';
|
|
3
2
|
import { NavigationLegacyContext } from '../utils/navigation-context';
|
|
3
|
+
import {
|
|
4
|
+
HeaderNavigationLinkProps,
|
|
5
|
+
HeaderNavigationTriggerProps,
|
|
6
|
+
} from '../utils/navigation-legacy';
|
|
4
7
|
import {
|
|
5
8
|
HeaderNavigationLink as HeaderNavigationLinkLegacy,
|
|
6
9
|
HeaderNavigationTrigger as HeaderNavigationTriggerLegacy,
|
|
@@ -112,11 +112,14 @@ export const ProfileDropdownWithHintPopup = () => (
|
|
|
112
112
|
onOpen={() => log('open profile dropdown')}
|
|
113
113
|
onClose={() => log('close profile dropdown')}
|
|
114
114
|
>
|
|
115
|
-
<ProfileDropdown.Link id="first" to="https://google.com">
|
|
115
|
+
<ProfileDropdown.Link id="first" to="https://google.com" counter={12}>
|
|
116
116
|
first item
|
|
117
117
|
</ProfileDropdown.Link>
|
|
118
118
|
<ProfileDropdown.Divider />
|
|
119
119
|
<ProfileDropdown.Section id="second">second item</ProfileDropdown.Section>
|
|
120
|
+
<ProfileDropdown.Link id="third" to="https://google.com" tag={{ value: 1 }}>
|
|
121
|
+
third item
|
|
122
|
+
</ProfileDropdown.Link>
|
|
120
123
|
</ProfileDropdown>
|
|
121
124
|
);
|
|
122
125
|
|
|
@@ -18,11 +18,13 @@ import {
|
|
|
18
18
|
useState,
|
|
19
19
|
} from 'react';
|
|
20
20
|
|
|
21
|
+
import { CounterTagData, CounterTagValue } from '../../utils/counter-tag';
|
|
21
22
|
import {
|
|
22
23
|
NavigationComponentContext,
|
|
23
24
|
NavigationLegacyContext,
|
|
24
25
|
} from '../../utils/navigation-context';
|
|
25
|
-
import {
|
|
26
|
+
import { getCounterTag } from '../../utils/side-nav';
|
|
27
|
+
import { CounterTag } from '../counter-tag';
|
|
26
28
|
import * as Styles from './profile-dropdown.module.less';
|
|
27
29
|
import { ProfileLogo } from './profile-icon';
|
|
28
30
|
|
|
@@ -192,7 +194,8 @@ export interface ProfileDropdownLinkPropsStrict {
|
|
|
192
194
|
external?: boolean;
|
|
193
195
|
target?: HTMLAttributeAnchorTarget;
|
|
194
196
|
to?: string;
|
|
195
|
-
tag?:
|
|
197
|
+
tag?: CounterTagData;
|
|
198
|
+
counter?: CounterTagValue;
|
|
196
199
|
onClick?: () => void;
|
|
197
200
|
}
|
|
198
201
|
|
|
@@ -205,6 +208,7 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
|
|
|
205
208
|
className,
|
|
206
209
|
external,
|
|
207
210
|
id,
|
|
211
|
+
counter,
|
|
208
212
|
tag,
|
|
209
213
|
target,
|
|
210
214
|
to,
|
|
@@ -220,7 +224,10 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
|
|
|
220
224
|
|
|
221
225
|
const isExternalLink = external ?? to?.startsWith('http');
|
|
222
226
|
|
|
223
|
-
const tagElement = useMemo(
|
|
227
|
+
const tagElement = useMemo(
|
|
228
|
+
() => <CounterTag data={getCounterTag(counter, tag)} className={Styles.counter} />,
|
|
229
|
+
[counter, tag]
|
|
230
|
+
);
|
|
224
231
|
|
|
225
232
|
return isExternalLink ? (
|
|
226
233
|
<a
|
package/src/index.ts
CHANGED
|
@@ -7,4 +7,9 @@ export * from './components/counter-tag';
|
|
|
7
7
|
export * from './components/left-navigation';
|
|
8
8
|
export * from './components/links';
|
|
9
9
|
export * from './utils/navigation';
|
|
10
|
-
export {
|
|
10
|
+
export {
|
|
11
|
+
NavigationComponentContext,
|
|
12
|
+
NavLinkComponentPropsStrict,
|
|
13
|
+
NavLinkComponentProps,
|
|
14
|
+
} from './utils/navigation-context';
|
|
15
|
+
export * from './utils/navigation-legacy';
|
package/src/test/data.tsx
CHANGED
|
@@ -38,13 +38,9 @@ import { Fragment, forwardRef, useState } from 'react';
|
|
|
38
38
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
39
39
|
import { MemoryRouter, Redirect, Switch, useHistory, useLocation } from 'react-router-dom';
|
|
40
40
|
import { HeaderNavigationTrigger } from '../components/links';
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
HeaderNavigationItemSubmenuLink,
|
|
45
|
-
NavLinkComponentProps,
|
|
46
|
-
} from '../utils/navigation';
|
|
47
|
-
import { NavigationComponentContext } from '../utils/navigation-context';
|
|
41
|
+
import { NavigationSubmenuGroupData, NavigationSubmenuItemData } from '../utils/navigation';
|
|
42
|
+
import { NavLinkComponentProps, NavigationComponentContext } from '../utils/navigation-context';
|
|
43
|
+
import { HeaderNavigationItemData } from '../utils/navigation-legacy';
|
|
48
44
|
import * as Styles from './data-stories.module.less';
|
|
49
45
|
|
|
50
46
|
export const NavLinkMock = forwardRef<any, NavLinkComponentProps>(
|
|
@@ -145,8 +141,8 @@ const getItem = (
|
|
|
145
141
|
|
|
146
142
|
const getSubItem = (
|
|
147
143
|
id: string,
|
|
148
|
-
data: Partial<
|
|
149
|
-
):
|
|
144
|
+
data: Partial<NavigationSubmenuItemData>
|
|
145
|
+
): NavigationSubmenuItemData => ({
|
|
150
146
|
id,
|
|
151
147
|
to: id,
|
|
152
148
|
title: id[0].toUpperCase() + id.substring(1),
|
|
@@ -155,8 +151,8 @@ const getSubItem = (
|
|
|
155
151
|
|
|
156
152
|
const getGroup = (
|
|
157
153
|
title: string,
|
|
158
|
-
links:
|
|
159
|
-
):
|
|
154
|
+
links: NavigationSubmenuItemData[]
|
|
155
|
+
): NavigationSubmenuGroupData => ({
|
|
160
156
|
title,
|
|
161
157
|
links,
|
|
162
158
|
});
|
|
@@ -176,7 +172,7 @@ export const items = {
|
|
|
176
172
|
iconName: 'local_phone',
|
|
177
173
|
icon: SvgCalls,
|
|
178
174
|
iconActive: SvgCallsActive,
|
|
179
|
-
|
|
175
|
+
counter: 12,
|
|
180
176
|
}),
|
|
181
177
|
dashboard: getItem('dashboard', {
|
|
182
178
|
iconName: 'odometer',
|
|
@@ -187,7 +183,7 @@ export const items = {
|
|
|
187
183
|
iconName: 'location_disabled',
|
|
188
184
|
icon: SvgDispatch,
|
|
189
185
|
iconActive: SvgDispatchActive,
|
|
190
|
-
tag:
|
|
186
|
+
tag: { value: 3 },
|
|
191
187
|
}),
|
|
192
188
|
fleet: getItem('fleet', {
|
|
193
189
|
iconName: 'fleet-pro',
|
|
@@ -241,7 +237,7 @@ export const items = {
|
|
|
241
237
|
iconName: 'assignment',
|
|
242
238
|
icon: SvgAccounting,
|
|
243
239
|
iconActive: SvgAccountingActive,
|
|
244
|
-
|
|
240
|
+
counter: true,
|
|
245
241
|
}),
|
|
246
242
|
accountingWithSubmenu: getItem('accounting', {
|
|
247
243
|
iconName: 'assignment',
|
|
@@ -251,9 +247,12 @@ export const items = {
|
|
|
251
247
|
groups: [
|
|
252
248
|
getGroup('Accounts Receivable', [
|
|
253
249
|
getSubItem('ar', { title: 'AR Management' }),
|
|
254
|
-
getSubItem('export', {
|
|
255
|
-
|
|
256
|
-
|
|
250
|
+
getSubItem('export', {
|
|
251
|
+
title: 'Batch/Export Transactions',
|
|
252
|
+
counter: true,
|
|
253
|
+
}),
|
|
254
|
+
getSubItem('invoices', { title: 'Invoices', counter: 3 }),
|
|
255
|
+
getSubItem('payments', { title: 'Customer Payments', counter: 2 }),
|
|
257
256
|
getSubItem('deposits', { title: 'Bank Deposits' }),
|
|
258
257
|
]),
|
|
259
258
|
getGroup('Accounts Payable', [getSubItem('bills', { title: 'Bills' })]),
|
|
@@ -307,7 +306,7 @@ export const CallsNavigationTrigger = () => {
|
|
|
307
306
|
<HeaderNavigationTrigger
|
|
308
307
|
id="dialpad"
|
|
309
308
|
iconName="phone"
|
|
310
|
-
|
|
309
|
+
counter={2}
|
|
311
310
|
icon={SvgPhone}
|
|
312
311
|
iconActive={SvgPhoneActive}
|
|
313
312
|
onClick={() => setOpen(!open)}
|
package/src/utils/counter-tag.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
export type CounterTagValue = boolean | number;
|
|
2
2
|
|
|
3
|
-
export interface
|
|
4
|
-
value:
|
|
5
|
-
className?: string;
|
|
3
|
+
export interface CounterTagData {
|
|
4
|
+
value: CounterTagValue;
|
|
6
5
|
}
|
|
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;
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import { FC, createContext } from 'react';
|
|
2
|
-
|
|
1
|
+
import { FC, HTMLAttributeAnchorTarget, ReactNode, createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface NavLinkComponentPropsStrict {
|
|
4
|
+
to: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
activeClassName?: string;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
isActive?: (pathname: string) => boolean;
|
|
10
|
+
target?: HTMLAttributeAnchorTarget;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NavLinkComponentProps extends NavLinkComponentPropsStrict {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
3
16
|
|
|
4
17
|
export const DefaultNavLinkComponent: FC<NavLinkComponentProps> = ({
|
|
5
18
|
children,
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { IconProps } from '@servicetitan/anvil2';
|
|
2
|
+
import { IconPropsStrict } from '@servicetitan/design-system';
|
|
3
|
+
import { FC, HTMLAttributeAnchorTarget } from 'react';
|
|
4
|
+
import { CounterTagData, CounterTagValue } from './counter-tag';
|
|
5
|
+
import { NavigationSubmenuData } from './navigation';
|
|
6
|
+
|
|
7
|
+
export interface HeaderNavigationItemData extends HeaderNavigationItemLinkProps {
|
|
8
|
+
/** link description */
|
|
9
|
+
hint: string;
|
|
10
|
+
|
|
11
|
+
/** flag if the link is not shown (based on FG and/or user permissions) */
|
|
12
|
+
isHidden?: boolean;
|
|
13
|
+
|
|
14
|
+
/** custom className (can be used for mdi icons) */
|
|
15
|
+
iconClassName?: string;
|
|
16
|
+
|
|
17
|
+
/** anvil's icon name of item */
|
|
18
|
+
iconName?: IconPropsStrict['name'];
|
|
19
|
+
|
|
20
|
+
/** svg icon (anvil2) of inactive item */
|
|
21
|
+
icon: IconProps['svg'] | undefined;
|
|
22
|
+
|
|
23
|
+
/** svg icon (anvil2) of active item */
|
|
24
|
+
iconActive: IconProps['svg'] | undefined;
|
|
25
|
+
|
|
26
|
+
/** icon component of item (<svg />) */
|
|
27
|
+
iconComponent?: FC;
|
|
28
|
+
|
|
29
|
+
/** item tag (optional). shown if it is set and true or greater than 0 */
|
|
30
|
+
counter?: CounterTagValue;
|
|
31
|
+
tag?: CounterTagData;
|
|
32
|
+
|
|
33
|
+
/** class name of link item */
|
|
34
|
+
className?: string;
|
|
35
|
+
|
|
36
|
+
/** optional submenu of link item */
|
|
37
|
+
submenu?: NavigationSubmenuData;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface HeaderNavigationItemLinkProps {
|
|
41
|
+
/** link id */
|
|
42
|
+
id: string;
|
|
43
|
+
|
|
44
|
+
/** link href */
|
|
45
|
+
to: string;
|
|
46
|
+
|
|
47
|
+
/** link title */
|
|
48
|
+
title: string;
|
|
49
|
+
|
|
50
|
+
/** callback to return active state. By default, it compares link href with current pathname */
|
|
51
|
+
isActive?: boolean | ((pathname: string) => boolean);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface HeaderNavigationTriggerPropsStrict {
|
|
55
|
+
/** unique identifier */
|
|
56
|
+
id: string;
|
|
57
|
+
/** tooltip text */
|
|
58
|
+
tooltip?: string;
|
|
59
|
+
/** item description */
|
|
60
|
+
hint?: string;
|
|
61
|
+
/** container class name */
|
|
62
|
+
className?: string;
|
|
63
|
+
/** item label */
|
|
64
|
+
label?: string;
|
|
65
|
+
/** label class name */
|
|
66
|
+
labelClassName?: string;
|
|
67
|
+
/** isActive */
|
|
68
|
+
isActive?: boolean;
|
|
69
|
+
/** counter value shown for item */
|
|
70
|
+
counter?: CounterTagValue;
|
|
71
|
+
tag?: CounterTagData;
|
|
72
|
+
/** counter component class name */
|
|
73
|
+
counterClassName?: string;
|
|
74
|
+
/** icon component class name */
|
|
75
|
+
iconClassName?: string;
|
|
76
|
+
/** IconComponent custom icon component */
|
|
77
|
+
iconComponent?: FC;
|
|
78
|
+
/** iconName name of anvil icon */
|
|
79
|
+
iconName?: IconPropsStrict['name'];
|
|
80
|
+
/** svg icon (anvil2) of inactive item */
|
|
81
|
+
icon: IconProps['svg'] | undefined;
|
|
82
|
+
/** svg icon (anvil2) of active item */
|
|
83
|
+
iconActive: IconProps['svg'] | undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface HeaderNavigationTriggerProps extends HeaderNavigationTriggerPropsStrict {
|
|
87
|
+
/** unstrict props */
|
|
88
|
+
[key: string]: any;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface HeaderNavigationLinkPropsStrict
|
|
92
|
+
extends Omit<HeaderNavigationTriggerPropsStrict, 'isActive'> {
|
|
93
|
+
/** link href */
|
|
94
|
+
to: string;
|
|
95
|
+
/** isActive */
|
|
96
|
+
isActive?: boolean | ((pathname: string) => boolean);
|
|
97
|
+
/** link html target */
|
|
98
|
+
target?: HTMLAttributeAnchorTarget;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface HeaderNavigationLinkProps extends HeaderNavigationLinkPropsStrict {
|
|
102
|
+
/** unstrict props */
|
|
103
|
+
[key: string]: any;
|
|
104
|
+
}
|
package/src/utils/navigation.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import { IconProps } from '@servicetitan/anvil2';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { CounterTagPropsType } from '../components/counter-tag';
|
|
5
|
-
|
|
6
|
-
export interface HeaderNavigationItemData extends HeaderNavigationItemLinkProps {
|
|
7
|
-
/** link description */
|
|
8
|
-
hint: string;
|
|
2
|
+
import { FC } from 'react';
|
|
3
|
+
import { CounterTagData, CounterTagValue } from './counter-tag';
|
|
9
4
|
|
|
5
|
+
export interface NavigationItemData extends NavigationLinkData {
|
|
10
6
|
/** flag if the link is not shown (based on FG and/or user permissions) */
|
|
11
7
|
isHidden?: boolean;
|
|
12
8
|
|
|
13
9
|
/** custom className (can be used for mdi icons) */
|
|
14
10
|
iconClassName?: string;
|
|
15
11
|
|
|
16
|
-
/** anvil's icon name of item */
|
|
17
|
-
iconName?: IconPropsStrict['name'];
|
|
18
|
-
|
|
19
12
|
/** svg icon (anvil2) of inactive item */
|
|
20
13
|
icon: IconProps['svg'] | undefined;
|
|
21
14
|
|
|
@@ -26,16 +19,17 @@ export interface HeaderNavigationItemData extends HeaderNavigationItemLinkProps
|
|
|
26
19
|
iconComponent?: FC;
|
|
27
20
|
|
|
28
21
|
/** item tag (optional). shown if it is set and true or greater than 0 */
|
|
29
|
-
|
|
22
|
+
counter?: CounterTagValue;
|
|
23
|
+
tag?: CounterTagData;
|
|
30
24
|
|
|
31
25
|
/** class name of link item */
|
|
32
26
|
className?: string;
|
|
33
27
|
|
|
34
28
|
/** optional submenu of link item */
|
|
35
|
-
submenu?:
|
|
29
|
+
submenu?: NavigationSubmenuData;
|
|
36
30
|
}
|
|
37
31
|
|
|
38
|
-
export interface
|
|
32
|
+
export interface NavigationLinkData {
|
|
39
33
|
/** link id */
|
|
40
34
|
id: string;
|
|
41
35
|
|
|
@@ -49,85 +43,21 @@ export interface HeaderNavigationItemLinkProps {
|
|
|
49
43
|
isActive?: boolean | ((pathname: string) => boolean);
|
|
50
44
|
}
|
|
51
45
|
|
|
52
|
-
export interface
|
|
46
|
+
export interface NavigationSubmenuData {
|
|
53
47
|
/** submenu groups */
|
|
54
|
-
groups:
|
|
48
|
+
groups: NavigationSubmenuGroupData[];
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
export interface
|
|
58
|
-
/** item tag (optional). shown if it is set and true or greater than 0 */
|
|
59
|
-
|
|
51
|
+
export interface NavigationSubmenuItemData extends NavigationLinkData {
|
|
52
|
+
/** item tag (optional) value. shown if it is set and true or greater than 0 */
|
|
53
|
+
counter?: CounterTagValue;
|
|
54
|
+
tag?: CounterTagData;
|
|
60
55
|
}
|
|
61
56
|
|
|
62
|
-
export interface
|
|
57
|
+
export interface NavigationSubmenuGroupData {
|
|
63
58
|
/** submenu group title */
|
|
64
59
|
title: string;
|
|
65
60
|
|
|
66
61
|
/** submenu group links */
|
|
67
|
-
links:
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface NavLinkComponentPropsStrict {
|
|
71
|
-
to: string;
|
|
72
|
-
title?: string;
|
|
73
|
-
className?: string;
|
|
74
|
-
activeClassName?: string;
|
|
75
|
-
children: ReactNode;
|
|
76
|
-
isActive?: (pathname: string) => boolean;
|
|
77
|
-
target?: HTMLAttributeAnchorTarget;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface NavLinkComponentProps extends NavLinkComponentPropsStrict {
|
|
81
|
-
[key: string]: any;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface HeaderNavigationTriggerPropsStrict {
|
|
85
|
-
/** unique identifier */
|
|
86
|
-
id: string;
|
|
87
|
-
/** tooltip text */
|
|
88
|
-
tooltip?: string;
|
|
89
|
-
/** item description */
|
|
90
|
-
hint?: string;
|
|
91
|
-
/** container class name */
|
|
92
|
-
className?: string;
|
|
93
|
-
/** item label */
|
|
94
|
-
label?: string;
|
|
95
|
-
/** label class name */
|
|
96
|
-
labelClassName?: string;
|
|
97
|
-
/** isActive */
|
|
98
|
-
isActive?: boolean;
|
|
99
|
-
/** counter tag shown for item */
|
|
100
|
-
tag?: CounterTagPropsType;
|
|
101
|
-
/** counter component class name */
|
|
102
|
-
counterClassName?: string;
|
|
103
|
-
/** icon component class name */
|
|
104
|
-
iconClassName?: string;
|
|
105
|
-
/** IconComponent custom icon component */
|
|
106
|
-
iconComponent?: FC;
|
|
107
|
-
/** iconName name of anvil icon */
|
|
108
|
-
iconName?: IconPropsStrict['name'];
|
|
109
|
-
/** svg icon (anvil2) of inactive item */
|
|
110
|
-
icon: IconProps['svg'] | undefined;
|
|
111
|
-
/** svg icon (anvil2) of active item */
|
|
112
|
-
iconActive: IconProps['svg'] | undefined;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export interface HeaderNavigationTriggerProps extends HeaderNavigationTriggerPropsStrict {
|
|
116
|
-
/** unstrict props */
|
|
117
|
-
[key: string]: any;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface HeaderNavigationLinkPropsStrict
|
|
121
|
-
extends Omit<HeaderNavigationTriggerPropsStrict, 'isActive'> {
|
|
122
|
-
/** link href */
|
|
123
|
-
to: string;
|
|
124
|
-
/** isActive */
|
|
125
|
-
isActive?: boolean | ((pathname: string) => boolean);
|
|
126
|
-
/** link html target */
|
|
127
|
-
target?: HTMLAttributeAnchorTarget;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface HeaderNavigationLinkProps extends HeaderNavigationLinkPropsStrict {
|
|
131
|
-
/** unstrict props */
|
|
132
|
-
[key: string]: any;
|
|
62
|
+
links: NavigationSubmenuItemData[];
|
|
133
63
|
}
|
package/src/utils/side-nav.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { CounterTagProps } from '../components/counter-tag';
|
|
2
|
+
import { CounterTagData, CounterTagValue } from './counter-tag';
|
|
3
|
+
import { NavigationSubmenuData } from './navigation';
|
|
3
4
|
|
|
4
5
|
export function getSubmenuGroupTag(
|
|
5
|
-
submenu:
|
|
6
|
-
defaultTag:
|
|
7
|
-
):
|
|
6
|
+
submenu: NavigationSubmenuData | undefined,
|
|
7
|
+
defaultTag: CounterTagProps | undefined
|
|
8
|
+
): CounterTagProps | undefined {
|
|
8
9
|
if (!submenu) {
|
|
9
10
|
return defaultTag;
|
|
10
11
|
}
|
|
@@ -13,9 +14,7 @@ export function getSubmenuGroupTag(
|
|
|
13
14
|
|
|
14
15
|
for (const group of submenu.groups) {
|
|
15
16
|
for (const link of group.links) {
|
|
16
|
-
const ltv: number | boolean | undefined =
|
|
17
|
-
? link.tag.value
|
|
18
|
-
: link.tag;
|
|
17
|
+
const ltv: number | boolean | undefined = link.counter;
|
|
19
18
|
|
|
20
19
|
if (ltv) {
|
|
21
20
|
if (typeof ltv === 'number') {
|
|
@@ -30,5 +29,14 @@ export function getSubmenuGroupTag(
|
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
return tagValue
|
|
32
|
+
return tagValue ? getCounterTag(tagValue) : defaultTag;
|
|
34
33
|
}
|
|
34
|
+
|
|
35
|
+
export const getCounterTag = (
|
|
36
|
+
counter: CounterTagValue | undefined,
|
|
37
|
+
tag?: CounterTagData | undefined
|
|
38
|
+
): CounterTagProps | undefined => {
|
|
39
|
+
const value = counter ?? tag?.value;
|
|
40
|
+
|
|
41
|
+
return value ? { value, className: '' } : undefined;
|
|
42
|
+
};
|