nexus-shared 3.2.0 → 4.1.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 +2359 -0
- package/README.md +1911 -1123
- package/dist/Client.Index.d.ts +27 -0
- package/dist/Client.Index.js +27 -0
- package/dist/Components/Chats/ChatComposer.d.ts +7 -1
- package/dist/Components/Chats/ChatComposer.js +9 -6
- package/dist/Components/Chats/ChatParts.d.ts +15 -2
- package/dist/Components/Chats/ChatParts.js +15 -4
- package/dist/Components/Chats/ChatPopup.d.ts +46 -0
- package/dist/Components/Chats/ChatPopup.js +34 -0
- package/dist/Components/Chats/ChatThread.d.ts +9 -1
- package/dist/Components/Chats/ChatThread.js +54 -6
- package/dist/Components/Dashboards/DashboardBoard.d.ts +62 -0
- package/dist/Components/Dashboards/DashboardBoard.js +594 -0
- package/dist/Components/Dashboards/DashboardWidgets.d.ts +155 -0
- package/dist/Components/Dashboards/DashboardWidgets.js +159 -0
- package/dist/Components/Dashboards/WidgetFrame.d.ts +51 -0
- package/dist/Components/Dashboards/WidgetFrame.js +45 -0
- package/dist/Components/Documents/Button.d.ts +6 -1
- package/dist/Components/Documents/Button.js +2 -2
- package/dist/Components/Documents/DocumentFrame.d.ts +50 -0
- package/dist/Components/Documents/DocumentFrame.js +83 -0
- package/dist/Components/Documents/Menu.d.ts +4 -0
- package/dist/Components/Documents/Menu.js +40 -24
- package/dist/Components/Documents/PrintDocument.d.ts +95 -0
- package/dist/Components/Documents/PrintDocument.js +62 -0
- package/dist/Components/Documents/TabButtons.d.ts +6 -0
- package/dist/Components/Documents/TabButtons.js +5 -4
- package/dist/Components/Documents/Tabs.d.ts +59 -0
- package/dist/Components/Documents/Tabs.js +70 -0
- package/dist/Components/Domains/DomainCard.d.ts +98 -0
- package/dist/Components/Domains/DomainCard.js +182 -0
- package/dist/Components/Forms/ApiForm.js +24 -3
- package/dist/Components/Forms/Crud.d.ts +2 -2
- package/dist/Components/Forms/Crud.js +628 -247
- package/dist/Components/Forms/CrudActions.d.ts +137 -0
- package/dist/Components/Forms/CrudActions.js +214 -0
- package/dist/Components/Forms/CrudHistory.d.ts +6 -1
- package/dist/Components/Forms/CrudHistory.js +14 -6
- package/dist/Components/Forms/CrudNarrowPicker.d.ts +31 -0
- package/dist/Components/Forms/CrudNarrowPicker.js +180 -0
- package/dist/Components/Forms/CrudParts.d.ts +37 -2
- package/dist/Components/Forms/CrudParts.js +123 -7
- package/dist/Components/Forms/CrudRowForms.d.ts +26 -0
- package/dist/Components/Forms/CrudRowForms.js +174 -0
- package/dist/Components/Forms/CrudScopes.d.ts +28 -0
- package/dist/Components/Forms/CrudScopes.js +76 -0
- package/dist/Components/Forms/CrudTree.d.ts +90 -0
- package/dist/Components/Forms/CrudTree.js +363 -0
- package/dist/Components/Forms/CrudWorkspace.d.ts +73 -0
- package/dist/Components/Forms/CrudWorkspace.js +177 -0
- package/dist/Components/Forms/ExcelImport.js +3 -3
- package/dist/Components/Forms/Form.d.ts +6 -5
- package/dist/Components/Forms/Form.js +134 -21
- package/dist/Components/Forms/FormLeaveGuard.d.ts +44 -0
- package/dist/Components/Forms/FormLeaveGuard.js +65 -0
- package/dist/Components/Forms/FormQuestion.d.ts +6 -0
- package/dist/Components/Forms/FormQuestion.js +28 -0
- package/dist/Components/Forms/RecordFlows.d.ts +50 -0
- package/dist/Components/Forms/RecordFlows.js +282 -0
- package/dist/Components/Forms/SubmitForm.d.ts +37 -2
- package/dist/Components/Forms/SubmitForm.js +182 -10
- package/dist/Components/Inputs/CheckBox.js +1 -1
- package/dist/Components/Inputs/ChoiceField.d.ts +21 -1
- package/dist/Components/Inputs/ChoiceField.js +28 -2
- package/dist/Components/Inputs/ComputedInput.d.ts +51 -0
- package/dist/Components/Inputs/ComputedInput.js +179 -0
- package/dist/Components/Inputs/Dropdown.d.ts +13 -0
- package/dist/Components/Inputs/Dropdown.js +8 -6
- package/dist/Components/Inputs/DropdownParts.d.ts +3 -1
- package/dist/Components/Inputs/DropdownParts.js +16 -4
- package/dist/Components/Inputs/Field.d.ts +7 -1
- package/dist/Components/Inputs/Field.js +2 -2
- package/dist/Components/Inputs/GroupForm.d.ts +6 -6
- package/dist/Components/Inputs/GroupForm.js +12 -12
- package/dist/Components/Inputs/InputRenderer.d.ts +13 -6
- package/dist/Components/Inputs/InputRenderer.js +37 -32
- package/dist/Components/Inputs/MarkdownEditor.d.ts +6 -0
- package/dist/Components/Inputs/MarkdownEditor.js +32 -6
- package/dist/Components/Inputs/PictureInput.d.ts +41 -0
- package/dist/Components/Inputs/PictureInput.js +75 -0
- package/dist/Components/Inputs/RadioGroup.d.ts +16 -3
- package/dist/Components/Inputs/RadioGroup.js +8 -3
- package/dist/Components/Inputs/RowsInput.d.ts +15 -2
- package/dist/Components/Inputs/RowsInput.js +96 -8
- package/dist/Components/Inputs/TabularForm.d.ts +5 -5
- package/dist/Components/Inputs/TabularForm.js +45 -32
- package/dist/Components/Inputs/TextArea.d.ts +6 -0
- package/dist/Components/Inputs/TextArea.js +11 -2
- package/dist/Components/Inputs/TextBoxTypes.d.ts +6 -0
- package/dist/Components/Inputs/TextBoxTypes.js +17 -0
- package/dist/Components/Inputs/TreeView.d.ts +76 -2
- package/dist/Components/Inputs/TreeView.js +227 -16
- package/dist/Components/Layouts/MessageBox.d.ts +15 -2
- package/dist/Components/Layouts/MessageBox.js +56 -7
- package/dist/Components/Layouts/Popup.d.ts +34 -7
- package/dist/Components/Layouts/Popup.js +143 -13
- package/dist/Components/Layouts/PopupDock.d.ts +3 -1
- package/dist/Components/Layouts/PopupDock.js +2 -1
- package/dist/Components/Layouts/PopupHost.js +5 -4
- package/dist/Components/Messages/MailClient.d.ts +50 -0
- package/dist/Components/Messages/MailClient.js +410 -0
- package/dist/Components/Messages/MailColumns.d.ts +21 -0
- package/dist/Components/Messages/MailColumns.js +92 -0
- package/dist/Components/Messages/MailCompose.d.ts +46 -0
- package/dist/Components/Messages/MailCompose.js +154 -0
- package/dist/Components/Messages/MailReader.d.ts +43 -0
- package/dist/Components/Messages/MailReader.js +207 -0
- package/dist/Components/Messages/MailThread.d.ts +71 -0
- package/dist/Components/Messages/MailThread.js +185 -0
- package/dist/Components/Messages/MessageBell.d.ts +41 -0
- package/dist/Components/Messages/MessageBell.js +76 -0
- package/dist/Components/Viewers/DataTable.js +153 -49
- package/dist/Components/Viewers/DataTableColumns.d.ts +2 -2
- package/dist/Components/Viewers/DataTableColumns.js +2 -1
- package/dist/Components/Viewers/DataTableFilters.d.ts +1 -1
- package/dist/Components/Viewers/DataTableFilters.js +17 -2
- package/dist/Components/Viewers/DataTableParts.d.ts +23 -5
- package/dist/Components/Viewers/DataTableParts.js +26 -14
- package/dist/Components/Viewers/OwnerFiles.d.ts +227 -0
- package/dist/Components/Viewers/OwnerFiles.js +700 -0
- package/dist/Components/Viewers/QrCodeImage.d.ts +22 -0
- package/dist/Components/Viewers/QrCodeImage.js +15 -0
- package/dist/Components/Viewers/RecordCards.d.ts +16 -0
- package/dist/Components/Viewers/RecordCards.js +509 -0
- package/dist/Helpers/ApiModules.js +4 -0
- package/dist/Helpers/AuditEntries.d.ts +50 -0
- package/dist/Helpers/AuditEntries.js +96 -0
- package/dist/Helpers/BusyHooks.d.ts +6 -0
- package/dist/Helpers/BusyHooks.js +39 -0
- package/dist/Helpers/ChatBackend.d.ts +8 -1
- package/dist/Helpers/ChatBackend.js +18 -0
- package/dist/Helpers/ChatHelpers.d.ts +2 -0
- package/dist/Helpers/ChatHelpers.js +4 -1
- package/dist/Helpers/CrudBackend.d.ts +20 -2
- package/dist/Helpers/CrudBackend.js +46 -2
- package/dist/Helpers/CrudColumns.d.ts +91 -6
- package/dist/Helpers/CrudColumns.js +148 -7
- package/dist/Helpers/CrudDetailsTabs.d.ts +58 -0
- package/dist/Helpers/CrudDetailsTabs.js +126 -0
- package/dist/Helpers/CrudHelpers.d.ts +116 -2
- package/dist/Helpers/CrudHelpers.js +256 -0
- package/dist/Helpers/CrudNarrowPick.d.ts +83 -0
- package/dist/Helpers/CrudNarrowPick.js +157 -0
- package/dist/Helpers/CrudPickerPlan.d.ts +58 -0
- package/dist/Helpers/CrudPickerPlan.js +46 -0
- package/dist/Helpers/CrudRowForms.d.ts +32 -0
- package/dist/Helpers/CrudRowForms.js +76 -0
- package/dist/Helpers/CrudScopes.d.ts +32 -0
- package/dist/Helpers/CrudScopes.js +79 -0
- package/dist/Helpers/DashboardHelpers.d.ts +115 -0
- package/dist/Helpers/DashboardHelpers.js +305 -0
- package/dist/Helpers/DomainCards.d.ts +140 -0
- package/dist/Helpers/DomainCards.js +370 -0
- package/dist/Helpers/DropdownHelpers.d.ts +3 -1
- package/dist/Helpers/DropdownHelpers.js +6 -2
- package/dist/Helpers/ExcelHelpers.d.ts +1 -1
- package/dist/Helpers/ExcelHelpers.js +12 -11
- package/dist/Helpers/FileAdapter.d.ts +158 -0
- package/dist/Helpers/FileAdapter.js +173 -0
- package/dist/Helpers/FilePrimaries.d.ts +48 -0
- package/dist/Helpers/FilePrimaries.js +138 -0
- package/dist/Helpers/FormConfirm.d.ts +32 -0
- package/dist/Helpers/FormConfirm.js +40 -0
- package/dist/Helpers/FormStore.d.ts +100 -5
- package/dist/Helpers/FormStore.js +368 -25
- package/dist/Helpers/InputConditions.d.ts +56 -0
- package/dist/Helpers/InputConditions.js +192 -0
- package/dist/Helpers/InputMemory.d.ts +106 -0
- package/dist/Helpers/InputMemory.js +395 -0
- package/dist/Helpers/InputNarrowing.d.ts +50 -0
- package/dist/Helpers/InputNarrowing.js +148 -0
- package/dist/Helpers/InputParamsHelpers.d.ts +44 -1
- package/dist/Helpers/InputParamsHelpers.js +157 -74
- package/dist/Helpers/MailClientHelpers.d.ts +96 -0
- package/dist/Helpers/MailClientHelpers.js +211 -0
- package/dist/Helpers/MessageBackend.d.ts +152 -0
- package/dist/Helpers/MessageBackend.js +329 -0
- package/dist/Helpers/MessageHelpers.d.ts +160 -0
- package/dist/Helpers/MessageHelpers.js +573 -0
- package/dist/Helpers/MessageUnread.d.ts +95 -0
- package/dist/Helpers/MessageUnread.js +245 -0
- package/dist/Helpers/NexusDriveAdapter.d.ts +71 -0
- package/dist/Helpers/NexusDriveAdapter.js +236 -0
- package/dist/Helpers/NumberHelpers.d.ts +156 -0
- package/dist/Helpers/NumberHelpers.js +242 -0
- package/dist/Helpers/PagedPicker.d.ts +42 -0
- package/dist/Helpers/PagedPicker.js +85 -0
- package/dist/Helpers/Permissions.js +2 -1
- package/dist/Helpers/QrCode.d.ts +26 -0
- package/dist/Helpers/QrCode.js +463 -0
- package/dist/Helpers/RecordCards.d.ts +205 -0
- package/dist/Helpers/RecordCards.js +378 -0
- package/dist/Helpers/RequestCache.d.ts +14 -2
- package/dist/Helpers/RequestCache.js +22 -3
- package/dist/Helpers/RowsStore.d.ts +61 -2
- package/dist/Helpers/RowsStore.js +203 -16
- package/dist/Helpers/ServerPreview.d.ts +69 -0
- package/dist/Helpers/ServerPreview.js +99 -0
- package/dist/Helpers/TableColumns.js +4 -3
- package/dist/Helpers/TableExport.d.ts +7 -1
- package/dist/Helpers/TableExport.js +9 -3
- package/dist/Helpers/TableFilters.d.ts +1 -1
- package/dist/Helpers/TableFilters.js +24 -23
- package/dist/Helpers/TableHelpers.d.ts +38 -4
- package/dist/Helpers/TableHelpers.js +78 -10
- package/dist/Helpers/TableJoins.d.ts +13 -0
- package/dist/Helpers/TableJoins.js +34 -0
- package/dist/Helpers/TableStore.d.ts +28 -4
- package/dist/Helpers/TableStore.js +73 -11
- package/dist/Helpers/ToolbarFit.d.ts +23 -0
- package/dist/Helpers/ToolbarFit.js +30 -0
- package/dist/Helpers/TreeStore.d.ts +156 -6
- package/dist/Helpers/TreeStore.js +547 -18
- package/dist/Interfaces/ApiInterfaces.d.ts +10 -1
- package/dist/Interfaces/ApiInterfaces.js +10 -1
- package/dist/Interfaces/ChatInterfaces.d.ts +22 -0
- package/dist/Interfaces/CrudInterfaces.d.ts +539 -6
- package/dist/Interfaces/DashboardInterfaces.d.ts +123 -0
- package/dist/Interfaces/DashboardInterfaces.js +1 -0
- package/dist/Interfaces/DomainInterfaces.d.ts +145 -0
- package/dist/Interfaces/DomainInterfaces.js +1 -0
- package/dist/Interfaces/FileInterfaces.d.ts +183 -0
- package/dist/Interfaces/FileInterfaces.js +6 -0
- package/dist/Interfaces/FormInterfaces.d.ts +460 -32
- package/dist/Interfaces/FormInterfaces.js +79 -1
- package/dist/Interfaces/InputInterfaces.d.ts +22 -3
- package/dist/Interfaces/MailInterfaces.d.ts +192 -0
- package/dist/Interfaces/MailInterfaces.js +1 -0
- package/dist/Interfaces/RecordInterfaces.d.ts +367 -0
- package/dist/Interfaces/RecordInterfaces.js +1 -0
- package/dist/Interfaces/TableInterfaces.d.ts +102 -3
- package/dist/Services/ExcelApi.js +5 -0
- package/dist/Services/FileApi.d.ts +13 -0
- package/dist/Services/FileApi.js +29 -0
- package/dist/Services/ImageEditorLoader.d.ts +14 -0
- package/dist/Services/ImageEditorLoader.js +51 -0
- package/dist/Services/JoinSources.d.ts +79 -6
- package/dist/Services/JoinSources.js +132 -21
- package/dist/Services/MessageApi.d.ts +18 -0
- package/dist/Services/MessageApi.js +64 -0
- package/dist/Services/ModuleImport.d.ts +7 -0
- package/dist/Services/ModuleImport.js +22 -0
- package/dist/Shared.Index.d.ts +28 -0
- package/dist/Shared.Index.js +28 -0
- package/package.json +13 -2
- package/src/Styles/Nexus.Avatar.css +6 -5
- package/src/Styles/Nexus.Button.css +39 -4
- package/src/Styles/Nexus.Chat.css +114 -22
- package/src/Styles/Nexus.Choice.css +16 -0
- package/src/Styles/Nexus.Crud.css +486 -21
- package/src/Styles/Nexus.Dashboard.css +763 -0
- package/src/Styles/Nexus.Domain.css +384 -0
- package/src/Styles/Nexus.Dropdown.css +8 -0
- package/src/Styles/Nexus.Editor.css +20 -0
- package/src/Styles/Nexus.Files.css +437 -0
- package/src/Styles/Nexus.Form.css +5 -2
- package/src/Styles/Nexus.Index.css +7 -0
- package/src/Styles/Nexus.Input.css +73 -0
- package/src/Styles/Nexus.Mail.css +1062 -0
- package/src/Styles/Nexus.Menu.css +10 -1
- package/src/Styles/Nexus.Popup.css +135 -1
- package/src/Styles/Nexus.Print.css +288 -0
- package/src/Styles/Nexus.QrCode.css +12 -0
- package/src/Styles/Nexus.Record.css +430 -0
- package/src/Styles/Nexus.Tab.Buttons.css +87 -22
- package/src/Styles/Nexus.Table.css +1458 -1387
- package/src/Styles/Nexus.Theme.Picker.css +1 -0
- package/src/Styles/Nexus.Themes.css +12 -6
- package/src/Styles/Nexus.Tokens.css +8 -3
- package/src/Styles/Nexus.Tree.css +41 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A widget's size on the board's 12-column grid: `S` 3×1, `M` 6×2, `L` 6×4, `W` 12×2, `T` 12×4 (columns × rows).
|
|
4
|
+
* Presets rather than free resizing: fewer layouts that look broken, and nothing to work out on a phone, where every
|
|
5
|
+
* widget is the full width.
|
|
6
|
+
*/
|
|
7
|
+
export type WidgetSize = "S" | "M" | "L" | "W" | "T";
|
|
8
|
+
/** Where a widget may go: `own` only on its module's dashboard, `anywhere` on any dashboard (the Home too). */
|
|
9
|
+
export type WidgetPlacement = "own" | "anywhere";
|
|
10
|
+
/** One widget on a board: which, and how big. A layout is an ordered list of these: no coordinates are kept. */
|
|
11
|
+
export interface DashboardLayoutItem {
|
|
12
|
+
code: string;
|
|
13
|
+
size: WidgetSize;
|
|
14
|
+
}
|
|
15
|
+
/** A board's layout: the widgets in the order they flow, the grid filling every gap (`grid-auto-flow: dense`). */
|
|
16
|
+
export type DashboardLayout = readonly DashboardLayoutItem[];
|
|
17
|
+
/** The version a saved layout carries, so two windows never overwrite each other unseen. */
|
|
18
|
+
export type DashboardVersion = string | number | null;
|
|
19
|
+
/**
|
|
20
|
+
* What a save (or a reset) answered. `saved` with the new version; `stale` when another window saved first (the
|
|
21
|
+
* server's 409): its layout and version, which the board shows in place of the edit; `failed` with a sentence.
|
|
22
|
+
*/
|
|
23
|
+
export type DashboardSaveResult = {
|
|
24
|
+
status: "saved";
|
|
25
|
+
version: DashboardVersion;
|
|
26
|
+
layout?: DashboardLayout;
|
|
27
|
+
} | {
|
|
28
|
+
status: "stale";
|
|
29
|
+
layout: DashboardLayout;
|
|
30
|
+
version: DashboardVersion;
|
|
31
|
+
} | {
|
|
32
|
+
status: "failed";
|
|
33
|
+
message?: string;
|
|
34
|
+
};
|
|
35
|
+
/** What a widget's `load` and `render` are told. */
|
|
36
|
+
export interface WidgetContext {
|
|
37
|
+
/** The board's place (`home`, `message`, ...). */
|
|
38
|
+
place: string;
|
|
39
|
+
/** The size it is drawn at. */
|
|
40
|
+
size: WidgetSize;
|
|
41
|
+
}
|
|
42
|
+
/** What a widget's `render` is told besides its data. */
|
|
43
|
+
export interface WidgetRenderContext extends WidgetContext {
|
|
44
|
+
/** Reads the widget's data again now. */
|
|
45
|
+
refresh: () => void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A widget answered by its module's one call per draw: the board gathers the codes of every widget of `module` that
|
|
49
|
+
* is near the screen and asks the app's `loadModule(module, codes)` once. `codes` are the parts this widget needs from
|
|
50
|
+
* that answer (default: its own code); `pick` turns them into its data (default: the one part, or every part by code
|
|
51
|
+
* when there are several).
|
|
52
|
+
*/
|
|
53
|
+
export interface WidgetBatch<TData = unknown> {
|
|
54
|
+
module: string;
|
|
55
|
+
codes?: readonly string[];
|
|
56
|
+
pick?: (parts: Readonly<Record<string, unknown>>) => TData;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A widget, declared once in the app's code: what it is, where it may go, its sizes, who may see it, where its data
|
|
60
|
+
* comes from and how it is drawn. Nothing about a widget lives in a database: only layouts do.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const unread: WidgetDefinition<MailCounts> = {
|
|
64
|
+
* code: "message.counts", module: "message", placement: "anywhere", title: "Mail", sizes: ["S", "M"],
|
|
65
|
+
* batch: { module: "message" }, refresh: 60,
|
|
66
|
+
* render: counts => <StatWidget items={[{ label: "Unread", value: counts.unread, href: "/admin/message?list=2" }]} />,
|
|
67
|
+
* };
|
|
68
|
+
*/
|
|
69
|
+
export interface WidgetDefinition<TData = unknown> {
|
|
70
|
+
/** Unique in the app, `module.name`: `message.counts`, `requisition.my-approvals`. What a layout keeps. */
|
|
71
|
+
code: string;
|
|
72
|
+
/** The module it belongs to: the Add list groups by it, and an `own` widget goes only on its module's board. */
|
|
73
|
+
module: string;
|
|
74
|
+
placement: WidgetPlacement;
|
|
75
|
+
/** Its heading on the board and in the Add list. */
|
|
76
|
+
title: string;
|
|
77
|
+
/** A sentence under the title in the Add list. */
|
|
78
|
+
description?: string;
|
|
79
|
+
/** Beside the title in the Add list. */
|
|
80
|
+
icon?: ReactNode;
|
|
81
|
+
/** The sizes it can take, the first the default. At least one. */
|
|
82
|
+
sizes: readonly WidgetSize[];
|
|
83
|
+
/**
|
|
84
|
+
* The permission key whose holder may see it (none: everyone signed in). The board does not read it: the app's
|
|
85
|
+
* `canSee(widget)` does, with whatever it knows of the person and the company.
|
|
86
|
+
*/
|
|
87
|
+
key?: string;
|
|
88
|
+
/** Its own data call. A widget with neither `load` nor `batch` needs no data (a version, a clock). */
|
|
89
|
+
load?: (context: WidgetContext) => Promise<TData>;
|
|
90
|
+
/** Its part of its module's one call per draw, in place of `load`. */
|
|
91
|
+
batch?: WidgetBatch<TData>;
|
|
92
|
+
/** Seconds its data stays fresh while the page is open: read again after that while it is on screen. Default: the page's life. */
|
|
93
|
+
refresh?: number;
|
|
94
|
+
/** Draws it from its data. */
|
|
95
|
+
render: (data: TData, context: WidgetRenderContext) => ReactNode;
|
|
96
|
+
/** Whether the data is nothing to show: the frame then says `empty`. Default: `null`, `undefined` or an empty list. */
|
|
97
|
+
isEmpty?: (data: TData) => boolean;
|
|
98
|
+
/** What an empty widget says. Default "Nothing to show yet." */
|
|
99
|
+
empty?: ReactNode;
|
|
100
|
+
/** A link in its heading, to the page its data comes from. */
|
|
101
|
+
link?: {
|
|
102
|
+
href: string;
|
|
103
|
+
label?: string;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** What `loadModule` answers: each asked code's part. A code left out is a part the person may not see (empty). */
|
|
107
|
+
export type WidgetModuleAnswer = Readonly<Record<string, unknown>>;
|
|
108
|
+
/** The app's one call per module per draw. */
|
|
109
|
+
export type WidgetModuleLoader = (module: string, codes: readonly string[]) => Promise<WidgetModuleAnswer>;
|
|
110
|
+
/** A widget's data as the board holds it. */
|
|
111
|
+
export type WidgetState<TData = unknown> = {
|
|
112
|
+
status: "idle";
|
|
113
|
+
} | {
|
|
114
|
+
status: "loading";
|
|
115
|
+
data?: TData;
|
|
116
|
+
} | {
|
|
117
|
+
status: "ready";
|
|
118
|
+
data: TData;
|
|
119
|
+
at: number;
|
|
120
|
+
} | {
|
|
121
|
+
status: "failed";
|
|
122
|
+
message: string;
|
|
123
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ChatDomainValue, ChatId } from "./ChatInterfaces.ts";
|
|
3
|
+
import type { Tone } from "./TypeInterfaces.ts";
|
|
4
|
+
/** How a value is written: a plain text, a date or a moment in the reader's settings, days, money, a person's name. */
|
|
5
|
+
export type DomainCardValueKind = "text" | "number" | "date" | "datetime" | "days" | "money" | "person";
|
|
6
|
+
/** One field of a card: its label and value, written by its kind. A field with no value is left out. */
|
|
7
|
+
export interface DomainCardField {
|
|
8
|
+
label: string;
|
|
9
|
+
/** An ISO date for `date`, a UTC moment for `datetime`, a number for `days`, `number` and `money`. */
|
|
10
|
+
value: string | number | null | undefined;
|
|
11
|
+
/** Default `text`. */
|
|
12
|
+
kind?: DomainCardValueKind;
|
|
13
|
+
/** Words after the value, quieter: "second half", "from the 2081/82 year". */
|
|
14
|
+
note?: string;
|
|
15
|
+
/** Written in place of a missing value; without it the field is left out. */
|
|
16
|
+
empty?: string;
|
|
17
|
+
/** A `money` field's currency, over the card's. */
|
|
18
|
+
currency?: string;
|
|
19
|
+
}
|
|
20
|
+
/** A figure: a number that matters, drawn large in a row of them ("Available 14 days", "Taken 5 days"). */
|
|
21
|
+
export interface DomainCardFigure {
|
|
22
|
+
label: string;
|
|
23
|
+
/** A number is written by its kind; a text as it is. A missing value is written as "-". */
|
|
24
|
+
value: number | string | null | undefined;
|
|
25
|
+
/** Default `number`. `days` writes the unit "day" or "days" by itself. */
|
|
26
|
+
kind?: Extract<DomainCardValueKind, "number" | "days" | "money">;
|
|
27
|
+
/** Words after the value, smaller: "items". Left out for `days` (its own) and `money` (its currency). */
|
|
28
|
+
unit?: string;
|
|
29
|
+
/** Marks the figure with its colour beside it: `warning` for days held, `danger` for an overdrawn balance. */
|
|
30
|
+
tone?: Tone;
|
|
31
|
+
/** A short line under the figure: "2 of them this request". */
|
|
32
|
+
hint?: string;
|
|
33
|
+
/** A `money` figure's currency, over the card's. */
|
|
34
|
+
currency?: string;
|
|
35
|
+
}
|
|
36
|
+
/** A column of a card's lines. */
|
|
37
|
+
export interface DomainCardLineColumn {
|
|
38
|
+
label: string;
|
|
39
|
+
/** Default `text`; `number`, `money` and `days` sit at the end. */
|
|
40
|
+
kind?: DomainCardValueKind;
|
|
41
|
+
/** Default: the end for numbers, the start for the rest. */
|
|
42
|
+
align?: "start" | "end";
|
|
43
|
+
}
|
|
44
|
+
/** A short table on a card: the first items of a requisition, with how many more there are. */
|
|
45
|
+
export interface DomainCardLines {
|
|
46
|
+
columns: readonly DomainCardLineColumn[];
|
|
47
|
+
/** One row per line, a value per column, written by the column's kind. */
|
|
48
|
+
rows: readonly (readonly (string | number | null | undefined)[])[];
|
|
49
|
+
/** Lines the card does not show: "and 3 more". */
|
|
50
|
+
more?: number;
|
|
51
|
+
/** What the lines are, for a screen reader: "Items". Default "Lines". */
|
|
52
|
+
label?: string;
|
|
53
|
+
}
|
|
54
|
+
/** Where the record can be opened in full: a link at the end of the line under the title. */
|
|
55
|
+
export interface DomainCardLink {
|
|
56
|
+
href: string;
|
|
57
|
+
label: string;
|
|
58
|
+
/** `_blank` opens a new tab. */
|
|
59
|
+
target?: string;
|
|
60
|
+
}
|
|
61
|
+
/** A card as it is drawn: what an app's `view` makes of its module's answer. */
|
|
62
|
+
export interface DomainCardParams {
|
|
63
|
+
/** What the record is, in a few words: "Home leave · 2 days". */
|
|
64
|
+
title: string;
|
|
65
|
+
/** Its number, on the quiet line under the title: "LR2082-0007". */
|
|
66
|
+
code?: string | null;
|
|
67
|
+
/** Words on the line under the title, after the code: the request's own title. */
|
|
68
|
+
subtitle?: string | null;
|
|
69
|
+
/** Where it stands, as a tag in its tone: "In approval" (info), "Rejected" (danger). */
|
|
70
|
+
state?: {
|
|
71
|
+
label: string;
|
|
72
|
+
tone?: Tone;
|
|
73
|
+
} | null;
|
|
74
|
+
fields?: readonly DomainCardField[];
|
|
75
|
+
figures?: readonly DomainCardFigure[];
|
|
76
|
+
lines?: DomainCardLines | null;
|
|
77
|
+
link?: DomainCardLink | null;
|
|
78
|
+
/** The currency every `money` value is written in, unless it names its own: "Rs.". */
|
|
79
|
+
currency?: string | null;
|
|
80
|
+
}
|
|
81
|
+
/** What a card's `load`, `view` and `extra` are told besides the record. */
|
|
82
|
+
export interface DomainCardContext {
|
|
83
|
+
/** The record's kind: the app's own domain value. */
|
|
84
|
+
domainType: ChatDomainValue;
|
|
85
|
+
/** The record's id, as the reader may open it (a token sealed for them). */
|
|
86
|
+
id: ChatId;
|
|
87
|
+
/** Who reads, when the page says (a thread's reader). */
|
|
88
|
+
viewer?: ChatId;
|
|
89
|
+
/** The record's words as the message holds them: "LR2082-0007 · Puja Shrestha". */
|
|
90
|
+
label?: string | null;
|
|
91
|
+
/** The kind's name on screen, from `defineChatDomains`: "Leave request". */
|
|
92
|
+
kind?: string;
|
|
93
|
+
}
|
|
94
|
+
/** How many of each part a card holds: what its placeholder draws while it loads, so it does not jump when it lands. */
|
|
95
|
+
export interface DomainCardShape {
|
|
96
|
+
/** The quiet line under the title: the code, the subtitle, the link. */
|
|
97
|
+
subtitle: boolean;
|
|
98
|
+
state: boolean;
|
|
99
|
+
fields: number;
|
|
100
|
+
figures: number;
|
|
101
|
+
/** Which figures, counted from 0, have a hint under them. */
|
|
102
|
+
hints: readonly number[];
|
|
103
|
+
/** Rows of lines shown, and their columns. */
|
|
104
|
+
lines: number;
|
|
105
|
+
columns: number;
|
|
106
|
+
/** An "and 3 more" under the lines. */
|
|
107
|
+
more: boolean;
|
|
108
|
+
link: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The card of one kind of record: how to read it and how to show it. Give it to the kind's row of `defineChatDomains`
|
|
112
|
+
* (`card`); `domainCard(...)` types `view` by what `load` answers.
|
|
113
|
+
*/
|
|
114
|
+
export interface DomainCardDefinition<TData = unknown> {
|
|
115
|
+
/**
|
|
116
|
+
* Reads the record from the module that owns it: its card door, which checks the reader. A refusal of the reader
|
|
117
|
+
* (403) or a record that is not there for them (404) is shown as "You cannot open this ..."; any other failure as a
|
|
118
|
+
* failure with Try again. The signal aborts when nobody waits for the answer any more.
|
|
119
|
+
*/
|
|
120
|
+
load(id: ChatId, signal: AbortSignal, context: DomainCardContext): Promise<TData>;
|
|
121
|
+
/** Maps the answer to what the card draws. */
|
|
122
|
+
view(data: TData, context: DomainCardContext): DomainCardParams;
|
|
123
|
+
/** One more piece after the lines, made of this package's parts, for a kind that needs it. */
|
|
124
|
+
extra?(data: TData, context: DomainCardContext): ReactNode;
|
|
125
|
+
/** What the placeholder holds the first time a card of this kind loads; later ones hold the last card's shape. */
|
|
126
|
+
held?: Partial<DomainCardShape>;
|
|
127
|
+
/** How long an answer is kept for every card of the page, in milliseconds. Default 30,000; 0 keeps none. */
|
|
128
|
+
lifetime?: number;
|
|
129
|
+
}
|
|
130
|
+
/** Where one card stands. */
|
|
131
|
+
export type DomainCardStatus = "loading" | "ready" | "refused" | "failed";
|
|
132
|
+
/** One card's read, as its component draws it. */
|
|
133
|
+
export interface DomainCardSnapshot<TData = unknown> {
|
|
134
|
+
status: DomainCardStatus;
|
|
135
|
+
/** The record as last read: kept on screen while it is read again, and when reading again fails. */
|
|
136
|
+
data?: TData;
|
|
137
|
+
/** A read is on its way while the card shows what it read before. */
|
|
138
|
+
refreshing: boolean;
|
|
139
|
+
/** The last read again failed: the card on screen is the one read before. */
|
|
140
|
+
refreshFailed: boolean;
|
|
141
|
+
/** When a read again found the record changed from the one on screen (milliseconds since 1970). */
|
|
142
|
+
changedAt?: number;
|
|
143
|
+
/** Why the last read failed. */
|
|
144
|
+
error?: unknown;
|
|
145
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { ApiModuleValue, AppModule } from "./ApiInterfaces.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Whose files: the module that owns the row, the category, and the row's id. The module decides who may change them
|
|
4
|
+
* (with Nexus, its `Files/Ticket` signs the change), so it is the owner's module, not the one that stores the bytes.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* { module: NexusModule.Enterprise, category: "branch-picture", ownerId: branch.id }
|
|
8
|
+
* { module: NexusModule.Enterprise, category: "user-picture", ownerId: "me" } // the person's own
|
|
9
|
+
*/
|
|
10
|
+
export interface FileOwner<TModule extends ApiModuleValue = AppModule> {
|
|
11
|
+
module: TModule;
|
|
12
|
+
/** The category's code: `branch-picture`, `subscriber-document`. */
|
|
13
|
+
category: string;
|
|
14
|
+
/** The owner row's id, as the module answers it; `me` for the person's own. */
|
|
15
|
+
ownerId: string;
|
|
16
|
+
}
|
|
17
|
+
/** Which copy of a stored file: the file itself, or its small picture. */
|
|
18
|
+
export type FileCopy = "original" | "thumbnail";
|
|
19
|
+
/**
|
|
20
|
+
* One way an owner's files change: a file added, renamed, made the owner's picture (or none), or deleted. In words, as a
|
|
21
|
+
* category's kinds are MIME types; they are the Nexus core's `EFileChanges` (Add 1, Rename 2, Primary 3, Remove 4) one
|
|
22
|
+
* for one. A record whose files may only be added to - a posted goods receipt's documents - allows `["add"]`.
|
|
23
|
+
*/
|
|
24
|
+
export type FileChange = "add" | "rename" | "primary" | "remove";
|
|
25
|
+
/** Every change, in the order the core numbers them. */
|
|
26
|
+
export declare const FILE_CHANGES: readonly FileChange[];
|
|
27
|
+
/** One stored file, as the adapter reads it. */
|
|
28
|
+
export interface StoredFile {
|
|
29
|
+
/** Its id, as the backend answers it (with Nexus, encrypted for the person asking). */
|
|
30
|
+
id: string;
|
|
31
|
+
/** The name it is shown by, with the extension of what it really is. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** What its bytes are: `image/png`, `image/jpeg`, `image/webp`, `application/pdf`. */
|
|
34
|
+
contentType: string;
|
|
35
|
+
/** Its size in bytes. */
|
|
36
|
+
size: number;
|
|
37
|
+
/** A picture's size in pixels; null for a document. */
|
|
38
|
+
width: number | null;
|
|
39
|
+
height: number | null;
|
|
40
|
+
/** Whether a thumbnail was stored with it. Without one, the thumbnail copy is the file itself (pictures only). */
|
|
41
|
+
hasThumbnail: boolean;
|
|
42
|
+
/** Whether it is the owner's picture: at most one per owner and category. */
|
|
43
|
+
isPrimary: boolean;
|
|
44
|
+
/** When it was stored: an ISO UTC moment, or null when the backend does not say. */
|
|
45
|
+
createdAt: string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Its Delete waits for a review: in a category that holds removals (`FileCategoryInfo.holdsRemovals`, a reviewed
|
|
48
|
+
* gallery) a Delete only marks the file, which is still served and listed until the reviewer decides, and the person
|
|
49
|
+
* may Keep it (`FileAdapter.keep`) until then. Left out (or false) for every other file.
|
|
50
|
+
*/
|
|
51
|
+
pendingRemoval?: boolean;
|
|
52
|
+
/** When its removal was asked, while it waits for the review: an ISO UTC moment, when the backend says. */
|
|
53
|
+
removalAt?: string;
|
|
54
|
+
}
|
|
55
|
+
/** What a category takes, as the backend says: what a gallery tells the person before an upload is refused. */
|
|
56
|
+
export interface FileCategoryInfo {
|
|
57
|
+
/** The category's code. */
|
|
58
|
+
code: string;
|
|
59
|
+
/** Its name: "Branch picture". */
|
|
60
|
+
name: string;
|
|
61
|
+
/** The MIME types it takes: `["image/png", "image/jpeg", "image/webp"]`. */
|
|
62
|
+
types: readonly string[];
|
|
63
|
+
/** The largest file it takes, in bytes. */
|
|
64
|
+
maxBytes: number;
|
|
65
|
+
/** How many files one owner keeps. */
|
|
66
|
+
maxCount: number;
|
|
67
|
+
/** The longest side of a thumbnail in pixels; 0 when it keeps none. */
|
|
68
|
+
thumbnailSize: number;
|
|
69
|
+
/** Whether this person may change the files: upload, make primary, rename, delete. */
|
|
70
|
+
canWrite: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The longest side a stored picture may have, in pixels: Drive's `Nexus:Drive:Pictures:MaxSide`. Every picture is
|
|
73
|
+
* made to fit it in the browser before it is sent. Default `PICTURE_LIMITS.maxSide` (1920) when the backend does not say.
|
|
74
|
+
*/
|
|
75
|
+
pictureMaxSide?: number;
|
|
76
|
+
/** The highest quality a picture is written at, in percent: Drive's `Quality`. Default `PICTURE_LIMITS.quality` (80). */
|
|
77
|
+
pictureQuality?: number;
|
|
78
|
+
/**
|
|
79
|
+
* The most bytes a stored picture may hold: Drive's `MaxKilobytes`, never above `maxBytes`. The browser writes every
|
|
80
|
+
* picture under it (a lower quality, then a smaller size). Default `PICTURE_LIMITS.maxBytes` (300 KB), at most `maxBytes`.
|
|
81
|
+
*/
|
|
82
|
+
pictureMaxBytes?: number;
|
|
83
|
+
/**
|
|
84
|
+
* A Delete here waits for a review (a company's public gallery, which Nexus support approves): the file is marked
|
|
85
|
+
* `pendingRemoval`, not removed, until the reviewer decides. Left out (or false) where a Delete removes at once.
|
|
86
|
+
*/
|
|
87
|
+
holdsRemovals?: boolean;
|
|
88
|
+
}
|
|
89
|
+
/** An owner's files and what their category takes. */
|
|
90
|
+
export interface OwnerFiles {
|
|
91
|
+
category: FileCategoryInfo;
|
|
92
|
+
/** The live files, in their order. */
|
|
93
|
+
files: StoredFile[];
|
|
94
|
+
/**
|
|
95
|
+
* Why this person may only look (`category.canWrite` false), in the backend's words when it gave them: the refusal of
|
|
96
|
+
* the write ticket ("You do not hold the key to change this branch").
|
|
97
|
+
*/
|
|
98
|
+
readOnlyReason?: string;
|
|
99
|
+
}
|
|
100
|
+
/** What an upload sends: the file the browser made, and for a picture its thumbnail. */
|
|
101
|
+
export interface FileUpload {
|
|
102
|
+
file: Blob;
|
|
103
|
+
/** The name to keep: "Front desk.jpg". The backend keeps the real kind's extension whatever it says. */
|
|
104
|
+
name: string;
|
|
105
|
+
thumbnail?: Blob | null;
|
|
106
|
+
}
|
|
107
|
+
/** What every call of the adapter takes. */
|
|
108
|
+
export interface FileCallOptions {
|
|
109
|
+
signal?: AbortSignal;
|
|
110
|
+
/** Shows no toast for this call: the panel says what happened. */
|
|
111
|
+
toast?: false;
|
|
112
|
+
}
|
|
113
|
+
/** Picture kinds a browser canvas writes, and so the ones the editor saves. */
|
|
114
|
+
export type PictureType = "image/jpeg" | "image/png" | "image/webp";
|
|
115
|
+
/** The MIME types of pictures (what a canvas can read back), in the order a file picker offers them. */
|
|
116
|
+
export declare const PICTURE_TYPES: readonly PictureType[];
|
|
117
|
+
/** Whether a MIME type is a picture this package can show and edit. */
|
|
118
|
+
export declare const isPictureType: (type: string | null | undefined) => type is PictureType;
|
|
119
|
+
/** What the editor is opened with (a part of `nexus-image-editor`'s `ImageEditorOptions`). */
|
|
120
|
+
export interface ImageEditorOptions {
|
|
121
|
+
src?: File | Blob | string;
|
|
122
|
+
/** A number locks the shape (1 for a logo or an avatar); `free` lets the person choose. */
|
|
123
|
+
aspect?: number | "free" | "original" | Array<number | "free" | "original">;
|
|
124
|
+
/** A round guide over a square crop, for a person's picture. */
|
|
125
|
+
shape?: "rect" | "circle";
|
|
126
|
+
maxWidth?: number;
|
|
127
|
+
maxHeight?: number;
|
|
128
|
+
minWidth?: number;
|
|
129
|
+
minHeight?: number;
|
|
130
|
+
type?: PictureType;
|
|
131
|
+
/**
|
|
132
|
+
* The kinds the place the picture goes to takes (a file category's): the only ones the editor offers and saves - a
|
|
133
|
+
* picture too large as a PNG becomes a JPEG or a WebP only when one of them is taken, else stays a PNG, made smaller.
|
|
134
|
+
*/
|
|
135
|
+
types?: readonly PictureType[];
|
|
136
|
+
/** 0-1. */
|
|
137
|
+
quality?: number;
|
|
138
|
+
/** 0-1: the highest quality written (the slider's top, where it starts at most). */
|
|
139
|
+
maxQuality?: number;
|
|
140
|
+
/** The most bytes the saved file may hold: a lower quality, then a smaller picture, until it fits. */
|
|
141
|
+
maxBytes?: number;
|
|
142
|
+
/** The longest side of a thumbnail made with the picture, in pixels. */
|
|
143
|
+
thumbnail?: number | boolean;
|
|
144
|
+
title?: string;
|
|
145
|
+
fileName?: string;
|
|
146
|
+
signal?: AbortSignal;
|
|
147
|
+
}
|
|
148
|
+
/** What the editor answers on Save. */
|
|
149
|
+
export interface ImageEditorResult {
|
|
150
|
+
blob: Blob;
|
|
151
|
+
width: number;
|
|
152
|
+
height: number;
|
|
153
|
+
type: string;
|
|
154
|
+
thumbnail: Blob | null;
|
|
155
|
+
name: string;
|
|
156
|
+
/** What `maxBytes` took (another type, a lower quality 0-1, the size it would have had), or null when nothing. */
|
|
157
|
+
fitted?: {
|
|
158
|
+
maxBytes: number;
|
|
159
|
+
type?: string;
|
|
160
|
+
quality?: number;
|
|
161
|
+
from?: {
|
|
162
|
+
width: number;
|
|
163
|
+
height: number;
|
|
164
|
+
};
|
|
165
|
+
} | null;
|
|
166
|
+
}
|
|
167
|
+
/** One picture of the viewer. */
|
|
168
|
+
export interface ImageViewerItem {
|
|
169
|
+
src: string | Blob;
|
|
170
|
+
title?: string;
|
|
171
|
+
}
|
|
172
|
+
/** The parts of `nexus-image-editor` this package calls. */
|
|
173
|
+
export interface ImageEditorModule {
|
|
174
|
+
openImageEditor(options?: ImageEditorOptions): Promise<ImageEditorResult | null>;
|
|
175
|
+
openImageViewer(options: {
|
|
176
|
+
images: ImageViewerItem[];
|
|
177
|
+
index?: number;
|
|
178
|
+
title?: string;
|
|
179
|
+
}): Promise<void>;
|
|
180
|
+
/** Makes the stored picture without opening the editor: the size clamped, the thumbnail made. `null` edits: as it is. */
|
|
181
|
+
renderImage(src: File | Blob | string, edits: null, options?: Pick<ImageEditorOptions, "maxWidth" | "maxHeight" | "type" | "types" | "quality" | "maxQuality" | "maxBytes" | "thumbnail">): Promise<Omit<ImageEditorResult, "name">>;
|
|
182
|
+
readonly VERSION: string;
|
|
183
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Every change, in the order the core numbers them. */
|
|
2
|
+
export const FILE_CHANGES = ["add", "rename", "primary", "remove"];
|
|
3
|
+
/** The MIME types of pictures (what a canvas can read back), in the order a file picker offers them. */
|
|
4
|
+
export const PICTURE_TYPES = ["image/jpeg", "image/png", "image/webp"];
|
|
5
|
+
/** Whether a MIME type is a picture this package can show and edit. */
|
|
6
|
+
export const isPictureType = (type) => PICTURE_TYPES.includes(type);
|