diff --git a/Package.swift b/Package.swift index 59c18dd..0bd7c8a 100644 --- a/Package.swift +++ b/Package.swift @@ -15,8 +15,8 @@ let package = Package( targets: [ .binaryTarget( name: "Pow", - url: "https://packages.movingparts.io/binaries/pow/0.1.1/Pow.xcframework.zip", - checksum: "5ae07875130ecb40d9310460b13da6aaa6f783d1e6e9af88b7c96a1ba32fd22a" + url: "https://packages.movingparts.io/binaries/pow/0.2.0/Pow.xcframework.zip", + checksum: "a3b2f1b8714002631293dec6087068017e1b3744f4d462c99a5c385abcbcd600" ), ] ) diff --git a/README.md b/README.md index cc90e24..7a40dde 100644 --- a/README.md +++ b/README.md @@ -51,20 +51,35 @@ likeButton - Parameters: - `origin`: The origin of the particles. + - `layer`: The `ParticleLayer` on which to render the effect, default is `local`. - `particles`: The particles to emit. ```swift -static func spray(origin: UnitPoint = .center, @ViewBuilder _ particles: () -> some View) -> AnyChangeEffect +static func spray(origin: UnitPoint = .center, layer: ParticleLayer = .local, @ViewBuilder _ particles: () -> some View) -> AnyChangeEffect ``` ### Haptic Feedback -Triggers the given haptic feedback type whenever a value changes. +Triggers haptic feedback to communicate successes, failures, and warnings whenever a value changes. -- `feedback`: The feedback type beiged triggered. +- `notification`: The feedback type to trigger. ```swift -static func hapticFeedback(_ feedback: UINotificationFeedbackGenerator.FeedbackType) -> AnyChangeEffect +static func feedback(hapticNotification type: UINotificationFeedbackGenerator.FeedbackType) -> AnyChangeEffect +``` + +Triggers haptic feedback to simulate physical impacts whenever a value changes. + +- `impact`: The feedback style to trigger. + +```swift +static func feedback(hapticImpact style: UIImpactFeedbackGenerator.FeedbackStyle) -> AnyChangeEffect +``` + +Triggers haptic feedback to indicate a change in selection whenever a value changes. + +```swift +static var feedbackHapticSelection: AnyChangeEffect ``` ### Jump @@ -114,10 +129,11 @@ An effect that emits the provided particles from the origin point and slowly flo - Parameters: - `origin`: The origin of the particle. + - `layer`: The `ParticleLayer` on which to render the effect, default is `local`. - `particles`: The particles to emit. ```swift -static func rise(origin: UnitPoint = .center, @ViewBuilder _ particles: () -> some View) -> AnyChangeEffect +static func rise(origin: UnitPoint = .center, layer: ParticleLayer = .local, @ViewBuilder _ particles: () -> some View) -> AnyChangeEffect ``` ### Shake @@ -160,7 +176,7 @@ static func shine(duration: Double) -> AnyChangeEffect Highlights the view with a shine moving over the view. -The angle is relative to the current `layoutDirection`, such that 0° represents sweeping towards the trailing edge and 90° represents sweeping towards the top edge. +The angle is relative to the current `layoutDirection`, such that 0° represents sweeping towards the trailing edge and 90° represents sweeping towards the bottom edge. - Parameters: - `angle`: The angle of the animation. @@ -170,6 +186,20 @@ The angle is relative to the current `layoutDirection`, such that 0° represents static func shine(angle: Angle, duration: Double = 1.0) -> AnyChangeEffect ``` +### Sound Effect Feedback + +Triggers a sound effect as feedback whenever a value changes. + +This effect will not interrupt or duck any other audio that may currently playing. It may also not triggered based on the setting of the user's silent switch or playback device. + +To relay important information to the user, you should always accompany audio effects with visual cues. + +- `soundEffect`: The sound effect to trigger. + +```swift +static func feedback(_ soundEffect: SoundEffect) -> AnyChangeEffect +``` + ### Spin [Preview](https://movingparts.io/pow/#spin) @@ -192,6 +222,40 @@ Spins the view around the given axis when a change happens. static func spin(axis: (x: CGFloat, y: CGFloat, z: CGFloat), anchor: UnitPoint = .center, anchorZ: CGFloat = 0, perspective: CGFloat = 1 / 6) -> AnyChangeEffect ``` +### Delay + +Every change effect can be delayed to trigger the effect after some time. + +```swift +Button("Submit") { + <#code#> +} +.buttonStyle(.borderedProminent) +.disabled(name.isEmpty) +.changeEffect(.shine.delay(1), value: name.isEmpty, isEnabled: !name.isEmpty) +``` + +- Parameters: + - `delay`: The delay in seconds. + +```swift +func delay(_ delay: Double) -> AnyChangeEffect +``` + +## Particle Layer + +A particle layer is a context in which particle effects draw their particles. + +The `particleLayer(name:)` view modifier wraps the view in a particle layer with the given name. + +Particle effects such as `AnyChangeEffect.spray` can render their particles on this position in the view tree to avoid being clipped by their immediate ancestor. + +For example, certain `List` styles may clip their rows. Use `particleLayer(_:)` to render particles on top of the entire `List` or even its enclosing `NavigationStack`. + +```swift +func particleLayer(name: AnyHashable) -> some View +``` + ## Transitions All transitions are namespaced under the `movingParts` static variable, e.g. @@ -255,8 +319,9 @@ elastic deformation of the view. static var boing: AnyTransition ``` -A transition that moves the view away towards the specified edge, with -any overshoot resulting in an elastic deformation of the view. +A transition that moves the view from the specified edge on insertion, +and towards it on removal, with any overshoot resulting in an elastic +deformation of the view. ```swift static func boing(edge: Edge) -> AnyTransition @@ -340,8 +405,8 @@ A transitions that shows the view by combining a wipe with a colored streak. The angle is relative to the current `layoutDirection`, such that 0° -represents sweeping towards the leading edge on insertion and 90° -represents sweeping towards the top edge. +represents sweeping towards the trailing edge on insertion and 90° +represents sweeping towards the bottom edge. In this example, the removal of the view is using a glare with an exponential ease-in curve, combined with a anticipating scale animation, @@ -400,7 +465,7 @@ static func move(edge: Edge) -> AnyTransition A transition that moves the view at the specified angle. -The angle is relative to the current `layoutDirection`, such that 0° represents animating towards the leading edge on insertion and 90° represents inserting towards the top edge. +The angle is relative to the current `layoutDirection`, such that 0° represents animating towards the trailing edge on insertion and 90° represents inserting towards the bottom edge. In this example, the view insertion is animated by moving it towards the top trailing corner and the removal is animated by moving it towards the bottom edge. @@ -610,3 +675,17 @@ towards it on removal. ```swift static func wipe(edge: Edge, blurRadius: CGFloat = 0) -> AnyTransition ``` + +A transition using a sweep at the specified angle. + +The angle is relative to the current `layoutDirection`, such that 0° +represents sweeping towards the trailing edge on insertion and 90° +represents sweeping towards the bottom edge. + +- Parameters: + - `angle`: The angle of the animation. + - `blurRadius`: The radius of the blur applied to the mask. + +```swift +static func wipe(angle: Angle, blurRadius: CGFloat = 0) -> AnyTransition +```