|
| 1 | +import ComponentsKit |
| 2 | +import SwiftUI |
| 3 | +import UIKit |
| 4 | + |
| 5 | +struct AlertPreview: View { |
| 6 | + @State private var model = AlertVM { |
| 7 | + $0.title = Self.alertTitle |
| 8 | + $0.message = AlertMessage.short.rawValue |
| 9 | + $0.primaryButton = Self.initialPrimaryButton |
| 10 | + $0.secondaryButton = Self.initialSecondaryButton |
| 11 | + } |
| 12 | + |
| 13 | + var body: some View { |
| 14 | + VStack { |
| 15 | + PreviewWrapper(title: "UIKit") { |
| 16 | + UKButton(model: .init { $0.title = "Show Alert" }) { |
| 17 | + UIApplication.shared.topViewController?.present( |
| 18 | + UKAlertController(model: self.model), |
| 19 | + animated: true |
| 20 | + ) |
| 21 | + } |
| 22 | + .preview |
| 23 | + } |
| 24 | + Form { |
| 25 | + Section("Title") { |
| 26 | + Toggle("Has Title", isOn: .init( |
| 27 | + get: { return self.model.title != nil }, |
| 28 | + set: { newValue in |
| 29 | + self.model.title = newValue ? Self.alertTitle : nil |
| 30 | + } |
| 31 | + )) |
| 32 | + } |
| 33 | + |
| 34 | + Section("Message") { |
| 35 | + Picker("Alert Message", selection: self.$model.message) { |
| 36 | + Text("None").tag(Optional<String>.none) |
| 37 | + Text("Short").tag(AlertMessage.short.rawValue) |
| 38 | + Text("Long").tag(AlertMessage.long.rawValue) |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + Section("Primary Button") { |
| 43 | + Toggle("Has Primary Button", isOn: .init( |
| 44 | + get: { return self.model.primaryButton != nil }, |
| 45 | + set: { newValue in |
| 46 | + self.model.primaryButton = newValue ? Self.initialPrimaryButton : nil |
| 47 | + } |
| 48 | + )) |
| 49 | + if self.model.primaryButton != nil { |
| 50 | + Picker("Title", selection: self.primaryButtonVMOrDefault.title) { |
| 51 | + Text("Short").tag(PrimaryButtonText.short.rawValue) |
| 52 | + Text("Longer").tag(PrimaryButtonText.longer.rawValue) |
| 53 | + } |
| 54 | + self.buttonPickers(for: self.primaryButtonVMOrDefault) |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + Section("Secondary Button") { |
| 59 | + Toggle("Has Secondary Button", isOn: .init( |
| 60 | + get: { return self.model.secondaryButton != nil }, |
| 61 | + set: { newValue in |
| 62 | + self.model.secondaryButton = newValue ? Self.initialSecondaryButton : nil |
| 63 | + } |
| 64 | + )) |
| 65 | + if self.model.secondaryButton != nil { |
| 66 | + Picker("Title", selection: self.secondaryButtonVMOrDefault.title) { |
| 67 | + Text("Short").tag(SecondaryButtonText.short.rawValue) |
| 68 | + Text("Longer").tag(SecondaryButtonText.longer.rawValue) |
| 69 | + } |
| 70 | + self.buttonPickers(for: self.secondaryButtonVMOrDefault) |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + Section("Main Properties") { |
| 75 | + Picker("Background Color", selection: self.$model.backgroundColor) { |
| 76 | + Text("Default").tag(Optional<UniversalColor>.none) |
| 77 | + Text("Accent Background").tag(ComponentColor.accent.background) |
| 78 | + Text("Success Background").tag(ComponentColor.success.background) |
| 79 | + Text("Warning Background").tag(ComponentColor.warning.background) |
| 80 | + Text("Danger Background").tag(ComponentColor.danger.background) |
| 81 | + } |
| 82 | + Toggle("Closes On Overlay Tap", isOn: self.$model.closesOnOverlayTap) |
| 83 | + Picker("Content Paddings", selection: self.$model.contentPaddings) { |
| 84 | + Text("12px").tag(Paddings(padding: 12)) |
| 85 | + Text("16px").tag(Paddings(padding: 16)) |
| 86 | + Text("20px").tag(Paddings(padding: 20)) |
| 87 | + } |
| 88 | + ContainerRadiusPicker(selection: self.$model.cornerRadius) { |
| 89 | + Text("Custom 30px").tag(ContainerRadius.custom(30)) |
| 90 | + } |
| 91 | + OverlayStylePicker(selection: self.$model.overlayStyle) |
| 92 | + TransitionPicker(selection: self.$model.transition) |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + // MARK: - Reusable Pickers |
| 99 | + |
| 100 | + private func buttonPickers(for buttonVM: Binding<AlertButtonVM>) -> some View { |
| 101 | + Group { |
| 102 | + AnimationScalePicker(selection: buttonVM.animationScale) |
| 103 | + ComponentOptionalColorPicker(selection: buttonVM.color) |
| 104 | + ComponentRadiusPicker(selection: buttonVM.cornerRadius) { |
| 105 | + Text("Custom: 20px").tag(ComponentRadius.custom(20)) |
| 106 | + } |
| 107 | + Picker("Style", selection: buttonVM.style) { |
| 108 | + Text("Filled").tag(ButtonStyle.filled) |
| 109 | + Text("Plain").tag(ButtonStyle.plain) |
| 110 | + Text("Light").tag(ButtonStyle.light) |
| 111 | + Text("Bordered with small border").tag(ButtonStyle.bordered(.small)) |
| 112 | + Text("Bordered with medium border").tag(ButtonStyle.bordered(.medium)) |
| 113 | + Text("Bordered with large border").tag(ButtonStyle.bordered(.large)) |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + // MARK: - Helpers |
| 119 | + |
| 120 | + enum AlertMessage: String { |
| 121 | + case short = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." |
| 122 | + case long = """ |
| 123 | +Lorem ipsum odor amet, consectetuer adipiscing elit. Vitae vehicula pellentesque lectus orci fames. Cras suscipit dui tortor penatibus turpis ultrices. Laoreet montes adipiscing ante dapibus facilisis. Lorem per fames nec duis quis eleifend imperdiet. Tincidunt id interdum adipiscing eros dis quis platea varius. Potenti eleifend eu molestie laoreet varius sapien. Adipiscing nascetur platea penatibus curabitur tempus nibh laoreet porttitor. Augue et curabitur cras sed semper inceptos nunc montes mollis. |
| 124 | +
|
| 125 | +Lectus arcu pellentesque inceptos tempor fringilla nascetur. Erat curae convallis integer mi, quis facilisi tortor. Phasellus aliquam molestie vehicula odio in dis maximus diam elit. Rutrum gravida amet euismod feugiat fusce. Est egestas velit vulputate senectus sociosqu fringilla eget nibh. Nam pellentesque aenean mi platea tincidunt quam sem purus. Himenaeos suspendisse nec sapien habitasse ultricies maecenas libero odio. Rutrum senectus maximus ultrices, ad nam ultricies placerat. |
| 126 | +
|
| 127 | +Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros risus nibh morbi eu aenean. Velit ligula magnis aliquet at luctus. Dapibus vestibulum consectetur euismod vitae per ultrices litora quis. Aptent eleifend dapibus urna lacinia felis nisl. Sit amet fusce nullam feugiat posuere. Urna amet curae velit fermentum interdum vestibulum penatibus. Penatibus vivamus sem ultricies pellentesque congue id mattis diam. Aliquam efficitur mi gravida sollicitudin; amet imperdiet. Rutrum mollis risus justo tortor in duis cursus. |
| 128 | +""" |
| 129 | + } |
| 130 | + enum PrimaryButtonText: String { |
| 131 | + case short = "Continue" |
| 132 | + case longer = "Remind me later" |
| 133 | + } |
| 134 | + enum SecondaryButtonText: String { |
| 135 | + case short = "Cancel" |
| 136 | + case longer = "Cancel, Don't Do That" |
| 137 | + } |
| 138 | + static let alertTitle = "Alert Title" |
| 139 | + static let initialPrimaryButton = AlertButtonVM { |
| 140 | + $0.title = PrimaryButtonText.short.rawValue |
| 141 | + $0.style = .filled |
| 142 | + $0.color = .primary |
| 143 | + } |
| 144 | + static let initialSecondaryButton = AlertButtonVM { |
| 145 | + $0.title = SecondaryButtonText.short.rawValue |
| 146 | + $0.style = .light |
| 147 | + } |
| 148 | + |
| 149 | + var primaryButtonVMOrDefault: Binding<AlertButtonVM> { |
| 150 | + return .init( |
| 151 | + get: { self.model.primaryButton ?? Self.initialPrimaryButton }, |
| 152 | + set: { self.model.primaryButton = $0 } |
| 153 | + ) |
| 154 | + } |
| 155 | + var secondaryButtonVMOrDefault: Binding<AlertButtonVM> { |
| 156 | + return .init( |
| 157 | + get: { self.model.secondaryButton ?? Self.initialSecondaryButton }, |
| 158 | + set: { self.model.secondaryButton = $0 } |
| 159 | + ) |
| 160 | + } |
| 161 | +} |
| 162 | + |
| 163 | +#Preview { |
| 164 | + AlertPreview() |
| 165 | +} |
0 commit comments