@vuu-ui/vuu-table-extras 5.0.0-alpha.1 → 5.0.0-alpha.3

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.0.0-alpha.1",
2
+ "version": "5.0.0-alpha.3",
3
3
  "author": "heswell",
4
4
  "main": "./src/index.js",
5
5
  "license": "Apache-2.0",
@@ -11,25 +11,25 @@
11
11
  "lezer-generate:column": "lezer-generator --output ./src/column-expression-input/column-language-parser/generated/column-parser.ts ./src/column-expression-input/column-language-parser/grammar/column.grammar"
12
12
  },
13
13
  "devDependencies": {
14
- "@vuu-ui/vuu-filter-types": "5.0.0-alpha.1",
15
- "@vuu-ui/vuu-protocol-types": "5.0.0-alpha.1"
14
+ "@vuu-ui/vuu-filter-types": "5.0.0-alpha.3",
15
+ "@vuu-ui/vuu-protocol-types": "5.0.0-alpha.3"
16
16
  },
17
17
  "dependencies": {
18
- "@vuu-ui/vuu-codemirror": "5.0.0-alpha.1",
19
- "@vuu-ui/vuu-data-editing": "5.0.0-alpha.1",
20
- "@vuu-ui/vuu-data-react": "5.0.0-alpha.1",
21
- "@vuu-ui/vuu-data-types": "5.0.0-alpha.1",
22
- "@vuu-ui/vuu-table-types": "5.0.0-alpha.1",
23
- "@vuu-ui/vuu-popups": "5.0.0-alpha.1",
24
- "@vuu-ui/vuu-table": "5.0.0-alpha.1",
25
- "@vuu-ui/vuu-utils": "5.0.0-alpha.1",
26
- "@vuu-ui/vuu-ui-controls": "5.0.0-alpha.1",
18
+ "@vuu-ui/vuu-codemirror": "5.0.0-alpha.3",
19
+ "@vuu-ui/vuu-data-editing": "5.0.0-alpha.3",
20
+ "@vuu-ui/vuu-data-react": "5.0.0-alpha.3",
21
+ "@vuu-ui/vuu-data-types": "5.0.0-alpha.3",
22
+ "@vuu-ui/vuu-table-types": "5.0.0-alpha.3",
23
+ "@vuu-ui/vuu-popups": "5.0.0-alpha.3",
24
+ "@vuu-ui/vuu-table": "5.0.0-alpha.3",
25
+ "@vuu-ui/vuu-utils": "5.0.0-alpha.3",
26
+ "@vuu-ui/vuu-ui-controls": "5.0.0-alpha.3",
27
27
  "@lezer/lr": "1.4.2",
28
28
  "@salt-ds/core": "1.74.0",
29
29
  "@salt-ds/styles": "0.4.2",
30
30
  "@salt-ds/window": "0.1.2",
31
31
  "csv-parse": "^7.0.0",
32
- "@vuu-ui/core": "5.0.0-alpha.1"
32
+ "@vuu-ui/core": "5.0.0-alpha.3"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@floating-ui/react": "^0.27.19",
@@ -0,0 +1,93 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { DataEditingProvider, EditButtons, useEditableTable } from "@vuu-ui/vuu-data-editing";
3
+ import { BulkEditPanel } from "@vuu-ui/vuu-table";
4
+ import { useModal } from "@vuu-ui/core";
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ const NOT_EDITING = {
7
+ copyOption: "Selected",
8
+ editing: false
9
+ };
10
+ const useBulkEditDialog = ({ bulkEditPanelProps, confirmCancel, dataSource: sourceTableDataSource, deleteMode, editSessionApi, onCancelled, onError, onSaved, rowDefaults, saveLabel = "Save", title = "Edit rows" })=>{
11
+ const { closeDialog, showDialog } = useModal();
12
+ const [{ copyOption, editing }, setDialogState] = useState(NOT_EDITING);
13
+ const callbacksRef = useRef({
14
+ onCancelled,
15
+ onSaved
16
+ });
17
+ callbacksRef.current = {
18
+ onCancelled,
19
+ onSaved
20
+ };
21
+ const handleCancelled = useCallback(()=>{
22
+ setDialogState(NOT_EDITING);
23
+ callbacksRef.current.onCancelled?.();
24
+ }, []);
25
+ const handleSaved = useCallback(()=>{
26
+ setDialogState(NOT_EDITING);
27
+ callbacksRef.current.onSaved?.();
28
+ }, []);
29
+ const { editSession, onCancel, onSave, rowClassNameGenerators, sessionDataSource, sourceDataSource } = useEditableTable({
30
+ copyOption,
31
+ dataSource: sourceTableDataSource,
32
+ deleteMode,
33
+ editSessionApi,
34
+ isEditMode: editing,
35
+ onCancel: handleCancelled,
36
+ onError,
37
+ onSave: handleSaved,
38
+ rowDefaults
39
+ });
40
+ const editSelectedRows = useCallback(()=>{
41
+ setDialogState({
42
+ copyOption: "Selected",
43
+ editing: true
44
+ });
45
+ }, []);
46
+ const insertRows = useCallback(()=>{
47
+ setDialogState({
48
+ copyOption: "Empty",
49
+ editing: true
50
+ });
51
+ }, []);
52
+ useEffect(()=>{
53
+ if (editing && sessionDataSource) showDialog(/*#__PURE__*/ jsx(DataEditingProvider, {
54
+ editSession: editSession,
55
+ children: /*#__PURE__*/ jsx(BulkEditPanel, {
56
+ ...bulkEditPanelProps,
57
+ parentDs: sourceDataSource,
58
+ rowClassNameGenerators: rowClassNameGenerators,
59
+ sessionDs: sessionDataSource
60
+ })
61
+ }), title, [
62
+ /*#__PURE__*/ jsx(EditButtons, {
63
+ confirmCancel: confirmCancel,
64
+ editSession: editSession,
65
+ onCancel: onCancel,
66
+ onSave: onSave,
67
+ saveLabel: saveLabel
68
+ }, "edit-buttons")
69
+ ], true);
70
+ else closeDialog();
71
+ }, [
72
+ bulkEditPanelProps,
73
+ closeDialog,
74
+ confirmCancel,
75
+ editSession,
76
+ editing,
77
+ onCancel,
78
+ onSave,
79
+ rowClassNameGenerators,
80
+ saveLabel,
81
+ sessionDataSource,
82
+ showDialog,
83
+ sourceDataSource,
84
+ title
85
+ ]);
86
+ return {
87
+ editSelectedRows,
88
+ editSession,
89
+ insertRows,
90
+ isEditing: editing
91
+ };
92
+ };
93
+ export { useBulkEditDialog };
@@ -0,0 +1,41 @@
1
+ const css = `
2
+ .vuuEditableTable {
3
+ --vuuMeasuredContainer-flex: 1 1 1px;
4
+ flex-direction: column;
5
+ flex: auto;
6
+ min-width: 0;
7
+ height: 100%;
8
+ min-height: 0;
9
+ display: flex;
10
+ }
11
+
12
+ .vuuEditableTable-withPanel {
13
+ flex-direction: row;
14
+ }
15
+
16
+ .vuuEditableTable-main {
17
+ --vuuMeasuredContainer-flex: 1 1 1px;
18
+ flex-direction: column;
19
+ flex: auto;
20
+ min-width: 0;
21
+ min-height: 0;
22
+ display: flex;
23
+ }
24
+
25
+ .vuuEditableTable-panel {
26
+ --saltSidePanel-width: 320px;
27
+ }
28
+
29
+ .vuuEditableTable-panelHeader > :first-child {
30
+ flex: 1;
31
+ min-width: 0;
32
+ }
33
+
34
+ .vuuEditableTable-detail {
35
+ min-height: 0;
36
+ overflow: auto;
37
+ }
38
+
39
+
40
+ `;
41
+ export default css;
@@ -0,0 +1,176 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { SidePanelContent, SidePanelTitle } from "@salt-ds/core";
3
+ import { useComponentCssInjection } from "@salt-ds/styles";
4
+ import { useWindow } from "@salt-ds/window";
5
+ import clsx from "clsx";
6
+ import { TableEditorCreateForm, TableEditorEditButton, TableEditorForm, TableEditorModeToggle, TableEditorNewButton, TableEditorPlaceholder, TableEditorTable, TableEditorToolbar, useTableEditor } from "../table-editor/index.js";
7
+ import { TableEditorProvider } from "../table-editor/TableEditorProvider.js";
8
+ import EditableTable from "./EditableTable.css";
9
+ import { EditableTableFooter, EditableTableMain, EditableTablePanel, EditableTablePanelHeader } from "./EditableTableLayout.js";
10
+ const classBase = "vuuEditableTable";
11
+ const PanelTitle = ({ createTitle, formTitle })=>{
12
+ const { mode, selectedRow } = useTableEditor();
13
+ const title = "create" === mode ? createTitle : selectedRow ? "function" == typeof formTitle ? formTitle(selectedRow) : formTitle : null;
14
+ return title ? /*#__PURE__*/ jsx(SidePanelTitle, {
15
+ children: title
16
+ }) : null;
17
+ };
18
+ const InlineContent = ({ createFields, createTitle = "New", panelClassName, saveLabel, showEditModeToggle, testId, validateCreate, ...tableProps })=>{
19
+ const { createStrategy, editModel } = useTableEditor();
20
+ const hasCreateForm = "form" === createStrategy;
21
+ const showToggle = showEditModeToggle ?? "session" === editModel;
22
+ const table = /*#__PURE__*/ jsxs(Fragment, {
23
+ children: [
24
+ showToggle || hasCreateForm ? /*#__PURE__*/ jsxs(TableEditorToolbar, {
25
+ children: [
26
+ showToggle ? /*#__PURE__*/ jsx(TableEditorModeToggle, {
27
+ testId: testId
28
+ }) : null,
29
+ hasCreateForm ? /*#__PURE__*/ jsx(TableEditorNewButton, {
30
+ "data-testid": `new-button${testId}`
31
+ }) : null
32
+ ]
33
+ }) : null,
34
+ /*#__PURE__*/ jsx(TableEditorTable, {
35
+ "data-testid": `table${testId}`,
36
+ ...tableProps
37
+ }),
38
+ /*#__PURE__*/ jsx(EditableTableFooter, {
39
+ saveLabel: saveLabel
40
+ })
41
+ ]
42
+ });
43
+ return hasCreateForm ? /*#__PURE__*/ jsxs(Fragment, {
44
+ children: [
45
+ /*#__PURE__*/ jsx(EditableTableMain, {
46
+ children: table
47
+ }),
48
+ /*#__PURE__*/ jsxs(EditableTablePanel, {
49
+ className: panelClassName,
50
+ "data-testid": `edit-panel${testId}`,
51
+ children: [
52
+ /*#__PURE__*/ jsx(EditableTablePanelHeader, {
53
+ children: /*#__PURE__*/ jsx(PanelTitle, {
54
+ createTitle: createTitle
55
+ })
56
+ }),
57
+ /*#__PURE__*/ jsx(SidePanelContent, {
58
+ className: `${classBase}-detail`,
59
+ children: /*#__PURE__*/ jsx(TableEditorCreateForm, {
60
+ "data-testid": `create-form${testId}`,
61
+ fields: createFields,
62
+ validate: validateCreate
63
+ })
64
+ })
65
+ ]
66
+ })
67
+ ]
68
+ }) : table;
69
+ };
70
+ const FormContent = ({ allowCreate = true, createFields, createTitle = "New", fields, formTitle, panelClassName, placeholder = "Select a row to see its details", testId, validate, validateCreate = validate, ...tableProps })=>/*#__PURE__*/ jsxs(Fragment, {
71
+ children: [
72
+ /*#__PURE__*/ jsxs(EditableTableMain, {
73
+ children: [
74
+ /*#__PURE__*/ jsxs(TableEditorToolbar, {
75
+ children: [
76
+ /*#__PURE__*/ jsx(TableEditorEditButton, {
77
+ "data-testid": `edit-button${testId}`
78
+ }),
79
+ allowCreate ? /*#__PURE__*/ jsx(TableEditorNewButton, {
80
+ "data-testid": `new-button${testId}`
81
+ }) : null
82
+ ]
83
+ }),
84
+ /*#__PURE__*/ jsx(TableEditorTable, {
85
+ "data-testid": `table${testId}`,
86
+ ...tableProps
87
+ })
88
+ ]
89
+ }),
90
+ /*#__PURE__*/ jsxs(EditableTablePanel, {
91
+ className: panelClassName,
92
+ "data-testid": `edit-panel${testId}`,
93
+ children: [
94
+ /*#__PURE__*/ jsx(EditableTablePanelHeader, {
95
+ children: /*#__PURE__*/ jsx(PanelTitle, {
96
+ createTitle: createTitle,
97
+ formTitle: formTitle
98
+ })
99
+ }),
100
+ /*#__PURE__*/ jsxs(SidePanelContent, {
101
+ className: `${classBase}-detail`,
102
+ children: [
103
+ /*#__PURE__*/ jsx(TableEditorPlaceholder, {
104
+ children: placeholder
105
+ }),
106
+ /*#__PURE__*/ jsx(TableEditorForm, {
107
+ "data-testid": `edit-form${testId}`,
108
+ fields: fields,
109
+ validate: validate
110
+ }),
111
+ allowCreate ? /*#__PURE__*/ jsx(TableEditorCreateForm, {
112
+ "data-testid": `create-form${testId}`,
113
+ fields: createFields ?? fields,
114
+ validate: validateCreate
115
+ }) : null
116
+ ]
117
+ })
118
+ ]
119
+ })
120
+ ]
121
+ });
122
+ const Container = ({ children, className, style, testId })=>{
123
+ const targetWindow = useWindow();
124
+ useComponentCssInjection({
125
+ testId: "vuu-editable-table",
126
+ css: EditableTable,
127
+ window: targetWindow
128
+ });
129
+ const { createStrategy, editStrategy, mode, panelOpen } = useTableEditor();
130
+ return /*#__PURE__*/ jsx("div", {
131
+ className: clsx(classBase, className, `${classBase}-${mode}`, {
132
+ [`${classBase}-editing`]: "edit" === mode,
133
+ [`${classBase}-panelOpen`]: panelOpen,
134
+ [`${classBase}-withPanel`]: "form" === editStrategy || "form" === createStrategy
135
+ }),
136
+ "data-testid": `edit-table${testId}`,
137
+ style: style,
138
+ children: children
139
+ });
140
+ };
141
+ const EditableTable_EditableTable = (props)=>{
142
+ const { allowDelete = false, children, className, confirmCancel, copyOption, createStrategy, dataSource, defaultMode, deleteMode, editModel = "session", editSessionApi, editStrategy = "inline", mode, onCancelled, onError, onModeChange, onSaved, panelVisibility, rowDefaults, style, testId = "", ...contentProps } = props;
143
+ const isInlineDirect = "inline" === editStrategy && "direct" === editModel;
144
+ return /*#__PURE__*/ jsx(TableEditorProvider, {
145
+ allowDelete: allowDelete,
146
+ confirmCancel: confirmCancel,
147
+ copyOption: copyOption,
148
+ createStrategy: createStrategy,
149
+ dataSource: dataSource,
150
+ defaultMode: defaultMode ?? (isInlineDirect ? "edit" : "view"),
151
+ deleteMode: deleteMode,
152
+ editModel: editModel,
153
+ editSessionApi: editSessionApi,
154
+ editStrategy: editStrategy,
155
+ mode: mode,
156
+ onCancelled: onCancelled,
157
+ onError: onError,
158
+ onModeChange: onModeChange,
159
+ onSaved: onSaved,
160
+ panelVisibility: panelVisibility,
161
+ rowDefaults: rowDefaults,
162
+ children: /*#__PURE__*/ jsx(Container, {
163
+ className: className,
164
+ style: style,
165
+ testId: testId,
166
+ children: children ?? ("form" === editStrategy ? /*#__PURE__*/ jsx(FormContent, {
167
+ ...contentProps,
168
+ testId: testId
169
+ }) : /*#__PURE__*/ jsx(InlineContent, {
170
+ ...contentProps,
171
+ testId: testId
172
+ }))
173
+ })
174
+ });
175
+ };
176
+ export { EditableTable_EditableTable as EditableTable };
@@ -0,0 +1,61 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { SidePanel, SidePanelHeader, useForkRef } from "@salt-ds/core";
3
+ import clsx from "clsx";
4
+ import { forwardRef } from "react";
5
+ import { DataSourceStats } from "../datasource-stats/DatasourceStats.js";
6
+ import { TableEditorButtons, TableEditorPanelCloseButton } from "../table-editor/index.js";
7
+ import { useTableEditorContext } from "../table-editor/TableEditorContext.js";
8
+ import { TableFooter, TableFooterTray } from "../table-footer/TableFooter.js";
9
+ const EditableTableFooter = ({ children, saveLabel, ...htmlAttributes })=>{
10
+ const { dataSource, editableTable } = useTableEditorContext("EditableTableFooter");
11
+ return /*#__PURE__*/ jsx(TableFooter, {
12
+ ...htmlAttributes,
13
+ children: editableTable?.isEditSessionReady ? /*#__PURE__*/ jsx(TableFooterTray, {
14
+ position: "center",
15
+ children: /*#__PURE__*/ jsx(TableEditorButtons, {
16
+ saveLabel: saveLabel
17
+ })
18
+ }) : children ?? /*#__PURE__*/ jsx(DataSourceStats, {
19
+ dataSource: dataSource
20
+ })
21
+ });
22
+ };
23
+ const classBase = "vuuEditableTable";
24
+ const EditableTableLayout_EditableTableMain = /*#__PURE__*/ forwardRef(function({ className, ...htmlAttributes }, forwardedRef) {
25
+ return /*#__PURE__*/ jsx("div", {
26
+ ...htmlAttributes,
27
+ className: clsx(`${classBase}-main`, className),
28
+ ref: forwardedRef
29
+ });
30
+ });
31
+ const animationWidth = "--saltSidePanel-animation-width";
32
+ const measureAnimationWidth = (el)=>{
33
+ if (el?.classList.contains("saltSidePanel-enterAnimation") && !el.style.getPropertyValue(animationWidth)) {
34
+ const { animation } = el.style;
35
+ el.style.animation = "none";
36
+ const { width } = el.getBoundingClientRect();
37
+ el.style.animation = animation;
38
+ el.style.setProperty(animationWidth, `${width}px`);
39
+ }
40
+ };
41
+ const EditableTableLayout_EditableTablePanel = /*#__PURE__*/ forwardRef(function({ className, ...props }, forwardedRef) {
42
+ const ref = useForkRef(measureAnimationWidth, forwardedRef);
43
+ return /*#__PURE__*/ jsx(SidePanel, {
44
+ ...props,
45
+ className: clsx(`${classBase}-panel`, className),
46
+ position: "right",
47
+ ref: ref
48
+ });
49
+ });
50
+ const EditableTableLayout_EditableTablePanelHeader = /*#__PURE__*/ forwardRef(function({ canClose = true, children, className, ...props }, forwardedRef) {
51
+ return /*#__PURE__*/ jsxs(SidePanelHeader, {
52
+ ...props,
53
+ className: clsx(`${classBase}-panelHeader`, className),
54
+ ref: forwardedRef,
55
+ children: [
56
+ children,
57
+ canClose ? /*#__PURE__*/ jsx(TableEditorPanelCloseButton, {}) : null
58
+ ]
59
+ });
60
+ });
61
+ export { EditableTableFooter, EditableTableLayout_EditableTableMain as EditableTableMain, EditableTableLayout_EditableTablePanel as EditableTablePanel, EditableTableLayout_EditableTablePanelHeader as EditableTablePanelHeader };
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ export * from "./cell-renderers/index.js";
5
5
  export * from "./column-expression-input/index.js";
6
6
  export * from "./column-formatting-settings/index.js";
7
7
  export * from "./inline-add-row/index.js";
8
+ export * from "./table-editor/index.js";
8
9
  export { CalculatedColumnPanel } from "./calculated-column/CalculatedColumnPanel.js";
9
10
  export { ColumnMenu } from "./column-menu/ColumnMenu.js";
10
11
  export { useColumnActions } from "./column-menu/useColumnActions.js";
@@ -22,3 +23,6 @@ export { TabbedTableSettingsAction } from "./tabbed-table-config-panel/TabbedTab
22
23
  export { TableFooter, TableFooterTray } from "./table-footer/TableFooter.js";
23
24
  export { TableProvider, useTableContext } from "./table-provider/TableProvider.js";
24
25
  export { TableSettingsPanel, defaultTableSettingsPermissions } from "./table-settings-panel/TableSettingsPanel.js";
26
+ export { useBulkEditDialog } from "./bulk-edit-dialog/useBulkEditDialog.js";
27
+ export { EditableTable } from "./editable-table/EditableTable.js";
28
+ export { EditableTableFooter, EditableTableMain, EditableTablePanel, EditableTablePanelHeader } from "./editable-table/EditableTableLayout.js";
@@ -0,0 +1,9 @@
1
+ import { createContext, useContext } from "react";
2
+ const TableEditorContext = createContext(void 0);
3
+ const useTableEditorContext = (componentName)=>{
4
+ const context = useContext(TableEditorContext);
5
+ if (void 0 === context) throw Error(`${componentName} must be used within an EditableTable`);
6
+ return context;
7
+ };
8
+ const useTableEditor = ()=>useTableEditorContext("useTableEditor");
9
+ export { TableEditorContext, useTableEditor, useTableEditorContext };
@@ -0,0 +1,86 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Button, SidePanelCloseButton, ToggleButton, ToggleButtonGroup } from "@salt-ds/core";
3
+ import { EditButtons, EditFormButtons, useEditFormContext } from "@vuu-ui/vuu-data-editing";
4
+ import { forwardRef, useCallback } from "react";
5
+ import { useTableEditorContext } from "./TableEditorContext.js";
6
+ const TableEditorButtons = ({ hideCancel, saveLabel })=>{
7
+ const { allowDelete, confirmCancel, editStrategy, editableTable } = useTableEditorContext("TableEditorButtons");
8
+ const form = useEditFormContext();
9
+ if (form || "form" === editStrategy) return form ? /*#__PURE__*/ jsx(EditFormButtons, {
10
+ confirmCancel: confirmCancel,
11
+ hideCancel: hideCancel,
12
+ saveLabel: saveLabel
13
+ }) : null;
14
+ if (editableTable) {
15
+ const { canCancel, canSave, editSession, hasSelection, onCancel, onDelete, onSave } = editableTable;
16
+ return /*#__PURE__*/ jsx(EditButtons, {
17
+ canCancel: canCancel,
18
+ canSave: canSave,
19
+ confirmCancel: confirmCancel,
20
+ editSession: editSession,
21
+ hasSelection: allowDelete ? hasSelection : void 0,
22
+ onCancel: hideCancel ? void 0 : onCancel,
23
+ onDelete: allowDelete ? onDelete : void 0,
24
+ onSave: onSave,
25
+ saveLabel: saveLabel
26
+ });
27
+ }
28
+ return null;
29
+ };
30
+ const TableEditorModeToggle = ({ "aria-label": ariaLabel = "Mode", disabled, testId = "", ...props })=>{
31
+ const { cancel, editStrategy, mode, selectedRow, startEdit } = useTableEditorContext("TableEditorModeToggle");
32
+ const handleChange = useCallback((e)=>{
33
+ if ("edit" === e.currentTarget.value) startEdit();
34
+ else cancel();
35
+ }, [
36
+ cancel,
37
+ startEdit
38
+ ]);
39
+ return /*#__PURE__*/ jsxs(ToggleButtonGroup, {
40
+ ...props,
41
+ "aria-label": ariaLabel,
42
+ disabled: disabled || "create" === mode || "form" === editStrategy && void 0 === selectedRow,
43
+ onChange: handleChange,
44
+ value: "edit" === mode ? "edit" : "view",
45
+ children: [
46
+ /*#__PURE__*/ jsx(ToggleButton, {
47
+ "data-testid": `toggle-view${testId}`,
48
+ value: "view",
49
+ children: "View"
50
+ }),
51
+ /*#__PURE__*/ jsx(ToggleButton, {
52
+ "data-testid": `toggle-edit${testId}`,
53
+ value: "edit",
54
+ children: "Edit"
55
+ })
56
+ ]
57
+ });
58
+ };
59
+ const TableEditorControls_TableEditorEditButton = /*#__PURE__*/ forwardRef(function({ children = "Edit", disabled, ...props }, ref) {
60
+ const { isEditing, selectedRow, startEdit } = useTableEditorContext("TableEditorEditButton");
61
+ return /*#__PURE__*/ jsx(Button, {
62
+ ...props,
63
+ disabled: disabled || isEditing || void 0 === selectedRow,
64
+ onClick: startEdit,
65
+ ref: ref,
66
+ children: children
67
+ });
68
+ });
69
+ const TableEditorControls_TableEditorNewButton = /*#__PURE__*/ forwardRef(function({ children = "New", disabled, ...props }, ref) {
70
+ const { canCreate, startCreate } = useTableEditorContext("TableEditorNewButton");
71
+ return /*#__PURE__*/ jsx(Button, {
72
+ ...props,
73
+ disabled: disabled || !canCreate,
74
+ onClick: startCreate,
75
+ ref: ref,
76
+ children: children
77
+ });
78
+ });
79
+ const TableEditorControls_TableEditorPanelCloseButton = /*#__PURE__*/ forwardRef(function(props, ref) {
80
+ const { canClosePanel } = useTableEditorContext("TableEditorPanelCloseButton");
81
+ return canClosePanel ? /*#__PURE__*/ jsx(SidePanelCloseButton, {
82
+ ...props,
83
+ ref: ref
84
+ }) : null;
85
+ });
86
+ export { TableEditorButtons, TableEditorControls_TableEditorEditButton as TableEditorEditButton, TableEditorControls_TableEditorNewButton as TableEditorNewButton, TableEditorControls_TableEditorPanelCloseButton as TableEditorPanelCloseButton, TableEditorModeToggle };
@@ -0,0 +1,142 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { createElement, useCallback, useLayoutEffect, useMemo, useRef } from "react";
3
+ import { CreateRowForm, EditField, EditForm, getFormFields, useEditFormContext } from "@vuu-ui/vuu-data-editing";
4
+ import { useTableEditorContext } from "./TableEditorContext.js";
5
+ const classBase = "vuuTableEditorForm";
6
+ const useFormFields = (fields, operation, enabled)=>{
7
+ const { columns, dataSource } = useTableEditorContext("TableEditorForm");
8
+ const schema = dataSource.tableSchema;
9
+ return useMemo(()=>enabled ? getFormFields({
10
+ columns,
11
+ fields,
12
+ operation,
13
+ schema
14
+ }) : [], [
15
+ columns,
16
+ enabled,
17
+ fields,
18
+ operation,
19
+ schema
20
+ ]);
21
+ };
22
+ const requiredNames = (fields)=>fields.filter(({ required })=>required).map(({ name })=>name);
23
+ const FormRegistration = ()=>{
24
+ const form = useEditFormContext();
25
+ const { formHandleRef } = useTableEditorContext("TableEditorForm");
26
+ useLayoutEffect(()=>{
27
+ formHandleRef.current = form ? {
28
+ cancel: form.cancel,
29
+ getValues: form.getValues,
30
+ isDirty: form.isDirty
31
+ } : void 0;
32
+ });
33
+ useLayoutEffect(()=>()=>{
34
+ formHandleRef.current = void 0;
35
+ }, [
36
+ formHandleRef
37
+ ]);
38
+ return null;
39
+ };
40
+ const TableEditorForm = ({ children, className, fields, onCancelled, onSaved, showButtons = void 0 === children, validate, ...formProps })=>{
41
+ const { confirmCancel, dataSource, editModel, editStrategy, formHandleRef, formSessionProps, mode, onEditCancelled, onEditSaved, selectedRow } = useTableEditorContext("TableEditorForm");
42
+ const formFields = useFormFields(fields, "update", void 0 === children);
43
+ const requiredColumns = useMemo(()=>requiredNames(formFields), [
44
+ formFields
45
+ ]);
46
+ const submittedValuesRef = useRef(void 0);
47
+ const validateEdit = useCallback((values)=>{
48
+ submittedValuesRef.current = values;
49
+ return validate?.(values);
50
+ }, [
51
+ validate
52
+ ]);
53
+ const handleCancelled = useCallback(()=>{
54
+ onCancelled?.();
55
+ onEditCancelled();
56
+ }, [
57
+ onCancelled,
58
+ onEditCancelled
59
+ ]);
60
+ const handleSaved = useCallback(()=>{
61
+ onSaved?.();
62
+ onEditSaved("direct" === editModel ? formHandleRef.current?.getValues() : submittedValuesRef.current);
63
+ }, [
64
+ editModel,
65
+ formHandleRef,
66
+ onEditSaved,
67
+ onSaved
68
+ ]);
69
+ if ("form" !== editStrategy || "create" === mode || void 0 === selectedRow) return null;
70
+ return /*#__PURE__*/ createElement(EditForm, {
71
+ ...formProps,
72
+ ...formSessionProps,
73
+ className: [
74
+ classBase,
75
+ className
76
+ ].filter(Boolean).join(" "),
77
+ confirmCancel: confirmCancel,
78
+ dataRow: selectedRow,
79
+ dataSource: dataSource,
80
+ editModel: editModel,
81
+ isEditMode: "edit" === mode,
82
+ key: selectedRow.key,
83
+ onCancelled: handleCancelled,
84
+ onSaved: handleSaved,
85
+ requiredColumns: requiredColumns,
86
+ showButtons: showButtons,
87
+ validate: validateEdit,
88
+ children: [
89
+ children ?? formFields.map((field)=>/*#__PURE__*/ jsx(EditField, {
90
+ column: field
91
+ }, field.name)),
92
+ /*#__PURE__*/ jsx(FormRegistration, {})
93
+ ]
94
+ });
95
+ };
96
+ const TableEditorCreateForm = ({ children, className, fields, onCancelled, onSaved, ...formProps })=>{
97
+ const { confirmCancel, createKey, createStrategy, dataSource, editModel, editSession, editStrategy, formSessionProps, mode, onCreateDone } = useTableEditorContext("TableEditorCreateForm");
98
+ const generatedFields = useFormFields(fields, "insert", void 0 !== fields || void 0 === children);
99
+ const formFields = useMemo(()=>fields ? generatedFields : generatedFields.map((field)=>field.required ? field : {
100
+ ...field,
101
+ required: false
102
+ }), [
103
+ fields,
104
+ generatedFields
105
+ ]);
106
+ const sharedEditSession = "inline" === editStrategy && "session" === editModel ? editSession : void 0;
107
+ const handleCancelled = useCallback(()=>{
108
+ onCancelled?.();
109
+ onCreateDone(false);
110
+ }, [
111
+ onCancelled,
112
+ onCreateDone
113
+ ]);
114
+ const handleSaved = useCallback(()=>{
115
+ onSaved?.();
116
+ onCreateDone(true);
117
+ }, [
118
+ onCreateDone,
119
+ onSaved
120
+ ]);
121
+ if ("form" !== createStrategy || "create" !== mode) return null;
122
+ return /*#__PURE__*/ createElement(CreateRowForm, {
123
+ ...formProps,
124
+ ...formSessionProps,
125
+ className: [
126
+ classBase,
127
+ className
128
+ ].filter(Boolean).join(" "),
129
+ confirmCancel: confirmCancel,
130
+ dataSource: dataSource,
131
+ editSession: sharedEditSession,
132
+ fields: formFields,
133
+ key: createKey,
134
+ onCancelled: handleCancelled,
135
+ onSaved: handleSaved,
136
+ children: [
137
+ children,
138
+ /*#__PURE__*/ jsx(FormRegistration, {})
139
+ ]
140
+ });
141
+ };
142
+ export { TableEditorCreateForm, TableEditorForm };