@swiftbrowser/swift 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. package/Package.swift +214 -0
  2. package/README.md +10 -2
  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 +61 -0
  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/FoundationBridge/Bundle.swift +119 -0
  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 +29 -0
  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/Locale.swift +86 -0
  170. package/Sources/FoundationBridge/Localization.swift +149 -0
  171. package/Sources/FoundationBridge/Locks.swift +50 -0
  172. package/Sources/FoundationBridge/Markdown.swift +527 -0
  173. package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
  174. package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
  175. package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
  176. package/Sources/FoundationBridge/Operation.swift +195 -0
  177. package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
  178. package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
  179. package/Sources/FoundationBridge/SceneStorage.swift +78 -0
  180. package/Sources/FoundationBridge/SecurityExports.swift +8 -0
  181. package/Sources/FoundationBridge/Selector.swift +226 -0
  182. package/Sources/FoundationBridge/StringComparators.swift +17 -0
  183. package/Sources/FoundationBridge/Table.swift +211 -0
  184. package/Sources/FoundationBridge/TextAttributes.swift +42 -0
  185. package/Sources/FoundationBridge/Timer.swift +53 -0
  186. package/Sources/FoundationBridge/UITextChecker.swift +30 -0
  187. package/Sources/FoundationBridge/URLSession.swift +718 -0
  188. package/Sources/FoundationBridge/UserDefaults.swift +183 -0
  189. package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
  190. package/Sources/FoundationBridge/WebSocket.swift +187 -0
  191. package/Sources/FoundationModels/FoundationModels.swift +1098 -0
  192. package/Sources/ImageIO/GIF.swift +72 -0
  193. package/Sources/ImageIO/ImageIO.swift +248 -0
  194. package/Sources/ImageIO/ImageTypes.swift +28 -0
  195. package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
  196. package/Sources/LocalAuthentication/LAContext.swift +86 -0
  197. package/Sources/MapKit/Geometry.swift +223 -0
  198. package/Sources/MapKit/Map.swift +638 -0
  199. package/Sources/MapKit/MapView.swift +229 -0
  200. package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
  201. package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
  202. package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
  203. package/Sources/OSLog/OSLog.swift +6 -0
  204. package/Sources/Photos/Photos.swift +572 -0
  205. package/Sources/PhotosUI/PhotosPicker.swift +248 -0
  206. package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
  207. package/Sources/QuickLook/QuickLook.swift +168 -0
  208. package/Sources/SafariServices/SafariServices.swift +106 -0
  209. package/Sources/Security/Security.swift +332 -0
  210. package/Sources/StoreKit/AppStore.swift +207 -0
  211. package/Sources/StoreKit/Products.swift +280 -0
  212. package/Sources/StoreKit/RequestReview.swift +28 -0
  213. package/Sources/StoreKit/StoreKit1.swift +486 -0
  214. package/Sources/StoreKit/StoreViews.swift +428 -0
  215. package/Sources/StoreKit/Transactions.swift +197 -0
  216. package/Sources/SwiftData/Macros.swift +58 -0
  217. package/Sources/SwiftData/ModelActor.swift +38 -0
  218. package/Sources/SwiftData/ModelContainer.swift +129 -0
  219. package/Sources/SwiftData/ModelContext.swift +451 -0
  220. package/Sources/SwiftData/PersistentModel.swift +238 -0
  221. package/Sources/SwiftData/Properties.swift +261 -0
  222. package/Sources/SwiftData/Query.swift +256 -0
  223. package/Sources/SwiftData/Schema.swift +192 -0
  224. package/Sources/SwiftData/Store.swift +146 -0
  225. package/Sources/SwiftData/StringPredicates.swift +125 -0
  226. package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
  227. package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
  228. package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
  229. package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
  230. package/Sources/SwiftDataMacros/Plugin.swift +18 -0
  231. package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
  232. package/Sources/SwiftUI/API/Accessibility.swift +181 -0
  233. package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
  234. package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
  235. package/Sources/SwiftUI/API/Alert.swift +221 -0
  236. package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
  237. package/Sources/SwiftUI/API/Animation.swift +285 -0
  238. package/Sources/SwiftUI/API/App.swift +87 -0
  239. package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
  240. package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
  241. package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
  242. package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
  243. package/Sources/SwiftUI/API/Canvas.swift +337 -0
  244. package/Sources/SwiftUI/API/Color.swift +237 -0
  245. package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
  246. package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
  247. package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
  248. package/Sources/SwiftUI/API/Commands.swift +106 -0
  249. package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
  250. package/Sources/SwiftUI/API/ContentShape.swift +33 -0
  251. package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
  252. package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
  253. package/Sources/SwiftUI/API/Controls.swift +300 -0
  254. package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
  255. package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
  256. package/Sources/SwiftUI/API/Decorations.swift +92 -0
  257. package/Sources/SwiftUI/API/EditMode.swift +212 -0
  258. package/Sources/SwiftUI/API/Effects.swift +388 -0
  259. package/Sources/SwiftUI/API/Entry.swift +8 -0
  260. package/Sources/SwiftUI/API/Environment.swift +439 -0
  261. package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
  262. package/Sources/SwiftUI/API/Focus.swift +137 -0
  263. package/Sources/SwiftUI/API/Font.swift +131 -0
  264. package/Sources/SwiftUI/API/Gauge.swift +290 -0
  265. package/Sources/SwiftUI/API/Geometry.swift +89 -0
  266. package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
  267. package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
  268. package/Sources/SwiftUI/API/GestureState.swift +65 -0
  269. package/Sources/SwiftUI/API/Gestures.swift +342 -0
  270. package/Sources/SwiftUI/API/Glass.swift +127 -0
  271. package/Sources/SwiftUI/API/Grid.swift +188 -0
  272. package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
  273. package/Sources/SwiftUI/API/KeyPress.swift +54 -0
  274. package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
  275. package/Sources/SwiftUI/API/Layout.swift +220 -0
  276. package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
  277. package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
  278. package/Sources/SwiftUI/API/Lists.swift +331 -0
  279. package/Sources/SwiftUI/API/Menu.swift +58 -0
  280. package/Sources/SwiftUI/API/Modifiers.swift +313 -0
  281. package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
  282. package/Sources/SwiftUI/API/Namespace.swift +44 -0
  283. package/Sources/SwiftUI/API/Navigation.swift +386 -0
  284. package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
  285. package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
  286. package/Sources/SwiftUI/API/OnChange.swift +48 -0
  287. package/Sources/SwiftUI/API/Path.swift +543 -0
  288. package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
  289. package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
  290. package/Sources/SwiftUI/API/Picker.swift +185 -0
  291. package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
  292. package/Sources/SwiftUI/API/Popover.swift +41 -0
  293. package/Sources/SwiftUI/API/Preferences.swift +262 -0
  294. package/Sources/SwiftUI/API/Presentation.swift +122 -0
  295. package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
  296. package/Sources/SwiftUI/API/Primitives.swift +517 -0
  297. package/Sources/SwiftUI/API/Publishers.swift +107 -0
  298. package/Sources/SwiftUI/API/Redaction.swift +75 -0
  299. package/Sources/SwiftUI/API/RowActions.swift +84 -0
  300. package/Sources/SwiftUI/API/Scenes.swift +131 -0
  301. package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
  302. package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
  303. package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
  304. package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
  305. package/Sources/SwiftUI/API/Shape.swift +214 -0
  306. package/Sources/SwiftUI/API/ShapeStyle.swift +409 -0
  307. package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
  308. package/Sources/SwiftUI/API/Sharing.swift +193 -0
  309. package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
  310. package/Sources/SwiftUI/API/State.swift +144 -0
  311. package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
  312. package/Sources/SwiftUI/API/StrokeStyle.swift +30 -0
  313. package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
  314. package/Sources/SwiftUI/API/TabContent.swift +841 -0
  315. package/Sources/SwiftUI/API/Table.swift +382 -0
  316. package/Sources/SwiftUI/API/Tabs.swift +263 -0
  317. package/Sources/SwiftUI/API/Tasks.swift +35 -0
  318. package/Sources/SwiftUI/API/Text.swift +386 -0
  319. package/Sources/SwiftUI/API/TextDates.swift +61 -0
  320. package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
  321. package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
  322. package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
  323. package/Sources/SwiftUI/API/Timeline.swift +212 -0
  324. package/Sources/SwiftUI/API/Toolbar.swift +251 -0
  325. package/Sources/SwiftUI/API/Transfer.swift +145 -0
  326. package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
  327. package/Sources/SwiftUI/API/Video.swift +64 -0
  328. package/Sources/SwiftUI/API/View.swift +215 -0
  329. package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
  330. package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
  331. package/Sources/SwiftUI/API/Windows.swift +25 -0
  332. package/Sources/SwiftUI/Charts/Axis.swift +325 -0
  333. package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
  334. package/Sources/SwiftUI/Charts/Chart.swift +660 -0
  335. package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
  336. package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
  337. package/Sources/SwiftUI/Charts/Marks.swift +204 -0
  338. package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
  339. package/Sources/SwiftUI/Charts/Scales.swift +326 -0
  340. package/Sources/SwiftUI/Localization/Localization.swift +498 -0
  341. package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
  342. package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
  343. package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
  344. package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
  345. package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
  346. package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
  347. package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
  348. package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
  349. package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
  350. package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
  351. package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
  352. package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
  353. package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
  354. package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
  355. package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
  356. package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
  357. package/Sources/Symbols/Symbols.swift +25 -0
  358. package/Sources/Translation/Translation.swift +423 -0
  359. package/Sources/UIKit/Activity.swift +213 -0
  360. package/Sources/UIKit/Alerts.swift +69 -0
  361. package/Sources/UIKit/AppDelegate.swift +222 -0
  362. package/Sources/UIKit/Appearance.swift +84 -0
  363. package/Sources/UIKit/ColorConversions.swift +70 -0
  364. package/Sources/UIKit/Controls.swift +225 -0
  365. package/Sources/UIKit/Device.swift +200 -0
  366. package/Sources/UIKit/Feedback.swift +65 -0
  367. package/Sources/UIKit/Font.swift +307 -0
  368. package/Sources/UIKit/Graphics.swift +204 -0
  369. package/Sources/UIKit/HostingController.swift +185 -0
  370. package/Sources/UIKit/Identity.swift +24 -0
  371. package/Sources/UIKit/Introspectable.swift +510 -0
  372. package/Sources/UIKit/Pasteboard.swift +363 -0
  373. package/Sources/UIKit/PhotoAlbum.swift +81 -0
  374. package/Sources/UIKit/RemoteNotifications.swift +15 -0
  375. package/Sources/UIKit/Representable.swift +288 -0
  376. package/Sources/UIKit/SafeArea.swift +12 -0
  377. package/Sources/UIKit/SceneDelegates.swift +132 -0
  378. package/Sources/UIKit/Scenes.swift +40 -0
  379. package/Sources/UIKit/ScrollView.swift +157 -0
  380. package/Sources/UIKit/ShortcutItems.swift +67 -0
  381. package/Sources/UIKit/SymbolConfiguration.swift +124 -0
  382. package/Sources/UIKit/TargetAction.swift +123 -0
  383. package/Sources/UIKit/TextPaste.swift +161 -0
  384. package/Sources/UIKit/TextView.swift +538 -0
  385. package/Sources/UIKit/UIKit.swift +292 -0
  386. package/Sources/UIKit/UIView.swift +855 -0
  387. package/Sources/UIKit/ViewTranslation.swift +311 -0
  388. package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
  389. package/Sources/UserNotifications/Content.swift +370 -0
  390. package/Sources/UserNotifications/NotificationCenter.swift +309 -0
  391. package/Sources/WeatherKit/WeatherKit.swift +228 -0
  392. package/Sources/WebKit/WebKit.swift +245 -0
  393. package/Sources/os/os.swift +376 -0
  394. package/Sources/zlib/zlib.swift +6 -0
  395. package/index.d.ts +2 -0
  396. package/index.mjs +16 -0
  397. package/manifest.d.mts +2 -0
  398. package/manifest.mjs +39 -0
  399. package/package.json +30 -4
  400. package/sync-sources.mjs +33 -0
@@ -0,0 +1,538 @@
1
+ // UIKit's text views and the attributed strings they show. A representable's
2
+ // `UILabel` is drawn as a `text`, a `UITextView` as a `texteditor` while it is
3
+ // editable and as a `text` (with the rich text `runs`) when it is not
4
+ // (ViewTranslation.swift). What the user types reaches the text view as
5
+ // UIKit's typing would: the delegate is asked
6
+ // `textView(_:shouldChangeTextIn:replacementText:)` for the edit (the
7
+ // range and replacement found by comparing the old and new text), the text
8
+ // changes, the caret moves to the end of the replacement, and the delegate
9
+ // hears `textViewDidChange` and `textViewDidChangeSelection`. Focus is
10
+ // shared both ways: `becomeFirstResponder` focuses the page's text area, and
11
+ // a tap into it (or out) makes the view first responder (or resigns). The
12
+ // page does not report the caret itself, so `selectedRange` is that guess; typing
13
+ // attributes, keyboard settings, data detectors, input accessory views and
14
+ // the like are kept and not used. Sizes (`sizeThatFits`,
15
+ // `intrinsicContentSize`) are estimates from the font's size: Swift has no
16
+ // text metrics, so a label or text view whose size matters is better left
17
+ // to the page (a representable sizes them by measuring what it draws).
18
+ //
19
+ // Corelibs Foundation has `NSAttributedString` without UIKit's attribute
20
+ // keys, and without the conversions from and to `AttributedString` that
21
+ // Apple's Foundation has; both are here, as `import SwiftUI` brings UIKit.
22
+
23
+ import Foundation
24
+ import FoundationBridge
25
+ import SwiftUI
26
+
27
+ // MARK: - Attributed strings
28
+
29
+ extension NSAttributedString.Key {
30
+ public static let font = NSAttributedString.Key("NSFont")
31
+ public static let foregroundColor = NSAttributedString.Key("NSColor")
32
+ public static let backgroundColor = NSAttributedString.Key("NSBackgroundColor")
33
+ public static let link = NSAttributedString.Key("NSLink")
34
+ public static let underlineStyle = NSAttributedString.Key("NSUnderline")
35
+ public static let underlineColor = NSAttributedString.Key("NSUnderlineColor")
36
+ public static let strikethroughStyle = NSAttributedString.Key("NSStrikethrough")
37
+ public static let strikethroughColor = NSAttributedString.Key("NSStrikethroughColor")
38
+ public static let kern = NSAttributedString.Key("NSKern")
39
+ public static let baselineOffset = NSAttributedString.Key("NSBaselineOffset")
40
+ public static let paragraphStyle = NSAttributedString.Key("NSParagraphStyle")
41
+ public static let attachment = NSAttributedString.Key("NSAttachment")
42
+ public static let shadow = NSAttributedString.Key("NSShadow")
43
+ public static let obliqueness = NSAttributedString.Key("NSObliqueness")
44
+ public static let inlinePresentationIntent = NSAttributedString.Key("NSInlinePresentationIntent")
45
+ }
46
+
47
+ /// How text is underlined or struck through.
48
+ public struct NSUnderlineStyle: OptionSet, Hashable, Sendable {
49
+ public let rawValue: Int
50
+ public init(rawValue: Int) { self.rawValue = rawValue }
51
+ public static let single = NSUnderlineStyle(rawValue: 0x01)
52
+ public static let thick = NSUnderlineStyle(rawValue: 0x02)
53
+ public static let double = NSUnderlineStyle(rawValue: 0x09)
54
+ public static let patternDot = NSUnderlineStyle(rawValue: 0x0100)
55
+ public static let patternDash = NSUnderlineStyle(rawValue: 0x0200)
56
+ public static let byWord = NSUnderlineStyle(rawValue: 0x8000)
57
+ }
58
+
59
+ public enum NSTextAlignment: Int, Sendable {
60
+ case left = 0, center = 1, right = 2, justified = 3, natural = 4
61
+ }
62
+
63
+ public enum NSLineBreakMode: Int, Sendable {
64
+ case byWordWrapping = 0, byCharWrapping, byClipping, byTruncatingHead, byTruncatingTail, byTruncatingMiddle
65
+ }
66
+
67
+ extension NSAttributedString {
68
+ /// The runs of an `AttributedString`: their links and inline
69
+ /// presentation intents (Markdown's emphasis), the attributes the browser
70
+ /// build's `AttributedString` carries.
71
+ public convenience init(_ attributedString: AttributedString) {
72
+ self.init(attributedString: _nsAttributedString(attributedString))
73
+ }
74
+ }
75
+
76
+ extension AttributedString {
77
+ /// The string's runs with their links and inline presentation intents;
78
+ /// UIKit's attributes (font, color) have no place in it here and are dropped.
79
+ public init(_ nsAttributedString: NSAttributedString) {
80
+ var result = AttributedString()
81
+ nsAttributedString.enumerateAttributes(in: NSRange(location: 0, length: nsAttributedString.length)) { attributes, range, _ in
82
+ var piece = AttributedString(nsAttributedString.attributedSubstring(from: range).string)
83
+ if let link = _url(attributes[.link]) { piece.link = link }
84
+ if let intent = attributes[.inlinePresentationIntent] as? InlinePresentationIntent { piece.inlinePresentationIntent = intent }
85
+ result += piece
86
+ }
87
+ self = result
88
+ }
89
+ }
90
+
91
+ private func _nsAttributedString(_ attributedString: AttributedString) -> NSAttributedString {
92
+ let result = NSMutableAttributedString(string: "")
93
+ for run in attributedString.runs {
94
+ var attributes: [NSAttributedString.Key: Any] = [:]
95
+ if let link = run.link { attributes[.link] = link }
96
+ if let intent = run.inlinePresentationIntent { attributes[.inlinePresentationIntent] = intent }
97
+ result.append(NSAttributedString(string: String(attributedString[run.range].characters), attributes: attributes))
98
+ }
99
+ return result
100
+ }
101
+
102
+ /// A link attribute's URL: a `URL` or a string.
103
+ func _url(_ value: Any?) -> URL? {
104
+ if let url = value as? URL { return url }
105
+ if let string = value as? String { return URL(string: string) }
106
+ return nil
107
+ }
108
+
109
+ extension Text {
110
+ /// An attributed string as styled text: each run's font, color,
111
+ /// underline, strikethrough, kerning, baseline offset, link and inline
112
+ /// presentation intent. Runs without a font or color take the view's.
113
+ init(_uiKit attributed: NSAttributedString) {
114
+ var result: Text?
115
+ attributed.enumerateAttributes(in: NSRange(location: 0, length: attributed.length)) { attributes, range, _ in
116
+ var piece = Text(verbatim: attributed.attributedSubstring(from: range).string)
117
+ if let font = attributes[.font] as? UIFont { piece = piece.font(Font(font)) }
118
+ if let color = attributes[.foregroundColor] as? UIColor { piece = piece.foregroundColor(Color(uiColor: color)) }
119
+ if let style = attributes[.underlineStyle] as? Int, style != 0 {
120
+ piece = piece.underline(true, color: (attributes[.underlineColor] as? UIColor).map { Color(uiColor: $0) })
121
+ }
122
+ if let style = attributes[.strikethroughStyle] as? Int, style != 0 {
123
+ piece = piece.strikethrough(true, color: (attributes[.strikethroughColor] as? UIColor).map { Color(uiColor: $0) })
124
+ }
125
+ if let kern = attributes[.kern] as? CGFloat { piece = piece.kerning(kern) }
126
+ if let kern = attributes[.kern] as? Double { piece = piece.kerning(CGFloat(kern)) }
127
+ if let offset = attributes[.baselineOffset] as? CGFloat { piece = piece.baselineOffset(offset) }
128
+ if let intent = attributes[.inlinePresentationIntent] as? InlinePresentationIntent {
129
+ if intent.contains(.stronglyEmphasized) { piece = piece.bold() }
130
+ if intent.contains(.emphasized) { piece = piece.italic() }
131
+ if intent.contains(.code) { piece = piece.monospaced() }
132
+ if intent.contains(.strikethrough) { piece = piece.strikethrough() }
133
+ }
134
+ if let link = _url(attributes[.link]) { piece = piece._link(link.absoluteString) }
135
+ result = result.map { $0 + piece } ?? piece
136
+ }
137
+ self = result ?? Text(verbatim: "")
138
+ }
139
+ }
140
+
141
+ // MARK: - Size estimates
142
+
143
+ /// Text sizes from a font's point size alone: an average character is a
144
+ /// little over half the size wide, and paragraphs wrap at `width`.
145
+ enum _TextEstimate {
146
+ static func size(of string: String, font: UIFont, width: CGFloat?, maximumLines: Int = 0) -> CGSize {
147
+ let characterWidth = font.pointSize * 0.52
148
+ let paragraphs = string.split(separator: "\n", omittingEmptySubsequences: false)
149
+ var lines = 0
150
+ var widest: CGFloat = 0
151
+ for paragraph in paragraphs {
152
+ let natural = CGFloat(paragraph.count) * characterWidth
153
+ widest = max(widest, natural)
154
+ if let width, width > 0, width.isFinite {
155
+ lines += max(1, Int((natural / width).rounded(.up)))
156
+ } else {
157
+ lines += 1
158
+ }
159
+ }
160
+ if maximumLines > 0 { lines = min(lines, maximumLines) }
161
+ let resolvedWidth = width.flatMap { $0 > 0 && $0.isFinite ? min($0, widest) : nil } ?? widest
162
+ return CGSize(width: resolvedWidth.rounded(.up), height: CGFloat(max(1, lines)) * font.lineHeight)
163
+ }
164
+ }
165
+
166
+ // MARK: - Labels
167
+
168
+ /// A label: drawn as a `text` with its font, color, alignment and line limit.
169
+ @MainActor
170
+ open class UILabel: UIView {
171
+ private var plainText: String?
172
+ private var attributed: NSAttributedString?
173
+
174
+ open var text: String? {
175
+ get { attributed?.string ?? plainText }
176
+ set {
177
+ plainText = newValue
178
+ attributed = nil
179
+ _setNeedsTranslation()
180
+ }
181
+ }
182
+ open var attributedText: NSAttributedString? {
183
+ get {
184
+ if let attributed { return attributed }
185
+ guard let plainText else { return nil }
186
+ var attributes: [NSAttributedString.Key: Any] = [:]
187
+ if let font { attributes[.font] = font }
188
+ if let textColor { attributes[.foregroundColor] = textColor }
189
+ return NSAttributedString(string: plainText, attributes: attributes)
190
+ }
191
+ set {
192
+ attributed = newValue.map { NSAttributedString(attributedString: $0) }
193
+ plainText = newValue?.string
194
+ _setNeedsTranslation()
195
+ }
196
+ }
197
+ /// Whether the text was set as an attributed string (drawn with its runs).
198
+ var _hasAttributedText: Bool { attributed != nil }
199
+ open var font: UIFont! = .systemFont(ofSize: 17) { didSet { _setNeedsTranslation() } }
200
+ open var textColor: UIColor! = .label { didSet { _setNeedsTranslation() } }
201
+ open var textAlignment: NSTextAlignment = .natural { didSet { _setNeedsTranslation() } }
202
+ open var numberOfLines = 1 { didSet { _setNeedsTranslation() } }
203
+ open var lineBreakMode: NSLineBreakMode = .byTruncatingTail
204
+ open var isEnabled = true { didSet { _setNeedsTranslation() } }
205
+ open var isHighlighted = false
206
+ open var highlightedTextColor: UIColor?
207
+ open var adjustsFontSizeToFitWidth = false
208
+ open var adjustsFontForContentSizeCategory = false
209
+ open var minimumScaleFactor: CGFloat = 0
210
+ open var allowsDefaultTighteningForTruncation = false
211
+ open var preferredMaxLayoutWidth: CGFloat = 0
212
+
213
+ public override init(frame: CGRect) { super.init(frame: frame) }
214
+ public required init?(coder: NSCoder) { super.init(coder: coder) }
215
+
216
+ open override var intrinsicContentSize: CGSize {
217
+ _TextEstimate.size(of: text ?? "", font: font, width: preferredMaxLayoutWidth > 0 ? preferredMaxLayoutWidth : nil,
218
+ maximumLines: numberOfLines)
219
+ }
220
+
221
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
222
+ _TextEstimate.size(of: text ?? "", font: font, width: size.width > 0 ? size.width : nil, maximumLines: numberOfLines)
223
+ }
224
+ }
225
+
226
+ // MARK: - Text views
227
+
228
+ /// A text container's settings, kept (the page lays the text out).
229
+ @MainActor
230
+ open class NSTextContainer {
231
+ open var size: CGSize
232
+ open var lineFragmentPadding: CGFloat = 5
233
+ open var maximumNumberOfLines = 0
234
+ open var lineBreakMode: NSLineBreakMode = .byWordWrapping
235
+ open var widthTracksTextView = true
236
+ open var heightTracksTextView = false
237
+
238
+ public init(size: CGSize = .zero) { self.size = size }
239
+ }
240
+
241
+ /// A position in a text input's text, as a UTF-16 offset.
242
+ @MainActor
243
+ open class UITextPosition {
244
+ let offset: Int
245
+ init(offset: Int) { self.offset = offset }
246
+ }
247
+
248
+ /// A range of a text input's text.
249
+ @MainActor
250
+ open class UITextRange {
251
+ public let start: UITextPosition
252
+ public let end: UITextPosition
253
+ open var isEmpty: Bool { start.offset == end.offset }
254
+ init(start: UITextPosition, end: UITextPosition) {
255
+ self.start = start
256
+ self.end = end
257
+ }
258
+ }
259
+
260
+ public enum UITextAutocapitalizationType: Int, Sendable { case none, words, sentences, allCharacters }
261
+ public enum UITextAutocorrectionType: Int, Sendable { case `default`, no, yes }
262
+ public enum UITextSpellCheckingType: Int, Sendable { case `default`, no, yes }
263
+ public enum UITextSmartQuotesType: Int, Sendable { case `default`, no, yes }
264
+ public enum UITextSmartDashesType: Int, Sendable { case `default`, no, yes }
265
+ public enum UITextInlinePredictionType: Int, Sendable { case `default`, no, yes }
266
+ public enum UIReturnKeyType: Int, Sendable {
267
+ case `default`, go, google, join, next, route, search, send, yahoo, done, emergencyCall, `continue`
268
+ }
269
+ public enum UITextItemInteraction: Int, Sendable { case invokeDefaultAction, presentActions, preview }
270
+
271
+ public struct UIDataDetectorTypes: OptionSet, Sendable {
272
+ public let rawValue: UInt
273
+ public init(rawValue: UInt) { self.rawValue = rawValue }
274
+ public static let phoneNumber = UIDataDetectorTypes(rawValue: 1 << 0)
275
+ public static let link = UIDataDetectorTypes(rawValue: 1 << 1)
276
+ public static let address = UIDataDetectorTypes(rawValue: 1 << 2)
277
+ public static let calendarEvent = UIDataDetectorTypes(rawValue: 1 << 3)
278
+ public static let all = UIDataDetectorTypes(rawValue: UInt.max)
279
+ }
280
+
281
+ /// What a text view tells its delegate. Every method has a default (they are
282
+ /// `@objc optional` on iOS); `delegate?.textViewDidChange?(textView)`, the
283
+ /// Objective-C way to call one, works through the properties below.
284
+ @MainActor
285
+ public protocol UITextViewDelegate: UIScrollViewDelegate {
286
+ func textViewShouldBeginEditing(_ textView: UITextView) -> Bool
287
+ func textViewShouldEndEditing(_ textView: UITextView) -> Bool
288
+ func textViewDidBeginEditing(_ textView: UITextView)
289
+ func textViewDidEndEditing(_ textView: UITextView)
290
+ func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
291
+ func textViewDidChange(_ textView: UITextView)
292
+ func textViewDidChangeSelection(_ textView: UITextView)
293
+ func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange,
294
+ interaction: UITextItemInteraction) -> Bool
295
+ }
296
+
297
+ extension UITextViewDelegate {
298
+ public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { true }
299
+ public func textViewShouldEndEditing(_ textView: UITextView) -> Bool { true }
300
+ public func textViewDidBeginEditing(_ textView: UITextView) {}
301
+ public func textViewDidEndEditing(_ textView: UITextView) {}
302
+ public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { true }
303
+ public func textViewDidChange(_ textView: UITextView) {}
304
+ public func textViewDidChangeSelection(_ textView: UITextView) {}
305
+ public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange,
306
+ interaction: UITextItemInteraction) -> Bool { true }
307
+
308
+ // `delegate?.textViewDidChange?(textView)`: an optional requirement's
309
+ // call on iOS. A property of optional function type with the method's
310
+ // base name lets the same expression call the (always present) method.
311
+ public var textViewDidChange: ((UITextView) -> Void)? { { self.textViewDidChange($0) } }
312
+ public var textViewDidChangeSelection: ((UITextView) -> Void)? { { self.textViewDidChangeSelection($0) } }
313
+ public var textViewDidBeginEditing: ((UITextView) -> Void)? { { self.textViewDidBeginEditing($0) } }
314
+ public var textViewDidEndEditing: ((UITextView) -> Void)? { { self.textViewDidEndEditing($0) } }
315
+ }
316
+
317
+ /// A multi-line text view: editable, drawn as a `texteditor`; read-only, as
318
+ /// a `text` (see the top of the file).
319
+ @MainActor
320
+ open class UITextView: UIScrollView {
321
+ private var storage = NSMutableAttributedString(string: "")
322
+
323
+ /// The text; setting it gives all of it the view's font and color.
324
+ open var text: String! {
325
+ get { storage.string }
326
+ set {
327
+ storage = NSMutableAttributedString(string: newValue ?? "", attributes: baseAttributes)
328
+ clampSelection()
329
+ _setNeedsTranslation()
330
+ }
331
+ }
332
+ open var attributedText: NSAttributedString! {
333
+ get { NSAttributedString(attributedString: storage) }
334
+ set {
335
+ storage = NSMutableAttributedString(attributedString: newValue ?? NSAttributedString(string: ""))
336
+ clampSelection()
337
+ _setNeedsTranslation()
338
+ }
339
+ }
340
+ /// The font of all the text (setting it restyles the text, as on iOS).
341
+ open var font: UIFont? {
342
+ didSet {
343
+ if let font { storage.addAttribute(.font, value: font, range: NSRange(location: 0, length: storage.length)) }
344
+ _setNeedsTranslation()
345
+ }
346
+ }
347
+ open var textColor: UIColor? {
348
+ didSet {
349
+ if let textColor { storage.addAttribute(.foregroundColor, value: textColor, range: NSRange(location: 0, length: storage.length)) }
350
+ _setNeedsTranslation()
351
+ }
352
+ }
353
+ open var textAlignment: NSTextAlignment = .natural { didSet { _setNeedsTranslation() } }
354
+ open var isEditable = true { didSet { _setNeedsTranslation() } }
355
+ open var isSelectable = true { didSet { _setNeedsTranslation() } }
356
+ /// The selection: where the app put it, else the end of the last edit.
357
+ open var selectedRange = NSRange(location: 0, length: 0)
358
+ open var typingAttributes: [NSAttributedString.Key: Any] = [:]
359
+ open var linkTextAttributes: [NSAttributedString.Key: Any] = [:]
360
+ open var textContainerInset = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0) { didSet { _setNeedsTranslation() } }
361
+ public let textContainer = NSTextContainer()
362
+ open var keyboardType: UIKeyboardType = .default
363
+ open var autocapitalizationType: UITextAutocapitalizationType = .sentences
364
+ open var autocorrectionType: UITextAutocorrectionType = .default
365
+ open var spellCheckingType: UITextSpellCheckingType = .default
366
+ open var smartQuotesType: UITextSmartQuotesType = .default
367
+ open var smartDashesType: UITextSmartDashesType = .default
368
+ open var inlinePredictionType: UITextInlinePredictionType = .default
369
+ open var returnKeyType: UIReturnKeyType = .default
370
+ open var dataDetectorTypes: UIDataDetectorTypes = []
371
+ open var allowsEditingTextAttributes = false
372
+ open var adjustsFontForContentSizeCategory = false
373
+ open var clearsOnInsertion = false
374
+ open var isFindInteractionEnabled = false
375
+ open var inputAccessoryView: UIView?
376
+ open var inputView: UIView?
377
+ /// No marked (composing) text reaches Swift: the page commits it first.
378
+ open var markedTextRange: UITextRange? { nil }
379
+ /// Also the scroll view's delegate (`UITextViewDelegate` refines it).
380
+ open weak var delegate: UITextViewDelegate? { didSet { _scrollDelegate = delegate } }
381
+ /// Asked to transform pasted items (TextPaste.swift). The page pastes
382
+ /// text into the text area itself, so it is not consulted yet.
383
+ open weak var pasteDelegate: (any UITextPasteDelegate)?
384
+ /// What the view accepts when pasted or dropped into; kept.
385
+ open var pasteConfiguration: UIPasteConfiguration?
386
+ public private(set) var isFirstResponder = false
387
+
388
+ public override init(frame: CGRect) {
389
+ super.init(frame: frame)
390
+ isScrollEnabled = true
391
+ }
392
+
393
+ public convenience init(frame: CGRect, textContainer: NSTextContainer?) {
394
+ self.init(frame: frame)
395
+ }
396
+
397
+ public required init?(coder: NSCoder) { super.init(coder: coder) }
398
+
399
+ private var baseAttributes: [NSAttributedString.Key: Any] {
400
+ var attributes = typingAttributes
401
+ if let font { attributes[.font] = font }
402
+ if let textColor { attributes[.foregroundColor] = textColor }
403
+ return attributes
404
+ }
405
+
406
+ open var hasText: Bool { storage.length > 0 }
407
+
408
+ /// Takes the keyboard focus: the page focuses the text area, and the
409
+ /// delegate hears that editing began.
410
+ @discardableResult open func becomeFirstResponder() -> Bool {
411
+ guard !isFirstResponder else { return true }
412
+ guard isEditable, delegate?.textViewShouldBeginEditing(self) ?? true else { return false }
413
+ isFirstResponder = true
414
+ _setNeedsTranslation()
415
+ delegate?.textViewDidBeginEditing(self)
416
+ return true
417
+ }
418
+
419
+ @discardableResult open func resignFirstResponder() -> Bool {
420
+ guard isFirstResponder else { return true }
421
+ guard delegate?.textViewShouldEndEditing(self) ?? true else { return false }
422
+ isFirstResponder = false
423
+ _setNeedsTranslation()
424
+ delegate?.textViewDidEndEditing(self)
425
+ return true
426
+ }
427
+
428
+ open func select(_ sender: Any?) {}
429
+ open func selectAll(_ sender: Any?) { selectedRange = NSRange(location: 0, length: storage.length) }
430
+ open func scrollRangeToVisible(_ range: NSRange) {}
431
+
432
+ /// Typing: replaces the selection with `text` (as the keyboard would).
433
+ open func insertText(_ text: String) {
434
+ _replace(selectedRange, with: text)
435
+ }
436
+
437
+ open func deleteBackward() {
438
+ let range = selectedRange.length > 0 ? selectedRange
439
+ : NSRange(location: max(0, selectedRange.location - 1), length: selectedRange.location > 0 ? 1 : 0)
440
+ guard range.length > 0 else { return }
441
+ _replace(range, with: "")
442
+ }
443
+
444
+ // MARK: Positions and ranges
445
+
446
+ public var beginningOfDocument: UITextPosition { UITextPosition(offset: 0) }
447
+ public var endOfDocument: UITextPosition { UITextPosition(offset: storage.length) }
448
+ open var selectedTextRange: UITextRange? {
449
+ get {
450
+ UITextRange(start: UITextPosition(offset: selectedRange.location),
451
+ end: UITextPosition(offset: selectedRange.location + selectedRange.length))
452
+ }
453
+ set {
454
+ guard let newValue else { return }
455
+ selectedRange = NSRange(location: newValue.start.offset, length: max(0, newValue.end.offset - newValue.start.offset))
456
+ }
457
+ }
458
+ public func position(from position: UITextPosition, offset: Int) -> UITextPosition? {
459
+ let target = position.offset + offset
460
+ return (0...storage.length).contains(target) ? UITextPosition(offset: target) : nil
461
+ }
462
+ public func offset(from: UITextPosition, to toPosition: UITextPosition) -> Int { toPosition.offset - from.offset }
463
+ public func textRange(from fromPosition: UITextPosition, to toPosition: UITextPosition) -> UITextRange? {
464
+ UITextRange(start: fromPosition, end: toPosition)
465
+ }
466
+ public func text(in range: UITextRange) -> String? {
467
+ let nsRange = NSRange(location: range.start.offset, length: range.end.offset - range.start.offset)
468
+ guard nsRange.location >= 0, nsRange.length >= 0, nsRange.location + nsRange.length <= storage.length else { return nil }
469
+ return storage.attributedSubstring(from: nsRange).string
470
+ }
471
+ public func replace(_ range: UITextRange, withText text: String) {
472
+ _replace(NSRange(location: range.start.offset, length: range.end.offset - range.start.offset), with: text)
473
+ }
474
+
475
+ // MARK: Sizes
476
+
477
+ /// An estimate: the text wrapped at `size.width` less the insets, at
478
+ /// the font's line height (Swift has no text metrics).
479
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
480
+ let insets = textContainerInset
481
+ let padding = textContainer.lineFragmentPadding * 2 + insets.left + insets.right
482
+ let width = size.width.isFinite && size.width > 0 ? max(1, size.width - padding) : nil
483
+ let font = self.font ?? .preferredFont(forTextStyle: .body)
484
+ let text = _TextEstimate.size(of: storage.string, font: font, width: width)
485
+ return CGSize(width: width.map { $0 + padding } ?? text.width + padding,
486
+ height: text.height + insets.top + insets.bottom)
487
+ }
488
+
489
+ open override var intrinsicContentSize: CGSize {
490
+ isScrollEnabled ? CGSize(width: UIView.noIntrinsicMetric, height: UIView.noIntrinsicMetric)
491
+ : sizeThatFits(CGSize(width: bounds.width, height: .greatestFiniteMagnitude))
492
+ }
493
+
494
+ // MARK: Editing
495
+
496
+ /// The page's text area now shows `newText`: works out the edit, asks
497
+ /// the delegate, applies it and reports it (see the top of the file).
498
+ func _userEdited(_ newText: String) {
499
+ let old = Array(storage.string)
500
+ let new = Array(newText)
501
+ guard old != new else { return }
502
+ var prefix = 0
503
+ while prefix < old.count, prefix < new.count, old[prefix] == new[prefix] { prefix += 1 }
504
+ var suffix = 0
505
+ while suffix < old.count - prefix, suffix < new.count - prefix,
506
+ old[old.count - 1 - suffix] == new[new.count - 1 - suffix] { suffix += 1 }
507
+ let location = String(old[..<prefix]).utf16.count
508
+ let length = String(old[prefix..<(old.count - suffix)]).utf16.count
509
+ let replacement = String(new[prefix..<(new.count - suffix)])
510
+ let range = NSRange(location: location, length: length)
511
+ if !isFirstResponder { becomeFirstResponder() }
512
+ // A refused edit stays on the page until the text next changes: the
513
+ // text area is only told about text that differs from what it was sent.
514
+ guard delegate?.textView(self, shouldChangeTextIn: range, replacementText: replacement) ?? true else { return }
515
+ _replace(range, with: replacement)
516
+ }
517
+
518
+ private func _replace(_ range: NSRange, with replacement: String) {
519
+ let clamped = NSRange(location: min(range.location, storage.length),
520
+ length: max(0, min(range.length, storage.length - min(range.location, storage.length))))
521
+ var attributes = baseAttributes
522
+ if clamped.location > 0, typingAttributes.isEmpty {
523
+ // Typed text continues the attributes before it, as on iOS.
524
+ attributes.merge(storage.attributes(at: clamped.location - 1, effectiveRange: nil)) { _, previous in previous }
525
+ }
526
+ storage.replaceCharacters(in: clamped, with: NSAttributedString(string: replacement, attributes: attributes))
527
+ selectedRange = NSRange(location: clamped.location + replacement.utf16.count, length: 0)
528
+ _setNeedsTranslation()
529
+ delegate?.textViewDidChange(self)
530
+ delegate?.textViewDidChangeSelection(self)
531
+ }
532
+
533
+ private func clampSelection() {
534
+ let length = storage.length
535
+ let location = min(selectedRange.location, length)
536
+ selectedRange = NSRange(location: location, length: min(selectedRange.length, length - location))
537
+ }
538
+ }