@wavemaker-ai/react-runtime 1.0.0-rc.647712 → 12.0.0-rc.335

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 (106) hide show
  1. package/components/basic/richtexteditor/index.d.ts +1 -0
  2. package/components/basic/search/index.js +5 -4
  3. package/components/basic/search/utils.d.ts +1 -0
  4. package/components/basic/search/utils.js +9 -0
  5. package/components/common/index.d.ts +2 -0
  6. package/components/common/index.js +2 -0
  7. package/components/common/partial-content-wrapper.d.ts +15 -0
  8. package/components/common/partial-content-wrapper.js +11 -0
  9. package/components/container/index.js +5 -2
  10. package/components/container/tabs/index.js +5 -3
  11. package/components/container/wizard/index.js +36 -3
  12. package/components/container/wizard/props.d.ts +2 -2
  13. package/components/data/form/dynamic-fields/WmxDynamicFormField.js +9 -23
  14. package/components/data/form/form-controller/props.d.ts +2 -0
  15. package/components/data/form/form-controller/utils.js +3 -2
  16. package/components/data/form/form-controller/validation-contrustor.js +112 -1
  17. package/components/data/form/form-controller/withFormController.js +1 -1
  18. package/components/data/form/form-field/index.js +6 -3
  19. package/components/data/form/form-field/props.d.ts +1 -0
  20. package/components/data/list/components/ListItemWithTemplate.js +1 -1
  21. package/components/data/list/index.js +1 -1
  22. package/components/data/table/components/EditableCell.js +47 -24
  23. package/components/data/table/components/FieldValidationError.js +1 -1
  24. package/components/data/table/components/TableHeader.js +9 -3
  25. package/components/data/table/hooks/useFormWidget.js +11 -0
  26. package/components/data/table/hooks/useRowSelection.js +58 -1
  27. package/components/data/table/hooks/useTableEdit.d.ts +1 -1
  28. package/components/data/table/hooks/useTableEdit.js +115 -75
  29. package/components/data/table/hooks/useTableEditForms.d.ts +25 -0
  30. package/components/data/table/hooks/useTableEditForms.js +30 -0
  31. package/components/data/table/index.js +68 -32
  32. package/components/data/table/props.d.ts +42 -23
  33. package/components/data/table/utils/buildSelectionColumns.js +3 -3
  34. package/components/data/table/utils/columnProxy.d.ts +7 -1
  35. package/components/data/table/utils/columnProxy.js +21 -1
  36. package/components/data/table/utils/columnValidation.d.ts +19 -0
  37. package/components/data/table/utils/columnValidation.js +76 -0
  38. package/components/data/table/utils/constants.d.ts +2 -0
  39. package/components/data/table/utils/constants.js +2 -0
  40. package/components/data/table/utils/index.d.ts +4 -12
  41. package/components/data/table/utils/index.js +13 -77
  42. package/components/data/table/utils/selectionUtils.js +13 -5
  43. package/components/input/chips/index.d.ts +1 -0
  44. package/components/input/color-picker/index.d.ts +1 -0
  45. package/components/input/currency/index.d.ts +1 -0
  46. package/components/input/default/checkbox/index.d.ts +1 -0
  47. package/components/input/default/checkboxset/index.d.ts +1 -0
  48. package/components/input/default/radioset/index.d.ts +1 -0
  49. package/components/input/default/switch/index.d.ts +1 -0
  50. package/components/input/epoch/datetime/index.js +10 -2
  51. package/components/input/number/index.d.ts +1 -0
  52. package/components/input/rating/index.d.ts +1 -0
  53. package/components/input/select/index.d.ts +1 -0
  54. package/components/input/slider/index.d.ts +1 -0
  55. package/components/input/text/index.d.ts +1 -0
  56. package/components/input/textarea/index.d.ts +1 -0
  57. package/components/input/upload/index.d.ts +1 -0
  58. package/components/layout/footer/index.js +4 -2
  59. package/components/layout/footer/props.d.ts +1 -0
  60. package/components/layout/header/index.js +29 -3
  61. package/components/layout/header/props.d.ts +1 -0
  62. package/components/layout/leftnav/index.js +22 -6
  63. package/components/layout/leftnav/props.d.ts +1 -0
  64. package/components/layout/leftnav/utils/page-class-util.d.ts +1 -0
  65. package/components/layout/leftnav/utils/page-class-util.js +4 -3
  66. package/components/layout/rightnav/index.js +4 -2
  67. package/components/layout/rightnav/props.d.ts +1 -0
  68. package/components/layout/topnav/index.js +4 -2
  69. package/components/layout/topnav/props.d.ts +1 -0
  70. package/components/navbar/index.js +32 -7
  71. package/components/navigation/menu/index.js +6 -2
  72. package/components/page/index.js +60 -19
  73. package/components/page/page-context.d.ts +4 -0
  74. package/core/proxy-service.js +86 -19
  75. package/higherOrder/BaseApp.js +1 -1
  76. package/higherOrder/BasePage.js +2 -1
  77. package/higherOrder/withBaseWrapper.js +10 -2
  78. package/hooks/useHttp.d.ts +14 -4
  79. package/hooks/useHttp.js +47 -9
  80. package/package-lock.json +314 -308
  81. package/package.json +3 -3
  82. package/runtime-dynamic/App.js +21 -2
  83. package/runtime-dynamic/app-initializer.js +8 -1
  84. package/runtime-dynamic/factories/dynamic-component.js +4 -3
  85. package/runtime-dynamic/main.d.ts +1 -0
  86. package/runtime-dynamic/main.js +9 -1
  87. package/runtime-dynamic/services/compile-render.js +7 -0
  88. package/runtime-dynamic/services/css-scoping.d.ts +1 -1
  89. package/runtime-dynamic/services/css-scoping.js +2 -2
  90. package/runtime-dynamic/services/variable-factory.js +2 -1
  91. package/runtime-dynamic/services/variable-transpiler.js +4 -1
  92. package/runtime-dynamic/wmx-shared.d.ts +40 -0
  93. package/runtime-dynamic/wmx-shared.js +33 -0
  94. package/utils/style-utils.js +1 -1
  95. package/utils/wmx.utils.d.ts +0 -1
  96. package/utils/wmx.utils.js +0 -25
  97. package/variables/crud-variable.d.ts +10 -0
  98. package/variables/crud-variable.js +53 -2
  99. package/variables/live-variable.d.ts +1 -0
  100. package/variables/live-variable.js +2 -1
  101. package/variables/operation-params.d.ts +29 -0
  102. package/variables/operation-params.js +69 -0
  103. package/variables/service-variable.d.ts +9 -0
  104. package/variables/service-variable.js +21 -2
  105. package/components/data/table/utils/validation.d.ts +0 -13
  106. package/components/data/table/utils/validation.js +0 -82
@@ -0,0 +1,30 @@
1
+ import { useMemo } from "react";
2
+ import { useForm } from "react-hook-form";
3
+ const EDIT_FORM_OPTIONS = {
4
+ mode: "onChange",
5
+ // Validate on blur (widgets use updateon="blur")
6
+ shouldUnregister: true
7
+ // Drop field on unmount; prevents orphaned errors
8
+ };
9
+ const useTableEditForm = (tableName) => {
10
+ const { control, trigger, setValue, setError, reset, getFieldState } = useForm(EDIT_FORM_OPTIONS);
11
+ return useMemo(
12
+ () => ({
13
+ formRef: { control, trigger, name: tableName, validationtype: "default" },
14
+ validate: () => trigger(),
15
+ getInvalidFields: (fieldNames) => fieldNames.filter((fieldName) => getFieldState(fieldName).invalid),
16
+ setFieldValue: (fieldName, value) => setValue(fieldName, value, { shouldValidate: false, shouldDirty: true }),
17
+ setFieldError: (fieldName, message) => setError(fieldName, { type: "native", message }),
18
+ reset: () => reset()
19
+ }),
20
+ [control, trigger, setValue, setError, reset, getFieldState, tableName]
21
+ );
22
+ };
23
+ const useTableEditForms = (tableName) => {
24
+ const editForm = useTableEditForm(tableName);
25
+ const newRowForm = useTableEditForm(tableName);
26
+ return { editForm, newRowForm };
27
+ };
28
+ export {
29
+ useTableEditForms
30
+ };
@@ -446,7 +446,9 @@ const WmTableComponent = memo(
446
446
  handleMultiSelection,
447
447
  handleSelectAll,
448
448
  handleRowSelectionClick,
449
- isRowSelected
449
+ isRowSelected,
450
+ selectItem,
451
+ deselectItem
450
452
  } = useRowSelection({
451
453
  radioselect,
452
454
  multiselect: effectiveMultiselect,
@@ -532,6 +534,7 @@ const WmTableComponent = memo(
532
534
  }),
533
535
  [wmTableColumns, columnOverrides]
534
536
  );
537
+ const columnValidatorsRef = useRef({});
535
538
  const {
536
539
  editingRowId,
537
540
  isRowEditing,
@@ -577,7 +580,8 @@ const WmTableComponent = memo(
577
580
  onRowdelete,
578
581
  tableRef,
579
582
  isServerSidePagination: isServerSidePagination(),
580
- tableName: name
583
+ tableName: name,
584
+ columnValidatorsRef
581
585
  });
582
586
  const { handleRowClick } = useRowHandlers({
583
587
  editingRowId,
@@ -756,7 +760,13 @@ const WmTableComponent = memo(
756
760
  []
757
761
  );
758
762
  const columnsProxy = useMemo(
759
- () => createColumnsProxy(wmTableColumns, applyOverride, setColumnsVersion, setSummaryRowDef),
763
+ () => createColumnsProxy(
764
+ wmTableColumns,
765
+ applyOverride,
766
+ setColumnsVersion,
767
+ setSummaryRowDef,
768
+ columnValidatorsRef.current
769
+ ),
760
770
  [wmTableColumns, applyOverride, setColumnsVersion, setSummaryRowDef]
761
771
  );
762
772
  const {
@@ -969,6 +979,23 @@ const WmTableComponent = memo(
969
979
  },
970
980
  [name]
971
981
  );
982
+ const selectItemRef = useRef(selectItem);
983
+ const deselectItemRef = useRef(deselectItem);
984
+ selectItemRef.current = selectItem;
985
+ deselectItemRef.current = deselectItem;
986
+ const widgetSelectItem = useCallback((itemOrIndex) => {
987
+ selectItemRef.current(itemOrIndex);
988
+ }, []);
989
+ const widgetDeselectItem = useCallback((itemOrIndex) => {
990
+ deselectItemRef.current(itemOrIndex);
991
+ }, []);
992
+ useEffect(() => {
993
+ var _a2;
994
+ (_a2 = listener == null ? void 0 : listener.onChange) == null ? void 0 : _a2.call(listener, widgetRegistrationKey, {
995
+ selectItem: widgetSelectItem,
996
+ deselectItem: widgetDeselectItem
997
+ });
998
+ });
972
999
  const sortInfoForExport = useMemo(() => {
973
1000
  if (sorting.length > 0) {
974
1001
  return {
@@ -1355,7 +1382,10 @@ const WmTableComponent = memo(
1355
1382
  datasource,
1356
1383
  dataset,
1357
1384
  selectPageSize,
1358
- rowDefInstances
1385
+ rowDefInstances,
1386
+ // Angular parity: table.selectItem / table.deselectItem (accepts a row or an index).
1387
+ selectItem: widgetSelectItem,
1388
+ deselectItem: widgetDeselectItem
1359
1389
  };
1360
1390
  const getRowId = (row) => row._wmTableRowId || String(row.id);
1361
1391
  const pushSelectedItemsToWidget = (selectedIds) => {
@@ -1525,34 +1555,40 @@ const WmTableComponent = memo(
1525
1555
  } : {})
1526
1556
  }, { name }), {
1527
1557
  children: [
1528
- showheader && wmTableColumns.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1529
- /* @__PURE__ */ jsx(
1530
- TableHeaderComponent,
1531
- {
1532
- table,
1533
- enablesort,
1534
- enablecolumnselection,
1535
- rowClass,
1536
- ColClassSignature,
1537
- sorting,
1538
- columnSizing,
1539
- rowSelection,
1540
- rowExpansionConfig: visibleRowExpansionConfig,
1541
- columnsVersion,
1542
- filterMode: filtermode,
1543
- columnFilters,
1544
- onColumnFilterChange: setColumnFilter,
1545
- renderFormWidget,
1546
- listener,
1547
- tableStructure,
1548
- onColumnSelect: handleColumnSelect,
1549
- onColumnDeselect: handleColumnDeselect,
1550
- onHeaderclick,
1551
- tableName: name
1552
- }
1553
- ),
1554
- /* @__PURE__ */ jsx("colgroup", { children: colGroupSpec.map((c) => /* @__PURE__ */ jsx("col", { style: c.style, width: c.width }, c.key)) })
1555
- ] }),
1558
+ colGroupSpec.length > 0 && /* @__PURE__ */ jsx("colgroup", { children: colGroupSpec.map((c) => /* @__PURE__ */ jsx(
1559
+ "col",
1560
+ __spreadValues({
1561
+ style: c.style,
1562
+ width: c.width
1563
+ }, c.domHidden ? { "data-wm-col-hidden": "" } : {}),
1564
+ c.key
1565
+ )) }),
1566
+ showheader && wmTableColumns.length > 0 && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
1567
+ TableHeaderComponent,
1568
+ {
1569
+ table,
1570
+ enablesort,
1571
+ enablecolumnselection,
1572
+ rowClass,
1573
+ ColClassSignature,
1574
+ sorting,
1575
+ columnSizing,
1576
+ rowSelection,
1577
+ rowExpansionConfig: visibleRowExpansionConfig,
1578
+ columnsVersion,
1579
+ filterMode: filtermode,
1580
+ columnFilters,
1581
+ onColumnFilterChange: setColumnFilter,
1582
+ renderFormWidget,
1583
+ listener,
1584
+ viewParent,
1585
+ tableStructure,
1586
+ onColumnSelect: handleColumnSelect,
1587
+ onColumnDeselect: handleColumnDeselect,
1588
+ onHeaderclick,
1589
+ tableName: name
1590
+ }
1591
+ ) }),
1556
1592
  (internalDataset.length > 0 || !isTableLoading) && /* @__PURE__ */ jsx(
1557
1593
  TableBodyComponent,
1558
1594
  {
@@ -6,6 +6,9 @@ import { IAlignment, INavigation } from "../list/props";
6
6
  import { EditWidgetType } from "./utils";
7
7
  import { StorageType } from "../../../utils/state-persistance";
8
8
  import { LiveVariableConfig } from "@wavemaker-ai/react-runtime/variables/live-variable";
9
+ import { ValidatorConfig } from "@wavemaker-ai/react-runtime/components/data/form/form-controller/props";
10
+ import { ColumnValidatorRegistry } from "./utils/columnValidation";
11
+ import { TableEditFormRef } from "./hooks/useTableEditForms";
9
12
  export type TableEditMode = "inline" | "dialog" | "form" | "quickedit" | "none";
10
13
  export type TableActionPosition = "header" | "footer";
11
14
  export type TableFormPosition = "top" | "bottom";
@@ -820,6 +823,7 @@ export interface TableHeaderProps {
820
823
  columnsVersion?: number;
821
824
  filterMode?: TableFilterMode;
822
825
  listener: any;
826
+ viewParent?: any;
823
827
  columnFilters?: Record<string, any>;
824
828
  onColumnFilterChange?: (columnId: string, value: string, matchMode?: string) => void;
825
829
  renderFormWidget: (fieldName: string, widgetType: string, value: any, onChange: (value: any) => void, additionalProps?: any) => React.ReactNode;
@@ -854,7 +858,7 @@ export interface AddNewRowProps {
854
858
  sessionKey: number;
855
859
  editingRowData: Record<string, any>;
856
860
  renderEditableCell: (column: WmTableColumnProps, fieldName: string, widgetType: string, editValue: any, rowId: string) => ReactElement;
857
- onKeyDown?: (e: KeyboardEvent, sourceRowId?: string) => void;
861
+ onKeyDown?: (e: React.KeyboardEvent, sourceRowId?: string) => void;
858
862
  handleSave: () => void;
859
863
  handleCancel: () => void;
860
864
  listener?: any;
@@ -868,13 +872,17 @@ export interface EditableCellProps {
868
872
  fieldName: string;
869
873
  widgetType: string;
870
874
  editValue: any;
871
- fieldValidationErrorsRef: RefObject<Record<string, boolean>>;
872
- cellUpdateCallbacksRef: RefObject<Record<string, () => void>>;
875
+ /** The react-hook-form instance for this edit session, handed to the cell's widget. */
876
+ formRef: TableEditFormRef;
877
+ /** Shared `${rowId}_${fieldName}` -> true map of cells currently in error. */
878
+ cellErrorsRef?: RefObject<Record<string, boolean>>;
879
+ /** Cell containers, keyed `${rowId}_${fieldName}`. */
873
880
  fieldRefs: RefObject<Record<string, HTMLElement | null>>;
874
- renderFormWidget: (name: string, type: string, value: any, onChange: (newValue: any) => void, props: any) => ReactElement;
881
+ columnValidatorsRef?: RefObject<ColumnValidatorRegistry>;
882
+ renderFormWidget: (name: string, type: string, value: any, onChange: (newValue: any) => void, props: TableEditWidgetProps) => ReactElement;
875
883
  updateFieldValue: (fieldName: string, newValue: any, rowId?: string) => void;
876
884
  sessionKey?: number;
877
- onKeyDown?: (e: KeyboardEvent, sourceRowId?: string) => void;
885
+ onKeyDown?: (e: React.KeyboardEvent, sourceRowId?: string) => void;
878
886
  editMode?: TableEditMode;
879
887
  validationmessage?: string;
880
888
  }
@@ -980,14 +988,32 @@ export interface UseTableDataReturn {
980
988
  export interface UseFormWidgetProps {
981
989
  listener?: any;
982
990
  }
991
+ /** Everything an editable cell hands to its edit widget beyond the value itself. */
992
+ export interface TableEditWidgetProps {
993
+ required?: boolean;
994
+ disabled?: boolean;
995
+ placeholder?: string;
996
+ defaultvalue?: string | number | boolean;
997
+ sessionKey?: string | number;
998
+ rowData?: any;
999
+ column?: any;
1000
+ /**
1001
+ * The edit session's react-hook-form instance. `withFormController` validates the widget
1002
+ * against it and, from the same validators, derives the date/time bounds the picker enforces
1003
+ * on its own input.
1004
+ */
1005
+ formRef?: TableEditFormRef;
1006
+ /** Form field name for the cell — the column field, independent of the row. */
1007
+ formKey?: string;
1008
+ /** Validators set by a page script via `columns.<name>.setValidators([...])`. */
1009
+ validators?: ValidatorConfig[];
1010
+ /** Validators set via `columns.<name>.setAsyncValidators([...])`. */
1011
+ asyncValidators?: ValidatorConfig[];
1012
+ /** Keep the widget out of the form entirely (hidden columns). */
1013
+ ignoreInForm?: boolean;
1014
+ }
983
1015
  export interface UseFormWidgetReturn {
984
- renderFormWidget: (fieldName: string, widgetType: string, value: any, onFieldChange?: (newValue: any) => void, widgetProps?: {
985
- required?: boolean;
986
- disabled?: boolean;
987
- placeholder?: string;
988
- defaultvalue?: string | number | boolean;
989
- sessionKey?: string | number;
990
- }) => ReactElement;
1016
+ renderFormWidget: (fieldName: string, widgetType: string, value: any, onFieldChange?: (newValue: any) => void, widgetProps?: TableEditWidgetProps) => ReactElement;
991
1017
  }
992
1018
  export interface UseTableEditProps {
993
1019
  editMode?: TableEditMode;
@@ -1020,6 +1046,8 @@ export interface UseTableEditProps {
1020
1046
  onRowupdate?: (event: any, widget: any, data: any) => void;
1021
1047
  tableRef?: React.RefObject<any>;
1022
1048
  isServerSidePagination?: boolean;
1049
+ /** Validators set by a page script via `columns.<name>.setValidators([...])`. */
1050
+ columnValidatorsRef?: RefObject<Record<string, any>>;
1023
1051
  }
1024
1052
  export interface UseTableEditReturn {
1025
1053
  editingRowId: string | null;
@@ -1128,6 +1156,8 @@ export interface UseRowSelectionReturn {
1128
1156
  handleRowSelectionClick: (event: MouseEvent, rowId: string, rowData: any) => boolean;
1129
1157
  isRowSelected: (rowId: string) => boolean;
1130
1158
  isInteractiveElement: (event: MouseEvent) => boolean;
1159
+ selectItem: (itemOrIndex: any) => void;
1160
+ deselectItem: (itemOrIndex: any) => void;
1131
1161
  }
1132
1162
  export interface UseTableStateProps {
1133
1163
  editMode?: TableEditMode;
@@ -1302,17 +1332,6 @@ export interface UseRowExpansionReturn {
1302
1332
  registerRowDefInstance: (rowId: string, instance: any, rowData?: any) => void;
1303
1333
  rowDefInstances: Record<string, any>;
1304
1334
  }
1305
- export interface FieldValidationState {
1306
- fieldRefs: RefObject<Record<string, HTMLElement | null>>;
1307
- fieldValidationErrors: RefObject<Record<string, boolean>>;
1308
- cellUpdateCallbacks: RefObject<Record<string, () => void>>;
1309
- }
1310
- export interface ValidationResult {
1311
- isValid: boolean;
1312
- invalidElements: HTMLElement[];
1313
- invalidFieldKeys?: string[];
1314
- firstInvalidElement?: HTMLElement;
1315
- }
1316
1335
  /**
1317
1336
  * Interface for summary row value with optional styling
1318
1337
  */
@@ -10,7 +10,7 @@ function RadioSelectCell(ctx) {
10
10
  const rowId = row.id;
11
11
  const isSelected = row.getIsSelected();
12
12
  const { handleRadioSelection, radioselecttitle, radioselectarialabel, tableName } = getSelectionMeta(ctx);
13
- return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx(Tooltip, { title: radioselecttitle != null ? radioselecttitle : "", placement: "top", children: /* @__PURE__ */ jsx(Box, { className: "radio app-radio", children: /* @__PURE__ */ jsxs(Box, { component: "label", children: [
13
+ return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "center" }, "data-role": "select-row", children: /* @__PURE__ */ jsx(Tooltip, { title: radioselecttitle != null ? radioselecttitle : "", placement: "top", children: /* @__PURE__ */ jsx(Box, { className: "radio app-radio", children: /* @__PURE__ */ jsxs(Box, { component: "label", children: [
14
14
  /* @__PURE__ */ jsx(
15
15
  Box,
16
16
  {
@@ -33,7 +33,7 @@ function MultiSelectCell(ctx) {
33
33
  const rowId = row.id;
34
34
  const isSelected = row.getIsSelected();
35
35
  const { handleMultiSelection, multiselecttitle, multiselectarialabel } = getSelectionMeta(ctx);
36
- return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex" }, children: [
36
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex" }, "data-role": "select-row", children: [
37
37
  /* @__PURE__ */ jsx(Tooltip, { title: multiselecttitle != null ? multiselecttitle : "", placement: "top", children: /* @__PURE__ */ jsx(Box, { className: "app-checkbox checkbox", children: /* @__PURE__ */ jsxs(Box, { component: "label", className: isSelected ? "" : "unchecked", children: [
38
38
  /* @__PURE__ */ jsx(Box, { component: "span", className: "sr-only", "aria-live": "assertive", children: "Select row" }),
39
39
  /* @__PURE__ */ jsx(
@@ -59,7 +59,7 @@ function MultiSelectHeader({ table, column }) {
59
59
  var _a, _b;
60
60
  const isAllSelected = table.getIsAllRowsSelected();
61
61
  const { handleSelectAll } = (_b = (_a = column.columnDef.meta) == null ? void 0 : _a.selection) != null ? _b : {};
62
- return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", width: "100%" }, children: /* @__PURE__ */ jsx(Box, { className: "app-checkbox checkbox", children: /* @__PURE__ */ jsxs(Box, { component: "label", className: isAllSelected ? "" : "unchecked", children: [
62
+ return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", width: "100%" }, "data-role": "select-all", children: /* @__PURE__ */ jsx(Box, { className: "app-checkbox checkbox", children: /* @__PURE__ */ jsxs(Box, { component: "label", className: isAllSelected ? "" : "unchecked", children: [
63
63
  /* @__PURE__ */ jsx(
64
64
  Box,
65
65
  {
@@ -1,3 +1,5 @@
1
+ import { ValidatorConfig } from "@wavemaker-ai/react-runtime/components/data/form/form-controller/props";
2
+ import { ColumnValidatorRegistry } from "./columnValidation";
1
3
  export declare const keyMap: {
2
4
  [key: string]: string;
3
5
  };
@@ -17,5 +19,9 @@ export interface ColumnAggregate {
17
19
  export interface EnhancedColumnProxy {
18
20
  aggregate: ColumnAggregate;
19
21
  setSummaryRowData: (data: SummaryRowData | SummaryRowData[]) => void;
22
+ setValidators: (validators: ValidatorConfig[]) => void;
23
+ setAsyncValidators: (asyncValidators: ValidatorConfig[]) => void;
20
24
  }
21
- export declare function createColumnsProxy(wmTableColumns: any[], applyOverride: (field: string, key: string, value: any) => void, setColumnsVersion?: (updater: (v: number) => number) => void, setSummaryRowDef?: (columnKey: string, data: any, rowIndex: number, refresh: boolean, show?: boolean) => void): Record<string, any>;
25
+ export declare function createColumnsProxy(wmTableColumns: any[], applyOverride: (field: string, key: string, value: any) => void, setColumnsVersion?: (updater: (v: number) => number) => void, setSummaryRowDef?: (columnKey: string, data: any, rowIndex: number, refresh: boolean, show?: boolean) => void,
26
+ /** Live validator store, held in a ref so script calls survive column-def rebuilds. */
27
+ validatorRegistry?: ColumnValidatorRegistry): Record<string, any>;
@@ -17,6 +17,9 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ import {
21
+ storeColumnValidators
22
+ } from "./columnValidation";
20
23
  const keyMap = {
21
24
  caption: "header",
22
25
  name: "accessorKey",
@@ -29,7 +32,7 @@ const keyMap = {
29
32
  "col-class": "meta.className",
30
33
  style: "meta"
31
34
  };
32
- function createColumnsProxy(wmTableColumns, applyOverride, setColumnsVersion, setSummaryRowDef) {
35
+ function createColumnsProxy(wmTableColumns, applyOverride, setColumnsVersion, setSummaryRowDef, validatorRegistry) {
33
36
  const proxy = {};
34
37
  wmTableColumns.forEach((col, idx) => {
35
38
  const key = col.field;
@@ -39,11 +42,28 @@ function createColumnsProxy(wmTableColumns, applyOverride, setColumnsVersion, se
39
42
  const newData = Array.isArray(data) ? data : [data];
40
43
  invokeSummaryRowData(key, newData, setSummaryRowDef, columnShow);
41
44
  };
45
+ const storeValidators = (kind, method) => (validators) => {
46
+ if (!validatorRegistry) {
47
+ console.warn(
48
+ `${method} called on column "${key}" before the table wired up validation.`
49
+ );
50
+ return;
51
+ }
52
+ storeColumnValidators(validatorRegistry, key, kind, validators);
53
+ };
54
+ const setValidators = storeValidators("validators", "setValidators");
55
+ const setAsyncValidators = storeValidators("asyncValidators", "setAsyncValidators");
42
56
  proxy[key] = new Proxy(col, {
43
57
  get(target, prop) {
44
58
  if (prop === "setSummaryRowData") {
45
59
  return setSummaryRowData;
46
60
  }
61
+ if (prop === "setValidators") {
62
+ return setValidators;
63
+ }
64
+ if (prop === "setAsyncValidators") {
65
+ return setAsyncValidators;
66
+ }
47
67
  return target[prop];
48
68
  },
49
69
  set(target, prop, value) {
@@ -0,0 +1,19 @@
1
+ import { ValidatorConfig } from "@wavemaker-ai/react-runtime/components/data/form/form-controller/props";
2
+ import { WmTableColumnProps } from "../props";
3
+ export interface ColumnValidators {
4
+ /** From `columns.<field>.setValidators([...])`. */
5
+ validators: ValidatorConfig[];
6
+ /** From `columns.<field>.setAsyncValidators([...])`. */
7
+ asyncValidators: ValidatorConfig[];
8
+ }
9
+ export type ColumnValidatorRegistry = Record<string, ColumnValidators>;
10
+ export declare const isColumnValidatable: (column: WmTableColumnProps | undefined) => boolean;
11
+ export declare const cloneValidators: (validators: ValidatorConfig[]) => ValidatorConfig[];
12
+ export declare const storeColumnValidators: (registry: ColumnValidatorRegistry, field: string, kind: keyof ColumnValidators, validators: ValidatorConfig[]) => void;
13
+ export interface NativeValidityError {
14
+ /** The column field, i.e. the react-hook-form field name for the cell. */
15
+ fieldName: string;
16
+ message: string;
17
+ }
18
+ export declare const collectNativeValidityErrors: (cellElements: Record<string, HTMLElement | null>, rowId: string) => NativeValidityError[];
19
+ export declare const focusFirstInvalidCell: (cellElements: Record<string, HTMLElement | null>, rowId: string, invalidFieldNames: string[]) => void;
@@ -0,0 +1,76 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ import { cloneDeep } from "lodash-es";
21
+ const isColumnValidatable = (column) => {
22
+ if (!column || !column.field) return false;
23
+ if (column.readonly) return false;
24
+ if (column.show === false) return false;
25
+ return true;
26
+ };
27
+ const cloneValidators = (validators) => Array.isArray(validators) ? cloneDeep(validators) : [];
28
+ const storeColumnValidators = (registry, field, kind, validators) => {
29
+ const current = registry[field] || { validators: [], asyncValidators: [] };
30
+ registry[field] = __spreadProps(__spreadValues({}, current), { [kind]: cloneValidators(validators) });
31
+ };
32
+ const NATIVE_VALIDITY_FLAGS = [
33
+ "badInput",
34
+ "typeMismatch",
35
+ "stepMismatch",
36
+ "rangeOverflow",
37
+ "rangeUnderflow",
38
+ "tooLong",
39
+ "tooShort"
40
+ ];
41
+ const hasNativeError = (input) => !input.validity.valid && NATIVE_VALIDITY_FLAGS.some((flag) => input.validity[flag]);
42
+ const collectNativeValidityErrors = (cellElements, rowId) => {
43
+ const errors = [];
44
+ const prefix = `${rowId}_`;
45
+ for (const [fieldKey, element] of Object.entries(cellElements)) {
46
+ if (!element || !fieldKey.startsWith(prefix)) continue;
47
+ const fieldName = element.getAttribute("data-field-name") || fieldKey.slice(prefix.length);
48
+ const inputs = Array.from(element.querySelectorAll("input, select, textarea"));
49
+ const invalid = inputs.find(
50
+ (input) => !input.disabled && !("readOnly" in input && input.readOnly) && hasNativeError(input)
51
+ );
52
+ if (invalid) {
53
+ errors.push({ fieldName, message: invalid.validationMessage || "Value is not valid" });
54
+ }
55
+ }
56
+ return errors;
57
+ };
58
+ const focusFirstInvalidCell = (cellElements, rowId, invalidFieldNames) => {
59
+ var _a;
60
+ for (const fieldName of invalidFieldNames) {
61
+ const target = (_a = cellElements[`${rowId}_${fieldName}`]) == null ? void 0 : _a.querySelector(
62
+ "[focus-target], input, textarea, select"
63
+ );
64
+ if (target) {
65
+ target.focus();
66
+ return;
67
+ }
68
+ }
69
+ };
70
+ export {
71
+ cloneValidators,
72
+ collectNativeValidityErrors,
73
+ focusFirstInvalidCell,
74
+ isColumnValidatable,
75
+ storeColumnValidators
76
+ };
@@ -44,5 +44,7 @@ export declare const TABLE_MESSAGES: {
44
44
  export declare const INTERACTIVE_CLASSES: readonly ["MuiInputBase", "MuiSelect", "MuiButton", "MuiCheckbox", "MuiRadio", "MuiSlider", "MuiSwitch", "MuiTextField", "MuiAutocomplete", "MuiChip", "MuiRating", "MuiToggleButton", "MuiPickersDay", "MuiDatePicker", "MuiTimePicker", "MuiDateTimePicker", "MuiCalendarPicker", "MuiClockPicker", "MuiColorPicker", "MuiFormControl", "MuiFormGroup", "MuiFormControlLabel", "app-text", "app-textarea", "app-checkbox", "app-slider", "app-currency", "app-switch", "app-select", "app-checkboxset", "app-radioset", "app-date", "app-time", "app-timestamp", "app-rating", "app-datetime", "app-search", "app-chips", "app-colorpicker", "app-calendar", "app-editor"];
45
45
  export declare const INTERACTIVE_ROLES: readonly ["button", "textbox", "combobox", "listbox"];
46
46
  export declare const INTERACTIVE_DATA_ROLES: readonly ["input", "select", "date", "time", "color", "editor", "checkbox", "radio", "slider", "chips", "rating"];
47
+ /** data-role values on the table selection column. Clicks here must not count as interactive widgets. */
48
+ export declare const SELECTION_COLUMN_DATA_ROLES: readonly ["select-all", "select-row"];
47
49
  export declare const INTERACTIVE_TAG_NAMES: readonly ["INPUT", "BUTTON", "SELECT", "TEXTAREA", "A", "LABEL"];
48
50
  export declare const UNSUPPORTED_STATE_PERSISTENCE_TYPES: readonly string[];
@@ -104,6 +104,7 @@ const INTERACTIVE_DATA_ROLES = [
104
104
  "chips",
105
105
  "rating"
106
106
  ];
107
+ const SELECTION_COLUMN_DATA_ROLES = ["select-all", "select-row"];
107
108
  const INTERACTIVE_TAG_NAMES = [
108
109
  "INPUT",
109
110
  "BUTTON",
@@ -122,6 +123,7 @@ export {
122
123
  INTERACTIVE_DATA_ROLES,
123
124
  INTERACTIVE_ROLES,
124
125
  INTERACTIVE_TAG_NAMES,
126
+ SELECTION_COLUMN_DATA_ROLES,
125
127
  TABLE_CSS_CLASSES,
126
128
  TABLE_DATA_STATES,
127
129
  TABLE_MESSAGES,
@@ -1,5 +1,5 @@
1
1
  import React, { type CSSProperties } from "react";
2
- import { WmTableColumnProps, WmTableRowActionProps, WmTableRowProps, WmTableActionProps, ValidationResult } from "../props";
2
+ import { WmTableColumnProps, WmTableRowActionProps, WmTableRowProps, WmTableActionProps } from "../props";
3
3
  declare const formWidgets: readonly ["WmText", "WmTextarea", "WmCheckbox", "WmSlider", "WmCurrency", "WmSwitch", "WmSelect", "WmCheckboxSet", "WmRadioSet", "WmDate", "WmTime", "WmTimestamp", "WmRating", "WmDatetime", "WmSearch", "WmChips", "WmColorPicker"];
4
4
  type FormWidgetType = (typeof formWidgets)[number];
5
5
  export type EditWidgetType = FormWidgetType;
@@ -69,15 +69,6 @@ export declare const isDeleteAction: (actionKey: string) => boolean;
69
69
  export declare const isAddNewAction: (actionKey: string) => boolean;
70
70
  export declare const getActionButtonClass: (action: WmTableRowActionProps) => string;
71
71
  export declare const getTableActionButtonClass: (action: WmTableActionProps) => string;
72
- /**
73
- * Validates editing fields and focuses first invalid field if validation fails
74
- * Can be used across different edit modes (inline, dialog, quick edit)
75
- *
76
- * @param fieldRefs - Record of field references from editing form
77
- * @param editingRowId - Optional ID for logging/debugging purposes
78
- * @returns ValidationResult object with validation status and invalid elements
79
- */
80
- export declare const validateEditingFields: (fieldRefs: Record<string, HTMLElement | null>, editingRowId?: string) => ValidationResult;
81
72
  export declare const getButtonClasses: (action: any, spacing?: string, isGridEditMode?: boolean, isLoading?: boolean) => string;
82
73
  export declare const getSpacingClasses: (spacing?: string) => string;
83
74
  export declare const shouldShowPagination: ({ shownavigation, onDemandLoad, internalDataset, pagesize, allowpagesizechange, datasource, showrecordcount, }: {
@@ -123,10 +114,11 @@ export declare function getDomHiddenColStyle(meta?: Record<string, unknown>): CS
123
114
  /** Inline style for hidden th/td — display:none and zero box so flex sizing cannot leak width. */
124
115
  export declare function getDomHiddenCellStyle(meta?: Record<string, unknown>): CSSProperties | undefined;
125
116
  export declare const getColClass: (colClass: string, rowData: any, columnName: string) => string;
126
- export { TABLE_CSS_CLASSES, TABLE_DATA_STATES, TABLE_MESSAGES, INTERACTIVE_CLASSES, INTERACTIVE_ROLES, INTERACTIVE_DATA_ROLES, INTERACTIVE_TAG_NAMES, UNSUPPORTED_STATE_PERSISTENCE_TYPES, } from "./constants";
117
+ export { TABLE_CSS_CLASSES, TABLE_DATA_STATES, TABLE_MESSAGES, INTERACTIVE_CLASSES, INTERACTIVE_ROLES, INTERACTIVE_DATA_ROLES, INTERACTIVE_TAG_NAMES, SELECTION_COLUMN_DATA_ROLES, UNSUPPORTED_STATE_PERSISTENCE_TYPES, } from "./constants";
127
118
  export { renderDisplayCell } from "./renderDisplayCell";
128
119
  export { buildSelectionColumns } from "./buildSelectionColumns";
129
- export { validateField, resetValidationState, updateValidationErrors } from "./validation";
120
+ export { cloneValidators, collectNativeValidityErrors, focusFirstInvalidCell, isColumnValidatable, } from "./columnValidation";
121
+ export type { ColumnValidatorRegistry, NativeValidityError } from "./columnValidation";
130
122
  export { hasInteractiveClass, hasInteractiveAttributes, isInteractiveElement, getRowIdsFromDataset, rowExistsInDataset, selectionStateHelpers, } from "./selectionUtils";
131
123
  export { createRowIndexColumn, createDataColumn, createDataColumns, createEditingActionButtons, createDefaultColumnProps, getActionColumnSize, } from "./columnBuilder";
132
124
  export { isDataColumn, hasExplicitWidth, distributeColumnWidths } from "./columnWidthDistribution";