@tenphi/tasty 3.10.0 → 3.11.1

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 (88) hide show
  1. package/README.md +403 -380
  2. package/dist/{babel-types-C_7kRP38.d.ts → babel-types-BKDTT4--.d.ts} +2 -2
  3. package/dist/chunks/async-storage-f9j9JRtq.js +37 -0
  4. package/dist/chunks/async-storage-f9j9JRtq.js.map +1 -0
  5. package/dist/chunks/{build-config-l2Ys-AJr.js → build-config-5d8WlQbq.js} +5 -5
  6. package/dist/chunks/{build-config-l2Ys-AJr.js.map → build-config-5d8WlQbq.js.map} +1 -1
  7. package/dist/chunks/{collector-CaNtsRtn.js → collector-CjCak4iE.js} +4 -4
  8. package/dist/chunks/{collector-CaNtsRtn.js.map → collector-CjCak4iE.js.map} +1 -1
  9. package/dist/chunks/{config-engine-CpExZO_T.js → config-engine-uOFYZidB.js} +4 -4
  10. package/dist/chunks/{config-engine-CpExZO_T.js.map → config-engine-uOFYZidB.js.map} +1 -1
  11. package/dist/chunks/config-file-DlZXJMj8.js +25 -0
  12. package/dist/chunks/config-file-DlZXJMj8.js.map +1 -0
  13. package/dist/chunks/{css-definitions-DAIJxzFY.js → css-definitions-ubrHP97m.js} +88 -77
  14. package/dist/chunks/css-definitions-ubrHP97m.js.map +1 -0
  15. package/dist/chunks/{debug-CKy49GEr.js → debug-CJ31U_WE.js} +6 -6
  16. package/dist/chunks/{debug-CKy49GEr.js.map → debug-CJ31U_WE.js.map} +1 -1
  17. package/dist/chunks/{dsl-DRhFWQzo.js → dsl-DYSJc1-T.js} +11 -6
  18. package/dist/chunks/dsl-DYSJc1-T.js.map +1 -0
  19. package/dist/chunks/{react-runtime-oi6i3ELR.js → react-runtime-CyyCI02N.js} +168 -61
  20. package/dist/chunks/react-runtime-CyyCI02N.js.map +1 -0
  21. package/dist/chunks/{runtime-engine-DoULyhPt.js → runtime-engine-BQmOu5-W.js} +53 -36
  22. package/dist/chunks/runtime-engine-BQmOu5-W.js.map +1 -0
  23. package/dist/chunks/{runtime-state-CZ2J5QiZ.js → runtime-state-DEsyUMU-.js} +14 -3
  24. package/dist/chunks/runtime-state-DEsyUMU-.js.map +1 -0
  25. package/dist/chunks/{style-engine-CeKsjtIr.js → style-engine-BX2LshDZ.js} +116 -56
  26. package/dist/chunks/style-engine-BX2LshDZ.js.map +1 -0
  27. package/dist/chunks/{zero-engine-fxKu8Jbn.js → zero-engine-Dw0P4yGM.js} +22 -7
  28. package/dist/chunks/zero-engine-Dw0P4yGM.js.map +1 -0
  29. package/dist/{collector-w4mBj5gd.d.ts → collector-CTU-nl0g.d.ts} +2 -2
  30. package/dist/{config-CrZOfNJ5.d.ts → config-CcxqSZI2.d.ts} +28 -9
  31. package/dist/core/index.d.ts +4 -4
  32. package/dist/core/index.js +7 -7
  33. package/dist/hydrate-CRyjjAyl.d.ts +22 -0
  34. package/dist/{index-CYJtAI9a.d.ts → index--GdqCPlp.d.ts} +58 -16
  35. package/dist/index.d.ts +4 -4
  36. package/dist/index.js +8 -8
  37. package/dist/{merge-styles-VXwJ0Frr.d.ts → merge-styles-DSkVc6CD.d.ts} +2 -2
  38. package/dist/ssr/astro.js +4 -4
  39. package/dist/ssr/client.d.ts +2 -0
  40. package/dist/ssr/client.js +2 -0
  41. package/dist/ssr/index.d.ts +3 -22
  42. package/dist/ssr/index.js +4 -4
  43. package/dist/ssr/index.js.map +1 -1
  44. package/dist/ssr/next-config.d.ts +1 -1
  45. package/dist/ssr/next-config.js +6 -17
  46. package/dist/ssr/next-config.js.map +1 -1
  47. package/dist/ssr/next.d.ts +1 -1
  48. package/dist/ssr/next.js +3 -3
  49. package/dist/static/index.d.ts +2 -2
  50. package/dist/{types-JEY8PVYP.d.ts → types-DJEM_BOJ.d.ts} +6 -6
  51. package/dist/zero/babel.d.ts +1 -1
  52. package/dist/zero/babel.js +30 -19
  53. package/dist/zero/babel.js.map +1 -1
  54. package/dist/zero/index.d.ts +24 -6
  55. package/dist/zero/index.js +4 -4
  56. package/dist/zero/index.js.map +1 -1
  57. package/dist/zero/next.d.ts +1 -1
  58. package/dist/zero/next.js +3 -7
  59. package/dist/zero/next.js.map +1 -1
  60. package/docs/README.md +4 -1
  61. package/docs/adoption.md +25 -17
  62. package/docs/ai-agents.md +39 -34
  63. package/docs/comparison.md +9 -8
  64. package/docs/configuration.md +174 -58
  65. package/docs/debug.md +3 -2
  66. package/docs/design-system.md +117 -15
  67. package/docs/dsl.md +145 -81
  68. package/docs/getting-started.md +81 -24
  69. package/docs/injector.md +41 -40
  70. package/docs/methodology.md +46 -21
  71. package/docs/migration-v3.md +3 -3
  72. package/docs/pipeline.md +19 -16
  73. package/docs/plugins.md +21 -41
  74. package/docs/react-api.md +61 -9
  75. package/docs/runtime-benchmarks.md +4 -4
  76. package/docs/ssr.md +92 -66
  77. package/docs/styles.md +33 -17
  78. package/docs/tasty-static.md +129 -58
  79. package/package.json +23 -9
  80. package/dist/chunks/async-storage-CG5HnUT5.js +0 -20
  81. package/dist/chunks/async-storage-CG5HnUT5.js.map +0 -1
  82. package/dist/chunks/css-definitions-DAIJxzFY.js.map +0 -1
  83. package/dist/chunks/dsl-DRhFWQzo.js.map +0 -1
  84. package/dist/chunks/react-runtime-oi6i3ELR.js.map +0 -1
  85. package/dist/chunks/runtime-engine-DoULyhPt.js.map +0 -1
  86. package/dist/chunks/runtime-state-CZ2J5QiZ.js.map +0 -1
  87. package/dist/chunks/style-engine-CeKsjtIr.js.map +0 -1
  88. package/dist/chunks/zero-engine-fxKu8Jbn.js.map +0 -1
package/docs/debug.md CHANGED
@@ -78,7 +78,7 @@ Retrieves CSS text for a given target. Logs the result with rule count and size.
78
78
  |---|---|
79
79
  | `'all'` | All tasty CSS (component + global + raw) |
80
80
  | `'active'` | CSS for classes currently in the DOM |
81
- | `'unused'` | CSS for injected classes no element carries (cached but not rendered) |
81
+ | `'unused'` | CSS for classes `gc({ force: true })` would delete now — not rendered, not pinned, past the `gc.grace` window |
82
82
  | `'global'` | Only global CSS (from `injectGlobal`) |
83
83
  | `'page'` | All CSS on the page (including non-tasty) |
84
84
  | `'t3a5f'` | CSS for a specific tasty class (class names are `t` + base36 hash) |
@@ -154,7 +154,8 @@ One-shot overview of the entire Tasty CSS state. Logs a compact report.
154
154
  ```typescript
155
155
  interface Summary {
156
156
  activeClasses: string[];
157
- unusedClasses: string[];
157
+ unusedClasses: string[]; // classes gc({ force: true }) would delete now
158
+ hotClasses: string[]; // not rendered, but pinned or inside gc.grace — not yet collectable
158
159
  totalStyledClasses: string[];
159
160
 
160
161
  activeCSSSize: number;
@@ -42,15 +42,25 @@ configure({
42
42
  // Borders
43
43
  '#border': '#e0e0e0',
44
44
 
45
- // Unit values
45
+ // Spacing and shape scale
46
46
  $gap: '8px',
47
47
  $radius: '4px',
48
48
  '$border-width': '1px',
49
49
  '$outline-width': '2px',
50
50
  },
51
+ // Built-in units compile to fixed values by default. Pointing them at the
52
+ // tokens above lets a theme or density mode change the scale at runtime.
53
+ units: {
54
+ x: 'var(--gap)', // 2x → calc(2 * var(--gap))
55
+ r: 'var(--radius)',
56
+ bw: 'var(--border-width)',
57
+ ow: 'var(--outline-width)',
58
+ },
51
59
  });
52
60
  ```
53
61
 
62
+ Leave out the `units` block to keep the built-in fixed scale (`x` = `8px`, `r` = `6px`, `bw` = `1px`, `ow` = `3px`), or set fixed values there instead (`units: { x: '8px', r: '4px' }`). Define the token a unit points at; until you do, `--gap`, `--radius`, `--border-width`, and `--outline-width` start at the built-in unit values. Boolean shorthands follow the same scale: `radius: true` is `1r`, `border: true` is `1bw`, and `outline: true` is `1ow`. See [Built-in Units](dsl.md#built-in-units).
63
+
54
64
  Tokens are injected as CSS custom properties on `:root` when the first style is rendered. They support state maps for theme-aware values:
55
65
 
56
66
  ```tsx
@@ -66,7 +76,7 @@ configure({
66
76
 
67
77
  The `#on-*` convention names the text color that sits on top of a fill — `#on-primary` is the text color on a `#primary` background. This makes state maps self-documenting: `fill: '#primary'` and `color: '#on-primary'` clearly belong together.
68
78
 
69
- For OKHSL-based palette generation with automatic WCAG contrast solving, see [Glaze](https://github.com/tenphi/glaze).
79
+ To generate the whole palette instead of hand-picking values, use [Glaze](https://github.com/tenphi/glaze): it builds light, dark, and high-contrast variants from one hue in the OKHST color space, solves WCAG and APCA contrast, and exports Tasty tokens you can pass straight to `configure({ tokens: theme.tasty() })`.
70
80
 
71
81
  ### Replace tokens for value aliases
72
82
 
@@ -176,11 +186,13 @@ const Card = tasty({
176
186
  styles: {
177
187
  padding: { '': '4x', '@mobile': '2x' },
178
188
  flow: { '': 'row', '@mobile': 'column' },
179
- fill: { '': '#surface', '@dark': '#surface-dark' },
189
+ radius: { '': '1r', '@mobile': '0' },
180
190
  },
181
191
  });
182
192
  ```
183
193
 
194
+ Theme switching belongs in tokens (`'#surface': { '': '#fff', '@dark': '#1c1c1e' }`) rather than in component state maps, so components stay theme-agnostic.
195
+
184
196
  Without aliases, the same component would need the full media query expression inlined in every state map — across every property, in every component. Aliases eliminate that duplication.
185
197
 
186
198
  ---
@@ -279,7 +291,7 @@ const Grid = tasty({
279
291
  display: 'grid',
280
292
  gap: '1x',
281
293
  },
282
- styleProps: [...FLOW_STYLES, 'gridColumns', 'gridRows', 'gridAreas'],
294
+ styleProps: FLOW_STYLES, // includes gridColumns, gridRows, gridAreas
283
295
  });
284
296
  ```
285
297
 
@@ -298,18 +310,54 @@ Product engineers use these to compose layouts without writing CSS:
298
310
  </Grid>
299
311
  ```
300
312
 
313
+ ### Interactive components with variants
314
+
315
+ Variants are named looks that replace each other. Combine them with `modProps` for states that stack, such as size or loading:
316
+
317
+ ```tsx
318
+ const Button = tasty({
319
+ as: 'button',
320
+ modProps: { size: ['sm', 'md', 'lg'] as const },
321
+ styles: {
322
+ recipe: 'interactive',
323
+ padding: { '': '1.5x 3x', 'size=sm': '1x 2x', 'size=lg': '2x 4x' },
324
+ radius: '1r',
325
+ },
326
+ variants: {
327
+ default: {
328
+ fill: {
329
+ '': '#primary',
330
+ ':hover': '#primary-hover',
331
+ disabled: '#surface',
332
+ },
333
+ color: '#on-primary',
334
+ },
335
+ danger: {
336
+ fill: { '': '#danger', ':hover': '#danger-hover', disabled: '#surface' },
337
+ color: '#on-danger',
338
+ },
339
+ },
340
+ });
341
+
342
+ <Button variant="danger" size="lg">
343
+ Delete
344
+ </Button>;
345
+ ```
346
+
347
+ `variant` is typed from the keys, the `default` variant applies when no `variant` prop is passed (or the variant the `variant` option names, such as `variant: 'danger'`), and only the variants that actually render emit CSS. See [React API — Variants](react-api.md#variants).
348
+
301
349
  ### Which styleProps to expose
302
350
 
303
351
  Match the prop set to the component's role:
304
352
 
305
- | Component category | Recommended styleProps |
306
- | ------------------------------------------ | -------------------------------------------------------------- |
307
- | Layout containers (`Space`, `Box`, `Grid`) | `FLOW_STYLES` — flow, gap, align, justify, padding, fill |
308
- | Positioned elements (`Button`, `Badge`) | `POSITION_STYLES` — placeSelf, gridArea, order |
309
- | Text elements | `['preset', 'color']` or a custom subset |
310
- | Compound components | Typically none — styling happens via sub-elements and wrapping |
353
+ | Component category | Recommended styleProps |
354
+ | ------------------------------------------ | --------------------------------------------------------------------------------------------------- |
355
+ | Layout containers (`Space`, `Box`, `Grid`) | `FLOW_STYLES` — flow, gap, align/justify/place, grid templates (add `padding` or `fill` explicitly) |
356
+ | Positioned elements (`Button`, `Badge`) | `POSITION_STYLES` — placeSelf, gridArea, order |
357
+ | Text elements | `['color', ...TEXT_STYLES]` (`preset` is always available) |
358
+ | Compound components | Typically none — styling happens via sub-elements and wrapping |
311
359
 
312
- Exposing too many props weakens the design system's constraints. See [Methodology — styleProps as the public API](methodology.md#styleprops-as-the-public-api) for the rationale.
360
+ `BASE_STYLES` (`display`, `font`, `preset`, `hide`, `whiteSpace`, `opacity`, `transition`) are accepted as props on every component without being listed. Exposing too many props weakens the design system's constraints. See [Methodology — styleProps as the public API](methodology.md#styleprops-as-the-public-api) for the rationale.
313
361
 
314
362
  ---
315
363
 
@@ -369,14 +417,14 @@ For sub-element syntax details (selector affix `$`, `@own()`, `elements` config)
369
417
 
370
418
  ## Defining the override contract
371
419
 
372
- A design system works best when the rules for customization are explicit. Tasty provides three levels of control:
420
+ A design system works best when the rules for customization are explicit. Tasty gives product engineers four sanctioned ways to customize a component, and a few to discourage:
373
421
 
374
422
  ### What product engineers can do
375
423
 
376
424
  1. **Use styleProps** — adjust layout, spacing, positioning through the props the component exposes:
377
425
 
378
426
  ```tsx
379
- <Space flow="row" gap="3x" padding="2x">
427
+ <Space flow="row" gap="3x" placeItems="center">
380
428
  ```
381
429
 
382
430
  2. **Use modProps** — control component states through typed props instead of `mods`:
@@ -398,7 +446,12 @@ A design system works best when the rules for customization are explicit. Tasty
398
446
  ```tsx
399
447
  const DangerButton = tasty(Button, {
400
448
  styles: {
401
- fill: { '': '#danger', ':hover': '#danger-hover' },
449
+ fill: {
450
+ '': '#danger',
451
+ ':hover': '#danger-hover',
452
+ ':active': '#danger-pressed',
453
+ disabled: '@inherit', // a map with '' replaces the parent's; keep its disabled branch
454
+ },
402
455
  color: '#on-danger',
403
456
  },
404
457
  });
@@ -414,6 +467,53 @@ See [Methodology — styles prop vs style prop](methodology.md#styles-prop-vs-st
414
467
 
415
468
  ---
416
469
 
470
+ ## Guardrails: linting and types
471
+
472
+ A vocabulary only holds if mistakes surface early. Register the same names you pass to `configure()` with the ESLint plugin and with TypeScript:
473
+
474
+ ```ts
475
+ // tasty.config.ts — read by @tenphi/eslint-plugin-tasty
476
+ export default {
477
+ tokens: ['#surface', '#text', '#primary', '#danger', '$gap', '$radius'],
478
+ states: ['@mobile', '@tablet', '@desktop', '@dark', '@reduced-motion'],
479
+ presets: ['h1', 'h2', 'h3', 't2', 't3'],
480
+ recipes: ['card', 'elevated', 'input-reset', 'interactive'],
481
+ importSources: ['@my-org/ds'], // where product code imports tasty() from
482
+ };
483
+ ```
484
+
485
+ ```js
486
+ // eslint.config.js
487
+ import tasty from '@tenphi/eslint-plugin-tasty';
488
+
489
+ export default [tasty.configs.recommended]; // or tasty.configs.strict
490
+ ```
491
+
492
+ ```ts
493
+ // tasty.d.ts
494
+ import '@tenphi/tasty';
495
+
496
+ declare module '@tenphi/tasty' {
497
+ interface TastyNamedColors {
498
+ surface: true;
499
+ text: true;
500
+ primary: true;
501
+ danger: true;
502
+ }
503
+ interface TastyPresetNames {
504
+ h1: true;
505
+ h2: true;
506
+ h3: true;
507
+ t2: true;
508
+ t3: true;
509
+ }
510
+ }
511
+ ```
512
+
513
+ Unknown colors, presets, and recipes then fail lint (`valid-color-token`, `valid-preset`, `valid-recipe`), and `strict` adds checks for unknown `$` tokens and state aliases (`valid-custom-property`, `no-unknown-state-alias`). The same names autocomplete in editors. Deriving both lists from the same token and recipe modules that `config.ts` imports keeps all three in sync.
514
+
515
+ ---
516
+
417
517
  ## Project structure
418
518
 
419
519
  A recommended structure for a design system built on Tasty:
@@ -421,6 +521,8 @@ A recommended structure for a design system built on Tasty:
421
521
  ```
422
522
  ds/
423
523
  config.ts # configure() — tokens, units, states, recipes
524
+ tasty.config.ts # Names the ESLint plugin validates against
525
+ tasty.d.ts # TypeScript augmentation for autocomplete
424
526
  primitives/
425
527
  Space.tsx # Layout: flex container with FLOW_STYLES
426
528
  Box.tsx # Generic container
@@ -436,7 +538,7 @@ ds/
436
538
  tokens/
437
539
  colors.ts # Color token definitions
438
540
  typography.ts # Typography presets for configure({ presets })
439
- spacing.ts # Spacing token definitions
541
+ units.ts # Spacing and shape scale for configure({ units })
440
542
  index.ts # Public API: re-exports components + configure
441
543
  ```
442
544