@purpur/library 9.0.9 → 9.0.10

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 (206) hide show
  1. package/CHANGELOG.json +30 -0
  2. package/CHANGELOG.md +14 -1
  3. package/dist/LICENSE.txt +7 -7
  4. package/dist/{autocomplete-DJ3zbA0m.mjs → autocomplete-Dn503hFM.mjs} +2 -2
  5. package/dist/{autocomplete-DJ3zbA0m.mjs.map → autocomplete-Dn503hFM.mjs.map} +1 -1
  6. package/dist/{autocomplete-B_OBQM2h.js → autocomplete-Dy8YL7Mo.js} +2 -2
  7. package/dist/{autocomplete-B_OBQM2h.js.map → autocomplete-Dy8YL7Mo.js.map} +1 -1
  8. package/dist/autocomplete.cjs.js +1 -1
  9. package/dist/autocomplete.es.js +1 -1
  10. package/dist/button-Cv7NlYbv.mjs +109 -0
  11. package/dist/button-Cv7NlYbv.mjs.map +1 -0
  12. package/dist/button-Dqxdc3nC.js +2 -0
  13. package/dist/button-Dqxdc3nC.js.map +1 -0
  14. package/dist/button.cjs.js +1 -1
  15. package/dist/button.es.js +1 -1
  16. package/dist/{calendar-BSdvi_DA.js → calendar-C-F-pVCe.js} +2 -2
  17. package/dist/{calendar-BSdvi_DA.js.map → calendar-C-F-pVCe.js.map} +1 -1
  18. package/dist/{calendar-9p_aA7KY.mjs → calendar-DWpnuylk.mjs} +2 -2
  19. package/dist/{calendar-9p_aA7KY.mjs.map → calendar-DWpnuylk.mjs.map} +1 -1
  20. package/dist/calendar.cjs.js +1 -1
  21. package/dist/calendar.es.js +1 -1
  22. package/dist/components/button/src/button.d.ts +4 -0
  23. package/dist/components/button/src/button.d.ts.map +1 -1
  24. package/dist/components/drawer/src/drawer-container.d.ts +2 -0
  25. package/dist/components/drawer/src/drawer-container.d.ts.map +1 -1
  26. package/dist/components/drawer/src/drawer-content.d.ts.map +1 -1
  27. package/dist/components/drawer/src/drawer-frame.d.ts +2 -1
  28. package/dist/components/drawer/src/drawer-frame.d.ts.map +1 -1
  29. package/dist/components/drawer/src/drawer-handle.d.ts +2 -1
  30. package/dist/components/drawer/src/drawer-handle.d.ts.map +1 -1
  31. package/dist/components/drawer/src/drawer-header.d.ts +2 -0
  32. package/dist/components/drawer/src/drawer-header.d.ts.map +1 -1
  33. package/dist/components/drawer/src/drawer-scroll-area.d.ts +2 -0
  34. package/dist/components/drawer/src/drawer-scroll-area.d.ts.map +1 -1
  35. package/dist/components/drawer/src/drawer.context.d.ts +6 -2
  36. package/dist/components/drawer/src/drawer.context.d.ts.map +1 -1
  37. package/dist/components/drawer/src/drawer.d.ts +3 -0
  38. package/dist/components/drawer/src/drawer.d.ts.map +1 -1
  39. package/dist/components/drawer/src/types.d.ts +1 -0
  40. package/dist/components/drawer/src/types.d.ts.map +1 -1
  41. package/dist/components/notification/src/notification.d.ts +2 -1
  42. package/dist/components/notification/src/notification.d.ts.map +1 -1
  43. package/dist/components-metadata.js +1 -0
  44. package/dist/{date-field-Ch2lM7-P.mjs → date-field-DACXrowI.mjs} +2 -2
  45. package/dist/{date-field-Ch2lM7-P.mjs.map → date-field-DACXrowI.mjs.map} +1 -1
  46. package/dist/{date-field-DTI5mQkg.js → date-field-Z3LKO4b7.js} +2 -2
  47. package/dist/{date-field-DTI5mQkg.js.map → date-field-Z3LKO4b7.js.map} +1 -1
  48. package/dist/date-field.cjs.js +1 -1
  49. package/dist/date-field.es.js +1 -1
  50. package/dist/{date-picker-Dk39IXG5.js → date-picker-5Gr_cEqA.js} +2 -2
  51. package/dist/{date-picker-Dk39IXG5.js.map → date-picker-5Gr_cEqA.js.map} +1 -1
  52. package/dist/{date-picker-Bt3IaH23.mjs → date-picker-CdVUA8NC.mjs} +4 -4
  53. package/dist/{date-picker-Bt3IaH23.mjs.map → date-picker-CdVUA8NC.mjs.map} +1 -1
  54. package/dist/date-picker.cjs.js +1 -1
  55. package/dist/date-picker.es.js +1 -1
  56. package/dist/drawer-UdK-u7IX.js +2 -0
  57. package/dist/drawer-UdK-u7IX.js.map +1 -0
  58. package/dist/drawer-Vi9H2O3N.mjs +562 -0
  59. package/dist/drawer-Vi9H2O3N.mjs.map +1 -0
  60. package/dist/drawer.cjs.js +1 -1
  61. package/dist/drawer.es.js +1 -1
  62. package/dist/{hero-banner-B5HKmkXc.mjs → hero-banner-BjwICxaJ.mjs} +2 -2
  63. package/dist/{hero-banner-B5HKmkXc.mjs.map → hero-banner-BjwICxaJ.mjs.map} +1 -1
  64. package/dist/{hero-banner-OnNSuxNT.js → hero-banner-yGRM4OlS.js} +2 -2
  65. package/dist/{hero-banner-OnNSuxNT.js.map → hero-banner-yGRM4OlS.js.map} +1 -1
  66. package/dist/hero-banner.cjs.js +1 -1
  67. package/dist/hero-banner.es.js +1 -1
  68. package/dist/illustrative-icon/assets/json/cart-checkmark-duocolor-animated.json.d.ts +1 -1
  69. package/dist/illustrative-icon/assets/json/cart-checkmark-offblack-animated.json.d.ts +1 -1
  70. package/dist/illustrative-icon/assets/json/checkmark-duocolor-animated.json.d.ts +1 -1
  71. package/dist/illustrative-icon/assets/json/checkmark-offblack-animated.json.d.ts +1 -1
  72. package/dist/illustrative-icon/assets/json/document-checkmark-duocolor-animated.json.d.ts +1 -1
  73. package/dist/illustrative-icon/assets/json/document-checkmark-offblack-animated.json.d.ts +1 -1
  74. package/dist/illustrative-icon/assets/json/support-checkmark-duocolor-animated.json.d.ts +1 -1
  75. package/dist/illustrative-icon/assets/json/support-checkmark-offblack-animated.json.d.ts +1 -1
  76. package/dist/illustrative-icon/assets/json/user-checkmark-duocolor-animated.json.d.ts +1 -1
  77. package/dist/illustrative-icon/assets/json/user-checkmark-offblack-animated.json.d.ts +1 -1
  78. package/dist/illustrative-icon/components/cart-checkmark-duocolor-animated.cjs.js +1 -1
  79. package/dist/illustrative-icon/components/cart-checkmark-duocolor-animated.cjs.js.map +1 -1
  80. package/dist/illustrative-icon/components/cart-checkmark-duocolor-animated.es.js +1 -1
  81. package/dist/illustrative-icon/components/cart-checkmark-offblack-animated.cjs.js +1 -1
  82. package/dist/illustrative-icon/components/cart-checkmark-offblack-animated.cjs.js.map +1 -1
  83. package/dist/illustrative-icon/components/cart-checkmark-offblack-animated.es.js +1 -1
  84. package/dist/illustrative-icon/components/checkmark-duocolor-animated.cjs.js +1 -1
  85. package/dist/illustrative-icon/components/checkmark-duocolor-animated.cjs.js.map +1 -1
  86. package/dist/illustrative-icon/components/checkmark-duocolor-animated.es.js +1 -1
  87. package/dist/illustrative-icon/components/checkmark-offblack-animated.cjs.js +1 -1
  88. package/dist/illustrative-icon/components/checkmark-offblack-animated.cjs.js.map +1 -1
  89. package/dist/illustrative-icon/components/checkmark-offblack-animated.es.js +1 -1
  90. package/dist/illustrative-icon/components/document-checkmark-duocolor-animated.cjs.js +2 -2
  91. package/dist/illustrative-icon/components/document-checkmark-duocolor-animated.es.js +2 -2
  92. package/dist/illustrative-icon/components/document-checkmark-offblack-animated.cjs.js +2 -2
  93. package/dist/illustrative-icon/components/document-checkmark-offblack-animated.es.js +2 -2
  94. package/dist/illustrative-icon/components/support-checkmark-duocolor-animated.cjs.js +1 -1
  95. package/dist/illustrative-icon/components/support-checkmark-duocolor-animated.cjs.js.map +1 -1
  96. package/dist/illustrative-icon/components/support-checkmark-duocolor-animated.es.js +1 -1
  97. package/dist/illustrative-icon/components/support-checkmark-offblack-animated.cjs.js +1 -1
  98. package/dist/illustrative-icon/components/support-checkmark-offblack-animated.cjs.js.map +1 -1
  99. package/dist/illustrative-icon/components/support-checkmark-offblack-animated.es.js +1 -1
  100. package/dist/illustrative-icon/components/user-checkmark-duocolor-animated.cjs.js +1 -1
  101. package/dist/illustrative-icon/components/user-checkmark-duocolor-animated.es.js +1 -1
  102. package/dist/illustrative-icon/components/user-checkmark-offblack-animated.cjs.js +1 -1
  103. package/dist/illustrative-icon/components/user-checkmark-offblack-animated.es.js +1 -1
  104. package/dist/libraries/theme/src/theme-props.d.ts +1 -0
  105. package/dist/libraries/theme/src/theme-props.d.ts.map +1 -1
  106. package/dist/libraries/tokens/dist/border/variables.d.ts +1 -0
  107. package/dist/libraries/tokens/dist/border/variables.dark.d.ts +1 -0
  108. package/dist/library.cjs.js +1 -1
  109. package/dist/library.es.js +465 -464
  110. package/dist/{modal-CQiJ98iI.js → modal-DMeRO1wE.js} +2 -2
  111. package/dist/{modal-CQiJ98iI.js.map → modal-DMeRO1wE.js.map} +1 -1
  112. package/dist/{modal-B1eJu9HN.mjs → modal-fTWvPEPW.mjs} +2 -2
  113. package/dist/{modal-B1eJu9HN.mjs.map → modal-fTWvPEPW.mjs.map} +1 -1
  114. package/dist/modal.cjs.js +1 -1
  115. package/dist/modal.es.js +1 -1
  116. package/dist/{notification-BtcM7Ndu.mjs → notification-BvoL7BIW.mjs} +60 -51
  117. package/dist/notification-BvoL7BIW.mjs.map +1 -0
  118. package/dist/notification-DE1pvk9W.js +2 -0
  119. package/dist/notification-DE1pvk9W.js.map +1 -0
  120. package/dist/{notification-banner-CbKcE7o4.mjs → notification-banner-C4gkkSlf.mjs} +2 -2
  121. package/dist/{notification-banner-CbKcE7o4.mjs.map → notification-banner-C4gkkSlf.mjs.map} +1 -1
  122. package/dist/{notification-banner-B0CUuKZn.js → notification-banner-COH7wJu2.js} +2 -2
  123. package/dist/{notification-banner-B0CUuKZn.js.map → notification-banner-COH7wJu2.js.map} +1 -1
  124. package/dist/notification-banner.cjs.js +1 -1
  125. package/dist/notification-banner.es.js +1 -1
  126. package/dist/notification.cjs.js +1 -1
  127. package/dist/notification.es.js +1 -1
  128. package/dist/{popover-D6k4-oO1.js → popover-BnUVNqSi.js} +2 -2
  129. package/dist/{popover-D6k4-oO1.js.map → popover-BnUVNqSi.js.map} +1 -1
  130. package/dist/{popover-D3b2gHm-.mjs → popover-lxTyKALA.mjs} +2 -2
  131. package/dist/{popover-D3b2gHm-.mjs.map → popover-lxTyKALA.mjs.map} +1 -1
  132. package/dist/popover.cjs.js +1 -1
  133. package/dist/popover.es.js +1 -1
  134. package/dist/purpur.css +1 -1
  135. package/dist/{quantity-selector-Bc-4Dnpc.js → quantity-selector-D28He6R8.js} +2 -2
  136. package/dist/{quantity-selector-Bc-4Dnpc.js.map → quantity-selector-D28He6R8.js.map} +1 -1
  137. package/dist/{quantity-selector-Djf8APeL.mjs → quantity-selector-w10wKMmT.mjs} +3 -3
  138. package/dist/{quantity-selector-Djf8APeL.mjs.map → quantity-selector-w10wKMmT.mjs.map} +1 -1
  139. package/dist/quantity-selector.cjs.js +1 -1
  140. package/dist/quantity-selector.es.js +1 -1
  141. package/dist/{search-field-0CBoxcNH.js → search-field-CNpJp3Tg.js} +2 -2
  142. package/dist/{search-field-0CBoxcNH.js.map → search-field-CNpJp3Tg.js.map} +1 -1
  143. package/dist/{search-field-aP_i6Nr0.mjs → search-field-CWqLnqdo.mjs} +3 -3
  144. package/dist/{search-field-aP_i6Nr0.mjs.map → search-field-CWqLnqdo.mjs.map} +1 -1
  145. package/dist/search-field.cjs.js +1 -1
  146. package/dist/search-field.es.js +1 -1
  147. package/dist/{stepper-CTdGj87I.mjs → stepper-B351hexi.mjs} +3 -3
  148. package/dist/{stepper-CTdGj87I.mjs.map → stepper-B351hexi.mjs.map} +1 -1
  149. package/dist/{stepper-BaoOY4Ea.js → stepper-Cb4_9D2h.js} +2 -2
  150. package/dist/{stepper-BaoOY4Ea.js.map → stepper-Cb4_9D2h.js.map} +1 -1
  151. package/dist/stepper.cjs.js +1 -1
  152. package/dist/stepper.es.js +1 -1
  153. package/dist/{table-TdOPMFoP.js → table-CJijBJsy.js} +2 -2
  154. package/dist/{table-TdOPMFoP.js.map → table-CJijBJsy.js.map} +1 -1
  155. package/dist/{table-D7qthqj_.mjs → table-YR-bpfU0.mjs} +5 -5
  156. package/dist/{table-D7qthqj_.mjs.map → table-YR-bpfU0.mjs.map} +1 -1
  157. package/dist/table.cjs.js +1 -1
  158. package/dist/table.es.js +1 -1
  159. package/dist/{text-field-9zPmL99g.mjs → text-field-BMDf8j-K.mjs} +2 -2
  160. package/dist/{text-field-9zPmL99g.mjs.map → text-field-BMDf8j-K.mjs.map} +1 -1
  161. package/dist/{text-field-CKCwxTJX.js → text-field-CiLEj0Fq.js} +2 -2
  162. package/dist/{text-field-CKCwxTJX.js.map → text-field-CiLEj0Fq.js.map} +1 -1
  163. package/dist/text-field.cjs.js +1 -1
  164. package/dist/text-field.es.js +1 -1
  165. package/dist/tokens/border/variables.css +1 -0
  166. package/dist/tokens/border/variables.d.ts +1 -0
  167. package/dist/tokens/border/variables.dark.css +1 -0
  168. package/dist/tokens/border/variables.dark.d.ts +1 -0
  169. package/dist/tokens/border/variables.dark.js +1 -0
  170. package/dist/tokens/border/variables.dark.json +1 -0
  171. package/dist/tokens/border/variables.dark.scss +1 -0
  172. package/dist/tokens/border/variables.js +1 -0
  173. package/dist/tokens/border/variables.json +1 -0
  174. package/dist/tokens/border/variables.scss +1 -0
  175. package/dist/tokens.cjs.js +1 -1
  176. package/dist/tokens.cjs.js.map +1 -1
  177. package/dist/tokens.es.js +337 -336
  178. package/dist/tokens.es.js.map +1 -1
  179. package/dist/{tooltip-BtGtu3ph.mjs → tooltip-BHsVKFJ3.mjs} +2 -2
  180. package/dist/{tooltip-BtGtu3ph.mjs.map → tooltip-BHsVKFJ3.mjs.map} +1 -1
  181. package/dist/{tooltip-eUP35j3v.js → tooltip-B_qTqtcF.js} +2 -2
  182. package/dist/{tooltip-eUP35j3v.js.map → tooltip-B_qTqtcF.js.map} +1 -1
  183. package/dist/tooltip.cjs.js +1 -1
  184. package/dist/tooltip.es.js +1 -1
  185. package/package.json +20 -20
  186. package/tokens/border/variables.css +1 -0
  187. package/tokens/border/variables.d.ts +1 -0
  188. package/tokens/border/variables.dark.css +1 -0
  189. package/tokens/border/variables.dark.d.ts +1 -0
  190. package/tokens/border/variables.dark.js +1 -0
  191. package/tokens/border/variables.dark.json +1 -0
  192. package/tokens/border/variables.dark.scss +1 -0
  193. package/tokens/border/variables.js +1 -0
  194. package/tokens/border/variables.json +1 -0
  195. package/tokens/border/variables.scss +1 -0
  196. package/dist/button-BxdChrq-.js +0 -2
  197. package/dist/button-BxdChrq-.js.map +0 -1
  198. package/dist/button-D-BBdNhd.mjs +0 -105
  199. package/dist/button-D-BBdNhd.mjs.map +0 -1
  200. package/dist/drawer-B6j8nfAY.mjs +0 -530
  201. package/dist/drawer-B6j8nfAY.mjs.map +0 -1
  202. package/dist/drawer-CJsLdd2x.js +0 -2
  203. package/dist/drawer-CJsLdd2x.js.map +0 -1
  204. package/dist/notification-BtcM7Ndu.mjs.map +0 -1
  205. package/dist/notification-Dsg3Vzfi.js +0 -2
  206. package/dist/notification-Dsg3Vzfi.js.map +0 -1
package/CHANGELOG.json CHANGED
@@ -1,6 +1,36 @@
1
1
  {
2
2
  "name": "@purpur/library",
3
3
  "entries": [
4
+ {
5
+ "version": "9.0.10",
6
+ "tag": "@purpur/library_v9.0.10",
7
+ "date": "Mon, 30 Mar 2026 07:48:48 GMT",
8
+ "comments": {
9
+ "none": [
10
+ {
11
+ "comment": "Theme: Add borderRadiusXl prop to ThemeProps"
12
+ },
13
+ {
14
+ "comment": "Tokens: Add border-radius xl token (24px/1.5rem)"
15
+ },
16
+ {
17
+ "comment": "Button: Added AI variants for primary, secondary, expressive and text"
18
+ },
19
+ {
20
+ "comment": "Drawer: Added AI variant"
21
+ },
22
+ {
23
+ "comment": "Notification: Added AI variant"
24
+ },
25
+ {
26
+ "comment": "Icon: Fix so that icons don't shrink in Storybook"
27
+ },
28
+ {
29
+ "comment": "IllustrativeIcon: Fix checkmark centering in animated Illustrative icons"
30
+ }
31
+ ]
32
+ }
33
+ },
4
34
  {
5
35
  "version": "9.0.9",
6
36
  "tag": "@purpur/library_v9.0.9",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # Change Log - @purpur/library
2
2
 
3
- This log was last generated on Thu, 26 Mar 2026 09:15:46 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 30 Mar 2026 07:48:48 GMT and should not be manually modified.
4
+
5
+ ## 9.0.10
6
+ Mon, 30 Mar 2026 07:48:48 GMT
7
+
8
+ ### Updates
9
+
10
+ - Theme: Add borderRadiusXl prop to ThemeProps
11
+ - Tokens: Add border-radius xl token (24px/1.5rem)
12
+ - Button: Added AI variants for primary, secondary, expressive and text
13
+ - Drawer: Added AI variant
14
+ - Notification: Added AI variant
15
+ - Icon: Fix so that icons don't shrink in Storybook
16
+ - IllustrativeIcon: Fix checkmark centering in animated Illustrative icons
4
17
 
5
18
  ## 9.0.9
6
19
  Thu, 26 Mar 2026 09:15:46 GMT
package/dist/LICENSE.txt CHANGED
@@ -814,13 +814,6 @@ Private: false
814
814
 
815
815
  ---
816
816
 
817
- Name: @purpur/notification
818
- Version: 8.21.0
819
- License: AGPL-3.0-only
820
- Private: false
821
-
822
- ---
823
-
824
817
  Name: @purpur/cta-link
825
818
  Version: 8.21.0
826
819
  License: AGPL-3.0-only
@@ -851,6 +844,13 @@ Private: false
851
844
 
852
845
  ---
853
846
 
847
+ Name: @purpur/notification
848
+ Version: 8.21.0
849
+ License: AGPL-3.0-only
850
+ Private: false
851
+
852
+ ---
853
+
854
854
  Name: tabbable
855
855
  Version: 6.4.0
856
856
  License: MIT
@@ -2,7 +2,7 @@ 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
4
  import { L as V } from "./listbox-oDeP8FvH.mjs";
5
- import { i as _e } from "./text-field-9zPmL99g.mjs";
5
+ import { i as _e } from "./text-field-BMDf8j-K.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-DJ3zbA0m.mjs.map
228
+ //# sourceMappingURL=autocomplete-Dn503hFM.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-DJ3zbA0m.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
+ {"version":3,"file":"autocomplete-Dn503hFM.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";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-CKCwxTJX.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-B_OBQM2h.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-CiLEj0Fq.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-Dy8YL7Mo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-B_OBQM2h.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-Dy8YL7Mo.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,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./autocomplete-B_OBQM2h.js");exports.Autocomplete=e.Autocomplete;exports.useAutocomplete=e.useAutocomplete;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./autocomplete-Dy8YL7Mo.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-DJ3zbA0m.mjs";
1
+ import { A as t, u } from "./autocomplete-Dn503hFM.mjs";
2
2
  export {
3
3
  t as Autocomplete,
4
4
  u as useAutocomplete
@@ -0,0 +1,109 @@
1
+ import { jsxs as g, jsx as f } from "react/jsx-runtime";
2
+ import { forwardRef as T } from "react";
3
+ import { a as R } from "./spinner-DRQN6YdK.mjs";
4
+ import { c as $ } from "./bind-CU-R61T-.mjs";
5
+ const E = {
6
+ PRIMARY: "primary",
7
+ SECONDARY: "secondary",
8
+ EXPRESSIVE: "expressive"
9
+ }, N = {
10
+ LG: "lg"
11
+ }, A = {
12
+ "purpur-button": "_purpur-button_zehbw_1",
13
+ "purpur-button--xs": "_purpur-button--xs_zehbw_22",
14
+ "purpur-button--icon-only": "_purpur-button--icon-only_zehbw_25",
15
+ "purpur-button--sm": "_purpur-button--sm_zehbw_28",
16
+ "purpur-button--md": "_purpur-button--md_zehbw_34",
17
+ "purpur-button--lg": "_purpur-button--lg_zehbw_40",
18
+ "purpur-button--full-width": "_purpur-button--full-width_zehbw_46",
19
+ "purpur-button--primary": "_purpur-button--primary_zehbw_64",
20
+ "purpur-button--disabled": "_purpur-button--disabled_zehbw_68",
21
+ "purpur-button--primary-negative": "_purpur-button--primary-negative_zehbw_74",
22
+ "purpur-button--secondary": "_purpur-button--secondary_zehbw_86",
23
+ "purpur-button--secondary-negative": "_purpur-button--secondary-negative_zehbw_97",
24
+ "purpur-button--expressive": "_purpur-button--expressive_zehbw_108",
25
+ "purpur-button--expressive-negative": "_purpur-button--expressive-negative_zehbw_118",
26
+ "purpur-button--negative": "_purpur-button--negative_zehbw_130",
27
+ "purpur-button--destructive": "_purpur-button--destructive_zehbw_137",
28
+ "purpur-button--destructive-negative": "_purpur-button--destructive-negative_zehbw_147",
29
+ "purpur-button--tertiary-purple": "_purpur-button--tertiary-purple_zehbw_157",
30
+ "purpur-button--tertiary-purple-negative": "_purpur-button--tertiary-purple-negative_zehbw_170",
31
+ "purpur-button--text": "_purpur-button--text_zehbw_185",
32
+ "purpur-button--text-negative": "_purpur-button--text-negative_zehbw_207",
33
+ "purpur-button--primary-ai": "_purpur-button--primary-ai_zehbw_230",
34
+ "purpur-button--primary-ai-negative": "_purpur-button--primary-ai-negative_zehbw_276",
35
+ "purpur-button--secondary-ai": "_purpur-button--secondary-ai_zehbw_323",
36
+ "purpur-button__spinner": "_purpur-button__spinner_zehbw_348",
37
+ "purpur-button--secondary-ai-negative": "_purpur-button--secondary-ai-negative_zehbw_416",
38
+ "purpur-button--expressive-ai": "_purpur-button--expressive-ai_zehbw_509",
39
+ "purpur-button--expressive-ai-negative": "_purpur-button--expressive-ai-negative_zehbw_556",
40
+ "purpur-button--text-ai": "_purpur-button--text-ai_zehbw_606",
41
+ "purpur-button--text-ai-negative": "_purpur-button--text-ai-negative_zehbw_679"
42
+ }, C = {
43
+ ...E,
44
+ DESTRUCTIVE: "destructive",
45
+ TERTIARY_PURPLE: "tertiary-purple",
46
+ TEXT: "text"
47
+ }, Y = Object.values(C), c = $.bind(A), t = "purpur-button", j = ["button", "submit", "reset"], I = ({ iconOnly: r, loading: e }) => !(r && e), S = T(
48
+ ({
49
+ ai: r = !1,
50
+ children: e,
51
+ className: v,
52
+ disabled: p = !1,
53
+ fullWidth: h = !1,
54
+ iconOnly: n,
55
+ loading: u = !1,
56
+ negative: o = !1,
57
+ onClick: b,
58
+ size: _ = "md",
59
+ variant: a,
60
+ type: d = "button",
61
+ ...i
62
+ }, w) => {
63
+ if (n && a === "destructive")
64
+ return null;
65
+ const z = `${a}${r ? "-ai" : ""}${o ? "-negative" : ""}`, m = c(
66
+ [t, `${t}--${z}`, `${t}--${_}`],
67
+ {
68
+ [`${t}--icon-only`]: n,
69
+ [`${t}--negative`]: o,
70
+ [`${t}--full-width`]: h,
71
+ [`${t}--disabled`]: p || u
72
+ },
73
+ v
74
+ ), x = (l) => {
75
+ p || u ? l.preventDefault() : b && b(l);
76
+ }, s = !!i["aria-disabled"] || p || u, y = I({ iconOnly: n, loading: u });
77
+ return /* @__PURE__ */ g(
78
+ "button",
79
+ {
80
+ className: m,
81
+ type: d,
82
+ ref: w,
83
+ "aria-disabled": s,
84
+ onClick: x,
85
+ ...i,
86
+ children: [
87
+ u && /* @__PURE__ */ f(
88
+ R,
89
+ {
90
+ size: _ === N.LG ? "xs" : "xxs",
91
+ negative: o,
92
+ disabled: s,
93
+ className: c(`${t}__spinner`)
94
+ }
95
+ ),
96
+ y ? e : null
97
+ ]
98
+ }
99
+ );
100
+ }
101
+ );
102
+ S.displayName = "Button";
103
+ export {
104
+ j as B,
105
+ C as a,
106
+ S as b,
107
+ Y as c
108
+ };
109
+ //# sourceMappingURL=button-Cv7NlYbv.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-Cv7NlYbv.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 TERTIARY_PURPLE: \"tertiary-purple\",\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\ntype ButtonBaseProps = BaseProps<\"button\"> & { ai?: boolean; loading?: boolean };\n\nexport type ButtonProps =\n | (ActionProps<ButtonVariant> & ButtonBaseProps & { iconOnly?: false | undefined })\n | (ActionProps<Exclude<ButtonVariant, \"destructive\">> & ButtonBaseProps & { iconOnly: true });\n\ntype DistributiveOmit<T, K extends keyof never> = T extends unknown ? Omit<T, K> : never;\n\nconst shouldRenderChildren = ({ iconOnly, loading }: Pick<ButtonProps, \"iconOnly\" | \"loading\">) =>\n !(iconOnly && loading);\n\nexport const Button = forwardRef<\n HTMLButtonElement,\n DistributiveOmit<ButtonProps, \"type\"> & { type?: ButtonType }\n>(\n (\n {\n ai = false,\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\" as string)) {\n return null;\n }\n\n const variantClass = `${variant}${ai ? \"-ai\" : \"\"}${negative ? \"-negative\" : \"\"}`;\n\n const classes = cx(\n [rootClassName, `${rootClassName}--${variantClass}`, `${rootClassName}--${size}`],\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 const renderChildren = shouldRenderChildren({ iconOnly, 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 {renderChildren ? children : null}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n"],"names":["VARIANT","SIZE","BUTTON_VARIANT","buttonVariants","cx","c","styles","rootClassName","BUTTON_TYPES","shouldRenderChildren","iconOnly","loading","Button","forwardRef","ai","children","className","disabled","fullWidth","negative","onClick","size","variant","type","props","ref","variantClass","classes","handleClick","e","_disabled","renderChildren","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,iBAAiB;AAAA,EACjB,MAAM;AACR,GAEaG,IAAiB,OAAO,OAAOD,CAAc,GAGpDE,IAAKC,EAAE,KAAKC,CAAM,GAClBC,IAAgB,iBAGTC,IAA6B,CAAC,UAAU,UAAU,OAAO,GAUhEC,IAAuB,CAAC,EAAE,UAAAC,GAAU,SAAAC,EAAA,MACxC,EAAED,KAAYC,IAEHC,IAASC;AAAA,EAIpB,CACE;AAAA,IACE,IAAAC,IAAK;AAAA,IACL,UAAAC;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,WAAAC,IAAY;AAAA,IACZ,UAAAR;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,UAAAQ,IAAW;AAAA,IACX,SAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,SAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,QAAIf,KAAYY,MAAa;AAC3B,aAAO;AAGT,UAAMI,IAAe,GAAGJ,CAAO,GAAGR,IAAK,QAAQ,EAAE,GAAGK,IAAW,cAAc,EAAE,IAEzEQ,IAAUvB;AAAA,MACd,CAACG,GAAe,GAAGA,CAAa,KAAKmB,CAAY,IAAI,GAAGnB,CAAa,KAAKc,CAAI,EAAE;AAAA,MAChF;AAAA,QACE,CAAC,GAAGd,CAAa,aAAa,GAAGG;AAAA,QACjC,CAAC,GAAGH,CAAa,YAAY,GAAGY;AAAA,QAChC,CAAC,GAAGZ,CAAa,cAAc,GAAGW;AAAA,QAClC,CAAC,GAAGX,CAAa,YAAY,GAAGU,KAAYN;AAAA,MAAA;AAAA,MAE9CK;AAAA,IAAA,GAGIY,IAAc,CAACC,MAAqC;AACxD,MAAIZ,KAAYN,IACdkB,EAAE,eAAA,IACOT,KACTA,EAAQS,CAAC;AAAA,IAEb,GAEMC,IAAY,EAAQN,EAAM,eAAe,KAAMP,KAAYN,GAC3DoB,IAAiBtB,EAAqB,EAAE,UAAAC,GAAU,SAAAC,GAAS;AAEjE,WACE,gBAAAqB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWL;AAAA,QACX,MAAAJ;AAAA,QACA,KAAAE;AAAA,QACA,iBAAeK;AAAA,QACf,SAASF;AAAA,QACR,GAAGJ;AAAA,QAEH,UAAA;AAAA,UAAAb,KACC,gBAAAsB;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,MAAMb,MAASpB,EAAK,KAAK,OAAO;AAAA,cAChC,UAAAkB;AAAA,cACA,UAAUW;AAAA,cACV,WAAW1B,EAAG,GAAGG,CAAa,WAAW;AAAA,YAAA;AAAA,UAAA;AAAA,UAG5CwB,IAAiBhB,IAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGnC;AACF;AAEAH,EAAO,cAAc;"}
@@ -0,0 +1,2 @@
1
+ "use strict";const l=require("react/jsx-runtime"),f=require("react"),E=require("./spinner-tKunS_o-.js"),N=require("./bind-DeUYJ6m9.js"),$={PRIMARY:"primary",SECONDARY:"secondary",EXPRESSIVE:"expressive"},A={LG:"lg"},B={"purpur-button":"_purpur-button_zehbw_1","purpur-button--xs":"_purpur-button--xs_zehbw_22","purpur-button--icon-only":"_purpur-button--icon-only_zehbw_25","purpur-button--sm":"_purpur-button--sm_zehbw_28","purpur-button--md":"_purpur-button--md_zehbw_34","purpur-button--lg":"_purpur-button--lg_zehbw_40","purpur-button--full-width":"_purpur-button--full-width_zehbw_46","purpur-button--primary":"_purpur-button--primary_zehbw_64","purpur-button--disabled":"_purpur-button--disabled_zehbw_68","purpur-button--primary-negative":"_purpur-button--primary-negative_zehbw_74","purpur-button--secondary":"_purpur-button--secondary_zehbw_86","purpur-button--secondary-negative":"_purpur-button--secondary-negative_zehbw_97","purpur-button--expressive":"_purpur-button--expressive_zehbw_108","purpur-button--expressive-negative":"_purpur-button--expressive-negative_zehbw_118","purpur-button--negative":"_purpur-button--negative_zehbw_130","purpur-button--destructive":"_purpur-button--destructive_zehbw_137","purpur-button--destructive-negative":"_purpur-button--destructive-negative_zehbw_147","purpur-button--tertiary-purple":"_purpur-button--tertiary-purple_zehbw_157","purpur-button--tertiary-purple-negative":"_purpur-button--tertiary-purple-negative_zehbw_170","purpur-button--text":"_purpur-button--text_zehbw_185","purpur-button--text-negative":"_purpur-button--text-negative_zehbw_207","purpur-button--primary-ai":"_purpur-button--primary-ai_zehbw_230","purpur-button--primary-ai-negative":"_purpur-button--primary-ai-negative_zehbw_276","purpur-button--secondary-ai":"_purpur-button--secondary-ai_zehbw_323","purpur-button__spinner":"_purpur-button__spinner_zehbw_348","purpur-button--secondary-ai-negative":"_purpur-button--secondary-ai-negative_zehbw_416","purpur-button--expressive-ai":"_purpur-button--expressive-ai_zehbw_509","purpur-button--expressive-ai-negative":"_purpur-button--expressive-ai-negative_zehbw_556","purpur-button--text-ai":"_purpur-button--text-ai_zehbw_606","purpur-button--text-ai-negative":"_purpur-button--text-ai-negative_zehbw_679"},d={...$,DESTRUCTIVE:"destructive",TERTIARY_PURPLE:"tertiary-purple",TEXT:"text"},I=Object.values(d),v=N.c.bind(B),t="purpur-button",S=["button","submit","reset"],C=({iconOnly:r,loading:e})=>!(r&&e),h=f.forwardRef(({ai:r=!1,children:e,className:w,disabled:p=!1,fullWidth:z=!1,iconOnly:n,loading:u=!1,negative:b=!1,onClick:o,size:_="md",variant:i,type:x="button",...s},y)=>{if(n&&i==="destructive")return null;const g=`${i}${r?"-ai":""}${b?"-negative":""}`,m=v([t,`${t}--${g}`,`${t}--${_}`],{[`${t}--icon-only`]:n,[`${t}--negative`]:b,[`${t}--full-width`]:z,[`${t}--disabled`]:p||u},w),T=c=>{p||u?c.preventDefault():o&&o(c)},a=!!s["aria-disabled"]||p||u,R=C({iconOnly:n,loading:u});return l.jsxs("button",{className:m,type:x,ref:y,"aria-disabled":a,onClick:T,...s,children:[u&&l.jsx(E.Spinner,{size:_===A.LG?"xs":"xxs",negative:b,disabled:a,className:v(`${t}__spinner`)}),R?e:null]})});h.displayName="Button";exports.BUTTON_TYPES=S;exports.BUTTON_VARIANT=d;exports.Button=h;exports.buttonVariants=I;
2
+ //# sourceMappingURL=button-Dqxdc3nC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-Dqxdc3nC.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 TERTIARY_PURPLE: \"tertiary-purple\",\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\ntype ButtonBaseProps = BaseProps<\"button\"> & { ai?: boolean; loading?: boolean };\n\nexport type ButtonProps =\n | (ActionProps<ButtonVariant> & ButtonBaseProps & { iconOnly?: false | undefined })\n | (ActionProps<Exclude<ButtonVariant, \"destructive\">> & ButtonBaseProps & { iconOnly: true });\n\ntype DistributiveOmit<T, K extends keyof never> = T extends unknown ? Omit<T, K> : never;\n\nconst shouldRenderChildren = ({ iconOnly, loading }: Pick<ButtonProps, \"iconOnly\" | \"loading\">) =>\n !(iconOnly && loading);\n\nexport const Button = forwardRef<\n HTMLButtonElement,\n DistributiveOmit<ButtonProps, \"type\"> & { type?: ButtonType }\n>(\n (\n {\n ai = false,\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\" as string)) {\n return null;\n }\n\n const variantClass = `${variant}${ai ? \"-ai\" : \"\"}${negative ? \"-negative\" : \"\"}`;\n\n const classes = cx(\n [rootClassName, `${rootClassName}--${variantClass}`, `${rootClassName}--${size}`],\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 const renderChildren = shouldRenderChildren({ iconOnly, 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 {renderChildren ? children : null}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n"],"names":["VARIANT","SIZE","BUTTON_VARIANT","buttonVariants","cx","c","styles","rootClassName","BUTTON_TYPES","shouldRenderChildren","iconOnly","loading","Button","forwardRef","ai","children","className","disabled","fullWidth","negative","onClick","size","variant","type","props","ref","variantClass","classes","handleClick","e","_disabled","renderChildren","jsxs","jsx","Spinner"],"mappings":"wIAEaA,EAAU,CACrB,QAAS,UACT,UAAW,YACX,WAAY,YACd,EAKaC,EAAO,CAIlB,GAAI,IACN,uhECRaC,EAAiB,CAC5B,GAAGF,EACH,YAAa,cACb,gBAAiB,kBACjB,KAAM,MACR,EAEaG,EAAiB,OAAO,OAAOD,CAAc,EAGpDE,EAAKC,EAAAA,EAAE,KAAKC,CAAM,EAClBC,EAAgB,gBAGTC,EAA6B,CAAC,SAAU,SAAU,OAAO,EAUhEC,EAAuB,CAAC,CAAE,SAAAC,EAAU,QAAAC,CAAA,IACxC,EAAED,GAAYC,GAEHC,EAASC,EAAAA,WAIpB,CACE,CACE,GAAAC,EAAK,GACL,SAAAC,EACA,UAAAC,EACA,SAAAC,EAAW,GACX,UAAAC,EAAY,GACZ,SAAAR,EACA,QAAAC,EAAU,GACV,SAAAQ,EAAW,GACX,QAAAC,EACA,KAAAC,EAAO,KACP,QAAAC,EACA,KAAAC,EAAO,SACP,GAAGC,CAAA,EAELC,IACG,CACH,GAAIf,GAAYY,IAAa,cAC3B,OAAO,KAGT,MAAMI,EAAe,GAAGJ,CAAO,GAAGR,EAAK,MAAQ,EAAE,GAAGK,EAAW,YAAc,EAAE,GAEzEQ,EAAUvB,EACd,CAACG,EAAe,GAAGA,CAAa,KAAKmB,CAAY,GAAI,GAAGnB,CAAa,KAAKc,CAAI,EAAE,EAChF,CACE,CAAC,GAAGd,CAAa,aAAa,EAAGG,EACjC,CAAC,GAAGH,CAAa,YAAY,EAAGY,EAChC,CAAC,GAAGZ,CAAa,cAAc,EAAGW,EAClC,CAAC,GAAGX,CAAa,YAAY,EAAGU,GAAYN,CAAA,EAE9CK,CAAA,EAGIY,EAAeC,GAAqC,CACpDZ,GAAYN,EACdkB,EAAE,eAAA,EACOT,GACTA,EAAQS,CAAC,CAEb,EAEMC,EAAY,EAAQN,EAAM,eAAe,GAAMP,GAAYN,EAC3DoB,EAAiBtB,EAAqB,CAAE,SAAAC,EAAU,QAAAC,EAAS,EAEjE,OACEqB,EAAAA,KAAC,SAAA,CACC,UAAWL,EACX,KAAAJ,EACA,IAAAE,EACA,gBAAeK,EACf,QAASF,EACR,GAAGJ,EAEH,SAAA,CAAAb,GACCsB,EAAAA,IAACC,EAAAA,QAAA,CACC,KAAMb,IAASpB,EAAK,GAAK,KAAO,MAChC,SAAAkB,EACA,SAAUW,EACV,UAAW1B,EAAG,GAAGG,CAAa,WAAW,CAAA,CAAA,EAG5CwB,EAAiBhB,EAAW,IAAA,CAAA,CAAA,CAGnC,CACF,EAEAH,EAAO,YAAc"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./button-BxdChrq-.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-Dqxdc3nC.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 { B as T, a as s, b as o, c as B } from "./button-D-BBdNhd.mjs";
1
+ import { B as T, a as s, b as o, c as B } from "./button-Cv7NlYbv.mjs";
2
2
  export {
3
3
  T as BUTTON_TYPES,
4
4
  s as BUTTON_VARIANT,