Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] #14 - PophoryTextField 구현 #18

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
46 changes: 29 additions & 17 deletions pophory-TCA/pophory-TCA.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

/* Begin PBXBuildFile section */
3797E0182C7ECCA200EC6E26 /* PophoryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3797E0172C7ECCA200EC6E26 /* PophoryButton.swift */; };
37CBFBF72C65B6390049332C /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = 37CBFBF62C65B6390049332C /* ComposableArchitecture */; };
3B1C335A2C65B552001DB285 /* Pretendard-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3BC585262C6472AC003763AF /* Pretendard-Bold.otf */; };
3B1C335B2C65B552001DB285 /* Pretendard-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3BC585232C6472AB003763AF /* Pretendard-Medium.otf */; };
3B1C335C2C65B552001DB285 /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3BC585292C6472AC003763AF /* Pretendard-Regular.otf */; };
Expand All @@ -17,12 +16,16 @@
3B1C335F2C65B552001DB285 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3BC5851F2C6470FE003763AF /* Colors.xcassets */; };
3B3B9BE42C675E6B00AF9D5C /* View+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B9BE32C675E6B00AF9D5C /* View+.swift */; };
3B3B9BE62C675E7400AF9D5C /* ViewModifier+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B9BE52C675E7400AF9D5C /* ViewModifier+.swift */; };
3B3FEDE72C7D7056001B7A81 /* PophoryTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3FEDE62C7D7056001B7A81 /* PophoryTextField.swift */; };
3BC584D72C646530003763AF /* pophory_TCAApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC584D62C646530003763AF /* pophory_TCAApp.swift */; };
3BC584D92C646530003763AF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC584D82C646530003763AF /* ContentView.swift */; };
3BC584E82C646531003763AF /* pophory_TCATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC584E72C646531003763AF /* pophory_TCATests.swift */; };
3BC584F22C646531003763AF /* pophory_TCAUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC584F12C646531003763AF /* pophory_TCAUITests.swift */; };
3BC584F42C646531003763AF /* pophory_TCAUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC584F32C646531003763AF /* pophory_TCAUITestsLaunchTests.swift */; };
3BC585352C64743E003763AF /* UIFontWithLineHeight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC585342C64743E003763AF /* UIFontWithLineHeight.swift */; };
3BC757942C80174B00752385 /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = 3BC757932C80174B00752385 /* ComposableArchitecture */; };
3BF2F8A32C8FE18A000408A2 /* TextFieldType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF2F8A22C8FE18A000408A2 /* TextFieldType.swift */; };
3BF2F8A52C8FE1A9000408A2 /* PophoryTextFieldSytyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF2F8A42C8FE1A9000408A2 /* PophoryTextFieldSytyle.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -47,6 +50,7 @@
3B1C33602C65B5F3001DB285 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3B3B9BE32C675E6B00AF9D5C /* View+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+.swift"; sourceTree = "<group>"; };
3B3B9BE52C675E7400AF9D5C /* ViewModifier+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewModifier+.swift"; sourceTree = "<group>"; };
3B3FEDE62C7D7056001B7A81 /* PophoryTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PophoryTextField.swift; sourceTree = "<group>"; };
3BC584D32C646530003763AF /* pophory-TCA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "pophory-TCA.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3BC584D62C646530003763AF /* pophory_TCAApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = pophory_TCAApp.swift; sourceTree = "<group>"; };
3BC584D82C646530003763AF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand All @@ -63,14 +67,16 @@
3BC585262C6472AC003763AF /* Pretendard-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Bold.otf"; sourceTree = "<group>"; };
3BC585292C6472AC003763AF /* Pretendard-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.otf"; sourceTree = "<group>"; };
3BC585342C64743E003763AF /* UIFontWithLineHeight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFontWithLineHeight.swift; sourceTree = "<group>"; };
3BF2F8A22C8FE18A000408A2 /* TextFieldType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldType.swift; sourceTree = "<group>"; };
3BF2F8A42C8FE1A9000408A2 /* PophoryTextFieldSytyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PophoryTextFieldSytyle.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
3BC584D02C646530003763AF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
37CBFBF72C65B6390049332C /* ComposableArchitecture in Frameworks */,
3BC757942C80174B00752385 /* ComposableArchitecture in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -94,18 +100,12 @@
3797E0162C7ECC5D00EC6E26 /* Components */ = {
isa = PBXGroup;
children = (
3BF2F8A12C8FE16E000408A2 /* PophoryTextField */,
3797E0172C7ECCA200EC6E26 /* PophoryButton.swift */,
);
path = Components;
sourceTree = "<group>";
};
3B00A4842C6B032000D851F1 /* Components */ = {
isa = PBXGroup;
children = (
);
path = Components;
sourceTree = "<group>";
};
3BC584CA2C646530003763AF = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -338,7 +338,6 @@
3BC585162C6468F1003763AF /* Assets */ = {
isa = PBXGroup;
children = (
3B00A4842C6B032000D851F1 /* Components */,
3BC585212C64723F003763AF /* Fonts */,
3BC584DA2C646531003763AF /* Assets.xcassets */,
3BC5851F2C6470FE003763AF /* Colors.xcassets */,
Expand Down Expand Up @@ -405,6 +404,16 @@
path = Fonts;
sourceTree = "<group>";
};
3BF2F8A12C8FE16E000408A2 /* PophoryTextField */ = {
isa = PBXGroup;
children = (
3B3FEDE62C7D7056001B7A81 /* PophoryTextField.swift */,
3BF2F8A22C8FE18A000408A2 /* TextFieldType.swift */,
3BF2F8A42C8FE1A9000408A2 /* PophoryTextFieldSytyle.swift */,
);
path = PophoryTextField;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand All @@ -422,7 +431,7 @@
);
name = "pophory-TCA";
packageProductDependencies = (
37CBFBF62C65B6390049332C /* ComposableArchitecture */,
3BC757932C80174B00752385 /* ComposableArchitecture */,
);
productName = "pophory-TCA";
productReference = 3BC584D32C646530003763AF /* pophory-TCA.app */;
Expand Down Expand Up @@ -497,7 +506,7 @@
);
mainGroup = 3BC584CA2C646530003763AF;
packageReferences = (
37CBFBF52C65B6390049332C /* XCRemoteSwiftPackageReference "swift-composable-architecture" */,
3BC757922C80174B00752385 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */,
);
productRefGroup = 3BC584D42C646530003763AF /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -545,7 +554,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3BF2F8A32C8FE18A000408A2 /* TextFieldType.swift in Sources */,
3B3B9BE42C675E6B00AF9D5C /* View+.swift in Sources */,
3B3FEDE72C7D7056001B7A81 /* PophoryTextField.swift in Sources */,
3BF2F8A52C8FE1A9000408A2 /* PophoryTextFieldSytyle.swift in Sources */,
3BC585352C64743E003763AF /* UIFontWithLineHeight.swift in Sources */,
3B3B9BE62C675E7400AF9D5C /* ViewModifier+.swift in Sources */,
3797E0182C7ECCA200EC6E26 /* PophoryButton.swift in Sources */,
Expand Down Expand Up @@ -884,20 +896,20 @@
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
37CBFBF52C65B6390049332C /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
3BC757922C80174B00752385 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture.git";
repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.12.1;
minimumVersion = 1.14.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
37CBFBF62C65B6390049332C /* ComposableArchitecture */ = {
3BC757932C80174B00752385 /* ComposableArchitecture */ = {
isa = XCSwiftPackageProductDependency;
package = 37CBFBF52C65B6390049332C /* XCRemoteSwiftPackageReference "swift-composable-architecture" */;
package = 3BC757922C80174B00752385 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */;
productName = ComposableArchitecture;
};
/* End XCSwiftPackageProductDependency section */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// PophoryTextField.swift
// pophory-TCA
//
// Created by 강윤서 on 8/27/24.
//

import SwiftUI

struct PophoryTextField: View {
@State private var text: String = ""
@State private var isValid: Bool = true
let type: TextFieldType

var body: some View {
VStack {
TextField(type.placeholder, text: $text)
.onChange(of: text, { _, newValue in
if newValue.count > type.maxCharacterLimit {
text = String(newValue.prefix(type.maxCharacterLimit))
}
isValid = validate(newValue) || text.isEmpty
})
.textFieldStyle(PophoryTextFieldStyle(
isEmpty: .constant(text.isEmpty),
isValid: .constant(isValid))
)

HStack {
if !isValid {
Text(type.errorMessage)
.fontWithLineHeightView(fontType: .caption01Medium)
.padding(.leading, 6)
.foregroundStyle(.pryRed)
}

Spacer()

Text("(\(text.count)/\(type.maxCharacterLimit))")
.fontWithLineHeightView(fontType: .text01Medium)
.foregroundStyle(.gray400)
}
.padding(.top, 10)
}
}

private func validate(_ text: String) -> Bool {
let regex = try? NSRegularExpression(pattern: "^[A-Za-z0-9._]{4,12}$")
let range = NSRange(location: 0, length: text.utf16.count)
return regex?.firstMatch(in: text, options: [], range: range) != nil
}
}

#Preview {
PophoryTextField(type: .id)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// PophoryTextFieldSytyle.swift
// pophory-TCA
//
// Created by 강윤서 on 9/10/24.
//

import SwiftUI

struct PophoryTextFieldStyle: TextFieldStyle {
@Binding var isEmpty: Bool
@Binding var isValid: Bool

func _body(configuration: TextField<Self._Label>) -> some View {
configuration
.padding(EdgeInsets(top: 19, leading: 15, bottom: 18, trailing: 18))
.fontWithLineHeightView(fontType: .text01Medium)
.overlay(
RoundedRectangle(cornerRadius: 18)
.stroke(strokeColor(), lineWidth: 1.0)
)
.onAppear {
UITextField.appearance().clearButtonMode = .whileEditing
}
}

private func strokeColor() -> Color {
if isEmpty {
return .gray300
} else if isValid {
return .pryPurple
} else {
return .pryRed
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// TextFieldType.swift
// pophory-TCA
//
// Created by 강윤서 on 9/10/24.
//

enum TextFieldType {
case id
case nickName

var placeholder: String {
switch self {
case .id:
return "아이디"
case .nickName:
return "닉네임"
}
}

var regex: String {
switch self {
case .id:
return "^[a-zA-Z0-9._]{4,12}$"
case .nickName:
return "^[가-힣]{2,6}$"
}
}

var errorMessage: String {
switch self {
case .id:
return "*올바른 형식의 아이디가 아닙니다"
case .nickName:
return "*2-6글자 이내로 작성해주세요"
}
}

var maxCharacterLimit: Int {
switch self {
case .id:
return 12
case .nickName:
return 6
}
}
}
22 changes: 11 additions & 11 deletions pophory-TCA/pophory-TCA/Global/Constants/UIFontWithLineHeight.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ extension UIFontWithLineHeight {
static let modalTitleBold: UIFontWithLineHeight = customPretendard(.Bold, size: 20, lineHeight: 28)

// SemiBold
static let headline02SemiBold: UIFontWithLineHeight = customPretendard(.Bold, size: 20, lineHeight: 24)
static let headline03SemiBold: UIFontWithLineHeight = customPretendard(.Bold, size: 18, lineHeight: 17)
static let headline02SemiBold: UIFontWithLineHeight = customPretendard(.SemiBold, size: 20, lineHeight: 24)
static let headline03SemiBold: UIFontWithLineHeight = customPretendard(.SemiBold, size: 18, lineHeight: 17)

// Medium
static let headline01Medium: UIFontWithLineHeight = customPretendard(.Bold, size: 24, lineHeight: 34)
static let title01Medium: UIFontWithLineHeight = customPretendard(.Bold, size: 17, lineHeight: 24)
static let text01Medium: UIFontWithLineHeight = customPretendard(.Bold, size: 16, lineHeight: 21)
static let caption01Medium: UIFontWithLineHeight = customPretendard(.Bold, size: 14, lineHeight: 20)
static let caption02Medium: UIFontWithLineHeight = customPretendard(.Bold, size: 12, lineHeight: 17)
static let popupButtonMedium: UIFontWithLineHeight = customPretendard(.Bold, size: 16, lineHeight: 23)
static let popupLineMedium: UIFontWithLineHeight = customPretendard(.Bold, size: 14, lineHeight: 17)
static let modalText: UIFontWithLineHeight = customPretendard(.Bold, size: 18, lineHeight: 26)
static let headline01Medium: UIFontWithLineHeight = customPretendard(.Medium, size: 24, lineHeight: 34)
static let title01Medium: UIFontWithLineHeight = customPretendard(.Medium, size: 17, lineHeight: 24)
static let text01Medium: UIFontWithLineHeight = customPretendard(.Medium, size: 16, lineHeight: 21)
static let caption01Medium: UIFontWithLineHeight = customPretendard(.Medium, size: 14, lineHeight: 20)
static let caption02Medium: UIFontWithLineHeight = customPretendard(.Medium, size: 12, lineHeight: 17)
static let popupButtonMedium: UIFontWithLineHeight = customPretendard(.Medium, size: 16, lineHeight: 23)
static let popupLineMedium: UIFontWithLineHeight = customPretendard(.Medium, size: 14, lineHeight: 17)
static let modalText: UIFontWithLineHeight = customPretendard(.Medium, size: 18, lineHeight: 26)

// Regular
static let popupTextRegular: UIFontWithLineHeight = customPretendard(.Bold, size: 16, lineHeight: 23)
static let popupTextRegular: UIFontWithLineHeight = customPretendard(.Regular, size: 16, lineHeight: 23)
}

// static func
Expand Down