@servicetitan/navigation 10.7.0 → 11.0.0-canary.237.0a4df1d.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 (162) hide show
  1. package/dist/components/badge-tag.d.ts +1 -1
  2. package/dist/components/badge-tag.d.ts.map +1 -1
  3. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
  4. package/dist/components/header-navigation/header-navigation-extra.stories.js +5 -5
  5. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
  6. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-links.js +2 -2
  8. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  9. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
  10. package/dist/components/header-navigation/header-navigation-stacked.stories.js +1 -1
  11. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
  12. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  13. package/dist/components/header-navigation/header-navigation.stories.js +2 -2
  14. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  15. package/dist/components/header-navigation/with-tooltip.d.ts +1 -1
  16. package/dist/components/header-navigation/with-tooltip.d.ts.map +1 -1
  17. package/dist/components/left-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
  18. package/dist/components/left-navigation/header-navigation-tiny.stories.js +2 -2
  19. package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
  20. package/dist/components/links.d.ts.map +1 -1
  21. package/dist/components/links.js +7 -7
  22. package/dist/components/links.js.map +1 -1
  23. package/dist/components/logo/logo-company-title.d.ts +1 -0
  24. package/dist/components/logo/logo-company-title.d.ts.map +1 -1
  25. package/dist/components/logo/logo-company-title.js +2 -2
  26. package/dist/components/logo/logo-company-title.js.map +1 -1
  27. package/dist/components/logo/logo-titan-text.d.ts +1 -1
  28. package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
  29. package/dist/components/profile-dropdown/profile-dropdown.d.ts +17 -9
  30. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  31. package/dist/components/profile-dropdown/profile-dropdown.js +11 -9
  32. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  33. package/dist/components/profile-dropdown/profile-dropdown.module.less +24 -6
  34. package/dist/components/profile-dropdown/profile-dropdown.stories.js +2 -2
  35. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  36. package/dist/components/titan-layout/index.d.ts +6 -0
  37. package/dist/components/titan-layout/index.d.ts.map +1 -0
  38. package/dist/components/titan-layout/index.js +6 -0
  39. package/dist/components/titan-layout/index.js.map +1 -0
  40. package/dist/components/titan-layout/interface-internal.d.ts +6 -0
  41. package/dist/components/titan-layout/interface-internal.d.ts.map +1 -0
  42. package/dist/components/titan-layout/interface-internal.js +2 -0
  43. package/dist/components/titan-layout/interface-internal.js.map +1 -0
  44. package/dist/components/titan-layout/interface.d.ts +21 -0
  45. package/dist/components/titan-layout/interface.d.ts.map +1 -0
  46. package/dist/components/titan-layout/interface.js +2 -0
  47. package/dist/components/titan-layout/interface.js.map +1 -0
  48. package/dist/components/titan-layout/layout-context.d.ts +20 -0
  49. package/dist/components/titan-layout/layout-context.d.ts.map +1 -0
  50. package/dist/components/titan-layout/layout-context.js +12 -0
  51. package/dist/components/titan-layout/layout-context.js.map +1 -0
  52. package/dist/components/titan-layout/layout-header-links.d.ts +7 -0
  53. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -0
  54. package/dist/components/titan-layout/layout-header-links.js +32 -0
  55. package/dist/components/titan-layout/layout-header-links.js.map +1 -0
  56. package/dist/components/titan-layout/layout-header.d.ts +22 -0
  57. package/dist/components/titan-layout/layout-header.d.ts.map +1 -0
  58. package/dist/components/titan-layout/layout-header.js +10 -0
  59. package/dist/components/titan-layout/layout-header.js.map +1 -0
  60. package/dist/components/titan-layout/layout-header.module.less +193 -0
  61. package/dist/components/titan-layout/layout-logo.d.ts +12 -0
  62. package/dist/components/titan-layout/layout-logo.d.ts.map +1 -0
  63. package/dist/components/titan-layout/layout-logo.js +16 -0
  64. package/dist/components/titan-layout/layout-logo.js.map +1 -0
  65. package/dist/components/titan-layout/layout-logo.stories.d.ts +13 -0
  66. package/dist/components/titan-layout/layout-logo.stories.d.ts.map +1 -0
  67. package/dist/components/titan-layout/layout-logo.stories.js +17 -0
  68. package/dist/components/titan-layout/layout-logo.stories.js.map +1 -0
  69. package/dist/components/titan-layout/layout-profile.d.ts +9 -0
  70. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -0
  71. package/dist/components/titan-layout/layout-profile.js +72 -0
  72. package/dist/components/titan-layout/layout-profile.js.map +1 -0
  73. package/dist/components/titan-layout/layout-profile.stories.d.ts +13 -0
  74. package/dist/components/titan-layout/layout-profile.stories.d.ts.map +1 -0
  75. package/dist/components/titan-layout/layout-profile.stories.js +13 -0
  76. package/dist/components/titan-layout/layout-profile.stories.js.map +1 -0
  77. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +46 -0
  78. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -0
  79. package/dist/components/titan-layout/layout-sidebar-links-internal.js +61 -0
  80. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -0
  81. package/dist/components/titan-layout/layout-sidebar-links.d.ts +6 -0
  82. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -0
  83. package/dist/components/titan-layout/layout-sidebar-links.js +28 -0
  84. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -0
  85. package/dist/components/titan-layout/layout-sidebar.d.ts +19 -0
  86. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -0
  87. package/dist/components/titan-layout/layout-sidebar.js +67 -0
  88. package/dist/components/titan-layout/layout-sidebar.js.map +1 -0
  89. package/dist/components/titan-layout/layout-sidebar.module.less +536 -0
  90. package/dist/components/titan-layout/notifications-context.d.ts +13 -0
  91. package/dist/components/titan-layout/notifications-context.d.ts.map +1 -0
  92. package/dist/components/titan-layout/notifications-context.js +23 -0
  93. package/dist/components/titan-layout/notifications-context.js.map +1 -0
  94. package/dist/components/titan-layout/titan-layout.d.ts +40 -0
  95. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
  96. package/dist/components/titan-layout/titan-layout.js +192 -0
  97. package/dist/components/titan-layout/titan-layout.js.map +1 -0
  98. package/dist/components/titan-layout/titan-layout.module.less +106 -0
  99. package/dist/components/titan-layout/titan-layout.stories.d.ts +22 -0
  100. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
  101. package/dist/components/titan-layout/titan-layout.stories.js +83 -0
  102. package/dist/components/titan-layout/titan-layout.stories.js.map +1 -0
  103. package/dist/components/titan-layout/with-tooltip.d.ts +4 -0
  104. package/dist/components/titan-layout/with-tooltip.d.ts.map +1 -0
  105. package/dist/components/titan-layout/with-tooltip.js +4 -0
  106. package/dist/components/titan-layout/with-tooltip.js.map +1 -0
  107. package/dist/index.d.ts +2 -1
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +2 -1
  110. package/dist/index.js.map +1 -1
  111. package/dist/test/data.d.ts +4 -1
  112. package/dist/test/data.d.ts.map +1 -1
  113. package/dist/test/data.js +5 -6
  114. package/dist/test/data.js.map +1 -1
  115. package/dist/utils/navigation-legacy.d.ts +3 -1
  116. package/dist/utils/navigation-legacy.d.ts.map +1 -1
  117. package/dist/utils/use-breakpoint.d.ts +8 -0
  118. package/dist/utils/use-breakpoint.d.ts.map +1 -0
  119. package/dist/utils/use-breakpoint.js +14 -0
  120. package/dist/utils/use-breakpoint.js.map +1 -0
  121. package/package.json +5 -6
  122. package/src/components/badge-tag.tsx +1 -1
  123. package/src/components/header-navigation/header-navigation-extra.stories.tsx +7 -0
  124. package/src/components/header-navigation/header-navigation-links.tsx +2 -0
  125. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +5 -1
  126. package/src/components/header-navigation/header-navigation.stories.tsx +6 -1
  127. package/src/components/left-navigation/header-navigation-tiny.stories.tsx +8 -2
  128. package/src/components/left-navigation/side-navigation-links.tsx +1 -1
  129. package/src/components/links.tsx +33 -13
  130. package/src/components/logo/logo-company-title.tsx +8 -6
  131. package/src/components/logo/logo-titan-text.tsx +1 -1
  132. package/src/components/profile-dropdown/profile-dropdown.module.less +24 -6
  133. package/src/components/profile-dropdown/profile-dropdown.module.less.d.ts +2 -0
  134. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -4
  135. package/src/components/profile-dropdown/profile-dropdown.tsx +87 -55
  136. package/src/components/titan-layout/index.ts +5 -0
  137. package/src/components/titan-layout/interface-internal.ts +6 -0
  138. package/src/components/titan-layout/interface.ts +26 -0
  139. package/src/components/titan-layout/layout-context.tsx +30 -0
  140. package/src/components/titan-layout/layout-header-links.tsx +145 -0
  141. package/src/components/titan-layout/layout-header.module.less +193 -0
  142. package/src/components/titan-layout/layout-header.module.less.d.ts +18 -0
  143. package/src/components/titan-layout/layout-header.tsx +97 -0
  144. package/src/components/titan-layout/layout-logo.stories.tsx +31 -0
  145. package/src/components/titan-layout/layout-logo.tsx +64 -0
  146. package/src/components/titan-layout/layout-profile.stories.tsx +46 -0
  147. package/src/components/titan-layout/layout-profile.tsx +180 -0
  148. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +278 -0
  149. package/src/components/titan-layout/layout-sidebar-links.tsx +72 -0
  150. package/src/components/titan-layout/layout-sidebar.module.less +536 -0
  151. package/src/components/titan-layout/layout-sidebar.module.less.d.ts +49 -0
  152. package/src/components/titan-layout/layout-sidebar.tsx +304 -0
  153. package/src/components/titan-layout/notifications-context.tsx +44 -0
  154. package/src/components/titan-layout/titan-layout.module.less +106 -0
  155. package/src/components/titan-layout/titan-layout.module.less.d.ts +16 -0
  156. package/src/components/titan-layout/titan-layout.stories.tsx +346 -0
  157. package/src/components/titan-layout/titan-layout.tsx +457 -0
  158. package/src/components/titan-layout/with-tooltip.tsx +16 -0
  159. package/src/index.ts +2 -1
  160. package/src/test/data.tsx +5 -5
  161. package/src/utils/navigation-legacy.ts +3 -1
  162. package/src/utils/use-breakpoint.ts +21 -0
@@ -0,0 +1,304 @@
1
+ import { Icon, Popover, Text, ThemeProvider } from '@servicetitan/anvil2';
2
+ import SvgClose from '@servicetitan/anvil2/assets/icons/material/round/close.svg';
3
+ import SvgCollapse from '@servicetitan/anvil2/assets/icons/st/gnav_menu_collapse.svg';
4
+ import SvgExpand from '@servicetitan/anvil2/assets/icons/st/gnav_menu_expand.svg';
5
+ import classNames from 'classnames';
6
+ import {
7
+ Children,
8
+ FC,
9
+ Fragment,
10
+ MouseEvent,
11
+ ReactElement,
12
+ isValidElement,
13
+ useCallback,
14
+ } from 'react';
15
+ import { NavigationItemData, NavigationSubmenuData } from '../../utils/navigation';
16
+ import { NavLinkComponentProps } from '../../utils/navigation-context';
17
+ import { getCounterTag, getSubmenuGroupTag } from '../../utils/side-nav';
18
+ import { NavigationComponentProps } from './interface-internal';
19
+ import { LayoutPlacementContext, useTitanLayoutContext } from './layout-context';
20
+ import {
21
+ InternalSideNavigationGroup,
22
+ InternalSideNavigationGroupLink,
23
+ InternalSideNavigationLink,
24
+ } from './layout-sidebar-links-internal';
25
+ import * as Styles from './layout-sidebar.module.less';
26
+
27
+ import { withTooltip } from './with-tooltip';
28
+
29
+ export interface LayoutSidebarProps {
30
+ className?: string;
31
+ top?: ReactElement[];
32
+ bottom?: ReactElement;
33
+ mainItems?: NavigationItemData[];
34
+ barExpanded: boolean;
35
+ submenuExpanded: string | undefined;
36
+ drawerOpened: boolean;
37
+ mobile: boolean;
38
+ navigationComponent: FC<NavLinkComponentProps>;
39
+ onBarExpandChange(expanded: boolean): void;
40
+ onDrawerOpenChange(expanded: boolean): void;
41
+ onSubmenuExpandChange(id: string, expanded: boolean): void;
42
+ }
43
+
44
+ export const LayoutSidebar: FC<LayoutSidebarProps> = ({
45
+ className,
46
+ mobile,
47
+ barExpanded,
48
+ submenuExpanded,
49
+ drawerOpened,
50
+ onBarExpandChange,
51
+ onSubmenuExpandChange,
52
+ onDrawerOpenChange,
53
+ mainItems,
54
+ top,
55
+ bottom,
56
+ navigationComponent,
57
+ }) => {
58
+ const closeDrawer = () => {
59
+ if (mobile) {
60
+ onDrawerOpenChange?.(false);
61
+ }
62
+ };
63
+
64
+ return (
65
+ <LayoutPlacementContext.Provider value="side">
66
+ {mobile && drawerOpened && (
67
+ <div className={Styles.navDrawerBackdrop} onClick={closeDrawer} />
68
+ )}
69
+ <div
70
+ className={classNames(
71
+ Styles.nav,
72
+ mobile && Styles.navDrawer,
73
+ mobile && drawerOpened && Styles.navDrawerOpened,
74
+ !mobile && (barExpanded ? Styles.navWide : Styles.navSlim),
75
+ className
76
+ )}
77
+ data-cy="side-navigation"
78
+ onClick={closeDrawer}
79
+ >
80
+ <ThemeProvider mode="dark" className={Styles.navMain}>
81
+ {mobile && (
82
+ <div className={Styles.navCloseWrapper}>
83
+ <div
84
+ className={Styles.navClose}
85
+ onClick={() => onBarExpandChange(false)}
86
+ >
87
+ <Icon svg={SvgClose} size="large" />
88
+ </div>
89
+ </div>
90
+ )}
91
+ {!!top?.length && <SidebarTop>{top}</SidebarTop>}
92
+
93
+ <div data-cy="navigation-items">
94
+ {mainItems?.map(item =>
95
+ item.submenu ? (
96
+ <SideNavigationGroupItem
97
+ key={item.id}
98
+ barExpanded={mobile ? drawerOpened : barExpanded}
99
+ submenuExpanded={!!item.id && submenuExpanded === item.id}
100
+ onSubmenuExpand={onSubmenuExpandChange}
101
+ navigationComponent={navigationComponent}
102
+ {...item}
103
+ />
104
+ ) : (
105
+ <InternalSideNavigationLink
106
+ key={item.id}
107
+ submenuExpanded={undefined}
108
+ navigationComponent={navigationComponent}
109
+ {...item}
110
+ tag={getSubmenuGroupTag(
111
+ item.submenu,
112
+ getCounterTag(item.counter, item.tag)
113
+ )}
114
+ />
115
+ )
116
+ )}
117
+ </div>
118
+
119
+ {!!bottom && <SidebarBottom>{bottom}</SidebarBottom>}
120
+ </ThemeProvider>
121
+
122
+ {!mobile && (
123
+ <div className={Styles.navFooter}>
124
+ <div className={Styles.divider} />
125
+ <div className={Styles.toggleWrapper}>
126
+ <SideNavigationOptionsToggle
127
+ appearance={barExpanded ? 'collapse-button' : 'expand'}
128
+ onExpandedChange={() => onBarExpandChange(!barExpanded)}
129
+ />
130
+ </div>
131
+ </div>
132
+ )}
133
+ </div>
134
+ </LayoutPlacementContext.Provider>
135
+ );
136
+ };
137
+ LayoutSidebar.displayName = 'LayoutSidebar';
138
+
139
+ /** Side Navigation options toggle */
140
+ const SideNavigationOptionsToggle: FC<{
141
+ appearance: 'expand' | 'collapse' | 'collapse-button';
142
+ onExpandedChange?(expanded: boolean): void;
143
+ }> = ({ appearance, onExpandedChange }) =>
144
+ withTooltip(
145
+ <div
146
+ data-cy="navigation-left-options"
147
+ data-pendo="navigation-left-options"
148
+ className={classNames(Styles.toggle)}
149
+ onClick={() => onExpandedChange?.(appearance === 'expand')}
150
+ >
151
+ <div className={Styles.toggleContent}>
152
+ <div className={Styles.toggleIconWrapper}>
153
+ <Icon
154
+ className={Styles.toggleIcon}
155
+ svg={appearance === 'expand' ? SvgExpand : SvgCollapse}
156
+ />
157
+ </div>
158
+
159
+ {appearance === 'collapse-button' && (
160
+ <span className={Styles.toggleText}>Collapse Menu</span>
161
+ )}
162
+ </div>
163
+ </div>,
164
+ appearance === 'expand'
165
+ ? 'Expand Menu'
166
+ : appearance === 'collapse'
167
+ ? 'Collapse Menu'
168
+ : undefined,
169
+ 'right'
170
+ );
171
+
172
+ /** Side Navigation menu item */
173
+ const SideNavigationGroupItem: FC<
174
+ NavigationItemData & {
175
+ navigationComponent: FC<NavLinkComponentProps>;
176
+ barExpanded: boolean;
177
+ submenuExpanded: boolean;
178
+ onSubmenuExpand: undefined | ((id: string, expanded: boolean) => void);
179
+ }
180
+ > = ({ onSubmenuExpand, barExpanded, submenuExpanded, ...props }) => {
181
+ const onExpandToggle = useCallback(
182
+ (e: MouseEvent<never>) => {
183
+ e.preventDefault();
184
+ e.stopPropagation();
185
+
186
+ if (props.id) {
187
+ onSubmenuExpand?.(props.id, !submenuExpanded);
188
+ }
189
+ },
190
+ [props.id, submenuExpanded, onSubmenuExpand]
191
+ );
192
+ const {
193
+ sidebar: {
194
+ styles: { popoverContent },
195
+ },
196
+ } = useTitanLayoutContext();
197
+
198
+ const tag = getSubmenuGroupTag(props.submenu, getCounterTag(props.counter, props.tag));
199
+
200
+ return barExpanded ? (
201
+ <InternalSideNavigationGroup
202
+ {...props}
203
+ submenuExpanded={submenuExpanded}
204
+ onExpandToggle={onExpandToggle}
205
+ tag={tag}
206
+ >
207
+ <SideNavigationGroupContent
208
+ groups={props.submenu?.groups ?? []}
209
+ navigationComponent={props.navigationComponent}
210
+ />
211
+ </InternalSideNavigationGroup>
212
+ ) : (
213
+ <Popover placement="right-start" openOnHover delay={500}>
214
+ <Popover.Trigger>
215
+ {(triggerProps: any) => (
216
+ <div {...triggerProps}>
217
+ <InternalSideNavigationLink
218
+ {...props}
219
+ submenuExpanded={undefined}
220
+ tag={tag}
221
+ />
222
+ </div>
223
+ )}
224
+ </Popover.Trigger>
225
+ <Popover.Content style={popoverContent} className="z-global-nav-i">
226
+ <div className={Styles.submenuPopover}>
227
+ <Text
228
+ variant="headline"
229
+ el="h4"
230
+ size="small"
231
+ className="c-white m-b-half-i m-t-1"
232
+ >
233
+ {props.title}
234
+ </Text>
235
+ <SideNavigationGroupContent
236
+ groups={props.submenu?.groups ?? []}
237
+ navigationComponent={props.navigationComponent}
238
+ />
239
+ </div>
240
+ </Popover.Content>
241
+ </Popover>
242
+ );
243
+ };
244
+ const SideNavigationGroupContent: FC<NavigationSubmenuData & NavigationComponentProps> = ({
245
+ groups,
246
+ navigationComponent,
247
+ }) => {
248
+ return (
249
+ <Fragment>
250
+ {groups.reduce((out, group, index) => {
251
+ if (!group.links.length) {
252
+ return out;
253
+ }
254
+
255
+ const title = group.title?.trim() ?? '';
256
+ /* eslint-disable react/no-array-index-key */
257
+ out.push(
258
+ <Text
259
+ key={`:group:${index}:title`}
260
+ variant="eyebrow"
261
+ className={classNames(Styles.submenuGroupHeader, {
262
+ [Styles.submenuGroupHeaderEmpty]: !title,
263
+ })}
264
+ >
265
+ {title}
266
+ </Text>
267
+ );
268
+ out.push(
269
+ ...group.links.map((link, index) => (
270
+ <InternalSideNavigationGroupLink
271
+ key={`:${link.id}:${index}`}
272
+ {...link}
273
+ navigationComponent={navigationComponent}
274
+ />
275
+ ))
276
+ );
277
+ /* eslint-enable react/no-array-index-key */
278
+
279
+ return out;
280
+ }, [] as ReactElement[])}
281
+ </Fragment>
282
+ );
283
+ };
284
+
285
+ function SidebarTop({ children }: any) {
286
+ const list = Children.map(children, child => {
287
+ return child && isValidElement(child) ? child : null;
288
+ });
289
+ return list?.length ? (
290
+ <ThemeProvider mode="dark" className={Styles.navTop} data-cy="navigation-items-top">
291
+ {list}
292
+ <div className={Styles.divider} />
293
+ </ThemeProvider>
294
+ ) : null;
295
+ }
296
+
297
+ function SidebarBottom({ children }: any) {
298
+ return (
299
+ <ThemeProvider mode="dark" className={Styles.navBottom} data-cy="navigation-items-bottom">
300
+ <div className={Styles.divider} />
301
+ {children}
302
+ </ThemeProvider>
303
+ );
304
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ FC,
3
+ PropsWithChildren,
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useRef,
8
+ useState,
9
+ } from 'react';
10
+
11
+ interface NotificationsContextType {
12
+ onNotificationsUpdate: (id: string, hasNotifications: boolean) => void;
13
+ }
14
+
15
+ const NotificationsContext = createContext<NotificationsContextType>({
16
+ onNotificationsUpdate: () => {},
17
+ });
18
+
19
+ export const useNotificationsContext = () => useContext(NotificationsContext);
20
+
21
+ export const useNotificationsState = () => {
22
+ const [hasNotifications, setHasNotifications] = useState(false);
23
+ const items = useRef(new Set<string>());
24
+ const onNotificationsUpdate = useCallback((id: string, hasNotifications: boolean) => {
25
+ if (hasNotifications && !items.current.has(id)) {
26
+ items.current.add(id);
27
+ setHasNotifications(!!items.current.size);
28
+ } else if (!hasNotifications && items.current.has(id)) {
29
+ items.current.delete(id);
30
+ setHasNotifications(!!items.current.size);
31
+ }
32
+ }, []);
33
+
34
+ const NotificationsContextProvider: FC<PropsWithChildren> = useCallback(
35
+ ({ children }) => (
36
+ <NotificationsContext.Provider value={{ onNotificationsUpdate }}>
37
+ {children}
38
+ </NotificationsContext.Provider>
39
+ ),
40
+ [onNotificationsUpdate]
41
+ );
42
+
43
+ return { NotificationsContextProvider, hasNotifications };
44
+ };
@@ -0,0 +1,106 @@
1
+ /* stylelint-disable no-descending-specificity */
2
+ @import (reference) '@servicetitan/tokens/core/tokens.less';
3
+
4
+ @text-color: var(--colorsTextInverted, @color-white);
5
+ @text-color-active: var(--colorsTextPrimarySubdued, @color-blue-300);
6
+ @border-color: var(--colorsTextOnGrey, @color-neutral-200);
7
+ @bg-color: #0f1d26;
8
+ @bg-color-hover: rgba(255, 255, 255, 0.08);
9
+ @bg-color-active: rgba(120, 187, 250, 0.2);
10
+
11
+ .layout-anvil1 {
12
+ height: calc(100vh - var(--nav-offset-top));
13
+ margin-top: var(--nav-offset-top);
14
+
15
+ display: flex;
16
+ flex-direction: column;
17
+
18
+ .side {
19
+ flex-basis: var(--nav-offset-left);
20
+ flex-grow: 0;
21
+ flex-shrink: 0;
22
+ }
23
+
24
+ .content {
25
+ flex-grow: 1;
26
+
27
+ display: flex;
28
+ flex-direction: column;
29
+ overflow: hidden;
30
+ }
31
+ }
32
+
33
+ .layout-anvil2 {
34
+ .content-header {
35
+ position: sticky;
36
+ top: var(--nav-offset-top);
37
+ z-index: 989;
38
+ }
39
+ }
40
+
41
+ .layout-desktop {
42
+ padding-left: var(--nav-offset-left);
43
+
44
+ .side {
45
+ position: fixed;
46
+ top: var(--nav-offset-top);
47
+ bottom: 0;
48
+ left: 0;
49
+ right: 0;
50
+ z-index: @z-index-global-nav;
51
+ }
52
+ }
53
+
54
+ .layout-legacy,
55
+ .layout-anvil2 {
56
+ .top-placeholder {
57
+ height: var(--nav-offset-top);
58
+ }
59
+ }
60
+
61
+ .layout {
62
+ --nav-offset-top: 0px;
63
+ --nav-offset-left: 0px;
64
+
65
+ &.layout-desktop.layout-top {
66
+ --nav-offset-top: 48px;
67
+ }
68
+
69
+ &.layout-mobile.layout-top {
70
+ --nav-offset-top: 72px;
71
+ }
72
+
73
+ &.layout-desktop.layout-nav-slim {
74
+ --nav-offset-left: 64px;
75
+ }
76
+
77
+ &.layout-desktop.layout-nav-wide {
78
+ --nav-offset-left: 212px;
79
+ }
80
+
81
+ .top {
82
+ position: fixed;
83
+ width: 100vw;
84
+ top: 0;
85
+ left: 0;
86
+ z-index: 991;
87
+ }
88
+
89
+ .content-header {
90
+ position: sticky;
91
+ left: 0;
92
+ right: 0;
93
+ }
94
+ }
95
+
96
+ @media print {
97
+ .layout {
98
+ --nav-offset-left: 0px !important;
99
+ --nav-offset-right: 0px !important;
100
+
101
+ .side,
102
+ .top {
103
+ display: none !important;
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,16 @@
1
+ export const __esModule: true;
2
+ export const content: string;
3
+ export const contentHeader: string;
4
+ export const layout: string;
5
+ export const layoutAnvil1: string;
6
+ export const layoutAnvil2: string;
7
+ export const layoutDesktop: string;
8
+ export const layoutLegacy: string;
9
+ export const layoutMobile: string;
10
+ export const layoutNavSlim: string;
11
+ export const layoutNavWide: string;
12
+ export const layoutTop: string;
13
+ export const side: string;
14
+ export const top: string;
15
+ export const topPlaceholder: string;
16
+