@seyuna/cli 1.0.0-canary.2 → 1.0.0-canary.21

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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/esm/_dnt.polyfills.d.ts +101 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +127 -0
  6. package/esm/_dnt.shims.d.ts +6 -0
  7. package/esm/_dnt.shims.d.ts.map +1 -0
  8. package/esm/_dnt.shims.js +61 -0
  9. package/esm/deno.d.ts +27 -0
  10. package/esm/deno.d.ts.map +1 -0
  11. package/esm/deno.js +30 -0
  12. package/esm/package.json +3 -0
  13. package/esm/src/config/init.d.ts +8 -0
  14. package/esm/src/config/init.d.ts.map +1 -0
  15. package/esm/src/config/init.js +68 -0
  16. package/esm/src/config/types.d.ts +25 -0
  17. package/esm/src/config/types.d.ts.map +1 -0
  18. package/esm/src/config/types.js +18 -0
  19. package/esm/src/helpers/cli.d.ts +45 -0
  20. package/esm/src/helpers/cli.d.ts.map +1 -0
  21. package/esm/src/helpers/cli.js +72 -0
  22. package/esm/src/helpers/fs.d.ts +35 -0
  23. package/esm/src/helpers/fs.d.ts.map +1 -0
  24. package/esm/src/helpers/fs.js +83 -0
  25. package/esm/src/helpers/styles.d.ts +54 -0
  26. package/esm/src/helpers/styles.d.ts.map +1 -0
  27. package/esm/src/helpers/styles.js +71 -0
  28. package/esm/src/main.d.ts +11 -0
  29. package/esm/src/main.d.ts.map +1 -0
  30. package/esm/src/main.js +110 -0
  31. package/esm/src/ui/compile.d.ts +21 -0
  32. package/esm/src/ui/compile.d.ts.map +1 -0
  33. package/esm/src/ui/compile.js +193 -0
  34. package/esm/src/ui/default.d.ts +8 -0
  35. package/esm/src/ui/default.d.ts.map +1 -0
  36. package/esm/src/ui/default.js +65 -0
  37. package/esm/src/ui/global.css.d.ts +11 -0
  38. package/esm/src/ui/global.css.d.ts.map +1 -0
  39. package/esm/src/ui/global.css.js +104 -0
  40. package/esm/src/ui/types.d.ts +77 -0
  41. package/esm/src/ui/types.d.ts.map +1 -0
  42. package/esm/src/ui/types.js +41 -0
  43. package/package.json +32 -18
  44. package/bin/seyuna.js +0 -10
  45. package/install.js +0 -42
@@ -0,0 +1,35 @@
1
+ import type { Config } from "../config/types.js";
2
+ /**
3
+ * Constructs an absolute or relative path from a filename and an output directory.
4
+ *
5
+ * @param fileName - The name of the file (e.g., "styles.css")
6
+ * @param outputDir - The target directory (e.g., "dist")
7
+ * @throws Error if fileName or outputDir are empty strings
8
+ * @returns The joined path string
9
+ */
10
+ export declare function createPathFromFileName(fileName: string, outputDir: string): string;
11
+ /**
12
+ * Reads the text content of a file at the specified path.
13
+ *
14
+ * @param path - Path to the file to be read
15
+ * @throws Error with a descriptive message if the file is not found or cannot be read
16
+ * @returns The file content as a string
17
+ */
18
+ export declare function readFile(path: string): Promise<string>;
19
+ /**
20
+ * Saves content to a file, ensuring the parent directory exists.
21
+ *
22
+ * @param path - The target file path
23
+ * @param content - The content to write (string or Uint8Array)
24
+ * @returns A promise that resolves when the file is written
25
+ */
26
+ export declare function saveFile(path: string, content: string | Uint8Array): Promise<void>;
27
+ /**
28
+ * Loads and parses the 'seyuna.json' configuration file from the current directory.
29
+ * Merges the user configuration with the default UI settings.
30
+ *
31
+ * @throws Error if 'seyuna.json' is missing or contains invalid JSON
32
+ * @returns The merged configuration object
33
+ */
34
+ export declare function loadSeyunaUserConfig(): Promise<Config>;
35
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../src/src/helpers/fs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAIjD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,CAQR;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS5D;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,UAAU,GAC3B,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAuB5D"}
@@ -0,0 +1,83 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { dirname, join } from "@jsr/std__path";
3
+ import { ensureDir } from "@jsr/std__fs";
4
+ import { mergeConfig } from "../config/types.js";
5
+ import { UI_CONFIGURATION } from "../ui/default.js";
6
+ /**
7
+ * Constructs an absolute or relative path from a filename and an output directory.
8
+ *
9
+ * @param fileName - The name of the file (e.g., "styles.css")
10
+ * @param outputDir - The target directory (e.g., "dist")
11
+ * @throws Error if fileName or outputDir are empty strings
12
+ * @returns The joined path string
13
+ */
14
+ export function createPathFromFileName(fileName, outputDir) {
15
+ if (!fileName.trim()) {
16
+ throw new Error("File name cannot be empty");
17
+ }
18
+ if (!outputDir.trim()) {
19
+ throw new Error("Output directory cannot be empty");
20
+ }
21
+ return join(outputDir, fileName);
22
+ }
23
+ /**
24
+ * Reads the text content of a file at the specified path.
25
+ *
26
+ * @param path - Path to the file to be read
27
+ * @throws Error with a descriptive message if the file is not found or cannot be read
28
+ * @returns The file content as a string
29
+ */
30
+ export async function readFile(path) {
31
+ try {
32
+ return await dntShim.Deno.readTextFile(path);
33
+ }
34
+ catch (error) {
35
+ if (error instanceof dntShim.Deno.errors.NotFound) {
36
+ throw new Error(`File not found at path: ${path}`);
37
+ }
38
+ throw new Error(`Failed to read file at ${path}: ${error instanceof Error ? error.message : "Unknown error"}`);
39
+ }
40
+ }
41
+ /**
42
+ * Saves content to a file, ensuring the parent directory exists.
43
+ *
44
+ * @param path - The target file path
45
+ * @param content - The content to write (string or Uint8Array)
46
+ * @returns A promise that resolves when the file is written
47
+ */
48
+ export async function saveFile(path, content) {
49
+ const dir = dirname(path);
50
+ await ensureDir(dir);
51
+ const data = typeof content === "string"
52
+ ? new TextEncoder().encode(content)
53
+ : content;
54
+ await dntShim.Deno.writeFile(path, data);
55
+ }
56
+ /**
57
+ * Loads and parses the 'seyuna.json' configuration file from the current directory.
58
+ * Merges the user configuration with the default UI settings.
59
+ *
60
+ * @throws Error if 'seyuna.json' is missing or contains invalid JSON
61
+ * @returns The merged configuration object
62
+ */
63
+ export async function loadSeyunaUserConfig() {
64
+ try {
65
+ const content = await readFile("seyuna.json");
66
+ const userConfig = JSON.parse(content);
67
+ /** @type {Config} Default fallback configuration */
68
+ const defaultConfig = {
69
+ license: undefined,
70
+ ui: UI_CONFIGURATION,
71
+ };
72
+ return mergeConfig(defaultConfig, userConfig);
73
+ }
74
+ catch (error) {
75
+ if (error instanceof Error && error.message.includes("File not found")) {
76
+ throw new Error("Could not find 'seyuna.json' in the current directory. Please run 'seyuna ui config --init' to generate it.");
77
+ }
78
+ if (error instanceof SyntaxError) {
79
+ throw new Error(`Failed to parse 'seyuna.json': ${error.message}`);
80
+ }
81
+ throw error;
82
+ }
83
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * A function that applies a color or style to a string.
3
+ */
4
+ export type ColorFunction = (text: string) => string;
5
+ /**
6
+ * Standard brand colors and styles for the Seyuna CLI.
7
+ * Provides a consistent visual identity across all command outputs.
8
+ */
9
+ export declare const Brand: {
10
+ /** Vibrant Spring Green - Primary brand color */
11
+ readonly primary: (text: string) => string;
12
+ /** Cyan - Secondary brand color */
13
+ readonly secondary: (text: string) => string;
14
+ /** Magenta - Accent color for highlights */
15
+ readonly accent: (text: string) => string;
16
+ /** Bold Green - Indicates successful operations */
17
+ readonly success: (text: string) => string;
18
+ /** Bold Red - Indicates errors or critical failures */
19
+ readonly error: (text: string) => string;
20
+ /** Bold Yellow - Indicates warnings or non-critical issues */
21
+ readonly warning: (text: string) => string;
22
+ /** Gray - For less important or decorative text */
23
+ readonly muted: (text: string) => string;
24
+ };
25
+ /**
26
+ * Interpolates between two hex colors to create a gradient effect on text.
27
+ *
28
+ * @param text - The string to apply the gradient to
29
+ * @param startRgb - Start color in hex format (e.g., 0x00FF87)
30
+ * @param endRgb - End color in hex format (e.g., 0x60EFFF)
31
+ * @returns The text with ANSI color codes applied per character
32
+ */
33
+ export declare function gradient(text: string, startRgb: number, endRgb: number): string;
34
+ /**
35
+ * Standard Seyuna gradient (Spring Green to Cyan).
36
+ * Used for logos and primary brand headings.
37
+ */
38
+ export declare const seyunaGradient: ColorFunction;
39
+ /**
40
+ * Branded Unicode symbols for consistent status reporting.
41
+ */
42
+ export declare const Symbols: {
43
+ /** Info icon (Cyan) */
44
+ readonly info: string;
45
+ /** Success icon (Green) */
46
+ readonly success: string;
47
+ /** Warning icon (Yellow) */
48
+ readonly warning: string;
49
+ /** Error icon (Red) */
50
+ readonly error: string;
51
+ /** Decorative arrow (Muted) */
52
+ readonly arrow: string;
53
+ };
54
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/src/helpers/styles.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,KAAK;IAChB,iDAAiD;6BACjC,MAAM;IAEtB,mCAAmC;+BACjB,MAAM;IAExB,4CAA4C;4BAC7B,MAAM;IAErB,mDAAmD;6BACnC,MAAM;IAEtB,uDAAuD;2BACzC,MAAM;IAEpB,8DAA8D;6BAC9C,MAAM;IAEtB,mDAAmD;2BACrC,MAAM;CAC4B,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAyB/E;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,aACO,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,OAAO;IAClB,uBAAuB;;IAGvB,2BAA2B;;IAG3B,4BAA4B;;IAG5B,uBAAuB;;IAGvB,+BAA+B;;CAEU,CAAC"}
@@ -0,0 +1,71 @@
1
+ import * as colors from "@jsr/std__fmt/colors";
2
+ /**
3
+ * Standard brand colors and styles for the Seyuna CLI.
4
+ * Provides a consistent visual identity across all command outputs.
5
+ */
6
+ export const Brand = {
7
+ /** Vibrant Spring Green - Primary brand color */
8
+ primary: (text) => colors.rgb24(text, 0x00FF87),
9
+ /** Cyan - Secondary brand color */
10
+ secondary: (text) => colors.rgb24(text, 0x60EFFF),
11
+ /** Magenta - Accent color for highlights */
12
+ accent: (text) => colors.rgb24(text, 0xFF00E5),
13
+ /** Bold Green - Indicates successful operations */
14
+ success: (text) => colors.bold(colors.green(text)),
15
+ /** Bold Red - Indicates errors or critical failures */
16
+ error: (text) => colors.bold(colors.red(text)),
17
+ /** Bold Yellow - Indicates warnings or non-critical issues */
18
+ warning: (text) => colors.bold(colors.yellow(text)),
19
+ /** Gray - For less important or decorative text */
20
+ muted: (text) => colors.gray(text),
21
+ };
22
+ /**
23
+ * Interpolates between two hex colors to create a gradient effect on text.
24
+ *
25
+ * @param text - The string to apply the gradient to
26
+ * @param startRgb - Start color in hex format (e.g., 0x00FF87)
27
+ * @param endRgb - End color in hex format (e.g., 0x60EFFF)
28
+ * @returns The text with ANSI color codes applied per character
29
+ */
30
+ export function gradient(text, startRgb, endRgb) {
31
+ const start = {
32
+ r: (startRgb >> 16) & 0xFF,
33
+ g: (startRgb >> 8) & 0xFF,
34
+ b: startRgb & 0xFF,
35
+ };
36
+ const end = {
37
+ r: (endRgb >> 16) & 0xFF,
38
+ g: (endRgb >> 8) & 0xFF,
39
+ b: endRgb & 0xFF,
40
+ };
41
+ const characters = Array.from(text);
42
+ const length = characters.length;
43
+ return characters.map((char, i) => {
44
+ // If text is 1 char long, use start color
45
+ const factor = length > 1 ? i / (length - 1) : 0;
46
+ const r = Math.round(start.r + factor * (end.r - start.r));
47
+ const g = Math.round(start.g + factor * (end.g - start.g));
48
+ const b = Math.round(start.b + factor * (end.b - start.b));
49
+ return colors.rgb24(char, (r << 16) | (g << 8) | b);
50
+ }).join("");
51
+ }
52
+ /**
53
+ * Standard Seyuna gradient (Spring Green to Cyan).
54
+ * Used for logos and primary brand headings.
55
+ */
56
+ export const seyunaGradient = (text) => gradient(text, 0x00FF87, 0x60EFFF);
57
+ /**
58
+ * Branded Unicode symbols for consistent status reporting.
59
+ */
60
+ export const Symbols = {
61
+ /** Info icon (Cyan) */
62
+ info: Brand.secondary("ℹ"),
63
+ /** Success icon (Green) */
64
+ success: Brand.success("✔"),
65
+ /** Warning icon (Yellow) */
66
+ warning: Brand.warning("⚠"),
67
+ /** Error icon (Red) */
68
+ error: Brand.error("✖"),
69
+ /** Decorative arrow (Muted) */
70
+ arrow: Brand.muted("›"),
71
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Seyuna CLI - Entrypoint
3
+ *
4
+ * This is the main orchestrator for the Seyuna Command Line Interface.
5
+ * It defines the command hierarchy and provides the branded "Premium"
6
+ * help screens.
7
+ *
8
+ * @module
9
+ */
10
+ import "../_dnt.polyfills.js";
11
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/src/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,sBAAsB,CAAC"}
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Seyuna CLI - Entrypoint
4
+ *
5
+ * This is the main orchestrator for the Seyuna Command Line Interface.
6
+ * It defines the command hierarchy and provides the branded "Premium"
7
+ * help screens.
8
+ *
9
+ * @module
10
+ */
11
+ import "../_dnt.polyfills.js";
12
+ import * as dntShim from "../_dnt.shims.js";
13
+ import { Command } from "@jsr/cliffy__command";
14
+ import * as colors from "@jsr/std__fmt/colors";
15
+ import { initConfig } from "./config/init.js";
16
+ import { compile } from "./ui/compile.js";
17
+ import { Brand, seyunaGradient } from "./helpers/styles.js";
18
+ // Import project name and version from deno.json for single-source-of-truth.
19
+ import denoConfig from "../deno.js";
20
+ const VERSION = denoConfig.version;
21
+ /**
22
+ * High-fidelity ASCII logo for the CLI.
23
+ * Rendered using the primary brand gradient.
24
+ */
25
+ const seyunaLogo = seyunaGradient(`
26
+
27
+ _____ _____ __ __ _____ _____ _____
28
+ | __| __| | | | | | | _ |
29
+ |__ | __|_ _| | | | | | |
30
+ |_____|_____| |_| |_____|_|___|__|__|
31
+
32
+ `);
33
+ /**
34
+ * 'ui' Command Definition.
35
+ * Handles style compilation, real-time watching, and configuration.
36
+ */
37
+ const uiCmd = new Command()
38
+ .option("-c, --compile", "Run a one-time compilation of your styles.")
39
+ .option("-w, --watch", "Watch for changes and re-compile automatically.")
40
+ .action(async (options) => {
41
+ if (options.compile || options.watch) {
42
+ await compile({ watch: options.watch });
43
+ }
44
+ else {
45
+ console.log(Brand.warning("Please provide an option or subcommand. See --help for more info."));
46
+ }
47
+ })
48
+ /**
49
+ * 'ui config' Subcommand.
50
+ * Handles project initialization.
51
+ */
52
+ .command("config")
53
+ .option("-i, --init", "Initialize a new 'seyuna.json' configuration.")
54
+ .action(async (options) => {
55
+ if (options.init) {
56
+ await initConfig();
57
+ }
58
+ else {
59
+ console.log(Brand.warning("Please provide an option. See --help for more info."));
60
+ }
61
+ });
62
+ /**
63
+ * Root 'seyuna' Command.
64
+ */
65
+ const cmd = new Command()
66
+ .name("seyuna")
67
+ .version(VERSION)
68
+ .action(() => {
69
+ // Show help by default if no subcommand is provided.
70
+ cmd.showHelp();
71
+ })
72
+ .command("ui", uiCmd)
73
+ .command("generate-json-schema")
74
+ .hidden() // Hidden command for future expansion
75
+ .action(() => {
76
+ console.log(Brand.muted("JSON schema generation is planned for a future release."));
77
+ });
78
+ /**
79
+ * Traverses the command tree and prepends the branded logo to every
80
+ * generated help screen. This ensures a consistent premium brand experience.
81
+ *
82
+ * @param command - The Cliffy Command instance to apply the logo to.
83
+ */
84
+ // deno-lint-ignore no-explicit-any
85
+ const applyBrandedHelp = (command) => {
86
+ const originalGetHelp = command.getHelp;
87
+ command.getHelp = function () {
88
+ return seyunaLogo + originalGetHelp.call(this);
89
+ };
90
+ // Recursively apply to all sub-commands
91
+ command.getCommands().forEach((c) => applyBrandedHelp(c));
92
+ };
93
+ // Initialize branding
94
+ // @ts-ignore: Cliffy Command types are highly generic and conflict after adding subcommands
95
+ applyBrandedHelp(cmd);
96
+ /**
97
+ * CLI Execution Loop.
98
+ * Handles argument parsing and top-level error reporting.
99
+ */
100
+ if (globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).main) {
101
+ try {
102
+ await cmd.parse(dntShim.Deno.args);
103
+ }
104
+ catch (error) {
105
+ if (error instanceof Error) {
106
+ console.error(`${colors.bold(colors.red("Error:"))} ${error.message}`);
107
+ }
108
+ dntShim.Deno.exit(1);
109
+ }
110
+ }
@@ -0,0 +1,21 @@
1
+ import type { Config } from "../config/types.js";
2
+ /**
3
+ * Main entrypoint for the UI compilation process.
4
+ * Orchestrates loading configuration, generating CSS, and optionally
5
+ * starting a file watcher for real-time development.
6
+ *
7
+ * @param options - Compilation options, including 'watch' mode
8
+ * @returns The loaded project configuration
9
+ */
10
+ export declare function compile(options: {
11
+ watch?: boolean;
12
+ }): Promise<Config>;
13
+ /**
14
+ * The core engine that translates project tokens into functional CSS files.
15
+ * Generates both 'seyuna-global.css' (reset + variables) and
16
+ * 'postcss-variables.css' (design token manifest for PostCSS).
17
+ *
18
+ * @param config - The project configuration object
19
+ */
20
+ export declare function compileCss(config: Config): Promise<void>;
21
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/src/ui/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAYjD;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAc3E;AAkCD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB9D"}
@@ -0,0 +1,193 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { GLOBAL_CSS } from "./global.css.js";
3
+ import { createPathFromFileName, loadSeyunaUserConfig, saveFile, } from "../helpers/fs.js";
4
+ import { SeyunaSpinner } from "../helpers/cli.js";
5
+ import { delay } from "@jsr/std__async";
6
+ import { Brand } from "../helpers/styles.js";
7
+ /**
8
+ * Main entrypoint for the UI compilation process.
9
+ * Orchestrates loading configuration, generating CSS, and optionally
10
+ * starting a file watcher for real-time development.
11
+ *
12
+ * @param options - Compilation options, including 'watch' mode
13
+ * @returns The loaded project configuration
14
+ */
15
+ export async function compile(options) {
16
+ try {
17
+ const config = await loadSeyunaUserConfig();
18
+ await compileCss(config);
19
+ if (options.watch) {
20
+ console.log(`\n${Brand.secondary("Watching for changes...")}`);
21
+ await watchConfigAndRecompile("seyuna.json");
22
+ }
23
+ return config;
24
+ }
25
+ catch (error) {
26
+ throw error;
27
+ }
28
+ }
29
+ /**
30
+ * Starts an optimized file watcher on the configuration manifest.
31
+ * Provides debounced recompilation to handle rapid file system events.
32
+ *
33
+ * @param file - The path to the configuration file to watch
34
+ */
35
+ async function watchConfigAndRecompile(file) {
36
+ const watcher = dntShim.Deno.watchFs(file);
37
+ let debounceTimer;
38
+ for await (const event of watcher) {
39
+ // Only trigger on actual content modifications
40
+ if (event.kind === "modify") {
41
+ if (debounceTimer)
42
+ clearTimeout(debounceTimer);
43
+ debounceTimer = setTimeout(async () => {
44
+ // Short delay to ensure the OS has finished writing the file
45
+ await delay(300);
46
+ try {
47
+ const config = await loadSeyunaUserConfig();
48
+ await compileCss(config);
49
+ const time = new Date().toLocaleTimeString();
50
+ console.log(`${Brand.muted(time)} ${Brand.success("Recompiled successfully")}`);
51
+ }
52
+ catch (e) {
53
+ console.error(`${Brand.error("Watch Error:")} ${e instanceof Error ? e.message : "Unknown error"}`);
54
+ }
55
+ }, 50);
56
+ }
57
+ }
58
+ }
59
+ /**
60
+ * The core engine that translates project tokens into functional CSS files.
61
+ * Generates both 'seyuna-global.css' (reset + variables) and
62
+ * 'postcss-variables.css' (design token manifest for PostCSS).
63
+ *
64
+ * @param config - The project configuration object
65
+ */
66
+ export async function compileCss(config) {
67
+ const spinner = new SeyunaSpinner("Compiling your UI styles").start();
68
+ try {
69
+ const ui = getUiConfig(config);
70
+ if (!ui.output_dir) {
71
+ throw new Error("Output directory ('output_dir') must be specified in the UI configuration.");
72
+ }
73
+ spinner.progress("Building token manifest");
74
+ const globalCss = buildGlobalCss(config);
75
+ const postcssVariables = buildPostcssVariables(config);
76
+ const globalPath = createPathFromFileName("seyuna-global.css", ui.output_dir);
77
+ const varsPath = createPathFromFileName("postcss-variables.css", ui.output_dir);
78
+ spinner.progress(`Persisting styles to ${ui.output_dir}`);
79
+ await saveFile(globalPath, globalCss);
80
+ await saveFile(varsPath, postcssVariables);
81
+ spinner.done("Styles compiled successfully!");
82
+ }
83
+ catch (error) {
84
+ spinner.error(`Compilation failed: ${error instanceof Error ? error.message : "Unknown error"}`);
85
+ throw error;
86
+ }
87
+ }
88
+ /**
89
+ * Safely extracts the UI block from the root configuration.
90
+ */
91
+ function getUiConfig(config) {
92
+ if (!config.ui) {
93
+ throw new Error("Missing 'ui' configuration block in 'seyuna.json'.");
94
+ }
95
+ return config.ui;
96
+ }
97
+ /**
98
+ * Combines dynamic token variables with the global reset template.
99
+ */
100
+ function buildGlobalCss(config) {
101
+ return [buildCssVariables(config), GLOBAL_CSS].join("\n");
102
+ }
103
+ /**
104
+ * Generates a full CSS variable sheet including base tokens,
105
+ * theme modes, and system scheme adaptivity.
106
+ */
107
+ function buildCssVariables(config) {
108
+ const ui = getUiConfig(config);
109
+ const out = [":root {"];
110
+ // Hue Tokens (e.g., --alpha-hue)
111
+ for (const [name, val] of Object.entries(ui.theme.hues)) {
112
+ out.push(` --${name}-hue: ${val};`);
113
+ }
114
+ // Global Semantic Colors
115
+ for (const [name, color] of Object.entries(ui.theme.colors)) {
116
+ out.push(` --${name}-lightness: ${color.lightness};`);
117
+ out.push(` --${name}-chroma: ${color.chroma};`);
118
+ out.push(` --${name}-hue: ${color.hue};`);
119
+ }
120
+ out.push("}\n");
121
+ const modes = ["light", "dark"];
122
+ // Explicit Theme Mode Overrides ([data-mode="light"])
123
+ for (const mode of modes) {
124
+ out.push(`[data-mode="${mode}"] {`);
125
+ out.push(buildModeBlock(ui, mode));
126
+ // Mode-specific semantic color overrides
127
+ for (const [name, color] of Object.entries(ui.theme[mode].colors)) {
128
+ out.push(` --${name}-lightness: ${color.lightness};`);
129
+ out.push(` --${name}-chroma: ${color.chroma};`);
130
+ out.push(` --${name}-hue: ${color.hue};`);
131
+ }
132
+ out.push("}\n");
133
+ }
134
+ // System Adatpivity (Auto switching via @media)
135
+ for (const mode of modes) {
136
+ out.push(`@media (prefers-color-scheme: ${mode}) {`);
137
+ out.push(' [data-mode="system"] {');
138
+ out.push(indent(buildModeBlock(ui, mode), 2));
139
+ for (const [name, color] of Object.entries(ui.theme[mode].colors)) {
140
+ out.push(` --${name}-lightness: ${color.lightness};`);
141
+ out.push(` --${name}-chroma: ${color.chroma};`);
142
+ out.push(` --${name}-hue: ${color.hue};`);
143
+ }
144
+ out.push(" }");
145
+ out.push("}\n");
146
+ }
147
+ return out.join("\n");
148
+ }
149
+ /**
150
+ * Generates a SASS/PostCSS compatible SCSS manifest.
151
+ * Used for deep integration with traditional build tools.
152
+ */
153
+ function buildPostcssVariables(config) {
154
+ const ui = getUiConfig(config);
155
+ const fixed = Object.keys(ui.theme.colors).map((c) => `'${c}'`).join(", ");
156
+ const hues = Object.keys(ui.theme.hues).map((n) => `'${n}'`).join(", ");
157
+ return [
158
+ `$fixed_colors: (${fixed});`,
159
+ `$standard_colors: (${hues});`,
160
+ "$xs: 20rem;",
161
+ "$sm: 40rem;",
162
+ "$md: 48rem;",
163
+ "$lg: 64rem;",
164
+ "$xl: 80rem;",
165
+ "\n",
166
+ ].join("\n");
167
+ }
168
+ /**
169
+ * Builds a block of core CSS variables (background, text) for a specific mode.
170
+ */
171
+ function buildModeBlock(ui, mode) {
172
+ const p = ui.theme[mode];
173
+ return [
174
+ ` --background: oklch(${p.background.lightness} ${p.background.chroma} ${p.background.hue});`,
175
+ ` --text: oklch(${p.text.lightness} ${p.text.chroma} ${p.text.hue});`,
176
+ ` --chroma: ${p.chroma};`,
177
+ ` --lightness: ${p.lightness};`,
178
+ ].join("\n");
179
+ }
180
+ /**
181
+ * Helper to indent string lines for pretty-printed CSS output.
182
+ *
183
+ * @param s - The string to indent
184
+ * @param level - Number of double-space indents to apply
185
+ * @returns The formatted and indented string
186
+ */
187
+ function indent(s, level) {
188
+ const pad = " ".repeat(level);
189
+ return s.split(/\r?\n/)
190
+ .filter((line) => line.trim().length > 0)
191
+ .map((line) => `${pad}${line.trim()}\n`)
192
+ .join("");
193
+ }
@@ -0,0 +1,8 @@
1
+ import type { UI } from "./types.js";
2
+ /**
3
+ * The default out-of-the-box UI configuration for Seyuna projects.
4
+ * This provides a robust set of design tokens including a full
5
+ * Greek-lettered hue scale and foundational semantic colors.
6
+ */
7
+ export declare const UI_CONFIGURATION: UI;
8
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../src/src/ui/default.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAErC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,EAgE9B,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The default out-of-the-box UI configuration for Seyuna projects.
3
+ * This provides a robust set of design tokens including a full
4
+ * Greek-lettered hue scale and foundational semantic colors.
5
+ */
6
+ export const UI_CONFIGURATION = {
7
+ theme: {
8
+ /**
9
+ * Global hue scale. Uses Greek letters to provide semantically neutral
10
+ * references for the 360-degree color wheel.
11
+ */
12
+ hues: {
13
+ "alpha": 0,
14
+ "beta": 15,
15
+ "gamma": 30,
16
+ "delta": 45,
17
+ "epsilon": 60,
18
+ "zeta": 75,
19
+ "eta": 90,
20
+ "theta": 105,
21
+ "iota": 120,
22
+ "kappa": 135,
23
+ "lambda": 150,
24
+ "mu": 165,
25
+ "nu": 180,
26
+ "xi": 195,
27
+ "omicron": 210,
28
+ "pi": 225,
29
+ "rho": 240,
30
+ "sigma": 255,
31
+ "tau": 270,
32
+ "upsilon": 285,
33
+ "phi": 300,
34
+ "chi": 315,
35
+ "psi": 330,
36
+ "omega": 345,
37
+ },
38
+ /** Base semantic colors shared across modes */
39
+ colors: {
40
+ "white": { lightness: 1.0, chroma: 0.0, hue: 0 },
41
+ "black": { lightness: 0.0, chroma: 0.0, hue: 0 },
42
+ "primary": { lightness: 0.66, chroma: 0.26, hue: 240 },
43
+ },
44
+ /** Default light mode palette */
45
+ light: {
46
+ chroma: 0.26,
47
+ lightness: 0.66,
48
+ background: { hue: 0, chroma: 0.0, lightness: 1.0 },
49
+ text: { hue: 0, chroma: 0.0, lightness: 0.0 },
50
+ colors: {},
51
+ },
52
+ /** Default dark mode palette */
53
+ dark: {
54
+ chroma: 0.26,
55
+ lightness: 0.66,
56
+ background: { hue: 0, chroma: 0.0, lightness: 0.0 },
57
+ text: { hue: 0, chroma: 0.0, lightness: 1.0 },
58
+ colors: {},
59
+ },
60
+ },
61
+ /** Default to following the system's preferred color scheme */
62
+ mode: "system",
63
+ /** Standard output directory for generated CSS assets */
64
+ output_dir: "src/styles",
65
+ };