@maccesar/titools 2.9.0 → 2.10.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.
@@ -302,6 +302,48 @@ Once the JSON and the `config.cjs` mapping are in place, you use the semantic cl
302
302
 
303
303
  When the appearance changes — whether from `Appearance.set(...)` or a system-level toggle — Titanium resolves each semantic color name to its `light` or `dark` value automatically. No event listeners, no manual repaint.
304
304
 
305
+ ### Opacity modifier auto-derivation
306
+
307
+ As of PurgeTSS v7.9.0, you can apply the `/N` opacity modifier to **any class that resolves to a semantic name** in `semantic.colors.json`, and PurgeTSS will derive a new semantic key with that alpha pre-applied for both `light` and `dark` modes. This works for `bg-*`, `text-*`, `border-*`, and any other color-accepting utility whose class is mapped through `theme.extend.colors` in `config.cjs`.
308
+
309
+ ```xml
310
+ <View class="bg-surface/65" />
311
+ <Label class="text-on-surface/80" text="Subtle" />
312
+ <View class="border border-accent/40" />
313
+ ```
314
+
315
+ On the next `purgetss build` (or plain `purgetss`) run, the toolchain executes a three-step flow:
316
+
317
+ 1. **Detects the mapping** — PurgeTSS sees that, for example, `bg-surface` is mapped to the semantic name `surfaceColor` via `config.cjs`.
318
+ 2. **Derives a new key** — it adds `surfaceColor_65` (naming convention: `<originalKey>_<alphaPercent>`, underscore + integer percent) to `semantic.colors.json`, copying the original hex values for both modes and tagging each with `alpha: "65"`:
319
+
320
+ ```json
321
+ "surfaceColor_65": {
322
+ "light": { "color": "#F9FAFB", "alpha": "65" },
323
+ "dark": { "color": "#0f172a", "alpha": "65" }
324
+ }
325
+ ```
326
+
327
+ 3. **Emits the rule against the derived key** — for example, `'.bg-surface/65': { backgroundColor: 'surfaceColor_65' }`. Light/Dark switching keeps working because Titanium handles the lookup like any other semantic color. The same flow runs for opacity inside an `apply:` string in `config.cjs`.
328
+
329
+ #### Idempotency and the `Conflict` error
330
+
331
+ Re-runs are idempotent: existing derived keys are reused, never duplicated. If you manually edit a derived key with values that disagree with what PurgeTSS would generate (different base color, different alpha, different shape), the next build halts with a `Conflict` error instead of silently overwriting your edits — you have to either revert the manual change or remove the derived key so it can be regenerated cleanly.
332
+
333
+ > **DANGER**
334
+ >
335
+ > **Native rebuild required for new alpha entries**
336
+ >
337
+ > `semantic.colors.json` is read at **native build time**, not at runtime. The first time a brand-new opacity variant is auto-derived (a class like `bg-surface/65` you've never used before), the running app **will not see it** until the next full Titanium build. Liveview hot-reload alone does **not** refresh `semantic.colors.json` for the running app — only the native binary does.
338
+ >
339
+ > In practice: after introducing a new opacity class, run `purgetss build` once, then start a fresh native build (`appc run` / `ti build`) before resuming your usual Liveview cycle. Subsequent runs of the *same* `/N` value reuse the existing derived key and need no extra rebuild.
340
+
341
+ #### Constraints
342
+
343
+ - **Alpha range**: integer `0–100`, matching the standard opacity modifier syntax. Values outside this range are rejected.
344
+ - **Base key must exist**: the semantic name behind the class (`surfaceColor` in the example) must already exist in `semantic.colors.json`. If it doesn't, PurgeTSS emits a warning for direct XML usage or throws an Error for `apply:` directives, with three concrete suggestions in the message.
345
+ - **Naming is fixed**: the derived key is always `<originalKey>_<alphaPercent>` — underscore + integer percent. This mirrors the `/65` you typed and stays quote-free in `config.cjs` if you ever need to reference it manually.
346
+
305
347
  ## Using semantic colors in controllers
306
348
 
307
349
  Semantic colors also work from JavaScript. Three patterns cover the cases you'll hit.
@@ -368,10 +410,11 @@ A minimal semantic palette that covers most app surfaces:
368
410
  | Cards / elevated | `surfaceHighColor` | `#FFFFFF` | `#1e293b` | `bg-surface-high` |
369
411
  | Primary text | `textColor` | `#111827` | `#f1f5f9` | `text-on-surface` |
370
412
  | Secondary text | `textSecondaryColor` | `#6B7280` | `#94a3b8` | `text-on-surface-variant` |
413
+ | Muted text | `textMutedColor` | `#9CA3AF` | `#64748b` | `text-muted` |
371
414
  | Borders / dividers | `borderColor` | `#E5E7EB` | `#334155` | `bg-border` |
372
415
  | Accent | `accentColor` | `#3B82F6` | `#60a5fa` | `text-accent`, `bg-accent` |
373
416
 
374
- Start with these 5-6 colors and add more only when the design requires it. Fewer semantic colors means easier maintenance.
417
+ Start with these 6-7 colors and add more only when the design requires it. Fewer semantic colors means easier maintenance.
375
418
 
376
419
  ## Related
377
420
 
@@ -316,9 +316,7 @@ Colors: `black`, `dark`, `light`, and `white` themes that affect background and
316
316
 
317
317
  Use this for code examples. Set `copy="true"` to add a copy button.
318
318
 
319
- > **Community-Discovered PatternPro tip**
320
- >
321
- > For best results, install a monospaced font (like Fira Code or JetBrains Mono) and configure `font-mono` in your PurgeTSS config.
319
+ **Pro tiprecommended monospace fonts:** For best results, install a monospaced font (like Fira Code or JetBrains Mono) and configure `font-mono` in your PurgeTSS config. (Source: official tikit docs, `tikit.md` line ~390.)
322
320
 
323
321
  **Localization:** The copy button uses `L('copy', 'Copy')` for its title and `L('code_copied', 'Code copied!')` for the confirmation message. Add these keys to your `strings.xml` files for translation.
324
322
 
@@ -0,0 +1,120 @@
1
+ # Values and Units
2
+
3
+ PurgeTSS writes plain numeric values into your TSS files. **Titanium decides how to interpret them at runtime**, based on `ti.ui.defaultunit` in `tiapp.xml`.
4
+
5
+ This is a foundational concept worth knowing before you start tweaking spacing scales, custom colors, or arbitrary values — it's the difference between "8 pixels" and "8 dp" being the same number on disk but very different on a high-DPI device.
6
+
7
+ ## The short version
8
+
9
+ Numeric values produced by PurgeTSS utility classes are **unitless**. When PurgeTSS compiles `rounded-lg` to:
10
+
11
+ ```tss
12
+ '.rounded-lg': { borderRadius: 8 }
13
+ ```
14
+
15
+ the `8` is **not a pixel value**. Titanium reads it at runtime using the unit declared in `tiapp.xml`:
16
+
17
+ ```xml
18
+ <ti:app>
19
+ <property name="ti.ui.defaultunit" type="string">dp</property>
20
+ </ti:app>
21
+ ```
22
+
23
+ The Alloy project template has used `dp` by default for years, so most PurgeTSS projects are working with **density-independent pixels**, not raw pixels. In practice, `borderRadius: 8` usually means `8dp`, not `8px`.
24
+
25
+ ## Why this matters
26
+
27
+ Saying `rounded-lg` gives you "8 pixels" is only correct if your `tiapp.xml` explicitly sets `ti.ui.defaultunit` to `px`. Most projects do not.
28
+
29
+ A more accurate way to describe it is:
30
+
31
+ > `rounded-lg` applies `borderRadius: 8` — which Titanium interprets as **8 units of `ti.ui.defaultunit`**, defaulting to `dp` on standard Alloy projects.
32
+
33
+ This applies to every utility class that sets a dimension:
34
+
35
+ | Category | Utility classes |
36
+ | ---------- | -------------------------------------------------------------------------------------------- |
37
+ | Spacing | `m-*`, `p-*`, `mt-*`, `mb-*`, `mx-*`, `my-*`, `top-*`, `left-*`, `right-*`, `bottom-*` |
38
+ | Sizes | `w-*`, `h-*`, `size-*`, `wh-*` |
39
+ | Corners | `rounded-*`, `border-radius-*` |
40
+ | Borders | `border-*` (width) |
41
+ | Typography | `text-*` (font size), `letter-spacing-*`, `line-spacing-*` |
42
+ | Shadows | `drop-shadow-*`, `shadow-radius-*` |
43
+ | Elevation | `elevation-*`, `max-elevation-*` |
44
+ | Transforms | `translate-*`, `move-by-*` |
45
+ | Offsets | `x-offset-*`, `y-offset-*` |
46
+
47
+ ## Valid values for `ti.ui.defaultunit`
48
+
49
+ Titanium recognizes these unit identifiers:
50
+
51
+ | Value | Meaning | Notes |
52
+ | -------- | -------------------------- | --------------------------------------------------------------------------- |
53
+ | `dp` | Density-independent pixels | Alloy template default. Good default for cross-density consistency. |
54
+ | `dip` | Alias for `dp` | Same as `dp`. |
55
+ | `px` | Raw pixels | Usually a poor fit for UI sizing on high-DPI devices. |
56
+ | `mm` | Millimeters | Physical measurement. |
57
+ | `cm` | Centimeters | Physical measurement. |
58
+ | `in` | Inches | Physical measurement. |
59
+ | `pt` | Points (1/72 inch) | Physical measurement. |
60
+ | `system` | Platform default | iOS uses points; Android uses pixels. This is inconsistent across platforms. |
61
+
62
+ ## Forcing pixels explicitly
63
+
64
+ Some PurgeTSS classes use explicit pixel values written as **strings**:
65
+
66
+ ```tss
67
+ '.border-radius-px': { borderRadius: '1px' }
68
+ '.w-px': { width: '1px' }
69
+ '.h-px': { height: '1px' }
70
+ ```
71
+
72
+ If a value includes its own suffix, such as `'1px'`, `'2pt'`, or `'4mm'`, Titanium uses that unit directly and **ignores `ti.ui.defaultunit`**.
73
+
74
+ Use these when you actually need a 1px line or another exact unit (typical case: hairline dividers between rows).
75
+
76
+ ## Percentages are unit-independent
77
+
78
+ Fractional utility classes produce percentage strings. Titanium resolves those against the **parent size**, not against `ti.ui.defaultunit`:
79
+
80
+ ```tss
81
+ '.w-1/2': { width: '50%' }
82
+ '.h-full': { height: '100%' }
83
+ ```
84
+
85
+ These behave the same no matter which default unit your app uses.
86
+
87
+ ## Titanium constants are unit-independent
88
+
89
+ Utility classes that resolve to Titanium layout constants also ignore units:
90
+
91
+ ```tss
92
+ '.w-auto': { width: Ti.UI.SIZE }
93
+ '.h-screen': { height: Ti.UI.FILL }
94
+ ```
95
+
96
+ `Ti.UI.SIZE` and `Ti.UI.FILL` are layout directives, not numeric dimensions.
97
+
98
+ ## Checking your project's setting
99
+
100
+ Open `tiapp.xml` and look for:
101
+
102
+ ```xml
103
+ <property name="ti.ui.defaultunit" type="string">dp</property>
104
+ ```
105
+
106
+ If that property is missing, Titanium falls back to `system`. That means iOS and Android can interpret the same number differently, so it is better to set `dp` explicitly.
107
+
108
+ ## Summary
109
+
110
+ - PurgeTSS writes **unitless numeric values** into `app.tss`.
111
+ - Titanium resolves those values using `ti.ui.defaultunit` in `tiapp.xml`.
112
+ - In most Alloy projects, that unit is `dp`, **not raw pixels**.
113
+ - Values ending in `-px` (written as quoted strings) force raw pixels regardless of the project setting.
114
+ - Percentage-based and `auto`/`screen` utilities are unit-independent.
115
+
116
+ ## Related
117
+
118
+ - [Arbitrary Values](./arbitrary-values.md) — parentheses notation `(20px)`, `(2rem)`, `(#ff0000)` for one-off values.
119
+ - [Customization Deep Dive](./customization-deep-dive.md) — defining your own spacing scale via `theme.spacing`.
120
+ - [Class Index](./class-index.md) — the full set of generated classes and their numeric vs. percentage vs. constant outputs.