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,254 @@
1
+ import { MIN_COLUMN_WIDTH } from "./TableHelpers.js";
2
+ /*
3
+ * The pointer work on the column headings of a table, with no React: dragging a heading to another place, and dragging
4
+ * its edge to change the width. Both write attributes on the cells while they run (a drop line, a cursor, the dragged
5
+ * heading) and tell the table only what came out, so a drag does not render the table on every pointer move.
6
+ */
7
+ /** How far the pointer must travel before a press on a heading becomes a drag, in pixels. */
8
+ const DRAG_THRESHOLD = 4;
9
+ /** Pixels from the edge of the scroller where a drag scrolls the columns. */
10
+ const EDGE = 52;
11
+ const KEY = "data-col";
12
+ const DROP_BEFORE = "data-drop-before";
13
+ const DROP_AFTER = "data-drop-after";
14
+ /** The headings a dragged one can be dropped between: the movable ones pinned to the same side. */
15
+ function dropTargets(heading) {
16
+ const row = heading.parentElement;
17
+ if (!row)
18
+ return [];
19
+ const pin = heading.getAttribute("data-pin") ?? "";
20
+ return [...row.children].filter((cell) => cell instanceof HTMLElement && cell.hasAttribute(KEY) && (cell.getAttribute("data-pin") ?? "") === pin);
21
+ }
22
+ function clearDropMarks(row) {
23
+ for (const cell of row?.children ?? []) {
24
+ cell.removeAttribute(DROP_BEFORE);
25
+ cell.removeAttribute(DROP_AFTER);
26
+ }
27
+ }
28
+ /**
29
+ * Drags a column heading to another place among the headings pinned to the same side. A line shows where it will land;
30
+ * Esc puts it back. Returns a function that ends the drag.
31
+ */
32
+ export function startColumnDrag(event, { heading, scroller, root, onDrop }) {
33
+ const key = heading.getAttribute(KEY) ?? "";
34
+ const row = heading.parentElement;
35
+ if (!key || !row)
36
+ return () => undefined;
37
+ const pointerId = event.pointerId;
38
+ const startX = event.clientX;
39
+ let dragging = false;
40
+ let done = false;
41
+ let target = null;
42
+ let scrollBy = 0;
43
+ let frame = 0;
44
+ function place(x) {
45
+ const targets = dropTargets(heading);
46
+ clearDropMarks(row);
47
+ target = null;
48
+ for (let index = 0; index < targets.length; index++) {
49
+ const cell = targets[index];
50
+ const rect = cell.getBoundingClientRect();
51
+ if (x >= rect.right && index < targets.length - 1)
52
+ continue;
53
+ const after = x > rect.left + rect.width / 2;
54
+ const next = targets[index + 1];
55
+ const cellKey = cell.getAttribute(KEY);
56
+ if (after) {
57
+ cell.setAttribute(DROP_AFTER, "");
58
+ target = { before: next?.getAttribute(KEY) ?? null };
59
+ }
60
+ else {
61
+ cell.setAttribute(DROP_BEFORE, "");
62
+ target = { before: cellKey };
63
+ }
64
+ // A drop where the column already sits changes nothing, so no line shows there.
65
+ if (target.before === key || cellKey === key) {
66
+ clearDropMarks(row);
67
+ target = null;
68
+ }
69
+ return;
70
+ }
71
+ }
72
+ // Near an edge of the scroller the columns move under the pointer, so a column can be dragged out of sight.
73
+ function tick() {
74
+ frame = 0;
75
+ if (!dragging || !scroller || !scrollBy)
76
+ return;
77
+ scroller.scrollLeft += scrollBy;
78
+ frame = requestAnimationFrame(tick);
79
+ }
80
+ function edgeScroll(x) {
81
+ if (!scroller)
82
+ return;
83
+ const rect = scroller.getBoundingClientRect();
84
+ const left = x - rect.left;
85
+ const right = rect.right - x;
86
+ scrollBy = left < EDGE ? -Math.ceil((EDGE - left) / 4) : right < EDGE ? Math.ceil((EDGE - right) / 4) : 0;
87
+ if (scrollBy && !frame)
88
+ frame = requestAnimationFrame(tick);
89
+ }
90
+ function begin() {
91
+ dragging = true;
92
+ heading.setAttribute("data-dragging", "");
93
+ root?.setAttribute("data-col-drag", "");
94
+ window.getSelection()?.removeAllRanges();
95
+ try {
96
+ heading.setPointerCapture(pointerId);
97
+ }
98
+ catch {
99
+ // The pointer is already gone; the next pointerup ends the drag.
100
+ }
101
+ }
102
+ function onMove(move) {
103
+ if (move.pointerId !== pointerId)
104
+ return;
105
+ if (!dragging) {
106
+ if (Math.abs(move.clientX - startX) < DRAG_THRESHOLD)
107
+ return;
108
+ begin();
109
+ }
110
+ move.preventDefault();
111
+ place(move.clientX);
112
+ edgeScroll(move.clientX);
113
+ }
114
+ function onUp(up) {
115
+ if (up.pointerId !== pointerId)
116
+ return;
117
+ const drop = target;
118
+ finish();
119
+ if (drop)
120
+ onDrop(key, drop.before);
121
+ }
122
+ function onKeyDown(press) {
123
+ if (press.key !== "Escape" || !dragging)
124
+ return;
125
+ press.preventDefault();
126
+ press.stopPropagation();
127
+ target = null;
128
+ finish();
129
+ }
130
+ // The click that ends a drag is not a click on the heading: it must not sort the column.
131
+ function swallowClick(click) {
132
+ click.stopPropagation();
133
+ click.preventDefault();
134
+ }
135
+ function finish() {
136
+ if (done)
137
+ return;
138
+ done = true;
139
+ window.removeEventListener("pointermove", onMove, true);
140
+ window.removeEventListener("pointerup", onUp, true);
141
+ window.removeEventListener("pointercancel", onUp, true);
142
+ window.removeEventListener("keydown", onKeyDown, true);
143
+ if (frame)
144
+ cancelAnimationFrame(frame);
145
+ if (!dragging)
146
+ return;
147
+ clearDropMarks(row);
148
+ heading.removeAttribute("data-dragging");
149
+ root?.removeAttribute("data-col-drag");
150
+ if (heading.hasPointerCapture?.(pointerId))
151
+ heading.releasePointerCapture(pointerId);
152
+ window.addEventListener("click", swallowClick, { capture: true, once: true });
153
+ setTimeout(() => window.removeEventListener("click", swallowClick, true), 0);
154
+ }
155
+ window.addEventListener("pointermove", onMove, true);
156
+ window.addEventListener("pointerup", onUp, true);
157
+ window.addEventListener("pointercancel", onUp, true);
158
+ window.addEventListener("keydown", onKeyDown, true);
159
+ return finish;
160
+ }
161
+ /** Drags the edge of a heading to change its width. Returns a function that ends the drag. */
162
+ export function startColumnResize(event, { heading, root, onStart, onResize, onCommit, min = MIN_COLUMN_WIDTH }) {
163
+ const pointerId = event.pointerId;
164
+ const startX = event.clientX;
165
+ const startWidth = heading.getBoundingClientRect().width;
166
+ const handle = event.currentTarget instanceof HTMLElement ? event.currentTarget : heading;
167
+ let width = startWidth;
168
+ let started = false;
169
+ let done = false;
170
+ function onMove(move) {
171
+ if (move.pointerId !== pointerId)
172
+ return;
173
+ if (!started) {
174
+ started = true;
175
+ onStart?.();
176
+ root?.setAttribute("data-col-resize", "");
177
+ handle.setAttribute("data-active", "");
178
+ window.getSelection()?.removeAllRanges();
179
+ try {
180
+ handle.setPointerCapture(pointerId);
181
+ }
182
+ catch {
183
+ // The pointer is already gone; the next pointerup ends the drag.
184
+ }
185
+ }
186
+ move.preventDefault();
187
+ width = Math.max(min, Math.round(startWidth + (move.clientX - startX)));
188
+ onResize(width);
189
+ }
190
+ function onUp(up) {
191
+ if (up.pointerId !== pointerId)
192
+ return;
193
+ finish(width);
194
+ }
195
+ function onKeyDown(press) {
196
+ if (press.key !== "Escape")
197
+ return;
198
+ press.preventDefault();
199
+ press.stopPropagation();
200
+ onResize(startWidth);
201
+ finish(startWidth);
202
+ }
203
+ function finish(final) {
204
+ if (done)
205
+ return;
206
+ done = true;
207
+ window.removeEventListener("pointermove", onMove, true);
208
+ window.removeEventListener("pointerup", onUp, true);
209
+ window.removeEventListener("pointercancel", onUp, true);
210
+ window.removeEventListener("keydown", onKeyDown, true);
211
+ root?.removeAttribute("data-col-resize");
212
+ handle.removeAttribute("data-active");
213
+ if (handle.hasPointerCapture?.(pointerId))
214
+ handle.releasePointerCapture(pointerId);
215
+ if (started)
216
+ onCommit(final);
217
+ }
218
+ window.addEventListener("pointermove", onMove, true);
219
+ window.addEventListener("pointerup", onUp, true);
220
+ window.addEventListener("pointercancel", onUp, true);
221
+ window.addEventListener("keydown", onKeyDown, true);
222
+ return () => finish(width);
223
+ }
224
+ /**
225
+ * The width a column needs for its widest value and its heading, at most `max`. Used by "Fit to content" in a heading's
226
+ * menu and by a double-click on its edge.
227
+ *
228
+ * A cell's value is a block that fills its column and cuts long text with an ellipsis, so its own width says nothing
229
+ * about the text inside it. Each one is measured at `max-content` instead, with the cap taken off: every cell is set,
230
+ * then every cell is read, so the browser lays the table out twice, not once per row.
231
+ */
232
+ export function fitColumnWidth(table, key, max = 520) {
233
+ // Each cell with the value inside it, or the heading with its label, sort arrow, and menu button.
234
+ const cells = [...table.querySelectorAll("[data-col=" + JSON.stringify(key) + "]")]
235
+ .map(cell => ({ cell, content: cell.firstElementChild, width: "", maxWidth: "" }))
236
+ .filter((pair) => pair.content instanceof HTMLElement);
237
+ for (const pair of cells) {
238
+ pair.width = pair.content.style.width;
239
+ pair.maxWidth = pair.content.style.maxWidth;
240
+ pair.content.style.width = "max-content";
241
+ pair.content.style.maxWidth = "none";
242
+ }
243
+ let widest = MIN_COLUMN_WIDTH;
244
+ for (const { cell, content } of cells) {
245
+ const style = getComputedStyle(cell);
246
+ const padding = Number.parseFloat(style.paddingLeft) + Number.parseFloat(style.paddingRight);
247
+ widest = Math.max(widest, Math.ceil(content.getBoundingClientRect().width + padding + 2));
248
+ }
249
+ for (const { content, width, maxWidth } of cells) {
250
+ content.style.width = width;
251
+ content.style.maxWidth = maxWidth;
252
+ }
253
+ return Math.min(widest, max);
254
+ }
@@ -0,0 +1,30 @@
1
+ import type { TableColumn, TableRow } from "../Interfaces/TableInterfaces.ts";
2
+ import { type CellTextOptions } from "./TableHelpers.ts";
3
+ /** What an export or a print writes. */
4
+ export interface TableOutput<TRow extends TableRow = TableRow> {
5
+ /** The columns the table shows, in their order. */
6
+ columns: readonly TableColumn<TRow>[];
7
+ /** The rows to write: every row that matches the search, or the page a server sent. */
8
+ rows: readonly TRow[];
9
+ /** The user's date and number settings, as the cells use them. */
10
+ cellOptions?: CellTextOptions;
11
+ /** Title of the file and the print view. Default "Table". */
12
+ name?: string;
13
+ /** A line under the title: the search, the list shown. */
14
+ note?: string;
15
+ }
16
+ /** The rows as CSV text: the column labels first, then a line per row. */
17
+ export declare function tableToCsv<TRow extends TableRow>({ columns, rows, cellOptions }: TableOutput<TRow>): string;
18
+ /** A file name without characters a file system refuses. */
19
+ export declare function safeFileName(name: string): string;
20
+ /** Hands the user a file to save, from text made in the browser. */
21
+ export declare function downloadText(name: string, text: string, type: string): void;
22
+ /** Writes the table as a CSV file the user saves. */
23
+ export declare function exportTableCsv<TRow extends TableRow>(output: TableOutput<TRow>): void;
24
+ /** The print view's HTML: a heading, a note, and the table. */
25
+ export declare function tableToPrintHtml<TRow extends TableRow>({ columns, rows, cellOptions, name, note }: TableOutput<TRow>): string;
26
+ /**
27
+ * Prints the table: its rows go into a frame of their own, so the page's own styles, menus, and popups stay out of the
28
+ * paper. The frame goes away once the print dialog closes.
29
+ */
30
+ export declare function printTable<TRow extends TableRow>(output: TableOutput<TRow>): void;
@@ -0,0 +1,97 @@
1
+ import { columnValue, formatCellText, isNumericColumn } from "./TableHelpers.js";
2
+ const CRLF = String.fromCharCode(13, 10);
3
+ const NEEDS_QUOTES = /[",\r\n]/;
4
+ /** One CSV field: quoted when it holds a comma, a quote, or a line break. A leading "=" or "+" is not a formula. */
5
+ function csvField(text) {
6
+ const safe = /^[=+\-@\t]/.test(text) ? "'" + text : text;
7
+ return NEEDS_QUOTES.test(safe) ? '"' + safe.replaceAll('"', '""') + '"' : safe;
8
+ }
9
+ /** The rows as CSV text: the column labels first, then a line per row. */
10
+ export function tableToCsv({ columns, rows, cellOptions = {} }) {
11
+ const lines = [columns.map(column => csvField(column.label)).join(",")];
12
+ for (const row of rows)
13
+ lines.push(columns.map(column => csvField(formatCellText(column, columnValue(column, row), cellOptions))).join(","));
14
+ return lines.join(CRLF) + CRLF;
15
+ }
16
+ /** A file name without characters a file system refuses. */
17
+ export function safeFileName(name) {
18
+ return name.replace(/[\/:*?"<>|]+/g, " ").trim().replace(/\s+/g, "-").toLowerCase() || "table";
19
+ }
20
+ /** Hands the user a file to save, from text made in the browser. */
21
+ export function downloadText(name, text, type) {
22
+ // A BOM, so Excel reads the file as UTF-8 and shows accents and Devanagari.
23
+ const blob = new Blob([String.fromCharCode(0xfeff) + text], { type });
24
+ const url = URL.createObjectURL(blob);
25
+ const link = document.createElement("a");
26
+ link.href = url;
27
+ link.download = name;
28
+ link.rel = "noopener";
29
+ document.body.append(link);
30
+ link.click();
31
+ link.remove();
32
+ // Firefox needs the object URL a moment longer than the click.
33
+ setTimeout(() => URL.revokeObjectURL(url), 10_000);
34
+ }
35
+ /** Writes the table as a CSV file the user saves. */
36
+ export function exportTableCsv(output) {
37
+ downloadText(safeFileName(output.name ?? "table") + ".csv", tableToCsv(output), "text/csv;charset=utf-8");
38
+ }
39
+ const escapeHtml = (text) => text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
40
+ /* Plain black on white, since the paper has no theme, and a header row that repeats on every page. */
41
+ const PRINT_STYLE = `
42
+ * { box-sizing: border-box; }
43
+ body { margin: 16mm 12mm; color: #111; font: 11pt/1.45 system-ui, "Segoe UI", sans-serif; }
44
+ h1 { margin: 0 0 2mm; font-size: 15pt; }
45
+ p.nx-note { margin: 0 0 5mm; color: #555; font-size: 9pt; }
46
+ table { width: 100%; border-collapse: collapse; font-size: 9.5pt; }
47
+ thead { display: table-header-group; }
48
+ th, td { padding: 4px 6px; border-bottom: 1px solid #bbb; text-align: left; vertical-align: top; }
49
+ th { border-bottom: 1.5px solid #555; font-weight: 600; white-space: nowrap; }
50
+ td.nx-end, th.nx-end { text-align: right; }
51
+ td.nx-center, th.nx-center { text-align: center; }
52
+ tr { page-break-inside: avoid; }
53
+ `;
54
+ /** The print view's HTML: a heading, a note, and the table. */
55
+ export function tableToPrintHtml({ columns, rows, cellOptions = {}, name = "Table", note }) {
56
+ const align = (column) => (column.align ?? (isNumericColumn(column) ? "end" : column.format === "boolean" ? "center" : "start"));
57
+ const cellClass = (column) => (align(column) === "end" ? ' class="nx-end"' : align(column) === "center" ? ' class="nx-center"' : "");
58
+ const head = columns.map(column => "<th" + cellClass(column) + ">" + escapeHtml(column.label) + "</th>").join("");
59
+ const body = rows
60
+ .map(row => "<tr>" + columns.map(column => "<td" + cellClass(column) + ">" + escapeHtml(formatCellText(column, columnValue(column, row), cellOptions)) + "</td>").join("") + "</tr>")
61
+ .join("");
62
+ return [
63
+ "<!doctype html><html><head><meta charset=\"utf-8\"><title>" + escapeHtml(name) + "</title><style>" + PRINT_STYLE + "</style></head><body>",
64
+ "<h1>" + escapeHtml(name) + "</h1>",
65
+ note ? '<p class="nx-note">' + escapeHtml(note) + "</p>" : "",
66
+ "<table><thead><tr>" + head + "</tr></thead><tbody>" + body + "</tbody></table>",
67
+ "</body></html>",
68
+ ].join("");
69
+ }
70
+ /**
71
+ * Prints the table: its rows go into a frame of their own, so the page's own styles, menus, and popups stay out of the
72
+ * paper. The frame goes away once the print dialog closes.
73
+ */
74
+ export function printTable(output) {
75
+ const frame = document.createElement("iframe");
76
+ frame.setAttribute("aria-hidden", "true");
77
+ frame.title = output.name ?? "Table";
78
+ frame.style.cssText = "position:fixed;right:0;bottom:0;width:1px;height:1px;border:0;opacity:0;";
79
+ document.body.append(frame);
80
+ const remove = () => frame.remove();
81
+ frame.addEventListener("load", () => {
82
+ const view = frame.contentWindow;
83
+ if (!view)
84
+ return remove();
85
+ view.addEventListener("afterprint", remove, { once: true });
86
+ // Safari and Firefox return from print() with the dialog still open; the load of the fonts is done by now.
87
+ view.focus();
88
+ view.print();
89
+ setTimeout(remove, 60_000);
90
+ });
91
+ const document_ = frame.contentDocument;
92
+ if (!document_)
93
+ return remove();
94
+ document_.open();
95
+ document_.write(tableToPrintHtml(output));
96
+ document_.close();
97
+ }
@@ -0,0 +1,102 @@
1
+ import type { DatePreferences } from "../Interfaces/DateInterfaces.ts";
2
+ import type { TableColumn, TableColumnOption, TableKey, TablePage, TablePinSide, TableQuery, TableRow, TableSort, TableViewColumn } from "../Interfaces/TableInterfaces.ts";
3
+ /** Rows per page when nothing says otherwise. */
4
+ export declare const DEFAULT_PAGE_SIZE = 10;
5
+ /** Choices of rows per page. */
6
+ export declare const DEFAULT_PAGE_SIZES: readonly number[];
7
+ /** Most rows a table lets the user select, as the old data table did. */
8
+ export declare const DEFAULT_MAX_SELECTION = 500;
9
+ /** Reads a field, or a path into the row: `readPath(row, "guest.name")`. */
10
+ export declare function readPath(row: unknown, path: string): unknown;
11
+ /** A row's key as text, so 5 and "5" are the same row. */
12
+ export declare function rowKeyText<TRow extends TableRow>(row: TRow, rowKey: string | ((row: TRow) => TableKey)): string;
13
+ /** A column's value in a row. */
14
+ export declare function columnValue<TRow extends TableRow>(column: TableColumn<TRow>, row: TRow): unknown;
15
+ /** The option a value stands for, if the column has options. Values compare as text, so 2 matches "2". */
16
+ export declare function columnOption(column: TableColumn<never> | TableColumn, value: unknown): TableColumnOption | undefined;
17
+ /** Whether a column lines its values up at the end, as numbers do. */
18
+ export declare function isNumericColumn(column: Pick<TableColumn, "format">): boolean;
19
+ /** Where a column's values sit in their cells. */
20
+ export declare function columnAlign(column: TableColumn<never> | TableColumn): "start" | "center" | "end";
21
+ /** Settings for writing values: the user's date and time settings, and the zone for moments. */
22
+ export interface CellTextOptions {
23
+ preferences?: Partial<DatePreferences>;
24
+ /** IANA zone for `date-time` values. Default: the browser's. */
25
+ timeZone?: string;
26
+ }
27
+ /**
28
+ * A value as the cell writes it, in the column's format: "1,250.00", "Rs. 4,500.00", "12.5%", the date and time in the
29
+ * user's settings, "Yes" or "No", an option's label. Empty values give "".
30
+ */
31
+ export declare function formatCellText<TRow extends TableRow>(column: TableColumn<TRow>, value: unknown, options?: CellTextOptions): string;
32
+ /** Text the search looks in: the column's `text`, an option's label, or the value as text (dates as ISO text). */
33
+ export declare function searchTextOf<TRow extends TableRow>(column: TableColumn<TRow>, row: TRow): string;
34
+ /** Compares two values of a column for sorting: numbers as numbers, text as a person reads it ("Room 9" before "Room 10"). */
35
+ export declare function compareCellValues(a: unknown, b: unknown): number;
36
+ /**
37
+ * Sorts rows by a column, keeping the order of equal rows. Empty values go last in both directions, so the rows with
38
+ * values stay on the first pages.
39
+ */
40
+ export declare function sortRows<TRow extends TableRow>(rows: readonly TRow[], column: TableColumn<TRow>, direction: TableSort["direction"]): TRow[];
41
+ /** How many pages `count` rows take. At least 1. */
42
+ export declare function pageCount(count: number, pageSize: number): number;
43
+ /** A page number within the pages there are. */
44
+ export declare function clampPage(page: number, count: number, pageSize: number): number;
45
+ /**
46
+ * The page buttons: the first and last pages, the pages around the current one, and `"gap"` where pages are left out.
47
+ * `pageButtons(6, 24)` gives [1, "gap", 5, 6, 7, "gap", 24]. The list is 7 long at most, so the pager keeps its width.
48
+ */
49
+ export declare function pageButtons(page: number, pages: number): (number | "gap")[];
50
+ /** Reads what a loader answered: a page, or every row. */
51
+ export declare function readTablePage<TRow extends TableRow>(answer: TablePage<TRow> | readonly TRow[] | null | undefined): {
52
+ rows: TRow[];
53
+ total: number;
54
+ matches: number;
55
+ };
56
+ /**
57
+ * Searches, sorts, and pages rows the way the table shows them. `texts` caches each row's folded search text, so a
58
+ * search of 10,000 rows looks at each row once per keystroke.
59
+ */
60
+ export declare function queryRows<TRow extends TableRow>(rows: readonly TRow[], columns: readonly TableColumn<TRow>[], query: TableQuery, texts?: WeakMap<TRow, string>): {
61
+ rows: TRow[];
62
+ matches: number;
63
+ page: number;
64
+ };
65
+ /** The next sort after a click on a column's heading: ascending, then descending, then none. */
66
+ export declare function nextSort(current: TableSort | null, key: string): TableSort | null;
67
+ /** A width in CSS: pixels for numbers, the text as it is. */
68
+ export declare const cssLength: (value: number | string | undefined) => string | undefined;
69
+ /** The table's own columns in the widths it remembers: the numbers and checkbox column, and the actions. */
70
+ export declare const TABLE_INDEX_COLUMN = "#index";
71
+ export declare const TABLE_ACTIONS_COLUMN = "#actions";
72
+ /** Narrowest a column gets while the user drags its edge, in pixels. */
73
+ export declare const MIN_COLUMN_WIDTH = 56;
74
+ /** Whether a key names one of the table's own columns, not a column of the page's. */
75
+ export declare const isOwnColumn: (key: string) => boolean;
76
+ /**
77
+ * The columns in the order the user put them: the keys of `order` first, in that order, then any column it does not
78
+ * name, where the columns were given. A key of a column that is gone is left out.
79
+ */
80
+ export declare function orderColumns<TRow extends TableRow>(columns: readonly TableColumn<TRow>[], order: readonly string[] | undefined): TableColumn<TRow>[];
81
+ /** The keys with `key` moved to just before `beforeKey`, or to the end when it is null. */
82
+ export declare function moveColumnKey(keys: readonly string[], key: string, beforeKey: string | null): string[];
83
+ /** Whether the user may pin, resize, or move a column: the table allows it and the column does not refuse it. */
84
+ export interface ColumnRights {
85
+ reorderable?: boolean;
86
+ resizable?: boolean;
87
+ pinnable?: boolean;
88
+ }
89
+ export interface ViewColumnsOptions extends ColumnRights {
90
+ order?: readonly string[];
91
+ pinned?: Readonly<Record<string, TablePinSide>>;
92
+ widths?: Readonly<Record<string, number>>;
93
+ /** Pixels from the pinned side, measured from the columns before it. */
94
+ offsets?: Readonly<Record<string, number>>;
95
+ }
96
+ /**
97
+ * The columns as the table draws them: in the user's order, with the pinned ones moved to their side (keeping their
98
+ * order among themselves), each with its width, its distance from that edge, and what the user may do with it.
99
+ */
100
+ export declare function viewColumns<TRow extends TableRow>(columns: readonly TableColumn<TRow>[], options?: ViewColumnsOptions): TableViewColumn<TRow>[];
101
+ /** Whether the user may pin this column to a side. */
102
+ export declare function canPinColumn(column: Pick<TableColumn, "pinnable">, rights: ColumnRights): boolean;