diff --git a/MLS/MLS.xcodeproj/project.pbxproj b/MLS/MLS.xcodeproj/project.pbxproj index fdc14e09..c59a4da2 100644 --- a/MLS/MLS.xcodeproj/project.pbxproj +++ b/MLS/MLS.xcodeproj/project.pbxproj @@ -148,7 +148,6 @@ 77BEB0402DBA84B0002FFCFC /* MLSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MLSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 77E260402EEABEC40059E889 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = MLS/Resource/Settings.bundle; sourceTree = ""; }; 77EB18D52DED9256004FB380 /* AuthFeature.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AuthFeature.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 77FA68752F72C6D80064B6EB /* MLSDesignSystem */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = MLSDesignSystem; path = Presentation/MLSDesignSystem; sourceTree = ""; }; 77FA687A2F72C7360064B6EB /* MLSDesignSystemExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MLSDesignSystemExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -325,7 +324,6 @@ 087D3EDF2DA7972C002F924D = { isa = PBXGroup; children = ( - 77FA68752F72C6D80064B6EB /* MLSDesignSystem */, 77E260402EEABEC40059E889 /* Settings.bundle */, 77660AD12DD0D361007A4EF3 /* KakaoConfig.xcconfig */, 085A7F742DAF99570046663F /* .swiftlint.yml */, diff --git a/MLS/MLS.xcworkspace/contents.xcworkspacedata b/MLS/MLS.xcworkspace/contents.xcworkspacedata index 4309165a..c5c30238 100644 --- a/MLS/MLS.xcworkspace/contents.xcworkspacedata +++ b/MLS/MLS.xcworkspace/contents.xcworkspacedata @@ -36,8 +36,11 @@ location = "group:Core/Core.xcodeproj"> - + location = "group:MLSDesignSystem"> + + + diff --git a/MLS/MLSDesignSystem/.gitignore b/MLS/MLSDesignSystem/.gitignore new file mode 100644 index 00000000..0023a534 --- /dev/null +++ b/MLS/MLSDesignSystem/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/MLS/MLSDesignSystem/Package.swift b/MLS/MLSDesignSystem/Package.swift new file mode 100644 index 00000000..60408739 --- /dev/null +++ b/MLS/MLSDesignSystem/Package.swift @@ -0,0 +1,38 @@ +// swift-tools-version: 6.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MLSDesignSystem", + platforms: [ + .iOS(.v15) + ], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "MLSDesignSystem", + targets: ["MLSDesignSystem"] + ) + ], + dependencies: [ + .package(url: "https://github.com/SnapKit/SnapKit.git", from: "5.7.1"), + .package(url: "https://github.com/ReactiveX/RxSwift.git", from: "6.9.1") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "MLSDesignSystem", + dependencies: [ + .product(name: "SnapKit", package: "SnapKit"), + .product(name: "RxSwift", package: "RxSwift"), + .product(name: "RxCocoa", package: "RxSwift"), + .product(name: "RxRelay", package: "RxSwift") + ], + resources: [ + .process("Resources") + ] + ) + ] +) diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/AuthGuideAlert.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/AuthGuideAlert.swift new file mode 100644 index 00000000..574b231d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/AuthGuideAlert.swift @@ -0,0 +1,130 @@ +import UIKit + +import SnapKit + +public class AuthGuideAlert: GuideAlert { + // MARK: - Type + private enum Constant { + static let iconSize: CGFloat = 24 + static let topSpacing: CGFloat = 14 + static let stackViewTopSpacing: CGFloat = stackViewBottomSpacing * 2 + static let stackViewBottomSpacing: CGFloat = 8 + static let iconSpacing: CGFloat = 5 + } + + public enum AuthGuideAlertType { + case logout + case withdraw + + var mainText: String { + switch self { + case .logout: + "정말 로그아웃 하시겠어요?" + case .withdraw: + "정말 탈퇴 하시겠어요?" + } + } + + var subText: String { + switch self { + case .logout: + "로그아웃하면 저장한 캐릭터,\n북마크한 아이템 정보를 볼 수 없어요." + case .withdraw: + "탈퇴 시, 아래 정보가 삭제 되어 복구가 불가능해요." + } + } + + var ctaText: String { + switch self { + case .logout: + "로그아웃 하기" + case .withdraw: + "탈퇴하기" + } + } + } + + // MARK: - Components + private let contentStackView: UIStackView = { + let view = UIStackView() + view.axis = .vertical + return view + }() + + private let subTextLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 2 + return label + }() + + private lazy var bookmarkStackView = makeStack(icon: DesignSystemAsset.image(named: "checkMarkFill"), text: "북마크 컬렉션") + private lazy var characterStackView = makeStack(icon: DesignSystemAsset.image(named: "checkMarkFill"), text: "캐릭터 정보") + + // MARK: - init + public init(type: AuthGuideAlertType) { + super.init(mainText: type.mainText, ctaText: type.ctaText, cancelText: "취소") + addViews(type: type) + setupConstraints(type: type) + configureUI(type: type) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension AuthGuideAlert { + func addViews(type: AuthGuideAlertType) { + addSubview(contentStackView) + + contentStackView.addArrangedSubview(subTextLabel) + if type == .withdraw { + contentStackView.addArrangedSubview(bookmarkStackView) + contentStackView.addArrangedSubview(characterStackView) + } + } + + func setupConstraints(type: AuthGuideAlertType) { + contentStackView.snp.makeConstraints { make in + make.top.equalTo(mainTextLabel.snp.bottom).offset(Constant.topSpacing) + make.horizontalEdges.equalToSuperview().inset(GuideAlert.Constant.horizontalInset) + } + + if type == .withdraw { + contentStackView.setCustomSpacing(Constant.stackViewTopSpacing, after: subTextLabel) + contentStackView.setCustomSpacing(Constant.stackViewBottomSpacing, after: bookmarkStackView) + } + + buttonStackView.snp.remakeConstraints { make in + make.top.equalTo(contentStackView.snp.bottom).offset(GuideAlert.Constant.verticalSpacing) + make.horizontalEdges.equalToSuperview().inset(GuideAlert.Constant.horizontalInset) + make.bottom.equalToSuperview().inset(GuideAlert.Constant.verticalInset) + make.height.equalTo(GuideAlert.Constant.buttonHeight) + } + } + + func configureUI(type: AuthGuideAlertType) { + subTextLabel.attributedText = .makeStyledString(font: .b_s_r, text: type.subText, color: .neutral700) + } + + func makeStack(icon: UIImage, text: String) -> UIStackView { + let iconView = UIImageView(image: icon) + + let label: UILabel = { + let label = UILabel() + label.attributedText = .makeStyledString(font: .cp_s_r, text: text, color: .neutral700, alignment: .left) + return label + }() + + iconView.snp.makeConstraints { make in + make.size.equalTo(Constant.iconSize) + } + + let stackView = UIStackView(arrangedSubviews: [iconView, label]) + stackView.axis = .horizontal + stackView.spacing = Constant.stackViewBottomSpacing + return stackView + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Badge.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Badge.swift new file mode 100644 index 00000000..6d7ff623 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Badge.swift @@ -0,0 +1,102 @@ +import UIKit + +import SnapKit + +public final class Badge: UIView { + // MARK: - Type + public enum BadgeStyle { + case element(String) + case preQuest + case currentQuest + case nextQuest + + var font: UIFont? { + switch self { + case .element: + return .cp_s_sb + case .currentQuest: + return .cp_xs_sb + default: + return .cp_xs_r + } + } + + var fontColor: UIColor { + switch self { + case .element, .currentQuest: + return .primary700 + default: + return .neutral600 + } + } + + var backgroundColor: UIColor { + switch self { + case .element, .currentQuest: + return .primary25 + default: + return .neutral100 + } + } + + var text: String { + switch self { + case .element(let text): + return text + case .preQuest: + return "이전 퀘스트" + case .currentQuest: + return "현재 퀘스트" + case .nextQuest: + return "다음 퀘스트" + } + } + } + + private enum Constant { + static let radius: CGFloat = 4 + static let contentInsets: CGFloat = 6 + } + + // MARK: - Components + private let textLabel = UILabel() + + // MARK: - init + public init(style: BadgeStyle) { + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI(style: style) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension Badge { + func addViews() { + addSubview(textLabel) + } + + func setupConstraints() { + textLabel.snp.makeConstraints { make in + make.edges.equalToSuperview().inset(Constant.contentInsets) + } + } + + func configureUI(style: BadgeStyle) { + layer.cornerRadius = Constant.radius + backgroundColor = style.backgroundColor + textLabel.attributedText = .makeStyledString(font: style.font, text: style.text, color: style.fontColor, lineHeight: 1) + } +} + +public extension Badge { + func update(style: BadgeStyle) { + configureUI(style: style) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift new file mode 100644 index 00000000..f461d117 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CardList.swift @@ -0,0 +1,283 @@ +import UIKit + +import SnapKit + +public final class CardList: UIView { + // MARK: - Type + public enum CardListType { + case bookmark + case checkbox + case detailStack + case detailStackText // 몬스터 카드일 경우 드롭률 + case detailStackBadge(Badge.BadgeStyle) + case recommended(rank: Int) + + var icon: UIImage? { + switch self { + case .bookmark, .recommended: + return DesignSystemAsset.image(named: "bookmarkBorderList") + case .checkbox: + return DesignSystemAsset.image(named: "checkSquare") + case .detailStack, .detailStackText, .detailStackBadge: + return nil + } + } + + var selectedIcon: UIImage? { + switch self { + case .bookmark, .recommended: + return DesignSystemAsset.image(named: "bookmarkList") + case .checkbox: + return DesignSystemAsset.image(named: "checkSquareFill") + case .detailStack, .detailStackText, .detailStackBadge: + return nil + } + } + } + + enum Constant { + static let cardRadius: CGFloat = 16 + static let cardLeadingInset: CGFloat = 12 + static let cardTrailingInset: CGFloat = 16 + static let infoLabelInset: CGFloat = 16 + static let imageRadius: CGFloat = 8 + static let imageInset: CGFloat = 10 + static let imageContentViewSize: CGFloat = 80 + static let stackViewSpacing: CGFloat = 4 + static let iconSize: CGFloat = 24 + static let mapImageSize: CGFloat = 40 + static let tagHeight: CGFloat = 24 + } + + // MARK: - Properties + private var type = CardListType.bookmark + private var icon = UIImage() + private var selectedIcon = UIImage() + + public var isIconSelected: Bool = false { + didSet { + updateIcon() + } + } + + public var mainText: String? { + didSet { + updateMainText() + } + } + + public var subText: String? { + didSet { + updateSubText() + } + } + + public var onIconTapped: (() -> Void)? + + // MARK: - Components + public let imageView = ItemImageView(image: nil, cornerRadius: Constant.imageRadius, inset: Constant.imageInset, backgroundColor: .listMap) + + private lazy var textLabelStackView: UIStackView = { + let view = UIStackView(arrangedSubviews: [rankTag, mainTextLabel, subTextLabel]) + view.axis = .vertical + view.spacing = Constant.stackViewSpacing + view.alignment = .leading + return view + }() + + private let mainTextLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 2 + label.lineBreakMode = .byTruncatingTail + label.lineBreakStrategy = .pushOut + return label + }() + + private let subTextLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + return label + }() + + private let iconButton: UIButton = { + let button = UIButton() + button.setImage(DesignSystemAsset.image(named: "bookmarkBorder"), for: .normal) + return button + }() + + // 드롭률 표시용 라벨 2개 + private let dropTitleLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + return label + }() + + private let dropValueLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + return label + }() + + // 2개 라벨을 세로로 묶는 스택뷰 + private lazy var dropInfoStack: UIStackView = { + let stack = UIStackView(arrangedSubviews: [dropTitleLabel, dropValueLabel]) + stack.axis = .vertical + stack.alignment = .trailing + stack.isHidden = true // 기본은 숨김 + return stack + }() + + private let badge = Badge(style: .currentQuest) + + private let rankTag = TagChip(style: .text, text: "순위") + + public init() { + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI() + bindButton() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension CardList { + func addViews() { + addSubview(imageView) + addSubview(textLabelStackView) + addSubview(iconButton) + addSubview(dropInfoStack) + addSubview(badge) + } + + func setupConstraints() { + imageView.snp.makeConstraints { make in + make.top.leading.bottom.equalToSuperview().inset(Constant.cardLeadingInset) + make.size.equalTo(Constant.imageContentViewSize) + } + + textLabelStackView.snp.makeConstraints { make in + make.leading.equalTo(imageView.snp.trailing).offset(Constant.cardLeadingInset) + make.centerY.equalToSuperview() + make.trailing.lessThanOrEqualToSuperview().inset(Constant.cardTrailingInset) + } + + dropInfoStack.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.trailing.equalToSuperview().inset(Constant.cardTrailingInset) + } + + badge.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.trailing.equalToSuperview().inset(Constant.cardTrailingInset) + } + + rankTag.snp.makeConstraints { make in + make.height.equalTo(Constant.tagHeight) + } + + iconButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.trailing.equalToSuperview().inset(Constant.cardTrailingInset) + make.size.equalTo(Constant.iconSize) + } + + textLabelStackView.snp.makeConstraints { make in + make.trailing.lessThanOrEqualTo(dropInfoStack.snp.leading).offset(-Constant.cardLeadingInset) + make.trailing.lessThanOrEqualTo(badge.snp.leading).offset(-Constant.cardLeadingInset) + make.trailing.lessThanOrEqualTo(iconButton.snp.leading).offset(-Constant.cardLeadingInset) + } + } + + func configureUI() { + backgroundColor = .whiteMLS + layer.cornerRadius = Constant.cardRadius + } + + func bindButton() { + iconButton.addAction(UIAction(handler: { [weak self] _ in + guard let self = self else { return } + self.onIconTapped?() + }), for: .touchUpInside) + } + + func updateMainText() { + mainTextLabel.attributedText = .makeStyledString(font: .sub_m_sb, text: mainText, alignment: .left) + } + + func updateSubText() { + subTextLabel.attributedText = .makeStyledString(font: .cp_s_r, text: subText, color: .neutral500, alignment: .left) + } + + func updateIcon() { + iconButton.setImage(isIconSelected ? selectedIcon : icon, for: .normal) + } +} + +public extension CardList { + func setMainText(text: String) { + mainText = text + } + + func setSubText(text: String?) { + subText = text + } + + func setImage(image: UIImage, backgroundColor: UIColor) { + imageView.setImage(image: image, backgroundColor: backgroundColor) + } + + func setMapImage(image: UIImage, backgroundColor: UIColor) { + imageView.setMapImage(image: image, backgroundColor: backgroundColor) + } + + func setSelected(isSelected: Bool) { + isIconSelected = isSelected + } + + func setType(type: CardListType) { + self.type = type + icon = type.icon ?? UIImage() + selectedIcon = type.selectedIcon ?? UIImage() + + switch type { + case .detailStack: + iconButton.isHidden = true + dropInfoStack.isHidden = true + badge.isHidden = true + rankTag.isHidden = true + case .detailStackText: + iconButton.isHidden = true + dropInfoStack.isHidden = false + badge.isHidden = true + rankTag.isHidden = true + case .detailStackBadge(let type): + iconButton.isHidden = true + dropInfoStack.isHidden = false + badge.isHidden = false + rankTag.isHidden = true + badge.update(style: type) + case .recommended(let rank): + iconButton.isHidden = true + dropInfoStack.isHidden = true + subTextLabel.isHidden = true + badge.isHidden = true + rankTag.isHidden = false + rankTag.text = "\(rank)위" + default: + iconButton.isHidden = false + dropInfoStack.isHidden = true + badge.isHidden = true + } + } + + func setDropInfoText(title: String, value: String?) { + dropTitleLabel.attributedText = .makeStyledString(font: .cp_s_r, text: title, color: .neutral700) + dropValueLabel.attributedText = .makeStyledString(font: .sub_m_b, text: value, color: .primary700) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CheckBoxButton.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CheckBoxButton.swift new file mode 100644 index 00000000..2b93edf5 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CheckBoxButton.swift @@ -0,0 +1,253 @@ +import UIKit + +import SnapKit + +public final class CheckBoxButton: UIButton { + // MARK: - Types + public enum CheckBoxButtonStyle { + case normal + case listSmall + case listMedium + case listLarge + + public var font: UIFont? { + switch self { + case .normal: + return .sub_m_b + case .listSmall, .listMedium: + return .b_s_r + case .listLarge: + return .b_m_r + } + } + + public var verticalInset: CGFloat { + switch self { + case .normal, .listLarge: + return 16 + case .listSmall: + return 4 + case .listMedium: + return 10 + } + } + + public var subtitleIsHidden: Bool { + switch self { + case .normal: + return false + default: + return true + } + } + + public var rightButtonIsHidden: Bool { + switch self { + case .listMedium: + return false + default: + return true + } + } + + public var backgroundColor: UIColor { + switch self { + case .normal: + return .neutral100 + default: + return .clearMLS + } + } + + public var textColor: UIColor { + switch self { + case .listSmall: + return .neutral700 + default: + return .textColor + } + } + + public var selecteTextColor: UIColor { + switch self { + case .listSmall: + return .primary700 + default: + return .textColor + } + } + + public var height: CGFloat? { + switch self { + case .normal: + return 56 + case .listSmall: + return 32 + case .listMedium: + return 44 + case .listLarge: + return nil + } + } + } + + private enum Constant { + static let imageSize: CGFloat = 24 + static let horizontalInset: CGFloat = 20 + static let labelSpacing: CGFloat = 4 + static let spacing: CGFloat = 8 + static let radius: CGFloat = 8 + } + + // MARK: - Properties + private let style: CheckBoxButtonStyle + + public var mainTitle: String? { + didSet { + updateText() + } + } + + public var subTitle: String? { + didSet { + updateText() + } + } + + override public var isSelected: Bool { + didSet { + updateTintColor() + } + } + + private lazy var contentStackView: UIStackView = { [weak self] in + let view = UIStackView() + view.isUserInteractionEnabled = false + view.spacing = Constant.spacing + return view + }() + + private let labelTrailingView: UIView = .init() + + private let checkIconImageView: UIImageView = { + let image = DesignSystemAsset.image(named: "checkCircleFill").withRenderingMode(.alwaysTemplate) + let view = UIImageView(image: image) + return view + }() + + private let buttonTitleLabel: UILabel = .init() + + private let buttonSubTitleLabel: UILabel = .init() + + public let rightButton: UIButton = { + let button = UIButton() + let image = DesignSystemAsset.image(named: "arrowForwardSmall").withRenderingMode(.alwaysTemplate) + button.setImage(image, for: .normal) + button.tintColor = .textColor + return button + }() + + // MARK: - init + public init(style: CheckBoxButtonStyle, mainTitle: String?, subTitle: String?) { + self.style = style + self.mainTitle = mainTitle + self.subTitle = subTitle + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } + + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + guard !isHidden, isUserInteractionEnabled, alpha > 0.01 else { return nil } + let view = super.hitTest(point, with: event) + if view != self { return view } + let rightPoint = convert(point, to: rightButton) + if rightButton.bounds.contains(rightPoint) && !rightButton.isHidden && rightButton.isUserInteractionEnabled { + return rightButton + } + return view + } +} + +// MARK: - SetUp +private extension CheckBoxButton { + func addViews() { + addSubview(contentStackView) + labelTrailingView.addSubview(buttonTitleLabel) + labelTrailingView.addSubview(buttonSubTitleLabel) + + if style == .listLarge { + contentStackView.addArrangedSubview(labelTrailingView) + contentStackView.addArrangedSubview(UIView()) + contentStackView.addArrangedSubview(checkIconImageView) + } else { + contentStackView.addArrangedSubview(checkIconImageView) + contentStackView.addArrangedSubview(labelTrailingView) + contentStackView.addArrangedSubview(UIView()) + contentStackView.addArrangedSubview(rightButton) + } + } + + func setupConstraints() { + snp.makeConstraints { make in + if let height = style.height { + make.height.equalTo(height) + } + } + + contentStackView.snp.makeConstraints { make in + if style == .listSmall { + make.horizontalEdges.equalToSuperview() + } else { + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalInset) + } + make.verticalEdges.equalToSuperview().inset(style.verticalInset) + } + + checkIconImageView.snp.makeConstraints { make in + make.size.equalTo(Constant.imageSize) + } + + buttonTitleLabel.snp.makeConstraints { make in + make.leading.verticalEdges.equalToSuperview() + make.centerY.equalToSuperview() + } + + buttonSubTitleLabel.snp.makeConstraints { make in + make.leading.equalTo(buttonTitleLabel.snp.trailing).offset(Constant.labelSpacing) + make.trailing.equalToSuperview() + make.centerY.equalToSuperview() + } + + rightButton.snp.makeConstraints { make in + make.size.equalTo(Constant.imageSize) + } + } + + func configureUI() { + updateTintColor() + updateText() + + buttonTitleLabel.font = style.font + buttonSubTitleLabel.isHidden = style.subtitleIsHidden + backgroundColor = style.backgroundColor + layer.cornerRadius = Constant.radius + rightButton.isHidden = style.rightButtonIsHidden + } + + func updateTintColor() { + checkIconImageView.tintColor = isSelected ? .primary700 : .neutral300 + buttonTitleLabel.attributedText = .makeStyledString(font: style.font, text: mainTitle, color: isSelected ? style.selecteTextColor : style.textColor) + } + + func updateText() { + buttonTitleLabel.attributedText = .makeStyledString(font: style.font, text: mainTitle, color: style.textColor) + buttonSubTitleLabel.attributedText = .makeStyledString(font: .b_m_r, text: subTitle) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CollectionList.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CollectionList.swift new file mode 100644 index 00000000..2c6d0240 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CollectionList.swift @@ -0,0 +1,143 @@ +import UIKit + +import SnapKit + +public final class CollectionList: UIView { + private enum Constant { + static let imageSize: CGFloat = 36 + static let imageInset: CGFloat = 4 + static let imageSpacing: CGFloat = 4 + static let imageRadius: CGFloat = 6 + static let contentInset: CGFloat = 10 + static let labelLeadingMargin: CGFloat = 20 + static let labelTrailingMargin: CGFloat = 64 + static let iconSize: CGFloat = 24 + static let radius: CGFloat = 12 + } + + // MARK: - Components + private lazy var imageViews: [ItemImageView] = (0 ..< 4).map { _ in + let view = ItemImageView( + image: nil, + cornerRadius: Constant.imageRadius, + inset: Constant.imageInset, + backgroundColor: .neutral200 + ) + return view + } + + private lazy var imageGridView: UIStackView = { + let topRow = UIStackView(arrangedSubviews: Array(imageViews[0...1])) + topRow.axis = .horizontal + topRow.spacing = Constant.imageSpacing + topRow.distribution = .fillEqually + + let bottomRow = UIStackView(arrangedSubviews: Array(imageViews[2...3])) + bottomRow.axis = .horizontal + bottomRow.spacing = Constant.imageSpacing + bottomRow.distribution = .fillEqually + + let stack = UIStackView(arrangedSubviews: [topRow, bottomRow]) + stack.axis = .vertical + stack.spacing = Constant.imageSpacing + return stack + }() + + private let titleLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + label.lineBreakMode = .byTruncatingTail + return label + }() + + private let subtitleLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + return label + }() + + private lazy var textStackView: UIStackView = { + let stack = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) + stack.axis = .vertical + stack.spacing = 4 + return stack + }() + + private let clickIcon: UIImageView = { + let view = UIImageView(image: DesignSystemAsset.image(named: "arrowForwardSmall")) + view.tintColor = .black + return view + }() + + // MARK: - Init + override public init(frame: CGRect) { + super.init(frame: frame) + addViews() + setupConstraints() + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension CollectionList { + func addViews() { + addSubview(imageGridView) + addSubview(textStackView) + addSubview(clickIcon) + } + + func setupConstraints() { + imageGridView.snp.makeConstraints { make in + make.leading.equalToSuperview().inset(Constant.contentInset) + make.verticalEdges.equalToSuperview().inset(Constant.contentInset) + make.width.height.equalTo((Constant.imageSize * 2) + Constant.imageSpacing) + } + + textStackView.snp.makeConstraints { make in + make.leading.equalTo(imageGridView.snp.trailing).offset(Constant.labelLeadingMargin) + make.centerY.equalToSuperview() + } + + clickIcon.snp.makeConstraints { make in + make.leading.equalTo(textStackView.snp.trailing).offset(Constant.labelTrailingMargin) + make.trailing.equalToSuperview().inset(Constant.contentInset) + make.centerY.equalToSuperview() + make.width.height.equalTo(Constant.iconSize) + } + + imageViews.forEach { + $0.snp.makeConstraints { make in + make.width.height.equalTo(Constant.imageSize) + } + } + } + + func configureUI() { + backgroundColor = .whiteMLS + layer.cornerRadius = Constant.radius + clipsToBounds = true + } +} + +public extension CollectionList { + func setTitle(text: String) { + titleLabel.attributedText = .makeStyledString(font: .b_s_m, text: text, alignment: .left) + } + + func setSubtitle(text: String) { + subtitleLabel.attributedText = .makeStyledString(font: .cp_xs_r, text: text, color: .neutral500, alignment: .left) + } + + func setImages(images: [UIImage?]) { + for (index, view) in imageViews.enumerated() { + let imageView = view.subviews.compactMap { $0 as? UIImageView }.first + print("이미지 뷰 설정") + imageView?.image = index < images.count ? images[index] : nil + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CommonButton.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CommonButton.swift new file mode 100644 index 00000000..738acf56 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/CommonButton.swift @@ -0,0 +1,193 @@ +import UIKit + +import SnapKit + +public final class CommonButton: UIButton { + // MARK: - Type + public enum CommonButtonStyle { + case normal + case text + case border + + public var height: CGFloat { + switch self { + case .normal, .border: + return 54 + case .text: + return 44 + } + } + + public var backgroundColor: UIColor { + switch self { + case .normal: + .primary700 + case .text, .border: + .clearMLS + } + } + + public var borderColor: UIColor { + switch self { + case .normal, .text: + UIColor.clearMLS + case .border: + UIColor.neutral300 + } + } + + public var textColor: UIColor { + switch self { + case .normal: + .whiteMLS + case .text, .border: + .textColor + } + } + + public var font: UIFont? { + switch self { + case .normal: + .btn_m_b + case .text: + .btn_s_r + case .border: + .btn_m_r + } + } + } + + private enum Constant { + static let height: CGFloat = 54 + static let normalStyleCornerRadius: CGFloat = 8 + static let textLineHeight: CGFloat = 1.2 + static let buttonInsets = NSDirectionalEdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20) + } + + // MARK: - Properties + private let style: CommonButtonStyle + private var title: String? + private var disabledTitle: String? + + override public var isEnabled: Bool { + didSet { + configureUI() + } + } + + // MARK: - init + public init(style: CommonButtonStyle, title: String?, disabledTitle: String?) { + self.style = style + self.title = title + self.disabledTitle = disabledTitle + super.init(frame: .zero) + configureUI() + } + + public init() { + self.style = .normal + self.title = nil + self.disabledTitle = nil + super.init(frame: .zero) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension CommonButton { + func configureUI() { + var config = UIButton.Configuration.plain() + config.contentInsets = Constant.buttonInsets + + switch style { + case .normal, .border: + config.background.backgroundColor = isEnabled ? style.backgroundColor : .neutral300 + config.background.cornerRadius = Constant.normalStyleCornerRadius + let currentTitle = isEnabled ? title : disabledTitle + config.attributedTitle = AttributedString(.makeStyledString(font: style.font, text: currentTitle, color: isEnabled ? style.textColor : .whiteMLS) ?? .init()) + config.baseForegroundColor = isEnabled ? style.textColor : .whiteMLS + switch style { + case .border: + config.background.strokeColor = isEnabled ? style.borderColor : .neutral300 + config.background.strokeWidth = 1 + default: + break + } + configuration = config + snp.makeConstraints { make in + make.height.equalTo(style.height) + } + case .text: + config.background.backgroundColor = .clear + let currentTitle = isEnabled ? title : disabledTitle + if let textButtonTitle = currentTitle, + let lineHeight = style.font?.lineHeight { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.minimumLineHeight = lineHeight * Constant.textLineHeight + paragraphStyle.maximumLineHeight = lineHeight * Constant.textLineHeight + paragraphStyle.alignment = .center + + let enabledAttributedString = NSAttributedString( + string: textButtonTitle, + attributes: [ + .foregroundColor: isEnabled ? style.textColor : .neutral700, + .underlineStyle: NSUnderlineStyle.single.rawValue, + .underlineColor: isEnabled ? style.textColor : .neutral700, + .paragraphStyle: paragraphStyle, + .font: style.font ?? UIFont() + ] + ) + config.attributedTitle = AttributedString(enabledAttributedString) + } + configuration = config + } + + configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + var updatedConfig = button.configuration + switch button.state { + case .highlighted: + switch style { + case .normal: + updatedConfig?.background.backgroundColor = self.style.backgroundColor.withAlphaComponent(0.9) + case .border: + updatedConfig?.background.backgroundColor = UIColor.neutral100 + default: + break + } + default: + updatedConfig?.background.backgroundColor = self.isEnabled ? self.style.backgroundColor : .neutral300 + } + button.configuration = updatedConfig + } + } +} + +public extension CommonButton { + func updateTitle(title: String, disabledTitle: String? = nil) { + self.title = title + if let disabledTitle = disabledTitle { + self.disabledTitle = disabledTitle + } + configureUI() + } + + func updateTitleColor(color: UIColor, for state: UIControl.State = .normal) { + var config = configuration ?? UIButton.Configuration.plain() + + if var attributedTitle = config.attributedTitle { + var container = AttributeContainer() + container.foregroundColor = color + attributedTitle.mergeAttributes(container, mergePolicy: .keepNew) + config.attributedTitle = attributedTitle + } else if let title = title(for: state) { + config.attributedTitle = AttributedString(title, attributes: AttributeContainer([.foregroundColor: color])) + } + + configuration = config + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DictionaryDetailListView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DictionaryDetailListView.swift new file mode 100644 index 00000000..a3b9c42e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DictionaryDetailListView.swift @@ -0,0 +1,132 @@ +import SnapKit +import UIKit + +public final class DictionaryDetailListView: UIStackView { + // MARK: - Type + private enum Constant { + static let height: CGFloat = 50 + static let horizontalInset: CGFloat = 7 + static let iconSize: CGFloat = 24 + static let spacing: CGFloat = 9 + } + + // MARK: - Components + private let mainLabel = UILabel() + private let mainButtonLabel = UILabel() + private lazy var mainButton = makeButton(label: mainButtonLabel) + + private let leftSpacer = UIView() + private let rightSpacer = UIView() + + private let mainAdditionalLabel = UILabel() + private let spacer = UIView() + + private let subLabel = UILabel() + private let subButtonLabel = UILabel() + private lazy var subButton = makeButton(label: subButtonLabel) + + private let underLine: UIView = { + let view = UIView() + view.backgroundColor = .neutral200 + return view + }() + + // MARK: - init + public init() { + super.init(frame: .zero) + axis = .horizontal + spacing = Constant.spacing + alignment = .center + + addBaseViews() + setupConstraints() + } + + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +private extension DictionaryDetailListView { + func addBaseViews() { + addArrangedSubview(leftSpacer) + addArrangedSubview(spacer) + addArrangedSubview(rightSpacer) + addSubview(underLine) + } + + func setupConstraints() { + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + + leftSpacer.snp.makeConstraints { make in + make.width.equalTo(Constant.horizontalInset) + } + + rightSpacer.snp.makeConstraints { make in + make.width.equalTo(Constant.horizontalInset) + } + + underLine.snp.makeConstraints { make in + make.horizontalEdges.bottom.equalToSuperview() + make.height.equalTo(1) + } + } + + func makeButton(label: UILabel) -> UIButton { + let button = UIButton() + let icon = UIImageView(image: UIImage(named: "rightArrow")) + + button.addSubview(label) + button.addSubview(icon) + + label.snp.makeConstraints { make in + make.leading.verticalEdges.equalToSuperview() + } + + icon.snp.makeConstraints { make in + make.leading.equalTo(label.snp.trailing) + make.trailing.centerY.equalToSuperview() + make.size.equalTo(Constant.iconSize) + } + + return button + } +} + +extension DictionaryDetailListView { + public func update(mainText: String? = nil, clickableMainText: String? = nil, additionalText: String? = nil, subText: String? = nil, clickableSubText: String? = nil) { + let fixedViews: Set = [leftSpacer, spacer, rightSpacer] + arrangedSubviews + .filter { !fixedViews.contains($0) } + .forEach { removeArrangedSubview($0); $0.removeFromSuperview() } + + insertArrangedSubview(leftSpacer, at: 0) + + if let mainText = mainText { + mainLabel.attributedText = .makeStyledString(font: .sub_m_sb, text: mainText) + insertArrangedSubview(mainLabel, at: 1) + } + + if let clickableMainText = clickableMainText { + mainButtonLabel.attributedText = .makeStyledUnderlinedString(font: .sub_m_sb, text: clickableMainText) + insertArrangedSubview(mainButton, at: arrangedSubviews.firstIndex(of: spacer) ?? 0) + } + + if let additionalText = additionalText { + mainAdditionalLabel.attributedText = .makeStyledString(font: .sub_m_sb, text: additionalText) + insertArrangedSubview(mainAdditionalLabel, at: arrangedSubviews.firstIndex(of: spacer) ?? 0) + } + + if let subText = subText { + subLabel.attributedText = .makeStyledString(font: .btn_s_r, text: subText) + insertArrangedSubview(subLabel, at: arrangedSubviews.firstIndex(of: rightSpacer) ?? 0) + } + + if let clickableSubText = clickableSubText { + subButtonLabel.attributedText = .makeStyledUnderlinedString(font: .btn_s_r, text: clickableSubText) + insertArrangedSubview(subButton, at: arrangedSubviews.firstIndex(of: rightSpacer) ?? 0) + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DividerView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DividerView.swift new file mode 100644 index 00000000..8f636bae --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DividerView.swift @@ -0,0 +1,19 @@ +import UIKit + +import SnapKit + +public final class DividerView: UIView { + // MARK: - init + public init() { + super.init(frame: .zero) + self.backgroundColor = .neutral200 + self.snp.makeConstraints { make in + make.height.equalTo(1) + } + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DropDownBox/DropDownBox.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DropDownBox/DropDownBox.swift new file mode 100644 index 00000000..7be4f3f8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DropDownBox/DropDownBox.swift @@ -0,0 +1,184 @@ +import UIKit + +import SnapKit + +public final class DropDownBox: UIStackView { + // MARK: - Properties + private var isExpanded = false + private var tableViewHeightConstraint: Constraint? + private var selectedIndex: Int? { + didSet { + tableView.reloadData() + } + } + + public var selectedItem: Item? { + guard let index = selectedIndex, items.indices.contains(index) else { + return nil + } + return items[index] + } + + // 선택 이벤트 콜백 + public var onItemSelected: ((Item) -> Void)? + + public var items = [Item]() { + didSet { + tableView.reloadData() + } + } + + // MARK: - Components + public let inputBox = InputBox() + + private let iconButton: UIButton = { + let view = UIButton() + view.setImage(DesignSystemAsset.image(named: "arrowDropdown"), for: .normal) + return view + }() + + public let tableView: UITableView = { + let tableView = UITableView() + tableView.isHidden = true + tableView.layer.borderWidth = 1 + tableView.layer.cornerRadius = 8 + tableView.layer.borderColor = UIColor.neutral300.cgColor + tableView.separatorStyle = .none + tableView.isScrollEnabled = false + tableView.contentInset = UIEdgeInsets(top: 4, left: 0, bottom: 4, right: 0) + tableView.register(DropDownBoxCell.self, forCellReuseIdentifier: "DropDownCell") + return tableView + }() + + // MARK: - Init + public init(label: String? = nil, placeHodler: String? = nil, items: [Item]) { + self.items = items + super.init(frame: .zero) + + inputBox.label.attributedText = .makeStyledString(font: .b_s_r, text: label, color: .neutral700, alignment: .left) + inputBox.textField.attributedPlaceholder = .makeStyledString(font: .b_m_r, text: placeHodler, color: .neutral500, alignment: .left) + + setupStackView() + setupInputBox() + setupTableView() + configureTap() + } + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - Setup +private extension DropDownBox { + func setupStackView() { + axis = .vertical + spacing = 4 + alignment = .fill + addArrangedSubview(inputBox) + addArrangedSubview(tableView) + } + + func setupInputBox() { + inputBox.borderView.addSubview(iconButton) + + inputBox.textField.snp.remakeConstraints { make in + make.verticalEdges.equalToSuperview().inset(16) + make.leading.equalToSuperview().inset(20) + } + + iconButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalTo(inputBox.textField.snp.trailing).offset(8) + make.trailing.equalToSuperview().inset(20) + make.size.equalTo(24) + } + + inputBox.borderView.layer.borderColor = UIColor.neutral300.cgColor + inputBox.textField.isUserInteractionEnabled = false + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap)) + inputBox.borderView.addGestureRecognizer(tapGesture) + inputBox.borderView.isUserInteractionEnabled = true + } + + func setupTableView() { + tableView.delegate = self + tableView.dataSource = self + + tableView.snp.makeConstraints { make in + make.horizontalEdges.equalTo(inputBox) + tableViewHeightConstraint = make.height.equalTo(0).constraint + } + } + + func configureTap() { + let action = UIAction { [weak self] _ in + self?.toggleDropdown() + } + iconButton.addAction(action, for: .touchUpInside) + } + + func toggleDropdown() { + isExpanded.toggle() + tableView.isHidden = !isExpanded + iconButton.setImage(isExpanded ? DesignSystemAsset.image(named: "arrowDropUp") : DesignSystemAsset.image(named: "arrowDropdown"), for: .normal) + let height = CGFloat(items.count) * 44 + tableView.contentInset.top + tableView.contentInset.bottom + tableViewHeightConstraint?.update(offset: isExpanded ? height : 0) + } + + func removeKeyboard() { + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) + } + + @objc private func handleTap() { + toggleDropdown() + removeKeyboard() + } +} + +// MARK: - UITableView +extension DropDownBox: UITableViewDataSource, UITableViewDelegate { + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return items.count + } + + public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "DropDownCell", for: indexPath) as? DropDownBoxCell else { + return UITableViewCell() + } + let isSelected = selectedIndex == indexPath.row + cell.injection(with: items[indexPath.row].name, isSelected: isSelected) + cell.selectionStyle = .none + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + selectedIndex = indexPath.row + let selectedItem = items[indexPath.row] + inputBox.textField.attributedText = .makeStyledString(font: .b_m_r, text: selectedItem.name, alignment: .left, lineHeight: 1.0) + inputBox.textField.sendActions(for: .editingChanged) + toggleDropdown() + + onItemSelected?(selectedItem) + } + + public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 44 + } +} + +// MARK: Model +extension DropDownBox { + public struct Item { + public let name: String + public let id: Int + + public init(name: String, id: Int) { + self.name = name + self.id = id + } + } + +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DropDownBox/DropDownBoxCell.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DropDownBox/DropDownBoxCell.swift new file mode 100644 index 00000000..183b96ef --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/DropDownBox/DropDownBoxCell.swift @@ -0,0 +1,61 @@ +import UIKit + +import SnapKit + +final class DropDownBoxCell: UITableViewCell { + // MARK: - Type + private enum Constant { + static let horizontalInset: CGFloat = 20 + static let verticalInset: CGFloat = 10 + static let cellInset: CGFloat = 4 + static let radius: CGFloat = 8 + } + + // MARK: - Components + private let titleLabel = UILabel() + + private let backgroundColorView: UIView = { + let view = UIView() + view.layer.cornerRadius = Constant.radius + return view + }() + + // MARK: - init + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + addViews() + setupContstraints() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension DropDownBoxCell { + func addViews() { + contentView.addSubview(backgroundColorView) + backgroundColorView.addSubview(titleLabel) + } + + func setupContstraints() { + titleLabel.snp.makeConstraints { make in + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalInset) + make.verticalEdges.equalToSuperview().inset(Constant.verticalInset) + } + + backgroundColorView.snp.makeConstraints { make in + make.horizontalEdges.equalToSuperview().inset(Constant.cellInset) + make.verticalEdges.equalToSuperview() + } + } +} + +extension DropDownBoxCell { + func injection(with input: String, isSelected: Bool) { + titleLabel.attributedText = .makeStyledString(font: .b_m_r, text: input, color: isSelected ? .textColor : .neutral500, alignment: .left) + backgroundColorView.backgroundColor = isSelected ? .neutral100 : .clearMLS + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ErrorMessage.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ErrorMessage.swift new file mode 100644 index 00000000..973bb586 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ErrorMessage.swift @@ -0,0 +1,69 @@ +import UIKit + +import SnapKit + +public final class ErrorMessage: UIView { + private enum Constant { + static let verticalEdgesInset: CGFloat = 8 + static let horizontalEdges: CGFloat = 20 + static let cornerRadius: CGFloat = 18 + static let spacing: CGFloat = 4 + static let height: CGFloat = 36 + static let iconSize: CGFloat = 16 + } + + // MARK: - Properties + private let iconView: UIImageView = { + let view = UIImageView() + view.image = UIImage(named: "error") + return view + }() + + public let label = UILabel() + + // MARK: - init + public init(message: String?) { + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI(message: message) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension ErrorMessage { + func addViews() { + addSubview(iconView) + addSubview(label) + } + + func setupConstraints() { + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + + iconView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalToSuperview().inset(Constant.horizontalEdges) + make.size.equalTo(Constant.iconSize) + } + + label.snp.makeConstraints { make in + make.verticalEdges.equalToSuperview().inset(Constant.verticalEdgesInset) + make.leading.equalTo(self.iconView.snp.trailing).offset(Constant.spacing) + make.trailing.equalToSuperview().inset(Constant.horizontalEdges) + } + } + + func configureUI(message: String?) { + self.backgroundColor = .error100 + self.layer.cornerRadius = Constant.cornerRadius + self.clipsToBounds = true + self.label.attributedText = .makeStyledString(font: .b_s_r, text: message, color: .error900) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/FloatingActionButton.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/FloatingActionButton.swift new file mode 100644 index 00000000..841459a8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/FloatingActionButton.swift @@ -0,0 +1,34 @@ +import UIKit + +import SnapKit + +public final class FloatingActionButton: UIButton { + // MARK: - Properties + private var action: (() -> Void)? + + // MARK: - LifeCycle + public init(action: @escaping () -> Void) { + self.action = action + super.init(frame: .zero) + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension FloatingActionButton { + func configureUI() { + setImage(UIImage(named: "fab"), for: .normal) + layer.cornerRadius = 24 + clipsToBounds = true + addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) + } + + @objc private func buttonTapped() { + action?() + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/GuideAlert.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/GuideAlert.swift new file mode 100644 index 00000000..13e1f05e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/GuideAlert.swift @@ -0,0 +1,110 @@ +import UIKit + +import SnapKit + +public class GuideAlert: UIView { + // MARK: - Type + enum Constant { + static let verticalInset: CGFloat = 20 + static let horizontalInset: CGFloat = 20 + static let iconSize: CGFloat = 48 + static let verticalSpacing: CGFloat = 24 + static let buttonSpacing: CGFloat = 4 + static let buttonHeight: CGFloat = 48 + static let alertWidth: CGFloat = 327 + static let radius: CGFloat = 24 + } + + // MARK: - Components + private let warningIconView: UIImageView = { + let view = UIImageView() + view.image = UIImage(named: "warning") + return view + }() + + public let mainTextLabel = UILabel() + public let buttonStackView: UIStackView = { + let view = UIStackView() + view.spacing = Constant.buttonSpacing + return view + }() + + public var ctaButton: CommonButton + public var cancelButton: CommonButton? + + // MARK: - init + public init(mainText: String, ctaText: String, cancelText: String?, ctaRatio: Double = 0.7) { + mainTextLabel.attributedText = .makeStyledString(font: .sub_l_b, text: mainText) + self.ctaButton = CommonButton(style: .normal, title: ctaText, disabledTitle: nil) + self.cancelButton = cancelText.map { CommonButton(style: .border, title: $0, disabledTitle: nil) } + mainTextLabel.numberOfLines = 0 + super.init(frame: .zero) + + addViews(cancelText: cancelText) + setupConstraints(ctaRatio: ctaRatio) + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension GuideAlert { + func addViews(cancelText: String?) { + addSubview(warningIconView) + addSubview(mainTextLabel) + addSubview(buttonStackView) + + if let cancelButton = cancelButton { + buttonStackView.addArrangedSubview(cancelButton) + } + buttonStackView.addArrangedSubview(ctaButton) + } + + func setupConstraints(ctaRatio: Double) { + snp.makeConstraints { make in + make.width.equalTo(Constant.alertWidth) + } + + warningIconView.snp.makeConstraints { make in + make.top.equalToSuperview().inset(Constant.verticalInset) + make.centerX.equalToSuperview() + make.size.equalTo(Constant.iconSize) + } + + mainTextLabel.snp.makeConstraints { make in + make.top.equalTo(warningIconView.snp.bottom).offset(Constant.verticalInset) + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalInset) + } + + buttonStackView.snp.makeConstraints { make in + make.top.equalTo(mainTextLabel.snp.bottom).offset(Constant.verticalSpacing) + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalInset) + make.bottom.equalToSuperview().inset(Constant.verticalInset) + make.height.equalTo(Constant.buttonHeight) + } + + if let cancelButton = cancelButton { + let cancelRatio = 1 - ctaRatio + + cancelButton.snp.makeConstraints { make in + make.width.equalTo(buttonStackView.snp.width).multipliedBy(cancelRatio).offset(-Constant.buttonSpacing) + } + ctaButton.snp.makeConstraints { make in + make.width.equalTo(buttonStackView.snp.width).multipliedBy(ctaRatio).offset(-Constant.buttonSpacing) + } + } else { + ctaButton.snp.makeConstraints { make in + make.width.equalTo(buttonStackView.snp.width) + } + } + } + + func configureUI() { + backgroundColor = .whiteMLS + layer.cornerRadius = Constant.radius + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Header.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Header.swift new file mode 100644 index 00000000..1da7a8b4 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Header.swift @@ -0,0 +1,102 @@ +import UIKit + +import SnapKit + +public final class Header: UIStackView { + // MARK: - Type + public enum HeaderStyle { + case main + case filter + + public var titleFont: UIFont? { + switch self { + case .main: + return .h_xxxl_sb + case .filter: + return .h_xl_sb + } + } + + var icons: [UIImage] { + switch self { + case .main: + return [DesignSystemAsset.image(named: "search"), DesignSystemAsset.image(named: "bell")].compactMap { $0 } + case .filter: + return [DesignSystemAsset.image(named: "largeX")].compactMap { $0 } + } + } + } + + private enum Constant { + static let iconSize: CGFloat = 24 + static let spacing: CGFloat = 16 + static let mainTypeHeight: CGFloat = 44 + } + + // MARK: - Properties + public let style: HeaderStyle + + // MARK: - Components + public let titleLabel = UILabel() + private let spacer = UIView() + public let firstIconButton = UIButton() + public let secondIconButton = UIButton() + + // MARK: - init + public init(style: HeaderStyle, title: String) { + titleLabel.attributedText = .makeStyledString(font: .h_xxxl_sb, text: title) + self.style = style + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI() + } + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension Header { + func addViews() { + addArrangedSubview(titleLabel) + addArrangedSubview(spacer) + addArrangedSubview(firstIconButton) + if style == .main { + addArrangedSubview(secondIconButton) + } + } + + func setupConstraints() { + if style == .main { + snp.makeConstraints { make in + make.height.equalTo(Constant.mainTypeHeight) + } + } + + firstIconButton.snp.makeConstraints { make in + make.size.equalTo(Constant.iconSize) + } + + secondIconButton.snp.makeConstraints { make in + make.size.equalTo(Constant.iconSize) + } + } + + func configureUI() { + alignment = .center + isLayoutMarginsRelativeArrangement = true + layoutMargins = UIEdgeInsets(top: 0, left: Constant.spacing, bottom: 0, right: Constant.spacing) + axis = .horizontal + spacing = Constant.spacing + titleLabel.font = style.titleFont + titleLabel.textColor = .textColor + firstIconButton.setImage(style.icons[0], for: .normal) + if style == .main { + secondIconButton.setImage(style.icons[1], for: .normal) + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/InputBox.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/InputBox.swift new file mode 100644 index 00000000..9ee776a5 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/InputBox.swift @@ -0,0 +1,105 @@ +import UIKit + +import SnapKit + +public final class InputBox: UIStackView { + // MARK: - Properties + private var type: InputBoxType = .edit { + didSet { + setBorderColor() + } + } + + // MARK: - Components + public let label = UILabel() + public let textField: UITextField = { + let textField = UITextField() + textField.clearButtonMode = .whileEditing + return textField + }() + + public lazy var borderView: UIView = { + let view = UIView() + view.layer.cornerRadius = 8 + view.layer.borderWidth = 1 + view.layer.borderColor = UIColor.neutral300.cgColor + + view.addSubview(textField) + + textField.snp.makeConstraints { make in + make.verticalEdges.equalToSuperview().inset(16) + make.leading.equalToSuperview().inset(20) + make.trailing.equalToSuperview().inset(10) + } + return view + }() + + // MARK: - Init + public init(label: String? = nil, placeHodler: String? = nil) { + super.init(frame: .zero) + configureUI(label: label, placeHodler: placeHodler) + } + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension InputBox { + func setupStackView() { + addArrangedSubview(label) + addArrangedSubview(borderView) + + spacing = 4 + axis = .vertical + alignment = .leading + } + + func setupLabel(label: String?) { + self.label.attributedText = .makeStyledString(font: .b_s_r, text: label, color: .neutral700, alignment: .left) + } + + func setupTextField(placeHolder: String?) { + textField.attributedPlaceholder = .makeStyledString(font: .b_m_r, text: placeHolder, color: .neutral500, alignment: .left) + } + + func setupConstaraints() { + borderView.snp.makeConstraints { make in + make.horizontalEdges.equalToSuperview() + } + } + + func configureUI(label: String?, placeHodler: String?) { + setupStackView() + setupLabel(label: label) + setupTextField(placeHolder: placeHodler) + setupConstaraints() + } + + func setBorderColor() { + borderView.layer.borderColor = type.borderColor.cgColor + } +} + +// MARK: - Mothods +public extension InputBox { + func setType(type: InputBoxType) { + self.type = type + } +} + +public enum InputBoxType { + case edit + case error + + var borderColor: UIColor { + switch self { + case .edit: + return .neutral300 + case .error: + return .error900 + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ItemImageView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ItemImageView.swift new file mode 100644 index 00000000..57a15624 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ItemImageView.swift @@ -0,0 +1,54 @@ +import UIKit + +import SnapKit + +public final class ItemImageView: UIView { + private let imageView = UIImageView() + + init(image: UIImage?, cornerRadius: CGFloat, inset: CGFloat, backgroundColor: UIColor) { + super.init(frame: .zero) + addViews() + setUpConstraints(inset: inset) + configureUI(radius: cornerRadius) + setImage(image: image, backgroundColor: backgroundColor) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension ItemImageView { + func addViews() { + addSubview(imageView) + } + + func setUpConstraints(inset: CGFloat) { + imageView.snp.makeConstraints { make in + make.edges.equalToSuperview().inset(inset) + } + } + + func configureUI(radius: CGFloat) { + layer.cornerRadius = radius + imageView.contentMode = .scaleAspectFit + imageView.backgroundColor = .clearMLS + } +} + +public extension ItemImageView { + func setImage(image: UIImage?, backgroundColor: UIColor) { + imageView.image = image + self.backgroundColor = backgroundColor + } + + func setMapImage(image: UIImage?, backgroundColor: UIColor) { + setImage(image: image, backgroundColor: backgroundColor) + imageView.snp.remakeConstraints { make in + make.center.equalToSuperview() + make.size.equalTo(40) + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/NavigationBar.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/NavigationBar.swift new file mode 100644 index 00000000..46a5cd02 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/NavigationBar.swift @@ -0,0 +1,182 @@ +import UIKit + +import SnapKit + +public final class NavigationBar: UIView { + // MARK: - Types + public enum NavigationType { + case withUnderLine(String) + case arrowRightLeft + case arrowLeft + case withString(String) + case collection(String) + } + + private enum Constant { + static let spacing: CGFloat = 8 + static let imageSize: CGFloat = 44 + static let rightInset: CGFloat = 16 + static let lineHeight: CGFloat = 1.17 + } + + // MARK: - Properties + private let contentStackView: UIStackView = { + let view = UIStackView() + view.alignment = .center + view.spacing = Constant.spacing + return view + }() + + public let leftButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(DesignSystemAsset.image(named: "arrowBack").withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = .textColor + return button + }() + + public let rightButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(DesignSystemAsset.image(named: "arrowForward").withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = .textColor + return button + }() + + public let underlineTextButton: UIButton = { + let button = UIButton() + button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10) + return button + }() + + public let boldTextButton: UIButton = { + let button = UIButton() + button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10) + return button + }() + + private let collectionTitleLabel = UILabel() + public let editButton: UIButton = { + let button = UIButton() + button.setImage(DesignSystemAsset.image(named: "edit"), for: .normal) + return button + }() + + public let addButton: UIButton = { + let button = UIButton() + button.setImage(DesignSystemAsset.image(named: "addIcon"), for: .normal) + return button + }() + + // MARK: - init + public init(type: NavigationType) { + super.init(frame: .zero) + addViews(type: type) + setupConstraints(type: type) + configureUI(type: type) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension NavigationBar { + func addViews(type: NavigationType) { + addSubview(contentStackView) + + switch type { + case .withUnderLine: + contentStackView.addArrangedSubview(leftButton) + contentStackView.addArrangedSubview(UIView()) + contentStackView.addArrangedSubview(underlineTextButton) + case .arrowRightLeft: + contentStackView.addArrangedSubview(leftButton) + contentStackView.addArrangedSubview(UIView()) + contentStackView.addArrangedSubview(rightButton) + case .arrowLeft: + contentStackView.addArrangedSubview(leftButton) + contentStackView.addArrangedSubview(UIView()) + case .withString: + contentStackView.addArrangedSubview(leftButton) + contentStackView.addArrangedSubview(UIView()) + contentStackView.addArrangedSubview(boldTextButton) + case .collection: + contentStackView.addArrangedSubview(leftButton) + contentStackView.addArrangedSubview(collectionTitleLabel) + contentStackView.addArrangedSubview(UIView()) + contentStackView.addArrangedSubview(editButton) + contentStackView.addArrangedSubview(addButton) + } + } + + func setupConstraints(type: NavigationType) { + contentStackView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + leftButton.snp.makeConstraints { make in + make.size.equalTo(Constant.imageSize) + } + switch type { + case .withUnderLine, .arrowRightLeft: + rightButton.snp.makeConstraints { make in + make.size.equalTo(Constant.imageSize) + } + case .withString: + boldTextButton.snp.makeConstraints { make in + make.trailing.equalToSuperview().inset(10) + } + case .collection: + editButton.snp.makeConstraints { make in + make.size.equalTo(Constant.imageSize) + } + addButton.snp.makeConstraints { make in + make.size.equalTo(Constant.imageSize) + } + default: + break + } + } + + func configureUI(type: NavigationType) { + switch type { + case .withUnderLine(let title): + guard let lineHeight = UIFont.b_s_r?.lineHeight, + let font = UIFont.b_m_r else { return } + + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.minimumLineHeight = lineHeight * Constant.lineHeight + paragraphStyle.maximumLineHeight = lineHeight * Constant.lineHeight + paragraphStyle.alignment = .center + + let attributedString = NSAttributedString( + string: title, + attributes: [ + .font: font, + .foregroundColor: UIColor.neutral700, + .underlineStyle: NSUnderlineStyle.single.rawValue, + .underlineColor: UIColor.neutral700, + .paragraphStyle: paragraphStyle + ] + ) + underlineTextButton.setAttributedTitle(attributedString, for: .normal) + case .withString(let title): + boldTextButton.setAttributedTitle( + .makeStyledString(font: .btn_m_b, text: title), + for: .normal + ) + case .collection(let title): + collectionTitleLabel.text = title + collectionTitleLabel.font = .b_m_r + collectionTitleLabel.textColor = .textColor + case .arrowRightLeft, .arrowLeft: + break + } + } +} + +public extension NavigationBar { + func setTitle(title: String) { + collectionTitleLabel.text = title + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/SearchBar.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/SearchBar.swift new file mode 100644 index 00000000..35cb221a --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/SearchBar.swift @@ -0,0 +1,163 @@ +import UIKit + +import SnapKit + +public protocol SearchBarDelegate: AnyObject { + func searchBarDidReturn(_ searchBar: SearchBar, text: String) +} + +public final class SearchBar: UIView { + // MARK: - Properties + public weak var searchDelegate: SearchBarDelegate? + + // MARK: - Components + public let backButton: UIButton = { + let button = UIButton(type: .system) + let image = DesignSystemAsset.image(named: "arrowBack").withRenderingMode(.alwaysTemplate) + button.setImage(image, for: .normal) + button.tintColor = .textColor + return button + }() + + public let textField: UITextField = { + let textField = UITextField() + textField.font = .b_l_r + textField.textColor = .textColor + textField.attributedPlaceholder = .makeStyledString(font: .b_l_r, text: "찾는 정보를 검색해 보세요", color: .neutral300) + textField.textAlignment = .left + textField.tintColor = .primary300 + textField.returnKeyType = .search + return textField + }() + + private let contentStackView: UIStackView = { + let view = UIStackView() + view.axis = .horizontal + view.alignment = .center + view.spacing = 8 + return view + }() + + public let searchButton: UIButton = { + let button = UIButton(type: .system) + let image = DesignSystemAsset.image(named: "search").withRenderingMode(.alwaysTemplate) + button.setImage(image, for: .normal) + button.tintColor = .textColor + return button + }() + + public let clearButton: UIButton = { + let button = UIButton(type: .custom) + let image = DesignSystemAsset.image(named: "textFieldClear") + button.setImage(image, for: .normal) + button.isHidden = true + return button + }() + + private let lineView: UIView = { + let view = UIView() + view.backgroundColor = .neutral300 + return view + }() + + private let fillLineView: UIView = { + let view = UIView() + view.backgroundColor = .primary700 + view.transform = CGAffineTransform(scaleX: 0, y: 1) + return view + }() + + // MARK: - init + public init() { + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension SearchBar { + func addViews() { + addSubview(contentStackView) + addSubview(lineView) + lineView.addSubview(fillLineView) + + contentStackView.addArrangedSubview(backButton) + contentStackView.addArrangedSubview(textField) + contentStackView.addArrangedSubview(clearButton) + contentStackView.addArrangedSubview(searchButton) + } + + func setupConstraints() { + contentStackView.snp.makeConstraints { make in + make.verticalEdges.leading.equalToSuperview() + make.trailing.equalToSuperview().inset(10) + } + lineView.snp.makeConstraints { make in + make.horizontalEdges.bottom.equalToSuperview() + make.height.equalTo(2) + } + backButton.snp.makeConstraints { make in + make.size.equalTo(44) + } + searchButton.snp.makeConstraints { make in + make.size.equalTo(44) + } + textField.snp.makeConstraints { make in + make.height.equalTo(25) + } + clearButton.snp.makeConstraints { make in + make.size.equalTo(19) + } + fillLineView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + + func configureUI() { + textField.delegate = self + clearButton.addAction(.init(handler: { [weak self] _ in self?.textField.text = "" }), for: .touchUpInside) + searchButton.addAction(.init(handler: { [weak self] _ in self?.endEditing(true) }), for: .touchUpInside) + } +} + +extension SearchBar: UITextFieldDelegate { + public func textFieldDidBeginEditing(_ textField: UITextField) { + clearButton.isHidden = (textField.text ?? "").isEmpty + UIView.animate(withDuration: 0.35, delay: 0, options: [.curveEaseOut]) { + self.fillLineView.transform = CGAffineTransform.identity + } + } + + public func textFieldDidEndEditing(_ textField: UITextField) { + clearButton.isHidden = true + UIView.animate(withDuration: 0.35, delay: 0, options: [.curveEaseIn]) { + self.fillLineView.transform = CGAffineTransform(scaleX: 0.001, y: 1) + } completion: { _ in + self.fillLineView.transform = CGAffineTransform(scaleX: 0, y: 1) + } + } + + public func textFieldShouldReturn(_ textField: UITextField) -> Bool { + searchDelegate?.searchBarDidReturn(self, text: textField.text ?? "") + + endEditing(true) + clearButton.isHidden = true + return true + } + + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + let currentText = textField.text ?? "" + guard let textRange = Range(range, in: currentText) else { return true } + let updatedText = currentText.replacingCharacters(in: textRange, with: string) + clearButton.isHidden = updatedText.isEmpty || !textField.isFirstResponder + return true + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/SnackBar.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/SnackBar.swift new file mode 100644 index 00000000..d093cf82 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/SnackBar.swift @@ -0,0 +1,115 @@ +import UIKit + +import SnapKit + +public final class SnackBar: UIView { + private enum Constant { + static let imageSize: CGFloat = 32 + static let imageInset: CGFloat = 5 + static let horizontalInset: CGFloat = 16 + static let width: CGFloat = 343 + static let height: CGFloat = 48 + static let spacing: CGFloat = 8 + static let radius: CGFloat = 8 + } + + // MARK: - ProPerties + private let type: SnackBarType + + // MARK: - Components + public let imageView: ItemImageView + private let label = UILabel() + private let button = UIButton() + + // MARK: - init + public init(type: SnackBarType, image: UIImage?, imageBackgroundColor: UIColor, text: String, buttonText: String, buttonAction: (() -> Void)?) { + self.type = type + imageView = ItemImageView(image: image, cornerRadius: 3.432, inset: 5, backgroundColor: imageBackgroundColor) + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI(text: text, buttonText: buttonText, buttonAction: buttonAction) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension SnackBar { + func addViews() { + addSubview(imageView) + addSubview(label) + addSubview(button) + } + + func setupConstraints() { + snp.makeConstraints { make in + make.width.equalTo(Constant.width) + make.height.equalTo(Constant.height) + } + + imageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalToSuperview().inset(Constant.horizontalInset) + make.size.equalTo(Constant.imageSize) + } + + label.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalTo(imageView.snp.trailing).offset(Constant.spacing) + } + + button.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalTo(label.snp.trailing) + make.trailing.equalToSuperview().inset(Constant.horizontalInset) + } + + label.setContentHuggingPriority(.defaultLow, for: .horizontal) + label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + + button.setContentHuggingPriority(.required, for: .horizontal) + button.setContentCompressionResistancePriority(.required, for: .horizontal) + } + + func configureUI(text: String, buttonText: String, buttonAction: (() -> Void)?) { + layer.cornerRadius = Constant.radius + clipsToBounds = true + + label.adjustsFontSizeToFitWidth = true + label.attributedText = .makeStyledString(font: .b_s_r, text: text, color: .whiteMLS, alignment: .left) + + let attributedTitle = NSAttributedString( + string: buttonText, + attributes: [ + .font: UIFont.btn_xs_r ?? UIFont.systemFont(ofSize: 12), + .foregroundColor: UIColor.whiteMLS, + .underlineStyle: NSUnderlineStyle.single.rawValue, + .underlineColor: UIColor.whiteMLS + ] + ) + button.setAttributedTitle(attributedTitle, for: .normal) + button.backgroundColor = .clear + button.addAction(UIAction { _ in + buttonAction?() + }, for: .touchUpInside) + + switch type { + case .normal: + backgroundColor = .neutral900 + case .delete: + backgroundColor = .error900 + } + } +} + +public extension SnackBar { + enum SnackBarType { + case normal + case delete + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/StepIndicator.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/StepIndicator.swift new file mode 100644 index 00000000..3b219fbc --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/StepIndicator.swift @@ -0,0 +1,57 @@ +import UIKit + +import SnapKit + +public final class StepIndicator: UIStackView { + // MARK: - Type + private enum Constant { + static let circleSize: CGFloat = 8 + static let spacing: CGFloat = 8 + } + + // MARK: - Components + + // MARK: - init + public init(circleCount: Int) { + super.init(frame: .zero) + configureUI(circleCount: circleCount) + } + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension StepIndicator { + func configureUI(circleCount: Int) { + axis = .horizontal + distribution = .fillEqually + spacing = Constant.spacing + + for _ in 0 ..< circleCount { + let view = UIImageView(image: DesignSystemAsset.image(named: "circle").withRenderingMode(.alwaysTemplate)) + view.contentMode = .scaleAspectFit + view.tintColor = .neutral300 + addArrangedSubview(view) + } + + arrangedSubviews.forEach { view in + view.snp.makeConstraints { make in + make.size.equalTo(Constant.circleSize) + } + } + } +} + +public extension StepIndicator { + func selectIndicator(index: Int) { + guard index >= 0, index < arrangedSubviews.count else { return } + + arrangedSubviews.enumerated().forEach { circleIndex, view in + guard let circle = view as? UIImageView else { return } + circle.tintColor = (index == circleIndex) ? .primary700 : .neutral300 + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/BottomTabBar.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/BottomTabBar.swift new file mode 100644 index 00000000..bf1c2a71 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/BottomTabBar.swift @@ -0,0 +1,100 @@ +import UIKit + +import SnapKit + +// MARK: - Model +public struct TabItem { + var title: String + var icon: UIImage +} + +public final class BottomTabBar: UIStackView { + // MARK: - Type + private enum Constant { + static let height: CGFloat = 64 + static let buttonSize: CGFloat = 64 + } + + // MARK: - Properties + public var onTabSelected: ((Int) -> Void)? + + private var tabButtons: [TabButton] = [] + private var selectedIndex: Int = 0 { + didSet { + selectIndex() + } + } + + // MARK: - Init + public init(tabItems: [TabItem], selectedIndex: Int) { + self.selectedIndex = selectedIndex + super.init(frame: .zero) + setUpConstraints() + configureUI(tabItems: tabItems) + setupStackView() + selectIndex() + } + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Setup + + private func setUpConstraints() { + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + } + + private func configureUI(tabItems: [TabItem]) { + tabButtons.forEach { $0.removeFromSuperview() } + tabButtons.removeAll() + arrangedSubviews.forEach { removeArrangedSubview($0); $0.removeFromSuperview() } + + for (index, item) in tabItems.enumerated() { + if index > 0 { + let spacer = UIView() + spacer.setContentHuggingPriority(.defaultLow, for: .horizontal) + spacer.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + addArrangedSubview(spacer) + } + + let button = TabButton(icon: item.icon, text: item.title) + button.tag = index + button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) + addArrangedSubview(button) + tabButtons.append(button) + + button.snp.makeConstraints { make in + make.width.equalTo(Constant.buttonSize) + } + } + } + + private func setupStackView() { + backgroundColor = .systemBackground + axis = .horizontal + distribution = .equalSpacing + spacing = 0 + } + + @objc private func tabButtonTapped(_ sender: TabButton) { + let newIndex = sender.tag + guard newIndex != selectedIndex else { return } + selectedIndex = newIndex + onTabSelected?(newIndex) + } + + private func selectIndex() { + for (index, button) in tabButtons.enumerated() { + button.isSelected = (index == selectedIndex) + } + } + + public func selectTab(index: Int) { + guard index != selectedIndex else { return } + selectedIndex = index + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/BottomTabBarController.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/BottomTabBarController.swift new file mode 100644 index 00000000..0a3ebd03 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/BottomTabBarController.swift @@ -0,0 +1,105 @@ +import UIKit + +import SnapKit + +public final class BottomTabBarController: UITabBarController { + // MARK: - Type + private enum Constant { + static let horizontalInset: CGFloat = 24 + } + + // MARK: - Components + private let divider = DividerView() + private let tabItems: [TabItem] + private let customTabBar: BottomTabBar + + // MARK: - Init + public init(viewControllers: [UIViewController], initialIndex: Int = 0) { + tabItems = [ + TabItem(title: "도감", icon: DesignSystemAsset.image(named: "dictionary")), + TabItem(title: "북마크", icon: DesignSystemAsset.image(named: "bookmarkList")), + TabItem(title: "MY", icon: DesignSystemAsset.image(named: "mypage")) + ] + customTabBar = BottomTabBar(tabItems: tabItems, selectedIndex: initialIndex) + super.init(nibName: nil, bundle: nil) + configureUI(controllers: viewControllers) + selectedIndex = initialIndex + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + addViews() + setupConstraints() + } +} + +// MARK: - SetUp +private extension BottomTabBarController { + func addViews() { + view.addSubview(customTabBar) + view.addSubview(divider) + } + + func setupConstraints() { + divider.snp.makeConstraints { make in + make.horizontalEdges.equalToSuperview() + make.bottom.equalTo(customTabBar.snp.top) + } + + customTabBar.snp.makeConstraints { make in + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalInset) + make.bottom.equalTo(view.safeAreaLayoutGuide) + } + } + + func configureUI(controllers: [UIViewController]) { + viewControllers = controllers.map { + if $0 is UINavigationController { + return $0 + } else { + return UINavigationController(rootViewController: $0) + } + } + tabBar.isHidden = true + + customTabBar.onTabSelected = { [weak self] index in + UIView.performWithoutAnimation { + self?.selectedIndex = index + self?.customTabBar.selectTab(index: index) + } + } + } +} + +public extension BottomTabBarController { + func setHidden(hidden: Bool, animated: Bool = false) { + guard customTabBar.isHidden != hidden else { return } + + if animated { + UIView.animate(withDuration: 0.3) { + self.customTabBar.alpha = hidden ? 0 : 1 + self.divider.alpha = hidden ? 0 : 1 + } completion: { _ in + self.customTabBar.isHidden = hidden + self.divider.isHidden = hidden + } + } else { + customTabBar.isHidden = hidden + customTabBar.alpha = hidden ? 0 : 1 + divider.isHidden = hidden + divider.alpha = hidden ? 0 : 1 + } + } + + func selectTab(index: Int, animated: Bool = false) { + UIView.performWithoutAnimation { + selectedIndex = index + customTabBar.selectTab(index: index) + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/TabButton.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/TabButton.swift new file mode 100644 index 00000000..664c2ea1 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Tabbar/TabButton.swift @@ -0,0 +1,73 @@ +import UIKit + +import SnapKit + +public final class TabButton: UIButton { + // MARK: - Type + private enum Constant { + static let spacing: CGFloat = 4 + static let iconSize: CGFloat = 24 + } + + // MARK: - Properties + override public var isSelected: Bool { + didSet { + updateUI() + } + } + + // MARK: - Components + private lazy var contentView: UIStackView = { + let view = UIStackView(arrangedSubviews: [iconView, textLabel]) + view.axis = .vertical + view.spacing = Constant.spacing + view.alignment = .center + view.isUserInteractionEnabled = false + return view + }() + + private let iconView = UIImageView() + private let textLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + return label + }() + + // MARK: - Init + public init(icon: UIImage, text: String) { + super.init(frame: .zero) + iconView.image = icon.withRenderingMode(.alwaysTemplate) + textLabel.text = text + addViews() + setupConstraints() + updateUI() + } + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension TabButton { + func addViews() { + addSubview(contentView) + } + + func setupConstraints() { + contentView.snp.makeConstraints { make in + make.center.equalToSuperview() + } + + iconView.snp.makeConstraints { make in + make.size.equalTo(Constant.iconSize) + } + } + + func updateUI() { + iconView.tintColor = isSelected ? .primary700 : .neutral300 + textLabel.textColor = isSelected ? .primary700 : .neutral700 + textLabel.font = .systemFont(ofSize: 11, weight: isSelected ? .semibold : .regular) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TagChip.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TagChip.swift new file mode 100644 index 00000000..61c23aa8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TagChip.swift @@ -0,0 +1,162 @@ +import UIKit + +import SnapKit + +public final class TagChip: UIButton { + // MARK: - Type + public enum TagChipStyle { + case normal + case search + case text + + var borderWidth: CGFloat { + switch self { + case .normal, .text: return 0 + case .search: return 1 + } + } + + var borderColor: CGColor { + switch self { + case .normal, .text: return UIColor.clearMLS.cgColor + case .search: return UIColor.neutral300.cgColor + } + } + + var fontColor: UIColor { + switch self { + case .normal, .text: return .primary700 + case .search: return .textColor + } + } + + var backgroundColor: UIColor { + switch self { + case .normal, .text: return .primary50 + case .search: return .clearMLS + } + } + + var radius: CGFloat { + switch self { + case .normal: return 16 + case .text: return 12 + case .search: return 8 + } + } + + var contentInsets: NSDirectionalEdgeInsets { + switch self { + case .normal: + return .init(top: 4, leading: 12, bottom: 4, trailing: 8) + case .text: + return .init(top: 4, leading: 12, bottom: 4, trailing: 12) + case .search: + return .init(top: 4, leading: 10, bottom: 4, trailing: 10) + } + } + + var font: UIFont? { + switch self { + case .text: return .cp_s_sb + case .normal, .search: return .cp_s_r + } + } + + var isHiddenButton: Bool { + switch self { + case .normal, .search: return false + case .text: return true + } + } + } + + private enum Constant { + static let height: CGFloat = 32 + static let imageSize: CGFloat = 24 + } + + // MARK: - Properties + public var style: TagChipStyle { + didSet { updateUI() } + } + + public var text: String? { + didSet { updateUI() } + } + + public let mainTitleLabel = UILabel() + + public let cancelButton: UIButton = { + let button = UIButton(type: .custom) + return button + }() + + private var cancelButtonWidthConstraint: Constraint? + + // MARK: - init + public init(style: TagChipStyle, text: String?) { + self.style = style + self.text = text + super.init(frame: .zero) + + setupLayout() + configureUI() + updateUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError() + } +} + +private extension TagChip { + func setupLayout() { + addSubview(mainTitleLabel) + addSubview(cancelButton) + + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + + mainTitleLabel.snp.makeConstraints { make in + make.leading.equalToSuperview().inset(style.contentInsets.leading) + make.centerY.equalToSuperview() + make.trailing.lessThanOrEqualTo(cancelButton.snp.leading).offset(-4) + } + + cancelButton.snp.makeConstraints { make in + make.trailing.equalToSuperview().inset(style.contentInsets.trailing) + make.centerY.equalToSuperview() + cancelButtonWidthConstraint = make.width.equalTo(Constant.imageSize).constraint + make.height.equalTo(Constant.imageSize) + } + } + + func configureUI() { + let image = DesignSystemAsset.image(named: "smallX") + .withRenderingMode(.alwaysTemplate) + cancelButton.setImage(image, for: .normal) + } + + func updateUI() { + backgroundColor = style.backgroundColor + + mainTitleLabel.attributedText = .makeStyledString( + font: style.font, + text: text, + color: style.fontColor + ) + + layer.borderColor = style.borderColor + layer.borderWidth = style.borderWidth + layer.cornerRadius = style.radius + + cancelButton.tintColor = style.fontColor + + let hidden = style.isHiddenButton + cancelButton.isHidden = hidden + cancelButtonWidthConstraint?.update(offset: hidden ? 0 : Constant.imageSize) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TapButton.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TapButton.swift new file mode 100644 index 00000000..629fd51b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TapButton.swift @@ -0,0 +1,75 @@ +import UIKit + +import SnapKit + +public final class TapButton: UIButton { + // MARK: - Type + private enum Constant { + static let height: CGFloat = 34 + static let borderWidth: CGFloat = 1 + static let radius: CGFloat = 17 + static let contentInsets: NSDirectionalEdgeInsets = .init(top: 10, leading: 16, bottom: 10, trailing: 16) + } + + public let mainTitleLabel: UILabel = { + let label = UILabel() + return label + }() + + // MARK: - Properties + override public var isSelected: Bool { + didSet { + updateUI() + } + } + + public var text: String? { + didSet { + updateUI() + } + } + + // MARK: - init + public init(text: String? = nil) { + self.text = text + super.init(frame: .zero) + + setupConstraints() + configureUI() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension TapButton { + func setupConstraints() { + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + addSubview(mainTitleLabel) + mainTitleLabel.snp.makeConstraints { make in + make.horizontalEdges.equalToSuperview().inset(Constant.contentInsets.leading) + make.verticalEdges.equalToSuperview().inset(Constant.contentInsets.top) + } + } + + func configureUI() { + backgroundColor = .clear + layer.borderWidth = Constant.borderWidth + layer.cornerRadius = Constant.radius + layer.borderColor = isSelected ? UIColor.primary700.cgColor : UIColor.neutral200.cgColor + } + + func updateUI() { + mainTitleLabel.attributedText = .makeStyledString( + font: isSelected ? .cp_s_sb : .cp_s_r, + text: text, + color: isSelected ? .primary700 : .neutral700 + ) + layer.borderColor = isSelected ? UIColor.primary700.cgColor : UIColor.neutral200.cgColor + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TextButton.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TextButton.swift new file mode 100644 index 00000000..3b05ec06 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/TextButton.swift @@ -0,0 +1,75 @@ +import UIKit + +import SnapKit + +public final class TextButton: UIButton { + // MARK: - Type + + private enum Constant { + static let height: CGFloat = 32 + static let iconSize: CGFloat = 16 + static let horizontalInset: CGFloat = 12 + static let spacing: CGFloat = 4 + static let radius: CGFloat = 16 + } + + // MARK: - Properties + public let iconView: UIImageView = { + let view = UIImageView() + view.image = UIImage(named: "edit")?.withRenderingMode(.alwaysTemplate) + view.tintColor = .neutral700 + return view + }() + + public let textLabel: UILabel = { + let label = UILabel() + label.attributedText = .makeStyledString(font: .btn_s_r, text: "편집", color: .neutral700) + return label + }() + + // MARK: - init + public init() { + super.init(frame: .zero) + + addViews() + setupConstraints() + configureUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension TextButton { + func addViews() { + addSubview(iconView) + addSubview(textLabel) + } + + func setupConstraints() { + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + + iconView.snp.makeConstraints { make in + make.leading.equalToSuperview().inset(Constant.horizontalInset) + make.centerY.equalToSuperview() + make.size.equalTo(Constant.iconSize) + } + + textLabel.snp.makeConstraints { make in + make.leading.equalTo(iconView.snp.trailing).offset(Constant.spacing) + make.centerY.equalToSuperview() + make.trailing.equalToSuperview().inset(Constant.horizontalInset) + } + } + + func configureUI() { + backgroundColor = .whiteMLS + layer.cornerRadius = Constant.radius + layer.borderWidth = 1 + layer.borderColor = UIColor.neutral300.cgColor + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Toast.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Toast.swift new file mode 100644 index 00000000..a889b4c6 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/Toast.swift @@ -0,0 +1,59 @@ +import UIKit + +import SnapKit + +public final class Toast: UIView { + private enum Constant { + static let verticalEdgesInset: CGFloat = 16 + static let horizontalEdges: CGFloat = 16 + static let cornerRadius: CGFloat = 8 + } + + // MARK: - Properties + private let toastContentView: UIView = { + let view = UIView() + view.backgroundColor = .neutral900 + return view + }() + + private let label: UILabel = .init() + + // MARK: - init + public init(message: String?) { + super.init(frame: .zero) + + self.addViews() + self.setupConstraints() + self.configureUI(message: message) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension Toast { + func addViews() { + addSubview(self.toastContentView) + toastContentView.addSubview(self.label) + } + + func setupConstraints() { + toastContentView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + label.snp.makeConstraints { make in + make.verticalEdges.equalToSuperview().inset(Constant.verticalEdgesInset) + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalEdges) + } + } + + func configureUI(message: String?) { + layer.cornerRadius = Constant.cornerRadius + clipsToBounds = true + label.attributedText = .makeStyledString(font: .b_s_r, text: message, color: .whiteMLS) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ToggleBox.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ToggleBox.swift new file mode 100644 index 00000000..890de020 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Components/ToggleBox.swift @@ -0,0 +1,69 @@ +import UIKit + +import SnapKit + +public final class ToggleBox: UIView { + // MARK: - Type + enum Constant { + static let margin: CGFloat = 20 + static let toggleWidth: CGFloat = 51 + static let toggleHeight: CGFloat = 31 + static let radius: CGFloat = 8 + static let height: CGFloat = 60 + } + + // MARK: - Components + private let textLabel = UILabel() + + public let toggle: UISwitch = { + let button = UISwitch() + button.thumbTintColor = .whiteMLS + button.onTintColor = .primary700 + button.isOn = false + return button + }() + + public init(text: String?) { + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI(text: text) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension ToggleBox { + func addViews() { + addSubview(textLabel) + addSubview(toggle) + } + + func setupConstraints() { + snp.makeConstraints { make in + make.height.equalTo(Constant.height) + } + + textLabel.snp.makeConstraints { make in + make.verticalEdges.equalToSuperview().inset(Constant.margin) + make.leading.equalToSuperview().inset(Constant.margin) + } + + toggle.snp.makeConstraints { make in + make.leading.equalTo(textLabel.snp.trailing) + make.trailing.centerY.equalToSuperview().inset(Constant.margin) + make.width.equalTo(Constant.toggleWidth) + make.height.equalTo(Constant.toggleHeight) + } + } + + func configureUI(text: String?) { + textLabel.attributedText = .makeStyledString(font: .sub_m_b, text: text, alignment: .left) + backgroundColor = .neutral100 + layer.cornerRadius = Constant.radius + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/BaseErrorViewController.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/BaseErrorViewController.swift new file mode 100644 index 00000000..03e79c3f --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/BaseErrorViewController.swift @@ -0,0 +1,100 @@ +import UIKit + +import RxCocoa +import RxSwift +import SnapKit + +@MainActor +public final class BaseErrorViewController: UIViewController { + // MARK: - Type + private enum Constant { + static let imageHeight: CGFloat = 171 + static let imageWidth: CGFloat = 165 + static let componentsSpacing: CGFloat = 24 + static let bottomButtonBottomSpacing: CGFloat = 16 + static let centerYMultiplied: CGFloat = 0.7 + } + + // MARK: - Properties + private var disposeBag = DisposeBag() + + private let containerView: UIView = UIView() + + private let imageView: UIImageView = { + let image = DesignSystemAsset.image(named: "errorImage") + let view = UIImageView(image: image) + return view + }() + + private let descriptionLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 0 + label.attributedText = .makeStyledString(font: .b_m_r, text: "알 수 없는 오류가 발생했어요.\n이전 화면으로 돌아가 다시 시도해 주세요.") + return label + }() + + private let backButton = CommonButton(style: .normal, title: "뒤로가기", disabledTitle: nil) + + public init() { + super.init(nibName: nil, bundle: nil) + modalPresentationStyle = .fullScreen + } + + @MainActor public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - Life Cycle +extension BaseErrorViewController { + public override func viewDidLoad() { + super.viewDidLoad() + + addViews() + setupConstraints() + configureUI() + bind() + } +} + +// MARK: - SetUp +private extension BaseErrorViewController { + func addViews() { + view.addSubview(backButton) + containerView.addSubview(imageView) + containerView.addSubview(descriptionLabel) + view.addSubview(containerView) + } + + func setupConstraints() { + backButton.snp.makeConstraints { make in + make.bottom.horizontalEdges.equalTo(view.safeAreaLayoutGuide).inset(Constant.bottomButtonBottomSpacing) + } + imageView.snp.makeConstraints { make in + make.height.equalTo(Constant.imageHeight) + make.width.equalTo(Constant.imageWidth) + make.top.equalToSuperview().inset(Constant.componentsSpacing) + make.centerX.equalToSuperview() + } + descriptionLabel.snp.makeConstraints { make in + make.top.equalTo(imageView.snp.bottom).offset(Constant.componentsSpacing) + make.horizontalEdges.equalToSuperview() + make.bottom.equalToSuperview() + } + containerView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.centerY.equalToSuperview().multipliedBy(Constant.centerYMultiplied) + } + } + + func configureUI() { } + + func bind() { + backButton.rx.tap + .withUnretained(self) + .subscribe { (owner, _) in + owner.dismiss(animated: true) + } + .disposed(by: disposeBag) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/BaseListView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/BaseListView.swift new file mode 100644 index 00000000..9463d6c8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/BaseListView.swift @@ -0,0 +1,175 @@ +import UIKit + +import SnapKit + +open class BaseListView: UIView { + // MARK: - Type + enum Constant { + static let filterInset: CGFloat = 6 + static let filterHeight: CGFloat = 32 + static let iconSize: CGFloat = 24 + static let stackViewSpacing: CGFloat = 12 + static let topMargin: CGFloat = 12 + static let cellSpacing: CGFloat = 10 + static let cellWidth: CGFloat = 343 + static let cellHeight: CGFloat = 104 + static let horizontalMargin: CGFloat = 16 + static let bottomInset: CGFloat = 64 + } + + // MARK: - Components + public let editButton: UIButton? + public let listCollectionView: UICollectionView + public let sortButton: UIButton + public let filterButton: UIButton + public let emptyView: DataEmptyView + + private lazy var filterStackView: UIStackView = { + var subviews: [UIView] = [] + + if let editButton = editButton { + subviews.append(editButton) + } + subviews.append(UIView()) + subviews.append(sortButton) + subviews.append(filterButton) + + let view = UIStackView(arrangedSubviews: subviews) + view.axis = .horizontal + view.spacing = Constant.stackViewSpacing + view.alignment = .fill + return view + }() + + // MARK: - Init + public init(editButton: UIButton? = nil, + sortButton: UIButton, + filterButton: UIButton, + emptyView: DataEmptyView, + isFilterHidden: Bool) { + self.editButton = editButton + self.sortButton = sortButton + self.filterButton = filterButton + self.emptyView = emptyView + self.listCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout()) + + super.init(frame: .zero) + addViews(isFilterHidden: isFilterHidden) + setupConstraints(isFilterHidden: isFilterHidden) + configureUI() + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { fatalError() } +} + +// MARK: - Setup +private extension BaseListView { + func addViews(isFilterHidden: Bool) { + if !isFilterHidden { + addSubview(filterStackView) + } + addSubview(listCollectionView) + addSubview(emptyView) + } + + func setupConstraints(isFilterHidden: Bool) { + if isFilterHidden { + listCollectionView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + emptyView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } else { + filterStackView.snp.makeConstraints { make in + make.top.equalToSuperview().inset(Constant.topMargin) + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalMargin) + make.height.equalTo(Constant.filterHeight) + } + + listCollectionView.snp.makeConstraints { make in + make.top.equalTo(filterStackView.snp.bottom).offset(Constant.topMargin) + make.horizontalEdges.bottom.equalToSuperview() + } + + emptyView.snp.makeConstraints { make in + make.top.equalTo(filterStackView.snp.bottom).offset(Constant.topMargin) + make.horizontalEdges.bottom.equalToSuperview() + } + } + } + + func configureUI() { + backgroundColor = .neutral100 + listCollectionView.backgroundColor = .neutral100 + } +} + +// MARK: - Methods +public extension BaseListView { + func updateFilter(sortType: String?) { + let hasFilter = sortType != nil + filterStackView.isHidden = !hasFilter + + listCollectionView.snp.remakeConstraints { make in + if hasFilter { + make.top.equalTo(filterStackView.snp.bottom).offset(Constant.topMargin) + } else { + make.top.equalToSuperview() + } + make.horizontalEdges.bottom.equalToSuperview() + } + + if let sortType = sortType { + sortButton.setAttributedTitle(.makeStyledString(font: .b_s_r, text: sortType, color: sortButton.tintColor), for: .normal) + } + } + + func updateBookmarkFilter(type: String) { + if type == "total" { + filterButton.isHidden = true + } + } + + static func makeSortButton(title: String, tintColor: UIColor) -> UIButton { + let button = UIButton() + button.setAttributedTitle(.makeStyledString(font: .b_s_r, text: title), for: .normal) + button.setImage(DesignSystemAsset.image(named: "lineArrowDown").withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = tintColor + button.setTitleColor(tintColor, for: .normal) + button.semanticContentAttribute = .forceRightToLeft + return button + } + + static func makeFilterButton(title: String, tintColor: UIColor) -> UIButton { + let button = UIButton() + button.setAttributedTitle(.makeStyledString(font: .b_s_r, text: title), for: .normal) + button.setImage(DesignSystemAsset.image(named: "filter").withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = tintColor + button.setTitleColor(tintColor, for: .normal) + button.semanticContentAttribute = .forceRightToLeft + return button + } + + func selectSort(selectedType: String) { + sortButton.setAttributedTitle(.makeStyledString(font: .b_s_r, text: selectedType, color: .primary700), for: .normal) + sortButton.tintColor = .primary700 + } + + func selectFilter() { + filterButton.setAttributedTitle(.makeStyledString(font: .b_s_r, text: "필터", color: .primary700), for: .normal) + filterButton.tintColor = .primary700 + } + + func resetFilter() { + filterButton.setAttributedTitle(.makeStyledString(font: .b_s_r, text: "필터"), for: .normal) + filterButton.tintColor = .black + } + + func checkEmptyData(isEmpty: Bool) { + emptyView.isHidden = !isEmpty + listCollectionView.isHidden = isEmpty + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/CharacterInputView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/CharacterInputView.swift new file mode 100644 index 00000000..d0d2d557 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/CharacterInputView.swift @@ -0,0 +1,132 @@ +import UIKit + +import RxCocoa +import RxSwift +import SnapKit + +open class CharacterInputView: UIView { + // MARK: - Type + public enum Constant { + public static let horizontalInset: CGFloat = 16 + public static let verticalInset: CGFloat = 40 + static let verticalSpacing: CGFloat = 28 + static let horizontalSpacing: CGFloat = 8 + public static let bottomInset: CGFloat = 16 + static let messageSpacing: CGFloat = 8 + static let boxInset: CGFloat = (horizontalInset + (horizontalSpacing / 2)) / 2 + } + + // MARK: - Properties + private let disposeBag = DisposeBag() + public var nextButtonBottomConstraint: Constraint? + + // MARK: - Components + public let descriptionLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 2 + return label + }() + + public let inputBox: InputBox = { + let box = InputBox(label: "레벨", placeHodler: "1~200") + box.textField.keyboardType = .numberPad + return box + }() + + public let dropDownBox = DropDownBox(label: "직업", placeHodler: "선택", items: []) + + public let errorMessage = ErrorMessage(message: "1에서 200까지 숫자만 입력해주세요") + + public let nextButton = CommonButton(style: .normal, title: "다음", disabledTitle: "다음") + + // MARK: - init + public init(title: String? = nil) { + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI(title: title) + setGesture() + } + + @available(*, unavailable) + required public init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } +} + +// MARK: - SetUp +private extension CharacterInputView { + func addViews() { + addSubview(descriptionLabel) + addSubview(inputBox) + addSubview(dropDownBox) + addSubview(errorMessage) + addSubview(nextButton) + } + + func setupConstraints() { + inputBox.snp.makeConstraints { make in + make.top.equalTo(descriptionLabel.snp.bottom).offset(Constant.verticalSpacing) + make.leading.equalToSuperview().inset(Constant.horizontalInset) + make.width.equalToSuperview().multipliedBy(0.5).inset(Constant.boxInset) + } + + dropDownBox.snp.makeConstraints { make in + make.top.equalTo(inputBox) + make.leading.equalTo(inputBox.snp.trailing).offset(Constant.horizontalSpacing) + make.trailing.equalToSuperview().inset(Constant.horizontalInset) + make.width.equalToSuperview().multipliedBy(0.5).inset(Constant.boxInset) + } + + errorMessage.snp.makeConstraints { make in + make.centerX.equalToSuperview() + } + + nextButton.snp.makeConstraints { make in + make.top.equalTo(errorMessage.snp.bottom).offset(Constant.messageSpacing) + make.horizontalEdges.equalToSuperview().inset(Constant.horizontalInset) + nextButtonBottomConstraint = make.bottom.equalToSuperview().inset(Constant.bottomInset).constraint + } + } + + func configureUI(title: String? = nil) { + inputBox.textField.delegate = self + errorMessage.isHidden = true + + descriptionLabel.attributedText = .makeStyledString(font: .h_xxl_b, text: title ?? "현재 레벨과 직업을\n입력해주세요.", alignment: .left) + } + + /// inputBox를 제외한 영역 선택시 키보드 제거 + func setGesture() { + let tapGesture = UITapGestureRecognizer() + tapGesture.cancelsTouchesInView = false + addGestureRecognizer(tapGesture) + + Observable.merge( + tapGesture.rx.event.map { $0.location(in: self) }.asObservable() + ) + .withUnretained(self) + .filter { owner, location in + !owner.inputBox.frame.contains(location) + } + .subscribe { owner, _ in + owner.inputBox.textField.resignFirstResponder() + } + .disposed(by: disposeBag) + } +} + +// MARK: - UITextFieldDelegate +extension CharacterInputView: UITextFieldDelegate { + /// textField의 붙여넣기 기능 차단 + /// - Parameters: + /// - action: 선택자를 나타내는 selector + /// - sender: 동작을 트리거한 객체 + /// - Returns: 붙여넣기가 허용되면 true / 허용되지 않으면 false + override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { + if action == #selector(paste(_:)) { + return false + } + return super.canPerformAction(action, withSender: sender) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/DataEmptyView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/DataEmptyView.swift new file mode 100644 index 00000000..cf7bc3dd --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/DataEmptyView.swift @@ -0,0 +1,102 @@ +import UIKit + +import SnapKit + +public enum EmptyViewType { + case dictionary + case bookmark +} + +public final class DataEmptyView: UIView { + // MARK: - Type + enum Constant { + static let imageSize: CGFloat = 220 + static let textSpacing: CGFloat = 10 + static let buttonSpacing: CGFloat = 24 + static let buttonWidth: CGFloat = 186 + } + + // MARK: - Components + public let imageView = UIImageView() + private let mainLabel = UILabel() + private let subLabel = UILabel() + + public let button = CommonButton() + + // MARK: - Init + public init(type: EmptyViewType) { + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI(type: type) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension DataEmptyView { + func addViews() { + addSubview(imageView) + addSubview(mainLabel) + addSubview(subLabel) + addSubview(button) + } + + func setupConstraints() { + imageView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.size.equalTo(Constant.imageSize) + } + + mainLabel.snp.makeConstraints { make in + make.top.equalTo(imageView.snp.bottom) + make.centerY.equalToSuperview() + make.horizontalEdges.equalToSuperview() + } + + subLabel.snp.makeConstraints { make in + make.top.equalTo(mainLabel.snp.bottom).offset(Constant.textSpacing) + make.centerX.equalToSuperview() + } + + button.snp.makeConstraints { make in + make.top.equalTo(subLabel.snp.bottom).offset(Constant.buttonSpacing) + make.centerX.equalToSuperview() + make.width.equalTo(Constant.buttonWidth) + } + } + + func configureUI(type: EmptyViewType) { + backgroundColor = .neutral100 + + switch type { + case .dictionary: + imageView.image = DesignSystemAsset.image(named: "noResult") + mainLabel.attributedText = .makeStyledString( + font: .b_m_r, + text: "검색 결과가 없습니다." + ) + + subLabel.isHidden = true + button.isHidden = true + case .bookmark: + imageView.image = DesignSystemAsset.image(named: "noShowList") + mainLabel.attributedText = .makeStyledString( + font: .h_xl_b, + text: "아직 아무것도 없어요!" + ) + + subLabel.attributedText = .makeStyledString( + font: .cp_s_r, + text: "북마크해서 추가해보세요.", + color: .neutral600 + ) + + button.updateTitle(title: "북마크하러 가기") + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/GuideAlertFactory.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/GuideAlertFactory.swift new file mode 100644 index 00000000..a19c01ca --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/GuideAlertFactory.swift @@ -0,0 +1,108 @@ +import UIKit + +import RxCocoa +import RxSwift +import SnapKit + +@MainActor +public enum GuideAlertFactory { + private static var currentAlertView: GuideAlert? + private static var dimmedView: UIView? + private static var containerView: UIView? + private static var disposeBag = DisposeBag() + + public static func show( + mainText: String, + ctaText: String, + cancelText: String? = nil, + ctaAction: @escaping () -> Void, + cancelAction: (() -> Void)? = nil + ) { + let alert = GuideAlert(mainText: mainText, ctaText: ctaText, cancelText: cancelText) + presentAlert(alert: alert, ctaAction: ctaAction, cancelAction: cancelAction) + } + + public static func showAuthAlert( + type: AuthGuideAlert.AuthGuideAlertType, + ctaAction: @escaping () -> Void, + cancelAction: (() -> Void)? = nil + ) { + let alert = AuthGuideAlert(type: type) + presentAlert(alert: alert, ctaAction: ctaAction, cancelAction: cancelAction) + } + + private static func presentAlert( + alert: GuideAlert, + ctaAction: @escaping () -> Void, + cancelAction: (() -> Void)? = nil + ) { + guard currentAlertView == nil, dimmedView == nil else { return } + guard let windowScene = UIApplication.shared.connectedScenes + .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene, + let window = windowScene.windows.first(where: { $0.isKeyWindow }) else { return } + + let container = UIView(frame: window.bounds) + window.addSubview(container) + + let dimmed = UIView() + dimmed.backgroundColor = UIColor.black.withAlphaComponent(0.4) + dimmed.alpha = 0 + container.addSubview(dimmed) + dimmed.snp.makeConstraints { $0.edges.equalToSuperview() } + + alert.alpha = 0 + container.addSubview(alert) + alert.snp.makeConstraints { + $0.center.equalToSuperview() + $0.leading.greaterThanOrEqualToSuperview().offset(16) + $0.trailing.lessThanOrEqualToSuperview().offset(-16) + } + + disposeBag = DisposeBag() + + alert.ctaButton.rx.tap + .bind { + dismiss() + ctaAction() + } + .disposed(by: disposeBag) + + if let cancelButton = alert.cancelButton { + cancelButton.rx.tap + .bind { + dismiss() + cancelAction?() + } + .disposed(by: disposeBag) + } + + currentAlertView = alert + dimmedView = dimmed + containerView = container + + UIView.animate(withDuration: 0.25) { + dimmed.alpha = 1 + alert.alpha = 1 + } + } + + public static func dismiss() { + guard let alert = currentAlertView, + let dimmed = dimmedView, + let container = containerView + else { return } + + UIView.animate(withDuration: 0.25, animations: { + alert.alpha = 0 + dimmed.alpha = 0 + }, completion: { _ in + alert.removeFromSuperview() + dimmed.removeFromSuperview() + container.removeFromSuperview() + currentAlertView = nil + dimmedView = nil + containerView = nil + disposeBag = DisposeBag() + }) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/SnackBarFactory.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/SnackBarFactory.swift new file mode 100644 index 00000000..55da2afa --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/SnackBarFactory.swift @@ -0,0 +1,101 @@ +import UIKit + +import RxSwift +import SnapKit + +@MainActor +public enum SnackBarFactory { + // MARK: - Properties + + /// 현재 디바이스 최상단 Window를 지정 + static var window: UIWindow? { + return UIApplication + .shared + .connectedScenes + .flatMap { ($0 as? UIWindowScene)?.windows ?? [] } + .first { $0.isKeyWindow } + } + + /// 최상단의 ViewController를 가져오는 메서드 + private static func topViewController( + _ rootViewController: UIViewController? = window?.rootViewController + ) -> UIViewController? { + if let navigationController = rootViewController as? UINavigationController { + return topViewController(navigationController.visibleViewController) + } + if let tabBarController = rootViewController as? UITabBarController { + return topViewController(tabBarController.selectedViewController) + } + if let presentedViewController = rootViewController?.presentedViewController { + return topViewController(presentedViewController) + } + return rootViewController + } + + private static var currentSnackBar: SnackBar? + private static var disposeBag = DisposeBag() +} + +public extension SnackBarFactory { + // MARK: - Method + + /// SnackBar를 생성하는 메소드 + /// - Parameters: + /// - type: normal / delete + /// - image: 스낵바 이미지 + /// - imageBackgroundColor: 이미지 배경색상 + /// - text: 스낵바에 들어갈 내용 + /// - buttonText: 버튼 제목 + /// - buttonAction: 버튼이 눌렸을때의 액션 + static func createSnackBar( + type: SnackBar.SnackBarType, + image: UIImage, + imageBackgroundColor: UIColor, + text: String, + buttonText: String, + buttonAction: (() -> Void)?, + bottomMargin: CGFloat = 76 + ) { + DispatchQueue.main.async { + currentSnackBar?.removeFromSuperview() + currentSnackBar = nil + + let snackBar = SnackBar( + type: type, + image: image, + imageBackgroundColor: imageBackgroundColor, + text: text, + buttonText: buttonText, + buttonAction: buttonAction + ) + snackBar.alpha = 0 + + // ✅ window 대신 topViewController의 view 사용 + guard let topVC = topViewController() else { return } + topVC.view.addSubview(snackBar) + currentSnackBar = snackBar + + snackBar.snp.makeConstraints { make in + make.bottom.equalTo(topVC.view.safeAreaLayoutGuide.snp.bottom).inset(bottomMargin) + make.centerX.equalToSuperview() + } + + snackBar.imageView.setImage(image: image, backgroundColor: imageBackgroundColor) + + UIView.animate(withDuration: 0.25) { + snackBar.alpha = 1 + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 2.3) { + UIView.animate(withDuration: 0.6, animations: { + snackBar.alpha = 0 + }, completion: { _ in + snackBar.removeFromSuperview() + if currentSnackBar == snackBar { + currentSnackBar = nil + } + }) + } + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/ToastFactory.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/ToastFactory.swift new file mode 100644 index 00000000..849298ba --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/Factory/ToastFactory.swift @@ -0,0 +1,76 @@ +import UIKit + +import RxSwift +import SnapKit + +@MainActor +public final class ToastFactory { + + // MARK: - Properties + + /// 현재 디바이스 최상단 Window를 지정 + static var window: UIWindow? { + return UIApplication + .shared + .connectedScenes + .flatMap { ($0 as? UIWindowScene)?.windows ?? [] } + .first { $0.isKeyWindow } + } + + /// 최상단의 ViewController를 가져오는 메서드 + private static func topViewController( + _ rootViewController: UIViewController? = window?.rootViewController + ) -> UIViewController? { + if let navigationController = rootViewController as? UINavigationController { + return topViewController(navigationController.visibleViewController) + } + if let tabBarController = rootViewController as? UITabBarController { + return topViewController(tabBarController.selectedViewController) + } + if let presentedViewController = rootViewController?.presentedViewController { + return topViewController(presentedViewController) + } + return rootViewController + } + + private static var currentToast: Toast? + private static var disposeBag = DisposeBag() +} + +extension ToastFactory { + + // MARK: - Method + + /// 토스트 메시지를 생성하는 메서드 + /// - Parameter message: 토스트 메세지에 담길 String 타입 + public static func createToast(message: String) { + + currentToast?.removeFromSuperview() + currentToast = nil + let toastMSG = Toast(message: message) + guard let window = window else { return } + window.addSubview(toastMSG) + currentToast = toastMSG + + toastMSG.snp.makeConstraints { make in + make.bottom.equalTo(window.snp.bottom).inset(120) + make.centerX.equalTo(window.snp.centerX) + } + + toastMSG.alpha = 0 + UIView.animate(withDuration: 0.25) { + toastMSG.alpha = 1 + } + + UIView.animate( + withDuration: 0.6, + delay: 2.3, + options: .curveEaseOut + ) { + toastMSG.alpha = 0 + } completion: { _ in + toastMSG.removeFromSuperview() + if currentToast == toastMSG { currentToast = nil } + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ModalPresentable/ModalPresentable.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ModalPresentable/ModalPresentable.swift new file mode 100644 index 00000000..8d2b0a76 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ModalPresentable/ModalPresentable.swift @@ -0,0 +1,25 @@ +import UIKit + +public protocol ModalPresentable { + var modalHeight: CGFloat? { get } + var allowsTapToDismiss: Bool { get } +} + +public extension ModalPresentable { + var allowsTapToDismiss: Bool { return false } +} + +// 모달 구성 관련 상수 정의 +internal enum ModalConfig { + static let containerTransformY: CGFloat = 400 + static let containerBottomInset: CGFloat = 8 + static let containerHorizontalInset: CGFloat = 8 + static let containerCornerRadius: CGFloat = 20 + static let bottomSheetStyleBottomInset: CGFloat = 34 + static let bottomSheetStyleHorizontalInset: CGFloat = 20 + static let alertSheetStyleInset: CGFloat = 20 + + static let gestureBarTopInset: CGFloat = 12 + static let gestureBarWidth: CGFloat = 60 + static let gestureBarHeight: CGFloat = 4 +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ModalPresentable/ModalWrapperView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ModalPresentable/ModalWrapperView.swift new file mode 100644 index 00000000..177357e8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ModalPresentable/ModalWrapperView.swift @@ -0,0 +1,72 @@ +import UIKit + +import SnapKit + +final class ModalWrapperView: UIView { + + weak var parentViewController: UIViewController? + + let dimView = UIView() + let containerView = UIView() + + private var initialY: CGFloat = 0 + private var containerBottomConstraint: Constraint? + + init(contentViewController: UIViewController & ModalPresentable, parent: UIViewController) { + super.init(frame: .zero) + self.parentViewController = parent + + // 뒷배경 뷰 (반투명) + dimView.backgroundColor = .overlays + dimView.alpha = 0 + addSubview(dimView) + dimView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + if contentViewController.allowsTapToDismiss { + // 탭 시 모달 닫기 + let tap = UITapGestureRecognizer(target: parent, action: #selector(parent.dismissCurrentModal)) + dimView.addGestureRecognizer(tap) + } + + // 모달 컨테이너 + containerView.backgroundColor = .systemBackground + containerView.layer.cornerRadius = ModalConfig.containerCornerRadius + containerView.clipsToBounds = true + containerView.transform = CGAffineTransform(translationX: 0, y: ModalConfig.containerTransformY) + addSubview(containerView) + + containerView.snp.makeConstraints { make in + self.containerBottomConstraint = make.bottom.equalToSuperview().constraint + make.horizontalEdges.equalToSuperview() + } + + // 자식 뷰컨트롤러 embed + parent.addChild(contentViewController) + containerView.addSubview(contentViewController.view) + contentViewController.view.snp.makeConstraints { make in + make.bottom.equalToSuperview().inset(ModalConfig.bottomSheetStyleBottomInset) + make.top.horizontalEdges.equalToSuperview() + if let height = contentViewController.modalHeight { make.height.equalTo(height) } + } + contentViewController.didMove(toParent: parent) + } + + func animateDismiss(completion: @escaping () -> Void) { + if let bottomConstraint = containerBottomConstraint { + // 아래로 내리기 위해 음수 inset + bottomConstraint.update(inset: -containerView.bounds.height) + UIView.animate(withDuration: 0.35, delay: 0, options: [.curveEaseIn], animations: { + self.layoutIfNeeded() + self.dimView.alpha = 0 + }, completion: { _ in + completion() + }) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/TabBarUnderlineController.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/TabBarUnderlineController.swift new file mode 100644 index 00000000..572b7462 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/TabBarUnderlineController.swift @@ -0,0 +1,143 @@ +import UIKit + +import RxCocoa +import RxSwift +import SnapKit + +@MainActor +public final class TabBarUnderlineController { + // MARK: - UI Components + + /// 선택된 탭 아래를 표시하는 인디케이터 뷰 + private let selectionIndicatorView: UIView = { + let view = UIView() + view.backgroundColor = .textColor + return view + }() + + /// 탭 바 하단의 구분선 + private let bottomUnderlineView: UIView = { + let view = UIView() + view.backgroundColor = .neutral300 + return view + }() + + // MARK: - Properties + + private var collectionView: UICollectionView? + private let disposeBag = DisposeBag() + + /// 현재 컬렉션 뷰의 스크롤 오프셋 (인디케이터 위치 계산용) + private var currentScrollOffset: CGPoint? + + // MARK: - Initialization + + public init() {} + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - Setup + +private extension TabBarUnderlineController { + func addIndicatorViews(to collectionView: UICollectionView) { + guard let superview = collectionView.superview else { return } + + superview.addSubview(bottomUnderlineView) + bottomUnderlineView.snp.makeConstraints { make in + make.horizontalEdges.bottom.equalTo(collectionView) + make.height.equalTo(1) + } + + superview.addSubview(selectionIndicatorView) + selectionIndicatorView.frame = CGRect( + x: 0, + y: collectionView.frame.maxY - 2, + width: 0, + height: 2 + ) + } +} + +// MARK: - Public Interface + +public extension TabBarUnderlineController { + /// 컬렉션 뷰에 인디케이터 컨트롤러 연결 + func configure(with collectionView: UICollectionView) { + self.collectionView = collectionView + addIndicatorViews(to: collectionView) + } + + /// 컬렉션 뷰 스크롤 오프셋이 변경될 때 호출 (scrollViewDidScroll 등에서) + func updateScrollOffset(_ offset: CGPoint) { + currentScrollOffset = offset + updateIndicatorFrameWithoutAnimation() + } + + /// 선택된 셀 위치에 인디케이터를 즉시 이동 + func updateIndicatorFrameWithoutAnimation() { + guard let collectionView, + let indexPath = collectionView.indexPathsForSelectedItems?.first, + let selectedFrame = collectionView.cellForItem(at: indexPath)?.frame + else { return } + + let xOffset = selectedFrame.minX - (currentScrollOffset?.x ?? 0) + selectionIndicatorView.frame.origin.x = xOffset + } + + /// 선택된 셀 위치로 인디케이터를 애니메이션으로 이동 + func animateIndicatorToSelectedItem() { + guard let collectionView, + let indexPath = collectionView.indexPathsForSelectedItems?.first, + let selectedFrame = collectionView.cellForItem(at: indexPath)?.frame + else { return } + + let xOffset = selectedFrame.minX - (currentScrollOffset?.x ?? 0) + let targetFrame = CGRect( + x: xOffset, + y: collectionView.frame.maxY - 2, + width: selectedFrame.width, + height: 2 + ) + + UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseInOut], animations: { [weak self] in + self?.selectionIndicatorView.frame = targetFrame + }) + } + + /// 선택된 셀 위치로 인디케이터를 애니메이션으로 이동 + func setInitialIndicator() { + guard let collectionView, + let indexPath = collectionView.indexPathsForSelectedItems?.first, + let selectedFrame = collectionView.cellForItem(at: indexPath)?.frame + else { return } + + let xOffset = selectedFrame.minX - (currentScrollOffset?.x ?? 0) + let targetFrame = CGRect( + x: xOffset, + y: collectionView.frame.maxY - 2, + width: selectedFrame.width, + height: 2 + ) + selectionIndicatorView.frame = targetFrame + } + + func setHidden(hidden: Bool, animated: Bool = false) { + let alpha: CGFloat = hidden ? 0 : 1 + if animated { + UIView.animate(withDuration: 0.25) { + self.selectionIndicatorView.alpha = alpha + self.bottomUnderlineView.alpha = alpha + } + } else { + selectionIndicatorView.alpha = alpha + bottomUnderlineView.alpha = alpha + } + + selectionIndicatorView.isHidden = hidden + bottomUnderlineView.isHidden = hidden + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ToLoginView.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ToLoginView.swift new file mode 100644 index 00000000..f2914040 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Layouts/ToLoginView.swift @@ -0,0 +1,84 @@ +import UIKit + +import SnapKit + +public final class ToLoginView: UIView { + // MARK: - Type + enum Constant { + static let imageSize: CGFloat = 220 + static let textSpacing: CGFloat = 10 + static let buttonSpacing: CGFloat = 24 + static let buttonWidth: CGFloat = 186 + } + + // MARK: - Components + public let imageView = UIImageView() + private let mainLabel = UILabel() + private let subLabel = UILabel() + + public let button = CommonButton() + + // MARK: - Init + public init(mainText: String, subText: String, buttonText: String? = nil) { + super.init(frame: .zero) + addViews() + setupConstraints() + configureUI(mainText: mainText, subText: subText, buttonText: buttonText) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - SetUp +private extension ToLoginView { + func addViews() { + addSubview(imageView) + addSubview(mainLabel) + addSubview(subLabel) + addSubview(button) + } + + func setupConstraints() { + imageView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.size.equalTo(Constant.imageSize) + } + + mainLabel.snp.makeConstraints { make in + make.top.equalTo(imageView.snp.bottom) + make.centerY.equalToSuperview() + make.horizontalEdges.equalToSuperview() + } + + subLabel.snp.makeConstraints { make in + make.top.equalTo(mainLabel.snp.bottom).offset(Constant.textSpacing) + make.centerX.equalToSuperview() + } + + button.snp.makeConstraints { make in + make.top.equalTo(subLabel.snp.bottom).offset(Constant.buttonSpacing) + make.centerX.equalToSuperview() + make.width.equalTo(Constant.buttonWidth) + } + } + + func configureUI(mainText: String, subText: String, buttonText: String? = nil) { + backgroundColor = .neutral100 + imageView.image = DesignSystemAsset.image(named: "noShowList") + mainLabel.attributedText = .makeStyledString( + font: .h_xl_b, + text: mainText + ) + + subLabel.attributedText = .makeStyledString( + font: .cp_s_r, + text: subText, + color: .neutral600 + ) + + button.updateTitle(title: buttonText ?? "로그인하러 가기") + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Bold.ttf b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Bold.ttf new file mode 100644 index 00000000..fb07fc65 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Bold.ttf differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Medium.ttf b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Medium.ttf new file mode 100644 index 00000000..1db67c68 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Medium.ttf differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Regular.ttf b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Regular.ttf new file mode 100644 index 00000000..01147e99 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-Regular.ttf differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-SemiBold.ttf b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-SemiBold.ttf new file mode 100644 index 00000000..9f2690f0 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Font/Pretendard-SemiBold.ttf differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideAlert.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideAlert.imageset/Contents.json new file mode 100644 index 00000000..7911bc12 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideAlert.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "guideAlert.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideAlert.imageset/guideAlert.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideAlert.imageset/guideAlert.png new file mode 100644 index 00000000..c7fa2f9f Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideAlert.imageset/guideAlert.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow1.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow1.imageset/Contents.json new file mode 100644 index 00000000..c540110a --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "guideArrow1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow1.imageset/guideArrow1.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow1.imageset/guideArrow1.png new file mode 100644 index 00000000..07e674cb Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow1.imageset/guideArrow1.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow2.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow2.imageset/Contents.json new file mode 100644 index 00000000..4e3272ad --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "guideArrow2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow2.imageset/guideArrow2.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow2.imageset/guideArrow2.png new file mode 100644 index 00000000..2b33ee8b Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideArrow2.imageset/guideArrow2.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideIcon.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideIcon.imageset/Contents.json new file mode 100644 index 00000000..6d1fa50c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "guideIcon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideIcon.imageset/guideIcon.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideIcon.imageset/guideIcon.png new file mode 100644 index 00000000..d92f19e2 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/BookmarkOnboarding/guideIcon.imageset/guideIcon.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/DropDown.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/DropDown.imageset/Contents.json new file mode 100644 index 00000000..cd7ddaee --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/DropDown.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "dropDown.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/DropDown.imageset/dropDown.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/DropDown.imageset/dropDown.svg new file mode 100644 index 00000000..67225443 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/DropDown.imageset/dropDown.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Fab.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Fab.imageset/Contents.json new file mode 100644 index 00000000..4b7e95d7 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Fab.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Fab.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Fab.imageset/Fab.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Fab.imageset/Fab.svg new file mode 100644 index 00000000..b3840368 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/Fab.imageset/Fab.svg @@ -0,0 +1,4 @@ + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/addIcon.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/addIcon.imageset/Contents.json new file mode 100644 index 00000000..b4988ec2 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/addIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "add.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/addIcon.imageset/add.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/addIcon.imageset/add.svg new file mode 100644 index 00000000..0530ce26 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/addIcon.imageset/add.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/appleLogo.imageset/AppleLogo.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/appleLogo.imageset/AppleLogo.svg new file mode 100644 index 00000000..39e20f52 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/appleLogo.imageset/AppleLogo.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/appleLogo.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/appleLogo.imageset/Contents.json new file mode 100644 index 00000000..52803e85 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/appleLogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "AppleLogo.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowBack.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowBack.imageset/Contents.json new file mode 100644 index 00000000..fa1b15e0 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowBack.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "arrowBack.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowBack.imageset/arrowBack.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowBack.imageset/arrowBack.svg new file mode 100644 index 00000000..690091c6 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowBack.imageset/arrowBack.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropUp.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropUp.imageset/Contents.json new file mode 100644 index 00000000..9df632b0 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropUp.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "arrowDropUp.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropUp.imageset/arrowDropUp.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropUp.imageset/arrowDropUp.svg new file mode 100644 index 00000000..20352b31 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropUp.imageset/arrowDropUp.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropdown.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropdown.imageset/Contents.json new file mode 100644 index 00000000..62f4cae1 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropdown.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "arrowDropdown.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropdown.imageset/arrowDropdown.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropdown.imageset/arrowDropdown.svg new file mode 100644 index 00000000..bc11335c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowDropdown.imageset/arrowDropdown.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForward.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForward.imageset/Contents.json new file mode 100644 index 00000000..21e06750 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForward.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "arrwoForward.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForward.imageset/arrwoForward.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForward.imageset/arrwoForward.svg new file mode 100644 index 00000000..93f8e30d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForward.imageset/arrwoForward.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForwardSmall.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForwardSmall.imageset/Contents.json new file mode 100644 index 00000000..2d79acc7 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForwardSmall.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "arrowForwordSmall.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForwardSmall.imageset/arrowForwordSmall.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForwardSmall.imageset/arrowForwordSmall.svg new file mode 100644 index 00000000..f0d29991 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/arrowForwardSmall.imageset/arrowForwordSmall.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bell.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bell.imageset/Contents.json new file mode 100644 index 00000000..b0db2947 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bell.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bell.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bell.imageset/bell.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bell.imageset/bell.svg new file mode 100644 index 00000000..389cbbae --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bell.imageset/bell.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmark.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmark.imageset/Contents.json new file mode 100644 index 00000000..b9a0914c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmark.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmark.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmark.imageset/bookmark.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmark.imageset/bookmark.svg new file mode 100644 index 00000000..4df98315 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmark.imageset/bookmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorder.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorder.imageset/Contents.json new file mode 100644 index 00000000..718b074b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorder.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmark_border.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorder.imageset/bookmark_border.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorder.imageset/bookmark_border.svg new file mode 100644 index 00000000..bf456cff --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorder.imageset/bookmark_border.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorderList.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorderList.imageset/Contents.json new file mode 100644 index 00000000..684a4e90 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorderList.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmarkBorderList.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorderList.imageset/bookmarkBorderList.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorderList.imageset/bookmarkBorderList.png new file mode 100644 index 00000000..9fe9661a Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkBorderList.imageset/bookmarkBorderList.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorder.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorder.imageset/Contents.json new file mode 100644 index 00000000..dda7fb83 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorder.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmarkBorder.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorder.imageset/bookmarkBorder.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorder.imageset/bookmarkBorder.svg new file mode 100644 index 00000000..c3875680 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorder.imageset/bookmarkBorder.svg @@ -0,0 +1,4 @@ + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorderList.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorderList.imageset/Contents.json new file mode 100644 index 00000000..e279269b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorderList.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmarkGrayBorderList.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorderList.imageset/bookmarkGrayBorderList.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorderList.imageset/bookmarkGrayBorderList.svg new file mode 100644 index 00000000..d5ace6ae --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkGrayBorderList.imageset/bookmarkGrayBorderList.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkList.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkList.imageset/Contents.json new file mode 100644 index 00000000..78cce243 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkList.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmarkList.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkList.imageset/bookmarkList.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkList.imageset/bookmarkList.svg new file mode 100644 index 00000000..dc45cef0 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/bookmarkList.imageset/bookmarkList.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircle.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircle.imageset/Contents.json new file mode 100644 index 00000000..ce4dc702 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircle.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "checkCircle.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircle.imageset/checkCircle.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircle.imageset/checkCircle.svg new file mode 100644 index 00000000..fd0968fd --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircle.imageset/checkCircle.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircleFill.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircleFill.imageset/Contents.json new file mode 100644 index 00000000..e2e75972 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircleFill.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "checkCircleFill.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircleFill.imageset/checkCircleFill.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircleFill.imageset/checkCircleFill.svg new file mode 100644 index 00000000..cc39a399 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkCircleFill.imageset/checkCircleFill.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMark.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMark.imageset/Contents.json new file mode 100644 index 00000000..7f105edc --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMark.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "checkMark.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMark.imageset/checkMark.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMark.imageset/checkMark.svg new file mode 100644 index 00000000..d6f5372f --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMark.imageset/checkMark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMarkFill.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMarkFill.imageset/Contents.json new file mode 100644 index 00000000..9976bef5 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMarkFill.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "checkMarkFill.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMarkFill.imageset/checkMarkFill.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMarkFill.imageset/checkMarkFill.svg new file mode 100644 index 00000000..b8409aae --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkMarkFill.imageset/checkMarkFill.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquare.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquare.imageset/Contents.json new file mode 100644 index 00000000..c9e9b7f5 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquare.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "checkSquare.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquare.imageset/checkSquare.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquare.imageset/checkSquare.svg new file mode 100644 index 00000000..4707e286 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquare.imageset/checkSquare.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquareFill.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquareFill.imageset/Contents.json new file mode 100644 index 00000000..f5c7ed27 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquareFill.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "checkSquareFill.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquareFill.imageset/checkSquareFill.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquareFill.imageset/checkSquareFill.svg new file mode 100644 index 00000000..7e06b1ad --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/checkSquareFill.imageset/checkSquareFill.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/circle.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/circle.imageset/Contents.json new file mode 100644 index 00000000..acd6921d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/circle.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon_circle.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/circle.imageset/icon_circle.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/circle.imageset/icon_circle.svg new file mode 100644 index 00000000..54655880 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/circle.imageset/icon_circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/dictionary.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/dictionary.imageset/Contents.json new file mode 100644 index 00000000..2475455d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/dictionary.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "dictionary.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/dictionary.imageset/dictionary.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/dictionary.imageset/dictionary.svg new file mode 100644 index 00000000..f09313b4 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/dictionary.imageset/dictionary.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/edit.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/edit.imageset/Contents.json new file mode 100644 index 00000000..13f9713f --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/edit.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "edit.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/edit.imageset/edit.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/edit.imageset/edit.svg new file mode 100644 index 00000000..35c2ed7d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/edit.imageset/edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/error.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/error.imageset/Contents.json new file mode 100644 index 00000000..8d95c25b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/error.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "error.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/error.imageset/error.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/error.imageset/error.svg new file mode 100644 index 00000000..049788c6 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/error.imageset/error.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorBlack.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorBlack.imageset/Contents.json new file mode 100644 index 00000000..8d95c25b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorBlack.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "error.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorBlack.imageset/error.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorBlack.imageset/error.svg new file mode 100644 index 00000000..e74491e2 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorBlack.imageset/error.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorImage.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorImage.imageset/Contents.json new file mode 100644 index 00000000..5179fc52 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "errorImage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorImage.imageset/errorImage.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorImage.imageset/errorImage.png new file mode 100644 index 00000000..e5204398 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/errorImage.imageset/errorImage.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/favorite.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/favorite.imageset/Contents.json new file mode 100644 index 00000000..33e62908 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/favorite.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "favorite_true.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/favorite.imageset/favorite_true.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/favorite.imageset/favorite_true.svg new file mode 100644 index 00000000..d47569a5 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/favorite.imageset/favorite_true.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/filter.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/filter.imageset/Contents.json new file mode 100644 index 00000000..01d6c7dd --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/filter.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "filter.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/filter.imageset/filter.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/filter.imageset/filter.svg new file mode 100644 index 00000000..131b98da --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/filter.imageset/filter.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnail.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnail.imageset/Contents.json new file mode 100644 index 00000000..f0818241 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnail.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "blueSnail.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnail.imageset/blueSnail.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnail.imageset/blueSnail.png new file mode 100644 index 00000000..50788978 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnail.imageset/blueSnail.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnailSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnailSelected.imageset/Contents.json new file mode 100644 index 00000000..b936cfb1 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnailSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "blueSnailSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnailSelected.imageset/blueSnailSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnailSelected.imageset/blueSnailSelected.png new file mode 100644 index 00000000..ccac9342 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/blueSnailSelected.imageset/blueSnailSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYeti.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYeti.imageset/Contents.json new file mode 100644 index 00000000..d25c043c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYeti.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "juniorYeti.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYeti.imageset/juniorYeti.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYeti.imageset/juniorYeti.png new file mode 100644 index 00000000..7d692953 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYeti.imageset/juniorYeti.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYetiSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYetiSelected.imageset/Contents.json new file mode 100644 index 00000000..52ceecf0 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYetiSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "juniorYetiSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYetiSelected.imageset/juniorYetiSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYetiSelected.imageset/juniorYetiSelected.png new file mode 100644 index 00000000..c81772ef Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/juniorYetiSelected.imageset/juniorYetiSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroom.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroom.imageset/Contents.json new file mode 100644 index 00000000..3a330589 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroom.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "mushroom.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroom.imageset/mushroom.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroom.imageset/mushroom.png new file mode 100644 index 00000000..0773ae4f Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroom.imageset/mushroom.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomSelected.imageset/Contents.json new file mode 100644 index 00000000..be7cc9af --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "mushroomSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomSelected.imageset/mushroomSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomSelected.imageset/mushroomSelected.png new file mode 100644 index 00000000..a502b616 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomSelected.imageset/mushroomSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomTest.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomTest.imageset/Contents.json new file mode 100644 index 00000000..a6efc45b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomTest.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "mushroomTest.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomTest.imageset/mushroomTest.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomTest.imageset/mushroomTest.png new file mode 100644 index 00000000..9a90b6c9 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/mushroomTest.imageset/mushroomTest.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepe.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepe.imageset/Contents.json new file mode 100644 index 00000000..b50a2622 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepe.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "pepe.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepe.imageset/pepe.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepe.imageset/pepe.png new file mode 100644 index 00000000..69653047 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepe.imageset/pepe.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepeSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepeSelected.imageset/Contents.json new file mode 100644 index 00000000..d2fd897d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepeSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "pepeSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepeSelected.imageset/pepeSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepeSelected.imageset/pepeSelected.png new file mode 100644 index 00000000..3657aa09 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/pepeSelected.imageset/pepeSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rash.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rash.imageset/Contents.json new file mode 100644 index 00000000..9c8da93a --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "rash.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rash.imageset/rash.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rash.imageset/rash.png new file mode 100644 index 00000000..5f095627 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rash.imageset/rash.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rashSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rashSelected.imageset/Contents.json new file mode 100644 index 00000000..11fa673c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rashSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "rashSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rashSelected.imageset/rashSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rashSelected.imageset/rashSelected.png new file mode 100644 index 00000000..f63ae757 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/rashSelected.imageset/rashSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slime.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slime.imageset/Contents.json new file mode 100644 index 00000000..4ced3bf3 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slime.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "slime.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slime.imageset/slime.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slime.imageset/slime.png new file mode 100644 index 00000000..4278e35a Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slime.imageset/slime.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slimeSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slimeSelected.imageset/Contents.json new file mode 100644 index 00000000..5722705d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slimeSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "slimeSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slimeSelected.imageset/slimeSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slimeSelected.imageset/slimeSelected.png new file mode 100644 index 00000000..fdb91b6f Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/slimeSelected.imageset/slimeSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixie.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixie.imageset/Contents.json new file mode 100644 index 00000000..70545b1b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixie.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "starpixie.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixie.imageset/starpixie.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixie.imageset/starpixie.png new file mode 100644 index 00000000..6cd9d7de Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixie.imageset/starpixie.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixieSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixieSelected.imageset/Contents.json new file mode 100644 index 00000000..e68397ab --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixieSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "starPixieSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixieSelected.imageset/starPixieSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixieSelected.imageset/starPixieSelected.png new file mode 100644 index 00000000..09fd755c Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/starPixieSelected.imageset/starPixieSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraith.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraith.imageset/Contents.json new file mode 100644 index 00000000..18c2f1df --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraith.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "wraith.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraith.imageset/wraith.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraith.imageset/wraith.png new file mode 100644 index 00000000..b6c4015e Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraith.imageset/wraith.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraithSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraithSelected.imageset/Contents.json new file mode 100644 index 00000000..170ee7e2 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraithSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "wraithSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraithSelected.imageset/wraithSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraithSelected.imageset/wraithSelected.png new file mode 100644 index 00000000..335885e3 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/wraithSelected.imageset/wraithSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yeti.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yeti.imageset/Contents.json new file mode 100644 index 00000000..01fd28ee --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yeti.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "yeti.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yeti.imageset/yeti.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yeti.imageset/yeti.png new file mode 100644 index 00000000..190ceb41 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yeti.imageset/yeti.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yetiSelected.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yetiSelected.imageset/Contents.json new file mode 100644 index 00000000..439a9018 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yetiSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "yetiSelected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yetiSelected.imageset/yetiSelected.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yetiSelected.imageset/yetiSelected.png new file mode 100644 index 00000000..4db0974f Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/illustration/yetiSelected.imageset/yetiSelected.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Login_KV_img.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Login_KV_img.imageset/Contents.json new file mode 100644 index 00000000..0ec129e8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Login_KV_img.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Login_KV_img.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Login_KV_img.imageset/Login_KV_img.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Login_KV_img.imageset/Login_KV_img.png new file mode 100644 index 00000000..1e6d15d3 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/Login_KV_img.imageset/Login_KV_img.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/addToCollection.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/addToCollection.imageset/Contents.json new file mode 100644 index 00000000..ed70f822 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/addToCollection.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "addToCollection.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/addToCollection.imageset/addToCollection.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/addToCollection.imageset/addToCollection.png new file mode 100644 index 00000000..4c38fbf8 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/addToCollection.imageset/addToCollection.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/appleImage.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/appleImage.imageset/Contents.json new file mode 100644 index 00000000..b3712ae4 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/appleImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "appleImage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/appleImage.imageset/appleImage.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/appleImage.imageset/appleImage.png new file mode 100644 index 00000000..e6038fb5 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/appleImage.imageset/appleImage.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/connectionError.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/connectionError.imageset/Contents.json new file mode 100644 index 00000000..fac1a53c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/connectionError.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "connectionError.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/connectionError.imageset/connectionError.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/connectionError.imageset/connectionError.png new file mode 100644 index 00000000..75604d9b Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/connectionError.imageset/connectionError.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/fabHint.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/fabHint.imageset/Contents.json new file mode 100644 index 00000000..e1484a1b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/fabHint.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "fabHint.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/fabHint.imageset/fabHint.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/fabHint.imageset/fabHint.png new file mode 100644 index 00000000..82a2ea35 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/fabHint.imageset/fabHint.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/getNotify.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/getNotify.imageset/Contents.json new file mode 100644 index 00000000..d14b19a0 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/getNotify.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "getNotify.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/getNotify.imageset/getNotify.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/getNotify.imageset/getNotify.png new file mode 100644 index 00000000..9fee5ecf Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/getNotify.imageset/getNotify.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/kakaoImage.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/kakaoImage.imageset/Contents.json new file mode 100644 index 00000000..8298ca5d --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/kakaoImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "kakaoImage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/kakaoImage.imageset/kakaoImage.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/kakaoImage.imageset/kakaoImage.png new file mode 100644 index 00000000..ef883fa6 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/kakaoImage.imageset/kakaoImage.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noResult.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noResult.imageset/Contents.json new file mode 100644 index 00000000..e0b54f5a --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noResult.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "noResult.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noResult.imageset/noResult.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noResult.imageset/noResult.png new file mode 100644 index 00000000..574e37d7 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noResult.imageset/noResult.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noShowList.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noShowList.imageset/Contents.json new file mode 100644 index 00000000..402e6280 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noShowList.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "noShowList.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noShowList.imageset/noShowList.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noShowList.imageset/noShowList.png new file mode 100644 index 00000000..e90300c0 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/noShowList.imageset/noShowList.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/onBoardingBookmark.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/onBoardingBookmark.imageset/Contents.json new file mode 100644 index 00000000..ed18840a --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/onBoardingBookmark.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bookmarkList.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/onBoardingBookmark.imageset/bookmarkList.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/onBoardingBookmark.imageset/bookmarkList.png new file mode 100644 index 00000000..988fc8e7 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/onBoardingBookmark.imageset/bookmarkList.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/questionNotify.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/questionNotify.imageset/Contents.json new file mode 100644 index 00000000..a71a5df4 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/questionNotify.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "questionNotify.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/questionNotify.imageset/questionNotify.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/questionNotify.imageset/questionNotify.png new file mode 100644 index 00000000..d7c51a5d Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/questionNotify.imageset/questionNotify.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/recentLoginLogo.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/recentLoginLogo.imageset/Contents.json new file mode 100644 index 00000000..c1fb5668 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/recentLoginLogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "recentLoginLogo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/recentLoginLogo.imageset/recentLoginLogo.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/recentLoginLogo.imageset/recentLoginLogo.png new file mode 100644 index 00000000..4afde34f Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/recentLoginLogo.imageset/recentLoginLogo.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/settingsHint.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/settingsHint.imageset/Contents.json new file mode 100644 index 00000000..4c241a10 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/settingsHint.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "settingsHint.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/settingsHint.imageset/settingsHint.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/settingsHint.imageset/settingsHint.png new file mode 100644 index 00000000..76be1394 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/image/settingsHint.imageset/settingsHint.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/kakaoLogo.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/kakaoLogo.imageset/Contents.json new file mode 100644 index 00000000..332f97e7 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/kakaoLogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "kakaoLogo.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/kakaoLogo.imageset/kakaoLogo.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/kakaoLogo.imageset/kakaoLogo.svg new file mode 100644 index 00000000..43ac1413 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/kakaoLogo.imageset/kakaoLogo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/largeX.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/largeX.imageset/Contents.json new file mode 100644 index 00000000..f93a7f69 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/largeX.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "x-black_big.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/largeX.imageset/x-black_big.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/largeX.imageset/x-black_big.svg new file mode 100644 index 00000000..d793ff8a --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/largeX.imageset/x-black_big.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/lineArrowDown.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/lineArrowDown.imageset/Contents.json new file mode 100644 index 00000000..1012cc97 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/lineArrowDown.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "lineArrowDown.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/lineArrowDown.imageset/lineArrowDown.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/lineArrowDown.imageset/lineArrowDown.svg new file mode 100644 index 00000000..67225443 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/lineArrowDown.imageset/lineArrowDown.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/logo.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/logo.imageset/Contents.json new file mode 100644 index 00000000..5f670ca8 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "logo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/logo.imageset/logo.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/logo.imageset/logo.png new file mode 100644 index 00000000..0c524885 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/logo.imageset/logo.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/mypage.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/mypage.imageset/Contents.json new file mode 100644 index 00000000..171be441 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/mypage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "mypage_true.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/mypage.imageset/mypage_true.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/mypage.imageset/mypage_true.svg new file mode 100644 index 00000000..89cd6bd5 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/mypage.imageset/mypage_true.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/plusIcon.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/plusIcon.imageset/Contents.json new file mode 100644 index 00000000..ccdb0f7e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/plusIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "plusicon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/plusIcon.imageset/plusicon.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/plusIcon.imageset/plusicon.svg new file mode 100644 index 00000000..c1ecbac2 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/plusIcon.imageset/plusicon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/rightArrow.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/rightArrow.imageset/Contents.json new file mode 100644 index 00000000..bfef48d9 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/rightArrow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "rightArrow.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/rightArrow.imageset/rightArrow.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/rightArrow.imageset/rightArrow.svg new file mode 100644 index 00000000..d722791e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/rightArrow.imageset/rightArrow.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/search.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/search.imageset/Contents.json new file mode 100644 index 00000000..e4d0b2c4 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/search.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "seach.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/search.imageset/seach.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/search.imageset/seach.svg new file mode 100644 index 00000000..e1f774eb --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/search.imageset/seach.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/smallX.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/smallX.imageset/Contents.json new file mode 100644 index 00000000..e29acd20 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/smallX.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "x-black.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/smallX.imageset/x-black.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/smallX.imageset/x-black.svg new file mode 100644 index 00000000..e530a67c --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/smallX.imageset/x-black.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage.imageset/Contents.json new file mode 100644 index 00000000..6a9ec0f9 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "testImage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage.imageset/testImage.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage.imageset/testImage.png new file mode 100644 index 00000000..95973c2a Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage.imageset/testImage.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage2.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage2.imageset/Contents.json new file mode 100644 index 00000000..d114ab7e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "image.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage2.imageset/image.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage2.imageset/image.png new file mode 100644 index 00000000..0fc3ba70 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/testImage2.imageset/image.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/textFieldClear.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/textFieldClear.imageset/Contents.json new file mode 100644 index 00000000..7080485b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/textFieldClear.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "textFieldClear.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/textFieldClear.imageset/textFieldClear.png b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/textFieldClear.imageset/textFieldClear.png new file mode 100644 index 00000000..5be83d97 Binary files /dev/null and b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/textFieldClear.imageset/textFieldClear.png differ diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/warning.imageset/Contents.json b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/warning.imageset/Contents.json new file mode 100644 index 00000000..d07182d3 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/warning.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "warning.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/warning.imageset/warning.svg b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/warning.imageset/warning.svg new file mode 100644 index 00000000..e6980bf6 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Resources/Image.xcassets/warning.imageset/warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIButton+.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIButton+.swift new file mode 100644 index 00000000..5c6822be --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIButton+.swift @@ -0,0 +1,21 @@ +import UIKit + +extension UIButton { + func setUnderlinedTitle(title: String, font: UIFont?, state: UIControl.State = .normal, textInsets: UIEdgeInsets = .zero) { + guard let font = font else { return } + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.minimumLineHeight = 0 + paragraphStyle.lineBreakMode = .byTruncatingTail + paragraphStyle.maximumLineHeight = font.lineHeight * 1.17 + + let attributes: [NSAttributedString.Key: Any] = [ + .underlineStyle: NSUnderlineStyle.single.rawValue, + .font: font, + .paragraphStyle: paragraphStyle + ] + + let attributedString = NSAttributedString(string: title, attributes: attributes) + setAttributedTitle(attributedString, for: state) + titleEdgeInsets = textInsets + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIColor+.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIColor+.swift new file mode 100644 index 00000000..b3c62f6e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIColor+.swift @@ -0,0 +1,58 @@ +import UIKit + +public extension UIColor { + static let primary900 = UIColor(hexCode: "EE500C") + static let primary700 = UIColor(hexCode: "FF5C00") + static let primary500 = UIColor(hexCode: "FF7D33") + static let primary300 = UIColor(hexCode: "FF9D66") + static let primary100 = UIColor(hexCode: "FFBE9A") + static let primary50 = UIColor(hexCode: "FFE6D8") + static let primary25 = UIColor(hexCode: "FFF1E9") + + static let secondary = UIColor(hexCode: "FFAA00") + static let textColor = UIColor(hexCode: "1D1D1F") + + static let neutral900 = UIColor(hexCode: "313131") + static let neutral700 = UIColor(hexCode: "575757") + static let neutral600 = UIColor(hexCode: "848484") + static let neutral500 = UIColor(hexCode: "AFAFAF") + static let neutral300 = UIColor(hexCode: "CFCFCF") + static let neutral200 = UIColor(hexCode: "E9E9E9") + static let neutral100 = UIColor(hexCode: "F5F5F5") + + static let whiteMLS = UIColor(hexCode: "FFFFFF") + static let clearMLS = UIColor(hexCode: "FFFFFF", alpha: 0) + + static let error900 = UIColor(hexCode: "FF4B4B") + static let error100 = UIColor(hexCode: "FFEFEF") + + static let success = UIColor(hexCode: "15CC00") + static let redMLS = UIColor(hexCode: "FF0000") + static let overlays = UIColor(hexCode: "000000", alpha: 0.2) + + static let listMonster = UIColor(hexCode: "FFEFCE") + static let listItem = UIColor(hexCode: "F1EEFC") + static let listMap = UIColor(hexCode: "EEF9E0") + static let listNPC = UIColor(hexCode: "E0EFF9") + static let listQuest = UIColor(hexCode: "FFECEF") + + convenience init(hexCode: String, alpha: CGFloat = 1.0) { + var hexFormatted: String = hexCode.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).uppercased() + + if hexFormatted.hasPrefix("#") { + hexFormatted = String(hexFormatted.dropFirst()) + } + + assert(hexFormatted.count == 6, "Invalid hex code used.") + + var rgbValue: UInt64 = 0 + Scanner(string: hexFormatted).scanHexInt64(&rgbValue) + + self.init( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: alpha + ) + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIFont+.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIFont+.swift new file mode 100644 index 00000000..3873351e --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIFont+.swift @@ -0,0 +1,48 @@ +// swiftlint:disable all + +import UIKit + +public extension UIFont { + static let h_xxxl_b = korFont(style: .bold, size: 24) + static let h_xxxl_sb = korFont(style: .semiBold, size: 24) + + static let h_xxl_b = korFont(style: .bold, size: 22) + + static let h_xl_b = korFont(style: .bold, size: 20) + static let h_xl_sb = korFont(style: .semiBold, size: 20) + static let h_xl_r = korFont(style: .regular, size: 20) + + static let b_l_r = korFont(style: .regular, size: 18) + static let b_m_r = korFont(style: .regular, size: 16) + static let b_s_sb = korFont(style: .semiBold, size: 14) + static let b_s_m = korFont(style: .medium, size: 14) + static let b_s_r = korFont(style: .regular, size: 14) + + static let sub_l_b = korFont(style: .bold, size: 18) + static let sub_l_m = korFont(style: .medium, size: 18) + static let sub_m_b = korFont(style: .bold, size: 16) + static let sub_m_sb = korFont(style: .semiBold, size: 16) + static let sub_m_m = korFont(style: .medium, size: 16) + + static let cp_s_sb = korFont(style: .semiBold, size: 14) + static let cp_s_m = korFont(style: .medium, size: 14) + static let cp_s_r = korFont(style: .regular, size: 14) + static let cp_xs_sb = korFont(style: .semiBold, size: 12) + static let cp_xs_r = korFont(style: .regular, size: 12) + + static let btn_m_b = korFont(style: .bold, size: 16) + static let btn_m_r = korFont(style: .regular, size: 16) + static let btn_s_r = korFont(style: .regular, size: 14) + static let btn_xs_r = korFont(style: .regular, size: 12) + + static func korFont(style: FontStyle, size: CGFloat) -> UIFont? { + return UIFont(name: "Pretendard\(style.rawValue)", size: size) + } + + enum FontStyle: String { + case bold = "-Bold" + case semiBold = "-SemiBold" + case medium = "-Medium" + case regular = "-Regular" + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIImage+.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIImage+.swift new file mode 100644 index 00000000..90112d88 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIImage+.swift @@ -0,0 +1,29 @@ +import UIKit + +extension UIImage { + static func fromColor(_ color: UIColor?) -> UIImage { + guard let color else { return UIImage() } + let rect = CGRect(x: 0, y: 0, width: 1, height: 1) + UIGraphicsBeginImageContext(rect.size) + color.setFill() + UIRectFill(rect) + let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage() + UIGraphicsEndImageContext() + return image + } + + func resizeImage(to targetSize: CGSize, preserveAspectRatio: Bool = true) -> UIImage? { + let size: CGSize + if preserveAspectRatio { + let aspectRatio = min(targetSize.width / self.size.width, targetSize.height / self.size.height) + size = CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio) + } else { + size = targetSize + } + + let renderer = UIGraphicsImageRenderer(size: size) + return renderer.image { _ in + self.draw(in: CGRect(origin: .zero, size: size)) + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIViewController+.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIViewController+.swift new file mode 100644 index 00000000..2e41286b --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignExtensions/UIViewController+.swift @@ -0,0 +1,133 @@ +import UIKit + +import SnapKit + +@MainActor private var modalWrapperKey: UInt8 = 0 +@MainActor private var modalHideTabBarKey: UInt8 = 0 + +public extension UIViewController { + + private var modalWrapperView: ModalWrapperView? { + get { objc_getAssociatedObject(self, &modalWrapperKey) as? ModalWrapperView } + set { objc_setAssociatedObject(self, &modalWrapperKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } + } + + private var modalHideTabBar: Bool { + get { (objc_getAssociatedObject(self, &modalHideTabBarKey) as? Bool) ?? false } + set { objc_setAssociatedObject(self, &modalHideTabBarKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } + } + + /// 커스텀 모달 프레젠트 + /// - Parameters: + /// - viewController: 표시할 모달 뷰컨 + /// - hideTabBar: 탭바를 숨길지 여부 (기본값: true) + func presentModal( + _ viewController: UIViewController & ModalPresentable, + hideTabBar: Bool = false + ) { + let wrapper = ModalWrapperView(contentViewController: viewController, parent: self) + + // 이전 상태 초기화 + modalHideTabBar = false + modalWrapperView = wrapper + + // 새 설정 적용 + modalHideTabBar = hideTabBar + + view.addSubview(wrapper) + wrapper.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + // 필요 시 탭바 숨김 + if hideTabBar, let tabBarController = findTabBarController() { + tabBarController.setHidden(hidden: true, animated: false) + } + + // present 애니메이션 + UIView.animate( + withDuration: 0.5, + delay: 0, + usingSpringWithDamping: 0.85, + initialSpringVelocity: 0.8, + options: [.curveEaseOut] + ) { + wrapper.dimView.alpha = 1 + wrapper.containerView.transform = .identity + DispatchQueue.main.async { + viewController.beginAppearanceTransition(true, animated: true) + viewController.endAppearanceTransition() + } + } + } + + /// 현재 모달 닫기 + @objc internal func dismissCurrentModal() { + guard let wrapper = modalWrapperView else { return } + + let shouldKeepHidden = modalHideTabBar + let tabBarController = findTabBarController() + + if shouldKeepHidden, let tabBarController { + tabBarController.setHidden(hidden: true, animated: false) + } + + UIView.animate(withDuration: 0.35, delay: 0, options: [.curveEaseInOut]) { + wrapper.dimView.alpha = 0 + wrapper.containerView.transform = CGAffineTransform(translationX: 0, y: 300) + } completion: { _ in + wrapper.removeFromSuperview() + self.modalWrapperView = nil + + // false인 경우 복원 + if !shouldKeepHidden, let tabBarController { + tabBarController.setHidden(hidden: false, animated: false) + } + + self.modalHideTabBar = false + } + } + + private func findTabBarController() -> BottomTabBarController? { + var parentVC: UIViewController? = self + while let current = parentVC { + if let tabBarController = current as? BottomTabBarController { + return tabBarController + } + parentVC = current.parent + } + return nil + } +} + +// 모달 내부에서 닫기 기능 제공 +@MainActor +extension ModalPresentable where Self: UIViewController { + public func dismissCurrentModal() { + parent?.dismissCurrentModal() + } +} + +@MainActor +private var fabKey: UInt8 = 0 + +public extension UIViewController { + func addFloatingButton(_ action: @escaping () -> Void) { + let fab = FloatingActionButton(action: action) + objc_setAssociatedObject(self, &fabKey, fab, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + + view.addSubview(fab) + fab.snp.makeConstraints { make in + make.trailing.equalTo(view.safeAreaLayoutGuide).inset(16) + make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16) + make.size.equalTo(CGSize(width: 48, height: 48)) + } + } + + func removeFloatingButton() { + if let fab = objc_getAssociatedObject(self, &fabKey) as? UIView { + fab.removeFromSuperview() + objc_setAssociatedObject(self, &fabKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignSystemAsset.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignSystemAsset.swift new file mode 100644 index 00000000..9ac04ad1 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/DesignSystemAsset.swift @@ -0,0 +1,47 @@ +import UIKit + +public enum DesignSystemAsset { + static let bundle: Bundle = .module + + public static func image(named name: String) -> UIImage { + guard let image = UIImage(named: name, in: .module, compatibleWith: nil) else { + fatalError("❌ Image not found: \(name)") + } + return image + } +} + +public enum MapleIllustration { + case mushroom + case slime + case blueSnail + case juniorYeti + case yeti + case pepe + case wraith + case starPixie + case rash + + public var url: String { + switch self { + case .mushroom: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_1.jpg" + case .slime: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_2.jpg" + case .blueSnail: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_3.jpg" + case .juniorYeti: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_4.jpg" + case .yeti: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_5.jpg" + case .pepe: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_6.jpg" + case .wraith: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_7.jpg" + case .starPixie: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_8.jpg" + case .rash: + "https://maple-db-team-s3.s3.ap-northeast-2.amazonaws.com/profile-images/profile_9.jpg" + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/FontManager.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/FontManager.swift new file mode 100644 index 00000000..ed79dfd9 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/FontManager.swift @@ -0,0 +1,30 @@ +import os +import UIKit + +public class FontManager { + /// 폰트를 등록하는 메서드 + public static func registerFonts() { + let fontNames = [ + "Pretendard-Bold", + "Pretendard-SemiBold", + "Pretendard-Medium", + "Pretendard-Regular" + ] + + fontNames.forEach { fontName in + guard let fontURL = Bundle.module.url(forResource: fontName, withExtension: "ttf") else { + os_log(.error, "Font file not found: \(fontName)") + return + } + + var error: Unmanaged? + CTFontManagerRegisterFontsForURL(fontURL as CFURL, .process, &error) + + if let error = error { + os_log(.error, "Error registering font: \(error.takeUnretainedValue())") + } else { + os_log(.error, "\(fontName) registered successfully") + } + } + } +} diff --git a/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/NSAttributedString.swift b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/NSAttributedString.swift new file mode 100644 index 00000000..663be1f3 --- /dev/null +++ b/MLS/MLSDesignSystem/Sources/MLSDesignSystem/Utills/NSAttributedString.swift @@ -0,0 +1,61 @@ +import UIKit + +// core의 extension에 위치하는게 올바를지? +public extension NSAttributedString { + static func makeStyledString( + font: UIFont?, + text: String?, + color: UIColor? = .textColor, + alignment: NSTextAlignment = .center, + lineHeight: CGFloat = 1.17 + ) -> NSAttributedString? { + guard let text, let color, let font else { return nil } + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.minimumLineHeight = 0 + paragraphStyle.lineBreakMode = .byTruncatingTail + paragraphStyle.lineHeightMultiple = lineHeight + paragraphStyle.alignment = alignment + + let actualLineHeight = font.lineHeight * lineHeight + let baselineOffset = (actualLineHeight - font.lineHeight) / 2 + + let attributedString = NSAttributedString( + string: text, + attributes: [ + .font: font, + .foregroundColor: color, + .paragraphStyle: paragraphStyle, + .baselineOffset: baselineOffset + ] + ) + return attributedString + } + + static func makeStyledUnderlinedString( + font: UIFont?, + text: String?, + color: UIColor? = .textColor, + alignment: NSTextAlignment = .center, + lineHeight: CGFloat = 1.17, + underlineStyle: NSUnderlineStyle = .single + ) -> NSAttributedString? { + guard let text, let color, let font else { return nil } + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.minimumLineHeight = 0 + paragraphStyle.lineBreakMode = .byTruncatingTail + paragraphStyle.maximumLineHeight = font.lineHeight * lineHeight + paragraphStyle.alignment = alignment + + let attributedString = NSAttributedString( + string: text, + attributes: [ + .font: font, + .foregroundColor: color, + .paragraphStyle: paragraphStyle, + .underlineStyle: underlineStyle.rawValue + ] + ) + + return attributedString + } +} diff --git a/MLS/MLSDesignSystemExample/ComponentsTest/CardListTestViewController.swift b/MLS/MLSDesignSystemExample/ComponentsTest/CardListTestViewController.swift index 5fc9c948..f6b156b5 100644 --- a/MLS/MLSDesignSystemExample/ComponentsTest/CardListTestViewController.swift +++ b/MLS/MLSDesignSystemExample/ComponentsTest/CardListTestViewController.swift @@ -111,6 +111,7 @@ private extension CardListTestViewController { func configureUI() { view.backgroundColor = .systemBackground + self.cardList.setType(type: CardList.CardListType.recommended(rank: 1)) self.cardList.setImage(image: DesignSystemAsset.image(named: "testImage"), backgroundColor: .listMap) }