nexus-shared 1.1.21 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +903 -0
- package/dist/Client.Index.d.ts +44 -0
- package/dist/Client.Index.js +49 -0
- package/dist/Components/Documents/Button.d.ts +29 -0
- package/dist/Components/Documents/Button.js +11 -0
- package/dist/Components/Documents/Menu.d.ts +102 -0
- package/dist/Components/Documents/Menu.js +238 -0
- package/dist/Components/Documents/SplitButton.d.ts +64 -0
- package/dist/Components/Documents/SplitButton.js +127 -0
- package/dist/Components/Documents/TabButtons.d.ts +62 -0
- package/dist/Components/Documents/TabButtons.js +19 -0
- package/dist/Components/Forms/ApiForm.d.ts +21 -0
- package/dist/Components/Forms/ApiForm.js +99 -0
- package/dist/Components/Forms/Crud.d.ts +17 -0
- package/dist/Components/Forms/Crud.js +556 -0
- package/dist/Components/Forms/CrudParts.d.ts +15 -0
- package/dist/Components/Forms/CrudParts.js +36 -0
- package/dist/Components/Forms/Form.d.ts +52 -0
- package/dist/Components/Forms/Form.js +319 -0
- package/dist/Components/Forms/SubmitForm.d.ts +65 -0
- package/dist/Components/Forms/SubmitForm.js +198 -0
- package/dist/Components/Inputs/Calendar.d.ts +69 -0
- package/dist/Components/Inputs/Calendar.js +258 -0
- package/dist/Components/Inputs/CheckBox.d.ts +53 -0
- package/dist/Components/Inputs/CheckBox.js +87 -0
- package/dist/Components/Inputs/CheckBoxGroup.d.ts +20 -0
- package/dist/Components/Inputs/CheckBoxGroup.js +80 -0
- package/dist/Components/Inputs/ChoiceField.d.ts +122 -0
- package/dist/Components/Inputs/ChoiceField.js +169 -0
- package/dist/Components/Inputs/DatePicker.d.ts +54 -0
- package/dist/Components/Inputs/DatePicker.js +246 -0
- package/dist/Components/Inputs/DateRangePicker.d.ts +62 -0
- package/dist/Components/Inputs/DateRangePicker.js +283 -0
- package/dist/Components/Inputs/DateTimePicker.d.ts +75 -0
- package/dist/Components/Inputs/DateTimePicker.js +399 -0
- package/dist/Components/Inputs/Dropdown.d.ts +117 -0
- package/dist/Components/Inputs/Dropdown.js +839 -0
- package/dist/Components/Inputs/DropdownParts.d.ts +84 -0
- package/dist/Components/Inputs/DropdownParts.js +102 -0
- package/dist/Components/Inputs/EditorShell.d.ts +45 -0
- package/dist/Components/Inputs/EditorShell.js +214 -0
- package/dist/Components/Inputs/Field.d.ts +53 -0
- package/dist/Components/Inputs/Field.js +16 -0
- package/dist/Components/Inputs/GroupForm.d.ts +20 -0
- package/dist/Components/Inputs/GroupForm.js +170 -0
- package/dist/Components/Inputs/InputField.d.ts +59 -0
- package/dist/Components/Inputs/InputField.js +169 -0
- package/dist/Components/Inputs/InputRenderer.d.ts +35 -0
- package/dist/Components/Inputs/InputRenderer.js +99 -0
- package/dist/Components/Inputs/MarkdownEditor.d.ts +67 -0
- package/dist/Components/Inputs/MarkdownEditor.js +289 -0
- package/dist/Components/Inputs/NumberBox.d.ts +53 -0
- package/dist/Components/Inputs/NumberBox.js +228 -0
- package/dist/Components/Inputs/RadioGroup.d.ts +20 -0
- package/dist/Components/Inputs/RadioGroup.js +43 -0
- package/dist/Components/Inputs/ReadOnlyNotice.d.ts +36 -0
- package/dist/Components/Inputs/ReadOnlyNotice.js +116 -0
- package/dist/Components/Inputs/RichTextEditor.d.ts +103 -0
- package/dist/Components/Inputs/RichTextEditor.js +1170 -0
- package/dist/Components/Inputs/RichTextParts.d.ts +63 -0
- package/dist/Components/Inputs/RichTextParts.js +157 -0
- package/dist/Components/Inputs/RowsInput.d.ts +104 -0
- package/dist/Components/Inputs/RowsInput.js +259 -0
- package/dist/Components/Inputs/Slider.d.ts +87 -0
- package/dist/Components/Inputs/Slider.js +216 -0
- package/dist/Components/Inputs/TabularForm.d.ts +23 -0
- package/dist/Components/Inputs/TabularForm.js +283 -0
- package/dist/Components/Inputs/TextArea.d.ts +43 -0
- package/dist/Components/Inputs/TextArea.js +31 -0
- package/dist/Components/Inputs/TextBox.d.ts +52 -0
- package/dist/Components/Inputs/TextBox.js +58 -0
- package/dist/Components/Inputs/TextField.d.ts +31 -0
- package/dist/Components/Inputs/TextField.js +35 -0
- package/dist/Components/Inputs/TimePanel.d.ts +34 -0
- package/dist/Components/Inputs/TimePanel.js +288 -0
- package/dist/Components/Inputs/TimePicker.d.ts +54 -0
- package/dist/Components/Inputs/TimePicker.js +239 -0
- package/dist/Components/Inputs/TreeView.d.ts +160 -0
- package/dist/Components/Inputs/TreeView.js +947 -0
- package/dist/Components/Layouts/MessageBox.d.ts +71 -0
- package/dist/Components/Layouts/MessageBox.js +104 -0
- package/dist/Components/Layouts/Popup.d.ts +92 -0
- package/dist/Components/Layouts/Popup.js +376 -0
- package/dist/Components/Layouts/PopupContext.d.ts +2 -0
- package/dist/Components/Layouts/PopupContext.js +4 -0
- package/dist/Components/Layouts/PopupDock.d.ts +22 -0
- package/dist/Components/Layouts/PopupDock.js +121 -0
- package/dist/Components/Layouts/PopupHost.d.ts +56 -0
- package/dist/Components/Layouts/PopupHost.js +163 -0
- package/dist/Components/Layouts/PopupRules.d.ts +30 -0
- package/dist/Components/Layouts/PopupRules.js +63 -0
- package/dist/Components/Layouts/ThemePicker.d.ts +13 -0
- package/dist/Components/Layouts/ThemePicker.js +22 -0
- package/dist/Components/Layouts/ThemeScript.d.ts +14 -0
- package/dist/Components/Layouts/ThemeScript.js +13 -0
- package/dist/Components/Layouts/ThemeSwitcher.d.ts +13 -0
- package/dist/Components/Layouts/ThemeSwitcher.js +29 -0
- package/dist/Components/Layouts/Toaster.d.ts +76 -0
- package/dist/Components/Layouts/Toaster.js +172 -0
- package/dist/Components/Viewers/DataTable.d.ts +25 -0
- package/dist/Components/Viewers/DataTable.js +542 -0
- package/dist/Components/Viewers/DataTableParts.d.ts +134 -0
- package/dist/Components/Viewers/DataTableParts.js +145 -0
- package/dist/Components/Viewers/MarkdownView.d.ts +26 -0
- package/dist/Components/Viewers/MarkdownView.js +79 -0
- package/dist/Components/Viewers/RichTextView.d.ts +18 -0
- package/dist/Components/Viewers/RichTextView.js +17 -0
- package/dist/Helpers/AnimationHelpers.d.ts +6 -0
- package/dist/Helpers/AnimationHelpers.js +35 -0
- package/dist/Helpers/ApiClient.d.ts +74 -0
- package/dist/Helpers/ApiClient.js +197 -0
- package/dist/Helpers/ApiFormHelpers.d.ts +26 -0
- package/dist/Helpers/ApiFormHelpers.js +56 -0
- package/dist/Helpers/ApiModules.d.ts +135 -0
- package/dist/Helpers/ApiModules.js +194 -0
- package/dist/Helpers/ApiResponses.d.ts +41 -0
- package/dist/Helpers/ApiResponses.js +159 -0
- package/dist/Helpers/ApiRoutes.d.ts +150 -0
- package/dist/Helpers/ApiRoutes.js +191 -0
- package/dist/Helpers/ApiToasts.d.ts +21 -0
- package/dist/Helpers/ApiToasts.js +22 -0
- package/dist/Helpers/ClassHelpers.d.ts +3 -0
- package/dist/Helpers/ClassHelpers.js +4 -0
- package/dist/Helpers/CrudBackend.d.ts +56 -0
- package/dist/Helpers/CrudBackend.js +119 -0
- package/dist/Helpers/CrudHelpers.d.ts +76 -0
- package/dist/Helpers/CrudHelpers.js +202 -0
- package/dist/Helpers/DateHelpers.d.ts +88 -0
- package/dist/Helpers/DateHelpers.js +363 -0
- package/dist/Helpers/DatePreferences.d.ts +14 -0
- package/dist/Helpers/DatePreferences.js +94 -0
- package/dist/Helpers/DateTimeHelpers.d.ts +87 -0
- package/dist/Helpers/DateTimeHelpers.js +286 -0
- package/dist/Helpers/DragHelpers.d.ts +129 -0
- package/dist/Helpers/DragHelpers.js +281 -0
- package/dist/Helpers/DropdownHelpers.d.ts +56 -0
- package/dist/Helpers/DropdownHelpers.js +180 -0
- package/dist/Helpers/FormDrafts.d.ts +18 -0
- package/dist/Helpers/FormDrafts.js +76 -0
- package/dist/Helpers/FormStore.d.ts +231 -0
- package/dist/Helpers/FormStore.js +734 -0
- package/dist/Helpers/InputParamsHelpers.d.ts +79 -0
- package/dist/Helpers/InputParamsHelpers.js +388 -0
- package/dist/Helpers/MarkdownEditing.d.ts +27 -0
- package/dist/Helpers/MarkdownEditing.js +250 -0
- package/dist/Helpers/MarkdownHelpers.d.ts +82 -0
- package/dist/Helpers/MarkdownHelpers.js +775 -0
- package/dist/Helpers/MessageBuilder.d.ts +74 -0
- package/dist/Helpers/MessageBuilder.js +254 -0
- package/dist/Helpers/NepaliCalendar.d.ts +25 -0
- package/dist/Helpers/NepaliCalendar.js +107 -0
- package/dist/Helpers/NumberHelpers.d.ts +71 -0
- package/dist/Helpers/NumberHelpers.js +202 -0
- package/dist/Helpers/Permissions.d.ts +62 -0
- package/dist/Helpers/Permissions.js +133 -0
- package/dist/Helpers/PopoverHelpers.d.ts +43 -0
- package/dist/Helpers/PopoverHelpers.js +91 -0
- package/dist/Helpers/RichTextHelpers.d.ts +77 -0
- package/dist/Helpers/RichTextHelpers.js +1072 -0
- package/dist/Helpers/RowsStore.d.ts +160 -0
- package/dist/Helpers/RowsStore.js +584 -0
- package/dist/Helpers/TableColumns.d.ts +40 -0
- package/dist/Helpers/TableColumns.js +254 -0
- package/dist/Helpers/TableExport.d.ts +30 -0
- package/dist/Helpers/TableExport.js +97 -0
- package/dist/Helpers/TableHelpers.d.ts +102 -0
- package/dist/Helpers/TableHelpers.js +281 -0
- package/dist/Helpers/TableStore.d.ts +142 -0
- package/dist/Helpers/TableStore.js +530 -0
- package/dist/Helpers/ThemeHelpers.d.ts +15 -0
- package/dist/Helpers/ThemeHelpers.js +16 -0
- package/dist/Helpers/TimeHelpers.d.ts +73 -0
- package/dist/Helpers/TimeHelpers.js +253 -0
- package/dist/Helpers/TreeStore.d.ts +188 -0
- package/dist/Helpers/TreeStore.js +577 -0
- package/dist/Helpers/ValidationHelpers.d.ts +124 -0
- package/dist/Helpers/ValidationHelpers.js +301 -0
- package/dist/Interfaces/ApiInterfaces.d.ts +149 -0
- package/dist/Interfaces/ApiInterfaces.js +24 -0
- package/dist/Interfaces/CrudInterfaces.d.ts +171 -0
- package/{src/sso-client.tsx → dist/Interfaces/CrudInterfaces.js} +1 -1
- package/dist/Interfaces/DateInterfaces.d.ts +154 -0
- package/dist/Interfaces/DateInterfaces.js +29 -0
- package/dist/Interfaces/FormInterfaces.d.ts +352 -0
- package/dist/Interfaces/FormInterfaces.js +1 -0
- package/dist/Interfaces/InputInterfaces.d.ts +141 -0
- package/dist/Interfaces/InputInterfaces.js +1 -0
- package/dist/Interfaces/MessageInterfaces.d.ts +111 -0
- package/dist/Interfaces/MessageInterfaces.js +5 -0
- package/dist/Interfaces/TableInterfaces.d.ts +291 -0
- package/dist/Interfaces/TableInterfaces.js +1 -0
- package/dist/Interfaces/ThemeInterfaces.d.ts +17 -0
- package/dist/Interfaces/ThemeInterfaces.js +17 -0
- package/dist/Interfaces/TypeInterfaces.d.ts +4 -0
- package/dist/Interfaces/TypeInterfaces.js +1 -0
- package/dist/Server.Index.d.ts +2 -0
- package/dist/Server.Index.js +5 -0
- package/dist/Services/ApiProxy.d.ts +32 -0
- package/dist/Services/ApiProxy.js +111 -0
- package/dist/Services/BrowserApi.d.ts +78 -0
- package/dist/Services/BrowserApi.js +111 -0
- package/dist/Services/ServerApi.d.ts +49 -0
- package/dist/Services/ServerApi.js +75 -0
- package/dist/Services/ThemeService.d.ts +17 -0
- package/dist/Services/ThemeService.js +83 -0
- package/dist/Shared.Index.d.ts +43 -0
- package/dist/Shared.Index.js +47 -0
- package/package.json +82 -33
- package/src/Styles/Nexus.Base.css +70 -0
- package/src/Styles/Nexus.Button.css +151 -0
- package/src/Styles/Nexus.Calendar.css +275 -0
- package/src/Styles/Nexus.Choice.css +345 -0
- package/src/Styles/Nexus.Crud.css +84 -0
- package/src/Styles/Nexus.DateTime.css +81 -0
- package/src/Styles/Nexus.Dropdown.css +774 -0
- package/src/Styles/Nexus.Editor.css +297 -0
- package/src/Styles/Nexus.Form.css +298 -0
- package/src/Styles/Nexus.Index.css +34 -0
- package/src/Styles/Nexus.Input.css +637 -0
- package/src/Styles/Nexus.Markdown.css +265 -0
- package/src/Styles/Nexus.Menu.css +249 -0
- package/src/Styles/Nexus.Popup.css +731 -0
- package/src/Styles/Nexus.RichText.css +463 -0
- package/src/Styles/Nexus.Rows.css +566 -0
- package/src/Styles/Nexus.Slider.css +278 -0
- package/src/Styles/Nexus.Tab.Buttons.css +364 -0
- package/src/Styles/Nexus.Table.css +1014 -0
- package/src/Styles/Nexus.Theme.Picker.css +159 -0
- package/src/Styles/Nexus.Themes.css +194 -0
- package/src/Styles/Nexus.Time.css +147 -0
- package/src/Styles/Nexus.Toast.css +265 -0
- package/src/Styles/Nexus.Tokens.css +72 -0
- package/src/Styles/Nexus.Tree.css +435 -0
- package/src/api-services/authentication-service.tsx +0 -23
- package/src/api-services/preference-service.tsx +0 -5
- package/src/api-services/system-service.tsx +0 -29
- package/src/client.ts +0 -31
- package/src/components/documents/button.tsx +0 -133
- package/src/components/documents/icon-box.tsx +0 -93
- package/src/components/documents/page-title.tsx +0 -7
- package/src/components/documents/tab-button.tsx +0 -172
- package/src/components/documents/tag.tsx +0 -30
- package/src/components/index.js +0 -0
- package/src/components/inputs/checkbox-input.tsx +0 -66
- package/src/components/inputs/input-box.tsx +0 -48
- package/src/components/inputs/input-element.tsx +0 -65
- package/src/components/inputs/input-form.tsx +0 -164
- package/src/components/inputs/input.tsx +0 -181
- package/src/components/inputs/number-input.tsx +0 -108
- package/src/components/inputs/radiobox-input.tsx +0 -53
- package/src/components/inputs/textarea-input.tsx +0 -47
- package/src/components/inputs/textbox-input.tsx +0 -45
- package/src/components/layouts/global-dialogbox.tsx +0 -431
- package/src/components/layouts/global-layout.tsx +0 -64
- package/src/components/layouts/layout-helpers.tsx +0 -20
- package/src/components/layouts/panels/user-panel.tsx +0 -112
- package/src/components/layouts/utility-menu.tsx +0 -49
- package/src/components/panels/theme-panel.tsx +0 -46
- package/src/helpers/bitwise-helpers.tsx +0 -11
- package/src/helpers/browser-helpers.tsx +0 -156
- package/src/helpers/datasource-helpers.tsx +0 -99
- package/src/helpers/element-helpers.tsx +0 -123
- package/src/helpers/input-helpers.tsx +0 -74
- package/src/helpers/string-helpers.tsx +0 -28
- package/src/helpers/utility-helpers.tsx +0 -45
- package/src/helpers/validation-helpers.tsx +0 -302
- package/src/index.ts +0 -26
- package/src/interface.ts +0 -19
- package/src/interfaces/auth-token-interfaces.tsx +0 -6
- package/src/interfaces/browser-interfaces.tsx +0 -36
- package/src/interfaces/button-interfaces.tsx +0 -63
- package/src/interfaces/datasource-interfaces.tsx +0 -22
- package/src/interfaces/datatable-interfaces.tsx +0 -25
- package/src/interfaces/dialogbox-interfaces.tsx +0 -5
- package/src/interfaces/exception-interfaces.tsx +0 -99
- package/src/interfaces/http-interfaces.tsx +0 -129
- package/src/interfaces/icon-interfaces.tsx +0 -129
- package/src/interfaces/input-interfaces.tsx +0 -410
- package/src/interfaces/layout-interfaces.tsx +0 -191
- package/src/interfaces/menu-interfaces.tsx +0 -53
- package/src/interfaces/message-interfaces.tsx +0 -32
- package/src/interfaces/permission-interfaces.tsx +0 -9
- package/src/interfaces/storage-interfaces.tsx +0 -5
- package/src/interfaces/system-interfaces.tsx +0 -22
- package/src/interfaces/theme-interfaces.tsx +0 -123
- package/src/interfaces/type-interfaces.tsx +0 -28
- package/src/interfaces/user-interfaces.tsx +0 -47
- package/src/nexus-client.tsx +0 -21
- package/src/nexus.environments.tsx +0 -66
- package/src/proxy-api/proxy-backend.tsx +0 -60
- package/src/proxy-api/proxy-constants.tsx +0 -28
- package/src/proxy-api/proxy-helpers.tsx +0 -91
- package/src/proxy-api-client.tsx +0 -1
- package/src/proxy-api-server.tsx +0 -2
- package/src/services/http-client-services.tsx +0 -75
- package/src/services/http-services.tsx +0 -158
- package/src/services/loader-service.tsx +0 -185
- package/src/services/localstorage-service.tsx +0 -119
- package/src/services/message-services.tsx +0 -383
- package/src/services/theme-service.tsx +0 -163
- package/src/services/user-services.tsx +0 -10
- package/src/sso-config/auth-token-validation.ts +0 -16
- package/src/sso-config/callback-route.tsx +0 -35
- package/src/sso-config/cookie-encryption.ts +0 -51
- package/src/sso-config/cookie-helpers.tsx +0 -102
- package/src/sso-config/forgot-password-route.tsx +0 -36
- package/src/sso-config/oauth-callback-state.ts +0 -61
- package/src/sso-config/pkce-helpers.ts +0 -9
- package/src/sso-config/provider-complete-route.tsx +0 -18
- package/src/sso-config/redirect-context-actions.tsx +0 -45
- package/src/sso-config/redirect-context-helpers.tsx +0 -159
- package/src/sso-config/redirect-context-persist.tsx +0 -18
- package/src/sso-config/redirect-context-route.tsx +0 -45
- package/src/sso-config/refresh-route.tsx +0 -23
- package/src/sso-config/sign-in-route.tsx +0 -74
- package/src/sso-config/sign-out-route.tsx +0 -57
- package/src/sso-config/sign-up-route.tsx +0 -57
- package/src/sso-config/sso-backend-flow.ts +0 -38
- package/src/sso-config/sso-complete-route.tsx +0 -50
- package/src/sso-config/sso-config.ts +0 -59
- package/src/sso-config/sso-interfaces.tsx +0 -99
- package/src/sso-config/sso-response-helpers.tsx +0 -20
- package/src/sso-server.tsx +0 -21
- package/src/styles/nexus.animation.css +0 -269
- package/src/styles/nexus.core.css +0 -119
- package/src/styles/nexus.dialog.css +0 -144
- package/src/styles/nexus.grid-view.css +0 -42
- package/src/styles/nexus.icon.css +0 -51
- package/src/styles/nexus.input.css +0 -207
- package/src/styles/nexus.loader.css +0 -11
- package/src/styles/nexus.logic.css +0 -47
- package/src/styles/nexus.utility.css +0 -347
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode, Ref } from "react";
|
|
2
|
+
import type { CheckBoxOnlyProps, CheckBoxProps } from "../Components/Inputs/CheckBox.tsx";
|
|
3
|
+
import type { CheckBoxGroupProps } from "../Components/Inputs/CheckBoxGroup.tsx";
|
|
4
|
+
import type { DatePickerProps } from "../Components/Inputs/DatePicker.tsx";
|
|
5
|
+
import type { DateRangePickerProps } from "../Components/Inputs/DateRangePicker.tsx";
|
|
6
|
+
import type { DateTimePickerProps } from "../Components/Inputs/DateTimePicker.tsx";
|
|
7
|
+
import type { DropdownProps } from "../Components/Inputs/Dropdown.tsx";
|
|
8
|
+
import type { MarkdownEditorProps } from "../Components/Inputs/MarkdownEditor.tsx";
|
|
9
|
+
import type { NumberBoxProps } from "../Components/Inputs/NumberBox.tsx";
|
|
10
|
+
import type { RadioGroupProps } from "../Components/Inputs/RadioGroup.tsx";
|
|
11
|
+
import type { RichTextEditorProps } from "../Components/Inputs/RichTextEditor.tsx";
|
|
12
|
+
import type { RangeSliderProps, SliderProps } from "../Components/Inputs/Slider.tsx";
|
|
13
|
+
import type { TextAreaProps } from "../Components/Inputs/TextArea.tsx";
|
|
14
|
+
import type { TextBoxProps, TextBoxType } from "../Components/Inputs/TextBox.tsx";
|
|
15
|
+
import type { TimePickerProps } from "../Components/Inputs/TimePicker.tsx";
|
|
16
|
+
import type { TreeViewProps } from "../Components/Inputs/TreeView.tsx";
|
|
17
|
+
import type { FormStore } from "../Helpers/FormStore.ts";
|
|
18
|
+
import type { ApiEndpoint, ApiResult } from "./ApiInterfaces.ts";
|
|
19
|
+
import type { DatePreferences } from "./DateInterfaces.ts";
|
|
20
|
+
import type { InputDesign, OptionValue } from "./InputInterfaces.ts";
|
|
21
|
+
import type { Size } from "./TypeInterfaces.ts";
|
|
22
|
+
/** Where a form places an input. The input itself ignores these keys. */
|
|
23
|
+
export interface InputLayoutParams {
|
|
24
|
+
/** Columns the input spans in a form's 12-column grid, and in a group form's section. Default 12, the full width. */
|
|
25
|
+
span?: number;
|
|
26
|
+
/** The column's width in a tabular form: a CSS length ("9rem") or pixels. Default by type, e.g. 10rem for text. */
|
|
27
|
+
width?: number | string;
|
|
28
|
+
/** The column's share of the spare width in a tabular form. Default 1; checkboxes, switches, and radios 0 (their width only). */
|
|
29
|
+
grow?: number;
|
|
30
|
+
/** Leaves the input out, e.g. a field only some roles may see. Its value stays in the data as it was. */
|
|
31
|
+
hidden?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/** What every input's params have. */
|
|
34
|
+
export interface InputParamsBase<TType extends string = string> extends InputLayoutParams {
|
|
35
|
+
/** Which input: "text", "number", "dropdown", "date", "tabular", ... */
|
|
36
|
+
type: TType;
|
|
37
|
+
/** The key of the value in the form's data, and in each row of a tabular or group form. */
|
|
38
|
+
name: string;
|
|
39
|
+
label?: ReactNode;
|
|
40
|
+
readOnly?: boolean;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Props the form sets itself: it holds the value and the element. */
|
|
44
|
+
type FormOwnedProps = "type" | "name" | "ref" | "value" | "checked";
|
|
45
|
+
/** Omit that keeps each member of a union apart, so a dropdown's `multiple: true` still decides its value's type. */
|
|
46
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
47
|
+
/** An input's params: its component's props without the ones the form owns, plus the base keys. */
|
|
48
|
+
export type InputParamsOf<TType extends string, TProps> = DistributiveOmit<TProps, FormOwnedProps> & InputParamsBase<TType>;
|
|
49
|
+
/** `TextBox`: "text", "email", "password", "search", "tel", or "url". */
|
|
50
|
+
export type TextInputParams = InputParamsOf<TextBoxType, TextBoxProps>;
|
|
51
|
+
export type TextAreaParams = InputParamsOf<"textarea", TextAreaProps>;
|
|
52
|
+
export type NumberInputParams = InputParamsOf<"number", NumberBoxProps>;
|
|
53
|
+
/** A checkbox: `true` or `false`. `defaultChecked` is the value of a new row. */
|
|
54
|
+
export type CheckBoxParams = InputParamsOf<"checkbox", CheckBoxProps & CheckBoxOnlyProps>;
|
|
55
|
+
export type SwitchParams = InputParamsOf<"switch", CheckBoxProps>;
|
|
56
|
+
/**
|
|
57
|
+
* One radio button, on or off. In a tabular or group form only one row can have it on, like a primary address: turning
|
|
58
|
+
* it on in a row turns it off in the others. `required` there means one row must have it.
|
|
59
|
+
*/
|
|
60
|
+
export type RadioParams = InputParamsOf<"radio", CheckBoxProps>;
|
|
61
|
+
export type CheckBoxGroupParams = InputParamsOf<"checkbox-group", CheckBoxGroupProps<OptionValue>>;
|
|
62
|
+
export type RadioGroupParams = InputParamsOf<"radio-group", RadioGroupProps<OptionValue>>;
|
|
63
|
+
/** A list of params holds dropdowns of many item types (countries, staff), so items are `any` here: typed columns and callbacks fit. */
|
|
64
|
+
export type DropdownParams = InputParamsOf<"dropdown", DropdownProps<any, OptionValue>>;
|
|
65
|
+
export type DateParams = InputParamsOf<"date", DatePickerProps>;
|
|
66
|
+
export type DateRangeParams = InputParamsOf<"date-range", DateRangePickerProps>;
|
|
67
|
+
export type TimeParams = InputParamsOf<"time", TimePickerProps>;
|
|
68
|
+
export type DateTimeParams = InputParamsOf<"date-time", DateTimePickerProps>;
|
|
69
|
+
export type SliderParams = InputParamsOf<"slider", SliderProps>;
|
|
70
|
+
export type RangeSliderParams = InputParamsOf<"range-slider", RangeSliderProps>;
|
|
71
|
+
export type MarkdownParams = InputParamsOf<"markdown", MarkdownEditorProps>;
|
|
72
|
+
/** `RichTextEditor`: the value is sanitized HTML. */
|
|
73
|
+
export type RichTextParams = InputParamsOf<"rich-text", RichTextEditorProps>;
|
|
74
|
+
export type TreeParams = InputParamsOf<"tree", TreeViewProps<any>>;
|
|
75
|
+
/** `TabularForm`: rows of inputs in a table. The value is an array of row objects. */
|
|
76
|
+
export type TabularParams = InputParamsOf<"tabular", TabularFormProps>;
|
|
77
|
+
/** `GroupForm`: the same rows, each as a section of inputs. */
|
|
78
|
+
export type GroupParams = InputParamsOf<"group", GroupFormProps>;
|
|
79
|
+
/** The params of any input: the root type every form takes as `inputs`. */
|
|
80
|
+
export type InputParams = TextInputParams | TextAreaParams | NumberInputParams | CheckBoxParams | SwitchParams | RadioParams | CheckBoxGroupParams | RadioGroupParams | DropdownParams | DateParams | DateRangeParams | TimeParams | DateTimeParams | SliderParams | RangeSliderParams | MarkdownParams | RichTextParams | TreeParams | TabularParams | GroupParams;
|
|
81
|
+
export type InputType = InputParams["type"];
|
|
82
|
+
/** Settings a check needs to write its message the way the field shows values: the user's date and time settings. */
|
|
83
|
+
export interface InputValidationContext {
|
|
84
|
+
/** Default: English (AD) dates as YYYY-MM-DD and 12-hour times. Components pass the user's own (`useDatePreferences`). */
|
|
85
|
+
preferences?: DatePreferences;
|
|
86
|
+
}
|
|
87
|
+
/** One row of a tabular or group form: the values by input name, plus any other fields the row came with, such as its id. */
|
|
88
|
+
export type RowValue = Record<string, unknown>;
|
|
89
|
+
/** Props shared by `TabularForm` and `GroupForm`. The value is an array of rows; each row holds one value per input. */
|
|
90
|
+
export interface RowsInputProps<TRow extends RowValue = RowValue> {
|
|
91
|
+
/** The inputs of one row, as params. Keep the array stable (a constant or `useMemo`): a new one checks every row again. */
|
|
92
|
+
inputs: readonly InputParams[];
|
|
93
|
+
label?: ReactNode;
|
|
94
|
+
/** Help text under the rows. An error takes its place. */
|
|
95
|
+
hint?: ReactNode;
|
|
96
|
+
/** An error from outside, such as a server message. Shown under the rows. */
|
|
97
|
+
error?: string | null;
|
|
98
|
+
/** What one row is, e.g. "Address": the Add button says "Add address", sections are "Address 1", and messages name it. Default "Row" (tabular) or "Item" (group). */
|
|
99
|
+
itemLabel?: string;
|
|
100
|
+
/** The plural of `itemLabel`, for messages such as "Add at least 2 addresses". Default: `itemLabel` with an English plural ending. */
|
|
101
|
+
itemLabelPlural?: string;
|
|
102
|
+
/** Text of the Add button. Default "Add " and the item label. */
|
|
103
|
+
addLabel?: string;
|
|
104
|
+
/** Shown while there are no rows. Default "No <items> yet." */
|
|
105
|
+
emptyMessage?: ReactNode;
|
|
106
|
+
/** Form field name. The form's data gets the rows as JSON under it: `JSON.parse(formData.get(name))`. */
|
|
107
|
+
name?: string;
|
|
108
|
+
/** Id of the form the rows belong to, when they sit outside it. */
|
|
109
|
+
form?: string;
|
|
110
|
+
/** The rows. With `value`, the input is controlled; pair it with `onValueChange`. Passing back the array it gave does nothing. */
|
|
111
|
+
value?: readonly TRow[];
|
|
112
|
+
defaultValue?: readonly TRow[];
|
|
113
|
+
/** Every row, after each change: a value typed or picked, a row added, removed, or moved. */
|
|
114
|
+
onValueChange?: (rows: TRow[]) => void;
|
|
115
|
+
/**
|
|
116
|
+
* After a value changes in a row, with the row as it is now and the input's name. Return values to set in the same
|
|
117
|
+
* row, e.g. `{ amount: row.quantity * row.rate }`, or nothing.
|
|
118
|
+
*/
|
|
119
|
+
onRowChange?: (row: TRow, name: string, index: number) => Partial<TRow> | null | undefined | void;
|
|
120
|
+
/** Values of a new row, over each input's `defaultValue` (`defaultChecked` for checkboxes). A function gets the new row's index. */
|
|
121
|
+
newRow?: Partial<TRow> | ((index: number) => Partial<TRow>);
|
|
122
|
+
/**
|
|
123
|
+
* The field that holds a row's id, e.g. "id". Rows keep their ids through edits, moves, and saves; new rows have none,
|
|
124
|
+
* and a copied row drops it. Default: rows are told apart by position when they load.
|
|
125
|
+
*/
|
|
126
|
+
rowKey?: string;
|
|
127
|
+
/** At least one row. */
|
|
128
|
+
required?: boolean;
|
|
129
|
+
/** Fewest rows. Not checked with no rows at all; use `required` for that. */
|
|
130
|
+
min?: number;
|
|
131
|
+
/** Most rows. The Add button stops at this count. */
|
|
132
|
+
max?: number;
|
|
133
|
+
/** Inputs whose values must differ between rows, such as an email or a phone number. Text compares without case and spaces around it. */
|
|
134
|
+
unique?: readonly string[];
|
|
135
|
+
/** Runs after the other rules pass, with every row, e.g. to check that debits equal credits. Runs after each change: keep it quick. */
|
|
136
|
+
validate?: (rows: TRow[]) => string | null | undefined;
|
|
137
|
+
/** Rows can be added. Default true. */
|
|
138
|
+
addable?: boolean;
|
|
139
|
+
/** Rows can be removed. Default true. */
|
|
140
|
+
removable?: boolean;
|
|
141
|
+
/** Rows can be moved up and down. Default false. */
|
|
142
|
+
sortable?: boolean;
|
|
143
|
+
/** Every input is read-only, and rows cannot be added, removed, or moved. */
|
|
144
|
+
readOnly?: boolean;
|
|
145
|
+
/** What the rows say when someone tries to change them. Default "Read-only: these rows cannot be changed." */
|
|
146
|
+
readOnlyMessage?: string;
|
|
147
|
+
disabled?: boolean;
|
|
148
|
+
/** Size of every input. Default `md`. */
|
|
149
|
+
size?: Size;
|
|
150
|
+
/** Name used in messages. Default: the label, when it is text. */
|
|
151
|
+
fieldName?: string;
|
|
152
|
+
id?: string;
|
|
153
|
+
className?: string;
|
|
154
|
+
style?: CSSProperties;
|
|
155
|
+
/** Name of the rows for screen readers, when there is no `label`. */
|
|
156
|
+
"aria-label"?: string;
|
|
157
|
+
ref?: Ref<RowsInputHandle<TRow>>;
|
|
158
|
+
}
|
|
159
|
+
/** What `ref` gives on a tabular or group form. */
|
|
160
|
+
export interface RowsInputHandle<TRow extends RowValue = RowValue> {
|
|
161
|
+
/** Every row as it is now. */
|
|
162
|
+
getValue: () => TRow[];
|
|
163
|
+
/** Replaces every row, e.g. with fresh data from a server. The rows given become the ones a form reset returns to. */
|
|
164
|
+
setValue: (rows: readonly TRow[]) => void;
|
|
165
|
+
/** Adds a row with these values (over `newRow`), at `index` or at the end, and focuses its first input. */
|
|
166
|
+
add: (values?: Partial<TRow>, index?: number) => void;
|
|
167
|
+
/** Removes the row at `index`. */
|
|
168
|
+
remove: (index: number) => void;
|
|
169
|
+
/** Checks every row, shows every message, and focuses the first problem. Returns whether all is valid. */
|
|
170
|
+
validate: () => boolean;
|
|
171
|
+
/** Brings the row at `index` into view and focuses its input named `name`, or its first input. */
|
|
172
|
+
focusRow: (index: number, name?: string) => void;
|
|
173
|
+
/** Focuses the first input of the first row, or the Add button. */
|
|
174
|
+
focus: () => void;
|
|
175
|
+
}
|
|
176
|
+
/** `TabularForm`: rows of inputs in a table, one column per input. */
|
|
177
|
+
export interface TabularFormProps<TRow extends RowValue = RowValue> extends RowsInputProps<TRow> {
|
|
178
|
+
/** The tallest the table grows before it scrolls, with the header row kept in view: pixels or a CSS length. Default 440. */
|
|
179
|
+
maxHeight?: number | string;
|
|
180
|
+
/** The row number column. Default true; it is also the button of each row's menu. */
|
|
181
|
+
numbered?: boolean;
|
|
182
|
+
}
|
|
183
|
+
/** `GroupForm`: each row as a section of inputs, laid out on a 12-column grid by each input's `span`. */
|
|
184
|
+
export interface GroupFormProps<TRow extends RowValue = RowValue> extends RowsInputProps<TRow> {
|
|
185
|
+
/** Label design of every input that does not set its own. Default `standard`. */
|
|
186
|
+
design?: InputDesign;
|
|
187
|
+
/** Sections can collapse to one line with a summary. Default true. */
|
|
188
|
+
collapsible?: boolean;
|
|
189
|
+
/** Sections start collapsed. New sections always start open. */
|
|
190
|
+
defaultCollapsed?: boolean;
|
|
191
|
+
/** Title of a section. Default: the item label and number, "Address 1". */
|
|
192
|
+
sectionTitle?: (row: TRow, index: number) => ReactNode;
|
|
193
|
+
/**
|
|
194
|
+
* What a collapsed section shows after its title: the inputs whose values to list (`["city", "country"]`), or a
|
|
195
|
+
* function. Default: the first three inputs with a value.
|
|
196
|
+
*/
|
|
197
|
+
summary?: readonly string[] | ((row: TRow, index: number) => ReactNode);
|
|
198
|
+
}
|
|
199
|
+
/** A form's values: one per input name, plus any other fields the record came with, such as its id. */
|
|
200
|
+
export type FormValues = Record<string, unknown>;
|
|
201
|
+
/** Messages by input name. An empty value clears a message. */
|
|
202
|
+
export type FormErrors = Record<string, string | null | undefined>;
|
|
203
|
+
/**
|
|
204
|
+
* What a form's own rule returns after checking the values together (a password and its confirmation, a start before an
|
|
205
|
+
* end): nothing when all is well, messages by input name, or a message about the whole form.
|
|
206
|
+
*/
|
|
207
|
+
export type FormRuleResult = FormErrors | string | null | undefined | void;
|
|
208
|
+
/** Props of `Form`, and of `SubmitForm` and `ApiForm`, which build on it. */
|
|
209
|
+
export interface FormProps<TValues extends FormValues = FormValues> {
|
|
210
|
+
/** The inputs, in their order on screen. Keep the array stable (a constant or `useMemo`): a new one checks every value again. */
|
|
211
|
+
inputs: readonly InputParams[];
|
|
212
|
+
/**
|
|
213
|
+
* The store behind the form, from `useForm()`, so the page can read and watch values and call the form from outside.
|
|
214
|
+
* Default: the form's own. A store outlives the form, so values typed in a form that unmounts (a closed tab) stay.
|
|
215
|
+
*/
|
|
216
|
+
form?: FormStore<TValues>;
|
|
217
|
+
/** The values the form opens with, such as a record to edit. Read once, when the store is new; `form.load(values)` loads others. */
|
|
218
|
+
defaultValue?: Partial<TValues>;
|
|
219
|
+
/** After every change: a value typed or picked, set from code, loaded, or reset. `name` is `null` for a load or a reset. */
|
|
220
|
+
onValueChange?: (values: TValues, name: string | null) => void;
|
|
221
|
+
/**
|
|
222
|
+
* After the user changes a value, with the values as they are now. Return values to set in the same form, e.g.
|
|
223
|
+
* `{ amount: values.quantity * values.rate }`, or nothing.
|
|
224
|
+
*/
|
|
225
|
+
onFieldChange?: (name: string, value: unknown, values: TValues) => Partial<TValues> | null | undefined | void;
|
|
226
|
+
/**
|
|
227
|
+
* Checks the values together, after the inputs' own rules, e.g. that a confirmation matches a password. Return messages
|
|
228
|
+
* by input name, a message for the whole form, or nothing. It runs after every change, so keep it quick. A message on
|
|
229
|
+
* an input shows once that input was left, and every message shows on submit.
|
|
230
|
+
*/
|
|
231
|
+
validate?: (values: TValues) => FormRuleResult;
|
|
232
|
+
/**
|
|
233
|
+
* Keeps unsaved changes on this device (IndexedDB) under this key, and brings them back when the form opens again: a
|
|
234
|
+
* reload, a crash, a closed tab. Make it unique per user, record, and form, e.g. `hotel-3:user-8:room:204`. Cleared after
|
|
235
|
+
* a save, a reset, or a cancel.
|
|
236
|
+
*/
|
|
237
|
+
draftKey?: string;
|
|
238
|
+
/** Label design of every input that does not set its own. */
|
|
239
|
+
design?: InputDesign;
|
|
240
|
+
/** Size of every input that does not set its own. Default `md`. */
|
|
241
|
+
size?: Size;
|
|
242
|
+
/** Every input is read-only, and nothing is checked. */
|
|
243
|
+
readOnly?: boolean;
|
|
244
|
+
/** Every input is disabled, and nothing is checked. */
|
|
245
|
+
disabled?: boolean;
|
|
246
|
+
/** Shows placeholders in place of the inputs, e.g. while the values load. */
|
|
247
|
+
loading?: boolean;
|
|
248
|
+
id?: string;
|
|
249
|
+
className?: string;
|
|
250
|
+
style?: CSSProperties;
|
|
251
|
+
/** The store, as `form` gives it. */
|
|
252
|
+
ref?: Ref<FormStore<TValues>>;
|
|
253
|
+
}
|
|
254
|
+
/** What `onSubmit` gets besides the values. */
|
|
255
|
+
export interface FormSubmitContext<TValues extends FormValues = FormValues> {
|
|
256
|
+
/** Only the values that changed since the form opened or last saved, e.g. for a PATCH request. */
|
|
257
|
+
changes: Partial<TValues>;
|
|
258
|
+
/** The values the form opened with, or saved last. */
|
|
259
|
+
initial: TValues;
|
|
260
|
+
form: FormStore<TValues>;
|
|
261
|
+
/** Aborted when the form unmounts, so a request can stop. */
|
|
262
|
+
signal: AbortSignal;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* What `onSubmit` returns. Nothing, `true`, or `{ ok: true }`: saved, and the values become the form's own (`values` from
|
|
266
|
+
* the server, such as a new id, go on top). `false`: not saved, and nothing to show. `{ ok: false }`: not saved, with
|
|
267
|
+
* messages by input name and a message for the form.
|
|
268
|
+
*/
|
|
269
|
+
export type FormSubmitResult<TValues extends FormValues = FormValues> = void | undefined | boolean | {
|
|
270
|
+
ok: true;
|
|
271
|
+
values?: Partial<TValues>;
|
|
272
|
+
} | {
|
|
273
|
+
ok: false;
|
|
274
|
+
errors?: FormErrors;
|
|
275
|
+
message?: string | null;
|
|
276
|
+
};
|
|
277
|
+
/** Where `SubmitForm` puts its buttons: at the end with the status line before them, at the start, or nowhere (`FormButtons` elsewhere). */
|
|
278
|
+
export type FormButtonsPlacement = "end" | "start" | false;
|
|
279
|
+
/** Props of `SubmitForm`: a `Form` in a `<form>`, checked on submit, with Save, Cancel, and Reset. */
|
|
280
|
+
export interface SubmitFormProps<TValues extends FormValues = FormValues> extends FormProps<TValues> {
|
|
281
|
+
/**
|
|
282
|
+
* Runs when every value is valid. Return or resolve nothing to say the values were saved, `false` when they were not,
|
|
283
|
+
* or `{ ok: false, errors, message }` to show why. A thrown error shows its message. It runs once at a time: Save waits
|
|
284
|
+
* with a spinner, and another submit does nothing until it ends.
|
|
285
|
+
*/
|
|
286
|
+
onSubmit: (values: TValues, context: FormSubmitContext<TValues>) => FormSubmitResult<TValues> | Promise<FormSubmitResult<TValues>>;
|
|
287
|
+
/** After a save, once the saved values are the form's own: close a popup, go to another page. */
|
|
288
|
+
onSaved?: (values: TValues, form: FormStore<TValues>) => void;
|
|
289
|
+
/** Shows a Cancel button. */
|
|
290
|
+
onCancel?: () => void;
|
|
291
|
+
/** Cancel asks before it drops changed values. Default true. */
|
|
292
|
+
confirmCancel?: boolean;
|
|
293
|
+
/** Default "Save". */
|
|
294
|
+
submitLabel?: ReactNode;
|
|
295
|
+
/** Default: a floppy disk. `null` shows none. */
|
|
296
|
+
submitIcon?: ReactNode | null;
|
|
297
|
+
/** Default "Cancel". */
|
|
298
|
+
cancelLabel?: ReactNode;
|
|
299
|
+
/** Shows a Reset button, which brings back the values the form opened with (or saved last). */
|
|
300
|
+
resettable?: boolean;
|
|
301
|
+
/** Default "Reset". */
|
|
302
|
+
resetLabel?: ReactNode;
|
|
303
|
+
/** After a save, the form goes back to the values it opened with, ready for the next entry. Default: the saved values stay. */
|
|
304
|
+
resetOnSuccess?: boolean;
|
|
305
|
+
/** Where the buttons go. Default `end`. With `false`, put a `FormButtons` with the same `form` elsewhere, such as a popup's footer. */
|
|
306
|
+
buttons?: FormButtonsPlacement;
|
|
307
|
+
/** Asks before the page closes or reloads with unsaved changes. Default: true without a `draftKey` (a draft keeps them). */
|
|
308
|
+
confirmLeave?: boolean;
|
|
309
|
+
/** Name for screen readers. */
|
|
310
|
+
"aria-label"?: string;
|
|
311
|
+
"aria-labelledby"?: string;
|
|
312
|
+
}
|
|
313
|
+
/** A request an API form sends to a URL outside the app's modules, through the app's `api`. A module's API is an endpoint. */
|
|
314
|
+
export interface ApiRequest {
|
|
315
|
+
url: string;
|
|
316
|
+
/** Default `POST`. */
|
|
317
|
+
method?: "POST" | "PUT" | "PATCH" | "DELETE";
|
|
318
|
+
headers?: Record<string, string>;
|
|
319
|
+
/** `json` (default) sends the values as JSON; `form-data` as fields, with lists and objects as JSON text. */
|
|
320
|
+
bodyType?: "json" | "form-data";
|
|
321
|
+
credentials?: RequestCredentials;
|
|
322
|
+
}
|
|
323
|
+
/** Sends a form's values with the app's own client. Return what it answers: a `Response`, a parsed body, or an `ApiResult`. */
|
|
324
|
+
export type ApiSend<TValues extends FormValues = FormValues> = (body: unknown, context: FormSubmitContext<TValues>) => Promise<unknown>;
|
|
325
|
+
/** Props of `ApiForm`: a `SubmitForm` that sends the values to an API and shows the server's messages on their inputs. */
|
|
326
|
+
export interface ApiFormProps<TValues extends FormValues = FormValues> extends Omit<SubmitFormProps<TValues>, "onSubmit" | "onSaved"> {
|
|
327
|
+
/**
|
|
328
|
+
* Where the values go: an endpoint (`ROOMS.update`, or `{ module, path, method }` in place; `{id}` in its path comes
|
|
329
|
+
* from the values), a request to a URL outside the app's modules (`{ url, method }`), or a function that sends them
|
|
330
|
+
* with a client of the app's own. Endpoints and requests go through `api`, with the app's headers and sign-in handling.
|
|
331
|
+
*/
|
|
332
|
+
api: ApiRequest | ApiEndpoint | ApiSend<TValues>;
|
|
333
|
+
/** Shapes what is sent, e.g. `{ items: [values] }` for a batch endpoint. May be async. Default: the values. */
|
|
334
|
+
transform?: (values: TValues, context: FormSubmitContext<TValues>) => unknown;
|
|
335
|
+
/**
|
|
336
|
+
* Reads the server's answer. Default `readApiResponse`: Nexus API responses (`{ isSuccess, message, inputName, result }`),
|
|
337
|
+
* ASP.NET Core problem details (`{ title, errors }`), and any JSON by its HTTP status.
|
|
338
|
+
*/
|
|
339
|
+
readResponse?: (body: unknown, status: number | undefined) => ApiResult;
|
|
340
|
+
/** After a save, once the saved values are the form's own, with what the server sent back: close a popup, update a table row. */
|
|
341
|
+
onSuccess?: (result: unknown, values: TValues, form: FormStore<TValues>) => void;
|
|
342
|
+
/** After a failed save, with the server's answer. The form already shows its messages. */
|
|
343
|
+
onError?: (response: ApiResult, values: TValues) => void;
|
|
344
|
+
/** The toast after a save: text, or `false` for none. Default: the server's message, else the endpoint's ("Room saved."), else "Saved." */
|
|
345
|
+
successMessage?: ReactNode | false;
|
|
346
|
+
/**
|
|
347
|
+
* Loads the values to edit, e.g. a record by id. Placeholders show while it runs, and a failure offers Retry. It runs
|
|
348
|
+
* once; give the form a new `key` to load another record.
|
|
349
|
+
*/
|
|
350
|
+
loadValue?: (signal: AbortSignal) => Promise<Partial<TValues> | null | undefined>;
|
|
351
|
+
}
|
|
352
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* How a field shows its label:
|
|
4
|
+
* - `standard`: above the box. Easiest to scan, and the default.
|
|
5
|
+
* - `outlined`: inside the box like a placeholder, rising onto the top border on focus or once there is a value.
|
|
6
|
+
* - `inbox`: small, inside the top of a taller box.
|
|
7
|
+
*/
|
|
8
|
+
export type InputDesign = "standard" | "outlined" | "inbox";
|
|
9
|
+
/** When a field shows its own validation message. Submitting the form always shows it. */
|
|
10
|
+
export type ValidateOn = "blur" | "change" | "submit";
|
|
11
|
+
/** A regular expression with the message shown when a value does not match. Plain strings, so params stay serializable. */
|
|
12
|
+
export interface TextPattern {
|
|
13
|
+
/** Regular expression source. It must match the whole value, as with the HTML `pattern` attribute. */
|
|
14
|
+
source: string;
|
|
15
|
+
/** Shown when the value does not match. */
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
/** Custom check. Receives the trimmed value, also when it is empty; returns a message to fail. */
|
|
19
|
+
export type TextValidator = (value: string) => string | null | undefined;
|
|
20
|
+
/** Validation rules for text, named like the HTML attributes. */
|
|
21
|
+
export interface TextRules {
|
|
22
|
+
required?: boolean;
|
|
23
|
+
/** Fewest characters, counted like the HTML attribute. Not checked on an empty value; use `required` for that. */
|
|
24
|
+
minLength?: number;
|
|
25
|
+
/** Most characters. Inputs also stop typing at this length. */
|
|
26
|
+
maxLength?: number;
|
|
27
|
+
/** A `TEXT_PATTERNS` entry, a regular expression source, or a `RegExp`. Not checked on an empty value. */
|
|
28
|
+
pattern?: TextPattern | string | RegExp;
|
|
29
|
+
/** Message for a `pattern` given as a string or `RegExp`. Default: "<field> is not valid." */
|
|
30
|
+
patternMessage?: string;
|
|
31
|
+
/** Runs after the built-in rules pass. */
|
|
32
|
+
validate?: TextValidator;
|
|
33
|
+
}
|
|
34
|
+
/** Custom check for a number. Receives the value, or `null` when the field is empty; returns a message to fail. */
|
|
35
|
+
export type NumberValidator = (value: number | null) => string | null | undefined;
|
|
36
|
+
/** Validation rules for a number, named like the HTML attributes. */
|
|
37
|
+
export interface NumberRules {
|
|
38
|
+
required?: boolean;
|
|
39
|
+
/** Smallest value allowed. Below 0 also allows typing a minus sign. */
|
|
40
|
+
min?: number;
|
|
41
|
+
/** Largest value allowed. */
|
|
42
|
+
max?: number;
|
|
43
|
+
/** Runs after the built-in rules pass. */
|
|
44
|
+
validate?: NumberValidator;
|
|
45
|
+
}
|
|
46
|
+
/** How a number is shown. Plain values, so they can come from params. */
|
|
47
|
+
export interface NumberFormatOptions {
|
|
48
|
+
/** Most digits after the decimal point. Typing stops there, and other values round to it. `0` allows whole numbers only. */
|
|
49
|
+
decimals?: number;
|
|
50
|
+
/** Always shows `decimals` digits, e.g. 1,250.00 for amounts. */
|
|
51
|
+
fixedDecimals?: boolean;
|
|
52
|
+
/** Group separators while the field is not being edited: 1,250,000. */
|
|
53
|
+
grouping?: boolean;
|
|
54
|
+
/** Locale of the separators, e.g. `en-IN` for 12,50,000 or `de-DE` for 1.250.000,5. Default `en-US`, so server and browser agree. */
|
|
55
|
+
locale?: string;
|
|
56
|
+
}
|
|
57
|
+
/** The value of a choice. Numbers are kept as numbers, so ids from an API come back with their type. */
|
|
58
|
+
export type OptionValue = string | number;
|
|
59
|
+
/** One option of a checkbox group, a radio group, and later a dropdown. */
|
|
60
|
+
export interface ChoiceOption<T extends OptionValue = string> {
|
|
61
|
+
value: T;
|
|
62
|
+
label: ReactNode;
|
|
63
|
+
/** A second line under the label. */
|
|
64
|
+
description?: ReactNode;
|
|
65
|
+
/** Shown before the label, e.g. `<Icon name="wifi" />`. */
|
|
66
|
+
icon?: ReactNode;
|
|
67
|
+
disabled?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/** `default`: a box or circle beside each label. `cards`: each option is a card, for choices that need a description. */
|
|
70
|
+
export type ChoiceDesign = "default" | "cards";
|
|
71
|
+
/** Custom check for a single checkbox or switch; returns a message to fail. */
|
|
72
|
+
export type CheckValidator = (checked: boolean) => string | null | undefined;
|
|
73
|
+
/** Validation rules for a single checkbox or switch. */
|
|
74
|
+
export interface CheckRules {
|
|
75
|
+
/** Must be checked, e.g. "I accept the terms". */
|
|
76
|
+
required?: boolean;
|
|
77
|
+
validate?: CheckValidator;
|
|
78
|
+
}
|
|
79
|
+
/** Validation rules for a set of chosen values. */
|
|
80
|
+
export interface SelectionRules<T extends OptionValue = OptionValue> {
|
|
81
|
+
/** At least one choice. */
|
|
82
|
+
required?: boolean;
|
|
83
|
+
/** Fewest choices. Not checked when nothing is chosen; use `required` for that. */
|
|
84
|
+
min?: number;
|
|
85
|
+
/** Most choices. A checkbox group also stops further choices at this count. */
|
|
86
|
+
max?: number;
|
|
87
|
+
/** Runs after the built-in rules pass, with the chosen values. */
|
|
88
|
+
validate?: (values: T[]) => string | null | undefined;
|
|
89
|
+
}
|
|
90
|
+
/** A labelled point under a slider's track, e.g. `{ value: 50, label: "Mid-range" }`. Clicking it moves the nearest thumb there. */
|
|
91
|
+
export interface SliderMark {
|
|
92
|
+
value: number;
|
|
93
|
+
/** Default: the value, formatted like the slider's value. */
|
|
94
|
+
label?: ReactNode;
|
|
95
|
+
}
|
|
96
|
+
/** Any object can be a dropdown item: API rows as they come, or `ChoiceOption`s. Fields are read by key. */
|
|
97
|
+
export type DropdownItem = object;
|
|
98
|
+
/**
|
|
99
|
+
* How a dropdown column draws its field:
|
|
100
|
+
* - `text`: the value as text, cut with an ellipsis. The default.
|
|
101
|
+
* - `muted`: text in the muted color, for secondary details such as an email or a role.
|
|
102
|
+
* - `code`: short muted text with even digits, such as a country code or an employee number.
|
|
103
|
+
* - `avatar`: a round photo from a URL; the initials of the item's label when there is no URL or it fails to load.
|
|
104
|
+
* - `image`: a small picture from a URL, 4:3, such as a flag or a logo.
|
|
105
|
+
* - `icon`: a Tabler icon by name, such as `"wifi"`.
|
|
106
|
+
*/
|
|
107
|
+
export type DropdownColumnType = "text" | "muted" | "code" | "avatar" | "image" | "icon";
|
|
108
|
+
/** One column of a dropdown's rows. Plain values, so a list of fields can describe it; `render` is the only function. */
|
|
109
|
+
export interface DropdownColumn<TItem extends DropdownItem = DropdownItem> {
|
|
110
|
+
/** The item's field, e.g. `"username"`. */
|
|
111
|
+
key: string;
|
|
112
|
+
/** Heading of the column. The list shows a header row when any column has one. */
|
|
113
|
+
header?: string;
|
|
114
|
+
/** Default `text`. */
|
|
115
|
+
type?: DropdownColumnType;
|
|
116
|
+
/** A CSS grid track: `"6rem"`, `"auto"`, `"1fr"`. Default: `auto` for avatar, image, icon, and code; `minmax(0, 1fr)` for text. */
|
|
117
|
+
width?: string;
|
|
118
|
+
/** Default `start`. */
|
|
119
|
+
align?: "start" | "center" | "end";
|
|
120
|
+
/** Draws the cell instead of `type`. */
|
|
121
|
+
render?: (item: TItem) => ReactNode;
|
|
122
|
+
}
|
|
123
|
+
/** What `loadOptions` receives: the search text and the page to load. `skip` suits APIs that take skip and take (max) counts. */
|
|
124
|
+
export interface DropdownPageRequest {
|
|
125
|
+
search: string;
|
|
126
|
+
/** From 1. */
|
|
127
|
+
page: number;
|
|
128
|
+
pageSize: number;
|
|
129
|
+
/** Items before this page: `(page - 1) * pageSize`. */
|
|
130
|
+
skip: number;
|
|
131
|
+
/** Aborted when a newer search replaces this request, or the dropdown unmounts. */
|
|
132
|
+
signal: AbortSignal;
|
|
133
|
+
}
|
|
134
|
+
/** What `loadOptions` returns for one page. */
|
|
135
|
+
export interface DropdownPage<TItem extends DropdownItem = DropdownItem> {
|
|
136
|
+
items: readonly TItem[];
|
|
137
|
+
/** Whether another page follows. Default: the page was full (`items.length === pageSize`). */
|
|
138
|
+
hasMore?: boolean;
|
|
139
|
+
/** All matches on the server, shown as "25 of 1,240" under the list. */
|
|
140
|
+
total?: number;
|
|
141
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,111 @@
|
|
|
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" | "archive" | "restore" | "recover" | "flag" | "unflag" | "pin" | "unpin" | "send" | "submit" | "upload" | "download" | "import" | "export" | "copy" | "approve" | "reject" | "cancel";
|
|
3
|
+
/** The words of an action. */
|
|
4
|
+
export interface ActionWords {
|
|
5
|
+
/** "save", or with the object inside: "move {object} to the trash". */
|
|
6
|
+
verb: string;
|
|
7
|
+
/** "saved", "moved to the trash". */
|
|
8
|
+
done: string;
|
|
9
|
+
/** "Saving", "Moving {object} to the trash". */
|
|
10
|
+
doing: string;
|
|
11
|
+
/** What a message names when nothing else is named: "the changes", "the file". */
|
|
12
|
+
object: string;
|
|
13
|
+
/** Whether the action sends values the server checks, which words a refusal as "did not accept the values". */
|
|
14
|
+
sendsValues?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* What a call or a button does, for its messages: "Room 204 saved.", "Could not delete 3 rooms." A name from
|
|
18
|
+
* `MESSAGE_ACTION_NAMES`, or the words of an action of your own: `{ verb: "check in", done: "checked in", doing: "Checking in",
|
|
19
|
+
* object: "the guest" }`.
|
|
20
|
+
*/
|
|
21
|
+
export type MessageAction = MessageActionName | ActionWords;
|
|
22
|
+
/**
|
|
23
|
+
* The kinds of message:
|
|
24
|
+
* - `success`: "Room 204 saved.", "3 rooms deleted.", "Saved."
|
|
25
|
+
* - `failure`: "Could not save Room 204."
|
|
26
|
+
* - `reason`: why it failed, by HTTP status: "You do not have permission to delete Room 204."
|
|
27
|
+
* - `loading`: "Saving Room 204…"
|
|
28
|
+
* - `confirm`: "Delete 3 rooms?"
|
|
29
|
+
* - `confirmDetail`: the line under a question, such as "This cannot be undone." (empty for most actions)
|
|
30
|
+
* - `label`: the action on a button: "Delete", "Move to the trash"
|
|
31
|
+
*/
|
|
32
|
+
export type MessageKind = "success" | "failure" | "reason" | "loading" | "confirm" | "confirmDetail" | "label";
|
|
33
|
+
/** What a message is about. Every part is optional: a message without a subject names the action's object. */
|
|
34
|
+
export interface MessageContext {
|
|
35
|
+
/** Default `save`. */
|
|
36
|
+
action?: MessageAction;
|
|
37
|
+
/** "Room 204", or a noun with `count`: "room". */
|
|
38
|
+
subject?: string;
|
|
39
|
+
/** How many: 3 with subject "room" → "3 rooms". */
|
|
40
|
+
count?: number;
|
|
41
|
+
/** The plural of `subject` when adding "s" is wrong: "people". */
|
|
42
|
+
plural?: string;
|
|
43
|
+
/** The HTTP status of a failure, for `reason`. */
|
|
44
|
+
status?: number;
|
|
45
|
+
/** Nothing reached the server, for `reason`. */
|
|
46
|
+
network?: boolean;
|
|
47
|
+
/** The server did not answer in time, for `reason`. */
|
|
48
|
+
timeout?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/** A message ready to show: a toast's tone, title, and line under it. */
|
|
51
|
+
export interface BuiltMessage {
|
|
52
|
+
tone: "success" | "danger";
|
|
53
|
+
title: string;
|
|
54
|
+
message?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Every text the builder uses, in one table. Filled in: `{act}` (the verb with its object: "delete Room 204"), `{acting}`
|
|
58
|
+
* ("Deleting Room 204"), `{verb}`, `{done}`, `{doing}`, `{object}` (what is named, or the action's object),
|
|
59
|
+
* `{target}` (what is named, or "this record"), `{status}`, `{module}`, and `{env}`. A capital first letter
|
|
60
|
+
* (`{Object}`, `{Act}`) capitalizes the value. Change them all at once with `configureMessages`, to reword or translate.
|
|
61
|
+
*/
|
|
62
|
+
export interface MessageTexts {
|
|
63
|
+
/** "{Object} {done}." → "Room 204 saved." */
|
|
64
|
+
success: string;
|
|
65
|
+
/** With nothing named: "{Done}." → "Saved." */
|
|
66
|
+
successPlain: string;
|
|
67
|
+
/** "Could not {act}." */
|
|
68
|
+
failure: string;
|
|
69
|
+
/** "{Acting}…" */
|
|
70
|
+
loading: string;
|
|
71
|
+
/** "{Act}?" */
|
|
72
|
+
confirm: string;
|
|
73
|
+
/** A button: "{Verb}". */
|
|
74
|
+
label: string;
|
|
75
|
+
/** The line under a question, by action. */
|
|
76
|
+
confirmDetails: Partial<Record<MessageActionName, string>>;
|
|
77
|
+
/** Why a call failed. */
|
|
78
|
+
reasons: MessageReasons;
|
|
79
|
+
}
|
|
80
|
+
export interface MessageReasons {
|
|
81
|
+
/** Nothing reached the server. */
|
|
82
|
+
network: string;
|
|
83
|
+
/** No answer in time, or 408. */
|
|
84
|
+
timeout: string;
|
|
85
|
+
/** 400 or 422 for an action that sends values. */
|
|
86
|
+
rejectedValues: string;
|
|
87
|
+
/** 400 or 422 for the rest. */
|
|
88
|
+
rejected: string;
|
|
89
|
+
/** 401. */
|
|
90
|
+
signedOut: string;
|
|
91
|
+
/** 403. */
|
|
92
|
+
forbidden: string;
|
|
93
|
+
/** 404 or 410. */
|
|
94
|
+
notFound: string;
|
|
95
|
+
/** 405. */
|
|
96
|
+
notAllowed: string;
|
|
97
|
+
/** 409. */
|
|
98
|
+
conflict: string;
|
|
99
|
+
/** 413. */
|
|
100
|
+
tooLarge: string;
|
|
101
|
+
/** 429. */
|
|
102
|
+
tooMany: string;
|
|
103
|
+
/** 502, 503, 504. */
|
|
104
|
+
unavailable: string;
|
|
105
|
+
/** Other 5xx. */
|
|
106
|
+
serverError: string;
|
|
107
|
+
/** Any other status: "{status}" is the number. */
|
|
108
|
+
other: string;
|
|
109
|
+
/** A module whose API root is not set: "{module}" and "{env}". */
|
|
110
|
+
notConfigured: string;
|
|
111
|
+
}
|