purgetss 7.4.0 → 7.5.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 +184 -61
- package/assets/fonts/FontAwesome7Brands-Regular.ttf +0 -0
- package/assets/fonts/FontAwesome7Free-Regular.ttf +0 -0
- package/assets/fonts/FontAwesome7Free-Solid.ttf +0 -0
- package/dist/fontawesome.js +55 -1
- package/dist/fontawesome.tss +55 -1
- package/dist/purgetss.ui.js +495 -26
- package/dist/utilities.tss +79 -68
- package/experimental/completions2.js +27 -12
- package/lib/templates/fontawesome/free-template.js.cjs +1 -1
- package/lib/templates/fontawesome/free-template.tss +1 -1
- package/lib/templates/purgetss.ui.js.cjs +487 -18
- package/package.json +2 -2
- package/src/core/builders/tailwind-builder.js +1 -0
- package/src/core/builders/tailwind-helpers.js +19 -9
- package/src/fonts/Font Awesome 7 Brands-Regular-400.otf +0 -0
- package/src/fonts/Font Awesome 7 Free-Regular-400.otf +0 -0
- package/src/fonts/Font Awesome 7 Free-Solid-900.otf +0 -0
- package/src/shared/helpers/animation.js +22 -0
- package/src/shared/helpers/utils.js +65 -6
|
@@ -3,14 +3,26 @@
|
|
|
3
3
|
|
|
4
4
|
function Animation(args = {}) {
|
|
5
5
|
const params = {
|
|
6
|
+
// Global
|
|
6
7
|
id: args.id,
|
|
8
|
+
debug: args.debug ?? false,
|
|
9
|
+
isIOS: Ti.Platform.osname === 'iphone' || Ti.Platform.osname === 'ipad',
|
|
10
|
+
|
|
11
|
+
// Play / Toggle / Sequence
|
|
7
12
|
open: false,
|
|
8
|
-
draggables: [],
|
|
9
13
|
playing: false,
|
|
10
14
|
delay: args.delay ?? 0,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
hasTransformation: (args.scale !== undefined || args.rotate !== undefined),
|
|
16
|
+
|
|
17
|
+
// Draggable
|
|
18
|
+
draggables: [],
|
|
19
|
+
|
|
20
|
+
// Collision Detection
|
|
21
|
+
collisionViews: [],
|
|
22
|
+
dragCB: null,
|
|
23
|
+
dropCB: null,
|
|
24
|
+
lastHoverTarget: null,
|
|
25
|
+
lastKnownTarget: null
|
|
14
26
|
}
|
|
15
27
|
|
|
16
28
|
logger('Create Animation View: ' + params.id)
|
|
@@ -41,6 +53,242 @@ function Animation(args = {}) {
|
|
|
41
53
|
makeViewsDraggable(_views)
|
|
42
54
|
}
|
|
43
55
|
|
|
56
|
+
animationView.detectCollisions = (views, _dragCB, _dropCB) => {
|
|
57
|
+
if (params.debug) { console.log('') }
|
|
58
|
+
logger('`detectCollisions` method called on: ' + params.id)
|
|
59
|
+
if (_dragCB) params.dragCB = _dragCB
|
|
60
|
+
if (_dropCB) params.dropCB = _dropCB
|
|
61
|
+
const arr = Array.isArray(views) ? views : [views]
|
|
62
|
+
arr.forEach(view => {
|
|
63
|
+
view._collisionEnabled = true
|
|
64
|
+
if (!params.collisionViews.includes(view)) {
|
|
65
|
+
params.collisionViews.push(view)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolvePosition(view) {
|
|
71
|
+
if (view._originTop !== undefined) return { top: view._originTop, left: view._originLeft }
|
|
72
|
+
if (view.top !== undefined && view.top !== null && view.left !== undefined && view.left !== null) return { top: view.top, left: view.left }
|
|
73
|
+
const r = view.rect
|
|
74
|
+
return { top: r.y, left: r.x }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function normalizePosition(view) {
|
|
78
|
+
const pos = resolvePosition(view)
|
|
79
|
+
view.applyProperties({ top: pos.top, left: pos.left, right: null, bottom: null })
|
|
80
|
+
view._originTop = pos.top
|
|
81
|
+
view._originLeft = pos.left
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
animationView.swap = (view1, view2) => {
|
|
85
|
+
if (params.debug) { console.log('') }
|
|
86
|
+
logger('`swap` method called on: ' + params.id)
|
|
87
|
+
|
|
88
|
+
// Cancel any pending bounce-back animations
|
|
89
|
+
;[view1, view2].forEach(v => {
|
|
90
|
+
if (v._bouncingBack) {
|
|
91
|
+
logger(` -> cancelling bounce-back for ${v.id} before swap`)
|
|
92
|
+
v.applyProperties({ top: v._originTop, left: v._originLeft, transform: Ti.UI.createMatrix2D() })
|
|
93
|
+
v._bouncingBack = false
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
// Read REAL positions — rect gives actual rendered position, no stale variables
|
|
98
|
+
const targetRect = view2.rect
|
|
99
|
+
const sourceHome = { top: view1._originTop ?? view1.top, left: view1._originLeft ?? view1.left }
|
|
100
|
+
|
|
101
|
+
// Source goes to target's real position, target goes to source's home
|
|
102
|
+
const dest1Top = targetRect.y
|
|
103
|
+
const dest1Left = targetRect.x
|
|
104
|
+
const dest2Top = sourceHome.top
|
|
105
|
+
const dest2Left = sourceHome.left
|
|
106
|
+
|
|
107
|
+
logger(` -> ${view1.id}: home(${sourceHome.top}, ${sourceHome.left}) → dest(${dest1Top}, ${dest1Left})`)
|
|
108
|
+
logger(` -> ${view2.id}: rect(${targetRect.y}, ${targetRect.x}) → dest(${dest2Top}, ${dest2Left})`)
|
|
109
|
+
|
|
110
|
+
const maxZ = params.draggables.length
|
|
111
|
+
view1.zIndex = maxZ + 1
|
|
112
|
+
view2.zIndex = maxZ
|
|
113
|
+
|
|
114
|
+
view1.animate({
|
|
115
|
+
...args, left: dest1Left, top: dest1Top, transform: Ti.UI.createMatrix2D()
|
|
116
|
+
}, () => {
|
|
117
|
+
view1.applyProperties({ left: dest1Left, top: dest1Top, transform: Ti.UI.createMatrix2D() })
|
|
118
|
+
params.draggables.forEach((d, k) => { d.zIndex = k })
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
view2.animate({
|
|
122
|
+
...args, left: dest2Left, top: dest2Top
|
|
123
|
+
}, () => {
|
|
124
|
+
view2.applyProperties({ left: dest2Left, top: dest2Top })
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
view1._originTop = dest1Top
|
|
128
|
+
view1._originLeft = dest1Left
|
|
129
|
+
view2._originTop = dest2Top
|
|
130
|
+
view2._originLeft = dest2Left
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
animationView.sequence = (_views, _cb) => {
|
|
134
|
+
if (params.debug) { console.log('') }
|
|
135
|
+
logger('`sequence` method called on: ' + params.id)
|
|
136
|
+
const views = Array.isArray(_views) ? _views : [_views]
|
|
137
|
+
const total = views.length
|
|
138
|
+
|
|
139
|
+
params.open = !params.open
|
|
140
|
+
chooseAnimationBasedOnState('play')
|
|
141
|
+
|
|
142
|
+
function animateNext(index) {
|
|
143
|
+
if (index >= total) { return }
|
|
144
|
+
const isLast = index === total - 1
|
|
145
|
+
playView(views[index], (e) => {
|
|
146
|
+
if (isLast && typeof _cb === 'function') {
|
|
147
|
+
_cb(e)
|
|
148
|
+
} else {
|
|
149
|
+
animateNext(index + 1)
|
|
150
|
+
}
|
|
151
|
+
}, 'play', index, total)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
animateNext(0)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
animationView.shake = (view, intensity = 10) => {
|
|
158
|
+
if (params.debug) { console.log('') }
|
|
159
|
+
logger('`shake` method called on: ' + params.id)
|
|
160
|
+
if (!view) { return notFound() }
|
|
161
|
+
|
|
162
|
+
view.applyProperties({ transform: Ti.UI.createMatrix2D().translate(-intensity, 0) })
|
|
163
|
+
|
|
164
|
+
view.animate({
|
|
165
|
+
...args,
|
|
166
|
+
transform: Ti.UI.createMatrix2D().translate(intensity, 0),
|
|
167
|
+
duration: Math.round((args.duration ?? 400) / 6),
|
|
168
|
+
autoreverse: true,
|
|
169
|
+
repeat: 3,
|
|
170
|
+
curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT
|
|
171
|
+
}, () => {
|
|
172
|
+
view.applyProperties({ transform: Ti.UI.createMatrix2D() })
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
animationView.pulse = (view, count = 1) => {
|
|
177
|
+
if (params.debug) { console.log('') }
|
|
178
|
+
logger('`pulse` method called on: ' + params.id)
|
|
179
|
+
if (!view) { return notFound() }
|
|
180
|
+
|
|
181
|
+
view.animate({
|
|
182
|
+
...args,
|
|
183
|
+
transform: args.transform ?? Ti.UI.createMatrix2D().scale(1.2),
|
|
184
|
+
autoreverse: true,
|
|
185
|
+
repeat: count,
|
|
186
|
+
curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT
|
|
187
|
+
}, () => {
|
|
188
|
+
view.applyProperties({ transform: Ti.UI.createMatrix2D() })
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
animationView.snapTo = (view, targets) => {
|
|
193
|
+
if (params.debug) { console.log('') }
|
|
194
|
+
logger('`snapTo` method called on: ' + params.id)
|
|
195
|
+
if (!view) { return notFound() }
|
|
196
|
+
|
|
197
|
+
const arr = Array.isArray(targets) ? targets : [targets]
|
|
198
|
+
const vr = view.rect
|
|
199
|
+
const vcx = (view._visualLeft ?? view.left) + vr.width / 2
|
|
200
|
+
const vcy = (view._visualTop ?? view.top) + vr.height / 2
|
|
201
|
+
|
|
202
|
+
let closest = null
|
|
203
|
+
let minDist = Infinity
|
|
204
|
+
|
|
205
|
+
arr.forEach(target => {
|
|
206
|
+
if (target === view) { return }
|
|
207
|
+
const tr = target.rect
|
|
208
|
+
const tcx = tr.x + tr.width / 2
|
|
209
|
+
const tcy = tr.y + tr.height / 2
|
|
210
|
+
const dist = Math.sqrt((vcx - tcx) ** 2 + (vcy - tcy) ** 2)
|
|
211
|
+
if (dist < minDist) {
|
|
212
|
+
minDist = dist
|
|
213
|
+
closest = target
|
|
214
|
+
}
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
if (!closest) { return null }
|
|
218
|
+
|
|
219
|
+
const cr = closest.rect
|
|
220
|
+
normalizePosition(closest)
|
|
221
|
+
const destLeft = closest._originLeft + (cr.width - vr.width) / 2
|
|
222
|
+
const destTop = closest._originTop + (cr.height - vr.height) / 2
|
|
223
|
+
|
|
224
|
+
view.animate({
|
|
225
|
+
...args, left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D()
|
|
226
|
+
}, () => {
|
|
227
|
+
view.applyProperties({ left: destLeft, top: destTop, transform: Ti.UI.createMatrix2D() })
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
view._originTop = destTop
|
|
231
|
+
view._originLeft = destLeft
|
|
232
|
+
|
|
233
|
+
return closest
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
animationView.reorder = (views, newOrder) => {
|
|
237
|
+
if (params.debug) { console.log('') }
|
|
238
|
+
logger('`reorder` method called on: ' + params.id)
|
|
239
|
+
const arr = Array.isArray(views) ? views : [views]
|
|
240
|
+
if (newOrder.length !== arr.length) { return }
|
|
241
|
+
|
|
242
|
+
arr.forEach(v => normalizePosition(v))
|
|
243
|
+
|
|
244
|
+
const positions = arr.map(v => ({
|
|
245
|
+
left: v._originLeft,
|
|
246
|
+
top: v._originTop
|
|
247
|
+
}))
|
|
248
|
+
|
|
249
|
+
arr.forEach((view, i) => {
|
|
250
|
+
const dest = positions[newOrder[i]]
|
|
251
|
+
|
|
252
|
+
view.animate({
|
|
253
|
+
...args, left: dest.left, top: dest.top, transform: Ti.UI.createMatrix2D()
|
|
254
|
+
}, () => {
|
|
255
|
+
view.applyProperties({ left: dest.left, top: dest.top, transform: Ti.UI.createMatrix2D() })
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
view._originTop = dest.top
|
|
259
|
+
view._originLeft = dest.left
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
animationView.undraggable = (_views) => {
|
|
264
|
+
if (params.debug) { console.log('') }
|
|
265
|
+
logger('`undraggable` method called on: ' + params.id)
|
|
266
|
+
const arr = Array.isArray(_views) ? _views : [_views]
|
|
267
|
+
|
|
268
|
+
arr.forEach(view => {
|
|
269
|
+
if (view._dragListeners) {
|
|
270
|
+
view.removeEventListener('touchstart', view._dragListeners.onTouchStart)
|
|
271
|
+
view.removeEventListener('touchend', view._dragListeners.onTouchEnd)
|
|
272
|
+
view.removeEventListener('touchmove', view._dragListeners.onTouchMove)
|
|
273
|
+
Ti.Gesture.removeEventListener('orientationchange', view._dragListeners.onOrientationChange)
|
|
274
|
+
delete view._dragListeners
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const idx = params.draggables.indexOf(view)
|
|
278
|
+
if (idx !== -1) { params.draggables.splice(idx, 1) }
|
|
279
|
+
|
|
280
|
+
const cIdx = params.collisionViews.indexOf(view)
|
|
281
|
+
if (cIdx !== -1) { params.collisionViews.splice(cIdx, 1) }
|
|
282
|
+
|
|
283
|
+
delete view._originTop
|
|
284
|
+
delete view._originLeft
|
|
285
|
+
delete view._visualTop
|
|
286
|
+
delete view._visualLeft
|
|
287
|
+
delete view._collisionEnabled
|
|
288
|
+
delete view._bouncingBack
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
|
|
44
292
|
animationView.open = (_views, _cb) => {
|
|
45
293
|
if (params.debug) { console.log('') }
|
|
46
294
|
logger('`open` method called on: ' + params.id)
|
|
@@ -53,6 +301,54 @@ function Animation(args = {}) {
|
|
|
53
301
|
mainPlayApplyFn(_views, _cb, 'play', 'close')
|
|
54
302
|
}
|
|
55
303
|
|
|
304
|
+
// Mac Catalyst note: Parent containers of transitioned views should use fixed
|
|
305
|
+
// dimensions (not Ti.UI.FILL). Resizable containers trigger a UIKit re-layout
|
|
306
|
+
// that distorts views with rotated Matrix2D transforms.
|
|
307
|
+
animationView.transition = (views, layouts) => {
|
|
308
|
+
if (params.debug) { console.log('') }
|
|
309
|
+
logger('`transition` method called on: ' + params.id)
|
|
310
|
+
|
|
311
|
+
const arr = Array.isArray(views) ? views : [views]
|
|
312
|
+
|
|
313
|
+
arr.forEach((view, i) => {
|
|
314
|
+
const layout = layouts[i]
|
|
315
|
+
|
|
316
|
+
if (!layout) {
|
|
317
|
+
view.animate(Ti.UI.createAnimation({ ...args, zIndex: 0, opacity: 0 }), () => {
|
|
318
|
+
view.applyProperties({ zIndex: 0, opacity: 0, transform: Ti.UI.createMatrix2D(), translation: { x: 0, y: 0 }, rotate: 0, scale: 1 })
|
|
319
|
+
})
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const tx = layout.translation?.x ?? 0
|
|
324
|
+
const ty = layout.translation?.y ?? 0
|
|
325
|
+
const rotate = layout.rotate ?? 0
|
|
326
|
+
const scale = layout.scale ?? 1
|
|
327
|
+
|
|
328
|
+
const transform = Ti.UI.createMatrix2D().translate(tx, ty).rotate(rotate).scale(scale)
|
|
329
|
+
|
|
330
|
+
const needsFadeIn = view.opacity === 0
|
|
331
|
+
|
|
332
|
+
if (layout.zIndex !== undefined) view.zIndex = layout.zIndex
|
|
333
|
+
|
|
334
|
+
const animation = Ti.UI.createAnimation({
|
|
335
|
+
...args,
|
|
336
|
+
transform
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
if (needsFadeIn) animation.opacity = 1
|
|
340
|
+
if (layout.width !== undefined) animation.width = layout.width
|
|
341
|
+
if (layout.height !== undefined) animation.height = layout.height
|
|
342
|
+
if (layout.opacity !== undefined) animation.opacity = layout.opacity
|
|
343
|
+
|
|
344
|
+
view.animate(animation, () => {
|
|
345
|
+
const props = { transform, translation: { x: tx, y: ty }, rotate, scale, zIndex: layout.zIndex }
|
|
346
|
+
if (needsFadeIn) props.opacity = 1
|
|
347
|
+
view.applyProperties(props)
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
|
|
56
352
|
function handleTransformations(args) {
|
|
57
353
|
if ('anchorPoint' in args || 'rotate' in args || 'scale' in args) {
|
|
58
354
|
logger(' -> Creating transform')
|
|
@@ -124,19 +420,113 @@ function Animation(args = {}) {
|
|
|
124
420
|
let offsetX, offsetY
|
|
125
421
|
setBounds(draggableView, args.bounds)
|
|
126
422
|
|
|
127
|
-
|
|
423
|
+
const onTouchStart = (event) => {
|
|
128
424
|
offsetX = event.x
|
|
129
425
|
offsetY = event.y
|
|
426
|
+
draggableView._wasDragged = false
|
|
427
|
+
|
|
428
|
+
// If a bounce-back animation is still running, complete it immediately
|
|
429
|
+
if (draggableView._bouncingBack) {
|
|
430
|
+
logger(` -> completing pending bounce-back for ${draggableView.id}`)
|
|
431
|
+
draggableView.applyProperties({
|
|
432
|
+
top: draggableView._originTop,
|
|
433
|
+
left: draggableView._originLeft,
|
|
434
|
+
transform: Ti.UI.createMatrix2D()
|
|
435
|
+
})
|
|
436
|
+
draggableView._bouncingBack = false
|
|
437
|
+
}
|
|
130
438
|
|
|
131
439
|
updateDraggableZIndex(event)
|
|
132
440
|
checkDraggable(draggableView, 'drag')
|
|
133
|
-
})
|
|
134
441
|
|
|
135
|
-
|
|
442
|
+
if (draggableView._collisionEnabled) {
|
|
443
|
+
if (draggableView._originTop === undefined) {
|
|
444
|
+
draggableView._originTop = draggableView.top
|
|
445
|
+
draggableView._originLeft = draggableView.left
|
|
446
|
+
logger(` -> touchStart origin capture (first): ${draggableView.id} top=${draggableView.top} left=${draggableView.left}`)
|
|
447
|
+
} else {
|
|
448
|
+
logger(` -> touchStart origin kept: ${draggableView.id} origin=(${draggableView._originTop}, ${draggableView._originLeft}) vs top/left=(${draggableView.top}, ${draggableView.left})`)
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
136
452
|
|
|
137
|
-
|
|
453
|
+
const onTouchEnd = () => {
|
|
454
|
+
checkDraggable(draggableView, 'drop')
|
|
138
455
|
|
|
139
|
-
|
|
456
|
+
// Android: consolidate transform after drag so transition reads correct state
|
|
457
|
+
if (!params.isIOS && draggableView.translation) {
|
|
458
|
+
const { translation, rotate, scale } = draggableView
|
|
459
|
+
draggableView.applyProperties({
|
|
460
|
+
translation, rotate, scale,
|
|
461
|
+
transform: Ti.UI.createMatrix2D().translate(translation.x, translation.y).rotate(rotate ?? 0).scale(scale ?? 1)
|
|
462
|
+
})
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (draggableView._collisionEnabled) {
|
|
466
|
+
const directTarget = checkCollision(draggableView)
|
|
467
|
+
const target = directTarget ?? params.lastKnownTarget
|
|
468
|
+
logger(` -> collision check: ${draggableView.id} | direct: ${directTarget?.id ?? 'null'} | lastKnown: ${params.lastKnownTarget?.id ?? 'null'} | final: ${target?.id ?? 'null'}`)
|
|
469
|
+
if (target) {
|
|
470
|
+
// On Android, consolidate drag position before snap to avoid animation conflict
|
|
471
|
+
if (!params.isIOS) {
|
|
472
|
+
draggableView.applyProperties({
|
|
473
|
+
top: draggableView._visualTop ?? draggableView.top,
|
|
474
|
+
left: draggableView._visualLeft ?? draggableView.left
|
|
475
|
+
})
|
|
476
|
+
}
|
|
477
|
+
if (args.animationProperties?.snap?.center) {
|
|
478
|
+
logger(` -> snap-center: ${draggableView.id} to ${target.id}`)
|
|
479
|
+
animationView.snapTo(draggableView, [target])
|
|
480
|
+
}
|
|
481
|
+
if (params.dropCB) {
|
|
482
|
+
logger(` -> dropCB: ${draggableView.id} on ${target.id}`)
|
|
483
|
+
params.dropCB(draggableView, target)
|
|
484
|
+
}
|
|
485
|
+
} else if (!target && args.animationProperties?.snap?.back) {
|
|
486
|
+
logger(` -> bounce-back: ${draggableView.id} to (${draggableView._originTop}, ${draggableView._originLeft})`)
|
|
487
|
+
|
|
488
|
+
// On Android, consolidate drag position before bounce-back to avoid animation conflict
|
|
489
|
+
if (!params.isIOS) {
|
|
490
|
+
draggableView.applyProperties({
|
|
491
|
+
top: draggableView._visualTop ?? draggableView.top,
|
|
492
|
+
left: draggableView._visualLeft ?? draggableView.left
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
draggableView._bouncingBack = true
|
|
497
|
+
|
|
498
|
+
draggableView.animate({
|
|
499
|
+
...args,
|
|
500
|
+
top: draggableView._originTop,
|
|
501
|
+
left: draggableView._originLeft,
|
|
502
|
+
transform: Ti.UI.createMatrix2D()
|
|
503
|
+
}, () => {
|
|
504
|
+
draggableView._bouncingBack = false
|
|
505
|
+
draggableView.applyProperties({
|
|
506
|
+
top: draggableView._originTop,
|
|
507
|
+
left: draggableView._originLeft,
|
|
508
|
+
transform: Ti.UI.createMatrix2D()
|
|
509
|
+
})
|
|
510
|
+
logger(` -> bounce-back complete: ${draggableView.id}`)
|
|
511
|
+
})
|
|
512
|
+
}
|
|
513
|
+
params.lastHoverTarget = null
|
|
514
|
+
params.lastKnownTarget = null
|
|
515
|
+
if (params.dragCB) {
|
|
516
|
+
params.dragCB(draggableView, null)
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const onTouchMove = (event) => handleTouchMove(event, draggableView, offsetX, offsetY)
|
|
522
|
+
const onOrientationChange = () => checkBoundaries(draggableView)
|
|
523
|
+
|
|
524
|
+
draggableView._dragListeners = { onTouchStart, onTouchEnd, onTouchMove, onOrientationChange }
|
|
525
|
+
|
|
526
|
+
draggableView.addEventListener('touchend', onTouchEnd)
|
|
527
|
+
draggableView.addEventListener('touchmove', onTouchMove)
|
|
528
|
+
draggableView.addEventListener('touchstart', onTouchStart)
|
|
529
|
+
Ti.Gesture.addEventListener('orientationchange', onOrientationChange)
|
|
140
530
|
|
|
141
531
|
params.draggables.push(draggableView)
|
|
142
532
|
} else {
|
|
@@ -145,6 +535,7 @@ function Animation(args = {}) {
|
|
|
145
535
|
}
|
|
146
536
|
|
|
147
537
|
function handleTouchMove(event, draggableView, offsetX, offsetY) {
|
|
538
|
+
draggableView._wasDragged = true
|
|
148
539
|
const convertedPoint = draggableView.convertPointToView({ x: event.x, y: event.y }, draggableView.parent)
|
|
149
540
|
let top = Math.round(convertedPoint.y - offsetY)
|
|
150
541
|
let left = Math.round(convertedPoint.x - offsetX)
|
|
@@ -166,11 +557,63 @@ function Animation(args = {}) {
|
|
|
166
557
|
}
|
|
167
558
|
}
|
|
168
559
|
|
|
560
|
+
draggableView._visualTop = top
|
|
561
|
+
draggableView._visualLeft = left
|
|
562
|
+
|
|
169
563
|
if (params.isIOS) {
|
|
170
|
-
const
|
|
171
|
-
|
|
564
|
+
const r = draggableView.rotate ?? 0
|
|
565
|
+
const s = draggableView.scale ?? 1
|
|
566
|
+
|
|
567
|
+
if (r !== 0 || s !== 1) {
|
|
568
|
+
// Delta-based drag for transformed views (preserves rotate/scale)
|
|
569
|
+
const translation = draggableView.translation ?? { x: 0, y: 0 }
|
|
570
|
+
const deltaX = Math.round((event.x - offsetX) * s)
|
|
571
|
+
const deltaY = Math.round((event.y - offsetY) * s)
|
|
572
|
+
translation.x += deltaX
|
|
573
|
+
translation.y += deltaY
|
|
574
|
+
draggableView.applyProperties({
|
|
575
|
+
translation, rotate: r, scale: s,
|
|
576
|
+
transform: Ti.UI.createMatrix2D().translate(translation.x, translation.y).rotate(r).scale(s)
|
|
577
|
+
})
|
|
578
|
+
} else {
|
|
579
|
+
// Standard drag for non-transformed views
|
|
580
|
+
const { x, y } = calculateTranslation(draggableView, draggableView.parent.rect, left, top)
|
|
581
|
+
draggableView.applyProperties({ duration: 0, transform: Ti.UI.createMatrix2D().translate(x, y) })
|
|
582
|
+
}
|
|
172
583
|
} else {
|
|
173
|
-
draggableView.
|
|
584
|
+
const r = draggableView.rotate ?? 0
|
|
585
|
+
const s = draggableView.scale ?? 1
|
|
586
|
+
|
|
587
|
+
if (r !== 0 || s !== 1) {
|
|
588
|
+
// Delta-based drag for transformed views on Android
|
|
589
|
+
const translation = draggableView.translation ?? { x: 0, y: 0 }
|
|
590
|
+
const deltaX = Math.round((event.x - offsetX) * s)
|
|
591
|
+
const deltaY = Math.round((event.y - offsetY) * s)
|
|
592
|
+
translation.x += deltaX
|
|
593
|
+
translation.y += deltaY
|
|
594
|
+
draggableView.animate(Ti.UI.createAnimation({
|
|
595
|
+
transform: Ti.UI.createMatrix2D().translate(translation.x, translation.y).rotate(r).scale(s),
|
|
596
|
+
duration: 0
|
|
597
|
+
}))
|
|
598
|
+
draggableView.translation = translation
|
|
599
|
+
draggableView.rotate = r
|
|
600
|
+
draggableView.scale = s
|
|
601
|
+
} else {
|
|
602
|
+
draggableView.animate(Ti.UI.createAnimation({ top, left, duration: 0 }))
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (draggableView._collisionEnabled && params.dragCB) {
|
|
607
|
+
try {
|
|
608
|
+
const target = checkCollision(draggableView)
|
|
609
|
+
if (target) { params.lastKnownTarget = target }
|
|
610
|
+
if (target !== params.lastHoverTarget) {
|
|
611
|
+
params.lastHoverTarget = target
|
|
612
|
+
params.dragCB(draggableView, target)
|
|
613
|
+
}
|
|
614
|
+
} catch (e) {
|
|
615
|
+
logger(` !! collision error in touchmove: ${e.message}`)
|
|
616
|
+
}
|
|
174
617
|
}
|
|
175
618
|
}
|
|
176
619
|
|
|
@@ -178,15 +621,15 @@ function Animation(args = {}) {
|
|
|
178
621
|
let x = left - parentViewRect.width / 2 + draggableView.rect.width / 2
|
|
179
622
|
let y = top - parentViewRect.height / 2 + draggableView.rect.height / 2
|
|
180
623
|
|
|
181
|
-
if (draggableView.left) {
|
|
624
|
+
if (draggableView.left != null) {
|
|
182
625
|
x = left - draggableView.left
|
|
183
|
-
} else if (draggableView.right) {
|
|
626
|
+
} else if (draggableView.right != null) {
|
|
184
627
|
x = left - (parentViewRect.width - draggableView.right - draggableView.rect.width)
|
|
185
628
|
}
|
|
186
629
|
|
|
187
|
-
if (draggableView.top) {
|
|
630
|
+
if (draggableView.top != null) {
|
|
188
631
|
y = top - draggableView.top
|
|
189
|
-
} else if (draggableView.bottom) {
|
|
632
|
+
} else if (draggableView.bottom != null) {
|
|
190
633
|
y = top - (parentViewRect.height - draggableView.bottom - draggableView.rect.height)
|
|
191
634
|
}
|
|
192
635
|
|
|
@@ -206,8 +649,14 @@ function Animation(args = {}) {
|
|
|
206
649
|
}
|
|
207
650
|
|
|
208
651
|
function updateDraggableZIndex(event) {
|
|
209
|
-
|
|
210
|
-
|
|
652
|
+
if (args.animationProperties?.keepZIndex) return
|
|
653
|
+
|
|
654
|
+
const source = realSourceView(event.source)
|
|
655
|
+
const idx = params.draggables.indexOf(source)
|
|
656
|
+
if (idx !== -1) {
|
|
657
|
+
params.draggables.push(params.draggables.splice(idx, 1)[0])
|
|
658
|
+
params.draggables.forEach((draggable, key) => { draggable.zIndex = key })
|
|
659
|
+
}
|
|
211
660
|
}
|
|
212
661
|
|
|
213
662
|
function realSourceView(_source) {
|
|
@@ -269,6 +718,26 @@ function Animation(args = {}) {
|
|
|
269
718
|
})
|
|
270
719
|
}
|
|
271
720
|
|
|
721
|
+
function checkCollision(draggableView) {
|
|
722
|
+
const top = draggableView._visualTop
|
|
723
|
+
const left = draggableView._visualLeft
|
|
724
|
+
if (left === null || left === undefined || top === null || top === undefined) {
|
|
725
|
+
return null
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const cy = top + draggableView.rect.height / 2
|
|
729
|
+
const cx = left + draggableView.rect.width / 2
|
|
730
|
+
|
|
731
|
+
for (const other of params.collisionViews) {
|
|
732
|
+
if (other === draggableView) { continue }
|
|
733
|
+
const r = other.rect
|
|
734
|
+
if (cx > r.x && cx < r.x + r.width && cy > r.y && cy < r.y + r.height) {
|
|
735
|
+
return other
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
return null
|
|
739
|
+
}
|
|
740
|
+
|
|
272
741
|
function checkDraggable(_view, _action) {
|
|
273
742
|
logger('Check Draggable')
|
|
274
743
|
logger(' -> `' + _action + '`')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "purgetss",
|
|
4
|
-
"version": "7.
|
|
4
|
+
"version": "7.5.0",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"purgetss": "bin/purgetss"
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
89
|
"@eslint/js": "^9.39.1",
|
|
90
|
-
"@fortawesome/fontawesome-free": "^7.
|
|
90
|
+
"@fortawesome/fontawesome-free": "^7.2.0",
|
|
91
91
|
"eslint": "^9.39.1",
|
|
92
92
|
"eslint-plugin-import": "^2.32.0",
|
|
93
93
|
"eslint-plugin-n": "^17.23.1",
|
|
@@ -103,17 +103,27 @@ export function combineAllValues(base, defaultTheme) {
|
|
|
103
103
|
const allValues = {}
|
|
104
104
|
|
|
105
105
|
// ! Custom Window, View and ImageView
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
// Merge extend values into theme (same as colors, spacing, etc.)
|
|
107
|
+
_.each(['Window', 'View', 'ImageView'], comp => {
|
|
108
|
+
if (configFile.theme.extend[comp]) {
|
|
109
|
+
configFile.theme[comp] = _.merge({}, configFile.theme[comp], configFile.theme.extend[comp])
|
|
110
|
+
delete configFile.theme.extend[comp]
|
|
111
|
+
}
|
|
112
|
+
// Normalize shorthand: { apply: '...' } → { default: { apply: '...' } }
|
|
113
|
+
if (configFile.theme[comp] && configFile.theme[comp].apply && !configFile.theme[comp].default) {
|
|
114
|
+
configFile.theme[comp] = { default: configFile.theme[comp] }
|
|
115
|
+
}
|
|
116
|
+
})
|
|
109
117
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
// Merge user config WITH defaults, then write back to configFile.theme
|
|
119
|
+
// so that downstream functions pick up the full merged object
|
|
120
|
+
configFile.theme.Window = _.merge({ default: { backgroundColor: '#FFFFFF' } }, configFile.theme.Window)
|
|
121
|
+
configFile.theme.ImageView = _.merge({ ios: { hires: true } }, configFile.theme.ImageView)
|
|
122
|
+
configFile.theme.View = _.merge({ default: { width: 'Ti.UI.SIZE', height: 'Ti.UI.SIZE' } }, configFile.theme.View)
|
|
113
123
|
|
|
114
|
-
allValues.
|
|
115
|
-
|
|
116
|
-
|
|
124
|
+
allValues.Window = configFile.theme.Window
|
|
125
|
+
allValues.ImageView = configFile.theme.ImageView
|
|
126
|
+
allValues.View = configFile.theme.View
|
|
117
127
|
|
|
118
128
|
// ! Width, height and margin properties
|
|
119
129
|
// INFO: sizingProperties: For glossary generator only... Do not move from this position.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -243,6 +243,28 @@ export function toggle() {
|
|
|
243
243
|
return convertedStyles
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Snap properties for the Animation module
|
|
248
|
+
* @returns {string} Generated styles
|
|
249
|
+
*/
|
|
250
|
+
export function snap() {
|
|
251
|
+
let convertedStyles = processComments({
|
|
252
|
+
prop: 'snap - For the Animation module',
|
|
253
|
+
modules: 'Animation'
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
convertedStyles += '\'.snap-back\': { animationProperties: { snap: { back: true } } }\n'
|
|
257
|
+
convertedStyles += '\'.snap-back-false\': { animationProperties: { snap: { back: false } } }\n'
|
|
258
|
+
convertedStyles += '\'.snap-center\': { animationProperties: { snap: { center: true } } }\n'
|
|
259
|
+
convertedStyles += '\'.snap-center-false\': { animationProperties: { snap: { center: false } } }\n'
|
|
260
|
+
convertedStyles += '\'.snap-magnet\': { animationProperties: { snap: { magnet: true } } }\n'
|
|
261
|
+
convertedStyles += '\'.snap-magnet-false\': { animationProperties: { snap: { magnet: false } } }\n'
|
|
262
|
+
convertedStyles += '\'.keep-z-index\': { animationProperties: { keepZIndex: true } }\n'
|
|
263
|
+
convertedStyles += '\'.keep-z-index-false\': { animationProperties: { keepZIndex: false } }\n'
|
|
264
|
+
|
|
265
|
+
return convertedStyles
|
|
266
|
+
}
|
|
267
|
+
|
|
246
268
|
/**
|
|
247
269
|
* Dragging type property
|
|
248
270
|
* @returns {string} Generated styles
|