@swiftbrowser/swift 0.1.0 → 0.3.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 +68 -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 +125 -10
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +100 -9
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +11 -3
- package/Sources/SwiftUI/API/Gauge.swift +26 -10
- 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 +71 -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 +88 -12
- 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 +14 -4
- 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 +168 -39
- 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 +86 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +187 -8
- 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 +46 -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 +524 -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 +41 -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,841 @@
|
|
|
1
|
+
// The iOS 18 tab API: `Tab`, `TabSection`, `TabContent` and its result
|
|
2
|
+
// builder, `TabRole`, placements, styles and customization.
|
|
3
|
+
//
|
|
4
|
+
// Tab content resolves to `_TabEntry`s, one per `Tab`, in declaration order
|
|
5
|
+
// (sections flattened, a `.search` tab moved to the trailing end). Each entry
|
|
6
|
+
// becomes a `_TabEntryView`, which is to the runtime exactly what
|
|
7
|
+
// `content.tabItem { label }.tag(value)` is, so a `TabView` of `Tab`s emits the
|
|
8
|
+
// same `tabview` / `tab` elements as the `.tabItem` API, plus a `tab`'s
|
|
9
|
+
// `badge` and `role` props when they are set. In a regular-width
|
|
10
|
+
// `.sidebarAdaptable` tab view the tabs are a sidebar instead (see
|
|
11
|
+
// `_tabSidebar` in Tabs.swift). See docs/ops-protocol.md, "Tabs (iOS 18)".
|
|
12
|
+
|
|
13
|
+
import Foundation
|
|
14
|
+
|
|
15
|
+
/// The content of a `TabView` built with `Tab`s: tabs, sections of tabs,
|
|
16
|
+
/// `ForEach` over them, or a type with a `body`. Like `ChartContent` it is not
|
|
17
|
+
/// main-actor isolated: tabs are created in nonisolated initializers (as in
|
|
18
|
+
/// SwiftUI, where `Tab`'s initializers are `nonisolated`).
|
|
19
|
+
public protocol TabContent<TabValue> {
|
|
20
|
+
associatedtype TabValue: Hashable
|
|
21
|
+
associatedtype Body: TabContent
|
|
22
|
+
@TabContentBuilder<TabValue> var body: Self.Body { get }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
extension Never: @preconcurrency TabContent {
|
|
26
|
+
public typealias TabValue = Never
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// Tab content the runtime reads directly instead of evaluating `body`.
|
|
30
|
+
public protocol _PrimitiveTabContent: TabContent where Body == Never {}
|
|
31
|
+
|
|
32
|
+
extension _PrimitiveTabContent {
|
|
33
|
+
public var body: Never { fatalError("\(Self.self) is primitive tab content and has no body") }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// MARK: - Entries
|
|
37
|
+
|
|
38
|
+
/// What the modifiers on tab content set; an inner modifier overrides an outer one.
|
|
39
|
+
struct _TabModifiers {
|
|
40
|
+
var badge: String?
|
|
41
|
+
var hidden = false
|
|
42
|
+
var placement: TabPlacement?
|
|
43
|
+
var customizationID: String?
|
|
44
|
+
var hiddenIn: Set<TabBarPlacement> = []
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// One `Tab`, resolved.
|
|
48
|
+
struct _TabEntry {
|
|
49
|
+
let content: any View
|
|
50
|
+
let label: any View
|
|
51
|
+
let value: AnyHashable?
|
|
52
|
+
let role: TabRole?
|
|
53
|
+
let modifiers: _TabModifiers
|
|
54
|
+
/// Index of the enclosing `TabSection` in `_TabCollector.sections`.
|
|
55
|
+
let section: Int?
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
struct _TabCollector {
|
|
59
|
+
var entries: [_TabEntry] = []
|
|
60
|
+
/// The sections' headers, in declaration order.
|
|
61
|
+
var sections: [any View] = []
|
|
62
|
+
var section: Int?
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Internal: contributes tab entries.
|
|
66
|
+
protocol _TabContentNode {
|
|
67
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
extension TabContent {
|
|
71
|
+
func _collectAny(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
72
|
+
if let node = self as? any _TabContentNode {
|
|
73
|
+
node._collect(into: &collector, modifiers: modifiers)
|
|
74
|
+
} else {
|
|
75
|
+
body._collectAny(into: &collector, modifiers: modifiers)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// One tab as a view: to the runtime it is `content.tabItem { label }.tag(value)`
|
|
81
|
+
/// (a `_TabItemProviding` and `_TagProviding` group of the content), and it
|
|
82
|
+
/// carries the badge, role and section for the `tab` element and the sidebar.
|
|
83
|
+
struct _TabEntryView {
|
|
84
|
+
let entry: _TabEntry
|
|
85
|
+
/// The section's header, when the tab is in a `TabSection`.
|
|
86
|
+
let sectionHeader: (any View)?
|
|
87
|
+
/// The position of the tab in declaration order (the sidebar's row order).
|
|
88
|
+
let order: Int
|
|
89
|
+
}
|
|
90
|
+
extension _TabEntryView: _PrimitiveView {}
|
|
91
|
+
extension _TabEntryView: _GroupView {
|
|
92
|
+
var _children: [any View] { [entry.content] }
|
|
93
|
+
}
|
|
94
|
+
extension _TabEntryView: _TabItemProviding {
|
|
95
|
+
var _tabLabel: any View { entry.label }
|
|
96
|
+
var _tabContent: any View { entry.content }
|
|
97
|
+
}
|
|
98
|
+
extension _TabEntryView: _TagProviding {
|
|
99
|
+
/// A tab without a value (`Value == Never`) is only selected by index.
|
|
100
|
+
var _tag: AnyHashable { entry.value ?? AnyHashable(_UntaggedTab()) }
|
|
101
|
+
var _tagged: any View { entry.content }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
struct _UntaggedTab: Hashable {}
|
|
105
|
+
|
|
106
|
+
// MARK: - Tab
|
|
107
|
+
|
|
108
|
+
/// The semantic role of a tab. A `.search` tab sits at the trailing end of the
|
|
109
|
+
/// tab bar; without a title or image of its own it is "Search" with a
|
|
110
|
+
/// magnifying glass.
|
|
111
|
+
public struct TabRole: Hashable, Sendable {
|
|
112
|
+
let name: String
|
|
113
|
+
public static let search = TabRole(name: "search")
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// The label of a tab made from a title and an image.
|
|
117
|
+
public struct DefaultTabLabel {
|
|
118
|
+
let title: Text
|
|
119
|
+
let systemImage: String?
|
|
120
|
+
let image: String?
|
|
121
|
+
}
|
|
122
|
+
extension DefaultTabLabel: View {
|
|
123
|
+
public var body: some View {
|
|
124
|
+
if let systemImage {
|
|
125
|
+
Label { title } icon: { Image(systemName: systemImage) }
|
|
126
|
+
} else if let image {
|
|
127
|
+
Label { title } icon: { Image(image) }
|
|
128
|
+
} else {
|
|
129
|
+
title
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// A tab of a `TabView`: its content, a label for the tab bar (or sidebar),
|
|
135
|
+
/// and the `value` the tab view's `selection` takes when it is selected.
|
|
136
|
+
public struct Tab<Value: Hashable, Content: View, Label: View> {
|
|
137
|
+
let value: Value?
|
|
138
|
+
let role: TabRole?
|
|
139
|
+
let content: Content
|
|
140
|
+
let label: Label
|
|
141
|
+
|
|
142
|
+
init(_value value: Value?, role: TabRole?, content: Content, label: Label) {
|
|
143
|
+
self.value = value
|
|
144
|
+
self.role = role
|
|
145
|
+
self.content = content
|
|
146
|
+
self.label = label
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
extension Tab: _PrimitiveTabContent {
|
|
150
|
+
public typealias TabValue = Value
|
|
151
|
+
}
|
|
152
|
+
extension Tab: _TabContentNode {
|
|
153
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
154
|
+
collector.entries.append(_TabEntry(
|
|
155
|
+
content: content, label: label, value: value.map { AnyHashable($0) },
|
|
156
|
+
role: role, modifiers: modifiers, section: collector.section))
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
extension DefaultTabLabel {
|
|
161
|
+
init(_ title: Text, systemImage: String? = nil, image: String? = nil) {
|
|
162
|
+
self.title = title
|
|
163
|
+
self.systemImage = systemImage
|
|
164
|
+
self.image = image
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Titles, as SwiftUI takes them: a string, a localized key or a resource.
|
|
169
|
+
// `LocalizedStringResource` is declared in FoundationBridge, which depends on
|
|
170
|
+
// this module, so the resource initializers take any `CustomStringConvertible`
|
|
171
|
+
// (disfavored, so strings and keys pick their own overloads): a resource's
|
|
172
|
+
// `description` is its localized text.
|
|
173
|
+
extension Text {
|
|
174
|
+
init<R: CustomStringConvertible>(_tabResource resource: R) {
|
|
175
|
+
self.init(verbatim: resource.description)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
extension Tab where Label == DefaultTabLabel {
|
|
180
|
+
// With a value.
|
|
181
|
+
|
|
182
|
+
public nonisolated init<S: StringProtocol>(_ title: S, systemImage: String, value: Value,
|
|
183
|
+
@ViewBuilder content: () -> Content) {
|
|
184
|
+
self.init(_value: value, role: nil, content: content(), label: DefaultTabLabel(Text(title), systemImage: systemImage))
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public nonisolated init<S: StringProtocol>(_ title: S, systemImage: String, value: Value, role: TabRole?,
|
|
188
|
+
@ViewBuilder content: () -> Content) {
|
|
189
|
+
self.init(_value: value, role: role, content: content(), label: DefaultTabLabel(Text(title), systemImage: systemImage))
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public nonisolated init(_ titleKey: LocalizedStringKey, systemImage: String, value: Value,
|
|
193
|
+
@ViewBuilder content: () -> Content) {
|
|
194
|
+
self.init(_value: value, role: nil, content: content(), label: DefaultTabLabel(Text(titleKey), systemImage: systemImage))
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public nonisolated init(_ titleKey: LocalizedStringKey, systemImage: String, value: Value, role: TabRole?,
|
|
198
|
+
@ViewBuilder content: () -> Content) {
|
|
199
|
+
self.init(_value: value, role: role, content: content(), label: DefaultTabLabel(Text(titleKey), systemImage: systemImage))
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@_disfavoredOverload
|
|
203
|
+
public nonisolated init<R: CustomStringConvertible>(_ titleResource: R, systemImage: String, value: Value,
|
|
204
|
+
@ViewBuilder content: () -> Content) {
|
|
205
|
+
self.init(_value: value, role: nil, content: content(),
|
|
206
|
+
label: DefaultTabLabel(Text(_tabResource: titleResource), systemImage: systemImage))
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@_disfavoredOverload
|
|
210
|
+
public nonisolated init<R: CustomStringConvertible>(_ titleResource: R, systemImage: String, value: Value, role: TabRole?,
|
|
211
|
+
@ViewBuilder content: () -> Content) {
|
|
212
|
+
self.init(_value: value, role: role, content: content(),
|
|
213
|
+
label: DefaultTabLabel(Text(_tabResource: titleResource), systemImage: systemImage))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public nonisolated init<S: StringProtocol>(_ title: S, image: String, value: Value, role: TabRole? = nil,
|
|
217
|
+
@ViewBuilder content: () -> Content) {
|
|
218
|
+
self.init(_value: value, role: role, content: content(), label: DefaultTabLabel(Text(title), image: image))
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public nonisolated init(_ titleKey: LocalizedStringKey, image: String, value: Value, role: TabRole? = nil,
|
|
222
|
+
@ViewBuilder content: () -> Content) {
|
|
223
|
+
self.init(_value: value, role: role, content: content(), label: DefaultTabLabel(Text(titleKey), image: image))
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// A tab with only a role (`Tab(value: .search, role: .search) { … }`):
|
|
227
|
+
/// its label comes from the role.
|
|
228
|
+
public nonisolated init(value: Value, role: TabRole, @ViewBuilder content: () -> Content) {
|
|
229
|
+
self.init(_value: value, role: role, content: content(), label: DefaultTabLabel(Text(verbatim: "")))
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// With an optional value (`TabView(selection: Binding<T?>)`).
|
|
233
|
+
|
|
234
|
+
public nonisolated init<S: StringProtocol, T: Hashable>(_ title: S, systemImage: String, value: T,
|
|
235
|
+
@ViewBuilder content: () -> Content) where Value == T? {
|
|
236
|
+
self.init(_value: Optional(value), role: nil, content: content(), label: DefaultTabLabel(Text(title), systemImage: systemImage))
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public nonisolated init<S: StringProtocol, T: Hashable>(_ title: S, systemImage: String, value: T, role: TabRole?,
|
|
240
|
+
@ViewBuilder content: () -> Content) where Value == T? {
|
|
241
|
+
self.init(_value: Optional(value), role: role, content: content(), label: DefaultTabLabel(Text(title), systemImage: systemImage))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public nonisolated init<T: Hashable>(_ titleKey: LocalizedStringKey, systemImage: String, value: T,
|
|
245
|
+
@ViewBuilder content: () -> Content) where Value == T? {
|
|
246
|
+
self.init(_value: Optional(value), role: nil, content: content(), label: DefaultTabLabel(Text(titleKey), systemImage: systemImage))
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public nonisolated init<T: Hashable>(_ titleKey: LocalizedStringKey, systemImage: String, value: T, role: TabRole?,
|
|
250
|
+
@ViewBuilder content: () -> Content) where Value == T? {
|
|
251
|
+
self.init(_value: Optional(value), role: role, content: content(), label: DefaultTabLabel(Text(titleKey), systemImage: systemImage))
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@_disfavoredOverload
|
|
255
|
+
public nonisolated init<R: CustomStringConvertible, T: Hashable>(_ titleResource: R, systemImage: String, value: T,
|
|
256
|
+
@ViewBuilder content: () -> Content) where Value == T? {
|
|
257
|
+
self.init(_value: Optional(value), role: nil, content: content(),
|
|
258
|
+
label: DefaultTabLabel(Text(_tabResource: titleResource), systemImage: systemImage))
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@_disfavoredOverload
|
|
262
|
+
public nonisolated init<R: CustomStringConvertible, T: Hashable>(_ titleResource: R, systemImage: String, value: T,
|
|
263
|
+
role: TabRole?, @ViewBuilder content: () -> Content) where Value == T? {
|
|
264
|
+
self.init(_value: Optional(value), role: role, content: content(),
|
|
265
|
+
label: DefaultTabLabel(Text(_tabResource: titleResource), systemImage: systemImage))
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
extension Tab {
|
|
270
|
+
/// A tab with a custom label.
|
|
271
|
+
public nonisolated init(value: Value, @ViewBuilder content: () -> Content, @ViewBuilder label: () -> Label) {
|
|
272
|
+
self.init(_value: value, role: nil, content: content(), label: label())
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public nonisolated init(value: Value, role: TabRole?, @ViewBuilder content: () -> Content,
|
|
276
|
+
@ViewBuilder label: () -> Label) {
|
|
277
|
+
self.init(_value: value, role: role, content: content(), label: label())
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public nonisolated init<T: Hashable>(value: T, @ViewBuilder content: () -> Content,
|
|
281
|
+
@ViewBuilder label: () -> Label) where Value == T? {
|
|
282
|
+
self.init(_value: Optional(value), role: nil, content: content(), label: label())
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public nonisolated init<T: Hashable>(value: T, role: TabRole?, @ViewBuilder content: () -> Content,
|
|
286
|
+
@ViewBuilder label: () -> Label) where Value == T? {
|
|
287
|
+
self.init(_value: Optional(value), role: role, content: content(), label: label())
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Tabs without a value (a `TabView` without a selection binding).
|
|
292
|
+
|
|
293
|
+
extension Tab where Value == Never, Label == DefaultTabLabel {
|
|
294
|
+
public nonisolated init<S: StringProtocol>(_ title: S, systemImage: String, @ViewBuilder content: () -> Content) {
|
|
295
|
+
self.init(_value: nil, role: nil, content: content(), label: DefaultTabLabel(Text(title), systemImage: systemImage))
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
public nonisolated init<S: StringProtocol>(_ title: S, systemImage: String, role: TabRole?,
|
|
299
|
+
@ViewBuilder content: () -> Content) {
|
|
300
|
+
self.init(_value: nil, role: role, content: content(), label: DefaultTabLabel(Text(title), systemImage: systemImage))
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
public nonisolated init(_ titleKey: LocalizedStringKey, systemImage: String, @ViewBuilder content: () -> Content) {
|
|
304
|
+
self.init(_value: nil, role: nil, content: content(), label: DefaultTabLabel(Text(titleKey), systemImage: systemImage))
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
public nonisolated init(_ titleKey: LocalizedStringKey, systemImage: String, role: TabRole?,
|
|
308
|
+
@ViewBuilder content: () -> Content) {
|
|
309
|
+
self.init(_value: nil, role: role, content: content(), label: DefaultTabLabel(Text(titleKey), systemImage: systemImage))
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
@_disfavoredOverload
|
|
313
|
+
public nonisolated init<R: CustomStringConvertible>(_ titleResource: R, systemImage: String,
|
|
314
|
+
@ViewBuilder content: () -> Content) {
|
|
315
|
+
self.init(_value: nil, role: nil, content: content(),
|
|
316
|
+
label: DefaultTabLabel(Text(_tabResource: titleResource), systemImage: systemImage))
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
@_disfavoredOverload
|
|
320
|
+
public nonisolated init<R: CustomStringConvertible>(_ titleResource: R, systemImage: String, role: TabRole?,
|
|
321
|
+
@ViewBuilder content: () -> Content) {
|
|
322
|
+
self.init(_value: nil, role: role, content: content(),
|
|
323
|
+
label: DefaultTabLabel(Text(_tabResource: titleResource), systemImage: systemImage))
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public nonisolated init<S: StringProtocol>(_ title: S, image: String, role: TabRole? = nil,
|
|
327
|
+
@ViewBuilder content: () -> Content) {
|
|
328
|
+
self.init(_value: nil, role: role, content: content(), label: DefaultTabLabel(Text(title), image: image))
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
public nonisolated init(role: TabRole, @ViewBuilder content: () -> Content) {
|
|
332
|
+
self.init(_value: nil, role: role, content: content(), label: DefaultTabLabel(Text(verbatim: "")))
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
extension Tab where Value == Never {
|
|
337
|
+
public nonisolated init(@ViewBuilder content: () -> Content, @ViewBuilder label: () -> Label) {
|
|
338
|
+
self.init(_value: nil, role: nil, content: content(), label: label())
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
public nonisolated init(role: TabRole?, @ViewBuilder content: () -> Content, @ViewBuilder label: () -> Label) {
|
|
342
|
+
self.init(_value: nil, role: role, content: content(), label: label())
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// MARK: - TabSection
|
|
347
|
+
|
|
348
|
+
/// A group of tabs. In a tab bar the section's tabs are tabs of their own
|
|
349
|
+
/// (flattened in order); in a regular-width `.sidebarAdaptable` sidebar they
|
|
350
|
+
/// are a list section under the header.
|
|
351
|
+
public struct TabSection<Header: View, Content: TabContent, Footer: View> {
|
|
352
|
+
let header: Header
|
|
353
|
+
let content: Content
|
|
354
|
+
let footer: Footer
|
|
355
|
+
}
|
|
356
|
+
extension TabSection: _PrimitiveTabContent {
|
|
357
|
+
public typealias TabValue = Content.TabValue
|
|
358
|
+
}
|
|
359
|
+
extension TabSection: _TabContentNode {
|
|
360
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
361
|
+
let outer = collector.section
|
|
362
|
+
collector.sections.append(header)
|
|
363
|
+
collector.section = collector.sections.count - 1
|
|
364
|
+
content._collectAny(into: &collector, modifiers: modifiers)
|
|
365
|
+
collector.section = outer
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
extension TabSection where Header == Text, Footer == EmptyView {
|
|
370
|
+
public nonisolated init<V>(_ titleKey: LocalizedStringKey, @TabContentBuilder<V> content: () -> Content)
|
|
371
|
+
where V == Content.TabValue {
|
|
372
|
+
self.init(header: Text(titleKey), content: content(), footer: EmptyView())
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
@_disfavoredOverload
|
|
376
|
+
public nonisolated init<S: StringProtocol, V>(_ title: S, @TabContentBuilder<V> content: () -> Content)
|
|
377
|
+
where V == Content.TabValue {
|
|
378
|
+
self.init(header: Text(title), content: content(), footer: EmptyView())
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
@_disfavoredOverload
|
|
382
|
+
public nonisolated init<R: CustomStringConvertible, V>(_ titleResource: R,
|
|
383
|
+
@TabContentBuilder<V> content: () -> Content)
|
|
384
|
+
where V == Content.TabValue {
|
|
385
|
+
self.init(header: Text(_tabResource: titleResource), content: content(), footer: EmptyView())
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
extension TabSection where Header == EmptyView, Footer == EmptyView {
|
|
390
|
+
public nonisolated init<V>(@TabContentBuilder<V> content: () -> Content) where V == Content.TabValue {
|
|
391
|
+
self.init(header: EmptyView(), content: content(), footer: EmptyView())
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
extension TabSection where Footer == EmptyView {
|
|
396
|
+
public nonisolated init<V>(@TabContentBuilder<V> content: () -> Content, @ViewBuilder header: () -> Header)
|
|
397
|
+
where V == Content.TabValue {
|
|
398
|
+
self.init(header: header(), content: content(), footer: EmptyView())
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
extension TabSection {
|
|
403
|
+
public nonisolated init<V>(@TabContentBuilder<V> content: () -> Content,
|
|
404
|
+
@ViewBuilder header: () -> Header, @ViewBuilder footer: () -> Footer)
|
|
405
|
+
where V == Content.TabValue {
|
|
406
|
+
self.init(header: header(), content: content(), footer: footer())
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/// Actions for the section's header in an iPadOS sidebar: accepted, not shown.
|
|
410
|
+
public nonisolated func sectionActions<A: View>(@ViewBuilder content: () -> A) -> some TabContent<TabValue> {
|
|
411
|
+
self
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// MARK: - Structural content
|
|
416
|
+
|
|
417
|
+
public struct _EmptyTabContent<TabValue: Hashable> {
|
|
418
|
+
public init() {}
|
|
419
|
+
}
|
|
420
|
+
extension _EmptyTabContent: _PrimitiveTabContent {}
|
|
421
|
+
extension _EmptyTabContent: _TabContentNode {
|
|
422
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
public struct _TupleTabContent<TabValue: Hashable, T> {
|
|
426
|
+
let children: [any TabContent]
|
|
427
|
+
}
|
|
428
|
+
extension _TupleTabContent: _PrimitiveTabContent {}
|
|
429
|
+
extension _TupleTabContent: _TabContentNode {
|
|
430
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
431
|
+
for child in children { child._collectAny(into: &collector, modifiers: modifiers) }
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
public struct _ConditionalTabContent<TrueContent: TabContent, FalseContent: TabContent>
|
|
436
|
+
where TrueContent.TabValue == FalseContent.TabValue {
|
|
437
|
+
enum Storage {
|
|
438
|
+
case trueContent(TrueContent)
|
|
439
|
+
case falseContent(FalseContent)
|
|
440
|
+
}
|
|
441
|
+
let storage: Storage
|
|
442
|
+
}
|
|
443
|
+
extension _ConditionalTabContent: _PrimitiveTabContent {
|
|
444
|
+
public typealias TabValue = TrueContent.TabValue
|
|
445
|
+
}
|
|
446
|
+
extension _ConditionalTabContent: _TabContentNode {
|
|
447
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
448
|
+
switch storage {
|
|
449
|
+
case .trueContent(let content): content._collectAny(into: &collector, modifiers: modifiers)
|
|
450
|
+
case .falseContent(let content): content._collectAny(into: &collector, modifiers: modifiers)
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
extension Optional: TabContent where Wrapped: TabContent {
|
|
456
|
+
public typealias TabValue = Wrapped.TabValue
|
|
457
|
+
public typealias Body = Never
|
|
458
|
+
public var body: Never { return fatalError("Optional is primitive tab content and has no body") }
|
|
459
|
+
}
|
|
460
|
+
extension Optional: _TabContentNode where Wrapped: TabContent {
|
|
461
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
462
|
+
if case .some(let content) = self { content._collectAny(into: &collector, modifiers: modifiers) }
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
public struct _ArrayTabContent<Element: TabContent> {
|
|
467
|
+
let elements: [Element]
|
|
468
|
+
}
|
|
469
|
+
extension _ArrayTabContent: _PrimitiveTabContent {
|
|
470
|
+
public typealias TabValue = Element.TabValue
|
|
471
|
+
}
|
|
472
|
+
extension _ArrayTabContent: _TabContentNode {
|
|
473
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
474
|
+
for element in elements { element._collectAny(into: &collector, modifiers: modifiers) }
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/// Type-erased tab content.
|
|
479
|
+
public struct AnyTabContent<TabValue: Hashable> {
|
|
480
|
+
let storage: any TabContent
|
|
481
|
+
public init<C: TabContent>(_ content: C) where C.TabValue == TabValue { storage = content }
|
|
482
|
+
public init<C: TabContent>(erasing content: C) where C.TabValue == TabValue { storage = content }
|
|
483
|
+
}
|
|
484
|
+
extension AnyTabContent: _PrimitiveTabContent {}
|
|
485
|
+
extension AnyTabContent: _TabContentNode {
|
|
486
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
487
|
+
storage._collectAny(into: &collector, modifiers: modifiers)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/// `ForEach` over tab content: the tabs of every element, in order.
|
|
492
|
+
extension ForEach: TabContent where Content: TabContent {
|
|
493
|
+
public typealias TabValue = Content.TabValue
|
|
494
|
+
public typealias Body = Never
|
|
495
|
+
public var body: Never { return fatalError("ForEach is primitive tab content and has no body") }
|
|
496
|
+
}
|
|
497
|
+
extension ForEach: _TabContentNode where Content: TabContent {
|
|
498
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
499
|
+
for element in data { content(element)._collectAny(into: &collector, modifiers: modifiers) }
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
extension ForEach where Content: TabContent {
|
|
504
|
+
public init<V>(_ data: Data, id: KeyPath<Data.Element, ID>,
|
|
505
|
+
@TabContentBuilder<V> content: @escaping (Data.Element) -> Content) where V == Content.TabValue {
|
|
506
|
+
self.init(_data: data, id: { $0[keyPath: id] }, content: content)
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
extension ForEach where Content: TabContent, Data.Element: Identifiable, ID == Data.Element.ID {
|
|
511
|
+
public init<V>(_ data: Data, @TabContentBuilder<V> content: @escaping (Data.Element) -> Content)
|
|
512
|
+
where V == Content.TabValue {
|
|
513
|
+
self.init(_data: data, id: { $0.id }, content: content)
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
extension ForEach where Content: TabContent, Data == Range<Int>, ID == Int {
|
|
518
|
+
public init<V>(_ data: Range<Int>, @TabContentBuilder<V> content: @escaping (Int) -> Content)
|
|
519
|
+
where V == Content.TabValue {
|
|
520
|
+
self.init(_data: data, id: { $0 }, content: content)
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// MARK: - TabContentBuilder
|
|
525
|
+
|
|
526
|
+
@resultBuilder
|
|
527
|
+
public struct TabContentBuilder<SelectionValue: Hashable> {
|
|
528
|
+
public static func buildBlock() -> _EmptyTabContent<SelectionValue> { _EmptyTabContent() }
|
|
529
|
+
|
|
530
|
+
public static func buildBlock<C: TabContent>(_ content: C) -> C where C.TabValue == SelectionValue { content }
|
|
531
|
+
|
|
532
|
+
public static func buildBlock<each C: TabContent>(
|
|
533
|
+
_ content: repeat each C
|
|
534
|
+
) -> _TupleTabContent<SelectionValue, (repeat each C)> {
|
|
535
|
+
var children: [any TabContent] = []
|
|
536
|
+
for child in repeat each content { children.append(child) }
|
|
537
|
+
return _TupleTabContent(children: children)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
public static func buildExpression<C: TabContent>(_ content: C) -> C where C.TabValue == SelectionValue { content }
|
|
541
|
+
|
|
542
|
+
public static func buildOptional<C: TabContent>(_ content: C?) -> C? where C.TabValue == SelectionValue { content }
|
|
543
|
+
|
|
544
|
+
public static func buildEither<TrueContent: TabContent, FalseContent: TabContent>(
|
|
545
|
+
first: TrueContent
|
|
546
|
+
) -> _ConditionalTabContent<TrueContent, FalseContent>
|
|
547
|
+
where TrueContent.TabValue == SelectionValue, FalseContent.TabValue == SelectionValue {
|
|
548
|
+
_ConditionalTabContent(storage: .trueContent(first))
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
public static func buildEither<TrueContent: TabContent, FalseContent: TabContent>(
|
|
552
|
+
second: FalseContent
|
|
553
|
+
) -> _ConditionalTabContent<TrueContent, FalseContent>
|
|
554
|
+
where TrueContent.TabValue == SelectionValue, FalseContent.TabValue == SelectionValue {
|
|
555
|
+
_ConditionalTabContent(storage: .falseContent(second))
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
public static func buildArray<C: TabContent>(_ components: [C]) -> _ArrayTabContent<C> where C.TabValue == SelectionValue {
|
|
559
|
+
_ArrayTabContent(elements: components)
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
public static func buildLimitedAvailability<C: TabContent>(_ content: C) -> AnyTabContent<SelectionValue>
|
|
563
|
+
where C.TabValue == SelectionValue {
|
|
564
|
+
AnyTabContent(content)
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/// A `TabView`'s content: the tab entries of `C` as `_TabEntryView`s.
|
|
568
|
+
public struct Content<C: TabContent> where C.TabValue == SelectionValue {
|
|
569
|
+
let content: C
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
extension TabContentBuilder.Content: _PrimitiveView {}
|
|
573
|
+
extension TabContentBuilder.Content: _GroupView {
|
|
574
|
+
/// The tabs in tab bar order: hidden tabs dropped and `.search` tabs moved
|
|
575
|
+
/// to the trailing end (where iOS puts the search tab).
|
|
576
|
+
var _children: [any View] {
|
|
577
|
+
var collector = _TabCollector()
|
|
578
|
+
content._collectAny(into: &collector, modifiers: _TabModifiers())
|
|
579
|
+
let declared = collector.entries.enumerated().filter { !$0.element.modifiers.hidden }
|
|
580
|
+
let ordered = declared.filter { $0.element.role != .search } + declared.filter { $0.element.role == .search }
|
|
581
|
+
return ordered.map { order, entry in
|
|
582
|
+
_TabEntryView(entry: entry, sectionHeader: entry.section.map { collector.sections[$0] }, order: order)
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// MARK: - Modifiers
|
|
588
|
+
|
|
589
|
+
/// Tab content with a modifier applied to every tab beneath it.
|
|
590
|
+
public struct _ModifiedTabContent<Content: TabContent> {
|
|
591
|
+
let content: Content
|
|
592
|
+
let transform: (inout _TabModifiers) -> Void
|
|
593
|
+
}
|
|
594
|
+
extension _ModifiedTabContent: _PrimitiveTabContent {
|
|
595
|
+
public typealias TabValue = Content.TabValue
|
|
596
|
+
}
|
|
597
|
+
extension _ModifiedTabContent: _TabContentNode {
|
|
598
|
+
func _collect(into collector: inout _TabCollector, modifiers: _TabModifiers) {
|
|
599
|
+
// Outer modifiers run first so that the tab's own (inner) ones win.
|
|
600
|
+
var modified = modifiers
|
|
601
|
+
transform(&modified)
|
|
602
|
+
content._collectAny(into: &collector, modifiers: modified)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/// Where a tab may appear when the tab bar and sidebar are customizable.
|
|
607
|
+
/// Recorded only: every tab appears in the tab bar (compact) and the sidebar
|
|
608
|
+
/// (regular `.sidebarAdaptable`).
|
|
609
|
+
public struct TabPlacement: Hashable, Sendable {
|
|
610
|
+
let name: String
|
|
611
|
+
public static let automatic = TabPlacement(name: "automatic")
|
|
612
|
+
public static let pinned = TabPlacement(name: "pinned")
|
|
613
|
+
public static let sidebarOnly = TabPlacement(name: "sidebarOnly")
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/// The bar a `TabView` shows its tabs in.
|
|
617
|
+
public struct TabBarPlacement: Hashable, Sendable {
|
|
618
|
+
let name: String
|
|
619
|
+
public static let automatic = TabBarPlacement(name: "automatic")
|
|
620
|
+
public static let tabBar = TabBarPlacement(name: "tabBar")
|
|
621
|
+
public static let sidebar = TabBarPlacement(name: "sidebar")
|
|
622
|
+
public static let ornament = TabBarPlacement(name: "ornament")
|
|
623
|
+
public static let topBar = TabBarPlacement(name: "topBar")
|
|
624
|
+
public static let bottomBar = TabBarPlacement(name: "bottomBar")
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/// The placement a `.sidebarAdaptable` tab view starts in.
|
|
628
|
+
public struct AdaptableTabBarPlacement: Hashable, Sendable {
|
|
629
|
+
let name: String
|
|
630
|
+
public static let automatic = AdaptableTabBarPlacement(name: "automatic")
|
|
631
|
+
public static let tabBar = AdaptableTabBarPlacement(name: "tabBar")
|
|
632
|
+
public static let sidebar = AdaptableTabBarPlacement(name: "sidebar")
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/// Whether the user may reorder or hide a tab or section (recorded only).
|
|
636
|
+
public struct TabCustomizationBehavior: Hashable, Sendable {
|
|
637
|
+
let name: String
|
|
638
|
+
public static let automatic = TabCustomizationBehavior(name: "automatic")
|
|
639
|
+
public static let reorderable = TabCustomizationBehavior(name: "reorderable")
|
|
640
|
+
public static let disabled = TabCustomizationBehavior(name: "disabled")
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
extension TabContent {
|
|
644
|
+
/// A badge on the tab's bar item (a count of 0 shows none).
|
|
645
|
+
public nonisolated func badge(_ count: Int) -> some TabContent<TabValue> {
|
|
646
|
+
_ModifiedTabContent(content: self) { $0.badge = count == 0 ? nil : String(count) }
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
public nonisolated func badge(_ label: Text?) -> some TabContent<TabValue> {
|
|
650
|
+
_ModifiedTabContent(content: self) { $0.badge = label.flatMap { $0.content.isEmpty ? nil : $0.content } }
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
@_disfavoredOverload
|
|
654
|
+
public nonisolated func badge<S: StringProtocol>(_ label: S?) -> some TabContent<TabValue> {
|
|
655
|
+
_ModifiedTabContent(content: self) { $0.badge = label.flatMap { $0.isEmpty ? nil : String($0) } }
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
public nonisolated func badge(_ key: LocalizedStringKey?) -> some TabContent<TabValue> {
|
|
659
|
+
_ModifiedTabContent(content: self) { modifiers in
|
|
660
|
+
modifiers.badge = key.flatMap { Text($0).content.isEmpty ? nil : Text($0).content }
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/// Hides the tab (it is not in the tab bar or the sidebar).
|
|
665
|
+
public nonisolated func hidden(_ hidden: Bool = true) -> some TabContent<TabValue> {
|
|
666
|
+
_ModifiedTabContent(content: self) { if hidden { $0.hidden = true } }
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/// Recorded only (see `TabPlacement`).
|
|
670
|
+
public nonisolated func tabPlacement(_ placement: TabPlacement) -> some TabContent<TabValue> {
|
|
671
|
+
_ModifiedTabContent(content: self) { $0.placement = placement }
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/// The identity of the tab in a `TabViewCustomization` (recorded only).
|
|
675
|
+
public nonisolated func customizationID(_ id: String) -> some TabContent<TabValue> {
|
|
676
|
+
_ModifiedTabContent(content: self) { $0.customizationID = id }
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/// Recorded only: tabs show in the tab bar and the sidebar regardless.
|
|
680
|
+
public nonisolated func defaultVisibility(_ visibility: Visibility,
|
|
681
|
+
for placements: TabBarPlacement...) -> some TabContent<TabValue> {
|
|
682
|
+
_ModifiedTabContent(content: self) { modifiers in
|
|
683
|
+
for placement in placements {
|
|
684
|
+
if visibility == .hidden {
|
|
685
|
+
modifiers.hiddenIn.insert(placement)
|
|
686
|
+
} else {
|
|
687
|
+
modifiers.hiddenIn.remove(placement)
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/// Accepted; tabs cannot be reordered or hidden by the user.
|
|
694
|
+
public nonisolated func customizationBehavior(_ behavior: TabCustomizationBehavior,
|
|
695
|
+
for placements: TabBarPlacement...) -> some TabContent<TabValue> {
|
|
696
|
+
self
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
public nonisolated func accessibilityIdentifier(_ identifier: String) -> some TabContent<TabValue> { self }
|
|
700
|
+
public nonisolated func accessibilityLabel(_ label: Text) -> some TabContent<TabValue> { self }
|
|
701
|
+
public nonisolated func springLoadingBehavior(_ behavior: SpringLoadingBehavior) -> some TabContent<TabValue> { self }
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/// Whether drags spring-load a tab (accepted; there is no drag and drop onto tabs).
|
|
705
|
+
public struct SpringLoadingBehavior: Hashable, Sendable {
|
|
706
|
+
let name: String
|
|
707
|
+
public static let automatic = SpringLoadingBehavior(name: "automatic")
|
|
708
|
+
public static let enabled = SpringLoadingBehavior(name: "enabled")
|
|
709
|
+
public static let disabled = SpringLoadingBehavior(name: "disabled")
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// MARK: - Customization
|
|
713
|
+
|
|
714
|
+
/// The user's customization of a tab view's tabs and sections (visibility and
|
|
715
|
+
/// order). The browser has no customization UI: the value is kept as state
|
|
716
|
+
/// (it is `Codable`, so `@AppStorage` round-trips it) and a tab view shows its
|
|
717
|
+
/// tabs as declared.
|
|
718
|
+
public struct TabViewCustomization: Equatable, Codable, Sendable {
|
|
719
|
+
var visibility: [String: String] = [:]
|
|
720
|
+
|
|
721
|
+
public init() {}
|
|
722
|
+
|
|
723
|
+
public subscript(visibility id: String) -> Visibility {
|
|
724
|
+
get {
|
|
725
|
+
switch visibility[id] {
|
|
726
|
+
case "visible": .visible
|
|
727
|
+
case "hidden": .hidden
|
|
728
|
+
default: .automatic
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
set {
|
|
732
|
+
switch newValue {
|
|
733
|
+
case .visible: visibility[id] = "visible"
|
|
734
|
+
case .hidden: visibility[id] = "hidden"
|
|
735
|
+
case .automatic: visibility[id] = nil
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
public mutating func resetVisibility() { visibility = [:] }
|
|
741
|
+
public mutating func resetTabOrder() {}
|
|
742
|
+
public mutating func resetSectionOrder(forIdentifier id: String) {}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// MARK: - Styles
|
|
746
|
+
|
|
747
|
+
/// How a `TabView` presents its tabs.
|
|
748
|
+
public protocol TabViewStyle {
|
|
749
|
+
var _name: String { get }
|
|
750
|
+
}
|
|
751
|
+
public struct DefaultTabViewStyle: TabViewStyle {
|
|
752
|
+
public init() {}
|
|
753
|
+
public var _name: String { "automatic" }
|
|
754
|
+
}
|
|
755
|
+
/// A tab bar in compact width; a sidebar in regular width.
|
|
756
|
+
public struct SidebarAdaptableTabViewStyle: TabViewStyle {
|
|
757
|
+
public init() {}
|
|
758
|
+
public var _name: String { "sidebarAdaptable" }
|
|
759
|
+
}
|
|
760
|
+
public struct TabBarOnlyTabViewStyle: TabViewStyle {
|
|
761
|
+
public init() {}
|
|
762
|
+
public var _name: String { "tabBarOnly" }
|
|
763
|
+
}
|
|
764
|
+
/// Accepted; the tabs are still shown with a tab bar.
|
|
765
|
+
public struct PageTabViewStyle: TabViewStyle {
|
|
766
|
+
public struct IndexDisplayMode: Hashable, Sendable {
|
|
767
|
+
let name: String
|
|
768
|
+
public static let automatic = IndexDisplayMode(name: "automatic")
|
|
769
|
+
public static let always = IndexDisplayMode(name: "always")
|
|
770
|
+
public static let never = IndexDisplayMode(name: "never")
|
|
771
|
+
}
|
|
772
|
+
public init(indexDisplayMode: IndexDisplayMode = .automatic) {}
|
|
773
|
+
public var _name: String { "page" }
|
|
774
|
+
}
|
|
775
|
+
extension TabViewStyle where Self == DefaultTabViewStyle {
|
|
776
|
+
public static var automatic: DefaultTabViewStyle { DefaultTabViewStyle() }
|
|
777
|
+
}
|
|
778
|
+
extension TabViewStyle where Self == SidebarAdaptableTabViewStyle {
|
|
779
|
+
public static var sidebarAdaptable: SidebarAdaptableTabViewStyle { SidebarAdaptableTabViewStyle() }
|
|
780
|
+
}
|
|
781
|
+
extension TabViewStyle where Self == TabBarOnlyTabViewStyle {
|
|
782
|
+
public static var tabBarOnly: TabBarOnlyTabViewStyle { TabBarOnlyTabViewStyle() }
|
|
783
|
+
}
|
|
784
|
+
extension TabViewStyle where Self == PageTabViewStyle {
|
|
785
|
+
public static var page: PageTabViewStyle { PageTabViewStyle() }
|
|
786
|
+
public static func page(indexDisplayMode: PageTabViewStyle.IndexDisplayMode) -> PageTabViewStyle {
|
|
787
|
+
PageTabViewStyle(indexDisplayMode: indexDisplayMode)
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
enum _TabViewStyleKey: EnvironmentKey { static let defaultValue = "automatic" }
|
|
792
|
+
enum _TabBarPlacementKey: EnvironmentKey { static let defaultValue = "automatic" }
|
|
793
|
+
|
|
794
|
+
extension EnvironmentValues {
|
|
795
|
+
var _tabViewStyle: String {
|
|
796
|
+
get { self[_TabViewStyleKey.self] }
|
|
797
|
+
set { self[_TabViewStyleKey.self] = newValue }
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/// The `defaultAdaptableTabBarPlacement` / `defaultTabBarPlacement` name.
|
|
801
|
+
var _tabBarPlacement: String {
|
|
802
|
+
get { self[_TabBarPlacementKey.self] }
|
|
803
|
+
set { self[_TabBarPlacementKey.self] = newValue }
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
nonisolated extension View {
|
|
808
|
+
public func tabViewStyle<S: TabViewStyle>(_ style: S) -> some View {
|
|
809
|
+
environment(\._tabViewStyle, style._name)
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/// Where a `.sidebarAdaptable` tab view shows its tabs in regular width:
|
|
813
|
+
/// `.tabBar` keeps the tab bar, anything else is the sidebar.
|
|
814
|
+
public func defaultAdaptableTabBarPlacement(_ placement: AdaptableTabBarPlacement = .automatic) -> some View {
|
|
815
|
+
environment(\._tabBarPlacement, placement.name)
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
public func defaultTabBarPlacement(_ placement: TabBarPlacement) -> some View {
|
|
819
|
+
environment(\._tabBarPlacement, placement.name)
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/// Accepted; the customization is kept by the app but not applied.
|
|
823
|
+
public func tabViewCustomization(_ customization: Binding<TabViewCustomization>?) -> some View { self }
|
|
824
|
+
|
|
825
|
+
public func tabViewSidebarHeader<V: View>(@ViewBuilder content: () -> V) -> some View { self }
|
|
826
|
+
public func tabViewSidebarFooter<V: View>(@ViewBuilder content: () -> V) -> some View { self }
|
|
827
|
+
public func tabViewSidebarBottomBar<V: View>(@ViewBuilder content: () -> V) -> some View { self }
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// MARK: - Symbol variants
|
|
831
|
+
|
|
832
|
+
enum _SymbolVariantsKey: EnvironmentKey { static let defaultValue = SymbolVariants.none }
|
|
833
|
+
|
|
834
|
+
extension EnvironmentValues {
|
|
835
|
+
/// The symbol variant the subtree asked for (tab labels set `.fill` on the
|
|
836
|
+
/// selected tab). Kept for views that read it; symbols draw as named.
|
|
837
|
+
public var symbolVariants: SymbolVariants {
|
|
838
|
+
get { self[_SymbolVariantsKey.self] }
|
|
839
|
+
set { self[_SymbolVariantsKey.self] = newValue }
|
|
840
|
+
}
|
|
841
|
+
}
|