@contentful/experience-design-system-cli 2.6.2-dev-build-3f849e3.0 → 2.6.2-dev-build-864e323.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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.6.2-dev-build-3f849e3.0",
3
+ "version": "2.6.2-dev-build-864e323.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,14 +31,18 @@ const OBVIOUS_PROP_NAMES = new Set([
31
31
  'aria-label',
32
32
  'aria-describedby',
33
33
  ]);
34
- // A union is "wide" if it mixes primitive base types with no additional narrowing
34
+ // A union is "wide" if it mixes 3+ distinct base primitive types (ignoring nullability modifiers).
35
+ // e.g. "string | number | boolean" → wide. "string | null | undefined" → NOT wide (just nullable string).
35
36
  function isWidePrimitiveUnion(type) {
36
- // e.g. "string | number | boolean" — three or more base primitives
37
37
  const parts = type.split('|').map((p) => p.trim());
38
38
  if (parts.length < 3)
39
39
  return false;
40
- const primitives = new Set(['string', 'number', 'boolean', 'null', 'undefined']);
41
- return parts.filter((p) => primitives.has(p)).length >= 3;
40
+ const basePrimitives = new Set(['string', 'number', 'boolean']);
41
+ const nullability = new Set(['null', 'undefined']);
42
+ const baseCount = parts.filter((p) => basePrimitives.has(p)).length;
43
+ const nullabilityCount = parts.filter((p) => nullability.has(p)).length;
44
+ // Wide only when there are 3+ base primitives, or 2+ base primitives combined with nullability modifiers
45
+ return baseCount >= 3 || (baseCount >= 2 && nullabilityCount > 0 && baseCount + nullabilityCount >= 3);
42
46
  }
43
47
  export function computeExtractionScore(component) {
44
48
  let confidence = 100;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { Box, Text, useStdout } from 'ink';
4
4
  import { readFile } from 'node:fs/promises';
5
5
  import { createReviewSessionDetail } from '../types.js';
@@ -40,6 +40,11 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
40
40
  const [finalizedResult, setFinalizedResult] = useState(null);
41
41
  const [sidebarScrollOffset, setSidebarScrollOffset] = useState(0);
42
42
  const [jsonScrollOffset, setJsonScrollOffset] = useState(0);
43
+ // Keeps the visual sort order in sync for use inside keymap handlers (which close over a stale render)
44
+ const sortedIdsRef = useRef([]);
45
+ // Source code kept separate from session state so lazy loading never mutates
46
+ // session.components — that would invalidate useMemo(sessionSummary) and flash the sidebar
47
+ const [sourceCodeById, setSourceCodeById] = useState({});
43
48
  const [previewAnnotations, setPreviewAnnotations] = useState(() => {
44
49
  const raw = process.env['EDS_PREVIEW_ANNOTATIONS'];
45
50
  if (!raw)
@@ -138,13 +143,22 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
138
143
  clearTimeout(previewDebounceRef.current);
139
144
  };
140
145
  }, []);
141
- // Sync loaded session into local state
146
+ // Sync loaded session into local state; selectedId is set to null here
147
+ // and will be corrected to the first sorted item on first render via the effect below
142
148
  useEffect(() => {
143
149
  if (loadedSession && !session) {
144
150
  setSession(loadedSession);
145
- setSelectedId(loadedSession.components[0]?.id ?? null);
151
+ setSelectedId(null);
146
152
  }
147
153
  }, [loadedSession]);
154
+ // Once the sort order is known (after first render), select the first sorted item.
155
+ // Runs only when session transitions from null → loaded.
156
+ const sessionLoaded = session !== null;
157
+ useEffect(() => {
158
+ if (sessionLoaded && selectedId === null && sortedIdsRef.current.length > 0) {
159
+ setSelectedId(sortedIdsRef.current[0]);
160
+ }
161
+ }, [sessionLoaded]);
148
162
  useEffect(() => {
149
163
  if (session && !previewResponse) {
150
164
  const raw = process.env['EDS_PREVIEW_COUNTS'];
@@ -172,26 +186,22 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
172
186
  }
173
187
  }
174
188
  }, [session]);
175
- // Lazy source code loading
189
+ // Lazy source code loading — writes to sourceCodeById, NOT session.components,
190
+ // so it doesn't invalidate useMemo(sessionSummary) and cause a sidebar flash
176
191
  useEffect(() => {
177
192
  if (!session || !selectedId)
178
193
  return;
194
+ if (sourceCodeById[selectedId] !== undefined)
195
+ return; // already loaded
179
196
  const selectedComponent = session.components.find((c) => c.id === selectedId);
180
- if (!selectedComponent || selectedComponent.sourceCode !== null)
197
+ if (!selectedComponent)
181
198
  return;
182
199
  readFile(selectedComponent.resolvedSourcePath, 'utf8')
183
200
  .then((code) => {
184
- setSession((prev) => {
185
- if (!prev)
186
- return prev;
187
- return {
188
- ...prev,
189
- components: prev.components.map((c) => (c.id === selectedComponent.id ? { ...c, sourceCode: code } : c)),
190
- };
191
- });
201
+ setSourceCodeById((prev) => ({ ...prev, [selectedId]: code }));
192
202
  })
193
203
  .catch(() => {
194
- // Leave as null; SourcePanel shows [No source available]
204
+ setSourceCodeById((prev) => ({ ...prev, [selectedId]: '' }));
195
205
  });
196
206
  }, [selectedId]);
197
207
  // SIGINT handler
@@ -235,9 +245,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
235
245
  onSidebarUp: () => {
236
246
  if (!session)
237
247
  return;
238
- const idx = session.components.findIndex((c) => c.id === selectedId);
248
+ const ids = sortedIdsRef.current;
249
+ const idx = ids.indexOf(selectedId ?? '');
239
250
  if (idx > 0) {
240
- setSelectedId(session.components[idx - 1].id);
251
+ setSelectedId(ids[idx - 1]);
241
252
  setJsonScrollOffset(0);
242
253
  setSidebarScrollOffset((prev) => Math.min(prev, idx - 1));
243
254
  }
@@ -245,9 +256,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
245
256
  onSidebarDown: () => {
246
257
  if (!session)
247
258
  return;
248
- const idx = session.components.findIndex((c) => c.id === selectedId);
249
- if (idx < session.components.length - 1) {
250
- setSelectedId(session.components[idx + 1].id);
259
+ const ids = sortedIdsRef.current;
260
+ const idx = ids.indexOf(selectedId ?? '');
261
+ if (idx < ids.length - 1) {
262
+ setSelectedId(ids[idx + 1]);
251
263
  setJsonScrollOffset(0);
252
264
  setSidebarScrollOffset((prev) => {
253
265
  const newIdx = idx + 1;
@@ -273,7 +285,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
273
285
  setEditMode(true);
274
286
  setDraftsByComponentId((prev) => ({
275
287
  ...prev,
276
- [selectedId]: prev[selectedId] ?? JSON.stringify(component.editedProposal, null, 2),
288
+ [selectedId]: (() => {
289
+ const { extractionConfidence: _c, reviewReasons: _r, needsReview: _n, ...rest } = component.editedProposal;
290
+ return prev[selectedId] ?? JSON.stringify(rest, null, 2);
291
+ })(),
277
292
  }));
278
293
  },
279
294
  onToggleSource: () => {
@@ -315,19 +330,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
315
330
  },
316
331
  onToggleHelp: () => setShowHelp((prev) => !prev),
317
332
  });
318
- if (loading) {
319
- return _jsx(Text, { children: "Loading session..." });
320
- }
321
- if (sessionError) {
322
- return (_jsxs(Text, { color: "red", children: [sessionError, '\nPress q to exit.'] }));
323
- }
324
- if (!session || !paths) {
325
- return _jsx(Text, { color: "red", children: "Session unavailable." });
326
- }
327
- if (finalizedResult) {
328
- return _jsx(FinalizedScreen, { result: finalizedResult });
329
- }
330
- const sessionSummary = session.components
333
+ // Sorted order: flagged+unresolved first, then ascending confidence.
334
+ // Memoised above early returns (React rules of hooks) so the array reference
335
+ // is stable between renders — prevents Sidebar repainting on scroll/select.
336
+ const sessionSummary = useMemo(() => (session?.components ?? [])
331
337
  .map((c) => ({
332
338
  id: c.id,
333
339
  name: c.name,
@@ -337,13 +343,27 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
337
343
  needsReview: c.originalProposal.needsReview ?? false,
338
344
  }))
339
345
  .sort((a, b) => {
340
- // Unresolved flagged items first, then by ascending confidence
341
346
  const aFlagged = a.needsReview && a.status === 'needs-review' ? 0 : 1;
342
347
  const bFlagged = b.needsReview && b.status === 'needs-review' ? 0 : 1;
343
348
  if (aFlagged !== bFlagged)
344
349
  return aFlagged - bFlagged;
345
350
  return a.extractionConfidence - b.extractionConfidence;
346
- });
351
+ }), [session?.components, previewAnnotations]);
352
+ // Stable ID order — kept in a ref for use inside keymap handlers
353
+ const sortedIds = useMemo(() => sessionSummary.map((c) => c.id), [sessionSummary]);
354
+ sortedIdsRef.current = sortedIds;
355
+ if (loading) {
356
+ return _jsx(Text, { children: "Loading session..." });
357
+ }
358
+ if (sessionError) {
359
+ return (_jsxs(Text, { color: "red", children: [sessionError, '\nPress q to exit.'] }));
360
+ }
361
+ if (!session || !paths) {
362
+ return _jsx(Text, { color: "red", children: "Session unavailable." });
363
+ }
364
+ if (finalizedResult) {
365
+ return _jsx(FinalizedScreen, { result: finalizedResult });
366
+ }
347
367
  const selectedRecord = session.components.find((c) => c.id === selectedId) ?? null;
348
368
  const sessionDetail = selectedRecord ? createReviewSessionDetail({ ...session, components: [selectedRecord] }) : null;
349
369
  const selectedDetail = sessionDetail?.components[0] ?? null;
@@ -363,7 +383,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
363
383
  { key: 'q', label: 'quit' },
364
384
  ];
365
385
  const collapsed = terminalWidth < 80;
366
- const visibleCount = 20;
386
+ // TopBar(1) + statusbar(1) + footer(1) + border padding(2) = ~5 chrome rows
387
+ const CHROME_ROWS = 5;
388
+ const terminalRows = stdout?.rows ?? 24;
389
+ const visibleCount = Math.max(1, terminalRows - CHROME_ROWS);
367
390
  const longestName = session.components.reduce((max, c) => Math.max(max, c.name.length), 0);
368
391
  // icon + space + name + 2 border chars; min 14, max 22
369
392
  const sidebarWidth = collapsed ? 3 : Math.min(Math.max(longestName + 4, 14), 22);
@@ -479,7 +502,7 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
479
502
  }, onCancel: () => setShowQuitDialog(false) })), !showHelp && !showFinalizeDialog && !showQuitDialog && (_jsxs(Box, { flexGrow: 1, children: [_jsx(Sidebar, { components: sessionSummary, selectedId: selectedId, focused: sidebarFocused, scrollOffset: sidebarScrollOffset, visibleCount: visibleCount, onSelect: (id) => {
480
503
  setSelectedId(id);
481
504
  setJsonScrollOffset(0);
482
- }, onScrollChange: setSidebarScrollOffset, collapsed: collapsed, width: sidebarWidth }), _jsx(Box, { flexGrow: 1, paddingLeft: 1, children: selectedDetail ? (_jsx(ComponentDetail, { component: selectedDetail, sourceCode: selectedRecord?.sourceCode ?? null, draftValue: selectedId ? (draftsByComponentId[selectedId] ?? '') : '', editMode: editMode, sourceVisible: sourceVisible, jsonScrollOffset: jsonScrollOffset, sourceScrollX: 0, sourceScrollY: 0, terminalWidth: terminalWidth, previewAnnotation: selectedRecord ? previewAnnotations[selectedRecord.name] : undefined, onDraftChange: (value) => {
505
+ }, onScrollChange: setSidebarScrollOffset, collapsed: collapsed, width: sidebarWidth }), _jsx(Box, { flexGrow: 1, paddingLeft: 1, children: selectedDetail ? (_jsx(ComponentDetail, { component: selectedDetail, sourceCode: selectedId ? (sourceCodeById[selectedId] ?? null) : null, draftValue: selectedId ? (draftsByComponentId[selectedId] ?? '') : '', editMode: editMode, sourceVisible: sourceVisible, jsonScrollOffset: jsonScrollOffset, sourceScrollX: 0, sourceScrollY: 0, terminalWidth: terminalWidth, previewAnnotation: selectedRecord ? previewAnnotations[selectedRecord.name] : undefined, onDraftChange: (value) => {
483
506
  if (!selectedId)
484
507
  return;
485
508
  setDraftsByComponentId((prev) => ({
@@ -34,10 +34,16 @@ export function ComponentDetail({ component, sourceCode, draftValue, editMode, s
34
34
  editWidth = availableWidth - originalWidth - 3;
35
35
  sourceWidth = 0;
36
36
  }
37
- const originalJson = JSON.stringify(component.originalProposal, null, 2);
38
- const editedJson = JSON.stringify(component.editedProposal, null, 2);
37
+ // Strip internal scoring fields — they're metadata, not part of the component definition
38
+ const stripScoring = ({ extractionConfidence: _c, reviewReasons: _r, needsReview: _n, ...rest }) => rest;
39
+ const originalJson = JSON.stringify(stripScoring(component.originalProposal), null, 2);
40
+ const editedJson = JSON.stringify(stripScoring(component.editedProposal), null, 2);
41
+ const conf = component.originalProposal.extractionConfidence ?? 100;
42
+ const nr = component.originalProposal.needsReview ?? false;
43
+ const confColor = nr ? 'red' : conf >= 80 ? 'white' : conf >= 50 ? 'yellow' : 'red';
44
+ const confLabel = (nr ? '⚑ ' : '') + 'confidence: ' + String(conf);
39
45
  return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: component.name }), (() => {
40
46
  const ann = annotationLabel(previewAnnotation);
41
47
  return ann ? _jsx(Text, { color: ann.color, children: ann.text }) : null;
42
- })(), _jsx(Box, { flexGrow: 1 }), _jsxs(Text, { dimColor: true, children: [sourceVisible ? '[s] hide src' : '[s] src', editMode ? '' : ' [e] edit'] })] }), _jsxs(Box, { children: [_jsx(JsonPanel, { label: "ORIGINAL (read-only)", value: originalJson, scrollOffset: jsonScrollOffset, width: originalWidth, height: panelHeight, active: false }), _jsx(Text, { children: " " }), editMode ? (_jsx(FieldEditor, { value: draftValue || editedJson, width: editWidth, height: panelHeight, onChange: onDraftChange, onSave: onSaveDraft, onDiscard: onDiscardDraft })) : (_jsx(JsonPanel, { label: "EDIT (draft)", value: draftValue || editedJson, scrollOffset: jsonScrollOffset, width: editWidth, height: panelHeight, active: true })), sourceVisible && sourceWidth > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(SourcePanel, { sourceCode: sourceCode, filePath: component.originalProposal.source, width: sourceWidth, height: panelHeight, scrollX: sourceScrollX, scrollY: sourceScrollY })] }))] }), !editMode && _jsx(Text, { dimColor: true, children: ' [a] accept [r] reject [e] edit [A] accept all [↑↓] scroll' })] }));
48
+ })(), _jsx(Text, { color: confColor, children: ' — ' + confLabel }), _jsx(Box, { flexGrow: 1 }), _jsxs(Text, { dimColor: true, children: [sourceVisible ? '[s] hide src' : '[s] src', editMode ? '' : ' [e] edit'] })] }), _jsxs(Box, { children: [_jsx(JsonPanel, { label: "ORIGINAL (read-only)", value: originalJson, scrollOffset: jsonScrollOffset, width: originalWidth, height: panelHeight, active: false }), _jsx(Text, { children: " " }), editMode ? (_jsx(FieldEditor, { value: draftValue || editedJson, width: editWidth, height: panelHeight, onChange: onDraftChange, onSave: onSaveDraft, onDiscard: onDiscardDraft })) : (_jsx(JsonPanel, { label: "EDIT (draft)", value: draftValue || editedJson, scrollOffset: jsonScrollOffset, width: editWidth, height: panelHeight, active: true })), sourceVisible && sourceWidth > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(SourcePanel, { sourceCode: sourceCode, filePath: component.originalProposal.source, width: sourceWidth, height: panelHeight, scrollX: sourceScrollX, scrollY: sourceScrollY })] }))] }), !editMode && _jsx(Text, { dimColor: true, children: ' [a] accept [r] reject [e] edit [A] accept all [↑↓] scroll' })] }));
43
49
  }
@@ -29,24 +29,6 @@ function truncateName(name, maxLen) {
29
29
  return name;
30
30
  return name.slice(0, maxLen) + '…';
31
31
  }
32
- function confidenceColor(confidence, needsReview) {
33
- if (needsReview)
34
- return 'red';
35
- if (confidence >= 80)
36
- return 'green';
37
- if (confidence >= 50)
38
- return 'yellow';
39
- return 'red';
40
- }
41
- function confidenceDot(confidence, needsReview) {
42
- if (needsReview)
43
- return '⚑';
44
- if (confidence >= 80)
45
- return '●';
46
- if (confidence >= 50)
47
- return '◐';
48
- return '○';
49
- }
50
32
  export function Sidebar({ components, selectedId, focused, scrollOffset, visibleCount, collapsed = false, width: widthProp, }) {
51
33
  const visible = components.slice(scrollOffset, scrollOffset + visibleCount);
52
34
  const showScrollUp = scrollOffset > 0;
@@ -56,16 +38,11 @@ export function Sidebar({ components, selectedId, focused, scrollOffset, visible
56
38
  const isSelected = component.id === selectedId;
57
39
  const icon = statusIcon(component.status);
58
40
  const color = statusColor(component.status);
59
- const conf = component.extractionConfidence ?? 100;
60
- const nr = component.needsReview ?? false;
61
- const dot = confidenceDot(conf, nr);
62
- const dotColor = confidenceColor(conf, nr);
63
- // reserve 2 chars for dot + space on top of existing icon + space
64
- const maxNameLen = Math.max(1, width - 7);
41
+ const maxNameLen = Math.max(1, width - 4);
65
42
  const name = truncateName(component.name, maxNameLen);
66
43
  if (collapsed) {
67
44
  return (_jsx(Box, { children: _jsx(Text, { color: color, inverse: isSelected && focused, underline: isSelected && !focused, children: icon }) }, component.id));
68
45
  }
69
- return (_jsxs(Box, { children: [_jsx(Text, { color: color, inverse: isSelected && focused, underline: isSelected && !focused, wrap: "truncate", children: icon + ' ' + name + ' ' }), _jsx(Text, { color: dotColor, children: dot })] }, component.id));
46
+ return (_jsx(Box, { children: _jsx(Text, { color: color, inverse: isSelected && focused, underline: isSelected && !focused, wrap: "truncate", children: icon + ' ' + name }) }, component.id));
70
47
  }), showScrollDown && !collapsed && _jsx(Text, { dimColor: true, children: "\u25BC" })] }));
71
48
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { Box, Text } from 'ink';
3
+ import { Box, Text, useStdout } from 'ink';
4
4
  import { TopBar } from '../select/tui/components/TopBar.js';
5
5
  import { useImmediateInput } from '../select/tui/hooks/useImmediateInput.js';
6
6
  function truncateName(name, maxLen = 30) {
@@ -10,6 +10,12 @@ function truncateName(name, maxLen = 30) {
10
10
  }
11
11
  export function AnalyzeView({ result, onExit }) {
12
12
  const [scrollOffset, setScrollOffset] = useState(0);
13
+ const { stdout } = useStdout();
14
+ // Header lines: TopBar(1) + summary(3) + blank(1) + dividers+header(3) + blank(1) + footer(1) + footer-bar(1) = ~12
15
+ const HEADER_ROWS = 12;
16
+ const terminalRows = stdout?.rows ?? 24;
17
+ const visibleCount = Math.max(1, terminalRows - HEADER_ROWS);
18
+ const maxOffset = Math.max(0, result.components.length - visibleCount);
13
19
  useImmediateInput((input, key) => {
14
20
  if (input === 'q' || key.return) {
15
21
  onExit();
@@ -19,24 +25,36 @@ export function AnalyzeView({ result, onExit }) {
19
25
  setScrollOffset((o) => Math.max(0, o - 1));
20
26
  }
21
27
  else if (key.downArrow || input === 'j') {
22
- setScrollOffset((o) => o + 1);
28
+ setScrollOffset((o) => Math.min(maxOffset, o + 1));
23
29
  }
24
30
  else if (input === 'g') {
25
31
  setScrollOffset(0);
26
32
  }
27
33
  else if (input === 'G') {
28
- setScrollOffset(Math.max(0, result.components.length + 10));
34
+ setScrollOffset(maxOffset);
29
35
  }
30
36
  });
37
+ const visible = result.components.slice(scrollOffset, scrollOffset + visibleCount);
38
+ const showScrollUp = scrollOffset > 0;
39
+ const showScrollDown = scrollOffset + visibleCount < result.components.length;
31
40
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(TopBar, { subcommand: "analyze", hints: [
32
41
  { key: '?', label: 'help' },
33
42
  { key: 'q', label: 'quit' },
34
- ] }), _jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsx(Text, { children: 'Scanned ' + result.fileCount + ' source files in ' + result.sourceDirectory }), _jsx(Text, { children: 'Extracted ' + result.components.length + ' components' }), _jsx(Text, { dimColor: true, children: 'Session: ' + result.sessionId }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, children: "Components" }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), result.components.slice(scrollOffset).map((component) => {
43
+ ] }), _jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsx(Text, { children: 'Scanned ' + result.fileCount + ' source files in ' + result.sourceDirectory }), _jsx(Text, { children: 'Extracted ' + result.components.length + ' components' }), _jsx(Text, { dimColor: true, children: 'Session: ' + result.sessionId }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, children: 'Components' +
44
+ (showScrollUp || showScrollDown
45
+ ? ' (' +
46
+ (scrollOffset + 1) +
47
+ '–' +
48
+ Math.min(scrollOffset + visibleCount, result.components.length) +
49
+ ' of ' +
50
+ result.components.length +
51
+ ')'
52
+ : '') }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), showScrollUp && _jsx(Text, { dimColor: true, children: " \u25B2 scroll up" }), visible.map((component) => {
35
53
  const conf = component.extractionConfidence ?? 100;
36
- const confColor = component.needsReview ? 'red' : conf >= 80 ? 'green' : conf >= 50 ? 'yellow' : 'red';
37
- const confDot = component.needsReview ? '⚑' : conf >= 80 ? '' : conf >= 50 ? '◐' : '○';
38
- return (_jsxs(Box, { children: [component.warnings.length > 0 && _jsx(Text, { color: "yellow", children: "\u26A0 " }), component.warnings.length === 0 && _jsx(Text, { children: " " }), _jsx(Text, { children: truncateName(component.name).padEnd(20) }), _jsx(Text, { dimColor: true, children: component.framework.padEnd(10) }), _jsx(Text, { children: (component.propCount + ' props').padEnd(10) }), _jsx(Text, { children: (component.slotCount + ' ' + (component.slotCount === 1 ? 'slot' : 'slots')).padEnd(8) }), _jsx(Text, { color: confColor, children: confDot + ' ' + String(conf).padStart(3) }), component.warnings.length > 0 && (_jsx(Text, { color: "yellow", children: ' ⚠ ' + component.warnings.length + ' warning' + (component.warnings.length === 1 ? '' : 's') }))] }, component.name));
39
- }), result.totalWarnings > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "yellow", children: 'Warnings (' + result.totalWarnings + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), result.components
54
+ const confColor = component.needsReview ? 'red' : conf >= 80 ? 'white' : conf >= 50 ? 'yellow' : 'red';
55
+ const confLabel = (component.needsReview ? '⚑ ' : '') + String(conf);
56
+ return (_jsxs(Box, { children: [component.warnings.length > 0 && _jsx(Text, { color: "yellow", children: "\u26A0 " }), component.warnings.length === 0 && _jsx(Text, { children: " " }), _jsx(Text, { children: truncateName(component.name).padEnd(20) }), _jsx(Text, { dimColor: true, children: component.framework.padEnd(10) }), _jsx(Text, { children: (component.propCount + ' props').padEnd(10) }), _jsx(Text, { children: (component.slotCount + ' ' + (component.slotCount === 1 ? 'slot' : 'slots')).padEnd(8) }), _jsx(Text, { color: confColor, children: confLabel }), component.warnings.length > 0 && (_jsx(Text, { color: "yellow", children: ' ⚠ ' + component.warnings.length + ' warning' + (component.warnings.length === 1 ? '' : 's') }))] }, component.name));
57
+ }), showScrollDown && _jsx(Text, { dimColor: true, children: " \u25BC scroll down" }), result.totalWarnings > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "yellow", children: 'Warnings (' + result.totalWarnings + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), result.components
40
58
  .filter((c) => c.warnings.length > 0)
41
59
  .flatMap((c) => c.warnings.map((w) => ({ component: c.name, warning: w })))
42
60
  .map((w, i) => (_jsx(Text, { color: "yellow", children: ' ⚠ ' + w.component + ': ' + w.warning }, i)))] })), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: 'Run: analyze select --session ' + result.sessionId }), _jsx(Text, { children: " " })] }), _jsx(Box, { borderStyle: "single", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter or q to exit" }) })] }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.6.2-dev-build-3f849e3.0",
3
+ "version": "2.6.2-dev-build-864e323.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,7 +36,7 @@
36
36
  "react-dom": "^18.3.1",
37
37
  "ts-morph": "^27.0.2",
38
38
  "typescript": "^5.9.3",
39
- "@contentful/experience-design-system-types": "2.6.2-dev-build-3f849e3.0"
39
+ "@contentful/experience-design-system-types": "2.6.2-dev-build-864e323.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@tsconfig/node24": "^24.0.3",