@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,77 @@
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 { DateRangeInputBase } from './DateRangeInputBase.js';
8
+ import { useInsideField, useInsideControl, rendersOwnField, rendersOwnControl } from './FormContext.js';
9
+ import { useAutoLabelledBy } from './useAutoLabelId.js';
10
+
11
+ /**
12
+ * The `DateRangeInput` component is a form input for a start and end date, picked from one popover calendar or typed into two segmented inputs.
13
+ *
14
+ * @function
15
+ * @param {DateRangeInputProps} props - Props for the DateRangeInput.
16
+ * @returns {JSX.Element}
17
+ *
18
+ * @example
19
+ * <DateRangeInput label="Stay" name="stay" min={new Date()} />
20
+ */
21
+ const DateRangeInput = forwardRef((props, ref) => {
22
+ const { label, labelSize, labelProps, horizontal, iconLeft, iconRight, iconLeftName = 'calendar', iconRightName, iconLeftSize, iconRightSize, hasIconsLeft, hasIconsRight, isLoading, isExpanded, controlSize, message, messageColor, fieldClassName, controlClassName, ...baseProps } = props;
23
+ const insideField = useInsideField();
24
+ const insideControl = useInsideControl();
25
+ const ownField = rendersOwnField('DateRangeInput', {
26
+ insideField,
27
+ insideControl,
28
+ label,
29
+ message,
30
+ horizontal,
31
+ fieldClassName,
32
+ });
33
+ // Inline mode renders a bare calendar with no input, so the Control's
34
+ // icon containers have nothing to anchor to, and it renders no Control
35
+ // inside one or out. The left icon is checked as the caller passed it:
36
+ // the default glyph is this component's own choice, not a prop the
37
+ // caller set, so it goes in only for the advice.
38
+ const ownControl = rendersOwnControl('DateRangeInput', {
39
+ insideControl,
40
+ inline: baseProps.inline,
41
+ isLoading,
42
+ iconLeft,
43
+ iconLeftName: props.iconLeftName,
44
+ defaultIconLeftName: iconLeftName,
45
+ iconLeftSize,
46
+ iconRight,
47
+ iconRightName,
48
+ iconRightSize,
49
+ hasIconsLeft,
50
+ hasIconsRight,
51
+ isExpanded,
52
+ controlSize,
53
+ controlClassName,
54
+ });
55
+ const { ariaLabelledBy, fieldLabelProps } = useAutoLabelledBy({
56
+ label,
57
+ labelProps,
58
+ rendersLabel: ownField,
59
+ callerProps: baseProps,
60
+ });
61
+ const helpClass = usePrefixedClassNames('help', {
62
+ [`is-${messageColor}`]: !!messageColor,
63
+ });
64
+ let content = (jsx(DateRangeInputBase, { ref: ref, "aria-labelledby": ariaLabelledBy, ...baseProps }));
65
+ if (ownControl) {
66
+ content = (jsx(Control, { iconLeft: iconLeft, iconRight: iconRight, iconLeftName: iconLeftName, iconRightName: iconRightName, iconLeftSize: iconLeftSize, iconRightSize: iconRightSize, hasIconsLeft: hasIconsLeft || !!iconLeftName, hasIconsRight: hasIconsRight, isLoading: isLoading, isExpanded: isExpanded, size: controlSize, className: controlClassName, children: content }));
67
+ }
68
+ const messageEl = message ? jsx("p", { className: helpClass, children: message }) : null;
69
+ if (ownField) {
70
+ return (jsxs(Field, { label: label, labelSize: labelSize, labelProps: fieldLabelProps, horizontal: horizontal, className: fieldClassName, children: [content, messageEl] }));
71
+ }
72
+ return (jsxs(Fragment, { children: [content, messageEl] }));
73
+ });
74
+ DateRangeInput.displayName = 'DateRangeInput';
75
+
76
+ export { DateRangeInput };
77
+ //# sourceMappingURL=DateRangeInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateRangeInput.js","sources":["../../../src/form/DateRangeInput.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { usePrefixedClassNames } from '../helpers/classNames';\nimport { Field, FieldProps } from './Field';\nimport { Control, ControlBaseProps } from './Control';\nimport {\n DateRangeInputBase,\n DateRangeInputBaseProps,\n} from './DateRangeInputBase';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n rendersOwnControl,\n} from './FormContext';\nimport { useAutoLabelledBy } from './useAutoLabelId';\n\n/**\n * Props for the DateRangeInput convenience wrapper. Extends\n * `DateRangeInputBaseProps` with Field-level (label, horizontal) and\n * Control-level (icons, loading) props. Inside an existing `Control` it\n * renders no `Control` of its own, so its Control-level props do nothing\n * there and warn in development; set them on that `Control` instead. In\n * `inline` mode it renders no `Control` anywhere, so they do nothing inside a\n * `Control` or out, and warn in development there too. Inside an outer\n * `Field`, or a `Control` with no `Field` around it, it renders no `Field` of\n * its own either. The exception is\n * `label`, `message`, `horizontal` or `fieldClassName` in that bare\n * `Control`: it keeps a `Field` for them, nested in the `.control`, and warns\n * in development. Wrap the `Control` in a `Field` instead.\n * @extraProp {string} [className] - Additional CSS classes for the root, the `role=\"group\"` that holds the two inputs.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Forwarded to the start `<input>`.\n */\nexport interface DateRangeInputProps extends DateRangeInputBaseProps {\n /** Field label naming the whole range. Associated through `aria-labelledby` on the `role=\"group\"` root, since it names two inputs rather than one; uses your `labelProps.id` when provided, otherwise a generated one. Each input keeps its own name, \"Start date\" or \"End date\" (`labels.rangeStart` / `labels.rangeEnd`). 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`). 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. */\n label?: React.ReactNode;\n /** Size for the label. */\n labelSize?: FieldProps['labelSize'];\n /** Props for the label element. An `htmlFor` here is dropped, since the label names the group rather than one input. */\n labelProps?: FieldProps['labelProps'];\n /** Render the field with horizontal layout. */\n horizontal?: boolean;\n /**\n * Icon props for the 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 field in its own addon `Control` instead.\n */\n iconLeft?: ControlBaseProps['iconLeft'];\n /**\n * Icon props for the right icon.\n * Bulma gives control icons `pointer-events: none`, so a clickable node here\n * never receives a click. Put a button beside the field in its own addon `Control` instead.\n */\n iconRight?: ControlBaseProps['iconRight'];\n /** Shortcut for the right icon name. */\n iconRightName?: string;\n /** Shortcut for left icon size. */\n iconLeftSize?: ControlBaseProps['iconLeftSize'];\n /** Shortcut for right icon size. */\n iconRightSize?: ControlBaseProps['iconRightSize'];\n /** Force the left icon container. */\n hasIconsLeft?: boolean;\n /** Force the right icon container. */\n hasIconsRight?: boolean;\n /**\n * Shows a loading spinner on the `Control` it renders, and hides the\n * launcher (`triggerIcon`) while it does. Inside your own `Control` it\n * renders none, so this draws nothing and warns in development; set\n * `isLoading` on that `Control`.\n */\n isLoading?: boolean;\n /**\n * Show a clickable launcher button on the right that toggles the popover.\n * Hidden by default while a spinner shows at the same right edge: this\n * component's `isLoading` when it renders its own `Control`, or the\n * enclosing `Control`'s `isLoading` inside one.\n * @defaultValue true\n */\n triggerIcon?: boolean;\n /** Expand the control to fill its container. */\n isExpanded?: boolean;\n /** Size of the wrapping Control. */\n controlSize?: ControlBaseProps['size'];\n /** Help/validation text below the field. */\n message?: React.ReactNode;\n /** Color modifier for the help message. */\n messageColor?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Additional CSS classes for the Field wrapper. */\n fieldClassName?: string;\n /** Additional CSS classes for the Control wrapper. */\n controlClassName?: string;\n}\n\n/**\n * The `DateRangeInput` component is a form input for a start and end date, picked from one popover calendar or typed into two segmented inputs.\n *\n * @function\n * @param {DateRangeInputProps} props - Props for the DateRangeInput.\n * @returns {JSX.Element}\n *\n * @example\n * <DateRangeInput label=\"Stay\" name=\"stay\" min={new Date()} />\n */\nexport const DateRangeInput = forwardRef<HTMLInputElement, DateRangeInputProps>(\n (props, ref) => {\n const {\n label,\n labelSize,\n labelProps,\n horizontal,\n iconLeft,\n iconRight,\n iconLeftName = 'calendar',\n iconRightName,\n iconLeftSize,\n iconRightSize,\n hasIconsLeft,\n hasIconsRight,\n isLoading,\n isExpanded,\n controlSize,\n message,\n messageColor,\n fieldClassName,\n controlClassName,\n ...baseProps\n } = props;\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('DateRangeInput', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n // Inline mode renders a bare calendar with no input, so the Control's\n // icon containers have nothing to anchor to, and it renders no Control\n // inside one or out. The left icon is checked as the caller passed it:\n // the default glyph is this component's own choice, not a prop the\n // caller set, so it goes in only for the advice.\n const ownControl = rendersOwnControl('DateRangeInput', {\n insideControl,\n inline: baseProps.inline,\n isLoading,\n iconLeft,\n iconLeftName: props.iconLeftName,\n defaultIconLeftName: iconLeftName,\n iconLeftSize,\n iconRight,\n iconRightName,\n iconRightSize,\n hasIconsLeft,\n hasIconsRight,\n isExpanded,\n controlSize,\n controlClassName,\n });\n const { ariaLabelledBy, fieldLabelProps } = useAutoLabelledBy({\n label,\n labelProps,\n rendersLabel: ownField,\n callerProps: baseProps,\n });\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n\n let content: React.ReactNode = (\n <DateRangeInputBase\n ref={ref}\n aria-labelledby={ariaLabelledBy}\n {...baseProps}\n />\n );\n\n if (ownControl) {\n content = (\n <Control\n iconLeft={iconLeft}\n iconRight={iconRight}\n iconLeftName={iconLeftName}\n iconRightName={iconRightName}\n iconLeftSize={iconLeftSize}\n iconRightSize={iconRightSize}\n hasIconsLeft={hasIconsLeft || !!iconLeftName}\n hasIconsRight={hasIconsRight}\n isLoading={isLoading}\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\nDateRangeInput.displayName = 'DateRangeInput';\n\nexport default DateRangeInput;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
@@ -0,0 +1,301 @@
1
+ /* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
+ import { forwardRef, useState, useMemo, useEffect, useRef, useId, useCallback } from 'react';
4
+ import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
5
+ import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
6
+ import { mergeLabels } from './_pickerInternals/pickerTypes.js';
7
+ import { formatDate, DEFAULT_DATE_FORMAT, parseDate, toIsoValue, fromIsoValue } from './_pickerInternals/formatters.js';
8
+ import { floorMin, clampDate, isSameDay, canCloseRange, startOfDay, isWithin } from './_pickerInternals/dateUtils.js';
9
+ import { Calendar, CALENDAR_FOCUSED_CELL } from './_pickerInternals/Calendar.js';
10
+ import { PickerPopover } from './_pickerInternals/PickerPopover.js';
11
+ import { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker.js';
12
+ import { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry.js';
13
+ import { useControlLoading } from './controlLoading.js';
14
+ import { Icon } from '../elements/Icon.js';
15
+
16
+ const EMPTY_RANGE = [null, null];
17
+ /** A range's end as the form and the native inputs carry it. */
18
+ const isoDay = (d) => (d ? toIsoValue(d, 'day') : '');
19
+ /** Today at local midnight, where typing into an empty end starts. */
20
+ const today = () => startOfDay(new Date());
21
+ /**
22
+ * Raw DateRangeInput: the two inputs and the popover calendar without
23
+ * Field/Control wrapping. Use `DateRangeInput` for the convenience wrapper.
24
+ *
25
+ * @function
26
+ * @param {DateRangeInputBaseProps} props
27
+ * @returns {JSX.Element}
28
+ */
29
+ const DateRangeInputBase = forwardRef((props, ref) => {
30
+ const { value: controlledValue, defaultValue, onChange, onOpen, onClose, min, max, disabled, readOnly, placeholder, format, parse, locale, inline = false, mobileNative = 'auto', editable = true, popover = true, openOnFocus = true, closeOnSelect = true, position = 'bottom-left', appendToBody = false, color, size, isRounded, shouldDisableDate, unselectableDates, allowDisabledInRange = false, firstDayOfWeek = 0, dayNames, monthNames, nearbyMonthDays = true, iconLeftName: _iconLeftName, triggerIcon: triggerIconProp, triggerIconName = 'chevron-down', labels, name, startName, endName, form, required, id, className, onFocus, onFocusCapture, ...rest } = props;
31
+ // The launcher gives way to the loading spinner of a Control this sits in.
32
+ const controlLoading = useControlLoading();
33
+ const triggerIcon = triggerIconProp ?? !controlLoading;
34
+ const t = mergeLabels(labels);
35
+ const resolvedFormat = format ?? DEFAULT_DATE_FORMAT;
36
+ const isControlled = controlledValue !== undefined;
37
+ const [internalValue, setInternalValue] = useState(defaultValue ?? EMPTY_RANGE);
38
+ const range = isControlled ? controlledValue : internalValue;
39
+ const [start, end] = range;
40
+ // Nothing before year 1 is in range, as in HTML's date inputs.
41
+ const lowerBound = useMemo(() => floorMin(min), [min]);
42
+ const [focusedDate, setFocusedDate] = useState(() => clampDate(start ?? end ?? new Date(), lowerBound, max));
43
+ // Re-clamp the focused day if the bounds change after mount, so the
44
+ // calendar never shows a month outside them.
45
+ useEffect(() => {
46
+ setFocusedDate(prev => clampDate(prev, lowerBound, max));
47
+ }, [lowerBound, max]);
48
+ const [open, setOpenState] = useState(false);
49
+ const [startText, setStartText] = useState(() => start ? formatDate(start, resolvedFormat, locale) : '');
50
+ const [endText, setEndText] = useState(() => end ? formatDate(end, resolvedFormat, locale) : '');
51
+ // Each input shows its end of the range as it changes from outside.
52
+ useEffect(() => {
53
+ setStartText(start ? formatDate(start, resolvedFormat, locale) : '');
54
+ }, [start, resolvedFormat, locale]);
55
+ useEffect(() => {
56
+ setEndText(end ? formatDate(end, resolvedFormat, locale) : '');
57
+ }, [end, resolvedFormat, locale]);
58
+ const containerRef = useRef(null);
59
+ const startRef = useRef(null);
60
+ const endRef = useRef(null);
61
+ const reactId = useId();
62
+ const popoverId = id ? `${id}-popover` : `picker-${reactId}`;
63
+ const { bulmaHelperClasses, rest: cleanRest } = useBulmaClasses(rest);
64
+ const { shouldUseNative } = useNativeMobilePicker({
65
+ force: mobileNative === 'auto' ? undefined : mobileNative,
66
+ });
67
+ const useNative = !inline && shouldUseNative;
68
+ // The root borrows DateInput's container class, which places the launcher
69
+ // and sizes a Control's icons around the field.
70
+ const containerClass = usePrefixedClassNames('daterangeinput', 'dateinput-container');
71
+ const fieldClass = usePrefixedClassNames('input', 'daterangeinput-field', {
72
+ [`is-${color}`]: !!color,
73
+ [`is-${size}`]: !!size,
74
+ 'is-rounded': isRounded,
75
+ 'is-disabled': disabled,
76
+ });
77
+ const inputClass = usePrefixedClassNames('daterangeinput-input');
78
+ const separatorClass = usePrefixedClassNames('daterangeinput-separator');
79
+ const triggerClass = usePrefixedClassNames('dateinput-trigger');
80
+ // What the latest request asked for, so a second request in the same event
81
+ // sees it before React renders. The callbacks fire here rather than in a
82
+ // state updater, which StrictMode calls twice.
83
+ const requestedOpenRef = useRef(false);
84
+ const setOpen = useCallback((next) => {
85
+ if (requestedOpenRef.current === next)
86
+ return;
87
+ requestedOpenRef.current = next;
88
+ setOpenState(next);
89
+ if (next)
90
+ onOpen?.();
91
+ else
92
+ onClose?.();
93
+ }, [onOpen, onClose]);
94
+ // Focus that moves inside the field, from one input to the other or from
95
+ // the launcher, is not focus arriving, so it opens nothing. Set as the
96
+ // focus is captured on the way in, and cleared once the input has handled
97
+ // it, so a click that follows still opens the popover.
98
+ const focusFromInsideRef = useRef(false);
99
+ const handleFocusCapture = (e) => {
100
+ const from = e.relatedTarget;
101
+ focusFromInsideRef.current = !!from && e.currentTarget.contains(from);
102
+ onFocusCapture?.(e);
103
+ };
104
+ const handleFocus = (e) => {
105
+ focusFromInsideRef.current = false;
106
+ onFocus?.(e);
107
+ };
108
+ const requestOpen = useCallback((next) => {
109
+ if (next && focusFromInsideRef.current)
110
+ return;
111
+ setOpen(next);
112
+ }, [setOpen]);
113
+ const commitRange = useCallback((next) => {
114
+ if (!isControlled)
115
+ setInternalValue(next);
116
+ onChange?.(next);
117
+ }, [isControlled, onChange]);
118
+ const constraints = useMemo(() => ({ shouldDisableDate, unselectableDates }), [shouldDisableDate, unselectableDates]);
119
+ // A day the calendar disables: shouldDisableDate or unselectableDates.
120
+ // Typing and the native inputs check the bounds alongside it.
121
+ const isBlockedDay = useCallback((d) => !!shouldDisableDate?.(d) ||
122
+ !!unselectableDates?.some(u => isSameDay(u, d)), [shouldDisableDate, unselectableDates]);
123
+ // An end the range can take: it is not disabled, and it closes a range
124
+ // from the start, which it can't when it comes first or, unless allowed,
125
+ // reaches over a disabled day.
126
+ const isBlockedEnd = useCallback((d) => isBlockedDay(d) ||
127
+ (!!start && !canCloseRange(start, d, constraints, allowDisabledInRange)), [isBlockedDay, start, constraints, allowDisabledInRange]);
128
+ // A new start keeps the end only while the two still make a range, so a
129
+ // start moved past the end, or over a disabled day before it, clears it.
130
+ const commitStart = useCallback((next) => {
131
+ const keepsEnd = !next ||
132
+ !end ||
133
+ canCloseRange(next, end, constraints, allowDisabledInRange);
134
+ commitRange([next, keepsEnd ? end : null]);
135
+ if (next)
136
+ setFocusedDate(next);
137
+ }, [end, constraints, allowDisabledInRange, commitRange]);
138
+ // Every digit typed into the start commits, so a start passes through
139
+ // values on its way to the one being typed. The first digits of a year make
140
+ // a start centuries back, which can't keep the end once a disabled day may
141
+ // lie between. Such a value waits for the segment's next digit rather than
142
+ // clearing an end the finished start may keep.
143
+ const startCostsEnd = useCallback((d) => !!end && !canCloseRange(d, end, constraints, allowDisabledInRange), [end, constraints, allowDisabledInRange]);
144
+ const commitEnd = useCallback((next) => {
145
+ commitRange([start, next]);
146
+ if (next)
147
+ setFocusedDate(next);
148
+ }, [start, commitRange]);
149
+ const handleRangeSelect = useCallback((from, to) => {
150
+ commitRange([from, to]);
151
+ setFocusedDate(to);
152
+ if (closeOnSelect)
153
+ setOpen(false);
154
+ }, [commitRange, closeOnSelect, setOpen]);
155
+ const tryParse = useCallback((s) => {
156
+ const trimmed = s.trim();
157
+ if (!trimmed)
158
+ return null;
159
+ const fmt = typeof format === 'string' ? format : undefined;
160
+ return parse
161
+ ? parse(trimmed)
162
+ : parseDate(trimmed, fmt ?? DEFAULT_DATE_FORMAT);
163
+ }, [parse, format, locale]);
164
+ // Typing into an empty end starts from the start, so only what differs
165
+ // needs typing; an empty start starts from today.
166
+ const makeEndBase = useCallback(() => (start ? startOfDay(start) : today()), [start]);
167
+ // Where focus goes back as the popover closes: the input focused last,
168
+ // which is the one that opened it unless the launcher did, or the start
169
+ // input before either has had focus.
170
+ const openerRef = useRef(null);
171
+ const restoreFocusRef = useMemo(() => ({
172
+ get current() {
173
+ return openerRef.current ?? startRef.current;
174
+ },
175
+ }), []);
176
+ const shared = {
177
+ format: resolvedFormat,
178
+ formatFn: formatDate,
179
+ tryParse,
180
+ locale,
181
+ min: lowerBound,
182
+ max,
183
+ disabled,
184
+ readOnly,
185
+ editable,
186
+ popover,
187
+ openOnFocus,
188
+ closeOnSelect,
189
+ isOpen: open,
190
+ setOpen: requestOpen,
191
+ };
192
+ // Each input is its own picker field. Its blur counts focus leaving it,
193
+ // even for the other input, so text typed into one is read as focus moves
194
+ // to the other.
195
+ const { inputHandlers: startHandlers } = useSegmentedEntry({
196
+ ...shared,
197
+ value: start,
198
+ commitValue: commitStart,
199
+ text: startText,
200
+ setText: setStartText,
201
+ makeBaseDate: today,
202
+ isBlocked: isBlockedDay,
203
+ isUnfinishedBlocked: startCostsEnd,
204
+ inputRef: startRef,
205
+ containerRef: startRef,
206
+ onFocus: () => {
207
+ openerRef.current = startRef.current;
208
+ },
209
+ });
210
+ const { inputHandlers: endHandlers } = useSegmentedEntry({
211
+ ...shared,
212
+ value: end,
213
+ commitValue: commitEnd,
214
+ text: endText,
215
+ setText: setEndText,
216
+ makeBaseDate: makeEndBase,
217
+ isBlocked: isBlockedEnd,
218
+ inputRef: endRef,
219
+ containerRef: endRef,
220
+ onFocus: () => {
221
+ openerRef.current = endRef.current;
222
+ },
223
+ });
224
+ const combinedRef = useCallback((node) => {
225
+ startRef.current =
226
+ node;
227
+ if (typeof ref === 'function')
228
+ ref(node);
229
+ else if (ref)
230
+ ref.current = node;
231
+ }, [ref]);
232
+ const handlePopoverClose = useCallback(() => setOpen(false), [setOpen]);
233
+ const startField = startName ?? (name ? `${name}[start]` : undefined);
234
+ const endField = endName ?? (name ? `${name}[end]` : undefined);
235
+ const hiddenInputs = (jsxs(Fragment, { children: [startField && (jsx("input", { type: "hidden", name: startField, form: form, value: isoDay(start) })), endField && (jsx("input", { type: "hidden", name: endField, form: form, value: isoDay(end) }))] }));
236
+ const separator = (jsx("span", { className: separatorClass, "aria-hidden": "true", children: t.rangeSeparator }));
237
+ // Native mobile path: two <input type="date">s, held to the same rules as
238
+ // typing. A change the rules refuse leaves the input showing the range.
239
+ if (useNative) {
240
+ const nativeChange = (commit, isBlocked) => (e) => {
241
+ // An empty value is the end cleared. A date input gives nothing else
242
+ // that doesn't read as a date.
243
+ const parsed = fromIsoValue(e.target.value, 'day');
244
+ if (!parsed)
245
+ commit(null);
246
+ else if (isWithin(parsed, lowerBound, max) && !isBlocked(parsed)) {
247
+ commit(parsed);
248
+ }
249
+ };
250
+ const minIso = min ? isoDay(lowerBound) : undefined;
251
+ const maxIso = max ? isoDay(max) : undefined;
252
+ return (jsxs("div", { ...cleanRest, ref: containerRef, role: "group", className: classNames(containerClass, bulmaHelperClasses, className), onFocus: onFocus, onFocusCapture: onFocusCapture, children: [jsxs("div", { className: fieldClass, children: [jsx("input", { ref: combinedRef, type: "date", id: id, "aria-label": t.rangeStart, className: inputClass, value: isoDay(start), onChange: nativeChange(commitStart, isBlockedDay), min: minIso, max: maxIso, disabled: disabled, readOnly: readOnly, required: required }), separator, jsx("input", { ref: endRef, type: "date", id: id ? `${id}-end` : undefined, "aria-label": t.rangeEnd, className: inputClass, value: isoDay(end), onChange: nativeChange(commitEnd, isBlockedEnd), min: start ? isoDay(start) : minIso, max: maxIso, disabled: disabled, readOnly: readOnly, required: required })] }), hiddenInputs] }));
253
+ }
254
+ const calendar = (jsx(Calendar, { range: range, onRangeSelect: handleRangeSelect, allowDisabledInRange: allowDisabledInRange, focusedDate: focusedDate, onFocusedDateChange: setFocusedDate, min: min, max: max, shouldDisableDate: shouldDisableDate, unselectableDates: unselectableDates, firstDayOfWeek: firstDayOfWeek, locale: locale, dayNames: dayNames, monthNames: monthNames, nearbyMonthDays: nearbyMonthDays, color: color, size: size,
255
+ // The popover panel takes `popoverId`, so the calendar inside it takes
256
+ // one of its own. Inline there is no panel.
257
+ id: inline ? popoverId : `${popoverId}-cal`, autoFocusCell: open, labels: labels }));
258
+ if (inline) {
259
+ return (jsxs("div", { ...cleanRest, ref: containerRef, role: "group", className: classNames(containerClass, bulmaHelperClasses, className), onFocus: onFocus, onFocusCapture: onFocusCapture, children: [calendar, hiddenInputs] }));
260
+ }
261
+ const canOpen = !!popover && !disabled && !readOnly;
262
+ const inputReadOnly = !!readOnly || !editable;
263
+ // The field reads as one text box, so a press on it that misses both
264
+ // inputs, on its padding, the gap or the separator, goes to the nearer
265
+ // input and does what a press on that input does.
266
+ const handleFieldMouseDown = (e) => {
267
+ const startInput = startRef.current;
268
+ const endInput = endRef.current;
269
+ if (disabled || e.button !== 0)
270
+ return;
271
+ if (e.target === startInput || e.target === endInput)
272
+ return;
273
+ e.preventDefault();
274
+ const middle = (startInput.getBoundingClientRect().right +
275
+ endInput.getBoundingClientRect().left) /
276
+ 2;
277
+ (e.clientX < middle ? startInput : endInput).focus();
278
+ if (openOnFocus && canOpen)
279
+ requestOpen(true);
280
+ };
281
+ const comboboxProps = {
282
+ type: 'text',
283
+ role: 'combobox',
284
+ 'aria-haspopup': 'dialog',
285
+ 'aria-expanded': open,
286
+ 'aria-controls': popoverId,
287
+ autoComplete: 'off',
288
+ className: inputClass,
289
+ placeholder,
290
+ disabled,
291
+ readOnly: inputReadOnly,
292
+ required,
293
+ };
294
+ return (jsxs("div", { ...cleanRest, ref: containerRef, role: "group", className: classNames(containerClass, bulmaHelperClasses, className), onFocus: handleFocus, onFocusCapture: handleFocusCapture, children: [jsxs("div", { className: fieldClass, onMouseDown: handleFieldMouseDown, children: [jsx("input", { ...comboboxProps, ref: combinedRef, id: id, "aria-label": t.rangeStart, value: startText, ...startHandlers }), separator, jsx("input", { ...comboboxProps, ref: endRef, id: id ? `${id}-end` : undefined, "aria-label": t.rangeEnd, value: endText, ...endHandlers })] }), popover && triggerIcon && (jsx("button", { type: "button", className: triggerClass,
295
+ // Disabled whenever the popover can't open, so a click can.
296
+ onClick: () => setOpen(!open), disabled: !canOpen, "aria-label": t.chooseDateRange, "aria-haspopup": "dialog", "aria-controls": popoverId, "aria-expanded": open, tabIndex: canOpen ? 0 : -1, children: jsx(Icon, { name: triggerIconName, size: size }) })), popover && (jsx(PickerPopover, { isOpen: open, onClose: handlePopoverClose, anchorRef: containerRef, position: position, appendToBody: appendToBody, ariaLabel: t.chooseDateRange, id: popoverId, restoreFocusRef: restoreFocusRef, initialFocusSelector: CALENDAR_FOCUSED_CELL, children: calendar })), hiddenInputs] }));
297
+ });
298
+ DateRangeInputBase.displayName = 'DateRangeInputBase';
299
+
300
+ export { DateRangeInputBase };
301
+ //# sourceMappingURL=DateRangeInputBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateRangeInputBase.js","sources":["../../../src/form/DateRangeInputBase.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport {\n DateRangeValue,\n DayOfWeek,\n PickerLabels,\n PickerPosition,\n mergeLabels,\n} from './_pickerInternals/pickerTypes';\nimport {\n DEFAULT_DATE_FORMAT,\n DateFormatOption,\n formatDate,\n fromIsoValue,\n parseDate,\n toIsoValue,\n} from './_pickerInternals/formatters';\nimport {\n canCloseRange,\n clampDate,\n floorMin,\n isSameDay,\n isWithin,\n startOfDay,\n} from './_pickerInternals/dateUtils';\nimport { Calendar, CALENDAR_FOCUSED_CELL } from './_pickerInternals/Calendar';\nimport { PickerPopover } from './_pickerInternals/PickerPopover';\nimport { useNativeMobilePicker } from './_pickerInternals/useNativeMobilePicker';\nimport { useSegmentedEntry } from './_pickerInternals/useSegmentedEntry';\nimport { useControlLoading } from './controlLoading';\nimport { Icon } from '../elements/Icon';\n\nexport type { DateRangeValue };\n\nconst EMPTY_RANGE: DateRangeValue = [null, null];\n\n/** A range's end as the form and the native inputs carry it. */\nconst isoDay = (d: Date | null): string => (d ? toIsoValue(d, 'day') : '');\n\n/** Today at local midnight, where typing into an empty end starts. */\nconst today = (): Date => startOfDay(new Date());\n\n/**\n * Props for the raw DateRangeInput base. Use the higher-level\n * `DateRangeInput` for Field/Control composition; `DateRangeInputBase` is the\n * two inputs and the popover only.\n */\nexport interface DateRangeInputBaseProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange' | 'color' | 'placeholder' | 'popover'\n >,\n Omit<BulmaClassesProps, 'color'> {\n /**\n * Controlled range, start first. Either end may be `null`, and\n * `[null, null]` is empty.\n */\n value?: DateRangeValue;\n /** Initial range for uncontrolled usage. */\n defaultValue?: DateRangeValue;\n /**\n * Fired when the range changes, with the start first. Typing commits one\n * end at a time, so a range half typed arrives as `[start, null]`. The\n * calendar commits only a finished range: its first pick marks the start\n * inside the calendar and its second commits both ends in one call. The\n * range stays ordered, so the end is never before the start.\n */\n onChange?: (range: DateRangeValue) => void;\n /** Fired when the popover opens. */\n onOpen?: () => void;\n /** Fired when the popover closes. */\n onClose?: () => void;\n /**\n * Earliest selectable date, for either end. A `min` before year 1 is raised\n * to 1 January of year 1, where the range starts without one too.\n */\n min?: Date;\n /** Latest selectable date, for either end. */\n max?: Date;\n /** Disable both inputs and the launcher. */\n disabled?: boolean;\n /** Make both inputs read-only and keep the popover closed. */\n readOnly?: boolean;\n /** Placeholder text, shown in both inputs while they are empty. */\n placeholder?: string;\n /**\n * Token format string or `Intl.DateTimeFormat` options, used by both\n * inputs.\n * @defaultValue 'YYYY-MM-DD'\n */\n format?: DateFormatOption;\n /**\n * Custom parser (use when `format` is `Intl.DateTimeFormatOptions`).\n * Enter and leaving an input call it only if the user changed its text.\n */\n parse?: (s: string) => Date | null;\n /** BCP-47 locale tag for day/month names and Intl formatting. */\n locale?: string;\n /**\n * Render the calendar inline, with no inputs and no popover. The hidden\n * form inputs still carry the range.\n */\n inline?: boolean;\n /**\n * Use two native `<input type=\"date\">`s on coarse-pointer, small-viewport\n * devices (`'auto'`), always (`true`) or never (`false`). The end input's\n * `min` follows the start, and a change goes through the same rules as\n * typing.\n */\n mobileNative?: boolean | 'auto';\n /** Allow segmented keyboard typing in both inputs. `false` makes the field picker-only. */\n editable?: boolean;\n /** Whether the calendar popover exists. `false` makes the field input-only. */\n popover?: boolean;\n /**\n * Open the popover when focus arrives in the field. Moving focus between\n * the two inputs, or back from the launcher, leaves it closed, and so does\n * the focus a closing popover hands back. A click on either input opens it.\n * With it off, the launcher or Alt+ArrowDown opens it.\n */\n openOnFocus?: boolean;\n /**\n * Close the popover once the range is picked. The first pick, which only\n * marks the start, never closes it.\n */\n closeOnSelect?: boolean;\n /** Popover anchor position relative to the field. */\n position?: PickerPosition;\n /** Render the popover into `document.body` via portal. */\n appendToBody?: boolean;\n /**\n * Bulma color modifier for the field, also carried by the calendar, where it\n * colors the range's ends and the band between them.\n */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Render the field with rounded corners. */\n isRounded?: boolean;\n /**\n * Predicate to disable specific dates (e.g. weekends). A disabled day can\n * be neither end, typing rejects it, and a range can't include one unless\n * `allowDisabledInRange` is set.\n */\n shouldDisableDate?: (d: Date) => boolean;\n /** Convenience array of disabled dates; merged with `shouldDisableDate`. Matched by calendar day. */\n unselectableDates?: Date[];\n /**\n * Let a range include days that `shouldDisableDate` or `unselectableDates`\n * disable, such as a stay over a night with no check-ins. Its ends still\n * can't be such days. Off, a pick in the calendar past a disabled day\n * starts a new range there, typing refuses an end past one, and a start\n * typed with one before the end clears the end. Finding one walks the days\n * between, so off, a span too long to walk is refused as well.\n */\n allowDisabledInRange?: boolean;\n /** Day the week starts on (0 = Sunday). */\n firstDayOfWeek?: DayOfWeek;\n /** Override the 7 day-name labels (in calendar order, post-rotation). */\n dayNames?: string[];\n /** Override the 12 month-name labels. */\n monthNames?: string[];\n /** Show dimmed dates from adjacent months in the grid. */\n nearbyMonthDays?: boolean;\n /** Decorative left icon glyph for the wrapping `Control` (shown by default). Set `''` to hide. */\n iconLeftName?: string;\n /**\n * Show a clickable launcher button on the right that toggles the popover.\n * Hidden by default while a `Control` it sits in shows its `isLoading`\n * spinner, which shares that right edge.\n * @defaultValue true\n */\n triggerIcon?: boolean;\n /** Glyph for the right launcher button. */\n triggerIconName?: string;\n /**\n * Optional translatable string overrides. `rangeStart` and `rangeEnd` name\n * the two inputs and the range's ends in the calendar, `rangePreviewEnd`\n * describes the day a pending range would end on, `rangeSeparator` sits\n * between the inputs, and `chooseDateRange` names the launcher and the\n * popover.\n */\n labels?: PickerLabels;\n /**\n * Form field name. Two hidden inputs submit the range as `YYYY-MM-DD`,\n * named `name[start]` and `name[end]`, in every mode. The visible inputs\n * carry no name.\n */\n name?: string;\n /** Name of the hidden input carrying the start, in place of `name[start]`. */\n startName?: string;\n /** Name of the hidden input carrying the end, in place of `name[end]`. */\n endName?: string;\n /** Form id the hidden inputs belong to. */\n form?: string;\n /**\n * Mark both visible inputs required, so a form won't submit with either\n * end empty. An `inline` calendar has no visible input, so it is not\n * checked there.\n */\n required?: boolean;\n /** Id of the start input. The end input takes `${id}-end`. */\n id?: string;\n}\n\n/**\n * Raw DateRangeInput: the two inputs and the popover calendar without\n * Field/Control wrapping. Use `DateRangeInput` for the convenience wrapper.\n *\n * @function\n * @param {DateRangeInputBaseProps} props\n * @returns {JSX.Element}\n */\nexport const DateRangeInputBase = forwardRef<\n HTMLInputElement,\n DateRangeInputBaseProps\n>((props, ref) => {\n const {\n value: controlledValue,\n defaultValue,\n onChange,\n onOpen,\n onClose,\n min,\n max,\n disabled,\n readOnly,\n placeholder,\n format,\n parse,\n locale,\n inline = false,\n mobileNative = 'auto',\n editable = true,\n popover = true,\n openOnFocus = true,\n closeOnSelect = true,\n position = 'bottom-left',\n appendToBody = false,\n color,\n size,\n isRounded,\n shouldDisableDate,\n unselectableDates,\n allowDisabledInRange = false,\n firstDayOfWeek = 0,\n dayNames,\n monthNames,\n nearbyMonthDays = true,\n iconLeftName: _iconLeftName,\n triggerIcon: triggerIconProp,\n triggerIconName = 'chevron-down',\n labels,\n name,\n startName,\n endName,\n form,\n required,\n id,\n className,\n onFocus,\n onFocusCapture,\n ...rest\n } = props;\n // The launcher gives way to the loading spinner of a Control this sits in.\n const controlLoading = useControlLoading();\n const triggerIcon = triggerIconProp ?? !controlLoading;\n\n const t = mergeLabels(labels);\n const resolvedFormat = format ?? DEFAULT_DATE_FORMAT;\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState<DateRangeValue>(\n defaultValue ?? EMPTY_RANGE\n );\n const range = isControlled ? controlledValue : internalValue;\n const [start, end] = range;\n\n // Nothing before year 1 is in range, as in HTML's date inputs.\n const lowerBound = useMemo(() => floorMin(min), [min]);\n\n const [focusedDate, setFocusedDate] = useState<Date>(() =>\n clampDate(start ?? end ?? new Date(), lowerBound, max)\n );\n // Re-clamp the focused day if the bounds change after mount, so the\n // calendar never shows a month outside them.\n useEffect(() => {\n setFocusedDate(prev => clampDate(prev, lowerBound, max));\n }, [lowerBound, max]);\n\n const [open, setOpenState] = useState(false);\n const [startText, setStartText] = useState(() =>\n start ? formatDate(start, resolvedFormat, locale) : ''\n );\n const [endText, setEndText] = useState(() =>\n end ? formatDate(end, resolvedFormat, locale) : ''\n );\n // Each input shows its end of the range as it changes from outside.\n useEffect(() => {\n setStartText(start ? formatDate(start, resolvedFormat, locale) : '');\n }, [start, resolvedFormat, locale]);\n useEffect(() => {\n setEndText(end ? formatDate(end, resolvedFormat, locale) : '');\n }, [end, resolvedFormat, locale]);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const startRef = useRef<HTMLInputElement>(null);\n const endRef = useRef<HTMLInputElement>(null);\n const reactId = useId();\n const popoverId = id ? `${id}-popover` : `picker-${reactId}`;\n\n const { bulmaHelperClasses, rest: cleanRest } = useBulmaClasses(rest);\n\n const { shouldUseNative } = useNativeMobilePicker({\n force: mobileNative === 'auto' ? undefined : mobileNative,\n });\n const useNative = !inline && shouldUseNative;\n\n // The root borrows DateInput's container class, which places the launcher\n // and sizes a Control's icons around the field.\n const containerClass = usePrefixedClassNames(\n 'daterangeinput',\n 'dateinput-container'\n );\n const fieldClass = usePrefixedClassNames('input', 'daterangeinput-field', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-rounded': isRounded,\n 'is-disabled': disabled,\n });\n const inputClass = usePrefixedClassNames('daterangeinput-input');\n const separatorClass = usePrefixedClassNames('daterangeinput-separator');\n const triggerClass = usePrefixedClassNames('dateinput-trigger');\n\n // What the latest request asked for, so a second request in the same event\n // sees it before React renders. The callbacks fire here rather than in a\n // state updater, which StrictMode calls twice.\n const requestedOpenRef = useRef(false);\n const setOpen = useCallback(\n (next: boolean) => {\n if (requestedOpenRef.current === next) return;\n requestedOpenRef.current = next;\n setOpenState(next);\n if (next) onOpen?.();\n else onClose?.();\n },\n [onOpen, onClose]\n );\n\n // Focus that moves inside the field, from one input to the other or from\n // the launcher, is not focus arriving, so it opens nothing. Set as the\n // focus is captured on the way in, and cleared once the input has handled\n // it, so a click that follows still opens the popover.\n const focusFromInsideRef = useRef(false);\n const handleFocusCapture = (e: React.FocusEvent<HTMLDivElement>) => {\n const from = e.relatedTarget as Node | null;\n focusFromInsideRef.current = !!from && e.currentTarget.contains(from);\n onFocusCapture?.(e);\n };\n const handleFocus = (e: React.FocusEvent<HTMLDivElement>) => {\n focusFromInsideRef.current = false;\n onFocus?.(e);\n };\n const requestOpen = useCallback(\n (next: boolean) => {\n if (next && focusFromInsideRef.current) return;\n setOpen(next);\n },\n [setOpen]\n );\n\n const commitRange = useCallback(\n (next: DateRangeValue) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n\n const constraints = useMemo(\n () => ({ shouldDisableDate, unselectableDates }),\n [shouldDisableDate, unselectableDates]\n );\n // A day the calendar disables: shouldDisableDate or unselectableDates.\n // Typing and the native inputs check the bounds alongside it.\n const isBlockedDay = useCallback(\n (d: Date) =>\n !!shouldDisableDate?.(d) ||\n !!unselectableDates?.some(u => isSameDay(u, d)),\n [shouldDisableDate, unselectableDates]\n );\n // An end the range can take: it is not disabled, and it closes a range\n // from the start, which it can't when it comes first or, unless allowed,\n // reaches over a disabled day.\n const isBlockedEnd = useCallback(\n (d: Date) =>\n isBlockedDay(d) ||\n (!!start && !canCloseRange(start, d, constraints, allowDisabledInRange)),\n [isBlockedDay, start, constraints, allowDisabledInRange]\n );\n\n // A new start keeps the end only while the two still make a range, so a\n // start moved past the end, or over a disabled day before it, clears it.\n const commitStart = useCallback(\n (next: Date | null) => {\n const keepsEnd =\n !next ||\n !end ||\n canCloseRange(next, end, constraints, allowDisabledInRange);\n commitRange([next, keepsEnd ? end : null]);\n if (next) setFocusedDate(next);\n },\n [end, constraints, allowDisabledInRange, commitRange]\n );\n // Every digit typed into the start commits, so a start passes through\n // values on its way to the one being typed. The first digits of a year make\n // a start centuries back, which can't keep the end once a disabled day may\n // lie between. Such a value waits for the segment's next digit rather than\n // clearing an end the finished start may keep.\n const startCostsEnd = useCallback(\n (d: Date) =>\n !!end && !canCloseRange(d, end, constraints, allowDisabledInRange),\n [end, constraints, allowDisabledInRange]\n );\n const commitEnd = useCallback(\n (next: Date | null) => {\n commitRange([start, next]);\n if (next) setFocusedDate(next);\n },\n [start, commitRange]\n );\n\n const handleRangeSelect = useCallback(\n (from: Date, to: Date) => {\n commitRange([from, to]);\n setFocusedDate(to);\n if (closeOnSelect) setOpen(false);\n },\n [commitRange, closeOnSelect, setOpen]\n );\n\n const tryParse = useCallback(\n (s: string): Date | null => {\n const trimmed = s.trim();\n if (!trimmed) return null;\n const fmt = typeof format === 'string' ? format : undefined;\n return parse\n ? parse(trimmed)\n : parseDate(trimmed, fmt ?? DEFAULT_DATE_FORMAT, locale);\n },\n [parse, format, locale]\n );\n\n // Typing into an empty end starts from the start, so only what differs\n // needs typing; an empty start starts from today.\n const makeEndBase = useCallback(\n () => (start ? startOfDay(start) : today()),\n [start]\n );\n\n // Where focus goes back as the popover closes: the input focused last,\n // which is the one that opened it unless the launcher did, or the start\n // input before either has had focus.\n const openerRef = useRef<HTMLInputElement | null>(null);\n const restoreFocusRef = useMemo(\n () => ({\n get current() {\n return openerRef.current ?? startRef.current;\n },\n }),\n []\n );\n\n const shared = {\n format: resolvedFormat,\n formatFn: formatDate,\n tryParse,\n locale,\n min: lowerBound,\n max,\n disabled,\n readOnly,\n editable,\n popover,\n openOnFocus,\n closeOnSelect,\n isOpen: open,\n setOpen: requestOpen,\n };\n // Each input is its own picker field. Its blur counts focus leaving it,\n // even for the other input, so text typed into one is read as focus moves\n // to the other.\n const { inputHandlers: startHandlers } = useSegmentedEntry({\n ...shared,\n value: start,\n commitValue: commitStart,\n text: startText,\n setText: setStartText,\n makeBaseDate: today,\n isBlocked: isBlockedDay,\n isUnfinishedBlocked: startCostsEnd,\n inputRef: startRef,\n containerRef: startRef,\n onFocus: () => {\n openerRef.current = startRef.current;\n },\n });\n const { inputHandlers: endHandlers } = useSegmentedEntry({\n ...shared,\n value: end,\n commitValue: commitEnd,\n text: endText,\n setText: setEndText,\n makeBaseDate: makeEndBase,\n isBlocked: isBlockedEnd,\n inputRef: endRef,\n containerRef: endRef,\n onFocus: () => {\n openerRef.current = endRef.current;\n },\n });\n\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (startRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n },\n [ref]\n );\n\n const handlePopoverClose = useCallback(() => setOpen(false), [setOpen]);\n\n const startField = startName ?? (name ? `${name}[start]` : undefined);\n const endField = endName ?? (name ? `${name}[end]` : undefined);\n const hiddenInputs = (\n <>\n {startField && (\n <input\n type=\"hidden\"\n name={startField}\n form={form}\n value={isoDay(start)}\n />\n )}\n {endField && (\n <input type=\"hidden\" name={endField} form={form} value={isoDay(end)} />\n )}\n </>\n );\n\n const separator = (\n <span className={separatorClass} aria-hidden=\"true\">\n {t.rangeSeparator}\n </span>\n );\n\n // Native mobile path: two <input type=\"date\">s, held to the same rules as\n // typing. A change the rules refuse leaves the input showing the range.\n if (useNative) {\n const nativeChange =\n (commit: (d: Date | null) => void, isBlocked: (d: Date) => boolean) =>\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // An empty value is the end cleared. A date input gives nothing else\n // that doesn't read as a date.\n const parsed = fromIsoValue(e.target.value, 'day');\n if (!parsed) commit(null);\n else if (isWithin(parsed, lowerBound, max) && !isBlocked(parsed)) {\n commit(parsed);\n }\n };\n const minIso = min ? isoDay(lowerBound) : undefined;\n const maxIso = max ? isoDay(max) : undefined;\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={onFocus}\n onFocusCapture={onFocusCapture}\n >\n <div className={fieldClass}>\n <input\n ref={combinedRef}\n type=\"date\"\n id={id}\n aria-label={t.rangeStart}\n className={inputClass}\n value={isoDay(start)}\n onChange={nativeChange(commitStart, isBlockedDay)}\n min={minIso}\n max={maxIso}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n {separator}\n <input\n ref={endRef}\n type=\"date\"\n id={id ? `${id}-end` : undefined}\n aria-label={t.rangeEnd}\n className={inputClass}\n value={isoDay(end)}\n onChange={nativeChange(commitEnd, isBlockedEnd)}\n min={start ? isoDay(start) : minIso}\n max={maxIso}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n </div>\n {hiddenInputs}\n </div>\n );\n }\n\n const calendar = (\n <Calendar\n range={range}\n onRangeSelect={handleRangeSelect}\n allowDisabledInRange={allowDisabledInRange}\n focusedDate={focusedDate}\n onFocusedDateChange={setFocusedDate}\n min={min}\n max={max}\n shouldDisableDate={shouldDisableDate}\n unselectableDates={unselectableDates}\n firstDayOfWeek={firstDayOfWeek}\n locale={locale}\n dayNames={dayNames}\n monthNames={monthNames}\n nearbyMonthDays={nearbyMonthDays}\n color={color}\n size={size}\n // The popover panel takes `popoverId`, so the calendar inside it takes\n // one of its own. Inline there is no panel.\n id={inline ? popoverId : `${popoverId}-cal`}\n autoFocusCell={open}\n labels={labels}\n />\n );\n\n if (inline) {\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={onFocus}\n onFocusCapture={onFocusCapture}\n >\n {calendar}\n {hiddenInputs}\n </div>\n );\n }\n\n const canOpen = !!popover && !disabled && !readOnly;\n const inputReadOnly = !!readOnly || !editable;\n\n // The field reads as one text box, so a press on it that misses both\n // inputs, on its padding, the gap or the separator, goes to the nearer\n // input and does what a press on that input does.\n const handleFieldMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n const startInput = startRef.current as HTMLInputElement;\n const endInput = endRef.current as HTMLInputElement;\n if (disabled || e.button !== 0) return;\n if (e.target === startInput || e.target === endInput) return;\n e.preventDefault();\n const middle =\n (startInput.getBoundingClientRect().right +\n endInput.getBoundingClientRect().left) /\n 2;\n (e.clientX < middle ? startInput : endInput).focus();\n if (openOnFocus && canOpen) requestOpen(true);\n };\n const comboboxProps = {\n type: 'text',\n role: 'combobox',\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n 'aria-controls': popoverId,\n autoComplete: 'off',\n className: inputClass,\n placeholder,\n disabled,\n readOnly: inputReadOnly,\n required,\n };\n\n return (\n <div\n {...cleanRest}\n ref={containerRef}\n role=\"group\"\n className={classNames(containerClass, bulmaHelperClasses, className)}\n onFocus={handleFocus}\n onFocusCapture={handleFocusCapture}\n >\n <div className={fieldClass} onMouseDown={handleFieldMouseDown}>\n <input\n {...comboboxProps}\n ref={combinedRef}\n id={id}\n aria-label={t.rangeStart}\n value={startText}\n {...startHandlers}\n />\n {separator}\n <input\n {...comboboxProps}\n ref={endRef}\n id={id ? `${id}-end` : undefined}\n aria-label={t.rangeEnd}\n value={endText}\n {...endHandlers}\n />\n </div>\n {popover && triggerIcon && (\n <button\n type=\"button\"\n className={triggerClass}\n // Disabled whenever the popover can't open, so a click can.\n onClick={() => setOpen(!open)}\n disabled={!canOpen}\n aria-label={t.chooseDateRange}\n aria-haspopup=\"dialog\"\n aria-controls={popoverId}\n aria-expanded={open}\n tabIndex={canOpen ? 0 : -1}\n >\n <Icon name={triggerIconName} size={size} />\n </button>\n )}\n {popover && (\n <PickerPopover\n isOpen={open}\n onClose={handlePopoverClose}\n anchorRef={containerRef}\n position={position}\n appendToBody={appendToBody}\n ariaLabel={t.chooseDateRange}\n id={popoverId}\n restoreFocusRef={restoreFocusRef}\n initialFocusSelector={CALENDAR_FOCUSED_CELL}\n >\n {calendar}\n </PickerPopover>\n )}\n {hiddenInputs}\n </div>\n );\n});\n\nDateRangeInputBase.displayName = 'DateRangeInputBase';\n\nexport default DateRangeInputBase;\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
@@ -0,0 +1,88 @@
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 { DateTimeInputBase } from './DateTimeInputBase.js';
8
+ import { useInsideField, useInsideControl, rendersOwnField, rendersOwnControl } from './FormContext.js';
9
+ import { useAutoLabelId } from './useAutoLabelId.js';
10
+
11
+ /**
12
+ * The `DateTimeInput` combines a calendar and a time **wheel spinner** in a single popover — an iOS-style layout.
13
+ *
14
+ * @function
15
+ * @param {DateTimeInputProps} props
16
+ * @returns {JSX.Element}
17
+ *
18
+ * @example
19
+ * <DateTimeInput label="Appointment" defaultValue={new Date()} />
20
+ *
21
+ * @example
22
+ * <DateTimeInput
23
+ * label="When"
24
+ * hourFormat="12"
25
+ * shouldDisableDate={d => d.getDay() === 0 || d.getDay() === 6}
26
+ * />
27
+ */
28
+ const DateTimeInput = forwardRef((props, ref) => {
29
+ const { label, labelSize, labelProps, horizontal, iconLeft, iconRight, iconLeftName = 'calendar-alt', iconRightName, iconLeftSize, iconRightSize, hasIconsLeft, hasIconsRight, isLoading, isExpanded, controlSize, message, messageColor, fieldClassName, controlClassName, ...baseProps } = props;
30
+ const insideField = useInsideField();
31
+ const insideControl = useInsideControl();
32
+ const ownField = rendersOwnField('DateTimeInput', {
33
+ insideField,
34
+ insideControl,
35
+ label,
36
+ message,
37
+ horizontal,
38
+ fieldClassName,
39
+ });
40
+ // Inline mode renders a bare picker with no input, so the Control's
41
+ // icon-left container has nothing to anchor to, and it renders no
42
+ // Control inside one or out. The left icon is checked as the caller
43
+ // passed it: the default glyph is this component's own choice, not a
44
+ // prop the caller set, so it goes in only for the advice.
45
+ const ownControl = rendersOwnControl('DateTimeInput', {
46
+ insideControl,
47
+ inline: baseProps.inline,
48
+ isLoading,
49
+ iconLeft,
50
+ iconLeftName: props.iconLeftName,
51
+ defaultIconLeftName: iconLeftName,
52
+ iconLeftSize,
53
+ iconRight,
54
+ iconRightName,
55
+ iconRightSize,
56
+ hasIconsLeft,
57
+ hasIconsRight,
58
+ isExpanded,
59
+ controlSize,
60
+ controlClassName,
61
+ });
62
+ const { controlId, fieldLabelProps } = useAutoLabelId({
63
+ label,
64
+ id: baseProps.id,
65
+ labelProps,
66
+ // Inline mode renders a bare picker with no input to label.
67
+ rendersLabel: ownField && !baseProps.inline,
68
+ hasInput: !baseProps.inline,
69
+ });
70
+ const helpClass = usePrefixedClassNames('help', {
71
+ [`is-${messageColor}`]: !!messageColor,
72
+ });
73
+ // The base hides its launcher while the Control it sits in is loading,
74
+ // whether that is the one rendered below or an enclosing one.
75
+ let content = (jsx(DateTimeInputBase, { ref: ref, ...baseProps, id: controlId }));
76
+ if (ownControl) {
77
+ content = (jsx(Control, { iconLeft: iconLeft, iconRight: iconRight, iconLeftName: iconLeftName, iconRightName: iconRightName, iconLeftSize: iconLeftSize, iconRightSize: iconRightSize, hasIconsLeft: hasIconsLeft || !!iconLeftName, hasIconsRight: hasIconsRight, isLoading: isLoading, isExpanded: isExpanded, size: controlSize, className: controlClassName, children: content }));
78
+ }
79
+ const messageEl = message ? jsx("p", { className: helpClass, children: message }) : null;
80
+ if (ownField) {
81
+ return (jsxs(Field, { label: label, labelSize: labelSize, labelProps: fieldLabelProps, horizontal: horizontal, className: fieldClassName, children: [content, messageEl] }));
82
+ }
83
+ return (jsxs(Fragment, { children: [content, messageEl] }));
84
+ });
85
+ DateTimeInput.displayName = 'DateTimeInput';
86
+
87
+ export { DateTimeInput };
88
+ //# sourceMappingURL=DateTimeInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateTimeInput.js","sources":["../../../src/form/DateTimeInput.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { usePrefixedClassNames } from '../helpers/classNames';\nimport { Field, FieldProps } from './Field';\nimport { Control, ControlBaseProps } from './Control';\nimport { DateTimeInputBase, DateTimeInputBaseProps } from './DateTimeInputBase';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n rendersOwnControl,\n} from './FormContext';\nimport { useAutoLabelId } from './useAutoLabelId';\n\n/**\n * Props for the DateTimeInput convenience wrapper. Extends\n * `DateTimeInputBaseProps` with Field-level and Control-level 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. In `inline` mode it renders no `Control` anywhere,\n * so they do nothing inside a `Control` or out, and warn in development\n * there too. Inside an outer `Field`, or a `Control` with no `Field` around\n * 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 * @extraProp {string} [name] - Form field name.\n * @extraProp {string} [form] - Optional id of the form the input belongs to.\n * @extraProp {boolean} [required=false] - Marks the field as required for native HTML form validation.\n */\nexport interface DateTimeInputProps extends DateTimeInputBaseProps {\n /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). 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. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */\n labelProps?: FieldProps['labelProps'];\n /** Render the field with horizontal layout. */\n horizontal?: boolean;\n /**\n * Icon props for the 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 /**\n * Icon props for the right 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 iconRight?: ControlBaseProps['iconRight'];\n /** Shortcut for the right icon name. */\n iconRightName?: string;\n /** Shortcut for left icon size. */\n iconLeftSize?: ControlBaseProps['iconLeftSize'];\n /** Shortcut for right icon size. */\n iconRightSize?: ControlBaseProps['iconRightSize'];\n /** Force the left icon container. */\n hasIconsLeft?: boolean;\n /** Force the right icon container. */\n hasIconsRight?: boolean;\n /**\n * Shows a loading spinner on the `Control` it renders, and hides the\n * launcher (`triggerIcon`) while it does. Inside your own `Control` it\n * renders none, so this draws nothing and warns in development; set\n * `isLoading` on that `Control`.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n isLoading?: boolean;\n /**\n * Show a clickable launcher button on the right that toggles the popover.\n * Hidden by default while a spinner shows at the same right edge: this\n * component's `isLoading` when it renders its own `Control`, or the\n * enclosing `Control`'s `isLoading` inside one.\n * @defaultValue true\n */\n triggerIcon?: boolean;\n /** Expand the control to fill its container. */\n isExpanded?: boolean;\n /** Size of the wrapping Control. */\n controlSize?: ControlBaseProps['size'];\n /** Help/validation text below the input. */\n message?: React.ReactNode;\n /** Message color. */\n messageColor?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Additional CSS classes for the Field wrapper. */\n fieldClassName?: string;\n /** Additional CSS classes for the Control wrapper. */\n controlClassName?: string;\n}\n\n/**\n * The `DateTimeInput` combines a calendar and a time **wheel spinner** in a single popover — an iOS-style layout.\n *\n * @function\n * @param {DateTimeInputProps} props\n * @returns {JSX.Element}\n *\n * @example\n * <DateTimeInput label=\"Appointment\" defaultValue={new Date()} />\n *\n * @example\n * <DateTimeInput\n * label=\"When\"\n * hourFormat=\"12\"\n * shouldDisableDate={d => d.getDay() === 0 || d.getDay() === 6}\n * />\n */\nexport const DateTimeInput = forwardRef<HTMLInputElement, DateTimeInputProps>(\n (props, ref) => {\n const {\n label,\n labelSize,\n labelProps,\n horizontal,\n iconLeft,\n iconRight,\n iconLeftName = 'calendar-alt',\n iconRightName,\n iconLeftSize,\n iconRightSize,\n hasIconsLeft,\n hasIconsRight,\n isLoading,\n isExpanded,\n controlSize,\n message,\n messageColor,\n fieldClassName,\n controlClassName,\n ...baseProps\n } = props;\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('DateTimeInput', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n // Inline mode renders a bare picker with no input, so the Control's\n // icon-left container has nothing to anchor to, and it renders no\n // Control inside one or out. The left icon is checked as the caller\n // passed it: the default glyph is this component's own choice, not a\n // prop the caller set, so it goes in only for the advice.\n const ownControl = rendersOwnControl('DateTimeInput', {\n insideControl,\n inline: baseProps.inline,\n isLoading,\n iconLeft,\n iconLeftName: props.iconLeftName,\n defaultIconLeftName: iconLeftName,\n iconLeftSize,\n iconRight,\n iconRightName,\n iconRightSize,\n hasIconsLeft,\n hasIconsRight,\n isExpanded,\n controlSize,\n controlClassName,\n });\n const { controlId, fieldLabelProps } = useAutoLabelId({\n label,\n id: baseProps.id,\n labelProps,\n // Inline mode renders a bare picker with no input to label.\n rendersLabel: ownField && !baseProps.inline,\n hasInput: !baseProps.inline,\n });\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n\n // The base hides its launcher while the Control it sits in is loading,\n // whether that is the one rendered below or an enclosing one.\n let content: React.ReactNode = (\n <DateTimeInputBase ref={ref} {...baseProps} id={controlId} />\n );\n\n if (ownControl) {\n content = (\n <Control\n iconLeft={iconLeft}\n iconRight={iconRight}\n iconLeftName={iconLeftName}\n iconRightName={iconRightName}\n iconLeftSize={iconLeftSize}\n iconRightSize={iconRightSize}\n hasIconsLeft={hasIconsLeft || !!iconLeftName}\n hasIconsRight={hasIconsRight}\n isLoading={isLoading}\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\nDateTimeInput.displayName = 'DateTimeInput';\n\nexport default DateTimeInput;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}