@allxsmith/bestax-bulma 5.27.0 → 5.27.2

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 (348) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/columns/Column.js +48 -0
  4. package/dist/esm/columns/Column.js.map +1 -0
  5. package/dist/esm/columns/Columns.js +53 -0
  6. package/dist/esm/columns/Columns.js.map +1 -0
  7. package/dist/esm/components/Avatar.js +299 -0
  8. package/dist/esm/components/Avatar.js.map +1 -0
  9. package/dist/esm/components/Avatars.js +81 -0
  10. package/dist/esm/components/Avatars.js.map +1 -0
  11. package/dist/esm/components/Badge.js +105 -0
  12. package/dist/esm/components/Badge.js.map +1 -0
  13. package/dist/esm/components/Breadcrumb.js +36 -0
  14. package/dist/esm/components/Breadcrumb.js.map +1 -0
  15. package/dist/esm/components/Card.js +252 -0
  16. package/dist/esm/components/Card.js.map +1 -0
  17. package/dist/esm/components/Carousel.js +351 -0
  18. package/dist/esm/components/Carousel.js.map +1 -0
  19. package/dist/esm/components/Collapse.js +193 -0
  20. package/dist/esm/components/Collapse.js.map +1 -0
  21. package/dist/esm/components/Collapses.js +99 -0
  22. package/dist/esm/components/Collapses.js.map +1 -0
  23. package/dist/esm/components/Dialog.js +230 -0
  24. package/dist/esm/components/Dialog.js.map +1 -0
  25. package/dist/esm/components/Dropdown.js +362 -0
  26. package/dist/esm/components/Dropdown.js.map +1 -0
  27. package/dist/esm/components/Loading.js +87 -0
  28. package/dist/esm/components/Loading.js.map +1 -0
  29. package/dist/esm/components/Menu.js +117 -0
  30. package/dist/esm/components/Menu.js.map +1 -0
  31. package/dist/esm/components/Message.js +56 -0
  32. package/dist/esm/components/Message.js.map +1 -0
  33. package/dist/esm/components/Modal.js +354 -0
  34. package/dist/esm/components/Modal.js.map +1 -0
  35. package/dist/esm/components/Navbar.js +287 -0
  36. package/dist/esm/components/Navbar.js.map +1 -0
  37. package/dist/esm/components/Pagination.js +191 -0
  38. package/dist/esm/components/Pagination.js.map +1 -0
  39. package/dist/esm/components/Panel.js +100 -0
  40. package/dist/esm/components/Panel.js.map +1 -0
  41. package/dist/esm/components/Popover.js +298 -0
  42. package/dist/esm/components/Popover.js.map +1 -0
  43. package/dist/esm/components/Reveal.js +157 -0
  44. package/dist/esm/components/Reveal.js.map +1 -0
  45. package/dist/esm/components/Sidebar.js +209 -0
  46. package/dist/esm/components/Sidebar.js.map +1 -0
  47. package/dist/esm/components/Steps.js +128 -0
  48. package/dist/esm/components/Steps.js.map +1 -0
  49. package/dist/esm/components/Tabs.js +335 -0
  50. package/dist/esm/components/Tabs.js.map +1 -0
  51. package/dist/esm/components/Toast.js +322 -0
  52. package/dist/esm/components/Toast.js.map +1 -0
  53. package/dist/esm/components/Tooltip.js +202 -0
  54. package/dist/esm/components/Tooltip.js.map +1 -0
  55. package/dist/esm/components/collapsesContext.js +12 -0
  56. package/dist/esm/components/collapsesContext.js.map +1 -0
  57. package/dist/esm/elements/Block.js +29 -0
  58. package/dist/esm/elements/Block.js.map +1 -0
  59. package/dist/esm/elements/Box.js +32 -0
  60. package/dist/esm/elements/Box.js.map +1 -0
  61. package/dist/esm/elements/Button.js +139 -0
  62. package/dist/esm/elements/Button.js.map +1 -0
  63. package/dist/esm/elements/Buttons.js +42 -0
  64. package/dist/esm/elements/Buttons.js.map +1 -0
  65. package/dist/esm/elements/Code.js +25 -0
  66. package/dist/esm/elements/Code.js.map +1 -0
  67. package/dist/esm/elements/Content.js +33 -0
  68. package/dist/esm/elements/Content.js.map +1 -0
  69. package/dist/esm/elements/Delete.js +35 -0
  70. package/dist/esm/elements/Delete.js.map +1 -0
  71. package/dist/esm/elements/Divider.js +27 -0
  72. package/dist/esm/elements/Divider.js.map +1 -0
  73. package/dist/esm/elements/Emphasis.js +25 -0
  74. package/dist/esm/elements/Emphasis.js.map +1 -0
  75. package/dist/esm/elements/Figure.js +58 -0
  76. package/dist/esm/elements/Figure.js.map +1 -0
  77. package/dist/esm/elements/Icon.js +256 -0
  78. package/dist/esm/elements/Icon.js.map +1 -0
  79. package/dist/esm/elements/IconText.js +36 -0
  80. package/dist/esm/elements/IconText.js.map +1 -0
  81. package/dist/esm/elements/Image.js +46 -0
  82. package/dist/esm/elements/Image.js.map +1 -0
  83. package/dist/esm/elements/Link.js +36 -0
  84. package/dist/esm/elements/Link.js.map +1 -0
  85. package/dist/esm/elements/LinkButton.js +37 -0
  86. package/dist/esm/elements/LinkButton.js.map +1 -0
  87. package/dist/esm/elements/ListItem.js +28 -0
  88. package/dist/esm/elements/ListItem.js.map +1 -0
  89. package/dist/esm/elements/Loader.js +37 -0
  90. package/dist/esm/elements/Loader.js.map +1 -0
  91. package/dist/esm/elements/Notification.js +316 -0
  92. package/dist/esm/elements/Notification.js.map +1 -0
  93. package/dist/esm/elements/OrderedList.js +31 -0
  94. package/dist/esm/elements/OrderedList.js.map +1 -0
  95. package/dist/esm/elements/Paragraph.js +28 -0
  96. package/dist/esm/elements/Paragraph.js.map +1 -0
  97. package/dist/esm/elements/Pre.js +25 -0
  98. package/dist/esm/elements/Pre.js.map +1 -0
  99. package/dist/esm/elements/Progress.js +33 -0
  100. package/dist/esm/elements/Progress.js.map +1 -0
  101. package/dist/esm/elements/Skeleton.js +30 -0
  102. package/dist/esm/elements/Skeleton.js.map +1 -0
  103. package/dist/esm/elements/Span.js +28 -0
  104. package/dist/esm/elements/Span.js.map +1 -0
  105. package/dist/esm/elements/Strong.js +25 -0
  106. package/dist/esm/elements/Strong.js.map +1 -0
  107. package/dist/esm/elements/SubTitle.js +51 -0
  108. package/dist/esm/elements/SubTitle.js.map +1 -0
  109. package/dist/esm/elements/Table.js +51 -0
  110. package/dist/esm/elements/Table.js.map +1 -0
  111. package/dist/esm/elements/Tag.js +49 -0
  112. package/dist/esm/elements/Tag.js.map +1 -0
  113. package/dist/esm/elements/Tags.js +34 -0
  114. package/dist/esm/elements/Tags.js.map +1 -0
  115. package/dist/esm/elements/Tbody.js +26 -0
  116. package/dist/esm/elements/Tbody.js.map +1 -0
  117. package/dist/esm/elements/Td.js +61 -0
  118. package/dist/esm/elements/Td.js.map +1 -0
  119. package/dist/esm/elements/Tfoot.js +26 -0
  120. package/dist/esm/elements/Tfoot.js.map +1 -0
  121. package/dist/esm/elements/Th.js +34 -0
  122. package/dist/esm/elements/Th.js.map +1 -0
  123. package/dist/esm/elements/Thead.js +26 -0
  124. package/dist/esm/elements/Thead.js.map +1 -0
  125. package/dist/esm/elements/Title.js +44 -0
  126. package/dist/esm/elements/Title.js.map +1 -0
  127. package/dist/esm/elements/Tr.js +31 -0
  128. package/dist/esm/elements/Tr.js.map +1 -0
  129. package/dist/esm/elements/UnorderedList.js +31 -0
  130. package/dist/esm/elements/UnorderedList.js.map +1 -0
  131. package/dist/esm/elements/iconProps.js +49 -0
  132. package/dist/esm/elements/iconProps.js.map +1 -0
  133. package/dist/esm/form/Autocomplete.js +279 -0
  134. package/dist/esm/form/Autocomplete.js.map +1 -0
  135. package/dist/esm/form/Checkbox.js +111 -0
  136. package/dist/esm/form/Checkbox.js.map +1 -0
  137. package/dist/esm/form/Checkboxes.js +90 -0
  138. package/dist/esm/form/Checkboxes.js.map +1 -0
  139. package/dist/esm/form/Control.js +79 -0
  140. package/dist/esm/form/Control.js.map +1 -0
  141. package/dist/esm/form/DateInput.js +88 -0
  142. package/dist/esm/form/DateInput.js.map +1 -0
  143. package/dist/esm/form/DateInputBase.js +263 -0
  144. package/dist/esm/form/DateInputBase.js.map +1 -0
  145. package/dist/esm/form/DateRangeInput.js +77 -0
  146. package/dist/esm/form/DateRangeInput.js.map +1 -0
  147. package/dist/esm/form/DateRangeInputBase.js +301 -0
  148. package/dist/esm/form/DateRangeInputBase.js.map +1 -0
  149. package/dist/esm/form/DateTimeInput.js +88 -0
  150. package/dist/esm/form/DateTimeInput.js.map +1 -0
  151. package/dist/esm/form/DateTimeInputBase.js +333 -0
  152. package/dist/esm/form/DateTimeInputBase.js.map +1 -0
  153. package/dist/esm/form/Field.js +167 -0
  154. package/dist/esm/form/Field.js.map +1 -0
  155. package/dist/esm/form/File.js +112 -0
  156. package/dist/esm/form/File.js.map +1 -0
  157. package/dist/esm/form/FormContext.js +194 -0
  158. package/dist/esm/form/FormContext.js.map +1 -0
  159. package/dist/esm/form/Input.js +88 -0
  160. package/dist/esm/form/Input.js.map +1 -0
  161. package/dist/esm/form/InputBase.js +40 -0
  162. package/dist/esm/form/InputBase.js.map +1 -0
  163. package/dist/esm/form/Numberinput.js +201 -0
  164. package/dist/esm/form/Numberinput.js.map +1 -0
  165. package/dist/esm/form/Radio.js +108 -0
  166. package/dist/esm/form/Radio.js.map +1 -0
  167. package/dist/esm/form/Radios.js +92 -0
  168. package/dist/esm/form/Radios.js.map +1 -0
  169. package/dist/esm/form/Rate.js +280 -0
  170. package/dist/esm/form/Rate.js.map +1 -0
  171. package/dist/esm/form/Select.js +81 -0
  172. package/dist/esm/form/Select.js.map +1 -0
  173. package/dist/esm/form/SelectBase.js +54 -0
  174. package/dist/esm/form/SelectBase.js.map +1 -0
  175. package/dist/esm/form/Slider.js +461 -0
  176. package/dist/esm/form/Slider.js.map +1 -0
  177. package/dist/esm/form/Switch.js +96 -0
  178. package/dist/esm/form/Switch.js.map +1 -0
  179. package/dist/esm/form/Taginput.js +351 -0
  180. package/dist/esm/form/Taginput.js.map +1 -0
  181. package/dist/esm/form/TextArea.js +77 -0
  182. package/dist/esm/form/TextArea.js.map +1 -0
  183. package/dist/esm/form/TextAreaBase.js +45 -0
  184. package/dist/esm/form/TextAreaBase.js.map +1 -0
  185. package/dist/esm/form/TimeInput.js +84 -0
  186. package/dist/esm/form/TimeInput.js.map +1 -0
  187. package/dist/esm/form/TimeInputBase.js +246 -0
  188. package/dist/esm/form/TimeInputBase.js.map +1 -0
  189. package/dist/esm/form/_pickerInternals/Calendar.js +760 -0
  190. package/dist/esm/form/_pickerInternals/Calendar.js.map +1 -0
  191. package/dist/esm/form/_pickerInternals/PickerPopover.js +95 -0
  192. package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -0
  193. package/dist/esm/form/_pickerInternals/TimeWheels.js +721 -0
  194. package/dist/esm/form/_pickerInternals/TimeWheels.js.map +1 -0
  195. package/dist/esm/form/_pickerInternals/audioTick.js +109 -0
  196. package/dist/esm/form/_pickerInternals/audioTick.js.map +1 -0
  197. package/dist/esm/form/_pickerInternals/dateUtils.js +267 -0
  198. package/dist/esm/form/_pickerInternals/dateUtils.js.map +1 -0
  199. package/dist/esm/form/_pickerInternals/formatters.js +322 -0
  200. package/dist/esm/form/_pickerInternals/formatters.js.map +1 -0
  201. package/dist/esm/form/_pickerInternals/haptics.js +38 -0
  202. package/dist/esm/form/_pickerInternals/haptics.js.map +1 -0
  203. package/dist/esm/form/_pickerInternals/nativeInputSupport.js +25 -0
  204. package/dist/esm/form/_pickerInternals/nativeInputSupport.js.map +1 -0
  205. package/dist/esm/form/_pickerInternals/pickerTypes.js +50 -0
  206. package/dist/esm/form/_pickerInternals/pickerTypes.js.map +1 -0
  207. package/dist/esm/form/_pickerInternals/segmentMap.js +315 -0
  208. package/dist/esm/form/_pickerInternals/segmentMap.js.map +1 -0
  209. package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js +49 -0
  210. package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js.map +1 -0
  211. package/dist/esm/form/_pickerInternals/useSegmentedEntry.js +427 -0
  212. package/dist/esm/form/_pickerInternals/useSegmentedEntry.js.map +1 -0
  213. package/dist/esm/form/controlLoading.js +18 -0
  214. package/dist/esm/form/controlLoading.js.map +1 -0
  215. package/dist/esm/form/useAutoLabelId.js +88 -0
  216. package/dist/esm/form/useAutoLabelId.js.map +1 -0
  217. package/dist/esm/grid/Cell.js +35 -0
  218. package/dist/esm/grid/Cell.js.map +1 -0
  219. package/dist/esm/grid/Grid.js +51 -0
  220. package/dist/esm/grid/Grid.js.map +1 -0
  221. package/dist/esm/helpers/ClientOnly.js +33 -0
  222. package/dist/esm/helpers/ClientOnly.js.map +1 -0
  223. package/dist/esm/helpers/Config.js +60 -0
  224. package/dist/esm/helpers/Config.js.map +1 -0
  225. package/dist/esm/helpers/Theme.js +947 -0
  226. package/dist/esm/helpers/Theme.js.map +1 -0
  227. package/dist/esm/helpers/anchorAttrs.js +72 -0
  228. package/dist/esm/helpers/anchorAttrs.js.map +1 -0
  229. package/dist/esm/helpers/bulmaClassHelpers.js +415 -0
  230. package/dist/esm/helpers/bulmaClassHelpers.js.map +1 -0
  231. package/dist/esm/helpers/buttonType.js +24 -0
  232. package/dist/esm/helpers/buttonType.js.map +1 -0
  233. package/dist/esm/helpers/classNames.js +137 -0
  234. package/dist/esm/helpers/classNames.js.map +1 -0
  235. package/dist/esm/helpers/colorDeprecations.js +50 -0
  236. package/dist/esm/helpers/colorDeprecations.js.map +1 -0
  237. package/dist/esm/helpers/devWarnings.js +27 -0
  238. package/dist/esm/helpers/devWarnings.js.map +1 -0
  239. package/dist/esm/helpers/inertProps.js +27 -0
  240. package/dist/esm/helpers/inertProps.js.map +1 -0
  241. package/dist/esm/helpers/mergeBulmaStyles.js +20 -0
  242. package/dist/esm/helpers/mergeBulmaStyles.js.map +1 -0
  243. package/dist/esm/helpers/polymorphic.js +18 -0
  244. package/dist/esm/helpers/polymorphic.js.map +1 -0
  245. package/dist/esm/helpers/portal.js +76 -0
  246. package/dist/esm/helpers/portal.js.map +1 -0
  247. package/dist/esm/helpers/positionStacks.js +45 -0
  248. package/dist/esm/helpers/positionStacks.js.map +1 -0
  249. package/dist/esm/helpers/scrollLock.js +38 -0
  250. package/dist/esm/helpers/scrollLock.js.map +1 -0
  251. package/dist/esm/helpers/shadowDom.js +71 -0
  252. package/dist/esm/helpers/shadowDom.js.map +1 -0
  253. package/dist/esm/helpers/statusRegion.js +282 -0
  254. package/dist/esm/helpers/statusRegion.js.map +1 -0
  255. package/dist/esm/helpers/useAnchoredPosition.js +86 -0
  256. package/dist/esm/helpers/useAnchoredPosition.js.map +1 -0
  257. package/dist/esm/helpers/useBulmaClasses.js +158 -0
  258. package/dist/esm/helpers/useBulmaClasses.js.map +1 -0
  259. package/dist/esm/helpers/useClientLayoutEffect.js +13 -0
  260. package/dist/esm/helpers/useClientLayoutEffect.js.map +1 -0
  261. package/dist/esm/helpers/useColorClasses.js +84 -0
  262. package/dist/esm/helpers/useColorClasses.js.map +1 -0
  263. package/dist/esm/helpers/useFlexboxClasses.js +92 -0
  264. package/dist/esm/helpers/useFlexboxClasses.js.map +1 -0
  265. package/dist/esm/helpers/useFocusTrap.js +470 -0
  266. package/dist/esm/helpers/useFocusTrap.js.map +1 -0
  267. package/dist/esm/helpers/useIsHydrated.js +31 -0
  268. package/dist/esm/helpers/useIsHydrated.js.map +1 -0
  269. package/dist/esm/helpers/useOtherClasses.js +115 -0
  270. package/dist/esm/helpers/useOtherClasses.js.map +1 -0
  271. package/dist/esm/helpers/useSpacingClasses.js +82 -0
  272. package/dist/esm/helpers/useSpacingClasses.js.map +1 -0
  273. package/dist/esm/helpers/useTypographyClasses.js +93 -0
  274. package/dist/esm/helpers/useTypographyClasses.js.map +1 -0
  275. package/dist/esm/helpers/useVisibilityClasses.js +134 -0
  276. package/dist/esm/helpers/useVisibilityClasses.js.map +1 -0
  277. package/dist/esm/helpers/withSubComponents.js +24 -0
  278. package/dist/esm/helpers/withSubComponents.js.map +1 -0
  279. package/dist/esm/layout/Container.js +48 -0
  280. package/dist/esm/layout/Container.js.map +1 -0
  281. package/dist/esm/layout/Footer.js +33 -0
  282. package/dist/esm/layout/Footer.js.map +1 -0
  283. package/dist/esm/layout/Hero.js +90 -0
  284. package/dist/esm/layout/Hero.js.map +1 -0
  285. package/dist/esm/layout/Level.js +110 -0
  286. package/dist/esm/layout/Level.js.map +1 -0
  287. package/dist/esm/layout/Media.js +86 -0
  288. package/dist/esm/layout/Media.js.map +1 -0
  289. package/dist/esm/layout/Section.js +30 -0
  290. package/dist/esm/layout/Section.js.map +1 -0
  291. package/dist/extras.css +1 -1
  292. package/dist/extras.css.map +1 -1
  293. package/dist/index.cjs +187 -57
  294. package/dist/index.cjs.map +1 -1
  295. package/dist/index.esm.js +115 -17516
  296. package/dist/index.esm.js.map +1 -1
  297. package/dist/types/elements/Icon.d.ts +10 -7
  298. package/dist/types/form/Autocomplete.d.ts +1 -1
  299. package/dist/types/form/Checkboxes.d.ts +1 -1
  300. package/dist/types/form/DateInput.d.ts +1 -1
  301. package/dist/types/form/DateInputBase.d.ts +3 -4
  302. package/dist/types/form/DateRangeInput.d.ts +1 -1
  303. package/dist/types/form/DateTimeInput.d.ts +1 -1
  304. package/dist/types/form/DateTimeInputBase.d.ts +3 -4
  305. package/dist/types/form/Field.d.ts +2 -2
  306. package/dist/types/form/File.d.ts +4 -4
  307. package/dist/types/form/FormContext.d.ts +24 -2
  308. package/dist/types/form/Numberinput.d.ts +1 -1
  309. package/dist/types/form/Radios.d.ts +1 -1
  310. package/dist/types/form/Rate.d.ts +1 -1
  311. package/dist/types/form/Slider.d.ts +1 -1
  312. package/dist/types/form/Taginput.d.ts +1 -1
  313. package/dist/types/form/TimeInput.d.ts +1 -1
  314. package/dist/types/form/useAutoLabelId.d.ts +25 -4
  315. package/dist/types/helpers/Config.d.ts +3 -4
  316. package/dist/types/helpers/Theme.d.ts +44 -40
  317. package/dist/types-cjs/elements/Icon.d.ts +10 -7
  318. package/dist/types-cjs/form/Autocomplete.d.ts +1 -1
  319. package/dist/types-cjs/form/Checkboxes.d.ts +1 -1
  320. package/dist/types-cjs/form/DateInput.d.ts +1 -1
  321. package/dist/types-cjs/form/DateInputBase.d.ts +3 -4
  322. package/dist/types-cjs/form/DateRangeInput.d.ts +1 -1
  323. package/dist/types-cjs/form/DateTimeInput.d.ts +1 -1
  324. package/dist/types-cjs/form/DateTimeInputBase.d.ts +3 -4
  325. package/dist/types-cjs/form/Field.d.ts +2 -2
  326. package/dist/types-cjs/form/File.d.ts +4 -4
  327. package/dist/types-cjs/form/FormContext.d.ts +24 -2
  328. package/dist/types-cjs/form/Numberinput.d.ts +1 -1
  329. package/dist/types-cjs/form/Radios.d.ts +1 -1
  330. package/dist/types-cjs/form/Rate.d.ts +1 -1
  331. package/dist/types-cjs/form/Slider.d.ts +1 -1
  332. package/dist/types-cjs/form/Taginput.d.ts +1 -1
  333. package/dist/types-cjs/form/TimeInput.d.ts +1 -1
  334. package/dist/types-cjs/form/useAutoLabelId.d.ts +25 -4
  335. package/dist/types-cjs/helpers/Config.d.ts +3 -4
  336. package/dist/types-cjs/helpers/Theme.d.ts +44 -40
  337. package/dist/versions/bestax-no-dark-mode.css +1 -1
  338. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  339. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  340. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  341. package/dist/versions/bestax-no-helpers.css +1 -1
  342. package/dist/versions/bestax-no-helpers.css.map +1 -1
  343. package/dist/versions/bestax-prefixed.css +1 -1
  344. package/dist/versions/bestax-prefixed.css.map +1 -1
  345. package/package.json +1 -1
  346. package/src/scss/form/_dateinput.scss +37 -6
  347. package/src/scss/form/_datetimeinput.scss +7 -2
  348. package/src/scss/form/_picker-popover.scss +1 -4
@@ -0,0 +1,280 @@
1
+ /* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { forwardRef, useId, useState, useCallback } from 'react';
4
+ import { usePrefixedClassNames, classNames, prefixedClassNames } from '../helpers/classNames.js';
5
+ import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
6
+ import { Icon } from '../elements/Icon.js';
7
+ import { useIconLibrary, useClassPrefix } from '../helpers/Config.js';
8
+ import { useInsideField, useInsideControl, rendersOwnField, rendersOwnControl } from './FormContext.js';
9
+ import { Field } from './Field.js';
10
+ import { Control } from './Control.js';
11
+ import { useAutoLabelledBy } from './useAutoLabelId.js';
12
+
13
+ /**
14
+ * Default star icon component.
15
+ */
16
+ const StarIcon = ({ filled }) => (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: filled ? 'currentColor' : 'none', stroke: "currentColor", strokeWidth: filled ? 0 : 2, "aria-hidden": "true", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" }) }));
17
+ /** Snap a value to the nearest precision step. */
18
+ function snapToPrecision(val, precision) {
19
+ return Math.round(val / precision) * precision;
20
+ }
21
+ /** Get fill percentage for a given icon index based on current value. */
22
+ function getFillPercent(iconIndex, value) {
23
+ if (value >= iconIndex + 1)
24
+ return 100;
25
+ if (value <= iconIndex)
26
+ return 0;
27
+ return Math.round((value - iconIndex) * 100);
28
+ }
29
+ /**
30
+ * The `Rate` component provides a star/icon-based rating system.
31
+ *
32
+ * @function
33
+ * @param {RateProps} props - Props for the Rate component.
34
+ * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the container element.
35
+ * @returns {JSX.Element} The rendered rating component.
36
+ *
37
+ * @example
38
+ * // Basic 5-star rating
39
+ * <Rate defaultValue={3} />
40
+ *
41
+ * @example
42
+ * // With color and precision
43
+ * <Rate defaultValue={3.5} color="warning" precision={0.5} showScore />
44
+ *
45
+ * @example
46
+ * // With Font Awesome icons
47
+ * <Rate iconName="star" iconLibrary="fa" iconVariant="solid" />
48
+ */
49
+ const Rate = forwardRef(({ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, value: controlledValue, defaultValue = 0, max = 5, size, disabled = false, showScore = false, showText = false, texts, onChange, customIcon, spaced = false, rtl = false, iconName, iconLibrary: iconLibraryProp, iconVariant, iconFeatures, color, precision = 1, customText, name, form, className, ...props }, ref) => {
50
+ const insideField = useInsideField();
51
+ const insideControl = useInsideControl();
52
+ const ownField = rendersOwnField('Rate', {
53
+ insideField,
54
+ insideControl,
55
+ label,
56
+ message,
57
+ horizontal,
58
+ fieldClassName,
59
+ });
60
+ const { ariaLabelledBy, fieldLabelProps } = useAutoLabelledBy({
61
+ label,
62
+ labelProps,
63
+ rendersLabel: ownField,
64
+ callerProps: props,
65
+ });
66
+ const { bulmaHelperClasses, rest } = useBulmaClasses(props);
67
+ const starBaseId = useId();
68
+ const [internalValue, setInternalValue] = useState(defaultValue);
69
+ const [hoverValue, setHoverValue] = useState(null);
70
+ const defaultIconLibrary = useIconLibrary();
71
+ const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';
72
+ // Determine if controlled
73
+ const isControlled = controlledValue !== undefined;
74
+ const currentValue = isControlled ? controlledValue : internalValue;
75
+ const displayValue = hoverValue !== null ? hoverValue : currentValue;
76
+ // Update value
77
+ const updateValue = useCallback((newValue) => {
78
+ if (disabled)
79
+ return;
80
+ // Allow clicking same value to deselect (set to 0)
81
+ const finalValue = newValue === currentValue ? 0 : newValue;
82
+ if (!isControlled) {
83
+ setInternalValue(finalValue);
84
+ }
85
+ onChange?.(finalValue);
86
+ }, [isControlled, currentValue, disabled, onChange]);
87
+ // Handle click with precision support
88
+ const handleClick = useCallback((iconIndex, e) => {
89
+ if (disabled)
90
+ return;
91
+ if (precision < 1) {
92
+ const rect = e.currentTarget.getBoundingClientRect();
93
+ let relativeX = (e.clientX - rect.left) / rect.width;
94
+ if (rtl)
95
+ relativeX = 1 - relativeX;
96
+ const rawValue = iconIndex + relativeX;
97
+ const snapped = snapToPrecision(rawValue, precision);
98
+ const clamped = Math.max(precision, Math.min(snapped, max));
99
+ updateValue(clamped);
100
+ }
101
+ else {
102
+ updateValue(iconIndex + 1);
103
+ }
104
+ }, [disabled, precision, rtl, max, updateValue]);
105
+ // Handle mouse enter on icon
106
+ const handleMouseEnter = useCallback((iconIndex) => {
107
+ if (disabled)
108
+ return;
109
+ setHoverValue(iconIndex + 1);
110
+ }, [disabled]);
111
+ // Handle mouse move with precision support
112
+ const handleMouseMove = useCallback((iconIndex, e) => {
113
+ if (disabled || precision >= 1)
114
+ return;
115
+ const rect = e.currentTarget.getBoundingClientRect();
116
+ let relativeX = (e.clientX - rect.left) / rect.width;
117
+ if (rtl)
118
+ relativeX = 1 - relativeX;
119
+ const rawValue = iconIndex + relativeX;
120
+ const snapped = snapToPrecision(rawValue, precision);
121
+ const clamped = Math.max(precision, Math.min(snapped, max));
122
+ setHoverValue(clamped);
123
+ }, [disabled, precision, rtl, max]);
124
+ // Handle mouse leave
125
+ const handleMouseLeave = useCallback(() => {
126
+ setHoverValue(null);
127
+ }, []);
128
+ // Handle keyboard
129
+ const handleKeyDown = useCallback((e) => {
130
+ if (disabled)
131
+ return;
132
+ let newValue = currentValue;
133
+ const step = precision < 1 ? precision : 1;
134
+ if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {
135
+ e.preventDefault();
136
+ newValue = Math.min(currentValue + step, max);
137
+ }
138
+ else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
139
+ e.preventDefault();
140
+ newValue = Math.max(currentValue - step, 0);
141
+ }
142
+ else if (e.key === 'Home') {
143
+ e.preventDefault();
144
+ newValue = 0;
145
+ }
146
+ else if (e.key === 'End') {
147
+ e.preventDefault();
148
+ newValue = max;
149
+ }
150
+ // Round to avoid floating point issues
151
+ newValue = Math.round(newValue * 1000) / 1000;
152
+ if (newValue !== currentValue) {
153
+ if (!isControlled) {
154
+ setInternalValue(newValue);
155
+ }
156
+ onChange?.(newValue);
157
+ }
158
+ }, [currentValue, max, precision, disabled, isControlled, onChange]);
159
+ // Get text for current value
160
+ const getText = () => {
161
+ if (!showText || !texts)
162
+ return null;
163
+ const wholeIndex = Math.ceil(displayValue) - 1;
164
+ const baseText = texts[wholeIndex] || null;
165
+ if (!baseText)
166
+ return null;
167
+ // For fractional hover values with precision < 1, append "+"
168
+ if (precision < 1 && hoverValue !== null && hoverValue % 1 !== 0) {
169
+ return `${baseText}+`;
170
+ }
171
+ return baseText;
172
+ };
173
+ // Format score display
174
+ const getScoreDisplay = () => {
175
+ if (precision < 1 && currentValue % 1 !== 0) {
176
+ return currentValue.toFixed(1);
177
+ }
178
+ return currentValue;
179
+ };
180
+ // Generate classes
181
+ const classPrefix = useClassPrefix();
182
+ const rateClasses = usePrefixedClassNames('rate', {
183
+ [`is-${size}`]: size,
184
+ 'is-disabled': disabled,
185
+ 'is-spaced': spaced,
186
+ 'is-rtl': rtl,
187
+ [`is-${color}`]: color,
188
+ });
189
+ const combinedClasses = classNames(rateClasses, bulmaHelperClasses, className);
190
+ // Render a single icon based on priority: customIcon > iconName > default SVG
191
+ const renderIcon = (iconIndex, isActive, fillPercent) => {
192
+ const iconProps = {
193
+ index: iconIndex,
194
+ isActive,
195
+ isHovered: hoverValue !== null && iconIndex < hoverValue,
196
+ value: displayValue,
197
+ fillPercent,
198
+ };
199
+ if (customIcon) {
200
+ return customIcon(iconProps);
201
+ }
202
+ if (iconName) {
203
+ return (jsx(Icon, { name: iconName, library: resolvedLibrary, variant: iconVariant, features: iconFeatures }));
204
+ }
205
+ return jsx(StarIcon, { filled: isActive });
206
+ };
207
+ // Render partial icon with layered approach
208
+ const renderPartialIcon = (iconIndex, fillPercent) => {
209
+ if (customIcon) {
210
+ // For custom icons, pass fillPercent and let consumer handle it
211
+ const iconProps = {
212
+ index: iconIndex,
213
+ isActive: fillPercent > 0,
214
+ isHovered: hoverValue !== null && iconIndex < (hoverValue ?? 0),
215
+ value: displayValue,
216
+ fillPercent,
217
+ };
218
+ return customIcon(iconProps);
219
+ }
220
+ if (iconName) {
221
+ return (jsxs("span", { className: prefixedClassNames(classPrefix, 'rate-icon-partial'), style: {
222
+ '--rate-fill-percent': `${fillPercent}%`,
223
+ }, children: [jsx("span", { className: prefixedClassNames(classPrefix, 'rate-icon-bg'), children: jsx(Icon, { name: iconName, library: resolvedLibrary, variant: iconVariant, features: iconFeatures }) }), jsx("span", { className: prefixedClassNames(classPrefix, 'rate-icon-fg'), children: jsx(Icon, { name: iconName, library: resolvedLibrary, variant: iconVariant, features: iconFeatures }) })] }));
224
+ }
225
+ // Default SVG with clipPath for partial fill
226
+ const clipId = `rate-clip-${iconIndex}`;
227
+ return (jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", "aria-hidden": "true", children: [jsx("defs", { children: jsx("clipPath", { id: clipId, children: jsx("rect", { x: "0", y: "0", width: `${(fillPercent / 100) * 24}`, height: "24" }) }) }), jsx("path", { fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", d: "M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" }), jsx("path", { clipPath: `url(#${clipId})`, fill: "currentColor", d: "M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" })] }));
228
+ };
229
+ // The star the value falls in is the checked radio, and it carries the
230
+ // value: a radiogroup takes no aria-value* of its own. A fractional value
231
+ // names that star by the value itself ("3.5 stars"). Both go by the value
232
+ // as that name writes it, to hundredths, so a value a hair over a whole
233
+ // number checks that number's star under its own name, and no two stars
234
+ // share a name.
235
+ const shownValue = Number(currentValue.toFixed(2));
236
+ const checkedIndex = shownValue > 0 ? Math.min(Math.ceil(shownValue), max) - 1 : -1;
237
+ // Render icons
238
+ const renderIcons = () => {
239
+ const icons = [];
240
+ for (let i = 0; i < max; i++) {
241
+ const iconIndex = rtl ? max - 1 - i : i;
242
+ const fillPercent = getFillPercent(iconIndex, displayValue);
243
+ const isActive = fillPercent === 100;
244
+ const isHovered = hoverValue !== null && iconIndex < hoverValue;
245
+ const isPartial = fillPercent > 0 && fillPercent < 100;
246
+ const icon = isPartial
247
+ ? renderPartialIcon(iconIndex, fillPercent)
248
+ : renderIcon(iconIndex, isActive, fillPercent);
249
+ icons.push(jsx("span", { className: prefixedClassNames(classPrefix, 'rate-item', {
250
+ 'is-active': isActive,
251
+ 'is-hovered': isHovered,
252
+ }), onClick: e => handleClick(iconIndex, e), onMouseEnter: () => handleMouseEnter(iconIndex), onMouseMove: e => handleMouseMove(iconIndex, e), onMouseLeave: handleMouseLeave, id: `${starBaseId}-${iconIndex}`, role: "radio", "aria-checked": iconIndex === checkedIndex, "aria-label": iconIndex === checkedIndex && shownValue % 1 !== 0
253
+ ? `${shownValue} stars`
254
+ : `${iconIndex + 1} star${iconIndex === 0 ? '' : 's'}`, tabIndex: -1, children: icon }, iconIndex));
255
+ }
256
+ return icons;
257
+ };
258
+ const text = getText();
259
+ const helpClass = usePrefixedClassNames('help', {
260
+ [`is-${messageColor}`]: !!messageColor,
261
+ });
262
+ const messageEl = message ? jsx("p", { className: helpClass, children: message }) : null;
263
+ const rateItemsClass = usePrefixedClassNames('rate-items');
264
+ const rateScoreClass = usePrefixedClassNames('rate-score');
265
+ const rateTextClass = usePrefixedClassNames('rate-text');
266
+ const rateCustomTextClass = usePrefixedClassNames('rate-custom-text');
267
+ const rateElement = (jsxs("div", { ref: ref, className: combinedClasses, role: "radiogroup", "aria-label": ariaLabelledBy ? undefined : 'Rating', "aria-labelledby": ariaLabelledBy, "aria-activedescendant": checkedIndex >= 0 ? `${starBaseId}-${checkedIndex}` : undefined, tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown, ...rest, children: [jsx("div", { className: rateItemsClass, children: renderIcons() }), showScore && (jsx("span", { className: rateScoreClass, children: getScoreDisplay() })), text && jsx("span", { className: rateTextClass, children: text }), customText && (jsx("span", { className: rateCustomTextClass, children: customText })), name && (jsx("input", { type: "hidden", name: name, value: currentValue, form: form }))] }));
268
+ let content = rateElement;
269
+ if (rendersOwnControl('Rate', { insideControl })) {
270
+ content = jsx(Control, { children: content });
271
+ }
272
+ if (ownField) {
273
+ return (jsxs(Field, { label: label, labelSize: labelSize, labelProps: fieldLabelProps, horizontal: horizontal, className: fieldClassName, children: [content, messageEl] }));
274
+ }
275
+ return (jsxs(Fragment, { children: [content, messageEl] }));
276
+ });
277
+ Rate.displayName = 'Rate';
278
+
279
+ export { Rate };
280
+ //# sourceMappingURL=Rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Rate.js","sources":["../../../src/form/Rate.tsx"],"sourcesContent":["import React, { forwardRef, useState, useCallback, useId } from 'react';\nimport {\n classNames,\n prefixedClassNames,\n usePrefixedClassNames,\n} from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { Icon } from '../elements/Icon';\nimport { useClassPrefix, useIconLibrary } from '../helpers/Config';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n rendersOwnControl,\n} from './FormContext';\nimport { Field } from './Field';\nimport { Control } from './Control';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelledBy } from './useAutoLabelId';\n\n/** Available size modifiers for the Rate component. */\nexport type RateSize = 'small' | 'medium' | 'large';\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\ntype BulmaColor =\n 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * Props for individual rate icons.\n */\nexport interface RateIconProps {\n /** The index of this icon (0-based) */\n index: number;\n /** Whether this icon is currently active (filled) */\n isActive: boolean;\n /** Whether this icon is currently hovered */\n isHovered: boolean;\n /** The current value */\n value: number;\n /** Fill percentage for partial icons (0-100). Used with precision < 1. */\n fillPercent: number;\n}\n\n/**\n * Props for the Rate component.\n * Inside an existing `Control` it renders no `Control` of its own. Inside an\n * outer `Field`, or a `Control` with no `Field` around it, it renders no\n * `Field` of its own either. The exception is `label`, `message`, `horizontal`\n * or `fieldClassName` in that bare `Control`: it keeps a `Field` for them,\n * nested in the `.control`, and warns in development. Wrap the `Control` in a\n * `Field` instead, and set the `label`, `horizontal` and class name on that\n * `Field`.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the container element.\n */\nexport interface RateProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'>,\n Omit<BulmaClassesProps, 'size'>,\n FormFieldProps {\n /** Field label naming the rating group. Automatically associated via `aria-labelledby` on the `role=\"radiogroup\"` container — uses your `labelProps.id` when provided, otherwise a generated one; it also replaces the default `aria-label=\"Rating\"`. Dropped inside an outer `Field`, whose own label names the group instead through `aria-labelledby` when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`), and replaces the `aria-label=\"Rating\"` fallback too. An `aria-label` or `aria-labelledby` you set on the group wins over either label, which still renders but no longer names it. An `aria-labelledby` key counts even when undefined, since it is spread over the group's own, and leaves the `\"Rating\"` fallback. */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `id` here is used as the `aria-labelledby` target instead of a generated one; any `htmlFor` is ignored (a group label names the group, never a single control). */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Form field name. When set, a hidden input is rendered. */\n name?: string;\n /** Optional id of the form this hidden input belongs to (use when the input lives outside the form element). */\n form?: string;\n /** Controlled value (0 to max). */\n value?: number;\n /** Default value for uncontrolled usage. */\n defaultValue?: number;\n /** Maximum rating value. */\n max?: number;\n /** Size variant. */\n size?: RateSize;\n /** Whether the rating is disabled. */\n disabled?: boolean;\n /** Show the numeric score next to stars. */\n showScore?: boolean;\n /** Show custom text based on value. */\n showText?: boolean;\n /** Array of text labels for each rating value. */\n texts?: string[];\n /** Callback when rating changes. */\n onChange?: (value: number) => void;\n /** Custom icon renderer. */\n customIcon?: (props: RateIconProps) => React.ReactNode;\n /** Add spacing between icons. */\n spaced?: boolean;\n /** Right-to-left direction. */\n rtl?: boolean;\n /** Custom icon name for the rating stars. */\n iconName?: string;\n /** Icon library to use (defaults to ConfigProvider value or 'fa'). */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Color of the active rating icons. */\n color?: BulmaColor;\n /** Rating precision (e.g., `0.5` for half stars). */\n precision?: number;\n /** Custom text displayed next to the rating. */\n customText?: string;\n}\n\n/**\n * Default star icon component.\n */\nconst StarIcon: React.FC<{ filled: boolean }> = ({ filled }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill={filled ? 'currentColor' : 'none'}\n stroke=\"currentColor\"\n strokeWidth={filled ? 0 : 2}\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z\"\n />\n </svg>\n);\n\n/** Snap a value to the nearest precision step. */\nfunction snapToPrecision(val: number, precision: number): number {\n return Math.round(val / precision) * precision;\n}\n\n/** Get fill percentage for a given icon index based on current value. */\nfunction getFillPercent(iconIndex: number, value: number): number {\n if (value >= iconIndex + 1) return 100;\n if (value <= iconIndex) return 0;\n return Math.round((value - iconIndex) * 100);\n}\n\n/**\n * The `Rate` component provides a star/icon-based rating system.\n *\n * @function\n * @param {RateProps} props - Props for the Rate component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the container element.\n * @returns {JSX.Element} The rendered rating component.\n *\n * @example\n * // Basic 5-star rating\n * <Rate defaultValue={3} />\n *\n * @example\n * // With color and precision\n * <Rate defaultValue={3.5} color=\"warning\" precision={0.5} showScore />\n *\n * @example\n * // With Font Awesome icons\n * <Rate iconName=\"star\" iconLibrary=\"fa\" iconVariant=\"solid\" />\n */\nexport const Rate = forwardRef<HTMLDivElement, RateProps>(\n (\n {\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n value: controlledValue,\n defaultValue = 0,\n max = 5,\n size,\n disabled = false,\n showScore = false,\n showText = false,\n texts,\n onChange,\n customIcon,\n spaced = false,\n rtl = false,\n iconName,\n iconLibrary: iconLibraryProp,\n iconVariant,\n iconFeatures,\n color,\n precision = 1,\n customText,\n name,\n form,\n className,\n ...props\n },\n ref\n ) => {\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Rate', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n const { ariaLabelledBy, fieldLabelProps } = useAutoLabelledBy({\n label,\n labelProps,\n rendersLabel: ownField,\n callerProps: props,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const starBaseId = useId();\n const [internalValue, setInternalValue] = useState(defaultValue);\n const [hoverValue, setHoverValue] = useState<number | null>(null);\n\n const defaultIconLibrary = useIconLibrary();\n const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';\n\n // Determine if controlled\n const isControlled = controlledValue !== undefined;\n const currentValue = isControlled ? controlledValue : internalValue;\n const displayValue = hoverValue !== null ? hoverValue : currentValue;\n\n // Update value\n const updateValue = useCallback(\n (newValue: number) => {\n if (disabled) return;\n\n // Allow clicking same value to deselect (set to 0)\n const finalValue = newValue === currentValue ? 0 : newValue;\n\n if (!isControlled) {\n setInternalValue(finalValue);\n }\n onChange?.(finalValue);\n },\n [isControlled, currentValue, disabled, onChange]\n );\n\n // Handle click with precision support\n const handleClick = useCallback(\n (iconIndex: number, e: React.MouseEvent<HTMLSpanElement>) => {\n if (disabled) return;\n\n if (precision < 1) {\n const rect = e.currentTarget.getBoundingClientRect();\n let relativeX = (e.clientX - rect.left) / rect.width;\n if (rtl) relativeX = 1 - relativeX;\n const rawValue = iconIndex + relativeX;\n const snapped = snapToPrecision(rawValue, precision);\n const clamped = Math.max(precision, Math.min(snapped, max));\n updateValue(clamped);\n } else {\n updateValue(iconIndex + 1);\n }\n },\n [disabled, precision, rtl, max, updateValue]\n );\n\n // Handle mouse enter on icon\n const handleMouseEnter = useCallback(\n (iconIndex: number) => {\n if (disabled) return;\n setHoverValue(iconIndex + 1);\n },\n [disabled]\n );\n\n // Handle mouse move with precision support\n const handleMouseMove = useCallback(\n (iconIndex: number, e: React.MouseEvent<HTMLSpanElement>) => {\n if (disabled || precision >= 1) return;\n const rect = e.currentTarget.getBoundingClientRect();\n let relativeX = (e.clientX - rect.left) / rect.width;\n if (rtl) relativeX = 1 - relativeX;\n const rawValue = iconIndex + relativeX;\n const snapped = snapToPrecision(rawValue, precision);\n const clamped = Math.max(precision, Math.min(snapped, max));\n setHoverValue(clamped);\n },\n [disabled, precision, rtl, max]\n );\n\n // Handle mouse leave\n const handleMouseLeave = useCallback(() => {\n setHoverValue(null);\n }, []);\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n\n let newValue = currentValue;\n const step = precision < 1 ? precision : 1;\n\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault();\n newValue = Math.min(currentValue + step, max);\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault();\n newValue = Math.max(currentValue - step, 0);\n } else if (e.key === 'Home') {\n e.preventDefault();\n newValue = 0;\n } else if (e.key === 'End') {\n e.preventDefault();\n newValue = max;\n }\n\n // Round to avoid floating point issues\n newValue = Math.round(newValue * 1000) / 1000;\n\n if (newValue !== currentValue) {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n }\n },\n [currentValue, max, precision, disabled, isControlled, onChange]\n );\n\n // Get text for current value\n const getText = () => {\n if (!showText || !texts) return null;\n const wholeIndex = Math.ceil(displayValue) - 1;\n const baseText = texts[wholeIndex] || null;\n if (!baseText) return null;\n // For fractional hover values with precision < 1, append \"+\"\n if (precision < 1 && hoverValue !== null && hoverValue % 1 !== 0) {\n return `${baseText}+`;\n }\n return baseText;\n };\n\n // Format score display\n const getScoreDisplay = () => {\n if (precision < 1 && currentValue % 1 !== 0) {\n return currentValue.toFixed(1);\n }\n return currentValue;\n };\n\n // Generate classes\n const classPrefix = useClassPrefix();\n const rateClasses = usePrefixedClassNames('rate', {\n [`is-${size}`]: size,\n 'is-disabled': disabled,\n 'is-spaced': spaced,\n 'is-rtl': rtl,\n [`is-${color}`]: color,\n });\n\n const combinedClasses = classNames(\n rateClasses,\n bulmaHelperClasses,\n className\n );\n\n // Render a single icon based on priority: customIcon > iconName > default SVG\n const renderIcon = (\n iconIndex: number,\n isActive: boolean,\n fillPercent: number\n ) => {\n const iconProps: RateIconProps = {\n index: iconIndex,\n isActive,\n isHovered: hoverValue !== null && iconIndex < hoverValue,\n value: displayValue,\n fillPercent,\n };\n\n if (customIcon) {\n return customIcon(iconProps);\n }\n\n if (iconName) {\n return (\n <Icon\n name={iconName}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n />\n );\n }\n\n return <StarIcon filled={isActive} />;\n };\n\n // Render partial icon with layered approach\n const renderPartialIcon = (iconIndex: number, fillPercent: number) => {\n if (customIcon) {\n // For custom icons, pass fillPercent and let consumer handle it\n const iconProps: RateIconProps = {\n index: iconIndex,\n isActive: fillPercent > 0,\n isHovered: hoverValue !== null && iconIndex < (hoverValue ?? 0),\n value: displayValue,\n fillPercent,\n };\n return customIcon(iconProps);\n }\n\n if (iconName) {\n return (\n <span\n className={prefixedClassNames(classPrefix, 'rate-icon-partial')}\n style={\n {\n '--rate-fill-percent': `${fillPercent}%`,\n } as React.CSSProperties\n }\n >\n <span className={prefixedClassNames(classPrefix, 'rate-icon-bg')}>\n <Icon\n name={iconName}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n />\n </span>\n <span className={prefixedClassNames(classPrefix, 'rate-icon-fg')}>\n <Icon\n name={iconName}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n />\n </span>\n </span>\n );\n }\n\n // Default SVG with clipPath for partial fill\n const clipId = `rate-clip-${iconIndex}`;\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <defs>\n <clipPath id={clipId}>\n <rect\n x=\"0\"\n y=\"0\"\n width={`${(fillPercent / 100) * 24}`}\n height=\"24\"\n />\n </clipPath>\n </defs>\n {/* Background: empty star */}\n <path\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z\"\n />\n {/* Foreground: filled portion */}\n <path\n clipPath={`url(#${clipId})`}\n fill=\"currentColor\"\n d=\"M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z\"\n />\n </svg>\n );\n };\n\n // The star the value falls in is the checked radio, and it carries the\n // value: a radiogroup takes no aria-value* of its own. A fractional value\n // names that star by the value itself (\"3.5 stars\"). Both go by the value\n // as that name writes it, to hundredths, so a value a hair over a whole\n // number checks that number's star under its own name, and no two stars\n // share a name.\n const shownValue = Number(currentValue.toFixed(2));\n const checkedIndex =\n shownValue > 0 ? Math.min(Math.ceil(shownValue), max) - 1 : -1;\n\n // Render icons\n const renderIcons = () => {\n const icons = [];\n\n for (let i = 0; i < max; i++) {\n const iconIndex = rtl ? max - 1 - i : i;\n const fillPercent = getFillPercent(iconIndex, displayValue);\n const isActive = fillPercent === 100;\n const isHovered = hoverValue !== null && iconIndex < hoverValue;\n const isPartial = fillPercent > 0 && fillPercent < 100;\n\n const icon = isPartial\n ? renderPartialIcon(iconIndex, fillPercent)\n : renderIcon(iconIndex, isActive, fillPercent);\n\n icons.push(\n <span\n key={iconIndex}\n className={prefixedClassNames(classPrefix, 'rate-item', {\n 'is-active': isActive,\n 'is-hovered': isHovered,\n })}\n onClick={e => handleClick(iconIndex, e)}\n onMouseEnter={() => handleMouseEnter(iconIndex)}\n onMouseMove={e => handleMouseMove(iconIndex, e)}\n onMouseLeave={handleMouseLeave}\n id={`${starBaseId}-${iconIndex}`}\n role=\"radio\"\n aria-checked={iconIndex === checkedIndex}\n aria-label={\n iconIndex === checkedIndex && shownValue % 1 !== 0\n ? `${shownValue} stars`\n : `${iconIndex + 1} star${iconIndex === 0 ? '' : 's'}`\n }\n tabIndex={-1}\n >\n {icon}\n </span>\n );\n }\n\n return icons;\n };\n\n const text = getText();\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n const rateItemsClass = usePrefixedClassNames('rate-items');\n const rateScoreClass = usePrefixedClassNames('rate-score');\n const rateTextClass = usePrefixedClassNames('rate-text');\n const rateCustomTextClass = usePrefixedClassNames('rate-custom-text');\n\n const rateElement = (\n <div\n ref={ref}\n className={combinedClasses}\n role=\"radiogroup\"\n // Fallback name only: a wired label names the group via labelledby.\n aria-label={ariaLabelledBy ? undefined : 'Rating'}\n aria-labelledby={ariaLabelledBy}\n // Focus stays on the group, so point it at the checked star for\n // assistive technology to announce as the value changes.\n aria-activedescendant={\n checkedIndex >= 0 ? `${starBaseId}-${checkedIndex}` : undefined\n }\n tabIndex={disabled ? -1 : 0}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n <div className={rateItemsClass}>{renderIcons()}</div>\n {showScore && (\n <span className={rateScoreClass}>{getScoreDisplay()}</span>\n )}\n {text && <span className={rateTextClass}>{text}</span>}\n {customText && (\n <span className={rateCustomTextClass}>{customText}</span>\n )}\n {name && (\n <input type=\"hidden\" name={name} value={currentValue} form={form} />\n )}\n </div>\n );\n\n let content = rateElement;\n\n if (rendersOwnControl('Rate', { insideControl })) {\n content = <Control>{content}</Control>;\n }\n\n if (ownField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {content}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {content}\n {messageEl}\n </>\n );\n }\n);\n\nRate.displayName = 'Rate';\n\nexport default Rate;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { forwardRef } from 'react';
4
+ import { usePrefixedClassNames } from '../helpers/classNames.js';
5
+ import { Field } from './Field.js';
6
+ import { Control } from './Control.js';
7
+ import { SelectBase } from './SelectBase.js';
8
+ import { useInsideField, useInsideControl, rendersOwnField, rendersOwnControl } from './FormContext.js';
9
+ import { useAutoLabelId } from './useAutoLabelId.js';
10
+
11
+ /**
12
+ * The `Select` component provides a Bulma-styled dropdown for selecting one or more options.
13
+ *
14
+ * @function
15
+ * @param {SelectProps} props - Props for Select.
16
+ * @returns {JSX.Element} The composed field element.
17
+ *
18
+ * @example
19
+ * <Select label="Country" iconLeftName="globe">
20
+ * <option>United States</option>
21
+ * <option>Canada</option>
22
+ * </Select>
23
+ */
24
+ const Select = forwardRef(({
25
+ // Field props
26
+ label, labelSize, labelProps, horizontal,
27
+ // Control props
28
+ iconLeft, iconLeftName, iconLeftSize, hasIconsLeft, isExpanded, controlSize,
29
+ // Message props
30
+ message, messageColor,
31
+ // Container class overrides
32
+ fieldClassName, controlClassName,
33
+ // Everything else (including isLoading) goes to Select.
34
+ // Note: isLoading on a select is rendered on the .select wrapper itself
35
+ // (replacing the chevron with a spinner), not on .control — this matches
36
+ // Bulma's documented behavior for `<div class="select is-loading">`.
37
+ ...selectProps }, ref) => {
38
+ const insideField = useInsideField();
39
+ const insideControl = useInsideControl();
40
+ const ownField = rendersOwnField('Select', {
41
+ insideField,
42
+ insideControl,
43
+ label,
44
+ message,
45
+ horizontal,
46
+ fieldClassName,
47
+ });
48
+ // Not isLoading, which the select draws itself and so keeps in a Control.
49
+ const ownControl = rendersOwnControl('Select', {
50
+ insideControl,
51
+ iconLeft,
52
+ iconLeftName,
53
+ iconLeftSize,
54
+ hasIconsLeft,
55
+ isExpanded,
56
+ controlSize,
57
+ controlClassName,
58
+ });
59
+ const { controlId, fieldLabelProps } = useAutoLabelId({
60
+ label,
61
+ id: selectProps.id,
62
+ labelProps,
63
+ rendersLabel: ownField,
64
+ });
65
+ const helpClass = usePrefixedClassNames('help', {
66
+ [`is-${messageColor}`]: !!messageColor,
67
+ });
68
+ let content = jsx(SelectBase, { ref: ref, ...selectProps, id: controlId });
69
+ if (ownControl) {
70
+ content = (jsx(Control, { iconLeft: iconLeft, iconLeftName: iconLeftName, iconLeftSize: iconLeftSize, hasIconsLeft: hasIconsLeft, isExpanded: isExpanded, size: controlSize, className: controlClassName, children: content }));
71
+ }
72
+ const messageEl = message ? jsx("p", { className: helpClass, children: message }) : null;
73
+ if (ownField) {
74
+ return (jsxs(Field, { label: label, labelSize: labelSize, labelProps: fieldLabelProps, horizontal: horizontal, className: fieldClassName, children: [content, messageEl] }));
75
+ }
76
+ return (jsxs(Fragment, { children: [content, messageEl] }));
77
+ });
78
+ Select.displayName = 'Select';
79
+
80
+ export { Select };
81
+ //# sourceMappingURL=Select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Select.js","sources":["../../../src/form/Select.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { usePrefixedClassNames } from '../helpers/classNames';\nimport { Field, FieldProps } from './Field';\nimport { Control, ControlBaseProps } from './Control';\nimport { SelectBase, SelectBaseProps } from './SelectBase';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n rendersOwnControl,\n} from './FormContext';\nimport { useAutoLabelId } from './useAutoLabelId';\n\n/**\n * Props for the Select component.\n *\n * Composes Field, Control, and SelectBase into a single convenience component.\n * Supports all SelectBase props, plus Field-level (label, horizontal) and\n * Control-level (icons) props.\n * Inside an existing `Control` it renders no `Control` of its own, so its\n * Control-level props do nothing there and warn in development; set them on\n * that `Control` instead. Inside an outer `Field`, or a `Control` with no\n * `Field` around it, it renders no `Field` of its own either.\n * The exception is `label`, `message`, `horizontal` or `fieldClassName` in that\n * bare `Control`: it keeps a `Field` for them, nested in the `.control`, and\n * warns in development. Wrap the `Control` in a `Field` instead, and set the\n * `label`, `horizontal` and class name on that `Field`.\n */\nexport interface SelectProps extends SelectBaseProps {\n /** Field label. Automatically associated with the select via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */\n label?: React.ReactNode;\n /** Size for the label. */\n labelSize?: FieldProps['labelSize'];\n /** Props for the label element when the component renders its own `Field`; dropped inside an outer `Field` (use that `Field`'s `labelProps` instead). An explicit `htmlFor` key — even `undefined` — overrides the automatic association and no id is generated. */\n labelProps?: FieldProps['labelProps'];\n /** Horizontal field layout. */\n horizontal?: boolean;\n /**\n * Icon props for left icon.\n * Bulma gives control icons `pointer-events: none`, so a clickable node here\n * never receives a click. Put a button beside the input in its own addon `Control` instead.\n */\n iconLeft?: ControlBaseProps['iconLeft'];\n /** Shortcut for left icon name. */\n iconLeftName?: string;\n /** Shortcut for left icon size. */\n iconLeftSize?: ControlBaseProps['iconLeftSize'];\n /** Force left icon container. */\n hasIconsLeft?: boolean;\n /**\n * Replaces the chevron with a loading spinner.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n isLoading?: boolean;\n /** Expand the control. */\n isExpanded?: boolean;\n /** Control size. */\n controlSize?: ControlBaseProps['size'];\n /** Help/validation message below the select. */\n message?: React.ReactNode;\n /** Bulma color for the message. */\n messageColor?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Additional CSS classes for the Field. */\n fieldClassName?: string;\n /** Additional CSS classes for the Control. */\n controlClassName?: string;\n}\n\n/**\n * The `Select` component provides a Bulma-styled dropdown for selecting one or more options.\n *\n * @function\n * @param {SelectProps} props - Props for Select.\n * @returns {JSX.Element} The composed field element.\n *\n * @example\n * <Select label=\"Country\" iconLeftName=\"globe\">\n * <option>United States</option>\n * <option>Canada</option>\n * </Select>\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n (\n {\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n // Control props\n iconLeft,\n iconLeftName,\n iconLeftSize,\n hasIconsLeft,\n isExpanded,\n controlSize,\n // Message props\n message,\n messageColor,\n // Container class overrides\n fieldClassName,\n controlClassName,\n // Everything else (including isLoading) goes to Select.\n // Note: isLoading on a select is rendered on the .select wrapper itself\n // (replacing the chevron with a spinner), not on .control — this matches\n // Bulma's documented behavior for `<div class=\"select is-loading\">`.\n ...selectProps\n },\n ref\n ) => {\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Select', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n // Not isLoading, which the select draws itself and so keeps in a Control.\n const ownControl = rendersOwnControl('Select', {\n insideControl,\n iconLeft,\n iconLeftName,\n iconLeftSize,\n hasIconsLeft,\n isExpanded,\n controlSize,\n controlClassName,\n });\n const { controlId, fieldLabelProps } = useAutoLabelId({\n label,\n id: selectProps.id,\n labelProps,\n rendersLabel: ownField,\n });\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n\n let content = <SelectBase ref={ref} {...selectProps} id={controlId} />;\n\n if (ownControl) {\n content = (\n <Control\n iconLeft={iconLeft}\n iconLeftName={iconLeftName}\n iconLeftSize={iconLeftSize}\n hasIconsLeft={hasIconsLeft}\n isExpanded={isExpanded}\n size={controlSize}\n className={controlClassName}\n >\n {content}\n </Control>\n );\n }\n\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n if (ownField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {content}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {content}\n {messageEl}\n </>\n );\n }\n);\n\nSelect.displayName = 'Select';\n\nexport default Select;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":";;;;;;;;;;AAqEA;;;;;;;;;;;;AAYG;AACI,MAAM,MAAM,GAAG,UAAU,CAC9B,CACE;AACE;AACA,KAAK,EACL,SAAS,EACT,UAAU,EACV,UAAU;AACV;AACA,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW;AACX;AACA,OAAO,EACP,YAAY;AACZ;AACA,cAAc,EACd,gBAAgB;AAChB;AACA;AACA;AACA;AACA,GAAG,WAAW,EACf,EACD,GAAG,KACD;AACF,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;AACpC,IAAA,MAAM,aAAa,GAAG,gBAAgB,EAAE;AACxC,IAAA,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE;QACzC,WAAW;QACX,aAAa;QACb,KAAK;QACL,OAAO;QACP,UAAU;QACV,cAAc;AACf,KAAA,CAAC;;AAEF,IAAA,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,EAAE;QAC7C,aAAa;QACb,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,UAAU;QACV,WAAW;QACX,gBAAgB;AACjB,KAAA,CAAC;AACF,IAAA,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,cAAc,CAAC;QACpD,KAAK;QACL,EAAE,EAAE,WAAW,CAAC,EAAE;QAClB,UAAU;AACV,QAAA,YAAY,EAAE,QAAQ;AACvB,KAAA,CAAC;AACF,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,EAAE;AAC9C,QAAA,CAAC,MAAM,YAAY,CAAA,CAAE,GAAG,CAAC,CAAC,YAAY;AACvC,KAAA,CAAC;AAEF,IAAA,IAAI,OAAO,GAAGA,GAAA,CAAC,UAAU,IAAC,GAAG,EAAE,GAAG,EAAA,GAAM,WAAW,EAAE,EAAE,EAAE,SAAS,GAAI;IAEtE,IAAI,UAAU,EAAE;AACd,QAAA,OAAO,IACLA,GAAA,CAAC,OAAO,EAAA,EACN,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,gBAAgB,EAAA,QAAA,EAE1B,OAAO,EAAA,CACA,CACX;IACH;AAEA,IAAA,MAAM,SAAS,GAAG,OAAO,GAAGA,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAE,SAAS,YAAG,OAAO,EAAA,CAAK,GAAG,IAAI;IAEzE,IAAI,QAAQ,EAAE;AACZ,QAAA,QACEC,IAAA,CAAC,KAAK,EAAA,EACJ,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,eAAe,EAC3B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,cAAc,EAAA,QAAA,EAAA,CAExB,OAAO,EACP,SAAS,CAAA,EAAA,CACJ;IAEZ;AAEA,IAAA,QACEA,IAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAA,CACG,OAAO,EACP,SAAS,CAAA,EAAA,CACT;AAEP,CAAC;AAGH,MAAM,CAAC,WAAW,GAAG,QAAQ;;"}
@@ -0,0 +1,54 @@
1
+ /* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { forwardRef } from 'react';
4
+ import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
5
+ import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
6
+ import { useFieldLabelId } from './FormContext.js';
7
+
8
+ /**
9
+ * Bulma Select component with full Bulma helper class support.
10
+ *
11
+ * @function
12
+ * @param {SelectBaseProps} props - Props for the SelectBase component.
13
+ * @returns {JSX.Element} The rendered select element.
14
+ * @see {@link https://bulma.io/documentation/form/select/ | Bulma Select documentation}
15
+ */
16
+ const SelectBase = forwardRef(({ color, size, isRounded, isLoading, isActive, isHovered, isFocused, isFullwidth, isFullWidth, className, disabled, children, multiple, multipleSize, ...props }, ref) => {
17
+ const { bulmaHelperClasses, rest } = useBulmaClasses({
18
+ color,
19
+ ...props,
20
+ });
21
+ const fieldLabelId = useFieldLabelId();
22
+ const mainClass = usePrefixedClassNames('select', {
23
+ [`is-${color}`]: !!color,
24
+ [`is-${size}`]: !!size,
25
+ 'is-rounded': isRounded,
26
+ 'is-loading': isLoading,
27
+ 'is-active': isActive,
28
+ 'is-multiple': !!multiple,
29
+ 'is-fullwidth': isFullwidth ?? isFullWidth,
30
+ });
31
+ const selectClass = classNames(mainClass, bulmaHelperClasses, className);
32
+ // is-hovered / is-focused belong on the inner <select> element, not the wrapper.
33
+ const innerSelectClass = usePrefixedClassNames('', {
34
+ 'is-hovered': isHovered,
35
+ 'is-focused': isFocused,
36
+ });
37
+ // Only set size attribute when multiple is true and multipleSize is specified
38
+ const selectProps = {
39
+ disabled,
40
+ multiple,
41
+ ...rest,
42
+ };
43
+ if (multiple && typeof multipleSize === 'number') {
44
+ selectProps.size = multipleSize;
45
+ }
46
+ return (jsx("div", { className: selectClass, children: jsx("select", { ref: ref, className: innerSelectClass || undefined, ...selectProps,
47
+ // After the spread: a labeled Field's generated id is adopted only
48
+ // when no user id arrived; the id belongs on the inner <select>.
49
+ id: selectProps.id ?? fieldLabelId, children: children }) }));
50
+ });
51
+ SelectBase.displayName = 'SelectBase';
52
+
53
+ export { SelectBase };
54
+ //# sourceMappingURL=SelectBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectBase.js","sources":["../../../src/form/SelectBase.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useFieldLabelId } from './FormContext';\n\n/**\n * Props for the Select component.\n */\nexport interface SelectBaseProps\n extends\n Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'>,\n Omit<BulmaClassesProps, 'color'> {\n /** Bulma color modifier for the select. */\n color?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'black'\n | 'dark'\n | 'light'\n | 'white';\n /** Size modifier for the select. */\n size?: 'small' | 'medium' | 'large';\n /** Rounded select corners. */\n isRounded?: boolean;\n /**\n * Replaces the chevron with a loading spinner.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n isLoading?: boolean;\n /** Applies Bulma's is-active modifier. */\n isActive?: boolean;\n /** Forces hovered state on the inner select. */\n isHovered?: boolean;\n /** Forces focused state on the inner select. */\n isFocused?: boolean;\n /** Makes the select span the full width of parent. */\n isFullwidth?: boolean;\n /** Makes the select span the full width of parent. @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n isFullWidth?: boolean;\n /** Additional CSS classes to apply. */\n className?: string;\n /** Disables the select. */\n disabled?: boolean;\n /** Allows multiple selections. */\n multiple?: boolean;\n /** Number of visible options in multiselect. */\n multipleSize?: number;\n /** `<option>` elements. */\n children?: React.ReactNode;\n}\n\n/**\n * Bulma Select component with full Bulma helper class support.\n *\n * @function\n * @param {SelectBaseProps} props - Props for the SelectBase component.\n * @returns {JSX.Element} The rendered select element.\n * @see {@link https://bulma.io/documentation/form/select/ | Bulma Select documentation}\n */\nexport const SelectBase = forwardRef<HTMLSelectElement, SelectBaseProps>(\n (\n {\n color,\n size,\n isRounded,\n isLoading,\n isActive,\n isHovered,\n isFocused,\n isFullwidth,\n isFullWidth,\n className,\n disabled,\n children,\n multiple,\n multipleSize,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color,\n ...props,\n });\n const fieldLabelId = useFieldLabelId();\n\n const mainClass = usePrefixedClassNames('select', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-loading': isLoading,\n 'is-active': isActive,\n 'is-multiple': !!multiple,\n 'is-fullwidth': isFullwidth ?? isFullWidth,\n });\n const selectClass = classNames(mainClass, bulmaHelperClasses, className);\n\n // is-hovered / is-focused belong on the inner <select> element, not the wrapper.\n const innerSelectClass = usePrefixedClassNames('', {\n 'is-hovered': isHovered,\n 'is-focused': isFocused,\n });\n\n // Only set size attribute when multiple is true and multipleSize is specified\n const selectProps: React.SelectHTMLAttributes<HTMLSelectElement> = {\n disabled,\n multiple,\n ...rest,\n };\n\n if (multiple && typeof multipleSize === 'number') {\n selectProps.size = multipleSize;\n }\n\n return (\n <div className={selectClass}>\n <select\n ref={ref}\n className={innerSelectClass || undefined}\n {...selectProps}\n // After the spread: a labeled Field's generated id is adopted only\n // when no user id arrived; the id belongs on the inner <select>.\n id={selectProps.id ?? fieldLabelId}\n >\n {children}\n </select>\n </div>\n );\n }\n);\n\nSelectBase.displayName = 'SelectBase';\n\nexport default SelectBase;\n"],"names":["_jsx"],"mappings":";;;;;;;AAwDA;;;;;;;AAOG;AACI,MAAM,UAAU,GAAG,UAAU,CAClC,CACE,EACE,KAAK,EACL,IAAI,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;QACnD,KAAK;AACL,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;AACF,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AAEtC,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,EAAE;AAChD,QAAA,CAAC,MAAM,KAAK,CAAA,CAAE,GAAG,CAAC,CAAC,KAAK;AACxB,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACtB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,WAAW,EAAE,QAAQ;QACrB,aAAa,EAAE,CAAC,CAAC,QAAQ;QACzB,cAAc,EAAE,WAAW,IAAI,WAAW;AAC3C,KAAA,CAAC;IACF,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;;AAGxE,IAAA,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,EAAE,EAAE;AACjD,QAAA,YAAY,EAAE,SAAS;AACvB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA,CAAC;;AAGF,IAAA,MAAM,WAAW,GAAkD;QACjE,QAAQ;QACR,QAAQ;AACR,QAAA,GAAG,IAAI;KACR;AAED,IAAA,IAAI,QAAQ,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;AAChD,QAAA,WAAW,CAAC,IAAI,GAAG,YAAY;IACjC;AAEA,IAAA,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,WAAW,YACzBA,GAAA,CAAA,QAAA,EAAA,EACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,gBAAgB,IAAI,SAAS,KACpC,WAAW;;;YAGf,EAAE,EAAE,WAAW,CAAC,EAAE,IAAI,YAAY,EAAA,QAAA,EAEjC,QAAQ,EAAA,CACF,EAAA,CACL;AAEV,CAAC;AAGH,UAAU,CAAC,WAAW,GAAG,YAAY;;"}