@swiftbrowser/swift 0.0.0-stage → 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 +214 -0
- package/README.md +10 -2
- 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 +61 -0
- 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/FoundationBridge/Bundle.swift +119 -0
- 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 +29 -0
- 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/Locale.swift +86 -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 +53 -0
- package/Sources/FoundationBridge/UITextChecker.swift +30 -0
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/FoundationBridge/UserDefaults.swift +183 -0
- 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 +181 -0
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +221 -0
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +285 -0
- package/Sources/SwiftUI/API/App.swift +87 -0
- 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 +237 -0
- 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 +300 -0
- package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +92 -0
- package/Sources/SwiftUI/API/EditMode.swift +212 -0
- package/Sources/SwiftUI/API/Effects.swift +388 -0
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +439 -0
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +137 -0
- package/Sources/SwiftUI/API/Font.swift +131 -0
- package/Sources/SwiftUI/API/Gauge.swift +290 -0
- package/Sources/SwiftUI/API/Geometry.swift +89 -0
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +342 -0
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +188 -0
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
- package/Sources/SwiftUI/API/Layout.swift +220 -0
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +331 -0
- package/Sources/SwiftUI/API/Menu.swift +58 -0
- package/Sources/SwiftUI/API/Modifiers.swift +313 -0
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +386 -0
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
- package/Sources/SwiftUI/API/OnChange.swift +48 -0
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +185 -0
- 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 +122 -0
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +517 -0
- package/Sources/SwiftUI/API/Publishers.swift +107 -0
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +84 -0
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
- 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 +409 -0
- 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 +144 -0
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/StrokeStyle.swift +30 -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 +263 -0
- package/Sources/SwiftUI/API/Tasks.swift +35 -0
- 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/Timeline.swift +212 -0
- package/Sources/SwiftUI/API/Toolbar.swift +251 -0
- 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 +215 -0
- package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
- package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +325 -0
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +660 -0
- package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Charts/Marks.swift +204 -0
- package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
- package/Sources/SwiftUI/Charts/Scales.swift +326 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
- package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
- package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
- 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 +2 -0
- package/index.mjs +16 -0
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +30 -4
- package/sync-sources.mjs +33 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Redaction (`.redacted(reason:)`, `@Environment(\.redactionReasons)`) and
|
|
2
|
+
// list separators' visibility. Redaction reasons pass down the environment,
|
|
3
|
+
// so views that check them (to show placeholder content) adapt; the page
|
|
4
|
+
// does not paint redacted text as grey boxes. The page draws a list's
|
|
5
|
+
// separators itself, so `.listRowSeparator` and `.listSectionSeparator`
|
|
6
|
+
// are accepted and leave the separators as they are.
|
|
7
|
+
|
|
8
|
+
public struct RedactionReasons: OptionSet, Hashable, Sendable {
|
|
9
|
+
public let rawValue: Int
|
|
10
|
+
public init(rawValue: Int) { self.rawValue = rawValue }
|
|
11
|
+
public static let placeholder = RedactionReasons(rawValue: 1 << 0)
|
|
12
|
+
public static let privacy = RedactionReasons(rawValue: 1 << 1)
|
|
13
|
+
public static let invalidated = RedactionReasons(rawValue: 1 << 2)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
struct _RedactionReasonsKey: EnvironmentKey {
|
|
17
|
+
static var defaultValue: RedactionReasons { [] }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
extension EnvironmentValues {
|
|
21
|
+
/// Why the content is redacted; empty unless an ancestor is `.redacted(reason:)`.
|
|
22
|
+
public var redactionReasons: RedactionReasons {
|
|
23
|
+
get { self[_RedactionReasonsKey.self] }
|
|
24
|
+
set { self[_RedactionReasonsKey.self] = newValue }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public enum VerticalEdge: Int8, CaseIterable, Hashable, Sendable {
|
|
29
|
+
case top, bottom
|
|
30
|
+
|
|
31
|
+
public struct Set: OptionSet, Hashable, Sendable {
|
|
32
|
+
public let rawValue: Int8
|
|
33
|
+
public init(rawValue: Int8) { self.rawValue = rawValue }
|
|
34
|
+
public init(_ edge: VerticalEdge) { rawValue = 1 << edge.rawValue }
|
|
35
|
+
public static let top = Set(.top)
|
|
36
|
+
public static let bottom = Set(.bottom)
|
|
37
|
+
public static let all: Set = [.top, .bottom]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
nonisolated extension View {
|
|
42
|
+
/// Adds `reason` to the environment's `redactionReasons` for the views below.
|
|
43
|
+
public func redacted(reason: RedactionReasons) -> some View {
|
|
44
|
+
_EnvironmentView(content: self) { $0.redactionReasons.formUnion(reason) }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Clears `redactionReasons` for the views below.
|
|
48
|
+
public func unredacted() -> some View {
|
|
49
|
+
_EnvironmentView(content: self) { $0.redactionReasons = [] }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Changes an environment value for the views below.
|
|
53
|
+
public func transformEnvironment<V>(_ keyPath: WritableKeyPath<EnvironmentValues, V>,
|
|
54
|
+
transform: @escaping (inout V) -> Void) -> some View {
|
|
55
|
+
_EnvironmentView(content: self) { transform(&$0[keyPath: keyPath]) }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Hides the separators at the row's `edges` (the page draws list
|
|
59
|
+
/// separators; a row hiding its bottom one, or the next row hiding its
|
|
60
|
+
/// top one, leaves the line between them out). `.visible` and
|
|
61
|
+
/// `.automatic` leave them as they are.
|
|
62
|
+
public func listRowSeparator(_ visibility: Visibility, edges: VerticalEdge.Set = .all) -> some View {
|
|
63
|
+
_styled {
|
|
64
|
+
guard visibility == .hidden else { return }
|
|
65
|
+
$0.extras["listRowSeparator"] = .object([
|
|
66
|
+
"top": .bool(edges.contains(.top)),
|
|
67
|
+
"bottom": .bool(edges.contains(.bottom)),
|
|
68
|
+
])
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/// The view unchanged: separators take the system color.
|
|
72
|
+
public func listRowSeparatorTint(_ color: Color?, edges: VerticalEdge.Set = .all) -> some View { self }
|
|
73
|
+
public func listSectionSeparator(_ visibility: Visibility, edges: VerticalEdge.Set = .all) -> some View { self }
|
|
74
|
+
public func listSectionSeparatorTint(_ color: Color?, edges: VerticalEdge.Set = .all) -> some View { self }
|
|
75
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/// Swipe actions and context menus on list rows (docs/ops-protocol.md, Phase 8).
|
|
2
|
+
|
|
3
|
+
public enum HorizontalEdge: Hashable, CaseIterable, Sendable {
|
|
4
|
+
case leading, trailing
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// MARK: - Swipe actions
|
|
8
|
+
|
|
9
|
+
/// The `swipeactions` element: `[content, ...trailing, ...leading]`, the
|
|
10
|
+
/// actions flattened to their `button`s (a `.tint` on a button stays as a
|
|
11
|
+
/// `styled` wrapper carrying `tint`). Several `.swipeActions` on one row
|
|
12
|
+
/// accumulate into one element.
|
|
13
|
+
public struct _SwipeActionsView {
|
|
14
|
+
let content: any View
|
|
15
|
+
var trailing: [any View] = []
|
|
16
|
+
var leading: [any View] = []
|
|
17
|
+
var fullSwipeTrailing = true
|
|
18
|
+
var fullSwipeLeading = true
|
|
19
|
+
|
|
20
|
+
@MainActor
|
|
21
|
+
mutating func add(edge: HorizontalEdge, allowsFullSwipe: Bool, actions: any View) {
|
|
22
|
+
let flat = _flattenChildren(actions)
|
|
23
|
+
switch edge {
|
|
24
|
+
case .trailing:
|
|
25
|
+
trailing += flat
|
|
26
|
+
fullSwipeTrailing = allowsFullSwipe
|
|
27
|
+
case .leading:
|
|
28
|
+
leading += flat
|
|
29
|
+
fullSwipeLeading = allowsFullSwipe
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
extension _SwipeActionsView: _PrimitiveView {}
|
|
34
|
+
extension _SwipeActionsView: _HostView {
|
|
35
|
+
var _kind: String { "swipeactions" }
|
|
36
|
+
func _props(in environment: EnvironmentValues) -> _JSON {
|
|
37
|
+
.object([
|
|
38
|
+
"trailing": .number(Double(trailing.count)),
|
|
39
|
+
"leading": .number(Double(leading.count)),
|
|
40
|
+
"fullSwipeTrailing": .bool(fullSwipeTrailing),
|
|
41
|
+
"fullSwipeLeading": .bool(fullSwipeLeading),
|
|
42
|
+
])
|
|
43
|
+
}
|
|
44
|
+
var _content: [any View] { [content] + trailing + leading }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
nonisolated extension View {
|
|
48
|
+
/// Buttons revealed by swiping the row horizontally. The first declared
|
|
49
|
+
/// action is nearest the content and is the one a full swipe performs.
|
|
50
|
+
@MainActor
|
|
51
|
+
public func swipeActions<T: View>(edge: HorizontalEdge = .trailing, allowsFullSwipe: Bool = true,
|
|
52
|
+
@ViewBuilder content: () -> T) -> _SwipeActionsView {
|
|
53
|
+
var view = (self as? _SwipeActionsView) ?? _SwipeActionsView(content: self)
|
|
54
|
+
view.add(edge: edge, allowsFullSwipe: allowsFullSwipe, actions: content())
|
|
55
|
+
return view
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// MARK: - Context menu
|
|
60
|
+
|
|
61
|
+
/// The `contextmenu` element: `[content, ...items]`, the items as in a `menu`.
|
|
62
|
+
struct _ContextMenuView<Content: View, Items: View> {
|
|
63
|
+
let content: Content
|
|
64
|
+
let items: Items
|
|
65
|
+
}
|
|
66
|
+
extension _ContextMenuView: _PrimitiveView {}
|
|
67
|
+
extension _ContextMenuView: _HostView {
|
|
68
|
+
var _kind: String { "contextmenu" }
|
|
69
|
+
func _props(in environment: EnvironmentValues) -> _JSON { .object([:]) }
|
|
70
|
+
var _content: [any View] { [content, items] }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
nonisolated extension View {
|
|
74
|
+
/// Items shown in a popover on a long press or right click.
|
|
75
|
+
public func contextMenu<M: View>(@ViewBuilder menuItems: () -> M) -> some View {
|
|
76
|
+
_ContextMenuView(content: self, items: menuItems())
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// The preview is accepted and ignored.
|
|
80
|
+
public func contextMenu<M: View, P: View>(@ViewBuilder menuItems: () -> M,
|
|
81
|
+
@ViewBuilder preview: () -> P) -> some View {
|
|
82
|
+
_ContextMenuView(content: self, items: menuItems())
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/// More of an app's scenes: several scenes in one `body`, window groups
|
|
2
|
+
/// with an identifier or for a presented value, and the scene modifiers.
|
|
3
|
+
///
|
|
4
|
+
/// The page is the app's one window. An app whose `body` lists several
|
|
5
|
+
/// scenes shows the first window group that is not for a value (a value's
|
|
6
|
+
/// window opens only through `openWindow`, which does nothing, Windows.swift).
|
|
7
|
+
/// `.onChange(of:)` on a scene watches the value from the window's root view.
|
|
8
|
+
/// Window sizes, resizability, styles and the menu bar's `.commands` are
|
|
9
|
+
/// accepted and do nothing: there is no window to size and no menu bar.
|
|
10
|
+
|
|
11
|
+
/// The scenes of a `body` that lists several.
|
|
12
|
+
public struct _TupleScene: Scene {
|
|
13
|
+
let parts: [any Scene]
|
|
14
|
+
public typealias Body = Never
|
|
15
|
+
public var body: Never { fatalError("_TupleScene is a primitive scene") }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
extension _TupleScene: _RootScene {
|
|
19
|
+
var _rootView: any View {
|
|
20
|
+
let roots = parts.compactMap { $0 as? any _RootScene }
|
|
21
|
+
guard let root = roots.first(where: { !($0 is any _ValueWindowScene) }) ?? roots.first else {
|
|
22
|
+
fatalError("No scene the runtime can present. Use WindowGroup.")
|
|
23
|
+
}
|
|
24
|
+
return root._rootView
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@MainActor
|
|
29
|
+
extension SceneBuilder {
|
|
30
|
+
public static func buildBlock<each Content: Scene>(_ content: repeat each Content) -> _TupleScene {
|
|
31
|
+
var parts: [any Scene] = []
|
|
32
|
+
for part in repeat each content { parts.append(part) }
|
|
33
|
+
return _TupleScene(parts: parts)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public static func buildOptional<Content: Scene>(_ content: Content?) -> _TupleScene {
|
|
37
|
+
_TupleScene(parts: content.map { [$0] } ?? [])
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public static func buildEither<Content: Scene>(first content: Content) -> _TupleScene {
|
|
41
|
+
_TupleScene(parts: [content])
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static func buildEither<Content: Scene>(second content: Content) -> _TupleScene {
|
|
45
|
+
_TupleScene(parts: [content])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public static func buildLimitedAvailability<Content: Scene>(_ content: Content) -> _TupleScene {
|
|
49
|
+
_TupleScene(parts: [content])
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
extension WindowGroup {
|
|
54
|
+
/// A window group with an identifier (`openWindow(id:)` names it).
|
|
55
|
+
public init(id: String, @ViewBuilder content: () -> Content) {
|
|
56
|
+
self.init(content: content)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public init(_ title: String, id: String, @ViewBuilder content: () -> Content) {
|
|
60
|
+
self.init(content: content)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public init(_ titleKey: LocalizedStringKey, id: String, @ViewBuilder content: () -> Content) {
|
|
64
|
+
self.init(content: content)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// The content of a `WindowGroup(for:)`: made with no value.
|
|
69
|
+
public struct _ValueWindowContent<Value: Codable & Hashable, Content: View>: View {
|
|
70
|
+
let make: (Binding<Value?>) -> Content
|
|
71
|
+
public var body: Content { make(.constant(nil)) }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// A window group for presented values: never opened in the browser.
|
|
75
|
+
protocol _ValueWindowScene {}
|
|
76
|
+
extension WindowGroup: _ValueWindowScene where Content: _ValueWindowContentMarker {}
|
|
77
|
+
protocol _ValueWindowContentMarker {}
|
|
78
|
+
extension _ValueWindowContent: _ValueWindowContentMarker {}
|
|
79
|
+
|
|
80
|
+
@MainActor
|
|
81
|
+
extension WindowGroup {
|
|
82
|
+
/// A window per presented value (`openWindow(value:)`). The page opens no
|
|
83
|
+
/// other window, so the group is declared and never shown.
|
|
84
|
+
public init<D: Codable & Hashable, C: View>(for type: D.Type, @ViewBuilder content: @escaping (Binding<D?>) -> C)
|
|
85
|
+
where Content == _ValueWindowContent<D, C> {
|
|
86
|
+
self.init { _ValueWindowContent(make: content) }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public init<D: Codable & Hashable, C: View>(_ title: String, for type: D.Type,
|
|
90
|
+
@ViewBuilder content: @escaping (Binding<D?>) -> C)
|
|
91
|
+
where Content == _ValueWindowContent<D, C> {
|
|
92
|
+
self.init { _ValueWindowContent(make: content) }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/// How a window may be resized; accepted.
|
|
97
|
+
public struct WindowResizability: Hashable, Sendable {
|
|
98
|
+
let name: String
|
|
99
|
+
public static let automatic = WindowResizability(name: "automatic")
|
|
100
|
+
public static let contentSize = WindowResizability(name: "contentSize")
|
|
101
|
+
public static let contentMinSize = WindowResizability(name: "contentMinSize")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// `.onChange(of:)` on a scene: the root view watches the value.
|
|
105
|
+
struct _SceneOnChange<Value: Equatable>: ViewModifier {
|
|
106
|
+
let value: Value
|
|
107
|
+
let initial: Bool
|
|
108
|
+
let action: (Value, Value) -> Void
|
|
109
|
+
|
|
110
|
+
func body(content: Content) -> some View {
|
|
111
|
+
content.onChange(of: value, initial: initial, action)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
extension Scene {
|
|
116
|
+
/// Accepted: the page is not a resizable window.
|
|
117
|
+
public func defaultSize(width: CGFloat, height: CGFloat) -> some Scene { self }
|
|
118
|
+
public func defaultSize(_ size: CGSize) -> some Scene { self }
|
|
119
|
+
public func windowResizability(_ resizability: WindowResizability) -> some Scene { self }
|
|
120
|
+
public func handlesExternalEvents(matching conditions: Set<String>) -> some Scene { self }
|
|
121
|
+
|
|
122
|
+
/// Runs `action` when `value` changes, from the window's root view.
|
|
123
|
+
public func onChange<V: Equatable>(of value: V, initial: Bool = false,
|
|
124
|
+
_ action: @escaping (_ oldValue: V, _ newValue: V) -> Void) -> some Scene {
|
|
125
|
+
_modifyingRootView(_SceneOnChange(value: value, initial: initial, action: action))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public func onChange<V: Equatable>(of value: V, initial: Bool = false, _ action: @escaping () -> Void) -> some Scene {
|
|
129
|
+
_modifyingRootView(_SceneOnChange(value: value, initial: initial) { _, _ in action() })
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/// Scroll snapping (docs/ops-protocol.md, "Phase 12"): `.scrollTargetBehavior`
|
|
2
|
+
/// on a `ScrollView` and `.scrollTargetLayout()` on the stack inside it. The
|
|
3
|
+
/// scroll view carries `snap` (`viewAligned` or `paging`) and the stack
|
|
4
|
+
/// `scrollTarget: true`; the renderer maps them to CSS scroll snapping, so
|
|
5
|
+
/// the children of the target layout become the snap points.
|
|
6
|
+
|
|
7
|
+
public struct ScrollTargetBehavior: Hashable, Sendable {
|
|
8
|
+
let name: String
|
|
9
|
+
public static let viewAligned = ScrollTargetBehavior(name: "viewAligned")
|
|
10
|
+
public static let paging = ScrollTargetBehavior(name: "paging")
|
|
11
|
+
public static func viewAligned(limitBehavior: ViewAlignedScrollTargetBehavior.LimitBehavior) -> ScrollTargetBehavior { .viewAligned }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public enum ViewAlignedScrollTargetBehavior {
|
|
15
|
+
public struct LimitBehavior: Hashable, Sendable {
|
|
16
|
+
let name: String
|
|
17
|
+
public static let automatic = LimitBehavior(name: "automatic")
|
|
18
|
+
public static let always = LimitBehavior(name: "always")
|
|
19
|
+
public static let never = LimitBehavior(name: "never")
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
enum _ScrollTargetBehaviorKey: EnvironmentKey { static let defaultValue: String? = nil }
|
|
24
|
+
enum _ScrollTargetLayoutKey: EnvironmentKey { static let defaultValue = false }
|
|
25
|
+
|
|
26
|
+
extension EnvironmentValues {
|
|
27
|
+
var _scrollTargetBehavior: String? {
|
|
28
|
+
get { self[_ScrollTargetBehaviorKey.self] }
|
|
29
|
+
set { self[_ScrollTargetBehaviorKey.self] = newValue }
|
|
30
|
+
}
|
|
31
|
+
/// Set by `.scrollTargetLayout()`; the first stack below consumes it.
|
|
32
|
+
var _scrollTargetLayout: Bool {
|
|
33
|
+
get { self[_ScrollTargetLayoutKey.self] }
|
|
34
|
+
set { self[_ScrollTargetLayoutKey.self] = newValue }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
nonisolated extension View {
|
|
39
|
+
public func scrollTargetBehavior(_ behavior: ScrollTargetBehavior) -> some View {
|
|
40
|
+
_EnvironmentView(content: self) { $0._scrollTargetBehavior = behavior.name }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public func scrollTargetLayout(isEnabled: Bool = true) -> some View {
|
|
44
|
+
_EnvironmentView(content: self) { $0._scrollTargetLayout = isEnabled }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Accepted for source compatibility; the browser's scroll views clip to their frame already.
|
|
48
|
+
public func scrollClipDisabled(_ disabled: Bool = true) -> some View { self }
|
|
49
|
+
|
|
50
|
+
/// Accepted for source compatibility; the browser decides bounce behavior.
|
|
51
|
+
public func scrollBounceBehavior(_ behavior: ScrollBounceBehavior, axes: Axis.Set = [.vertical]) -> some View { self }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public struct ScrollBounceBehavior: Hashable, Sendable {
|
|
55
|
+
let name: String
|
|
56
|
+
public static let automatic = ScrollBounceBehavior(name: "automatic")
|
|
57
|
+
public static let always = ScrollBounceBehavior(name: "always")
|
|
58
|
+
public static let basedOnSize = ScrollBounceBehavior(name: "basedOnSize")
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// The stacks `.scrollTargetLayout()` applies to; the runtime clears the flag
|
|
62
|
+
/// for their children so nested stacks do not add snap points.
|
|
63
|
+
protocol _ScrollTargetContainer: _TraitBearing {}
|
|
64
|
+
extension HStack: _ScrollTargetContainer {}
|
|
65
|
+
extension VStack: _ScrollTargetContainer {}
|
|
66
|
+
|
|
67
|
+
// MARK: - containerRelativeFrame
|
|
68
|
+
|
|
69
|
+
nonisolated extension View {
|
|
70
|
+
/// Sizes the view relative to its nearest container (the scroll view's
|
|
71
|
+
/// viewport or the screen): the whole container along `axes`, or `span`
|
|
72
|
+
/// of `count` equal columns separated by `spacing`. The renderer's layout
|
|
73
|
+
/// engine resolves it against the container it knows (`containerRelativeFrame`
|
|
74
|
+
/// style hint: an affine `a × container + b` per axis).
|
|
75
|
+
public func containerRelativeFrame(_ axes: Axis.Set, alignment: Alignment = .center) -> some View {
|
|
76
|
+
_containerRelativeFrame(axes, a: 1, b: 0, alignment: alignment)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public func containerRelativeFrame(_ axes: Axis.Set, count: Int, span: Int = 1, spacing: CGFloat,
|
|
80
|
+
alignment: Alignment = .center) -> some View {
|
|
81
|
+
let n = CGFloat(max(count, 1)), s = CGFloat(max(span, 1))
|
|
82
|
+
// SwiftUI: (container - spacing × (count - 1)) × span / count + spacing × (span - 1).
|
|
83
|
+
return _containerRelativeFrame(axes, a: s / n, b: -spacing * (n - 1) * s / n + spacing * (s - 1), alignment: alignment)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// The closure variant. The closure is sampled at two container lengths and
|
|
87
|
+
/// treated as affine (`width * 0.6`, `width - 40`), which the common uses are.
|
|
88
|
+
public func containerRelativeFrame(_ axes: Axis.Set, alignment: Alignment = .center,
|
|
89
|
+
_ length: @escaping (CGFloat, Axis) -> CGFloat) -> some View {
|
|
90
|
+
let axis: Axis = axes.contains(.horizontal) ? .horizontal : .vertical
|
|
91
|
+
let b = length(0, axis)
|
|
92
|
+
let a = (length(1000, axis) - b) / 1000
|
|
93
|
+
return _containerRelativeFrame(axes, a: a, b: b, alignment: alignment)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
func _containerRelativeFrame(_ axes: Axis.Set, a: CGFloat, b: CGFloat, alignment: Alignment) -> some View {
|
|
97
|
+
_styled {
|
|
98
|
+
var hint: [String: _JSON] = ["a": .number(a), "b": .number(b), "alignment": .string(alignment._name)]
|
|
99
|
+
if axes.contains(.horizontal) { hint["horizontal"] = .bool(true) }
|
|
100
|
+
if axes.contains(.vertical) { hint["vertical"] = .bool(true) }
|
|
101
|
+
$0.extras["containerRelativeFrame"] = .object(hint)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -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
|
+
}
|