@contentful/experience-design-system-cli 2.26.1-dev-build-a852362.0 → 2.26.1-dev-build-f03f014.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.
Files changed (204) hide show
  1. package/dist/package.json +14 -10
  2. package/dist/src/index.js +34937 -9
  3. package/dist/src/lib/cli-path.d.ts +4 -0
  4. package/dist/src/runs/export-helpers.d.ts +1 -12
  5. package/dist/src/runs/push-helpers.d.ts +1 -6
  6. package/package.json +12 -7
  7. package/skills/generate-components.md +427 -0
  8. package/skills/generate-tokens.md +194 -0
  9. package/skills/select-components.md +224 -0
  10. package/dist/src/analytics/apply.js +0 -30
  11. package/dist/src/analytics/client.js +0 -81
  12. package/dist/src/analytics/constants.js +0 -4
  13. package/dist/src/analytics/env.js +0 -14
  14. package/dist/src/analytics/exit.js +0 -24
  15. package/dist/src/analytics/index.js +0 -9
  16. package/dist/src/analytics/normalize.js +0 -18
  17. package/dist/src/analytics/os.js +0 -13
  18. package/dist/src/analytics/session.js +0 -15
  19. package/dist/src/analytics/tracker.js +0 -126
  20. package/dist/src/analytics/types.js +0 -1
  21. package/dist/src/analyze/build-analyze-view-rows.js +0 -63
  22. package/dist/src/analyze/command.js +0 -599
  23. package/dist/src/analyze/composite-closure.js +0 -0
  24. package/dist/src/analyze/composition/agent-parser/author-prompt.js +0 -22
  25. package/dist/src/analyze/composition/agent-parser/extract-parser.js +0 -44
  26. package/dist/src/analyze/composition/agent-parser/load-prompt.js +0 -31
  27. package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +0 -88
  28. package/dist/src/analyze/composition/agent-parser/sandbox.js +0 -187
  29. package/dist/src/analyze/composition/apply-mapping.js +0 -67
  30. package/dist/src/analyze/composition/candidate-critic-agent.js +0 -39
  31. package/dist/src/analyze/composition/candidate-critic.js +0 -63
  32. package/dist/src/analyze/composition/candidate-files.js +0 -131
  33. package/dist/src/analyze/composition/composition-cache-key.js +0 -19
  34. package/dist/src/analyze/composition/interchange-schema.js +0 -61
  35. package/dist/src/analyze/composition/manifest-doc-evidence.js +0 -136
  36. package/dist/src/analyze/composition/merge-edges.js +0 -70
  37. package/dist/src/analyze/composition/parse-map-edges.js +0 -55
  38. package/dist/src/analyze/composition/resolve-mapping-cli.js +0 -29
  39. package/dist/src/analyze/composition/resolve-mapping.js +0 -111
  40. package/dist/src/analyze/cycle-detection.js +0 -234
  41. package/dist/src/analyze/cycle-view.js +0 -28
  42. package/dist/src/analyze/fuzzy-search.js +0 -55
  43. package/dist/src/analyze/issue-inheritance.js +0 -108
  44. package/dist/src/analyze/lineage.js +0 -0
  45. package/dist/src/analyze/scope-gate-cascade.js +0 -170
  46. package/dist/src/analyze/search-neighborhood.js +0 -56
  47. package/dist/src/analyze/select/command.js +0 -484
  48. package/dist/src/analyze/select/index.js +0 -5
  49. package/dist/src/analyze/select/parser.js +0 -53
  50. package/dist/src/analyze/select/persistence.js +0 -80
  51. package/dist/src/analyze/select/preview-annotations.js +0 -62
  52. package/dist/src/analyze/select/stdout.js +0 -3
  53. package/dist/src/analyze/select/tui/App.js +0 -483
  54. package/dist/src/analyze/select/tui/components/ComponentDetail.js +0 -48
  55. package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +0 -125
  56. package/dist/src/analyze/select/tui/components/FieldEditor.js +0 -1131
  57. package/dist/src/analyze/select/tui/components/FinalizeDialog.js +0 -36
  58. package/dist/src/analyze/select/tui/components/GotoBanner.js +0 -30
  59. package/dist/src/analyze/select/tui/components/GroupedSidebar.js +0 -517
  60. package/dist/src/analyze/select/tui/components/HelpOverlay.js +0 -17
  61. package/dist/src/analyze/select/tui/components/JsonEditor.js +0 -131
  62. package/dist/src/analyze/select/tui/components/JsonPanel.js +0 -66
  63. package/dist/src/analyze/select/tui/components/LineagePanel.js +0 -22
  64. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +0 -29
  65. package/dist/src/analyze/select/tui/components/QuitDialog.js +0 -14
  66. package/dist/src/analyze/select/tui/components/RationalePanel.js +0 -80
  67. package/dist/src/analyze/select/tui/components/Sidebar.js +0 -92
  68. package/dist/src/analyze/select/tui/components/SourcePanel.js +0 -52
  69. package/dist/src/analyze/select/tui/components/StatusBar.js +0 -7
  70. package/dist/src/analyze/select/tui/components/TopBar.js +0 -10
  71. package/dist/src/analyze/select/tui/components/removed-components-text.js +0 -11
  72. package/dist/src/analyze/select/tui/hooks/scroll-offset.js +0 -26
  73. package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +0 -66
  74. package/dist/src/analyze/select/tui/hooks/useKeymap.js +0 -67
  75. package/dist/src/analyze/select/tui/hooks/useSession.js +0 -52
  76. package/dist/src/analyze/select/tui/hooks/useUndo.js +0 -26
  77. package/dist/src/analyze/select/tui/theme.js +0 -28
  78. package/dist/src/analyze/select/types.js +0 -39
  79. package/dist/src/analyze/select-agent/command.js +0 -558
  80. package/dist/src/analyze/select-agent/context-builder.js +0 -197
  81. package/dist/src/analyze/select-agent/show-rationale.js +0 -92
  82. package/dist/src/analyze/selection-cascade.js +0 -19
  83. package/dist/src/analyze/slot-graph.js +0 -17
  84. package/dist/src/analyze/tui/AnalyzeView.js +0 -64
  85. package/dist/src/apply/api-client.js +0 -440
  86. package/dist/src/apply/command.js +0 -845
  87. package/dist/src/apply/manifest.js +0 -1
  88. package/dist/src/apply/preview-utils.js +0 -26
  89. package/dist/src/apply/tui/SelectView.js +0 -34
  90. package/dist/src/apply/tui/ServerApplyView.js +0 -49
  91. package/dist/src/apply/tui/ServerPreviewView.js +0 -23
  92. package/dist/src/credentials-store.js +0 -74
  93. package/dist/src/generate/command.js +0 -597
  94. package/dist/src/generate/edit/command.js +0 -127
  95. package/dist/src/generate/tui/GenerateView.js +0 -10
  96. package/dist/src/host-utils.js +0 -26
  97. package/dist/src/import/agent-model-resolve.js +0 -35
  98. package/dist/src/import/auto-filter-resolve.js +0 -16
  99. package/dist/src/import/command.js +0 -380
  100. package/dist/src/import/cycle-auto-reject.js +0 -14
  101. package/dist/src/import/orchestrator.js +0 -603
  102. package/dist/src/import/path-utils.js +0 -30
  103. package/dist/src/import/picker-dispatch.js +0 -44
  104. package/dist/src/import/print-prompt.js +0 -31
  105. package/dist/src/import/strip-allowed-components.js +0 -22
  106. package/dist/src/import/tui/CustomPromptBanner.js +0 -8
  107. package/dist/src/import/tui/WizardApp.js +0 -1670
  108. package/dist/src/import/tui/ai-flag.js +0 -6
  109. package/dist/src/import/tui/auto-filter-error.js +0 -29
  110. package/dist/src/import/tui/autocomplete.js +0 -32
  111. package/dist/src/import/tui/components/AutoFilterBanner.js +0 -19
  112. package/dist/src/import/tui/components/CounterStrip.js +0 -12
  113. package/dist/src/import/tui/components/LegendEntry.js +0 -6
  114. package/dist/src/import/tui/cycle-panel-scroll.js +0 -33
  115. package/dist/src/import/tui/final-review-host.js +0 -25
  116. package/dist/src/import/tui/group-collapse.js +0 -11
  117. package/dist/src/import/tui/history.js +0 -53
  118. package/dist/src/import/tui/hooks/useLineage.js +0 -50
  119. package/dist/src/import/tui/hooks/useOverlayPanel.js +0 -27
  120. package/dist/src/import/tui/lineage-layout.js +0 -82
  121. package/dist/src/import/tui/merge-ai-decisions.js +0 -22
  122. package/dist/src/import/tui/push-decision-gate-helpers.js +0 -8
  123. package/dist/src/import/tui/push-progress.js +0 -1
  124. package/dist/src/import/tui/run-print-files-helpers.js +0 -8
  125. package/dist/src/import/tui/run-teaser.js +0 -9
  126. package/dist/src/import/tui/runLivePreview.js +0 -82
  127. package/dist/src/import/tui/runScopeGate.js +0 -28
  128. package/dist/src/import/tui/scope-gate-columns.js +0 -94
  129. package/dist/src/import/tui/scope-gate-host.js +0 -28
  130. package/dist/src/import/tui/sidebar-width.js +0 -3
  131. package/dist/src/import/tui/spawn-generate.js +0 -53
  132. package/dist/src/import/tui/step-filters.js +0 -42
  133. package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +0 -726
  134. package/dist/src/import/tui/steps/AtomicScopeGateStep.js +0 -210
  135. package/dist/src/import/tui/steps/CredentialsStep.js +0 -108
  136. package/dist/src/import/tui/steps/DoneStep.js +0 -24
  137. package/dist/src/import/tui/steps/ErrorStep.js +0 -16
  138. package/dist/src/import/tui/steps/GateStep.js +0 -22
  139. package/dist/src/import/tui/steps/GenerateReviewStep.js +0 -1618
  140. package/dist/src/import/tui/steps/PathValidationStep.js +0 -152
  141. package/dist/src/import/tui/steps/PreviewStep.js +0 -37
  142. package/dist/src/import/tui/steps/PreviewValidationErrorStep.js +0 -23
  143. package/dist/src/import/tui/steps/PushDecisionGateStep.js +0 -73
  144. package/dist/src/import/tui/steps/PushingStep.js +0 -24
  145. package/dist/src/import/tui/steps/RunningStep.js +0 -21
  146. package/dist/src/import/tui/steps/ScopeGateStep.js +0 -907
  147. package/dist/src/import/tui/steps/TokenInputStep.js +0 -88
  148. package/dist/src/import/tui/steps/WelcomeStep.js +0 -34
  149. package/dist/src/import/tui/steps/WizardPreviewStep.js +0 -169
  150. package/dist/src/import/tui/steps/auto-reject-decision.js +0 -9
  151. package/dist/src/import/tui/steps/breaking-change-format.js +0 -24
  152. package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
  153. package/dist/src/import/tui/steps/preview-diff.js +0 -175
  154. package/dist/src/import/tui/useFinalizePreview.js +0 -0
  155. package/dist/src/import/tui/useLivePreview.js +0 -122
  156. package/dist/src/import/tui/wizard-422-helpers.js +0 -60
  157. package/dist/src/import/tui/wizard-generate-progress.js +0 -25
  158. package/dist/src/import/tui/wizard-save-flow.js +0 -20
  159. package/dist/src/import/tui/wizard-state-transitions.js +0 -32
  160. package/dist/src/lib/agent-model-options.js +0 -15
  161. package/dist/src/lib/command-options.js +0 -30
  162. package/dist/src/lib/composition-mode.js +0 -39
  163. package/dist/src/lib/contentful-urls.js +0 -27
  164. package/dist/src/lib/debug-logger.js +0 -229
  165. package/dist/src/lib/debug-preamble.js +0 -33
  166. package/dist/src/lib/error-parser.js +0 -269
  167. package/dist/src/lib/prompt-overrides.js +0 -69
  168. package/dist/src/lib/terminal-capabilities.js +0 -51
  169. package/dist/src/lib/user-agent.js +0 -29
  170. package/dist/src/output/format.js +0 -110
  171. package/dist/src/print/command.js +0 -221
  172. package/dist/src/print/validate/tui/ValidateView.js +0 -37
  173. package/dist/src/print/validate/validators/cdf-validator.js +0 -104
  174. package/dist/src/print/validate/validators/dtcg-validator.js +0 -110
  175. package/dist/src/print/validate/validators/format-errors.js +0 -18
  176. package/dist/src/program.js +0 -105
  177. package/dist/src/runs/export-helpers.js +0 -59
  178. package/dist/src/runs/fingerprint.js +0 -75
  179. package/dist/src/runs/ls-command.js +0 -137
  180. package/dist/src/runs/modify-launcher.js +0 -42
  181. package/dist/src/runs/path-prompt.js +0 -72
  182. package/dist/src/runs/push-creds-prompt.js +0 -39
  183. package/dist/src/runs/push-helpers.js +0 -72
  184. package/dist/src/runs/push-launcher.js +0 -77
  185. package/dist/src/runs/replay-helpers.js +0 -164
  186. package/dist/src/runs/resolve-run-target.js +0 -45
  187. package/dist/src/runs/run-picker-mount.js +0 -72
  188. package/dist/src/runs/run-picker.js +0 -129
  189. package/dist/src/runs/save-conflict.js +0 -56
  190. package/dist/src/runs/save-path-resolver.js +0 -75
  191. package/dist/src/runs/staleness.js +0 -140
  192. package/dist/src/runs/store.js +0 -136
  193. package/dist/src/session/cache-keys.js +0 -44
  194. package/dist/src/session/command.js +0 -261
  195. package/dist/src/session/db.js +0 -1538
  196. package/dist/src/session/migration.js +0 -117
  197. package/dist/src/session/session-id.js +0 -212
  198. package/dist/src/session/stats.js +0 -89
  199. package/dist/src/setup/analytics-prompt.js +0 -24
  200. package/dist/src/setup/auto-filter-prompt.js +0 -24
  201. package/dist/src/setup/command.js +0 -966
  202. package/dist/src/setup/composition-mode-prompt.js +0 -37
  203. package/dist/src/setup/debug-mode-prompt.js +0 -22
  204. package/dist/src/types.js +0 -1
@@ -1,36 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { PALETTE } from '../theme.js';
3
- import { Box, Text } from 'ink';
4
- import { useImmediateInput } from '../hooks/useImmediateInput.js';
5
- import { removedComponentsHeader, removedComponentLine } from './removed-components-text.js';
6
- /** Max removed-component lines shown at once; the rest scroll with j/k.
7
- * Exported so the parent's scroll-offset clamping stays in sync. */
8
- export const FINALIZE_REMOVED_WINDOW = 6;
9
- export function FinalizeDialog({ accepted, rejected, needsReview, onConfirm, onCancel, removed = [],
10
- // Default 'done' so callers that pass a ready `removed` list (e.g. the atomic
11
- // review step) render it immediately without threading a status.
12
- previewStatus = 'done', removedScrollOffset = 0, }) {
13
- useImmediateInput((input, key) => {
14
- // j/k scroll the removed list; the parent owns the offset (handled there).
15
- if (input === 'j' || input === 'k' || key.upArrow || key.downArrow)
16
- return;
17
- if (input === 'y' || key.return) {
18
- onConfirm();
19
- }
20
- else if (input === 'n' || key.escape) {
21
- onCancel();
22
- }
23
- });
24
- const allResolved = needsReview === 0;
25
- const noneAccepted = accepted === 0;
26
- const maxOffset = Math.max(0, removed.length - FINALIZE_REMOVED_WINDOW);
27
- const offset = Math.min(Math.max(0, removedScrollOffset), maxOffset);
28
- const windowed = removed.slice(offset, offset + FINALIZE_REMOVED_WINDOW);
29
- const hasMoreBelow = offset + FINALIZE_REMOVED_WINDOW < removed.length;
30
- const hasMoreAbove = offset > 0;
31
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", padding: 1, width: 58, children: [_jsx(Text, { bold: true, children: '─'.repeat(17) + ' Finalize ' + '─'.repeat(17) }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [_jsxs(Text, { color: PALETTE.success, children: [accepted, " accepted"] }), _jsx(Text, { children: " \u00B7 " }), _jsxs(Text, { color: PALETTE.error, children: [rejected, " rejected"] }), _jsx(Text, { children: " \u00B7 " }), _jsxs(Text, { dimColor: true, children: [needsReview, " unresolved"] })] }), _jsx(Text, { children: " " }), noneAccepted && (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, color: PALETTE.warning, children: '⚠ No components are accepted — nothing will be pushed.' }), _jsx(Text, { color: PALETTE.warning, children: ' Accept at least one component ([a] a row, [A] accept all) to push.' }), _jsx(Text, { children: " " })] })), !allResolved && (_jsxs(_Fragment, { children: [_jsx(Text, { color: PALETTE.warning, children: '⚠ ' + needsReview + ' unresolved component' + (needsReview === 1 ? '' : 's') + ' will not be pushed.' }), _jsx(Text, { color: PALETTE.warning, children: ' Only explicitly accepted components ship.' }), _jsx(Text, { children: " " })] })), previewStatus === 'running' && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: "Previewing deletions against the target space\u2026" }), _jsx(Text, { children: " " })] })), previewStatus === 'error' && (_jsxs(_Fragment, { children: [_jsx(Text, { color: PALETTE.warning, children: '⚠ Could not preview deletions (the push will still proceed).' }), _jsx(Text, { children: " " })] })), previewStatus === 'done' && removed.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, color: PALETTE.error, children: removedComponentsHeader(removed.length, false) }), hasMoreAbove && _jsx(Text, { dimColor: true, children: ' ↑ more above' }), windowed.map((rc) => (_jsx(Text, { color: PALETTE.error, children: removedComponentLine(rc) }, rc.id))), hasMoreBelow && _jsx(Text, { dimColor: true, children: ' ↓ more below' }), removed.length > FINALIZE_REMOVED_WINDOW && _jsx(Text, { dimColor: true, children: ' [j/k] scroll deletions' }), _jsx(Text, { children: " " })] })), _jsx(Text, { children: noneAccepted
32
- ? 'Confirm exit with nothing accepted?'
33
- : allResolved
34
- ? 'Save decisions and exit? All components resolved.'
35
- : 'Save decisions and exit?' }), _jsx(Text, { children: " " }), _jsx(Text, { children: ' [y / Enter] Confirm [n / Esc] Cancel' })] }));
36
- }
@@ -1,30 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { PALETTE } from '../theme.js';
3
- import { Box, Text } from 'ink';
4
- const DEFAULT_MAX_ROWS = 15;
5
- function windowStart(rowCount, highlightIndex, maxRows) {
6
- if (rowCount <= maxRows)
7
- return 0;
8
- const maxStart = rowCount - maxRows;
9
- let start = highlightIndex - Math.floor(maxRows / 2);
10
- if (start < 0)
11
- start = 0;
12
- if (start > maxStart)
13
- start = maxStart;
14
- return start;
15
- }
16
- function defaultRenderRow(row, index, isCursor) {
17
- return (_jsxs(Text, { children: [isCursor ? (_jsx(Text, { color: PALETTE.info, bold: true, children: '▶' })) : (_jsx(Text, { children: " " })), _jsx(Text, { inverse: isCursor, children: ' ' + row.label })] }, index));
18
- }
19
- export function GotoBanner({ title, rows, cursor, cursorRowIndex, maxRows = DEFAULT_MAX_ROWS, width, footerHint, renderRow = defaultRenderRow, }) {
20
- const highlightIndex = cursorRowIndex ?? cursor;
21
- const start = windowStart(rows.length, highlightIndex, maxRows);
22
- const end = Math.min(rows.length, start + maxRows);
23
- const visible = rows.slice(start, end);
24
- const moreAbove = start;
25
- const moreBelow = rows.length - end;
26
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: PALETTE.info, paddingX: 1, marginTop: width === undefined ? 1 : 0, width: width, flexShrink: 0, children: [_jsx(Text, { bold: true, children: title }), moreAbove > 0 && _jsx(Text, { dimColor: true, children: ` ▲ ${moreAbove} more` }), visible.map((row, vi) => {
27
- const i = start + vi;
28
- return renderRow(row, i, i === highlightIndex);
29
- }), moreBelow > 0 && _jsx(Text, { dimColor: true, children: ` ▼ ${moreBelow} more` }), footerHint !== undefined && _jsx(Text, { dimColor: true, children: footerHint })] }));
30
- }
@@ -1,517 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { computeAllClosures, findSharedDeps, } from '../../../composite-closure.js';
4
- import { previewBadge } from './Sidebar.js';
5
- import { PALETTE } from '../theme.js';
6
- const GLYPH_EXPAND_COLLAPSED = '▸';
7
- const GLYPH_EXPAND_EXPANDED = '▾';
8
- const GLYPH_TREE_MID = '├─';
9
- const GLYPH_TREE_LAST = '└─';
10
- const GLYPH_WARN = '⚠';
11
- const GLYPH_ERROR = '✗';
12
- function isEmpty(entry) {
13
- return Object.keys(entry.$properties ?? {}).length === 0 && Object.keys(entry.$slots ?? {}).length === 0;
14
- }
15
- function aggregateGlyphFor(closure, statusByName) {
16
- let worst = 'ok';
17
- for (const node of closure.nodes) {
18
- const s = statusByName.get(node.name);
19
- if (!s)
20
- continue;
21
- if (s === 'error') {
22
- worst = 'error';
23
- break;
24
- }
25
- if (s === 'warning')
26
- worst = 'warning';
27
- }
28
- if (worst === 'error')
29
- return GLYPH_ERROR;
30
- if (worst === 'warning')
31
- return GLYPH_WARN;
32
- return null;
33
- }
34
- export function buildVisibleRows(props) {
35
- const { items, cycleParticipants, alwaysExpanded, showFlatTier, viewMode, graph, filterVisibleKeys } = props;
36
- if (viewMode === 'flat') {
37
- const rows = [];
38
- if (items.length === 0)
39
- return rows;
40
- const itemByKey = new Map(items.map((it, idx) => [it.key, { it, idx }]));
41
- const cycleKeys = [];
42
- const otherKeys = [];
43
- for (const it of items) {
44
- if (cycleParticipants.has(it.key))
45
- cycleKeys.push(it.key);
46
- else
47
- otherKeys.push(it.key);
48
- }
49
- cycleKeys.sort();
50
- otherKeys.sort();
51
- const otherKeySet = new Set(otherKeys);
52
- const flatGraph = graph.filter((n) => otherKeySet.has(n.name));
53
- const closures = computeAllClosures(flatGraph);
54
- const depCountByKey = new Map();
55
- for (const [name, closure] of closures) {
56
- if (closure.nodes.length > 1)
57
- depCountByKey.set(name, closure.nodes.length - 1);
58
- }
59
- for (const key of cycleKeys) {
60
- const rec = itemByKey.get(key);
61
- if (!rec)
62
- continue;
63
- rows.push({
64
- kind: 'cycle',
65
- key: `cycle:${key}`,
66
- label: `${GLYPH_WARN} ${key} (cycle)`,
67
- indent: 0,
68
- itemIdx: rec.idx,
69
- });
70
- }
71
- for (const key of otherKeys) {
72
- const rec = itemByKey.get(key);
73
- if (!rec)
74
- continue;
75
- const dep = depCountByKey.get(key);
76
- const suffix = dep !== undefined ? ` (${dep} dep${dep === 1 ? '' : 's'})` : '';
77
- rows.push({
78
- kind: 'flat',
79
- key: `flat:${key}`,
80
- label: `${key}${suffix}`,
81
- indent: 0,
82
- itemIdx: rec.idx,
83
- });
84
- }
85
- return rows;
86
- }
87
- const rows = [];
88
- if (items.length === 0)
89
- return rows;
90
- const itemByKey = new Map(items.map((it, idx) => [it.key, { it, idx }]));
91
- const statusByName = new Map(items.map((it) => [it.key, it.status]));
92
- const cycleKeys = [];
93
- const emptyKeys = [];
94
- const otherKeys = [];
95
- for (const it of items) {
96
- if (cycleParticipants.has(it.key))
97
- cycleKeys.push(it.key);
98
- else if (isEmpty(it.entry))
99
- emptyKeys.push(it.key);
100
- else
101
- otherKeys.push(it.key);
102
- }
103
- cycleKeys.sort();
104
- emptyKeys.sort();
105
- const seenCycleTierChildOccurrence = new Set();
106
- const computeCycleMemberSubtree = (root) => {
107
- const out = [];
108
- const visited = new Set([root]);
109
- const queue = [{ name: root, depth: 0 }];
110
- while (queue.length > 0) {
111
- const cur = queue.shift();
112
- const parentItem = itemByKey.get(cur.name)?.it;
113
- if (!parentItem)
114
- continue;
115
- const slotTargets = [];
116
- const seenTarget = new Set();
117
- for (const slot of Object.values(parentItem.entry.$slots ?? {})) {
118
- const allowed = Array.isArray(slot?.$allowedComponents)
119
- ? slot.$allowedComponents.filter((v) => typeof v === 'string')
120
- : [];
121
- for (const target of allowed) {
122
- if (!itemByKey.has(target))
123
- continue;
124
- if (seenTarget.has(target))
125
- continue;
126
- seenTarget.add(target);
127
- slotTargets.push(target);
128
- }
129
- }
130
- slotTargets.sort();
131
- for (const target of slotTargets) {
132
- if (visited.has(target))
133
- continue;
134
- visited.add(target);
135
- const isCycleMember = cycleParticipants.has(target);
136
- out.push({ name: target, depth: cur.depth + 1, isCycleMember });
137
- queue.push({ name: target, depth: cur.depth + 1 });
138
- }
139
- }
140
- return out;
141
- };
142
- for (const key of cycleKeys) {
143
- const rec = itemByKey.get(key);
144
- if (!rec)
145
- continue;
146
- const expanded = alwaysExpanded ? true : props.expandedGroups.has(key);
147
- const glyphExpand = expanded ? GLYPH_EXPAND_EXPANDED : GLYPH_EXPAND_COLLAPSED;
148
- rows.push({
149
- kind: 'cycle',
150
- key: `cycle:${key}`,
151
- label: `${glyphExpand} ${GLYPH_WARN} ${key} (cycle)`,
152
- indent: 0,
153
- itemIdx: rec.idx,
154
- rootName: key,
155
- });
156
- if (!expanded)
157
- continue;
158
- const subtree = computeCycleMemberSubtree(key);
159
- subtree.forEach((child, i) => {
160
- const isLast = i === subtree.length - 1;
161
- const glyph = isLast ? GLYPH_TREE_LAST : GLYPH_TREE_MID;
162
- let sharedSuffix = false;
163
- if (seenCycleTierChildOccurrence.has(child.name))
164
- sharedSuffix = true;
165
- else
166
- seenCycleTierChildOccurrence.add(child.name);
167
- const childRec = itemByKey.get(child.name);
168
- const indent = ' '.repeat(Math.max(0, child.depth - 1));
169
- const labelName = child.isCycleMember ? `${GLYPH_WARN} ${child.name} (cycle)` : child.name;
170
- rows.push({
171
- kind: 'group-child',
172
- key: `cycle-child:${key}:${child.name}`,
173
- label: `${indent}${glyph} ${labelName}${sharedSuffix ? ' (shared)' : ''}`,
174
- indent: child.depth,
175
- sharedSuffix,
176
- cycleChild: child.isCycleMember || undefined,
177
- itemIdx: childRec?.idx ?? -1,
178
- rootName: key,
179
- });
180
- });
181
- }
182
- for (const key of emptyKeys) {
183
- const rec = itemByKey.get(key);
184
- if (!rec)
185
- continue;
186
- rows.push({
187
- kind: 'empty',
188
- key: `empty:${key}`,
189
- label: `${key} (empty)`,
190
- indent: 0,
191
- itemIdx: rec.idx,
192
- });
193
- }
194
- const otherKeySet = new Set(otherKeys);
195
- const subgraph = graph.filter((n) => otherKeySet.has(n.name));
196
- const closures = computeAllClosures(subgraph);
197
- const sharedDeps = findSharedDeps(closures);
198
- const hasCycleDepDirect = (name) => {
199
- const it = itemByKey.get(name)?.it;
200
- if (!it)
201
- return false;
202
- for (const slot of Object.values(it.entry.$slots ?? {})) {
203
- const allowed = Array.isArray(slot?.$allowedComponents)
204
- ? slot.$allowedComponents.filter((v) => typeof v === 'string')
205
- : [];
206
- for (const target of allowed) {
207
- if (cycleParticipants.has(target))
208
- return true;
209
- }
210
- }
211
- return false;
212
- };
213
- const rootNames = [...closures.keys()].sort();
214
- const standaloneRoots = [];
215
- const groupRoots = [];
216
- for (const root of rootNames) {
217
- const c = closures.get(root);
218
- const promotesForCycle = hasCycleDepDirect(root);
219
- if (c.nodes.length <= 1 && !promotesForCycle)
220
- standaloneRoots.push(root);
221
- else
222
- groupRoots.push(root);
223
- }
224
- const seenSharedOccurrence = new Set();
225
- const seenCycleChildOccurrence = new Set();
226
- for (const root of groupRoots) {
227
- const closure = closures.get(root);
228
- let injectedCycleCount = 0;
229
- const seenInject = new Set();
230
- const countInjections = (parentName) => {
231
- const parentItem = itemByKey.get(parentName)?.it;
232
- if (!parentItem)
233
- return;
234
- for (const slot of Object.values(parentItem.entry.$slots ?? {})) {
235
- const allowed = Array.isArray(slot?.$allowedComponents)
236
- ? slot.$allowedComponents.filter((v) => typeof v === 'string')
237
- : [];
238
- for (const target of allowed) {
239
- if (!cycleParticipants.has(target))
240
- continue;
241
- const key = `${parentName}→${target}`;
242
- if (seenInject.has(key))
243
- continue;
244
- seenInject.add(key);
245
- injectedCycleCount += 1;
246
- }
247
- }
248
- };
249
- countInjections(root);
250
- for (const n of closure.nodes)
251
- if (n.name !== root)
252
- countInjections(n.name);
253
- const depCount = closure.nodes.length - 1 + injectedCycleCount;
254
- const expanded = alwaysExpanded ? true : props.expandedGroups.has(root);
255
- const glyphExpand = expanded ? GLYPH_EXPAND_EXPANDED : GLYPH_EXPAND_COLLAPSED;
256
- const aggregate = expanded ? null : aggregateGlyphFor(closure, statusByName);
257
- const rec = itemByKey.get(root);
258
- rows.push({
259
- kind: 'group-root',
260
- key: `root:${root}`,
261
- label: `${glyphExpand} ${root} (${depCount} dep${depCount === 1 ? '' : 's'})${aggregate ? ' ' + aggregate : ''}`,
262
- indent: 0,
263
- aggregateGlyph: aggregate,
264
- itemIdx: rec.idx,
265
- rootName: root,
266
- });
267
- if (!expanded)
268
- continue;
269
- const closureChildren = closure.nodes
270
- .filter((n) => n.name !== root)
271
- .slice()
272
- .sort((a, b) => a.depth - b.depth || a.name.localeCompare(b.name));
273
- const injectedChildren = [];
274
- const emitCycleChildrenOf = (parentName, parentDepth) => {
275
- const parentItem = itemByKey.get(parentName)?.it;
276
- if (!parentItem)
277
- return;
278
- const seen = new Set();
279
- for (const slot of Object.values(parentItem.entry.$slots ?? {})) {
280
- const allowed = Array.isArray(slot?.$allowedComponents)
281
- ? slot.$allowedComponents.filter((v) => typeof v === 'string')
282
- : [];
283
- for (const target of allowed) {
284
- if (!cycleParticipants.has(target))
285
- continue;
286
- if (seen.has(target))
287
- continue;
288
- seen.add(target);
289
- injectedChildren.push({
290
- name: target,
291
- depth: parentDepth + 1,
292
- isCycleChild: true,
293
- });
294
- }
295
- }
296
- };
297
- emitCycleChildrenOf(root, 0);
298
- for (const c of closureChildren) {
299
- injectedChildren.push({ name: c.name, depth: c.depth, isCycleChild: false });
300
- emitCycleChildrenOf(c.name, c.depth);
301
- }
302
- injectedChildren.forEach((child, i) => {
303
- const isLast = i === injectedChildren.length - 1;
304
- const glyph = isLast ? GLYPH_TREE_LAST : GLYPH_TREE_MID;
305
- let sharedSuffix = false;
306
- if (child.isCycleChild) {
307
- if (seenCycleChildOccurrence.has(child.name))
308
- sharedSuffix = true;
309
- else
310
- seenCycleChildOccurrence.add(child.name);
311
- }
312
- else if (sharedDeps.has(child.name)) {
313
- if (seenSharedOccurrence.has(child.name))
314
- sharedSuffix = true;
315
- else
316
- seenSharedOccurrence.add(child.name);
317
- }
318
- const childRec = itemByKey.get(child.name);
319
- const indent = ' '.repeat(Math.max(0, child.depth - 1));
320
- const labelName = child.isCycleChild ? `${GLYPH_WARN} ${child.name} (cycle)` : child.name;
321
- rows.push({
322
- kind: 'group-child',
323
- key: `child:${root}:${child.name}`,
324
- label: `${indent}${glyph} ${labelName}${sharedSuffix ? ' (shared)' : ''}`,
325
- indent: child.depth,
326
- sharedSuffix,
327
- cycleChild: child.isCycleChild || undefined,
328
- itemIdx: childRec?.idx ?? -1,
329
- rootName: root,
330
- });
331
- });
332
- }
333
- for (const name of standaloneRoots) {
334
- const rec = itemByKey.get(name);
335
- if (!rec)
336
- continue;
337
- rows.push({
338
- kind: 'standalone',
339
- key: `stand:${name}`,
340
- label: name,
341
- indent: 0,
342
- itemIdx: rec.idx,
343
- });
344
- }
345
- const nodeByName = new Map(subgraph.map((n) => [n.name, n]));
346
- const sharedLeafNames = [...sharedDeps.keys()]
347
- .filter((name) => (nodeByName.get(name)?.slots.length ?? 0) === 0)
348
- .sort();
349
- const seenStandaloneNames = new Set(standaloneRoots);
350
- for (const name of sharedLeafNames) {
351
- if (seenStandaloneNames.has(name))
352
- continue;
353
- const rec = itemByKey.get(name);
354
- if (!rec)
355
- continue;
356
- rows.push({
357
- kind: 'standalone',
358
- key: `shared-standalone:${name}`,
359
- label: `${name} (shared)`,
360
- indent: 0,
361
- sharedSuffix: true,
362
- itemIdx: rec.idx,
363
- });
364
- }
365
- if (showFlatTier) {
366
- const flatNames = otherKeys.slice().sort();
367
- if (flatNames.length > 0) {
368
- rows.push({
369
- kind: 'flat-header',
370
- key: 'flat-header',
371
- label: '── All components ──',
372
- indent: 0,
373
- itemIdx: -1,
374
- });
375
- for (const name of flatNames) {
376
- const rec = itemByKey.get(name);
377
- if (!rec)
378
- continue;
379
- rows.push({
380
- kind: 'flat',
381
- key: `flat:${name}`,
382
- label: name,
383
- indent: 0,
384
- itemIdx: rec.idx,
385
- });
386
- }
387
- }
388
- }
389
- if (filterVisibleKeys !== undefined) {
390
- return rows.filter((row) => {
391
- if (row.itemIdx < 0)
392
- return true;
393
- const name = items[row.itemIdx]?.key;
394
- if (name === undefined)
395
- return true;
396
- return filterVisibleKeys.has(name);
397
- });
398
- }
399
- return rows;
400
- }
401
- export function visibleItemOrder(props) {
402
- return buildVisibleRows(props)
403
- .filter((row) => row.itemIdx >= 0)
404
- .map((row) => row.itemIdx);
405
- }
406
- function rowColor(row, aggregate) {
407
- if (row.kind === 'cycle')
408
- return PALETTE.warning;
409
- if (row.kind === 'group-child' && row.cycleChild)
410
- return PALETTE.warning;
411
- if (row.kind === 'empty')
412
- return PALETTE.warning;
413
- if (row.kind === 'group-root' && aggregate === GLYPH_ERROR)
414
- return PALETTE.error;
415
- if (row.kind === 'group-root' && aggregate === GLYPH_WARN)
416
- return PALETTE.warning;
417
- return undefined;
418
- }
419
- export function labelStyleFor(input) {
420
- const { row, isCursor, wouldDim } = input;
421
- if (isCursor) {
422
- return { color: PALETTE.info, bold: true, dim: false };
423
- }
424
- return {
425
- color: rowColor(row, row.aggregateGlyph),
426
- bold: false,
427
- dim: wouldDim,
428
- };
429
- }
430
- export function selectionGlyphStyleFor(selState, isCycleRow) {
431
- if (selState === 'accepted') {
432
- return { glyph: '[✓]', color: PALETTE.success, dim: false, bold: isCycleRow };
433
- }
434
- if (selState === 'rejected') {
435
- return { glyph: '[✗]', color: PALETTE.error, dim: false, bold: isCycleRow };
436
- }
437
- if (selState === 'undecided') {
438
- return { glyph: '[ ]', color: PALETTE.muted, dim: !isCycleRow, bold: false };
439
- }
440
- return { glyph: null, color: undefined, dim: false, bold: false };
441
- }
442
- export function inheritanceGlyphStyleFor(input) {
443
- const { status, isOwn, isCursor } = input;
444
- if (status === 'error') {
445
- return { glyph: GLYPH_ERROR, color: PALETTE.error, dim: !isCursor && !isOwn, bold: isCursor };
446
- }
447
- if (status === 'warning') {
448
- return { glyph: GLYPH_WARN, color: PALETTE.warning, dim: !isCursor && !isOwn, bold: isCursor };
449
- }
450
- return { glyph: null, color: undefined, dim: false, bold: false };
451
- }
452
- export function GroupedSidebar(props) {
453
- const { items, cycleParticipants = new Set(), expandedGroups, focused, width, selectedIdx, selectedRowIdx, renderStatusByKey, previewAnnotationByKey, scrollOffset, visibleCount, alwaysExpanded, showFlatTier, viewMode, selectionStateByKey, aiFlaggedByKey, dimPredicate, visibleRows: providedRows, graph, filterVisibleKeys, } = props;
454
- const allRows = providedRows ??
455
- buildVisibleRows({
456
- items,
457
- cycleParticipants,
458
- expandedGroups,
459
- alwaysExpanded,
460
- showFlatTier,
461
- viewMode,
462
- graph,
463
- filterVisibleKeys,
464
- });
465
- const windowed = scrollOffset !== undefined && visibleCount !== undefined;
466
- const start = windowed ? Math.max(0, scrollOffset ?? 0) : 0;
467
- const end = windowed ? start + (visibleCount ?? allRows.length) : allRows.length;
468
- const rows = windowed ? allRows.slice(start, end) : allRows;
469
- const showScrollUp = windowed && start > 0;
470
- const showScrollDown = windowed && end < allRows.length;
471
- return (_jsxs(Box, { flexDirection: "column", width: width, flexShrink: 0, borderStyle: "single", borderColor: focused ? 'white' : undefined, children: [showScrollUp && _jsx(Text, { dimColor: true, children: "\u25B2" }), rows.map((row, i) => {
472
- const absoluteRowIdx = start + i;
473
- const isSelected = selectedRowIdx !== undefined
474
- ? absoluteRowIdx === selectedRowIdx && row.itemIdx >= 0
475
- : row.itemIdx >= 0 && row.itemIdx === selectedIdx;
476
- const itemName = row.itemIdx >= 0 ? items[row.itemIdx]?.key : undefined;
477
- const rs = itemName ? renderStatusByKey?.get(itemName) : undefined;
478
- const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
479
- const showInheritance = rs !== undefined && row.kind !== 'cycle' && row.kind !== 'empty' && row.kind !== 'group-root';
480
- const supportsSelectionGlyph = selectionStateByKey !== undefined &&
481
- itemName !== undefined &&
482
- (row.kind === 'standalone' ||
483
- row.kind === 'group-root' ||
484
- row.kind === 'group-child' ||
485
- row.kind === 'flat' ||
486
- row.kind === 'cycle');
487
- const selState = supportsSelectionGlyph ? (selectionStateByKey.get(itemName) ?? 'undecided') : undefined;
488
- const isCycleRow = row.kind === 'cycle';
489
- const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
490
- const selGlyph = selStyle.glyph;
491
- const selColor = selStyle.color;
492
- const selDim = selStyle.dim;
493
- const selBold = selStyle.bold;
494
- const aiFlagged = aiFlaggedByKey !== undefined &&
495
- itemName !== undefined &&
496
- row.kind !== 'flat-header' &&
497
- aiFlaggedByKey.get(itemName) === true;
498
- const canDim = dimPredicate !== undefined &&
499
- itemName !== undefined &&
500
- row.kind !== 'cycle' &&
501
- row.kind !== 'group-root' &&
502
- row.kind !== 'flat-header' &&
503
- dimPredicate(itemName);
504
- const isSynthetic = row.kind === 'flat-header';
505
- const isCursor = isSelected && focused;
506
- const wouldDim = row.kind === 'flat-header' || row.sharedSuffix === true || canDim;
507
- const labelStyle = labelStyleFor({ row, isCursor, wouldDim });
508
- const inheritanceStyle = inheritanceGlyphStyleFor({
509
- status: showInheritance ? rs?.status : undefined,
510
- isOwn: rs?.isOwn ?? false,
511
- isCursor,
512
- });
513
- return (_jsxs(Box, { children: [isCursor ? (_jsx(Text, { color: PALETTE.info, bold: true, children: '▶' })) : (_jsx(Text, { children: " " })), badge ? (_jsx(Text, { color: badge.color, bold: badge.bold, dimColor: badge.dim, children: badge.char })) : (_jsx(Text, { children: " " })), selectionStateByKey !== undefined &&
514
- (selGlyph && !isSynthetic ? (_jsx(Text, { color: selColor, dimColor: selDim, bold: selBold, children: ' ' + selGlyph })) : (_jsx(Text, { children: ' ' }))), aiFlaggedByKey !== undefined &&
515
- (aiFlagged ? (_jsx(Text, { color: PALETTE.warning, bold: true, children: ' [×]' })) : (_jsx(Text, { children: ' ' }))), _jsxs(Text, { color: labelStyle.color, bold: labelStyle.bold, inverse: isSelected && focused, underline: isSelected && !focused, dimColor: labelStyle.dim, wrap: "truncate", children: [' ', row.label] }), inheritanceStyle.glyph && (_jsx(Text, { color: inheritanceStyle.color, bold: inheritanceStyle.bold, dimColor: inheritanceStyle.dim, children: ' ' + inheritanceStyle.glyph }))] }, row.key));
516
- }), showScrollDown && _jsx(Text, { dimColor: true, children: "\u25BC" })] }));
517
- }
@@ -1,17 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React from 'react';
3
- import { Box, Text } from 'ink';
4
- import { useImmediateInput } from '../hooks/useImmediateInput.js';
5
- export function HelpOverlay(props) {
6
- const { onClose } = props;
7
- useImmediateInput((input, key) => {
8
- if (input === '?' || key.escape) {
9
- onClose();
10
- }
11
- });
12
- if (props.sections) {
13
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", padding: 1, width: 46, children: [_jsx(Text, { bold: true, children: '─'.repeat(18) + ' Help ' + '─'.repeat(18) }), props.sections.map((section) => (_jsxs(React.Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: section.title }), section.entries.map((entry) => (_jsx(Text, { children: entry.keys ? ' ' + entry.keys.padEnd(16) + ' ' + entry.label : ' ' + entry.label }, entry.keys + entry.label)))] }, section.title)))] }));
14
- }
15
- const mode = props.mode;
16
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", padding: 1, width: 46, children: [_jsx(Text, { bold: true, children: '─'.repeat(18) + ' Help ' + '─'.repeat(18) }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Navigation" }), _jsx(Text, { children: ' ↑ / k / PgUp Scroll up' }), _jsx(Text, { children: ' ↓ / j / PgDn Scroll down' }), _jsx(Text, { children: ' g / Home Jump to top' }), _jsx(Text, { children: ' G / End Jump to bottom' }), mode === 'review' && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "[Review mode only]" }), _jsx(Text, { children: ' Tab Toggle sidebar/detail' }), _jsx(Text, { children: ' a Accept component' }), _jsx(Text, { children: ' r Reject component' }), _jsx(Text, { children: ' e Edit proposal' }), _jsx(Text, { children: ' s Toggle source code' }), _jsx(Text, { children: ' A Approve all' }), _jsx(Text, { children: ' F Open finalize dialog' }), _jsx(Text, { children: ' Ctrl+S Save draft' }), _jsx(Text, { children: ' Ctrl+Z Undo' }), _jsx(Text, { children: ' Ctrl+Y Redo' }), _jsx(Text, { children: ' Esc Exit edit / close' })] })), _jsx(Text, { children: " " }), _jsx(Text, { children: ' ? Close help' }), _jsx(Text, { children: ' q Quit' })] }));
17
- }