@webspatial/platform-visionos 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/package.json +2 -2
  2. package/web-spatial/EventEmitter.swift +56 -0
  3. package/web-spatial/JSBCommand.swift +348 -0
  4. package/web-spatial/SpatialObject.swift +108 -0
  5. package/web-spatial/WebMsgCommand.swift +119 -0
  6. package/web-spatial/WebSpatialApp.swift +111 -0
  7. package/web-spatial/{libs/uiKitDelegate/Window.swift → Window.swift} +1 -0
  8. package/web-spatial/manager/Dynamic3DManager.swift +114 -0
  9. package/web-spatial/manager/JSBManager.swift +148 -0
  10. package/web-spatial/manager/WKWebViewManager.swift +39 -0
  11. package/web-spatial/{libs/webView/manifest.swift → manifest.swift} +16 -5
  12. package/web-spatial/model/SpatialApp.swift +190 -0
  13. package/web-spatial/model/SpatialScene.swift +1042 -0
  14. package/web-spatial/model/Spatialized2DElement.swift +128 -0
  15. package/web-spatial/model/SpatializedDynamic3DElement.swift +34 -0
  16. package/web-spatial/model/SpatializedElement.swift +95 -0
  17. package/web-spatial/model/SpatializedStatic3DElement.swift +19 -0
  18. package/web-spatial/model/dynamic3d/Geometry.swift +95 -0
  19. package/web-spatial/model/dynamic3d/SpatialComponent.swift +72 -0
  20. package/web-spatial/model/dynamic3d/SpatialEntity.swift +211 -0
  21. package/web-spatial/model/dynamic3d/SpatialMaterial.swift +39 -0
  22. package/web-spatial/model/dynamic3d/SpatialModelEntity.swift +39 -0
  23. package/web-spatial/model/dynamic3d/SpatialModelResource.swift +38 -0
  24. package/web-spatial/model/dynamic3d/SpatialTextureResource.swift +18 -0
  25. package/web-spatial/protocol/ScrollAbleSpatialElementContainer.swift +1 -0
  26. package/web-spatial/protocol/SpatialScrollAble.swift +8 -0
  27. package/web-spatial/protocol/SpatializedElementContainer.swift +8 -0
  28. package/web-spatial/protocol/WebMsgSender.swift +5 -0
  29. package/web-spatial/types/Vec2.swift +12 -0
  30. package/web-spatial/types/Vec3.swift +7 -0
  31. package/web-spatial/view/SceneHandlerUIView.swift +92 -0
  32. package/web-spatial/{views/ui/NavView.swift → view/SpatialNavView.swift} +149 -77
  33. package/web-spatial/view/SpatialSceneContentView.swift +218 -0
  34. package/web-spatial/view/SpatialSceneView.swift +53 -0
  35. package/web-spatial/view/Spatialized2DElementView.swift +96 -0
  36. package/web-spatial/view/SpatializedDynamic3DView.swift +104 -0
  37. package/web-spatial/view/SpatializedElementView.swift +178 -0
  38. package/web-spatial/view/SpatializedStatic3DView.swift +70 -0
  39. package/web-spatial/{views → view/view-modifier}/MaterialWithBorderCornerModifier.swift +28 -8
  40. package/web-spatial/webview/SpatialWebController.swift +300 -0
  41. package/web-spatial/webview/SpatialWebView.swift +34 -0
  42. package/web-spatial/webview/SpatialWebViewModel.swift +307 -0
  43. package/web-spatial.xcodeproj/project.pbxproj +126 -207
  44. package/web-spatial/libs/EventEmitter.swift +0 -25
  45. package/web-spatial/libs/SpatialComponent.swift +0 -24
  46. package/web-spatial/libs/SpatialEntity.swift +0 -172
  47. package/web-spatial/libs/SpatialInputComponent.swift +0 -19
  48. package/web-spatial/libs/SpatialMeshResource.swift +0 -12
  49. package/web-spatial/libs/SpatialModel3DComponent.swift +0 -51
  50. package/web-spatial/libs/SpatialModelComponent.swift +0 -25
  51. package/web-spatial/libs/SpatialObject.swift +0 -140
  52. package/web-spatial/libs/SpatialPhysicallyBasedMaterial.swift +0 -19
  53. package/web-spatial/libs/SpatialViewComponent.swift +0 -8
  54. package/web-spatial/libs/SpatialWindowComponent.swift +0 -454
  55. package/web-spatial/libs/SpatialWindowContainer.swift +0 -153
  56. package/web-spatial/libs/Utils/CommandManager.swift +0 -823
  57. package/web-spatial/libs/Utils/PerfClock.swift +0 -43
  58. package/web-spatial/libs/Utils/SceneManager.swift +0 -101
  59. package/web-spatial/libs/Utils/WindowContainerMgr.swift +0 -122
  60. package/web-spatial/libs/json/JsonParser.swift +0 -45
  61. package/web-spatial/libs/webView/UpdateSystem.swift +0 -26
  62. package/web-spatial/libs/webView/backend/NativeWebView.swift +0 -350
  63. package/web-spatial/views/ImmersiveView.swift +0 -17
  64. package/web-spatial/views/OpenDismissHandlerUI.swift +0 -45
  65. package/web-spatial/views/PlainWindowContainerView.swift +0 -132
  66. package/web-spatial/views/SpatialModel3DView.swift +0 -187
  67. package/web-spatial/views/SpatialViewUI.swift +0 -168
  68. package/web-spatial/views/SpatialWebViewUI.swift +0 -179
  69. package/web-spatial/views/VolumetricWindowContainerView.swift +0 -30
  70. package/web-spatial/web_spatialApp.swift +0 -141
  71. /package/web-spatial/{libs/Utils → Utils}/ColorExtension.swift +0 -0
  72. /package/web-spatial/{libs/Utils → Utils}/Logger.swift +0 -0
  73. /package/web-spatial/{views → view}/LoadingView.swift +0 -0
  74. /package/web-spatial/{views → view/view-modifier}/HideViewModifier.swift +0 -0
@@ -0,0 +1,39 @@
1
+ import SwiftUI
2
+ import RealityKit
3
+
4
+ @Observable
5
+ class SpatialModelEntity: SpatialEntity{
6
+ private var modelEntity:Entity? = nil
7
+ required init(_ modelResource:SpatialModelResource, _ _name:String = ""){
8
+ super.init(_name)
9
+ modelEntity = modelResource.resource
10
+ addChild(modelEntity!)
11
+ generateCollisionShapes(recursive: true)
12
+ }
13
+
14
+ required init() {
15
+ super.init()
16
+ }
17
+
18
+ override internal func onDestroy(){
19
+ super.onDestroy()
20
+ if let modelEntity = self.modelEntity{
21
+ removeChild(modelEntity)
22
+ }
23
+ modelEntity = nil
24
+ }
25
+
26
+ enum CodingKeys: String, CodingKey {
27
+ case id, name, isDestroyed, children, components, model
28
+ }
29
+
30
+ override func encode(to encoder: any Encoder) throws {
31
+ var container = encoder.container(keyedBy: CodingKeys.self)
32
+ try container.encode(spatialId, forKey: .id)
33
+ try container.encode(name, forKey: .name)
34
+ try container.encode(isDestroyed, forKey: .isDestroyed)
35
+ try container.encode(spatialChildren, forKey: .children)
36
+ try container.encode(spatialComponents, forKey: .components)
37
+ try container.encode(modelEntity?.id, forKey: .model)
38
+ }
39
+ }
@@ -0,0 +1,38 @@
1
+ import RealityKit
2
+ import SwiftUI
3
+
4
+ @Observable
5
+ class SpatialModelResource: SpatialObject {
6
+ var _resource: Entity? = nil
7
+ var resource: Entity? {
8
+ _resource
9
+ }
10
+
11
+ init(_ urlString: String, _ onload: @escaping (Result<SpatialModelResource, Error>) -> Void) {
12
+ super.init()
13
+ Dynamic3DManager.loadResourceToLocal(urlString) { result in
14
+ switch result {
15
+ case let .success(url):
16
+ DispatchQueue.main.async {
17
+ do {
18
+ let entity = try Entity.load(contentsOf: url)
19
+ self._resource = entity
20
+ onload(.success(self))
21
+ } catch {
22
+ print("Failed to load entity from URL: \(error)")
23
+ onload(.failure(error))
24
+ self.destroy()
25
+ }
26
+ }
27
+ case let .failure(error):
28
+ print("Failed to download model: \(error)")
29
+ onload(.failure(error))
30
+ self.destroy()
31
+ }
32
+ }
33
+ }
34
+
35
+ override func onDestroy() {
36
+ _resource = nil
37
+ }
38
+ }
@@ -0,0 +1,18 @@
1
+ import SwiftUI
2
+ import RealityKit
3
+
4
+ @Observable
5
+ class SpatialTextureResource:SpatialObject {
6
+ internal var _resource:TextureResource? = nil
7
+ var resource:TextureResource? {
8
+ _resource
9
+ }
10
+
11
+ override init(_ url:String){
12
+ super.init()
13
+ }
14
+
15
+ override internal func onDestroy() {
16
+ _resource = nil
17
+ }
18
+ }
@@ -0,0 +1 @@
1
+ protocol ScrollAbleSpatialElementContainer: SpatialScrollAble, SpatializedElementContainer {}
@@ -0,0 +1,8 @@
1
+ import CoreFoundation
2
+
3
+ protocol SpatialScrollAble {
4
+ func updateDeltaScrollOffset(_ delta: Vec2)
5
+ func stopScrolling()
6
+ var scrollPageEnabled: Bool { get }
7
+ var scrollOffset: Vec2 { get }
8
+ }
@@ -0,0 +1,8 @@
1
+ protocol SpatializedElementContainer {
2
+ var id: String { get }
3
+ var parent: ScrollAbleSpatialElementContainer? { get }
4
+ func addChild(_ spatializedElement: SpatializedElement)
5
+ func removeChild(_ spatializedElement: SpatializedElement)
6
+ func getChildren() -> [String: SpatializedElement]
7
+ func getChildrenOfType(_ type: SpatializedElementType) -> [String: SpatializedElement]
8
+ }
@@ -0,0 +1,5 @@
1
+ import CoreFoundation
2
+
3
+ protocol WebMsgSender {
4
+ func sendWebMsg(_ id: String, _ msg: Encodable)
5
+ }
@@ -0,0 +1,12 @@
1
+ import CoreFoundation
2
+
3
+ struct Vec2: Codable {
4
+ var x: CGFloat
5
+ var y: CGFloat
6
+ }
7
+
8
+ extension Vec2 {
9
+ static func + (left: Vec2, right: Vec2) -> Vec2 {
10
+ return Vec2(x: left.x + right.x, y: left.y + right.y)
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ import CoreFoundation
2
+
3
+ struct Vec3: Codable {
4
+ var x: CGFloat
5
+ var y: CGFloat
6
+ var z: CGFloat
7
+ }
@@ -0,0 +1,92 @@
1
+ import SwiftUI
2
+
3
+ struct SceneHandlerUIView: View {
4
+ @Environment(\.openImmersiveSpace) private var openImmersiveSpace
5
+ @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace
6
+ @Environment(\.openWindow) private var openWindow
7
+ @Environment(\.dismissWindow) private var dismissWindow
8
+ @EnvironmentObject private var sceneDelegate: SceneDelegate
9
+
10
+ @State var spatialScene: SpatialScene
11
+
12
+ @Environment(\.scenePhase) private var scenePhase
13
+
14
+ private func setResizibility(resizingRestrictions: UIWindowScene.ResizingRestrictions) {
15
+ sceneDelegate.window?.windowScene?
16
+ .requestGeometryUpdate(
17
+ .Vision(
18
+ resizingRestrictions: resizingRestrictions
19
+ )
20
+ )
21
+ }
22
+
23
+ private func setResizeRange(resizeRange: ResizeRange) {
24
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.0) {
25
+ sceneDelegate.window?.windowScene?
26
+ .requestGeometryUpdate(
27
+ .Vision(
28
+ minimumSize: CGSize(
29
+ width: resizeRange.minWidth ?? 0,
30
+ height: resizeRange
31
+ .minHeight ?? 0
32
+ ),
33
+ maximumSize: CGSize(
34
+ width: resizeRange.maxWidth ?? .infinity,
35
+ height: resizeRange.maxHeight ?? .infinity
36
+ )
37
+ )
38
+ ) { error in
39
+ print("error:", error)
40
+ }
41
+ }
42
+ }
43
+
44
+ var body: some View {
45
+ VStack {}
46
+ .onAppear {
47
+ // window scene only resize logic
48
+ guard spatialScene.windowStyle == .window else {
49
+ return
50
+ }
51
+ if let range = spatialScene.sceneConfig?.resizeRange {
52
+ self.setResizeRange(resizeRange: range)
53
+ if (range.minWidth != nil || range.minHeight != nil) && range.minWidth == range.maxWidth && range.minHeight == range.maxHeight {
54
+ self.setResizibility(resizingRestrictions: .none)
55
+ } else {
56
+ self.setResizibility(resizingRestrictions: .freeform)
57
+ }
58
+ }
59
+ }
60
+ .onDisappear {
61
+ print("onScene Disappear")
62
+ spatialScene.destroy()
63
+ }
64
+ .onReceive(spatialScene.openWindowData) { sceneID in
65
+ if let spatialScene = SpatialApp.Instance.getScene(sceneID) {
66
+ let _ = openWindow(
67
+ id: spatialScene.windowStyle.rawValue,
68
+ value: sceneID
69
+ )
70
+ }
71
+ }
72
+ .onReceive(spatialScene.closeWindowData) { sceneID in
73
+ if let spatialScene = SpatialApp.Instance.getScene(sceneID) {
74
+ dismissWindow(
75
+ id: spatialScene.windowStyle.rawValue,
76
+ value: sceneID
77
+ )
78
+ }
79
+ }
80
+ .onReceive(spatialScene.setLoadingWindowData) { wd in
81
+ if wd.method == .show {
82
+ openWindow(id: "loading", value: wd.sceneID)
83
+ } else if wd.method == .hide {
84
+ dismissWindow(id: "loading", value: wd.sceneID)
85
+ }
86
+ }
87
+
88
+ .onChange(of: scenePhase) { oldValue, newValue in
89
+ logger.debug("OpenDismissHandlerUI: Value changed from \(oldValue) to \(newValue)")
90
+ }
91
+ }
92
+ }
@@ -1,11 +1,75 @@
1
1
  import SwiftUI
2
- import WebKit
3
2
 
4
- struct NavView: View {
5
- static let navHeight: CGFloat = 60
3
+ struct NavButtonStyle: ButtonStyle {
4
+ func makeBody(configuration: Configuration) -> some View {
5
+ configuration.label
6
+ .background(Color.clear)
7
+ }
8
+ }
9
+
10
+ struct NavDivider: View {
11
+ var width: CGFloat = 1
12
+ var height: CGFloat = 16
13
+ var paddingLR: CGFloat = 4
14
+ var paddingTB: CGFloat = 12
15
+ var body: some View {
16
+ VStack {
17
+ Rectangle().fill(Color(hex: "#FFFFFF3D")).frame(width: width, height: height)
18
+ }
19
+ .padding([.top, .bottom], paddingTB)
20
+ .padding([.leading, .trailing], paddingLR)
21
+ }
22
+ }
23
+
24
+
25
+ struct NavButton: View {
26
+ var action: () -> Void
27
+ var children: Image
28
+ var size: CGFloat = 44
29
+ var padding: CGFloat = 10
30
+ var clearBackGround: Bool = true
31
+ var body: some View {
32
+ if clearBackGround {
33
+ Button(action: action, label: {
34
+ ZStack {
35
+ Circle()
36
+ .fill(Color.white.opacity(0))
37
+ .frame(width: size, height: size)
38
+ .overlay(
39
+ children.resizable().frame(width: size - padding * 2, height: size - padding * 2)
40
+ )
41
+ .contentShape(Circle())
42
+ }
43
+ }).buttonStyle(NavButtonStyle()).frame(width: size, height: size).hoverEffect(.highlight)
44
+ } else {
45
+ Button(action: action, label: {
46
+ Circle()
47
+ .fill(Color.white.opacity(0))
48
+ .frame(width: size, height: size)
49
+ .overlay(
50
+ children.resizable().frame(width: size - padding * 2, height: size - padding * 2)
51
+ )
52
+ .contentShape(Circle())
53
+ }).hoverEffect(.highlight)
54
+ }
55
+ }
56
+ }
57
+
58
+
59
+ struct SpatialNavView: View {
60
+ static let navHeight: CGFloat = SpatialScene.navHeight
6
61
  static let minWidth: CGFloat = 400
7
- @State var swc: SpatialWindowComponent?
8
- @StateObject var navInfo: NavInfo
62
+ var spatialScene: SpatialScene
63
+ var model:SpatialWebViewModel? {
64
+ get {
65
+ return spatialScene.spatialWebViewModel
66
+ }
67
+ }
68
+ var url: String {
69
+ get {
70
+ return spatialScene.url
71
+ }
72
+ }
9
73
  @State var navWidth: CGFloat = 0
10
74
  @State private var showCopyTip = false
11
75
  @State private var contentHeight: CGFloat = 60
@@ -17,6 +81,36 @@ struct NavView: View {
17
81
  @State private var showNav: Double = 0
18
82
  @State private var showUrl: Double = 0
19
83
  @Namespace var hoverNamespace
84
+
85
+ func checkButtonState(){
86
+ canGoBack = model!.getController().webview!.canGoBack
87
+ canGoForward = model!.getController().webview!.canGoForward
88
+ }
89
+
90
+ func goBack() {
91
+ model?.getController().webview?.goBack()
92
+ }
93
+
94
+ func goForward() {
95
+ model?.getController().webview?.goForward()
96
+ }
97
+
98
+ func reload() {
99
+ model?.getController().webview?.reload()
100
+ }
101
+
102
+ func navigateToURL(url: URL) {
103
+ model?.load(url.absoluteString)
104
+ }
105
+
106
+ func getURL() -> URL? {
107
+ return model?.getController().webview?.url
108
+ }
109
+
110
+ @State var canGoBack: Bool = false
111
+
112
+ @State var canGoForward: Bool = false
113
+
20
114
  var navHoverGroup: HoverEffectGroup {
21
115
  HoverEffectGroup(hoverNamespace)
22
116
  }
@@ -28,9 +122,19 @@ struct NavView: View {
28
122
  Image("logo").resizable().frame(width: 32, height: 32)
29
123
  .cornerRadius(100)
30
124
  if pwaManager.display == .minimal {
31
- NavButton(action: { swc?.goBack() }, children: Image("arrow_left"), clearBackGround: true).disabled(!(swc?.canGoBack ?? false))
32
- NavButton(action: { swc?.goForward() }, children: Image("arrow_right"), clearBackGround: true).disabled(!(swc?.canGoBack ?? false))
33
- NavButton(action: { swc?.reload() }, children: Image("refresh"), clearBackGround: true)
125
+ NavButton(
126
+ action: { self.goBack()
127
+ },
128
+ children: Image("arrow_left"),
129
+ clearBackGround: true)
130
+ .disabled(!(self.canGoBack))
131
+ NavButton(
132
+ action: { self.goForward()
133
+ },
134
+ children: Image("arrow_right"),
135
+ clearBackGround: true)
136
+ .disabled(!(self.canGoBack))
137
+ NavButton(action: { self.reload() }, children: Image("refresh"), clearBackGround: true)
34
138
  NavDivider()
35
139
  }
36
140
  NavButton(action: { print("click"); withAnimation(.easeInOut(duration: 0.5)) { showNav = 1.0; showEnter = 0 } }, children: Image("more"), clearBackGround: true)
@@ -49,12 +153,20 @@ struct NavView: View {
49
153
  .opacity(showEnter)
50
154
  HStack(spacing: 14) {
51
155
  if pwaManager.display == .minimal {
52
- NavButton(action: { swc?.goBack() }, children: Image("arrow_left")).disabled(!(swc?.canGoBack ?? false))
53
- NavButton(action: { swc?.goForward() }, children: Image("arrow_right")).disabled(!(swc?.canGoBack ?? false))
54
- NavButton(action: { swc?.reload() }, children: Image("refresh"))
156
+ NavButton(
157
+ action: { self.goBack()
158
+ },
159
+ children: Image("arrow_left"))
160
+ .disabled(!(self.canGoBack))
161
+ NavButton(
162
+ action: { self.goForward()
163
+ },
164
+ children: Image("arrow_right"))
165
+ .disabled(!(self.canGoBack))
166
+ NavButton(action: { self.reload() }, children: Image("refresh"))
55
167
  NavDivider()
56
168
  }
57
- NavButton(action: { swc?.navigateToURL(url: URL(string: pwaManager.start_url)!) }, children: Image("home"))
169
+ NavButton(action: { self.navigateToURL(url: URL(string: pwaManager.start_url)!) }, children: Image("home"))
58
170
  NavButton(action: { withAnimation(.easeInOut(duration: 0.5)) { showUrl = 1; showNav = 0 } }, children: Image("link"))
59
171
  NavButton(action: { showNav = 0; showEnter = 1 }, children: Image("back"))
60
172
  }
@@ -70,7 +182,11 @@ struct NavView: View {
70
182
  }
71
183
  }
72
184
  HStack(spacing: 6) {
73
- Text(navInfo.url.count > 0 ? navInfo.url : (swc?.getURL()?.absoluteString ?? ""))
185
+ Text(
186
+ url.count > 0 ? url : (
187
+ self.getURL()?.absoluteString ?? ""
188
+ )
189
+ )
74
190
  .lineLimit(1)
75
191
  .textSelection(.enabled)
76
192
  .padding(12)
@@ -80,18 +196,29 @@ struct NavView: View {
80
196
  .background(.black)
81
197
  .cornerRadius(100)
82
198
  NavButton(action: {
83
- UIPasteboard.general.string = swc?.getURL()?.absoluteString ?? ""
199
+ UIPasteboard.general.string = self.getURL()?.absoluteString ?? ""
84
200
  showCopyTip = true
85
201
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
86
202
  showCopyTip = false
87
203
  }
88
204
  withAnimation(.easeInOut(duration: 0.5)) { showUrl = 0; showNav = 1 }
89
205
  }, children: Image("copy"))
90
- NavButton(action: {
206
+ NavButton(
207
+ action: {
91
208
  print("open browser")
92
- UIApplication.shared.open(URL(string: navInfo.url.count > 0 ? navInfo.url : (swc?.getURL()?.absoluteString ?? ""))!, options: [:], completionHandler: nil)
209
+ UIApplication.shared
210
+ .open(
211
+ URL(
212
+ string: url.count > 0 ? url : (
213
+ self.getURL()?.absoluteString ?? ""
214
+ )
215
+ )!,
216
+ options: [:],
217
+ completionHandler: nil
218
+ )
93
219
  withAnimation(.easeInOut(duration: 0.5)) { showUrl = 0; showNav = 1 }
94
- }, children: Image("browser"))
220
+ },
221
+ children: Image("browser"))
95
222
  NavButton(action: { withAnimation(.easeInOut(duration: 0.5)) { showUrl = 0; showNav = 1 } }, children: Image("close"))
96
223
  }
97
224
  .popover(isPresented: $showCopyTip) {
@@ -105,6 +232,11 @@ struct NavView: View {
105
232
  .cornerRadius(100)
106
233
  .opacity(showUrl)
107
234
  }
235
+ .onAppear(){
236
+ model?.addStateListener(.didFinishLoad){
237
+ self.checkButtonState()
238
+ }
239
+ }
108
240
  }
109
241
 
110
242
  private func startTimer() {
@@ -128,63 +260,3 @@ struct NavView: View {
128
260
  timer = nil
129
261
  }
130
262
  }
131
-
132
- struct NavButtonStyle: ButtonStyle {
133
- func makeBody(configuration: Configuration) -> some View {
134
- configuration.label
135
- .background(Color.clear)
136
- }
137
- }
138
-
139
- struct NavButton: View {
140
- var action: () -> Void
141
- var children: Image
142
- var size: CGFloat = 44
143
- var padding: CGFloat = 10
144
- var clearBackGround: Bool = true
145
- var body: some View {
146
- if clearBackGround {
147
- Button(action: action, label: {
148
- ZStack {
149
- Circle()
150
- .fill(Color.white.opacity(0))
151
- .frame(width: size, height: size)
152
- .overlay(
153
- children.resizable().frame(width: size - padding * 2, height: size - padding * 2)
154
- )
155
- .contentShape(Circle())
156
- }
157
- }).buttonStyle(NavButtonStyle()).frame(width: size, height: size).hoverEffect(.highlight)
158
- } else {
159
- Button(action: action, label: {
160
- Circle()
161
- .fill(Color.white.opacity(0))
162
- .frame(width: size, height: size)
163
- .overlay(
164
- children.resizable().frame(width: size - padding * 2, height: size - padding * 2)
165
- )
166
- .contentShape(Circle())
167
- }).hoverEffect(.highlight)
168
- }
169
- }
170
- }
171
-
172
- struct NavDivider: View {
173
- var width: CGFloat = 1
174
- var height: CGFloat = 16
175
- var paddingLR: CGFloat = 4
176
- var paddingTB: CGFloat = 12
177
- var body: some View {
178
- VStack {
179
- Rectangle().fill(Color(hex: "#FFFFFF3D")).frame(width: width, height: height)
180
- }
181
- .padding([.top, .bottom], paddingTB)
182
- .padding([.leading, .trailing], paddingLR)
183
- }
184
- }
185
-
186
- // struct NavView_Previews: PreviewProvider {
187
- // static var previews: some View {
188
- // NavView()
189
- // }
190
- // }