@symblight/md-colors 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -10,44 +10,55 @@ Built on [`@material/material-color-utilities`](https://github.com/material-foun
10
10
  npm install @symblight/md-colors
11
11
  ```
12
12
 
13
- ## Two builds
13
+ ## Builds
14
14
 
15
15
  | Build | Entry | Format | Use case |
16
16
  |---|---|---|---|
17
- | Node / bundler | `dist/index.js` | ESM | Programmatic token generation, CSS file output |
18
- | Browser (bundler) | `dist/client.esm.js` | ESM | Vite, Storybook, bundler imports |
19
- | Browser (script) | `dist/client.js` | IIFE | Plain `<script>` tag, no bundler |
17
+ | Node / bundler | `dist/index.js` | ESM | `generateTokens`, `generateCSSFile` |
18
+ | Browser (bundler) | `dist/client.esm.js` | ESM | Vite, Storybook — named import |
19
+ | Browser (script) | `dist/client.js` | IIFE | Plain `<script>` tag |
20
+ | CLI | `dist/cli.js` | ESM | Terminal usage via `md-colors` |
20
21
 
21
22
  ---
22
23
 
23
24
  ## Node — programmatic API
24
25
 
25
- Import `generateTokens` to build token maps in Node.js scripts or server-side tooling.
26
-
27
26
  ```js
28
- import { generateTokens } from "@symblight/md-colors";
27
+ import { generateTokens, generateCSSFile } from "@symblight/md-colors";
28
+ ```
29
+
30
+ ### `generateTokens(config)`
29
31
 
32
+ Returns a token map — use it to apply tokens however you like.
33
+
34
+ ```js
30
35
  const tokens = generateTokens({ sourceColor: "#6750A4", scheme: "dark" });
31
36
  // { "--md-sys-color-primary": "oklch(…)", … }
32
37
  ```
33
38
 
34
- ### `generateTokens(config)`
35
-
36
39
  | Param | Type | Default | Description |
37
40
  |---|---|---|---|
38
41
  | `config.sourceColor` | `string` | `"#1D5D78"` | Seed color as a hex string |
39
42
  | `config.scheme` | `"light" \| "dark"` | `"light"` | Color scheme variant |
40
43
 
41
- Returns `Record<string, string>` — CSS variable names mapped to oklch color strings.
44
+ ### `generateCSSFile(config)`
42
45
 
43
- ### Generate a CSS file
46
+ Writes a `colors.css` file with `:root`-scoped tokens.
44
47
 
45
- Run the following to write a `colors.css` file to the package directory:
46
-
47
- ```bash
48
- pnpm generate-theme
48
+ ```js
49
+ generateCSSFile({
50
+ sourceColor: "#6750A4",
51
+ scheme: "dark",
52
+ output: "./theme/colors.css",
53
+ });
49
54
  ```
50
55
 
56
+ | Param | Type | Default | Description |
57
+ |---|---|---|---|
58
+ | `config.sourceColor` | `string` | `"#1D5D78"` | Seed color as a hex string |
59
+ | `config.scheme` | `"light" \| "dark"` | `"light"` | Color scheme variant |
60
+ | `config.output` | `string` | `./colors.css` (next to module) | Output file path |
61
+
51
62
  Output:
52
63
 
53
64
  ```css
@@ -59,32 +70,39 @@ Output:
59
70
  }
60
71
  ```
61
72
 
62
- Source color and scheme are configured directly in `create-theme-file.mjs`.
63
-
64
73
  ---
65
74
 
66
75
  ## Browser client — runtime theming
67
76
 
68
- The browser build registers `window.generateTheme`, which injects tokens as CSS custom properties on `:root` at runtime.
77
+ Import `generateTheme` and call it directly — no globals, no window assignment.
69
78
 
70
- ### Via ES module import (Vite, Storybook)
79
+ ### Named import (Vite, Storybook, bundler)
71
80
 
72
81
  ```js
73
- import "@symblight/md-colors/client";
82
+ import { generateTheme } from "@symblight/md-colors/client";
74
83
 
75
- window.generateTheme({ sourceColor: "#6750A4", scheme: "dark" });
84
+ generateTheme({ sourceColor: "#6750A4", scheme: "dark" });
76
85
  ```
77
86
 
78
87
  ### Via `<script>` tag (no bundler)
79
88
 
89
+ ```html
90
+ <script type="module">
91
+ import { generateTheme } from "./node_modules/@symblight/md-colors/dist/client.esm.js";
92
+ generateTheme({ sourceColor: "#6750A4", scheme: "dark" });
93
+ </script>
94
+ ```
95
+
96
+ Or with the self-contained IIFE build:
97
+
80
98
  ```html
81
99
  <script src="node_modules/@symblight/md-colors/dist/client.js"></script>
82
100
  <script>
83
- window.generateTheme({ sourceColor: "#6750A4", scheme: "dark" });
101
+ // client.js exposes nothing on window — use it as an ES module instead (see above)
84
102
  </script>
85
103
  ```
86
104
 
87
- ### `window.generateTheme(options)`
105
+ ### `generateTheme(options)`
88
106
 
89
107
  | Param | Type | Default | Description |
90
108
  |---|---|---|---|
@@ -95,11 +113,32 @@ Sets every `--md-sys-color-*` variable on `document.documentElement` via `style.
95
113
 
96
114
  ---
97
115
 
116
+ ## CLI
117
+
118
+ ```bash
119
+ # npx (no install)
120
+ npx md-colors --sourceColor="#6750A4" --scheme=dark --output=./theme/colors.css
121
+
122
+ # global install
123
+ npm install -g @symblight/md-colors
124
+ md-colors --sourceColor="#6750A4" --scheme=light --output=./colors.css
125
+ ```
126
+
127
+ ### Options
128
+
129
+ | Flag | Short | Default | Description |
130
+ |---|---|---|---|
131
+ | `--sourceColor` | `-c` | `#1D5D78` | Seed color as a hex string |
132
+ | `--scheme` | `-s` | `light` | `light` or `dark` |
133
+ | `--output` | `-o` | `./colors.css` | Output file path |
134
+
135
+ ---
136
+
98
137
  ## Development
99
138
 
100
139
  ```bash
101
140
  pnpm build # Build all dist outputs
102
- pnpm generate-theme # Write colors.css
141
+ pnpm generate-theme # Write colors.css via CLI (uses defaults)
103
142
  pnpm test # Run Jest tests
104
143
  ```
105
144
 
package/dist/cli.js ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+
4
+ // cli.mjs
5
+ import { parseArgs } from "node:util";
6
+
7
+ // create-theme-file.mjs
8
+ import path from "node:path";
9
+ import fs from "node:fs";
10
+ import { fileURLToPath } from "node:url";
11
+
12
+ // tokens.mjs
13
+ import {
14
+ argbFromHex,
15
+ themeFromSourceColor,
16
+ hexFromArgb,
17
+ MaterialDynamicColors,
18
+ SchemeContent,
19
+ Hct
20
+ } from "@material/material-color-utilities";
21
+ import { converter, formatCss } from "culori";
22
+ var oklch = converter("oklch");
23
+ var materialColors = {
24
+ "surface-container-highest": MaterialDynamicColors.surfaceContainerHighest,
25
+ "surface-container-high": MaterialDynamicColors.surfaceContainerHigh,
26
+ "surface-dim": MaterialDynamicColors.surfaceDim,
27
+ "surface-bright": MaterialDynamicColors.surfaceBright,
28
+ "surface-container-lowest": MaterialDynamicColors.surfaceContainerLowest,
29
+ "surface-container-low": MaterialDynamicColors.surfaceContainerLow
30
+ };
31
+ function setSchemeProperties(scheme2, suffix = "") {
32
+ let result = {};
33
+ for (const [key, value] of Object.entries(scheme2)) {
34
+ const token = key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
35
+ const color = hexFromArgb(value);
36
+ const converted = oklch(color);
37
+ const name = formatCss(converted);
38
+ const variableName = `--md-sys-color-${token}${suffix}`;
39
+ result[variableName] = name;
40
+ }
41
+ return result;
42
+ }
43
+ function generateTokens(config = { scheme: "light", sourceColor: "#1D5D78" }) {
44
+ const theme = themeFromSourceColor(argbFromHex(config.sourceColor), []);
45
+ const scheme2 = new SchemeContent(
46
+ Hct.fromInt(argbFromHex(config.sourceColor)),
47
+ config.scheme === "dark",
48
+ 0
49
+ );
50
+ let palette = {};
51
+ for (const [key, value] of Object.entries(materialColors)) {
52
+ palette[key] = value.getArgb(scheme2);
53
+ }
54
+ const currentTheme = theme.schemes[config.scheme].toJSON();
55
+ const tokens = setSchemeProperties({ ...currentTheme, ...palette });
56
+ return tokens;
57
+ }
58
+
59
+ // create-theme-file.mjs
60
+ function template(variables) {
61
+ return `:root {
62
+ ${variables}
63
+ }`;
64
+ }
65
+ function normalizeCSSVariablesContent(variables = {}) {
66
+ let str = "";
67
+ for (const cssVar in variables) {
68
+ str += `${cssVar}: ${variables[cssVar]};
69
+ `;
70
+ }
71
+ return str;
72
+ }
73
+ function generateCSSFile(config = {}) {
74
+ const { scheme: scheme2 = "light", sourceColor: sourceColor2 = "#1D5D78", output: output2 } = config;
75
+ const __filename = fileURLToPath(import.meta.url);
76
+ const __dirname = path.dirname(__filename);
77
+ const outputPath = output2 ? path.resolve(output2) : path.join(__dirname, "colors.css");
78
+ const tokens = generateTokens({ scheme: scheme2, sourceColor: sourceColor2 });
79
+ const stringTokens = normalizeCSSVariablesContent(tokens);
80
+ const themeBody = template(stringTokens);
81
+ fs.writeFile(outputPath, themeBody, (err) => {
82
+ if (err) {
83
+ console.error(err);
84
+ }
85
+ });
86
+ }
87
+
88
+ // cli.mjs
89
+ var { values } = parseArgs({
90
+ options: {
91
+ sourceColor: { type: "string", short: "c", default: "#1D5D78" },
92
+ scheme: { type: "string", short: "s", default: "light" },
93
+ output: { type: "string", short: "o", default: "./colors.css" }
94
+ }
95
+ });
96
+ var { sourceColor, scheme, output } = values;
97
+ if (scheme !== "light" && scheme !== "dark") {
98
+ console.error(`Error: --scheme must be "light" or "dark", got "${scheme}"`);
99
+ process.exit(1);
100
+ }
101
+ generateCSSFile({ sourceColor, scheme, output });
102
+ console.log(`Generated ${output} (sourceColor: ${sourceColor}, scheme: ${scheme})`);
@@ -6939,15 +6939,15 @@ function generateTokens(config = { scheme: "light", sourceColor: "#1D5D78" }) {
6939
6939
  }
6940
6940
 
6941
6941
  // client.mjs
6942
- window.generateTheme = function({ sourceColor, scheme = "light" } = {}) {
6943
- const tokens = generateTokens({
6944
- sourceColor,
6945
- scheme
6946
- });
6942
+ function generateTheme({ sourceColor, scheme = "light" } = {}) {
6943
+ const tokens = generateTokens({ sourceColor, scheme });
6947
6944
  const root = document.documentElement;
6948
6945
  for (const [variable, value] of Object.entries(tokens)) {
6949
6946
  root.style.setProperty(variable, value);
6950
6947
  }
6948
+ }
6949
+ export {
6950
+ generateTheme
6951
6951
  };
6952
6952
  /*! Bundled license information:
6953
6953