nexus-shared 1.1.20 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +903 -0
  3. package/dist/Client.Index.d.ts +44 -0
  4. package/dist/Client.Index.js +49 -0
  5. package/dist/Components/Documents/Button.d.ts +29 -0
  6. package/dist/Components/Documents/Button.js +11 -0
  7. package/dist/Components/Documents/Menu.d.ts +102 -0
  8. package/dist/Components/Documents/Menu.js +238 -0
  9. package/dist/Components/Documents/SplitButton.d.ts +64 -0
  10. package/dist/Components/Documents/SplitButton.js +127 -0
  11. package/dist/Components/Documents/TabButtons.d.ts +62 -0
  12. package/dist/Components/Documents/TabButtons.js +19 -0
  13. package/dist/Components/Forms/ApiForm.d.ts +21 -0
  14. package/dist/Components/Forms/ApiForm.js +99 -0
  15. package/dist/Components/Forms/Crud.d.ts +17 -0
  16. package/dist/Components/Forms/Crud.js +556 -0
  17. package/dist/Components/Forms/CrudParts.d.ts +15 -0
  18. package/dist/Components/Forms/CrudParts.js +36 -0
  19. package/dist/Components/Forms/Form.d.ts +52 -0
  20. package/dist/Components/Forms/Form.js +319 -0
  21. package/dist/Components/Forms/SubmitForm.d.ts +65 -0
  22. package/dist/Components/Forms/SubmitForm.js +198 -0
  23. package/dist/Components/Inputs/Calendar.d.ts +69 -0
  24. package/dist/Components/Inputs/Calendar.js +258 -0
  25. package/dist/Components/Inputs/CheckBox.d.ts +53 -0
  26. package/dist/Components/Inputs/CheckBox.js +87 -0
  27. package/dist/Components/Inputs/CheckBoxGroup.d.ts +20 -0
  28. package/dist/Components/Inputs/CheckBoxGroup.js +80 -0
  29. package/dist/Components/Inputs/ChoiceField.d.ts +122 -0
  30. package/dist/Components/Inputs/ChoiceField.js +169 -0
  31. package/dist/Components/Inputs/DatePicker.d.ts +54 -0
  32. package/dist/Components/Inputs/DatePicker.js +246 -0
  33. package/dist/Components/Inputs/DateRangePicker.d.ts +62 -0
  34. package/dist/Components/Inputs/DateRangePicker.js +283 -0
  35. package/dist/Components/Inputs/DateTimePicker.d.ts +75 -0
  36. package/dist/Components/Inputs/DateTimePicker.js +399 -0
  37. package/dist/Components/Inputs/Dropdown.d.ts +117 -0
  38. package/dist/Components/Inputs/Dropdown.js +839 -0
  39. package/dist/Components/Inputs/DropdownParts.d.ts +84 -0
  40. package/dist/Components/Inputs/DropdownParts.js +102 -0
  41. package/dist/Components/Inputs/EditorShell.d.ts +45 -0
  42. package/dist/Components/Inputs/EditorShell.js +214 -0
  43. package/dist/Components/Inputs/Field.d.ts +53 -0
  44. package/dist/Components/Inputs/Field.js +16 -0
  45. package/dist/Components/Inputs/GroupForm.d.ts +20 -0
  46. package/dist/Components/Inputs/GroupForm.js +170 -0
  47. package/dist/Components/Inputs/InputField.d.ts +59 -0
  48. package/dist/Components/Inputs/InputField.js +169 -0
  49. package/dist/Components/Inputs/InputRenderer.d.ts +35 -0
  50. package/dist/Components/Inputs/InputRenderer.js +99 -0
  51. package/dist/Components/Inputs/MarkdownEditor.d.ts +67 -0
  52. package/dist/Components/Inputs/MarkdownEditor.js +289 -0
  53. package/dist/Components/Inputs/NumberBox.d.ts +53 -0
  54. package/dist/Components/Inputs/NumberBox.js +228 -0
  55. package/dist/Components/Inputs/RadioGroup.d.ts +20 -0
  56. package/dist/Components/Inputs/RadioGroup.js +43 -0
  57. package/dist/Components/Inputs/ReadOnlyNotice.d.ts +36 -0
  58. package/dist/Components/Inputs/ReadOnlyNotice.js +116 -0
  59. package/dist/Components/Inputs/RichTextEditor.d.ts +103 -0
  60. package/dist/Components/Inputs/RichTextEditor.js +1170 -0
  61. package/dist/Components/Inputs/RichTextParts.d.ts +63 -0
  62. package/dist/Components/Inputs/RichTextParts.js +157 -0
  63. package/dist/Components/Inputs/RowsInput.d.ts +104 -0
  64. package/dist/Components/Inputs/RowsInput.js +259 -0
  65. package/dist/Components/Inputs/Slider.d.ts +87 -0
  66. package/dist/Components/Inputs/Slider.js +216 -0
  67. package/dist/Components/Inputs/TabularForm.d.ts +23 -0
  68. package/dist/Components/Inputs/TabularForm.js +283 -0
  69. package/dist/Components/Inputs/TextArea.d.ts +43 -0
  70. package/dist/Components/Inputs/TextArea.js +31 -0
  71. package/dist/Components/Inputs/TextBox.d.ts +52 -0
  72. package/dist/Components/Inputs/TextBox.js +58 -0
  73. package/dist/Components/Inputs/TextField.d.ts +31 -0
  74. package/dist/Components/Inputs/TextField.js +35 -0
  75. package/dist/Components/Inputs/TimePanel.d.ts +34 -0
  76. package/dist/Components/Inputs/TimePanel.js +288 -0
  77. package/dist/Components/Inputs/TimePicker.d.ts +54 -0
  78. package/dist/Components/Inputs/TimePicker.js +239 -0
  79. package/dist/Components/Inputs/TreeView.d.ts +160 -0
  80. package/dist/Components/Inputs/TreeView.js +947 -0
  81. package/dist/Components/Layouts/MessageBox.d.ts +71 -0
  82. package/dist/Components/Layouts/MessageBox.js +104 -0
  83. package/dist/Components/Layouts/Popup.d.ts +92 -0
  84. package/dist/Components/Layouts/Popup.js +376 -0
  85. package/dist/Components/Layouts/PopupContext.d.ts +2 -0
  86. package/dist/Components/Layouts/PopupContext.js +4 -0
  87. package/dist/Components/Layouts/PopupDock.d.ts +22 -0
  88. package/dist/Components/Layouts/PopupDock.js +121 -0
  89. package/dist/Components/Layouts/PopupHost.d.ts +56 -0
  90. package/dist/Components/Layouts/PopupHost.js +163 -0
  91. package/dist/Components/Layouts/PopupRules.d.ts +30 -0
  92. package/dist/Components/Layouts/PopupRules.js +63 -0
  93. package/dist/Components/Layouts/ThemePicker.d.ts +13 -0
  94. package/dist/Components/Layouts/ThemePicker.js +22 -0
  95. package/dist/Components/Layouts/ThemeScript.d.ts +14 -0
  96. package/dist/Components/Layouts/ThemeScript.js +13 -0
  97. package/dist/Components/Layouts/ThemeSwitcher.d.ts +13 -0
  98. package/dist/Components/Layouts/ThemeSwitcher.js +29 -0
  99. package/dist/Components/Layouts/Toaster.d.ts +76 -0
  100. package/dist/Components/Layouts/Toaster.js +172 -0
  101. package/dist/Components/Viewers/DataTable.d.ts +25 -0
  102. package/dist/Components/Viewers/DataTable.js +542 -0
  103. package/dist/Components/Viewers/DataTableParts.d.ts +134 -0
  104. package/dist/Components/Viewers/DataTableParts.js +145 -0
  105. package/dist/Components/Viewers/MarkdownView.d.ts +26 -0
  106. package/dist/Components/Viewers/MarkdownView.js +79 -0
  107. package/dist/Components/Viewers/RichTextView.d.ts +18 -0
  108. package/dist/Components/Viewers/RichTextView.js +17 -0
  109. package/dist/Helpers/AnimationHelpers.d.ts +6 -0
  110. package/dist/Helpers/AnimationHelpers.js +35 -0
  111. package/dist/Helpers/ApiClient.d.ts +74 -0
  112. package/dist/Helpers/ApiClient.js +197 -0
  113. package/dist/Helpers/ApiFormHelpers.d.ts +26 -0
  114. package/dist/Helpers/ApiFormHelpers.js +56 -0
  115. package/dist/Helpers/ApiModules.d.ts +135 -0
  116. package/dist/Helpers/ApiModules.js +194 -0
  117. package/dist/Helpers/ApiResponses.d.ts +41 -0
  118. package/dist/Helpers/ApiResponses.js +159 -0
  119. package/dist/Helpers/ApiRoutes.d.ts +150 -0
  120. package/dist/Helpers/ApiRoutes.js +191 -0
  121. package/dist/Helpers/ApiToasts.d.ts +21 -0
  122. package/dist/Helpers/ApiToasts.js +22 -0
  123. package/dist/Helpers/ClassHelpers.d.ts +3 -0
  124. package/dist/Helpers/ClassHelpers.js +4 -0
  125. package/dist/Helpers/CrudBackend.d.ts +56 -0
  126. package/dist/Helpers/CrudBackend.js +119 -0
  127. package/dist/Helpers/CrudHelpers.d.ts +76 -0
  128. package/dist/Helpers/CrudHelpers.js +202 -0
  129. package/dist/Helpers/DateHelpers.d.ts +88 -0
  130. package/dist/Helpers/DateHelpers.js +363 -0
  131. package/dist/Helpers/DatePreferences.d.ts +14 -0
  132. package/dist/Helpers/DatePreferences.js +94 -0
  133. package/dist/Helpers/DateTimeHelpers.d.ts +87 -0
  134. package/dist/Helpers/DateTimeHelpers.js +286 -0
  135. package/dist/Helpers/DragHelpers.d.ts +129 -0
  136. package/dist/Helpers/DragHelpers.js +281 -0
  137. package/dist/Helpers/DropdownHelpers.d.ts +56 -0
  138. package/dist/Helpers/DropdownHelpers.js +180 -0
  139. package/dist/Helpers/FormDrafts.d.ts +18 -0
  140. package/dist/Helpers/FormDrafts.js +76 -0
  141. package/dist/Helpers/FormStore.d.ts +231 -0
  142. package/dist/Helpers/FormStore.js +734 -0
  143. package/dist/Helpers/InputParamsHelpers.d.ts +79 -0
  144. package/dist/Helpers/InputParamsHelpers.js +388 -0
  145. package/dist/Helpers/MarkdownEditing.d.ts +27 -0
  146. package/dist/Helpers/MarkdownEditing.js +250 -0
  147. package/dist/Helpers/MarkdownHelpers.d.ts +82 -0
  148. package/dist/Helpers/MarkdownHelpers.js +775 -0
  149. package/dist/Helpers/MessageBuilder.d.ts +74 -0
  150. package/dist/Helpers/MessageBuilder.js +254 -0
  151. package/dist/Helpers/NepaliCalendar.d.ts +25 -0
  152. package/dist/Helpers/NepaliCalendar.js +107 -0
  153. package/dist/Helpers/NumberHelpers.d.ts +71 -0
  154. package/dist/Helpers/NumberHelpers.js +202 -0
  155. package/dist/Helpers/Permissions.d.ts +62 -0
  156. package/dist/Helpers/Permissions.js +133 -0
  157. package/dist/Helpers/PopoverHelpers.d.ts +43 -0
  158. package/dist/Helpers/PopoverHelpers.js +91 -0
  159. package/dist/Helpers/RichTextHelpers.d.ts +77 -0
  160. package/dist/Helpers/RichTextHelpers.js +1072 -0
  161. package/dist/Helpers/RowsStore.d.ts +160 -0
  162. package/dist/Helpers/RowsStore.js +584 -0
  163. package/dist/Helpers/TableColumns.d.ts +40 -0
  164. package/dist/Helpers/TableColumns.js +254 -0
  165. package/dist/Helpers/TableExport.d.ts +30 -0
  166. package/dist/Helpers/TableExport.js +97 -0
  167. package/dist/Helpers/TableHelpers.d.ts +102 -0
  168. package/dist/Helpers/TableHelpers.js +281 -0
  169. package/dist/Helpers/TableStore.d.ts +142 -0
  170. package/dist/Helpers/TableStore.js +530 -0
  171. package/dist/Helpers/ThemeHelpers.d.ts +15 -0
  172. package/dist/Helpers/ThemeHelpers.js +16 -0
  173. package/dist/Helpers/TimeHelpers.d.ts +73 -0
  174. package/dist/Helpers/TimeHelpers.js +253 -0
  175. package/dist/Helpers/TreeStore.d.ts +188 -0
  176. package/dist/Helpers/TreeStore.js +577 -0
  177. package/dist/Helpers/ValidationHelpers.d.ts +124 -0
  178. package/dist/Helpers/ValidationHelpers.js +301 -0
  179. package/dist/Interfaces/ApiInterfaces.d.ts +149 -0
  180. package/dist/Interfaces/ApiInterfaces.js +24 -0
  181. package/dist/Interfaces/CrudInterfaces.d.ts +171 -0
  182. package/{src/sso-client.tsx → dist/Interfaces/CrudInterfaces.js} +1 -1
  183. package/dist/Interfaces/DateInterfaces.d.ts +154 -0
  184. package/dist/Interfaces/DateInterfaces.js +29 -0
  185. package/dist/Interfaces/FormInterfaces.d.ts +352 -0
  186. package/dist/Interfaces/FormInterfaces.js +1 -0
  187. package/dist/Interfaces/InputInterfaces.d.ts +141 -0
  188. package/dist/Interfaces/InputInterfaces.js +1 -0
  189. package/dist/Interfaces/MessageInterfaces.d.ts +111 -0
  190. package/dist/Interfaces/MessageInterfaces.js +5 -0
  191. package/dist/Interfaces/TableInterfaces.d.ts +291 -0
  192. package/dist/Interfaces/TableInterfaces.js +1 -0
  193. package/dist/Interfaces/ThemeInterfaces.d.ts +17 -0
  194. package/dist/Interfaces/ThemeInterfaces.js +17 -0
  195. package/dist/Interfaces/TypeInterfaces.d.ts +4 -0
  196. package/dist/Interfaces/TypeInterfaces.js +1 -0
  197. package/dist/Server.Index.d.ts +2 -0
  198. package/dist/Server.Index.js +5 -0
  199. package/dist/Services/ApiProxy.d.ts +32 -0
  200. package/dist/Services/ApiProxy.js +111 -0
  201. package/dist/Services/BrowserApi.d.ts +78 -0
  202. package/dist/Services/BrowserApi.js +111 -0
  203. package/dist/Services/ServerApi.d.ts +49 -0
  204. package/dist/Services/ServerApi.js +75 -0
  205. package/dist/Services/ThemeService.d.ts +17 -0
  206. package/dist/Services/ThemeService.js +83 -0
  207. package/dist/Shared.Index.d.ts +43 -0
  208. package/dist/Shared.Index.js +47 -0
  209. package/package.json +82 -33
  210. package/src/Styles/Nexus.Base.css +70 -0
  211. package/src/Styles/Nexus.Button.css +151 -0
  212. package/src/Styles/Nexus.Calendar.css +275 -0
  213. package/src/Styles/Nexus.Choice.css +345 -0
  214. package/src/Styles/Nexus.Crud.css +84 -0
  215. package/src/Styles/Nexus.DateTime.css +81 -0
  216. package/src/Styles/Nexus.Dropdown.css +774 -0
  217. package/src/Styles/Nexus.Editor.css +297 -0
  218. package/src/Styles/Nexus.Form.css +298 -0
  219. package/src/Styles/Nexus.Index.css +34 -0
  220. package/src/Styles/Nexus.Input.css +637 -0
  221. package/src/Styles/Nexus.Markdown.css +265 -0
  222. package/src/Styles/Nexus.Menu.css +249 -0
  223. package/src/Styles/Nexus.Popup.css +731 -0
  224. package/src/Styles/Nexus.RichText.css +463 -0
  225. package/src/Styles/Nexus.Rows.css +566 -0
  226. package/src/Styles/Nexus.Slider.css +278 -0
  227. package/src/Styles/Nexus.Tab.Buttons.css +364 -0
  228. package/src/Styles/Nexus.Table.css +1014 -0
  229. package/src/Styles/Nexus.Theme.Picker.css +159 -0
  230. package/src/Styles/Nexus.Themes.css +194 -0
  231. package/src/Styles/Nexus.Time.css +147 -0
  232. package/src/Styles/Nexus.Toast.css +265 -0
  233. package/src/Styles/Nexus.Tokens.css +72 -0
  234. package/src/Styles/Nexus.Tree.css +435 -0
  235. package/src/api-services/authentication-service.tsx +0 -23
  236. package/src/api-services/preference-service.tsx +0 -5
  237. package/src/api-services/system-service.tsx +0 -34
  238. package/src/client.ts +0 -31
  239. package/src/components/documents/button.tsx +0 -142
  240. package/src/components/documents/icon-box.tsx +0 -93
  241. package/src/components/documents/page-title.tsx +0 -7
  242. package/src/components/documents/tab-button.tsx +0 -172
  243. package/src/components/documents/tag.tsx +0 -30
  244. package/src/components/index.js +0 -0
  245. package/src/components/inputs/checkbox-input.tsx +0 -66
  246. package/src/components/inputs/input-box.tsx +0 -48
  247. package/src/components/inputs/input-element.tsx +0 -65
  248. package/src/components/inputs/input-form.tsx +0 -164
  249. package/src/components/inputs/input.tsx +0 -181
  250. package/src/components/inputs/number-input.tsx +0 -108
  251. package/src/components/inputs/radiobox-input.tsx +0 -53
  252. package/src/components/inputs/textarea-input.tsx +0 -47
  253. package/src/components/inputs/textbox-input.tsx +0 -45
  254. package/src/components/layouts/global-dialogbox.tsx +0 -431
  255. package/src/components/layouts/global-layout.tsx +0 -59
  256. package/src/components/layouts/layout-helpers.tsx +0 -20
  257. package/src/components/layouts/panels/user-panel.tsx +0 -112
  258. package/src/components/layouts/utility-menu.tsx +0 -49
  259. package/src/components/panels/theme-panel.tsx +0 -46
  260. package/src/helpers/bitwise-helpers.tsx +0 -11
  261. package/src/helpers/browser-helpers.tsx +0 -156
  262. package/src/helpers/datasource-helpers.tsx +0 -99
  263. package/src/helpers/element-helpers.tsx +0 -57
  264. package/src/helpers/input-helpers.tsx +0 -74
  265. package/src/helpers/string-helpers.tsx +0 -28
  266. package/src/helpers/utility-helpers.tsx +0 -45
  267. package/src/helpers/validation-helpers.tsx +0 -302
  268. package/src/index.ts +0 -26
  269. package/src/interface.ts +0 -19
  270. package/src/interfaces/auth-token-interfaces.tsx +0 -6
  271. package/src/interfaces/browser-interfaces.tsx +0 -36
  272. package/src/interfaces/button-interfaces.tsx +0 -63
  273. package/src/interfaces/datasource-interfaces.tsx +0 -22
  274. package/src/interfaces/datatable-interfaces.tsx +0 -25
  275. package/src/interfaces/dialogbox-interfaces.tsx +0 -5
  276. package/src/interfaces/exception-interfaces.tsx +0 -99
  277. package/src/interfaces/http-interfaces.tsx +0 -129
  278. package/src/interfaces/icon-interfaces.tsx +0 -129
  279. package/src/interfaces/input-interfaces.tsx +0 -410
  280. package/src/interfaces/layout-interfaces.tsx +0 -191
  281. package/src/interfaces/menu-interfaces.tsx +0 -49
  282. package/src/interfaces/message-interfaces.tsx +0 -32
  283. package/src/interfaces/permission-interfaces.tsx +0 -9
  284. package/src/interfaces/storage-interfaces.tsx +0 -5
  285. package/src/interfaces/system-interfaces.tsx +0 -22
  286. package/src/interfaces/theme-interfaces.tsx +0 -123
  287. package/src/interfaces/type-interfaces.tsx +0 -28
  288. package/src/interfaces/user-interfaces.tsx +0 -47
  289. package/src/nexus-client.tsx +0 -21
  290. package/src/nexus.environments.tsx +0 -66
  291. package/src/proxy-api/proxy-backend.tsx +0 -60
  292. package/src/proxy-api/proxy-constants.tsx +0 -28
  293. package/src/proxy-api/proxy-helpers.tsx +0 -91
  294. package/src/proxy-api-client.tsx +0 -1
  295. package/src/proxy-api-server.tsx +0 -2
  296. package/src/services/http-client-services.tsx +0 -75
  297. package/src/services/http-services.tsx +0 -158
  298. package/src/services/loader-service.tsx +0 -185
  299. package/src/services/localstorage-service.tsx +0 -119
  300. package/src/services/message-services.tsx +0 -383
  301. package/src/services/theme-service.tsx +0 -161
  302. package/src/services/user-services.tsx +0 -10
  303. package/src/sso-config/auth-token-validation.ts +0 -16
  304. package/src/sso-config/callback-route.tsx +0 -35
  305. package/src/sso-config/cookie-encryption.ts +0 -51
  306. package/src/sso-config/cookie-helpers.tsx +0 -102
  307. package/src/sso-config/forgot-password-route.tsx +0 -36
  308. package/src/sso-config/oauth-callback-state.ts +0 -61
  309. package/src/sso-config/pkce-helpers.ts +0 -9
  310. package/src/sso-config/provider-complete-route.tsx +0 -18
  311. package/src/sso-config/redirect-context-actions.tsx +0 -45
  312. package/src/sso-config/redirect-context-helpers.tsx +0 -159
  313. package/src/sso-config/redirect-context-persist.tsx +0 -18
  314. package/src/sso-config/redirect-context-route.tsx +0 -45
  315. package/src/sso-config/refresh-route.tsx +0 -23
  316. package/src/sso-config/sign-in-route.tsx +0 -74
  317. package/src/sso-config/sign-out-route.tsx +0 -57
  318. package/src/sso-config/sign-up-route.tsx +0 -57
  319. package/src/sso-config/sso-backend-flow.ts +0 -38
  320. package/src/sso-config/sso-complete-route.tsx +0 -50
  321. package/src/sso-config/sso-config.ts +0 -59
  322. package/src/sso-config/sso-interfaces.tsx +0 -99
  323. package/src/sso-config/sso-response-helpers.tsx +0 -20
  324. package/src/sso-server.tsx +0 -21
  325. package/src/styles/nexus.animation.css +0 -269
  326. package/src/styles/nexus.core.css +0 -119
  327. package/src/styles/nexus.dialog.css +0 -144
  328. package/src/styles/nexus.icon.css +0 -51
  329. package/src/styles/nexus.input.css +0 -207
  330. package/src/styles/nexus.loader.css +0 -11
  331. package/src/styles/nexus.logic.css +0 -47
  332. package/src/styles/nexus.utility.css +0 -347
@@ -0,0 +1,283 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { iconCalendar, iconX, InlineIcon } from "nexus-icons";
4
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
5
+ import { cx } from "../../Helpers/ClassHelpers.js";
6
+ import { addDays, formatDate, formatDateRange, parseDateRangeText, toDateRange, usesDevanagari } from "../../Helpers/DateHelpers.js";
7
+ import { useDatePreferences } from "../../Helpers/DatePreferences.js";
8
+ import { DEFAULT_FIELD_NAME, validateDateRange } from "../../Helpers/ValidationHelpers.js";
9
+ import { Calendar } from "./Calendar.js";
10
+ import { Field, hasContent } from "./Field.js";
11
+ import { setInputValue, useInputField } from "./InputField.js";
12
+ import { useReadOnlyNotice } from "./ReadOnlyNotice.js";
13
+ const GAP = 4;
14
+ const MARGIN = 8;
15
+ // Two months of the small calendar are about 480px wide; a narrower window gets one month.
16
+ const TWO_MONTHS_MIN_WIDTH = 520;
17
+ const EMPTY = [null, null];
18
+ const sameRange = (a, b) => (a === null || b === null ? a === b : a[0] === b[0] && a[1] === b[1]);
19
+ /**
20
+ * A start and an end in one box: type them as "2026-09-17 – 2026-09-24" in the user's format, or pick them in the
21
+ * calendar that opens under the box, the start first and then the end, with a live preview of the days between.
22
+ * Shows the English (AD) or Nepali (BS) calendar from the user's settings, two months side by side when there is
23
+ * room, and always holds Gregorian ISO dates, which a form sends through hidden inputs (`startName` and `endName`,
24
+ * or both under `name`). Uncontrolled by default, so typing re-renders nothing.
25
+ *
26
+ * @example <DateRangePicker startName="checkIn" endName="checkOut" label="Stay" required min={todayIsoDate()} minDistance={1} />
27
+ */
28
+ export function DateRangePicker(props) {
29
+ const { label, hint, error, design = "standard", size = "md", icon, prefix, months = 2, clearable = true, closeOnSelect = true, fieldName, readOnlyMessage = "Read-only: these dates cannot be changed.", validateOn, value, defaultValue, onValueChange, startName, endName, weekStart, weekendDays, isDateDisabled, showOutsideDays, className, inputClassName, style, required, min, max, minDistance, maxDistance, validate, name, form, placeholder, disabled, readOnly, ref, onChange, onBlur, onFocus, onInvalid, onKeyDown, onClick, ...inputProps } = props;
30
+ const preferences = useDatePreferences();
31
+ const settings = {
32
+ calendar: props.calendar ?? preferences.calendar,
33
+ format: props.format ?? preferences.format,
34
+ script: props.script ?? preferences.script,
35
+ };
36
+ const editable = !disabled && !readOnly;
37
+ const initial = toDateRange(value !== undefined ? value : defaultValue);
38
+ const initialKey = `${initial[0]}|${initial[1]}`;
39
+ const text = (range) => formatDateRange(range, settings);
40
+ const day = (iso) => formatDate(iso, settings);
41
+ const messageName = fieldName ?? (typeof label === "string" ? label : DEFAULT_FIELD_NAME);
42
+ // The range, or `null` while the box holds text that is not a range.
43
+ const valueRef = useRef(initial);
44
+ const editedRef = useRef(false);
45
+ const startRef = useRef(null);
46
+ const endRef = useRef(null);
47
+ const panelRef = useRef(null);
48
+ const focusInPanelRef = useRef(false);
49
+ const focusCalendarRef = useRef(false);
50
+ const [open, setOpen] = useState(false);
51
+ // Re-renders the calendar's selection while it is open; typing with it closed re-renders nothing.
52
+ const [panelRange, setPanelRange] = useState(initial);
53
+ const [panelMonths, setPanelMonths] = useState(months);
54
+ const rules = {
55
+ required,
56
+ min,
57
+ max,
58
+ minDistance,
59
+ maxDistance,
60
+ validate: range => {
61
+ const [start, end] = range;
62
+ // A range cannot include an unavailable day, such as a booked night.
63
+ if (isDateDisabled && start && end) {
64
+ for (let iso = start; iso <= end; iso = addDays(iso, 1))
65
+ if (isDateDisabled(iso))
66
+ return `${messageName} cannot include ${day(iso)}.`;
67
+ }
68
+ return validate?.(range);
69
+ },
70
+ };
71
+ const field = useInputField({
72
+ ...props,
73
+ onChange: event => {
74
+ const input = event.currentTarget;
75
+ const range = parseDateRangeText(input.value, settings);
76
+ const changed = !sameRange(range, valueRef.current);
77
+ editedRef.current = true;
78
+ valueRef.current = range;
79
+ sync(range);
80
+ if (open)
81
+ setPanelRange(range ?? EMPTY);
82
+ onChange?.(event);
83
+ if (changed)
84
+ onValueChange?.(range ?? EMPTY, event);
85
+ },
86
+ }, {
87
+ // Text that is not a range is checked as itself, so the message says what to type.
88
+ check: (input, messageName) => validateDateRange(valueRef.current ?? (input.value.trim() || null), rules, messageName, day),
89
+ checkKeys: [initialKey, required, min, max, minDistance, maxDistance, validate, isDateDisabled, settings.calendar, settings.format, settings.script],
90
+ onReset: input => {
91
+ // Back to the range the field started with, written in the current format.
92
+ editedRef.current = false;
93
+ valueRef.current = initial;
94
+ input.value = text(initial);
95
+ sync(initial);
96
+ },
97
+ });
98
+ // A read-only box has no calendar: a lock, and a note when someone tries to open or change it, say why.
99
+ const readOnlyNotice = useReadOnlyNotice(Boolean(readOnly) && !disabled, field.elementRef, readOnlyMessage, { keys: ["ArrowDown"] });
100
+ /** Writes what depends on the value straight to the DOM: the hidden inputs a form sends. */
101
+ function sync(range) {
102
+ if (startRef.current)
103
+ startRef.current.value = range?.[0] ?? "";
104
+ if (endRef.current)
105
+ endRef.current.value = range?.[1] ?? "";
106
+ }
107
+ // A controlled value that differs from the box replaces its text. So does a default value that arrives after
108
+ // mount (from an API, say), as long as the user has not typed anything yet.
109
+ useLayoutEffect(() => {
110
+ const input = field.elementRef.current;
111
+ if (!input || (value === undefined && editedRef.current) || sameRange(initial, valueRef.current))
112
+ return;
113
+ valueRef.current = initial;
114
+ input.value = text(initial);
115
+ sync(initial);
116
+ setPanelRange(initial);
117
+ }, [initialKey]);
118
+ // New settings (another calendar, format, or script) rewrite the same dates.
119
+ useLayoutEffect(() => {
120
+ const input = field.elementRef.current;
121
+ const range = valueRef.current;
122
+ if (input && range && (range[0] || range[1]))
123
+ input.value = text(range);
124
+ // eslint-disable-next-line react-hooks/exhaustive-deps
125
+ }, [settings.calendar, settings.format, settings.script]);
126
+ // React sets a hidden input's default value again on every render, and for a hidden input that is its value.
127
+ // After each render, before paint, the hidden inputs take the box's dates back.
128
+ useLayoutEffect(() => {
129
+ sync(valueRef.current);
130
+ });
131
+ // The popover is a native one, placed under the box (above it when there is no room); it is shown once the calendar
132
+ // has rendered inside it.
133
+ useLayoutEffect(() => {
134
+ const panel = panelRef.current;
135
+ if (!open || !panel)
136
+ return;
137
+ if (!panel.matches(":popover-open"))
138
+ panel.showPopover();
139
+ place();
140
+ if (focusCalendarRef.current) {
141
+ focusCalendarRef.current = false;
142
+ panel.querySelector('[role="gridcell"][tabindex="0"]')?.focus();
143
+ }
144
+ // The panel is fixed, so it follows the box when the page scrolls or the window changes size.
145
+ let frame = 0;
146
+ const reposition = () => {
147
+ cancelAnimationFrame(frame);
148
+ frame = requestAnimationFrame(place);
149
+ };
150
+ const resize = () => {
151
+ fitMonths();
152
+ reposition();
153
+ };
154
+ window.addEventListener("scroll", reposition, { capture: true, passive: true });
155
+ window.addEventListener("resize", resize);
156
+ return () => {
157
+ cancelAnimationFrame(frame);
158
+ window.removeEventListener("scroll", reposition, { capture: true });
159
+ window.removeEventListener("resize", resize);
160
+ };
161
+ }, [open, panelMonths]);
162
+ useEffect(() => () => panelRef.current?.hidePopover?.(), []);
163
+ function place() {
164
+ const panel = panelRef.current;
165
+ const box = field.elementRef.current?.closest(".nx-field__box");
166
+ if (!panel || !box)
167
+ return;
168
+ const anchor = box.getBoundingClientRect();
169
+ const { width, height } = panel.getBoundingClientRect();
170
+ const below = anchor.bottom + GAP;
171
+ const fitsBelow = below + height <= window.innerHeight - MARGIN;
172
+ const top = fitsBelow || anchor.top - GAP - height < MARGIN ? below : anchor.top - GAP - height;
173
+ const left = Math.max(MARGIN, Math.min(anchor.left, window.innerWidth - width - MARGIN));
174
+ panel.style.top = `${Math.round(top)}px`;
175
+ panel.style.left = `${Math.round(left)}px`;
176
+ }
177
+ /** Two months when the window has room for them, else one. */
178
+ function fitMonths() {
179
+ setPanelMonths(months > 1 && window.innerWidth >= TWO_MONTHS_MIN_WIDTH ? months : 1);
180
+ }
181
+ function openPanel(focusCalendar) {
182
+ if (!editable)
183
+ return;
184
+ // The box is the control: it keeps focus while the calendar is open, so Esc and Enter reach it.
185
+ field.elementRef.current?.focus();
186
+ focusCalendarRef.current = focusCalendar;
187
+ fitMonths();
188
+ setPanelRange(valueRef.current ?? EMPTY);
189
+ setOpen(true);
190
+ }
191
+ function closePanel() {
192
+ panelRef.current?.hidePopover();
193
+ setOpen(false);
194
+ }
195
+ // Whether the calendar holds focus is known only before it hides: hiding it moves focus to the body.
196
+ function onBeforeToggle(event) {
197
+ if (event.newState === "closed")
198
+ focusInPanelRef.current = event.currentTarget.contains(document.activeElement);
199
+ }
200
+ function onToggle(event) {
201
+ if (event.newState !== "closed")
202
+ return;
203
+ setOpen(false);
204
+ // Focus returns to the box when the calendar had it.
205
+ if (focusInPanelRef.current) {
206
+ focusInPanelRef.current = false;
207
+ field.elementRef.current?.focus();
208
+ }
209
+ }
210
+ /** The calendar chose a start (end `null`), an end, or nothing. The box shows it; a complete range is checked and closes the calendar. */
211
+ function pickRange(range) {
212
+ const input = field.elementRef.current;
213
+ if (!input)
214
+ return;
215
+ setPanelRange(range);
216
+ setInputValue(input, text(range));
217
+ if (range[0] && range[1]) {
218
+ field.touch();
219
+ if (closeOnSelect)
220
+ closePanel();
221
+ }
222
+ }
223
+ function clear() {
224
+ const input = field.elementRef.current;
225
+ if (!input)
226
+ return;
227
+ setInputValue(input, "");
228
+ input.focus();
229
+ }
230
+ function handleKeyDown(event) {
231
+ const { key } = event;
232
+ readOnlyNotice.onKeyDown(event);
233
+ if (editable && key === "ArrowDown") {
234
+ event.preventDefault();
235
+ openPanel(true);
236
+ }
237
+ else if (key === "Escape" && open) {
238
+ // The popover closes itself; the page (a dialog, say) does not see this Esc.
239
+ event.stopPropagation();
240
+ }
241
+ else if (clearable && editable && key === "Escape" && event.currentTarget.value) {
242
+ event.preventDefault();
243
+ event.stopPropagation();
244
+ clear();
245
+ }
246
+ else if (key === "Enter" && open) {
247
+ event.preventDefault();
248
+ closePanel();
249
+ }
250
+ else if (key === "Tab" && open) {
251
+ // Tab moves on to the next field, not into the calendar; ArrowDown is the way in.
252
+ closePanel();
253
+ }
254
+ onKeyDown?.(event);
255
+ }
256
+ function handleClick(event) {
257
+ if (!open)
258
+ openPanel(false);
259
+ readOnlyNotice.onClick(event);
260
+ onClick?.(event);
261
+ }
262
+ function handleBlur(event) {
263
+ // Typed text takes the canonical form once it is a range.
264
+ const input = event.currentTarget;
265
+ const range = valueRef.current;
266
+ if (range && (range[0] || range[1]) && input.value !== text(range))
267
+ input.value = text(range);
268
+ // Focus moving anywhere but the calendar (its month and year menus) closes it.
269
+ if (open && !(event.relatedTarget instanceof Node && panelRef.current?.contains(event.relatedTarget)))
270
+ closePanel();
271
+ readOnlyNotice.hide();
272
+ field.controlProps.onBlur(event);
273
+ }
274
+ const showClear = clearable && editable;
275
+ const startField = startName ?? name;
276
+ const endField = endName ?? name;
277
+ return (_jsxs(_Fragment, { children: [_jsxs(Field, { controlId: field.controlId, messageId: field.messageId, label: label, required: required, design: design, size: size, hint: hint, error: field.error, icon: icon, prefix: prefix, actions: _jsxs(_Fragment, { children: [showClear && (_jsx("button", { type: "button", className: "nx-field__action nx-field__action--clear", tabIndex: -1, "aria-label": "Clear", title: "Clear", onMouseDown: event => event.preventDefault(), onClick: clear, children: _jsx(InlineIcon, { icon: iconX }) })), readOnlyNotice.lock, !readOnly && (_jsx("button", { type: "button", className: "nx-field__action nx-field__action--calendar", tabIndex: -1, "aria-label": "Open calendar", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": open ? `${field.controlId}-calendar` : undefined, title: "Open calendar", disabled: disabled, onMouseDown: event => event.preventDefault(), onClick: () => (open ? closePanel() : openPanel(false)), children: _jsx(InlineIcon, { icon: iconCalendar }) }))] }), disabled: disabled, readOnly: readOnly, raiseLabel: Boolean(placeholder) || hasContent(prefix), className: cx("nx-field--date", "nx-field--date-range", className), style: style, children: [_jsx("input", { autoComplete: "off", spellCheck: false, ...inputProps, ...field.controlProps, type: "text", name: undefined, form: form, lang: usesDevanagari(settings.calendar, settings.script) ? "ne" : undefined, defaultValue: text(initial), className: cx("nx-field__control", "nx-field__control--date", inputClassName), placeholder: placeholder || " ", disabled: disabled, readOnly: readOnly, onBlur: handleBlur, onFocus: onFocus, onKeyDown: handleKeyDown, onClick: handleClick }), startField && _jsx("input", { ref: startRef, type: "hidden", name: startField, form: form, disabled: disabled, defaultValue: initial[0] ?? "" }), endField && _jsx("input", { ref: endRef, type: "hidden", name: endField, form: form, disabled: disabled, defaultValue: initial[1] ?? "" })] }), readOnlyNotice.notice, !readOnly && (_jsx("div", { ref: panelRef, id: `${field.controlId}-calendar`, popover: "auto", role: "dialog", "aria-label": "Calendar", className: "nx-popover nx-date-popover", onBeforeToggle: onBeforeToggle, onToggle: onToggle,
278
+ // The box keeps focus while days and buttons are clicked; the month and year menus need focus to open.
279
+ onMouseDown: event => {
280
+ if (!event.target.closest("select"))
281
+ event.preventDefault();
282
+ }, children: open && (_jsx(Calendar, { size: "sm", mode: "range", months: panelMonths, calendar: settings.calendar, script: settings.script, range: panelRange, onRangeChange: pickRange, min: min, max: max, isDateDisabled: isDateDisabled, weekStart: weekStart, weekendDays: weekendDays, showOutsideDays: showOutsideDays, "aria-label": "Calendar" })) }))] }));
283
+ }
@@ -0,0 +1,75 @@
1
+ import { type ChangeEvent, type ComponentPropsWithRef, type ReactNode } from "react";
2
+ import type { CalendarType, DateScript, DateTimeInput, DateTimeRules, TimeInput } from "../../Interfaces/DateInterfaces.ts";
3
+ import type { InputDesign, ValidateOn } from "../../Interfaces/InputInterfaces.ts";
4
+ import type { Size } from "../../Interfaces/TypeInterfaces.ts";
5
+ import { type CalendarProps } from "./Calendar.tsx";
6
+ import { type TimePanelView } from "./TimePanel.tsx";
7
+ type NativeInputProps = Omit<ComponentPropsWithRef<"input">, "type" | "size" | "value" | "defaultValue" | "min" | "max" | "step" | "prefix" | "pattern" | "minLength" | "maxLength" | "children" | keyof DateTimeRules>;
8
+ export interface DateTimePickerProps extends NativeInputProps, DateTimeRules, Pick<CalendarProps, "weekStart" | "weekendDays" | "showOutsideDays"> {
9
+ label?: ReactNode;
10
+ /** Help text under the box. */
11
+ hint?: ReactNode;
12
+ /** An error from outside, such as a server message. Shown before the field's own message. */
13
+ error?: string | null;
14
+ /** Default `standard`. */
15
+ design?: InputDesign;
16
+ /** Default `md`. */
17
+ size?: Size;
18
+ /** Decorative icon at the start. The calendar and clock button is always at the end. */
19
+ icon?: ReactNode;
20
+ /** Text before the value inside the box. */
21
+ prefix?: ReactNode;
22
+ /** The calendar the date is shown and picked in: `ad` or `bs`. Default: the user's setting. */
23
+ calendar?: CalendarType;
24
+ /** How the date is written: `YYYY-MM-DD`, `DD/MM/YYYY`, `MMM D, YYYY`, ... Default: the user's setting. */
25
+ format?: string;
26
+ /** How the time is written: `hh:mm A` (02:30 PM), `HH:mm` (14:30), ... Seconds are added when `step` needs them. Default: the user's setting. */
27
+ timeFormat?: string;
28
+ /** Digits and names of Nepali dates, and the digits of the time with them. Default: the user's setting. */
29
+ script?: DateScript;
30
+ /**
31
+ * IANA id of the time zone the value is shown and picked in, such as "Asia/Kathmandu" or "UTC". Default: the
32
+ * browser's, so every user sees their own local time. The value is the same UTC moment whatever the zone.
33
+ */
34
+ timeZone?: string;
35
+ /** Writes the zone's city after the value in the box, e.g. "Kathmandu". Default: on when `timeZone` is given. */
36
+ showTimeZone?: boolean;
37
+ /** The time panel: `columns` (default) of hours, minutes, and AM/PM, or `list`, a slot every `step`, for bookings. */
38
+ view?: TimePanelView;
39
+ /** The time a day takes when it is picked, or typed, before any time: "12:00" for a check-in. Default: `minTime`, or midnight. */
40
+ defaultTime?: TimeInput;
41
+ /** Days that cannot be picked, such as fully booked days. Receives the ISO date where the user is. */
42
+ isDateDisabled?: (date: string) => boolean;
43
+ /** Times that cannot be picked on a day, such as booked slots. Receives the ISO time ("14:30") and date where the user is. */
44
+ isTimeDisabled?: (time: string, date: string) => boolean;
45
+ /** Shows a clear button while there is a value. Default true. */
46
+ clearable?: boolean;
47
+ /** What a read-only field says when someone tries to change it. Default "Read-only: this date and time cannot be changed." */
48
+ readOnlyMessage?: string;
49
+ /** Name used in messages, e.g. "Pickup is required." Default: the label, when it is text. */
50
+ fieldName?: string;
51
+ /** When the field shows its own message. Default `blur`; submitting a form always shows it. */
52
+ validateOn?: ValidateOn;
53
+ /**
54
+ * The moment, or `null` for empty. Held and sent as a UTC ISO string, "2026-09-17T08:45:00.000Z". An ISO date-time
55
+ * with a zone, one without a zone (read as UTC), a `Date`, or milliseconds are accepted; see `DateTimeInput`.
56
+ */
57
+ value?: DateTimeInput;
58
+ defaultValue?: DateTimeInput;
59
+ /** After each change: the UTC ISO value, or `null` when the box is empty or holds text that is not a date and time. */
60
+ onValueChange?: (value: string | null, event: ChangeEvent<HTMLInputElement>) => void;
61
+ /** Class of the outer field. `inputClassName` goes on the input. */
62
+ className?: string;
63
+ inputClassName?: string;
64
+ }
65
+ /**
66
+ * A date and time input for moments, such as a pickup, a deadline, or a reminder: type a date and time, or pick a day
67
+ * and a time from the panel that opens under the box. People see and pick their own local time, in their date and time
68
+ * formats (English or Nepali calendar, 12- or 24-hour clock); the value is always the UTC moment, which a form sends
69
+ * through a hidden input with the field's `name`, so no time zone ever moves it. A value is replaced only when the
70
+ * user changes what it shows: seconds and milliseconds the box does not show stay as they arrived.
71
+ *
72
+ * @example <DateTimePicker name="pickupAt" label="Pickup" required min={new Date()} step={900} />
73
+ */
74
+ export declare function DateTimePicker(props: DateTimePickerProps): import("react").JSX.Element;
75
+ export {};