@maccesar/titools 2.2.12 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -713
- package/bin/titools.js +1 -1
- package/lib/commands/update.js +5 -6
- package/lib/config.js +1 -0
- package/lib/downloader.js +10 -0
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +46 -48
- package/skills/alloy-guides/references/CONTROLLERS.md +4 -6
- package/skills/alloy-guides/references/MODELS.md +340 -184
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +3 -4
- package/skills/alloy-guides/references/VIEWS_STYLES.md +44 -46
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +4 -5
- package/skills/alloy-guides/references/VIEWS_XML.md +51 -17
- package/skills/alloy-guides/references/WIDGETS.md +1 -1
- package/skills/alloy-howtos/SKILL.md +12 -13
- package/skills/alloy-howtos/references/cli_reference.md +40 -41
- package/skills/alloy-howtos/references/samples.md +3 -4
- package/skills/purgetss/SKILL.md +369 -356
- package/skills/purgetss/references/EXAMPLES.md +24 -25
- package/skills/purgetss/references/animation-advanced.md +555 -0
- package/skills/purgetss/references/animation-system.md +395 -995
- package/skills/purgetss/references/apply-directive.md +111 -141
- package/skills/purgetss/references/arbitrary-values.md +206 -480
- package/skills/purgetss/references/class-categories.md +277 -0
- package/skills/purgetss/references/class-index.md +1 -420
- package/skills/purgetss/references/cli-commands.md +446 -556
- package/skills/purgetss/references/configurable-properties.md +163 -599
- package/skills/purgetss/references/custom-rules.md +33 -76
- package/skills/purgetss/references/customization-deep-dive.md +319 -518
- package/skills/purgetss/references/dynamic-component-creation.md +33 -37
- package/skills/purgetss/references/grid-layout.md +42 -371
- package/skills/purgetss/references/icon-fonts.md +82 -475
- package/skills/purgetss/references/installation-setup.md +159 -331
- package/skills/purgetss/references/migration-guide.md +54 -109
- package/skills/purgetss/references/opacity-modifier.md +25 -222
- package/skills/purgetss/references/performance-tips.md +2 -2
- package/skills/purgetss/references/platform-modifiers.md +21 -407
- package/skills/purgetss/references/tikit-components.md +237 -104
- package/skills/purgetss/references/titanium-resets.md +20 -21
- package/skills/purgetss/references/ui-ux-design.md +171 -1702
- package/skills/ti-api/SKILL.md +109 -0
- package/skills/ti-api/references/api-android.md +675 -0
- package/skills/ti-api/references/api-app-platform.md +636 -0
- package/skills/ti-api/references/api-core.md +764 -0
- package/skills/ti-api/references/api-data-network.md +641 -0
- package/skills/ti-api/references/api-media.md +655 -0
- package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
- package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
- package/skills/ti-api/references/api-modules-map.md +632 -0
- package/skills/ti-api/references/api-modules-nfc.md +725 -0
- package/skills/ti-api/references/api-modules-social-misc.md +526 -0
- package/skills/ti-api/references/api-services.md +700 -0
- package/skills/ti-api/references/api-ui-android.md +499 -0
- package/skills/ti-api/references/api-ui-extras.md +702 -0
- package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
- package/skills/ti-api/references/api-ui-ios.md +756 -0
- package/skills/ti-api/references/api-ui-lists.md +581 -0
- package/skills/ti-api/references/api-ui-text-input.md +607 -0
- package/skills/ti-api/references/api-ui-views.md +572 -0
- package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
- package/skills/ti-api/references/api-xml-global.md +743 -0
- package/skills/ti-expert/SKILL.md +46 -45
- package/skills/ti-expert/references/adaptive-layouts.md +414 -0
- package/skills/ti-expert/references/alloy-builtins.md +16 -20
- package/skills/ti-expert/references/alloy-structure.md +40 -42
- package/skills/ti-expert/references/anti-patterns.md +34 -0
- package/skills/ti-expert/references/code-conventions.md +5 -3
- package/skills/ti-expert/references/error-handling.md +14 -7
- package/skills/ti-expert/references/examples.md +4 -2
- package/skills/ti-expert/references/performance-optimization.md +26 -24
- package/skills/ti-expert/references/security-device.md +17 -14
- package/skills/ti-expert/references/security-fundamentals.md +60 -101
- package/skills/ti-expert/references/state-management.md +15 -14
- package/skills/ti-expert/references/testing-e2e-ci.md +30 -21
- package/skills/ti-expert/references/theming.md +12 -20
- package/skills/ti-guides/SKILL.md +13 -17
- package/skills/ti-guides/references/advanced-data-and-images.md +30 -10
- package/skills/ti-guides/references/application-frameworks.md +3 -3
- package/skills/ti-guides/references/coding-best-practices.md +31 -2
- package/skills/ti-guides/references/commonjs-advanced.md +46 -4
- package/skills/ti-guides/references/hello-world.md +9 -13
- package/skills/ti-guides/references/hyperloop-native-access.md +4 -1
- package/skills/ti-guides/references/javascript-primer.md +13 -5
- package/skills/ti-guides/references/resources.md +0 -2
- package/skills/ti-guides/references/style-and-conventions.md +1 -0
- package/skills/ti-guides/references/tiapp-config.md +0 -32
- package/skills/ti-howtos/SKILL.md +43 -45
- package/skills/ti-howtos/references/buffer-codec-streams.md +25 -3
- package/skills/ti-howtos/references/debugging-profiling.md +14 -25
- package/skills/ti-howtos/references/google-maps-v2.md +3 -3
- package/skills/ti-howtos/references/ios-map-kit.md +8 -1
- package/skills/ti-howtos/references/notification-services.md +0 -1
- package/skills/ti-howtos/references/webpack-build-pipeline.md +3 -0
- package/skills/ti-ui/SKILL.md +47 -49
- package/skills/ti-ui/references/application-structures.md +3 -2
- package/skills/ti-ui/references/orientation.md +17 -9
- package/skills/ti-ui/references/platform-ui-ios.md +63 -0
- package/skills/ti-ui/references/scrolling-views.md +39 -0
|
@@ -4,9 +4,8 @@ Complete examples of common patterns with anti-patterns and correct implementati
|
|
|
4
4
|
|
|
5
5
|
## Titanium Layout Patterns
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
Titanium does NOT support CSS Flexbox. All examples use `horizontal`, `vertical`, or `composite` layouts.
|
|
9
|
-
:::
|
|
7
|
+
> **🚨 NO FLEXBOX IN TITANIUM**
|
|
8
|
+
> Titanium does NOT support CSS Flexbox. All examples use `horizontal`, `vertical`, or `composite` layouts.
|
|
10
9
|
|
|
11
10
|
### Horizontal Row with Space Between
|
|
12
11
|
|
|
@@ -99,13 +98,13 @@ Titanium does NOT support CSS Flexbox. All examples use `horizontal`, `vertical`
|
|
|
99
98
|
|
|
100
99
|
### Available Layout Classes
|
|
101
100
|
|
|
102
|
-
| Class
|
|
103
|
-
|
|
|
104
|
-
| `horizontal`
|
|
105
|
-
| `vertical`
|
|
106
|
-
| *(no class)*
|
|
107
|
-
| `flow-col`
|
|
108
|
-
| `flow-row`
|
|
101
|
+
| Class | Description | Use Case |
|
|
102
|
+
| --------------- | ------------------------------------ | ------------------------------ |
|
|
103
|
+
| `horizontal` | Children arranged left to right | Rows of buttons, form fields |
|
|
104
|
+
| `vertical` | Children arranged top to bottom | Stacked content, lists |
|
|
105
|
+
| *(no class)* | Defaults to `composite` | Absolute positioning, overlays |
|
|
106
|
+
| `grid-flow-col` | Horizontal grid flow with 100% width | Special grid layouts |
|
|
107
|
+
| `grid-flow-row` | Vertical grid flow with 100% height | Special grid layouts |
|
|
109
108
|
|
|
110
109
|
---
|
|
111
110
|
|
|
@@ -213,11 +212,11 @@ alloy compile
|
|
|
213
212
|
**✅ CORRECT (Use margins on children instead):**
|
|
214
213
|
```xml
|
|
215
214
|
<View>
|
|
216
|
-
<Label class="m-4" text="Hello" />
|
|
215
|
+
<Label class="m-4 wh-auto" text="Hello" />
|
|
217
216
|
</View>
|
|
218
217
|
```
|
|
219
218
|
|
|
220
|
-
**Why:** Titanium Views don't support padding properties. Use margins on child elements.
|
|
219
|
+
**Why:** Titanium Views don't support padding properties. Use margins on child elements, and add `wh-auto` on `Label`/`Button`/`Switch` (or any `SIZE`-default component) when opposite margins would otherwise trigger Titanium edge pinning.
|
|
221
220
|
|
|
222
221
|
---
|
|
223
222
|
|
|
@@ -321,16 +320,16 @@ alloy compile
|
|
|
321
320
|
|
|
322
321
|
## Quick Reference Table
|
|
323
322
|
|
|
324
|
-
| Anti-Pattern | Why It Fails | Correct Approach
|
|
325
|
-
| --------------------- | ------------------------ |
|
|
326
|
-
| `flex-row` | Flexbox not supported | `horizontal`
|
|
327
|
-
| `flex-col` | Flexbox not supported | `vertical`
|
|
328
|
-
| `justify-*` | Flexbox not supported | Use margins/positioning
|
|
329
|
-
| `items-center` | Flexbox
|
|
330
|
-
| `p-4` on View | No padding on containers | `m-4` on children
|
|
331
|
-
| `w-full` | Percentage-based | `w-screen` (Ti.UI.FILL)
|
|
332
|
-
| `rounded-full` | Needs size suffix | `rounded-full-12`
|
|
333
|
-
| `composite` class | Already default | Omit it
|
|
334
|
-
| `w-[100px]` | Wrong syntax | `w-(100px)`
|
|
335
|
-
| Manual `.tss` | Overwritten by PurgeTSS | Use utility classes
|
|
336
|
-
| `gap` with `%` widths | Total exceeds 100% | Use explicit margins
|
|
323
|
+
| Anti-Pattern | Why It Fails | Correct Approach |
|
|
324
|
+
| --------------------- | ------------------------ | ------------------------ |
|
|
325
|
+
| `flex-row` | Flexbox not supported | `horizontal` |
|
|
326
|
+
| `flex-col` | Flexbox not supported | `vertical` |
|
|
327
|
+
| `justify-*` | Flexbox not supported | Use margins/positioning |
|
|
328
|
+
| `items-center` | Flexbox mental model | Use layout + positioning |
|
|
329
|
+
| `p-4` on View | No padding on containers | `m-4` on children |
|
|
330
|
+
| `w-full` | Percentage-based | `w-screen` (Ti.UI.FILL) |
|
|
331
|
+
| `rounded-full` | Needs size suffix | `rounded-full-12` |
|
|
332
|
+
| `composite` class | Already default | Omit it |
|
|
333
|
+
| `w-[100px]` | Wrong syntax | `w-(100px)` |
|
|
334
|
+
| Manual `.tss` | Overwritten by PurgeTSS | Use utility classes |
|
|
335
|
+
| `gap` with `%` widths | Total exceeds 100% | Use explicit margins |
|
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
# PurgeTSS Animation -- Advanced Reference
|
|
2
|
+
|
|
3
|
+
Property inheritance, timing/utility classes, utility functions, implementation rules, and complex UI examples.
|
|
4
|
+
|
|
5
|
+
For core animation methods (play, toggle, apply, open, close, draggable, undraggable, detectCollisions, sequence, swap, pulse, shake, snapTo, reorder, transition), see [animation-system.md](./animation-system.md).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Property Inheritance from the Animation Object
|
|
10
|
+
|
|
11
|
+
All methods in the Animation module inherit properties from the `<Animation>` object's classes. You configure animation behavior in XML and it applies to every method call.
|
|
12
|
+
|
|
13
|
+
When you declare an Animation object with utility classes:
|
|
14
|
+
|
|
15
|
+
```xml
|
|
16
|
+
<Animation id="myAnim" module="purgetss.ui" class="duration-150 delay-100 curve-animation-ease-out" />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The parsed properties (`duration: 150`, `delay: 100`, `curve: EASE_OUT`) are stored in the internal `args` object. Each method reads from `args` as its default values.
|
|
20
|
+
|
|
21
|
+
### Inheritance Matrix
|
|
22
|
+
|
|
23
|
+
| Property | play/toggle | open/close | apply | sequence | swap | reorder | snapTo | shake | pulse | transition |
|
|
24
|
+
| --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
|
25
|
+
| `duration` | Y | Y | -- | Y | Y | Y | Y | Y (div6) | Y | Y |
|
|
26
|
+
| `delay` | Y | Y | -- | Y | Y | Y | Y | Y | Y | Y |
|
|
27
|
+
| `curve` | Y | Y | -- | Y | Y | Y | Y | fixed | fixed | Y |
|
|
28
|
+
| `autoreverse` | Y | Y | -- | Y | -- | -- | -- | fixed | fixed | -- |
|
|
29
|
+
| `repeat` | Y | Y | -- | Y | -- | -- | -- | fixed | param | -- |
|
|
30
|
+
|
|
31
|
+
**Legend:**
|
|
32
|
+
- **Y** = inherited from Animation object
|
|
33
|
+
- **--** = not applicable to this method
|
|
34
|
+
- **fixed** = uses internal fixed values (`shake`: `autoreverse: true`, `repeat: 3`, `curve: EASE_IN_OUT`; `pulse`: `autoreverse: true`, `curve: EASE_IN_OUT`)
|
|
35
|
+
- **param** = controlled by method parameter (`pulse` `count` sets the repeat value)
|
|
36
|
+
- **(div6)** = `shake` divides the inherited duration by 6 for each oscillation cycle
|
|
37
|
+
|
|
38
|
+
### Fallback Defaults
|
|
39
|
+
|
|
40
|
+
When a property is not set on the Animation object and no explicit parameter is passed:
|
|
41
|
+
|
|
42
|
+
| Property | `swap` / `reorder` / `snapTo` | `shake` |
|
|
43
|
+
| --- | :---: | :---: |
|
|
44
|
+
| `duration` | 200ms | 400ms |
|
|
45
|
+
| `delay` | 0ms | 0ms |
|
|
46
|
+
| `curve` | `EASE_IN_OUT` | `EASE_IN_OUT` (fixed) |
|
|
47
|
+
|
|
48
|
+
### Explicit Parameters Take Precedence
|
|
49
|
+
|
|
50
|
+
An explicit value passed as a method parameter always overrides the inherited value:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// All timing controlled by the Animation object's classes
|
|
54
|
+
$.myAnim.swap($.card1, $.card2)
|
|
55
|
+
$.myAnim.reorder(cards, [2, 0, 1])
|
|
56
|
+
$.myAnim.shake($.errorField, 20)
|
|
57
|
+
$.myAnim.snapTo($.card, targets)
|
|
58
|
+
$.myAnim.transition(views, fanOutLayout)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Timing and Utility Classes
|
|
64
|
+
|
|
65
|
+
### anchorPoint / origin-* Classes
|
|
66
|
+
|
|
67
|
+
Controls the pivot point of the animation. Available as both `origin-*` and `anchor-point-*` variants:
|
|
68
|
+
|
|
69
|
+
| Class | anchorPoint |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| `origin-center` / `anchor-point-center` | `{ x: 0.5, y: 0.5 }` |
|
|
72
|
+
| `origin-top` / `anchor-point-top` | `{ x: 0.5, y: 0 }` |
|
|
73
|
+
| `origin-top-right` / `anchor-point-top-right` | `{ x: 1, y: 0 }` |
|
|
74
|
+
| `origin-right` / `anchor-point-right` | `{ x: 0.5, y: 1 }` |
|
|
75
|
+
| `origin-bottom-right` / `anchor-point-bottom-right` | `{ x: 1, y: 1 }` |
|
|
76
|
+
| `origin-bottom` / `anchor-point-bottom` | `{ x: 0.5, y: 1 }` |
|
|
77
|
+
| `origin-bottom-left` / `anchor-point-bottom-left` | `{ x: 0, y: 1 }` |
|
|
78
|
+
| `origin-left` / `anchor-point-left` | `{ x: 0, y: 0.5 }` |
|
|
79
|
+
| `origin-top-left` / `anchor-point-top-left` | `{ x: 0, y: 0 }` |
|
|
80
|
+
|
|
81
|
+
### autoreverse
|
|
82
|
+
|
|
83
|
+
Whether the animation replays in reverse after completing. Default: `false`.
|
|
84
|
+
|
|
85
|
+
```css
|
|
86
|
+
'.autoreverse': { autoreverse: true }
|
|
87
|
+
'.autoreverse-false': { autoreverse: false }
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Curve Classes
|
|
91
|
+
|
|
92
|
+
```css
|
|
93
|
+
'.curve-animation-ease-in': { curve: Ti.UI.ANIMATION_CURVE_EASE_IN }
|
|
94
|
+
'.curve-animation-ease-in-out': { curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT }
|
|
95
|
+
'.curve-animation-ease-out': { curve: Ti.UI.ANIMATION_CURVE_EASE_OUT }
|
|
96
|
+
'.curve-animation-linear': { curve: Ti.UI.ANIMATION_CURVE_LINEAR }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### delay-*
|
|
100
|
+
|
|
101
|
+
Delay in milliseconds before starting the animation. Range: **0** to **5000ms**.
|
|
102
|
+
|
|
103
|
+
Values: `delay-0`, `delay-25`, `delay-50`, `delay-75`, `delay-100`, `delay-150`, `delay-200`, `delay-250`, `delay-300`, `delay-350`, `delay-400`, `delay-450`, `delay-500`, `delay-600`, `delay-700`, `delay-800`, `delay-900`, `delay-1000`, `delay-2000`, `delay-3000`, `delay-4000`, `delay-5000`.
|
|
104
|
+
|
|
105
|
+
### duration-*
|
|
106
|
+
|
|
107
|
+
Duration of the animation in milliseconds. Range: **0** to **5000ms**.
|
|
108
|
+
|
|
109
|
+
Values: `duration-0`, `duration-25`, `duration-50`, `duration-75`, `duration-100`, `duration-150`, `duration-200`, `duration-250`, `duration-300`, `duration-350`, `duration-400`, `duration-450`, `duration-500`, `duration-600`, `duration-700`, `duration-800`, `duration-900`, `duration-1000`, `duration-2000`, `duration-3000`, `duration-4000`, `duration-5000`.
|
|
110
|
+
|
|
111
|
+
### repeat-*
|
|
112
|
+
|
|
113
|
+
Number of times the animation should run. If `autoreverse` is true, one repeat means the animation plays forward and backward once. Range: **0** to **12**.
|
|
114
|
+
|
|
115
|
+
Values: `repeat-0` through `repeat-12`.
|
|
116
|
+
|
|
117
|
+
### rotate-* and -rotate-*
|
|
118
|
+
|
|
119
|
+
Rotation in degrees. Range: **0** to **180**, positive and negative.
|
|
120
|
+
|
|
121
|
+
```css
|
|
122
|
+
'.rotate-0': { rotate: 0 }
|
|
123
|
+
'.rotate-1': { rotate: 1 }
|
|
124
|
+
'.rotate-2': { rotate: 2 }
|
|
125
|
+
'.rotate-3': { rotate: 3 }
|
|
126
|
+
'.rotate-6': { rotate: 6 }
|
|
127
|
+
'.rotate-12': { rotate: 12 }
|
|
128
|
+
'.rotate-45': { rotate: 45 }
|
|
129
|
+
'.rotate-90': { rotate: 90 }
|
|
130
|
+
'.rotate-180': { rotate: 180 }
|
|
131
|
+
'.-rotate-0': { rotate: 0 }
|
|
132
|
+
'.-rotate-1': { rotate: -1 }
|
|
133
|
+
'.-rotate-2': { rotate: -2 }
|
|
134
|
+
'.-rotate-3': { rotate: -3 }
|
|
135
|
+
'.-rotate-6': { rotate: -6 }
|
|
136
|
+
'.-rotate-12': { rotate: -12 }
|
|
137
|
+
'.-rotate-45': { rotate: -45 }
|
|
138
|
+
'.-rotate-90': { rotate: -90 }
|
|
139
|
+
'.-rotate-180': { rotate: -180 }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### scale-*
|
|
143
|
+
|
|
144
|
+
Scales the matrix by the specified factor. Same value for horizontal and vertical. Default: `1`.
|
|
145
|
+
|
|
146
|
+
```css
|
|
147
|
+
'.scale-0': { scale: 0 }
|
|
148
|
+
'.scale-1': { scale: 0.01 }
|
|
149
|
+
'.scale-5': { scale: 0.05 }
|
|
150
|
+
'.scale-10': { scale: 0.10 }
|
|
151
|
+
'.scale-25': { scale: 0.25 }
|
|
152
|
+
'.scale-50': { scale: 0.5 }
|
|
153
|
+
'.scale-75': { scale: 0.75 }
|
|
154
|
+
'.scale-90': { scale: 0.9 }
|
|
155
|
+
'.scale-95': { scale: 0.95 }
|
|
156
|
+
'.scale-100': { scale: 1 }
|
|
157
|
+
'.scale-105': { scale: 1.05 }
|
|
158
|
+
'.scale-110': { scale: 1.1 }
|
|
159
|
+
'.scale-125': { scale: 1.25 }
|
|
160
|
+
'.scale-150': { scale: 1.5 }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Snap Classes
|
|
164
|
+
|
|
165
|
+
Control how draggable views behave when dropped. All are **off by default**.
|
|
166
|
+
|
|
167
|
+
| Class | TSS | Description |
|
|
168
|
+
| --- | --- | --- |
|
|
169
|
+
| `snap-back` | `{ animationProperties: { snap: { back: true } } }` | Returns to origin when dropped outside target |
|
|
170
|
+
| `snap-back-false` | `{ animationProperties: { snap: { back: false } } }` | Disables snap-back |
|
|
171
|
+
| `snap-center` | `{ animationProperties: { snap: { center: true } } }` | Auto-centers on target |
|
|
172
|
+
| `snap-center-false` | `{ animationProperties: { snap: { center: false } } }` | Disables snap-center |
|
|
173
|
+
| `snap-magnet` | `{ animationProperties: { snap: { magnet: true } } }` | (Planned) Magnetic attraction |
|
|
174
|
+
| `snap-magnet-false` | `{ animationProperties: { snap: { magnet: false } } }` | Disables snap-magnet |
|
|
175
|
+
|
|
176
|
+
### keep-z-index
|
|
177
|
+
|
|
178
|
+
Prevents the drag system from auto-promoting the dragged view's z-index. Useful when using `transition` presets where z-order is part of the layout.
|
|
179
|
+
|
|
180
|
+
```css
|
|
181
|
+
'.keep-z-index': { animationProperties: { keepZIndex: true } }
|
|
182
|
+
'.keep-z-index-false': { animationProperties: { keepZIndex: false } }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Drag Type
|
|
186
|
+
|
|
187
|
+
```css
|
|
188
|
+
'.drag-apply': { draggingType: 'apply' }
|
|
189
|
+
'.drag-animate': { draggingType: 'animate' }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Opacity and Visibility Utilities
|
|
193
|
+
|
|
194
|
+
```css
|
|
195
|
+
'.opacity-to-0': { opacity: 1, animationProperties: { open: { opacity: 0 }, close: { opacity: 1 } } }
|
|
196
|
+
'.opacity-to-100': { opacity: 0, animationProperties: { open: { opacity: 1 }, close: { opacity: 0 } } }
|
|
197
|
+
'.toggle-visible': { animationProperties: { open: { visible: true }, close: { visible: false } } }
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### zoom-in-* / zoom-out-*
|
|
201
|
+
|
|
202
|
+
Animates zoom in and zoom out. Sets the View's scale to the specified value, then animates it back to 1. Range: **0** to **150**.
|
|
203
|
+
|
|
204
|
+
```css
|
|
205
|
+
'.zoom-in-0': { animationProperties: { open: { scale: 0 }, complete: { scale: 1 } } }
|
|
206
|
+
'.zoom-in-50': { animationProperties: { open: { scale: 0.5 }, complete: { scale: 1 } } }
|
|
207
|
+
'.zoom-in-95': { animationProperties: { open: { scale: 0.95 }, complete: { scale: 1 } } }
|
|
208
|
+
'.zoom-in-110': { animationProperties: { open: { scale: 1.1 }, complete: { scale: 1 } } }
|
|
209
|
+
'.zoom-out-0': { animationProperties: { close: { scale: 0 }, complete: { scale: 1 } } }
|
|
210
|
+
'.zoom-out-50': { animationProperties: { close: { scale: 0.5 }, complete: { scale: 1 } } }
|
|
211
|
+
'.zoom-out-95': { animationProperties: { close: { scale: 0.95 }, complete: { scale: 1 } } }
|
|
212
|
+
'.zoom-out-110': { animationProperties: { close: { scale: 1.1 }, complete: { scale: 1 } } }
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Full range: `zoom-in-0`, `zoom-in-1`, `zoom-in-5`, `zoom-in-10`, `zoom-in-25`, `zoom-in-50`, `zoom-in-75`, `zoom-in-90`, `zoom-in-95`, `zoom-in-100`, `zoom-in-105`, `zoom-in-110`, `zoom-in-125`, `zoom-in-150` (and same for `zoom-out-*`).
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Utility Functions
|
|
220
|
+
|
|
221
|
+
The module exports helper functions alongside the Animation component:
|
|
222
|
+
|
|
223
|
+
### deviceInfo()
|
|
224
|
+
|
|
225
|
+
Logs detailed platform and display information to the console. Works in both Alloy and Classic Titanium projects.
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
const { deviceInfo } = require('purgetss.ui')
|
|
229
|
+
deviceInfo()
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### saveComponent({ source, directory })
|
|
233
|
+
|
|
234
|
+
Saves a snapshot of a view as a PNG to the photo gallery.
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
const { saveComponent } = require('purgetss.ui')
|
|
238
|
+
saveComponent({ source: $.myView, directory: 'screenshots' })
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### createAnimation(args)
|
|
242
|
+
|
|
243
|
+
Factory function to create Animation objects programmatically.
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
const { createAnimation } = require('purgetss.ui')
|
|
247
|
+
const anim = createAnimation({ duration: 300, curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT })
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Implementation Rules
|
|
253
|
+
|
|
254
|
+
Rules that every method in the Animation module must follow. They keep behavior consistent with the declarative model of PurgeTSS.
|
|
255
|
+
|
|
256
|
+
### Rule 1: Inherit from the `<Animation />` object via `...args`
|
|
257
|
+
|
|
258
|
+
Every method MUST inherit all properties from the Animation object by spreading `args`. Never cherry-pick individual properties.
|
|
259
|
+
|
|
260
|
+
The `<Animation />` object is the single source of truth for animation behavior. When a developer declares:
|
|
261
|
+
|
|
262
|
+
```xml
|
|
263
|
+
<Animation id="myAnim" module="purgetss.ui" class="curve-animation-ease-out opacity-50 delay-100 duration-300" />
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Every property -- timing AND visual -- is available in `args` and MUST be inherited by all methods.
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
// CORRECT -- inherits everything, method-specific props override
|
|
270
|
+
view.animate({ ...args, left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D() })
|
|
271
|
+
|
|
272
|
+
// WRONG -- cherry-picks individual properties, breaks if new ones are added
|
|
273
|
+
view.animate({ duration: args.duration, delay: args.delay, left: destLeft, top: destTop })
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
This is the same pattern used by the core `playView` function:
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
const animation = Ti.UI.createAnimation(args)
|
|
280
|
+
view.animate(animation)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
If a developer adds `opacity-50` to their `<Animation>`, they expect ALL methods to animate opacity, not just `play`.
|
|
284
|
+
|
|
285
|
+
### Rule 2: Override by position, not by exclusion
|
|
286
|
+
|
|
287
|
+
If a method needs fixed values for specific properties, they go AFTER `...args` to override. Never filter or exclude properties from args.
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
// CORRECT -- shake: inherits everything, then overrides what it needs
|
|
291
|
+
view.animate({
|
|
292
|
+
...args,
|
|
293
|
+
transform: Ti.UI.createMatrix2D().translate(intensity, 0),
|
|
294
|
+
duration: Math.round((args.duration ?? 400) / 6),
|
|
295
|
+
autoreverse: true,
|
|
296
|
+
repeat: 3,
|
|
297
|
+
curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
// WRONG -- filters args, only picks what it thinks it needs
|
|
301
|
+
view.animate({
|
|
302
|
+
duration: args.duration,
|
|
303
|
+
transform: Ti.UI.createMatrix2D().translate(intensity, 0),
|
|
304
|
+
autoreverse: true,
|
|
305
|
+
repeat: 3
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Properties declared later in the object literal override earlier ones:
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
// If args = { duration: 300, opacity: 0.5, curve: EASE_OUT }
|
|
313
|
+
view.animate({
|
|
314
|
+
...args, // duration: 300, opacity: 0.5, curve: EASE_OUT
|
|
315
|
+
duration: 50, // overrides to 50
|
|
316
|
+
curve: EASE_IN // overrides to EASE_IN
|
|
317
|
+
})
|
|
318
|
+
// Result: { duration: 50, opacity: 0.5, curve: EASE_IN }
|
|
319
|
+
// opacity 0.5 is preserved from args -- not lost by filtering
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Rule 3: No timing parameters in method signatures
|
|
323
|
+
|
|
324
|
+
The existing core methods (`play`, `open`, `close`, `apply`, `sequence`) do NOT accept `duration`, `delay`, or `curve` as parameters. New methods MUST follow the same pattern. Only parameters specific to the method's unique functionality are allowed.
|
|
325
|
+
|
|
326
|
+
```javascript
|
|
327
|
+
// CORRECT -- only method-specific parameters
|
|
328
|
+
animationView.swap = (view1, view2) => {
|
|
329
|
+
animationView.reorder = (views, newOrder) => {
|
|
330
|
+
animationView.shake = (view, intensity = 10) => {
|
|
331
|
+
animationView.snapTo = (view, targets) => {
|
|
332
|
+
animationView.pulse = (view, count = 1) => {
|
|
333
|
+
|
|
334
|
+
// WRONG -- timing parameters belong in the <Animation /> object
|
|
335
|
+
animationView.swap = (view1, view2, duration) => {
|
|
336
|
+
animationView.shake = (view, intensity, duration) => {
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Users control timing declaratively:
|
|
340
|
+
|
|
341
|
+
```xml
|
|
342
|
+
<!-- Fast swap -->
|
|
343
|
+
<Animation id="fastSwap" module="purgetss.ui" class="duration-75" />
|
|
344
|
+
|
|
345
|
+
<!-- Slow swap with delay -->
|
|
346
|
+
<Animation id="slowSwap" module="purgetss.ui" class="delay-200 duration-500" />
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
```javascript
|
|
350
|
+
// Same method call, different behavior -- controlled by XML
|
|
351
|
+
$.fastSwap.swap($.card1, $.card2)
|
|
352
|
+
$.slowSwap.swap($.card1, $.card2)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Rule 4: Consolidate state with `applyProperties` post-animation
|
|
356
|
+
|
|
357
|
+
After animating position (`left`/`top`), ALWAYS consolidate with `applyProperties` in the callback so the final state is real (not just visual via transform).
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
// CORRECT -- consolidates after animation
|
|
361
|
+
view.animate({
|
|
362
|
+
...args, left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D()
|
|
363
|
+
}, () => {
|
|
364
|
+
view.applyProperties({ left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D() })
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
// WRONG -- animation ends but view's actual properties are stale
|
|
368
|
+
view.animate({
|
|
369
|
+
...args, left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D()
|
|
370
|
+
})
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
On iOS, dragging uses `transform.translate()` -- the view's `left`/`top` properties don't change. `applyProperties` ensures the view's actual properties match the visual position and the transform is reset to identity.
|
|
374
|
+
|
|
375
|
+
### Rule 5: Track position with `_origin*` properties
|
|
376
|
+
|
|
377
|
+
Methods that move position (`swap`, `reorder`, `snapTo`, and future methods like `slideTo`) MUST update `_originTop`/`_originLeft` after the animation so that subsequent drag/swap operations work correctly.
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
// CORRECT -- updates origin tracking
|
|
381
|
+
view.animate({
|
|
382
|
+
...args, left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D()
|
|
383
|
+
}, () => {
|
|
384
|
+
view.applyProperties({ left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D() })
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
view._originTop = destTop
|
|
388
|
+
view._originLeft = destLeft
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
How `_origin*` works:
|
|
392
|
+
- `_originTop`/`_originLeft` represent the view's "logical grid position"
|
|
393
|
+
- `swap` reads from `view._originTop ?? view.top` -- falls back to the actual `top` if no origin is set
|
|
394
|
+
- `onTouchStart` in the drag handler saves the current `top`/`left` as `_origin*` for bounce-back
|
|
395
|
+
- `undraggable` cleans up all `_origin*` properties
|
|
396
|
+
|
|
397
|
+
### Rule 6: Consolidate Android drag position before drop animations
|
|
398
|
+
|
|
399
|
+
On Android, drag uses `animate({ duration: 0 })` which is asynchronous -- the last frame may still be in-flight when `touchend` fires. Before starting any drop animation on Android, consolidate the view's position with `applyProperties`:
|
|
400
|
+
|
|
401
|
+
```javascript
|
|
402
|
+
if (!params.isIOS) {
|
|
403
|
+
draggableView.applyProperties({
|
|
404
|
+
top: draggableView._visualTop ?? draggableView.top,
|
|
405
|
+
left: draggableView._visualLeft ?? draggableView.left
|
|
406
|
+
})
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
This applies to both the snap path and the bounce-back path in `onTouchEnd`. iOS does not need this because drag uses synchronous `transform.translate()`.
|
|
411
|
+
|
|
412
|
+
**Collision fallback on drop:** During drag, `checkCollision` runs on every `touchmove`. When the user releases while still in motion, the drag center may exit the target between the last `touchmove` and `touchend`. The module tracks `lastKnownTarget` and uses it as fallback when `checkCollision` returns null on drop.
|
|
413
|
+
|
|
414
|
+
### Rule 7: Clean up in `undraggable`
|
|
415
|
+
|
|
416
|
+
Every internal property added to views MUST be cleaned up in `undraggable`:
|
|
417
|
+
|
|
418
|
+
| Property | Set by | Purpose |
|
|
419
|
+
| --- | --- | --- |
|
|
420
|
+
| `_originTop` / `_originLeft` | `swap`, `reorder`, `snapTo`, `onTouchStart` | Logical position tracking |
|
|
421
|
+
| `_visualTop` / `_visualLeft` | `handleTouchMove` | Visual position during drag |
|
|
422
|
+
| `_dragListeners` | `makeViewsDraggable` | Touch event listener references |
|
|
423
|
+
| `_collisionEnabled` | `detectCollisions` | Collision detection flag |
|
|
424
|
+
| `_wasDragged` | `onTouchStart` / `handleTouchMove` | Drag detection flag |
|
|
425
|
+
| `_bouncingBack` | `onTouchEnd` (bounce-back) | Prevents origin capture during mid-animation; `swap` cancels it before animating |
|
|
426
|
+
|
|
427
|
+
When adding a new method that stores internal state on views, add the cleanup to `undraggable`:
|
|
428
|
+
|
|
429
|
+
```javascript
|
|
430
|
+
animationView.undraggable = (_views) => {
|
|
431
|
+
const arr = Array.isArray(_views) ? _views : [_views]
|
|
432
|
+
arr.forEach(view => {
|
|
433
|
+
// ... existing cleanup ...
|
|
434
|
+
delete view._newProperty // ADD cleanup for any new internal property
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Method Implementation Template
|
|
442
|
+
|
|
443
|
+
When creating a new method, follow this template:
|
|
444
|
+
|
|
445
|
+
```javascript
|
|
446
|
+
animationView.newMethod = (view, specificParam = defaultValue) => {
|
|
447
|
+
if (params.debug) { console.log('') }
|
|
448
|
+
logger('`newMethod` method called on: ' + params.id)
|
|
449
|
+
if (!view) { return notFound() }
|
|
450
|
+
|
|
451
|
+
view.animate({
|
|
452
|
+
...args, // Rule 1: inherit all from <Animation />
|
|
453
|
+
specificProp: computedValue, // Rule 2: override AFTER ...args
|
|
454
|
+
}, () => {
|
|
455
|
+
view.applyProperties({ ... }) // Rule 4: consolidate state
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
view._originTop = newTop // Rule 5: track position (if applicable)
|
|
459
|
+
view._originLeft = newLeft
|
|
460
|
+
}
|
|
461
|
+
// Rule 3: no timing params in signature
|
|
462
|
+
// Rule 7: add cleanup to undraggable (if new internal state)
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## Complex UI Example
|
|
468
|
+
|
|
469
|
+
This example combines several Animation module features in a single UI: a collapsible sidebar, an expandable card, and draggable elements.
|
|
470
|
+
|
|
471
|
+
Install FontAwesome fonts first:
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
purgetss icon-library -v=fa
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### XML
|
|
478
|
+
|
|
479
|
+
```xml
|
|
480
|
+
<Alloy>
|
|
481
|
+
<Window class="exit-on-close-false portrait bg-purple-700">
|
|
482
|
+
<Animation id="draggableAnimation" module="purgetss.ui" class="bounds:m-4 bounds:mb-20" />
|
|
483
|
+
|
|
484
|
+
<!-- Sidebar -->
|
|
485
|
+
<Animation id="sideBarAnimation" module="purgetss.ui" class="close:w-24 duration-150 open:w-72" />
|
|
486
|
+
<Animation id="sideBarAnimationChevron" module="purgetss.ui" class="close:rotate-0 duration-150 open:rotate-180" />
|
|
487
|
+
|
|
488
|
+
<View id="sideBar" class="ml-2 h-1/2 w-24">
|
|
489
|
+
<View class="vertical ios:shadow-lg mr-8 rounded-lg bg-white" ios:onSingletap="doAction" android:onClick="doAction">
|
|
490
|
+
<View class="grid-flow-row">
|
|
491
|
+
<View class="ml-0 w-64 grid-rows-7">
|
|
492
|
+
<View class="horizontal bg-selected-purple-100 items-center" action="home">
|
|
493
|
+
<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" />
|
|
494
|
+
<Label class="touch-enabled-false text-purple-700" text="Home" />
|
|
495
|
+
</View>
|
|
496
|
+
</View>
|
|
497
|
+
<!-- More menu items: profile, messages, help, settings, password, sign-out -->
|
|
498
|
+
</View>
|
|
499
|
+
</View>
|
|
500
|
+
<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" />
|
|
501
|
+
</View>
|
|
502
|
+
|
|
503
|
+
<!-- My Card -->
|
|
504
|
+
<Animation id="myCardAnimation" module="purgetss.ui" class="open:h-(298) close:h-24 duration-150" />
|
|
505
|
+
<Animation id="myCardAnimationChevron" module="purgetss.ui" class="close:rotate-0 duration-150 open:rotate-180" />
|
|
506
|
+
|
|
507
|
+
<View id="myCard" class="mr-6 mt-6 h-24 w-8/12 rounded-lg shadow-lg">
|
|
508
|
+
<View class="vertical rounded-lg bg-white">
|
|
509
|
+
<View class="h-auto w-screen">
|
|
510
|
+
<ImageView class="rounded-16 m-4 ml-4 h-16 w-16" image="https://randomuser.me/api/portraits/women/17.jpg" />
|
|
511
|
+
<View class="vertical ml-24 h-auto">
|
|
512
|
+
<Label class="ml-0 text-sm font-bold text-gray-800" text="Someone Famous" />
|
|
513
|
+
<Label class="ml-0 text-xs font-bold text-gray-400" text="Website Designer" />
|
|
514
|
+
</View>
|
|
515
|
+
</View>
|
|
516
|
+
<View class="rounded-1 mx-2 h-0.5 w-screen bg-gray-300" />
|
|
517
|
+
<View class="bubble-parent-false mt-2 h-48 w-screen grid-flow-row" ios:onSingletap="doAction" android:onClick="doAction">
|
|
518
|
+
<!-- Card menu items: edit profile, inbox, settings, support, sign-out -->
|
|
519
|
+
</View>
|
|
520
|
+
</View>
|
|
521
|
+
<View class="rounded-tl-br-md wh-8 bubble-parent-false mb-0 mr-0 bg-blue-400">
|
|
522
|
+
<Button id="myCardChevron" class="fas fa-chevron-down border-transparent bg-transparent text-white" ios:onSingletap="myCardClicked" android:onClick="myCardClicked" />
|
|
523
|
+
</View>
|
|
524
|
+
</View>
|
|
525
|
+
|
|
526
|
+
<Label id="action" class="mx-4 mb-6 h-10 w-screen rounded-lg bg-purple-800 text-sm font-bold text-purple-50" />
|
|
527
|
+
</Window>
|
|
528
|
+
</Alloy>
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Controller
|
|
532
|
+
|
|
533
|
+
```javascript
|
|
534
|
+
$.index.open()
|
|
535
|
+
|
|
536
|
+
$.draggableAnimation.draggable($.myCard)
|
|
537
|
+
|
|
538
|
+
function sideBarClicked() {
|
|
539
|
+
$.sideBarAnimation.play($.sideBar)
|
|
540
|
+
$.sideBarAnimationChevron.play($.sideBarChevron)
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function myCardClicked() {
|
|
544
|
+
$.myCardAnimation.play($.myCard)
|
|
545
|
+
$.myCardAnimationChevron.play($.myCardChevron)
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function doAction(event) {
|
|
549
|
+
if (event.source.action) {
|
|
550
|
+
$.action.text = ` Action: ${event.source.action}`
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
This demonstrates: `play` for sidebar/card toggle, `open:`/`close:` modifiers for different states, `draggable` with `bounds:` modifier, and multiple Animation objects controlling different UI elements.
|