@maccesar/titools 4.1.0 → 4.4.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 +30 -7
  2. package/bin/titools.js +4 -4
  3. package/commands/ti-audit.md +13 -0
  4. package/commands/ti-check.md +15 -0
  5. package/commands/ti-new-screen.md +18 -0
  6. package/lib/claude-plugin.js +105 -0
  7. package/lib/cleanup.js +18 -0
  8. package/lib/commands/doctor.js +75 -3
  9. package/lib/commands/skills.js +66 -6
  10. package/lib/commands/uninstall.js +32 -2
  11. package/lib/commands/update.js +15 -0
  12. package/lib/config.js +37 -0
  13. package/lib/installer.js +85 -1
  14. package/lib/symlink.js +40 -3
  15. package/package.json +2 -1
  16. package/skills/alloy-guides/references/MODELS.md +23 -0
  17. package/skills/alloy-guides/references/MODELS_ADVANCED.md +19 -0
  18. package/skills/alloy-guides/references/VIEWS_STYLES.md +12 -0
  19. package/skills/alloy-guides/references/VIEWS_XML.md +18 -0
  20. package/skills/purgetss/references/EXAMPLES.md +24 -0
  21. package/skills/purgetss/references/animation-advanced.md +12 -0
  22. package/skills/purgetss/references/animation-system.md +23 -0
  23. package/skills/purgetss/references/app-branding.md +23 -0
  24. package/skills/purgetss/references/apply-directive.md +17 -0
  25. package/skills/purgetss/references/arbitrary-values.md +13 -0
  26. package/skills/purgetss/references/class-index-properties.md +11 -0
  27. package/skills/purgetss/references/cli-commands.md +27 -0
  28. package/skills/purgetss/references/customization-deep-dive.md +15 -0
  29. package/skills/purgetss/references/dynamic-component-creation.md +16 -0
  30. package/skills/purgetss/references/migration-guide.md +20 -0
  31. package/skills/purgetss/references/multi-density-images.md +27 -0
  32. package/skills/purgetss/references/semantic-colors.md +15 -0
  33. package/skills/purgetss/references/tikit-components.md +17 -0
  34. package/skills/purgetss/references/titanium-resets.md +16 -0
  35. package/skills/purgetss/references/ui-ux-design.md +20 -0
  36. package/skills/ti-api/references/api-android.md +23 -0
  37. package/skills/ti-api/references/api-app-platform.md +24 -0
  38. package/skills/ti-api/references/api-core.md +24 -0
  39. package/skills/ti-api/references/api-data-network.md +21 -0
  40. package/skills/ti-api/references/api-media.md +15 -1
  41. package/skills/ti-api/references/api-modules-ble-bluetooth.md +26 -0
  42. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +18 -0
  43. package/skills/ti-api/references/api-modules-map.md +21 -2
  44. package/skills/ti-api/references/api-modules-nfc.md +34 -0
  45. package/skills/ti-api/references/api-modules-social-misc.md +22 -0
  46. package/skills/ti-api/references/api-services.md +21 -1
  47. package/skills/ti-api/references/api-ui-android.md +18 -0
  48. package/skills/ti-api/references/api-ui-extras.md +19 -1
  49. package/skills/ti-api/references/api-ui-ios-animator.md +14 -0
  50. package/skills/ti-api/references/api-ui-ios.md +42 -0
  51. package/skills/ti-api/references/api-ui-lists.md +14 -2
  52. package/skills/ti-api/references/api-ui-text-input.md +15 -0
  53. package/skills/ti-api/references/api-ui-views.md +19 -0
  54. package/skills/ti-api/references/api-ui-windows-navigation.md +13 -0
  55. package/skills/ti-api/references/api-xml-global.md +31 -0
  56. package/skills/ti-expert/SKILL.md +38 -5
  57. package/skills/ti-expert/references/adaptive-layouts.md +14 -0
  58. package/skills/ti-expert/references/alloy-builtins.md +26 -22
  59. package/skills/ti-expert/references/alloy-structure.md +57 -18
  60. package/skills/ti-expert/references/anti-patterns.md +13 -5
  61. package/skills/ti-expert/references/code-conventions.md +28 -3
  62. package/skills/ti-expert/references/controller-patterns.md +51 -26
  63. package/skills/ti-expert/references/error-handling.md +16 -0
  64. package/skills/ti-expert/references/examples.md +65 -21
  65. package/skills/ti-expert/references/feedback-migration.md +165 -0
  66. package/skills/ti-expert/references/feedback-surfaces.md +140 -0
  67. package/skills/ti-expert/references/feedback-widget-contracts.md +213 -0
  68. package/skills/ti-expert/references/migration-patterns.md +61 -24
  69. package/skills/ti-expert/references/patterns.md +16 -0
  70. package/skills/ti-expert/references/performance-optimization.md +17 -0
  71. package/skills/ti-expert/references/security-device.md +71 -56
  72. package/skills/ti-expert/references/state-management.md +21 -5
  73. package/skills/ti-expert/references/testing-e2e-ci.md +17 -0
  74. package/skills/ti-expert/references/testing-unit.md +20 -0
  75. package/skills/ti-expert/references/theming.md +135 -373
  76. package/skills/ti-guides/references/app-distribution.md +34 -0
  77. package/skills/ti-guides/references/application-frameworks.md +13 -0
  78. package/skills/ti-guides/references/cli-reference.md +16 -0
  79. package/skills/ti-guides/references/hyperloop-native-access.md +21 -0
  80. package/skills/ti-guides/references/javascript-primer.md +12 -0
  81. package/skills/ti-guides/references/tiapp-config.md +15 -0
  82. package/skills/ti-howtos/references/android-platform-deep-dives.md +15 -0
  83. package/skills/ti-howtos/references/cross-platform-development.md +16 -0
  84. package/skills/ti-howtos/references/debugging-profiling.md +15 -0
  85. package/skills/ti-howtos/references/extending-titanium.md +14 -0
  86. package/skills/ti-howtos/references/ios-platform-deep-dives.md +16 -0
  87. package/skills/ti-howtos/references/local-data-sources.md +32 -0
  88. package/skills/ti-howtos/references/notification-services.md +12 -0
  89. package/skills/ti-howtos/references/remote-data-sources.md +15 -0
  90. package/skills/ti-howtos/references/tutorials.md +13 -0
  91. package/skills/ti-ui/references/animation-and-matrices.md +17 -0
  92. package/skills/ti-ui/references/application-structures.md +19 -0
  93. package/skills/ti-ui/references/custom-fonts-styling.md +18 -0
  94. package/skills/ti-ui/references/event-handling.md +16 -0
  95. package/skills/ti-ui/references/gestures.md +17 -0
  96. package/skills/ti-ui/references/icons-and-splash-screens.md +17 -0
  97. package/skills/ti-ui/references/layouts-and-positioning.md +16 -0
  98. package/skills/ti-ui/references/listviews-and-performance.md +21 -0
  99. package/skills/ti-ui/references/orientation.md +20 -0
  100. package/skills/ti-ui/references/platform-ui-android.md +20 -0
  101. package/skills/ti-ui/references/platform-ui-ios.md +17 -0
  102. package/skills/ti-ui/references/tableviews.md +24 -0
@@ -5,6 +5,26 @@
5
5
  > Testing is useful for teams practicing CI/CD, projects with complex business logic, or refactoring confidence.
6
6
  > If you prefer manual testing on device, you can safely skip this guide.
7
7
 
8
+ <!-- TOC-START -->
9
+ ## Contents
10
+
11
+ - [What can be tested (Without Compiling)](#what-can-be-tested-without-compiling)
12
+ - [What cannot be easily tested](#what-cannot-be-easily-tested)
13
+ - [Testing philosophy](#testing-philosophy)
14
+ - [Project structure](#project-structure)
15
+ - [Writing testable code](#writing-testable-code)
16
+ - [Unit testing services](#unit-testing-services)
17
+ - [Unit testing helpers](#unit-testing-helpers)
18
+ - [Integration testing controllers](#integration-testing-controllers)
19
+ - [Mock factory](#mock-factory)
20
+ - [Test helper functions](#test-helper-functions)
21
+ - [Test setup configuration](#test-setup-configuration)
22
+ - [Running tests](#running-tests)
23
+ - [Anti-patterns to avoid](#anti-patterns-to-avoid)
24
+ - [Test checklist](#test-checklist)
25
+
26
+ <!-- TOC-END -->
27
+
8
28
  ## What can be tested (Without Compiling)
9
29
 
10
30
  **Pure JavaScript Logic:**
@@ -1,428 +1,190 @@
1
- # Theming & dark mode
1
+ # Theming and dark mode
2
2
 
3
- ## Alloy theme system
3
+ Choose the styling path from the project, not from personal memory. Semantic
4
+ roles are the shared contract; PurgeTSS or standard Alloy materializes them.
4
5
 
5
- Alloy has a built-in theme system via the `app/themes/` folder. Themes override views, styles, and assets without modifying originals.
6
+ ## Contents
6
7
 
7
- ### Theme folder structure
8
+ - [Decision path](#decision-path)
9
+ - [Semantic color contract](#semantic-color-contract)
10
+ - [PurgeTSS projects](#purgetss-projects)
11
+ - [Standard Alloy projects](#standard-alloy-projects)
12
+ - [Alloy build-time themes](#alloy-build-time-themes)
13
+ - [Runtime custom themes](#runtime-custom-themes)
14
+ - [Component rules](#component-rules)
15
+ - [Verification](#verification)
8
16
 
9
- ```
10
- app/
11
- ├── themes/
12
- │ ├── light/ # Light theme (or default)
13
- │ │ ├── styles/
14
- │ │ │ └── app.tss # Overrides app/styles/app.tss
15
- │ │ └── assets/
16
- │ │ └── images/
17
- │ │ └── logo.png # Overrides app/assets/images/logo.png
18
- │ └── dark/ # Dark theme
19
- │ ├── styles/
20
- │ │ └── app.tss # Dark overrides
21
- │ └── assets/
22
- │ └── images/
23
- │ └── logo.png # Dark version of logo
24
- ├── styles/
25
- │ └── app.tss # Base styles (used when no theme active)
26
- ├── config.json
27
- ```
28
-
29
- ### Activating a theme
30
-
31
- Set the theme in `config.json`:
32
-
33
- ```json
34
- {
35
- "global": {
36
- "theme": "light"
37
- },
38
- "env:development": {
39
- "theme": "light"
40
- }
41
- }
42
- ```
43
-
44
- > **⚠️ Theme is compile-time only**
45
- > Alloy themes are applied at **build time**. You cannot switch themes at runtime using this system alone. For runtime switching, use the Dynamic Theming approach below.
46
-
47
- ### Theme cascade
48
-
49
- When a theme is active, Alloy merges files in this order:
50
- 1. `app/styles/app.tss` (base)
51
- 2. `app/themes/<theme>/styles/app.tss` (theme override)
52
- 3. `app/styles/<controller>.tss` (controller-specific)
53
- 4. `app/themes/<theme>/styles/<controller>.tss` (theme + controller override)
54
-
55
- Theme files **merge** with base files , you only need to include properties you want to override.
56
-
57
- ---
58
-
59
- ## Dynamic theming with Alloy.Globals
60
-
61
- For runtime theme switching (including Dark Mode), use `Alloy.Globals` as a centralized color palette.
62
-
63
- ### Step 1: define color palette
64
-
65
- ```javascript
66
- // alloy.js
67
- const themes = {
68
- light: {
69
- bg: '#ffffff',
70
- bgSecondary: '#f3f4f6',
71
- text: '#111827',
72
- textSecondary: '#6b7280',
73
- primary: '#2563eb',
74
- primaryText: '#ffffff',
75
- border: '#e5e7eb',
76
- card: '#ffffff',
77
- danger: '#ef4444',
78
- success: '#22c55e'
79
- },
80
- dark: {
81
- bg: '#111827',
82
- bgSecondary: '#1f2937',
83
- text: '#f9fafb',
84
- textSecondary: '#9ca3af',
85
- primary: '#3b82f6',
86
- primaryText: '#ffffff',
87
- border: '#374151',
88
- card: '#1f2937',
89
- danger: '#f87171',
90
- success: '#4ade80'
91
- }
92
- }
93
-
94
- // Load saved preference or default to light
95
- const savedTheme = Ti.App.Properties.getString('app:theme', 'light')
96
- Alloy.Globals.theme = themes[savedTheme]
97
- Alloy.Globals.themeName = savedTheme
98
- ```
17
+ ## Decision path
99
18
 
100
- ### Step 2: use in TSS with Alloy.Globals
19
+ 1. Detect `purgetss/` or `purgetss/config.cjs`.
20
+ 2. If detected, invoke the `purgetss` skill before writing any class or style.
21
+ 3. If not detected, use standard Alloy TSS and Titanium semantic colors.
22
+ 4. Use `Alloy.Globals` for a runtime palette only when the product requires
23
+ custom themes beyond the semantic light/dark/system model.
101
24
 
102
- ```tss
103
- /* app.tss - Global base styles using theme colors */
104
- "Window": {
105
- backgroundColor: Alloy.Globals.theme.bg
106
- }
25
+ Do not mix these paths accidentally. In particular, never teach a PurgeTSS
26
+ project to maintain the generated `app/styles/app.tss` by hand.
107
27
 
108
- "Label": {
109
- color: Alloy.Globals.theme.text
110
- }
28
+ ## Semantic color contract
111
29
 
112
- ".card": {
113
- backgroundColor: Alloy.Globals.theme.card,
114
- borderWidth: 1,
115
- borderColor: Alloy.Globals.theme.border,
116
- borderRadius: 12
117
- }
30
+ Name colors by purpose rather than appearance. A practical design-system
31
+ contract includes:
118
32
 
119
- ".btn-primary": {
120
- backgroundColor: Alloy.Globals.theme.primary,
121
- color: Alloy.Globals.theme.primaryText,
122
- height: 48,
123
- borderRadius: 8,
124
- font: { fontWeight: 'bold' }
125
- }
126
-
127
- ".text-secondary": {
128
- color: Alloy.Globals.theme.textSecondary
129
- }
33
+ - app background and elevated surface;
34
+ - primary and secondary text;
35
+ - border/divider;
36
+ - accent and text on accent;
37
+ - modal overlay;
38
+ - success, warning, error, and their readable foreground colors;
39
+ - disabled surface/text where needed.
130
40
 
131
- ".bg-secondary": {
132
- backgroundColor: Alloy.Globals.theme.bgSecondary
133
- }
134
- ```
41
+ Define light and dark values in:
135
42
 
136
- ### Step 3: theme switching service
43
+ - Alloy: `app/assets/semantic.colors.json`
44
+ - Classic: `Resources/semantic.colors.json`
137
45
 
138
- ```javascript
139
- // lib/services/themeService.js
140
- const EventBus = require('services/eventBus')
46
+ Example:
141
47
 
142
- const themes = {
143
- light: { /* ... same as alloy.js ... */ },
144
- dark: { /* ... same as alloy.js ... */ }
145
- }
146
-
147
- exports.ThemeService = {
148
- getCurrentTheme() {
149
- return Alloy.Globals.themeName
150
- },
151
-
152
- setTheme(name) {
153
- if (!themes[name]) return
154
-
155
- Alloy.Globals.theme = themes[name]
156
- Alloy.Globals.themeName = name
157
- Ti.App.Properties.setString('app:theme', name)
158
-
159
- // Notify all listeners
160
- EventBus.trigger('theme:changed', { theme: name })
48
+ ```json
49
+ {
50
+ "surfaceColor": {
51
+ "light": "#FFFFFF",
52
+ "dark": "#1E293B"
161
53
  },
162
-
163
- toggle() {
164
- const next = Alloy.Globals.themeName === 'light' ? 'dark' : 'light'
165
- this.setTheme(next)
54
+ "textColor": {
55
+ "light": "#111827",
56
+ "dark": "#F1F5F9"
166
57
  },
167
-
168
- // Follow system Dark Mode (iOS 13+, Android 10+)
169
- followSystem() {
170
- if (Ti.UI.semanticColorType !== undefined) {
171
- const isDark = Ti.UI.semanticColorType === Ti.UI.SEMANTIC_COLOR_TYPE_DARK
172
- this.setTheme(isDark ? 'dark' : 'light')
173
- }
58
+ "overlayColor": {
59
+ "light": "#00000080",
60
+ "dark": "#000000CC"
174
61
  }
175
62
  }
176
63
  ```
177
64
 
178
- ### Step 4: respond to theme changes in controllers
65
+ Titanium resolves a semantic color name when a color-accepting property uses
66
+ that name. Keep component APIs tone-based (`neutral`, `success`, `warning`,
67
+ `error`) and map tones to semantic roles inside the visual layer. Do not pass
68
+ raw brand hex values through business controllers.
179
69
 
180
- > **⚠️ Theme change requires UI rebuild**
181
- > Since TSS is applied at controller creation time, changing `Alloy.Globals.theme` does NOT retroactively update already-rendered views. You must manually update visible elements or restart the root controller.
70
+ ## PurgeTSS projects
182
71
 
183
- **Approach A: Rebuild root controller (simplest)**
72
+ The `purgetss` skill is the source of truth for supported classes, configuration,
73
+ appearance behavior, and commands. Apply these integration rules:
184
74
 
185
- ```javascript
186
- // controllers/settings.js
187
- const { ThemeService } = require('services/themeService')
188
-
189
- function onToggleTheme() {
190
- ThemeService.toggle()
75
+ - Map semantic color names under `theme.extend.colors` in
76
+ `purgetss/config.cjs`.
77
+ - Use verified utility classes in Alloy XML.
78
+ - Configure `options.widgets: true` when Widgets contain utility classes.
79
+ - Prefer `config.cjs` for reusable custom rules.
80
+ - Treat `app/styles/app.tss` as generated output and never edit it.
81
+ - Keep only truly specific properties in Widget/controller TSS when no verified
82
+ utility exists.
83
+ - Use the PurgeTSS Appearance module for light/dark/system selection instead of
84
+ creating a competing mode service.
85
+ - Read the current PurgeTSS references before naming any utility. Similarity to
86
+ Tailwind is not evidence that a class exists.
191
87
 
192
- // Restart app from root controller
193
- const root = Alloy.createController('index')
194
- root.getView().open()
195
-
196
- // Close current window tree
197
- $.getView().close()
198
- }
199
- ```
200
-
201
- **Approach B: Update visible elements in-place (smoother)**
88
+ Conceptual mapping only; verify the actual PurgeTSS syntax before use:
202
89
 
203
90
  ```javascript
204
- // controllers/settings.js
205
- const EventBus = require('services/eventBus')
206
- const { ThemeService } = require('services/themeService')
207
-
208
- function init() {
209
- EventBus.on('theme:changed', applyTheme)
210
- }
211
-
212
- function applyTheme() {
213
- const t = Alloy.Globals.theme
214
-
215
- $.settingsWindow.applyProperties({ backgroundColor: t.bg })
216
- $.titleLabel.applyProperties({ color: t.text })
217
- $.themeToggle.applyProperties({ backgroundColor: t.bgSecondary })
218
- }
219
-
220
- function onToggleTheme() {
221
- ThemeService.toggle()
222
- }
223
-
224
- function cleanup() {
225
- EventBus.off('theme:changed', applyTheme)
226
- $.destroy()
227
- }
228
-
229
- $.cleanup = cleanup
230
- ```
231
-
232
- ---
233
-
234
- ## System dark mode detection
235
-
236
- ### iOS 13+ / Android 10+
237
-
238
- ```javascript
239
- // lib/services/themeService.js (add to existing service)
240
-
241
- exports.ThemeService = {
242
- // ... existing methods ...
243
-
244
- // Initialize system theme listener
245
- initSystemListener() {
246
- // Detect current system theme at startup
247
- this.followSystem()
248
-
249
- // Re-check on resume (user may have changed system Dark Mode while app was backgrounded)
250
- // Note: Titanium does not fire a dedicated dark-mode-change event.
251
- // `Ti.UI.semanticColorType` is the correct way to check the current setting.
252
- Ti.App.addEventListener('resumed', () => {
253
- this.followSystem()
254
- })
91
+ // purgetss/config.cjs
92
+ module.exports = {
93
+ theme: {
94
+ extend: {
95
+ colors: {
96
+ surface: 'surfaceColor',
97
+ 'on-surface': 'textColor',
98
+ overlay: 'overlayColor'
99
+ }
100
+ }
255
101
  }
256
102
  }
257
103
  ```
258
104
 
259
- ### Semantic colors (Cross-Platform)
105
+ After generation, inspect the final `app.tss` section for unused or unsupported
106
+ classes. A clean build that still lists a new unsupported class is not complete.
260
107
 
261
- Titanium provides a cross-platform semantic colors API for Dark Mode support. Define colors in a `semantic.colors.json` file:
108
+ ## Standard Alloy projects
262
109
 
263
- **File location:**
264
- - **Classic apps**: `Resources/semantic.colors.json`
265
- - **Alloy apps**: `app/assets/semantic.colors.json`
110
+ Without PurgeTSS:
266
111
 
267
- ```json
268
- {
269
- "textColor": {
270
- "dark": {
271
- "color": "#ff85e2",
272
- "alpha": "50"
273
- },
274
- "light": "#ff1f1f"
275
- },
276
- "backgroundColor": {
277
- "dark": "#1a1a2e",
278
- "light": "#ffffff"
279
- },
280
- "primaryColor": {
281
- "dark": {
282
- "color": "#4ade80",
283
- "alpha": "100"
284
- },
285
- "light": {
286
- "color": "#22c55e",
287
- "alpha": "100"
288
- }
289
- }
290
- }
291
- ```
112
+ - keep global selectors in manually maintained `app/styles/app.tss`;
113
+ - keep screen-specific selectors in `app/styles/<controller>.tss`;
114
+ - keep Widget-specific properties in `app/widgets/<id>/styles/widget.tss`;
115
+ - reference semantic color names from TSS or controller properties;
116
+ - use platform and form-factor modifiers for platform-specific properties.
292
117
 
293
- **Using semantic colors:**
118
+ Example:
294
119
 
295
120
  ```tss
296
- /* Reference via Ti.UI.fetchSemanticColor() */
297
- "#label": {
298
- color: Ti.UI.fetchSemanticColor('textColor')
121
+ "Window": {
122
+ backgroundColor: "backgroundColor"
299
123
  }
300
124
 
301
- "#container": {
302
- backgroundColor: Ti.UI.fetchSemanticColor('backgroundColor')
125
+ ".card": {
126
+ backgroundColor: "surfaceColor",
127
+ borderColor: "borderColor",
128
+ borderWidth: 1
303
129
  }
304
- ```
305
130
 
306
- ```javascript
307
- // Or use color names directly as property values
308
- $.label.color = 'textColor';
309
- $.container.backgroundColor = 'backgroundColor';
131
+ ".bodyText": {
132
+ color: "textColor"
133
+ }
310
134
  ```
311
135
 
312
- **How it works:**
313
- - On iOS 13+ it uses the native system method that checks the user's system-wide Dark Mode setting
314
- - On all other platforms it checks `Ti.UI.semanticColorType` and returns the correct color variant
315
- - Alpha can be set from 0.0-100.0 (integer or float)
316
- - Light values can use hex with alpha via ARGB/AARRGGBB format
136
+ Do not copy a large utility system into manual TSS. Create only the small set of
137
+ selectors the app actually uses.
317
138
 
318
- > **💡 When to use Semantic Colors vs Alloy.Globals**
319
- > - **Semantic Colors**: Built-in Dark Mode support, automatic switching, simpler setup. Works cross-platform.
320
- > - **Alloy.Globals palette**: More control over when/how themes switch, easier to add custom themes beyond light/dark, runtime theme changes with UI rebuild.
139
+ ## Alloy build-time themes
321
140
 
322
- ---
141
+ Alloy's `app/themes/<name>/` folders can override views, styles, and assets at
142
+ build time. Select a theme through `app/config.json`. This is appropriate for
143
+ separate branded builds or compile-time variants.
323
144
 
324
- ## Reusable style classes pattern
145
+ Do not describe an Alloy build-time theme as runtime light/dark switching.
146
+ Semantic colors are the default for appearance changes while the app runs.
325
147
 
326
- Define a library of reusable TSS classes in `app.tss` for consistency across the app:
148
+ ## Runtime custom themes
327
149
 
328
- ```tss
329
- /* app.tss - Design System */
330
-
331
- /* === Layout === */
332
- ".row": { layout: 'horizontal', width: Ti.UI.FILL, height: Ti.UI.SIZE }
333
- ".col": { layout: 'vertical', width: Ti.UI.FILL, height: Ti.UI.SIZE }
334
- ".centered": { width: Ti.UI.SIZE, height: Ti.UI.SIZE }
335
-
336
- /* === Cards === */
337
- ".card": {
338
- backgroundColor: Alloy.Globals.theme.card,
339
- borderRadius: 12,
340
- borderWidth: 1,
341
- borderColor: Alloy.Globals.theme.border,
342
- width: Ti.UI.FILL,
343
- height: Ti.UI.SIZE
344
- }
345
-
346
- /* === Buttons === */
347
- ".btn-primary": {
348
- backgroundColor: Alloy.Globals.theme.primary,
349
- color: Alloy.Globals.theme.primaryText,
350
- height: 48,
351
- width: Ti.UI.FILL,
352
- borderRadius: 8,
353
- font: { fontSize: 16, fontWeight: 'bold' }
354
- }
150
+ Use a centralized runtime palette or theme service only when semantic
151
+ light/dark/system colors cannot model the requirement, such as multiple user
152
+ selectable brand themes.
355
153
 
356
- ".btn-secondary": {
357
- backgroundColor: 'transparent',
358
- color: Alloy.Globals.theme.primary,
359
- height: 48,
360
- width: Ti.UI.FILL,
361
- borderRadius: 8,
362
- borderWidth: 1,
363
- borderColor: Alloy.Globals.theme.primary,
364
- font: { fontSize: 16, fontWeight: 'bold' }
365
- }
154
+ If that exception applies:
366
155
 
367
- ".btn-danger": {
368
- backgroundColor: Alloy.Globals.theme.danger,
369
- color: '#ffffff',
370
- height: 48,
371
- width: Ti.UI.FILL,
372
- borderRadius: 8,
373
- font: { fontSize: 16, fontWeight: 'bold' }
374
- }
156
+ - keep the selected theme in one service;
157
+ - expose semantic roles, not control IDs;
158
+ - document how already-created proxies receive updates;
159
+ - remove all listeners in controller cleanup;
160
+ - avoid rebuilding the entire window tree unless the app has measured and
161
+ accepted that tradeoff.
375
162
 
376
- /* === Typography === */
377
- ".text-title": { font: { fontSize: 24, fontWeight: 'bold' }, color: Alloy.Globals.theme.text }
378
- ".text-subtitle": { font: { fontSize: 18, fontWeight: 'semibold' }, color: Alloy.Globals.theme.text }
379
- ".text-body": { font: { fontSize: 16 }, color: Alloy.Globals.theme.text }
380
- ".text-caption": { font: { fontSize: 14 }, color: Alloy.Globals.theme.textSecondary }
381
- ".text-small": { font: { fontSize: 12 }, color: Alloy.Globals.theme.textSecondary }
382
-
383
- /* === Inputs === */
384
- ".input": {
385
- height: 48,
386
- width: Ti.UI.FILL,
387
- borderRadius: 8,
388
- borderWidth: 1,
389
- borderColor: Alloy.Globals.theme.border,
390
- backgroundColor: Alloy.Globals.theme.bg,
391
- color: Alloy.Globals.theme.text,
392
- paddingLeft: 12,
393
- font: { fontSize: 16 }
394
- }
163
+ `Alloy.Globals` is a legacy/advanced interoperability option, not the first
164
+ recommendation for ordinary dark mode.
395
165
 
396
- /* === Spacing (applied via class in XML) === */
397
- ".mt-sm": { top: 8 }
398
- ".mt-md": { top: 16 }
399
- ".mt-lg": { top: 24 }
400
- ".mt-xl": { top: 32 }
401
- ".mx-md": { left: 16, right: 16 }
402
- ".mx-lg": { left: 24, right: 24 }
403
- ```
166
+ ## Component rules
404
167
 
405
- ### Using style classes in views
168
+ - Components consume semantic roles owned by the host app.
169
+ - Widgets own anatomy and behavior, not the product palette.
170
+ - Localized strings and business callbacks come from the host.
171
+ - Destructive styling must remain distinguishable in both appearances.
172
+ - Overlays, focus indicators, disabled states, and text must retain usable
173
+ contrast in light, dark, and system modes.
174
+ - Do not create separate light/dark controller branches when a semantic color
175
+ can express the difference.
406
176
 
407
- ```xml
408
- <Alloy>
409
- <Window>
410
- <View class="col mx-md">
411
- <Label class="text-title mt-lg" text="L('settings')" />
177
+ ## Verification
412
178
 
413
- <View class="card mt-md">
414
- <Label class="text-body mx-md mt-md" text="L('appearance')" />
415
- <Button class="btn-secondary mx-md mt-md" title="L('toggle_theme')" onClick="onToggleTheme" />
416
- </View>
179
+ For every supported platform and form factor:
417
180
 
418
- <Button class="btn-danger mt-xl mx-md" title="L('logout')" onClick="onLogout" />
419
- </View>
420
- </Window>
421
- </Alloy>
422
- ```
181
+ 1. test light, dark, and follow-system modes;
182
+ 2. change appearance while the relevant window remains open;
183
+ 3. inspect dialogs, sheets, Snackbars, disabled controls, and overlays;
184
+ 4. test localized long text and accessibility focus;
185
+ 5. run PurgeTSS generation when detected and resolve unsupported classes;
186
+ 6. compile and build both platform targets before claiming completion.
423
187
 
424
- This approach gives you:
425
- - Consistent spacing and typography across the entire app
426
- - Theme-aware colors that change with `Alloy.Globals.theme`
427
- - Clean XML views without inline styles
428
- - A single place to update design decisions (`app.tss`)
188
+ For exact PurgeTSS behavior, load its current `semantic-colors.md` and
189
+ `appearance-module.md` references. For Titanium property availability, verify
190
+ against the current `ti-api` skill.
@@ -2,6 +2,40 @@
2
2
 
3
3
  Guide for distributing Titanium apps to Google Play (Android) and the App Store (iOS).
4
4
 
5
+ <!-- TOC-START -->
6
+ ## Contents
7
+
8
+ - [Android distribution](#android-distribution)
9
+ - [1. Generate keystore and certificate](#1-generate-keystore-and-certificate)
10
+ - [2. Verify keystore](#2-verify-keystore)
11
+ - [3. Build for Google Play](#3-build-for-google-play)
12
+ - [4. Verify APK signing](#4-verify-apk-signing)
13
+ - [5. Deploy to device for testing](#5-deploy-to-device-for-testing)
14
+ - [6. Google Play submission requirements](#6-google-play-submission-requirements)
15
+ - [7. SD card installation](#7-sd-card-installation)
16
+ - [iOS distribution](#ios-distribution)
17
+ - [1. Distribution types](#1-distribution-types)
18
+ - [2. Create distribution certificate](#2-create-distribution-certificate)
19
+ - [3. Create distribution provisioning profile](#3-create-distribution-provisioning-profile)
20
+ - [4. Create App ID on App Store Connect](#4-create-app-id-on-app-store-connect)
21
+ - [5. Build and package](#5-build-and-package)
22
+ - [6. Upload to App Store Connect](#6-upload-to-app-store-connect)
23
+ - [7. Ad Hoc distribution](#7-ad-hoc-distribution)
24
+ - [Mac Catalyst distribution (Mac App Store)](#mac-catalyst-distribution-mac-app-store)
25
+ - [1. Enable Mac Catalyst for your App ID](#1-enable-mac-catalyst-for-your-app-id)
26
+ - [2. Create Mac App Store Distribution Certificate](#2-create-mac-app-store-distribution-certificate)
27
+ - [3. Mac Catalyst build targets](#3-mac-catalyst-build-targets)
28
+ - [4. Build for Mac Catalyst (Development)](#4-build-for-mac-catalyst-development)
29
+ - [5. Build for Mac App Store (Distribution)](#5-build-for-mac-app-store-distribution)
30
+ - [6. Upload to Mac App Store Connect](#6-upload-to-mac-app-store-connect)
31
+ - [7. Create app listing in App Store Connect](#7-create-app-listing-in-app-store-connect)
32
+ - [8. Mac Catalyst entitlements](#8-mac-catalyst-entitlements)
33
+ - [9. Common issues](#9-common-issues)
34
+ - [10. Versioning](#10-versioning)
35
+ - [11. Testing on Mac](#11-testing-on-mac)
36
+
37
+ <!-- TOC-END -->
38
+
5
39
  ## Android distribution
6
40
 
7
41
  ### 1. Generate keystore and certificate
@@ -2,6 +2,19 @@
2
2
 
3
3
  Framework options and architecture patterns for Titanium applications.
4
4
 
5
+ <!-- TOC-START -->
6
+ ## Contents
7
+
8
+ - [Alloy framework](#alloy-framework)
9
+ - [Classic Titanium](#classic-titanium)
10
+ - [Choosing a framework](#choosing-a-framework)
11
+ - [Architecture patterns](#architecture-patterns)
12
+ - [Framework interoperability](#framework-interoperability)
13
+ - [Best practices](#best-practices)
14
+ - [Resources](#resources)
15
+
16
+ <!-- TOC-END -->
17
+
5
18
  ## Alloy framework
6
19
 
7
20
  Alloy is the official MVC framework for Titanium. It was developed by Appcelerator and is now maintained by TiDev.
@@ -2,6 +2,22 @@
2
2
 
3
3
  Reference for Titanium CLI commands, options, and configuration.
4
4
 
5
+ <!-- TOC-START -->
6
+ ## Contents
7
+
8
+ - [Environment setup](#environment-setup)
9
+ - [Project commands](#project-commands)
10
+ - [Build commands](#build-commands)
11
+ - [Distribution commands](#distribution-commands)
12
+ - [SDK management](#sdk-management)
13
+ - [Configuration options](#configuration-options)
14
+ - [Common issues](#common-issues)
15
+ - [Command quick reference](#command-quick-reference)
16
+ - [SDK version precedence](#sdk-version-precedence)
17
+ - [References](#references)
18
+
19
+ <!-- TOC-END -->
20
+
5
21
  ## Environment setup
6
22
 
7
23
  ### Check environment