Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
274 changes: 121 additions & 153 deletions Sources/Blueprint/Sources/Scene/Previews/TextAreaPreview.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,68 +11,89 @@ import SwiftUI
import Montage

struct TextAreaPreview: View {
enum Size: String, CaseIterable {
case large
case medium

var description: String {
self.rawValue.capitalized
}

var s: TextArea.Size {
switch self {
case .large: .large
case .medium: .medium
}
}
}

enum Resize: String, CaseIterable {
case normal
case limit
case fixed

var description: String {
self.rawValue.capitalized
}

var r: TextArea.Resize {
switch self {
case .normal: .normal
case .limit: .limit
case .fixed: .fixed(min: 100, max: 200)
case .fixed: .fixed(min: 116, max: 200)
}
}
}

var resources: [TextArea.Resource?] {
[
.characterCount(limit: Int(limit), overflow: overflow),
.textButton(
.button(
title: "Text",
handler: {}
),
.iconButton(
icon: .send,
handler: {}
),
.primaryIconButton(
icon: .send,
handler: {}
),
.icon(
.chevronDown
),
.chip(
title: "Action",
handler: {}
.contentBadge(
title: "Badge"
),
.filterButton(
title: "Filter",
handler: {}
)
.segmentedControl(
selectedIndex: $segmentIndex,
icons: [.send, .chevronDown]
),
.slot {
Image(systemName: "star.fill")
.foregroundColor(.semantic(.primaryNormal))
}
]
}

@State private var showTransparentChecker: Bool = false
@State private var text: String = ""
@State private var size: Size = .large
@State private var resize: Resize = .normal
@State private var negative: Bool = false
@State private var focus: Bool = false
@FocusState private var focusState: Bool
@State private var disable: Bool = false
@State private var heading: Bool = false
@State private var requiredBadge: Bool = false
@State private var description: Bool = false
@State private var placeholder: Bool = true
@State private var leadingResources = [TextArea.Resource]()
@State private var trailingResources = [TextArea.Resource]()
@State private var limit: CGFloat = 10
@State private var overflow: Bool = false

@State private var maxLength: CGFloat = 0
@State private var characterCount: Int = 0
@State private var segmentIndex: Int = 0

var body: some View {
SwiftUI.ScrollView {
VStack(spacing: 12) {
VStack(alignment: .leading) {
HStack {
Text("Preview").bold()
Spacer()
Expand All @@ -83,140 +104,97 @@ struct TextAreaPreview: View {
.foregroundColor(.semantic(.primaryNormal))
}
}
TextArea(text: $text, focus: $focusState)
.resize(resize.r)
.negative(negative)
.disable(disable)
.heading(heading ? "제목" : nil)
.requiredBadge(requiredBadge)
.bottomResources(
leading: leadingResources,
trailing: trailingResources
Group {
TextArea(text: $text, focus: $focusState)
.size(size.s)
.resize(resize.r)
.negative(negative)
.disable(disable)
.bottomResources(
leading: leadingResources,
trailing: trailingResources
)
.maxLength(maxLength > 0 ? Int(maxLength) : nil)
.onTextChange { characterCount = $0.count }
.placeholder(placeholder ? "텍스트를 입력해주세요" : nil)
}
Text("Options").bold()
HStack {
Text("size")
SegmentedControl(
selectedIndex: Binding(
get: { Size.allCases.firstIndex(of: size) ?? 0 },
set: { size = Size.allCases[$0] }
),
labels: Size.allCases.map(\.description)
)
.size(.small)
}
HStack {
Text("resize")
SegmentedControl(
selectedIndex: Binding(
get: { Resize.allCases.firstIndex(of: resize) ?? 0 },
set: { resize = Resize.allCases[$0] }
),
labels: Resize.allCases.map(\.description)
)
.description(description ? "메세지에 마침표를 찍어요." : nil)
.placeholder(placeholder ? "텍스트를 입력해주세요" : nil)

VStack(alignment: .leading, spacing: 12) {
Text("Options").bold()
HStack {
HStack {
Text("Resize :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Menu(resize.description) {
ForEach(Resize.allCases, id: \.self) { r in
Button {
resize = r
} label: {
Text(r.description)
.size(.small)
}
HStack {
Text("placeholder")
Switch(checked: placeholder) { placeholder = $0 }
Text("focus")
Switch(checked: focus) { focusState = $0 }
}
HStack {
Text("disable")
Switch(checked: disable) { disable = $0 }
Text("negative")
Switch(checked: negative) { negative = $0 }
}
HStack {
Text("leading")
Menu("add") {
ForEach(resources.indices, id: \.self) { index in
if resources[index]?.isLeadingAllowed ?? false {
Button {
if let resource = resources[index] {
leadingResources.append(resource)
leadingResources = leadingResources.suffix(3)
}
} label: {
Text(resources[index]?.description ?? "none")
}
}
}
HStack {
Text("Placeholder :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: placeholder) { placeholder = $0 }
}
}
HStack {
HStack {
Text("Focus :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: focus) {
focusState = $0
}
}
HStack {
Text("Disable :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: disable) { disable = $0 }
}
}
HStack {
HStack {
Text("Heading :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: heading) { heading = $0 }
}
HStack {
Text("RequiredBadge :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: requiredBadge) { requiredBadge = $0 }
}
}
HStack {
HStack {
Text("Description :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: description) { description = $0 }
}
Text("Negative :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Switch(checked: negative) { negative = $0 }
}
HStack {
HStack {
Text("Leading :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Menu("add") {
ForEach(resources.indices, id: \.self) { index in
Button {
if let resource = resources[index] {
leadingResources.append(resource)
}
} label: {
Text(resources[index]?.description ?? "none")
}
}
}
Button("reset") {
leadingResources.removeAll()
}
}
HStack {
Text("Trailing :")
.typography(variant: .headline2, weight: .medium)
Spacer()
Menu("add") {
ForEach(resources.indices, id: \.self) { index in
Button {
if let resource = resources[index] {
trailingResources.append(resource)
}
} label: {
Text(resources[index]?.description ?? "none")
}
Button("reset") { leadingResources.removeAll() }
Spacer()
Text("trailing")
Menu("add") {
ForEach(resources.indices, id: \.self) { index in
Button {
if let resource = resources[index] {
trailingResources.append(resource)
trailingResources = trailingResources.suffix(3)
}
} label: {
Text(resources[index]?.description ?? "none")
}
Button("reset") {
trailingResources.removeAll()
}
}
}
.font(.font(variant: .label1))
if leadingResources.contains(where: { $0.isCharacterCount }) ||
trailingResources.contains(where: { $0.isCharacterCount })
{
HStack {
Text("characterCount")
.layoutPriority(1)
Text("limit")
SwiftUI.Slider(value: $limit, in: 10...1000, step: 10)
Text("overflow")
Switch(checked: overflow) { overflow = $0 }
}
}
Button("reset") { trailingResources.removeAll() }
}
HStack {
Text("maxLength")
.layoutPriority(1)
SwiftUI.Slider(value: $maxLength, in: 0...1000, step: 10)
Text(maxLength > 0 ? "\(characterCount)/\(Int(maxLength))" : "off")
}
Spacer(minLength: 0)
}
.font(.caption)
.padding()
}
.onChange(of: focusState) {
Expand All @@ -233,16 +211,6 @@ struct TextAreaPreview: View {
}
}

extension TextArea.Resource {
var isCharacterCount: Bool {
if case .characterCount = self {
return true
} else {
return false
}
}
}

extension TextArea.Resource: CaseDescribable {}

#Preview {
Expand Down
Loading
Loading