@maccesar/titools 3.2.0 → 4.0.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.
Files changed (102) hide show
  1. package/README.md +27 -61
  2. package/lib/cleanup.js +29 -0
  3. package/lib/commands/agents.js +8 -7
  4. package/lib/commands/skills.js +118 -23
  5. package/lib/config.js +13 -15
  6. package/lib/installer.js +5 -3
  7. package/lib/utils.js +36 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +188 -0
  10. package/skills/alloy-guides/references/CLI_TASKS.md +233 -0
  11. package/skills/alloy-guides/references/CONCEPTS.md +171 -0
  12. package/skills/alloy-guides/references/CONTROLLERS.md +279 -0
  13. package/skills/alloy-guides/references/MODELS.md +742 -0
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +482 -0
  15. package/skills/alloy-guides/references/PURGETSS.md +57 -0
  16. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +235 -0
  17. package/skills/alloy-guides/references/VIEWS_STYLES.md +375 -0
  18. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +102 -0
  19. package/skills/alloy-guides/references/VIEWS_XML.md +581 -0
  20. package/skills/alloy-guides/references/WIDGETS.md +160 -0
  21. package/skills/alloy-howtos/SKILL.md +179 -0
  22. package/skills/alloy-howtos/references/best_practices.md +121 -0
  23. package/skills/alloy-howtos/references/cli_reference.md +230 -0
  24. package/skills/alloy-howtos/references/config_files.md +158 -0
  25. package/skills/alloy-howtos/references/custom_tags.md +148 -0
  26. package/skills/alloy-howtos/references/debugging_troubleshooting.md +78 -0
  27. package/skills/alloy-howtos/references/samples.md +156 -0
  28. package/skills/purgetss/SKILL.md +184 -181
  29. package/skills/purgetss/references/EXAMPLES.md +8 -6
  30. package/skills/purgetss/references/app-branding.md +5 -0
  31. package/skills/purgetss/references/apply-directive.md +1 -1
  32. package/skills/purgetss/references/class-categories.md +1 -1
  33. package/skills/purgetss/references/class-index-properties.md +618 -0
  34. package/skills/purgetss/references/class-index.md +4 -610
  35. package/skills/purgetss/references/cli-commands.md +41 -410
  36. package/skills/purgetss/references/custom-fonts.md +292 -0
  37. package/skills/purgetss/references/custom-rules.md +1 -1
  38. package/skills/purgetss/references/customization-deep-dive.md +64 -1
  39. package/skills/purgetss/references/icon-fonts.md +208 -118
  40. package/skills/purgetss/references/installation-setup.md +4 -4
  41. package/skills/purgetss/references/migration-guide.md +53 -1
  42. package/skills/purgetss/references/multi-density-images.md +53 -2
  43. package/skills/purgetss/references/svg-pipeline.md +249 -0
  44. package/skills/purgetss/references/tikit-components.md +2 -2
  45. package/skills/purgetss/references/titanium-resets.md +2 -2
  46. package/skills/purgetss/references/ui-ux-design.md +7 -5
  47. package/skills/purgetss/references/version-history.md +71 -82
  48. package/skills/ti-api/SKILL.md +128 -0
  49. package/skills/ti-api/references/api-android.md +675 -0
  50. package/skills/ti-api/references/api-app-platform.md +636 -0
  51. package/skills/ti-api/references/api-core.md +764 -0
  52. package/skills/ti-api/references/api-data-network.md +641 -0
  53. package/skills/ti-api/references/api-media.md +655 -0
  54. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  55. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  56. package/skills/ti-api/references/api-modules-map.md +632 -0
  57. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  58. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  59. package/skills/ti-api/references/api-services.md +700 -0
  60. package/skills/ti-api/references/api-ui-android.md +499 -0
  61. package/skills/ti-api/references/api-ui-extras.md +702 -0
  62. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  63. package/skills/ti-api/references/api-ui-ios.md +756 -0
  64. package/skills/ti-api/references/api-ui-lists.md +581 -0
  65. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  66. package/skills/ti-api/references/api-ui-views.md +572 -0
  67. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  68. package/skills/ti-api/references/api-xml-global.md +743 -0
  69. package/skills/ti-guides/SKILL.md +82 -0
  70. package/skills/ti-guides/references/advanced-data-and-images.md +155 -0
  71. package/skills/ti-guides/references/android-manifest.md +97 -0
  72. package/skills/ti-guides/references/app-distribution.md +373 -0
  73. package/skills/ti-guides/references/application-frameworks.md +366 -0
  74. package/skills/ti-guides/references/cli-reference.md +700 -0
  75. package/skills/ti-guides/references/coding-best-practices.md +150 -0
  76. package/skills/ti-guides/references/commonjs-advanced.md +279 -0
  77. package/skills/ti-guides/references/hello-world.md +99 -0
  78. package/skills/ti-guides/references/hyperloop-native-access.md +458 -0
  79. package/skills/ti-guides/references/javascript-primer.md +402 -0
  80. package/skills/ti-guides/references/reserved-words.md +36 -0
  81. package/skills/ti-guides/references/resources.md +172 -0
  82. package/skills/ti-guides/references/style-and-conventions.md +104 -0
  83. package/skills/ti-guides/references/tiapp-config.md +655 -0
  84. package/skills/ti-howtos/SKILL.md +131 -0
  85. package/skills/ti-howtos/references/android-platform-deep-dives.md +609 -0
  86. package/skills/ti-howtos/references/automation-fastlane-appium.md +96 -0
  87. package/skills/ti-howtos/references/buffer-codec-streams.md +162 -0
  88. package/skills/ti-howtos/references/cross-platform-development.md +358 -0
  89. package/skills/ti-howtos/references/debugging-profiling.md +473 -0
  90. package/skills/ti-howtos/references/extending-titanium.md +684 -0
  91. package/skills/ti-howtos/references/google-maps-v2.md +172 -0
  92. package/skills/ti-howtos/references/ios-map-kit.md +149 -0
  93. package/skills/ti-howtos/references/ios-platform-deep-dives.md +595 -0
  94. package/skills/ti-howtos/references/local-data-sources.md +310 -0
  95. package/skills/ti-howtos/references/location-and-maps.md +267 -0
  96. package/skills/ti-howtos/references/media-apis.md +268 -0
  97. package/skills/ti-howtos/references/notification-services.md +539 -0
  98. package/skills/ti-howtos/references/remote-data-sources.md +339 -0
  99. package/skills/ti-howtos/references/tutorials.md +552 -0
  100. package/skills/ti-howtos/references/using-modules.md +182 -0
  101. package/skills/ti-howtos/references/web-content-integration.md +288 -0
  102. package/skills/ti-howtos/references/webpack-build-pipeline.md +125 -0
@@ -0,0 +1,292 @@
1
+ # Custom Fonts
2
+
3
+ Use the `purgetss/fonts/` folder and the `build-fonts` command to register any font in your Titanium app: brand typefaces, custom icon fonts, or community icon libraries that PurgeTSS no longer bundles.
4
+
5
+ For the 4 official icon families that ship with PurgeTSS (Font Awesome 7, Material Icons, Material Symbols, Framework7), see [Icon Fonts](./icon-fonts.md) — they use the `icon-library` command and do **not** require `build-fonts`.
6
+
7
+ ## The `fonts` folder
8
+
9
+ Place `.ttf` or `.otf` files in `./purgetss/fonts/`. For icon fonts, also include the `.css` file that ships with the library. PurgeTSS reads it to extract the Unicode characters for each icon class.
10
+
11
+ This example uses [Bevan and Dancing Script](https://fonts.google.com/share?selection.family=Bevan:ital@0;1%7CDancing%20Script:wght@400;500;600;700) from Google Fonts:
12
+
13
+ `./purgetss/fonts/`
14
+ ```bash
15
+ purgetss
16
+ └─ fonts
17
+ ├─ Bevan-Italic.ttf
18
+ ├─ Bevan-Regular.ttf
19
+ ├─ DancingScript-Bold.ttf
20
+ ├─ DancingScript-Medium.ttf
21
+ ├─ DancingScript-Regular.ttf
22
+ └─ DancingScript-SemiBold.ttf
23
+ ```
24
+
25
+ ### Organizing the fonts folder
26
+
27
+ If you prefer to keep things tidy, group each family in a subfolder. The output is the same.
28
+
29
+ `./purgetss/fonts/`
30
+ ```bash
31
+ purgetss
32
+ └─ fonts
33
+ └─ bevan
34
+ ├─ Bevan-Italic.ttf
35
+ └─ Bevan-Regular.ttf
36
+ └─ dancing-script
37
+ ├─ DancingScript-Bold.ttf
38
+ ├─ DancingScript-Medium.ttf
39
+ ├─ DancingScript-Regular.ttf
40
+ └─ DancingScript-SemiBold.ttf
41
+ ```
42
+
43
+ ## The `build-fonts` command
44
+
45
+ ```bash
46
+ $ purgetss build-fonts [-m] [-f]
47
+
48
+ # alias:
49
+ $ purgetss bf [-m] [-f]
50
+ ```
51
+
52
+ What it does:
53
+
54
+ 1. Creates `./purgetss/styles/fonts.tss` with one `fontFamily` class per file.
55
+ 2. Copies the font files into `./app/assets/fonts/`, renamed to their PostScript names so they work on both iOS and Android.
56
+
57
+ > ℹ️ **INFO — How this differs from the official icon fonts**
58
+ > Unlike the [official icon fonts](./icon-fonts.md), which PurgeTSS resolves automatically from its own bundled files and need no `.tss` in your project, custom fonts **do** generate `./purgetss/styles/fonts.tss`. That file is then folded into the generated `app/styles/app.tss` when you run `purgetss` (or compile your app) — that is where the final classes used by Alloy live.
59
+
60
+ After running `purgetss build-fonts` with the Bevan and Dancing Script example above:
61
+
62
+ `./purgetss/styles/fonts.tss`
63
+ ```css
64
+ // Fonts TSS file generated with PurgeTSS
65
+ // https://purgetss.com/docs/customization/custom-fonts
66
+
67
+ '.bevan-italic': { font: { fontFamily: 'Bevan-Italic' } }
68
+ '.bevan-regular': { font: { fontFamily: 'Bevan-Regular' } }
69
+
70
+ '.dancingscript-bold': { font: { fontFamily: 'DancingScript-Bold' } }
71
+ '.dancingscript-medium': { font: { fontFamily: 'DancingScript-Medium' } }
72
+ '.dancingscript-regular': { font: { fontFamily: 'DancingScript-Regular' } }
73
+ '.dancingscript-semibold': { font: { fontFamily: 'DancingScript-SemiBold' } }
74
+ ```
75
+
76
+ You can now use these classes on any Titanium component with a `font` property: Labels, Buttons, TextFields, TextAreas, ListItems, TableViewRows, and ActivityIndicators.
77
+
78
+ ### Renaming the class
79
+
80
+ To use a shorter or different class name, rename the font file. For example:
81
+
82
+ `./purgetss/fonts/`
83
+ ```bash
84
+ purgetss
85
+ └─ fonts
86
+ └─ dancing-script
87
+ ├─ Script-Bold.ttf
88
+ ├─ Script-Medium.ttf
89
+ ├─ Script-Regular.ttf
90
+ └─ Script-SemiBold.ttf
91
+ ```
92
+
93
+ Running `build-fonts` produces:
94
+
95
+ `./purgetss/styles/fonts.tss`
96
+ ```css
97
+ '.script-bold': { font: { fontFamily: 'DancingScript-Bold' } }
98
+ '.script-medium': { font: { fontFamily: 'DancingScript-Medium' } }
99
+ '.script-regular': { font: { fontFamily: 'DancingScript-Regular' } }
100
+ '.script-semibold': { font: { fontFamily: 'DancingScript-SemiBold' } }
101
+ ```
102
+
103
+ The class name changes, but the actual `fontFamily` value (the PostScript name) stays the same.
104
+
105
+ ## Adding icon fonts
106
+
107
+ Any icon font that ships a `.ttf` (or `.otf`) plus a `.css` file with Unicode characters works the same way.
108
+
109
+ This example uses [map-icons](http://map-icons.com) and [microns](https://www.s-ings.com/projects/microns-icon-font/):
110
+
111
+ `./purgetss/fonts/`
112
+ ```bash
113
+ purgetss
114
+ └─ fonts
115
+ └─ bevan
116
+ └─ dancing-script
117
+ └─ map-icons
118
+ ├─ map-icons.css
119
+ └─ map-icons.ttf
120
+ └─ microns
121
+ ├─ microns.css
122
+ └─ microns.ttf
123
+ ```
124
+
125
+ After `purgetss build-fonts`, the generated `fonts.tss` includes the family classes and one class per icon:
126
+
127
+ `./purgetss/styles/fonts.tss`
128
+ ```css
129
+ // Fonts TSS file generated with PurgeTSS
130
+ // https://purgetss.com/docs/customization/custom-fonts
131
+
132
+ '.map-icons': { font: { fontFamily: 'map-icons' } }
133
+ '.microns': { font: { fontFamily: 'microns' } }
134
+
135
+ /* Unicode Characters */
136
+ /* To use your Icon Fonts in Buttons AND Labels each class sets 'text' and 'title' properties */
137
+
138
+ /* map-icons/map-icons.css */
139
+ '.map-icon-abseiling': { text: '\ue800', title: '\ue800' }
140
+ '.map-icon-accounting': { text: '\ue801', title: '\ue801' }
141
+ '.map-icon-airport': { text: '\ue802', title: '\ue802' }
142
+ '.map-icon-amusement-park': { text: '\ue803', title: '\ue803' }
143
+ '.map-icon-aquarium': { text: '\ue804', title: '\ue804' }
144
+ /* ... */
145
+
146
+ /* microns/microns.css */
147
+ '.mu-arrow-left': { text: '\ue700', title: '\ue700' }
148
+ '.mu-arrow-right': { text: '\ue701', title: '\ue701' }
149
+ '.mu-arrow-up': { text: '\ue702', title: '\ue702' }
150
+ '.mu-arrow-down': { text: '\ue703', title: '\ue703' }
151
+ '.mu-left': { text: '\ue704', title: '\ue704' }
152
+ /* ... */
153
+ ```
154
+
155
+ ## Options
156
+
157
+ Two optional flags adjust what `build-fonts` generates:
158
+
159
+ - `-m, --module`: generates a CommonJS module in `./app/lib/purgetss.fonts.js` that exposes each icon's Unicode string to JavaScript. Handy when you set `label.text` from a controller.
160
+ - `-f, --font-class-from-filename`: uses the font's filename as the font class name and icon prefix instead of the font family name. Useful when you want shorter prefixes. Replaces the old `-p` flag.
161
+
162
+ ### Using `--module`
163
+
164
+ ```bash
165
+ $ purgetss build-fonts --module
166
+
167
+ # alias:
168
+ $ purgetss bf -m
169
+ ```
170
+
171
+ To avoid prefix conflicts between libraries, each icon keeps its prefix as a nested object. Both `icons` and `families` are exported:
172
+
173
+ `./app/lib/purgetss.fonts.js`
174
+ ```javascript
175
+ const icons = {
176
+ // map-icons/map-icons.css
177
+ 'mapIcon': {
178
+ 'abseiling': '\ue800',
179
+ 'accounting': '\ue801',
180
+ 'airport': '\ue802',
181
+ 'amusementPark': '\ue803',
182
+ // ...
183
+ },
184
+ // microns/microns.css
185
+ 'mu': {
186
+ 'arrowLeft': '\ue700',
187
+ 'arrowRight': '\ue701',
188
+ 'arrowUp': '\ue702',
189
+ 'arrowDown': '\ue703',
190
+ // ...
191
+ }
192
+ };
193
+ exports.icons = icons;
194
+
195
+ const families = {
196
+ // map-icons/map-icons.css
197
+ 'mapIcon': 'map-icons',
198
+ // microns/microns.css
199
+ 'mu': 'microns'
200
+ };
201
+ exports.families = families;
202
+ ```
203
+
204
+ ### Using `--font-class-from-filename`
205
+
206
+ When you want the class name and the icon prefix to come from the **filename** of the `.ttf` and `.css` instead of the font family, use `-f`.
207
+
208
+ `./purgetss/fonts/`
209
+ ```bash
210
+ purgetss
211
+ └─ fonts
212
+ └─ map-icons
213
+ ├─ map.ttf
214
+ └─ mp.css
215
+ └─ microns
216
+ ├─ mic.ttf
217
+ └─ mc.css
218
+ ```
219
+
220
+ `./purgetss/styles/fonts.tss`
221
+ ```css
222
+ /* "fontFamily" classes use the font's filename */
223
+ '.map': { font: { fontFamily: 'map-icons' } }
224
+ '.mic': { font: { fontFamily: 'microns' } }
225
+
226
+ /* map-icons/mp.css */
227
+ '.mp-abseiling': { text: '\ue800', title: '\ue800' }
228
+ '.mp-accounting': { text: '\ue801', title: '\ue801' }
229
+ '.mp-airport': { text: '\ue802', title: '\ue802' }
230
+ '.mp-amusement-park': { text: '\ue803', title: '\ue803' }
231
+ '.mp-aquarium': { text: '\ue804', title: '\ue804' }
232
+ /* ... */
233
+
234
+ /* microns/mc.css */
235
+ '.mc-arrow-left': { text: '\ue700', title: '\ue700' }
236
+ '.mc-arrow-right': { text: '\ue701', title: '\ue701' }
237
+ '.mc-arrow-up': { text: '\ue702', title: '\ue702' }
238
+ '.mc-arrow-down': { text: '\ue703', title: '\ue703' }
239
+ '.mc-left': { text: '\ue704', title: '\ue704' }
240
+ /* ... */
241
+ ```
242
+
243
+ `./app/lib/purgetss.fonts.js`
244
+ ```javascript
245
+ const icons = {
246
+ // map-icons/mp.css
247
+ 'mp': {
248
+ 'abseiling': '\ue800',
249
+ 'accounting': '\ue801',
250
+ 'airport': '\ue802',
251
+ 'amusementPark': '\ue803',
252
+ // ...
253
+ },
254
+ // microns/mc.css
255
+ 'mc': {
256
+ 'arrowLeft': '\ue700',
257
+ 'arrowRight': '\ue701',
258
+ 'arrowUp': '\ue702',
259
+ 'arrowDown': '\ue703',
260
+ // ...
261
+ }
262
+ };
263
+ exports.icons = icons;
264
+
265
+ const families = {
266
+ // map-icons/mp.css
267
+ 'mp': 'map-icons',
268
+ // microns/mc.css
269
+ 'mc': 'microns'
270
+ };
271
+ exports.families = families;
272
+ ```
273
+
274
+ > 🛑 **DANGER**
275
+ > Make sure the new prefix is unique and does not conflict with other class prefixes. A duplicate prefix will silently overwrite earlier rules in the generated `fonts.tss`, leaving you with icons that render the wrong glyph at runtime.
276
+
277
+ ## Custom proprietary icon fonts
278
+
279
+ If your design system ships its own icon font, treat it like any other icon library: drop the `.ttf` + `.css` pair into `./purgetss/fonts/<name>/` and run `build-fonts`. The classes are then available in your TSS.
280
+
281
+ ## Community-Discovered Patterns
282
+
283
+ The following notes reflect community experience with `build-fonts` against real-world Titanium projects.
284
+
285
+ > **💡 PostScript renaming**
286
+ > `build-fonts` copies `.ttf`/`.otf` files into `./app/assets/fonts/` renamed to their **PostScript names**. iOS reads PostScript names while Android tolerates filenames; by renaming both platforms work from the same `fontFamily` value.
287
+
288
+ > **🛑 Font Awesome Duotone**
289
+ > Titanium cannot render Font Awesome duotone icons because each icon uses two glyphs. If you work with Font Awesome Pro, avoid documenting duotone as supported.
290
+
291
+ > **💡 Use `--module` to set `text`/`title` from JavaScript**
292
+ > Hardcoding `` in a controller is brittle. The `-m` flag generates a `purgetss.fonts.js` you can `require()` and reference by friendly name: `label.text = icons.fa.home`. Combine with `families` to set `font.fontFamily` programmatically.
@@ -16,7 +16,7 @@ Whether you want to style a Ti Element (a markup element such as `Label`), a cus
16
16
 
17
17
  > **CAUTION — Migrating from PurgeTSS v4 or v5 to v7+**
18
18
  >
19
- > If your project started on PurgeTSS v5 or earlier and you are now on 7.x.x or later, the class-naming convention changed (`camelCase` -> `kebab-case`) and the config moved to ESM-style `config.cjs`. The recommended upgrade path is:
19
+ > If your project started on PurgeTSS v5 or earlier and you are now on 7.x.x or later, the class-naming convention changed (`camelCase` -> `kebab-case`) and the config moved to CommonJS-style `config.cjs`. The recommended upgrade path is:
20
20
  >
21
21
  > 1. **Audit current usage.** Set `purge.options.missing` to `true` in `config.cjs`. PurgeTSS will append a list of missing classes at the end of `app.tss` after the next compile — every entry is a class name you still need to migrate.
22
22
  > 2. **Rename selectors.** Convert every `.myCustomClassName` to `.my-custom-class-name` in both XML markup and `config.cjs`. The old camelCase names will not match anymore.
@@ -57,9 +57,11 @@ module.exports = {
57
57
  confirmOverwrites: true // prompt before overwriting files (set false to skip)
58
58
  },
59
59
  images: {
60
+ autoSync: true, // false = SVG pipeline computes dims but doesn't write to images.files (v7.11.0)
60
61
  quality: 85, // JPEG/WebP/AVIF quality (0-100)
61
62
  format: null, // null = keep original; 'webp' | 'jpeg' | 'png' to convert every image
62
- confirmOverwrites: true // prompt before overwriting files (set false to skip)
63
+ confirmOverwrites: true, // prompt before overwriting files (set false to skip)
64
+ files: [] // per-file overrides: [{ filename, width, height? }] (v7.11.0)
63
65
  // Note: --width (v7.8.0) and --opacity / --padding / --output (v7.10.0) are CLI-only
64
66
  // by design — those decisions are per-asset, not project-wide.
65
67
  },
@@ -270,6 +272,37 @@ module.exports = {
270
272
  };
271
273
  ```
272
274
 
275
+ ### Config Syntax Validation (v7.11.0)
276
+
277
+ Since v7.11.0, PurgeTSS validates known fields in `config.cjs` at load time. On a type mismatch it prints a formatted `Config Syntax Error` block — file, JSON path, context, issue, and a fix snippet — instead of crashing downstream with a cryptic message like `rule.startsWith is not a function`.
278
+
279
+ The validator runs on every config load and covers the case that trips up developers coming from Tailwind: `fontFamily` values must be a **string**, not a Tailwind-style array. It currently validates:
280
+
281
+ - `theme.fontFamily.*` — expected a string.
282
+ - `theme.extend.fontFamily.*` — expected a string.
283
+
284
+ ```javascript
285
+ // ✗ Tailwind-style array — triggers a Config Syntax Error
286
+ theme: {
287
+ extend: {
288
+ fontFamily: {
289
+ sans: ['Inter', 'sans-serif']
290
+ }
291
+ }
292
+ }
293
+
294
+ // ✓ Single font family per element (Titanium accepts one)
295
+ theme: {
296
+ extend: {
297
+ fontFamily: {
298
+ sans: 'Inter-Regular'
299
+ }
300
+ }
301
+ }
302
+ ```
303
+
304
+ The scope is defined by the `FIELD_RULES` array in `src/shared/validation/config-validator.js`; additional fields can be added there. Today only the two `fontFamily` paths are validated.
305
+
273
306
  ## Overriding and Extending Properties
274
307
 
275
308
  By default, your project inherits values from the default theme. You have two options depending on your goal.
@@ -396,6 +429,36 @@ module.exports = {
396
429
 
397
430
  The nested keys are combined with the parent key to form class names like `bg-tahiti-400` or `text-tahiti-400`.
398
431
 
432
+ ### Nesting beyond one level
433
+
434
+ Since v7.10.0, `theme` and `theme.extend` values are walked recursively, so you can group categories more than one level deep. Each level flattens into a kebab-case suffix on the generated class names:
435
+
436
+ ```javascript
437
+ module.exports = {
438
+ theme: {
439
+ extend: {
440
+ colors: {
441
+ brand: {
442
+ primary: {
443
+ 500: '#0ea5e9',
444
+ 900: '#0c4a6e'
445
+ },
446
+ accent: '#f97316'
447
+ }
448
+ }
449
+ }
450
+ }
451
+ };
452
+ ```
453
+
454
+ ```tss
455
+ '.bg-brand-primary-500': { backgroundColor: '#0ea5e9' }
456
+ '.bg-brand-primary-900': { backgroundColor: '#0c4a6e' }
457
+ '.bg-brand-accent': { backgroundColor: '#f97316' }
458
+ ```
459
+
460
+ Default modifier keys (`default`, `global`, `DEFAULT`) collapse without contributing to the suffix. The same flattening applies to other property categories that accept nested objects, including `backgroundGradient` and `backgroundSelectedGradient`. One-level configs behave exactly as before.
461
+
399
462
  ### Override a Default Color
400
463
 
401
464
  If you want to override one of the default colors but keep the rest, provide the new values in `theme.extend.colors`.