@updog/data-editor 0.1.17 → 0.1.19
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/LICENSE +4 -2
- package/README.md +75 -34
- package/index.js +22 -12
- package/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -232,8 +232,10 @@ Sections 5, 8, 11, 12, and 14 survive termination of this License.
|
|
|
232
232
|
--------------------------------------------------------------------------------
|
|
233
233
|
|
|
234
234
|
This License shall be governed by and construed in accordance with the laws of
|
|
235
|
-
the
|
|
236
|
-
|
|
235
|
+
the Dubai International Financial Centre (DIFC), as applied by the DIFC Courts.
|
|
236
|
+
Any dispute arising out of or in connection with this License, including any
|
|
237
|
+
question regarding its existence, validity, or termination, shall be subject to
|
|
238
|
+
the exclusive jurisdiction of the courts of the DIFC.
|
|
237
239
|
|
|
238
240
|
--------------------------------------------------------------------------------
|
|
239
241
|
15. EXPORT COMPLIANCE
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npm install @updog/data-editor
|
|
|
29
29
|
|
|
30
30
|
```tsx
|
|
31
31
|
import { useState } from "react";
|
|
32
|
-
import { DataEditor
|
|
32
|
+
import { DataEditor } from "@updog/data-editor";
|
|
33
33
|
import "@updog/data-editor/styles.css";
|
|
34
34
|
import type { DataEditorColumn } from "@updog/data-editor";
|
|
35
35
|
|
|
@@ -41,9 +41,26 @@ type Employee = {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
const columns: DataEditorColumn[] = [
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
{
|
|
45
|
+
id: "name",
|
|
46
|
+
title: "Full Name",
|
|
47
|
+
size: 200,
|
|
48
|
+
validators: [{ type: "required", message: "Name is required" }],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "email",
|
|
52
|
+
title: "Email",
|
|
53
|
+
size: 250,
|
|
54
|
+
validators: [
|
|
55
|
+
{ type: "required", message: "Email is required" },
|
|
56
|
+
{ type: "email", message: "Invalid email" },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "role",
|
|
61
|
+
title: "Role",
|
|
62
|
+
editor: { type: "select", options: ["Admin", "Editor", "Viewer"] },
|
|
63
|
+
},
|
|
47
64
|
];
|
|
48
65
|
|
|
49
66
|
export function App() {
|
|
@@ -147,7 +164,6 @@ In inline mode, `open` and `onClose` don't apply.
|
|
|
147
164
|
## Column Configuration
|
|
148
165
|
|
|
149
166
|
```tsx
|
|
150
|
-
import { required, email } from "@updog/data-editor";
|
|
151
167
|
import type { DataEditorColumn } from "@updog/data-editor";
|
|
152
168
|
|
|
153
169
|
const columns: DataEditorColumn[] = [
|
|
@@ -156,8 +172,11 @@ const columns: DataEditorColumn[] = [
|
|
|
156
172
|
title: "Email",
|
|
157
173
|
size: 260,
|
|
158
174
|
|
|
159
|
-
//
|
|
160
|
-
|
|
175
|
+
// Declarative validators. See "Built-in Validators" for the full list.
|
|
176
|
+
validators: [
|
|
177
|
+
{ type: "required", message: "Email is required" },
|
|
178
|
+
{ type: "email", message: "Enter a valid email" },
|
|
179
|
+
],
|
|
161
180
|
|
|
162
181
|
// Flag duplicates in this column as errors.
|
|
163
182
|
unique: true,
|
|
@@ -189,36 +208,42 @@ const columns: DataEditorColumn[] = [
|
|
|
189
208
|
|
|
190
209
|
## Built-in Validators
|
|
191
210
|
|
|
192
|
-
Validators are
|
|
211
|
+
Validators are declarative objects passed in the `validators` array on each column. The SDK ships a TS interpreter for the client; Updog Scale ships a matching Go interpreter for server mode. Both runtimes are pinned to the same fixture set, so a column definition produces identical pass/fail results regardless of where it runs.
|
|
212
|
+
|
|
213
|
+
| `type` | Fields | Behavior |
|
|
214
|
+
|---|---|---|
|
|
215
|
+
| `"required"` | `message?` | Value must be non-empty. |
|
|
216
|
+
| `"email"` | `message?` | Value must look like an email address. |
|
|
217
|
+
| `"numeric"` | `message?` | Value must parse as a number. Commas are stripped before parsing. |
|
|
218
|
+
| `"regex"` | `pattern`, `flags?`, `message?` | Value must match the regular expression. Empty values are skipped. |
|
|
219
|
+
| `"range"` | `min?`, `max?`, `message?` | Value must be numerically within `[min, max]`. Either bound is optional. |
|
|
220
|
+
| `"oneOf"` | `values: string[]`, `message?` | Value must be one of the listed strings. |
|
|
221
|
+
| `"date"` | `format?: "YYYY-MM-DD" \| "DD/MM/YYYY"`, `message?` | Value must parse as a date in the given format. When `format` is omitted, either format is accepted. |
|
|
193
222
|
|
|
194
223
|
```tsx
|
|
195
|
-
|
|
196
|
-
required,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
{ id: "
|
|
206
|
-
{
|
|
207
|
-
|
|
208
|
-
|
|
224
|
+
const columns: DataEditorColumn[] = [
|
|
225
|
+
{ id: "name", title: "Name", validators: [{ type: "required", message: "Required" }] },
|
|
226
|
+
{
|
|
227
|
+
id: "email",
|
|
228
|
+
title: "Email",
|
|
229
|
+
validators: [
|
|
230
|
+
{ type: "required", message: "Required" },
|
|
231
|
+
{ type: "email", message: "Invalid email" },
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
{ id: "salary", title: "Salary", validators: [{ type: "numeric", message: "Must be a number" }] },
|
|
235
|
+
{
|
|
236
|
+
id: "status",
|
|
237
|
+
title: "Status",
|
|
238
|
+
validators: [{ type: "oneOf", values: ["active", "inactive"], message: "Invalid status" }],
|
|
239
|
+
},
|
|
209
240
|
{
|
|
210
241
|
id: "startDate",
|
|
211
242
|
title: "Start",
|
|
212
|
-
|
|
243
|
+
validators: [{ type: "date", format: "YYYY-MM-DD", message: "Use YYYY-MM-DD" }],
|
|
213
244
|
editor: { type: "date" },
|
|
214
245
|
dependentFields: ["endDate"],
|
|
215
246
|
},
|
|
216
|
-
{
|
|
217
|
-
id: "endDate",
|
|
218
|
-
title: "End",
|
|
219
|
-
validate: [date("Invalid date"), endDateAfterStart("startDate", "End must be on or after start")],
|
|
220
|
-
editor: { type: "date" },
|
|
221
|
-
},
|
|
222
247
|
];
|
|
223
248
|
```
|
|
224
249
|
|
|
@@ -226,18 +251,34 @@ A `ValidationError` with `level: "error"` flags the cell in the grid but does **
|
|
|
226
251
|
|
|
227
252
|
### Custom validators
|
|
228
253
|
|
|
229
|
-
|
|
254
|
+
For cross-field checks or anything not covered by the built-ins, wrap a `CellValidator` function in `{ type: "function", fn }`. Function validators are client-mode only — they're dropped (with a one-time warning) when the SDK serializes the schema for server mode. Use `dependentFields` on the column to trigger re-validation when another column changes.
|
|
230
255
|
|
|
231
256
|
```tsx
|
|
232
|
-
import type { CellValidator } from "@updog/data-editor";
|
|
257
|
+
import type { CellValidator, DataEditorColumn } from "@updog/data-editor";
|
|
233
258
|
|
|
234
|
-
const
|
|
235
|
-
if (!value) return null;
|
|
236
|
-
if (
|
|
259
|
+
const endAfterStart: CellValidator = (value, row) => {
|
|
260
|
+
if (!value || !row.startDate) return null;
|
|
261
|
+
if (String(value) < String(row.startDate)) {
|
|
262
|
+
return { level: "error", message: "End must be on or after start" };
|
|
263
|
+
}
|
|
237
264
|
return null;
|
|
238
265
|
};
|
|
266
|
+
|
|
267
|
+
const columns: DataEditorColumn[] = [
|
|
268
|
+
{
|
|
269
|
+
id: "endDate",
|
|
270
|
+
title: "End",
|
|
271
|
+
editor: { type: "date" },
|
|
272
|
+
validators: [
|
|
273
|
+
{ type: "date", message: "Invalid date" },
|
|
274
|
+
{ type: "function", fn: endAfterStart },
|
|
275
|
+
],
|
|
276
|
+
},
|
|
277
|
+
];
|
|
239
278
|
```
|
|
240
279
|
|
|
280
|
+
The only `level` is `"error"`. Return `null` to indicate the value is valid.
|
|
281
|
+
|
|
241
282
|
## Data Loading
|
|
242
283
|
|
|
243
284
|
`loadData` is called once when the editor opens. Call `onChunk` one or more times to stream rows. The grid renders each chunk without blocking.
|
package/index.js
CHANGED
|
@@ -22104,17 +22104,27 @@ var KS = ({ source: e }) => {
|
|
|
22104
22104
|
})]
|
|
22105
22105
|
})
|
|
22106
22106
|
}), nC = ({ filtersResetKey: e }) => {
|
|
22107
|
-
let { store: t, scrollToGridTop: n } = X(), { t: r } = q(), { filteredErrorCount: i, errorMessageCounts: a } = Mo(t), [o, s] = b(() => new Set(t.getFilters().errorMessageFilters ?? []));
|
|
22107
|
+
let { store: t, scrollToGridTop: n } = X(), { t: r } = q(), { filteredErrorCount: i, errorMessageCounts: a } = Mo(t), [o, s] = b(() => new Set(t.getFilters().errorMessageFilters ?? [])), [c, l] = b(!1);
|
|
22108
22108
|
m(() => {
|
|
22109
|
-
s(new Set(t.getFilters().errorMessageFilters ?? []));
|
|
22109
|
+
s(new Set(t.getFilters().errorMessageFilters ?? [])), l(!1);
|
|
22110
22110
|
}, [e, t]);
|
|
22111
|
-
let
|
|
22112
|
-
|
|
22111
|
+
let u = Object.keys(a), d = u.length > 0;
|
|
22112
|
+
m(() => {
|
|
22113
|
+
!c || !d || (s(new Set(u)), t.setFilters({ errorMessageFilters: u }), l(!1));
|
|
22113
22114
|
}, [
|
|
22114
22115
|
c,
|
|
22116
|
+
d,
|
|
22117
|
+
u,
|
|
22118
|
+
t
|
|
22119
|
+
]);
|
|
22120
|
+
let p = d && u.every((e) => o.has(e)), h = u.some((e) => o.has(e)), g = d ? p : c, _ = d && h && !p, v = f((e) => {
|
|
22121
|
+
l(e), d && (s(e ? new Set(u) : /* @__PURE__ */ new Set()), n(), t.setFilters({ errorMessageFilters: e ? u : [] }));
|
|
22122
|
+
}, [
|
|
22123
|
+
d,
|
|
22124
|
+
u,
|
|
22115
22125
|
n,
|
|
22116
22126
|
t
|
|
22117
|
-
]),
|
|
22127
|
+
]), y = f((e, r) => {
|
|
22118
22128
|
s((i) => {
|
|
22119
22129
|
let a = new Set(i);
|
|
22120
22130
|
return r ? a.add(e) : a.delete(e), t.setFilters({ errorMessageFilters: [...a] }), n(), a;
|
|
@@ -22126,9 +22136,9 @@ var KS = ({ source: e }) => {
|
|
|
22126
22136
|
trigger: ({ toggle: e, isOpen: t }) => {
|
|
22127
22137
|
let n = r(t ? "dataEditor.filters.showLess" : "dataEditor.filters.showMore");
|
|
22128
22138
|
return /* @__PURE__ */ C(Ni, {
|
|
22129
|
-
checked:
|
|
22130
|
-
indeterminate:
|
|
22131
|
-
onChange:
|
|
22139
|
+
checked: g,
|
|
22140
|
+
indeterminate: _,
|
|
22141
|
+
onChange: v,
|
|
22132
22142
|
checkboxPosition: "start",
|
|
22133
22143
|
children: /* @__PURE__ */ w("div", {
|
|
22134
22144
|
className: "updog__error-filter-section__checkbox-label",
|
|
@@ -22137,7 +22147,7 @@ var KS = ({ source: e }) => {
|
|
|
22137
22147
|
className: "updog__error-filter-section__truncated",
|
|
22138
22148
|
children: r("dataEditor.filters.rowsWithErrors")
|
|
22139
22149
|
}),
|
|
22140
|
-
|
|
22150
|
+
u.length > 0 && /* @__PURE__ */ C(la, {
|
|
22141
22151
|
content: n,
|
|
22142
22152
|
children: /* @__PURE__ */ C(ui, {
|
|
22143
22153
|
variant: "ghost",
|
|
@@ -22160,13 +22170,13 @@ var KS = ({ source: e }) => {
|
|
|
22160
22170
|
})
|
|
22161
22171
|
});
|
|
22162
22172
|
},
|
|
22163
|
-
content:
|
|
22173
|
+
content: u.length > 0 && /* @__PURE__ */ C("div", {
|
|
22164
22174
|
className: "updog__error-filter-section__children",
|
|
22165
|
-
children:
|
|
22175
|
+
children: u.map((e) => /* @__PURE__ */ C(tC, {
|
|
22166
22176
|
message: e,
|
|
22167
22177
|
count: a[e] ?? 0,
|
|
22168
22178
|
checked: o.has(e),
|
|
22169
|
-
onChange:
|
|
22179
|
+
onChange: y
|
|
22170
22180
|
}, e))
|
|
22171
22181
|
})
|
|
22172
22182
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@updog/data-editor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Client-side CSV importer and spreadsheet editor SDK for React. Import CSV, Excel, JSON, TSV, and XML, match columns, validate, and edit 1M+ rows entirely in the browser.",
|
|
5
5
|
"author": "Mikhail Kutateladze <admin@updog.tech>",
|
|
6
6
|
"homepage": "https://updog.tech",
|