@maccesar/titools 2.0.7 → 2.2.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 (132) hide show
  1. package/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
  2. package/README.md +250 -168
  3. package/agents/{ti-researcher.md → ti-pro.md} +10 -10
  4. package/bin/titools.js +16 -12
  5. package/lib/cleanup.js +95 -0
  6. package/lib/commands/agents.js +146 -70
  7. package/lib/commands/skills.js +349 -0
  8. package/lib/commands/uninstall.js +189 -154
  9. package/lib/commands/update.js +104 -21
  10. package/lib/config.js +26 -20
  11. package/lib/downloader.js +1 -1
  12. package/lib/installer.js +37 -97
  13. package/lib/platform.js +9 -5
  14. package/lib/prompts/checkboxCancel.js +264 -0
  15. package/lib/prompts/selectCancel.js +204 -0
  16. package/lib/symlink.js +19 -7
  17. package/lib/utils.js +17 -17
  18. package/package.json +10 -10
  19. package/skills/alloy-guides/SKILL.md +8 -30
  20. package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
  21. package/skills/alloy-guides/references/CONCEPTS.md +5 -25
  22. package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
  23. package/skills/alloy-guides/references/MODELS.md +40 -10
  24. package/skills/alloy-guides/references/PURGETSS.md +1 -11
  25. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
  26. package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
  27. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
  28. package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
  29. package/skills/alloy-guides/references/WIDGETS.md +1 -17
  30. package/skills/alloy-howtos/SKILL.md +1 -22
  31. package/skills/alloy-howtos/references/best_practices.md +0 -17
  32. package/skills/alloy-howtos/references/cli_reference.md +1 -23
  33. package/skills/alloy-howtos/references/config_files.md +86 -15
  34. package/skills/alloy-howtos/references/custom_tags.md +14 -13
  35. package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
  36. package/skills/alloy-howtos/references/samples.md +4 -14
  37. package/skills/purgetss/SKILL.md +11 -37
  38. package/skills/purgetss/references/EXAMPLES.md +106 -17
  39. package/skills/purgetss/references/animation-system.md +0 -67
  40. package/skills/purgetss/references/apply-directive.md +0 -18
  41. package/skills/purgetss/references/arbitrary-values.md +0 -25
  42. package/skills/purgetss/references/class-index.md +0 -46
  43. package/skills/purgetss/references/cli-commands.md +0 -41
  44. package/skills/purgetss/references/configurable-properties.md +0 -55
  45. package/skills/purgetss/references/custom-rules.md +0 -14
  46. package/skills/purgetss/references/customization-deep-dive.md +0 -49
  47. package/skills/purgetss/references/dynamic-component-creation.md +56 -37
  48. package/skills/purgetss/references/grid-layout.md +0 -32
  49. package/skills/purgetss/references/icon-fonts.md +0 -50
  50. package/skills/purgetss/references/installation-setup.md +61 -32
  51. package/skills/purgetss/references/migration-guide.md +127 -0
  52. package/skills/purgetss/references/opacity-modifier.md +0 -34
  53. package/skills/purgetss/references/performance-tips.md +261 -0
  54. package/skills/purgetss/references/platform-modifiers.md +0 -46
  55. package/skills/purgetss/references/smart-mappings.md +0 -12
  56. package/skills/purgetss/references/tikit-components.md +393 -0
  57. package/skills/purgetss/references/titanium-resets.md +1 -27
  58. package/skills/purgetss/references/ui-ux-design.md +467 -117
  59. package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
  60. package/skills/ti-expert/references/alloy-builtins.md +387 -0
  61. package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
  62. package/skills/ti-expert/references/anti-patterns.md +90 -0
  63. package/skills/ti-expert/references/cli-expert.md +109 -0
  64. package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
  65. package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
  66. package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
  67. package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
  68. package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
  69. package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
  70. package/skills/ti-expert/references/performance-listview.md +251 -0
  71. package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
  72. package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
  73. package/skills/ti-expert/references/security-fundamentals.md +284 -0
  74. package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
  75. package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
  76. package/skills/ti-expert/references/testing-unit.md +433 -0
  77. package/skills/ti-expert/references/theming.md +394 -0
  78. package/skills/ti-guides/SKILL.md +1 -14
  79. package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
  80. package/skills/ti-guides/references/app-distribution.md +48 -10
  81. package/skills/ti-guides/references/application-frameworks.md +9 -2
  82. package/skills/ti-guides/references/cli-reference.md +338 -82
  83. package/skills/ti-guides/references/coding-best-practices.md +14 -4
  84. package/skills/ti-guides/references/commonjs-advanced.md +103 -6
  85. package/skills/ti-guides/references/hello-world.md +5 -2
  86. package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
  87. package/skills/ti-guides/references/javascript-primer.md +4 -3
  88. package/skills/ti-guides/references/resources.md +0 -1
  89. package/skills/ti-guides/references/style-and-conventions.md +57 -9
  90. package/skills/ti-guides/references/tiapp-config.md +48 -6
  91. package/skills/ti-howtos/SKILL.md +2 -27
  92. package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
  93. package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
  94. package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
  95. package/skills/ti-howtos/references/cross-platform-development.md +68 -37
  96. package/skills/ti-howtos/references/debugging-profiling.md +8 -53
  97. package/skills/ti-howtos/references/extending-titanium.md +12 -51
  98. package/skills/ti-howtos/references/google-maps-v2.md +30 -29
  99. package/skills/ti-howtos/references/ios-map-kit.md +19 -25
  100. package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
  101. package/skills/ti-howtos/references/local-data-sources.md +45 -37
  102. package/skills/ti-howtos/references/location-and-maps.md +47 -28
  103. package/skills/ti-howtos/references/media-apis.md +84 -27
  104. package/skills/ti-howtos/references/notification-services.md +40 -89
  105. package/skills/ti-howtos/references/remote-data-sources.md +21 -36
  106. package/skills/ti-howtos/references/tutorials.md +79 -39
  107. package/skills/ti-howtos/references/using-modules.md +4 -30
  108. package/skills/ti-howtos/references/web-content-integration.md +28 -45
  109. package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
  110. package/skills/ti-ui/SKILL.md +1 -21
  111. package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
  112. package/skills/ti-ui/references/animation-and-matrices.md +0 -47
  113. package/skills/ti-ui/references/application-structures.md +0 -46
  114. package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
  115. package/skills/ti-ui/references/event-handling.md +32 -40
  116. package/skills/ti-ui/references/gestures.md +0 -40
  117. package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
  118. package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
  119. package/skills/ti-ui/references/listviews-and-performance.md +187 -73
  120. package/skills/ti-ui/references/orientation.md +57 -71
  121. package/skills/ti-ui/references/platform-ui-android.md +114 -48
  122. package/skills/ti-ui/references/platform-ui-ios.md +63 -38
  123. package/skills/ti-ui/references/scrolling-views.md +14 -23
  124. package/skills/ti-ui/references/tableviews.md +6 -56
  125. package/lib/commands/install.js +0 -188
  126. package/skills/alloy-expert/references/anti-patterns.md +0 -133
  127. package/skills/alloy-expert/references/testing.md +0 -872
  128. package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
  129. package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
  130. package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
  131. /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
  132. /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
@@ -146,8 +146,8 @@ module.exports = new Logger()
146
146
 
147
147
  ```javascript
148
148
  // lib/services/errorHandler.js
149
- const logger = require('lib/services/logger')
150
- const { AppError } = require('lib/core/appError')
149
+ const logger = require('services/logger')
150
+ const { AppError } = require('core/appError')
151
151
 
152
152
  exports.handleError = function handleError(error, context = {}) {
153
153
  // Log the error
@@ -201,8 +201,8 @@ function _getUserMessage(error) {
201
201
 
202
202
  ```javascript
203
203
  // lib/services/userService.js
204
- const logger = require('lib/services/logger')
205
- const { NetworkError, NotFoundError } = require('lib/core/appError')
204
+ const logger = require('services/logger')
205
+ const { NetworkError, NotFoundError } = require('core/appError')
206
206
 
207
207
  exports.getUserProfile = async function getUserProfile(userId) {
208
208
  logger.info('UserService', 'Fetching user profile', { userId })
@@ -237,8 +237,8 @@ exports.getUserProfile = async function getUserProfile(userId) {
237
237
 
238
238
  ```javascript
239
239
  // lib/api/client.js
240
- const logger = require('lib/services/logger')
241
- const { NetworkError, AuthError, NotFoundError, ValidationError } = require('lib/core/appError')
240
+ const logger = require('services/logger')
241
+ const { NetworkError, AuthError, NotFoundError, ValidationError } = require('core/appError')
242
242
 
243
243
  exports.get = async function get(endpoint, params = {}) {
244
244
  return new Promise((resolve, reject) => {
@@ -306,9 +306,9 @@ exports.get = async function get(endpoint, params = {}) {
306
306
 
307
307
  ```javascript
308
308
  // controllers/user/detail.js
309
- const logger = require('lib/services/logger')
310
- const { handleError } = require('lib/services/errorHandler')
311
- const { getUserProfile } = require('lib/services/userService')
309
+ const logger = require('services/logger')
310
+ const { handleError } = require('services/errorHandler')
311
+ const { getUserProfile } = require('services/userService')
312
312
 
313
313
  function init() {
314
314
  logger.debug('UserDetail', 'Controller initialized', { userId: $.args.userId })
@@ -380,7 +380,7 @@ $.cleanup = cleanup
380
380
 
381
381
  ```javascript
382
382
  // alloy.js - Setup global error catching
383
- const { handleError } = require('lib/services/errorHandler')
383
+ const { handleError } = require('services/errorHandler')
384
384
 
385
385
  // Catch unhandled errors in production
386
386
  if (Ti.App.deployType === 'production') {
@@ -429,8 +429,8 @@ exports.reportToCrashService = function reportToCrashService(error, context = {}
429
429
 
430
430
  ```javascript
431
431
  // lib/helpers/validator.js
432
- const { ValidationError } = require('lib/core/appError')
433
- const logger = require('lib/services/logger')
432
+ const { ValidationError } = require('core/appError')
433
+ const logger = require('services/logger')
434
434
 
435
435
  exports.validateEmail = function validateEmail(email) {
436
436
  const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
@@ -1,4 +1,4 @@
1
- # PurgeTSS Implementation Examples (Alloy + PurgeTSS)
1
+ # Alloy Implementation Examples
2
2
 
3
3
  ## API Client Service
4
4
  Standard logic for network requests.
@@ -64,30 +64,26 @@ exports.definition = {
64
64
  }
65
65
  ```
66
66
 
67
- ## Fully Styled & Accessible View (PurgeTSS)
68
- Applying PurgeTSS classes while maintaining accessibility.
67
+ ## Fully Styled & Accessible View
68
+ Applying TSS styles while maintaining accessibility.
69
69
 
70
70
  ```xml
71
71
  <!-- views/login.xml -->
72
72
  <Alloy>
73
- <Window class="vertical bg-gray-50">
74
- <Animation id="myAnim" module="purgetss.ui" class="close:opacity-0 duration-500 open:opacity-100" />
75
-
73
+ <Window id="loginWindow">
76
74
  <!-- Spacer to center content -->
77
- <View class="h-auto" />
75
+ <View id="topSpacer" />
78
76
 
79
- <Label class="text-primary fa-solid fa-lock mx-6 mb-10 text-4xl"
77
+ <ImageView id="lockIcon" image="/images/lock.png"
80
78
  accessibilityLabel="L('login_icon_label')"
81
79
  />
82
80
 
83
81
  <TextField id="email"
84
- class="border-(1) mx-6 h-12 w-screen rounded-lg border-gray-300 bg-white"
85
82
  hintText="L('email_hint')"
86
83
  accessibilityLabel="L('email_label')"
87
84
  />
88
85
 
89
86
  <Button id="submit"
90
- class="bg-primary mx-6 mt-10 h-14 w-screen rounded-xl font-bold text-white"
91
87
  title="L('login_button')"
92
88
  accessibilityLabel="L('login_button')"
93
89
  accessibilityHint="L('login_hint')"
@@ -95,16 +91,25 @@ Applying PurgeTSS classes while maintaining accessibility.
95
91
  />
96
92
 
97
93
  <!-- Spacer to center content -->
98
- <View class="h-auto" />
94
+ <View id="bottomSpacer" />
99
95
  </Window>
100
96
  </Alloy>
101
97
  ```
102
98
 
99
+ ```tss
100
+ /* styles/login.tss */
101
+ "#loginWindow": { layout: 'vertical', backgroundColor: '#f9fafb' }
102
+ "#topSpacer": { height: Ti.UI.SIZE }
103
+ "#lockIcon": { left: 24, right: 24, bottom: 40, width: 48, height: 48 }
104
+ "#email": { left: 24, right: 24, height: 48, borderRadius: 8, borderWidth: 1, borderColor: '#d1d5db', backgroundColor: '#fff' }
105
+ "#submit": { left: 24, right: 24, top: 40, height: 56, borderRadius: 12, backgroundColor: '#2563eb', color: '#fff', font: { fontWeight: 'bold' } }
106
+ "#bottomSpacer": { height: Ti.UI.SIZE }
107
+ ```
108
+
103
109
  **Notes:**
104
- - Use `vertical` layout on Window (not `flex-col`)
105
- - Use `mx-6` for horizontal padding (not `p-6` on parent)
106
- - Use `w-screen` for full width (not `w-full`)
107
- - Use `border-(1)` with parentheses for arbitrary border width
110
+ - Use `layout: 'vertical'` on Window for top-to-bottom content flow
111
+ - Use margins on children for spacing (NOT padding on parent)
112
+ - Use `Ti.UI.FILL` for full-width elements
108
113
 
109
114
  ## Cleanup Pattern in Controller
110
115
  Critical for memory management and avoiding leaks.
@@ -128,13 +133,23 @@ function cleanup() {
128
133
  $.cleanup = cleanup
129
134
  ```
130
135
 
131
- ## Animation Component Usage
132
- Using the toolkit for UI transformations via the `<Animation>` component.
136
+ ## Animation Usage
137
+ Using `Ti.UI.createAnimation()` for UI transformations.
133
138
 
134
139
  ```javascript
135
140
  // Inside any controller
136
141
  function shakeError(element) {
137
- $.myAnim.play(element, 'animate-shake duration-200')
142
+ const shake = Ti.UI.createAnimation({ duration: 50 })
143
+ const offset = 10
144
+
145
+ shake.transform = Ti.UI.createMatrix2D().translate(offset, 0)
146
+ element.animate(shake, () => {
147
+ shake.transform = Ti.UI.createMatrix2D().translate(-offset, 0)
148
+ element.animate(shake, () => {
149
+ shake.transform = Ti.UI.createMatrix2D()
150
+ element.animate(shake)
151
+ })
152
+ })
138
153
  }
139
154
  ```
140
155
 
@@ -142,9 +157,9 @@ function shakeError(element) {
142
157
 
143
158
  ```javascript
144
159
  // lib/services/productService.js
145
- const { productApi } = require('lib/api/productApi')
146
- const { appStore } = require('lib/services/stateStore')
147
- const logger = require('lib/services/logger')
160
+ const { productApi } = require('api/productApi')
161
+ const { appStore } = require('services/stateStore')
162
+ const logger = require('services/logger')
148
163
 
149
164
  exports.productService = {
150
165
  getAll: async function(filters = {}) {
@@ -196,18 +211,18 @@ exports.productService = {
196
211
  ```xml
197
212
  <!-- views/products/list.xml -->
198
213
  <Alloy>
199
- <Window class="bg-gray-50">
200
- <ListView id="listView" class="wh-screen">
214
+ <Window id="productsWindow">
215
+ <ListView id="listView">
201
216
  <RefreshControl id="refresh" onRefresh="onRefresh" />
202
217
 
203
218
  <Templates>
204
219
  <ItemTemplate name="product" height="80">
205
- <View class="horizontal mb-2 h-20 w-screen bg-white">
206
- <ImageView bindId="image" class="wh-16 ml-3 rounded-lg" />
207
- <View class="vertical ml-3 w-auto">
208
- <Label bindId="name" class="text-base font-semibold" />
209
- <Label bindId="price" class="text-sm text-green-600" />
210
- <Label bindId="stock" class="text-xs text-gray-400" />
220
+ <View id="productRow">
221
+ <ImageView bindId="image" id="productImg" />
222
+ <View id="productInfo">
223
+ <Label bindId="name" id="productName" />
224
+ <Label bindId="price" id="productPrice" />
225
+ <Label bindId="stock" id="productStock" />
211
226
  </View>
212
227
  </View>
213
228
  </ItemTemplate>
@@ -223,20 +238,28 @@ exports.productService = {
223
238
  </ListSection>
224
239
  </ListView>
225
240
 
226
- <Button id="addBtn"
227
- class="bg-primary rounded-full-14 absolute bottom-6 right-6 shadow-lg"
228
- onClick="onAddProduct"
229
- >
230
- <Label class="fa-solid fa-plus text-xl text-white" />
231
- </Button>
241
+ <Button id="addBtn" onClick="onAddProduct" title="+" />
232
242
  </Window>
233
243
  </Alloy>
234
244
  ```
235
245
 
246
+ ```tss
247
+ /* styles/products/list.tss */
248
+ "#productsWindow": { backgroundColor: '#f9fafb' }
249
+ "#listView": { width: Ti.UI.FILL, height: Ti.UI.FILL }
250
+ "#productRow": { layout: 'horizontal', bottom: 8, height: 80, width: Ti.UI.FILL, backgroundColor: '#fff' }
251
+ "#productImg": { left: 12, width: 64, height: 64, borderRadius: 8 }
252
+ "#productInfo": { layout: 'vertical', left: 12 }
253
+ "#productName": { font: { fontSize: 16, fontWeight: 'semibold' } }
254
+ "#productPrice": { font: { fontSize: 14 }, color: '#16a34a' }
255
+ "#productStock": { font: { fontSize: 12 }, color: '#9ca3af' }
256
+ "#addBtn": { position: 'absolute', bottom: 24, right: 24, width: 56, height: 56, borderRadius: 28, backgroundColor: '#2563eb', color: '#fff', font: { fontSize: 24 } }
257
+ ```
258
+
236
259
  ```javascript
237
260
  // controllers/products/list.js
238
- const { Navigation } = require('lib/services/navigation')
239
- const { productService } = require('lib/services/productService')
261
+ const { Navigation } = require('services/navigation')
262
+ const { productService } = require('services/productService')
240
263
 
241
264
  function init() {
242
265
  loadProducts()
@@ -283,39 +306,50 @@ $.cleanup = cleanup
283
306
  ```xml
284
307
  <!-- views/contacts/list.xml -->
285
308
  <Alloy>
286
- <Window class="bg-white">
309
+ <Window id="contactsWindow">
287
310
  <!-- Search and Filter Bar -->
288
- <View class="horizontal h-14 w-screen bg-gray-100">
311
+ <View id="searchFilterBar">
289
312
  <SearchBar id="searchBar"
290
- class="h-10 w-8/12"
291
313
  hintText="L('search')"
292
314
  showCancel="true"
293
315
  />
294
316
  <Button id="filterBtn"
295
- class="h-10 w-4/12"
296
317
  title="L('filter')"
297
318
  onClick="showFilters"
298
319
  />
299
320
  </View>
300
321
 
301
322
  <!-- Active Filters -->
302
- <ScrollView id="filterTags" class="horizontal hidden h-10 w-screen">
323
+ <ScrollView id="filterTags">
303
324
  <!-- Dynamically populated filter tags -->
304
325
  </ScrollView>
305
326
 
306
- <ListView id="listView" class="wh-screen">
327
+ <ListView id="listView">
307
328
  <ListSection id="section" />
308
329
  </ListView>
309
330
 
310
331
  <!-- Empty State -->
311
- <View id="emptyState" class="wh-screen vertical hidden">
312
- <Label class="fa-solid fa-search mt-20 text-6xl text-gray-300" />
313
- <Label class="mt-4 text-lg text-gray-500" text="L('no_results')" />
332
+ <View id="emptyState">
333
+ <ImageView id="emptyIcon" image="/images/search.png" />
334
+ <Label id="emptyLabel" text="L('no_results')" />
314
335
  </View>
315
336
  </Window>
316
337
  </Alloy>
317
338
  ```
318
339
 
340
+ ```tss
341
+ /* styles/contacts/list.tss */
342
+ "#contactsWindow": { backgroundColor: '#fff' }
343
+ "#searchFilterBar": { layout: 'horizontal', height: 56, width: Ti.UI.FILL, backgroundColor: '#f3f4f6' }
344
+ "#searchBar": { height: 40, width: '66%' }
345
+ "#filterBtn": { height: 40, width: '34%' }
346
+ "#filterTags": { layout: 'horizontal', height: 40, width: Ti.UI.FILL, visible: false }
347
+ "#listView": { width: Ti.UI.FILL, height: Ti.UI.FILL }
348
+ "#emptyState": { layout: 'vertical', width: Ti.UI.FILL, height: Ti.UI.FILL, visible: false }
349
+ "#emptyIcon": { top: 80, width: 64, height: 64 }
350
+ "#emptyLabel": { top: 16, font: { fontSize: 18 }, color: '#6b7280' }
351
+ ```
352
+
319
353
  ```javascript
320
354
  // controllers/contacts/list.js
321
355
  let allItems = []
@@ -426,73 +460,70 @@ $.cleanup = cleanup
426
460
  ```xml
427
461
  <!-- views/auth/register.xml -->
428
462
  <Alloy>
429
- <Window class="vertical bg-white">
430
- <ScrollView class="wh-screen vertical" contentHeight="Ti.UI.SIZE">
431
- <View class="vertical mt-8 h-auto w-screen">
463
+ <Window id="registerWindow">
464
+ <ScrollView id="scrollView" contentHeight="Ti.UI.SIZE">
465
+ <View id="formContainer">
432
466
  <!-- Logo -->
433
- <ImageView class="wh-24" image="/images/logo.png" />
467
+ <ImageView id="logo" image="/images/logo.png" />
434
468
 
435
469
  <!-- Title -->
436
- <Label class="mt-6 text-2xl font-bold" text="L('create_account')" />
470
+ <Label id="titleLabel" text="L('create_account')" />
437
471
 
438
472
  <!-- Name Field -->
439
- <View class="mx-4 mt-6 w-screen">
440
- <Label class="text-sm text-gray-600" text="L('full_name')" />
441
- <TextField id="nameField"
442
- class="border-(1) return-key-type-next mt-1 h-12 w-screen rounded-lg border-gray-300 px-3"
443
- autocorrect="false"
473
+ <View id="nameGroup">
474
+ <Label id="nameLabel" text="L('full_name')" />
475
+ <TextField id="nameField" autocorrect="false"
476
+ returnKeyType="Ti.UI.RETURNKEY_NEXT"
444
477
  />
445
- <Label id="nameError" class="mt-1 hidden text-xs text-red-500" />
478
+ <Label id="nameError" />
446
479
  </View>
447
480
 
448
481
  <!-- Email Field -->
449
- <View class="mx-4 mt-4 w-screen">
450
- <Label class="text-sm text-gray-600" text="L('email')" />
482
+ <View id="emailGroup">
483
+ <Label id="emailLabel" text="L('email')" />
451
484
  <TextField id="emailField"
452
- class="border-(1) keyboard-type-email return-key-type-next mt-1 h-12 w-screen rounded-lg border-gray-300 px-3"
485
+ keyboardType="Ti.UI.KEYBOARD_TYPE_EMAIL"
486
+ returnKeyType="Ti.UI.RETURNKEY_NEXT"
453
487
  autocapitalization="none"
454
488
  />
455
- <Label id="emailError" class="mt-1 hidden text-xs text-red-500" />
489
+ <Label id="emailError" />
456
490
  </View>
457
491
 
458
492
  <!-- Password Field -->
459
- <View class="mx-4 mt-4 w-screen">
460
- <Label class="text-sm text-gray-600" text="L('password')" />
461
- <TextField id="passwordField"
462
- class="border-(1) return-key-type-next mt-1 h-12 w-screen rounded-lg border-gray-300 px-3"
463
- passwordMask="true"
493
+ <View id="passwordGroup">
494
+ <Label id="passwordLabel" text="L('password')" />
495
+ <TextField id="passwordField" passwordMask="true"
496
+ returnKeyType="Ti.UI.RETURNKEY_NEXT"
464
497
  />
465
- <Label id="passwordError" class="mt-1 hidden text-xs text-red-500" />
466
- <Label class="mt-1 text-xs text-gray-400" text="L('password_hint')" />
498
+ <Label id="passwordError" />
499
+ <Label id="passwordHint" text="L('password_hint')" />
467
500
  </View>
468
501
 
469
502
  <!-- Confirm Password -->
470
- <View class="mx-4 mt-4 w-screen">
471
- <Label class="text-sm text-gray-600" text="L('confirm_password')" />
472
- <TextField id="confirmField"
473
- class="border-(1) return-key-type-done mt-1 h-12 w-screen rounded-lg border-gray-300 px-3"
474
- passwordMask="true"
503
+ <View id="confirmGroup">
504
+ <Label id="confirmLabel" text="L('confirm_password')" />
505
+ <TextField id="confirmField" passwordMask="true"
506
+ returnKeyType="Ti.UI.RETURNKEY_DONE"
475
507
  />
476
- <Label id="confirmError" class="mt-1 hidden text-xs text-red-500" />
508
+ <Label id="confirmError" />
477
509
  </View>
478
510
 
479
511
  <!-- Terms Checkbox -->
480
- <View class="horizontal mx-4 mt-6 w-screen">
481
- <Switch id="termsSwitch" class="w-12" />
482
- <Label class="ml-2 w-auto text-sm text-gray-600" text="L('accept_terms')" />
512
+ <View id="termsRow">
513
+ <Switch id="termsSwitch" />
514
+ <Label id="termsLabel" text="L('accept_terms')" />
483
515
  </View>
484
516
 
485
517
  <!-- Register Button -->
486
518
  <Button id="registerBtn"
487
- class="bg-primary mx-4 mt-6 h-14 w-screen rounded-xl font-bold text-white"
488
519
  title="L('register')"
489
520
  onClick="onRegister"
490
521
  />
491
522
 
492
523
  <!-- Login Link -->
493
- <View class="horizontal mt-4">
494
- <Label class="text-sm text-gray-600" text="L('have_account')" />
495
- <Label class="text-primary ml-1 text-sm" text="L('login')" onClick="goToLogin" />
524
+ <View id="loginRow">
525
+ <Label id="haveAccountLabel" text="L('have_account')" />
526
+ <Label id="loginLink" text="L('login')" onClick="goToLogin" />
496
527
  </View>
497
528
  </View>
498
529
  </ScrollView>
@@ -500,10 +531,38 @@ $.cleanup = cleanup
500
531
  </Alloy>
501
532
  ```
502
533
 
534
+ ```tss
535
+ /* styles/auth/register.tss */
536
+ "#registerWindow": { layout: 'vertical', backgroundColor: '#fff' }
537
+ "#scrollView": { layout: 'vertical', width: Ti.UI.FILL, height: Ti.UI.FILL }
538
+ "#formContainer": { layout: 'vertical', top: 32, height: Ti.UI.SIZE, width: Ti.UI.FILL }
539
+ "#logo": { width: 96, height: 96 }
540
+ "#titleLabel": { top: 24, font: { fontSize: 24, fontWeight: 'bold' } }
541
+ ".fieldGroup": { layout: 'vertical', left: 16, right: 16, top: 16, width: Ti.UI.FILL }
542
+ "#nameGroup": { layout: 'vertical', left: 16, right: 16, top: 24, width: Ti.UI.FILL }
543
+ "#emailGroup": { layout: 'vertical', left: 16, right: 16, top: 16, width: Ti.UI.FILL }
544
+ "#passwordGroup": { layout: 'vertical', left: 16, right: 16, top: 16, width: Ti.UI.FILL }
545
+ "#confirmGroup": { layout: 'vertical', left: 16, right: 16, top: 16, width: Ti.UI.FILL }
546
+ "Label": { font: { fontSize: 14 }, color: '#4b5563' }
547
+ "TextField": { top: 4, height: 48, width: Ti.UI.FILL, borderRadius: 8, borderWidth: 1, borderColor: '#d1d5db', paddingLeft: 12 }
548
+ "#nameError": { top: 4, font: { fontSize: 12 }, color: '#ef4444', visible: false }
549
+ "#emailError": { top: 4, font: { fontSize: 12 }, color: '#ef4444', visible: false }
550
+ "#passwordError": { top: 4, font: { fontSize: 12 }, color: '#ef4444', visible: false }
551
+ "#passwordHint": { top: 4, font: { fontSize: 12 }, color: '#9ca3af' }
552
+ "#confirmError": { top: 4, font: { fontSize: 12 }, color: '#ef4444', visible: false }
553
+ "#termsRow": { layout: 'horizontal', left: 16, right: 16, top: 24, width: Ti.UI.FILL }
554
+ "#termsSwitch": { width: 48 }
555
+ "#termsLabel": { left: 8 }
556
+ "#registerBtn": { left: 16, right: 16, top: 24, height: 56, borderRadius: 12, backgroundColor: '#2563eb', color: '#fff', font: { fontWeight: 'bold' } }
557
+ "#loginRow": { layout: 'horizontal', top: 16 }
558
+ "#haveAccountLabel": { font: { fontSize: 14 }, color: '#4b5563' }
559
+ "#loginLink": { left: 4, font: { fontSize: 14 }, color: '#2563eb' }
560
+ ```
561
+
503
562
  ```javascript
504
563
  // controllers/auth/register.js
505
- const { AuthService } = require('lib/services/authService')
506
- const { Navigation } = require('lib/services/navigation')
564
+ const { AuthService } = require('services/authService')
565
+ const { Navigation } = require('services/navigation')
507
566
 
508
567
  const validators = {
509
568
  name: (value) => {
@@ -642,7 +701,7 @@ $.cleanup = cleanup
642
701
  ```xml
643
702
  <!-- views/main.xml -->
644
703
  <Alloy>
645
- <TabGroup id="tabGroup" class="tabs-bg-white active-tint-blue-500">
704
+ <TabGroup id="tabGroup">
646
705
 
647
706
  <Tab id="homeTab" title="L('home')" icon="/images/icons/home.png">
648
707
  <Require src="tabs/home" />
@@ -665,7 +724,7 @@ $.cleanup = cleanup
665
724
 
666
725
  ```javascript
667
726
  // controllers/main.js
668
- const EventBus = require('lib/services/eventBus')
727
+ const EventBus = require('services/eventBus')
669
728
  const Events = EventBus.Events
670
729
 
671
730
  function init() {
@@ -4,59 +4,61 @@
4
4
 
5
5
  Before migrating, evaluate the current codebase:
6
6
 
7
- | Area | Signs of Legacy Code | Target State |
8
- | ----------- | -------------------------------------------------- | ------------------------------- |
9
- | Styling | Manual `.tss` files, inline attributes | PurgeTSS utility classes |
10
- | Controllers | 200+ lines, API calls, business logic | Thin orchestrators (<100 lines) |
11
- | Events | `Ti.App.fireEvent` everywhere | Backbone.Events or StateStore |
12
- | Navigation | Direct `Alloy.createController().getView().open()` | Navigation service |
13
- | Data | Scattered `Ti.App.Properties`, no collections | Centralized state + Collections |
7
+ | Area | Signs of Legacy Code | Target State |
8
+ | ----------- | -------------------------------------------------- | --------------------------------------------- |
9
+ | Styling | Inline attributes, scattered styles | Organized TSS files (per-controller + global) |
10
+ | Controllers | 200+ lines, API calls, business logic | Thin orchestrators (<100 lines) |
11
+ | Events | `Ti.App.fireEvent` everywhere | Backbone.Events or StateStore |
12
+ | Navigation | Direct `Alloy.createController().getView().open()` | Navigation service |
13
+ | Data | Scattered `Ti.App.Properties`, no collections | Centralized state + Collections |
14
14
 
15
- ## Phase 1: PurgeTSS Integration
15
+ ## Phase 1: TSS Organization
16
16
 
17
- **Goal**: Migrate from manual TSS to utility-first styling.
17
+ **Goal**: Migrate from inline styling and scattered styles to well-organized TSS files.
18
18
 
19
- ### Step 1: Initialize PurgeTSS
19
+ ### Step 1: Audit Existing Styles
20
20
 
21
+ Find all inline attributes and consolidate into TSS files:
21
22
  ```bash
22
- # In existing project
23
- cd your-app
24
- purgetss init
23
+ # Find inline styling in XML views
24
+ grep -r 'backgroundColor=' app/views/
25
+ grep -r 'font=' app/views/
26
+ grep -r 'color=' app/views/
25
27
  ```
26
28
 
27
- ### Step 2: Backup Existing Styles
29
+ ### Step 2: Move Inline Attributes to TSS
28
30
 
29
- PurgeTSS automatically backs up `app.tss` to `_app.tss`. Your custom styles are preserved.
30
-
31
- ### Step 3: Migrate Views Incrementally
31
+ ```xml
32
+ <!-- BEFORE: Inline attributes -->
33
+ <View id="header" backgroundColor="#fff" height="60" top="0">
34
+ <Label id="title" text="Welcome" color="#333" font="{fontSize:18, fontWeight:'bold'}" />
35
+ </View>
36
+ ```
32
37
 
33
38
  ```xml
34
- <!-- BEFORE: Manual styling -->
39
+ <!-- AFTER: Clean XML + TSS file -->
35
40
  <View id="header">
36
- <Label id="title" text="Welcome" />
41
+ <Label id="title" text="L('welcome')" />
37
42
  </View>
43
+ ```
38
44
 
39
- <!-- styles/index.tss -->
45
+ ```tss
46
+ /* styles/index.tss */
40
47
  "#header": { backgroundColor: "#fff", height: 60, top: 0 }
41
48
  "#title": { color: "#333", font: { fontSize: 18, fontWeight: "bold" } }
42
49
  ```
43
50
 
44
- ```xml
45
- <!-- AFTER: PurgeTSS classes -->
46
- <View class="top-0 h-16 bg-white">
47
- <Label class="text-lg font-bold text-gray-800" text="Welcome" />
48
- </View>
51
+ ### Step 3: Organize TSS Structure
49
52
 
50
- <!-- No manual TSS needed - delete #header and #title styles -->
53
+ 1. Use `app.tss` for global styles (shared across all views)
54
+ 2. Use per-controller TSS files for view-specific styles
55
+ 3. Use class selectors for reusable style patterns:
56
+ ```tss
57
+ /* app.tss - Global reusable styles */
58
+ ".card": { borderRadius: 12, backgroundColor: '#fff' }
59
+ ".btn-primary": { backgroundColor: '#2563eb', color: '#fff', height: 44, borderRadius: 8 }
51
60
  ```
52
61
 
53
- ### Step 4: Remove Manual TSS Files
54
-
55
- Once a view is fully migrated to utility classes:
56
- 1. Remove corresponding entries from `_app.tss`
57
- 2. Delete any controller-specific `.tss` files
58
- 3. Run `purgetss` to regenerate `app.tss`
59
-
60
62
  ## Phase 2: Service Layer Extraction
61
63
 
62
64
  **Goal**: Move business logic from controllers to services.
@@ -221,7 +223,7 @@ exports.getStack = function() {
221
223
  Alloy.createController('detail', { id: 123 }).getView().open()
222
224
 
223
225
  // AFTER: Navigation service (auto cleanup)
224
- const navigation = require('lib/services/navigation')
226
+ const navigation = require('services/navigation')
225
227
  navigation.open('detail', { id: 123 })
226
228
  ```
227
229
 
@@ -252,7 +254,7 @@ const user = JSON.parse(Ti.App.Properties.getString('user'))
252
254
 
253
255
  // AFTER: Centralized state
254
256
  // In service
255
- const { appStore } = require('lib/services/stateStore')
257
+ const { appStore } = require('services/stateStore')
256
258
  appStore.setState({ user })
257
259
 
258
260
  // In any controller
@@ -263,7 +265,7 @@ const { user } = appStore.getState()
263
265
 
264
266
  Recommended sequence to minimize risk:
265
267
 
266
- 1. **PurgeTSS** - Visual only, no logic changes
268
+ 1. **TSS Organization** - Visual only, no logic changes
267
269
  2. **Service Layer** - Extract logic without changing behavior
268
270
  3. **Navigation Service** - Centralize with cleanup
269
271
  4. **Event System** - Replace Ti.App events
@@ -104,10 +104,10 @@ exports.UserRepository = {
104
104
 
105
105
  ```javascript
106
106
  // lib/services/authService.js
107
- const authApi = require('lib/api/authApi').authApi
108
- const { TokenStorage } = require('lib/services/tokenStorage')
109
- const { appStore } = require('lib/services/stateStore')
110
- const { Validator } = require('lib/helpers/validator')
107
+ const authApi = require('api/authApi').authApi
108
+ const { TokenStorage } = require('services/tokenStorage')
109
+ const { appStore } = require('services/stateStore')
110
+ const { Validator } = require('helpers/validator')
111
111
 
112
112
  exports.AuthService = {
113
113
  async login(email, password) {
@@ -175,7 +175,7 @@ module.exports.Events = Events
175
175
 
176
176
  ```javascript
177
177
  // controllers/profile.js
178
- const EventBus = require('lib/services/eventBus')
178
+ const EventBus = require('services/eventBus')
179
179
  const { Events } = EventBus
180
180
 
181
181
  function init() {
@@ -339,7 +339,7 @@ $.cleanup = cleanup
339
339
 
340
340
  ```xml
341
341
  <!-- views/products/list.xml -->
342
- <ListView class="wh-screen">
342
+ <ListView id="listView">
343
343
  <ListSection dataCollection="products">
344
344
  <ListItem title="{name}" subtitle="{description}" />
345
345
  </ListSection>
@@ -352,9 +352,9 @@ $.cleanup = cleanup
352
352
 
353
353
  ```javascript
354
354
  // controllers/dashboard.js
355
- const EventBus = require('lib/services/eventBus')
355
+ const EventBus = require('services/eventBus')
356
356
  const { Events } = EventBus
357
- const { appStore } = require('lib/services/stateStore')
357
+ const { appStore } = require('services/stateStore')
358
358
 
359
359
  // Store references for cleanup
360
360
  let storeUnsubscribe = null