@svgrid/enterprise 3.1.22 → 3.1.24

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.
Files changed (57) hide show
  1. package/dist/SvGridBoard.svelte +39 -0
  2. package/dist/SvGridGallery.svelte +23 -0
  3. package/dist/SvGridScheduler.svelte +25 -7
  4. package/dist/cdn/svgrid-enterprise.svelte-external.js +13739 -13667
  5. package/dist/designer/assets/{index-ICCQKTGR.js → index-BB1G1RTR.js} +318 -318
  6. package/dist/designer/assets/index-CHx3F4Ij.css +1 -0
  7. package/dist/designer/assets/merges-Bg-KqPEl.js +1 -0
  8. package/dist/designer/index.html +2 -2
  9. package/dist/export.d.ts +7 -0
  10. package/dist/export.js +7 -0
  11. package/dist/fields/RecordView.svelte +5 -2
  12. package/dist/fields/activity.svelte.d.ts +5 -2
  13. package/dist/fields/activity.svelte.js +4 -3
  14. package/dist/fields/grid-access.d.ts +1 -1
  15. package/dist/fields/grid-access.js +13 -3
  16. package/dist/fields/index.d.ts +18 -0
  17. package/dist/fields/index.js +31 -0
  18. package/dist/node/studio.js +2 -2
  19. package/dist/review/GhostCell.svelte +60 -0
  20. package/dist/review/GhostCell.svelte.d.ts +14 -0
  21. package/dist/review/RichCellMark.svelte +72 -0
  22. package/dist/review/RichCellMark.svelte.d.ts +8 -0
  23. package/dist/review/SvReviewPanel.svelte +759 -0
  24. package/dist/review/SvReviewPanel.svelte.d.ts +16 -0
  25. package/dist/review/adapters.d.ts +91 -0
  26. package/dist/review/adapters.js +127 -0
  27. package/dist/review/agent.d.ts +65 -0
  28. package/dist/review/agent.js +237 -0
  29. package/dist/review/card-marks.svelte.d.ts +42 -0
  30. package/dist/review/card-marks.svelte.js +51 -0
  31. package/dist/review/cluster.d.ts +40 -0
  32. package/dist/review/cluster.js +386 -0
  33. package/dist/review/equal.d.ts +14 -0
  34. package/dist/review/equal.js +40 -0
  35. package/dist/review/formats.d.ts +42 -0
  36. package/dist/review/formats.js +48 -0
  37. package/dist/review/ghost.d.ts +18 -0
  38. package/dist/review/ghost.js +105 -0
  39. package/dist/review/index.d.ts +42 -0
  40. package/dist/review/index.js +36 -0
  41. package/dist/review/messages.d.ts +122 -0
  42. package/dist/review/messages.js +141 -0
  43. package/dist/review/model.svelte.d.ts +294 -0
  44. package/dist/review/model.svelte.js +890 -0
  45. package/dist/review/pending-filter.d.ts +26 -0
  46. package/dist/review/pending-filter.js +71 -0
  47. package/dist/review/rich-cells.d.ts +1 -0
  48. package/dist/review/rich-cells.js +36 -0
  49. package/dist/review/types.d.ts +96 -0
  50. package/dist/review/types.js +7 -0
  51. package/dist/upgrade-prompt.d.ts +1 -1
  52. package/dist/version.d.ts +2 -2
  53. package/dist/version.js +2 -2
  54. package/dist/wc/merges-DQTOlMWM.js +109 -0
  55. package/dist/wc/sv-sheet-element.js +5688 -5735
  56. package/package.json +9 -3
  57. package/dist/designer/assets/index-9APkRkTg.css +0 -1
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @svgrid/enterprise/review - change review. Writes nobody typed (AI helper
3
+ * results, agent edits, imports, syncs) arrive as proposals held apart from
4
+ * the data, grouped by the transformation they apply, and are accepted or
5
+ * rejected a group at a time. Accepted values are written to the app's data,
6
+ * a cell that changed since the proposal was made is never overwritten, and
7
+ * every decision is one Ctrl+Z.
8
+ *
9
+ * ```svelte
10
+ * <script lang="ts">
11
+ * import { SvGrid } from '@svgrid/grid'
12
+ * import { createReview, reviewSmartFill, SvReviewPanel } from '@svgrid/enterprise/review'
13
+ *
14
+ * let rows = $state(initialRows)
15
+ * let api = $state()
16
+ * const review = createReview({ api: () => api, setRows: (next) => (rows = next) })
17
+ * </script>
18
+ *
19
+ * <SvGrid data={rows} columns={review.columns(columns)} getRowId={(r) => r.id}
20
+ * conditionalFormats={review.formats} onApiReady={(a) => (api = a)} />
21
+ * <SvReviewPanel {review} />
22
+ * ```
23
+ *
24
+ * Adds nothing to `@svgrid/grid`: the tint is `conditionalFormats`, the
25
+ * proposed value is a wrapped `cell`, the undo step is the public command
26
+ * context.
27
+ */
28
+ export { createReview } from './model.svelte.js';
29
+ export type { Review, ReviewOptions, ReviewOutcome, ReviewGridApi, ReviewJSON, ReviewDecision, AddInput } from './model.svelte.js';
30
+ export { createGridTools, registerWebMcpTools } from './agent.js';
31
+ export type { GridTool, GridToolsOptions } from './agent.js';
32
+ export { clusterProposals, showValue } from './cluster.js';
33
+ export type { ClusterOptions } from './cluster.js';
34
+ export { sameValue, isBlank } from './equal.js';
35
+ export { REVIEW_MESSAGES } from './messages.js';
36
+ export type { ReviewMessages } from './messages.js';
37
+ export { pendingFormats, PENDING_BG, PENDING_ICON, CONFLICT_BG, CONFLICT_ICON } from './formats.js';
38
+ export { canGhost } from './ghost.js';
39
+ export { fromSmartFill, fromClassify, fromRows, fromStaged, reviewSmartFill, reviewClassify, blankTargets } from './adapters.js';
40
+ export type { AdapterResult } from './adapters.js';
41
+ export type { Proposal, ProposalInput, ProposalSource, ProposalStatus, ChangeSet, GroupKind, ProposalGroup } from './types.js';
42
+ export { default as SvReviewPanel } from './SvReviewPanel.svelte';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @svgrid/enterprise/review - change review. Writes nobody typed (AI helper
3
+ * results, agent edits, imports, syncs) arrive as proposals held apart from
4
+ * the data, grouped by the transformation they apply, and are accepted or
5
+ * rejected a group at a time. Accepted values are written to the app's data,
6
+ * a cell that changed since the proposal was made is never overwritten, and
7
+ * every decision is one Ctrl+Z.
8
+ *
9
+ * ```svelte
10
+ * <script lang="ts">
11
+ * import { SvGrid } from '@svgrid/grid'
12
+ * import { createReview, reviewSmartFill, SvReviewPanel } from '@svgrid/enterprise/review'
13
+ *
14
+ * let rows = $state(initialRows)
15
+ * let api = $state()
16
+ * const review = createReview({ api: () => api, setRows: (next) => (rows = next) })
17
+ * </script>
18
+ *
19
+ * <SvGrid data={rows} columns={review.columns(columns)} getRowId={(r) => r.id}
20
+ * conditionalFormats={review.formats} onApiReady={(a) => (api = a)} />
21
+ * <SvReviewPanel {review} />
22
+ * ```
23
+ *
24
+ * Adds nothing to `@svgrid/grid`: the tint is `conditionalFormats`, the
25
+ * proposed value is a wrapped `cell`, the undo step is the public command
26
+ * context.
27
+ */
28
+ export { createReview } from './model.svelte.js';
29
+ export { createGridTools, registerWebMcpTools } from './agent.js';
30
+ export { clusterProposals, showValue } from './cluster.js';
31
+ export { sameValue, isBlank } from './equal.js';
32
+ export { REVIEW_MESSAGES } from './messages.js';
33
+ export { pendingFormats, PENDING_BG, PENDING_ICON, CONFLICT_BG, CONFLICT_ICON } from './formats.js';
34
+ export { canGhost } from './ghost.js';
35
+ export { fromSmartFill, fromClassify, fromRows, fromStaged, reviewSmartFill, reviewClassify, blankTargets } from './adapters.js';
36
+ export { default as SvReviewPanel } from './SvReviewPanel.svelte';
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Every string change review shows: the panel, the group labels, the card and
3
+ * cell marks. English defaults; pass any subset as `createReview({ messages })`
4
+ * (and `<SvReviewPanel messages>` for one panel), unset keys stay English. The
5
+ * idiom of the grid's own `localization.text`: a flat map, `{name}`
6
+ * placeholders. Kept free of imports: the clustering uses it in plain Node.
7
+ */
8
+ export declare const REVIEW_MESSAGES: {
9
+ title: string;
10
+ decided: string;
11
+ pendingInGroups: string;
12
+ pendingInOneGroup: string;
13
+ nothingPending: string;
14
+ inConflict: string;
15
+ acceptAll: string;
16
+ rejectAll: string;
17
+ acceptRuleGroups: string;
18
+ resolveFirst: string;
19
+ onlyRowsWithChanges: string;
20
+ confirmAcceptGroup: string;
21
+ confirmRejectGroup: string;
22
+ confirmAcceptAll: string;
23
+ confirmRejectAll: string;
24
+ confirmAcceptRules: string;
25
+ confirmYes: string;
26
+ cancel: string;
27
+ conflictsTitle: string;
28
+ conflictCell: string;
29
+ keep: string;
30
+ badgeRule: string;
31
+ hintRule: string;
32
+ hintMapping: string;
33
+ hintFill: string;
34
+ hintConstant: string;
35
+ hintEach: string;
36
+ oneChange: string;
37
+ changes: string;
38
+ sure: string;
39
+ sureRange: string;
40
+ accept: string;
41
+ reject: string;
42
+ acceptGroupLabel: string;
43
+ rejectGroupLabel: string;
44
+ from: string;
45
+ otherValues: string;
46
+ sampleOf: string;
47
+ everyChange: string;
48
+ firstN: string;
49
+ showRow: string;
50
+ rowId: string;
51
+ acceptOne: string;
52
+ rejectOne: string;
53
+ showAll: string;
54
+ keysHint: string;
55
+ showInGrid: string;
56
+ nextInGrid: string;
57
+ hiddenRows: string;
58
+ allReviewed: string;
59
+ reviewedSummary: string;
60
+ reviewedStale: string;
61
+ noProposals: string;
62
+ noProposalsHint: string;
63
+ notWritten: string;
64
+ rowField: string;
65
+ decidedLabel: string;
66
+ noteCellChanged: string;
67
+ noteRowGone: string;
68
+ noteRowEditing: string;
69
+ noteGridNotReady: string;
70
+ noteSavedStale: string;
71
+ noteConflict: string;
72
+ undoHint: string;
73
+ announceAccepted: string;
74
+ announceRejected: string;
75
+ announceStale: string;
76
+ announceSkipped: string;
77
+ announceCommittedStale: string;
78
+ announceNotSaved: string;
79
+ announceNothing: string;
80
+ undoFailed: string;
81
+ redoFailed: string;
82
+ cardProposed: string;
83
+ proposes: string;
84
+ nowValue: string;
85
+ empty: string;
86
+ labelWhitespace: string;
87
+ labelCase: string;
88
+ caseUpper: string;
89
+ caseLower: string;
90
+ caseTitle: string;
91
+ caseMixed: string;
92
+ labelToNumber: string;
93
+ labelDates: string;
94
+ datesAsDates: string;
95
+ labelShape: string;
96
+ labelPunct: string;
97
+ punctRemove: string;
98
+ punctAdd: string;
99
+ punctSpaces: string;
100
+ labelDivide: string;
101
+ labelMultiply: string;
102
+ labelMapping: string;
103
+ mappingValues: string;
104
+ labelFill: string;
105
+ labelFillVarious: string;
106
+ labelConstant: string;
107
+ labelUnpatterned: string;
108
+ };
109
+ /**
110
+ * Every string the review shows, with the keys of `REVIEW_MESSAGES`.
111
+ */
112
+ export type ReviewMessages = typeof REVIEW_MESSAGES;
113
+ /**
114
+ * English, with `overrides` laid over it (blank values ignored).
115
+ * @internal
116
+ */
117
+ export declare function reviewMessages(...overrides: Array<Partial<ReviewMessages> | null | undefined>): ReviewMessages;
118
+ /**
119
+ * A template with its `{name}` placeholders filled.
120
+ * @internal
121
+ */
122
+ export declare function fill(template: string, vars: Record<string, string | number>): string;
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Every string change review shows: the panel, the group labels, the card and
3
+ * cell marks. English defaults; pass any subset as `createReview({ messages })`
4
+ * (and `<SvReviewPanel messages>` for one panel), unset keys stay English. The
5
+ * idiom of the grid's own `localization.text`: a flat map, `{name}`
6
+ * placeholders. Kept free of imports: the clustering uses it in plain Node.
7
+ */
8
+ export const REVIEW_MESSAGES = {
9
+ // Panel header
10
+ title: 'Review changes',
11
+ decided: '{decided} of {total} decided',
12
+ pendingInGroups: '{count} pending in {groups} groups',
13
+ pendingInOneGroup: '{count} pending in 1 group',
14
+ nothingPending: 'Nothing pending',
15
+ inConflict: ', {count} in conflict',
16
+ acceptAll: 'Accept all',
17
+ rejectAll: 'Reject all',
18
+ acceptRuleGroups: 'Accept rule groups ({count})',
19
+ resolveFirst: 'Resolve the conflicts before accepting everything.',
20
+ onlyRowsWithChanges: 'Only rows with changes',
21
+ // Confirm
22
+ confirmAcceptGroup: 'Accept {count} changes: {label}?',
23
+ confirmRejectGroup: 'Reject {count} changes: {label}?',
24
+ confirmAcceptAll: 'Accept all {count} changes?',
25
+ confirmRejectAll: 'Reject all {count} changes?',
26
+ confirmAcceptRules: 'Accept {groups} rule groups ({count} changes)?',
27
+ confirmYes: 'Yes, {count}',
28
+ cancel: 'Cancel',
29
+ // Conflicts
30
+ conflictsTitle: 'Two sources disagree',
31
+ conflictCell: '{row}, {field}: now {value}',
32
+ keep: 'Keep {value}',
33
+ // Groups
34
+ badgeRule: 'Rule',
35
+ hintRule: 'Every change in this group follows the rule.',
36
+ hintMapping: 'Check the mapping before accepting.',
37
+ hintFill: 'Check the sample: the least sure ones come first.',
38
+ hintConstant: 'Many different values set to one: check what they were.',
39
+ hintEach: 'No shared pattern: look at each change.',
40
+ oneChange: '{count} change',
41
+ changes: '{count} changes',
42
+ sure: '{pct} sure',
43
+ sureRange: '{min} to {avg} sure',
44
+ accept: 'Accept',
45
+ reject: 'Reject',
46
+ acceptGroupLabel: 'Accept {count}: {label}',
47
+ rejectGroupLabel: 'Reject {count}: {label}',
48
+ from: 'From',
49
+ otherValues: 'other values',
50
+ sampleOf: 'Sample of {count}',
51
+ everyChange: 'Every change',
52
+ firstN: 'First {count}',
53
+ showRow: 'Show {row} in the grid',
54
+ rowId: 'Row {row}',
55
+ acceptOne: 'Accept this change',
56
+ rejectOne: 'Reject this change',
57
+ showAll: 'Show all {count}',
58
+ keysHint: 'J / K move between groups, Enter opens one, A accepts it, R rejects it.',
59
+ showInGrid: 'Show in grid',
60
+ nextInGrid: 'Next in grid',
61
+ hiddenRows: '{count} hidden by filters or grouping',
62
+ // Empty and done
63
+ allReviewed: 'All {count} reviewed',
64
+ reviewedSummary: '{accepted} accepted, {rejected} rejected',
65
+ reviewedStale: ', {count} not written because the cell changed',
66
+ noProposals: 'No proposals yet',
67
+ noProposalsHint: 'Edits an agent, an import or an AI helper proposes show up here, grouped by what they change.',
68
+ notWritten: '{count} not written',
69
+ rowField: '{row}, {field}',
70
+ decidedLabel: 'Decided',
71
+ // Why a proposal was not written or is waiting (shown in the panel)
72
+ noteCellChanged: 'the cell changed after this was proposed',
73
+ noteRowGone: 'the row no longer exists',
74
+ noteRowEditing: 'the row is being edited',
75
+ noteGridNotReady: 'the grid is not ready',
76
+ noteSavedStale: 'saved, but the cell changed before it was written here',
77
+ noteConflict: 'another source proposed a different value',
78
+ undoHint: 'Ctrl+Z in the grid undoes the last decision.',
79
+ // Announced after a decision
80
+ announceAccepted: '{count} accepted',
81
+ announceRejected: '{count} rejected',
82
+ announceStale: '{count} not written: the cell changed',
83
+ announceSkipped: '{count} left pending',
84
+ announceCommittedStale: '{count} saved but not shown: the cell changed while saving',
85
+ announceNotSaved: 'not saved: {error}',
86
+ announceNothing: 'Nothing to decide',
87
+ undoFailed: 'Undo not saved: {error}',
88
+ redoFailed: 'Redo not saved: {error}',
89
+ // Marks
90
+ cardProposed: '{count} proposed',
91
+ proposes: '{source} proposes {value}',
92
+ nowValue: 'Now: {value}',
93
+ empty: '(empty)',
94
+ // Group labels ({field} is the column header)
95
+ labelWhitespace: 'Trim spaces in {field}',
96
+ labelCase: 'Change {field} to {case}',
97
+ caseUpper: 'UPPER CASE',
98
+ caseLower: 'lower case',
99
+ caseTitle: 'Title Case',
100
+ caseMixed: 'a different case',
101
+ labelToNumber: 'Convert {field} text to numbers',
102
+ labelDates: 'Reformat {field} dates as {shape}',
103
+ datesAsDates: 'dates',
104
+ labelShape: 'Reformat {field} as {shape}',
105
+ labelPunct: '{change} in {field}',
106
+ punctRemove: 'remove {chars}',
107
+ punctAdd: 'add {chars}',
108
+ punctSpaces: 'spaces',
109
+ labelDivide: 'Divide {field} by {n}',
110
+ labelMultiply: 'Multiply {field} by {n}',
111
+ labelMapping: '{field}: {from} → {to}',
112
+ mappingValues: '{count} values',
113
+ labelFill: 'Fill empty {field} with {value}',
114
+ labelFillVarious: 'Fill empty {field} (different values)',
115
+ labelConstant: 'Set {field} to {value}',
116
+ labelUnpatterned: '{field}: no shared pattern',
117
+ };
118
+ /**
119
+ * English, with `overrides` laid over it (blank values ignored).
120
+ * @internal
121
+ */
122
+ export function reviewMessages(...overrides) {
123
+ const out = { ...REVIEW_MESSAGES };
124
+ for (const o of overrides) {
125
+ if (!o)
126
+ continue;
127
+ for (const k in o) {
128
+ const v = o[k];
129
+ if (v != null && v !== '')
130
+ out[k] = v;
131
+ }
132
+ }
133
+ return out;
134
+ }
135
+ /**
136
+ * A template with its `{name}` placeholders filled.
137
+ * @internal
138
+ */
139
+ export function fill(template, vars) {
140
+ return template.replace(/\{(\w+)\}/g, (whole, key) => (key in vars ? String(vars[key]) : whole));
141
+ }
@@ -0,0 +1,294 @@
1
+ /**
2
+ * A change review: proposals held apart from the grid's data until a person
3
+ * accepts them, grouped for review, written to the app's data on accept, and
4
+ * undone with one Ctrl+Z per decision.
5
+ *
6
+ * ```svelte
7
+ * <script lang="ts">
8
+ * import { createReview, SvReviewPanel } from '@svgrid/enterprise/review'
9
+ * let orders = $state(initial)
10
+ * let api = $state()
11
+ * const review = createReview({ api: () => api, setRows: (next) => (orders = next) })
12
+ * review.add({ source: { kind: 'agent', id: 'cleanup', label: 'Cleanup agent' }, proposals })
13
+ * </script>
14
+ *
15
+ * <SvGrid data={orders} columns={review.columns(columns)} getRowId={(r) => r.id}
16
+ * conditionalFormats={review.formats} onApiReady={(a) => (api = a)} />
17
+ * <SvReviewPanel {review} />
18
+ * ```
19
+ *
20
+ * Why the app's data and not the grid's writers: `api.setCellValue` and the
21
+ * command context write by view index into the grid's own copy, which the
22
+ * next `data` prop discards. Reads go through `api.getData()` instead, which
23
+ * includes the grid's own writes (paste, fill, addRows), so `next` carries
24
+ * them forward. `setRows` must apply synchronously.
25
+ */
26
+ import type { ConditionalFormat, SvGridApi } from '@svgrid/grid';
27
+ import { type ClusterOptions } from './cluster.js';
28
+ import { type ReviewMessages } from './messages.js';
29
+ import type { ChangeSet, Proposal, ProposalGroup, ProposalInput, ProposalSource } from './types.js';
30
+ /** The part of the grid api a review uses. Any `SvGridApi` satisfies it. */
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
+ */
37
+ export type ReviewOptions<TData> = {
38
+ /** The grid api, or a getter for it (it is bound after mount). */
39
+ api: ReviewGridApi | (() => ReviewGridApi | undefined | null);
40
+ /** Replace the app's rows. Required unless `server` is set. Must apply synchronously. */
41
+ setRows?: (next: TData[]) => void;
42
+ /**
43
+ * Server row model: the controller passed to the grid as `rowModel`.
44
+ * Accept and undo commit through `onCommit` and then refresh it.
45
+ */
46
+ server?: {
47
+ refresh(): void;
48
+ };
49
+ /** Persist accepted values. Reject (throw) to keep them pending. Required with `server`. */
50
+ onCommit?: (accepted: Proposal[]) => void | Promise<void>;
51
+ /** Who decides, stamped on each decided proposal. */
52
+ user?: string;
53
+ cluster?: ClusterOptions;
54
+ /** Wording of everything the review shows (panel, group labels, marks); English by default. */
55
+ messages?: Partial<ReviewMessages>;
56
+ /**
57
+ * Called after every decision, its undo and its redo, with copies of the
58
+ * proposals it moved. Write these to an audit log of your own.
59
+ */
60
+ onDecision?: (decision: ReviewDecision) => void;
61
+ /**
62
+ * Called as accepted values (or an undo / redo of them) are written, with
63
+ * the proposals and the new rows just before they go to `setRows`, so
64
+ * bookkeeping that edits a row lands in the same write. SvGrid Base stamps
65
+ * "last modified" and notes the record's activity with
66
+ * `baseReviewApplied(api)` from `@svgrid/enterprise/base`. With a server
67
+ * row model there are no rows to edit: `rows` is undefined.
68
+ */
69
+ onApply?: (applied: Proposal[], how: 'accept' | 'undo' | 'redo', rows?: TData[]) => void;
70
+ /**
71
+ * An undo or redo whose `onCommit` failed: nothing was written and the
72
+ * decision stands. Also kept as `review.lastError`, which the panel announces.
73
+ */
74
+ onError?: (error: unknown, during: 'undo' | 'redo') => void;
75
+ /**
76
+ * What names a row on the panel's lines, such as its company, so a reviewer
77
+ * knows whose record a change is in. Default: the row's first visible text
78
+ * column, left out when that column is the one the change is to.
79
+ */
80
+ rowLabel?: (row: TData) => string | null | undefined;
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
+ */
86
+ export type ReviewDecision = {
87
+ action: 'accept' | 'reject' | 'undo' | 'redo';
88
+ /** For undo / redo: which decision was undone or redone. */
89
+ of?: 'accept' | 'reject';
90
+ proposals: Proposal[];
91
+ by?: string;
92
+ at: number;
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
+ */
99
+ export type ReviewOutcome = {
100
+ accepted: string[];
101
+ rejected: string[];
102
+ /** The cell changed since the proposal was made, or its row is gone. Never written. */
103
+ stale: string[];
104
+ /** Left pending: the row is being edited, the proposal is already being accepted, or the grid is not ready. */
105
+ skipped: string[];
106
+ /**
107
+ * Saved by `onCommit`, then not written here because the cell changed while
108
+ * it was saving. The backend holds the proposed value; reload or save the
109
+ * cell's value back.
110
+ */
111
+ committedStale: string[];
112
+ /** What `onCommit` threw; nothing was written and the proposals stay pending. */
113
+ error?: unknown;
114
+ };
115
+ /**
116
+ * A change set for `review.add`: where it came from, an optional title and
117
+ * id, and its proposals.
118
+ */
119
+ export type AddInput = {
120
+ source: ProposalSource;
121
+ title?: string;
122
+ id?: string;
123
+ proposals: ReadonlyArray<ProposalInput>;
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
+ */
129
+ export type ReviewJSON = {
130
+ v: 1;
131
+ sets: ChangeSet[];
132
+ };
133
+ /**
134
+ * What `createReview` returns.
135
+ */
136
+ export type Review<TData = unknown> = ReturnType<typeof createReview<TData>>;
137
+ /**
138
+ * Hold writes nobody typed (an agent's edits, an import, an AI helper's
139
+ * output) as proposals, grouped by the change they make, and write them only
140
+ * when a person accepts them. Give the grid `review.columns(columns)` and
141
+ * `review.formats`, and render `<SvReviewPanel {review} />` beside it. Each
142
+ * decision is one Ctrl+Z in the grid.
143
+ */
144
+ export declare function createReview<TData = unknown>(opts: ReviewOptions<TData>): {
145
+ readonly version: number;
146
+ /** The wording in effect: English with `messages` laid over it. */
147
+ messages: {
148
+ title: string;
149
+ decided: string;
150
+ pendingInGroups: string;
151
+ pendingInOneGroup: string;
152
+ nothingPending: string;
153
+ inConflict: string;
154
+ acceptAll: string;
155
+ rejectAll: string;
156
+ acceptRuleGroups: string;
157
+ resolveFirst: string;
158
+ onlyRowsWithChanges: string;
159
+ confirmAcceptGroup: string;
160
+ confirmRejectGroup: string;
161
+ confirmAcceptAll: string;
162
+ confirmRejectAll: string;
163
+ confirmAcceptRules: string;
164
+ confirmYes: string;
165
+ cancel: string;
166
+ conflictsTitle: string;
167
+ conflictCell: string;
168
+ keep: string;
169
+ badgeRule: string;
170
+ hintRule: string;
171
+ hintMapping: string;
172
+ hintFill: string;
173
+ hintConstant: string;
174
+ hintEach: string;
175
+ oneChange: string;
176
+ changes: string;
177
+ sure: string;
178
+ sureRange: string;
179
+ accept: string;
180
+ reject: string;
181
+ acceptGroupLabel: string;
182
+ rejectGroupLabel: string;
183
+ from: string;
184
+ otherValues: string;
185
+ sampleOf: string;
186
+ everyChange: string;
187
+ firstN: string;
188
+ showRow: string;
189
+ rowId: string;
190
+ acceptOne: string;
191
+ rejectOne: string;
192
+ showAll: string;
193
+ keysHint: string;
194
+ showInGrid: string;
195
+ nextInGrid: string;
196
+ hiddenRows: string;
197
+ allReviewed: string;
198
+ reviewedSummary: string;
199
+ reviewedStale: string;
200
+ noProposals: string;
201
+ noProposalsHint: string;
202
+ notWritten: string;
203
+ rowField: string;
204
+ decidedLabel: string;
205
+ noteCellChanged: string;
206
+ noteRowGone: string;
207
+ noteRowEditing: string;
208
+ noteGridNotReady: string;
209
+ noteSavedStale: string;
210
+ noteConflict: string;
211
+ undoHint: string;
212
+ announceAccepted: string;
213
+ announceRejected: string;
214
+ announceStale: string;
215
+ announceSkipped: string;
216
+ announceCommittedStale: string;
217
+ announceNotSaved: string;
218
+ announceNothing: string;
219
+ undoFailed: string;
220
+ redoFailed: string;
221
+ cardProposed: string;
222
+ proposes: string;
223
+ nowValue: string;
224
+ empty: string;
225
+ labelWhitespace: string;
226
+ labelCase: string;
227
+ caseUpper: string;
228
+ caseLower: string;
229
+ caseTitle: string;
230
+ caseMixed: string;
231
+ labelToNumber: string;
232
+ labelDates: string;
233
+ datesAsDates: string;
234
+ labelShape: string;
235
+ labelPunct: string;
236
+ punctRemove: string;
237
+ punctAdd: string;
238
+ punctSpaces: string;
239
+ labelDivide: string;
240
+ labelMultiply: string;
241
+ labelMapping: string;
242
+ mappingValues: string;
243
+ labelFill: string;
244
+ labelFillVarious: string;
245
+ labelConstant: string;
246
+ labelUnpatterned: string;
247
+ };
248
+ /** The last undo or redo whose save failed, or null. */
249
+ readonly lastError: {
250
+ error: unknown;
251
+ during: "undo" | "redo";
252
+ at: number;
253
+ } | null;
254
+ add: (input: AddInput) => ChangeSet;
255
+ get: (id: string) => Proposal | undefined;
256
+ proposals: () => Proposal[];
257
+ /** What names the proposal's row (`rowLabel`), or null. */
258
+ rowLabel: (p: Proposal) => string | null;
259
+ /** A field's column header, as the group labels show it. */
260
+ fieldLabel: (field: string) => string;
261
+ pending: () => Proposal[];
262
+ conflicts: () => Proposal[];
263
+ groups: () => ProposalGroup[];
264
+ pendingFor: (rowId: string, field: string) => Proposal | undefined;
265
+ accept: (ids: ReadonlyArray<string>) => Promise<ReviewOutcome>;
266
+ reject: (ids: ReadonlyArray<string>) => ReviewOutcome;
267
+ acceptGroup: (key: string, shownIds: ReadonlyArray<string>) => Promise<ReviewOutcome>;
268
+ rejectGroup: (key: string, shownIds: ReadonlyArray<string>) => ReviewOutcome;
269
+ resolveConflict: (keepId: string) => void;
270
+ readonly formats: ConditionalFormat<any>[];
271
+ columns: <C extends ReadonlyArray<any>>(cols: C) => C;
272
+ reveal: (ids: ReadonlyArray<string>, fromId?: string) => {
273
+ id: string | null;
274
+ hidden: number;
275
+ };
276
+ showPendingOnly: (on: boolean) => void;
277
+ /** On while our condition is in the grid's advanced filter (the grid's own Clear takes it out too). */
278
+ readonly pendingOnly: boolean;
279
+ toJSON: (opts?: {
280
+ setIds?: ReadonlyArray<string>;
281
+ }) => ReviewJSON;
282
+ load: (json: ReviewJSON) => {
283
+ dropped: number;
284
+ };
285
+ merge: (json: ReviewJSON) => {
286
+ dropped: number;
287
+ };
288
+ log: () => Proposal[];
289
+ revertSet: (setId: string) => ChangeSet | null;
290
+ sets: () => Array<Omit<ChangeSet, "proposals"> & {
291
+ count: number;
292
+ }>;
293
+ clear: () => void;
294
+ };