@swiftbrowser/swift 0.0.0-stage → 0.1.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 (74) hide show
  1. package/Package.swift +23 -0
  2. package/README.md +12 -2
  3. package/Sources/Charts/Charts.swift +65 -0
  4. package/Sources/FoundationBridge/FoundationBridge.swift +77 -0
  5. package/Sources/FoundationBridge/Locale.swift +86 -0
  6. package/Sources/FoundationBridge/Timer.swift +48 -0
  7. package/Sources/FoundationBridge/UITextChecker.swift +30 -0
  8. package/Sources/FoundationLite/Common.swift +3 -0
  9. package/Sources/FoundationLite/FoundationLite.swift +171 -0
  10. package/Sources/FoundationLite/Interaction.swift +146 -0
  11. package/Sources/FoundationLite/Timer.swift +48 -0
  12. package/Sources/SwiftUI/API/Accessibility.swift +132 -0
  13. package/Sources/SwiftUI/API/Alert.swift +221 -0
  14. package/Sources/SwiftUI/API/Animation.swift +253 -0
  15. package/Sources/SwiftUI/API/App.swift +57 -0
  16. package/Sources/SwiftUI/API/Color.swift +161 -0
  17. package/Sources/SwiftUI/API/Controls.swift +268 -0
  18. package/Sources/SwiftUI/API/CustomLayout.swift +403 -0
  19. package/Sources/SwiftUI/API/Decorations.swift +92 -0
  20. package/Sources/SwiftUI/API/EditMode.swift +269 -0
  21. package/Sources/SwiftUI/API/Effects.swift +290 -0
  22. package/Sources/SwiftUI/API/Environment.swift +355 -0
  23. package/Sources/SwiftUI/API/Focus.swift +129 -0
  24. package/Sources/SwiftUI/API/Font.swift +131 -0
  25. package/Sources/SwiftUI/API/Gauge.swift +289 -0
  26. package/Sources/SwiftUI/API/Geometry.swift +89 -0
  27. package/Sources/SwiftUI/API/GeometryReader.swift +124 -0
  28. package/Sources/SwiftUI/API/Gestures.swift +342 -0
  29. package/Sources/SwiftUI/API/Grid.swift +188 -0
  30. package/Sources/SwiftUI/API/LabelStyle.swift +117 -0
  31. package/Sources/SwiftUI/API/Layout.swift +165 -0
  32. package/Sources/SwiftUI/API/Lists.swift +276 -0
  33. package/Sources/SwiftUI/API/Menu.swift +51 -0
  34. package/Sources/SwiftUI/API/Modifiers.swift +243 -0
  35. package/Sources/SwiftUI/API/Navigation.swift +371 -0
  36. package/Sources/SwiftUI/API/ObservableObject.swift +279 -0
  37. package/Sources/SwiftUI/API/OnChange.swift +48 -0
  38. package/Sources/SwiftUI/API/Phase8Controls.swift +394 -0
  39. package/Sources/SwiftUI/API/Picker.swift +176 -0
  40. package/Sources/SwiftUI/API/Presentation.swift +109 -0
  41. package/Sources/SwiftUI/API/Primitives.swift +390 -0
  42. package/Sources/SwiftUI/API/Publishers.swift +107 -0
  43. package/Sources/SwiftUI/API/RowActions.swift +83 -0
  44. package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
  45. package/Sources/SwiftUI/API/ShapeStyle.swift +311 -0
  46. package/Sources/SwiftUI/API/State.swift +127 -0
  47. package/Sources/SwiftUI/API/StrokeStyle.swift +30 -0
  48. package/Sources/SwiftUI/API/Tabs.swift +119 -0
  49. package/Sources/SwiftUI/API/Tasks.swift +35 -0
  50. package/Sources/SwiftUI/API/Timeline.swift +212 -0
  51. package/Sources/SwiftUI/API/Toolbar.swift +215 -0
  52. package/Sources/SwiftUI/API/View.swift +207 -0
  53. package/Sources/SwiftUI/API/ViewModifier.swift +40 -0
  54. package/Sources/SwiftUI/API/VisualEffect.swift +82 -0
  55. package/Sources/SwiftUI/Charts/Axis.swift +319 -0
  56. package/Sources/SwiftUI/Charts/Chart.swift +646 -0
  57. package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
  58. package/Sources/SwiftUI/Charts/Marks.swift +204 -0
  59. package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
  60. package/Sources/SwiftUI/Charts/Scales.swift +326 -0
  61. package/Sources/SwiftUI/Runtime/Executor.swift +83 -0
  62. package/Sources/SwiftUI/Runtime/Exports.swift +65 -0
  63. package/Sources/SwiftUI/Runtime/JSON.swift +71 -0
  64. package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
  65. package/Sources/SwiftUI/Runtime/Ops.swift +106 -0
  66. package/Sources/SwiftUI/Runtime/Reconciler.swift +210 -0
  67. package/Sources/SwiftUI/Runtime/Runtime.swift +1367 -0
  68. package/Sources/_FoundationCommon/Bundle.swift +82 -0
  69. package/Sources/_FoundationCommon/UserDefaults.swift +170 -0
  70. package/Sources/_FoundationCommon/_FoundationCommon.swift +10 -0
  71. package/index.d.ts +2 -0
  72. package/index.mjs +16 -0
  73. package/package.json +28 -4
  74. package/sync-sources.mjs +19 -0
@@ -0,0 +1,210 @@
1
+ /// A node of the element tree produced from the mounted view tree each pass.
2
+ struct _Element {
3
+ var kind: String
4
+ var props: _JSON
5
+ var children: [_Element]
6
+ var handler: ((_JSON) -> Void)?
7
+ /// Identity for keyed children (`ForEach`); unkeyed elements match by position.
8
+ var key: AnyHashable?
9
+ /// What makes this element a selectable or deletable `List` row (Phase 8).
10
+ var row: _RowMark?
11
+ /// Identity of this element value: a fresh token per produced element,
12
+ /// kept by copies. Two elements with one token are the same subtree (a
13
+ /// clean node's cached output), which the reconciler skips whole.
14
+ var token: Int = _Element.nextToken()
15
+
16
+ nonisolated(unsafe) private static var tokenCounter = 0
17
+ static func nextToken() -> Int {
18
+ tokenCounter += 1
19
+ return tokenCounter
20
+ }
21
+ }
22
+
23
+ /// Row metadata the runtime attaches while producing elements and consumes
24
+ /// when it emits a `list`: a `.tag` (or a `ForEach` id, the implicit tag), a
25
+ /// `NavigationLink(value:)`'s value and handler, and the `onDelete` of the
26
+ /// row's `ForEach`.
27
+ struct _RowMark {
28
+ var tag: AnyHashable?
29
+ var linkValue: AnyHashable?
30
+ var linkHandler: ((_JSON) -> Void)?
31
+ var delete: (() -> Void)?
32
+ var deleteDisabled = false
33
+
34
+ var isEmpty: Bool { tag == nil && linkValue == nil && delete == nil && !deleteDisabled }
35
+
36
+ /// Fills what `self` lacks from an inner element's mark.
37
+ func merged(with inner: _RowMark) -> _RowMark {
38
+ var result = self
39
+ if result.tag == nil { result.tag = inner.tag }
40
+ if result.linkValue == nil {
41
+ result.linkValue = inner.linkValue
42
+ result.linkHandler = inner.linkHandler
43
+ }
44
+ if result.delete == nil { result.delete = inner.delete }
45
+ result.deleteDisabled = result.deleteDisabled || inner.deleteDisabled
46
+ return result
47
+ }
48
+ }
49
+
50
+ /// Diffs successive element trees and emits ops. Ids are assigned by position
51
+ /// (or key) and kind: an element that keeps both keeps its id across passes.
52
+ @MainActor
53
+ final class _Reconciler {
54
+ struct Rendered {
55
+ var id: Int
56
+ var kind: String
57
+ var props: _JSON
58
+ var children: [Rendered]
59
+ var key: AnyHashable?
60
+ /// The token of the element this was rendered from.
61
+ var token: Int
62
+ }
63
+
64
+ private(set) var roots: [Rendered] = []
65
+ private var nextId = 1
66
+ private(set) var handlers: [Int: (_JSON) -> Void] = [:]
67
+
68
+ func update(with elements: [_Element], animation: _JSON? = nil) -> [_Op] {
69
+ var ops: [_Op] = []
70
+ roots = diff(parent: 0, old: roots, new: elements, ops: &ops)
71
+ ops.append(.commit(animation: animation))
72
+ return ops
73
+ }
74
+
75
+ private func diff(parent: Int, old: [Rendered], new: [_Element], ops: inout [_Op]) -> [Rendered] {
76
+ let keyed = new.contains { $0.key != nil } || old.contains { $0.key != nil }
77
+ return keyed
78
+ ? diffKeyed(parent: parent, old: old, new: new, ops: &ops)
79
+ : diffPositional(parent: parent, old: old, new: new, ops: &ops)
80
+ }
81
+
82
+ private func diffPositional(parent: Int, old: [Rendered], new: [_Element], ops: inout [_Op]) -> [Rendered] {
83
+ var result: [Rendered] = []
84
+ result.reserveCapacity(new.count)
85
+
86
+ for (index, element) in new.enumerated() {
87
+ if index < old.count, old[index].kind == element.kind {
88
+ result.append(reuse(old[index], for: element, ops: &ops))
89
+ } else {
90
+ if index < old.count { destroy(old[index], ops: &ops) }
91
+ result.append(create(element, parent: parent, index: index, ops: &ops))
92
+ }
93
+ }
94
+
95
+ for stale in old.dropFirst(new.count) {
96
+ destroy(stale, ops: &ops)
97
+ }
98
+ return result
99
+ }
100
+
101
+ /// Keyed children: match by key, move what survives, create the rest.
102
+ /// Unkeyed children in a keyed list are matched by their position.
103
+ private func diffKeyed(parent: Int, old: [Rendered], new: [_Element], ops: inout [_Op]) -> [Rendered] {
104
+ func identity(_ key: AnyHashable?, _ index: Int) -> AnyHashable {
105
+ key ?? AnyHashable(_PositionKey(index: index))
106
+ }
107
+
108
+ var oldByIdentity: [AnyHashable: Rendered] = [:]
109
+ for (index, rendered) in old.enumerated() {
110
+ oldByIdentity[identity(rendered.key, index)] = rendered
111
+ }
112
+ let newIdentities = new.enumerated().map { identity($1.key, $0) }
113
+ let kept = Set(newIdentities.enumerated().compactMap { index, id in
114
+ oldByIdentity[id].map { $0.kind == new[index].kind ? id : nil } ?? nil
115
+ })
116
+
117
+ // 1. Remove everything that does not survive, so the parent's children
118
+ // are exactly the kept old elements in their old order.
119
+ var pending: [AnyHashable] = []
120
+ for (index, rendered) in old.enumerated() {
121
+ let id = identity(rendered.key, index)
122
+ if kept.contains(id) { pending.append(id) } else { destroy(rendered, ops: &ops) }
123
+ }
124
+
125
+ // 2. Walk the new order; anything not already at the front is moved there.
126
+ var result: [Rendered] = []
127
+ result.reserveCapacity(new.count)
128
+ for (index, element) in new.enumerated() {
129
+ let id = newIdentities[index]
130
+ if kept.contains(id), let previous = oldByIdentity[id] {
131
+ if pending.first == id {
132
+ pending.removeFirst()
133
+ } else {
134
+ pending.removeAll { $0 == id }
135
+ ops.append(.insert(parent: parent, id: previous.id, index: index))
136
+ }
137
+ var rendered = reuse(previous, for: element, ops: &ops)
138
+ rendered.key = element.key
139
+ result.append(rendered)
140
+ } else {
141
+ var rendered = create(element, parent: parent, index: index, ops: &ops)
142
+ rendered.key = element.key
143
+ result.append(rendered)
144
+ }
145
+ }
146
+ return result
147
+ }
148
+
149
+ private func reuse(_ previous: Rendered, for element: _Element, ops: inout [_Op]) -> Rendered {
150
+ // The same element value as last pass (a clean subtree's cached
151
+ // output): nothing below it changed, and its handlers are registered.
152
+ if previous.token == element.token { return previous }
153
+ var rendered = previous
154
+ rendered.token = element.token
155
+ if rendered.props != element.props {
156
+ ops.append(.update(id: rendered.id, props: element.props))
157
+ rendered.props = element.props
158
+ }
159
+ setHandler(element.handler, for: rendered.id)
160
+ rendered.children = diff(parent: rendered.id, old: rendered.children, new: element.children, ops: &ops)
161
+ return rendered
162
+ }
163
+
164
+ private func create(_ element: _Element, parent: Int, index: Int, ops: inout [_Op]) -> Rendered {
165
+ let id = nextId
166
+ nextId += 1
167
+ ops.append(.create(id: id, kind: element.kind, props: element.props))
168
+ ops.append(.insert(parent: parent, id: id, index: index))
169
+ setHandler(element.handler, for: id)
170
+ let children = element.children.enumerated().map { childIndex, child in
171
+ create(child, parent: id, index: childIndex, ops: &ops)
172
+ }
173
+ return Rendered(id: id, kind: element.kind, props: element.props, children: children, key: element.key, token: element.token)
174
+ }
175
+
176
+ private func destroy(_ rendered: Rendered, ops: inout [_Op]) {
177
+ ops.append(.remove(id: rendered.id))
178
+ forget(rendered)
179
+ }
180
+
181
+ private func forget(_ rendered: Rendered) {
182
+ handlers[rendered.id] = nil
183
+ for child in rendered.children { forget(child) }
184
+ }
185
+
186
+ private func setHandler(_ handler: ((_JSON) -> Void)?, for id: Int) {
187
+ if let handler {
188
+ handlers[id] = handler
189
+ } else {
190
+ handlers[id] = nil
191
+ }
192
+ }
193
+ }
194
+
195
+ private struct _PositionKey: Hashable {
196
+ let index: Int
197
+ }
198
+
199
+ /// Key given to the elements a keyed mounted node produces.
200
+ struct _ElementKey: Hashable {
201
+ let base: AnyHashable
202
+ let index: Int
203
+ }
204
+
205
+ /// `_ElementKey` qualified by the keyed group's position among its siblings,
206
+ /// so two `ForEach`es in one container never share a key.
207
+ struct _GroupKey: Hashable {
208
+ let position: Int
209
+ let key: AnyHashable
210
+ }