diff --git a/README.md b/README.md index 88198213..69fbd80b 100644 --- a/README.md +++ b/README.md @@ -1,192 +1,180 @@ # SwiftUICharts -Swift package for displaying charts effortlessly. +### SwiftUICharts is here with a new version, giving more controll and customization over the charts and full ios 13 backwards compatibility. -![SwiftUI Charts](./Resources/showcase1.gif "SwiftUI Charts") +SwiftUICharts is an open source library for creating charts in iOS apps with SwiftUI. Built natively with SwiftUI in mind and it is fully compatible with the latest versions of iOS, also backwards **compatible up to iOS 13.** -It supports: -* Line charts -* Bar charts -* Pie charts +With SwiftUICharts, you can easily create a variety of chart types, including line charts, bar charts, ring charts and pie charts. It also provides additional chart types and customization options, giving you the flexibility to create charts that perfectly fit your needs. -### Installation: +In addition to its native SwiftUI integration, backwards compatibility and wide range of chart types, SwiftUICharts is also easy to use, making it a great choice for creating stunning and intuitive charts in your applications. -It requires iOS 13 and Xcode 11! +

+ +

-In Xcode got to `File -> Swift Packages -> Add Package Dependency` and paste inthe repo's url: `https://github.com/AppPear/ChartView` +### Composable -### Usage: +You can now build your custom chart from prebuilt layers. Use a simple chart, add background grids, add chart labels to the axes, add tcks to the line, etc. -import the package in the file you would like to use it: `import SwiftUICharts` +### Works great with native SwiftUI elements -You can display a Chart by adding a chart view to your parent view: +[Example codes here](./example.md) +

+ + +

-### Demo +### Installation -Added an example project, with **iOS, watchOS** target: https://github.com/AppPear/ChartViewDemo +It is a SPM package, in Xcode go to File -> Swift Packages -> Add Package Dependency and paste in the repo's url: https://github.com/AppPear/ChartView -## Line charts +if you want to add previous releases you can find release tags https://github.com/AppPear/ChartView/releases -**LineChartView with multiple lines!** -First release of this feature, interaction is disabled for now, I'll figure it out how could be the best to interact with multiple lines with a single touch. -![Multiine Charts](./Resources/multiline1.gif "Multiine Charts") +### Slack -Usage: -```swift -MultiLineChartView(data: [([8,32,11,23,40,28], GradientColors.green), ([90,99,78,111,70,60,77], GradientColors.purple), ([34,56,72,38,43,100,50], GradientColors.orngPink)], title: "Title") -``` -Gradient colors are now under the `GradientColor` struct you can create your own gradient by `GradientColor(start: Color, end: Color)` - -Available preset gradients: -* orange -* blue -* green -* blu -* bluPurpl -* purple -* prplPink -* prplNeon -* orngPink +Join our Slack channel for day to day conversation and more insights: -**Full screen view called LineView!!!** +https://join.slack.com/t/swiftuichartview/shared_invite/zt-g6mxioq8-j3iUTF1YKX7D23ML3qcc4g -![Line Charts](./Resources/fullscreen2.gif "Line Charts") +## Quick start guide: -```swift - LineView(data: [8,23,54,32,12,37,7,23,43], title: "Line chart", legend: "Full screen") // legend is optional, use optional .padding() -``` +**Create a simple chart:** -Adopts to dark mode automatically - -![Line Charts](./Resources/showcase3.gif "Line Charts") - -You can add your custom darkmode style by specifying: +

+ +

```swift -let myCustomStyle = ChartStyle(...) -let myCutsomDarkModeStyle = ChartStyle(...) -myCustomStyle.darkModeStyle = myCutsomDarkModeStyle +LineChart() + .data([3, 5, 4, 1, 0, 2, 4, 1, 0, 2, 8]) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) ``` -**Line chart is interactive, so you can drag across to reveal the data points** +**Add a background grid to the chart:** -You can add a line chart with the following code: +

+ +

```swift - LineChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", legend: "Legendary") // legend is optional +ChartGrid { + LineChart() + .data([3, 5, 4, 1, 0, 2, 4, 1, 0, 2, 8]) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) +} +.setNumberOfHorizontalLines(5) +.setNumberOfVerticalLines(4) ``` -**Turn drop shadow off by adding to the Initialiser: `dropShadow: false`** - - -## Bar charts -![Bar Charts](./Resources/showcase2.gif "Bar Charts") +**Add a axis label to the chart:** -**[New feature] you can display labels also along values and points for each bar to descirbe your data better!** -**Bar chart is interactive, so you can drag across to reveal the data points** - -You can add a bar chart with the following code: - -Labels and points: - -```swift - BarChartView(data: ChartData(values: [("2018 Q4",63150), ("2019 Q1",50900), ("2019 Q2",77550), ("2019 Q3",79600), ("2019 Q4",92550)]), title: "Sales", legend: "Quarterly") // legend is optional -``` -Only points: +

+ +

```swift - BarChartView(data: ChartData(points: [8,23,54,32,12,37,7,23,43]), title: "Title", legend: "Legendary") // legend is optional +AxisLabels { + ChartGrid { + LineChart() + .data([3, 5, 4, 1, 0, 2, 4, 1, 0, 2, 8]) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(4) +} +.setAxisXLabels([(1, "Nov"), (2, "Dec"), (3, "Jan")], range: 1...3) ``` -**ChartData** structure -Stores values in data pairs (actually tuple): `(String,Double)` -* you can have duplicate values -* keeps the data order - -You can initialise ChartData multiple ways: -* For integer values: `ChartData(points: [8,23,54,32,12,37,7,23,43])` -* For floating point values: `ChartData(points: [2.34,3.14,4.56])` -* For label,value pairs: `ChartData(values: [("2018 Q4",63150), ("2019 Q1",50900)])` +**Show chart marks on the line:** - -You can add different formats: -* Small `ChartForm.small` -* Medium `ChartForm.medium` -* Large `ChartForm.large` +

+ +

```swift -BarChartView(data: ChartData(points: [8,23,54,32,12,37,7,23,43]), title: "Title", form: ChartForm.small) +AxisLabels { + ChartGrid { + LineChart() + .showChartMarks(true) + .data([3, 5, 4, 1, 0, 2, 4, 1, 0, 2, 8]) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(4) +} +.setAxisXLabels([(1, "Nov"), (2, "Dec"), (3, "Jan")], range: 1...3) ``` -For floating point numbers, you can set a custom specifier: +**Apply custom ranges on chart** -```swift -BarChartView(data: ChartData(points:[1.23,2.43,3.37]) ,title: "A", valueSpecifier: "%.2f") -``` -For integers you can disable by passing: `valueSpecifier: "%.0f"` - - -You can set your custom image in the upper right corner by passing in the initialiser: `cornerImage:Image(systemName: "waveform.path.ecg")` - - - **Turn drop shadow off by adding to the Initialiser: `dropShadow: false`** - - ### You can customize styling of the chart with a ChartStyle object: - -Customizable: -* background color -* accent color -* second gradient color -* text color -* legend text color - -```swift - let chartStyle = ChartStyle(backgroundColor: Color.black, accentColor: Colors.OrangeStart, secondGradientColor: Colors.OrangeEnd, chartFormSize: ChartForm.medium, textColor: Color.white, legendTextColor: Color.white ) - ... - BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: chartStyle) -``` +

+ +

-You can access built-in styles: ```swift - BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: Styles.barChartMidnightGreen) +AxisLabels { + ChartGrid { + LineChart() + .showChartMarks(true) + .data([3, 5, 4, 1, 0, 2, 4, 1, 0, 2, 8]) + .rangeY(0...10) + .rangeX(0...5) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(4) +} +.setAxisXLabels([(1, "Nov"), (2, "Dec"), (3, "Jan")], range: 1...3) ``` -#### All styles available as a preset: -* barChartStyleOrangeLight -* barChartStyleOrangeDark -* barChartStyleNeonBlueLight -* barChartStyleNeonBlueDark -* barChartMidnightGreenLight -* barChartMidnightGreenDark - -![Midnightgreen](./Resources/midnightgreen.gif "Midnightgreen") - -![Custom Charts](./Resources/showcase5.png "Custom Charts") +**Add multiple charts in the same frame** -### You can customize the size of the chart with a ChartForm object: - -**ChartForm** -* `.small` -* `.medium` -* `.large` -* `.detail` +

+ +

```swift -BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", form: ChartForm.small) +AxisLabels { + ChartGrid { + LineChart() + .showChartMarks(true) + .data([3, 5, 4, 1, 0, 2, 4, 1, 0, 2, 8]) + .rangeY(0...12) + .rangeX(0...5) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) + LineChart() + .showChartMarks(true) + .data([4, 1, 0, 2, 8, 3, 6, 1, 4]) + .rangeY(0...12) + .rangeX(0...5) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.blue, .purple))) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(4) +} +.setAxisXLabels([(1, "Nov"), (2, "Dec"), (3, "Jan")], range: 1...3) ``` -### WatchOS support for Bar charts: - -![Pie Charts](./Resources/watchos1.png "Pie Charts") +**Combine chart types in the same frame** -## Pie charts -![Pie Charts](./Resources/showcase4.png "Pie Charts") - -You can add a pie chart with the following code: +

+ +

```swift - PieChartView(data: [8,23,54,32], title: "Title", legend: "Legendary") // legend is optional +AxisLabels { + ChartGrid { + BarChart() + .data([2, 4, 1, 3]) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.orange, .red))) + LineChart() + .showChartMarks(true) + .data([2, 4, 1, 3]) + .chartStyle(ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient(.blue, .purple))) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(4) +} +.setAxisXLabels([(1, "Nov"), (2, "Dec"), (3, "Jan")], range: 1...3) ``` -**Turn drop shadow off by adding to the Initialiser: `dropShadow: false`** - diff --git a/Resources/barchartcard.png b/Resources/barchartcard.png new file mode 100644 index 00000000..2e816179 Binary files /dev/null and b/Resources/barchartcard.png differ diff --git a/Resources/barvid2.gif b/Resources/barvid2.gif new file mode 100644 index 00000000..3e8499a6 Binary files /dev/null and b/Resources/barvid2.gif differ diff --git a/Resources/chartpic1.png b/Resources/chartpic1.png new file mode 100644 index 00000000..62608829 Binary files /dev/null and b/Resources/chartpic1.png differ diff --git a/Resources/chartpic2.png b/Resources/chartpic2.png new file mode 100644 index 00000000..939cb8fb Binary files /dev/null and b/Resources/chartpic2.png differ diff --git a/Resources/chartpic3.png b/Resources/chartpic3.png new file mode 100644 index 00000000..1bd0d5e7 Binary files /dev/null and b/Resources/chartpic3.png differ diff --git a/Resources/chartpic4.png b/Resources/chartpic4.png new file mode 100644 index 00000000..1aa7a358 Binary files /dev/null and b/Resources/chartpic4.png differ diff --git a/Resources/chartpic5.png b/Resources/chartpic5.png new file mode 100644 index 00000000..d1e06b88 Binary files /dev/null and b/Resources/chartpic5.png differ diff --git a/Resources/chartpic6.png b/Resources/chartpic6.png new file mode 100644 index 00000000..1d16a59e Binary files /dev/null and b/Resources/chartpic6.png differ diff --git a/Resources/chartpic7.png b/Resources/chartpic7.png new file mode 100644 index 00000000..aee3f227 Binary files /dev/null and b/Resources/chartpic7.png differ diff --git a/Resources/fullscreen1.gif b/Resources/fullscreen1.gif deleted file mode 100644 index 5e52fdf5..00000000 Binary files a/Resources/fullscreen1.gif and /dev/null differ diff --git a/Resources/fullscreen2.gif b/Resources/fullscreen2.gif deleted file mode 100644 index 2bf3af2d..00000000 Binary files a/Resources/fullscreen2.gif and /dev/null differ diff --git a/Resources/linechartcard.png b/Resources/linechartcard.png new file mode 100644 index 00000000..d7c49156 Binary files /dev/null and b/Resources/linechartcard.png differ diff --git a/Resources/linevid2.gif b/Resources/linevid2.gif new file mode 100644 index 00000000..8bc8a650 Binary files /dev/null and b/Resources/linevid2.gif differ diff --git a/Resources/midnightgreen.gif b/Resources/midnightgreen.gif deleted file mode 100644 index 7fc8f746..00000000 Binary files a/Resources/midnightgreen.gif and /dev/null differ diff --git a/Resources/multiline1.gif b/Resources/multiline1.gif deleted file mode 100644 index 5eb45b28..00000000 Binary files a/Resources/multiline1.gif and /dev/null differ diff --git a/Resources/piechartcard.png b/Resources/piechartcard.png new file mode 100644 index 00000000..0cc1e751 Binary files /dev/null and b/Resources/piechartcard.png differ diff --git a/Resources/pievid2.gif b/Resources/pievid2.gif new file mode 100644 index 00000000..a30279bb Binary files /dev/null and b/Resources/pievid2.gif differ diff --git a/Resources/ringchart1.png b/Resources/ringchart1.png new file mode 100644 index 00000000..da2b200e Binary files /dev/null and b/Resources/ringchart1.png differ diff --git a/Resources/showcase1.gif b/Resources/showcase1.gif deleted file mode 100644 index 52bba15a..00000000 Binary files a/Resources/showcase1.gif and /dev/null differ diff --git a/Resources/showcase2.gif b/Resources/showcase2.gif deleted file mode 100644 index 66db188d..00000000 Binary files a/Resources/showcase2.gif and /dev/null differ diff --git a/Resources/showcase3.gif b/Resources/showcase3.gif deleted file mode 100644 index 497fed2a..00000000 Binary files a/Resources/showcase3.gif and /dev/null differ diff --git a/Resources/showcase4.png b/Resources/showcase4.png deleted file mode 100644 index a58c861f..00000000 Binary files a/Resources/showcase4.png and /dev/null differ diff --git a/Resources/showcase5.png b/Resources/showcase5.png deleted file mode 100644 index 319cd116..00000000 Binary files a/Resources/showcase5.png and /dev/null differ diff --git a/Resources/watchos1.png b/Resources/watchos1.png deleted file mode 100644 index 65d42e5e..00000000 Binary files a/Resources/watchos1.png and /dev/null differ diff --git a/Sources/SwiftUICharts/Base/Axis/AxisLabels.swift b/Sources/SwiftUICharts/Base/Axis/AxisLabels.swift index 0efaa897..f58eca6d 100644 --- a/Sources/SwiftUICharts/Base/Axis/AxisLabels.swift +++ b/Sources/SwiftUICharts/Base/Axis/AxisLabels.swift @@ -58,7 +58,7 @@ public struct AxisLabels: View { } public var body: some View { - VStack(spacing: 0.0) { + VStack(spacing: 4.0) { HStack { if axisLabelsStyle.axisLabelsYPosition == .leading { yAxis diff --git a/Sources/SwiftUICharts/Charts/BarChart/BarChartCell.swift b/Sources/SwiftUICharts/Charts/BarChart/BarChartCell.swift index 13153557..31ac488f 100644 --- a/Sources/SwiftUICharts/Charts/BarChart/BarChartCell.swift +++ b/Sources/SwiftUICharts/Charts/BarChart/BarChartCell.swift @@ -36,6 +36,7 @@ struct BarChartCell_Previews: PreviewProvider { Group { Group { BarChartCell(value: 0, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat()) + .padding(50) BarChartCell(value: 0.5, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat()) BarChartCell(value: 0.75, gradientColor: ColorGradient.whiteBlack, touchLocation: CGFloat()) diff --git a/Sources/SwiftUICharts/Charts/BarChart/BarChartCellShape.swift b/Sources/SwiftUICharts/Charts/BarChart/BarChartCellShape.swift index 268f4229..2e1b61e6 100644 --- a/Sources/SwiftUICharts/Charts/BarChart/BarChartCellShape.swift +++ b/Sources/SwiftUICharts/Charts/BarChart/BarChartCellShape.swift @@ -12,6 +12,9 @@ struct BarChartCellShape: Shape, Animatable { func path(in rect: CGRect) -> Path { let adjustedOriginY = rect.height - (rect.height * CGFloat(value)) var path = Path() + guard value != 0 else { + return path + } path.move(to: CGPoint(x: 0.0 , y: rect.height)) path.addLine(to: CGPoint(x: 0.0, y: adjustedOriginY + cornerRadius)) path.addArc(center: CGPoint(x: cornerRadius, y: adjustedOriginY + cornerRadius), @@ -40,6 +43,10 @@ struct BarChartCellShape_Previews: PreviewProvider { BarChartCellShape(value: 0.3) .fill(Color.blue) + + BarChartCellShape(value: 0) + .fill(Color.blue) + .padding(50) BarChartCellShape(value: -0.3) .fill(Color.blue) diff --git a/Sources/SwiftUICharts/Charts/BarChart/BarChartRow.swift b/Sources/SwiftUICharts/Charts/BarChart/BarChartRow.swift index 1115d30b..4d435a65 100644 --- a/Sources/SwiftUICharts/Charts/BarChart/BarChartRow.swift +++ b/Sources/SwiftUICharts/Charts/BarChart/BarChartRow.swift @@ -62,7 +62,7 @@ public struct BarChartRow: View { } struct BarChartRow_Previews: PreviewProvider { - static let chartData = ChartData([6, 2, 5, 8, 6]) + static let chartData = ChartData([6, 2, 0, 8, 6]) static let chartStyle = ChartStyle(backgroundColor: .white, foregroundColor: .orangeBright) static var previews: some View { BarChartRow(chartData: chartData, style: chartStyle) diff --git a/Sources/SwiftUICharts/Charts/LineChart/Model/LineChartProperties.swift b/Sources/SwiftUICharts/Charts/LineChart/Model/LineChartProperties.swift index 24893be2..1dab4087 100644 --- a/Sources/SwiftUICharts/Charts/LineChart/Model/LineChartProperties.swift +++ b/Sources/SwiftUICharts/Charts/LineChart/Model/LineChartProperties.swift @@ -3,7 +3,7 @@ import SwiftUI public class LineChartProperties: ObservableObject { @Published var lineWidth: CGFloat = 2.0 @Published var backgroundGradient: ColorGradient? - @Published var showChartMarks: Bool = true + @Published var showChartMarks: Bool = false @Published var customChartMarksColors: ColorGradient? @Published var lineStyle: LineStyle = .curved @Published var animationEnabled: Bool = true diff --git a/example.md b/example.md new file mode 100644 index 00000000..12ed808c --- /dev/null +++ b/example.md @@ -0,0 +1,193 @@ +# SwiftUICharts + +### Example codes + +

+ +

+ +```swift +import SwiftUI +import SwiftUICharts + +struct DemoView: View { + var body: some View { + VStack(alignment: .leading) { + Text("Sneakers sold") + .font(.title) + Text("Last week") + .font(.subheadline) + .foregroundColor(.gray) + .padding(.bottom, 8.0) + HStack { + AxisLabels { + ChartGrid { + LineChart() + .showChartMarks(true) + .rangeY(10...40) + .data([12, 34, 23, 18, 36, 22, 26]) + .chartStyle(ChartStyle(backgroundColor: .white, + foregroundColor: ColorGradient(.blue, .purple))) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(0) + } + .setAxisXLabels([(1, "M"), (2, "T"), (3, "W"),(4, "T"), (5, "F"), (6, "S"), (7, "S")], + range: 1...7) + .setColor(.gray) + .setFont(.caption2) + + VStack(alignment: .leading, spacing: 8.0) { + Text("Highest revenue:") + .font(.callout) + Text("Tuesday") + .font(.subheadline) + .bold() + + Text("Most sales:") + .font(.callout) + Text("Friday") + .font(.subheadline) + .bold() + Spacer() + } + .frame(maxWidth: .infinity) + } + } + .padding(16.0) + .background(RoundedRectangle(cornerRadius: 20) + .fill(.white) + .shadow(radius: 8.0)) + .padding(32) + .frame(width: 450, height: 350) + } +} +``` + +

+ +

+ +```swift +import SwiftUI +import SwiftUICharts + +struct DemoView: View { + var body: some View { + VStack(alignment: .leading) { + Text("Sneaker brands") + .font(.title) + Text("By popularity") + .font(.subheadline) + .foregroundColor(.gray) + .padding(.bottom, 8.0) + HStack { + AxisLabels { + ChartGrid { + BarChart() + .data([34, 23, 12]) + .chartStyle(ChartStyle(backgroundColor: .white, + foregroundColor: [ColorGradient(.red, .orange), + ColorGradient(.blue, .purple), + ColorGradient(.green, .yellow)])) + } + .setNumberOfHorizontalLines(5) + .setNumberOfVerticalLines(0) + } + .setAxisYLabels([(1, "0"), (2, "100"), (3, "200")], + range: 1...3) + .setColor(.gray) + .setFont(.caption2) + + VStack(alignment: .leading, spacing: 8.0) { + HStack { + Circle() + .fill(ColorGradient(.red, .orange).linearGradient(from: .bottom, to: .top)) + .frame(width: 24.0, height: 24.0) + Text("Sneaker brand 1") + } + HStack { + Circle() + .fill(ColorGradient(.blue, .purple).linearGradient(from: .bottom, to: .top)) + .frame(width: 24.0, height: 24.0) + Text("Sneaker brand 2") + } + HStack { + Circle() + .fill(ColorGradient(.green, .yellow).linearGradient(from: .bottom, to: .top)) + .frame(width: 24.0, height: 24.0) + Text("Sneaker brand 3") + } + Spacer() + } + .frame(maxWidth: .infinity) + } + } + .padding(16.0) + .background(RoundedRectangle(cornerRadius: 20) + .fill(.white) + .shadow(radius: 8.0)) + .padding(32) + .frame(width: 450, height: 350) + } +} +``` + +

+ +

+ +```swift +import SwiftUI +import SwiftUICharts + +struct DemoView: View { + var body: some View { + VStack(alignment: .leading) { + Text("Sneaker brands") + .font(.title) + Text("By popularity") + .font(.subheadline) + .foregroundColor(.gray) + .padding(.bottom, 8.0) + HStack { + PieChart() + .data([34, 23, 12]) + .chartStyle(ChartStyle(backgroundColor: .white, + foregroundColor: [ColorGradient(.red, .orange), + ColorGradient(.blue, .purple), + ColorGradient(.yellow, .green),])) + + VStack(alignment: .leading, spacing: 8.0) { + HStack { + Circle() + .fill(ColorGradient(.red, .orange).linearGradient(from: .bottom, to: .top)) + .frame(width: 24.0, height: 24.0) + Text("Sneaker brand 1") + } + HStack { + Circle() + .fill(ColorGradient(.blue, .purple).linearGradient(from: .bottom, to: .top)) + .frame(width: 24.0, height: 24.0) + Text("Sneaker brand 2") + } + HStack { + Circle() + .fill(ColorGradient(.green, .yellow).linearGradient(from: .bottom, to: .top)) + .frame(width: 24.0, height: 24.0) + Text("Sneaker brand 3") + } + Spacer() + } + .frame(maxWidth: .infinity) + } + } + .padding(16.0) + .background(RoundedRectangle(cornerRadius: 20) + .fill(.white) + .shadow(radius: 8.0)) + .padding(32) + .frame(width: 450, height: 350) + } +} +``` \ No newline at end of file