@purpur/library 9.0.6 → 9.0.7

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 (251) hide show
  1. package/CHANGELOG.json +33 -0
  2. package/CHANGELOG.md +15 -1
  3. package/dist/{RichText-DRacgpis.mjs → RichText-Bi51HE6X.mjs} +3 -3
  4. package/dist/{RichText-DRacgpis.mjs.map → RichText-Bi51HE6X.mjs.map} +1 -1
  5. package/dist/{RichText-DMyGiMN0.js → RichText-DNroJJXv.js} +2 -2
  6. package/dist/{RichText-DMyGiMN0.js.map → RichText-DNroJJXv.js.map} +1 -1
  7. package/dist/{ThemeProvider-CrjMv3M8.mjs → ThemeProvider-BR1hJQOD.mjs} +85 -85
  8. package/dist/{ThemeProvider-CrjMv3M8.mjs.map → ThemeProvider-BR1hJQOD.mjs.map} +1 -1
  9. package/dist/{accordion-DWflnyWa.mjs → accordion-BKTz9DM6.mjs} +18 -18
  10. package/dist/{accordion-DWflnyWa.mjs.map → accordion-BKTz9DM6.mjs.map} +1 -1
  11. package/dist/{accordion-CF2fj2uq.js → accordion-DX8efWOt.js} +2 -2
  12. package/dist/{accordion-CF2fj2uq.js.map → accordion-DX8efWOt.js.map} +1 -1
  13. package/dist/accordion.cjs.js +1 -1
  14. package/dist/accordion.es.js +1 -1
  15. package/dist/{alert-badge-u7qAhYbR.mjs → alert-badge-DR8cigWu.mjs} +3 -3
  16. package/dist/{alert-badge-u7qAhYbR.mjs.map → alert-badge-DR8cigWu.mjs.map} +1 -1
  17. package/dist/alert-badge.es.js +1 -1
  18. package/dist/{autocomplete-yD0-1vlF.js → autocomplete-6qSqK3SI.js} +2 -2
  19. package/dist/{autocomplete-yD0-1vlF.js.map → autocomplete-6qSqK3SI.js.map} +1 -1
  20. package/dist/{autocomplete-0kGG_STe.mjs → autocomplete-B4dZx9zF.mjs} +3 -3
  21. package/dist/{autocomplete-0kGG_STe.mjs.map → autocomplete-B4dZx9zF.mjs.map} +1 -1
  22. package/dist/autocomplete.cjs.js +1 -1
  23. package/dist/autocomplete.es.js +1 -1
  24. package/dist/button-BfYKNBmC.mjs +102 -0
  25. package/dist/button-BfYKNBmC.mjs.map +1 -0
  26. package/dist/button-DDYGuqZ0.js +2 -0
  27. package/dist/button-DDYGuqZ0.js.map +1 -0
  28. package/dist/button.cjs.js +1 -1
  29. package/dist/button.es.js +1 -1
  30. package/dist/{calendar-pMM0fKEu.js → calendar-CxkJMONO.js} +2 -2
  31. package/dist/{calendar-pMM0fKEu.js.map → calendar-CxkJMONO.js.map} +1 -1
  32. package/dist/{calendar-DDie8jSH.mjs → calendar-vALLklKV.mjs} +2 -2
  33. package/dist/{calendar-DDie8jSH.mjs.map → calendar-vALLklKV.mjs.map} +1 -1
  34. package/dist/calendar.cjs.js +1 -1
  35. package/dist/calendar.es.js +1 -1
  36. package/dist/{card-DiMVw06l.mjs → card-CkZQZOz1.mjs} +9 -9
  37. package/dist/{card-DiMVw06l.mjs.map → card-CkZQZOz1.mjs.map} +1 -1
  38. package/dist/{card-B512KHpr.js → card-VMa3cGCP.js} +2 -2
  39. package/dist/{card-B512KHpr.js.map → card-VMa3cGCP.js.map} +1 -1
  40. package/dist/card.cjs.js +1 -1
  41. package/dist/card.es.js +1 -1
  42. package/dist/{checkbox-LYzMiXu7.mjs → checkbox-D6qWgpWR.mjs} +8 -8
  43. package/dist/{checkbox-LYzMiXu7.mjs.map → checkbox-D6qWgpWR.mjs.map} +1 -1
  44. package/dist/checkbox.es.js +1 -1
  45. package/dist/{chip-group-aj1fdnjC.js → chip-group-B775zvKD.js} +2 -2
  46. package/dist/{chip-group-aj1fdnjC.js.map → chip-group-B775zvKD.js.map} +1 -1
  47. package/dist/{chip-group-CJVvfl_J.mjs → chip-group-xuOe7nL3.mjs} +3 -3
  48. package/dist/{chip-group-CJVvfl_J.mjs.map → chip-group-xuOe7nL3.mjs.map} +1 -1
  49. package/dist/chip-group.cjs.js +1 -1
  50. package/dist/chip-group.es.js +1 -1
  51. package/dist/components/button/src/button.d.ts +1 -2
  52. package/dist/components/button/src/button.d.ts.map +1 -1
  53. package/dist/components/date-field/src/date-field.d.ts.map +1 -1
  54. package/dist/components/stepper/src/stepper-button.d.ts.map +1 -1
  55. package/dist/components/table/src/table-toolbar.d.ts.map +1 -1
  56. package/dist/components/tabs/src/tab-content.d.ts.map +1 -1
  57. package/dist/components/tabs/src/tabs.d.ts.map +1 -1
  58. package/dist/{container-Bw12NgHN.mjs → container-DLjBTB_w.mjs} +3 -3
  59. package/dist/{container-Bw12NgHN.mjs.map → container-DLjBTB_w.mjs.map} +1 -1
  60. package/dist/container.es.js +1 -1
  61. package/dist/{content-block-DUcjAZgG.mjs → content-block-BMOvlH7a.mjs} +6 -6
  62. package/dist/{content-block-DUcjAZgG.mjs.map → content-block-BMOvlH7a.mjs.map} +1 -1
  63. package/dist/{content-block-kzdUWgvH.js → content-block-Cd7xSE8t.js} +2 -2
  64. package/dist/{content-block-kzdUWgvH.js.map → content-block-Cd7xSE8t.js.map} +1 -1
  65. package/dist/content-block.cjs.js +1 -1
  66. package/dist/content-block.es.js +1 -1
  67. package/dist/{countdown-DxAGVUFI.mjs → countdown-DZ4IwkNy.mjs} +12 -12
  68. package/dist/{countdown-DxAGVUFI.mjs.map → countdown-DZ4IwkNy.mjs.map} +1 -1
  69. package/dist/countdown.es.js +1 -1
  70. package/dist/date-field-CORqon6B.js +2 -0
  71. package/dist/{date-field-CPiTZqa0.js.map → date-field-CORqon6B.js.map} +1 -1
  72. package/dist/{date-field-D_6iP2fC.mjs → date-field-CTJB8O0e.mjs} +325 -310
  73. package/dist/{date-field-D_6iP2fC.mjs.map → date-field-CTJB8O0e.mjs.map} +1 -1
  74. package/dist/date-field.cjs.js +1 -1
  75. package/dist/date-field.es.js +1 -1
  76. package/dist/{date-picker-BRnwwZv1.mjs → date-picker-CJcIJ5VL.mjs} +5 -5
  77. package/dist/{date-picker-BRnwwZv1.mjs.map → date-picker-CJcIJ5VL.mjs.map} +1 -1
  78. package/dist/{date-picker-DlJGggam.js → date-picker-Dv3W05Hf.js} +2 -2
  79. package/dist/{date-picker-DlJGggam.js.map → date-picker-Dv3W05Hf.js.map} +1 -1
  80. package/dist/date-picker.cjs.js +1 -1
  81. package/dist/date-picker.es.js +1 -1
  82. package/dist/{dismissable-chip-group-DsO2cZaF.js → dismissable-chip-group-CnziecOt.js} +2 -2
  83. package/dist/{dismissable-chip-group-DsO2cZaF.js.map → dismissable-chip-group-CnziecOt.js.map} +1 -1
  84. package/dist/{dismissable-chip-group-Bl0D18qM.mjs → dismissable-chip-group-ZCYOt1sB.mjs} +2 -2
  85. package/dist/{dismissable-chip-group-Bl0D18qM.mjs.map → dismissable-chip-group-ZCYOt1sB.mjs.map} +1 -1
  86. package/dist/dismissable-chip-group.cjs.js +1 -1
  87. package/dist/dismissable-chip-group.es.js +1 -1
  88. package/dist/{drawer-nBpCtIdI.js → drawer-Ce5LNpU2.js} +2 -2
  89. package/dist/{drawer-nBpCtIdI.js.map → drawer-Ce5LNpU2.js.map} +1 -1
  90. package/dist/{drawer-Boqmgh-i.mjs → drawer-DSFZ61OH.mjs} +14 -14
  91. package/dist/{drawer-Boqmgh-i.mjs.map → drawer-DSFZ61OH.mjs.map} +1 -1
  92. package/dist/drawer.cjs.js +1 -1
  93. package/dist/drawer.es.js +1 -1
  94. package/dist/{floating-ui.react-dom-0ol4sFzt.mjs → floating-ui.react-dom-gsHLgcoR.mjs} +5 -5
  95. package/dist/{floating-ui.react-dom-0ol4sFzt.mjs.map → floating-ui.react-dom-gsHLgcoR.mjs.map} +1 -1
  96. package/dist/{footer-DrjAwjuL.js → footer-BL0ewBZT.js} +2 -2
  97. package/dist/{footer-DrjAwjuL.js.map → footer-BL0ewBZT.js.map} +1 -1
  98. package/dist/{footer-DcWsihxS.mjs → footer-cH07Xqil.mjs} +5 -5
  99. package/dist/{footer-DcWsihxS.mjs.map → footer-cH07Xqil.mjs.map} +1 -1
  100. package/dist/footer.cjs.js +1 -1
  101. package/dist/footer.es.js +1 -1
  102. package/dist/heading-drD5ugCC.js +2 -0
  103. package/dist/{heading-DLCdW6gx.js.map → heading-drD5ugCC.js.map} +1 -1
  104. package/dist/heading-xwBuT_-9.mjs +75 -0
  105. package/dist/{heading-gqtQNo5n.mjs.map → heading-xwBuT_-9.mjs.map} +1 -1
  106. package/dist/heading.cjs.js +1 -1
  107. package/dist/heading.es.js +1 -1
  108. package/dist/{hero-banner-B8fRHxXc.mjs → hero-banner-CkSSlxTW.mjs} +5 -5
  109. package/dist/{hero-banner-B8fRHxXc.mjs.map → hero-banner-CkSSlxTW.mjs.map} +1 -1
  110. package/dist/{hero-banner-D3peC1NR.js → hero-banner-JFaqW20R.js} +2 -2
  111. package/dist/{hero-banner-D3peC1NR.js.map → hero-banner-JFaqW20R.js.map} +1 -1
  112. package/dist/hero-banner.cjs.js +1 -1
  113. package/dist/hero-banner.es.js +1 -1
  114. package/dist/library.cjs.js +1 -1
  115. package/dist/library.es.js +44 -44
  116. package/dist/{listbox-u6__DsLw.mjs → listbox-oDeP8FvH.mjs} +2 -2
  117. package/dist/{listbox-u6__DsLw.mjs.map → listbox-oDeP8FvH.mjs.map} +1 -1
  118. package/dist/listbox.es.js +1 -1
  119. package/dist/{modal-C2UQsW-g.mjs → modal-2ymCXTup.mjs} +19 -19
  120. package/dist/{modal-C2UQsW-g.mjs.map → modal-2ymCXTup.mjs.map} +1 -1
  121. package/dist/{modal-nyhf5zxG.js → modal-CXi2xez5.js} +2 -2
  122. package/dist/{modal-nyhf5zxG.js.map → modal-CXi2xez5.js.map} +1 -1
  123. package/dist/modal.cjs.js +1 -1
  124. package/dist/modal.es.js +1 -1
  125. package/dist/{notification-C32wHljA.mjs → notification-BFSOuDp8.mjs} +22 -22
  126. package/dist/{notification-C32wHljA.mjs.map → notification-BFSOuDp8.mjs.map} +1 -1
  127. package/dist/{notification-Bg1vQkQ3.js → notification-DdnI2rOh.js} +2 -2
  128. package/dist/{notification-Bg1vQkQ3.js.map → notification-DdnI2rOh.js.map} +1 -1
  129. package/dist/{notification-banner-BY2iZOIa.mjs → notification-banner-CQvBezAL.mjs} +3 -3
  130. package/dist/{notification-banner-BY2iZOIa.mjs.map → notification-banner-CQvBezAL.mjs.map} +1 -1
  131. package/dist/{notification-banner-C8XsBDTq.js → notification-banner-CT4ew8IQ.js} +2 -2
  132. package/dist/{notification-banner-C8XsBDTq.js.map → notification-banner-CT4ew8IQ.js.map} +1 -1
  133. package/dist/notification-banner.cjs.js +1 -1
  134. package/dist/notification-banner.es.js +1 -1
  135. package/dist/notification.cjs.js +1 -1
  136. package/dist/notification.es.js +1 -1
  137. package/dist/{pagination-CVVCAQ65.mjs → pagination-BdCjh1Pi.mjs} +2 -2
  138. package/dist/{pagination-CVVCAQ65.mjs.map → pagination-BdCjh1Pi.mjs.map} +1 -1
  139. package/dist/pagination.es.js +1 -1
  140. package/dist/{paragraph-DNtj7OLr.mjs → paragraph-Ci50OF1u.mjs} +3 -3
  141. package/dist/{paragraph-DNtj7OLr.mjs.map → paragraph-Ci50OF1u.mjs.map} +1 -1
  142. package/dist/paragraph.es.js +1 -1
  143. package/dist/{popover-B1BgSoQx.js → popover-D3qWbbU4.js} +2 -2
  144. package/dist/{popover-B1BgSoQx.js.map → popover-D3qWbbU4.js.map} +1 -1
  145. package/dist/{popover-DBMI9Jy1.mjs → popover-ZeQKmyEb.mjs} +25 -25
  146. package/dist/{popover-DBMI9Jy1.mjs.map → popover-ZeQKmyEb.mjs.map} +1 -1
  147. package/dist/popover.cjs.js +1 -1
  148. package/dist/popover.es.js +1 -1
  149. package/dist/{product-card-rfpJbzzV.mjs → product-card-BU1ThhCx.mjs} +12 -12
  150. package/dist/{product-card-rfpJbzzV.mjs.map → product-card-BU1ThhCx.mjs.map} +1 -1
  151. package/dist/{product-card-DOBHGAa2.js → product-card-CNBegEBW.js} +2 -2
  152. package/dist/{product-card-DOBHGAa2.js.map → product-card-CNBegEBW.js.map} +1 -1
  153. package/dist/product-card.cjs.js +1 -1
  154. package/dist/product-card.es.js +1 -1
  155. package/dist/{promotion-card-BIFOwMrw.js → promotion-card-CXNhskRl.js} +2 -2
  156. package/dist/{promotion-card-BIFOwMrw.js.map → promotion-card-CXNhskRl.js.map} +1 -1
  157. package/dist/{promotion-card-DeyqFnyP.mjs → promotion-card-_bPyVr9t.mjs} +9 -9
  158. package/dist/{promotion-card-DeyqFnyP.mjs.map → promotion-card-_bPyVr9t.mjs.map} +1 -1
  159. package/dist/promotion-card.cjs.js +1 -1
  160. package/dist/promotion-card.es.js +1 -1
  161. package/dist/purpur.css +1 -1
  162. package/dist/{quantity-selector-DPOTlMSq.js → quantity-selector-CjSAaj7d.js} +2 -2
  163. package/dist/{quantity-selector-DPOTlMSq.js.map → quantity-selector-CjSAaj7d.js.map} +1 -1
  164. package/dist/{quantity-selector-_VcZYLjR.mjs → quantity-selector-HvyYSKah.mjs} +5 -5
  165. package/dist/{quantity-selector-_VcZYLjR.mjs.map → quantity-selector-HvyYSKah.mjs.map} +1 -1
  166. package/dist/quantity-selector.cjs.js +1 -1
  167. package/dist/quantity-selector.es.js +1 -1
  168. package/dist/{radio-button-group-CZ_FnVAi.js → radio-button-group-BaFpGAcD.js} +2 -2
  169. package/dist/{radio-button-group-CZ_FnVAi.js.map → radio-button-group-BaFpGAcD.js.map} +1 -1
  170. package/dist/{radio-button-group-BnCPcmSN.mjs → radio-button-group-CFqPsu5A.mjs} +5 -5
  171. package/dist/{radio-button-group-BnCPcmSN.mjs.map → radio-button-group-CFqPsu5A.mjs.map} +1 -1
  172. package/dist/radio-button-group.cjs.js +1 -1
  173. package/dist/radio-button-group.es.js +1 -1
  174. package/dist/{radio-card-group-DkaMcmen.mjs → radio-card-group-BlRZBa-9.mjs} +16 -16
  175. package/dist/{radio-card-group-DkaMcmen.mjs.map → radio-card-group-BlRZBa-9.mjs.map} +1 -1
  176. package/dist/{radio-card-group-BT5pV3tA.js → radio-card-group-sYcfDPJq.js} +2 -2
  177. package/dist/{radio-card-group-BT5pV3tA.js.map → radio-card-group-sYcfDPJq.js.map} +1 -1
  178. package/dist/radio-card-group.cjs.js +1 -1
  179. package/dist/radio-card-group.es.js +1 -1
  180. package/dist/rich-text.cjs.js +1 -1
  181. package/dist/rich-text.es.js +1 -1
  182. package/dist/scss/heading.mixins.scss +1 -1
  183. package/dist/{search-field-DH0xeW_J.mjs → search-field-BOmCVr5b.mjs} +11 -11
  184. package/dist/{search-field-DH0xeW_J.mjs.map → search-field-BOmCVr5b.mjs.map} +1 -1
  185. package/dist/{search-field-CxX4BBcg.js → search-field-CanOlkIY.js} +2 -2
  186. package/dist/{search-field-CxX4BBcg.js.map → search-field-CanOlkIY.js.map} +1 -1
  187. package/dist/search-field.cjs.js +1 -1
  188. package/dist/search-field.es.js +1 -1
  189. package/dist/{stepper-BfIbJwZn.mjs → stepper-D7T0wed7.mjs} +68 -71
  190. package/dist/stepper-D7T0wed7.mjs.map +1 -0
  191. package/dist/stepper-DYjJgEHL.js +2 -0
  192. package/dist/stepper-DYjJgEHL.js.map +1 -0
  193. package/dist/stepper.cjs.js +1 -1
  194. package/dist/stepper.es.js +1 -1
  195. package/dist/{table-DvcpczWf.mjs → table-B4pts_r4.mjs} +181 -179
  196. package/dist/{table-DvcpczWf.mjs.map → table-B4pts_r4.mjs.map} +1 -1
  197. package/dist/{table-BNeo_B1h.js → table-Bv_BISXV.js} +4 -4
  198. package/dist/{table-BNeo_B1h.js.map → table-Bv_BISXV.js.map} +1 -1
  199. package/dist/table.cjs.js +1 -1
  200. package/dist/table.es.js +1 -1
  201. package/dist/tabs-Bye5lgZ1.mjs +424 -0
  202. package/dist/tabs-Bye5lgZ1.mjs.map +1 -0
  203. package/dist/tabs-D-nfZHIA.js +2 -0
  204. package/dist/tabs-D-nfZHIA.js.map +1 -0
  205. package/dist/tabs.cjs.js +1 -1
  206. package/dist/tabs.es.js +1 -1
  207. package/dist/{text-area-Cb9Hm2Z9.mjs → text-area-CpYWt99s.mjs} +3 -3
  208. package/dist/{text-area-Cb9Hm2Z9.mjs.map → text-area-CpYWt99s.mjs.map} +1 -1
  209. package/dist/text-area.es.js +1 -1
  210. package/dist/{text-field-PKAaXO1N.mjs → text-field-5rIuW8gc.mjs} +2 -2
  211. package/dist/{text-field-PKAaXO1N.mjs.map → text-field-5rIuW8gc.mjs.map} +1 -1
  212. package/dist/{text-field-B8a-NKm4.js → text-field-Xt6T3zjO.js} +2 -2
  213. package/dist/{text-field-B8a-NKm4.js.map → text-field-Xt6T3zjO.js.map} +1 -1
  214. package/dist/text-field.cjs.js +1 -1
  215. package/dist/text-field.es.js +1 -1
  216. package/dist/theme.es.js +2 -2
  217. package/dist/{toggle-Cezg5MUc.mjs → toggle-D23x1wWk.mjs} +9 -9
  218. package/dist/{toggle-Cezg5MUc.mjs.map → toggle-D23x1wWk.mjs.map} +1 -1
  219. package/dist/toggle.es.js +1 -1
  220. package/dist/tokens.es.js +3 -3
  221. package/dist/{tooltip-DXi7ikUT.mjs → tooltip-DkwyNxrQ.mjs} +12 -12
  222. package/dist/{tooltip-DXi7ikUT.mjs.map → tooltip-DkwyNxrQ.mjs.map} +1 -1
  223. package/dist/{tooltip-CLQLxoaf.js → tooltip-svlZkXBs.js} +2 -2
  224. package/dist/{tooltip-CLQLxoaf.js.map → tooltip-svlZkXBs.js.map} +1 -1
  225. package/dist/tooltip.cjs.js +1 -1
  226. package/dist/tooltip.es.js +1 -1
  227. package/dist/{useColorScheme-DRQcbSog.mjs → useColorScheme-9rgSgG0N.mjs} +2 -2
  228. package/dist/{useColorScheme-DRQcbSog.mjs.map → useColorScheme-9rgSgG0N.mjs.map} +1 -1
  229. package/dist/{variables-91UvS2rU.mjs → variables-BVgnpUH9.mjs} +253 -253
  230. package/dist/{variables-91UvS2rU.mjs.map → variables-BVgnpUH9.mjs.map} +1 -1
  231. package/dist/{variables-BSsIx39i.mjs → variables-DkCN2x27.mjs} +7 -7
  232. package/dist/{variables-BSsIx39i.mjs.map → variables-DkCN2x27.mjs.map} +1 -1
  233. package/dist/{variables-BUfnQw6H.mjs → variables-Dr3Hsdn-.mjs} +9 -9
  234. package/dist/{variables-BUfnQw6H.mjs.map → variables-Dr3Hsdn-.mjs.map} +1 -1
  235. package/package.json +18 -18
  236. package/scripts/generate.mts +4 -1
  237. package/vite-plugin-generate-components-metadata.js +4 -1
  238. package/dist/button-ChYUPi2k.js +0 -2
  239. package/dist/button-ChYUPi2k.js.map +0 -1
  240. package/dist/button-DBX_tvfJ.mjs +0 -105
  241. package/dist/button-DBX_tvfJ.mjs.map +0 -1
  242. package/dist/date-field-CPiTZqa0.js +0 -2
  243. package/dist/heading-DLCdW6gx.js +0 -2
  244. package/dist/heading-gqtQNo5n.mjs +0 -75
  245. package/dist/stepper-B248FwO-.js +0 -2
  246. package/dist/stepper-B248FwO-.js.map +0 -1
  247. package/dist/stepper-BfIbJwZn.mjs.map +0 -1
  248. package/dist/tabs-CfHd4UQ2.js +0 -2
  249. package/dist/tabs-CfHd4UQ2.js.map +0 -1
  250. package/dist/tabs-CoXMAwMx.mjs +0 -396
  251. package/dist/tabs-CoXMAwMx.mjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";const p=require("react/jsx-runtime"),r=require("react"),de=require("./chevron-down.es-BMjgiS3F.js"),M=require("./listbox-BmjBtIv8.js"),pe=require("./text-field-B8a-NKm4.js"),be=require("./bind-DeUYJ6m9.js"),me={"purpur-autocomplete":"_purpur-autocomplete_dgjyz_1","purpur-autocomplete__listbox":"_purpur-autocomplete__listbox_dgjyz_4","purpur-autocomplete__chevron-button":"_purpur-autocomplete__chevron-button_dgjyz_9","purpur-autocomplete__chevron-icon":"_purpur-autocomplete__chevron-icon_dgjyz_15","purpur-autocomplete__chevron-icon--up":"_purpur-autocomplete__chevron-icon--up_dgjyz_20"},fe=i=>r.useRef(i),xe=(i,x)=>{const n=r.useCallback(_=>{i&&!i.contains(_.target)&&x()},[x,i]);r.useEffect(()=>(document.addEventListener("mousedown",n),()=>{document.removeEventListener("mousedown",n)}),[n])},Z=({combobox:i,comboboxButtonAriaLabel:x,highlightFirstOption:n,defaultInputValue:_,inputValue:u,filterOption:R,id:l,listboxLabel:S,listboxMaxHeight:b,onInputBlur:h,onInputChange:L,onInputFocus:D,onInputKeyDown:k,onInputMouseDown:$,openOnFocus:A,noOptionsText:E,onSelect:T,options:a,selectedOption:t,["data-testid"]:y})=>{const[C,K]=r.useState(((typeof u=="string"?u:_)||t?.label)??""),F=typeof u=="string"?u:C,[c,v]=r.useState(n?a[0]:void 0),B=r.useRef(null),U=fe(null),N=r.useRef(null),O=r.useRef({}),[V,Y]=r.useState(!1);function q(e){return y?`${y}-${e}`:void 0}const w=()=>{Y(!1),v(void 0)};xe(U.current,w);const g=({eventType:e})=>{Y(!0),t&&requestAnimationFrame(()=>{v({...t,isSetByClickEvent:e==="CLICK"}),z(O.current[t.id])})},ee=e=>{if(R)return a.filter(s=>R(e,s));if(!e)return a;const o=e.toUpperCase().split(" ")||[];return a.filter(s=>o.every(f=>(s.value||s.label).toUpperCase().includes(f)))},G=e=>t&&t?.label===e?a:ee(e),d=G(F),P=e=>{L?.(e),K(e)},z=e=>{if(e){const o=e.getBoundingClientRect(),s=N.current?.getBoundingClientRect()||{top:0,bottom:0};(o.top<s.top||o.bottom>s.bottom)&&e.scrollIntoView({block:"nearest"})}},J=e=>{e&&(B.current?.focus(),P(e.label),T?.(e)),w()},te=e=>{const o=n&&!c?0:d.findIndex(f=>f&&c?.id===f.id),s=d.length;return e==="ArrowDown"?d[(o??-1)+1]||d[0]:d[(o??s)-1]||d[s-1]},m=V&&(!!d.length||!!E),oe=e=>{!m&&g({eventType:"KEYBOARD"});const o=te(e);v(o),o&&z(O.current[o.id])},ne=e=>{switch(k?.(e),e.key){case"ArrowUp":case"ArrowDown":e.preventDefault(),oe(e.key);break;case"Enter":{const o=c||(n?a[0]:void 0);m&&J(o),!m&&g({eventType:"KEYBOARD"});break}case"Escape":case"Tab":w();break}},se=e=>{const o=G(e.target.value);P(e.target.value),v(void 0),!m&&g({eventType:"KEYBOARD"}),n&&o[0]&&z(O.current[o[0].id])},ce=e=>{$?.(e),m?w():g({eventType:"CLICK"})},re=e=>{D?.(e),!V&&A&&g({eventType:"KEYBOARD"}),B.current?.select()},ie=e=>{h?.(e),setTimeout(()=>{!B.current?.contains(document.activeElement)&&!N.current?.contains(document.activeElement)&&(w(),i&&P(t?t.label:""))})},ue={maxHeight:typeof b=="number"?`${b}px`:b},Q={"aria-label":S,"aria-expanded":m,"data-testid":q("listbox"),id:`${l}-listbox`,ref:N,onMouseLeave:()=>v(void 0),style:b?ue:void 0},W=e=>`${l}-listbox-item-${e.id}`,le=(e,o)=>{const s=()=>e.id!==c?.id&&v({...e,isSetByClickEvent:!0}),f=(e.id===c?.id||!!n&&!c&&o===0)&&!c?.isSetByClickEvent;return{"data-testid":q(`listbox-item-${e.id}`),id:W(e),key:e.id,onMouseMove:s,onMouseUp:()=>J(e),ref:X=>{X&&(O.current[e.id]=X)},tabIndex:-1,selected:e.id===t?.id,disabled:e.disabled,highlighted:f,hovered:e.id===c?.id&&!!c?.isSetByClickEvent}},ae={"aria-activedescendant":c?W(c):void 0,"aria-autocomplete":"list","aria-controls":Q.id,"data-testid":q("input"),autoComplete:"off",id:`${l}-input`,onChange:se,onMouseDown:ce,onFocus:re,onKeyDown:ne,onBlur:ie,ref:B,role:"combobox",value:F};return{id:l,inputProps:ae,internalRef:U,optionsToShow:d,showListbox:m,noOptionsText:E,combobox:i,comboboxButtonAriaLabel:x,getListBoxItemProps:le,listboxProps:Q}},j=be.c.bind(me),I="purpur-autocomplete",ve=({className:i,renderInput:x,renderOption:n,..._},u)=>{const{id:R,inputProps:l,internalRef:S,optionsToShow:b,showListbox:h,noOptionsText:L,combobox:D,comboboxButtonAriaLabel:k,getListBoxItemProps:$,listboxProps:A}=Z(_),E=(t,y)=>{const{key:C,...K}=$(t,y);return p.jsx(M.Listbox.Item,{...K,children:n?n?.(t):t.label},C)},T=t=>{S.current=t,typeof u=="function"?u(t):u&&(u.current=t)},a=()=>{const t=x(l);if(D&&k&&L&&t&&pe.isTextField(t)){const C=p.jsxs(p.Fragment,{children:[t.props.endAdornment,p.jsx("button",{"data-testid":"chevron button",type:"button",className:j(`${I}__chevron-button`),onClick:()=>{l.onFocus(void 0),l.onMouseDown(void 0)},"aria-label":k,"aria-expanded":h,"aria-controls":A.id,children:p.jsx(de.l,{size:"sm",className:j(`${I}__chevron-icon`,{[`${I}__chevron-icon--up`]:h})})})]});return r.cloneElement(t,{endAdornment:C})}return t};return p.jsxs("div",{id:R,ref:T,className:j([I,i]),children:[a(),h&&p.jsx(M.Listbox,{...A,className:j(`${I}__listbox`),children:b.length?b.filter(t=>!!t).map(E):p.jsx(M.Listbox.Item,{noninteractive:!0,children:L})})]})},H=r.forwardRef(ve);H.displayName="Autocomplete";exports.Autocomplete=H;exports.useAutocomplete=Z;
2
- //# sourceMappingURL=autocomplete-yD0-1vlF.js.map
1
+ "use strict";const p=require("react/jsx-runtime"),r=require("react"),de=require("./chevron-down.es-BMjgiS3F.js"),M=require("./listbox-BmjBtIv8.js"),pe=require("./text-field-Xt6T3zjO.js"),be=require("./bind-DeUYJ6m9.js"),me={"purpur-autocomplete":"_purpur-autocomplete_dgjyz_1","purpur-autocomplete__listbox":"_purpur-autocomplete__listbox_dgjyz_4","purpur-autocomplete__chevron-button":"_purpur-autocomplete__chevron-button_dgjyz_9","purpur-autocomplete__chevron-icon":"_purpur-autocomplete__chevron-icon_dgjyz_15","purpur-autocomplete__chevron-icon--up":"_purpur-autocomplete__chevron-icon--up_dgjyz_20"},fe=i=>r.useRef(i),xe=(i,x)=>{const n=r.useCallback(_=>{i&&!i.contains(_.target)&&x()},[x,i]);r.useEffect(()=>(document.addEventListener("mousedown",n),()=>{document.removeEventListener("mousedown",n)}),[n])},Z=({combobox:i,comboboxButtonAriaLabel:x,highlightFirstOption:n,defaultInputValue:_,inputValue:u,filterOption:R,id:l,listboxLabel:S,listboxMaxHeight:b,onInputBlur:h,onInputChange:L,onInputFocus:D,onInputKeyDown:k,onInputMouseDown:$,openOnFocus:A,noOptionsText:E,onSelect:T,options:a,selectedOption:t,["data-testid"]:y})=>{const[C,K]=r.useState(((typeof u=="string"?u:_)||t?.label)??""),F=typeof u=="string"?u:C,[c,v]=r.useState(n?a[0]:void 0),B=r.useRef(null),U=fe(null),N=r.useRef(null),O=r.useRef({}),[V,Y]=r.useState(!1);function q(e){return y?`${y}-${e}`:void 0}const w=()=>{Y(!1),v(void 0)};xe(U.current,w);const g=({eventType:e})=>{Y(!0),t&&requestAnimationFrame(()=>{v({...t,isSetByClickEvent:e==="CLICK"}),z(O.current[t.id])})},ee=e=>{if(R)return a.filter(s=>R(e,s));if(!e)return a;const o=e.toUpperCase().split(" ")||[];return a.filter(s=>o.every(f=>(s.value||s.label).toUpperCase().includes(f)))},G=e=>t&&t?.label===e?a:ee(e),d=G(F),P=e=>{L?.(e),K(e)},z=e=>{if(e){const o=e.getBoundingClientRect(),s=N.current?.getBoundingClientRect()||{top:0,bottom:0};(o.top<s.top||o.bottom>s.bottom)&&e.scrollIntoView({block:"nearest"})}},J=e=>{e&&(B.current?.focus(),P(e.label),T?.(e)),w()},te=e=>{const o=n&&!c?0:d.findIndex(f=>f&&c?.id===f.id),s=d.length;return e==="ArrowDown"?d[(o??-1)+1]||d[0]:d[(o??s)-1]||d[s-1]},m=V&&(!!d.length||!!E),oe=e=>{!m&&g({eventType:"KEYBOARD"});const o=te(e);v(o),o&&z(O.current[o.id])},ne=e=>{switch(k?.(e),e.key){case"ArrowUp":case"ArrowDown":e.preventDefault(),oe(e.key);break;case"Enter":{const o=c||(n?a[0]:void 0);m&&J(o),!m&&g({eventType:"KEYBOARD"});break}case"Escape":case"Tab":w();break}},se=e=>{const o=G(e.target.value);P(e.target.value),v(void 0),!m&&g({eventType:"KEYBOARD"}),n&&o[0]&&z(O.current[o[0].id])},ce=e=>{$?.(e),m?w():g({eventType:"CLICK"})},re=e=>{D?.(e),!V&&A&&g({eventType:"KEYBOARD"}),B.current?.select()},ie=e=>{h?.(e),setTimeout(()=>{!B.current?.contains(document.activeElement)&&!N.current?.contains(document.activeElement)&&(w(),i&&P(t?t.label:""))})},ue={maxHeight:typeof b=="number"?`${b}px`:b},Q={"aria-label":S,"aria-expanded":m,"data-testid":q("listbox"),id:`${l}-listbox`,ref:N,onMouseLeave:()=>v(void 0),style:b?ue:void 0},W=e=>`${l}-listbox-item-${e.id}`,le=(e,o)=>{const s=()=>e.id!==c?.id&&v({...e,isSetByClickEvent:!0}),f=(e.id===c?.id||!!n&&!c&&o===0)&&!c?.isSetByClickEvent;return{"data-testid":q(`listbox-item-${e.id}`),id:W(e),key:e.id,onMouseMove:s,onMouseUp:()=>J(e),ref:X=>{X&&(O.current[e.id]=X)},tabIndex:-1,selected:e.id===t?.id,disabled:e.disabled,highlighted:f,hovered:e.id===c?.id&&!!c?.isSetByClickEvent}},ae={"aria-activedescendant":c?W(c):void 0,"aria-autocomplete":"list","aria-controls":Q.id,"data-testid":q("input"),autoComplete:"off",id:`${l}-input`,onChange:se,onMouseDown:ce,onFocus:re,onKeyDown:ne,onBlur:ie,ref:B,role:"combobox",value:F};return{id:l,inputProps:ae,internalRef:U,optionsToShow:d,showListbox:m,noOptionsText:E,combobox:i,comboboxButtonAriaLabel:x,getListBoxItemProps:le,listboxProps:Q}},j=be.c.bind(me),I="purpur-autocomplete",ve=({className:i,renderInput:x,renderOption:n,..._},u)=>{const{id:R,inputProps:l,internalRef:S,optionsToShow:b,showListbox:h,noOptionsText:L,combobox:D,comboboxButtonAriaLabel:k,getListBoxItemProps:$,listboxProps:A}=Z(_),E=(t,y)=>{const{key:C,...K}=$(t,y);return p.jsx(M.Listbox.Item,{...K,children:n?n?.(t):t.label},C)},T=t=>{S.current=t,typeof u=="function"?u(t):u&&(u.current=t)},a=()=>{const t=x(l);if(D&&k&&L&&t&&pe.isTextField(t)){const C=p.jsxs(p.Fragment,{children:[t.props.endAdornment,p.jsx("button",{"data-testid":"chevron button",type:"button",className:j(`${I}__chevron-button`),onClick:()=>{l.onFocus(void 0),l.onMouseDown(void 0)},"aria-label":k,"aria-expanded":h,"aria-controls":A.id,children:p.jsx(de.l,{size:"sm",className:j(`${I}__chevron-icon`,{[`${I}__chevron-icon--up`]:h})})})]});return r.cloneElement(t,{endAdornment:C})}return t};return p.jsxs("div",{id:R,ref:T,className:j([I,i]),children:[a(),h&&p.jsx(M.Listbox,{...A,className:j(`${I}__listbox`),children:b.length?b.filter(t=>!!t).map(E):p.jsx(M.Listbox.Item,{noninteractive:!0,children:L})})]})},H=r.forwardRef(ve);H.displayName="Autocomplete";exports.Autocomplete=H;exports.useAutocomplete=Z;
2
+ //# sourceMappingURL=autocomplete-6qSqK3SI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-yD0-1vlF.js","sources":["../../../components/autocomplete/src/utils.ts","../../../components/autocomplete/src/useAutocomplete.ts","../../../components/autocomplete/src/autocomplete.tsx"],"sourcesContent":["import { type RefObject, useCallback, useEffect, useRef } from \"react\";\n\n// Used to \"merge\" \"intersection types\". Used to get comments on the props to the docs.\nexport type Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport const useRefObject = <T>(value: T): RefObject<T> => {\n return useRef<T>(value) as RefObject<T>;\n};\n\nexport const useOnClickOutside = (element: HTMLElement | null, callback: () => void) => {\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (element && !element.contains(event.target as Node)) {\n callback();\n }\n },\n [callback, element]\n );\n\n useEffect(() => {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [handleClickOutside]);\n};\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useRef, useState } from \"react\";\nimport type { BaseProps } from \"@purpur/common-types\";\nimport type { ListboxItemProps, ListboxProps } from \"@purpur/listbox\";\n\nimport { useOnClickOutside, useRefObject } from \"./utils\";\n\nexport type AutocompleteOption = {\n label: string;\n id: string;\n value?: string;\n disabled?: boolean;\n};\n\nexport type InputProps = Omit<BaseProps<\"input\">, \"onFocus\" | \"onMouseDown\"> & {\n onFocus: (event: React.FocusEvent<HTMLInputElement> | undefined) => void;\n onMouseDown: (event: React.MouseEvent<HTMLInputElement> | undefined) => void;\n};\n\ntype ComboboxProps = {\n /*\n * Set to get combobox features. Use in combination with `noOptionsText`, `comboboxButtonAriaLabel` and Purpur TextField.\n */\n combobox: true;\n /**\n * An accessible label for the button that toggles the list of options for a combobox.\n * */\n comboboxButtonAriaLabel: string;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText: ReactNode;\n};\n\ntype NoComboboxProps = {\n combobox?: never;\n comboboxButtonAriaLabel?: never;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText?: ReactNode;\n};\n\nexport type UseAutocompleteResult<T extends AutocompleteOption> = {\n /*\n * Set to highlight the first option in the listbox when the input is focused.\n */\n highlightFirstOption?: boolean;\n /*\n * The default input value. Only to use when the input is uncontrolled.\n */\n defaultInputValue?: string;\n /*\n * The input value. Use this to control the input value.\n */\n inputValue?: string;\n /*\n * Invoked for each option. Use to control which options are shown.\n */\n filterOption?: (inputValue: string | undefined, option: T) => boolean;\n /*\n * Id will be used to prefix id:s of all elements.\n */\n id: string;\n /*\n * The label of the listbox (dropdown) displaying the options.\n */\n listboxLabel: string;\n /*\n * The height of the listbox. Number will be interpreted as px value. defaults to `calc(2 * var(--purpur-spacing-1200))`.\n */\n listboxMaxHeight?: string | number;\n /*\n * NOTE! Always use this instead of onBlur directly on the input element. Event handler invoked on input blur.\n */\n onInputBlur?: React.FocusEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onChange directly on the input element. Event handler invoked when the input value changes.\n */\n onInputChange?: (value: string) => void;\n /*\n * NOTE! Always use this instead of onFocus directly on the input element. Event handler invoked on input focus.\n */\n onInputFocus?: (event: React.FocusEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * NOTE! Always use this instead of onKeyDown directly on the input element. Event handler invoked on input key down.\n */\n onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onMouseDown directly on the input element. Event handler invoked on input mouse down.\n */\n onInputMouseDown?: (event: React.MouseEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * Set to open the listbox when input gets focus.\n */\n openOnFocus?: boolean;\n /*\n * Event handler invoked when an option is selected.\n */\n onSelect?: (option: T | undefined) => void;\n /*\n * The list of options. Could include custom props.\n */\n options: T[];\n /*\n * The selected option.\n */\n selectedOption?: T;\n [\"data-testid\"]?: string;\n} & (ComboboxProps | NoComboboxProps);\n\nexport const useAutocomplete = <T extends AutocompleteOption>({\n combobox,\n comboboxButtonAriaLabel,\n highlightFirstOption,\n defaultInputValue,\n inputValue,\n filterOption,\n id,\n listboxLabel,\n listboxMaxHeight,\n onInputBlur,\n onInputChange,\n onInputFocus,\n onInputKeyDown,\n onInputMouseDown,\n openOnFocus,\n noOptionsText,\n onSelect,\n options,\n selectedOption,\n [\"data-testid\"]: dataTestid,\n}: UseAutocompleteResult<T>) => {\n const [internalInputValue, setInternalInputValue] = useState(\n ((typeof inputValue === \"string\" ? inputValue : defaultInputValue) || selectedOption?.label) ??\n \"\"\n );\n const definiteInputValue = typeof inputValue === \"string\" ? inputValue : internalInputValue;\n const [highlightedOption, setHighlightedOption] = useState<\n (T & { isSetByClickEvent?: false }) | undefined\n >(highlightFirstOption ? options[0] : undefined);\n const inputRef = useRef<HTMLInputElement>(null);\n const internalRef = useRefObject<HTMLDivElement | null>(null);\n const listboxRef = useRef<HTMLUListElement>(null);\n const optionRefs = useRef<Record<string, HTMLLIElement>>({});\n const [listboxIsOpen, setListboxIsOpen] = useState(false);\n\n function getTestId(name: string) {\n return dataTestid ? `${dataTestid}-${name}` : undefined;\n }\n\n const closeListbox = () => {\n setListboxIsOpen(false);\n setHighlightedOption(undefined);\n };\n\n useOnClickOutside(internalRef.current, closeListbox);\n\n const openListbox = ({ eventType }: { eventType: \"CLICK\" | \"KEYBOARD\" }) => {\n setListboxIsOpen(true);\n if (selectedOption) {\n requestAnimationFrame(() => {\n const isSetByClickEvent = eventType === \"CLICK\";\n setHighlightedOption({ ...selectedOption, isSetByClickEvent });\n scrollOptionIntoView(optionRefs.current[selectedOption.id]);\n });\n }\n };\n\n const filterOptions = (searchTerm: string | undefined) => {\n if (filterOption) {\n return options.filter((option) => filterOption(searchTerm, option));\n }\n\n if (!searchTerm) {\n return options;\n }\n\n const searchTermChunks = searchTerm.toUpperCase().split(\" \") || [];\n return options.filter((option) =>\n searchTermChunks.every((chunk) =>\n (option.value || option.label).toUpperCase().includes(chunk)\n )\n );\n };\n\n const getOptionsToShow = (searchTerm: string | undefined): (T | undefined)[] => {\n return selectedOption && selectedOption?.label === searchTerm\n ? options\n : filterOptions(searchTerm);\n };\n\n const optionsToShow = getOptionsToShow(definiteInputValue);\n\n const populateInputField = (value: string) => {\n onInputChange?.(value);\n setInternalInputValue(value);\n };\n\n const scrollOptionIntoView = (option: HTMLLIElement | undefined) => {\n if (option) {\n const optionRect = option.getBoundingClientRect();\n const listboxRect = listboxRef.current?.getBoundingClientRect() || { top: 0, bottom: 0 };\n const isOptionOutsideView =\n optionRect.top < listboxRect.top || optionRect.bottom > listboxRect.bottom;\n if (isOptionOutsideView) {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }\n };\n\n const selectOption = (option: T | undefined) => {\n if (option) {\n inputRef.current?.focus();\n populateInputField(option.label);\n onSelect?.(option);\n }\n closeListbox();\n };\n\n const findNextOption = (key: \"ArrowUp\" | \"ArrowDown\"): T | undefined => {\n const index =\n highlightFirstOption && !highlightedOption\n ? 0\n : optionsToShow.findIndex((option) => option && highlightedOption?.id === option.id);\n\n const optionsLength = optionsToShow.length;\n\n return key === \"ArrowDown\"\n ? optionsToShow[(index ?? -1) + 1] || optionsToShow[0]\n : optionsToShow[(index ?? optionsLength) - 1] || optionsToShow[optionsLength - 1];\n };\n\n const showListbox = listboxIsOpen && (!!optionsToShow.length || !!noOptionsText);\n\n const highlightNextOption = (key: \"ArrowUp\" | \"ArrowDown\") => {\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n const nextOption = findNextOption(key);\n\n setHighlightedOption(nextOption);\n nextOption && scrollOptionIntoView(optionRefs.current[nextOption.id]);\n };\n\n const handleOnKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {\n onInputKeyDown?.(event);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowDown\":\n event.preventDefault(); // Preventing default to not move cursor in input\n highlightNextOption(event.key);\n break;\n case \"Enter\": {\n const optionToSelect = highlightedOption || (highlightFirstOption ? options[0] : undefined);\n showListbox && selectOption(optionToSelect);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n break;\n }\n case \"Escape\":\n case \"Tab\":\n closeListbox();\n break;\n }\n };\n\n const handleOnChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const nextOptionsToShow = getOptionsToShow(e.target.value);\n populateInputField(e.target.value);\n setHighlightedOption(undefined);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n highlightFirstOption &&\n nextOptionsToShow[0] &&\n scrollOptionIntoView(optionRefs.current[nextOptionsToShow[0].id]);\n };\n\n const handleOnMouseDown = (event: React.MouseEvent<HTMLInputElement> | undefined) => {\n onInputMouseDown?.(event);\n showListbox ? closeListbox() : openListbox({ eventType: \"CLICK\" });\n };\n\n const handleOnFocus = (event: React.FocusEvent<HTMLInputElement> | undefined) => {\n onInputFocus?.(event);\n !listboxIsOpen && openOnFocus && openListbox({ eventType: \"KEYBOARD\" });\n inputRef.current?.select();\n };\n\n const handleOnBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {\n onInputBlur?.(event);\n // Use a timeout to allow click events on the listbox to fire before this check\n setTimeout(() => {\n if (\n !inputRef.current?.contains(document.activeElement) &&\n !listboxRef.current?.contains(document.activeElement)\n ) {\n closeListbox();\n\n // If the blur happened due to a click inside the listbox for a combobox, don't reset the value\n if (combobox) {\n populateInputField(selectedOption ? selectedOption.label : \"\");\n }\n }\n });\n };\n\n const listboxStyle: CSSProperties = {\n maxHeight: typeof listboxMaxHeight === \"number\" ? `${listboxMaxHeight}px` : listboxMaxHeight,\n };\n\n const listboxProps: ListboxProps = {\n \"aria-label\": listboxLabel,\n \"aria-expanded\": showListbox,\n \"data-testid\": getTestId(\"listbox\"),\n id: `${id}-listbox`,\n ref: listboxRef,\n onMouseLeave: () => setHighlightedOption(undefined),\n style: listboxMaxHeight ? listboxStyle : undefined,\n };\n\n const createListboxItemId = (option: T) => `${id}-listbox-item-${option.id}`;\n\n const getListBoxItemProps = (option: T, index: number): ListboxItemProps => {\n const handleOnMouseMove = () =>\n option.id !== highlightedOption?.id &&\n setHighlightedOption({ ...option, isSetByClickEvent: true });\n\n const highlighted =\n (option.id === highlightedOption?.id ||\n (!!highlightFirstOption && !highlightedOption && index === 0)) &&\n !highlightedOption?.isSetByClickEvent;\n\n return {\n \"data-testid\": getTestId(`listbox-item-${option.id}`),\n id: createListboxItemId(option),\n key: option.id,\n onMouseMove: handleOnMouseMove,\n onMouseUp: () => selectOption(option),\n ref: (el) => {\n if (el) {\n optionRefs.current[option.id] = el;\n }\n },\n tabIndex: -1,\n selected: option.id === selectedOption?.id,\n disabled: option.disabled,\n highlighted,\n hovered: option.id === highlightedOption?.id && !!highlightedOption?.isSetByClickEvent,\n };\n };\n\n const inputProps: InputProps = {\n \"aria-activedescendant\": highlightedOption ? createListboxItemId(highlightedOption) : undefined,\n \"aria-autocomplete\": \"list\",\n \"aria-controls\": listboxProps.id,\n \"data-testid\": getTestId(\"input\"),\n autoComplete: \"off\",\n id: `${id}-input`,\n onChange: handleOnChange,\n onMouseDown: handleOnMouseDown,\n onFocus: handleOnFocus,\n onKeyDown: handleOnKeyDown,\n onBlur: handleOnBlur,\n ref: inputRef,\n role: \"combobox\",\n value: definiteInputValue,\n };\n\n return {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n };\n};\n","import type { ComponentPropsWithRef, ForwardedRef, ReactNode } from \"react\";\nimport React, { cloneElement, forwardRef } from \"react\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Listbox } from \"@purpur/listbox\";\nimport { isTextField } from \"@purpur/text-field\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./autocomplete.module.scss\";\nimport type { AutocompleteOption, UseAutocompleteResult } from \"./useAutocomplete\";\nimport { useAutocomplete } from \"./useAutocomplete\";\nimport type { Prettify } from \"./utils\";\n\nconst cx = c.bind(styles);\n\ntype AutocompleteProps<T extends AutocompleteOption> = Prettify<\n UseAutocompleteResult<T> & {\n className?: string;\n /**\n * Render the input. `props` are native input props\n */\n renderInput: (props: ComponentPropsWithRef<\"input\">) => ReactNode;\n /**\n * Invoked for each given option. Use to customize the rendering of the options\n */\n renderOption?: (option: T) => ReactNode;\n }\n>;\n\nconst rootClassName = \"purpur-autocomplete\";\n\nconst AutocompleteComponent = <T extends AutocompleteOption>(\n { className, renderInput, renderOption, ...useAutocompleteProps }: AutocompleteProps<T>,\n ref: ForwardedRef<HTMLDivElement>\n) => {\n const {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n } = useAutocomplete(useAutocompleteProps);\n\n const renderListboxItem = (option: T, index: number) => {\n const { key, ...listboxItemProps } = getListBoxItemProps(option, index);\n\n return (\n <Listbox.Item key={key} {...listboxItemProps}>\n {renderOption ? renderOption?.(option) : option.label}\n </Listbox.Item>\n );\n };\n\n const setRootRef = (node: HTMLDivElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n };\n\n const getInputComponent = () => {\n const input = renderInput(inputProps);\n const isCombobox =\n combobox && comboboxButtonAriaLabel && noOptionsText && input && isTextField(input);\n\n if (isCombobox) {\n const endAdornment = (\n <>\n {input.props.endAdornment}\n <button\n data-testid=\"chevron button\"\n type=\"button\"\n className={cx(`${rootClassName}__chevron-button`)}\n onClick={() => {\n inputProps.onFocus(undefined);\n inputProps.onMouseDown(undefined);\n }}\n aria-label={comboboxButtonAriaLabel}\n aria-expanded={showListbox}\n aria-controls={listboxProps.id}\n >\n <IconChevronDown\n size=\"sm\"\n className={cx(`${rootClassName}__chevron-icon`, {\n [`${rootClassName}__chevron-icon--up`]: showListbox,\n })}\n />\n </button>\n </>\n );\n\n return cloneElement(input, { endAdornment });\n }\n\n return input;\n };\n\n return (\n <div id={id} ref={setRootRef} className={cx([rootClassName, className])}>\n {getInputComponent()}\n {showListbox && (\n <Listbox {...listboxProps} className={cx(`${rootClassName}__listbox`)}>\n {!optionsToShow.length ? (\n <Listbox.Item noninteractive>{noOptionsText}</Listbox.Item>\n ) : (\n optionsToShow.filter((option): option is T => !!option).map(renderListboxItem)\n )}\n </Listbox>\n )}\n </div>\n );\n};\n\nexport const Autocomplete = forwardRef(AutocompleteComponent);\nAutocomplete.displayName = \"Autocomplete\";\n\nexport type {\n AutocompleteOption,\n UseAutocompleteResult as UseAutocompleteOptions,\n} from \"./useAutocomplete\";\nexport { useAutocomplete } from \"./useAutocomplete\";\n"],"names":["useRefObject","value","useRef","useOnClickOutside","element","callback","handleClickOutside","useCallback","event","useEffect","useAutocomplete","combobox","comboboxButtonAriaLabel","highlightFirstOption","defaultInputValue","inputValue","filterOption","id","listboxLabel","listboxMaxHeight","onInputBlur","onInputChange","onInputFocus","onInputKeyDown","onInputMouseDown","openOnFocus","noOptionsText","onSelect","options","selectedOption","dataTestid","internalInputValue","setInternalInputValue","useState","definiteInputValue","highlightedOption","setHighlightedOption","inputRef","internalRef","listboxRef","optionRefs","listboxIsOpen","setListboxIsOpen","getTestId","name","closeListbox","openListbox","eventType","scrollOptionIntoView","filterOptions","searchTerm","option","searchTermChunks","chunk","getOptionsToShow","optionsToShow","populateInputField","optionRect","listboxRect","selectOption","findNextOption","key","index","optionsLength","showListbox","highlightNextOption","nextOption","handleOnKeyDown","optionToSelect","handleOnChange","nextOptionsToShow","handleOnMouseDown","handleOnFocus","handleOnBlur","listboxStyle","listboxProps","createListboxItemId","getListBoxItemProps","handleOnMouseMove","highlighted","el","inputProps","cx","c","styles","rootClassName","AutocompleteComponent","className","renderInput","renderOption","useAutocompleteProps","ref","renderListboxItem","listboxItemProps","jsx","Listbox","setRootRef","node","getInputComponent","input","isTextField","endAdornment","jsxs","Fragment","IconChevronDown","cloneElement","Autocomplete","forwardRef"],"mappings":"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"}
1
+ {"version":3,"file":"autocomplete-6qSqK3SI.js","sources":["../../../components/autocomplete/src/utils.ts","../../../components/autocomplete/src/useAutocomplete.ts","../../../components/autocomplete/src/autocomplete.tsx"],"sourcesContent":["import { type RefObject, useCallback, useEffect, useRef } from \"react\";\n\n// Used to \"merge\" \"intersection types\". Used to get comments on the props to the docs.\nexport type Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport const useRefObject = <T>(value: T): RefObject<T> => {\n return useRef<T>(value) as RefObject<T>;\n};\n\nexport const useOnClickOutside = (element: HTMLElement | null, callback: () => void) => {\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (element && !element.contains(event.target as Node)) {\n callback();\n }\n },\n [callback, element]\n );\n\n useEffect(() => {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [handleClickOutside]);\n};\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useRef, useState } from \"react\";\nimport type { BaseProps } from \"@purpur/common-types\";\nimport type { ListboxItemProps, ListboxProps } from \"@purpur/listbox\";\n\nimport { useOnClickOutside, useRefObject } from \"./utils\";\n\nexport type AutocompleteOption = {\n label: string;\n id: string;\n value?: string;\n disabled?: boolean;\n};\n\nexport type InputProps = Omit<BaseProps<\"input\">, \"onFocus\" | \"onMouseDown\"> & {\n onFocus: (event: React.FocusEvent<HTMLInputElement> | undefined) => void;\n onMouseDown: (event: React.MouseEvent<HTMLInputElement> | undefined) => void;\n};\n\ntype ComboboxProps = {\n /*\n * Set to get combobox features. Use in combination with `noOptionsText`, `comboboxButtonAriaLabel` and Purpur TextField.\n */\n combobox: true;\n /**\n * An accessible label for the button that toggles the list of options for a combobox.\n * */\n comboboxButtonAriaLabel: string;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText: ReactNode;\n};\n\ntype NoComboboxProps = {\n combobox?: never;\n comboboxButtonAriaLabel?: never;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText?: ReactNode;\n};\n\nexport type UseAutocompleteResult<T extends AutocompleteOption> = {\n /*\n * Set to highlight the first option in the listbox when the input is focused.\n */\n highlightFirstOption?: boolean;\n /*\n * The default input value. Only to use when the input is uncontrolled.\n */\n defaultInputValue?: string;\n /*\n * The input value. Use this to control the input value.\n */\n inputValue?: string;\n /*\n * Invoked for each option. Use to control which options are shown.\n */\n filterOption?: (inputValue: string | undefined, option: T) => boolean;\n /*\n * Id will be used to prefix id:s of all elements.\n */\n id: string;\n /*\n * The label of the listbox (dropdown) displaying the options.\n */\n listboxLabel: string;\n /*\n * The height of the listbox. Number will be interpreted as px value. defaults to `calc(2 * var(--purpur-spacing-1200))`.\n */\n listboxMaxHeight?: string | number;\n /*\n * NOTE! Always use this instead of onBlur directly on the input element. Event handler invoked on input blur.\n */\n onInputBlur?: React.FocusEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onChange directly on the input element. Event handler invoked when the input value changes.\n */\n onInputChange?: (value: string) => void;\n /*\n * NOTE! Always use this instead of onFocus directly on the input element. Event handler invoked on input focus.\n */\n onInputFocus?: (event: React.FocusEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * NOTE! Always use this instead of onKeyDown directly on the input element. Event handler invoked on input key down.\n */\n onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onMouseDown directly on the input element. Event handler invoked on input mouse down.\n */\n onInputMouseDown?: (event: React.MouseEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * Set to open the listbox when input gets focus.\n */\n openOnFocus?: boolean;\n /*\n * Event handler invoked when an option is selected.\n */\n onSelect?: (option: T | undefined) => void;\n /*\n * The list of options. Could include custom props.\n */\n options: T[];\n /*\n * The selected option.\n */\n selectedOption?: T;\n [\"data-testid\"]?: string;\n} & (ComboboxProps | NoComboboxProps);\n\nexport const useAutocomplete = <T extends AutocompleteOption>({\n combobox,\n comboboxButtonAriaLabel,\n highlightFirstOption,\n defaultInputValue,\n inputValue,\n filterOption,\n id,\n listboxLabel,\n listboxMaxHeight,\n onInputBlur,\n onInputChange,\n onInputFocus,\n onInputKeyDown,\n onInputMouseDown,\n openOnFocus,\n noOptionsText,\n onSelect,\n options,\n selectedOption,\n [\"data-testid\"]: dataTestid,\n}: UseAutocompleteResult<T>) => {\n const [internalInputValue, setInternalInputValue] = useState(\n ((typeof inputValue === \"string\" ? inputValue : defaultInputValue) || selectedOption?.label) ??\n \"\"\n );\n const definiteInputValue = typeof inputValue === \"string\" ? inputValue : internalInputValue;\n const [highlightedOption, setHighlightedOption] = useState<\n (T & { isSetByClickEvent?: false }) | undefined\n >(highlightFirstOption ? options[0] : undefined);\n const inputRef = useRef<HTMLInputElement>(null);\n const internalRef = useRefObject<HTMLDivElement | null>(null);\n const listboxRef = useRef<HTMLUListElement>(null);\n const optionRefs = useRef<Record<string, HTMLLIElement>>({});\n const [listboxIsOpen, setListboxIsOpen] = useState(false);\n\n function getTestId(name: string) {\n return dataTestid ? `${dataTestid}-${name}` : undefined;\n }\n\n const closeListbox = () => {\n setListboxIsOpen(false);\n setHighlightedOption(undefined);\n };\n\n useOnClickOutside(internalRef.current, closeListbox);\n\n const openListbox = ({ eventType }: { eventType: \"CLICK\" | \"KEYBOARD\" }) => {\n setListboxIsOpen(true);\n if (selectedOption) {\n requestAnimationFrame(() => {\n const isSetByClickEvent = eventType === \"CLICK\";\n setHighlightedOption({ ...selectedOption, isSetByClickEvent });\n scrollOptionIntoView(optionRefs.current[selectedOption.id]);\n });\n }\n };\n\n const filterOptions = (searchTerm: string | undefined) => {\n if (filterOption) {\n return options.filter((option) => filterOption(searchTerm, option));\n }\n\n if (!searchTerm) {\n return options;\n }\n\n const searchTermChunks = searchTerm.toUpperCase().split(\" \") || [];\n return options.filter((option) =>\n searchTermChunks.every((chunk) =>\n (option.value || option.label).toUpperCase().includes(chunk)\n )\n );\n };\n\n const getOptionsToShow = (searchTerm: string | undefined): (T | undefined)[] => {\n return selectedOption && selectedOption?.label === searchTerm\n ? options\n : filterOptions(searchTerm);\n };\n\n const optionsToShow = getOptionsToShow(definiteInputValue);\n\n const populateInputField = (value: string) => {\n onInputChange?.(value);\n setInternalInputValue(value);\n };\n\n const scrollOptionIntoView = (option: HTMLLIElement | undefined) => {\n if (option) {\n const optionRect = option.getBoundingClientRect();\n const listboxRect = listboxRef.current?.getBoundingClientRect() || { top: 0, bottom: 0 };\n const isOptionOutsideView =\n optionRect.top < listboxRect.top || optionRect.bottom > listboxRect.bottom;\n if (isOptionOutsideView) {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }\n };\n\n const selectOption = (option: T | undefined) => {\n if (option) {\n inputRef.current?.focus();\n populateInputField(option.label);\n onSelect?.(option);\n }\n closeListbox();\n };\n\n const findNextOption = (key: \"ArrowUp\" | \"ArrowDown\"): T | undefined => {\n const index =\n highlightFirstOption && !highlightedOption\n ? 0\n : optionsToShow.findIndex((option) => option && highlightedOption?.id === option.id);\n\n const optionsLength = optionsToShow.length;\n\n return key === \"ArrowDown\"\n ? optionsToShow[(index ?? -1) + 1] || optionsToShow[0]\n : optionsToShow[(index ?? optionsLength) - 1] || optionsToShow[optionsLength - 1];\n };\n\n const showListbox = listboxIsOpen && (!!optionsToShow.length || !!noOptionsText);\n\n const highlightNextOption = (key: \"ArrowUp\" | \"ArrowDown\") => {\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n const nextOption = findNextOption(key);\n\n setHighlightedOption(nextOption);\n nextOption && scrollOptionIntoView(optionRefs.current[nextOption.id]);\n };\n\n const handleOnKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {\n onInputKeyDown?.(event);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowDown\":\n event.preventDefault(); // Preventing default to not move cursor in input\n highlightNextOption(event.key);\n break;\n case \"Enter\": {\n const optionToSelect = highlightedOption || (highlightFirstOption ? options[0] : undefined);\n showListbox && selectOption(optionToSelect);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n break;\n }\n case \"Escape\":\n case \"Tab\":\n closeListbox();\n break;\n }\n };\n\n const handleOnChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const nextOptionsToShow = getOptionsToShow(e.target.value);\n populateInputField(e.target.value);\n setHighlightedOption(undefined);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n highlightFirstOption &&\n nextOptionsToShow[0] &&\n scrollOptionIntoView(optionRefs.current[nextOptionsToShow[0].id]);\n };\n\n const handleOnMouseDown = (event: React.MouseEvent<HTMLInputElement> | undefined) => {\n onInputMouseDown?.(event);\n showListbox ? closeListbox() : openListbox({ eventType: \"CLICK\" });\n };\n\n const handleOnFocus = (event: React.FocusEvent<HTMLInputElement> | undefined) => {\n onInputFocus?.(event);\n !listboxIsOpen && openOnFocus && openListbox({ eventType: \"KEYBOARD\" });\n inputRef.current?.select();\n };\n\n const handleOnBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {\n onInputBlur?.(event);\n // Use a timeout to allow click events on the listbox to fire before this check\n setTimeout(() => {\n if (\n !inputRef.current?.contains(document.activeElement) &&\n !listboxRef.current?.contains(document.activeElement)\n ) {\n closeListbox();\n\n // If the blur happened due to a click inside the listbox for a combobox, don't reset the value\n if (combobox) {\n populateInputField(selectedOption ? selectedOption.label : \"\");\n }\n }\n });\n };\n\n const listboxStyle: CSSProperties = {\n maxHeight: typeof listboxMaxHeight === \"number\" ? `${listboxMaxHeight}px` : listboxMaxHeight,\n };\n\n const listboxProps: ListboxProps = {\n \"aria-label\": listboxLabel,\n \"aria-expanded\": showListbox,\n \"data-testid\": getTestId(\"listbox\"),\n id: `${id}-listbox`,\n ref: listboxRef,\n onMouseLeave: () => setHighlightedOption(undefined),\n style: listboxMaxHeight ? listboxStyle : undefined,\n };\n\n const createListboxItemId = (option: T) => `${id}-listbox-item-${option.id}`;\n\n const getListBoxItemProps = (option: T, index: number): ListboxItemProps => {\n const handleOnMouseMove = () =>\n option.id !== highlightedOption?.id &&\n setHighlightedOption({ ...option, isSetByClickEvent: true });\n\n const highlighted =\n (option.id === highlightedOption?.id ||\n (!!highlightFirstOption && !highlightedOption && index === 0)) &&\n !highlightedOption?.isSetByClickEvent;\n\n return {\n \"data-testid\": getTestId(`listbox-item-${option.id}`),\n id: createListboxItemId(option),\n key: option.id,\n onMouseMove: handleOnMouseMove,\n onMouseUp: () => selectOption(option),\n ref: (el) => {\n if (el) {\n optionRefs.current[option.id] = el;\n }\n },\n tabIndex: -1,\n selected: option.id === selectedOption?.id,\n disabled: option.disabled,\n highlighted,\n hovered: option.id === highlightedOption?.id && !!highlightedOption?.isSetByClickEvent,\n };\n };\n\n const inputProps: InputProps = {\n \"aria-activedescendant\": highlightedOption ? createListboxItemId(highlightedOption) : undefined,\n \"aria-autocomplete\": \"list\",\n \"aria-controls\": listboxProps.id,\n \"data-testid\": getTestId(\"input\"),\n autoComplete: \"off\",\n id: `${id}-input`,\n onChange: handleOnChange,\n onMouseDown: handleOnMouseDown,\n onFocus: handleOnFocus,\n onKeyDown: handleOnKeyDown,\n onBlur: handleOnBlur,\n ref: inputRef,\n role: \"combobox\",\n value: definiteInputValue,\n };\n\n return {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n };\n};\n","import type { ComponentPropsWithRef, ForwardedRef, ReactNode } from \"react\";\nimport React, { cloneElement, forwardRef } from \"react\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Listbox } from \"@purpur/listbox\";\nimport { isTextField } from \"@purpur/text-field\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./autocomplete.module.scss\";\nimport type { AutocompleteOption, UseAutocompleteResult } from \"./useAutocomplete\";\nimport { useAutocomplete } from \"./useAutocomplete\";\nimport type { Prettify } from \"./utils\";\n\nconst cx = c.bind(styles);\n\ntype AutocompleteProps<T extends AutocompleteOption> = Prettify<\n UseAutocompleteResult<T> & {\n className?: string;\n /**\n * Render the input. `props` are native input props\n */\n renderInput: (props: ComponentPropsWithRef<\"input\">) => ReactNode;\n /**\n * Invoked for each given option. Use to customize the rendering of the options\n */\n renderOption?: (option: T) => ReactNode;\n }\n>;\n\nconst rootClassName = \"purpur-autocomplete\";\n\nconst AutocompleteComponent = <T extends AutocompleteOption>(\n { className, renderInput, renderOption, ...useAutocompleteProps }: AutocompleteProps<T>,\n ref: ForwardedRef<HTMLDivElement>\n) => {\n const {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n } = useAutocomplete(useAutocompleteProps);\n\n const renderListboxItem = (option: T, index: number) => {\n const { key, ...listboxItemProps } = getListBoxItemProps(option, index);\n\n return (\n <Listbox.Item key={key} {...listboxItemProps}>\n {renderOption ? renderOption?.(option) : option.label}\n </Listbox.Item>\n );\n };\n\n const setRootRef = (node: HTMLDivElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n };\n\n const getInputComponent = () => {\n const input = renderInput(inputProps);\n const isCombobox =\n combobox && comboboxButtonAriaLabel && noOptionsText && input && isTextField(input);\n\n if (isCombobox) {\n const endAdornment = (\n <>\n {input.props.endAdornment}\n <button\n data-testid=\"chevron button\"\n type=\"button\"\n className={cx(`${rootClassName}__chevron-button`)}\n onClick={() => {\n inputProps.onFocus(undefined);\n inputProps.onMouseDown(undefined);\n }}\n aria-label={comboboxButtonAriaLabel}\n aria-expanded={showListbox}\n aria-controls={listboxProps.id}\n >\n <IconChevronDown\n size=\"sm\"\n className={cx(`${rootClassName}__chevron-icon`, {\n [`${rootClassName}__chevron-icon--up`]: showListbox,\n })}\n />\n </button>\n </>\n );\n\n return cloneElement(input, { endAdornment });\n }\n\n return input;\n };\n\n return (\n <div id={id} ref={setRootRef} className={cx([rootClassName, className])}>\n {getInputComponent()}\n {showListbox && (\n <Listbox {...listboxProps} className={cx(`${rootClassName}__listbox`)}>\n {!optionsToShow.length ? (\n <Listbox.Item noninteractive>{noOptionsText}</Listbox.Item>\n ) : (\n optionsToShow.filter((option): option is T => !!option).map(renderListboxItem)\n )}\n </Listbox>\n )}\n </div>\n );\n};\n\nexport const Autocomplete = forwardRef(AutocompleteComponent);\nAutocomplete.displayName = \"Autocomplete\";\n\nexport type {\n AutocompleteOption,\n UseAutocompleteResult as UseAutocompleteOptions,\n} from \"./useAutocomplete\";\nexport { useAutocomplete } from \"./useAutocomplete\";\n"],"names":["useRefObject","value","useRef","useOnClickOutside","element","callback","handleClickOutside","useCallback","event","useEffect","useAutocomplete","combobox","comboboxButtonAriaLabel","highlightFirstOption","defaultInputValue","inputValue","filterOption","id","listboxLabel","listboxMaxHeight","onInputBlur","onInputChange","onInputFocus","onInputKeyDown","onInputMouseDown","openOnFocus","noOptionsText","onSelect","options","selectedOption","dataTestid","internalInputValue","setInternalInputValue","useState","definiteInputValue","highlightedOption","setHighlightedOption","inputRef","internalRef","listboxRef","optionRefs","listboxIsOpen","setListboxIsOpen","getTestId","name","closeListbox","openListbox","eventType","scrollOptionIntoView","filterOptions","searchTerm","option","searchTermChunks","chunk","getOptionsToShow","optionsToShow","populateInputField","optionRect","listboxRect","selectOption","findNextOption","key","index","optionsLength","showListbox","highlightNextOption","nextOption","handleOnKeyDown","optionToSelect","handleOnChange","nextOptionsToShow","handleOnMouseDown","handleOnFocus","handleOnBlur","listboxStyle","listboxProps","createListboxItemId","getListBoxItemProps","handleOnMouseMove","highlighted","el","inputProps","cx","c","styles","rootClassName","AutocompleteComponent","className","renderInput","renderOption","useAutocompleteProps","ref","renderListboxItem","listboxItemProps","jsx","Listbox","setRootRef","node","getInputComponent","input","isTextField","endAdornment","jsxs","Fragment","IconChevronDown","cloneElement","Autocomplete","forwardRef"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { jsxs as H, jsx as g, Fragment as de } from "react/jsx-runtime";
2
2
  import { useRef as D, useCallback as pe, useEffect as me, useState as U, forwardRef as be, cloneElement as fe } from "react";
3
3
  import { l as ve } from "./chevron-down.es-PCIIj6oG.mjs";
4
- import { L as V } from "./listbox-u6__DsLw.mjs";
5
- import { i as _e } from "./text-field-PKAaXO1N.mjs";
4
+ import { L as V } from "./listbox-oDeP8FvH.mjs";
5
+ import { i as _e } from "./text-field-5rIuW8gc.mjs";
6
6
  import { c as xe } from "./bind-CU-R61T-.mjs";
7
7
  const he = {
8
8
  "purpur-autocomplete": "_purpur-autocomplete_dgjyz_1",
@@ -225,4 +225,4 @@ export {
225
225
  Ie as A,
226
226
  ge as u
227
227
  };
228
- //# sourceMappingURL=autocomplete-0kGG_STe.mjs.map
228
+ //# sourceMappingURL=autocomplete-B4dZx9zF.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-0kGG_STe.mjs","sources":["../../../components/autocomplete/src/utils.ts","../../../components/autocomplete/src/useAutocomplete.ts","../../../components/autocomplete/src/autocomplete.tsx"],"sourcesContent":["import { type RefObject, useCallback, useEffect, useRef } from \"react\";\n\n// Used to \"merge\" \"intersection types\". Used to get comments on the props to the docs.\nexport type Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport const useRefObject = <T>(value: T): RefObject<T> => {\n return useRef<T>(value) as RefObject<T>;\n};\n\nexport const useOnClickOutside = (element: HTMLElement | null, callback: () => void) => {\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (element && !element.contains(event.target as Node)) {\n callback();\n }\n },\n [callback, element]\n );\n\n useEffect(() => {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [handleClickOutside]);\n};\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useRef, useState } from \"react\";\nimport type { BaseProps } from \"@purpur/common-types\";\nimport type { ListboxItemProps, ListboxProps } from \"@purpur/listbox\";\n\nimport { useOnClickOutside, useRefObject } from \"./utils\";\n\nexport type AutocompleteOption = {\n label: string;\n id: string;\n value?: string;\n disabled?: boolean;\n};\n\nexport type InputProps = Omit<BaseProps<\"input\">, \"onFocus\" | \"onMouseDown\"> & {\n onFocus: (event: React.FocusEvent<HTMLInputElement> | undefined) => void;\n onMouseDown: (event: React.MouseEvent<HTMLInputElement> | undefined) => void;\n};\n\ntype ComboboxProps = {\n /*\n * Set to get combobox features. Use in combination with `noOptionsText`, `comboboxButtonAriaLabel` and Purpur TextField.\n */\n combobox: true;\n /**\n * An accessible label for the button that toggles the list of options for a combobox.\n * */\n comboboxButtonAriaLabel: string;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText: ReactNode;\n};\n\ntype NoComboboxProps = {\n combobox?: never;\n comboboxButtonAriaLabel?: never;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText?: ReactNode;\n};\n\nexport type UseAutocompleteResult<T extends AutocompleteOption> = {\n /*\n * Set to highlight the first option in the listbox when the input is focused.\n */\n highlightFirstOption?: boolean;\n /*\n * The default input value. Only to use when the input is uncontrolled.\n */\n defaultInputValue?: string;\n /*\n * The input value. Use this to control the input value.\n */\n inputValue?: string;\n /*\n * Invoked for each option. Use to control which options are shown.\n */\n filterOption?: (inputValue: string | undefined, option: T) => boolean;\n /*\n * Id will be used to prefix id:s of all elements.\n */\n id: string;\n /*\n * The label of the listbox (dropdown) displaying the options.\n */\n listboxLabel: string;\n /*\n * The height of the listbox. Number will be interpreted as px value. defaults to `calc(2 * var(--purpur-spacing-1200))`.\n */\n listboxMaxHeight?: string | number;\n /*\n * NOTE! Always use this instead of onBlur directly on the input element. Event handler invoked on input blur.\n */\n onInputBlur?: React.FocusEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onChange directly on the input element. Event handler invoked when the input value changes.\n */\n onInputChange?: (value: string) => void;\n /*\n * NOTE! Always use this instead of onFocus directly on the input element. Event handler invoked on input focus.\n */\n onInputFocus?: (event: React.FocusEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * NOTE! Always use this instead of onKeyDown directly on the input element. Event handler invoked on input key down.\n */\n onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onMouseDown directly on the input element. Event handler invoked on input mouse down.\n */\n onInputMouseDown?: (event: React.MouseEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * Set to open the listbox when input gets focus.\n */\n openOnFocus?: boolean;\n /*\n * Event handler invoked when an option is selected.\n */\n onSelect?: (option: T | undefined) => void;\n /*\n * The list of options. Could include custom props.\n */\n options: T[];\n /*\n * The selected option.\n */\n selectedOption?: T;\n [\"data-testid\"]?: string;\n} & (ComboboxProps | NoComboboxProps);\n\nexport const useAutocomplete = <T extends AutocompleteOption>({\n combobox,\n comboboxButtonAriaLabel,\n highlightFirstOption,\n defaultInputValue,\n inputValue,\n filterOption,\n id,\n listboxLabel,\n listboxMaxHeight,\n onInputBlur,\n onInputChange,\n onInputFocus,\n onInputKeyDown,\n onInputMouseDown,\n openOnFocus,\n noOptionsText,\n onSelect,\n options,\n selectedOption,\n [\"data-testid\"]: dataTestid,\n}: UseAutocompleteResult<T>) => {\n const [internalInputValue, setInternalInputValue] = useState(\n ((typeof inputValue === \"string\" ? inputValue : defaultInputValue) || selectedOption?.label) ??\n \"\"\n );\n const definiteInputValue = typeof inputValue === \"string\" ? inputValue : internalInputValue;\n const [highlightedOption, setHighlightedOption] = useState<\n (T & { isSetByClickEvent?: false }) | undefined\n >(highlightFirstOption ? options[0] : undefined);\n const inputRef = useRef<HTMLInputElement>(null);\n const internalRef = useRefObject<HTMLDivElement | null>(null);\n const listboxRef = useRef<HTMLUListElement>(null);\n const optionRefs = useRef<Record<string, HTMLLIElement>>({});\n const [listboxIsOpen, setListboxIsOpen] = useState(false);\n\n function getTestId(name: string) {\n return dataTestid ? `${dataTestid}-${name}` : undefined;\n }\n\n const closeListbox = () => {\n setListboxIsOpen(false);\n setHighlightedOption(undefined);\n };\n\n useOnClickOutside(internalRef.current, closeListbox);\n\n const openListbox = ({ eventType }: { eventType: \"CLICK\" | \"KEYBOARD\" }) => {\n setListboxIsOpen(true);\n if (selectedOption) {\n requestAnimationFrame(() => {\n const isSetByClickEvent = eventType === \"CLICK\";\n setHighlightedOption({ ...selectedOption, isSetByClickEvent });\n scrollOptionIntoView(optionRefs.current[selectedOption.id]);\n });\n }\n };\n\n const filterOptions = (searchTerm: string | undefined) => {\n if (filterOption) {\n return options.filter((option) => filterOption(searchTerm, option));\n }\n\n if (!searchTerm) {\n return options;\n }\n\n const searchTermChunks = searchTerm.toUpperCase().split(\" \") || [];\n return options.filter((option) =>\n searchTermChunks.every((chunk) =>\n (option.value || option.label).toUpperCase().includes(chunk)\n )\n );\n };\n\n const getOptionsToShow = (searchTerm: string | undefined): (T | undefined)[] => {\n return selectedOption && selectedOption?.label === searchTerm\n ? options\n : filterOptions(searchTerm);\n };\n\n const optionsToShow = getOptionsToShow(definiteInputValue);\n\n const populateInputField = (value: string) => {\n onInputChange?.(value);\n setInternalInputValue(value);\n };\n\n const scrollOptionIntoView = (option: HTMLLIElement | undefined) => {\n if (option) {\n const optionRect = option.getBoundingClientRect();\n const listboxRect = listboxRef.current?.getBoundingClientRect() || { top: 0, bottom: 0 };\n const isOptionOutsideView =\n optionRect.top < listboxRect.top || optionRect.bottom > listboxRect.bottom;\n if (isOptionOutsideView) {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }\n };\n\n const selectOption = (option: T | undefined) => {\n if (option) {\n inputRef.current?.focus();\n populateInputField(option.label);\n onSelect?.(option);\n }\n closeListbox();\n };\n\n const findNextOption = (key: \"ArrowUp\" | \"ArrowDown\"): T | undefined => {\n const index =\n highlightFirstOption && !highlightedOption\n ? 0\n : optionsToShow.findIndex((option) => option && highlightedOption?.id === option.id);\n\n const optionsLength = optionsToShow.length;\n\n return key === \"ArrowDown\"\n ? optionsToShow[(index ?? -1) + 1] || optionsToShow[0]\n : optionsToShow[(index ?? optionsLength) - 1] || optionsToShow[optionsLength - 1];\n };\n\n const showListbox = listboxIsOpen && (!!optionsToShow.length || !!noOptionsText);\n\n const highlightNextOption = (key: \"ArrowUp\" | \"ArrowDown\") => {\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n const nextOption = findNextOption(key);\n\n setHighlightedOption(nextOption);\n nextOption && scrollOptionIntoView(optionRefs.current[nextOption.id]);\n };\n\n const handleOnKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {\n onInputKeyDown?.(event);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowDown\":\n event.preventDefault(); // Preventing default to not move cursor in input\n highlightNextOption(event.key);\n break;\n case \"Enter\": {\n const optionToSelect = highlightedOption || (highlightFirstOption ? options[0] : undefined);\n showListbox && selectOption(optionToSelect);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n break;\n }\n case \"Escape\":\n case \"Tab\":\n closeListbox();\n break;\n }\n };\n\n const handleOnChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const nextOptionsToShow = getOptionsToShow(e.target.value);\n populateInputField(e.target.value);\n setHighlightedOption(undefined);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n highlightFirstOption &&\n nextOptionsToShow[0] &&\n scrollOptionIntoView(optionRefs.current[nextOptionsToShow[0].id]);\n };\n\n const handleOnMouseDown = (event: React.MouseEvent<HTMLInputElement> | undefined) => {\n onInputMouseDown?.(event);\n showListbox ? closeListbox() : openListbox({ eventType: \"CLICK\" });\n };\n\n const handleOnFocus = (event: React.FocusEvent<HTMLInputElement> | undefined) => {\n onInputFocus?.(event);\n !listboxIsOpen && openOnFocus && openListbox({ eventType: \"KEYBOARD\" });\n inputRef.current?.select();\n };\n\n const handleOnBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {\n onInputBlur?.(event);\n // Use a timeout to allow click events on the listbox to fire before this check\n setTimeout(() => {\n if (\n !inputRef.current?.contains(document.activeElement) &&\n !listboxRef.current?.contains(document.activeElement)\n ) {\n closeListbox();\n\n // If the blur happened due to a click inside the listbox for a combobox, don't reset the value\n if (combobox) {\n populateInputField(selectedOption ? selectedOption.label : \"\");\n }\n }\n });\n };\n\n const listboxStyle: CSSProperties = {\n maxHeight: typeof listboxMaxHeight === \"number\" ? `${listboxMaxHeight}px` : listboxMaxHeight,\n };\n\n const listboxProps: ListboxProps = {\n \"aria-label\": listboxLabel,\n \"aria-expanded\": showListbox,\n \"data-testid\": getTestId(\"listbox\"),\n id: `${id}-listbox`,\n ref: listboxRef,\n onMouseLeave: () => setHighlightedOption(undefined),\n style: listboxMaxHeight ? listboxStyle : undefined,\n };\n\n const createListboxItemId = (option: T) => `${id}-listbox-item-${option.id}`;\n\n const getListBoxItemProps = (option: T, index: number): ListboxItemProps => {\n const handleOnMouseMove = () =>\n option.id !== highlightedOption?.id &&\n setHighlightedOption({ ...option, isSetByClickEvent: true });\n\n const highlighted =\n (option.id === highlightedOption?.id ||\n (!!highlightFirstOption && !highlightedOption && index === 0)) &&\n !highlightedOption?.isSetByClickEvent;\n\n return {\n \"data-testid\": getTestId(`listbox-item-${option.id}`),\n id: createListboxItemId(option),\n key: option.id,\n onMouseMove: handleOnMouseMove,\n onMouseUp: () => selectOption(option),\n ref: (el) => {\n if (el) {\n optionRefs.current[option.id] = el;\n }\n },\n tabIndex: -1,\n selected: option.id === selectedOption?.id,\n disabled: option.disabled,\n highlighted,\n hovered: option.id === highlightedOption?.id && !!highlightedOption?.isSetByClickEvent,\n };\n };\n\n const inputProps: InputProps = {\n \"aria-activedescendant\": highlightedOption ? createListboxItemId(highlightedOption) : undefined,\n \"aria-autocomplete\": \"list\",\n \"aria-controls\": listboxProps.id,\n \"data-testid\": getTestId(\"input\"),\n autoComplete: \"off\",\n id: `${id}-input`,\n onChange: handleOnChange,\n onMouseDown: handleOnMouseDown,\n onFocus: handleOnFocus,\n onKeyDown: handleOnKeyDown,\n onBlur: handleOnBlur,\n ref: inputRef,\n role: \"combobox\",\n value: definiteInputValue,\n };\n\n return {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n };\n};\n","import type { ComponentPropsWithRef, ForwardedRef, ReactNode } from \"react\";\nimport React, { cloneElement, forwardRef } from \"react\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Listbox } from \"@purpur/listbox\";\nimport { isTextField } from \"@purpur/text-field\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./autocomplete.module.scss\";\nimport type { AutocompleteOption, UseAutocompleteResult } from \"./useAutocomplete\";\nimport { useAutocomplete } from \"./useAutocomplete\";\nimport type { Prettify } from \"./utils\";\n\nconst cx = c.bind(styles);\n\ntype AutocompleteProps<T extends AutocompleteOption> = Prettify<\n UseAutocompleteResult<T> & {\n className?: string;\n /**\n * Render the input. `props` are native input props\n */\n renderInput: (props: ComponentPropsWithRef<\"input\">) => ReactNode;\n /**\n * Invoked for each given option. Use to customize the rendering of the options\n */\n renderOption?: (option: T) => ReactNode;\n }\n>;\n\nconst rootClassName = \"purpur-autocomplete\";\n\nconst AutocompleteComponent = <T extends AutocompleteOption>(\n { className, renderInput, renderOption, ...useAutocompleteProps }: AutocompleteProps<T>,\n ref: ForwardedRef<HTMLDivElement>\n) => {\n const {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n } = useAutocomplete(useAutocompleteProps);\n\n const renderListboxItem = (option: T, index: number) => {\n const { key, ...listboxItemProps } = getListBoxItemProps(option, index);\n\n return (\n <Listbox.Item key={key} {...listboxItemProps}>\n {renderOption ? renderOption?.(option) : option.label}\n </Listbox.Item>\n );\n };\n\n const setRootRef = (node: HTMLDivElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n };\n\n const getInputComponent = () => {\n const input = renderInput(inputProps);\n const isCombobox =\n combobox && comboboxButtonAriaLabel && noOptionsText && input && isTextField(input);\n\n if (isCombobox) {\n const endAdornment = (\n <>\n {input.props.endAdornment}\n <button\n data-testid=\"chevron button\"\n type=\"button\"\n className={cx(`${rootClassName}__chevron-button`)}\n onClick={() => {\n inputProps.onFocus(undefined);\n inputProps.onMouseDown(undefined);\n }}\n aria-label={comboboxButtonAriaLabel}\n aria-expanded={showListbox}\n aria-controls={listboxProps.id}\n >\n <IconChevronDown\n size=\"sm\"\n className={cx(`${rootClassName}__chevron-icon`, {\n [`${rootClassName}__chevron-icon--up`]: showListbox,\n })}\n />\n </button>\n </>\n );\n\n return cloneElement(input, { endAdornment });\n }\n\n return input;\n };\n\n return (\n <div id={id} ref={setRootRef} className={cx([rootClassName, className])}>\n {getInputComponent()}\n {showListbox && (\n <Listbox {...listboxProps} className={cx(`${rootClassName}__listbox`)}>\n {!optionsToShow.length ? (\n <Listbox.Item noninteractive>{noOptionsText}</Listbox.Item>\n ) : (\n optionsToShow.filter((option): option is T => !!option).map(renderListboxItem)\n )}\n </Listbox>\n )}\n </div>\n );\n};\n\nexport const Autocomplete = forwardRef(AutocompleteComponent);\nAutocomplete.displayName = \"Autocomplete\";\n\nexport type {\n AutocompleteOption,\n UseAutocompleteResult as UseAutocompleteOptions,\n} from \"./useAutocomplete\";\nexport { useAutocomplete } from \"./useAutocomplete\";\n"],"names":["useRefObject","value","useRef","useOnClickOutside","element","callback","handleClickOutside","useCallback","event","useEffect","useAutocomplete","combobox","comboboxButtonAriaLabel","highlightFirstOption","defaultInputValue","inputValue","filterOption","id","listboxLabel","listboxMaxHeight","onInputBlur","onInputChange","onInputFocus","onInputKeyDown","onInputMouseDown","openOnFocus","noOptionsText","onSelect","options","selectedOption","dataTestid","internalInputValue","setInternalInputValue","useState","definiteInputValue","highlightedOption","setHighlightedOption","inputRef","internalRef","listboxRef","optionRefs","listboxIsOpen","setListboxIsOpen","getTestId","name","closeListbox","openListbox","eventType","scrollOptionIntoView","filterOptions","searchTerm","option","searchTermChunks","chunk","getOptionsToShow","optionsToShow","populateInputField","optionRect","listboxRect","selectOption","findNextOption","key","index","optionsLength","showListbox","highlightNextOption","nextOption","handleOnKeyDown","optionToSelect","handleOnChange","nextOptionsToShow","handleOnMouseDown","handleOnFocus","handleOnBlur","listboxStyle","listboxProps","createListboxItemId","getListBoxItemProps","handleOnMouseMove","highlighted","el","inputProps","cx","c","styles","rootClassName","AutocompleteComponent","className","renderInput","renderOption","useAutocompleteProps","ref","renderListboxItem","listboxItemProps","jsx","Listbox","setRootRef","node","getInputComponent","input","isTextField","endAdornment","jsxs","Fragment","IconChevronDown","cloneElement","Autocomplete","forwardRef"],"mappings":";;;;;;;;;;;;GAOaA,KAAe,CAAIC,MACvBC,EAAUD,CAAK,GAGXE,KAAoB,CAACC,GAA6BC,MAAyB;AACtF,QAAMC,IAAqBC;AAAA,IACzB,CAACC,MAAsB;AACrB,MAAIJ,KAAW,CAACA,EAAQ,SAASI,EAAM,MAAc,KACnDH,EAAA;AAAA,IAEJ;AAAA,IACA,CAACA,GAAUD,CAAO;AAAA,EAAA;AAGpB,EAAAK,GAAU,OACR,SAAS,iBAAiB,aAAaH,CAAkB,GAClD,MAAM;AACX,aAAS,oBAAoB,aAAaA,CAAkB;AAAA,EAC9D,IACC,CAACA,CAAkB,CAAC;AACzB,GCoFaI,KAAkB,CAA+B;AAAA,EAC5D,UAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,YAAAC;AAAA,EACA,cAAAC;AAAA,EACA,IAAAC;AAAA,EACA,cAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,cAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,CAAC,gBAAgBC;AACnB,MAAgC;AAC9B,QAAM,CAACC,GAAoBC,CAAqB,IAAIC;AAAA,MAChD,OAAOlB,KAAe,WAAWA,IAAaD,MAAsBe,GAAgB,UACpF;AAAA,EAAA,GAEEK,IAAqB,OAAOnB,KAAe,WAAWA,IAAagB,GACnE,CAACI,GAAmBC,CAAoB,IAAIH,EAEhDpB,IAAuBe,EAAQ,CAAC,IAAI,MAAS,GACzCS,IAAWnC,EAAyB,IAAI,GACxCoC,IAActC,GAAoC,IAAI,GACtDuC,IAAarC,EAAyB,IAAI,GAC1CsC,IAAatC,EAAsC,EAAE,GACrD,CAACuC,GAAeC,CAAgB,IAAIT,EAAS,EAAK;AAExD,WAASU,EAAUC,GAAc;AAC/B,WAAOd,IAAa,GAAGA,CAAU,IAAIc,CAAI,KAAK;AAAA,EAChD;AAEA,QAAMC,IAAe,MAAM;AACzB,IAAAH,EAAiB,EAAK,GACtBN,EAAqB,MAAS;AAAA,EAChC;AAEA,EAAAjC,GAAkBmC,EAAY,SAASO,CAAY;AAEnD,QAAMC,IAAc,CAAC,EAAE,WAAAC,QAAqD;AAC1E,IAAAL,EAAiB,EAAI,GACjBb,KACF,sBAAsB,MAAM;AAE1B,MAAAO,EAAqB,EAAE,GAAGP,GAAgB,mBADhBkB,MAAc,SACqB,GAC7DC,EAAqBR,EAAW,QAAQX,EAAe,EAAE,CAAC;AAAA,IAC5D,CAAC;AAAA,EAEL,GAEMoB,KAAgB,CAACC,MAAmC;AACxD,QAAIlC;AACF,aAAOY,EAAQ,OAAO,CAACuB,MAAWnC,EAAakC,GAAYC,CAAM,CAAC;AAGpE,QAAI,CAACD;AACH,aAAOtB;AAGT,UAAMwB,IAAmBF,EAAW,YAAA,EAAc,MAAM,GAAG,KAAK,CAAA;AAChE,WAAOtB,EAAQ;AAAA,MAAO,CAACuB,MACrBC,EAAiB;AAAA,QAAM,CAACC,OACrBF,EAAO,SAASA,EAAO,OAAO,cAAc,SAASE,CAAK;AAAA,MAAA;AAAA,IAC7D;AAAA,EAEJ,GAEMC,IAAmB,CAACJ,MACjBrB,KAAkBA,GAAgB,UAAUqB,IAC/CtB,IACAqB,GAAcC,CAAU,GAGxBK,IAAgBD,EAAiBpB,CAAkB,GAEnDsB,IAAqB,CAACvD,MAAkB;AAC5C,IAAAoB,IAAgBpB,CAAK,GACrB+B,EAAsB/B,CAAK;AAAA,EAC7B,GAEM+C,IAAuB,CAACG,MAAsC;AAClE,QAAIA,GAAQ;AACV,YAAMM,IAAaN,EAAO,sBAAA,GACpBO,IAAcnB,EAAW,SAAS,sBAAA,KAA2B,EAAE,KAAK,GAAG,QAAQ,EAAA;AAGrF,OADEkB,EAAW,MAAMC,EAAY,OAAOD,EAAW,SAASC,EAAY,WAEpEP,EAAO,eAAe,EAAE,OAAO,UAAA,CAAW;AAAA,IAE9C;AAAA,EACF,GAEMQ,IAAe,CAACR,MAA0B;AAC9C,IAAIA,MACFd,EAAS,SAAS,MAAA,GAClBmB,EAAmBL,EAAO,KAAK,GAC/BxB,IAAWwB,CAAM,IAEnBN,EAAA;AAAA,EACF,GAEMe,KAAiB,CAACC,MAAgD;AACtE,UAAMC,IACJjD,KAAwB,CAACsB,IACrB,IACAoB,EAAc,UAAU,CAACJ,MAAWA,KAAUhB,GAAmB,OAAOgB,EAAO,EAAE,GAEjFY,IAAgBR,EAAc;AAEpC,WAAOM,MAAQ,cACXN,GAAeO,KAAS,MAAM,CAAC,KAAKP,EAAc,CAAC,IACnDA,GAAeO,KAASC,KAAiB,CAAC,KAAKR,EAAcQ,IAAgB,CAAC;AAAA,EACpF,GAEMC,IAAcvB,MAAkB,CAAC,CAACc,EAAc,UAAU,CAAC,CAAC7B,IAE5DuC,KAAsB,CAACJ,MAAiC;AAC5D,KAACG,KAAelB,EAAY,EAAE,WAAW,YAAY;AACrD,UAAMoB,IAAaN,GAAeC,CAAG;AAErC,IAAAzB,EAAqB8B,CAAU,GAC/BA,KAAclB,EAAqBR,EAAW,QAAQ0B,EAAW,EAAE,CAAC;AAAA,EACtE,GAEMC,KAAgE,CAAC3D,MAAU;AAE/E,YADAe,IAAiBf,CAAK,GACdA,EAAM,KAAA;AAAA,MACZ,KAAK;AAAA,MACL,KAAK;AACH,QAAAA,EAAM,eAAA,GACNyD,GAAoBzD,EAAM,GAAG;AAC7B;AAAA,MACF,KAAK,SAAS;AACZ,cAAM4D,IAAiBjC,MAAsBtB,IAAuBe,EAAQ,CAAC,IAAI;AACjF,QAAAoC,KAAeL,EAAaS,CAAc,GAC1C,CAACJ,KAAelB,EAAY,EAAE,WAAW,YAAY;AACrD;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AACH,QAAAD,EAAA;AACA;AAAA,IAAA;AAAA,EAEN,GAEMwB,KAA6D,CAAC,MAAM;AACxE,UAAMC,IAAoBhB,EAAiB,EAAE,OAAO,KAAK;AACzD,IAAAE,EAAmB,EAAE,OAAO,KAAK,GACjCpB,EAAqB,MAAS,GAC9B,CAAC4B,KAAelB,EAAY,EAAE,WAAW,YAAY,GACrDjC,KACEyD,EAAkB,CAAC,KACnBtB,EAAqBR,EAAW,QAAQ8B,EAAkB,CAAC,EAAE,EAAE,CAAC;AAAA,EACpE,GAEMC,KAAoB,CAAC/D,MAA0D;AACnF,IAAAgB,IAAmBhB,CAAK,GACxBwD,IAAcnB,MAAiBC,EAAY,EAAE,WAAW,SAAS;AAAA,EACnE,GAEM0B,KAAgB,CAAChE,MAA0D;AAC/E,IAAAc,IAAed,CAAK,GACpB,CAACiC,KAAiBhB,KAAeqB,EAAY,EAAE,WAAW,YAAY,GACtET,EAAS,SAAS,OAAA;AAAA,EACpB,GAEMoC,KAA0D,CAACjE,MAAU;AACzE,IAAAY,IAAcZ,CAAK,GAEnB,WAAW,MAAM;AACf,MACE,CAAC6B,EAAS,SAAS,SAAS,SAAS,aAAa,KAClD,CAACE,EAAW,SAAS,SAAS,SAAS,aAAa,MAEpDM,EAAA,GAGIlC,KACF6C,EAAmB3B,IAAiBA,EAAe,QAAQ,EAAE;AAAA,IAGnE,CAAC;AAAA,EACH,GAEM6C,KAA8B;AAAA,IAClC,WAAW,OAAOvD,KAAqB,WAAW,GAAGA,CAAgB,OAAOA;AAAA,EAAA,GAGxEwD,IAA6B;AAAA,IACjC,cAAczD;AAAA,IACd,iBAAiB8C;AAAA,IACjB,eAAerB,EAAU,SAAS;AAAA,IAClC,IAAI,GAAG1B,CAAE;AAAA,IACT,KAAKsB;AAAA,IACL,cAAc,MAAMH,EAAqB,MAAS;AAAA,IAClD,OAAOjB,IAAmBuD,KAAe;AAAA,EAAA,GAGrCE,IAAsB,CAACzB,MAAc,GAAGlC,CAAE,iBAAiBkC,EAAO,EAAE,IAEpE0B,KAAsB,CAAC1B,GAAWW,MAAoC;AAC1E,UAAMgB,IAAoB,MACxB3B,EAAO,OAAOhB,GAAmB,MACjCC,EAAqB,EAAE,GAAGe,GAAQ,mBAAmB,GAAA,CAAM,GAEvD4B,KACH5B,EAAO,OAAOhB,GAAmB,MAC/B,CAAC,CAACtB,KAAwB,CAACsB,KAAqB2B,MAAU,MAC7D,CAAC3B,GAAmB;AAEtB,WAAO;AAAA,MACL,eAAeQ,EAAU,gBAAgBQ,EAAO,EAAE,EAAE;AAAA,MACpD,IAAIyB,EAAoBzB,CAAM;AAAA,MAC9B,KAAKA,EAAO;AAAA,MACZ,aAAa2B;AAAA,MACb,WAAW,MAAMnB,EAAaR,CAAM;AAAA,MACpC,KAAK,CAAC6B,MAAO;AACX,QAAIA,MACFxC,EAAW,QAAQW,EAAO,EAAE,IAAI6B;AAAA,MAEpC;AAAA,MACA,UAAU;AAAA,MACV,UAAU7B,EAAO,OAAOtB,GAAgB;AAAA,MACxC,UAAUsB,EAAO;AAAA,MACjB,aAAA4B;AAAA,MACA,SAAS5B,EAAO,OAAOhB,GAAmB,MAAM,CAAC,CAACA,GAAmB;AAAA,IAAA;AAAA,EAEzE,GAEM8C,KAAyB;AAAA,IAC7B,yBAAyB9C,IAAoByC,EAAoBzC,CAAiB,IAAI;AAAA,IACtF,qBAAqB;AAAA,IACrB,iBAAiBwC,EAAa;AAAA,IAC9B,eAAehC,EAAU,OAAO;AAAA,IAChC,cAAc;AAAA,IACd,IAAI,GAAG1B,CAAE;AAAA,IACT,UAAUoD;AAAA,IACV,aAAaE;AAAA,IACb,SAASC;AAAA,IACT,WAAWL;AAAA,IACX,QAAQM;AAAA,IACR,KAAKpC;AAAA,IACL,MAAM;AAAA,IACN,OAAOH;AAAA,EAAA;AAGT,SAAO;AAAA,IACL,IAAAjB;AAAA,IACA,YAAAgE;AAAA,IACA,aAAA3C;AAAA,IACA,eAAAiB;AAAA,IACA,aAAAS;AAAA,IACA,eAAAtC;AAAA,IACA,UAAAf;AAAA,IACA,yBAAAC;AAAA,IACA,qBAAAiE;AAAA,IACA,cAAAF;AAAA,EAAA;AAEJ,GC7WMO,IAAKC,GAAE,KAAKC,EAAM,GAgBlBC,IAAgB,uBAEhBC,KAAwB,CAC5B,EAAE,WAAAC,GAAW,aAAAC,GAAa,cAAAC,GAAc,GAAGC,EAAA,GAC3CC,MACG;AACH,QAAM;AAAA,IACJ,IAAA1E;AAAA,IACA,YAAAgE;AAAA,IACA,aAAA3C;AAAA,IACA,eAAAiB;AAAA,IACA,aAAAS;AAAA,IACA,eAAAtC;AAAA,IACA,UAAAf;AAAA,IACA,yBAAAC;AAAA,IACA,qBAAAiE;AAAA,IACA,cAAAF;AAAA,EAAA,IACEjE,GAAgBgF,CAAoB,GAElCE,IAAoB,CAACzC,GAAWW,MAAkB;AACtD,UAAM,EAAE,KAAAD,GAAK,GAAGgC,MAAqBhB,EAAoB1B,GAAQW,CAAK;AAEtE,WACE,gBAAAgC,EAACC,EAAQ,MAAR,EAAwB,GAAGF,GACzB,UAAAJ,IAAeA,IAAetC,CAAM,IAAIA,EAAO,MAAA,GAD/BU,CAEnB;AAAA,EAEJ,GAEMmC,IAAa,CAACC,MAAgC;AAClD,IAAA3D,EAAY,UAAU2D,GAClB,OAAON,KAAQ,aACjBA,EAAIM,CAAI,IACCN,MACTA,EAAI,UAAUM;AAAA,EAElB,GAEMC,IAAoB,MAAM;AAC9B,UAAMC,IAAQX,EAAYP,CAAU;AAIpC,QAFEtE,KAAYC,KAA2Bc,KAAiByE,KAASC,GAAYD,CAAK,GAEpE;AACd,YAAME,IACJ,gBAAAC,EAAAC,IAAA,EACG,UAAA;AAAA,QAAAJ,EAAM,MAAM;AAAA,QACb,gBAAAL;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,eAAY;AAAA,YACZ,MAAK;AAAA,YACL,WAAWZ,EAAG,GAAGG,CAAa,kBAAkB;AAAA,YAChD,SAAS,MAAM;AACb,cAAAJ,EAAW,QAAQ,MAAS,GAC5BA,EAAW,YAAY,MAAS;AAAA,YAClC;AAAA,YACA,cAAYrE;AAAA,YACZ,iBAAeoD;AAAA,YACf,iBAAeW,EAAa;AAAA,YAE5B,UAAA,gBAAAmB;AAAA,cAACU;AAAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAWtB,EAAG,GAAGG,CAAa,kBAAkB;AAAA,kBAC9C,CAAC,GAAGA,CAAa,oBAAoB,GAAGrB;AAAA,gBAAA,CACzC;AAAA,cAAA;AAAA,YAAA;AAAA,UACH;AAAA,QAAA;AAAA,MACF,GACF;AAGF,aAAOyC,GAAaN,GAAO,EAAE,cAAAE,GAAc;AAAA,IAC7C;AAEA,WAAOF;AAAA,EACT;AAEA,SACE,gBAAAG,EAAC,OAAA,EAAI,IAAArF,GAAQ,KAAK+E,GAAY,WAAWd,EAAG,CAACG,GAAeE,CAAS,CAAC,GACnE,UAAA;AAAA,IAAAW,EAAA;AAAA,IACAlC,KACC,gBAAA8B,EAACC,GAAA,EAAS,GAAGpB,GAAc,WAAWO,EAAG,GAAGG,CAAa,WAAW,GACjE,UAAC9B,EAAc,SAGdA,EAAc,OAAO,CAACJ,MAAwB,CAAC,CAACA,CAAM,EAAE,IAAIyC,CAAiB,IAF7E,gBAAAE,EAACC,EAAQ,MAAR,EAAa,gBAAc,IAAE,UAAArE,EAAA,CAAc,EAEiC,CAEjF;AAAA,EAAA,GAEJ;AAEJ,GAEagF,KAAeC,GAAWrB,EAAqB;AAC5DoB,GAAa,cAAc;"}
1
+ {"version":3,"file":"autocomplete-B4dZx9zF.mjs","sources":["../../../components/autocomplete/src/utils.ts","../../../components/autocomplete/src/useAutocomplete.ts","../../../components/autocomplete/src/autocomplete.tsx"],"sourcesContent":["import { type RefObject, useCallback, useEffect, useRef } from \"react\";\n\n// Used to \"merge\" \"intersection types\". Used to get comments on the props to the docs.\nexport type Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport const useRefObject = <T>(value: T): RefObject<T> => {\n return useRef<T>(value) as RefObject<T>;\n};\n\nexport const useOnClickOutside = (element: HTMLElement | null, callback: () => void) => {\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (element && !element.contains(event.target as Node)) {\n callback();\n }\n },\n [callback, element]\n );\n\n useEffect(() => {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [handleClickOutside]);\n};\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useRef, useState } from \"react\";\nimport type { BaseProps } from \"@purpur/common-types\";\nimport type { ListboxItemProps, ListboxProps } from \"@purpur/listbox\";\n\nimport { useOnClickOutside, useRefObject } from \"./utils\";\n\nexport type AutocompleteOption = {\n label: string;\n id: string;\n value?: string;\n disabled?: boolean;\n};\n\nexport type InputProps = Omit<BaseProps<\"input\">, \"onFocus\" | \"onMouseDown\"> & {\n onFocus: (event: React.FocusEvent<HTMLInputElement> | undefined) => void;\n onMouseDown: (event: React.MouseEvent<HTMLInputElement> | undefined) => void;\n};\n\ntype ComboboxProps = {\n /*\n * Set to get combobox features. Use in combination with `noOptionsText`, `comboboxButtonAriaLabel` and Purpur TextField.\n */\n combobox: true;\n /**\n * An accessible label for the button that toggles the list of options for a combobox.\n * */\n comboboxButtonAriaLabel: string;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText: ReactNode;\n};\n\ntype NoComboboxProps = {\n combobox?: never;\n comboboxButtonAriaLabel?: never;\n /*\n * Shown when there are no options to show. Will be displayed inside a listbox item.\n */\n noOptionsText?: ReactNode;\n};\n\nexport type UseAutocompleteResult<T extends AutocompleteOption> = {\n /*\n * Set to highlight the first option in the listbox when the input is focused.\n */\n highlightFirstOption?: boolean;\n /*\n * The default input value. Only to use when the input is uncontrolled.\n */\n defaultInputValue?: string;\n /*\n * The input value. Use this to control the input value.\n */\n inputValue?: string;\n /*\n * Invoked for each option. Use to control which options are shown.\n */\n filterOption?: (inputValue: string | undefined, option: T) => boolean;\n /*\n * Id will be used to prefix id:s of all elements.\n */\n id: string;\n /*\n * The label of the listbox (dropdown) displaying the options.\n */\n listboxLabel: string;\n /*\n * The height of the listbox. Number will be interpreted as px value. defaults to `calc(2 * var(--purpur-spacing-1200))`.\n */\n listboxMaxHeight?: string | number;\n /*\n * NOTE! Always use this instead of onBlur directly on the input element. Event handler invoked on input blur.\n */\n onInputBlur?: React.FocusEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onChange directly on the input element. Event handler invoked when the input value changes.\n */\n onInputChange?: (value: string) => void;\n /*\n * NOTE! Always use this instead of onFocus directly on the input element. Event handler invoked on input focus.\n */\n onInputFocus?: (event: React.FocusEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * NOTE! Always use this instead of onKeyDown directly on the input element. Event handler invoked on input key down.\n */\n onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /*\n * NOTE! Always use this instead of onMouseDown directly on the input element. Event handler invoked on input mouse down.\n */\n onInputMouseDown?: (event: React.MouseEvent<HTMLInputElement> | undefined) => undefined;\n /*\n * Set to open the listbox when input gets focus.\n */\n openOnFocus?: boolean;\n /*\n * Event handler invoked when an option is selected.\n */\n onSelect?: (option: T | undefined) => void;\n /*\n * The list of options. Could include custom props.\n */\n options: T[];\n /*\n * The selected option.\n */\n selectedOption?: T;\n [\"data-testid\"]?: string;\n} & (ComboboxProps | NoComboboxProps);\n\nexport const useAutocomplete = <T extends AutocompleteOption>({\n combobox,\n comboboxButtonAriaLabel,\n highlightFirstOption,\n defaultInputValue,\n inputValue,\n filterOption,\n id,\n listboxLabel,\n listboxMaxHeight,\n onInputBlur,\n onInputChange,\n onInputFocus,\n onInputKeyDown,\n onInputMouseDown,\n openOnFocus,\n noOptionsText,\n onSelect,\n options,\n selectedOption,\n [\"data-testid\"]: dataTestid,\n}: UseAutocompleteResult<T>) => {\n const [internalInputValue, setInternalInputValue] = useState(\n ((typeof inputValue === \"string\" ? inputValue : defaultInputValue) || selectedOption?.label) ??\n \"\"\n );\n const definiteInputValue = typeof inputValue === \"string\" ? inputValue : internalInputValue;\n const [highlightedOption, setHighlightedOption] = useState<\n (T & { isSetByClickEvent?: false }) | undefined\n >(highlightFirstOption ? options[0] : undefined);\n const inputRef = useRef<HTMLInputElement>(null);\n const internalRef = useRefObject<HTMLDivElement | null>(null);\n const listboxRef = useRef<HTMLUListElement>(null);\n const optionRefs = useRef<Record<string, HTMLLIElement>>({});\n const [listboxIsOpen, setListboxIsOpen] = useState(false);\n\n function getTestId(name: string) {\n return dataTestid ? `${dataTestid}-${name}` : undefined;\n }\n\n const closeListbox = () => {\n setListboxIsOpen(false);\n setHighlightedOption(undefined);\n };\n\n useOnClickOutside(internalRef.current, closeListbox);\n\n const openListbox = ({ eventType }: { eventType: \"CLICK\" | \"KEYBOARD\" }) => {\n setListboxIsOpen(true);\n if (selectedOption) {\n requestAnimationFrame(() => {\n const isSetByClickEvent = eventType === \"CLICK\";\n setHighlightedOption({ ...selectedOption, isSetByClickEvent });\n scrollOptionIntoView(optionRefs.current[selectedOption.id]);\n });\n }\n };\n\n const filterOptions = (searchTerm: string | undefined) => {\n if (filterOption) {\n return options.filter((option) => filterOption(searchTerm, option));\n }\n\n if (!searchTerm) {\n return options;\n }\n\n const searchTermChunks = searchTerm.toUpperCase().split(\" \") || [];\n return options.filter((option) =>\n searchTermChunks.every((chunk) =>\n (option.value || option.label).toUpperCase().includes(chunk)\n )\n );\n };\n\n const getOptionsToShow = (searchTerm: string | undefined): (T | undefined)[] => {\n return selectedOption && selectedOption?.label === searchTerm\n ? options\n : filterOptions(searchTerm);\n };\n\n const optionsToShow = getOptionsToShow(definiteInputValue);\n\n const populateInputField = (value: string) => {\n onInputChange?.(value);\n setInternalInputValue(value);\n };\n\n const scrollOptionIntoView = (option: HTMLLIElement | undefined) => {\n if (option) {\n const optionRect = option.getBoundingClientRect();\n const listboxRect = listboxRef.current?.getBoundingClientRect() || { top: 0, bottom: 0 };\n const isOptionOutsideView =\n optionRect.top < listboxRect.top || optionRect.bottom > listboxRect.bottom;\n if (isOptionOutsideView) {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }\n };\n\n const selectOption = (option: T | undefined) => {\n if (option) {\n inputRef.current?.focus();\n populateInputField(option.label);\n onSelect?.(option);\n }\n closeListbox();\n };\n\n const findNextOption = (key: \"ArrowUp\" | \"ArrowDown\"): T | undefined => {\n const index =\n highlightFirstOption && !highlightedOption\n ? 0\n : optionsToShow.findIndex((option) => option && highlightedOption?.id === option.id);\n\n const optionsLength = optionsToShow.length;\n\n return key === \"ArrowDown\"\n ? optionsToShow[(index ?? -1) + 1] || optionsToShow[0]\n : optionsToShow[(index ?? optionsLength) - 1] || optionsToShow[optionsLength - 1];\n };\n\n const showListbox = listboxIsOpen && (!!optionsToShow.length || !!noOptionsText);\n\n const highlightNextOption = (key: \"ArrowUp\" | \"ArrowDown\") => {\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n const nextOption = findNextOption(key);\n\n setHighlightedOption(nextOption);\n nextOption && scrollOptionIntoView(optionRefs.current[nextOption.id]);\n };\n\n const handleOnKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {\n onInputKeyDown?.(event);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowDown\":\n event.preventDefault(); // Preventing default to not move cursor in input\n highlightNextOption(event.key);\n break;\n case \"Enter\": {\n const optionToSelect = highlightedOption || (highlightFirstOption ? options[0] : undefined);\n showListbox && selectOption(optionToSelect);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n break;\n }\n case \"Escape\":\n case \"Tab\":\n closeListbox();\n break;\n }\n };\n\n const handleOnChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {\n const nextOptionsToShow = getOptionsToShow(e.target.value);\n populateInputField(e.target.value);\n setHighlightedOption(undefined);\n !showListbox && openListbox({ eventType: \"KEYBOARD\" });\n highlightFirstOption &&\n nextOptionsToShow[0] &&\n scrollOptionIntoView(optionRefs.current[nextOptionsToShow[0].id]);\n };\n\n const handleOnMouseDown = (event: React.MouseEvent<HTMLInputElement> | undefined) => {\n onInputMouseDown?.(event);\n showListbox ? closeListbox() : openListbox({ eventType: \"CLICK\" });\n };\n\n const handleOnFocus = (event: React.FocusEvent<HTMLInputElement> | undefined) => {\n onInputFocus?.(event);\n !listboxIsOpen && openOnFocus && openListbox({ eventType: \"KEYBOARD\" });\n inputRef.current?.select();\n };\n\n const handleOnBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {\n onInputBlur?.(event);\n // Use a timeout to allow click events on the listbox to fire before this check\n setTimeout(() => {\n if (\n !inputRef.current?.contains(document.activeElement) &&\n !listboxRef.current?.contains(document.activeElement)\n ) {\n closeListbox();\n\n // If the blur happened due to a click inside the listbox for a combobox, don't reset the value\n if (combobox) {\n populateInputField(selectedOption ? selectedOption.label : \"\");\n }\n }\n });\n };\n\n const listboxStyle: CSSProperties = {\n maxHeight: typeof listboxMaxHeight === \"number\" ? `${listboxMaxHeight}px` : listboxMaxHeight,\n };\n\n const listboxProps: ListboxProps = {\n \"aria-label\": listboxLabel,\n \"aria-expanded\": showListbox,\n \"data-testid\": getTestId(\"listbox\"),\n id: `${id}-listbox`,\n ref: listboxRef,\n onMouseLeave: () => setHighlightedOption(undefined),\n style: listboxMaxHeight ? listboxStyle : undefined,\n };\n\n const createListboxItemId = (option: T) => `${id}-listbox-item-${option.id}`;\n\n const getListBoxItemProps = (option: T, index: number): ListboxItemProps => {\n const handleOnMouseMove = () =>\n option.id !== highlightedOption?.id &&\n setHighlightedOption({ ...option, isSetByClickEvent: true });\n\n const highlighted =\n (option.id === highlightedOption?.id ||\n (!!highlightFirstOption && !highlightedOption && index === 0)) &&\n !highlightedOption?.isSetByClickEvent;\n\n return {\n \"data-testid\": getTestId(`listbox-item-${option.id}`),\n id: createListboxItemId(option),\n key: option.id,\n onMouseMove: handleOnMouseMove,\n onMouseUp: () => selectOption(option),\n ref: (el) => {\n if (el) {\n optionRefs.current[option.id] = el;\n }\n },\n tabIndex: -1,\n selected: option.id === selectedOption?.id,\n disabled: option.disabled,\n highlighted,\n hovered: option.id === highlightedOption?.id && !!highlightedOption?.isSetByClickEvent,\n };\n };\n\n const inputProps: InputProps = {\n \"aria-activedescendant\": highlightedOption ? createListboxItemId(highlightedOption) : undefined,\n \"aria-autocomplete\": \"list\",\n \"aria-controls\": listboxProps.id,\n \"data-testid\": getTestId(\"input\"),\n autoComplete: \"off\",\n id: `${id}-input`,\n onChange: handleOnChange,\n onMouseDown: handleOnMouseDown,\n onFocus: handleOnFocus,\n onKeyDown: handleOnKeyDown,\n onBlur: handleOnBlur,\n ref: inputRef,\n role: \"combobox\",\n value: definiteInputValue,\n };\n\n return {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n };\n};\n","import type { ComponentPropsWithRef, ForwardedRef, ReactNode } from \"react\";\nimport React, { cloneElement, forwardRef } from \"react\";\nimport { IconChevronDown } from \"@purpur/icon/chevron-down\";\nimport { Listbox } from \"@purpur/listbox\";\nimport { isTextField } from \"@purpur/text-field\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./autocomplete.module.scss\";\nimport type { AutocompleteOption, UseAutocompleteResult } from \"./useAutocomplete\";\nimport { useAutocomplete } from \"./useAutocomplete\";\nimport type { Prettify } from \"./utils\";\n\nconst cx = c.bind(styles);\n\ntype AutocompleteProps<T extends AutocompleteOption> = Prettify<\n UseAutocompleteResult<T> & {\n className?: string;\n /**\n * Render the input. `props` are native input props\n */\n renderInput: (props: ComponentPropsWithRef<\"input\">) => ReactNode;\n /**\n * Invoked for each given option. Use to customize the rendering of the options\n */\n renderOption?: (option: T) => ReactNode;\n }\n>;\n\nconst rootClassName = \"purpur-autocomplete\";\n\nconst AutocompleteComponent = <T extends AutocompleteOption>(\n { className, renderInput, renderOption, ...useAutocompleteProps }: AutocompleteProps<T>,\n ref: ForwardedRef<HTMLDivElement>\n) => {\n const {\n id,\n inputProps,\n internalRef,\n optionsToShow,\n showListbox,\n noOptionsText,\n combobox,\n comboboxButtonAriaLabel,\n getListBoxItemProps,\n listboxProps,\n } = useAutocomplete(useAutocompleteProps);\n\n const renderListboxItem = (option: T, index: number) => {\n const { key, ...listboxItemProps } = getListBoxItemProps(option, index);\n\n return (\n <Listbox.Item key={key} {...listboxItemProps}>\n {renderOption ? renderOption?.(option) : option.label}\n </Listbox.Item>\n );\n };\n\n const setRootRef = (node: HTMLDivElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n };\n\n const getInputComponent = () => {\n const input = renderInput(inputProps);\n const isCombobox =\n combobox && comboboxButtonAriaLabel && noOptionsText && input && isTextField(input);\n\n if (isCombobox) {\n const endAdornment = (\n <>\n {input.props.endAdornment}\n <button\n data-testid=\"chevron button\"\n type=\"button\"\n className={cx(`${rootClassName}__chevron-button`)}\n onClick={() => {\n inputProps.onFocus(undefined);\n inputProps.onMouseDown(undefined);\n }}\n aria-label={comboboxButtonAriaLabel}\n aria-expanded={showListbox}\n aria-controls={listboxProps.id}\n >\n <IconChevronDown\n size=\"sm\"\n className={cx(`${rootClassName}__chevron-icon`, {\n [`${rootClassName}__chevron-icon--up`]: showListbox,\n })}\n />\n </button>\n </>\n );\n\n return cloneElement(input, { endAdornment });\n }\n\n return input;\n };\n\n return (\n <div id={id} ref={setRootRef} className={cx([rootClassName, className])}>\n {getInputComponent()}\n {showListbox && (\n <Listbox {...listboxProps} className={cx(`${rootClassName}__listbox`)}>\n {!optionsToShow.length ? (\n <Listbox.Item noninteractive>{noOptionsText}</Listbox.Item>\n ) : (\n optionsToShow.filter((option): option is T => !!option).map(renderListboxItem)\n )}\n </Listbox>\n )}\n </div>\n );\n};\n\nexport const Autocomplete = forwardRef(AutocompleteComponent);\nAutocomplete.displayName = \"Autocomplete\";\n\nexport type {\n AutocompleteOption,\n UseAutocompleteResult as UseAutocompleteOptions,\n} from \"./useAutocomplete\";\nexport { useAutocomplete } from \"./useAutocomplete\";\n"],"names":["useRefObject","value","useRef","useOnClickOutside","element","callback","handleClickOutside","useCallback","event","useEffect","useAutocomplete","combobox","comboboxButtonAriaLabel","highlightFirstOption","defaultInputValue","inputValue","filterOption","id","listboxLabel","listboxMaxHeight","onInputBlur","onInputChange","onInputFocus","onInputKeyDown","onInputMouseDown","openOnFocus","noOptionsText","onSelect","options","selectedOption","dataTestid","internalInputValue","setInternalInputValue","useState","definiteInputValue","highlightedOption","setHighlightedOption","inputRef","internalRef","listboxRef","optionRefs","listboxIsOpen","setListboxIsOpen","getTestId","name","closeListbox","openListbox","eventType","scrollOptionIntoView","filterOptions","searchTerm","option","searchTermChunks","chunk","getOptionsToShow","optionsToShow","populateInputField","optionRect","listboxRect","selectOption","findNextOption","key","index","optionsLength","showListbox","highlightNextOption","nextOption","handleOnKeyDown","optionToSelect","handleOnChange","nextOptionsToShow","handleOnMouseDown","handleOnFocus","handleOnBlur","listboxStyle","listboxProps","createListboxItemId","getListBoxItemProps","handleOnMouseMove","highlighted","el","inputProps","cx","c","styles","rootClassName","AutocompleteComponent","className","renderInput","renderOption","useAutocompleteProps","ref","renderListboxItem","listboxItemProps","jsx","Listbox","setRootRef","node","getInputComponent","input","isTextField","endAdornment","jsxs","Fragment","IconChevronDown","cloneElement","Autocomplete","forwardRef"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./autocomplete-yD0-1vlF.js");exports.Autocomplete=e.Autocomplete;exports.useAutocomplete=e.useAutocomplete;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./autocomplete-6qSqK3SI.js");exports.Autocomplete=e.Autocomplete;exports.useAutocomplete=e.useAutocomplete;
2
2
  //# sourceMappingURL=autocomplete.cjs.js.map
@@ -1,4 +1,4 @@
1
- import { A as t, u } from "./autocomplete-0kGG_STe.mjs";
1
+ import { A as t, u } from "./autocomplete-B4dZx9zF.mjs";
2
2
  export {
3
3
  t as Autocomplete,
4
4
  u as useAutocomplete
@@ -0,0 +1,102 @@
1
+ import { jsxs as y, jsx as g } from "react/jsx-runtime";
2
+ import { forwardRef as T } from "react";
3
+ import { a as $ } from "./spinner-DRQN6YdK.mjs";
4
+ import { c as E } from "./bind-CU-R61T-.mjs";
5
+ const N = {
6
+ PRIMARY: "primary",
7
+ SECONDARY: "secondary",
8
+ EXPRESSIVE: "expressive"
9
+ }, R = {
10
+ LG: "lg"
11
+ }, S = {
12
+ "purpur-button": "_purpur-button_m4udv_1",
13
+ "purpur-button--xs": "_purpur-button--xs_m4udv_22",
14
+ "purpur-button--icon-only": "_purpur-button--icon-only_m4udv_25",
15
+ "purpur-button--sm": "_purpur-button--sm_m4udv_28",
16
+ "purpur-button--md": "_purpur-button--md_m4udv_34",
17
+ "purpur-button--lg": "_purpur-button--lg_m4udv_40",
18
+ "purpur-button--full-width": "_purpur-button--full-width_m4udv_46",
19
+ "purpur-button--primary": "_purpur-button--primary_m4udv_64",
20
+ "purpur-button--disabled": "_purpur-button--disabled_m4udv_68",
21
+ "purpur-button--primary-negative": "_purpur-button--primary-negative_m4udv_74",
22
+ "purpur-button--secondary": "_purpur-button--secondary_m4udv_86",
23
+ "purpur-button--secondary-negative": "_purpur-button--secondary-negative_m4udv_97",
24
+ "purpur-button--expressive": "_purpur-button--expressive_m4udv_108",
25
+ "purpur-button--expressive-negative": "_purpur-button--expressive-negative_m4udv_118",
26
+ "purpur-button--negative": "_purpur-button--negative_m4udv_130",
27
+ "purpur-button--destructive": "_purpur-button--destructive_m4udv_137",
28
+ "purpur-button--destructive-negative": "_purpur-button--destructive-negative_m4udv_147",
29
+ "purpur-button--text": "_purpur-button--text_m4udv_157",
30
+ "purpur-button--text-negative": "_purpur-button--text-negative_m4udv_157",
31
+ "purpur-button__spinner": "_purpur-button__spinner_m4udv_202"
32
+ }, A = {
33
+ ...N,
34
+ DESTRUCTIVE: "destructive",
35
+ TEXT: "text"
36
+ }, C = Object.values(A), a = E.bind(S), u = "purpur-button", j = ["button", "submit", "reset"], B = T(
37
+ ({
38
+ children: d,
39
+ className: m,
40
+ disabled: r = !1,
41
+ fullWidth: v = !1,
42
+ iconOnly: n,
43
+ loading: t = !1,
44
+ negative: p = !1,
45
+ onClick: o,
46
+ size: s = "md",
47
+ variant: e,
48
+ type: c = "button",
49
+ ..._
50
+ }, l) => {
51
+ if (n && e === "destructive")
52
+ return null;
53
+ const x = a(
54
+ [
55
+ u,
56
+ `${u}--${p ? `${e}-negative` : e}`,
57
+ `${u}--${s}`
58
+ ],
59
+ {
60
+ [`${u}--icon-only`]: n,
61
+ [`${u}--negative`]: p,
62
+ [`${u}--full-width`]: v,
63
+ [`${u}--disabled`]: r || t
64
+ },
65
+ m
66
+ ), f = (i) => {
67
+ r || t ? i.preventDefault() : o && o(i);
68
+ }, b = !!_["aria-disabled"] || r || t;
69
+ return /* @__PURE__ */ y(
70
+ "button",
71
+ {
72
+ className: x,
73
+ type: c,
74
+ ref: l,
75
+ "aria-disabled": b,
76
+ onClick: f,
77
+ ..._,
78
+ children: [
79
+ t && /* @__PURE__ */ g(
80
+ $,
81
+ {
82
+ size: s === R.LG ? "xs" : "xxs",
83
+ negative: p,
84
+ disabled: b,
85
+ className: a(`${u}__spinner`)
86
+ }
87
+ ),
88
+ " ",
89
+ d
90
+ ]
91
+ }
92
+ );
93
+ }
94
+ );
95
+ B.displayName = "Button";
96
+ export {
97
+ j as B,
98
+ A as a,
99
+ B as b,
100
+ C as c
101
+ };
102
+ //# sourceMappingURL=button-BfYKNBmC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-BfYKNBmC.mjs","sources":["../../action/src/action.tsx","../../../components/button/src/button.tsx"],"sourcesContent":["import { type ReactNode } from \"react\";\n\nexport const VARIANT = {\n PRIMARY: \"primary\",\n SECONDARY: \"secondary\",\n EXPRESSIVE: \"expressive\",\n} as const;\n\nexport const variants = Object.values(VARIANT);\nexport type Variant = (typeof VARIANT)[keyof typeof VARIANT];\n\nexport const SIZE = {\n XS: \"xs\",\n SM: \"sm\",\n MD: \"md\",\n LG: \"lg\",\n} as const;\n\nexport const sizes = Object.values(SIZE);\nexport type Size = (typeof SIZE)[keyof typeof SIZE];\n\ntype DefaultProps<TVariant, T = object> = {\n [\"data-testid\"]?: string;\n children?: ReactNode;\n className?: string;\n fullWidth?: boolean;\n negative?: boolean;\n size?: Size;\n variant: TVariant | Variant;\n} & T;\n\nexport type UnionParams<TVariant> =\n | DefaultProps<TVariant, { iconOnly: boolean; [\"aria-label\"]: string }>\n | DefaultProps<TVariant, { [\"aria-label\"]?: string }>;\n\ntype UnionKeys<T> = T extends T ? keyof T : never;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype StrictUnionHelper<T, TAll> = T extends any\n ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>>\n : never;\n\ntype StrictUnion<T> = StrictUnionHelper<T, T>;\n\nexport type ActionProps<TVariant extends string = Variant> = StrictUnion<UnionParams<TVariant>>;\n","import React, { type ButtonHTMLAttributes, forwardRef, type MouseEvent } from \"react\";\nimport { type ActionProps, SIZE, VARIANT } from \"@purpur/action\";\nimport type { BaseProps } from \"@purpur/common-types\";\nimport { Spinner } from \"@purpur/spinner\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./button.module.scss\";\n\nexport const BUTTON_VARIANT = {\n ...VARIANT,\n DESTRUCTIVE: \"destructive\",\n TEXT: \"text\",\n} as const;\n\nexport const buttonVariants = Object.values(BUTTON_VARIANT);\nexport type ButtonVariant = (typeof BUTTON_VARIANT)[keyof typeof BUTTON_VARIANT];\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-button\";\n\ntype ButtonType = Pick<ButtonHTMLAttributes<HTMLButtonElement>, \"type\">[\"type\"];\nexport const BUTTON_TYPES: ButtonType[] = [\"button\", \"submit\", \"reset\"] as const;\n\nexport type ButtonProps = ActionProps<ButtonVariant> & BaseProps<\"button\"> & { loading?: boolean };\n\nexport const Button = forwardRef<\n HTMLButtonElement,\n Omit<ButtonProps, \"type\"> & { type?: ButtonType }\n>(\n (\n {\n children,\n className,\n disabled = false,\n fullWidth = false,\n iconOnly,\n loading = false,\n negative = false,\n onClick,\n size = \"md\",\n variant,\n type = \"button\",\n ...props\n },\n ref\n ) => {\n if (iconOnly && variant === \"destructive\") {\n return null;\n }\n\n const classes = cx(\n [\n rootClassName,\n `${rootClassName}--${negative ? `${variant}-negative` : variant}`,\n `${rootClassName}--${size}`,\n ],\n {\n [`${rootClassName}--icon-only`]: iconOnly,\n [`${rootClassName}--negative`]: negative,\n [`${rootClassName}--full-width`]: fullWidth,\n [`${rootClassName}--disabled`]: disabled || loading,\n },\n className\n );\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n if (disabled || loading) {\n e.preventDefault();\n } else if (onClick) {\n onClick(e);\n }\n };\n\n const _disabled = Boolean(props[\"aria-disabled\"]) || disabled || loading;\n\n return (\n <button\n className={classes}\n type={type}\n ref={ref}\n aria-disabled={_disabled}\n onClick={handleClick}\n {...props}\n >\n {loading && (\n <Spinner\n size={size === SIZE.LG ? \"xs\" : \"xxs\"}\n negative={negative}\n disabled={_disabled}\n className={cx(`${rootClassName}__spinner`)}\n />\n )}{\" \"}\n {children}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n"],"names":["VARIANT","SIZE","BUTTON_VARIANT","buttonVariants","cx","c","styles","rootClassName","BUTTON_TYPES","Button","forwardRef","children","className","disabled","fullWidth","iconOnly","loading","negative","onClick","size","variant","type","props","ref","classes","handleClick","e","_disabled","jsxs","jsx","Spinner"],"mappings":";;;;AAEO,MAAMA,IAAU;AAAA,EACrB,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AACd,GAKaC,IAAO;AAAA,EAIlB,IAAI;AACN;;;;;;;;;;;;;;;;;;;;;GCRaC,IAAiB;AAAA,EAC5B,GAAGF;AAAA,EACH,aAAa;AAAA,EACb,MAAM;AACR,GAEaG,IAAiB,OAAO,OAAOD,CAAc,GAGpDE,IAAKC,EAAE,KAAKC,CAAM,GAClBC,IAAgB,iBAGTC,IAA6B,CAAC,UAAU,UAAU,OAAO,GAIzDC,IAASC;AAAA,EAIpB,CACE;AAAA,IACE,UAAAC;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,WAAAC,IAAY;AAAA,IACZ,UAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,UAAAC,IAAW;AAAA,IACX,SAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,SAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,QAAIR,KAAYK,MAAY;AAC1B,aAAO;AAGT,UAAMI,IAAUpB;AAAA,MACd;AAAA,QACEG;AAAA,QACA,GAAGA,CAAa,KAAKU,IAAW,GAAGG,CAAO,cAAcA,CAAO;AAAA,QAC/D,GAAGb,CAAa,KAAKY,CAAI;AAAA,MAAA;AAAA,MAE3B;AAAA,QACE,CAAC,GAAGZ,CAAa,aAAa,GAAGQ;AAAA,QACjC,CAAC,GAAGR,CAAa,YAAY,GAAGU;AAAA,QAChC,CAAC,GAAGV,CAAa,cAAc,GAAGO;AAAA,QAClC,CAAC,GAAGP,CAAa,YAAY,GAAGM,KAAYG;AAAA,MAAA;AAAA,MAE9CJ;AAAA,IAAA,GAGIa,IAAc,CAACC,MAAqC;AACxD,MAAIb,KAAYG,IACdU,EAAE,eAAA,IACOR,KACTA,EAAQQ,CAAC;AAAA,IAEb,GAEMC,IAAY,EAAQL,EAAM,eAAe,KAAMT,KAAYG;AAEjE,WACE,gBAAAY;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWJ;AAAA,QACX,MAAAH;AAAA,QACA,KAAAE;AAAA,QACA,iBAAeI;AAAA,QACf,SAASF;AAAA,QACR,GAAGH;AAAA,QAEH,UAAA;AAAA,UAAAN,KACC,gBAAAa;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,MAAMX,MAASlB,EAAK,KAAK,OAAO;AAAA,cAChC,UAAAgB;AAAA,cACA,UAAUU;AAAA,cACV,WAAWvB,EAAG,GAAGG,CAAa,WAAW;AAAA,YAAA;AAAA,UAAA;AAAA,UAE1C;AAAA,UACFI;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEAF,EAAO,cAAc;"}
@@ -0,0 +1,2 @@
1
+ "use strict";const d=require("react/jsx-runtime"),N=require("react"),R=require("./spinner-tKunS_o-.js"),E=require("./bind-DeUYJ6m9.js"),$={PRIMARY:"primary",SECONDARY:"secondary",EXPRESSIVE:"expressive"},A={LG:"lg"},B={"purpur-button":"_purpur-button_m4udv_1","purpur-button--xs":"_purpur-button--xs_m4udv_22","purpur-button--icon-only":"_purpur-button--icon-only_m4udv_25","purpur-button--sm":"_purpur-button--sm_m4udv_28","purpur-button--md":"_purpur-button--md_m4udv_34","purpur-button--lg":"_purpur-button--lg_m4udv_40","purpur-button--full-width":"_purpur-button--full-width_m4udv_46","purpur-button--primary":"_purpur-button--primary_m4udv_64","purpur-button--disabled":"_purpur-button--disabled_m4udv_68","purpur-button--primary-negative":"_purpur-button--primary-negative_m4udv_74","purpur-button--secondary":"_purpur-button--secondary_m4udv_86","purpur-button--secondary-negative":"_purpur-button--secondary-negative_m4udv_97","purpur-button--expressive":"_purpur-button--expressive_m4udv_108","purpur-button--expressive-negative":"_purpur-button--expressive-negative_m4udv_118","purpur-button--negative":"_purpur-button--negative_m4udv_130","purpur-button--destructive":"_purpur-button--destructive_m4udv_137","purpur-button--destructive-negative":"_purpur-button--destructive-negative_m4udv_147","purpur-button--text":"_purpur-button--text_m4udv_157","purpur-button--text-negative":"_purpur-button--text-negative_m4udv_157","purpur-button__spinner":"_purpur-button__spinner_m4udv_202"},v={...$,DESTRUCTIVE:"destructive",TEXT:"text"},S=Object.values(v),a=E.c.bind(B),u="purpur-button",I=["button","submit","reset"],c=N.forwardRef(({children:m,className:l,disabled:r=!1,fullWidth:x=!1,iconOnly:p,loading:t=!1,negative:e=!1,onClick:s,size:o="md",variant:n,type:T="button",..._},y)=>{if(p&&n==="destructive")return null;const f=a([u,`${u}--${e?`${n}-negative`:n}`,`${u}--${o}`],{[`${u}--icon-only`]:p,[`${u}--negative`]:e,[`${u}--full-width`]:x,[`${u}--disabled`]:r||t},l),g=b=>{r||t?b.preventDefault():s&&s(b)},i=!!_["aria-disabled"]||r||t;return d.jsxs("button",{className:f,type:T,ref:y,"aria-disabled":i,onClick:g,..._,children:[t&&d.jsx(R.Spinner,{size:o===A.LG?"xs":"xxs",negative:e,disabled:i,className:a(`${u}__spinner`)})," ",m]})});c.displayName="Button";exports.BUTTON_TYPES=I;exports.BUTTON_VARIANT=v;exports.Button=c;exports.buttonVariants=S;
2
+ //# sourceMappingURL=button-DDYGuqZ0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-DDYGuqZ0.js","sources":["../../action/src/action.tsx","../../../components/button/src/button.tsx"],"sourcesContent":["import { type ReactNode } from \"react\";\n\nexport const VARIANT = {\n PRIMARY: \"primary\",\n SECONDARY: \"secondary\",\n EXPRESSIVE: \"expressive\",\n} as const;\n\nexport const variants = Object.values(VARIANT);\nexport type Variant = (typeof VARIANT)[keyof typeof VARIANT];\n\nexport const SIZE = {\n XS: \"xs\",\n SM: \"sm\",\n MD: \"md\",\n LG: \"lg\",\n} as const;\n\nexport const sizes = Object.values(SIZE);\nexport type Size = (typeof SIZE)[keyof typeof SIZE];\n\ntype DefaultProps<TVariant, T = object> = {\n [\"data-testid\"]?: string;\n children?: ReactNode;\n className?: string;\n fullWidth?: boolean;\n negative?: boolean;\n size?: Size;\n variant: TVariant | Variant;\n} & T;\n\nexport type UnionParams<TVariant> =\n | DefaultProps<TVariant, { iconOnly: boolean; [\"aria-label\"]: string }>\n | DefaultProps<TVariant, { [\"aria-label\"]?: string }>;\n\ntype UnionKeys<T> = T extends T ? keyof T : never;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype StrictUnionHelper<T, TAll> = T extends any\n ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>>\n : never;\n\ntype StrictUnion<T> = StrictUnionHelper<T, T>;\n\nexport type ActionProps<TVariant extends string = Variant> = StrictUnion<UnionParams<TVariant>>;\n","import React, { type ButtonHTMLAttributes, forwardRef, type MouseEvent } from \"react\";\nimport { type ActionProps, SIZE, VARIANT } from \"@purpur/action\";\nimport type { BaseProps } from \"@purpur/common-types\";\nimport { Spinner } from \"@purpur/spinner\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./button.module.scss\";\n\nexport const BUTTON_VARIANT = {\n ...VARIANT,\n DESTRUCTIVE: \"destructive\",\n TEXT: \"text\",\n} as const;\n\nexport const buttonVariants = Object.values(BUTTON_VARIANT);\nexport type ButtonVariant = (typeof BUTTON_VARIANT)[keyof typeof BUTTON_VARIANT];\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-button\";\n\ntype ButtonType = Pick<ButtonHTMLAttributes<HTMLButtonElement>, \"type\">[\"type\"];\nexport const BUTTON_TYPES: ButtonType[] = [\"button\", \"submit\", \"reset\"] as const;\n\nexport type ButtonProps = ActionProps<ButtonVariant> & BaseProps<\"button\"> & { loading?: boolean };\n\nexport const Button = forwardRef<\n HTMLButtonElement,\n Omit<ButtonProps, \"type\"> & { type?: ButtonType }\n>(\n (\n {\n children,\n className,\n disabled = false,\n fullWidth = false,\n iconOnly,\n loading = false,\n negative = false,\n onClick,\n size = \"md\",\n variant,\n type = \"button\",\n ...props\n },\n ref\n ) => {\n if (iconOnly && variant === \"destructive\") {\n return null;\n }\n\n const classes = cx(\n [\n rootClassName,\n `${rootClassName}--${negative ? `${variant}-negative` : variant}`,\n `${rootClassName}--${size}`,\n ],\n {\n [`${rootClassName}--icon-only`]: iconOnly,\n [`${rootClassName}--negative`]: negative,\n [`${rootClassName}--full-width`]: fullWidth,\n [`${rootClassName}--disabled`]: disabled || loading,\n },\n className\n );\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n if (disabled || loading) {\n e.preventDefault();\n } else if (onClick) {\n onClick(e);\n }\n };\n\n const _disabled = Boolean(props[\"aria-disabled\"]) || disabled || loading;\n\n return (\n <button\n className={classes}\n type={type}\n ref={ref}\n aria-disabled={_disabled}\n onClick={handleClick}\n {...props}\n >\n {loading && (\n <Spinner\n size={size === SIZE.LG ? \"xs\" : \"xxs\"}\n negative={negative}\n disabled={_disabled}\n className={cx(`${rootClassName}__spinner`)}\n />\n )}{\" \"}\n {children}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n"],"names":["VARIANT","SIZE","BUTTON_VARIANT","buttonVariants","cx","c","styles","rootClassName","BUTTON_TYPES","Button","forwardRef","children","className","disabled","fullWidth","iconOnly","loading","negative","onClick","size","variant","type","props","ref","classes","handleClick","e","_disabled","jsxs","jsx","Spinner"],"mappings":"wIAEaA,EAAU,CACrB,QAAS,UACT,UAAW,YACX,WAAY,YACd,EAKaC,EAAO,CAIlB,GAAI,IACN,mwCCRaC,EAAiB,CAC5B,GAAGF,EACH,YAAa,cACb,KAAM,MACR,EAEaG,EAAiB,OAAO,OAAOD,CAAc,EAGpDE,EAAKC,EAAAA,EAAE,KAAKC,CAAM,EAClBC,EAAgB,gBAGTC,EAA6B,CAAC,SAAU,SAAU,OAAO,EAIzDC,EAASC,EAAAA,WAIpB,CACE,CACE,SAAAC,EACA,UAAAC,EACA,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,SAAAC,EACA,QAAAC,EAAU,GACV,SAAAC,EAAW,GACX,QAAAC,EACA,KAAAC,EAAO,KACP,QAAAC,EACA,KAAAC,EAAO,SACP,GAAGC,CAAA,EAELC,IACG,CACH,GAAIR,GAAYK,IAAY,cAC1B,OAAO,KAGT,MAAMI,EAAUpB,EACd,CACEG,EACA,GAAGA,CAAa,KAAKU,EAAW,GAAGG,CAAO,YAAcA,CAAO,GAC/D,GAAGb,CAAa,KAAKY,CAAI,EAAA,EAE3B,CACE,CAAC,GAAGZ,CAAa,aAAa,EAAGQ,EACjC,CAAC,GAAGR,CAAa,YAAY,EAAGU,EAChC,CAAC,GAAGV,CAAa,cAAc,EAAGO,EAClC,CAAC,GAAGP,CAAa,YAAY,EAAGM,GAAYG,CAAA,EAE9CJ,CAAA,EAGIa,EAAeC,GAAqC,CACpDb,GAAYG,EACdU,EAAE,eAAA,EACOR,GACTA,EAAQQ,CAAC,CAEb,EAEMC,EAAY,EAAQL,EAAM,eAAe,GAAMT,GAAYG,EAEjE,OACEY,EAAAA,KAAC,SAAA,CACC,UAAWJ,EACX,KAAAH,EACA,IAAAE,EACA,gBAAeI,EACf,QAASF,EACR,GAAGH,EAEH,SAAA,CAAAN,GACCa,EAAAA,IAACC,EAAAA,QAAA,CACC,KAAMX,IAASlB,EAAK,GAAK,KAAO,MAChC,SAAAgB,EACA,SAAUU,EACV,UAAWvB,EAAG,GAAGG,CAAa,WAAW,CAAA,CAAA,EAE1C,IACFI,CAAA,CAAA,CAAA,CAGP,CACF,EAEAF,EAAO,YAAc"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./button-ChYUPi2k.js");exports.BUTTON_TYPES=t.BUTTON_TYPES;exports.BUTTON_VARIANT=t.BUTTON_VARIANT;exports.Button=t.Button;exports.buttonVariants=t.buttonVariants;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./button-DDYGuqZ0.js");exports.BUTTON_TYPES=t.BUTTON_TYPES;exports.BUTTON_VARIANT=t.BUTTON_VARIANT;exports.Button=t.Button;exports.buttonVariants=t.buttonVariants;
2
2
  //# sourceMappingURL=button.cjs.js.map
package/dist/button.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as T, B as s, c as o, b as B } from "./button-DBX_tvfJ.mjs";
1
+ import { B as T, a as s, b as o, c as B } from "./button-BfYKNBmC.mjs";
2
2
  export {
3
3
  T as BUTTON_TYPES,
4
4
  s as BUTTON_VARIANT,