@contentful/experience-design-system-cli 2.14.2 → 2.15.0
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/README.md +64 -2
- package/dist/package.json +3 -2
- package/dist/src/analyze/command.d.ts +11 -0
- package/dist/src/analyze/command.js +298 -3
- package/dist/src/analyze/composite-closure.d.ts +25 -0
- package/dist/src/analyze/composite-closure.js +0 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.d.ts +4 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.js +22 -0
- package/dist/src/analyze/composition/agent-parser/extract-parser.d.ts +8 -0
- package/dist/src/analyze/composition/agent-parser/extract-parser.js +44 -0
- package/dist/src/analyze/composition/agent-parser/load-prompt.d.ts +7 -0
- package/dist/src/analyze/composition/agent-parser/load-prompt.js +31 -0
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.d.ts +46 -0
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +88 -0
- package/dist/src/analyze/composition/agent-parser/sandbox.d.ts +45 -0
- package/dist/src/analyze/composition/agent-parser/sandbox.js +187 -0
- package/dist/src/analyze/composition/apply-mapping.d.ts +22 -0
- package/dist/src/analyze/composition/apply-mapping.js +67 -0
- package/dist/src/analyze/composition/candidate-critic-agent.d.ts +7 -0
- package/dist/src/analyze/composition/candidate-critic-agent.js +39 -0
- package/dist/src/analyze/composition/candidate-critic.d.ts +32 -0
- package/dist/src/analyze/composition/candidate-critic.js +63 -0
- package/dist/src/analyze/composition/candidate-files.d.ts +34 -0
- package/dist/src/analyze/composition/candidate-files.js +131 -0
- package/dist/src/analyze/composition/composition-cache-key.d.ts +19 -0
- package/dist/src/analyze/composition/composition-cache-key.js +19 -0
- package/dist/src/analyze/composition/interchange-schema.d.ts +37 -0
- package/dist/src/analyze/composition/interchange-schema.js +61 -0
- package/dist/src/analyze/composition/merge-edges.d.ts +19 -0
- package/dist/src/analyze/composition/merge-edges.js +50 -0
- package/dist/src/analyze/composition/parse-map-edges.d.ts +16 -0
- package/dist/src/analyze/composition/parse-map-edges.js +55 -0
- package/dist/src/analyze/composition/resolve-mapping-cli.d.ts +23 -0
- package/dist/src/analyze/composition/resolve-mapping-cli.js +29 -0
- package/dist/src/analyze/composition/resolve-mapping.d.ts +59 -0
- package/dist/src/analyze/composition/resolve-mapping.js +94 -0
- package/dist/src/analyze/cycle-detection.d.ts +27 -0
- package/dist/src/analyze/cycle-detection.js +234 -0
- package/dist/src/analyze/cycle-view.d.ts +7 -0
- package/dist/src/analyze/cycle-view.js +28 -0
- package/dist/src/analyze/fuzzy-search.d.ts +3 -0
- package/dist/src/analyze/fuzzy-search.js +55 -0
- package/dist/src/analyze/issue-inheritance.d.ts +12 -0
- package/dist/src/analyze/issue-inheritance.js +108 -0
- package/dist/src/analyze/lineage.d.ts +29 -0
- package/dist/src/analyze/lineage.js +0 -0
- package/dist/src/analyze/scope-gate-cascade.d.ts +11 -0
- package/dist/src/analyze/scope-gate-cascade.js +170 -0
- package/dist/src/analyze/search-neighborhood.d.ts +3 -0
- package/dist/src/analyze/search-neighborhood.js +56 -0
- package/dist/src/analyze/select/tui/App.js +5 -16
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.d.ts +0 -4
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +3 -15
- package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +29 -38
- package/dist/src/analyze/select/tui/components/FieldEditor.js +309 -185
- package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +13 -1
- package/dist/src/analyze/select/tui/components/FinalizeDialog.js +23 -2
- package/dist/src/analyze/select/tui/components/GotoBanner.d.ts +31 -0
- package/dist/src/analyze/select/tui/components/GotoBanner.js +30 -0
- package/dist/src/analyze/select/tui/components/GroupedSidebar.d.ts +91 -0
- package/dist/src/analyze/select/tui/components/GroupedSidebar.js +497 -0
- package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +13 -1
- package/dist/src/analyze/select/tui/components/HelpOverlay.js +9 -3
- package/dist/src/analyze/select/tui/components/JsonEditor.js +3 -3
- package/dist/src/analyze/select/tui/components/LineagePanel.d.ts +14 -0
- package/dist/src/analyze/select/tui/components/LineagePanel.js +22 -0
- package/dist/src/analyze/select/tui/components/RationalePanel.d.ts +0 -7
- package/dist/src/analyze/select/tui/components/RationalePanel.js +3 -15
- package/dist/src/analyze/select/tui/components/Sidebar.d.ts +0 -6
- package/dist/src/analyze/select/tui/components/Sidebar.js +11 -27
- package/dist/src/analyze/select/tui/components/StatusBar.js +2 -1
- package/dist/src/analyze/select/tui/components/removed-components-text.d.ts +7 -0
- package/dist/src/analyze/select/tui/components/removed-components-text.js +11 -0
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +1 -5
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +8 -10
- package/dist/src/analyze/select/tui/theme.d.ts +15 -0
- package/dist/src/analyze/select/tui/theme.js +28 -0
- package/dist/src/analyze/selection-cascade.d.ts +3 -0
- package/dist/src/analyze/selection-cascade.js +19 -0
- package/dist/src/analyze/slot-graph.d.ts +11 -0
- package/dist/src/analyze/slot-graph.js +17 -0
- package/dist/src/apply/api-client.d.ts +2 -1
- package/dist/src/apply/api-client.js +40 -6
- package/dist/src/apply/command.d.ts +17 -1
- package/dist/src/apply/command.js +69 -11
- package/dist/src/apply/error-parser.d.ts +16 -0
- package/dist/src/apply/error-parser.js +117 -0
- package/dist/src/apply/tui/ServerPreviewView.js +3 -1
- package/dist/src/credentials-store.d.ts +6 -0
- package/dist/src/credentials-store.js +5 -1
- package/dist/src/generate/agent-runner.d.ts +6 -0
- package/dist/src/generate/agent-runner.js +24 -8
- package/dist/src/import/command.js +69 -31
- package/dist/src/import/cycle-auto-reject.d.ts +4 -0
- package/dist/src/import/cycle-auto-reject.js +14 -0
- package/dist/src/import/orchestrator.d.ts +20 -7
- package/dist/src/import/orchestrator.js +139 -35
- package/dist/src/import/strip-allowed-components.d.ts +18 -0
- package/dist/src/import/strip-allowed-components.js +22 -0
- package/dist/src/import/tui/CustomPromptBanner.d.ts +0 -5
- package/dist/src/import/tui/CustomPromptBanner.js +2 -1
- package/dist/src/import/tui/WizardApp.d.ts +10 -74
- package/dist/src/import/tui/WizardApp.js +234 -246
- package/dist/src/import/tui/ai-flag.d.ts +5 -0
- package/dist/src/import/tui/ai-flag.js +6 -0
- package/dist/src/import/tui/autocomplete.d.ts +5 -0
- package/dist/src/import/tui/autocomplete.js +32 -0
- package/dist/src/import/tui/components/AutoFilterBanner.d.ts +10 -0
- package/dist/src/import/tui/components/AutoFilterBanner.js +19 -0
- package/dist/src/import/tui/components/CounterStrip.d.ts +12 -0
- package/dist/src/import/tui/components/CounterStrip.js +12 -0
- package/dist/src/import/tui/components/LegendEntry.d.ts +2 -0
- package/dist/src/import/tui/components/LegendEntry.js +6 -0
- package/dist/src/import/tui/cycle-panel-scroll.d.ts +8 -0
- package/dist/src/import/tui/cycle-panel-scroll.js +33 -0
- package/dist/src/import/tui/final-review-host.d.ts +3 -7
- package/dist/src/import/tui/final-review-host.js +9 -4
- package/dist/src/import/tui/group-collapse.d.ts +2 -0
- package/dist/src/import/tui/group-collapse.js +11 -0
- package/dist/src/import/tui/history.d.ts +22 -0
- package/dist/src/import/tui/history.js +53 -0
- package/dist/src/import/tui/hooks/useLineage.d.ts +32 -0
- package/dist/src/import/tui/hooks/useLineage.js +50 -0
- package/dist/src/import/tui/hooks/useOverlayPanel.d.ts +13 -0
- package/dist/src/import/tui/hooks/useOverlayPanel.js +27 -0
- package/dist/src/import/tui/lineage-layout.d.ts +75 -0
- package/dist/src/import/tui/lineage-layout.js +82 -0
- package/dist/src/import/tui/runLivePreview.d.ts +11 -0
- package/dist/src/import/tui/runLivePreview.js +7 -1
- package/dist/src/import/tui/scope-gate-columns.d.ts +31 -0
- package/dist/src/import/tui/scope-gate-columns.js +94 -0
- package/dist/src/import/tui/scope-gate-host.d.ts +3 -1
- package/dist/src/import/tui/scope-gate-host.js +11 -3
- package/dist/src/import/tui/sidebar-width.d.ts +1 -0
- package/dist/src/import/tui/sidebar-width.js +3 -0
- package/dist/src/import/tui/step-filters.d.ts +19 -0
- package/dist/src/import/tui/step-filters.js +42 -0
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.d.ts +42 -0
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +726 -0
- package/dist/src/import/tui/steps/AtomicScopeGateStep.d.ts +3 -0
- package/dist/src/import/tui/steps/AtomicScopeGateStep.js +211 -0
- package/dist/src/import/tui/steps/CredentialsStep.js +5 -18
- package/dist/src/import/tui/steps/DoneStep.d.ts +0 -2
- package/dist/src/import/tui/steps/DoneStep.js +3 -2
- package/dist/src/import/tui/steps/ErrorStep.js +2 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +19 -25
- package/dist/src/import/tui/steps/GenerateReviewStep.js +1258 -229
- package/dist/src/import/tui/steps/PathValidationStep.js +3 -2
- package/dist/src/import/tui/steps/PreviewStep.js +2 -1
- package/dist/src/import/tui/steps/PushDecisionGateStep.d.ts +0 -7
- package/dist/src/import/tui/steps/PushDecisionGateStep.js +3 -6
- package/dist/src/import/tui/steps/PushingStep.js +2 -1
- package/dist/src/import/tui/steps/RunningStep.d.ts +4 -1
- package/dist/src/import/tui/steps/RunningStep.js +3 -2
- package/dist/src/import/tui/steps/ScopeGateStep.d.ts +24 -0
- package/dist/src/import/tui/steps/ScopeGateStep.js +850 -193
- package/dist/src/import/tui/steps/TokenInputStep.js +2 -1
- package/dist/src/import/tui/steps/WelcomeStep.js +2 -1
- package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +6 -0
- package/dist/src/import/tui/steps/WizardPreviewStep.js +95 -56
- package/dist/src/import/tui/steps/auto-reject-decision.d.ts +7 -0
- package/dist/src/import/tui/steps/auto-reject-decision.js +9 -0
- package/dist/src/import/tui/steps/breaking-change-format.d.ts +2 -0
- package/dist/src/import/tui/steps/breaking-change-format.js +24 -0
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.d.ts +14 -0
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
- package/dist/src/import/tui/steps/preview-diff.js +48 -5
- package/dist/src/import/tui/useFinalizePreview.d.ts +34 -0
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.d.ts +3 -0
- package/dist/src/import/tui/useLivePreview.js +1 -0
- package/dist/src/import/tui/wizard-state-transitions.d.ts +5 -59
- package/dist/src/import/tui/wizard-state-transitions.js +5 -60
- package/dist/src/lib/composition-mode.d.ts +28 -0
- package/dist/src/lib/composition-mode.js +37 -0
- package/dist/src/lib/prompt-overrides.d.ts +38 -0
- package/dist/src/lib/prompt-overrides.js +69 -0
- package/dist/src/print/command.js +19 -1
- package/dist/src/runs/modify-launcher.d.ts +3 -0
- package/dist/src/runs/modify-launcher.js +2 -0
- package/dist/src/runs/replay-helpers.js +1 -0
- package/dist/src/runs/run-picker.js +2 -18
- package/dist/src/runs/store.d.ts +4 -0
- package/dist/src/session/db.d.ts +23 -40
- package/dist/src/session/db.js +110 -138
- package/dist/src/setup/composition-mode-prompt.d.ts +14 -0
- package/dist/src/setup/composition-mode-prompt.js +37 -0
- package/package.json +5 -4
- package/prompts/composition-dir-critic.md +7 -0
- package/prompts/composition-edges.md +8 -0
- package/prompts/composition-parser-repair-empty.md +1 -0
- package/prompts/composition-parser-repair-error.md +2 -0
- package/prompts/composition-parser.md +42 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ScopeGateStepProps } from './ScopeGateStep.js';
|
|
3
|
+
export declare function AtomicScopeGateStep({ components, onConfirm, onQuit, aiFilterStatus, aiFilterProgress, aiFilterError, onCancelAutoFilter, }: ScopeGateStepProps): React.ReactElement;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useStdout } from 'ink';
|
|
3
|
+
import React, { useMemo, useState } from 'react';
|
|
4
|
+
import { useImmediateInput } from '../../../analyze/select/tui/hooks/useImmediateInput.js';
|
|
5
|
+
import { PALETTE } from '../../../analyze/select/tui/theme.js';
|
|
6
|
+
import { AutoFilterBanner } from '../components/AutoFilterBanner.js';
|
|
7
|
+
import { CounterStrip } from '../components/CounterStrip.js';
|
|
8
|
+
import { isAiFlagged } from '../ai-flag.js';
|
|
9
|
+
// Atomic-mode scope gate (spec T9). Recovered from the pre-composite `main`
|
|
10
|
+
// implementation: a flat included/excluded list with NO hierarchy affordances
|
|
11
|
+
// (no closures, cycles, cascade, lineage, grouped sidebar, or graph). Styling
|
|
12
|
+
// is ported to PALETTE and the shared AutoFilterBanner/CounterStrip so it reads
|
|
13
|
+
// as the same product as its composite sibling — "fewer panels, identical look."
|
|
14
|
+
const VISIBLE_COUNT = 10;
|
|
15
|
+
const REASON_DISPLAY_MAX = 60;
|
|
16
|
+
const AI_MARKER = '*';
|
|
17
|
+
const REASON_WRAP_INDENT = ' ';
|
|
18
|
+
function truncateReason(reason) {
|
|
19
|
+
if (reason === null || reason === undefined || reason === '')
|
|
20
|
+
return '<no reason given>';
|
|
21
|
+
if (reason.length <= REASON_DISPLAY_MAX)
|
|
22
|
+
return reason;
|
|
23
|
+
return reason.slice(0, REASON_DISPLAY_MAX - 1).trimEnd() + '…';
|
|
24
|
+
}
|
|
25
|
+
export function AtomicScopeGateStep({ components, onConfirm, onQuit, aiFilterStatus = 'idle', aiFilterProgress = null, aiFilterError = null, onCancelAutoFilter, }) {
|
|
26
|
+
const { stdout } = useStdout();
|
|
27
|
+
const totalWidth = stdout?.columns ?? 80;
|
|
28
|
+
// Inverted "included" model, kept from `main` (deliberately NOT the
|
|
29
|
+
// composite step's userDecisions Map — see spec T9 "what to NOT share").
|
|
30
|
+
const [userExcluded, setUserExcluded] = useState(new Set());
|
|
31
|
+
const [userUnExcluded, setUserUnExcluded] = useState(new Set());
|
|
32
|
+
const [cursor, setCursor] = useState(0);
|
|
33
|
+
const [scrollOffset, setScrollOffset] = useState(0);
|
|
34
|
+
const [reasonPanelOpen, setReasonPanelOpen] = useState(false);
|
|
35
|
+
const aiList = components.filter(isAiFlagged);
|
|
36
|
+
const componentsList = components.filter((c) => !isAiFlagged(c));
|
|
37
|
+
const flatList = [...aiList, ...componentsList];
|
|
38
|
+
const isIncluded = (row) => {
|
|
39
|
+
if (userExcluded.has(row.name))
|
|
40
|
+
return false;
|
|
41
|
+
if (userUnExcluded.has(row.name))
|
|
42
|
+
return true;
|
|
43
|
+
// INTEG-4318: exclude on 'rejected' AND 'failed'.
|
|
44
|
+
return row.aiDecision !== 'rejected' && row.aiDecision !== 'failed';
|
|
45
|
+
};
|
|
46
|
+
const partition = () => {
|
|
47
|
+
const accepted = [];
|
|
48
|
+
const rejected = [];
|
|
49
|
+
for (const c of flatList) {
|
|
50
|
+
if (isIncluded(c))
|
|
51
|
+
accepted.push(c.name);
|
|
52
|
+
else
|
|
53
|
+
rejected.push(c.name);
|
|
54
|
+
}
|
|
55
|
+
return { accepted, rejected };
|
|
56
|
+
};
|
|
57
|
+
const toggleFocused = () => {
|
|
58
|
+
const target = flatList[cursor];
|
|
59
|
+
if (!target)
|
|
60
|
+
return;
|
|
61
|
+
const currentlyIn = isIncluded(target);
|
|
62
|
+
if (currentlyIn) {
|
|
63
|
+
setUserExcluded((prev) => {
|
|
64
|
+
if (prev.has(target.name))
|
|
65
|
+
return prev;
|
|
66
|
+
const next = new Set(prev);
|
|
67
|
+
next.add(target.name);
|
|
68
|
+
return next;
|
|
69
|
+
});
|
|
70
|
+
setUserUnExcluded((prev) => {
|
|
71
|
+
if (!prev.has(target.name))
|
|
72
|
+
return prev;
|
|
73
|
+
const next = new Set(prev);
|
|
74
|
+
next.delete(target.name);
|
|
75
|
+
return next;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
setUserUnExcluded((prev) => {
|
|
80
|
+
if (prev.has(target.name))
|
|
81
|
+
return prev;
|
|
82
|
+
const next = new Set(prev);
|
|
83
|
+
next.add(target.name);
|
|
84
|
+
return next;
|
|
85
|
+
});
|
|
86
|
+
setUserExcluded((prev) => {
|
|
87
|
+
if (!prev.has(target.name))
|
|
88
|
+
return prev;
|
|
89
|
+
const next = new Set(prev);
|
|
90
|
+
next.delete(target.name);
|
|
91
|
+
return next;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
useImmediateInput((input, key) => {
|
|
96
|
+
if (input === 'q' || key.escape) {
|
|
97
|
+
if (aiFilterStatus === 'running' && onCancelAutoFilter) {
|
|
98
|
+
onCancelAutoFilter();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (key.escape && reasonPanelOpen) {
|
|
102
|
+
setReasonPanelOpen(false);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
onQuit();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (input === 'f' || input === 'F') {
|
|
109
|
+
onConfirm(partition());
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (input === 's') {
|
|
113
|
+
setReasonPanelOpen((prev) => !prev);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (input === 'a' || input === ' ' || input === 'r') {
|
|
117
|
+
toggleFocused();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (input === 'A') {
|
|
121
|
+
const compNames = componentsList.map((c) => c.name);
|
|
122
|
+
const anyCompExcluded = componentsList.some((c) => !isIncluded(c));
|
|
123
|
+
if (anyCompExcluded) {
|
|
124
|
+
setUserUnExcluded((prev) => {
|
|
125
|
+
const next = new Set(prev);
|
|
126
|
+
for (const n of compNames)
|
|
127
|
+
next.add(n);
|
|
128
|
+
return next;
|
|
129
|
+
});
|
|
130
|
+
setUserExcluded((prev) => {
|
|
131
|
+
const next = new Set(prev);
|
|
132
|
+
for (const n of compNames)
|
|
133
|
+
next.delete(n);
|
|
134
|
+
return next;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
setUserExcluded((prev) => {
|
|
139
|
+
const next = new Set(prev);
|
|
140
|
+
for (const n of compNames)
|
|
141
|
+
next.add(n);
|
|
142
|
+
return next;
|
|
143
|
+
});
|
|
144
|
+
setUserUnExcluded((prev) => {
|
|
145
|
+
const next = new Set(prev);
|
|
146
|
+
for (const n of compNames)
|
|
147
|
+
next.delete(n);
|
|
148
|
+
return next;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (key.upArrow || input === 'k') {
|
|
154
|
+
const len = flatList.length;
|
|
155
|
+
if (len === 0)
|
|
156
|
+
return;
|
|
157
|
+
setCursor((c) => {
|
|
158
|
+
const next = c <= 0 ? 0 : c - 1;
|
|
159
|
+
setScrollOffset((prev) => Math.min(prev, next));
|
|
160
|
+
return next;
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (key.downArrow || input === 'j') {
|
|
165
|
+
const len = flatList.length;
|
|
166
|
+
if (len === 0)
|
|
167
|
+
return;
|
|
168
|
+
setCursor((c) => {
|
|
169
|
+
const next = c >= len - 1 ? len - 1 : c + 1;
|
|
170
|
+
setScrollOffset((prev) => (next >= prev + VISIBLE_COUNT ? next - VISIBLE_COUNT + 1 : prev));
|
|
171
|
+
return next;
|
|
172
|
+
});
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
const total = flatList.length;
|
|
177
|
+
const includedCount = useMemo(() => flatList.filter((c) => isIncluded(c)).length, [components, userExcluded, userUnExcluded]);
|
|
178
|
+
const hasAnyAi = flatList.some(isAiFlagged);
|
|
179
|
+
const visibleEnd = Math.min(scrollOffset + VISIBLE_COUNT, total);
|
|
180
|
+
const visible = flatList.slice(scrollOffset, visibleEnd);
|
|
181
|
+
const above = scrollOffset;
|
|
182
|
+
const below = Math.max(0, total - visibleEnd);
|
|
183
|
+
const allRejected = aiFilterStatus === 'complete' && total > 0 && flatList.every((c) => !isIncluded(c));
|
|
184
|
+
// Atomic has no groups; the counter strip shows binary included/excluded.
|
|
185
|
+
const counters = {
|
|
186
|
+
accepted: includedCount,
|
|
187
|
+
rejected: total - includedCount,
|
|
188
|
+
undecided: 0,
|
|
189
|
+
groups: 0,
|
|
190
|
+
total,
|
|
191
|
+
};
|
|
192
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [_jsx(Text, { color: PALETTE.success, children: "\u2713 Extraction complete" }), _jsxs(Text, { dimColor: true, children: ["Found ", total, " component", total === 1 ? '' : 's', ". Pick which ones to import. Generation runs only on the included set."] }), _jsx(AutoFilterBanner, { status: aiFilterStatus, progress: aiFilterProgress, error: aiFilterError }), _jsx(CounterStrip, { counters: counters, totalWidth: totalWidth }), reasonPanelOpen && flatList[cursor] !== undefined && isAiFlagged(flatList[cursor]) && (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: PALETTE.border, paddingX: 1, marginTop: 1, children: [_jsx(Text, { dimColor: true, bold: true, children: `AI rejection reason: ${flatList[cursor].name}` }), _jsx(Text, { children: flatList[cursor].aiReason ?? '<no reason given>' }), _jsx(Text, { dimColor: true, children: "[s] close \u00B7 [Esc] close" })] })), allRejected ? (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: PALETTE.warning, children: "AI excluded all components \u2014 press [a] to override or [q] to quit" }) })) : (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [above > 0 && _jsxs(Text, { dimColor: true, children: ["\u2191 ", above, " above"] }), visible.map((c, vi) => {
|
|
193
|
+
const i = vi + scrollOffset;
|
|
194
|
+
const isCursor = i === cursor;
|
|
195
|
+
const included = isIncluded(c);
|
|
196
|
+
const aiFlagged = isAiFlagged(c);
|
|
197
|
+
const prefix = isCursor ? '›' : ' ';
|
|
198
|
+
const stateGlyph = included ? '[✓]' : '[✗]';
|
|
199
|
+
const stateColor = included ? PALETTE.success : PALETTE.error;
|
|
200
|
+
const aiMarkerNode = aiFlagged ? _jsx(Text, { color: PALETTE.info, children: `${AI_MARKER} ` }) : null;
|
|
201
|
+
const inlineReason = !isCursor && aiFlagged ? ` ${truncateReason(c.aiReason)}` : '';
|
|
202
|
+
const showAiHeader = aiList.length > 0 && i === 0;
|
|
203
|
+
const showComponentsHeader = componentsList.length > 0 && i === aiList.length;
|
|
204
|
+
const header = showAiHeader ? (_jsx(Text, { bold: true, children: `AI recommended exclusions (${aiList.length})` }, `hdr-ai-${i}`)) : showComponentsHeader ? (_jsx(Text, { bold: true, children: `Components (${componentsList.length})` }, `hdr-comp-${i}`)) : null;
|
|
205
|
+
if (isCursor) {
|
|
206
|
+
const wrapReason = aiFlagged && c.aiReason !== null && c.aiReason !== undefined && c.aiReason.length > 0;
|
|
207
|
+
return (_jsxs(React.Fragment, { children: [header, _jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: `${prefix} ` }), aiMarkerNode, _jsx(Text, { color: stateColor, children: stateGlyph }), _jsx(Text, { color: PALETTE.info, children: ` ${c.name}` })] }), wrapReason && _jsx(Text, { dimColor: true, children: `${REASON_WRAP_INDENT}${c.aiReason}` })] }, c.componentId));
|
|
208
|
+
}
|
|
209
|
+
return (_jsxs(React.Fragment, { children: [header, _jsxs(Text, { children: [_jsx(Text, { children: `${prefix} ` }), aiMarkerNode, _jsx(Text, { color: stateColor, children: stateGlyph }), _jsx(Text, { color: stateColor, children: ` ${c.name}` }), inlineReason !== '' && _jsx(Text, { dimColor: true, children: inlineReason })] })] }, c.componentId));
|
|
210
|
+
}), below > 0 && _jsxs(Text, { dimColor: true, children: ["\u2193 ", below, " below"] })] })), _jsxs(Box, { gap: 3, marginTop: 1, children: [includedCount > 0 ? (_jsxs(Text, { children: [_jsx(Text, { color: PALETTE.success, children: includedCount }), _jsxs(Text, { dimColor: true, children: ["/", total, " included"] })] })) : (_jsx(Text, { color: PALETTE.warning, children: "none included" })), _jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "[j/k]" }), " ", _jsx(Text, { dimColor: true, children: "move" })] }), _jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "[a/space]" }), " ", _jsx(Text, { dimColor: true, children: "toggle" })] }), _jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "[A]" }), " ", _jsx(Text, { dimColor: true, children: "toggle all" })] }), _jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "[f]" }), " ", _jsx(Text, { dimColor: true, children: "continue" })] }), _jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "[q]" }), " ", _jsx(Text, { dimColor: true, children: "quit" })] }), hasAnyAi && (_jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "[s]" }), " ", _jsx(Text, { dimColor: true, children: "AI reason" })] })), hasAnyAi && (_jsxs(Text, { children: [_jsx(Text, { color: PALETTE.info, children: "*" }), " ", _jsx(Text, { dimColor: true, children: "originally excluded by AI" })] }))] })] }));
|
|
211
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect, useRef } from 'react';
|
|
3
|
+
import { PALETTE } from '../../../analyze/select/tui/theme.js';
|
|
3
4
|
import { Box, Text } from 'ink';
|
|
4
5
|
import { useImmediateInput } from '../../../analyze/select/tui/hooks/useImmediateInput.js';
|
|
5
6
|
import { DEFAULT_CONFIGURED_HOST, toConfiguredHost } from '../../../host-utils.js';
|
|
@@ -12,21 +13,12 @@ export function CredentialsStep({ summary, error: externalError, initialSpaceId
|
|
|
12
13
|
const [activeField, setActiveField] = useState('spaceId');
|
|
13
14
|
const [inlineError, setInlineError] = useState(null);
|
|
14
15
|
const [cursorVisible, setCursorVisible] = useState(true);
|
|
15
|
-
// Tracks whether the operator has typed any printable character into a
|
|
16
|
-
// form field since mount. While false, the `s` keybind is interpreted as
|
|
17
|
-
// the skip-credentials shortcut. Once the operator has begun typing, `s`
|
|
18
|
-
// is routed into the active field as input (we don't want to swallow a
|
|
19
|
-
// legitimate letter in a space ID / token / host).
|
|
20
16
|
const hasTypedRef = useRef(false);
|
|
21
17
|
useEffect(() => {
|
|
22
18
|
const interval = setInterval(() => setCursorVisible((v) => !v), 500);
|
|
23
19
|
return () => clearInterval(interval);
|
|
24
20
|
}, []);
|
|
25
21
|
useImmediateInput((input, key) => {
|
|
26
|
-
// While we are validating credentials, the screen stays mounted but the
|
|
27
|
-
// form is locked — any input is dropped. The exception is `R` when a
|
|
28
|
-
// prefetch failed and we expose a retry hook (so the operator can recover
|
|
29
|
-
// without backing out of the wizard).
|
|
30
22
|
if (validating) {
|
|
31
23
|
return;
|
|
32
24
|
}
|
|
@@ -47,7 +39,6 @@ export function CredentialsStep({ summary, error: externalError, initialSpaceId
|
|
|
47
39
|
setActiveField('host');
|
|
48
40
|
return;
|
|
49
41
|
}
|
|
50
|
-
// Submit
|
|
51
42
|
if (!spaceId.trim() || !environmentId.trim() || !cmaToken.trim()) {
|
|
52
43
|
setInlineError('All fields are required.');
|
|
53
44
|
return;
|
|
@@ -74,10 +65,6 @@ export function CredentialsStep({ summary, error: externalError, initialSpaceId
|
|
|
74
65
|
onQuit();
|
|
75
66
|
return;
|
|
76
67
|
}
|
|
77
|
-
// Skip-credentials shortcut. Gated against text-entry mode so the letter
|
|
78
|
-
// 's' can still be typed into a form field once the operator has begun
|
|
79
|
-
// editing. The legend hint is always rendered (see below) so operators
|
|
80
|
-
// know the escape hatch exists from the moment the screen mounts.
|
|
81
68
|
if ((input === 's' || input === 'S') && onSkip && !hasTypedRef.current) {
|
|
82
69
|
onSkip();
|
|
83
70
|
return;
|
|
@@ -110,12 +97,12 @@ export function CredentialsStep({ summary, error: externalError, initialSpaceId
|
|
|
110
97
|
const isActive = activeField === field;
|
|
111
98
|
const display = masked ? '•'.repeat(value.length) : value;
|
|
112
99
|
const fallback = field === 'host' ? DEFAULT_CONFIGURED_HOST : _jsx(Text, { dimColor: true, children: "(empty)" });
|
|
113
|
-
return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: isActive ?
|
|
100
|
+
return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: isActive ? PALETTE.info : undefined, children: '?' }), _jsxs(Text, { bold: isActive, children: [label, ":"] }), _jsx(Text, { children: isActive ? display + cursor : display || fallback })] }));
|
|
114
101
|
}
|
|
115
102
|
const displayError = inlineError ?? externalError ?? null;
|
|
116
|
-
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [summary && _jsxs(Text, { color:
|
|
103
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [summary && _jsxs(Text, { color: PALETTE.success, children: ["\u2713 ", summary] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: initialSpaceId && initialCmaToken
|
|
117
104
|
? 'Credentials pre-filled from experiences setup. Press Enter to continue or edit any field to update.'
|
|
118
|
-
: 'Enter your Contentful credentials to continue.' }) }), !(initialSpaceId && initialCmaToken) && (_jsx(Text, { dimColor: true, children: "Tip: run experiences setup to save these to ~/.config/experiences/credentials.json so they pre-fill here automatically." })), _jsxs(Box, { flexDirection: "column", gap: 0, marginTop: 1, children: [renderField('Space ID', spaceId, 'spaceId'), renderField('Environment', environmentId, 'environmentId'), renderField('CMA Token', cmaToken, 'cmaToken', true), renderField('API Host', host, 'host')] }), activeField === 'host' && _jsx(Text, { dimColor: true, children: "Default: api.contentful.com \u00B7 EU spaces: api.eu.contentful.com" }), displayError && _jsxs(Text, { color:
|
|
105
|
+
: 'Enter your Contentful credentials to continue.' }) }), !(initialSpaceId && initialCmaToken) && (_jsx(Text, { dimColor: true, children: "Tip: run experiences setup to save these to ~/.config/experiences/credentials.json so they pre-fill here automatically." })), _jsxs(Box, { flexDirection: "column", gap: 0, marginTop: 1, children: [renderField('Space ID', spaceId, 'spaceId'), renderField('Environment', environmentId, 'environmentId'), renderField('CMA Token', cmaToken, 'cmaToken', true), renderField('API Host', host, 'host')] }), activeField === 'host' && _jsx(Text, { dimColor: true, children: "Default: api.contentful.com \u00B7 EU spaces: api.eu.contentful.com" }), displayError && _jsxs(Text, { color: PALETTE.error, children: ["\u2717 ", displayError] }), validating && (_jsx(Text, { color: PALETTE.info, children: generatePrefetchStatus === 'running'
|
|
119
106
|
? 'Validating credentials & finishing component generation...'
|
|
120
|
-
: 'Validating credentials...' })), !validating && generatePrefetchStatus === 'running' && _jsx(Text, { dimColor: true, children: "Component generation in progress..." }), !validating && generatePrefetchStatus === 'complete' && (_jsx(Text, { color:
|
|
107
|
+
: 'Validating credentials...' })), !validating && generatePrefetchStatus === 'running' && _jsx(Text, { dimColor: true, children: "Component generation in progress..." }), !validating && generatePrefetchStatus === 'complete' && (_jsx(Text, { color: PALETTE.success, children: "Component generation complete." })), !validating && generatePrefetchStatus === 'failed' && (_jsxs(Text, { color: PALETTE.warning, children: ["Component generation failed", generatePrefetchError ? `: ${generatePrefetchError}` : '', ". Will retry after credential validation.", onRetryPrefetch ? ' Press R to retry now.' : ''] })), _jsxs(Box, { gap: 3, marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "[Enter] Next field / Submit" }), _jsx(Text, { dimColor: true, children: "[Tab] Switch field" }), _jsx(Text, { dimColor: true, children: "[q] Quit" })] }), onSkip && (_jsx(Box, { marginTop: 0, children: _jsx(Text, { dimColor: true, children: "[s] Skip \u2014 review locally only (no push, no live preview)" }) }))] }));
|
|
121
108
|
}
|
|
@@ -15,9 +15,7 @@ type DoneStepProps = {
|
|
|
15
15
|
};
|
|
16
16
|
spaceId: string;
|
|
17
17
|
environmentId: string;
|
|
18
|
-
/** Configured API host (e.g. `api.contentful.com`). Used to derive the webapp URL. */
|
|
19
18
|
host?: string;
|
|
20
|
-
/** Task 8 — pre-formatted run teaser; rendered dim below the space link. */
|
|
21
19
|
runTeaser?: string;
|
|
22
20
|
onExit: () => void;
|
|
23
21
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { PALETTE } from '../../../analyze/select/tui/theme.js';
|
|
2
3
|
import { Box, Text } from 'ink';
|
|
3
4
|
import { useImmediateInput } from '../../../analyze/select/tui/hooks/useImmediateInput.js';
|
|
4
5
|
import { buildPostPushUrl } from '../../../lib/contentful-urls.js';
|
|
@@ -17,7 +18,7 @@ export function DoneStep({ componentTypes, designTokens, summary, spaceId, envir
|
|
|
17
18
|
designTokens.removed;
|
|
18
19
|
const success = totalFailed === 0;
|
|
19
20
|
function EntityRows({ entity, label }) {
|
|
20
|
-
return (_jsxs(_Fragment, { children: [entity.created > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color:
|
|
21
|
+
return (_jsxs(_Fragment, { children: [entity.created > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: PALETTE.success, children: "\u2713" }), _jsxs(Text, { children: [entity.created, " ", label, entity.created !== 1 ? 's' : '', " created"] })] })), entity.updated > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: PALETTE.success, children: "\u2713" }), _jsxs(Text, { children: [entity.updated, " ", label, entity.updated !== 1 ? 's' : '', " updated"] })] })), entity.removed > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: PALETTE.success, children: "\u2713" }), _jsxs(Text, { children: [entity.removed, " ", label, entity.removed !== 1 ? 's' : '', " removed"] })] })), entity.failed > 0 && (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: PALETTE.error, children: "\u2717" }), _jsxs(Text, { color: PALETTE.error, children: [entity.failed, " ", label, entity.failed !== 1 ? 's' : '', " failed \u2014 check logs above"] })] }))] }));
|
|
21
22
|
}
|
|
22
|
-
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [success ? (_jsx(Text, { bold: true, color:
|
|
23
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [success ? (_jsx(Text, { bold: true, color: PALETTE.success, children: "Done!" })) : (_jsx(Text, { bold: true, color: PALETTE.warning, children: "\u26A0 Finished with errors" })), totalPushed === 0 && totalFailed === 0 && !summary ? (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Nothing was pushed \u2014 everything was already up to date." }) })) : (_jsxs(Box, { flexDirection: "column", gap: 0, marginTop: 1, children: [_jsx(EntityRows, { entity: componentTypes, label: "Component Type" }), _jsx(EntityRows, { entity: designTokens, label: "Design Token" }), summary && (_jsxs(Box, { gap: 1, marginTop: 1, children: [_jsxs(Text, { dimColor: true, children: ["Server: ", summary.succeeded, "/", summary.total, " succeeded"] }), summary.failed > 0 && _jsxs(Text, { color: PALETTE.error, children: [", ", summary.failed, " failed"] })] }))] })), _jsxs(Box, { gap: 1, marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Space:" }), _jsx(Text, { children: spaceId }), _jsx(Text, { dimColor: true, children: "/" }), _jsx(Text, { dimColor: true, children: "Environment:" }), _jsx(Text, { children: environmentId })] }), success && totalPushed > 0 && (_jsxs(Box, { flexDirection: "column", gap: 1, marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Your design system is now in Contentful ExO." }), _jsxs(Box, { flexDirection: "column", gap: 0, children: [_jsx(Text, { dimColor: true, children: "View it here:" }), _jsx(Text, { color: PALETTE.info, children: buildPostPushUrl({ host: host ?? 'api.contentful.com', spaceId, environmentId }) })] })] })), runTeaser && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: runTeaser }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "[Enter / q] Exit" }) })] }));
|
|
23
24
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { PALETTE } from '../../../analyze/select/tui/theme.js';
|
|
2
3
|
import { Box, Text } from 'ink';
|
|
3
4
|
import { useImmediateInput } from '../../../analyze/select/tui/hooks/useImmediateInput.js';
|
|
4
5
|
export function ErrorStep({ stepName, message, onExit, onRetryCredentials }) {
|
|
@@ -11,5 +12,5 @@ export function ErrorStep({ stepName, message, onExit, onRetryCredentials }) {
|
|
|
11
12
|
onExit();
|
|
12
13
|
}
|
|
13
14
|
});
|
|
14
|
-
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [_jsxs(Text, { bold: true, color:
|
|
15
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [_jsxs(Text, { bold: true, color: PALETTE.error, children: ["\u2717 ", stepName, " failed"] }), _jsx(Text, { color: PALETTE.error, children: message }), _jsxs(Box, { gap: 3, marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "[Enter / q] Exit" }), onRetryCredentials && _jsx(Text, { dimColor: true, children: "[r] Re-enter credentials" })] })] }));
|
|
15
16
|
}
|
|
@@ -1,42 +1,36 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { CDFComponentEntry } from '@contentful/experience-design-system-types';
|
|
2
|
+
import type { BreakingChange, CDFComponentEntry, ComponentTypeSummary, DownstreamImpact, ServerPreviewResponse } from '@contentful/experience-design-system-types';
|
|
3
3
|
type GenerateReviewStepProps = {
|
|
4
4
|
extractSessionId: string;
|
|
5
5
|
onFinalize: (accepted: number, rejected: number, unresolved: number) => void;
|
|
6
6
|
onQuit: () => void;
|
|
7
|
-
/**
|
|
8
|
-
* Feature 2 (live preview after every save). When `true` (default), the
|
|
9
|
-
* wizard re-runs `previewImport` after each successful FieldEditor Ctrl+S
|
|
10
|
-
* (debounced 500ms) and refreshes the sidebar's previewAnnotation badges.
|
|
11
|
-
* Operator opts out via `experiences import --no-live-preview`.
|
|
12
|
-
*/
|
|
13
7
|
livePreview?: boolean;
|
|
14
8
|
spaceId?: string;
|
|
15
9
|
environmentId?: string;
|
|
16
10
|
cmaToken?: string;
|
|
17
11
|
host?: string;
|
|
18
12
|
tokensPath?: string;
|
|
19
|
-
/**
|
|
20
|
-
* INTEG-4411 refined: initial value for the inline `finalizeError` banner.
|
|
21
|
-
* The wizard sets this when it routes back to `final-review` after the
|
|
22
|
-
* preview API returned an empty diff (pure no-op push). Cleared on the
|
|
23
|
-
* next `a` / `A` keystroke.
|
|
24
|
-
*/
|
|
25
13
|
initialFinalizeError?: string | null;
|
|
26
14
|
};
|
|
27
|
-
/**
|
|
28
|
-
* Sort components for the final-review sidebar so the underlying data array
|
|
29
|
-
* matches the visual order. Empty components (zero classified $properties)
|
|
30
|
-
* surface at the top via the warning-tier path in Sidebar.tsx; we mirror that
|
|
31
|
-
* here so `selectedIdx` indexes into the same order the user sees. Without
|
|
32
|
-
* this, j/k navigation lands on different rows than the visually-selected
|
|
33
|
-
* one (INTEG-4259).
|
|
34
|
-
*
|
|
35
|
-
* Within each tier (empty / non-empty) we tie-break alphabetically by `key`.
|
|
36
|
-
*/
|
|
37
15
|
export declare function sortComponentsForSidebar<T extends {
|
|
38
16
|
key: string;
|
|
39
17
|
entry: CDFComponentEntry;
|
|
40
|
-
}>(components: T[]): T[];
|
|
18
|
+
}>(components: T[], cycleParticipants?: Set<string>): T[];
|
|
19
|
+
export { computeCycleAutoRejectTargets } from '../../cycle-auto-reject.js';
|
|
20
|
+
export interface BreakingComponent {
|
|
21
|
+
componentName: string;
|
|
22
|
+
changes: BreakingChange[];
|
|
23
|
+
impact?: DownstreamImpact;
|
|
24
|
+
current?: ComponentTypeSummary;
|
|
25
|
+
}
|
|
26
|
+
export interface BreakingRow {
|
|
27
|
+
label: string;
|
|
28
|
+
componentName: string;
|
|
29
|
+
focusTarget?: {
|
|
30
|
+
kind: 'prop' | 'slot';
|
|
31
|
+
name: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare function buildBreakingRows(breakingChanges: BreakingComponent[]): BreakingRow[];
|
|
35
|
+
export declare function deriveBreakingChanges(response: ServerPreviewResponse): BreakingComponent[];
|
|
41
36
|
export declare function GenerateReviewStep({ extractSessionId, onFinalize, onQuit, livePreview, spaceId, environmentId, cmaToken, host, tokensPath, initialFinalizeError, }: GenerateReviewStepProps): React.ReactElement;
|
|
42
|
-
export {};
|