[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n/.build\n/Packages\n/*.xcodeproj\nxcuserdata/\nDerivedData/\n.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata\n"
  },
  {
    "path": "Example/BottomSheetExample/Apple Applications/StocksExample.swift",
    "content": "//\n//  Stocks.swift\n//  BottomSheetExample\n//\n//  Created by Wouter van de Kamp on 04/12/2022.\n//\n\nimport SwiftUI\nimport BottomSheet\n\nstruct StocksExample: View {\n    @EnvironmentObject var settings: SheetSettings\n\n    var body: some View {\n        VStack {\n            Button(\"Close\") {\n                settings.isPresented.toggle()\n            }\n\n            Button(\"Change\") {\n                settings.selectedDetent = .large\n            }\n\n            Color.clear\n                .navigationBarTitleDisplayMode(.inline)\n                .navigationTitle(\"\\(settings.translation.rounded())\")\n                .onAppear {\n                    settings.isPresented = true\n                    settings.activeSheetType = .stocks\n                }\n        }\n    }\n}\n\nstruct StocksHeader: View {\n    var body: some View {\n        VStack {\n            HStack {\n                VStack(alignment: .leading, spacing: 2) {\n                    Text(\"Business News\")\n                        .font(.title)\n                        .fontWeight(.heavy)\n                    Text(\"From Yahoo Finance\")\n                        .foregroundColor(Color(UIColor.secondaryLabel))\n                }\n                .padding(.top, 10)\n                .padding(.bottom, 16)\n\n                Spacer()\n            }\n\n            Divider()\n             .frame(height: 1)\n             .background(Color(UIColor.systemGray6))\n        }\n        .padding(.top, 8)\n        .padding(.horizontal, 16)\n    }\n}\n\nstruct StocksMainContent: View {\n    var body: some View {\n        VStack(spacing: 0) {\n            ScrollView {\n                ForEach(0..<5, id: \\.self) { _ in\n                    newsRow\n                }\n            }\n            Spacer(minLength: 72)\n        }\n    }\n\n    var newsRow: some View {\n        VStack {\n            HStack {\n                VStack(alignment: .leading, spacing: 4) {\n                    Text(\"FX Empire\")\n                        .font(.caption)\n                        .foregroundColor(Color(UIColor.secondaryLabel))\n\n                    Text(\"Bitcoin (BTC) treads water after brief visit to sub-$39,000\")\n                        .font(.headline)\n                        .foregroundColor(Color(UIColor.label))\n\n                    Text(\"While Bitcoin (BTC) struggled on Saturday, XRP\")\n                        .foregroundColor(Color(UIColor.secondaryLabel))\n                        .lineLimit(1)\n                }\n                .padding(.vertical, 16)\n\n                Spacer()\n            }\n\n            HStack {\n                Text(\"13h ago\")\n                    .font(.caption)\n                    .fontWeight(.medium)\n                    .foregroundColor(Color(UIColor.secondaryLabel))\n\n                Spacer()\n            }\n        }\n        .padding(.horizontal, 16)\n    }\n}\n\nstruct StocksExample_Previews: PreviewProvider {\n    static var previews: some View {\n        StocksExample()\n    }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/Assets.xcassets/AccentColor.colorset/Contents.json",
    "content": "{\n  \"colors\" : [\n    {\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"60x60\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"60x60\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"76x76\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"76x76\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"83.5x83.5\"\n    },\n    {\n      \"idiom\" : \"ios-marketing\",\n      \"scale\" : \"1x\",\n      \"size\" : \"1024x1024\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/BottomSheetExampleApp.swift",
    "content": "//\n//  BottomSheetExampleApp.swift\n//  BottomSheetExample\n//\n//  Created by Wouter van de Kamp on 10/03/2022.\n//\n\nimport SwiftUI\n\n@main\nstruct BottomSheetExampleApp: App {\n    var body: some Scene {\n        WindowGroup {\n            ExampleOverview()\n        }\n    }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/ExampleOverview.swift",
    "content": "//\n//  ExampleOverview.swift\n//  BottomSheetExample\n//\n//  Created by Wouter van de Kamp on 24/05/2022.\n//\n\nimport SwiftUI\nimport BottomSheet\n\nenum SheetExampleTypes {\n    case home\n    case stocks\n    case staticScrollView\n}\n\nclass SheetSettings: ObservableObject {\n    @Published var isPresented = false\n    @Published var activeSheetType: SheetExampleTypes = .home\n    @Published var selectedDetent: BottomSheet.PresentationDetent = .medium\n    @Published var translation: CGFloat = BottomSheet.PresentationDetent.large.size\n}\n\nstruct ExampleOverview: View {\n    @StateObject var settings = SheetSettings()\n\n    var views: [(label: String, view: AnyView)] = [\n        (label: \"Stocks example\", view: AnyView(StocksExample())),\n        (label: \"Static scrollview example\", view: AnyView(StaticScrollViewExample()))\n    ]\n\n    @ViewBuilder\n    var headerContent: some View {\n        switch settings.activeSheetType {\n        case .stocks:\n            StocksHeader()\n        case .staticScrollView:\n            StaticScrollViewHeader()\n        default:\n            EmptyView()\n        }\n    }\n\n    @ViewBuilder\n    var mainContent: some View {\n        switch settings.activeSheetType {\n        case .stocks:\n            StocksMainContent()\n                .presentationDetentsPlus(\n                    [.height(244), .medium, .large],\n                    selection: $settings.selectedDetent\n                )\n        case .staticScrollView:\n            StaticScrollViewContent()\n                .presentationDetentsPlus(\n                    [.height(244), .height(380), .height(480), .large],\n                    selection: $settings.selectedDetent\n                )\n                .presentationDragIndicatorPlus(.visible)\n                .presentationBackgroundInteractionPlus(.enabled(upThrough: .height(380)))\n        default:\n            EmptyView()\n        }\n    }\n\n    var body: some View {\n        ZStack {\n            NavigationView {\n                List(views.indices, id: \\.self) { index in\n                    NavigationLink(destination: views[index].view) {\n                        Text(views[index].label)\n                    }\n                }\n                .background(Color(UIColor.systemGroupedBackground))\n                .listStyle(.grouped)\n                .navigationTitle(\"Examples\")\n                .onAppear {\n                    settings.isPresented = false\n                    settings.activeSheetType = .home\n                    settings.selectedDetent = .medium\n                }\n            }\n            .navigationViewStyle(.stack)\n        }\n        .environmentObject(settings)\n        .sheetPlus(\n            isPresented: $settings.isPresented,\n            background: (\n                Color(UIColor.secondarySystemBackground)\n                    .cornerRadius(12, corners: [.topLeft, .topRight])\n            ),\n            onDrag: { translation in\n                settings.translation = translation\n            },\n            header: { headerContent },\n            main: {\n                mainContent\n            }\n        )\n        .overlay(\n            VStack(spacing: 0) {\n                Divider()\n                    .frame(height: 1)\n                    .background(Color(UIColor.systemGray6))\n\n                HStack {\n                    Text(\"Yahoo Finance\")\n                    Spacer()\n                }\n                .padding(.horizontal, 16)\n                .padding(.vertical, 16)\n            }\n            .background(\n                Color(UIColor.secondarySystemBackground)\n                    .edgesIgnoringSafeArea([.bottom])\n            )\n            .opacity(\n                settings.activeSheetType == .stocks ? 1 : 0\n            )\n            ,\n            alignment: .bottom\n        )\n    }\n}\n\nstruct ExampleOverview_Previews: PreviewProvider {\n    static var previews: some View {\n        ExampleOverview()\n    }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/Examples/StaticScrollViewExample.swift",
    "content": "//\n//  StaticScrollViewExample.swift\n//  BottomSheetExample\n//\n//  Created by Wouter van de Kamp on 28/10/2023.\n//\n\nimport SwiftUI\n\nstruct StaticScrollViewExample: View {\n    @EnvironmentObject var settings: SheetSettings\n\n    var body: some View {\n        VStack {\n            Button(\"Close\") {\n                settings.isPresented.toggle()\n            }\n\n            Button(\"Change\") {\n                settings.selectedDetent = .large\n            }\n\n            Color.clear\n                .navigationBarTitleDisplayMode(.inline)\n                .navigationTitle(\"\\(settings.translation.rounded())\")\n                .onAppear {\n                    settings.isPresented = true\n                    settings.activeSheetType = .staticScrollView\n                }\n        }\n    }\n}\n\nstruct StaticScrollViewHeader: View {\n    @State private var searchterm = \"\"\n\n    var body: some View {\n        VStack {\n            TextField(\"Search item\", text: $searchterm)\n        }\n    }\n}\n\nstruct StaticScrollViewContent: View {\n    var body: some View {\n        ScrollView {\n            ForEach(0..<5, id: \\.self) { idx in\n                Text(\"Item \\(idx)\")\n            }\n        }\n    }\n}\n\nstruct StaticScrollViewExample_Previews: PreviewProvider {\n    static var previews: some View {\n        StaticScrollViewExample()\n    }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/Preview Content/Preview Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample/View Modifiers/CornerRadius.swift",
    "content": "//\n//  CornerRadius.swift\n//  BottomSheetExample\n//\n//  Created by Wouter van de Kamp on 25/03/2022.\n//\n\nimport SwiftUI\n\nstruct CornerRadiusStyle: ViewModifier {\n    var radius: CGFloat\n    var corners: UIRectCorner\n\n    struct CornerRadiusShape: Shape {\n        var radius = CGFloat.infinity\n        var corners = UIRectCorner.allCorners\n\n        func path(in rect: CGRect) -> Path {\n            let path = UIBezierPath(\n                roundedRect: rect,\n                byRoundingCorners: corners,\n                cornerRadii: CGSize(width: radius, height: radius)\n            )\n            return Path(path.cgPath)\n        }\n    }\n\n    func body(content: Content) -> some View {\n        content\n            .clipShape(CornerRadiusShape(radius: radius, corners: corners))\n    }\n}\n\nextension View {\n    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {\n        ModifiedContent(content: self, modifier: CornerRadiusStyle(radius: radius, corners: corners))\n    }\n}\n"
  },
  {
    "path": "Example/BottomSheetExample.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 55;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t6C0BD46D27DA862D000AF3CD /* BottomSheetExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0BD46C27DA862D000AF3CD /* BottomSheetExampleApp.swift */; };\n\t\t6C0BD47127DA862D000AF3CD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C0BD47027DA862D000AF3CD /* Assets.xcassets */; };\n\t\t6C0BD47427DA862D000AF3CD /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C0BD47327DA862D000AF3CD /* Preview Assets.xcassets */; };\n\t\t6C6EB0B6292AEADC00106A1D /* BottomSheet in Frameworks */ = {isa = PBXBuildFile; productRef = 6C6EB0B5292AEADC00106A1D /* BottomSheet */; };\n\t\t6C763147283D774500463709 /* ExampleOverview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C763146283D774500463709 /* ExampleOverview.swift */; };\n\t\t6C8CBF1D2AED12E00007E10E /* StaticScrollViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8CBF1C2AED12E00007E10E /* StaticScrollViewExample.swift */; };\n\t\t6CDF5A0D27ED33C7004609F4 /* CornerRadius.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF5A0C27ED33C7004609F4 /* CornerRadius.swift */; };\n\t\t6CF78515293D36FB000E6581 /* StocksExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CF78514293D36FB000E6581 /* StocksExample.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t6C0BD46927DA862D000AF3CD /* BottomSheetExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BottomSheetExample.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t6C0BD46C27DA862D000AF3CD /* BottomSheetExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetExampleApp.swift; sourceTree = \"<group>\"; };\n\t\t6C0BD47027DA862D000AF3CD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t6C0BD47327DA862D000AF3CD /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = \"Preview Assets.xcassets\"; sourceTree = \"<group>\"; };\n\t\t6C1DE0102889CF10003C6EE9 /* BottomSheet */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BottomSheet; path = ..; sourceTree = \"<group>\"; };\n\t\t6C763146283D774500463709 /* ExampleOverview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleOverview.swift; sourceTree = \"<group>\"; };\n\t\t6C8CBF1C2AED12E00007E10E /* StaticScrollViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticScrollViewExample.swift; sourceTree = \"<group>\"; };\n\t\t6CDF5A0C27ED33C7004609F4 /* CornerRadius.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerRadius.swift; sourceTree = \"<group>\"; };\n\t\t6CF78514293D36FB000E6581 /* StocksExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StocksExample.swift; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t6C0BD46627DA862D000AF3CD /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C6EB0B6292AEADC00106A1D /* BottomSheet in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t6C0BD46027DA862C000AF3CD = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C1DE0102889CF10003C6EE9 /* BottomSheet */,\n\t\t\t\t6C0BD46B27DA862D000AF3CD /* BottomSheetExample */,\n\t\t\t\t6C0BD46A27DA862D000AF3CD /* Products */,\n\t\t\t\t6C0BD47A27DA87A1000AF3CD /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0BD46A27DA862D000AF3CD /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0BD46927DA862D000AF3CD /* BottomSheetExample.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0BD46B27DA862D000AF3CD /* BottomSheetExample */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0BD46C27DA862D000AF3CD /* BottomSheetExampleApp.swift */,\n\t\t\t\t6C763146283D774500463709 /* ExampleOverview.swift */,\n\t\t\t\t6CF78516293D3703000E6581 /* Apple Applications */,\n\t\t\t\t6C8CBF1B2AED12C60007E10E /* Examples */,\n\t\t\t\t6CDF5A0E27ED33D3004609F4 /* View Modifiers */,\n\t\t\t\t6C0BD47027DA862D000AF3CD /* Assets.xcassets */,\n\t\t\t\t6C0BD47227DA862D000AF3CD /* Preview Content */,\n\t\t\t);\n\t\t\tpath = BottomSheetExample;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0BD47227DA862D000AF3CD /* Preview Content */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0BD47327DA862D000AF3CD /* Preview Assets.xcassets */,\n\t\t\t);\n\t\t\tpath = \"Preview Content\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0BD47A27DA87A1000AF3CD /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C8CBF1B2AED12C60007E10E /* Examples */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C8CBF1C2AED12E00007E10E /* StaticScrollViewExample.swift */,\n\t\t\t);\n\t\t\tpath = Examples;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6CDF5A0E27ED33D3004609F4 /* View Modifiers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6CDF5A0C27ED33C7004609F4 /* CornerRadius.swift */,\n\t\t\t);\n\t\t\tpath = \"View Modifiers\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6CF78516293D3703000E6581 /* Apple Applications */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6CF78514293D36FB000E6581 /* StocksExample.swift */,\n\t\t\t);\n\t\t\tpath = \"Apple Applications\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t6C0BD46827DA862D000AF3CD /* BottomSheetExample */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 6C0BD47727DA862D000AF3CD /* Build configuration list for PBXNativeTarget \"BottomSheetExample\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t6C0BD46527DA862D000AF3CD /* Sources */,\n\t\t\t\t6C0BD46627DA862D000AF3CD /* Frameworks */,\n\t\t\t\t6C939DBE294DFF9200F6EF50 /* Swiftlint */,\n\t\t\t\t6C0BD46727DA862D000AF3CD /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = BottomSheetExample;\n\t\t\tpackageProductDependencies = (\n\t\t\t\t6C6EB0B5292AEADC00106A1D /* BottomSheet */,\n\t\t\t);\n\t\t\tproductName = BottomSheetExample;\n\t\t\tproductReference = 6C0BD46927DA862D000AF3CD /* BottomSheetExample.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t6C0BD46127DA862C000AF3CD /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = 1;\n\t\t\t\tLastSwiftUpdateCheck = 1320;\n\t\t\t\tLastUpgradeCheck = 1320;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t6C0BD46827DA862D000AF3CD = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 13.2.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 6C0BD46427DA862C000AF3CD /* Build configuration list for PBXProject \"BottomSheetExample\" */;\n\t\t\tcompatibilityVersion = \"Xcode 13.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 6C0BD46027DA862C000AF3CD;\n\t\t\tpackageReferences = (\n\t\t\t);\n\t\t\tproductRefGroup = 6C0BD46A27DA862D000AF3CD /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t6C0BD46827DA862D000AF3CD /* BottomSheetExample */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t6C0BD46727DA862D000AF3CD /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C0BD47427DA862D000AF3CD /* Preview Assets.xcassets in Resources */,\n\t\t\t\t6C0BD47127DA862D000AF3CD /* Assets.xcassets in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t6C939DBE294DFF9200F6EF50 /* Swiftlint */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = Swiftlint;\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"export PATH=\\\"$PATH:/opt/homebrew/bin\\\"\\nif which swiftlint > /dev/null; then\\n  swiftlint\\nelse\\n  echo \\\"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\\\"\\nfi\\n\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t6C0BD46527DA862D000AF3CD /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C0BD46D27DA862D000AF3CD /* BottomSheetExampleApp.swift in Sources */,\n\t\t\t\t6C8CBF1D2AED12E00007E10E /* StaticScrollViewExample.swift in Sources */,\n\t\t\t\t6CDF5A0D27ED33C7004609F4 /* CornerRadius.swift in Sources */,\n\t\t\t\t6C763147283D774500463709 /* ExampleOverview.swift in Sources */,\n\t\t\t\t6CF78515293D36FB000E6581 /* StocksExample.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t6C0BD47527DA862D000AF3CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t6C0BD47627DA862D000AF3CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t6C0BD47827DA862D000AF3CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_ASSET_PATHS = \"BottomSheetExample/Preview\\\\ Content\";\n\t\t\t\tDEVELOPMENT_TEAM = KZAMEFAGHT;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchScreen_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 16.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.chargetrip.BottomSheetExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t6C0BD47927DA862D000AF3CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_ASSET_PATHS = \"BottomSheetExample/Preview\\\\ Content\";\n\t\t\t\tDEVELOPMENT_TEAM = KZAMEFAGHT;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchScreen_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 16.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.chargetrip.BottomSheetExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t6C0BD46427DA862C000AF3CD /* Build configuration list for PBXProject \"BottomSheetExample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t6C0BD47527DA862D000AF3CD /* Debug */,\n\t\t\t\t6C0BD47627DA862D000AF3CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t6C0BD47727DA862D000AF3CD /* Build configuration list for PBXNativeTarget \"BottomSheetExample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t6C0BD47827DA862D000AF3CD /* Debug */,\n\t\t\t\t6C0BD47927DA862D000AF3CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\n/* Begin XCSwiftPackageProductDependency section */\n\t\t6C6EB0B5292AEADC00106A1D /* BottomSheet */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tproductName = BottomSheet;\n\t\t};\n/* End XCSwiftPackageProductDependency section */\n\t};\n\trootObject = 6C0BD46127DA862C000AF3CD /* Project object */;\n}\n"
  },
  {
    "path": "Example/BottomSheetExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Example/BottomSheetExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Example/BottomSheetExample.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>PreviewsEnabled</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Example/BottomSheetExample.xcodeproj/xcshareddata/xcschemes/BottomSheetExample.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1410\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"6C0BD46827DA862D000AF3CD\"\n               BuildableName = \"BottomSheetExample.app\"\n               BlueprintName = \"BottomSheetExample\"\n               ReferencedContainer = \"container:BottomSheetExample.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"6C0BD46827DA862D000AF3CD\"\n            BuildableName = \"BottomSheetExample.app\"\n            BlueprintName = \"BottomSheetExample\"\n            ReferencedContainer = \"container:BottomSheetExample.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"6C0BD46827DA862D000AF3CD\"\n            BuildableName = \"BottomSheetExample.app\"\n            BlueprintName = \"BottomSheetExample\"\n            ReferencedContainer = \"container:BottomSheetExample.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 Wouter van de Kamp.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:5.5\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"BottomSheet\",\n    platforms: [\n        .iOS(.v14)\n    ],\n    products: [\n        // Products define the executables and libraries a package produces, and make them visible to other packages.\n        .library(\n            name: \"BottomSheet\",\n            targets: [\"BottomSheet\"]),\n    ],\n    dependencies: [\n        // Dependencies declare other packages that this package depends on.\n        // .package(url: /* package url */, from: \"1.0.0\"),\n    ],\n    targets: [\n        // Targets are the basic building blocks of a package. A target can define a module or a test suite.\n        // Targets can depend on other targets in this package, and on products in packages this package depends on.\n        .target(\n            name: \"BottomSheet\",\n            dependencies: []),\n        .testTarget(\n            name: \"BottomSheetTests\",\n            dependencies: [\"BottomSheet\"]),\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "# BottomSheet\n\nAn iOS library for SwiftUI to create draggable sheet experiences similar to iOS applications like Maps and Stocks. \n\n## Feature overview \n\nThe library currently supports;\n\n- [x] Unlimited snap positions\n- [x] Realtime position callback\n- [x] Absolute and relative positioning\n- [x] Customizable animation parameters\n- [x] An optional sticky header\n- [x] Views with and without a scrollview\n\n## How to install\n\nCurrently BottomSheet is only available through the [Swift Package Manager](https://swift.org/package-manager/) or manual install. \n\n1. Installation through Swift Package Manager can be done by going to `File > Add Packages`. Then enter the following URL in the searchbar; `https://github.com/Wouter125/BottomSheet`.\n\n2. Manual installation can be done by cloning this repository and dragging all assets into your Xcode Project.\n\n## How to use\n\n1. Import BottomSheet\n\n2. Create a state property that contains the presentation state of the bottom sheet and one for the current selection;\n\n```\n@Published var isPresented = false\n@Published var selectedDetent: BottomSheet.PresentationDetent = .medium\n```\n\n4. Add the `BottomSheetView` to your SwiftUI view hierachy by using a view modifier;\n\n```\n.sheetPlus(\n    isPresented: $isPresented,\n    header: { },\n    main: { \n        EmptyView()\n            .presentationDetentsPlus(\n                [.height(244), .fraction(0.4), .medium, .large],\n                selection: $selectedDetent\n            )\n    }\n)\n```\n\n5. Optionally receive the current panel position with a callback, change the background color, show a drag indicator or limit the background interaction based on the height;\n```\n.sheetPlus(\n    isPresented: $isPresented,\n    background: (\n        Color(UIColor.secondarySystemBackground)\n    ),\n    onDrag: { translation in\n        print(translation)\n    },\n    header: { EmptyView() },\n    main: {\n        EmptyView()\n            .presentationDetentsPlus(\n                [.height(244), .fraction(0.4), .medium, .large],\n                selection: $selectedDetent\n            )\n            .presentationDragIndicatorPlus(.visible)\n            .presentationBackgroundInteractionPlus(.enabled(upThrough: .height(380)))\n    }\n)\n```\n\n## Interface\n\n| Modifier                 | Type                | Default | Description                                                                       |\n|--------------------------|---------------------|---------|-----------------------------------------------------------------------------------|\n| animationCurve.mass      | Double              | 1.2     | The mass of the object attached to the spring.                                    |\n| animationCurve.stiffness | Double              | 200     | The stiffness of the spring.                                                      |\n| animationCurve.damping   | Double              | 25      | The spring damping value.                                                         |\n\n## Example\n\nTo give you an idea of how to use this library you can use the example that is attached to this repo. Simply clone it and open the `BottomSheetExample` folder in Xcode.\n\n## Roadmap\n\n1. Add landscape support\n2. Add iPad support\n"
  },
  {
    "path": "Sources/BottomSheet/Animation/Animation.swift",
    "content": "//\n//  Animation.swift\n//  \n//\n//  Created by Wouter van de Kamp on 26/11/2022.\n//\n\nimport Foundation\n\npublic struct SheetAnimation {\n    var mass: Double\n    var stiffness: Double\n    var damping: Double\n    \n    public init(mass: Double, stiffness: Double, damping: Double) {\n        self.mass = mass\n        self.stiffness = stiffness\n        self.damping = damping\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Animation/AnimationDefaults.swift",
    "content": "//\n//  AnimationDefaults.swift\n//  \n//\n//  Created by Wouter van de Kamp on 26/11/2022.\n//\n\nimport Foundation\n\npublic struct SheetAnimationDefaults {\n    public static let mass: Double =  1.2\n    public static let stiffness: Double = 200\n    public static let damping: Double = 25\n}\n"
  },
  {
    "path": "Sources/BottomSheet/BottomSheet.swift",
    "content": "//\n//  BottomSheet.swift\n//\n//\n//  Created by Wouter van de Kamp on 26/11/2022.\n//\n\nimport SwiftUI\n\nstruct SheetPlus<HContent: View, MContent: View, Background: View>: ViewModifier, KeyboardReader {\n    @Binding private var isPresented: Bool\n    \n    @State private var translation: CGFloat = 0\n    @State private var sheetConfig: SheetPlusConfig?\n    @State private var showDragIndicator: VisibilityPlus?\n    @State private var allowBackgroundInteraction: PresentationBackgroundInteractionPlus?\n    \n    @State private var newValue = 0.0\n    @State private var startTime: DragGesture.Value?\n    \n    @State private var detents: Set<PresentationDetent> = []\n    @State private var limits: (min: CGFloat, max: CGFloat) = (min: 0, max: 0)\n    \n    let mainContent: MContent\n    let headerContent: HContent\n    let animationCurve: SheetAnimation\n    let onDismiss: () -> Void\n    let onDrag: (CGFloat) -> Void\n    let background: Background\n    \n    init(\n        isPresented: Binding<Bool>,\n        animationCurve: SheetAnimation,\n        background: Background,\n        onDismiss: @escaping () -> Void,\n        onDrag: @escaping (CGFloat) -> Void,\n        @ViewBuilder hcontent: () -> HContent,\n        @ViewBuilder mcontent: () -> MContent\n    ) {\n        self._isPresented = isPresented\n        \n        self.animationCurve = animationCurve\n        self.background = background\n        self.onDismiss = onDismiss\n        self.onDrag = onDrag\n        \n        self.headerContent = hcontent()\n        self.mainContent = mcontent()\n    }\n    \n    func body(content: Content) -> some View {\n        ZStack() {\n            content\n                .allowsHitTesting(allowBackgroundInteraction == .disabled ? false : true)\n                \n            if isPresented {\n                GeometryReader { geometry in\n                    VStack(spacing: 0) {\n                        // If / else statement here breaks the animation from the bottom level\n                        // Might want to see if we can refactor the top level animation a bit\n                        DragIndicator(\n                            translation: $translation,\n                            detents: detents\n                        )\n                            .frame(height: showDragIndicator == .visible ? 22 : 0)\n                            .opacity(showDragIndicator == .visible ? 1 : 0)\n\n                        headerContent\n                            .contentShape(Rectangle())\n                            .gesture(\n                                DragGesture(coordinateSpace: .global)\n                                    .onChanged { value in\n                                        translation -= value.location.y - value.startLocation.y - newValue\n                                        newValue = value.location.y - value.startLocation.y\n                                        \n                                        if startTime == nil {\n                                            startTime = value\n                                        }\n                                    }\n                                    .onEnded { value in\n                                        // Reset the distance on release so we start with a\n                                        // clean translation next time\n                                        newValue = 0\n                                        \n                                        // Calculate velocity based on pt/s so it matches the UIPanGesture\n                                        let distance: CGFloat = value.translation.height\n                                        let time: CGFloat = value.time.timeIntervalSince(startTime!.time)\n                                        \n                                        let yVelocity: CGFloat = -1 * ((distance / time) / 1000)\n                                        startTime = nil\n                                        \n                                        if let result = snapBottomSheet(translation, detents, yVelocity) {\n                                            translation = result.size\n                                            sheetConfig?.selectedDetent = result\n                                        }\n                                    }\n                            )\n                        \n                        UIScrollViewWrapper(\n                            translation: $translation,\n                            preferenceKey: $sheetConfig,\n                            limits: limits,\n                            detents: detents\n                        ) {\n                            mainContent\n                                .frame(width: geometry.size.width)\n                        }\n                    }\n                    .background(background)\n                    .frame(height:\n                            (limits.max - geometry.safeAreaInsets.top) > 0\n                                ? limits.max - geometry.safeAreaInsets.top\n                                : limits.max\n                    )\n                    .onChange(of: translation) { newValue in\n                        // Small little hack to make the iOS scroll behaviour work smoothly\n                        if limits.max == 0 { return }\n                        translation = min(limits.max, max(newValue, limits.min))\n\n                        currentGlobalTranslation = translation\n                    }\n                    .onAnimationChange(of: translation) { value in\n                        onDrag(value)\n                    }\n                    .offset(y: UIScreen.main.bounds.height - translation)\n                    .onDisappear {\n                        translation = 0\n                        detents = []\n                        \n                        onDismiss()\n                    }\n                    .animation(\n                        .interpolatingSpring(\n                            mass: animationCurve.mass,\n                            stiffness: animationCurve.stiffness,\n                            damping: animationCurve.damping\n                        )\n                    )\n                }\n                .edgesIgnoringSafeArea([.bottom])\n                .transition(.move(edge: .bottom))\n            }\n        }\n        .onPreferenceChange(SheetPlusKey.self) { value in\n            /// Quick hack to prevent the scrollview from resetting the height when keyboard shows up.\n            /// Replace if the root cause has been located.\n            if value.detents.count == 0 { return }\n                                                \n            sheetConfig = value\n            translation = value.translation\n\n            detents = value.detents\n            limits = detentLimits(detents: detents)\n        }\n        .onPreferenceChange(SheetPlusIndicatorKey.self) { value in\n            showDragIndicator = value\n        }\n        .onPreferenceChange(SheetPlusBackgroundInteractionKey.self) { value in\n            allowBackgroundInteraction = value\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Detents/DetentDefaults.swift",
    "content": "//\n//  DetentsDefaults.swift\n//  \n//\n//  Created by Wouter van de Kamp on 20/11/2022.\n//\n\nimport SwiftUI\n\ninternal struct PresentationDetentDefaults {\n    static let small: CGFloat = UIScreen.main.bounds.height * 0.2\n    static let medium: CGFloat = UIScreen.main.bounds.height * 0.5\n    static let large: CGFloat = UIScreen.main.bounds.height * 0.9\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Detents/DetentHelpers.swift",
    "content": "//\n//  DetentsHelper.swift\n//  \n//\n//  Created by Wouter van de Kamp on 20/11/2022.\n//\n\nimport SwiftUI\n\n/// Computes the limits of how far the sheet can move.\n/// - Parameter detents: The list of detents provided when initializing the bottomsheet\n/// - Returns: Tuple with top and bottom. Top reflects the offset from the top of the screen when the sheet is in it's largest form. Bottom reflects the offset from the top of the screen when the sheet is in it's smallest form.\ninternal func detentLimits(detents: Set<PresentationDetent>) -> (min: CGFloat, max: CGFloat) {\n    let detentLimits: [CGFloat] = detents\n        .map { detent in\n            switch detent {\n            case .small:\n                return PresentationDetentDefaults.small\n            case .medium:\n                return PresentationDetentDefaults.medium\n            case .large:\n                return PresentationDetentDefaults.large\n            case .fraction(let fraction):\n                return UIScreen.main.bounds.height * fraction\n            case .height(let height):\n                return height\n            }\n        }\n        .sorted(by: <)\n    \n    return (min: detentLimits.first ?? 0, max: detentLimits.last ?? 0)\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Detents/Detents.swift",
    "content": "//\n//  Detents.swift\n//  \n//\n//  Created by Wouter van de Kamp on 20/11/2022.\n//\n\nimport SwiftUI\n\npublic enum PresentationDetent: Hashable {\n    case small\n    case medium\n    case large\n    case fraction(CGFloat)\n    case height(CGFloat)\n\n    public var size: CGFloat {\n        switch self {\n        case .small:\n            return PresentationDetentDefaults.small\n        case .medium:\n            return PresentationDetentDefaults.medium\n        case .large:\n            return PresentationDetentDefaults.large\n        case .fraction(let fraction):\n            return min(\n                UIScreen.main.bounds.height * fraction,\n                UIScreen.main.bounds.height\n            )\n        case .height(let height):\n            return min(\n                height,\n                UIScreen.main.bounds.height\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Helpers/KeyboardReader.swift",
    "content": "//\n//  KeyboardReader.swift\n//  \n//\n//  Created by Wouter van de Kamp on 28/10/2023.\n//\n\nimport Combine\nimport UIKit\n\nprotocol KeyboardReader {\n    var keyboardPublisher: AnyPublisher<Bool, Never> { get }\n}\n\nextension KeyboardReader {\n    var keyboardPublisher: AnyPublisher<Bool, Never> {\n        Publishers.Merge(\n            NotificationCenter.default\n                .publisher(for: UIResponder.keyboardWillShowNotification)\n                .map { _ in true },\n\n            NotificationCenter.default\n                .publisher(for: UIResponder.keyboardWillHideNotification)\n                .map { _ in false }\n        )\n        .eraseToAnyPublisher()\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Helpers/Snapping.swift",
    "content": "//\n//  Snapping.swift\n//  \n//\n//  Created by Wouter van de Kamp on 20/11/2022.\n//\n\nimport Foundation\n\n/// Helper function that computes where the bottomsheet should snap to\n/// - Parameters:\n///   - translation: the current translated distance\n///   - detents: the detents the translation can snap to\n///   - yVelocity: the speed at which the drag gesture ended. Used to compute a snapping behaviour\n/// - Returns: The snapping position distance\ninternal func snapBottomSheet(_ translation: CGFloat, _ detents: Set<PresentationDetent>, _ yVelocity: CGFloat) -> PresentationDetent? {\n    let detents = detents.sorted(by: { $0.size < $1.size })\n    \n    let position: [PresentationDetent] = detents.enumerated().compactMap { idx, detent in\n        if idx < detents.index(before: detents.count) {\n            let detentBracket = (\n                lower: detents[idx],\n                middle: detents[idx].size + ((detents[idx + 1].size - detents[idx].size) / 2),\n                upper: detents[idx + 1]\n            )            \n            \n            if detentBracket.lower.size...detentBracket.upper.size ~= translation {\n                if abs(yVelocity) > 1.8 {\n                    return yVelocity > 0 ? detentBracket.upper : detentBracket.lower\n                } else {\n                    return translation > detentBracket.middle\n                    ? detentBracket.upper\n                    : detentBracket.lower\n                }\n            }\n        }\n        \n        return nil\n    }\n    \n    return position.first\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Preference Keys/BackgroundInteractionKey.swift",
    "content": "//\n//  BackgroundInteractionKey.swift\n//  \n//\n//  Created by Wouter van de Kamp on 29/10/2023.\n//\n\nimport SwiftUI\n\n// Currently using a global var.\n// Might want to rework this by setting up the view modifiers a bit different.\n// Probably something that we can hold translation in 1 var. Now both need to be in sync.\nvar currentGlobalTranslation: CGFloat = 0\n\npublic enum PresentationBackgroundInteractionPlus {\n    case automatic\n    case disabled\n    case enabled\n\n    public static func enabled(upThrough detent: PresentationDetent) -> PresentationBackgroundInteractionPlus {\n        currentGlobalTranslation > detent.size ? .disabled : .enabled\n    }\n}\n\nstruct SheetPlusBackgroundInteractionKey: PreferenceKey {\n    static var defaultValue: PresentationBackgroundInteractionPlus = .automatic\n\n    static func reduce(value: inout PresentationBackgroundInteractionPlus, nextValue: () -> PresentationBackgroundInteractionPlus) {\n        value = nextValue()\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Preference Keys/ConfigKey.swift",
    "content": "//\n//  ConfigKey.swift\n//  \n//\n//  Created by Wouter van de Kamp on 20/11/2022.\n//\n\nimport SwiftUI\n\nstruct SheetPlusConfig: Equatable {\n    let detents: Set<PresentationDetent>\n    @Binding var selectedDetent: PresentationDetent\n    let translation: CGFloat\n    \n    \n    static func == (lhs: SheetPlusConfig, rhs: SheetPlusConfig) -> Bool {\n        return lhs.selectedDetent == rhs.selectedDetent && lhs.translation == rhs.translation && lhs.detents == rhs.detents\n    }\n}\n\nstruct SheetPlusKey: PreferenceKey {\n    static var defaultValue: SheetPlusConfig = SheetPlusConfig(detents: [], selectedDetent: .constant(.height(.zero)), translation: 0)\n    \n    static func reduce(value: inout SheetPlusConfig, nextValue: () -> SheetPlusConfig) {\n        /// This prevents the translation changes to be called whenever the keyboard is triggered.\n        /// If the keyboard gets triggered it will also reset the whole configkey and losing the binding.\n        /// https://stackoverflow.com/questions/67644164/preferencekey-issue-swiftui-sometimes-seems-to-generate-additional-views-that\n        value = nextValue() != defaultValue ? nextValue() : value\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Preference Keys/IndicatorKey.swift",
    "content": "//\n//  IndicatorKey.swift\n//  \n//\n//  Created by Wouter van de Kamp on 29/10/2023.\n//\n\nimport Foundation\nimport SwiftUI\n\nstruct SheetPlusIndicatorKey: PreferenceKey {\n    static var defaultValue: VisibilityPlus = .automatic\n\n    static func reduce(value: inout VisibilityPlus, nextValue: () -> VisibilityPlus) {\n        value = nextValue()\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/UIKit Views/UIScrollViewWrapper.swift",
    "content": "//\n//  UIScrollViewWrapper.swift\n//  \n//\n//  Created by Wouter van de Kamp on 20/11/2022.\n//\n\nimport Foundation\nimport SwiftUI\nimport UIKit\n\ninternal struct UIScrollViewWrapper<Content: View>: UIViewRepresentable {\n    @Binding var translation: CGFloat\n    @Binding var preferenceKey: SheetPlusConfig?\n    \n    let limits: (min: CGFloat, max: CGFloat)\n    let detents: Set<PresentationDetent>\n    \n    let content: () -> Content\n    \n    func makeUIView(context: Context) -> UIScrollView {\n        let scrollView = UIScrollView()\n        let hostingController = context.coordinator.hostingController\n        \n        scrollView.addSubview(hostingController.view)\n        \n        scrollView.contentInsetAdjustmentBehavior = .automatic\n        scrollView.alwaysBounceVertical = true\n        scrollView.delegate = context.coordinator\n        \n        hostingController.view.translatesAutoresizingMaskIntoConstraints = false\n        \n        scrollView.addConstraints([\n            hostingController.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),\n            hostingController.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),\n            hostingController.view.topAnchor.constraint(equalTo: scrollView.topAnchor),\n            hostingController.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor)\n        ])\n        \n        hostingController.view.backgroundColor = .clear\n        scrollView.backgroundColor = .clear\n\n        scrollView.layoutIfNeeded()\n        \n        return scrollView\n    }\n    \n    func updateUIView(_ scrollView: UIScrollView, context: Context) {\n        context.coordinator.limits = limits\n        context.coordinator.detents = detents\n        \n        context.coordinator.hostingController.rootView = self.content()\n    }\n    \n    func makeCoordinator() -> Coordinator {\n        return Coordinator(\n            representable: self,\n            hostingController: UIHostingController(rootView: content()),\n            limits: limits,\n            detents: detents\n        )\n    }\n    \n    class Coordinator: NSObject, UIScrollViewDelegate {\n        private var scrollOffset: CGFloat = 0\n        private var newValue: CGFloat = 0\n        \n        var representable: UIScrollViewWrapper\n        var hostingController: UIHostingController<Content>\n        \n        var limits: (min: CGFloat, max: CGFloat)\n        var detents: Set<PresentationDetent>\n        \n        init(\n            representable: UIScrollViewWrapper,\n            hostingController: UIHostingController<Content>,\n            limits: (min: CGFloat, max: CGFloat),\n            detents: Set<PresentationDetent>\n        ) {\n            self.hostingController = hostingController\n            self.limits = limits\n            self.detents = detents\n            self.representable = representable\n        }\n        \n        private func shouldDragSheet(_ scrollViewPosition: CGFloat, isFixedHeight: Bool) -> Bool {\n            // Translation on a scrollview without an overflow get's set to 0 somehow.\n            // Implemented this check to prevent it from snapping back to the original position.\n            // Need to dive deeper to figure out why it gets set to 0.\n            if isFixedHeight && representable.translation == 0 {\n                if scrollViewPosition > scrollOffset {\n                    scrollOffset = scrollViewPosition\n                }\n\n                return scrollViewPosition < 0\n            }\n\n            if representable.translation >= limits.max {\n                if scrollViewPosition > scrollOffset {\n                    scrollOffset = scrollViewPosition\n                }\n\n                return scrollViewPosition < 0\n            }\n\n            return true\n        }\n\n        func scrollViewDidScroll(_ scrollView: UIScrollView) {\n            let isFixedHeight = scrollView.contentSize.height < scrollView.frame.size.height\n\n            guard scrollView.isTracking else { return }\n            guard shouldDragSheet(scrollView.contentOffset.y, isFixedHeight: isFixedHeight) else {\n                scrollView.showsVerticalScrollIndicator = true\n                return\n            }\n            \n            let localTranslation = scrollView.panGestureRecognizer.translation(in: scrollView.superview).y - scrollOffset\n            let translationDelta = localTranslation - newValue\n\n            representable.translation -= translationDelta\n\n            newValue = localTranslation\n\n            scrollView.showsVerticalScrollIndicator = false\n            scrollView.contentOffset.y = .zero\n        }\n\n        func scrollViewWillEndDragging(\n            _ scrollView: UIScrollView,\n            withVelocity velocity: CGPoint,\n            targetContentOffset: UnsafeMutablePointer<CGPoint>\n        ) {\n            if representable.translation != limits.max {\n                targetContentOffset.pointee = .zero\n            }\n            \n            if let result = snapBottomSheet(\n                representable.translation,\n                detents,\n                scrollView.contentOffset.y > 0 ? 0 : velocity.y\n            ) {\n                representable.translation = result.size\n                representable.preferenceKey?.selectedDetent = result\n            }\n\n            scrollOffset = 0\n            newValue = 0\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/View Modifiers/View+AnimationChange.swift",
    "content": "//\n//  OnAnimationChange.swift\n//  \n//\n//  Created by Wouter van de Kamp on 10/03/2022.\n//\n\nimport SwiftUI\n\ninternal struct AnimationObserverModifier<Value>: AnimatableModifier where Value: VectorArithmetic {\n    var animatableData: Value {\n        didSet {\n            updateAnimationData()\n        }\n    }\n\n    private var update: (CGFloat) -> Void\n\n    init(observedValue: Value, update: @escaping (CGFloat) -> Void) {\n        self.animatableData = observedValue\n        self.update = update\n    }\n\n    func body(content: Content) -> some View {\n        return content\n    }\n\n    private func updateAnimationData() {\n        DispatchQueue.main.async {\n            // swiftlint:disable force_cast\n            update(animatableData as! CGFloat)\n        }\n   }\n}\n\nextension View {\n    func onAnimationChange<Value: VectorArithmetic>(\n        of value: Value,\n        perform: @escaping (CGFloat) -> Void\n    ) -> ModifiedContent<Self, AnimationObserverModifier<Value>> {\n        return modifier(AnimationObserverModifier(observedValue: value, update: perform))\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/View Modifiers/View+BackgroundInteraction.swift",
    "content": "//\n//  View+BackgroundInteraction.swift\n//  \n//\n//  Created by Wouter van de Kamp on 29/10/2023.\n//\n\nimport SwiftUI\n\nextension View {\n    public func presentationBackgroundInteractionPlus(\n        _ interaction: PresentationBackgroundInteractionPlus\n    ) -> some View {\n        return self.preference(\n            key: SheetPlusBackgroundInteractionKey.self,\n            value: interaction\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/View Modifiers/View+Detents.swift",
    "content": "//\n//  View+Detents.swift\n//  \n//\n//  Created by Wouter van de Kamp on 02/07/2023.\n//\n\nimport SwiftUI\n\nextension View {    \n    public func presentationDetentsPlus(\n        _ detents: Set<PresentationDetent>\n    ) -> some View {\n        let sortedDetents = Array(detents).sorted(by: { $0.size < $1.size })\n        \n        return self.preference(\n            key: SheetPlusKey.self,\n            value: SheetPlusConfig(\n                detents: detents,\n                selectedDetent: Binding(get: { sortedDetents.first! }, set: { _ in }),\n                translation: sortedDetents.first!.size\n            )\n        )\n    }\n    \n    public func presentationDetentsPlus(\n        _ detents: Set<PresentationDetent>,\n        selection: Binding<PresentationDetent>\n    ) -> some View {\n        return self.preference(\n            key: SheetPlusKey.self,\n            value: SheetPlusConfig(\n                detents: detents,\n                selectedDetent: selection,\n                translation: selection.wrappedValue.size\n            )\n        )\n    }\n}\n\n"
  },
  {
    "path": "Sources/BottomSheet/View Modifiers/View+DragIndicator.swift",
    "content": "//\n//  View+DragIndicator.swift\n//  \n//\n//  Created by Wouter van de Kamp on 29/10/2023.\n//\n\nimport SwiftUI\n\npublic enum VisibilityPlus {\n    case hidden\n    case visible\n    case automatic\n}\n\nextension View {\n    public func presentationDragIndicatorPlus(\n        _ visibility: VisibilityPlus\n    ) -> some View {\n        return self.preference(\n            key: SheetPlusIndicatorKey.self,\n            value: visibility\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/View Modifiers/View+SheetPlus.swift",
    "content": "//\n//  View+SheetPlus.swift\n//  \n//\n//  Created by Wouter van de Kamp on 21/11/2022.\n//\n\nimport SwiftUI\n\nextension View {\n    public func sheetPlus<HContent: View, MContent: View, Background: View>(\n        isPresented: Binding<Bool>,\n        animationCurve: SheetAnimation = SheetAnimation(\n            mass: SheetAnimationDefaults.mass,\n            stiffness: SheetAnimationDefaults.stiffness,\n            damping: SheetAnimationDefaults.damping\n        ),\n        background: Background = Color(UIColor.systemBackground),\n        onDismiss: @escaping () -> Void = {},\n        onDrag: @escaping (CGFloat) -> Void = { _ in },\n        header: () -> HContent = { EmptyView() },\n        main: () -> MContent\n    ) -> some View {\n        modifier(\n            SheetPlus(\n                isPresented: isPresented,\n                animationCurve: animationCurve,\n                background: background,\n                onDismiss: onDismiss,\n                onDrag: onDrag,\n                hcontent: header,\n                mcontent: main\n            )\n        )\n    }\n}\n"
  },
  {
    "path": "Sources/BottomSheet/Views/DragIndicator.swift",
    "content": "//\n//  DragIndicator.swift\n//  \n//\n//  Created by Wouter van de Kamp on 29/10/2023.\n//\n\nimport SwiftUI\n\nstruct DragIndicator: View {\n    @Binding var translation: CGFloat\n    var detents: Set<PresentationDetent>\n\n    var body: some View {\n        RoundedRectangle(cornerRadius: 3)\n            .contentShape(Rectangle())\n            .frame(width: 42, height: 6)\n            .foregroundColor(Color(UIColor.systemGray3))\n            .padding(.vertical, 8)\n            .onTapGesture {\n                let sortedDetents = detents.sorted { $0.size < $1.size }\n                let nextDetent = sortedDetents.first(where: { $0.size > translation })\n\n                if let nextDetent = nextDetent {\n                    translation = nextDetent.size\n                } else {\n                    translation = sortedDetents.first!.size\n                }\n            }\n    }\n}\n\nstruct DragIndicator_Previews: PreviewProvider {\n    static var previews: some View {\n        DragIndicator(\n            translation: .constant(0),\n            detents: []\n        )\n    }\n}\n"
  },
  {
    "path": "Tests/BottomSheetTests/BottomSheetTests.swift",
    "content": "import XCTest\n@testable import BottomSheet\n\nfinal class BottomSheetTests: XCTestCase {\n    func testExample() throws {\n        \n    }\n}\n"
  }
]