@swiftbrowser/swift 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. package/Package.swift +200 -9
  2. package/README.md +7 -9
  3. package/Sources/AVFoundation/AVFoundation.swift +131 -0
  4. package/Sources/AVFoundation/Asset.swift +487 -0
  5. package/Sources/AVFoundation/AudioSession.swift +144 -0
  6. package/Sources/AVFoundation/CMTime.swift +303 -0
  7. package/Sources/AVFoundation/Capture.swift +688 -0
  8. package/Sources/AVFoundation/Player.swift +749 -0
  9. package/Sources/AVFoundation/PlayerView.swift +117 -0
  10. package/Sources/AVKit/AVKit.swift +132 -0
  11. package/Sources/Accelerate/Accelerate.swift +122 -0
  12. package/Sources/AppIntents/AppIntents.swift +144 -0
  13. package/Sources/AppIntents/Parameters.swift +220 -0
  14. package/Sources/AppIntents/Shortcuts.swift +159 -0
  15. package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
  16. package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
  17. package/Sources/AuthenticationServices/Authorization.swift +251 -0
  18. package/Sources/Charts/Charts.swift +0 -4
  19. package/Sources/Combine/AnyCancellable.swift +65 -0
  20. package/Sources/Combine/AnyPublisher.swift +148 -0
  21. package/Sources/Combine/AnySubscriber.swift +230 -0
  22. package/Sources/Combine/Cancellable.swift +35 -0
  23. package/Sources/Combine/Codable.swift +29 -0
  24. package/Sources/Combine/CombineIdentifier.swift +45 -0
  25. package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
  26. package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
  27. package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
  28. package/Sources/Combine/CurrentValueSubject.swift +252 -0
  29. package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
  30. package/Sources/Combine/Future.swift +228 -0
  31. package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
  32. package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
  33. package/Sources/Combine/Helpers/ConduitList.swift +59 -0
  34. package/Sources/Combine/Helpers/DebugHook.swift +177 -0
  35. package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
  36. package/Sources/Combine/Helpers/Locking.swift +30 -0
  37. package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
  38. package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
  39. package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
  40. package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
  41. package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
  42. package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
  43. package/Sources/Combine/Helpers/Utils.swift +30 -0
  44. package/Sources/Combine/Helpers/Violations.swift +33 -0
  45. package/Sources/Combine/ImmediateScheduler.swift +178 -0
  46. package/Sources/Combine/LICENSE +21 -0
  47. package/Sources/Combine/NotificationPublisher.swift +48 -0
  48. package/Sources/Combine/ObjectWillChange.swift +46 -0
  49. package/Sources/Combine/PassthroughSubject.swift +222 -0
  50. package/Sources/Combine/Publisher+Subscribe.swift +53 -0
  51. package/Sources/Combine/Publishers/Deferred.swift +48 -0
  52. package/Sources/Combine/Publishers/Empty.swift +54 -0
  53. package/Sources/Combine/Publishers/Fail.swift +42 -0
  54. package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
  55. package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
  56. package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
  57. package/Sources/Combine/Publishers/Just.swift +313 -0
  58. package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
  59. package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
  60. package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
  61. package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
  62. package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
  63. package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
  64. package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
  65. package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
  66. package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
  67. package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
  68. package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
  69. package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
  70. package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
  71. package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
  72. package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
  73. package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
  74. package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
  75. package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
  76. package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
  77. package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
  78. package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
  79. package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
  80. package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
  81. package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
  82. package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
  83. package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
  84. package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
  85. package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
  86. package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
  87. package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
  88. package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
  89. package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
  90. package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
  91. package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
  92. package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
  93. package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
  94. package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
  95. package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
  96. package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
  97. package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
  98. package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
  99. package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
  100. package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
  101. package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
  102. package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
  103. package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
  104. package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
  105. package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
  106. package/Sources/Combine/Publishers/Publishers.swift +13 -0
  107. package/Sources/Combine/Publishers/Record.swift +237 -0
  108. package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
  109. package/Sources/Combine/Result.swift +46 -0
  110. package/Sources/Combine/Scheduler.swift +89 -0
  111. package/Sources/Combine/Schedulers.swift +211 -0
  112. package/Sources/Combine/Subject+Void.swift +17 -0
  113. package/Sources/Combine/Subscriber+Void.swift +20 -0
  114. package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
  115. package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
  116. package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
  117. package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
  118. package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
  119. package/Sources/Combine/Subscription.swift +22 -0
  120. package/Sources/Combine/Subscriptions.swift +42 -0
  121. package/Sources/Combine/SwiftUIObservation.swift +10 -0
  122. package/Sources/Combine/_Introspection.swift +107 -0
  123. package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
  124. package/Sources/Compression/Compression.swift +365 -0
  125. package/Sources/Compression/Deflate.swift +407 -0
  126. package/Sources/Compression/Zlib.swift +179 -0
  127. package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
  128. package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
  129. package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
  130. package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
  131. package/Sources/CoreImage/CIColor.swift +41 -0
  132. package/Sources/CoreImage/CIContext.swift +31 -0
  133. package/Sources/CoreImage/CIDetector.swift +57 -0
  134. package/Sources/CoreImage/CIFilter.swift +243 -0
  135. package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
  136. package/Sources/CoreImage/CIImage.swift +162 -0
  137. package/Sources/CoreImage/QRCode.swift +393 -0
  138. package/Sources/CoreLocation/Coordinate.swift +30 -0
  139. package/Sources/CoreLocation/Location.swift +65 -0
  140. package/Sources/CoreML/Evaluation.swift +414 -0
  141. package/Sources/CoreML/FeatureValue.swift +266 -0
  142. package/Sources/CoreML/Model.swift +269 -0
  143. package/Sources/CoreML/MultiArray.swift +92 -0
  144. package/Sources/CoreML/Specification.swift +233 -0
  145. package/Sources/CoreText/CoreText.swift +64 -0
  146. package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
  147. package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
  148. package/Sources/CryptoKit/CryptoKit.swift +375 -0
  149. package/Sources/CryptoKit/Curve25519.swift +317 -0
  150. package/Sources/CryptoKit/P256.swift +321 -0
  151. package/Sources/FoundationBridge/AppStorage.swift +165 -0
  152. package/Sources/FoundationBridge/AssetResources.swift +90 -0
  153. package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
  154. package/Sources/FoundationBridge/AsyncImage.swift +116 -0
  155. package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
  156. package/Sources/{_FoundationCommon → FoundationBridge}/Bundle.swift +41 -4
  157. package/Sources/FoundationBridge/CombineExports.swift +8 -0
  158. package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
  159. package/Sources/FoundationBridge/Dispatch.swift +458 -0
  160. package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
  161. package/Sources/FoundationBridge/FileImporter.swift +128 -0
  162. package/Sources/FoundationBridge/FileSystem.swift +68 -0
  163. package/Sources/FoundationBridge/FoundationBridge.swift +24 -72
  164. package/Sources/FoundationBridge/HostResolution.swift +31 -0
  165. package/Sources/FoundationBridge/ItemProvider.swift +655 -0
  166. package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
  167. package/Sources/FoundationBridge/Links.swift +127 -0
  168. package/Sources/FoundationBridge/ListFormatter.swift +32 -0
  169. package/Sources/FoundationBridge/Localization.swift +149 -0
  170. package/Sources/FoundationBridge/Locks.swift +50 -0
  171. package/Sources/FoundationBridge/Markdown.swift +527 -0
  172. package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
  173. package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
  174. package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
  175. package/Sources/FoundationBridge/Operation.swift +195 -0
  176. package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
  177. package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
  178. package/Sources/FoundationBridge/SceneStorage.swift +78 -0
  179. package/Sources/FoundationBridge/SecurityExports.swift +8 -0
  180. package/Sources/FoundationBridge/Selector.swift +226 -0
  181. package/Sources/FoundationBridge/StringComparators.swift +17 -0
  182. package/Sources/FoundationBridge/Table.swift +211 -0
  183. package/Sources/FoundationBridge/TextAttributes.swift +42 -0
  184. package/Sources/FoundationBridge/Timer.swift +6 -1
  185. package/Sources/FoundationBridge/URLSession.swift +718 -0
  186. package/Sources/{_FoundationCommon → FoundationBridge}/UserDefaults.swift +17 -4
  187. package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
  188. package/Sources/FoundationBridge/WebSocket.swift +187 -0
  189. package/Sources/FoundationModels/FoundationModels.swift +1098 -0
  190. package/Sources/ImageIO/GIF.swift +72 -0
  191. package/Sources/ImageIO/ImageIO.swift +248 -0
  192. package/Sources/ImageIO/ImageTypes.swift +28 -0
  193. package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
  194. package/Sources/LocalAuthentication/LAContext.swift +86 -0
  195. package/Sources/MapKit/Geometry.swift +223 -0
  196. package/Sources/MapKit/Map.swift +638 -0
  197. package/Sources/MapKit/MapView.swift +229 -0
  198. package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
  199. package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
  200. package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
  201. package/Sources/OSLog/OSLog.swift +6 -0
  202. package/Sources/Photos/Photos.swift +572 -0
  203. package/Sources/PhotosUI/PhotosPicker.swift +248 -0
  204. package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
  205. package/Sources/QuickLook/QuickLook.swift +168 -0
  206. package/Sources/SafariServices/SafariServices.swift +106 -0
  207. package/Sources/Security/Security.swift +332 -0
  208. package/Sources/StoreKit/AppStore.swift +207 -0
  209. package/Sources/StoreKit/Products.swift +280 -0
  210. package/Sources/StoreKit/RequestReview.swift +28 -0
  211. package/Sources/StoreKit/StoreKit1.swift +486 -0
  212. package/Sources/StoreKit/StoreViews.swift +428 -0
  213. package/Sources/StoreKit/Transactions.swift +197 -0
  214. package/Sources/SwiftData/Macros.swift +58 -0
  215. package/Sources/SwiftData/ModelActor.swift +38 -0
  216. package/Sources/SwiftData/ModelContainer.swift +129 -0
  217. package/Sources/SwiftData/ModelContext.swift +451 -0
  218. package/Sources/SwiftData/PersistentModel.swift +238 -0
  219. package/Sources/SwiftData/Properties.swift +261 -0
  220. package/Sources/SwiftData/Query.swift +256 -0
  221. package/Sources/SwiftData/Schema.swift +192 -0
  222. package/Sources/SwiftData/Store.swift +146 -0
  223. package/Sources/SwiftData/StringPredicates.swift +125 -0
  224. package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
  225. package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
  226. package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
  227. package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
  228. package/Sources/SwiftDataMacros/Plugin.swift +18 -0
  229. package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
  230. package/Sources/SwiftUI/API/Accessibility.swift +55 -6
  231. package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
  232. package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
  233. package/Sources/SwiftUI/API/Alert.swift +1 -1
  234. package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
  235. package/Sources/SwiftUI/API/Animation.swift +37 -5
  236. package/Sources/SwiftUI/API/App.swift +31 -1
  237. package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
  238. package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
  239. package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
  240. package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
  241. package/Sources/SwiftUI/API/Canvas.swift +337 -0
  242. package/Sources/SwiftUI/API/Color.swift +104 -28
  243. package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
  244. package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
  245. package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
  246. package/Sources/SwiftUI/API/Commands.swift +106 -0
  247. package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
  248. package/Sources/SwiftUI/API/ContentShape.swift +33 -0
  249. package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
  250. package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
  251. package/Sources/SwiftUI/API/Controls.swift +59 -27
  252. package/Sources/SwiftUI/API/CustomLayout.swift +49 -10
  253. package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
  254. package/Sources/SwiftUI/API/Decorations.swift +1 -1
  255. package/Sources/SwiftUI/API/EditMode.swift +25 -82
  256. package/Sources/SwiftUI/API/Effects.swift +105 -7
  257. package/Sources/SwiftUI/API/Entry.swift +8 -0
  258. package/Sources/SwiftUI/API/Environment.swift +93 -9
  259. package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
  260. package/Sources/SwiftUI/API/Focus.swift +11 -3
  261. package/Sources/SwiftUI/API/Gauge.swift +3 -2
  262. package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
  263. package/Sources/SwiftUI/API/GeometryReader.swift +13 -2
  264. package/Sources/SwiftUI/API/GestureState.swift +65 -0
  265. package/Sources/SwiftUI/API/Gestures.swift +1 -1
  266. package/Sources/SwiftUI/API/Glass.swift +127 -0
  267. package/Sources/SwiftUI/API/Grid.swift +1 -1
  268. package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
  269. package/Sources/SwiftUI/API/KeyPress.swift +54 -0
  270. package/Sources/SwiftUI/API/LabelStyle.swift +13 -6
  271. package/Sources/SwiftUI/API/Layout.swift +67 -12
  272. package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
  273. package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
  274. package/Sources/SwiftUI/API/Lists.swift +61 -6
  275. package/Sources/SwiftUI/API/Menu.swift +8 -1
  276. package/Sources/SwiftUI/API/Modifiers.swift +80 -10
  277. package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
  278. package/Sources/SwiftUI/API/Namespace.swift +44 -0
  279. package/Sources/SwiftUI/API/Navigation.swift +24 -9
  280. package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
  281. package/Sources/SwiftUI/API/ObservableObject.swift +16 -2
  282. package/Sources/SwiftUI/API/Path.swift +543 -0
  283. package/Sources/SwiftUI/API/Phase8Controls.swift +48 -31
  284. package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
  285. package/Sources/SwiftUI/API/Picker.swift +11 -2
  286. package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
  287. package/Sources/SwiftUI/API/Popover.swift +41 -0
  288. package/Sources/SwiftUI/API/Preferences.swift +262 -0
  289. package/Sources/SwiftUI/API/Presentation.swift +17 -4
  290. package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
  291. package/Sources/SwiftUI/API/Primitives.swift +164 -37
  292. package/Sources/SwiftUI/API/Publishers.swift +4 -4
  293. package/Sources/SwiftUI/API/Redaction.swift +75 -0
  294. package/Sources/SwiftUI/API/RowActions.swift +3 -2
  295. package/Sources/SwiftUI/API/Scenes.swift +131 -0
  296. package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
  297. package/Sources/SwiftUI/API/ScrollTargets.swift +3 -3
  298. package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
  299. package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
  300. package/Sources/SwiftUI/API/Shape.swift +214 -0
  301. package/Sources/SwiftUI/API/ShapeStyle.swift +105 -7
  302. package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
  303. package/Sources/SwiftUI/API/Sharing.swift +193 -0
  304. package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
  305. package/Sources/SwiftUI/API/State.swift +18 -1
  306. package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
  307. package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
  308. package/Sources/SwiftUI/API/TabContent.swift +841 -0
  309. package/Sources/SwiftUI/API/Table.swift +382 -0
  310. package/Sources/SwiftUI/API/Tabs.swift +148 -4
  311. package/Sources/SwiftUI/API/Tasks.swift +2 -2
  312. package/Sources/SwiftUI/API/Text.swift +386 -0
  313. package/Sources/SwiftUI/API/TextDates.swift +61 -0
  314. package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
  315. package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
  316. package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
  317. package/Sources/SwiftUI/API/Toolbar.swift +52 -16
  318. package/Sources/SwiftUI/API/Transfer.swift +145 -0
  319. package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
  320. package/Sources/SwiftUI/API/Video.swift +64 -0
  321. package/Sources/SwiftUI/API/View.swift +10 -2
  322. package/Sources/SwiftUI/API/ViewModifier.swift +4 -1
  323. package/Sources/SwiftUI/API/VisualEffect.swift +74 -1
  324. package/Sources/SwiftUI/API/Windows.swift +25 -0
  325. package/Sources/SwiftUI/Charts/Axis.swift +7 -1
  326. package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
  327. package/Sources/SwiftUI/Charts/Chart.swift +17 -3
  328. package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
  329. package/Sources/SwiftUI/Localization/Localization.swift +498 -0
  330. package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
  331. package/Sources/SwiftUI/Runtime/Executor.swift +2 -0
  332. package/Sources/SwiftUI/Runtime/Exports.swift +37 -1
  333. package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
  334. package/Sources/SwiftUI/Runtime/JSON.swift +76 -4
  335. package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
  336. package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
  337. package/Sources/SwiftUI/Runtime/Ops.swift +58 -12
  338. package/Sources/SwiftUI/Runtime/Reconciler.swift +10 -1
  339. package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
  340. package/Sources/SwiftUI/Runtime/Runtime.swift +977 -198
  341. package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
  342. package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
  343. package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
  344. package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
  345. package/Sources/Symbols/Symbols.swift +25 -0
  346. package/Sources/Translation/Translation.swift +423 -0
  347. package/Sources/UIKit/Activity.swift +213 -0
  348. package/Sources/UIKit/Alerts.swift +69 -0
  349. package/Sources/UIKit/AppDelegate.swift +222 -0
  350. package/Sources/UIKit/Appearance.swift +84 -0
  351. package/Sources/UIKit/ColorConversions.swift +70 -0
  352. package/Sources/UIKit/Controls.swift +225 -0
  353. package/Sources/UIKit/Device.swift +200 -0
  354. package/Sources/UIKit/Feedback.swift +65 -0
  355. package/Sources/UIKit/Font.swift +307 -0
  356. package/Sources/UIKit/Graphics.swift +204 -0
  357. package/Sources/UIKit/HostingController.swift +185 -0
  358. package/Sources/UIKit/Identity.swift +24 -0
  359. package/Sources/UIKit/Introspectable.swift +510 -0
  360. package/Sources/UIKit/Pasteboard.swift +363 -0
  361. package/Sources/UIKit/PhotoAlbum.swift +81 -0
  362. package/Sources/UIKit/RemoteNotifications.swift +15 -0
  363. package/Sources/UIKit/Representable.swift +288 -0
  364. package/Sources/UIKit/SafeArea.swift +12 -0
  365. package/Sources/UIKit/SceneDelegates.swift +132 -0
  366. package/Sources/UIKit/Scenes.swift +40 -0
  367. package/Sources/UIKit/ScrollView.swift +157 -0
  368. package/Sources/UIKit/ShortcutItems.swift +67 -0
  369. package/Sources/UIKit/SymbolConfiguration.swift +124 -0
  370. package/Sources/UIKit/TargetAction.swift +123 -0
  371. package/Sources/UIKit/TextPaste.swift +161 -0
  372. package/Sources/UIKit/TextView.swift +538 -0
  373. package/Sources/UIKit/UIKit.swift +292 -0
  374. package/Sources/UIKit/UIView.swift +855 -0
  375. package/Sources/UIKit/ViewTranslation.swift +311 -0
  376. package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
  377. package/Sources/UserNotifications/Content.swift +370 -0
  378. package/Sources/UserNotifications/NotificationCenter.swift +309 -0
  379. package/Sources/WeatherKit/WeatherKit.swift +228 -0
  380. package/Sources/WebKit/WebKit.swift +245 -0
  381. package/Sources/os/os.swift +376 -0
  382. package/Sources/zlib/zlib.swift +6 -0
  383. package/index.d.ts +1 -1
  384. package/index.mjs +2 -2
  385. package/manifest.d.mts +2 -0
  386. package/manifest.mjs +39 -0
  387. package/package.json +5 -3
  388. package/sync-sources.mjs +21 -7
  389. package/Sources/FoundationLite/Common.swift +0 -3
  390. package/Sources/FoundationLite/FoundationLite.swift +0 -171
  391. package/Sources/FoundationLite/Interaction.swift +0 -146
  392. package/Sources/FoundationLite/Timer.swift +0 -48
  393. package/Sources/_FoundationCommon/_FoundationCommon.swift +0 -10
@@ -0,0 +1,254 @@
1
+ import Foundation
2
+
3
+ // `UIImage` and `CGImage`, as far as SwiftUI apps use them: made from an
4
+ // image file's bytes, from Core Image (Sources/CoreImage), from an SF Symbol
5
+ // or a catalog name, and shown with `Image(uiImage:)`. On iOS SwiftUI
6
+ // re-exports UIKit's `UIImage` and Core Graphics' `CGImage`, so a file that
7
+ // imports SwiftUI alone uses both; here they live in the shim for the same
8
+ // reason. Neither holds pixels: each is a recipe the page draws
9
+ // (Runtime/ImageSource.swift, docs/ops-protocol.md, "Bitmaps and Core Image").
10
+
11
+ /// A bitmap: `width` × `height` pixels the page produces from a recipe.
12
+ public final class CGImage: @unchecked Sendable {
13
+ public let width: Int
14
+ public let height: Int
15
+ /// The recipe, ending at this image's pixel grid (extent `(0, 0, width, height)`).
16
+ public let _recipe: _ImageRecipe
17
+
18
+ /// Made by Core Image (`CIContext.createCGImage`) from a rendered recipe.
19
+ public init(_recipe recipe: _ImageRecipe) {
20
+ _recipe = recipe
21
+ let extent = recipe.extent.isNull || recipe.extent.isInfinite ? CGRect.zero : recipe.extent
22
+ width = Int(extent.width)
23
+ height = Int(extent.height)
24
+ }
25
+
26
+ public var bitsPerComponent: Int { 8 }
27
+ public var bitsPerPixel: Int { 32 }
28
+ public var bytesPerRow: Int { width * 4 }
29
+
30
+ /// The part of the image inside `rect` (pixels, origin at the top left),
31
+ /// clipped to the image; nil when they do not overlap.
32
+ public func cropping(to rect: CGRect) -> CGImage? {
33
+ let bounds = CGRect(x: 0, y: 0, width: Double(width), height: Double(height))
34
+ let box = rect.integral.intersection(bounds)
35
+ guard !box.isNull, box.width >= 1, box.height >= 1 else { return nil }
36
+ // Core Image's origin is at the bottom left.
37
+ let flipped = CGRect(x: box.minX, y: Double(height) - box.maxY, width: box.width, height: box.height)
38
+ return _recipe.rendered(in: flipped).map(CGImage.init(_recipe:))
39
+ }
40
+ }
41
+
42
+ /// UIKit's image: a bitmap with a scale (pixels per point), or an SF Symbol
43
+ /// or asset-catalog image the page draws by name.
44
+ public final class UIImage: Hashable, @unchecked Sendable {
45
+ public enum Orientation: Int, Sendable {
46
+ case up, down, left, right, upMirrored, downMirrored, leftMirrored, rightMirrored
47
+ }
48
+
49
+ enum Content {
50
+ case bitmap(_ImageRecipe)
51
+ case system(String)
52
+ case named(String)
53
+ }
54
+
55
+ let content: Content
56
+ /// The size in points: pixels ÷ `scale`.
57
+ public let size: CGSize
58
+ public let scale: CGFloat
59
+ /// Always `.up` for decoded files: the page draws them with their EXIF
60
+ /// rotation applied, and their size already accounts for it.
61
+ public let imageOrientation: Orientation
62
+ /// The `CIImage` a Core Image-backed image was made from (`UIImage(ciImage:)`).
63
+ public let _ciImage: AnyObject?
64
+ /// UIKit's `renderingMode`: 0 automatic, 1 always original, 2 always template.
65
+ public private(set) var _renderingMode = 0
66
+
67
+ private init(content: Content, size: CGSize, scale: CGFloat, orientation: Orientation, ciImage: AnyObject?) {
68
+ self.content = content
69
+ self.size = size
70
+ self.scale = scale
71
+ imageOrientation = orientation
72
+ _ciImage = ciImage
73
+ }
74
+
75
+ /// The same image with another rendering mode (UIKit's `withRenderingMode`),
76
+ /// or another bitmap of the same size (`withTintColor`).
77
+ public func _copy(recipe: _ImageRecipe? = nil, renderingMode: Int) -> UIImage {
78
+ let copy = UIImage(content: recipe.map(Content.bitmap) ?? content, size: size, scale: scale, orientation: imageOrientation,
79
+ ciImage: recipe == nil ? _ciImage : nil)
80
+ copy._renderingMode = renderingMode
81
+ return copy
82
+ }
83
+
84
+ /// Whether the image is an SF Symbol (drawn by the page by name).
85
+ public var _isSymbol: Bool {
86
+ if case .system = content { return true }
87
+ return false
88
+ }
89
+
90
+ /// An empty image, 0 × 0.
91
+ public init() {
92
+ content = .bitmap(.empty)
93
+ size = .zero
94
+ scale = 1
95
+ imageOrientation = .up
96
+ _ciImage = nil
97
+ }
98
+
99
+ /// The image in a PNG, JPEG, GIF, WebP, BMP, HEIC or AVIF file; nil when
100
+ /// the data is not one. Only the header is read here; the page decodes
101
+ /// the file when it draws it. (Chromium and Firefox draw no HEIC.)
102
+ public convenience init?(data: Data) {
103
+ self.init(data: data, scale: 1)
104
+ }
105
+
106
+ public init?(data: Data, scale: CGFloat) {
107
+ guard let source = _ImageSource(encoded: [UInt8](data)) else { return nil }
108
+ let factor = scale > 0 ? scale : 1
109
+ content = .bitmap(_ImageRecipe(source: source))
110
+ size = CGSize(width: Double(source.width) / factor, height: Double(source.height) / factor)
111
+ self.scale = factor
112
+ imageOrientation = .up
113
+ _ciImage = nil
114
+ }
115
+
116
+ public convenience init(cgImage: CGImage) {
117
+ self.init(cgImage: cgImage, scale: 1, orientation: .up)
118
+ }
119
+
120
+ /// `orientation` is recorded, not applied: the page draws the bitmap upright.
121
+ public init(cgImage: CGImage, scale: CGFloat, orientation: Orientation) {
122
+ let factor = scale > 0 ? scale : 1
123
+ content = .bitmap(cgImage._recipe)
124
+ size = CGSize(width: Double(cgImage.width) / factor, height: Double(cgImage.height) / factor)
125
+ self.scale = factor
126
+ imageOrientation = orientation
127
+ _ciImage = nil
128
+ }
129
+
130
+ /// A bitmap from a recipe whose extent is its pixel grid, `(0, 0, w, h)`
131
+ /// (Core Image's `UIImage(ciImage:)`).
132
+ public init(_recipe recipe: _ImageRecipe, scale: CGFloat, ciImage: AnyObject?) {
133
+ let factor = scale > 0 ? scale : 1
134
+ let extent = recipe.extent.isNull || recipe.extent.isInfinite ? CGRect.zero : recipe.extent
135
+ content = .bitmap(recipe)
136
+ size = CGSize(width: extent.width / factor, height: extent.height / factor)
137
+ self.scale = factor
138
+ imageOrientation = .up
139
+ _ciImage = ciImage
140
+ }
141
+
142
+ /// An SF Symbol. Never nil: the shim cannot tell which names exist, and
143
+ /// the page draws a placeholder for one it does not know. The size is
144
+ /// that of a symbol at the body text style.
145
+ public init?(systemName: String) {
146
+ content = .system(systemName)
147
+ size = CGSize(width: 20, height: 20)
148
+ scale = 1
149
+ imageOrientation = .up
150
+ _ciImage = nil
151
+ }
152
+
153
+ /// An asset-catalog image. Never nil, and its size is zero: the catalog
154
+ /// is the page's (docs/ops-protocol.md, "Phase 5"), so only the page knows it.
155
+ public init?(named name: String) {
156
+ content = .named(name)
157
+ size = .zero
158
+ scale = 1
159
+ imageOrientation = .up
160
+ _ciImage = nil
161
+ }
162
+
163
+ /// The bitmap, for an image made from data or a `CGImage`; nil for a
164
+ /// symbol, a catalog image, an empty image or one backed by a `CIImage`
165
+ /// (as on iOS).
166
+ public var cgImage: CGImage? {
167
+ guard _ciImage == nil, case .bitmap(let recipe) = content, recipe.source != nil else { return nil }
168
+ return CGImage(_recipe: recipe)
169
+ }
170
+
171
+ /// The recipe the page draws; nil for a symbol or a catalog image.
172
+ public var _recipe: _ImageRecipe? {
173
+ if case .bitmap(let recipe) = content { return recipe }
174
+ return nil
175
+ }
176
+
177
+ public static func == (lhs: UIImage, rhs: UIImage) -> Bool { lhs === rhs }
178
+ public func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }
179
+ }
180
+
181
+ extension Image {
182
+ /// The way `Image(_:scale:orientation:label:)` takes a `CGImage`.
183
+ /// Recorded, not applied: the page draws the bitmap upright.
184
+ public enum Orientation: UInt8, CaseIterable, Hashable, Sendable {
185
+ case up, upMirrored, down, downMirrored, left, leftMirrored, right, rightMirrored
186
+ }
187
+
188
+ /// A `UIImage`: its bitmap (drawn by the page from its recipe), or the
189
+ /// symbol or catalog image it names. The intrinsic size is the image's
190
+ /// size in points.
191
+ public init(uiImage: UIImage) {
192
+ switch uiImage.content {
193
+ case .system(let name): self.init(source: .system(name), isResizable: false)
194
+ case .named(let name): self.init(source: .named(name), isResizable: false)
195
+ case .bitmap(let recipe):
196
+ self.init(source: .bitmap(recipe, width: uiImage.size.width, height: uiImage.size.height), isResizable: false)
197
+ }
198
+ }
199
+
200
+ public init(_ cgImage: CGImage, scale: CGFloat, orientation: Orientation = .up, label: Text) {
201
+ let factor = scale > 0 ? scale : 1
202
+ self.init(source: .bitmap(cgImage._recipe, width: Double(cgImage.width) / factor, height: Double(cgImage.height) / factor),
203
+ isResizable: false)
204
+ }
205
+
206
+ public init(decorative cgImage: CGImage, scale: CGFloat, orientation: Orientation = .up) {
207
+ self.init(cgImage, scale: scale, orientation: orientation, label: Text(""))
208
+ }
209
+
210
+ /// Sends the bitmap's source to the page once (an `imagedata` op), before
211
+ /// the element that draws it.
212
+ @MainActor func _sendBitmapSource(through runtime: _Runtime) {
213
+ if case .bitmap(let recipe, _, _) = source, let source = recipe.source { runtime._sendImageSource(source) }
214
+ }
215
+ }
216
+
217
+ // Core Graphics' rectangle helpers that Core Image's extents need.
218
+ extension CGRect {
219
+ /// A rectangle covering the whole plane (a `clampedToExtent()` image's extent).
220
+ public static let infinite = CGRect(x: -Double.greatestFiniteMagnitude / 2, y: -Double.greatestFiniteMagnitude / 2,
221
+ width: Double.greatestFiniteMagnitude, height: Double.greatestFiniteMagnitude)
222
+ /// No rectangle at all (the intersection of two that do not meet).
223
+ public static let null = CGRect(x: Double.infinity, y: Double.infinity, width: 0, height: 0)
224
+
225
+ public var isInfinite: Bool { size.width >= Double.greatestFiniteMagnitude || size.height >= Double.greatestFiniteMagnitude }
226
+ public var isNull: Bool { origin.x == .infinity || origin.y == .infinity }
227
+
228
+ /// The overlap of two rectangles; `.null` when they do not overlap.
229
+ public func intersection(_ other: CGRect) -> CGRect {
230
+ if isNull || other.isNull { return .null }
231
+ if isInfinite { return other }
232
+ if other.isInfinite { return self }
233
+ let x0 = max(minX, other.minX), y0 = max(minY, other.minY)
234
+ let x1 = min(maxX, other.maxX), y1 = min(maxY, other.maxY)
235
+ guard x1 > x0, y1 > y0 else { return .null }
236
+ return CGRect(x: x0, y: y0, width: x1 - x0, height: y1 - y0)
237
+ }
238
+
239
+ /// The smallest rectangle containing both.
240
+ public func union(_ other: CGRect) -> CGRect {
241
+ if isNull { return other }
242
+ if other.isNull { return self }
243
+ if isInfinite || other.isInfinite { return .infinite }
244
+ let x0 = min(minX, other.minX), y0 = min(minY, other.minY)
245
+ return CGRect(x: x0, y: y0, width: max(maxX, other.maxX) - x0, height: max(maxY, other.maxY) - y0)
246
+ }
247
+
248
+ /// The smallest rectangle with integer coordinates containing this one.
249
+ public var integral: CGRect {
250
+ if isNull || isInfinite { return self }
251
+ let x0 = minX.rounded(.down), y0 = minY.rounded(.down)
252
+ return CGRect(x: x0, y: y0, width: maxX.rounded(.up) - x0, height: maxY.rounded(.up) - y0)
253
+ }
254
+ }
@@ -0,0 +1,96 @@
1
+ /// Custom button styles: `ButtonStyle` and `.buttonStyle(_:)` with one.
2
+ ///
3
+ /// A button under a custom style draws what the style's
4
+ /// `makeBody(configuration:)` returns in place of its label, inside the same
5
+ /// `button` element (the page's `plain` style: no tint and no chrome of its
6
+ /// own), so taps still run the action. The style's `@Environment` properties
7
+ /// are resolved like a view's. `isPressed` is always false: the page does not
8
+ /// report a press in progress, so a style's pressed look is never drawn.
9
+ /// A nearer `.buttonStyle` wins, custom or built in.
10
+
11
+ /// The view a style gets as `configuration.label`: the button's label.
12
+ public struct ButtonStyleConfiguration {
13
+ public struct Label {
14
+ let view: AnyView
15
+ }
16
+
17
+ /// The button's role (`.destructive`, `.cancel`), if any.
18
+ public let role: ButtonRole?
19
+ public let label: Label
20
+ /// Always false in the browser (see the file comment).
21
+ public let isPressed: Bool
22
+ }
23
+
24
+ extension ButtonStyleConfiguration.Label: View {
25
+ public typealias Body = Never
26
+ public var body: Never { fatalError("ButtonStyleConfiguration.Label is a primitive view") }
27
+ }
28
+ extension ButtonStyleConfiguration.Label: _PrimitiveView {}
29
+ extension ButtonStyleConfiguration.Label: _GroupView {
30
+ var _children: [any View] { [view] }
31
+ }
32
+
33
+ /// A style that draws a button from its label.
34
+ @MainActor @preconcurrency
35
+ public protocol ButtonStyle {
36
+ associatedtype Body: View
37
+ typealias Configuration = ButtonStyleConfiguration
38
+ @ViewBuilder func makeBody(configuration: Configuration) -> Body
39
+ }
40
+
41
+ /// The style a `.buttonStyle(_:)` put in the environment.
42
+ struct _CustomButtonStyle {
43
+ /// `_buttonStyle`'s value under a custom style; the page gets `plain`.
44
+ static let marker = "\u{1}custom"
45
+ let makeBody: @MainActor (ButtonStyleConfiguration) -> any View
46
+ }
47
+
48
+ struct _CustomButtonStyleKey: EnvironmentKey {
49
+ static var defaultValue: _CustomButtonStyle? { nil }
50
+ }
51
+
52
+ extension EnvironmentValues {
53
+ var _customButtonStyle: _CustomButtonStyle? {
54
+ get { self[_CustomButtonStyleKey.self] }
55
+ set { self[_CustomButtonStyleKey.self] = newValue }
56
+ }
57
+ }
58
+
59
+ /// Runs a style's `makeBody` as a view's body, so that the runtime resolves
60
+ /// the style's `@Environment` and `@State` properties (it reflects into a
61
+ /// stored `ButtonStyle` as into a `ViewModifier`).
62
+ struct _ButtonStyleBody<Style: ButtonStyle>: View {
63
+ let style: Style
64
+ let configuration: ButtonStyleConfiguration
65
+ var body: Style.Body { style.makeBody(configuration: configuration) }
66
+ }
67
+
68
+ extension _ButtonStyleBody: _HoldsModifier {}
69
+
70
+ nonisolated extension View {
71
+ /// Draws the buttons inside with `style` (see the file comment).
72
+ public func buttonStyle<S: ButtonStyle>(_ style: S) -> some View {
73
+ // Read on the main actor only, when a button's body is made.
74
+ nonisolated(unsafe) let style = style
75
+ return environment(\._buttonStyle, _CustomButtonStyle.marker)
76
+ .environment(\._customButtonStyle, _CustomButtonStyle { configuration in
77
+ _ButtonStyleBody(style: style, configuration: configuration)
78
+ })
79
+ }
80
+ }
81
+
82
+ /// A host view whose children depend on the environment (a button under a
83
+ /// custom style); checked by the runtime ahead of `_HostView._content`.
84
+ protocol _EnvironmentContent {
85
+ func _content(in environment: EnvironmentValues) -> [any View]
86
+ }
87
+
88
+ extension Button: _EnvironmentContent {
89
+ func _content(in environment: EnvironmentValues) -> [any View] {
90
+ guard environment._buttonStyle == _CustomButtonStyle.marker, let style = environment._customButtonStyle else {
91
+ return [label]
92
+ }
93
+ let configuration = ButtonStyleConfiguration(role: role, label: .init(view: AnyView(label)), isPressed: false)
94
+ return [MainActor.assumeIsolated { style.makeBody(configuration) }]
95
+ }
96
+ }
@@ -0,0 +1,337 @@
1
+ // `Canvas` and its `GraphicsContext`. The renderer closure runs in Swift
2
+ // against a context that records what it draws (paths filled or stroked,
3
+ // images, text) with the context's transform, opacity, blend mode, clip and
4
+ // filters at that moment; the page draws the list as SVG over the canvas's
5
+ // box, clipped to it (Web/src/canvasDrawing.ts, docs/ops-protocol.md,
6
+ // "Canvas"). A canvas fills the size it is offered, which reaches Swift as a
7
+ // `GeometryReader`'s does: the closure runs again with the laid-out size.
8
+ //
9
+ // Not drawn: `resolveSymbol(id:)` views (none resolve), bitmaps
10
+ // (`Image(uiImage:)`), and filters other than blur, shadow and the color
11
+ // adjustments. A resolved image or text knows no size (`.zero`).
12
+
13
+ public struct Canvas<Symbols: View>: View {
14
+ let renderer: (inout GraphicsContext, CGSize) -> Void
15
+ let symbols: Symbols
16
+ let isOpaque: Bool
17
+
18
+ public init(opaque: Bool = false, colorMode: ColorRenderingMode = .nonLinear, rendersAsynchronously: Bool = false,
19
+ renderer: @escaping (inout GraphicsContext, CGSize) -> Void, @ViewBuilder symbols: () -> Symbols) {
20
+ self.renderer = renderer
21
+ self.symbols = symbols()
22
+ self.isOpaque = opaque
23
+ }
24
+
25
+ public var body: some View {
26
+ GeometryReader { proxy in
27
+ _CanvasDrawing(size: proxy.size, renderer: renderer)
28
+ }
29
+ }
30
+ }
31
+
32
+ extension Canvas where Symbols == EmptyView {
33
+ public init(opaque: Bool = false, colorMode: ColorRenderingMode = .nonLinear, rendersAsynchronously: Bool = false,
34
+ renderer: @escaping (inout GraphicsContext, CGSize) -> Void) {
35
+ self.init(opaque: opaque, colorMode: colorMode, rendersAsynchronously: rendersAsynchronously, renderer: renderer) { EmptyView() }
36
+ }
37
+ }
38
+
39
+ /// The drawing of a canvas at one size: a `canvas` element whose props are the commands.
40
+ struct _CanvasDrawing {
41
+ let size: CGSize
42
+ let renderer: (inout GraphicsContext, CGSize) -> Void
43
+ }
44
+ extension _CanvasDrawing: _PrimitiveView {}
45
+ extension _CanvasDrawing: _HostView {
46
+ var _kind: String { "canvas" }
47
+ func _props(in environment: EnvironmentValues) -> _JSON {
48
+ let recorder = GraphicsContext._Recorder()
49
+ var context = GraphicsContext(recorder: recorder, environment: environment)
50
+ renderer(&context, size)
51
+ return .object([
52
+ "width": .number(size.width),
53
+ "height": .number(size.height),
54
+ "commands": .array(recorder.commands),
55
+ ])
56
+ }
57
+ }
58
+
59
+ /// What a `Canvas` draws with. A copy (as `drawLayer` gives) draws into the
60
+ /// same canvas with its own transform, opacity, clip and filters.
61
+ public struct GraphicsContext {
62
+ final class _Recorder {
63
+ var commands: [_JSON] = []
64
+ }
65
+
66
+ let recorder: _Recorder
67
+ public var environment: EnvironmentValues
68
+ public var transform: CGAffineTransform = .identity
69
+ public var opacity: Double = 1
70
+ public var blendMode: BlendMode = .normal
71
+ /// The clip paths, already in the canvas's coordinates.
72
+ var clips: [Path] = []
73
+ var filters: [_JSON] = []
74
+
75
+ init(recorder: _Recorder, environment: EnvironmentValues) {
76
+ self.recorder = recorder
77
+ self.environment = environment
78
+ }
79
+
80
+ // MARK: Transform
81
+
82
+ public mutating func translateBy(x: CGFloat, y: CGFloat) { transform = transform.translatedBy(x: x, y: y) }
83
+ public mutating func scaleBy(x: CGFloat, y: CGFloat) { transform = transform.scaledBy(x: x, y: y) }
84
+ public mutating func rotate(by angle: Angle) { transform = transform.rotated(by: angle.radians) }
85
+ public mutating func concatenate(_ matrix: CGAffineTransform) { transform = matrix.concatenating(transform) }
86
+
87
+ // MARK: Clip
88
+
89
+ public struct ClipOptions: OptionSet, Sendable {
90
+ public let rawValue: UInt32
91
+ public init(rawValue: UInt32) { self.rawValue = rawValue }
92
+ /// Clips to the outside of the path: not drawn here (the clip is left as is).
93
+ public static let inverse = ClipOptions(rawValue: 1)
94
+ }
95
+
96
+ public mutating func clip(to path: Path, style: FillStyle = FillStyle(), options: ClipOptions = []) {
97
+ guard !options.contains(.inverse) else { return }
98
+ clips.append(path.applying(transform))
99
+ }
100
+
101
+ public var clipBoundingRect: CGRect {
102
+ clips.last?.boundingRect ?? CGRect(x: -.greatestFiniteMagnitude / 2, y: -.greatestFiniteMagnitude / 2,
103
+ width: .greatestFiniteMagnitude, height: .greatestFiniteMagnitude)
104
+ }
105
+
106
+ // MARK: Layers and filters
107
+
108
+ public func drawLayer(content: (inout GraphicsContext) throws -> Void) rethrows {
109
+ var layer = self
110
+ try content(&layer)
111
+ }
112
+
113
+ public struct Filter: Sendable {
114
+ let json: _JSON
115
+
116
+ public static func blur(radius: CGFloat, options: BlurOptions = BlurOptions()) -> Filter {
117
+ Filter(json: .object(["blur": .number(radius)]))
118
+ }
119
+ public static func shadow(color: Color = Color(.sRGBLinear, white: 0, opacity: 0.33), radius: CGFloat,
120
+ x: CGFloat = 0, y: CGFloat = 0, blendMode: BlendMode = .normal, options: ShadowOptions = ShadowOptions()) -> Filter {
121
+ Filter(json: .object(["shadow": .object(["color": color._json, "radius": .number(radius), "x": .number(x), "y": .number(y)])]))
122
+ }
123
+ public static func grayscale(_ amount: Double) -> Filter { Filter(json: .object(["grayscale": .number(amount)])) }
124
+ public static func saturation(_ amount: Double) -> Filter { Filter(json: .object(["saturation": .number(amount)])) }
125
+ public static func brightness(_ amount: Double) -> Filter { Filter(json: .object(["brightness": .number(amount)])) }
126
+ public static func contrast(_ amount: Double) -> Filter { Filter(json: .object(["contrast": .number(amount)])) }
127
+ public static func hueRotation(_ angle: Angle) -> Filter { Filter(json: .object(["hueRotation": .number(angle.degrees)])) }
128
+ public static func colorInvert(_ amount: Double = 1) -> Filter { Filter(json: .object(["invert": .number(amount)])) }
129
+ /// Not drawn.
130
+ public static func colorMultiply(_ color: Color) -> Filter { Filter(json: .null) }
131
+ /// Not drawn.
132
+ public static var luminanceToAlpha: Filter { Filter(json: .null) }
133
+ /// Not drawn.
134
+ public static func alphaThreshold(min: Double, max: Double = 1, color: Color = .black) -> Filter { Filter(json: .null) }
135
+ }
136
+
137
+ public struct BlurOptions: OptionSet, Sendable {
138
+ public let rawValue: UInt32
139
+ public init(rawValue: UInt32) { self.rawValue = rawValue }
140
+ public static let opaque = BlurOptions(rawValue: 1)
141
+ public static let dithersResult = BlurOptions(rawValue: 2)
142
+ }
143
+
144
+ public struct ShadowOptions: OptionSet, Sendable {
145
+ public let rawValue: UInt32
146
+ public init(rawValue: UInt32) { self.rawValue = rawValue }
147
+ public static let shadowAbove = ShadowOptions(rawValue: 1)
148
+ public static let shadowOnly = ShadowOptions(rawValue: 2)
149
+ public static let invertsAlpha = ShadowOptions(rawValue: 4)
150
+ public static let disablesGroup = ShadowOptions(rawValue: 8)
151
+ }
152
+
153
+ public struct FilterOptions: OptionSet, Sendable {
154
+ public let rawValue: UInt32
155
+ public init(rawValue: UInt32) { self.rawValue = rawValue }
156
+ public static let linearColor = FilterOptions(rawValue: 1)
157
+ }
158
+
159
+ public mutating func addFilter(_ filter: Filter, options: FilterOptions = FilterOptions()) {
160
+ if filter.json != .null { filters.append(filter.json) }
161
+ }
162
+
163
+ // MARK: Shading
164
+
165
+ /// A paint: a color, a style, or a gradient in the context's coordinates.
166
+ public struct Shading: Sendable {
167
+ let json: _JSON
168
+
169
+ public static var foreground: Shading { Shading(json: ForegroundStyle()._json) }
170
+ public static func color(_ color: Color) -> Shading { Shading(json: color._json) }
171
+ public static func color(_ colorSpace: Color.RGBColorSpace = .sRGB, red: Double, green: Double, blue: Double, opacity: Double = 1) -> Shading {
172
+ .color(Color(colorSpace, red: red, green: green, blue: blue, opacity: opacity))
173
+ }
174
+ public static func color(_ colorSpace: Color.RGBColorSpace = .sRGB, white: Double, opacity: Double = 1) -> Shading {
175
+ .color(Color(colorSpace, white: white, opacity: opacity))
176
+ }
177
+ public static func style<S: ShapeStyle>(_ style: S) -> Shading { Shading(json: style._json) }
178
+ public static func palette(_ array: [Shading]) -> Shading { array.first ?? .foreground }
179
+
180
+ public static func linearGradient(_ gradient: Gradient, startPoint: CGPoint, endPoint: CGPoint, options: GradientOptions = GradientOptions()) -> Shading {
181
+ Shading(json: .object(["canvasLinearGradient": .object([
182
+ "stops": gradient._stopsJSON,
183
+ "start": point(startPoint), "end": point(endPoint),
184
+ ])]))
185
+ }
186
+ public static func radialGradient(_ gradient: Gradient, center: CGPoint, startRadius: CGFloat, endRadius: CGFloat, options: GradientOptions = GradientOptions()) -> Shading {
187
+ Shading(json: .object(["canvasRadialGradient": .object([
188
+ "stops": gradient._stopsJSON,
189
+ "center": point(center),
190
+ "startRadius": .number(startRadius), "endRadius": .number(endRadius),
191
+ ])]))
192
+ }
193
+ /// Drawn as its first color.
194
+ public static func conicGradient(_ gradient: Gradient, center: CGPoint, angle: Angle = Angle(), options: GradientOptions = GradientOptions()) -> Shading {
195
+ .color(gradient.stops.first?.color ?? .clear)
196
+ }
197
+
198
+ static func point(_ p: CGPoint) -> _JSON { .object(["x": .number(p.x), "y": .number(p.y)]) }
199
+ }
200
+
201
+ public struct GradientOptions: OptionSet, Sendable {
202
+ public let rawValue: UInt32
203
+ public init(rawValue: UInt32) { self.rawValue = rawValue }
204
+ public static let `repeat` = GradientOptions(rawValue: 1)
205
+ public static let mirror = GradientOptions(rawValue: 2)
206
+ public static let linearColor = GradientOptions(rawValue: 4)
207
+ }
208
+
209
+ // MARK: Drawing
210
+
211
+ public func fill(_ path: Path, with shading: Shading, style: FillStyle = FillStyle()) {
212
+ var command: [String: _JSON] = ["op": .string("fill"), "path": .string(path._svg), "shading": shading.json]
213
+ if style.isEOFilled { command["evenOdd"] = .bool(true) }
214
+ record(command)
215
+ }
216
+
217
+ public func stroke(_ path: Path, with shading: Shading, style: StrokeStyle) {
218
+ var command: [String: _JSON] = [
219
+ "op": .string("stroke"), "path": .string(path._svg), "shading": shading.json,
220
+ "lineWidth": .number(style.lineWidth),
221
+ ]
222
+ command["lineCap"] = .string(style.lineCap == .round ? "round" : style.lineCap == .square ? "square" : "butt")
223
+ command["lineJoin"] = .string(style.lineJoin == .round ? "round" : style.lineJoin == .bevel ? "bevel" : "miter")
224
+ command["miterLimit"] = .number(style.miterLimit)
225
+ if !style.dash.isEmpty {
226
+ command["dash"] = .array(style.dash.map { .number($0) })
227
+ command["dashPhase"] = .number(style.dashPhase)
228
+ }
229
+ record(command)
230
+ }
231
+
232
+ public func stroke(_ path: Path, with shading: Shading, lineWidth: CGFloat = 1) {
233
+ stroke(path, with: shading, style: StrokeStyle(lineWidth: lineWidth))
234
+ }
235
+
236
+ /// An image or text made ready to draw (`resolve(_:)`); its size is not known here.
237
+ public struct ResolvedImage {
238
+ let image: Image
239
+ public var size: CGSize { .zero }
240
+ public var baseline: CGFloat { 0 }
241
+ public var shading: Shading?
242
+ }
243
+
244
+ public struct ResolvedText {
245
+ let text: Text
246
+ public var shading: Shading = .foreground
247
+ public func measure(in size: CGSize) -> CGSize { .zero }
248
+ public func firstBaseline(in size: CGSize) -> CGFloat { 0 }
249
+ public func lastBaseline(in size: CGSize) -> CGFloat { 0 }
250
+ }
251
+
252
+ /// A view passed to `Canvas(renderer:symbols:)`; none resolve here.
253
+ public struct ResolvedSymbol {
254
+ public var size: CGSize { .zero }
255
+ }
256
+
257
+ public func resolve(_ image: Image) -> ResolvedImage { ResolvedImage(image: image) }
258
+ public func resolve(_ text: Text) -> ResolvedText { ResolvedText(text: text) }
259
+ public func resolveSymbol<ID: Hashable>(id: ID) -> ResolvedSymbol? { nil }
260
+
261
+ public func draw(_ image: ResolvedImage, at point: CGPoint, anchor: UnitPoint = .center) {
262
+ drawImage(image.image, at: point, anchor: anchor, shading: image.shading)
263
+ }
264
+
265
+ public func draw(_ image: ResolvedImage, in rect: CGRect, style: FillStyle = FillStyle()) {
266
+ drawImage(image.image, in: rect, shading: image.shading)
267
+ }
268
+
269
+ public func draw(_ image: Image, at point: CGPoint, anchor: UnitPoint = .center) {
270
+ drawImage(image, at: point, anchor: anchor, shading: nil)
271
+ }
272
+
273
+ public func draw(_ image: Image, in rect: CGRect, style: FillStyle = FillStyle()) {
274
+ drawImage(image, in: rect, shading: nil)
275
+ }
276
+
277
+ public func draw(_ text: ResolvedText, at point: CGPoint, anchor: UnitPoint = .center) {
278
+ drawText(text.text, at: point, anchor: anchor, shading: text.shading)
279
+ }
280
+
281
+ public func draw(_ text: ResolvedText, in rect: CGRect) {
282
+ drawText(text.text, at: CGPoint(x: rect.minX, y: rect.minY), anchor: .topLeading, shading: text.shading)
283
+ }
284
+
285
+ public func draw(_ text: Text, at point: CGPoint, anchor: UnitPoint = .center) {
286
+ drawText(text, at: point, anchor: anchor, shading: .foreground)
287
+ }
288
+
289
+ public func draw(_ text: Text, in rect: CGRect) {
290
+ drawText(text, at: CGPoint(x: rect.minX, y: rect.minY), anchor: .topLeading, shading: .foreground)
291
+ }
292
+
293
+ public func draw(_ symbol: ResolvedSymbol, at point: CGPoint, anchor: UnitPoint = .center) {}
294
+ public func draw(_ symbol: ResolvedSymbol, in rect: CGRect) {}
295
+
296
+ private func drawImage(_ image: Image, at point: CGPoint, anchor: UnitPoint, shading: Shading?) {
297
+ var command: [String: _JSON] = [
298
+ "op": .string("image"), "image": image._props(in: environment),
299
+ "x": .number(point.x), "y": .number(point.y), "anchor": anchor._json,
300
+ ]
301
+ if let shading { command["shading"] = shading.json }
302
+ record(command)
303
+ }
304
+
305
+ private func drawImage(_ image: Image, in rect: CGRect, shading: Shading?) {
306
+ var command: [String: _JSON] = [
307
+ "op": .string("image"), "image": image._props(in: environment),
308
+ "x": .number(rect.minX), "y": .number(rect.minY), "anchor": UnitPoint.topLeading._json,
309
+ "width": .number(rect.width), "height": .number(rect.height),
310
+ ]
311
+ if let shading { command["shading"] = shading.json }
312
+ record(command)
313
+ }
314
+
315
+ private func drawText(_ text: Text, at point: CGPoint, anchor: UnitPoint, shading: Shading) {
316
+ var command: [String: _JSON] = [
317
+ "op": .string("text"), "text": .string(text.content),
318
+ "x": .number(point.x), "y": .number(point.y), "anchor": anchor._json,
319
+ "shading": shading.json,
320
+ ]
321
+ if let font = environment.font { command["font"] = font._json }
322
+ record(command)
323
+ }
324
+
325
+ /// Adds the context's state to a command and records it.
326
+ private func record(_ command: [String: _JSON]) {
327
+ var command = command
328
+ if !transform.isIdentity {
329
+ command["transform"] = .array([transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty].map { .number($0) })
330
+ }
331
+ if opacity < 1 { command["opacity"] = .number(max(0, opacity)) }
332
+ if blendMode != .normal { command["blendMode"] = .string(blendMode._css) }
333
+ if !clips.isEmpty { command["clips"] = .array(clips.map { .string($0._svg) }) }
334
+ if !filters.isEmpty { command["filters"] = .array(filters) }
335
+ recorder.commands.append(.object(command))
336
+ }
337
+ }