@vuu-ui/vuu-data-editing 3.4.0 → 3.4.1
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/package.json +6 -6
- package/src/DataEditingProvider.js +5 -3
- package/src/DirectEditSession.js +35 -0
- package/src/EditSession.js +9 -0
- package/src/TableEditSession.js +0 -0
- package/src/edit-utils.js +1 -1
- package/src/index.js +2 -1
- package/types/DataEditingProvider.d.ts +14 -2
- package/types/DirectEditSession.d.ts +22 -0
- package/types/EditSession.d.ts +3 -1
- package/types/TableEditSession.d.ts +28 -0
- package/types/edit-field/EditField.d.ts +21 -0
- package/types/edit-field/useEditField.d.ts +26 -0
- package/types/index.d.ts +3 -1
- package/types/lookup-values/useLookupValues.d.ts +19 -0
- package/types/src/DataEditingProvider.d.ts +8 -0
- package/types/src/EditButtons.d.ts +14 -0
- package/types/src/EditModeProvider.d.ts +13 -0
- package/types/src/EditSession.d.ts +86 -0
- package/types/src/UndoCellRenderer.d.ts +12 -0
- package/types/src/edit-utils.d.ts +5 -0
- package/types/src/editActionRowClassNameGenerator.d.ts +3 -0
- package/types/src/index.d.ts +10 -0
- package/types/src/useCellEdited.d.ts +2 -0
- package/types/src/useEditableTable.d.ts +44 -0
- package/types/useCellEdited.d.ts +2 -2
- package/types/useEditable.d.ts +13 -0
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.4.
|
|
2
|
+
"version": "3.4.1",
|
|
3
3
|
"description": "Shared data editing APIs and React components for VUU UI",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"author": "heswell",
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@salt-ds/core": "1.54.1",
|
|
15
|
-
"@vuu-ui/vuu-ui-controls": "3.4.
|
|
16
|
-
"@vuu-ui/vuu-utils": "3.4.
|
|
15
|
+
"@vuu-ui/vuu-ui-controls": "3.4.1",
|
|
16
|
+
"@vuu-ui/vuu-utils": "3.4.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@vuu-ui/vuu-data-types": "3.4.
|
|
20
|
-
"@vuu-ui/vuu-protocol-types": "3.4.
|
|
21
|
-
"@vuu-ui/vuu-table-types": "3.4.
|
|
19
|
+
"@vuu-ui/vuu-data-types": "3.4.1",
|
|
20
|
+
"@vuu-ui/vuu-protocol-types": "3.4.1",
|
|
21
|
+
"@vuu-ui/vuu-table-types": "3.4.1"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"react": "^19.2.3"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
|
+
import { EditSession } from "./EditSession.js";
|
|
3
4
|
const DataEditingContext = /*#__PURE__*/ createContext(void 0);
|
|
4
5
|
const DataEditingProvider = ({ children, editSession })=>/*#__PURE__*/ jsx(DataEditingContext.Provider, {
|
|
5
6
|
value: editSession,
|
|
@@ -7,7 +8,8 @@ const DataEditingProvider = ({ children, editSession })=>/*#__PURE__*/ jsx(DataE
|
|
|
7
8
|
});
|
|
8
9
|
function useEditSession(throwIfUnavailable = false) {
|
|
9
10
|
const editSession = useContext(DataEditingContext);
|
|
10
|
-
if (
|
|
11
|
-
if (throwIfUnavailable) throw Error("[useEditSession] no DataEditingContext in scope. You need to enclose editable component(s) with DataEditingProvider");
|
|
11
|
+
if (editSession instanceof EditSession) return editSession;
|
|
12
|
+
if (throwIfUnavailable) throw Error(void 0 === editSession ? "[useEditSession] no DataEditingContext in scope. You need to enclose editable component(s) with DataEditingProvider" : "[useEditSession] DataEditingProvider does not provide an EditSession");
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
const useTableEditSession = ()=>useContext(DataEditingContext);
|
|
15
|
+
export { DataEditingProvider, useEditSession, useTableEditSession };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EventEmitter } from "@vuu-ui/vuu-utils";
|
|
2
|
+
class DirectEditSession extends EventEmitter {
|
|
3
|
+
#dataSource;
|
|
4
|
+
constructor({ dataSource }){
|
|
5
|
+
super();
|
|
6
|
+
this.#dataSource = dataSource;
|
|
7
|
+
}
|
|
8
|
+
get dataSource() {
|
|
9
|
+
return this.#dataSource;
|
|
10
|
+
}
|
|
11
|
+
get inEditMode() {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
isCellEdited(_key, _columnName) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
async cancel(_key, _columnName, _restoredValue) {
|
|
18
|
+
return {
|
|
19
|
+
data: void 0,
|
|
20
|
+
type: "SUCCESS_RESULT"
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async commit(key, columnName, _originalValue, typedValue, isValid) {
|
|
24
|
+
if (!isValid) return {
|
|
25
|
+
errorMessage: "Invalid value",
|
|
26
|
+
type: "ERROR_RESULT"
|
|
27
|
+
};
|
|
28
|
+
const editCell = this.#dataSource.editCell;
|
|
29
|
+
if (void 0 === editCell) throw Error("[DirectEditSession] datasource does not support editCell");
|
|
30
|
+
const response = await editCell.call(this.#dataSource, key, columnName, typedValue);
|
|
31
|
+
if (void 0 === response) throw Error("[DirectEditSession] datasource returned no response from editCell");
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export { DirectEditSession };
|
package/src/EditSession.js
CHANGED
|
@@ -471,6 +471,15 @@ class EditSession extends EventEmitter {
|
|
|
471
471
|
#isLatestCellCommit(key, columnName, revision) {
|
|
472
472
|
return this.#cellCommitRevisions.get(key)?.get(columnName) === revision;
|
|
473
473
|
}
|
|
474
|
+
async cancel(key, columnName, restoredValue) {
|
|
475
|
+
const cellEdits = this.#rowEdits.get(key)?.cellEdits;
|
|
476
|
+
const cellEdit = cellEdits?.get(columnName);
|
|
477
|
+
if (this.inEditMode && cellEdits && cellEdit && !cellEdit.isValid) this.#storeCellEdit(key, cellEdits, columnName, cellEdit.originalValue, restoredValue, true);
|
|
478
|
+
return {
|
|
479
|
+
data: void 0,
|
|
480
|
+
type: "SUCCESS_RESULT"
|
|
481
|
+
};
|
|
482
|
+
}
|
|
474
483
|
async commit(key, columnName, originalValue, typedValue, isValid) {
|
|
475
484
|
if ("active" !== this.#lifecycle.status && !("error" === this.#lifecycle.status && "end" === this.#lifecycle.operation)) throw new Error("No edit session in progress");
|
|
476
485
|
const revision = this.#setCellCommitRevision(key, columnName);
|
|
File without changes
|
package/src/edit-utils.js
CHANGED
|
@@ -4,7 +4,7 @@ const timeFormatter = formatDate({
|
|
|
4
4
|
time: "hh:mm:ss"
|
|
5
5
|
});
|
|
6
6
|
const dataRowEditErrors = Symbol("vuuDataRowEditErrors");
|
|
7
|
-
const isEditRowReadOnly = (dataRow)=>"deleteRow" === dataRow.vuuAction;
|
|
7
|
+
const isEditRowReadOnly = (dataRow)=>dataRow.hasColumn("vuuAction") && "deleteRow" === dataRow.vuuAction;
|
|
8
8
|
const withDataRowEditErrors = (dataRow, errors)=>{
|
|
9
9
|
Object.defineProperty(dataRow, dataRowEditErrors, {
|
|
10
10
|
configurable: true,
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { DataEditingProvider, useEditSession } from "./DataEditingProvider.js";
|
|
1
|
+
export { DataEditingProvider, useEditSession, useTableEditSession } from "./DataEditingProvider.js";
|
|
2
|
+
export { DirectEditSession } from "./DirectEditSession.js";
|
|
2
3
|
export { useCellEdited } from "./useCellEdited.js";
|
|
3
4
|
export { useEditState } from "./useEditState.js";
|
|
4
5
|
export { getVuuEditMessage, isEditRowReadOnly, isInlineEditingSession, withDataRowEditErrors } from "./edit-utils.js";
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import
|
|
2
|
+
import { EditSession } from "./EditSession";
|
|
3
|
+
import type { TableEditSession } from "./TableEditSession";
|
|
3
4
|
export declare const DataEditingProvider: ({ children, editSession, }: {
|
|
4
5
|
children: ReactNode;
|
|
5
|
-
editSession:
|
|
6
|
+
editSession: TableEditSession;
|
|
6
7
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
/**
|
|
9
|
+
* Returns the EditSession provided by an enclosing DataEditingProvider. If the
|
|
10
|
+
* provider holds some other TableEditSession (e.g. DirectEditSession), there is
|
|
11
|
+
* no EditSession in scope and undefined is returned.
|
|
12
|
+
*/
|
|
7
13
|
export declare function useEditSession(throwIfUnavailable?: false): EditSession | undefined;
|
|
8
14
|
export declare function useEditSession(throwIfUnavailable: true): EditSession;
|
|
15
|
+
/**
|
|
16
|
+
* Returns whichever TableEditSession is provided by an enclosing
|
|
17
|
+
* DataEditingProvider. Intended for use by Table cells, which commit and
|
|
18
|
+
* cancel edits regardless of the type of session.
|
|
19
|
+
*/
|
|
20
|
+
export declare const useTableEditSession: () => TableEditSession | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DataSource } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import type { RpcResult, VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
import { EventEmitter } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import type { TableEditSession, TableEditSessionEvents } from "./TableEditSession";
|
|
5
|
+
export type DirectEditSessionConstructorProps = {
|
|
6
|
+
dataSource: DataSource;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* A lightweight edit session for services that allow cells to be edited
|
|
10
|
+
* directly on the source table. There is no begin/end lifecycle, no session
|
|
11
|
+
* table and no local tracking of edits - each committed edit is sent
|
|
12
|
+
* immediately via the dataSource editCell RPC.
|
|
13
|
+
*/
|
|
14
|
+
export declare class DirectEditSession extends EventEmitter<TableEditSessionEvents> implements TableEditSession {
|
|
15
|
+
#private;
|
|
16
|
+
constructor({ dataSource }: DirectEditSessionConstructorProps);
|
|
17
|
+
get dataSource(): DataSource;
|
|
18
|
+
get inEditMode(): boolean;
|
|
19
|
+
isCellEdited(_key: string, _columnName: string): boolean;
|
|
20
|
+
cancel(_key: string, _columnName: string, _restoredValue: VuuRowDataItemType): Promise<RpcResult>;
|
|
21
|
+
commit(key: string, columnName: string, _originalValue: VuuRowDataItemType, typedValue: string | number | boolean, isValid: boolean): Promise<RpcResult>;
|
|
22
|
+
}
|
package/types/EditSession.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CopyOption, DataSource, DeleteRowMode, SessionType } from "@vuu-ui/vuu-data-types";
|
|
2
2
|
import type { RpcResult, VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
3
3
|
import { EventEmitter } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import type { TableEditSession } from "./TableEditSession";
|
|
4
5
|
export type EditState = "clean" | "dirty" | "invalid" | "stale";
|
|
5
6
|
export type EditActionType = "deleteRow" | "addRow" | "editCell";
|
|
6
7
|
/** Column name to default value mapping applied to every addRow call when a column is absent from the row data. */
|
|
@@ -49,7 +50,7 @@ type EditSessionEvents = {
|
|
|
49
50
|
lifecycle: (lifecycle: EditLifecycle) => void;
|
|
50
51
|
newRow: (newRowState: NewRowState) => void;
|
|
51
52
|
};
|
|
52
|
-
export declare class EditSession extends EventEmitter<EditSessionEvents> {
|
|
53
|
+
export declare class EditSession extends EventEmitter<EditSessionEvents> implements TableEditSession {
|
|
53
54
|
#private;
|
|
54
55
|
static readonly newRowKey = "__vuu_new_row__";
|
|
55
56
|
constructor({ dataSource, deleteMode, editSessionApi, rowDefaults, }: EditSessionConstructorProps);
|
|
@@ -82,6 +83,7 @@ export declare class EditSession extends EventEmitter<EditSessionEvents> {
|
|
|
82
83
|
end(saveChanges?: boolean, force?: boolean): Promise<void>;
|
|
83
84
|
get lifecycle(): EditLifecycle;
|
|
84
85
|
get inEditMode(): boolean;
|
|
86
|
+
cancel(key: string, columnName: string, restoredValue: VuuRowDataItemType): Promise<RpcResult>;
|
|
85
87
|
commit(key: string, columnName: string, originalValue: VuuRowDataItemType, typedValue: string | number | boolean, isValid: boolean): Promise<RpcResult>;
|
|
86
88
|
}
|
|
87
89
|
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { RpcResult, VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
+
export type TableEditSessionEvents = {
|
|
3
|
+
cellEditChanged: (key: string, columnName: string) => void;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* The subset of edit session behaviour consumed by Table and its cells.
|
|
7
|
+
* Implemented by EditSession (edits staged in a session table, committed or
|
|
8
|
+
* discarded at end of session) and DirectEditSession (edits applied directly
|
|
9
|
+
* to the source table).
|
|
10
|
+
*/
|
|
11
|
+
export interface TableEditSession {
|
|
12
|
+
/**
|
|
13
|
+
* True while a staged edit session is in progress. Always false for
|
|
14
|
+
* DirectEditSession.
|
|
15
|
+
*/
|
|
16
|
+
readonly inEditMode: boolean;
|
|
17
|
+
commit(key: string, columnName: string, originalValue: VuuRowDataItemType, typedValue: string | number | boolean, isValid: boolean): Promise<RpcResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Invoked when user abandons an in-progress cell edit, restoring the value
|
|
20
|
+
* the cell held before editing began. Values that have only been typed, not
|
|
21
|
+
* committed, have never been sent to the server, so nothing is sent here.
|
|
22
|
+
* Any invalid edit previously recorded for the cell is discarded.
|
|
23
|
+
*/
|
|
24
|
+
cancel(key: string, columnName: string, restoredValue: VuuRowDataItemType): Promise<RpcResult>;
|
|
25
|
+
isCellEdited(key: string, columnName: string): boolean;
|
|
26
|
+
on<E extends keyof TableEditSessionEvents>(event: E, listener: TableEditSessionEvents[E]): void;
|
|
27
|
+
removeListener<E extends keyof TableEditSessionEvents>(event: E, listener: TableEditSessionEvents[E]): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DataRow } from "@vuu-ui/vuu-table-types";
|
|
2
|
+
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
import { type OptionMap } from "../lookup-values/useLookupValues";
|
|
4
|
+
import "./EditField.css";
|
|
5
|
+
export type TextFieldType = "email" | "password";
|
|
6
|
+
export type EditFieldType = "checkbox" | "dropdown" | TextFieldType;
|
|
7
|
+
export interface EditFieldProps {
|
|
8
|
+
dataRow: DataRow;
|
|
9
|
+
deferNewRow?: boolean;
|
|
10
|
+
label: string;
|
|
11
|
+
name: string;
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
type?: EditFieldType;
|
|
15
|
+
}
|
|
16
|
+
export interface DropdownEditFieldProps extends EditFieldProps {
|
|
17
|
+
type: "dropdown";
|
|
18
|
+
optionMap: OptionMap;
|
|
19
|
+
table: VuuTable;
|
|
20
|
+
}
|
|
21
|
+
export declare const EditField: ({ dataRow, deferNewRow, label, name, readOnly, required, type, ...options }: EditFieldProps | DropdownEditFieldProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
+
import type { RuntimeColumnDescriptor, TableCellEditHandler } from "@vuu-ui/vuu-table-types";
|
|
3
|
+
import { type ChangeEventHandler, type FocusEventHandler, type KeyboardEvent, type SyntheticEvent } from "react";
|
|
4
|
+
import type { LookupOption } from "../lookup-values/useLookupValues";
|
|
5
|
+
import type { TextFieldType } from "./EditField";
|
|
6
|
+
export interface EditFieldHookProps<T extends VuuRowDataItemType = VuuRowDataItemType> {
|
|
7
|
+
column: Pick<RuntimeColumnDescriptor, "clientSideEditValidationCheck" | "label" | "name">;
|
|
8
|
+
value?: T;
|
|
9
|
+
onEdit?: TableCellEditHandler;
|
|
10
|
+
textType?: TextFieldType;
|
|
11
|
+
type?: "string" | "number" | "boolean";
|
|
12
|
+
}
|
|
13
|
+
export declare const useEditField: <T extends string | number | boolean = string>({ column, value, onEdit, textType, type, }: EditFieldHookProps<T>) => {
|
|
14
|
+
editing: boolean;
|
|
15
|
+
inputProps: {
|
|
16
|
+
onBlur: FocusEventHandler<HTMLElement>;
|
|
17
|
+
onFocus: FocusEventHandler<HTMLElement>;
|
|
18
|
+
type: TextFieldType | undefined;
|
|
19
|
+
};
|
|
20
|
+
onKeyDown: (evt: KeyboardEvent<HTMLElement>) => Promise<void>;
|
|
21
|
+
previousValue: string | undefined;
|
|
22
|
+
value: string;
|
|
23
|
+
warningMessage: string | undefined;
|
|
24
|
+
onChange: ChangeEventHandler;
|
|
25
|
+
onDropdownSelectionChange: (_evt: SyntheticEvent, [selectedOption]: LookupOption[]) => void;
|
|
26
|
+
};
|
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { DataEditingProvider, useEditSession } from "./DataEditingProvider";
|
|
1
|
+
export { DataEditingProvider, useEditSession, useTableEditSession, } from "./DataEditingProvider";
|
|
2
|
+
export { DirectEditSession, type DirectEditSessionConstructorProps, } from "./DirectEditSession";
|
|
3
|
+
export type { TableEditSession, TableEditSessionEvents, } from "./TableEditSession";
|
|
2
4
|
export { useCellEdited } from "./useCellEdited";
|
|
3
5
|
export { useEditState } from "./useEditState";
|
|
4
6
|
export { getVuuEditMessage, isInlineEditingSession, isEditRowReadOnly, withDataRowEditErrors, } from "./edit-utils";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DataSourceRow } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
export type LookupOption = {
|
|
4
|
+
label: string;
|
|
5
|
+
metadata?: Record<string, string>;
|
|
6
|
+
value: number | string;
|
|
7
|
+
};
|
|
8
|
+
export type OptionMap = {
|
|
9
|
+
additionalFields?: readonly string[];
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
};
|
|
13
|
+
export interface LookupValuedHookProps {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
optionMap?: OptionMap;
|
|
16
|
+
table?: VuuTable;
|
|
17
|
+
}
|
|
18
|
+
export declare const lookupOptionsFromRows: (columns: string[], rows: DataSourceRow[], optionMap: OptionMap) => LookupOption[];
|
|
19
|
+
export declare const useLookupValues: ({ enabled, optionMap, table, }: LookupValuedHookProps) => LookupOption[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { EditSession } from "./EditSession";
|
|
3
|
+
export declare const DataEditingProvider: ({ children, editSession, }: {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
editSession: EditSession;
|
|
6
|
+
}) => import("react").JSX.Element;
|
|
7
|
+
export declare function useEditSession(throwIfUnavailable?: false): EditSession | undefined;
|
|
8
|
+
export declare function useEditSession(throwIfUnavailable: true): EditSession;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EditSession } from "./EditSession";
|
|
2
|
+
export interface EditButtonProps {
|
|
3
|
+
canCancel: boolean;
|
|
4
|
+
canSave: boolean;
|
|
5
|
+
editSession?: EditSession;
|
|
6
|
+
hasSelection?: boolean;
|
|
7
|
+
onCancel?: () => void;
|
|
8
|
+
onDelete?: () => void;
|
|
9
|
+
onSave: (force?: boolean) => void;
|
|
10
|
+
saveLabel?: string;
|
|
11
|
+
confirmSave?: () => boolean | Promise<boolean>;
|
|
12
|
+
confirmCancel?: () => boolean | Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
export declare const EditButtons: ({ canCancel, canSave, confirmCancel, confirmSave, editSession, hasSelection, onCancel, onDelete, onSave, saveLabel, }: EditButtonProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
export interface EditModeContextProps {
|
|
3
|
+
isEditMode: boolean;
|
|
4
|
+
setEditMode: (inEditMode: boolean) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Implemented as a standalone Provider so that EditMode cna be implemented
|
|
8
|
+
* at higher level than individual edit controls.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EditModeProvider: ({ children }: {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}) => import("react").JSX.Element;
|
|
13
|
+
export declare const useEditMode: () => EditModeContextProps;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { CopyOption, DataSource, DeleteRowMode, SessionType } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import type { RpcResult, VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
import { EventEmitter } from "@vuu-ui/vuu-utils";
|
|
4
|
+
export type EditState = "clean" | "dirty" | "invalid" | "stale";
|
|
5
|
+
export type EditActionType = "deleteRow" | "addRow" | "editCell";
|
|
6
|
+
/** Column name to default value mapping applied to every addRow call when a column is absent from the row data. */
|
|
7
|
+
export type RowDefaultDataItemValues = Record<string, VuuRowDataItemType>;
|
|
8
|
+
export type EditSessionApi = "createSessionDataSource" | "beginEditSession";
|
|
9
|
+
export type EditSessionConstructorProps = {
|
|
10
|
+
dataSource: DataSource;
|
|
11
|
+
/** @default "soft" */
|
|
12
|
+
deleteMode?: DeleteRowMode;
|
|
13
|
+
/** @default "createSessionDataSource" */
|
|
14
|
+
editSessionApi?: EditSessionApi;
|
|
15
|
+
/** Default column values merged into every addRow call for absent columns. Pass a stable reference. */
|
|
16
|
+
rowDefaults?: RowDefaultDataItemValues;
|
|
17
|
+
};
|
|
18
|
+
export type NewRowState = {
|
|
19
|
+
columns: readonly string[];
|
|
20
|
+
requiredColumns?: readonly string[];
|
|
21
|
+
draftRevision: number;
|
|
22
|
+
errors: Readonly<Record<string, string>>;
|
|
23
|
+
submitting: boolean;
|
|
24
|
+
values: Readonly<Record<string, VuuRowDataItemType>>;
|
|
25
|
+
};
|
|
26
|
+
export type EditLifecycle = {
|
|
27
|
+
status: "idle";
|
|
28
|
+
} | {
|
|
29
|
+
status: "starting";
|
|
30
|
+
} | {
|
|
31
|
+
status: "active";
|
|
32
|
+
sessionDataSource: DataSource;
|
|
33
|
+
} | {
|
|
34
|
+
status: "ending";
|
|
35
|
+
sessionDataSource: DataSource;
|
|
36
|
+
} | {
|
|
37
|
+
status: "error";
|
|
38
|
+
operation: "begin" | "end";
|
|
39
|
+
error: Error;
|
|
40
|
+
sessionDataSource?: DataSource;
|
|
41
|
+
};
|
|
42
|
+
export declare class EditError extends Error {
|
|
43
|
+
}
|
|
44
|
+
export declare class SupersededEditError extends Error {
|
|
45
|
+
}
|
|
46
|
+
type EditSessionEvents = {
|
|
47
|
+
cellEditChanged: (key: string, columnName: string) => void;
|
|
48
|
+
editState: (editState: EditState) => void;
|
|
49
|
+
lifecycle: (lifecycle: EditLifecycle) => void;
|
|
50
|
+
newRow: (newRowState: NewRowState) => void;
|
|
51
|
+
};
|
|
52
|
+
export declare class EditSession extends EventEmitter<EditSessionEvents> {
|
|
53
|
+
#private;
|
|
54
|
+
static readonly newRowKey = "__vuu_new_row__";
|
|
55
|
+
constructor({ dataSource, deleteMode, editSessionApi, rowDefaults, }: EditSessionConstructorProps);
|
|
56
|
+
get editCount(): number;
|
|
57
|
+
get invalidCount(): number;
|
|
58
|
+
get deleteCount(): number;
|
|
59
|
+
get addCount(): number;
|
|
60
|
+
get editState(): EditState;
|
|
61
|
+
get newRowState(): NewRowState;
|
|
62
|
+
isNewRow(key: string): key is "__vuu_new_row__";
|
|
63
|
+
isNewRowFinalColumn(columnName: string): boolean;
|
|
64
|
+
isNewRowComplete(): boolean;
|
|
65
|
+
configureNewRow(columns: readonly string[], requiredColumns?: readonly string[]): void;
|
|
66
|
+
setNewRowValue(column: string, value: VuuRowDataItemType): void;
|
|
67
|
+
addNewRow(): Promise<RpcResult>;
|
|
68
|
+
deleteSelectedRows(): Promise<RpcResult>;
|
|
69
|
+
addRow(rowData?: Record<string, VuuRowDataItemType>): Promise<RpcResult>;
|
|
70
|
+
hasRowChanges(key: string): boolean;
|
|
71
|
+
isCellEdited(key: string, columnName: string): boolean;
|
|
72
|
+
undoRowChange(key: string, action: EditActionType): Promise<RpcResult | undefined>;
|
|
73
|
+
begin(copyOption?: CopyOption, sessionType?: SessionType): Promise<DataSource>;
|
|
74
|
+
/**
|
|
75
|
+
* Safe to call repeatedly - schema of a remote session table typically arrives
|
|
76
|
+
* after begin() resolves, so callers re-invoke this once 'subscribed' fires.
|
|
77
|
+
*/
|
|
78
|
+
reconcileWithSessionSchema(): void;
|
|
79
|
+
get dataSource(): import("@vuu-ui/vuu-data-types").DataSourceBase<import("@vuu-ui/vuu-data-types").DataSourceRowWithBigint> | undefined;
|
|
80
|
+
get sessionDataSource(): DataSource | undefined;
|
|
81
|
+
end(saveChanges?: boolean, force?: boolean): Promise<void>;
|
|
82
|
+
get lifecycle(): EditLifecycle;
|
|
83
|
+
get inEditMode(): boolean;
|
|
84
|
+
commit(key: string, columnName: string, originalValue: VuuRowDataItemType, typedValue: string | number | boolean, isValid: boolean): Promise<RpcResult>;
|
|
85
|
+
}
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TableCellRendererProps } from "@vuu-ui/vuu-table-types";
|
|
2
|
+
export declare const UNDO_CELL_RENDERER = "vuu.undo-cell";
|
|
3
|
+
export interface UndoCellRendererComponentProps {
|
|
4
|
+
icon?: string;
|
|
5
|
+
text?: string | false;
|
|
6
|
+
}
|
|
7
|
+
export declare const getUndoButtonContent: (componentProps?: UndoCellRendererComponentProps) => {
|
|
8
|
+
icon: string | undefined;
|
|
9
|
+
text: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
export declare const getUndoTooltipContent: (action: unknown) => "Undo delete row" | "Undo insert row" | "Undo row edits" | undefined;
|
|
12
|
+
export declare const UndoCellRenderer: ({ column, dataRow, }: TableCellRendererProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DataRow, RuntimeColumnDescriptor } from "@vuu-ui/vuu-table-types";
|
|
2
|
+
export { isInlineEditingSession } from "@vuu-ui/vuu-utils";
|
|
3
|
+
export declare const isEditRowReadOnly: (dataRow: DataRow) => boolean;
|
|
4
|
+
export declare const withDataRowEditErrors: <T extends DataRow>(dataRow: T, errors: Record<string, string>) => T;
|
|
5
|
+
export declare const getVuuEditMessage: (dataRow: DataRow, column: RuntimeColumnDescriptor, originalValue: string) => string | import("react").JSX.Element | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { DataEditingProvider, useEditSession } from "./DataEditingProvider";
|
|
2
|
+
export { useCellEdited } from "./useCellEdited";
|
|
3
|
+
export { getVuuEditMessage, isInlineEditingSession, isEditRowReadOnly, withDataRowEditErrors, } from "./edit-utils";
|
|
4
|
+
export { EditButtons, type EditButtonProps } from "./EditButtons";
|
|
5
|
+
export { EditModeProvider, useEditMode, type EditModeContextProps, } from "./EditModeProvider";
|
|
6
|
+
export { EditError, EditSession, SupersededEditError, type EditActionType, type EditLifecycle, type EditSessionConstructorProps, type NewRowState, type EditState, type RowDefaultDataItemValues, } from "./EditSession";
|
|
7
|
+
export { StaleUpdateError } from "@vuu-ui/vuu-utils";
|
|
8
|
+
export { EDIT_ACTION_ROW_CLASS_NAME_GENERATOR, editActionRowClassNameGenerator, } from "./editActionRowClassNameGenerator";
|
|
9
|
+
export { getUndoButtonContent, getUndoTooltipContent, UNDO_CELL_RENDERER, UndoCellRenderer, type UndoCellRendererComponentProps, } from "./UndoCellRenderer";
|
|
10
|
+
export { useEditableTable, type EditableTableHookProps, type EditMode, } from "./useEditableTable";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CopyOption, DataSource, DeleteRowMode } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
import { EditSession, type EditActionType, type EditLifecycle, type EditSessionApi, type RowDefaultDataItemValues } from "./EditSession";
|
|
4
|
+
export type EditMode = "edit" | "view";
|
|
5
|
+
export interface EditableTableHookProps {
|
|
6
|
+
/**
|
|
7
|
+
* columns to be included in subscription. If not provided,
|
|
8
|
+
* default will be '*'. Ignored if dataSource prop present.
|
|
9
|
+
*/
|
|
10
|
+
columns?: string[];
|
|
11
|
+
dataSource?: DataSource;
|
|
12
|
+
addRowsCount?: number;
|
|
13
|
+
deleteMode?: DeleteRowMode;
|
|
14
|
+
editSessionApi?: EditSessionApi;
|
|
15
|
+
copyOption?: CopyOption;
|
|
16
|
+
isEditMode: boolean;
|
|
17
|
+
onCancel: () => void;
|
|
18
|
+
onSave: () => void;
|
|
19
|
+
/** Default column values applied to every addRow call. Pass a stable reference — a new object triggers EditSession recreation. */
|
|
20
|
+
rowDefaults?: RowDefaultDataItemValues;
|
|
21
|
+
/**
|
|
22
|
+
* If dataSource not provided, new DataSource
|
|
23
|
+
* will be created using table and columns
|
|
24
|
+
*/
|
|
25
|
+
table?: VuuTable;
|
|
26
|
+
}
|
|
27
|
+
export declare const useEditableTable: ({ columns, dataSource: dataSourceProp, deleteMode, editSessionApi, copyOption, isEditMode, onCancel, onSave, rowDefaults, table, }: EditableTableHookProps) => {
|
|
28
|
+
canCancel: boolean;
|
|
29
|
+
canSave: boolean;
|
|
30
|
+
columnsDiverge: boolean;
|
|
31
|
+
dataSource: DataSource;
|
|
32
|
+
editSchema: import("@vuu-ui/vuu-data-types").TableSchema | undefined;
|
|
33
|
+
editSession: EditSession;
|
|
34
|
+
lifecycle: EditLifecycle;
|
|
35
|
+
hasSelection: boolean;
|
|
36
|
+
isEditSessionReady: boolean;
|
|
37
|
+
onCancel: () => Promise<void>;
|
|
38
|
+
onDelete: () => Promise<void>;
|
|
39
|
+
onSave: (force?: boolean) => Promise<void>;
|
|
40
|
+
onUndoRowChange: (key: string, action: EditActionType) => undefined;
|
|
41
|
+
rowClassNameGenerators: string[] | undefined;
|
|
42
|
+
sessionDataSource: import("@vuu-ui/vuu-data-types").DataSourceBase<import("@vuu-ui/vuu-data-types").DataSourceRowWithBigint> | undefined;
|
|
43
|
+
sourceDataSource: DataSource;
|
|
44
|
+
};
|
package/types/useCellEdited.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const useCellEdited: (editSession:
|
|
1
|
+
import type { TableEditSession } from "./TableEditSession";
|
|
2
|
+
export declare const useCellEdited: (editSession: TableEditSession | undefined, key: string, columnName: string) => boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CopyOption, DataSource } from "@vuu-ui/vuu-data-types";
|
|
2
|
+
import { EditSession } from ".";
|
|
3
|
+
export interface EditableHookProps {
|
|
4
|
+
copyOption?: CopyOption;
|
|
5
|
+
dataSource: DataSource;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
onSave: () => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const useEditable: ({ copyOption, dataSource, onCancel, onSave }: EditableHookProps) => {
|
|
10
|
+
editSession: EditSession;
|
|
11
|
+
onCancel: () => Promise<void>;
|
|
12
|
+
onSave: (force?: boolean) => Promise<void>;
|
|
13
|
+
};
|