@servicetitan/navigation 11.0.0-canary.237.fef17f5.0 → 11.0.0-canary.237.ff793b3.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/badge-tag.d.ts +1 -1
- package/dist/components/badge-tag.d.ts.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.stories.js +1 -1
- package/dist/components/header-navigation/header-navigation.stories.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/logo/logo-titan-text.d.ts +1 -1
- package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.d.ts +10 -7
- package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.js +2 -2
- package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.module.less +2 -0
- package/dist/components/titan-layout/layout-context.js +1 -1
- package/dist/components/titan-layout/layout-context.js.map +1 -1
- package/dist/components/titan-layout/layout-header.d.ts +2 -0
- package/dist/components/titan-layout/layout-header.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-header.js +3 -4
- package/dist/components/titan-layout/layout-header.js.map +1 -1
- package/dist/components/titan-layout/layout-header.module.less +37 -6
- package/dist/components/titan-layout/layout-logo.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-logo.js +2 -1
- package/dist/components/titan-layout/layout-logo.js.map +1 -1
- package/dist/components/titan-layout/layout-profile.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-profile.js +32 -8
- package/dist/components/titan-layout/layout-profile.js.map +1 -1
- package/dist/components/titan-layout/layout-profile.stories.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-profile.stories.js +1 -1
- package/dist/components/titan-layout/layout-profile.stories.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +2 -2
- package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links-internal.js +4 -4
- package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links.js +9 -2
- package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar.d.ts +2 -0
- package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-sidebar.js +6 -4
- package/dist/components/titan-layout/layout-sidebar.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar.module.less +25 -5
- package/dist/components/titan-layout/notifications-context.d.ts +13 -0
- package/dist/components/titan-layout/notifications-context.d.ts.map +1 -0
- package/dist/components/titan-layout/notifications-context.js +23 -0
- package/dist/components/titan-layout/notifications-context.js.map +1 -0
- package/dist/components/titan-layout/titan-layout.d.ts +6 -3
- package/dist/components/titan-layout/titan-layout.d.ts.map +1 -1
- package/dist/components/titan-layout/titan-layout.js +77 -22
- package/dist/components/titan-layout/titan-layout.js.map +1 -1
- package/dist/components/titan-layout/titan-layout.module.less +42 -20
- package/dist/components/titan-layout/titan-layout.stories.d.ts +4 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -1
- package/dist/components/titan-layout/titan-layout.stories.js +15 -7
- package/dist/components/titan-layout/titan-layout.stories.js.map +1 -1
- package/dist/test/data.d.ts +4 -1
- package/dist/test/data.d.ts.map +1 -1
- package/dist/test/data.js +2 -3
- package/dist/test/data.js.map +1 -1
- package/dist/utils/use-breakpoint.d.ts +1 -0
- package/dist/utils/use-breakpoint.d.ts.map +1 -1
- package/dist/utils/use-breakpoint.js +2 -1
- package/dist/utils/use-breakpoint.js.map +1 -1
- package/package.json +2 -2
- package/src/components/badge-tag.tsx +1 -1
- package/src/components/header-navigation/header-navigation-stacked.stories.tsx +1 -1
- package/src/components/header-navigation/header-navigation.stories.tsx +1 -1
- package/src/components/left-navigation/header-navigation-tiny.stories.tsx +2 -2
- package/src/components/logo/logo-titan-text.tsx +1 -1
- package/src/components/profile-dropdown/profile-dropdown.module.less +2 -0
- package/src/components/profile-dropdown/profile-dropdown.tsx +13 -6
- package/src/components/titan-layout/layout-context.tsx +1 -1
- package/src/components/titan-layout/layout-header.module.less +37 -6
- package/src/components/titan-layout/layout-header.tsx +7 -4
- package/src/components/titan-layout/layout-logo.tsx +13 -6
- package/src/components/titan-layout/layout-profile.stories.tsx +10 -1
- package/src/components/titan-layout/layout-profile.tsx +60 -25
- package/src/components/titan-layout/layout-sidebar-links-internal.tsx +18 -5
- package/src/components/titan-layout/layout-sidebar-links.tsx +11 -2
- package/src/components/titan-layout/layout-sidebar.module.less +25 -5
- package/src/components/titan-layout/layout-sidebar.module.less.d.ts +1 -0
- package/src/components/titan-layout/layout-sidebar.tsx +14 -5
- package/src/components/titan-layout/notifications-context.tsx +44 -0
- package/src/components/titan-layout/titan-layout.module.less +42 -20
- package/src/components/titan-layout/titan-layout.module.less.d.ts +2 -1
- package/src/components/titan-layout/titan-layout.stories.tsx +113 -6
- package/src/components/titan-layout/titan-layout.tsx +218 -88
- package/src/test/data.tsx +2 -3
- package/src/utils/use-breakpoint.ts +2 -0
|
@@ -25,6 +25,10 @@ interface LayoutContentArgs {
|
|
|
25
25
|
sideTop: boolean;
|
|
26
26
|
extraText: boolean;
|
|
27
27
|
search: boolean;
|
|
28
|
+
longContent: boolean;
|
|
29
|
+
wideContent: boolean;
|
|
30
|
+
minWidth: boolean;
|
|
31
|
+
emptyNav: boolean;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
export default {
|
|
@@ -37,6 +41,10 @@ export default {
|
|
|
37
41
|
sideTop: true,
|
|
38
42
|
extraText: true,
|
|
39
43
|
search: true,
|
|
44
|
+
longContent: true,
|
|
45
|
+
wideContent: false,
|
|
46
|
+
minWidth: false,
|
|
47
|
+
emptyNav: false,
|
|
40
48
|
} as LayoutContentArgs,
|
|
41
49
|
};
|
|
42
50
|
|
|
@@ -64,6 +72,7 @@ const profile = (
|
|
|
64
72
|
to="https://google.com"
|
|
65
73
|
tooltip="Google it"
|
|
66
74
|
target="_blank"
|
|
75
|
+
tag={{ value: true }}
|
|
67
76
|
>
|
|
68
77
|
first link
|
|
69
78
|
</ProfileDropdown.Link>
|
|
@@ -176,7 +185,9 @@ const ContentHeader = () => {
|
|
|
176
185
|
</Fragment>
|
|
177
186
|
);
|
|
178
187
|
};
|
|
179
|
-
const SearchBar = () =>
|
|
188
|
+
const SearchBar = () => (
|
|
189
|
+
<TextField size="small" placeholder="Search" className="w-100-i m-x-half-i" />
|
|
190
|
+
);
|
|
180
191
|
|
|
181
192
|
const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
|
|
182
193
|
const [state, setState] = useState<TitanLayoutState | undefined>(undefined);
|
|
@@ -186,7 +197,7 @@ const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
|
|
|
186
197
|
onStateChange: setState,
|
|
187
198
|
|
|
188
199
|
navigationComponent: NavLinkMock,
|
|
189
|
-
navigationMainItems: mainNavItems,
|
|
200
|
+
navigationMainItems: args.emptyNav ? [] : mainNavItems,
|
|
190
201
|
|
|
191
202
|
profile,
|
|
192
203
|
top: args.search ? <SearchBar /> : undefined,
|
|
@@ -196,15 +207,111 @@ const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
|
|
|
196
207
|
extraLinksTop,
|
|
197
208
|
extraText: args.extraText ? 'EST (-8 hrs)' : undefined,
|
|
198
209
|
|
|
199
|
-
sideTop: args.sideTop ? sidebarTop() : undefined,
|
|
210
|
+
sideTop: args.sideTop && !args.emptyNav ? sidebarTop() : undefined,
|
|
211
|
+
|
|
212
|
+
minContentWidth: args.minWidth ? 900 : undefined,
|
|
200
213
|
};
|
|
201
214
|
};
|
|
202
215
|
|
|
216
|
+
const Content = (args: LayoutContentArgs) => {
|
|
217
|
+
return (
|
|
218
|
+
<Fragment>
|
|
219
|
+
<LocationInfo className="m-b-3" />
|
|
220
|
+
{args.wideContent && (
|
|
221
|
+
<div style={{ width: '1200px' }}>
|
|
222
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
|
|
223
|
+
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
|
|
224
|
+
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
|
225
|
+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
|
|
226
|
+
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
|
227
|
+
culpa qui officia deserunt mollit anim id est laborum.
|
|
228
|
+
</div>
|
|
229
|
+
)}
|
|
230
|
+
|
|
231
|
+
{args.longContent && (
|
|
232
|
+
<div>
|
|
233
|
+
<p>Lorem</p>
|
|
234
|
+
<p>ipsum</p>
|
|
235
|
+
<p>dolor</p>
|
|
236
|
+
<p>sit</p>
|
|
237
|
+
<p>amet,</p>
|
|
238
|
+
<p>consectetur</p>
|
|
239
|
+
<p>adipiscing</p>
|
|
240
|
+
<p>elit,</p>
|
|
241
|
+
<p>sed</p>
|
|
242
|
+
<p>do</p>
|
|
243
|
+
<p>eiusmod</p>
|
|
244
|
+
<p>tempor</p>
|
|
245
|
+
<p>incididunt</p>
|
|
246
|
+
<p>ut</p>
|
|
247
|
+
<p>labore</p>
|
|
248
|
+
<p>et</p>
|
|
249
|
+
<p>dolore</p>
|
|
250
|
+
<p>magna</p>
|
|
251
|
+
<p>aliqua.</p>
|
|
252
|
+
<p>Ut</p>
|
|
253
|
+
<p>enim</p>
|
|
254
|
+
<p>ad</p>
|
|
255
|
+
<p>minim</p>
|
|
256
|
+
<p>veniam,</p>
|
|
257
|
+
<p>quis</p>
|
|
258
|
+
<p>nostrud</p>
|
|
259
|
+
<p>exercitation</p>
|
|
260
|
+
<p>ullamco</p>
|
|
261
|
+
<p>laboris</p>
|
|
262
|
+
<p>nisi</p>
|
|
263
|
+
<p>ut</p>
|
|
264
|
+
<p>aliquip</p>
|
|
265
|
+
<p>ex</p>
|
|
266
|
+
<p>ea</p>
|
|
267
|
+
<p>commodo</p>
|
|
268
|
+
<p>consequat.</p>
|
|
269
|
+
<p>Duis</p>
|
|
270
|
+
<p>aute</p>
|
|
271
|
+
<p>irure</p>
|
|
272
|
+
<p>dolor</p>
|
|
273
|
+
<p>in</p>
|
|
274
|
+
<p>reprehenderit</p>
|
|
275
|
+
<p>in</p>
|
|
276
|
+
<p>voluptate</p>
|
|
277
|
+
<p>velit</p>
|
|
278
|
+
<p>esse</p>
|
|
279
|
+
<p>cillum</p>
|
|
280
|
+
<p>dolore</p>
|
|
281
|
+
<p>eu</p>
|
|
282
|
+
<p>fugiat</p>
|
|
283
|
+
<p>nulla</p>
|
|
284
|
+
<p>pariatur.</p>
|
|
285
|
+
<p>Excepteur</p>
|
|
286
|
+
<p>sint</p>
|
|
287
|
+
<p>occaecat</p>
|
|
288
|
+
<p>cupidatat</p>
|
|
289
|
+
<p>non</p>
|
|
290
|
+
<p>proident,</p>
|
|
291
|
+
<p>sunt</p>
|
|
292
|
+
<p>in</p>
|
|
293
|
+
<p>culpa</p>
|
|
294
|
+
<p>qui</p>
|
|
295
|
+
<p>officia</p>
|
|
296
|
+
<p>deserunt</p>
|
|
297
|
+
<p>mollit</p>
|
|
298
|
+
<p>anim</p>
|
|
299
|
+
<p>id</p>
|
|
300
|
+
<p>est</p>
|
|
301
|
+
<p>laborum.</p>
|
|
302
|
+
</div>
|
|
303
|
+
)}
|
|
304
|
+
</Fragment>
|
|
305
|
+
);
|
|
306
|
+
};
|
|
307
|
+
|
|
203
308
|
export const TitanLayoutLegacy = (args: LayoutContentArgs) => (
|
|
204
309
|
<TitanLayout {...useLayoutProps(args)} appearance="legacy">
|
|
205
310
|
<TitanLayout.Logo title />
|
|
206
311
|
<TitanLayout.Content>
|
|
207
|
-
<
|
|
312
|
+
<div className="p-3">
|
|
313
|
+
<Content {...args} />
|
|
314
|
+
</div>
|
|
208
315
|
</TitanLayout.Content>
|
|
209
316
|
</TitanLayout>
|
|
210
317
|
);
|
|
@@ -214,7 +321,7 @@ export const TitanLayoutAnvil1 = (args: LayoutContentArgs) => (
|
|
|
214
321
|
<TitanLayout.Logo title />
|
|
215
322
|
<TitanLayout.Content>
|
|
216
323
|
<Anvil1Page>
|
|
217
|
-
<
|
|
324
|
+
<Content {...args} />
|
|
218
325
|
</Anvil1Page>
|
|
219
326
|
</TitanLayout.Content>
|
|
220
327
|
</TitanLayout>
|
|
@@ -226,7 +333,7 @@ export const TitanLayoutAnvil2 = (args: LayoutContentArgs) => (
|
|
|
226
333
|
<TitanLayout.Content>
|
|
227
334
|
<Anvil2Page>
|
|
228
335
|
<Anvil2Page.Content>
|
|
229
|
-
<
|
|
336
|
+
<Content {...args} />
|
|
230
337
|
</Anvil2Page.Content>
|
|
231
338
|
</Anvil2Page>
|
|
232
339
|
</TitanLayout.Content>
|
|
@@ -29,24 +29,27 @@ import { TitanLayoutLogo, TitanLayoutLogoProps } from './layout-logo';
|
|
|
29
29
|
import { LayoutSidebar } from './layout-sidebar';
|
|
30
30
|
import { TitanLayoutSidebarLink, TitanLayoutSidebarTrigger } from './layout-sidebar-links';
|
|
31
31
|
import { InternalSideNavigationTrigger } from './layout-sidebar-links-internal';
|
|
32
|
+
import { useNotificationsState } from './notifications-context';
|
|
32
33
|
import * as Styles from './titan-layout.module.less';
|
|
33
34
|
|
|
34
35
|
type TitanLayoutChild = ReactElement<TitanLayoutContentProps> | ReactElement<TitanLayoutLogoProps>;
|
|
35
36
|
|
|
36
37
|
export type TitanLayoutProps = Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'style'> & {
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
/** layout appearance */
|
|
39
39
|
appearance?: 'legacy' | 'anvil1' | 'anvil2';
|
|
40
40
|
|
|
41
|
+
/** layout's content */
|
|
42
|
+
children?: TitanLayoutChild | TitanLayoutChild[];
|
|
43
|
+
|
|
44
|
+
/** show only content without side and top bars */
|
|
45
|
+
contentOnly?: boolean;
|
|
46
|
+
|
|
41
47
|
/** component used for navigation */
|
|
42
48
|
navigationComponent?: FC<NavLinkComponentProps>;
|
|
43
49
|
|
|
44
50
|
/** data for main navigation links */
|
|
45
51
|
navigationMainItems?: NavigationItemData[];
|
|
46
52
|
|
|
47
|
-
/** layout's content */
|
|
48
|
-
children?: TitanLayoutChild | TitanLayoutChild[];
|
|
49
|
-
|
|
50
53
|
state?: TitanLayoutState;
|
|
51
54
|
onStateChange?: (state: TitanLayoutState) => void;
|
|
52
55
|
|
|
@@ -57,6 +60,7 @@ export type TitanLayoutProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'
|
|
|
57
60
|
extraLinks?: ReactElement;
|
|
58
61
|
extraLinksTop?: ReactElement;
|
|
59
62
|
extraText?: string;
|
|
63
|
+
minContentWidth?: number;
|
|
60
64
|
};
|
|
61
65
|
|
|
62
66
|
const defaultSidebarContext: TitanLayoutSidebarContextType = {
|
|
@@ -115,6 +119,7 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
|
|
|
115
119
|
appearance = 'anvil2',
|
|
116
120
|
id,
|
|
117
121
|
children,
|
|
122
|
+
contentOnly,
|
|
118
123
|
navigationComponent,
|
|
119
124
|
header,
|
|
120
125
|
top,
|
|
@@ -125,10 +130,10 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
|
|
|
125
130
|
extraLinks,
|
|
126
131
|
extraLinksTop,
|
|
127
132
|
extraText,
|
|
133
|
+
minContentWidth,
|
|
128
134
|
sideTop,
|
|
129
135
|
}) => {
|
|
130
136
|
const breakpoint = useTitanBreakpoint();
|
|
131
|
-
const isMobile = breakpoint.isMobile;
|
|
132
137
|
const context: TitanLayoutContextType = useMemo(
|
|
133
138
|
() => ({
|
|
134
139
|
NavigationComponent: navigationComponent ?? DefaultNavLinkComponent,
|
|
@@ -141,21 +146,23 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
|
|
|
141
146
|
const variant = useVariant(appearance);
|
|
142
147
|
const [mobileDrawerOpened, setMobileDrawerOpened] = useState(false);
|
|
143
148
|
const { content, logo } = useLayoutChildren(children);
|
|
149
|
+
const { hasNotifications, NotificationsContextProvider } = useNotificationsState();
|
|
150
|
+
const [anvil2Styles, setAnvil2Styles] = useState<object>({});
|
|
151
|
+
const updateIndicatorsHeight = useCallback((offset: number) => {
|
|
152
|
+
setAnvil2Styles({ '--offset': `calc(var(--nav-offset-top) + ${offset}px)` });
|
|
153
|
+
}, []);
|
|
154
|
+
|
|
155
|
+
const isMobile = breakpoint.isMobile;
|
|
156
|
+
const hasSideBar = !contentOnly && (!!navigationMainItems?.length || !!sideTop?.length);
|
|
157
|
+
const hasTopBar = !contentOnly;
|
|
144
158
|
|
|
145
159
|
useEffect(() => {
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
if (variant.isAnvil1) {
|
|
161
|
+
const bodyClassName = 'of-hidden-i';
|
|
162
|
+
document.body.classList.add(bodyClassName);
|
|
163
|
+
return () => document.body.classList.remove(bodyClassName);
|
|
149
164
|
}
|
|
150
|
-
|
|
151
|
-
const listener = () => {
|
|
152
|
-
setMobileDrawerOpened(false);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
document.addEventListener('click', listener);
|
|
156
|
-
|
|
157
|
-
return () => document.removeEventListener('click', listener);
|
|
158
|
-
}, [isMobile]);
|
|
165
|
+
}, [variant.isAnvil1]);
|
|
159
166
|
|
|
160
167
|
const onBurgerClick = useCallback((e: MouseEvent) => {
|
|
161
168
|
setMobileDrawerOpened(true);
|
|
@@ -181,6 +188,48 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
|
|
|
181
188
|
},
|
|
182
189
|
[state, onStateChange]
|
|
183
190
|
);
|
|
191
|
+
const hasMenuNotifications = useMemo(() => {
|
|
192
|
+
try {
|
|
193
|
+
return (
|
|
194
|
+
navigationMainItems?.some(item => {
|
|
195
|
+
if (item.counter || item.tag?.value) {
|
|
196
|
+
return true;
|
|
197
|
+
} else if (item.submenu) {
|
|
198
|
+
return item.submenu.groups.some(group =>
|
|
199
|
+
group.links.some(link => !!link.counter || !!link.tag?.value)
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}) ?? false
|
|
204
|
+
);
|
|
205
|
+
} catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}, [navigationMainItems]);
|
|
209
|
+
|
|
210
|
+
const limitContentWidth = useMemo(() => {
|
|
211
|
+
if (variant.isAnvil2 || !minContentWidth) {
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (breakpoint.width < minContentWidth) {
|
|
216
|
+
return minContentWidth;
|
|
217
|
+
}
|
|
218
|
+
}, [variant, minContentWidth, breakpoint.width]);
|
|
219
|
+
|
|
220
|
+
const contentStyles = useMemo(() => {
|
|
221
|
+
if (variant.isAnvil2) {
|
|
222
|
+
return anvil2Styles;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (variant.isLegacy && limitContentWidth) {
|
|
226
|
+
return {
|
|
227
|
+
display: 'flex',
|
|
228
|
+
flexDirection: 'column',
|
|
229
|
+
minHeight: '100vh',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}, [variant, anvil2Styles, limitContentWidth]);
|
|
184
233
|
|
|
185
234
|
const layoutClass = variant.isLegacy
|
|
186
235
|
? Styles.layoutLegacy
|
|
@@ -196,62 +245,88 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
|
|
|
196
245
|
className={classNames(
|
|
197
246
|
Styles.layout,
|
|
198
247
|
isMobile ? Styles.layoutMobile : Styles.layoutDesktop,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
:
|
|
248
|
+
{
|
|
249
|
+
[Styles.layoutTop]: hasTopBar,
|
|
250
|
+
[Styles.layoutNavSlim]: !isMobile && hasSideBar && state?.navCollapsed,
|
|
251
|
+
[Styles.layoutNavWide]: !isMobile && hasSideBar && !state?.navCollapsed,
|
|
252
|
+
},
|
|
202
253
|
layoutClass
|
|
203
254
|
)}
|
|
255
|
+
style={contentStyles}
|
|
204
256
|
>
|
|
205
257
|
{variant.isSequent && <div className={Styles.topPlaceholder} />}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
{extraLinksTop}
|
|
215
|
-
{!isMobile && extraLinks}
|
|
216
|
-
</Fragment>
|
|
217
|
-
}
|
|
218
|
-
onBurgerClick={onBurgerClick}
|
|
219
|
-
/>
|
|
220
|
-
|
|
221
|
-
<LayoutSidebar
|
|
222
|
-
className={Styles.side}
|
|
223
|
-
mobile={breakpoint.isMobile}
|
|
224
|
-
barExpanded={isMobile ? mobileDrawerOpened : !state?.navCollapsed}
|
|
225
|
-
submenuExpanded={state?.submenuExpanded}
|
|
226
|
-
onBarExpandChange={onBarExpandChange}
|
|
227
|
-
onSubmenuExpandChange={onSubmenuExpandChange}
|
|
228
|
-
top={sideTop}
|
|
229
|
-
mainItems={navigationMainItems}
|
|
230
|
-
navigationComponent={context.NavigationComponent}
|
|
231
|
-
bottom={
|
|
232
|
-
isMobile ? (
|
|
258
|
+
{hasTopBar && (
|
|
259
|
+
<LayoutHeader
|
|
260
|
+
className={Styles.top}
|
|
261
|
+
logo={logo}
|
|
262
|
+
profile={isMobile ? undefined : profile}
|
|
263
|
+
center={top}
|
|
264
|
+
rightText={isMobile ? undefined : extraText}
|
|
265
|
+
right={
|
|
233
266
|
<Fragment>
|
|
234
|
-
{
|
|
235
|
-
{extraLinks}
|
|
236
|
-
{!!extraText && (
|
|
237
|
-
<InternalSideNavigationTrigger
|
|
238
|
-
id="__extra_text"
|
|
239
|
-
title={extraText}
|
|
240
|
-
submenuExpanded={undefined}
|
|
241
|
-
dataPrefix="navigation-extra-text"
|
|
242
|
-
tag={undefined}
|
|
243
|
-
icon={undefined}
|
|
244
|
-
iconActive={undefined}
|
|
245
|
-
/>
|
|
246
|
-
)}
|
|
267
|
+
{extraLinksTop}
|
|
268
|
+
{!isMobile && extraLinks}
|
|
247
269
|
</Fragment>
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
270
|
+
}
|
|
271
|
+
isMobile={isMobile}
|
|
272
|
+
hasNotifications={hasNotifications || hasMenuNotifications}
|
|
273
|
+
onBurgerClick={onBurgerClick}
|
|
274
|
+
/>
|
|
275
|
+
)}
|
|
251
276
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
277
|
+
{hasSideBar && (
|
|
278
|
+
<NotificationsContextProvider>
|
|
279
|
+
<LayoutSidebar
|
|
280
|
+
className={Styles.side}
|
|
281
|
+
mobile={breakpoint.isMobile}
|
|
282
|
+
barExpanded={!state?.navCollapsed}
|
|
283
|
+
onBarExpandChange={onBarExpandChange}
|
|
284
|
+
submenuExpanded={state?.submenuExpanded}
|
|
285
|
+
onSubmenuExpandChange={onSubmenuExpandChange}
|
|
286
|
+
drawerOpened={mobileDrawerOpened}
|
|
287
|
+
onDrawerOpenChange={setMobileDrawerOpened}
|
|
288
|
+
top={sideTop}
|
|
289
|
+
mainItems={navigationMainItems}
|
|
290
|
+
navigationComponent={context.NavigationComponent}
|
|
291
|
+
bottom={
|
|
292
|
+
isMobile ? (
|
|
293
|
+
<Fragment>
|
|
294
|
+
{profile}
|
|
295
|
+
{extraLinks}
|
|
296
|
+
{!!extraText && (
|
|
297
|
+
<InternalSideNavigationTrigger
|
|
298
|
+
id="__extra_text"
|
|
299
|
+
title={extraText}
|
|
300
|
+
submenuExpanded={undefined}
|
|
301
|
+
dataPrefix="navigation-extra-text"
|
|
302
|
+
tag={undefined}
|
|
303
|
+
icon={undefined}
|
|
304
|
+
iconActive={undefined}
|
|
305
|
+
/>
|
|
306
|
+
)}
|
|
307
|
+
</Fragment>
|
|
308
|
+
) : undefined
|
|
309
|
+
}
|
|
310
|
+
/>
|
|
311
|
+
</NotificationsContextProvider>
|
|
312
|
+
)}
|
|
313
|
+
|
|
314
|
+
{variant.isAnvil1 ? (
|
|
315
|
+
<LayoutContentAnvil1 header={header} minWidth={limitContentWidth}>
|
|
316
|
+
{content}
|
|
317
|
+
</LayoutContentAnvil1>
|
|
318
|
+
) : variant.isLegacy ? (
|
|
319
|
+
<LayoutContentLegacy header={header} minWidth={limitContentWidth}>
|
|
320
|
+
{content}
|
|
321
|
+
</LayoutContentLegacy>
|
|
322
|
+
) : (
|
|
323
|
+
<LayoutContentAnvil2
|
|
324
|
+
header={header}
|
|
325
|
+
onHeaderHeightChange={updateIndicatorsHeight}
|
|
326
|
+
>
|
|
327
|
+
{content}
|
|
328
|
+
</LayoutContentAnvil2>
|
|
329
|
+
)}
|
|
255
330
|
</div>
|
|
256
331
|
</LayoutPlacementContext.Provider>
|
|
257
332
|
</LayoutContext.Provider>
|
|
@@ -287,7 +362,14 @@ const TitanLayoutHeaderObserved: FC<{
|
|
|
287
362
|
};
|
|
288
363
|
}, [heightChange]);
|
|
289
364
|
return (
|
|
290
|
-
<div ref={ref} className={Styles.header
|
|
365
|
+
<div ref={ref} className={Styles.contentHeader} data-cy="layout-content-header">
|
|
366
|
+
{children}
|
|
367
|
+
</div>
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
const TitanLayoutHeader: FC<{ children: ReactNode }> = ({ children }) => {
|
|
371
|
+
return (
|
|
372
|
+
<div className={Styles.contentHeader} data-cy="layout-content-header">
|
|
291
373
|
{children}
|
|
292
374
|
</div>
|
|
293
375
|
);
|
|
@@ -298,28 +380,76 @@ export interface TitanLayoutContentProps {
|
|
|
298
380
|
}
|
|
299
381
|
const TitanLayoutContent: FC<TitanLayoutContentProps> = ({ children }) => children;
|
|
300
382
|
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}) => {
|
|
306
|
-
const [anvil2Styles, setAnvil2Styles] = useState<object>({});
|
|
307
|
-
const updateIndicatorsHeight = useCallback((offset: number) => {
|
|
308
|
-
setAnvil2Styles({ '--offset': `calc(var(--nav-offset-top) + ${offset}px)` });
|
|
309
|
-
}, []);
|
|
310
|
-
|
|
383
|
+
const LayoutContentAnvil2: FC<{
|
|
384
|
+
children: ReactNode;
|
|
385
|
+
header?: ReactNode;
|
|
386
|
+
onHeaderHeightChange?: (height: number) => void;
|
|
387
|
+
}> = ({ children, header, onHeaderHeightChange }) => {
|
|
311
388
|
return (
|
|
312
|
-
<
|
|
313
|
-
{
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
{header}
|
|
317
|
-
</TitanLayoutHeaderObserved>
|
|
318
|
-
) : (
|
|
319
|
-
header
|
|
320
|
-
))}
|
|
389
|
+
<Fragment>
|
|
390
|
+
<TitanLayoutHeaderObserved heightChange={onHeaderHeightChange}>
|
|
391
|
+
{header}
|
|
392
|
+
</TitanLayoutHeaderObserved>
|
|
321
393
|
{children}
|
|
322
|
-
</
|
|
394
|
+
</Fragment>
|
|
395
|
+
);
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const LayoutContentAnvil1: FC<{
|
|
399
|
+
children: ReactNode;
|
|
400
|
+
header?: ReactNode;
|
|
401
|
+
minWidth?: number;
|
|
402
|
+
}> = ({ children, header, minWidth }) => {
|
|
403
|
+
const innerContentStyles: CSSProperties = useMemo(
|
|
404
|
+
() => ({
|
|
405
|
+
...(minWidth ? { minWidth: `${minWidth}px` } : {}),
|
|
406
|
+
}),
|
|
407
|
+
[minWidth]
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
<Fragment>
|
|
412
|
+
<TitanLayoutHeader>{header}</TitanLayoutHeader>
|
|
413
|
+
<div
|
|
414
|
+
className={classNames(Styles.content, { 'of-x-auto': !!minWidth })}
|
|
415
|
+
data-cy="layout-content"
|
|
416
|
+
>
|
|
417
|
+
<div
|
|
418
|
+
className="position-relative d-f flex-grow-1 flex-basis-0 of-hidden"
|
|
419
|
+
style={innerContentStyles}
|
|
420
|
+
>
|
|
421
|
+
{children}
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
</Fragment>
|
|
425
|
+
);
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const LayoutContentLegacy: FC<{
|
|
429
|
+
children: ReactNode;
|
|
430
|
+
header?: ReactNode;
|
|
431
|
+
minWidth: number | undefined;
|
|
432
|
+
}> = ({ children, header, minWidth }) => {
|
|
433
|
+
const innerContentStyles: CSSProperties = useMemo(
|
|
434
|
+
() => ({
|
|
435
|
+
position: 'relative',
|
|
436
|
+
minWidth: `${minWidth}px`,
|
|
437
|
+
}),
|
|
438
|
+
[minWidth]
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
<Fragment>
|
|
443
|
+
<TitanLayoutHeader>{header}</TitanLayoutHeader>
|
|
444
|
+
|
|
445
|
+
{minWidth ? (
|
|
446
|
+
<div className="of-x-auto flex-basis-0 flex-grow-1">
|
|
447
|
+
<div style={innerContentStyles}>{children}</div>
|
|
448
|
+
</div>
|
|
449
|
+
) : (
|
|
450
|
+
children
|
|
451
|
+
)}
|
|
452
|
+
</Fragment>
|
|
323
453
|
);
|
|
324
454
|
};
|
|
325
455
|
|
package/src/test/data.tsx
CHANGED
|
@@ -66,7 +66,6 @@ export const NavLinkMock = forwardRef<any, NavLinkComponentProps>(
|
|
|
66
66
|
{...rest}
|
|
67
67
|
onClick={e => {
|
|
68
68
|
e.preventDefault();
|
|
69
|
-
e.stopPropagation();
|
|
70
69
|
|
|
71
70
|
if (!to.startsWith('http')) {
|
|
72
71
|
history.replace(to);
|
|
@@ -82,10 +81,10 @@ export const NavLinkMock = forwardRef<any, NavLinkComponentProps>(
|
|
|
82
81
|
}
|
|
83
82
|
);
|
|
84
83
|
|
|
85
|
-
export const LocationInfo = () => {
|
|
84
|
+
export const LocationInfo: FC<{ className?: string }> = ({ className }) => {
|
|
86
85
|
const location = useLocation();
|
|
87
86
|
|
|
88
|
-
return <BodyText>current location - {location.pathname}</BodyText>;
|
|
87
|
+
return <BodyText className={className}>current location - {location.pathname}</BodyText>;
|
|
89
88
|
};
|
|
90
89
|
|
|
91
90
|
const LocationProvider: FC<{ children: any }> = ({ children }) => {
|
|
@@ -4,6 +4,7 @@ import { useMemo } from 'react';
|
|
|
4
4
|
export interface TitanBreakpoint {
|
|
5
5
|
name: BreakpointReturnProps['name'];
|
|
6
6
|
isMobile: boolean;
|
|
7
|
+
width: number;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export const useTitanBreakpoint = (): TitanBreakpoint => {
|
|
@@ -13,6 +14,7 @@ export const useTitanBreakpoint = (): TitanBreakpoint => {
|
|
|
13
14
|
() => ({
|
|
14
15
|
name: breakpoint?.name ?? 'xl',
|
|
15
16
|
isMobile: breakpoint ? breakpoint.innerWidth <= 768 : false,
|
|
17
|
+
width: breakpoint?.innerWidth ?? 0,
|
|
16
18
|
}),
|
|
17
19
|
[breakpoint]
|
|
18
20
|
);
|