@telefonica/mistica 16.59.0-beta.1 → 16.60.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 +2 -14
  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
package/src/carousel.tsx DELETED
@@ -1,1300 +0,0 @@
1
- 'use client';
2
- import * as React from 'react';
3
- import IconChevronLeftRegular from './generated/mistica-icons/icon-chevron-left-regular';
4
- import IconChevronRightRegular from './generated/mistica-icons/icon-chevron-right-regular';
5
- import {useIsInViewport, useIsomorphicLayoutEffect, useScreenSize, useTheme} from './hooks';
6
- import Inline from './inline';
7
- import classNames from 'classnames';
8
- import {ThemeVariant, useThemeVariant} from './theme-variant-context';
9
- import {getPrefixedDataAttributes, listenResize} from './utils/dom';
10
- import {isAndroid, isIos, isRunningAcceptanceTest} from './utils/platform';
11
- import {useDocumentVisibility} from './utils/document-visibility';
12
- import * as styles from './carousel.css';
13
- import * as mediaStyles from './image.css';
14
- import {useDesktopContainerType} from './desktop-container-type-context';
15
- import {VIVO_NEW_SKIN} from './skins/constants';
16
- import {applyCssVars} from './utils/css';
17
- import {ResetResponsiveLayout} from './responsive-layout';
18
- import {InternalIconButton, ToggleIconButton} from './icon-button';
19
- import IconPauseFilled from './generated/mistica-icons/icon-pause-filled';
20
- import IconPlayFilled from './generated/mistica-icons/icon-play-filled';
21
- import IconReloadRegular from './generated/mistica-icons/icon-reload-regular';
22
- import * as tokens from './text-tokens';
23
- import {isClientSide} from './utils/environment';
24
-
25
- import type {DesktopContainerType} from './desktop-container-type-context';
26
- import type {ByBreakpoint, DataAttributes} from './utils/types';
27
-
28
- const useShouldAutoplay = (
29
- autoplay: boolean,
30
- ref: React.RefObject<HTMLElement | null>
31
- ): {isAutoplayEnabled: boolean; shouldAutoplay: boolean; setShouldAutoPlay: (enabled: boolean) => void} => {
32
- const reducedMotion = isClientSide()
33
- ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
34
- : false;
35
- const [isAutoplayEnabled, setIsAutoplayEnabled] = React.useState(!!autoplay && !reducedMotion);
36
-
37
- const isDocumentVisible = useDocumentVisibility();
38
- const isInViewport = useIsInViewport(ref, false);
39
- return {
40
- isAutoplayEnabled: isAutoplayEnabled && !!autoplay,
41
- shouldAutoplay: isInViewport && isDocumentVisible && !!autoplay && isAutoplayEnabled,
42
- setShouldAutoPlay: setIsAutoplayEnabled,
43
- };
44
- };
45
-
46
- const throwMissingProviderError = () => {
47
- throw new Error('You must wrap your component with a CarouselContextProvider to use CarouselContext');
48
- };
49
- const defaultBulletProps = {currentIndex: 0, numPages: 0};
50
- const defaultAutoplayProps = {
51
- isAutoplayEnabled: false,
52
- isAtLastPage: false,
53
- onAutoplayChanged: throwMissingProviderError,
54
- };
55
- const defaultPageControlsProps = {
56
- setShouldAutoplay: throwMissingProviderError,
57
- prevArrowEnabled: false,
58
- nextArrowEnabled: false,
59
- };
60
-
61
- type GoToPage = (pageIndex: number, animate?: boolean) => void;
62
- type SetIsAutoplayEnabled = (isAutoplayEnabled: boolean) => void;
63
-
64
- type PageBulletsProps = {
65
- currentIndex: number;
66
- numPages: number | ByBreakpoint<number>;
67
- };
68
-
69
- type AutoplayControlProps = {
70
- isAutoplayEnabled: boolean;
71
- isAtLastPage: boolean;
72
- onAutoplayChanged: (autoplay: boolean) => void;
73
- };
74
-
75
- type PageControlsProps = {
76
- setShouldAutoplay: (autoplay: boolean) => void;
77
- prevArrowEnabled: boolean;
78
- nextArrowEnabled: boolean;
79
- };
80
-
81
- type CarouselControls = {
82
- goPrev: () => void;
83
- goNext: () => void;
84
- goToPage: GoToPage;
85
- autoplayControlProps: AutoplayControlProps;
86
- pageControlsProps: PageControlsProps;
87
- bulletsProps: PageBulletsProps;
88
- };
89
-
90
- const CarouselContext = React.createContext<CarouselControls>({
91
- goPrev: throwMissingProviderError,
92
- goNext: throwMissingProviderError,
93
- goToPage: throwMissingProviderError,
94
- bulletsProps: defaultBulletProps,
95
- autoplayControlProps: defaultAutoplayProps,
96
- pageControlsProps: defaultPageControlsProps,
97
- });
98
-
99
- const CarouselControlsSetterContext = React.createContext<{
100
- setGoPrev: (goPrev: () => void) => void;
101
- setGoNext: (goNext: () => void) => void;
102
- setGoToPage: (goToPage: GoToPage) => void;
103
- setBulletsProps: (bulletsProps: PageBulletsProps) => void;
104
- setAutoplayControlProps: (autoplayControlProps: AutoplayControlProps) => void;
105
- setPageControlsProps: (pageControlsProps: PageControlsProps) => void;
106
- setIsAutoplayEnabledSetter: (isAutoplayEnabledSetter: SetIsAutoplayEnabled) => void;
107
- } | null>(null);
108
-
109
- export const CarouselContextProvider = ({children}: {children: React.ReactNode}): JSX.Element => {
110
- const [bulletsProps, setBulletsProps] = React.useState<PageBulletsProps>(defaultBulletProps);
111
- const [autoplayControlProps, setAutoplayControlProps] =
112
- React.useState<AutoplayControlProps>(defaultAutoplayProps);
113
- const [pageControlsProps, setPageControlsProps] =
114
- React.useState<PageControlsProps>(defaultPageControlsProps);
115
- const goPrevRef = React.useRef<() => void>(throwMissingProviderError);
116
- const goNextRef = React.useRef<() => void>(throwMissingProviderError);
117
- const goToPageRef = React.useRef<GoToPage>(throwMissingProviderError);
118
- const setIsAutoplayEnabledRef =
119
- React.useRef<(isAutoplayEnabled: boolean) => void>(throwMissingProviderError);
120
-
121
- const controls = React.useMemo<CarouselControls>(
122
- () => ({
123
- goPrev: () => {
124
- goPrevRef.current();
125
- },
126
- goNext: () => {
127
- goNextRef.current();
128
- },
129
- goToPage: (pageIndex, animate = true) => {
130
- goToPageRef.current(pageIndex, animate);
131
- },
132
- bulletsProps,
133
- autoplayControlProps,
134
- pageControlsProps,
135
- }),
136
- [bulletsProps, autoplayControlProps, pageControlsProps]
137
- );
138
-
139
- return (
140
- <CarouselContext.Provider value={controls}>
141
- <CarouselControlsSetterContext.Provider
142
- value={{
143
- setGoPrev: (goPrev) => {
144
- goPrevRef.current = goPrev;
145
- },
146
- setGoNext: (goNext) => {
147
- goNextRef.current = goNext;
148
- },
149
- setGoToPage: (goToPage) => {
150
- goToPageRef.current = goToPage;
151
- },
152
- setBulletsProps,
153
- setAutoplayControlProps,
154
- setPageControlsProps,
155
- setIsAutoplayEnabledSetter: (isAutoplayEnabledSetter) => {
156
- setIsAutoplayEnabledRef.current = isAutoplayEnabledSetter;
157
- },
158
- }}
159
- >
160
- {children}
161
- </CarouselControlsSetterContext.Provider>
162
- </CarouselContext.Provider>
163
- );
164
- };
165
-
166
- export const useCarouselContext = (): CarouselControls => React.useContext(CarouselContext);
167
- export const CarouselContextConsumer = CarouselContext.Consumer;
168
-
169
- export const PageBullets = ({currentIndex, numPages}: PageBulletsProps): JSX.Element => {
170
- const themeVariant = useThemeVariant();
171
- const {isTablet, isDesktopOrBigger} = useScreenSize();
172
- const pagesCount =
173
- typeof numPages === 'number'
174
- ? numPages
175
- : isDesktopOrBigger
176
- ? numPages.desktop
177
- : isTablet
178
- ? numPages.tablet ?? numPages.mobile
179
- : numPages.mobile;
180
-
181
- const getClassNames = (bulletIndex: number) => {
182
- const classNames: {[key: string]: boolean} = {};
183
-
184
- if (themeVariant === 'brand' || themeVariant === 'media') {
185
- classNames[currentIndex === bulletIndex ? styles.bulletActiveBrand : styles.bulletBrand] = true;
186
- } else if (themeVariant === 'negative') {
187
- classNames[currentIndex === bulletIndex ? styles.bulletActiveNegative : styles.bulletNegative] =
188
- true;
189
- } else {
190
- classNames[currentIndex === bulletIndex ? styles.bulletActive : styles.bullet] = true;
191
- }
192
-
193
- if (currentIndex === bulletIndex) {
194
- classNames[styles.bulletActiveSizing] = true;
195
- return classNames;
196
- }
197
-
198
- const distanceToCurrent = Math.abs(bulletIndex - currentIndex);
199
-
200
- if (pagesCount <= styles.VISIBLE_BULLETS || distanceToCurrent === 1) {
201
- classNames[styles.bulletInactiveSizing] = true;
202
- return classNames;
203
- }
204
-
205
- const isFirstOrLastItemActive = currentIndex === 0 || currentIndex === pagesCount - 1;
206
-
207
- if (isFirstOrLastItemActive) {
208
- classNames[styles.bulletInactiveSizing] = distanceToCurrent === 2;
209
- classNames[styles.bulletInactiveMediumSizing] = distanceToCurrent === 3;
210
- classNames[styles.bulletInactiveSmallSizing] = distanceToCurrent > 3;
211
-
212
- return classNames;
213
- }
214
-
215
- classNames[styles.bulletInactiveMediumSizing] = distanceToCurrent === 2;
216
- classNames[styles.bulletInactiveSmallSizing] = distanceToCurrent > 2;
217
-
218
- return classNames;
219
- };
220
-
221
- const getLeftOffsetPosition = (bulletIndex: number) => {
222
- if (currentIndex + 2 < styles.VISIBLE_BULLETS) {
223
- return bulletIndex;
224
- }
225
-
226
- if (pagesCount - currentIndex + 1 < styles.VISIBLE_BULLETS) {
227
- return bulletIndex - (pagesCount - styles.VISIBLE_BULLETS);
228
- }
229
-
230
- return bulletIndex - (currentIndex - 2);
231
- };
232
-
233
- return (
234
- <div
235
- {...getPrefixedDataAttributes({'component-name': 'PageBullets', testid: 'PageBullets'})}
236
- className={classNames(styles.bulletsScrollableContainerBase, {
237
- [styles.bulletsScrollableContainer]: pagesCount > styles.VISIBLE_BULLETS,
238
- })}
239
- >
240
- {Array.from({length: pagesCount}, (_, i: number) => {
241
- const bulletLeftOffsetPosition = getLeftOffsetPosition(i);
242
-
243
- return (
244
- <div
245
- className={classNames(
246
- {
247
- [styles.scrollableBullet]: pagesCount > styles.VISIBLE_BULLETS,
248
- },
249
- typeof numPages === 'number'
250
- ? {[styles.bulletButton]: true, [styles.bulletVisibility]: i < numPages}
251
- : {
252
- [styles.bulletButton]: true,
253
- [styles.bulletVisibilityMobile]: i < numPages.mobile,
254
- [styles.bulletVisibilityTablet]:
255
- i < (numPages.tablet ?? numPages.mobile),
256
- [styles.bulletVisibilityDesktop]: i < numPages.desktop,
257
- }
258
- )}
259
- key={i}
260
- data-testid={currentIndex === i ? 'active-bullet' : 'bullet'}
261
- style={{
262
- ...applyCssVars({
263
- [styles.vars.desktopBulletLeftPosition]:
264
- `${bulletLeftOffsetPosition * styles.LARGE_BULLET_FULL_SIZE}px`,
265
- [styles.vars.mobileBulletLeftPosition]:
266
- `${bulletLeftOffsetPosition * styles.SMALL_BULLET_FULL_SIZE}px`,
267
- }),
268
- }}
269
- >
270
- <div className={classNames(getClassNames(i))} />
271
- </div>
272
- );
273
- })}
274
- </div>
275
- );
276
- };
277
-
278
- const useControlLabel = (type: 'prev' | 'next', pageIndex?: number, pageCount?: number) => {
279
- const {texts, t} = useTheme();
280
-
281
- const hasPageInfo = pageIndex !== undefined && pageCount !== undefined;
282
- const isFirstPage = hasPageInfo && pageIndex === 0;
283
- const isLastPage = hasPageInfo && pageIndex === pageCount - 1;
284
-
285
- const getPageNumber = (pageIndex: number) => {
286
- if (type === 'prev') {
287
- return isFirstPage ? pageIndex + 1 : pageIndex;
288
- }
289
- return isLastPage ? pageIndex + 1 : pageIndex + 2;
290
- };
291
-
292
- const pageNumberText = hasPageInfo
293
- ? `, ${t(texts.carouselPageNumber || tokens.carouselPageNumber, getPageNumber(pageIndex), pageCount)}`
294
- : '';
295
-
296
- if (type === 'prev') {
297
- return isFirstPage
298
- ? (texts.carouselFirstButton || t(tokens.carouselFirstButton)) + pageNumberText
299
- : (texts.carouselPrevButton || t(tokens.carouselPrevButton)) + pageNumberText;
300
- }
301
-
302
- return isLastPage
303
- ? (texts.carouselLastButton || t(tokens.carouselLastButton)) + pageNumberText
304
- : (texts.carouselNextButton || t(tokens.carouselNextButton)) + pageNumberText;
305
- };
306
-
307
- type CarouselPageControlsProps = PageControlsProps & {
308
- bleedLeft?: boolean;
309
- bleedRight?: boolean;
310
- goPrev: () => void;
311
- goNext: () => void;
312
- pagesCount?: number;
313
- currentPageIndex?: number;
314
- };
315
-
316
- export const CarouselPageControls = ({
317
- bleedLeft,
318
- bleedRight,
319
- goPrev,
320
- goNext,
321
- setShouldAutoplay,
322
- prevArrowEnabled,
323
- nextArrowEnabled,
324
- pagesCount,
325
- currentPageIndex,
326
- }: CarouselPageControlsProps): JSX.Element => {
327
- const variant = useThemeVariant();
328
- const prevPageLabel = useControlLabel('prev', currentPageIndex, pagesCount);
329
- const nextPageLabel = useControlLabel('next', currentPageIndex, pagesCount);
330
-
331
- return (
332
- <Inline space={variant === 'media' ? 16 : 8}>
333
- <InternalIconButton
334
- Icon={IconChevronLeftRegular}
335
- aria-label={prevPageLabel}
336
- type="neutral"
337
- backgroundType={variant === 'media' ? 'transparent' : 'soft'}
338
- small
339
- bleedLeft={bleedLeft}
340
- onPress={() => {
341
- goPrev();
342
- setShouldAutoplay(false);
343
- }}
344
- aria-disabled={!prevArrowEnabled}
345
- />
346
- <InternalIconButton
347
- Icon={IconChevronRightRegular}
348
- aria-label={nextPageLabel}
349
- type="neutral"
350
- backgroundType={variant === 'media' ? 'transparent' : 'soft'}
351
- small
352
- bleedRight={bleedRight}
353
- onPress={() => {
354
- goNext();
355
- setShouldAutoplay(false);
356
- }}
357
- aria-disabled={!nextArrowEnabled}
358
- />
359
- </Inline>
360
- );
361
- };
362
-
363
- type CarouselAutoplayControlProps = AutoplayControlProps & {
364
- bleedLeft?: boolean;
365
- bleedRight?: boolean;
366
- };
367
-
368
- export const CarouselAutoplayControl = ({
369
- isAutoplayEnabled,
370
- isAtLastPage,
371
- onAutoplayChanged,
372
- bleedLeft = false,
373
- bleedRight = false,
374
- }: CarouselAutoplayControlProps): JSX.Element => {
375
- const {texts, t} = useTheme();
376
- return (
377
- <ToggleIconButton
378
- checkedProps={{
379
- Icon: IconPauseFilled,
380
- type: 'neutral',
381
- 'aria-label': texts.carouselPauseAutoplay || t(tokens.carouselPauseAutoplay),
382
- }}
383
- uncheckedProps={{
384
- Icon: isAtLastPage ? IconReloadRegular : IconPlayFilled,
385
- type: 'neutral',
386
- 'aria-label': isAtLastPage
387
- ? texts.carouselReloadAutoplay || t(tokens.carouselReloadAutoplay)
388
- : texts.carouselEnableAutoplay || t(tokens.carouselEnableAutoplay),
389
- }}
390
- small
391
- bleedLeft={bleedLeft}
392
- bleedRight={bleedRight}
393
- onChange={onAutoplayChanged}
394
- checked={isAutoplayEnabled}
395
- />
396
- );
397
- };
398
-
399
- type DesktopItemsPerPage = {small?: number; medium?: number; large?: number} | number;
400
- type ItemsPerPageProp = {mobile?: number; tablet?: number; desktop?: DesktopItemsPerPage} | number;
401
-
402
- const selectDesktopItemsPerPage = (
403
- containerType: DesktopContainerType,
404
- defaultItemsPerPage: {small: number; medium: number; large: number},
405
- itemsPerPage?: DesktopItemsPerPage
406
- ): number => {
407
- if (!itemsPerPage) {
408
- return defaultItemsPerPage[containerType];
409
- }
410
- if (typeof itemsPerPage === 'number') {
411
- return itemsPerPage;
412
- }
413
- return itemsPerPage[containerType] || defaultItemsPerPage[containerType];
414
- };
415
-
416
- const normalizeItemsPerPage = (
417
- desktopContainerType: DesktopContainerType,
418
- itemsPerPage?: ItemsPerPageProp
419
- ): {
420
- mobile: number;
421
- tablet: number;
422
- desktop: number;
423
- } => {
424
- const defaultItemsPerPage = {mobile: 1, tablet: 2, desktop: {small: 1, medium: 2, large: 3}};
425
- if (!itemsPerPage) {
426
- return {
427
- ...defaultItemsPerPage,
428
- desktop: selectDesktopItemsPerPage(desktopContainerType, defaultItemsPerPage.desktop),
429
- };
430
- }
431
-
432
- if (typeof itemsPerPage === 'number') {
433
- return {
434
- mobile: itemsPerPage,
435
- tablet: itemsPerPage,
436
- desktop: itemsPerPage,
437
- };
438
- }
439
-
440
- const itemsPerPageDesktop = selectDesktopItemsPerPage(
441
- desktopContainerType,
442
- defaultItemsPerPage.desktop,
443
- itemsPerPage.desktop
444
- );
445
-
446
- return {
447
- ...defaultItemsPerPage,
448
- ...itemsPerPage,
449
- desktop: itemsPerPageDesktop,
450
- };
451
- };
452
-
453
- const calcPagesScrollPositions = (itemsScrollPosition: Array<number>, numPages: number) => {
454
- if (itemsScrollPosition.length === 0) {
455
- return [];
456
- }
457
-
458
- const itemsPerPage = Math.ceil(itemsScrollPosition.length / numPages);
459
- const pagesScrollPositions = [];
460
- for (let i = 0; i < itemsScrollPosition.length; i += itemsPerPage) {
461
- pagesScrollPositions.push(itemsScrollPosition[i]);
462
- }
463
- pagesScrollPositions[pagesScrollPositions.length - 1] =
464
- itemsScrollPosition[itemsScrollPosition.length - itemsPerPage];
465
-
466
- return pagesScrollPositions;
467
- };
468
-
469
- const calcCurrentPageIndex = (scrollPosition: number, pagesScrollPositions: Array<number>) => {
470
- const middlePageScrollPositions = [];
471
- for (let i = 0; i < pagesScrollPositions.length; i++) {
472
- if (i === 0) {
473
- middlePageScrollPositions.push(pagesScrollPositions[0]);
474
- } else {
475
- middlePageScrollPositions.push((pagesScrollPositions[i] + pagesScrollPositions[i - 1]) / 2);
476
- }
477
- }
478
- for (let i = middlePageScrollPositions.length - 1; i >= 0; i--) {
479
- if (scrollPosition - middlePageScrollPositions[i] >= -1) {
480
- return i;
481
- }
482
- }
483
- return 0;
484
- };
485
-
486
- const DEFAULT_AUTOPLAY_TIME = 5000;
487
-
488
- type BaseCarouselProps = {
489
- items: ReadonlyArray<React.ReactNode>;
490
- itemStyle?: React.CSSProperties;
491
- itemClassName?: string;
492
- withBullets?: boolean;
493
- /**
494
- * @deprecated use CarouselContextProvider and CarouselContextConsumer to provide bullets props to custom bullets component.
495
- * See an example here: https://mistica-web.vercel.app/?path=/story/components-carousels-carousel--with-carousel-context
496
- */
497
- renderBullets?: (bulletsProps: PageBulletsProps) => React.ReactNode;
498
- initialActiveItem?: number;
499
- itemsPerPage?: ItemsPerPageProp;
500
- /** scrolls one page by default */
501
- itemsToScroll?: number;
502
- mobilePageOffset?: 'regular' | 'large';
503
- /** If true, scroll snap doesn't apply and the user has a free scroll */
504
- free?: boolean;
505
- gap?: number;
506
- /** centered mode only applies to mobile. It includes a horizontal padding of half of the size of an item to show the items centered */
507
- centered?: boolean;
508
- autoplay?: boolean | {time: number; loop?: boolean};
509
- withControls?: boolean;
510
- onPageChange?: (newPageInfo: {pageIndex: number; shownItemIndexes: Array<number>}) => void;
511
- dataAttributes?: DataAttributes;
512
- children?: void;
513
- 'aria-label'?: string;
514
- 'aria-labelledby'?: string;
515
- };
516
-
517
- const BaseCarousel = ({
518
- items,
519
- itemStyle,
520
- itemClassName,
521
- withBullets,
522
- renderBullets,
523
- initialActiveItem,
524
- itemsPerPage,
525
- itemsToScroll,
526
- mobilePageOffset,
527
- gap,
528
- free,
529
- centered,
530
- autoplay,
531
- withControls = true,
532
- onPageChange,
533
- dataAttributes,
534
- 'aria-label': ariaLabelProp,
535
- 'aria-labelledby': ariaLabelledByProp,
536
- }: BaseCarouselProps): JSX.Element => {
537
- const {platformOverrides, skinName, texts, t} = useTheme();
538
-
539
- const desktopContainerType = useDesktopContainerType();
540
- const itemsPerPageConfig = normalizeItemsPerPage(desktopContainerType || 'large', itemsPerPage);
541
-
542
- const {isDesktopOrBigger, isTablet} = useScreenSize();
543
- const mobileOrTabletItemsPerPage = isTablet ? itemsPerPageConfig.tablet : itemsPerPageConfig.mobile;
544
- const itemsPerPageFloor = Math.max(
545
- Math.floor(isDesktopOrBigger ? itemsPerPageConfig.desktop : mobileOrTabletItemsPerPage),
546
- 1
547
- );
548
-
549
- const carouselRef = React.useRef<HTMLDivElement>(null);
550
-
551
- const pagesCountMobile = Math.ceil(items.length / Math.max(Math.floor(itemsPerPageConfig.mobile), 1));
552
- const pagesCountTablet = Math.ceil(items.length / Math.max(Math.floor(itemsPerPageConfig.tablet), 1));
553
- const pagesCountDesktop = Math.ceil(items.length / Math.max(Math.floor(itemsPerPageConfig.desktop), 1));
554
- const pagesCount = Math.ceil(items.length / itemsPerPageFloor);
555
-
556
- // ScrollRight is initialized to 1 to avoid the next arrow being disabled when the carousel is first rendered.
557
- // This is required to make the SSR test pass, and taking advantage of the fact that this is the base case (having more than one page)
558
- const [{scrollLeft, scrollRight}, setScroll] = React.useState({scrollLeft: 0, scrollRight: 1});
559
-
560
- const [itemScrollPositions, setItemScrollPositions] = React.useState<Array<number>>([]);
561
-
562
- const pagesScrollPositions = React.useMemo(
563
- () => calcPagesScrollPositions(itemScrollPositions, pagesCount),
564
- [itemScrollPositions, pagesCount]
565
- );
566
- const scrollPositions = itemsToScroll
567
- ? calcPagesScrollPositions(itemScrollPositions, Math.ceil(items.length / itemsToScroll))
568
- : pagesScrollPositions;
569
-
570
- const nextArrowEnabled = scrollRight !== 0;
571
- const prevArrowEnabled = scrollLeft !== 0;
572
-
573
- const {isAutoplayEnabled, shouldAutoplay, setShouldAutoPlay} = useShouldAutoplay(!!autoplay, carouselRef);
574
-
575
- React.useEffect(() => {
576
- if (carouselRef.current) {
577
- const carouselEl = carouselRef.current;
578
-
579
- const handleCarouselChange = () => {
580
- const {scrollWidth, clientWidth} = carouselEl;
581
- const scrollLeft = Math.round(carouselEl.scrollLeft);
582
-
583
- const scrollRight = Math.round(scrollWidth - (scrollLeft + clientWidth));
584
-
585
- setScroll({scrollLeft, scrollRight});
586
- };
587
-
588
- const calcItemScrollPositions = () => {
589
- const maxScroll = carouselEl.scrollWidth - carouselEl.clientWidth;
590
-
591
- setItemScrollPositions(
592
- Array.from(carouselEl.querySelectorAll('[data-item]')).map((itemEl, idx) => {
593
- if (idx === items.length - 1) {
594
- return maxScroll;
595
- }
596
- const offsetLeft = (itemEl as HTMLElement).offsetLeft;
597
- const scrollMargin = parseInt(getComputedStyle(itemEl).scrollMargin);
598
- const scrollPosition =
599
- centered && !isDesktopOrBigger ? offsetLeft - itemEl.clientWidth / 2 : offsetLeft;
600
- return Math.min(scrollPosition - scrollMargin - carouselEl.offsetLeft, maxScroll);
601
- })
602
- );
603
- };
604
-
605
- handleCarouselChange();
606
- calcItemScrollPositions();
607
-
608
- carouselEl.addEventListener('scroll', handleCarouselChange);
609
- const unlistenResize = listenResize(carouselEl, () => {
610
- handleCarouselChange();
611
- calcItemScrollPositions();
612
- });
613
-
614
- return () => {
615
- carouselEl.removeEventListener('scroll', handleCarouselChange);
616
- unlistenResize();
617
- };
618
- }
619
- return () => {};
620
- }, [
621
- itemsPerPageConfig.desktop,
622
- itemsPerPageConfig.tablet,
623
- itemsPerPageConfig.mobile,
624
- pagesCount,
625
- gap,
626
- centered,
627
- isDesktopOrBigger,
628
- items.length,
629
- ]);
630
-
631
- const goToPage = React.useCallback(
632
- (pageIndex: number, animate = true) => {
633
- const carouselEl = carouselRef.current;
634
- if (carouselEl) {
635
- const scroll = pagesScrollPositions[pageIndex];
636
- carouselEl.scrollTo({left: scroll, behavior: animate ? 'smooth' : 'auto'});
637
- }
638
- },
639
- [pagesScrollPositions]
640
- );
641
-
642
- const goPrev = React.useCallback(() => {
643
- const carouselEl = carouselRef.current;
644
- if (carouselEl) {
645
- const {scrollLeft} = carouselEl;
646
- const prevPageScrollPosition = [...scrollPositions]
647
- .reverse()
648
- .find((pos) => pos - scrollLeft < -1);
649
- carouselEl.scrollTo({left: prevPageScrollPosition, behavior: 'smooth'});
650
- }
651
- }, [scrollPositions]);
652
-
653
- const goNext = React.useCallback(() => {
654
- const carouselEl = carouselRef.current;
655
- if (carouselEl) {
656
- const {scrollLeft} = carouselEl;
657
- const nextPageScrollPosition = scrollPositions.find((pos) => pos - scrollLeft > 1);
658
- carouselEl.scrollTo({left: nextPageScrollPosition, behavior: 'smooth'});
659
- }
660
- }, [scrollPositions]);
661
-
662
- React.useEffect(() => {
663
- if (initialActiveItem !== undefined) {
664
- goToPage(Math.floor(initialActiveItem / itemsPerPageFloor), false);
665
- }
666
- }, [initialActiveItem, goToPage, itemsPerPageFloor]);
667
-
668
- const hasAutoplayLoop = (typeof autoplay === 'object' && autoplay.loop) || false;
669
-
670
- const interactionDetectorRef = React.useRef<{interacting: boolean; left: number}>({
671
- interacting: false,
672
- left: 0,
673
- });
674
-
675
- React.useEffect(() => {
676
- if (shouldAutoplay && autoplay) {
677
- const time = typeof autoplay === 'boolean' ? DEFAULT_AUTOPLAY_TIME : autoplay.time;
678
- const interval = setInterval(() => {
679
- if (!interactionDetectorRef.current.interacting) {
680
- if (scrollRight !== 0) {
681
- goNext();
682
- } else if (hasAutoplayLoop) {
683
- carouselRef.current?.scrollTo({left: 0, behavior: 'smooth'});
684
- }
685
- }
686
- }, time);
687
- return () => clearInterval(interval);
688
- }
689
- }, [autoplay, goNext, scrollRight, shouldAutoplay, hasAutoplayLoop]);
690
-
691
- const currentPageIndex = calcCurrentPageIndex(scrollLeft, pagesScrollPositions);
692
-
693
- const INTERACTION_DETECTOR_THRESHOLD = 20; // pixels
694
-
695
- React.useEffect(() => {
696
- if (currentPageIndex === pagesCount - 1 && !hasAutoplayLoop) {
697
- setShouldAutoPlay(false);
698
- }
699
- }, [currentPageIndex, pagesCount, setShouldAutoPlay, hasAutoplayLoop]);
700
-
701
- const pageInitialized = React.useRef<boolean>(!initialActiveItem);
702
- const lastPageIndex = React.useRef<number>(0);
703
-
704
- React.useEffect(() => {
705
- if (onPageChange) {
706
- const lastShownItemIndex = Math.min(
707
- (currentPageIndex + 1) * itemsPerPageFloor - 1,
708
- items.length - 1
709
- );
710
- const shownItemIndexes = [];
711
- for (let i = 0; i < itemsPerPageFloor; i++) {
712
- const idx = lastShownItemIndex - i;
713
- if (idx >= 0) {
714
- shownItemIndexes.unshift(idx);
715
- }
716
- }
717
-
718
- if (!pageInitialized.current) {
719
- pageInitialized.current = shownItemIndexes.includes(initialActiveItem || 0);
720
- } else if (lastPageIndex.current !== currentPageIndex) {
721
- onPageChange({pageIndex: currentPageIndex, shownItemIndexes});
722
- }
723
-
724
- lastPageIndex.current = currentPageIndex;
725
- }
726
- }, [currentPageIndex, items.length, itemsPerPageFloor, initialActiveItem, onPageChange]);
727
-
728
- const controlsSetter = React.useContext(CarouselControlsSetterContext);
729
-
730
- const bulletsProps = React.useMemo(
731
- () => ({
732
- currentIndex: currentPageIndex,
733
- numPages: {
734
- mobile: pagesCountMobile,
735
- tablet: pagesCountTablet,
736
- desktop: pagesCountDesktop,
737
- },
738
- }),
739
- [currentPageIndex, pagesCountDesktop, pagesCountMobile, pagesCountTablet]
740
- );
741
- const autoplayControlProps = React.useMemo(
742
- () => ({
743
- isAutoplayEnabled,
744
- isAtLastPage: currentPageIndex === pagesCount - 1,
745
- onAutoplayChanged: setShouldAutoPlay,
746
- }),
747
- [isAutoplayEnabled, currentPageIndex, pagesCount, setShouldAutoPlay]
748
- );
749
- const pageControlsProps = React.useMemo(
750
- () => ({
751
- setShouldAutoplay: setShouldAutoPlay,
752
- prevArrowEnabled,
753
- nextArrowEnabled,
754
- }),
755
- [setShouldAutoPlay, prevArrowEnabled, nextArrowEnabled]
756
- );
757
-
758
- React.useEffect(() => {
759
- if (controlsSetter) {
760
- controlsSetter.setGoPrev(goPrev);
761
- controlsSetter.setGoNext(goNext);
762
- controlsSetter.setGoToPage(goToPage);
763
- controlsSetter.setBulletsProps(bulletsProps);
764
- controlsSetter.setAutoplayControlProps(autoplayControlProps);
765
- controlsSetter.setPageControlsProps(pageControlsProps);
766
- controlsSetter.setIsAutoplayEnabledSetter(setShouldAutoPlay);
767
- }
768
- }, [
769
- controlsSetter,
770
- goNext,
771
- goPrev,
772
- bulletsProps,
773
- autoplayControlProps,
774
- pageControlsProps,
775
- goToPage,
776
- prevArrowEnabled,
777
- nextArrowEnabled,
778
- autoplay,
779
- isAutoplayEnabled,
780
- setShouldAutoPlay,
781
- ]);
782
-
783
- let bullets: React.ReactNode = null;
784
-
785
- if (renderBullets) {
786
- bullets = renderBullets({numPages: pagesCount, currentIndex: currentPageIndex});
787
- } else if (withBullets) {
788
- bullets = <PageBullets {...bulletsProps} />;
789
- }
790
-
791
- const largePageOffset = '64px';
792
- const vivoNewMobilePageOffset = '36px';
793
-
794
- const bulletsContainer = (
795
- <div
796
- className={classNames(
797
- styles.carouselBullets,
798
- // when renderBullets is provided, we let the consumer decide if the bullets should be hidden
799
- !renderBullets && {
800
- [styles.noCarouselBulletsDesktop]: pagesCountDesktop <= 1,
801
- [styles.noCarouselBulletsTablet]: pagesCountTablet <= 1,
802
- [styles.noCarouselBulletsMobile]: pagesCountMobile <= 1,
803
- }
804
- )}
805
- >
806
- {bullets}
807
- </div>
808
- );
809
-
810
- return (
811
- <div
812
- {...getPrefixedDataAttributes({
813
- 'component-name': 'Carousel',
814
- testid: 'Carousel',
815
- ...dataAttributes,
816
- })}
817
- className={styles.carouselComponentContainer}
818
- role="region"
819
- aria-label={
820
- ariaLabelProp
821
- ? `${ariaLabelProp}, ${texts.carouselRegion || t(tokens.carouselRegion)}`
822
- : undefined
823
- }
824
- aria-labelledby={ariaLabelProp ? undefined : ariaLabelledByProp}
825
- >
826
- <div
827
- className={classNames(styles.carouselControlsVisibility, {
828
- [styles.carouselControlsVisibilityMobile]: pagesCountMobile > 1,
829
- [styles.carouselControlsVisibilityTablet]: pagesCountTablet > 1,
830
- [styles.carouselControlsVisibilityDesktop]: pagesCountDesktop > 1,
831
- })}
832
- >
833
- {withControls ? (
834
- <Inline space="between" alignItems="center" className={styles.carouselControlsContainer}>
835
- {!!autoplay && (
836
- <div className={styles.carouselAutoplayControlContainer}>
837
- <CarouselAutoplayControl
838
- isAutoplayEnabled={isAutoplayEnabled}
839
- isAtLastPage={currentPageIndex === pagesCount - 1}
840
- onAutoplayChanged={(autoplayEnabled: boolean) => {
841
- if (!nextArrowEnabled && autoplayEnabled) {
842
- goToPage(0);
843
- }
844
- setShouldAutoPlay(autoplayEnabled);
845
- }}
846
- />
847
- </div>
848
- )}
849
- {bulletsContainer}
850
- <div className={styles.carouselPagesControlsContainer}>
851
- <CarouselPageControls
852
- goNext={goNext}
853
- goPrev={goPrev}
854
- setShouldAutoplay={setShouldAutoPlay}
855
- prevArrowEnabled={prevArrowEnabled}
856
- nextArrowEnabled={nextArrowEnabled}
857
- pagesCount={pagesCount}
858
- currentPageIndex={currentPageIndex}
859
- />
860
- </div>
861
- </Inline>
862
- ) : (
863
- bullets && (
864
- <Inline space="around" className={styles.carouselControlsContainer}>
865
- {bulletsContainer}
866
- </Inline>
867
- )
868
- )}
869
- </div>
870
- <div className={styles.carouselContainer}>
871
- {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
872
- <div
873
- className={classNames(styles.carousel, {
874
- [styles.centeredCarousel]: centered,
875
- [styles.carouselWithScrollMobile]: pagesCountMobile > 1,
876
- [styles.carouselWithScrollTablet]: pagesCountTablet > 1,
877
- })}
878
- role="list"
879
- style={{
880
- ...applyCssVars({
881
- [styles.vars.itemsPerPageDesktop]: String(itemsPerPageConfig.desktop),
882
- [styles.vars.itemsPerPageTablet]: String(itemsPerPageConfig.tablet),
883
- [styles.vars.itemsPerPageMobile]: String(itemsPerPageConfig.mobile),
884
- ...(mobilePageOffset === 'large'
885
- ? {[styles.vars.mobilePageOffset]: largePageOffset}
886
- : skinName === VIVO_NEW_SKIN
887
- ? {[styles.vars.mobilePageOffset]: vivoNewMobilePageOffset}
888
- : {}),
889
- ...(gap !== undefined ? {[styles.vars.gap]: String(gap)} : {}),
890
- }),
891
- scrollSnapType: free ? 'initial' : 'x mandatory',
892
-
893
- // Hack to fix https://jira.tid.es/browse/NOVUMCC-8988
894
- // there is a webkit rendering bug that causes a half pixel white line to appear at
895
- // the bottom of the scrollable area in retina displays when it has a height with
896
- // decimals. This extra padding avoids that line to partially cover the carousel
897
- // slides border:
898
- paddingBottom:
899
- isIos(platformOverrides) && !isRunningAcceptanceTest(platformOverrides)
900
- ? 0.5
901
- : undefined,
902
- }}
903
- ref={carouselRef}
904
- onTouchStart={(e) => {
905
- interactionDetectorRef.current.left = e.currentTarget.scrollLeft;
906
- interactionDetectorRef.current.interacting = true;
907
- }}
908
- onTouchEnd={(e) => {
909
- interactionDetectorRef.current.interacting = false;
910
- if (
911
- Math.abs(e.currentTarget.scrollLeft - interactionDetectorRef.current.left) >
912
- INTERACTION_DETECTOR_THRESHOLD
913
- ) {
914
- setShouldAutoPlay(false);
915
- }
916
- }}
917
- onKeyDown={() => {
918
- setShouldAutoPlay(false);
919
- }}
920
- >
921
- {items.map((item, index) => (
922
- <div
923
- key={index}
924
- className={classNames(styles.carouselItem, itemClassName)}
925
- style={{
926
- ...itemStyle,
927
- scrollSnapStop: isAndroid(platformOverrides) ? 'always' : 'normal',
928
- }}
929
- role="listitem"
930
- data-item
931
- >
932
- {item}
933
- </div>
934
- ))}
935
- </div>
936
- </div>
937
- </div>
938
- );
939
- };
940
-
941
- type CarouselProps = {
942
- items: ReadonlyArray<React.ReactNode>;
943
- itemStyle?: React.CSSProperties;
944
- itemClassName?: string;
945
- withBullets?: boolean;
946
- /**
947
- * @deprecated use CarouselContextProvider and CarouselContextConsumer to provide bullets props to custom bullets component.
948
- * See an example here: https://mistica-web.vercel.app/?path=/story/components-carousels-carousel--with-carousel-context
949
- */
950
- renderBullets?: (bulletsProps: PageBulletsProps) => React.ReactNode;
951
- initialActiveItem?: number;
952
- itemsPerPage?: ItemsPerPageProp;
953
- /** scrolls one page by default */
954
- itemsToScroll?: number;
955
- mobilePageOffset?: 'regular' | 'large';
956
- /** If true, scroll snap doesn't apply and the user has a free scroll */
957
- free?: boolean;
958
- autoplay?: boolean | {time: number; loop?: boolean};
959
- withControls?: boolean;
960
- onPageChange?: (newPageInfo: {pageIndex: number; shownItemIndexes: Array<number>}) => void;
961
- dataAttributes?: DataAttributes;
962
- 'aria-label'?: string;
963
- 'aria-labelledby'?: string;
964
-
965
- children?: void;
966
- };
967
-
968
- /**
969
- * This is a workaround for a bug that happens when rendering a carousel in a webview inside a hidden tab (eg. Explore).
970
- * The webview has a width of 0 when it's hidden, and the carousel doesn't render correctly when it's first shown.
971
- * This hook forces the carousel to re-render when the webview is shown, by adding a key to the carousel component.
972
- *
973
- * This workaround gets executed only once, when the webview with changes from 0 to another value and then it removes the listener.
974
- * Related issue: https://jira.tid.es/browse/WEB-1644
975
- */
976
- const useWorkaroundForZeroWidthWebView = () => {
977
- const [key, setKey] = React.useState(1);
978
- React.useEffect(() => {
979
- const handler = () => {
980
- if (window.innerWidth !== 0) {
981
- setKey((k) => k + 1);
982
- window.removeEventListener('resize', handler);
983
- }
984
- };
985
- // Set the listener only when the webview has zero width
986
- if (window.innerWidth === 0) {
987
- window.addEventListener('resize', handler);
988
- }
989
- return () => {
990
- window.removeEventListener('resize', handler);
991
- };
992
- }, []);
993
- return key;
994
- };
995
-
996
- export const Carousel = (props: CarouselProps): JSX.Element => {
997
- const key = useWorkaroundForZeroWidthWebView();
998
- return <BaseCarousel {...props} key={key} />;
999
- };
1000
-
1001
- type CenteredCarouselProps = {
1002
- items: ReadonlyArray<React.ReactNode>;
1003
- itemStyle?: React.CSSProperties;
1004
- itemClassName?: string;
1005
- withBullets?: boolean;
1006
- withControls?: boolean;
1007
- /**
1008
- * @deprecated use CarouselContextProvider and CarouselContextConsumer to provide bullets props to custom bullets component.
1009
- * See an example here: https://mistica-web.vercel.app/?path=/story/components-carousels-carousel--with-carousel-context
1010
- */
1011
- renderBullets?: (bulletsProps: PageBulletsProps) => React.ReactNode;
1012
- initialActiveItem?: number;
1013
- onPageChange?: (newPageInfo: {pageIndex: number; shownItemIndexes: Array<number>}) => void;
1014
- dataAttributes?: DataAttributes;
1015
- 'aria-label'?: string;
1016
- 'aria-labelledby'?: string;
1017
-
1018
- children?: void;
1019
- };
1020
-
1021
- export const CenteredCarousel = ({
1022
- items,
1023
- itemStyle,
1024
- itemClassName,
1025
- withBullets,
1026
- renderBullets,
1027
- withControls = true,
1028
- initialActiveItem,
1029
- onPageChange,
1030
- dataAttributes,
1031
- 'aria-label': ariaLabelProp,
1032
- 'aria-labelledby': ariaLabelledByProp,
1033
- }: CenteredCarouselProps): JSX.Element => {
1034
- const key = useWorkaroundForZeroWidthWebView();
1035
- return (
1036
- <BaseCarousel
1037
- key={key}
1038
- items={items}
1039
- itemStyle={itemStyle}
1040
- itemClassName={itemClassName}
1041
- itemsPerPage={{mobile: 1, tablet: 1, desktop: 3}}
1042
- centered
1043
- itemsToScroll={1}
1044
- gap={0}
1045
- withBullets={withBullets}
1046
- renderBullets={renderBullets}
1047
- withControls={withControls}
1048
- initialActiveItem={initialActiveItem}
1049
- onPageChange={onPageChange}
1050
- dataAttributes={dataAttributes}
1051
- aria-label={ariaLabelProp}
1052
- aria-labelledby={ariaLabelledByProp}
1053
- />
1054
- );
1055
- };
1056
-
1057
- type SlideshowProps = {
1058
- items: ReadonlyArray<React.ReactNode>;
1059
- withBullets?: boolean;
1060
- autoplay?: boolean | {time: number; loop?: boolean};
1061
- initialPageIndex?: number;
1062
- withControls?: boolean;
1063
- onPageChange?: (newPageIndex: number) => void;
1064
- dataAttributes?: DataAttributes;
1065
- inverseBullets?: boolean;
1066
-
1067
- children?: void;
1068
- };
1069
-
1070
- /**
1071
- * This context is used internally to let other components (Hero) now if they are rendered inside a Slideshow
1072
- * to make some tweaks in the UI
1073
- */
1074
- const SlideshowContext = React.createContext<{withBullets: boolean} | undefined>(undefined);
1075
-
1076
- export const useSlideshowContext = (): {withBullets: boolean} | undefined =>
1077
- React.useContext(SlideshowContext);
1078
-
1079
- export const Slideshow = ({
1080
- items,
1081
- withBullets,
1082
- withControls = true,
1083
- autoplay,
1084
- initialPageIndex = 0,
1085
- onPageChange,
1086
- dataAttributes,
1087
- inverseBullets = true,
1088
- }: SlideshowProps): JSX.Element => {
1089
- const {platformOverrides} = useTheme();
1090
- const controlsSetter = React.useContext(CarouselControlsSetterContext);
1091
-
1092
- const carouselRef = React.useRef<HTMLDivElement>(null);
1093
-
1094
- // ScrollRight is initialized to 1 to avoid the next arrow being disabled when the carousel is first rendered.
1095
- // This is required to make the SSR test pass, and taking advantage of the fact that this is the base case (having more than one page)
1096
- const [{scrollLeft, scrollRight}, setScroll] = React.useState({scrollLeft: 0, scrollRight: 1});
1097
- const nextArrowEnabled = scrollRight !== 0;
1098
- const prevArrowEnabled = scrollLeft !== 0;
1099
-
1100
- const goPrev = React.useCallback(() => {
1101
- const carouselEl = carouselRef.current;
1102
- if (carouselEl) {
1103
- carouselEl.scrollBy({left: -carouselEl.clientWidth, behavior: 'smooth'});
1104
- }
1105
- }, []);
1106
-
1107
- const goNext = React.useCallback(() => {
1108
- const carouselEl = carouselRef.current;
1109
- if (carouselEl) {
1110
- carouselEl.scrollBy({left: carouselEl.clientWidth, behavior: 'smooth'});
1111
- }
1112
- }, []);
1113
-
1114
- const goToPage = React.useCallback(
1115
- (pageIndex: number, animate = true) => {
1116
- const carouselEl = carouselRef.current;
1117
- if (carouselEl) {
1118
- carouselEl.scrollTo({
1119
- left: carouselEl.clientWidth * pageIndex,
1120
- behavior: animate ? 'smooth' : 'auto',
1121
- });
1122
- }
1123
- },
1124
- [carouselRef]
1125
- );
1126
-
1127
- const currentIndex = carouselRef.current
1128
- ? Math.floor((scrollLeft + carouselRef.current.clientWidth / 2) / carouselRef.current.clientWidth)
1129
- : 0;
1130
-
1131
- useIsomorphicLayoutEffect(() => {
1132
- const carouselEl = carouselRef.current;
1133
- if (carouselEl) {
1134
- const handleCarouselChange = () => {
1135
- const {scrollWidth, clientWidth} = carouselEl;
1136
- const scrollLeft = Math.round(carouselEl.scrollLeft);
1137
- const scrollRight = Math.round(scrollWidth - (scrollLeft + clientWidth));
1138
- setScroll({scrollLeft, scrollRight});
1139
- };
1140
-
1141
- handleCarouselChange();
1142
-
1143
- carouselEl.addEventListener('scroll', handleCarouselChange);
1144
- const unlistenResize = listenResize(carouselEl, handleCarouselChange);
1145
-
1146
- return () => {
1147
- carouselEl.removeEventListener('scroll', handleCarouselChange);
1148
- unlistenResize();
1149
- };
1150
- }
1151
- }, [items.length]);
1152
-
1153
- const {isAutoplayEnabled, shouldAutoplay, setShouldAutoPlay} = useShouldAutoplay(!!autoplay, carouselRef);
1154
-
1155
- const hasAutoplayLoop = (typeof autoplay === 'object' && autoplay.loop) || false;
1156
-
1157
- React.useEffect(() => {
1158
- if (shouldAutoplay && autoplay) {
1159
- const time = typeof autoplay === 'boolean' ? DEFAULT_AUTOPLAY_TIME : autoplay.time;
1160
- const interval = setInterval(() => {
1161
- if (scrollRight !== 0) {
1162
- goNext();
1163
- } else if (hasAutoplayLoop) {
1164
- carouselRef.current?.scrollTo({left: 0, behavior: 'smooth'});
1165
- }
1166
- }, time);
1167
- return () => clearInterval(interval);
1168
- }
1169
- }, [autoplay, goNext, scrollRight, shouldAutoplay, hasAutoplayLoop]);
1170
-
1171
- React.useEffect(() => {
1172
- if (currentIndex === items.length - 1 && !hasAutoplayLoop) {
1173
- setShouldAutoPlay(false);
1174
- }
1175
- }, [currentIndex, items.length, setShouldAutoPlay, hasAutoplayLoop]);
1176
-
1177
- const pageInitialized = React.useRef(false);
1178
- const lastPageIndex = React.useRef(0);
1179
-
1180
- React.useEffect(() => {
1181
- if (onPageChange) {
1182
- if (!pageInitialized.current) {
1183
- pageInitialized.current = initialPageIndex === currentIndex;
1184
- } else if (lastPageIndex.current !== currentIndex) {
1185
- onPageChange(currentIndex);
1186
- }
1187
- }
1188
-
1189
- lastPageIndex.current = currentIndex;
1190
- }, [currentIndex, initialPageIndex, onPageChange]);
1191
-
1192
- React.useEffect(() => {
1193
- const carouselEl = carouselRef.current;
1194
- if (initialPageIndex !== undefined && carouselEl && !pageInitialized.current) {
1195
- carouselEl.scrollTo({left: carouselEl.clientWidth * initialPageIndex});
1196
- }
1197
- }, [initialPageIndex]);
1198
-
1199
- const bulletsProps = React.useMemo<PageBulletsProps>(
1200
- () => ({
1201
- currentIndex,
1202
- numPages: items.length,
1203
- }),
1204
- [currentIndex, items.length]
1205
- );
1206
-
1207
- React.useEffect(() => {
1208
- if (controlsSetter) {
1209
- controlsSetter.setGoPrev(goPrev);
1210
- controlsSetter.setGoNext(goNext);
1211
- controlsSetter.setGoToPage(goToPage);
1212
- controlsSetter.setBulletsProps(bulletsProps);
1213
- }
1214
- }, [controlsSetter, goNext, goPrev, bulletsProps, goToPage]);
1215
-
1216
- const bulletsContainer = withBullets && (
1217
- <div className={styles.slideshowBulletsContainer}>
1218
- <ThemeVariant variant={inverseBullets ? 'inverse' : 'default'}>
1219
- <PageBullets {...bulletsProps} />
1220
- </ThemeVariant>
1221
- </div>
1222
- );
1223
-
1224
- const onlyControls = !withBullets && !autoplay;
1225
-
1226
- return (
1227
- <SlideshowContext.Provider value={{withBullets: !!withBullets}}>
1228
- <ResetResponsiveLayout skipDesktop>
1229
- <div
1230
- className={classNames(styles.slideshowContainer, {
1231
- [styles.slideshowWithBullets]: !!withBullets,
1232
- })}
1233
- {...getPrefixedDataAttributes(dataAttributes, 'SlideShow')}
1234
- >
1235
- {items.length > 1 &&
1236
- (withControls ? (
1237
- <ThemeVariant variant="media">
1238
- <Inline
1239
- space={onlyControls ? 0 : 'between'}
1240
- alignItems="center"
1241
- className={classNames(styles.slideshowControlsContainer, {
1242
- [styles.slideshowControlsContainerSingleItem]: onlyControls,
1243
- })}
1244
- >
1245
- {!!autoplay && (
1246
- <div className={styles.slideshowAutoplayControlContainer}>
1247
- <CarouselAutoplayControl
1248
- isAutoplayEnabled={isAutoplayEnabled}
1249
- isAtLastPage={currentIndex === items.length - 1}
1250
- onAutoplayChanged={(autoplayEnabled: boolean) => {
1251
- if (
1252
- currentIndex === items.length - 1 &&
1253
- autoplayEnabled
1254
- ) {
1255
- goToPage(0);
1256
- }
1257
- setShouldAutoPlay(autoplayEnabled);
1258
- }}
1259
- />
1260
- </div>
1261
- )}
1262
- {bulletsContainer}
1263
- <CarouselPageControls
1264
- goNext={goNext}
1265
- goPrev={goPrev}
1266
- setShouldAutoplay={setShouldAutoPlay}
1267
- prevArrowEnabled={prevArrowEnabled}
1268
- nextArrowEnabled={nextArrowEnabled}
1269
- pagesCount={items.length}
1270
- currentPageIndex={currentIndex}
1271
- />
1272
- </Inline>
1273
- </ThemeVariant>
1274
- ) : (
1275
- withBullets && (
1276
- <Inline space="around" className={styles.slideshowControlsContainer}>
1277
- {bulletsContainer}
1278
- </Inline>
1279
- )
1280
- ))}
1281
- <div style={applyCssVars({[mediaStyles.vars.mediaBorderRadius]: '0px'})}>
1282
- <div className={styles.slideshow} ref={carouselRef}>
1283
- {items.map((item, index) => (
1284
- <div
1285
- key={index}
1286
- className={styles.slideshowItem}
1287
- style={{
1288
- scrollSnapStop: isAndroid(platformOverrides) ? 'always' : 'normal',
1289
- }}
1290
- >
1291
- {item}
1292
- </div>
1293
- ))}
1294
- </div>
1295
- </div>
1296
- </div>
1297
- </ResetResponsiveLayout>
1298
- </SlideshowContext.Provider>
1299
- );
1300
- };