@updog/data-editor 0.1.5 → 0.1.7

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.
@@ -0,0 +1 @@
1
+ (function(){function e(e){let{ops:t,rows:n,fields:r}=e,i={};for(let[t,n]of Object.entries(e.ctx.opts))i[t]=new Set(n);let a={opts:i},o=[],s=[];for(let e of t)try{let t=Function(`return `+e.fn)();s.push({action:e.action,fn:t})}catch(t){o.push(`Failed to compile ${e.action} op: ${t instanceof Error?t.message:String(t)}`)}let c=new Map,l=[];for(let[e,t]of n){let n={...t},i=!1;for(let e of s)if(e.action===`delete`)try{if(e.fn(n,a)){i=!0;break}}catch{}else try{e.fn(n,a)}catch{}if(i){l.push(e);continue}for(let i of r){let r=t[i],a=n[i];if(a!==r){let t=c.get(i);t||(t=[],c.set(i,t)),t.push([e,r,a])}}}let u=[];for(let[e,t]of c)u.push({field:e,changes:t});return{deltas:u,deleteIds:l,errors:o}}let t=self;self.addEventListener(`message`,n=>{try{let{ops:r,ctx:i,rows:a,fields:o}=n.data,s=e({ops:r,ctx:i,rows:a,fields:o});t.postMessage({type:`RESULT`,deltas:s.deltas,deleteIds:s.deleteIds,errors:s.errors})}catch(e){t.postMessage({type:`ERROR`,message:e instanceof Error?e.message:`Transform worker error`})}})})();
package/index.d.ts CHANGED
@@ -1379,6 +1379,189 @@ type PasteSpec = {
1379
1379
  isCut: boolean;
1380
1380
  };
1381
1381
 
1382
+ /**
1383
+ * Base row shape. Each key is a column ID, each value is the cell data.
1384
+ * Extend this with your own type via the `<DataEditor<TRow>>` generic for
1385
+ * type-safe column access. When the generic is omitted, rows are typed as
1386
+ * `Record<string, unknown>`.
1387
+ *
1388
+ * @example
1389
+ * ```ts
1390
+ * type Employee = { id: string; name: string; email: string };
1391
+ * <DataEditor<Employee> columns={...} primaryKey="id" />
1392
+ * ```
1393
+ */
1394
+ type DataEditorRow = Record<string, unknown>;
1395
+ /** Sort direction. */
1396
+ type SortDirection = "asc" | "desc";
1397
+ /** Current sort state. `null` means no active sort. */
1398
+ type SortState = {
1399
+ columnId: string;
1400
+ direction: SortDirection;
1401
+ } | null;
1402
+ type Filters = {
1403
+ search: string;
1404
+ matchCase: boolean;
1405
+ matchEntireCell: boolean;
1406
+ errorMessageFilters: string[];
1407
+ showOnlyNewRows: boolean;
1408
+ showOnlyEditedRows: boolean;
1409
+ showOnlyEmptyCells: boolean;
1410
+ /** When true, show only rows flagged for deletion (bin mode). All other filters are bypassed. */
1411
+ showOnlyDeletedRows: boolean;
1412
+ filterColumns: string[] | null;
1413
+ /** Per-column value filters. Key = column ID, value = allowed display-formatted strings. */
1414
+ columnValueFilters: Record<string, string[]>;
1415
+ /** Per-column numeric range filters. Key = column ID. */
1416
+ columnRangeFilters: Record<string, {
1417
+ min?: number;
1418
+ max?: number;
1419
+ }>;
1420
+ /** Per-column date range filters. Key = column ID, values are ISO date strings (YYYY-MM-DD). */
1421
+ columnDateRangeFilters: Record<string, {
1422
+ min?: string;
1423
+ max?: string;
1424
+ }>;
1425
+ };
1426
+
1427
+ /**
1428
+ * A single operation the LLM wants to apply to rows in the current filtered view.
1429
+ *
1430
+ * - `edit` — `fn` is `(r, ctx) => void`. Mutates `r` in place. Changed fields
1431
+ * become column deltas. Rows with no changes are no-ops.
1432
+ * - `delete` — `fn` is `(r, ctx) => boolean`. Truthy means "flag this row for
1433
+ * deletion". Soft delete via `DeleteRowCommand`.
1434
+ */
1435
+ type ChatOp = {
1436
+ action: "edit";
1437
+ fn: string;
1438
+ } | {
1439
+ action: "delete";
1440
+ fn: string;
1441
+ };
1442
+ /**
1443
+ * A single chunk in the stream returned from `DataEditorChat.onMessage`.
1444
+ *
1445
+ * - `status` — progress message shown while processing (e.g. "Analyzing 500 rows...").
1446
+ * - `message` — chat reply shown to the user.
1447
+ * - `rows` — updated rows to apply to the grid. Matched by `primaryKey`.
1448
+ * - `ops` — array of per-row operations (edits and/or deletes) to apply in order.
1449
+ */
1450
+ type ChatResponseChunk<TRow extends DataEditorRow = DataEditorRow> = {
1451
+ type: "status";
1452
+ content: string;
1453
+ } | {
1454
+ type: "message";
1455
+ content: string;
1456
+ } | {
1457
+ type: "rows";
1458
+ content: TRow[];
1459
+ } | {
1460
+ type: "ops";
1461
+ content: ChatOp[];
1462
+ };
1463
+ /** Status of a row in the chat sample, relative to its origin snapshot. */
1464
+ type ChatRowStatus = "new" | "edited" | "original";
1465
+ /** A sample row handed to the chat callback, with its current status and validation errors. */
1466
+ type ChatRow<TRow extends DataEditorRow = DataEditorRow> = {
1467
+ /** Row data keyed by column ID. */
1468
+ data: TRow;
1469
+ /** Whether the row was newly added, edited, or is unchanged. */
1470
+ status: ChatRowStatus;
1471
+ /** Validation errors keyed by column ID. */
1472
+ errors: Record<string, string[]>;
1473
+ /** The source this row belongs to. */
1474
+ source: string;
1475
+ };
1476
+ /** Aggregated error count across the current view, grouped by field and message. */
1477
+ type ChatErrorSummary = {
1478
+ /** Column ID where the error occurred. */
1479
+ field: string;
1480
+ /** The validation message. */
1481
+ message: string;
1482
+ /** How many rows hit this error. */
1483
+ count: number;
1484
+ /** A few example values that triggered the error. */
1485
+ examples: string[];
1486
+ };
1487
+ /**
1488
+ * Context about the current dataset, passed to `loadSuggestions` and extended
1489
+ * into `ChatContext` for `onMessage`.
1490
+ */
1491
+ type ChatDataContext<TRow extends DataEditorRow = DataEditorRow> = {
1492
+ /** Full column definitions. */
1493
+ columns: DataEditorColumn[];
1494
+ /** Row identifier field. */
1495
+ primaryKey: keyof TRow;
1496
+ /** Total rows in the dataset. */
1497
+ totalRowCount: number;
1498
+ /** Rows in the current filtered view. */
1499
+ filteredRowCount: number;
1500
+ /** Sample rows, with status and errors. Size controlled by `sampleSize`. */
1501
+ sample: ChatRow<TRow>[];
1502
+ /** Aggregated error counts by field and message. */
1503
+ errorSummary: ChatErrorSummary[];
1504
+ /** Access all rows. Use for full-dataset operations. */
1505
+ getRows: () => ChatRow<TRow>[];
1506
+ };
1507
+ /**
1508
+ * The full context passed to `DataEditorChat.onMessage` when the user sends
1509
+ * a prompt. Includes the prompt itself and all dataset context.
1510
+ */
1511
+ type ChatContext<TRow extends DataEditorRow = DataEditorRow> = ChatDataContext<TRow> & {
1512
+ /** The user's chat prompt. */
1513
+ message: string;
1514
+ };
1515
+ /**
1516
+ * Bring-your-own-AI chat configuration. When provided via the `chat` prop,
1517
+ * the editor shows a chat panel alongside the grid. You own the AI
1518
+ * integration; the SDK hands you dataset context and renders the streamed
1519
+ * response.
1520
+ *
1521
+ * @example
1522
+ * ```ts
1523
+ * chat={{
1524
+ * sampleSize: 50,
1525
+ * onMessage: async function* (context) {
1526
+ * yield { type: "status", content: "Thinking..." };
1527
+ * const res = await fetch("/api/ai", {
1528
+ * method: "POST",
1529
+ * body: JSON.stringify({
1530
+ * prompt: context.message,
1531
+ * columns: context.columns,
1532
+ * sample: context.sample.map(r => r.data),
1533
+ * errors: context.errorSummary,
1534
+ * }),
1535
+ * }).then(r => r.json());
1536
+ * yield { type: "rows", content: res.updatedRows };
1537
+ * yield { type: "ops", content: res.ops };
1538
+ * yield { type: "message", content: res.reply };
1539
+ * },
1540
+ * }}
1541
+ * ```
1542
+ */
1543
+ type DataEditorChat<TRow extends DataEditorRow = DataEditorRow> = {
1544
+ /**
1545
+ * How many rows to include in the context sample. The SDK picks a
1546
+ * representative slice including rows with errors. When omitted, the SDK decides.
1547
+ */
1548
+ sampleSize?: number;
1549
+ /** Title shown above the suggestion list when the chat is empty. */
1550
+ emptyTitle?: string;
1551
+ /** How many suggestions to request from `loadSuggestions`. */
1552
+ suggestionsCount?: number;
1553
+ /** Optional prompt generator for the empty-state suggestion chips. */
1554
+ loadSuggestions?: (context: ChatDataContext<TRow>) => Promise<string[]>;
1555
+ /**
1556
+ * Called when the user sends a message. Receives full dataset context.
1557
+ * Returns an async iterable of response chunks — the SDK streams them
1558
+ * into the UI.
1559
+ */
1560
+ onMessage: (context: ChatContext<TRow>) => AsyncIterable<ChatResponseChunk<TRow>>;
1561
+ /** Called when the user cancels a pending request. Use to abort your API call. */
1562
+ onCancel?: () => void;
1563
+ };
1564
+
1382
1565
  type ApplyFormulaOptions = {
1383
1566
  /**
1384
1567
  * Column IDs to delete AFTER the formula has been applied.
@@ -1683,12 +1866,14 @@ declare class DataStore<TRow extends DataEditorRow = DataEditorRow> {
1683
1866
  private syncFormulaToServer;
1684
1867
  private transformWorker;
1685
1868
  private initTransformWorker;
1686
- private buildChatTransformCommand;
1687
- applyChatTransform(fnString: string, ctx: {
1869
+ private buildChatOpsCommand;
1870
+ applyChatOps(ops: ChatOp[], ctx: {
1688
1871
  opts: Record<string, Set<string>>;
1689
- }): Promise<void>;
1690
- private _applyChatTransformViaWorker;
1691
- private _applyChatTransformSync;
1872
+ }, enableDeleteRow: 'all' | 'new' | false): Promise<void>;
1873
+ private filterDeleteIdsByPolicy;
1874
+ private _applyChatOpsViaWorker;
1875
+ private _applyChatOpsSync;
1876
+ private _commitChatOps;
1692
1877
  applyChatRows(incomingRows: Record<string, unknown>[], primaryKey: string): Promise<void>;
1693
1878
  private syncChatTransformToServer;
1694
1879
  private get revertRowReader();
@@ -1772,174 +1957,6 @@ type ColumnDelta = {
1772
1957
  newValues: Map<TRowId, unknown>;
1773
1958
  };
1774
1959
 
1775
- /**
1776
- * Base row shape. Each key is a column ID, each value is the cell data.
1777
- * Extend this with your own type via the `<DataEditor<TRow>>` generic for
1778
- * type-safe column access. When the generic is omitted, rows are typed as
1779
- * `Record<string, unknown>`.
1780
- *
1781
- * @example
1782
- * ```ts
1783
- * type Employee = { id: string; name: string; email: string };
1784
- * <DataEditor<Employee> columns={...} primaryKey="id" />
1785
- * ```
1786
- */
1787
- type DataEditorRow = Record<string, unknown>;
1788
- /** Sort direction. */
1789
- type SortDirection = "asc" | "desc";
1790
- /** Current sort state. `null` means no active sort. */
1791
- type SortState = {
1792
- columnId: string;
1793
- direction: SortDirection;
1794
- } | null;
1795
- type Filters = {
1796
- search: string;
1797
- matchCase: boolean;
1798
- matchEntireCell: boolean;
1799
- errorMessageFilters: string[];
1800
- showOnlyNewRows: boolean;
1801
- showOnlyEditedRows: boolean;
1802
- showOnlyEmptyCells: boolean;
1803
- /** When true, show only rows flagged for deletion (bin mode). All other filters are bypassed. */
1804
- showOnlyDeletedRows: boolean;
1805
- filterColumns: string[] | null;
1806
- /** Per-column value filters. Key = column ID, value = allowed display-formatted strings. */
1807
- columnValueFilters: Record<string, string[]>;
1808
- /** Per-column numeric range filters. Key = column ID. */
1809
- columnRangeFilters: Record<string, {
1810
- min?: number;
1811
- max?: number;
1812
- }>;
1813
- /** Per-column date range filters. Key = column ID, values are ISO date strings (YYYY-MM-DD). */
1814
- columnDateRangeFilters: Record<string, {
1815
- min?: string;
1816
- max?: string;
1817
- }>;
1818
- };
1819
-
1820
- /**
1821
- * A single chunk in the stream returned from `DataEditorChat.onMessage`.
1822
- *
1823
- * - `status` — progress message shown while processing (e.g. "Analyzing 500 rows...").
1824
- * - `message` — chat reply shown to the user.
1825
- * - `rows` — updated rows to apply to the grid. Matched by `primaryKey`.
1826
- * - `transform` — description of the transform applied.
1827
- */
1828
- type ChatResponseChunk<TRow extends DataEditorRow = DataEditorRow> = {
1829
- type: "status";
1830
- content: string;
1831
- } | {
1832
- type: "message";
1833
- content: string;
1834
- } | {
1835
- type: "rows";
1836
- content: TRow[];
1837
- } | {
1838
- type: "transform";
1839
- content: string;
1840
- };
1841
- /** Status of a row in the chat sample, relative to its origin snapshot. */
1842
- type ChatRowStatus = "new" | "edited" | "original";
1843
- /** A sample row handed to the chat callback, with its current status and validation errors. */
1844
- type ChatRow<TRow extends DataEditorRow = DataEditorRow> = {
1845
- /** Row data keyed by column ID. */
1846
- data: TRow;
1847
- /** Whether the row was newly added, edited, or is unchanged. */
1848
- status: ChatRowStatus;
1849
- /** Validation errors keyed by column ID. */
1850
- errors: Record<string, string[]>;
1851
- /** The source this row belongs to. */
1852
- source: string;
1853
- };
1854
- /** Aggregated error count across the current view, grouped by field and message. */
1855
- type ChatErrorSummary = {
1856
- /** Column ID where the error occurred. */
1857
- field: string;
1858
- /** The validation message. */
1859
- message: string;
1860
- /** How many rows hit this error. */
1861
- count: number;
1862
- /** A few example values that triggered the error. */
1863
- examples: string[];
1864
- };
1865
- /**
1866
- * Context about the current dataset, passed to `loadSuggestions` and extended
1867
- * into `ChatContext` for `onMessage`.
1868
- */
1869
- type ChatDataContext<TRow extends DataEditorRow = DataEditorRow> = {
1870
- /** Full column definitions. */
1871
- columns: DataEditorColumn[];
1872
- /** Row identifier field. */
1873
- primaryKey: keyof TRow;
1874
- /** Total rows in the dataset. */
1875
- totalRowCount: number;
1876
- /** Rows in the current filtered view. */
1877
- filteredRowCount: number;
1878
- /** Sample rows, with status and errors. Size controlled by `sampleSize`. */
1879
- sample: ChatRow<TRow>[];
1880
- /** Aggregated error counts by field and message. */
1881
- errorSummary: ChatErrorSummary[];
1882
- /** Access all rows. Use for full-dataset operations. */
1883
- getRows: () => ChatRow<TRow>[];
1884
- };
1885
- /**
1886
- * The full context passed to `DataEditorChat.onMessage` when the user sends
1887
- * a prompt. Includes the prompt itself and all dataset context.
1888
- */
1889
- type ChatContext<TRow extends DataEditorRow = DataEditorRow> = ChatDataContext<TRow> & {
1890
- /** The user's chat prompt. */
1891
- message: string;
1892
- };
1893
- /**
1894
- * Bring-your-own-AI chat configuration. When provided via the `chat` prop,
1895
- * the editor shows a chat panel alongside the grid. You own the AI
1896
- * integration; the SDK hands you dataset context and renders the streamed
1897
- * response.
1898
- *
1899
- * @example
1900
- * ```ts
1901
- * chat={{
1902
- * sampleSize: 50,
1903
- * onMessage: async function* (context) {
1904
- * yield { type: "status", content: "Thinking..." };
1905
- * const res = await fetch("/api/ai", {
1906
- * method: "POST",
1907
- * body: JSON.stringify({
1908
- * prompt: context.message,
1909
- * columns: context.columns,
1910
- * sample: context.sample.map(r => r.data),
1911
- * errors: context.errorSummary,
1912
- * }),
1913
- * }).then(r => r.json());
1914
- * yield { type: "rows", content: res.updatedRows };
1915
- * yield { type: "transform", content: res.description };
1916
- * yield { type: "message", content: res.reply };
1917
- * },
1918
- * }}
1919
- * ```
1920
- */
1921
- type DataEditorChat<TRow extends DataEditorRow = DataEditorRow> = {
1922
- /**
1923
- * How many rows to include in the context sample. The SDK picks a
1924
- * representative slice including rows with errors. When omitted, the SDK decides.
1925
- */
1926
- sampleSize?: number;
1927
- /** Title shown above the suggestion list when the chat is empty. */
1928
- emptyTitle?: string;
1929
- /** How many suggestions to request from `loadSuggestions`. */
1930
- suggestionsCount?: number;
1931
- /** Optional prompt generator for the empty-state suggestion chips. */
1932
- loadSuggestions?: (context: ChatDataContext<TRow>) => Promise<string[]>;
1933
- /**
1934
- * Called when the user sends a message. Receives full dataset context.
1935
- * Returns an async iterable of response chunks — the SDK streams them
1936
- * into the UI.
1937
- */
1938
- onMessage: (context: ChatContext<TRow>) => AsyncIterable<ChatResponseChunk<TRow>>;
1939
- /** Called when the user cancels a pending request. Use to abort your API call. */
1940
- onCancel?: () => void;
1941
- };
1942
-
1943
1960
  /** Severity level for a validation message. */
1944
1961
  type ValidationLevel = "error";
1945
1962
  /**