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,530 @@
1
+ import { errorMessage, isAbortError } from "./ApiResponses.js";
2
+ import { DEFAULT_MAX_SELECTION, DEFAULT_PAGE_SIZE, MIN_COLUMN_WIDTH, clampPage, moveColumnKey, nextSort, queryRows, readTablePage, rowKeyText } from "./TableHelpers.js";
3
+ /** How long a changed or added row stays highlighted. */
4
+ export const TABLE_FLASH_MS = 1600;
5
+ const EMPTY_MAP = new Map();
6
+ const EMPTY_SET = new Set();
7
+ const EMPTY_LIST = [];
8
+ const NO_WIDTHS = {};
9
+ const NO_PINS = {};
10
+ function initialState(pageSize) {
11
+ return {
12
+ status: "loading",
13
+ refreshing: false,
14
+ error: null,
15
+ rows: [],
16
+ offset: 0,
17
+ total: 0,
18
+ matches: 0,
19
+ query: { search: "", sort: null, page: 1, pageSize },
20
+ selected: EMPTY_MAP,
21
+ busy: EMPTY_SET,
22
+ flashed: EMPTY_SET,
23
+ hidden: EMPTY_SET,
24
+ order: EMPTY_LIST,
25
+ widths: NO_WIDTHS,
26
+ pinned: NO_PINS,
27
+ };
28
+ }
29
+ export class TableStore {
30
+ options = { columns: [], rowKey: "id", paging: "client" };
31
+ state;
32
+ listeners = new Set();
33
+ /** Every row, when the table has them all. */
34
+ all = [];
35
+ /** Whether `all` holds rows given by the page (not loaded). */
36
+ given = null;
37
+ texts = new WeakMap();
38
+ controller = null;
39
+ seq = 0;
40
+ flashTimer;
41
+ reloadTimer;
42
+ /** A load was stopped by `dispose`. */
43
+ interrupted = false;
44
+ constructor(pageSize = DEFAULT_PAGE_SIZE) {
45
+ this.state = initialState(pageSize);
46
+ }
47
+ /* Reading */
48
+ getState = () => this.state;
49
+ subscribe = (listener) => {
50
+ this.listeners.add(listener);
51
+ return () => {
52
+ this.listeners.delete(listener);
53
+ };
54
+ };
55
+ get paging() {
56
+ return this.options.paging;
57
+ }
58
+ get columns() {
59
+ return this.options.columns;
60
+ }
61
+ /** A row's key as text. */
62
+ keyOf(row) {
63
+ return rowKeyText(row, this.options.rowKey);
64
+ }
65
+ /** Every row the table has: all of them in a client table, the page's in a server table. */
66
+ getRows() {
67
+ return this.options.paging === "server" ? [...this.state.rows] : [...this.all];
68
+ }
69
+ /** The row with this key, if the table has it. */
70
+ getRow(key) {
71
+ const text = String(key);
72
+ const list = this.options.paging === "server" ? this.state.rows : this.all;
73
+ return list.find(row => this.keyOf(row) === text) ?? this.state.selected.get(text);
74
+ }
75
+ getSelected() {
76
+ return [...this.state.selected.values()];
77
+ }
78
+ /**
79
+ * Every row the table would show for its query, in order: the whole searched and sorted list for a client table, the
80
+ * page a server sent for a server table. An export and a print write these.
81
+ */
82
+ getViewRows() {
83
+ if (this.options.paging === "server")
84
+ return [...this.state.rows];
85
+ return queryRows(this.all, this.options.columns, { ...this.state.query, page: 1, pageSize: Number.MAX_SAFE_INTEGER }, this.texts).rows;
86
+ }
87
+ isSelected(row) {
88
+ return this.state.selected.has(this.keyOf(row));
89
+ }
90
+ /* Setting up */
91
+ /** Takes the component's props. Tells nobody: the component calls it while rendering. */
92
+ configure(options) {
93
+ if (options.columns !== this.options.columns)
94
+ this.texts = new WeakMap();
95
+ this.options = options;
96
+ }
97
+ set(changes) {
98
+ const previous = this.state;
99
+ this.state = { ...previous, ...changes };
100
+ for (const listener of this.listeners)
101
+ listener();
102
+ if (changes.selected && changes.selected !== previous.selected)
103
+ this.options.onSelectionChange?.(this.getSelected());
104
+ }
105
+ /** Puts back what was saved on this device (page size, sort, columns), before the first load. Tells nobody. */
106
+ restore(saved) {
107
+ const query = { ...this.state.query };
108
+ if (saved.pageSize && saved.pageSize > 0)
109
+ query.pageSize = saved.pageSize;
110
+ if (saved.sort !== undefined)
111
+ query.sort = saved.sort;
112
+ this.state = {
113
+ ...this.state,
114
+ query,
115
+ hidden: saved.hidden ? new Set(saved.hidden) : this.state.hidden,
116
+ order: saved.order ?? this.state.order,
117
+ widths: saved.widths ?? this.state.widths,
118
+ pinned: saved.pinned ?? this.state.pinned,
119
+ };
120
+ }
121
+ /* Rows given by the page */
122
+ /** Shows these rows: every row there is. The table searches, sorts, and pages them. */
123
+ setRows(rows) {
124
+ if (rows === this.given)
125
+ return;
126
+ this.given = rows;
127
+ this.all = [...rows];
128
+ this.dropMissingSelection();
129
+ this.view({ status: "ready", error: null, refreshing: false });
130
+ }
131
+ /* Loading */
132
+ /**
133
+ * Loads the rows again: every row for a client table, the page for a server table. A newer load stops an older one,
134
+ * so the table always shows the answer to its latest query. Resolves when the rows are in (or the load failed).
135
+ */
136
+ async reload({ quiet, reset = false } = {}) {
137
+ const load = this.options.load;
138
+ if (!load) {
139
+ if (this.given)
140
+ this.view();
141
+ return;
142
+ }
143
+ clearTimeout(this.reloadTimer);
144
+ this.interrupted = false;
145
+ this.controller?.abort();
146
+ const controller = new AbortController();
147
+ this.controller = controller;
148
+ const seq = ++this.seq;
149
+ if (reset) {
150
+ this.state = { ...this.state, query: { ...this.state.query, search: "", page: 1 } };
151
+ if (this.state.selected.size)
152
+ this.set({ selected: EMPTY_MAP });
153
+ }
154
+ const keepRows = quiet ?? (this.state.status === "ready" && !reset);
155
+ const query = this.state.query;
156
+ const request = this.options.paging === "server" ? query : { ...query, page: 1, pageSize: Number.MAX_SAFE_INTEGER };
157
+ let answer;
158
+ try {
159
+ answer = load(request, controller.signal);
160
+ }
161
+ catch (error) {
162
+ this.fail(error, seq);
163
+ return;
164
+ }
165
+ // An answer without a promise (a cache) shows at once: no placeholders, no second paint.
166
+ if (!(answer instanceof Promise)) {
167
+ this.take(answer, seq);
168
+ return;
169
+ }
170
+ if (keepRows)
171
+ this.set({ refreshing: true });
172
+ else
173
+ this.set({ status: "loading", refreshing: false, error: null, rows: [] });
174
+ try {
175
+ const result = await answer;
176
+ if (controller.signal.aborted)
177
+ return;
178
+ this.take(result, seq);
179
+ }
180
+ catch (error) {
181
+ if (controller.signal.aborted || isAbortError(error))
182
+ return;
183
+ this.fail(error, seq);
184
+ }
185
+ }
186
+ take(answer, seq) {
187
+ if (seq !== this.seq)
188
+ return;
189
+ this.controller = null;
190
+ const page = readTablePage(answer);
191
+ if (this.options.paging === "server") {
192
+ const query = { ...this.state.query, page: clampPage(this.state.query.page, page.matches, this.state.query.pageSize) };
193
+ // A page past the end (rows were removed elsewhere) loads the last page instead.
194
+ if (query.page !== this.state.query.page && page.rows.length === 0 && page.matches > 0) {
195
+ this.state = { ...this.state, query };
196
+ void this.reload({ quiet: true });
197
+ return;
198
+ }
199
+ this.set({
200
+ status: "ready",
201
+ refreshing: false,
202
+ error: null,
203
+ rows: page.rows,
204
+ total: page.total,
205
+ matches: page.matches,
206
+ offset: (query.page - 1) * query.pageSize,
207
+ query,
208
+ selected: this.refreshSelected(page.rows),
209
+ });
210
+ return;
211
+ }
212
+ this.all = page.rows;
213
+ this.given = null;
214
+ this.dropMissingSelection();
215
+ this.view({ status: "ready", refreshing: false, error: null });
216
+ }
217
+ fail(error, seq) {
218
+ if (seq !== this.seq)
219
+ return;
220
+ this.controller = null;
221
+ this.set({ status: "error", refreshing: false, error: errorMessage(error, "The rows could not be loaded.") });
222
+ }
223
+ /** Searches, sorts, and pages every row (client tables), then tells the table. */
224
+ view(extra = {}) {
225
+ if (this.options.paging === "server") {
226
+ this.set(extra);
227
+ return;
228
+ }
229
+ const query = { ...this.state.query, ...extra.query };
230
+ const result = queryRows(this.all, this.options.columns, query, this.texts);
231
+ const page = result.page;
232
+ this.set({
233
+ ...extra,
234
+ rows: result.rows,
235
+ total: this.all.length,
236
+ matches: result.matches,
237
+ offset: (page - 1) * query.pageSize,
238
+ query: page === query.page ? query : { ...query, page },
239
+ });
240
+ }
241
+ /** Changes the query: a client table shows it at once, a server table loads it. */
242
+ query(changes) {
243
+ const query = { ...this.state.query, ...changes };
244
+ if (this.options.paging === "server" && this.options.load) {
245
+ this.state = { ...this.state, query };
246
+ void this.reload({ quiet: this.state.status === "ready" });
247
+ }
248
+ else
249
+ this.view({ query });
250
+ }
251
+ setSearch(search) {
252
+ const text = search.trim();
253
+ if (text === this.state.query.search)
254
+ return;
255
+ this.query({ search: text, page: 1 });
256
+ }
257
+ setSort(sort) {
258
+ this.query({ sort, page: 1 });
259
+ }
260
+ /** Sorts by a column: ascending, then descending, then back to no sort. */
261
+ toggleSort(key) {
262
+ this.setSort(nextSort(this.state.query.sort, key));
263
+ }
264
+ setPage(page) {
265
+ const next = clampPage(page, this.state.matches, this.state.query.pageSize);
266
+ if (next === this.state.query.page)
267
+ return;
268
+ this.query({ page: next });
269
+ }
270
+ /** Changes the rows per page, keeping the first row of the page in view. */
271
+ setPageSize(pageSize) {
272
+ if (pageSize === this.state.query.pageSize || pageSize < 1)
273
+ return;
274
+ const first = this.state.offset;
275
+ this.query({ pageSize, page: Math.floor(first / pageSize) + 1 });
276
+ }
277
+ /* Changing rows from outside: a saved record, a deleted one */
278
+ /**
279
+ * Adds a row, or replaces the row with its key. A new row goes first (a server page grows by one until the next load),
280
+ * and is highlighted for a moment.
281
+ */
282
+ upsert(row, { at = "start", flash = true } = {}) {
283
+ const key = this.keyOf(row);
284
+ if (this.options.paging === "server") {
285
+ const index = this.state.rows.findIndex(candidate => this.keyOf(candidate) === key);
286
+ const rows = [...this.state.rows];
287
+ let { total, matches } = this.state;
288
+ if (index >= 0)
289
+ rows[index] = row;
290
+ else {
291
+ if (at === "start")
292
+ rows.unshift(row);
293
+ else
294
+ rows.push(row);
295
+ total++;
296
+ matches++;
297
+ }
298
+ this.set({ rows, total, matches, selected: this.replaceSelected(key, row), status: "ready" });
299
+ }
300
+ else {
301
+ const index = this.all.findIndex(candidate => this.keyOf(candidate) === key);
302
+ if (index >= 0)
303
+ this.all[index] = row;
304
+ else if (at === "start")
305
+ this.all.unshift(row);
306
+ else
307
+ this.all.push(row);
308
+ this.all = [...this.all];
309
+ this.view({ selected: this.replaceSelected(key, row), status: "ready" });
310
+ }
311
+ if (flash && key)
312
+ this.flash([key]);
313
+ }
314
+ /**
315
+ * Changes fields of the row with this key: an object of new values, or a function of the row. Quiet by default; pass
316
+ * `{ flash: true }` to highlight the row, such as after an action the user took on it.
317
+ */
318
+ patch(key, changes, { flash = false } = {}) {
319
+ const text = String(key);
320
+ const row = this.getRow(text);
321
+ if (!row)
322
+ return;
323
+ const next = typeof changes === "function" ? changes(row) : { ...row, ...changes };
324
+ this.upsert(next, { flash });
325
+ }
326
+ /**
327
+ * Takes rows out: they moved to another list or were deleted. A server table loads its page again in the background,
328
+ * so the page fills up and the counts stay right.
329
+ */
330
+ remove(keys) {
331
+ if (keys.length === 0)
332
+ return;
333
+ const gone = new Set(keys.map(String));
334
+ const selected = new Map(this.state.selected);
335
+ for (const key of gone)
336
+ selected.delete(key);
337
+ const busy = new Set([...this.state.busy].filter(key => !gone.has(key)));
338
+ if (this.options.paging === "server") {
339
+ const rows = this.state.rows.filter(row => !gone.has(this.keyOf(row)));
340
+ const removed = this.state.rows.length - rows.length;
341
+ this.set({
342
+ rows,
343
+ total: Math.max(0, this.state.total - removed),
344
+ matches: Math.max(0, this.state.matches - removed),
345
+ selected: selected.size === this.state.selected.size ? this.state.selected : selected,
346
+ busy,
347
+ });
348
+ // A short wait lets several removals (a mass action's rows) share one load.
349
+ clearTimeout(this.reloadTimer);
350
+ this.reloadTimer = setTimeout(() => void this.reload({ quiet: true }), 60);
351
+ return;
352
+ }
353
+ this.all = this.all.filter(row => !gone.has(this.keyOf(row)));
354
+ this.view({ selected: selected.size === this.state.selected.size ? this.state.selected : selected, busy });
355
+ }
356
+ /* Selection */
357
+ /** Selects or unselects rows, up to `maxSelection`. Returns how many rows it could not select. */
358
+ select(rows, on) {
359
+ const selected = new Map(this.state.selected);
360
+ const most = this.options.maxSelection ?? DEFAULT_MAX_SELECTION;
361
+ let refused = 0;
362
+ for (const row of rows) {
363
+ const key = this.keyOf(row);
364
+ if (!key)
365
+ continue;
366
+ if (!on)
367
+ selected.delete(key);
368
+ else if (selected.has(key))
369
+ selected.set(key, row);
370
+ else if (selected.size < most)
371
+ selected.set(key, row);
372
+ else
373
+ refused++;
374
+ }
375
+ this.set({ selected });
376
+ return refused;
377
+ }
378
+ /** Selects or unselects every row on the page. */
379
+ selectPage(on) {
380
+ return this.select(this.state.rows, on);
381
+ }
382
+ clearSelection() {
383
+ if (this.state.selected.size)
384
+ this.set({ selected: EMPTY_MAP });
385
+ }
386
+ // Selected rows keep their newest values, so a mass action sends what the table shows.
387
+ replaceSelected(key, row) {
388
+ if (!this.state.selected.has(key))
389
+ return this.state.selected;
390
+ const selected = new Map(this.state.selected);
391
+ selected.set(key, row);
392
+ return selected;
393
+ }
394
+ refreshSelected(rows) {
395
+ if (!this.state.selected.size)
396
+ return this.state.selected;
397
+ let selected = null;
398
+ for (const row of rows) {
399
+ const key = this.keyOf(row);
400
+ if (this.state.selected.has(key) && this.state.selected.get(key) !== row)
401
+ (selected ??= new Map(this.state.selected)).set(key, row);
402
+ }
403
+ return selected ?? this.state.selected;
404
+ }
405
+ /** A client table forgets selected rows that are gone from its rows. */
406
+ dropMissingSelection() {
407
+ if (!this.state.selected.size)
408
+ return;
409
+ const byKey = new Map(this.all.map(row => [this.keyOf(row), row]));
410
+ const selected = new Map();
411
+ let changed = false;
412
+ for (const [key, old] of this.state.selected) {
413
+ const row = byKey.get(key);
414
+ if (row)
415
+ selected.set(key, row);
416
+ changed ||= row !== old;
417
+ }
418
+ if (!changed)
419
+ return;
420
+ this.state = { ...this.state, selected: selected.size ? selected : EMPTY_MAP };
421
+ this.options.onSelectionChange?.(this.getSelected());
422
+ }
423
+ /* Rows with an action running, and rows to highlight */
424
+ setBusy(keys, on) {
425
+ const busy = new Set(this.state.busy);
426
+ for (const key of keys) {
427
+ if (on)
428
+ busy.add(String(key));
429
+ else
430
+ busy.delete(String(key));
431
+ }
432
+ this.set({ busy });
433
+ }
434
+ flash(keys) {
435
+ this.set({ flashed: new Set([...this.state.flashed, ...keys.map(String)]) });
436
+ clearTimeout(this.flashTimer);
437
+ this.flashTimer = setTimeout(() => this.set({ flashed: EMPTY_SET }), TABLE_FLASH_MS);
438
+ }
439
+ /* Columns: shown or hidden, their order, their widths, and the ones pinned to a side */
440
+ setHidden(key, hidden) {
441
+ if (this.state.hidden.has(key) === hidden)
442
+ return;
443
+ const next = new Set(this.state.hidden);
444
+ if (hidden)
445
+ next.add(key);
446
+ else
447
+ next.delete(key);
448
+ this.set({ hidden: next });
449
+ }
450
+ /** The order of every column, by key. Keys the columns do not have are kept, in case the column comes back. */
451
+ setOrder(order) {
452
+ this.set({ order: [...order] });
453
+ }
454
+ /** Moves a column to just before another one, or to the end when `beforeKey` is null. */
455
+ moveColumn(key, beforeKey) {
456
+ const keys = this.state.order.length ? this.state.order : this.options.columns.map(column => column.key);
457
+ const next = moveColumnKey(keys, key, beforeKey);
458
+ if (next.join() === keys.join())
459
+ return;
460
+ this.set({ order: next });
461
+ }
462
+ /** Sets the width of one column in pixels, or takes the width away (`null`), letting the content size it again. */
463
+ setWidth(key, width) {
464
+ const widths = { ...this.state.widths };
465
+ if (width === null) {
466
+ if (widths[key] === undefined)
467
+ return;
468
+ delete widths[key];
469
+ }
470
+ else {
471
+ const rounded = Math.round(Math.max(MIN_COLUMN_WIDTH, width));
472
+ if (widths[key] === rounded)
473
+ return;
474
+ widths[key] = rounded;
475
+ }
476
+ this.set({ widths });
477
+ }
478
+ /** Sets several widths at once: what the table measured when the user started to resize a column. */
479
+ setWidths(widths) {
480
+ this.set({ widths: { ...this.state.widths, ...widths } });
481
+ }
482
+ /** Back to widths that follow the content. */
483
+ clearWidths() {
484
+ if (Object.keys(this.state.widths).length === 0)
485
+ return;
486
+ this.set({ widths: NO_WIDTHS });
487
+ }
488
+ /** Keeps a column on the left or the right while the others scroll, or lets it scroll again (`null`). */
489
+ setPinned(key, side) {
490
+ if ((this.state.pinned[key] ?? null) === side)
491
+ return;
492
+ const pinned = { ...this.state.pinned };
493
+ if (side === null)
494
+ delete pinned[key];
495
+ else
496
+ pinned[key] = side;
497
+ this.set({ pinned });
498
+ }
499
+ /** Every column back as its params say: the given order, widths from the content, no pins, and the hidden ones. */
500
+ resetColumns() {
501
+ this.set({ order: EMPTY_LIST, widths: NO_WIDTHS, pinned: NO_PINS, hidden: new Set(this.options.columns.filter(column => column.hidden).map(column => column.key)) });
502
+ }
503
+ /** Whether the user has arranged the columns: an order, a width, a pin, or a hidden column of their own. */
504
+ hasColumnChanges() {
505
+ const { order, widths, pinned, hidden } = this.state;
506
+ if (order.length || Object.keys(widths).length || Object.keys(pinned).length)
507
+ return true;
508
+ const byParams = this.options.columns.filter(column => column.hidden).map(column => column.key);
509
+ return hidden.size !== byParams.length || byParams.some(key => !hidden.has(key));
510
+ }
511
+ /** Stops a load that runs and the timers. The table calls it when it goes away. */
512
+ dispose() {
513
+ if (this.controller)
514
+ this.interrupted = true;
515
+ this.controller?.abort();
516
+ this.controller = null;
517
+ clearTimeout(this.flashTimer);
518
+ clearTimeout(this.reloadTimer);
519
+ }
520
+ /**
521
+ * Loads again what `dispose` stopped, when the table comes back: React's Strict Mode unmounts and mounts every table
522
+ * once in development, and a store given as `table` can move to another place on the page.
523
+ */
524
+ resume() {
525
+ if (!this.interrupted)
526
+ return;
527
+ this.interrupted = false;
528
+ void this.reload();
529
+ }
530
+ }
@@ -0,0 +1,15 @@
1
+ import { type ThemeMode, type ThemeOption } from "../Interfaces/ThemeInterfaces.ts";
2
+ export declare const THEME_ID_PATTERN: RegExp;
3
+ export interface ThemeScriptOptions {
4
+ /** Themes a saved choice may name. Default: every built-in theme. */
5
+ themes?: readonly ThemeOption[];
6
+ /** Theme before the visitor chooses one. Default `nexus`. */
7
+ defaultTheme?: string;
8
+ /** Mode before the visitor chooses one. Default `system`. */
9
+ defaultMode?: ThemeMode;
10
+ }
11
+ /**
12
+ * JavaScript that sets the saved theme and mode on `<html>` before the page paints, so a page never flashes
13
+ * the default colors first. `ThemeScript` renders it; use this directly only outside React.
14
+ */
15
+ export declare function themeScript({ themes, defaultTheme, defaultMode }?: ThemeScriptOptions): string;
@@ -0,0 +1,16 @@
1
+ import { DEFAULT_THEME, NEXUS_THEMES, THEME_ATTRIBUTE, THEME_MODE_ATTRIBUTE, THEME_MODE_STORAGE_KEY, THEME_STORAGE_KEY, } from "../Interfaces/ThemeInterfaces.js";
2
+ export const THEME_ID_PATTERN = /^[a-z0-9-]+$/;
3
+ /**
4
+ * JavaScript that sets the saved theme and mode on `<html>` before the page paints, so a page never flashes
5
+ * the default colors first. `ThemeScript` renders it; use this directly only outside React.
6
+ */
7
+ export function themeScript({ themes = NEXUS_THEMES, defaultTheme = DEFAULT_THEME, defaultMode = "system" } = {}) {
8
+ const ids = themes.map(theme => theme.id).filter(id => THEME_ID_PATTERN.test(id));
9
+ const config = [ids, defaultTheme, defaultMode, THEME_STORAGE_KEY, THEME_MODE_STORAGE_KEY, THEME_ATTRIBUTE, THEME_MODE_ATTRIBUTE];
10
+ // "<" is escaped so no value can close the <script> element.
11
+ const json = JSON.stringify(config).replace(/</g, "\\u003c");
12
+ return ("(function(c){var d=document.documentElement,t=c[1],m=c[2];" +
13
+ "try{var s=localStorage,a=s.getItem(c[3]),b=s.getItem(c[4]);if(c[0].indexOf(a)>-1)t=a;if(b==='light'||b==='dark'||b==='system')m=b}catch(e){}" +
14
+ "if(c[0].indexOf(t)>-1)d.setAttribute(c[5],t);if(m==='light'||m==='dark')d.setAttribute(c[6],m)" +
15
+ `})(${json})`);
16
+ }
@@ -0,0 +1,73 @@
1
+ import { type DateScript, type TimeInput } from "../Interfaces/DateInterfaces.ts";
2
+ export declare const SECONDS_PER_DAY = 86400;
3
+ /** "14:30" or "14:30:15": hours 00 to 23, a two-digit minute, an optional two-digit second. */
4
+ export declare const ISO_TIME_PATTERN: RegExp;
5
+ /** Options of `formatTime` and `parseTimeText`. */
6
+ export interface TimeFormatOptions {
7
+ /** Tokens `HH` `H` 24-hour, `hh` `h` 12-hour, `mm` `m` minute, `ss` `s` second, `A` AM/PM, `a` am/pm. Default `hh:mm A`. */
8
+ format?: string;
9
+ /** `devanagari` writes Nepali digits and पूर्वाह्न/अपराह्न. Default `latin`. */
10
+ script?: DateScript;
11
+ /** Whether the time has seconds: `true` adds them to a format without them, `false` removes them. Default: as the format says. */
12
+ seconds?: boolean;
13
+ }
14
+ /** Whether text is an ISO time: "14:30" or "14:30:15". */
15
+ export declare function isIsoTime(text: unknown): text is string;
16
+ /** Seconds since midnight of an ISO time. The text must be an ISO time (`isIsoTime`). */
17
+ export declare function timeToSeconds(iso: string): number;
18
+ /** The ISO time of seconds since midnight, wrapping past midnight both ways: "HH:mm", or "HH:mm:ss" with `seconds`. */
19
+ export declare function secondsToIsoTime(total: number, seconds?: boolean): string;
20
+ /**
21
+ * Turns anything a time can arrive as into an ISO time, or `null`:
22
+ * - "14:30", "9:05", "14:30:15", "14:30:15.250" (a .NET `TimeOnly` or SQL `time`);
23
+ * - an ISO date-time with a zone, "2026-09-17T08:45:00Z", becomes the browser's local time of that instant;
24
+ * - one without a zone, "2026-09-17T14:30:00", keeps its time part;
25
+ * - a `Date` gives its local time, like `new Date()` for now.
26
+ * Without `seconds` the result is "HH:mm" and any seconds are dropped; with it, "HH:mm:ss".
27
+ */
28
+ export declare function toIsoTime(input: TimeInput, seconds?: boolean): string | null;
29
+ /** The time now where the browser is. */
30
+ export declare function nowIsoTime(seconds?: boolean): string;
31
+ /** Adds minutes (negative to go back), wrapping past midnight: `addMinutes("23:30", 45)` is "00:15". Keeps the value's seconds. */
32
+ export declare function addMinutes(iso: string, minutes: number): string;
33
+ /** Negative when `a` is earlier than `b`. "14:30" and "14:30:00" are the same time. */
34
+ export declare const compareIsoTimes: (a: string, b: string) => number;
35
+ /**
36
+ * Whether a time lies within inclusive limits, given as seconds since midnight. With `max` earlier than `min` the
37
+ * range runs past midnight: 22:00 to 06:00 allows 23:00 and 05:00, not 12:00.
38
+ */
39
+ export declare function isSecondsInRange(value: number, min: number | null, max: number | null): boolean;
40
+ /** Whether an ISO time lies within limits given as time inputs; see `isSecondsInRange` for ranges past midnight. */
41
+ export declare function isTimeInRange(iso: string, min?: TimeInput, max?: TimeInput): boolean;
42
+ /** A step in seconds as the components use it: a whole number from 1 to a day, 60 when missing or invalid. */
43
+ export declare function normalizeTimeStep(step: number | undefined): number;
44
+ /** Whether a step needs seconds: any step that is not a whole number of minutes. */
45
+ export declare const stepHasSeconds: (step: number | undefined) => boolean;
46
+ /** "15 minutes", "1 hour", "30 seconds", "1 minute 30 seconds": a step as words, for messages. */
47
+ export declare function describeTimeStep(step: number): string;
48
+ /** Whether a time format is on a 12-hour clock: it has an `hh` or `h` token. */
49
+ export declare const isTwelveHourFormat: (format: string) => boolean;
50
+ /** The names of the two halves of the day: AM and PM, or पूर्वाह्न and अपराह्न. */
51
+ export declare function getMeridiemNames(script?: DateScript): readonly [string, string];
52
+ /**
53
+ * A format with or without seconds: `true` adds ":ss" after the minutes of a format that has none ("hh:mm A" gives
54
+ * "hh:mm:ss A"), `false` removes the seconds and the separator before them. `undefined` keeps the format.
55
+ */
56
+ export declare function timeFormatWithSeconds(format: string, seconds: boolean | undefined): string;
57
+ /**
58
+ * Writes a time with a format of tokens: `HH` `H` 24-hour, `hh` `h` 12-hour, `mm` `m` minute, `ss` `s` second, `A`
59
+ * AM/PM, `a` am/pm. "hh:mm A" gives 02:30 PM; "HH:mm" gives 14:30. With the Devanagari script, digits and the
60
+ * halves of the day are Nepali: ०२:३० अपराह्न. Returns "" for an empty or invalid input.
61
+ */
62
+ export declare function formatTime(input: TimeInput, options?: TimeFormatOptions): string;
63
+ /**
64
+ * Reads a time the user typed, on either clock: "14:30", "2:30 pm", "2.30p", "230 PM", "1430", "9", "12 am",
65
+ * "14:30:15", "०२:३० अपराह्न". Without AM or PM the hours are read on a 24-hour clock, so "2:30" is 02:30. Returns the
66
+ * ISO time, "HH:mm" (typed seconds are dropped) or "HH:mm:ss" with `seconds`, or `null` for text that is not a time.
67
+ */
68
+ export declare function parseTimeText(text: string, options?: Pick<TimeFormatOptions, "seconds">): string | null;
69
+ /**
70
+ * The times a list of slots offers: every `step` seconds from `min` (or midnight) to `max` (or the end of the day),
71
+ * past midnight when `max` is earlier than `min`. Returns ISO times, with seconds when the step needs them.
72
+ */
73
+ export declare function listTimeSlots(step: number, min?: TimeInput, max?: TimeInput): string[];