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,134 @@
1
+ import { type IconNode } from "nexus-icons";
2
+ import { type CSSProperties, type MouseEvent, type ReactNode } from "react";
3
+ import { type CellTextOptions } from "../../Helpers/TableHelpers.ts";
4
+ import type { TableColumn, TableRow, TableRowAction, TableState, TableViewColumn } from "../../Interfaces/TableInterfaces.ts";
5
+ /** A number as the table writes counts: 1,234. */
6
+ export declare const formatCount: (count: number) => string;
7
+ /** A value in its column's format: text, a tag for an option with a tone, a check for `true`. Empty values show a dash. */
8
+ export declare function TableCellValue<TRow extends TableRow>({ column, row, options }: {
9
+ column: TableColumn<TRow>;
10
+ row: TRow;
11
+ options: CellTextOptions;
12
+ }): import("react").JSX.Element;
13
+ /**
14
+ * A cell's own style: where a pinned column sits, and the width its values fit in. Once the user has set any width, a
15
+ * `<colgroup>` gives every column its width and the cells only cap their text.
16
+ */
17
+ export declare function columnStyle<TRow extends TableRow>(view: TableViewColumn<TRow>, sized: boolean): CSSProperties;
18
+ /** Where the table's own columns sit, and whether they stay while the rest scrolls. */
19
+ export interface TableFrameColumns {
20
+ /** The numbers and checkbox column: `null` when the table has neither. */
21
+ index: {
22
+ offset: number;
23
+ edge: boolean;
24
+ } | null;
25
+ actions: {
26
+ offset: number;
27
+ edge: boolean;
28
+ } | null;
29
+ }
30
+ /**
31
+ * The widths of the columns, once the user has changed one: the table then lays out its columns from this list
32
+ * (`table-layout: fixed`), so dragging one edge moves that edge only. The last column takes the space left over.
33
+ */
34
+ export declare function TableColumnGroup<TRow extends TableRow>({ columns, widths, frame, colRefs, }: {
35
+ columns: readonly TableViewColumn<TRow>[];
36
+ widths: Readonly<Record<string, number>>;
37
+ frame: TableFrameColumns;
38
+ colRefs: Map<string, HTMLTableColElement>;
39
+ }): import("react").JSX.Element;
40
+ /** The number of a row, its checkbox, or both: the number until the pointer is over the row or something is selected. */
41
+ export declare function TableIndexCell({ heading, own, number, numbered, selectable, checkbox, }: {
42
+ heading?: boolean;
43
+ own: {
44
+ offset: number;
45
+ edge: boolean;
46
+ } | null;
47
+ /** The row's number, or "#" in the heading. */
48
+ number?: ReactNode;
49
+ numbered: boolean;
50
+ selectable: boolean;
51
+ checkbox?: ReactNode;
52
+ }): import("react").JSX.Element;
53
+ export interface TableRowViewProps<TRow extends TableRow> {
54
+ row: TRow;
55
+ rowKey: string;
56
+ number: number;
57
+ label: string;
58
+ columns: readonly TableViewColumn<TRow>[];
59
+ cellOptions: CellTextOptions;
60
+ selectable: boolean;
61
+ selected: boolean;
62
+ /** No more rows can be selected, and this one is not. */
63
+ selectionFull: boolean;
64
+ busy: boolean;
65
+ flashed: boolean;
66
+ numbered: boolean;
67
+ /** A row of the pinned section above the page: its number is a pin. */
68
+ pinned?: boolean;
69
+ /** Where the table's own columns sit; `null` for the ones it does not have. */
70
+ frame: TableFrameColumns;
71
+ /** The user gave a column a width, so the table lays its columns out from the `<colgroup>`. */
72
+ sized: boolean;
73
+ actions: readonly TableRowAction<TRow>[] | null;
74
+ onToggle: (row: TRow, on: boolean, event: MouseEvent<HTMLInputElement>) => void;
75
+ onAction: (row: TRow, action: TableRowAction<TRow>) => void;
76
+ onOpen?: (row: TRow) => void;
77
+ }
78
+ /** One row. It renders again only when its row, its state, or the columns change. */
79
+ declare function TableRowViewInner<TRow extends TableRow>({ row, rowKey, number, label, columns, cellOptions, selectable, selected, selectionFull, busy, flashed, numbered, pinned, frame, sized, actions, onToggle, onAction, onOpen, }: TableRowViewProps<TRow>): import("react").JSX.Element;
80
+ export declare const TableRowView: typeof TableRowViewInner;
81
+ /**
82
+ * The head of the pinned section: one row across the table with a button that folds the pinned records open and shut,
83
+ * how many there are, and the most that can be pinned.
84
+ */
85
+ export declare function TablePinnedHead({ span, label, count, max, loading, open, onToggle }: {
86
+ span: number;
87
+ label: string;
88
+ count: number;
89
+ max?: number;
90
+ loading: boolean;
91
+ open: boolean;
92
+ onToggle: () => void;
93
+ }): import("react").JSX.Element;
94
+ /** Placeholder rows while the first rows load, in the shape of the columns. */
95
+ export declare function TableSkeletonRows({ count, cells, frame, sized }: {
96
+ count: number;
97
+ cells: number;
98
+ frame: TableFrameColumns;
99
+ sized: boolean;
100
+ }): import("react").JSX.Element;
101
+ /** A row across the table with a message: an empty list, no matches, a failed load. */
102
+ export declare function TableMessageRow({ span, icon, title, detail, tone, children }: {
103
+ span: number;
104
+ icon: IconNode;
105
+ title: ReactNode;
106
+ detail?: ReactNode;
107
+ tone?: "danger";
108
+ children?: ReactNode;
109
+ }): import("react").JSX.Element;
110
+ /** The pager: previous, the page buttons (1 … 5 6 7 … 24), next. */
111
+ export declare function TablePager({ page, matches, pageSize, disabled, onPage }: {
112
+ page: number;
113
+ matches: number;
114
+ pageSize: number;
115
+ disabled: boolean;
116
+ onPage: (page: number) => void;
117
+ }): import("react").JSX.Element | null;
118
+ /** Rows per page, as a menu of the choices. Inside the search box (`compact`) it shows only the number. */
119
+ export declare function TablePageSize({ pageSize, pageSizes, compact, onChange }: {
120
+ pageSize: number;
121
+ pageSizes: readonly number[];
122
+ compact?: boolean;
123
+ onChange: (size: number) => void;
124
+ }): import("react").JSX.Element | null;
125
+ /**
126
+ * Under the table: which rows show and how many the search left ("Showing 41–50 of 234 · filtered from 1,000"), the page
127
+ * of how many, and the pager.
128
+ */
129
+ export declare function TableFooter<TRow extends TableRow>({ state, disabled, onPage }: {
130
+ state: TableState<TRow>;
131
+ disabled: boolean;
132
+ onPage: (page: number) => void;
133
+ }): import("react").JSX.Element;
134
+ export {};
@@ -0,0 +1,145 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { iconCheck, iconChevronDown, iconChevronLeft, iconChevronRight, iconDotsVertical, iconLoader2, iconPin, InlineIcon } from "nexus-icons";
4
+ import { memo } from "react";
5
+ import { cx } from "../../Helpers/ClassHelpers.js";
6
+ import { columnAlign, columnOption, columnValue, cssLength, formatCellText, pageButtons, pageCount, TABLE_ACTIONS_COLUMN, TABLE_INDEX_COLUMN, } from "../../Helpers/TableHelpers.js";
7
+ import { Button } from "../Documents/Button.js";
8
+ import { Menu } from "../Documents/Menu.js";
9
+ /*
10
+ * The parts of a data table: a cell in its column's format, a row with its number and checkbox in one column and its
11
+ * actions, the widths of the columns the user set, the head of the pinned section, the pager, and the footer. The
12
+ * details view of the CRUD draws values with the same `TableCellValue`.
13
+ */
14
+ const countFormat = new Intl.NumberFormat("en-US");
15
+ /** A number as the table writes counts: 1,234. */
16
+ export const formatCount = (count) => countFormat.format(count);
17
+ /** A value in its column's format: text, a tag for an option with a tone, a check for `true`. Empty values show a dash. */
18
+ export function TableCellValue({ column, row, options }) {
19
+ const value = columnValue(column, row);
20
+ if (column.render)
21
+ return _jsx(_Fragment, { children: column.render(row, value) });
22
+ const option = columnOption(column, value);
23
+ if (option?.tone) {
24
+ return (_jsx("span", { className: "nx-table__tag", "data-tone": option.tone, children: option.label }));
25
+ }
26
+ if (column.format === "boolean" && !option) {
27
+ const on = value === true || value === "true" || value === 1;
28
+ return on ? (_jsxs("span", { className: "nx-table__yes", children: [_jsx(InlineIcon, { icon: iconCheck }), _jsx("span", { className: "nx-visually-hidden", children: "Yes" })] })) : (_jsx("span", { className: "nx-table__no", children: "No" }));
29
+ }
30
+ // A moment needs the browser's zone, unknown while the page hydrates: nothing shows until then, not another zone's time.
31
+ if (column.format === "date-time" && !options.timeZone && value)
32
+ return _jsx("span", { className: "nx-table__pending" });
33
+ const text = formatCellText(column, value, options);
34
+ if (!text)
35
+ return _jsx("span", { className: "nx-table__dash", children: "\u2014" });
36
+ return _jsx(_Fragment, { children: text });
37
+ }
38
+ /**
39
+ * A cell's own style: where a pinned column sits, and the width its values fit in. Once the user has set any width, a
40
+ * `<colgroup>` gives every column its width and the cells only cap their text.
41
+ */
42
+ export function columnStyle(view, sized) {
43
+ const style = {};
44
+ if (view.pin === "left")
45
+ style.left = view.offset;
46
+ else if (view.pin === "right")
47
+ style.right = view.offset;
48
+ if (sized) {
49
+ // The widths come from the colgroup now; the narrowest the column may become stays on the cell, for a resize to read.
50
+ style.minWidth = cssLength(view.column.minWidth);
51
+ style["--nx-col-max"] = "100%";
52
+ return style;
53
+ }
54
+ const width = cssLength(view.column.width);
55
+ style.width = width;
56
+ style.minWidth = cssLength(view.column.minWidth) ?? width;
57
+ style["--nx-col-max"] = width;
58
+ return style;
59
+ }
60
+ const ownStyle = (own, side) => (side === "left" ? { left: own?.offset ?? 0 } : { right: own?.offset ?? 0 });
61
+ /** What a column takes while the table lays out from its widths, when it has none of its own: a column shown again. */
62
+ const FALLBACK_COLUMN_WIDTH = "12rem";
63
+ /**
64
+ * The widths of the columns, once the user has changed one: the table then lays out its columns from this list
65
+ * (`table-layout: fixed`), so dragging one edge moves that edge only. The last column takes the space left over.
66
+ */
67
+ export function TableColumnGroup({ columns, widths, frame, colRefs, }) {
68
+ const hold = (key) => (element) => {
69
+ if (element)
70
+ colRefs.set(key, element);
71
+ else
72
+ colRefs.delete(key);
73
+ };
74
+ const own = (key, on) => on && _jsx("col", { ref: hold(key), style: { width: widths[key] } }, key);
75
+ return (_jsxs("colgroup", { children: [own(TABLE_INDEX_COLUMN, Boolean(frame.index)), columns.map(view => (_jsx("col", { ref: hold(view.column.key), style: { width: widths[view.column.key] ?? cssLength(view.column.width) ?? FALLBACK_COLUMN_WIDTH } }, view.column.key))), _jsx("col", { className: "nx-table__col-filler" }), own(TABLE_ACTIONS_COLUMN, Boolean(frame.actions))] }));
76
+ }
77
+ /** The number of a row, its checkbox, or both: the number until the pointer is over the row or something is selected. */
78
+ export function TableIndexCell({ heading, own, number, numbered, selectable, checkbox, }) {
79
+ const shared = {
80
+ className: cx(heading ? "nx-table__heading" : "nx-table__cell", "nx-table__cell--index"),
81
+ "data-col": TABLE_INDEX_COLUMN,
82
+ "data-pin": "left",
83
+ "data-pin-edge": own?.edge || undefined,
84
+ // Both in one cell: the number gives way to the checkbox under the pointer, and once anything is selected.
85
+ "data-swap": (numbered && selectable) || undefined,
86
+ style: ownStyle(own, "left"),
87
+ };
88
+ const content = (_jsxs(_Fragment, { children: [numbered && (_jsx("span", { className: "nx-table__number", "aria-hidden": selectable || undefined, children: number })), checkbox] }));
89
+ return heading ? (_jsx("th", { scope: "col", ...shared, children: content })) : (_jsx("td", { ...shared, children: content }));
90
+ }
91
+ /** One row. It renders again only when its row, its state, or the columns change. */
92
+ function TableRowViewInner({ row, rowKey, number, label, columns, cellOptions, selectable, selected, selectionFull, busy, flashed, numbered, pinned, frame, sized, actions, onToggle, onAction, onOpen, }) {
93
+ const inline = actions?.filter(action => action.inline && action.icon) ?? [];
94
+ const inMenu = actions?.filter(action => !(action.inline && action.icon)) ?? [];
95
+ const items = inMenu.map(action => ({ value: action.id, label: action.label, icon: action.icon, description: action.description, tone: action.tone, disabled: action.disabled }));
96
+ return (_jsxs("tr", { className: "nx-table__row", "data-key": rowKey, "data-pinned": pinned || undefined, "data-selected": selected || undefined, "data-busy": busy || undefined, "data-flash": flashed || undefined, "aria-busy": busy || undefined, onDoubleClick: onOpen &&
97
+ (event => {
98
+ if (event.target.closest("button, a, input, label, [role=menu]"))
99
+ return;
100
+ onOpen(row);
101
+ }), children: [frame.index && (_jsx(TableIndexCell, { own: frame.index, number: pinned ? _jsx(InlineIcon, { icon: iconPin, className: "nx-table__pin-mark" }) : formatCount(number), numbered: numbered || Boolean(pinned), selectable: selectable, checkbox: selectable && (_jsx("label", { className: "nx-choice nx-choice--sm nx-table__check", title: selectionFull ? "No more rows can be selected." : undefined, children: _jsx("input", { type: "checkbox", className: "nx-choice__control nx-choice__control--checkbox", checked: selected, disabled: selectionFull && !selected, "aria-label": `Select ${label}`, onClick: event => onToggle(row, event.currentTarget.checked, event), onChange: () => undefined }) })) })), columns.map(view => (_jsx("td", { className: cx("nx-table__cell", `nx-table__cell--${columnAlign(view.column)}`, view.column.wrap && "nx-table__cell--wrap"), "data-col": view.column.key, "data-pin": view.pin ?? undefined, "data-pin-edge": (view.pin && view.edge) || undefined, style: columnStyle(view, sized), children: _jsx("span", { className: "nx-table__value", children: _jsx(TableCellValue, { column: view.column, row: row, options: cellOptions }) }) }, view.column.key))), sized && _jsx("td", { className: "nx-table__cell nx-table__cell--filler" }), frame.actions && (_jsx("td", { className: "nx-table__cell nx-table__cell--actions", "data-col": TABLE_ACTIONS_COLUMN, "data-pin": "right", "data-pin-edge": frame.actions.edge || undefined, style: ownStyle(frame.actions, "right"), children: _jsxs("div", { className: "nx-table__actions", children: [inline.map(action => (_jsx(Button, { variant: "ghost", size: "sm", icon: action.icon, hoverTone: action.tone === "danger" ? "danger" : undefined, "aria-label": `${action.label}: ${label}`, title: action.label, "data-action": action.id, disabled: busy || action.disabled, onClick: () => onAction(row, action) }, action.id))), items.length > 0 && (_jsx(Menu, { items: items, align: "end", "aria-label": `Actions: ${label}`, onSelect: value => onAction(row, inMenu.find(action => action.id === value)), children: _jsx(Button, { variant: "ghost", size: "sm", icon: _jsx(InlineIcon, { icon: iconDotsVertical }), loading: busy, "aria-label": `More actions: ${label}`, title: "More actions" }) })), items.length === 0 && busy && _jsx(Button, { variant: "ghost", size: "sm", loading: true, "aria-label": `Working: ${label}` })] }) }))] }));
102
+ }
103
+ export const TableRowView = memo(TableRowViewInner);
104
+ /**
105
+ * The head of the pinned section: one row across the table with a button that folds the pinned records open and shut,
106
+ * how many there are, and the most that can be pinned.
107
+ */
108
+ export function TablePinnedHead({ span, label, count, max, loading, open, onToggle }) {
109
+ return (_jsx("tr", { className: "nx-table__row nx-table__pin-row", children: _jsx("td", { colSpan: span, className: "nx-table__pin-cell", children: _jsxs("button", { type: "button", className: "nx-table__pin-toggle", "aria-expanded": open, onClick: onToggle, "data-table-pins": true, children: [_jsx(InlineIcon, { icon: iconChevronRight, className: "nx-table__pin-caret" }), _jsx(InlineIcon, { icon: iconPin, className: "nx-table__pin-icon" }), _jsx("span", { className: "nx-table__pin-title", children: label }), (count > 0 || !loading) && (_jsx("span", { className: "nx-table__pin-count", children: max ? `${formatCount(count)} of ${formatCount(max)}` : formatCount(count) })), loading && _jsx(InlineIcon, { icon: iconLoader2, className: "nx-spin nx-table__pin-loading" })] }) }) }));
110
+ }
111
+ /** Placeholder rows while the first rows load, in the shape of the columns. */
112
+ export function TableSkeletonRows({ count, cells, frame, sized }) {
113
+ return (_jsx(_Fragment, { children: Array.from({ length: count }, (_, index) => (_jsxs("tr", { className: "nx-table__row nx-table__row--skeleton", "aria-hidden": "true", children: [frame.index && _jsx("td", { className: "nx-table__cell nx-table__cell--index", "data-pin": "left", style: ownStyle(frame.index, "left") }), Array.from({ length: cells }, (_, cell) => (_jsx("td", { className: "nx-table__cell", children: _jsx("span", { className: "nx-table__bone", style: { width: `${45 + ((index * 7 + cell * 13) % 45)}%` } }) }, cell))), sized && _jsx("td", { className: "nx-table__cell nx-table__cell--filler" }), frame.actions && _jsx("td", { className: "nx-table__cell nx-table__cell--actions", "data-pin": "right", style: ownStyle(frame.actions, "right") })] }, index))) }));
114
+ }
115
+ /** A row across the table with a message: an empty list, no matches, a failed load. */
116
+ export function TableMessageRow({ span, icon, title, detail, tone, children }) {
117
+ return (_jsx("tr", { className: "nx-table__row nx-table__row--message", children: _jsx("td", { colSpan: span, className: "nx-table__message-cell", children: _jsxs("div", { className: "nx-table__message", "data-tone": tone, role: tone === "danger" ? "alert" : undefined, children: [_jsx(InlineIcon, { icon: icon, className: "nx-table__message-icon" }), _jsx("p", { className: "nx-table__message-title", children: title }), detail && _jsx("p", { className: "nx-table__message-detail", children: detail }), children && _jsx("div", { className: "nx-table__message-actions", children: children })] }) }) }));
118
+ }
119
+ /** The pager: previous, the page buttons (1 … 5 6 7 … 24), next. */
120
+ export function TablePager({ page, matches, pageSize, disabled, onPage }) {
121
+ const pages = pageCount(matches, pageSize);
122
+ if (pages <= 1)
123
+ return null;
124
+ return (_jsxs("nav", { className: "nx-table__pager", "aria-label": "Pages", children: [_jsx(Button, { variant: "ghost", size: "sm", icon: _jsx(InlineIcon, { icon: iconChevronLeft }), "aria-label": "Previous page", disabled: disabled || page <= 1, onClick: () => onPage(page - 1) }), _jsx("span", { className: "nx-table__page-list", children: pageButtons(page, pages).map((entry, index) => entry === "gap" ? (_jsx("span", { className: "nx-table__page-gap", "aria-hidden": "true", children: "\u2026" }, `gap-${index}`)) : (_jsx("button", { type: "button", className: "nx-table__page", "aria-current": entry === page ? "page" : undefined, "aria-label": `Page ${entry}`, disabled: disabled && entry !== page, onClick: () => entry !== page && onPage(entry), children: formatCount(entry) }, entry))) }), _jsx(Button, { variant: "ghost", size: "sm", icon: _jsx(InlineIcon, { icon: iconChevronRight }), "aria-label": "Next page", disabled: disabled || page >= pages, onClick: () => onPage(page + 1) })] }));
125
+ }
126
+ /** Rows per page, as a menu of the choices. Inside the search box (`compact`) it shows only the number. */
127
+ export function TablePageSize({ pageSize, pageSizes, compact = false, onChange }) {
128
+ if (pageSizes.length < 2)
129
+ return null;
130
+ const items = pageSizes.map(size => ({ value: String(size), label: `${formatCount(size)} per page`, checked: size === pageSize }));
131
+ return (_jsx(Menu, { items: items, kind: "radio", size: "sm", align: compact ? "start" : "end", "aria-label": "Rows per page", onSelect: value => onChange(Number(value)), children: _jsx(Button, { variant: "ghost", size: "sm", iconEnd: _jsx(InlineIcon, { icon: iconChevronDown }), className: cx("nx-table__page-size", compact && "nx-table__page-size--field"), "aria-label": `Rows per page: ${pageSize}`, title: "Rows per page", children: compact ? formatCount(pageSize) : `${formatCount(pageSize)} / page` }) }));
132
+ }
133
+ /**
134
+ * Under the table: which rows show and how many the search left ("Showing 41–50 of 234 · filtered from 1,000"), the page
135
+ * of how many, and the pager.
136
+ */
137
+ export function TableFooter({ state, disabled, onPage }) {
138
+ const { status, rows, offset, matches, total, query } = state;
139
+ if (status !== "ready" || total === 0)
140
+ return _jsx("div", { className: "nx-table__footer" });
141
+ const first = rows.length ? offset + 1 : 0;
142
+ const last = offset + rows.length;
143
+ const pages = pageCount(matches, query.pageSize);
144
+ return (_jsxs("div", { className: "nx-table__footer", children: [_jsxs("p", { className: "nx-table__range", "aria-live": "polite", children: [rows.length ? (_jsxs(_Fragment, { children: ["Showing ", _jsx("b", { children: `${formatCount(first)}–${formatCount(last)}` }), " of ", _jsx("b", { children: formatCount(matches) })] })) : (_jsx(_Fragment, { children: "No rows on this page" })), query.search && matches !== total && _jsxs("span", { className: "nx-table__range-all", children: [" \u00B7 filtered from ", formatCount(total)] })] }), _jsxs("div", { className: "nx-table__paging", children: [_jsxs("span", { className: "nx-table__page-info", children: ["Page ", formatCount(query.page), " of ", formatCount(pages)] }), _jsx(TablePager, { page: query.page, matches: matches, pageSize: query.pageSize, disabled: disabled, onPage: onPage })] })] }));
145
+ }
@@ -0,0 +1,26 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
2
+ /** Which links open in a new tab: links to other sites (`external`), `all`, or `none`. */
3
+ export type MarkdownLinkTarget = "external" | "all" | "none";
4
+ export interface MarkdownViewProps extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
5
+ /** The Markdown text. */
6
+ value: string;
7
+ /** Every line break inside a paragraph shows as a line break, as in GitHub comments. Default true. */
8
+ breaks?: boolean;
9
+ /** Which links open in a new tab. Default `external`. */
10
+ newTab?: MarkdownLinkTarget;
11
+ /** Shown when the text is empty. */
12
+ placeholder?: ReactNode;
13
+ /**
14
+ * Called when a task box is clicked, with the line of its marker (from 0) and its new state; see `toggleMarkdownTask`.
15
+ * Without it, task boxes are read-only.
16
+ */
17
+ onTaskToggle?: (line: number, checked: boolean) => void;
18
+ }
19
+ /**
20
+ * Shows Markdown as formatted text: headings, lists, tasks, tables, code, quotes, links, and images. Raw HTML stays
21
+ * text and unsafe addresses are dropped, so it is safe for text from any user. It has no state, so it renders on the
22
+ * server as well.
23
+ *
24
+ * @example <MarkdownView value={room.description} />
25
+ */
26
+ export declare function MarkdownView({ value, breaks, newTab, placeholder, onTaskToggle, className, ...rest }: MarkdownViewProps): import("react").JSX.Element;
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cx } from "../../Helpers/ClassHelpers.js";
3
+ import { parseMarkdown } from "../../Helpers/MarkdownHelpers.js";
4
+ /**
5
+ * Shows Markdown as formatted text: headings, lists, tasks, tables, code, quotes, links, and images. Raw HTML stays
6
+ * text and unsafe addresses are dropped, so it is safe for text from any user. It has no state, so it renders on the
7
+ * server as well.
8
+ *
9
+ * @example <MarkdownView value={room.description} />
10
+ */
11
+ export function MarkdownView({ value, breaks = true, newTab = "external", placeholder, onTaskToggle, className, ...rest }) {
12
+ const blocks = parseMarkdown(value, { breaks });
13
+ return (_jsx("div", { ...rest, className: cx("nx-markdown", className), children: blocks.length > 0 ? renderBlocks(blocks, { newTab, onTaskToggle }) : placeholder && _jsx("p", { className: "nx-markdown__empty", children: placeholder }) }));
14
+ }
15
+ function renderBlocks(blocks, options, tight = false) {
16
+ return blocks.map((block, key) => {
17
+ switch (block.type) {
18
+ case "heading": {
19
+ const Heading = `h${block.level}`;
20
+ return _jsx(Heading, { children: renderInlines(block.children, options) }, key);
21
+ }
22
+ case "paragraph":
23
+ // Items of a tight list hold their text without paragraph spacing.
24
+ return tight ? _jsx("span", { children: renderInlines(block.children, options) }, key) : _jsx("p", { children: renderInlines(block.children, options) }, key);
25
+ case "code":
26
+ return (_jsx("pre", { children: _jsx("code", { className: block.language ? `language-${block.language.replace(/[^\w#+.-]/g, "")}` : undefined, children: block.text }) }, key));
27
+ case "quote":
28
+ return _jsx("blockquote", { children: renderBlocks(block.children, options) }, key);
29
+ case "list": {
30
+ const List = block.ordered ? "ol" : "ul";
31
+ return (_jsx(List, { start: block.ordered && block.start !== 1 ? block.start : undefined, children: block.items.map((item, index) => renderItem(item, index, options, block.tight)) }, key));
32
+ }
33
+ case "table":
34
+ return (_jsx("div", { className: "nx-markdown__table", children: _jsxs("table", { children: [_jsx("thead", { children: _jsx("tr", { children: block.head.map((cell, index) => (_jsx("th", { scope: "col", style: block.align[index] ? { textAlign: block.align[index] } : undefined, children: renderInlines(cell.children, options) }, index))) }) }), block.rows.length > 0 && (_jsx("tbody", { children: block.rows.map((row, rowIndex) => (_jsx("tr", { children: row.map((cell, index) => (_jsx("td", { style: block.align[index] ? { textAlign: block.align[index] } : undefined, children: renderInlines(cell.children, options) }, index))) }, rowIndex))) }))] }) }, key));
35
+ case "rule":
36
+ return _jsx("hr", {}, key);
37
+ }
38
+ });
39
+ }
40
+ function renderItem(item, key, options, tight) {
41
+ if (item.checked === null)
42
+ return _jsx("li", { children: renderBlocks(item.children, options, tight) }, key);
43
+ const { onTaskToggle } = options;
44
+ const first = item.children[0];
45
+ const label = first && (first.type === "paragraph" || first.type === "heading") ? plainText(first.children) : undefined;
46
+ return (_jsxs("li", { className: "nx-markdown__task", children: [_jsx("input", { type: "checkbox", checked: item.checked, disabled: !onTaskToggle, "aria-label": label || "Task", onChange: onTaskToggle ? () => onTaskToggle(item.line, !item.checked) : undefined }), renderBlocks(item.children, options, tight)] }, key));
47
+ }
48
+ function renderInlines(nodes, options) {
49
+ return nodes.map((node, key) => {
50
+ switch (node.type) {
51
+ case "text":
52
+ return node.text;
53
+ case "strong":
54
+ return _jsx("strong", { children: renderInlines(node.children, options) }, key);
55
+ case "emphasis":
56
+ return _jsx("em", { children: renderInlines(node.children, options) }, key);
57
+ case "strike":
58
+ return _jsx("del", { children: renderInlines(node.children, options) }, key);
59
+ case "code":
60
+ return _jsx("code", { children: node.text }, key);
61
+ case "break":
62
+ return _jsx("br", {}, key);
63
+ case "image":
64
+ return node.src === null ? (_jsx("span", { children: node.alt }, key)) : (_jsx("img", { src: node.src, alt: node.alt, title: node.title, loading: "lazy", decoding: "async" }, key));
65
+ case "link": {
66
+ const children = renderInlines(node.children, options);
67
+ if (node.href === null)
68
+ return _jsx("span", { children: children }, key);
69
+ // Links to other sites carry no referrer and no endorsement for search engines, since any user may write them.
70
+ const external = /^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(node.href);
71
+ const newTab = options.newTab === "all" || (options.newTab === "external" && external);
72
+ return (_jsx("a", { href: node.href, title: node.title, target: newTab ? "_blank" : undefined, rel: external ? "nofollow noopener noreferrer" : newTab ? "noopener noreferrer" : undefined, children: children }, key));
73
+ }
74
+ }
75
+ });
76
+ }
77
+ function plainText(nodes) {
78
+ return nodes.map(node => (node.type === "text" || node.type === "code" ? node.text : node.type === "image" ? node.alt : node.type === "break" ? " " : plainText(node.children))).join("");
79
+ }
@@ -0,0 +1,18 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
2
+ import { type RichTextRenderOptions } from "../../Helpers/RichTextHelpers.ts";
3
+ export interface RichTextViewProps extends Omit<ComponentPropsWithoutRef<"div">, "children" | "dangerouslySetInnerHTML">, Omit<RichTextRenderOptions, "newTab"> {
4
+ /** The HTML, as a rich text editor stored it. It is sanitized again here, so HTML from anywhere is safe to show. */
5
+ value: string | null | undefined;
6
+ /** Links to other sites open in a new tab. Default true. */
7
+ newTab?: boolean;
8
+ /** Shown when there is nothing to show. */
9
+ placeholder?: ReactNode;
10
+ }
11
+ /**
12
+ * Shows rich text: the HTML a `RichTextEditor` made, sanitized again and styled like the editor. Tokens are filled
13
+ * from `values` when given, e.g. to preview a template with sample data. No state and no effects, so it renders in
14
+ * server components too.
15
+ *
16
+ * @example <RichTextView value={room.description} />
17
+ */
18
+ export declare function RichTextView({ value, newTab, placeholder, images, tokenFormat, values, className, ...rest }: RichTextViewProps): import("react").JSX.Element | null;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cx } from "../../Helpers/ClassHelpers.js";
3
+ import { renderRichTextHtml } from "../../Helpers/RichTextHelpers.js";
4
+ /**
5
+ * Shows rich text: the HTML a `RichTextEditor` made, sanitized again and styled like the editor. Tokens are filled
6
+ * from `values` when given, e.g. to preview a template with sample data. No state and no effects, so it renders in
7
+ * server components too.
8
+ *
9
+ * @example <RichTextView value={room.description} />
10
+ */
11
+ export function RichTextView({ value, newTab = true, placeholder, images, tokenFormat, values, className, ...rest }) {
12
+ const html = renderRichTextHtml(value, { newTab, images, tokenFormat, values });
13
+ if (!html) {
14
+ return placeholder ? (_jsx("div", { ...rest, className: cx("nx-richtext", className), children: _jsx("p", { className: "nx-richtext__empty", children: placeholder }) })) : null;
15
+ }
16
+ return _jsx("div", { ...rest, className: cx("nx-richtext", className), dangerouslySetInnerHTML: { __html: html } });
17
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Calls `done` once the element's CSS animation `name` has finished, or at once when the element runs no animation of
3
+ * that name. Call it after the class that starts the animation is on the element, e.g. in a layout effect.
4
+ * Returns a function that cancels the wait.
5
+ */
6
+ export declare function afterAnimation(element: Element, name: string, done: () => void): () => void;
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Exit animations. A closing element gets a class that starts a CSS animation, and the next step (closing a dialog,
3
+ * removing a toast) waits for it. When no animation runs, the step must not wait: with reduced motion (which Windows
4
+ * reports when its animations are turned off) or when a theme sets `animation: none`.
5
+ */
6
+ /**
7
+ * Calls `done` once the element's CSS animation `name` has finished, or at once when the element runs no animation of
8
+ * that name. Call it after the class that starts the animation is on the element, e.g. in a layout effect.
9
+ * Returns a function that cancels the wait.
10
+ */
11
+ export function afterAnimation(element, name, done) {
12
+ const animation = typeof element.getAnimations === "function" ? element.getAnimations().find(item => item.animationName === name) : undefined;
13
+ if (!animation) {
14
+ done();
15
+ return () => undefined;
16
+ }
17
+ let waiting = true;
18
+ let timer = 0;
19
+ const finish = () => {
20
+ if (!waiting)
21
+ return;
22
+ waiting = false;
23
+ window.clearTimeout(timer);
24
+ done();
25
+ };
26
+ // A safety net for a timeline that stops, as in a hidden tab: the animation's own length, and a little more.
27
+ const end = Number(animation.effect?.getComputedTiming().endTime);
28
+ timer = window.setTimeout(finish, (Number.isFinite(end) ? end : 0) + 100);
29
+ // Rejects when the animation is cancelled, e.g. the popup opens again; the caller cancels the wait then.
30
+ animation.finished.then(finish, () => undefined);
31
+ return () => {
32
+ waiting = false;
33
+ window.clearTimeout(timer);
34
+ };
35
+ }
@@ -0,0 +1,74 @@
1
+ import type { ApiCallOptions, ApiEndpoint, ApiResult, ApiTarget, HttpMethod } from "../Interfaces/ApiInterfaces.ts";
2
+ import type { MessageActionName, MessageContext } from "../Interfaces/MessageInterfaces.ts";
3
+ /** One call, as a client's hooks see it. */
4
+ export interface ApiCall<TOptions = object> {
5
+ target: ApiTarget;
6
+ /** The endpoint, when the target is one. */
7
+ endpoint?: ApiEndpoint;
8
+ method: HttpMethod;
9
+ /** The full URL; empty while it is not known yet, or when it could not be built. */
10
+ url: string;
11
+ options: ApiCallOptions & TOptions;
12
+ /** What the call does and acts on, for its messages. */
13
+ context: MessageContext;
14
+ }
15
+ export interface ApiClientConfig<TOptions = object> {
16
+ /** The full URL of an endpoint, given its filled path: through the proxy in the browser, the module's root on a server. */
17
+ resolveUrl: (endpoint: ApiEndpoint, path: string, call: ApiCall<TOptions>) => string | Promise<string>;
18
+ /** The full URL of a plain URL target. Default: as it is. */
19
+ resolveTarget?: (url: string, call: ApiCall<TOptions>) => string | Promise<string>;
20
+ /** Headers on every call, such as the tenant or branch. */
21
+ headers?: (call: ApiCall<TOptions>) => Record<string, string> | undefined | Promise<Record<string, string> | undefined>;
22
+ /** A bearer token for every call. */
23
+ token?: (call: ApiCall<TOptions>) => string | null | undefined | Promise<string | null | undefined>;
24
+ /** Milliseconds to wait for an answer. Default 60,000. */
25
+ timeout?: number;
26
+ credentials?: RequestCredentials;
27
+ /** Changes the request just before it is sent, such as Next.js caching on a server. */
28
+ prepare?: (init: RequestInit, call: ApiCall<TOptions>) => RequestInit;
29
+ /**
30
+ * Sends a GET only once while the same one runs, and gives every caller its answer. Only where every call is the same
31
+ * user's (the browser): on a server, callers are different users.
32
+ */
33
+ dedupe?: boolean;
34
+ /** Before a call is sent, such as a loading toast. May return a function that gets the answer. */
35
+ onStart?: (call: ApiCall<TOptions>) => ((result: ApiResult) => void) | void;
36
+ /** After every answer: toasts in the browser, logs on a server. */
37
+ onResult?: (result: ApiResult, call: ApiCall<TOptions>) => void;
38
+ /** The `fetch` to use. Default: the global one, looked up on each call. */
39
+ fetch?: typeof fetch;
40
+ }
41
+ type Options<TOptions> = ApiCallOptions & TOptions;
42
+ export interface ApiClient<TOptions = object> {
43
+ /** Sends a call with the endpoint's method (or `options.method`). */
44
+ send<T = unknown>(target: ApiTarget, options?: Options<TOptions>): Promise<ApiResult<T>>;
45
+ get<T = unknown>(target: ApiTarget, options?: Omit<Options<TOptions>, "body" | "method">): Promise<ApiResult<T>>;
46
+ post<T = unknown>(target: ApiTarget, body?: unknown, options?: Omit<Options<TOptions>, "body" | "method">): Promise<ApiResult<T>>;
47
+ put<T = unknown>(target: ApiTarget, body?: unknown, options?: Omit<Options<TOptions>, "body" | "method">): Promise<ApiResult<T>>;
48
+ patch<T = unknown>(target: ApiTarget, body?: unknown, options?: Omit<Options<TOptions>, "body" | "method">): Promise<ApiResult<T>>;
49
+ /** A DELETE; ids for a batch go in `options.body`. */
50
+ delete<T = unknown>(target: ApiTarget, options?: Omit<Options<TOptions>, "method">): Promise<ApiResult<T>>;
51
+ /** The URL a call would go to, for links and downloads. Throws when it cannot be built. */
52
+ url(target: ApiTarget, options?: Pick<ApiCallOptions, "params" | "query" | "body">): Promise<string>;
53
+ }
54
+ export declare const DEFAULT_API_TIMEOUT = 60000;
55
+ /** What a call does when it names nothing: GET loads, DELETE deletes, the rest save. */
56
+ export declare function defaultAction(method: HttpMethod): MessageActionName;
57
+ /** What a call does and acts on: its endpoint, its method, and the context its messages are built from. */
58
+ export declare function apiCallContext(target: ApiTarget, options?: Pick<ApiCallOptions, "method" | "action" | "subject" | "count" | "plural">): {
59
+ endpoint?: ApiEndpoint;
60
+ method: HttpMethod;
61
+ context: MessageContext;
62
+ };
63
+ /**
64
+ * Whether an error is a framework's own signal passing through a call, never a failed request: Next.js throws one from
65
+ * `headers()`, `cookies()`, or a `no-store` fetch while it prerenders, to learn that a page renders per request (and
66
+ * for `redirect()` and `notFound()`). Each carries a `digest`, or React's `$typeof`. The engine throws them on.
67
+ */
68
+ export declare function isFrameworkError(error: unknown): boolean;
69
+ /**
70
+ * Makes an API client. Apps use the two made here, `api` (browser) and `serverApi` (server); make another for an API
71
+ * that is not a Nexus module.
72
+ */
73
+ export declare function createApiClient<TOptions extends object = object>(config: ApiClientConfig<TOptions>): ApiClient<TOptions>;
74
+ export {};