swatchkit 0.0.7 → 0.0.9

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 (3) hide show
  1. package/README.md +59 -4
  2. package/build.js +71 -5
  3. package/package.json +5 -2
package/README.md CHANGED
@@ -71,7 +71,59 @@ SwatchKit scaffolds a design system for you. Edit the JSON files in `swatches/to
71
71
 
72
72
  Documentation patterns for these are automatically created alongside the JSON files.
73
73
 
74
- ### 3. CSS Workflow
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
+ { "name": "jumbo", "max": 64, "fluidRatio": 1.5 } // Auto: 42.6px -> 64px (64 / 1.5)
94
+ ]
95
+ }
96
+ ```
97
+
98
+ **Generated CSS:**
99
+ ```css
100
+ :root {
101
+ --s-base: 1rem;
102
+ --s-md: clamp(1rem, ... , 1.25rem);
103
+ --s-lg: clamp(1.2rem, ... , 1.5rem);
104
+ --s-xl: clamp(2rem, ... , 2.5rem);
105
+ --s-jumbo: clamp(2.66rem, ... , 4rem);
106
+ }
107
+ ```
108
+
109
+ ### 4. Hybrid Text Leading
110
+
111
+ You can mix modular scales with manual overrides.
112
+
113
+ **Example (`swatches/tokens/text-leading.json`):**
114
+ ```json
115
+ {
116
+ "base": 1,
117
+ "ratio": 1.2,
118
+ "items": [
119
+ { "name": "tight", "step": -1 }, // Modular: 1 * (1.2 ^ -1)
120
+ { "name": "flat", "value": 1 }, // Manual: 1
121
+ { "name": "loose", "step": 1 } // Modular: 1 * (1.2 ^ 1)
122
+ ]
123
+ }
124
+ ```
125
+
126
+ ### 5. CSS Workflow
75
127
 
76
128
  SwatchKit generates `css/tokens.css` with your design tokens as CSS custom properties. The starter `css/styles.css` imports this file:
77
129
 
@@ -88,7 +140,7 @@ body {
88
140
 
89
141
  The pattern library uses **your stylesheet**, so components render exactly as they will in your app.
90
142
 
91
- ### 4. Custom Layouts
143
+ ### 6. Custom Layouts
92
144
  When you run `swatchkit init`, we create `swatches/_layout.html`.
93
145
  **You own this file.**
94
146
  * Link to your own stylesheets.
@@ -97,7 +149,7 @@ When you run `swatchkit init`, we create `swatches/_layout.html`.
97
149
 
98
150
  SwatchKit injects content into the `<!-- PATTERNS -->`, `<!-- SIDEBAR_LINKS -->`, and `<!-- HEAD_EXTRAS -->` placeholders.
99
151
 
100
- ### 5. JavaScript Bundling
152
+ ### 7. JavaScript Bundling
101
153
  If your component needs client-side JS:
102
154
  1. Create a folder: `swatches/carousel/`.
103
155
  2. Add `index.html` (Markup).
@@ -118,7 +170,7 @@ swatchkit [command] [options]
118
170
  ### Flags
119
171
  | Flag | Short | Description |
120
172
  | :--- | :--- | :--- |
121
- | `--watch` | `-w` | Watch mode (coming soon). |
173
+ | `--watch` | `-w` | Watch files and rebuild on change. |
122
174
  | `--config` | `-c` | Path to config file. |
123
175
  | `--input` | `-i` | Pattern directory (Default: `swatches/`). |
124
176
  | `--outDir` | `-o` | Output directory (Default: `public/swatchkit`). |
@@ -138,6 +190,9 @@ module.exports = {
138
190
  // Override CSS directory
139
191
  css: './assets/css',
140
192
 
193
+ // Exclude files (supports glob patterns)
194
+ exclude: ['*.test.js', 'temp*'],
195
+
141
196
  // Override token settings
142
197
  tokens: {
143
198
  input: './design-tokens', // Where token JSON files live
package/build.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  const fs = require("fs");
3
3
  const path = require("path");
4
+ const chokidar = require("chokidar");
4
5
  const { processTokens } = require("./src/tokens");
5
6
 
6
7
  /**
@@ -66,6 +67,27 @@ function loadConfig(configPath) {
66
67
  return {};
67
68
  }
68
69
 
70
+ // --- 2.5 Glob Matching Helper ---
71
+ function matchesPattern(filename, pattern) {
72
+ // Simple wildcard support
73
+ if (pattern.includes("*")) {
74
+ const parts = pattern.split("*");
75
+ // Handle "foo*"
76
+ if (pattern.endsWith("*") && !pattern.startsWith("*")) {
77
+ return filename.startsWith(parts[0]);
78
+ }
79
+ // Handle "*bar"
80
+ if (pattern.startsWith("*") && !pattern.endsWith("*")) {
81
+ return filename.endsWith(parts[1]);
82
+ }
83
+ // Handle "*bar*"
84
+ if (pattern.startsWith("*") && pattern.endsWith("*")) {
85
+ return filename.includes(parts[1]);
86
+ }
87
+ }
88
+ return filename === pattern;
89
+ }
90
+
69
91
  // --- 3. Smart Defaults & Path Resolution ---
70
92
  function resolveSettings(cliOptions, fileConfig) {
71
93
  const cwd = process.cwd();
@@ -108,12 +130,16 @@ function resolveSettings(cliOptions, fileConfig) {
108
130
  const tokensDir = fileConfig.tokens?.input
109
131
  ? path.resolve(cwd, fileConfig.tokens.input)
110
132
  : path.join(patternsDir, "tokens");
133
+
134
+ // Exclude patterns
135
+ const exclude = fileConfig.exclude || [];
111
136
 
112
137
  return {
113
138
  patternsDir,
114
139
  outDir,
115
140
  cssDir,
116
141
  tokensDir,
142
+ exclude,
117
143
  fileConfig, // Expose config to init
118
144
  // Internal layout template (relative to this script)
119
145
  internalLayout: path.join(__dirname, "src/layout.html"),
@@ -264,8 +290,10 @@ function scanDirectory(dir, scriptsCollector, exclude = []) {
264
290
  const items = fs.readdirSync(dir);
265
291
 
266
292
  items.forEach((item) => {
267
- // Skip excluded items, _layout.html, or hidden files
268
- if (exclude.includes(item)) return;
293
+ // Skip excluded items
294
+ if (exclude.some(pattern => matchesPattern(item, pattern))) return;
295
+
296
+ // Skip _layout.html or hidden files
269
297
  if (item.startsWith("_") || item.startsWith(".")) return;
270
298
 
271
299
  const itemPath = path.join(dir, item);
@@ -372,8 +400,9 @@ function build(settings) {
372
400
  const tokensDir = path.join(settings.patternsDir, "tokens");
373
401
  const tokenPages = scanDirectory(tokensDir, scripts);
374
402
 
375
- // Pass 2: Patterns (in [patternsDir], excluding 'tokens')
376
- const patternPages = scanDirectory(settings.patternsDir, scripts, ["tokens"]);
403
+ // Pass 2: Patterns (in [patternsDir], excluding 'tokens' and user excludes)
404
+ const userExcludes = settings.exclude || [];
405
+ const patternPages = scanDirectory(settings.patternsDir, scripts, ["tokens", ...userExcludes]);
377
406
 
378
407
  // Combine for content generation (Tokens first, then Patterns)
379
408
  const allPatterns = [...tokenPages, ...patternPages];
@@ -451,6 +480,43 @@ function build(settings) {
451
480
  console.log(`Build complete! Generated ${settings.outputFile}`);
452
481
  }
453
482
 
483
+ // --- 6. Watch Logic ---
484
+ function watch(settings) {
485
+ const watchPaths = [
486
+ settings.patternsDir,
487
+ settings.tokensDir,
488
+ settings.projectLayout,
489
+ settings.stylesCssFile
490
+ ].filter(p => fs.existsSync(p)); // Only watch files that exist
491
+
492
+ console.log("[SwatchKit] Watch mode enabled.");
493
+ console.log("Watching for changes in:");
494
+ watchPaths.forEach(p => console.log(` - ${p}`));
495
+
496
+ let buildTimeout;
497
+ const rebuild = () => {
498
+ if (buildTimeout) clearTimeout(buildTimeout);
499
+ buildTimeout = setTimeout(() => {
500
+ try {
501
+ console.log("[SwatchKit] Change detected. Rebuilding...");
502
+ build(settings);
503
+ } catch (e) {
504
+ console.error("[SwatchKit] Build failed:", e.message);
505
+ }
506
+ }, 100); // 100ms debounce
507
+ };
508
+
509
+ const watcher = chokidar.watch(watchPaths, {
510
+ ignored: /(^|[\/\\])\../, // ignore dotfiles
511
+ persistent: true,
512
+ ignoreInitial: true
513
+ });
514
+
515
+ watcher.on('all', (event, path) => {
516
+ rebuild();
517
+ });
518
+ }
519
+
454
520
  // --- Main Execution ---
455
521
  try {
456
522
  const cliOptions = parseArgs(process.argv);
@@ -462,7 +528,7 @@ try {
462
528
  } else {
463
529
  build(settings);
464
530
  if (cliOptions.watch) {
465
- console.log("[SwatchKit] Watch mode is not yet fully implemented.");
531
+ watch(settings);
466
532
  }
467
533
  }
468
534
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swatchkit",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "A lightweight tool for creating HTML pattern libraries.",
5
5
  "main": "build.js",
6
6
  "bin": {
@@ -23,5 +23,8 @@
23
23
  "bugs": {
24
24
  "url": "https://github.com/cwebley/swatchkit/issues"
25
25
  },
26
- "homepage": "https://github.com/cwebley/swatchkit#readme"
26
+ "homepage": "https://github.com/cwebley/swatchkit#readme",
27
+ "dependencies": {
28
+ "chokidar": "^5.0.0"
29
+ }
27
30
  }