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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { InputDesign } from "../Interfaces/InputInterfaces.ts";
|
|
2
|
+
import { type UserPreferences } from "../Interfaces/PreferenceInterfaces.ts";
|
|
3
|
+
/** The saved settings, with the defaults for anything missing or invalid. Safe to call on the server. */
|
|
4
|
+
export declare function readUserPreferences(): UserPreferences;
|
|
5
|
+
/** Saves settings and updates every component that shows them. Settings left out keep their value. */
|
|
6
|
+
export declare function setUserPreferences(changes: Partial<UserPreferences>): void;
|
|
7
|
+
/** Calls back when the settings change here or in another tab. Returns the function that stops listening. */
|
|
8
|
+
export declare function subscribeUserPreferences(listener: () => void): () => void;
|
|
9
|
+
/** The current settings; the component renders again when they change. */
|
|
10
|
+
export declare function useUserPreferences(): UserPreferences;
|
|
11
|
+
/**
|
|
12
|
+
* The locale for the person's number settings (`numberLocale`): what a number box, a slider and a table's number cells
|
|
13
|
+
* use when they are given no `locale` of their own.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useNumberLocale(): string;
|
|
16
|
+
/**
|
|
17
|
+
* The design an input takes: its own (its page's or its form's), else the person's choice in the quick preferences,
|
|
18
|
+
* else `standard`. A grid's cells and a demo of the designs name theirs, so they keep it. An input with no label of its
|
|
19
|
+
* own - a table's search box, a picker named by a heading above it - has no label to place, so the choice passes it by:
|
|
20
|
+
* a design for one would only leave an empty strip where the label would be.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useInputDesign(own: InputDesign | undefined, labelled?: boolean): InputDesign;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useSyncExternalStore } from "react";
|
|
3
|
+
import { DEFAULT_USER_PREFERENCES, ENumberScales, PREFERENCE_STORAGE_KEYS } from "../Interfaces/PreferenceInterfaces.js";
|
|
4
|
+
import { numberLocale } from "./NumberHelpers.js";
|
|
5
|
+
/*
|
|
6
|
+
* The person's settings for the interface language, numbers and tables, saved in local storage under the
|
|
7
|
+
* PREFERENCE_STORAGE_KEYS and read by the components that show them: a change here redraws every number and table on
|
|
8
|
+
* the page at once, and in other open tabs. The same pattern as the date settings (DatePreferences.ts). On the server
|
|
9
|
+
* there is no storage, so pages render with the defaults and take the saved settings right after hydration.
|
|
10
|
+
*/
|
|
11
|
+
const listeners = new Set();
|
|
12
|
+
let snapshot = DEFAULT_USER_PREFERENCES;
|
|
13
|
+
const SEPARATORS = ["comma", "period", "space", "none"];
|
|
14
|
+
const INPUT_DESIGNS = ["standard", "outlined", "inbox"];
|
|
15
|
+
function read(key) {
|
|
16
|
+
try {
|
|
17
|
+
return localStorage.getItem(key);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** The saved settings, with the defaults for anything missing or invalid. Safe to call on the server. */
|
|
24
|
+
export function readUserPreferences() {
|
|
25
|
+
if (typeof localStorage === "undefined")
|
|
26
|
+
return DEFAULT_USER_PREFERENCES;
|
|
27
|
+
const language = read(PREFERENCE_STORAGE_KEYS.language);
|
|
28
|
+
const scale = Number(read(PREFERENCE_STORAGE_KEYS.numberScale));
|
|
29
|
+
const thousands = read(PREFERENCE_STORAGE_KEYS.thousands);
|
|
30
|
+
const pageSize = Number(read(PREFERENCE_STORAGE_KEYS.pageSize));
|
|
31
|
+
const rowClick = read(PREFERENCE_STORAGE_KEYS.rowClick);
|
|
32
|
+
const inputDesign = read(PREFERENCE_STORAGE_KEYS.inputDesign);
|
|
33
|
+
const next = {
|
|
34
|
+
language: language === "ne" ? "ne" : DEFAULT_USER_PREFERENCES.language,
|
|
35
|
+
numberScale: scale === ENumberScales.SouthAsian ? ENumberScales.SouthAsian : DEFAULT_USER_PREFERENCES.numberScale,
|
|
36
|
+
thousands: thousands && SEPARATORS.includes(thousands) ? thousands : DEFAULT_USER_PREFERENCES.thousands,
|
|
37
|
+
pageSize: Number.isInteger(pageSize) && pageSize > 0 ? pageSize : DEFAULT_USER_PREFERENCES.pageSize,
|
|
38
|
+
rowClick: rowClick === "1" ? true : rowClick === "0" ? false : DEFAULT_USER_PREFERENCES.rowClick,
|
|
39
|
+
inputDesign: inputDesign && INPUT_DESIGNS.includes(inputDesign) ? inputDesign : DEFAULT_USER_PREFERENCES.inputDesign,
|
|
40
|
+
};
|
|
41
|
+
// The same object while nothing changed, so React sees a stable snapshot.
|
|
42
|
+
const keys = Object.keys(next);
|
|
43
|
+
if (keys.some(key => next[key] !== snapshot[key]))
|
|
44
|
+
snapshot = next;
|
|
45
|
+
return snapshot;
|
|
46
|
+
}
|
|
47
|
+
/** Saves settings and updates every component that shows them. Settings left out keep their value. */
|
|
48
|
+
export function setUserPreferences(changes) {
|
|
49
|
+
try {
|
|
50
|
+
if (changes.language !== undefined)
|
|
51
|
+
localStorage.setItem(PREFERENCE_STORAGE_KEYS.language, changes.language);
|
|
52
|
+
if (changes.numberScale !== undefined)
|
|
53
|
+
localStorage.setItem(PREFERENCE_STORAGE_KEYS.numberScale, String(changes.numberScale));
|
|
54
|
+
if (changes.thousands !== undefined)
|
|
55
|
+
localStorage.setItem(PREFERENCE_STORAGE_KEYS.thousands, changes.thousands);
|
|
56
|
+
// `null` goes back to each table's own.
|
|
57
|
+
if (changes.pageSize === null)
|
|
58
|
+
localStorage.removeItem(PREFERENCE_STORAGE_KEYS.pageSize);
|
|
59
|
+
else if (changes.pageSize !== undefined)
|
|
60
|
+
localStorage.setItem(PREFERENCE_STORAGE_KEYS.pageSize, String(changes.pageSize));
|
|
61
|
+
if (changes.rowClick === null)
|
|
62
|
+
localStorage.removeItem(PREFERENCE_STORAGE_KEYS.rowClick);
|
|
63
|
+
else if (changes.rowClick !== undefined)
|
|
64
|
+
localStorage.setItem(PREFERENCE_STORAGE_KEYS.rowClick, changes.rowClick ? "1" : "0");
|
|
65
|
+
if (changes.inputDesign === null)
|
|
66
|
+
localStorage.removeItem(PREFERENCE_STORAGE_KEYS.inputDesign);
|
|
67
|
+
else if (changes.inputDesign !== undefined)
|
|
68
|
+
localStorage.setItem(PREFERENCE_STORAGE_KEYS.inputDesign, changes.inputDesign);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Storage blocked (private mode, for example): the components keep what they have.
|
|
72
|
+
}
|
|
73
|
+
for (const listener of listeners)
|
|
74
|
+
listener();
|
|
75
|
+
}
|
|
76
|
+
// One storage listener for the page, however many components are mounted.
|
|
77
|
+
const STORAGE_KEY_LIST = Object.values(PREFERENCE_STORAGE_KEYS);
|
|
78
|
+
const onStorage = (event) => {
|
|
79
|
+
if (event.key === null || STORAGE_KEY_LIST.includes(event.key))
|
|
80
|
+
for (const listener of listeners)
|
|
81
|
+
listener();
|
|
82
|
+
};
|
|
83
|
+
/** Calls back when the settings change here or in another tab. Returns the function that stops listening. */
|
|
84
|
+
export function subscribeUserPreferences(listener) {
|
|
85
|
+
if (listeners.size === 0)
|
|
86
|
+
window.addEventListener("storage", onStorage);
|
|
87
|
+
listeners.add(listener);
|
|
88
|
+
return () => {
|
|
89
|
+
listeners.delete(listener);
|
|
90
|
+
if (listeners.size === 0)
|
|
91
|
+
window.removeEventListener("storage", onStorage);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const serverSnapshot = () => DEFAULT_USER_PREFERENCES;
|
|
95
|
+
/** The current settings; the component renders again when they change. */
|
|
96
|
+
export function useUserPreferences() {
|
|
97
|
+
return useSyncExternalStore(subscribeUserPreferences, readUserPreferences, serverSnapshot);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The locale for the person's number settings (`numberLocale`): what a number box, a slider and a table's number cells
|
|
101
|
+
* use when they are given no `locale` of their own.
|
|
102
|
+
*/
|
|
103
|
+
export function useNumberLocale() {
|
|
104
|
+
const { numberScale, thousands } = useUserPreferences();
|
|
105
|
+
return numberLocale(numberScale, thousands);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The design an input takes: its own (its page's or its form's), else the person's choice in the quick preferences,
|
|
109
|
+
* else `standard`. A grid's cells and a demo of the designs name theirs, so they keep it. An input with no label of its
|
|
110
|
+
* own - a table's search box, a picker named by a heading above it - has no label to place, so the choice passes it by:
|
|
111
|
+
* a design for one would only leave an empty strip where the label would be.
|
|
112
|
+
*/
|
|
113
|
+
export function useInputDesign(own, labelled = true) {
|
|
114
|
+
const chosen = useSyncExternalStore(subscribeUserPreferences, () => readUserPreferences().inputDesign, () => DEFAULT_USER_PREFERENCES.inputDesign);
|
|
115
|
+
return own ?? (labelled ? chosen : null) ?? "standard";
|
|
116
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode, Ref } from "react";
|
|
2
2
|
import type { PopupSize } from "../Components/Layouts/Popup.tsx";
|
|
3
|
+
import type { PopupHandle } from "../Components/Layouts/PopupHost.tsx";
|
|
3
4
|
import type { FormStore } from "../Helpers/FormStore.ts";
|
|
5
|
+
import type { CrudBackend } from "../Helpers/CrudBackend.ts";
|
|
4
6
|
import type { TableStore } from "../Helpers/TableStore.ts";
|
|
5
7
|
import type { ApiEndpoint } from "./ApiInterfaces.ts";
|
|
6
8
|
import type { FormProps, FormValues, InputParams } from "./FormInterfaces.ts";
|
|
@@ -8,14 +10,19 @@ import type { InputDesign } from "./InputInterfaces.ts";
|
|
|
8
10
|
import type { DataTableProps, TableColumn, TableMassAction, TablePaging, TableRowAction } from "./TableInterfaces.ts";
|
|
9
11
|
/**
|
|
10
12
|
* The lists of a controller: every active record (`normal`), the flagged ones, the trash, and the deleted ones
|
|
11
|
-
* (which can go back to the trash). The records the user pinned are not
|
|
12
|
-
* active list, and in it.
|
|
13
|
+
* (which can go back to the trash). The records the user pinned or made favourites are not lists of their own: they
|
|
14
|
+
* sit in sections above the active list, and in it.
|
|
13
15
|
*/
|
|
14
16
|
export type CrudMode = "normal" | "flag" | "trash" | "deleted";
|
|
15
17
|
/** The built-in actions on one record. */
|
|
16
|
-
export type CrudRowActionName = "view" | "edit" | "flag" | "pin" | "trash" | "recover" | "delete" | "trashFromDelete";
|
|
18
|
+
export type CrudRowActionName = "view" | "edit" | "flag" | "pin" | "favorite" | "history" | "trash" | "recover" | "delete" | "trashFromDelete";
|
|
17
19
|
/** The built-in actions on many records at once. */
|
|
18
|
-
export type CrudMassActionName = "flag" | "pin" | "trash" | "recover" | "delete" | "trashFromDelete" | "description";
|
|
20
|
+
export type CrudMassActionName = "flag" | "pin" | "favorite" | "trash" | "recover" | "delete" | "trashFromDelete" | "description";
|
|
21
|
+
/**
|
|
22
|
+
* A mark a user puts on a record for themselves: pinned, or one of their favourites. Each has a section above the
|
|
23
|
+
* active list and its own limit, and a record may carry both.
|
|
24
|
+
*/
|
|
25
|
+
export type CrudMark = "pin" | "favorite";
|
|
19
26
|
/** Every built-in action: Add, the row actions, and a new description for many records. */
|
|
20
27
|
export type CrudActionName = "create" | CrudRowActionName | "description";
|
|
21
28
|
/**
|
|
@@ -28,8 +35,15 @@ export interface CrudEndpoints {
|
|
|
28
35
|
/** One page of a list, for tables that page on the server: `Room/NormalPagination`, … */
|
|
29
36
|
pages?: Partial<Record<CrudMode, ApiEndpoint>>;
|
|
30
37
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
38
|
+
* This user's marked records, pins and favourites in one list: `Room/BookmarkListing`. Each record says which marks
|
|
39
|
+
* it has (`CrudBackend.marksOf`), and the CRUD splits them into the Pinned and Favourites sections above the active
|
|
40
|
+
* list. It is also where the CRUD learns every record's marks, so a list's own rows need not carry them. Without it
|
|
41
|
+
* (or `pins`) there are no sections, and nothing counts the marks against their limits.
|
|
42
|
+
*/
|
|
43
|
+
bookmarks?: ApiEndpoint;
|
|
44
|
+
/**
|
|
45
|
+
* The records the user pinned, from a backend that keeps no favourites: `Room/PinListing`. A Pinned section and no
|
|
46
|
+
* Favourites. `bookmarks` wins when both are given.
|
|
33
47
|
*/
|
|
34
48
|
pins?: ApiEndpoint;
|
|
35
49
|
/** One record by its key: `{id}` in the path. */
|
|
@@ -37,14 +51,34 @@ export interface CrudEndpoints {
|
|
|
37
51
|
create?: ApiEndpoint;
|
|
38
52
|
update?: ApiEndpoint;
|
|
39
53
|
flag?: ApiEndpoint;
|
|
40
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Sets this user's marks on a record: `Room/SwitchBookmarks/{id}`, sent the whole set the record is to have, never a
|
|
56
|
+
* toggle (`CrudBackend.marksRequest`). Pin and Favourite both use it.
|
|
57
|
+
*/
|
|
58
|
+
bookmark?: ApiEndpoint;
|
|
59
|
+
/** Pins a record or unpins it, on a backend without `bookmark`: `Room/Pin/{id}`, a toggle. `bookmark` wins when both are given. */
|
|
41
60
|
pin?: ApiEndpoint;
|
|
61
|
+
/**
|
|
62
|
+
* A record's history, 50 entries a call: `Room/AuditListing/{ownerId}/{skipCount}`. With it every row offers History
|
|
63
|
+
* and the details View history, to a person who may call it.
|
|
64
|
+
*/
|
|
65
|
+
audit?: ApiEndpoint;
|
|
42
66
|
trash?: ApiEndpoint;
|
|
43
67
|
recover?: ApiEndpoint;
|
|
44
68
|
delete?: ApiEndpoint;
|
|
45
69
|
trashFromDelete?: ApiEndpoint;
|
|
46
|
-
/**
|
|
47
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Actions on many records, sent the selected keys. `bookmark` puts one mark on every record sent or takes it off, and
|
|
72
|
+
* leaves their other marks alone (`Room/MassSwitchBookmarks`): Pin and Favourite both use it, and it wins over `pin`.
|
|
73
|
+
*/
|
|
74
|
+
mass?: Partial<Record<Exclude<CrudMassActionName, "favorite"> | "bookmark", ApiEndpoint>>;
|
|
75
|
+
/**
|
|
76
|
+
* Where other pages look this controller's records up: by key (`Room/FindListing`, a table's client join and a
|
|
77
|
+
* picker's saved values) and as a picker's list (`Room/ActiveListing`). The CRUD calls neither; a change it makes marks
|
|
78
|
+
* what was looked up through them as old, so a name or a status shown elsewhere is read again.
|
|
79
|
+
*/
|
|
80
|
+
findListing?: ApiEndpoint;
|
|
81
|
+
activeListing?: ApiEndpoint;
|
|
48
82
|
}
|
|
49
83
|
/** Inputs of the Add and Edit forms: one list for both, a list for each, or a function of the action and the row. */
|
|
50
84
|
export type CrudInputs<TRow extends FormValues = FormValues> = readonly InputParams[] | {
|
|
@@ -128,6 +162,24 @@ export interface CrudDetailsOptions<TRow extends FormValues = FormValues> {
|
|
|
128
162
|
* "{Subject} {label}". Default `details`. A popup whose panel is the point says so: `schema`, `preview`.
|
|
129
163
|
*/
|
|
130
164
|
label?: string;
|
|
165
|
+
/** Buttons of the page's own in the footer, before Edit and Close: "View history". */
|
|
166
|
+
actions?: readonly CrudDetailsAction<TRow>[];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* A button in the details popup's footer. One that names the endpoint it calls shows only to a user who may call
|
|
170
|
+
* it, by the same rule every built-in action follows - so it appears and disappears with the user's rights, with
|
|
171
|
+
* nothing to change here when they come from the backend.
|
|
172
|
+
*/
|
|
173
|
+
export interface CrudDetailsAction<TRow extends FormValues = FormValues> {
|
|
174
|
+
id: string;
|
|
175
|
+
label: string;
|
|
176
|
+
icon?: ReactNode;
|
|
177
|
+
/** What it calls: the button shows only when the user may call it. */
|
|
178
|
+
endpoint?: ApiEndpoint;
|
|
179
|
+
/** Hidden for this record, by a rule of the page's own. */
|
|
180
|
+
hidden?: (row: TRow) => boolean;
|
|
181
|
+
/** On a click, with the record and the popup (close it, or leave it open beside what this opens). */
|
|
182
|
+
onSelect: (row: TRow, popup: PopupHandle) => void;
|
|
131
183
|
}
|
|
132
184
|
/** What changed, for `onChange`. */
|
|
133
185
|
export interface CrudChange<TRow extends FormValues = FormValues> {
|
|
@@ -137,7 +189,7 @@ export interface CrudChange<TRow extends FormValues = FormValues> {
|
|
|
137
189
|
mode: CrudMode;
|
|
138
190
|
}
|
|
139
191
|
/** Table settings a CRUD passes on to its `DataTable`. */
|
|
140
|
-
export type CrudTableOptions<TRow extends FormValues = FormValues> = Pick<DataTableProps<TRow>, "pageSize" | "pageSizes" | "defaultSort" | "numbered" | "maxHeight" | "fill" | "excel" | "size" | "searchPlaceholder" | "maxSelection" | "emptyMessage" | "columnsMenu" | "stateKey" | "searchDelay" | "reorderable" | "resizable" | "pinnable" | "moreActions" | "exportable" | "printable" | "exportName" | "onImport" | "openOnClick">;
|
|
192
|
+
export type CrudTableOptions<TRow extends FormValues = FormValues> = Pick<DataTableProps<TRow>, "pageSize" | "pageSizes" | "defaultSort" | "numbered" | "maxHeight" | "fill" | "excel" | "size" | "searchPlaceholder" | "maxSelection" | "emptyMessage" | "columnsMenu" | "stateKey" | "searchDelay" | "filterInputs" | "reorderable" | "resizable" | "pinnable" | "moreActions" | "exportable" | "printable" | "exportName" | "onImport" | "openOnClick">;
|
|
141
193
|
/** Props of `Crud`. */
|
|
142
194
|
export interface CrudProps<TRow extends FormValues = FormValues> {
|
|
143
195
|
/** The endpoints: `MODULES.controller(NexusModule.Reservation, "Guest", "guest")`, or an object of your own. */
|
|
@@ -187,6 +239,11 @@ export interface CrudProps<TRow extends FormValues = FormValues> {
|
|
|
187
239
|
table?: CrudTableOptions<TRow>;
|
|
188
240
|
/** After every change the CRUD made: a record added, saved, trashed, deleted. */
|
|
189
241
|
onChange?: (change: CrudChange<TRow>) => void;
|
|
242
|
+
/**
|
|
243
|
+
* The conventions of this controller's backend, when they differ from the app's (`defineCrudBackend`): an app whose
|
|
244
|
+
* pages sit on two backends gives the other one here. Default the app's, else the Nexus backend's.
|
|
245
|
+
*/
|
|
246
|
+
backend?: CrudBackend;
|
|
190
247
|
/** The table's name for screen readers. Default: the plural of the subject ("Guests"). */
|
|
191
248
|
"aria-label"?: string;
|
|
192
249
|
"aria-labelledby"?: string;
|
|
@@ -84,6 +84,18 @@ export interface ExcelSettings {
|
|
|
84
84
|
* what the editors draw from until it is not.
|
|
85
85
|
*/
|
|
86
86
|
inputs?: readonly unknown[];
|
|
87
|
+
/**
|
|
88
|
+
* The statuses a new record may start in when it is imported, each with its words: the import offers them as a
|
|
89
|
+
* choice. Empty, or absent, when the model offers none, and then no choice is shown.
|
|
90
|
+
*/
|
|
91
|
+
recordStatuses?: ExcelRecordStatus[];
|
|
92
|
+
/** The status picked unless the person picks another: the backend's "Imported". */
|
|
93
|
+
defaultRecordStatus?: number;
|
|
94
|
+
}
|
|
95
|
+
/** One status an imported record may start in: the backend's number, and the words for it. */
|
|
96
|
+
export interface ExcelRecordStatus {
|
|
97
|
+
value: number;
|
|
98
|
+
label: string;
|
|
87
99
|
}
|
|
88
100
|
/** One thing wrong with one cell, told so the person can find it. */
|
|
89
101
|
export interface ExcelCellProblem {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode, Ref } from "react";
|
|
2
2
|
import type { CheckBoxOnlyProps, CheckBoxProps } from "../Components/Inputs/CheckBox.tsx";
|
|
3
3
|
import type { CheckBoxGroupProps } from "../Components/Inputs/CheckBoxGroup.tsx";
|
|
4
|
+
import type { CodeBoxProps } from "../Components/Inputs/CodeBox.tsx";
|
|
4
5
|
import type { DatePickerProps } from "../Components/Inputs/DatePicker.tsx";
|
|
5
6
|
import type { DateRangePickerProps } from "../Components/Inputs/DateRangePicker.tsx";
|
|
6
7
|
import type { DateTimePickerProps } from "../Components/Inputs/DateTimePicker.tsx";
|
|
@@ -63,6 +64,8 @@ export type InputParamsOf<TType extends string, TProps> = DistributiveOmit<TProp
|
|
|
63
64
|
export type TextInputParams = InputParamsOf<TextBoxType, TextBoxProps>;
|
|
64
65
|
export type TextAreaParams = InputParamsOf<"textarea", TextAreaProps>;
|
|
65
66
|
export type NumberInputParams = InputParamsOf<"number", NumberBoxProps>;
|
|
67
|
+
/** `CodeBox`: a box per character. The value is the code's characters, without separators. */
|
|
68
|
+
export type CodeInputParams = InputParamsOf<"code", CodeBoxProps>;
|
|
66
69
|
/** A checkbox: `true` or `false`. `defaultChecked` is the value of a new row. */
|
|
67
70
|
export type CheckBoxParams = InputParamsOf<"checkbox", CheckBoxProps & CheckBoxOnlyProps>;
|
|
68
71
|
export type SwitchParams = InputParamsOf<"switch", CheckBoxProps>;
|
|
@@ -90,7 +93,7 @@ export type TabularParams = InputParamsOf<"tabular", TabularFormProps>;
|
|
|
90
93
|
/** `GroupForm`: the same rows, each as a section of inputs. */
|
|
91
94
|
export type GroupParams = InputParamsOf<"group", GroupFormProps>;
|
|
92
95
|
/** The params of any input: the root type every form takes as `inputs`. */
|
|
93
|
-
export type InputParams = TextInputParams | TextAreaParams | NumberInputParams | CheckBoxParams | SwitchParams | RadioParams | CheckBoxGroupParams | RadioGroupParams | DropdownParams | DateParams | DateRangeParams | TimeParams | DateTimeParams | SliderParams | RangeSliderParams | MarkdownParams | RichTextParams | TreeParams | TabularParams | GroupParams;
|
|
96
|
+
export type InputParams = TextInputParams | TextAreaParams | NumberInputParams | CodeInputParams | CheckBoxParams | SwitchParams | RadioParams | CheckBoxGroupParams | RadioGroupParams | DropdownParams | DateParams | DateRangeParams | TimeParams | DateTimeParams | SliderParams | RangeSliderParams | MarkdownParams | RichTextParams | TreeParams | TabularParams | GroupParams;
|
|
94
97
|
export type InputType = InputParams["type"];
|
|
95
98
|
/** Settings a check needs to write its message the way the field shows values: the user's date and time settings. */
|
|
96
99
|
export interface InputValidationContext {
|
|
@@ -213,8 +216,13 @@ export interface RowsInputHandle<TRow extends RowValue = RowValue> {
|
|
|
213
216
|
setValue: (rows: readonly TRow[]) => void;
|
|
214
217
|
/** Adds a row with these values (over `newRow`), at `index` or at the end, and focuses its first input. */
|
|
215
218
|
add: (values?: Partial<TRow>, index?: number) => void;
|
|
216
|
-
/**
|
|
217
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Removes the row at `index`, with an Undo under the rows - or none with `undo: false`, for a row the code drops
|
|
221
|
+
* rather than the person, such as one nothing was typed in.
|
|
222
|
+
*/
|
|
223
|
+
remove: (index: number, options?: {
|
|
224
|
+
undo?: boolean;
|
|
225
|
+
}) => void;
|
|
218
226
|
/** Checks every row, shows every message, and focuses the first problem. Returns whether all is valid. */
|
|
219
227
|
validate: () => boolean;
|
|
220
228
|
/** Brings the row at `index` into view and focuses its input named `name`, or its first input. */
|
|
@@ -228,6 +236,17 @@ export interface TabularFormProps<TRow extends RowValue = RowValue> extends Rows
|
|
|
228
236
|
maxHeight?: number | string;
|
|
229
237
|
/** The row number column. Default true; it is also the button of each row's menu. */
|
|
230
238
|
numbered?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* Where each row's actions sit. `"number"` (the default): a menu beside the row's number. `"end"`: a column fixed at
|
|
241
|
+
* the right edge, as a data table has them - Remove and Lock as buttons of their own, any other action in a menu
|
|
242
|
+
* after them.
|
|
243
|
+
*/
|
|
244
|
+
actionsAt?: "number" | "end";
|
|
245
|
+
/**
|
|
246
|
+
* The person can lock a row, and unlock it: a locked row's inputs are read-only and it cannot be removed. The locks
|
|
247
|
+
* are the screen's, never part of the value - a locked row is still sent. Its button is with the row's actions.
|
|
248
|
+
*/
|
|
249
|
+
lockable?: boolean;
|
|
231
250
|
}
|
|
232
251
|
/** `GroupForm`: each row as a section of inputs, laid out on a 12-column grid by each input's `span`. */
|
|
233
252
|
export interface GroupFormProps<TRow extends RowValue = RowValue> extends RowsInputProps<TRow> {
|
|
@@ -292,7 +311,10 @@ export interface FormProps<TValues extends FormValues = FormValues> {
|
|
|
292
311
|
readOnly?: boolean;
|
|
293
312
|
/** Every input is disabled, and nothing is checked. */
|
|
294
313
|
disabled?: boolean;
|
|
295
|
-
/**
|
|
314
|
+
/**
|
|
315
|
+
* The values are loading: the inputs show at once, disabled, so the form has its final size from the first frame, and
|
|
316
|
+
* nothing typed is taken (even with `disabled` taken off by hand) until it ends. A submit waits too.
|
|
317
|
+
*/
|
|
296
318
|
loading?: boolean;
|
|
297
319
|
id?: string;
|
|
298
320
|
className?: string;
|
|
@@ -325,6 +347,13 @@ export type FormSubmitResult<TValues extends FormValues = FormValues> = void | u
|
|
|
325
347
|
};
|
|
326
348
|
/** Where `SubmitForm` puts its buttons: at the end with the status line before them, at the start, or nowhere (`FormButtons` elsewhere). */
|
|
327
349
|
export type FormButtonsPlacement = "end" | "start" | false;
|
|
350
|
+
/**
|
|
351
|
+
* What a form's status line reports. `full`: loading, saving, what needs attention, unsaved changes, and when it saved.
|
|
352
|
+
* `errors`: only an error that belongs to no field, such as the server's "The sign-in took too long", for a short form
|
|
353
|
+
* that keeps nothing (a sign-in, a search, a code to verify): "Unsaved changes" would be untrue there, the button's
|
|
354
|
+
* spinner already says it is working, and every field is in view with its own message under it.
|
|
355
|
+
*/
|
|
356
|
+
export type FormStatusLineMode = "full" | "errors";
|
|
328
357
|
/** Props of `SubmitForm`: a `Form` in a `<form>`, checked on submit, with Save, Cancel, and Reset. */
|
|
329
358
|
export interface SubmitFormProps<TValues extends FormValues = FormValues> extends FormProps<TValues> {
|
|
330
359
|
/**
|
|
@@ -353,6 +382,8 @@ export interface SubmitFormProps<TValues extends FormValues = FormValues> extend
|
|
|
353
382
|
resetOnSuccess?: boolean;
|
|
354
383
|
/** Where the buttons go. Default `end`. With `false`, put a `FormButtons` with the same `form` elsewhere, such as a popup's footer. */
|
|
355
384
|
buttons?: FormButtonsPlacement;
|
|
385
|
+
/** What the status line reports. Default `full`; `errors` for a short form that keeps nothing, such as a sign-in or a search. */
|
|
386
|
+
statusLine?: FormStatusLineMode;
|
|
356
387
|
/** Asks before the page closes or reloads with unsaved changes. Default: true without a `draftKey` (a draft keeps them). */
|
|
357
388
|
confirmLeave?: boolean;
|
|
358
389
|
/** Name for screen readers. */
|
|
@@ -394,8 +425,8 @@ export interface ApiFormProps<TValues extends FormValues = FormValues> extends O
|
|
|
394
425
|
/** The toast after a save: text, or `false` for none. Default: the server's message, else the endpoint's ("Room saved."), else "Saved." */
|
|
395
426
|
successMessage?: ReactNode | false;
|
|
396
427
|
/**
|
|
397
|
-
* Loads the values to edit, e.g. a record by id.
|
|
398
|
-
* once; give the form a new `key` to load another record.
|
|
428
|
+
* Loads the values to edit, e.g. a record by id. The inputs show disabled while it runs, and a failure offers Retry.
|
|
429
|
+
* It runs once; give the form a new `key` to load another record.
|
|
399
430
|
*/
|
|
400
431
|
loadValue?: (signal: AbortSignal) => Promise<Partial<TValues> | null | undefined>;
|
|
401
432
|
}
|
|
@@ -31,6 +31,30 @@ export interface TextRules {
|
|
|
31
31
|
/** Runs after the built-in rules pass. */
|
|
32
32
|
validate?: TextValidator;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* What a code box takes, one character to a box:
|
|
36
|
+
* - `digits`: 0–9, with the phone's number pad. A one-time code, a PIN, an SSN.
|
|
37
|
+
* - `letters`: A–Z.
|
|
38
|
+
* - `alphanumeric`: letters and digits, such as a licence key or a booking reference.
|
|
39
|
+
* - `hex`: 0–9 and A–F, such as a colour or a device id.
|
|
40
|
+
*/
|
|
41
|
+
export type CodeCharacters = "digits" | "letters" | "alphanumeric" | "hex";
|
|
42
|
+
/** The shape and rules of a code: how many boxes, in which groups, and what each box takes. Plain values, so params stay serializable. */
|
|
43
|
+
export interface CodeRules {
|
|
44
|
+
/** How many boxes. Default 6. Left out when `groups` is given. */
|
|
45
|
+
length?: number;
|
|
46
|
+
/** Boxes in groups, with a gap or a `separator` between them: `[3, 2, 4]` for an SSN, `[3, 3]` for a one-time code. */
|
|
47
|
+
groups?: readonly number[];
|
|
48
|
+
/** Default `digits`. */
|
|
49
|
+
characters?: CodeCharacters;
|
|
50
|
+
/** A regular expression for one character, in place of `characters`: `"[A-HJ-NP-Z2-9]"` leaves out I, O, 0 and 1. */
|
|
51
|
+
allowed?: string;
|
|
52
|
+
/** Letters as typed are turned to this case. Default `upper`; `any` keeps them as typed. */
|
|
53
|
+
letterCase?: "upper" | "lower" | "any";
|
|
54
|
+
required?: boolean;
|
|
55
|
+
/** Runs after the built-in rules pass, with the code. */
|
|
56
|
+
validate?: TextValidator;
|
|
57
|
+
}
|
|
34
58
|
/** Custom check for a number. Receives the value, or `null` when the field is empty; returns a message to fail. */
|
|
35
59
|
export type NumberValidator = (value: number | null) => string | null | undefined;
|
|
36
60
|
/** Validation rules for a number, named like the HTML attributes. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** The actions the builder knows by name (`MESSAGE_ACTION_NAMES`); `actionWords(name)` gives their words. */
|
|
2
|
-
export type MessageActionName = "load" | "save" | "create" | "update" | "delete" | "trash" | "restore" | "recover" | "flag" | "unflag" | "pin" | "unpin" | "send" | "submit" | "upload" | "download" | "import" | "export" | "copy" | "approve" | "reject" | "cancel";
|
|
2
|
+
export type MessageActionName = "load" | "save" | "create" | "update" | "delete" | "trash" | "restore" | "recover" | "flag" | "unflag" | "pin" | "unpin" | "favorite" | "unfavorite" | "send" | "submit" | "upload" | "download" | "import" | "export" | "copy" | "approve" | "reject" | "cancel";
|
|
3
3
|
/** The words of an action. */
|
|
4
4
|
export interface ActionWords {
|
|
5
5
|
/** "save", or with the object inside: "move {object} to the trash". */
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { InputDesign } from "./InputInterfaces.ts";
|
|
2
|
+
/** The words of the app itself. Data keeps the language it was entered in. */
|
|
3
|
+
export type InterfaceLanguage = "en" | "ne";
|
|
4
|
+
/**
|
|
5
|
+
* The core's `ENumberScales`, by member value: where the groups of a number fall. `International` writes 1,234,567
|
|
6
|
+
* (thousand, million, billion); `SouthAsian` writes 12,34,567 (thousand, lakh, crore).
|
|
7
|
+
*/
|
|
8
|
+
export declare const ENumberScales: {
|
|
9
|
+
readonly International: 0;
|
|
10
|
+
readonly SouthAsian: 1;
|
|
11
|
+
};
|
|
12
|
+
export type ENumberScales = (typeof ENumberScales)[keyof typeof ENumberScales];
|
|
13
|
+
/**
|
|
14
|
+
* The mark between groups of digits: 1,200, 1.200, 1 200 (a no-break space) or 1200. A period between the groups
|
|
15
|
+
* takes a comma for the decimal mark, as it does in much of Europe; every other choice keeps the period.
|
|
16
|
+
*/
|
|
17
|
+
export type ThousandsSeparator = "comma" | "period" | "space" | "none";
|
|
18
|
+
export interface UserPreferences {
|
|
19
|
+
/** Default `en`. */
|
|
20
|
+
language: InterfaceLanguage;
|
|
21
|
+
/** Default `International`. */
|
|
22
|
+
numberScale: ENumberScales;
|
|
23
|
+
/** Default `comma`. */
|
|
24
|
+
thousands: ThousandsSeparator;
|
|
25
|
+
/**
|
|
26
|
+
* The rows every table opens with, over the size the table names itself, when the table offers it; a size picked in a
|
|
27
|
+
* table with a `stateKey` still wins there. `null` (the default): not chosen, each table's own.
|
|
28
|
+
*/
|
|
29
|
+
pageSize: number | null;
|
|
30
|
+
/**
|
|
31
|
+
* A single click on a row opens its record (`true`) or only a double-click does (`false`), in every table, over what
|
|
32
|
+
* the table says itself. `null` (the default): not chosen, each table's own `openOnClick`.
|
|
33
|
+
*/
|
|
34
|
+
rowClick: boolean | null;
|
|
35
|
+
/**
|
|
36
|
+
* The design every input takes when its page or form names none: the label above the box (`standard`), on its edge
|
|
37
|
+
* (`outlined`) or inside its top (`inbox`). `null` (the default): not chosen, `standard`. An input whose page fixes a
|
|
38
|
+
* design - a grid's cells, a demo of the designs - keeps it.
|
|
39
|
+
*/
|
|
40
|
+
inputDesign: InputDesign | null;
|
|
41
|
+
}
|
|
42
|
+
export declare const DEFAULT_USER_PREFERENCES: UserPreferences;
|
|
43
|
+
/** Local storage keys of the settings. A number scale is kept as its member value ("0", "1"), a row click as "1" or "0". */
|
|
44
|
+
export declare const PREFERENCE_STORAGE_KEYS: {
|
|
45
|
+
readonly language: "nx-language";
|
|
46
|
+
readonly numberScale: "nx-number-scale";
|
|
47
|
+
readonly thousands: "nx-thousands";
|
|
48
|
+
readonly pageSize: "nx-page-size";
|
|
49
|
+
readonly rowClick: "nx-row-click";
|
|
50
|
+
readonly inputDesign: "nx-input-design";
|
|
51
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The core's `ENumberScales`, by member value: where the groups of a number fall. `International` writes 1,234,567
|
|
3
|
+
* (thousand, million, billion); `SouthAsian` writes 12,34,567 (thousand, lakh, crore).
|
|
4
|
+
*/
|
|
5
|
+
export const ENumberScales = {
|
|
6
|
+
International: 0,
|
|
7
|
+
SouthAsian: 1,
|
|
8
|
+
};
|
|
9
|
+
export const DEFAULT_USER_PREFERENCES = {
|
|
10
|
+
language: "en",
|
|
11
|
+
numberScale: ENumberScales.International,
|
|
12
|
+
thousands: "comma",
|
|
13
|
+
pageSize: null,
|
|
14
|
+
rowClick: null,
|
|
15
|
+
inputDesign: null,
|
|
16
|
+
};
|
|
17
|
+
/** Local storage keys of the settings. A number scale is kept as its member value ("0", "1"), a row click as "1" or "0". */
|
|
18
|
+
export const PREFERENCE_STORAGE_KEYS = {
|
|
19
|
+
language: "nx-language",
|
|
20
|
+
numberScale: "nx-number-scale",
|
|
21
|
+
thousands: "nx-thousands",
|
|
22
|
+
pageSize: "nx-page-size",
|
|
23
|
+
rowClick: "nx-row-click",
|
|
24
|
+
inputDesign: "nx-input-design",
|
|
25
|
+
};
|