@servicetitan/navigation 10.7.0 → 11.0.0-canary.237.0c461af.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 (149) hide show
  1. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
  2. package/dist/components/header-navigation/header-navigation-extra.stories.js +5 -5
  3. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
  4. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
  5. package/dist/components/header-navigation/header-navigation-links.js +2 -2
  6. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
  8. package/dist/components/header-navigation/header-navigation-stacked.stories.js +1 -1
  9. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
  10. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  11. package/dist/components/header-navigation/header-navigation.stories.js +2 -2
  12. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  13. package/dist/components/header-navigation/with-tooltip.d.ts +1 -1
  14. package/dist/components/header-navigation/with-tooltip.d.ts.map +1 -1
  15. package/dist/components/left-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
  16. package/dist/components/left-navigation/header-navigation-tiny.stories.js +2 -2
  17. package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
  18. package/dist/components/links.d.ts.map +1 -1
  19. package/dist/components/links.js +7 -7
  20. package/dist/components/links.js.map +1 -1
  21. package/dist/components/logo/logo-company-title.d.ts +1 -0
  22. package/dist/components/logo/logo-company-title.d.ts.map +1 -1
  23. package/dist/components/logo/logo-company-title.js +2 -2
  24. package/dist/components/logo/logo-company-title.js.map +1 -1
  25. package/dist/components/profile-dropdown/profile-dropdown.d.ts +15 -9
  26. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  27. package/dist/components/profile-dropdown/profile-dropdown.js +7 -8
  28. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  29. package/dist/components/profile-dropdown/profile-dropdown.module.less +4 -0
  30. package/dist/components/profile-dropdown/profile-dropdown.stories.js +2 -2
  31. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  32. package/dist/components/titan-layout/index.d.ts +6 -0
  33. package/dist/components/titan-layout/index.d.ts.map +1 -0
  34. package/dist/components/titan-layout/index.js +6 -0
  35. package/dist/components/titan-layout/index.js.map +1 -0
  36. package/dist/components/titan-layout/interface-internal.d.ts +6 -0
  37. package/dist/components/titan-layout/interface-internal.d.ts.map +1 -0
  38. package/dist/components/titan-layout/interface-internal.js +2 -0
  39. package/dist/components/titan-layout/interface-internal.js.map +1 -0
  40. package/dist/components/titan-layout/interface.d.ts +21 -0
  41. package/dist/components/titan-layout/interface.d.ts.map +1 -0
  42. package/dist/components/titan-layout/interface.js +2 -0
  43. package/dist/components/titan-layout/interface.js.map +1 -0
  44. package/dist/components/titan-layout/layout-context.d.ts +20 -0
  45. package/dist/components/titan-layout/layout-context.d.ts.map +1 -0
  46. package/dist/components/titan-layout/layout-context.js +12 -0
  47. package/dist/components/titan-layout/layout-context.js.map +1 -0
  48. package/dist/components/titan-layout/layout-header-links.d.ts +7 -0
  49. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -0
  50. package/dist/components/titan-layout/layout-header-links.js +32 -0
  51. package/dist/components/titan-layout/layout-header-links.js.map +1 -0
  52. package/dist/components/titan-layout/layout-header.d.ts +20 -0
  53. package/dist/components/titan-layout/layout-header.d.ts.map +1 -0
  54. package/dist/components/titan-layout/layout-header.js +11 -0
  55. package/dist/components/titan-layout/layout-header.js.map +1 -0
  56. package/dist/components/titan-layout/layout-header.module.less +174 -0
  57. package/dist/components/titan-layout/layout-logo.d.ts +12 -0
  58. package/dist/components/titan-layout/layout-logo.d.ts.map +1 -0
  59. package/dist/components/titan-layout/layout-logo.js +15 -0
  60. package/dist/components/titan-layout/layout-logo.js.map +1 -0
  61. package/dist/components/titan-layout/layout-logo.stories.d.ts +13 -0
  62. package/dist/components/titan-layout/layout-logo.stories.d.ts.map +1 -0
  63. package/dist/components/titan-layout/layout-logo.stories.js +17 -0
  64. package/dist/components/titan-layout/layout-logo.stories.js.map +1 -0
  65. package/dist/components/titan-layout/layout-profile.d.ts +9 -0
  66. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -0
  67. package/dist/components/titan-layout/layout-profile.js +54 -0
  68. package/dist/components/titan-layout/layout-profile.js.map +1 -0
  69. package/dist/components/titan-layout/layout-profile.stories.d.ts +13 -0
  70. package/dist/components/titan-layout/layout-profile.stories.d.ts.map +1 -0
  71. package/dist/components/titan-layout/layout-profile.stories.js +13 -0
  72. package/dist/components/titan-layout/layout-profile.stories.js.map +1 -0
  73. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +46 -0
  74. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -0
  75. package/dist/components/titan-layout/layout-sidebar-links-internal.js +61 -0
  76. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -0
  77. package/dist/components/titan-layout/layout-sidebar-links.d.ts +6 -0
  78. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -0
  79. package/dist/components/titan-layout/layout-sidebar-links.js +21 -0
  80. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -0
  81. package/dist/components/titan-layout/layout-sidebar.d.ts +17 -0
  82. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -0
  83. package/dist/components/titan-layout/layout-sidebar.js +65 -0
  84. package/dist/components/titan-layout/layout-sidebar.js.map +1 -0
  85. package/dist/components/titan-layout/layout-sidebar.module.less +516 -0
  86. package/dist/components/titan-layout/titan-layout.d.ts +38 -0
  87. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
  88. package/dist/components/titan-layout/titan-layout.js +147 -0
  89. package/dist/components/titan-layout/titan-layout.js.map +1 -0
  90. package/dist/components/titan-layout/titan-layout.module.less +103 -0
  91. package/dist/components/titan-layout/titan-layout.stories.d.ts +20 -0
  92. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
  93. package/dist/components/titan-layout/titan-layout.stories.js +80 -0
  94. package/dist/components/titan-layout/titan-layout.stories.js.map +1 -0
  95. package/dist/components/titan-layout/with-tooltip.d.ts +4 -0
  96. package/dist/components/titan-layout/with-tooltip.d.ts.map +1 -0
  97. package/dist/components/titan-layout/with-tooltip.js +4 -0
  98. package/dist/components/titan-layout/with-tooltip.js.map +1 -0
  99. package/dist/index.d.ts +2 -1
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +2 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/test/data.d.ts.map +1 -1
  104. package/dist/test/data.js +3 -3
  105. package/dist/test/data.js.map +1 -1
  106. package/dist/utils/navigation-legacy.d.ts +3 -1
  107. package/dist/utils/navigation-legacy.d.ts.map +1 -1
  108. package/dist/utils/use-breakpoint.d.ts +7 -0
  109. package/dist/utils/use-breakpoint.d.ts.map +1 -0
  110. package/dist/utils/use-breakpoint.js +13 -0
  111. package/dist/utils/use-breakpoint.js.map +1 -0
  112. package/package.json +5 -6
  113. package/src/components/header-navigation/header-navigation-extra.stories.tsx +7 -0
  114. package/src/components/header-navigation/header-navigation-links.tsx +2 -0
  115. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +5 -1
  116. package/src/components/header-navigation/header-navigation.stories.tsx +6 -1
  117. package/src/components/left-navigation/header-navigation-tiny.stories.tsx +8 -2
  118. package/src/components/left-navigation/side-navigation-links.tsx +1 -1
  119. package/src/components/links.tsx +33 -13
  120. package/src/components/logo/logo-company-title.tsx +8 -6
  121. package/src/components/profile-dropdown/profile-dropdown.module.less +4 -0
  122. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -4
  123. package/src/components/profile-dropdown/profile-dropdown.tsx +55 -51
  124. package/src/components/titan-layout/index.ts +5 -0
  125. package/src/components/titan-layout/interface-internal.ts +6 -0
  126. package/src/components/titan-layout/interface.ts +26 -0
  127. package/src/components/titan-layout/layout-context.tsx +30 -0
  128. package/src/components/titan-layout/layout-header-links.tsx +144 -0
  129. package/src/components/titan-layout/layout-header.module.less +174 -0
  130. package/src/components/titan-layout/layout-header.module.less.d.ts +16 -0
  131. package/src/components/titan-layout/layout-header.tsx +90 -0
  132. package/src/components/titan-layout/layout-logo.stories.tsx +31 -0
  133. package/src/components/titan-layout/layout-logo.tsx +57 -0
  134. package/src/components/titan-layout/layout-profile.stories.tsx +46 -0
  135. package/src/components/titan-layout/layout-profile.tsx +132 -0
  136. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +275 -0
  137. package/src/components/titan-layout/layout-sidebar-links.tsx +59 -0
  138. package/src/components/titan-layout/layout-sidebar.module.less +516 -0
  139. package/src/components/titan-layout/layout-sidebar.module.less.d.ts +48 -0
  140. package/src/components/titan-layout/layout-sidebar.tsx +295 -0
  141. package/src/components/titan-layout/titan-layout.module.less +103 -0
  142. package/src/components/titan-layout/titan-layout.module.less.d.ts +15 -0
  143. package/src/components/titan-layout/titan-layout.stories.tsx +332 -0
  144. package/src/components/titan-layout/titan-layout.tsx +365 -0
  145. package/src/components/titan-layout/with-tooltip.tsx +16 -0
  146. package/src/index.ts +2 -1
  147. package/src/test/data.tsx +3 -2
  148. package/src/utils/navigation-legacy.ts +3 -1
  149. package/src/utils/use-breakpoint.ts +19 -0
@@ -0,0 +1,174 @@
1
+ /* stylelint-disable no-descending-specificity */
2
+ @import (reference) '@servicetitan/tokens/core/tokens.less';
3
+
4
+ @size-links-tiny: 24px;
5
+
6
+ .header {
7
+ display: flex;
8
+ justify-content: space-between;
9
+
10
+ background-color: @color-white;
11
+ color: @color-black;
12
+ border-bottom: 1px solid @color-neutral-60;
13
+
14
+ & > * {
15
+ overflow-y: hidden;
16
+ }
17
+
18
+ .he-top-left {
19
+ display: flex;
20
+ align-items: center;
21
+ }
22
+
23
+ .he-top-right {
24
+ & > * {
25
+ color: @color-black;
26
+ }
27
+
28
+ .he-top-right-text {
29
+ font-size: @typescale-2;
30
+ font-weight: @font-weight-bold;
31
+ font-family: @base-font-family;
32
+ margin-right: @spacing-1;
33
+ }
34
+ }
35
+
36
+ :global(.profile-dropdown-image) {
37
+ height: 24px;
38
+ width: 24px;
39
+ }
40
+
41
+ :global(.profile-dropdown-trigger) {
42
+ height: 32px;
43
+ font-size: @size-links-tiny;
44
+ }
45
+
46
+ .navigation-link {
47
+ border-radius: 12px;
48
+ font-size: @size-links-tiny;
49
+ color: inherit;
50
+
51
+ &.navigation-item-active:not(.navigation-item-overflow) {
52
+ background-color: @color-blue-100 !important;
53
+ color: @color-blue-500 !important;
54
+ }
55
+ &:hover:not(.navigation-item-active):not(.navigation-item-overflow) {
56
+ background-color: rgba(0, 0, 0, 0.12) !important;
57
+ }
58
+
59
+ &.navigation-item-icon-state.navigation-item-active {
60
+ .navigation-icon:not(.navigation-icon-active) {
61
+ display: none;
62
+ }
63
+
64
+ .navigation-icon.navigation-icon-active[data-anv][data-anv] {
65
+ display: block;
66
+ }
67
+ }
68
+ }
69
+
70
+ .navigation-icon[data-anv][data-anv] {
71
+ display: inline-block;
72
+ color: inherit;
73
+ height: 24px;
74
+ width: 24px;
75
+
76
+ > svg {
77
+ height: @size-links-tiny;
78
+ width: @size-links-tiny;
79
+ }
80
+
81
+ &.navigation-icon-active {
82
+ display: none;
83
+ }
84
+ }
85
+ }
86
+
87
+ // desktop
88
+ @media only screen and (min-width: 768px) {
89
+ .header {
90
+ height: var(--nav-offset-top);
91
+ .navigation-link {
92
+ margin: 6px 2px;
93
+ padding: 6px 6px;
94
+ }
95
+
96
+ .he-top-left {
97
+ padding-left: @spacing-1;
98
+ }
99
+ .he-top-center {
100
+ flex: 1;
101
+ margin-left: @spacing-2;
102
+ margin-right: @spacing-2;
103
+ max-width: 400px;
104
+ }
105
+ }
106
+ }
107
+ // desktop wide
108
+ @media only screen and (min-width: 1200px) {
109
+ .header {
110
+ display: grid;
111
+ grid-template-columns: repeat(3, 1fr);
112
+ grid-template-rows: 48px;
113
+
114
+ .he-top-left,
115
+ .he-top-center,
116
+ .he-top-right {
117
+ grid-column: span 1;
118
+ }
119
+
120
+ .he-top-center {
121
+ max-width: unset;
122
+ }
123
+ }
124
+ }
125
+
126
+ // mobile
127
+ @media only screen and (max-width: 768px) {
128
+ .header {
129
+ padding: @spacing-1 @spacing-half;
130
+
131
+ .navigation-link {
132
+ padding: 10px;
133
+ }
134
+
135
+ .he-top-center {
136
+ max-width: unset;
137
+ flex: 1;
138
+ margin-left: @spacing-3;
139
+ margin-right: @spacing-3;
140
+ }
141
+ }
142
+ }
143
+
144
+ .navigation-link {
145
+ // styles specific to extra nav links
146
+ color: @color-black;
147
+ position: relative;
148
+ display: flex;
149
+ align-items: center;
150
+ flex-wrap: nowrap;
151
+ text-wrap: nowrap;
152
+
153
+ .navigation-item-counter {
154
+ color: @color-white;
155
+ font-weight: @font-weight-semibold;
156
+ font-size: 8px !important;
157
+ min-width: 12px;
158
+ position: absolute;
159
+ top: 4px;
160
+ right: -2px;
161
+ }
162
+
163
+ .navigation-item-label {
164
+ color: inherit;
165
+ font-size: @typescale-1;
166
+ font-family: @base-font-family;
167
+ font-weight: @font-weight-semibold;
168
+ margin-left: @spacing-half;
169
+ }
170
+
171
+ &.navigation-item-counter-long {
172
+ right: -8px;
173
+ }
174
+ }
@@ -0,0 +1,16 @@
1
+ export const __esModule: true;
2
+ export const heTopCenter: string;
3
+ export const heTopLeft: string;
4
+ export const heTopRight: string;
5
+ export const heTopRightText: string;
6
+ export const header: string;
7
+ export const navigationIcon: string;
8
+ export const navigationIconActive: string;
9
+ export const navigationItemActive: string;
10
+ export const navigationItemCounter: string;
11
+ export const navigationItemCounterLong: string;
12
+ export const navigationItemIconState: string;
13
+ export const navigationItemLabel: string;
14
+ export const navigationItemOverflow: string;
15
+ export const navigationLink: string;
16
+
@@ -0,0 +1,90 @@
1
+ import SvgBurgerMenu from '@servicetitan/anvil2/assets/icons/material/round/menu.svg';
2
+ import classNames from 'classnames';
3
+ import { ComponentPropsWithoutRef, FC, ReactElement, ReactNode } from 'react';
4
+ import { LayoutPlacementContext, useTitanLayoutContext } from './layout-context';
5
+ import { LayoutHeaderNavigationTrigger } from './layout-header-links';
6
+ import * as Styles from './layout-header.module.less';
7
+ import { TitanLayoutLogoProps } from './layout-logo';
8
+
9
+ export interface TitanLayoutHeaderLogoProps {
10
+ title?: true | string;
11
+ mantleFill?: string;
12
+ to?: string;
13
+ }
14
+
15
+ export type LayoutHeaderProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
16
+ right?: ReactNode;
17
+ rightText?: string;
18
+ rightClassName?: string;
19
+
20
+ id?: string;
21
+
22
+ center?: ReactElement;
23
+ centerClassName?: string;
24
+
25
+ logo: ReactElement<TitanLayoutLogoProps>;
26
+ profile?: ReactElement;
27
+
28
+ onBurgerClick?: (e: MouseEvent) => void;
29
+ };
30
+
31
+ export const LayoutHeader: FC<LayoutHeaderProps> = ({
32
+ className,
33
+ right,
34
+ rightText,
35
+ rightClassName,
36
+ center,
37
+ centerClassName,
38
+ logo,
39
+ profile,
40
+ onBurgerClick,
41
+ ...rest
42
+ }) => {
43
+ const { breakpoint } = useTitanLayoutContext();
44
+
45
+ return (
46
+ <LayoutPlacementContext.Provider value="top">
47
+ <div
48
+ className={classNames(Styles.header, className)}
49
+ {...rest}
50
+ data-cy="header-navigation"
51
+ >
52
+ <div className={classNames(Styles.heTopLeft)} data-cy="navigation-left">
53
+ {breakpoint.isMobile && (
54
+ <LayoutHeaderNavigationTrigger
55
+ id="burger"
56
+ title=""
57
+ icon={SvgBurgerMenu}
58
+ iconActive={SvgBurgerMenu}
59
+ className="m-r-1"
60
+ onClick={onBurgerClick}
61
+ />
62
+ )}
63
+ {logo}
64
+ </div>
65
+ <div
66
+ className={classNames(
67
+ Styles.heTopCenter,
68
+ 'd-f align-items-center justify-content-center',
69
+ centerClassName
70
+ )}
71
+ data-cy="navigation-center"
72
+ >
73
+ {center}
74
+ </div>
75
+ <div
76
+ className={classNames(
77
+ 'd-f flex-row justify-content-end align-items-center',
78
+ Styles.heTopRight,
79
+ rightClassName
80
+ )}
81
+ data-cy="navigation-right"
82
+ >
83
+ {!!rightText && <div className={Styles.heTopRightText}>{rightText}</div>}
84
+ {right}
85
+ {profile}
86
+ </div>
87
+ </div>
88
+ </LayoutPlacementContext.Provider>
89
+ );
90
+ };
@@ -0,0 +1,31 @@
1
+ import { Chip } from '@servicetitan/anvil2';
2
+ import { ReactElement } from 'react';
3
+ import { withAnvil, withDefaultRedirects, withMemoryRouter } from '../../test/data';
4
+ import { TitanLayoutLogo, TitanLayoutLogoProps } from './layout-logo';
5
+ import { TitanLayout } from './titan-layout';
6
+
7
+ const withTitanLayout = (element: ReactElement<TitanLayoutLogoProps>) => () => (
8
+ <TitanLayout navigationMainItems={[]}>
9
+ {element}
10
+ <TitanLayout.Content>logo</TitanLayout.Content>
11
+ </TitanLayout>
12
+ );
13
+
14
+ export default {
15
+ title: 'Navigation/TitanLayoutLogo',
16
+ component: TitanLayoutLogo,
17
+ decorators: [withDefaultRedirects, withMemoryRouter, withAnvil],
18
+ parameters: {},
19
+ };
20
+
21
+ export const LogoDefault = withTitanLayout(<TitanLayoutLogo />);
22
+
23
+ export const LogoCompanyTitle = withTitanLayout(<TitanLayoutLogo title />);
24
+
25
+ export const LogoCommercial = withTitanLayout(
26
+ <TitanLayoutLogo title="Commercial" mantleFill="#2270EE" />
27
+ );
28
+
29
+ export const LogoWithPostfix = withTitanLayout(
30
+ <TitanLayoutLogo title postfix={<Chip className="m-l-2-i" label="demo" />} />
31
+ );
@@ -0,0 +1,57 @@
1
+ import classNames from 'classnames';
2
+ import { FC, Fragment, ReactNode } from 'react';
3
+ import { LogoCompanyTitle } from '../logo/logo-company-title';
4
+ import { LogoTitan, LogoTitanTitle, WrapperProps } from '../logo/logo-titan-text';
5
+ import { useTitanLayoutContext } from './layout-context';
6
+
7
+ export interface TitanLayoutLogoProps {
8
+ /** container class name */
9
+ className?: string;
10
+
11
+ title?: string | boolean;
12
+
13
+ postfix?: ReactNode;
14
+
15
+ logoWrapper?: WrapperProps;
16
+
17
+ mantleFill?: string;
18
+ }
19
+
20
+ const EmptyWrapper: FC<any> = ({ children }) => children;
21
+
22
+ export const TitanLayoutLogo: FC<TitanLayoutLogoProps> = ({
23
+ className,
24
+ mantleFill,
25
+ postfix,
26
+ title,
27
+ logoWrapper = EmptyWrapper,
28
+ }) => {
29
+ const {
30
+ breakpoint: { isMobile },
31
+ } = useTitanLayoutContext();
32
+
33
+ const Wrapper = logoWrapper;
34
+ const logoSize = isMobile ? 44 : 56;
35
+ const logoCompanySize = 48;
36
+
37
+ return (
38
+ <div className={classNames('d-f align-items-center', className)}>
39
+ {typeof title === 'string' ? (
40
+ <Fragment>
41
+ <LogoTitan size={logoSize} mantleFill={mantleFill} logoWrapper={Wrapper} />
42
+ {!isMobile && (
43
+ <LogoTitanTitle className="c-inherit m-l-1">{title}</LogoTitanTitle>
44
+ )}
45
+ </Fragment>
46
+ ) : title === true && !isMobile ? (
47
+ <Wrapper className="">
48
+ <LogoCompanyTitle height={logoCompanySize} />
49
+ </Wrapper>
50
+ ) : (
51
+ <LogoTitan size={logoSize} mantleFill={mantleFill} logoWrapper={Wrapper} />
52
+ )}
53
+
54
+ {!isMobile && postfix}
55
+ </div>
56
+ );
57
+ };
@@ -0,0 +1,46 @@
1
+ import { ReactElement } from 'react';
2
+ import { withAnvil, withDefaultRedirects, withMemoryRouter } from '../../test/data';
3
+ import { ProfileDropdown } from './layout-profile';
4
+ import { TitanLayout } from './titan-layout';
5
+
6
+ const withTitanLayout = (element: ReactElement) => () => (
7
+ <TitanLayout navigationMainItems={[]} profile={element}>
8
+ <TitanLayout.Content>profile</TitanLayout.Content>
9
+ </TitanLayout>
10
+ );
11
+
12
+ export default {
13
+ title: 'Navigation/TitanLayoutProfile',
14
+ component: ProfileDropdown,
15
+ decorators: [withDefaultRedirects, withMemoryRouter, withAnvil],
16
+ parameters: {},
17
+ };
18
+
19
+ export const ProfileDefault = withTitanLayout(
20
+ <ProfileDropdown>
21
+ <ProfileDropdown.Link id="first" to="https://google.com" external>
22
+ first link
23
+ </ProfileDropdown.Link>
24
+ <ProfileDropdown.Section id="second" onClick={() => alert('second click')}>
25
+ second link
26
+ </ProfileDropdown.Section>
27
+ <ProfileDropdown.Divider />
28
+ <ProfileDropdown.Section id="content">some content</ProfileDropdown.Section>
29
+ <ProfileDropdown.Divider />
30
+ <ProfileDropdown.Divider />
31
+ <ProfileDropdown.Divider />
32
+ <ProfileDropdown.Link id="third" to="third">
33
+ third link
34
+ </ProfileDropdown.Link>
35
+ <ProfileDropdown.Divider />
36
+ <ProfileDropdown.Section
37
+ id="forth"
38
+ onClick={() => alert('forth click')}
39
+ text="Sign Out user"
40
+ >
41
+ Sign Out
42
+ <span className="c-neutral-60 m-l-1">user</span>
43
+ </ProfileDropdown.Section>
44
+ <ProfileDropdown.Divider />
45
+ </ProfileDropdown>
46
+ );
@@ -0,0 +1,132 @@
1
+ import SvgAccountActive from '@servicetitan/anvil2/assets/icons/st/gnav_account_active.svg';
2
+ import SvgAccountInactive from '@servicetitan/anvil2/assets/icons/st/gnav_account_inactive.svg';
3
+
4
+ import { FC, useState } from 'react';
5
+ import { NavLinkComponentProps, NavigationComponentContext } from '../../utils/navigation-context';
6
+ import {
7
+ ProfileDropdown as DesktopProfileDropdown,
8
+ ProfileDropdownLinkProps,
9
+ ProfileDropdownProps,
10
+ ProfileDropdownSectionProps,
11
+ } from '../profile-dropdown/profile-dropdown';
12
+ import { NavigationComponentProps } from './interface-internal';
13
+ import { useTitanLayoutContext } from './layout-context';
14
+ import {
15
+ InternalSideNavigationGroup,
16
+ InternalSideNavigationGroupDivider,
17
+ InternalSideNavigationGroupLink,
18
+ InternalSideNavigationGroupTrigger,
19
+ } from './layout-sidebar-links-internal';
20
+
21
+ export type {
22
+ ProfileDropdownProps,
23
+ ProfileDropdownSectionProps,
24
+ ProfileDropdownLinkProps,
25
+ } from '../profile-dropdown/profile-dropdown';
26
+
27
+ const ExternalNavComponent: FC<NavLinkComponentProps> = ({ children, isActive, ...props }) => (
28
+ <a {...props}>{children}</a>
29
+ );
30
+
31
+ const ProfileDropdownContent: FC<ProfileDropdownProps> = props => {
32
+ const { breakpoint, NavigationComponent } = useTitanLayoutContext();
33
+ return breakpoint.isMobile ? (
34
+ <MobileProfileDropdown {...props} navigationComponent={NavigationComponent} />
35
+ ) : (
36
+ <NavigationComponentContext.Provider value={NavigationComponent}>
37
+ <DesktopProfileDropdown {...props} />
38
+ </NavigationComponentContext.Provider>
39
+ );
40
+ };
41
+ ProfileDropdownContent.displayName = 'ProfileDropdown';
42
+
43
+ const MobileProfileDropdown: FC<ProfileDropdownProps & NavigationComponentProps> = ({
44
+ children,
45
+ ...props
46
+ }) => {
47
+ const [expanded, setExpanded] = useState(false);
48
+ const onExpandToggle = () => setExpanded(!expanded);
49
+ return (
50
+ <InternalSideNavigationGroup
51
+ id="__profile"
52
+ to={undefined}
53
+ title="Profile"
54
+ icon={SvgAccountInactive}
55
+ iconActive={SvgAccountActive}
56
+ isActive={expanded}
57
+ {...props}
58
+ submenuExpanded={expanded}
59
+ onExpandToggle={onExpandToggle}
60
+ onClick={onExpandToggle}
61
+ tag={undefined}
62
+ >
63
+ {children}
64
+ </InternalSideNavigationGroup>
65
+ );
66
+ };
67
+
68
+ const ProfileDropdownDivider: FC = () => {
69
+ const { breakpoint } = useTitanLayoutContext();
70
+ return breakpoint.isMobile ? (
71
+ <InternalSideNavigationGroupDivider />
72
+ ) : (
73
+ <DesktopProfileDropdown.Divider />
74
+ );
75
+ };
76
+
77
+ const getText = (props: any): string | undefined => {
78
+ if (typeof props.children === 'string') {
79
+ return props.children;
80
+ }
81
+
82
+ if (typeof props.text === 'string') {
83
+ return props.text;
84
+ }
85
+
86
+ return undefined;
87
+ };
88
+
89
+ const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = props => {
90
+ const { breakpoint } = useTitanLayoutContext();
91
+ return breakpoint.isMobile ? (
92
+ <MobileProfileDropdownSection {...props} />
93
+ ) : (
94
+ <DesktopProfileDropdown.Section {...props} />
95
+ );
96
+ };
97
+ const MobileProfileDropdownSection: FC<ProfileDropdownSectionProps> = props => {
98
+ const text = getText(props);
99
+ return text ? (
100
+ <InternalSideNavigationGroupTrigger id={props.id} title={text} onClick={props.onClick} />
101
+ ) : null;
102
+ };
103
+
104
+ const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = props => {
105
+ const { breakpoint, NavigationComponent } = useTitanLayoutContext();
106
+ return breakpoint.isMobile ? (
107
+ <MobileProfileDropdownLink {...props} navigationComponent={NavigationComponent} />
108
+ ) : (
109
+ <DesktopProfileDropdown.Link {...props} />
110
+ );
111
+ };
112
+ const MobileProfileDropdownLink: FC<ProfileDropdownLinkProps & NavigationComponentProps> = ({
113
+ to,
114
+ navigationComponent,
115
+ ...props
116
+ }) => {
117
+ const text = getText(props);
118
+ return text ? (
119
+ <InternalSideNavigationGroupLink
120
+ {...props}
121
+ to={to}
122
+ title={text}
123
+ navigationComponent={props.external ? ExternalNavComponent : navigationComponent}
124
+ />
125
+ ) : null;
126
+ };
127
+
128
+ export const ProfileDropdown = Object.assign(ProfileDropdownContent, {
129
+ Divider: ProfileDropdownDivider,
130
+ Link: ProfileDropdownLink,
131
+ Section: ProfileDropdownSection,
132
+ });