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,239 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { iconClock, iconX, InlineIcon } from "nexus-icons";
4
+ import { useLayoutEffect, useRef, useState } from "react";
5
+ import { cx } from "../../Helpers/ClassHelpers.js";
6
+ import { usesDevanagari } from "../../Helpers/DateHelpers.js";
7
+ import { useDatePreferences } from "../../Helpers/DatePreferences.js";
8
+ import { followAnchor, isPopoverOpen, placeUnderAnchor } from "../../Helpers/PopoverHelpers.js";
9
+ import { formatTime, normalizeTimeStep, parseTimeText, timeFormatWithSeconds, toIsoTime } from "../../Helpers/TimeHelpers.js";
10
+ import { DEFAULT_FIELD_NAME, validateTime } from "../../Helpers/ValidationHelpers.js";
11
+ import { Field, hasContent } from "./Field.js";
12
+ import { setInputValue, useInputField } from "./InputField.js";
13
+ import { useReadOnlyNotice } from "./ReadOnlyNotice.js";
14
+ import { TimePanel } from "./TimePanel.js";
15
+ /**
16
+ * A time input: type a time on either clock ("2:30 pm", "1430"), or pick one from the panel that opens under the box.
17
+ * Written in the user's time format, 12- or 24-hour, and always held as an ISO time with no date and no zone, which a
18
+ * form sends through a hidden input with the field's `name`. Uncontrolled by default, so typing re-renders nothing.
19
+ *
20
+ * @example <TimePicker name="arrival" label="Arrival" min="12:00" max="22:00" step={1800} view="list" />
21
+ */
22
+ export function TimePicker(props) {
23
+ const { label, hint, error, design = "standard", size = "md", icon, prefix, view = "columns", clearable = true, fieldName, readOnlyMessage = "Read-only: this time cannot be changed.", validateOn, value, defaultValue, onValueChange, isTimeDisabled, className, inputClassName, style, required, min, max, step, validate, name, form, placeholder, disabled, readOnly, ref, onChange, onBlur, onFocus, onInvalid, onKeyDown, onClick, ...inputProps } = props;
24
+ const preferences = useDatePreferences();
25
+ const script = props.script ?? (usesDevanagari(preferences.calendar, preferences.script) ? "devanagari" : "latin");
26
+ const seconds = normalizeTimeStep(step) % 60 !== 0;
27
+ const format = timeFormatWithSeconds(props.format ?? preferences.timeFormat, seconds);
28
+ const editable = !disabled && !readOnly;
29
+ const initial = toIsoTime(value !== undefined ? value : defaultValue, seconds);
30
+ const text = (iso) => formatTime(iso, { format, script });
31
+ const messageName = fieldName ?? (typeof label === "string" ? label : DEFAULT_FIELD_NAME);
32
+ const valueRef = useRef(initial);
33
+ const editedRef = useRef(false);
34
+ const hiddenRef = useRef(null);
35
+ const panelRef = useRef(null);
36
+ const focusPanelRef = useRef(false);
37
+ const [open, setOpen] = useState(false);
38
+ // Re-renders the panel's selection while it is open; typing with it closed re-renders nothing.
39
+ const [panelValue, setPanelValue] = useState(initial);
40
+ const rules = {
41
+ required,
42
+ min,
43
+ max,
44
+ step,
45
+ validate: iso => (iso && isTimeDisabled?.(iso) ? `${messageName} cannot be ${text(iso)}.` : validate?.(iso)),
46
+ };
47
+ const field = useInputField({
48
+ ...props,
49
+ onChange: event => {
50
+ const input = event.currentTarget;
51
+ const iso = input.value.trim() ? parseTimeText(input.value, { seconds }) : null;
52
+ const changed = iso !== valueRef.current;
53
+ editedRef.current = true;
54
+ valueRef.current = iso;
55
+ sync(iso);
56
+ if (open)
57
+ setPanelValue(iso);
58
+ onChange?.(event);
59
+ if (changed)
60
+ onValueChange?.(iso, event);
61
+ },
62
+ }, {
63
+ // Text that is not a time is checked as itself, so the message says what to type.
64
+ check: (input, messageName) => validateTime(valueRef.current ?? (input.value.trim() ? input.value : null), rules, messageName, text),
65
+ checkKeys: [value, required, min, max, step, validate, isTimeDisabled, format, script],
66
+ onReset: input => {
67
+ // Back to the time the field started with, written in the current format.
68
+ editedRef.current = false;
69
+ valueRef.current = initial;
70
+ input.value = text(initial);
71
+ sync(initial);
72
+ },
73
+ });
74
+ // A read-only box has no panel: a lock, and a note when someone tries to open or change it, say why.
75
+ const readOnlyNotice = useReadOnlyNotice(Boolean(readOnly) && !disabled, field.elementRef, readOnlyMessage, { keys: ["ArrowDown"] });
76
+ /** Writes what depends on the value straight to the DOM: the hidden input a form sends. */
77
+ function sync(iso) {
78
+ if (hiddenRef.current)
79
+ hiddenRef.current.value = iso ?? "";
80
+ }
81
+ // A controlled value that differs from the box replaces its text. So does a default value that arrives after
82
+ // mount (from an API, say), as long as the user has not typed anything yet.
83
+ useLayoutEffect(() => {
84
+ const input = field.elementRef.current;
85
+ if (!input || (value === undefined && editedRef.current) || initial === valueRef.current)
86
+ return;
87
+ valueRef.current = initial;
88
+ input.value = text(initial);
89
+ sync(initial);
90
+ setPanelValue(initial);
91
+ }, [initial]);
92
+ // A new format or script rewrites the same time.
93
+ useLayoutEffect(() => {
94
+ const input = field.elementRef.current;
95
+ if (input && valueRef.current)
96
+ input.value = text(valueRef.current);
97
+ // eslint-disable-next-line react-hooks/exhaustive-deps
98
+ }, [format, script]);
99
+ // React sets a hidden input's default value again on every render, and for a hidden input that is its value.
100
+ // After each render, before paint, the hidden input takes the box's time back.
101
+ useLayoutEffect(() => {
102
+ sync(valueRef.current);
103
+ });
104
+ // The panel is a manual popover under the box (above it when there is no room), shown once its content has rendered.
105
+ // It closes only through this component (Esc, Enter, Done, a pick in the list, focus or a press elsewhere), so the
106
+ // state always matches the screen: a click right after Esc opens it again, and a click on the box keeps it open.
107
+ useLayoutEffect(() => {
108
+ const panel = panelRef.current;
109
+ const box = field.elementRef.current?.closest(".nx-field__box");
110
+ if (!open || !panel || !box)
111
+ return;
112
+ if (!isPopoverOpen(panel))
113
+ panel.showPopover();
114
+ const place = () => placeUnderAnchor(panel, box.getBoundingClientRect());
115
+ place();
116
+ const stopFollowing = followAnchor(place);
117
+ const onPointerDown = (event) => {
118
+ const target = event.target;
119
+ if (!panel.contains(target) && !box.contains(target))
120
+ closePanel();
121
+ };
122
+ document.addEventListener("pointerdown", onPointerDown, true);
123
+ return () => {
124
+ stopFollowing();
125
+ document.removeEventListener("pointerdown", onPointerDown, true);
126
+ if (isPopoverOpen(panel))
127
+ panel.hidePopover();
128
+ };
129
+ }, [open]);
130
+ function openPanel(focusPanel) {
131
+ if (!editable)
132
+ return;
133
+ // The box is the control: it keeps focus while the panel is open, so Esc and Enter reach it.
134
+ field.elementRef.current?.focus();
135
+ focusPanelRef.current = focusPanel;
136
+ // Shown before its content renders, so the panel can scroll its columns and take focus as it mounts. Nothing is
137
+ // painted in between: the render that fills it runs before the frame.
138
+ const panel = panelRef.current;
139
+ if (panel && !isPopoverOpen(panel))
140
+ panel.showPopover();
141
+ setPanelValue(valueRef.current);
142
+ setOpen(true);
143
+ }
144
+ /** Closes the panel. With `returnFocus`, focus that was inside the panel goes back to the box (Esc, Enter, Done). */
145
+ function closePanel(returnFocus = false) {
146
+ const panel = panelRef.current;
147
+ const focusInPanel = Boolean(panel?.contains(document.activeElement));
148
+ // Blur, a press elsewhere, and Done may all close it; hiding happens once.
149
+ if (isPopoverOpen(panel))
150
+ panel.hidePopover();
151
+ setOpen(false);
152
+ if (returnFocus && focusInPanel)
153
+ field.elementRef.current?.focus();
154
+ }
155
+ function select(iso) {
156
+ const input = field.elementRef.current;
157
+ if (!input)
158
+ return;
159
+ setInputValue(input, text(iso));
160
+ field.touch();
161
+ }
162
+ function clear() {
163
+ const input = field.elementRef.current;
164
+ if (!input)
165
+ return;
166
+ setInputValue(input, "");
167
+ input.focus();
168
+ }
169
+ function handleKeyDown(event) {
170
+ const { key } = event;
171
+ readOnlyNotice.onKeyDown(event);
172
+ if (editable && key === "ArrowDown") {
173
+ event.preventDefault();
174
+ if (open)
175
+ panelRef.current?.querySelector('[role="option"][tabindex="0"]')?.focus({ preventScroll: true });
176
+ else
177
+ openPanel(true);
178
+ }
179
+ else if (key === "Escape" && open) {
180
+ // Closes the panel only: the page (a dialog, say) does not see this Esc.
181
+ event.preventDefault();
182
+ event.stopPropagation();
183
+ closePanel();
184
+ }
185
+ else if (clearable && editable && key === "Escape" && event.currentTarget.value) {
186
+ event.preventDefault();
187
+ event.stopPropagation();
188
+ clear();
189
+ }
190
+ else if (key === "Enter" && open) {
191
+ event.preventDefault();
192
+ closePanel();
193
+ }
194
+ else if (key === "Tab" && open) {
195
+ // Tab moves on to the next field, not into the panel; ↓ is the way in.
196
+ closePanel();
197
+ }
198
+ onKeyDown?.(event);
199
+ }
200
+ function handleClick(event) {
201
+ if (!open)
202
+ openPanel(false);
203
+ readOnlyNotice.onClick(event);
204
+ onClick?.(event);
205
+ }
206
+ function handleBlur(event) {
207
+ // Typed text takes the canonical form once it is a time.
208
+ const input = event.currentTarget;
209
+ if (valueRef.current && input.value !== text(valueRef.current))
210
+ input.value = text(valueRef.current);
211
+ // Focus moving anywhere but the panel closes it.
212
+ if (open && !(event.relatedTarget instanceof Node && panelRef.current?.contains(event.relatedTarget)))
213
+ closePanel();
214
+ readOnlyNotice.hide();
215
+ field.controlProps.onBlur(event);
216
+ }
217
+ // Focus leaving the panel for anything but the box (Tab past Done, a click elsewhere) closes it.
218
+ function handlePanelBlur(event) {
219
+ const next = event.relatedTarget;
220
+ if (next instanceof Node && (event.currentTarget.contains(next) || next === field.elementRef.current))
221
+ return;
222
+ closePanel();
223
+ }
224
+ function handlePanelKeyDown(event) {
225
+ if (event.key !== "Escape")
226
+ return;
227
+ event.preventDefault();
228
+ event.stopPropagation();
229
+ closePanel(true);
230
+ }
231
+ const showClear = clearable && editable;
232
+ 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--clock", tabIndex: -1, "aria-label": "Choose a time", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": open ? `${field.controlId}-times` : undefined, title: "Choose a time", disabled: disabled, onMouseDown: event => event.preventDefault(), onClick: () => (open ? closePanel() : openPanel(false)), children: _jsx(InlineIcon, { icon: iconClock }) }))] }), disabled: disabled, readOnly: readOnly, raiseLabel: Boolean(placeholder) || hasContent(prefix), className: cx("nx-field--time", className), style: style, children: [_jsx("input", { autoComplete: "off", spellCheck: false, ...inputProps, ...field.controlProps, type: "text", name: undefined, form: form, lang: script === "devanagari" ? "ne" : undefined, defaultValue: text(initial), className: cx("nx-field__control", "nx-field__control--time", inputClassName), placeholder: placeholder || " ", disabled: disabled, readOnly: readOnly, onBlur: handleBlur, onFocus: onFocus, onKeyDown: handleKeyDown, onClick: handleClick }), name && _jsx("input", { ref: hiddenRef, type: "hidden", name: name, form: form, disabled: disabled, defaultValue: initial ?? "" })] }), readOnlyNotice.notice, !readOnly && (_jsx("div", { ref: panelRef, id: `${field.controlId}-times`, popover: "manual", role: "dialog", "aria-label": "Choose a time", className: cx("nx-popover", "nx-time-popover"), onKeyDown: handlePanelKeyDown, onBlur: handlePanelBlur,
233
+ // The box keeps focus while items, buttons, and the space between them are clicked. A press on a column
234
+ // itself is left alone, so its scroll bar can be dragged; the column takes focus, inside the panel.
235
+ onMouseDown: event => {
236
+ if (!event.target.matches("[data-column]"))
237
+ event.preventDefault();
238
+ }, children: open && (_jsx(TimePanel, { view: view, value: panelValue, onValueChange: select, onDone: () => closePanel(true), format: format, script: script, seconds: seconds, step: step, min: min, max: max, isTimeDisabled: isTimeDisabled, autoFocus: focusPanelRef.current })) }))] }));
239
+ }
@@ -0,0 +1,160 @@
1
+ import { type CSSProperties, type ReactNode, type Ref } from "react";
2
+ import { type TreeItem, type TreeValue, type TreeValueMode } from "../../Helpers/TreeStore.ts";
3
+ import type { Size } from "../../Interfaces/TypeInterfaces.ts";
4
+ export type TreeAction = "create" | "update" | "delete";
5
+ export interface TreeCreateRequest<TItem extends TreeItem = TreeItem> {
6
+ /** The item the new one goes under, or `null` at the top level. */
7
+ parent: TItem | null;
8
+ parentValue: TreeValue | null;
9
+ /** The name typed, trimmed. */
10
+ label: string;
11
+ /** What the tree adds when `onCreate` returns nothing: a generated value, the parent's value, and the label. */
12
+ item: TItem;
13
+ }
14
+ export interface TreeUpdateRequest<TItem extends TreeItem = TreeItem> {
15
+ item: TItem;
16
+ value: TreeValue;
17
+ /** The new name, trimmed. */
18
+ label: string;
19
+ }
20
+ export interface TreeDeleteRequest<TItem extends TreeItem = TreeItem> {
21
+ item: TItem;
22
+ value: TreeValue;
23
+ /** The item and everything under it, in tree order. */
24
+ items: TItem[];
25
+ }
26
+ /** What a `ref` on `TreeView` can do. */
27
+ export interface TreeViewHandle<TItem extends TreeItem = TreeItem> {
28
+ /** Expands every item, or the first `levels` levels. */
29
+ expandAll: (levels?: number) => void;
30
+ collapseAll: () => void;
31
+ /** Expands an item and its parents. */
32
+ expand: (value: TreeValue) => void;
33
+ collapse: (value: TreeValue) => void;
34
+ /** Expands the parents of an item, scrolls to it, and focuses it unless `focus` is false. */
35
+ reveal: (value: TreeValue, focus?: boolean) => void;
36
+ getValue: () => TreeValue[];
37
+ /** Checks exactly these values, locked items included. For a tree without `value`. */
38
+ setValue: (values: readonly TreeValue[]) => void;
39
+ /** Checks or unchecks every item that is not locked. */
40
+ checkAll: (checked: boolean) => void;
41
+ /** Every item in tree order, with the changes made in the tree. */
42
+ getItems: () => TItem[];
43
+ /** Opens the editor for a new item under `parentValue`, or at the top level for `null`. */
44
+ startCreate: (parentValue: TreeValue | null) => void;
45
+ startRename: (value: TreeValue) => void;
46
+ /** Asks (unless `confirmDelete` is off), then deletes an item. Resolves with whether it was deleted. */
47
+ remove: (value: TreeValue) => Promise<boolean>;
48
+ /** Focuses the focused row, or the first. */
49
+ focus: () => void;
50
+ }
51
+ export interface TreeViewProps<TItem extends TreeItem = TreeItem> {
52
+ /**
53
+ * The items, flat: each names its parent through `parentKey`, and siblings keep this order. Keep the array stable
54
+ * (state, a constant, or `useMemo`): a different array, or one with different items, builds the tree again.
55
+ */
56
+ items: readonly TItem[];
57
+ /** The item field that holds its value. Default `id`. */
58
+ valueKey?: string;
59
+ /** The item field that holds its parent's value; empty for a top-level item. Default `parentId`. */
60
+ parentKey?: string;
61
+ /** The item field shown as its name. Default `label`. */
62
+ labelKey?: string;
63
+ /** Muted text after the label. Default `description`. */
64
+ descriptionKey?: string;
65
+ /** A Tabler icon name, or an element, before the label. Default `icon`. */
66
+ iconKey?: string;
67
+ /**
68
+ * Items the user has no permission to change: they cannot be checked, unchecked, renamed, or deleted, and everything
69
+ * under them is locked too. A lock shows at the end of the row, and a try shows `lockedMessage`. Default:
70
+ * `disabled: true` or `isDisabled: true`.
71
+ */
72
+ isItemDisabled?: (item: TItem) => boolean;
73
+ /** What a locked item says when someone tries to change it. Default "You do not have permission to change this item." */
74
+ lockedMessage?: string;
75
+ label?: ReactNode;
76
+ /** Help text under the tree. */
77
+ hint?: ReactNode;
78
+ /** An error from outside, such as a server message. */
79
+ error?: string | null;
80
+ /** Default `md`. */
81
+ size?: Size;
82
+ /** A checkbox on every row. */
83
+ checkable?: boolean;
84
+ /** With `checkable`: checking a parent checks everything under it, and a parent shows the state of its items. Default true. */
85
+ cascade?: boolean;
86
+ /** Which checked items the value holds. Default `leaves`, such as the action ids of a permission tree. See `TreeValueMode`. */
87
+ valueMode?: TreeValueMode;
88
+ /** The checked values. With `value`, the tree is controlled; pair it with `onValueChange`. */
89
+ value?: readonly TreeValue[];
90
+ /** The checked values at the start. Without it, items with `checked: true` or `isChecked: true` start checked. */
91
+ defaultValue?: readonly TreeValue[];
92
+ /** After each check or uncheck: the values and their items, in tree order. */
93
+ onValueChange?: (values: TreeValue[], items: TItem[]) => void;
94
+ /** A form gets the value as hidden inputs named `name`, one per value. Leave it out for very large values and read them from `onValueChange`. */
95
+ name?: string;
96
+ form?: string;
97
+ /** With `checkable` and `cascade`: a parent shows how many of its items are checked, as "3/5". Default true. */
98
+ counts?: boolean;
99
+ /** What is expanded at the start: `"all"`, a number of levels, or the values of items to open. */
100
+ defaultExpanded?: "all" | number | readonly TreeValue[];
101
+ /** Items can be added: a + on each row adds under it, and Add in the toolbar adds at the top level. */
102
+ creatable?: boolean;
103
+ /** Items can be renamed: a pencil on each row, F2, or the context menu. */
104
+ editable?: boolean;
105
+ /** Items can be deleted, with everything under them: a bin on each row, Delete, or the context menu. */
106
+ deletable?: boolean;
107
+ /** Narrows the actions per item, e.g. from the user's permissions. `item` is `null` for adding at the top level. */
108
+ canChange?: (action: TreeAction, item: TItem | null) => boolean;
109
+ /**
110
+ * Saves a new item, e.g. through an API. Return the saved item (with the server's id), or nothing to keep
111
+ * `request.item`. A thrown error keeps the editor open with the name typed and shows the message under the tree.
112
+ */
113
+ onCreate?: (request: TreeCreateRequest<TItem>) => TItem | void | Promise<TItem | void>;
114
+ /** Saves a new name. Return the saved item, or nothing to keep the item with the new label. A thrown error keeps the editor open. */
115
+ onUpdate?: (request: TreeUpdateRequest<TItem>) => TItem | void | Promise<TItem | void>;
116
+ /** Deletes an item and everything under it. A thrown error keeps the items and shows the message. */
117
+ onDelete?: (request: TreeDeleteRequest<TItem>) => void | Promise<void>;
118
+ /** After an item is added, renamed, or deleted: every item in tree order. Passing this array back as `items` does not rebuild the tree. */
119
+ onItemsChange?: (items: TItem[]) => void;
120
+ /** Asks before deleting. Default true; needs `<PopupHost />` on the page. */
121
+ confirmDelete?: boolean;
122
+ /** The longest name the editor takes. Default 100. */
123
+ maxLabelLength?: number;
124
+ /** A click on a row without a checkbox, or Enter on it. Without it, a click expands or collapses a parent. */
125
+ onItemClick?: (item: TItem) => void;
126
+ /** Items are on their way: placeholder rows while the tree is empty, and a spinner in the toolbar. */
127
+ loading?: boolean;
128
+ /** Shown when there are no items. Default "No items". */
129
+ emptyMessage?: ReactNode;
130
+ /** The bar above the rows: select all, counts, expand all, collapse all, and Add. Default true. */
131
+ toolbar?: boolean;
132
+ /** A fixed height for the rows' area, e.g. 480 or "60vh". */
133
+ height?: number | string;
134
+ /** The tallest the rows' area grows before it scrolls. Default 420. */
135
+ maxHeight?: number | string;
136
+ /** Can be browsed, expanded, and focused, but not changed. A lock follows the label, and a try shows a note. */
137
+ readOnly?: boolean;
138
+ /** What a read-only tree says when someone tries to change it. Default "Read-only: this tree cannot be changed." */
139
+ readOnlyMessage?: string;
140
+ disabled?: boolean;
141
+ id?: string;
142
+ className?: string;
143
+ style?: CSSProperties;
144
+ /** Name for screen readers when there is no `label`. */
145
+ "aria-label"?: string;
146
+ ref?: Ref<TreeViewHandle<TItem>>;
147
+ }
148
+ /**
149
+ * A tree of items from a flat list: a permission tree (controller > menu > action) with checkboxes that cascade and
150
+ * items the user may not change, or a tree of categories to add, rename, and delete. Only the rows in view are
151
+ * rendered, so collapsed items never reach the page, and 100,000 expanded items scroll like 40. Expanding and
152
+ * collapsing slide open and closed (at once with reduced motion).
153
+ *
154
+ * Keys: arrows move and expand, Home and End jump, letters find a row, Space checks, Enter opens, `*` expands the
155
+ * siblings, F2 renames, Delete deletes, Insert adds under the focused row, and Shift+F10 opens the actions menu.
156
+ *
157
+ * @example
158
+ * <TreeView label="Permissions" items={permissions} checkable name="actionIds" defaultExpanded={1} isItemDisabled={item => !item.canAssign} />
159
+ */
160
+ export declare function TreeView<TItem extends TreeItem = TreeItem>(props: TreeViewProps<TItem>): import("react").JSX.Element;