@rokkit/cli 1.10.1 → 1.11.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.
@@ -109,10 +109,64 @@ export function generateZenSumiConfig(opts?: {}): {
109
109
  900: string;
110
110
  950: string;
111
111
  };
112
+ beni: {
113
+ 50: string;
114
+ 100: string;
115
+ 200: string;
116
+ 300: string;
117
+ 400: string;
118
+ 500: string;
119
+ 600: string;
120
+ 700: string;
121
+ 800: string;
122
+ 900: string;
123
+ 950: string;
124
+ };
125
+ ai: {
126
+ 50: string;
127
+ 100: string;
128
+ 200: string;
129
+ 300: string;
130
+ 400: string;
131
+ 500: string;
132
+ 600: string;
133
+ 700: string;
134
+ 800: string;
135
+ 900: string;
136
+ 950: string;
137
+ };
138
+ murasaki: {
139
+ 50: string;
140
+ 100: string;
141
+ 200: string;
142
+ 300: string;
143
+ 400: string;
144
+ 500: string;
145
+ 600: string;
146
+ 700: string;
147
+ 800: string;
148
+ 900: string;
149
+ 950: string;
150
+ };
112
151
  };
113
152
  colorSpace: string;
114
153
  tokens: string;
115
154
  skin: {
155
+ overrides: {
156
+ [k: string]: {
157
+ light: string;
158
+ dark: string;
159
+ };
160
+ };
161
+ success: string;
162
+ warning: string;
163
+ danger: string;
164
+ error: string;
165
+ info: string;
166
+ primary: string;
167
+ secondary: string;
168
+ tertiary: string;
169
+ accent: string;
116
170
  surface: {
117
171
  light: string;
118
172
  dark: string;
@@ -121,13 +175,6 @@ export function generateZenSumiConfig(opts?: {}): {
121
175
  light: string;
122
176
  dark: string;
123
177
  };
124
- primary: string;
125
- accent: string;
126
- success: string;
127
- warning: string;
128
- danger: string;
129
- error: string;
130
- info: string;
131
178
  };
132
179
  shape: {
133
180
  radius: string;
@@ -209,10 +256,64 @@ export function generateZenSumiConfig(opts?: {}): {
209
256
  900: string;
210
257
  950: string;
211
258
  };
259
+ beni: {
260
+ 50: string;
261
+ 100: string;
262
+ 200: string;
263
+ 300: string;
264
+ 400: string;
265
+ 500: string;
266
+ 600: string;
267
+ 700: string;
268
+ 800: string;
269
+ 900: string;
270
+ 950: string;
271
+ };
272
+ ai: {
273
+ 50: string;
274
+ 100: string;
275
+ 200: string;
276
+ 300: string;
277
+ 400: string;
278
+ 500: string;
279
+ 600: string;
280
+ 700: string;
281
+ 800: string;
282
+ 900: string;
283
+ 950: string;
284
+ };
285
+ murasaki: {
286
+ 50: string;
287
+ 100: string;
288
+ 200: string;
289
+ 300: string;
290
+ 400: string;
291
+ 500: string;
292
+ 600: string;
293
+ 700: string;
294
+ 800: string;
295
+ 900: string;
296
+ 950: string;
297
+ };
212
298
  };
213
299
  colorSpace: string;
214
300
  tokens: string;
215
301
  skin: {
302
+ overrides: {
303
+ [k: string]: {
304
+ light: string;
305
+ dark: string;
306
+ };
307
+ };
308
+ success: string;
309
+ warning: string;
310
+ danger: string;
311
+ error: string;
312
+ info: string;
313
+ primary: string;
314
+ secondary: string;
315
+ tertiary: string;
316
+ accent: string;
216
317
  surface: {
217
318
  light: string;
218
319
  dark: string;
@@ -221,13 +322,6 @@ export function generateZenSumiConfig(opts?: {}): {
221
322
  light: string;
222
323
  dark: string;
223
324
  };
224
- primary: string;
225
- accent: string;
226
- success: string;
227
- warning: string;
228
- danger: string;
229
- error: string;
230
- info: string;
231
325
  };
232
326
  shape: {
233
327
  radius: string;
@@ -309,10 +403,64 @@ export function generateZenSumiConfig(opts?: {}): {
309
403
  900: string;
310
404
  950: string;
311
405
  };
406
+ beni: {
407
+ 50: string;
408
+ 100: string;
409
+ 200: string;
410
+ 300: string;
411
+ 400: string;
412
+ 500: string;
413
+ 600: string;
414
+ 700: string;
415
+ 800: string;
416
+ 900: string;
417
+ 950: string;
418
+ };
419
+ ai: {
420
+ 50: string;
421
+ 100: string;
422
+ 200: string;
423
+ 300: string;
424
+ 400: string;
425
+ 500: string;
426
+ 600: string;
427
+ 700: string;
428
+ 800: string;
429
+ 900: string;
430
+ 950: string;
431
+ };
432
+ murasaki: {
433
+ 50: string;
434
+ 100: string;
435
+ 200: string;
436
+ 300: string;
437
+ 400: string;
438
+ 500: string;
439
+ 600: string;
440
+ 700: string;
441
+ 800: string;
442
+ 900: string;
443
+ 950: string;
444
+ };
312
445
  };
313
446
  colorSpace: string;
314
447
  tokens: string;
315
448
  skin: {
449
+ overrides: {
450
+ [k: string]: {
451
+ light: string;
452
+ dark: string;
453
+ };
454
+ };
455
+ success: string;
456
+ warning: string;
457
+ danger: string;
458
+ error: string;
459
+ info: string;
460
+ primary: string;
461
+ secondary: string;
462
+ tertiary: string;
463
+ accent: string;
316
464
  surface: {
317
465
  light: string;
318
466
  dark: string;
@@ -321,13 +469,6 @@ export function generateZenSumiConfig(opts?: {}): {
321
469
  light: string;
322
470
  dark: string;
323
471
  };
324
- primary: string;
325
- accent: string;
326
- success: string;
327
- warning: string;
328
- danger: string;
329
- error: string;
330
- info: string;
331
472
  };
332
473
  shape: {
333
474
  radius: string;
@@ -409,10 +550,64 @@ export function generateZenSumiConfig(opts?: {}): {
409
550
  900: string;
410
551
  950: string;
411
552
  };
553
+ beni: {
554
+ 50: string;
555
+ 100: string;
556
+ 200: string;
557
+ 300: string;
558
+ 400: string;
559
+ 500: string;
560
+ 600: string;
561
+ 700: string;
562
+ 800: string;
563
+ 900: string;
564
+ 950: string;
565
+ };
566
+ ai: {
567
+ 50: string;
568
+ 100: string;
569
+ 200: string;
570
+ 300: string;
571
+ 400: string;
572
+ 500: string;
573
+ 600: string;
574
+ 700: string;
575
+ 800: string;
576
+ 900: string;
577
+ 950: string;
578
+ };
579
+ murasaki: {
580
+ 50: string;
581
+ 100: string;
582
+ 200: string;
583
+ 300: string;
584
+ 400: string;
585
+ 500: string;
586
+ 600: string;
587
+ 700: string;
588
+ 800: string;
589
+ 900: string;
590
+ 950: string;
591
+ };
412
592
  };
413
593
  colorSpace: string;
414
594
  tokens: string;
415
595
  skin: {
596
+ overrides: {
597
+ [k: string]: {
598
+ light: string;
599
+ dark: string;
600
+ };
601
+ };
602
+ success: string;
603
+ warning: string;
604
+ danger: string;
605
+ error: string;
606
+ info: string;
607
+ primary: string;
608
+ secondary: string;
609
+ tertiary: string;
610
+ accent: string;
416
611
  surface: {
417
612
  light: string;
418
613
  dark: string;
@@ -421,13 +616,6 @@ export function generateZenSumiConfig(opts?: {}): {
421
616
  light: string;
422
617
  dark: string;
423
618
  };
424
- primary: string;
425
- accent: string;
426
- success: string;
427
- warning: string;
428
- danger: string;
429
- error: string;
430
- info: string;
431
619
  };
432
620
  shape: {
433
621
  radius: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/cli",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "description": "Command line utilities for icon bundling and conversion.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,9 +27,9 @@
27
27
  "vitest": "^4.1.11"
28
28
  },
29
29
  "dependencies": {
30
- "@rokkit/core": "1.10.1",
30
+ "@rokkit/core": "1.11.0",
31
31
  "@mdi/svg": "^7.4.47",
32
- "@rokkit/unocss": "1.10.1",
32
+ "@rokkit/unocss": "1.11.0",
33
33
  "sade": "^1.8.1",
34
34
  "@iconify/tools": "^5.0.14",
35
35
  "@iconify/types": "^2.0.0",
@@ -52,6 +52,18 @@ The preset wraps values into complete colors when it emits CSS vars (see Layer 3
52
52
 
53
53
  ---
54
54
 
55
+ ## Layer 1a — Palette families (prefer these to hand-copied palettes)
56
+
57
+ Before writing palette literals, check whether a rokkit family fits: `zen-sumi`, `sea-glass`,
58
+ `sakura-ember`, `fuji-dusk`, `moss-garden`, from `@rokkit/unocss/palettes`. Each is
59
+ `{ name, description, palettes, skin }` and passes AA for every ink tone and status text in both
60
+ modes. Use `palettes: { ...zenSumi.palettes }, colorSpace: 'oklch', skin: zenSumi.skin` (or
61
+ `skins: { default: zenSumi.skin, 'sea-glass': seaGlass.skin }`). A copied family drifts; an
62
+ imported one follows rokkit's tuning on upgrade. A skin may carry its own `overrides` block
63
+ (token → `palette.shade` or `{ light, dark }`), which is how the families put status text on a
64
+ mode-appropriate shade.
65
+
66
+
55
67
  ## Layer 2 — Skin and skins
56
68
 
57
69
  **What:** A skin maps semantic role names to palette names. The core roles that back the
@@ -312,7 +324,7 @@ Default stays `'core'`.
312
324
  documents the vocabulary). Two starters via the palette prompt:
313
325
 
314
326
  - **Tailwind (rgb)** — `skin` of Tailwind palette names, `colorSpace: 'rgb'`, `tokens: 'core'`. Single-palette → light-leaning (see Layer 2b).
315
- - **Zen-Sumi (OKLCH)** — ships `palettes` (kami/sumi/shu/…), `colorSpace: 'oklch'`, dual-palette `surface`/`ink` → full dark mode out of the box.
327
+ - **Zen-Sumi (OKLCH)** — writes `import { zenSumi } from '@rokkit/unocss/palettes'` with `palettes: zenSumi.palettes`, `skin: zenSumi.skin`, `colorSpace: 'oklch'` → full dark mode out of the box, and the family's tuning follows rokkit upgrades.
316
328
 
317
329
  **`rokkit doctor`** validates an existing setup. Beyond file checks (config exists,
318
330
  `uno.config.js` uses `presetRokkit(config)`, `app.css` imports a theme, `app.html` has the
@@ -70,6 +70,45 @@ Consumer `skins:` in `rokkit.config.js` merge on top and can override or extend
70
70
 
71
71
  ---
72
72
 
73
+ ## Palette families — import, don't copy
74
+
75
+ rokkit exports ready-made colour systems, so an app imports a family instead of copying its
76
+ values. Each family is `{ name, description, palettes, skin }`: `palettes` are bare OKLCH
77
+ components (`colorSpace: 'oklch'`), and `skin` maps every role — surface and ink as a light/dark
78
+ pair, primary, secondary, tertiary, accent and the five status roles.
79
+
80
+ | Family | Mood | Primary | Paper |
81
+ | --- | --- | --- | --- |
82
+ | `zen-sumi` | Sumi ink on washi paper with a vermillion seal — quiet, warm, deliberate | shu (vermillion) | kami / sumi |
83
+ | `sea-glass` | Sea teal and open sky over cool mist — calm, clear, airy | umi (teal) | kiri / yoru |
84
+ | `sakura-ember` | Bitter-orange embers and cherry blossom on warm paper — lively, friendly | daidai (orange) | kami / sumi |
85
+ | `fuji-dusk` | Wisteria and bellflower at dusk over cool mist — dreamy, focused | fuji (violet) | kiri / yoru |
86
+ | `moss-garden` | Moss and running water on warm stone paper — grounded, fresh | koke (emerald) | kami / sumi |
87
+
88
+ ```js
89
+ // rokkit.config.js
90
+ import { zenSumi, seaGlass } from '@rokkit/unocss/palettes'
91
+
92
+ export default {
93
+ palettes: { ...zenSumi.palettes, ...seaGlass.palettes },
94
+ colorSpace: 'oklch',
95
+ skins: { default: zenSumi.skin, 'sea-glass': seaGlass.skin }
96
+ }
97
+ ```
98
+
99
+ `PALETTE_FAMILIES` maps every family by name. Families share a palette name only where the
100
+ values are identical, so several can be spread into one `palettes` block.
101
+
102
+ Every family is held to the same bar in both modes: all four ink tones read at AA (4.5:1) on
103
+ `paper` and `paper-soft`; primary and the status roles are distinct palettes; the primary fill
104
+ takes a readable on-colour; and status text (`text-danger`, `-success`, `-warning`, `-info`)
105
+ reads at AA on paper. No single shade does that on both light and dark paper, so each family
106
+ skin carries its own `overrides` — status text uses a darker shade on light paper and a lighter
107
+ one on dark paper (zen-sumi: `danger` is `beni.600` in light, `beni.400` in dark). A skin
108
+ `overrides` block takes the same shape as the config's, and applies wherever that skin
109
+ applies. `text-on-{role}` reads `--on-{role}`, which the preset derives per skin and mode from
110
+ the fill actually painted.
111
+
73
112
  ## Switching at runtime
74
113
 
75
114
  Three moving parts: **`vibe.skin`** (reactive state), **`themable`** (writes `data-skin` to
package/src/init.js CHANGED
@@ -5,6 +5,7 @@ import { resolve } from 'path'
5
5
  import { execFileSync } from 'child_process'
6
6
  import { detectPackageManager, buildInstallCommand } from './upgrade.js'
7
7
  import { themeInitScript } from '@rokkit/unocss/hooks'
8
+ import { PALETTE_FAMILIES, zenSumi } from '@rokkit/unocss/palettes'
8
9
 
9
10
  const ROKKIT_PACKAGES = ['@rokkit/ui', '@rokkit/unocss', '@rokkit/themes', '@rokkit/icons']
10
11
  const LOCKFILES = ['bun.lock', 'bun.lockb', 'pnpm-lock.yaml', 'yarn.lock', 'package-lock.json']
@@ -36,6 +37,41 @@ const OKLCH_PALETTES_NOTE = `/**
36
37
  */
37
38
  `
38
39
 
40
+ /**
41
+ * Exported palette families, by the binding a config imports them under. A family's
42
+ * `palettes` or `skin` in a config serializes as a reference to the import, not a copy.
43
+ */
44
+ const FAMILY_BINDINGS = Object.values(PALETTE_FAMILIES).map((family) => ({
45
+ family,
46
+ binding: family.name.replace(/-(\w)/g, (_, c) => c.toUpperCase())
47
+ }))
48
+
49
+ /**
50
+ * The families a config uses by reference, and the JSON with each reference written as an
51
+ * expression (`zenSumi.palettes`) instead of its values.
52
+ * @param {Record<string, unknown>} config
53
+ * @returns {{ imports: string[], json: string }}
54
+ */
55
+ function serializeFamilies(config) {
56
+ const used = new Set()
57
+ const json = JSON.stringify(
58
+ config,
59
+ (_key, value) => {
60
+ for (const { family, binding } of FAMILY_BINDINGS) {
61
+ for (const part of ['palettes', 'skin']) {
62
+ if (value === family[part]) {
63
+ used.add(binding)
64
+ return `@@${binding}.${part}@@`
65
+ }
66
+ }
67
+ }
68
+ return value
69
+ },
70
+ 2
71
+ ).replace(/"@@([\w.]+)@@"/g, '$1')
72
+ return { imports: [...used], json }
73
+ }
74
+
39
75
  /**
40
76
  * Derive a safe localStorage key from an npm package name.
41
77
  * Strips the scope, keeps case, maps unsafe chars to '-'. Returns '' when there
@@ -58,7 +94,9 @@ export function storageKeyFromName(name) {
58
94
  */
59
95
  export function serializeRokkitConfig(config) {
60
96
  const palettesNote = config.palettes ? OKLCH_PALETTES_NOTE : ''
61
- return `${NAMED_TOKEN_HEADER}${palettesNote}export default ${JSON.stringify(config, null, 2)}\n`
97
+ const { imports, json } = serializeFamilies(config)
98
+ const importLine = imports.length ? `import { ${imports.join(', ')} } from '@rokkit/unocss/palettes'\n\n` : ''
99
+ return `${importLine}${NAMED_TOKEN_HEADER}${palettesNote}export default ${json}\n`
62
100
  }
63
101
 
64
102
  /**
@@ -169,40 +207,6 @@ function resolveSkin(palette, customColors) {
169
207
  }
170
208
  }
171
209
 
172
- // Zen-Sumi OKLCH palettes — bare "L C H" components (colorSpace: 'oklch').
173
- const ZEN_SUMI_PALETTES = {
174
- kami: {
175
- 50: '0.985 0.005 85', 100: '0.975 0.008 85', 200: '0.955 0.010 85',
176
- 300: '0.920 0.012 85', 400: '0.850 0.010 70', 500: '0.750 0.008 50',
177
- 600: '0.510 0.010 50', 700: '0.470 0.012 50', 800: '0.380 0.012 50',
178
- 900: '0.220 0.012 50', 950: '0.170 0.010 50'
179
- },
180
- sumi: {
181
- 50: '0.170 0.010 50', 100: '0.210 0.012 50', 200: '0.250 0.012 50',
182
- 300: '0.320 0.012 50', 400: '0.420 0.010 50', 500: '0.570 0.010 50',
183
- 600: '0.660 0.009 85', 700: '0.720 0.009 85', 800: '0.780 0.008 85',
184
- 900: '0.940 0.008 85', 950: '0.975 0.008 85'
185
- },
186
- shu: {
187
- 50: '0.970 0.020 35', 100: '0.940 0.040 35', 200: '0.880 0.070 35',
188
- 300: '0.800 0.100 35', 400: '0.700 0.130 35', 500: '0.580 0.150 35',
189
- 600: '0.500 0.140 35', 700: '0.420 0.120 35', 800: '0.350 0.100 35',
190
- 900: '0.280 0.080 35', 950: '0.220 0.060 35'
191
- },
192
- hisui: {
193
- 50: '0.970 0.015 160', 100: '0.940 0.030 160', 200: '0.880 0.050 160',
194
- 300: '0.800 0.065 160', 400: '0.720 0.075 160', 500: '0.620 0.080 160',
195
- 600: '0.540 0.075 160', 700: '0.460 0.065 160', 800: '0.380 0.055 160',
196
- 900: '0.300 0.045 160', 950: '0.240 0.035 160'
197
- },
198
- kohaku: {
199
- 50: '0.980 0.020 75', 100: '0.950 0.040 75', 200: '0.900 0.070 75',
200
- 300: '0.850 0.095 75', 400: '0.790 0.110 75', 500: '0.720 0.120 75',
201
- 600: '0.640 0.110 75', 700: '0.560 0.095 75', 800: '0.470 0.080 75',
202
- 900: '0.380 0.065 75', 950: '0.300 0.050 75'
203
- }
204
- }
205
-
206
210
  /**
207
211
  * Build the chart config section from user prompt answers.
208
212
  * @param {{ chartColors: string, chartShades: string }} opts
@@ -227,20 +231,10 @@ export function generateChartConfig({ chartColors, chartShades }) {
227
231
  * function rather than being rebuilt per call alongside the user's answers.
228
232
  */
229
233
  const ZEN_SUMI_BASE = {
230
- palettes: ZEN_SUMI_PALETTES,
234
+ palettes: zenSumi.palettes,
231
235
  colorSpace: 'oklch',
232
236
  tokens: 'core',
233
- skin: {
234
- surface: { light: 'kami', dark: 'sumi' },
235
- ink: { light: 'kami', dark: 'sumi' },
236
- primary: 'shu',
237
- accent: 'shu',
238
- success: 'hisui',
239
- warning: 'kohaku',
240
- danger: 'shu',
241
- error: 'shu',
242
- info: 'kohaku'
243
- },
237
+ skin: zenSumi.skin,
244
238
  shape: { radius: 'soft' },
245
239
  typography: {
246
240
  display: "'Fraunces', 'Iowan Old Style', Georgia, serif",