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 CHANGED
@@ -16,10 +16,23 @@ npx swatchkit init
16
16
  npx swatchkit
17
17
  ```
18
18
 
19
- This will:
20
- 1. Create a `swatches/` folder.
21
- 2. Scaffold a complete **Design System** in `src/tokens/` (Colors, Fluid Type, Spacing).
22
- 3. Build your site to `public/swatchkit/`.
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 powerful, CUBE CSS-friendly design system for you. Edit the JSON files in `src/tokens/`, and SwatchKit auto-generates `src/css/tokens.css`.
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
- Docs for these are automatically created in `swatches/tokens/*.html`.
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
- ### 3. Custom Layouts
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
- * Add your own `<link rel="stylesheet" href="/css/app.css">`.
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 simply injects the content into the `<!-- PATTERNS -->`, `<!-- SIDEBAR_LINKS -->`, and `<!-- HEAD_EXTRAS -->` placeholders.
148
+ SwatchKit injects content into the `<!-- PATTERNS -->`, `<!-- SIDEBAR_LINKS -->`, and `<!-- HEAD_EXTRAS -->` placeholders.
69
149
 
70
- ### 4. JavaScript Bundling
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: './src/patterns',
183
+ input: './patterns',
104
184
 
105
185
  // Override default output directory
106
- outDir: './dist/docs',
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 Token Defaults
194
+ // Override token settings
109
195
  tokens: {
196
+ input: './design-tokens', // Where token JSON files live
110
197
  leading: {
111
- ratio: 1.25, // Change modular scale ratio
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
- const cssDir = path.join(cwd, "src/css");
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 patterns/tokens directory
133
- const patternsTokensDir = path.join(settings.patternsDir, "tokens");
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 sample tokens file at ${destPath}`);
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(patternsTokensDir, destFilename);
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 sample pattern at ${destPath}`);
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(patternsTokensDir, "script.js");
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
- // Generate initial CSS
218
- processTokens(process.cwd(), settings.cssDir);
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, _layout.html, or hidden files
249
- if (exclude.includes(item)) return;
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(process.cwd(), settings.cssDir);
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 patternPages = scanDirectory(settings.patternsDir, scripts, ["tokens"]);
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
- let headExtras = "";
422
- // Check if the tokens file exists in the *output* directory (where we copied it to)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swatchkit",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "A lightweight tool for creating HTML pattern libraries.",
5
5
  "main": "build.js",
6
6
  "bin": {
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="/css/global.css" />
7
+ <link rel="stylesheet" href="css/styles.css" />
8
8
  <!-- HEAD_EXTRAS -->
9
9
  <style>
10
10
  body {