Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4866759
Add hidden, disabled, tag, zIndex, fixedSize modifiers to UIView and …
cruisediary Mar 22, 2026
d435b31
Add contentInset, scrollIndicatorInsets, alwaysBounce, decelerationRa…
cruisediary Mar 22, 2026
46b7ef4
Add UISwitch+Toggle extension with SwiftUI-style modifiers
cruisediary Mar 22, 2026
f736e11
Add tests for UISwitch+Toggle extension
cruisediary Mar 22, 2026
d574379
Add UISlider+Slider extension with SwiftUI-style modifiers
cruisediary Mar 22, 2026
2a09c8a
Add tests for UISlider+Slider extension
cruisediary Mar 22, 2026
e86ff13
Add UIStepper+Stepper extension with SwiftUI-style modifiers
cruisediary Mar 22, 2026
979ec30
Add tests for UIStepper+Stepper extension
cruisediary Mar 22, 2026
c6b8392
Add UIProgressView+ProgressView extension with SwiftUI-style modifiers
cruisediary Mar 22, 2026
73a8a81
Add tests for UIProgressView+ProgressView extension
cruisediary Mar 22, 2026
fa3f789
Add UIActivityIndicatorView extension for activity indicator control
cruisediary Mar 22, 2026
a957d47
Add tests for UIActivityIndicatorView extension
cruisediary Mar 22, 2026
de3faca
Add UIPageControl extension with SwiftUI-style modifiers
cruisediary Mar 22, 2026
4f34505
Add tests for UIPageControl extension
cruisediary Mar 22, 2026
11e7e87
Add highlighted image, animation images, and symbol configuration mod…
cruisediary Mar 22, 2026
570d175
Add tests for UIImageView extension modifiers
cruisediary Mar 22, 2026
749fa85
Update README with new UIKit extensions
cruisediary Mar 22, 2026
cda4c28
Fix failing tests: use internal handler methods for onChange tests an…
cruisediary Mar 22, 2026
5f222d9
Update example to use local package reference and update Package.reso…
cruisediary Mar 22, 2026
bb049bf
Fix local package relative path in example project
cruisediary Mar 22, 2026
e4e0f0e
Add colors convenience initializer to Gradient
cruisediary Mar 22, 2026
d1b71b6
Add ConceptList entry point and remote image loading to example
cruisediary Mar 22, 2026
0a275ea
Add Music Player concept example
cruisediary Mar 22, 2026
b610cd2
Add Social Profile concept example
cruisediary Mar 22, 2026
ef0d710
Add Settings concept example
cruisediary Mar 22, 2026
987680b
Add Travel Carousel concept example
cruisediary Mar 22, 2026
de94b3c
Add Component Gallery concept example
cruisediary Mar 22, 2026
ff5b252
Add Animation Showcase concept example
cruisediary Mar 22, 2026
177c17e
Address review: fix duplicate palette color and weak self in async cl…
cruisediary Mar 22, 2026
f5a9862
Fix onChange target-action duplication and associated object policy
cruisediary Mar 22, 2026
6dbd129
Fix fixedSize() to also set content hugging priority to required
cruisediary Mar 22, 2026
c5b93fc
Remove unused pageControlView weak property
cruisediary Mar 22, 2026
f6cd202
Address review: fix shuffle replay, follower count visibility, and ha…
cruisediary Mar 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion Example/HypeUI-Example/HypeUI-Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
FC8A9F12291D33C200022ED3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FC8A9F11291D33C200022ED3 /* Assets.xcassets */; };
FC8A9F15291D33C200022ED3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FC8A9F13291D33C200022ED3 /* LaunchScreen.storyboard */; };
FC8A9F1E291D33FC00022ED3 /* HypeUI in Frameworks */ = {isa = PBXBuildFile; productRef = FC8A9F1D291D33FC00022ED3 /* HypeUI */; };
AA010002000000000000001A /* UIImageView+Remote.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA010001000000000000001A /* UIImageView+Remote.swift */; };
AA010004000000000000001A /* MusicPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA010003000000000000001A /* MusicPlayerViewController.swift */; };
AA010006000000000000001A /* SocialProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA010005000000000000001A /* SocialProfileViewController.swift */; };
AA010008000000000000001A /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA010007000000000000001A /* SettingsViewController.swift */; };
AA01000A000000000000001A /* TravelCarouselViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA010009000000000000001A /* TravelCarouselViewController.swift */; };
AA01000C000000000000001A /* ComponentGalleryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA01000B000000000000001A /* ComponentGalleryViewController.swift */; };
AA01000E000000000000001A /* AnimationShowcaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA01000D000000000000001A /* AnimationShowcaseViewController.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -25,6 +32,13 @@
FC8A9F11291D33C200022ED3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
FC8A9F14291D33C200022ED3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
FC8A9F16291D33C300022ED3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AA010001000000000000001A /* UIImageView+Remote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Remote.swift"; sourceTree = "<group>"; };
AA010003000000000000001A /* MusicPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicPlayerViewController.swift; sourceTree = "<group>"; };
AA010005000000000000001A /* SocialProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialProfileViewController.swift; sourceTree = "<group>"; };
AA010007000000000000001A /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
AA010009000000000000001A /* TravelCarouselViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TravelCarouselViewController.swift; sourceTree = "<group>"; };
AA01000B000000000000001A /* ComponentGalleryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComponentGalleryViewController.swift; sourceTree = "<group>"; };
AA01000D000000000000001A /* AnimationShowcaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationShowcaseViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -61,6 +75,13 @@
FC8A9F08291D33C100022ED3 /* AppDelegate.swift */,
FC8A9F0A291D33C100022ED3 /* SceneDelegate.swift */,
FC8A9F0C291D33C100022ED3 /* ViewController.swift */,
AA010001000000000000001A /* UIImageView+Remote.swift */,
AA010003000000000000001A /* MusicPlayerViewController.swift */,
AA010005000000000000001A /* SocialProfileViewController.swift */,
AA010007000000000000001A /* SettingsViewController.swift */,
AA010009000000000000001A /* TravelCarouselViewController.swift */,
AA01000B000000000000001A /* ComponentGalleryViewController.swift */,
AA01000D000000000000001A /* AnimationShowcaseViewController.swift */,
FC8A9F0E291D33C100022ED3 /* Main.storyboard */,
FC8A9F11291D33C200022ED3 /* Assets.xcassets */,
FC8A9F13291D33C200022ED3 /* LaunchScreen.storyboard */,
Expand Down Expand Up @@ -147,6 +168,13 @@
buildActionMask = 2147483647;
files = (
FC8A9F0D291D33C100022ED3 /* ViewController.swift in Sources */,
AA010002000000000000001A /* UIImageView+Remote.swift in Sources */,
AA010004000000000000001A /* MusicPlayerViewController.swift in Sources */,
AA010006000000000000001A /* SocialProfileViewController.swift in Sources */,
AA010008000000000000001A /* SettingsViewController.swift in Sources */,
AA01000A000000000000001A /* TravelCarouselViewController.swift in Sources */,
AA01000C000000000000001A /* ComponentGalleryViewController.swift in Sources */,
AA01000E000000000000001A /* AnimationShowcaseViewController.swift in Sources */,
FC8A9F09291D33C100022ED3 /* AppDelegate.swift in Sources */,
FC8A9F0B291D33C100022ED3 /* SceneDelegate.swift in Sources */,
);
Expand Down Expand Up @@ -377,7 +405,7 @@
/* Begin XCSwiftPackageProductDependency section */
FC8A9F1D291D33FC00022ED3 /* HypeUI */ = {
isa = XCSwiftPackageProductDependency;
package = FC8A9F1C291D33FC00022ED3 /* XCRemoteSwiftPackageReference "HypeUI" */;
package = FC8A9F1C291D33FC00022ED3 /* XCLocalSwiftPackageReference "../.." */;
productName = HypeUI;
};
/* End XCSwiftPackageProductDependency section */
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//
// Copyright 2022 Hyperconnect Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import UIKit
import HypeUI

// MARK: - AnimationShowcaseViewController

final class AnimationShowcaseViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
title = "Animation"
view.backgroundColor = .systemBackground

let fadeBox = UIView()
.background(.systemBlue)
.frame(width: 64, height: 64)
.cornerRadius(14)

let scaleBox = UIView()
.background(.systemPurple)
.frame(width: 64, height: 64)
.cornerRadius(14)

let rotateBox = UIView()
.background(.systemOrange)
.frame(width: 64, height: 64)
.cornerRadius(14)

let pulseBox = UIView()
.background(.systemGreen)
.frame(width: 64, height: 64)
.cornerRadius(32)

let shakeBox = UIView()
.background(.systemRed)
.frame(width: 48, height: 48)
.cornerRadius(12)

view.addSubviewWithFit(
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 12) {
// Row 1
HStack(spacing: 12) {
animCard(box: fadeBox, title: "Fade", subtitle: "alpha") {
UIView.animate(withDuration: 0.4) {
fadeBox.alpha = fadeBox.alpha == 1 ? 0.15 : 1
}
}
animCard(box: scaleBox, title: "Scale", subtitle: "spring") {
let enlarged = scaleBox.transform.a < 1.4
UIView.animate(
withDuration: 0.35,
delay: 0,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 0.5
) {
scaleBox.transform = enlarged
? CGAffineTransform(scaleX: 1.5, y: 1.5)
: .identity
}
}
}
.distributed(.fillEqually)

// Row 2
HStack(spacing: 12) {
animCard(box: rotateBox, title: "Rotate", subtitle: "transform") {
let angle = atan2(rotateBox.transform.b, rotateBox.transform.a)
UIView.animate(withDuration: 0.4) {
rotateBox.transform = CGAffineTransform(rotationAngle: angle + .pi / 2)
}
}
animCard(box: pulseBox, title: "Pulse", subtitle: "keyframe") {
UIView.animateKeyframes(withDuration: 0.6, delay: 0, options: []) {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.3) {
pulseBox.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
pulseBox.alpha = 0.7
}
UIView.addKeyframe(withRelativeStartTime: 0.3, relativeDuration: 0.7) {
pulseBox.transform = .identity
pulseBox.alpha = 1
}
}
}
}
.distributed(.fillEqually)

// Row 3: Featured shake card — full width
Button(action: {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: .linear)
animation.duration = 0.5
animation.values = [-12, 12, -10, 10, -6, 6, -3, 3, 0]
shakeBox.layer.add(animation, forKey: "shake")
}) {
HStack(alignment: .center, spacing: 16) {
shakeBox
VStack(alignment: .leading, spacing: 3) {
Text("Shake")
.font(UIFont.systemFont(ofSize: 15, weight: .semibold))
.foregroundColor(.label)
Text("CAKeyframeAnimation · error feedback")
.font(UIFont.systemFont(ofSize: 11, weight: .regular))
.foregroundColor(.secondaryLabel)
}
Spacer()
Text("Tap →")
.font(UIFont.systemFont(ofSize: 13, weight: .medium))
.foregroundColor(.tertiaryLabel)
.fixedSize()
}
.padding(.all, 16)
.background(.systemBackground)
.border(.separator, width: 1)
.cornerRadius(16)
}
}
.padding(.horizontal, 20)
.padding(.vertical, 16)
}
)
}

private func animCard(
box: UIView,
title: String,
subtitle: String,
action: @escaping () -> Void
) -> UIView {
Button(action: action) {
// VStack with default .fill alignment so center() container gets full width
VStack(spacing: 10) {
box.center()
.frame(height: 110)
.background(.systemGray6)
.cornerRadius(12)
VStack(alignment: .center, spacing: 2) {
Text(title)
.font(UIFont.systemFont(ofSize: 14, weight: .semibold))
.foregroundColor(.label)
.textAligned(.center)
Text(subtitle)
.font(UIFont.systemFont(ofSize: 11, weight: .regular))
.foregroundColor(.secondaryLabel)
.textAligned(.center)
}
Text("Tap to animate")
.font(UIFont.systemFont(ofSize: 10, weight: .medium))
.foregroundColor(.systemBlue)
.textAligned(.center)
}
.padding(.all, 12)
.background(.systemBackground)
.border(.separator, width: 1)
.cornerRadius(16)
}
}
}
Loading