@updog/data-editor 0.1.81 → 0.1.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
 
3
3
  declare var export_default = {
4
4
  ui: {
@@ -417,6 +417,7 @@ declare var export_default = {
417
417
  outOfRange: "Out of range",
418
418
  required: "This field is required",
419
419
  structuralMismatch: "This might be in the wrong column.",
420
+ tooManyDecimals: "Too many decimal places",
420
421
  valueMustBeUnique: "Value must be unique",
421
422
  },
422
423
  license: {
@@ -448,24 +449,6 @@ declare var export_default = {
448
449
  text: "Your subscription is no longer active. Please renew to continue.",
449
450
  },
450
451
  },
451
- scale: {
452
- bootstrap_failed: {
453
- title: "Couldn't connect to the server",
454
- text: "The server returned an error. Please refresh the page or contact support.",
455
- },
456
- workspace_lost: {
457
- title: "Connection lost",
458
- text: "The session ended unexpectedly. Refresh the page to reconnect.",
459
- },
460
- unreachable: {
461
- title: "Server unreachable",
462
- text: "Check your connection and refresh the page.",
463
- },
464
- server_error: {
465
- title: "Server error",
466
- text: "The server returned an error. Please refresh the page or contact support.",
467
- },
468
- },
469
452
  },
470
453
  uploader: {
471
454
  steps: {
@@ -646,11 +629,12 @@ type SortState = {
646
629
  columnId: string;
647
630
  direction: SortDirection;
648
631
  } | null;
632
+ type ErrorFilter = "all" | string[] | null;
649
633
  type Filters = {
650
634
  search: string;
651
635
  matchCase: boolean;
652
636
  matchEntireCell: boolean;
653
- errorMessageFilters: string[];
637
+ errorFilter: ErrorFilter;
654
638
  showOnlyNewRows: boolean;
655
639
  showOnlyEditedRows: boolean;
656
640
  showOnlyEmptyCells: boolean;
@@ -673,104 +657,6 @@ type Filters = {
673
657
  }>;
674
658
  };
675
659
 
676
- /**
677
- * A built-in declarative validator. Mode-symmetric: the SDK ships a TS
678
- * interpreter, the Updog Scale Go binary ships a Go interpreter, and both
679
- * agree on pass/fail outcomes per `api/validators.json`.
680
- */
681
- type BuiltInValidator = {
682
- type: "required";
683
- message?: string;
684
- } | {
685
- type: "regex";
686
- pattern: string;
687
- flags?: string;
688
- message?: string;
689
- } | {
690
- type: "oneOf";
691
- values: string[];
692
- message?: string;
693
- } | {
694
- type: "range";
695
- min?: number;
696
- max?: number;
697
- message?: string;
698
- } | {
699
- type: "email";
700
- message?: string;
701
- } | {
702
- type: "date";
703
- format?: "YYYY-MM-DD" | "DD/MM/YYYY";
704
- message?: string;
705
- } | {
706
- type: "numeric";
707
- message?: string;
708
- } | {
709
- type: "unique";
710
- message?: string;
711
- fn?: UniqueRemoteFn;
712
- };
713
- /** One cell in an asyncFunction batch. Row is passed by reference. */
714
- type AsyncValidatorCell = {
715
- /** Value of the validated column for this cell. */
716
- value: unknown;
717
- /** The full row — for row-dependent checks. */
718
- row: DataEditorRow;
719
- };
720
- /**
721
- * Remote existence check for `{ type: "unique" }`. Called once per sweep
722
- * with all distinct candidate values; report the subset that already exists —
723
- * return it and/or stream it via onChunk (results are unioned). `signal`
724
- * fires only when results can no longer be used. Client-mode only.
725
- */
726
- type UniqueRemoteFn = (values: unknown[], onChunk: (existing: unknown[]) => void, signal: AbortSignal) => Promise<unknown[] | void>;
727
- type AsyncFunctionValidator = {
728
- type: "asyncFunction";
729
- /**
730
- * Called once per column per operation with every affected cell. Report
731
- * failures by `index` into `cells`: return an array aligned with the input
732
- * (null = valid) and/or stream sparse failures via onChunk (unioned, any
733
- * order). `signal` fires only when results can no longer be used.
734
- * Client-mode only. For uniqueness use `unique.fn`, not this.
735
- */
736
- fn: (cells: AsyncValidatorCell[], onChunk: (failures: {
737
- index: number;
738
- error: ValidationError;
739
- }[]) => void, signal: AbortSignal) => Promise<(ValidationError | null)[] | void>;
740
- };
741
- /**
742
- * Server-mode-only escape hatch: an expression evaluated by the Go binary
743
- * via expr-lang. Skipped at runtime in client mode (warned at mount).
744
- */
745
- type ExpressionValidator = {
746
- type: "expression";
747
- expr: string;
748
- message?: string;
749
- };
750
- /**
751
- * Client-mode-only escape hatch: a JS predicate run inline. Dropped (with
752
- * one warn per column) when the SDK serializes the schema for server mode.
753
- */
754
- type FunctionValidator = {
755
- type: "function";
756
- fn: CellValidator;
757
- };
758
- /**
759
- * The validator-rule union accepted by `DataEditorColumn.validators`.
760
- * - Built-ins and `expression` are declarative objects (cross the wire).
761
- * - `function` wraps a `CellValidator`; client-mode-only, dropped+warned in server mode.
762
- *
763
- * Named `ValidatorRule` (not `Validator`) so it doesn't clash with the
764
- * runtime `Validator` class in `core/Validator.ts`.
765
- */
766
- type ValidatorRule = BuiltInValidator | ExpressionValidator | FunctionValidator | AsyncFunctionValidator;
767
- /**
768
- * Async-check state of a cell, orthogonal to errors/misplaced: "pending"
769
- * while a verdict is awaited, "unverified" when the check failed or timed
770
- * out. Idle cells carry no entry.
771
- */
772
- type CellAsyncState = "pending" | "unverified";
773
-
774
660
  /**
775
661
  * Severity level for a validation message.
776
662
  * - `"error"` — a validation failure: marks the row invalid, counts as an error.
@@ -809,13 +695,9 @@ type CellValidator = (value: unknown, row: DataEditorRow) => ValidationError | n
809
695
  type TextEditorCell = {
810
696
  type: "text";
811
697
  };
812
- /** Date picker cell. Optionally restrict the selectable date range. */
698
+ /** Date picker cell. Bounds come from the column's `{ type: "date" }` validator. */
813
699
  type DateEditorCell = {
814
700
  type: "date";
815
- /** Earliest selectable date. */
816
- minDate?: Date;
817
- /** Latest selectable date. */
818
- maxDate?: Date;
819
701
  };
820
702
  /** Dropdown select cell. The user picks from a fixed list of options. */
821
703
  type SelectEditorCell = {
@@ -838,23 +720,19 @@ type MultiSelectEditorCell = {
838
720
  /** Splits a raw imported cell and joins on export. Omitted: import auto-detects, export joins with `", "`. */
839
721
  delimiter?: string;
840
722
  };
841
- /** Number input cell with locale-aware formatting. */
723
+ /** Number input cell with locale-aware formatting. Bounds and decimal digits come from the column's `{ type: "number" }` validator. */
842
724
  type NumberEditorCell = {
843
725
  type: "number";
844
- /** Maximum number of decimal digits allowed. When omitted, decimals are unrestricted. */
845
- decimalPlaces?: number;
846
726
  /** Character used as the decimal point (e.g. `"."` or `","`). Defaults to the browser locale. */
847
727
  decimalSeparator?: string;
848
728
  /** Character inserted between groups of three digits (e.g. `","` or `"."`). Defaults to the browser locale. */
849
729
  thousandsSeparator?: string;
850
- /** Extra characters to allow beyond digits, decimal separator, and minus sign (e.g. `"%-"`). When defined, minus is only kept if explicitly included. */
851
- allowChars?: string;
852
730
  };
853
731
  /**
854
732
  * Controls how a cell is edited.
855
733
  *
856
734
  * - `"text"` — plain text input (default).
857
- * - `"date"` — date picker with optional min/max bounds.
735
+ * - `"date"` — date picker; the calendar honours the column's date validator bounds.
858
736
  * - `"select"` — dropdown with a fixed list of options.
859
737
  * - `"multiselect"` — dropdown allowing zero or more options; stored as `string[]`.
860
738
  * - `"number"` — number input with locale-aware formatting.
@@ -903,7 +781,7 @@ type ColumnLockMode = "all" | "default";
903
781
  * { id: "name", title: "Full Name", size: 200, validators: [{ type: "required", message: "Name is required" }] },
904
782
  * { id: "email", title: "Email", size: 250, validators: [{ type: "required", message: "Email is required" }, { type: "email", message: "Invalid email" }, { type: "unique" }] },
905
783
  * { id: "role", title: "Role", editor: { type: "select", options: ["Admin", "Editor", "Viewer"] } },
906
- * { id: "salary", title: "Salary", validators: [{ type: "numeric", message: "Must be a number" }], formatter: (v) => v ? `$${v}` : "" },
784
+ * { id: "salary", title: "Salary", validators: [{ type: "number", message: "Must be a number" }], formatter: (v) => v ? `$${v}` : "" },
907
785
  * ];
908
786
  * ```
909
787
  */
@@ -914,11 +792,9 @@ type DataEditorColumn = {
914
792
  title: string;
915
793
  /**
916
794
  * One or more validators run on every edit. Accepts:
917
- * - Built-in object literals: `{ type: "required" | "email" | "regex" | "range" | "oneOf" | "date" | "numeric" | "unique", ... }`.
918
- * - `{ type: "expression", expr }` — server-mode only. Warned in client mode.
919
- * - `{ type: "function", fn }` — client-mode only. Dropped+warned in server mode.
920
- *
921
- * See `_specs/VALIDATIONS.md` §4.5 for the per-mode support matrix.
795
+ * - Built-in object literals: `{ type: "required" | "email" | "regex" | "number" | "oneOf" | "date" | "unique", ... }`.
796
+ * - `{ type: "function", fn }` — a JS predicate run inline.
797
+ * - `{ type: "asyncFunction", fn }` — batched remote checks.
922
798
  */
923
799
  validators?: ValidatorRule[];
924
800
  /**
@@ -955,360 +831,91 @@ type DataEditorColumn = {
955
831
  locked?: boolean | ColumnLockMode;
956
832
  };
957
833
 
958
- /** Params passed to `findAndReplace.onFind` when the user types a search query. */
959
- type FindParams = {
960
- /** The search string. */
961
- search: string;
962
- /** When `true`, matching is case-sensitive. */
963
- matchCase?: boolean;
964
- /** When `true`, the entire cell value must equal the search string. */
965
- matchEntireCell?: boolean;
966
- /** Restrict search to these columns. `null` or omitted = all columns. */
967
- columnIds?: string[] | null;
968
- /** Current view filters so the server can scope matches to the active filter set. */
969
- filters?: QueryFilters;
970
- /** Current sort state so match ordering follows the visual row order. */
971
- sort?: SortState;
972
- };
973
- /** A single match location returned by the server. */
974
- type FindMatch = {
975
- /** Row position in the current filtered+sorted view (for grid scrolling). */
976
- rowIndex: number;
977
- /** Column ID where the match occurs. */
978
- columnId: string;
979
- /** Character offset within the cell value (for inline highlight). */
980
- startIndex: number;
981
- /** 0-based position in the ordered match list (for counter display). */
982
- matchIndex: number;
983
- };
984
- /** Response from `findAndReplace.onFind`. */
985
- type FindResponse = {
986
- /** Total number of matches across all rows. */
987
- totalCount: number;
988
- /** The first match. Omit when `totalCount` is 0. */
989
- current?: FindMatch;
990
- };
991
- /** Params passed to `findAndReplace.onNavigate` when the user clicks prev/next. */
992
- type FindNavigateParams = FindParams & {
993
- /** Navigation direction. */
994
- direction: "next" | "prev";
995
- /** Current match position so the server knows where to navigate from. */
996
- currentMatchIndex: number;
997
- };
998
- /** Params passed to `findAndReplace.onReplace`. */
999
- type ReplaceParams = FindParams & {
1000
- /** The replacement text. */
1001
- replacement: string;
1002
- /** When `true`, replace all matches. When omitted or `false`, replace only `target`. */
1003
- all?: boolean;
1004
- /** The specific match to replace. Required when `all` is not `true`. */
1005
- target?: FindMatch;
1006
- };
1007
- /** Response from `findAndReplace.onReplace`. */
1008
- type ReplaceResponse = {
1009
- /** Remaining match count after replacement. */
1010
- totalCount: number;
1011
- /** Next match to navigate to after replacement. Omit when none left. */
1012
- current?: FindMatch;
1013
- };
1014
- /** Server-side find and replace configuration. */
1015
- type FindAndReplaceConfig = {
1016
- /** Called when the user types a search query. Returns total count and first match. */
1017
- onFind: (params: FindParams) => Promise<FindResponse>;
1018
- /** Called when the user clicks prev/next arrows. Returns the target match. */
1019
- onNavigate: (params: FindNavigateParams) => Promise<FindMatch>;
1020
- /** Called when the user clicks Replace or Replace All. */
1021
- onReplace: (params: ReplaceParams) => Promise<ReplaceResponse>;
1022
- };
1023
- type StoreMode = "client" | "server";
1024
- type ServerRowId = string | number;
1025
- /** Row-level status flags returned by the server. Drive row filters and sidebar counts. */
1026
- type ServerRowStatus = {
1027
- edited?: boolean;
1028
- new?: boolean;
1029
- deleted?: boolean;
1030
- hasErrors?: boolean;
1031
- hasEmptyCells?: boolean;
1032
- };
1033
- /** Server-reported change for a single cell. The current value lives in `fields`. */
1034
- type ServerCellChange = {
1035
- original: unknown;
1036
- };
1037
- /** Server-reported validation error for a single cell. */
1038
- type ServerCellError = {
1039
- message: string;
1040
- code?: number | string;
1041
- };
1042
- /** Per-row metadata returned by the server in server-delegated mode. */
1043
- type ServerRowMeta = {
1044
- /** Row-level status flags — drive row filters and sidebar counts. */
1045
- status?: ServerRowStatus;
1046
- /** Cell-level change tracking. Key = field name. */
1047
- changes?: Record<string, ServerCellChange>;
1048
- /** Cell-level validation errors. Key = field name. */
1049
- errors?: Record<string, ServerCellError[]>;
1050
- };
1051
- /** Per-source row count returned by the server. Drives the Data Sources sidebar. */
1052
- type ServerSourceCount = {
1053
- id: string;
1054
- name: string;
1055
- count: number;
1056
- };
1057
- /** Aggregate row counts returned alongside a query page. Drive sidebar indicators. */
1058
- type ServerQueryCounts = {
1059
- edited?: number;
1060
- new?: number;
1061
- deleted?: number;
1062
- errors?: number;
1063
- emptyCells?: number;
1064
- sources?: ServerSourceCount[];
1065
- };
1066
- type ServerRow<T extends DataEditorRow = DataEditorRow> = {
1067
- id: ServerRowId;
1068
- fields: T;
1069
- meta?: ServerRowMeta;
1070
- };
1071
- type ServerResponse<T> = {
1072
- data: T;
1073
- meta?: Record<string, unknown>;
1074
- };
1075
- type QueryFilters<F = Record<string, unknown>> = Partial<Filters> & F;
1076
- type QueryParams<F = Record<string, unknown>> = {
1077
- filters?: QueryFilters<F>;
1078
- sort?: SortState;
1079
- /** When present, only rows belonging to these source IDs are returned. Omit to include all sources. */
1080
- sources?: string[];
1081
- offset?: number;
1082
- limit: number;
1083
- signal?: AbortSignal;
1084
- };
1085
- type QueryResponse<T extends DataEditorRow = DataEditorRow> = ServerResponse<{
1086
- rows: ServerRow<T>[];
1087
- totalCount: number;
1088
- filteredCount?: number;
1089
- counts?: ServerQueryCounts;
1090
- }>;
1091
834
  /**
1092
- * Filter options returned by `onFilterOptions` for populating sidebar filter controls in server mode.
1093
- * Keys are column IDs. Only include columns that have a `filter` configured.
835
+ * A built-in declarative validator a declarative object the SDK interprets.
1094
836
  */
1095
- type FilterOptionsResponse = {
1096
- [columnId: string]: {
1097
- /** Values for `"select"` filters. Raw display strings — no formatter is applied. */
1098
- options?: string[];
1099
- /** Bounds for `"number-range"` filters. */
1100
- range?: {
1101
- min: number;
1102
- max: number;
1103
- };
1104
- /** Bounds for `"date-range"` filters. Values are ISO date strings (YYYY-MM-DD). */
1105
- dateRange?: {
1106
- min: string;
1107
- max: string;
1108
- };
1109
- };
837
+ type BuiltInValidator = {
838
+ type: "required";
839
+ message?: string;
840
+ } | {
841
+ type: "regex";
842
+ pattern: string;
843
+ flags?: string;
844
+ message?: string;
845
+ } | {
846
+ type: "oneOf";
847
+ values: string[];
848
+ message?: string;
849
+ } | {
850
+ type: "number";
851
+ /** Inclusive lower bound. */
852
+ min?: number;
853
+ /** Inclusive upper bound. */
854
+ max?: number;
855
+ /** Maximum decimal digits; `0` means integers. Values with more are flagged, never rounded. */
856
+ decimalPlaces?: number;
857
+ message?: string;
858
+ } | {
859
+ type: "email";
860
+ message?: string;
861
+ } | {
862
+ type: "date";
863
+ min?: string;
864
+ max?: string;
865
+ message?: string;
866
+ } | {
867
+ type: "unique";
868
+ message?: string;
869
+ fn?: UniqueRemoteFn;
1110
870
  };
1111
- type ServerCallOptions = {
1112
- signal: AbortSignal;
871
+ /** One cell in an asyncFunction batch. Row is passed by reference. */
872
+ type AsyncValidatorCell = {
873
+ /** Value of the validated column for this cell. */
874
+ value: unknown;
875
+ /** The full row — for row-dependent checks. */
876
+ row: DataEditorRow;
1113
877
  };
1114
878
  /**
1115
- * Coordinate rectangle within the server's data view.
1116
- * Uses ServerRowId (primary key) for rows and column ID strings for columns.
1117
- *
1118
- * Convention:
1119
- * - Both row fields omitted → all rows.
1120
- * - Both column fields omitted → all columns.
1121
- * - Single row: `fromRow` AND `toRow` both set, `toRow === fromRow`.
1122
- * - Single column: `fromColumn` AND `toColumn` both set, `toColumn === fromColumn`.
1123
- * - Range: both `from` and `to` set, `to !== from`.
1124
- * - `allSelected: true` → all rows and all columns.
1125
- * - Empty `{}` → used only for insert operations.
1126
- *
1127
- * INVALID: `from` present without `to`, or vice versa.
879
+ * Remote existence check for `{ type: "unique" }`. Called once per sweep
880
+ * with all distinct candidate values; report the subset that already exists
881
+ * return it and/or stream it via onChunk (results are unioned). `signal`
882
+ * fires only when results can no longer be used. Client-mode only.
1128
883
  */
1129
- type Region = {
1130
- fromRow?: ServerRowId;
1131
- toRow?: ServerRowId;
1132
- fromColumn?: string;
1133
- toColumn?: string;
1134
- allSelected?: boolean;
1135
- };
1136
- /** Describes where and how to insert a new row. */
1137
- type InsertParams = {
1138
- /** Existing row to anchor the insert relative to. Omitted when appending to the end. */
1139
- anchorRow?: ServerRowId;
1140
- /** Insert before or after the anchor row. */
1141
- position: "above" | "below";
1142
- /** Column IDs matching the order of `values` entries. */
1143
- columns: string[];
884
+ type UniqueRemoteFn = (values: unknown[], onChunk: (existing: unknown[]) => void, signal: AbortSignal) => Promise<unknown[] | void>;
885
+ type AsyncFunctionValidator = {
886
+ type: "asyncFunction";
887
+ /**
888
+ * Called once per column per operation with every affected cell. Report
889
+ * failures by `index` into `cells`: return an array aligned with the input
890
+ * (null = valid) and/or stream sparse failures via onChunk (unioned, any
891
+ * order). `signal` fires only when results can no longer be used.
892
+ * Client-mode only. For uniqueness use `unique.fn`, not this.
893
+ */
894
+ fn: (cells: AsyncValidatorCell[], onChunk: (failures: {
895
+ index: number;
896
+ error: ValidationError;
897
+ }[]) => void, signal: AbortSignal) => Promise<(ValidationError | null)[] | void>;
1144
898
  };
1145
899
  /**
1146
- * Unified edit params for all data mutations in server-delegated mode.
1147
- *
1148
- * The combination of fields determines the operation:
1149
- * - `target` + `values` → cell edit, clear, or external paste
1150
- * - `target` + `source` → internal paste (+ `cut` for cut-paste)
1151
- * - `target` + `source` (fill) → fill handle
1152
- * - `target` + `transform` → transform / revert
1153
- * - `target` + `delete: true` → mark rows for deletion
1154
- * - `target` + `delete: false` → restore rows (unmark deletion)
1155
- * - `insert` + `values` → create a new row
1156
- *
1157
- * `values` is always a 2D array. For a single cell edit: `[["newValue"]]`.
1158
- * For clearing: `[[""]]`. The server interprets dimensions relative to `target`:
1159
- * a 1×1 `values` applied to a multi-cell target means "fill all cells with this value".
1160
- *
1161
- * `filters` and `sort` provide the view context so the server can resolve
1162
- * which rows fall between `fromRow` and `toRow` in the current view.
1163
- * Omitted for single-cell edits where `fromRow` is a direct row ID.
900
+ * Escape hatch: a JS predicate run inline against the cell value and its row.
1164
901
  */
1165
- type EditParams = {
1166
- target: Region[];
1167
- source?: Region[];
1168
- values?: unknown[][];
1169
- transform?: TransformParams;
1170
- cut?: boolean;
1171
- delete?: boolean;
1172
- insert?: InsertParams;
1173
- undo?: boolean;
1174
- filters?: QueryFilters;
1175
- sort?: SortState;
1176
- lockedColumns?: Array<{
1177
- columnId: string;
1178
- mode: "all" | "default";
1179
- }>;
1180
- };
1181
- type ExportParams$1<F = Record<string, unknown>> = {
1182
- format: "csv" | "tsv" | "xlsx" | "json" | "xml";
1183
- allRows: boolean;
1184
- rtl?: boolean;
1185
- filters?: QueryFilters<F>;
1186
- sort?: SortState;
1187
- signal?: AbortSignal;
1188
- };
1189
- /** Transform operation descriptor. `type` identifies the operation, optional fields carry parameters. */
1190
- type TransformParams = {
1191
- type: string;
1192
- separator?: string;
1193
- /** When `true`, the server should delete the dynamic source columns after applying the transform. */
1194
- deleteSource?: boolean;
1195
- };
1196
- /** Params passed to `onColumnDelete` when the user deletes a dynamic column. */
1197
- type ColumnDeleteParams = {
1198
- /** ID of the dynamic column to delete. */
1199
- columnId: string;
1200
- /** `true` when the server should reverse this operation (undo). Omitted on initial call and redo. */
1201
- undo?: boolean;
1202
- };
1203
- /** Params passed to `onColumnEdit` when the user renames a dynamic column. */
1204
- type ColumnEditParams = {
1205
- /** ID of the dynamic column being edited. */
1206
- columnId: string;
1207
- /** New title for the column. */
1208
- title: string;
1209
- /** `true` when the server should reverse this operation (undo). Omitted on initial call and redo. */
1210
- undo?: boolean;
1211
- };
1212
- /** Server's response after applying a mutation. */
1213
- type EditResponse = {
1214
- counts?: ServerQueryCounts;
1215
- /** Business-logic rejection. SDK reverts the optimistic update and shows `reason` in a toast. */
1216
- rejected?: boolean;
1217
- /** Why the server rejected. Shown to the user as-is. */
1218
- reason?: string;
1219
- /** The full row created by the server. Returned for insert operations. */
1220
- row?: ServerRow;
1221
- /** Updated column list. When present, the SDK replaces its columns with this list. */
1222
- columns?: Array<{
1223
- id: string;
1224
- title: string;
1225
- }>;
902
+ type FunctionValidator = {
903
+ type: "function";
904
+ fn: CellValidator;
1226
905
  };
1227
906
  /**
1228
- * Every decision the user made during the import wizard, packed into one object.
1229
- * You get the raw file and the full mapping config. Parse it however you want —
1230
- * stream it, bulk-load it, hand it to a background job. Your call.
907
+ * The validator-rule union accepted by `DataEditorColumn.validators`.
908
+ *
909
+ * Named `ValidatorRule` (not `Validator`) so it doesn't clash with the
910
+ * runtime `Validator` class in `core/Validator.ts`.
1231
911
  */
1232
- type ImportMappings = {
1233
- /** CSV header → column ID. Headers the user left unmatched are `undefined`. */
1234
- columnMapping: Record<string, string | undefined>;
1235
- /**
1236
- * Value substitutions for select columns.
1237
- * Outer key = column ID, inner key = imported value, inner value = target option.
1238
- * Only present when at least one select column was matched.
1239
- */
1240
- valueMapping: Record<string, Record<string, string | undefined>>;
1241
- /** Column ID used to match imported rows against existing data. Same value as `DataEditorProps.primaryKey`. */
1242
- primaryKey: string;
1243
- /** Sheet name the user selected. Only present for multi-sheet XLSX files. */
1244
- selectedSheet?: string;
1245
- /** Zero-based index of the row the SDK detected as the header row. */
1246
- headerRowIndex: number;
1247
- /** Number format detected from the file contents. Affects how `"1.234,56"` vs `"1,234.56"` is read. */
1248
- numberFormat: "EU" | "US";
1249
- /**
1250
- * Date order detected from the file's date columns. `"EU"` = day-first,
1251
- * `"US"` = month-first. One verdict for the file, since date order follows
1252
- * the source locale; ISO values are parsed regardless of this.
1253
- */
1254
- dateFormat: "EU" | "US";
1255
- /**
1256
- * Columns the user created during import for unmatched headers.
1257
- * These don't exist in your schema yet — you decide whether to persist them.
1258
- */
1259
- newColumns: DataEditorColumn[];
1260
- };
1261
- /** Params passed to `onFileImport`. The original file, unchanged, plus everything the wizard collected. */
1262
- type FileImportParams = {
1263
- /** The original file. Same bytes the user dropped into the browser. */
1264
- file: File;
1265
- /** All mapping decisions from the import wizard. */
1266
- mappings: ImportMappings;
1267
- /** Display name for this import source. Typically the file name. */
1268
- sourceName: string;
1269
- /** Fires when the user cancels the import. */
1270
- signal?: AbortSignal;
1271
- };
912
+ type ValidatorRule = BuiltInValidator | FunctionValidator | AsyncFunctionValidator;
1272
913
  /**
1273
- * Params passed to `onRowsImport` once per chunk.
1274
- * The SDK already parsed the file, applied column mappings, normalized dates
1275
- * and numbers, and resolved value mappings. You get clean, schema-conformant rows.
914
+ * Async-check state of a cell, orthogonal to errors/misplaced: "pending"
915
+ * while a verdict is awaited, "unverified" when the check failed or timed
916
+ * out. Idle cells carry no entry.
1276
917
  */
1277
- type RowsImportParams = {
1278
- /** Stable ID for this import session. Use it for idempotency or correlation. */
1279
- importId: string;
1280
- /** Display name for this import source. Typically the file name. */
1281
- sourceName: string;
1282
- /** Zero-based chunk index. Together with `importId`, uniquely identifies each chunk. */
1283
- chunkIndex: number;
1284
- /** `true` on the last chunk. Safe to finalize, run post-import hooks, or trigger validation. */
1285
- isLastChunk: boolean;
1286
- /** Transformed rows, keyed by column ID. Ready to store. */
1287
- rows: Record<string, unknown>[];
1288
- /** Columns the user created during import. Only present on the first chunk (`chunkIndex === 0`). */
1289
- newColumns?: DataEditorColumn[];
1290
- /** Column ID used to match imported rows against existing data. */
1291
- primaryKey: string;
1292
- /** Fires when the user cancels mid-import. Clean up any partial state. */
1293
- signal?: AbortSignal;
1294
- };
1295
- /** Your response after processing a chunk. */
1296
- type RowsImportResponse = {
1297
- /** How many rows you accepted from this chunk. Drives progress reporting. */
1298
- accepted: number;
1299
- /** Per-row errors. `rowIndex` is relative to the chunk (0-based). Surfaced in the UI after import. */
1300
- errors?: Array<{
1301
- rowIndex: number;
1302
- message: string;
1303
- }>;
1304
- };
1305
- /** Params passed to `onSourceRemove` when the user deletes a data source. */
1306
- type SourceRemoveParams = {
1307
- /** The source ID to remove. Matches the `id` from `ServerQueryCounts.sources`. */
1308
- sourceId: string;
1309
- /** Fires when the user cancels. */
1310
- signal?: AbortSignal;
1311
- };
918
+ type CellAsyncState = "pending" | "unverified";
1312
919
 
1313
920
  /**
1314
921
  * ChunkedProcessor — Generic utility for processing items in prioritized chunks
@@ -1353,33 +960,10 @@ declare class ChunkedProcessor<T> {
1353
960
  private _pendingChunkFn;
1354
961
  constructor(chunkSize?: number);
1355
962
  get isRunning(): boolean;
1356
- get chunkSize(): number;
1357
963
  run(params: ChunkedProcessorCallbacks<T>): void;
1358
964
  cancel(): void;
1359
965
  }
1360
966
 
1361
- /**
1362
- * Internal contract: the surface a Scale client exposes to the SDK's data
1363
- * layer. Implemented by `ScaleClient`. Not part of the public SDK API —
1364
- * customers configure server mode via `server: { url }` and never see this
1365
- * type.
1366
- */
1367
- type ScaleClientApi<TRow extends DataEditorRow = DataEditorRow, TFilters = Record<string, unknown>> = {
1368
- onQuery: (params: QueryParams<TFilters>) => Promise<QueryResponse<TRow>>;
1369
- onFilterOptions?: () => Promise<FilterOptionsResponse>;
1370
- onExport?: (params: ExportParams$1<TFilters>) => Promise<void>;
1371
- onEdit: (params: EditParams, options?: ServerCallOptions) => Promise<EditResponse | void>;
1372
- onFileImport?: (params: FileImportParams) => Promise<void>;
1373
- onRowsImport?: (params: RowsImportParams) => Promise<RowsImportResponse | void>;
1374
- importChunkSize?: number;
1375
- onSourceRemove?: (params: SourceRemoveParams) => Promise<void>;
1376
- onColumnDelete?: (params: ColumnDeleteParams) => Promise<EditResponse | void>;
1377
- onColumnEdit?: (params: ColumnEditParams) => Promise<EditResponse | void>;
1378
- findAndReplace?: FindAndReplaceConfig;
1379
- pageSize?: number;
1380
- scrollSensitivity?: number;
1381
- };
1382
-
1383
967
  /**
1384
968
  * A single operation the LLM wants to apply to rows in the current filtered view.
1385
969
  *
@@ -1520,12 +1104,10 @@ type DataEditorChat<TRow extends DataEditorRow = DataEditorRow> = {
1520
1104
 
1521
1105
  /**
1522
1106
  * Categories of internal errors surfaced through the `onError` callback.
1523
- *
1524
- * Existing categories cover client-side failures. `scale.*` codes cover
1525
- * server-mode (Updog Scale) failures. `license.*` codes cover license
1526
- * validation failures (previously a separate `LicenseErrorCode` enum).
1107
+ * `license.*` codes cover license validation failures (previously a separate
1108
+ * `LicenseErrorCode` enum).
1527
1109
  */
1528
- type UpdogErrorCode = "PARSE_ERROR" | "RENDER_ERROR" | "TRANSFORM_ERROR" | "VALIDATION_ERROR" | "WORKER_ERROR" | "COMMAND_ERROR" | "OPERATION_ERROR" | "license.invalid" | "license.missing" | "license.domain_not_allowed" | "license.subscription_inactive" | "license.trial_expired" | "scale.bootstrap_failed" | "scale.workspace_lost" | "scale.unreachable" | "scale.server_error";
1110
+ type UpdogErrorCode = "PARSE_ERROR" | "RENDER_ERROR" | "TRANSFORM_ERROR" | "VALIDATION_ERROR" | "WORKER_ERROR" | "COMMAND_ERROR" | "OPERATION_ERROR" | "license.invalid" | "license.missing" | "license.domain_not_allowed" | "license.subscription_inactive" | "license.trial_expired";
1529
1111
  /**
1530
1112
  * An internal error caught by the SDK and passed to `onError`. The SDK
1531
1113
  * recovers gracefully where possible — `onError` is for your logging and
@@ -1645,272 +1227,29 @@ type UniqueConfig = {
1645
1227
  fn?: UniqueRemoteFn;
1646
1228
  };
1647
1229
  /**
1648
- * Core-internal column shape produced by normalizeUniqueColumns. Uniqueness
1230
+ * Core-internal column shape produced by normalizeColumns. Uniqueness
1649
1231
  * lives in `uniqueConfig` and asyncFunction rules in `asyncConfig` — the
1650
1232
  * single internal sources of truth — never as entries in `validators`.
1651
1233
  * Never exported from the package entry.
1652
1234
  */
1653
- type NormalizedColumn = DataEditorColumn & {
1235
+ type NormalizedColumn = Omit<DataEditorColumn, "validators"> & {
1236
+ validators?: ValidatorRule[];
1654
1237
  uniqueConfig?: UniqueConfig;
1655
1238
  asyncConfig?: AsyncFunctionValidator[];
1239
+ numberConfig?: NumberConfig;
1240
+ dateConfig?: DateConfig;
1656
1241
  };
1657
-
1658
- type PrimaryKeyInput = string | readonly string[];
1659
-
1660
- type RegisterSourceOptions = {
1661
- name: string;
1662
- id?: DataSourceId;
1663
- isDeletable?: boolean;
1664
- isInitialData?: boolean;
1665
- };
1666
- type MergeEntry<TRow> = {
1667
- row: TRow;
1668
- sourceId: DataSourceId;
1669
- isNew: boolean;
1670
- isEdited: boolean;
1671
- /** Diff basis the row carried before the merge. Present only when isEdited. */
1672
- originalRow?: TRow;
1673
- };
1674
- type RemovalPlan<TRow> = {
1675
- rowsToDelete: Set<TRowId>;
1676
- rowsToRestore: Array<{
1677
- rowId: TRowId;
1678
- row: TRow;
1679
- originalSourceId: DataSourceId;
1680
- isNew: boolean;
1681
- isEdited: boolean;
1682
- originalRow?: TRow;
1683
- }>;
1684
- };
1685
- type ExtendedRemovalPlan<TRow> = RemovalPlan<TRow> & {
1686
- sourceId: DataSourceId;
1687
- repairedEntries: Array<{
1688
- sourceId: DataSourceId;
1689
- rowId: TRowId;
1690
- before: MergeEntry<TRow>;
1691
- after: MergeEntry<TRow> | null;
1692
- }>;
1242
+ type NumberConfig = {
1243
+ min?: number;
1244
+ max?: number;
1245
+ decimalPlaces?: number;
1693
1246
  };
1694
- declare class SourceManager<TRow extends DataEditorRow = DataEditorRow> {
1695
- private readonly _defaultSourceId;
1696
- private readonly overrides;
1697
- private readonly sources;
1698
- private readonly mergedRows;
1699
- getSourceId(rowId: TRowId): DataSourceId;
1700
- setSourceId(rowId: TRowId, sourceId: DataSourceId): void;
1701
- deleteSourceId(rowId: TRowId): void;
1702
- getOverrides(): ReadonlyMap<TRowId, DataSourceId>;
1703
- register(options: RegisterSourceOptions): DataSourceId;
1704
- /**
1705
- * Re-insert a source using a full captured state, preserving
1706
- * isVisible, isLoading, rowCount, etc. Used by SourceLifecycle.restore.
1707
- * If the source already exists, overwrites its state.
1708
- */
1709
- restoreState(state: DataSourceState): void;
1710
- has(sourceId: DataSourceId): boolean;
1711
- get(sourceId: DataSourceId): DataSourceState | undefined;
1712
- delete(sourceId: DataSourceId): void;
1713
- setLoading(sourceId: DataSourceId, isLoading: boolean): void;
1714
- finalizeAllSources(): void;
1715
- values(): IterableIterator<DataSourceState>;
1716
- getHiddenSourceIds(): Set<DataSourceId>;
1717
- saveMergeSnapshot(sourceId: DataSourceId, rowId: TRowId, existingRow: TRow, previousSourceId: DataSourceId, isNew: boolean, isEdited: boolean, originalRow?: TRow): void;
1718
- /**
1719
- * Public so commands can re-install merge entries during undo of a remove.
1720
- */
1721
- restoreMergeEntry(sourceId: DataSourceId, rowId: TRowId, entry: MergeEntry<TRow>): void;
1722
- /**
1723
- * Pure — computes the full removal plan without mutating any state.
1724
- * Callers run applyRemovalPlan(plan) to commit.
1725
- */
1726
- planRemoval(sourceId: DataSourceId): ExtendedRemovalPlan<TRow> | null;
1727
- /**
1728
- * Mutates internal state per plan produced by planRemoval.
1729
- */
1730
- applyRemovalPlan(plan: ExtendedRemovalPlan<TRow>): void;
1731
- clear(): void;
1732
- private getUniqueName;
1733
- }
1734
-
1735
- type ServerDataManagerDeps<TRow extends DataEditorRow = DataEditorRow> = {
1736
- clear(): void;
1737
- setLoading(isLoading: boolean): void;
1738
- registerSource(options: RegisterSourceOptions): DataSourceId;
1739
- setSourceLoading(sourceId: DataSourceId, isLoading: boolean): void;
1740
- getLocalRowCount(): number;
1741
- replaceServerRows(sourceId: DataSourceId, rows: ServerRow<TRow>[], offset: number, counts?: ServerQueryCounts): void;
1742
- appendServerRows(rows: ServerRow<TRow>[], counts?: ServerQueryCounts): void;
1743
- prependServerRows(rows: ServerRow<TRow>[], offset: number, counts?: ServerQueryCounts): void;
1744
- applyServerRowMeta(rows: ServerRow<TRow>[], counts?: ServerQueryCounts): void;
1745
- };
1746
- type FetchDirection = "forward" | "backward" | "jump";
1747
- declare class ServerDataManager<TRow extends DataEditorRow = DataEditorRow> {
1748
- private _offset;
1749
- private _totalCount;
1750
- private _isFetching;
1751
- private readonly _pageSize;
1752
- private readonly _maxBufferRows;
1753
- private _filters;
1754
- private _sources;
1755
- private _sort;
1756
- private _filterOptions;
1757
- private _filterOptionsFetched;
1758
- private _abortController;
1759
- private _syncAbort;
1760
- private _lastVisibleStart;
1761
- private _debouncedFetch;
1762
- private readonly _config;
1763
- private readonly _dataStoreRef;
1764
- private readonly _sourceLabel;
1765
- private _onChanged;
1766
- constructor(config: ScaleClientApi<TRow>, dataStoreRef: ServerDataManagerDeps<TRow>, sourceLabel: string);
1767
- get offset(): number;
1768
- get totalCount(): number | null;
1769
- get isFetching(): boolean;
1770
- get pageSize(): number;
1771
- get maxBufferRows(): number;
1772
- setOnChanged(callback: () => void): void;
1773
- setOffset(offset: number): void;
1774
- setTotalCount(count: number): void;
1775
- private setFetching;
1776
- getExcess(currentCount: number, newCount: number): number;
1777
- shouldFetch(visibleStart: number, visibleEnd: number, loadedCount: number): FetchDirection | null;
1778
- /**
1779
- * Full reload — abort in-flight, clear store, fetch first page.
1780
- * Called on initial load, search/filter/sort changes, and resetFilters.
1781
- */
1782
- reload(): void;
1783
- /**
1784
- * Scroll-driven pagination with velocity-based debouncing.
1785
- * Called from CanvasGrid on every scroll event.
1786
- */
1787
- handleScroll(visibleStart: number, visibleEnd: number): void;
1788
- /**
1789
- * Fetch a single page based on scroll position and current window state.
1790
- */
1791
- private fetchPage;
1792
- /**
1793
- * Re-query the current viewport and replace row data, metadata, and counts.
1794
- * Called after successful edits and find-and-replace mutations.
1795
- * Each call aborts the previous in-flight sync.
1796
- */
1797
- syncCurrentView(): void;
1798
- /**
1799
- * Merge filter keys into server filter state and reload.
1800
- * Called by DataStore.setFilters() in server mode and by filter components.
1801
- */
1802
- setFilters(filters: Partial<Filters>): void;
1803
- /**
1804
- * Set sort state and reload.
1805
- */
1806
- setSort(sort: SortState): void;
1807
- /**
1808
- * Restrict query to visible sources and reload.
1809
- * Pass `undefined` to include all sources.
1810
- */
1811
- setSources(sources: string[] | undefined): void;
1812
- /**
1813
- * Clear all filters and sort, then reload.
1814
- */
1815
- resetFilters(): void;
1816
- /**
1817
- * One-time fetch of filter option dictionaries for sidebar filter controls.
1818
- */
1819
- fetchFilterOptions(): void;
1820
- getFilterOptions(): FilterOptionsResponse | null;
1821
- get onEdit(): (params: EditParams, options?: ServerCallOptions) => Promise<EditResponse | void>;
1822
- get filters(): Record<string, unknown>;
1823
- get sort(): SortState;
1824
- get sources(): string[] | undefined;
1825
- get onSourceRemove(): ((params: SourceRemoveParams) => Promise<void>) | undefined;
1826
- get onColumnDelete(): ((params: ColumnDeleteParams) => Promise<EditResponse | void>) | undefined;
1827
- get onColumnEdit(): ((params: ColumnEditParams) => Promise<EditResponse | void>) | undefined;
1828
- get hasExport(): boolean;
1829
- private _exportAbortController;
1830
- export(format: DataEditorFormat, allRows: boolean, rtl: boolean): Promise<void>;
1831
- clear(): void;
1832
- destroy(): void;
1833
- }
1834
-
1835
- /**
1836
- * A post-resolution selection rectangle in stable coordinate space.
1837
- * Produced by grid-layer resolvers from CellRange[] in grid-index space.
1838
- * Consumed by DataStore operations and server sync.
1839
- */
1840
- type SelectionRect = {
1841
- readonly fields: readonly string[];
1842
- readonly rowIds: readonly TRowId[];
1247
+ type DateConfig = {
1248
+ min?: string;
1249
+ max?: string;
1843
1250
  };
1844
1251
 
1845
- /**
1846
- * ServerEditBuilder — Stateless coordinate translator for server-delegated edits.
1847
- *
1848
- * Converts frontend coordinates (TRowId, column index, grid ranges) into
1849
- * `EditParams` with `Region[]` that the server can interpret.
1850
- *
1851
- * Does NOT call `onEdit`. Only builds params.
1852
- * DataStore calls the builder, then sends the result to the server.
1853
- *
1854
- * Responsibilities:
1855
- * - TRowId → ServerRowId translation via primaryKey
1856
- * - Grid index → column ID translation via columns array
1857
- * - Filter/sort context attachment from ServerDataManager
1858
- */
1859
-
1860
- type ServerEditDeps<TRow extends DataEditorRow = DataEditorRow> = {
1861
- getPrimaryKey: () => string;
1862
- getRowById: (id: TRowId) => TRow | undefined;
1863
- getColumnIds: () => string[];
1864
- getFilters: () => Record<string, unknown>;
1865
- getSort: () => SortState;
1866
- getLockedColumns: () => ReadonlyMap<string, ColumnLockMode>;
1867
- };
1868
- declare class ServerEditBuilder<TRow extends DataEditorRow = DataEditorRow> {
1869
- private readonly _deps;
1870
- constructor(deps: ServerEditDeps<TRow>);
1871
- resolveServerRowId(rowId: TRowId): ServerRowId | undefined;
1872
- buildRegion(rowIds: TRowId[], columnIds: string[]): Region;
1873
- /**
1874
- * Collapse rowIds × columnIds into minimal Region[].
1875
- * - All columns → omit column fields (row-only regions).
1876
- * - Contiguous columns in schema order → single fromColumn/toColumn span.
1877
- * - Non-contiguous → one region per contiguous column group.
1878
- * Rows are expressed as fromRow/toRow using first/last of the provided array.
1879
- */
1880
- buildRegions(rowIds: TRowId[], columnIds: string[]): Region[];
1881
- /**
1882
- * Collapse columnIds into minimal column-only Region[] (all rows implied).
1883
- * - All columns → `{ allSelected: true }`.
1884
- * - Contiguous in schema order → single `{ fromColumn, toColumn }`.
1885
- * - Non-contiguous → one region per contiguous group.
1886
- */
1887
- buildColumnRegions(columnIds: string[]): Region[];
1888
- /**
1889
- * Build minimal Region[] from multiple selection rectangles.
1890
- * Each rect is collapsed independently, preserving disjoint selections.
1891
- */
1892
- buildRegionsFromRects(rects: SelectionRect[]): Region[];
1893
- buildAllSelectedRegion(): Region;
1894
- buildColumnRegion(columnId: string): Region;
1895
- buildRowRegion(fromRowId: TRowId, toRowId: TRowId): Region;
1896
- cellEdit(rowId: TRowId, field: string, value: unknown): EditParams;
1897
- clear(target: Region[]): EditParams;
1898
- paste(source: Region[], target: Region[], cut?: boolean): EditParams;
1899
- pasteExternal(target: Region[], values: unknown[][]): EditParams;
1900
- fill(source: Region[], target: Region[]): EditParams;
1901
- transform(target: Region[], transform: TransformParams): EditParams;
1902
- deleteRows(rowRanges: [TRowId, TRowId][]): EditParams;
1903
- restoreRows(rowRanges: [TRowId, TRowId][]): EditParams;
1904
- deleteAllRows(): EditParams;
1905
- restoreAllRows(): EditParams;
1906
- insertRow(anchorRowId: TRowId | undefined, position: InsertParams["position"], values: unknown[][], columnIds: string[]): EditParams;
1907
- /**
1908
- * Returns null when all columns are selected (caller decides representation).
1909
- * Otherwise returns contiguous column spans as `{ fromColumn, toColumn }` regions.
1910
- */
1911
- private collapseColumns;
1912
- private viewContext;
1913
- }
1252
+ type PrimaryKeyInput = string | readonly string[];
1914
1253
 
1915
1254
  /**
1916
1255
  * DirtyTracker — Change classification and revert detection for rows.
@@ -1998,7 +1337,6 @@ type IFilterEngine<TRow extends DataEditorRow = DataEditorRow> = {
1998
1337
  getWordsPerRow(): number;
1999
1338
  getShowOnlyDeletedRows(): boolean;
2000
1339
  getSortState(): SortState;
2001
- setReaders(rowReader: FilterRowReader<TRow>, flagReader: FlagReader): void;
2002
1340
  setColumns(columns: DataEditorColumn[]): void;
2003
1341
  setFilters(filters: Partial<Filters>): void;
2004
1342
  setSortState(state: SortState, sortType?: SortType, locales?: string[]): Promise<void>;
@@ -2130,12 +1468,6 @@ interface SnapshotStateReader {
2130
1468
  getSortState(): SortState;
2131
1469
  getShowOnlyDeletedRows(): boolean;
2132
1470
  getPendingValidationCount(): number;
2133
- /** Server-provided aggregate counts. Present only in server mode. */
2134
- getServerEditedCount?(): number;
2135
- getServerNewCount?(): number;
2136
- getServerErrorCount?(): number;
2137
- getServerEmptyCount?(): number;
2138
- getServerDeletedCount?(): number;
2139
1471
  }
2140
1472
  declare class SnapshotManager {
2141
1473
  private _visibleNewCount;
@@ -2181,6 +1513,81 @@ declare class SnapshotManager {
2181
1513
  private recomputeFilteredCounts;
2182
1514
  }
2183
1515
 
1516
+ type RegisterSourceOptions = {
1517
+ name: string;
1518
+ id?: DataSourceId;
1519
+ isDeletable?: boolean;
1520
+ isInitialData?: boolean;
1521
+ };
1522
+ type MergeEntry<TRow> = {
1523
+ row: TRow;
1524
+ sourceId: DataSourceId;
1525
+ isNew: boolean;
1526
+ isEdited: boolean;
1527
+ /** Diff basis the row carried before the merge. Present only when isEdited. */
1528
+ originalRow?: TRow;
1529
+ };
1530
+ type RemovalPlan<TRow> = {
1531
+ rowsToDelete: Set<TRowId>;
1532
+ rowsToRestore: Array<{
1533
+ rowId: TRowId;
1534
+ row: TRow;
1535
+ originalSourceId: DataSourceId;
1536
+ isNew: boolean;
1537
+ isEdited: boolean;
1538
+ originalRow?: TRow;
1539
+ }>;
1540
+ };
1541
+ type ExtendedRemovalPlan<TRow> = RemovalPlan<TRow> & {
1542
+ sourceId: DataSourceId;
1543
+ repairedEntries: Array<{
1544
+ sourceId: DataSourceId;
1545
+ rowId: TRowId;
1546
+ before: MergeEntry<TRow>;
1547
+ after: MergeEntry<TRow> | null;
1548
+ }>;
1549
+ };
1550
+ declare class SourceManager<TRow extends DataEditorRow = DataEditorRow> {
1551
+ private readonly _defaultSourceId;
1552
+ private readonly overrides;
1553
+ private readonly sources;
1554
+ private readonly mergedRows;
1555
+ getSourceId(rowId: TRowId): DataSourceId;
1556
+ setSourceId(rowId: TRowId, sourceId: DataSourceId): void;
1557
+ deleteSourceId(rowId: TRowId): void;
1558
+ getOverrides(): ReadonlyMap<TRowId, DataSourceId>;
1559
+ register(options: RegisterSourceOptions): DataSourceId;
1560
+ /**
1561
+ * Re-insert a source using a full captured state, preserving
1562
+ * isVisible, isLoading, rowCount, etc. Used by SourceLifecycle.restore.
1563
+ * If the source already exists, overwrites its state.
1564
+ */
1565
+ restoreState(state: DataSourceState): void;
1566
+ has(sourceId: DataSourceId): boolean;
1567
+ get(sourceId: DataSourceId): DataSourceState | undefined;
1568
+ delete(sourceId: DataSourceId): void;
1569
+ setLoading(sourceId: DataSourceId, isLoading: boolean): void;
1570
+ finalizeAllSources(): void;
1571
+ values(): IterableIterator<DataSourceState>;
1572
+ getHiddenSourceIds(): Set<DataSourceId>;
1573
+ saveMergeSnapshot(sourceId: DataSourceId, rowId: TRowId, existingRow: TRow, previousSourceId: DataSourceId, isNew: boolean, isEdited: boolean, originalRow?: TRow): void;
1574
+ /**
1575
+ * Public so commands can re-install merge entries during undo of a remove.
1576
+ */
1577
+ restoreMergeEntry(sourceId: DataSourceId, rowId: TRowId, entry: MergeEntry<TRow>): void;
1578
+ /**
1579
+ * Pure — computes the full removal plan without mutating any state.
1580
+ * Callers run applyRemovalPlan(plan) to commit.
1581
+ */
1582
+ planRemoval(sourceId: DataSourceId): ExtendedRemovalPlan<TRow> | null;
1583
+ /**
1584
+ * Mutates internal state per plan produced by planRemoval.
1585
+ */
1586
+ applyRemovalPlan(plan: ExtendedRemovalPlan<TRow>): void;
1587
+ clear(): void;
1588
+ private getUniqueName;
1589
+ }
1590
+
2184
1591
  /**
2185
1592
  * ValidationStore — Cell-level validation state with incremental count tracking.
2186
1593
  *
@@ -2227,6 +1634,26 @@ type IValidationStore = {
2227
1634
  clear(): void;
2228
1635
  };
2229
1636
 
1637
+ type IValueIndex<TRow extends DataEditorRow = DataEditorRow> = {
1638
+ setTrackedFields(fields: Set<string>): void;
1639
+ addRow(row: TRow): void;
1640
+ removeRow(row: TRow): void;
1641
+ updateField(field: string, oldValue: unknown, newValue: unknown): void;
1642
+ rebuild(rows: Iterable<TRow>): void;
1643
+ getValues(field: string): ReadonlyMap<string, number>;
1644
+ getVersion(): number;
1645
+ isTracked(field: string): boolean;
1646
+ getMinMax(field: string): {
1647
+ min: number;
1648
+ max: number;
1649
+ } | null;
1650
+ getDateMinMax(field: string): {
1651
+ min: string;
1652
+ max: string;
1653
+ } | null;
1654
+ bumpVersion(): void;
1655
+ };
1656
+
2230
1657
  /**
2231
1658
  * AsyncValidationScheduler — facade over the async annotation channel.
2232
1659
  *
@@ -2275,26 +1702,6 @@ type IValidator<TRow extends DataEditorRow = DataEditorRow> = {
2275
1702
  destroy(): void;
2276
1703
  };
2277
1704
 
2278
- type IValueIndex<TRow extends DataEditorRow = DataEditorRow> = {
2279
- setTrackedFields(fields: Set<string>): void;
2280
- addRow(row: TRow): void;
2281
- removeRow(row: TRow): void;
2282
- updateField(field: string, oldValue: unknown, newValue: unknown): void;
2283
- rebuild(rows: Iterable<TRow>): void;
2284
- getValues(field: string): ReadonlyMap<string, number>;
2285
- getVersion(): number;
2286
- isTracked(field: string): boolean;
2287
- getMinMax(field: string): {
2288
- min: number;
2289
- max: number;
2290
- } | null;
2291
- getDateMinMax(field: string): {
2292
- min: string;
2293
- max: string;
2294
- } | null;
2295
- bumpVersion(): void;
2296
- };
2297
-
2298
1705
  type RowEntry<TRow extends DataEditorRow> = {
2299
1706
  rowId: TRowId;
2300
1707
  row: TRow;
@@ -2316,10 +1723,9 @@ type SourceSnapshot<TRow extends DataEditorRow> = {
2316
1723
  plan: ExtendedRemovalPlan<TRow>;
2317
1724
  };
2318
1725
  type SourceLifecycleHost<TRow extends DataEditorRow> = {
2319
- getValidator: () => IValidator<TRow> | null;
1726
+ getValidator: () => IValidator<TRow>;
2320
1727
  pushCommand: (cmd: Command<TRow>, cost?: number) => number;
2321
1728
  notify: () => void;
2322
- isServerStrategy: () => boolean;
2323
1729
  checkRowEmptyCells: (rowId: TRowId) => void;
2324
1730
  clearRowValidations: (rowId: TRowId) => void;
2325
1731
  };
@@ -2350,28 +1756,19 @@ declare class SourceLifecycle<TRow extends DataEditorRow = DataEditorRow> {
2350
1756
  }
2351
1757
 
2352
1758
  /**
2353
- * Fill-level delta computations.
2354
- *
2355
- * Pure functions that compute ColumnDelta[] for fill handle operations.
2356
- * Zero side effects — take a spec + row reader, return deltas.
2357
- *
2358
- * buildFillSpec() — reads source values once, builds tiling index
2359
- * computeFillDeltas() — processes a chunk of target rows against the spec
2360
- *
2361
- * Fill uses a tiling pattern: source values repeat cyclically.
2362
- * For row r in fill range: srcRow = r % sourceHeight.
2363
- * For col c in fill range: srcCol = c % sourceWidth.
1759
+ * A post-resolution selection rectangle in stable coordinate space.
1760
+ * Produced by grid-layer resolvers from CellRange[] in grid-index space.
1761
+ * Consumed by DataStore operations and server sync.
2364
1762
  */
1763
+ type SelectionRect = {
1764
+ readonly fields: readonly string[];
1765
+ readonly rowIds: readonly TRowId[];
1766
+ };
2365
1767
 
2366
- type FillSpec = {
2367
- /** 2D source grid: sourceValues[row][col]. Read once — source region is always small. */
2368
- sourceValues: unknown[][];
2369
- sourceHeight: number;
2370
- sourceWidth: number;
2371
- /** Column IDs for the fill target columns. */
2372
- fields: string[];
2373
- /** Target rowId → position within the fill range, for tiling modulo. */
2374
- rowIdToFillIndex: ReadonlyMap<TRowId, number>;
1768
+ type MultiSelectEditorConfig = {
1769
+ options: string[];
1770
+ delimiter?: string;
1771
+ enableCustomValue?: boolean;
2375
1772
  };
2376
1773
 
2377
1774
  /**
@@ -2389,15 +1786,47 @@ type FillSpec = {
2389
1786
  * - Large datasets: orchestrator calls computePasteDeltas() per chunk
2390
1787
  */
2391
1788
 
1789
+ type MultiSelectTarget = {
1790
+ delimiter: string;
1791
+ editor: MultiSelectEditorConfig;
1792
+ };
2392
1793
  type PasteSpec = {
2393
1794
  sourceColumnIds: string[];
2394
1795
  targetColumnIds: string[];
2395
1796
  targetToSource: ReadonlyMap<TRowId, TRowId>;
2396
1797
  selectOptionsMap: ReadonlyMap<string, ReadonlySet<string>>;
1798
+ multiSelectTargets: ReadonlyMap<string, MultiSelectTarget>;
2397
1799
  skipColumnIndices: ReadonlySet<number>;
2398
1800
  isCut: boolean;
2399
1801
  };
2400
1802
 
1803
+ /**
1804
+ * Fill-level delta computations.
1805
+ *
1806
+ * Pure functions that compute ColumnDelta[] for fill handle operations.
1807
+ * Zero side effects — take a spec + row reader, return deltas.
1808
+ *
1809
+ * buildFillSpec() — reads source values once, builds tiling index
1810
+ * computeFillDeltas() — processes a chunk of target rows against the spec
1811
+ *
1812
+ * Fill uses a tiling pattern: source values repeat cyclically.
1813
+ * For row r in fill range: srcRow = r % sourceHeight.
1814
+ * For col c in fill range: srcCol = c % sourceWidth.
1815
+ */
1816
+
1817
+ type FillSpec = {
1818
+ /** 2D source grid: sourceValues[row][col]. Read once — source region is always small. */
1819
+ sourceValues: unknown[][];
1820
+ sourceHeight: number;
1821
+ sourceWidth: number;
1822
+ /** Column IDs for the fill target columns. */
1823
+ fields: string[];
1824
+ /** Target rowId → position within the fill range, for tiling modulo. */
1825
+ rowIdToFillIndex: ReadonlyMap<TRowId, number>;
1826
+ /** Multiselect target fields with the delimiter resolved from the source grid. */
1827
+ multiSelectTargets: ReadonlyMap<string, MultiSelectTarget>;
1828
+ };
1829
+
2401
1830
  type ApplyFormulaOptions = {
2402
1831
  /**
2403
1832
  * Column IDs to delete AFTER the formula has been applied.
@@ -2414,9 +1843,6 @@ type UpsertOptions = {
2414
1843
  skipRowValidation?: boolean;
2415
1844
  };
2416
1845
  declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2417
- private readonly _mode;
2418
- isServer(): boolean;
2419
- isClient(): boolean;
2420
1846
  private rowStore;
2421
1847
  readonly formulaRegistry: FormulaRegistry;
2422
1848
  private _isLoading;
@@ -2430,8 +1856,6 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2430
1856
  private history;
2431
1857
  private validator;
2432
1858
  private valueIndex;
2433
- private serverCounts;
2434
- private editBuilder;
2435
1859
  private isUndoRedoing;
2436
1860
  private anchorMapCache;
2437
1861
  private pendingBatchCommands;
@@ -2439,7 +1863,6 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2439
1863
  private _skipNotify;
2440
1864
  private _bulkMode;
2441
1865
  private _editedCells;
2442
- private _primaryKeyFields;
2443
1866
  /** Columns that are currently locked (pre-locked from schema + user-locked at runtime). */
2444
1867
  private _lockedColumns;
2445
1868
  /** Columns locked via schema definition — user cannot unlock these. */
@@ -2447,12 +1870,8 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2447
1870
  /** Last-known visible row range reported by the canvas scroll handler. */
2448
1871
  private _viewportStart;
2449
1872
  private _viewportEnd;
2450
- private pendingMutations;
2451
- private editParamsHistory;
2452
1873
  readonly errorHandler: ErrorHandler;
2453
- readonly server: ServerDataManager<TRow> | null;
2454
1874
  private readonly strategy;
2455
- private readonly serverStrategy;
2456
1875
  private snapshotReader;
2457
1876
  private flagReader;
2458
1877
  private buildErrorBitmask;
@@ -2467,16 +1886,10 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2467
1886
  private filterRowReader;
2468
1887
  private bulkMutationHost;
2469
1888
  private orchestrator;
2470
- constructor(mode?: StoreMode, serverInit?: {
2471
- config: ScaleClientApi<TRow>;
2472
- sourceLabel: string;
2473
- }, errorHandler?: ErrorHandler);
2474
- get mode(): StoreMode;
2475
- getEditBuilder(): ServerEditBuilder<TRow> | null;
1889
+ constructor(errorHandler?: ErrorHandler);
2476
1890
  getRowId(index: number): TRowId | undefined;
2477
1891
  getLocalRowCount(): number;
2478
1892
  setValidator(validator: IValidator<TRow>): void;
2479
- setPrimaryKey(key: PrimaryKeyInput): void;
2480
1893
  isColumnLocked(field: string): boolean;
2481
1894
  isColumnPreLocked(field: string): boolean;
2482
1895
  lockColumn(field: string, mode?: ColumnLockMode): void;
@@ -2558,35 +1971,19 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2558
1971
  * Flag rows as deleted. Pushes a command for undo/redo.
2559
1972
  * Rows stay in all stores — they are just excluded from alive-mode filters.
2560
1973
  */
2561
- deleteRows(rowIds: TRowId[], rowRanges?: [TRowId, TRowId][]): Promise<void>;
1974
+ deleteRows(rowIds: TRowId[]): Promise<void>;
2562
1975
  /**
2563
- * Delete all visible rows at once. In server mode sends { allSelected: true }
2564
- * instead of enumerating every row. Locally marks all loaded rows as deleted
2565
- * and clears the RowStore display list.
1976
+ * Delete all visible rows at once. Marks all loaded rows as deleted.
2566
1977
  */
2567
1978
  deleteAllRows(): Promise<void>;
2568
- /**
2569
- * Optimistic bulk delete for server mode. Marks all locally loaded rows
2570
- * as deleted, clears the RowStore, and adjusts counts.
2571
- */
2572
- private deleteAllServer;
2573
1979
  /**
2574
1980
  * Unflag rows (restore from deletion). Pushes a command for undo/redo.
2575
1981
  */
2576
- restoreRows(rowIds: TRowId[], rowRanges?: [TRowId, TRowId][]): Promise<void>;
1982
+ restoreRows(rowIds: TRowId[]): Promise<void>;
2577
1983
  /**
2578
- * Restore all deleted rows at once. In server mode sends { allSelected: true }
2579
- * instead of enumerating every row. Locally clears all deleted flags and
2580
- * empties the RowStore display list (bin view becomes empty).
1984
+ * Restore all deleted rows at once. Clears every deleted flag.
2581
1985
  */
2582
1986
  restoreAllRows(): Promise<void>;
2583
- /**
2584
- * Optimistic bulk restore for server mode. Clears all locally known deleted
2585
- * flags and empties the RowStore display list (we are in deleted-only view,
2586
- * so every visible row is being restored out). Server-provided counts will
2587
- * be authoritative after the sync response arrives.
2588
- */
2589
- private restoreAllDeletedServer;
2590
1987
  /**
2591
1988
  * Apply delete flags directly without cost-gating. Called by commands
2592
1989
  * (DeleteRowCommand.redo/undo, restore inline commands) where runHeavy
@@ -2602,16 +1999,13 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2602
1999
  insertRow(sourceId: DataSourceId, row: TRow, position: number): Promise<TRowId>;
2603
2000
  insertRowDirect(rowId: TRowId, row: TRow, sourceId: DataSourceId, position: number): void;
2604
2001
  /**
2605
- * Ingest a single ServerRow at a specific local position.
2606
- * Used after the server confirms an insert and returns the full row.
2607
- * Source counts come from the server via counts.sources no local source tracking.
2002
+ * Append rows supplied by the client through `loadData`. Date columns are
2003
+ * canonicalised to ISO, number columns to the canonical stored form, and
2004
+ * `column.transformer` runs, matching what a file import does. `appendRows` stays a plain append, so the import path — which
2005
+ * has already normalised through buildImportRow — never transforms twice.
2608
2006
  */
2609
- insertServerRow(serverRow: ServerRow<TRow>, position: number): TRowId;
2610
- /**
2611
- * Server-mode insert: send insert request to server, wait for response,
2612
- * then ingest the returned row locally. Non-optimistic.
2613
- */
2614
- insertRowServer(row: TRow, localPosition: number, anchorRowId: TRowId | undefined, insertPosition: "above" | "below", columnIds: string[]): Promise<TRowId>;
2007
+ appendClientRows(sourceId: DataSourceId, newRows: TRow[]): TRowId[];
2008
+ private normalizeClientRows;
2615
2009
  appendRows(sourceId: DataSourceId, newRows: TRow[], rowIdMap?: Map<number, TRowId>): TRowId[];
2616
2010
  seedInitialChanges(assignedRowIds: TRowId[], currentRows: TRow[], changes: InitialRowChange<TRow>[]): void;
2617
2011
  upsertRows(sourceId: DataSourceId, newRows: TRow[], options?: UpsertOptions): UpsertResult<TRow>;
@@ -2627,7 +2021,8 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2627
2021
  * Called by the orchestrator after all chunks complete, before validation.
2628
2022
  * Deferred per-row work from updateColumnDirect is flushed here in bulk:
2629
2023
  * - rowTextCache cleared once instead of per-row
2630
- * - checkRevert run for each affected row
2024
+ * - checkRevert and checkRowEmptyCells run for each affected row
2025
+ * - the filter worker gets every affected row's text in one batch
2631
2026
  * - _editedCells populated for FindReplace incremental matching
2632
2027
  */
2633
2028
  flushBulkMode(deltas: ColumnDelta[]): void;
@@ -2640,30 +2035,12 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2640
2035
  */
2641
2036
  getViewportRowIds(): TRowId[];
2642
2037
  getAllFilteredRowIds(): TRowId[];
2643
- replaceServerRows(sourceId: DataSourceId, serverRows: ServerRow<TRow>[], offset: number, counts?: ServerQueryCounts): void;
2644
- appendServerRows(serverRows: ServerRow<TRow>[], counts?: ServerQueryCounts): void;
2645
- prependServerRows(serverRows: ServerRow<TRow>[], newOffset: number, counts?: ServerQueryCounts): void;
2646
- /**
2647
- * Seeds DirtyTracker from server-provided row metadata.
2648
- * For rows with `meta.status.edited`, builds a synthetic original row
2649
- * from `meta.changes` so that `isCellDirty()` and `getOriginalCellValue()`
2650
- * work through the existing DirtyTracker comparison logic.
2651
- */
2652
- private hydrateServerMeta;
2653
- private hydrateRowMeta;
2654
- applyServerRowMeta(serverRows: ServerRow<TRow>[], counts?: ServerQueryCounts): void;
2655
2038
  clear(): void;
2656
2039
  destroy(): void;
2657
2040
  setFilters(filters: Partial<Filters>): void;
2658
2041
  getFilters(): Filters;
2659
2042
  setSort(sortState: SortState, sortType?: SortType, locales?: string[]): Promise<void>;
2660
- handleServerScroll(visibleStart: number, visibleEnd: number): void;
2661
- reloadServerData(): void;
2662
2043
  resetFilters(): void;
2663
- fetchFilterOptions(): void;
2664
- getFilterOptions(): FilterOptionsResponse | null;
2665
- get hasServerExport(): boolean;
2666
- serverExport(format: DataEditorFormat, allRows: boolean, rtl: boolean): Promise<void>;
2667
2044
  syncWorkerFlags(): void;
2668
2045
  setCellValidation(rowId: TRowId, field: string, result: ValidationResult): void;
2669
2046
  getCellValidation(rowId: TRowId, field: string): ValidationResult;
@@ -2694,14 +2071,6 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2694
2071
  undo(): Promise<UndoRedoResult>;
2695
2072
  private _undoSync;
2696
2073
  pushCommand(cmd: Command<TRow>, cost?: number): number;
2697
- removeCommandById(id: number): void;
2698
- /**
2699
- * Delegate to ServerStrategy. Called by ActionsDispatcher and ClipboardManager
2700
- * for non-cell edits (clear, paste, fill, transform).
2701
- */
2702
- syncServerEdit(params: EditParams, cmdId: number, revertFn: () => void): void;
2703
- fireServerEditParams(params: EditParams): void;
2704
- syncColumnEdit(params: ColumnEditParams, cmdId: number, revertFn: () => void): void;
2705
2074
  redo(): Promise<UndoRedoResult>;
2706
2075
  private _redoSync;
2707
2076
  getOriginalCellValue(rowId: TRowId, field: string): unknown | undefined;
@@ -2732,7 +2101,6 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2732
2101
  private _runFormulaOperation;
2733
2102
  private captureDeleteColumnSnapshots;
2734
2103
  private applyDeleteColumnSnapshots;
2735
- private syncFormulaToServer;
2736
2104
  private transformWorker;
2737
2105
  private initTransformWorker;
2738
2106
  private buildChatOpsCommand;
@@ -2744,21 +2112,17 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2744
2112
  private _applyChatOpsSync;
2745
2113
  private _commitChatOps;
2746
2114
  applyChatRows(incomingRows: Record<string, unknown>[], primaryKey: PrimaryKeyInput): Promise<void>;
2747
- private syncChatTransformToServer;
2748
2115
  private get revertRowReader();
2749
2116
  revertColumns(fields: string[]): Promise<void>;
2750
2117
  revertRange(rects: SelectionRect[]): Promise<void>;
2751
2118
  private _revertInternal;
2752
2119
  private _buildRevertCommand;
2753
- private syncRevertToServer;
2754
2120
  clearColumn(field: string): Promise<void>;
2755
2121
  clearColumns(fields: string[]): Promise<void>;
2756
- private syncClearToServer;
2757
2122
  purgeField(columnId: string, rowIds?: TRowId[]): void;
2758
2123
  deleteColumn(columnId: string): Promise<void>;
2759
2124
  deleteColumns(columnIds: readonly string[]): Promise<void>;
2760
2125
  clearRange(rects: SelectionRect[]): Promise<void>;
2761
- private syncRangeClearToServer;
2762
2126
  pasteChunked(spec: PasteSpec, targetRowIds: TRowId[], targetCell: {
2763
2127
  rowId: TRowId;
2764
2128
  field: string;
@@ -2798,7 +2162,7 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
2798
2162
  * Each command knows how to apply and revert its changes.
2799
2163
  */
2800
2164
  interface Command<TRow extends DataEditorRow = DataEditorRow> {
2801
- /** Assigned by CommandHistory.push(). Used by removeById() to target specific commands. */
2165
+ /** Assigned by CommandHistory.push() and handed back as its return value. */
2802
2166
  id?: number;
2803
2167
  redo(store: DataStore<TRow>, validator: IValidator<TRow>): void;
2804
2168
  undo(store: DataStore<TRow>, validator: IValidator<TRow>): void;
@@ -2827,10 +2191,6 @@ type ColumnDelta = {
2827
2191
  newValues: Map<TRowId, unknown>;
2828
2192
  };
2829
2193
 
2830
- type ScaleServerConfig = {
2831
- url: string;
2832
- };
2833
-
2834
2194
  /** Numeric row identifier. V8 stores small integers (Smi) inline — no heap allocation. */
2835
2195
  type TRowId = number;
2836
2196
  type SortType = "text" | "number" | "date";
@@ -3384,11 +2744,6 @@ type DataEditorMode = "modal" | "inline";
3384
2744
  type DataEditorCommonProps<TRow extends DataEditorRow = DataEditorRow> = DataEditorBaseProps<TRow> & {
3385
2745
  /** Your Updog license key. Validated on each open. */
3386
2746
  apiKey: string;
3387
- /**
3388
- * @internal
3389
- * Reserved for future server-delegated mode. Not part of the public API.
3390
- */
3391
- __server?: ScaleServerConfig;
3392
2747
  /**
3393
2748
  * Controls what the editor stores in `localStorage`. Set to `false` to
3394
2749
  * disable all local storage usage.
@@ -3516,7 +2871,7 @@ declare function exportDataEditor<TRow extends DataEditorRow>(params: ExportPara
3516
2871
  * />
3517
2872
  * ```
3518
2873
  */
3519
- declare function DataEditor<TRow extends DataEditorRow = DataEditorRow>(allProps: DataEditorProps<TRow>): react_jsx_runtime.JSX.Element;
2874
+ declare function DataEditor<TRow extends DataEditorRow = DataEditorRow>(allProps: DataEditorProps<TRow>): react.JSX.Element;
3520
2875
 
3521
2876
  export { DataEditor, downloadExampleFile, exportDataEditor };
3522
2877
  export type { CellValidator, ChatContext, ChatErrorSummary, ChatResponseChunk, ChatRow, ChatRowStatus, ChunkSourceOptions, CustomImportFormat, CustomImportTable, DataEditorChat, DataEditorColumn, DataEditorFormat, DataEditorInlineProps, DataEditorLocalStorage, DataEditorModalProps, DataEditorMode, DataEditorProps, DataEditorResult, DataEditorRow, DataEditorSourceResult, DataEditorTranslations, DataEditorVariant, InitialRowChange, RemoteSource, ResultRow, UpdogError, UpdogErrorCode, ValidationError, ValueMatchInput, ValueMatchOutput };