@updog/data-editor-wc 0.1.18 → 0.1.20

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/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `@updog/data-editor` and `@updog/data-editor-wc` are docu
4
4
 
5
5
  This project follows [Semantic Versioning](https://semver.org/). While the version is `0.x`, minor version bumps may include breaking changes; we will call them out explicitly.
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ### Changed
10
+
11
+ - **Workers inlined as blob URLs.** Internal change: `filter` and `chatTransform` workers now ship inlined in the main bundle and spawn via `URL.createObjectURL`. Resolves loading failures in Next.js 16 / Turbopack and other non-Vite consumers. Adds ~27 KB to the main bundle (minified worker source, no source maps). Requires `worker-src blob:` in any strict Content-Security-Policy.
12
+
7
13
  ## [0.1.0] — 2026-04-21
8
14
 
9
15
  First public release.
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
- { id: "name", title: "Full Name", size: 200, validate: required("Name is required") },
57
- { id: "email", title: "Email", size: 250, validate: [required("Email is required"), email("Invalid email")] },
58
- { id: "role", title: "Role", editor: { type: "select", options: ["Admin", "Editor", "Viewer"] } },
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
- // One validator, or an array. Each returns `{ level: "error", message }` or null.
202
- validate: [required("Email is required"), email("Enter a valid email")],
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 factory functions call each one with the error message you want displayed.
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
- ```js
237
- import {
238
- required,
239
- numeric,
240
- email,
241
- date,
242
- oneOf,
243
- endDateAfterStart,
244
- } from "@updog/data-editor-wc";
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", validate: required("Required") },
248
- { id: "email", title: "Email", validate: [required("Required"), email("Invalid email")] },
249
- { id: "salary", title: "Salary", validate: numeric("Must be a number") },
250
- { id: "status", title: "Status", validate: oneOf(["active", "inactive"], "Invalid status") },
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
- validate: date("Use YYYY-MM-DD or DD/MM/YYYY"),
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
- A validator is `(value, row) => ValidationError | null`. The only `level` is `"error"`.
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 mustContainAt = (value) => {
275
- if (!value) return null;
276
- if (!String(value).includes("@")) return { level: "error", message: "Must contain @" };
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 };