@maccesar/titools 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/AGENTS-TEMPLATE.md +173 -0
  2. package/README.md +867 -0
  3. package/agents/ti-researcher.md +108 -0
  4. package/bin/titools.js +53 -0
  5. package/lib/commands/agents.js +126 -0
  6. package/lib/commands/install.js +188 -0
  7. package/lib/commands/uninstall.js +215 -0
  8. package/lib/commands/update.js +159 -0
  9. package/lib/config.js +119 -0
  10. package/lib/downloader.js +153 -0
  11. package/lib/installer.js +253 -0
  12. package/lib/platform.js +108 -0
  13. package/lib/symlink.js +142 -0
  14. package/lib/utils.js +270 -0
  15. package/package.json +67 -0
  16. package/skills/alloy-expert/SKILL.md +247 -0
  17. package/skills/alloy-expert/assets/ControllerAutoCleanup.js +182 -0
  18. package/skills/alloy-expert/references/alloy-structure.md +381 -0
  19. package/skills/alloy-expert/references/anti-patterns.md +133 -0
  20. package/skills/alloy-expert/references/code-conventions.md +469 -0
  21. package/skills/alloy-expert/references/contracts.md +280 -0
  22. package/skills/alloy-expert/references/controller-patterns.md +520 -0
  23. package/skills/alloy-expert/references/error-handling.md +484 -0
  24. package/skills/alloy-expert/references/examples.md +735 -0
  25. package/skills/alloy-expert/references/migration-patterns.md +298 -0
  26. package/skills/alloy-expert/references/patterns.md +448 -0
  27. package/skills/alloy-expert/references/performance-patterns.md +855 -0
  28. package/skills/alloy-expert/references/security-patterns.md +847 -0
  29. package/skills/alloy-expert/references/state-management.md +779 -0
  30. package/skills/alloy-expert/references/testing.md +872 -0
  31. package/skills/alloy-guides/SKILL.md +214 -0
  32. package/skills/alloy-guides/references/CLI_TASKS.md +243 -0
  33. package/skills/alloy-guides/references/CONCEPTS.md +191 -0
  34. package/skills/alloy-guides/references/CONTROLLERS.md +298 -0
  35. package/skills/alloy-guides/references/MODELS.md +1028 -0
  36. package/skills/alloy-guides/references/PURGETSS.md +56 -0
  37. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +242 -0
  38. package/skills/alloy-guides/references/VIEWS_STYLES.md +388 -0
  39. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +109 -0
  40. package/skills/alloy-guides/references/VIEWS_XML.md +558 -0
  41. package/skills/alloy-guides/references/WIDGETS.md +176 -0
  42. package/skills/alloy-howtos/SKILL.md +203 -0
  43. package/skills/alloy-howtos/references/best_practices.md +138 -0
  44. package/skills/alloy-howtos/references/cli_reference.md +253 -0
  45. package/skills/alloy-howtos/references/config_files.md +87 -0
  46. package/skills/alloy-howtos/references/custom_tags.md +147 -0
  47. package/skills/alloy-howtos/references/debugging_troubleshooting.md +101 -0
  48. package/skills/alloy-howtos/references/samples.md +167 -0
  49. package/skills/purgetss/SKILL.md +442 -0
  50. package/skills/purgetss/assets/purgetss.config.cjs +17 -0
  51. package/skills/purgetss/references/EXAMPLES.md +247 -0
  52. package/skills/purgetss/references/animation-system.md +1294 -0
  53. package/skills/purgetss/references/apply-directive.md +375 -0
  54. package/skills/purgetss/references/arbitrary-values.md +612 -0
  55. package/skills/purgetss/references/class-index.md +1350 -0
  56. package/skills/purgetss/references/cli-commands.md +948 -0
  57. package/skills/purgetss/references/configurable-properties.md +654 -0
  58. package/skills/purgetss/references/custom-rules.md +161 -0
  59. package/skills/purgetss/references/customization-deep-dive.md +722 -0
  60. package/skills/purgetss/references/dynamic-component-creation.md +489 -0
  61. package/skills/purgetss/references/grid-layout.md +455 -0
  62. package/skills/purgetss/references/icon-fonts.md +609 -0
  63. package/skills/purgetss/references/installation-setup.md +366 -0
  64. package/skills/purgetss/references/opacity-modifier.md +291 -0
  65. package/skills/purgetss/references/platform-modifiers.md +479 -0
  66. package/skills/purgetss/references/smart-mappings.md +42 -0
  67. package/skills/purgetss/references/titanium-resets.md +359 -0
  68. package/skills/purgetss/references/ui-ux-design.md +1526 -0
  69. package/skills/ti-guides/SKILL.md +94 -0
  70. package/skills/ti-guides/references/advanced-data-and-images.md +19 -0
  71. package/skills/ti-guides/references/alloy-cli-advanced.md +84 -0
  72. package/skills/ti-guides/references/alloy-data-mastery.md +29 -0
  73. package/skills/ti-guides/references/alloy-widgets-and-themes.md +19 -0
  74. package/skills/ti-guides/references/android-manifest.md +97 -0
  75. package/skills/ti-guides/references/app-distribution.md +258 -0
  76. package/skills/ti-guides/references/application-frameworks.md +377 -0
  77. package/skills/ti-guides/references/cli-reference.md +402 -0
  78. package/skills/ti-guides/references/coding-best-practices.md +102 -0
  79. package/skills/ti-guides/references/commonjs-advanced.md +134 -0
  80. package/skills/ti-guides/references/hello-world.md +100 -0
  81. package/skills/ti-guides/references/hyperloop-native-access.md +62 -0
  82. package/skills/ti-guides/references/javascript-primer.md +411 -0
  83. package/skills/ti-guides/references/reserved-words.md +36 -0
  84. package/skills/ti-guides/references/resources.md +183 -0
  85. package/skills/ti-guides/references/style-and-conventions.md +48 -0
  86. package/skills/ti-guides/references/tiapp-config.md +609 -0
  87. package/skills/ti-howtos/SKILL.md +174 -0
  88. package/skills/ti-howtos/references/android-platform-deep-dives.md +658 -0
  89. package/skills/ti-howtos/references/automation-fastlane-appium.md +95 -0
  90. package/skills/ti-howtos/references/buffer-codec-streams.md +140 -0
  91. package/skills/ti-howtos/references/cross-platform-development.md +348 -0
  92. package/skills/ti-howtos/references/debugging-profiling.md +543 -0
  93. package/skills/ti-howtos/references/extending-titanium.md +723 -0
  94. package/skills/ti-howtos/references/google-maps-v2.md +169 -0
  95. package/skills/ti-howtos/references/ios-map-kit.md +143 -0
  96. package/skills/ti-howtos/references/ios-platform-deep-dives.md +783 -0
  97. package/skills/ti-howtos/references/local-data-sources.md +301 -0
  98. package/skills/ti-howtos/references/location-and-maps.md +252 -0
  99. package/skills/ti-howtos/references/media-apis.md +210 -0
  100. package/skills/ti-howtos/references/notification-services.md +599 -0
  101. package/skills/ti-howtos/references/remote-data-sources.md +349 -0
  102. package/skills/ti-howtos/references/tutorials.md +502 -0
  103. package/skills/ti-howtos/references/using-modules.md +237 -0
  104. package/skills/ti-howtos/references/web-content-integration.md +307 -0
  105. package/skills/ti-howtos/references/webpack-build-pipeline.md +78 -0
  106. package/skills/ti-ui/SKILL.md +179 -0
  107. package/skills/ti-ui/references/accessibility-deep-dive.md +242 -0
  108. package/skills/ti-ui/references/animation-and-matrices.md +599 -0
  109. package/skills/ti-ui/references/application-structures.md +655 -0
  110. package/skills/ti-ui/references/custom-fonts-styling.md +579 -0
  111. package/skills/ti-ui/references/event-handling.md +393 -0
  112. package/skills/ti-ui/references/gestures.md +473 -0
  113. package/skills/ti-ui/references/icons-and-splash-screens.md +409 -0
  114. package/skills/ti-ui/references/layouts-and-positioning.md +462 -0
  115. package/skills/ti-ui/references/listviews-and-performance.md +619 -0
  116. package/skills/ti-ui/references/orientation.md +362 -0
  117. package/skills/ti-ui/references/platform-ui-android.md +635 -0
  118. package/skills/ti-ui/references/platform-ui-ios.md +469 -0
  119. package/skills/ti-ui/references/scrolling-views.md +252 -0
  120. package/skills/ti-ui/references/tableviews.md +568 -0
@@ -0,0 +1,1294 @@
1
+ # PurgeTSS Animation System
2
+
3
+ The `<Animation>` component (`purgetss.ui`) provides declarative, native 2D Matrix animations and transformations for Titanium.
4
+
5
+ :::info
6
+ **PurgeTSS** includes an Animation module to apply simple 2D Matrix animations and transformations to any element, an array of elements, or even to individual children of an element.
7
+ :::
8
+
9
+ The Animation object describes the properties of an animation. It represents:
10
+ - A single-phase animation with an end state
11
+ - A multi-phase animation using the `open`, `close`, and `complete` modifiers
12
+ - Global states for children of a View using the `children` modifier
13
+
14
+ When the `play` method is called on a View, the View is animated from its current state to the state described by the `Animation` object. The properties that can be animated include the view's position, size, colors, transformation matrix, and opacity.
15
+
16
+ ## Table of Contents
17
+
18
+ - [PurgeTSS Animation System](#purgetss-animation-system)
19
+ - [Table of Contents](#table-of-contents)
20
+ - [Installation](#installation)
21
+ - [Basic Usage](#basic-usage)
22
+ - [Available Methods](#available-methods)
23
+ - [The `play` Method](#the-play-method)
24
+ - [`play(views, [callback])`](#playviews-callback)
25
+ - [Play Example 1](#play-example-1)
26
+ - [Play Example 2: Complex Animations with States](#play-example-2-complex-animations-with-states)
27
+ - [`toggle(views, [callback])`](#toggleviews-callback)
28
+ - [The `open` and `close` Methods](#the-open-and-close-methods)
29
+ - [`open(views, [callback])`](#openviews-callback)
30
+ - [Open Method Example](#open-method-example)
31
+ - [`close(views, [callback])`](#closeviews-callback)
32
+ - [Close Method Example](#close-method-example)
33
+ - [The `apply` Method](#the-apply-method)
34
+ - [`apply(views)`](#applyviews)
35
+ - [Apply Example: TikTok-like Interface](#apply-example-tiktok-like-interface)
36
+ - [The `draggable` Method](#the-draggable-method)
37
+ - [Draggable Example](#draggable-example)
38
+ - [`drag` and `drop` Modifiers](#drag-and-drop-modifiers)
39
+ - [Drag \& Drop Example](#drag--drop-example)
40
+ - [`draggingType` Property](#draggingtype-property)
41
+ - [Dragging Type Example](#dragging-type-example)
42
+ - [`bounds` Modifier](#bounds-modifier)
43
+ - [Bounds Example 1: Local Bounds](#bounds-example-1-local-bounds)
44
+ - [Bounds Example 2: Global Bounds](#bounds-example-2-global-bounds)
45
+ - [`vertical` and `horizontal` Constraints](#vertical-and-horizontal-constraints)
46
+ - [Constraint Example](#constraint-example)
47
+ - [State Modifiers](#state-modifiers)
48
+ - [`open:` and `close:`](#open-and-close)
49
+ - [`complete:` Modifier](#complete-modifier)
50
+ - [Complete Example: Wordle Animation](#complete-example-wordle-animation)
51
+ - [`children:`](#children)
52
+ - [`child:`](#child)
53
+ - [Complex UI Elements](#complex-ui-elements)
54
+ - [Available Utilities](#available-utilities)
55
+ - [anchorPoint](#anchorpoint)
56
+ - [autoreverse](#autoreverse)
57
+ - [curve](#curve)
58
+ - [delay](#delay)
59
+ - [duration](#duration)
60
+ - [repeat](#repeat)
61
+ - [rotate](#rotate)
62
+ - [scale](#scale)
63
+ - [drag-apply, drag-animate](#drag-apply-drag-animate)
64
+ - [opacity-to-\*, toggle-visible](#opacity-to--toggle-visible)
65
+ - [zoom-in-*, zoom-out-*](#zoom-in--zoom-out-)
66
+ - [Best Practices](#best-practices)
67
+ - [1. Use Semantic IDs](#1-use-semantic-ids)
68
+ - [2. Combine Methods for Sequences](#2-combine-methods-for-sequences)
69
+ - [3. Use `complete:` for Post-Animation State](#3-use-complete-for-post-animation-state)
70
+ - [4. Leverage `children:` for Batch Animations](#4-leverage-children-for-batch-animations)
71
+ - [5. Use `toggle` for UI States](#5-use-toggle-for-ui-states)
72
+ - [Common Patterns](#common-patterns)
73
+ - [Modal Fade In/Out](#modal-fade-inout)
74
+ - [Slide Up/Down](#slide-updown)
75
+ - [Scale on Touch](#scale-on-touch)
76
+ - [Draggable Element with Bounds](#draggable-element-with-bounds)
77
+ - [Animation Properties Summary](#animation-properties-summary)
78
+ - [State Modifiers](#state-modifiers-1)
79
+ - [Timing and Special Classes](#timing-and-special-classes)
80
+
81
+ ---
82
+
83
+ ## Installation
84
+
85
+ ```bash
86
+ purgetss module
87
+ # or
88
+ purgetss m
89
+ ```
90
+
91
+ Installs `purgetss.ui.js` in `app/lib/`.
92
+
93
+ ## Basic Usage
94
+
95
+ ```xml
96
+ <Animation id="myAnimation" module="purgetss.ui" class="opacity-0 duration-200 open:opacity-100" />
97
+ ```
98
+
99
+ ```javascript
100
+ $.myAnimation.play($.myView)
101
+ ```
102
+
103
+ **You can set any position, size, colors, transformation, and opacity classes from `utilities.tss`.**
104
+
105
+ ---
106
+
107
+ ## Available Methods
108
+
109
+ | Method | Purpose |
110
+ | ---------------- | -------------------------------------------------------- |
111
+ | `play`, `toggle` | Animate element(s) or children with Animation properties |
112
+ | `open`, `close` | Explicitly manage opening/closing animations |
113
+ | `apply` | Apply properties instantly without animation |
114
+ | `draggable` | Convert View(s) to draggable elements |
115
+
116
+ ---
117
+
118
+ ## The `play` Method
119
+
120
+ The `play` method is used to reproduce the animation for a single view or an array of views. You can chain multiple Animation objects with callback functions to create a sequence of animations.
121
+
122
+ ### `play(views, [callback])`
123
+
124
+ Animates target(s) using defined class properties.
125
+
126
+ ```javascript
127
+ $.myAnimation.play($.myView)
128
+ $.myAnimation.play([$.view1, $.view2])
129
+ $.myAnimation.play($.myView, () => { console.log('done') })
130
+ ```
131
+
132
+ **Use cases:**
133
+ - One-time animations
134
+ - Sequences with callbacks
135
+ - Animating multiple views simultaneously
136
+
137
+ ### Play Example 1
138
+
139
+ Create an Animation element and the view you want to animate, and set the desired properties.
140
+
141
+ ```xml title="index.xml"
142
+ <Alloy>
143
+ <Window>
144
+ <Animation module="purgetss.ui" id="myAnimation" class="wh-32 bg-green-500 duration-1000" />
145
+
146
+ <View id="square" class="wh-16 bg-blue-500" />
147
+ </Window>
148
+ </Alloy>
149
+ ```
150
+
151
+ ```javascript title="index.js"
152
+ $.index.open()
153
+
154
+ $.myAnimation.play($.square)
155
+ ```
156
+
157
+ When the `play` method is called, the blue square will go from size 64x64 to 128x128 and change its color to green.
158
+
159
+ ### Play Example 2: Complex Animations with States
160
+
161
+ ```xml title="index.xml"
162
+ <Alloy>
163
+ <Window class="keep-screen-on">
164
+ <Animation id="changeWidth" class="close:w-28 debug open:w-11/12" module="purgetss.ui" />
165
+ <Animation id="changeColor" class="close:bg-blue-700 debug open:bg-purple-500" module="purgetss.ui" />
166
+ <Animation id="changeTransparency" class="close:duration-300 open:mt-(null) close:mt-8 open:h-11/12 close:w-14 close:h-14 close:opacity-100 open:w-10/12 open:opacity-50 open:duration-150" module="purgetss.ui" />
167
+ <Animation id="changeRetweet" class="close:duration-150 close:-mb-52 open:-mb-16 open:duration-200" module="purgetss.ui" />
168
+
169
+ <View class="vertical">
170
+ <Button class="ios:mt-16 mt-1 w-48 rounded bg-purple-500 text-purple-50" onClick="squaresFn" title="3 Squares" />
171
+ <Button class="mt-2 w-48 rounded bg-purple-500 text-purple-50" onClick="toggleFn" title="Toggle Colors" />
172
+ <Button class="mt-2 w-48 rounded bg-purple-500 text-purple-50" onClick="retweetFn" title="Toggle Re-Tweet" />
173
+
174
+ <View id="squaresView" class="vertical mt-10 w-screen">
175
+ <View class="wh-28 rounded-xl bg-blue-700" />
176
+ <View class="wh-28 mt-4 rounded-xl bg-blue-700" />
177
+ <View class="wh-28 mt-4 rounded-xl bg-blue-700" />
178
+ </View>
179
+ </View>
180
+
181
+ <View id="blueSquareView" class="mt-8 h-14 w-14 rounded-xl bg-blue-500" onClick="transparencyFn" />
182
+
183
+ <View id="retweetView" class="vertical -mb-52 h-48 w-screen rounded-2xl bg-gray-800" onClick="retweetFn">
184
+ <View class="mt-4 h-1 w-8 bg-slate-700" />
185
+
186
+ <View class="horizontal mx-4 mt-4">
187
+ <Label class="fas fa-retweet w-7 text-xl text-slate-500" />
188
+ <Label class="ml-2 text-left text-xl text-white" text="Re-Tweet" />
189
+ </View>
190
+
191
+ <View class="horizontal mx-4 mt-4">
192
+ <Label class="fas fa-pencil-alt w-7 text-xl text-slate-500" />
193
+ <Label class="ml-2 text-left text-xl text-white" text="Quote Tweet" />
194
+ </View>
195
+ </View>
196
+ </Window>
197
+ </Alloy>
198
+ ```
199
+
200
+ ```javascript title="index.js"
201
+ function transparencyFn() {
202
+ $.changeTransparency.play($.blueSquareView)
203
+ }
204
+
205
+ function toggleFn() {
206
+ $.changeColor.toggle($.squaresView.children)
207
+ }
208
+
209
+ function squaresFn() {
210
+ $.changeWidth.play($.squaresView.children)
211
+ }
212
+
213
+ function retweetFn() {
214
+ $.changeRetweet.play($.retweetView)
215
+ }
216
+
217
+ $.index.open()
218
+ ```
219
+
220
+ ### `toggle(views, [callback])`
221
+
222
+ Alternates between `open:` and `close:` states.
223
+
224
+ ```javascript
225
+ $.myAnimation.toggle($.myView)
226
+ ```
227
+
228
+ **Use cases:**
229
+ - UI state toggles (show/hide)
230
+ - Accordion behavior
231
+ - Alternating animations
232
+
233
+ ---
234
+
235
+ ## The `open` and `close` Methods
236
+
237
+ The `open` and `close` methods provide a clear and straightforward way to manage the opening and closing animations of your views, utilizing the predefined classes with the `open` and `close` modifiers.
238
+
239
+ By using these methods, you can ensure consistent and manageable animation behavior across your application, as opposed to using the `play` or `toggle` methods, which alternate between the `open` and `close` states based on the current state of the view.
240
+
241
+ This explicit control helps in scenarios where the exact state of the view is crucial for the desired user experience or application logic.
242
+
243
+ ### `open(views, [callback])`
244
+
245
+ The `open` method triggers the opening animation for the specified views. It uses the properties defined under the classes with the `open` modifier.
246
+
247
+ ```javascript
248
+ $.myAnimation.open(views, callback);
249
+ ```
250
+
251
+ - `views`: The view or array of views to apply the opening animation to.
252
+ - `callback`: An optional callback function that gets called when the animation completes.
253
+
254
+ #### Open Method Example
255
+
256
+ ```xml title="index.xml"
257
+ <Alloy>
258
+ <Window>
259
+ <Animation module="purgetss.ui" id="myAnimation" class="close:opacity-0 open:opacity-100" />
260
+
261
+ <View id="myView" class="opacity-0" />
262
+ </Window>
263
+ </Alloy>
264
+ ```
265
+
266
+ ```javascript title="index.js"
267
+ $.myAnimation.open($.myView, () => {
268
+ console.log('Open animation complete');
269
+ });
270
+ ```
271
+
272
+ In this example, the `myView` element will apply the animation properties defined in the classes with the `open` modifier when the `open` method is called, making the view fully opaque.
273
+
274
+ ### `close(views, [callback])`
275
+
276
+ The `close` method triggers the closing animation for the specified views. It uses the properties defined under the classes with the `close` modifier.
277
+
278
+ ```javascript
279
+ $.myAnimation.close(views, callback);
280
+ ```
281
+
282
+ - `views`: The view or array of views to apply the closing animation to.
283
+ - `callback`: An optional callback function that gets called when the animation completes.
284
+
285
+ #### Close Method Example
286
+
287
+ ```xml title="index.xml"
288
+ <Alloy>
289
+ <Window>
290
+ <Animation module="purgetss.ui" id="myAnimation" class="close:opacity-0 open:opacity-100" />
291
+
292
+ <View id="myView" class="opacity-100" />
293
+ </Window>
294
+ </Alloy>
295
+ ```
296
+
297
+ ```javascript title="index.js"
298
+ $.myAnimation.close($.myView, () => {
299
+ console.log('Close animation complete');
300
+ });
301
+ ```
302
+
303
+ In this example, the `myView` element will apply the animation properties defined in the classes with the `close` modifier when the `close` method is called, making the view fully transparent.
304
+
305
+ :::info
306
+ The `open` and `close` methods provide explicit control over animation states, as opposed to `play` or `toggle` which alternate based on current state.
307
+ :::
308
+
309
+ ---
310
+
311
+ ## The `apply` Method
312
+
313
+ Use the `apply` method when you need to immediately apply the properties and transformations to a view without any animation.
314
+
315
+ ### `apply(views)`
316
+
317
+ Applies properties instantly without animation (bypasses bridge thread).
318
+
319
+ ```javascript
320
+ $.myAnimation.apply($.myView)
321
+ ```
322
+
323
+ **Use cases:**
324
+ - Resetting to initial state
325
+ - Instant style changes
326
+ - Setting up initial positions
327
+
328
+ ### Apply Example: TikTok-like Interface
329
+
330
+ The `apply` method sets the properties instantly. In this example, the `ScrollableView` is rotated 90 degrees, and its content is counter-rotated -90 degrees to simulate a **TikTok-like** interface.
331
+
332
+ ```xml title="index.xml"
333
+ <Alloy>
334
+ <Window class="exit-on-close-false keep-screen-on">
335
+ <Animation module="purgetss.ui" id="rotate" class="platform-wh-inverted rotate-90" />
336
+ <Animation module="purgetss.ui" id="counterRotate" class="platform-wh -rotate-90" />
337
+
338
+ <ScrollableView id="scrollableView" class="overlay-enabled disable-bounce paging-control-alpha-100 scrolling-enabled show-paging-control paging-control-h-14 paging-control-on-top-false paging-control-transparent page-indicator-(rgba(0,0,0,0.24)) current-page-indicator-(rgba(0,0,0,1))">
339
+ <View class="bg-blue-500">
340
+ <Label class="text-center" text="View's Content" />
341
+ </View>
342
+
343
+ <View class="bg-red-500">
344
+ <Label class="text-center" text="View's Content" />
345
+ </View>
346
+
347
+ <View class="bg-green-500">
348
+ <Label class="text-center" text="View's Content" />
349
+ </View>
350
+ </ScrollableView>
351
+ </Window>
352
+ </Alloy>
353
+ ```
354
+
355
+ ```javascript title="index.js"
356
+ $.rotate.apply($.scrollableView)
357
+
358
+ $.counterRotate.apply($.scrollableView.views)
359
+
360
+ $.index.open()
361
+ ```
362
+
363
+ ---
364
+
365
+ ## The `draggable` Method
366
+
367
+ The `draggable` method allows you to convert any view or an array of views into draggable elements.
368
+
369
+ - You can set **basic animations** when dragging or dropping elements using the `drag:` and `drop:` modifiers.
370
+ - You can `apply` or `animate` the properties either globally or locally using the `drag-apply` or `drag-animate` classes.
371
+ - You can also constrain any view using the `horizontal-constraint` or `vertical-constraint` classes.
372
+
373
+ ```javascript
374
+ // Calling a draggable method
375
+ $.draggableAnimation.draggable('A View or an array of Views')
376
+ ```
377
+
378
+ :::info
379
+ **You can create a blank `Animation` object or use an existing one to call the `draggable` method to convert a view or array of views into 'draggable' objects.**
380
+
381
+ **When using an Animation object on an array of views, it will handle the zIndex of each draggable element.**
382
+ :::
383
+
384
+ ### Draggable Example
385
+
386
+ ```xml title="index.xml"
387
+ <Alloy>
388
+ <Window class="keep-screen-on exit-on-close-false">
389
+ <Animation module="purgetss.ui" id="draggableAnimation" />
390
+
391
+ <Label text="Draggable Example" class="mt-16 text-center" />
392
+
393
+ <View id="red" class="ml-4 h-32 w-32 rounded-lg bg-red-500" />
394
+
395
+ <View id="green" class="ml-10 h-32 w-32 rounded-lg bg-green-500" />
396
+
397
+ <View id="blue" class="ml-16 h-32 w-32 rounded-lg bg-blue-500" />
398
+ </Window>
399
+ </Alloy>
400
+ ```
401
+
402
+ ```javascript title="index.js"
403
+ $.index.open()
404
+
405
+ $.draggableAnimation.draggable([$.red, $.green, $.blue])
406
+ ```
407
+
408
+ ### `drag` and `drop` Modifiers
409
+
410
+ The `drag:` and `drop:` modifiers allow you to set basic animations while dragging and dropping elements.
411
+
412
+ - You can set 'global' modifiers in the `Animation` object, or you can set individual modifiers for each view.
413
+ - Local modifiers will overwrite any global modifier.
414
+
415
+ :::info
416
+ To simplify things, we are restricting the types of animations that can be applied while dragging (or dropping).
417
+
418
+ **Mainly, we are not applying any `size`, `scale`, or `anchorPoint` transformation.**
419
+ :::
420
+
421
+ #### Drag & Drop Example
422
+
423
+ ```xml title="index.xml"
424
+ <Alloy>
425
+ <Window class="keep-screen-on exit-on-close-false">
426
+ <!-- Global set of modifiers -->
427
+ <Animation id="draggableAnimation" module="purgetss.ui" class="drag:duration-100 drag:opacity-50 drop:opacity-100" />
428
+
429
+ <Label text="Global Modifiers:\ndrag:duration-100 drag:opacity-50 drop:opacity-100" class="mt-16 text-center" />
430
+
431
+ <!-- No local modifiers -->
432
+ <Label id="red" class="mx-2 ml-4 h-32 w-32 rounded-lg bg-red-500 text-center text-xs text-white" text="No local modifiers" />
433
+
434
+ <!-- drag:bg-green-800 drop:bg-green-500 -->
435
+ <Label id="green" class="drag:bg-green-800 drop:bg-green-500 ml-10 h-32 w-32 rounded-lg bg-green-500 text-center text-xs text-white" text="drag:bg-green-800 drop:bg-green-500" />
436
+
437
+ <!-- drag:opacity-25 -->
438
+ <Label id="blue" class="drag:opacity-25 ml-16 h-32 w-32 rounded-lg bg-blue-500 text-center text-xs text-white" text="drag:opacity-25" />
439
+ </Window>
440
+ </Alloy>
441
+ ```
442
+
443
+ ### `draggingType` Property
444
+
445
+ To control how `drag:` and `drop:` modifiers are applied, you can use either the `drag-animate` (default) or `drag-apply` class. The `drag-animate` class will animate the properties, while the `drag-apply` class will apply them immediately.
446
+
447
+ ```css title="utilities.tss"
448
+ /* Component(s): For the Animation Component */
449
+ /* Property(ies): draggingType */
450
+ .drag-apply { draggingType: 'apply' }
451
+ .drag-animate { draggingType: 'animate' }
452
+ ```
453
+
454
+ #### Dragging Type Example
455
+
456
+ In the following example, the `Animation` element sets the global dragging type to `drag-apply`, but the green square overwrites it to `drag-animate`.
457
+
458
+ ```xml title="index.xml"
459
+ <Alloy>
460
+ <Window class="keep-screen-on exit-on-close-false">
461
+ <!-- Global set of modifiers -->
462
+ <Animation id="draggableAnimation" module="purgetss.ui" class="drag-apply drag:duration-500 drag:opacity-50 drop:opacity-100" />
463
+
464
+ <Label text="draggingType Example:\ndrag-apply drag:duration-500 drag:opacity-50 drop:opacity-100" class="mt-16 text-center" />
465
+
466
+ <!-- No local modifiers, will be using the global modifiers -->
467
+ <Label id="red" class="ml-4 h-32 w-32 rounded-lg bg-red-500 text-center text-xs text-white" text="No local modifiers" />
468
+
469
+ <!-- drag-animate drag:bg-green-800 drop:bg-green-500 -->
470
+ <Label id="green" class="drag-animate drag:bg-green-800 drop:bg-green-500 ml-10 h-32 w-32 rounded-lg bg-green-500 text-center text-xs text-white" text="drag-animate drag:bg-green-800 drop:bg-green-500" />
471
+
472
+ <!-- drag:opacity-25 -->
473
+ <Label id="blue" class="drag:opacity-25 ml-16 h-32 w-32 rounded-lg bg-blue-500 text-center text-xs text-white" text="drag:opacity-25" />
474
+ </Window>
475
+ </Alloy>
476
+ ```
477
+
478
+ ### `bounds` Modifier
479
+
480
+ You can set boundaries in which a view can move within its parent view using the `bounds:` modifier.
481
+
482
+ - You can set global boundaries in the Animation object and/or local boundaries for each individual child view.
483
+ - Local values will overwrite any global values.
484
+
485
+ #### Bounds Example 1: Local Bounds
486
+
487
+ The `card` view has a boundary of `m-4` and a bottom boundary of `mb-16`.
488
+
489
+ ```xml title="index.xml"
490
+ <Alloy>
491
+ <Window class="keep-screen-on exit-on-close-false bg-green-50">
492
+ <Animation id="draggableAnimation" module="purgetss.ui" />
493
+
494
+ <View class="mx-6 mb-6 mt-10 h-screen w-screen rounded-lg bg-green-200">
495
+ <View id="card" class="bounds:m-2 bounds:mb-16 mt-8 h-24 w-64 shadow-lg">
496
+ <View id="cardInside" class="w-screen rounded-lg border-2 border-purple-700 bg-white">
497
+ <ImageView id="theImage" class="rounded-16 prevent-default-image m-4 ml-4 h-16 w-16 bg-gray-50" image="https://randomuser.me/api/portraits/women/17.jpg" />
498
+
499
+ <View class="vertical ml-24 w-screen">
500
+ <Label class="ml-0 text-sm font-bold text-gray-800" text="Ms. Jane Doe" />
501
+ <Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
502
+ </View>
503
+ </View>
504
+ </View>
505
+
506
+ <Label class="bg-(#80000000) mx-2 mb-2 h-12 w-screen rounded-lg text-center text-white" text="Some Element..." />
507
+ </View>
508
+ </Window>
509
+ </Alloy>
510
+ ```
511
+
512
+ ```javascript title="index.js"
513
+ $.index.open()
514
+
515
+ $.draggableAnimation.draggable($.card)
516
+ ```
517
+
518
+ #### Bounds Example 2: Global Bounds
519
+
520
+ In this example, the boundaries are set globally in the `draggableAnimation` view. Every card view will use these global values.
521
+
522
+ ```xml title="index.xml"
523
+ <Alloy>
524
+ <Window class="keep-screen-on exit-on-close-false bg-green-50">
525
+ <Animation id="draggableAnimation" module="purgetss.ui" class="bounds:m-2 bounds:mb-16" />
526
+
527
+ <View class="wh-screen mx-6 mb-6 mt-10 rounded-lg bg-green-200">
528
+ <View id="card" class="mt-8 h-24 w-64 shadow-lg">
529
+ <View id="cardInside" class="w-screen rounded-lg border-2 border-purple-700 bg-white">
530
+ <ImageView id="theImage" class="rounded-16 prevent-default-image wh-16 m-4 bg-gray-50" image="https://randomuser.me/api/portraits/women/17.jpg" />
531
+
532
+ <View class="vertical ml-24 w-screen">
533
+ <Label class="ml-0 text-sm font-bold text-gray-800" text="Ms. Jane Doe" />
534
+ <Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
535
+ </View>
536
+ </View>
537
+ </View>
538
+
539
+ <View id="card2" class="mt-40 h-24 w-64 shadow-lg">
540
+ <View id="cardInside" class="w-screen rounded-lg border-2 border-purple-700 bg-white">
541
+ <ImageView id="theImage" class="rounded-16 prevent-default-image wh-16 m-4 bg-gray-50" image="https://randomuser.me/api/portraits/women/21.jpg" />
542
+
543
+ <View class="vertical ml-24 w-screen">
544
+ <Label class="ml-0 text-sm font-bold text-gray-800" text="Ms. Jane Doe" />
545
+ <Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
546
+ </View>
547
+ </View>
548
+ </View>
549
+
550
+ <View id="card3" class="mt-72 h-24 w-64 shadow-lg">
551
+ <View id="cardInside" class="w-screen rounded-lg border-2 border-purple-700 bg-white">
552
+ <ImageView id="theImage" class="rounded-16 prevent-default-image wh-16 m-4 bg-gray-50" image="https://randomuser.me/api/portraits/women/25.jpg" />
553
+
554
+ <View class="vertical ml-24 w-screen">
555
+ <Label class="ml-0 text-sm font-bold text-gray-800" text="Ms. Jane Doe" />
556
+ <Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
557
+ </View>
558
+ </View>
559
+ </View>
560
+
561
+ <Label class="bg-(#80000000) mx-2 mb-2 h-12 w-screen rounded-lg text-center text-white" text="Some Element..." />
562
+ </View>
563
+ </Window>
564
+ </Alloy>
565
+ ```
566
+
567
+ ```javascript title="index.js"
568
+ $.index.open()
569
+
570
+ $.draggableAnimation.draggable([$.card, $.card2, $.card3])
571
+ ```
572
+
573
+ ### `vertical` and `horizontal` Constraints
574
+
575
+ To add a vertical or horizontal constraint to any `dragging` element, set the `vertical-constraint` or `horizontal-constraint` classes on the view.
576
+
577
+ ```css
578
+ /* Component(s): Ti.UI.Animation */
579
+ /* Property(ies): A custom property to use it with the Animation module */
580
+ '.horizontal-constraint': { constraint: 'horizontal' }
581
+ '.vertical-constraint': { constraint: 'vertical' }
582
+ ```
583
+
584
+ #### Constraint Example
585
+
586
+ In this example, the `card` view will move only from side to side.
587
+
588
+ ```xml title="index.xml"
589
+ <Alloy>
590
+ <Window class="keep-screen-on exit-on-close-false">
591
+ <Animation id="draggableAnimation" module="purgetss.ui" />
592
+
593
+ <View id="card" class="horizontal-constraint h-24 w-64 shadow-lg">
594
+ <View id="cardInside" class="w-screen rounded-lg border-2 border-purple-700 bg-white">
595
+ <ImageView id="theImage" class="rounded-16 wh-16 m-4 ml-4" image="https://randomuser.me/api/portraits/women/17.jpg" />
596
+
597
+ <View class="vertical ml-24 w-screen">
598
+ <Label class="ml-0 text-sm font-bold text-gray-800" text="Ms. Jane Doe" />
599
+ <Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
600
+ </View>
601
+ </View>
602
+ </View>
603
+ </Window>
604
+ </Alloy>
605
+ ```
606
+
607
+ ```javascript title="index.js"
608
+ $.index.open()
609
+
610
+ $.draggableAnimation.draggable($.card)
611
+ ```
612
+
613
+ ---
614
+
615
+ ## State Modifiers
616
+
617
+ Define behavior in the `class` attribute:
618
+
619
+ ### `open:` and `close:`
620
+
621
+ Properties for opening/closing phases.
622
+
623
+ ```xml
624
+ <Animation class="close:opacity-0 close:w-28 open:w-11/12 open:opacity-100" />
625
+ ```
626
+
627
+ ### `complete:` Modifier
628
+
629
+ To apply additional properties after an `open` animation is finished, use the `complete` modifier.
630
+
631
+ ```xml
632
+ <Animation class="open:scale-1 complete:bg-(#008800) complete:scale-100" />
633
+ ```
634
+
635
+ :::tip
636
+ Use `complete:` for post-animation state - e.g., setting a background color after a fade-in completes.
637
+ :::
638
+
639
+ #### Complete Example: Wordle Animation
640
+
641
+ In the following code, the `open` animation reduces the children of the `letters` view to a size of 1%. After completion, the `complete` modifier will set the background color to green and the scaling back to 100%.
642
+
643
+ ```xml title="index.xml"
644
+ <Alloy>
645
+ <Window title="App Wordle" class="bg-(#181e2d)">
646
+ <Animation module="purgetss.ui" id="myAnimationReset" class="bg-transparent" />
647
+ <Animation module="purgetss.ui" id="myAnimationOpen" class="open:scale-1 complete:bg-(#008800) complete:scale-100" />
648
+
649
+ <View class="vertical">
650
+ <View id="letters" class="horizontal">
651
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="T" />
652
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="I" />
653
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="T" />
654
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="A" />
655
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="N" />
656
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="I" />
657
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="U" />
658
+ <Label class="wh-10 mx-1 rounded border-white bg-transparent text-center text-white" text="M" />
659
+ </View>
660
+
661
+ <Button title="Animate" class="mt-8" android:onClick="doAnimate" ios:onSingletap="doAnimate" />
662
+ <Button title="Reset" class="mt-4" android:onClick="doReset" ios:onSingletap="doReset" />
663
+ </View>
664
+ </Window>
665
+ </Alloy>
666
+ ```
667
+
668
+ ```javascript title="index.js"
669
+ $.index.open()
670
+
671
+ function doAnimate() {
672
+ $.myAnimationOpen.play($.letters.children)
673
+ }
674
+
675
+ function doReset() {
676
+ $.myAnimationReset.apply($.letters.children)
677
+ }
678
+ ```
679
+
680
+ ### `children:`
681
+
682
+ Applies animation rules globally to ALL children of target View.
683
+
684
+ ```xml
685
+ <Animation class="children:opacity-50 complete:opacity-100" />
686
+
687
+ <View>
688
+ <Label /> <!-- All children affected -->
689
+ <View /> <!-- All children affected -->
690
+ </View>
691
+ ```
692
+
693
+ ### `child:`
694
+
695
+ Targets specific child properties by index (0-based).
696
+
697
+ ```xml
698
+ <Animation class="child:0:bg-red-500 child:1:bg-blue-500" />
699
+
700
+ <View>
701
+ <Label /> <!-- Index 0: Red background -->
702
+ <View /> <!-- Index 1: Blue background -->
703
+ </View>
704
+ ```
705
+
706
+ ---
707
+
708
+ ## Complex UI Elements
709
+
710
+ Here is an example of the Animation module with a more complex UI featuring an animated sidebar and expandable card.
711
+
712
+ :::tip
713
+ To use this example, you'll need to install the FontAwesome fonts in your project by running:
714
+ ```bash
715
+ purgetss icon-library -v=fa
716
+ ```
717
+ :::
718
+
719
+ ```xml title="index.xml"
720
+ <Alloy>
721
+ <Window class="exit-on-close-false portrait bg-purple-700">
722
+ <Animation id="draggableAnimation" module="purgetss.ui" class="bounds:m-4 bounds:mb-20" />
723
+
724
+ <!-- Sidebar -->
725
+ <Animation id="sideBarAnimation" module="purgetss.ui" class="close:w-24 duration-150 open:w-72" />
726
+ <Animation id="sideBarAnimationChevron" module="purgetss.ui" class="close:rotate-0 duration-150 open:rotate-180" />
727
+
728
+ <View id="sideBar" class="ml-2 h-1/2 w-24">
729
+ <View class="vertical ios:shadow-lg mr-8 rounded-lg bg-white" ios:onSingletap="doAction" android:onClick="doAction">
730
+ <View class="grid-flow-row">
731
+ <View class="grid-rows-7 ml-0 w-64">
732
+ <View class="horizontal bg-selected-purple-100 items-center" action="home">
733
+ <Label class="touch-enabled-false fas fa-home ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
734
+ <Label class="touch-enabled-false text-purple-700" text="Home" />
735
+ </View>
736
+ </View>
737
+
738
+ <View class="grid-rows-7 ml-0 w-64">
739
+ <View class="horizontal bg-selected-purple-100 items-center" action="profile">
740
+ <Label class="touch-enabled-false fas fa-user ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
741
+ <Label class="touch-enabled-false text-purple-700" text="Profile" />
742
+ </View>
743
+ </View>
744
+
745
+ <View class="grid-rows-7 ml-0 w-64">
746
+ <View class="horizontal bg-selected-purple-100 items-center" action="messages">
747
+ <Label class="touch-enabled-false fas fa-comment ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
748
+ <Label class="touch-enabled-false text-purple-700" text="Messages" />
749
+ </View>
750
+ </View>
751
+
752
+ <View class="grid-rows-7 ml-0 w-64">
753
+ <View class="horizontal bg-selected-purple-100 items-center" action="help">
754
+ <Label class="touch-enabled-false fas fa-question-circle ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
755
+ <Label class="touch-enabled-false text-purple-700" text="Help" />
756
+ </View>
757
+ </View>
758
+
759
+ <View class="grid-rows-7 ml-0 w-64">
760
+ <View class="horizontal bg-selected-purple-100 items-center" action="settings">
761
+ <Label class="touch-enabled-false fas fa-cog ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
762
+ <Label class="touch-enabled-false text-purple-700" text="Settings" />
763
+ </View>
764
+ </View>
765
+
766
+ <View class="grid-rows-7 ml-0 w-64">
767
+ <View class="horizontal bg-selected-purple-100 items-center" action="password">
768
+ <Label class="touch-enabled-false fas fa-lock ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
769
+ <Label class="touch-enabled-false text-purple-700" text="Password" />
770
+ </View>
771
+ </View>
772
+
773
+ <View class="grid-rows-7 ml-0 w-64">
774
+ <View class="horizontal bg-selected-purple-100 items-center" action="sign-out">
775
+ <Label class="touch-enabled-false fas fa-sign-out-alt ml-0 h-full w-16 border-transparent bg-transparent text-center text-xl text-purple-700" />
776
+ <Label class="touch-enabled-false text-purple-700" text="Sign Out" />
777
+ </View>
778
+ </View>
779
+ </View>
780
+ </View>
781
+
782
+ <Button id="sideBarChevron" class="fas rounded-10 fa-chevron-right mr-1.5 h-10 w-10 border-4 border-purple-700 bg-white text-xl text-purple-700" ios:onSingletap="sideBarClicked" android:onClick="sideBarClicked" />
783
+
784
+ </View>
785
+
786
+ <!-- My Card -->
787
+ <Animation id="myCardAnimation" module="purgetss.ui" class="open:h-(298) close:h-24 duration-150" />
788
+ <Animation id="myCardAnimationChevron" module="purgetss.ui" class="close:rotate-0 duration-150 open:rotate-180" />
789
+
790
+ <View id="myCard" class="mr-6 mt-6 h-24 w-8/12 rounded-lg shadow-lg">
791
+ <View class="vertical rounded-lg bg-white">
792
+ <View class="h-auto w-screen">
793
+ <ImageView class="rounded-16 m-4 ml-4 h-16 w-16" image="https://randomuser.me/api/portraits/women/17.jpg" />
794
+
795
+ <View class="vertical ml-24 h-auto">
796
+ <Label class="ml-0 text-sm font-bold text-gray-800" text="Someone Famous" />
797
+ <Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
798
+ </View>
799
+ </View>
800
+
801
+ <View class="rounded-1 mx-2 h-0.5 w-screen bg-gray-300" />
802
+
803
+ <View class="bubble-parent-false mt-2 h-48 w-screen grid-flow-row" ios:onSingletap="doAction" android:onClick="doAction">
804
+ <View class="ml-0 w-screen grid-rows-5">
805
+ <View class="horizontal bg-selected-purple-100 items-center" action="profile">
806
+ <Label class="touch-enabled-false fas fa-user ml-0 h-full w-14 border-transparent bg-transparent text-center text-xl text-purple-700" />
807
+ <Label class="touch-enabled-false text-sm text-purple-700" text="Edit Profile" />
808
+ </View>
809
+ </View>
810
+
811
+ <View class="ml-0 w-screen grid-rows-5">
812
+ <View class="horizontal bg-selected-purple-100 items-center" action="inbox">
813
+ <Label class="touch-enabled-false fas fa-inbox ml-0 h-full w-14 border-transparent bg-transparent text-center text-xl text-purple-700" />
814
+ <Label class="touch-enabled-false text-sm text-purple-700" text="Inbox" />
815
+ </View>
816
+ </View>
817
+
818
+ <View class="ml-0 w-screen grid-rows-5">
819
+ <View class="horizontal bg-selected-purple-100 items-center" action="settings">
820
+ <Label class="touch-enabled-false fas fa-cog ml-0 h-full w-14 border-transparent bg-transparent text-center text-xl text-purple-700" />
821
+ <Label class="touch-enabled-false text-sm text-purple-700" text="Settings" />
822
+ </View>
823
+ </View>
824
+
825
+ <View class="ml-0 w-screen grid-rows-5">
826
+ <View class="horizontal bg-selected-purple-100 items-center" action="support">
827
+ <Label class="touch-enabled-false fas fa-question-circle ml-0 h-full w-14 border-transparent bg-transparent text-center text-xl text-purple-700" />
828
+ <Label class="touch-enabled-false text-sm text-purple-700" text="Support" />
829
+ </View>
830
+ </View>
831
+
832
+ <View class="ml-0 w-screen grid-rows-5">
833
+ <View class="horizontal bg-selected-purple-100 items-center" action="sign-out">
834
+ <Label class="touch-enabled-false fas fa-sign-out-alt ml-0 h-full w-14 border-transparent bg-transparent text-center text-xl text-purple-700" />
835
+ <Label class="touch-enabled-false text-sm text-purple-700" text="Sign Out" />
836
+ </View>
837
+ </View>
838
+ </View>
839
+ </View>
840
+
841
+ <View class="rounded-tl-br-md wh-8 bubble-parent-false mb-0 mr-0 bg-blue-400">
842
+ <Button id="myCardChevron" class="fas fa-chevron-down border-transparent bg-transparent text-white" ios:onSingletap="myCardClicked" android:onClick="myCardClicked" />
843
+ </View>
844
+ </View>
845
+
846
+ <Label id="action" class="mx-4 mb-6 h-10 w-screen rounded-lg bg-purple-800 text-sm font-bold text-purple-50" />
847
+ </Window>
848
+ </Alloy>
849
+ ```
850
+
851
+ ```javascript title="index.js"
852
+ $.index.open()
853
+
854
+ $.draggableAnimation.draggable($.myCard)
855
+
856
+ function sideBarClicked() {
857
+ $.sideBarAnimation.play($.sideBar)
858
+ $.sideBarAnimationChevron.play($.sideBarChevron)
859
+ }
860
+
861
+ function myCardClicked() {
862
+ $.myCardAnimation.play($.myCard)
863
+ $.myCardAnimationChevron.play($.myCardChevron)
864
+ }
865
+
866
+ function doAction(event) {
867
+ if (event.source.action) {
868
+ $.action.text = ` Action: ${event.source.action}`
869
+ }
870
+ }
871
+ ```
872
+
873
+ ---
874
+
875
+ ## Available Utilities
876
+
877
+ Along with the regular utilities like color, widths, and heights, you can set the following utilities on your animations:
878
+
879
+ ### anchorPoint
880
+
881
+ Coordinate of the view about which to pivot an animation.
882
+
883
+ This is specified as a dictionary object with x and y properties, where `{x: 0.5, y: 0.5}` represents the center of whatever is being rotated.
884
+
885
+ **Default:** `(0.5, 0.5)`
886
+
887
+ ```css
888
+ /* Property(ies): anchorPoint */
889
+ /* Component(s): Ti.UI.Animation, Ti.UI.View */
890
+ '.origin-center': { anchorPoint: { x: 0.5, y: 0.5 } }
891
+ '.origin-top': { anchorPoint: { x: 0.5, y: 0 } }
892
+ '.origin-top-right': { anchorPoint: { x: 1, y: 0 } }
893
+ '.origin-right': { anchorPoint: { x: 0.5, y: 1 } }
894
+ '.origin-bottom-right': { anchorPoint: { x: 1, y: 1 } }
895
+ '.origin-bottom': { anchorPoint: { x: 0.5, y: 1 } }
896
+ '.origin-bottom-left': { anchorPoint: { x: 0, y: 1 } }
897
+ '.origin-left': { anchorPoint: { x: 0, y: 0.5 } }
898
+ '.origin-top-left': { anchorPoint: { x: 0, y: 0 } }
899
+
900
+ /* anchor-point-{position} variant */
901
+ '.anchor-point-center': { anchorPoint: { x: 0.5, y: 0.5 } }
902
+ '.anchor-point-top': { anchorPoint: { x: 0.5, y: 0 } }
903
+ '.anchor-point-top-right': { anchorPoint: { x: 1, y: 0 } }
904
+ '.anchor-point-right': { anchorPoint: { x: 0.5, y: 1 } }
905
+ '.anchor-point-bottom-right': { anchorPoint: { x: 1, y: 1 } }
906
+ '.anchor-point-bottom': { anchorPoint: { x: 0.5, y: 1 } }
907
+ '.anchor-point-bottom-left': { anchorPoint: { x: 0, y: 1 } }
908
+ '.anchor-point-left': { anchorPoint: { x: 0, y: 0.5 } }
909
+ '.anchor-point-top-left': { anchorPoint: { x: 0, y: 0 } }
910
+ ```
911
+
912
+ ### autoreverse
913
+
914
+ Specifies if the animation should be replayed in reverse upon completion.
915
+
916
+ **Default:** `false`
917
+
918
+ ```css
919
+ /* Property: autoreverse */
920
+ /* Description: Specifies if the animation should be replayed in reverse upon completion. */
921
+ /* Component(s): Ti.UI.Animation */
922
+ '.autoreverse': { autoreverse: true }
923
+ '.autoreverse-false': { autoreverse: false }
924
+ ```
925
+
926
+ ### curve
927
+
928
+ Animation curve or easing function to apply to the animation.
929
+
930
+ This API can be assigned the following constants:
931
+
932
+ ```css
933
+ /* Property: curve */
934
+ /* Description: Animation curve or easing function to apply to the animation. */
935
+ /* Component(s): Ti.UI.Animation */
936
+ '.curve-animation-ease-in': { curve: Ti.UI.ANIMATION_CURVE_EASE_IN }
937
+ '.curve-animation-ease-in-out': { curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT }
938
+ '.curve-animation-ease-out': { curve: Ti.UI.ANIMATION_CURVE_EASE_OUT }
939
+ '.curve-animation-linear': { curve: Ti.UI.ANIMATION_CURVE_LINEAR }
940
+ ```
941
+
942
+ ### delay
943
+
944
+ Delay, in milliseconds before starting the animation.
945
+
946
+ ```css
947
+ /* Property: delay */
948
+ /* Description: Delay, in milliseconds before starting the animation. */
949
+ /* Component(s): Ti.UI.Animation */
950
+ '.delay-0': { delay: 0 }
951
+ '.delay-25': { delay: 25 }
952
+ '.delay-50': { delay: 50 }
953
+ '.delay-75': { delay: 75 }
954
+ '.delay-100': { delay: 100 }
955
+ '.delay-150': { delay: 150 }
956
+ '.delay-200': { delay: 200 }
957
+ '.delay-250': { delay: 250 }
958
+ '.delay-300': { delay: 300 }
959
+ '.delay-350': { delay: 350 }
960
+ '.delay-400': { delay: 400 }
961
+ '.delay-450': { delay: 450 }
962
+ '.delay-500': { delay: 500 }
963
+ '.delay-600': { delay: 600 }
964
+ '.delay-700': { delay: 700 }
965
+ '.delay-800': { delay: 800 }
966
+ '.delay-900': { delay: 900 }
967
+ '.delay-1000': { delay: 1000 }
968
+ '.delay-2000': { delay: 2000 }
969
+ '.delay-3000': { delay: 3000 }
970
+ '.delay-4000': { delay: 4000 }
971
+ '.delay-5000': { delay: 5000 }
972
+ ```
973
+
974
+ ### duration
975
+
976
+ Duration of the animation, in milliseconds.
977
+
978
+ ```css
979
+ /* Property: duration */
980
+ /* Component(s): Ti.UI.Animation */
981
+ '.duration-0': { duration: 0 }
982
+ '.duration-25': { duration: 25 }
983
+ '.duration-50': { duration: 50 }
984
+ '.duration-75': { duration: 75 }
985
+ '.duration-100': { duration: 100 }
986
+ '.duration-150': { duration: 150 }
987
+ '.duration-200': { duration: 200 }
988
+ '.duration-250': { duration: 250 }
989
+ '.duration-300': { duration: 300 }
990
+ '.duration-350': { duration: 350 }
991
+ '.duration-400': { duration: 400 }
992
+ '.duration-450': { duration: 450 }
993
+ '.duration-500': { duration: 500 }
994
+ '.duration-600': { duration: 600 }
995
+ '.duration-700': { duration: 700 }
996
+ '.duration-800': { duration: 800 }
997
+ '.duration-900': { duration: 900 }
998
+ '.duration-1000': { duration: 1000 }
999
+ '.duration-2000': { duration: 2000 }
1000
+ '.duration-3000': { duration: 3000 }
1001
+ '.duration-4000': { duration: 4000 }
1002
+ '.duration-5000': { duration: 5000 }
1003
+ ```
1004
+
1005
+ ### repeat
1006
+
1007
+ Number of times the animation should be performed.
1008
+
1009
+ If `autoreverse` is true, then one repeat of the animation consists of the animation being played once forward and once backward.
1010
+
1011
+ ```css
1012
+ /* Property: repeat */
1013
+ /* Component(s): Ti.UI.Animation */
1014
+ '.repeat-0': { repeat: 0 }
1015
+ '.repeat-1': { repeat: 1 }
1016
+ '.repeat-2': { repeat: 2 }
1017
+ '.repeat-3': { repeat: 3 }
1018
+ '.repeat-4': { repeat: 4 }
1019
+ '.repeat-5': { repeat: 5 }
1020
+ '.repeat-6': { repeat: 6 }
1021
+ '.repeat-7': { repeat: 7 }
1022
+ '.repeat-8': { repeat: 8 }
1023
+ '.repeat-9': { repeat: 9 }
1024
+ '.repeat-10': { repeat: 10 }
1025
+ '.repeat-11': { repeat: 11 }
1026
+ '.repeat-12': { repeat: 12 }
1027
+ ```
1028
+
1029
+ ### rotate
1030
+
1031
+ Utility to specify the amount of rotation.
1032
+
1033
+ This is specified as the rotation angle in degrees.
1034
+
1035
+ **Default:** `No rotation.`
1036
+
1037
+ ```css
1038
+ /* Property: rotate */
1039
+ /* Component(s): MatrixCreationDict, Matrix2DCreationDict */
1040
+ '.rotate-0': { rotate: 0 }
1041
+ '.rotate-1': { rotate: 1 }
1042
+ '.rotate-2': { rotate: 2 }
1043
+ '.rotate-3': { rotate: 3 }
1044
+ '.rotate-6': { rotate: 6 }
1045
+ '.rotate-12': { rotate: 12 }
1046
+ '.rotate-45': { rotate: 45 }
1047
+ '.rotate-90': { rotate: 90 }
1048
+ '.rotate-180': { rotate: 180 }
1049
+
1050
+ /* Property(ies): rotate ( Negative values ) */
1051
+ /* Component(s): For the Animation Component */
1052
+ '.-rotate-0': { rotate: 0 }
1053
+ '.-rotate-1': { rotate: -1 }
1054
+ '.-rotate-2': { rotate: -2 }
1055
+ '.-rotate-3': { rotate: -3 }
1056
+ '.-rotate-6': { rotate: -6 }
1057
+ '.-rotate-12': { rotate: -12 }
1058
+ '.-rotate-45': { rotate: -45 }
1059
+ '.-rotate-90': { rotate: -90 }
1060
+ '.-rotate-180': { rotate: -180 }
1061
+ ```
1062
+
1063
+ ### scale
1064
+
1065
+ Scales the matrix by the specified scaling factor. The same scaling factor is used for both horizontal and vertical scaling.
1066
+
1067
+ **Default:** `1`
1068
+
1069
+ ```css
1070
+ /* Property: scale */
1071
+ /* Component(s): MatrixCreationDict, Matrix2DCreationDict, Matrix3DCreationDict */
1072
+ '.scale-0': { scale: 0 }
1073
+ '.scale-1': { scale: 0.01 }
1074
+ '.scale-5': { scale: 0.05 }
1075
+ '.scale-10': { scale: 0.10 }
1076
+ '.scale-25': { scale: 0.25 }
1077
+ '.scale-50': { scale: 0.5 }
1078
+ '.scale-75': { scale: 0.75 }
1079
+ '.scale-90': { scale: 0.9 }
1080
+ '.scale-95': { scale: 0.95 }
1081
+ '.scale-100': { scale: 1 }
1082
+ '.scale-105': { scale: 1.05 }
1083
+ '.scale-110': { scale: 1.1 }
1084
+ '.scale-125': { scale: 1.25 }
1085
+ '.scale-150': { scale: 1.5 }
1086
+ ```
1087
+
1088
+ ### drag-apply, drag-animate
1089
+
1090
+ To control how `drag:` and `drop:` modifiers are applied, you can use either the `drag-animate` (*default*) or `drag-apply` class. The `drag-animate` class will animate the properties, while the `drag-apply` class will apply them immediately.
1091
+
1092
+ ```css
1093
+ /* Property(ies): draggingType */
1094
+ /* Component(s): For the Animation Component */
1095
+ '.drag-apply': { draggingType: 'apply' }
1096
+ '.drag-animate': { draggingType: 'animate' }
1097
+ ```
1098
+
1099
+ ### opacity-to-*, toggle-visible
1100
+
1101
+ A special utility to automatically animate the opacity of a view and toggle its visibility.
1102
+
1103
+ ```css
1104
+ /* Property(ies): toggle - For the Animation module */
1105
+ /* Component(s): Animation */
1106
+ '.opacity-to-0': { opacity: 1, animationProperties: { open: { opacity: 0 }, close: { opacity: 1 } } }
1107
+ '.opacity-to-100': { opacity: 0, animationProperties: { open: { opacity: 1 }, close: { opacity: 0 } } }
1108
+ '.toggle-visible': { animationProperties: { open: { visible: true }, close: { visible: false } } }
1109
+ ```
1110
+
1111
+ ### zoom-in-*, zoom-out-*
1112
+
1113
+ A special utility to automatically animate the zoom-in and zoom-out of a view.
1114
+
1115
+ It will initially set the view's scale to the specified value and then animate it to 1.
1116
+
1117
+ ```css
1118
+ /* Property(ies): animationProperties - scales the view (in or out) and resets it to 100% when the animation completes */
1119
+ /* Component(s): Animation */
1120
+ '.zoom-in-0': { animationProperties: { open: { scale: 0 }, complete: { scale: 1 } } }
1121
+ '.zoom-in-1': { animationProperties: { open: { scale: 0.01 }, complete: { scale: 1 } } }
1122
+ '.zoom-in-5': { animationProperties: { open: { scale: 0.05 }, complete: { scale: 1 } } }
1123
+ '.zoom-in-10': { animationProperties: { open: { scale: 0.10 }, complete: { scale: 1 } } }
1124
+ '.zoom-in-25': { animationProperties: { open: { scale: 0.25 }, complete: { scale: 1 } } }
1125
+ '.zoom-in-50': { animationProperties: { open: { scale: 0.5 }, complete: { scale: 1 } } }
1126
+ '.zoom-in-75': { animationProperties: { open: { scale: 0.75 }, complete: { scale: 1 } } }
1127
+ '.zoom-in-90': { animationProperties: { open: { scale: 0.9 }, complete: { scale: 1 } } }
1128
+ '.zoom-in-95': { animationProperties: { open: { scale: 0.95 }, complete: { scale: 1 } } }
1129
+ '.zoom-in-100': { animationProperties: { open: { scale: 1 }, complete: { scale: 1 } } }
1130
+ '.zoom-in-105': { animationProperties: { open: { scale: 1.05 }, complete: { scale: 1 } } }
1131
+ '.zoom-in-110': { animationProperties: { open: { scale: 1.1 }, complete: { scale: 1 } } }
1132
+ '.zoom-in-125': { animationProperties: { open: { scale: 1.25 }, complete: { scale: 1 } } }
1133
+ '.zoom-in-150': { animationProperties: { open: { scale: 1.5 }, complete: { scale: 1 } } }
1134
+ '.zoom-out-0': { animationProperties: { close: { scale: 0 }, complete: { scale: 1 } } }
1135
+ '.zoom-out-1': { animationProperties: { close: { scale: 0.01 }, complete: { scale: 1 } } }
1136
+ '.zoom-out-5': { animationProperties: { close: { scale: 0.05 }, complete: { scale: 1 } } }
1137
+ '.zoom-out-10': { animationProperties: { close: { scale: 0.10 }, complete: { scale: 1 } } }
1138
+ '.zoom-out-25': { animationProperties: { close: { scale: 0.25 }, complete: { scale: 1 } } }
1139
+ '.zoom-out-50': { animationProperties: { close: { scale: 0.5 }, complete: { scale: 1 } } }
1140
+ '.zoom-out-75': { animationProperties: { close: { scale: 0.75 }, complete: { scale: 1 } } }
1141
+ '.zoom-out-90': { animationProperties: { close: { scale: 0.9 }, complete: { scale: 1 } } }
1142
+ '.zoom-out-95': { animationProperties: { close: { scale: 0.95 }, complete: { scale: 1 } } }
1143
+ '.zoom-out-100': { animationProperties: { close: { scale: 1 }, complete: { scale: 1 } } }
1144
+ '.zoom-out-105': { animationProperties: { close: { scale: 1.05 }, complete: { scale: 1 } } }
1145
+ '.zoom-out-110': { animationProperties: { close: { scale: 1.1 }, complete: { scale: 1 } } }
1146
+ '.zoom-out-125': { animationProperties: { close: { scale: 1.25 }, complete: { scale: 1 } } }
1147
+ '.zoom-out-150': { animationProperties: { close: { scale: 1.5 }, complete: { scale: 1 } } }
1148
+ ```
1149
+
1150
+ ---
1151
+
1152
+ ## Best Practices
1153
+
1154
+ ### 1. Use Semantic IDs
1155
+
1156
+ ```xml
1157
+ <!-- Good -->
1158
+ <Animation id="fadeIn" class="close:opacity-0 open:opacity-100" />
1159
+ <Animation id="expandCard" class="close:h-20 open:h-40" />
1160
+
1161
+ <!-- Avoid -->
1162
+ <Animation id="anim1" class="..." />
1163
+ <Animation id="anim2" class="..." />
1164
+ ```
1165
+
1166
+ ### 2. Combine Methods for Sequences
1167
+
1168
+ ```javascript
1169
+ function playSequence() {
1170
+ $.fadeIn.play($.view1, () => {
1171
+ $.expandCard.play($.view2)
1172
+ })
1173
+ }
1174
+ ```
1175
+
1176
+ ### 3. Use `complete:` for Post-Animation State
1177
+
1178
+ ```xml
1179
+ <Animation class="complete:scale-100 duration-200 open:scale-110" />
1180
+ ```
1181
+
1182
+ ### 4. Leverage `children:` for Batch Animations
1183
+
1184
+ ```xml
1185
+ <Animation class="children:opacity-0 complete:opacity-100 duration-300" />
1186
+
1187
+ <View>
1188
+ <Label /> <!-- All fade in together -->
1189
+ <View /> <!-- All fade in together -->
1190
+ </View>
1191
+ ```
1192
+
1193
+ ### 5. Use `toggle` for UI States
1194
+
1195
+ ```javascript
1196
+ function toggleMenu() {
1197
+ $.menuAnimation.toggle($.menuView)
1198
+ }
1199
+ ```
1200
+
1201
+ ---
1202
+
1203
+ ## Common Patterns
1204
+
1205
+ ### Modal Fade In/Out
1206
+
1207
+ ```xml
1208
+ <Animation id="modalFade" class="close:opacity-0 open:opacity-100" />
1209
+
1210
+ <View id="modalView" class="opacity-0">
1211
+ <!-- Modal content -->
1212
+ </View>
1213
+ ```
1214
+
1215
+ ```javascript
1216
+ // Open
1217
+ $.modalFade.open($.modalView)
1218
+
1219
+ // Close
1220
+ $.modalFade.close($.modalView)
1221
+ ```
1222
+
1223
+ ### Slide Up/Down
1224
+
1225
+ ```xml
1226
+ <Animation id="slideUp" class="close:translate-y-full open:translate-y-0" />
1227
+ ```
1228
+
1229
+ ### Scale on Touch
1230
+
1231
+ ```xml
1232
+ <Animation id="cardPop" class="duration-200 open:scale-105" />
1233
+
1234
+ <View class="w-screen bg-white shadow" onTouchstart="onCardTouch">
1235
+ <!-- Card content -->
1236
+ </View>
1237
+ ```
1238
+
1239
+ ```javascript
1240
+ function onCardTouch(e) {
1241
+ $.cardPop.play(e.source)
1242
+ }
1243
+ ```
1244
+
1245
+ ### Draggable Element with Bounds
1246
+
1247
+ ```xml
1248
+ <Animation id="draggableCard" class="bounds:m-8" />
1249
+
1250
+ <View id="card" class="h-32 w-64 bg-white shadow" />
1251
+ ```
1252
+
1253
+ ```javascript
1254
+ $.draggableCard.draggable($.card)
1255
+ ```
1256
+
1257
+ ---
1258
+
1259
+ ## Animation Properties Summary
1260
+
1261
+ ### State Modifiers
1262
+
1263
+ | Modifier | Purpose | Example |
1264
+ | ----------- | ------------------------ | ------------------------------ |
1265
+ | `open:` | Opening state properties | `open:opacity-100 open:w-full` |
1266
+ | `close:` | Closing state properties | `close:opacity-0 close:h-0` |
1267
+ | `complete:` | Post-open state | `complete:bg-green-500` |
1268
+ | `children:` | All children affected | `children:opacity-50` |
1269
+ | `child:{n}` | Specific child by index | `child:0:bg-red-500` |
1270
+ | `drag:` | Dragging state | `drag:opacity-50` |
1271
+ | `drop:` | Dropped state | `drop:scale-95` |
1272
+ | `bounds:` | Movement limits | `bounds:m-4` |
1273
+
1274
+ ### Timing and Special Classes
1275
+
1276
+ | Utility | Purpose | Example |
1277
+ | --------------------------------------------------- | ----------------------------- | ---------------------------------- |
1278
+ | `delay-{ms}` | Delay before animation starts | `delay-300` |
1279
+ | `duration-{ms}` | Duration of animation | `duration-500` |
1280
+ | `ease-in`, `ease-out`, `ease-linear`, `ease-in-out` | Animation curve | `ease-out` |
1281
+ | `rotate-{degrees}` | Rotation | `rotate-45`, `-rotate-90` |
1282
+ | `scale-{0-150}` | Scale | `scale-110` |
1283
+ | `repeat-{n}` | Repetitions | `repeat-3` |
1284
+ | `autoreverse` | Auto-reverse on completion | `autoreverse` |
1285
+ | `zoom-in-{0-150}` | Zoom in effect | `zoom-in-125` |
1286
+ | `zoom-out-{0-150}` | Zoom out effect | `zoom-out-75` |
1287
+ | `drag-apply` | Instant drag properties | `drag-apply` |
1288
+ | `drag-animate` | Animated drag properties | `drag-animate` |
1289
+ | `horizontal-constraint` | Horizontal movement only | `horizontal-constraint` |
1290
+ | `vertical-constraint` | Vertical movement only | `vertical-constraint` |
1291
+ | `opacity-to-0` | Fade out | `opacity-to-0` |
1292
+ | `opacity-to-100` | Fade in | `opacity-to-100` |
1293
+ | `toggle-visible` | Visibility toggle | `toggle-visible` |
1294
+ | `origin-*` | Anchor point | `origin-center`, `origin-top-left` |