@swiftbrowser/swift 0.1.0 → 0.2.0
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.
- package/Package.swift +200 -9
- package/README.md +7 -9
- package/Sources/AVFoundation/AVFoundation.swift +131 -0
- package/Sources/AVFoundation/Asset.swift +487 -0
- package/Sources/AVFoundation/AudioSession.swift +144 -0
- package/Sources/AVFoundation/CMTime.swift +303 -0
- package/Sources/AVFoundation/Capture.swift +688 -0
- package/Sources/AVFoundation/Player.swift +749 -0
- package/Sources/AVFoundation/PlayerView.swift +117 -0
- package/Sources/AVKit/AVKit.swift +132 -0
- package/Sources/Accelerate/Accelerate.swift +122 -0
- package/Sources/AppIntents/AppIntents.swift +144 -0
- package/Sources/AppIntents/Parameters.swift +220 -0
- package/Sources/AppIntents/Shortcuts.swift +159 -0
- package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
- package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
- package/Sources/AuthenticationServices/Authorization.swift +251 -0
- package/Sources/Charts/Charts.swift +0 -4
- package/Sources/Combine/AnyCancellable.swift +65 -0
- package/Sources/Combine/AnyPublisher.swift +148 -0
- package/Sources/Combine/AnySubscriber.swift +230 -0
- package/Sources/Combine/Cancellable.swift +35 -0
- package/Sources/Combine/Codable.swift +29 -0
- package/Sources/Combine/CombineIdentifier.swift +45 -0
- package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
- package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
- package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
- package/Sources/Combine/CurrentValueSubject.swift +252 -0
- package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
- package/Sources/Combine/Future.swift +228 -0
- package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
- package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
- package/Sources/Combine/Helpers/ConduitList.swift +59 -0
- package/Sources/Combine/Helpers/DebugHook.swift +177 -0
- package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
- package/Sources/Combine/Helpers/Locking.swift +30 -0
- package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
- package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
- package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
- package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
- package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
- package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
- package/Sources/Combine/Helpers/Utils.swift +30 -0
- package/Sources/Combine/Helpers/Violations.swift +33 -0
- package/Sources/Combine/ImmediateScheduler.swift +178 -0
- package/Sources/Combine/LICENSE +21 -0
- package/Sources/Combine/NotificationPublisher.swift +48 -0
- package/Sources/Combine/ObjectWillChange.swift +46 -0
- package/Sources/Combine/PassthroughSubject.swift +222 -0
- package/Sources/Combine/Publisher+Subscribe.swift +53 -0
- package/Sources/Combine/Publishers/Deferred.swift +48 -0
- package/Sources/Combine/Publishers/Empty.swift +54 -0
- package/Sources/Combine/Publishers/Fail.swift +42 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
- package/Sources/Combine/Publishers/Just.swift +313 -0
- package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
- package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
- package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
- package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
- package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
- package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
- package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
- package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
- package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
- package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
- package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
- package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
- package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
- package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
- package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
- package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
- package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
- package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
- package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
- package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
- package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
- package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
- package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
- package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
- package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
- package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
- package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
- package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
- package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
- package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
- package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
- package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
- package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
- package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
- package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
- package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
- package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
- package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
- package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
- package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
- package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
- package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
- package/Sources/Combine/Publishers/Publishers.swift +13 -0
- package/Sources/Combine/Publishers/Record.swift +237 -0
- package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
- package/Sources/Combine/Result.swift +46 -0
- package/Sources/Combine/Scheduler.swift +89 -0
- package/Sources/Combine/Schedulers.swift +211 -0
- package/Sources/Combine/Subject+Void.swift +17 -0
- package/Sources/Combine/Subscriber+Void.swift +20 -0
- package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
- package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
- package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
- package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
- package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
- package/Sources/Combine/Subscription.swift +22 -0
- package/Sources/Combine/Subscriptions.swift +42 -0
- package/Sources/Combine/SwiftUIObservation.swift +10 -0
- package/Sources/Combine/_Introspection.swift +107 -0
- package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
- package/Sources/Compression/Compression.swift +365 -0
- package/Sources/Compression/Deflate.swift +407 -0
- package/Sources/Compression/Zlib.swift +179 -0
- package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
- package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
- package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
- package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
- package/Sources/CoreImage/CIColor.swift +41 -0
- package/Sources/CoreImage/CIContext.swift +31 -0
- package/Sources/CoreImage/CIDetector.swift +57 -0
- package/Sources/CoreImage/CIFilter.swift +243 -0
- package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
- package/Sources/CoreImage/CIImage.swift +162 -0
- package/Sources/CoreImage/QRCode.swift +393 -0
- package/Sources/CoreLocation/Coordinate.swift +30 -0
- package/Sources/CoreLocation/Location.swift +65 -0
- package/Sources/CoreML/Evaluation.swift +414 -0
- package/Sources/CoreML/FeatureValue.swift +266 -0
- package/Sources/CoreML/Model.swift +269 -0
- package/Sources/CoreML/MultiArray.swift +92 -0
- package/Sources/CoreML/Specification.swift +233 -0
- package/Sources/CoreText/CoreText.swift +64 -0
- package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
- package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
- package/Sources/CryptoKit/CryptoKit.swift +375 -0
- package/Sources/CryptoKit/Curve25519.swift +317 -0
- package/Sources/CryptoKit/P256.swift +321 -0
- package/Sources/FoundationBridge/AppStorage.swift +165 -0
- package/Sources/FoundationBridge/AssetResources.swift +90 -0
- package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
- package/Sources/FoundationBridge/AsyncImage.swift +116 -0
- package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/Bundle.swift +41 -4
- package/Sources/FoundationBridge/CombineExports.swift +8 -0
- package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
- package/Sources/FoundationBridge/Dispatch.swift +458 -0
- package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
- package/Sources/FoundationBridge/FileImporter.swift +128 -0
- package/Sources/FoundationBridge/FileSystem.swift +68 -0
- package/Sources/FoundationBridge/FoundationBridge.swift +24 -72
- package/Sources/FoundationBridge/HostResolution.swift +31 -0
- package/Sources/FoundationBridge/ItemProvider.swift +655 -0
- package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
- package/Sources/FoundationBridge/Links.swift +127 -0
- package/Sources/FoundationBridge/ListFormatter.swift +32 -0
- package/Sources/FoundationBridge/Localization.swift +149 -0
- package/Sources/FoundationBridge/Locks.swift +50 -0
- package/Sources/FoundationBridge/Markdown.swift +527 -0
- package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
- package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
- package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
- package/Sources/FoundationBridge/Operation.swift +195 -0
- package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
- package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
- package/Sources/FoundationBridge/SceneStorage.swift +78 -0
- package/Sources/FoundationBridge/SecurityExports.swift +8 -0
- package/Sources/FoundationBridge/Selector.swift +226 -0
- package/Sources/FoundationBridge/StringComparators.swift +17 -0
- package/Sources/FoundationBridge/Table.swift +211 -0
- package/Sources/FoundationBridge/TextAttributes.swift +42 -0
- package/Sources/FoundationBridge/Timer.swift +6 -1
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/UserDefaults.swift +17 -4
- package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
- package/Sources/FoundationBridge/WebSocket.swift +187 -0
- package/Sources/FoundationModels/FoundationModels.swift +1098 -0
- package/Sources/ImageIO/GIF.swift +72 -0
- package/Sources/ImageIO/ImageIO.swift +248 -0
- package/Sources/ImageIO/ImageTypes.swift +28 -0
- package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
- package/Sources/LocalAuthentication/LAContext.swift +86 -0
- package/Sources/MapKit/Geometry.swift +223 -0
- package/Sources/MapKit/Map.swift +638 -0
- package/Sources/MapKit/MapView.swift +229 -0
- package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
- package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
- package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
- package/Sources/OSLog/OSLog.swift +6 -0
- package/Sources/Photos/Photos.swift +572 -0
- package/Sources/PhotosUI/PhotosPicker.swift +248 -0
- package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
- package/Sources/QuickLook/QuickLook.swift +168 -0
- package/Sources/SafariServices/SafariServices.swift +106 -0
- package/Sources/Security/Security.swift +332 -0
- package/Sources/StoreKit/AppStore.swift +207 -0
- package/Sources/StoreKit/Products.swift +280 -0
- package/Sources/StoreKit/RequestReview.swift +28 -0
- package/Sources/StoreKit/StoreKit1.swift +486 -0
- package/Sources/StoreKit/StoreViews.swift +428 -0
- package/Sources/StoreKit/Transactions.swift +197 -0
- package/Sources/SwiftData/Macros.swift +58 -0
- package/Sources/SwiftData/ModelActor.swift +38 -0
- package/Sources/SwiftData/ModelContainer.swift +129 -0
- package/Sources/SwiftData/ModelContext.swift +451 -0
- package/Sources/SwiftData/PersistentModel.swift +238 -0
- package/Sources/SwiftData/Properties.swift +261 -0
- package/Sources/SwiftData/Query.swift +256 -0
- package/Sources/SwiftData/Schema.swift +192 -0
- package/Sources/SwiftData/Store.swift +146 -0
- package/Sources/SwiftData/StringPredicates.swift +125 -0
- package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
- package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
- package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
- package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
- package/Sources/SwiftDataMacros/Plugin.swift +18 -0
- package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
- package/Sources/SwiftUI/API/Accessibility.swift +55 -6
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +1 -1
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +37 -5
- package/Sources/SwiftUI/API/App.swift +31 -1
- package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
- package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
- package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
- package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
- package/Sources/SwiftUI/API/Canvas.swift +337 -0
- package/Sources/SwiftUI/API/Color.swift +104 -28
- package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
- package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
- package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
- package/Sources/SwiftUI/API/Commands.swift +106 -0
- package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
- package/Sources/SwiftUI/API/ContentShape.swift +33 -0
- package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
- package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
- package/Sources/SwiftUI/API/Controls.swift +59 -27
- package/Sources/SwiftUI/API/CustomLayout.swift +49 -10
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +1 -1
- package/Sources/SwiftUI/API/EditMode.swift +25 -82
- package/Sources/SwiftUI/API/Effects.swift +105 -7
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +93 -9
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +11 -3
- package/Sources/SwiftUI/API/Gauge.swift +3 -2
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +13 -2
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +1 -1
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +1 -1
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +13 -6
- package/Sources/SwiftUI/API/Layout.swift +67 -12
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +61 -6
- package/Sources/SwiftUI/API/Menu.swift +8 -1
- package/Sources/SwiftUI/API/Modifiers.swift +80 -10
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +24 -9
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +16 -2
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +48 -31
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +11 -2
- package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
- package/Sources/SwiftUI/API/Popover.swift +41 -0
- package/Sources/SwiftUI/API/Preferences.swift +262 -0
- package/Sources/SwiftUI/API/Presentation.swift +17 -4
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +164 -37
- package/Sources/SwiftUI/API/Publishers.swift +4 -4
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +3 -2
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +3 -3
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +105 -7
- package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
- package/Sources/SwiftUI/API/Sharing.swift +193 -0
- package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
- package/Sources/SwiftUI/API/State.swift +18 -1
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
- package/Sources/SwiftUI/API/TabContent.swift +841 -0
- package/Sources/SwiftUI/API/Table.swift +382 -0
- package/Sources/SwiftUI/API/Tabs.swift +148 -4
- package/Sources/SwiftUI/API/Tasks.swift +2 -2
- package/Sources/SwiftUI/API/Text.swift +386 -0
- package/Sources/SwiftUI/API/TextDates.swift +61 -0
- package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
- package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
- package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
- package/Sources/SwiftUI/API/Toolbar.swift +52 -16
- package/Sources/SwiftUI/API/Transfer.swift +145 -0
- package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
- package/Sources/SwiftUI/API/Video.swift +64 -0
- package/Sources/SwiftUI/API/View.swift +10 -2
- package/Sources/SwiftUI/API/ViewModifier.swift +4 -1
- package/Sources/SwiftUI/API/VisualEffect.swift +74 -1
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +7 -1
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +17 -3
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +2 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +37 -1
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +76 -4
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +58 -12
- package/Sources/SwiftUI/Runtime/Reconciler.swift +10 -1
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +977 -198
- package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
- package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
- package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
- package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
- package/Sources/Symbols/Symbols.swift +25 -0
- package/Sources/Translation/Translation.swift +423 -0
- package/Sources/UIKit/Activity.swift +213 -0
- package/Sources/UIKit/Alerts.swift +69 -0
- package/Sources/UIKit/AppDelegate.swift +222 -0
- package/Sources/UIKit/Appearance.swift +84 -0
- package/Sources/UIKit/ColorConversions.swift +70 -0
- package/Sources/UIKit/Controls.swift +225 -0
- package/Sources/UIKit/Device.swift +200 -0
- package/Sources/UIKit/Feedback.swift +65 -0
- package/Sources/UIKit/Font.swift +307 -0
- package/Sources/UIKit/Graphics.swift +204 -0
- package/Sources/UIKit/HostingController.swift +185 -0
- package/Sources/UIKit/Identity.swift +24 -0
- package/Sources/UIKit/Introspectable.swift +510 -0
- package/Sources/UIKit/Pasteboard.swift +363 -0
- package/Sources/UIKit/PhotoAlbum.swift +81 -0
- package/Sources/UIKit/RemoteNotifications.swift +15 -0
- package/Sources/UIKit/Representable.swift +288 -0
- package/Sources/UIKit/SafeArea.swift +12 -0
- package/Sources/UIKit/SceneDelegates.swift +132 -0
- package/Sources/UIKit/Scenes.swift +40 -0
- package/Sources/UIKit/ScrollView.swift +157 -0
- package/Sources/UIKit/ShortcutItems.swift +67 -0
- package/Sources/UIKit/SymbolConfiguration.swift +124 -0
- package/Sources/UIKit/TargetAction.swift +123 -0
- package/Sources/UIKit/TextPaste.swift +161 -0
- package/Sources/UIKit/TextView.swift +538 -0
- package/Sources/UIKit/UIKit.swift +292 -0
- package/Sources/UIKit/UIView.swift +855 -0
- package/Sources/UIKit/ViewTranslation.swift +311 -0
- package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
- package/Sources/UserNotifications/Content.swift +370 -0
- package/Sources/UserNotifications/NotificationCenter.swift +309 -0
- package/Sources/WeatherKit/WeatherKit.swift +228 -0
- package/Sources/WebKit/WebKit.swift +245 -0
- package/Sources/os/os.swift +376 -0
- package/Sources/zlib/zlib.swift +6 -0
- package/index.d.ts +1 -1
- package/index.mjs +2 -2
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +5 -3
- package/sync-sources.mjs +21 -7
- package/Sources/FoundationLite/Common.swift +0 -3
- package/Sources/FoundationLite/FoundationLite.swift +0 -171
- package/Sources/FoundationLite/Interaction.swift +0 -146
- package/Sources/FoundationLite/Timer.swift +0 -48
- package/Sources/_FoundationCommon/_FoundationCommon.swift +0 -10
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Scroll view modifiers from iOS 16-26 that Ice Cubes uses.
|
|
2
|
+
//
|
|
3
|
+
// - `.scrollDismissesKeyboard(.immediately | .interactively)`: the `list` or
|
|
4
|
+
// `scrollview` carries `"dismissesKeyboard": true`; when the viewer scrolls
|
|
5
|
+
// it, the page takes the focus away from the text field being edited
|
|
6
|
+
// (`.interactively` dismisses at the start of the scroll too: the page has
|
|
7
|
+
// no keyboard to drag down). `.automatic` and `.never` add nothing.
|
|
8
|
+
// - `.scrollIndicators(_:axes:)`: accepted; the page's scroll views never
|
|
9
|
+
// show scroll bars (iOS shows them only while scrolling).
|
|
10
|
+
// - `.scrollEdgeEffectStyle(_:for:)` (iOS 26): accepted; the page draws no
|
|
11
|
+
// edge blur under the bars.
|
|
12
|
+
// - `.safeAreaInset(edge:alignment:spacing:content:)`: approximated as a
|
|
13
|
+
// stack: the inset view takes its room above or below (before or after)
|
|
14
|
+
// the view, which gets the rest, instead of overlapping a scroll view's
|
|
15
|
+
// content that can scroll out from under it; a nil `spacing` is none.
|
|
16
|
+
|
|
17
|
+
public struct ScrollDismissesKeyboardMode: Hashable, Sendable {
|
|
18
|
+
let dismisses: Bool
|
|
19
|
+
public static let automatic = ScrollDismissesKeyboardMode(dismisses: false)
|
|
20
|
+
public static let immediately = ScrollDismissesKeyboardMode(dismisses: true)
|
|
21
|
+
public static let interactively = ScrollDismissesKeyboardMode(dismisses: true)
|
|
22
|
+
public static let never = ScrollDismissesKeyboardMode(dismisses: false)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public struct ScrollIndicatorVisibility: Hashable, Sendable {
|
|
26
|
+
let name: String
|
|
27
|
+
public static let automatic = ScrollIndicatorVisibility(name: "automatic")
|
|
28
|
+
public static let visible = ScrollIndicatorVisibility(name: "visible")
|
|
29
|
+
public static let hidden = ScrollIndicatorVisibility(name: "hidden")
|
|
30
|
+
public static let never = ScrollIndicatorVisibility(name: "never")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public struct ScrollEdgeEffectStyle: Hashable, Sendable {
|
|
34
|
+
let name: String
|
|
35
|
+
public static let automatic = ScrollEdgeEffectStyle(name: "automatic")
|
|
36
|
+
public static let hard = ScrollEdgeEffectStyle(name: "hard")
|
|
37
|
+
public static let soft = ScrollEdgeEffectStyle(name: "soft")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
enum _ScrollDismissesKeyboardKey: EnvironmentKey { static let defaultValue = false }
|
|
41
|
+
|
|
42
|
+
extension EnvironmentValues {
|
|
43
|
+
/// `.scrollDismissesKeyboard(.immediately | .interactively)` above a list or scroll view.
|
|
44
|
+
var _scrollDismissesKeyboard: Bool {
|
|
45
|
+
get { self[_ScrollDismissesKeyboardKey.self] }
|
|
46
|
+
set { self[_ScrollDismissesKeyboardKey.self] = newValue }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
nonisolated extension View {
|
|
51
|
+
public func scrollDismissesKeyboard(_ mode: ScrollDismissesKeyboardMode) -> some View {
|
|
52
|
+
environment(\._scrollDismissesKeyboard, mode.dismisses)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public func scrollIndicators(_ visibility: ScrollIndicatorVisibility, axes: Axis.Set = [.vertical, .horizontal]) -> some View {
|
|
56
|
+
self
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public func scrollEdgeEffectStyle(_ style: ScrollEdgeEffectStyle?, for edges: Edge.Set) -> some View { self }
|
|
60
|
+
|
|
61
|
+
public func scrollEdgeEffectHidden(_ hidden: Bool = true, for edges: Edge.Set = .all) -> some View { self }
|
|
62
|
+
|
|
63
|
+
public func safeAreaInset<V: View>(edge: VerticalEdge, alignment: HorizontalAlignment = .center,
|
|
64
|
+
spacing: CGFloat? = nil, @ViewBuilder content: () -> V) -> some View {
|
|
65
|
+
let inset = content()
|
|
66
|
+
return VStack(alignment: alignment, spacing: spacing ?? 0) {
|
|
67
|
+
if edge == .top { inset }
|
|
68
|
+
self.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
69
|
+
if edge == .bottom { inset }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public func safeAreaInset<V: View>(edge: HorizontalEdge, alignment: VerticalAlignment = .center,
|
|
74
|
+
spacing: CGFloat? = nil, @ViewBuilder content: () -> V) -> some View {
|
|
75
|
+
let inset = content()
|
|
76
|
+
return HStack(alignment: alignment, spacing: spacing ?? 0) {
|
|
77
|
+
if edge == .leading { inset }
|
|
78
|
+
self.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
79
|
+
if edge == .trailing { inset }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// MARK: - Content margins (iOS 17)
|
|
85
|
+
|
|
86
|
+
/// Where content margins apply: a scroll view's content, or its indicators
|
|
87
|
+
/// (which the page's scroll views do not inset).
|
|
88
|
+
public struct ContentMarginPlacement: Hashable, Sendable {
|
|
89
|
+
let name: String
|
|
90
|
+
public static let automatic = ContentMarginPlacement(name: "automatic")
|
|
91
|
+
public static let scrollContent = ContentMarginPlacement(name: "scrollContent")
|
|
92
|
+
public static let scrollIndicators = ContentMarginPlacement(name: "scrollIndicators")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
enum _ContentMarginsKey: EnvironmentKey { static let defaultValue: EdgeInsets? = nil }
|
|
96
|
+
|
|
97
|
+
extension EnvironmentValues {
|
|
98
|
+
/// `.contentMargins(_:_:for:)` above a scroll view: the insets around its content.
|
|
99
|
+
var _scrollContentMargins: EdgeInsets? {
|
|
100
|
+
get { self[_ContentMarginsKey.self] }
|
|
101
|
+
set { self[_ContentMarginsKey.self] = newValue }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
nonisolated extension View {
|
|
106
|
+
/// Insets the content of the scroll views below by `insets` on `edges`
|
|
107
|
+
/// (the content scrolls under the margin's area, as in SwiftUI, since it
|
|
108
|
+
/// is padding inside the scroll view). A margin set closer to the scroll
|
|
109
|
+
/// view wins on its edges.
|
|
110
|
+
public func contentMargins(_ edges: Edge.Set = .all, _ insets: EdgeInsets,
|
|
111
|
+
for placement: ContentMarginPlacement = .automatic) -> some View {
|
|
112
|
+
transformEnvironment(\._scrollContentMargins) { margins in
|
|
113
|
+
guard placement != .scrollIndicators else { return }
|
|
114
|
+
var value = margins ?? EdgeInsets()
|
|
115
|
+
if edges.contains(.top) { value.top = insets.top }
|
|
116
|
+
if edges.contains(.leading) { value.leading = insets.leading }
|
|
117
|
+
if edges.contains(.bottom) { value.bottom = insets.bottom }
|
|
118
|
+
if edges.contains(.trailing) { value.trailing = insets.trailing }
|
|
119
|
+
margins = value
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public func contentMargins(_ edges: Edge.Set = .all, _ length: CGFloat?,
|
|
124
|
+
for placement: ContentMarginPlacement = .automatic) -> some View {
|
|
125
|
+
let amount = length ?? 16
|
|
126
|
+
return contentMargins(edges, EdgeInsets(top: amount, leading: amount, bottom: amount, trailing: amount), for: placement)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public func contentMargins(_ length: CGFloat, for placement: ContentMarginPlacement = .automatic) -> some View {
|
|
130
|
+
contentMargins(.all, length, for: placement)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -35,7 +35,7 @@ extension EnvironmentValues {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
extension View {
|
|
38
|
+
nonisolated extension View {
|
|
39
39
|
public func scrollTargetBehavior(_ behavior: ScrollTargetBehavior) -> some View {
|
|
40
40
|
_EnvironmentView(content: self) { $0._scrollTargetBehavior = behavior.name }
|
|
41
41
|
}
|
|
@@ -60,13 +60,13 @@ public struct ScrollBounceBehavior: Hashable, Sendable {
|
|
|
60
60
|
|
|
61
61
|
/// The stacks `.scrollTargetLayout()` applies to; the runtime clears the flag
|
|
62
62
|
/// for their children so nested stacks do not add snap points.
|
|
63
|
-
protocol _ScrollTargetContainer {}
|
|
63
|
+
protocol _ScrollTargetContainer: _TraitBearing {}
|
|
64
64
|
extension HStack: _ScrollTargetContainer {}
|
|
65
65
|
extension VStack: _ScrollTargetContainer {}
|
|
66
66
|
|
|
67
67
|
// MARK: - containerRelativeFrame
|
|
68
68
|
|
|
69
|
-
extension View {
|
|
69
|
+
nonisolated extension View {
|
|
70
70
|
/// Sizes the view relative to its nearest container (the scroll view's
|
|
71
71
|
/// viewport or the screen): the whole container along `axes`, or `span`
|
|
72
72
|
/// of `count` equal columns separated by `spacing`. The renderer's layout
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// `ScrollViewReader` / `ScrollViewProxy.scrollTo(_:anchor:)`, and the
|
|
2
|
+
// `.id(_:)` that names what to scroll to (docs/ops-protocol.md, "Scrolling
|
|
3
|
+
// to a view").
|
|
4
|
+
//
|
|
5
|
+
// Inside a reader, every view with `.id(x)` is wrapped in a `styled` element
|
|
6
|
+
// marked `"scrollID": true`. `proxy.scrollTo(x, anchor:)` queues a request
|
|
7
|
+
// with a new serial number (increasing across all readers) and re-renders
|
|
8
|
+
// the reader, whose body takes the queue: in that pass the marked element
|
|
9
|
+
// whose id is `x` gets `"scrollTo": {"anchor": {x, y} | null, "serial": n}`
|
|
10
|
+
// in its style (it loses it the next time the reader's body runs). After
|
|
11
|
+
// laying out a pass that brings a `scrollTo` with a serial above every one
|
|
12
|
+
// it handled, the page scrolls the scroll views (and lists) around the
|
|
13
|
+
// element so the element's anchor point meets the same point of the visible
|
|
14
|
+
// area (smoothly when the pass is animated, `withAnimation {
|
|
15
|
+
// proxy.scrollTo(…) }`); a nil anchor scrolls as little as makes the
|
|
16
|
+
// element visible.
|
|
17
|
+
//
|
|
18
|
+
// Outside a reader `.id(_:)` adds nothing to the element tree, as before.
|
|
19
|
+
// Not supported: a `ForEach`'s own ids (the views need `.id(_:)` to be
|
|
20
|
+
// targets), and `.id` resetting the identity (and state) of its view when
|
|
21
|
+
// the id changes.
|
|
22
|
+
|
|
23
|
+
// MARK: - Requests
|
|
24
|
+
|
|
25
|
+
/// One `scrollTo` a reader is carrying out.
|
|
26
|
+
struct _ScrollRequest: Equatable {
|
|
27
|
+
let target: AnyHashable
|
|
28
|
+
let anchor: UnitPoint?
|
|
29
|
+
/// Tells the page a repeated request from an old one.
|
|
30
|
+
let serial: Int
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// A reader's queue of requests, taken by its next body run.
|
|
34
|
+
final class _ScrollRequestQueue {
|
|
35
|
+
var pending: [_ScrollRequest] = []
|
|
36
|
+
nonisolated(unsafe) static var lastSerial = 0
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// What `.id(_:)` views read: the requests of every enclosing reader.
|
|
40
|
+
struct _ScrollReaderContext: Equatable {
|
|
41
|
+
var requests: [_ScrollRequest] = []
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
enum _ScrollReaderKey: EnvironmentKey { static var defaultValue: _ScrollReaderContext? { nil } }
|
|
45
|
+
|
|
46
|
+
extension EnvironmentValues {
|
|
47
|
+
/// Set by `ScrollViewReader`; nil outside one.
|
|
48
|
+
var _scrollReader: _ScrollReaderContext? {
|
|
49
|
+
get { self[_ScrollReaderKey.self] }
|
|
50
|
+
set { self[_ScrollReaderKey.self] = newValue }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// MARK: - ScrollViewReader
|
|
55
|
+
|
|
56
|
+
/// Scrolls the scroll views inside its content to the views given an `.id`.
|
|
57
|
+
public struct ScrollViewProxy {
|
|
58
|
+
let request: @MainActor (AnyHashable, UnitPoint?) -> Void
|
|
59
|
+
|
|
60
|
+
/// Scrolls so the view with `.id(id)` is visible, its `anchor` point at
|
|
61
|
+
/// the same point of the scroll view's visible area (nil: as little as
|
|
62
|
+
/// makes it visible). Does nothing when no such view is on screen.
|
|
63
|
+
@MainActor
|
|
64
|
+
public func scrollTo<ID: Hashable>(_ id: ID, anchor: UnitPoint? = nil) {
|
|
65
|
+
request(AnyHashable(id), anchor)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public struct ScrollViewReader<Content: View>: View {
|
|
70
|
+
let content: (ScrollViewProxy) -> Content
|
|
71
|
+
@State private var queue = _ScrollRequestQueue()
|
|
72
|
+
/// Bumped by `scrollTo` so the reader's body runs and takes the queue.
|
|
73
|
+
@State private var requests = 0
|
|
74
|
+
@Environment(\._scrollReader) private var outer
|
|
75
|
+
|
|
76
|
+
public init(@ViewBuilder content: @escaping (ScrollViewProxy) -> Content) {
|
|
77
|
+
self.content = content
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public var body: some View {
|
|
81
|
+
let queue = self.queue
|
|
82
|
+
let bump = $requests
|
|
83
|
+
let proxy = ScrollViewProxy { target, anchor in
|
|
84
|
+
_ScrollRequestQueue.lastSerial += 1
|
|
85
|
+
queue.pending.append(_ScrollRequest(target: target, anchor: anchor, serial: _ScrollRequestQueue.lastSerial))
|
|
86
|
+
bump.wrappedValue += 1
|
|
87
|
+
}
|
|
88
|
+
var context = outer ?? _ScrollReaderContext()
|
|
89
|
+
context.requests += queue.pending
|
|
90
|
+
queue.pending.removeAll()
|
|
91
|
+
return content(proxy).environment(\._scrollReader, context)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// MARK: - .id(_:)
|
|
96
|
+
|
|
97
|
+
/// `.id(x)`: inside a `ScrollViewReader`, a `styled` element marking a
|
|
98
|
+
/// scroll target (carrying the scroll command in the pass that asks for
|
|
99
|
+
/// it); elsewhere the view itself.
|
|
100
|
+
struct _IdentifiedView<Content: View> {
|
|
101
|
+
let content: Content
|
|
102
|
+
let id: AnyHashable
|
|
103
|
+
@Environment(\._scrollReader) var reader
|
|
104
|
+
}
|
|
105
|
+
extension _IdentifiedView: View {
|
|
106
|
+
var body: some View {
|
|
107
|
+
if let reader {
|
|
108
|
+
let request = reader.requests.last { $0.target == id }
|
|
109
|
+
content._styled { style in
|
|
110
|
+
style.extras["scrollID"] = .bool(true)
|
|
111
|
+
if let request {
|
|
112
|
+
style.extras["scrollTo"] = .object([
|
|
113
|
+
"anchor": request.anchor.map { .object(["x": .number($0.x), "y": .number($0.y)]) } ?? .null,
|
|
114
|
+
"serial": .number(Double(request.serial)),
|
|
115
|
+
])
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
content
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// MARK: - scrollContentBackground
|
|
125
|
+
|
|
126
|
+
enum _ScrollContentBackgroundKey: EnvironmentKey { static let defaultValue: Visibility = .automatic }
|
|
127
|
+
|
|
128
|
+
extension EnvironmentValues {
|
|
129
|
+
/// `.scrollContentBackground(_:)`; a `List` hides its grouped background when `.hidden`.
|
|
130
|
+
var _scrollContentBackground: Visibility {
|
|
131
|
+
get { self[_ScrollContentBackgroundKey.self] }
|
|
132
|
+
set { self[_ScrollContentBackgroundKey.self] = newValue }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
nonisolated extension View {
|
|
137
|
+
/// `.hidden` drops a `List`'s own background (the system grouped
|
|
138
|
+
/// background), so a `.background(…)` behind the list shows through its
|
|
139
|
+
/// gaps; the rows keep their cell background. Scroll views and text
|
|
140
|
+
/// editors draw no background of their own already.
|
|
141
|
+
public func scrollContentBackground(_ visibility: Visibility) -> some View {
|
|
142
|
+
environment(\._scrollContentBackground, visibility)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// `Section` headers and footers that are views, not just `Text`.
|
|
2
|
+
//
|
|
3
|
+
// A `Text` header or footer (or an optional one, `footer: { if x { Text(…) } }`)
|
|
4
|
+
// stays the `section`'s `header` / `footer` string, as it always was. Any
|
|
5
|
+
// other view becomes a child of the `section`: a `sectionheader` before the
|
|
6
|
+
// rows and a `sectionfooter` after them, each with the view inside (props
|
|
7
|
+
// `{}`). In a list the page lays the header view out above the section's card
|
|
8
|
+
// and the footer view below it, in the content width, in the footnote font
|
|
9
|
+
// and the secondary color; outside a list (a `Section` in a `LazyVStack`) they
|
|
10
|
+
// stack with the rows. As for a string header, the texts in a header view
|
|
11
|
+
// are upper-cased (the environment's `textCase`, which `.textCase(nil)`
|
|
12
|
+
// inside the header undoes).
|
|
13
|
+
|
|
14
|
+
/// A section's view header or footer: kind `sectionheader` or `sectionfooter`.
|
|
15
|
+
struct _SectionSupplement {
|
|
16
|
+
let kind: String
|
|
17
|
+
let content: any View
|
|
18
|
+
}
|
|
19
|
+
extension _SectionSupplement: _PrimitiveView {}
|
|
20
|
+
extension _SectionSupplement: _HostView {
|
|
21
|
+
var _kind: String { kind }
|
|
22
|
+
func _props(in environment: EnvironmentValues) -> _JSON { .object([:]) }
|
|
23
|
+
var _content: [any View] {
|
|
24
|
+
guard kind == "sectionheader" else { return [content] }
|
|
25
|
+
return [_withEnvironment(content) { $0.textCase = .uppercase }]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// `content.environment(…)` for an existential view.
|
|
30
|
+
private func _withEnvironment(_ view: any View, _ apply: @escaping (inout EnvironmentValues) -> Void) -> any View {
|
|
31
|
+
func open<V: View>(_ content: V) -> any View { _EnvironmentView(content: content, apply: apply) }
|
|
32
|
+
return open(view)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// A header or footer view as the section stores it: a `Text` (or an
|
|
36
|
+
/// optional `Text`) as its string, anything else as a view.
|
|
37
|
+
private enum _SectionLabel {
|
|
38
|
+
case text(String?)
|
|
39
|
+
case view(any View)
|
|
40
|
+
|
|
41
|
+
init<V: View>(_ view: V) {
|
|
42
|
+
if let text = view as? Text {
|
|
43
|
+
self = .text(text.content)
|
|
44
|
+
} else if let optional = view as? Text? {
|
|
45
|
+
self = .text(optional?.content)
|
|
46
|
+
} else {
|
|
47
|
+
self = .view(view)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var string: String? {
|
|
52
|
+
if case .text(let string) = self { return string }
|
|
53
|
+
return nil
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var view: (any View)? {
|
|
57
|
+
if case .view(let view) = self { return view }
|
|
58
|
+
return nil
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
extension Section {
|
|
63
|
+
private init(content: Content, header: _SectionLabel?, footer: _SectionLabel?) {
|
|
64
|
+
self.header = header?.string
|
|
65
|
+
self.footer = footer?.string
|
|
66
|
+
self.content = content
|
|
67
|
+
headerView = header?.view
|
|
68
|
+
footerView = footer?.view
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public init<H: View>(@ViewBuilder content: () -> Content, @ViewBuilder header: () -> H) {
|
|
72
|
+
self.init(content: content(), header: _SectionLabel(header()), footer: nil)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public init<F: View>(@ViewBuilder content: () -> Content, @ViewBuilder footer: () -> F) {
|
|
76
|
+
self.init(content: content(), header: nil, footer: _SectionLabel(footer()))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public init<H: View, F: View>(@ViewBuilder content: () -> Content, @ViewBuilder header: () -> H,
|
|
80
|
+
@ViewBuilder footer: () -> F) {
|
|
81
|
+
self.init(content: content(), header: _SectionLabel(header()), footer: _SectionLabel(footer()))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// The pre-iOS 15 spellings, with the header and footer as values.
|
|
85
|
+
public init<H: View>(header: H, @ViewBuilder content: () -> Content) {
|
|
86
|
+
self.init(content: content(), header: _SectionLabel(header), footer: nil)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public init<F: View>(footer: F, @ViewBuilder content: () -> Content) {
|
|
90
|
+
self.init(content: content(), header: nil, footer: _SectionLabel(footer))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public init<H: View, F: View>(header: H, footer: F, @ViewBuilder content: () -> Content) {
|
|
94
|
+
self.init(content: content(), header: _SectionLabel(header), footer: _SectionLabel(footer))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Custom shapes: a `Shape` that is not one of the built-in shapes the page
|
|
2
|
+
// draws by name (`_name` is `"path"`) is drawn from its `path(in:)`.
|
|
3
|
+
//
|
|
4
|
+
// The path depends on the size the shape is laid out at, which only the page
|
|
5
|
+
// knows, so a shape's element reports its size (`reportsSize`, like a
|
|
6
|
+
// `GeometryReader`'s) and the next render sends the path for it: SVG path
|
|
7
|
+
// data in `path`, for the rectangle `size`. Until the first report the
|
|
8
|
+
// shape draws nothing.
|
|
9
|
+
//
|
|
10
|
+
// SwiftUI animates a shape by interpolating its `animatableData` and asking
|
|
11
|
+
// for the path at each step. Here, when a shape's `animatableData` changes in
|
|
12
|
+
// a pass that may animate it (the transaction has an animation, or an
|
|
13
|
+
// `.animation(_:value:)` above it saw its value change), the element also
|
|
14
|
+
// carries the path along the way (`frames`: the paths at
|
|
15
|
+
// fractions of the change, and below 0 and above 1 for a spring that
|
|
16
|
+
// overshoots). The page plays them when the commit animates the shape, in the
|
|
17
|
+
// commit's timing curve (src/animation.ts); otherwise it draws the end path.
|
|
18
|
+
|
|
19
|
+
/// A shape that can be inset (`strokeBorder` draws inside its bounds).
|
|
20
|
+
public protocol InsettableShape: Shape {
|
|
21
|
+
associatedtype InsetShape: InsettableShape
|
|
22
|
+
func inset(by amount: CGFloat) -> InsetShape
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// A shape inset by `amount` on every side.
|
|
26
|
+
nonisolated public struct _InsetShape<Base: Shape>: InsettableShape {
|
|
27
|
+
let base: Base
|
|
28
|
+
let amount: CGFloat
|
|
29
|
+
|
|
30
|
+
public func path(in rect: CGRect) -> Path {
|
|
31
|
+
let inset = rect.insetBy(dx: amount, dy: amount)
|
|
32
|
+
guard inset.width >= 0, inset.height >= 0 else { return Path() }
|
|
33
|
+
return base.path(in: inset)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public func inset(by amount: CGFloat) -> _InsetShape<Base> {
|
|
37
|
+
_InsetShape(base: base, amount: self.amount + amount)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public var animatableData: CGFloat {
|
|
41
|
+
get { amount }
|
|
42
|
+
set { self = _InsetShape(base: base, amount: newValue) }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
extension Rectangle: InsettableShape {
|
|
47
|
+
public func inset(by amount: CGFloat) -> _InsetShape<Rectangle> { _InsetShape(base: self, amount: amount) }
|
|
48
|
+
}
|
|
49
|
+
extension RoundedRectangle: InsettableShape {
|
|
50
|
+
public func inset(by amount: CGFloat) -> _InsetShape<RoundedRectangle> { _InsetShape(base: self, amount: amount) }
|
|
51
|
+
}
|
|
52
|
+
extension UnevenRoundedRectangle: InsettableShape {
|
|
53
|
+
public func inset(by amount: CGFloat) -> _InsetShape<UnevenRoundedRectangle> { _InsetShape(base: self, amount: amount) }
|
|
54
|
+
}
|
|
55
|
+
extension Circle: InsettableShape {
|
|
56
|
+
public func inset(by amount: CGFloat) -> _InsetShape<Circle> { _InsetShape(base: self, amount: amount) }
|
|
57
|
+
}
|
|
58
|
+
extension Capsule: InsettableShape {
|
|
59
|
+
public func inset(by amount: CGFloat) -> _InsetShape<Capsule> { _InsetShape(base: self, amount: amount) }
|
|
60
|
+
}
|
|
61
|
+
extension Ellipse: InsettableShape {
|
|
62
|
+
public func inset(by amount: CGFloat) -> _InsetShape<Ellipse> { _InsetShape(base: self, amount: amount) }
|
|
63
|
+
}
|
|
64
|
+
extension ContainerRelativeShape: InsettableShape {
|
|
65
|
+
public func inset(by amount: CGFloat) -> _InsetShape<ContainerRelativeShape> { _InsetShape(base: self, amount: amount) }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
extension Path: Shape {
|
|
69
|
+
public func path(in rect: CGRect) -> Path { self }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// A shape is a view: drawn filled with the foreground style.
|
|
73
|
+
extension Shape {
|
|
74
|
+
public var body: _ShapeView<Self> { _ShapeView(shape: self, fill: nil, stroke: nil) }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Drawing from the path
|
|
78
|
+
|
|
79
|
+
/// A view whose element may draw a path for its laid-out size: the runtime
|
|
80
|
+
/// reports the size to it and adds the path to its props.
|
|
81
|
+
@MainActor protocol _PathDrawing: _TraitBearing {
|
|
82
|
+
/// Whether this value draws a path (a built-in shape draws by name).
|
|
83
|
+
var _drawsPath: Bool { get }
|
|
84
|
+
/// `props` with the path for `size`, and the frames of a change of the
|
|
85
|
+
/// shape's `animatableData` when the pass may animate it (`animated`).
|
|
86
|
+
func _pathProps(_ props: _JSON, size: CGSize, state: _PathState, animated: Bool) -> _JSON
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// What a path-drawing node keeps between renders: the shape it drew last,
|
|
90
|
+
/// for which size, and the path props it sent for them.
|
|
91
|
+
final class _PathState {
|
|
92
|
+
var shape: Any?
|
|
93
|
+
var size = CGSize.zero
|
|
94
|
+
var inset: CGFloat = 0
|
|
95
|
+
var fields: [String: _JSON] = [:]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// The paths at these fractions of an animated change are sent with it.
|
|
99
|
+
let _pathFrameProgress: [Double] = [-0.3, -0.2, -0.1] + (0...60).map { Double($0) / 60 } + [1.1, 1.2, 1.3]
|
|
100
|
+
|
|
101
|
+
extension _ShapeView: _PathDrawing {
|
|
102
|
+
var _drawsPath: Bool { shape._name == "path" }
|
|
103
|
+
|
|
104
|
+
/// How far inside its bounds the path is drawn: half the line of a
|
|
105
|
+
/// `strokeBorder`, so that the line lies inside.
|
|
106
|
+
private var strokeInset: CGFloat {
|
|
107
|
+
guard let stroke, stroke.inset else { return 0 }
|
|
108
|
+
return stroke.lineWidth / 2
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@MainActor func _pathProps(_ props: _JSON, size: CGSize, state: _PathState, animated: Bool) -> _JSON {
|
|
112
|
+
guard case .object(var fields) = props else { return props }
|
|
113
|
+
let inset = strokeInset
|
|
114
|
+
var budget = 4096
|
|
115
|
+
let unchanged = state.size == size && state.inset == inset
|
|
116
|
+
&& state.shape.map { _Sameness.same($0, shape, budget: &budget) } == true
|
|
117
|
+
if !unchanged {
|
|
118
|
+
var path: [String: _JSON] = [
|
|
119
|
+
"path": .string(size == .zero ? "" : Self.drawnPath(of: shape, inset: inset, in: size)._svg),
|
|
120
|
+
"size": .object(["width": .number(size.width), "height": .number(size.height)]),
|
|
121
|
+
]
|
|
122
|
+
if animated, size != .zero, let previous = state.shape as? S,
|
|
123
|
+
let frames = Self.frames(from: previous, to: shape, inset: inset, in: size) {
|
|
124
|
+
path["frames"] = frames
|
|
125
|
+
}
|
|
126
|
+
state.shape = shape
|
|
127
|
+
state.size = size
|
|
128
|
+
state.inset = inset
|
|
129
|
+
state.fields = path
|
|
130
|
+
}
|
|
131
|
+
fields.merge(state.fields) { _, new in new }
|
|
132
|
+
return .object(fields)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// The path of `shape` in a rectangle of `size`, inset by `inset` (an
|
|
136
|
+
/// insettable shape is inset as a shape, any other as a rectangle).
|
|
137
|
+
@MainActor static func drawnPath(of shape: S, inset: CGFloat, in size: CGSize) -> Path {
|
|
138
|
+
let rect = CGRect(origin: .zero, size: size)
|
|
139
|
+
guard inset != 0 else { return shape.path(in: rect) }
|
|
140
|
+
if let insettable = shape as? any InsettableShape {
|
|
141
|
+
return insettable.inset(by: inset).path(in: rect)
|
|
142
|
+
}
|
|
143
|
+
return shape.path(in: rect.insetBy(dx: inset, dy: inset))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// The paths along a change of `animatableData`, or nil when it did not change.
|
|
147
|
+
@MainActor static func frames(from previous: S, to shape: S, inset: CGFloat, in size: CGSize) -> _JSON? {
|
|
148
|
+
let from = previous.animatableData, to = shape.animatableData
|
|
149
|
+
guard S.AnimatableData.self != EmptyAnimatableData.self, from != to else { return nil }
|
|
150
|
+
var paths: [String] = []
|
|
151
|
+
var indices: [Int: Int] = [:]
|
|
152
|
+
var index: [_JSON] = []
|
|
153
|
+
for progress in _pathFrameProgress {
|
|
154
|
+
var step = shape
|
|
155
|
+
step.animatableData = from.interpolated(towards: to, amount: progress)
|
|
156
|
+
let svg = drawnPath(of: step, inset: inset, in: size)._svg
|
|
157
|
+
let hash = svg.hashValue
|
|
158
|
+
if let known = indices[hash], paths[known] == svg {
|
|
159
|
+
index.append(.number(Double(known)))
|
|
160
|
+
} else {
|
|
161
|
+
indices[hash] = paths.count
|
|
162
|
+
index.append(.number(Double(paths.count)))
|
|
163
|
+
paths.append(svg)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return .object([
|
|
167
|
+
"progress": .array(_pathFrameProgress.map(_JSON.number)),
|
|
168
|
+
"index": .array(index),
|
|
169
|
+
"paths": .array(paths.map(_JSON.string)),
|
|
170
|
+
])
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
extension _TrimmedShapeView: _PathDrawing {
|
|
175
|
+
var _drawsPath: Bool { _name == "path" }
|
|
176
|
+
|
|
177
|
+
@MainActor func _pathProps(_ props: _JSON, size: CGSize, state: _PathState, animated: Bool) -> _JSON {
|
|
178
|
+
_ShapeView(shape: self, fill: nil, stroke: nil)._pathProps(props, size: size, state: state, animated: animated)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// MARK: - Scaled shapes
|
|
183
|
+
|
|
184
|
+
/// A shape scaled about an anchor of its bounds (`shape.scale(0.99)`), drawn from its path.
|
|
185
|
+
nonisolated public struct ScaledShape<Content: Shape>: Shape {
|
|
186
|
+
public var shape: Content
|
|
187
|
+
public var scale: CGSize
|
|
188
|
+
public var anchor: UnitPoint
|
|
189
|
+
|
|
190
|
+
public init(shape: Content, scale: CGSize, anchor: UnitPoint = .center) {
|
|
191
|
+
self.shape = shape
|
|
192
|
+
self.scale = scale
|
|
193
|
+
self.anchor = anchor
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
public func path(in rect: CGRect) -> Path {
|
|
197
|
+
let x = rect.minX + anchor.x * rect.width
|
|
198
|
+
let y = rect.minY + anchor.y * rect.height
|
|
199
|
+
let transform = CGAffineTransform(translationX: -x, y: -y)
|
|
200
|
+
.concatenating(CGAffineTransform(scaleX: scale.width, y: scale.height))
|
|
201
|
+
.concatenating(CGAffineTransform(translationX: x, y: y))
|
|
202
|
+
return shape.path(in: rect).applying(transform)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
nonisolated extension Shape {
|
|
207
|
+
public func scale(x: CGFloat = 1, y: CGFloat = 1, anchor: UnitPoint = .center) -> ScaledShape<Self> {
|
|
208
|
+
ScaledShape(shape: self, scale: CGSize(width: x, height: y), anchor: anchor)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public func scale(_ scale: CGFloat, anchor: UnitPoint = .center) -> ScaledShape<Self> {
|
|
212
|
+
ScaledShape(shape: self, scale: CGSize(width: scale, height: scale), anchor: anchor)
|
|
213
|
+
}
|
|
214
|
+
}
|