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,79 @@
1
+ import type { InputParams, InputValidationContext, RowsInputProps, RowValue } from "../Interfaces/FormInterfaces.ts";
2
+ /** Keys that place an input in a form; a renderer leaves them out of the component's props. */
3
+ export declare const INPUT_LAYOUT_KEYS: readonly ["span", "width", "grow", "hidden"];
4
+ /** Inputs whose value is `true` or `false`. */
5
+ export declare const isBooleanInput: (params: InputParams) => params is import("../Shared.Index.ts").CheckBoxParams | import("../Shared.Index.ts").SwitchParams | import("../Shared.Index.ts").RadioParams;
6
+ /** Inputs whose value is an array of rows. */
7
+ export declare const isRowsInput: (params: InputParams) => params is import("../Shared.Index.ts").TabularParams | import("../Shared.Index.ts").GroupParams;
8
+ /**
9
+ * The name an input's messages use, as the input itself picks it: `fieldName`, or the label when it is text. A checkbox's
10
+ * label is usually a sentence, so it uses `fieldName` only.
11
+ */
12
+ export declare function inputFieldName(params: InputParams): string | undefined;
13
+ /** The value of an input with nothing in it: "" for text, `null` for a number or a date, `false`, `[]`, and so on. */
14
+ export declare function emptyInputValue(params: InputParams): unknown;
15
+ /** The value an input starts with in a new row: its `defaultValue` (`defaultChecked` for a checkbox), or empty. */
16
+ export declare function initialInputValue(params: InputParams): unknown;
17
+ /**
18
+ * A value as the input reports it, from what an API or a default gave: "2026-09-17T00:00:00" becomes "2026-09-17" for a
19
+ * date, "12.5" becomes 12.5 for a number, `null` becomes "" for text. Missing values become the empty value.
20
+ */
21
+ export declare function normalizeInputValue(params: InputParams, value: unknown): unknown;
22
+ /** Whether a value counts as empty: `null`, "", spaces, `false`, an empty array, or a range with no ends. */
23
+ export declare function isEmptyInputValue(value: unknown): boolean;
24
+ /** Equal values: the same primitive, or arrays with the same items in the same order. */
25
+ export declare function inputValuesEqual(a: unknown, b: unknown): boolean;
26
+ /**
27
+ * Checks a value against its input's rules and returns the first message, or `null` when it is valid: the same
28
+ * message the input shows. Pure, so a form can check thousands of values on submit, including rows not on screen.
29
+ * A tabular or group form's value is checked row by row, and the first problem is named with its row: "Address 2: City is required."
30
+ */
31
+ export declare function validateInput(params: InputParams, value: unknown, context?: InputValidationContext): string | null;
32
+ /** The rules of a tabular or group form's rows, as `validateRows` reads them. */
33
+ export type RowsRules<TRow extends RowValue = RowValue> = Pick<RowsInputProps<TRow>, "inputs" | "required" | "min" | "max" | "unique" | "validate" | "itemLabel" | "itemLabelPlural">;
34
+ /** A value in a row that fails its input's rules, or repeats another row's. */
35
+ export interface RowsProblem {
36
+ /** The row's position, from 0. */
37
+ index: number;
38
+ /** The input's name. */
39
+ name: string;
40
+ message: string;
41
+ }
42
+ export interface RowsValidation {
43
+ /** The rows' own message: too few or too many, none of a radio column on, or `validate`'s. `null` when fine. */
44
+ message: string | null;
45
+ /** Each value that fails, in row order, then input order. */
46
+ cells: RowsProblem[];
47
+ }
48
+ /** How a row is named: `title` for "Address 2", and `item` and `items` in lower case for sentences. */
49
+ export declare function rowsItemNames(props: Pick<RowsInputProps, "itemLabel" | "itemLabelPlural">, fallback: string): {
50
+ title: string;
51
+ item: string;
52
+ items: string;
53
+ };
54
+ /** The text two values are compared by for `unique`: trimmed and in lower case, numbers as they are. `null` when empty. */
55
+ export declare function uniqueKeyOf(value: unknown): string | null;
56
+ /** The rows' own message for a list of rows: count rules, radio columns that one row must have on, then `validate`. */
57
+ export declare function rowsMessage<TRow extends RowValue>(rows: readonly TRow[], rules: RowsRules<TRow>, fallback?: string): string | null;
58
+ /**
59
+ * Rows whose value in a `unique` input another row also has: the row, the input, and the position of the other row it
60
+ * is named after. Every row with the value is found, so the one just edited says so, whichever came first: the first
61
+ * row names the second, the others name the first.
62
+ */
63
+ export declare function findDuplicates<TRow extends RowValue>(rows: readonly TRow[], names: readonly string[]): {
64
+ index: number;
65
+ name: string;
66
+ first: number;
67
+ }[];
68
+ /** The message of a repeated value: "Email is the same as in row 1." */
69
+ export declare function duplicateMessageFor(params: InputParams | undefined, name: string, first: number, item: string): string;
70
+ /**
71
+ * Checks every row of a tabular or group form: each value against its input's rules, repeated values in `unique`
72
+ * inputs, and the rows' own rules. Pure, like `validateInput`, which uses it for a rows input's value.
73
+ */
74
+ export declare function validateRows<TRow extends RowValue>(rows: readonly TRow[] | null | undefined, rules: RowsRules<TRow>, context?: InputValidationContext): RowsValidation;
75
+ /**
76
+ * A value as short text, for a collapsed section's summary or a message: a number with its format, an option's label,
77
+ * a date in the user's calendar. "" for an empty value.
78
+ */
79
+ export declare function formatInputValue(params: InputParams, value: unknown, context?: InputValidationContext): string;
@@ -0,0 +1,388 @@
1
+ import { DEFAULT_DATE_PREFERENCES } from "../Interfaces/DateInterfaces.js";
2
+ import { formatDate, formatDateRange, toDateRange, toIsoDate, usesDevanagari } from "./DateHelpers.js";
3
+ import { formatDateTime, toUtcDateTime } from "./DateTimeHelpers.js";
4
+ import { formatNumber, parseNumber } from "./NumberHelpers.js";
5
+ import { richTextToPlainText, validateRichText } from "./RichTextHelpers.js";
6
+ import { pluralize } from "./MessageBuilder.js";
7
+ import { formatTime, normalizeTimeStep, timeFormatWithSeconds, toIsoTime } from "./TimeHelpers.js";
8
+ import { chooseRowMessage, duplicateRowMessage, maxRowsMessage, minRowsMessage, validateCheck, validateDate, validateDateRange, validateDateTime, validateNumber, validateSelection, validateText, validateTime, } from "./ValidationHelpers.js";
9
+ /*
10
+ * Working with input params without a browser: the empty value of each input, its value in a new row, loaded values
11
+ * turned into the type the input reports, and the same checks the inputs run, as pure functions. A form validates
12
+ * every value on submit with them, rows that are not on screen included.
13
+ */
14
+ /** Keys that place an input in a form; a renderer leaves them out of the component's props. */
15
+ export const INPUT_LAYOUT_KEYS = ["span", "width", "grow", "hidden"];
16
+ /** Inputs whose value is `true` or `false`. */
17
+ export const isBooleanInput = (params) => params.type === "checkbox" || params.type === "switch" || params.type === "radio";
18
+ /** Inputs whose value is an array of rows. */
19
+ export const isRowsInput = (params) => params.type === "tabular" || params.type === "group";
20
+ /**
21
+ * The name an input's messages use, as the input itself picks it: `fieldName`, or the label when it is text. A checkbox's
22
+ * label is usually a sentence, so it uses `fieldName` only.
23
+ */
24
+ export function inputFieldName(params) {
25
+ const { fieldName } = params;
26
+ if (fieldName)
27
+ return fieldName;
28
+ if (params.type === "checkbox" || params.type === "switch")
29
+ return undefined;
30
+ return typeof params.label === "string" ? params.label : undefined;
31
+ }
32
+ /** The value of an input with nothing in it: "" for text, `null` for a number or a date, `false`, `[]`, and so on. */
33
+ export function emptyInputValue(params) {
34
+ switch (params.type) {
35
+ case "number":
36
+ case "date":
37
+ case "time":
38
+ case "date-time":
39
+ case "radio-group":
40
+ return null;
41
+ case "checkbox":
42
+ case "switch":
43
+ case "radio":
44
+ return false;
45
+ case "checkbox-group":
46
+ case "tree":
47
+ case "tabular":
48
+ case "group":
49
+ return [];
50
+ case "dropdown":
51
+ return params.multiple ? [] : null;
52
+ case "date-range":
53
+ return [null, null];
54
+ case "slider":
55
+ return params.min ?? 0;
56
+ case "range-slider":
57
+ return [params.min ?? 0, params.max ?? 100];
58
+ default:
59
+ return "";
60
+ }
61
+ }
62
+ /** The value an input starts with in a new row: its `defaultValue` (`defaultChecked` for a checkbox), or empty. */
63
+ export function initialInputValue(params) {
64
+ if (isBooleanInput(params))
65
+ return Boolean(params.defaultChecked);
66
+ const { defaultValue } = params;
67
+ return normalizeInputValue(params, defaultValue);
68
+ }
69
+ /**
70
+ * A value as the input reports it, from what an API or a default gave: "2026-09-17T00:00:00" becomes "2026-09-17" for a
71
+ * date, "12.5" becomes 12.5 for a number, `null` becomes "" for text. Missing values become the empty value.
72
+ */
73
+ export function normalizeInputValue(params, value) {
74
+ if (value === undefined || value === null) {
75
+ // A dropdown or radio group keeps a saved null; a number, a date, and a time do too, as their empty value.
76
+ return emptyInputValue(params);
77
+ }
78
+ switch (params.type) {
79
+ case "number": {
80
+ if (typeof value === "number")
81
+ return Number.isNaN(value) ? null : value;
82
+ return typeof value === "string" ? parseNumber(value, params.locale) : null;
83
+ }
84
+ case "checkbox":
85
+ case "switch":
86
+ case "radio":
87
+ return value === true || value === "true" || value === 1;
88
+ case "date":
89
+ return toIsoDate(value) ?? (typeof value === "string" ? value : null);
90
+ case "date-range":
91
+ return toDateRange(Array.isArray(value) ? value : null);
92
+ case "time":
93
+ return toIsoTime(value, normalizeTimeStep(params.step) % 60 !== 0) ?? (typeof value === "string" ? value : null);
94
+ case "date-time":
95
+ return toUtcDateTime(value) ?? (typeof value === "string" ? value : null);
96
+ case "checkbox-group":
97
+ case "tree":
98
+ case "tabular":
99
+ case "group":
100
+ return Array.isArray(value) ? value : [];
101
+ case "dropdown":
102
+ if (params.multiple)
103
+ return Array.isArray(value) ? value : [value];
104
+ return Array.isArray(value) ? (value[0] ?? null) : value;
105
+ case "slider":
106
+ return typeof value === "number" ? value : (parseNumber(String(value)) ?? params.min ?? 0);
107
+ case "range-slider":
108
+ return Array.isArray(value) && value.length === 2 ? value : emptyInputValue(params);
109
+ case "radio-group":
110
+ return value;
111
+ default:
112
+ return typeof value === "string" ? value : String(value);
113
+ }
114
+ }
115
+ /** Whether a value counts as empty: `null`, "", spaces, `false`, an empty array, or a range with no ends. */
116
+ export function isEmptyInputValue(value) {
117
+ if (value === null || value === undefined || value === false)
118
+ return true;
119
+ if (typeof value === "string")
120
+ return value.trim() === "";
121
+ if (Array.isArray(value))
122
+ return value.every(item => item === null || item === undefined || item === "");
123
+ return false;
124
+ }
125
+ /** Equal values: the same primitive, or arrays with the same items in the same order. */
126
+ export function inputValuesEqual(a, b) {
127
+ if (Object.is(a, b))
128
+ return true;
129
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
130
+ return false;
131
+ return a.every((item, index) => Object.is(item, b[index]));
132
+ }
133
+ function dateSettings(params, preferences) {
134
+ return {
135
+ calendar: params.calendar ?? preferences.calendar,
136
+ format: params.format ?? preferences.format,
137
+ script: params.script ?? preferences.script,
138
+ };
139
+ }
140
+ function timeSettings(params, preferences) {
141
+ const seconds = normalizeTimeStep(params.step) % 60 !== 0;
142
+ return {
143
+ format: timeFormatWithSeconds(params.format ?? preferences.timeFormat ?? DEFAULT_DATE_PREFERENCES.timeFormat, seconds),
144
+ script: params.script ?? (usesDevanagari(preferences.calendar, preferences.script) ? "devanagari" : "latin"),
145
+ };
146
+ }
147
+ function asArray(value) {
148
+ if (Array.isArray(value))
149
+ return value;
150
+ return value === null || value === undefined ? [] : [value];
151
+ }
152
+ /**
153
+ * Checks a value against its input's rules and returns the first message, or `null` when it is valid: the same
154
+ * message the input shows. Pure, so a form can check thousands of values on submit, including rows not on screen.
155
+ * A tabular or group form's value is checked row by row, and the first problem is named with its row: "Address 2: City is required."
156
+ */
157
+ export function validateInput(params, value, context = {}) {
158
+ if (params.hidden || params.disabled || params.readOnly)
159
+ return null;
160
+ const name = inputFieldName(params);
161
+ const preferences = context.preferences ?? DEFAULT_DATE_PREFERENCES;
162
+ switch (params.type) {
163
+ case "number":
164
+ return validateNumber(value, params, name, limit => formatNumber(limit, { locale: params.locale, grouping: true }));
165
+ case "checkbox":
166
+ case "switch":
167
+ return validateCheck(value === true, params, params.fieldName);
168
+ case "radio":
169
+ // One row at a time can have it on; whether one must is the rows' rule.
170
+ return null;
171
+ case "checkbox-group":
172
+ return validateSelection(asArray(value), params, name);
173
+ case "radio-group": {
174
+ const { validate } = params;
175
+ return validateSelection(asArray(value), { required: params.required, validate: validate && (values => validate(values[0] ?? null)) }, name);
176
+ }
177
+ case "dropdown":
178
+ return validateSelection(asArray(value), { required: params.required, min: params.min, max: params.max, validate: params.validate }, name);
179
+ case "date": {
180
+ const settings = dateSettings(params, preferences);
181
+ return validateDate(value, params, name, iso => formatDate(iso, settings));
182
+ }
183
+ case "date-range": {
184
+ const settings = dateSettings(params, preferences);
185
+ return validateDateRange(value, params, name, iso => formatDate(iso, settings));
186
+ }
187
+ case "time": {
188
+ const settings = timeSettings(params, preferences);
189
+ return validateTime(value, params, name, iso => formatTime(iso, settings));
190
+ }
191
+ case "date-time": {
192
+ const seconds = normalizeTimeStep(params.step) % 60 !== 0;
193
+ return validateDateTime(value, params, name, {
194
+ ...dateSettings(params, preferences),
195
+ timeFormat: timeFormatWithSeconds(params.timeFormat ?? preferences.timeFormat ?? DEFAULT_DATE_PREFERENCES.timeFormat, seconds),
196
+ timeZone: params.timeZone,
197
+ seconds,
198
+ });
199
+ }
200
+ case "slider":
201
+ return params.validate?.(value) || null;
202
+ case "range-slider":
203
+ return params.validate?.(value) || null;
204
+ case "tree":
205
+ return null;
206
+ case "rich-text":
207
+ return validateRichText(value, params, name);
208
+ case "tabular":
209
+ case "group": {
210
+ const result = validateRows(asArray(value), params, context);
211
+ if (result.message)
212
+ return result.message;
213
+ const first = result.cells[0];
214
+ return first ? `${rowsItemNames(params, params.type === "tabular" ? "Row" : "Item").title} ${first.index + 1}: ${first.message}` : null;
215
+ }
216
+ default:
217
+ return validateText(value, params, name);
218
+ }
219
+ }
220
+ /** Lower case for use inside a sentence, except words that are capitals throughout (PAN, URL). */
221
+ function inSentence(text) {
222
+ const [first = ""] = text.split(" ");
223
+ return first.length > 1 && first === first.toUpperCase() ? text : text.charAt(0).toLowerCase() + text.slice(1);
224
+ }
225
+ /** How a row is named: `title` for "Address 2", and `item` and `items` in lower case for sentences. */
226
+ export function rowsItemNames(props, fallback) {
227
+ const title = props.itemLabel?.trim() || fallback;
228
+ const plural = props.itemLabelPlural?.trim() || pluralize(title);
229
+ return { title, item: inSentence(title), items: inSentence(plural) };
230
+ }
231
+ /** The text two values are compared by for `unique`: trimmed and in lower case, numbers as they are. `null` when empty. */
232
+ export function uniqueKeyOf(value) {
233
+ if (isEmptyInputValue(value))
234
+ return null;
235
+ if (typeof value === "string")
236
+ return "s:" + value.trim().toLocaleLowerCase();
237
+ if (typeof value === "number" || typeof value === "boolean")
238
+ return typeof value + ":" + String(value);
239
+ return "j:" + JSON.stringify(value);
240
+ }
241
+ /** The name of a radio column in "Choose the primary address": its `fieldName` or text label, in lower case. */
242
+ function radioName(params) {
243
+ const { fieldName } = params;
244
+ return inSentence(fieldName ?? (typeof params.label === "string" ? params.label : params.name));
245
+ }
246
+ /** The rows' own message for a list of rows: count rules, radio columns that one row must have on, then `validate`. */
247
+ export function rowsMessage(rows, rules, fallback = "Row") {
248
+ const names = rowsItemNames(rules, fallback);
249
+ const count = rows.length;
250
+ if (count === 0) {
251
+ if (rules.required)
252
+ return minRowsMessage(Math.max(1, rules.min ?? 1), names.item, names.items);
253
+ }
254
+ else {
255
+ if (rules.min !== undefined && count < rules.min)
256
+ return minRowsMessage(rules.min, names.item, names.items);
257
+ if (rules.max !== undefined && count > rules.max)
258
+ return maxRowsMessage(rules.max, names.item, names.items);
259
+ for (const params of rules.inputs) {
260
+ if (params.type !== "radio" || !params.required || params.hidden)
261
+ continue;
262
+ if (!rows.some(row => row[params.name] === true))
263
+ return chooseRowMessage(radioName(params), names.item);
264
+ }
265
+ }
266
+ return rules.validate?.([...rows]) || null;
267
+ }
268
+ /**
269
+ * Rows whose value in a `unique` input another row also has: the row, the input, and the position of the other row it
270
+ * is named after. Every row with the value is found, so the one just edited says so, whichever came first: the first
271
+ * row names the second, the others name the first.
272
+ */
273
+ export function findDuplicates(rows, names) {
274
+ const found = [];
275
+ for (const name of names) {
276
+ const groups = new Map();
277
+ rows.forEach((row, index) => {
278
+ const key = uniqueKeyOf(row[name]);
279
+ if (key === null)
280
+ return;
281
+ const group = groups.get(key);
282
+ if (group)
283
+ group.push(index);
284
+ else
285
+ groups.set(key, [index]);
286
+ });
287
+ for (const group of groups.values()) {
288
+ if (group.length < 2)
289
+ continue;
290
+ for (const index of group)
291
+ found.push({ index, name, first: index === group[0] ? group[1] : group[0] });
292
+ }
293
+ }
294
+ return found.sort((a, b) => a.index - b.index);
295
+ }
296
+ /** The message of a repeated value: "Email is the same as in row 1." */
297
+ export function duplicateMessageFor(params, name, first, item) {
298
+ const fieldName = (params && inputFieldName(params)) ?? name;
299
+ return duplicateRowMessage(fieldName, item, first + 1);
300
+ }
301
+ /**
302
+ * Checks every row of a tabular or group form: each value against its input's rules, repeated values in `unique`
303
+ * inputs, and the rows' own rules. Pure, like `validateInput`, which uses it for a rows input's value.
304
+ */
305
+ export function validateRows(rows, rules, context = {}) {
306
+ const list = rows ?? [];
307
+ const inputs = rules.inputs.filter(params => !params.hidden);
308
+ const order = new Map(inputs.map((params, index) => [params.name, index]));
309
+ const names = rowsItemNames(rules, "Row");
310
+ const cells = [];
311
+ const failed = new Set();
312
+ list.forEach((row, index) => {
313
+ for (const params of inputs) {
314
+ const message = validateInput(params, normalizeInputValue(params, row[params.name]), context);
315
+ if (!message)
316
+ continue;
317
+ cells.push({ index, name: params.name, message });
318
+ failed.add(`${index}:${params.name}`);
319
+ }
320
+ });
321
+ for (const { index, name, first } of findDuplicates(list, rules.unique ?? [])) {
322
+ // A value that breaks its own rules says so first.
323
+ if (failed.has(`${index}:${name}`))
324
+ continue;
325
+ cells.push({ index, name, message: duplicateMessageFor(inputs.find(params => params.name === name), name, first, names.item) });
326
+ }
327
+ cells.sort((a, b) => a.index - b.index || (order.get(a.name) ?? 0) - (order.get(b.name) ?? 0));
328
+ return { message: rowsMessage(list, rules), cells };
329
+ }
330
+ /* Text for summaries */
331
+ function optionLabel(options, value, valueKey = "value", labelKey = "label") {
332
+ const item = options?.find(option => option[valueKey] === value);
333
+ const label = item?.[labelKey];
334
+ return typeof label === "string" || typeof label === "number" ? String(label) : String(value);
335
+ }
336
+ /**
337
+ * A value as short text, for a collapsed section's summary or a message: a number with its format, an option's label,
338
+ * a date in the user's calendar. "" for an empty value.
339
+ */
340
+ export function formatInputValue(params, value, context = {}) {
341
+ if (isEmptyInputValue(value))
342
+ return "";
343
+ const preferences = context.preferences ?? DEFAULT_DATE_PREFERENCES;
344
+ switch (params.type) {
345
+ case "number": {
346
+ const text = formatNumber(value, { ...params, grouping: params.grouping ?? true });
347
+ const prefix = typeof params.prefix === "string" ? params.prefix + " " : "";
348
+ const suffix = typeof params.suffix === "string" ? " " + params.suffix : "";
349
+ return prefix + text + suffix;
350
+ }
351
+ case "checkbox":
352
+ case "switch":
353
+ case "radio":
354
+ return typeof params.label === "string" ? params.label : "";
355
+ case "dropdown":
356
+ return asArray(value)
357
+ .map(item => optionLabel(params.options, item, params.valueKey, params.labelKey))
358
+ .join(", ");
359
+ case "checkbox-group":
360
+ case "radio-group":
361
+ return asArray(value)
362
+ .map(item => optionLabel(params.options, item))
363
+ .join(", ");
364
+ case "date":
365
+ return formatDate(value, dateSettings(params, preferences));
366
+ case "date-range":
367
+ return formatDateRange(value, dateSettings(params, preferences));
368
+ case "time":
369
+ return formatTime(value, timeSettings(params, preferences));
370
+ case "date-time":
371
+ return formatDateTime(value, { ...dateSettings(params, preferences), timeFormat: params.timeFormat ?? preferences.timeFormat, timeZone: params.timeZone });
372
+ case "slider":
373
+ return formatNumber(value, params);
374
+ case "range-slider":
375
+ return asArray(value)
376
+ .map(item => formatNumber(item, params))
377
+ .join(" – ");
378
+ case "tree":
379
+ case "tabular":
380
+ case "group":
381
+ return "";
382
+ default: {
383
+ const text = params.type === "rich-text" ? richTextToPlainText(String(value)) : String(value).trim();
384
+ const line = text.split("\n", 1)[0] ?? "";
385
+ return line.length > 60 ? line.slice(0, 57) + "…" : line;
386
+ }
387
+ }
388
+ }
@@ -0,0 +1,27 @@
1
+ export type MarkdownTool = "heading" | "bold" | "italic" | "strikethrough" | "code" | "link" | "image" | "quote" | "bulletList" | "numberedList" | "taskList" | "codeBlock" | "table" | "rule";
2
+ export interface MarkdownEdit {
3
+ /** Replaces the text from `start` to `end` with `text`. */
4
+ start: number;
5
+ end: number;
6
+ text: string;
7
+ /** The selection after the edit. Without it, the selection stays where it was. */
8
+ selectionStart?: number;
9
+ selectionEnd?: number;
10
+ }
11
+ /** A starter table: three columns, a header, and one row. */
12
+ export declare const MARKDOWN_TABLE = "| Column | Column | Column |\n| --- | --- | --- |\n| Text | Text | Text |";
13
+ /**
14
+ * The edit for a toolbar button. Inline marks (bold, italic, strikethrough, code) wrap the selection or the word at the
15
+ * caret, or remove the marks when they are already there. Line marks (quote, lists) apply to every selected line and
16
+ * come off when every line has them. Blocks (table, horizontal line) go on their own lines after the selection.
17
+ */
18
+ export declare function applyMarkdownTool(value: string, selectionStart: number, selectionEnd: number, tool: MarkdownTool): MarkdownEdit;
19
+ /**
20
+ * The edit for Enter at the end of a list item: a new item with the same indent and marker, the next number, and an
21
+ * empty box for a task. Enter on an empty item ends the list instead. `null` when Enter should just break the line.
22
+ */
23
+ export declare function continueMarkdownList(value: string, selectionStart: number, selectionEnd: number): MarkdownEdit | null;
24
+ /** The edit that ticks or clears the task whose marker is on `line` (from 0), as `MarkdownListItem.line` gives it. */
25
+ export declare function toggleMarkdownTask(value: string, line: number, checked: boolean): MarkdownEdit | null;
26
+ /** The edit that turns selected text into a link when a URL is pasted over it. `null` for any other paste. */
27
+ export declare function linkPastedUrl(value: string, selectionStart: number, selectionEnd: number, pasted: string): MarkdownEdit | null;