@svgrid/enterprise 3.1.23 → 3.1.25
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/dist/cdn/svgrid-enterprise.svelte-external.js +1 -1
- package/dist/designer/assets/{index-CIxqRzKJ.js → index-UhFdGGXv.js} +1 -1
- package/dist/designer/index.html +1 -1
- package/dist/export.d.ts +7 -0
- package/dist/export.js +7 -0
- package/dist/node/studio.js +1 -1
- package/dist/review/adapters.d.ts +12 -0
- package/dist/review/adapters.js +8 -0
- package/dist/review/agent.d.ts +13 -0
- package/dist/review/agent.js +5 -0
- package/dist/review/cluster.d.ts +15 -1
- package/dist/review/cluster.js +10 -1
- package/dist/review/equal.d.ts +5 -0
- package/dist/review/equal.js +5 -0
- package/dist/review/formats.d.ts +12 -1
- package/dist/review/formats.js +12 -1
- package/dist/review/ghost.d.ts +1 -0
- package/dist/review/ghost.js +1 -0
- package/dist/review/messages.d.ts +11 -2
- package/dist/review/messages.js +8 -2
- package/dist/review/model.svelte.d.ts +89 -132
- package/dist/review/model.svelte.js +7 -0
- package/dist/review/types.d.ts +13 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -64741,7 +64741,7 @@ function g1(e) {
|
|
|
64741
64741
|
}
|
|
64742
64742
|
//#endregion
|
|
64743
64743
|
//#region src/version.ts
|
|
64744
|
-
var _1 = "3.1.
|
|
64744
|
+
var _1 = "3.1.25", v1 = "3.0.22", y1 = (e, t) => e.some((e) => e.config.kind === t), b1 = (e) => `activeTab_${e.replace(/[^a-zA-Z0-9_$]/g, "_")}`, x1 = (e, t) => `${e}-${t}`, S1 = (e) => `accOpen_${e.replace(/[^a-zA-Z0-9_$]/g, "_")}`, C1 = (e, t) => `${e}-s${t}`, w1 = (e) => `md_${e.replace(/[^a-zA-Z0-9]/g, "_")}_rows`;
|
|
64745
64745
|
function T1(e) {
|
|
64746
64746
|
switch (e.type) {
|
|
64747
64747
|
case "number": {
|
|
@@ -76261,7 +76261,7 @@ ${k}
|
|
|
76261
76261
|
.st-home a { color: var(--sg-accent, #6366f1); font-weight: 600; }
|
|
76262
76262
|
@keyframes st-home-spin { to { transform: rotate(360deg); } }
|
|
76263
76263
|
</style>
|
|
76264
|
-
`}}function M1(e){for(let t of e)MG(t);let t=new Map(e.map(e=>[e.name,e])),n=e.map(e=>{let n=c1(e,t);return{schema:l1(e,n),infos:n}});return{entries:n,seed:u1(n)}}function wre(e,t={}){let{entries:n,seed:r}=M1(e),{file:i,needs:a}=O1(n,r,t.sources,t.supabaseConn,t.serverMemory),o=[_re(n),i];(a.supabase||t.supabaseAuth)&&!a.supabaseUrl&&(t.supabaseConn?.url||t.supabaseConn?.key)&&(a.supabaseUrl=t.supabaseConn.url,a.supabaseKey=t.supabaseConn.key),(a.supabase||t.supabaseAuth)&&o.push(k1(a));for(let e of a.sqlRoutes)o.push(y1(e.schema,e.table,e.dialect,{access:t.accessEnabled,audit:t.auditEnabled,screenIds:t.screensByEntity?.get(e.schema.name)??[],triggers:t.triggers?.[e.schema.name],dbSchema:e.dbSchema,tenantField:t.tenantField&&t.tenantScoped?.(e.schema.name)!==!1?t.tenantField:void 0}));if(a.memoryRoutes.length){o.push(x1(a.memoryRoutes));for(let e of a.memoryRoutes)o.push(b1(e.schema,{access:t.accessEnabled,audit:t.auditEnabled,screenIds:t.screensByEntity?.get(e.schema.name)??[],triggers:t.triggers?.[e.schema.name],tenantField:t.tenantField&&t.tenantScoped?.(e.schema.name)!==!1?t.tenantField:void 0}))}return{files:o,prepared:n.map(e=>e.schema)}}var N1=`3.1.
|
|
76264
|
+
`}}function M1(e){for(let t of e)MG(t);let t=new Map(e.map(e=>[e.name,e])),n=e.map(e=>{let n=c1(e,t);return{schema:l1(e,n),infos:n}});return{entries:n,seed:u1(n)}}function wre(e,t={}){let{entries:n,seed:r}=M1(e),{file:i,needs:a}=O1(n,r,t.sources,t.supabaseConn,t.serverMemory),o=[_re(n),i];(a.supabase||t.supabaseAuth)&&!a.supabaseUrl&&(t.supabaseConn?.url||t.supabaseConn?.key)&&(a.supabaseUrl=t.supabaseConn.url,a.supabaseKey=t.supabaseConn.key),(a.supabase||t.supabaseAuth)&&o.push(k1(a));for(let e of a.sqlRoutes)o.push(y1(e.schema,e.table,e.dialect,{access:t.accessEnabled,audit:t.auditEnabled,screenIds:t.screensByEntity?.get(e.schema.name)??[],triggers:t.triggers?.[e.schema.name],dbSchema:e.dbSchema,tenantField:t.tenantField&&t.tenantScoped?.(e.schema.name)!==!1?t.tenantField:void 0}));if(a.memoryRoutes.length){o.push(x1(a.memoryRoutes));for(let e of a.memoryRoutes)o.push(b1(e.schema,{access:t.accessEnabled,audit:t.auditEnabled,screenIds:t.screensByEntity?.get(e.schema.name)??[],triggers:t.triggers?.[e.schema.name],tenantField:t.tenantField&&t.tenantScoped?.(e.schema.name)!==!1?t.tenantField:void 0}))}return{files:o,prepared:n.map(e=>e.schema)}}var N1=`3.1.25`,P1=`3.0.22`,F1=(e,t)=>e.some(e=>e.config.kind===t),I1=e=>`activeTab_${e.replace(/[^a-zA-Z0-9_$]/g,`_`)}`,L1=(e,t)=>`${e}-${t}`,R1=e=>`accOpen_${e.replace(/[^a-zA-Z0-9_$]/g,`_`)}`,z1=(e,t)=>`${e}-s${t}`,B1=e=>`md_${e.replace(/[^a-zA-Z0-9]/g,`_`)}_rows`;function V1(e){switch(e.type){case`number`:{let t=e.decimals;return t==null?`{ type: 'number' }`:`{ type: 'number', options: { minimumFractionDigits: ${t}, maximumFractionDigits: ${t} } }`}case`currency`:return`{ type: 'currency', currency: ${$1(e.currency||`USD`)} }`;case`percent`:{let t=[`type: 'percent'`];return e.valueIsPercentPoints&&t.push(`valueIsPercentPoints: true`),e.decimals!=null&&t.push(`options: { minimumFractionDigits: ${e.decimals}, maximumFractionDigits: ${e.decimals} }`),`{ ${t.join(`, `)} }`}case`date`:case`datetime`:return e.pattern?`{ type: '${e.type}', pattern: ${$1(e.pattern)} }`:`{ type: '${e.type}' }`}}function H1(e,t,n,r){if(t.config.kind!==`grid`)return`schemaToColumns(${e})`;let i=t.config,a=t.id.replace(/-/g,`_`),o=i.columns.filter(e=>e.show),s=new Set(o.map(e=>e.field)),c=new Set,l=o.map(e=>{let t=r?.get(e.field);return{c:e,col:t&&!s.has(t)?t:e.field}}).filter(e=>!c.has(e.col)&&!!c.add(e.col)),u=i.editing===`inline`?``:`, editable: false`;if(l.length===0)return u?`schemaToColumns(${e}).map((c) => ({ ...c${u} }))`:`schemaToColumns(${e})`;let d=l.map(e=>`'${e.col}'`),f=l.map(({c:e,col:t})=>{let r=[];return e.header&&r.push(`header: ${JSON.stringify(e.header)}`),e.width!=null&&r.push(`width: ${e.width}`),e.align&&r.push(`align: '${e.align}'`),e.aggregate&&r.push(`aggregate: '${e.aggregate}'`),i.treeData&&e.field===i.treeData.labelField&&n?r.push(`cell: (ctx: CellContext<${n}>) => renderSnippet(treeCell_${a}, { value: ctx.getValue(), row: ctx.row.original })`):e.cellType&&n?r.push(`cell: (ctx: CellContext<${n}>) => renderSnippet(${d0(a,e.field)}, { value: ctx.getValue() })`):e.format&&r.push(`format: ${V1(e.format)}`),r.length?`'${t}': { ${r.join(`, `)} }`:null}).filter(e=>!!e),p=f.length?` const ov: Record<string, Partial<(typeof all)[number]>> = { ${f.join(`, `)} };`:``,m=f.length?`, ...(ov[String(c.field)] ?? {})`:``,h=`[${d.join(`, `)}].map((f) => all.find((c) => c.field === f)).filter((c): c is (typeof all)[number] => !!c)`;return`(() => { const all = schemaToColumns(${e});${p} return ${u||m?`${h}.map((c) => ({ ...c${u}${m} }))`:h} })()`}function U1(e,t){let n=[`grid-column: span ${uZ(e)}`,`min-width: 0`];t&&n.push(t);let r=fZ(e.style);return r&&n.push(r),`style="${n.join(`; `)}"`}var Tre=e=>e&&e.replace(/[^#a-zA-Z0-9(),.%\s_-]/g,``).slice(0,40)||`var(--sg-accent)`;function W1(e,t){let n=[t,lZ(e)].filter(Boolean).join(` `);return n?` class="${n}"`:``}function G1(e){let t=cZ(e.className);return t?` ${t}`:``}function Ere(e){let t=n$(e);if(t===`grid`){let t=BZ(e),n=t.maxWidth?` max-width: ${t.maxWidth}px; margin-inline: auto;`:``;return` .st-screen { grid-template-columns: repeat(12, 1fr); gap: ${t.rowGap}px ${t.colGap}px; align-items: ${t.align};${n} }\n @media (max-width: ${t.mobileBreakpoint}px) { .st-screen { grid-template-columns: 1fr; gap: 12px; } }\n`}if(t===`stack`){let t=VZ(e),n=t.maxWidth?` max-width: ${t.maxWidth}px;${t.align===`center`?` margin-inline: auto;`:``}`:``,r=t.minHeight?`\n .st-stack > * { min-height: ${t.minHeight}px; }`:``,i=t.dividers?`\n .st-stack > * + * { border-top: 1px solid var(--sg-border, #e2e8f0); padding-top: ${t.gap}px; }`:``;return` .st-stack { gap: ${t.gap}px;${n} }${r}${i}\n`}if(t===`canvas`){let t=WZ(e),n=t.showGrid?`\n .st-canvas { background-image: linear-gradient(var(--sg-border, #e6e8ec) 1px, transparent 1px), linear-gradient(90deg, var(--sg-border, #e6e8ec) 1px, transparent 1px); background-size: calc((100% - ${t.cols-1} * ${t.gap}px) / ${t.cols} + ${t.gap}px) calc(${t.rowHeight}px + ${t.gap}px); }`:``;return` .st-canvas { grid-template-columns: repeat(${t.cols}, 1fr); grid-auto-rows: ${t.rowHeight}px; gap: ${t.gap}px; }${n}\n`}return``}function K1(e,t,n,r,i,a={hasRecord:!1}){let o=(e,t)=>a.i18n?`{$t('block.${t}', ${JSON.stringify(e)})}`:e,s=a.pane?`style="height: 100%; min-width: 0; min-height: 0; display: flex; flex-direction: column;"`:U1(r),c=W1(r),l=r.config,u=a.handleNames?.get(r.id),d=u?`${u}.rows`:`allRows`;switch(l.kind){case`grid`:{let t=r.id.replace(/-/g,`_`),o=`columns_${t}`,u=`No ${(e.label??e.name).toLowerCase()} yet.`,d=Dre(l,t);if(l.scheduler){let t=s1(a.rawEntity??e,i);return` <div ${s}${c}>
|
|
76265
76265
|
${d.decls} <SvGrid
|
|
76266
76266
|
data={allRows}
|
|
76267
76267
|
columns={${o}}
|
package/dist/designer/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>SvGrid Studio - Designer</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-UhFdGGXv.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-Dd_uD5pT.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="./assets/disclose-version-CIm4S9xS.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="./assets/cell-formatting-JoxA0t65.js">
|
package/dist/export.d.ts
CHANGED
|
@@ -304,6 +304,13 @@ export declare function buildLinkResolver<TData extends RowData>(cols: ReadonlyA
|
|
|
304
304
|
* the numeric / currency columns. Values use the same formatting as the grid.
|
|
305
305
|
*/
|
|
306
306
|
export declare function buildGroupedPdfBody<TData extends RowData>(cols: ReadonlyArray<ExportColumn<TData>>, rows: ReadonlyArray<TData>, groupBy: ReadonlyArray<string>): PdfBodyRow[];
|
|
307
|
+
/**
|
|
308
|
+
* Export a grid's rows to a file: xlsx, xls, pdf, csv, tsv, html, json, xml
|
|
309
|
+
* or md, picked by `opts.format`. It reads the columns and rows through the
|
|
310
|
+
* grid api, so sorting, filtering and grouping carry over, and downloads the
|
|
311
|
+
* file unless `opts.download` is false. Resolves with the file (`ExportResult`)
|
|
312
|
+
* on the paths that build it in memory, undefined on the others.
|
|
313
|
+
*/
|
|
307
314
|
export declare function exportGrid<TFeatures extends TableFeatures, TData extends RowData>(api: SvGridApi<TFeatures, TData>, opts: ExportOptions<TData>): Promise<ExportResult | undefined>;
|
|
308
315
|
/** Native formats that can be placed on the clipboard. */
|
|
309
316
|
export type ClipboardFormat = 'csv' | 'tsv' | 'html' | 'json' | 'xml' | 'md';
|
package/dist/export.js
CHANGED
|
@@ -833,6 +833,13 @@ async function exportXlsxNative(api, opts) {
|
|
|
833
833
|
opts.onProgress?.({ phase: 'write', ratio: 1, total: src.length });
|
|
834
834
|
return deliver(blob, ensureExt(filename, 'xlsx'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', src.length, opts.download);
|
|
835
835
|
}
|
|
836
|
+
/**
|
|
837
|
+
* Export a grid's rows to a file: xlsx, xls, pdf, csv, tsv, html, json, xml
|
|
838
|
+
* or md, picked by `opts.format`. It reads the columns and rows through the
|
|
839
|
+
* grid api, so sorting, filtering and grouping carry over, and downloads the
|
|
840
|
+
* file unless `opts.download` is false. Resolves with the file (`ExportResult`)
|
|
841
|
+
* on the paths that build it in memory, undefined on the others.
|
|
842
|
+
*/
|
|
836
843
|
export async function exportGrid(api, opts) {
|
|
837
844
|
assertEnterpriseLicensed('Export');
|
|
838
845
|
// Native text formats have their own dependency-free, streaming path.
|
package/dist/node/studio.js
CHANGED
|
@@ -16506,7 +16506,7 @@ function hasFieldConditions(schema) {
|
|
|
16506
16506
|
*
|
|
16507
16507
|
* `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
|
|
16508
16508
|
*/
|
|
16509
|
-
var SVGRID_VERSION = "3.1.
|
|
16509
|
+
var SVGRID_VERSION = "3.1.25";
|
|
16510
16510
|
/**
|
|
16511
16511
|
* The version of `@svgrid/grid`, which releases on its own line: enterprise is
|
|
16512
16512
|
* on 3.1.x while the grid is on 3.0.x.
|
|
@@ -12,6 +12,10 @@ import { type AIClassifyOptions, type AIClassifyResult, type AISmartFillOptions,
|
|
|
12
12
|
import type { ReviewGridApi } from './model.svelte.js';
|
|
13
13
|
import type { ProposalInput, ProposalSource } from './types.js';
|
|
14
14
|
type RowIdApi = Pick<ReviewGridApi, 'getOption'>;
|
|
15
|
+
/**
|
|
16
|
+
* A change set built from another tool's output, ready for `review.add`, with
|
|
17
|
+
* a count of the predictions that could not become proposals.
|
|
18
|
+
*/
|
|
15
19
|
export type AdapterResult = {
|
|
16
20
|
source: ProposalSource;
|
|
17
21
|
title: string;
|
|
@@ -21,11 +25,19 @@ export type AdapterResult = {
|
|
|
21
25
|
};
|
|
22
26
|
/** Blank cells of `field`: what `aiSmartFill` targets when given no indices. */
|
|
23
27
|
export declare const blankTargets: (snapshot: ReadonlyArray<unknown>, field: string) => number[];
|
|
28
|
+
/**
|
|
29
|
+
* Proposals from an `aiSmartFill` result, its row indices resolved to row ids
|
|
30
|
+
* through the snapshot the call ran on.
|
|
31
|
+
*/
|
|
24
32
|
export declare function fromSmartFill<TData>(result: AISmartFillResult, snapshot: ReadonlyArray<TData>, opts: {
|
|
25
33
|
api: RowIdApi;
|
|
26
34
|
targets?: ReadonlyArray<number>;
|
|
27
35
|
source?: ProposalSource;
|
|
28
36
|
}): AdapterResult;
|
|
37
|
+
/**
|
|
38
|
+
* Proposals from an `aiClassify` result, its row indices resolved to row ids
|
|
39
|
+
* through the snapshot the call ran on.
|
|
40
|
+
*/
|
|
29
41
|
export declare function fromClassify<TData>(result: AIClassifyResult, snapshot: ReadonlyArray<TData>, opts: {
|
|
30
42
|
api: RowIdApi;
|
|
31
43
|
targets?: ReadonlyArray<number>;
|
package/dist/review/adapters.js
CHANGED
|
@@ -39,12 +39,20 @@ function fromPredictions(predictions, field, snapshot, targets, api, reason) {
|
|
|
39
39
|
}
|
|
40
40
|
/** Blank cells of `field`: what `aiSmartFill` targets when given no indices. */
|
|
41
41
|
export const blankTargets = (snapshot, field) => snapshot.flatMap((row, i) => (isBlank(row[field]) ? [i] : []));
|
|
42
|
+
/**
|
|
43
|
+
* Proposals from an `aiSmartFill` result, its row indices resolved to row ids
|
|
44
|
+
* through the snapshot the call ran on.
|
|
45
|
+
*/
|
|
42
46
|
export function fromSmartFill(result, snapshot, opts) {
|
|
43
47
|
const targets = opts.targets ?? blankTargets(snapshot, result.field);
|
|
44
48
|
const { proposals, dropped } = fromPredictions(result.predictions, result.field, snapshot, targets, opts.api, result.rationale || undefined);
|
|
45
49
|
const source = opts.source ?? { kind: 'ai', id: `smart-fill:${result.field}`, label: 'Smart fill' };
|
|
46
50
|
return { source, title: `Smart fill: ${result.field}`, proposals, dropped };
|
|
47
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Proposals from an `aiClassify` result, its row indices resolved to row ids
|
|
54
|
+
* through the snapshot the call ran on.
|
|
55
|
+
*/
|
|
48
56
|
export function fromClassify(result, snapshot, opts) {
|
|
49
57
|
const targets = opts.targets ?? snapshot.map((_, i) => i);
|
|
50
58
|
const { proposals, dropped } = fromPredictions(result.predictions, result.outputField, snapshot, targets, opts.api, `classified from ${result.inputField}`);
|
package/dist/review/agent.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ReviewGridApi } from './model.svelte.js';
|
|
2
2
|
import type { Proposal, ProposalGroup, ProposalInput, ProposalSource } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* One agent tool in the shape tool-use loops take: a name, a description, a
|
|
5
|
+
* JSON Schema for its input, and `execute`.
|
|
6
|
+
*/
|
|
3
7
|
export type GridTool = {
|
|
4
8
|
name: string;
|
|
5
9
|
description: string;
|
|
@@ -21,6 +25,10 @@ type ToolReview = {
|
|
|
21
25
|
proposals(): Proposal[];
|
|
22
26
|
};
|
|
23
27
|
type ToolApi = Pick<ReviewGridApi, 'getData' | 'getColumns' | 'getOption'>;
|
|
28
|
+
/**
|
|
29
|
+
* Options for `createGridTools`: the review edits are proposed into, the grid
|
|
30
|
+
* api, and the fields the agent may edit.
|
|
31
|
+
*/
|
|
24
32
|
export type GridToolsOptions = {
|
|
25
33
|
review: ToolReview;
|
|
26
34
|
/** The grid api, or a getter for it. */
|
|
@@ -36,6 +44,11 @@ export type GridToolsOptions = {
|
|
|
36
44
|
/** Most edits one grid_propose_edits call may carry. Default 500. */
|
|
37
45
|
maxEdits?: number;
|
|
38
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* The tools an agent edits a grid through: `grid_describe`, `grid_query_rows`,
|
|
49
|
+
* `grid_propose_edits` and `grid_review_status`. None of them writes the data:
|
|
50
|
+
* edits arrive in the review as proposals for a person to accept.
|
|
51
|
+
*/
|
|
39
52
|
export declare function createGridTools(opts: GridToolsOptions): GridTool[];
|
|
40
53
|
/**
|
|
41
54
|
* Register tools with the browser's WebMCP API, so an agent driving the page
|
package/dist/review/agent.js
CHANGED
|
@@ -43,6 +43,11 @@ function wrongType(type, current, value) {
|
|
|
43
43
|
return 'expects a date (YYYY-MM-DD)';
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The tools an agent edits a grid through: `grid_describe`, `grid_query_rows`,
|
|
48
|
+
* `grid_propose_edits` and `grid_review_status`. None of them writes the data:
|
|
49
|
+
* edits arrive in the review as proposals for a person to accept.
|
|
50
|
+
*/
|
|
46
51
|
export function createGridTools(opts) {
|
|
47
52
|
const prefix = opts.prefix ?? 'grid_';
|
|
48
53
|
const source = opts.source ?? { kind: 'agent', id: 'agent', label: 'Agent' };
|
package/dist/review/cluster.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { type ReviewMessages } from './messages.js';
|
|
2
2
|
import type { Proposal, ProposalGroup } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* How `clusterProposals` labels and splits groups: field labels, the size a
|
|
5
|
+
* scale group needs, the confidence below which a proposal counts as unsure,
|
|
6
|
+
* and the wording.
|
|
7
|
+
*/
|
|
3
8
|
export type ClusterOptions = {
|
|
4
9
|
/** Wording of the group labels (the `label*`, `case*`, `punct*` keys); English by default. */
|
|
5
10
|
messages?: Partial<ReviewMessages>;
|
|
@@ -10,12 +15,21 @@ export type ClusterOptions = {
|
|
|
10
15
|
/** Below this, a judgment group sorts with the risky ones. Default 0.6. */
|
|
11
16
|
lowConfidence?: number;
|
|
12
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Group proposals by the change they make (trim, case, reformat, scale, one
|
|
20
|
+
* mapping, fill empty, one target, no pattern), the groups that need a person
|
|
21
|
+
* first. What the panel lists.
|
|
22
|
+
*/
|
|
13
23
|
export declare function clusterProposals(proposals: ReadonlyArray<Proposal>, opts?: ClusterOptions): ProposalGroup[];
|
|
14
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* A key that tells values apart by type as well as content.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
15
28
|
export declare function keyOf(v: unknown): string;
|
|
16
29
|
/**
|
|
17
30
|
* Spaces a reader cannot see, drawn as `·`: leading and trailing ones and runs
|
|
18
31
|
* of two or more. A trim proposal otherwise reads "Acme -> Acme".
|
|
32
|
+
* @internal
|
|
19
33
|
*/
|
|
20
34
|
export declare function visibleSpaces(s: string): string;
|
|
21
35
|
/**
|
package/dist/review/cluster.js
CHANGED
|
@@ -28,6 +28,11 @@ import { isBlank } from './equal.js';
|
|
|
28
28
|
import { fill, reviewMessages } from './messages.js';
|
|
29
29
|
const RULE_KINDS = new Set(['whitespace', 'case', 'format', 'scale']);
|
|
30
30
|
const SEP = '\u0001';
|
|
31
|
+
/**
|
|
32
|
+
* Group proposals by the change they make (trim, case, reformat, scale, one
|
|
33
|
+
* mapping, fill empty, one target, no pattern), the groups that need a person
|
|
34
|
+
* first. What the panel lists.
|
|
35
|
+
*/
|
|
31
36
|
export function clusterProposals(proposals, opts = {}) {
|
|
32
37
|
const fieldLabel = opts.fieldLabel ?? ((f) => f);
|
|
33
38
|
const msg = reviewMessages(opts.messages);
|
|
@@ -241,7 +246,10 @@ function valid(y, mo, d) {
|
|
|
241
246
|
}
|
|
242
247
|
const ymd = (y, m, d) => `${y}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
|
|
243
248
|
// ---- grouping helpers -----------------------------------------------------
|
|
244
|
-
/**
|
|
249
|
+
/**
|
|
250
|
+
* A key that tells values apart by type as well as content.
|
|
251
|
+
* @internal
|
|
252
|
+
*/
|
|
245
253
|
export function keyOf(v) {
|
|
246
254
|
if (v instanceof Date)
|
|
247
255
|
return 'd:' + v.getTime();
|
|
@@ -307,6 +315,7 @@ function rankOf(g, low) {
|
|
|
307
315
|
/**
|
|
308
316
|
* Spaces a reader cannot see, drawn as `·`: leading and trailing ones and runs
|
|
309
317
|
* of two or more. A trim proposal otherwise reads "Acme -> Acme".
|
|
318
|
+
* @internal
|
|
310
319
|
*/
|
|
311
320
|
export function visibleSpaces(s) {
|
|
312
321
|
return s.replace(/^\s+|\s+$/g, (m) => '·'.repeat(m.length)).replace(/ {2,}/g, (m) => '·'.repeat(m.length));
|
package/dist/review/equal.d.ts
CHANGED
|
@@ -5,5 +5,10 @@
|
|
|
5
5
|
* the same rule Base sync uses (`fields/base-sync.ts`), so a cell cleared to
|
|
6
6
|
* '' does not make a proposal made against `null` look stale.
|
|
7
7
|
*/
|
|
8
|
+
/** Whether a cell value is blank: null, undefined or the empty string. */
|
|
8
9
|
export declare const isBlank: (v: unknown) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether two cell values are the same for a review: `Object.is`, Dates by
|
|
12
|
+
* time, arrays and plain objects by structure, and any two blanks.
|
|
13
|
+
*/
|
|
9
14
|
export declare function sameValue(a: unknown, b: unknown): boolean;
|
package/dist/review/equal.js
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* the same rule Base sync uses (`fields/base-sync.ts`), so a cell cleared to
|
|
6
6
|
* '' does not make a proposal made against `null` look stale.
|
|
7
7
|
*/
|
|
8
|
+
/** Whether a cell value is blank: null, undefined or the empty string. */
|
|
8
9
|
export const isBlank = (v) => v == null || v === '';
|
|
10
|
+
/**
|
|
11
|
+
* Whether two cell values are the same for a review: `Object.is`, Dates by
|
|
12
|
+
* time, arrays and plain objects by structure, and any two blanks.
|
|
13
|
+
*/
|
|
9
14
|
export function sameValue(a, b) {
|
|
10
15
|
if (Object.is(a, b))
|
|
11
16
|
return true;
|
package/dist/review/formats.d.ts
CHANGED
|
@@ -12,7 +12,10 @@ import type { Proposal } from './types.js';
|
|
|
12
12
|
* selection and focus.
|
|
13
13
|
*/
|
|
14
14
|
export declare const PENDING_BG = "var(--sg-review-pending-bg, color-mix(in srgb, var(--sg-warning, #d97706) 13%, transparent))";
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* The row "Show in grid" lands on, for a moment: a stronger wash of the same amber.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
16
19
|
export declare const FLASH_BG = "var(--sg-review-flash-bg, color-mix(in srgb, var(--sg-warning, #d97706) 32%, transparent))";
|
|
17
20
|
/** Drawn before the value, so a pending cell is never marked by colour alone. */
|
|
18
21
|
export declare const PENDING_ICON = "\u2022";
|
|
@@ -21,7 +24,15 @@ export declare const PENDING_ICON = "\u2022";
|
|
|
21
24
|
* a "!" before the value, so the grid shows where the panel's conflicts are.
|
|
22
25
|
*/
|
|
23
26
|
export declare const CONFLICT_BG = "var(--sg-review-conflict-bg, color-mix(in srgb, var(--sg-danger, #dc2626) 12%, transparent))";
|
|
27
|
+
/**
|
|
28
|
+
* Drawn before the value of a cell two sources disagree on.
|
|
29
|
+
*/
|
|
24
30
|
export declare const CONFLICT_ICON = "!";
|
|
31
|
+
/**
|
|
32
|
+
* `conditionalFormats` rules that tint the cells of the given proposals, one
|
|
33
|
+
* rule per field, scoped to that field's columns. `review.formats` is built
|
|
34
|
+
* from it.
|
|
35
|
+
*/
|
|
25
36
|
export declare function pendingFormats<TData>(pending: ReadonlyArray<Proposal>, rowId: (row: TData, index: number) => string, columns: ReadonlyArray<{
|
|
26
37
|
id: string;
|
|
27
38
|
field?: string;
|
package/dist/review/formats.js
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* selection and focus.
|
|
5
5
|
*/
|
|
6
6
|
export const PENDING_BG = 'var(--sg-review-pending-bg, color-mix(in srgb, var(--sg-warning, #d97706) 13%, transparent))';
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* The row "Show in grid" lands on, for a moment: a stronger wash of the same amber.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
8
11
|
export const FLASH_BG = 'var(--sg-review-flash-bg, color-mix(in srgb, var(--sg-warning, #d97706) 32%, transparent))';
|
|
9
12
|
/** Drawn before the value, so a pending cell is never marked by colour alone. */
|
|
10
13
|
export const PENDING_ICON = '•';
|
|
@@ -13,7 +16,15 @@ export const PENDING_ICON = '•';
|
|
|
13
16
|
* a "!" before the value, so the grid shows where the panel's conflicts are.
|
|
14
17
|
*/
|
|
15
18
|
export const CONFLICT_BG = 'var(--sg-review-conflict-bg, color-mix(in srgb, var(--sg-danger, #dc2626) 12%, transparent))';
|
|
19
|
+
/**
|
|
20
|
+
* Drawn before the value of a cell two sources disagree on.
|
|
21
|
+
*/
|
|
16
22
|
export const CONFLICT_ICON = '!';
|
|
23
|
+
/**
|
|
24
|
+
* `conditionalFormats` rules that tint the cells of the given proposals, one
|
|
25
|
+
* rule per field, scoped to that field's columns. `review.formats` is built
|
|
26
|
+
* from it.
|
|
27
|
+
*/
|
|
17
28
|
export function pendingFormats(pending, rowId, columns, look = { background: PENDING_BG, icon: PENDING_ICON }) {
|
|
18
29
|
const rowsByField = new Map();
|
|
19
30
|
for (const p of pending) {
|
package/dist/review/ghost.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare function canGhost(raw: any, sample?: unknown, columns?: ReadonlyA
|
|
|
12
12
|
/**
|
|
13
13
|
* Wrap the `cell` of every ghostable column whose field has a pending
|
|
14
14
|
* proposal. Returns the same array when nothing needs wrapping.
|
|
15
|
+
* @internal
|
|
15
16
|
*/
|
|
16
17
|
export declare function wrapColumns<C extends ReadonlyArray<any>>(cols: C, fields: ReadonlySet<string>, review: Ghostable, sample?: (field: string) => unknown): C;
|
|
17
18
|
export {};
|
package/dist/review/ghost.js
CHANGED
|
@@ -46,6 +46,7 @@ export function canGhost(raw, sample, columns = []) {
|
|
|
46
46
|
/**
|
|
47
47
|
* Wrap the `cell` of every ghostable column whose field has a pending
|
|
48
48
|
* proposal. Returns the same array when nothing needs wrapping.
|
|
49
|
+
* @internal
|
|
49
50
|
*/
|
|
50
51
|
export function wrapColumns(cols, fields, review, sample = () => undefined) {
|
|
51
52
|
if (!fields.size)
|
|
@@ -106,8 +106,17 @@ export declare const REVIEW_MESSAGES: {
|
|
|
106
106
|
labelConstant: string;
|
|
107
107
|
labelUnpatterned: string;
|
|
108
108
|
};
|
|
109
|
+
/**
|
|
110
|
+
* Every string the review shows, with the keys of `REVIEW_MESSAGES`.
|
|
111
|
+
*/
|
|
109
112
|
export type ReviewMessages = typeof REVIEW_MESSAGES;
|
|
110
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* English, with `overrides` laid over it (blank values ignored).
|
|
115
|
+
* @internal
|
|
116
|
+
*/
|
|
111
117
|
export declare function reviewMessages(...overrides: Array<Partial<ReviewMessages> | null | undefined>): ReviewMessages;
|
|
112
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* A template with its `{name}` placeholders filled.
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
113
122
|
export declare function fill(template: string, vars: Record<string, string | number>): string;
|
package/dist/review/messages.js
CHANGED
|
@@ -115,7 +115,10 @@ export const REVIEW_MESSAGES = {
|
|
|
115
115
|
labelConstant: 'Set {field} to {value}',
|
|
116
116
|
labelUnpatterned: '{field}: no shared pattern',
|
|
117
117
|
};
|
|
118
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* English, with `overrides` laid over it (blank values ignored).
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
119
122
|
export function reviewMessages(...overrides) {
|
|
120
123
|
const out = { ...REVIEW_MESSAGES };
|
|
121
124
|
for (const o of overrides) {
|
|
@@ -129,7 +132,10 @@ export function reviewMessages(...overrides) {
|
|
|
129
132
|
}
|
|
130
133
|
return out;
|
|
131
134
|
}
|
|
132
|
-
/**
|
|
135
|
+
/**
|
|
136
|
+
* A template with its `{name}` placeholders filled.
|
|
137
|
+
* @internal
|
|
138
|
+
*/
|
|
133
139
|
export function fill(template, vars) {
|
|
134
140
|
return template.replace(/\{(\w+)\}/g, (whole, key) => (key in vars ? String(vars[key]) : whole));
|
|
135
141
|
}
|
|
@@ -29,6 +29,11 @@ import { type ReviewMessages } from './messages.js';
|
|
|
29
29
|
import type { ChangeSet, Proposal, ProposalGroup, ProposalInput, ProposalSource } from './types.js';
|
|
30
30
|
/** The part of the grid api a review uses. Any `SvGridApi` satisfies it. */
|
|
31
31
|
export type ReviewGridApi = Pick<SvGridApi<any, any>, 'getData' | 'getOption' | 'getActiveCell' | 'getRowId' | 'getColumns' | 'getCommandContext' | 'stopEditing' | 'scrollToRow' | 'getDisplayedRows' | 'getAdvancedFilter' | 'setAdvancedFilter' | 'getRowPosition' | 'getPageInfo' | 'setPage' | 'getState'>;
|
|
32
|
+
/**
|
|
33
|
+
* Options for `createReview`: the grid it reviews, how accepted values are
|
|
34
|
+
* written (`setRows`, or `server` with `onCommit`), and what to call as
|
|
35
|
+
* decisions are made.
|
|
36
|
+
*/
|
|
32
37
|
export type ReviewOptions<TData> = {
|
|
33
38
|
/** The grid api, or a getter for it (it is bound after mount). */
|
|
34
39
|
api: ReviewGridApi | (() => ReviewGridApi | undefined | null);
|
|
@@ -74,6 +79,10 @@ export type ReviewOptions<TData> = {
|
|
|
74
79
|
*/
|
|
75
80
|
rowLabel?: (row: TData) => string | null | undefined;
|
|
76
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* One decision, its undo or its redo, as `onDecision` receives it, with copies
|
|
84
|
+
* of the proposals it moved. Write these to an audit log.
|
|
85
|
+
*/
|
|
77
86
|
export type ReviewDecision = {
|
|
78
87
|
action: 'accept' | 'reject' | 'undo' | 'redo';
|
|
79
88
|
/** For undo / redo: which decision was undone or redone. */
|
|
@@ -82,6 +91,11 @@ export type ReviewDecision = {
|
|
|
82
91
|
by?: string;
|
|
83
92
|
at: number;
|
|
84
93
|
};
|
|
94
|
+
/**
|
|
95
|
+
* What an accept or a reject did, by proposal id: accepted, rejected, stale
|
|
96
|
+
* (the cell changed before the write), committed and then found stale, or
|
|
97
|
+
* skipped; and what `onCommit` threw, if it did.
|
|
98
|
+
*/
|
|
85
99
|
export type ReviewOutcome = {
|
|
86
100
|
accepted: string[];
|
|
87
101
|
rejected: string[];
|
|
@@ -98,165 +112,108 @@ export type ReviewOutcome = {
|
|
|
98
112
|
/** What `onCommit` threw; nothing was written and the proposals stay pending. */
|
|
99
113
|
error?: unknown;
|
|
100
114
|
};
|
|
115
|
+
/**
|
|
116
|
+
* A change set for `review.add`: where it came from, an optional title and
|
|
117
|
+
* id, and its proposals.
|
|
118
|
+
*/
|
|
101
119
|
export type AddInput = {
|
|
102
120
|
source: ProposalSource;
|
|
103
121
|
title?: string;
|
|
104
122
|
id?: string;
|
|
105
123
|
proposals: ReadonlyArray<ProposalInput>;
|
|
106
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* A review's change sets as `review.toJSON()` writes them and `review.load` /
|
|
127
|
+
* `review.merge` read them, to route a review to an approver.
|
|
128
|
+
*/
|
|
107
129
|
export type ReviewJSON = {
|
|
108
130
|
v: 1;
|
|
109
131
|
sets: ChangeSet[];
|
|
110
132
|
};
|
|
111
|
-
|
|
112
|
-
|
|
133
|
+
/**
|
|
134
|
+
* What `createReview` returns: the proposals, their groups, the decisions,
|
|
135
|
+
* and what the grid takes (`columns`, `formats`). Every read is reactive.
|
|
136
|
+
*/
|
|
137
|
+
export interface Review<TData = unknown> {
|
|
138
|
+
/** Bumped on every change, for code that caches what it reads. */
|
|
113
139
|
readonly version: number;
|
|
114
140
|
/** The wording in effect: English with `messages` laid over it. */
|
|
115
|
-
messages:
|
|
116
|
-
title: string;
|
|
117
|
-
decided: string;
|
|
118
|
-
pendingInGroups: string;
|
|
119
|
-
pendingInOneGroup: string;
|
|
120
|
-
nothingPending: string;
|
|
121
|
-
inConflict: string;
|
|
122
|
-
acceptAll: string;
|
|
123
|
-
rejectAll: string;
|
|
124
|
-
acceptRuleGroups: string;
|
|
125
|
-
resolveFirst: string;
|
|
126
|
-
onlyRowsWithChanges: string;
|
|
127
|
-
confirmAcceptGroup: string;
|
|
128
|
-
confirmRejectGroup: string;
|
|
129
|
-
confirmAcceptAll: string;
|
|
130
|
-
confirmRejectAll: string;
|
|
131
|
-
confirmAcceptRules: string;
|
|
132
|
-
confirmYes: string;
|
|
133
|
-
cancel: string;
|
|
134
|
-
conflictsTitle: string;
|
|
135
|
-
conflictCell: string;
|
|
136
|
-
keep: string;
|
|
137
|
-
badgeRule: string;
|
|
138
|
-
hintRule: string;
|
|
139
|
-
hintMapping: string;
|
|
140
|
-
hintFill: string;
|
|
141
|
-
hintConstant: string;
|
|
142
|
-
hintEach: string;
|
|
143
|
-
oneChange: string;
|
|
144
|
-
changes: string;
|
|
145
|
-
sure: string;
|
|
146
|
-
sureRange: string;
|
|
147
|
-
accept: string;
|
|
148
|
-
reject: string;
|
|
149
|
-
acceptGroupLabel: string;
|
|
150
|
-
rejectGroupLabel: string;
|
|
151
|
-
from: string;
|
|
152
|
-
otherValues: string;
|
|
153
|
-
sampleOf: string;
|
|
154
|
-
everyChange: string;
|
|
155
|
-
firstN: string;
|
|
156
|
-
showRow: string;
|
|
157
|
-
rowId: string;
|
|
158
|
-
acceptOne: string;
|
|
159
|
-
rejectOne: string;
|
|
160
|
-
showAll: string;
|
|
161
|
-
keysHint: string;
|
|
162
|
-
showInGrid: string;
|
|
163
|
-
nextInGrid: string;
|
|
164
|
-
hiddenRows: string;
|
|
165
|
-
allReviewed: string;
|
|
166
|
-
reviewedSummary: string;
|
|
167
|
-
reviewedStale: string;
|
|
168
|
-
noProposals: string;
|
|
169
|
-
noProposalsHint: string;
|
|
170
|
-
notWritten: string;
|
|
171
|
-
rowField: string;
|
|
172
|
-
decidedLabel: string;
|
|
173
|
-
noteCellChanged: string;
|
|
174
|
-
noteRowGone: string;
|
|
175
|
-
noteRowEditing: string;
|
|
176
|
-
noteGridNotReady: string;
|
|
177
|
-
noteSavedStale: string;
|
|
178
|
-
noteConflict: string;
|
|
179
|
-
undoHint: string;
|
|
180
|
-
announceAccepted: string;
|
|
181
|
-
announceRejected: string;
|
|
182
|
-
announceStale: string;
|
|
183
|
-
announceSkipped: string;
|
|
184
|
-
announceCommittedStale: string;
|
|
185
|
-
announceNotSaved: string;
|
|
186
|
-
announceNothing: string;
|
|
187
|
-
undoFailed: string;
|
|
188
|
-
redoFailed: string;
|
|
189
|
-
cardProposed: string;
|
|
190
|
-
proposes: string;
|
|
191
|
-
nowValue: string;
|
|
192
|
-
empty: string;
|
|
193
|
-
labelWhitespace: string;
|
|
194
|
-
labelCase: string;
|
|
195
|
-
caseUpper: string;
|
|
196
|
-
caseLower: string;
|
|
197
|
-
caseTitle: string;
|
|
198
|
-
caseMixed: string;
|
|
199
|
-
labelToNumber: string;
|
|
200
|
-
labelDates: string;
|
|
201
|
-
datesAsDates: string;
|
|
202
|
-
labelShape: string;
|
|
203
|
-
labelPunct: string;
|
|
204
|
-
punctRemove: string;
|
|
205
|
-
punctAdd: string;
|
|
206
|
-
punctSpaces: string;
|
|
207
|
-
labelDivide: string;
|
|
208
|
-
labelMultiply: string;
|
|
209
|
-
labelMapping: string;
|
|
210
|
-
mappingValues: string;
|
|
211
|
-
labelFill: string;
|
|
212
|
-
labelFillVarious: string;
|
|
213
|
-
labelConstant: string;
|
|
214
|
-
labelUnpatterned: string;
|
|
215
|
-
};
|
|
141
|
+
readonly messages: ReviewMessages;
|
|
216
142
|
/** The last undo or redo whose save failed, or null. */
|
|
217
143
|
readonly lastError: {
|
|
218
144
|
error: unknown;
|
|
219
|
-
during:
|
|
145
|
+
during: 'undo' | 'redo';
|
|
220
146
|
at: number;
|
|
221
147
|
} | null;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
148
|
+
/** Add a change set; a cell that already has a live proposal from another source becomes a conflict. */
|
|
149
|
+
add(input: AddInput): ChangeSet;
|
|
150
|
+
/** One proposal by id. */
|
|
151
|
+
get(id: string): Proposal | undefined;
|
|
152
|
+
/** Every proposal of the session, whatever its status. */
|
|
153
|
+
proposals(): Proposal[];
|
|
154
|
+
/** What names a proposal's row (`rowLabel`), or null. */
|
|
155
|
+
rowLabel(p: Proposal): string | null;
|
|
227
156
|
/** A field's column header, as the group labels show it. */
|
|
228
|
-
fieldLabel
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
157
|
+
fieldLabel(field: string): string;
|
|
158
|
+
/** The proposals waiting for a decision. */
|
|
159
|
+
pending(): Proposal[];
|
|
160
|
+
/** The proposals two sources disagree on, to settle with `resolveConflict`. */
|
|
161
|
+
conflicts(): Proposal[];
|
|
162
|
+
/** The pending proposals grouped by the change they make, the groups that need a person first. */
|
|
163
|
+
groups(): ProposalGroup[];
|
|
164
|
+
/** The pending proposal for one cell, if there is one. */
|
|
165
|
+
pendingFor(rowId: string, field: string): Proposal | undefined;
|
|
166
|
+
/** Write these proposals: checks each cell still holds `before`, before and after `onCommit`. One undo step. */
|
|
167
|
+
accept(ids: ReadonlyArray<string>): Promise<ReviewOutcome>;
|
|
168
|
+
/** Decide against these proposals; nothing is written. One undo step. */
|
|
169
|
+
reject(ids: ReadonlyArray<string>): ReviewOutcome;
|
|
170
|
+
/** Accept a group, limited to the ids the person was shown, so a proposal added since is not decided unseen. */
|
|
171
|
+
acceptGroup(key: string, shownIds: ReadonlyArray<string>): Promise<ReviewOutcome>;
|
|
172
|
+
/** Reject a group, limited to the ids the person was shown. */
|
|
173
|
+
rejectGroup(key: string, shownIds: ReadonlyArray<string>): ReviewOutcome;
|
|
174
|
+
/** Keep one of a cell's conflicting proposals (it becomes pending) and reject the rest, as one undo step. */
|
|
175
|
+
resolveConflict(keepId: string): void;
|
|
176
|
+
/** `conditionalFormats` for the grid: pending cells tinted, conflicting cells marked, the row "Show in grid" lands on lit. */
|
|
238
177
|
readonly formats: ConditionalFormat<any>[];
|
|
239
|
-
columns
|
|
240
|
-
|
|
178
|
+
/** The grid's columns with the proposed value drawn in each pending cell. */
|
|
179
|
+
columns<C extends ReadonlyArray<any>>(cols: C): C;
|
|
180
|
+
/** Show the next proposal of `ids` after `fromId` in the grid, on whatever page it is. */
|
|
181
|
+
reveal(ids: ReadonlyArray<string>, fromId?: string): {
|
|
241
182
|
id: string | null;
|
|
242
183
|
hidden: number;
|
|
243
184
|
};
|
|
244
|
-
|
|
245
|
-
|
|
185
|
+
/** Show only rows with a pending or conflicting proposal, on top of the user's own filters. */
|
|
186
|
+
showPendingOnly(on: boolean): void;
|
|
187
|
+
/** Whether `showPendingOnly` is on (the grid's own Clear turns it off too). */
|
|
246
188
|
readonly pendingOnly: boolean;
|
|
247
|
-
|
|
189
|
+
/** Every set with its proposals and their status, as plain JSON; `setIds` exports only some. */
|
|
190
|
+
toJSON(opts?: {
|
|
248
191
|
setIds?: ReadonlyArray<string>;
|
|
249
|
-
})
|
|
250
|
-
|
|
192
|
+
}): ReviewJSON;
|
|
193
|
+
/** Replace everything with an export; returns how many malformed proposals were dropped. */
|
|
194
|
+
load(json: ReviewJSON): {
|
|
251
195
|
dropped: number;
|
|
252
196
|
};
|
|
253
|
-
|
|
197
|
+
/** Add the sets of an export, keeping what is here; returns how many were dropped. */
|
|
198
|
+
merge(json: ReviewJSON): {
|
|
254
199
|
dropped: number;
|
|
255
200
|
};
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
201
|
+
/** Every decided proposal (accepted, rejected or stale), oldest decision first. */
|
|
202
|
+
log(): Proposal[];
|
|
203
|
+
/** Propose undoing what a set wrote, as a new set to review; null when nothing of it was accepted. */
|
|
204
|
+
revertSet(setId: string): ChangeSet | null;
|
|
205
|
+
/** The sets in this review, newest last, without their proposals. */
|
|
206
|
+
sets(): Array<Omit<ChangeSet, 'proposals'> & {
|
|
259
207
|
count: number;
|
|
260
208
|
}>;
|
|
261
|
-
|
|
262
|
-
|
|
209
|
+
/** Forget every proposal and set. */
|
|
210
|
+
clear(): void;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Hold writes nobody typed (an agent's edits, an import, an AI helper's
|
|
214
|
+
* output) as proposals, grouped by the change they make, and write them only
|
|
215
|
+
* when a person accepts them. Give the grid `review.columns(columns)` and
|
|
216
|
+
* `review.formats`, and render `<SvReviewPanel {review} />` beside it. Each
|
|
217
|
+
* decision is one Ctrl+Z in the grid.
|
|
218
|
+
*/
|
|
219
|
+
export declare function createReview<TData = unknown>(opts: ReviewOptions<TData>): Review<TData>;
|
|
@@ -56,6 +56,13 @@ let uid = 0;
|
|
|
56
56
|
const nextId = (prefix) => `${prefix}${Date.now().toString(36)}-${(uid++).toString(36)}`;
|
|
57
57
|
const SEP = '\u0000';
|
|
58
58
|
const cellKey = (rowId, field) => rowId + SEP + field;
|
|
59
|
+
/**
|
|
60
|
+
* Hold writes nobody typed (an agent's edits, an import, an AI helper's
|
|
61
|
+
* output) as proposals, grouped by the change they make, and write them only
|
|
62
|
+
* when a person accepts them. Give the grid `review.columns(columns)` and
|
|
63
|
+
* `review.formats`, and render `<SvReviewPanel {review} />` beside it. Each
|
|
64
|
+
* decision is one Ctrl+Z in the grid.
|
|
65
|
+
*/
|
|
59
66
|
export function createReview(opts) {
|
|
60
67
|
if (!opts.setRows && !opts.server)
|
|
61
68
|
throw new Error('[svgrid review] pass setRows (client data) or server (server row model)');
|
package/dist/review/types.d.ts
CHANGED
|
@@ -10,7 +10,16 @@ export type ProposalSource = {
|
|
|
10
10
|
id: string;
|
|
11
11
|
label: string;
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Where a proposal stands: waiting, accepted, rejected, stale (its cell
|
|
15
|
+
* changed first), or in conflict with another source's proposal for the same
|
|
16
|
+
* cell.
|
|
17
|
+
*/
|
|
13
18
|
export type ProposalStatus = 'pending' | 'accepted' | 'rejected' | 'stale' | 'conflict';
|
|
19
|
+
/**
|
|
20
|
+
* One proposed change to one cell, with where it came from and where it
|
|
21
|
+
* stands.
|
|
22
|
+
*/
|
|
14
23
|
export type Proposal = {
|
|
15
24
|
id: string;
|
|
16
25
|
/** Only `update` in this release; inserts and deletes come later. */
|
|
@@ -53,6 +62,10 @@ export type ChangeSet = {
|
|
|
53
62
|
* has to look.
|
|
54
63
|
*/
|
|
55
64
|
export type GroupKind = 'whitespace' | 'case' | 'format' | 'scale' | 'same-mapping' | 'fill-empty' | 'constant-target' | 'unpatterned';
|
|
65
|
+
/**
|
|
66
|
+
* Proposals that make the same change, as the panel lists them: a label, a
|
|
67
|
+
* kind, whether a rule proves every member, and a sample to check.
|
|
68
|
+
*/
|
|
56
69
|
export type ProposalGroup = {
|
|
57
70
|
/** Stable while the group's members do not change: source, field, kind and param. */
|
|
58
71
|
key: string;
|
package/dist/version.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
|
|
12
12
|
*/
|
|
13
|
-
export declare const SVGRID_VERSION = "3.1.
|
|
13
|
+
export declare const SVGRID_VERSION = "3.1.25";
|
|
14
14
|
/**
|
|
15
15
|
* The version of `@svgrid/grid`, which releases on its own line: enterprise is
|
|
16
16
|
* on 3.1.x while the grid is on 3.0.x.
|
package/dist/version.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
|
|
12
12
|
*/
|
|
13
|
-
export const SVGRID_VERSION = '3.1.
|
|
13
|
+
export const SVGRID_VERSION = '3.1.25';
|
|
14
14
|
/**
|
|
15
15
|
* The version of `@svgrid/grid`, which releases on its own line: enterprise is
|
|
16
16
|
* on 3.1.x while the grid is on 3.0.x.
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "commercial",
|
|
5
5
|
"url": "https://svgrid.com/pricing"
|
|
6
6
|
},
|
|
7
|
-
"version": "3.1.
|
|
7
|
+
"version": "3.1.25",
|
|
8
8
|
"description": "Enterprise feature pack for SvGrid: the server-side row model (lazy grouping, tree, pivot, transactions, selection across unloaded rows), Excel (xlsx) and PDF export, Excel/CSV/JSON import, pivot tables with a drag-and-drop designer, paginated print, Kanban board and scheduler renderers, no-code alerts and batch editing. CSV, TSV and JSON export are already free in @svgrid/grid. Requires a paid license key.",
|
|
9
9
|
"license": "SEE LICENSE IN LICENSE",
|
|
10
10
|
"author": "jQWidgets <sales@jqwidgets.com>",
|