@vuu-ui/vuu-data-react 0.11.2 → 0.12.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.
Files changed (48) hide show
  1. package/cjs/data-editing/EditForm.js +3 -10
  2. package/cjs/data-editing/EditForm.js.map +1 -1
  3. package/cjs/data-editing/edit-validation-rules.js.map +1 -1
  4. package/cjs/data-editing/useEditForm.js +1 -1
  5. package/cjs/data-editing/useEditForm.js.map +1 -1
  6. package/cjs/datasource-provider/RestDataSourceProvider.js +1 -1
  7. package/cjs/datasource-provider/RestDataSourceProvider.js.map +1 -1
  8. package/cjs/datasource-provider/VuuDataSourceProvider.js +1 -1
  9. package/cjs/datasource-provider/VuuDataSourceProvider.js.map +1 -1
  10. package/cjs/hooks/useLookupValues.js +1 -1
  11. package/cjs/hooks/useLookupValues.js.map +1 -1
  12. package/cjs/hooks/useSessionDataSource.js +3 -3
  13. package/cjs/hooks/useSessionDataSource.js.map +1 -1
  14. package/cjs/hooks/useTypeaheadSuggestions.js +1 -1
  15. package/cjs/hooks/useTypeaheadSuggestions.js.map +1 -1
  16. package/cjs/hooks/useVuuMenuActions.js +166 -17
  17. package/cjs/hooks/useVuuMenuActions.js.map +1 -1
  18. package/cjs/hooks/useVuuTables.js +1 -1
  19. package/cjs/hooks/useVuuTables.js.map +1 -1
  20. package/cjs/index.js +2 -0
  21. package/cjs/index.js.map +1 -1
  22. package/cjs/session-editing-form/SessionEditingForm.js +1 -1
  23. package/cjs/session-editing-form/SessionEditingForm.js.map +1 -1
  24. package/esm/data-editing/EditForm.js +3 -10
  25. package/esm/data-editing/EditForm.js.map +1 -1
  26. package/esm/data-editing/edit-validation-rules.js.map +1 -1
  27. package/esm/data-editing/useEditForm.js +2 -2
  28. package/esm/data-editing/useEditForm.js.map +1 -1
  29. package/esm/datasource-provider/RestDataSourceProvider.js +2 -2
  30. package/esm/datasource-provider/RestDataSourceProvider.js.map +1 -1
  31. package/esm/datasource-provider/VuuDataSourceProvider.js +2 -2
  32. package/esm/datasource-provider/VuuDataSourceProvider.js.map +1 -1
  33. package/esm/hooks/useLookupValues.js +2 -2
  34. package/esm/hooks/useLookupValues.js.map +1 -1
  35. package/esm/hooks/useSessionDataSource.js +3 -3
  36. package/esm/hooks/useSessionDataSource.js.map +1 -1
  37. package/esm/hooks/useTypeaheadSuggestions.js +2 -2
  38. package/esm/hooks/useTypeaheadSuggestions.js.map +1 -1
  39. package/esm/hooks/useVuuMenuActions.js +163 -16
  40. package/esm/hooks/useVuuMenuActions.js.map +1 -1
  41. package/esm/hooks/useVuuTables.js +2 -2
  42. package/esm/hooks/useVuuTables.js.map +1 -1
  43. package/esm/index.js +1 -1
  44. package/esm/session-editing-form/SessionEditingForm.js +2 -2
  45. package/esm/session-editing-form/SessionEditingForm.js.map +1 -1
  46. package/package.json +14 -13
  47. package/types/hooks/useSessionDataSource.d.ts +1 -1
  48. package/types/hooks/useVuuMenuActions.d.ts +24 -8
@@ -1,4 +1,4 @@
1
- import { useDataSource } from '@vuu-ui/vuu-utils';
1
+ import { useData } from '@vuu-ui/vuu-utils';
2
2
  import { useCallback } from 'react';
3
3
 
4
4
  const getTypeaheadParams = (table, column, text = "", selectedValues = []) => {
@@ -8,7 +8,7 @@ const getTypeaheadParams = (table, column, text = "", selectedValues = []) => {
8
8
  return [table, column];
9
9
  };
10
10
  const useTypeaheadSuggestions = () => {
11
- const { getServerAPI } = useDataSource();
11
+ const { getServerAPI } = useData();
12
12
  return useCallback(
13
13
  async (params) => {
14
14
  const rpcMessage = params.length === 2 ? {
@@ -1 +1 @@
1
- {"version":3,"file":"useTypeaheadSuggestions.js","sources":["../../src/hooks/useTypeaheadSuggestions.ts"],"sourcesContent":["import { SuggestionFetcher, TableSchemaTable } from \"@vuu-ui/vuu-data-types\";\nimport {\n VuuRpcServiceRequest,\n TypeaheadParams,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { useDataSource } from \"@vuu-ui/vuu-utils\";\nimport { useCallback } from \"react\";\n\nexport const getTypeaheadParams = (\n table: TableSchemaTable,\n column: string,\n text = \"\",\n selectedValues: string[] = [],\n): TypeaheadParams => {\n if (text !== \"\" && !selectedValues.includes(text.toLowerCase())) {\n return [table, column, text];\n }\n return [table, column];\n};\n\nexport const useTypeaheadSuggestions = () => {\n const { getServerAPI } = useDataSource();\n return useCallback<SuggestionFetcher>(\n async (params: TypeaheadParams) => {\n const rpcMessage: VuuRpcServiceRequest =\n params.length === 2\n ? {\n type: \"RPC_CALL\",\n service: \"TypeAheadRpcHandler\",\n method: \"getUniqueFieldValues\",\n params,\n }\n : {\n type: \"RPC_CALL\",\n service: \"TypeAheadRpcHandler\",\n method: \"getUniqueFieldValuesStartingWith\",\n params,\n };\n\n try {\n const serverAPI = await getServerAPI();\n // We don't just return serverAPI.rpcCall . In the case of an\n // error we will be returning the rejected promise, bypassing\n // the catch block below.\n const response = await serverAPI.rpcCall<string[]>(rpcMessage);\n return response;\n } catch (err) {\n return false;\n }\n },\n [getServerAPI],\n );\n};\n"],"names":[],"mappings":";;;AAQa,MAAA,kBAAA,GAAqB,CAChC,KACA,EAAA,MAAA,EACA,OAAO,EACP,EAAA,cAAA,GAA2B,EACP,KAAA;AACpB,EAAI,IAAA,IAAA,KAAS,MAAM,CAAC,cAAA,CAAe,SAAS,IAAK,CAAA,WAAA,EAAa,CAAG,EAAA;AAC/D,IAAO,OAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,IAAI,CAAA;AAAA;AAE7B,EAAO,OAAA,CAAC,OAAO,MAAM,CAAA;AACvB;AAEO,MAAM,0BAA0B,MAAM;AAC3C,EAAM,MAAA,EAAE,YAAa,EAAA,GAAI,aAAc,EAAA;AACvC,EAAO,OAAA,WAAA;AAAA,IACL,OAAO,MAA4B,KAAA;AACjC,MAAM,MAAA,UAAA,GACJ,MAAO,CAAA,MAAA,KAAW,CACd,GAAA;AAAA,QACE,IAAM,EAAA,UAAA;AAAA,QACN,OAAS,EAAA,qBAAA;AAAA,QACT,MAAQ,EAAA,sBAAA;AAAA,QACR;AAAA,OAEF,GAAA;AAAA,QACE,IAAM,EAAA,UAAA;AAAA,QACN,OAAS,EAAA,qBAAA;AAAA,QACT,MAAQ,EAAA,kCAAA;AAAA,QACR;AAAA,OACF;AAEN,MAAI,IAAA;AACF,QAAM,MAAA,SAAA,GAAY,MAAM,YAAa,EAAA;AAIrC,QAAA,MAAM,QAAW,GAAA,MAAM,SAAU,CAAA,OAAA,CAAkB,UAAU,CAAA;AAC7D,QAAO,OAAA,QAAA;AAAA,eACA,GAAK,EAAA;AACZ,QAAO,OAAA,KAAA;AAAA;AACT,KACF;AAAA,IACA,CAAC,YAAY;AAAA,GACf;AACF;;;;"}
1
+ {"version":3,"file":"useTypeaheadSuggestions.js","sources":["../../src/hooks/useTypeaheadSuggestions.ts"],"sourcesContent":["import { SuggestionFetcher, TableSchemaTable } from \"@vuu-ui/vuu-data-types\";\nimport {\n VuuRpcServiceRequest,\n TypeaheadParams,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { useData } from \"@vuu-ui/vuu-utils\";\nimport { useCallback } from \"react\";\n\nexport const getTypeaheadParams = (\n table: TableSchemaTable,\n column: string,\n text = \"\",\n selectedValues: string[] = [],\n): TypeaheadParams => {\n if (text !== \"\" && !selectedValues.includes(text.toLowerCase())) {\n return [table, column, text];\n }\n return [table, column];\n};\n\nexport const useTypeaheadSuggestions = () => {\n const { getServerAPI } = useData();\n return useCallback<SuggestionFetcher>(\n async (params: TypeaheadParams) => {\n const rpcMessage: VuuRpcServiceRequest =\n params.length === 2\n ? {\n type: \"RPC_CALL\",\n service: \"TypeAheadRpcHandler\",\n method: \"getUniqueFieldValues\",\n params,\n }\n : {\n type: \"RPC_CALL\",\n service: \"TypeAheadRpcHandler\",\n method: \"getUniqueFieldValuesStartingWith\",\n params,\n };\n\n try {\n const serverAPI = await getServerAPI();\n // We don't just return serverAPI.rpcCall . In the case of an\n // error we will be returning the rejected promise, bypassing\n // the catch block below.\n const response = await serverAPI.rpcCall<string[]>(rpcMessage);\n return response;\n } catch (err) {\n return false;\n }\n },\n [getServerAPI],\n );\n};\n"],"names":[],"mappings":";;;AAQa,MAAA,kBAAA,GAAqB,CAChC,KACA,EAAA,MAAA,EACA,OAAO,EACP,EAAA,cAAA,GAA2B,EACP,KAAA;AACpB,EAAI,IAAA,IAAA,KAAS,MAAM,CAAC,cAAA,CAAe,SAAS,IAAK,CAAA,WAAA,EAAa,CAAG,EAAA;AAC/D,IAAO,OAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,IAAI,CAAA;AAAA;AAE7B,EAAO,OAAA,CAAC,OAAO,MAAM,CAAA;AACvB;AAEO,MAAM,0BAA0B,MAAM;AAC3C,EAAM,MAAA,EAAE,YAAa,EAAA,GAAI,OAAQ,EAAA;AACjC,EAAO,OAAA,WAAA;AAAA,IACL,OAAO,MAA4B,KAAA;AACjC,MAAM,MAAA,UAAA,GACJ,MAAO,CAAA,MAAA,KAAW,CACd,GAAA;AAAA,QACE,IAAM,EAAA,UAAA;AAAA,QACN,OAAS,EAAA,qBAAA;AAAA,QACT,MAAQ,EAAA,sBAAA;AAAA,QACR;AAAA,OAEF,GAAA;AAAA,QACE,IAAM,EAAA,UAAA;AAAA,QACN,OAAS,EAAA,qBAAA;AAAA,QACT,MAAQ,EAAA,kCAAA;AAAA,QACR;AAAA,OACF;AAEN,MAAI,IAAA;AACF,QAAM,MAAA,SAAA,GAAY,MAAM,YAAa,EAAA;AAIrC,QAAA,MAAM,QAAW,GAAA,MAAM,SAAU,CAAA,OAAA,CAAkB,UAAU,CAAA;AAC7D,QAAO,OAAA,QAAA;AAAA,eACA,GAAK,EAAA;AACZ,QAAO,OAAA,KAAA;AAAA;AACT,KACF;AAAA,IACA,CAAC,YAAY;AAAA,GACf;AACF;;;;"}
@@ -1,11 +1,129 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { useDialogContext, useNotifications } from '@vuu-ui/vuu-popups';
3
- import { BulkEditDialog, BulkEditPanel } from '@vuu-ui/vuu-table';
4
- import { useDataSource, isTableLocation, buildMenuDescriptorFromVuuMenu, isRoot, isGroupMenuItemDescriptor, toColumnName, getMenuRpcRequest, isActionMessage, hasShowNotificationAction, isOpenBulkEditResponse, isSessionTableActionMessage, viewportRpcRequest } from '@vuu-ui/vuu-utils';
5
2
  import { Button } from '@salt-ds/core';
3
+ import { isGroupMenuItemDescriptor } from '@vuu-ui/vuu-context-menu';
4
+ import { getFilterPredicate } from '@vuu-ui/vuu-filter-parser';
5
+ import { useDialogContext, useNotifications } from '@vuu-ui/vuu-popups';
6
+ import { isTableLocation, BulkEditDialog, BulkEditPanel } from '@vuu-ui/vuu-table';
7
+ import { useData, toColumnName, isActionMessage, hasShowNotificationAction, isOpenBulkEditResponse, isSessionTableActionMessage, viewportRpcRequest, dataSourceRowToDataRowDto, metadataKeys } from '@vuu-ui/vuu-utils';
6
8
  import { useCallback } from 'react';
7
9
  import { SessionEditingForm } from '../session-editing-form/SessionEditingForm.js';
8
10
 
11
+ const isRoot = (menu) => menu.name === "ROOT";
12
+ const isCellMenu = (options) => options.context === "cell";
13
+ const isRowMenu = (options) => options.context === "row";
14
+ const isSelectionMenu = (options) => options.context === "selected-rows";
15
+ const getColumnsFromOptions = (options) => {
16
+ if (options && typeof options === "object" && "columns" in options) {
17
+ return options.columns;
18
+ }
19
+ };
20
+ const isVuuMenuItem = (menu) => "rpcName" in menu;
21
+ const isGroupMenuItem = (menu) => "menus" in menu;
22
+ const hasFilter = ({ filter }) => typeof filter === "string" && filter.length > 0;
23
+ const { KEY } = metadataKeys;
24
+ const getMenuItemOptions = (menu, options) => {
25
+ switch (menu.context) {
26
+ case "cell":
27
+ return {
28
+ ...menu,
29
+ field: options.column.name,
30
+ rowKey: options.row[KEY],
31
+ value: options.row[options.columnMap[options.column.name]]
32
+ };
33
+ case "row":
34
+ return {
35
+ ...menu,
36
+ columns: options.columns,
37
+ row: dataSourceRowToDataRowDto(options.row, options.columnMap),
38
+ rowKey: options.row[KEY]
39
+ };
40
+ case "selected-rows":
41
+ return {
42
+ ...menu,
43
+ columns: options.columns
44
+ };
45
+ default:
46
+ return menu;
47
+ }
48
+ };
49
+ const vuuContextCompatibleWithTableLocation = (uiLocation, vuuContext, selectedRowCount = 0) => {
50
+ switch (uiLocation) {
51
+ case "grid":
52
+ if (vuuContext === "selected-rows") {
53
+ return selectedRowCount > 0;
54
+ } else {
55
+ return true;
56
+ }
57
+ case "header":
58
+ return vuuContext === "grid";
59
+ default:
60
+ return false;
61
+ }
62
+ };
63
+ const gridRowMeetsFilterCriteria = (context, row, selectedRows, filter, columnMap) => {
64
+ if (context === "cell" || context === "row") {
65
+ const filterPredicate = getFilterPredicate(columnMap, filter);
66
+ return filterPredicate(row);
67
+ } else if (context === "selected-rows") {
68
+ if (selectedRows.length === 0) {
69
+ return false;
70
+ } else {
71
+ const filterPredicate = getFilterPredicate(columnMap, filter);
72
+ return selectedRows.every(filterPredicate);
73
+ }
74
+ }
75
+ return true;
76
+ };
77
+ const menuShouldBeRenderedInThisContext = (menuItem, tableLocation, options) => {
78
+ if (isGroupMenuItem(menuItem)) {
79
+ return menuItem.menus.some(
80
+ (childMenu) => menuShouldBeRenderedInThisContext(childMenu, tableLocation, options)
81
+ );
82
+ }
83
+ if (!vuuContextCompatibleWithTableLocation(
84
+ tableLocation,
85
+ menuItem.context,
86
+ options.selectedRows?.length
87
+ )) {
88
+ return false;
89
+ }
90
+ if (tableLocation === "grid" && hasFilter(menuItem)) {
91
+ return gridRowMeetsFilterCriteria(
92
+ menuItem.context,
93
+ options.row,
94
+ options.selectedRows,
95
+ menuItem.filter,
96
+ options.columnMap
97
+ );
98
+ }
99
+ if (isCellMenu(menuItem) && menuItem.field !== "*") {
100
+ return menuItem.field === options.column.name;
101
+ }
102
+ return true;
103
+ };
104
+ const buildMenuDescriptorFromVuuMenu = (menu, tableLocation, options) => {
105
+ if (menuShouldBeRenderedInThisContext(menu, tableLocation, options)) {
106
+ if (isVuuMenuItem(menu)) {
107
+ return {
108
+ label: menu.name,
109
+ id: "MENU_RPC_CALL",
110
+ options: getMenuItemOptions(menu, options)
111
+ };
112
+ } else {
113
+ const children = menu.menus.map(
114
+ (childMenu) => buildMenuDescriptorFromVuuMenu(childMenu, tableLocation, options)
115
+ ).filter(
116
+ (childMenu) => childMenu !== void 0
117
+ );
118
+ if (children.length > 0) {
119
+ return {
120
+ label: menu.name,
121
+ children
122
+ };
123
+ }
124
+ }
125
+ }
126
+ };
9
127
  const keyFirst = (c1, c2) => c1.isKeyField ? -1 : c2.isKeyField ? 1 : 0;
10
128
  const defaultFormConfig = {
11
129
  fields: [],
@@ -41,8 +159,8 @@ const useVuuMenuActions = ({
41
159
  dataSource,
42
160
  onRpcResponse
43
161
  }) => {
44
- const { VuuDataSource } = useDataSource();
45
- const buildViewserverMenuOptions = useCallback(
162
+ const { VuuDataSource } = useData();
163
+ const menuBuilder = useCallback(
46
164
  (location, options) => {
47
165
  const descriptors = [];
48
166
  if (dataSource) {
@@ -54,7 +172,7 @@ const useVuuMenuActions = ({
54
172
  const label = linkLabel ? linkLabel : link.toTable;
55
173
  descriptors.push({
56
174
  label: `Link to ${label}`,
57
- action: "link-table",
175
+ id: "link-table",
58
176
  options: linkDescriptor
59
177
  });
60
178
  });
@@ -146,11 +264,40 @@ const useVuuMenuActions = ({
146
264
  },
147
265
  [closeDialog, showDialog]
148
266
  );
149
- const handleMenuAction = useCallback(
150
- ({ menuId, options }) => {
151
- if (clientSideMenuActionHandler?.(menuId, options)) {
267
+ const getMenuRpcRequest = (options) => {
268
+ const { rpcName } = options;
269
+ if (isCellMenu(options)) {
270
+ return {
271
+ field: options.field,
272
+ rowKey: options.rowKey,
273
+ rpcName,
274
+ value: options.value,
275
+ type: "VIEW_PORT_MENU_CELL_RPC"
276
+ };
277
+ } else if (isRowMenu(options)) {
278
+ return {
279
+ rowKey: options.rowKey,
280
+ row: options.row,
281
+ rpcName,
282
+ type: "VIEW_PORT_MENU_ROW_RPC"
283
+ };
284
+ } else if (isSelectionMenu(options)) {
285
+ return {
286
+ rpcName,
287
+ type: "VIEW_PORT_MENUS_SELECT_RPC"
288
+ };
289
+ } else {
290
+ return {
291
+ rpcName,
292
+ type: "VIEW_PORT_MENU_TABLE_RPC"
293
+ };
294
+ }
295
+ };
296
+ const menuActionHandler = useCallback(
297
+ (menuItemId, options) => {
298
+ if (clientSideMenuActionHandler?.(menuItemId, options)) {
152
299
  return true;
153
- } else if (menuId === "MENU_RPC_CALL") {
300
+ } else if (menuItemId === "MENU_RPC_CALL") {
154
301
  const rpcRequest = getMenuRpcRequest(options);
155
302
  dataSource?.menuRpcCall(rpcRequest).then((rpcResponse) => {
156
303
  if (rpcResponse) {
@@ -171,7 +318,7 @@ const useVuuMenuActions = ({
171
318
  showBulkEditDialog(
172
319
  dataSource,
173
320
  rpcResponse.action.table,
174
- options.columns
321
+ getColumnsFromOptions(options)
175
322
  );
176
323
  } else if (isSessionTableActionMessage(rpcResponse)) {
177
324
  showSessionEditingForm(dataSource, rpcResponse.action);
@@ -180,14 +327,14 @@ const useVuuMenuActions = ({
180
327
  }
181
328
  });
182
329
  return true;
183
- } else if (menuId === "link-table") {
330
+ } else if (menuItemId === "link-table") {
184
331
  if (dataSource) {
185
332
  dataSource.visualLink = options;
186
333
  }
187
334
  return true;
188
335
  } else {
189
336
  console.log(
190
- `useViewServer handleMenuAction, can't handle action type ${menuId}`
337
+ `useViewServer handleMenuAction, can't handle action type ${menuItemId}`
191
338
  );
192
339
  }
193
340
  return false;
@@ -202,10 +349,10 @@ const useVuuMenuActions = ({
202
349
  ]
203
350
  );
204
351
  return {
205
- buildViewserverMenuOptions,
206
- handleMenuAction
352
+ menuBuilder,
353
+ menuActionHandler
207
354
  };
208
355
  };
209
356
 
210
- export { useVuuMenuActions };
357
+ export { isRowMenu, isSelectionMenu, useVuuMenuActions };
211
358
  //# sourceMappingURL=useVuuMenuActions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useVuuMenuActions.js","sources":["../../src/hooks/useVuuMenuActions.tsx"],"sourcesContent":["import {\n ContextMenuItemDescriptor,\n DataSource,\n DataSourceVisualLinkCreatedMessage,\n MenuActionHandler,\n MenuBuilder,\n RpcResponseHandler,\n TableSchema,\n} from \"@vuu-ui/vuu-data-types\";\nimport {\n useDialogContext,\n useNotifications,\n type MenuActionClosePopup,\n} from \"@vuu-ui/vuu-popups\";\nimport type {\n LinkDescriptorWithLabel,\n OpenDialogAction,\n VuuMenu,\n VuuMenuItem,\n VuuRpcResponse,\n VuuTable,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport { BulkEditPanel, BulkEditDialog } from \"@vuu-ui/vuu-table\";\nimport { ColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport {\n VuuServerMenuOptions,\n buildMenuDescriptorFromVuuMenu,\n getMenuRpcRequest,\n hasShowNotificationAction,\n isActionMessage,\n isGroupMenuItemDescriptor,\n isOpenBulkEditResponse,\n isRoot,\n isSessionTableActionMessage,\n isTableLocation,\n toColumnName,\n useDataSource,\n viewportRpcRequest,\n} from \"@vuu-ui/vuu-utils\";\nimport { Button } from \"@salt-ds/core\";\nimport { useCallback } from \"react\";\nimport {\n FormConfig,\n FormFieldDescriptor,\n SessionEditingForm,\n} from \"../session-editing-form\";\n\nexport type VuuMenuActionHandler = (type: string, options: unknown) => boolean;\n\nexport interface ViewServerHookResult {\n buildViewserverMenuOptions: MenuBuilder;\n handleMenuAction: MenuActionHandler;\n}\n\nexport interface MenuActionConfig {\n vuuMenu?: VuuMenu;\n visualLink?: DataSourceVisualLinkCreatedMessage;\n visualLinks?: LinkDescriptorWithLabel[];\n}\n\nexport interface VuuMenuActionHookProps {\n /**\n * By default, vuuMenuActions will be handled automatically. When activated, a\n * message will be sent to server and response will be handled here too.\n * This prop allows client to provide a custom handler for a menu Item. This will\n * take priority and if handler returns true, no further processing for the menu\n * item will be handled by Vuu. This can also be used to prevent an item from being\n * actioned, even when no custom handling is intended. If the handler returns false,\n * Vuu will process the menuItem.\n */\n clientSideMenuActionHandler?: VuuMenuActionHandler;\n dataSource?: DataSource;\n menuActionConfig?: MenuActionConfig;\n onRpcResponse?: RpcResponseHandler;\n}\n\nconst keyFirst = (c1: FormFieldDescriptor, c2: FormFieldDescriptor) =>\n c1.isKeyField ? -1 : c2.isKeyField ? 1 : 0;\n\nconst defaultFormConfig = {\n fields: [],\n key: \"\",\n title: \"\",\n};\n\nconst configFromSchema = (schema?: TableSchema): FormConfig | undefined => {\n if (schema) {\n const { columns, key } = schema;\n return {\n key,\n title: `Parameters for command`,\n fields: columns\n .map((col) => ({\n description: col.name,\n label: col.name,\n name: col.name,\n type: col.serverDataType,\n isKeyField: col.name === key,\n }))\n .sort(keyFirst),\n };\n }\n};\n\nconst getFormConfig = (\n action: OpenDialogAction & { tableSchema: TableSchema },\n) => {\n const { tableSchema: schema } = action;\n const config = configFromSchema(schema) ?? defaultFormConfig;\n\n return {\n config,\n schema,\n };\n};\n\nexport const useVuuMenuActions = ({\n clientSideMenuActionHandler,\n dataSource,\n onRpcResponse,\n}: VuuMenuActionHookProps): ViewServerHookResult => {\n const { VuuDataSource } = useDataSource();\n const buildViewserverMenuOptions: MenuBuilder = useCallback(\n (location, options) => {\n const descriptors: ContextMenuItemDescriptor[] = [];\n if (dataSource) {\n const { links, menu } = dataSource;\n const { visualLink } = dataSource;\n\n if (location === \"grid\" && links && !visualLink) {\n links.forEach((linkDescriptor: LinkDescriptorWithLabel) => {\n const { link, label: linkLabel } = linkDescriptor;\n const label = linkLabel ? linkLabel : link.toTable;\n descriptors.push({\n label: `Link to ${label}`,\n action: \"link-table\",\n options: linkDescriptor,\n });\n });\n }\n\n if (menu && isTableLocation(location)) {\n const menuDescriptor = buildMenuDescriptorFromVuuMenu(\n menu,\n location,\n options as VuuServerMenuOptions,\n );\n if (isRoot(menu) && isGroupMenuItemDescriptor(menuDescriptor)) {\n descriptors.push(...menuDescriptor.children);\n } else if (menuDescriptor) {\n descriptors.push(menuDescriptor);\n }\n }\n } else {\n throw Error(\"useVuuMenuActions no dataSource provided\");\n }\n\n return descriptors;\n },\n [dataSource],\n );\n\n const { showDialog, closeDialog } = useDialogContext();\n const showNotification = useNotifications();\n\n const showBulkEditDialog = useCallback(\n (ds: DataSource, table: VuuTable, columns?: ColumnDescriptor[]) => {\n const sessionDs = new VuuDataSource({\n columns: columns?.map(toColumnName),\n table,\n viewport: table.table,\n });\n\n const handleClose = () => {\n sessionDs.unsubscribe();\n closeDialog();\n };\n\n showDialog(\n <BulkEditDialog\n columns={columns}\n sessionDs={sessionDs}\n parentDs={ds}\n closeDialog={handleClose}\n />,\n \"Bulk Amend\",\n );\n\n return true;\n },\n [VuuDataSource, closeDialog, showDialog],\n );\n\n const showSessionEditingForm = useCallback(\n (\n ds: DataSource,\n action: OpenDialogAction & { tableSchema: TableSchema },\n ) => {\n const { tableSchema } = action;\n if (tableSchema) {\n const formConfig = getFormConfig(action);\n showDialog(\n <SessionEditingForm {...formConfig} onClose={closeDialog} />,\n \"Set Parameters\",\n );\n }\n\n const sessionDs = ds.createSessionDataSource?.(action.table);\n const handleSubmit = () => {\n sessionDs?.rpcCall?.(viewportRpcRequest(\"VP_BULK_EDIT_SUBMIT_RPC\"));\n closeDialog();\n };\n\n const handleChange = (isValid: boolean) => {\n console.log(\"placeholder: \", isValid);\n };\n\n if (sessionDs) {\n showDialog(\n <BulkEditPanel\n dataSource={sessionDs}\n onSubmit={handleSubmit}\n parentDs={ds}\n onValidationStatusChange={handleChange}\n />,\n \"Multi Row Edit\",\n [\n <Button key=\"cancel\" onClick={closeDialog}>\n Cancel\n </Button>,\n <Button key=\"submit\" onClick={handleSubmit}>\n Save\n </Button>,\n ],\n );\n }\n },\n [closeDialog, showDialog],\n );\n\n const handleMenuAction = useCallback(\n ({ menuId, options }: MenuActionClosePopup) => {\n if (clientSideMenuActionHandler?.(menuId, options)) {\n return true;\n } else if (menuId === \"MENU_RPC_CALL\") {\n const rpcRequest = getMenuRpcRequest(options as unknown as VuuMenuItem);\n\n dataSource\n ?.menuRpcCall(rpcRequest)\n .then((rpcResponse: Omit<VuuRpcResponse, \"requestId\">) => {\n if (rpcResponse) {\n if (onRpcResponse?.(rpcResponse) === true) {\n return true;\n }\n if (isActionMessage(rpcResponse)) {\n if (hasShowNotificationAction(rpcResponse)) {\n const {\n action: { message, title = \"Success\" },\n } = rpcResponse;\n showNotification({\n type: \"success\",\n body: message,\n header: title,\n });\n } else if (isOpenBulkEditResponse(rpcResponse)) {\n showBulkEditDialog(\n dataSource,\n rpcResponse.action.table,\n options.columns,\n );\n } else if (isSessionTableActionMessage(rpcResponse)) {\n showSessionEditingForm(dataSource, rpcResponse.action);\n }\n }\n }\n });\n return true;\n } else if (menuId === \"link-table\") {\n if (dataSource) {\n dataSource.visualLink = options as LinkDescriptorWithLabel;\n }\n return true;\n } else {\n console.log(\n `useViewServer handleMenuAction, can't handle action type ${menuId}`,\n );\n }\n\n return false;\n },\n [\n clientSideMenuActionHandler,\n dataSource,\n onRpcResponse,\n showBulkEditDialog,\n showNotification,\n showSessionEditingForm,\n ],\n );\n\n return {\n buildViewserverMenuOptions,\n handleMenuAction,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useVuuMenuActions.js","sources":["../../src/hooks/useVuuMenuActions.tsx"],"sourcesContent":["import { Button } from \"@salt-ds/core\";\nimport {\n type ContextMenuItemDescriptor,\n isGroupMenuItemDescriptor,\n type MenuActionHandler,\n type MenuBuilder,\n} from \"@vuu-ui/vuu-context-menu\";\nimport {\n DataSource,\n DataSourceRow,\n DataSourceVisualLinkCreatedMessage,\n RpcResponseHandler,\n TableSchema,\n} from \"@vuu-ui/vuu-data-types\";\nimport { getFilterPredicate } from \"@vuu-ui/vuu-filter-parser\";\nimport { useDialogContext, useNotifications } from \"@vuu-ui/vuu-popups\";\nimport type {\n ClientToServerMenuCellRPC,\n ClientToServerMenuRowRPC,\n LinkDescriptorWithLabel,\n OpenDialogAction,\n VuuDataRowDto,\n VuuMenu,\n VuuMenuContext,\n VuuMenuItem,\n VuuRowDataItemType,\n VuuRpcMenuRequest,\n VuuRpcResponse,\n VuuTable,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport {\n BulkEditDialog,\n BulkEditPanel,\n isTableLocation,\n TableContextMenuOptions,\n TableMenuLocation,\n} from \"@vuu-ui/vuu-table\";\nimport type { ColumnDescriptor } from \"@vuu-ui/vuu-table-types\";\nimport {\n ColumnMap,\n dataSourceRowToDataRowDto,\n hasShowNotificationAction,\n isActionMessage,\n isOpenBulkEditResponse,\n isSessionTableActionMessage,\n metadataKeys,\n toColumnName,\n useData,\n viewportRpcRequest,\n} from \"@vuu-ui/vuu-utils\";\nimport { useCallback } from \"react\";\nimport {\n FormConfig,\n FormFieldDescriptor,\n SessionEditingForm,\n} from \"../session-editing-form\";\n\nexport interface VuuMenuActionHookResult {\n menuBuilder: MenuBuilder<TableMenuLocation, TableContextMenuOptions>;\n menuActionHandler: MenuActionHandler;\n}\n\nexport interface MenuActionConfig {\n vuuMenu?: VuuMenu;\n visualLink?: DataSourceVisualLinkCreatedMessage;\n visualLinks?: LinkDescriptorWithLabel[];\n}\n\nexport interface VuuMenuActionHookProps {\n /**\n * By default, vuuMenuActions will be handled automatically. When activated, a\n * message will be sent to server and response will be handled here too.\n * This prop allows client to provide a custom handler for a menu Item. This will\n * take priority and if handler returns true, no further processing for the menu\n * item will be handled by Vuu. This can also be used to prevent an item from being\n * actioned, even when no custom handling is intended. If the handler returns false,\n * Vuu will process the menuItem.\n */\n clientSideMenuActionHandler?: MenuActionHandler;\n dataSource?: DataSource;\n menuActionConfig?: MenuActionConfig;\n onRpcResponse?: RpcResponseHandler;\n}\n\nexport interface VuuCellContextMenuItemOptions extends VuuMenuItem {\n rowKey: string;\n field: string;\n value: VuuRowDataItemType;\n}\nexport interface VuuRowContextMenuItemOptions extends VuuMenuItem {\n rowKey: string;\n row: VuuDataRowDto;\n}\nexport interface VuuSelectedRowsContextMenuItemOptions extends VuuMenuItem {\n columns: ColumnDescriptor[];\n}\n\nconst isRoot = (menu: VuuMenu) => menu.name === \"ROOT\";\n\nconst isCellMenu = (\n options: VuuMenuItem,\n): options is VuuCellContextMenuItemOptions => options.context === \"cell\";\n\nexport const isRowMenu = (\n options: VuuMenuItem,\n): options is VuuRowContextMenuItemOptions => options.context === \"row\";\n\nexport const isSelectionMenu = (\n options: VuuMenuItem,\n): options is VuuSelectedRowsContextMenuItemOptions =>\n options.context === \"selected-rows\";\n\nconst getColumnsFromOptions = (options: unknown) => {\n if (options && typeof options === \"object\" && \"columns\" in options) {\n return options.columns as VuuSelectedRowsContextMenuItemOptions[\"columns\"];\n }\n};\n\nconst isVuuMenuItem = (menu: VuuMenuItem | VuuMenu): menu is VuuMenuItem =>\n \"rpcName\" in menu;\n\nconst isGroupMenuItem = (menu: VuuMenuItem | VuuMenu): menu is VuuMenu =>\n \"menus\" in menu;\n\nconst hasFilter = ({ filter }: VuuMenuItem) =>\n typeof filter === \"string\" && filter.length > 0;\n\nconst { KEY } = metadataKeys;\n\nconst getMenuItemOptions = (\n menu: VuuMenuItem,\n options: TableContextMenuOptions,\n) => {\n switch (menu.context) {\n case \"cell\":\n return {\n ...menu,\n field: options.column.name,\n rowKey: options.row[KEY],\n value: options.row[options.columnMap[options.column.name]],\n };\n case \"row\":\n return {\n ...menu,\n columns: options.columns,\n row: dataSourceRowToDataRowDto(options.row, options.columnMap),\n rowKey: options.row[KEY],\n };\n case \"selected-rows\":\n return {\n ...menu,\n columns: options.columns,\n };\n default:\n return menu;\n }\n};\n\nconst vuuContextCompatibleWithTableLocation = (\n uiLocation: TableMenuLocation,\n vuuContext: VuuMenuContext,\n selectedRowCount = 0,\n) => {\n switch (uiLocation) {\n case \"grid\":\n if (vuuContext === \"selected-rows\") {\n return selectedRowCount > 0;\n } else {\n return true;\n }\n case \"header\":\n return vuuContext === \"grid\";\n default:\n return false;\n }\n};\n\nconst gridRowMeetsFilterCriteria = (\n context: VuuMenuContext,\n row: DataSourceRow,\n selectedRows: DataSourceRow[],\n filter: string,\n columnMap: ColumnMap,\n): boolean => {\n if (context === \"cell\" || context === \"row\") {\n const filterPredicate = getFilterPredicate(columnMap, filter);\n return filterPredicate(row);\n } else if (context === \"selected-rows\") {\n if (selectedRows.length === 0) {\n return false;\n } else {\n const filterPredicate = getFilterPredicate(columnMap, filter);\n return selectedRows.every(filterPredicate);\n }\n }\n return true;\n};\n\nconst menuShouldBeRenderedInThisContext = (\n menuItem: VuuMenu | VuuMenuItem,\n tableLocation: TableMenuLocation,\n options: TableContextMenuOptions,\n): boolean => {\n if (isGroupMenuItem(menuItem)) {\n return menuItem.menus.some((childMenu) =>\n menuShouldBeRenderedInThisContext(childMenu, tableLocation, options),\n );\n }\n if (\n !vuuContextCompatibleWithTableLocation(\n tableLocation,\n menuItem.context,\n options.selectedRows?.length,\n )\n ) {\n return false;\n }\n\n if (tableLocation === \"grid\" && hasFilter(menuItem)) {\n return gridRowMeetsFilterCriteria(\n menuItem.context,\n options.row,\n options.selectedRows,\n menuItem.filter,\n options.columnMap,\n );\n }\n\n if (isCellMenu(menuItem) && menuItem.field !== \"*\") {\n return menuItem.field === options.column.name;\n }\n\n return true;\n};\n\nconst buildMenuDescriptorFromVuuMenu = (\n menu: VuuMenu | VuuMenuItem,\n tableLocation: TableMenuLocation,\n options: TableContextMenuOptions,\n): ContextMenuItemDescriptor | undefined => {\n if (menuShouldBeRenderedInThisContext(menu, tableLocation, options)) {\n if (isVuuMenuItem(menu)) {\n return {\n label: menu.name,\n id: \"MENU_RPC_CALL\",\n options: getMenuItemOptions(menu, options),\n };\n } else {\n const children = menu.menus\n .map((childMenu) =>\n buildMenuDescriptorFromVuuMenu(childMenu, tableLocation, options),\n )\n .filter(\n (childMenu) => childMenu !== undefined,\n ) as ContextMenuItemDescriptor[];\n if (children.length > 0) {\n return {\n label: menu.name,\n children,\n };\n }\n }\n }\n};\n\nconst keyFirst = (c1: FormFieldDescriptor, c2: FormFieldDescriptor) =>\n c1.isKeyField ? -1 : c2.isKeyField ? 1 : 0;\n\nconst defaultFormConfig = {\n fields: [],\n key: \"\",\n title: \"\",\n};\n\nconst configFromSchema = (schema?: TableSchema): FormConfig | undefined => {\n if (schema) {\n const { columns, key } = schema;\n return {\n key,\n title: `Parameters for command`,\n fields: columns\n .map((col) => ({\n description: col.name,\n label: col.name,\n name: col.name,\n type: col.serverDataType,\n isKeyField: col.name === key,\n }))\n .sort(keyFirst),\n };\n }\n};\n\nconst getFormConfig = (\n action: OpenDialogAction & { tableSchema: TableSchema },\n) => {\n const { tableSchema: schema } = action;\n const config = configFromSchema(schema) ?? defaultFormConfig;\n\n return {\n config,\n schema,\n };\n};\n\nexport const useVuuMenuActions = ({\n clientSideMenuActionHandler,\n dataSource,\n onRpcResponse,\n}: VuuMenuActionHookProps): VuuMenuActionHookResult => {\n const { VuuDataSource } = useData();\n const menuBuilder: MenuBuilder<TableMenuLocation, TableContextMenuOptions> =\n useCallback(\n (location, options) => {\n const descriptors: ContextMenuItemDescriptor[] = [];\n if (dataSource) {\n const { links, menu } = dataSource;\n const { visualLink } = dataSource;\n\n if (location === \"grid\" && links && !visualLink) {\n links.forEach((linkDescriptor: LinkDescriptorWithLabel) => {\n const { link, label: linkLabel } = linkDescriptor;\n const label = linkLabel ? linkLabel : link.toTable;\n descriptors.push({\n label: `Link to ${label}`,\n id: \"link-table\",\n options: linkDescriptor,\n });\n });\n }\n\n if (menu && isTableLocation(location)) {\n const menuDescriptor = buildMenuDescriptorFromVuuMenu(\n menu,\n location,\n options,\n );\n if (isRoot(menu) && isGroupMenuItemDescriptor(menuDescriptor)) {\n descriptors.push(...menuDescriptor.children);\n } else if (menuDescriptor) {\n descriptors.push(menuDescriptor);\n }\n }\n } else {\n throw Error(\"useVuuMenuActions no dataSource provided\");\n }\n\n return descriptors;\n },\n [dataSource],\n );\n\n const { showDialog, closeDialog } = useDialogContext();\n const showNotification = useNotifications();\n\n const showBulkEditDialog = useCallback(\n (ds: DataSource, table: VuuTable, columns?: ColumnDescriptor[]) => {\n const sessionDs = new VuuDataSource({\n columns: columns?.map(toColumnName),\n table,\n viewport: table.table,\n });\n\n const handleClose = () => {\n sessionDs.unsubscribe();\n closeDialog();\n };\n\n showDialog(\n <BulkEditDialog\n columns={columns}\n sessionDs={sessionDs}\n parentDs={ds}\n closeDialog={handleClose}\n />,\n \"Bulk Amend\",\n );\n\n return true;\n },\n [VuuDataSource, closeDialog, showDialog],\n );\n\n const showSessionEditingForm = useCallback(\n (\n ds: DataSource,\n action: OpenDialogAction & { tableSchema: TableSchema },\n ) => {\n const { tableSchema } = action;\n if (tableSchema) {\n const formConfig = getFormConfig(action);\n showDialog(\n <SessionEditingForm {...formConfig} onClose={closeDialog} />,\n \"Set Parameters\",\n );\n }\n\n const sessionDs = ds.createSessionDataSource?.(action.table);\n const handleSubmit = () => {\n sessionDs?.rpcCall?.(viewportRpcRequest(\"VP_BULK_EDIT_SUBMIT_RPC\"));\n closeDialog();\n };\n\n const handleChange = (isValid: boolean) => {\n console.log(\"placeholder: \", isValid);\n };\n\n if (sessionDs) {\n showDialog(\n <BulkEditPanel\n dataSource={sessionDs}\n onSubmit={handleSubmit}\n parentDs={ds}\n onValidationStatusChange={handleChange}\n />,\n \"Multi Row Edit\",\n [\n <Button key=\"cancel\" onClick={closeDialog}>\n Cancel\n </Button>,\n <Button key=\"submit\" onClick={handleSubmit}>\n Save\n </Button>,\n ],\n );\n }\n },\n [closeDialog, showDialog],\n );\n\n const getMenuRpcRequest = (\n options: VuuMenuItem,\n ): Omit<VuuRpcMenuRequest, \"vpId\"> => {\n const { rpcName } = options;\n if (isCellMenu(options)) {\n return {\n field: options.field,\n rowKey: options.rowKey,\n rpcName,\n value: options.value,\n type: \"VIEW_PORT_MENU_CELL_RPC\",\n } as Omit<ClientToServerMenuCellRPC, \"vpId\">;\n } else if (isRowMenu(options)) {\n return {\n rowKey: options.rowKey,\n row: options.row,\n rpcName,\n type: \"VIEW_PORT_MENU_ROW_RPC\",\n } as Omit<ClientToServerMenuRowRPC, \"vpId\">;\n } else if (isSelectionMenu(options)) {\n return {\n rpcName,\n type: \"VIEW_PORT_MENUS_SELECT_RPC\",\n } as Omit<VuuRpcMenuRequest, \"vpId\">;\n } else {\n return {\n rpcName,\n type: \"VIEW_PORT_MENU_TABLE_RPC\",\n } as Omit<VuuRpcMenuRequest, \"vpId\">;\n }\n };\n\n const menuActionHandler = useCallback<MenuActionHandler>(\n (menuItemId, options) => {\n if (clientSideMenuActionHandler?.(menuItemId, options)) {\n return true;\n } else if (menuItemId === \"MENU_RPC_CALL\") {\n const rpcRequest = getMenuRpcRequest(options as VuuMenuItem);\n\n dataSource\n ?.menuRpcCall(rpcRequest)\n .then((rpcResponse: Omit<VuuRpcResponse, \"requestId\">) => {\n if (rpcResponse) {\n if (onRpcResponse?.(rpcResponse) === true) {\n return true;\n }\n if (isActionMessage(rpcResponse)) {\n if (hasShowNotificationAction(rpcResponse)) {\n const {\n action: { message, title = \"Success\" },\n } = rpcResponse;\n showNotification({\n type: \"success\",\n body: message,\n header: title,\n });\n } else if (isOpenBulkEditResponse(rpcResponse)) {\n showBulkEditDialog(\n dataSource,\n rpcResponse.action.table,\n getColumnsFromOptions(options),\n );\n } else if (isSessionTableActionMessage(rpcResponse)) {\n showSessionEditingForm(dataSource, rpcResponse.action);\n }\n }\n }\n });\n return true;\n } else if (menuItemId === \"link-table\") {\n if (dataSource) {\n dataSource.visualLink = options as LinkDescriptorWithLabel;\n }\n return true;\n } else {\n console.log(\n `useViewServer handleMenuAction, can't handle action type ${menuItemId}`,\n );\n }\n\n return false;\n },\n [\n clientSideMenuActionHandler,\n dataSource,\n onRpcResponse,\n showBulkEditDialog,\n showNotification,\n showSessionEditingForm,\n ],\n );\n\n return {\n menuBuilder,\n menuActionHandler,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { useDataSource } from '@vuu-ui/vuu-utils';
1
+ import { useData } from '@vuu-ui/vuu-utils';
2
2
  import { useState, useCallback, useEffect } from 'react';
3
3
 
4
4
  const useVuuTables = () => {
5
5
  const [tableSchemas, setTableSchemas] = useState();
6
- const { getServerAPI } = useDataSource();
6
+ const { getServerAPI } = useData();
7
7
  const buildTables = useCallback((schemas) => {
8
8
  const vuuTables = /* @__PURE__ */ new Map();
9
9
  schemas.forEach((schema) => {
@@ -1 +1 @@
1
- {"version":3,"file":"useVuuTables.js","sources":["../../src/hooks/useVuuTables.ts"],"sourcesContent":["import type { TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport { useDataSource } from \"@vuu-ui/vuu-utils\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nexport const useVuuTables = () => {\n const [tableSchemas, setTableSchemas] = useState<TableSchema[] | undefined>();\n\n const { getServerAPI } = useDataSource();\n\n const buildTables = useCallback((schemas: TableSchema[]) => {\n const vuuTables = new Map<string, TableSchema>();\n schemas.forEach((schema) => {\n const { module, table } = schema.table;\n vuuTables.set(`${module}:${table}`, schema);\n });\n return vuuTables;\n }, []);\n\n useEffect(() => {\n async function fetchTableMetadata() {\n try {\n const server = await getServerAPI();\n const { tables } = await server.getTableList();\n const tableSchemas = await Promise.all(\n tables.map((vuuTable) => server.getTableSchema(vuuTable)),\n );\n setTableSchemas(tableSchemas);\n } catch (err) {\n console.warn(\n `useVuuTables: error fetching table metadata ${String(err)}`,\n );\n }\n }\n\n fetchTableMetadata();\n }, [buildTables, getServerAPI]);\n\n return tableSchemas;\n};\n"],"names":["tableSchemas"],"mappings":";;;AAIO,MAAM,eAAe,MAAM;AAChC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAoC,EAAA;AAE5E,EAAM,MAAA,EAAE,YAAa,EAAA,GAAI,aAAc,EAAA;AAEvC,EAAM,MAAA,WAAA,GAAc,WAAY,CAAA,CAAC,OAA2B,KAAA;AAC1D,IAAM,MAAA,SAAA,uBAAgB,GAAyB,EAAA;AAC/C,IAAQ,OAAA,CAAA,OAAA,CAAQ,CAAC,MAAW,KAAA;AAC1B,MAAA,MAAM,EAAE,MAAA,EAAQ,KAAM,EAAA,GAAI,MAAO,CAAA,KAAA;AACjC,MAAA,SAAA,CAAU,IAAI,CAAG,EAAA,MAAM,CAAI,CAAA,EAAA,KAAK,IAAI,MAAM,CAAA;AAAA,KAC3C,CAAA;AACD,IAAO,OAAA,SAAA;AAAA,GACT,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAe,kBAAqB,GAAA;AAClC,MAAI,IAAA;AACF,QAAM,MAAA,MAAA,GAAS,MAAM,YAAa,EAAA;AAClC,QAAA,MAAM,EAAE,MAAA,EAAW,GAAA,MAAM,OAAO,YAAa,EAAA;AAC7C,QAAMA,MAAAA,aAAAA,GAAe,MAAM,OAAQ,CAAA,GAAA;AAAA,UACjC,OAAO,GAAI,CAAA,CAAC,aAAa,MAAO,CAAA,cAAA,CAAe,QAAQ,CAAC;AAAA,SAC1D;AACA,QAAA,eAAA,CAAgBA,aAAY,CAAA;AAAA,eACrB,GAAK,EAAA;AACZ,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,CAAA,4CAAA,EAA+C,MAAO,CAAA,GAAG,CAAC,CAAA;AAAA,SAC5D;AAAA;AACF;AAGF,IAAmB,kBAAA,EAAA;AAAA,GAClB,EAAA,CAAC,WAAa,EAAA,YAAY,CAAC,CAAA;AAE9B,EAAO,OAAA,YAAA;AACT;;;;"}
1
+ {"version":3,"file":"useVuuTables.js","sources":["../../src/hooks/useVuuTables.ts"],"sourcesContent":["import type { TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport { useData } from \"@vuu-ui/vuu-utils\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nexport const useVuuTables = () => {\n const [tableSchemas, setTableSchemas] = useState<TableSchema[] | undefined>();\n\n const { getServerAPI } = useData();\n\n const buildTables = useCallback((schemas: TableSchema[]) => {\n const vuuTables = new Map<string, TableSchema>();\n schemas.forEach((schema) => {\n const { module, table } = schema.table;\n vuuTables.set(`${module}:${table}`, schema);\n });\n return vuuTables;\n }, []);\n\n useEffect(() => {\n async function fetchTableMetadata() {\n try {\n const server = await getServerAPI();\n const { tables } = await server.getTableList();\n const tableSchemas = await Promise.all(\n tables.map((vuuTable) => server.getTableSchema(vuuTable)),\n );\n setTableSchemas(tableSchemas);\n } catch (err) {\n console.warn(\n `useVuuTables: error fetching table metadata ${String(err)}`,\n );\n }\n }\n\n fetchTableMetadata();\n }, [buildTables, getServerAPI]);\n\n return tableSchemas;\n};\n"],"names":["tableSchemas"],"mappings":";;;AAIO,MAAM,eAAe,MAAM;AAChC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAoC,EAAA;AAE5E,EAAM,MAAA,EAAE,YAAa,EAAA,GAAI,OAAQ,EAAA;AAEjC,EAAM,MAAA,WAAA,GAAc,WAAY,CAAA,CAAC,OAA2B,KAAA;AAC1D,IAAM,MAAA,SAAA,uBAAgB,GAAyB,EAAA;AAC/C,IAAQ,OAAA,CAAA,OAAA,CAAQ,CAAC,MAAW,KAAA;AAC1B,MAAA,MAAM,EAAE,MAAA,EAAQ,KAAM,EAAA,GAAI,MAAO,CAAA,KAAA;AACjC,MAAA,SAAA,CAAU,IAAI,CAAG,EAAA,MAAM,CAAI,CAAA,EAAA,KAAK,IAAI,MAAM,CAAA;AAAA,KAC3C,CAAA;AACD,IAAO,OAAA,SAAA;AAAA,GACT,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAe,kBAAqB,GAAA;AAClC,MAAI,IAAA;AACF,QAAM,MAAA,MAAA,GAAS,MAAM,YAAa,EAAA;AAClC,QAAA,MAAM,EAAE,MAAA,EAAW,GAAA,MAAM,OAAO,YAAa,EAAA;AAC7C,QAAMA,MAAAA,aAAAA,GAAe,MAAM,OAAQ,CAAA,GAAA;AAAA,UACjC,OAAO,GAAI,CAAA,CAAC,aAAa,MAAO,CAAA,cAAA,CAAe,QAAQ,CAAC;AAAA,SAC1D;AACA,QAAA,eAAA,CAAgBA,aAAY,CAAA;AAAA,eACrB,GAAK,EAAA;AACZ,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,CAAA,4CAAA,EAA+C,MAAO,CAAA,GAAG,CAAC,CAAA;AAAA,SAC5D;AAAA;AACF;AAGF,IAAmB,kBAAA,EAAA;AAAA,GAClB,EAAA,CAAC,WAAa,EAAA,YAAY,CAAC,CAAA;AAE9B,EAAO,OAAA,YAAA;AACT;;;;"}
package/esm/index.js CHANGED
@@ -8,7 +8,7 @@ export { RestDataSourceProvider, isRestDataSourceExtension } from './datasource-
8
8
  export { VuuDataSourceProvider } from './datasource-provider/VuuDataSourceProvider.js';
9
9
  export { useLookupValues } from './hooks/useLookupValues.js';
10
10
  export { useSessionDataSource } from './hooks/useSessionDataSource.js';
11
- export { useVuuMenuActions } from './hooks/useVuuMenuActions.js';
11
+ export { isRowMenu, isSelectionMenu, useVuuMenuActions } from './hooks/useVuuMenuActions.js';
12
12
  export { useVuuTables } from './hooks/useVuuTables.js';
13
13
  export { useVisualLinks } from './hooks/useVisualLinks.js';
14
14
  export { getTypeaheadParams, useTypeaheadSuggestions } from './hooks/useTypeaheadSuggestions.js';
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { VuuDataSource } from '@vuu-ui/vuu-data-remote';
3
- import { buildColumnMap, getTypedValue, shallowEquals, vuuEditCellRequest, isErrorResponse, isActionMessage, queryClosest } from '@vuu-ui/vuu-utils';
3
+ import { buildColumnMap, Range, getTypedValue, shallowEquals, vuuEditCellRequest, isErrorResponse, isActionMessage, queryClosest } from '@vuu-ui/vuu-utils';
4
4
  import { useIdMemo, FormField, FormFieldLabel, FormFieldHelperText, Button, Input } from '@salt-ds/core';
5
5
  import { useComponentCssInjection } from '@salt-ds/styles';
6
6
  import { useWindow } from '@salt-ds/window';
@@ -92,7 +92,7 @@ const SessionEditingForm = ({
92
92
  setValues(values2);
93
93
  }
94
94
  };
95
- ds.subscribe({ range: { from: 0, to: 5 } }, (message) => {
95
+ ds.subscribe({ range: Range(0, 5) }, (message) => {
96
96
  if (message.type === "viewport-update" && message.rows) {
97
97
  if (dataStatusRef.current === Status.uninitialised) {
98
98
  applyServerData(message.rows[0]);
@@ -1 +1 @@
1
- {"version":3,"file":"SessionEditingForm.js","sources":["../../src/session-editing-form/SessionEditingForm.tsx"],"sourcesContent":["import { VuuDataSource } from \"@vuu-ui/vuu-data-remote\";\nimport { DataSource, TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport {\n VuuColumnDataType,\n VuuDataRow,\n VuuRowDataItemType,\n VuuRpcAction,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport {\n buildColumnMap,\n getTypedValue,\n isActionMessage,\n isErrorResponse,\n queryClosest,\n shallowEquals,\n vuuEditCellRequest,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n Button,\n FormField,\n FormFieldHelperText,\n FormFieldLabel,\n Input,\n useIdMemo,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport {\n ChangeEvent,\n ChangeEventHandler,\n FocusEvent,\n FocusEventHandler,\n HTMLAttributes,\n KeyboardEventHandler,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport sessionEditingFormCss from \"./SessionEditingForm.css\";\n\nexport type FormFieldDescriptor = {\n isKeyField?: boolean;\n label?: string;\n name: string;\n type: VuuColumnDataType;\n description: string;\n readonly?: boolean;\n required?: boolean;\n};\n\nexport type FormConfig = {\n title: string;\n key: string;\n fields: FormFieldDescriptor[];\n};\n\nexport interface SessionEditingFormProps\n extends HTMLAttributes<HTMLDivElement> {\n config: FormConfig;\n onClose?: () => void;\n dataSource?: DataSource;\n schema?: TableSchema;\n}\n\nconst classBase = \"vuuSessionEditingForm\";\n\nconst getField = (\n fields: FormFieldDescriptor[],\n name: string,\n): FormFieldDescriptor => {\n const field = fields.find((f) => f.name === name);\n if (field) {\n return field;\n } else {\n throw Error(`SessionEditingForm, no field '${name}' found`);\n }\n};\n\nconst getFieldNameAndValue = ({\n target,\n}: ChangeEvent<HTMLInputElement> | FocusEvent<HTMLInputElement>): [\n string,\n string,\n] => {\n const formField = queryClosest(target, \".saltFormField\");\n if (formField) {\n const {\n dataset: { field },\n } = formField;\n if (field === undefined) {\n throw Error(\"SessionEditingForm, form field has no field data attribute\");\n }\n return [field, target.value];\n } else {\n throw Error(\"Form control is not enclosed in FormField\");\n }\n};\n\nconst Status = {\n uninitialised: 0,\n unchanged: 1,\n changed: 2,\n invalid: 3,\n};\n\nconst getDataSource = (\n dataSource?: DataSource,\n schema?: TableSchema,\n): DataSource => {\n if (dataSource) {\n return dataSource;\n } else if (schema) {\n return new VuuDataSource({\n bufferSize: 0,\n table: schema.table,\n columns: schema.columns.map((col) => col.name),\n }) as DataSource;\n } else {\n throw Error(\n \"SessionEditingForm: either a DataSource or a TableSchema must be provided\",\n );\n }\n};\n\ntype FormValues = { [key: string]: VuuRowDataItemType | undefined };\n\nexport const SessionEditingForm = ({\n className,\n config: { fields, key: keyField },\n dataSource: dataSourceProp,\n id: idProp,\n onClose,\n schema,\n ...htmlAttributes\n}: SessionEditingFormProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-session-editing-form\",\n css: sessionEditingFormCss,\n window: targetWindow,\n });\n\n const [fieldStatusValues, setFieldStatusValues] = useState<\n Record<string, string | undefined>\n >({});\n const [values, setValues] = useState<FormValues>();\n const [errorMessage, setErrorMessage] = useState(\"\");\n const formContentRef = useRef<HTMLDivElement>(null);\n const initialDataRef = useRef<FormValues>();\n const dataStatusRef = useRef(Status.uninitialised);\n\n const dataSource = useMemo(() => {\n const ds = getDataSource(dataSourceProp, schema);\n const { columns } = ds;\n const columnMap = buildColumnMap(ds.columns);\n\n const applyServerData = (data: VuuDataRow) => {\n if (columnMap) {\n const values: { [key: string]: VuuRowDataItemType } = {};\n for (const column of columns) {\n values[column] = data[columnMap[column]];\n }\n if (dataStatusRef.current === Status.uninitialised) {\n dataStatusRef.current = Status.unchanged;\n initialDataRef.current = values;\n }\n setValues(values);\n }\n };\n\n ds.subscribe({ range: { from: 0, to: 5 } }, (message) => {\n if (message.type === \"viewport-update\" && message.rows) {\n if (dataStatusRef.current === Status.uninitialised) {\n applyServerData(message.rows[0]);\n } else {\n console.log(\"what do we do with server updates\");\n }\n }\n });\n return ds;\n }, [dataSourceProp, schema]);\n\n const id = useIdMemo(idProp);\n\n const handleChange = useCallback<ChangeEventHandler<HTMLInputElement>>(\n (evt) => {\n const [field, value] = getFieldNameAndValue(evt);\n const { type } = getField(fields, field);\n const typedValue = getTypedValue(value, type);\n setValues((values = {}) => {\n const newValues = {\n ...values,\n [field]: typedValue,\n };\n const notUpdated = shallowEquals(newValues, initialDataRef.current);\n dataStatusRef.current = notUpdated\n ? Status.unchanged\n : typedValue !== undefined\n ? Status.changed\n : Status.invalid;\n return newValues;\n });\n },\n [fields],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLInputElement>>(\n (evt) => {\n const [field, value] = getFieldNameAndValue(evt);\n const rowKey = values?.[keyField];\n // TODO link this with client side validation if we're going to use it\n const { type } = getField(fields, field);\n const typedValue = getTypedValue(value, type, true);\n if (typeof rowKey === \"string\") {\n dataSource\n .menuRpcCall(vuuEditCellRequest(rowKey, field, typedValue))\n .then((response) => {\n if (isErrorResponse(response)) {\n console.log(`edit rejected ${response.error}`);\n setFieldStatusValues((map) => ({\n ...map,\n [field]: response.error,\n }));\n } else {\n setFieldStatusValues((map) => ({\n ...map,\n [field]: undefined,\n }));\n }\n });\n }\n },\n [dataSource, fields, keyField, values],\n );\n\n const applyAction = useCallback(\n (action: VuuRpcAction) => {\n if (action.type === \"CLOSE_DIALOG_ACTION\") {\n onClose?.();\n }\n },\n [onClose],\n );\n\n const handleSubmit = useCallback(async () => {\n const rpcResponse = await dataSource.menuRpcCall({\n type: \"VP_EDIT_SUBMIT_FORM_RPC\",\n });\n if (isErrorResponse(rpcResponse)) {\n setErrorMessage(rpcResponse.error);\n } else if (isActionMessage(rpcResponse)) {\n applyAction(rpcResponse.action);\n }\n }, [applyAction, dataSource]);\n\n const handleKeyDown = useCallback<KeyboardEventHandler>(\n (evt) => {\n if (evt.key === \"Enter\" && dataStatusRef.current === Status.changed) {\n handleSubmit();\n }\n },\n [handleSubmit],\n );\n\n const handleCancel = useCallback(() => {\n onClose?.();\n }, [onClose]);\n\n const getFormControl = (field: FormFieldDescriptor) => {\n const value = String(values?.[field.name] ?? \"\");\n if (field.readonly || field.name === keyField) {\n return (\n <div className={`${classBase}-fieldValue vuuReadOnly`}>{value}</div>\n );\n } else {\n return (\n <Input\n className={`${classBase}-fieldValue`}\n onBlur={handleBlur}\n onChange={handleChange}\n value={value}\n id={`${id}-input-${field.name}`}\n />\n );\n }\n };\n\n useEffect(() => {\n if (formContentRef.current) {\n const firstInput = formContentRef.current.querySelector(\n \"input\",\n ) as HTMLInputElement;\n if (firstInput) {\n setTimeout(() => {\n firstInput.focus();\n firstInput.select();\n }, 100);\n }\n }\n }, []);\n\n useEffect(() => {\n return () => {\n if (dataSource) {\n dataSource.unsubscribe();\n }\n };\n }, [dataSource]);\n\n const isDirty = dataStatusRef.current === Status.changed;\n return (\n <div {...htmlAttributes} className={cx(classBase, className)}>\n {errorMessage ? (\n <div\n className={`${classBase}-errorBanner`}\n data-icon=\"error\"\n title={errorMessage}\n >\n Error, edit(s) not saved\n </div>\n ) : undefined}\n <div\n className={`${classBase}-content`}\n ref={formContentRef}\n onKeyDown={handleKeyDown}\n >\n {fields.map((field) => (\n <FormField\n className={`${classBase}-field`}\n data-field={field.name}\n key={field.name}\n necessity={field.required ? \"required\" : \"optional\"}\n readOnly={field.readonly}\n validationStatus={\n fieldStatusValues[field.name] ? \"error\" : undefined\n }\n >\n <FormFieldLabel>{field?.label ?? field.description}</FormFieldLabel>\n {getFormControl(field)}\n <FormFieldHelperText>\n {fieldStatusValues[field.name] ?? \"\"}\n </FormFieldHelperText>\n </FormField>\n ))}\n </div>\n <div className={`${classBase}-buttonbar salt-theme salt-density-high`}>\n <Button\n type=\"submit\"\n variant=\"cta\"\n disabled={!isDirty}\n onClick={handleSubmit}\n >\n Submit\n </Button>\n <Button variant=\"secondary\" onClick={handleCancel}>\n Cancel\n </Button>\n </div>\n </div>\n );\n};\n"],"names":["values"],"mappings":"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"}
1
+ {"version":3,"file":"SessionEditingForm.js","sources":["../../src/session-editing-form/SessionEditingForm.tsx"],"sourcesContent":["import { VuuDataSource } from \"@vuu-ui/vuu-data-remote\";\nimport { DataSource, TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport {\n VuuColumnDataType,\n VuuDataRow,\n VuuRowDataItemType,\n VuuRpcAction,\n} from \"@vuu-ui/vuu-protocol-types\";\nimport {\n buildColumnMap,\n getTypedValue,\n isActionMessage,\n isErrorResponse,\n queryClosest,\n Range,\n shallowEquals,\n vuuEditCellRequest,\n} from \"@vuu-ui/vuu-utils\";\nimport {\n Button,\n FormField,\n FormFieldHelperText,\n FormFieldLabel,\n Input,\n useIdMemo,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport {\n ChangeEvent,\n ChangeEventHandler,\n FocusEvent,\n FocusEventHandler,\n HTMLAttributes,\n KeyboardEventHandler,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport sessionEditingFormCss from \"./SessionEditingForm.css\";\n\nexport type FormFieldDescriptor = {\n isKeyField?: boolean;\n label?: string;\n name: string;\n type: VuuColumnDataType;\n description: string;\n readonly?: boolean;\n required?: boolean;\n};\n\nexport type FormConfig = {\n title: string;\n key: string;\n fields: FormFieldDescriptor[];\n};\n\nexport interface SessionEditingFormProps\n extends HTMLAttributes<HTMLDivElement> {\n config: FormConfig;\n onClose?: () => void;\n dataSource?: DataSource;\n schema?: TableSchema;\n}\n\nconst classBase = \"vuuSessionEditingForm\";\n\nconst getField = (\n fields: FormFieldDescriptor[],\n name: string,\n): FormFieldDescriptor => {\n const field = fields.find((f) => f.name === name);\n if (field) {\n return field;\n } else {\n throw Error(`SessionEditingForm, no field '${name}' found`);\n }\n};\n\nconst getFieldNameAndValue = ({\n target,\n}: ChangeEvent<HTMLInputElement> | FocusEvent<HTMLInputElement>): [\n string,\n string,\n] => {\n const formField = queryClosest(target, \".saltFormField\");\n if (formField) {\n const {\n dataset: { field },\n } = formField;\n if (field === undefined) {\n throw Error(\"SessionEditingForm, form field has no field data attribute\");\n }\n return [field, target.value];\n } else {\n throw Error(\"Form control is not enclosed in FormField\");\n }\n};\n\nconst Status = {\n uninitialised: 0,\n unchanged: 1,\n changed: 2,\n invalid: 3,\n};\n\nconst getDataSource = (\n dataSource?: DataSource,\n schema?: TableSchema,\n): DataSource => {\n if (dataSource) {\n return dataSource;\n } else if (schema) {\n return new VuuDataSource({\n bufferSize: 0,\n table: schema.table,\n columns: schema.columns.map((col) => col.name),\n }) as DataSource;\n } else {\n throw Error(\n \"SessionEditingForm: either a DataSource or a TableSchema must be provided\",\n );\n }\n};\n\ntype FormValues = { [key: string]: VuuRowDataItemType | undefined };\n\nexport const SessionEditingForm = ({\n className,\n config: { fields, key: keyField },\n dataSource: dataSourceProp,\n id: idProp,\n onClose,\n schema,\n ...htmlAttributes\n}: SessionEditingFormProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-session-editing-form\",\n css: sessionEditingFormCss,\n window: targetWindow,\n });\n\n const [fieldStatusValues, setFieldStatusValues] = useState<\n Record<string, string | undefined>\n >({});\n const [values, setValues] = useState<FormValues>();\n const [errorMessage, setErrorMessage] = useState(\"\");\n const formContentRef = useRef<HTMLDivElement>(null);\n const initialDataRef = useRef<FormValues>();\n const dataStatusRef = useRef(Status.uninitialised);\n\n const dataSource = useMemo(() => {\n const ds = getDataSource(dataSourceProp, schema);\n const { columns } = ds;\n const columnMap = buildColumnMap(ds.columns);\n\n const applyServerData = (data: VuuDataRow) => {\n if (columnMap) {\n const values: { [key: string]: VuuRowDataItemType } = {};\n for (const column of columns) {\n values[column] = data[columnMap[column]];\n }\n if (dataStatusRef.current === Status.uninitialised) {\n dataStatusRef.current = Status.unchanged;\n initialDataRef.current = values;\n }\n setValues(values);\n }\n };\n\n ds.subscribe({ range: Range(0, 5) }, (message) => {\n if (message.type === \"viewport-update\" && message.rows) {\n if (dataStatusRef.current === Status.uninitialised) {\n applyServerData(message.rows[0]);\n } else {\n console.log(\"what do we do with server updates\");\n }\n }\n });\n return ds;\n }, [dataSourceProp, schema]);\n\n const id = useIdMemo(idProp);\n\n const handleChange = useCallback<ChangeEventHandler<HTMLInputElement>>(\n (evt) => {\n const [field, value] = getFieldNameAndValue(evt);\n const { type } = getField(fields, field);\n const typedValue = getTypedValue(value, type);\n setValues((values = {}) => {\n const newValues = {\n ...values,\n [field]: typedValue,\n };\n const notUpdated = shallowEquals(newValues, initialDataRef.current);\n dataStatusRef.current = notUpdated\n ? Status.unchanged\n : typedValue !== undefined\n ? Status.changed\n : Status.invalid;\n return newValues;\n });\n },\n [fields],\n );\n\n const handleBlur = useCallback<FocusEventHandler<HTMLInputElement>>(\n (evt) => {\n const [field, value] = getFieldNameAndValue(evt);\n const rowKey = values?.[keyField];\n // TODO link this with client side validation if we're going to use it\n const { type } = getField(fields, field);\n const typedValue = getTypedValue(value, type, true);\n if (typeof rowKey === \"string\") {\n dataSource\n .menuRpcCall(vuuEditCellRequest(rowKey, field, typedValue))\n .then((response) => {\n if (isErrorResponse(response)) {\n console.log(`edit rejected ${response.error}`);\n setFieldStatusValues((map) => ({\n ...map,\n [field]: response.error,\n }));\n } else {\n setFieldStatusValues((map) => ({\n ...map,\n [field]: undefined,\n }));\n }\n });\n }\n },\n [dataSource, fields, keyField, values],\n );\n\n const applyAction = useCallback(\n (action: VuuRpcAction) => {\n if (action.type === \"CLOSE_DIALOG_ACTION\") {\n onClose?.();\n }\n },\n [onClose],\n );\n\n const handleSubmit = useCallback(async () => {\n const rpcResponse = await dataSource.menuRpcCall({\n type: \"VP_EDIT_SUBMIT_FORM_RPC\",\n });\n if (isErrorResponse(rpcResponse)) {\n setErrorMessage(rpcResponse.error);\n } else if (isActionMessage(rpcResponse)) {\n applyAction(rpcResponse.action);\n }\n }, [applyAction, dataSource]);\n\n const handleKeyDown = useCallback<KeyboardEventHandler>(\n (evt) => {\n if (evt.key === \"Enter\" && dataStatusRef.current === Status.changed) {\n handleSubmit();\n }\n },\n [handleSubmit],\n );\n\n const handleCancel = useCallback(() => {\n onClose?.();\n }, [onClose]);\n\n const getFormControl = (field: FormFieldDescriptor) => {\n const value = String(values?.[field.name] ?? \"\");\n if (field.readonly || field.name === keyField) {\n return (\n <div className={`${classBase}-fieldValue vuuReadOnly`}>{value}</div>\n );\n } else {\n return (\n <Input\n className={`${classBase}-fieldValue`}\n onBlur={handleBlur}\n onChange={handleChange}\n value={value}\n id={`${id}-input-${field.name}`}\n />\n );\n }\n };\n\n useEffect(() => {\n if (formContentRef.current) {\n const firstInput = formContentRef.current.querySelector(\n \"input\",\n ) as HTMLInputElement;\n if (firstInput) {\n setTimeout(() => {\n firstInput.focus();\n firstInput.select();\n }, 100);\n }\n }\n }, []);\n\n useEffect(() => {\n return () => {\n if (dataSource) {\n dataSource.unsubscribe();\n }\n };\n }, [dataSource]);\n\n const isDirty = dataStatusRef.current === Status.changed;\n return (\n <div {...htmlAttributes} className={cx(classBase, className)}>\n {errorMessage ? (\n <div\n className={`${classBase}-errorBanner`}\n data-icon=\"error\"\n title={errorMessage}\n >\n Error, edit(s) not saved\n </div>\n ) : undefined}\n <div\n className={`${classBase}-content`}\n ref={formContentRef}\n onKeyDown={handleKeyDown}\n >\n {fields.map((field) => (\n <FormField\n className={`${classBase}-field`}\n data-field={field.name}\n key={field.name}\n necessity={field.required ? \"required\" : \"optional\"}\n readOnly={field.readonly}\n validationStatus={\n fieldStatusValues[field.name] ? \"error\" : undefined\n }\n >\n <FormFieldLabel>{field?.label ?? field.description}</FormFieldLabel>\n {getFormControl(field)}\n <FormFieldHelperText>\n {fieldStatusValues[field.name] ?? \"\"}\n </FormFieldHelperText>\n </FormField>\n ))}\n </div>\n <div className={`${classBase}-buttonbar salt-theme salt-density-high`}>\n <Button\n type=\"submit\"\n variant=\"cta\"\n disabled={!isDirty}\n onClick={handleSubmit}\n >\n Submit\n </Button>\n <Button variant=\"secondary\" onClick={handleCancel}>\n Cancel\n </Button>\n </div>\n </div>\n );\n};\n"],"names":["values"],"mappings":";;;;;;;;;;AAqEA,MAAM,SAAY,GAAA,uBAAA;AAElB,MAAM,QAAA,GAAW,CACf,MAAA,EACA,IACwB,KAAA;AACxB,EAAA,MAAM,QAAQ,MAAO,CAAA,IAAA,CAAK,CAAC,CAAM,KAAA,CAAA,CAAE,SAAS,IAAI,CAAA;AAChD,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,OAAA,KAAA;AAAA,GACF,MAAA;AACL,IAAM,MAAA,KAAA,CAAM,CAAiC,8BAAA,EAAA,IAAI,CAAS,OAAA,CAAA,CAAA;AAAA;AAE9D,CAAA;AAEA,MAAM,uBAAuB,CAAC;AAAA,EAC5B;AACF,CAGK,KAAA;AACH,EAAM,MAAA,SAAA,GAAY,YAAa,CAAA,MAAA,EAAQ,gBAAgB,CAAA;AACvD,EAAA,IAAI,SAAW,EAAA;AACb,IAAM,MAAA;AAAA,MACJ,OAAA,EAAS,EAAE,KAAM;AAAA,KACf,GAAA,SAAA;AACJ,IAAA,IAAI,UAAU,KAAW,CAAA,EAAA;AACvB,MAAA,MAAM,MAAM,4DAA4D,CAAA;AAAA;AAE1E,IAAO,OAAA,CAAC,KAAO,EAAA,MAAA,CAAO,KAAK,CAAA;AAAA,GACtB,MAAA;AACL,IAAA,MAAM,MAAM,2CAA2C,CAAA;AAAA;AAE3D,CAAA;AAEA,MAAM,MAAS,GAAA;AAAA,EACb,aAAe,EAAA,CAAA;AAAA,EACf,SAAW,EAAA,CAAA;AAAA,EACX,OAAS,EAAA,CAAA;AAAA,EACT,OAAS,EAAA;AACX,CAAA;AAEA,MAAM,aAAA,GAAgB,CACpB,UAAA,EACA,MACe,KAAA;AACf,EAAA,IAAI,UAAY,EAAA;AACd,IAAO,OAAA,UAAA;AAAA,aACE,MAAQ,EAAA;AACjB,IAAA,OAAO,IAAI,aAAc,CAAA;AAAA,MACvB,UAAY,EAAA,CAAA;AAAA,MACZ,OAAO,MAAO,CAAA,KAAA;AAAA,MACd,SAAS,MAAO,CAAA,OAAA,CAAQ,IAAI,CAAC,GAAA,KAAQ,IAAI,IAAI;AAAA,KAC9C,CAAA;AAAA,GACI,MAAA;AACL,IAAM,MAAA,KAAA;AAAA,MACJ;AAAA,KACF;AAAA;AAEJ,CAAA;AAIO,MAAM,qBAAqB,CAAC;AAAA,EACjC,SAAA;AAAA,EACA,MAAQ,EAAA,EAAE,MAAQ,EAAA,GAAA,EAAK,QAAS,EAAA;AAAA,EAChC,UAAY,EAAA,cAAA;AAAA,EACZ,EAAI,EAAA,MAAA;AAAA,EACJ,OAAA;AAAA,EACA,MAAA;AAAA,EACA,GAAG;AACL,CAA+B,KAAA;AAC7B,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,0BAAA;AAAA,IACR,GAAK,EAAA,qBAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAA,MAAM,CAAC,iBAAmB,EAAA,oBAAoB,CAAI,GAAA,QAAA,CAEhD,EAAE,CAAA;AACJ,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,QAAqB,EAAA;AACjD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,EAAE,CAAA;AACnD,EAAM,MAAA,cAAA,GAAiB,OAAuB,IAAI,CAAA;AAClD,EAAA,MAAM,iBAAiB,MAAmB,EAAA;AAC1C,EAAM,MAAA,aAAA,GAAgB,MAAO,CAAA,MAAA,CAAO,aAAa,CAAA;AAEjD,EAAM,MAAA,UAAA,GAAa,QAAQ,MAAM;AAC/B,IAAM,MAAA,EAAA,GAAK,aAAc,CAAA,cAAA,EAAgB,MAAM,CAAA;AAC/C,IAAM,MAAA,EAAE,SAAY,GAAA,EAAA;AACpB,IAAM,MAAA,SAAA,GAAY,cAAe,CAAA,EAAA,CAAG,OAAO,CAAA;AAE3C,IAAM,MAAA,eAAA,GAAkB,CAAC,IAAqB,KAAA;AAC5C,MAAA,IAAI,SAAW,EAAA;AACb,QAAA,MAAMA,UAAgD,EAAC;AACvD,QAAA,KAAA,MAAW,UAAU,OAAS,EAAA;AAC5B,UAAAA,QAAO,MAAM,CAAA,GAAI,IAAK,CAAA,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA;AAEzC,QAAI,IAAA,aAAA,CAAc,OAAY,KAAA,MAAA,CAAO,aAAe,EAAA;AAClD,UAAA,aAAA,CAAc,UAAU,MAAO,CAAA,SAAA;AAC/B,UAAA,cAAA,CAAe,OAAUA,GAAAA,OAAAA;AAAA;AAE3B,QAAA,SAAA,CAAUA,OAAM,CAAA;AAAA;AAClB,KACF;AAEA,IAAG,EAAA,CAAA,SAAA,CAAU,EAAE,KAAO,EAAA,KAAA,CAAM,GAAG,CAAC,CAAA,EAAK,EAAA,CAAC,OAAY,KAAA;AAChD,MAAA,IAAI,OAAQ,CAAA,IAAA,KAAS,iBAAqB,IAAA,OAAA,CAAQ,IAAM,EAAA;AACtD,QAAI,IAAA,aAAA,CAAc,OAAY,KAAA,MAAA,CAAO,aAAe,EAAA;AAClD,UAAgB,eAAA,CAAA,OAAA,CAAQ,IAAK,CAAA,CAAC,CAAC,CAAA;AAAA,SAC1B,MAAA;AACL,UAAA,OAAA,CAAQ,IAAI,mCAAmC,CAAA;AAAA;AACjD;AACF,KACD,CAAA;AACD,IAAO,OAAA,EAAA;AAAA,GACN,EAAA,CAAC,cAAgB,EAAA,MAAM,CAAC,CAAA;AAE3B,EAAM,MAAA,EAAA,GAAK,UAAU,MAAM,CAAA;AAE3B,EAAA,MAAM,YAAe,GAAA,WAAA;AAAA,IACnB,CAAC,GAAQ,KAAA;AACP,MAAA,MAAM,CAAC,KAAA,EAAO,KAAK,CAAA,GAAI,qBAAqB,GAAG,CAAA;AAC/C,MAAA,MAAM,EAAE,IAAA,EAAS,GAAA,QAAA,CAAS,QAAQ,KAAK,CAAA;AACvC,MAAM,MAAA,UAAA,GAAa,aAAc,CAAA,KAAA,EAAO,IAAI,CAAA;AAC5C,MAAU,SAAA,CAAA,CAACA,OAAS,GAAA,EAAO,KAAA;AACzB,QAAA,MAAM,SAAY,GAAA;AAAA,UAChB,GAAGA,OAAAA;AAAA,UACH,CAAC,KAAK,GAAG;AAAA,SACX;AACA,QAAA,MAAM,UAAa,GAAA,aAAA,CAAc,SAAW,EAAA,cAAA,CAAe,OAAO,CAAA;AAClE,QAAc,aAAA,CAAA,OAAA,GAAU,aACpB,MAAO,CAAA,SAAA,GACP,eAAe,KACb,CAAA,GAAA,MAAA,CAAO,UACP,MAAO,CAAA,OAAA;AACb,QAAO,OAAA,SAAA;AAAA,OACR,CAAA;AAAA,KACH;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,CAAC,GAAQ,KAAA;AACP,MAAA,MAAM,CAAC,KAAA,EAAO,KAAK,CAAA,GAAI,qBAAqB,GAAG,CAAA;AAC/C,MAAM,MAAA,MAAA,GAAS,SAAS,QAAQ,CAAA;AAEhC,MAAA,MAAM,EAAE,IAAA,EAAS,GAAA,QAAA,CAAS,QAAQ,KAAK,CAAA;AACvC,MAAA,MAAM,UAAa,GAAA,aAAA,CAAc,KAAO,EAAA,IAAA,EAAM,IAAI,CAAA;AAClD,MAAI,IAAA,OAAO,WAAW,QAAU,EAAA;AAC9B,QACG,UAAA,CAAA,WAAA,CAAY,mBAAmB,MAAQ,EAAA,KAAA,EAAO,UAAU,CAAC,CAAA,CACzD,IAAK,CAAA,CAAC,QAAa,KAAA;AAClB,UAAI,IAAA,eAAA,CAAgB,QAAQ,CAAG,EAAA;AAC7B,YAAA,OAAA,CAAQ,GAAI,CAAA,CAAA,cAAA,EAAiB,QAAS,CAAA,KAAK,CAAE,CAAA,CAAA;AAC7C,YAAA,oBAAA,CAAqB,CAAC,GAAS,MAAA;AAAA,cAC7B,GAAG,GAAA;AAAA,cACH,CAAC,KAAK,GAAG,QAAS,CAAA;AAAA,aAClB,CAAA,CAAA;AAAA,WACG,MAAA;AACL,YAAA,oBAAA,CAAqB,CAAC,GAAS,MAAA;AAAA,cAC7B,GAAG,GAAA;AAAA,cACH,CAAC,KAAK,GAAG,KAAA;AAAA,aACT,CAAA,CAAA;AAAA;AACJ,SACD,CAAA;AAAA;AACL,KACF;AAAA,IACA,CAAC,UAAA,EAAY,MAAQ,EAAA,QAAA,EAAU,MAAM;AAAA,GACvC;AAEA,EAAA,MAAM,WAAc,GAAA,WAAA;AAAA,IAClB,CAAC,MAAyB,KAAA;AACxB,MAAI,IAAA,MAAA,CAAO,SAAS,qBAAuB,EAAA;AACzC,QAAU,OAAA,IAAA;AAAA;AACZ,KACF;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAM,MAAA,YAAA,GAAe,YAAY,YAAY;AAC3C,IAAM,MAAA,WAAA,GAAc,MAAM,UAAA,CAAW,WAAY,CAAA;AAAA,MAC/C,IAAM,EAAA;AAAA,KACP,CAAA;AACD,IAAI,IAAA,eAAA,CAAgB,WAAW,CAAG,EAAA;AAChC,MAAA,eAAA,CAAgB,YAAY,KAAK,CAAA;AAAA,KACnC,MAAA,IAAW,eAAgB,CAAA,WAAW,CAAG,EAAA;AACvC,MAAA,WAAA,CAAY,YAAY,MAAM,CAAA;AAAA;AAChC,GACC,EAAA,CAAC,WAAa,EAAA,UAAU,CAAC,CAAA;AAE5B,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,CAAC,GAAQ,KAAA;AACP,MAAA,IAAI,IAAI,GAAQ,KAAA,OAAA,IAAW,aAAc,CAAA,OAAA,KAAY,OAAO,OAAS,EAAA;AACnE,QAAa,YAAA,EAAA;AAAA;AACf,KACF;AAAA,IACA,CAAC,YAAY;AAAA,GACf;AAEA,EAAM,MAAA,YAAA,GAAe,YAAY,MAAM;AACrC,IAAU,OAAA,IAAA;AAAA,GACZ,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAM,MAAA,cAAA,GAAiB,CAAC,KAA+B,KAAA;AACrD,IAAA,MAAM,QAAQ,MAAO,CAAA,MAAA,GAAS,KAAM,CAAA,IAAI,KAAK,EAAE,CAAA;AAC/C,IAAA,IAAI,KAAM,CAAA,QAAA,IAAY,KAAM,CAAA,IAAA,KAAS,QAAU,EAAA;AAC7C,MAAA,2BACG,KAAI,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,2BAA4B,QAAM,EAAA,KAAA,EAAA,CAAA;AAAA,KAE3D,MAAA;AACL,MACE,uBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,GAAG,SAAS,CAAA,WAAA,CAAA;AAAA,UACvB,MAAQ,EAAA,UAAA;AAAA,UACR,QAAU,EAAA,YAAA;AAAA,UACV,KAAA;AAAA,UACA,EAAI,EAAA,CAAA,EAAG,EAAE,CAAA,OAAA,EAAU,MAAM,IAAI,CAAA;AAAA;AAAA,OAC/B;AAAA;AAEJ,GACF;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,eAAe,OAAS,EAAA;AAC1B,MAAM,MAAA,UAAA,GAAa,eAAe,OAAQ,CAAA,aAAA;AAAA,QACxC;AAAA,OACF;AACA,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,UAAA,CAAW,KAAM,EAAA;AACjB,UAAA,UAAA,CAAW,MAAO,EAAA;AAAA,WACjB,GAAG,CAAA;AAAA;AACR;AACF,GACF,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,UAAA,CAAW,WAAY,EAAA;AAAA;AACzB,KACF;AAAA,GACF,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAM,MAAA,OAAA,GAAU,aAAc,CAAA,OAAA,KAAY,MAAO,CAAA,OAAA;AACjD,EACE,uBAAA,IAAA,CAAC,SAAK,GAAG,cAAA,EAAgB,WAAW,EAAG,CAAA,SAAA,EAAW,SAAS,CACxD,EAAA,QAAA,EAAA;AAAA,IACC,YAAA,mBAAA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,GAAG,SAAS,CAAA,YAAA,CAAA;AAAA,QACvB,WAAU,EAAA,OAAA;AAAA,QACV,KAAO,EAAA,YAAA;AAAA,QACR,QAAA,EAAA;AAAA;AAAA,KAGC,GAAA,KAAA,CAAA;AAAA,oBACJ,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,GAAG,SAAS,CAAA,QAAA,CAAA;AAAA,QACvB,GAAK,EAAA,cAAA;AAAA,QACL,SAAW,EAAA,aAAA;AAAA,QAEV,QAAA,EAAA,MAAA,CAAO,GAAI,CAAA,CAAC,KACX,qBAAA,IAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,GAAG,SAAS,CAAA,MAAA,CAAA;AAAA,YACvB,cAAY,KAAM,CAAA,IAAA;AAAA,YAElB,SAAA,EAAW,KAAM,CAAA,QAAA,GAAW,UAAa,GAAA,UAAA;AAAA,YACzC,UAAU,KAAM,CAAA,QAAA;AAAA,YAChB,gBACE,EAAA,iBAAA,CAAkB,KAAM,CAAA,IAAI,IAAI,OAAU,GAAA,KAAA,CAAA;AAAA,YAG5C,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,cAAgB,EAAA,EAAA,QAAA,EAAA,KAAA,EAAO,KAAS,IAAA,KAAA,CAAM,WAAY,EAAA,CAAA;AAAA,cAClD,eAAe,KAAK,CAAA;AAAA,kCACpB,mBACE,EAAA,EAAA,QAAA,EAAA,iBAAA,CAAkB,KAAM,CAAA,IAAI,KAAK,EACpC,EAAA;AAAA;AAAA,WAAA;AAAA,UAXK,KAAM,CAAA;AAAA,SAad;AAAA;AAAA,KACH;AAAA,oBACC,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,CAAA,EAAG,SAAS,CAC1B,uCAAA,CAAA,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,IAAK,EAAA,QAAA;AAAA,UACL,OAAQ,EAAA,KAAA;AAAA,UACR,UAAU,CAAC,OAAA;AAAA,UACX,OAAS,EAAA,YAAA;AAAA,UACV,QAAA,EAAA;AAAA;AAAA,OAED;AAAA,0BACC,MAAO,EAAA,EAAA,OAAA,EAAQ,WAAY,EAAA,OAAA,EAAS,cAAc,QAEnD,EAAA,QAAA,EAAA;AAAA,KACF,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
package/package.json CHANGED
@@ -1,22 +1,23 @@
1
1
  {
2
- "version": "0.11.2",
2
+ "version": "0.12.0",
3
3
  "author": "heswell",
4
4
  "license": "Apache-2.0",
5
5
  "devDependencies": {
6
- "@vuu-ui/vuu-data-types": "0.11.2",
7
- "@vuu-ui/vuu-filter-types": "0.11.2",
8
- "@vuu-ui/vuu-popups": "0.11.2",
9
- "@vuu-ui/vuu-protocol-types": "0.11.2",
10
- "@vuu-ui/vuu-table-types": "0.11.2"
6
+ "@vuu-ui/vuu-data-types": "0.12.0",
7
+ "@vuu-ui/vuu-filter-types": "0.12.0",
8
+ "@vuu-ui/vuu-popups": "0.12.0",
9
+ "@vuu-ui/vuu-protocol-types": "0.12.0",
10
+ "@vuu-ui/vuu-table-types": "0.12.0"
11
11
  },
12
12
  "dependencies": {
13
- "@vuu-ui/vuu-data-remote": "0.11.2",
14
- "@vuu-ui/vuu-filter-parser": "0.11.2",
15
- "@vuu-ui/vuu-layout": "0.11.2",
16
- "@vuu-ui/vuu-popups": "0.11.2",
17
- "@vuu-ui/vuu-ui-controls": "0.11.2",
18
- "@vuu-ui/vuu-utils": "0.11.2",
19
- "@vuu-ui/vuu-table": "0.11.2",
13
+ "@vuu-ui/vuu-context-menu": "0.12.0",
14
+ "@vuu-ui/vuu-data-remote": "0.12.0",
15
+ "@vuu-ui/vuu-filter-parser": "0.12.0",
16
+ "@vuu-ui/vuu-layout": "0.12.0",
17
+ "@vuu-ui/vuu-popups": "0.12.0",
18
+ "@vuu-ui/vuu-ui-controls": "0.12.0",
19
+ "@vuu-ui/vuu-utils": "0.12.0",
20
+ "@vuu-ui/vuu-table": "0.12.0",
20
21
  "@salt-ds/core": "1.43.0",
21
22
  "@salt-ds/styles": "0.2.1",
22
23
  "@salt-ds/window": "0.1.1"
@@ -1,4 +1,4 @@
1
- import { DataSource, TableSchema } from "@vuu-ui/vuu-data-types";
1
+ import type { DataSource, TableSchema } from "@vuu-ui/vuu-data-types";
2
2
  export declare const useSessionDataSource: ({ dataSourceSessionKey, tableSchema, }: {
3
3
  dataSourceSessionKey?: string;
4
4
  tableSchema: TableSchema;
@@ -1,9 +1,11 @@
1
- import { DataSource, DataSourceVisualLinkCreatedMessage, MenuActionHandler, MenuBuilder, RpcResponseHandler } from "@vuu-ui/vuu-data-types";
2
- import type { LinkDescriptorWithLabel, VuuMenu } from "@vuu-ui/vuu-protocol-types";
3
- export type VuuMenuActionHandler = (type: string, options: unknown) => boolean;
4
- export interface ViewServerHookResult {
5
- buildViewserverMenuOptions: MenuBuilder;
6
- handleMenuAction: MenuActionHandler;
1
+ import { type MenuActionHandler, type MenuBuilder } from "@vuu-ui/vuu-context-menu";
2
+ import { DataSource, DataSourceVisualLinkCreatedMessage, RpcResponseHandler } from "@vuu-ui/vuu-data-types";
3
+ import type { LinkDescriptorWithLabel, VuuDataRowDto, VuuMenu, VuuMenuItem, VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
4
+ import { TableContextMenuOptions, TableMenuLocation } from "@vuu-ui/vuu-table";
5
+ import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
6
+ export interface VuuMenuActionHookResult {
7
+ menuBuilder: MenuBuilder<TableMenuLocation, TableContextMenuOptions>;
8
+ menuActionHandler: MenuActionHandler;
7
9
  }
8
10
  export interface MenuActionConfig {
9
11
  vuuMenu?: VuuMenu;
@@ -20,9 +22,23 @@ export interface VuuMenuActionHookProps {
20
22
  * actioned, even when no custom handling is intended. If the handler returns false,
21
23
  * Vuu will process the menuItem.
22
24
  */
23
- clientSideMenuActionHandler?: VuuMenuActionHandler;
25
+ clientSideMenuActionHandler?: MenuActionHandler;
24
26
  dataSource?: DataSource;
25
27
  menuActionConfig?: MenuActionConfig;
26
28
  onRpcResponse?: RpcResponseHandler;
27
29
  }
28
- export declare const useVuuMenuActions: ({ clientSideMenuActionHandler, dataSource, onRpcResponse, }: VuuMenuActionHookProps) => ViewServerHookResult;
30
+ export interface VuuCellContextMenuItemOptions extends VuuMenuItem {
31
+ rowKey: string;
32
+ field: string;
33
+ value: VuuRowDataItemType;
34
+ }
35
+ export interface VuuRowContextMenuItemOptions extends VuuMenuItem {
36
+ rowKey: string;
37
+ row: VuuDataRowDto;
38
+ }
39
+ export interface VuuSelectedRowsContextMenuItemOptions extends VuuMenuItem {
40
+ columns: ColumnDescriptor[];
41
+ }
42
+ export declare const isRowMenu: (options: VuuMenuItem) => options is VuuRowContextMenuItemOptions;
43
+ export declare const isSelectionMenu: (options: VuuMenuItem) => options is VuuSelectedRowsContextMenuItemOptions;
44
+ export declare const useVuuMenuActions: ({ clientSideMenuActionHandler, dataSource, onRpcResponse, }: VuuMenuActionHookProps) => VuuMenuActionHookResult;