@12-apps/ui 6.7.0 → 6.9.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 (405) hide show
  1. package/dist/chunk-3X3JVF6E.js +438 -0
  2. package/dist/chunk-3X3JVF6E.js.map +1 -0
  3. package/dist/chunk-AL3W7TXN.js +465 -0
  4. package/dist/chunk-AL3W7TXN.js.map +1 -0
  5. package/dist/{chunk-QLBYAYUG.js → chunk-KR2BP7NK.js} +4 -4
  6. package/dist/chunk-KR2BP7NK.js.map +1 -0
  7. package/dist/{chunk-DFVRZ3UK.js → chunk-KXARS46L.js} +3 -3
  8. package/dist/chunk-KXARS46L.js.map +1 -0
  9. package/dist/{chunk-JP55QWVR.js → chunk-L7L6SX64.js} +5 -2
  10. package/dist/chunk-L7L6SX64.js.map +1 -0
  11. package/dist/{chunk-QZZVHY6U.js → chunk-PVLDKXKR.js} +7 -3
  12. package/dist/chunk-PVLDKXKR.js.map +1 -0
  13. package/dist/{chunk-H7UAGTVW.js → chunk-TSG5C7MP.js} +4 -3
  14. package/dist/chunk-TSG5C7MP.js.map +1 -0
  15. package/dist/{chunk-NUCLEOHF.js → chunk-UNM7KFDX.js} +44 -14
  16. package/dist/chunk-UNM7KFDX.js.map +1 -0
  17. package/dist/{chunk-CEKPLUQV.js → chunk-UY7UF7IN.js} +19 -13
  18. package/dist/chunk-UY7UF7IN.js.map +1 -0
  19. package/dist/data-display/DataGrid.js +1 -1
  20. package/dist/data-display/DataViews.js +88 -65
  21. package/dist/data-display/DataViews.js.map +1 -1
  22. package/dist/data-display/HoverCard.js +4 -1
  23. package/dist/data-display/HoverCard.js.map +1 -1
  24. package/dist/data-display/Table.js +4 -2
  25. package/dist/data-display/Table.js.map +1 -1
  26. package/dist/data-display/TimingDiagram.js +3 -2
  27. package/dist/data-display/TimingDiagram.js.map +1 -1
  28. package/dist/en-US.js +56 -0
  29. package/dist/en-US.js.map +1 -0
  30. package/dist/feedback/Sonner.js +5 -4
  31. package/dist/feedback/Sonner.js.map +1 -1
  32. package/dist/feedback/StackedModal.js +1 -1
  33. package/dist/feedback/TutorialOverlay.js +19 -5
  34. package/dist/feedback/TutorialOverlay.js.map +1 -1
  35. package/dist/form/AddressAutocomplete.js +16 -8
  36. package/dist/form/AddressAutocomplete.js.map +1 -1
  37. package/dist/form/Autocomplete.js +9 -7
  38. package/dist/form/Autocomplete.js.map +1 -1
  39. package/dist/form/Calendar.js +1 -1
  40. package/dist/form/CodeEditor.js +14 -9
  41. package/dist/form/CodeEditor.js.map +1 -1
  42. package/dist/form/DateRangePicker.js +10 -3
  43. package/dist/form/DateRangePicker.js.map +1 -1
  44. package/dist/form/Menubar.js +4 -1
  45. package/dist/form/Menubar.js.map +1 -1
  46. package/dist/form/PasswordStrength.js +48 -28
  47. package/dist/form/PasswordStrength.js.map +1 -1
  48. package/dist/form/PhoneInput.js +11 -5
  49. package/dist/form/PhoneInput.js.map +1 -1
  50. package/dist/form/SearchPalette.js +4 -1
  51. package/dist/form/SearchPalette.js.map +1 -1
  52. package/dist/form/Textarea.js +21 -19
  53. package/dist/form/Textarea.js.map +1 -1
  54. package/dist/form/UploadButton.js +16 -11
  55. package/dist/form/UploadButton.js.map +1 -1
  56. package/dist/layout/ContentToolbar.js +1 -1
  57. package/dist/layout/Dashboard.js +2 -1
  58. package/dist/layout/Dashboard.js.map +1 -1
  59. package/dist/layout/ScrollArea.js +9 -3
  60. package/dist/layout/ScrollArea.js.map +1 -1
  61. package/dist/layout/TableFilter.js +1 -1
  62. package/dist/locales.js +171 -0
  63. package/dist/locales.js.map +1 -0
  64. package/dist/navigation/Breadcrumbs.js +9 -3
  65. package/dist/navigation/Breadcrumbs.js.map +1 -1
  66. package/dist/navigation/CommandPalette.js +20 -7
  67. package/dist/navigation/CommandPalette.js.map +1 -1
  68. package/dist/navigation/Pagination.js +1 -1
  69. package/dist/navigation/Tabs.js +7 -3
  70. package/dist/navigation/Tabs.js.map +1 -1
  71. package/dist/pt-BR.js +42 -274
  72. package/dist/pt-BR.js.map +1 -1
  73. package/dist/types/components/data-display/DataGrid/DataGrid.states.d.ts +1 -0
  74. package/dist/types/components/data-display/DataGrid/DataGrid.states.d.ts.map +1 -1
  75. package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts +5 -0
  76. package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts.map +1 -1
  77. package/dist/types/components/data-display/DataViews/data-views-category-pill.d.ts.map +1 -1
  78. package/dist/types/components/data-display/DataViews/data-views-copy.d.ts +27 -1
  79. package/dist/types/components/data-display/DataViews/data-views-copy.d.ts.map +1 -1
  80. package/dist/types/components/data-display/DataViews/data-views-day-input.d.ts +12 -1
  81. package/dist/types/components/data-display/DataViews/data-views-day-input.d.ts.map +1 -1
  82. package/dist/types/components/data-display/DataViews/data-views-filter-panel.d.ts.map +1 -1
  83. package/dist/types/components/data-display/DataViews/data-views-grid-bodies.d.ts.map +1 -1
  84. package/dist/types/components/data-display/DataViews/data-views-grid-parts.d.ts.map +1 -1
  85. package/dist/types/components/data-display/DataViews/data-views-more-fields.d.ts.map +1 -1
  86. package/dist/types/components/data-display/DataViews/data-views-pagination.d.ts.map +1 -1
  87. package/dist/types/components/data-display/DataViews/data-views-range-pill.d.ts.map +1 -1
  88. package/dist/types/components/data-display/DataViews/data-views-toolbar.d.ts.map +1 -1
  89. package/dist/types/components/data-display/HoverCard/HoverCard.content.d.ts +1 -1
  90. package/dist/types/components/data-display/HoverCard/HoverCard.content.d.ts.map +1 -1
  91. package/dist/types/components/data-display/HoverCard/HoverCard.d.ts.map +1 -1
  92. package/dist/types/components/data-display/HoverCard/HoverCard.types.d.ts +2 -0
  93. package/dist/types/components/data-display/HoverCard/HoverCard.types.d.ts.map +1 -1
  94. package/dist/types/components/data-display/Table/Table.d.ts.map +1 -1
  95. package/dist/types/components/data-display/Table/Table.types.d.ts +5 -0
  96. package/dist/types/components/data-display/Table/Table.types.d.ts.map +1 -1
  97. package/dist/types/components/data-display/Table/TableStates.d.ts +3 -1
  98. package/dist/types/components/data-display/Table/TableStates.d.ts.map +1 -1
  99. package/dist/types/components/data-display/TimingDiagram/TimingDiagram.d.ts.map +1 -1
  100. package/dist/types/components/data-display/TimingDiagram/TimingDiagram.types.d.ts +3 -0
  101. package/dist/types/components/data-display/TimingDiagram/TimingDiagram.types.d.ts.map +1 -1
  102. package/dist/types/components/feedback/Sonner/Sonner.d.ts +8 -0
  103. package/dist/types/components/feedback/Sonner/Sonner.d.ts.map +1 -1
  104. package/dist/types/components/feedback/Sonner/Sonner.types.d.ts +2 -0
  105. package/dist/types/components/feedback/Sonner/Sonner.types.d.ts.map +1 -1
  106. package/dist/types/components/feedback/Sonner/SonnerToast.d.ts.map +1 -1
  107. package/dist/types/components/feedback/StackedModal/StackedModal.d.ts.map +1 -1
  108. package/dist/types/components/feedback/StackedModal/StackedModal.parts.d.ts +2 -0
  109. package/dist/types/components/feedback/StackedModal/StackedModal.parts.d.ts.map +1 -1
  110. package/dist/types/components/feedback/StackedModal/StackedModal.types.d.ts +2 -0
  111. package/dist/types/components/feedback/StackedModal/StackedModal.types.d.ts.map +1 -1
  112. package/dist/types/components/feedback/TutorialOverlay/TutorialOverlay.d.ts.map +1 -1
  113. package/dist/types/components/feedback/TutorialOverlay/TutorialOverlay.types.d.ts +3 -0
  114. package/dist/types/components/feedback/TutorialOverlay/TutorialOverlay.types.d.ts.map +1 -1
  115. package/dist/types/components/feedback/TutorialOverlay/TutorialStepBody.d.ts +2 -0
  116. package/dist/types/components/feedback/TutorialOverlay/TutorialStepBody.d.ts.map +1 -1
  117. package/dist/types/components/form/AddressAutocomplete/AddressAutocomplete.types.d.ts +7 -0
  118. package/dist/types/components/form/AddressAutocomplete/AddressAutocomplete.types.d.ts.map +1 -1
  119. package/dist/types/components/form/AddressAutocomplete/AddressAutocompleteField.d.ts.map +1 -1
  120. package/dist/types/components/form/AddressAutocomplete/AddressFallbackField.d.ts +1 -0
  121. package/dist/types/components/form/AddressAutocomplete/AddressFallbackField.d.ts.map +1 -1
  122. package/dist/types/components/form/AddressAutocomplete/AddressInputField.d.ts +1 -0
  123. package/dist/types/components/form/AddressAutocomplete/AddressInputField.d.ts.map +1 -1
  124. package/dist/types/components/form/Autocomplete/Autocomplete.d.ts.map +1 -1
  125. package/dist/types/components/form/Autocomplete/Autocomplete.parts.d.ts +9 -3
  126. package/dist/types/components/form/Autocomplete/Autocomplete.parts.d.ts.map +1 -1
  127. package/dist/types/components/form/Autocomplete/Autocomplete.types.d.ts +7 -0
  128. package/dist/types/components/form/Autocomplete/Autocomplete.types.d.ts.map +1 -1
  129. package/dist/types/components/form/Calendar/Calendar.types.d.ts +6 -0
  130. package/dist/types/components/form/Calendar/Calendar.types.d.ts.map +1 -1
  131. package/dist/types/components/form/CodeEditor/CodeEditor.d.ts.map +1 -1
  132. package/dist/types/components/form/CodeEditor/CodeEditor.types.d.ts +7 -0
  133. package/dist/types/components/form/CodeEditor/CodeEditor.types.d.ts.map +1 -1
  134. package/dist/types/components/form/CodeEditor/CodeEditorToolbar.d.ts +2 -0
  135. package/dist/types/components/form/CodeEditor/CodeEditorToolbar.d.ts.map +1 -1
  136. package/dist/types/components/form/DateRangePicker/DateRangePicker.d.ts.map +1 -1
  137. package/dist/types/components/form/DateRangePicker/DateRangePicker.range.d.ts.map +1 -1
  138. package/dist/types/components/form/DateRangePicker/DateRangePicker.types.d.ts +11 -0
  139. package/dist/types/components/form/DateRangePicker/DateRangePicker.types.d.ts.map +1 -1
  140. package/dist/types/components/form/DateRangePicker/DateRangePickerFields.d.ts.map +1 -1
  141. package/dist/types/components/form/Menubar/Menubar.d.ts.map +1 -1
  142. package/dist/types/components/form/Menubar/Menubar.toolbar.d.ts +1 -0
  143. package/dist/types/components/form/Menubar/Menubar.toolbar.d.ts.map +1 -1
  144. package/dist/types/components/form/Menubar/Menubar.types.d.ts +5 -0
  145. package/dist/types/components/form/Menubar/Menubar.types.d.ts.map +1 -1
  146. package/dist/types/components/form/PasswordStrength/PasswordStrength.d.ts.map +1 -1
  147. package/dist/types/components/form/PasswordStrength/PasswordStrength.helpers.d.ts +4 -2
  148. package/dist/types/components/form/PasswordStrength/PasswordStrength.helpers.d.ts.map +1 -1
  149. package/dist/types/components/form/PasswordStrength/PasswordStrength.types.d.ts +8 -0
  150. package/dist/types/components/form/PasswordStrength/PasswordStrength.types.d.ts.map +1 -1
  151. package/dist/types/components/form/PhoneInput/PhoneInput.d.ts.map +1 -1
  152. package/dist/types/components/form/PhoneInput/PhoneInput.types.d.ts +7 -0
  153. package/dist/types/components/form/PhoneInput/PhoneInput.types.d.ts.map +1 -1
  154. package/dist/types/components/form/SearchPalette/SearchPalette.d.ts.map +1 -1
  155. package/dist/types/components/form/SearchPalette/SearchPalette.parts.d.ts +2 -0
  156. package/dist/types/components/form/SearchPalette/SearchPalette.parts.d.ts.map +1 -1
  157. package/dist/types/components/form/SearchPalette/SearchPalette.types.d.ts +6 -0
  158. package/dist/types/components/form/SearchPalette/SearchPalette.types.d.ts.map +1 -1
  159. package/dist/types/components/form/Textarea/Textarea.d.ts.map +1 -1
  160. package/dist/types/components/form/Textarea/Textarea.types.d.ts +16 -1
  161. package/dist/types/components/form/Textarea/Textarea.types.d.ts.map +1 -1
  162. package/dist/types/components/form/Textarea/TextareaRichEditor.d.ts +7 -0
  163. package/dist/types/components/form/Textarea/TextareaRichEditor.d.ts.map +1 -1
  164. package/dist/types/components/form/UploadButton/UploadButton.d.ts.map +1 -1
  165. package/dist/types/components/form/UploadButton/UploadButton.parts.d.ts +6 -3
  166. package/dist/types/components/form/UploadButton/UploadButton.parts.d.ts.map +1 -1
  167. package/dist/types/components/form/UploadButton/UploadButton.types.d.ts +7 -0
  168. package/dist/types/components/form/UploadButton/UploadButton.types.d.ts.map +1 -1
  169. package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts +1 -1
  170. package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts.map +1 -1
  171. package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts +12 -0
  172. package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts.map +1 -1
  173. package/dist/types/components/layout/ContentToolbar/MultiSelectDropdown.d.ts +1 -1
  174. package/dist/types/components/layout/ContentToolbar/MultiSelectDropdown.d.ts.map +1 -1
  175. package/dist/types/components/layout/ContentToolbar/SortByDropdown.d.ts +1 -1
  176. package/dist/types/components/layout/ContentToolbar/SortByDropdown.d.ts.map +1 -1
  177. package/dist/types/components/layout/ContentToolbar/ViewSelector.d.ts +1 -1
  178. package/dist/types/components/layout/ContentToolbar/ViewSelector.d.ts.map +1 -1
  179. package/dist/types/components/layout/Dashboard/Dashboard.d.ts +1 -1
  180. package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts +4 -0
  181. package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts.map +1 -1
  182. package/dist/types/components/layout/Dashboard/DashboardParts.d.ts +1 -1
  183. package/dist/types/components/layout/Dashboard/DashboardParts.d.ts.map +1 -1
  184. package/dist/types/components/layout/ScrollArea/ScrollArea.d.ts.map +1 -1
  185. package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts +21 -3
  186. package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts.map +1 -1
  187. package/dist/types/components/layout/ScrollArea/ScrollViewport.d.ts +2 -0
  188. package/dist/types/components/layout/ScrollArea/ScrollViewport.d.ts.map +1 -1
  189. package/dist/types/components/layout/TableFilter/TableFilter.d.ts +1 -1
  190. package/dist/types/components/layout/TableFilter/TableFilter.d.ts.map +1 -1
  191. package/dist/types/components/layout/TableFilter/TableFilter.types.d.ts +7 -0
  192. package/dist/types/components/layout/TableFilter/TableFilter.types.d.ts.map +1 -1
  193. package/dist/types/components/layout/TableFilter/TableFilterContext.d.ts +9 -0
  194. package/dist/types/components/layout/TableFilter/TableFilterContext.d.ts.map +1 -1
  195. package/dist/types/components/navigation/Breadcrumbs/BreadcrumbEntry.d.ts +2 -0
  196. package/dist/types/components/navigation/Breadcrumbs/BreadcrumbEntry.d.ts.map +1 -1
  197. package/dist/types/components/navigation/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
  198. package/dist/types/components/navigation/Breadcrumbs/Breadcrumbs.types.d.ts +3 -0
  199. package/dist/types/components/navigation/Breadcrumbs/Breadcrumbs.types.d.ts.map +1 -1
  200. package/dist/types/components/navigation/CommandPalette/CommandPalette.d.ts.map +1 -1
  201. package/dist/types/components/navigation/CommandPalette/CommandPalette.types.d.ts +3 -0
  202. package/dist/types/components/navigation/CommandPalette/CommandPalette.types.d.ts.map +1 -1
  203. package/dist/types/components/navigation/CommandPalette/CommandPaletteResults.d.ts +2 -0
  204. package/dist/types/components/navigation/CommandPalette/CommandPaletteResults.d.ts.map +1 -1
  205. package/dist/types/components/navigation/Pagination/Pagination.d.ts.map +1 -1
  206. package/dist/types/components/navigation/Pagination/Pagination.types.d.ts +2 -0
  207. package/dist/types/components/navigation/Pagination/Pagination.types.d.ts.map +1 -1
  208. package/dist/types/components/navigation/Pagination/PaginationParts.d.ts +2 -0
  209. package/dist/types/components/navigation/Pagination/PaginationParts.d.ts.map +1 -1
  210. package/dist/types/components/navigation/Tabs/Tabs.d.ts.map +1 -1
  211. package/dist/types/components/navigation/Tabs/Tabs.types.d.ts +2 -0
  212. package/dist/types/components/navigation/Tabs/Tabs.types.d.ts.map +1 -1
  213. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
  214. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts +6 -2
  215. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts.map +1 -1
  216. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts +6 -0
  217. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts.map +1 -1
  218. package/dist/types/components/utility/InstallPrompt/InstallPrompt.d.ts +4 -2
  219. package/dist/types/components/utility/InstallPrompt/InstallPrompt.d.ts.map +1 -1
  220. package/dist/types/components/utility/InstallPrompt/InstallPrompt.types.d.ts +8 -7
  221. package/dist/types/components/utility/InstallPrompt/InstallPrompt.types.d.ts.map +1 -1
  222. package/dist/types/copy/data-display.d.ts +56 -0
  223. package/dist/types/copy/data-display.d.ts.map +1 -0
  224. package/dist/types/copy/feedback.d.ts +38 -0
  225. package/dist/types/copy/feedback.d.ts.map +1 -0
  226. package/dist/types/copy/form.d.ts +146 -0
  227. package/dist/types/copy/form.d.ts.map +1 -0
  228. package/dist/types/copy/layout.d.ts +18 -0
  229. package/dist/types/copy/layout.d.ts.map +1 -0
  230. package/dist/types/copy/navigation.d.ts +24 -0
  231. package/dist/types/copy/navigation.d.ts.map +1 -0
  232. package/dist/types/copy/shared.d.ts +119 -0
  233. package/dist/types/copy/shared.d.ts.map +1 -0
  234. package/dist/types/copy/utility.d.ts +35 -0
  235. package/dist/types/copy/utility.d.ts.map +1 -0
  236. package/dist/types/copy.d.ts +12 -165
  237. package/dist/types/copy.d.ts.map +1 -1
  238. package/dist/types/en-US.d.ts +24 -0
  239. package/dist/types/en-US.d.ts.map +1 -0
  240. package/dist/types/en-US.data-display.d.ts +13 -0
  241. package/dist/types/en-US.data-display.d.ts.map +1 -0
  242. package/dist/types/en-US.feedback.d.ts +8 -0
  243. package/dist/types/en-US.feedback.d.ts.map +1 -0
  244. package/dist/types/en-US.form.d.ts +13 -0
  245. package/dist/types/en-US.form.d.ts.map +1 -0
  246. package/dist/types/en-US.layout.d.ts +7 -0
  247. package/dist/types/en-US.layout.d.ts.map +1 -0
  248. package/dist/types/en-US.navigation.d.ts +8 -0
  249. package/dist/types/en-US.navigation.d.ts.map +1 -0
  250. package/dist/types/en-US.shared.d.ts +26 -0
  251. package/dist/types/en-US.shared.d.ts.map +1 -0
  252. package/dist/types/en-US.utility.d.ts +8 -0
  253. package/dist/types/en-US.utility.d.ts.map +1 -0
  254. package/dist/types/locales.d.ts +53 -0
  255. package/dist/types/locales.d.ts.map +1 -0
  256. package/dist/types/pt-BR.d.ts +15 -22
  257. package/dist/types/pt-BR.d.ts.map +1 -1
  258. package/dist/types/pt-BR.data-display.d.ts +13 -0
  259. package/dist/types/pt-BR.data-display.d.ts.map +1 -0
  260. package/dist/types/pt-BR.feedback.d.ts +8 -0
  261. package/dist/types/pt-BR.feedback.d.ts.map +1 -0
  262. package/dist/types/pt-BR.form.d.ts +13 -0
  263. package/dist/types/pt-BR.form.d.ts.map +1 -0
  264. package/dist/types/pt-BR.layout.d.ts +7 -0
  265. package/dist/types/pt-BR.layout.d.ts.map +1 -0
  266. package/dist/types/pt-BR.navigation.d.ts +8 -0
  267. package/dist/types/pt-BR.navigation.d.ts.map +1 -0
  268. package/dist/types/pt-BR.shared.d.ts +21 -0
  269. package/dist/types/pt-BR.shared.d.ts.map +1 -0
  270. package/dist/types/pt-BR.utility.d.ts +8 -0
  271. package/dist/types/pt-BR.utility.d.ts.map +1 -0
  272. package/dist/types/user-avatar/user-avatar.d.ts +7 -1
  273. package/dist/types/user-avatar/user-avatar.d.ts.map +1 -1
  274. package/dist/user-avatar.js +2 -2
  275. package/dist/user-avatar.js.map +1 -1
  276. package/dist/utility/InfiniteScroll.js +7 -5
  277. package/dist/utility/InfiniteScroll.js.map +1 -1
  278. package/dist/utility/InstallPrompt.js +14 -13
  279. package/dist/utility/InstallPrompt.js.map +1 -1
  280. package/package.json +10 -1
  281. package/src/components/data-display/DataGrid/DataGrid.states.tsx +3 -3
  282. package/src/components/data-display/DataGrid/DataGrid.tsx +1 -1
  283. package/src/components/data-display/DataGrid/DataGrid.types.ts +5 -0
  284. package/src/components/data-display/DataViews/data-views-category-pill.tsx +2 -0
  285. package/src/components/data-display/DataViews/data-views-copy.ts +27 -1
  286. package/src/components/data-display/DataViews/data-views-day-input.tsx +14 -3
  287. package/src/components/data-display/DataViews/data-views-filter-panel.tsx +2 -1
  288. package/src/components/data-display/DataViews/data-views-grid-bodies.tsx +3 -0
  289. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +9 -10
  290. package/src/components/data-display/DataViews/data-views-more-fields.tsx +3 -1
  291. package/src/components/data-display/DataViews/data-views-pagination.tsx +3 -0
  292. package/src/components/data-display/DataViews/data-views-range-pill.tsx +3 -1
  293. package/src/components/data-display/DataViews/data-views-toolbar.tsx +2 -0
  294. package/src/components/data-display/HoverCard/HoverCard.content.tsx +10 -2
  295. package/src/components/data-display/HoverCard/HoverCard.tsx +2 -3
  296. package/src/components/data-display/HoverCard/HoverCard.types.ts +2 -0
  297. package/src/components/data-display/Table/Table.tsx +7 -2
  298. package/src/components/data-display/Table/Table.types.ts +5 -0
  299. package/src/components/data-display/Table/TableStates.tsx +2 -2
  300. package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +3 -2
  301. package/src/components/data-display/TimingDiagram/TimingDiagram.types.ts +3 -0
  302. package/src/components/feedback/Sonner/Sonner.tsx +15 -3
  303. package/src/components/feedback/Sonner/Sonner.types.ts +2 -0
  304. package/src/components/feedback/Sonner/SonnerToast.tsx +2 -1
  305. package/src/components/feedback/StackedModal/StackedModal.parts.tsx +10 -3
  306. package/src/components/feedback/StackedModal/StackedModal.tsx +2 -1
  307. package/src/components/feedback/StackedModal/StackedModal.types.ts +2 -0
  308. package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +13 -1
  309. package/src/components/feedback/TutorialOverlay/TutorialOverlay.types.ts +3 -0
  310. package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +10 -4
  311. package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +7 -0
  312. package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +2 -0
  313. package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +4 -2
  314. package/src/components/form/AddressAutocomplete/AddressInputField.tsx +13 -6
  315. package/src/components/form/Autocomplete/Autocomplete.parts.tsx +9 -6
  316. package/src/components/form/Autocomplete/Autocomplete.tsx +2 -1
  317. package/src/components/form/Autocomplete/Autocomplete.types.ts +7 -0
  318. package/src/components/form/Calendar/Calendar.tsx +2 -2
  319. package/src/components/form/Calendar/Calendar.types.ts +7 -0
  320. package/src/components/form/CodeEditor/CodeEditor.tsx +6 -4
  321. package/src/components/form/CodeEditor/CodeEditor.types.ts +7 -0
  322. package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +12 -5
  323. package/src/components/form/DateRangePicker/DateRangePicker.range.ts +2 -0
  324. package/src/components/form/DateRangePicker/DateRangePicker.tsx +4 -0
  325. package/src/components/form/DateRangePicker/DateRangePicker.types.ts +11 -0
  326. package/src/components/form/DateRangePicker/DateRangePickerFields.tsx +2 -0
  327. package/src/components/form/Menubar/Menubar.toolbar.tsx +3 -1
  328. package/src/components/form/Menubar/Menubar.tsx +2 -1
  329. package/src/components/form/Menubar/Menubar.types.ts +5 -0
  330. package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +33 -17
  331. package/src/components/form/PasswordStrength/PasswordStrength.tsx +29 -13
  332. package/src/components/form/PasswordStrength/PasswordStrength.types.ts +9 -0
  333. package/src/components/form/PhoneInput/PhoneInput.tsx +15 -5
  334. package/src/components/form/PhoneInput/PhoneInput.types.ts +7 -0
  335. package/src/components/form/SearchPalette/SearchPalette.parts.tsx +4 -1
  336. package/src/components/form/SearchPalette/SearchPalette.tsx +4 -1
  337. package/src/components/form/SearchPalette/SearchPalette.types.ts +6 -0
  338. package/src/components/form/Textarea/Textarea.tsx +6 -1
  339. package/src/components/form/Textarea/Textarea.types.ts +14 -1
  340. package/src/components/form/Textarea/TextareaRichEditor.tsx +28 -18
  341. package/src/components/form/UploadButton/UploadButton.parts.tsx +16 -7
  342. package/src/components/form/UploadButton/UploadButton.tsx +4 -1
  343. package/src/components/form/UploadButton/UploadButton.types.ts +8 -0
  344. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +10 -2
  345. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +12 -0
  346. package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +15 -4
  347. package/src/components/layout/ContentToolbar/SortByDropdown.tsx +12 -3
  348. package/src/components/layout/ContentToolbar/ViewSelector.tsx +2 -1
  349. package/src/components/layout/Dashboard/Dashboard.types.ts +4 -0
  350. package/src/components/layout/Dashboard/DashboardParts.tsx +2 -1
  351. package/src/components/layout/ScrollArea/ScrollArea.tsx +16 -3
  352. package/src/components/layout/ScrollArea/ScrollArea.types.ts +19 -4
  353. package/src/components/layout/ScrollArea/ScrollViewport.tsx +4 -1
  354. package/src/components/layout/TableFilter/TableFilter.tsx +19 -11
  355. package/src/components/layout/TableFilter/TableFilter.types.ts +8 -0
  356. package/src/components/layout/TableFilter/TableFilterContext.tsx +10 -0
  357. package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +11 -4
  358. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +2 -0
  359. package/src/components/navigation/Breadcrumbs/Breadcrumbs.types.ts +3 -0
  360. package/src/components/navigation/CommandPalette/CommandPalette.tsx +15 -5
  361. package/src/components/navigation/CommandPalette/CommandPalette.types.ts +3 -0
  362. package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +5 -2
  363. package/src/components/navigation/Pagination/Pagination.tsx +2 -0
  364. package/src/components/navigation/Pagination/Pagination.types.ts +2 -0
  365. package/src/components/navigation/Pagination/PaginationParts.tsx +4 -1
  366. package/src/components/navigation/Tabs/Tabs.tsx +8 -3
  367. package/src/components/navigation/Tabs/Tabs.types.ts +2 -0
  368. package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +4 -4
  369. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +4 -2
  370. package/src/components/utility/InfiniteScroll/InfiniteScroll.types.ts +6 -0
  371. package/src/components/utility/InstallPrompt/InstallPrompt.tsx +18 -13
  372. package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +9 -7
  373. package/src/copy/data-display.ts +60 -0
  374. package/src/copy/feedback.ts +39 -0
  375. package/src/copy/form.ts +154 -0
  376. package/src/copy/layout.ts +18 -0
  377. package/src/copy/navigation.ts +25 -0
  378. package/src/copy/shared.ts +122 -0
  379. package/src/copy/utility.ts +36 -0
  380. package/src/copy.ts +12 -173
  381. package/src/en-US.data-display.ts +244 -0
  382. package/src/en-US.feedback.ts +25 -0
  383. package/src/en-US.form.ts +103 -0
  384. package/src/en-US.layout.ts +15 -0
  385. package/src/en-US.navigation.ts +23 -0
  386. package/src/en-US.shared.ts +105 -0
  387. package/src/en-US.ts +24 -0
  388. package/src/en-US.utility.ts +24 -0
  389. package/src/locales.ts +151 -0
  390. package/src/pt-BR.data-display.ts +236 -0
  391. package/src/pt-BR.feedback.ts +25 -0
  392. package/src/pt-BR.form.ts +96 -0
  393. package/src/pt-BR.layout.ts +15 -0
  394. package/src/pt-BR.navigation.ts +21 -0
  395. package/src/pt-BR.shared.ts +94 -0
  396. package/src/pt-BR.ts +15 -307
  397. package/src/pt-BR.utility.ts +21 -0
  398. package/src/user-avatar/user-avatar.tsx +8 -2
  399. package/dist/chunk-CEKPLUQV.js.map +0 -1
  400. package/dist/chunk-DFVRZ3UK.js.map +0 -1
  401. package/dist/chunk-H7UAGTVW.js.map +0 -1
  402. package/dist/chunk-JP55QWVR.js.map +0 -1
  403. package/dist/chunk-NUCLEOHF.js.map +0 -1
  404. package/dist/chunk-QLBYAYUG.js.map +0 -1
  405. package/dist/chunk-QZZVHY6U.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/form/PasswordStrength/PasswordStrength.tsx","../../src/components/form/PasswordStrength/PasswordStrength.helpers.tsx"],"sourcesContent":["import CheckIcon from '@mui/icons-material/Check';\nimport CloseIcon from '@mui/icons-material/Close';\n\nimport {\n alpha,\n Box,\n Chip,\n Fade,\n keyframes,\n LinearProgress,\n Stack,\n styled,\n Typography,\n useTheme } from '@mui/material';\nimport type { FC} from 'react';\nimport React, { useMemo } from 'react';\n\nimport type { RequirementChecks } from './PasswordStrength.helpers';\nimport {\n buildSuggestions,\n calculatePasswordStrength,\n defaultRequirements,\n evaluateRequirements,\n getStrengthIcon,\n getStrengthLabel,\n SuggestionsList } from './PasswordStrength.helpers';\nimport type { PasswordRequirements, PasswordStrengthProps } from './PasswordStrength.types';\n\ninterface RequirementIconProps {\n met: boolean;\n}\n const RequirementIcon: FC<RequirementIconProps> = ({ met }) => {\n return met ? (\n <CheckIcon data-testid=\"check-icon\" />\n ) : (\n <CloseIcon data-testid=\"close-icon\" />\n );\n};\n\n// Default requirements\n// Animation keyframes\nconst pulseAnimation = keyframes`\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.7;\n }\n`;\n\nconst slideInAnimation = keyframes`\n from {\n transform: translateX(-10px);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n`;\n\n// Styled components\nconst StrengthContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'animated' })<{ animated?: boolean }>(({ theme, animated }) => ({\n width: '100%',\n padding: theme.spacing(2),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.8)} 0%, ${alpha(theme.palette.background.paper, 0.6)} 100%)`,\n backdropFilter: 'blur(10px)',\n WebkitBackdropFilter: 'blur(10px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n borderRadius: theme.shape.borderRadius * 2,\n transition: animated ? 'all 0.3s ease' : 'none' }));\n\nconst StrengthBar = styled(LinearProgress, {\n shouldForwardProp: (prop) => prop !== 'strength' && prop !== 'animated' })<{ strength: number; animated?: boolean }>(({ theme, strength, animated }) => {\n const getColor = () => {\n if (strength <= 20) return theme.palette.error.main;\n if (strength <= 40) return theme.palette.warning.main;\n if (strength <= 60) return theme.palette.info.main;\n if (strength <= 80) return theme.palette.success.light;\n return theme.palette.success.main;\n };\n\n const getGradient = () => {\n const color = getColor();\n return `linear-gradient(90deg, ${color} 0%, ${alpha(color, 0.8)} 100%)`;\n };\n\n return {\n height: 8,\n borderRadius: 4,\n backgroundColor: alpha(theme.palette.action.disabled, 0.1),\n '& .MuiLinearProgress-bar': {\n borderRadius: 4,\n background: getGradient(),\n transition: animated ? 'all 0.3s ease' : 'none',\n boxShadow: `0 2px 8px ${alpha(getColor(), 0.3)}` } };\n});\n\nconst RequirementItem = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'met' && prop !== 'animated' })<{ met: boolean; animated?: boolean }>(({ theme, met, animated }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n padding: theme.spacing(0.75, 1),\n borderRadius: theme.shape.borderRadius,\n background: met\n ? alpha(theme.palette.success.main, 0.08)\n : alpha(theme.palette.action.disabled, 0.04),\n transition: animated ? 'all 0.3s ease' : 'none',\n animation: animated ? `${slideInAnimation} 0.3s ease` : 'none',\n '& svg': {\n fontSize: '1rem',\n color: met ? theme.palette.success.main : theme.palette.text.disabled } }));\n\nconst StrengthLabel = styled(Chip, {\n shouldForwardProp: (prop) => prop !== 'strength' && prop !== 'animated' })<{ strength: number; animated?: boolean }>(({ theme, strength, animated }) => {\n const getColor = () => {\n if (strength <= 20) return theme.palette.error;\n if (strength <= 40) return theme.palette.warning;\n if (strength <= 60) return theme.palette.info;\n if (strength <= 80) return theme.palette.success;\n return theme.palette.success;\n };\n\n const palette = getColor();\n\n return {\n background: alpha(palette.main, 0.1),\n color: palette.main,\n border: `1px solid ${alpha(palette.main, 0.3)}`,\n fontWeight: 600,\n animation: animated ? `${pulseAnimation} 2s ease infinite` : 'none' };\n});\n\nconst StepsContainer = styled(Box)(({ theme }) => ({\n display: 'flex',\n gap: theme.spacing(1),\n marginTop: theme.spacing(2) }));\n\nconst Step = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'active' && prop !== 'completed' && prop !== 'animated' })<{ active: boolean; completed: boolean; animated?: boolean }>(\n ({ theme, active, completed, animated }) => ({\n flex: 1,\n height: 6,\n borderRadius: 3,\n background: completed\n ? `linear-gradient(90deg, ${theme.palette.success.main} 0%, ${theme.palette.success.light} 100%)`\n : active\n ? `linear-gradient(90deg, ${theme.palette.warning.main} 0%, ${theme.palette.warning.light} 100%)`\n : alpha(theme.palette.action.disabled, 0.2),\n transition: animated ? 'all 0.3s ease' : 'none',\n boxShadow: completed ? `0 2px 8px ${alpha(theme.palette.success.main, 0.3)}` : 'none' }),\n);\n\n// The three indicator variants, out of the component body so the render keeps\n// only its own layout branches.\nconst StrengthIndicator: React.FC<{\n variant: PasswordStrengthProps['variant'];\n strength: number;\n animated: boolean;\n}> = ({ variant, strength, animated }) => {\n const theme = useTheme();\n\n switch (variant) {\n case 'circular':\n return (\n <Box sx={{ position: 'relative', display: 'inline-flex' }}>\n <Box\n sx={{\n width: 80,\n height: 80,\n borderRadius: '50%',\n background: `conic-gradient(\n ${theme.palette.success.main} 0deg ${strength * 3.6}deg,\n ${alpha(theme.palette.action.disabled, 0.1)} ${strength * 3.6}deg 360deg\n )`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: `0 4px 12px ${alpha(theme.palette.success.main, strength / 200)}` }}\n >\n <Box\n sx={{\n width: 64,\n height: 64,\n borderRadius: '50%',\n background: theme.palette.background.paper,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'column' }}\n >\n <Typography variant=\"h6\" fontWeight=\"bold\">\n {strength}%\n </Typography>\n </Box>\n </Box>\n </Box>\n );\n\n case 'steps': {\n const steps = 5;\n const activeStep = Math.ceil((strength / 100) * steps);\n return (\n <StepsContainer>\n {Array.from({ length: steps }, (_, i) => (\n <Step key={i} active={i === activeStep - 1} completed={i < activeStep - 1} animated={animated} />\n ))}\n </StepsContainer>\n );\n }\n\n default:\n return <StrengthBar variant=\"determinate\" value={strength} strength={strength} animated={animated} />;\n }\n};\n\nconst StrengthHeading: React.FC<{\n strength: number;\n hasValue: boolean;\n animated: boolean;\n}> = ({ strength, hasValue, animated }) => (\n <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n Password Strength\n </Typography>\n {hasValue && (\n <Fade in={true}>\n <StrengthLabel\n label={getStrengthLabel(strength)}\n icon={getStrengthIcon(strength)}\n size=\"small\"\n strength={strength}\n animated={animated}\n />\n </Fade>\n )}\n </Box>\n);\n\n// One row per enabled requirement. Previously five near-identical JSX blocks,\n// each with its own `requirements.x &&` guard.\nconst RequirementsList: React.FC<{\n requirements: PasswordRequirements;\n checks: RequirementChecks;\n animated: boolean;\n}> = ({ requirements, checks, animated }) => {\n const rows: ReadonlyArray<[unknown, keyof RequirementChecks, React.ReactNode]> = [\n [requirements.minLength, 'length', `At least ${requirements.minLength} characters`],\n [requirements.uppercase, 'uppercase', 'One uppercase letter'],\n [requirements.lowercase, 'lowercase', 'One lowercase letter'],\n [requirements.numbers, 'numbers', 'One number'],\n [requirements.special, 'special', 'One special character'],\n ];\n\n return (\n <Stack spacing={1}>\n <Typography variant=\"caption\" color=\"text.secondary\" fontWeight=\"medium\">\n Requirements:\n </Typography>\n {rows\n .filter(([enabled]) => Boolean(enabled))\n .map(([, key, label]) => (\n <RequirementItem key={key} met={checks[key]} animated={animated}>\n <RequirementIcon met={checks[key]} />\n <Typography variant=\"caption\">{label}</Typography>\n </RequirementItem>\n ))}\n </Stack>\n );\n};\n\n// The visible sections. Kept apart from PasswordStrength itself so the exported\n// component is just prop defaults plus the three memos, and every display guard\n// lives in one place.\nconst PasswordStrengthBody: React.FC<{\n value: string;\n strength: number;\n requirements: PasswordRequirements;\n requirementChecks: RequirementChecks;\n suggestions: string[];\n showStrengthLabel: boolean;\n showRequirements: boolean;\n showSuggestions: boolean;\n variant: PasswordStrengthProps['variant'];\n animated: boolean;\n}> = ({\n value,\n strength,\n requirements,\n requirementChecks,\n suggestions,\n showStrengthLabel,\n showRequirements,\n showSuggestions,\n variant,\n animated }) => (\n <Stack spacing={2}>\n {showStrengthLabel && (\n <StrengthHeading strength={strength} hasValue={value.length > 0} animated={animated} />\n )}\n\n <StrengthIndicator variant={variant} strength={strength} animated={animated} />\n\n {showRequirements && (\n <Fade in={value.length > 0}>\n <RequirementsList\n requirements={requirements}\n checks={requirementChecks}\n animated={animated}\n />\n </Fade>\n )}\n\n {showSuggestions && suggestions.length > 0 && value.length > 0 && (\n <Fade in={true}>\n <SuggestionsList suggestions={suggestions} />\n </Fade>\n )}\n </Stack>\n);\n\n// Main component\nexport const PasswordStrength: FC<PasswordStrengthProps> = ({\n value = '',\n showRequirements = true,\n requirements = defaultRequirements,\n showStrengthLabel = true,\n showSuggestions = false,\n variant = 'linear',\n animated = true,\n 'data-testid': dataTestId }) => {\n\n const strength = useMemo(\n () => calculatePasswordStrength(value, requirements),\n [value, requirements],\n );\n\n const requirementChecks = useMemo(\n () => evaluateRequirements(value, requirements),\n [value, requirements],\n );\n\n const suggestions = useMemo(() => buildSuggestions(requirementChecks), [requirementChecks]);\n\n return (\n <StrengthContainer animated={animated} data-testid={dataTestId}>\n <PasswordStrengthBody\n value={value}\n strength={strength}\n requirements={requirements}\n requirementChecks={requirementChecks}\n suggestions={suggestions}\n showStrengthLabel={showStrengthLabel}\n showRequirements={showRequirements}\n showSuggestions={showSuggestions}\n variant={variant}\n animated={animated}\n />\n </StrengthContainer>\n );\n};\n\n// Export default\nexport default PasswordStrength;\n","import SecurityIcon from '@mui/icons-material/Security';\nimport SuccessIcon from '@mui/icons-material/CheckCircle';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport { Box, Typography } from '@mui/material';\nimport React from 'react';\n\nimport type { PasswordRequirements } from './PasswordStrength.types';\n\nexport const defaultRequirements: PasswordRequirements = {\n minLength: 8,\n uppercase: true,\n lowercase: true,\n numbers: true,\n special: true,\n};\n\n\nconst SPECIAL_CHARACTERS = /[!@#$%^&*(),.?\":{}|<>]/;\nconst DEFAULT_MIN_LENGTH = 8;\n\n// Points awarded per satisfied requirement.\nconst REQUIREMENT_POINTS = {\n length: 20,\n uppercase: 10,\n lowercase: 10,\n numbers: 15,\n special: 15,\n} as const;\n\nexport type RequirementChecks = Record<keyof typeof REQUIREMENT_POINTS, boolean>;\n\n// A requirement that is switched off counts as satisfied. This was previously\n// written out twice — once to score the password and once to render the\n// checklist — so the two could drift.\nexport const evaluateRequirements = (\n password: string,\n requirements: PasswordRequirements,\n): RequirementChecks => {\n if (!password) {\n return { length: false, uppercase: false, lowercase: false, numbers: false, special: false };\n }\n\n return {\n length: password.length >= (requirements.minLength || DEFAULT_MIN_LENGTH),\n uppercase: !requirements.uppercase || /[A-Z]/.test(password),\n lowercase: !requirements.lowercase || /[a-z]/.test(password),\n numbers: !requirements.numbers || /\\d/.test(password),\n special: !requirements.special || SPECIAL_CHARACTERS.test(password),\n };\n};\n\nconst lengthBonus = (length: number): number => {\n const base = Math.min(length * 3, 30);\n const over12 = length > 12 ? 10 : 0;\n const over16 = length > 16 ? 10 : 0;\n\n return base + over12 + over16;\n};\n\nexport const calculatePasswordStrength = (\n password: string,\n requirements: PasswordRequirements,\n): number => {\n if (!password) return 0;\n\n const checks = evaluateRequirements(password, requirements);\n const earned = Object.entries(REQUIREMENT_POINTS).reduce(\n (total, [key, points]) => total + (checks[key as keyof RequirementChecks] ? points : 0),\n 0,\n );\n\n return Math.min(earned + lengthBonus(password.length), 100);\n};\n\nconst STRENGTH_LABELS: ReadonlyArray<[number, string]> = [\n [20, 'Very Weak'],\n [40, 'Weak'],\n [60, 'Fair'],\n [80, 'Good'],\n];\n\nexport const getStrengthLabel = (strength: number): string =>\n STRENGTH_LABELS.find(([ceiling]) => strength <= ceiling)?.[1] ?? 'Strong';\n\nexport const getStrengthIcon = (strength: number) => {\n if (strength <= 40) return <WarningIcon />;\n if (strength <= 80) return <SecurityIcon />;\n return <SuccessIcon />;\n};\n\nconst SUGGESTIONS: ReadonlyArray<[keyof RequirementChecks, string]> = [\n ['length', 'Use at least 8 characters'],\n ['uppercase', 'Add uppercase letters'],\n ['lowercase', 'Add lowercase letters'],\n ['numbers', 'Include numbers'],\n ['special', 'Add special characters'],\n];\n\nexport const buildSuggestions = (checks: RequirementChecks): string[] =>\n SUGGESTIONS.filter(([key]) => !checks[key]).map(([, tip]) => tip);\n\n// Rendered by PasswordStrength; depends on nothing styled, so it lives beside\n// the pure helpers rather than in the component file.\nexport const SuggestionsList: React.FC<{ suggestions: string[] }> = ({ suggestions }) => (\n <Box>\n <Typography variant=\"caption\" color=\"text.secondary\" fontWeight=\"medium\">\n Suggestions:\n </Typography>\n <Box sx={{ mt: 1 }}>\n {suggestions.map((tip) => (\n <Typography key={tip} variant=\"caption\" display=\"block\" color=\"warning.main\" sx={{ ml: 2 }}>\n • {tip}\n </Typography>\n ))}\n </Box>\n </Box>\n);\n"],"mappings":"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","names":["Box","Typography","jsx","jsxs","Box","Typography"]}
1
+ {"version":3,"sources":["../../src/components/form/PasswordStrength/PasswordStrength.tsx","../../src/components/form/PasswordStrength/PasswordStrength.helpers.tsx"],"sourcesContent":["import CheckIcon from '@mui/icons-material/Check';\nimport CloseIcon from '@mui/icons-material/Close';\n\nimport {\n alpha,\n Box,\n Chip,\n Fade,\n keyframes,\n LinearProgress,\n Stack,\n styled,\n Typography,\n useTheme } from '@mui/material';\nimport type { FC} from 'react';\nimport React, { useMemo } from 'react';\n\nimport type { RequirementChecks } from './PasswordStrength.helpers';\nimport {\n buildSuggestions,\n calculatePasswordStrength,\n defaultRequirements,\n evaluateRequirements,\n getStrengthIcon,\n getStrengthLabel,\n SuggestionsList } from './PasswordStrength.helpers';\nimport type { PasswordRequirements, PasswordStrengthProps } from './PasswordStrength.types';\nimport type { PasswordStrengthCopy } from '../../../copy';\n\ninterface RequirementIconProps {\n met: boolean;\n}\n const RequirementIcon: FC<RequirementIconProps> = ({ met }) => {\n return met ? (\n <CheckIcon data-testid=\"check-icon\" />\n ) : (\n <CloseIcon data-testid=\"close-icon\" />\n );\n};\n\n// Default requirements\n// Animation keyframes\nconst pulseAnimation = keyframes`\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.7;\n }\n`;\n\nconst slideInAnimation = keyframes`\n from {\n transform: translateX(-10px);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n`;\n\n// Styled components\nconst StrengthContainer = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'animated' })<{ animated?: boolean }>(({ theme, animated }) => ({\n width: '100%',\n padding: theme.spacing(2),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.8)} 0%, ${alpha(theme.palette.background.paper, 0.6)} 100%)`,\n backdropFilter: 'blur(10px)',\n WebkitBackdropFilter: 'blur(10px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n borderRadius: theme.shape.borderRadius * 2,\n transition: animated ? 'all 0.3s ease' : 'none' }));\n\nconst StrengthBar = styled(LinearProgress, {\n shouldForwardProp: (prop) => prop !== 'strength' && prop !== 'animated' })<{ strength: number; animated?: boolean }>(({ theme, strength, animated }) => {\n const getColor = () => {\n if (strength <= 20) return theme.palette.error.main;\n if (strength <= 40) return theme.palette.warning.main;\n if (strength <= 60) return theme.palette.info.main;\n if (strength <= 80) return theme.palette.success.light;\n return theme.palette.success.main;\n };\n\n const getGradient = () => {\n const color = getColor();\n return `linear-gradient(90deg, ${color} 0%, ${alpha(color, 0.8)} 100%)`;\n };\n\n return {\n height: 8,\n borderRadius: 4,\n backgroundColor: alpha(theme.palette.action.disabled, 0.1),\n '& .MuiLinearProgress-bar': {\n borderRadius: 4,\n background: getGradient(),\n transition: animated ? 'all 0.3s ease' : 'none',\n boxShadow: `0 2px 8px ${alpha(getColor(), 0.3)}` } };\n});\n\nconst RequirementItem = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'met' && prop !== 'animated' })<{ met: boolean; animated?: boolean }>(({ theme, met, animated }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n padding: theme.spacing(0.75, 1),\n borderRadius: theme.shape.borderRadius,\n background: met\n ? alpha(theme.palette.success.main, 0.08)\n : alpha(theme.palette.action.disabled, 0.04),\n transition: animated ? 'all 0.3s ease' : 'none',\n animation: animated ? `${slideInAnimation} 0.3s ease` : 'none',\n '& svg': {\n fontSize: '1rem',\n color: met ? theme.palette.success.main : theme.palette.text.disabled } }));\n\nconst StrengthLabel = styled(Chip, {\n shouldForwardProp: (prop) => prop !== 'strength' && prop !== 'animated' })<{ strength: number; animated?: boolean }>(({ theme, strength, animated }) => {\n const getColor = () => {\n if (strength <= 20) return theme.palette.error;\n if (strength <= 40) return theme.palette.warning;\n if (strength <= 60) return theme.palette.info;\n if (strength <= 80) return theme.palette.success;\n return theme.palette.success;\n };\n\n const palette = getColor();\n\n return {\n background: alpha(palette.main, 0.1),\n color: palette.main,\n border: `1px solid ${alpha(palette.main, 0.3)}`,\n fontWeight: 600,\n animation: animated ? `${pulseAnimation} 2s ease infinite` : 'none' };\n});\n\nconst StepsContainer = styled(Box)(({ theme }) => ({\n display: 'flex',\n gap: theme.spacing(1),\n marginTop: theme.spacing(2) }));\n\nconst Step = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'active' && prop !== 'completed' && prop !== 'animated' })<{ active: boolean; completed: boolean; animated?: boolean }>(\n ({ theme, active, completed, animated }) => ({\n flex: 1,\n height: 6,\n borderRadius: 3,\n background: completed\n ? `linear-gradient(90deg, ${theme.palette.success.main} 0%, ${theme.palette.success.light} 100%)`\n : active\n ? `linear-gradient(90deg, ${theme.palette.warning.main} 0%, ${theme.palette.warning.light} 100%)`\n : alpha(theme.palette.action.disabled, 0.2),\n transition: animated ? 'all 0.3s ease' : 'none',\n boxShadow: completed ? `0 2px 8px ${alpha(theme.palette.success.main, 0.3)}` : 'none' }),\n);\n\n// The three indicator variants, out of the component body so the render keeps\n// only its own layout branches.\nconst StrengthIndicator: React.FC<{\n variant: PasswordStrengthProps['variant'];\n strength: number;\n animated: boolean;\n}> = ({ variant, strength, animated }) => {\n const theme = useTheme();\n\n switch (variant) {\n case 'circular':\n return (\n <Box sx={{ position: 'relative', display: 'inline-flex' }}>\n <Box\n sx={{\n width: 80,\n height: 80,\n borderRadius: '50%',\n background: `conic-gradient(\n ${theme.palette.success.main} 0deg ${strength * 3.6}deg,\n ${alpha(theme.palette.action.disabled, 0.1)} ${strength * 3.6}deg 360deg\n )`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: `0 4px 12px ${alpha(theme.palette.success.main, strength / 200)}` }}\n >\n <Box\n sx={{\n width: 64,\n height: 64,\n borderRadius: '50%',\n background: theme.palette.background.paper,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'column' }}\n >\n <Typography variant=\"h6\" fontWeight=\"bold\">\n {strength}%\n </Typography>\n </Box>\n </Box>\n </Box>\n );\n\n case 'steps': {\n const steps = 5;\n const activeStep = Math.ceil((strength / 100) * steps);\n return (\n <StepsContainer>\n {Array.from({ length: steps }, (_, i) => (\n <Step key={i} active={i === activeStep - 1} completed={i < activeStep - 1} animated={animated} />\n ))}\n </StepsContainer>\n );\n }\n\n default:\n return <StrengthBar variant=\"determinate\" value={strength} strength={strength} animated={animated} />;\n }\n};\n\nconst StrengthHeading: React.FC<{\n copy: PasswordStrengthCopy;\n strength: number;\n hasValue: boolean;\n animated: boolean;\n}> = ({ copy, strength, hasValue, animated }) => (\n <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {copy.strengthHeading}\n </Typography>\n {hasValue && (\n <Fade in={true}>\n <StrengthLabel\n label={getStrengthLabel(strength, copy.bands)}\n icon={getStrengthIcon(strength)}\n size=\"small\"\n strength={strength}\n animated={animated}\n />\n </Fade>\n )}\n </Box>\n);\n\n// One row per enabled requirement. Previously five near-identical JSX blocks,\n// each with its own `requirements.x &&` guard.\nconst RequirementsList: React.FC<{\n copy: PasswordStrengthCopy;\n requirements: PasswordRequirements;\n checks: RequirementChecks;\n animated: boolean;\n}> = ({ copy, requirements, checks, animated }) => {\n const rows: ReadonlyArray<[unknown, keyof RequirementChecks, React.ReactNode]> = [\n [requirements.minLength, 'length', copy.requirements.minLength(requirements.minLength ?? 0)],\n [requirements.uppercase, 'uppercase', copy.requirements.uppercase],\n [requirements.lowercase, 'lowercase', copy.requirements.lowercase],\n [requirements.numbers, 'numbers', copy.requirements.numbers],\n [requirements.special, 'special', copy.requirements.special],\n ];\n\n return (\n <Stack spacing={1}>\n <Typography variant=\"caption\" color=\"text.secondary\" fontWeight=\"medium\">\n {copy.requirementsHeading}\n </Typography>\n {rows\n .filter(([enabled]) => Boolean(enabled))\n .map(([, key, label]) => (\n <RequirementItem key={key} met={checks[key]} animated={animated}>\n <RequirementIcon met={checks[key]} />\n <Typography variant=\"caption\">{label}</Typography>\n </RequirementItem>\n ))}\n </Stack>\n );\n};\n\n// The visible sections. Kept apart from PasswordStrength itself so the exported\n// component is just prop defaults plus the three memos, and every display guard\n// lives in one place.\nconst PasswordStrengthBody: React.FC<{\n value: string;\n strength: number;\n copy: PasswordStrengthCopy;\n requirements: PasswordRequirements;\n requirementChecks: RequirementChecks;\n suggestions: string[];\n showStrengthLabel: boolean;\n showRequirements: boolean;\n showSuggestions: boolean;\n variant: PasswordStrengthProps['variant'];\n animated: boolean;\n}> = ({\n copy,\n value,\n strength,\n requirements,\n requirementChecks,\n suggestions,\n showStrengthLabel,\n showRequirements,\n showSuggestions,\n variant,\n animated }) => (\n <Stack spacing={2}>\n {showStrengthLabel && (\n <StrengthHeading\n copy={copy}\n strength={strength}\n hasValue={value.length > 0}\n animated={animated}\n />\n )}\n\n <StrengthIndicator variant={variant} strength={strength} animated={animated} />\n\n {showRequirements && (\n <Fade in={value.length > 0}>\n <RequirementsList\n copy={copy}\n requirements={requirements}\n checks={requirementChecks}\n animated={animated}\n />\n </Fade>\n )}\n\n {showSuggestions && suggestions.length > 0 && value.length > 0 && (\n <Fade in={true}>\n <SuggestionsList suggestions={suggestions} heading={copy.suggestionsHeading} />\n </Fade>\n )}\n </Stack>\n);\n\n// Main component\nexport const PasswordStrength: FC<PasswordStrengthProps> = ({\n copy,\n value = '',\n showRequirements = true,\n requirements = defaultRequirements,\n showStrengthLabel = true,\n showSuggestions = false,\n variant = 'linear',\n animated = true,\n 'data-testid': dataTestId }) => {\n\n const strength = useMemo(\n () => calculatePasswordStrength(value, requirements),\n [value, requirements],\n );\n\n const requirementChecks = useMemo(\n () => evaluateRequirements(value, requirements),\n [value, requirements],\n );\n\n const suggestions = useMemo(\n () => buildSuggestions(requirementChecks, copy.suggestions, requirements.minLength ?? 0),\n [requirementChecks, copy.suggestions, requirements.minLength],\n );\n\n return (\n <StrengthContainer animated={animated} data-testid={dataTestId}>\n <PasswordStrengthBody\n copy={copy}\n value={value}\n strength={strength}\n requirements={requirements}\n requirementChecks={requirementChecks}\n suggestions={suggestions}\n showStrengthLabel={showStrengthLabel}\n showRequirements={showRequirements}\n showSuggestions={showSuggestions}\n variant={variant}\n animated={animated}\n />\n </StrengthContainer>\n );\n};\n\n// Export default\nexport default PasswordStrength;\n","import SecurityIcon from '@mui/icons-material/Security';\nimport SuccessIcon from '@mui/icons-material/CheckCircle';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport { Box, Typography } from '@mui/material';\nimport React from 'react';\n\nimport type { PasswordRequirementCopy, PasswordStrengthCopy } from '../../../copy';\nimport type { PasswordRequirements } from './PasswordStrength.types';\n\nexport const defaultRequirements: PasswordRequirements = {\n minLength: 8,\n uppercase: true,\n lowercase: true,\n numbers: true,\n special: true,\n};\n\n\nconst SPECIAL_CHARACTERS = /[!@#$%^&*(),.?\":{}|<>]/;\nconst DEFAULT_MIN_LENGTH = 8;\n\n// Points awarded per satisfied requirement.\nconst REQUIREMENT_POINTS = {\n length: 20,\n uppercase: 10,\n lowercase: 10,\n numbers: 15,\n special: 15,\n} as const;\n\nexport type RequirementChecks = Record<keyof typeof REQUIREMENT_POINTS, boolean>;\n\n// A requirement that is switched off counts as satisfied. This was previously\n// written out twice — once to score the password and once to render the\n// checklist — so the two could drift.\nexport const evaluateRequirements = (\n password: string,\n requirements: PasswordRequirements,\n): RequirementChecks => {\n if (!password) {\n return { length: false, uppercase: false, lowercase: false, numbers: false, special: false };\n }\n\n return {\n length: password.length >= (requirements.minLength || DEFAULT_MIN_LENGTH),\n uppercase: !requirements.uppercase || /[A-Z]/.test(password),\n lowercase: !requirements.lowercase || /[a-z]/.test(password),\n numbers: !requirements.numbers || /\\d/.test(password),\n special: !requirements.special || SPECIAL_CHARACTERS.test(password),\n };\n};\n\nconst lengthBonus = (length: number): number => {\n const base = Math.min(length * 3, 30);\n const over12 = length > 12 ? 10 : 0;\n const over16 = length > 16 ? 10 : 0;\n\n return base + over12 + over16;\n};\n\nexport const calculatePasswordStrength = (\n password: string,\n requirements: PasswordRequirements,\n): number => {\n if (!password) return 0;\n\n const checks = evaluateRequirements(password, requirements);\n const earned = Object.entries(REQUIREMENT_POINTS).reduce(\n (total, [key, points]) => total + (checks[key as keyof RequirementChecks] ? points : 0),\n 0,\n );\n\n return Math.min(earned + lengthBonus(password.length), 100);\n};\n\n// The four ceilings, and which band each one names. The band NAMES come from\n// the host's table — only the thresholds are ours.\nconst STRENGTH_BANDS: ReadonlyArray<[number, keyof PasswordStrengthCopy['bands']]> = [\n [20, 'veryWeak'],\n [40, 'weak'],\n [60, 'fair'],\n [80, 'good'],\n];\n\nexport const getStrengthLabel = (\n strength: number,\n bands: PasswordStrengthCopy['bands'],\n): string => bands[STRENGTH_BANDS.find(([ceiling]) => strength <= ceiling)?.[1] ?? 'strong'];\n\nexport const getStrengthIcon = (strength: number) => {\n if (strength <= 40) return <WarningIcon />;\n if (strength <= 80) return <SecurityIcon />;\n return <SuccessIcon />;\n};\n\n// One tip per unmet requirement, in checklist order. The `length` tip carries\n// the configured minimum, so the number in the sentence is the one enforced.\nconst SUGGESTION_KEYS: ReadonlyArray<[keyof RequirementChecks, keyof PasswordRequirementCopy]> = [\n ['length', 'minLength'],\n ['uppercase', 'uppercase'],\n ['lowercase', 'lowercase'],\n ['numbers', 'numbers'],\n ['special', 'special'],\n];\n\nexport const buildSuggestions = (\n checks: RequirementChecks,\n copy: PasswordRequirementCopy,\n minLength: number,\n): string[] =>\n SUGGESTION_KEYS.filter(([check]) => !checks[check]).map(([, key]) =>\n key === 'minLength' ? copy.minLength(minLength) : copy[key],\n );\n\n// Rendered by PasswordStrength; depends on nothing styled, so it lives beside\n// the pure helpers rather than in the component file.\nexport const SuggestionsList: React.FC<{ suggestions: string[]; heading: string }> = ({\n suggestions,\n heading,\n}) => (\n <Box>\n <Typography variant=\"caption\" color=\"text.secondary\" fontWeight=\"medium\">\n {heading}\n </Typography>\n <Box sx={{ mt: 1 }}>\n {suggestions.map((tip) => (\n <Typography key={tip} variant=\"caption\" display=\"block\" color=\"warning.main\" sx={{ ml: 2 }}>\n • {tip}\n </Typography>\n ))}\n </Box>\n </Box>\n);\n"],"mappings":"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","names":["Box","Typography","jsx","jsxs","Box","Typography"]}
@@ -246,6 +246,7 @@ var CountryMenu = styled(Menu)(({ theme }) => ({
246
246
  }));
247
247
  var PhoneField = ({
248
248
  TextFieldComponent,
249
+ copy,
249
250
  variant,
250
251
  label,
251
252
  placeholder,
@@ -284,6 +285,7 @@ var PhoneField = ({
284
285
  startAdornment: /* @__PURE__ */ jsx(
285
286
  CountryAdornment,
286
287
  {
288
+ selectCountryLabel: copy.selectCountry,
287
289
  country: selectedCountry,
288
290
  menuOpen: Boolean(anchorEl),
289
291
  onOpen: onCountryOpen,
@@ -315,12 +317,12 @@ var PHONE_INPUT_DEFAULTS = {
315
317
  var definedProps = (props) => Object.fromEntries(
316
318
  Object.entries(props).filter(([, value]) => value !== void 0)
317
319
  );
318
- var CountryAdornment = ({ country, menuOpen, onOpen, onOpenViaKeyboard }) => /* @__PURE__ */ jsx(InputAdornment, { position: "start", "data-testid": "phone-input-start-adornment", children: /* @__PURE__ */ jsxs(
320
+ var CountryAdornment = ({ country, menuOpen, onOpen, onOpenViaKeyboard, selectCountryLabel }) => /* @__PURE__ */ jsx(InputAdornment, { position: "start", "data-testid": "phone-input-start-adornment", children: /* @__PURE__ */ jsxs(
319
321
  CountrySelector,
320
322
  {
321
323
  onClick: onOpen,
322
324
  role: "button",
323
- "aria-label": "Select country",
325
+ "aria-label": selectCountryLabel,
324
326
  "aria-expanded": menuOpen,
325
327
  tabIndex: 0,
326
328
  "data-testid": "country-selector",
@@ -416,15 +418,17 @@ var resolveValidation = ({
416
418
  value,
417
419
  isFocused,
418
420
  helper,
419
- countryName
421
+ countryName,
422
+ copy
420
423
  }) => {
421
424
  const looksInvalid = !isValid && value !== "" && !isFocused;
422
425
  return {
423
426
  hasError: error || looksInvalid,
424
- helperText: errorMessage || (looksInvalid ? `Invalid phone number for ${countryName || "selected country"}` : helper)
427
+ helperText: errorMessage || (looksInvalid ? copy.invalidNumber(countryName || copy.unknownCountry) : helper)
425
428
  };
426
429
  };
427
430
  var PhoneInput = (props) => {
431
+ const { copy } = props;
428
432
  const {
429
433
  variant,
430
434
  label,
@@ -462,13 +466,15 @@ var PhoneInput = (props) => {
462
466
  value,
463
467
  isFocused,
464
468
  helper,
465
- countryName: selectedCountry?.name
469
+ countryName: selectedCountry?.name,
470
+ copy
466
471
  });
467
472
  const TextFieldComponent = variant === "glass" ? GlassTextField : TextField;
468
473
  return /* @__PURE__ */ jsxs(Box, { "data-testid": "phone-input-container", children: [
469
474
  /* @__PURE__ */ jsx(
470
475
  PhoneField,
471
476
  {
477
+ copy,
472
478
  TextFieldComponent,
473
479
  variant,
474
480
  label: floating ? void 0 : label,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/form/PhoneInput/PhoneInput.tsx","../../src/components/form/PhoneInput/countries.ts","../../src/components/form/PhoneInput/PhoneInput.hooks.ts","../../src/components/form/PhoneInput/phone.ts"],"sourcesContent":["import ArrowDropDown from '@mui/icons-material/ArrowDropDown';\nimport PhoneIcon from '@mui/icons-material/Phone';\nimport {\n alpha,\n Box,\n InputAdornment,\n ListItemIcon,\n ListItemText,\n Menu,\n MenuItem,\n styled,\n TextField,\n Typography,\n useTheme } from '@mui/material';\nimport type { FC} from 'react';\nimport React, { } from 'react';\n\nimport { countries } from './countries';\nimport { usePhoneInput } from './PhoneInput.hooks';\nimport type { CountryData,PhoneInputProps } from './PhoneInput.types';\n\n// Country data with expanded support\n\n// Styled components\nconst GlassTextField = styled(TextField)(({ theme }) => ({\n '& .MuiOutlinedInput-root': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.8)} 0%, ${alpha(theme.palette.background.paper, 0.6)} 100%)`,\n backdropFilter: 'blur(10px)',\n WebkitBackdropFilter: 'blur(10px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n transition: theme.transitions.create(['border-color', 'box-shadow', 'background']),\n '&:hover': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.9)} 0%, ${alpha(theme.palette.background.paper, 0.7)} 100%)`,\n borderColor: theme.palette.primary.main },\n '&.Mui-focused': {\n background: theme.palette.background.paper,\n boxShadow: `0 0 0 2px ${alpha(theme.palette.primary.main, 0.25)}` },\n '& fieldset': {\n border: 'none' } },\n '& .MuiInputLabel-root': {\n '&.Mui-focused': {\n color: theme.palette.primary.main } } }));\n\nconst CountrySelector = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n padding: theme.spacing(0.5, 1),\n borderRadius: theme.shape.borderRadius,\n cursor: 'pointer',\n transition: theme.transitions.create(['background-color']),\n '&:hover': {\n backgroundColor: alpha(theme.palette.primary.main, 0.08) } }));\n\nconst CountryMenu = styled(Menu)(({ theme }) => ({\n '& .MuiPaper-root': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.98)} 0%, ${alpha(theme.palette.background.paper, 0.95)} 100%)`,\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n maxHeight: 400 } }));\n\n// Helper functions with enhanced validation\n// The text field itself with its two adornments. Split out so PhoneInput is\n// prop defaults, the hook call and composition.\nconst PhoneField: React.FC<{\n TextFieldComponent: React.ElementType;\n variant: PhoneInputProps['variant'];\n label?: React.ReactNode;\n placeholder?: string;\n value: string;\n validation: { hasError: boolean; helperText?: React.ReactNode };\n disabled: boolean;\n required: boolean;\n fullWidth: boolean;\n icon?: React.ReactNode;\n isValid: boolean;\n selectedCountry?: CountryData;\n anchorEl: HTMLElement | null;\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onCountryOpen: (event: React.MouseEvent<HTMLElement>) => void;\n onCountryOpenViaKeyboard: (element: HTMLElement) => void;\n}> = ({\n TextFieldComponent,\n variant,\n label,\n placeholder,\n value,\n validation,\n disabled,\n required,\n fullWidth,\n icon,\n isValid,\n selectedCountry,\n anchorEl,\n onChange,\n onFocus,\n onBlur,\n onCountryOpen,\n onCountryOpenViaKeyboard }) => (\n <TextFieldComponent\n variant={variant === 'glass' ? 'outlined' : variant}\n label={label}\n placeholder={placeholder}\n value={value}\n onChange={onChange}\n onFocus={onFocus}\n onBlur={onBlur}\n error={validation.hasError}\n helperText={validation.helperText}\n disabled={disabled}\n required={required}\n fullWidth={fullWidth}\n type=\"tel\"\n data-testid=\"phone-input-field\"\n InputProps={{\n startAdornment: (\n <CountryAdornment\n country={selectedCountry}\n menuOpen={Boolean(anchorEl)}\n onOpen={onCountryOpen}\n onOpenViaKeyboard={onCountryOpenViaKeyboard}\n />\n ),\n endAdornment: <ValidityAdornment icon={icon} isValid={isValid} /> }}\n sx={{\n '& input': {\n letterSpacing: '0.5px' } }}\n />\n);\n\nconst PHONE_INPUT_DEFAULTS = {\n variant: 'outlined',\n label: 'Phone Number',\n placeholder: 'Enter phone number',\n icon: <PhoneIcon />,\n defaultValue: '',\n countryCode: 'US',\n floating: false,\n error: false,\n disabled: false,\n required: false,\n fullWidth: true } satisfies Partial<PhoneInputProps>;\n\n// Drops explicitly-undefined props before the merge, so `prop={undefined}` falls\n// back to the default exactly as a destructuring default would. Eleven separate\n// destructuring defaults were most of this component's branch count.\nconst definedProps = (props: PhoneInputProps): Partial<PhoneInputProps> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<PhoneInputProps>;\n\nconst CountryAdornment: React.FC<{\n country?: CountryData;\n menuOpen: boolean;\n onOpen: (event: React.MouseEvent<HTMLElement>) => void;\n onOpenViaKeyboard: (element: HTMLElement) => void;\n}> = ({ country, menuOpen, onOpen, onOpenViaKeyboard }) => (\n <InputAdornment position=\"start\" data-testid=\"phone-input-start-adornment\">\n <CountrySelector\n onClick={onOpen}\n role=\"button\"\n aria-label=\"Select country\"\n aria-expanded={menuOpen}\n tabIndex={0}\n data-testid=\"country-selector\"\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return;\n e.preventDefault();\n onOpenViaKeyboard(e.currentTarget as HTMLElement);\n }}\n >\n <Typography variant=\"h6\" component=\"span\" sx={{ mr: 0.5 }} data-testid=\"country-flag\">\n {country?.flag}\n </Typography>\n <Typography\n variant=\"body2\"\n color=\"text.secondary\"\n sx={{ mr: 0.5 }}\n data-testid=\"country-dial-code\"\n >\n {country?.dial}\n </Typography>\n <ArrowDropDown fontSize=\"small\" data-testid=\"country-dropdown-icon\" />\n </CountrySelector>\n </InputAdornment>\n);\n\n// The trailing icon turns green once the number validates.\nconst ValidityAdornment: React.FC<{ icon?: React.ReactNode; isValid: boolean }> = ({\n icon,\n isValid }) => {\n const theme = useTheme();\n\n if (!icon) return null;\n\n return (\n <InputAdornment position=\"end\" data-testid=\"phone-input-end-adornment\">\n <Box\n sx={{\n color: isValid ? theme.palette.success.main : theme.palette.text.secondary,\n transition: 'color 0.3s ease' }}\n data-testid=\"phone-input-icon\"\n >\n {icon}\n </Box>\n </InputAdornment>\n );\n};\n\nconst CountryPicker: React.FC<{\n anchorEl: HTMLElement | null;\n selectedCode?: CountryData['code'];\n onClose: () => void;\n onSelect: (country: CountryData) => void;\n}> = ({ anchorEl, selectedCode, onClose, onSelect }) => {\n const theme = useTheme();\n\n return (\n <CountryMenu\n anchorEl={anchorEl}\n open={Boolean(anchorEl)}\n onClose={onClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left' }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'left' }}\n data-testid=\"country-menu\"\n >\n {countries.map((country) => (\n <MenuItem\n key={country.code}\n onClick={() => onSelect(country)}\n selected={country.code === selectedCode}\n data-testid={`country-option-${country.code}`}\n sx={{\n '&:hover': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.1)} 0%, ${alpha(theme.palette.primary.main, 0.05)} 100%)` } }}\n >\n <ListItemIcon sx={{ minWidth: 36 }}>\n <Typography variant=\"h5\" component=\"span\">\n {country.flag}\n </Typography>\n </ListItemIcon>\n <ListItemText\n primary={country.name}\n secondary={country.dial}\n primaryTypographyProps={{ fontSize: '0.9rem' }}\n secondaryTypographyProps={{ fontSize: '0.8rem' }}\n />\n </MenuItem>\n ))}\n </CountryMenu>\n );\n};\n\n// The field shows an error either because the caller says so, or because what\n// has been typed does not validate and the user has moved on.\nconst resolveValidation = ({\n error,\n errorMessage,\n isValid,\n value,\n isFocused,\n helper,\n countryName }: {\n error: boolean;\n errorMessage?: string;\n isValid: boolean;\n value: string;\n isFocused: boolean;\n helper?: React.ReactNode;\n countryName?: string;\n}) => {\n const looksInvalid = !isValid && value !== '' && !isFocused;\n\n return {\n hasError: error || looksInvalid,\n helperText:\n errorMessage ||\n (looksInvalid ? `Invalid phone number for ${countryName || 'selected country'}` : helper) };\n};\n\nexport const PhoneInput: FC<PhoneInputProps> = (props) => {\n const {\n variant,\n label,\n placeholder,\n icon,\n defaultValue,\n countryCode: initialCountryCode,\n floating,\n onChange,\n helper,\n error,\n errorMessage,\n disabled,\n required,\n fullWidth } = { ...PHONE_INPUT_DEFAULTS, ...definedProps(props) };\n const {\n value,\n selectedCountry,\n anchorEl,\n isValid,\n isFocused,\n setIsFocused,\n setAnchorEl,\n handleCountryClick,\n handleCountryClose,\n handleCountrySelect,\n handleChange,\n handleBlur } = usePhoneInput({ defaultValue, initialCountryCode, onChange });\n\n const validation = resolveValidation({\n error,\n errorMessage,\n isValid,\n value,\n isFocused,\n helper,\n countryName: selectedCountry?.name });\n\n const TextFieldComponent = variant === 'glass' ? GlassTextField : TextField;\n\n return (\n <Box data-testid=\"phone-input-container\">\n <PhoneField\n TextFieldComponent={TextFieldComponent}\n variant={variant}\n label={floating ? undefined : label}\n placeholder={placeholder}\n value={value}\n validation={validation}\n disabled={disabled}\n required={required}\n fullWidth={fullWidth}\n icon={icon}\n isValid={isValid}\n selectedCountry={selectedCountry}\n anchorEl={anchorEl}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={handleBlur}\n onCountryOpen={handleCountryClick}\n onCountryOpenViaKeyboard={setAnchorEl}\n />\n\n <CountryPicker\n anchorEl={anchorEl}\n selectedCode={selectedCountry?.code}\n onClose={handleCountryClose}\n onSelect={handleCountrySelect}\n />\n </Box>\n );\n};\n\n// Export default\nexport default PhoneInput;\n","import type { CountryCode } from 'libphonenumber-js';\n\nimport type { CountryData } from './PhoneInput.types';\n\n// Dial codes and flags for the countries the input offers, sorted by name.\nexport const countries: CountryData[] = [\n { code: 'US' as CountryCode, name: 'United States', dial: '+1', flag: '🇺🇸' },\n { code: 'GB' as CountryCode, name: 'United Kingdom', dial: '+44', flag: '🇬🇧' },\n { code: 'CA' as CountryCode, name: 'Canada', dial: '+1', flag: '🇨🇦' },\n { code: 'AU' as CountryCode, name: 'Australia', dial: '+61', flag: '🇦🇺' },\n { code: 'DE' as CountryCode, name: 'Germany', dial: '+49', flag: '🇩🇪' },\n { code: 'FR' as CountryCode, name: 'France', dial: '+33', flag: '🇫🇷' },\n { code: 'IT' as CountryCode, name: 'Italy', dial: '+39', flag: '🇮🇹' },\n { code: 'ES' as CountryCode, name: 'Spain', dial: '+34', flag: '🇪🇸' },\n { code: 'NL' as CountryCode, name: 'Netherlands', dial: '+31', flag: '🇳🇱' },\n { code: 'JP' as CountryCode, name: 'Japan', dial: '+81', flag: '🇯🇵' },\n { code: 'CN' as CountryCode, name: 'China', dial: '+86', flag: '🇨🇳' },\n { code: 'IN' as CountryCode, name: 'India', dial: '+91', flag: '🇮🇳' },\n { code: 'BR' as CountryCode, name: 'Brazil', dial: '+55', flag: '🇧🇷' },\n { code: 'MX' as CountryCode, name: 'Mexico', dial: '+52', flag: '🇲🇽' },\n { code: 'KR' as CountryCode, name: 'South Korea', dial: '+82', flag: '🇰🇷' },\n { code: 'SE' as CountryCode, name: 'Sweden', dial: '+46', flag: '🇸🇪' },\n { code: 'NO' as CountryCode, name: 'Norway', dial: '+47', flag: '🇳🇴' },\n { code: 'DK' as CountryCode, name: 'Denmark', dial: '+45', flag: '🇩🇰' },\n { code: 'CH' as CountryCode, name: 'Switzerland', dial: '+41', flag: '🇨🇭' },\n { code: 'AT' as CountryCode, name: 'Austria', dial: '+43', flag: '🇦🇹' },\n { code: 'BE' as CountryCode, name: 'Belgium', dial: '+32', flag: '🇧🇪' },\n { code: 'FI' as CountryCode, name: 'Finland', dial: '+358', flag: '🇫🇮' },\n { code: 'IE' as CountryCode, name: 'Ireland', dial: '+353', flag: '🇮🇪' },\n { code: 'PT' as CountryCode, name: 'Portugal', dial: '+351', flag: '🇵🇹' },\n { code: 'GR' as CountryCode, name: 'Greece', dial: '+30', flag: '🇬🇷' },\n { code: 'PL' as CountryCode, name: 'Poland', dial: '+48', flag: '🇵🇱' },\n { code: 'CZ' as CountryCode, name: 'Czech Republic', dial: '+420', flag: '🇨🇿' },\n { code: 'HU' as CountryCode, name: 'Hungary', dial: '+36', flag: '🇭🇺' },\n { code: 'RU' as CountryCode, name: 'Russia', dial: '+7', flag: '🇷🇺' },\n { code: 'ZA' as CountryCode, name: 'South Africa', dial: '+27', flag: '🇿🇦' },\n { code: 'EG' as CountryCode, name: 'Egypt', dial: '+20', flag: '🇪🇬' },\n { code: 'NG' as CountryCode, name: 'Nigeria', dial: '+234', flag: '🇳🇬' },\n { code: 'KE' as CountryCode, name: 'Kenya', dial: '+254', flag: '🇰🇪' },\n { code: 'AR' as CountryCode, name: 'Argentina', dial: '+54', flag: '🇦🇷' },\n { code: 'CL' as CountryCode, name: 'Chile', dial: '+56', flag: '🇨🇱' },\n { code: 'CO' as CountryCode, name: 'Colombia', dial: '+57', flag: '🇨🇴' },\n { code: 'PE' as CountryCode, name: 'Peru', dial: '+51', flag: '🇵🇪' },\n { code: 'MY' as CountryCode, name: 'Malaysia', dial: '+60', flag: '🇲🇾' },\n { code: 'SG' as CountryCode, name: 'Singapore', dial: '+65', flag: '🇸🇬' },\n { code: 'TH' as CountryCode, name: 'Thailand', dial: '+66', flag: '🇹🇭' },\n { code: 'VN' as CountryCode, name: 'Vietnam', dial: '+84', flag: '🇻🇳' },\n { code: 'PH' as CountryCode, name: 'Philippines', dial: '+63', flag: '🇵🇭' },\n { code: 'ID' as CountryCode, name: 'Indonesia', dial: '+62', flag: '🇮🇩' },\n { code: 'TR' as CountryCode, name: 'Turkey', dial: '+90', flag: '🇹🇷' },\n { code: 'IL' as CountryCode, name: 'Israel', dial: '+972', flag: '🇮🇱' },\n { code: 'AE' as CountryCode, name: 'United Arab Emirates', dial: '+971', flag: '🇦🇪' },\n { code: 'SA' as CountryCode, name: 'Saudi Arabia', dial: '+966', flag: '🇸🇦' },\n].sort((a, b) => a.name.localeCompare(b.name));\n","import type { CountryCode } from 'libphonenumber-js';\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { countries } from './countries';\nimport { detectCountryFromNumber, formatPhoneNumber, validatePhoneNumber } from './phone';\nimport type { CountryData } from './PhoneInput.types';\n\n// Value, selected country, menu anchor and validity, plus the handlers that move\n// between them. Kept out of the component so its body is markup.\nexport const usePhoneInput = ({\n defaultValue,\n initialCountryCode,\n onChange,\n}: {\n defaultValue: string;\n initialCountryCode: CountryCode;\n onChange?: (value: string, isValid: boolean, country: CountryCode) => void;\n}) => {\nconst [value, setValue] = useState(defaultValue);\nconst [selectedCountry, setSelectedCountry] = useState(\n countries.find((c) => c.code === initialCountryCode) || countries[0],\n);\nconst [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\nconst [isValid, setIsValid] = useState(false);\nconst [isFocused, setIsFocused] = useState(false);\nconst onChangeRef = useRef(onChange);\nconst isInitialMountRef = useRef(true);\n\n// Update ref when onChange changes\nuseEffect(() => {\n onChangeRef.current = onChange;\n}, [onChange]);\n\nuseEffect(() => {\n if (!selectedCountry) return;\n\n const valid = validatePhoneNumber(value, selectedCountry.code);\n setIsValid(valid);\n\n // Skip onChange call on initial mount\n if (isInitialMountRef.current) {\n isInitialMountRef.current = false;\n return;\n }\n\n // Call onChange for all value/country changes after initial mount\n if (onChangeRef.current) {\n onChangeRef.current(value, valid, selectedCountry.code);\n }\n}, [value, selectedCountry]);\n\n const handlers = usePhoneHandlers({\n value,\n setValue,\n selectedCountry,\n setSelectedCountry,\n setAnchorEl,\n setIsFocused,\n });\n\n return {\n value,\n selectedCountry,\n anchorEl,\n isValid,\n isFocused,\n setIsFocused,\n setAnchorEl,\n ...handlers,\n };\n};\n\n// Opening and closing the country menu, picking a country, typing, and\n// reformatting on blur.\nconst usePhoneHandlers = ({\n value,\n setValue,\n selectedCountry,\n setSelectedCountry,\n setAnchorEl,\n setIsFocused,\n}: {\n value: string;\n setValue: React.Dispatch<React.SetStateAction<string>>;\n selectedCountry?: CountryData;\n setSelectedCountry: React.Dispatch<React.SetStateAction<CountryData | undefined>>;\n setAnchorEl: React.Dispatch<React.SetStateAction<null | HTMLElement>>;\n setIsFocused: React.Dispatch<React.SetStateAction<boolean>>;\n}) => {\n const handleCountryClick = (event: React.MouseEvent<HTMLElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleCountryClose = () => {\n setAnchorEl(null);\n };\n\n const handleCountrySelect = (country: CountryData) => {\n setSelectedCountry(country);\n handleCountryClose();\n\n // Reformat number with new country code\n if (value) {\n const formatted = formatPhoneNumber(value, country.code);\n setValue(formatted);\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = event.target.value;\n setValue(newValue);\n\n // Auto-detect country if user types international format\n if (newValue.startsWith('+')) {\n const detectedCountry = detectCountryFromNumber(newValue);\n if (detectedCountry) {\n const detectedCountryData = countries.find((c) => c.code === detectedCountry);\n if (detectedCountryData && detectedCountryData.code !== selectedCountry?.code) {\n setSelectedCountry(detectedCountryData);\n }\n }\n }\n };\n\n const handleBlur = () => {\n setIsFocused(false);\n if (value && selectedCountry) {\n const formatted = formatPhoneNumber(value, selectedCountry.code);\n setValue(formatted);\n }\n };\n\n return { handleCountryClick, handleCountryClose, handleCountrySelect, handleChange, handleBlur };\n};\n","import type { CountryCode } from 'libphonenumber-js';\nimport { parsePhoneNumber } from 'libphonenumber-js';\n\n\nexport const formatPhoneNumber = (value: string, country: CountryCode): string => {\n if (!value || value.trim() === '') return value;\n\n try {\n const phoneNumber = parsePhoneNumber(value, country);\n // Format if we have a phone number object, regardless of strict validity\n // This allows formatting of test numbers (like 555 prefix) and partially valid numbers\n if (phoneNumber) {\n return phoneNumber.formatInternational();\n }\n } catch {\n // Silently handle formatting errors\n }\n return value;\n};\n\nexport const validatePhoneNumber = (value: string, country: CountryCode): boolean => {\n if (!value || value.trim() === '') return false;\n\n try {\n const phoneNumber = parsePhoneNumber(value, country);\n // Consider a number valid if it can be parsed and has the right format\n // This allows test numbers (like 555 prefix) which isPossible but not isValid\n return phoneNumber ? phoneNumber.isPossible() : false;\n } catch {\n // Silently handle validation errors\n return false;\n }\n};\n\n// Enhanced helper to detect country from number\nexport const detectCountryFromNumber = (value: string): CountryCode | undefined => {\n if (!value || !value.startsWith('+')) return undefined;\n\n try {\n const phoneNumber = parsePhoneNumber(value);\n return phoneNumber?.country;\n } catch {\n return undefined;\n }\n};\n\n// Main component\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/form/PhoneInput/PhoneInput.tsx","../../src/components/form/PhoneInput/countries.ts","../../src/components/form/PhoneInput/PhoneInput.hooks.ts","../../src/components/form/PhoneInput/phone.ts"],"sourcesContent":["import ArrowDropDown from '@mui/icons-material/ArrowDropDown';\nimport PhoneIcon from '@mui/icons-material/Phone';\nimport {\n alpha,\n Box,\n InputAdornment,\n ListItemIcon,\n ListItemText,\n Menu,\n MenuItem,\n styled,\n TextField,\n Typography,\n useTheme } from '@mui/material';\nimport type { FC} from 'react';\nimport React, { } from 'react';\n\nimport { countries } from './countries';\nimport { usePhoneInput } from './PhoneInput.hooks';\nimport type { CountryData,PhoneInputProps } from './PhoneInput.types';\nimport type { PhoneInputCopy } from '../../../copy';\n\n// Country data with expanded support\n\n// Styled components\nconst GlassTextField = styled(TextField)(({ theme }) => ({\n '& .MuiOutlinedInput-root': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.8)} 0%, ${alpha(theme.palette.background.paper, 0.6)} 100%)`,\n backdropFilter: 'blur(10px)',\n WebkitBackdropFilter: 'blur(10px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n transition: theme.transitions.create(['border-color', 'box-shadow', 'background']),\n '&:hover': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.9)} 0%, ${alpha(theme.palette.background.paper, 0.7)} 100%)`,\n borderColor: theme.palette.primary.main },\n '&.Mui-focused': {\n background: theme.palette.background.paper,\n boxShadow: `0 0 0 2px ${alpha(theme.palette.primary.main, 0.25)}` },\n '& fieldset': {\n border: 'none' } },\n '& .MuiInputLabel-root': {\n '&.Mui-focused': {\n color: theme.palette.primary.main } } }));\n\nconst CountrySelector = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n padding: theme.spacing(0.5, 1),\n borderRadius: theme.shape.borderRadius,\n cursor: 'pointer',\n transition: theme.transitions.create(['background-color']),\n '&:hover': {\n backgroundColor: alpha(theme.palette.primary.main, 0.08) } }));\n\nconst CountryMenu = styled(Menu)(({ theme }) => ({\n '& .MuiPaper-root': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.98)} 0%, ${alpha(theme.palette.background.paper, 0.95)} 100%)`,\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n maxHeight: 400 } }));\n\n// Helper functions with enhanced validation\n// The text field itself with its two adornments. Split out so PhoneInput is\n// prop defaults, the hook call and composition.\nconst PhoneField: React.FC<{\n TextFieldComponent: React.ElementType;\n variant: PhoneInputProps['variant'];\n label?: React.ReactNode;\n placeholder?: string;\n value: string;\n validation: { hasError: boolean; helperText?: React.ReactNode };\n disabled: boolean;\n required: boolean;\n fullWidth: boolean;\n icon?: React.ReactNode;\n isValid: boolean;\n selectedCountry?: CountryData;\n anchorEl: HTMLElement | null;\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onCountryOpen: (event: React.MouseEvent<HTMLElement>) => void;\n onCountryOpenViaKeyboard: (element: HTMLElement) => void;\n copy: PhoneInputCopy;\n}> = ({\n TextFieldComponent,\n copy,\n variant,\n label,\n placeholder,\n value,\n validation,\n disabled,\n required,\n fullWidth,\n icon,\n isValid,\n selectedCountry,\n anchorEl,\n onChange,\n onFocus,\n onBlur,\n onCountryOpen,\n onCountryOpenViaKeyboard }) => (\n <TextFieldComponent\n variant={variant === 'glass' ? 'outlined' : variant}\n label={label}\n placeholder={placeholder}\n value={value}\n onChange={onChange}\n onFocus={onFocus}\n onBlur={onBlur}\n error={validation.hasError}\n helperText={validation.helperText}\n disabled={disabled}\n required={required}\n fullWidth={fullWidth}\n type=\"tel\"\n data-testid=\"phone-input-field\"\n InputProps={{\n startAdornment: (\n <CountryAdornment\n selectCountryLabel={copy.selectCountry}\n country={selectedCountry}\n menuOpen={Boolean(anchorEl)}\n onOpen={onCountryOpen}\n onOpenViaKeyboard={onCountryOpenViaKeyboard}\n />\n ),\n endAdornment: <ValidityAdornment icon={icon} isValid={isValid} /> }}\n sx={{\n '& input': {\n letterSpacing: '0.5px' } }}\n />\n);\n\nconst PHONE_INPUT_DEFAULTS = {\n variant: 'outlined',\n label: 'Phone Number',\n placeholder: 'Enter phone number',\n icon: <PhoneIcon />,\n defaultValue: '',\n countryCode: 'US',\n floating: false,\n error: false,\n disabled: false,\n required: false,\n fullWidth: true } satisfies Partial<PhoneInputProps>;\n\n// Drops explicitly-undefined props before the merge, so `prop={undefined}` falls\n// back to the default exactly as a destructuring default would. Eleven separate\n// destructuring defaults were most of this component's branch count.\nconst definedProps = (props: PhoneInputProps): Partial<PhoneInputProps> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<PhoneInputProps>;\n\nconst CountryAdornment: React.FC<{\n country?: CountryData;\n menuOpen: boolean;\n onOpen: (event: React.MouseEvent<HTMLElement>) => void;\n onOpenViaKeyboard: (element: HTMLElement) => void;\n selectCountryLabel: string;\n}> = ({ country, menuOpen, onOpen, onOpenViaKeyboard, selectCountryLabel }) => (\n <InputAdornment position=\"start\" data-testid=\"phone-input-start-adornment\">\n <CountrySelector\n onClick={onOpen}\n role=\"button\"\n aria-label={selectCountryLabel}\n aria-expanded={menuOpen}\n tabIndex={0}\n data-testid=\"country-selector\"\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return;\n e.preventDefault();\n onOpenViaKeyboard(e.currentTarget as HTMLElement);\n }}\n >\n <Typography variant=\"h6\" component=\"span\" sx={{ mr: 0.5 }} data-testid=\"country-flag\">\n {country?.flag}\n </Typography>\n <Typography\n variant=\"body2\"\n color=\"text.secondary\"\n sx={{ mr: 0.5 }}\n data-testid=\"country-dial-code\"\n >\n {country?.dial}\n </Typography>\n <ArrowDropDown fontSize=\"small\" data-testid=\"country-dropdown-icon\" />\n </CountrySelector>\n </InputAdornment>\n);\n\n// The trailing icon turns green once the number validates.\nconst ValidityAdornment: React.FC<{ icon?: React.ReactNode; isValid: boolean }> = ({\n icon,\n isValid }) => {\n const theme = useTheme();\n\n if (!icon) return null;\n\n return (\n <InputAdornment position=\"end\" data-testid=\"phone-input-end-adornment\">\n <Box\n sx={{\n color: isValid ? theme.palette.success.main : theme.palette.text.secondary,\n transition: 'color 0.3s ease' }}\n data-testid=\"phone-input-icon\"\n >\n {icon}\n </Box>\n </InputAdornment>\n );\n};\n\nconst CountryPicker: React.FC<{\n anchorEl: HTMLElement | null;\n selectedCode?: CountryData['code'];\n onClose: () => void;\n onSelect: (country: CountryData) => void;\n}> = ({ anchorEl, selectedCode, onClose, onSelect }) => {\n const theme = useTheme();\n\n return (\n <CountryMenu\n anchorEl={anchorEl}\n open={Boolean(anchorEl)}\n onClose={onClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left' }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'left' }}\n data-testid=\"country-menu\"\n >\n {countries.map((country) => (\n <MenuItem\n key={country.code}\n onClick={() => onSelect(country)}\n selected={country.code === selectedCode}\n data-testid={`country-option-${country.code}`}\n sx={{\n '&:hover': {\n background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.1)} 0%, ${alpha(theme.palette.primary.main, 0.05)} 100%)` } }}\n >\n <ListItemIcon sx={{ minWidth: 36 }}>\n <Typography variant=\"h5\" component=\"span\">\n {country.flag}\n </Typography>\n </ListItemIcon>\n <ListItemText\n primary={country.name}\n secondary={country.dial}\n primaryTypographyProps={{ fontSize: '0.9rem' }}\n secondaryTypographyProps={{ fontSize: '0.8rem' }}\n />\n </MenuItem>\n ))}\n </CountryMenu>\n );\n};\n\n// The field shows an error either because the caller says so, or because what\n// has been typed does not validate and the user has moved on.\nconst resolveValidation = ({\n error,\n errorMessage,\n isValid,\n value,\n isFocused,\n helper,\n countryName,\n copy }: {\n error: boolean;\n errorMessage?: string;\n isValid: boolean;\n value: string;\n isFocused: boolean;\n helper?: React.ReactNode;\n countryName?: string;\n copy: PhoneInputCopy;\n}) => {\n const looksInvalid = !isValid && value !== '' && !isFocused;\n\n return {\n hasError: error || looksInvalid,\n helperText:\n errorMessage ||\n (looksInvalid ? copy.invalidNumber(countryName || copy.unknownCountry) : helper) };\n};\n\nexport const PhoneInput: FC<PhoneInputProps> = (props) => {\n const { copy } = props;\n const {\n variant,\n label,\n placeholder,\n icon,\n defaultValue,\n countryCode: initialCountryCode,\n floating,\n onChange,\n helper,\n error,\n errorMessage,\n disabled,\n required,\n fullWidth } = { ...PHONE_INPUT_DEFAULTS, ...definedProps(props) };\n const {\n value,\n selectedCountry,\n anchorEl,\n isValid,\n isFocused,\n setIsFocused,\n setAnchorEl,\n handleCountryClick,\n handleCountryClose,\n handleCountrySelect,\n handleChange,\n handleBlur } = usePhoneInput({ defaultValue, initialCountryCode, onChange });\n\n const validation = resolveValidation({\n error,\n errorMessage,\n isValid,\n value,\n isFocused,\n helper,\n countryName: selectedCountry?.name,\n copy });\n\n const TextFieldComponent = variant === 'glass' ? GlassTextField : TextField;\n\n return (\n <Box data-testid=\"phone-input-container\">\n <PhoneField\n copy={copy}\n TextFieldComponent={TextFieldComponent}\n variant={variant}\n label={floating ? undefined : label}\n placeholder={placeholder}\n value={value}\n validation={validation}\n disabled={disabled}\n required={required}\n fullWidth={fullWidth}\n icon={icon}\n isValid={isValid}\n selectedCountry={selectedCountry}\n anchorEl={anchorEl}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={handleBlur}\n onCountryOpen={handleCountryClick}\n onCountryOpenViaKeyboard={setAnchorEl}\n />\n\n <CountryPicker\n anchorEl={anchorEl}\n selectedCode={selectedCountry?.code}\n onClose={handleCountryClose}\n onSelect={handleCountrySelect}\n />\n </Box>\n );\n};\n\n// Export default\nexport default PhoneInput;\n","import type { CountryCode } from 'libphonenumber-js';\n\nimport type { CountryData } from './PhoneInput.types';\n\n// Dial codes and flags for the countries the input offers, sorted by name.\nexport const countries: CountryData[] = [\n { code: 'US' as CountryCode, name: 'United States', dial: '+1', flag: '🇺🇸' },\n { code: 'GB' as CountryCode, name: 'United Kingdom', dial: '+44', flag: '🇬🇧' },\n { code: 'CA' as CountryCode, name: 'Canada', dial: '+1', flag: '🇨🇦' },\n { code: 'AU' as CountryCode, name: 'Australia', dial: '+61', flag: '🇦🇺' },\n { code: 'DE' as CountryCode, name: 'Germany', dial: '+49', flag: '🇩🇪' },\n { code: 'FR' as CountryCode, name: 'France', dial: '+33', flag: '🇫🇷' },\n { code: 'IT' as CountryCode, name: 'Italy', dial: '+39', flag: '🇮🇹' },\n { code: 'ES' as CountryCode, name: 'Spain', dial: '+34', flag: '🇪🇸' },\n { code: 'NL' as CountryCode, name: 'Netherlands', dial: '+31', flag: '🇳🇱' },\n { code: 'JP' as CountryCode, name: 'Japan', dial: '+81', flag: '🇯🇵' },\n { code: 'CN' as CountryCode, name: 'China', dial: '+86', flag: '🇨🇳' },\n { code: 'IN' as CountryCode, name: 'India', dial: '+91', flag: '🇮🇳' },\n { code: 'BR' as CountryCode, name: 'Brazil', dial: '+55', flag: '🇧🇷' },\n { code: 'MX' as CountryCode, name: 'Mexico', dial: '+52', flag: '🇲🇽' },\n { code: 'KR' as CountryCode, name: 'South Korea', dial: '+82', flag: '🇰🇷' },\n { code: 'SE' as CountryCode, name: 'Sweden', dial: '+46', flag: '🇸🇪' },\n { code: 'NO' as CountryCode, name: 'Norway', dial: '+47', flag: '🇳🇴' },\n { code: 'DK' as CountryCode, name: 'Denmark', dial: '+45', flag: '🇩🇰' },\n { code: 'CH' as CountryCode, name: 'Switzerland', dial: '+41', flag: '🇨🇭' },\n { code: 'AT' as CountryCode, name: 'Austria', dial: '+43', flag: '🇦🇹' },\n { code: 'BE' as CountryCode, name: 'Belgium', dial: '+32', flag: '🇧🇪' },\n { code: 'FI' as CountryCode, name: 'Finland', dial: '+358', flag: '🇫🇮' },\n { code: 'IE' as CountryCode, name: 'Ireland', dial: '+353', flag: '🇮🇪' },\n { code: 'PT' as CountryCode, name: 'Portugal', dial: '+351', flag: '🇵🇹' },\n { code: 'GR' as CountryCode, name: 'Greece', dial: '+30', flag: '🇬🇷' },\n { code: 'PL' as CountryCode, name: 'Poland', dial: '+48', flag: '🇵🇱' },\n { code: 'CZ' as CountryCode, name: 'Czech Republic', dial: '+420', flag: '🇨🇿' },\n { code: 'HU' as CountryCode, name: 'Hungary', dial: '+36', flag: '🇭🇺' },\n { code: 'RU' as CountryCode, name: 'Russia', dial: '+7', flag: '🇷🇺' },\n { code: 'ZA' as CountryCode, name: 'South Africa', dial: '+27', flag: '🇿🇦' },\n { code: 'EG' as CountryCode, name: 'Egypt', dial: '+20', flag: '🇪🇬' },\n { code: 'NG' as CountryCode, name: 'Nigeria', dial: '+234', flag: '🇳🇬' },\n { code: 'KE' as CountryCode, name: 'Kenya', dial: '+254', flag: '🇰🇪' },\n { code: 'AR' as CountryCode, name: 'Argentina', dial: '+54', flag: '🇦🇷' },\n { code: 'CL' as CountryCode, name: 'Chile', dial: '+56', flag: '🇨🇱' },\n { code: 'CO' as CountryCode, name: 'Colombia', dial: '+57', flag: '🇨🇴' },\n { code: 'PE' as CountryCode, name: 'Peru', dial: '+51', flag: '🇵🇪' },\n { code: 'MY' as CountryCode, name: 'Malaysia', dial: '+60', flag: '🇲🇾' },\n { code: 'SG' as CountryCode, name: 'Singapore', dial: '+65', flag: '🇸🇬' },\n { code: 'TH' as CountryCode, name: 'Thailand', dial: '+66', flag: '🇹🇭' },\n { code: 'VN' as CountryCode, name: 'Vietnam', dial: '+84', flag: '🇻🇳' },\n { code: 'PH' as CountryCode, name: 'Philippines', dial: '+63', flag: '🇵🇭' },\n { code: 'ID' as CountryCode, name: 'Indonesia', dial: '+62', flag: '🇮🇩' },\n { code: 'TR' as CountryCode, name: 'Turkey', dial: '+90', flag: '🇹🇷' },\n { code: 'IL' as CountryCode, name: 'Israel', dial: '+972', flag: '🇮🇱' },\n { code: 'AE' as CountryCode, name: 'United Arab Emirates', dial: '+971', flag: '🇦🇪' },\n { code: 'SA' as CountryCode, name: 'Saudi Arabia', dial: '+966', flag: '🇸🇦' },\n].sort((a, b) => a.name.localeCompare(b.name));\n","import type { CountryCode } from 'libphonenumber-js';\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { countries } from './countries';\nimport { detectCountryFromNumber, formatPhoneNumber, validatePhoneNumber } from './phone';\nimport type { CountryData } from './PhoneInput.types';\n\n// Value, selected country, menu anchor and validity, plus the handlers that move\n// between them. Kept out of the component so its body is markup.\nexport const usePhoneInput = ({\n defaultValue,\n initialCountryCode,\n onChange,\n}: {\n defaultValue: string;\n initialCountryCode: CountryCode;\n onChange?: (value: string, isValid: boolean, country: CountryCode) => void;\n}) => {\nconst [value, setValue] = useState(defaultValue);\nconst [selectedCountry, setSelectedCountry] = useState(\n countries.find((c) => c.code === initialCountryCode) || countries[0],\n);\nconst [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\nconst [isValid, setIsValid] = useState(false);\nconst [isFocused, setIsFocused] = useState(false);\nconst onChangeRef = useRef(onChange);\nconst isInitialMountRef = useRef(true);\n\n// Update ref when onChange changes\nuseEffect(() => {\n onChangeRef.current = onChange;\n}, [onChange]);\n\nuseEffect(() => {\n if (!selectedCountry) return;\n\n const valid = validatePhoneNumber(value, selectedCountry.code);\n setIsValid(valid);\n\n // Skip onChange call on initial mount\n if (isInitialMountRef.current) {\n isInitialMountRef.current = false;\n return;\n }\n\n // Call onChange for all value/country changes after initial mount\n if (onChangeRef.current) {\n onChangeRef.current(value, valid, selectedCountry.code);\n }\n}, [value, selectedCountry]);\n\n const handlers = usePhoneHandlers({\n value,\n setValue,\n selectedCountry,\n setSelectedCountry,\n setAnchorEl,\n setIsFocused,\n });\n\n return {\n value,\n selectedCountry,\n anchorEl,\n isValid,\n isFocused,\n setIsFocused,\n setAnchorEl,\n ...handlers,\n };\n};\n\n// Opening and closing the country menu, picking a country, typing, and\n// reformatting on blur.\nconst usePhoneHandlers = ({\n value,\n setValue,\n selectedCountry,\n setSelectedCountry,\n setAnchorEl,\n setIsFocused,\n}: {\n value: string;\n setValue: React.Dispatch<React.SetStateAction<string>>;\n selectedCountry?: CountryData;\n setSelectedCountry: React.Dispatch<React.SetStateAction<CountryData | undefined>>;\n setAnchorEl: React.Dispatch<React.SetStateAction<null | HTMLElement>>;\n setIsFocused: React.Dispatch<React.SetStateAction<boolean>>;\n}) => {\n const handleCountryClick = (event: React.MouseEvent<HTMLElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleCountryClose = () => {\n setAnchorEl(null);\n };\n\n const handleCountrySelect = (country: CountryData) => {\n setSelectedCountry(country);\n handleCountryClose();\n\n // Reformat number with new country code\n if (value) {\n const formatted = formatPhoneNumber(value, country.code);\n setValue(formatted);\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = event.target.value;\n setValue(newValue);\n\n // Auto-detect country if user types international format\n if (newValue.startsWith('+')) {\n const detectedCountry = detectCountryFromNumber(newValue);\n if (detectedCountry) {\n const detectedCountryData = countries.find((c) => c.code === detectedCountry);\n if (detectedCountryData && detectedCountryData.code !== selectedCountry?.code) {\n setSelectedCountry(detectedCountryData);\n }\n }\n }\n };\n\n const handleBlur = () => {\n setIsFocused(false);\n if (value && selectedCountry) {\n const formatted = formatPhoneNumber(value, selectedCountry.code);\n setValue(formatted);\n }\n };\n\n return { handleCountryClick, handleCountryClose, handleCountrySelect, handleChange, handleBlur };\n};\n","import type { CountryCode } from 'libphonenumber-js';\nimport { parsePhoneNumber } from 'libphonenumber-js';\n\n\nexport const formatPhoneNumber = (value: string, country: CountryCode): string => {\n if (!value || value.trim() === '') return value;\n\n try {\n const phoneNumber = parsePhoneNumber(value, country);\n // Format if we have a phone number object, regardless of strict validity\n // This allows formatting of test numbers (like 555 prefix) and partially valid numbers\n if (phoneNumber) {\n return phoneNumber.formatInternational();\n }\n } catch {\n // Silently handle formatting errors\n }\n return value;\n};\n\nexport const validatePhoneNumber = (value: string, country: CountryCode): boolean => {\n if (!value || value.trim() === '') return false;\n\n try {\n const phoneNumber = parsePhoneNumber(value, country);\n // Consider a number valid if it can be parsed and has the right format\n // This allows test numbers (like 555 prefix) which isPossible but not isValid\n return phoneNumber ? phoneNumber.isPossible() : false;\n } catch {\n // Silently handle validation errors\n return false;\n }\n};\n\n// Enhanced helper to detect country from number\nexport const detectCountryFromNumber = (value: string): CountryCode | undefined => {\n if (!value || !value.startsWith('+')) return undefined;\n\n try {\n const phoneNumber = parsePhoneNumber(value);\n return phoneNumber?.country;\n } catch {\n return undefined;\n }\n};\n\n// Main component\n"],"mappings":"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","names":[]}
@@ -167,7 +167,7 @@ function SubmitAllFooter(props) {
167
167
  /* @__PURE__ */ jsx(SearchIcon, { fontSize: "small", sx: { color: "text.secondary", flexShrink: 0 } }),
168
168
  /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { flex: 1, minWidth: 0 }, noWrap: true, children: props.label }),
169
169
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.5, color: "text.secondary" }, children: [
170
- /* @__PURE__ */ jsx(Typography, { variant: "caption", children: "Enter" }),
170
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: props.keyLabel }),
171
171
  /* @__PURE__ */ jsx(KeyboardReturnIcon, { sx: { fontSize: 14 } })
172
172
  ] })
173
173
  ]
@@ -200,6 +200,7 @@ function PaletteBody(view) {
200
200
  SubmitAllFooter,
201
201
  {
202
202
  label: view.submitAllLabel(view.trimmed),
203
+ keyLabel: view.submitKeyLabel,
203
204
  selected: view.activeIndex === view.footerIndex,
204
205
  onSelect: () => view.onSubmitAll?.(view.trimmed),
205
206
  onHover: () => view.setActiveIndex(view.footerIndex)
@@ -265,6 +266,7 @@ function resolveOpts(props) {
265
266
  function resolveText(props) {
266
267
  return {
267
268
  submitAllLabel: props.submitAllLabel,
269
+ submitKeyLabel: props.submitKeyLabel,
268
270
  noResultsLabel: props.noResultsLabel,
269
271
  placeholder: props.placeholder,
270
272
  dataTestId: props.dataTestId ?? "search-palette"
@@ -344,6 +346,7 @@ function SearchPalette(props) {
344
346
  activeIndex,
345
347
  trimmed,
346
348
  submitAllLabel: text.submitAllLabel,
349
+ submitKeyLabel: text.submitKeyLabel,
347
350
  getKey: props.getKey,
348
351
  getPrimary: props.getPrimary,
349
352
  getSecondary: props.getSecondary,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/form/SearchPalette/SearchPalette.tsx","../../src/components/form/SearchPalette/SearchPalette.parts.tsx"],"sourcesContent":["import React from 'react';\n\nimport {\n createKeyDownHandler,\n FilterChips,\n ghostRemainder,\n PALETTE_CARD_SX,\n PaletteBody,\n PaletteInput,\n PaletteScrollArea,\n Paper,\n} from './SearchPalette.parts';\nimport type { SearchPaletteProps } from './SearchPalette.types';\n\n/**\n * A Gmail-style search palette (FUT-168): a single card with a search input,\n * a toggleable filter-chip row, a compact list of rich result rows (leading\n * image/avatar/icon + primary/secondary + trailing), and a \"see all results\"\n * footer. Fully app-agnostic — every label, filter, and row field is supplied\n * by the host through accessors, so it drops into any surface.\n *\n * Keyboard: ↑/↓ move the active row across the results and the footer, Enter\n * selects it (row → `onSelect`, footer → `onSubmitAll`), Esc calls `onClose`,\n * and Tab/→ accepts the inline ghost completion of the top result.\n *\n * Presentational pieces + the keydown builder live in `SearchPalette.parts`.\n */\n\nconst DEFAULT_MAX_ITEMS = 5;\n\n/** Non-string option defaults (numbers / flags / arrays). */\nfunction resolveOpts<T>(props: SearchPaletteProps<T>): {\n maxItems: number;\n filters: NonNullable<SearchPaletteProps<T>['filters']>;\n activeFilterIds: string[];\n isLoading: boolean;\n showGhostText: boolean;\n autoFocus: boolean;\n} {\n return {\n maxItems: props.maxItems ?? DEFAULT_MAX_ITEMS,\n filters: props.filters ?? [],\n activeFilterIds: props.activeFilterIds ?? [],\n isLoading: Boolean(props.isLoading),\n showGhostText: props.showGhostText ?? true,\n autoFocus: props.autoFocus ?? true,\n };\n}\n\n/** String / label defaults. */\nfunction resolveText<T>(props: SearchPaletteProps<T>): {\n submitAllLabel: (q: string) => string;\n noResultsLabel: string;\n placeholder: string;\n dataTestId: string;\n} {\n return {\n submitAllLabel: props.submitAllLabel,\n noResultsLabel: props.noResultsLabel,\n placeholder: props.placeholder,\n dataTestId: props.dataTestId ?? 'search-palette',\n };\n}\n\nexport function SearchPalette<T>(props: SearchPaletteProps<T>): React.JSX.Element {\n const opts = resolveOpts(props);\n const text = resolveText(props);\n\n const trimmed = props.value.trim();\n const hasQuery = trimmed.length > 0;\n const visible = props.items.slice(0, opts.maxItems);\n const showFooter = Boolean(props.onSubmitAll) && hasQuery;\n const rowCount = visible.length + (showFooter ? 1 : 0);\n const footerIndex = showFooter ? visible.length : -1;\n\n const [activeIndex, setActiveIndex] = React.useState(0);\n // Keep the active row in range as results change (typing, filtering).\n React.useEffect(() => {\n setActiveIndex((i) => (rowCount === 0 ? 0 : Math.min(i, rowCount - 1)));\n }, [rowCount]);\n\n const top = visible[0];\n const ghost =\n opts.showGhostText && hasQuery && top ? ghostRemainder(props.getPrimary(top), props.value) : '';\n\n const onKeyDown = createKeyDownHandler<T>({\n rowCount,\n activeIndex,\n footerIndex,\n visible,\n hasQuery,\n ghost,\n top,\n trimmed,\n getPrimary: props.getPrimary,\n onChange: props.onChange,\n onSelect: props.onSelect,\n onSubmitAll: props.onSubmitAll,\n onClose: props.onClose,\n setActiveIndex,\n });\n\n return (\n <Paper\n elevation={8}\n className={props.className}\n data-testid={text.dataTestId}\n sx={PALETTE_CARD_SX}\n >\n <PaletteInput\n value={props.value}\n ghost={ghost}\n isLoading={opts.isLoading}\n autoFocus={opts.autoFocus}\n placeholder={text.placeholder}\n inputAriaLabel={props.inputAriaLabel}\n hasQuery={hasQuery}\n onChange={props.onChange}\n onKeyDown={onKeyDown}\n />\n {opts.filters.length > 0 && (\n <FilterChips\n filters={opts.filters}\n activeFilterIds={opts.activeFilterIds}\n onToggleFilter={props.onToggleFilter}\n />\n )}\n <PaletteScrollArea>\n <PaletteBody<T>\n hasQuery={hasQuery} emptyQueryContent={props.emptyQueryContent} visible={visible}\n isLoading={opts.isLoading} noResultsLabel={text.noResultsLabel} showFooter={showFooter}\n footerIndex={footerIndex} activeIndex={activeIndex} trimmed={trimmed}\n submitAllLabel={text.submitAllLabel} getKey={props.getKey} getPrimary={props.getPrimary}\n getSecondary={props.getSecondary} getLead={props.getLead} getTrailing={props.getTrailing}\n onSelect={props.onSelect} onSubmitAll={props.onSubmitAll} setActiveIndex={setActiveIndex}\n />\n </PaletteScrollArea>\n </Paper>\n );\n}\n\nSearchPalette.displayName = 'SearchPalette';\n\nexport default SearchPalette;\n","import KeyboardReturnIcon from '@mui/icons-material/KeyboardReturn';\nimport SearchIcon from '@mui/icons-material/Search';\nimport {\n Avatar,\n Box,\n Chip,\n CircularProgress,\n InputBase,\n List,\n ListItemButton,\n Paper,\n Typography,\n} from '@mui/material';\nimport React from 'react';\n\nimport type { SearchFilterChip, SearchResultLead } from './SearchPalette.types';\n\n/** Bold the first case-insensitive occurrence of `query` within `text`. */\nexport function highlight(text: string, query: string): React.ReactNode {\n const q = query.trim();\n const at = q ? text.toLowerCase().indexOf(q.toLowerCase()) : -1;\n if (at < 0) return text;\n return (\n <>\n {text.slice(0, at)}\n <Box component=\"span\" sx={{ fontWeight: 700 }}>\n {text.slice(at, at + q.length)}\n </Box>\n {text.slice(at + q.length)}\n </>\n );\n}\n\n/** The leading visual of a result row (image / avatar / icon). */\nexport function Lead({ lead }: { lead: SearchResultLead | undefined }): React.JSX.Element | null {\n if (!lead) return null;\n if (lead.kind === 'image') {\n return (\n <Box\n component=\"img\"\n src={lead.src}\n alt={lead.alt ?? ''}\n sx={{ width: 32, height: 32, borderRadius: 1, objectFit: 'cover', flexShrink: 0 }}\n />\n );\n }\n if (lead.kind === 'avatar') {\n return (\n <Avatar src={lead.src} alt={lead.alt ?? ''} sx={{ width: 32, height: 32, fontSize: '0.85rem' }}>\n {lead.fallback}\n </Avatar>\n );\n }\n return (\n <Box sx={{ display: 'flex', width: 32, justifyContent: 'center', flexShrink: 0, color: 'text.secondary' }}>\n {lead.node}\n </Box>\n );\n}\n\n/** Compute the ghost-completion remainder of the top result for `query`. */\nexport function ghostRemainder(topPrimary: string | undefined, query: string): string {\n if (!query || !topPrimary) return '';\n return topPrimary.toLowerCase().startsWith(query.toLowerCase()) && topPrimary.length > query.length\n ? topPrimary.slice(query.length)\n : '';\n}\n\n/** The search input row: leading icon, ghost overlay, the field, and a spinner. */\nexport function PaletteInput(props: {\n value: string;\n ghost: string;\n isLoading: boolean;\n autoFocus: boolean;\n placeholder: string;\n inputAriaLabel?: string;\n hasQuery: boolean;\n onChange: (v: string) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n}): React.JSX.Element {\n return (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.25, px: 2, py: 1.5 }}>\n <SearchIcon fontSize=\"small\" sx={{ color: 'text.secondary', flexShrink: 0 }} />\n <Box sx={{ position: 'relative', flex: 1, minWidth: 0 }}>\n {props.ghost && (\n <Box\n aria-hidden\n sx={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n pointerEvents: 'none',\n whiteSpace: 'pre',\n overflow: 'hidden',\n fontSize: '1rem',\n }}\n >\n <Box component=\"span\" sx={{ visibility: 'hidden' }}>\n {props.value}\n </Box>\n <Box component=\"span\" sx={{ color: 'text.secondary', opacity: 0.6 }}>\n {props.ghost}\n </Box>\n </Box>\n )}\n <InputBase\n fullWidth\n autoFocus={props.autoFocus}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n onKeyDown={props.onKeyDown}\n placeholder={props.placeholder}\n inputProps={{\n role: 'combobox',\n 'aria-expanded': props.hasQuery,\n 'aria-label': props.inputAriaLabel,\n 'aria-autocomplete': 'list',\n }}\n sx={{ fontSize: '1rem' }}\n />\n </Box>\n {props.isLoading && <CircularProgress size={18} sx={{ flexShrink: 0 }} />}\n </Box>\n );\n}\n\n/** The toggleable filter-chip row. */\nexport function FilterChips(props: {\n filters: SearchFilterChip[];\n activeFilterIds: string[];\n onToggleFilter?: (id: string) => void;\n}): React.JSX.Element {\n return (\n <Box\n data-testid=\"search-palette-filters\"\n sx={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: 1,\n px: 2,\n pb: 1.5,\n borderBottom: (theme) => `1px solid ${theme.palette.divider}`,\n }}\n >\n {props.filters.map((chip) => {\n const active = props.activeFilterIds.includes(chip.id);\n return (\n <Chip\n key={chip.id}\n label={chip.label}\n icon={chip.icon as React.ReactElement | undefined}\n onClick={() => props.onToggleFilter?.(chip.id)}\n variant={active ? 'filled' : 'outlined'}\n color={active ? 'primary' : 'default'}\n size=\"small\"\n aria-pressed={active}\n data-testid={`search-palette-filter-${chip.id}`}\n sx={{ borderRadius: 2 }}\n />\n );\n })}\n </Box>\n );\n}\n\n/** One rich result row. */\nexport function ResultRow(props: {\n index: number;\n active: boolean;\n query: string;\n lead: SearchResultLead | undefined;\n primary: string;\n secondary: string | undefined;\n trailing: React.ReactNode | undefined;\n onSelect: () => void;\n onHover: () => void;\n}): React.JSX.Element {\n return (\n <ListItemButton\n role=\"option\"\n aria-selected={props.active}\n selected={props.active}\n onMouseEnter={props.onHover}\n onMouseDown={(e) => e.preventDefault()}\n onClick={props.onSelect}\n data-testid={`search-palette-result-${props.index}`}\n sx={{ gap: 1.25, px: 2, py: 1 }}\n >\n <Lead lead={props.lead} />\n <Box sx={{ minWidth: 0, flex: 1 }}>\n <Typography variant=\"body2\" noWrap sx={{ color: 'text.primary' }}>\n {highlight(props.primary, props.query)}\n </Typography>\n {props.secondary && (\n <Typography variant=\"caption\" noWrap sx={{ display: 'block', color: 'text.secondary' }}>\n {props.secondary}\n </Typography>\n )}\n </Box>\n {props.trailing != null && (\n <Box sx={{ flexShrink: 0, color: 'text.secondary', fontSize: '0.75rem' }}>{props.trailing}</Box>\n )}\n </ListItemButton>\n );\n}\n\n/** The \"see all results — Press ENTER\" footer row. */\nexport function SubmitAllFooter(props: {\n label: string;\n selected: boolean;\n onSelect: () => void;\n onHover: () => void;\n}): React.JSX.Element {\n return (\n <ListItemButton\n selected={props.selected}\n onMouseEnter={props.onHover}\n onMouseDown={(e) => e.preventDefault()}\n onClick={props.onSelect}\n data-testid=\"search-palette-submit-all\"\n sx={{ gap: 1.25, px: 2, py: 1, borderTop: (theme) => `1px solid ${theme.palette.divider}` }}\n >\n <SearchIcon fontSize=\"small\" sx={{ color: 'text.secondary', flexShrink: 0 }} />\n <Typography variant=\"body2\" sx={{ flex: 1, minWidth: 0 }} noWrap>\n {props.label}\n </Typography>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, color: 'text.secondary' }}>\n <Typography variant=\"caption\">Enter</Typography>\n <KeyboardReturnIcon sx={{ fontSize: 14 }} />\n </Box>\n </ListItemButton>\n );\n}\n\n/** Resolved view state shared by the body renderer. */\nexport interface BodyView<T> {\n hasQuery: boolean;\n emptyQueryContent: React.ReactNode;\n visible: T[];\n isLoading: boolean;\n noResultsLabel: string;\n showFooter: boolean;\n footerIndex: number;\n activeIndex: number;\n trimmed: string;\n submitAllLabel: (q: string) => string;\n getKey: (item: T) => string;\n getPrimary: (item: T) => string;\n getSecondary?: (item: T) => string | undefined;\n getLead?: (item: T) => SearchResultLead | undefined;\n getTrailing?: (item: T) => React.ReactNode | undefined;\n onSelect: (item: T) => void;\n onSubmitAll?: (query: string) => void;\n setActiveIndex: (i: number) => void;\n}\n\n/** The results list (or the empty-query slot / no-results message) + footer. */\nexport function PaletteBody<T>(view: BodyView<T>): React.JSX.Element | null {\n if (!view.hasQuery) {\n return view.emptyQueryContent ? (\n <Box data-testid=\"search-palette-empty-query\">{view.emptyQueryContent}</Box>\n ) : null;\n }\n const empty = view.visible.length === 0;\n return (\n <>\n {!empty && (\n <List dense disablePadding role=\"listbox\" data-testid=\"search-palette-results\">\n {view.visible.map((item, index) => (\n <ResultRow\n key={view.getKey(item)}\n index={index}\n active={index === view.activeIndex}\n query={view.trimmed}\n lead={view.getLead?.(item)}\n primary={view.getPrimary(item)}\n secondary={view.getSecondary?.(item)}\n trailing={view.getTrailing?.(item)}\n onSelect={() => view.onSelect(item)}\n onHover={() => view.setActiveIndex(index)}\n />\n ))}\n </List>\n )}\n {empty && !view.isLoading && (\n <Box sx={{ px: 2, py: 1.5 }} data-testid=\"search-palette-no-results\">\n <Typography variant=\"body2\" color=\"text.secondary\">\n {view.noResultsLabel}\n </Typography>\n </Box>\n )}\n {view.showFooter && (\n <SubmitAllFooter\n label={view.submitAllLabel(view.trimmed)}\n selected={view.activeIndex === view.footerIndex}\n onSelect={() => view.onSubmitAll?.(view.trimmed)}\n onHover={() => view.setActiveIndex(view.footerIndex)}\n />\n )}\n </>\n );\n}\n\n/**\n * The palette card: a flex column capped at the height its container allows, so\n * the input and the filter chips stay pinned while only the results scroll and a\n * long result set can never push the palette past the bottom of the viewport.\n */\nexport const PALETTE_CARD_SX = {\n width: '100%',\n maxWidth: 640,\n maxHeight: '100%',\n borderRadius: 2,\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n} as const;\n\n/** The scrolling region of the card — the results, and nothing above them. */\nexport function PaletteScrollArea({ children }: { children: React.ReactNode }): React.JSX.Element {\n return (\n <Box sx={{ minHeight: 0, overflowY: 'auto', overscrollBehavior: 'contain' }}>{children}</Box>\n );\n}\n\nexport { Paper };\n\n/** Context for the keydown handler builder. */\nexport interface KeyCtx<T> {\n rowCount: number;\n activeIndex: number;\n footerIndex: number;\n visible: T[];\n hasQuery: boolean;\n ghost: string;\n top: T | undefined;\n trimmed: string;\n getPrimary: (item: T) => string;\n onChange: (v: string) => void;\n onSelect: (item: T) => void;\n onSubmitAll?: (query: string) => void;\n onClose?: () => void;\n setActiveIndex: React.Dispatch<React.SetStateAction<number>>;\n}\n\n/** Build the input's keydown handler (nav / select / ghost-accept / close). */\nexport function createKeyDownHandler<T>(ctx: KeyCtx<T>): (e: React.KeyboardEvent) => void {\n const move = (delta: number): void =>\n ctx.setActiveIndex((i) => Math.min(Math.max(i + delta, 0), Math.max(ctx.rowCount - 1, 0)));\n const commit = (): void => {\n if (!ctx.hasQuery) return;\n if (ctx.activeIndex === ctx.footerIndex) {\n ctx.onSubmitAll?.(ctx.trimmed);\n return;\n }\n const item = ctx.visible[ctx.activeIndex];\n if (item) ctx.onSelect(item);\n };\n // A lookup keeps the handler itself flat (low complexity). Tab/→ is special —\n // it must only swallow the event when there is a ghost to accept, otherwise\n // Tab keeps its native focus behavior.\n const actions: Record<string, (() => void) | undefined> = {\n ArrowDown: () => move(1),\n ArrowUp: () => move(-1),\n Enter: commit,\n Escape: () => ctx.onClose?.(),\n };\n return (e) => {\n if ((e.key === 'Tab' || e.key === 'ArrowRight') && ctx.ghost && ctx.top) {\n e.preventDefault();\n ctx.onChange(ctx.getPrimary(ctx.top));\n return;\n }\n const action = actions[e.key];\n if (!action) return;\n e.preventDefault();\n action();\n };\n}\n"],"mappings":"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","names":["jsx","jsxs"]}
1
+ {"version":3,"sources":["../../src/components/form/SearchPalette/SearchPalette.tsx","../../src/components/form/SearchPalette/SearchPalette.parts.tsx"],"sourcesContent":["import React from 'react';\n\nimport {\n createKeyDownHandler,\n FilterChips,\n ghostRemainder,\n PALETTE_CARD_SX,\n PaletteBody,\n PaletteInput,\n PaletteScrollArea,\n Paper,\n} from './SearchPalette.parts';\nimport type { SearchPaletteProps } from './SearchPalette.types';\n\n/**\n * A Gmail-style search palette (FUT-168): a single card with a search input,\n * a toggleable filter-chip row, a compact list of rich result rows (leading\n * image/avatar/icon + primary/secondary + trailing), and a \"see all results\"\n * footer. Fully app-agnostic — every label, filter, and row field is supplied\n * by the host through accessors, so it drops into any surface.\n *\n * Keyboard: ↑/↓ move the active row across the results and the footer, Enter\n * selects it (row → `onSelect`, footer → `onSubmitAll`), Esc calls `onClose`,\n * and Tab/→ accepts the inline ghost completion of the top result.\n *\n * Presentational pieces + the keydown builder live in `SearchPalette.parts`.\n */\n\nconst DEFAULT_MAX_ITEMS = 5;\n\n/** Non-string option defaults (numbers / flags / arrays). */\nfunction resolveOpts<T>(props: SearchPaletteProps<T>): {\n maxItems: number;\n filters: NonNullable<SearchPaletteProps<T>['filters']>;\n activeFilterIds: string[];\n isLoading: boolean;\n showGhostText: boolean;\n autoFocus: boolean;\n} {\n return {\n maxItems: props.maxItems ?? DEFAULT_MAX_ITEMS,\n filters: props.filters ?? [],\n activeFilterIds: props.activeFilterIds ?? [],\n isLoading: Boolean(props.isLoading),\n showGhostText: props.showGhostText ?? true,\n autoFocus: props.autoFocus ?? true,\n };\n}\n\n/** String / label defaults. */\nfunction resolveText<T>(props: SearchPaletteProps<T>): {\n submitAllLabel: (q: string) => string;\n submitKeyLabel: string;\n noResultsLabel: string;\n placeholder: string;\n dataTestId: string;\n} {\n return {\n submitAllLabel: props.submitAllLabel,\n submitKeyLabel: props.submitKeyLabel,\n noResultsLabel: props.noResultsLabel,\n placeholder: props.placeholder,\n dataTestId: props.dataTestId ?? 'search-palette',\n };\n}\n\nexport function SearchPalette<T>(props: SearchPaletteProps<T>): React.JSX.Element {\n const opts = resolveOpts(props);\n const text = resolveText(props);\n\n const trimmed = props.value.trim();\n const hasQuery = trimmed.length > 0;\n const visible = props.items.slice(0, opts.maxItems);\n const showFooter = Boolean(props.onSubmitAll) && hasQuery;\n const rowCount = visible.length + (showFooter ? 1 : 0);\n const footerIndex = showFooter ? visible.length : -1;\n\n const [activeIndex, setActiveIndex] = React.useState(0);\n // Keep the active row in range as results change (typing, filtering).\n React.useEffect(() => {\n setActiveIndex((i) => (rowCount === 0 ? 0 : Math.min(i, rowCount - 1)));\n }, [rowCount]);\n\n const top = visible[0];\n const ghost =\n opts.showGhostText && hasQuery && top ? ghostRemainder(props.getPrimary(top), props.value) : '';\n\n const onKeyDown = createKeyDownHandler<T>({\n rowCount,\n activeIndex,\n footerIndex,\n visible,\n hasQuery,\n ghost,\n top,\n trimmed,\n getPrimary: props.getPrimary,\n onChange: props.onChange,\n onSelect: props.onSelect,\n onSubmitAll: props.onSubmitAll,\n onClose: props.onClose,\n setActiveIndex,\n });\n\n return (\n <Paper\n elevation={8}\n className={props.className}\n data-testid={text.dataTestId}\n sx={PALETTE_CARD_SX}\n >\n <PaletteInput\n value={props.value}\n ghost={ghost}\n isLoading={opts.isLoading}\n autoFocus={opts.autoFocus}\n placeholder={text.placeholder}\n inputAriaLabel={props.inputAriaLabel}\n hasQuery={hasQuery}\n onChange={props.onChange}\n onKeyDown={onKeyDown}\n />\n {opts.filters.length > 0 && (\n <FilterChips\n filters={opts.filters}\n activeFilterIds={opts.activeFilterIds}\n onToggleFilter={props.onToggleFilter}\n />\n )}\n <PaletteScrollArea>\n <PaletteBody<T>\n hasQuery={hasQuery} emptyQueryContent={props.emptyQueryContent} visible={visible}\n isLoading={opts.isLoading} noResultsLabel={text.noResultsLabel} showFooter={showFooter}\n footerIndex={footerIndex} activeIndex={activeIndex} trimmed={trimmed}\n submitAllLabel={text.submitAllLabel} submitKeyLabel={text.submitKeyLabel}\n getKey={props.getKey} getPrimary={props.getPrimary}\n getSecondary={props.getSecondary} getLead={props.getLead} getTrailing={props.getTrailing}\n onSelect={props.onSelect} onSubmitAll={props.onSubmitAll} setActiveIndex={setActiveIndex}\n />\n </PaletteScrollArea>\n </Paper>\n );\n}\n\nSearchPalette.displayName = 'SearchPalette';\n\nexport default SearchPalette;\n","import KeyboardReturnIcon from '@mui/icons-material/KeyboardReturn';\nimport SearchIcon from '@mui/icons-material/Search';\nimport {\n Avatar,\n Box,\n Chip,\n CircularProgress,\n InputBase,\n List,\n ListItemButton,\n Paper,\n Typography,\n} from '@mui/material';\nimport React from 'react';\n\nimport type { SearchFilterChip, SearchResultLead } from './SearchPalette.types';\n\n/** Bold the first case-insensitive occurrence of `query` within `text`. */\nexport function highlight(text: string, query: string): React.ReactNode {\n const q = query.trim();\n const at = q ? text.toLowerCase().indexOf(q.toLowerCase()) : -1;\n if (at < 0) return text;\n return (\n <>\n {text.slice(0, at)}\n <Box component=\"span\" sx={{ fontWeight: 700 }}>\n {text.slice(at, at + q.length)}\n </Box>\n {text.slice(at + q.length)}\n </>\n );\n}\n\n/** The leading visual of a result row (image / avatar / icon). */\nexport function Lead({ lead }: { lead: SearchResultLead | undefined }): React.JSX.Element | null {\n if (!lead) return null;\n if (lead.kind === 'image') {\n return (\n <Box\n component=\"img\"\n src={lead.src}\n alt={lead.alt ?? ''}\n sx={{ width: 32, height: 32, borderRadius: 1, objectFit: 'cover', flexShrink: 0 }}\n />\n );\n }\n if (lead.kind === 'avatar') {\n return (\n <Avatar src={lead.src} alt={lead.alt ?? ''} sx={{ width: 32, height: 32, fontSize: '0.85rem' }}>\n {lead.fallback}\n </Avatar>\n );\n }\n return (\n <Box sx={{ display: 'flex', width: 32, justifyContent: 'center', flexShrink: 0, color: 'text.secondary' }}>\n {lead.node}\n </Box>\n );\n}\n\n/** Compute the ghost-completion remainder of the top result for `query`. */\nexport function ghostRemainder(topPrimary: string | undefined, query: string): string {\n if (!query || !topPrimary) return '';\n return topPrimary.toLowerCase().startsWith(query.toLowerCase()) && topPrimary.length > query.length\n ? topPrimary.slice(query.length)\n : '';\n}\n\n/** The search input row: leading icon, ghost overlay, the field, and a spinner. */\nexport function PaletteInput(props: {\n value: string;\n ghost: string;\n isLoading: boolean;\n autoFocus: boolean;\n placeholder: string;\n inputAriaLabel?: string;\n hasQuery: boolean;\n onChange: (v: string) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n}): React.JSX.Element {\n return (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.25, px: 2, py: 1.5 }}>\n <SearchIcon fontSize=\"small\" sx={{ color: 'text.secondary', flexShrink: 0 }} />\n <Box sx={{ position: 'relative', flex: 1, minWidth: 0 }}>\n {props.ghost && (\n <Box\n aria-hidden\n sx={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n pointerEvents: 'none',\n whiteSpace: 'pre',\n overflow: 'hidden',\n fontSize: '1rem',\n }}\n >\n <Box component=\"span\" sx={{ visibility: 'hidden' }}>\n {props.value}\n </Box>\n <Box component=\"span\" sx={{ color: 'text.secondary', opacity: 0.6 }}>\n {props.ghost}\n </Box>\n </Box>\n )}\n <InputBase\n fullWidth\n autoFocus={props.autoFocus}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n onKeyDown={props.onKeyDown}\n placeholder={props.placeholder}\n inputProps={{\n role: 'combobox',\n 'aria-expanded': props.hasQuery,\n 'aria-label': props.inputAriaLabel,\n 'aria-autocomplete': 'list',\n }}\n sx={{ fontSize: '1rem' }}\n />\n </Box>\n {props.isLoading && <CircularProgress size={18} sx={{ flexShrink: 0 }} />}\n </Box>\n );\n}\n\n/** The toggleable filter-chip row. */\nexport function FilterChips(props: {\n filters: SearchFilterChip[];\n activeFilterIds: string[];\n onToggleFilter?: (id: string) => void;\n}): React.JSX.Element {\n return (\n <Box\n data-testid=\"search-palette-filters\"\n sx={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: 1,\n px: 2,\n pb: 1.5,\n borderBottom: (theme) => `1px solid ${theme.palette.divider}`,\n }}\n >\n {props.filters.map((chip) => {\n const active = props.activeFilterIds.includes(chip.id);\n return (\n <Chip\n key={chip.id}\n label={chip.label}\n icon={chip.icon as React.ReactElement | undefined}\n onClick={() => props.onToggleFilter?.(chip.id)}\n variant={active ? 'filled' : 'outlined'}\n color={active ? 'primary' : 'default'}\n size=\"small\"\n aria-pressed={active}\n data-testid={`search-palette-filter-${chip.id}`}\n sx={{ borderRadius: 2 }}\n />\n );\n })}\n </Box>\n );\n}\n\n/** One rich result row. */\nexport function ResultRow(props: {\n index: number;\n active: boolean;\n query: string;\n lead: SearchResultLead | undefined;\n primary: string;\n secondary: string | undefined;\n trailing: React.ReactNode | undefined;\n onSelect: () => void;\n onHover: () => void;\n}): React.JSX.Element {\n return (\n <ListItemButton\n role=\"option\"\n aria-selected={props.active}\n selected={props.active}\n onMouseEnter={props.onHover}\n onMouseDown={(e) => e.preventDefault()}\n onClick={props.onSelect}\n data-testid={`search-palette-result-${props.index}`}\n sx={{ gap: 1.25, px: 2, py: 1 }}\n >\n <Lead lead={props.lead} />\n <Box sx={{ minWidth: 0, flex: 1 }}>\n <Typography variant=\"body2\" noWrap sx={{ color: 'text.primary' }}>\n {highlight(props.primary, props.query)}\n </Typography>\n {props.secondary && (\n <Typography variant=\"caption\" noWrap sx={{ display: 'block', color: 'text.secondary' }}>\n {props.secondary}\n </Typography>\n )}\n </Box>\n {props.trailing != null && (\n <Box sx={{ flexShrink: 0, color: 'text.secondary', fontSize: '0.75rem' }}>{props.trailing}</Box>\n )}\n </ListItemButton>\n );\n}\n\n/** The \"see all results — Press ENTER\" footer row. */\nexport function SubmitAllFooter(props: {\n label: string;\n keyLabel: string;\n selected: boolean;\n onSelect: () => void;\n onHover: () => void;\n}): React.JSX.Element {\n return (\n <ListItemButton\n selected={props.selected}\n onMouseEnter={props.onHover}\n onMouseDown={(e) => e.preventDefault()}\n onClick={props.onSelect}\n data-testid=\"search-palette-submit-all\"\n sx={{ gap: 1.25, px: 2, py: 1, borderTop: (theme) => `1px solid ${theme.palette.divider}` }}\n >\n <SearchIcon fontSize=\"small\" sx={{ color: 'text.secondary', flexShrink: 0 }} />\n <Typography variant=\"body2\" sx={{ flex: 1, minWidth: 0 }} noWrap>\n {props.label}\n </Typography>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, color: 'text.secondary' }}>\n <Typography variant=\"caption\">{props.keyLabel}</Typography>\n <KeyboardReturnIcon sx={{ fontSize: 14 }} />\n </Box>\n </ListItemButton>\n );\n}\n\n/** Resolved view state shared by the body renderer. */\nexport interface BodyView<T> {\n hasQuery: boolean;\n emptyQueryContent: React.ReactNode;\n visible: T[];\n isLoading: boolean;\n noResultsLabel: string;\n showFooter: boolean;\n footerIndex: number;\n activeIndex: number;\n trimmed: string;\n submitAllLabel: (q: string) => string;\n submitKeyLabel: string;\n getKey: (item: T) => string;\n getPrimary: (item: T) => string;\n getSecondary?: (item: T) => string | undefined;\n getLead?: (item: T) => SearchResultLead | undefined;\n getTrailing?: (item: T) => React.ReactNode | undefined;\n onSelect: (item: T) => void;\n onSubmitAll?: (query: string) => void;\n setActiveIndex: (i: number) => void;\n}\n\n/** The results list (or the empty-query slot / no-results message) + footer. */\nexport function PaletteBody<T>(view: BodyView<T>): React.JSX.Element | null {\n if (!view.hasQuery) {\n return view.emptyQueryContent ? (\n <Box data-testid=\"search-palette-empty-query\">{view.emptyQueryContent}</Box>\n ) : null;\n }\n const empty = view.visible.length === 0;\n return (\n <>\n {!empty && (\n <List dense disablePadding role=\"listbox\" data-testid=\"search-palette-results\">\n {view.visible.map((item, index) => (\n <ResultRow\n key={view.getKey(item)}\n index={index}\n active={index === view.activeIndex}\n query={view.trimmed}\n lead={view.getLead?.(item)}\n primary={view.getPrimary(item)}\n secondary={view.getSecondary?.(item)}\n trailing={view.getTrailing?.(item)}\n onSelect={() => view.onSelect(item)}\n onHover={() => view.setActiveIndex(index)}\n />\n ))}\n </List>\n )}\n {empty && !view.isLoading && (\n <Box sx={{ px: 2, py: 1.5 }} data-testid=\"search-palette-no-results\">\n <Typography variant=\"body2\" color=\"text.secondary\">\n {view.noResultsLabel}\n </Typography>\n </Box>\n )}\n {view.showFooter && (\n <SubmitAllFooter\n label={view.submitAllLabel(view.trimmed)}\n keyLabel={view.submitKeyLabel}\n selected={view.activeIndex === view.footerIndex}\n onSelect={() => view.onSubmitAll?.(view.trimmed)}\n onHover={() => view.setActiveIndex(view.footerIndex)}\n />\n )}\n </>\n );\n}\n\n/**\n * The palette card: a flex column capped at the height its container allows, so\n * the input and the filter chips stay pinned while only the results scroll and a\n * long result set can never push the palette past the bottom of the viewport.\n */\nexport const PALETTE_CARD_SX = {\n width: '100%',\n maxWidth: 640,\n maxHeight: '100%',\n borderRadius: 2,\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n} as const;\n\n/** The scrolling region of the card — the results, and nothing above them. */\nexport function PaletteScrollArea({ children }: { children: React.ReactNode }): React.JSX.Element {\n return (\n <Box sx={{ minHeight: 0, overflowY: 'auto', overscrollBehavior: 'contain' }}>{children}</Box>\n );\n}\n\nexport { Paper };\n\n/** Context for the keydown handler builder. */\nexport interface KeyCtx<T> {\n rowCount: number;\n activeIndex: number;\n footerIndex: number;\n visible: T[];\n hasQuery: boolean;\n ghost: string;\n top: T | undefined;\n trimmed: string;\n getPrimary: (item: T) => string;\n onChange: (v: string) => void;\n onSelect: (item: T) => void;\n onSubmitAll?: (query: string) => void;\n onClose?: () => void;\n setActiveIndex: React.Dispatch<React.SetStateAction<number>>;\n}\n\n/** Build the input's keydown handler (nav / select / ghost-accept / close). */\nexport function createKeyDownHandler<T>(ctx: KeyCtx<T>): (e: React.KeyboardEvent) => void {\n const move = (delta: number): void =>\n ctx.setActiveIndex((i) => Math.min(Math.max(i + delta, 0), Math.max(ctx.rowCount - 1, 0)));\n const commit = (): void => {\n if (!ctx.hasQuery) return;\n if (ctx.activeIndex === ctx.footerIndex) {\n ctx.onSubmitAll?.(ctx.trimmed);\n return;\n }\n const item = ctx.visible[ctx.activeIndex];\n if (item) ctx.onSelect(item);\n };\n // A lookup keeps the handler itself flat (low complexity). Tab/→ is special —\n // it must only swallow the event when there is a ghost to accept, otherwise\n // Tab keeps its native focus behavior.\n const actions: Record<string, (() => void) | undefined> = {\n ArrowDown: () => move(1),\n ArrowUp: () => move(-1),\n Enter: commit,\n Escape: () => ctx.onClose?.(),\n };\n return (e) => {\n if ((e.key === 'Tab' || e.key === 'ArrowRight') && ctx.ghost && ctx.top) {\n e.preventDefault();\n ctx.onChange(ctx.getPrimary(ctx.top));\n return;\n }\n const action = actions[e.key];\n if (!action) return;\n e.preventDefault();\n action();\n };\n}\n"],"mappings":"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","names":["jsx","jsxs"]}