@maccesar/titools 4.23.1 → 5.1.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.
- package/README.md +26 -3
- package/package.json +1 -1
- package/skills/alloy-guides/references/MODELS.md +2 -2
- package/skills/alloy-guides/references/MODELS_ADVANCED.md +1 -1
- package/skills/alloy-guides/references/VIEWS_XML.md +13 -13
- package/skills/alloy-howtos/references/best_practices.md +2 -2
- package/skills/alloy-howtos/references/cli_reference.md +1 -1
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +1 -1
- package/skills/purgetss/SKILL.md +27 -24
- package/skills/purgetss/references/EXAMPLES.md +52 -41
- package/skills/purgetss/references/adopting-purgetss.md +137 -0
- package/skills/purgetss/references/animation-advanced.md +18 -5
- package/skills/purgetss/references/animation-system.md +21 -9
- package/skills/purgetss/references/app-branding.md +36 -97
- package/skills/purgetss/references/appearance-module.md +70 -5
- package/skills/purgetss/references/apply-directive.md +14 -6
- package/skills/purgetss/references/arbitrary-values.md +59 -23
- package/skills/purgetss/references/brand-padding-geometry.md +105 -0
- package/skills/purgetss/references/class-categories.md +684 -272
- package/skills/purgetss/references/class-index-properties.md +713 -607
- package/skills/purgetss/references/class-index.md +149 -84
- package/skills/purgetss/references/classic-projects.md +2 -2
- package/skills/purgetss/references/cli-commands.md +27 -213
- package/skills/purgetss/references/color-commands.md +218 -0
- package/skills/purgetss/references/configurable-properties.md +17 -2
- package/skills/purgetss/references/custom-fonts.md +21 -16
- package/skills/purgetss/references/custom-rules.md +7 -7
- package/skills/purgetss/references/customization-deep-dive.md +14 -11
- package/skills/purgetss/references/dynamic-component-creation.md +104 -61
- package/skills/purgetss/references/grid-layout.md +21 -24
- package/skills/purgetss/references/icon-fonts.md +37 -20
- package/skills/purgetss/references/installation-setup.md +1 -1
- package/skills/purgetss/references/ios-large-titles.md +12 -11
- package/skills/purgetss/references/migration-guide.md +101 -10
- package/skills/purgetss/references/multi-density-images.md +44 -24
- package/skills/purgetss/references/opacity-modifier.md +1 -1
- package/skills/purgetss/references/performance-tips.md +5 -4
- package/skills/purgetss/references/platform-modifiers.md +2 -2
- package/skills/purgetss/references/purgetss-ui-classic.md +21 -5
- package/skills/purgetss/references/semantic-colors.md +20 -13
- package/skills/purgetss/references/smart-mappings.md +8 -7
- package/skills/purgetss/references/svg-pipeline.md +21 -13
- package/skills/purgetss/references/tikit-components.md +2 -2
- package/skills/purgetss/references/titanium-resets.md +27 -17
- package/skills/purgetss/references/ui-ux-design.md +38 -26
- package/skills/purgetss/references/values-and-units.md +1 -2
- package/skills/purgetss/references/version-history.md +32 -4
- package/skills/ti-api/references/api-data-network.md +1 -1
- package/skills/ti-api/references/api-media.md +1 -1
- package/skills/ti-api/references/api-services.md +8 -5
- package/skills/ti-api/references/api-ui-lists.md +3 -2
- package/skills/ti-api/references/api-ui-text-input.md +1 -1
- package/skills/ti-expert/references/feedback-surfaces.md +1 -1
- package/skills/ti-guides/references/resources.md +1 -1
- package/skills/ti-guides/references/sdk-release-notes.md +22 -11
- package/skills/ti-howtos/references/extending-titanium.md +77 -0
|
@@ -84,7 +84,7 @@ After running `purgetss build-fonts` with the Bevan and Dancing Script example a
|
|
|
84
84
|
`./purgetss/styles/fonts.tss`
|
|
85
85
|
```css
|
|
86
86
|
// Fonts TSS file generated with PurgeTSS
|
|
87
|
-
// https://purgetss.com/docs/
|
|
87
|
+
// https://purgetss.com/docs/commands#build-fonts-command
|
|
88
88
|
|
|
89
89
|
'.bevan-italic': { font: { fontFamily: 'Bevan-Italic' } }
|
|
90
90
|
'.bevan-regular': { font: { fontFamily: 'Bevan-Regular' } }
|
|
@@ -95,11 +95,13 @@ After running `purgetss build-fonts` with the Bevan and Dancing Script example a
|
|
|
95
95
|
'.dancingscript-semibold': { font: { fontFamily: 'DancingScript-SemiBold' } }
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
The generated file also places a `/** … */` metadata comment (full name, version, vendor, license) before each font class; it is omitted from these excerpts.
|
|
99
|
+
|
|
98
100
|
You can now use these classes on any Titanium component with a `font` property: Labels, Buttons, TextFields, TextAreas, ListItems, TableViewRows, and ActivityIndicators.
|
|
99
101
|
|
|
100
102
|
### Renaming the class
|
|
101
103
|
|
|
102
|
-
|
|
104
|
+
By default the class name is the lowercased PostScript name, so renaming the font file alone changes nothing. The file name drives the class only with `-f, --font-class-from-filename`. For example, rename the files:
|
|
103
105
|
|
|
104
106
|
`./purgetss/fonts/`
|
|
105
107
|
```bash
|
|
@@ -112,7 +114,7 @@ purgetss
|
|
|
112
114
|
└─ Script-SemiBold.ttf
|
|
113
115
|
```
|
|
114
116
|
|
|
115
|
-
Running `build-fonts` produces:
|
|
117
|
+
Running `purgetss build-fonts -f` produces:
|
|
116
118
|
|
|
117
119
|
`./purgetss/styles/fonts.tss`
|
|
118
120
|
```css
|
|
@@ -149,29 +151,29 @@ After `purgetss build-fonts`, the generated `fonts.tss` includes the family clas
|
|
|
149
151
|
`./purgetss/styles/fonts.tss`
|
|
150
152
|
```css
|
|
151
153
|
// Fonts TSS file generated with PurgeTSS
|
|
152
|
-
// https://purgetss.com/docs/
|
|
154
|
+
// https://purgetss.com/docs/commands#build-fonts-command
|
|
153
155
|
|
|
154
156
|
'.map-icons': { font: { fontFamily: 'map-icons' } }
|
|
155
157
|
'.microns': { font: { fontFamily: 'microns' } }
|
|
156
158
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
// Unicode Characters
|
|
160
|
+
// To use your Icon Fonts in Buttons AND Labels each class sets 'text' and 'title' properties
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
// map-icons/map-icons.css
|
|
161
163
|
'.map-icon-abseiling': { text: '\ue800', title: '\ue800' }
|
|
162
164
|
'.map-icon-accounting': { text: '\ue801', title: '\ue801' }
|
|
163
165
|
'.map-icon-airport': { text: '\ue802', title: '\ue802' }
|
|
164
166
|
'.map-icon-amusement-park': { text: '\ue803', title: '\ue803' }
|
|
165
167
|
'.map-icon-aquarium': { text: '\ue804', title: '\ue804' }
|
|
166
|
-
|
|
168
|
+
// ...
|
|
167
169
|
|
|
168
|
-
|
|
170
|
+
// microns/microns.css
|
|
169
171
|
'.mu-arrow-left': { text: '\ue700', title: '\ue700' }
|
|
170
172
|
'.mu-arrow-right': { text: '\ue701', title: '\ue701' }
|
|
171
173
|
'.mu-arrow-up': { text: '\ue702', title: '\ue702' }
|
|
172
174
|
'.mu-arrow-down': { text: '\ue703', title: '\ue703' }
|
|
173
175
|
'.mu-left': { text: '\ue704', title: '\ue704' }
|
|
174
|
-
|
|
176
|
+
// ...
|
|
175
177
|
```
|
|
176
178
|
|
|
177
179
|
## Options
|
|
@@ -192,6 +194,10 @@ $ purgetss bf -m
|
|
|
192
194
|
|
|
193
195
|
The module is generated for text-only font collections too. By default, every TTF/OTF contributes a camel-cased PostScript-name key to `families`; with `--font-class-from-filename`, that key comes from the filename instead. Icon CSS can add a shorter family alias and a nested `icons` map. Both singular and plural export names remain available.
|
|
194
196
|
|
|
197
|
+
Once `purgetss.fonts.js` exists, later `build-fonts` runs regenerate it even without `--module`; if no font or icon data remains, the file is deleted.
|
|
198
|
+
|
|
199
|
+
The module also appends the `getIcon`, `setText`, `setTitle`, `getRandomKey`, and `getRandomValue` helpers. They look up top-level `icons` keys, which in this module are library prefixes, so read a glyph directly as `icons.<prefix>.<name>`.
|
|
200
|
+
|
|
195
201
|
`app/lib/purgetss.fonts.js` (Alloy) or `Resources/lib/purgetss.fonts.js` (Classic)
|
|
196
202
|
```javascript
|
|
197
203
|
const icons = {
|
|
@@ -264,25 +270,24 @@ purgetss
|
|
|
264
270
|
|
|
265
271
|
`./purgetss/styles/fonts.tss`
|
|
266
272
|
```css
|
|
267
|
-
/* "fontFamily" classes use the font's filename */
|
|
268
273
|
'.map': { font: { fontFamily: 'map-icons' } }
|
|
269
274
|
'.mic': { font: { fontFamily: 'microns' } }
|
|
270
275
|
|
|
271
|
-
|
|
276
|
+
// map-icons/mp.css
|
|
272
277
|
'.mp-abseiling': { text: '\ue800', title: '\ue800' }
|
|
273
278
|
'.mp-accounting': { text: '\ue801', title: '\ue801' }
|
|
274
279
|
'.mp-airport': { text: '\ue802', title: '\ue802' }
|
|
275
280
|
'.mp-amusement-park': { text: '\ue803', title: '\ue803' }
|
|
276
281
|
'.mp-aquarium': { text: '\ue804', title: '\ue804' }
|
|
277
|
-
|
|
282
|
+
// ...
|
|
278
283
|
|
|
279
|
-
|
|
284
|
+
// microns/mc.css
|
|
280
285
|
'.mc-arrow-left': { text: '\ue700', title: '\ue700' }
|
|
281
286
|
'.mc-arrow-right': { text: '\ue701', title: '\ue701' }
|
|
282
287
|
'.mc-arrow-up': { text: '\ue702', title: '\ue702' }
|
|
283
288
|
'.mc-arrow-down': { text: '\ue703', title: '\ue703' }
|
|
284
289
|
'.mc-left': { text: '\ue704', title: '\ue704' }
|
|
285
|
-
|
|
290
|
+
// ...
|
|
286
291
|
```
|
|
287
292
|
|
|
288
293
|
`app/lib/purgetss.fonts.js` (Alloy) or `Resources/lib/purgetss.fonts.js` (Classic)
|
|
@@ -338,4 +343,4 @@ The following notes reflect community experience with `build-fonts` against real
|
|
|
338
343
|
> 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.
|
|
339
344
|
|
|
340
345
|
> **💡 Use `--module` to set `text`/`title` from JavaScript**
|
|
341
|
-
> Hardcoding
|
|
346
|
+
> Hardcoding `'\uf015'` 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.
|
|
@@ -20,8 +20,8 @@ Whether you want to style a Ti Element (a markup element such as `Label`), a cus
|
|
|
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.
|
|
23
|
-
> 3. **
|
|
24
|
-
> 4. **Re-run `purgetss build
|
|
23
|
+
> 3. **Let PurgeTSS rename the config.** If the project still has `./purgetss/config.js`, the next PurgeTSS run renames it to `./purgetss/config.cjs` automatically. If both files exist, PurgeTSS reads only `config.cjs` and leaves `config.js` untouched, so merge any settings it holds into `config.cjs` and delete it.
|
|
24
|
+
> 4. **Re-run `purgetss`** (or build the Alloy project, which runs it through the auto-purge hook). Verify the missing-classes list at the end of `app.tss` is empty before turning `missing` back off. `purgetss build` only regenerates `utilities.tss`; it does not write `app.tss`.
|
|
25
25
|
>
|
|
26
26
|
> Skipping any of these steps tends to surface as silently dropped styles at runtime — the app compiles, but selectors no longer match.
|
|
27
27
|
|
|
@@ -43,7 +43,7 @@ The way you write property values determines how PurgeTSS emits them in the gene
|
|
|
43
43
|
- For `spacing` values you can mix unit types. Each unit follows a specific conversion rule:
|
|
44
44
|
- `%`, `px`, `cm`, and `in` are passed through to TSS without conversion.
|
|
45
45
|
- `em` and `rem` values are converted with the formula `value * 16` (so `1rem` becomes `16`).
|
|
46
|
-
- `dp` removes the unit and keeps the numeric value as-is
|
|
46
|
+
- `dp` removes the unit and keeps the numeric value as-is. Titanium resolves unit-less numbers with `ti.ui.defaultunit` in `tiapp.xml` (the Alloy template default is `dp`).
|
|
47
47
|
|
|
48
48
|
## `config.cjs` File Example
|
|
49
49
|
|
|
@@ -100,21 +100,21 @@ module.exports = {
|
|
|
100
100
|
PurgeTSS reads `config.cjs` and emits a single `utilities.tss` file that Alloy then merges with the rest of the project's styling. The file below shows what the example above generates — note how block keys translate into TSS query suffixes (`[platform=android]`, `[formFactor=tablet]`, `[if=...]`).
|
|
101
101
|
|
|
102
102
|
```tss
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// Property: TextField
|
|
104
|
+
// Description: A single line text field.
|
|
105
105
|
'TextField': { top: 10, left: 20, right: 20, bottom: 0 }
|
|
106
106
|
'TextField[if=Alloy.Globals.iPhoneX]': { bottom: Alloy.CFG.iPhoneXNotchSize }
|
|
107
107
|
'TextField[platform=android]': { touchFeedback: true }
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
// Custom Classes
|
|
110
110
|
'#main-banner': { width: '300px', height: '80px' }
|
|
111
111
|
'#main-banner[platform=ios]': { clipMode: Ti.UI.iOS.CLIP_MODE_DISABLED }
|
|
112
|
-
|
|
113
112
|
'.gallery': { height: Ti.UI.SIZE }
|
|
114
113
|
'.gallery[platform=ios]': { clipMode: Ti.UI.iOS.CLIP_MODE_ENABLED }
|
|
115
114
|
'.gallery[platform=android]': { hiddenBehavior: Ti.UI.HIDDEN_BEHAVIOR_GONE }
|
|
116
115
|
'.gallery[formFactor=handheld]': { width: '250px' }
|
|
117
116
|
'.gallery[formFactor=tablet]': { width: '500px' }
|
|
117
|
+
// End of Custom Classes
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
## Community-Discovered Patterns
|
|
@@ -36,10 +36,11 @@ purgetss init
|
|
|
36
36
|
This creates a `./purgetss/config.cjs` file with the default sections:
|
|
37
37
|
|
|
38
38
|
```javascript
|
|
39
|
+
// ./purgetss/config.cjs
|
|
39
40
|
module.exports = {
|
|
40
41
|
purge: {
|
|
41
42
|
mode: 'all',
|
|
42
|
-
method: 'sync', //
|
|
43
|
+
method: 'sync', // set how to execute auto-purging: sync or async
|
|
43
44
|
|
|
44
45
|
// These options are passed directly to PurgeTSS
|
|
45
46
|
options: {
|
|
@@ -50,14 +51,17 @@ module.exports = {
|
|
|
50
51
|
}
|
|
51
52
|
},
|
|
52
53
|
brand: {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
// Opaque fallback fill; configurable, not required to be white by either platform.
|
|
55
|
+
background: '#FFFFFF', // inherited by pieces that use an opaque background canvas
|
|
56
|
+
artworkCornerRadius: '0%', // rounded non-icon artwork: splashes, Feature Graphic and LaunchLogo (0-50)
|
|
57
|
+
confirmOverwrites: true, // prompt before overwriting files (set false to skip)
|
|
58
|
+
optimize: false, // true = quantize the generated PNGs to a palette (lossy, ~71% smaller)
|
|
57
59
|
|
|
58
60
|
// One block per piece. Artwork comes from purgetss/brand/logo-<piece>.{svg,png};
|
|
59
61
|
// these keys are for numbers, colors and activation. Padding is never inherited.
|
|
60
|
-
//
|
|
62
|
+
// iosSplash, androidSplash, featureGraphic and launchLogo accept cornerRadius.
|
|
63
|
+
// Store and launcher icons stay square for platform masking.
|
|
64
|
+
// iOS/store icons are full-bleed by default; increase padding only for logo artwork.
|
|
61
65
|
icon: { padding: '0%' }, // DefaultIcon.png + DefaultIcon-ios.png
|
|
62
66
|
dark: { background: null }, // DefaultIcon-Dark.png
|
|
63
67
|
tinted: {}, // DefaultIcon-Tinted.png
|
|
@@ -86,18 +90,17 @@ module.exports = {
|
|
|
86
90
|
autoSync: true, // false = SVG pipeline computes dims but doesn't write to images.files
|
|
87
91
|
confirmOverwrites: true, // prompt before overwriting files (set false to skip)
|
|
88
92
|
files: [] // per-file overrides: [{ filename: 'images/<sub>/<name>.<ext>', width, height? }]
|
|
89
|
-
// Note: --width (v7.8.0) and --opacity / --padding / --output (v7.10.0) are CLI-only
|
|
90
|
-
// by design — those decisions are per-asset, not project-wide. Since v7.17.0
|
|
91
|
-
// writing any of them here aborts the run instead of being ignored.
|
|
92
93
|
},
|
|
93
94
|
theme: {
|
|
94
95
|
extend: {}
|
|
95
96
|
}
|
|
96
|
-
}
|
|
97
|
+
}
|
|
97
98
|
```
|
|
98
99
|
|
|
99
100
|
`init` also creates empty `purgetss/fonts/`, `purgetss/brand/`, and `purgetss/images/` folders on first run, so you can see where each kind of asset goes.
|
|
100
101
|
|
|
102
|
+
`--width` (v7.8.0) and `--opacity` / `--padding` / `--output` (v7.10.0) are CLI-only flags of `purgetss images`, by design: those decisions are per-asset, not project-wide. Since v7.17.0 the `images:` section rejects unknown keys, so writing any of them in `config.cjs` aborts the run instead of being ignored.
|
|
103
|
+
|
|
101
104
|
Every section is optional. Only add what you want to change. Anything missing falls back to the defaults.
|
|
102
105
|
|
|
103
106
|
## Structure
|
|
@@ -533,7 +536,7 @@ module.exports = {
|
|
|
533
536
|
This generates classes like `bg-regal-blue` in addition to all of Tailwind's default colors.
|
|
534
537
|
|
|
535
538
|
> **ℹ️ INFO**
|
|
536
|
-
> You can use the `shades` command to generate a range of shades for a color and add them to `config.cjs`. See [
|
|
539
|
+
> You can use the `shades` command to generate a range of shades for a color and add them to `config.cjs`. See [Color Commands](./color-commands.md#shades-command).
|
|
537
540
|
|
|
538
541
|
## Customize Spacing
|
|
539
542
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **SCOPE NOTE**
|
|
4
4
|
>
|
|
5
|
-
> This reference covers dynamic component creation using **Alloy's `$.UI.create()` helper** and
|
|
5
|
+
> This reference covers dynamic component creation using **Alloy's `$.UI.create()` helper** and **`$.createStyle()` + `applyProperties()`**, both combined with PurgeTSS utility classes. It is an Alloy + PurgeTSS integration guide, **not** documentation for the `purgetss.ui` native module (see [animation-system.md](./animation-system.md) and [animation-advanced.md](./animation-advanced.md) for Alloy animation usage, or [purgetss-ui-classic.md](./purgetss-ui-classic.md) for the generated Classic runtime).
|
|
6
6
|
>
|
|
7
7
|
> For general Alloy controller and view patterns, refer to the `alloy-guides` and `alloy-howtos` skills.
|
|
8
8
|
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
- [Community-Discovered Patterns](#community-discovered-patterns)
|
|
13
13
|
- [Overview](#overview)
|
|
14
14
|
- [Method 1: `$.UI.create()` (Recommended)](#method-1-uicreate-recommended)
|
|
15
|
-
- [Method 2:
|
|
15
|
+
- [Method 2: `$.createStyle()` + `applyProperties()`](#method-2-createstyle--applyproperties)
|
|
16
16
|
- [Comparison: Which Method to Use?](#comparison-which-method-to-use)
|
|
17
17
|
- [Real-World Examples](#real-world-examples)
|
|
18
18
|
- [Important Notes](#important-notes)
|
|
19
|
-
- [
|
|
19
|
+
- [Changing Classes at Runtime](#changing-classes-at-runtime)
|
|
20
20
|
- [Anti-Patterns to Avoid](#anti-patterns-to-avoid)
|
|
21
21
|
- [Summary](#summary)
|
|
22
22
|
|
|
@@ -31,11 +31,11 @@ The guidance in this file reflects patterns that PurgeTSS users have converged o
|
|
|
31
31
|
When creating components dynamically in Controllers (not declaratively in XML), PurgeTSS provides two methods to apply utility classes:
|
|
32
32
|
|
|
33
33
|
1. **`$.UI.create()`** - Create components with PurgeTSS classes (Recommended)
|
|
34
|
-
2.
|
|
34
|
+
2. **`$.createStyle()` + `applyProperties()`** - Apply PurgeTSS styles to existing components
|
|
35
35
|
|
|
36
36
|
> **BEST PRACTICE**
|
|
37
37
|
>
|
|
38
|
-
> Always prefer `$.UI.create()` for dynamic components — it's cleaner, more readable, and PurgeTSS
|
|
38
|
+
> Always prefer `$.UI.create()` for dynamic components — it's cleaner, more readable, and PurgeTSS picks up the classes during build as long as they are written as literals under a `classes:` key in a controller (see [What the Class Scanner Collects](#what-the-class-scanner-collects)).
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
@@ -62,7 +62,7 @@ $.UI.create('ComponentType', {
|
|
|
62
62
|
function createThemeCard(themeName, themeTitle, imagePath) {
|
|
63
63
|
return $.UI.create('View', {
|
|
64
64
|
// View properties
|
|
65
|
-
|
|
65
|
+
accessibilityLabel: themeTitle, // Read by VoiceOver/TalkBack (Ti.UI.View has no `title` property)
|
|
66
66
|
|
|
67
67
|
// PurgeTSS utility classes
|
|
68
68
|
classes: [
|
|
@@ -102,7 +102,7 @@ classes: ['w-screen', 'h-auto', 'bg-white', 'rounded-lg']
|
|
|
102
102
|
classes: 'w-screen h-auto bg-white rounded-lg'
|
|
103
103
|
|
|
104
104
|
// Option 3: Mix arbitrary values with predefined classes
|
|
105
|
-
classes: ['w-(
|
|
105
|
+
classes: ['w-(100)', 'h-auto', 'bg-(#ff0000)', 'rounded-lg']
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
### Platform Modifiers in Dynamic Components
|
|
@@ -123,7 +123,7 @@ classes: [
|
|
|
123
123
|
// Arbitrary values use parentheses notation
|
|
124
124
|
classes: [
|
|
125
125
|
'w-(160)', // Custom width
|
|
126
|
-
'h-(
|
|
126
|
+
'h-(12.5rem)', // Custom height with a unit (not px: a px suffix stops the build)
|
|
127
127
|
'bg-(#3b82f6)', // Custom hex color
|
|
128
128
|
'm-(10dp)', // Custom margin with unit
|
|
129
129
|
'border-(2)' // Custom border width
|
|
@@ -157,21 +157,21 @@ function createListItem(text, icon) {
|
|
|
157
157
|
|
|
158
158
|
---
|
|
159
159
|
|
|
160
|
-
## Method 2:
|
|
160
|
+
## Method 2: `$.createStyle()` + `applyProperties()`
|
|
161
161
|
|
|
162
162
|
### When to Use This Method
|
|
163
163
|
|
|
164
|
-
Use `
|
|
164
|
+
Use the controller's `createStyle()` method when you need to:
|
|
165
165
|
- Apply PurgeTSS styles to an **existing component** (created without `$.UI.create()`)
|
|
166
|
-
-
|
|
167
|
-
-
|
|
166
|
+
- Build a style dictionary once and apply it to several components
|
|
167
|
+
- Style a view of another controller (`Alloy.createController('dialog').createStyle(...)`, as in the Alloy dynamic styles guide)
|
|
168
168
|
|
|
169
169
|
### Basic Syntax
|
|
170
170
|
|
|
171
171
|
```javascript
|
|
172
172
|
// Create style object
|
|
173
|
-
const style =
|
|
174
|
-
apiName: '
|
|
173
|
+
const style = $.createStyle({
|
|
174
|
+
apiName: 'View',
|
|
175
175
|
classes: 'bg-white rounded-lg'
|
|
176
176
|
})
|
|
177
177
|
|
|
@@ -185,8 +185,8 @@ $.myView.applyProperties(style)
|
|
|
185
185
|
// controllers/form/validation.js
|
|
186
186
|
function showError(inputField, errorMessage) {
|
|
187
187
|
// Create error style
|
|
188
|
-
const errorStyle =
|
|
189
|
-
apiName: '
|
|
188
|
+
const errorStyle = $.createStyle({
|
|
189
|
+
apiName: 'TextField',
|
|
190
190
|
classes: ['border-2', 'border-red-500', 'bg-red-50']
|
|
191
191
|
})
|
|
192
192
|
|
|
@@ -196,8 +196,8 @@ function showError(inputField, errorMessage) {
|
|
|
196
196
|
|
|
197
197
|
function clearError(inputField) {
|
|
198
198
|
// Create normal style
|
|
199
|
-
const normalStyle =
|
|
200
|
-
apiName: '
|
|
199
|
+
const normalStyle = $.createStyle({
|
|
200
|
+
apiName: 'TextField',
|
|
201
201
|
classes: ['border-1', 'border-gray-300', 'bg-white']
|
|
202
202
|
})
|
|
203
203
|
|
|
@@ -210,10 +210,11 @@ function clearError(inputField) {
|
|
|
210
210
|
|
|
211
211
|
```javascript
|
|
212
212
|
// String format
|
|
213
|
-
|
|
213
|
+
$.createStyle({ apiName: 'View', classes: 'bg-white rounded-lg' })
|
|
214
214
|
|
|
215
215
|
// Array format
|
|
216
|
-
|
|
216
|
+
$.createStyle({
|
|
217
|
+
apiName: 'Label',
|
|
217
218
|
classes: ['bg-white', 'rounded-lg', 'text-center']
|
|
218
219
|
})
|
|
219
220
|
```
|
|
@@ -225,8 +226,8 @@ Alloy.createStyle('index', {
|
|
|
225
226
|
| Scenario | Recommended Method | Example |
|
|
226
227
|
| ------------------------------- | ------------------------------------------- | ------------------------------------------------ |
|
|
227
228
|
| **Creating new components** | `$.UI.create()` | `$.UI.create('View', { classes: ['bg-white'] })` |
|
|
228
|
-
| **Styling existing components** |
|
|
229
|
-
| **
|
|
229
|
+
| **Styling existing components** | `$.createStyle()` + `applyProperties()` | `view.applyProperties($.createStyle(...))` |
|
|
230
|
+
| **Swapping classes at runtime** | `$.addClass()` / `$.removeClass()` / `$.resetClass()` | Form validation, active/inactive states |
|
|
230
231
|
| **Component factories** | `$.UI.create()` | Reusable component creators |
|
|
231
232
|
|
|
232
233
|
---
|
|
@@ -236,21 +237,19 @@ Alloy.createStyle('index', {
|
|
|
236
237
|
### Example 1: Dynamic Form Fields
|
|
237
238
|
|
|
238
239
|
```javascript
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
const baseClasses = ['w-screen', 'h-12', 'mx-4', 'border-gray-300', 'border-(1)', 'rounded-lg']
|
|
242
|
-
|
|
240
|
+
// controllers/form.js
|
|
241
|
+
function createFormField(fieldType, options) {
|
|
243
242
|
switch (fieldType) {
|
|
244
243
|
case 'text':
|
|
245
244
|
return $.UI.create('TextField', {
|
|
246
245
|
hintText: options.hint,
|
|
247
|
-
classes: [
|
|
246
|
+
classes: ['w-screen', 'h-12', 'mx-4', 'border-gray-300', 'border-(1)', 'rounded-lg', 'bg-white', 'px-4']
|
|
248
247
|
})
|
|
249
248
|
|
|
250
249
|
case 'textarea':
|
|
251
250
|
return $.UI.create('TextArea', {
|
|
252
251
|
hintText: options.hint,
|
|
253
|
-
classes: [
|
|
252
|
+
classes: ['w-screen', 'h-24', 'mx-4', 'border-gray-300', 'border-(1)', 'rounded-lg', 'bg-white', 'px-4']
|
|
254
253
|
})
|
|
255
254
|
|
|
256
255
|
case 'button':
|
|
@@ -262,6 +261,12 @@ exports.createFormField = function(fieldType, options) {
|
|
|
262
261
|
}
|
|
263
262
|
```
|
|
264
263
|
|
|
264
|
+
> **NOTE — Keep factories in controllers, with literal class lists**
|
|
265
|
+
>
|
|
266
|
+
> - `$` is the controller instance, so `$.UI.create()` is not available in a plain `app/lib/` CommonJS module, and PurgeTSS does not scan `app/lib/` for classes.
|
|
267
|
+
> - Each class list is written out in full under `classes:`. A shared `baseClasses` array spread into `classes: [...baseClasses, ...]` is invisible to the scanner: spread elements are skipped and the array itself is not under a `classes:` key, so those classes would be purged from `app.tss`.
|
|
268
|
+
> - `px-4` sets `padding`, which exists only on `Ti.UI.TextField`, `Ti.UI.TextArea` (Android and iOS) and `Ti.UI.Android.CardView` (apidoc 13_4_1_GA). The `// padding - Android Only` comment in `utilities.tss` is inaccurate for the two text inputs.
|
|
269
|
+
|
|
265
270
|
### Example 2: Dynamic List Items
|
|
266
271
|
|
|
267
272
|
```javascript
|
|
@@ -306,12 +311,12 @@ function createProductCard(product) {
|
|
|
306
311
|
function applyTheme(theme) {
|
|
307
312
|
const themes = {
|
|
308
313
|
light: {
|
|
309
|
-
window:
|
|
310
|
-
text:
|
|
314
|
+
window: $.createStyle({ apiName: 'Window', classes: 'bg-white' }),
|
|
315
|
+
text: $.createStyle({ apiName: 'Label', classes: 'text-gray-900' })
|
|
311
316
|
},
|
|
312
317
|
dark: {
|
|
313
|
-
window:
|
|
314
|
-
text:
|
|
318
|
+
window: $.createStyle({ apiName: 'Window', classes: 'bg-gray-900' }),
|
|
319
|
+
text: $.createStyle({ apiName: 'Label', classes: 'text-gray-100' })
|
|
315
320
|
}
|
|
316
321
|
}
|
|
317
322
|
|
|
@@ -325,13 +330,19 @@ function applyTheme(theme) {
|
|
|
325
330
|
```javascript
|
|
326
331
|
// controllers/dashboard/grid.js
|
|
327
332
|
function createIconGrid(items) {
|
|
333
|
+
// `grid` goes on the container; `grid-cols-4` (width: 25%) goes on each cell
|
|
328
334
|
const grid = $.UI.create('View', {
|
|
329
|
-
classes: ['
|
|
335
|
+
classes: ['grid']
|
|
330
336
|
})
|
|
331
337
|
|
|
332
338
|
items.forEach(item => {
|
|
339
|
+
const cell = $.UI.create('View', {
|
|
340
|
+
classes: ['grid-cols-4']
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
// Optional gutter: `gap-*` sets margins, so it goes on an inner view
|
|
333
344
|
const icon = $.UI.create('View', {
|
|
334
|
-
classes: ['vertical']
|
|
345
|
+
classes: ['gap-1', 'vertical']
|
|
335
346
|
})
|
|
336
347
|
|
|
337
348
|
const iconView = $.UI.create('Label', {
|
|
@@ -346,7 +357,8 @@ function createIconGrid(items) {
|
|
|
346
357
|
|
|
347
358
|
icon.add(iconView)
|
|
348
359
|
icon.add(label)
|
|
349
|
-
|
|
360
|
+
cell.add(icon)
|
|
361
|
+
grid.add(cell)
|
|
350
362
|
})
|
|
351
363
|
|
|
352
364
|
return grid
|
|
@@ -361,13 +373,39 @@ function createIconGrid(items) {
|
|
|
361
373
|
|
|
362
374
|
> **NOTE — HOW IT WORKS**
|
|
363
375
|
>
|
|
364
|
-
> When you use `$.UI.create()` or
|
|
376
|
+
> When you use `$.UI.create()` or `$.createStyle()` with classes:
|
|
365
377
|
>
|
|
366
378
|
> 1. PurgeTSS scans your controllers for these class references
|
|
367
379
|
> 2. It adds the classes to the generated `app.tss`
|
|
368
380
|
> 3. At runtime, Alloy applies the styles to your components
|
|
369
381
|
>
|
|
370
|
-
> This
|
|
382
|
+
> This works only for classes the scanner can see (next section). Anything else is purged from `app.tss` and silently does nothing at runtime.
|
|
383
|
+
|
|
384
|
+
### What the Class Scanner Collects
|
|
385
|
+
|
|
386
|
+
PurgeTSS parses every file in `app/controllers/**/*.js`, plus `app/widgets/**/controllers/*.js` when `purge.options.widgets` is `true`. Files in `app/lib/` are not scanned.
|
|
387
|
+
|
|
388
|
+
It collects class names only from these shapes:
|
|
389
|
+
|
|
390
|
+
| Shape | Example |
|
|
391
|
+
| --- | --- |
|
|
392
|
+
| Value of a `classes:` or `apply:` property | `classes: ['bg-white', 'rounded-lg']`, `classes: 'bg-white rounded-lg'` |
|
|
393
|
+
| Second argument of any `*Class(target, value)` call, or `resetClass(target, value)` | `$.addClass($.label, 'text-red-500')` |
|
|
394
|
+
|
|
395
|
+
Inside those, it reads string literals, template literals without `${}`, array elements, and both branches of a ternary (`isActive ? 'text-green-500' : 'text-red-500'`).
|
|
396
|
+
|
|
397
|
+
It does not see classes held in a variable, built by concatenation or interpolation (`` `bg-${color}-500` ``), added with `.push()`, or spread from another array (`[...baseClasses]`). For classes that must be built dynamically, list them in `purge.options.safelist` in `purgetss/config.cjs`, which keeps them no matter the purge mode (see the PurgeTSS configuring guide, `options.safelist`):
|
|
398
|
+
|
|
399
|
+
```javascript
|
|
400
|
+
// purgetss/config.cjs
|
|
401
|
+
module.exports = {
|
|
402
|
+
purge: {
|
|
403
|
+
options: {
|
|
404
|
+
safelist: ['bg-red-500', 'bg-green-500', 'bg-blue-500']
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
```
|
|
371
409
|
|
|
372
410
|
### Class Verification
|
|
373
411
|
|
|
@@ -378,7 +416,10 @@ Just like with XML views, always verify classes exist before using them:
|
|
|
378
416
|
classes: ['w-screen', 'h-auto', 'bg-white', 'rounded-lg']
|
|
379
417
|
|
|
380
418
|
// WRONG - These classes don't exist
|
|
381
|
-
classes: ['flex-row', 'justify-center'
|
|
419
|
+
classes: ['flex-row', 'justify-center'] // No flexbox in Titanium
|
|
420
|
+
|
|
421
|
+
// NO EFFECT - `p-4` exists, but it sets `padding`, which only TextField, TextArea and Android CardView have
|
|
422
|
+
$.UI.create('View', { classes: ['p-4'] }) // Use margins on the children instead
|
|
382
423
|
```
|
|
383
424
|
|
|
384
425
|
See [Class Index](class-index.md) for available classes.
|
|
@@ -394,7 +435,7 @@ classes: [
|
|
|
394
435
|
'bg-white'
|
|
395
436
|
]
|
|
396
437
|
|
|
397
|
-
// Avoid: Conditional logic in controllers
|
|
438
|
+
// Avoid: Conditional logic in controllers (the scanner does not see `.push()`, so classes added only this way are purged)
|
|
398
439
|
if (OS_IOS) {
|
|
399
440
|
classes.push('mx-4')
|
|
400
441
|
} else {
|
|
@@ -404,20 +445,24 @@ if (OS_IOS) {
|
|
|
404
445
|
|
|
405
446
|
---
|
|
406
447
|
|
|
407
|
-
##
|
|
448
|
+
## Changing Classes at Runtime
|
|
408
449
|
|
|
409
|
-
|
|
450
|
+
`applyProperties({ classes: [...] })` does not restyle a view: it only sets a `classes` property on the proxy. To change the classes of a view that already exists, use the controller's `addClass`, `removeClass` and `resetClass` methods (Alloy dynamic styles guide). Pass the view, then the classes as an array or space-separated string, and optionally inline properties as a third argument:
|
|
410
451
|
|
|
411
452
|
```javascript
|
|
412
453
|
// Toggle status styling dynamically
|
|
413
454
|
function setStatus(isActive) {
|
|
414
|
-
$.statusLabel
|
|
415
|
-
|
|
455
|
+
$.removeClass($.statusLabel, isActive ? 'text-red-500' : 'text-green-500')
|
|
456
|
+
$.addClass($.statusLabel, isActive ? 'text-green-500' : 'text-red-500', {
|
|
416
457
|
text: isActive ? L('active') : L('inactive')
|
|
417
458
|
})
|
|
418
459
|
}
|
|
419
460
|
```
|
|
420
461
|
|
|
462
|
+
- `resetClass(view, classes)` replaces every class on the view, including the ones set in XML, so pass the full list.
|
|
463
|
+
- Enable autostyle (`<Alloy autoStyle="true">` in the view, or `autoStyle: true` in `config.json`) so removing a class also reverts its properties. Without it, a removed class leaves its values on the view.
|
|
464
|
+
- The PurgeTSS scanner reads the second argument of these calls, including both branches of a ternary.
|
|
465
|
+
|
|
421
466
|
### Conditional Styling Based on State
|
|
422
467
|
|
|
423
468
|
```javascript
|
|
@@ -452,9 +497,9 @@ function setState(state) {
|
|
|
452
497
|
}
|
|
453
498
|
```
|
|
454
499
|
|
|
455
|
-
> **NOTE — When to use `
|
|
500
|
+
> **NOTE — When to use `addClass`/`removeClass` vs `applyProperties`**
|
|
456
501
|
>
|
|
457
|
-
> - Use `
|
|
502
|
+
> - Use `addClass`/`removeClass`/`resetClass` when you want to swap entire style sets (e.g., active/inactive states)
|
|
458
503
|
> - Use `applyProperties` with direct values when changing individual properties (e.g., text, enabled)
|
|
459
504
|
> - Combine both for complex state changes
|
|
460
505
|
|
|
@@ -483,33 +528,30 @@ const view = $.UI.create('View', {
|
|
|
483
528
|
})
|
|
484
529
|
```
|
|
485
530
|
|
|
486
|
-
###
|
|
531
|
+
### Mixing inline properties and classes: keep inline values for runtime data
|
|
532
|
+
|
|
533
|
+
Alloy supports inline properties next to `classes`, and inline properties take precedence over class styles. Use them for values only known at runtime, and keep static styling in classes so it stays consistent with the rest of the app:
|
|
487
534
|
|
|
488
535
|
```javascript
|
|
489
|
-
//
|
|
536
|
+
// Avoid - a static value that a class already covers
|
|
490
537
|
const view = $.UI.create('View', {
|
|
491
|
-
backgroundColor: '#ffffff', //
|
|
492
|
-
classes: ['w-screen', 'rounded-lg']
|
|
538
|
+
backgroundColor: '#ffffff', // Same as `bg-white`
|
|
539
|
+
classes: ['w-screen', 'rounded-lg']
|
|
493
540
|
})
|
|
494
541
|
```
|
|
495
542
|
|
|
496
|
-
### Use only classes (or only styles)
|
|
497
|
-
|
|
498
543
|
```javascript
|
|
499
544
|
// CORRECT - Pure PurgeTSS
|
|
500
545
|
const view = $.UI.create('View', {
|
|
501
546
|
classes: ['w-screen', 'h-auto', 'bg-white', 'rounded-lg']
|
|
502
547
|
})
|
|
503
548
|
|
|
504
|
-
//
|
|
505
|
-
const view =
|
|
506
|
-
backgroundColor: dynamicColor, // Runtime value
|
|
507
|
-
width: calculatedWidth
|
|
508
|
-
})
|
|
509
|
-
// Then apply PurgeTSS classes
|
|
510
|
-
view.applyProperties(Alloy.createStyle('index', {
|
|
549
|
+
// CORRECT - Runtime values inline, static styling as classes
|
|
550
|
+
const view = $.UI.create('View', {
|
|
551
|
+
backgroundColor: dynamicColor, // Runtime value, overrides any class color
|
|
552
|
+
width: calculatedWidth,
|
|
511
553
|
classes: ['rounded-lg', 'm-4']
|
|
512
|
-
})
|
|
554
|
+
})
|
|
513
555
|
```
|
|
514
556
|
|
|
515
557
|
---
|
|
@@ -519,8 +561,9 @@ view.applyProperties(Alloy.createStyle('index', {
|
|
|
519
561
|
| Method | Use Case | Syntax |
|
|
520
562
|
| ------------------------- | --------------------------- | ---------------------------------------------------- |
|
|
521
563
|
| **`$.UI.create()`** | Creating new components | `$.UI.create('View', { classes: ['bg-white'] })` |
|
|
522
|
-
|
|
|
564
|
+
| **`$.createStyle()`** | Styling existing components | `$.createStyle({ apiName: 'View', classes: 'bg-white' })` |
|
|
523
565
|
| **`applyProperties()`** | Apply style to component | `component.applyProperties(style)` |
|
|
566
|
+
| **`$.addClass()` / `$.removeClass()` / `$.resetClass()`** | Swapping classes at runtime | `$.addClass($.label, 'text-red-500')` |
|
|
524
567
|
|
|
525
568
|
> **NOTE — REMEMBER**
|
|
526
569
|
>
|
|
@@ -531,4 +574,4 @@ view.applyProperties(Alloy.createStyle('index', {
|
|
|
531
574
|
> - All layout classes (`horizontal`, `vertical`)
|
|
532
575
|
> - All typography classes (`text-*`, `font-*`)
|
|
533
576
|
> - Platform modifiers (`ios:*`, `android:*`)
|
|
534
|
-
> - Arbitrary values (`w-(
|
|
577
|
+
> - Arbitrary values (`w-(100)`, `bg-(#ff0000)`)
|