@octane-xplat/lottie 0.9.0 → 0.11.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/README.md +36 -16
- package/dist/native/index.js +10 -9
- package/dist/native/octane-client-build.json +1 -1
- package/dist/web/index.js +39 -25
- package/dist/web/octane-client-build.json +1 -1
- package/package.json +25 -3
- package/platforms/macos/LICENSE-EpoxyCore-Apache-2.0.txt +201 -0
- package/platforms/macos/LICENSE-LRUCache-MIT.txt +22 -0
- package/platforms/macos/LICENSE-Lottie-Apache-2.0.txt +201 -0
- package/platforms/macos/LICENSE-ZIPFoundation-MIT.txt +21 -0
- package/platforms/macos/UPSTREAM.md +13 -0
- package/platforms/macos/resources/PrivacyInfo.xcprivacy +23 -0
- package/platforms/macos/resources/THIRD-PARTY-NOTICES.txt +10 -0
- package/platforms/macos/src/XplatAppKitLottie.swift +246 -0
- package/platforms/macos/src/vendor/Lottie/PrivacyInfo.xcprivacy +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +476 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +92 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/CustomPathAnimation.swift +89 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/DropShadowAnimation.swift +179 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/EllipseAnimation.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/GradientAnimations.swift +287 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/LayerProperty.swift +440 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/OpacityAnimation.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/RectangleAnimation.swift +59 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/ShapeAnimation.swift +246 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/StarAnimation.swift +119 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/StrokeAnimation.swift +96 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/TransformAnimations.swift +380 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Animations/VisibilityAnimation.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/CompatibilityTracker.swift +129 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/CoreAnimationLayer.swift +645 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +28 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/Keyframes+combined.swift +345 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift +46 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/AnimationLayer.swift +169 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/BaseAnimationLayer.swift +46 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +120 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +169 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/GradientRenderLayer.swift +101 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/ImageLayer.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +59 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +139 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/PreCompLayer.swift +107 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/RepeaterLayer.swift +113 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/ShapeItemLayer.swift +346 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/ShapeLayer.swift +569 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/SolidLayer.swift +66 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/TextLayer.swift +157 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/Layers/TransformLayer.swift +13 -0
- package/platforms/macos/src/vendor/Lottie/Private/CoreAnimation/ValueProviderStore.swift +157 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/Collection+Diff.swift +267 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/Diffable.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/DiffableSection.swift +16 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/IndexChangeset.swift +187 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Diffing/SectionedChangeset.swift +22 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Logging/EpoxyLogger.swift +102 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/CallbackContextEpoxyModeled.swift +8 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift +48 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift +158 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelStorage.swift +88 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModeled.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/AnyEpoxyModelProperty.swift +31 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/ClassReference.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/AnimatedProviding.swift +10 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DataIDProviding.swift +58 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidDisplayProviding.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidEndDisplayingProviding.swift +42 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidSelectProviding.swift +36 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ErasedContentProviding.swift +49 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/MakeViewProviding.swift +61 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetBehaviorsProviding.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetContentProviding.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/StyleIDProviding.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/TraitCollectionProviding.swift +14 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewDifferentiatorProviding.swift +34 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewProviding.swift +13 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/WillDisplayProviding.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Model/ViewEpoxyModeled.swift +10 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/README.md +30 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIIntrinsicContentSizeInvalidator.swift +34 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUILayoutMargins.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxyableView+SwiftUIView.swift +165 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift +127 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +468 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/SwiftUIView.swift +146 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIView+SwiftUIView.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIViewConfiguringSwiftUIView.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/BehaviorsConfigurableView.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/ContentConfigurableView.swift +36 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/EpoxyableView.swift +5 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/StyledView.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/EpoxyCore/Views/ViewType.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +257 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/LRUCache/README.md +24 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/README.md +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift +149 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Deprecated.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +361 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift +205 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift +66 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift +160 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+ReadingDeprecated.swift +50 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift +403 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+WritingDeprecated.swift +95 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive+ZIP64.swift +191 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Archive.swift +404 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +632 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Data+CompressionDeprecated.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Data+Serialization.swift +146 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Date+ZIP.swift +101 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Entry+Serialization.swift +191 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift +170 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/Entry.swift +669 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +405 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIPDeprecated.swift +28 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/README.md +24 -0
- package/platforms/macos/src/vendor/Lottie/Private/EmbeddedLibraries/ZipFoundation/URL+ZIP.swift +34 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +177 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +191 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/NullCompositionLayer.swift +28 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +137 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.swift +60 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +247 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +321 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +56 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +103 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +424 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +55 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift +52 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +38 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +149 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +146 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift +62 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift +26 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueContainer.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +39 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/DropShadowNode.swift +102 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/LayerEffectNode.swift +25 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift +85 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +281 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +74 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +89 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +69 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +253 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +64 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +158 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +165 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +143 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +173 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +238 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift +73 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +224 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +162 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +88 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +103 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +149 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +179 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +345 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift +197 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift +20 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift +60 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +78 -0
- package/platforms/macos/src/vendor/Lottie/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/Asset.swift +51 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/AssetLibrary.swift +75 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/ImageAsset.swift +141 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Assets/PrecompAsset.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DictionaryInitializable.swift +73 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieAnimation.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieImageProvider.swift +89 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieManifest.swift +42 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/DotLottie/DotLottieUtils.swift +71 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Extensions/Bundle.swift +58 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +71 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Keyframes/KeyframeData.swift +111 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Keyframes/KeyframeGroup.swift +265 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/DropShadowEffect.swift +52 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/EffectValues/EffectValue.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerEffects/LayerEffect.swift +103 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerStyles/DropShadowStyle.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/LayerStyles/LayerStyle.swift +85 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/ImageLayerModel.swift +49 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/LayerModel.swift +266 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/PreCompLayerModel.swift +74 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/ShapeLayerModel.swift +50 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/SolidLayerModel.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Layers/TextLayerModel.swift +65 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/DashPattern.swift +42 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/Marker.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/Mask.swift +80 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Objects/Transform.swift +261 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Ellipse.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Fill.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/GradientFill.swift +142 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/GradientStroke.swift +244 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Group.swift +55 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Merge.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Rectangle.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Repeater.swift +181 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/RoundedCorners.swift +53 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Shape.swift +63 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/ShapeItem.swift +171 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/ShapeTransform.swift +202 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Star.swift +136 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Stroke.swift +144 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/ShapeItems/Trim.swift +90 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/Font.swift +67 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/Glyph.swift +94 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/TextAnimator.swift +240 -0
- package/platforms/macos/src/vendor/Lottie/Private/Model/Text/TextDocument.swift +142 -0
- package/platforms/macos/src/vendor/Lottie/Private/RootAnimationLayer.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Debugging/AnimatorNodeDebugging.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Debugging/LayerDebugging.swift +231 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Debugging/TestHelpers.swift +10 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/AnimationKeypathExtension.swift +303 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/BlendMode+Filter.swift +31 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/CGColor+RGB.swift +45 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/CGFloatExtensions.swift +152 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/DataExtension.swift +33 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/MathKit.swift +454 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Extensions/StringExtensions.swift +44 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/AnimationContext.swift +95 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/AnyEquatable.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/Binding+Map.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Helpers/View+ValueChanged.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Interpolatable/InterpolatableExtensions.swift +143 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Interpolatable/KeyframeExtensions.swift +47 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Interpolatable/KeyframeInterpolator.swift +250 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/LottieAnimationSource.swift +51 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/BezierPath.swift +509 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/BezierPathRoundExtension.swift +163 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/CGPointExtension.swift +35 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/ColorExtension.swift +101 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/CompoundBezierPath.swift +169 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/CurveVertex.swift +190 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/PathElement.swift +78 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/UnitBezier.swift +119 -0
- package/platforms/macos/src/vendor/Lottie/Private/Utility/Primitives/VectorsExtensions.swift +368 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimation.swift +179 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationHelpers.swift +317 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationLayer.swift +1582 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationView.swift +1090 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieAnimationViewInitializers.swift +226 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottiePlaybackMode.swift +266 -0
- package/platforms/macos/src/vendor/Lottie/Public/Animation/LottieView.swift +643 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/AnimationCacheProvider.swift +21 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/DefaultAnimationCache.swift +67 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/LRUAnimationCache.swift +11 -0
- package/platforms/macos/src/vendor/Lottie/Public/AnimationCache/LottieAnimationCache.swift +15 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/DecodingStrategy.swift +15 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/LottieConfiguration.swift +54 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/LottieURLSession.swift +31 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/ReducedMotionOption.swift +128 -0
- package/platforms/macos/src/vendor/Lottie/Public/Configuration/RenderingEngineOption.swift +117 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/AnimatedButton.swift +128 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/AnimatedControl.swift +248 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/AnimatedSwitch.swift +271 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/LottieButton.swift +119 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/LottieSwitch.swift +144 -0
- package/platforms/macos/src/vendor/Lottie/Public/Controls/LottieViewType.swift +79 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/Cache/DotLottieCache.swift +66 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/Cache/DotLottieCacheProvider.swift +21 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/DotLottieConfiguration.swift +72 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/DotLottieFile.swift +186 -0
- package/platforms/macos/src/vendor/Lottie/Public/DotLottie/DotLottieFileHelpers.swift +386 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/AnimationKeypath.swift +57 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/AnyValueProvider.swift +132 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +96 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +138 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +81 -0
- package/platforms/macos/src/vendor/Lottie/Public/FontProvider/AnimationFontProvider.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Public/ImageProvider/AnimationImageProvider.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Public/Keyframes/Interpolatable.swift +285 -0
- package/platforms/macos/src/vendor/Lottie/Public/Keyframes/Keyframe.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Public/Logging/LottieLogger.swift +138 -0
- package/platforms/macos/src/vendor/Lottie/Public/Primitives/AnimationTime.swift +15 -0
- package/platforms/macos/src/vendor/Lottie/Public/Primitives/LottieColor.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Public/Primitives/Vectors.swift +36 -0
- package/platforms/macos/src/vendor/Lottie/Public/TextProvider/AnimationTextProvider.swift +135 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/AnimationSubview.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/BundleImageProvider.swift +98 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift +33 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleAnimationView.swift +567 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleFontProvider.swift +41 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/Compatibility/CompatibleImageProvider.swift +43 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/FilepathImageProvider.swift +78 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/LottieAnimationViewBase.swift +85 -0
- package/platforms/macos/src/vendor/Lottie/Public/iOS/UIColorExtension.swift +23 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/AnimationSubview.macOS.swift +19 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/BundleImageProvider.macOS.swift +90 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/FilepathImageProvider.macOS.swift +86 -0
- package/platforms/macos/src/vendor/Lottie/Public/macOS/LottieAnimationViewBase.macOS.swift +102 -0
- package/src/Lottie.macos.tsrx +129 -0
- package/src/Lottie.tsrx +6 -4
- package/src/Lottie.web.tsrx +28 -11
- package/src/index.macos.ts +2 -0
- package/src/props.ts +6 -1
- package/types/generated/props.d.ts +5 -1
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
// Created by Bryn Bodayle on 1/24/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
// MARK: - SwiftUIMeasurementContainer
|
|
7
|
+
|
|
8
|
+
/// A view that has an `intrinsicContentSize` of the `uiView`'s `systemLayoutSizeFitting(…)` and
|
|
9
|
+
/// supports double layout pass sizing and content size category changes.
|
|
10
|
+
///
|
|
11
|
+
/// This container view uses an injected proposed width to measure the view and return its ideal
|
|
12
|
+
/// height through the `SwiftUISizingContext` binding.
|
|
13
|
+
///
|
|
14
|
+
/// - SeeAlso: ``MeasuringViewRepresentable``
|
|
15
|
+
final class SwiftUIMeasurementContainer<Content: ViewType>: ViewType {
|
|
16
|
+
|
|
17
|
+
// MARK: Lifecycle
|
|
18
|
+
|
|
19
|
+
init(content: Content, strategy: SwiftUIMeasurementContainerStrategy) {
|
|
20
|
+
self.content = content
|
|
21
|
+
self.strategy = strategy
|
|
22
|
+
|
|
23
|
+
// On iOS 15 and below, passing zero can result in a constraint failure the first time a view
|
|
24
|
+
// is displayed, but the system gracefully recovers afterwards. On iOS 16, it's fine to pass
|
|
25
|
+
// zero.
|
|
26
|
+
let initialSize: CGSize =
|
|
27
|
+
if #available(iOS 16, tvOS 16, macOS 13, *) {
|
|
28
|
+
.zero
|
|
29
|
+
} else {
|
|
30
|
+
.init(width: 375, height: 150)
|
|
31
|
+
}
|
|
32
|
+
super.init(frame: .init(origin: .zero, size: initialSize))
|
|
33
|
+
|
|
34
|
+
addSubview(content)
|
|
35
|
+
setUpConstraints()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@available(*, unavailable)
|
|
39
|
+
required init?(coder _: NSCoder) {
|
|
40
|
+
fatalError("init(coder:) has not been implemented")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// MARK: Internal
|
|
44
|
+
|
|
45
|
+
/// The most recently measured fitting size of the `uiView` that fits within the current
|
|
46
|
+
/// `proposedSize`.
|
|
47
|
+
///
|
|
48
|
+
/// Contains `proposedSize`/`bounds.size` fallbacks for dimensions with no intrinsic size, as
|
|
49
|
+
/// compared to `intrinsicContentSize` which has `UIView.noIntrinsicMetric` fields in the case of
|
|
50
|
+
/// no intrinsic size.
|
|
51
|
+
var measuredFittingSize: CGSize {
|
|
52
|
+
_measuredFittingSize ?? measureView()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// The `UIView` content that's being measured by this container.
|
|
56
|
+
var content: Content {
|
|
57
|
+
didSet {
|
|
58
|
+
guard content !== oldValue else { return }
|
|
59
|
+
oldValue.removeFromSuperview()
|
|
60
|
+
addSubview(content)
|
|
61
|
+
// Invalidate the strategy since it's derived from this view.
|
|
62
|
+
_resolvedStrategy = nil
|
|
63
|
+
// Re-configure the constraints since they depend on the resolved strategy.
|
|
64
|
+
setUpConstraints()
|
|
65
|
+
// Finally, we need to re-measure the view.
|
|
66
|
+
_measuredFittingSize = nil
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// The proposed size at the time of the latest measurement.
|
|
71
|
+
///
|
|
72
|
+
/// Has a side-effect of updating the `measuredIntrinsicContentSize` if it's changed.
|
|
73
|
+
var proposedSize = CGSize.noIntrinsicMetric {
|
|
74
|
+
didSet {
|
|
75
|
+
guard oldValue != proposedSize else { return }
|
|
76
|
+
// The proposed size is only used by the measurement, so just re-measure.
|
|
77
|
+
_measuredFittingSize = nil
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// The measurement strategy of this container.
|
|
82
|
+
///
|
|
83
|
+
/// Has a side-effect of updating the `measuredIntrinsicContentSize` if it's changed.
|
|
84
|
+
var strategy: SwiftUIMeasurementContainerStrategy {
|
|
85
|
+
didSet {
|
|
86
|
+
guard oldValue != strategy else { return }
|
|
87
|
+
// Invalidate the resolved strategy since it's derived from this strategy.
|
|
88
|
+
_resolvedStrategy = nil
|
|
89
|
+
// Then, re-measure the view.
|
|
90
|
+
_measuredFittingSize = nil
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
override var intrinsicContentSize: CGSize {
|
|
95
|
+
_intrinsicContentSize
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#if os(macOS)
|
|
99
|
+
override func layout() {
|
|
100
|
+
super.layout()
|
|
101
|
+
|
|
102
|
+
// We need to re-measure the view whenever the size of the bounds changes, as the previous size
|
|
103
|
+
// may now be incorrect.
|
|
104
|
+
if latestMeasurementBoundsSize != nil, bounds.size != latestMeasurementBoundsSize {
|
|
105
|
+
// This will trigger SwiftUI to re-measure the view.
|
|
106
|
+
super.invalidateIntrinsicContentSize()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
#else
|
|
110
|
+
override func layoutSubviews() {
|
|
111
|
+
super.layoutSubviews()
|
|
112
|
+
|
|
113
|
+
// We need to re-measure the view whenever the size of the bounds changes, as the previous size
|
|
114
|
+
// may now be incorrect.
|
|
115
|
+
if latestMeasurementBoundsSize != nil, bounds.size != latestMeasurementBoundsSize {
|
|
116
|
+
// This will trigger SwiftUI to re-measure the view.
|
|
117
|
+
super.invalidateIntrinsicContentSize()
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
#endif
|
|
121
|
+
|
|
122
|
+
override func invalidateIntrinsicContentSize() {
|
|
123
|
+
super.invalidateIntrinsicContentSize()
|
|
124
|
+
|
|
125
|
+
// Invalidate the resolved strategy in case it changes with the re-measurement as it relies on
|
|
126
|
+
// the intrinsic size.
|
|
127
|
+
_resolvedStrategy = nil
|
|
128
|
+
_measuredFittingSize = nil
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// MARK: Private
|
|
132
|
+
|
|
133
|
+
/// The most recently measured intrinsic content size of the `uiView`, else `noIntrinsicMetric` if
|
|
134
|
+
/// it has not yet been measured.
|
|
135
|
+
///
|
|
136
|
+
/// Contains `UIView.noIntrinsicMetric` fallbacks for dimensions with no intrinsic size,
|
|
137
|
+
/// as compared to `measuredFittingSize` which has `proposedSize`/`bounds.size` fallbacks.
|
|
138
|
+
private var _intrinsicContentSize = CGSize.noIntrinsicMetric
|
|
139
|
+
|
|
140
|
+
/// The bounds size at the time of the latest measurement.
|
|
141
|
+
private var latestMeasurementBoundsSize: CGSize?
|
|
142
|
+
|
|
143
|
+
/// The most recently updated set of constraints constraining `uiView` to `self`.
|
|
144
|
+
private var uiViewConstraints = [NSLayoutConstraint.Attribute: NSLayoutConstraint]()
|
|
145
|
+
|
|
146
|
+
/// The cached `resolvedStrategy` to prevent unnecessary re-measurements.
|
|
147
|
+
private var _resolvedStrategy: ResolvedSwiftUIMeasurementContainerStrategy?
|
|
148
|
+
|
|
149
|
+
/// The cached `measuredFittingSize` to prevent unnecessary re-measurements.
|
|
150
|
+
private var _measuredFittingSize: CGSize?
|
|
151
|
+
|
|
152
|
+
/// The resolved measurement strategy.
|
|
153
|
+
private var resolvedStrategy: ResolvedSwiftUIMeasurementContainerStrategy {
|
|
154
|
+
if let resolvedStrategy = _resolvedStrategy {
|
|
155
|
+
return resolvedStrategy
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let resolved: ResolvedSwiftUIMeasurementContainerStrategy
|
|
159
|
+
switch strategy {
|
|
160
|
+
case .automatic:
|
|
161
|
+
// Perform an intrinsic size measurement pass, which gives us valid values for
|
|
162
|
+
// `UILabel.preferredMaxLayoutWidth`.
|
|
163
|
+
let intrinsicSize = content.systemLayoutFittingIntrinsicSize()
|
|
164
|
+
|
|
165
|
+
// If the view has a intrinsic width and contains a double layout pass subview, give it the
|
|
166
|
+
// proposed width to allow the label content to gracefully wrap to multiple lines.
|
|
167
|
+
if intrinsicSize.width > 0, content.containsDoubleLayoutPassSubviews() {
|
|
168
|
+
resolved = .intrinsicHeightProposedWidth
|
|
169
|
+
} else {
|
|
170
|
+
let zero = CGFloat(0)
|
|
171
|
+
switch (width: intrinsicSize.width, height: intrinsicSize.height) {
|
|
172
|
+
case (width: ...zero, height: ...zero):
|
|
173
|
+
resolved = .proposed
|
|
174
|
+
case (width: ...zero, height: zero.nextUp...):
|
|
175
|
+
resolved = .intrinsicHeightProposedWidth
|
|
176
|
+
case (width: zero.nextUp..., height: ...zero):
|
|
177
|
+
resolved = .intrinsicWidthProposedHeight
|
|
178
|
+
default:
|
|
179
|
+
resolved = .intrinsic(intrinsicSize)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
case .proposed:
|
|
184
|
+
resolved = .proposed
|
|
185
|
+
|
|
186
|
+
case .intrinsicHeightProposedWidth:
|
|
187
|
+
resolved = .intrinsicHeightProposedWidth
|
|
188
|
+
|
|
189
|
+
case .intrinsicWidthProposedHeight:
|
|
190
|
+
resolved = .intrinsicWidthProposedHeight
|
|
191
|
+
|
|
192
|
+
case .intrinsic:
|
|
193
|
+
resolved = .intrinsic(content.systemLayoutFittingIntrinsicSize())
|
|
194
|
+
}
|
|
195
|
+
_resolvedStrategy = resolved
|
|
196
|
+
return resolved
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private func setUpConstraints() {
|
|
200
|
+
content.translatesAutoresizingMaskIntoConstraints = false
|
|
201
|
+
|
|
202
|
+
let leading = content.leadingAnchor.constraint(equalTo: leadingAnchor)
|
|
203
|
+
let top = content.topAnchor.constraint(equalTo: topAnchor)
|
|
204
|
+
let trailing = content.trailingAnchor.constraint(equalTo: trailingAnchor)
|
|
205
|
+
let bottom = content.bottomAnchor.constraint(equalTo: bottomAnchor)
|
|
206
|
+
let newConstraints: [NSLayoutConstraint.Attribute: NSLayoutConstraint] = [
|
|
207
|
+
.leading: leading,
|
|
208
|
+
.top: top,
|
|
209
|
+
.trailing: trailing,
|
|
210
|
+
.bottom: bottom,
|
|
211
|
+
]
|
|
212
|
+
// Start with the lowest priority constraints so we aren't measuring the view too early, the
|
|
213
|
+
// priorities will be updated later on.
|
|
214
|
+
prioritizeConstraints(newConstraints, strategy: .intrinsic(.zero))
|
|
215
|
+
|
|
216
|
+
NSLayoutConstraint.deactivate(Array(uiViewConstraints.values))
|
|
217
|
+
uiViewConstraints = newConstraints
|
|
218
|
+
NSLayoutConstraint.activate(Array(uiViewConstraints.values))
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/// Prioritizes the given constraints based on the provided resolved strategy.
|
|
222
|
+
private func prioritizeConstraints(
|
|
223
|
+
_ constraints: [NSLayoutConstraint.Attribute: NSLayoutConstraint],
|
|
224
|
+
strategy: ResolvedSwiftUIMeasurementContainerStrategy
|
|
225
|
+
) {
|
|
226
|
+
// Give a required constraint in the dimensions that are fixed to the bounds, otherwise almost
|
|
227
|
+
// required.
|
|
228
|
+
switch strategy {
|
|
229
|
+
case .proposed:
|
|
230
|
+
constraints[.trailing]?.priority = .required
|
|
231
|
+
constraints[.bottom]?.priority = .required
|
|
232
|
+
|
|
233
|
+
case .intrinsicHeightProposedWidth:
|
|
234
|
+
constraints[.trailing]?.priority = .required
|
|
235
|
+
constraints[.bottom]?.priority = .almostRequired
|
|
236
|
+
|
|
237
|
+
case .intrinsicWidthProposedHeight:
|
|
238
|
+
constraints[.trailing]?.priority = .almostRequired
|
|
239
|
+
constraints[.bottom]?.priority = .required
|
|
240
|
+
|
|
241
|
+
case .intrinsic:
|
|
242
|
+
constraints[.trailing]?.priority = .almostRequired
|
|
243
|
+
constraints[.bottom]?.priority = .almostRequired
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#if os(macOS)
|
|
247
|
+
// On macOS, views default to having required constraints setting their height / width
|
|
248
|
+
// equal to their intrinsic content size. These have to be disabled in favor of the constraints
|
|
249
|
+
// we create here.
|
|
250
|
+
content.isVerticalContentSizeConstraintActive = false
|
|
251
|
+
content.isHorizontalContentSizeConstraintActive = false
|
|
252
|
+
#endif
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/// Measures the `uiView`, storing the resulting size in `measuredIntrinsicContentSize`.
|
|
256
|
+
private func measureView() -> CGSize {
|
|
257
|
+
latestMeasurementBoundsSize = bounds.size
|
|
258
|
+
prioritizeConstraints(uiViewConstraints, strategy: resolvedStrategy)
|
|
259
|
+
|
|
260
|
+
var measuredSize: CGSize
|
|
261
|
+
let proposedSizeElseBounds = proposedSize.replacingNoIntrinsicMetric(with: bounds.size)
|
|
262
|
+
|
|
263
|
+
switch resolvedStrategy {
|
|
264
|
+
case .proposed:
|
|
265
|
+
measuredSize = .noIntrinsicMetric
|
|
266
|
+
|
|
267
|
+
case .intrinsicHeightProposedWidth:
|
|
268
|
+
measuredSize = content.systemLayoutFittingIntrinsicHeightFixedWidth(proposedSizeElseBounds.width)
|
|
269
|
+
measuredSize.width = ViewType.noIntrinsicMetric
|
|
270
|
+
|
|
271
|
+
case .intrinsicWidthProposedHeight:
|
|
272
|
+
measuredSize = content.systemLayoutFittingIntrinsicWidthFixedHeight(proposedSizeElseBounds.height)
|
|
273
|
+
measuredSize.height = ViewType.noIntrinsicMetric
|
|
274
|
+
|
|
275
|
+
case .intrinsic(let size):
|
|
276
|
+
measuredSize = size
|
|
277
|
+
|
|
278
|
+
// If the measured size exceeds an available width or height, set the measured size to
|
|
279
|
+
// `noIntrinsicMetric` to ensure that the component can be compressed, otherwise it will
|
|
280
|
+
// overflow beyond the proposed size.
|
|
281
|
+
// - If the previous intrinsic content size is the same as the new proposed size, we don't
|
|
282
|
+
// do this as SwiftUI sometimes "proposes" the same intrinsic size back to the component and
|
|
283
|
+
// we don't want that scenario to prevent size changes when there is actually more space
|
|
284
|
+
// available.
|
|
285
|
+
if
|
|
286
|
+
proposedSize.width != ViewType.noIntrinsicMetric,
|
|
287
|
+
measuredSize.width > proposedSizeElseBounds.width,
|
|
288
|
+
_intrinsicContentSize.width != proposedSize.width
|
|
289
|
+
{
|
|
290
|
+
measuredSize.width = ViewType.noIntrinsicMetric
|
|
291
|
+
}
|
|
292
|
+
if
|
|
293
|
+
proposedSize.height != ViewType.noIntrinsicMetric,
|
|
294
|
+
measuredSize.height > proposedSizeElseBounds.height,
|
|
295
|
+
_intrinsicContentSize.height != proposedSize.height
|
|
296
|
+
{
|
|
297
|
+
measuredSize.height = ViewType.noIntrinsicMetric
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
_intrinsicContentSize = measuredSize
|
|
302
|
+
|
|
303
|
+
let measuredFittingSize = measuredSize.replacingNoIntrinsicMetric(with: proposedSizeElseBounds)
|
|
304
|
+
_measuredFittingSize = measuredFittingSize
|
|
305
|
+
return measuredFittingSize
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// MARK: - SwiftUIMeasurementContainerStrategy
|
|
310
|
+
|
|
311
|
+
/// The measurement strategy of a `SwiftUIMeasurementContainer`.
|
|
312
|
+
enum SwiftUIMeasurementContainerStrategy {
|
|
313
|
+
/// The container makes a best effort to correctly choose the measurement strategy of the view.
|
|
314
|
+
///
|
|
315
|
+
/// The best effort is based on a number of heuristics:
|
|
316
|
+
/// - The `uiView` will be given its intrinsic width and/or height when measurement in that
|
|
317
|
+
/// dimension produces a positive value, while zero/negative values will result in that
|
|
318
|
+
/// dimension receiving the available space proposed by the parent.
|
|
319
|
+
/// - If the view contains `UILabel` subviews that require a double layout pass as determined by
|
|
320
|
+
/// a `preferredMaxLayoutWidth` that's greater than zero after a layout, then the view will
|
|
321
|
+
/// default to `intrinsicHeightProposedWidth` to allow the labels to wrap.
|
|
322
|
+
///
|
|
323
|
+
/// If you would like to opt out of automatic sizing for performance or to override the default
|
|
324
|
+
/// behavior, choose another strategy.
|
|
325
|
+
case automatic
|
|
326
|
+
|
|
327
|
+
/// The `uiView` is sized to fill the area proposed by its parent.
|
|
328
|
+
///
|
|
329
|
+
/// Typically used for views that should expand greedily in both axes, e.g. a background view.
|
|
330
|
+
case proposed
|
|
331
|
+
|
|
332
|
+
/// The `uiView` is sized with its intrinsic height and expands horizontally to fill the width
|
|
333
|
+
/// proposed by its parent.
|
|
334
|
+
///
|
|
335
|
+
/// Typically used for views that have a height that's a function of their width, e.g. a row with
|
|
336
|
+
/// text that can wrap to multiple lines.
|
|
337
|
+
case intrinsicHeightProposedWidth
|
|
338
|
+
|
|
339
|
+
/// The `uiView` is sized with its intrinsic width and expands vertically to fill the height
|
|
340
|
+
/// proposed by its parent.
|
|
341
|
+
///
|
|
342
|
+
/// Typically used for views that are free to grow vertically but have a fixed width, e.g. a view
|
|
343
|
+
/// in a horizontal carousel.
|
|
344
|
+
case intrinsicWidthProposedHeight
|
|
345
|
+
|
|
346
|
+
/// The `uiView` is sized to its intrinsic width and height.
|
|
347
|
+
///
|
|
348
|
+
/// Typically used for components with a specific intrinsic size in both axes, e.g. controls or
|
|
349
|
+
/// inputs.
|
|
350
|
+
case intrinsic
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// MARK: - ResolvedSwiftUIMeasurementContainerStrategy
|
|
354
|
+
|
|
355
|
+
/// The resolved measurement strategy of a `SwiftUIMeasurementContainer`, matching the cases of the
|
|
356
|
+
/// `SwiftUIMeasurementContainerStrategy` without the automatic case.
|
|
357
|
+
private enum ResolvedSwiftUIMeasurementContainerStrategy {
|
|
358
|
+
case proposed
|
|
359
|
+
case intrinsicHeightProposedWidth
|
|
360
|
+
case intrinsicWidthProposedHeight
|
|
361
|
+
case intrinsic(CGSize)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// MARK: - UILayoutPriority
|
|
365
|
+
|
|
366
|
+
extension LayoutPriorityType {
|
|
367
|
+
/// An "almost required" constraint, useful for creating near-required constraints that don't
|
|
368
|
+
/// error when unable to be satisfied.
|
|
369
|
+
@nonobjc
|
|
370
|
+
fileprivate static var almostRequired: LayoutPriorityType {
|
|
371
|
+
.init(rawValue: required.rawValue - 1)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// MARK: - UIView
|
|
376
|
+
|
|
377
|
+
extension ViewType {
|
|
378
|
+
/// The `systemLayoutSizeFitting(…)` of this view with a compressed size and fitting priorities.
|
|
379
|
+
@nonobjc
|
|
380
|
+
fileprivate func systemLayoutFittingIntrinsicSize() -> CGSize {
|
|
381
|
+
#if os(macOS)
|
|
382
|
+
intrinsicContentSize
|
|
383
|
+
#else
|
|
384
|
+
systemLayoutSizeFitting(
|
|
385
|
+
UIView.layoutFittingCompressedSize,
|
|
386
|
+
withHorizontalFittingPriority: .fittingSizeLevel,
|
|
387
|
+
verticalFittingPriority: .fittingSizeLevel
|
|
388
|
+
)
|
|
389
|
+
#endif
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/// The `systemLayoutSizeFitting(…)` of this view with a compressed height with a fitting size
|
|
393
|
+
/// priority and with the given fixed width and fitting priority.
|
|
394
|
+
@nonobjc
|
|
395
|
+
fileprivate func systemLayoutFittingIntrinsicHeightFixedWidth(
|
|
396
|
+
_ width: CGFloat,
|
|
397
|
+
priority: LayoutPriorityType = .almostRequired
|
|
398
|
+
) -> CGSize {
|
|
399
|
+
#if os(macOS)
|
|
400
|
+
return CGSize(width: width, height: intrinsicContentSize.height)
|
|
401
|
+
#else
|
|
402
|
+
let targetSize = CGSize(width: width, height: UIView.layoutFittingCompressedSize.height)
|
|
403
|
+
|
|
404
|
+
return systemLayoutSizeFitting(
|
|
405
|
+
targetSize,
|
|
406
|
+
withHorizontalFittingPriority: priority,
|
|
407
|
+
verticalFittingPriority: .fittingSizeLevel
|
|
408
|
+
)
|
|
409
|
+
#endif
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/// The `systemLayoutSizeFitting(…)` of this view with a compressed width with a fitting size
|
|
413
|
+
/// priority and with the given fixed height and fitting priority.
|
|
414
|
+
@nonobjc
|
|
415
|
+
fileprivate func systemLayoutFittingIntrinsicWidthFixedHeight(
|
|
416
|
+
_ height: CGFloat,
|
|
417
|
+
priority: LayoutPriorityType = .almostRequired
|
|
418
|
+
) -> CGSize {
|
|
419
|
+
#if os(macOS)
|
|
420
|
+
return CGSize(width: intrinsicContentSize.width, height: height)
|
|
421
|
+
#else
|
|
422
|
+
let targetSize = CGSize(width: UIView.layoutFittingCompressedSize.width, height: height)
|
|
423
|
+
|
|
424
|
+
return systemLayoutSizeFitting(
|
|
425
|
+
targetSize,
|
|
426
|
+
withHorizontalFittingPriority: .fittingSizeLevel,
|
|
427
|
+
verticalFittingPriority: priority
|
|
428
|
+
)
|
|
429
|
+
#endif
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/// Whether this view or any of its subviews has a subview that has a double layout pass `UILabel`
|
|
433
|
+
/// as determined by a non-zero `preferredMaxLayoutWidth`, which implies that it should get a
|
|
434
|
+
/// `intrinsicHeightProposedWidth` sizing strategy to allow the label to wrap and grow.
|
|
435
|
+
@nonobjc
|
|
436
|
+
fileprivate func containsDoubleLayoutPassSubviews() -> Bool {
|
|
437
|
+
#if os(macOS)
|
|
438
|
+
return false
|
|
439
|
+
#else
|
|
440
|
+
var contains = false
|
|
441
|
+
if let label = self as? UILabel, label.preferredMaxLayoutWidth > 0 {
|
|
442
|
+
contains = true
|
|
443
|
+
}
|
|
444
|
+
for subview in subviews {
|
|
445
|
+
contains = contains || subview.containsDoubleLayoutPassSubviews()
|
|
446
|
+
}
|
|
447
|
+
return contains
|
|
448
|
+
#endif
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// MARK: - CGSize
|
|
453
|
+
|
|
454
|
+
extension CGSize {
|
|
455
|
+
/// A `CGSize` with `noIntrinsicMetric` for both its width and height.
|
|
456
|
+
fileprivate static var noIntrinsicMetric: CGSize {
|
|
457
|
+
.init(width: ViewType.noIntrinsicMetric, height: ViewType.noIntrinsicMetric)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/// Returns a `CGSize` with its width and/or height replaced with the corresponding field of the
|
|
461
|
+
/// provided `fallback` size if they are `UIView.noIntrinsicMetric`.
|
|
462
|
+
fileprivate func replacingNoIntrinsicMetric(with fallback: CGSize) -> CGSize {
|
|
463
|
+
.init(
|
|
464
|
+
width: width == ViewType.noIntrinsicMetric ? fallback.width : width,
|
|
465
|
+
height: height == ViewType.noIntrinsicMetric ? fallback.height : height
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Created by eric_horacek on 9/8/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
// MARK: - SwiftUIView
|
|
7
|
+
|
|
8
|
+
/// A `UIViewRepresentable` SwiftUI `View` that wraps its `Content` `UIView` within a
|
|
9
|
+
/// `SwiftUIMeasurementContainer`, used to size a UIKit view correctly within a SwiftUI view
|
|
10
|
+
/// hierarchy.
|
|
11
|
+
///
|
|
12
|
+
/// Includes an optional generic `Storage` value, which can be used to compare old and new values
|
|
13
|
+
/// across state changes to prevent redundant view updates.
|
|
14
|
+
struct SwiftUIView<Content: ViewType, Storage>: MeasuringViewRepresentable,
|
|
15
|
+
UIViewConfiguringSwiftUIView
|
|
16
|
+
{
|
|
17
|
+
|
|
18
|
+
// MARK: Lifecycle
|
|
19
|
+
|
|
20
|
+
/// Creates a SwiftUI representation of the content view with the given storage and the provided
|
|
21
|
+
/// `makeContent` closure to construct the content whenever `makeUIView(…)` is invoked.
|
|
22
|
+
init(storage: Storage, makeContent: @escaping () -> Content) {
|
|
23
|
+
self.storage = storage
|
|
24
|
+
self.makeContent = makeContent
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// Creates a SwiftUI representation of the content view with the provided `makeContent` closure
|
|
28
|
+
/// to construct it whenever `makeUIView(…)` is invoked.
|
|
29
|
+
init(makeContent: @escaping () -> Content) where Storage == Void {
|
|
30
|
+
storage = ()
|
|
31
|
+
self.makeContent = makeContent
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// MARK: Internal
|
|
35
|
+
|
|
36
|
+
var configurations = [Configuration]()
|
|
37
|
+
|
|
38
|
+
var sizing = SwiftUIMeasurementContainerStrategy.automatic
|
|
39
|
+
|
|
40
|
+
// MARK: Private
|
|
41
|
+
|
|
42
|
+
/// The current stored value, with the previous value provided to the configuration closure as
|
|
43
|
+
/// the `oldStorage`.
|
|
44
|
+
private var storage: Storage
|
|
45
|
+
|
|
46
|
+
/// A closure that's invoked to construct the represented content view.
|
|
47
|
+
private var makeContent: () -> Content
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// MARK: UIViewRepresentable
|
|
51
|
+
|
|
52
|
+
extension SwiftUIView {
|
|
53
|
+
func makeCoordinator() -> Coordinator {
|
|
54
|
+
Coordinator(storage: storage)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#if os(macOS)
|
|
58
|
+
func makeNSView(context _: Context) -> SwiftUIMeasurementContainer<Content> {
|
|
59
|
+
SwiftUIMeasurementContainer(content: makeContent(), strategy: sizing)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
func updateNSView(_ uiView: SwiftUIMeasurementContainer<Content>, context: Context) {
|
|
63
|
+
let oldStorage = context.coordinator.storage
|
|
64
|
+
context.coordinator.storage = storage
|
|
65
|
+
|
|
66
|
+
let configurationContext = ConfigurationContext(
|
|
67
|
+
oldStorage: oldStorage,
|
|
68
|
+
viewRepresentableContext: context,
|
|
69
|
+
container: uiView
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
for configuration in configurations {
|
|
73
|
+
configuration(configurationContext)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
#else
|
|
77
|
+
func makeUIView(context _: Context) -> SwiftUIMeasurementContainer<Content> {
|
|
78
|
+
SwiftUIMeasurementContainer(content: makeContent(), strategy: sizing)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
func updateUIView(_ uiView: SwiftUIMeasurementContainer<Content>, context: Context) {
|
|
82
|
+
let oldStorage = context.coordinator.storage
|
|
83
|
+
context.coordinator.storage = storage
|
|
84
|
+
|
|
85
|
+
let configurationContext = ConfigurationContext(
|
|
86
|
+
oldStorage: oldStorage,
|
|
87
|
+
viewRepresentableContext: context,
|
|
88
|
+
container: uiView
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for configuration in configurations {
|
|
92
|
+
configuration(configurationContext)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
#endif
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// MARK: SwiftUIView.ConfigurationContext
|
|
99
|
+
|
|
100
|
+
extension SwiftUIView {
|
|
101
|
+
/// The configuration context that's available to configure the `Content` view whenever the
|
|
102
|
+
/// `updateUIView()` method is invoked via a configuration closure.
|
|
103
|
+
struct ConfigurationContext: ViewProviding {
|
|
104
|
+
/// The previous value for the `Storage` of this `SwiftUIView`, which can be used to store
|
|
105
|
+
/// values across state changes to prevent redundant view updates.
|
|
106
|
+
var oldStorage: Storage
|
|
107
|
+
|
|
108
|
+
/// The `UIViewRepresentable.Context`, with information about the transaction and environment.
|
|
109
|
+
var viewRepresentableContext: Context
|
|
110
|
+
|
|
111
|
+
/// The backing measurement container that contains the `Content`.
|
|
112
|
+
var container: SwiftUIMeasurementContainer<Content>
|
|
113
|
+
|
|
114
|
+
/// The `UIView` content that's being configured.
|
|
115
|
+
///
|
|
116
|
+
/// Setting this to a new value updates the backing measurement container's `content`.
|
|
117
|
+
var view: Content {
|
|
118
|
+
get { container.content }
|
|
119
|
+
nonmutating set { container.content = newValue }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// A convenience accessor indicating whether this content update should be animated.
|
|
123
|
+
var animated: Bool {
|
|
124
|
+
viewRepresentableContext.transaction.animation != nil
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// MARK: SwiftUIView.Coordinator
|
|
130
|
+
|
|
131
|
+
extension SwiftUIView {
|
|
132
|
+
/// A coordinator that stores the `storage` associated with this view, enabling the old storage
|
|
133
|
+
/// value to be accessed during the `updateUIView(…)`.
|
|
134
|
+
final class Coordinator {
|
|
135
|
+
|
|
136
|
+
// MARK: Lifecycle
|
|
137
|
+
|
|
138
|
+
fileprivate init(storage: Storage) {
|
|
139
|
+
self.storage = storage
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// MARK: Internal
|
|
143
|
+
|
|
144
|
+
fileprivate(set) var storage: Storage
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Created by eric_horacek on 3/3/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
// MARK: - ViewTypeProtocol + swiftUIView
|
|
7
|
+
|
|
8
|
+
extension ViewTypeProtocol {
|
|
9
|
+
/// Returns a SwiftUI `View` representing this `UIView`, constructed with the given `makeView`
|
|
10
|
+
/// closure and sized with the given sizing configuration.
|
|
11
|
+
///
|
|
12
|
+
/// To perform additional configuration of the `UIView` instance, call `configure` on the
|
|
13
|
+
/// returned SwiftUI `View`:
|
|
14
|
+
/// ```
|
|
15
|
+
/// MyUIView.swiftUIView(…)
|
|
16
|
+
/// .configure { context in
|
|
17
|
+
/// context.view.doSomething()
|
|
18
|
+
/// }
|
|
19
|
+
/// ```
|
|
20
|
+
///
|
|
21
|
+
/// To configure the sizing behavior of the `UIView` instance, call `sizing` on the returned
|
|
22
|
+
/// SwiftUI `View`:
|
|
23
|
+
/// ```
|
|
24
|
+
/// MyView.swiftUIView(…).sizing(.intrinsicSize)
|
|
25
|
+
/// ```
|
|
26
|
+
/// The sizing defaults to `.automatic`.
|
|
27
|
+
static func swiftUIView(makeView: @escaping () -> Self) -> SwiftUIView<Self, Void> {
|
|
28
|
+
SwiftUIView(makeContent: makeView)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// MARK: - ViewTypeProtocol
|
|
33
|
+
|
|
34
|
+
/// A protocol that all `UIView`s conform to, enabling extensions that have a `Self` reference.
|
|
35
|
+
protocol ViewTypeProtocol: ViewType { }
|
|
36
|
+
|
|
37
|
+
// MARK: - ViewType + ViewTypeProtocol
|
|
38
|
+
|
|
39
|
+
extension ViewType: ViewTypeProtocol { }
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Created by eric_horacek on 3/4/22.
|
|
2
|
+
// Copyright © 2022 Airbnb Inc. All rights reserved.
|
|
3
|
+
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
// MARK: - UIViewConfiguringSwiftUIView
|
|
7
|
+
|
|
8
|
+
/// A protocol describing a SwiftUI `View` that can configure its `UIView` content via an array of
|
|
9
|
+
/// `configuration` closures.
|
|
10
|
+
protocol UIViewConfiguringSwiftUIView: View {
|
|
11
|
+
/// The context available to this configuration, which provides the `UIView` instance at a minimum
|
|
12
|
+
/// but can include additional context as needed.
|
|
13
|
+
associatedtype ConfigurationContext: ViewProviding
|
|
14
|
+
|
|
15
|
+
/// A closure that is invoked to configure the represented content view.
|
|
16
|
+
typealias Configuration = (ConfigurationContext) -> Void
|
|
17
|
+
|
|
18
|
+
/// A mutable array of configuration closures that should each be invoked with the
|
|
19
|
+
/// `ConfigurationContext` whenever `updateUIView` is called in a `UIViewRepresentable`.
|
|
20
|
+
var configurations: [Configuration] { get set }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MARK: Extensions
|
|
24
|
+
|
|
25
|
+
extension UIViewConfiguringSwiftUIView {
|
|
26
|
+
/// Returns a copy of this view updated to have the given closure applied to its represented view
|
|
27
|
+
/// whenever it is updated via the `updateUIView(…)` method.
|
|
28
|
+
func configure(_ configure: @escaping Configuration) -> Self {
|
|
29
|
+
var copy = self
|
|
30
|
+
copy.configurations.append(configure)
|
|
31
|
+
return copy
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Returns a copy of this view updated to have the given closures applied to its represented view
|
|
35
|
+
/// whenever it is updated via the `updateUIView(…)` method.
|
|
36
|
+
func configurations(_ configurations: [Configuration]) -> Self {
|
|
37
|
+
var copy = self
|
|
38
|
+
copy.configurations.append(contentsOf: configurations)
|
|
39
|
+
return copy
|
|
40
|
+
}
|
|
41
|
+
}
|