Compare commits

...

25 commits
v0.3.1 ... main

Author SHA1 Message Date
Joe Fabisevich
1b4b1dda28
Fix ambiguous use of .pi (#83)
Some checks failed
Build / build (push) Has been cancelled
2026-02-20 10:10:51 -05:00
Itay Brenner
f650bd26c7
Set swift version (#80) 2025-02-18 13:52:15 -03:00
Itay Brenner
8381662164
Add badges to Readme.md (#76) 2025-02-18 13:47:40 -03:00
Joe Fabisevich
a504eb6d14
Adding custom WiggleRate, ShakeRate, and SpinRate options (#67) 2024-11-09 22:56:08 -05:00
Kabir Oberai
4f47e338c9
Fix SwiftPM build (#73) 2024-09-15 15:20:32 -04:00
Jakub Kiermasz
f2e23ad418
Start/stop engine when entering background/foreground (#70) 2024-08-12 14:45:25 -04:00
Adam McNight
f0d0f3e72d
Add tvOS support (#66) 2024-05-19 14:44:29 -04:00
Joe Fabisevich
5ac7140413
Adding custom phase length options for WiggleRate and ShakeRate (#62) 2024-05-19 14:33:56 -04:00
Nick Kohrn
ebf05a2239
[README] Fix Sound Effect Feedback Documentation (#64) 2024-04-06 12:13:48 -04:00
noahsmartin
392ad0d0b7
Add snapshots (#43) 2024-01-03 09:01:34 -08:00
noahsmartin
897afcde74
Add package (#50) 2023-12-26 17:31:16 -08:00
noahsmartin
76ced9f8e3
Update README.md (#56) 2023-12-26 14:56:08 -08:00
noahsmartin
fdc39e509c
Update gemfile (#54) 2023-12-25 20:48:44 -08:00
Robb Böhnke
cc014eba4b
Fix glow preventing hit tests (#53) 2023-12-15 23:55:55 -05:00
noahsmartin
75b716d86a
Build for release (#49) 2023-12-11 09:57:09 +01:00
noahsmartin
bff3dcfabe
Add build (#48) 2023-12-09 01:02:24 +01:00
Itay Brenner
c24472ed83
Fix ControlSize.extraLarge not available for Xcode lower than 15 (#47) 2023-12-05 10:03:05 -05:00
Vatsal Manot
bf6f133381
Fix compilation for visionOS (#44) 2023-12-03 13:19:32 -03:00
Joe Fabisevich
825e0f112a
Fixes crash when using smoke effect (#42) 2023-11-30 12:26:23 -05:00
noahsmartin
44654cbf40
Update example links (#41) 2023-11-30 12:11:17 -03:00
noahsmartin
f86f4ef25b
Update example README.md (#40) 2023-11-30 11:51:50 -03:00
ɥsoɾ
21f24ba77d
Update README.md (#39) 2023-11-30 07:57:27 -03:00
Joe Fabisevich
5b95fe95b0
Moving Pow to @emergetools (#36)
Co-authored-by: Robert Böhnke <robb@robb.is>
Co-authored-by: Kasper Lahti <kasper@lahti.email>
2023-11-29 12:08:53 -03:00
Robb Böhnke
d5dc8370f8
Update README.md
Pow is now free!
2023-10-17 15:54:43 +02:00
Nick Kohrn
241d6fee0b
Update README.md (#32) 2023-07-14 17:41:45 -07:00
218 changed files with 14232 additions and 198 deletions

21
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: Build
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: macos-14
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Select Xcode version
run: sudo xcode-select -s '/Applications/Xcode_16.1.0.app/Contents/Developer'
- name: Run fastlane
env:
EMERGE_API_TOKEN: ${{ secrets.EMERGE_API_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: bundle install && bundle exec fastlane build

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*.DS_Store
.build
.swiftpm

View file

@ -0,0 +1,61 @@
# 1.0 Update Guide
If you are moving from a version of Pow below 1.0.0 the first thing you'll notice is that Pow is now open source. 🎉🎉🎉
Previously Pow was a paid product, and now it is a a community project operated and sponsored by [Emerge Tools](https://github.com/EmergeTools).
---
> [!NOTE]
> Pow's version number has been bumped from 0.3.1 to 1.0.0, and despite this being a new major version there are **no breaking changes**.
>
> Now that the Pow project is run by EmergeTools you should use the URL https://github.com/EmergeTools/Pow rather than https://github.com/movingparts-io/Pow.
### Integrate Pow 1.0.0+ into your app.
If you've integrated Pow through Xcode's Package Dependencies you will need to update the Pow package dependency to point to 1.0.0.
If you're using the default Up to Next Major Version rule you may need to manually update the version number to 1.0.0. Going from 0.x.x to 1.0.0 is considered a major version update, so Xcode will not do it automatically on your behalf for fear of breaking changes.
![](./images/pow-version-updated-before.png)
When you set Pow to version 1.0.0 in your Package Dependencies list it will now look like this.
![](./images/pow-version-updated-after.png)
If you're using Swift Package Manager you should update the URL and version number of any references you have to Pow.
> Before
> ```swift
> .package(url: "https://github.com/movingparts-io/Pow", from: Version(0, 3, 1))
> ```
> After
> ```swift
> .package(url: "https://github.com/EmergeTools/Pow", from: Version(1, 0, 0))
> ```
Sometimes Swift Package Manager will show errors like this after upgrading a dependency.
![](./images/xcode-errors.png)
This is a long-standing issue with Xcode, not Pow. The solution of course is to close and re-open Xcode.
![](./images/pow-source-after-update.png)
To confirm that Pow has been updated you can look at the list of installed Swift Packages in your project's File Navigator. (The first tab of Xcode's left sidebar.) If everything has gone correctly you will see Pow 1.0.0, and now that the framework is open source you will also see all of the source code.
---
### Remove Pow's License
Now that Pow is free, you too are free to remove this line of code that would validate your purchase of a Pow license.
```swift
Pow.unlockPow(reason: .iDidBuyTheLicense)
```
---
And that's it, easy as 0.1, 0.2, 0.3. If you run into any problems upgrading please file an [issue](gihtub.com/EmergeTools/Pow/issues), we're more than happy to help.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View file

@ -0,0 +1,808 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
236B13462940BAFD0022AF1F /* CheckoutExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 236B13452940BAFD0022AF1F /* CheckoutExample.swift */; };
541356DC293E91A000EC0F1A /* SoundEffectsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541356DB293E91A000EC0F1A /* SoundEffectsExample.swift */; };
54135714293E941000EC0F1A /* pick.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135708293E93D600EC0F1A /* pick.m4a */; };
54135715293E941000EC0F1A /* reel.falling.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E4293E93D400EC0F1A /* reel.falling.m4a */; };
54135716293E941000EC0F1A /* latch1.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356EA293E93D400EC0F1A /* latch1.m4a */; };
54135717293E941000EC0F1A /* pick.falling.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E5293E93D400EC0F1A /* pick.falling.m4a */; };
54135718293E941000EC0F1A /* brush.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135704293E93D600EC0F1A /* brush.m4a */; };
54135719293E941000EC0F1A /* pop4.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356FF293E93D600EC0F1A /* pop4.m4a */; };
5413571A293E941000EC0F1A /* reel.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356DF293E93D400EC0F1A /* reel.m4a */; };
5413571B293E941000EC0F1A /* sparkle.rising.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F9293E93D500EC0F1A /* sparkle.rising.m4a */; };
5413571C293E941000EC0F1A /* wip.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356EB293E93D400EC0F1A /* wip.m4a */; };
5413571D293E941000EC0F1A /* tock.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F0293E93D500EC0F1A /* tock.m4a */; };
5413571E293E941000EC0F1A /* pick.flat.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356ED293E93D400EC0F1A /* pick.flat.m4a */; };
5413571F293E941000EC0F1A /* chime.falling.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5413570F293E93D700EC0F1A /* chime.falling.m4a */; };
54135720293E941000EC0F1A /* chime.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F7293E93D500EC0F1A /* chime.m4a */; };
54135721293E941000EC0F1A /* swipe.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135709293E93D600EC0F1A /* swipe.m4a */; };
54135722293E941000EC0F1A /* tick.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135705293E93D600EC0F1A /* tick.m4a */; };
54135723293E941000EC0F1A /* lock1.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135701293E93D600EC0F1A /* lock1.m4a */; };
54135724293E941000EC0F1A /* pick.rising.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135706293E93D600EC0F1A /* pick.rising.m4a */; };
54135725293E941000EC0F1A /* plop.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F6293E93D500EC0F1A /* plop.m4a */; };
54135726293E941000EC0F1A /* detach.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135710293E93D700EC0F1A /* detach.m4a */; };
54135727293E941000EC0F1A /* swish.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356FA293E93D500EC0F1A /* swish.m4a */; };
54135728293E941000EC0F1A /* snap.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135707293E93D600EC0F1A /* snap.m4a */; };
54135729293E941000EC0F1A /* drip.falling.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5413570C293E93D600EC0F1A /* drip.falling.m4a */; };
5413572A293E941000EC0F1A /* chime.rising.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E3293E93D400EC0F1A /* chime.rising.m4a */; };
5413572B293E941000EC0F1A /* notfound.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356EC293E93D400EC0F1A /* notfound.m4a */; };
5413572C293E941000EC0F1A /* pluck.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5413570E293E93D600EC0F1A /* pluck.m4a */; };
5413572D293E941000EC0F1A /* dial.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E9293E93D400EC0F1A /* dial.m4a */; };
5413572E293E941000EC0F1A /* shake.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E7293E93D400EC0F1A /* shake.m4a */; };
5413572F293E941000EC0F1A /* tink.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F1293E93D500EC0F1A /* tink.m4a */; };
54135730293E941000EC0F1A /* lock4.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F2293E93D500EC0F1A /* lock4.m4a */; };
54135731293E941000EC0F1A /* boop.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356FB293E93D500EC0F1A /* boop.m4a */; };
54135732293E941000EC0F1A /* drip.flat.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135713293E93D700EC0F1A /* drip.flat.m4a */; };
54135733293E941000EC0F1A /* latch2.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135702293E93D600EC0F1A /* latch2.m4a */; };
54135734293E941000EC0F1A /* lock2.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E1293E93D400EC0F1A /* lock2.m4a */; };
54135735293E941000EC0F1A /* pop5.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F5293E93D500EC0F1A /* pop5.m4a */; };
54135736293E941000EC0F1A /* latch4.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E8293E93D400EC0F1A /* latch4.m4a */; };
54135737293E941000EC0F1A /* glass.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135700293E93D600EC0F1A /* glass.m4a */; };
54135738293E941000EC0F1A /* zing.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356EE293E93D400EC0F1A /* zing.m4a */; };
54135739293E941000EC0F1A /* pong.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E2293E93D400EC0F1A /* pong.m4a */; };
5413573A293E941000EC0F1A /* drip.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135711293E93D700EC0F1A /* drip.m4a */; };
5413573B293E941000EC0F1A /* beep.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356FC293E93D500EC0F1A /* beep.m4a */; };
5413573C293E941000EC0F1A /* latch3.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F3293E93D500EC0F1A /* latch3.m4a */; };
5413573D293E941000EC0F1A /* reel.rising.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5413570D293E93D600EC0F1A /* reel.rising.m4a */; };
5413573E293E941000EC0F1A /* sparkle.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5413570A293E93D600EC0F1A /* sparkle.m4a */; };
5413573F293E941000EC0F1A /* sparkle.flat.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356FD293E93D500EC0F1A /* sparkle.flat.m4a */; };
54135740293E941000EC0F1A /* reel.flat.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356DE293E93D300EC0F1A /* reel.flat.m4a */; };
54135741293E941000EC0F1A /* pop2.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135703293E93D600EC0F1A /* pop2.m4a */; };
54135742293E941000EC0F1A /* chime.flat.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356EF293E93D500EC0F1A /* chime.flat.m4a */; };
54135743293E941000EC0F1A /* whop.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356FE293E93D500EC0F1A /* whop.m4a */; };
54135744293E941000EC0F1A /* drip.rising.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5413570B293E93D600EC0F1A /* drip.rising.m4a */; };
54135745293E941000EC0F1A /* ping.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F8293E93D500EC0F1A /* ping.m4a */; };
54135746293E941000EC0F1A /* lock3.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356F4293E93D500EC0F1A /* lock3.m4a */; };
54135747293E941000EC0F1A /* pop1.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54135712293E93D700EC0F1A /* pop1.m4a */; };
54135748293E941000EC0F1A /* sparkle.falling.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E6293E93D400EC0F1A /* sparkle.falling.m4a */; };
54135749293E941000EC0F1A /* pop3.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356E0293E93D400EC0F1A /* pop3.m4a */; };
5413574A293E941000EC0F1A /* biip.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 541356DD293E93D300EC0F1A /* biip.m4a */; };
546A298A292A31BB00A80DE2 /* PowExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A2989292A31BB00A80DE2 /* PowExampleApp.swift */; };
546A298C292A31BB00A80DE2 /* ExampleList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A298B292A31BB00A80DE2 /* ExampleList.swift */; };
546A298E292A31BC00A80DE2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 546A298D292A31BC00A80DE2 /* Assets.xcassets */; };
546A2991292A31BC00A80DE2 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 546A2990292A31BC00A80DE2 /* Preview Assets.xcassets */; };
546A299B292A332900A80DE2 /* AnvilExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A299A292A332900A80DE2 /* AnvilExample.swift */; };
546A299E292A335600A80DE2 /* PlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A299D292A335600A80DE2 /* PlaceholderView.swift */; };
546A29A0292A341700A80DE2 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A299F292A341700A80DE2 /* Example.swift */; };
546A29A2292A349900A80DE2 /* BlindsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29A1292A349900A80DE2 /* BlindsExample.swift */; };
546A29A4292A34A600A80DE2 /* ClockExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29A3292A34A600A80DE2 /* ClockExample.swift */; };
546A29A6292A355400A80DE2 /* BoingExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29A5292A355400A80DE2 /* BoingExample.swift */; };
546A29AA292A397100A80DE2 /* BlurExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29A9292A397100A80DE2 /* BlurExample.swift */; };
546A29AC292A3B9D00A80DE2 /* FilmExposureExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29AB292A3B9D00A80DE2 /* FilmExposureExample.swift */; };
546A29AE292A3D8900A80DE2 /* FlipExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29AD292A3D8900A80DE2 /* FlipExample.swift */; };
546A29B0292A3DA800A80DE2 /* FlickerExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29AF292A3DA800A80DE2 /* FlickerExample.swift */; };
546A29B2292A3ED800A80DE2 /* GlareExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29B1292A3ED800A80DE2 /* GlareExample.swift */; };
546A29B4292A401500A80DE2 /* PopExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29B3292A401500A80DE2 /* PopExample.swift */; };
546A29B6292A406E00A80DE2 /* IrisExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29B5292A406E00A80DE2 /* IrisExample.swift */; };
546A29B8292A40B000A80DE2 /* MoveExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29B7292A40AF00A80DE2 /* MoveExample.swift */; };
546A29BA292A40D800A80DE2 /* PoofExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29B9292A40D800A80DE2 /* PoofExample.swift */; };
546A29BC292A414A00A80DE2 /* SnapshotExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29BB292A414A00A80DE2 /* SnapshotExample.swift */; };
546A29BE292A41CF00A80DE2 /* VanishExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29BD292A41CF00A80DE2 /* VanishExample.swift */; };
546A29C0292A420F00A80DE2 /* SwooshExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29BF292A420E00A80DE2 /* SwooshExample.swift */; };
546A29C2292A431800A80DE2 /* WipeExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29C1292A431800A80DE2 /* WipeExample.swift */; };
546A29C6292A4BC100A80DE2 /* JumpExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29C5292A4BC100A80DE2 /* JumpExample.swift */; };
546A29C8292A4BFA00A80DE2 /* PingExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29C7292A4BFA00A80DE2 /* PingExample.swift */; };
546A29CA292A4DBD00A80DE2 /* RiseExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29C9292A4DBD00A80DE2 /* RiseExample.swift */; };
546A29CC292A559A00A80DE2 /* ShakeExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29CB292A559A00A80DE2 /* ShakeExample.swift */; };
546A29CE292A591F00A80DE2 /* ShineExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29CD292A591F00A80DE2 /* ShineExample.swift */; };
546A29D0292A676200A80DE2 /* SkidExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29CF292A676200A80DE2 /* SkidExample.swift */; };
546A29D2292A68E100A80DE2 /* SpinExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29D1292A68E100A80DE2 /* SpinExample.swift */; };
546A29D4292A6B1200A80DE2 /* SprayExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 546A29D3292A6B1200A80DE2 /* SprayExample.swift */; };
549BF5F5293642BC00B2DCCF /* SocialFeedExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 549BF5F4293642BC00B2DCCF /* SocialFeedExample.swift */; };
54A962302934CC4400BBD5FE /* GithubButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54A9622F2934CC4400BBD5FE /* GithubButton.swift */; };
54B7259729F9C70900C17B99 /* PushDownExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7259629F9C70900C17B99 /* PushDownExample.swift */; };
54F15E5029D598150054690B /* RepeatExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F15E4F29D598150054690B /* RepeatExample.swift */; };
54F15E5229D59A920054690B /* SmokeExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F15E5129D59A920054690B /* SmokeExample.swift */; };
54F15E5429D59D250054690B /* PulseExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F15E5329D59D250054690B /* PulseExample.swift */; };
54F15E5629D5A0D70054690B /* GlowExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F15E5529D5A0D70054690B /* GlowExample.swift */; };
B7A5DA8D2B0E853A0035FC0A /* Pow in Frameworks */ = {isa = PBXBuildFile; productRef = B7A5DA8C2B0E853A0035FC0A /* Pow */; };
FA13B8ED2B3BAF5600F58836 /* SnapshotPreferences in Frameworks */ = {isa = PBXBuildFile; productRef = FA13B8EC2B3BAF5600F58836 /* SnapshotPreferences */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
236B13452940BAFD0022AF1F /* CheckoutExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckoutExample.swift; sourceTree = "<group>"; };
541356DB293E91A000EC0F1A /* SoundEffectsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundEffectsExample.swift; sourceTree = "<group>"; };
541356DD293E93D300EC0F1A /* biip.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = biip.m4a; sourceTree = "<group>"; };
541356DE293E93D300EC0F1A /* reel.flat.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = reel.flat.m4a; sourceTree = "<group>"; };
541356DF293E93D400EC0F1A /* reel.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = reel.m4a; sourceTree = "<group>"; };
541356E0293E93D400EC0F1A /* pop3.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pop3.m4a; sourceTree = "<group>"; };
541356E1293E93D400EC0F1A /* lock2.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = lock2.m4a; sourceTree = "<group>"; };
541356E2293E93D400EC0F1A /* pong.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pong.m4a; sourceTree = "<group>"; };
541356E3293E93D400EC0F1A /* chime.rising.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = chime.rising.m4a; sourceTree = "<group>"; };
541356E4293E93D400EC0F1A /* reel.falling.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = reel.falling.m4a; sourceTree = "<group>"; };
541356E5293E93D400EC0F1A /* pick.falling.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pick.falling.m4a; sourceTree = "<group>"; };
541356E6293E93D400EC0F1A /* sparkle.falling.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = sparkle.falling.m4a; sourceTree = "<group>"; };
541356E7293E93D400EC0F1A /* shake.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = shake.m4a; sourceTree = "<group>"; };
541356E8293E93D400EC0F1A /* latch4.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = latch4.m4a; sourceTree = "<group>"; };
541356E9293E93D400EC0F1A /* dial.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = dial.m4a; sourceTree = "<group>"; };
541356EA293E93D400EC0F1A /* latch1.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = latch1.m4a; sourceTree = "<group>"; };
541356EB293E93D400EC0F1A /* wip.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = wip.m4a; sourceTree = "<group>"; };
541356EC293E93D400EC0F1A /* notfound.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = notfound.m4a; sourceTree = "<group>"; };
541356ED293E93D400EC0F1A /* pick.flat.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pick.flat.m4a; sourceTree = "<group>"; };
541356EE293E93D400EC0F1A /* zing.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = zing.m4a; sourceTree = "<group>"; };
541356EF293E93D500EC0F1A /* chime.flat.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = chime.flat.m4a; sourceTree = "<group>"; };
541356F0293E93D500EC0F1A /* tock.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = tock.m4a; sourceTree = "<group>"; };
541356F1293E93D500EC0F1A /* tink.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = tink.m4a; sourceTree = "<group>"; };
541356F2293E93D500EC0F1A /* lock4.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = lock4.m4a; sourceTree = "<group>"; };
541356F3293E93D500EC0F1A /* latch3.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = latch3.m4a; sourceTree = "<group>"; };
541356F4293E93D500EC0F1A /* lock3.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = lock3.m4a; sourceTree = "<group>"; };
541356F5293E93D500EC0F1A /* pop5.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pop5.m4a; sourceTree = "<group>"; };
541356F6293E93D500EC0F1A /* plop.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = plop.m4a; sourceTree = "<group>"; };
541356F7293E93D500EC0F1A /* chime.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = chime.m4a; sourceTree = "<group>"; };
541356F8293E93D500EC0F1A /* ping.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = ping.m4a; sourceTree = "<group>"; };
541356F9293E93D500EC0F1A /* sparkle.rising.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = sparkle.rising.m4a; sourceTree = "<group>"; };
541356FA293E93D500EC0F1A /* swish.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = swish.m4a; sourceTree = "<group>"; };
541356FB293E93D500EC0F1A /* boop.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = boop.m4a; sourceTree = "<group>"; };
541356FC293E93D500EC0F1A /* beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = beep.m4a; sourceTree = "<group>"; };
541356FD293E93D500EC0F1A /* sparkle.flat.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = sparkle.flat.m4a; sourceTree = "<group>"; };
541356FE293E93D500EC0F1A /* whop.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = whop.m4a; sourceTree = "<group>"; };
541356FF293E93D600EC0F1A /* pop4.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pop4.m4a; sourceTree = "<group>"; };
54135700293E93D600EC0F1A /* glass.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = glass.m4a; sourceTree = "<group>"; };
54135701293E93D600EC0F1A /* lock1.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = lock1.m4a; sourceTree = "<group>"; };
54135702293E93D600EC0F1A /* latch2.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = latch2.m4a; sourceTree = "<group>"; };
54135703293E93D600EC0F1A /* pop2.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pop2.m4a; sourceTree = "<group>"; };
54135704293E93D600EC0F1A /* brush.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = brush.m4a; sourceTree = "<group>"; };
54135705293E93D600EC0F1A /* tick.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = tick.m4a; sourceTree = "<group>"; };
54135706293E93D600EC0F1A /* pick.rising.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pick.rising.m4a; sourceTree = "<group>"; };
54135707293E93D600EC0F1A /* snap.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = snap.m4a; sourceTree = "<group>"; };
54135708293E93D600EC0F1A /* pick.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pick.m4a; sourceTree = "<group>"; };
54135709293E93D600EC0F1A /* swipe.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = swipe.m4a; sourceTree = "<group>"; };
5413570A293E93D600EC0F1A /* sparkle.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = sparkle.m4a; sourceTree = "<group>"; };
5413570B293E93D600EC0F1A /* drip.rising.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = drip.rising.m4a; sourceTree = "<group>"; };
5413570C293E93D600EC0F1A /* drip.falling.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = drip.falling.m4a; sourceTree = "<group>"; };
5413570D293E93D600EC0F1A /* reel.rising.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = reel.rising.m4a; sourceTree = "<group>"; };
5413570E293E93D600EC0F1A /* pluck.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pluck.m4a; sourceTree = "<group>"; };
5413570F293E93D700EC0F1A /* chime.falling.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = chime.falling.m4a; sourceTree = "<group>"; };
54135710293E93D700EC0F1A /* detach.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = detach.m4a; sourceTree = "<group>"; };
54135711293E93D700EC0F1A /* drip.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = drip.m4a; sourceTree = "<group>"; };
54135712293E93D700EC0F1A /* pop1.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = pop1.m4a; sourceTree = "<group>"; };
54135713293E93D700EC0F1A /* drip.flat.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = drip.flat.m4a; sourceTree = "<group>"; };
546A2986292A31BB00A80DE2 /* Pow Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Pow Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
546A2989292A31BB00A80DE2 /* PowExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowExampleApp.swift; sourceTree = "<group>"; };
546A298B292A31BB00A80DE2 /* ExampleList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleList.swift; sourceTree = "<group>"; };
546A298D292A31BC00A80DE2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
546A2990292A31BC00A80DE2 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
546A299A292A332900A80DE2 /* AnvilExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnvilExample.swift; sourceTree = "<group>"; };
546A299D292A335600A80DE2 /* PlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderView.swift; sourceTree = "<group>"; };
546A299F292A341700A80DE2 /* Example.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = "<group>"; };
546A29A1292A349900A80DE2 /* BlindsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlindsExample.swift; sourceTree = "<group>"; };
546A29A3292A34A600A80DE2 /* ClockExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClockExample.swift; sourceTree = "<group>"; };
546A29A5292A355400A80DE2 /* BoingExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoingExample.swift; sourceTree = "<group>"; };
546A29A9292A397100A80DE2 /* BlurExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurExample.swift; sourceTree = "<group>"; };
546A29AB292A3B9D00A80DE2 /* FilmExposureExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilmExposureExample.swift; sourceTree = "<group>"; };
546A29AD292A3D8900A80DE2 /* FlipExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlipExample.swift; sourceTree = "<group>"; };
546A29AF292A3DA800A80DE2 /* FlickerExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlickerExample.swift; sourceTree = "<group>"; };
546A29B1292A3ED800A80DE2 /* GlareExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlareExample.swift; sourceTree = "<group>"; };
546A29B3292A401500A80DE2 /* PopExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopExample.swift; sourceTree = "<group>"; };
546A29B5292A406E00A80DE2 /* IrisExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IrisExample.swift; sourceTree = "<group>"; };
546A29B7292A40AF00A80DE2 /* MoveExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveExample.swift; sourceTree = "<group>"; };
546A29B9292A40D800A80DE2 /* PoofExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PoofExample.swift; sourceTree = "<group>"; };
546A29BB292A414A00A80DE2 /* SnapshotExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotExample.swift; sourceTree = "<group>"; };
546A29BD292A41CF00A80DE2 /* VanishExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VanishExample.swift; sourceTree = "<group>"; };
546A29BF292A420E00A80DE2 /* SwooshExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwooshExample.swift; sourceTree = "<group>"; };
546A29C1292A431800A80DE2 /* WipeExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WipeExample.swift; sourceTree = "<group>"; };
546A29C5292A4BC100A80DE2 /* JumpExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JumpExample.swift; sourceTree = "<group>"; };
546A29C7292A4BFA00A80DE2 /* PingExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PingExample.swift; sourceTree = "<group>"; };
546A29C9292A4DBD00A80DE2 /* RiseExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiseExample.swift; sourceTree = "<group>"; };
546A29CB292A559A00A80DE2 /* ShakeExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShakeExample.swift; sourceTree = "<group>"; };
546A29CD292A591F00A80DE2 /* ShineExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShineExample.swift; sourceTree = "<group>"; };
546A29CF292A676200A80DE2 /* SkidExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkidExample.swift; sourceTree = "<group>"; };
546A29D1292A68E100A80DE2 /* SpinExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpinExample.swift; sourceTree = "<group>"; };
546A29D3292A6B1200A80DE2 /* SprayExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SprayExample.swift; sourceTree = "<group>"; };
549BF5F4293642BC00B2DCCF /* SocialFeedExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialFeedExample.swift; sourceTree = "<group>"; };
54A9622F2934CC4400BBD5FE /* GithubButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubButton.swift; sourceTree = "<group>"; };
54B7259629F9C70900C17B99 /* PushDownExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushDownExample.swift; sourceTree = "<group>"; };
54D37CAD292F9C4A00788E8A /* Pow-Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Pow-Example-Info.plist"; sourceTree = SOURCE_ROOT; };
54F15E4F29D598150054690B /* RepeatExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatExample.swift; sourceTree = "<group>"; };
54F15E5129D59A920054690B /* SmokeExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmokeExample.swift; sourceTree = "<group>"; };
54F15E5329D59D250054690B /* PulseExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PulseExample.swift; sourceTree = "<group>"; };
54F15E5529D5A0D70054690B /* GlowExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlowExample.swift; sourceTree = "<group>"; };
B7A5DA8A2B0E85260035FC0A /* Pow */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Pow; path = ..; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
546A2983292A31BB00A80DE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B7A5DA8D2B0E853A0035FC0A /* Pow in Frameworks */,
FA13B8ED2B3BAF5600F58836 /* SnapshotPreferences in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
5413566C293E917E00EC0F1A /* Sounds */ = {
isa = PBXGroup;
children = (
541356FC293E93D500EC0F1A /* beep.m4a */,
541356DD293E93D300EC0F1A /* biip.m4a */,
541356FB293E93D500EC0F1A /* boop.m4a */,
54135704293E93D600EC0F1A /* brush.m4a */,
5413570F293E93D700EC0F1A /* chime.falling.m4a */,
541356EF293E93D500EC0F1A /* chime.flat.m4a */,
541356F7293E93D500EC0F1A /* chime.m4a */,
541356E3293E93D400EC0F1A /* chime.rising.m4a */,
54135710293E93D700EC0F1A /* detach.m4a */,
541356E9293E93D400EC0F1A /* dial.m4a */,
5413570C293E93D600EC0F1A /* drip.falling.m4a */,
54135713293E93D700EC0F1A /* drip.flat.m4a */,
54135711293E93D700EC0F1A /* drip.m4a */,
5413570B293E93D600EC0F1A /* drip.rising.m4a */,
54135700293E93D600EC0F1A /* glass.m4a */,
541356EA293E93D400EC0F1A /* latch1.m4a */,
54135702293E93D600EC0F1A /* latch2.m4a */,
541356F3293E93D500EC0F1A /* latch3.m4a */,
541356E8293E93D400EC0F1A /* latch4.m4a */,
54135701293E93D600EC0F1A /* lock1.m4a */,
541356E1293E93D400EC0F1A /* lock2.m4a */,
541356F4293E93D500EC0F1A /* lock3.m4a */,
541356F2293E93D500EC0F1A /* lock4.m4a */,
541356EC293E93D400EC0F1A /* notfound.m4a */,
541356E5293E93D400EC0F1A /* pick.falling.m4a */,
541356ED293E93D400EC0F1A /* pick.flat.m4a */,
54135708293E93D600EC0F1A /* pick.m4a */,
54135706293E93D600EC0F1A /* pick.rising.m4a */,
541356F8293E93D500EC0F1A /* ping.m4a */,
541356F6293E93D500EC0F1A /* plop.m4a */,
5413570E293E93D600EC0F1A /* pluck.m4a */,
541356E2293E93D400EC0F1A /* pong.m4a */,
54135712293E93D700EC0F1A /* pop1.m4a */,
54135703293E93D600EC0F1A /* pop2.m4a */,
541356E0293E93D400EC0F1A /* pop3.m4a */,
541356FF293E93D600EC0F1A /* pop4.m4a */,
541356F5293E93D500EC0F1A /* pop5.m4a */,
541356E4293E93D400EC0F1A /* reel.falling.m4a */,
541356DE293E93D300EC0F1A /* reel.flat.m4a */,
541356DF293E93D400EC0F1A /* reel.m4a */,
5413570D293E93D600EC0F1A /* reel.rising.m4a */,
541356E7293E93D400EC0F1A /* shake.m4a */,
54135707293E93D600EC0F1A /* snap.m4a */,
541356E6293E93D400EC0F1A /* sparkle.falling.m4a */,
541356FD293E93D500EC0F1A /* sparkle.flat.m4a */,
5413570A293E93D600EC0F1A /* sparkle.m4a */,
541356F9293E93D500EC0F1A /* sparkle.rising.m4a */,
54135709293E93D600EC0F1A /* swipe.m4a */,
541356FA293E93D500EC0F1A /* swish.m4a */,
54135705293E93D600EC0F1A /* tick.m4a */,
541356F1293E93D500EC0F1A /* tink.m4a */,
541356F0293E93D500EC0F1A /* tock.m4a */,
541356FE293E93D500EC0F1A /* whop.m4a */,
541356EB293E93D400EC0F1A /* wip.m4a */,
541356EE293E93D400EC0F1A /* zing.m4a */,
);
path = Sounds;
sourceTree = "<group>";
};
546A297D292A31BB00A80DE2 = {
isa = PBXGroup;
children = (
B7A5DA8A2B0E85260035FC0A /* Pow */,
546A2988292A31BB00A80DE2 /* Pow Example */,
546A2987292A31BB00A80DE2 /* Products */,
B7A5DA8B2B0E853A0035FC0A /* Frameworks */,
);
sourceTree = "<group>";
};
546A2987292A31BB00A80DE2 /* Products */ = {
isa = PBXGroup;
children = (
546A2986292A31BB00A80DE2 /* Pow Example.app */,
);
name = Products;
sourceTree = "<group>";
};
546A2988292A31BB00A80DE2 /* Pow Example */ = {
isa = PBXGroup;
children = (
54D37CAD292F9C4A00788E8A /* Pow-Example-Info.plist */,
546A2989292A31BB00A80DE2 /* PowExampleApp.swift */,
546A298B292A31BB00A80DE2 /* ExampleList.swift */,
546A299D292A335600A80DE2 /* PlaceholderView.swift */,
54A9622F2934CC4400BBD5FE /* GithubButton.swift */,
546A299C292A332C00A80DE2 /* Examples */,
546A298D292A31BC00A80DE2 /* Assets.xcassets */,
5413566C293E917E00EC0F1A /* Sounds */,
546A298F292A31BC00A80DE2 /* Preview Content */,
);
path = "Pow Example";
sourceTree = "<group>";
};
546A298F292A31BC00A80DE2 /* Preview Content */ = {
isa = PBXGroup;
children = (
546A2990292A31BC00A80DE2 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
546A299C292A332C00A80DE2 /* Examples */ = {
isa = PBXGroup;
children = (
546A299F292A341700A80DE2 /* Example.swift */,
546A29C3292A4B9000A80DE2 /* Transitions */,
546A29C4292A4B9F00A80DE2 /* Change Effects */,
54F15E4E29D598020054690B /* Conditional Effects */,
549BF5F6293642BE00B2DCCF /* Screens */,
);
path = Examples;
sourceTree = "<group>";
};
546A29C3292A4B9000A80DE2 /* Transitions */ = {
isa = PBXGroup;
children = (
546A299A292A332900A80DE2 /* AnvilExample.swift */,
546A29A1292A349900A80DE2 /* BlindsExample.swift */,
546A29A9292A397100A80DE2 /* BlurExample.swift */,
546A29A5292A355400A80DE2 /* BoingExample.swift */,
546A29A3292A34A600A80DE2 /* ClockExample.swift */,
546A29AB292A3B9D00A80DE2 /* FilmExposureExample.swift */,
546A29AF292A3DA800A80DE2 /* FlickerExample.swift */,
546A29AD292A3D8900A80DE2 /* FlipExample.swift */,
546A29B1292A3ED800A80DE2 /* GlareExample.swift */,
546A29B5292A406E00A80DE2 /* IrisExample.swift */,
546A29B7292A40AF00A80DE2 /* MoveExample.swift */,
546A29B9292A40D800A80DE2 /* PoofExample.swift */,
546A29B3292A401500A80DE2 /* PopExample.swift */,
546A29CF292A676200A80DE2 /* SkidExample.swift */,
546A29BB292A414A00A80DE2 /* SnapshotExample.swift */,
546A29BF292A420E00A80DE2 /* SwooshExample.swift */,
546A29BD292A41CF00A80DE2 /* VanishExample.swift */,
546A29C1292A431800A80DE2 /* WipeExample.swift */,
);
path = Transitions;
sourceTree = "<group>";
};
546A29C4292A4B9F00A80DE2 /* Change Effects */ = {
isa = PBXGroup;
children = (
546A29C5292A4BC100A80DE2 /* JumpExample.swift */,
546A29C7292A4BFA00A80DE2 /* PingExample.swift */,
546A29C9292A4DBD00A80DE2 /* RiseExample.swift */,
546A29CB292A559A00A80DE2 /* ShakeExample.swift */,
546A29CD292A591F00A80DE2 /* ShineExample.swift */,
54F15E5529D5A0D70054690B /* GlowExample.swift */,
541356DB293E91A000EC0F1A /* SoundEffectsExample.swift */,
546A29D1292A68E100A80DE2 /* SpinExample.swift */,
546A29D3292A6B1200A80DE2 /* SprayExample.swift */,
54F15E5329D59D250054690B /* PulseExample.swift */,
);
path = "Change Effects";
sourceTree = "<group>";
};
549BF5F6293642BE00B2DCCF /* Screens */ = {
isa = PBXGroup;
children = (
236B13452940BAFD0022AF1F /* CheckoutExample.swift */,
549BF5F4293642BC00B2DCCF /* SocialFeedExample.swift */,
);
path = Screens;
sourceTree = "<group>";
};
54F15E4E29D598020054690B /* Conditional Effects */ = {
isa = PBXGroup;
children = (
54B7259629F9C70900C17B99 /* PushDownExample.swift */,
54F15E4F29D598150054690B /* RepeatExample.swift */,
54F15E5129D59A920054690B /* SmokeExample.swift */,
);
path = "Conditional Effects";
sourceTree = "<group>";
};
B7A5DA8B2B0E853A0035FC0A /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
546A2985292A31BB00A80DE2 /* Pow Example */ = {
isa = PBXNativeTarget;
buildConfigurationList = 546A2994292A31BC00A80DE2 /* Build configuration list for PBXNativeTarget "Pow Example" */;
buildPhases = (
546A2982292A31BB00A80DE2 /* Sources */,
546A2983292A31BB00A80DE2 /* Frameworks */,
546A2984292A31BB00A80DE2 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Pow Example";
packageProductDependencies = (
B7A5DA8C2B0E853A0035FC0A /* Pow */,
FA13B8EC2B3BAF5600F58836 /* SnapshotPreferences */,
);
productName = "Pow Example";
productReference = 546A2986292A31BB00A80DE2 /* Pow Example.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
546A297E292A31BB00A80DE2 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1410;
LastUpgradeCheck = 1500;
TargetAttributes = {
546A2985292A31BB00A80DE2 = {
CreatedOnToolsVersion = 14.1;
};
};
};
buildConfigurationList = 546A2981292A31BB00A80DE2 /* Build configuration list for PBXProject "Pow Example" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 546A297D292A31BB00A80DE2;
packageReferences = (
FA13B8EB2B3BAF5600F58836 /* XCRemoteSwiftPackageReference "SnapshotPreviews-iOS" */,
);
productRefGroup = 546A2987292A31BB00A80DE2 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
546A2985292A31BB00A80DE2 /* Pow Example */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
546A2984292A31BB00A80DE2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5413571B293E941000EC0F1A /* sparkle.rising.m4a in Resources */,
5413573D293E941000EC0F1A /* reel.rising.m4a in Resources */,
54135732293E941000EC0F1A /* drip.flat.m4a in Resources */,
54135721293E941000EC0F1A /* swipe.m4a in Resources */,
5413571E293E941000EC0F1A /* pick.flat.m4a in Resources */,
54135728293E941000EC0F1A /* snap.m4a in Resources */,
54135725293E941000EC0F1A /* plop.m4a in Resources */,
54135733293E941000EC0F1A /* latch2.m4a in Resources */,
5413573A293E941000EC0F1A /* drip.m4a in Resources */,
5413571D293E941000EC0F1A /* tock.m4a in Resources */,
546A2991292A31BC00A80DE2 /* Preview Assets.xcassets in Resources */,
5413571F293E941000EC0F1A /* chime.falling.m4a in Resources */,
54135731293E941000EC0F1A /* boop.m4a in Resources */,
54135742293E941000EC0F1A /* chime.flat.m4a in Resources */,
5413572E293E941000EC0F1A /* shake.m4a in Resources */,
5413571A293E941000EC0F1A /* reel.m4a in Resources */,
54135730293E941000EC0F1A /* lock4.m4a in Resources */,
54135734293E941000EC0F1A /* lock2.m4a in Resources */,
5413573B293E941000EC0F1A /* beep.m4a in Resources */,
54135720293E941000EC0F1A /* chime.m4a in Resources */,
54135716293E941000EC0F1A /* latch1.m4a in Resources */,
5413571C293E941000EC0F1A /* wip.m4a in Resources */,
54135746293E941000EC0F1A /* lock3.m4a in Resources */,
54135726293E941000EC0F1A /* detach.m4a in Resources */,
54135737293E941000EC0F1A /* glass.m4a in Resources */,
5413574A293E941000EC0F1A /* biip.m4a in Resources */,
5413573F293E941000EC0F1A /* sparkle.flat.m4a in Resources */,
54135749293E941000EC0F1A /* pop3.m4a in Resources */,
54135736293E941000EC0F1A /* latch4.m4a in Resources */,
54135745293E941000EC0F1A /* ping.m4a in Resources */,
54135747293E941000EC0F1A /* pop1.m4a in Resources */,
54135741293E941000EC0F1A /* pop2.m4a in Resources */,
54135748293E941000EC0F1A /* sparkle.falling.m4a in Resources */,
54135717293E941000EC0F1A /* pick.falling.m4a in Resources */,
54135727293E941000EC0F1A /* swish.m4a in Resources */,
54135724293E941000EC0F1A /* pick.rising.m4a in Resources */,
5413572A293E941000EC0F1A /* chime.rising.m4a in Resources */,
54135719293E941000EC0F1A /* pop4.m4a in Resources */,
5413572D293E941000EC0F1A /* dial.m4a in Resources */,
54135718293E941000EC0F1A /* brush.m4a in Resources */,
54135744293E941000EC0F1A /* drip.rising.m4a in Resources */,
5413573E293E941000EC0F1A /* sparkle.m4a in Resources */,
54135739293E941000EC0F1A /* pong.m4a in Resources */,
54135738293E941000EC0F1A /* zing.m4a in Resources */,
5413572B293E941000EC0F1A /* notfound.m4a in Resources */,
54135729293E941000EC0F1A /* drip.falling.m4a in Resources */,
54135735293E941000EC0F1A /* pop5.m4a in Resources */,
54135723293E941000EC0F1A /* lock1.m4a in Resources */,
54135714293E941000EC0F1A /* pick.m4a in Resources */,
5413573C293E941000EC0F1A /* latch3.m4a in Resources */,
5413572C293E941000EC0F1A /* pluck.m4a in Resources */,
546A298E292A31BC00A80DE2 /* Assets.xcassets in Resources */,
54135715293E941000EC0F1A /* reel.falling.m4a in Resources */,
54135740293E941000EC0F1A /* reel.flat.m4a in Resources */,
5413572F293E941000EC0F1A /* tink.m4a in Resources */,
54135743293E941000EC0F1A /* whop.m4a in Resources */,
54135722293E941000EC0F1A /* tick.m4a in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
546A2982292A31BB00A80DE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
546A298C292A31BB00A80DE2 /* ExampleList.swift in Sources */,
54F15E5229D59A920054690B /* SmokeExample.swift in Sources */,
546A29CE292A591F00A80DE2 /* ShineExample.swift in Sources */,
546A29C0292A420F00A80DE2 /* SwooshExample.swift in Sources */,
546A29BA292A40D800A80DE2 /* PoofExample.swift in Sources */,
546A29B2292A3ED800A80DE2 /* GlareExample.swift in Sources */,
546A29B6292A406E00A80DE2 /* IrisExample.swift in Sources */,
546A29A4292A34A600A80DE2 /* ClockExample.swift in Sources */,
546A29D2292A68E100A80DE2 /* SpinExample.swift in Sources */,
546A29BE292A41CF00A80DE2 /* VanishExample.swift in Sources */,
541356DC293E91A000EC0F1A /* SoundEffectsExample.swift in Sources */,
546A29C8292A4BFA00A80DE2 /* PingExample.swift in Sources */,
546A29C2292A431800A80DE2 /* WipeExample.swift in Sources */,
546A298A292A31BB00A80DE2 /* PowExampleApp.swift in Sources */,
549BF5F5293642BC00B2DCCF /* SocialFeedExample.swift in Sources */,
546A299E292A335600A80DE2 /* PlaceholderView.swift in Sources */,
54B7259729F9C70900C17B99 /* PushDownExample.swift in Sources */,
546A29D0292A676200A80DE2 /* SkidExample.swift in Sources */,
546A29C6292A4BC100A80DE2 /* JumpExample.swift in Sources */,
546A29AA292A397100A80DE2 /* BlurExample.swift in Sources */,
546A29A0292A341700A80DE2 /* Example.swift in Sources */,
54F15E5629D5A0D70054690B /* GlowExample.swift in Sources */,
236B13462940BAFD0022AF1F /* CheckoutExample.swift in Sources */,
546A29BC292A414A00A80DE2 /* SnapshotExample.swift in Sources */,
54A962302934CC4400BBD5FE /* GithubButton.swift in Sources */,
546A29B4292A401500A80DE2 /* PopExample.swift in Sources */,
546A29CC292A559A00A80DE2 /* ShakeExample.swift in Sources */,
546A29AE292A3D8900A80DE2 /* FlipExample.swift in Sources */,
546A29A6292A355400A80DE2 /* BoingExample.swift in Sources */,
54F15E5429D59D250054690B /* PulseExample.swift in Sources */,
546A299B292A332900A80DE2 /* AnvilExample.swift in Sources */,
546A29A2292A349900A80DE2 /* BlindsExample.swift in Sources */,
546A29AC292A3B9D00A80DE2 /* FilmExposureExample.swift in Sources */,
546A29B0292A3DA800A80DE2 /* FlickerExample.swift in Sources */,
54F15E5029D598150054690B /* RepeatExample.swift in Sources */,
546A29D4292A6B1200A80DE2 /* SprayExample.swift in Sources */,
546A29CA292A4DBD00A80DE2 /* RiseExample.swift in Sources */,
546A29B8292A40B000A80DE2 /* MoveExample.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
546A2992292A31BC00A80DE2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
546A2993292A31BC00A80DE2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
546A2995292A31BC00A80DE2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_ASSET_PATHS = "\"Pow Example/Preview Content\"";
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Pow-Example-Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Pow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "io.movingparts.Pow-Example.Debug";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
546A2996292A31BC00A80DE2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_ASSET_PATHS = "\"Pow Example/Preview Content\"";
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Pow-Example-Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Pow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "io.movingparts.Pow-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
546A2981292A31BB00A80DE2 /* Build configuration list for PBXProject "Pow Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
546A2992292A31BC00A80DE2 /* Debug */,
546A2993292A31BC00A80DE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
546A2994292A31BC00A80DE2 /* Build configuration list for PBXNativeTarget "Pow Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
546A2995292A31BC00A80DE2 /* Debug */,
546A2996292A31BC00A80DE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
FA13B8EB2B3BAF5600F58836 /* XCRemoteSwiftPackageReference "SnapshotPreviews-iOS" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/EmergeTools/SnapshotPreviews-iOS";
requirement = {
kind = exactVersion;
version = 0.10.21;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
B7A5DA8C2B0E853A0035FC0A /* Pow */ = {
isa = XCSwiftPackageProductDependency;
productName = Pow;
};
FA13B8EC2B3BAF5600F58836 /* SnapshotPreferences */ = {
isa = XCSwiftPackageProductDependency;
package = FA13B8EB2B3BAF5600F58836 /* XCRemoteSwiftPackageReference "SnapshotPreviews-iOS" */;
productName = SnapshotPreferences;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 546A297E292A31BB00A80DE2 /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "icon.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "disco.jpg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "mvp.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -0,0 +1,158 @@
import Pow
import MessageUI
import SwiftUI
struct ExampleList: View {
var body: some View {
List {
Section {
VStack(alignment: .leading, spacing: 12) {
Text("This is the official example app for Pow, the Surprise and Delight framework for SwiftUI.")
Text("Tap the individual examples to see the effects and transitions in action.")
Text("**Note:** While this app requires iOS 16, Pow itself supports iOS 15 and above.")
}
.font(.subheadline.leading(.loose))
.foregroundColor(.primary)
Link(destination: URL(string: "https://movingparts.io/pow")!) {
ViewThatFits {
Label("Pow Website", systemImage: "safari")
Label("Pow Website", systemImage: "safari")
Label("Pow Website", systemImage: "safari")
Label("Pow Website", systemImage: "safari")
}
}
Link(destination: URL(string: "https://github.com/movingparts-io/Pow-Examples")!) {
ViewThatFits {
Label("GitHub Repository for this App", systemImage: "terminal")
Label("GitHub Repo for this App", systemImage: "terminal")
Label("Repo for this App", systemImage: "terminal")
}
}
if MFMailComposeViewController.canSendMail() {
Link(destination: URL(string: "mailto:hello@movingparts.io")!) {
Label("Support", systemImage: "envelope")
}
}
}
Section {
SocialFeedExample.navigationLink
CheckoutExample.navigationLink
} header: {
Label("Screens", systemImage: "iphone")
} footer: {
Text("Pre-composed screens that show how to use Pow in context. Use them as inspiration for your app.")
}
Section {
PushDownExample.navigationLink
RepeatExample.navigationLink
SmokeExample.navigationLink
} header: {
Label("Conditional Effects", systemImage: "checklist")
} footer: {
Text("Conditional Effects are triggered continously, as long as a condition is met.")
}
Section {
GlowExample.navigationLink
PulseExample.navigationLink
JumpExample.navigationLink
PingExample.navigationLink
RiseExample.navigationLink
ShakeExample.navigationLink
ShineExample.navigationLink
SoundEffectExample.navigationLink
SpinExample.navigationLink
SprayExample.navigationLink
} header: {
Label("Change Effects", systemImage: "sparkles")
} footer: {
Text("Change Effects can be triggered whenever a value changes.")
}
Section {
Group {
AnvilExample.navigationLink
BlindsExample.navigationLink
BlurExample.navigationLink
BoingExample.navigationLink
ClockExample.navigationLink
FilmExposureExample.navigationLink
FlickerExample.navigationLink
FlipExample.navigationLink
GlareExample.navigationLink
}
Group {
IrisExample.navigationLink
MoveExample.navigationLink
PoofExample.navigationLink
PopExample.navigationLink
SkidExample.navigationLink
SnapshotExample.navigationLink
SwooshExample.navigationLink
VanishExample.navigationLink
WipeExample.navigationLink
}
} header: {
Label("Transitions", systemImage: "arrow.forward.square")
} footer: {
Text("Transitions use the existing SwiftUI `.transition(_:)` API.")
}
}
.navigationTitle("Pow Examples")
}
}
struct PresentInfoAction: Sendable {
var action: @MainActor (any Example.Type) -> ()
init(action: @escaping @MainActor (any Example.Type) -> Void) {
self.action = action
}
@MainActor func callAsFunction<T: Example>(_ type: T.Type) {
action(type)
}
}
extension EnvironmentValues {
struct PresentInfoActionKey: EnvironmentKey {
static let defaultValue: PresentInfoAction? = nil
}
var presentInfoAction: PresentInfoAction? {
get { self[PresentInfoActionKey.self] }
set { self[PresentInfoActionKey.self] = newValue }
}
}
struct InfoButton<T: Example>: View {
var type: T.Type
@Environment(\.presentInfoAction)
var presentInfoAction
var body: some View {
if let presentInfoAction {
Button {
presentInfoAction(type)
} label: {
Label("About", systemImage: "info.circle")
}
}
}
}
struct ExampleList_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
ExampleList()
}
}
}

View file

@ -0,0 +1,71 @@
import Pow
import SwiftUI
struct GlowExample: View, Example {
@State
var changes: Int = 0
var body: some View {
VStack {
// GroupBox {
// LabeledContent("Drawing Mode") {
// Picker("Drawing Mode", selection: $drawingMode) {
// Text("Fill").tag(AnyChangeEffect.PulseDrawingMode.fill)
// Text("Stroke").tag(AnyChangeEffect.PulseDrawingMode.stroke)
// }
// }
// }
// .padding(.horizontal)
Spacer()
ZStack {
PlaceholderView()
.overlay(alignment: .badgeAlignment) {
let shape = Capsule()
Text(changes.formatted())
.font(.body.bold().monospacedDigit())
.foregroundColor(.white)
.padding(.vertical, 8)
.padding(.horizontal, 16)
.background {
shape.fill(.pink)
.changeEffect(.glow(color: .pink, radius: 20), value: changes)
}
.alignmentGuide(HorizontalAlignment.badgeAlignment) { d in
d[HorizontalAlignment.center]
}
.alignmentGuide(VerticalAlignment.badgeAlignment) { d in
d[VerticalAlignment.center]
}
.allowsHitTesting(false)
}
}
Spacer()
}
.defaultBackground()
.onTapGesture {
changes += 1
}
}
static var description: some View {
Text("""
Makes the view glow whenever a value changes
- Parameters:
- `color`: The color to use.
- `radius`: The radius of the glow.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "dot.radiowaves.left.and.right")
}
static var newIn0_3_0: Bool { true }
}

View file

@ -0,0 +1,32 @@
import Pow
import SwiftUI
struct JumpExample: View, Example {
@State
var changes: Int = 0
var body: some View {
ZStack {
PlaceholderView()
.changeEffect(.jump(height: 40), value: changes)
}
.defaultBackground()
.onTapGesture {
changes += 1
}
}
static var description: some View {
Text("""
Makes the view jump the given height and then bounces a few times before settling.
- `height`: The height of the jump.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "figure.jumprope")
}
}

View file

@ -0,0 +1,79 @@
import Pow
import SwiftUI
struct PingExample: View, Example {
@State
var changes: Int = 0
var body: some View {
ZStack {
PlaceholderView()
.overlay(alignment: .badgeAlignment) {
let shape = Capsule()
Text(changes.formatted())
.font(.body.bold().monospacedDigit())
.foregroundColor(.white)
.padding(.vertical, 8)
.padding(.horizontal, 16)
.background {
shape.fill(.pink)
.changeEffect(.pulse(shape: shape, style: .pink, count: 3), value: changes)
}
.alignmentGuide(HorizontalAlignment.badgeAlignment) { d in
d[HorizontalAlignment.center]
}
.alignmentGuide(VerticalAlignment.badgeAlignment) { d in
d[VerticalAlignment.center]
}
}
}
.defaultBackground()
.onTapGesture {
changes += 1
}
}
static var description: some View {
Text("""
Adds one or more shapes that slowly grow and fade-out behind the view.
The shape will be colored by the current tint style.
-Parameters:
- `shape`: The shape to use for the effect.
- `style`: The style to use for the effect.
- `count`: The number of shapes to emit.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "dot.radiowaves.left.and.right")
}
}
extension VerticalAlignment {
struct BadgeAlignmentID: AlignmentID {
static func defaultValue(in d: ViewDimensions) -> CGFloat {
d[.top]
}
}
static let badgeAlignment = VerticalAlignment(BadgeAlignmentID.self)
}
extension HorizontalAlignment {
struct BadgeAlignmentID: AlignmentID {
static func defaultValue(in d: ViewDimensions) -> CGFloat {
d[.trailing]
}
}
static let badgeAlignment = HorizontalAlignment(BadgeAlignmentID.self)
}
extension Alignment {
static let badgeAlignment = Alignment(horizontal: .badgeAlignment, vertical: .badgeAlignment)
}

View file

@ -0,0 +1,79 @@
import Pow
import SwiftUI
struct PulseExample: View, Example {
@State
var changes: Int = 0
@State
var drawingMode: AnyChangeEffect.PulseDrawingMode = .fill
var body: some View {
VStack {
GroupBox {
LabeledContent("Drawing Mode") {
Picker("Drawing Mode", selection: $drawingMode) {
Text("Fill").tag(AnyChangeEffect.PulseDrawingMode.fill)
Text("Stroke").tag(AnyChangeEffect.PulseDrawingMode.stroke)
}
}
}
.padding(.horizontal)
Spacer()
ZStack {
PlaceholderView()
.overlay(alignment: .badgeAlignment) {
let shape = Capsule()
Text(changes.formatted())
.font(.body.bold().monospacedDigit())
.foregroundColor(.white)
.padding(.vertical, 8)
.padding(.horizontal, 16)
.background {
shape.fill(.pink)
.changeEffect(.pulse(shape: shape, style: .pink, drawingMode: drawingMode, count: 1), value: changes)
}
.alignmentGuide(HorizontalAlignment.badgeAlignment) { d in
d[HorizontalAlignment.center]
}
.alignmentGuide(VerticalAlignment.badgeAlignment) { d in
d[VerticalAlignment.center]
}
.allowsHitTesting(false)
}
}
Spacer()
}
.defaultBackground()
.onTapGesture {
changes += 1
}
}
static var description: some View {
Text("""
Adds one or more shapes that are emitted from the view.
By default, the shape will be colored in the current tint style.
- Parameters:
- `shape`: The shape to use for the effect.
- `style`: The style to use for the effect.
- `drawingMode` Changes between filled or stroked shapes. Default is `.fill`.
- `count`: The number of shapes to emit.
- `layer` The particle layer to use. Prevents the shape from being clipped by the parent view. (Optional)
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "dot.radiowaves.left.and.right")
}
static var newIn0_3_0: Bool { true }
}

View file

@ -0,0 +1,61 @@
import Pow
import SwiftUI
struct RiseExample: View, Example {
@State
var changes: Int = 0
var body: some View {
let colors = [Color.red, .orange, .yellow, .green, .blue, .indigo, .purple]
ZStack {
Label {
Text(changes.formatted())
.contentTransition(.identity)
.monospacedDigit()
.changeEffect(.rise {
// Rise will cycle through provided views
ForEach(colors, id: \.self) { color in
Text("+1")
.foregroundStyle(color.gradient)
.shadow(color: color.opacity(0.4), radius: 0.5, y: 0.5)
}
.font(.system(.body, design: .rounded, weight: .bold))
}, value: changes)
} icon: {
Image(systemName: "star.fill")
.foregroundStyle(
LinearGradient(colors: colors, startPoint: UnitPoint(x: 0.2, y: 0.2), endPoint: UnitPoint(x: 0.8, y: 0.8))
)
}
.padding(.vertical, 8)
.padding(.leading, 16)
.padding(.trailing, 20)
.background(.thinMaterial, in: Capsule())
.foregroundColor(.primary)
.font(.system(.title, design: .rounded, weight: .bold))
}
.defaultBackground()
.onTapGesture {
withAnimation {
changes += 1
}
}
}
static var description: some View {
Text("""
An effect that emits the provided particles from the origin point and slowly float up while moving side to side.
- Parameters:
- `origin`: The origin of the particle.
- `particles`: The particles to emit.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.up.and.down.and.sparkles")
}
}

View file

@ -0,0 +1,53 @@
import Pow
import SwiftUI
struct ShakeExample: View, Example {
@State var password = ""
@State var loginAttempts = 0
@State var isProcessing = false
var body: some View {
ZStack {
GroupBox("Sign In") {
VStack(alignment: .leading, spacing: 12) {
SecureField("Password", text: $password)
.changeEffect(.shake(rate: .fast), value: loginAttempts)
.onSubmit {
Task {
isProcessing = true
defer { isProcessing = false }
try? await Task.sleep(for: .seconds(1))
loginAttempts += 1
}
}
.disabled(isProcessing)
.textFieldStyle(.roundedBorder)
.changeEffect(.shake(rate: .fast), value: loginAttempts)
Text("Submit the form to see the effect.").font(.caption).foregroundColor(.secondary)
}
}
.frame(maxWidth: 320)
.padding(24)
}
.defaultBackground()
}
static var description: some View {
Text("""
An effect that shakes the view when a change happens.
- `rate`: The rate of the shake.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.left.arrow.right")
}
}

View file

@ -0,0 +1,54 @@
import Pow
import SwiftUI
struct ShineExample: View, Example {
@State var name = ""
var body: some View {
ZStack {
GroupBox("Sign In") {
TextField("Name", text: $name)
.textFieldStyle(.roundedBorder)
.padding(.bottom, 24)
Button {
} label: {
Spacer()
Text("Submit")
Spacer()
}
.disabled(name.isEmpty)
.changeEffect(.shine.delay(1), value: name.isEmpty, isEnabled: !name.isEmpty)
.buttonStyle(.borderedProminent)
}
.frame(maxWidth: 320)
.padding(24)
}
.defaultBackground()
.onTapGesture {
if name.isEmpty {
name = "Jay Appleseed"
}
}
}
static var description: some View {
Text("""
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.
- Parameters:
- `angle`: The angle of the animation.
- `duration`: The duration of the animation.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "sparkles")
}
}

View file

@ -0,0 +1,182 @@
import Pow
import SwiftUI
struct SoundEffectExample: View, Example {
var body: some View {
// All `SoundEffects` used here can be found in the
// `Pow Example/Sounds/` folder and are free to use with any licensed
// copy of Pow.
ScrollView {
VStack {
GroupBox("Alerts") {
HStack {
SoundEffectPad("Not Found", SoundEffect("notfound"))
SoundEffectPad("Pluck", SoundEffect("pluck"))
SoundEffectPad("Pong", SoundEffect("pong"))
SoundEffectPad("Ping", SoundEffect("ping"))
}
}
GroupBox("Blips") {
HStack {
SoundEffectPad("Boop", SoundEffect("boop"))
SoundEffectPad("Beep", SoundEffect("beep"))
SoundEffectPad("Biip", SoundEffect("biip"))
SoundEffectPad("Biip", SoundEffect("biip")).hidden()
}
}
GroupBox("Clicks & Plops") {
HStack {
SoundEffectPad("Dial", SoundEffect("dial"))
SoundEffectPad("Tock", SoundEffect("tock"))
SoundEffectPad("Plop", SoundEffect("plop"))
SoundEffectPad("Pop", SoundEffect("pop1", "pop2", "pop3", "pop4", "pop5"))
}
}
GroupBox("Drips") {
HStack {
SoundEffectPad("Drip", SoundEffect("drip"))
SoundEffectPad("Drip\nFlat", SoundEffect("drip.flat"))
SoundEffectPad("Drip\nRising", SoundEffect("drip.rising"))
SoundEffectPad("Drip\nFalling", SoundEffect("drip.falling"))
}
}
GroupBox("Glas") {
HStack {
SoundEffectPad("Tink", SoundEffect("tink"))
SoundEffectPad("Zing", SoundEffect("zing"))
SoundEffectPad("Glass", SoundEffect("glass"))
SoundEffectPad("Tick", SoundEffect("tick"))
}
}
GroupBox("Metal") {
HStack {
SoundEffectPad("Latch", SoundEffect("latch1", "latch2", "latch3", "latch4"))
SoundEffectPad("Lock", SoundEffect("lock1", "lock2", "lock3", "lock4"))
SoundEffectPad("Snap", SoundEffect("snap"))
SoundEffectPad("Snap", SoundEffect("snap")).hidden()
}
}
GroupBox("Notifications") {
HStack {
SoundEffectPad("Chime", SoundEffect("chime"))
SoundEffectPad("Chime\nFlat", SoundEffect("chime.flat"))
SoundEffectPad("Chime\nRising", SoundEffect("chime.rising"))
SoundEffectPad("Chime\nFalling", SoundEffect("chime.falling"))
}
HStack {
SoundEffectPad("Pick", SoundEffect("pick"))
SoundEffectPad("Pick\nFlat", SoundEffect("pick.flat"))
SoundEffectPad("Pick\nRising", SoundEffect("pick.rising"))
SoundEffectPad("Pick\nFalling", SoundEffect("pick.falling"))
}
}
GroupBox("Results") {
HStack {
SoundEffectPad("Sparkle", SoundEffect("sparkle"))
SoundEffectPad("Sparkle\nFlat", SoundEffect("sparkle.flat"))
SoundEffectPad("Sparkle\nRising", SoundEffect("sparkle.rising"))
SoundEffectPad("Sparkle\nFalling", SoundEffect("sparkle.falling"))
}
}
GroupBox("Tension/Release") {
HStack {
SoundEffectPad("Reel", SoundEffect("reel"))
SoundEffectPad("Reel\nFlat", SoundEffect("reel.flat"))
SoundEffectPad("Reel\nRising", SoundEffect("reel.rising"))
SoundEffectPad("Reel\nFalling", SoundEffect("reel.falling"))
}
}
GroupBox("Undo/Redo") {
HStack {
SoundEffectPad("Brush", SoundEffect("brush"))
SoundEffectPad("Shake", SoundEffect("shake"))
SoundEffectPad("Swipe", SoundEffect("swipe"))
SoundEffectPad("Swish", SoundEffect("swish"))
}
HStack {
SoundEffectPad("Wip", SoundEffect("wip"))
SoundEffectPad("Whooop", SoundEffect("whop"))
SoundEffectPad("Detach", SoundEffect("detach"))
SoundEffectPad("Detach", SoundEffect("detach")).hidden()
}
}
}
.padding()
}
.buttonStyle(SoundEffectButtonStyle())
.buttonStyle(.bordered)
}
static var description: some View {
Text("""
Triggers the playback of a sound.
- Parameters:
- `effect`: The `SoundEffect` to play back.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "speaker.wave.2")
}
static let newIn0_2_0: Bool = true
}
private struct SoundEffectPad: View {
var name: String
var effect: SoundEffect
init(_ name: String, _ effect: SoundEffect) {
self.name = name
self.effect = effect
}
@State
private var triggers = 0
var body: some View {
Button(name) {
triggers += 1
}
.changeEffect(.feedback(effect), value: triggers)
}
}
private struct SoundEffectButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.font(.caption2)
.padding(4)
.foregroundStyle(.secondary)
.background(.tertiary, in: RoundedRectangle(cornerRadius: 3, style: .continuous))
.overlay {
if configuration.isPressed {
Circle()
.fill(RadialGradient(colors: [.white, .white.opacity(0.0)], center: .center, startRadius: 0, endRadius: 30))
.opacity(0.5)
}
}
.frame(height: 64)
}
}
struct SoundEffectExample_Previews: PreviewProvider {
static var previews: some View {
SoundEffectExample()
}
}

View file

@ -0,0 +1,52 @@
import Pow
import SwiftUI
struct SpinExample: View, Example {
@State
var changes: Int = 0
var body: some View {
ZStack {
Label {
Text(changes.formatted())
.contentTransition(.identity)
.monospacedDigit()
} icon: {
Image(systemName: "hand.thumbsup.fill")
.foregroundStyle(.blue.gradient)
.changeEffect(.spin(axis: (0, 1, -0.05), anchor: UnitPoint(x: 0.5, y: 0.5), perspective: 0.6, rate: .fast), value: changes)
}
.padding(.vertical, 8)
.padding(.leading, 16)
.padding(.trailing, 24)
.background(.thinMaterial, in: Capsule(style: .continuous))
.foregroundColor(.primary)
.font(.system(.title, design: .rounded, weight: .bold))
}
.defaultBackground()
.onTapGesture {
withAnimation {
changes += 1
}
}
}
static var description: some View {
Text("""
Spins the view around the given axis when a change happens.
- Parameters:
- `axis`: The x, y and z elements that specify the axis of rotation.
- `anchor`: The location with a default of center that defines a point in 3D space about which the rotation is anchored.
- `anchorZ`: The location with a default of 0 that defines a point in 3D space about which the rotation is anchored.
- `perspective`: The relative vanishing point with a default of 1 / 6 for this rotation.
- `rate`: How fast the the view spins.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.clockwise")
}
}

View file

@ -0,0 +1,71 @@
import Pow
import SwiftUI
struct SprayExample: View, Example {
@State
var isFavorited: Bool = false
var body: some View {
ZStack {
Label {
let favoriteCount = isFavorited ? 143 : 142
Text(favoriteCount.formatted())
.contentTransition(.numericText())
.monospacedDigit()
} icon: {
ZStack {
Image(systemName: "heart")
.foregroundColor(.gray)
.fontWeight(.light)
.opacity(isFavorited ? 0 : 1)
Image(systemName: "heart.fill")
.foregroundStyle(.pink.gradient)
.scaleEffect(isFavorited ? 1 : 0.1, anchor: .center)
.opacity(isFavorited ? 1 : 0)
}
.changeEffect(.spray {
Group {
Image(systemName: "heart.fill")
Image(systemName: "sparkles")
}
.font(.title)
.foregroundStyle(.pink.gradient)
}, value: isFavorited, isEnabled: isFavorited)
}
.padding(.vertical, 8)
.padding(.leading, 16)
.padding(.trailing, 24)
.background {
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(.foreground)
.opacity(0.3)
}
.foregroundStyle(isFavorited ? .pink : .secondary)
.font(.system(.title, design: .rounded, weight: .semibold))
}
.defaultBackground()
.onTapGesture {
withAnimation(.movingParts.overshoot(duration: 0.4)) {
isFavorited.toggle()
}
}
}
static var description: some View {
Text("""
An effect that emits multiple particles in different shades and sizes moving up from the origin point.
- Parameters:
- `origin`: The origin of the particles.
- `particles`: The particles to emit.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "party.popper")
}
}

View file

@ -0,0 +1,45 @@
import Pow
import SwiftUI
struct PushDownExample: View, Example {
@State
var isPressed: Bool = false
var body: some View {
VStack {
Spacer()
Text("Push me")
.font(.system(.title, design: .rounded, weight: .semibold))
.blendMode(.destinationOut)
.padding()
.frame(maxWidth: .infinity)
.background(Color.accentColor.gradient, in: Capsule(style: .continuous))
._onButtonGesture {
isPressed = $0
} perform: {
}
.conditionalEffect(.pushDown, condition: isPressed)
.compositingGroup()
.padding()
Spacer()
}
.defaultBackground()
}
static var description: some View {
Text("""
Scales the view down as if pushed wile a condition is met.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.down.to.line.compact")
}
static var newIn0_3_0: Bool { true }
}

View file

@ -0,0 +1,58 @@
import Pow
import SwiftUI
struct RepeatExample: View, Example {
@State
var isEnabled: Bool = false
var body: some View {
VStack {
GroupBox {
Toggle("Enable Effect", isOn: $isEnabled.animation())
}
.padding(.horizontal)
Spacer()
Button {
} label: {
Label("Accept", systemImage: "phone.fill")
}
.tint(.green)
.disabled(!isEnabled)
.conditionalEffect(.repeat(.wiggle(rate: .fast), every: .seconds(2)), condition: isEnabled)
Button {
} label: {
Label("Update", systemImage: "sparkles")
}
.disabled(!isEnabled)
.conditionalEffect(.repeat(.shine, every: .seconds(2)), condition: isEnabled)
Spacer()
}
.controlSize(.large)
.buttonStyle(.borderedProminent)
.defaultBackground()
.autotoggle($isEnabled)
}
static var description: some View {
Text("""
Repeats an `AnyChangeEffect` at regular intervals.
- `effect`: The effect to repeat.
- `interval` The candence at which the effect is repeated.
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.counterclockwise")
}
static var newIn0_3_0: Bool { true }
}

View file

@ -0,0 +1,66 @@
import Pow
import SwiftUI
struct SmokeExample: View, Example {
@State
var isEnabled: Bool = false
var body: some View {
VStack {
GroupBox {
Toggle("Enable Effect", isOn: $isEnabled.animation())
}
.padding(.horizontal)
Spacer()
ZStack {
Circle()
.fill(.orange.gradient)
.brightness(-0.1)
Rectangle()
.fill(.white.gradient)
.mask {
ZStack {
Circle()
.strokeBorder(.white.opacity(0.8).gradient, lineWidth: 4)
.padding(6)
Image(systemName: "opticaldiscdrive.fill")
.imageScale(.large)
.font(.system(size: 40, weight: .black))
.offset(y: -2)
}
}
.blendMode(.lighten)
}
.compositingGroup()
.drawingGroup()
.frame(width: 120, height: 120)
.grayscale(isEnabled ? 0 : 1)
.conditionalEffect(.smoke(layer: .named("root")), condition: isEnabled)
Spacer()
}
.defaultBackground()
.autotoggle($isEnabled)
}
static var description: some View {
Text("""
Emmits smoke from behind the view.
- `layer` The particle layer to use. Prevents the smoke from being clipped by the parent view. (Optional)
""")
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "flame")
}
static var newIn0_3_0: Bool { true }
}

View file

@ -0,0 +1,217 @@
import SwiftUI
protocol Example: View {
associatedtype Description: View
init()
static var title: String { get }
@ViewBuilder
static var description: Description { get }
static var icon: Image? { get }
static var localPath: LocalPath { get }
static var newIn0_2_0: Bool { get }
static var newIn0_3_0: Bool { get }
}
extension Example {
static var title: String {
String(describing: type(of: self))
.replacingOccurrences(of: "Example.Type", with: "")
.reduce(into: "") { string, character in
if string.last?.isUppercase == false && character.isUppercase {
string.append(" ")
}
string.append(character)
}
}
@ViewBuilder
static var navigationLink: NavigationLink<some View, some View> {
NavigationLink {
ZStack {
Self()
.background()
.toolbar {
GithubButton(Self.localPath)
if type(of: Self.description) != EmptyView.self {
InfoButton(type: Self.self)
}
}
.navigationTitle(title)
}
} label: {
let colors = [Color.red, .orange, .yellow, .green, .blue, .indigo, .purple, .mint]
var rng = MinimalPCG(string: title)
Label {
Text(title)
.layoutPriority(1)
if newIn0_2_0 {
Spacer()
NewBadge("0.2.0")
}
if newIn0_3_0 {
Spacer()
NewBadge("0.3.0")
}
} icon: {
IconView {
icon ?? Image(systemName: "wand.and.stars.inverse")
}
.foregroundStyle(colors[Int(rng.next()) % colors.count].gradient)
}
}
}
static var icon: Image? { nil }
static var newIn0_2_0: Bool { false }
static var newIn0_3_0: Bool { false }
static var description: some View {
EmptyView()
}
static var erasedDescription: AnyView {
AnyView(description)
}
}
extension View {
func defaultBackground() -> some View {
self
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Rectangle().fill(.background).ignoresSafeArea())
.contentShape(Rectangle())
}
func autotoggle(_ binding: Binding<Bool>, with animation: Animation = .default) -> some View {
self
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
withAnimation(animation) {
binding.wrappedValue = true
}
}
}
}
}
struct NewBadge: View {
var version: String
init(_ version: String) {
self.version = version
}
var body: some View {
ViewThatFits {
Text("New in \(version)").fixedSize()
Text("\(version)").fixedSize()
}
.dynamicTypeSize(...DynamicTypeSize.accessibility1)
.font(.caption2.monospacedDigit())
.textCase(.uppercase)
.bold()
.foregroundStyle(.secondary)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(.thinMaterial, in: Capsule())
.overlay {
Capsule()
.stroke(.quaternary)
}
}
}
struct IconView<Content: View>: View {
var content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
@Environment(\.colorScheme)
var colorScheme
var body: some View {
ZStack {
Rectangle()
.fill(.primary)
.aspectRatio(1, contentMode: .fill)
.frame(width: 28, height: 28)
.brightness(colorScheme == .dark ? -0.2 : -0.03)
content
.foregroundStyle(.white)
}
.font(.system(size: 18))
.imageScale(.small)
.symbolRenderingMode(.monochrome)
.symbolVariant(.fill)
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
.overlay {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.strokeBorder(.white.opacity(0.1), lineWidth: 0.5)
.blendMode(.plusLighter)
}
}
}
struct LocalPath {
var path: String
init(path: String = #file) {
self.path = path
}
var url: URL {
URL(fileURLWithPath: path)
}
}
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
//
// Ported from https://www.pcg-random.org/download.html
private struct MinimalPCG {
var state: UInt64
var inc: UInt64
init(string: String) {
self.state = string.utf8.reduce(0.0) { a, b in a + (Double(b) * .pi) }.bitPattern
self.inc = (Double(string.count) * .pi).bitPattern
}
init(state: UInt64, inc: UInt64) {
self.state = state
self.inc = inc
}
mutating func next() -> UInt32 {
let oldstate = state
// Advance internal state
state = oldstate &* 6364136223846793005 &+ (inc | 1)
// Calculate output function (XSH RR), uses old state for max ILP
let xorshifted = ((oldstate >> 18) ^ oldstate) >> 27
let rot = Int(truncatingIfNeeded: oldstate >> 59)
return UInt32(truncatingIfNeeded: (xorshifted >> rot) | (xorshifted << ((-rot) & 31)))
}
}

View file

@ -0,0 +1,277 @@
import Pow
import SwiftUI
import SnapshotPreferences
struct CheckoutExample: View, Example {
enum PaymentError: Error {
case unknown
}
@State
var result: Result<Void, Error>?
@State
var quantity = 1
var body: some View {
List {
if case .success = result {
VStack(alignment: .leading) {
Text("Thank You For Your Order")
.font(.title2)
.bold()
Text("We'll notify you when your order has been sent.")
.font(.title3)
.foregroundStyle(.secondary)
}
.listRowSeparator(.hidden)
Spacer()
LabeledContent("Purchase Number", value: "P023121114")
} else {
VStack(alignment: .leading) {
Text("Checkout")
.font(.largeTitle)
.bold()
.accessibility(addTraits: .isHeader)
Text(quantity > 0 ? "1 Item" : "No Items")
.font(.title2)
.foregroundStyle(.secondary)
}
.listRowSeparator(.hidden)
Spacer()
Section {
if quantity > 0 {
CartItem(quantity: $quantity)
}
}
}
Spacer()
Section {
LabeledContent("Address", value: "jane.doe@example.com")
LabeledContent("Payment", value: "VISA")
}
}
.listStyle(.plain)
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.animation(.default, value: quantity != 0)
.toolbar {
if quantity == 0 {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Undo") {
quantity = 1
}
}
}
}
.changeEffect(.feedback(SoundEffect("whop")), value: quantity == 0, isEnabled: quantity == 0)
.changeEffect(.feedback(SoundEffect("wip")), value: quantity != 0, isEnabled: quantity != 0)
.safeAreaInset(edge: .bottom, spacing: 0) {
VStack(spacing: 16) {
VStack(alignment: .leading, spacing: 0) {
LabeledContent("Subtotal", value: 99 * quantity, format: .currency(code: "USD"))
.foregroundStyle(.secondary)
LabeledContent("Shipping", value: 0, format: .currency(code: "USD"))
.foregroundStyle(.secondary)
LabeledContent("Total", value: 99 * quantity, format: .currency(code: "USD"))
.fontWeight(.heavy)
}
PayButton {
let isFirstPayAttempt = result == nil
try? await Task.sleep(nanoseconds: 1_000_000_000)
if isFirstPayAttempt {
throw PaymentError.unknown
}
} completion: { payResult in
withAnimation {
result = payResult
}
}
.disabled(quantity == 0)
.changeEffect(.shine.delay(1), value: quantity != 0, isEnabled: quantity != 0)
}
.padding()
.background(.bar)
}
.labeledContentStyle(CheckoutLabeledContentStyle())
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "cart")
}
static let newIn0_2_0: Bool = true
}
private struct CartItem: View {
@Binding
var quantity: Int
@State
var lastQuantity: Int = 0
var body: some View {
HStack {
Stepper("Quantity", value: $quantity, in: 0...99)
.labelsHidden()
.alignmentGuide(.listRowSeparatorLeading) { dimensions in
dimensions[.leading]
}
.changeEffect(.feedback(SoundEffect("beep")), value: quantity, isEnabled: quantity > lastQuantity && quantity > 1)
.changeEffect(.feedback(SoundEffect("boop")), value: quantity, isEnabled: quantity < lastQuantity && quantity > 0)
.onChange(of: quantity) { newValue in
lastQuantity = quantity
}
Text(quantity, format: .number).monospacedDigit() + Text("×")
LabeledContent("Pow License", value: 99, format: .currency(code: "USD"))
}
}
}
struct PayButton: View {
var action: () async throws -> Void
var completion: (Result<Void, Error>) -> Void
enum Status {
case initial
case inProgress
case succeeded
case failed
}
@State
var status: Status = .initial
var body: some View {
Button {
status = .inProgress
Task {
do {
try await action()
status = .succeeded
completion(.success(()))
} catch {
status = .failed
try? await Task.sleep(nanoseconds: 1_500_000_000)
status = .initial
completion(.failure(error))
}
}
} label: {
HStack(spacing: 12) {
ZStack {
ProgressView()
.controlSize(.regular)
.tint(.white)
.opacity(status == .inProgress ? 1 : 0)
.animation(.spring(), value: status == .inProgress)
Image(systemName: "exclamationmark.triangle")
.opacity(status == .failed ? 1 : 0)
.animation(.spring(), value: status == .failed)
Checkmark()
.trim(from: 0, to: status == .succeeded ? 1 : 0)
.stroke(style: .init(lineWidth: 3, lineCap: .round, lineJoin: .round))
.padding(4)
.animation(.spring(response: 0.3), value: status == .succeeded)
}
.frame(width: 20, height: 20)
.imageScale(.large)
Spacer()
switch status {
case .initial:
Text("Pay")
case .inProgress:
Text("Paying…")
case .succeeded:
Text("Paid")
case .failed:
Text("Try Again")
}
Color.clear
.frame(width: 20, height: 20)
Spacer()
}
}
.font(.headline)
.buttonStyle(.borderedProminent)
.transformEnvironment(\.backgroundMaterial, transform: { material in
material = nil
})
.controlSize(.large)
.animation(.spring(response: 0.3), value: status == .inProgress)
.tint(status == .failed ? .red : status == .succeeded ? .green : nil)
.allowsHitTesting(status == .initial)
.changeEffect(.shake(rate: .fast), value: status == .failed, isEnabled: status == .failed)
.changeEffect(.feedback(SoundEffect("plop")), value: status == .inProgress, isEnabled: status == .inProgress)
.changeEffect(.feedback(SoundEffect("sparkle")), value: status == .succeeded, isEnabled: status == .succeeded)
.changeEffect(.feedback(SoundEffect("notfound")), value: status == .failed, isEnabled: status == .failed)
}
}
private struct Checkmark: Shape {
func path(in rect: CGRect) -> Path {
let insetFrame = rect
let referenceSize = CGSize(width: 67, height: 68)
let referencePoint1: CGPoint
let referencePoint2: CGPoint
let referencePoint3: CGPoint
referencePoint1 = CGPoint(x: 3.5, y: 36.5)
referencePoint2 = CGPoint(x: 25.5, y: 63.5)
referencePoint3 = CGPoint(x: 63, y: 5.5)
return Path { path in
path.move(to: CGPoint(x: insetFrame.width * referencePoint1.x / referenceSize.width, y: insetFrame.height * referencePoint1.y / referenceSize.height))
path.addLine(to: CGPoint(x: insetFrame.width * referencePoint2.x / referenceSize.width, y: insetFrame.width * referencePoint2.y / referenceSize.height))
path.addLine(to: CGPoint(x: insetFrame.width * referencePoint3.x / referenceSize.width, y: insetFrame.width * referencePoint3.y / referenceSize.height))
}
.offsetBy(dx: insetFrame.origin.x, dy: insetFrame.origin.y)
}
}
private struct CheckoutLabeledContentStyle: LabeledContentStyle {
func makeBody(configuration: Configuration) -> some View {
HStack(alignment: .firstTextBaseline) {
configuration.label
.font(.headline)
Spacer()
configuration.content
.font(.body)
.multilineTextAlignment(.trailing)
}
.padding(.vertical, 8)
.contentShape(Rectangle())
}
}
struct CheckoutExample_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
CheckoutExample()
.toolbar(.visible, for: .navigationBar)
}
.emergeSnapshotPrecision(0.99)
}
}

View file

@ -0,0 +1,261 @@
import Pow
import SwiftUI
struct SocialFeedExample: View, Example {
@State
var isLiked = false
@State
var isBoosted = false
@State
var clapCount = 202
@State
var isBookmarked = false
@State
var notificationCount: Int = 0
var body: some View {
ScrollView {
VStack(alignment: .trailing, spacing: 24) {
HStack(alignment: .top, spacing: 12) {
Image("mvp")
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(Circle())
.frame(width: 52, height: 52)
VStack(alignment: .leading, spacing: 6) {
VStack(alignment: .leading, spacing: 0) {
HStack(alignment: .firstTextBaseline) {
Text("Moving Parts").font(.headline.bold())
Spacer()
Text("12 min")
.font(.footnote)
.foregroundColor(.secondary)
}
Text("@movingpartsio").foregroundColor(.secondary)
}
.padding(.top, 3)
Text("Use Pow's Change Effects to give your buttons a little extra flair.")
Text("Try it on these buttons here:")
}
}
ViewThatFits {
buttonBar
.labelStyle(CustomButtonLabelStyle())
buttonBar
.labelStyle(.iconOnly)
}
.buttonStyle(.bordered)
.controlSize(.mini)
.tint(.gray)
.font(.footnote.weight(.medium).monospacedDigit())
}
.padding(12)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12, style: .continuous))
.padding(12)
}
.task {
try? await Task.sleep(for: .seconds(3))
withAnimation {
notificationCount += 1
}
}
.safeAreaInset(edge: .bottom, spacing: 0) {
tabBar
}
.navigationBarTitleDisplayMode(.inline)
}
var buttonBar: some View {
HStack(alignment: .firstTextBaseline, spacing: 12) {
let pop = SoundEffect("pop1", "pop2", "pop3", "pop4", "pop5")
Button {
isLiked.toggle()
} label: {
let likeCount = isLiked ? 144: 143
Label {
Text(likeCount.formatted())
} icon: {
Image(systemName: "heart.fill")
.changeEffect(
.spray {
Image(systemName: "heart.fill").foregroundStyle(.red)
},
value: likeCount,
isEnabled: isLiked
)
}
}
.tint(isLiked ? .red : .gray)
.changeEffect(.feedback(pop), value: isLiked, isEnabled: isLiked)
let sparkle = SoundEffect(isBoosted ? "sparkle.rising" : "sparkle.falling")
Button {
isBoosted.toggle()
} label: {
let boostCount = isBoosted ? 55 : 54
Label {
Text(boostCount.formatted())
} icon: {
Image(systemName: "arrow.3.trianglepath")
.changeEffect(
.rise {
Text("+1")
.font(.footnote.weight(.heavy))
.shadow(color: .green.opacity(0.5), radius: 1)
.foregroundStyle(.green.gradient)
},
value: boostCount,
isEnabled: isBoosted
)
}
}
.tint(isBoosted ? .green : .gray)
.changeEffect(.feedback(sparkle), value: isBoosted)
Button {
clapCount += 1
} label: {
Label {
Text(clapCount.formatted())
} icon: {
Image(systemName: "hands.clap.fill")
.changeEffect(
.spray {
Group {
Image(systemName: "circle.fill").foregroundColor(.red)
Image(systemName: "square.fill").foregroundColor(.green)
Image(systemName: "circle.fill").foregroundColor(.blue)
Image(systemName: "diamond.fill").foregroundColor(.orange)
Image(systemName: "triangle.fill").foregroundColor(.indigo)
}
.shadow(radius: 1)
.font(.caption.weight(.black))
},
value: clapCount
)
}
}
.changeEffect(.feedback(pop), value: clapCount)
.tint(clapCount > 202 ? .blue : .gray)
let pick = SoundEffect(isBookmarked ? "pick.rising" : "pick.falling")
Button {
isBookmarked.toggle()
} label: {
Label {
ZStack {
Text("Saved").hidden()
Text(isBookmarked ? "Saved" : "Save")
}
} icon: {
Image(systemName: "bookmark.fill")
}
}
.tint(isBookmarked ? .orange : .gray)
.animation(.spring(response: 0.4, dampingFraction: 1), value: isBookmarked)
.changeEffect(.feedback(pick), value: isBookmarked)
}
}
var tabBar: some View {
HStack {
Label("Home", systemImage: "house")
.labelStyle(SocialFeedTabBarLabelStyle(isSelected: true))
Label("Search", systemImage: "magnifyingglass")
Label {
Text("Notifications")
} icon: {
Image(systemName: "bell")
.overlay(alignment: .topTrailing) {
Text(notificationCount.formatted())
.fixedSize()
.font(.caption.monospacedDigit())
.foregroundColor(.white)
.padding(.vertical, 2)
.padding(.horizontal, 7)
.background(.red, in: Capsule())
.changeEffect(.pulse(shape: Capsule(), style: .red, count: 3), value: notificationCount)
.alignmentGuide(.top) { dimensions in
dimensions[VerticalAlignment.center] - 2
}
.alignmentGuide(.trailing) { dimensions in
dimensions[HorizontalAlignment.center]
}
.scaleEffect(notificationCount > 0 ? 1 : 0.1)
.opacity(notificationCount > 0 ? 1 : 0)
}
}
.onTapGesture {
withAnimation {
notificationCount += 1
}
}
Label {
Text("Archive")
} icon: {
Image(systemName: "archivebox")
.changeEffect(.jump(height: 50), value: isBookmarked, isEnabled: isBookmarked)
}
Label("Profile", systemImage: "person")
}
.labelStyle(SocialFeedTabBarLabelStyle(isSelected: false))
.padding(12)
.padding(.bottom, 2)
.background(.regularMaterial, in: Capsule(style: .continuous))
.padding(.horizontal)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "heart")
}
}
private struct SocialFeedTabBarLabelStyle: LabelStyle {
var isSelected: Bool
func makeBody(configuration: Configuration) -> some View {
VStack(spacing: 6) {
configuration.icon
.imageScale(.medium)
.symbolVariant(isSelected ? .fill : .none)
.font(.system(size: 22))
}
.foregroundStyle(isSelected ? AnyShapeStyle(.tint) : AnyShapeStyle(Color.primary))
.frame(maxWidth: .infinity)
}
}
private struct CustomButtonLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
HStack(spacing: 4) {
configuration.icon
configuration.title
.lineLimit(1)
.fixedSize(horizontal: true, vertical: false)
}
.frame(maxWidth: .infinity)
}
}

View file

@ -0,0 +1,29 @@
import Pow
import SwiftUI
struct AnvilExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(.movingParts.anvil)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "scalemass")
}
}

View file

@ -0,0 +1,29 @@
import Pow
import SwiftUI
struct BlindsExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(.movingParts.blinds)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "blinds.horizontal.open")
}
}

View file

@ -0,0 +1,29 @@
import Pow
import SwiftUI
struct BlurExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(.movingParts.blur.combined(with: .opacity))
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "drop")
}
}

View file

@ -0,0 +1,59 @@
import Pow
import SwiftUI
struct BoingExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
HStack {
if isVisible {
let defaultSpring = Animation.spring()
PlaceholderView()
.frame(maxWidth: 120, maxHeight: 120)
.transition(
.asymmetric(
insertion: .movingParts.boing(edge: .top).animation(defaultSpring),
removal: .movingParts.boing(edge: .top).animation(defaultSpring).combined(with: .opacity.animation(.easeInOut(duration: 0.2)))
)
)
let mediumSpring = Animation.interactiveSpring(dampingFraction: 0.5)
PlaceholderView()
.frame(maxWidth: 120, maxHeight: 120)
.transition(
.asymmetric(
insertion: .movingParts.boing(edge: .top).animation(mediumSpring),
removal: .movingParts.boing(edge: .top).animation(mediumSpring).combined(with: .opacity.animation(.easeInOut(duration: 0.2)))
)
)
let looseSpring = Animation.interpolatingSpring(stiffness: 100, damping: 8)
PlaceholderView()
.frame(maxWidth: 120, maxHeight: 120)
.transition(
.asymmetric(
insertion: .movingParts.boing(edge: .top).animation(looseSpring),
removal: .movingParts.boing(edge: .top).animation(looseSpring).combined(with: .opacity.animation(.easeInOut(duration: 0.2)))
)
)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "figure.jumprope")
}
}

View file

@ -0,0 +1,29 @@
import Pow
import SwiftUI
struct ClockExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(.movingParts.clock(blurRadius: 10))
}
}
.defaultBackground()
.onTapGesture {
withAnimation(.spring(dampingFraction: 1)) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: .spring(dampingFraction: 1))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "clock")
}
}

View file

@ -0,0 +1,40 @@
import Pow
import SwiftUI
struct FilmExposureExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
ZStack {
// Placeholder
Rectangle().fill(.black)
if isVisible {
Image("disco")
.resizable()
.zIndex(1)
.transition(.movingParts.filmExposure)
} else {
ProgressView()
.tint(.white)
}
}
.frame(width: 350, height: 525)
}
.defaultBackground()
.onTapGesture {
withAnimation(.easeInOut(duration: 1.8)) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: .easeInOut(duration: 1.8))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "film")
}
}

View file

@ -0,0 +1,29 @@
import Pow
import SwiftUI
struct FlickerExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(.movingParts.flicker)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "lightbulb")
}
}

View file

@ -0,0 +1,79 @@
import Pow
import SwiftUI
struct FlipExample: View, Example {
enum Variant: Hashable {
case flip
case standUp
case sideways
var transition: AnyTransition {
switch self {
case .flip: return .movingParts.flip
case .standUp: return .movingParts.rotate3D(.degrees(90), axis: (1, 0, 0), anchor: .bottom, perspective: 1 / 6)
case .sideways: return .movingParts.rotate3D(.degrees(90), axis: (0, 1, 0), perspective: 1 / 6)
}
}
}
@State
var variant: Variant = .flip
@State
var isVisible: Bool = false
var body: some View {
VStack {
GroupBox {
LabeledContent("Configuration") {
Picker("Configuration", selection: $variant) {
Text("Flip").tag(Variant.flip)
Text("Sideways").tag(Variant.sideways)
Text("Stand Up").tag(Variant.standUp)
}
}
}
.padding(.horizontal)
VStack {
if isVisible {
PlaceholderView()
.id(variant)
.transition(variant.transition)
}
}
.frame(maxHeight: .infinity)
.defaultBackground()
.onTapGesture {
withAnimation(animation) {
isVisible.toggle()
}
}
}
.defaultBackground()
.onChange(of: variant) { _ in
withAnimation(animation) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: animation)
}
var animation: Animation {
if isVisible {
return .easeIn
} else {
return .interactiveSpring(response: 0.4, dampingFraction: 0.4, blendDuration: 2.45)
}
}
static var title: String {
"Flip & Rotate3D"
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "rotate.3d")
}
}

View file

@ -0,0 +1,39 @@
import Pow
import SwiftUI
struct GlareExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(
.asymmetric(
insertion: .movingParts.glare(angle: .degrees(225), color: .white),
removal: .movingParts.glare(angle: .degrees(45), color: .white)
.animation(.movingParts.easeInExponential(duration: 0.9))
.combined(with:
.scale(scale: 1.4)
.animation(.movingParts.anticipate(duration: 0.9).delay(0.1))
)
)
)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "sun.max")
}
}

View file

@ -0,0 +1,30 @@
import Pow
import SwiftUI
struct IrisExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.compositingGroup()
.transition(.movingParts.iris(blurRadius: 10))
}
}
.defaultBackground()
.onTapGesture {
withAnimation(.spring(dampingFraction: 1)) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: .spring(dampingFraction: 1))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "camera.aperture")
}
}

View file

@ -0,0 +1,62 @@
import Pow
import SwiftUI
struct MoveExample: View, Example {
@State
var angle: Angle = .degrees(225)
@State
var isVisible: Bool = false
var body: some View {
VStack {
GroupBox {
LabeledContent {
Slider(value: $angle.degrees, in: 0 ... 360, step: 5)
} label: {
Text("Angle")
Spacer()
Text(Measurement(value: angle.degrees, unit: UnitAngle.degrees).formatted(.measurement(width: .narrow, numberFormatStyle: .number.precision(.fractionLength(0)))))
.foregroundColor(.secondary)
.font(.subheadline.monospacedDigit())
}
}
.padding(.horizontal)
VStack {
if isVisible {
PlaceholderView()
.compositingGroup()
.transition(.movingParts.move(angle: angle).combined(with: .opacity))
}
}
.defaultBackground()
.onTapGesture {
withAnimation(.spring(dampingFraction: 1)) {
isVisible.toggle()
}
}
}
.labeledContentStyle(VerticalLabeledContentStyle())
.defaultBackground()
.autotoggle($isVisible, with: .spring(dampingFraction: 1))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.up.left.and.down.right.and.arrow.up.right.and.down.left")
}
}
private struct VerticalLabeledContentStyle: LabeledContentStyle {
func makeBody(configuration: Configuration) -> some View {
VStack(alignment: .leading) {
HStack(alignment: .firstTextBaseline) {
configuration.label
}
configuration.content
}
}
}

View file

@ -0,0 +1,35 @@
import Pow
import SwiftUI
struct PoofExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.compositingGroup()
// Assign a random ID so that quick re-insertion will not
// play the poof transition backwards.
.id(UUID())
.transition(
.asymmetric(insertion: .opacity, removal: .movingParts.poof)
)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "trash")
}
}

View file

@ -0,0 +1,44 @@
import Pow
import SwiftUI
struct PopExample: View, Example {
@State
var isFavorited: Bool = false
var body: some View {
ZStack {
HStack {
if isFavorited {
Image(systemName: "heart.fill")
.foregroundColor(.red)
.transition(
.movingParts.pop(.red)
)
} else {
Image(systemName: "heart")
.foregroundColor(.gray)
.transition(.identity)
}
let favoriteCount = isFavorited ? 143 : 142
Text(favoriteCount.formatted())
.foregroundColor(isFavorited ? .red : .gray)
.animation(isFavorited ? .default.delay(0.4) : nil, value: isFavorited)
}
}
.defaultBackground()
.onTapGesture {
withAnimation(.spring(dampingFraction: 1)) {
isFavorited.toggle()
}
}
.autotoggle($isFavorited, with: .spring(dampingFraction: 1))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "rays")
}
}

View file

@ -0,0 +1,44 @@
import Pow
import SwiftUI
struct SkidExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
VStack {
if isVisible {
let overshoot = Animation.movingParts.overshoot(duration: 0.8)
PlaceholderView()
.frame(maxWidth: 120, maxHeight: 120)
.transition(.movingParts.skid(direction: .leading).animation(overshoot))
let mediumSpring = Animation.interactiveSpring(dampingFraction: 0.5)
PlaceholderView()
.frame(maxWidth: 120, maxHeight: 120)
.transition(.movingParts.skid.animation(mediumSpring))
let looseSpring = Animation.interpolatingSpring(stiffness: 100, damping: 8)
PlaceholderView()
.frame(maxWidth: 120, maxHeight: 120)
.transition(.movingParts.skid.animation(looseSpring))
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "arrow.left.and.right.square")
}
}

View file

@ -0,0 +1,38 @@
import Pow
import SwiftUI
struct SnapshotExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
ZStack {
// Placeholder
Rectangle()
.fill(.white)
if isVisible {
Image("disco")
.resizable()
.zIndex(1)
.transition(.movingParts.snapshot)
}
}
.frame(width: 350, height: 525)
}
.defaultBackground()
.onTapGesture {
withAnimation(.easeInOut(duration: 1.8)) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: .easeInOut(duration: 1.8))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "camera")
}
}

View file

@ -0,0 +1,37 @@
import Pow
import SwiftUI
struct SwooshExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
.transition(.movingParts.swoosh.combined(with: .opacity))
}
}
.defaultBackground()
.onTapGesture {
let animation: Animation
if isVisible {
animation = .easeIn
} else {
animation = .spring()
}
withAnimation(animation) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: .spring())
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "skew")
}
}

View file

@ -0,0 +1,38 @@
import Pow
import SwiftUI
struct VanishExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
Circle()
.frame(width: 250, height: 250)
// Assign a random ID so that quick re-insertion will not
// play the vanish transition backwards.
.id(UUID())
.transition(
.asymmetric(
insertion: .opacity,
removal: .movingParts.vanish(Color(white: 0.8), mask: Circle())
)
)
}
}
.defaultBackground()
.onTapGesture {
withAnimation {
isVisible.toggle()
}
}
.autotoggle($isVisible)
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "circle.dotted")
}
}

View file

@ -0,0 +1,37 @@
import Pow
import SwiftUI
struct WipeExample: View, Example {
@State
var isVisible: Bool = false
var body: some View {
ZStack {
if isVisible {
PlaceholderView()
// Assign a random ID so that quick re-insertion will not
// play the wipe transition backwards.
.id(UUID())
.transition(
.asymmetric(
insertion: .movingParts.wipe(angle: .degrees(235), blurRadius: 30),
removal: .movingParts.wipe(angle: .degrees(55), blurRadius: 30)
)
)
}
}
.defaultBackground()
.onTapGesture {
withAnimation(.spring(dampingFraction: 1)) {
isVisible.toggle()
}
}
.autotoggle($isVisible, with: .spring(dampingFraction: 1))
}
static let localPath = LocalPath()
static var icon: Image? {
Image(systemName: "windshield.rear.and.wiper")
}
}

View file

@ -0,0 +1,43 @@
import SwiftUI
struct GithubButton: View {
var localPath: LocalPath
let baseURL = URL(string: "https://github.com/EmergeTools/Pow/blob/main/Example/")!
init(_ localPath: LocalPath) {
self.localPath = localPath
}
var body: some View {
let srcroot = Bundle.main.object(forInfoDictionaryKey: "MVP_SRCROOT") as? String
if let srcURL = srcroot.map(URL.init(fileURLWithPath:)) {
let relative = localPath.url.relativePath(to: srcURL)
let url = baseURL.appendingPathComponent(relative)
Link(destination: url) {
ViewThatFits {
Label("Show Example on GitHub", systemImage: "terminal")
Label("Show on GitHub", systemImage: "terminal")
}
}
}
}
}
private extension URL {
func relativePath(to base: URL) -> String {
let pathComponents = self.pathComponents
let baseComponents = base.pathComponents
guard pathComponents.starts(with: baseComponents) else {
fatalError("\(self) is not contained inside \(base).")
}
return pathComponents
.dropFirst(baseComponents.count)
.joined(separator: "/")
}
}

View file

@ -0,0 +1,94 @@
import SwiftUI
struct PlaceholderView: View {
var hiddenContent: Bool
init(hiddenContent: Bool = false) {
self.hiddenContent = hiddenContent
}
var gridLines: some View {
ZStack {
Circle()
.stroke(lineWidth: 1)
.padding()
Circle()
.stroke(lineWidth: 1)
.padding()
.padding()
.padding()
.padding()
HStack {
ForEach(0..<5) { _ in
Spacer()
Rectangle().frame(width: 1)
}
Spacer()
}
VStack {
Spacer()
Rectangle().frame(height: 1)
Spacer()
Rectangle().frame(height: 1)
Spacer()
Rectangle().frame(height: 1)
Spacer()
Rectangle().frame(height: 1)
Spacer()
}
}
.overlay {
Rectangle().frame(width: 1, height: 500)
.rotationEffect(.degrees(45))
Rectangle().frame(width: 1, height: 500)
.rotationEffect(.degrees(-45))
}
}
var fillColors: [Color] {
if !hiddenContent {
return [
Color(.displayP3, red: 0.32, green: 0.61, blue: 0.97),
Color(.displayP3, red: 0.20, green: 0.47, blue: 0.96)
]
} else {
return [
Color(.displayP3, white: 0.25),
Color(.displayP3, white: 0.3)
]
}
}
@ViewBuilder
var fill: some View {
RoundedRectangle(cornerRadius: 32, style: .continuous)
.fill(LinearGradient(colors: fillColors, startPoint: .top, endPoint: .bottom))
.overlay {
RoundedRectangle(cornerRadius: 32, style: .continuous)
.strokeBorder(.black.opacity(0.3), lineWidth: 4)
}
}
var body: some View {
fill
.overlay {
gridLines
.opacity(0.25)
.scaledToFill()
}
.foregroundColor(.white)
.multilineTextAlignment(.center)
.font(
Font
.system(.largeTitle)
.bold()
.leading(.tight)
)
.multilineTextAlignment(.center)
.environment(\.dynamicTypeSize, .xxLarge)
.aspectRatio(1, contentMode: .fit)
.clipShape(RoundedRectangle(cornerRadius: 32, style: .continuous))
.compositingGroup()
.frame(maxWidth: 250, maxHeight: 250)
}
}

View file

@ -0,0 +1,40 @@
import SwiftUI
@main
struct PowExampleApp: App {
struct Presentation: Identifiable {
var type: any Example.Type
var id: UUID = UUID()
}
@State
var presentedType: Presentation? = nil
var body: some Scene {
WindowGroup {
NavigationStack {
ExampleList()
}
.environment(\.presentInfoAction, PresentInfoAction {
presentedType = Presentation(type: $0)
})
.sheet(item: $presentedType) { t in
ScrollView {
VStack(alignment: .leading, spacing: 12) {
Text(t.type.title).font(.title.bold())
GithubButton(t.type.localPath)
.controlSize(.small)
.buttonStyle(.bordered)
t.type.erasedDescription
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
.presentationDetents([.medium])
}
}
}
}

View file

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more