@updog/data-editor-wc 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 +72 -33
- package/index.d.ts +12 -10
- 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
|
@@ -45,7 +45,6 @@ How you wire the element into a framework (Angular's `CUSTOM_ELEMENTS_SCHEMA`, V
|
|
|
45
45
|
<script type="module">
|
|
46
46
|
import "@updog/data-editor-wc";
|
|
47
47
|
import "@updog/data-editor-wc/styles.css";
|
|
48
|
-
import { required, email } from "@updog/data-editor-wc";
|
|
49
48
|
|
|
50
49
|
const editor = document.getElementById("editor");
|
|
51
50
|
|
|
@@ -53,9 +52,26 @@ How you wire the element into a framework (Angular's `CUSTOM_ELEMENTS_SCHEMA`, V
|
|
|
53
52
|
apiKey: "your-license-key",
|
|
54
53
|
primaryKey: "id",
|
|
55
54
|
columns: [
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
{
|
|
56
|
+
id: "name",
|
|
57
|
+
title: "Full Name",
|
|
58
|
+
size: 200,
|
|
59
|
+
validators: [{ type: "required", message: "Name is required" }],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "email",
|
|
63
|
+
title: "Email",
|
|
64
|
+
size: 250,
|
|
65
|
+
validators: [
|
|
66
|
+
{ type: "required", message: "Email is required" },
|
|
67
|
+
{ type: "email", message: "Invalid email" },
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "role",
|
|
72
|
+
title: "Role",
|
|
73
|
+
editor: { type: "select", options: ["Admin", "Editor", "Viewer"] },
|
|
74
|
+
},
|
|
59
75
|
],
|
|
60
76
|
loadData: async (onChunk) => {
|
|
61
77
|
const res = await fetch("/api/employees");
|
|
@@ -190,16 +206,17 @@ editor.addEventListener("close", () => editor.hide());
|
|
|
190
206
|
## Column Configuration
|
|
191
207
|
|
|
192
208
|
```js
|
|
193
|
-
import { required, email } from "@updog/data-editor-wc";
|
|
194
|
-
|
|
195
209
|
editor.columns = [
|
|
196
210
|
{
|
|
197
211
|
id: "email",
|
|
198
212
|
title: "Email",
|
|
199
213
|
size: 260,
|
|
200
214
|
|
|
201
|
-
//
|
|
202
|
-
|
|
215
|
+
// Declarative validators. See "Built-in Validators" for the full list.
|
|
216
|
+
validators: [
|
|
217
|
+
{ type: "required", message: "Email is required" },
|
|
218
|
+
{ type: "email", message: "Enter a valid email" },
|
|
219
|
+
],
|
|
203
220
|
|
|
204
221
|
// Flag duplicates in this column as errors.
|
|
205
222
|
unique: true,
|
|
@@ -231,36 +248,42 @@ editor.columns = [
|
|
|
231
248
|
|
|
232
249
|
## Built-in Validators
|
|
233
250
|
|
|
234
|
-
Validators are
|
|
251
|
+
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.
|
|
235
252
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
253
|
+
| `type` | Fields | Behavior |
|
|
254
|
+
|---|---|---|
|
|
255
|
+
| `"required"` | `message?` | Value must be non-empty. |
|
|
256
|
+
| `"email"` | `message?` | Value must look like an email address. |
|
|
257
|
+
| `"numeric"` | `message?` | Value must parse as a number. Commas are stripped before parsing. |
|
|
258
|
+
| `"regex"` | `pattern`, `flags?`, `message?` | Value must match the regular expression. Empty values are skipped. |
|
|
259
|
+
| `"range"` | `min?`, `max?`, `message?` | Value must be numerically within `[min, max]`. Either bound is optional. |
|
|
260
|
+
| `"oneOf"` | `values: string[]`, `message?` | Value must be one of the listed strings. |
|
|
261
|
+
| `"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. |
|
|
245
262
|
|
|
263
|
+
```js
|
|
246
264
|
editor.columns = [
|
|
247
|
-
{ id: "name", title: "Name",
|
|
248
|
-
{
|
|
249
|
-
|
|
250
|
-
|
|
265
|
+
{ id: "name", title: "Name", validators: [{ type: "required", message: "Required" }] },
|
|
266
|
+
{
|
|
267
|
+
id: "email",
|
|
268
|
+
title: "Email",
|
|
269
|
+
validators: [
|
|
270
|
+
{ type: "required", message: "Required" },
|
|
271
|
+
{ type: "email", message: "Invalid email" },
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
{ id: "salary", title: "Salary", validators: [{ type: "numeric", message: "Must be a number" }] },
|
|
275
|
+
{
|
|
276
|
+
id: "status",
|
|
277
|
+
title: "Status",
|
|
278
|
+
validators: [{ type: "oneOf", values: ["active", "inactive"], message: "Invalid status" }],
|
|
279
|
+
},
|
|
251
280
|
{
|
|
252
281
|
id: "startDate",
|
|
253
282
|
title: "Start",
|
|
254
|
-
|
|
283
|
+
validators: [{ type: "date", format: "YYYY-MM-DD", message: "Use YYYY-MM-DD" }],
|
|
255
284
|
editor: { type: "date" },
|
|
256
285
|
dependentFields: ["endDate"],
|
|
257
286
|
},
|
|
258
|
-
{
|
|
259
|
-
id: "endDate",
|
|
260
|
-
title: "End",
|
|
261
|
-
validate: [date("Invalid date"), endDateAfterStart("startDate", "End must be on or after start")],
|
|
262
|
-
editor: { type: "date" },
|
|
263
|
-
},
|
|
264
287
|
];
|
|
265
288
|
```
|
|
266
289
|
|
|
@@ -268,16 +291,32 @@ A `ValidationError` with `level: "error"` flags the cell in the grid but does **
|
|
|
268
291
|
|
|
269
292
|
### Custom validators
|
|
270
293
|
|
|
271
|
-
|
|
294
|
+
For cross-field checks or anything not covered by the built-ins, wrap a `(value, row) => ValidationError | null` 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.
|
|
272
295
|
|
|
273
296
|
```js
|
|
274
|
-
const
|
|
275
|
-
if (!value) return null;
|
|
276
|
-
if (
|
|
297
|
+
const endAfterStart = (value, row) => {
|
|
298
|
+
if (!value || !row.startDate) return null;
|
|
299
|
+
if (String(value) < String(row.startDate)) {
|
|
300
|
+
return { level: "error", message: "End must be on or after start" };
|
|
301
|
+
}
|
|
277
302
|
return null;
|
|
278
303
|
};
|
|
304
|
+
|
|
305
|
+
editor.columns = [
|
|
306
|
+
{
|
|
307
|
+
id: "endDate",
|
|
308
|
+
title: "End",
|
|
309
|
+
editor: { type: "date" },
|
|
310
|
+
validators: [
|
|
311
|
+
{ type: "date", message: "Invalid date" },
|
|
312
|
+
{ type: "function", fn: endAfterStart },
|
|
313
|
+
],
|
|
314
|
+
},
|
|
315
|
+
];
|
|
279
316
|
```
|
|
280
317
|
|
|
318
|
+
The only `level` is `"error"`. Return `null` to indicate the value is valid.
|
|
319
|
+
|
|
281
320
|
## Data Loading
|
|
282
321
|
|
|
283
322
|
`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.d.ts
CHANGED
|
@@ -1427,18 +1427,20 @@ type UpdogEditorProps = Omit<Props, "onClose" | "className"> & {
|
|
|
1427
1427
|
/** Close the editor modal. Same as setting `editor.open = false`. */
|
|
1428
1428
|
hide(): void;
|
|
1429
1429
|
};
|
|
1430
|
+
/**
|
|
1431
|
+
* The `<updog-editor>` custom element. A full-screen modal spreadsheet editor.
|
|
1432
|
+
*
|
|
1433
|
+
* Supports CSV/XLSX import, cell validation, undo/redo, find & replace, and exporting.
|
|
1434
|
+
* Works in any framework (Angular, Vue, vanilla JS) — no React needed.
|
|
1435
|
+
*
|
|
1436
|
+
* @see {@link UpdogEditorProps} for all available properties.
|
|
1437
|
+
*/
|
|
1438
|
+
interface UpdogEditorElement extends HTMLElement, UpdogEditorProps {
|
|
1439
|
+
}
|
|
1430
1440
|
declare global {
|
|
1431
|
-
/**
|
|
1432
|
-
* The `<updog-editor>` custom element. A full-screen modal spreadsheet editor.
|
|
1433
|
-
*
|
|
1434
|
-
* Supports CSV/XLSX import, cell validation, undo/redo, find & replace, and exporting.
|
|
1435
|
-
* Works in any framework (Angular, Vue, vanilla JS) — no React needed.
|
|
1436
|
-
*
|
|
1437
|
-
* @see {@link UpdogEditorProps} for all available properties.
|
|
1438
|
-
*/
|
|
1439
|
-
interface UpdogEditorElement extends HTMLElement, UpdogEditorProps {
|
|
1440
|
-
}
|
|
1441
1441
|
interface HTMLElementTagNameMap {
|
|
1442
1442
|
"updog-editor": UpdogEditorElement;
|
|
1443
1443
|
}
|
|
1444
1444
|
}
|
|
1445
|
+
|
|
1446
|
+
export type { UpdogEditorElement, UpdogEditorProps };
|
package/index.js
CHANGED
|
@@ -39027,17 +39027,27 @@ var dN = ({ source: e }) => {
|
|
|
39027
39027
|
})]
|
|
39028
39028
|
})
|
|
39029
39029
|
}), xN = ({ filtersResetKey: e }) => {
|
|
39030
|
-
let { store: t, scrollToGridTop: n } = Bd(), { t: r } = k(), { filteredErrorCount: i, errorMessageCounts: a } = nl(t), [o, s] = (0, _.useState)(() => new Set(t.getFilters().errorMessageFilters ?? []));
|
|
39030
|
+
let { store: t, scrollToGridTop: n } = Bd(), { t: r } = k(), { filteredErrorCount: i, errorMessageCounts: a } = nl(t), [o, s] = (0, _.useState)(() => new Set(t.getFilters().errorMessageFilters ?? [])), [c, l] = (0, _.useState)(!1);
|
|
39031
39031
|
(0, _.useEffect)(() => {
|
|
39032
|
-
s(new Set(t.getFilters().errorMessageFilters ?? []));
|
|
39032
|
+
s(new Set(t.getFilters().errorMessageFilters ?? [])), l(!1);
|
|
39033
39033
|
}, [e, t]);
|
|
39034
|
-
let
|
|
39035
|
-
|
|
39034
|
+
let u = Object.keys(a), d = u.length > 0;
|
|
39035
|
+
(0, _.useEffect)(() => {
|
|
39036
|
+
!c || !d || (s(new Set(u)), t.setFilters({ errorMessageFilters: u }), l(!1));
|
|
39036
39037
|
}, [
|
|
39037
39038
|
c,
|
|
39039
|
+
d,
|
|
39040
|
+
u,
|
|
39041
|
+
t
|
|
39042
|
+
]);
|
|
39043
|
+
let f = d && u.every((e) => o.has(e)), p = u.some((e) => o.has(e)), m = d ? f : c, h = d && p && !f, g = (0, _.useCallback)((e) => {
|
|
39044
|
+
l(e), d && (s(e ? new Set(u) : /* @__PURE__ */ new Set()), n(), t.setFilters({ errorMessageFilters: e ? u : [] }));
|
|
39045
|
+
}, [
|
|
39046
|
+
d,
|
|
39047
|
+
u,
|
|
39038
39048
|
n,
|
|
39039
39049
|
t
|
|
39040
|
-
]),
|
|
39050
|
+
]), v = (0, _.useCallback)((e, r) => {
|
|
39041
39051
|
s((i) => {
|
|
39042
39052
|
let a = new Set(i);
|
|
39043
39053
|
return r ? a.add(e) : a.delete(e), t.setFilters({ errorMessageFilters: [...a] }), n(), a;
|
|
@@ -39049,9 +39059,9 @@ var dN = ({ source: e }) => {
|
|
|
39049
39059
|
trigger: ({ toggle: e, isOpen: t }) => {
|
|
39050
39060
|
let n = r(t ? "dataEditor.filters.showLess" : "dataEditor.filters.showMore");
|
|
39051
39061
|
return /* @__PURE__ */ (0, E.jsx)(Tt, {
|
|
39052
|
-
checked:
|
|
39053
|
-
indeterminate:
|
|
39054
|
-
onChange:
|
|
39062
|
+
checked: m,
|
|
39063
|
+
indeterminate: h,
|
|
39064
|
+
onChange: g,
|
|
39055
39065
|
checkboxPosition: "start",
|
|
39056
39066
|
children: /* @__PURE__ */ (0, E.jsxs)("div", {
|
|
39057
39067
|
className: "updog__error-filter-section__checkbox-label",
|
|
@@ -39060,7 +39070,7 @@ var dN = ({ source: e }) => {
|
|
|
39060
39070
|
className: "updog__error-filter-section__truncated",
|
|
39061
39071
|
children: r("dataEditor.filters.rowsWithErrors")
|
|
39062
39072
|
}),
|
|
39063
|
-
|
|
39073
|
+
u.length > 0 && /* @__PURE__ */ (0, E.jsx)(Ps, {
|
|
39064
39074
|
content: n,
|
|
39065
39075
|
children: /* @__PURE__ */ (0, E.jsx)(nt, {
|
|
39066
39076
|
variant: "ghost",
|
|
@@ -39083,13 +39093,13 @@ var dN = ({ source: e }) => {
|
|
|
39083
39093
|
})
|
|
39084
39094
|
});
|
|
39085
39095
|
},
|
|
39086
|
-
content:
|
|
39096
|
+
content: u.length > 0 && /* @__PURE__ */ (0, E.jsx)("div", {
|
|
39087
39097
|
className: "updog__error-filter-section__children",
|
|
39088
|
-
children:
|
|
39098
|
+
children: u.map((e) => /* @__PURE__ */ (0, E.jsx)(bN, {
|
|
39089
39099
|
message: e,
|
|
39090
39100
|
count: a[e] ?? 0,
|
|
39091
39101
|
checked: o.has(e),
|
|
39092
|
-
onChange:
|
|
39102
|
+
onChange: v
|
|
39093
39103
|
}, e))
|
|
39094
39104
|
})
|
|
39095
39105
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@updog/data-editor-wc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Client-side CSV importer and spreadsheet editor SDK as a Web Component. Drop into Vue, Angular, Svelte, or vanilla JS. Import CSV, Excel, JSON; edit 1M+ rows entirely in the browser.",
|
|
5
5
|
"author": "Mikhail Kutateladze <admin@updog.tech>",
|
|
6
6
|
"homepage": "https://updog.tech",
|