@maccesar/titools 4.18.0 → 4.19.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/package.json +1 -1
- package/skills/purgetss/SKILL.md +9 -4
- package/skills/purgetss/references/animation-advanced.md +93 -226
- package/skills/purgetss/references/animation-system.md +26 -17
- package/skills/purgetss/references/app-branding.md +31 -8
- package/skills/purgetss/references/appearance-module.md +63 -9
- package/skills/purgetss/references/class-categories.md +2 -2
- package/skills/purgetss/references/class-index.md +1 -1
- package/skills/purgetss/references/classic-projects.md +24 -5
- package/skills/purgetss/references/cli-commands.md +34 -24
- package/skills/purgetss/references/custom-fonts.md +29 -2
- package/skills/purgetss/references/customization-deep-dive.md +11 -6
- package/skills/purgetss/references/dynamic-component-creation.md +1 -1
- package/skills/purgetss/references/icon-fonts.md +3 -1
- package/skills/purgetss/references/installation-setup.md +5 -1
- package/skills/purgetss/references/purgetss-ui-classic.md +341 -0
- package/skills/purgetss/references/version-history.md +12 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **SCOPE NOTE**
|
|
4
4
|
>
|
|
5
|
-
> This reference covers dynamic component creation using **Alloy's `$.UI.create()` helper** and **`Alloy.createStyle()` + `applyProperties()`**, both combined with PurgeTSS utility classes. It is an Alloy + PurgeTSS integration guide, **not** documentation for the `purgetss.ui` native module (see [animation-system.md](./animation-system.md) and [animation-advanced.md](./animation-advanced.md) for
|
|
5
|
+
> This reference covers dynamic component creation using **Alloy's `$.UI.create()` helper** and **`Alloy.createStyle()` + `applyProperties()`**, both combined with PurgeTSS utility classes. It is an Alloy + PurgeTSS integration guide, **not** documentation for the `purgetss.ui` native module (see [animation-system.md](./animation-system.md) and [animation-advanced.md](./animation-advanced.md) for Alloy animation usage, or [purgetss-ui-classic.md](./purgetss-ui-classic.md) for the generated Classic runtime).
|
|
6
6
|
>
|
|
7
7
|
> For general Alloy controller and view patterns, refer to the `alloy-guides` and `alloy-howtos` skills.
|
|
8
8
|
|
|
@@ -93,7 +93,7 @@ Each module exposes its existing icon lookup API plus a `families` object with `
|
|
|
93
93
|
| `framework7icons` | `fontFamily` |
|
|
94
94
|
|
|
95
95
|
```javascript
|
|
96
|
-
const fontAwesome = require('fontawesome')
|
|
96
|
+
const fontAwesome = require('lib/fontawesome')
|
|
97
97
|
|
|
98
98
|
const home = Ti.UI.createLabel({
|
|
99
99
|
text: fontAwesome.icons.home,
|
|
@@ -104,6 +104,8 @@ const home = Ti.UI.createLabel({
|
|
|
104
104
|
})
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
+
All generated modules live under `Resources/lib/`, so use the pattern shown above: include `lib/` in the path and omit both `Resources/` and `.js`. See the centralized [Classic module path table](./classic-projects.md#loading-generated-modules-in-classic) for all four filenames.
|
|
108
|
+
|
|
107
109
|
The direct alias and `families` values agree, for example `fontAwesome.solid === fontAwesome.families.solid`; `families.default` provides the library's default variant.
|
|
108
110
|
|
|
109
111
|
## Using icons in Alloy XML
|
|
@@ -61,7 +61,11 @@ When you run `purgetss` for the first time in your project, it does the followin
|
|
|
61
61
|
|
|
62
62
|
### 1. Auto-run Hook
|
|
63
63
|
|
|
64
|
-
PurgeTSS adds a task in `alloy.jmk` to run `purgetss` every time you compile your app.
|
|
64
|
+
PurgeTSS adds a task in `alloy.jmk` to run `purgetss` every time you compile your app. This works well with `liveview`.
|
|
65
|
+
|
|
66
|
+
With the default synchronous method, the hook inherits PurgeTSS output so XML validation and other diagnostics appear before Alloy's generic compiler failure. It then prints a final hint to run `purgetss` from the project root and rethrows the error.
|
|
67
|
+
|
|
68
|
+
Current `init` runs update an older active or disabled hook without changing its enabled state. Invoking `watch` normally enables a disabled hook.
|
|
65
69
|
|
|
66
70
|
### 2. `purgetss` Folder
|
|
67
71
|
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# `purgetss.ui` in Titanium Classic
|
|
2
|
+
|
|
3
|
+
Titanium Classic uses the same generated `purgetss.ui` runtime as Alloy, but it does not compile Alloy XML, TSS, utility classes, controllers, or `$.*` references. Configure the runtime with JavaScript objects containing native Titanium properties.
|
|
4
|
+
|
|
5
|
+
<!-- TOC-START -->
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Install and load](#install-and-load)
|
|
9
|
+
- [Public exports](#public-exports)
|
|
10
|
+
- [Quick start](#quick-start)
|
|
11
|
+
- [Animation method contract](#animation-method-contract)
|
|
12
|
+
- [Native animation configuration](#native-animation-configuration)
|
|
13
|
+
- [States and direct children](#states-and-direct-children)
|
|
14
|
+
- [Position helpers](#position-helpers)
|
|
15
|
+
- [Drag and collision configuration](#drag-and-collision-configuration)
|
|
16
|
+
- [Drag lifecycle and cleanup](#drag-lifecycle-and-cleanup)
|
|
17
|
+
- [Layout transitions](#layout-transitions)
|
|
18
|
+
- [Appearance in Classic](#appearance-in-classic)
|
|
19
|
+
- [Runtime utilities](#runtime-utilities)
|
|
20
|
+
- [Related references](#related-references)
|
|
21
|
+
|
|
22
|
+
<!-- TOC-END -->
|
|
23
|
+
|
|
24
|
+
## Install and load
|
|
25
|
+
|
|
26
|
+
Run this from the Classic project root:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
purgetss module
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The command creates `Resources/lib/purgetss.ui.js`. Load it from a file such as `Resources/app.js`:
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
const {
|
|
36
|
+
createAnimation,
|
|
37
|
+
Appearance,
|
|
38
|
+
deviceInfo,
|
|
39
|
+
saveComponent
|
|
40
|
+
} = require('lib/purgetss.ui')
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Use `createAnimation(args)` for ordinary Classic code. It returns a zero-size, touch-disabled `Ti.UI.View` decorated with animation methods. Treat this view as a behavior object; do not add it to the window.
|
|
44
|
+
|
|
45
|
+
## Public exports
|
|
46
|
+
|
|
47
|
+
| Export | Type and return | Contract |
|
|
48
|
+
| --- | --- | --- |
|
|
49
|
+
| `AnimationProperties` | Constructor returning the decorated animation view | Public, but less clear than the factory in Classic |
|
|
50
|
+
| `createAnimation(args)` | Factory returning the decorated animation view | Preferred Classic entry point |
|
|
51
|
+
| `Appearance` | Singleton object | `init()`, `set()`, `get()`, `toggle()` |
|
|
52
|
+
| `deviceInfo()` | Function returning `undefined` | Logs platform and display information |
|
|
53
|
+
| `saveComponent({ source, directory? })` | Function returning `undefined` | Writes a PNG and invokes the photo-gallery API |
|
|
54
|
+
|
|
55
|
+
## Quick start
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const { createAnimation, Appearance } = require('lib/purgetss.ui')
|
|
59
|
+
|
|
60
|
+
Appearance.init()
|
|
61
|
+
|
|
62
|
+
const window = Ti.UI.createWindow({ backgroundColor: 'surfaceColor' })
|
|
63
|
+
const card = Ti.UI.createView({
|
|
64
|
+
width: 220,
|
|
65
|
+
height: 120,
|
|
66
|
+
backgroundColor: 'accentColor',
|
|
67
|
+
opacity: 0,
|
|
68
|
+
transform: Ti.UI.createMatrix2D().scale(0.92)
|
|
69
|
+
})
|
|
70
|
+
const motion = createAnimation({
|
|
71
|
+
duration: 220,
|
|
72
|
+
curve: Ti.UI.ANIMATION_CURVE_EASE_OUT,
|
|
73
|
+
animationProperties: {
|
|
74
|
+
open: { opacity: 1, scale: 1 },
|
|
75
|
+
close: { opacity: 0, scale: 0.92 }
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
function onCardClick() { motion.play(card) }
|
|
80
|
+
function onWindowOpen() { motion.open(card) }
|
|
81
|
+
function disposeWindow() {
|
|
82
|
+
card.removeEventListener('click', onCardClick)
|
|
83
|
+
window.removeEventListener('open', onWindowOpen)
|
|
84
|
+
window.removeEventListener('close', disposeWindow)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
card.addEventListener('click', onCardClick)
|
|
88
|
+
window.add(card)
|
|
89
|
+
window.addEventListener('open', onWindowOpen)
|
|
90
|
+
window.addEventListener('close', disposeWindow)
|
|
91
|
+
window.open()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`surfaceColor` and `accentColor` are names from `Resources/semantic.colors.json`; see [appearance-module.md#titanium-classic](./appearance-module.md#titanium-classic).
|
|
95
|
+
|
|
96
|
+
## Animation method contract
|
|
97
|
+
|
|
98
|
+
| Method | Signature | Return and callback |
|
|
99
|
+
| --- | --- | --- |
|
|
100
|
+
| `play` | `play(viewOrViews, callback?)` | `undefined`; callback once per view after its base animation completes |
|
|
101
|
+
| `toggle` | `toggle(viewOrViews, callback?)` | Exact alias of `play` |
|
|
102
|
+
| `apply` | `apply(viewOrViews, callback?)` | `undefined`; synchronous callback once per view |
|
|
103
|
+
| `open` | `open(viewOrViews, callback?)` | `undefined`; forces open state, callback once per view |
|
|
104
|
+
| `close` | `close(viewOrViews, callback?)` | `undefined`; forces close state, callback once per view |
|
|
105
|
+
| `draggable` | `draggable(viewOrViews)` | `undefined` |
|
|
106
|
+
| `undraggable` | `undraggable(viewOrViews)` | `undefined` |
|
|
107
|
+
| `detectCollisions` | `detectCollisions(views, dragCallback?, dropCallback?)` | `undefined` |
|
|
108
|
+
| `sequence` | `sequence(viewOrViews, callback?)` | `undefined`; callback once after the final view |
|
|
109
|
+
| `swap` | `swap(view1, view2)` | `undefined` |
|
|
110
|
+
| `pulse` | `pulse(view, count = 1)` | `undefined` |
|
|
111
|
+
| `shake` | `shake(view, intensity = 10)` | `undefined` |
|
|
112
|
+
| `snapTo` | `snapTo(view, targets)` | Selected target, `null` if none qualifies, or `undefined` for a missing source |
|
|
113
|
+
| `reorder` | `reorder(views, newOrder)` | `undefined` |
|
|
114
|
+
| `transition` | `transition(viewOrViews, layouts)` | `undefined` |
|
|
115
|
+
|
|
116
|
+
`play`, `toggle`, `apply`, `open`, and `close` accept one view or an array. The array callback runs once per view with:
|
|
117
|
+
|
|
118
|
+
- `type`: native completion type, or `'applied'` for `apply`.
|
|
119
|
+
- `bubbles` and `cancelBubble`: selected native primitives.
|
|
120
|
+
- `action`: `'play'` or `'apply'`.
|
|
121
|
+
- `state`: `'open'` or `'close'`.
|
|
122
|
+
- `id` and `targetId`.
|
|
123
|
+
- `index` and `total`.
|
|
124
|
+
- `getTarget()`: returns the affected view.
|
|
125
|
+
|
|
126
|
+
This is a newly constructed object, not the original Titanium event. For array playback, the configured base delay accumulates for successive views. `sequence()` instead waits for each native completion and invokes its callback once after the last view. Passing an empty array to `sequence()` produces no callback.
|
|
127
|
+
|
|
128
|
+
`animationProperties.complete` starts after the active `play`, `toggle`, `open`, or `close` base phase, and is applied immediately after `apply`. The public play callback does not wait for the second top-level `complete` animation.
|
|
129
|
+
|
|
130
|
+
## Native animation configuration
|
|
131
|
+
|
|
132
|
+
Pass native `Ti.UI.Animation` values directly:
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
const { createAnimation } = require('lib/purgetss.ui')
|
|
136
|
+
|
|
137
|
+
const motion = createAnimation({
|
|
138
|
+
id: 'cardMotion',
|
|
139
|
+
duration: 240,
|
|
140
|
+
delay: 40,
|
|
141
|
+
curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT,
|
|
142
|
+
repeat: 1,
|
|
143
|
+
autoreverse: false,
|
|
144
|
+
opacity: 0.8,
|
|
145
|
+
backgroundColor: '#2563eb',
|
|
146
|
+
scale: 1.05,
|
|
147
|
+
rotate: 4
|
|
148
|
+
})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The constructor removes `id` from the native animation object. It converts top-level `scale`, `rotate`, and `anchorPoint` into one `Ti.UI.Matrix2D`; it performs the same conversion separately for `animationProperties.open` and `.close`. Helpers such as `pulse`, `shake`, `swap`, `snapTo`, `reorder`, and `transition` can replace or reset that transform.
|
|
152
|
+
|
|
153
|
+
Most helpers spread the base object before their method-specific assignments, so later helper fields win. There is no shared `200ms` timing fallback for position/layout helpers. Only `shake()` computes `(duration ?? 400) / 6`, rounded to the nearest millisecond; `pulse()` supplies a default scale of `1.2`. Both force `ANIMATION_CURVE_EASE_IN_OUT`.
|
|
154
|
+
|
|
155
|
+
Titanium exposes `anchorPoint` differently across platforms. Test pivot-dependent animation on both platforms; in Classic, set the view's iOS anchor point before animation and pass an Android animation anchor point only inside a platform guard.
|
|
156
|
+
|
|
157
|
+
## States and direct children
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
const panelMotion = createAnimation({
|
|
161
|
+
duration: 220,
|
|
162
|
+
animationProperties: {
|
|
163
|
+
open: { opacity: 1, scale: 1 },
|
|
164
|
+
close: { opacity: 0, scale: 0.94 },
|
|
165
|
+
complete: { borderColor: '#22c55e' },
|
|
166
|
+
children: { duration: 160 }
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
titleLabel.animationProperties = {
|
|
171
|
+
child: { delay: 40 },
|
|
172
|
+
open: { opacity: 1, top: 16 },
|
|
173
|
+
close: { opacity: 0, top: 24 },
|
|
174
|
+
complete: { color: '#22c55e' }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
panelMotion.open(panel)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
For a direct child, merge precedence is:
|
|
181
|
+
|
|
182
|
+
1. Parent `animationProperties.children`.
|
|
183
|
+
2. Child `animationProperties.child`.
|
|
184
|
+
3. Child's active `open`, `close`, or `complete` object.
|
|
185
|
+
|
|
186
|
+
Later values win. Nested descendants are not traversed automatically.
|
|
187
|
+
|
|
188
|
+
## Position helpers
|
|
189
|
+
|
|
190
|
+
- `swap()` exchanges two rendered positions, temporarily promotes both views, persists `top`/`left`, and updates private drag origins. It restores stacking from the current draggable registry order, not arbitrary original z-index values.
|
|
191
|
+
- `snapTo()` chooses the nearest target by center distance and returns it immediately. Views must be laid out because it reads `rect`.
|
|
192
|
+
- `reorder()` maps each view to the captured position at `newOrder[index]`. A length mismatch returns without changes.
|
|
193
|
+
- `pulse()` forces autoreverse, the supplied repeat count, and ease-in-out, then resets the transform.
|
|
194
|
+
- `shake()` starts at `-intensity`, animates to `+intensity` through six short phases, and resets the transform.
|
|
195
|
+
|
|
196
|
+
These methods do not expose completion callbacks. Configure duration, delay, and curve on the object passed to `createAnimation()`.
|
|
197
|
+
|
|
198
|
+
## Drag and collision configuration
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const dragMotion = createAnimation({
|
|
202
|
+
duration: 160,
|
|
203
|
+
bounds: { top: 12, right: 12, bottom: 12, left: 12 },
|
|
204
|
+
draggingType: 'animate',
|
|
205
|
+
draggable: {
|
|
206
|
+
drag: { opacity: 0.7, scale: 1.04 },
|
|
207
|
+
drop: { opacity: 1, scale: 1 }
|
|
208
|
+
},
|
|
209
|
+
animationProperties: {
|
|
210
|
+
keepZIndex: true,
|
|
211
|
+
snap: { back: true, center: true }
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
piece.bounds = { bottom: 40 }
|
|
216
|
+
piece.constraint = 'horizontal'
|
|
217
|
+
piece.draggingType = 'apply'
|
|
218
|
+
piece.draggable = {
|
|
219
|
+
drag: { opacity: 0.5 },
|
|
220
|
+
drop: { opacity: 1 }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
dragMotion.draggable(piece)
|
|
224
|
+
dragMotion.detectCollisions([piece, target], (source, hovered) => {
|
|
225
|
+
target.borderColor = hovered === target ? '#22c55e' : 'transparent'
|
|
226
|
+
}, (source, droppedOn) => {
|
|
227
|
+
Ti.API.info(`${source.id} dropped on ${droppedOn.id}`)
|
|
228
|
+
})
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Runtime precedence and behavior:
|
|
232
|
+
|
|
233
|
+
- Global bounds are the base; `view.bounds` overrides individual edges.
|
|
234
|
+
- Axis restriction comes from `view.constraint`; a constructor-level constraint is not read.
|
|
235
|
+
- Per-view `draggingType` overrides the constructor value.
|
|
236
|
+
- Global and per-view `draggable.drag/drop` objects are merged; view fields win.
|
|
237
|
+
- Every resolved drag/drop property is forwarded, including size, transform, and anchor-point fields.
|
|
238
|
+
- `snap.center` calls `snapTo()` after a valid drop; `snap.back` returns a missed drop to its origin.
|
|
239
|
+
- There is no `snap.magnet` behavior.
|
|
240
|
+
- Collision detection tests the dragged view's center against registered targets. The last non-null hover target is a fallback at release.
|
|
241
|
+
|
|
242
|
+
Call drag/collision setup after the views are attached and laid out. `draggable(array)` assigns each view `zIndex` from its array index before registration. `keepZIndex` only prevents later touch-start promotion; register views individually if their existing z-index values must not be overwritten.
|
|
243
|
+
|
|
244
|
+
## Drag lifecycle and cleanup
|
|
245
|
+
|
|
246
|
+
Register each view once. The current runtime does not deduplicate repeated `draggable()` calls: they create additional listeners and registry entries. One `undraggable()` call removes only the latest stored listener set and the first matching registry entries.
|
|
247
|
+
|
|
248
|
+
`undraggable()` removes the stored `touchstart`, `touchmove`, `touchend`, and global `orientationchange` listeners and most private position/collision fields, but it leaves `_wasDragged`. `detectCollisions()` retains the last non-null callbacks on the animation object; passing `null` does not clear them.
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
let dragReady = false
|
|
252
|
+
|
|
253
|
+
function enableDrag() {
|
|
254
|
+
if (dragReady) return
|
|
255
|
+
dragReady = true
|
|
256
|
+
dragMotion.draggable(piece)
|
|
257
|
+
dragMotion.detectCollisions([piece, target])
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function disposeWindow() {
|
|
261
|
+
dragMotion.undraggable([piece, target])
|
|
262
|
+
window.removeEventListener('open', enableDrag)
|
|
263
|
+
window.removeEventListener('close', disposeWindow)
|
|
264
|
+
dragReady = false
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
window.addEventListener('open', enableDrag)
|
|
268
|
+
window.addEventListener('close', disposeWindow)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Release view, callback, and animation references after close. Application code should not depend on private underscore fields.
|
|
272
|
+
|
|
273
|
+
## Layout transitions
|
|
274
|
+
|
|
275
|
+
`transition(views, layouts)` accepts these layout fields:
|
|
276
|
+
|
|
277
|
+
| Field | Default | Behavior |
|
|
278
|
+
| --- | --- | --- |
|
|
279
|
+
| `translation` | `{ x: 0, y: 0 }` | Matrix translation |
|
|
280
|
+
| `rotate` | `0` | Matrix rotation in degrees |
|
|
281
|
+
| `scale` | `1` | Matrix scale |
|
|
282
|
+
| `zIndex` | unchanged | Assigned before animation |
|
|
283
|
+
| `width`, `height` | unchanged | Optional size animation |
|
|
284
|
+
| `opacity` | unchanged | Optional opacity animation |
|
|
285
|
+
|
|
286
|
+
```javascript
|
|
287
|
+
const layoutMotion = createAnimation({
|
|
288
|
+
duration: 220,
|
|
289
|
+
curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT
|
|
290
|
+
})
|
|
291
|
+
const fan = [
|
|
292
|
+
{ translation: { x: -120, y: 20 }, rotate: -15, scale: 0.8, zIndex: 1 },
|
|
293
|
+
{ translation: { x: 0, y: 0 }, rotate: 0, scale: 1, zIndex: 3 },
|
|
294
|
+
{ translation: { x: 120, y: 20 }, rotate: 15, scale: 0.8, zIndex: 2 }
|
|
295
|
+
]
|
|
296
|
+
|
|
297
|
+
layoutMotion.transition([cardA, cardB, cardC], fan)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
A view without a matching layout fades to opacity `0`, receives `zIndex: 0`, and has touch disabled. Extra layouts are ignored. A later matching layout fades a hidden view in and reenables touch. iOS preserves the last transform while hidden; Android resets transform, translation, rotation, and scale. Completion forces `touchEnabled: true` for every matched view, so reapply `false` afterward when a view must remain non-interactive.
|
|
301
|
+
|
|
302
|
+
On Mac Catalyst, use a fixed-size parent rather than `Ti.UI.FILL` for rotated layouts; a resizable parent can distort the matrix.
|
|
303
|
+
|
|
304
|
+
## Appearance in Classic
|
|
305
|
+
|
|
306
|
+
Put semantic colors in `Resources/semantic.colors.json`, use their names directly in native color properties, and call `Appearance.init()` before opening the first window. Classic does not need utility classes, TSS, `purgetss/config.cjs`, or Alloy runtime files. Run a full native build after adding or changing semantic keys; LiveView alone does not rebuild the native catalog.
|
|
307
|
+
|
|
308
|
+
See [appearance-module.md#titanium-classic](./appearance-module.md#titanium-classic) for setup and all four method contracts.
|
|
309
|
+
|
|
310
|
+
## Runtime utilities
|
|
311
|
+
|
|
312
|
+
```javascript
|
|
313
|
+
const { deviceInfo, saveComponent } = require('lib/purgetss.ui')
|
|
314
|
+
|
|
315
|
+
deviceInfo()
|
|
316
|
+
|
|
317
|
+
function savePreview() {
|
|
318
|
+
if (!Ti.Media.hasPhotoGalleryPermissions()) {
|
|
319
|
+
Ti.Media.requestPhotoGalleryPermissions(event => {
|
|
320
|
+
if (event.success) savePreview()
|
|
321
|
+
})
|
|
322
|
+
return
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
saveComponent({
|
|
326
|
+
source: preview,
|
|
327
|
+
directory: Ti.Filesystem.applicationDataDirectory
|
|
328
|
+
})
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
`deviceInfo()` logs values and returns `undefined`. It logs `xdpi` and `ydpi` only on Android. Its tablet flag recognizes iPad only, so Android tablets are currently logged as `isTablet: false` and `isHandheld: true`.
|
|
333
|
+
|
|
334
|
+
`saveComponent()` calls `source.toImage()`, derives an MD5-based `.png` filename, writes it to `directory` (default: `Ti.Filesystem.tempDirectory`), then invokes `Ti.Media.saveToPhotoGallery()`. It returns `undefined` and provides no completion or error callback. Check/request gallery permission before calling it; on iOS, declare the required photo-library add usage description.
|
|
335
|
+
|
|
336
|
+
## Related references
|
|
337
|
+
|
|
338
|
+
- [animation-system.md](./animation-system.md) — Alloy syntax and all animation methods.
|
|
339
|
+
- [animation-advanced.md](./animation-advanced.md) — generated timing classes and runtime rules.
|
|
340
|
+
- [appearance-module.md](./appearance-module.md) — Appearance workflow and API.
|
|
341
|
+
- [classic-projects.md](./classic-projects.md) — commands and capabilities available to Classic projects.
|
|
@@ -8,6 +8,18 @@ When in doubt about whether a class, flag, or config key exists in the user's in
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## v7.16.2
|
|
12
|
+
- `build-fonts --module` now exports every processed TTF/OTF PostScript name through `families`, including text-only collections; icon CSS additionally populates `icons`. Filename-derived keys such as `poppinsSemiBold` are supported. See [custom-fonts.md](custom-fonts.md).
|
|
13
|
+
- In clean Classic projects, saved `shades` palettes and `color-module` no longer scaffold empty brand, font, or image source folders. `shades` still refreshes an existing generated color module. See [classic-projects.md](classic-projects.md).
|
|
14
|
+
|
|
15
|
+
## v7.16.1
|
|
16
|
+
- Alloy auto-purge hooks now expose PurgeTSS output before Alloy's generic failure, print a command-line diagnostic hint, and migrate older active or disabled hooks without losing their state. See [installation-setup.md](installation-setup.md).
|
|
17
|
+
|
|
18
|
+
## v7.16.0
|
|
19
|
+
- `brand.artworkCornerRadius` and optional `brand.splashCornerRadius` add shared rounding for non-icon artwork; the iOS/Android splash, Feature Graphic, and LaunchLogo pieces also accept `cornerRadius`. Values are 0–50, and unsupported pieces reject the key before writing. Platform-masked and store icon outputs remain unrounded. See [app-branding.md](app-branding.md).
|
|
20
|
+
- Six CLI radius flags provide shared, splash-only, and per-piece one-run overrides. `--appicon-padding` completes the existing `brand.appicon.padding` contract, whose canonical default is `10%`.
|
|
21
|
+
- Branding summaries and `--dry-run` now report effective padding and corner radius for rounded pieces.
|
|
22
|
+
|
|
11
23
|
## v7.15.0
|
|
12
24
|
- Standalone `images`, `semantic`, `shades`, `color-module`, `module`, `icon-library`, and `build-fonts` now support Classic without installing the Alloy hook or utility-class lifecycle. Outputs route to native `Resources/` paths where appropriate. See [classic-projects.md](classic-projects.md).
|
|
13
25
|
- `images` follows `<deployment-targets>` from `tiapp.xml` by default; explicit `--android` / `--ios` override that selection.
|