swatchkit 0.0.6 → 0.0.8
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 +101 -14
- package/build.js +70 -26
- package/package.json +1 -1
- package/src/layout.html +1 -1
package/README.md
CHANGED
|
@@ -16,10 +16,23 @@ npx swatchkit init
|
|
|
16
16
|
npx swatchkit
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
This will:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
This will create:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
my-project/
|
|
23
|
+
├── css/
|
|
24
|
+
│ ├── tokens.css # Generated design tokens (CSS custom properties)
|
|
25
|
+
│ └── styles.css # Starter stylesheet (imports tokens.css)
|
|
26
|
+
├── swatches/
|
|
27
|
+
│ ├── _layout.html # Layout template (you own this)
|
|
28
|
+
│ └── tokens/ # Token definitions + documentation patterns
|
|
29
|
+
│ ├── colors.json
|
|
30
|
+
│ ├── colors.html
|
|
31
|
+
│ └── ...
|
|
32
|
+
└── public/
|
|
33
|
+
└── swatchkit/ # Built pattern library
|
|
34
|
+
└── index.html
|
|
35
|
+
```
|
|
23
36
|
|
|
24
37
|
---
|
|
25
38
|
|
|
@@ -47,7 +60,7 @@ By default, SwatchKit looks for a `swatches/` folder in your project root.
|
|
|
47
60
|
* **Component Folder:** Drop a folder like `swatches/carousel/` containing `index.html`. It works the same way.
|
|
48
61
|
|
|
49
62
|
### 2. Design Token Engine
|
|
50
|
-
SwatchKit scaffolds a
|
|
63
|
+
SwatchKit scaffolds a design system for you. Edit the JSON files in `swatches/tokens/`, and SwatchKit auto-generates `css/tokens.css`.
|
|
51
64
|
|
|
52
65
|
**Supported Tokens:**
|
|
53
66
|
* **Colors** (`colors.json`): Generates palettes.
|
|
@@ -56,18 +69,85 @@ SwatchKit scaffolds a powerful, CUBE CSS-friendly design system for you. Edit th
|
|
|
56
69
|
* **Modular Leading** (`text-leading.json`): Generates line-heights using `pow()` modular scales.
|
|
57
70
|
* **Fonts & Weights**: Manages font families and weights.
|
|
58
71
|
|
|
59
|
-
|
|
72
|
+
Documentation patterns for these are automatically created alongside the JSON files.
|
|
73
|
+
|
|
74
|
+
### 3. Intelligent Fluid Logic (New!)
|
|
75
|
+
|
|
76
|
+
SwatchKit can auto-calculate fluid typography and spacing scales.
|
|
77
|
+
|
|
78
|
+
**Static vs Fluid:**
|
|
79
|
+
* **Static:** Provide a `value` (e.g. `"16px"`).
|
|
80
|
+
* **Fluid:** Provide `min` and `max` (e.g. `16` and `18`).
|
|
81
|
+
* **Auto-Fluid:** Provide just ONE side (`min` or `max`), and SwatchKit calculates the other using a default ratio (1.125).
|
|
82
|
+
|
|
83
|
+
**Example (`swatches/tokens/text-sizes.json`):**
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"title": "Text Sizes",
|
|
87
|
+
"fluidRatio": 1.25,
|
|
88
|
+
"items": [
|
|
89
|
+
{ "name": "base", "value": "1rem" }, // Static: 1rem always
|
|
90
|
+
{ "name": "md", "min": 16, "max": 20 }, // Fluid: 16px -> 20px
|
|
91
|
+
{ "name": "lg", "max": 24 }, // Auto: 19.2px -> 24px (24 / 1.25)
|
|
92
|
+
{ "name": "xl", "min": 32 } // Auto: 32px -> 40px (32 * 1.25)
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Generated CSS:**
|
|
98
|
+
```css
|
|
99
|
+
:root {
|
|
100
|
+
--s-base: 1rem;
|
|
101
|
+
--s-md: clamp(1rem, ... , 1.25rem);
|
|
102
|
+
--s-lg: clamp(1.2rem, ... , 1.5rem);
|
|
103
|
+
--s-xl: clamp(2rem, ... , 2.5rem);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 4. Hybrid Text Leading
|
|
108
|
+
|
|
109
|
+
You can mix modular scales with manual overrides.
|
|
60
110
|
|
|
61
|
-
|
|
111
|
+
**Example (`swatches/tokens/text-leading.json`):**
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"base": 1,
|
|
115
|
+
"ratio": 1.2,
|
|
116
|
+
"items": [
|
|
117
|
+
{ "name": "tight", "step": -1 }, // Modular: 1 * (1.2 ^ -1)
|
|
118
|
+
{ "name": "flat", "value": 1 }, // Manual: 1
|
|
119
|
+
{ "name": "loose", "step": 1 } // Modular: 1 * (1.2 ^ 1)
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 5. CSS Workflow
|
|
125
|
+
|
|
126
|
+
SwatchKit generates `css/tokens.css` with your design tokens as CSS custom properties. The starter `css/styles.css` imports this file:
|
|
127
|
+
|
|
128
|
+
```css
|
|
129
|
+
@import 'tokens.css';
|
|
130
|
+
|
|
131
|
+
body {
|
|
132
|
+
font-family: var(--font-base);
|
|
133
|
+
color: var(--color-dark);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Add your app styles here */
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The pattern library uses **your stylesheet**, so components render exactly as they will in your app.
|
|
140
|
+
|
|
141
|
+
### 6. Custom Layouts
|
|
62
142
|
When you run `swatchkit init`, we create `swatches/_layout.html`.
|
|
63
143
|
**You own this file.**
|
|
64
|
-
*
|
|
144
|
+
* Link to your own stylesheets.
|
|
65
145
|
* Add custom fonts, scripts, or meta tags.
|
|
66
146
|
* Change the HTML structure, logo, or classes.
|
|
67
147
|
|
|
68
|
-
SwatchKit
|
|
148
|
+
SwatchKit injects content into the `<!-- PATTERNS -->`, `<!-- SIDEBAR_LINKS -->`, and `<!-- HEAD_EXTRAS -->` placeholders.
|
|
69
149
|
|
|
70
|
-
###
|
|
150
|
+
### 7. JavaScript Bundling
|
|
71
151
|
If your component needs client-side JS:
|
|
72
152
|
1. Create a folder: `swatches/carousel/`.
|
|
73
153
|
2. Add `index.html` (Markup).
|
|
@@ -100,15 +180,22 @@ Optional. Create `swatchkit.config.js` in your root for persistent settings.
|
|
|
100
180
|
```javascript
|
|
101
181
|
module.exports = {
|
|
102
182
|
// Override default pattern directory
|
|
103
|
-
input: './
|
|
183
|
+
input: './patterns',
|
|
104
184
|
|
|
105
185
|
// Override default output directory
|
|
106
|
-
outDir: './dist/
|
|
186
|
+
outDir: './dist/patterns',
|
|
187
|
+
|
|
188
|
+
// Override CSS directory
|
|
189
|
+
css: './assets/css',
|
|
190
|
+
|
|
191
|
+
// Exclude files (supports glob patterns)
|
|
192
|
+
exclude: ['*.test.js', 'temp*'],
|
|
107
193
|
|
|
108
|
-
// Override
|
|
194
|
+
// Override token settings
|
|
109
195
|
tokens: {
|
|
196
|
+
input: './design-tokens', // Where token JSON files live
|
|
110
197
|
leading: {
|
|
111
|
-
ratio: 1.25,
|
|
198
|
+
ratio: 1.25, // Modular scale ratio
|
|
112
199
|
base: 1
|
|
113
200
|
}
|
|
114
201
|
}
|
package/build.js
CHANGED
|
@@ -66,6 +66,27 @@ function loadConfig(configPath) {
|
|
|
66
66
|
return {};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// --- 2.5 Glob Matching Helper ---
|
|
70
|
+
function matchesPattern(filename, pattern) {
|
|
71
|
+
// Simple wildcard support
|
|
72
|
+
if (pattern.includes("*")) {
|
|
73
|
+
const parts = pattern.split("*");
|
|
74
|
+
// Handle "foo*"
|
|
75
|
+
if (pattern.endsWith("*") && !pattern.startsWith("*")) {
|
|
76
|
+
return filename.startsWith(parts[0]);
|
|
77
|
+
}
|
|
78
|
+
// Handle "*bar"
|
|
79
|
+
if (pattern.startsWith("*") && !pattern.endsWith("*")) {
|
|
80
|
+
return filename.endsWith(parts[1]);
|
|
81
|
+
}
|
|
82
|
+
// Handle "*bar*"
|
|
83
|
+
if (pattern.startsWith("*") && pattern.endsWith("*")) {
|
|
84
|
+
return filename.includes(parts[1]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return filename === pattern;
|
|
88
|
+
}
|
|
89
|
+
|
|
69
90
|
// --- 3. Smart Defaults & Path Resolution ---
|
|
70
91
|
function resolveSettings(cliOptions, fileConfig) {
|
|
71
92
|
const cwd = process.cwd();
|
|
@@ -97,12 +118,27 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
97
118
|
? path.resolve(cwd, fileConfig.outDir)
|
|
98
119
|
: path.join(cwd, "public/swatchkit");
|
|
99
120
|
|
|
100
|
-
|
|
121
|
+
// CSS directory - where tokens.css and user's styles.css live
|
|
122
|
+
// Default: css/ at project root (not src/css/)
|
|
123
|
+
const cssDir = fileConfig.css
|
|
124
|
+
? path.resolve(cwd, fileConfig.css)
|
|
125
|
+
: path.join(cwd, "css");
|
|
126
|
+
|
|
127
|
+
// Token definitions directory
|
|
128
|
+
// Default: swatches/tokens/ (not src/tokens/)
|
|
129
|
+
const tokensDir = fileConfig.tokens?.input
|
|
130
|
+
? path.resolve(cwd, fileConfig.tokens.input)
|
|
131
|
+
: path.join(patternsDir, "tokens");
|
|
132
|
+
|
|
133
|
+
// Exclude patterns
|
|
134
|
+
const exclude = fileConfig.exclude || [];
|
|
101
135
|
|
|
102
136
|
return {
|
|
103
137
|
patternsDir,
|
|
104
138
|
outDir,
|
|
105
139
|
cssDir,
|
|
140
|
+
tokensDir,
|
|
141
|
+
exclude,
|
|
106
142
|
fileConfig, // Expose config to init
|
|
107
143
|
// Internal layout template (relative to this script)
|
|
108
144
|
internalLayout: path.join(__dirname, "src/layout.html"),
|
|
@@ -116,6 +152,7 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
116
152
|
outputFile: path.join(outDir, "index.html"),
|
|
117
153
|
outputJsFile: path.join(outDir, "js/patterns.js"),
|
|
118
154
|
tokensCssFile: path.join(cssDir, "tokens.css"),
|
|
155
|
+
stylesCssFile: path.join(cssDir, "styles.css"),
|
|
119
156
|
};
|
|
120
157
|
}
|
|
121
158
|
|
|
@@ -129,27 +166,26 @@ function runInit(settings, options) {
|
|
|
129
166
|
fs.mkdirSync(settings.patternsDir, { recursive: true });
|
|
130
167
|
}
|
|
131
168
|
|
|
132
|
-
// Create
|
|
133
|
-
const
|
|
134
|
-
if (!fs.existsSync(patternsTokensDir)) {
|
|
135
|
-
console.log(`Creating patterns/tokens directory: ${patternsTokensDir}`);
|
|
136
|
-
fs.mkdirSync(patternsTokensDir, { recursive: true });
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Create src/tokens directory and sample colors.json
|
|
140
|
-
const tokensDir = path.join(process.cwd(), "src/tokens");
|
|
169
|
+
// Create swatches/tokens directory (for both JSON definitions and HTML patterns)
|
|
170
|
+
const tokensDir = settings.tokensDir;
|
|
141
171
|
if (!fs.existsSync(tokensDir)) {
|
|
142
172
|
console.log(`Creating tokens directory: ${tokensDir}`);
|
|
143
173
|
fs.mkdirSync(tokensDir, { recursive: true });
|
|
144
174
|
}
|
|
145
175
|
|
|
176
|
+
// Create css/ directory at project root
|
|
177
|
+
if (!fs.existsSync(settings.cssDir)) {
|
|
178
|
+
console.log(`Creating CSS directory: ${settings.cssDir}`);
|
|
179
|
+
fs.mkdirSync(settings.cssDir, { recursive: true });
|
|
180
|
+
}
|
|
181
|
+
|
|
146
182
|
const copyDefault = (srcFilename, destFilename) => {
|
|
147
183
|
const destPath = path.join(tokensDir, destFilename);
|
|
148
184
|
if (!fs.existsSync(destPath)) {
|
|
149
185
|
const srcPath = path.join(__dirname, 'src/blueprints', srcFilename);
|
|
150
186
|
const content = fs.readFileSync(srcPath, 'utf-8');
|
|
151
187
|
fs.writeFileSync(destPath, content);
|
|
152
|
-
console.log(`Created
|
|
188
|
+
console.log(`Created token file at ${destPath}`);
|
|
153
189
|
}
|
|
154
190
|
};
|
|
155
191
|
|
|
@@ -188,12 +224,12 @@ function runInit(settings, options) {
|
|
|
188
224
|
copyDefault('fonts.json', 'fonts.json');
|
|
189
225
|
|
|
190
226
|
const copyTemplate = (srcFilename, destFilename) => {
|
|
191
|
-
const destPath = path.join(
|
|
227
|
+
const destPath = path.join(tokensDir, destFilename);
|
|
192
228
|
if (!fs.existsSync(destPath)) {
|
|
193
229
|
const srcPath = path.join(__dirname, 'src/templates', srcFilename);
|
|
194
230
|
const content = fs.readFileSync(srcPath, 'utf-8');
|
|
195
231
|
fs.writeFileSync(destPath, content.trim());
|
|
196
|
-
console.log(`Created
|
|
232
|
+
console.log(`Created pattern at ${destPath}`);
|
|
197
233
|
}
|
|
198
234
|
};
|
|
199
235
|
|
|
@@ -206,7 +242,7 @@ function runInit(settings, options) {
|
|
|
206
242
|
copyTemplate('fonts.html', 'fonts.html');
|
|
207
243
|
|
|
208
244
|
// Create shared script for tokens
|
|
209
|
-
const tokensScriptFile = path.join(
|
|
245
|
+
const tokensScriptFile = path.join(tokensDir, "script.js");
|
|
210
246
|
if (!fs.existsSync(tokensScriptFile)) {
|
|
211
247
|
const srcPath = path.join(__dirname, 'src/templates/script.js');
|
|
212
248
|
const content = fs.readFileSync(srcPath, 'utf-8');
|
|
@@ -214,8 +250,16 @@ function runInit(settings, options) {
|
|
|
214
250
|
console.log(`Created tokens script at ${tokensScriptFile}`);
|
|
215
251
|
}
|
|
216
252
|
|
|
217
|
-
//
|
|
218
|
-
|
|
253
|
+
// Create starter styles.css
|
|
254
|
+
if (!fs.existsSync(settings.stylesCssFile)) {
|
|
255
|
+
const srcPath = path.join(__dirname, 'src/blueprints/styles.css');
|
|
256
|
+
const content = fs.readFileSync(srcPath, 'utf-8');
|
|
257
|
+
fs.writeFileSync(settings.stylesCssFile, content);
|
|
258
|
+
console.log(`Created starter stylesheet at ${settings.stylesCssFile}`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Generate initial tokens.css
|
|
262
|
+
processTokens(settings.tokensDir, settings.cssDir);
|
|
219
263
|
|
|
220
264
|
const targetLayout = settings.projectLayout;
|
|
221
265
|
|
|
@@ -245,8 +289,10 @@ function scanDirectory(dir, scriptsCollector, exclude = []) {
|
|
|
245
289
|
const items = fs.readdirSync(dir);
|
|
246
290
|
|
|
247
291
|
items.forEach((item) => {
|
|
248
|
-
// Skip excluded items
|
|
249
|
-
if (exclude.
|
|
292
|
+
// Skip excluded items
|
|
293
|
+
if (exclude.some(pattern => matchesPattern(item, pattern))) return;
|
|
294
|
+
|
|
295
|
+
// Skip _layout.html or hidden files
|
|
250
296
|
if (item.startsWith("_") || item.startsWith(".")) return;
|
|
251
297
|
|
|
252
298
|
const itemPath = path.join(dir, item);
|
|
@@ -329,7 +375,7 @@ function build(settings) {
|
|
|
329
375
|
});
|
|
330
376
|
|
|
331
377
|
// 2.5 Process Tokens
|
|
332
|
-
processTokens(
|
|
378
|
+
processTokens(settings.tokensDir, settings.cssDir);
|
|
333
379
|
|
|
334
380
|
// 3. Copy CSS files
|
|
335
381
|
if (fs.existsSync(settings.cssDir)) {
|
|
@@ -353,8 +399,9 @@ function build(settings) {
|
|
|
353
399
|
const tokensDir = path.join(settings.patternsDir, "tokens");
|
|
354
400
|
const tokenPages = scanDirectory(tokensDir, scripts);
|
|
355
401
|
|
|
356
|
-
// Pass 2: Patterns (in [patternsDir], excluding 'tokens')
|
|
357
|
-
const
|
|
402
|
+
// Pass 2: Patterns (in [patternsDir], excluding 'tokens' and user excludes)
|
|
403
|
+
const userExcludes = settings.exclude || [];
|
|
404
|
+
const patternPages = scanDirectory(settings.patternsDir, scripts, ["tokens", ...userExcludes]);
|
|
358
405
|
|
|
359
406
|
// Combine for content generation (Tokens first, then Patterns)
|
|
360
407
|
const allPatterns = [...tokenPages, ...patternPages];
|
|
@@ -418,11 +465,8 @@ function build(settings) {
|
|
|
418
465
|
layoutContent = fs.readFileSync(settings.internalLayout, "utf-8");
|
|
419
466
|
}
|
|
420
467
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
if (fs.existsSync(settings.distTokensCssFile)) {
|
|
424
|
-
headExtras = '<link rel="stylesheet" href="css/tokens.css">';
|
|
425
|
-
}
|
|
468
|
+
// HEAD_EXTRAS placeholder available for future use (e.g., custom fonts)
|
|
469
|
+
const headExtras = "";
|
|
426
470
|
|
|
427
471
|
const finalHtml = layoutContent
|
|
428
472
|
.replace("<!-- SIDEBAR_LINKS -->", sidebarLinks)
|
package/package.json
CHANGED
package/src/layout.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>SwatchKit</title>
|
|
7
|
-
<link rel="stylesheet" href="
|
|
7
|
+
<link rel="stylesheet" href="css/styles.css" />
|
|
8
8
|
<!-- HEAD_EXTRAS -->
|
|
9
9
|
<style>
|
|
10
10
|
body {
|