@diskette/palette 0.21.1 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -24
- package/dist/package.json +62 -0
- package/dist/src/cli/cli.d.ts +1 -0
- package/dist/src/cli/cli.js +96 -0
- package/dist/src/cli/utils.d.ts +22 -0
- package/dist/src/cli/utils.js +100 -0
- package/dist/{css.d.ts → src/css.d.ts} +5 -1
- package/dist/{css.js → src/css.js} +16 -3
- package/dist/{utils.d.ts → src/utils.d.ts} +1 -10
- package/dist/{utils.js → src/utils.js} +8 -52
- package/package.json +12 -9
- package/dist/cli/cli.d.ts +0 -1
- package/dist/cli/cli.js +0 -70
- /package/dist/{colors → src/colors}/amber.d.ts +0 -0
- /package/dist/{colors → src/colors}/amber.js +0 -0
- /package/dist/{colors → src/colors}/black-alpha.d.ts +0 -0
- /package/dist/{colors → src/colors}/black-alpha.js +0 -0
- /package/dist/{colors → src/colors}/blue.d.ts +0 -0
- /package/dist/{colors → src/colors}/blue.js +0 -0
- /package/dist/{colors → src/colors}/bronze.d.ts +0 -0
- /package/dist/{colors → src/colors}/bronze.js +0 -0
- /package/dist/{colors → src/colors}/brown.d.ts +0 -0
- /package/dist/{colors → src/colors}/brown.js +0 -0
- /package/dist/{colors → src/colors}/crimson.d.ts +0 -0
- /package/dist/{colors → src/colors}/crimson.js +0 -0
- /package/dist/{colors → src/colors}/cyan.d.ts +0 -0
- /package/dist/{colors → src/colors}/cyan.js +0 -0
- /package/dist/{colors → src/colors}/gold.d.ts +0 -0
- /package/dist/{colors → src/colors}/gold.js +0 -0
- /package/dist/{colors → src/colors}/grass.d.ts +0 -0
- /package/dist/{colors → src/colors}/grass.js +0 -0
- /package/dist/{colors → src/colors}/gray.d.ts +0 -0
- /package/dist/{colors → src/colors}/gray.js +0 -0
- /package/dist/{colors → src/colors}/green.d.ts +0 -0
- /package/dist/{colors → src/colors}/green.js +0 -0
- /package/dist/{colors → src/colors}/index.d.ts +0 -0
- /package/dist/{colors → src/colors}/index.js +0 -0
- /package/dist/{colors → src/colors}/indigo.d.ts +0 -0
- /package/dist/{colors → src/colors}/indigo.js +0 -0
- /package/dist/{colors → src/colors}/iris.d.ts +0 -0
- /package/dist/{colors → src/colors}/iris.js +0 -0
- /package/dist/{colors → src/colors}/jade.d.ts +0 -0
- /package/dist/{colors → src/colors}/jade.js +0 -0
- /package/dist/{colors → src/colors}/lime.d.ts +0 -0
- /package/dist/{colors → src/colors}/lime.js +0 -0
- /package/dist/{colors → src/colors}/mauve.d.ts +0 -0
- /package/dist/{colors → src/colors}/mauve.js +0 -0
- /package/dist/{colors → src/colors}/mint.d.ts +0 -0
- /package/dist/{colors → src/colors}/mint.js +0 -0
- /package/dist/{colors → src/colors}/olive.d.ts +0 -0
- /package/dist/{colors → src/colors}/olive.js +0 -0
- /package/dist/{colors → src/colors}/orange.d.ts +0 -0
- /package/dist/{colors → src/colors}/orange.js +0 -0
- /package/dist/{colors → src/colors}/pink.d.ts +0 -0
- /package/dist/{colors → src/colors}/pink.js +0 -0
- /package/dist/{colors → src/colors}/plum.d.ts +0 -0
- /package/dist/{colors → src/colors}/plum.js +0 -0
- /package/dist/{colors → src/colors}/purple.d.ts +0 -0
- /package/dist/{colors → src/colors}/purple.js +0 -0
- /package/dist/{colors → src/colors}/red.d.ts +0 -0
- /package/dist/{colors → src/colors}/red.js +0 -0
- /package/dist/{colors → src/colors}/ruby.d.ts +0 -0
- /package/dist/{colors → src/colors}/ruby.js +0 -0
- /package/dist/{colors → src/colors}/sage.d.ts +0 -0
- /package/dist/{colors → src/colors}/sage.js +0 -0
- /package/dist/{colors → src/colors}/sand.d.ts +0 -0
- /package/dist/{colors → src/colors}/sand.js +0 -0
- /package/dist/{colors → src/colors}/sky.d.ts +0 -0
- /package/dist/{colors → src/colors}/sky.js +0 -0
- /package/dist/{colors → src/colors}/slate.d.ts +0 -0
- /package/dist/{colors → src/colors}/slate.js +0 -0
- /package/dist/{colors → src/colors}/teal.d.ts +0 -0
- /package/dist/{colors → src/colors}/teal.js +0 -0
- /package/dist/{colors → src/colors}/tomato.d.ts +0 -0
- /package/dist/{colors → src/colors}/tomato.js +0 -0
- /package/dist/{colors → src/colors}/violet.d.ts +0 -0
- /package/dist/{colors → src/colors}/violet.js +0 -0
- /package/dist/{colors → src/colors}/white-alpha.d.ts +0 -0
- /package/dist/{colors → src/colors}/white-alpha.js +0 -0
- /package/dist/{colors → src/colors}/yellow.d.ts +0 -0
- /package/dist/{colors → src/colors}/yellow.js +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{types.d.ts → src/types.d.ts} +0 -0
- /package/dist/{types.js → src/types.js} +0 -0
package/README.md
CHANGED
|
@@ -87,20 +87,24 @@ whiteAlpha.p3.whiteA5 // 'color(display-p3 1 1 1 / 0.3)'
|
|
|
87
87
|
|
|
88
88
|
## CLI
|
|
89
89
|
|
|
90
|
-
The package includes
|
|
91
|
-
|
|
92
|
-
### `palette generate`
|
|
93
|
-
|
|
94
|
-
Generate CSS files for color palettes.
|
|
90
|
+
The package includes an interactive CLI for generating CSS files.
|
|
95
91
|
|
|
96
92
|
```bash
|
|
97
|
-
palette
|
|
93
|
+
npx @diskette/palette
|
|
98
94
|
```
|
|
99
95
|
|
|
96
|
+
The CLI guides you through:
|
|
97
|
+
|
|
98
|
+
1. **Select accent colors** - Choose from all available accent colors with color swatches, plus alpha colors (blackAlpha, whiteAlpha)
|
|
99
|
+
2. **Select gray colors** - Natural pairings are pre-selected based on your accent choices
|
|
100
|
+
3. **Output directory** - Where to save the generated files (default: `./palette`)
|
|
101
|
+
4. **Generate accents.css?** - Include `[data-accent-color]` and `[data-gray-color]` selectors
|
|
102
|
+
5. **Generate Tailwind v4 config?** - Include `@theme inline` mappings in `index.css`
|
|
103
|
+
|
|
104
|
+
Example output:
|
|
105
|
+
|
|
100
106
|
```
|
|
101
|
-
|
|
102
|
-
├── index.css # Imports + Tailwind v4 @theme mappings
|
|
103
|
-
├── accents.css # [data-accent-color] selectors (-a flag)
|
|
107
|
+
palette/
|
|
104
108
|
├── blue.css # Light theme: --blue-1 through --blue-12, --blue-a1 through --blue-a12
|
|
105
109
|
├── blue-dark.css # Dark theme variants
|
|
106
110
|
├── red.css
|
|
@@ -108,21 +112,9 @@ styles/
|
|
|
108
112
|
├── slate.css
|
|
109
113
|
├── slate-dark.css
|
|
110
114
|
├── black-alpha.css # --black-a1 through --black-a12
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
**Options:**
|
|
115
|
-
- `-o, --output <dir>` - Output directory (required)
|
|
116
|
-
- `-a, --accents` - Generate `accents.css` with `[data-accent-color]` and `[data-gray-color]` selectors
|
|
117
|
-
|
|
118
|
-
### `palette list`
|
|
119
|
-
|
|
120
|
-
List available colors.
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
palette list # List all colors
|
|
124
|
-
palette list --accent # List only accent colors
|
|
125
|
-
palette list --gray # List only gray colors
|
|
115
|
+
├── white-alpha.css # --white-a1 through --white-a12
|
|
116
|
+
├── accents.css # [data-accent-color] selectors (optional)
|
|
117
|
+
└── index.css # Tailwind v4 @theme mappings (optional)
|
|
126
118
|
```
|
|
127
119
|
|
|
128
120
|
## Available Colors
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@diskette/palette",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.22.0",
|
|
5
|
+
"bin": {
|
|
6
|
+
"palette": "./dist/cli/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./colors": {
|
|
14
|
+
"types": "./dist/colors/index.d.ts",
|
|
15
|
+
"default": "./dist/colors/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./colors/*": {
|
|
18
|
+
"types": "./dist/colors/*.d.ts",
|
|
19
|
+
"default": "./dist/colors/*.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"packageManager": "pnpm@10.22.0",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
28
|
+
"prepublishOnly": "pnpm build",
|
|
29
|
+
"typecheck": "tsc",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"lint": "oxlint --type-aware src",
|
|
32
|
+
"release": "changeset version && changeset publish && git push --follow-tags"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@clack/prompts": "1.0.0-alpha.8",
|
|
36
|
+
"chalk": "^5.6.2"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@changesets/cli": "^2.29.8",
|
|
40
|
+
"@diskette/fs": "^0.17.0",
|
|
41
|
+
"@types/node": "^24.10.2",
|
|
42
|
+
"@types/react": "^19.2.7",
|
|
43
|
+
"magicast": "^0.5.1",
|
|
44
|
+
"oxlint": "^1.32.0",
|
|
45
|
+
"oxlint-tsgolint": "^0.8.5",
|
|
46
|
+
"prettier": "^3.7.4",
|
|
47
|
+
"react": "^19.2.1",
|
|
48
|
+
"tsx": "^4.21.0",
|
|
49
|
+
"typescript": "^5.9.2",
|
|
50
|
+
"vitest": "^4.0.15"
|
|
51
|
+
},
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/diskettejs/palette.git"
|
|
55
|
+
},
|
|
56
|
+
"keywords": [],
|
|
57
|
+
"prettier": {
|
|
58
|
+
"semi": false,
|
|
59
|
+
"singleQuote": true
|
|
60
|
+
},
|
|
61
|
+
"license": "MIT"
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { mkdirSync } from 'node:fs';
|
|
4
|
+
import { relative, resolve } from 'node:path';
|
|
5
|
+
import pkg from '../../package.json' with { type: 'json' };
|
|
6
|
+
import { accentColors, grayColors, } from "../types.js";
|
|
7
|
+
import { getMatchingGrayColor } from "../utils.js";
|
|
8
|
+
import { alphaColors, capitalize, getColorHex, writeAccentsFile, writeColorFiles, writeTailwindFile, } from "./utils.js";
|
|
9
|
+
const accentOptions = {
|
|
10
|
+
Accents: accentColors
|
|
11
|
+
.filter((c) => c !== 'gray')
|
|
12
|
+
.map((c) => {
|
|
13
|
+
const hex = getColorHex(c);
|
|
14
|
+
const swatch = hex ? chalk.bgHex(hex)(' ') + ' ' : '';
|
|
15
|
+
return { value: c, label: `${swatch}${capitalize(c)}` };
|
|
16
|
+
}),
|
|
17
|
+
Alpha: alphaColors.map((c) => {
|
|
18
|
+
const [label] = c.split('Alpha');
|
|
19
|
+
return { value: c, label: capitalize(label) };
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
const grayOptions = grayColors.map((c) => {
|
|
23
|
+
const hex = getColorHex(c);
|
|
24
|
+
const swatch = hex ? chalk.bgHex(hex)(' ') + ' ' : '';
|
|
25
|
+
return { value: c, label: `${swatch}${capitalize(c)}` };
|
|
26
|
+
});
|
|
27
|
+
async function main() {
|
|
28
|
+
p.intro(`palette v${pkg.version}`);
|
|
29
|
+
const results = await p.group({
|
|
30
|
+
colors: () => p.groupMultiselect({
|
|
31
|
+
message: 'Select accent colors',
|
|
32
|
+
options: accentOptions,
|
|
33
|
+
required: true,
|
|
34
|
+
initialValues: [...alphaColors],
|
|
35
|
+
}),
|
|
36
|
+
grays: ({ results }) => {
|
|
37
|
+
// Get matching grays for selected accent colors
|
|
38
|
+
const selectedAccents = (results.colors ?? []).filter((c) => accentColors.includes(c));
|
|
39
|
+
const matchingGrays = [
|
|
40
|
+
...new Set(selectedAccents.map(getMatchingGrayColor)),
|
|
41
|
+
];
|
|
42
|
+
return p.multiselect({
|
|
43
|
+
message: 'Select gray colors (natural pairings pre-selected)',
|
|
44
|
+
options: grayOptions,
|
|
45
|
+
initialValues: matchingGrays,
|
|
46
|
+
required: false,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
output: () => p.text({
|
|
50
|
+
message: 'Output directory',
|
|
51
|
+
placeholder: './palette',
|
|
52
|
+
defaultValue: './palette',
|
|
53
|
+
}),
|
|
54
|
+
accents: () => p.confirm({
|
|
55
|
+
message: 'Generate accents.css?',
|
|
56
|
+
initialValue: true,
|
|
57
|
+
}),
|
|
58
|
+
tailwind: () => p.confirm({
|
|
59
|
+
message: 'Generate Tailwind v4 config?',
|
|
60
|
+
initialValue: false,
|
|
61
|
+
}),
|
|
62
|
+
}, {
|
|
63
|
+
onCancel: () => {
|
|
64
|
+
p.cancel('Operation cancelled.');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
const selectedGrays = (results.grays ?? []);
|
|
69
|
+
const allColors = [...results.colors, ...selectedGrays];
|
|
70
|
+
if (allColors.length === 0) {
|
|
71
|
+
p.cancel('No colors selected.');
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
const cwd = process.cwd();
|
|
75
|
+
const outputPath = resolve(cwd, results.output);
|
|
76
|
+
mkdirSync(outputPath, { recursive: true });
|
|
77
|
+
const s = p.spinner();
|
|
78
|
+
s.start('Generating CSS files...');
|
|
79
|
+
writeColorFiles(allColors, outputPath);
|
|
80
|
+
if (results.accents) {
|
|
81
|
+
writeAccentsFile(allColors, outputPath);
|
|
82
|
+
}
|
|
83
|
+
if (results.tailwind) {
|
|
84
|
+
writeTailwindFile(allColors, outputPath, results.accents);
|
|
85
|
+
}
|
|
86
|
+
s.stop();
|
|
87
|
+
const rel = relative(cwd, outputPath);
|
|
88
|
+
const display = rel.startsWith('..') ? rel : `./${rel}`;
|
|
89
|
+
const extras = [
|
|
90
|
+
results.accents && 'accents.css',
|
|
91
|
+
results.tailwind && 'index.css',
|
|
92
|
+
].filter(Boolean);
|
|
93
|
+
p.log.success(`Generated ${allColors.length} color${allColors.length > 1 ? 's' : ''}${extras.length ? ` + ${extras.join(', ')}` : ''}`);
|
|
94
|
+
p.outro(`Saved to ${display}`);
|
|
95
|
+
}
|
|
96
|
+
main();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Color } from '../types.ts';
|
|
2
|
+
export declare const alphaColors: readonly ["blackAlpha", "whiteAlpha"];
|
|
3
|
+
export type AlphaColor = (typeof alphaColors)[number];
|
|
4
|
+
/**
|
|
5
|
+
* get package.json content from startDir
|
|
6
|
+
* @param cwd
|
|
7
|
+
* @returns package.json content
|
|
8
|
+
*/
|
|
9
|
+
export declare const getPackageJson: (cwd: string) => {
|
|
10
|
+
pkg: any;
|
|
11
|
+
packageJsonPath: string;
|
|
12
|
+
} | undefined;
|
|
13
|
+
export declare function writeColorFiles(selected: string[], outputPath: string): void;
|
|
14
|
+
export declare function writeAlphaColorFile(name: AlphaColor, outputPath: string): void;
|
|
15
|
+
export declare function writePaletteColorFiles(name: Color, outputPath: string): void;
|
|
16
|
+
export declare function writeAccentsFile(selected: string[], outputPath: string): void;
|
|
17
|
+
export declare function writeTailwindFile(selected: string[], outputPath: string, includeAccents: boolean): void;
|
|
18
|
+
export declare function writeIfNotExists(path: string, data: string | NodeJS.ArrayBufferView): boolean;
|
|
19
|
+
export declare const capitalize: (s: string) => string;
|
|
20
|
+
/** Get hex color (step 9) for a palette color */
|
|
21
|
+
export declare const getColorHex: (name: string) => string | null;
|
|
22
|
+
export declare function invariant(condition: unknown, message?: string | Error): asserts condition;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs, { existsSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import * as url from 'node:url';
|
|
5
|
+
import * as colors from "../colors/index.js";
|
|
6
|
+
import * as palette from "../colors/index.js";
|
|
7
|
+
import { css } from "../css.js";
|
|
8
|
+
import {} from "../types.js";
|
|
9
|
+
export const alphaColors = ['blackAlpha', 'whiteAlpha'];
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
/**
|
|
12
|
+
* get package.json content from startDir
|
|
13
|
+
* @param cwd
|
|
14
|
+
* @returns package.json content
|
|
15
|
+
*/
|
|
16
|
+
export const getPackageJson = (cwd) => {
|
|
17
|
+
try {
|
|
18
|
+
const startDir = path.dirname(url.fileURLToPath(cwd));
|
|
19
|
+
const packageJsonPath = findPackageJson(startDir);
|
|
20
|
+
if (packageJsonPath) {
|
|
21
|
+
const pkg = require(packageJsonPath);
|
|
22
|
+
return { pkg, packageJsonPath };
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
// ignore error
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* search package.json from startDir
|
|
33
|
+
* @param startDir
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
const findPackageJson = (startDir) => {
|
|
37
|
+
let currentDir = startDir;
|
|
38
|
+
while (true) {
|
|
39
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
40
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
41
|
+
return packageJsonPath;
|
|
42
|
+
}
|
|
43
|
+
const parentDir = path.resolve(currentDir, '..');
|
|
44
|
+
if (parentDir === currentDir) {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
currentDir = parentDir;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
export function writeColorFiles(selected, outputPath) {
|
|
51
|
+
for (const name of selected) {
|
|
52
|
+
if (alphaColors.includes(name)) {
|
|
53
|
+
writeAlphaColorFile(name, outputPath);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
writePaletteColorFiles(name, outputPath);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function writeAlphaColorFile(name, outputPath) {
|
|
61
|
+
const config = palette[name];
|
|
62
|
+
const fileName = name === 'blackAlpha' ? 'black-alpha' : 'white-alpha';
|
|
63
|
+
writeIfNotExists(`${outputPath}/${fileName}.css`, css.alpha(config));
|
|
64
|
+
}
|
|
65
|
+
export function writePaletteColorFiles(name, outputPath) {
|
|
66
|
+
const color = palette[name];
|
|
67
|
+
writeIfNotExists(`${outputPath}/${name}.css`, css.palette(color, { schemes: ['light'], alpha: true }));
|
|
68
|
+
writeIfNotExists(`${outputPath}/${name}-dark.css`, css.palette(color, { schemes: ['dark'], alpha: true }));
|
|
69
|
+
}
|
|
70
|
+
export function writeAccentsFile(selected, outputPath) {
|
|
71
|
+
const accentColorNames = selected.filter((c) => !alphaColors.includes(c));
|
|
72
|
+
writeIfNotExists(`${outputPath}/accents.css`, css.accents(accentColorNames));
|
|
73
|
+
}
|
|
74
|
+
export function writeTailwindFile(selected, outputPath, includeAccents) {
|
|
75
|
+
const tailwindColorNames = selected.map((c) => c === 'blackAlpha' ? 'black' : c === 'whiteAlpha' ? 'white' : c);
|
|
76
|
+
writeIfNotExists(`${outputPath}/index.css`, css.tailwind(tailwindColorNames, { accents: includeAccents }));
|
|
77
|
+
}
|
|
78
|
+
export function writeIfNotExists(path, data) {
|
|
79
|
+
if (existsSync(path)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
writeFileSync(path, data);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
export const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
86
|
+
/** Get hex color (step 9) for a palette color */
|
|
87
|
+
export const getColorHex = (name) => {
|
|
88
|
+
const color = colors[name];
|
|
89
|
+
invariant(color, `${color} is missing its step 9`);
|
|
90
|
+
return color?.dark?.srgb?.solid?.[8] ?? null;
|
|
91
|
+
};
|
|
92
|
+
export function invariant(condition, message) {
|
|
93
|
+
if (condition) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (message && typeof message === 'string') {
|
|
97
|
+
throw new Error(message);
|
|
98
|
+
}
|
|
99
|
+
throw message;
|
|
100
|
+
}
|
|
@@ -13,7 +13,11 @@ declare function palette<C extends Color>(config: PaletteColor<C>, options?: Pal
|
|
|
13
13
|
declare function alpha(config: AlphaConfig): string;
|
|
14
14
|
declare function accents(colorNames: string[]): string;
|
|
15
15
|
declare function grays(names: readonly string[], className: string): string;
|
|
16
|
-
|
|
16
|
+
type TailwindOptions = {
|
|
17
|
+
/** Include @import for accents.css. Defaults to false */
|
|
18
|
+
accents?: boolean;
|
|
19
|
+
};
|
|
20
|
+
declare function tailwind(colorNames: string[], options?: TailwindOptions): string;
|
|
17
21
|
export declare const css: {
|
|
18
22
|
/**
|
|
19
23
|
* Generate combined CSS for scale variables and semantic tokens
|
|
@@ -103,11 +103,23 @@ function grays(names, className) {
|
|
|
103
103
|
});
|
|
104
104
|
return `.${className} {\n ${blocks.join('\n\n ')}\n}\n`;
|
|
105
105
|
}
|
|
106
|
-
function tailwind(colorNames) {
|
|
106
|
+
function tailwind(colorNames, options = {}) {
|
|
107
|
+
const { accents: includeAccents = false } = options;
|
|
108
|
+
const imports = [];
|
|
107
109
|
const blocks = [];
|
|
110
|
+
if (includeAccents) {
|
|
111
|
+
imports.push(`@import './accents.css';`);
|
|
112
|
+
}
|
|
108
113
|
for (const name of colorNames) {
|
|
109
114
|
const declarations = [];
|
|
110
115
|
const isAlphaOnly = name === 'white' || name === 'black';
|
|
116
|
+
if (isAlphaOnly) {
|
|
117
|
+
imports.push(`@import './${name}-alpha.css';`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
imports.push(`@import './${name}.css';`);
|
|
121
|
+
imports.push(`@import './${name}-dark.css';`);
|
|
122
|
+
}
|
|
111
123
|
if (!isAlphaOnly) {
|
|
112
124
|
for (const n of steps) {
|
|
113
125
|
declarations.push(`--color-${name}-${n}: var(--${name}-${n})`);
|
|
@@ -127,8 +139,9 @@ function tailwind(colorNames) {
|
|
|
127
139
|
focus.push(`--color-focus-${n}: var(--accent-${n})`);
|
|
128
140
|
focusAlpha.push(`--color-focus-a${n}: var(--accent-a${n})`);
|
|
129
141
|
}
|
|
130
|
-
blocks.push(focus.join(';\n'), focusAlpha.join(';\n'));
|
|
131
|
-
|
|
142
|
+
blocks.push(focus.join(';\n '), focusAlpha.join(';\n '));
|
|
143
|
+
const importsBlock = imports.length > 0 ? imports.join('\n') + '\n\n' : '';
|
|
144
|
+
return `${importsBlock}@theme inline {\n ${blocks.join(';\n\n ')};\n}\n`;
|
|
132
145
|
}
|
|
133
146
|
export const css = {
|
|
134
147
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { AccentColor, GrayColor } from './types.ts';
|
|
2
|
-
export declare function getMatchingGrayColor(accentColor: AccentColor): GrayColor;
|
|
3
2
|
export declare const LIGHT_SELECTOR = ":root, .light, .light-theme";
|
|
4
3
|
export declare const DARK_SELECTOR = ".dark, .dark-theme";
|
|
5
4
|
export declare const schemeSelector: (scheme: "light" | "dark") => string;
|
|
@@ -8,12 +7,4 @@ export declare const toVarName: (key: string) => string;
|
|
|
8
7
|
export declare const formatRule: (selector: string, vars: string[]) => string;
|
|
9
8
|
export declare const formatP3: (selector: string, vars: string[]) => string;
|
|
10
9
|
export declare const formatNestedBlock: (selector: string, vars: string[]) => string;
|
|
11
|
-
|
|
12
|
-
* get package.json content from startDir
|
|
13
|
-
* @param cwd
|
|
14
|
-
* @returns package.json content
|
|
15
|
-
*/
|
|
16
|
-
export declare const getPackageJson: (cwd: string) => {
|
|
17
|
-
pkg: any;
|
|
18
|
-
packageJsonPath: string;
|
|
19
|
-
} | undefined;
|
|
10
|
+
export declare function getMatchingGrayColor(accentColor: AccentColor): GrayColor;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export const LIGHT_SELECTOR = ':root, .light, .light-theme';
|
|
2
|
+
export const DARK_SELECTOR = '.dark, .dark-theme';
|
|
3
|
+
export const schemeSelector = (scheme) => scheme === 'light' ? LIGHT_SELECTOR : DARK_SELECTOR;
|
|
4
|
+
/** Convert "amber9" to "--amber-9" or "amberA9" to "--amber-a9" */
|
|
5
|
+
export const toVarName = (key) => `--${key.replace(/A?(\d+)/, (m, n) => (m.startsWith('A') ? `-a${n}` : `-${n}`))}`;
|
|
6
|
+
export const formatRule = (selector, vars) => `${selector} {\n ${vars.join(';\n ')};\n}`;
|
|
7
|
+
export const formatP3 = (selector, vars) => `@supports (color: color(display-p3 1 1 1)) {\n @media (color-gamut: p3) {\n ${selector} {\n ${vars.join(';\n ')};\n }\n }\n}`;
|
|
8
|
+
export const formatNestedBlock = (selector, vars) => `&:where(${selector}) {\n ${vars.join(';\n ')};\n }`;
|
|
5
9
|
export function getMatchingGrayColor(accentColor) {
|
|
6
10
|
switch (accentColor) {
|
|
7
11
|
case 'tomato':
|
|
@@ -39,51 +43,3 @@ export function getMatchingGrayColor(accentColor) {
|
|
|
39
43
|
return 'gray';
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
|
-
export const LIGHT_SELECTOR = ':root, .light, .light-theme';
|
|
43
|
-
export const DARK_SELECTOR = '.dark, .dark-theme';
|
|
44
|
-
export const schemeSelector = (scheme) => scheme === 'light' ? LIGHT_SELECTOR : DARK_SELECTOR;
|
|
45
|
-
/** Convert "amber9" to "--amber-9" or "amberA9" to "--amber-a9" */
|
|
46
|
-
export const toVarName = (key) => `--${key.replace(/A?(\d+)/, (m, n) => (m.startsWith('A') ? `-a${n}` : `-${n}`))}`;
|
|
47
|
-
export const formatRule = (selector, vars) => `${selector} {\n ${vars.join(';\n ')};\n}`;
|
|
48
|
-
export const formatP3 = (selector, vars) => `@supports (color: color(display-p3 1 1 1)) {\n @media (color-gamut: p3) {\n ${selector} {\n ${vars.join(';\n ')};\n }\n }\n}`;
|
|
49
|
-
export const formatNestedBlock = (selector, vars) => `&:where(${selector}) {\n ${vars.join(';\n ')};\n }`;
|
|
50
|
-
const require = createRequire(import.meta.url);
|
|
51
|
-
/**
|
|
52
|
-
* get package.json content from startDir
|
|
53
|
-
* @param cwd
|
|
54
|
-
* @returns package.json content
|
|
55
|
-
*/
|
|
56
|
-
export const getPackageJson = (cwd) => {
|
|
57
|
-
try {
|
|
58
|
-
const startDir = path.dirname(url.fileURLToPath(cwd));
|
|
59
|
-
const packageJsonPath = findPackageJson(startDir);
|
|
60
|
-
if (packageJsonPath) {
|
|
61
|
-
const pkg = require(packageJsonPath);
|
|
62
|
-
return { pkg, packageJsonPath };
|
|
63
|
-
}
|
|
64
|
-
return undefined;
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
// ignore error
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* search package.json from startDir
|
|
73
|
-
* @param startDir
|
|
74
|
-
* @returns
|
|
75
|
-
*/
|
|
76
|
-
const findPackageJson = (startDir) => {
|
|
77
|
-
let currentDir = startDir;
|
|
78
|
-
while (true) {
|
|
79
|
-
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
80
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
81
|
-
return packageJsonPath;
|
|
82
|
-
}
|
|
83
|
-
const parentDir = path.resolve(currentDir, '..');
|
|
84
|
-
if (parentDir === currentDir) {
|
|
85
|
-
return '';
|
|
86
|
-
}
|
|
87
|
-
currentDir = parentDir;
|
|
88
|
-
}
|
|
89
|
-
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diskette/palette",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"palette": "./dist/cli/cli.js"
|
|
7
7
|
},
|
|
@@ -23,19 +23,22 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"
|
|
26
|
+
"@clack/prompts": "1.0.0-alpha.8",
|
|
27
|
+
"chalk": "^5.6.2"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@changesets/cli": "^2.29.
|
|
30
|
+
"@changesets/cli": "^2.29.8",
|
|
30
31
|
"@diskette/fs": "^0.17.0",
|
|
31
|
-
"@types/node": "^24.
|
|
32
|
+
"@types/node": "^24.10.2",
|
|
33
|
+
"@types/react": "^19.2.7",
|
|
32
34
|
"magicast": "^0.5.1",
|
|
33
|
-
"oxlint": "^1.
|
|
34
|
-
"oxlint-tsgolint": "^0.
|
|
35
|
-
"prettier": "^3.
|
|
36
|
-
"
|
|
35
|
+
"oxlint": "^1.32.0",
|
|
36
|
+
"oxlint-tsgolint": "^0.8.5",
|
|
37
|
+
"prettier": "^3.7.4",
|
|
38
|
+
"react": "^19.2.1",
|
|
39
|
+
"tsx": "^4.21.0",
|
|
37
40
|
"typescript": "^5.9.2",
|
|
38
|
-
"vitest": "^4.0.
|
|
41
|
+
"vitest": "^4.0.15"
|
|
39
42
|
},
|
|
40
43
|
"repository": {
|
|
41
44
|
"type": "git",
|
package/dist/cli/cli.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function writeIfNotExists(path: string, data: string | NodeJS.ArrayBufferView): boolean;
|
package/dist/cli/cli.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { defineCommand, runMain } from 'citty';
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { dirname, relative, resolve } from 'node:path';
|
|
4
|
-
import * as palette from "../colors/index.js";
|
|
5
|
-
import { css } from "../css.js";
|
|
6
|
-
import { accentColors, grayColors } from "../types.js";
|
|
7
|
-
import { getPackageJson } from "../utils.js";
|
|
8
|
-
const alphaColors = ['blackAlpha', 'whiteAlpha'];
|
|
9
|
-
// Combined list of all colors (deduplicated since 'gray' appears in both)
|
|
10
|
-
const allColors = [
|
|
11
|
-
...new Set([...accentColors, ...grayColors]),
|
|
12
|
-
...alphaColors,
|
|
13
|
-
];
|
|
14
|
-
const { pkg, packageJsonPath } = getPackageJson(import.meta.url) ?? {};
|
|
15
|
-
const main = defineCommand({
|
|
16
|
-
meta: {
|
|
17
|
-
name: 'palette',
|
|
18
|
-
version: pkg?.version,
|
|
19
|
-
description: pkg?.description ?? '',
|
|
20
|
-
},
|
|
21
|
-
args: {
|
|
22
|
-
colors: {
|
|
23
|
-
type: 'positional',
|
|
24
|
-
description: 'Colors',
|
|
25
|
-
required: true,
|
|
26
|
-
},
|
|
27
|
-
output: {
|
|
28
|
-
type: 'string',
|
|
29
|
-
alias: 'o',
|
|
30
|
-
description: 'Output directory',
|
|
31
|
-
},
|
|
32
|
-
accents: {
|
|
33
|
-
type: 'boolean',
|
|
34
|
-
alias: 'a',
|
|
35
|
-
description: 'Generate accents.css with [data-accent-color] selectors',
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
run({ args }) {
|
|
39
|
-
const selected = args._.filter((c) => allColors.includes(c));
|
|
40
|
-
const outputPath = resolve(process.cwd(), args.output);
|
|
41
|
-
mkdirSync(outputPath, { recursive: true });
|
|
42
|
-
for (const name of selected) {
|
|
43
|
-
if (alphaColors.includes(name)) {
|
|
44
|
-
const alphaName = name;
|
|
45
|
-
const config = palette[alphaName];
|
|
46
|
-
const fileName = alphaName === 'blackAlpha' ? 'black-alpha' : 'white-alpha';
|
|
47
|
-
writeIfNotExists(`${outputPath}/${fileName}.css`, css.alpha(config));
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
const color = palette[name];
|
|
51
|
-
writeIfNotExists(`${outputPath}/${name}.css`, css.palette(color, { schemes: ['light'], alpha: true }));
|
|
52
|
-
writeIfNotExists(`${outputPath}/${name}-dark.css`, css.palette(color, { schemes: ['dark'], alpha: true }));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (args.accents) {
|
|
56
|
-
const accentColorNames = selected.filter((c) => !alphaColors.includes(c));
|
|
57
|
-
writeIfNotExists(`${outputPath}/accents.css`, css.accents(accentColorNames));
|
|
58
|
-
}
|
|
59
|
-
const path = relative(dirname(packageJsonPath), resolve(outputPath));
|
|
60
|
-
console.log(`\nCSS saved to ${outputPath}`);
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
runMain(main);
|
|
64
|
-
export function writeIfNotExists(path, data) {
|
|
65
|
-
if (existsSync(path)) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
writeFileSync(path, data);
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|