@okta/odyssey-react-mui 1.24.1 → 1.26.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 (504) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/Autocomplete.js +30 -191
  3. package/dist/Autocomplete.js.map +1 -1
  4. package/dist/Box.js +2 -0
  5. package/dist/Box.js.map +1 -1
  6. package/dist/Card.js +1 -0
  7. package/dist/Card.js.map +1 -1
  8. package/dist/OdysseyDesignTokensContext.js +3 -2
  9. package/dist/OdysseyDesignTokensContext.js.map +1 -1
  10. package/dist/OdysseyProvider.js +22 -40
  11. package/dist/OdysseyProvider.js.map +1 -1
  12. package/dist/OdysseyThemeProvider.js +33 -12
  13. package/dist/OdysseyThemeProvider.js.map +1 -1
  14. package/dist/OdysseyTranslationProvider.types.js +1 -1
  15. package/dist/OdysseyTranslationProvider.types.js.map +1 -1
  16. package/dist/Pagination/Pagination.js +46 -14
  17. package/dist/Pagination/Pagination.js.map +1 -1
  18. package/dist/Select.js +10 -2
  19. package/dist/Select.js.map +1 -1
  20. package/dist/Surface.js +4 -1
  21. package/dist/Surface.js.map +1 -1
  22. package/dist/Tag.js +97 -47
  23. package/dist/Tag.js.map +1 -1
  24. package/dist/i18n.js +2 -0
  25. package/dist/i18n.js.map +1 -1
  26. package/dist/index.js +6 -7
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.scss +1 -1
  29. package/dist/labs/AppTile.js +137 -39
  30. package/dist/labs/AppTile.js.map +1 -1
  31. package/dist/labs/DataView/CardLayoutContent.js +7 -8
  32. package/dist/labs/DataView/CardLayoutContent.js.map +1 -1
  33. package/dist/labs/DataView/DataCard.js +96 -43
  34. package/dist/labs/DataView/DataCard.js.map +1 -1
  35. package/dist/labs/DataView/TableLayoutContent.js +3 -2
  36. package/dist/labs/DataView/TableLayoutContent.js.map +1 -1
  37. package/dist/labs/DataView/componentTypes.js.map +1 -1
  38. package/dist/labs/DataView/index.js.map +1 -1
  39. package/dist/labs/OdysseyPickers/ComposablePicker.js +113 -0
  40. package/dist/labs/OdysseyPickers/ComposablePicker.js.map +1 -0
  41. package/dist/labs/OdysseyPickers/Picker.js +261 -0
  42. package/dist/labs/OdysseyPickers/Picker.js.map +1 -0
  43. package/dist/labs/OdysseyPickers/PickerVirtualizationListBox.js +132 -0
  44. package/dist/labs/OdysseyPickers/PickerVirtualizationListBox.js.map +1 -0
  45. package/dist/labs/OdysseyPickers/PickerWithOptionAdornment.js +291 -0
  46. package/dist/labs/OdysseyPickers/PickerWithOptionAdornment.js.map +1 -0
  47. package/dist/{src/createShadowDomElements.d.ts → labs/OdysseyPickers/index.js} +4 -7
  48. package/dist/labs/OdysseyPickers/index.js.map +1 -0
  49. package/dist/labs/PageTemplate.js +14 -10
  50. package/dist/labs/PageTemplate.js.map +1 -1
  51. package/dist/labs/SideNav/CollapseIcon.js +11 -25
  52. package/dist/labs/SideNav/CollapseIcon.js.map +1 -1
  53. package/dist/labs/SideNav/HandleIcon.js +32 -0
  54. package/dist/labs/SideNav/HandleIcon.js.map +1 -0
  55. package/dist/labs/{NavAccordion.js → SideNav/NavAccordion.js} +35 -6
  56. package/dist/labs/SideNav/NavAccordion.js.map +1 -0
  57. package/dist/labs/SideNav/OktaAura.js +32 -0
  58. package/dist/labs/SideNav/OktaAura.js.map +1 -0
  59. package/dist/labs/SideNav/OktaLogo.js +6 -9
  60. package/dist/labs/SideNav/OktaLogo.js.map +1 -1
  61. package/dist/labs/SideNav/SideNav.js +239 -169
  62. package/dist/labs/SideNav/SideNav.js.map +1 -1
  63. package/dist/labs/SideNav/SideNavFooterContent.js +32 -18
  64. package/dist/labs/SideNav/SideNavFooterContent.js.map +1 -1
  65. package/dist/labs/SideNav/SideNavHeader.js +48 -37
  66. package/dist/labs/SideNav/SideNavHeader.js.map +1 -1
  67. package/dist/labs/SideNav/SideNavItemContent.js +100 -58
  68. package/dist/labs/SideNav/SideNavItemContent.js.map +1 -1
  69. package/dist/labs/SideNav/SideNavItemContentContext.js +19 -0
  70. package/dist/labs/SideNav/SideNavItemContentContext.js.map +1 -0
  71. package/dist/labs/SideNav/SideNavItemLinkContent.js +14 -13
  72. package/dist/labs/SideNav/SideNavItemLinkContent.js.map +1 -1
  73. package/dist/labs/SideNav/SideNavLogo.js +42 -0
  74. package/dist/labs/SideNav/SideNavLogo.js.map +1 -0
  75. package/dist/labs/SideNav/SideNavToggleButton.js +170 -0
  76. package/dist/labs/SideNav/SideNavToggleButton.js.map +1 -0
  77. package/dist/labs/SideNav/types.js.map +1 -1
  78. package/dist/labs/TopNav/TopNav.js +65 -0
  79. package/dist/labs/TopNav/TopNav.js.map +1 -0
  80. package/dist/labs/TopNav/TopNavLinksList.js +38 -0
  81. package/dist/labs/TopNav/TopNavLinksList.js.map +1 -0
  82. package/dist/labs/TopNav/TopNavListItem.js +132 -0
  83. package/dist/labs/TopNav/TopNavListItem.js.map +1 -0
  84. package/dist/labs/TopNav/UserProfile.js +65 -0
  85. package/dist/labs/TopNav/UserProfile.js.map +1 -0
  86. package/dist/labs/TopNav/index.js +14 -0
  87. package/dist/labs/TopNav/index.js.map +1 -0
  88. package/dist/labs/UiShell/UiShell.js +68 -0
  89. package/dist/labs/UiShell/UiShell.js.map +1 -0
  90. package/dist/labs/UiShell/UiShellContent.js +114 -0
  91. package/dist/labs/UiShell/UiShellContent.js.map +1 -0
  92. package/dist/labs/UiShell/bufferLatest.js +37 -0
  93. package/dist/labs/UiShell/bufferLatest.js.map +1 -0
  94. package/dist/labs/UiShell/createMessageBus.js +30 -0
  95. package/dist/labs/UiShell/createMessageBus.js.map +1 -0
  96. package/dist/labs/UiShell/createStore.js +24 -0
  97. package/dist/labs/UiShell/createStore.js.map +1 -0
  98. package/dist/labs/UiShell/index.js +15 -0
  99. package/dist/labs/UiShell/index.js.map +1 -0
  100. package/dist/labs/UiShell/renderUiShell.js +78 -0
  101. package/dist/labs/UiShell/renderUiShell.js.map +1 -0
  102. package/dist/labs/UiShell/useHasUiShell.js +22 -0
  103. package/dist/labs/UiShell/useHasUiShell.js.map +1 -0
  104. package/dist/labs/UiShell/useScrollState.js +41 -0
  105. package/dist/labs/UiShell/useScrollState.js.map +1 -0
  106. package/dist/labs/index.js +5 -3
  107. package/dist/labs/index.js.map +1 -1
  108. package/dist/properties/ts/odyssey-react-mui.js +7 -1
  109. package/dist/properties/ts/odyssey-react-mui.js.map +1 -1
  110. package/dist/properties/ts/odyssey-react-mui_cs.js +3 -1
  111. package/dist/properties/ts/odyssey-react-mui_cs.js.map +1 -1
  112. package/dist/properties/ts/odyssey-react-mui_da.js +3 -1
  113. package/dist/properties/ts/odyssey-react-mui_da.js.map +1 -1
  114. package/dist/properties/ts/odyssey-react-mui_de.js +3 -1
  115. package/dist/properties/ts/odyssey-react-mui_de.js.map +1 -1
  116. package/dist/properties/ts/odyssey-react-mui_el.js +3 -1
  117. package/dist/properties/ts/odyssey-react-mui_el.js.map +1 -1
  118. package/dist/properties/ts/odyssey-react-mui_es.js +3 -1
  119. package/dist/properties/ts/odyssey-react-mui_es.js.map +1 -1
  120. package/dist/properties/ts/odyssey-react-mui_fi.js +3 -1
  121. package/dist/properties/ts/odyssey-react-mui_fi.js.map +1 -1
  122. package/dist/properties/ts/odyssey-react-mui_fr.js +5 -3
  123. package/dist/properties/ts/odyssey-react-mui_fr.js.map +1 -1
  124. package/dist/properties/ts/odyssey-react-mui_ht.js +3 -1
  125. package/dist/properties/ts/odyssey-react-mui_ht.js.map +1 -1
  126. package/dist/properties/ts/odyssey-react-mui_hu.js +3 -1
  127. package/dist/properties/ts/odyssey-react-mui_hu.js.map +1 -1
  128. package/dist/properties/ts/odyssey-react-mui_id.js +3 -1
  129. package/dist/properties/ts/odyssey-react-mui_id.js.map +1 -1
  130. package/dist/properties/ts/odyssey-react-mui_it.js +4 -2
  131. package/dist/properties/ts/odyssey-react-mui_it.js.map +1 -1
  132. package/dist/properties/ts/odyssey-react-mui_ja.js +9 -7
  133. package/dist/properties/ts/odyssey-react-mui_ja.js.map +1 -1
  134. package/dist/properties/ts/odyssey-react-mui_ko.js +3 -1
  135. package/dist/properties/ts/odyssey-react-mui_ko.js.map +1 -1
  136. package/dist/properties/ts/odyssey-react-mui_ms.js +3 -1
  137. package/dist/properties/ts/odyssey-react-mui_ms.js.map +1 -1
  138. package/dist/properties/ts/odyssey-react-mui_nb.js +3 -1
  139. package/dist/properties/ts/odyssey-react-mui_nb.js.map +1 -1
  140. package/dist/properties/ts/odyssey-react-mui_nl_NL.js +3 -1
  141. package/dist/properties/ts/odyssey-react-mui_nl_NL.js.map +1 -1
  142. package/dist/properties/ts/odyssey-react-mui_pl.js +3 -1
  143. package/dist/properties/ts/odyssey-react-mui_pl.js.map +1 -1
  144. package/dist/properties/ts/odyssey-react-mui_pt_BR.js +3 -1
  145. package/dist/properties/ts/odyssey-react-mui_pt_BR.js.map +1 -1
  146. package/dist/properties/ts/odyssey-react-mui_ro.js +3 -1
  147. package/dist/properties/ts/odyssey-react-mui_ro.js.map +1 -1
  148. package/dist/properties/ts/odyssey-react-mui_ru.js +3 -1
  149. package/dist/properties/ts/odyssey-react-mui_ru.js.map +1 -1
  150. package/dist/properties/ts/odyssey-react-mui_sv.js +3 -1
  151. package/dist/properties/ts/odyssey-react-mui_sv.js.map +1 -1
  152. package/dist/properties/ts/odyssey-react-mui_th.js +3 -1
  153. package/dist/properties/ts/odyssey-react-mui_th.js.map +1 -1
  154. package/dist/properties/ts/odyssey-react-mui_tr.js +4 -2
  155. package/dist/properties/ts/odyssey-react-mui_tr.js.map +1 -1
  156. package/dist/properties/ts/odyssey-react-mui_uk.js +3 -1
  157. package/dist/properties/ts/odyssey-react-mui_uk.js.map +1 -1
  158. package/dist/properties/ts/odyssey-react-mui_vi.js +3 -1
  159. package/dist/properties/ts/odyssey-react-mui_vi.js.map +1 -1
  160. package/dist/properties/ts/odyssey-react-mui_zh_CN.js +3 -1
  161. package/dist/properties/ts/odyssey-react-mui_zh_CN.js.map +1 -1
  162. package/dist/properties/ts/odyssey-react-mui_zh_TW.js +3 -1
  163. package/dist/properties/ts/odyssey-react-mui_zh_TW.js.map +1 -1
  164. package/dist/src/Autocomplete.d.ts +21 -22
  165. package/dist/src/Autocomplete.d.ts.map +1 -1
  166. package/dist/src/Box.d.ts +3 -1
  167. package/dist/src/Box.d.ts.map +1 -1
  168. package/dist/src/Card.d.ts.map +1 -1
  169. package/dist/src/OdysseyDesignTokensContext.d.ts +5 -4
  170. package/dist/src/OdysseyDesignTokensContext.d.ts.map +1 -1
  171. package/dist/src/OdysseyProvider.d.ts +1 -3
  172. package/dist/src/OdysseyProvider.d.ts.map +1 -1
  173. package/dist/src/OdysseyThemeProvider.d.ts +10 -4
  174. package/dist/src/OdysseyThemeProvider.d.ts.map +1 -1
  175. package/dist/src/OdysseyTranslationProvider.d.ts +1 -1
  176. package/dist/src/OdysseyTranslationProvider.d.ts.map +1 -1
  177. package/dist/src/OdysseyTranslationProvider.types.d.ts +1 -1
  178. package/dist/src/OdysseyTranslationProvider.types.d.ts.map +1 -1
  179. package/dist/src/Pagination/Pagination.d.ts +21 -7
  180. package/dist/src/Pagination/Pagination.d.ts.map +1 -1
  181. package/dist/src/Select.d.ts.map +1 -1
  182. package/dist/src/Surface.d.ts.map +1 -1
  183. package/dist/src/Tag.d.ts +5 -2
  184. package/dist/src/Tag.d.ts.map +1 -1
  185. package/dist/src/i18n.d.ts.map +1 -1
  186. package/dist/src/index.d.ts +6 -7
  187. package/dist/src/index.d.ts.map +1 -1
  188. package/dist/src/labs/AppTile.d.ts +3 -1
  189. package/dist/src/labs/AppTile.d.ts.map +1 -1
  190. package/dist/src/labs/DataView/CardLayoutContent.d.ts.map +1 -1
  191. package/dist/src/labs/DataView/DataCard.d.ts +9 -3
  192. package/dist/src/labs/DataView/DataCard.d.ts.map +1 -1
  193. package/dist/src/labs/DataView/TableLayoutContent.d.ts.map +1 -1
  194. package/dist/src/labs/DataView/componentTypes.d.ts +1 -1
  195. package/dist/src/labs/DataView/componentTypes.d.ts.map +1 -1
  196. package/dist/src/labs/DataView/index.d.ts +1 -0
  197. package/dist/src/labs/DataView/index.d.ts.map +1 -1
  198. package/dist/src/labs/OdysseyPickers/ComposablePicker.d.ts +33 -0
  199. package/dist/src/labs/OdysseyPickers/ComposablePicker.d.ts.map +1 -0
  200. package/dist/src/labs/OdysseyPickers/Picker.d.ts +98 -0
  201. package/dist/src/labs/OdysseyPickers/Picker.d.ts.map +1 -0
  202. package/dist/src/labs/OdysseyPickers/PickerVirtualizationListBox.d.ts +17 -0
  203. package/dist/src/labs/OdysseyPickers/PickerVirtualizationListBox.d.ts.map +1 -0
  204. package/dist/src/labs/OdysseyPickers/PickerWithOptionAdornment.d.ts +26 -0
  205. package/dist/src/labs/OdysseyPickers/PickerWithOptionAdornment.d.ts.map +1 -0
  206. package/dist/src/labs/OdysseyPickers/index.d.ts +15 -0
  207. package/dist/src/labs/OdysseyPickers/index.d.ts.map +1 -0
  208. package/dist/src/labs/PageTemplate.d.ts +1 -1
  209. package/dist/src/labs/PageTemplate.d.ts.map +1 -1
  210. package/dist/src/labs/SideNav/CollapseIcon.d.ts +1 -4
  211. package/dist/src/labs/SideNav/CollapseIcon.d.ts.map +1 -1
  212. package/dist/src/labs/SideNav/HandleIcon.d.ts +14 -0
  213. package/dist/src/labs/SideNav/HandleIcon.d.ts.map +1 -0
  214. package/dist/src/labs/{NavAccordion.d.ts → SideNav/NavAccordion.d.ts} +6 -2
  215. package/dist/src/labs/SideNav/NavAccordion.d.ts.map +1 -0
  216. package/dist/src/labs/SideNav/OktaAura.d.ts +14 -0
  217. package/dist/src/labs/SideNav/OktaAura.d.ts.map +1 -0
  218. package/dist/src/labs/SideNav/OktaLogo.d.ts.map +1 -1
  219. package/dist/src/labs/SideNav/SideNav.d.ts +2 -1
  220. package/dist/src/labs/SideNav/SideNav.d.ts.map +1 -1
  221. package/dist/src/labs/SideNav/SideNavFooterContent.d.ts +1 -1
  222. package/dist/src/labs/SideNav/SideNavFooterContent.d.ts.map +1 -1
  223. package/dist/src/labs/SideNav/SideNavHeader.d.ts +12 -3
  224. package/dist/src/labs/SideNav/SideNavHeader.d.ts.map +1 -1
  225. package/dist/src/labs/SideNav/SideNavItemContent.d.ts +2 -3
  226. package/dist/src/labs/SideNav/SideNavItemContent.d.ts.map +1 -1
  227. package/dist/src/labs/SideNav/SideNavItemContentContext.d.ts +18 -0
  228. package/dist/src/labs/SideNav/SideNavItemContentContext.d.ts.map +1 -0
  229. package/dist/src/labs/SideNav/SideNavItemLinkContent.d.ts +1 -1
  230. package/dist/src/labs/SideNav/SideNavItemLinkContent.d.ts.map +1 -1
  231. package/dist/src/labs/SideNav/SideNavLogo.d.ts +15 -0
  232. package/dist/src/labs/SideNav/SideNavLogo.d.ts.map +1 -0
  233. package/dist/src/labs/SideNav/SideNavToggleButton.d.ts +38 -0
  234. package/dist/src/labs/SideNav/SideNavToggleButton.d.ts.map +1 -0
  235. package/dist/src/labs/SideNav/types.d.ts +67 -33
  236. package/dist/src/labs/SideNav/types.d.ts.map +1 -1
  237. package/dist/src/labs/TopNav/TopNav.d.ts +31 -0
  238. package/dist/src/labs/TopNav/TopNav.d.ts.map +1 -0
  239. package/dist/src/labs/TopNav/TopNavLinksList.d.ts +44 -0
  240. package/dist/src/labs/TopNav/TopNavLinksList.d.ts.map +1 -0
  241. package/dist/src/labs/TopNav/TopNavListItem.d.ts +42 -0
  242. package/dist/src/labs/TopNav/TopNavListItem.d.ts.map +1 -0
  243. package/dist/src/labs/TopNav/UserProfile.d.ts +29 -0
  244. package/dist/src/labs/TopNav/UserProfile.d.ts.map +1 -0
  245. package/dist/src/labs/TopNav/index.d.ts +14 -0
  246. package/dist/src/labs/TopNav/index.d.ts.map +1 -0
  247. package/dist/src/labs/UiShell/UiShell.d.ts +33 -0
  248. package/dist/src/labs/UiShell/UiShell.d.ts.map +1 -0
  249. package/dist/src/labs/UiShell/UiShellContent.d.ts +47 -0
  250. package/dist/src/labs/UiShell/UiShellContent.d.ts.map +1 -0
  251. package/dist/src/labs/UiShell/bufferLatest.d.ts +31 -0
  252. package/dist/src/labs/UiShell/bufferLatest.d.ts.map +1 -0
  253. package/dist/src/labs/UiShell/createMessageBus.d.ts +24 -0
  254. package/dist/src/labs/UiShell/createMessageBus.d.ts.map +1 -0
  255. package/dist/src/labs/UiShell/createStore.d.ts +22 -0
  256. package/dist/src/labs/UiShell/createStore.d.ts.map +1 -0
  257. package/dist/src/labs/UiShell/index.d.ts +16 -0
  258. package/dist/src/labs/UiShell/index.d.ts.map +1 -0
  259. package/dist/src/labs/UiShell/renderUiShell.d.ts +45 -0
  260. package/dist/src/labs/UiShell/renderUiShell.d.ts.map +1 -0
  261. package/dist/src/labs/UiShell/useHasUiShell.d.ts +13 -0
  262. package/dist/src/labs/UiShell/useHasUiShell.d.ts.map +1 -0
  263. package/dist/src/labs/UiShell/useScrollState.d.ts +16 -0
  264. package/dist/src/labs/UiShell/useScrollState.d.ts.map +1 -0
  265. package/dist/src/labs/index.d.ts +6 -2
  266. package/dist/src/labs/index.d.ts.map +1 -1
  267. package/dist/src/properties/ts/odyssey-react-mui.d.ts +6 -0
  268. package/dist/src/properties/ts/odyssey-react-mui.d.ts.map +1 -1
  269. package/dist/src/properties/ts/odyssey-react-mui_cs.d.ts +2 -0
  270. package/dist/src/properties/ts/odyssey-react-mui_cs.d.ts.map +1 -1
  271. package/dist/src/properties/ts/odyssey-react-mui_da.d.ts +2 -0
  272. package/dist/src/properties/ts/odyssey-react-mui_da.d.ts.map +1 -1
  273. package/dist/src/properties/ts/odyssey-react-mui_de.d.ts +2 -0
  274. package/dist/src/properties/ts/odyssey-react-mui_de.d.ts.map +1 -1
  275. package/dist/src/properties/ts/odyssey-react-mui_el.d.ts +2 -0
  276. package/dist/src/properties/ts/odyssey-react-mui_el.d.ts.map +1 -1
  277. package/dist/src/properties/ts/odyssey-react-mui_es.d.ts +2 -0
  278. package/dist/src/properties/ts/odyssey-react-mui_es.d.ts.map +1 -1
  279. package/dist/src/properties/ts/odyssey-react-mui_fi.d.ts +2 -0
  280. package/dist/src/properties/ts/odyssey-react-mui_fi.d.ts.map +1 -1
  281. package/dist/src/properties/ts/odyssey-react-mui_fr.d.ts +2 -0
  282. package/dist/src/properties/ts/odyssey-react-mui_fr.d.ts.map +1 -1
  283. package/dist/src/properties/ts/odyssey-react-mui_ht.d.ts +2 -0
  284. package/dist/src/properties/ts/odyssey-react-mui_ht.d.ts.map +1 -1
  285. package/dist/src/properties/ts/odyssey-react-mui_hu.d.ts +2 -0
  286. package/dist/src/properties/ts/odyssey-react-mui_hu.d.ts.map +1 -1
  287. package/dist/src/properties/ts/odyssey-react-mui_id.d.ts +2 -0
  288. package/dist/src/properties/ts/odyssey-react-mui_id.d.ts.map +1 -1
  289. package/dist/src/properties/ts/odyssey-react-mui_it.d.ts +2 -0
  290. package/dist/src/properties/ts/odyssey-react-mui_it.d.ts.map +1 -1
  291. package/dist/src/properties/ts/odyssey-react-mui_ja.d.ts +2 -0
  292. package/dist/src/properties/ts/odyssey-react-mui_ja.d.ts.map +1 -1
  293. package/dist/src/properties/ts/odyssey-react-mui_ko.d.ts +2 -0
  294. package/dist/src/properties/ts/odyssey-react-mui_ko.d.ts.map +1 -1
  295. package/dist/src/properties/ts/odyssey-react-mui_ms.d.ts +2 -0
  296. package/dist/src/properties/ts/odyssey-react-mui_ms.d.ts.map +1 -1
  297. package/dist/src/properties/ts/odyssey-react-mui_nb.d.ts +2 -0
  298. package/dist/src/properties/ts/odyssey-react-mui_nb.d.ts.map +1 -1
  299. package/dist/src/properties/ts/odyssey-react-mui_nl_NL.d.ts +2 -0
  300. package/dist/src/properties/ts/odyssey-react-mui_nl_NL.d.ts.map +1 -1
  301. package/dist/src/properties/ts/odyssey-react-mui_pl.d.ts +2 -0
  302. package/dist/src/properties/ts/odyssey-react-mui_pl.d.ts.map +1 -1
  303. package/dist/src/properties/ts/odyssey-react-mui_pt_BR.d.ts +2 -0
  304. package/dist/src/properties/ts/odyssey-react-mui_pt_BR.d.ts.map +1 -1
  305. package/dist/src/properties/ts/odyssey-react-mui_ro.d.ts +2 -0
  306. package/dist/src/properties/ts/odyssey-react-mui_ro.d.ts.map +1 -1
  307. package/dist/src/properties/ts/odyssey-react-mui_ru.d.ts +2 -0
  308. package/dist/src/properties/ts/odyssey-react-mui_ru.d.ts.map +1 -1
  309. package/dist/src/properties/ts/odyssey-react-mui_sv.d.ts +2 -0
  310. package/dist/src/properties/ts/odyssey-react-mui_sv.d.ts.map +1 -1
  311. package/dist/src/properties/ts/odyssey-react-mui_th.d.ts +2 -0
  312. package/dist/src/properties/ts/odyssey-react-mui_th.d.ts.map +1 -1
  313. package/dist/src/properties/ts/odyssey-react-mui_tr.d.ts +2 -0
  314. package/dist/src/properties/ts/odyssey-react-mui_tr.d.ts.map +1 -1
  315. package/dist/src/properties/ts/odyssey-react-mui_uk.d.ts +2 -0
  316. package/dist/src/properties/ts/odyssey-react-mui_uk.d.ts.map +1 -1
  317. package/dist/src/properties/ts/odyssey-react-mui_vi.d.ts +2 -0
  318. package/dist/src/properties/ts/odyssey-react-mui_vi.d.ts.map +1 -1
  319. package/dist/src/properties/ts/odyssey-react-mui_zh_CN.d.ts +2 -0
  320. package/dist/src/properties/ts/odyssey-react-mui_zh_CN.d.ts.map +1 -1
  321. package/dist/src/properties/ts/odyssey-react-mui_zh_TW.d.ts +2 -0
  322. package/dist/src/properties/ts/odyssey-react-mui_zh_TW.d.ts.map +1 -1
  323. package/dist/src/test-selectors/querySelector.d.ts +2 -2
  324. package/dist/src/theme/components.d.ts +3 -1
  325. package/dist/src/theme/components.d.ts.map +1 -1
  326. package/dist/src/theme/createOdysseyMuiTheme.d.ts +3 -1
  327. package/dist/src/theme/createOdysseyMuiTheme.d.ts.map +1 -1
  328. package/dist/src/useAutocomplete.d.ts +29 -0
  329. package/dist/src/useAutocomplete.d.ts.map +1 -0
  330. package/dist/src/useContrastMode.d.ts +46 -0
  331. package/dist/src/useContrastMode.d.ts.map +1 -0
  332. package/dist/src/web-component/index.d.ts +14 -0
  333. package/dist/src/web-component/index.d.ts.map +1 -0
  334. package/dist/src/web-component/renderReactInWebComponent.d.ts +76 -0
  335. package/dist/src/web-component/renderReactInWebComponent.d.ts.map +1 -0
  336. package/dist/src/web-component/shadow-dom.d.ts +23 -0
  337. package/dist/src/web-component/shadow-dom.d.ts.map +1 -0
  338. package/dist/test-selectors/querySelector.js.map +1 -1
  339. package/dist/theme/components.js +41 -32
  340. package/dist/theme/components.js.map +1 -1
  341. package/dist/theme/createOdysseyMuiTheme.js +3 -0
  342. package/dist/theme/createOdysseyMuiTheme.js.map +1 -1
  343. package/dist/tsconfig.production.tsbuildinfo +1 -1
  344. package/dist/tsconfig.tsbuildinfo +1 -1
  345. package/dist/useAutocomplete.js +105 -0
  346. package/dist/useAutocomplete.js.map +1 -0
  347. package/dist/useContrastMode.js +93 -0
  348. package/dist/useContrastMode.js.map +1 -0
  349. package/dist/web-component/index.js +14 -0
  350. package/dist/web-component/index.js.map +1 -0
  351. package/dist/web-component/renderReactInWebComponent.js +72 -0
  352. package/dist/web-component/renderReactInWebComponent.js.map +1 -0
  353. package/dist/{createShadowDomElements.js → web-component/shadow-dom.js} +10 -12
  354. package/dist/web-component/shadow-dom.js.map +1 -0
  355. package/jest.config.cjs +21 -2
  356. package/jest.setup.js +0 -3
  357. package/package.json +4 -3
  358. package/src/Autocomplete.tsx +40 -330
  359. package/src/Box.tsx +4 -2
  360. package/src/Card.tsx +1 -0
  361. package/src/OdysseyDesignTokensContext.tsx +6 -3
  362. package/src/OdysseyProvider.tsx +29 -56
  363. package/src/OdysseyThemeProvider.test.tsx +209 -0
  364. package/src/OdysseyThemeProvider.tsx +43 -17
  365. package/src/OdysseyTranslationProvider.types.ts +1 -0
  366. package/src/Pagination/Pagination.test.tsx +305 -0
  367. package/src/Pagination/Pagination.tsx +86 -38
  368. package/src/Select.tsx +12 -3
  369. package/src/Surface.tsx +2 -1
  370. package/src/Tag.tsx +102 -41
  371. package/src/createUniqueAlphabeticalId.test.ts +1 -1
  372. package/src/createUniqueId.test.ts +1 -1
  373. package/src/i18n.ts +2 -0
  374. package/src/index.ts +6 -7
  375. package/src/labs/AppTile.tsx +169 -40
  376. package/src/labs/DataView/CardLayoutContent.tsx +12 -14
  377. package/src/labs/DataView/DataCard.tsx +137 -69
  378. package/src/labs/DataView/DataView.test.tsx +6 -4
  379. package/src/labs/DataView/TableLayoutContent.tsx +6 -2
  380. package/src/labs/DataView/componentTypes.ts +1 -1
  381. package/src/labs/DataView/index.tsx +1 -0
  382. package/src/labs/OdysseyPickers/ComposablePicker.test.tsx +29 -0
  383. package/src/labs/OdysseyPickers/ComposablePicker.tsx +188 -0
  384. package/src/labs/OdysseyPickers/Picker.tsx +381 -0
  385. package/src/labs/OdysseyPickers/PickerVirtualizationListBox.tsx +191 -0
  386. package/src/labs/OdysseyPickers/PickerWithOptionAdornment.tsx +429 -0
  387. package/src/labs/OdysseyPickers/index.ts +15 -0
  388. package/src/labs/PageTemplate.tsx +18 -10
  389. package/src/labs/SideNav/CollapseIcon.tsx +14 -28
  390. package/src/labs/SideNav/HandleIcon.tsx +35 -0
  391. package/src/labs/{NavAccordion.tsx → SideNav/NavAccordion.tsx} +48 -8
  392. package/src/labs/SideNav/OktaAura.tsx +35 -0
  393. package/src/labs/SideNav/OktaLogo.tsx +5 -10
  394. package/src/labs/SideNav/SideNav.test.tsx +323 -0
  395. package/src/labs/SideNav/SideNav.tsx +291 -204
  396. package/src/labs/SideNav/SideNavFooterContent.tsx +36 -28
  397. package/src/labs/SideNav/SideNavHeader.tsx +62 -45
  398. package/src/labs/SideNav/SideNavItemContent.tsx +142 -62
  399. package/src/labs/SideNav/SideNavItemContentContext.tsx +27 -0
  400. package/src/labs/SideNav/SideNavItemLinkContent.tsx +17 -14
  401. package/src/labs/SideNav/SideNavLogo.tsx +41 -0
  402. package/src/labs/SideNav/SideNavToggleButton.tsx +249 -0
  403. package/src/labs/SideNav/types.ts +72 -33
  404. package/src/labs/TopNav/TopNav.tsx +95 -0
  405. package/src/labs/TopNav/TopNavLinksList.tsx +68 -0
  406. package/src/labs/TopNav/TopNavListItem.tsx +209 -0
  407. package/src/labs/TopNav/UserProfile.tsx +79 -0
  408. package/src/labs/TopNav/index.ts +14 -0
  409. package/src/labs/UiShell/UiShell.test.tsx +284 -0
  410. package/src/labs/UiShell/UiShell.tsx +109 -0
  411. package/src/labs/UiShell/UiShellContent.tsx +170 -0
  412. package/src/labs/UiShell/bufferLatest.test.ts +79 -0
  413. package/src/labs/UiShell/bufferLatest.ts +64 -0
  414. package/src/labs/UiShell/createMessageBus.test.ts +115 -0
  415. package/src/labs/UiShell/createMessageBus.ts +53 -0
  416. package/src/labs/UiShell/createStore.test.ts +103 -0
  417. package/src/labs/UiShell/createStore.ts +37 -0
  418. package/src/labs/UiShell/index.ts +17 -0
  419. package/src/labs/UiShell/renderUiShell.test.tsx +197 -0
  420. package/src/labs/UiShell/renderUiShell.tsx +132 -0
  421. package/src/labs/UiShell/useHasUiShell.ts +25 -0
  422. package/src/labs/UiShell/useScrollState.ts +56 -0
  423. package/src/labs/index.ts +10 -3
  424. package/src/properties/odyssey-react-mui.properties +7 -0
  425. package/src/properties/translations/odyssey-react-mui_cs.properties +2 -1
  426. package/src/properties/translations/odyssey-react-mui_da.properties +2 -1
  427. package/src/properties/translations/odyssey-react-mui_de.properties +2 -1
  428. package/src/properties/translations/odyssey-react-mui_el.properties +2 -1
  429. package/src/properties/translations/odyssey-react-mui_es.properties +2 -1
  430. package/src/properties/translations/odyssey-react-mui_fi.properties +2 -1
  431. package/src/properties/translations/odyssey-react-mui_fr.properties +4 -3
  432. package/src/properties/translations/odyssey-react-mui_ht.properties +2 -1
  433. package/src/properties/translations/odyssey-react-mui_hu.properties +2 -1
  434. package/src/properties/translations/odyssey-react-mui_id.properties +2 -1
  435. package/src/properties/translations/odyssey-react-mui_it.properties +3 -2
  436. package/src/properties/translations/odyssey-react-mui_ja.properties +8 -7
  437. package/src/properties/translations/odyssey-react-mui_ko.properties +2 -1
  438. package/src/properties/translations/odyssey-react-mui_ms.properties +2 -1
  439. package/src/properties/translations/odyssey-react-mui_nb.properties +2 -1
  440. package/src/properties/translations/odyssey-react-mui_nl_NL.properties +2 -1
  441. package/src/properties/translations/odyssey-react-mui_pl.properties +2 -1
  442. package/src/properties/translations/odyssey-react-mui_pt_BR.properties +2 -1
  443. package/src/properties/translations/odyssey-react-mui_ro.properties +2 -1
  444. package/src/properties/translations/odyssey-react-mui_ru.properties +2 -1
  445. package/src/properties/translations/odyssey-react-mui_sv.properties +2 -1
  446. package/src/properties/translations/odyssey-react-mui_th.properties +2 -1
  447. package/src/properties/translations/odyssey-react-mui_tr.properties +3 -2
  448. package/src/properties/translations/odyssey-react-mui_uk.properties +2 -1
  449. package/src/properties/translations/odyssey-react-mui_vi.properties +2 -1
  450. package/src/properties/translations/odyssey-react-mui_zh_CN.properties +2 -1
  451. package/src/properties/translations/odyssey-react-mui_zh_TW.properties +2 -1
  452. package/src/properties/ts/odyssey-react-mui.ts +1 -1
  453. package/src/properties/ts/odyssey-react-mui_cs.ts +1 -1
  454. package/src/properties/ts/odyssey-react-mui_da.ts +1 -1
  455. package/src/properties/ts/odyssey-react-mui_de.ts +1 -1
  456. package/src/properties/ts/odyssey-react-mui_el.ts +1 -1
  457. package/src/properties/ts/odyssey-react-mui_es.ts +1 -1
  458. package/src/properties/ts/odyssey-react-mui_fi.ts +1 -1
  459. package/src/properties/ts/odyssey-react-mui_fr.ts +1 -1
  460. package/src/properties/ts/odyssey-react-mui_ht.ts +1 -1
  461. package/src/properties/ts/odyssey-react-mui_hu.ts +1 -1
  462. package/src/properties/ts/odyssey-react-mui_id.ts +1 -1
  463. package/src/properties/ts/odyssey-react-mui_it.ts +1 -1
  464. package/src/properties/ts/odyssey-react-mui_ja.ts +1 -1
  465. package/src/properties/ts/odyssey-react-mui_ko.ts +1 -1
  466. package/src/properties/ts/odyssey-react-mui_ms.ts +1 -1
  467. package/src/properties/ts/odyssey-react-mui_nb.ts +1 -1
  468. package/src/properties/ts/odyssey-react-mui_nl_NL.ts +1 -1
  469. package/src/properties/ts/odyssey-react-mui_pl.ts +1 -1
  470. package/src/properties/ts/odyssey-react-mui_pt_BR.ts +1 -1
  471. package/src/properties/ts/odyssey-react-mui_ro.ts +1 -1
  472. package/src/properties/ts/odyssey-react-mui_ru.ts +1 -1
  473. package/src/properties/ts/odyssey-react-mui_sv.ts +1 -1
  474. package/src/properties/ts/odyssey-react-mui_th.ts +1 -1
  475. package/src/properties/ts/odyssey-react-mui_tr.ts +1 -1
  476. package/src/properties/ts/odyssey-react-mui_uk.ts +1 -1
  477. package/src/properties/ts/odyssey-react-mui_vi.ts +1 -1
  478. package/src/properties/ts/odyssey-react-mui_zh_CN.ts +1 -1
  479. package/src/properties/ts/odyssey-react-mui_zh_TW.ts +1 -1
  480. package/src/test-selectors/querySelector.ts +1 -1
  481. package/src/theme/components.tsx +55 -31
  482. package/src/theme/createOdysseyMuiTheme.ts +4 -0
  483. package/src/theme/useContrastMode.test.tsx +503 -0
  484. package/src/useAutocomplete.tsx +183 -0
  485. package/src/useContrastMode.tsx +149 -0
  486. package/src/web-component/index.ts +14 -0
  487. package/src/web-component/renderReactInWebComponent.test.tsx +156 -0
  488. package/src/web-component/renderReactInWebComponent.ts +153 -0
  489. package/src/web-component/shadow-dom.test.ts +24 -0
  490. package/src/{createShadowDomElements.ts → web-component/shadow-dom.ts} +15 -14
  491. package/dist/ContrastModeProvider.js +0 -86
  492. package/dist/ContrastModeProvider.js.map +0 -1
  493. package/dist/createShadowDomElements.js.map +0 -1
  494. package/dist/labs/NavAccordion.js.map +0 -1
  495. package/dist/labs/TopNav.js +0 -281
  496. package/dist/labs/TopNav.js.map +0 -1
  497. package/dist/src/ContrastModeProvider.d.ts +0 -34
  498. package/dist/src/ContrastModeProvider.d.ts.map +0 -1
  499. package/dist/src/createShadowDomElements.d.ts.map +0 -1
  500. package/dist/src/labs/NavAccordion.d.ts.map +0 -1
  501. package/dist/src/labs/TopNav.d.ts +0 -78
  502. package/dist/src/labs/TopNav.d.ts.map +0 -1
  503. package/src/ContrastModeProvider.tsx +0 -131
  504. package/src/labs/TopNav.tsx +0 -396
@@ -0,0 +1,503 @@
1
+ /*!
2
+ * Copyright (c) 2024-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { render, waitFor, act } from "@testing-library/react";
14
+ import {
15
+ ContrastModeContext,
16
+ defaultParentBackgroundColor,
17
+ getBackgroundColor,
18
+ getElementComputedBackgroundColor,
19
+ hexToRgb,
20
+ hueNeutral50Rgb,
21
+ isTransparentColor,
22
+ normalizeBackgroundColor,
23
+ normalizeRgbaToRgb,
24
+ useContrastMode,
25
+ useContrastModeContext,
26
+ } from "../useContrastMode";
27
+ import * as Tokens from "@okta/odyssey-design-tokens";
28
+ import { renderHook } from "@testing-library/react";
29
+
30
+ describe("useContrastMode and related functions", () => {
31
+ afterEach(() => {
32
+ jest.clearAllMocks();
33
+ document.documentElement.style.setProperty("backgroundColor", null);
34
+ });
35
+
36
+ describe("useContrastMode hook", () => {
37
+ let getComputedStyleSpy: jest.SpyInstance;
38
+
39
+ beforeEach(() => {
40
+ getComputedStyleSpy = jest
41
+ .spyOn(window, "getComputedStyle")
42
+ .mockImplementation(
43
+ () =>
44
+ ({ backgroundColor: "rgba(0, 0, 0, 0)" }) as CSSStyleDeclaration,
45
+ );
46
+ });
47
+
48
+ afterEach(() => {
49
+ getComputedStyleSpy.mockRestore();
50
+ });
51
+
52
+ it("should return lowContrast mode by default", () => {
53
+ const { result } = renderHook(() => useContrastMode({}), {
54
+ wrapper: ({ children }) => (
55
+ <ContrastModeContext.Provider value={{ contrastMode: "lowContrast" }}>
56
+ {children}
57
+ </ContrastModeContext.Provider>
58
+ ),
59
+ });
60
+ expect(result.current.parentBackgroundColor).toBe(
61
+ defaultParentBackgroundColor,
62
+ );
63
+ expect(result.current.contrastMode).toBe("lowContrast");
64
+ expect(result.current.contrastContainerRef.current).toBe(null);
65
+ });
66
+
67
+ it("should respect explicitly set contrast mode", () => {
68
+ const { result } = renderHook(
69
+ () => useContrastMode({ contrastMode: "highContrast" }),
70
+ {
71
+ wrapper: ({ children }) => (
72
+ <ContrastModeContext.Provider
73
+ value={{ contrastMode: "lowContrast" }}
74
+ >
75
+ {children}
76
+ </ContrastModeContext.Provider>
77
+ ),
78
+ },
79
+ );
80
+
81
+ expect(result.current.contrastMode).toBe("highContrast");
82
+ });
83
+
84
+ it("should update contrast mode based on background color changes", async () => {
85
+ // Mock getComputedStyle to simulate background color checks
86
+ getComputedStyleSpy.mockImplementation(
87
+ () => ({ backgroundColor: Tokens.HueNeutral50 }) as CSSStyleDeclaration,
88
+ );
89
+
90
+ const TestComponent = () => {
91
+ const { contrastContainerRef, contrastMode } = useContrastMode({});
92
+ return (
93
+ <div ref={contrastContainerRef} data-testid="container">
94
+ {contrastMode}
95
+ </div>
96
+ );
97
+ };
98
+
99
+ const { getByTestId } = render(
100
+ <ContrastModeContext.Provider value={{ contrastMode: "lowContrast" }}>
101
+ <TestComponent />
102
+ </ContrastModeContext.Provider>,
103
+ );
104
+
105
+ const testContainer = getByTestId("container");
106
+
107
+ // Create and dispatch a transitionend event to simulate CSS transition completion
108
+ // Storybook and certain elements use transitions which could interfere with tests
109
+ await act(async () => {
110
+ testContainer.style.backgroundColor = Tokens.HueNeutral50;
111
+
112
+ const transitionEvent = new Event("transitionend");
113
+
114
+ testContainer.dispatchEvent(
115
+ Object.assign(transitionEvent, { propertyName: "background-color" }),
116
+ );
117
+
118
+ await Promise.resolve();
119
+ });
120
+
121
+ await waitFor(() => {
122
+ expect(getByTestId("container").textContent).toBe("highContrast");
123
+ });
124
+ });
125
+
126
+ it("should clean up observers and event listeners on unmount", () => {
127
+ const disconnect = jest.fn();
128
+ const observe = jest.fn();
129
+ const addEventListenerSpy = jest.spyOn(document, "addEventListener");
130
+ const removeEventListenerSpy = jest.spyOn(
131
+ document,
132
+ "removeEventListener",
133
+ );
134
+
135
+ const mockMutationObserver = jest.fn<
136
+ MutationObserver,
137
+ [MutationCallback]
138
+ >(() => ({
139
+ disconnect,
140
+ observe,
141
+ takeRecords: jest.fn(),
142
+ }));
143
+
144
+ const originalMutationObserver = global.MutationObserver;
145
+ global.MutationObserver = mockMutationObserver;
146
+
147
+ const TestComponent = () => {
148
+ const { contrastContainerRef } = useContrastMode({});
149
+ return <div ref={contrastContainerRef}>Test</div>;
150
+ };
151
+
152
+ const { unmount } = render(
153
+ <ContrastModeContext.Provider value={{ contrastMode: "lowContrast" }}>
154
+ <TestComponent />
155
+ </ContrastModeContext.Provider>,
156
+ );
157
+
158
+ unmount();
159
+
160
+ expect(disconnect).toHaveBeenCalled();
161
+ expect(removeEventListenerSpy).toHaveBeenCalledWith(
162
+ "transitionend",
163
+ expect.any(Function),
164
+ );
165
+
166
+ global.MutationObserver = originalMutationObserver;
167
+ addEventListenerSpy.mockRestore();
168
+ removeEventListenerSpy.mockRestore();
169
+ });
170
+ });
171
+
172
+ describe("getBackgroundColor", () => {
173
+ let getComputedStyleSpy: jest.SpyInstance;
174
+
175
+ beforeEach(() => {
176
+ getComputedStyleSpy = jest
177
+ .spyOn(window, "getComputedStyle")
178
+ .mockImplementation(
179
+ () =>
180
+ ({ backgroundColor: "rgba(0, 0, 0, 0)" }) as CSSStyleDeclaration,
181
+ );
182
+ });
183
+
184
+ afterEach(() => {
185
+ getComputedStyleSpy.mockRestore();
186
+ });
187
+
188
+ it("returns defaultParentBackgroundColor if transparent background is found", () => {
189
+ const element = document.createElement("div");
190
+ expect(getBackgroundColor(element)).toBe(defaultParentBackgroundColor);
191
+ });
192
+
193
+ it("returns the background color of the element if it is not transparent", () => {
194
+ const getComputedStyleSpy = jest
195
+ .spyOn(window, "getComputedStyle")
196
+ .mockImplementation(
197
+ (element: Element) =>
198
+ ({
199
+ backgroundColor:
200
+ (element as HTMLElement).style.backgroundColor ||
201
+ "rgba(0, 0, 0, 0)",
202
+ }) as CSSStyleDeclaration,
203
+ );
204
+
205
+ const element = document.createElement("div");
206
+ element.style.setProperty("background-color", "rgb(255, 0, 0)");
207
+ const result = getBackgroundColor(element);
208
+ expect(result).toBe("rgb(255, 0, 0)");
209
+
210
+ getComputedStyleSpy.mockRestore();
211
+ });
212
+
213
+ it("returns defaultParentBackgroundColor if no non-transparent background is found", () => {
214
+ const getComputedStyleSpy = jest
215
+ .spyOn(window, "getComputedStyle")
216
+ .mockImplementation(
217
+ () =>
218
+ ({ backgroundColor: "rgba(0, 0, 0, 0)" }) as CSSStyleDeclaration,
219
+ );
220
+
221
+ const element = document.createElement("div");
222
+ expect(getBackgroundColor(element)).toBe(defaultParentBackgroundColor);
223
+
224
+ getComputedStyleSpy.mockRestore();
225
+ });
226
+
227
+ it("returns the background color of the parent if the element is transparent", () => {
228
+ const parent = document.createElement("div");
229
+ const child = document.createElement("div");
230
+ parent.appendChild(child);
231
+ parent.style.setProperty("background-color", "rgb(0, 255, 0)");
232
+
233
+ const getComputedStyleSpy = jest
234
+ .spyOn(window, "getComputedStyle")
235
+ .mockImplementation(
236
+ (el: Element) =>
237
+ ({
238
+ backgroundColor:
239
+ el === parent ? "rgb(0, 255, 0)" : "rgba(0, 0, 0, 0)",
240
+ }) as CSSStyleDeclaration,
241
+ );
242
+
243
+ expect(getBackgroundColor(child)).toBe("rgb(0, 255, 0)");
244
+
245
+ getComputedStyleSpy.mockRestore();
246
+ });
247
+
248
+ it("returns HueNeutral50 token for its RGB equivalent", () => {
249
+ const getComputedStyleSpy = jest
250
+ .spyOn(window, "getComputedStyle")
251
+ .mockImplementation(
252
+ () => ({ backgroundColor: hueNeutral50Rgb }) as CSSStyleDeclaration,
253
+ );
254
+
255
+ const element = document.createElement("div");
256
+ element.style.setProperty("background-color", hueNeutral50Rgb);
257
+ expect(getBackgroundColor(element)).toBe(Tokens.HueNeutral50);
258
+
259
+ getComputedStyleSpy.mockRestore();
260
+ });
261
+
262
+ it("handles nested transparent elements correctly", () => {
263
+ const grandparent = document.createElement("div");
264
+ const parent = document.createElement("div");
265
+ const child = document.createElement("div");
266
+ grandparent.appendChild(parent);
267
+ parent.appendChild(child);
268
+ grandparent.style.setProperty("backgroundColor", "rgb(0, 0, 255)");
269
+
270
+ const getComputedStyleSpy = jest
271
+ .spyOn(window, "getComputedStyle")
272
+ .mockImplementation(
273
+ (el: Element) =>
274
+ ({
275
+ backgroundColor:
276
+ el === grandparent ? "rgb(0, 0, 255)" : "rgba(0, 0, 0, 0)",
277
+ }) as CSSStyleDeclaration,
278
+ );
279
+
280
+ expect(getBackgroundColor(child)).toBe("rgb(0, 0, 255)");
281
+
282
+ getComputedStyleSpy.mockRestore();
283
+ });
284
+ });
285
+
286
+ describe("MutationObserver functionality", () => {
287
+ let originalAddEventListener: typeof document.addEventListener;
288
+ let originalRemoveEventListener: typeof document.removeEventListener;
289
+
290
+ beforeEach(() => {
291
+ originalAddEventListener = document.addEventListener;
292
+ originalRemoveEventListener = document.removeEventListener;
293
+ document.addEventListener = jest.fn();
294
+ document.removeEventListener = jest.fn();
295
+ });
296
+
297
+ afterEach(() => {
298
+ document.addEventListener = originalAddEventListener;
299
+ document.removeEventListener = originalRemoveEventListener;
300
+ });
301
+
302
+ it("should clean up observers and event listeners on unmount", () => {
303
+ const disconnect = jest.fn();
304
+ const observe = jest.fn();
305
+
306
+ const mockMutationObserver = jest.fn<
307
+ MutationObserver,
308
+ [MutationCallback]
309
+ >(() => ({
310
+ disconnect,
311
+ observe,
312
+ takeRecords: jest.fn(),
313
+ }));
314
+
315
+ const originalMutationObserver = global.MutationObserver;
316
+ global.MutationObserver = mockMutationObserver;
317
+
318
+ const TestComponent = () => {
319
+ const { contrastContainerRef } = useContrastMode({});
320
+ return <div ref={contrastContainerRef}>Test</div>;
321
+ };
322
+
323
+ const { unmount } = render(
324
+ <ContrastModeContext.Provider value={{ contrastMode: "lowContrast" }}>
325
+ <TestComponent />
326
+ </ContrastModeContext.Provider>,
327
+ );
328
+
329
+ unmount();
330
+
331
+ expect(disconnect).toHaveBeenCalled();
332
+ expect(document.removeEventListener).toHaveBeenCalledWith(
333
+ "transitionend",
334
+ expect.any(Function),
335
+ );
336
+
337
+ global.MutationObserver = originalMutationObserver;
338
+ });
339
+ });
340
+
341
+ describe("useContrastModeContext", () => {
342
+ it("should return the current contrast mode from context", () => {
343
+ const { result } = renderHook(() => useContrastModeContext(), {
344
+ wrapper: ({ children }) => (
345
+ <ContrastModeContext.Provider
346
+ value={{ contrastMode: "highContrast" }}
347
+ >
348
+ {children}
349
+ </ContrastModeContext.Provider>
350
+ ),
351
+ });
352
+
353
+ expect(result.current.contrastMode).toBe("highContrast");
354
+ });
355
+ });
356
+
357
+ it("detects parent background color changes", () => {
358
+ const parent = document.createElement("div");
359
+ const child = document.createElement("div");
360
+ parent.appendChild(child);
361
+
362
+ const getComputedStyleSpy = jest
363
+ .spyOn(window, "getComputedStyle")
364
+ .mockImplementation(
365
+ (el: Element) =>
366
+ ({
367
+ backgroundColor:
368
+ el === parent ? Tokens.HueNeutral50 : "rgba(0, 0, 0, 0)",
369
+ }) as CSSStyleDeclaration,
370
+ );
371
+
372
+ const result = getBackgroundColor(child);
373
+ expect(result).toBe(Tokens.HueNeutral50);
374
+
375
+ getComputedStyleSpy.mockRestore();
376
+ });
377
+
378
+ describe("Color utility functions", () => {
379
+ describe("hexToRgb", () => {
380
+ it("converts black hex to rgb", () => {
381
+ expect(hexToRgb("#000000")).toBe("rgb(0, 0, 0)");
382
+ });
383
+
384
+ it("converts white hex to rgb", () => {
385
+ expect(hexToRgb("#ffffff")).toBe("rgb(255, 255, 255)");
386
+ });
387
+
388
+ it("converts mixed color hex to rgb", () => {
389
+ expect(hexToRgb("#ff0088")).toBe("rgb(255, 0, 136)");
390
+ });
391
+
392
+ it("correctly converts HueNeutral50 token to rgb", () => {
393
+ const result = hexToRgb(Tokens.HueNeutral50);
394
+ expect(result).toBe(hueNeutral50Rgb);
395
+ });
396
+ });
397
+
398
+ describe("isTransparentColor", () => {
399
+ it("identifies rgba(0, 0, 0, 0) as transparent", () => {
400
+ expect(isTransparentColor("rgba(0, 0, 0, 0)")).toBe(true);
401
+ });
402
+
403
+ it('identifies "transparent" keyword as transparent', () => {
404
+ expect(isTransparentColor("transparent")).toBe(true);
405
+ });
406
+
407
+ it("identifies solid colors as non-transparent", () => {
408
+ expect(isTransparentColor("rgb(255, 255, 255)")).toBe(false);
409
+ expect(isTransparentColor("rgba(255, 255, 255, 1)")).toBe(false);
410
+ expect(isTransparentColor(defaultParentBackgroundColor)).toBe(false);
411
+ });
412
+ });
413
+
414
+ describe("normalizeRgbaToRgb", () => {
415
+ it("converts rgba to rgb format", () => {
416
+ expect(normalizeRgbaToRgb("rgba(255, 128, 0, 0.5)")).toBe(
417
+ "rgb(255, 128, 0)",
418
+ );
419
+ });
420
+
421
+ it("handles zero alpha value", () => {
422
+ expect(normalizeRgbaToRgb("rgba(255, 128, 0, 0)")).toBe(
423
+ "rgb(255, 128, 0)",
424
+ );
425
+ });
426
+
427
+ it("handles full alpha value", () => {
428
+ expect(normalizeRgbaToRgb("rgba(255, 128, 0, 1)")).toBe(
429
+ "rgb(255, 128, 0)",
430
+ );
431
+ });
432
+
433
+ it("does not modify rgb format", () => {
434
+ const rgbColor = "rgb(255, 128, 0)";
435
+ expect(normalizeRgbaToRgb(rgbColor)).toBe(rgbColor);
436
+ });
437
+ });
438
+
439
+ describe("normalizeBackgroundColor", () => {
440
+ it("converts rgba to rgb and matches against HueNeutral50", () => {
441
+ const rgbaColor = hueNeutral50Rgb
442
+ .replace("rgb", "rgba")
443
+ .replace(")", ", 0.5)");
444
+ expect(normalizeBackgroundColor(rgbaColor)).toBe(Tokens.HueNeutral50);
445
+ });
446
+
447
+ it("returns original color if not matching HueNeutral50", () => {
448
+ const rgbaColor = "rgba(255, 0, 0, 0.5)";
449
+ expect(normalizeBackgroundColor(rgbaColor)).toBe("rgb(255, 0, 0)");
450
+ });
451
+
452
+ it("returns HueNeutral50 token for matching rgb value", () => {
453
+ expect(normalizeBackgroundColor(hueNeutral50Rgb)).toBe(
454
+ Tokens.HueNeutral50,
455
+ );
456
+ });
457
+
458
+ it("returns original color for non-matching rgb value", () => {
459
+ const rgbColor = "rgb(255, 0, 0)";
460
+ expect(normalizeBackgroundColor(rgbColor)).toBe(rgbColor);
461
+ });
462
+ });
463
+
464
+ describe("getElementComputedBackgroundColor", () => {
465
+ let getComputedStyleSpy: jest.SpyInstance;
466
+
467
+ beforeEach(() => {
468
+ getComputedStyleSpy = jest.spyOn(window, "getComputedStyle");
469
+ });
470
+
471
+ afterEach(() => {
472
+ getComputedStyleSpy.mockRestore();
473
+ });
474
+
475
+ it("returns the computed background color of an element", () => {
476
+ const element = document.createElement("div");
477
+ const expectedColor = "rgb(255, 0, 0)";
478
+
479
+ getComputedStyleSpy.mockImplementation(
480
+ () =>
481
+ ({
482
+ backgroundColor: expectedColor,
483
+ }) as CSSStyleDeclaration,
484
+ );
485
+
486
+ expect(getElementComputedBackgroundColor(element)).toBe(expectedColor);
487
+ });
488
+
489
+ it("handles transparent background color", () => {
490
+ const element = document.createElement("div");
491
+
492
+ getComputedStyleSpy.mockImplementation(
493
+ () =>
494
+ ({
495
+ backgroundColor: "transparent",
496
+ }) as CSSStyleDeclaration,
497
+ );
498
+
499
+ expect(getElementComputedBackgroundColor(element)).toBe("transparent");
500
+ });
501
+ });
502
+ });
503
+ });
@@ -0,0 +1,183 @@
1
+ /*!
2
+ * Copyright (c) 2024-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { useCallback, useMemo, useRef } from "react";
14
+ import {
15
+ InputBase,
16
+ AutocompleteValue,
17
+ AutocompleteRenderInputParams,
18
+ } from "@mui/material";
19
+
20
+ import { AutocompleteProps } from "./Autocomplete";
21
+ import { Field } from "./Field";
22
+ import {
23
+ ComponentControlledState,
24
+ useInputValues,
25
+ getControlState,
26
+ } from "./inputUtils";
27
+
28
+ export type UseAutocompleteProps<
29
+ OptionType,
30
+ HasMultipleChoices extends boolean | undefined,
31
+ IsCustomValueAllowed extends boolean | undefined,
32
+ > = Pick<
33
+ AutocompleteProps<OptionType, HasMultipleChoices, IsCustomValueAllowed>,
34
+ | "ariaDescribedBy"
35
+ | "defaultValue"
36
+ | "errorMessage"
37
+ | "errorMessageList"
38
+ | "hasMultipleChoices"
39
+ | "hint"
40
+ | "HintLinkComponent"
41
+ | "inputValue"
42
+ | "isFullWidth"
43
+ | "isOptional"
44
+ | "isVirtualized"
45
+ | "label"
46
+ | "name"
47
+ | "testId"
48
+ | "value"
49
+ >;
50
+
51
+ export const useAutocomplete = <
52
+ OptionType,
53
+ HasMultipleChoices extends boolean | undefined,
54
+ IsCustomValueAllowed extends boolean | undefined,
55
+ >({
56
+ ariaDescribedBy,
57
+ defaultValue,
58
+ errorMessage,
59
+ errorMessageList,
60
+ hasMultipleChoices,
61
+ hint,
62
+ HintLinkComponent,
63
+ inputValue,
64
+ isFullWidth,
65
+ isOptional,
66
+ isVirtualized: isVirtualizedProp,
67
+ label,
68
+ name: nameOverride,
69
+ testId,
70
+ value,
71
+ }: UseAutocompleteProps<
72
+ OptionType,
73
+ HasMultipleChoices,
74
+ IsCustomValueAllowed
75
+ >) => {
76
+ const controlledStateRef = useRef(
77
+ getControlState({
78
+ controlledValue: value,
79
+ uncontrolledValue: defaultValue,
80
+ }),
81
+ );
82
+
83
+ const isVirtualizedRef = useRef(Boolean(isVirtualizedProp));
84
+
85
+ const defaultValueProp = useMemo<
86
+ | AutocompleteValue<
87
+ OptionType,
88
+ HasMultipleChoices,
89
+ undefined,
90
+ IsCustomValueAllowed
91
+ >
92
+ | undefined
93
+ >(() => {
94
+ if (hasMultipleChoices) {
95
+ if (value === undefined) {
96
+ return defaultValue;
97
+ }
98
+ return [] as AutocompleteValue<
99
+ OptionType,
100
+ HasMultipleChoices,
101
+ undefined,
102
+ IsCustomValueAllowed
103
+ >;
104
+ }
105
+ return value === undefined ? defaultValue : undefined;
106
+ }, [defaultValue, hasMultipleChoices, value]);
107
+
108
+ const valueProps = useInputValues({
109
+ defaultValue: defaultValueProp,
110
+ value: value,
111
+ controlState: controlledStateRef.current,
112
+ });
113
+
114
+ const inputValueProp = useMemo(() => {
115
+ if (controlledStateRef.current === ComponentControlledState.CONTROLLED) {
116
+ return { inputValue };
117
+ }
118
+ return undefined;
119
+ }, [inputValue]);
120
+
121
+ const renderInput = useCallback(
122
+ ({
123
+ InputLabelProps,
124
+ InputProps,
125
+ ...params
126
+ }: AutocompleteRenderInputParams) => (
127
+ <Field
128
+ ariaDescribedBy={ariaDescribedBy}
129
+ errorMessage={errorMessage}
130
+ errorMessageList={errorMessageList}
131
+ fieldType="single"
132
+ hasVisibleLabel
133
+ //@ts-expect-error htmlFor does not exist ont he InputLabelProps for autocomplete
134
+ id={InputLabelProps.htmlFor}
135
+ isFullWidth={isFullWidth}
136
+ hint={hint}
137
+ HintLinkComponent={HintLinkComponent}
138
+ label={label}
139
+ isOptional={isOptional}
140
+ renderFieldComponent={({
141
+ ariaDescribedBy,
142
+ id,
143
+ errorMessageElementId,
144
+ labelElementId,
145
+ }) => (
146
+ <InputBase
147
+ {...params}
148
+ {...InputProps}
149
+ inputProps={{
150
+ ...params.inputProps,
151
+ "aria-errormessage": errorMessageElementId,
152
+ "aria-labelledby": labelElementId,
153
+ "data-se": testId,
154
+ }}
155
+ aria-describedby={ariaDescribedBy}
156
+ id={id}
157
+ name={nameOverride ?? id}
158
+ required={!isOptional}
159
+ />
160
+ )}
161
+ />
162
+ ),
163
+ [
164
+ ariaDescribedBy,
165
+ errorMessage,
166
+ errorMessageList,
167
+ hint,
168
+ HintLinkComponent,
169
+ isFullWidth,
170
+ isOptional,
171
+ label,
172
+ nameOverride,
173
+ testId,
174
+ ],
175
+ );
176
+
177
+ return {
178
+ inputValueProp,
179
+ isVirtualizedRef,
180
+ renderInput,
181
+ valueProps,
182
+ };
183
+ };