veryfront 0.0.84 → 0.0.86

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 (35) hide show
  1. package/README.md +18 -44
  2. package/esm/deno.js +1 -1
  3. package/esm/src/cli/app/components/list-select.js +2 -2
  4. package/esm/src/cli/app/index.d.ts +1 -1
  5. package/esm/src/cli/app/index.d.ts.map +1 -1
  6. package/esm/src/cli/app/index.js +26 -33
  7. package/esm/src/cli/app/state.d.ts +3 -0
  8. package/esm/src/cli/app/state.d.ts.map +1 -1
  9. package/esm/src/cli/app/state.js +4 -0
  10. package/esm/src/cli/app/views/dashboard.d.ts.map +1 -1
  11. package/esm/src/cli/app/views/dashboard.js +45 -57
  12. package/esm/src/cli/app/views/startup.d.ts +39 -0
  13. package/esm/src/cli/app/views/startup.d.ts.map +1 -0
  14. package/esm/src/cli/app/views/startup.js +103 -0
  15. package/esm/src/cli/ui/colors.d.ts +8 -0
  16. package/esm/src/cli/ui/colors.d.ts.map +1 -1
  17. package/esm/src/cli/ui/colors.js +34 -0
  18. package/esm/src/cli/ui/dot-matrix.d.ts +8 -0
  19. package/esm/src/cli/ui/dot-matrix.d.ts.map +1 -1
  20. package/esm/src/cli/ui/dot-matrix.js +67 -2
  21. package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
  22. package/esm/src/modules/react-loader/ssr-module-loader/loader.js +28 -6
  23. package/esm/src/transforms/esm/http-cache.d.ts.map +1 -1
  24. package/esm/src/transforms/esm/http-cache.js +25 -17
  25. package/package.json +1 -1
  26. package/src/deno.js +1 -1
  27. package/src/src/cli/app/components/list-select.ts +2 -2
  28. package/src/src/cli/app/index.ts +34 -35
  29. package/src/src/cli/app/state.ts +7 -0
  30. package/src/src/cli/app/views/dashboard.ts +46 -60
  31. package/src/src/cli/app/views/startup.ts +132 -0
  32. package/src/src/cli/ui/colors.ts +37 -0
  33. package/src/src/cli/ui/dot-matrix.ts +77 -1
  34. package/src/src/modules/react-loader/ssr-module-loader/loader.ts +43 -30
  35. package/src/src/transforms/esm/http-cache.ts +26 -17
package/README.md CHANGED
@@ -7,54 +7,28 @@ npx veryfront
7
7
  ```
8
8
 
9
9
  ```
10
- ○ ○ ○ ○ ○ ○ ○
11
- ○ ● ● ● ○ ○ ○ Veryfront Code is running
12
- ○ ○ ○
13
- ○ ● ● Url http://veryfront.me:3000
14
- ○ ○ ● ● ● ○ Mcp http://veryfront.me:3002/mcp
15
- ○ ● ●
16
- ○ ○ ○
17
-
18
- Server ready
19
- ✓ MCP ready
10
+ ╭──────────────────────────────────────────────────────────╮
11
+ │ │
12
+ ○ ○ ○
13
+ ○ ● ● ● Veryfront Code is now running │
14
+ ○ ● ● ● ○ ○ ○ │
15
+ ○ ● ● ○ Url http://veryfront.me:8080 │
16
+ ○ ○ ○ Mcp http://veryfront.me:9999/mcp │
17
+ │ ○ ○ ○ ● ● ● ○ │
18
+ ○ ○ ○ ○ ○ │
19
+ │ │
20
+ ╰──────────────────────────────────────────────────────────╯
20
21
  ```
21
22
 
22
23
  One command. Zero config. Just build.
23
24
 
24
- ## Project Structure
25
+ [Docs](https://veryfront.com/docs/framework) · [Discord](https://discord.gg/veryfront) · [X](https://x.com/veryfrontdev) · MIT
25
26
 
26
- ```
27
- my-app/
28
- ├── app/ # App Router (pages & APIs)
29
- │ ├── chat/page.tsx
30
- │ └── api/chat/route.ts
31
- ├── agents/ # AI agents
32
- ├── tools/ # MCP tools
33
- ├── workflows/ # Durable workflows
34
- ├── prompts/ # Prompt templates
35
- └── resources/ # MCP resources
36
- ```
37
-
38
- All directories are auto-discovered.
39
-
40
- ## Documentation
41
-
42
- - [Getting Started](https://veryfront.com/docs/framework)
43
- - [Agents](https://veryfront.com/docs/framework/agents)
44
- - [Tools](https://veryfront.com/docs/framework/tools)
45
- - [Workflows](https://veryfront.com/docs/framework/workflows)
46
- - [MCP Server](https://veryfront.com/docs/framework/mcp)
47
-
48
- ## Community
49
-
50
- - [Discord](https://discord.gg/veryfront)
51
- - [X](https://x.com/veryfrontdev)
52
- - [GitHub Discussions](https://github.com/veryfront/veryfront/discussions)
53
-
54
- ## Contributing
55
-
56
- See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
27
+ ## Releasing
57
28
 
58
- ## License
29
+ Create a new release with `gh release create vX.X.X`. The publish workflow runs automatically and takes ~4-5 minutes:
59
30
 
60
- MIT
31
+ 1. Builds native binaries for 5 platforms (macOS arm64/x64, Linux x64/arm64, Windows x64)
32
+ 2. Publishes to npm with provenance
33
+ 3. Creates GitHub releases in both repos
34
+ 4. Updates Homebrew formula
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.0.84",
3
+ "version": "0.0.86",
4
4
  "nodeModulesDir": "auto",
5
5
  "exclude": [
6
6
  "npm/",
@@ -123,9 +123,9 @@ export function renderList(state, options = {}) {
123
123
  }
124
124
  }
125
125
  if (start > 0)
126
- lines.unshift(` ${dim("more above")}`);
126
+ lines.unshift(` ${dim("↑")} ${dim("more above")}`);
127
127
  if (end < state.items.length)
128
- lines.push(` ${dim("more below")}`);
128
+ lines.push(` ${dim("↓")} ${dim("more below")}`);
129
129
  return lines.join("\n");
130
130
  }
131
131
  /**
@@ -35,7 +35,7 @@ export interface App {
35
35
  */
36
36
  export declare function createApp(config: AppConfig): App;
37
37
  /**
38
- * Show startup animation
38
+ * Show startup animation with boxed view and shimmer effect
39
39
  */
40
40
  export declare function showStartup(steps: string[]): Promise<void>;
41
41
  export type { AppState } from "./state.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/app/index.ts"],"names":[],"mappings":"AA2BA,OAAO,EAEL,KAAK,QAAQ,EAcb,KAAK,YAAY,EAOlB,MAAM,YAAY,CAAC;AASpB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,GAAG;IAClB,oBAAoB;IACpB,KAAK,IAAI,IAAI,CAAC;IACd,wCAAwC;IACxC,IAAI,IAAI,IAAI,CAAC;IACb,mBAAmB;IACnB,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,wBAAwB;IACxB,QAAQ,IAAI,QAAQ,CAAC;IACrB,8BAA8B;IAC9B,MAAM,IAAI,IAAI,CAAC;IACf,uBAAuB;IACvB,cAAc,IAAI,IAAI,CAAC;IACvB,mBAAmB;IACnB,QAAQ,IAAI,IAAI,CAAC;IACjB,mBAAmB;IACnB,WAAW,IAAI,IAAI,CAAC;IACpB,uCAAuC;IACvC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,qDAAqD;IACrD,gBAAgB,IAAI,MAAM,IAAI,CAAC;CAChC;AAuMD;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG,CAymChD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuChE;AAED,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/app/index.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,QAAQ,EAcb,KAAK,YAAY,EAQlB,MAAM,YAAY,CAAC;AASpB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,GAAG;IAClB,oBAAoB;IACpB,KAAK,IAAI,IAAI,CAAC;IACd,wCAAwC;IACxC,IAAI,IAAI,IAAI,CAAC;IACb,mBAAmB;IACnB,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,wBAAwB;IACxB,QAAQ,IAAI,QAAQ,CAAC;IACrB,8BAA8B;IAC9B,MAAM,IAAI,IAAI,CAAC;IACf,uBAAuB;IACvB,cAAc,IAAI,IAAI,CAAC;IACvB,mBAAmB;IACnB,QAAQ,IAAI,IAAI,CAAC;IACjB,mBAAmB;IACnB,WAAW,IAAI,IAAI,CAAC;IACpB,uCAAuC;IACvC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,qDAAqD;IACrD,gBAAgB,IAAI,MAAM,IAAI,CAAC;CAChC;AAuMD;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG,CA4mChD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhE;AAED,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC"}
@@ -11,12 +11,14 @@ import { join } from "../../platform/compat/path/index.js";
11
11
  import { getRuntimeEnv } from "../../config/runtime-env.js";
12
12
  import { getStdinReader, setRawMode } from "../../platform/compat/stdin.js";
13
13
  import { cursor, screen, SPINNER_FRAMES } from "../ui/ansi.js";
14
- import { brand, dim, success } from "../ui/colors.js";
14
+ import { brand, dim } from "../ui/colors.js";
15
+ import { getTerminalWidth } from "../ui/layout.js";
15
16
  import { moveDown, moveUp, selectByNumber } from "./components/list-select.js";
16
17
  import { renderDashboard, renderEmptyState } from "./views/dashboard.js";
18
+ import { createStartupState, incrementFrame, renderStartup, setStepActive, } from "./views/startup.js";
17
19
  import { openInBrowser, openInIDE, openInStudio, openMCPSettings } from "./actions.js";
18
20
  import { initCommand } from "../commands/init/init-command.js";
19
- import { addLog, createInitialState, endInput, getActiveSelection, goBack, navigateTo, scrollLogs, setActiveList, setExamples, setProjects, setTemplates, startInput, toggleLogsExpanded, updateActiveList, updateInputValue, updateMCP, updateRemote, updateServer, } from "./state.js";
21
+ import { addLog, createInitialState, endInput, getActiveSelection, goBack, navigateTo, scrollLogs, setActiveList, setExamples, setProjects, setTemplates, startInput, toggleHelp, toggleLogsExpanded, updateActiveList, updateInputValue, updateMCP, updateRemote, updateServer, } from "./state.js";
20
22
  import { handleInputKey, renderInput, renderLogs } from "./components/inline-input.js";
21
23
  import { login, logout, validateToken } from "../auth/login.js";
22
24
  import { readToken } from "../auth/token-store.js";
@@ -430,10 +432,12 @@ export function createApp(config) {
430
432
  content = renderDashboard(state);
431
433
  }
432
434
  const parts = [content];
435
+ // Divider width matches the box in dashboard
436
+ const dividerWidth = Math.min(getTerminalWidth() - 4, 80);
433
437
  if (state.logs.length > 0) {
434
438
  const logsHeader = state.logsExpanded ? "▼ Logs" : "▶ Logs";
435
439
  parts.push("");
436
- parts.push(` ${dim("─".repeat(60))}`);
440
+ parts.push(dim("─".repeat(dividerWidth)));
437
441
  parts.push(` ${dim(logsHeader)} ${dim(`(${state.logs.length})`)} ${dim("l")} ${dim("toggle")} ${state.logsExpanded ? `${dim("↑↓")} ${dim("scroll")}` : ""}`);
438
442
  parts.push(renderLogs(state.logs, {
439
443
  maxLines: state.logsExpanded ? 15 : 3,
@@ -443,13 +447,13 @@ export function createApp(config) {
443
447
  }
444
448
  if (state.input.active) {
445
449
  parts.push("");
446
- parts.push(` ${dim("─".repeat(60))}`);
450
+ parts.push(dim("─".repeat(dividerWidth)));
447
451
  parts.push(renderInput(state.input));
448
452
  }
449
453
  if (!isInteractiveMode)
450
454
  return;
451
455
  write(cursor.moveTo(1, 1) + screen.clearDown);
452
- write(parts.join("\n"));
456
+ write("\n" + parts.join("\n"));
453
457
  }
454
458
  function update(updater) {
455
459
  state = updater(state);
@@ -792,7 +796,7 @@ export function createApp(config) {
792
796
  return;
793
797
  }
794
798
  if (key === "?") {
795
- update(navigateTo("help"));
799
+ update(toggleHelp());
796
800
  return;
797
801
  }
798
802
  if (key === "m" && state.mcp.enabled) {
@@ -1212,40 +1216,29 @@ export function createApp(config) {
1212
1216
  };
1213
1217
  }
1214
1218
  /**
1215
- * Show startup animation
1219
+ * Show startup animation with boxed view and shimmer effect
1216
1220
  */
1217
1221
  export async function showStartup(steps) {
1218
1222
  const write = (text) => writeStdout(text);
1219
1223
  write(screen.altOn + cursor.hide);
1224
+ let startupState = createStartupState(steps);
1225
+ // Show each step with spinning avatar animation
1220
1226
  for (let i = 0; i < steps.length; i++) {
1221
- const step = steps[i];
1222
- const completed = steps.slice(0, i).map((s) => ` ${success("✓")} ${dim(s)}`);
1223
- const current = ` ${brand("●")} ${step}`;
1224
- const pending = steps.slice(i + 1).map((s) => ` ${dim("○")} ${dim(s)}`);
1225
- const content = [
1226
- "",
1227
- ` ${brand("Veryfront")} ${dim("starting...")}`,
1228
- "",
1229
- ...completed,
1230
- current,
1231
- ...pending,
1232
- "",
1233
- ].join("\n");
1234
- write(cursor.moveTo(1, 1) + screen.clearDown + content);
1235
- await new Promise((r) => dntShim.setTimeout(r, 200));
1227
+ startupState = setStepActive(startupState, i);
1228
+ // Animate spinning avatar (16 frames at 60ms = ~1s per step for full rotation)
1229
+ const framesPerStep = 16;
1230
+ for (let f = 0; f < framesPerStep; f++) {
1231
+ write(cursor.moveTo(1, 1) + screen.clearDown + "\n" + renderStartup(startupState));
1232
+ startupState = incrementFrame(startupState);
1233
+ await new Promise((r) => dntShim.setTimeout(r, 60));
1234
+ }
1236
1235
  }
1237
- const allComplete = steps.map((s) => ` ${success("✓")} ${dim(s)}`);
1238
- const finalContent = [
1239
- "",
1240
- ` ${brand("Veryfront")} ${success("ready")}`,
1241
- "",
1242
- ...allComplete,
1243
- "",
1244
- ].join("\n");
1245
- write(cursor.moveTo(1, 1) + screen.clearDown + finalContent);
1246
- await new Promise((r) => dntShim.setTimeout(r, 300));
1236
+ // Mark all steps done - logo fills up and holds before transitioning
1237
+ startupState = setStepActive(startupState, steps.length);
1238
+ write(cursor.moveTo(1, 1) + screen.clearDown + "\n" + renderStartup(startupState));
1239
+ await new Promise((r) => dntShim.setTimeout(r, 400));
1247
1240
  // Don't exit alternate screen - let app.start() continue in it
1248
- // This prevents a flash when transitioning to the dashboard
1241
+ // Dashboard takes over directly from here
1249
1242
  }
1250
1243
  export * from "./state.js";
1251
1244
  export * from "./actions.js";
@@ -84,6 +84,8 @@ export interface AppState {
84
84
  authProviderIndex: number;
85
85
  /** New project option index (0=template, 1=example, 2=scratch) */
86
86
  newProjectIndex: number;
87
+ /** Show expanded help */
88
+ showHelp: boolean;
87
89
  }
88
90
  export declare function createInitialState(): AppState;
89
91
  export type StateUpdater = (state: AppState) => AppState;
@@ -117,6 +119,7 @@ export declare function endInput(): StateUpdater;
117
119
  export declare function addLog(level: LogEntry["level"], message: string, meta?: LogMeta): StateUpdater;
118
120
  export declare function clearLogs(): StateUpdater;
119
121
  export declare function toggleLogsExpanded(): StateUpdater;
122
+ export declare function toggleHelp(): StateUpdater;
120
123
  export declare function scrollLogs(direction: "up" | "down"): StateUpdater;
121
124
  export declare function getActiveSelection(state: AppState): ListItem<ProjectInfo> | undefined;
122
125
  //# sourceMappingURL=state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/app/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAK7E,MAAM,MAAM,OAAO,GACf,WAAW,GACX,gBAAgB,GAChB,aAAa,GACb,WAAW,GACX,UAAU,GACV,MAAM,GACN,MAAM,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9C,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAE7B,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IAEpB,QAAQ,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IACvC,QAAQ,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IACvC,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IAExC,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,gBAAgB,CAAC;IACrE,eAAe,EAAE,WAAW,GAAG,IAAI,CAAC;IAEpC,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;QACrD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IAEF,KAAK,EAAE,UAAU,CAAC;IAElB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAElB,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,kBAAkB,IAAI,QAAQ,CAiD7C;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAEzD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9C,YAAY,CAYd;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACpE,YAAY,CAYd;AAED,wBAAgB,YAAY,CAC1B,SAAS,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,GAClE,YAAY,CAYd;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAExE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,YAAY,CAElE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,YAAY,CAEvE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,CAEtD;AAED,wBAAgB,MAAM,IAAI,YAAY,CAMrC;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,gBAAgB,GAC7D,YAAY,CAEd;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,eAAe,CAAC,WAAW,CAAC,GAC5E,YAAY,CAOd;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,YAAY,CAWvE;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,GAClC,YAAY,CAEd;AAED,wBAAgB,WAAW,IAAI,YAAY,CAW1C;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,EACrB,YAAY,CAAC,EAAE,MAAM,GACpB,YAAY,CAYd;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAK/E;AAED,wBAAgB,QAAQ,IAAI,YAAY,CAYvC;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY,CAM9F;AAED,wBAAgB,SAAS,IAAI,YAAY,CAExC;AAED,wBAAgB,kBAAkB,IAAI,YAAY,CAMjD;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,YAAY,CAejE;AAqBD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,GACd,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAKnC"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/app/state.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,7 @@ export function createInitialState() {
49
49
  logScroll: 0,
50
50
  authProviderIndex: 0,
51
51
  newProjectIndex: 0,
52
+ showHelp: false,
52
53
  };
53
54
  }
54
55
  export function setProjects(projects) {
@@ -192,6 +193,9 @@ export function toggleLogsExpanded() {
192
193
  logScroll: 0,
193
194
  });
194
195
  }
196
+ export function toggleHelp() {
197
+ return (state) => ({ ...state, showHelp: !state.showHelp });
198
+ }
195
199
  export function scrollLogs(direction) {
196
200
  return (state) => {
197
201
  if (!state.logsExpanded)
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../../../src/src/cli/app/views/dashboard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CA4EvD;AAsFD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAY5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAazC"}
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../../../src/src/cli/app/views/dashboard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CA4EvD;AAmFD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAY5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
@@ -4,7 +4,7 @@
4
4
  * Main view showing server status, projects, and quick actions.
5
5
  */
6
6
  import { box } from "../../ui/box.js";
7
- import { brand, dim, error, muted, success } from "../../ui/colors.js";
7
+ import { brand, dim, error, muted } from "../../ui/colors.js";
8
8
  import { getTerminalWidth } from "../../ui/layout.js";
9
9
  import { getAgentFaceWithText } from "../../ui/dot-matrix.js";
10
10
  import { renderList } from "../components/list-select.js";
@@ -21,7 +21,7 @@ export function renderDashboard(state) {
21
21
  const hasRemoteProjects = state.remote.user && state.remote.projects.length > 0;
22
22
  if (hasProjects) {
23
23
  const isActive = state.activeList === "projects";
24
- lines.push(renderSection("Local Projects", state.projects.items.length, isActive));
24
+ lines.push(renderSection("Local", state.projects.items.length, isActive));
25
25
  lines.push(renderList(state.projects, {
26
26
  maxWidth: maxListWidth,
27
27
  visibleCount: 5,
@@ -36,9 +36,9 @@ export function renderDashboard(state) {
36
36
  const start = state.remote.scrollOffset;
37
37
  const end = Math.min(start + visibleCount, state.remote.projects.length);
38
38
  const visibleProjects = state.remote.projects.slice(start, end);
39
- lines.push(renderSection("Remote Projects", state.remote.projects.length, isRemoteActive));
39
+ lines.push(renderSection("Remote", state.remote.projects.length, isRemoteActive));
40
40
  if (start > 0) {
41
- lines.push(` ${dim("more above")}`);
41
+ lines.push(` ${dim("↑")} ${dim("more above")}`);
42
42
  }
43
43
  visibleProjects.forEach((p, i) => {
44
44
  const actualIndex = start + i;
@@ -54,7 +54,7 @@ export function renderDashboard(state) {
54
54
  lines.push(`${cursor} ${num} ${label}`);
55
55
  });
56
56
  if (end < state.remote.projects.length) {
57
- lines.push(` ${dim("more below")}`);
57
+ lines.push(` ${dim("↓")} ${dim("more below")}`);
58
58
  }
59
59
  lines.push("");
60
60
  }
@@ -72,24 +72,24 @@ export function renderDashboard(state) {
72
72
  return lines.join("\n");
73
73
  }
74
74
  /**
75
- * Render the banner with agent face and server info
75
+ * Render the banner with agent face and server info inside a box
76
76
  */
77
77
  function renderBanner(state) {
78
- const serverDot = state.server.running ? success("●") : error("●");
79
- const mcpDot = state.mcp.enabled ? success("●") : dim("○");
78
+ const termWidth = Math.min(getTerminalWidth() - 4, 80);
80
79
  const textLines = [];
81
- textLines.push(`${serverDot} ${dim("Server running")}`);
82
- textLines.push(` ${brand(state.server.url)}`);
83
- if (state.mcp.enabled) {
84
- textLines.push(`${mcpDot} ${dim("MCP")}`);
85
- if (state.mcp.transport === "http") {
86
- const port = state.mcp.httpPort ?? 9999;
87
- textLines.push(` ${brand(`http://veryfront.me:${port}/mcp`)}`);
88
- }
89
- else {
90
- textLines.push(` ${dim("stdio")}`);
91
- }
80
+ textLines.push("");
81
+ textLines.push(`${brand("Veryfront Code")} ${dim("is now running")}`);
82
+ textLines.push("");
83
+ // Server URL and MCP URL - always reserve both lines to prevent jumps
84
+ textLines.push(`${dim("Url")} ${brand(state.server.url)}`);
85
+ if (state.mcp.enabled && state.mcp.transport === "http") {
86
+ const port = state.mcp.httpPort ?? 9999;
87
+ textLines.push(`${dim("Mcp")} ${brand(`http://veryfront.me:${port}/mcp`)}`);
88
+ }
89
+ else {
90
+ textLines.push("");
92
91
  }
92
+ // Errors/warnings on separate line if any
93
93
  const { errors, warnings } = state.server;
94
94
  if (errors > 0 || warnings > 0) {
95
95
  const parts = [];
@@ -99,50 +99,49 @@ function renderBanner(state) {
99
99
  parts.push(muted(`${warnings} warnings`));
100
100
  textLines.push(parts.join(" "));
101
101
  }
102
- return getAgentFaceWithText(textLines, {
102
+ // Pad to 7 text lines (matching avatar height) for consistent title position
103
+ while (textLines.length < 7) {
104
+ textLines.push("");
105
+ }
106
+ const content = getAgentFaceWithText(textLines, {
103
107
  litColor: "\x1b[38;2;252;143;93m", // Veryfront brand orange
104
108
  });
109
+ return box(content, {
110
+ style: "rounded",
111
+ width: termWidth,
112
+ paddingX: 2,
113
+ paddingY: 1,
114
+ borderColor: "\x1b[2m", // Dim to match footer
115
+ });
105
116
  }
106
117
  /**
107
118
  * Render a section header
108
119
  */
109
- function renderSection(title, count, isActive = true) {
120
+ function renderSection(title, _count, isActive = true) {
110
121
  const indicator = isActive ? brand("›") : " ";
111
122
  const titleText = isActive ? title : dim(title);
112
- return ` ${indicator} ${titleText} ${dim(`(${count})`)}`;
123
+ return ` ${indicator} ${titleText}`;
113
124
  }
114
125
  /**
115
126
  * Render the help bar at the bottom
116
127
  */
117
128
  function renderHelpBar(state) {
118
- const parts = [];
119
- const hasProjects = state.projects.items.length > 0;
120
- const hasExamples = state.examples.items.length > 0;
121
- const hasRemoteProjects = state.remote.user && state.remote.projects.length > 0;
122
- // Count sections for tab switching
123
- const sectionCount = [hasProjects, hasExamples, hasRemoteProjects].filter(Boolean).length;
124
- if (sectionCount > 1) {
125
- parts.push(dim("tab switch"));
126
- }
127
- parts.push(dim("↑↓ nav"));
128
- if (hasProjects || hasExamples || hasRemoteProjects) {
129
- parts.push(dim("o open"), dim("s studio"), dim("i ide"));
129
+ // Minimal by default, ? reveals all
130
+ if (!state.showHelp) {
131
+ const userInfo = state.remote.user ? ` ${dim("-")} ${brand(state.remote.user.email)}` : "";
132
+ return ` ${dim("↑↓ select enter open ? more q quit")}${userInfo}`;
130
133
  }
134
+ // Expanded help
135
+ const lines = [];
136
+ lines.push(` ${dim("o")} open ${dim("s")} studio ${dim("i")} ide`);
131
137
  if (!state.remote.user) {
132
- parts.push(dim("a login"));
138
+ lines.push(` ${dim("n")} new ${dim("a")} login`);
133
139
  }
134
140
  else {
135
- // Show context-aware actions based on active list
136
- if (state.activeList === "projects") {
137
- parts.push(dim("p pull"), dim("u push"));
138
- }
139
- else if (state.activeList === "remoteProjects") {
140
- parts.push(dim("p pull"));
141
- }
142
- parts.push(dim("n new"), dim("x logout"));
141
+ lines.push(` ${dim("n")} new ${dim("p")} pull ${dim("u")} push ${dim("x")} logout`);
143
142
  }
144
- parts.push(dim("? help"), dim("q quit"));
145
- return ` ${parts.join(" ")}`;
143
+ lines.push(` ${dim("? hide q quit")}`);
144
+ return lines.join("\n");
146
145
  }
147
146
  /**
148
147
  * Render a boxed dashboard (alternative style)
@@ -163,16 +162,5 @@ export function renderDashboardBoxed(state) {
163
162
  * Render empty state when no projects found
164
163
  */
165
164
  export function renderEmptyState() {
166
- return [
167
- "",
168
- ` ${dim("No projects found.")}`,
169
- "",
170
- ` ${dim("Get started:")}`,
171
- ` ${brand("[n]")} Create a new project`,
172
- ` ${brand("[t]")} Browse templates`,
173
- "",
174
- ` ${dim("Or run with a project directory:")}`,
175
- ` ${muted("deno task start --project ./my-project")}`,
176
- "",
177
- ].join("\n");
165
+ return `\n ${dim("No projects.")} ${brand("n")} ${dim("to create")}\n`;
178
166
  }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Startup View
3
+ *
4
+ * Shows loading progress with consistent box sizing.
5
+ * Displays avatar, title, and step checklist.
6
+ */
7
+ export interface StartupStep {
8
+ label: string;
9
+ status: "pending" | "active" | "done";
10
+ }
11
+ export interface StartupState {
12
+ steps: StartupStep[];
13
+ serverUrl?: string;
14
+ mcpUrl?: string;
15
+ ready: boolean;
16
+ /** Animation frame counter for shimmer effect */
17
+ frame: number;
18
+ }
19
+ /**
20
+ * Render the startup view inside a consistent-sized box
21
+ */
22
+ export declare function renderStartup(state: StartupState): string;
23
+ /**
24
+ * Create initial startup state with steps
25
+ */
26
+ export declare function createStartupState(stepLabels: string[]): StartupState;
27
+ /**
28
+ * Increment animation frame for shimmer effect
29
+ */
30
+ export declare function incrementFrame(state: StartupState): StartupState;
31
+ /**
32
+ * Set a step to active
33
+ */
34
+ export declare function setStepActive(state: StartupState, index: number): StartupState;
35
+ /**
36
+ * Mark all steps done and set ready
37
+ */
38
+ export declare function setStartupReady(state: StartupState, serverUrl: string, mcpUrl?: string): StartupState;
39
+ //# sourceMappingURL=startup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../../../../../src/src/cli/app/views/startup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAqDzD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,YAAY,CAMrE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAEhE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAO9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,YAAY,CAOd"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Startup View
3
+ *
4
+ * Shows loading progress with consistent box sizing.
5
+ * Displays avatar, title, and step checklist.
6
+ */
7
+ import { box } from "../../ui/box.js";
8
+ import { brand, dim, shimmer } from "../../ui/colors.js";
9
+ // Dim orange for completed steps - matches the trailing dots in spinning animation
10
+ const dimOrange = (text) => `\x1b[38;2;180;100;65m${text}\x1b[0m`;
11
+ import { getTerminalWidth } from "../../ui/layout.js";
12
+ import { getAgentFaceWithText, getSpinningAgentFace } from "../../ui/dot-matrix.js";
13
+ /**
14
+ * Render the startup view inside a consistent-sized box
15
+ */
16
+ export function renderStartup(state) {
17
+ const termWidth = Math.min(getTerminalWidth() - 4, 80);
18
+ const textLines = [];
19
+ if (state.ready) {
20
+ // Running state - always reserve space for both URL lines to prevent jumps
21
+ textLines.push("");
22
+ textLines.push(`${brand("Veryfront Code")} ${dim("is now running")}`);
23
+ textLines.push("");
24
+ textLines.push(state.serverUrl ? `${dim("Url")} ${brand(state.serverUrl)}` : "");
25
+ textLines.push(state.mcpUrl ? `${dim("Mcp")} ${brand(state.mcpUrl)}` : "");
26
+ }
27
+ else {
28
+ // Loading state - match ready state layout
29
+ textLines.push("");
30
+ textLines.push(`${brand("Veryfront Code")} ${dim("starting...")}`);
31
+ textLines.push("");
32
+ for (const step of state.steps) {
33
+ if (step.status === "done") {
34
+ // Completed: dim orange (fades into background, coherent with avatar)
35
+ textLines.push(`${dimOrange("●")} ${dimOrange(step.label)}`);
36
+ }
37
+ else if (step.status === "active") {
38
+ // Active: bright orange dot with shimmer text
39
+ textLines.push(`${brand("●")} ${shimmer(step.label, state.frame)}`);
40
+ }
41
+ else {
42
+ // Pending: gray empty circle
43
+ textLines.push(`${dim("○")} ${dim(step.label)}`);
44
+ }
45
+ }
46
+ }
47
+ // Pad to 7 text lines (matching avatar height) for consistent title position
48
+ while (textLines.length < 7) {
49
+ textLines.push("");
50
+ }
51
+ // Use spinning avatar during loading, static when ready or all steps done
52
+ const allStepsDone = state.steps.every((s) => s.status === "done");
53
+ const content = state.ready || allStepsDone
54
+ ? getAgentFaceWithText(textLines, {
55
+ litColor: "\x1b[38;2;252;143;93m", // Veryfront brand orange
56
+ })
57
+ : getSpinningAgentFace(textLines, state.frame, {
58
+ litColor: "\x1b[38;2;252;143;93m", // Veryfront brand orange
59
+ });
60
+ return box(content, {
61
+ style: "rounded",
62
+ width: termWidth,
63
+ paddingX: 2,
64
+ paddingY: 1,
65
+ borderColor: "\x1b[2m", // Dim to match footer
66
+ });
67
+ }
68
+ /**
69
+ * Create initial startup state with steps
70
+ */
71
+ export function createStartupState(stepLabels) {
72
+ return {
73
+ steps: stepLabels.map((label) => ({ label, status: "pending" })),
74
+ ready: false,
75
+ frame: 0,
76
+ };
77
+ }
78
+ /**
79
+ * Increment animation frame for shimmer effect
80
+ */
81
+ export function incrementFrame(state) {
82
+ return { ...state, frame: state.frame + 1 };
83
+ }
84
+ /**
85
+ * Set a step to active
86
+ */
87
+ export function setStepActive(state, index) {
88
+ const steps = state.steps.map((step, i) => ({
89
+ ...step,
90
+ status: i < index ? "done" : i === index ? "active" : "pending",
91
+ }));
92
+ return { ...state, steps };
93
+ }
94
+ /**
95
+ * Mark all steps done and set ready
96
+ */
97
+ export function setStartupReady(state, serverUrl, mcpUrl) {
98
+ const steps = state.steps.map((step) => ({
99
+ ...step,
100
+ status: "done",
101
+ }));
102
+ return { ...state, steps, serverUrl, mcpUrl, ready: true };
103
+ }
@@ -20,4 +20,12 @@ export declare const successBold: (text: string) => string;
20
20
  export declare const errorBold: (text: string) => string;
21
21
  export { RESET as reset };
22
22
  export declare function animatedMatrix(frame: number): string;
23
+ /**
24
+ * Apply shimmer effect to text - creates a wave of brightness moving across
25
+ * @param text The text to shimmer
26
+ * @param frame Current animation frame (increments over time)
27
+ * @param waveWidth Width of the bright wave (default: 3 characters)
28
+ * @returns Text with shimmer effect applied
29
+ */
30
+ export declare function shimmer(text: string, frame: number, waveWidth?: number): string;
23
31
  //# sourceMappingURL=colors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/ui/colors.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;AAE7D,wBAAgB,aAAa,IAAI,UAAU,CA+B1C;AAED,wBAAgB,cAAc,IAAI,OAAO,CAExC;AASD,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAgED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGzD;AAMD,eAAO,MAAM,KAAK,SAJsC,MAAM,WAIxB,CAAC;AACvC,eAAO,MAAM,OAAO,SAJsC,MAAM,WAItB,CAAC;AAE3C,eAAO,MAAM,OAAO,SAPoC,MAAM,WAOvB,CAAC;AACxC,eAAO,MAAM,KAAK,SARsC,MAAM,WAQzB,CAAC;AACtC,eAAO,MAAM,OAAO,SAToC,MAAM,WASvB,CAAC;AACxC,eAAO,MAAM,KAAK,SAVsC,MAAM,WAUvB,CAAC;AAExC,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,WAA+B,CAAC;AACjE,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,WAA+B,CAAC;AAChE,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,WAA+B,CAAC;AACnE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,WAA+B,CAAC;AAEtE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,WAAsB,CAAC;AAC7D,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,WAAwB,CAAC;AACjE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,WAAsB,CAAC;AAE7D,OAAO,EAAE,KAAK,IAAI,KAAK,EAAE,CAAC;AAS1B,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGpD"}
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/ui/colors.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;AAE7D,wBAAgB,aAAa,IAAI,UAAU,CA+B1C;AAED,wBAAgB,cAAc,IAAI,OAAO,CAExC;AASD,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAgED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGzD;AAMD,eAAO,MAAM,KAAK,SAJsC,MAAM,WAIxB,CAAC;AACvC,eAAO,MAAM,OAAO,SAJsC,MAAM,WAItB,CAAC;AAE3C,eAAO,MAAM,OAAO,SAPoC,MAAM,WAOvB,CAAC;AACxC,eAAO,MAAM,KAAK,SARsC,MAAM,WAQzB,CAAC;AACtC,eAAO,MAAM,OAAO,SAToC,MAAM,WASvB,CAAC;AACxC,eAAO,MAAM,KAAK,SAVsC,MAAM,WAUvB,CAAC;AAExC,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,WAA+B,CAAC;AACjE,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,WAA+B,CAAC;AAChE,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,WAA+B,CAAC;AACnE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,WAA+B,CAAC;AAEtE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,WAAsB,CAAC;AAC7D,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,WAAwB,CAAC;AACjE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,WAAsB,CAAC;AAE7D,OAAO,EAAE,KAAK,IAAI,KAAK,EAAE,CAAC;AAS1B,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,MAAM,CA4B1E"}