nexus-shared 3.0.0 → 3.2.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.
- package/CHANGELOG.md +442 -0
- package/README.md +1123 -1000
- package/dist/Client.Index.d.ts +6 -0
- package/dist/Client.Index.js +6 -0
- package/dist/Components/Chats/ChatParts.d.ts +2 -2
- package/dist/Components/Chats/ChatParts.js +3 -7
- package/dist/Components/Chats/ChatThread.js +3 -3
- package/dist/Components/Documents/Button.d.ts +6 -1
- package/dist/Components/Documents/Button.js +2 -2
- package/dist/Components/Documents/Menu.js +21 -9
- package/dist/Components/Documents/SplitButton.d.ts +3 -1
- package/dist/Components/Documents/SplitButton.js +7 -5
- package/dist/Components/Documents/TabButtons.d.ts +5 -2
- package/dist/Components/Documents/TabButtons.js +2 -2
- package/dist/Components/Forms/ApiForm.d.ts +1 -1
- package/dist/Components/Forms/ApiForm.js +1 -1
- package/dist/Components/Forms/Crud.js +486 -206
- package/dist/Components/Forms/CrudHistory.d.ts +66 -0
- package/dist/Components/Forms/CrudHistory.js +140 -0
- package/dist/Components/Forms/CrudParts.d.ts +5 -1
- package/dist/Components/Forms/CrudParts.js +38 -5
- package/dist/Components/Forms/ExcelImport.d.ts +23 -7
- package/dist/Components/Forms/ExcelImport.js +189 -60
- package/dist/Components/Forms/Form.js +9 -14
- package/dist/Components/Forms/SubmitForm.d.ts +11 -2
- package/dist/Components/Forms/SubmitForm.js +23 -12
- package/dist/Components/Inputs/CodeBox.d.ts +69 -0
- package/dist/Components/Inputs/CodeBox.js +316 -0
- package/dist/Components/Inputs/DatePicker.js +4 -1
- package/dist/Components/Inputs/DateRangePicker.js +4 -1
- package/dist/Components/Inputs/DateTimePicker.js +4 -1
- package/dist/Components/Inputs/Dropdown.js +4 -1
- package/dist/Components/Inputs/DropdownParts.d.ts +1 -1
- package/dist/Components/Inputs/DropdownParts.js +4 -6
- package/dist/Components/Inputs/InputRenderer.js +3 -0
- package/dist/Components/Inputs/NumberBox.js +26 -2
- package/dist/Components/Inputs/RowsInput.js +2 -2
- package/dist/Components/Inputs/Slider.js +4 -1
- package/dist/Components/Inputs/TabularForm.js +42 -10
- package/dist/Components/Inputs/TextArea.js +4 -1
- package/dist/Components/Inputs/TextBox.js +4 -1
- package/dist/Components/Inputs/TimePanel.js +4 -3
- package/dist/Components/Inputs/TimePicker.js +4 -1
- package/dist/Components/Inputs/TreeView.d.ts +55 -5
- package/dist/Components/Inputs/TreeView.js +372 -23
- package/dist/Components/Layouts/Popup.js +1 -4
- package/dist/Components/Layouts/ThemePicker.d.ts +21 -3
- package/dist/Components/Layouts/ThemePicker.js +89 -6
- package/dist/Components/Layouts/ThemeScript.d.ts +4 -2
- package/dist/Components/Layouts/ThemeScript.js +4 -2
- package/dist/Components/Layouts/ThemeSwitcher.d.ts +6 -3
- package/dist/Components/Layouts/ThemeSwitcher.js +9 -8
- package/dist/Components/Viewers/Avatar.d.ts +21 -0
- package/dist/Components/Viewers/Avatar.js +21 -0
- package/dist/Components/Viewers/DataTable.js +252 -62
- package/dist/Components/Viewers/DataTableColumns.d.ts +7 -3
- package/dist/Components/Viewers/DataTableColumns.js +25 -68
- package/dist/Components/Viewers/DataTableFilters.d.ts +21 -0
- package/dist/Components/Viewers/DataTableFilters.js +68 -0
- package/dist/Components/Viewers/DataTableParts.d.ts +28 -10
- package/dist/Components/Viewers/DataTableParts.js +42 -13
- package/dist/Helpers/AnimationHelpers.d.ts +11 -0
- package/dist/Helpers/AnimationHelpers.js +20 -2
- package/dist/Helpers/ApiModules.d.ts +3 -34
- package/dist/Helpers/ApiModules.js +3 -3
- package/dist/Helpers/ApiRoutes.d.ts +68 -26
- package/dist/Helpers/ApiRoutes.js +31 -27
- package/dist/Helpers/ArrayHelpers.d.ts +0 -0
- package/dist/Helpers/ArrayHelpers.js +2 -0
- package/dist/Helpers/CodeHelpers.d.ts +97 -0
- package/dist/Helpers/CodeHelpers.js +332 -0
- package/dist/Helpers/CrudBackend.d.ts +101 -8
- package/dist/Helpers/CrudBackend.js +172 -11
- package/dist/Helpers/CrudColumns.d.ts +51 -0
- package/dist/Helpers/CrudColumns.js +69 -0
- package/dist/Helpers/CrudHelpers.d.ts +50 -5
- package/dist/Helpers/CrudHelpers.js +109 -12
- package/dist/Helpers/ExcelBackend.d.ts +3 -3
- package/dist/Helpers/ExcelBackend.js +8 -2
- package/dist/Helpers/ExcelHelpers.d.ts +36 -8
- package/dist/Helpers/ExcelHelpers.js +55 -13
- package/dist/Helpers/FormStore.d.ts +9 -5
- package/dist/Helpers/FormStore.js +25 -5
- package/dist/Helpers/InputParamsHelpers.js +8 -0
- package/dist/Helpers/MessageBuilder.js +3 -0
- package/dist/Helpers/NexusHelpers.d.ts +0 -0
- package/dist/Helpers/NexusHelpers.js +1 -0
- package/dist/Helpers/NumberHelpers.d.ts +7 -1
- package/dist/Helpers/NumberHelpers.js +41 -3
- package/dist/Helpers/PopoverHelpers.d.ts +17 -5
- package/dist/Helpers/PopoverHelpers.js +52 -17
- package/dist/Helpers/PopoverHooks.d.ts +24 -0
- package/dist/Helpers/PopoverHooks.js +62 -0
- package/dist/Helpers/RequestCache.d.ts +35 -0
- package/dist/Helpers/RequestCache.js +113 -0
- package/dist/Helpers/RowsStore.d.ts +7 -2
- package/dist/Helpers/RowsStore.js +15 -3
- package/dist/Helpers/TableFilters.d.ts +25 -0
- package/dist/Helpers/TableFilters.js +162 -0
- package/dist/Helpers/TableHelpers.d.ts +7 -4
- package/dist/Helpers/TableHelpers.js +15 -6
- package/dist/Helpers/TableJoins.d.ts +70 -0
- package/dist/Helpers/TableJoins.js +250 -0
- package/dist/Helpers/TableStore.d.ts +16 -3
- package/dist/Helpers/TableStore.js +25 -5
- package/dist/Helpers/ThemeHelpers.d.ts +21 -4
- package/dist/Helpers/ThemeHelpers.js +46 -9
- package/dist/Helpers/TreeStore.d.ts +225 -11
- package/dist/Helpers/TreeStore.js +683 -90
- package/dist/Helpers/UserPreferences.d.ts +22 -0
- package/dist/Helpers/UserPreferences.js +116 -0
- package/dist/Interfaces/CrudInterfaces.d.ts +67 -10
- package/dist/Interfaces/ExcelInterfaces.d.ts +12 -0
- package/dist/Interfaces/FormInterfaces.d.ts +37 -6
- package/dist/Interfaces/InputInterfaces.d.ts +24 -0
- package/dist/Interfaces/MessageInterfaces.d.ts +1 -1
- package/dist/Interfaces/PreferenceInterfaces.d.ts +51 -0
- package/dist/Interfaces/PreferenceInterfaces.js +25 -0
- package/dist/Interfaces/TableInterfaces.d.ts +145 -16
- package/dist/Interfaces/ThemeInterfaces.d.ts +25 -0
- package/dist/Interfaces/ThemeInterfaces.js +15 -0
- package/dist/Services/ApiProxy.d.ts +36 -1
- package/dist/Services/ApiProxy.js +182 -52
- package/dist/Services/ApiProxyRules.d.ts +203 -0
- package/dist/Services/ApiProxyRules.js +426 -0
- package/dist/Services/ExcelApi.d.ts +3 -1
- package/dist/Services/ExcelApi.js +1 -1
- package/dist/Services/JoinSources.d.ts +48 -0
- package/dist/Services/JoinSources.js +74 -0
- package/dist/Services/ServerApi.d.ts +13 -2
- package/dist/Services/ServerApi.js +8 -3
- package/dist/Services/ThemeService.d.ts +18 -2
- package/dist/Services/ThemeService.js +80 -16
- package/dist/Shared.Index.d.ts +6 -0
- package/dist/Shared.Index.js +6 -0
- package/package.json +4 -2
- package/src/Styles/Nexus.Avatar.css +79 -0
- package/src/Styles/Nexus.Base.css +51 -4
- package/src/Styles/Nexus.Button.css +27 -0
- package/src/Styles/Nexus.Calendar.css +4 -6
- package/src/Styles/Nexus.Chat.css +5 -51
- package/src/Styles/Nexus.Choice.css +4 -6
- package/src/Styles/Nexus.Crud.css +16 -9
- package/src/Styles/Nexus.Dropdown.css +12 -61
- package/src/Styles/Nexus.Editor.css +4 -6
- package/src/Styles/Nexus.Excel.css +34 -15
- package/src/Styles/Nexus.Form.css +25 -67
- package/src/Styles/Nexus.Index.css +1 -0
- package/src/Styles/Nexus.Input.css +794 -637
- package/src/Styles/Nexus.Markdown.css +0 -28
- package/src/Styles/Nexus.Menu.css +8 -30
- package/src/Styles/Nexus.Popup.css +22 -29
- package/src/Styles/Nexus.RichText.css +2 -32
- package/src/Styles/Nexus.Rows.css +51 -10
- package/src/Styles/Nexus.Slider.css +3 -5
- package/src/Styles/Nexus.Tab.Buttons.css +20 -7
- package/src/Styles/Nexus.Table.css +1387 -1296
- package/src/Styles/Nexus.Theme.Picker.css +342 -232
- package/src/Styles/Nexus.Time.css +9 -12
- package/src/Styles/Nexus.Toast.css +6 -8
- package/src/Styles/Nexus.Tokens.css +17 -0
- package/src/Styles/Nexus.Tree.css +76 -11
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import type { IconNode } from "nexus-icons";
|
|
1
2
|
import type { CSSProperties, ReactNode, Ref } from "react";
|
|
2
3
|
import type { TableStore } from "../Helpers/TableStore.ts";
|
|
4
|
+
import type { ApiEndpoint } from "./ApiInterfaces.ts";
|
|
3
5
|
import type { ExcelEndpoints } from "./ExcelInterfaces.ts";
|
|
6
|
+
import type { InputParams } from "./FormInterfaces.ts";
|
|
4
7
|
import type { Size, Tone } from "./TypeInterfaces.ts";
|
|
5
8
|
/** A row's id: its `rowKey` field, such as `id`. */
|
|
6
9
|
export type TableKey = string | number;
|
|
@@ -15,6 +18,11 @@ export interface TableColumnOption {
|
|
|
15
18
|
/** Draws the value as a tag with a dot of this color. */
|
|
16
19
|
tone?: Tone;
|
|
17
20
|
}
|
|
21
|
+
/** A short tag after a cell's value (`TableColumn.tag`): its words and the color of its dot. */
|
|
22
|
+
export interface TableTag {
|
|
23
|
+
label: string;
|
|
24
|
+
tone?: Tone;
|
|
25
|
+
}
|
|
18
26
|
/** One column: which field it shows, how, and what the user can do with it. */
|
|
19
27
|
export interface TableColumn<TRow extends TableRow = TableRow> {
|
|
20
28
|
/** The field: `"name"`, or a path into the row, `"guest.name"`. It is also the column's id and its sort name. */
|
|
@@ -64,6 +72,8 @@ export interface TableColumn<TRow extends TableRow = TableRow> {
|
|
|
64
72
|
hideable?: boolean;
|
|
65
73
|
/** Long text wraps onto more lines instead of ending in "…". */
|
|
66
74
|
wrap?: boolean;
|
|
75
|
+
/** Its text is Markdown: the table shows the text, and a record's details show it formatted. */
|
|
76
|
+
markdown?: boolean;
|
|
67
77
|
/** The user can drag the heading to another place, or move it from its menu. Default true. */
|
|
68
78
|
movable?: boolean;
|
|
69
79
|
/** The user can drag the edge of the heading to change the width. Default true; `false` for a column that must keep its width. */
|
|
@@ -72,6 +82,44 @@ export interface TableColumn<TRow extends TableRow = TableRow> {
|
|
|
72
82
|
pinnable?: boolean;
|
|
73
83
|
/** Pinned before the user pins anything: `left` keeps it at the start, `right` at the end. */
|
|
74
84
|
pinned?: TablePinSide;
|
|
85
|
+
/**
|
|
86
|
+
* The value is another record's, looked up by the key this row holds: a country's sub-region named from the
|
|
87
|
+
* sub-regions' `FindListing`. The table collects every key its rows hold, asks once for the ones it has not got, keeps
|
|
88
|
+
* the answers for every table on the page, and shows the field once they are in - searched and sorted like any other
|
|
89
|
+
* column. A key the source does not answer shows as "Not found". (A join the database already made needs none of
|
|
90
|
+
* this: the row carries the name, and `tag` reads its status.)
|
|
91
|
+
*/
|
|
92
|
+
join?: TableJoin;
|
|
93
|
+
/**
|
|
94
|
+
* A short tag after the value: "Trashed" beside a parent that is in the trash. Given the row and, on a `join` column,
|
|
95
|
+
* the record it looked up; nothing when it answers nothing. `crudColumns.dbJoin` and `crudColumns.clientJoin` set it.
|
|
96
|
+
*/
|
|
97
|
+
tag?: (row: TRow, joined?: TableJoinedRecord) => TableTag | null | undefined;
|
|
98
|
+
}
|
|
99
|
+
/** A record a `join` looked up: whatever its source answers for one key. */
|
|
100
|
+
export type TableJoinedRecord = Readonly<Record<string, unknown>>;
|
|
101
|
+
/** Where a `join` looks records up: the records behind a set of keys, in any status. */
|
|
102
|
+
export interface TableJoinSource {
|
|
103
|
+
/** One name per source. Every column and table that names it shares its answers and its calls. */
|
|
104
|
+
readonly name: string;
|
|
105
|
+
/** The records behind these keys; a key with no record is left out. One call for every key the page needs at once. */
|
|
106
|
+
load(keys: readonly string[], signal: AbortSignal): Promise<readonly TableJoinedRecord[]>;
|
|
107
|
+
/** The field of a loaded record that holds its key. Default `id`. */
|
|
108
|
+
readonly key?: string;
|
|
109
|
+
/** How long an answer is kept, in milliseconds, before it is asked again. Default 5 minutes. */
|
|
110
|
+
readonly lifetime?: number;
|
|
111
|
+
}
|
|
112
|
+
/** A column whose value is another record's (`TableColumn.join`). */
|
|
113
|
+
export interface TableJoin {
|
|
114
|
+
/** The field of this row that holds the other record's key: `"subRegionId"`. */
|
|
115
|
+
from: string;
|
|
116
|
+
/** The field of the other record the column shows. Default: the column's own `key`. */
|
|
117
|
+
field?: string;
|
|
118
|
+
/**
|
|
119
|
+
* Where the records come from: an endpoint the keys are POSTed to as an array (a Nexus controller's `findListing`),
|
|
120
|
+
* or a source of the page's own.
|
|
121
|
+
*/
|
|
122
|
+
source: ApiEndpoint | TableJoinSource;
|
|
75
123
|
}
|
|
76
124
|
/** Which side a pinned column stays on while the others scroll. */
|
|
77
125
|
export type TablePinSide = "left" | "right";
|
|
@@ -81,7 +129,13 @@ export interface TableSort {
|
|
|
81
129
|
key: string;
|
|
82
130
|
direction: TableSortDirection;
|
|
83
131
|
}
|
|
84
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* The advanced filter's values, by input name: only the inputs that hold a value, in the order of the inputs, so the
|
|
134
|
+
* same filters always serialize the same way (a cache key, a request). A date range is its pair ["2026-10-01", null],
|
|
135
|
+
* a range slider [2, 7], a multiple choice its list, a ticked checkbox `true`.
|
|
136
|
+
*/
|
|
137
|
+
export type TableFilters = Readonly<Record<string, unknown>>;
|
|
138
|
+
/** What the table shows: the search, the filters, the sort, and the page. */
|
|
85
139
|
export interface TableQuery {
|
|
86
140
|
/** The search text, trimmed. */
|
|
87
141
|
search: string;
|
|
@@ -89,13 +143,18 @@ export interface TableQuery {
|
|
|
89
143
|
/** The page, from 1. */
|
|
90
144
|
page: number;
|
|
91
145
|
pageSize: number;
|
|
146
|
+
/**
|
|
147
|
+
* The advanced filter while any input holds a value; absent otherwise. A client table matches its rows; a server
|
|
148
|
+
* table's loader receives the raw values (`filterRequest` gives them in a server's names).
|
|
149
|
+
*/
|
|
150
|
+
filters?: TableFilters;
|
|
92
151
|
}
|
|
93
152
|
/** One page of rows, as a server sends it. */
|
|
94
153
|
export interface TablePage<TRow extends TableRow = TableRow> {
|
|
95
154
|
rows: readonly TRow[];
|
|
96
155
|
/** Every row there is. Default: the rows given. */
|
|
97
156
|
total?: number;
|
|
98
|
-
/** The rows that match the search. Default: `total`. */
|
|
157
|
+
/** The rows that match the search and the filters. Default: `total`. */
|
|
99
158
|
matches?: number;
|
|
100
159
|
}
|
|
101
160
|
/**
|
|
@@ -120,7 +179,7 @@ export interface TableState<TRow extends TableRow = TableRow> {
|
|
|
120
179
|
offset: number;
|
|
121
180
|
/** Every row there is. */
|
|
122
181
|
total: number;
|
|
123
|
-
/** The rows that match the search. */
|
|
182
|
+
/** The rows that match the search and the filters. */
|
|
124
183
|
matches: number;
|
|
125
184
|
query: TableQuery;
|
|
126
185
|
/** The selected rows by key (keys as text), in the order they were picked. */
|
|
@@ -175,10 +234,15 @@ export interface TableExcel {
|
|
|
175
234
|
subject?: string;
|
|
176
235
|
/** Values the endpoints' own params need, such as a parent's id. */
|
|
177
236
|
params?: Record<string, string | number>;
|
|
178
|
-
/**
|
|
237
|
+
/** Filters the page holds outside the table, sent beside the table's own (`filterInputs`); the page's win a clash. */
|
|
179
238
|
filters?: () => Record<string, unknown>;
|
|
180
|
-
/** After an import wrote something
|
|
239
|
+
/** After an import wrote something, before the table reads its rows again: drop here whatever the page keeps of them. */
|
|
181
240
|
onImported?: () => void;
|
|
241
|
+
/**
|
|
242
|
+
* No **Bulk insert** entry. A sheet with a required list cannot be typed in - its key is picked in the spreadsheet -
|
|
243
|
+
* and its panel says so; this leaves the entry out instead.
|
|
244
|
+
*/
|
|
245
|
+
bulk?: false;
|
|
182
246
|
}
|
|
183
247
|
/** An item of the table's options menu (⋮): Import, Print, a report of the page's own. */
|
|
184
248
|
export interface TableMenuAction {
|
|
@@ -195,6 +259,36 @@ export interface TableMenuAction {
|
|
|
195
259
|
separator?: boolean;
|
|
196
260
|
onSelect: () => void;
|
|
197
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Rows kept in a section above the page, which the user folds open and shut: the records they pinned, their
|
|
264
|
+
* favourites. They are the rows as they came from their own endpoint, the same records also show in the list below,
|
|
265
|
+
* and each section's row wears the section's icon where the rows of the page show their number.
|
|
266
|
+
*/
|
|
267
|
+
export interface TableRowSection<TRow extends TableRow = TableRow> {
|
|
268
|
+
/** Tells the sections apart; the table remembers each one's fold under it. */
|
|
269
|
+
key: string;
|
|
270
|
+
/** What the section is called: "Pinned rooms". */
|
|
271
|
+
label: string;
|
|
272
|
+
/** The section's icon, in its head and on each of its rows. */
|
|
273
|
+
icon: IconNode;
|
|
274
|
+
rows: readonly TRow[];
|
|
275
|
+
/** The rows are on their way: the section shows that it is loading. */
|
|
276
|
+
loading?: boolean;
|
|
277
|
+
/** Most rows the section can hold, shown beside the count so the user knows the limit. */
|
|
278
|
+
max?: number;
|
|
279
|
+
}
|
|
280
|
+
/** A mark a row carries for this user - pinned, a favourite - drawn in its first column where its number would be. */
|
|
281
|
+
export interface TableRowMark {
|
|
282
|
+
icon: IconNode;
|
|
283
|
+
/** What the mark says: "Pinned". */
|
|
284
|
+
label: string;
|
|
285
|
+
}
|
|
286
|
+
/** A way to select rows by what they are, such as "Pinned" or "Not flagged". */
|
|
287
|
+
export interface TableSelectBy<TRow extends TableRow = TableRow> {
|
|
288
|
+
label: string;
|
|
289
|
+
icon?: ReactNode;
|
|
290
|
+
test: (row: TRow) => boolean;
|
|
291
|
+
}
|
|
198
292
|
/** An action on one row, in its row: an icon button (`inline`) or an item of the row's menu. */
|
|
199
293
|
export interface TableRowAction<TRow extends TableRow = TableRow> {
|
|
200
294
|
/** Tells actions apart; a test or a style can find it by `data-action`. */
|
|
@@ -247,22 +341,33 @@ export interface DataTableProps<TRow extends TableRow = TableRow> {
|
|
|
247
341
|
searchable?: boolean;
|
|
248
342
|
/** Default "Search…". */
|
|
249
343
|
searchPlaceholder?: string;
|
|
250
|
-
/**
|
|
344
|
+
/** On the left of the bar, after the Add section: tabs, filters. On a narrow table the line under the search. */
|
|
251
345
|
toolbar?: ReactNode;
|
|
252
|
-
/**
|
|
346
|
+
/** The page's own buttons, in the Add section after the table's Add: first in the bar, last on a phone. */
|
|
253
347
|
actions?: ReactNode;
|
|
348
|
+
/**
|
|
349
|
+
* The table's Add, first in the bar. With `excel`, its arrow holds the template, the import and the export, which
|
|
350
|
+
* then leave the options menu.
|
|
351
|
+
*/
|
|
352
|
+
add?: {
|
|
353
|
+
label: ReactNode;
|
|
354
|
+
onClick: () => void;
|
|
355
|
+
};
|
|
254
356
|
/** The Columns panel, where columns are shown, hidden, and dragged into another order. Default true. */
|
|
255
357
|
columnsMenu?: boolean;
|
|
256
358
|
/**
|
|
257
359
|
* The spreadsheet side of this table, against the backend's Excel controller. The options menu (⋮) then offers
|
|
258
360
|
* **Download template**, **Import from a spreadsheet** (the file is verified, the person goes over the rows, and the
|
|
259
|
-
* table reloads once they are written)
|
|
260
|
-
*
|
|
361
|
+
* table reloads once they are written), **Bulk insert** (the same import with no file: the rows are typed into the
|
|
362
|
+
* same editor; offered only with `add`, as it is an Add of many rows) and, where the endpoints have one, **Export to
|
|
363
|
+
* Excel** - which asks the server with the search, the filters and the sort on screen instead of writing a file of
|
|
364
|
+
* the rows this browser happens to hold.
|
|
261
365
|
*
|
|
262
|
-
* It replaces `onImport`, which is the hook for a page that imports its own way.
|
|
366
|
+
* It replaces `onImport`, which is the hook for a page that imports its own way. With `add`, they are under the
|
|
367
|
+
* Add's arrow instead of the options menu.
|
|
263
368
|
*/
|
|
264
369
|
excel?: TableExcel;
|
|
265
|
-
/** A Reload button. Default true when rows are loaded. */
|
|
370
|
+
/** A Reload button (in the options menu on a table under 375px wide). Default true when rows are loaded. */
|
|
266
371
|
reloadable?: boolean;
|
|
267
372
|
/** When the user presses Reload, before the rows load again: drop a cache of your own. */
|
|
268
373
|
onReload?: () => void;
|
|
@@ -288,6 +393,11 @@ export interface DataTableProps<TRow extends TableRow = TableRow> {
|
|
|
288
393
|
maxSelection?: number;
|
|
289
394
|
/** After the selection changes. */
|
|
290
395
|
onSelectionChange?: (rows: TRow[]) => void;
|
|
396
|
+
/**
|
|
397
|
+
* While rows are selected, their count opens a menu that selects again by what the rows are: every row on the page,
|
|
398
|
+
* then these, each picking exactly the rows on the page that pass its test.
|
|
399
|
+
*/
|
|
400
|
+
selectBy?: readonly TableSelectBy<TRow>[];
|
|
291
401
|
/** Actions on the selected rows. A function gets the selected rows. */
|
|
292
402
|
massActions?: readonly TableMassAction<TRow>[] | ((rows: TRow[]) => readonly TableMassAction<TRow>[]);
|
|
293
403
|
/** Actions of each row. */
|
|
@@ -301,8 +411,19 @@ export interface DataTableProps<TRow extends TableRow = TableRow> {
|
|
|
301
411
|
*/
|
|
302
412
|
openOnClick?: boolean;
|
|
303
413
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
414
|
+
* Sections above the page, in this order, each folding open and shut on its own: the records the user pinned, then
|
|
415
|
+
* their favourites. A section with no rows and none on their way does not show.
|
|
416
|
+
*/
|
|
417
|
+
sections?: readonly TableRowSection<TRow>[];
|
|
418
|
+
/**
|
|
419
|
+
* The marks each row carries (pinned, a favourite), in its first column in place of its number, one under the
|
|
420
|
+
* other - in the list and in the sections alike, so no column of their own is needed. A row with none shows its
|
|
421
|
+
* number; a section's row with none shows the section's icon.
|
|
422
|
+
*/
|
|
423
|
+
rowMarks?: (row: TRow) => readonly TableRowMark[];
|
|
424
|
+
/**
|
|
425
|
+
* One section of pinned rows, before any `sections`: the same as a section with the key `pins` and the pin icon.
|
|
426
|
+
* Leave it out for no such section.
|
|
306
427
|
*/
|
|
307
428
|
pinnedRows?: readonly TRow[];
|
|
308
429
|
/** The pinned rows are on their way: the section shows that it is loading. */
|
|
@@ -322,14 +443,22 @@ export interface DataTableProps<TRow extends TableRow = TableRow> {
|
|
|
322
443
|
* as the pointer is over the row or anything is selected.
|
|
323
444
|
*/
|
|
324
445
|
numbered?: boolean;
|
|
325
|
-
/** Remembers the page size, the sort, hidden columns, the order, widths, and pins of the columns, and
|
|
326
|
-
*
|
|
446
|
+
/** Remembers the page size, the sort, hidden columns, the order, widths, and pins of the columns, and which sections
|
|
447
|
+
* are open, on this device. */
|
|
327
448
|
stateKey?: string;
|
|
328
449
|
/** Milliseconds after the last key before a search goes to a server. Default 300; a table with every row searches at once. */
|
|
329
450
|
searchDelay?: number;
|
|
451
|
+
/**
|
|
452
|
+
* The advanced filter: the inputs the rows can be filtered by, as a form takes them. Keep the array stable.
|
|
453
|
+
* With any, the options menu (⋮) offers **Filters**: a panel of these inputs under its button, applied as they change.
|
|
454
|
+
* Name an input after the column `key` it filters (else a path into the row); that name is also what a server gets.
|
|
455
|
+
* A `number` input named `{key}From` / `{key}To` is a lower / upper bound of column `{key}`.
|
|
456
|
+
* `required`, `defaultValue` and `defaultChecked` are ignored, so the Add form's params can be reused.
|
|
457
|
+
*/
|
|
458
|
+
filterInputs?: readonly InputParams[];
|
|
330
459
|
/** Shown when there are no rows at all. Default "No records yet." */
|
|
331
460
|
emptyMessage?: ReactNode;
|
|
332
|
-
/** Beside the empty message
|
|
461
|
+
/** Beside the empty message. Default: the table's Add (`add`); `null` for none. */
|
|
333
462
|
emptyAction?: ReactNode;
|
|
334
463
|
/** The tallest the table grows before its rows scroll under a header that stays: pixels or a CSS length. */
|
|
335
464
|
maxHeight?: number | string;
|
|
@@ -9,9 +9,34 @@ export interface ThemeOption {
|
|
|
9
9
|
/** The themes in `nexus-shared/styles.css`. Each has a light and a dark palette. */
|
|
10
10
|
export declare const NEXUS_THEMES: readonly ThemeOption[];
|
|
11
11
|
export declare const DEFAULT_THEME = "nexus";
|
|
12
|
+
/** `compact` (default): today's sizes. `cozy`: every control and row a step taller, for touch screens and large monitors. */
|
|
13
|
+
export type Density = "compact" | "cozy";
|
|
14
|
+
/**
|
|
15
|
+
* Whether things move: `on` even when the operating system asks for less motion, `off` never, `system` as the
|
|
16
|
+
* operating system says (`prefers-reduced-motion`). Some people turn animations off for the whole desktop and still
|
|
17
|
+
* want them here, which is why this is a choice of its own.
|
|
18
|
+
*/
|
|
19
|
+
export type AnimationMode = "on" | "off" | "system";
|
|
20
|
+
/** The scale grid, a development tool: off, a 4px sheet with a solid line every 48px, or millimetres and centimetres. */
|
|
21
|
+
export type ScaleGrid = "off" | "px" | "cm";
|
|
12
22
|
/** Browser storage keys for the saved choice. */
|
|
13
23
|
export declare const THEME_STORAGE_KEY = "nx-theme";
|
|
14
24
|
export declare const THEME_MODE_STORAGE_KEY = "nx-mode";
|
|
25
|
+
export declare const DENSITY_STORAGE_KEY = "nx-density";
|
|
26
|
+
export declare const ANIMATIONS_STORAGE_KEY = "nx-animations";
|
|
27
|
+
export declare const GRID_STORAGE_KEY = "nx-grid";
|
|
15
28
|
/** Attributes on `<html>` that select the theme and the mode. Without `data-nx-mode`, the system setting applies. */
|
|
16
29
|
export declare const THEME_ATTRIBUTE = "data-nx-theme";
|
|
17
30
|
export declare const THEME_MODE_ATTRIBUTE = "data-nx-mode";
|
|
31
|
+
/** `compact` or `cozy`; the size tokens follow it. */
|
|
32
|
+
export declare const DENSITY_ATTRIBUTE = "data-nx-density";
|
|
33
|
+
/** The visitor's animations choice, `on` or `off`. Without it, the system setting applies. */
|
|
34
|
+
export declare const ANIMATIONS_ATTRIBUTE = "data-nx-animations";
|
|
35
|
+
/**
|
|
36
|
+
* What the stylesheets read: `reduce` while nothing may move, `full` otherwise. `ThemeScript` works it out from the
|
|
37
|
+
* choice and the system setting before the first paint, and again when the system setting changes, so no component
|
|
38
|
+
* asks `prefers-reduced-motion` itself.
|
|
39
|
+
*/
|
|
40
|
+
export declare const MOTION_ATTRIBUTE = "data-nx-motion";
|
|
41
|
+
/** `px` or `cm` while the scale grid shows; development builds only. */
|
|
42
|
+
export declare const GRID_ATTRIBUTE = "data-nx-grid";
|
|
@@ -12,6 +12,21 @@ export const DEFAULT_THEME = "nexus";
|
|
|
12
12
|
/** Browser storage keys for the saved choice. */
|
|
13
13
|
export const THEME_STORAGE_KEY = "nx-theme";
|
|
14
14
|
export const THEME_MODE_STORAGE_KEY = "nx-mode";
|
|
15
|
+
export const DENSITY_STORAGE_KEY = "nx-density";
|
|
16
|
+
export const ANIMATIONS_STORAGE_KEY = "nx-animations";
|
|
17
|
+
export const GRID_STORAGE_KEY = "nx-grid";
|
|
15
18
|
/** Attributes on `<html>` that select the theme and the mode. Without `data-nx-mode`, the system setting applies. */
|
|
16
19
|
export const THEME_ATTRIBUTE = "data-nx-theme";
|
|
17
20
|
export const THEME_MODE_ATTRIBUTE = "data-nx-mode";
|
|
21
|
+
/** `compact` or `cozy`; the size tokens follow it. */
|
|
22
|
+
export const DENSITY_ATTRIBUTE = "data-nx-density";
|
|
23
|
+
/** The visitor's animations choice, `on` or `off`. Without it, the system setting applies. */
|
|
24
|
+
export const ANIMATIONS_ATTRIBUTE = "data-nx-animations";
|
|
25
|
+
/**
|
|
26
|
+
* What the stylesheets read: `reduce` while nothing may move, `full` otherwise. `ThemeScript` works it out from the
|
|
27
|
+
* choice and the system setting before the first paint, and again when the system setting changes, so no component
|
|
28
|
+
* asks `prefers-reduced-motion` itself.
|
|
29
|
+
*/
|
|
30
|
+
export const MOTION_ATTRIBUTE = "data-nx-motion";
|
|
31
|
+
/** `px` or `cm` while the scale grid shows; development builds only. */
|
|
32
|
+
export const GRID_ATTRIBUTE = "data-nx-grid";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ApiModuleValue } from "../Interfaces/ApiInterfaces.ts";
|
|
2
|
+
import { type ApiProxyCode, type ApiProxyFailure } from "./ApiProxyRules.ts";
|
|
3
|
+
export { DEFAULT_PROXY_BODY_LIMIT, DEFAULT_PROXY_REDIRECTS, DEFAULT_PROXY_RESPONSE_HEADERS, lastForwardedAddress, nexusFailure, PROXY_REFUSALS, readIpAddress, type ApiProxyCode, type ApiProxyFailure } from "./ApiProxyRules.ts";
|
|
2
4
|
export interface ApiProxyOptions {
|
|
3
5
|
/** The user's token for the backend, such as from the session cookie. Without one, the request's own Authorization header goes on. */
|
|
4
6
|
token?: (request: Request) => string | null | undefined | Promise<string | null | undefined>;
|
|
@@ -6,10 +8,34 @@ export interface ApiProxyOptions {
|
|
|
6
8
|
headers?: (request: Request) => Record<string, string> | undefined | Promise<Record<string, string> | undefined>;
|
|
7
9
|
/** Serves only these modules, of those the app's `ApiModules` sends through the proxy. Default: all of those. */
|
|
8
10
|
allow?: readonly ApiModuleValue[];
|
|
9
|
-
/** Milliseconds to wait for the backend to start answering. Default 60,000. */
|
|
11
|
+
/** Milliseconds to wait for the backend to start answering, its redirects included. Default 60,000. */
|
|
10
12
|
timeout?: number;
|
|
11
13
|
/** The `fetch` to use. Default: the global one. */
|
|
12
14
|
fetch?: typeof fetch;
|
|
15
|
+
/**
|
|
16
|
+
* More of the backend's response headers to pass on, besides `DEFAULT_PROXY_RESPONSE_HEADERS` and the Nexus backend's
|
|
17
|
+
* own `X-Nexus-*`: `["X-Total-Count"]`. A header that names the backend or carries its own policies (Server,
|
|
18
|
+
* X-Powered-By, X-AspNet-*, Via, Alt-Svc, Strict-Transport-Security, CORS, Location, Link) is dropped even when named.
|
|
19
|
+
*/
|
|
20
|
+
responseHeaders?: readonly string[];
|
|
21
|
+
/** Passes the backend's Set-Cookie headers to the browser. Default false: the app keeps its own session. */
|
|
22
|
+
passCookies?: boolean;
|
|
23
|
+
/** The most bytes a request body may have; a bigger one is refused with 413 before it reaches the backend. Default 100 MB. */
|
|
24
|
+
maxBodySize?: number;
|
|
25
|
+
/** How many redirects inside a module to follow for one call; 0 refuses every redirect. Default 3. */
|
|
26
|
+
maxRedirects?: number;
|
|
27
|
+
/**
|
|
28
|
+
* The client's IP address, sent to the backend as X-Forwarded-For for its sign-in lockout and rate limits. Default:
|
|
29
|
+
* the last address of the X-Forwarded-For the app received, the one Next.js or the app's own reverse proxy wrote. Pass
|
|
30
|
+
* it behind more than one proxy of the app's own, or behind a CDN that names the client in a header of its own.
|
|
31
|
+
*/
|
|
32
|
+
clientAddress?: (request: Request) => string | null | undefined | Promise<string | null | undefined>;
|
|
33
|
+
/** Lets pages of other sites call through the proxy. Default false: the app's own pages, links followed, and non-browser callers. */
|
|
34
|
+
allowCrossSite?: boolean;
|
|
35
|
+
/** Builds the answer to a refusal of the proxy's own, for a backend whose envelope is not Nexus's. Default `nexusFailure`. */
|
|
36
|
+
failure?: (failure: ApiProxyFailure) => Response;
|
|
37
|
+
/** Hears what the proxy hid or refused, on the server. Default: one line in `console.error`. */
|
|
38
|
+
onProblem?: (problem: ApiProxyProblem) => void;
|
|
13
39
|
}
|
|
14
40
|
/** What a Next.js route handler for `[module]/[...path]` receives. */
|
|
15
41
|
export interface ApiProxyContext {
|
|
@@ -18,6 +44,15 @@ export interface ApiProxyContext {
|
|
|
18
44
|
path?: string[];
|
|
19
45
|
}>;
|
|
20
46
|
}
|
|
47
|
+
/** What the proxy hid or refused, for the server's log. It never holds the user's token or a query string. */
|
|
48
|
+
export interface ApiProxyProblem {
|
|
49
|
+
/** The refusal's code, the one the browser got: "BACKEND_REDIRECT_REFUSED". */
|
|
50
|
+
messageCode: ApiProxyCode;
|
|
51
|
+
/** The call, as the browser made it: "POST configuration/Region/MassRecover". */
|
|
52
|
+
call: string;
|
|
53
|
+
/** What happened, for a developer: the backend's address and status, a piece of its error page, why it failed. */
|
|
54
|
+
detail: string;
|
|
55
|
+
}
|
|
21
56
|
/**
|
|
22
57
|
* Makes the route handlers of the proxy. Only the modules' configured roots can be reached: a path cannot climb out of
|
|
23
58
|
* its module (`..` is refused), and the query goes on unchanged.
|