sitevision-cli 1.0.0-beta.18 → 1.0.0-beta.19

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/cli.js CHANGED
@@ -30,11 +30,13 @@ const cli = meow(`
30
30
  info Show project information
31
31
 
32
32
  Options
33
+ --minimal Shell: compact layout for small terminals
33
34
  --help Show this help message
34
35
  --version Show version number
35
36
 
36
37
  Examples
37
38
  $ svc # Shell: run inside an app, or at the repo root
39
+ $ svc --minimal # Shell without the sidebar, for a small pane
38
40
  $ svc dev
39
41
  $ svc dev --signed
40
42
  $ svc watch
@@ -66,6 +68,10 @@ const cli = meow(`
66
68
  cookie: {
67
69
  type: 'string',
68
70
  },
71
+ minimal: {
72
+ type: 'boolean',
73
+ default: false,
74
+ },
69
75
  },
70
76
  });
71
77
  const [commandName, ...args] = cli.input;
@@ -125,14 +131,14 @@ async function playIntro(art) {
125
131
  async function runShell(apps, workspaceRoot) {
126
132
  process.stdout.write('\x1b[?1049h\x1b[H');
127
133
  try {
128
- const art = process.stdin.isTTY && settings.introAnimation
134
+ const art = process.stdin.isTTY && settings.introAnimation && !cli.flags.minimal
129
135
  ? pickIntroArt(process.stdout.columns ?? 0)
130
136
  : undefined;
131
137
  if (art) {
132
138
  await playIntro(art);
133
139
  process.stdout.write('\x1b[2J\x1b[H');
134
140
  }
135
- const app = render(_jsx(Shell, { apps: apps, workspaceRoot: workspaceRoot, version: pkg.version }));
141
+ const app = render(_jsx(Shell, { apps: apps, workspaceRoot: workspaceRoot, version: pkg.version, minimal: cli.flags.minimal }));
136
142
  await app.waitUntilExit();
137
143
  }
138
144
  finally {
@@ -453,7 +453,7 @@ export function ConfigForm({ project, active, width, height, pickAddon, onSaved,
453
453
  let lastSection;
454
454
  for (const f of fields) {
455
455
  if (f.section && f.section !== lastSection) {
456
- rows.push(_jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, dimColor: true, children: t(f.section) }) }, `s-${f.section}`));
456
+ rows.push(_jsx(Box, { marginTop: 1, flexShrink: 0, children: _jsx(Text, { bold: true, dimColor: true, children: t(f.section) }) }, `s-${f.section}`));
457
457
  lastSection = f.section;
458
458
  }
459
459
  const focused = active && f === current;
@@ -487,11 +487,11 @@ export function ConfigForm({ project, active, width, height, pickAddon, onSaved,
487
487
  display = typing ? (withCaret(draft)) : value ? (_jsx(Text, { children: value })) : (_jsx(Text, { dimColor: true, children: f.hint ? t(f.hint) : '—' }));
488
488
  }
489
489
  const src = source(f);
490
- rows.push(_jsxs(Box, { height: 1, children: [_jsx(Text, { color: focused ? ACCENT : undefined, bold: focused, dimColor: !focused, children: (focused ? '▸ ' : ' ') + t(f.label).padEnd(22) }), _jsx(Box, { width: valueWidth, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", children: display }) }), _jsx(Box, { width: SOURCE_WIDTH, flexShrink: 0, children: _jsx(Text, { dimColor: !src.color, color: src.color, wrap: "truncate", children: focused && f.hint && f.key === 'addonName' ? t(f.hint) : src.text }) })] }, f.key));
490
+ rows.push(_jsxs(Box, { height: 1, flexShrink: 0, children: [_jsx(Text, { color: focused ? ACCENT : undefined, bold: focused, dimColor: !focused, children: (focused ? '▸ ' : ' ') + t(f.label).padEnd(22) }), _jsx(Box, { width: valueWidth, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", children: display }) }), _jsx(Box, { width: SOURCE_WIDTH, flexShrink: 0, children: _jsx(Text, { dimColor: !src.color, color: src.color, wrap: "truncate", children: focused && f.hint && f.key === 'addonName' ? t(f.hint) : src.text }) })] }, f.key));
491
491
  }
492
- return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", height: height, children: [_jsxs(Text, { dimColor: true, children: [(' ' + t('FIELD')).padEnd(24), t('VALUE').padEnd(valueWidth), t('SOURCE')] }), rows, project.workspace && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: t("Shared by every app below {root}. An app's own value wins.", {
492
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", height: height, children: [_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: [(' ' + t('FIELD')).padEnd(24), t('VALUE').padEnd(valueWidth), t('SOURCE')] }) }), rows, project.workspace && (_jsx(Box, { marginTop: 1, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: t("Shared by every app below {root}. An app's own value wins.", {
493
493
  root: project.root,
494
- }) }) })), !project.workspace && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { bold: true, dimColor: true, children: [t('PACKAGE.JSON SYNC'), ' ', _jsx(Text, { color: changes.length > 0 ? 'yellow' : 'green', children: changes.length === 0
494
+ }) }) })), !project.workspace && (_jsxs(Box, { marginTop: 1, flexDirection: "column", flexShrink: 0, children: [_jsxs(Text, { bold: true, dimColor: true, children: [t('PACKAGE.JSON SYNC'), ' ', _jsx(Text, { color: changes.length > 0 ? 'yellow' : 'green', children: changes.length === 0
495
495
  ? t('in sync')
496
496
  : changes.length === 1
497
497
  ? t('1 diff · y to apply')
@@ -47,7 +47,7 @@ export interface NavigatorProps {
47
47
  filter?: string;
48
48
  }
49
49
  export declare function Navigator({ apps, groupOf, selected, focused, tasks, height, single, settingsSelected, width, filter, }: NavigatorProps): import("react").JSX.Element;
50
- export declare function NavigatorStrip({ apps, selected, focused, }: Pick<NavigatorProps, 'apps' | 'selected' | 'focused'>): import("react").JSX.Element;
50
+ export declare function NavigatorStrip({ apps, selected, focused, width, filter, }: Pick<NavigatorProps, 'apps' | 'selected' | 'focused' | 'width' | 'filter'>): import("react").JSX.Element;
51
51
  export declare function elapsed(task: Task): string;
52
52
  export interface Hint {
53
53
  key: string;
@@ -109,8 +109,21 @@ export function Navigator({ apps, groupOf, selected, focused, tasks, height, sin
109
109
  ? t('WORKSPACE 1 app')
110
110
  : t('WORKSPACE {n} apps', { n: apps.length }) })), shown, _jsx(Text, { dimColor: true, children: ' ' + t('deps·config·sync·signing') }), !single && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { backgroundColor: settingsSelected && focused ? ACCENT : undefined, color: settingsSelected && focused ? 'black' : undefined, bold: settingsSelected, children: [settingsSelected ? '▎' : ' ', "\u2699 ", t('Workspace settings')] }) })), running.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, dimColor: true, children: t('TASKS') }), running.map(task => (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: ACCENT, children: _jsx(Spinner, { type: "dots" }) }), ' ', task.label, " ", task.appName, " ", _jsx(Text, { dimColor: true, children: elapsed(task) })] }, task.id)))] }))] }));
111
111
  }
112
- export function NavigatorStrip({ apps, selected, focused, }) {
113
- return (_jsx(Box, { paddingX: 1, children: _jsx(Text, { wrap: "truncate", children: apps.map((app, index) => (_jsxs(Text, { backgroundColor: index === selected && focused ? ACCENT : undefined, color: index === selected && focused ? 'black' : undefined, bold: index === selected, children: [' ', typeGlyph(app.manifest), " ", appLabel(app), ' '] }, app.root))) }) }));
112
+ export function NavigatorStrip({ apps, selected, focused, width, filter = '', }) {
113
+ const label = (app) => ` ${typeGlyph(app.manifest)} ${appLabel(app)} `;
114
+ // Scroll the strip so the selection stays on screen: walk left from it
115
+ // until the row is full.
116
+ const budget = width - 2 - (filter ? filter.length + 5 : 0);
117
+ const from = Math.min(Math.max(0, selected), apps.length - 1);
118
+ let start = from;
119
+ let used = 0;
120
+ for (let i = from; i >= 0; i--) {
121
+ used += label(apps[i]).length;
122
+ if (used > budget)
123
+ break;
124
+ start = i;
125
+ }
126
+ return (_jsx(Box, { paddingX: 1, children: _jsxs(Text, { wrap: "truncate", children: [filter && (_jsxs(Text, { children: [_jsx(Text, { color: ACCENT, children: "\u276F " }), filter, _jsx(Text, { dimColor: true, children: " \u00B7" })] })), apps.slice(start).map((app, index) => (_jsx(Text, { backgroundColor: index + start === selected && focused ? ACCENT : undefined, color: index + start === selected && focused ? 'black' : undefined, bold: index + start === selected, children: label(app) }, app.root)))] }) }));
114
127
  }
115
128
  export function elapsed(task) {
116
129
  const ms = (task.endedAt ?? Date.now()) - task.startedAt;
@@ -3,6 +3,7 @@ interface Props {
3
3
  apps: ProjectInfo[];
4
4
  workspaceRoot?: string;
5
5
  version: string;
6
+ minimal?: boolean;
6
7
  }
7
- export declare function Shell({ apps: initialApps, workspaceRoot, version }: Props): import("react").JSX.Element;
8
+ export declare function Shell({ apps: initialApps, workspaceRoot, version, minimal, }: Props): import("react").JSX.Element;
8
9
  export {};
@@ -32,7 +32,7 @@ function useSize() {
32
32
  }, [stdout]);
33
33
  return size;
34
34
  }
35
- export function Shell({ apps: initialApps, workspaceRoot, version }) {
35
+ export function Shell({ apps: initialApps, workspaceRoot, version, minimal = false, }) {
36
36
  const { exit } = useApp();
37
37
  const { columns, rows } = useSize();
38
38
  const tasks = useTasks();
@@ -77,7 +77,7 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
77
77
  // Re-read after any reload so saved values show up.
78
78
  // eslint-disable-next-line react-hooks/exhaustive-deps
79
79
  [workspaceRoot, apps, env]);
80
- const narrow = columns < NARROW_BELOW;
80
+ const narrow = minimal || columns < NARROW_BELOW;
81
81
  const sidebar = navWidth(columns);
82
82
  // The navigator shows the fuzzy matches; `selected` stays an index into
83
83
  // `apps` (with `apps.length` meaning the workspace settings row).
@@ -363,7 +363,9 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
363
363
  run(action);
364
364
  }, { isActive: overlay === null && !editing });
365
365
  // Frame geometry: one row for Ink's trailing newline, top bar, bottom bar.
366
- const frameRows = Math.max(10, rows - 1);
366
+ // The sidebar layout needs 10 rows to stack its own fixed rows without
367
+ // overflowing; the compact one has no sidebar and fits in 6.
368
+ const frameRows = Math.max(narrow ? 6 : 10, rows - 1);
367
369
  const mainHeight = frameRows - 2;
368
370
  const contentHeight = mainHeight - 1 - (narrow ? 1 : 0);
369
371
  const groupOf = (app) => workspaceRoot ? appGroup(workspaceRoot, app.root) : '.';
@@ -495,9 +497,9 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
495
497
  return (_jsxs(Box, { flexDirection: "column", width: columns, height: frameRows, children: [_jsx(TopBar, { context: contextLabel, domain: project.devProperties?.domain, auth: authState(project), environment: {
496
498
  name: env,
497
499
  color: environmentColor(env, rawProject.devProperties),
498
- }, version: version }), _jsxs(Box, { flexGrow: 1, height: mainHeight, borderStyle: "single", borderDimColor: true, borderLeft: false, borderRight: false, borderBottom: false, children: [!narrow && (_jsx(Navigator, { apps: matches.map(i => apps[i]), groupOf: groupOf, selected: matches.indexOf(selected), focused: focus === 'nav', tasks: tasks, height: mainHeight - 1, single: single, settingsSelected: settings, width: sidebar, filter: filter })), _jsxs(Box, { flexDirection: "column", width: narrow ? columns : columns - sidebar, overflow: "hidden", children: [narrow && !single && (_jsx(NavigatorStrip, { apps: matches.map(i => apps[i]), selected: matches.indexOf(selected), focused: focus === 'nav' })), settings ? (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: t('Workspace settings') }), _jsx(Text, { dimColor: true, children: onboard && configIncomplete(workspaceTarget?.base)
500
+ }, version: version }), _jsxs(Box, { flexGrow: 1, height: mainHeight, borderStyle: "single", borderDimColor: true, borderLeft: false, borderRight: false, borderBottom: false, children: [!narrow && (_jsx(Navigator, { apps: matches.map(i => apps[i]), groupOf: groupOf, selected: matches.indexOf(selected), focused: focus === 'nav', tasks: tasks, height: mainHeight - 1, single: single, settingsSelected: settings, width: sidebar, filter: filter })), _jsxs(Box, { flexDirection: "column", width: narrow ? columns : columns - sidebar, overflow: "hidden", children: [narrow && !single && (_jsx(NavigatorStrip, { apps: matches.map(i => apps[i]), selected: matches.indexOf(selected), focused: focus === 'nav', width: columns, filter: filter })), settings ? (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: t('Workspace settings') }), _jsx(Text, { dimColor: true, children: onboard && configIncomplete(workspaceTarget?.base)
499
501
  ? t(' · new workspace: fill in once, every app inherits · Esc skips')
500
- : t(' · shared .dev_properties.json at the root') })] })) : (_jsx(TabBar, { tab: tab, narrow: narrow, focused: focus === 'content' })), _jsx(Box, { height: contentHeight, overflow: "hidden", alignItems: "flex-start", children: content })] })] }), _jsx(BottomBar, { hints: hints, right: right })] }));
502
+ : t(' · shared .dev_properties.json at the root') })] })) : (_jsx(TabBar, { tab: tab, narrow: narrow, focused: focus === 'content' })), _jsx(Box, { flexDirection: "column", height: contentHeight, overflow: "hidden", alignItems: "flex-start", children: content })] })] }), _jsx(BottomBar, { hints: hints, right: right })] }));
501
503
  }
502
504
  function renderOverlay(overlay, env) {
503
505
  const { project, closeOverlay, run, notify, loadAddons, height, rerender, openWorkspace, } = env;
@@ -15,7 +15,7 @@ export function TabBar({ tab, narrow, focused, }) {
15
15
  return (_jsx(Box, { paddingX: 1, children: TABS.map((entry, i) => (_jsxs(Text, { children: [_jsxs(Text, { bold: entry.id === tab, color: entry.id === tab ? ACCENT : undefined, dimColor: entry.id !== tab, underline: entry.id === tab && focused, children: [i + 1, " ", t(narrow ? entry.short : entry.label)] }), ' '.repeat(3)] }, entry.id))) }));
16
16
  }
17
17
  function Row({ label, value, dim, }) {
18
- return (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { dimColor: true, children: label.padEnd(14) }), value, dim && _jsxs(Text, { dimColor: true, children: [" ", dim] })] }));
18
+ return (_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { dimColor: true, children: label.padEnd(14) }), value, dim && _jsxs(Text, { dimColor: true, children: [" ", dim] })] }) }));
19
19
  }
20
20
  const LEVEL_COLOR = {
21
21
  info: undefined,
@@ -48,7 +48,7 @@ export function Overview({ project, tasks, height, }) {
48
48
  .slice(-Math.max(1, height - 18))
49
49
  .toReversed();
50
50
  const status = (ok, okText, badText, warn = false) => (_jsxs(Text, { children: [_jsx(Text, { color: ok ? 'green' : warn ? 'yellow' : 'red', children: ok ? '✓' : warn ? '~' : '✗' }), ' ', ok ? okText : badText] }));
51
- return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [_jsxs(Text, { bold: true, children: [localizedText(project.manifest.name) || project.manifest.id, ' ', _jsxs(Text, { dimColor: true, children: [project.manifest.type, project.manifest.bundled ? t(' · bundled') : ''] })] }), _jsx(Row, { label: t('id'), value: project.manifest.id }), _jsx(Row, { label: t('version'), value: project.manifest.version }), _jsx(Row, { label: t('type'), value: `${project.manifest.type} (${appTypeOf(project.manifest) ?? '?'})` }), _jsx(Row, { label: t('addon'), value: dev?.addonName ?? notSet, dim: src('addonName') }), _jsx(Row, { label: t('site'), value: dev?.siteName ?? notSet, dim: src('siteName') }), _jsx(Row, { label: t('environment'), value: dev?.environmentName ?? 'dev', dim: dev?.productionEnvironment ? t('production') : undefined }), _jsx(Row, { label: t('domain'), value: dev?.domain ?? notSet, dim: src('domain') }), _jsx(Row, { label: t('auth'), value: dev?.authMethod ?? (dev ? 'basic' : notSet), dim: src('authMethod') }), _jsx(Row, { label: t('signing user'), value: dev?.signingUsername ?? notSet, dim: src('signingUsername') }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: [t('deps').padEnd(10), status(project.hasNodeModules, 'node_modules', t('missing · i to install'))] }), _jsxs(Text, { dimColor: true, children: [t('config').padEnd(10), status(Boolean(dev), t('dev properties'), t('missing · e to edit'))] }), _jsxs(Text, { dimColor: true, children: [t('sync').padEnd(10), status(sync === 0, 'package.json', sync === 1
51
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { bold: true, wrap: "truncate", children: [localizedText(project.manifest.name) || project.manifest.id, ' ', _jsxs(Text, { dimColor: true, children: [project.manifest.type, project.manifest.bundled ? t(' · bundled') : ''] })] }) }), _jsx(Row, { label: t('id'), value: project.manifest.id }), _jsx(Row, { label: t('version'), value: project.manifest.version }), _jsx(Row, { label: t('type'), value: `${project.manifest.type} (${appTypeOf(project.manifest) ?? '?'})` }), _jsx(Row, { label: t('addon'), value: dev?.addonName ?? notSet, dim: src('addonName') }), _jsx(Row, { label: t('site'), value: dev?.siteName ?? notSet, dim: src('siteName') }), _jsx(Row, { label: t('environment'), value: dev?.environmentName ?? 'dev', dim: dev?.productionEnvironment ? t('production') : undefined }), _jsx(Row, { label: t('domain'), value: dev?.domain ?? notSet, dim: src('domain') }), _jsx(Row, { label: t('auth'), value: dev?.authMethod ?? (dev ? 'basic' : notSet), dim: src('authMethod') }), _jsx(Row, { label: t('signing user'), value: dev?.signingUsername ?? notSet, dim: src('signingUsername') }), _jsxs(Box, { marginTop: 1, flexDirection: "column", flexShrink: 0, children: [_jsxs(Text, { dimColor: true, children: [t('deps').padEnd(10), status(project.hasNodeModules, 'node_modules', t('missing · i to install'))] }), _jsxs(Text, { dimColor: true, children: [t('config').padEnd(10), status(Boolean(dev), t('dev properties'), t('missing · e to edit'))] }), _jsxs(Text, { dimColor: true, children: [t('sync').padEnd(10), status(sync === 0, 'package.json', sync === 1
52
52
  ? t('1 diff · y to apply')
53
53
  : t('{n} diffs · y to apply', { n: sync }), true)] }), _jsxs(Text, { dimColor: true, children: [t('signing').padEnd(10), status(project.hasSigningProperties, dev?.signingUsername ?? '', t('missing · / set up signing'))] }), _jsxs(Text, { dimColor: true, children: [t('scripts').padEnd(10), status(scripts.status === 'ok', scripts.installed ?? '', scripts.installed
54
54
  ? `${scripts.installed} · ${scripts.status}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sitevision-cli",
3
- "version": "1.0.0-beta.18",
3
+ "version": "1.0.0-beta.19",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "svc": "dist/cli.js"