From 80d5f427c9d3d664692abe1f16af1e4e90cb70ad Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 2 Jul 2020 18:06:58 +0100 Subject: [PATCH 01/11] Empty Picker implementation --- Sources/TokamakCore/Views/Picker.swift | 56 ++++++++++++++++++++++++ Sources/TokamakDOM/Views/Picker.swift | 27 ++++++++++++ Sources/TokamakDOM/Views/TextField.swift | 4 +- docs/progress.md | 30 ++++++------- 4 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 Sources/TokamakCore/Views/Picker.swift create mode 100644 Sources/TokamakDOM/Views/Picker.swift diff --git a/Sources/TokamakCore/Views/Picker.swift b/Sources/TokamakCore/Views/Picker.swift new file mode 100644 index 000000000..9ded50036 --- /dev/null +++ b/Sources/TokamakCore/Views/Picker.swift @@ -0,0 +1,56 @@ +// Copyright 2020 Tokamak contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +public struct Picker: View { + let selection: Binding + let label: Label + let content: Content + + public init( + selection: Binding, + label: Label, + @ViewBuilder content: () -> Content + ) { + self.selection = selection + self.label = label + self.content = content() + } + + public var body: Never { + neverBody("Picker") + } +} + +extension Picker where Label == Text { + @_disfavoredOverload public init( + _ title: S, + selection: Binding, + @ViewBuilder content: () -> Content + ) { + self.init(selection: selection, label: Text(title)) { + content() + } + } +} + +/// This is a helper class that works around absence of "package private" access control in Swift +public struct _PickerProxy { + public let subject: Picker + + public init(_ subject: Picker) { self.subject = subject } + + public var selection: Binding { subject.selection } + public var label: Label { subject.label } + public var content: Content { subject.content } +} diff --git a/Sources/TokamakDOM/Views/Picker.swift b/Sources/TokamakDOM/Views/Picker.swift new file mode 100644 index 000000000..a473ff488 --- /dev/null +++ b/Sources/TokamakDOM/Views/Picker.swift @@ -0,0 +1,27 @@ +// Copyright 2020 Tokamak contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import TokamakCore + +public typealias Picker = TokamakCore.Picker + +extension Picker: ViewDeferredToRenderer where Label == Text { + public var deferredBody: AnyView { + let proxy = _PickerProxy(self) + + return AnyView(HTML("select") { + proxy.content + }) + } +} diff --git a/Sources/TokamakDOM/Views/TextField.swift b/Sources/TokamakDOM/Views/TextField.swift index f1df76314..84e35cd93 100644 --- a/Sources/TokamakDOM/Views/TextField.swift +++ b/Sources/TokamakDOM/Views/TextField.swift @@ -22,8 +22,8 @@ public typealias TextField = TokamakCore.TextField func css(for style: TextFieldStyle) -> String { if style is PlainTextFieldStyle { return """ - background: transparent; - border: none; + background: transparent; + border: none; """ } else { return "" diff --git a/docs/progress.md b/docs/progress.md index f9f29177d..d30c7e94a 100644 --- a/docs/progress.md +++ b/docs/progress.md @@ -44,7 +44,7 @@ Table columns: | | | | | --- | ---------------------------------------------------------------------------- | :-: | | | [Toggle](https://developer.apple.com/documentation/swiftui/toggle) | | -| | [Picker](https://developer.apple.com/documentation/swiftui/picker) | | +| 🚧 | [Picker](https://developer.apple.com/documentation/swiftui/picker) | | | | [DatePicker](https://developer.apple.com/documentation/swiftui/datepicker) | | | | [Slider](https://developer.apple.com/documentation/swiftui/slider) | | | | [Stepper](https://developer.apple.com/documentation/swiftui/stepper) | | @@ -110,7 +110,7 @@ Table columns: | | | | | --- | -------------------------------------------------------------------- | :-: | -| ✅ | [Spacer](https://developer.apple.com/documentation/swiftui/spacer) | | +| ✅ | [Spacer](https://developer.apple.com/documentation/swiftui/spacer) | | | | [Divider](https://developer.apple.com/documentation/swiftui/divider) | | ### Architectural Views @@ -140,22 +140,22 @@ Table columns: ### Shapes -| | | | -| --- | ------------------------------------------------------------------------------------------ | :-: | -| 🚧 | [Rectangle](https://developer.apple.com/documentation/swiftui/rectangle) | | -| 🚧 | [RoundedRectangle](https://developer.apple.com/documentation/swiftui/roundedrectangle) | | -| 🚧 | [Ellipse](https://developer.apple.com/documentation/swiftui/ellipse) | | -| 🚧 | [Circle](https://developer.apple.com/documentation/swiftui/circle) | | -| 🚧 | [Capsule](https://developer.apple.com/documentation/swiftui/capsule) | | +| | | | +| --- | -------------------------------------------------------------------------------------- | :-: | +| 🚧 | [Rectangle](https://developer.apple.com/documentation/swiftui/rectangle) | | +| 🚧 | [RoundedRectangle](https://developer.apple.com/documentation/swiftui/roundedrectangle) | | +| 🚧 | [Ellipse](https://developer.apple.com/documentation/swiftui/ellipse) | | +| 🚧 | [Circle](https://developer.apple.com/documentation/swiftui/circle) | | +| 🚧 | [Capsule](https://developer.apple.com/documentation/swiftui/capsule) | | ### Paths -| | | | -| --- | ------------------------------------------------------------------------------------------ | :-: | -| 🚧 | [Path](https://developer.apple.com/documentation/swiftui/path) | | +| | | | +| --- | -------------------------------------------------------------- | :-: | +| 🚧 | [Path](https://developer.apple.com/documentation/swiftui/path) | | ### Styles -| | | | -| --- | ------------------------------------------------------------------------------------------ | :-: | -| 🚧 | [Color](https://developer.apple.com/documentation/swiftui/color) | | +| | | | +| --- | ---------------------------------------------------------------- | :-: | +| 🚧 | [Color](https://developer.apple.com/documentation/swiftui/color) | | From c0e3e1f0dc486fcae0e1ee6804e85460abed6b29 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Thu, 2 Jul 2020 21:08:47 +0100 Subject: [PATCH 02/11] Add PickerStyle with sub-styles --- Sources/TokamakCore/Styles/PickerStyle.swift | 42 ++++++++++++++++ Sources/TokamakCore/Views/Picker.swift | 53 ++++++++++++++++---- Sources/TokamakCore/Views/TextField.swift | 3 +- Sources/TokamakDOM/Views/Picker.swift | 14 ++++-- 4 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 Sources/TokamakCore/Styles/PickerStyle.swift diff --git a/Sources/TokamakCore/Styles/PickerStyle.swift b/Sources/TokamakCore/Styles/PickerStyle.swift new file mode 100644 index 000000000..38ca5c9d1 --- /dev/null +++ b/Sources/TokamakCore/Styles/PickerStyle.swift @@ -0,0 +1,42 @@ +// Copyright 2020 Tokamak contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +public protocol PickerStyle {} + +public struct PopUpButtonPickerStyle: PickerStyle {} + +public struct RadioGroupPickerStyle: PickerStyle {} + +public struct DefaultPickerStyle: PickerStyle {} + +enum PickerStyleKey: EnvironmentKey { + static var defaultValue: PickerStyle = DefaultPickerStyle() +} + +extension EnvironmentValues { + var pickerStyle: PickerStyle { + get { + self[PickerStyleKey.self] + } + set { + self[PickerStyleKey.self] = newValue + } + } +} + +extension View { + public func pickerStyle(_ style: PickerStyle) -> some View { + environment(\.pickerStyle, style) + } +} diff --git a/Sources/TokamakCore/Views/Picker.swift b/Sources/TokamakCore/Views/Picker.swift index 9ded50036..4ed84a5e6 100644 --- a/Sources/TokamakCore/Views/Picker.swift +++ b/Sources/TokamakCore/Views/Picker.swift @@ -12,10 +12,39 @@ // See the License for the specific language governing permissions and // limitations under the License. +public struct _RadioGroupPicker: View { + public let content: Content + + public var body: Never { + neverBody("RadioGroupPicker") + } +} + +public struct _PopUpButtonPicker: View { + public let content: Content + + public init(content: Content) { + self.content = content + } + + public var body: Never { + neverBody("PopUpButtonPicker") + } +} + +public struct _DefaultPicker: View { + public let content: Content + + public var body: Never { + neverBody("DefaultPicker") + } +} + public struct Picker: View { let selection: Binding let label: Label let content: Content + @Environment(\.pickerStyle) var style: PickerStyle public init( selection: Binding, @@ -27,8 +56,15 @@ public struct Picker: View self.content = content() } - public var body: Never { - neverBody("Picker") + public var body: some View { + switch style { + case is PopUpButtonPickerStyle: + return AnyView(_PopUpButtonPicker(content: content)) + case is RadioGroupPickerStyle: + return AnyView(_RadioGroupPicker(content: content)) + default: + return AnyView(_DefaultPicker(content: content)) + } } } @@ -44,13 +80,8 @@ extension Picker where Label == Text { } } -/// This is a helper class that works around absence of "package private" access control in Swift -public struct _PickerProxy { - public let subject: Picker - - public init(_ subject: Picker) { self.subject = subject } - - public var selection: Binding { subject.selection } - public var label: Label { subject.label } - public var content: Content { subject.content } +extension Picker: ParentView { + public var children: [AnyView] { + (content as? GroupView)?.children ?? [AnyView(content)] + } } diff --git a/Sources/TokamakCore/Views/TextField.swift b/Sources/TokamakCore/Views/TextField.swift index ce9c9a381..9aa065ef8 100644 --- a/Sources/TokamakCore/Views/TextField.swift +++ b/Sources/TokamakCore/Views/TextField.swift @@ -48,7 +48,8 @@ public struct TextField