@telefonica/mistica 16.59.0-beta.1 → 16.59.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 (539) hide show
  1. package/css/mistica.css +1 -1
  2. package/dist/accordion.css-mistica.js +16 -16
  3. package/dist/align.css-mistica.js +2 -2
  4. package/dist/autocomplete.css-mistica.js +6 -6
  5. package/dist/avatar.css-mistica.js +3 -3
  6. package/dist/badge.css-mistica.js +7 -7
  7. package/dist/box.css-mistica.js +15 -15
  8. package/dist/boxed.css-mistica.js +31 -31
  9. package/dist/button-group.css-mistica.js +10 -10
  10. package/dist/button-layout.css-mistica.js +21 -21
  11. package/dist/button.css-mistica.js +51 -51
  12. package/dist/callout.css-mistica.js +16 -16
  13. package/dist/card-internal.css-mistica.js +38 -38
  14. package/dist/carousel.css-mistica.js +18 -18
  15. package/dist/checkbox.css-mistica.js +21 -21
  16. package/dist/chip.css-mistica.js +30 -30
  17. package/dist/circle.css-mistica.js +2 -2
  18. package/dist/community/advanced-data-card.css-mistica.js +26 -26
  19. package/dist/community/blocks.css-mistica.js +3 -3
  20. package/dist/community/example-component.css-mistica.js +2 -2
  21. package/dist/counter.css-mistica.js +12 -12
  22. package/dist/cover-hero.css-mistica.js +16 -16
  23. package/dist/credit-card-number-field.css-mistica.js +6 -6
  24. package/dist/date-field.css-mistica.js +1 -1
  25. package/dist/date-time-picker.css-mistica.js +2 -2
  26. package/dist/dialog.css-mistica.js +15 -15
  27. package/dist/divider.css-mistica.js +5 -5
  28. package/dist/double-field.css-mistica.js +4 -4
  29. package/dist/drawer.css-mistica.js +15 -15
  30. package/dist/empty-state-card.css-mistica.js +4 -4
  31. package/dist/empty-state.css-mistica.js +14 -14
  32. package/dist/fade-in.css-mistica.js +1 -1
  33. package/dist/feedback.css-mistica.js +14 -14
  34. package/dist/file-upload.css-mistica.js +14 -14
  35. package/dist/fixed-footer-layout.css-mistica.js +12 -12
  36. package/dist/form.css-mistica.js +2 -2
  37. package/dist/grid-layout.css-mistica.js +9 -9
  38. package/dist/grid.css-mistica.js +147 -147
  39. package/dist/header.css-mistica.js +5 -5
  40. package/dist/hero.css-mistica.js +11 -11
  41. package/dist/horizontal-scroll.css-mistica.js +3 -3
  42. package/dist/icon-button.css-mistica.js +66 -66
  43. package/dist/icons/icon-chevron.css-mistica.js +6 -6
  44. package/dist/icons/icon-error.css-mistica.js +3 -3
  45. package/dist/image.css-mistica.js +11 -11
  46. package/dist/inline.css-mistica.js +16 -16
  47. package/dist/list.css-mistica.js +15 -15
  48. package/dist/loading-bar.css-mistica.js +5 -5
  49. package/dist/loading-screen.css-mistica.js +15 -15
  50. package/dist/logo.css-mistica.js +9 -9
  51. package/dist/menu.css-mistica.js +24 -24
  52. package/dist/mosaic.css-mistica.js +3 -3
  53. package/dist/navigation-bar.css-mistica.js +45 -45
  54. package/dist/navigation-breadcrumbs.css-mistica.js +5 -5
  55. package/dist/package-version.js +2 -2
  56. package/dist/pin-field.css-mistica.js +10 -10
  57. package/dist/popover.css-mistica.js +2 -2
  58. package/dist/progress-bar.css-mistica.js +12 -12
  59. package/dist/radio-button.css-mistica.js +33 -33
  60. package/dist/rating.css-mistica.js +12 -12
  61. package/dist/responsive-layout.css-mistica.js +20 -20
  62. package/dist/screen-reader-only.css-mistica.js +2 -2
  63. package/dist/select.css-mistica.js +29 -29
  64. package/dist/sheet-action-row.css-mistica.js +2 -2
  65. package/dist/sheet-common.css-mistica.js +16 -16
  66. package/dist/sheet-info.css-mistica.js +4 -4
  67. package/dist/skeletons.css-mistica.js +12 -12
  68. package/dist/skins/skin-contract.css-mistica.js +686 -686
  69. package/dist/skip-link.css-mistica.js +3 -3
  70. package/dist/slider.css-mistica.js +28 -28
  71. package/dist/snackbar.css-mistica.js +16 -16
  72. package/dist/spinner.css-mistica.js +5 -5
  73. package/dist/square.css-mistica.js +2 -2
  74. package/dist/stack.css-mistica.js +9 -9
  75. package/dist/stacking-group.css-mistica.js +2 -2
  76. package/dist/stepper.css-mistica.js +16 -16
  77. package/dist/switch-component.css-mistica.js +53 -53
  78. package/dist/table.css-mistica.js +24 -24
  79. package/dist/tabs.css-mistica.js +30 -30
  80. package/dist/tag.css-mistica.js +5 -5
  81. package/dist/text-field-base.css-mistica.js +30 -30
  82. package/dist/text-field-components.css-mistica.js +23 -20
  83. package/dist/text-field-components.css.d.ts +1 -0
  84. package/dist/text-field-components.js +31 -25
  85. package/dist/text-link.css-mistica.js +10 -10
  86. package/dist/text.css-mistica.js +13 -13
  87. package/dist/theme-context.css-mistica.js +2 -2
  88. package/dist/timeline.css-mistica.js +18 -18
  89. package/dist/timer.css-mistica.js +13 -13
  90. package/dist/tooltip.css-mistica.js +12 -12
  91. package/dist/touchable.css-mistica.js +5 -5
  92. package/dist/utils/aspect-ratio-support.css-mistica.js +7 -7
  93. package/dist/video.css-mistica.js +2 -2
  94. package/dist/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +3 -3
  95. package/dist-es/accordion.css-mistica.js +7 -7
  96. package/dist-es/align.css-mistica.js +2 -2
  97. package/dist-es/autocomplete.css-mistica.js +2 -2
  98. package/dist-es/avatar.css-mistica.js +2 -2
  99. package/dist-es/badge.css-mistica.js +2 -2
  100. package/dist-es/box.css-mistica.js +15 -15
  101. package/dist-es/boxed.css-mistica.js +25 -25
  102. package/dist-es/button-group.css-mistica.js +2 -2
  103. package/dist-es/button-layout.css-mistica.js +16 -16
  104. package/dist-es/button.css-mistica.js +38 -38
  105. package/dist-es/callout.css-mistica.js +12 -12
  106. package/dist-es/card-internal.css-mistica.js +20 -20
  107. package/dist-es/carousel.css-mistica.js +10 -10
  108. package/dist-es/checkbox.css-mistica.js +14 -14
  109. package/dist-es/chip.css-mistica.js +17 -17
  110. package/dist-es/circle.css-mistica.js +2 -2
  111. package/dist-es/community/advanced-data-card.css-mistica.js +7 -7
  112. package/dist-es/community/blocks.css-mistica.js +2 -2
  113. package/dist-es/community/example-component.css-mistica.js +2 -2
  114. package/dist-es/counter.css-mistica.js +2 -2
  115. package/dist-es/cover-hero.css-mistica.js +4 -4
  116. package/dist-es/credit-card-number-field.css-mistica.js +4 -4
  117. package/dist-es/date-field.css-mistica.js +1 -1
  118. package/dist-es/date-time-picker.css-mistica.js +2 -2
  119. package/dist-es/dialog.css-mistica.js +5 -5
  120. package/dist-es/divider.css-mistica.js +5 -5
  121. package/dist-es/double-field.css-mistica.js +4 -4
  122. package/dist-es/drawer.css-mistica.js +2 -2
  123. package/dist-es/empty-state-card.css-mistica.js +2 -2
  124. package/dist-es/empty-state.css-mistica.js +7 -7
  125. package/dist-es/fade-in.css-mistica.js +1 -1
  126. package/dist-es/feedback.css-mistica.js +2 -2
  127. package/dist-es/file-upload.css-mistica.js +8 -8
  128. package/dist-es/fixed-footer-layout.css-mistica.js +4 -4
  129. package/dist-es/form.css-mistica.js +2 -2
  130. package/dist-es/grid-layout.css-mistica.js +4 -4
  131. package/dist-es/grid.css-mistica.js +127 -127
  132. package/dist-es/header.css-mistica.js +2 -2
  133. package/dist-es/hero.css-mistica.js +4 -4
  134. package/dist-es/horizontal-scroll.css-mistica.js +2 -2
  135. package/dist-es/icon-button.css-mistica.js +56 -56
  136. package/dist-es/icons/icon-chevron.css-mistica.js +4 -4
  137. package/dist-es/icons/icon-error.css-mistica.js +2 -2
  138. package/dist-es/image.css-mistica.js +4 -4
  139. package/dist-es/inline.css-mistica.js +10 -10
  140. package/dist-es/list.css-mistica.js +2 -2
  141. package/dist-es/loading-bar.css-mistica.js +2 -2
  142. package/dist-es/loading-screen.css-mistica.js +5 -5
  143. package/dist-es/logo.css-mistica.js +7 -7
  144. package/dist-es/menu.css-mistica.js +15 -15
  145. package/dist-es/mosaic.css-mistica.js +2 -2
  146. package/dist-es/navigation-bar.css-mistica.js +20 -20
  147. package/dist-es/navigation-breadcrumbs.css-mistica.js +2 -2
  148. package/dist-es/package-version.js +2 -2
  149. package/dist-es/pin-field.css-mistica.js +2 -2
  150. package/dist-es/popover.css-mistica.js +2 -2
  151. package/dist-es/progress-bar.css-mistica.js +8 -8
  152. package/dist-es/radio-button.css-mistica.js +25 -25
  153. package/dist-es/rating.css-mistica.js +4 -4
  154. package/dist-es/responsive-layout.css-mistica.js +7 -7
  155. package/dist-es/screen-reader-only.css-mistica.js +2 -2
  156. package/dist-es/select.css-mistica.js +20 -20
  157. package/dist-es/sheet-action-row.css-mistica.js +2 -2
  158. package/dist-es/sheet-common.css-mistica.js +2 -2
  159. package/dist-es/sheet-info.css-mistica.js +2 -2
  160. package/dist-es/skeletons.css-mistica.js +8 -8
  161. package/dist-es/skins/skin-contract.css-mistica.js +686 -686
  162. package/dist-es/skip-link.css-mistica.js +2 -2
  163. package/dist-es/slider.css-mistica.js +20 -20
  164. package/dist-es/snackbar.css-mistica.js +5 -5
  165. package/dist-es/spinner.css-mistica.js +2 -2
  166. package/dist-es/square.css-mistica.js +2 -2
  167. package/dist-es/stack.css-mistica.js +7 -7
  168. package/dist-es/stacking-group.css-mistica.js +2 -2
  169. package/dist-es/stepper.css-mistica.js +4 -4
  170. package/dist-es/style.css +1 -1
  171. package/dist-es/switch-component.css-mistica.js +41 -41
  172. package/dist-es/table.css-mistica.js +11 -11
  173. package/dist-es/tabs.css-mistica.js +21 -21
  174. package/dist-es/tag.css-mistica.js +2 -2
  175. package/dist-es/text-field-base.css-mistica.js +17 -17
  176. package/dist-es/text-field-components.css-mistica.js +4 -4
  177. package/dist-es/text-field-components.js +52 -46
  178. package/dist-es/text-link.css-mistica.js +9 -9
  179. package/dist-es/text.css-mistica.js +8 -8
  180. package/dist-es/theme-context.css-mistica.js +2 -2
  181. package/dist-es/timeline.css-mistica.js +11 -11
  182. package/dist-es/timer.css-mistica.js +7 -7
  183. package/dist-es/tooltip.css-mistica.js +3 -3
  184. package/dist-es/touchable.css-mistica.js +2 -2
  185. package/dist-es/utils/aspect-ratio-support.css-mistica.js +4 -4
  186. package/dist-es/video.css-mistica.js +2 -2
  187. package/dist-es/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +2 -2
  188. package/doc/llms.md +0 -24
  189. package/package.json +1 -13
  190. package/src/accordion.css.ts +0 -121
  191. package/src/accordion.tsx +0 -366
  192. package/src/align.css.ts +0 -7
  193. package/src/align.tsx +0 -32
  194. package/src/autocomplete.css.ts +0 -62
  195. package/src/autocomplete.tsx +0 -239
  196. package/src/avatar.css.ts +0 -14
  197. package/src/avatar.tsx +0 -120
  198. package/src/badge.css.ts +0 -51
  199. package/src/badge.tsx +0 -79
  200. package/src/box.css.ts +0 -51
  201. package/src/box.tsx +0 -114
  202. package/src/boxed.css.ts +0 -132
  203. package/src/boxed.tsx +0 -153
  204. package/src/button-fixed-footer-layout.tsx +0 -62
  205. package/src/button-group.css.ts +0 -75
  206. package/src/button-group.tsx +0 -91
  207. package/src/button-layout.css.ts +0 -162
  208. package/src/button-layout.tsx +0 -91
  209. package/src/button.css.ts +0 -758
  210. package/src/button.tsx +0 -632
  211. package/src/callout.css.ts +0 -50
  212. package/src/callout.tsx +0 -147
  213. package/src/card-cover.tsx +0 -242
  214. package/src/card-data.tsx +0 -152
  215. package/src/card-internal.css.ts +0 -271
  216. package/src/card-internal.tsx +0 -1724
  217. package/src/card-media.tsx +0 -157
  218. package/src/card-naked.tsx +0 -63
  219. package/src/carousel.css.ts +0 -522
  220. package/src/carousel.tsx +0 -1300
  221. package/src/checkbox.css.ts +0 -94
  222. package/src/checkbox.tsx +0 -192
  223. package/src/chip.css.ts +0 -204
  224. package/src/chip.tsx +0 -191
  225. package/src/circle.css.ts +0 -14
  226. package/src/circle.tsx +0 -52
  227. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-and-link-footer-image-false-1-snap.png +0 -0
  228. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-and-link-footer-image-true-1-snap.png +0 -0
  229. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-footer-image-false-1-snap.png +0 -0
  230. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-button-footer-image-true-1-snap.png +0 -0
  231. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-link-footer-image-false-1-snap.png +0 -0
  232. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-link-footer-image-true-1-snap.png +0 -0
  233. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-none-footer-image-false-1-snap.png +0 -0
  234. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-actions-none-footer-image-true-1-snap.png +0 -0
  235. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-0-1-snap.png +0 -0
  236. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-1-1-snap.png +0 -0
  237. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-3-1-snap.png +0 -0
  238. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-extras-3-no-divider-1-snap.png +0 -0
  239. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-inside-carousel-1-snap.png +0 -0
  240. package/src/community/__screenshot_tests__/__image_snapshots__/advanced-data-card-screenshot-test-tsx-advanced-data-card-without-stacking-group-with-top-actions-and-too-long-title-1-snap.png +0 -0
  241. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-highlighted-value-block-1-snap.png +0 -0
  242. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-information-block-1-snap.png +0 -0
  243. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-progress-block-1-snap.png +0 -0
  244. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-progress-block-2-snap.png +0 -0
  245. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-row-block-1-snap.png +0 -0
  246. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-simple-block-1-snap.png +0 -0
  247. package/src/community/__screenshot_tests__/__image_snapshots__/blocks-screenshot-test-tsx-blocks-value-block-1-snap.png +0 -0
  248. package/src/community/__screenshot_tests__/advanced-data-card-screenshot-test.tsx +0 -84
  249. package/src/community/__screenshot_tests__/blocks-screenshot-test.tsx +0 -72
  250. package/src/community/__stories__/advanced-data-card-carousel-story.tsx +0 -66
  251. package/src/community/__stories__/advanced-data-card-story.tsx +0 -158
  252. package/src/community/__stories__/blocks-story.tsx +0 -272
  253. package/src/community/__stories__/example-component-story.tsx +0 -15
  254. package/src/community/__stories__/index-story.tsx +0 -154
  255. package/src/community/__type_tests__/advanced-data-card-type-test.tsx +0 -40
  256. package/src/community/advanced-data-card.css.ts +0 -271
  257. package/src/community/advanced-data-card.tsx +0 -431
  258. package/src/community/blocks.css.ts +0 -12
  259. package/src/community/blocks.tsx +0 -290
  260. package/src/community/example-component.css.ts +0 -7
  261. package/src/community/example-component.tsx +0 -17
  262. package/src/community/index.tsx +0 -10
  263. package/src/counter.css.ts +0 -150
  264. package/src/counter.tsx +0 -215
  265. package/src/cover-hero-media.tsx +0 -39
  266. package/src/cover-hero.css.ts +0 -133
  267. package/src/cover-hero.tsx +0 -262
  268. package/src/credit-card-expiration-field.tsx +0 -187
  269. package/src/credit-card-fields.tsx +0 -56
  270. package/src/credit-card-number-field.css.ts +0 -47
  271. package/src/credit-card-number-field.tsx +0 -245
  272. package/src/cvv-field.tsx +0 -169
  273. package/src/date-field.css.ts +0 -14
  274. package/src/date-field.tsx +0 -130
  275. package/src/date-time-field.tsx +0 -141
  276. package/src/date-time-picker.css.ts +0 -126
  277. package/src/date-time-picker.tsx +0 -188
  278. package/src/decimal-field.tsx +0 -160
  279. package/src/desktop-container-type-context.tsx +0 -15
  280. package/src/dialog-context.tsx +0 -81
  281. package/src/dialog.css.ts +0 -155
  282. package/src/dialog.tsx +0 -423
  283. package/src/divider.css.ts +0 -10
  284. package/src/divider.tsx +0 -11
  285. package/src/double-field.css.ts +0 -33
  286. package/src/double-field.tsx +0 -71
  287. package/src/drawer.css.ts +0 -123
  288. package/src/drawer.tsx +0 -304
  289. package/src/email-field.tsx +0 -76
  290. package/src/empty-state-card.css.ts +0 -40
  291. package/src/empty-state-card.tsx +0 -92
  292. package/src/empty-state.css.ts +0 -119
  293. package/src/empty-state.tsx +0 -141
  294. package/src/fade-in.css.ts +0 -12
  295. package/src/fade-in.tsx +0 -40
  296. package/src/feedback.css.ts +0 -119
  297. package/src/feedback.tsx +0 -432
  298. package/src/file-upload.css.ts +0 -156
  299. package/src/file-upload.tsx +0 -612
  300. package/src/fixed-footer-layout.css.ts +0 -96
  301. package/src/fixed-footer-layout.tsx +0 -215
  302. package/src/fixed-to-top.tsx +0 -21
  303. package/src/focus-trap.tsx +0 -17
  304. package/src/form-context.tsx +0 -198
  305. package/src/form.css.ts +0 -5
  306. package/src/form.tsx +0 -287
  307. package/src/grid-layout.css.ts +0 -68
  308. package/src/grid-layout.tsx +0 -201
  309. package/src/grid.css.ts +0 -203
  310. package/src/grid.tsx +0 -241
  311. package/src/header.css.ts +0 -30
  312. package/src/header.tsx +0 -319
  313. package/src/hero.css.ts +0 -71
  314. package/src/hero.tsx +0 -318
  315. package/src/hooks.tsx +0 -313
  316. package/src/horizontal-scroll.css.ts +0 -43
  317. package/src/horizontal-scroll.tsx +0 -18
  318. package/src/iban-field.tsx +0 -218
  319. package/src/icon-button.css.ts +0 -561
  320. package/src/icon-button.tsx +0 -221
  321. package/src/icons/__stories__/mistica-icons-story.tsx +0 -192
  322. package/src/icons/icon-amex.tsx +0 -40
  323. package/src/icons/icon-chevron.css.ts +0 -23
  324. package/src/icons/icon-chevron.tsx +0 -150
  325. package/src/icons/icon-cvv-amex.tsx +0 -31
  326. package/src/icons/icon-cvv-visa-mc.tsx +0 -31
  327. package/src/icons/icon-error.css.ts +0 -27
  328. package/src/icons/icon-error.tsx +0 -207
  329. package/src/icons/icon-info.tsx +0 -86
  330. package/src/icons/icon-mastercard.tsx +0 -36
  331. package/src/icons/icon-success-vivo-new.tsx +0 -51
  332. package/src/icons/icon-success-vivo.tsx +0 -36
  333. package/src/icons/icon-success.tsx +0 -211
  334. package/src/icons/icon-visa.tsx +0 -32
  335. package/src/image.css.ts +0 -48
  336. package/src/image.tsx +0 -345
  337. package/src/index.tsx +0 -2466
  338. package/src/inline.css.ts +0 -131
  339. package/src/inline.tsx +0 -135
  340. package/src/integer-field.tsx +0 -93
  341. package/src/list.css.ts +0 -281
  342. package/src/list.tsx +0 -963
  343. package/src/loading-bar.css.ts +0 -69
  344. package/src/loading-bar.tsx +0 -25
  345. package/src/loading-screen.css.ts +0 -114
  346. package/src/loading-screen.tsx +0 -376
  347. package/src/logo-blau-shell.tsx +0 -30
  348. package/src/logo-blau.tsx +0 -60
  349. package/src/logo-common.tsx +0 -29
  350. package/src/logo-esimflag-shell.tsx +0 -30
  351. package/src/logo-esimflag.tsx +0 -56
  352. package/src/logo-movistar-new-shell.tsx +0 -30
  353. package/src/logo-movistar-new.tsx +0 -85
  354. package/src/logo-movistar-shell.tsx +0 -30
  355. package/src/logo-movistar.tsx +0 -63
  356. package/src/logo-o2-new-shell.tsx +0 -26
  357. package/src/logo-o2-new.tsx +0 -27
  358. package/src/logo-o2-shell.tsx +0 -26
  359. package/src/logo-o2.tsx +0 -27
  360. package/src/logo-telefonica-shell.tsx +0 -30
  361. package/src/logo-telefonica.tsx +0 -95
  362. package/src/logo-tu-shell.tsx +0 -26
  363. package/src/logo-tu.tsx +0 -28
  364. package/src/logo-vivo-shell.tsx +0 -30
  365. package/src/logo-vivo.tsx +0 -53
  366. package/src/logo.css.ts +0 -33
  367. package/src/logo.tsx +0 -313
  368. package/src/master-detail-layout.tsx +0 -28
  369. package/src/maybe-dismissable.css.ts +0 -37
  370. package/src/maybe-dismissable.tsx +0 -58
  371. package/src/media-queries.css.ts +0 -67
  372. package/src/menu.css.ts +0 -132
  373. package/src/menu.tsx +0 -468
  374. package/src/meter.tsx +0 -516
  375. package/src/modal-context-provider.tsx +0 -45
  376. package/src/month-field.tsx +0 -124
  377. package/src/mosaic.css.ts +0 -73
  378. package/src/mosaic.tsx +0 -205
  379. package/src/navigation-bar.css.ts +0 -558
  380. package/src/navigation-bar.tsx +0 -1637
  381. package/src/navigation-breadcrumbs.css.ts +0 -22
  382. package/src/navigation-breadcrumbs.tsx +0 -69
  383. package/src/negative-box.tsx +0 -15
  384. package/src/nestable-context.tsx +0 -139
  385. package/src/overlay.tsx +0 -86
  386. package/src/overscroll-color-context.tsx +0 -141
  387. package/src/package-version.tsx +0 -2
  388. package/src/password-field.tsx +0 -126
  389. package/src/phone-number-field-lite.tsx +0 -265
  390. package/src/phone-number-field.tsx +0 -171
  391. package/src/pin-field.css.ts +0 -90
  392. package/src/pin-field.tsx +0 -346
  393. package/src/placeholder.tsx +0 -41
  394. package/src/popover.css.ts +0 -8
  395. package/src/popover.tsx +0 -85
  396. package/src/portal.tsx +0 -43
  397. package/src/progress-bar.css.ts +0 -61
  398. package/src/progress-bar.tsx +0 -174
  399. package/src/radio-button.css.ts +0 -174
  400. package/src/radio-button.tsx +0 -322
  401. package/src/rating.css.ts +0 -128
  402. package/src/rating.tsx +0 -351
  403. package/src/responsive-layout.css.ts +0 -162
  404. package/src/responsive-layout.tsx +0 -106
  405. package/src/screen-reader-only.css.ts +0 -27
  406. package/src/screen-reader-only.tsx +0 -33
  407. package/src/screen-size-context-provider.tsx +0 -96
  408. package/src/screen-size-context.tsx +0 -23
  409. package/src/search-field.tsx +0 -126
  410. package/src/select.css.ts +0 -226
  411. package/src/select.tsx +0 -513
  412. package/src/sheet-action-row.css.ts +0 -33
  413. package/src/sheet-actions-list.tsx +0 -113
  414. package/src/sheet-actions.tsx +0 -95
  415. package/src/sheet-common.css.ts +0 -254
  416. package/src/sheet-common.tsx +0 -402
  417. package/src/sheet-info.css.ts +0 -19
  418. package/src/sheet-info.tsx +0 -127
  419. package/src/sheet-native.tsx +0 -189
  420. package/src/sheet-radio-list.tsx +0 -118
  421. package/src/sheet-root.tsx +0 -127
  422. package/src/sheet-types.tsx +0 -94
  423. package/src/sheet-web.tsx +0 -140
  424. package/src/skeleton-base.tsx +0 -38
  425. package/src/skeletons.css.ts +0 -56
  426. package/src/skeletons.tsx +0 -133
  427. package/src/skins/blau.tsx +0 -724
  428. package/src/skins/constants.tsx +0 -10
  429. package/src/skins/defaults.tsx +0 -104
  430. package/src/skins/esimflag.tsx +0 -728
  431. package/src/skins/movistar-new.tsx +0 -735
  432. package/src/skins/movistar.tsx +0 -740
  433. package/src/skins/o2-new.tsx +0 -731
  434. package/src/skins/o2.tsx +0 -727
  435. package/src/skins/skin-contract.css.ts +0 -380
  436. package/src/skins/telefonica.tsx +0 -768
  437. package/src/skins/tu.tsx +0 -741
  438. package/src/skins/types/colors.tsx +0 -286
  439. package/src/skins/types/index.tsx +0 -153
  440. package/src/skins/utils.tsx +0 -66
  441. package/src/skins/vivo-new.tsx +0 -745
  442. package/src/skins/vivo.tsx +0 -720
  443. package/src/skip-link.css.ts +0 -34
  444. package/src/skip-link.tsx +0 -52
  445. package/src/slider.css.ts +0 -181
  446. package/src/slider.tsx +0 -384
  447. package/src/snackbar-context.tsx +0 -98
  448. package/src/snackbar-native.ts +0 -37
  449. package/src/snackbar.css.ts +0 -176
  450. package/src/snackbar.tsx +0 -258
  451. package/src/spinner.css.ts +0 -66
  452. package/src/spinner.tsx +0 -136
  453. package/src/sprinkles.css.ts +0 -83
  454. package/src/square.css.ts +0 -15
  455. package/src/square.tsx +0 -55
  456. package/src/stack.css.ts +0 -44
  457. package/src/stack.tsx +0 -79
  458. package/src/stacking-group.css.ts +0 -15
  459. package/src/stacking-group.tsx +0 -82
  460. package/src/stepper.css.ts +0 -233
  461. package/src/stepper.tsx +0 -156
  462. package/src/switch-component.css.ts +0 -181
  463. package/src/switch-component.tsx +0 -187
  464. package/src/tab-focus.tsx +0 -68
  465. package/src/table-actions-header.tsx +0 -21
  466. package/src/table-cell-text.tsx +0 -35
  467. package/src/table.css.ts +0 -297
  468. package/src/table.tsx +0 -398
  469. package/src/tabs.css.ts +0 -212
  470. package/src/tabs.tsx +0 -263
  471. package/src/tag.css.ts +0 -42
  472. package/src/tag.tsx +0 -161
  473. package/src/test-utils/environment/setup-ssr.tsx +0 -10
  474. package/src/test-utils/fail-test-on-console-error.tsx +0 -22
  475. package/src/test-utils/index.tsx +0 -341
  476. package/src/test-utils/setup-ssr-test-env.tsx +0 -13
  477. package/src/test-utils/ssr.tsx +0 -197
  478. package/src/text-field-base.css.ts +0 -416
  479. package/src/text-field-base.tsx +0 -628
  480. package/src/text-field-components.css.ts +0 -159
  481. package/src/text-field-components.tsx +0 -225
  482. package/src/text-field.tsx +0 -118
  483. package/src/text-link.css.ts +0 -83
  484. package/src/text-link.tsx +0 -85
  485. package/src/text-tokens.tsx +0 -708
  486. package/src/text.css.ts +0 -60
  487. package/src/text.tsx +0 -516
  488. package/src/theme-context-provider.tsx +0 -370
  489. package/src/theme-context.css.ts +0 -3
  490. package/src/theme-context.tsx +0 -8
  491. package/src/theme-variant-context.tsx +0 -51
  492. package/src/theme.tsx +0 -184
  493. package/src/time-field.tsx +0 -99
  494. package/src/timeline.css.ts +0 -135
  495. package/src/timeline.tsx +0 -250
  496. package/src/timer.css.ts +0 -99
  497. package/src/timer.tsx +0 -420
  498. package/src/title.tsx +0 -119
  499. package/src/tooltip-context-provider.tsx +0 -57
  500. package/src/tooltip.css.ts +0 -106
  501. package/src/tooltip.tsx +0 -649
  502. package/src/touchable.css.ts +0 -56
  503. package/src/touchable.tsx +0 -355
  504. package/src/types/font-face.d.ts +0 -47
  505. package/src/types/libs.d.ts +0 -3
  506. package/src/utils/__tests__/analytics-test.tsx +0 -35
  507. package/src/utils/__tests__/browser-test.tsx +0 -28
  508. package/src/utils/__tests__/dom-test.tsx +0 -23
  509. package/src/utils/__tests__/helpers-test.tsx +0 -166
  510. package/src/utils/analytics.tsx +0 -28
  511. package/src/utils/animation.tsx +0 -201
  512. package/src/utils/aspect-ratio-support.css.ts +0 -28
  513. package/src/utils/aspect-ratio-support.tsx +0 -141
  514. package/src/utils/browser.tsx +0 -9
  515. package/src/utils/color.tsx +0 -46
  516. package/src/utils/common.tsx +0 -27
  517. package/src/utils/credit-card.tsx +0 -46
  518. package/src/utils/css.tsx +0 -25
  519. package/src/utils/document-visibility.tsx +0 -52
  520. package/src/utils/dom.tsx +0 -155
  521. package/src/utils/environment.tsx +0 -6
  522. package/src/utils/headings.tsx +0 -18
  523. package/src/utils/helpers.tsx +0 -182
  524. package/src/utils/keys.tsx +0 -8
  525. package/src/utils/locale.tsx +0 -27
  526. package/src/utils/platform.tsx +0 -94
  527. package/src/utils/region-code.tsx +0 -1
  528. package/src/utils/renders-element.tsx +0 -6
  529. package/src/utils/time.tsx +0 -22
  530. package/src/utils/types.tsx +0 -19
  531. package/src/utils/utility-types.tsx +0 -8
  532. package/src/video.css.ts +0 -11
  533. package/src/video.tsx +0 -355
  534. package/src/vivinho-loading-animation/in-lottie.json +0 -402
  535. package/src/vivinho-loading-animation/index.tsx +0 -90
  536. package/src/vivinho-loading-animation/out-lottie.json +0 -575
  537. package/src/vivinho-loading-animation/pulse-lottie.json +0 -551
  538. package/src/vivinho-loading-animation/vivinho-loading-animation.css.ts +0 -15
  539. package/src/vivinho-loading-animation/wave-lottie.json +0 -2829
@@ -1,1637 +0,0 @@
1
- 'use client';
2
- import * as React from 'react';
3
- import {CSSTransition} from 'react-transition-group';
4
- import classnames from 'classnames';
5
- import ResponsiveLayout, {ResetResponsiveLayout} from './responsive-layout';
6
- import Inline from './inline';
7
- import Touchable, {BaseTouchable} from './touchable';
8
- import {Text2, Text3} from './text';
9
- import {useElementDimensions, useScreenSize, useTheme} from './hooks';
10
- import IconMenuRegular from './generated/mistica-icons/icon-menu-regular';
11
- import IconCloseRegular from './generated/mistica-icons/icon-close-regular';
12
- import IconChevronLeftRegular from './generated/mistica-icons/icon-chevron-left-regular';
13
- import {IconButton} from './icon-button';
14
- import {Row, RowList} from './list';
15
- import {ThemeVariant, normalizeVariant, useThemeVariant} from './theme-variant-context';
16
- import FocusTrap from './focus-trap';
17
- import {Portal} from './portal';
18
- import GridLayout from './grid-layout';
19
- import {useSetModalState} from './modal-context-provider';
20
- import {Logo} from './logo';
21
- import {vars} from './skins/skin-contract.css';
22
- import * as styles from './navigation-bar.css';
23
- import {cancelEvent, getPrefixedDataAttributes} from './utils/dom';
24
- import Stack from './stack';
25
- import Box from './box';
26
- import {isRunningAcceptanceTest} from './utils/platform';
27
- import * as tokens from './text-tokens';
28
- import {NAVBAR_HEIGHT_DESKTOP, NAVBAR_HEIGHT_DESKTOP_LARGE, NAVBAR_HEIGHT_MOBILE} from './theme';
29
- import TextLink from './text-link';
30
- import {Title1, Title3} from './title';
31
- import {ButtonLink} from './button';
32
- import {Grid, GridItem} from './grid';
33
- import {DOWN, ESC, UP} from './utils/keys';
34
- import {debounce, isEqual} from './utils/helpers';
35
- import NegativeBox from './negative-box';
36
-
37
- import type {BoxProps} from './box';
38
- import type {ExclusifyUnion} from './utils/utility-types';
39
- import type {NonDeprecatedVariant, Variant} from './theme-variant-context';
40
- import type {TouchableProps} from './touchable';
41
- import type {DataAttributes, HeadingType, IconProps} from './utils/types';
42
-
43
- const MAIN_NAVIGATION_BAR_MENU_DEBOUNCE_TIME = 120;
44
-
45
- const MenuSectionArrow = ({size = 24, color = vars.colors.neutralHigh, style, className}: IconProps) => (
46
- <svg width={size} height={size} viewBox="0 0 8 8" style={style} className={className}>
47
- <path
48
- d="M6.32595 3.46071L3.03801 0.158595L3.03292 0.153747L3.032 0.152903L3.02931 0.150463L3.02848 0.149738L3.02248 0.144353C2.88533 0.021206 2.71386 -0.0126731 2.56343 0.00394249C2.41648 0.0201739 2.27272 0.0856702 2.16886 0.18711C2.06893 0.281844 2.01209 0.42816 2.00175 0.567065C1.99083 0.71377 2.02925 0.889583 2.16869 1.02392L5.24446 4.00145L2.15859 6.96199L2.15375 6.96708L2.1529 6.968L2.15046 6.97069L2.14974 6.97152L2.14435 6.97752C2.02121 7.11467 1.98733 7.28614 2.00394 7.43657C2.02017 7.58352 2.08567 7.72728 2.18711 7.83114C2.28184 7.93107 2.42816 7.98791 2.56706 7.99825C2.71377 8.00917 2.88958 7.97075 3.02392 7.83132L6.32595 4.5422V4.5422C6.6246 4.24355 6.6246 3.75935 6.32595 3.46071V3.46071Z"
49
- fill={color}
50
- />
51
- </svg>
52
- );
53
-
54
- const BurgerMenuIcon = ({isOpen}: {isOpen: boolean}) => {
55
- return (
56
- <div className={styles.burgerIconContainer} role="presentation" data-component-name="BurgerMenuIcon">
57
- <div className={isOpen ? styles.iconCloseOpen : styles.iconCloseHidden}>
58
- <IconCloseRegular />
59
- </div>
60
- <div className={isOpen ? styles.iconMenuHidden : styles.iconMenuOpen}>
61
- <IconMenuRegular />
62
- </div>
63
- </div>
64
- );
65
- };
66
-
67
- type HeaderProps = {
68
- children: React.ReactNode;
69
- topFixed?: boolean;
70
- variant: NonDeprecatedVariant;
71
- withBorder?: boolean;
72
- isBurgerMenuOpen?: boolean;
73
- dataAttributes?: DataAttributes;
74
- isBottomRow?: boolean;
75
- };
76
-
77
- const Header = ({children, topFixed, withBorder, isBurgerMenuOpen, variant, dataAttributes}: HeaderProps) => {
78
- const {isDarkMode} = useTheme();
79
-
80
- const getBorderClass = () => {
81
- const isBrandVariant = (variant === 'brand' || variant === 'negative') && !isDarkMode;
82
- if (isBrandVariant || !withBorder) return styles.navbarBorderColorVariants.noBorder;
83
- if (isBurgerMenuOpen) return styles.navbarBorderColorVariants.menuOpen;
84
-
85
- return styles.navbarBorderColorVariants.default;
86
- };
87
-
88
- const backgroundColor = {
89
- default: vars.colors.background,
90
- brand: vars.colors.navigationBarBackground,
91
- negative: vars.colors.backgroundNegative,
92
- alternative: vars.colors.backgroundAlternative,
93
- media: vars.colors.navigationBarBackground,
94
- } as const;
95
-
96
- return (
97
- <header
98
- className={classnames(getBorderClass(), {[styles.topFixed]: topFixed})}
99
- style={{
100
- background: backgroundColor[variant],
101
- }}
102
- {...getPrefixedDataAttributes(dataAttributes)}
103
- >
104
- {children}
105
- </header>
106
- );
107
- };
108
-
109
- type NavigationBarContentContainerProps = {
110
- right?: React.ReactNode;
111
- children?: React.ReactNode;
112
- desktopOnly?: boolean;
113
- expandRightContent?: boolean;
114
- };
115
-
116
- const NavigationBarContentContainer = React.forwardRef<HTMLDivElement, NavigationBarContentContainerProps>(
117
- ({right, children, desktopOnly, expandRightContent}, ref) => {
118
- return (
119
- <div
120
- ref={ref}
121
- className={classnames(styles.navigationBarContent, {[styles.desktopOnly]: desktopOnly})}
122
- >
123
- {children}
124
- {right && (
125
- <div
126
- className={
127
- expandRightContent
128
- ? styles.navigationBarContentRightExpanded
129
- : styles.navigationBarContentRight
130
- }
131
- >
132
- {right}
133
- </div>
134
- )}
135
- </div>
136
- );
137
- }
138
- );
139
-
140
- type WideConfig = {
141
- paddingX: BoxProps['paddingX'];
142
- };
143
-
144
- const NavigationBarSideMargins = ({
145
- children,
146
- wide,
147
- backgroundColor,
148
- }: {
149
- children: React.ReactNode;
150
- wide: boolean | WideConfig;
151
- backgroundColor?: string;
152
- }) => {
153
- if (!wide) {
154
- return <ResponsiveLayout backgroundColor={backgroundColor}>{children}</ResponsiveLayout>;
155
- }
156
-
157
- const defaultWidePaddingX: BoxProps['paddingX'] = {
158
- mobile: 16,
159
- tablet: 24,
160
- desktop: 24,
161
- };
162
-
163
- return (
164
- <Box
165
- width="100%"
166
- paddingX={
167
- wide === true
168
- ? defaultWidePaddingX
169
- : typeof wide.paddingX === 'number'
170
- ? wide.paddingX
171
- : {
172
- ...defaultWidePaddingX,
173
- ...wide.paddingX,
174
- }
175
- }
176
- background={backgroundColor}
177
- >
178
- {children}
179
- </Box>
180
- );
181
- };
182
-
183
- interface NavigationBarCommonProps {
184
- variant?: Variant;
185
- onBack?: () => void;
186
- title?: string;
187
- titleAs?: HeadingType;
188
- right?: React.ReactElement;
189
- withBorder?: boolean;
190
- children?: undefined;
191
- wide?: boolean | WideConfig;
192
- }
193
-
194
- interface NavigationBarTopFixedProps extends NavigationBarCommonProps {
195
- topFixed?: true;
196
- paddingX?: undefined;
197
- }
198
-
199
- interface NavigationBarNotFixedProps extends NavigationBarCommonProps {
200
- topFixed: false;
201
- /** @deprecated use wide */
202
- paddingX?: number;
203
- }
204
-
205
- type NavigationBarProps = NavigationBarTopFixedProps | NavigationBarNotFixedProps;
206
-
207
- export const NavigationBar = ({
208
- onBack,
209
- title,
210
- titleAs,
211
- right,
212
- variant = 'default',
213
- topFixed = true,
214
- paddingX = 0,
215
- withBorder = true,
216
- wide = false,
217
- }: NavigationBarProps): JSX.Element => {
218
- const {texts, t} = useTheme();
219
- const content = (
220
- <NavigationBarContentContainer right={right} expandRightContent>
221
- <Inline space={24} alignItems="center">
222
- {onBack && (
223
- <IconButton
224
- aria-label={texts.backNavigationBar || t(tokens.backNavigationBar)}
225
- onPress={onBack}
226
- Icon={IconChevronLeftRegular}
227
- bleedLeft
228
- bleedRight
229
- />
230
- )}
231
- <Text3 regular truncate as={titleAs}>
232
- {title}
233
- </Text3>
234
- </Inline>
235
- </NavigationBarContentContainer>
236
- );
237
-
238
- const calcPaddingXWhenNotTopFixed = (): BoxProps['paddingX'] => {
239
- if (wide !== undefined) {
240
- if (typeof wide !== 'object') {
241
- return 0;
242
- }
243
- return wide.paddingX ?? 0;
244
- }
245
-
246
- return paddingX as BoxProps['paddingX'];
247
- };
248
-
249
- const normalizedVariant = normalizeVariant(variant);
250
-
251
- return (
252
- <ThemeVariant variant={normalizedVariant}>
253
- <Header
254
- topFixed={topFixed}
255
- withBorder={withBorder}
256
- variant={normalizedVariant}
257
- dataAttributes={{'component-name': 'NavigationBar'}}
258
- >
259
- {topFixed ? (
260
- <NavigationBarSideMargins wide={wide}>{content}</NavigationBarSideMargins>
261
- ) : (
262
- <Box width="100%" paddingX={calcPaddingXWhenNotTopFixed()}>
263
- {content}
264
- </Box>
265
- )}
266
- </Header>
267
- {topFixed && <div className={styles.spacer} />}
268
- </ThemeVariant>
269
- );
270
- };
271
-
272
- type InteractiveProps = ExclusifyUnion<{href: string} | {to: string} | {onPress: () => void}>;
273
- type MaybeInteractiveProps = ExclusifyUnion<{href?: string} | {to?: string} | {onPress?: () => void}>;
274
-
275
- type SectionItem = {title: string} & InteractiveProps;
276
-
277
- type SectionColumn = {
278
- title: string;
279
- items: ReadonlyArray<SectionItem>;
280
- };
281
-
282
- type SectionMenu = ExclusifyUnion<
283
- | {columns: ReadonlyArray<SectionColumn>}
284
- // Content prop can receive a function as value with the closeMenu callback as parameter.
285
- // In this way, custom content can also force the menu to close programmatically.
286
- | {content?: React.ReactElement | ((props: {closeMenu: () => void}) => React.ReactElement)}
287
- >;
288
-
289
- const getInteractivePropsWithCloseMenu = (interactiveProps: InteractiveProps, closeMenu: () => void) => {
290
- if (
291
- interactiveProps.href === undefined &&
292
- interactiveProps.onPress === undefined &&
293
- interactiveProps.to === undefined
294
- ) {
295
- return {onPress: closeMenu};
296
- }
297
-
298
- return interactiveProps.onPress
299
- ? {
300
- onPress: () => {
301
- interactiveProps.onPress();
302
- closeMenu();
303
- },
304
- }
305
- : {...interactiveProps, onNavigate: () => closeMenu()};
306
- };
307
-
308
- type MainNavigationBarSection = {
309
- title: string;
310
- menu?: SectionMenu;
311
- } & MaybeInteractiveProps;
312
-
313
- type MainNavigationBarProps = {
314
- sections?: ReadonlyArray<MainNavigationBarSection>;
315
- selectedIndex?: number;
316
- right?: React.ReactElement;
317
- topSlot?: React.ReactElement;
318
- topSlotBackgroundColor?: string;
319
- logo?: React.ReactElement;
320
- variant?: Variant;
321
- children?: undefined;
322
- topFixed?: boolean;
323
- withBorder?: boolean;
324
- burgerMenuExtra?: React.ReactNode;
325
- large?: boolean;
326
- desktopLargeMenu?: boolean;
327
- wide?: boolean | WideConfig;
328
- };
329
-
330
- type MainNavigationBarMenuStatus = 'opening' | 'opened' | 'closing' | 'closed';
331
- type MainNavigationBarMenuAction = 'open' | 'finishOpen' | 'close' | 'finishClose';
332
-
333
- const mainNavigationBurgerMenuTranstions: Record<
334
- MainNavigationBarMenuStatus,
335
- Partial<Record<MainNavigationBarMenuAction, MainNavigationBarMenuStatus>>
336
- > = {
337
- opening: {
338
- close: 'closing',
339
- finishOpen: 'opened',
340
- },
341
- opened: {
342
- close: 'closing',
343
- },
344
- closing: {
345
- open: 'opening',
346
- finishClose: 'closed',
347
- },
348
- closed: {
349
- open: 'opening',
350
- },
351
- };
352
-
353
- const burgerMenuReducer = (state: MainNavigationBarMenuStatus, action: MainNavigationBarMenuAction) => {
354
- return mainNavigationBurgerMenuTranstions[state][action] || state;
355
- };
356
-
357
- const MainNavigationBarBurgerSection = ({
358
- section,
359
- closeSubMenu,
360
- closeMenu,
361
- }: {
362
- section: MainNavigationBarSection;
363
- closeSubMenu: () => void;
364
- closeMenu: () => void;
365
- }) => {
366
- const {texts, t} = useTheme();
367
-
368
- const {title, menu, ...interactiveProps} = section;
369
-
370
- const columns = menu?.columns || [];
371
- const customContent = menu?.content;
372
- const hasCustomInteraction =
373
- interactiveProps.href !== undefined ||
374
- interactiveProps.onPress !== undefined ||
375
- interactiveProps.to !== undefined;
376
-
377
- return (
378
- <ResponsiveLayout>
379
- <Stack space={32}>
380
- <Stack space={16}>
381
- <NavigationBar
382
- title={texts.backNavigationBar || t(tokens.backNavigationBar)}
383
- onBack={closeSubMenu}
384
- topFixed={false}
385
- withBorder={false}
386
- />
387
- <Title3
388
- right={
389
- hasCustomInteraction ? (
390
- <ButtonLink
391
- small
392
- bleedY
393
- bleedRight
394
- withChevron
395
- // Close the menu when "See all" button is pressed
396
- {...getInteractivePropsWithCloseMenu(
397
- interactiveProps as InteractiveProps,
398
- closeMenu
399
- )}
400
- >
401
- {texts.mainNavigationBarSectionSeeAll ||
402
- t(tokens.mainNavigationBarSectionSeeAll)}
403
- </ButtonLink>
404
- ) : undefined
405
- }
406
- >
407
- {title}
408
- </Title3>
409
- </Stack>
410
-
411
- {customContent ? (
412
- <Box paddingBottom={16}>
413
- {typeof customContent === 'function' ? customContent({closeMenu}) : customContent}
414
- </Box>
415
- ) : (
416
- columns.map((column, columnIndex) => (
417
- <Stack space={8} key={columnIndex}>
418
- <Title1> {column.title}</Title1>
419
- <NegativeBox>
420
- <RowList>
421
- {column.items.map(
422
- ({title: itemTitle, ...itemInteractiveProps}, itemIndex) => (
423
- <Row
424
- key={itemIndex}
425
- title={itemTitle}
426
- // Close the menu when one of the rows is pressed
427
- {...getInteractivePropsWithCloseMenu(
428
- itemInteractiveProps,
429
- closeMenu
430
- )}
431
- />
432
- )
433
- )}
434
- </RowList>
435
- </NegativeBox>
436
- </Stack>
437
- ))
438
- )}
439
- </Stack>
440
- </ResponsiveLayout>
441
- );
442
- };
443
-
444
- const MainNavigationBarBurgerMenu = ({
445
- sections,
446
- extra,
447
- closeMenu,
448
- open,
449
- topSlotHeight,
450
- id,
451
- disableFocusTrap,
452
- setDisableFocusTrap,
453
- }: {
454
- sections: ReadonlyArray<MainNavigationBarSection>;
455
- extra: React.ReactNode;
456
- closeMenu: () => void;
457
- open: boolean;
458
- topSlotHeight: number;
459
- id: string;
460
- disableFocusTrap: boolean;
461
- setDisableFocusTrap: (value: boolean) => void;
462
- }) => {
463
- const {isDarkMode, texts, t} = useTheme();
464
- const [openedSection, setOpenedSection] = React.useState(-1);
465
- const [isSubMenuOpen, setIsSubMenuOpen] = React.useState(false);
466
- const [subMenuStatus, dispatch] = React.useReducer(burgerMenuReducer, 'closed');
467
- const menuRef = React.useRef<HTMLDivElement>(null);
468
-
469
- const shadowAlpha = isDarkMode ? 1 : 0.2;
470
- const menuAnimationDuration = isRunningAcceptanceTest() ? 0 : styles.BURGER_MENU_ANIMATION_DURATION_MS;
471
-
472
- React.useEffect(() => {
473
- let id: NodeJS.Timeout;
474
-
475
- // menu starts opening or closing
476
- if (isSubMenuOpen) {
477
- dispatch('open');
478
- id = setTimeout(() => dispatch('finishOpen'), menuAnimationDuration);
479
- } else {
480
- dispatch('close');
481
- id = setTimeout(() => dispatch('finishClose'), menuAnimationDuration);
482
- }
483
-
484
- return () => clearTimeout(id);
485
- }, [isSubMenuOpen, menuAnimationDuration]);
486
-
487
- const sectionContainerRef = React.useRef<HTMLDivElement>(null);
488
-
489
- React.useEffect(() => {
490
- // Make screen reader focus on back button when opening any section's menu
491
- if (subMenuStatus === 'opening') {
492
- const sectionBackButtonElement = sectionContainerRef.current?.querySelector<HTMLButtonElement>(
493
- `button[aria-label="${texts.backNavigationBar || t(tokens.backNavigationBar)}"]`
494
- );
495
-
496
- sectionBackButtonElement?.focus();
497
- }
498
- }, [subMenuStatus, t, texts]);
499
-
500
- return (
501
- <Portal>
502
- <FocusTrap disabled={disableFocusTrap} group="burger-menu-lock">
503
- <CSSTransition
504
- onEntered={() => setDisableFocusTrap(false)}
505
- onExiting={() => setDisableFocusTrap(true)}
506
- onExited={() => {
507
- setIsSubMenuOpen(false);
508
- setOpenedSection(-1);
509
- }}
510
- classNames={styles.burgerMenuTransition}
511
- in={open}
512
- nodeRef={menuRef}
513
- timeout={menuAnimationDuration}
514
- mountOnEnter
515
- unmountOnExit
516
- >
517
- <nav
518
- className={styles.burgerMenu}
519
- style={{
520
- boxShadow: `6px 0 4px -4px rgba(0, 0, 0, ${shadowAlpha})`,
521
- top: NAVBAR_HEIGHT_MOBILE + topSlotHeight,
522
- }}
523
- id={id}
524
- ref={menuRef}
525
- >
526
- <div className={styles.burgerMenuContainer}>
527
- <div
528
- className={styles.burgerMenuContentContainer}
529
- style={{
530
- transform: `translate(${isSubMenuOpen ? '-100vw' : '0'})`,
531
- }}
532
- >
533
- {subMenuStatus !== 'opened' && (
534
- <ResponsiveLayout>
535
- <ResetResponsiveLayout>
536
- <RowList>
537
- {sections.map(({title, menu, ...interactiveProps}, index) => (
538
- <Row
539
- key={index}
540
- title={title}
541
- {...(menu
542
- ? {
543
- onPress: () => {
544
- setIsSubMenuOpen(true);
545
- setOpenedSection(index);
546
- },
547
- }
548
- : // Close the menu when one of the rows is pressed
549
- getInteractivePropsWithCloseMenu(
550
- interactiveProps as InteractiveProps,
551
- closeMenu
552
- ))}
553
- />
554
- ))}
555
- </RowList>
556
- </ResetResponsiveLayout>
557
- {extra && <Box paddingY={16}>{extra}</Box>}
558
- </ResponsiveLayout>
559
- )}
560
- </div>
561
-
562
- <div
563
- className={styles.burgerMenuContentContainer}
564
- ref={sectionContainerRef}
565
- style={{
566
- transform: `translate(${isSubMenuOpen ? '0' : '100vw'})`,
567
- }}
568
- >
569
- {subMenuStatus !== 'closed' && openedSection !== -1 && (
570
- <MainNavigationBarBurgerSection
571
- section={sections[openedSection]}
572
- closeMenu={closeMenu}
573
- closeSubMenu={() => setIsSubMenuOpen(false)}
574
- />
575
- )}
576
- </div>
577
- </div>
578
- </nav>
579
- </CSSTransition>
580
- </FocusTrap>
581
- </Portal>
582
- );
583
- };
584
-
585
- const mainNavigationDesktopMenuTranstions: Record<
586
- MainNavigationBarMenuStatus,
587
- Partial<Record<MainNavigationBarMenuAction, MainNavigationBarMenuStatus>>
588
- > = {
589
- opening: {
590
- close: 'closing',
591
- finishOpen: 'opened',
592
- },
593
- opened: {
594
- close: 'closing',
595
- },
596
- closing: {
597
- // If a section was opened while the menu was closing, the menu should be considered as
598
- // already open. This is useful for example to avoid the new content's fade-in animation
599
- open: 'opened',
600
- finishClose: 'closed',
601
- },
602
- closed: {
603
- open: 'opening',
604
- },
605
- };
606
-
607
- const desktopMenuReducer = (state: MainNavigationBarMenuStatus, action: MainNavigationBarMenuAction) => {
608
- return mainNavigationDesktopMenuTranstions[state][action] || state;
609
- };
610
-
611
- type MainNavigationBarDesktopMenuState = {
612
- isMenuOpen: boolean;
613
- openedSection: number;
614
- menuHeight: string;
615
- menuStatus: MainNavigationBarMenuStatus;
616
- openSectionMenu: (index: number) => void;
617
- closeMenu: () => void;
618
- setMenuHeight: (height: string) => void;
619
- setIsMenuHovered: (value: boolean) => void;
620
- setFocusedItem: (item?: {column: number; index: number}) => void;
621
- debouncedOpenSectionMenu: (index: number) => void;
622
- cancelDebouncedOpenSectionMenu: (index: number) => void;
623
- };
624
-
625
- const MainNavigationBarDesktopMenuContext = React.createContext<MainNavigationBarDesktopMenuState>({
626
- isMenuOpen: false,
627
- openedSection: -1,
628
- menuHeight: '0px',
629
- menuStatus: 'closed',
630
- openSectionMenu: () => {},
631
- closeMenu: () => {},
632
- setMenuHeight: () => {},
633
- setIsMenuHovered: () => {},
634
- setFocusedItem: () => {},
635
- debouncedOpenSectionMenu: () => {},
636
- cancelDebouncedOpenSectionMenu: () => {},
637
- });
638
-
639
- const MainNavigationBarDesktopMenuContextProvider = ({
640
- children,
641
- sections,
642
- isLargeMenu,
643
- }: {
644
- children: React.ReactNode;
645
- sections?: ReadonlyArray<MainNavigationBarSection>;
646
- isLargeMenu?: boolean;
647
- }): JSX.Element => {
648
- const {isTabletOrSmaller} = useScreenSize();
649
- const [isMenuOpen, setIsMenuOpen] = React.useState(false);
650
- const [menuHeight, setMenuHeight] = React.useState('0px');
651
- const [menuStatus, dispatch] = React.useReducer(desktopMenuReducer, 'closed');
652
- const [debouncedOpenSectionIndex, setDebouncedOpenSectionIndex] = React.useState(-1);
653
-
654
- // Item that is currently focused inside a section. This state is used to handle pressing
655
- // up/down arrows to navigate through the items of a section.
656
- const [focusedItem, setFocusedItem] = React.useState<{column: number; index: number} | undefined>();
657
-
658
- // State that indicated whether the menu container has been hovered
659
- const [isMenuHovered, setIsMenuHovered] = React.useState(false);
660
-
661
- // State that indicates whether the current rendered section has been hovered or its arrow button is focused
662
- const [isSectionHovered, setIsSectionHovered] = React.useState(false);
663
-
664
- // Section that is currently being rendered
665
- const [openedSection, setOpenedSection] = React.useState(-1);
666
-
667
- // Callback used when a section has been hovered or it's focused arrow has been pressed while it's closed
668
- const openSectionMenu = React.useCallback(
669
- (index: number) => {
670
- setDebouncedOpenSectionIndex(-1);
671
- if (sections?.[index]?.menu) {
672
- setIsSectionHovered(true);
673
- setOpenedSection(index);
674
- } else {
675
- // If the section has no menu, close the current opened one
676
- setIsMenuHovered(false);
677
- setIsSectionHovered(false);
678
- }
679
- },
680
- [sections]
681
- );
682
-
683
- const debouncedOpenSectionMenu = React.useMemo(
684
- () => debounce(openSectionMenu, MAIN_NAVIGATION_BAR_MENU_DEBOUNCE_TIME),
685
- [openSectionMenu]
686
- );
687
-
688
- const closeMenu = React.useCallback(() => {
689
- setIsMenuHovered(false);
690
- setIsSectionHovered(false);
691
- debouncedOpenSectionMenu.cancel();
692
- setDebouncedOpenSectionIndex(-1);
693
- }, [debouncedOpenSectionMenu]);
694
-
695
- // Close menu when viewport is too small
696
- React.useEffect(() => {
697
- if (isTabletOrSmaller) {
698
- closeMenu();
699
- }
700
- }, [isTabletOrSmaller, closeMenu]);
701
-
702
- React.useEffect(() => {
703
- if (!isSectionHovered && !isMenuHovered) {
704
- setIsMenuOpen(false);
705
- setMenuHeight('0px');
706
- } else {
707
- setIsMenuOpen(true);
708
- }
709
- }, [isMenuHovered, isSectionHovered]);
710
-
711
- React.useEffect(() => {
712
- const menuAnimationDuration =
713
- isRunningAcceptanceTest() || !isLargeMenu ? 0 : styles.DESKTOP_MENU_ANIMATION_DURATION_MS;
714
-
715
- let id: NodeJS.Timeout;
716
-
717
- // menu starts opening or closing
718
- if (!isMenuOpen) {
719
- dispatch('close');
720
- id = setTimeout(() => dispatch('finishClose'), menuAnimationDuration);
721
- } else {
722
- dispatch('open');
723
- id = setTimeout(() => dispatch('finishOpen'), menuAnimationDuration);
724
- }
725
-
726
- return () => clearTimeout(id);
727
- }, [isMenuOpen, isLargeMenu]);
728
-
729
- React.useEffect(() => {
730
- // reset openedSection when the menu has been closed
731
- if (menuStatus === 'closed') {
732
- setOpenedSection(-1);
733
- }
734
- }, [menuStatus]);
735
-
736
- const focusItem = React.useCallback(
737
- (item: {column: number; index: number} | undefined) => {
738
- if (!isEqual(focusedItem, item)) {
739
- setFocusedItem(item);
740
- }
741
- },
742
- [focusedItem]
743
- );
744
-
745
- React.useEffect(() => {
746
- // Find all the items of the section and focus the next (or previous) element
747
- const focusNextItem = (reverse?: boolean) => {
748
- if (focusedItem) {
749
- const itemsContainer = document.querySelector('[data-navigation-bar-menu-items]');
750
- const itemsList = Array.from(itemsContainer?.querySelectorAll('a,button') || []);
751
-
752
- const currentIndex = itemsList.findIndex((el) =>
753
- el.hasAttribute(
754
- `data-navigation-bar-menu-item-${focusedItem.column}-${focusedItem.index}`
755
- )
756
- );
757
-
758
- const nextIndex = reverse ? currentIndex - 1 : currentIndex + 1;
759
- (itemsList[(nextIndex + itemsList.length) % itemsList.length] as HTMLElement).focus();
760
- }
761
- };
762
-
763
- const handleKeyDown = (e: KeyboardEvent) => {
764
- switch (e.key) {
765
- case DOWN:
766
- if (focusedItem) {
767
- cancelEvent(e);
768
- focusNextItem();
769
- }
770
- break;
771
-
772
- case UP:
773
- if (focusedItem) {
774
- cancelEvent(e);
775
- focusNextItem(true);
776
- }
777
- break;
778
-
779
- case ESC:
780
- closeMenu();
781
- break;
782
-
783
- default:
784
- // Do nothing
785
- }
786
- };
787
- // Close menu when ESC key is pressed
788
- document.addEventListener('keydown', handleKeyDown, false);
789
- return () => {
790
- document.removeEventListener('keydown', handleKeyDown, false);
791
- };
792
- }, [closeMenu, focusedItem]);
793
-
794
- React.useEffect(() => {
795
- // Restore focusedItem when opened section changes (or when the menu is closed)
796
- setFocusedItem(undefined);
797
- }, [openedSection]);
798
-
799
- return (
800
- <MainNavigationBarDesktopMenuContext.Provider
801
- value={{
802
- isMenuOpen,
803
- openedSection,
804
- menuHeight,
805
- menuStatus,
806
- openSectionMenu,
807
- debouncedOpenSectionMenu: (index: number) => {
808
- setDebouncedOpenSectionIndex(index);
809
- debouncedOpenSectionMenu(index);
810
- },
811
- cancelDebouncedOpenSectionMenu: (index: number) => {
812
- if (index === debouncedOpenSectionIndex) {
813
- debouncedOpenSectionMenu.cancel();
814
- setDebouncedOpenSectionIndex(-1);
815
- }
816
- },
817
- closeMenu,
818
- setMenuHeight,
819
- setIsMenuHovered,
820
- setFocusedItem: focusItem,
821
- }}
822
- >
823
- {children}
824
- </MainNavigationBarDesktopMenuContext.Provider>
825
- );
826
- };
827
-
828
- export const useMainNavigationBarDesktopMenuState = (): MainNavigationBarDesktopMenuState =>
829
- React.useContext(MainNavigationBarDesktopMenuContext);
830
-
831
- const MainNavigationBarDesktopMenuSectionColumn = ({
832
- column,
833
- columnIndex,
834
- }: {
835
- column: SectionColumn;
836
- columnIndex: number;
837
- }) => {
838
- const {setFocusedItem, closeMenu} = useMainNavigationBarDesktopMenuState();
839
-
840
- return (
841
- <Stack space={24}>
842
- <Text2 medium color={vars.colors.textSecondary} transform="uppercase">
843
- {column.title}
844
- </Text2>
845
-
846
- <Stack space={16} role="list">
847
- {column.items.map(({title, ...touchableProps}, itemIdx) => (
848
- // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
849
- <div
850
- key={itemIdx}
851
- onFocus={() => setFocusedItem({column: columnIndex, index: itemIdx})}
852
- onBlur={() => setFocusedItem(undefined)}
853
- role="listitem"
854
- >
855
- <TextLink
856
- underline="on hover"
857
- className={styles.desktopMenuColumnItem}
858
- dataAttributes={{
859
- [`navigation-bar-menu-item-${columnIndex}-${itemIdx}`]: 'true',
860
- }}
861
- // Close the menu when one of the section items is pressed
862
- {...getInteractivePropsWithCloseMenu(touchableProps, closeMenu)}
863
- >
864
- {title}
865
- </TextLink>
866
- </div>
867
- ))}
868
- </Stack>
869
- </Stack>
870
- );
871
- };
872
-
873
- const MainNavigationBarDesktopMenuContent = ({
874
- section,
875
- index,
876
- isLargeNavigationBar,
877
- topSlotHeight,
878
- wide,
879
- }: {
880
- section: MainNavigationBarSection;
881
- index: number;
882
- isLargeNavigationBar: boolean;
883
- topSlotHeight: number;
884
- wide: boolean | WideConfig;
885
- }): JSX.Element => {
886
- const menuRef = React.useRef<HTMLDivElement>(null);
887
- const [isMenuContentScrollable, setIsMenuContentScrollable] = React.useState(false);
888
-
889
- const menuAnimationDuration = isRunningAcceptanceTest() ? 0 : styles.DESKTOP_MENU_ANIMATION_DURATION_MS;
890
- const topSpace =
891
- (isLargeNavigationBar ? NAVBAR_HEIGHT_DESKTOP_LARGE : NAVBAR_HEIGHT_DESKTOP) + topSlotHeight;
892
- const bottomSpace = 40;
893
-
894
- const {menuStatus, isMenuOpen, openedSection, closeMenu, setIsMenuHovered, setMenuHeight} =
895
- useMainNavigationBarDesktopMenuState();
896
-
897
- React.useEffect(() => {
898
- // Scroll to top of the content if the opened section changed
899
- if (menuRef.current && isMenuOpen) {
900
- menuRef.current.scrollTop = 0;
901
- }
902
-
903
- // Disable scroll in menu content until height's animation is finished to avoid
904
- // showing the scrollbar while the menu's container is changing it's height
905
- setIsMenuContentScrollable(false);
906
- if (isMenuOpen) {
907
- const id = setTimeout(() => setIsMenuContentScrollable(true), menuAnimationDuration);
908
- return () => clearTimeout(id);
909
- }
910
- }, [isMenuOpen, openedSection, menuAnimationDuration]);
911
-
912
- const [isContentVisible, setIsContentVisible] = React.useState(true);
913
-
914
- React.useEffect(() => {
915
- if (openedSection === index) {
916
- // If menu is opening, trigger the fade-in effect for current section
917
- if (menuStatus === 'opening') {
918
- setIsContentVisible(false);
919
- const id = requestAnimationFrame(() => setIsContentVisible(true));
920
- return () => cancelAnimationFrame(id);
921
- } else {
922
- setIsContentVisible(true);
923
- }
924
- }
925
- }, [menuStatus, openedSection, index]);
926
-
927
- React.useEffect(() => {
928
- // disable scroll when menu is closing to avoid showing the scrollbar
929
- if (menuStatus === 'closing') {
930
- setIsMenuContentScrollable(false);
931
- }
932
- }, [menuStatus]);
933
-
934
- const columns = section.menu?.columns || [];
935
- const customContent = section?.menu?.content;
936
-
937
- return (
938
- <div className={styles.desktopOnly}>
939
- <ThemeVariant variant="default">
940
- {openedSection === index && (
941
- <ResetResponsiveLayout>
942
- <div
943
- className={styles.desktopMenuContainer}
944
- onMouseEnter={() => setIsMenuHovered(true)}
945
- onMouseLeave={() => setIsMenuHovered(false)}
946
- style={{
947
- // disable pointer events when menu is closing
948
- pointerEvents:
949
- menuStatus === 'closed' || menuStatus === 'closing' ? 'none' : undefined,
950
- top: topSpace,
951
- maxHeight: `calc(100vh - ${topSpace}px - ${bottomSpace}px)`,
952
- overflowY: isMenuContentScrollable ? 'auto' : 'hidden',
953
- }}
954
- >
955
- <NavigationBarSideMargins wide={wide}>
956
- <div
957
- className={classnames(styles.desktopMenu, {
958
- [styles.desktopMenuContentFadeIn]: isContentVisible,
959
- })}
960
- ref={(el) => {
961
- if (el && isMenuOpen) {
962
- setMenuHeight(
963
- `min(${el.scrollHeight}px, calc(100vh - ${topSpace}px - ${bottomSpace}px))`
964
- );
965
- }
966
- }}
967
- >
968
- {customContent ? (
969
- typeof customContent === 'function' ? (
970
- customContent({closeMenu})
971
- ) : (
972
- customContent
973
- )
974
- ) : (
975
- <Grid
976
- rows={1}
977
- columns={12}
978
- gap={[24, 40]}
979
- dataAttributes={{'navigation-bar-menu-items': 'true'}}
980
- >
981
- {columns.map((column, columnIdx) => (
982
- <GridItem key={columnIdx} columnSpan={2}>
983
- <MainNavigationBarDesktopMenuSectionColumn
984
- column={column}
985
- columnIndex={columnIdx}
986
- />
987
- </GridItem>
988
- ))}
989
- </Grid>
990
- )}
991
- </div>
992
- </NavigationBarSideMargins>
993
- </div>
994
- </ResetResponsiveLayout>
995
- )}
996
- </ThemeVariant>
997
- </div>
998
- );
999
- };
1000
-
1001
- // This is the menu's background panel. The menu content is rendered separately for each tab
1002
- // in order to make the section's content follow the natural focus order of elements
1003
- // when using the keyboard or a screen reader to navigate
1004
- const MainNavigationBarDesktopMenuBackground = ({
1005
- isLargeNavigationBar,
1006
- topSlotHeight,
1007
- }: {
1008
- isLargeNavigationBar: boolean;
1009
- topSlotHeight: number;
1010
- }): JSX.Element => {
1011
- const topSpace =
1012
- (isLargeNavigationBar ? NAVBAR_HEIGHT_DESKTOP_LARGE : NAVBAR_HEIGHT_DESKTOP) + topSlotHeight;
1013
- const {menuHeight} = useMainNavigationBarDesktopMenuState();
1014
-
1015
- return (
1016
- <div className={styles.desktopOnly}>
1017
- <div className={styles.desktopMenuWrapper} style={{top: topSpace}}>
1018
- <div
1019
- className={styles.desktopMenuBackgroundContainer}
1020
- style={{
1021
- height: menuHeight,
1022
- }}
1023
- />
1024
- </div>
1025
- </div>
1026
- );
1027
- };
1028
-
1029
- const MainNavigationBarDesktopSmallMenu = ({
1030
- section,
1031
- isLargeNavigationBar,
1032
- topSlotHeight,
1033
- leftPosition,
1034
- index,
1035
- }: {
1036
- section: MainNavigationBarSection;
1037
- isLargeNavigationBar: boolean;
1038
- topSlotHeight: number;
1039
- leftPosition: number;
1040
- index: number;
1041
- }): JSX.Element => {
1042
- const topSpace =
1043
- (isLargeNavigationBar ? NAVBAR_HEIGHT_DESKTOP_LARGE : NAVBAR_HEIGHT_DESKTOP) + topSlotHeight;
1044
- const bottomSpace = 40;
1045
-
1046
- const columns = section.menu?.columns || [];
1047
- const customContent = section?.menu?.content;
1048
-
1049
- const {openedSection, menuStatus, setIsMenuHovered, closeMenu} = useMainNavigationBarDesktopMenuState();
1050
-
1051
- return (
1052
- <div className={styles.desktopOnly}>
1053
- {index === openedSection && (
1054
- <ThemeVariant variant="default">
1055
- <div
1056
- className={styles.desktopSmallMenuContainer}
1057
- onMouseEnter={() => setIsMenuHovered(true)}
1058
- onMouseLeave={() => setIsMenuHovered(false)}
1059
- style={{
1060
- // disable pointer events when menu is closing
1061
- pointerEvents:
1062
- menuStatus === 'closed' || menuStatus === 'closing' ? 'none' : undefined,
1063
- top: topSpace,
1064
- left: leftPosition,
1065
- maxHeight: `calc(100vh - ${topSpace}px - ${bottomSpace}px)`,
1066
- }}
1067
- >
1068
- {customContent ? (
1069
- typeof customContent === 'function' ? (
1070
- customContent({closeMenu})
1071
- ) : (
1072
- customContent
1073
- )
1074
- ) : (
1075
- <Stack space={40} dataAttributes={{'navigation-bar-menu-items': 'true'}}>
1076
- {columns.map((column, columnIdx) => (
1077
- <MainNavigationBarDesktopMenuSectionColumn
1078
- key={columnIdx}
1079
- column={column}
1080
- columnIndex={columnIdx}
1081
- />
1082
- ))}
1083
- </Stack>
1084
- )}
1085
- </div>
1086
- </ThemeVariant>
1087
- )}
1088
- </div>
1089
- );
1090
- };
1091
-
1092
- const MainNavigationBarDesktopSection = ({
1093
- section,
1094
- index,
1095
- selectedIndex,
1096
- isFirstSection,
1097
- isLastSection,
1098
- navigationBarRef,
1099
- variant,
1100
- isLargeNavigationBar,
1101
- topSlotHeight,
1102
- desktopLargeMenu,
1103
- wide,
1104
- }: {
1105
- section: MainNavigationBarSection;
1106
- index: number;
1107
- selectedIndex?: number;
1108
- isFirstSection: boolean;
1109
- isLastSection: boolean;
1110
- navigationBarRef: React.RefObject<HTMLDivElement | null>;
1111
- variant: NonDeprecatedVariant;
1112
- isLargeNavigationBar: boolean;
1113
- topSlotHeight: number;
1114
- desktopLargeMenu?: boolean;
1115
- wide: boolean | WideConfig;
1116
- }): JSX.Element => {
1117
- const {texts, t} = useTheme();
1118
- const {title, menu, ...touchableProps} = section;
1119
- const sectionRef = React.useRef<HTMLDivElement>(null);
1120
- const [smallMenuLeftPosition, setSmallMenuLeftPosition] = React.useState(0);
1121
- const [isMenuControlFocused, setIsMenuControlFocused] = React.useState(false);
1122
- const {
1123
- isMenuOpen,
1124
- openedSection,
1125
- openSectionMenu,
1126
- debouncedOpenSectionMenu,
1127
- cancelDebouncedOpenSectionMenu,
1128
- closeMenu,
1129
- } = useMainNavigationBarDesktopMenuState();
1130
-
1131
- const hasCustomInteraction =
1132
- touchableProps.href !== undefined ||
1133
- touchableProps.onPress !== undefined ||
1134
- touchableProps.to !== undefined;
1135
-
1136
- const openCurrentSectionMenu = React.useCallback(
1137
- (withDebounce?: boolean) => {
1138
- // Align small menu to left border of the section if it fits. Otherwise, align it to the right border
1139
- const getSmallMenuLeftPosition = () => {
1140
- const {left, right} = sectionRef.current?.getBoundingClientRect() || {left: 0, right: 0};
1141
- const maxLeftOffset =
1142
- (navigationBarRef.current?.getBoundingClientRect().right || 0) -
1143
- styles.DESKTOP_SMALL_MENU_WIDTH;
1144
-
1145
- return left <= maxLeftOffset ? left : right - styles.DESKTOP_SMALL_MENU_WIDTH;
1146
- };
1147
- if (!desktopLargeMenu) {
1148
- setSmallMenuLeftPosition(getSmallMenuLeftPosition());
1149
- }
1150
-
1151
- if (withDebounce) {
1152
- debouncedOpenSectionMenu(index);
1153
- } else {
1154
- openSectionMenu(index);
1155
- }
1156
- },
1157
- [desktopLargeMenu, index, openSectionMenu, debouncedOpenSectionMenu, navigationBarRef]
1158
- );
1159
-
1160
- React.useEffect(() => {
1161
- const handleKeyDown = (e: KeyboardEvent) => {
1162
- switch (e.key) {
1163
- // If arrow is focused and DOWN key is pressed, open the menu if it was closed
1164
- case DOWN:
1165
- if (isMenuControlFocused) {
1166
- cancelEvent(e);
1167
- openCurrentSectionMenu();
1168
- }
1169
- break;
1170
-
1171
- // If arrow is focused and UP key is pressed, close the menu if it was opened
1172
- case UP:
1173
- if (isMenuControlFocused) {
1174
- cancelEvent(e);
1175
- closeMenu();
1176
- }
1177
- break;
1178
-
1179
- default:
1180
- // Do nothing
1181
- }
1182
- };
1183
-
1184
- document.addEventListener('keydown', handleKeyDown, false);
1185
- return () => {
1186
- document.removeEventListener('keydown', handleKeyDown, false);
1187
- };
1188
- }, [index, isMenuControlFocused, openCurrentSectionMenu, closeMenu, menu, hasCustomInteraction]);
1189
-
1190
- const isSectionMenuOpen = isMenuOpen && openedSection === index;
1191
-
1192
- const menuButtonOnPress = React.useCallback(() => {
1193
- if (isSectionMenuOpen) {
1194
- closeMenu();
1195
- } else {
1196
- openCurrentSectionMenu();
1197
- }
1198
- }, [isSectionMenuOpen, openCurrentSectionMenu, closeMenu]);
1199
-
1200
- const getSectionInteractiveProps = React.useCallback(
1201
- (touchableProps: InteractiveProps) => {
1202
- // Open or close the menu when a section without interaction is pressed
1203
- if (!hasCustomInteraction) {
1204
- return {
1205
- onPress: menuButtonOnPress,
1206
- };
1207
- }
1208
-
1209
- return touchableProps as InteractiveProps;
1210
- },
1211
- [hasCustomInteraction, menuButtonOnPress]
1212
- );
1213
-
1214
- return (
1215
- <div className={styles.desktopMenuSectionWithArrowWrapper}>
1216
- <div
1217
- ref={sectionRef}
1218
- className={classnames(styles.desktopMenuSectionContainer, {
1219
- [styles.desktopMenuFirstSection]: isFirstSection,
1220
- [styles.desktopMenuLastSection]: isLastSection,
1221
- })}
1222
- onMouseEnter={() => openCurrentSectionMenu(true)}
1223
- onMouseLeave={() => cancelDebouncedOpenSectionMenu(index)}
1224
- onFocus={() => {
1225
- if (menu && !hasCustomInteraction) setIsMenuControlFocused(true);
1226
- }}
1227
- onBlur={() => {
1228
- if (menu && !hasCustomInteraction) setIsMenuControlFocused(false);
1229
- }}
1230
- >
1231
- <BaseTouchable
1232
- {...getSectionInteractiveProps(touchableProps as InteractiveProps)}
1233
- aria-label={
1234
- !hasCustomInteraction
1235
- ? `${section.title}, ${texts.mainNavigationBarOpenSectionMenu || t(tokens.mainNavigationBarOpenSectionMenu)}`
1236
- : undefined
1237
- }
1238
- aria-haspopup={!hasCustomInteraction}
1239
- aria-expanded={!hasCustomInteraction ? isSectionMenuOpen : undefined}
1240
- className={classnames(
1241
- styles.section,
1242
- {
1243
- [styles.selectedSectionVariants[variant === 'brand' ? 'brand' : 'default']]:
1244
- index === selectedIndex,
1245
- },
1246
- styles.textWrapperVariants[variant === 'brand' ? 'brand' : 'default']
1247
- )}
1248
- >
1249
- <Text3 regular color="inherit">
1250
- {title}
1251
- </Text3>
1252
- </BaseTouchable>
1253
- </div>
1254
- {menu && (
1255
- <>
1256
- {hasCustomInteraction && (
1257
- <div
1258
- className={styles.desktopMenuSectionArrowContainer}
1259
- onFocus={() => setIsMenuControlFocused(true)}
1260
- onBlur={() => setIsMenuControlFocused(false)}
1261
- >
1262
- <BaseTouchable
1263
- className={styles.desktopMenuSectionArrow}
1264
- aria-label={`${section.title}, ${texts.mainNavigationBarOpenSectionMenu || t(tokens.mainNavigationBarOpenSectionMenu)}`}
1265
- aria-haspopup
1266
- aria-expanded={isSectionMenuOpen}
1267
- onPress={() => {
1268
- if (isMenuControlFocused) {
1269
- menuButtonOnPress();
1270
- }
1271
- }}
1272
- style={{
1273
- pointerEvents: isMenuControlFocused ? 'auto' : 'none',
1274
- opacity: isMenuControlFocused ? 1 : 0,
1275
- // We are using the same chevron as in ButtonLink, and that svg has
1276
- // some extra space on the left that we want to ignore in this case
1277
- marginTop: -2,
1278
- }}
1279
- >
1280
- <MenuSectionArrow
1281
- size={8}
1282
- style={{
1283
- transform: `rotate(${isSectionMenuOpen ? -90 : 90}deg)`,
1284
- }}
1285
- />
1286
- </BaseTouchable>
1287
- </div>
1288
- )}
1289
- {desktopLargeMenu ? (
1290
- <MainNavigationBarDesktopMenuContent
1291
- section={section}
1292
- isLargeNavigationBar={isLargeNavigationBar}
1293
- topSlotHeight={topSlotHeight}
1294
- index={index}
1295
- wide={wide}
1296
- />
1297
- ) : (
1298
- <MainNavigationBarDesktopSmallMenu
1299
- section={section}
1300
- isLargeNavigationBar={isLargeNavigationBar}
1301
- topSlotHeight={topSlotHeight}
1302
- leftPosition={smallMenuLeftPosition}
1303
- index={index}
1304
- />
1305
- )}
1306
- </>
1307
- )}
1308
- </div>
1309
- );
1310
- };
1311
-
1312
- const MainNavigationBarDesktopSections = ({
1313
- sections,
1314
- selectedIndex,
1315
- navigationBarRef,
1316
- variant,
1317
- isLargeNavigationBar,
1318
- topSlotHeight,
1319
- hasRightContent,
1320
- desktopLargeMenu,
1321
- wide,
1322
- }: {
1323
- sections: ReadonlyArray<MainNavigationBarSection>;
1324
- selectedIndex?: number;
1325
- navigationBarRef: React.RefObject<HTMLDivElement | null>;
1326
- variant: NonDeprecatedVariant;
1327
- hasRightContent: boolean;
1328
- isLargeNavigationBar: boolean;
1329
- topSlotHeight: number;
1330
- desktopLargeMenu: boolean;
1331
- wide: boolean | WideConfig;
1332
- }): JSX.Element => {
1333
- const {openSectionMenu, openedSection, closeMenu} = useMainNavigationBarDesktopMenuState();
1334
-
1335
- return (
1336
- // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
1337
- <nav
1338
- className={classnames(styles.desktopOnly, styles.mainNavBarSectionsContainer)}
1339
- style={{
1340
- paddingLeft: !isLargeNavigationBar ? 48 : 0,
1341
- paddingRight: !isLargeNavigationBar && hasRightContent ? 136 : 0,
1342
- }}
1343
- onMouseEnter={() => {
1344
- // Mark current opened section as active to avoid closing the menu when moving the pointer
1345
- // from the menu content to the navigation bar (without hovering the tab itself)
1346
- if (openedSection !== -1) {
1347
- openSectionMenu(openedSection);
1348
- }
1349
- }}
1350
- onMouseLeave={closeMenu}
1351
- >
1352
- <Inline space={32}>
1353
- {sections.map((section, idx) => (
1354
- <MainNavigationBarDesktopSection
1355
- key={idx}
1356
- index={idx}
1357
- selectedIndex={selectedIndex}
1358
- navigationBarRef={navigationBarRef}
1359
- isFirstSection={idx === 0}
1360
- isLastSection={idx === sections.length - 1}
1361
- variant={variant}
1362
- section={section}
1363
- isLargeNavigationBar={isLargeNavigationBar}
1364
- topSlotHeight={topSlotHeight}
1365
- desktopLargeMenu={desktopLargeMenu}
1366
- wide={wide}
1367
- />
1368
- ))}
1369
- </Inline>
1370
- </nav>
1371
- );
1372
- };
1373
-
1374
- // It's not easy to coordinate the animation of the menu content height when switching between opened
1375
- // sections. This is because each section has it's own element where it displays the content. Instead,
1376
- // the contents of the sections are rendered without any animation, and we keep this wrapper around
1377
- // all of them, which "hides" the rendered smoothly by using animated clip-path
1378
- const MainNavigationBarContentWrapper = ({
1379
- children,
1380
- isLargeNavigationBar,
1381
- topSlotHeight,
1382
- desktopLargeMenu,
1383
- }: {
1384
- children: React.ReactNode;
1385
- isLargeNavigationBar: boolean;
1386
- topSlotHeight: number;
1387
- desktopLargeMenu: boolean;
1388
- }): JSX.Element => {
1389
- const {menuHeight} = useMainNavigationBarDesktopMenuState();
1390
- const topSpace =
1391
- (isLargeNavigationBar ? NAVBAR_HEIGHT_DESKTOP_LARGE : NAVBAR_HEIGHT_DESKTOP) + topSlotHeight;
1392
-
1393
- return (
1394
- <div
1395
- className={styles.mainNavigationBarContentWrapper}
1396
- style={
1397
- desktopLargeMenu
1398
- ? {
1399
- clipPath: `rect(0 100% calc(${topSpace}px + ${menuHeight}) 0)`,
1400
- WebkitClipPath: `rect(0 100% calc(${topSpace}px + ${menuHeight}) 0)`,
1401
- }
1402
- : undefined
1403
- }
1404
- >
1405
- {children}
1406
- </div>
1407
- );
1408
- };
1409
-
1410
- export const MainNavigationBar = ({
1411
- sections = [],
1412
- selectedIndex,
1413
- right,
1414
- topSlot,
1415
- topSlotBackgroundColor,
1416
- variant = 'default',
1417
- topFixed = true,
1418
- withBorder = true,
1419
- burgerMenuExtra,
1420
- logo,
1421
- large = false,
1422
- desktopLargeMenu = false,
1423
- wide = false,
1424
- }: MainNavigationBarProps): JSX.Element => {
1425
- const {texts, t} = useTheme();
1426
- const menuId = React.useId();
1427
- const {isTabletOrSmaller} = useScreenSize();
1428
- const logoElement = logo || <Logo size={{mobile: 40, desktop: 48}} />;
1429
- const hasBottomSections = large && sections.length > 0;
1430
-
1431
- const [isBurgerMenuOpen, setIsBurgerMenuOpen] = React.useState(false);
1432
- const [disableFocusTrap, setDisableFocusTrap] = React.useState(true);
1433
- const navigationBarRef = React.useRef<HTMLDivElement>(null);
1434
- const {height: topSlotHeight, ref: topSlotRef} = useElementDimensions();
1435
- const setModalState = useSetModalState();
1436
-
1437
- const normalizedVariant = normalizeVariant(variant);
1438
-
1439
- const desktopSections = (
1440
- <MainNavigationBarDesktopSections
1441
- sections={sections}
1442
- selectedIndex={selectedIndex}
1443
- navigationBarRef={navigationBarRef}
1444
- variant={normalizedVariant}
1445
- hasRightContent={!!right}
1446
- isLargeNavigationBar={hasBottomSections}
1447
- topSlotHeight={topSlotHeight}
1448
- desktopLargeMenu={desktopLargeMenu}
1449
- wide={wide}
1450
- />
1451
- );
1452
-
1453
- const openMenu = () => {
1454
- setIsBurgerMenuOpen(true);
1455
- setModalState({isModalOpen: true});
1456
- };
1457
-
1458
- const closeMenu = () => {
1459
- setIsBurgerMenuOpen(false);
1460
- setModalState({isModalOpen: false});
1461
- };
1462
-
1463
- const showBurger = sections.length > 1;
1464
-
1465
- const mainNavBar = (
1466
- <ThemeVariant variant={normalizedVariant}>
1467
- <Header
1468
- topFixed={topFixed}
1469
- withBorder={withBorder}
1470
- isBurgerMenuOpen={isBurgerMenuOpen}
1471
- variant={normalizedVariant}
1472
- dataAttributes={{'component-name': 'MainNavigationBar'}}
1473
- >
1474
- {desktopLargeMenu && (
1475
- <MainNavigationBarDesktopMenuBackground
1476
- isLargeNavigationBar={hasBottomSections}
1477
- topSlotHeight={topSlotHeight}
1478
- />
1479
- )}
1480
- <MainNavigationBarContentWrapper
1481
- isLargeNavigationBar={hasBottomSections}
1482
- topSlotHeight={topSlotHeight}
1483
- desktopLargeMenu={desktopLargeMenu}
1484
- >
1485
- {topSlot && (
1486
- <NavigationBarSideMargins wide={wide} backgroundColor={topSlotBackgroundColor}>
1487
- <div ref={topSlotRef}>{topSlot}</div>
1488
- </NavigationBarSideMargins>
1489
- )}
1490
- <NavigationBarSideMargins wide={wide}>
1491
- <NavigationBarContentContainer
1492
- ref={navigationBarRef}
1493
- right={right}
1494
- expandRightContent={hasBottomSections}
1495
- >
1496
- {showBurger && (
1497
- <Touchable
1498
- className={styles.burgerMenuButton}
1499
- aria-live="polite"
1500
- aria-label={
1501
- isBurgerMenuOpen
1502
- ? texts.closeNavigationMenu || t(tokens.closeNavigationMenu)
1503
- : texts.openNavigationMenu || t(tokens.openNavigationMenu)
1504
- }
1505
- aria-expanded={isBurgerMenuOpen}
1506
- aria-controls={menuId}
1507
- onPress={isBurgerMenuOpen ? closeMenu : openMenu}
1508
- >
1509
- <BurgerMenuIcon isOpen={isBurgerMenuOpen} />
1510
- </Touchable>
1511
- )}
1512
- <div className={styles.logoContainer}>{logoElement}</div>
1513
- {!hasBottomSections && desktopSections}
1514
- </NavigationBarContentContainer>
1515
- {hasBottomSections && (
1516
- <NavigationBarContentContainer desktopOnly>
1517
- {desktopSections}
1518
- </NavigationBarContentContainer>
1519
- )}
1520
- </NavigationBarSideMargins>
1521
- </MainNavigationBarContentWrapper>
1522
- </Header>
1523
- {topFixed && topSlotHeight > 0 && <div style={{height: topSlotHeight}} />}
1524
- {topFixed && <div className={hasBottomSections ? styles.spacerLarge : styles.spacer} />}
1525
- </ThemeVariant>
1526
- );
1527
-
1528
- return (
1529
- <MainNavigationBarDesktopMenuContextProvider sections={sections} isLargeMenu={desktopLargeMenu}>
1530
- {!isTabletOrSmaller ? (
1531
- mainNavBar
1532
- ) : (
1533
- <>
1534
- <FocusTrap disabled={disableFocusTrap} group="burger-menu-lock">
1535
- {mainNavBar}
1536
- </FocusTrap>
1537
- <MainNavigationBarBurgerMenu
1538
- open={isBurgerMenuOpen}
1539
- id={menuId}
1540
- sections={sections}
1541
- extra={burgerMenuExtra}
1542
- closeMenu={closeMenu}
1543
- topSlotHeight={topSlotHeight}
1544
- disableFocusTrap={disableFocusTrap}
1545
- setDisableFocusTrap={setDisableFocusTrap}
1546
- />
1547
- </>
1548
- )}
1549
- </MainNavigationBarDesktopMenuContextProvider>
1550
- );
1551
- };
1552
-
1553
- type FunnelNavigationBarProps = {
1554
- variant?: Variant;
1555
- logo?: React.ReactElement;
1556
- right?: React.ReactElement;
1557
- topFixed?: boolean;
1558
- children?: undefined;
1559
- withBorder?: boolean;
1560
- wide?: boolean | WideConfig;
1561
- };
1562
-
1563
- export const FunnelNavigationBar = ({
1564
- logo,
1565
- right,
1566
- variant = 'default',
1567
- topFixed = true,
1568
- withBorder = true,
1569
- wide = false,
1570
- }: FunnelNavigationBarProps): JSX.Element => {
1571
- logo = logo ?? <Logo size={{mobile: 40, desktop: 48}} />;
1572
-
1573
- const normalizedVariant = normalizeVariant(variant);
1574
-
1575
- return (
1576
- <ThemeVariant variant={normalizedVariant}>
1577
- <Header
1578
- topFixed={topFixed}
1579
- withBorder={withBorder}
1580
- variant={normalizedVariant}
1581
- dataAttributes={{'component-name': 'FunnelNavigationBar'}}
1582
- >
1583
- <NavigationBarSideMargins wide={wide}>
1584
- <GridLayout template="10">
1585
- <NavigationBarContentContainer right={right} expandRightContent>
1586
- {logo}
1587
- </NavigationBarContentContainer>
1588
- </GridLayout>
1589
- </NavigationBarSideMargins>
1590
- </Header>
1591
- {topFixed && <div className={styles.spacer} />}
1592
- </ThemeVariant>
1593
- );
1594
- };
1595
-
1596
- type NavigationBarActionGroupProps = {
1597
- children: React.ReactNode;
1598
- };
1599
-
1600
- export const NavigationBarActionGroup = ({children}: NavigationBarActionGroupProps): JSX.Element => {
1601
- return (
1602
- <div className={styles.lineHeightFix} data-component-name="NavigationBarActionGroup">
1603
- <Inline space={24} alignItems="center">
1604
- {children}
1605
- </Inline>
1606
- </div>
1607
- );
1608
- };
1609
-
1610
- type NavigationBarActionProps = TouchableProps;
1611
-
1612
- export const NavigationBarAction = ({children, ...touchableProps}: NavigationBarActionProps): JSX.Element => {
1613
- const themeVariant = useThemeVariant();
1614
- return (
1615
- <BaseTouchable
1616
- {...touchableProps}
1617
- className={classnames(
1618
- styles.navigationBarAction,
1619
- styles.lineHeightFix,
1620
- styles.textWrapperVariants[themeVariant]
1621
- )}
1622
- dataAttributes={{'component-name': 'NavigationBarAction'}}
1623
- >
1624
- <Inline space={16} alignItems="center">
1625
- {React.Children.map(children, (child) =>
1626
- typeof child === 'string' ? (
1627
- <Text2 regular color="inherit">
1628
- {child}
1629
- </Text2>
1630
- ) : (
1631
- child
1632
- )
1633
- )}
1634
- </Inline>
1635
- </BaseTouchable>
1636
- );
1637
- };