@servicetitan/navigation 11.0.0-canary.237.ff793b3.0 → 11.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/components/badge-tag.js +7 -2
  2. package/dist/components/badge-tag.js.map +1 -1
  3. package/dist/components/counter-tag.js +10 -2
  4. package/dist/components/counter-tag.js.map +1 -1
  5. package/dist/components/header-navigation/header-navigation-content.js +44 -8
  6. package/dist/components/header-navigation/header-navigation-content.js.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-links.js +49 -13
  8. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  9. package/dist/components/header-navigation/header-navigation-stories.module.less.d.ts +3 -0
  10. package/dist/components/header-navigation/header-navigation.js +178 -46
  11. package/dist/components/header-navigation/header-navigation.js.map +1 -1
  12. package/dist/components/header-navigation/header-navigation.module.less.d.ts +22 -0
  13. package/dist/components/header-navigation/index.js +1 -0
  14. package/dist/components/header-navigation/index.js.map +1 -1
  15. package/dist/components/header-navigation/with-tooltip.js +7 -1
  16. package/dist/components/header-navigation/with-tooltip.js.map +1 -1
  17. package/dist/components/left-navigation/header-navigation-tiny-links.js +62 -15
  18. package/dist/components/left-navigation/header-navigation-tiny-links.js.map +1 -1
  19. package/dist/components/left-navigation/header-navigation-tiny.js +27 -2
  20. package/dist/components/left-navigation/header-navigation-tiny.js.map +1 -1
  21. package/dist/components/left-navigation/header-navigation-tiny.module.less.d.ts +15 -0
  22. package/dist/components/left-navigation/index.d.ts +1 -1
  23. package/dist/components/left-navigation/index.d.ts.map +1 -1
  24. package/dist/components/left-navigation/index.js +1 -1
  25. package/dist/components/left-navigation/index.js.map +1 -1
  26. package/dist/components/left-navigation/interface-internal.js +2 -1
  27. package/dist/components/left-navigation/interface-internal.js.map +1 -1
  28. package/dist/components/left-navigation/interface.js +2 -1
  29. package/dist/components/left-navigation/interface.js.map +1 -1
  30. package/dist/components/left-navigation/side-navigation-context.js +4 -3
  31. package/dist/components/left-navigation/side-navigation-context.js.map +1 -1
  32. package/dist/components/left-navigation/side-navigation-links-internal.js +76 -16
  33. package/dist/components/left-navigation/side-navigation-links-internal.js.map +1 -1
  34. package/dist/components/left-navigation/side-navigation-links.js +34 -13
  35. package/dist/components/left-navigation/side-navigation-links.js.map +1 -1
  36. package/dist/components/left-navigation/side-navigation.js +314 -85
  37. package/dist/components/left-navigation/side-navigation.js.map +1 -1
  38. package/dist/components/left-navigation/side-navigation.module.less.d.ts +48 -0
  39. package/dist/components/left-navigation/with-tooltip.js +12 -1
  40. package/dist/components/left-navigation/with-tooltip.js.map +1 -1
  41. package/dist/components/links.js +28 -7
  42. package/dist/components/links.js.map +1 -1
  43. package/dist/components/logo/logo-company-title.js +19 -3
  44. package/dist/components/logo/logo-company-title.js.map +1 -1
  45. package/dist/components/logo/logo-titan-text.js +50 -6
  46. package/dist/components/logo/logo-titan-text.js.map +1 -1
  47. package/dist/components/logo/logo-titan-text.module.less.d.ts +6 -0
  48. package/dist/components/logo/logo-titan.d.ts +1 -0
  49. package/dist/components/logo/logo-titan.d.ts.map +1 -1
  50. package/dist/components/logo/logo-titan.js +53 -8
  51. package/dist/components/logo/logo-titan.js.map +1 -1
  52. package/dist/components/profile-dropdown/profile-dropdown.d.ts +2 -0
  53. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  54. package/dist/components/profile-dropdown/profile-dropdown.js +176 -32
  55. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  56. package/dist/components/profile-dropdown/profile-dropdown.module.less +20 -8
  57. package/dist/components/profile-dropdown/profile-dropdown.module.less.d.ts +23 -0
  58. package/dist/components/profile-dropdown/profile-icon.js +49 -3
  59. package/dist/components/profile-dropdown/profile-icon.js.map +1 -1
  60. package/dist/components/titan-layout/index.d.ts +2 -2
  61. package/dist/components/titan-layout/index.d.ts.map +1 -1
  62. package/dist/components/titan-layout/index.js +1 -2
  63. package/dist/components/titan-layout/index.js.map +1 -1
  64. package/dist/components/titan-layout/interface-internal.js +2 -1
  65. package/dist/components/titan-layout/interface-internal.js.map +1 -1
  66. package/dist/components/titan-layout/interface.js +2 -1
  67. package/dist/components/titan-layout/interface.js.map +1 -1
  68. package/dist/components/titan-layout/layout-context.js +15 -6
  69. package/dist/components/titan-layout/layout-context.js.map +1 -1
  70. package/dist/components/titan-layout/layout-header-dark.d.ts +10 -0
  71. package/dist/components/titan-layout/layout-header-dark.d.ts.map +1 -0
  72. package/dist/components/titan-layout/layout-header-dark.js +146 -0
  73. package/dist/components/titan-layout/layout-header-dark.js.map +1 -0
  74. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -1
  75. package/dist/components/titan-layout/layout-header-links.js +61 -15
  76. package/dist/components/titan-layout/layout-header-links.js.map +1 -1
  77. package/dist/components/titan-layout/layout-header.d.ts +2 -6
  78. package/dist/components/titan-layout/layout-header.d.ts.map +1 -1
  79. package/dist/components/titan-layout/layout-header.js +46 -2
  80. package/dist/components/titan-layout/layout-header.js.map +1 -1
  81. package/dist/components/titan-layout/layout-header.module.less +320 -90
  82. package/dist/components/titan-layout/layout-header.module.less.d.ts +34 -0
  83. package/dist/components/titan-layout/layout-logo.d.ts +5 -3
  84. package/dist/components/titan-layout/layout-logo.d.ts.map +1 -1
  85. package/dist/components/titan-layout/layout-logo.js +45 -9
  86. package/dist/components/titan-layout/layout-logo.js.map +1 -1
  87. package/dist/components/titan-layout/layout-logo.stories.d.ts +15 -4
  88. package/dist/components/titan-layout/layout-logo.stories.d.ts.map +1 -1
  89. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -1
  90. package/dist/components/titan-layout/layout-profile.js +87 -31
  91. package/dist/components/titan-layout/layout-profile.js.map +1 -1
  92. package/dist/components/titan-layout/layout-sidebar-links-internal.js +162 -36
  93. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -1
  94. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -1
  95. package/dist/components/titan-layout/layout-sidebar-links.js +33 -13
  96. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -1
  97. package/dist/components/titan-layout/layout-sidebar.js +198 -34
  98. package/dist/components/titan-layout/layout-sidebar.js.map +1 -1
  99. package/dist/components/titan-layout/layout-sidebar.module.less +6 -2
  100. package/dist/components/titan-layout/layout-sidebar.module.less.d.ts +49 -0
  101. package/dist/components/titan-layout/notifications-context.js +20 -10
  102. package/dist/components/titan-layout/notifications-context.js.map +1 -1
  103. package/dist/components/titan-layout/titan-layout.d.ts +7 -8
  104. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -1
  105. package/dist/components/titan-layout/titan-layout.js +275 -121
  106. package/dist/components/titan-layout/titan-layout.js.map +1 -1
  107. package/dist/components/titan-layout/titan-layout.module.less +9 -2
  108. package/dist/components/titan-layout/titan-layout.module.less.d.ts +17 -0
  109. package/dist/components/titan-layout/titan-layout.stories.d.ts +6 -0
  110. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -1
  111. package/dist/components/titan-layout/with-tooltip.d.ts +4 -1
  112. package/dist/components/titan-layout/with-tooltip.d.ts.map +1 -1
  113. package/dist/components/titan-layout/with-tooltip.js +13 -1
  114. package/dist/components/titan-layout/with-tooltip.js.map +1 -1
  115. package/dist/index.d.ts +4 -3
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +2 -3
  118. package/dist/index.js.map +1 -1
  119. package/dist/test/data-stories.module.less.d.ts +3 -0
  120. package/dist/test/data.js +223 -90
  121. package/dist/test/data.js.map +1 -1
  122. package/dist/utils/counter-tag.js +2 -1
  123. package/dist/utils/counter-tag.js.map +1 -1
  124. package/dist/utils/navigation-context.js +12 -6
  125. package/dist/utils/navigation-context.js.map +1 -1
  126. package/dist/utils/navigation-legacy.js +2 -1
  127. package/dist/utils/navigation-legacy.js.map +1 -1
  128. package/dist/utils/navigation.js +2 -1
  129. package/dist/utils/navigation.js.map +1 -1
  130. package/dist/utils/side-nav.js +9 -6
  131. package/dist/utils/side-nav.js.map +1 -1
  132. package/dist/utils/use-breakpoint.js +12 -9
  133. package/dist/utils/use-breakpoint.js.map +1 -1
  134. package/package.json +4 -4
  135. package/src/components/left-navigation/index.ts +1 -1
  136. package/src/components/logo/logo-titan.tsx +3 -1
  137. package/src/components/profile-dropdown/profile-dropdown.module.less +20 -8
  138. package/src/components/profile-dropdown/profile-dropdown.module.less.d.ts +2 -0
  139. package/src/components/profile-dropdown/profile-dropdown.tsx +45 -13
  140. package/src/components/titan-layout/index.ts +2 -2
  141. package/src/components/titan-layout/layout-header-dark.tsx +186 -0
  142. package/src/components/titan-layout/layout-header-links.tsx +3 -2
  143. package/src/components/titan-layout/layout-header.module.less +320 -90
  144. package/src/components/titan-layout/layout-header.module.less.d.ts +20 -2
  145. package/src/components/titan-layout/layout-header.tsx +18 -17
  146. package/src/components/titan-layout/layout-logo.stories.tsx +103 -15
  147. package/src/components/titan-layout/layout-logo.tsx +33 -36
  148. package/src/components/titan-layout/layout-profile.stories.tsx +1 -1
  149. package/src/components/titan-layout/layout-profile.tsx +46 -17
  150. package/src/components/titan-layout/layout-sidebar-links.tsx +5 -1
  151. package/src/components/titan-layout/layout-sidebar.module.less +6 -2
  152. package/src/components/titan-layout/layout-sidebar.tsx +1 -1
  153. package/src/components/titan-layout/titan-layout.module.less +9 -2
  154. package/src/components/titan-layout/titan-layout.module.less.d.ts +2 -1
  155. package/src/components/titan-layout/titan-layout.stories.tsx +82 -20
  156. package/src/components/titan-layout/titan-layout.tsx +115 -125
  157. package/src/components/titan-layout/with-tooltip.tsx +5 -2
  158. package/src/index.ts +4 -5
  159. package/src/utils/use-breakpoint.ts +1 -1
  160. package/dist/components/header-navigation/header-navigation-extra-stacked.stories.js +0 -13
  161. package/dist/components/header-navigation/header-navigation-extra-stacked.stories.js.map +0 -1
  162. package/dist/components/header-navigation/header-navigation-extra.stories.js +0 -29
  163. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +0 -1
  164. package/dist/components/header-navigation/header-navigation-stacked.stories.js +0 -50
  165. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +0 -1
  166. package/dist/components/header-navigation/header-navigation.stories.js +0 -54
  167. package/dist/components/header-navigation/header-navigation.stories.js.map +0 -1
  168. package/dist/components/layout.stories.js +0 -29
  169. package/dist/components/layout.stories.js.map +0 -1
  170. package/dist/components/left-navigation/header-navigation-extra-tiny.stories.js +0 -13
  171. package/dist/components/left-navigation/header-navigation-extra-tiny.stories.js.map +0 -1
  172. package/dist/components/left-navigation/header-navigation-tiny.stories.js +0 -30
  173. package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +0 -1
  174. package/dist/components/left-navigation/side-navigation.stories.js +0 -115
  175. package/dist/components/left-navigation/side-navigation.stories.js.map +0 -1
  176. package/dist/components/logo/logo.stories.js +0 -20
  177. package/dist/components/logo/logo.stories.js.map +0 -1
  178. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js +0 -13
  179. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js.map +0 -1
  180. package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.js +0 -13
  181. package/dist/components/profile-dropdown/profile-dropdown-tiny.stories.js.map +0 -1
  182. package/dist/components/profile-dropdown/profile-dropdown.stories.js +0 -51
  183. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +0 -1
  184. package/dist/components/titan-layout/layout-logo.stories.js +0 -17
  185. package/dist/components/titan-layout/layout-logo.stories.js.map +0 -1
  186. package/dist/components/titan-layout/layout-profile.stories.js +0 -13
  187. package/dist/components/titan-layout/layout-profile.stories.js.map +0 -1
  188. package/dist/components/titan-layout/titan-layout.stories.js +0 -83
  189. package/dist/components/titan-layout/titan-layout.stories.js.map +0 -1
@@ -1,2 +1,3 @@
1
- export {};
1
+ export { };
2
+
2
3
  //# sourceMappingURL=navigation-legacy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-legacy.js","sourceRoot":"","sources":["../../src/utils/navigation-legacy.ts"],"names":[],"mappings":""}
1
+ {"version":3,"sources":["../../src/utils/navigation-legacy.ts"],"sourcesContent":["import { IconProps } from '@servicetitan/anvil2';\nimport { IconPropsStrict } from '@servicetitan/design-system';\nimport { FC, HTMLAttributeAnchorTarget } from 'react';\nimport { CounterTagData, CounterTagValue } from './counter-tag';\nimport { NavigationSubmenuData } from './navigation';\n\nexport interface HeaderNavigationItemData extends HeaderNavigationItemLinkProps {\n /** link description */\n hint: string;\n\n /** flag if the link is not shown (based on FG and/or user permissions) */\n isHidden?: boolean;\n\n /** custom className (can be used for mdi icons) */\n iconClassName?: string;\n\n /** anvil's icon name of item */\n iconName?: IconPropsStrict['name'];\n\n /** svg icon (anvil2) of inactive item */\n icon: IconProps['svg'] | undefined;\n\n /** svg icon (anvil2) of active item */\n iconActive: IconProps['svg'] | undefined;\n\n /** icon component of item (<svg />) */\n iconComponent?: FC;\n\n /** item tag (optional). shown if it is set and true or greater than 0 */\n counter?: CounterTagValue;\n tag?: CounterTagData;\n\n /** class name of link item */\n className?: string;\n\n /** optional submenu of link item */\n submenu?: NavigationSubmenuData;\n}\n\nexport interface HeaderNavigationItemLinkProps {\n /** link id */\n id: string;\n\n /** link href */\n to: string;\n\n /** link title */\n title: string;\n\n /** callback to return active state. By default, it compares link href with current pathname */\n isActive?: boolean | ((pathname: string) => boolean);\n}\n\nexport interface HeaderNavigationTriggerPropsStrict {\n /** unique identifier */\n id: string;\n /** item title (used for mobile) */\n title: string;\n /** tooltip text */\n tooltip?: string;\n /** item description */\n hint?: string;\n /** container class name */\n className?: string;\n /** item label */\n label?: string;\n /** label class name */\n labelClassName?: string;\n /** isActive */\n isActive?: boolean;\n /** counter value shown for item */\n counter?: CounterTagValue;\n tag?: CounterTagData;\n /** counter component class name */\n counterClassName?: string;\n /** icon component class name */\n iconClassName?: string;\n /** IconComponent custom icon component */\n iconComponent?: FC;\n /** iconName name of anvil icon */\n iconName?: IconPropsStrict['name'];\n /** svg icon (anvil2) of inactive item */\n icon: IconProps['svg'] | undefined;\n /** svg icon (anvil2) of active item */\n iconActive?: IconProps['svg'];\n}\n\nexport interface HeaderNavigationTriggerProps extends HeaderNavigationTriggerPropsStrict {\n /** unstrict props */\n [key: string]: any;\n}\n\nexport interface HeaderNavigationLinkPropsStrict\n extends Omit<HeaderNavigationTriggerPropsStrict, 'isActive'> {\n /** link href */\n to: string;\n /** isActive */\n isActive?: boolean | ((pathname: string) => boolean);\n /** link html target */\n target?: HTMLAttributeAnchorTarget;\n}\n\nexport interface HeaderNavigationLinkProps extends HeaderNavigationLinkPropsStrict {\n /** unstrict props */\n [key: string]: any;\n}\n"],"names":[],"mappings":"AAsGA,WAGC"}
@@ -1,2 +1,3 @@
1
- export {};
1
+ export { };
2
+
2
3
  //# sourceMappingURL=navigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/utils/navigation.ts"],"names":[],"mappings":""}
1
+ {"version":3,"sources":["../../src/utils/navigation.ts"],"sourcesContent":["import { IconProps } from '@servicetitan/anvil2';\nimport { FC } from 'react';\nimport { CounterTagData, CounterTagValue } from './counter-tag';\n\nexport interface NavigationItemData extends NavigationLinkData {\n /** flag if the link is not shown (based on FG and/or user permissions) */\n isHidden?: boolean;\n\n /** custom className (can be used for mdi icons) */\n iconClassName?: string;\n\n /** svg icon (anvil2) of inactive item */\n icon: IconProps['svg'] | undefined;\n\n /** svg icon (anvil2) of active item */\n iconActive: IconProps['svg'] | undefined;\n\n /** icon component of item (<svg />) */\n iconComponent?: FC;\n\n /** item tag (optional). shown if it is set and true or greater than 0 */\n counter?: CounterTagValue;\n tag?: CounterTagData;\n\n /** class name of link item */\n className?: string;\n\n /** optional submenu of link item */\n submenu?: NavigationSubmenuData;\n}\n\nexport interface NavigationLinkData {\n /** link id */\n id: string;\n\n /** link href */\n to: string;\n\n /** link title */\n title: string;\n\n /** callback to return active state. By default, it compares link href with current pathname */\n isActive?: boolean | ((pathname: string) => boolean);\n}\n\nexport interface NavigationSubmenuData {\n /** submenu groups */\n groups: NavigationSubmenuGroupData[];\n}\n\nexport interface NavigationSubmenuItemData extends NavigationLinkData {\n /** item tag (optional) value. shown if it is set and true or greater than 0 */\n counter?: CounterTagValue;\n tag?: CounterTagData;\n}\n\nexport interface NavigationSubmenuGroupData {\n /** submenu group title */\n title: string;\n\n /** submenu group links */\n links: NavigationSubmenuItemData[];\n}\n"],"names":[],"mappings":"AAwDA,WAMC"}
@@ -3,8 +3,8 @@ export function getSubmenuGroupTag(submenu, defaultTag) {
3
3
  return defaultTag;
4
4
  }
5
5
  let tagValue = undefined;
6
- for (const group of submenu.groups) {
7
- for (const link of group.links) {
6
+ for (const group of submenu.groups){
7
+ for (const link of group.links){
8
8
  const ltv = link.counter;
9
9
  if (ltv) {
10
10
  if (typeof ltv === 'number') {
@@ -12,8 +12,7 @@ export function getSubmenuGroupTag(submenu, defaultTag) {
12
12
  tagValue = 0;
13
13
  }
14
14
  tagValue += ltv;
15
- }
16
- else if (typeof tagValue !== 'number') {
15
+ } else if (typeof tagValue !== 'number') {
17
16
  tagValue = true;
18
17
  }
19
18
  }
@@ -21,8 +20,12 @@ export function getSubmenuGroupTag(submenu, defaultTag) {
21
20
  }
22
21
  return tagValue ? getCounterTag(tagValue) : defaultTag;
23
22
  }
24
- export const getCounterTag = (counter, tag) => {
23
+ export const getCounterTag = (counter, tag)=>{
25
24
  const value = counter !== null && counter !== void 0 ? counter : tag === null || tag === void 0 ? void 0 : tag.value;
26
- return value ? { value, className: '' } : undefined;
25
+ return value ? {
26
+ value,
27
+ className: ''
28
+ } : undefined;
27
29
  };
30
+
28
31
  //# sourceMappingURL=side-nav.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"side-nav.js","sourceRoot":"","sources":["../../src/utils/side-nav.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,kBAAkB,CAC9B,OAA0C,EAC1C,UAAuC;IAEvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,IAAI,QAAQ,GAAiC,SAAS,CAAC;IAEvD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAiC,IAAI,CAAC,OAAO,CAAC;YAEvD,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;oBAC1B,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;wBAC/B,QAAQ,GAAG,CAAC,CAAC;oBACjB,CAAC;oBACD,QAAQ,IAAI,GAAG,CAAC;gBACpB,CAAC;qBAAM,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBACtC,QAAQ,GAAG,IAAI,CAAC;gBACpB,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CACzB,OAAoC,EACpC,GAAoB,EACO,EAAE;IAC7B,MAAM,KAAK,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,CAAC;IAEpC,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC,CAAC"}
1
+ {"version":3,"sources":["../../src/utils/side-nav.ts"],"sourcesContent":["import { CounterTagProps } from '../components/counter-tag';\nimport { CounterTagData, CounterTagValue } from './counter-tag';\nimport { NavigationSubmenuData } from './navigation';\n\nexport function getSubmenuGroupTag(\n submenu: NavigationSubmenuData | undefined,\n defaultTag: CounterTagProps | undefined\n): CounterTagProps | undefined {\n if (!submenu) {\n return defaultTag;\n }\n\n let tagValue: number | boolean | undefined = undefined;\n\n for (const group of submenu.groups) {\n for (const link of group.links) {\n const ltv: number | boolean | undefined = link.counter;\n\n if (ltv) {\n if (typeof ltv === 'number') {\n if (typeof tagValue !== 'number') {\n tagValue = 0;\n }\n tagValue += ltv;\n } else if (typeof tagValue !== 'number') {\n tagValue = true;\n }\n }\n }\n }\n\n return tagValue ? getCounterTag(tagValue) : defaultTag;\n}\n\nexport const getCounterTag = (\n counter: CounterTagValue | undefined,\n tag?: CounterTagData\n): CounterTagProps | undefined => {\n const value = counter ?? tag?.value;\n\n return value ? { value, className: '' } : undefined;\n};\n"],"names":["getSubmenuGroupTag","submenu","defaultTag","tagValue","undefined","group","groups","link","links","ltv","counter","getCounterTag","tag","value","className"],"mappings":"AAIA,OAAO,SAASA,mBACZC,OAA0C,EAC1CC,UAAuC;IAEvC,IAAI,CAACD,SAAS;QACV,OAAOC;IACX;IAEA,IAAIC,WAAyCC;IAE7C,KAAK,MAAMC,SAASJ,QAAQK,MAAM,CAAE;QAChC,KAAK,MAAMC,QAAQF,MAAMG,KAAK,CAAE;YAC5B,MAAMC,MAAoCF,KAAKG,OAAO;YAEtD,IAAID,KAAK;gBACL,IAAI,OAAOA,QAAQ,UAAU;oBACzB,IAAI,OAAON,aAAa,UAAU;wBAC9BA,WAAW;oBACf;oBACAA,YAAYM;gBAChB,OAAO,IAAI,OAAON,aAAa,UAAU;oBACrCA,WAAW;gBACf;YACJ;QACJ;IACJ;IAEA,OAAOA,WAAWQ,cAAcR,YAAYD;AAChD;AAEA,OAAO,MAAMS,gBAAgB,CACzBD,SACAE;IAEA,MAAMC,QAAQH,oBAAAA,qBAAAA,UAAWE,gBAAAA,0BAAAA,IAAKC,KAAK;IAEnC,OAAOA,QAAQ;QAAEA;QAAOC,WAAW;IAAG,IAAIV;AAC9C,EAAE"}
@@ -1,14 +1,17 @@
1
1
  import { useBreakpoint } from '@servicetitan/anvil2';
2
2
  import { useMemo } from 'react';
3
- export const useTitanBreakpoint = () => {
3
+ export const useTitanBreakpoint = ()=>{
4
4
  const breakpoint = useBreakpoint();
5
- return useMemo(() => {
6
- var _a, _b;
7
- return ({
8
- name: (_a = breakpoint === null || breakpoint === void 0 ? void 0 : breakpoint.name) !== null && _a !== void 0 ? _a : 'xl',
9
- isMobile: breakpoint ? breakpoint.innerWidth <= 768 : false,
10
- width: (_b = breakpoint === null || breakpoint === void 0 ? void 0 : breakpoint.innerWidth) !== null && _b !== void 0 ? _b : 0,
11
- });
12
- }, [breakpoint]);
5
+ return useMemo(()=>{
6
+ var _breakpoint_name, _breakpoint_innerWidth;
7
+ return {
8
+ name: (_breakpoint_name = breakpoint === null || breakpoint === void 0 ? void 0 : breakpoint.name) !== null && _breakpoint_name !== void 0 ? _breakpoint_name : 'xl',
9
+ isMobile: breakpoint ? breakpoint.innerWidth < 768 : false,
10
+ width: (_breakpoint_innerWidth = breakpoint === null || breakpoint === void 0 ? void 0 : breakpoint.innerWidth) !== null && _breakpoint_innerWidth !== void 0 ? _breakpoint_innerWidth : 0
11
+ };
12
+ }, [
13
+ breakpoint
14
+ ]);
13
15
  };
16
+
14
17
  //# sourceMappingURL=use-breakpoint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-breakpoint.js","sourceRoot":"","sources":["../../src/utils/use-breakpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAQhC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAoB,EAAE;IACpD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,OAAO,OAAO,CACV,GAAG,EAAE;;QAAC,OAAA,CAAC;YACH,IAAI,EAAE,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,IAAI,mCAAI,IAAI;YAC9B,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK;YAC3D,KAAK,EAAE,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,UAAU,mCAAI,CAAC;SACrC,CAAC,CAAA;KAAA,EACF,CAAC,UAAU,CAAC,CACf,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"sources":["../../src/utils/use-breakpoint.ts"],"sourcesContent":["import { BreakpointReturnProps, useBreakpoint } from '@servicetitan/anvil2';\nimport { useMemo } from 'react';\n\nexport interface TitanBreakpoint {\n name: BreakpointReturnProps['name'];\n isMobile: boolean;\n width: number;\n}\n\nexport const useTitanBreakpoint = (): TitanBreakpoint => {\n const breakpoint = useBreakpoint();\n\n return useMemo(\n () => ({\n name: breakpoint?.name ?? 'xl',\n isMobile: breakpoint ? breakpoint.innerWidth < 768 : false,\n width: breakpoint?.innerWidth ?? 0,\n }),\n [breakpoint]\n );\n};\n"],"names":["useBreakpoint","useMemo","useTitanBreakpoint","breakpoint","name","isMobile","innerWidth","width"],"mappings":"AAAA,SAAgCA,aAAa,QAAQ,uBAAuB;AAC5E,SAASC,OAAO,QAAQ,QAAQ;AAQhC,OAAO,MAAMC,qBAAqB;IAC9B,MAAMC,aAAaH;IAEnB,OAAOC,QACH;YACUE,kBAECA;eAHJ;YACHC,MAAMD,CAAAA,mBAAAA,uBAAAA,iCAAAA,WAAYC,IAAI,cAAhBD,8BAAAA,mBAAoB;YAC1BE,UAAUF,aAAaA,WAAWG,UAAU,GAAG,MAAM;YACrDC,OAAOJ,CAAAA,yBAAAA,uBAAAA,iCAAAA,WAAYG,UAAU,cAAtBH,oCAAAA,yBAA0B;QACrC;OACA;QAACA;KAAW;AAEpB,EAAE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/navigation",
3
- "version": "11.0.0-canary.237.ff793b3.0",
3
+ "version": "11.1.0",
4
4
  "description": "Navigation components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,9 +26,9 @@
26
26
  "react": ">=18.0.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@servicetitan/anvil2": "~1.47.1",
29
+ "@servicetitan/anvil2": "~1.49.2",
30
30
  "@servicetitan/design-system": "~14.5.1",
31
- "@servicetitan/react-ioc": "^30.3.1",
31
+ "@servicetitan/react-ioc": "^32.6.0",
32
32
  "@servicetitan/tokens": ">=12.1.11",
33
33
  "@testing-library/react": "^16.2.0",
34
34
  "mobx": "~6.10.2",
@@ -42,5 +42,5 @@
42
42
  "less": true,
43
43
  "webpack": false
44
44
  },
45
- "gitHead": "ff793b337eca5999e2472d38757b0618e5331fd9"
45
+ "gitHead": "e3dfbcd9f507c9f4373502a0e0d835f8e9fe2f2a"
46
46
  }
@@ -1,4 +1,4 @@
1
1
  export * from './header-navigation-tiny';
2
2
  export * from './side-navigation';
3
3
  export * from './side-navigation-links';
4
- export * from './interface';
4
+ export type * from './interface';
@@ -1,6 +1,7 @@
1
1
  import { FC } from 'react';
2
2
 
3
3
  export interface LogoTitanSvgProps {
4
+ className?: string;
4
5
  height?: number;
5
6
  width?: number;
6
7
  fill?: string;
@@ -13,11 +14,12 @@ export const LogoTitanSvg: FC<LogoTitanSvgProps> = props => {
13
14
  width: props.width ?? 116,
14
15
  height: props.height ?? 106,
15
16
  };
16
- const fill = props.fill ?? '#3A3A3A';
17
+ const fill = props.fill ?? 'currentColor';
17
18
  const mantleFill = props.mantleFill ?? fill;
18
19
 
19
20
  return (
20
21
  <svg
22
+ className={props.className}
21
23
  xmlns="http://www.w3.org/2000/svg"
22
24
  xmlnsXlink="http://www.w3.org/1999/xlink"
23
25
  {...dimensions}
@@ -123,6 +123,11 @@
123
123
 
124
124
  .dropdown-section {
125
125
  padding: @spacing-1 @spacing-2;
126
+ position: relative;
127
+
128
+ &.dropdown-section-with-counter {
129
+ padding-right: @spacing-3;
130
+ }
126
131
  }
127
132
 
128
133
  .dropdown-link {
@@ -136,15 +141,22 @@
136
141
  }
137
142
  }
138
143
 
139
- .counter {
140
- color: @color-white;
141
- font-size: @typescale-0;
142
- font-weight: @font-weight-semibold;
144
+ .counter-wrapper {
143
145
  position: absolute;
144
- top: @spacing-half;
145
- margin-left: @spacing-half;
146
- min-width: 12px !important;
147
- min-height: 12px !important;
146
+ top: 0;
147
+ bottom: 0;
148
+ right: @spacing-1;
149
+
150
+ display: flex;
151
+ align-items: center;
152
+
153
+ .counter {
154
+ color: @color-white;
155
+ font-size: @typescale-0;
156
+ font-weight: @font-weight-semibold;
157
+ min-width: 12px !important;
158
+ min-height: 12px !important;
159
+ }
148
160
  }
149
161
  }
150
162
 
@@ -4,12 +4,14 @@ export const badge: string;
4
4
  export const badgeNoContent: string;
5
5
  export const badgeWithContent: string;
6
6
  export const counter: string;
7
+ export const counterWrapper: string;
7
8
  export const dropdown: string;
8
9
  export const dropdownContent: string;
9
10
  export const dropdownContentBottomLeft: string;
10
11
  export const dropdownContentWrapper: string;
11
12
  export const dropdownLink: string;
12
13
  export const dropdownSection: string;
14
+ export const dropdownSectionWithCounter: string;
13
15
  export const expandIcon: string;
14
16
  export const hint: string;
15
17
  export const hintContent: string;
@@ -96,7 +96,11 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
96
96
  ) : isLegacy ? (
97
97
  <ProfileLogo />
98
98
  ) : (
99
- <Icon size="large" svg={open ? SvgAccountActive : SvgAccountInactive} />
99
+ <Icon
100
+ className="c-inherit-i"
101
+ size="large"
102
+ svg={open ? SvgAccountActive : SvgAccountInactive}
103
+ />
100
104
  )}
101
105
 
102
106
  {!!info && (
@@ -121,7 +125,7 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
121
125
 
122
126
  <Icon
123
127
  svg={open ? SvgExpandLess : SvgExpandMore}
124
- className={classNames(Styles.expandIcon)}
128
+ className={classNames(Styles.expandIcon, 'c-inherit-i')}
125
129
  size="small"
126
130
  />
127
131
 
@@ -148,6 +152,17 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
148
152
  );
149
153
  };
150
154
 
155
+ const useTag = (counter?: CounterTagValue, tag?: CounterTagData) =>
156
+ useMemo(() => {
157
+ const data = getCounterTag(counter, tag);
158
+
159
+ return data ? (
160
+ <div className={Styles.counterWrapper}>
161
+ <CounterTag className={Styles.counter} data={data} />
162
+ </div>
163
+ ) : undefined;
164
+ }, [counter, tag]);
165
+
151
166
  export type ProfileItemContent =
152
167
  | { children: string; text?: string }
153
168
  | { children: ReactNode; text: string };
@@ -157,6 +172,8 @@ export interface ProfileDropdownSectionPropsStrict {
157
172
  id: string;
158
173
  tooltip?: string;
159
174
  className?: string;
175
+ tag?: CounterTagData;
176
+ counter?: CounterTagValue;
160
177
  onClick?(e: MouseEvent): void;
161
178
  }
162
179
 
@@ -167,7 +184,9 @@ export type ProfileDropdownSectionProps = Omit<ComponentPropsWithoutRef<'div'>,
167
184
  export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
168
185
  children,
169
186
  className,
187
+ counter,
170
188
  id,
189
+ tag,
171
190
  text,
172
191
  tooltip,
173
192
  onClick,
@@ -181,20 +200,26 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
181
200
  }
182
201
  };
183
202
 
203
+ const tagElement = useTag(counter, tag);
204
+
184
205
  return withTooltip(
185
206
  <div
186
- className={classNames(Styles.dropdownSection, className, {
187
- 'cursor-pointer': !!onClick,
188
- })}
207
+ className={classNames(
208
+ Styles.dropdownSection,
209
+ tagElement && Styles.dropdownSectionWithCounter,
210
+ !!onClick && Styles.dropdownLink,
211
+ className
212
+ )}
189
213
  onClick={clickHandler}
190
214
  data-cy={`profile-dropdown-section-${id}`}
191
215
  data-pendo={`profile-dropdown-section-${id}`}
192
216
  {...rest}
193
217
  >
194
218
  {children}
219
+ {tagElement}
195
220
  </div>,
196
221
  tooltip,
197
- 'left'
222
+ { placement: 'left' }
198
223
  );
199
224
  };
200
225
 
@@ -234,15 +259,17 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
234
259
 
235
260
  const isExternalLink = external ?? to?.startsWith('http');
236
261
 
237
- const tagElement = useMemo(
238
- () => <CounterTag data={getCounterTag(counter, tag)} className={Styles.counter} />,
239
- [counter, tag]
240
- );
262
+ const tagElement = useTag(counter, tag);
241
263
 
242
264
  return withTooltip(
243
265
  isExternalLink ? (
244
266
  <a
245
- className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
267
+ className={classNames(
268
+ Styles.dropdownSection,
269
+ tagElement && Styles.dropdownSectionWithCounter,
270
+ Styles.dropdownLink,
271
+ className
272
+ )}
246
273
  href={to}
247
274
  target={target}
248
275
  data-cy={`profile-dropdown-link-${id}`}
@@ -254,7 +281,12 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
254
281
  </a>
255
282
  ) : (
256
283
  <NavigationComponent
257
- className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
284
+ className={classNames(
285
+ Styles.dropdownSection,
286
+ Styles.dropdownLink,
287
+ { [Styles.dropdownSectionWithCounter]: !!tagElement },
288
+ className
289
+ )}
258
290
  target={target}
259
291
  to={to}
260
292
  data-cy={`profile-dropdown-link-${id}`}
@@ -266,7 +298,7 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
266
298
  </NavigationComponent>
267
299
  ),
268
300
  tooltip,
269
- 'left'
301
+ { placement: 'left' }
270
302
  );
271
303
  };
272
304
 
@@ -1,5 +1,5 @@
1
1
  export * from './titan-layout';
2
2
  export * from './layout-profile';
3
3
  export * from './layout-context';
4
- export * from './layout-logo';
5
- export * from './interface';
4
+ export type { TitanLayoutLogoProps } from './layout-logo';
5
+ export type * from './interface';
@@ -0,0 +1,186 @@
1
+ import { ButtonCompound, Icon, Menu } from '@servicetitan/anvil2';
2
+ import SvgMoreVert from '@servicetitan/anvil2/assets/icons/material/round/more_vert.svg';
3
+ import classNames from 'classnames';
4
+ import { FC, useCallback, useEffect, useRef, useState } from 'react';
5
+ import { NavigationItemData } from '../../utils/navigation';
6
+ import { LayoutHeader, LayoutHeaderProps } from './layout-header';
7
+ import { LayoutHeaderNavigationLink } from './layout-header-links';
8
+ import * as Styles from './layout-header.module.less';
9
+ import { withTooltip } from './with-tooltip';
10
+
11
+ function useForceUpdate() {
12
+ const [, setTick] = useState(0);
13
+ return useCallback(() => {
14
+ setTick(tick => tick + 1);
15
+ }, []);
16
+ }
17
+
18
+ enum MinimizedState {
19
+ Calculating,
20
+ Minimized,
21
+ Full,
22
+ }
23
+
24
+ interface LayoutHeaderStackedProps extends Omit<LayoutHeaderProps, 'variant'> {
25
+ navigationMainItems?: NavigationItemData[];
26
+ navigationOverflowItems?: NavigationItemData[];
27
+ }
28
+
29
+ export const LayoutHeaderDark: FC<LayoutHeaderStackedProps> = ({
30
+ className,
31
+ isMobile,
32
+ navigationMainItems,
33
+ navigationOverflowItems,
34
+ hasNotifications,
35
+ onBurgerClick,
36
+ logo,
37
+ profile,
38
+ right,
39
+ rightText,
40
+ rightClassName,
41
+ center,
42
+ centerClassName,
43
+ ...rest
44
+ }) => {
45
+ return center ? (
46
+ <div
47
+ className={classNames(Styles.headerStacked, className)}
48
+ data-cy="header-navigation"
49
+ {...rest}
50
+ >
51
+ <LayoutHeader
52
+ variant="dark"
53
+ right={right}
54
+ rightText={rightText}
55
+ rightClassName={rightClassName}
56
+ center={center}
57
+ centerClassName={centerClassName}
58
+ isMobile={isMobile}
59
+ hasNotifications={hasNotifications}
60
+ logo={logo}
61
+ profile={profile}
62
+ onBurgerClick={onBurgerClick}
63
+ data-cy="header-navigation-top"
64
+ />
65
+
66
+ {!isMobile && (
67
+ <LayoutHeaderNav
68
+ className={Styles.headerStackedNav}
69
+ mainItems={navigationMainItems}
70
+ overflowItems={navigationOverflowItems}
71
+ />
72
+ )}
73
+ </div>
74
+ ) : (
75
+ <LayoutHeader
76
+ variant="dark"
77
+ className={classNames(className, !isMobile && Styles.headerDesktopNav)}
78
+ right={right}
79
+ rightText={rightText}
80
+ rightClassName={rightClassName}
81
+ center={
82
+ isMobile ? undefined : (
83
+ <LayoutHeaderNav
84
+ mainItems={navigationMainItems}
85
+ overflowItems={navigationOverflowItems}
86
+ />
87
+ )
88
+ }
89
+ centerClassName={centerClassName}
90
+ isMobile={isMobile}
91
+ hasNotifications={hasNotifications}
92
+ logo={logo}
93
+ profile={profile}
94
+ onBurgerClick={onBurgerClick}
95
+ {...rest}
96
+ />
97
+ );
98
+ };
99
+
100
+ interface LayoutHeaderNavProps {
101
+ className?: string;
102
+ mainItems?: NavigationItemData[];
103
+ overflowItems?: NavigationItemData[];
104
+ }
105
+ const LayoutHeaderNav: FC<LayoutHeaderNavProps> = ({ className, mainItems, overflowItems }) => {
106
+ const containerRef = useRef<HTMLDivElement>(null);
107
+ const navigationRef = useRef<HTMLDivElement>(null);
108
+ const forceUpdate = useForceUpdate();
109
+ const [minimized, setMinimized] = useState(MinimizedState.Calculating);
110
+
111
+ useEffect(() => {
112
+ const handleResize = () => {
113
+ setMinimized(MinimizedState.Calculating);
114
+ forceUpdate();
115
+ };
116
+
117
+ window.addEventListener('resize', handleResize);
118
+ return () => window.removeEventListener('resize', handleResize);
119
+ }, [forceUpdate]);
120
+
121
+ const updateIsMinimized = () => {
122
+ if (containerRef.current && navigationRef.current) {
123
+ if (navigationRef.current.clientWidth + 16 > containerRef.current.clientWidth) {
124
+ setMinimized(MinimizedState.Minimized);
125
+ } else if (minimized === MinimizedState.Calculating) {
126
+ setMinimized(MinimizedState.Full);
127
+ }
128
+ }
129
+ };
130
+
131
+ useEffect(() => {
132
+ updateIsMinimized();
133
+ });
134
+
135
+ useEffect(() => {
136
+ setMinimized(MinimizedState.Calculating);
137
+ forceUpdate();
138
+ }, [forceUpdate]);
139
+
140
+ const isMinimized = minimized === MinimizedState.Minimized;
141
+
142
+ return (
143
+ <div
144
+ ref={containerRef}
145
+ className={classNames(Styles.headerNavigationWrapper, className, {
146
+ [Styles.calculating]: minimized === MinimizedState.Calculating,
147
+ })}
148
+ data-cy="navigation-items"
149
+ >
150
+ <div ref={navigationRef} className={classNames(Styles.headerNavigation)}>
151
+ {mainItems?.map(item =>
152
+ withTooltip(
153
+ <LayoutHeaderNavigationLink
154
+ {...item}
155
+ label={isMinimized ? undefined : item.title}
156
+ key={item.id}
157
+ />,
158
+ isMinimized ? item.title : undefined,
159
+ { key: item.id }
160
+ )
161
+ )}
162
+ </div>
163
+ {!!overflowItems?.length && <LayoutHeaderNavOverflow items={overflowItems} />}
164
+ </div>
165
+ );
166
+ };
167
+
168
+ const LayoutHeaderNavOverflow: FC<{
169
+ items: NavigationItemData[];
170
+ }> = ({ items }) => {
171
+ return (
172
+ <Menu
173
+ trigger={props => (
174
+ <ButtonCompound {...props} className={Styles.headerNavigationOverflowTrigger}>
175
+ <Icon svg={SvgMoreVert} size="medium" />
176
+ </ButtonCompound>
177
+ )}
178
+ contentClassName={Styles.headerNavigationOverflow}
179
+ placement="bottom-end"
180
+ >
181
+ {items.map(item => (
182
+ <LayoutHeaderNavigationLink {...item} label={item.title} key={item.id} />
183
+ ))}
184
+ </Menu>
185
+ );
186
+ };
@@ -66,6 +66,7 @@ export const LayoutHeaderNavigationLink: FC<HeaderNavigationLinkProps> = ({
66
66
  labelClassName,
67
67
  tag,
68
68
  target,
69
+ title,
69
70
  ...rest
70
71
  }) => {
71
72
  const { NavigationComponent } = useTitanLayoutContext();
@@ -77,7 +78,6 @@ export const LayoutHeaderNavigationLink: FC<HeaderNavigationLinkProps> = ({
77
78
  {...rest}
78
79
  key={id}
79
80
  to={to}
80
- title={hint}
81
81
  className={classNames(Styles.navigationLink, className, {
82
82
  [Styles.navigationItemActive]: isActive === true,
83
83
  [Styles.navigationItemIconState]: !!icon && !!iconActive,
@@ -134,7 +134,8 @@ export const LayoutHeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = (
134
134
  >
135
135
  <HeaderNavigationItemContent
136
136
  tag={getCounterTag(counter, tag)}
137
- icon={isActive && iconActive ? iconActive : icon}
137
+ icon={icon}
138
+ iconActive={iconActive}
138
139
  label={label}
139
140
  labelClassName={labelClassName}
140
141
  />