@swiftbrowser/react 0.26.10 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -2
- package/dist/components/lists.d.ts +4 -3
- package/dist/components/lists.d.ts.map +1 -1
- package/dist/components/remoteTree.d.ts.map +1 -1
- package/dist/components/split.d.ts +6 -0
- package/dist/components/split.d.ts.map +1 -1
- package/dist/host/instance.d.ts +16 -0
- package/dist/host/instance.d.ts.map +1 -1
- package/dist/host/reconciler.d.ts +1 -1
- package/dist/host/reconciler.d.ts.map +1 -1
- package/dist/host/tree.d.ts +47 -2
- package/dist/host/tree.d.ts.map +1 -1
- package/dist/index.js +350 -192
- package/dist/index.js.map +1 -1
- package/dist/inheritedStyle.d.ts +31 -0
- package/dist/inheritedStyle.d.ts.map +1 -0
- package/dist/island.d.ts +8 -1
- package/dist/island.d.ts.map +1 -1
- package/dist/modifiers.d.ts +9 -0
- package/dist/modifiers.d.ts.map +1 -1
- package/dist/mount.d.ts +7 -0
- package/dist/mount.d.ts.map +1 -1
- package/dist/presentation.d.ts +10 -2
- package/dist/presentation.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, createElement, useSyncExternalStore, useLayoutEffect, useRef, Fragment, useState, Children, useEffect,
|
|
1
|
+
import { createContext, useContext, createElement, isValidElement, useMemo, useSyncExternalStore, useLayoutEffect, useRef, Fragment, useState, Children, useEffect, useId, cloneElement, useCallback } from "react";
|
|
2
2
|
import { DefaultEventPriority, ConcurrentRoot } from "react-reconciler/constants";
|
|
3
3
|
import Reconciler from "react-reconciler";
|
|
4
4
|
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
@@ -63,153 +63,41 @@ function usePlatform() {
|
|
|
63
63
|
function useRedacted() {
|
|
64
64
|
return useContext(ViewEnvironmentContext).redacted === true;
|
|
65
65
|
}
|
|
66
|
-
let currentUpdatePriority = 0;
|
|
67
|
-
function detach(parent, child) {
|
|
68
|
-
const at = parent.children.indexOf(child);
|
|
69
|
-
if (at >= 0) parent.children.splice(at, 1);
|
|
70
|
-
}
|
|
71
|
-
const hostConfig = {
|
|
72
|
-
supportsMutation: true,
|
|
73
|
-
supportsPersistence: false,
|
|
74
|
-
supportsHydration: false,
|
|
75
|
-
isPrimaryRenderer: true,
|
|
76
|
-
noTimeout: -1,
|
|
77
|
-
scheduleTimeout: setTimeout,
|
|
78
|
-
cancelTimeout: clearTimeout,
|
|
79
|
-
supportsMicrotasks: true,
|
|
80
|
-
scheduleMicrotask: queueMicrotask,
|
|
81
|
-
getRootHostContext: () => ({}),
|
|
82
|
-
getChildHostContext: (parent) => parent,
|
|
83
|
-
getPublicInstance: (instance) => instance,
|
|
84
|
-
prepareForCommit: () => null,
|
|
85
|
-
resetAfterCommit: (tree) => tree.commit(),
|
|
86
|
-
preparePortalMount: () => {
|
|
87
|
-
},
|
|
88
|
-
shouldSetTextContent: () => false,
|
|
89
|
-
createInstance: (type, props, tree) => {
|
|
90
|
-
if (type !== "sb") throw new Error(`Unknown host element <${type}>: only SwiftUI components render here.`);
|
|
91
|
-
return tree.createInstance(props);
|
|
92
|
-
},
|
|
93
|
-
createTextInstance: (text) => {
|
|
94
|
-
throw new Error(`Text strings must be rendered within a <Text> component (got ${JSON.stringify(text)}).`);
|
|
95
|
-
},
|
|
96
|
-
appendInitialChild: (parent, child) => parent.children.push(child),
|
|
97
|
-
finalizeInitialChildren: () => false,
|
|
98
|
-
commitMount: () => {
|
|
99
|
-
},
|
|
100
|
-
commitUpdate: (instance, _type, _prev, next, handle) => {
|
|
101
|
-
const tree = treeOf(handle);
|
|
102
|
-
if (tree) tree.updateInstance(instance, next);
|
|
103
|
-
else {
|
|
104
|
-
instance.props = next.props ?? {};
|
|
105
|
-
instance.on = next.on;
|
|
106
|
-
instance.target = next.target;
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
appendChild: (parent, child) => {
|
|
110
|
-
detach(parent, child);
|
|
111
|
-
parent.children.push(child);
|
|
112
|
-
},
|
|
113
|
-
appendChildToContainer: (tree, child) => {
|
|
114
|
-
detach(tree.root, child);
|
|
115
|
-
tree.root.children.push(child);
|
|
116
|
-
},
|
|
117
|
-
insertBefore: (parent, child, before) => {
|
|
118
|
-
detach(parent, child);
|
|
119
|
-
const at = parent.children.indexOf(before);
|
|
120
|
-
parent.children.splice(at < 0 ? parent.children.length : at, 0, child);
|
|
121
|
-
},
|
|
122
|
-
insertInContainerBefore: (tree, child, before) => {
|
|
123
|
-
detach(tree.root, child);
|
|
124
|
-
const at = tree.root.children.indexOf(before);
|
|
125
|
-
tree.root.children.splice(at < 0 ? tree.root.children.length : at, 0, child);
|
|
126
|
-
},
|
|
127
|
-
removeChild: (parent, child) => detach(parent, child),
|
|
128
|
-
removeChildFromContainer: (tree, child) => detach(tree.root, child),
|
|
129
|
-
clearContainer: (tree) => {
|
|
130
|
-
tree.root.children = [];
|
|
131
|
-
},
|
|
132
|
-
resetTextContent: () => {
|
|
133
|
-
},
|
|
134
|
-
commitTextUpdate: () => {
|
|
135
|
-
},
|
|
136
|
-
hideInstance: (instance) => {
|
|
137
|
-
instance.hidden = true;
|
|
138
|
-
},
|
|
139
|
-
unhideInstance: (instance) => {
|
|
140
|
-
instance.hidden = false;
|
|
141
|
-
},
|
|
142
|
-
hideTextInstance: () => {
|
|
143
|
-
},
|
|
144
|
-
unhideTextInstance: () => {
|
|
145
|
-
},
|
|
146
|
-
detachDeletedInstance: () => {
|
|
147
|
-
},
|
|
148
|
-
getInstanceFromNode: () => null,
|
|
149
|
-
beforeActiveInstanceBlur: () => {
|
|
150
|
-
},
|
|
151
|
-
afterActiveInstanceBlur: () => {
|
|
152
|
-
},
|
|
153
|
-
prepareScopeUpdate: () => {
|
|
154
|
-
},
|
|
155
|
-
getInstanceFromScope: () => null,
|
|
156
|
-
setCurrentUpdatePriority: (priority) => {
|
|
157
|
-
currentUpdatePriority = priority;
|
|
158
|
-
},
|
|
159
|
-
getCurrentUpdatePriority: () => currentUpdatePriority,
|
|
160
|
-
resolveUpdatePriority: () => currentUpdatePriority !== 0 ? currentUpdatePriority : DefaultEventPriority,
|
|
161
|
-
resetFormInstance: () => {
|
|
162
|
-
},
|
|
163
|
-
requestPostPaintCallback: () => {
|
|
164
|
-
},
|
|
165
|
-
shouldAttemptEagerTransition: () => false,
|
|
166
|
-
trackSchedulerEvent: () => {
|
|
167
|
-
},
|
|
168
|
-
resolveEventType: () => null,
|
|
169
|
-
resolveEventTimeStamp: () => -1.1,
|
|
170
|
-
maySuspendCommit: () => false,
|
|
171
|
-
maySuspendCommitOnUpdate: () => false,
|
|
172
|
-
maySuspendCommitInSyncRender: () => false,
|
|
173
|
-
suspendOnActiveViewTransition: () => {
|
|
174
|
-
},
|
|
175
|
-
getSuspendedCommitReason: () => null,
|
|
176
|
-
bindToConsole: (methodName, args) => () => console[methodName]?.(...args),
|
|
177
|
-
preloadInstance: () => true,
|
|
178
|
-
startSuspendingCommit: () => null,
|
|
179
|
-
suspendInstance: () => {
|
|
180
|
-
},
|
|
181
|
-
waitForCommitToBeReady: () => null,
|
|
182
|
-
NotPendingTransition: null,
|
|
183
|
-
HostTransitionContext: createContext(null),
|
|
184
|
-
rendererVersion: "0.3.1",
|
|
185
|
-
rendererPackageName: "@swiftbrowser/react",
|
|
186
|
-
extraDevToolsConfig: null
|
|
187
|
-
};
|
|
188
|
-
function treeOf(handle) {
|
|
189
|
-
let fiber = handle;
|
|
190
|
-
while (fiber) {
|
|
191
|
-
if (fiber.tag === 3) return fiber.stateNode.containerInfo;
|
|
192
|
-
fiber = fiber.return;
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
const reconciler = Reconciler(hostConfig);
|
|
197
66
|
const PREF_KIND = "$pref";
|
|
198
67
|
const HOIST_KIND = "$hoist";
|
|
199
|
-
function inheritTitleModes(screens
|
|
68
|
+
function inheritTitleModes(screens) {
|
|
200
69
|
let below = "large";
|
|
201
70
|
for (const screen of screens) {
|
|
202
|
-
const
|
|
203
|
-
if (!
|
|
204
|
-
const
|
|
205
|
-
|
|
71
|
+
const entry = screen.kind === "navscreen" ? screen.entry : null;
|
|
72
|
+
if (!entry) continue;
|
|
73
|
+
const base = entry.base;
|
|
74
|
+
const depth = typeof base["depth"] === "number" ? base["depth"] : 0;
|
|
75
|
+
let mode = typeof base["displayMode"] === "string" ? base["displayMode"] : "automatic";
|
|
206
76
|
if (mode === "automatic") {
|
|
207
|
-
if (depth > 0)
|
|
77
|
+
if (depth > 0) {
|
|
78
|
+
if (entry.props["displayMode"] !== below) entry.props = { ...base, displayMode: below };
|
|
79
|
+
} else if (entry.props !== base) entry.props = base;
|
|
208
80
|
mode = depth > 0 ? below : "large";
|
|
209
|
-
}
|
|
81
|
+
} else if (entry.props !== base) entry.props = base;
|
|
210
82
|
below = mode === "inline" ? "inline" : "large";
|
|
211
83
|
}
|
|
212
84
|
}
|
|
85
|
+
function markStale(node) {
|
|
86
|
+
for (let current = node; current && !current.stale; current = current.kind === "root" ? null : current.parent) current.stale = true;
|
|
87
|
+
}
|
|
88
|
+
function attach(parent, child, index) {
|
|
89
|
+
detach(parent, child);
|
|
90
|
+
if (index === void 0 || index < 0 || index > parent.children.length) parent.children.push(child);
|
|
91
|
+
else parent.children.splice(index, 0, child);
|
|
92
|
+
child.parent = parent;
|
|
93
|
+
markStale(parent);
|
|
94
|
+
}
|
|
95
|
+
function detach(parent, child) {
|
|
96
|
+
const at = parent.children.indexOf(child);
|
|
97
|
+
if (at >= 0) parent.children.splice(at, 1);
|
|
98
|
+
if (child.parent === parent) child.parent = null;
|
|
99
|
+
markStale(parent);
|
|
100
|
+
}
|
|
213
101
|
class HostTree {
|
|
214
102
|
constructor(sink, options = {}) {
|
|
215
103
|
this.sink = sink;
|
|
@@ -217,13 +105,14 @@ class HostTree {
|
|
|
217
105
|
}
|
|
218
106
|
sink;
|
|
219
107
|
options;
|
|
220
|
-
root = { id: 0, kind: "root", children: [], committedChildren: [] };
|
|
108
|
+
root = { id: 0, kind: "root", children: [], committedChildren: [], parent: null, stale: true, entry: null };
|
|
221
109
|
nextId = 1;
|
|
222
110
|
/** Emitted elements by id, for event dispatch. */
|
|
223
111
|
live = /* @__PURE__ */ new Map();
|
|
224
|
-
committedLive = /* @__PURE__ */ new Set();
|
|
225
112
|
/** Ids whose element changed kind: removed at the end of the next flush. */
|
|
226
113
|
retired = [];
|
|
114
|
+
/** Which flush is under way; an instance resolved in it carries the number. */
|
|
115
|
+
generation = 0;
|
|
227
116
|
/** `withAnimation`: stamped on the next `commit`. */
|
|
228
117
|
pendingAnimation;
|
|
229
118
|
/** `withAnimation(_:completionCriteria:_:completion:)`: stamped on the next `commit` with its serial; the callback waits in `completions`. */
|
|
@@ -249,7 +138,13 @@ class HostTree {
|
|
|
249
138
|
created: false,
|
|
250
139
|
committedProps: null,
|
|
251
140
|
committedParent: null,
|
|
252
|
-
committedChildren: []
|
|
141
|
+
committedChildren: [],
|
|
142
|
+
parent: null,
|
|
143
|
+
stale: true,
|
|
144
|
+
entry: null,
|
|
145
|
+
shown: false,
|
|
146
|
+
effectiveParent: null,
|
|
147
|
+
resolvedIn: 0
|
|
253
148
|
};
|
|
254
149
|
}
|
|
255
150
|
updateInstance(instance, next) {
|
|
@@ -268,6 +163,12 @@ class HostTree {
|
|
|
268
163
|
instance.props = next.props ?? {};
|
|
269
164
|
instance.on = next.on;
|
|
270
165
|
instance.target = next.target;
|
|
166
|
+
markStale(instance);
|
|
167
|
+
}
|
|
168
|
+
/** `node` is hidden or shown again (Suspense): it leaves or rejoins the emitted tree. */
|
|
169
|
+
setHidden(instance, hidden) {
|
|
170
|
+
instance.hidden = hidden;
|
|
171
|
+
markStale(instance);
|
|
271
172
|
}
|
|
272
173
|
/** Emit the ops for everything that changed since the last commit. */
|
|
273
174
|
commit() {
|
|
@@ -279,68 +180,134 @@ class HostTree {
|
|
|
279
180
|
this.pendingAnimation = void 0;
|
|
280
181
|
const completion = this.pendingCompletion;
|
|
281
182
|
this.pendingCompletion = void 0;
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
const
|
|
183
|
+
const generation = ++this.generation;
|
|
184
|
+
const root = this.root;
|
|
185
|
+
const rootEntry = { props: {}, base: {}, children: [], hoisted: [], escaping: [] };
|
|
186
|
+
const previousRoot = root.entry;
|
|
187
|
+
root.entry = rootEntry;
|
|
188
|
+
const resolved = [];
|
|
189
|
+
const path = [];
|
|
190
|
+
const targetOf = (target, ctx, hoist) => {
|
|
191
|
+
if (target === "root" || target === void 0) return root;
|
|
192
|
+
return ctx[target] ?? (hoist || this.options.remote ? root : void 0);
|
|
193
|
+
};
|
|
194
|
+
const keep = (contribution, target) => {
|
|
195
|
+
for (let i = path.length - 1; i >= 0; i--) {
|
|
196
|
+
const node = path[i];
|
|
197
|
+
if (node === target) return;
|
|
198
|
+
node.entry.escaping.push(contribution);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
const assign = (target, props) => {
|
|
202
|
+
const entry = target.entry;
|
|
203
|
+
if (target.kind !== "root" && entry.props === target.props) {
|
|
204
|
+
entry.props = { ...entry.props };
|
|
205
|
+
entry.base = entry.props;
|
|
206
|
+
}
|
|
207
|
+
Object.assign(entry.props, props);
|
|
208
|
+
if (entry.base !== entry.props) Object.assign(entry.base, props);
|
|
209
|
+
};
|
|
210
|
+
const contribute = (contribution, ctx) => {
|
|
211
|
+
if (contribution.kind === "pref") {
|
|
212
|
+
const target = targetOf(contribution.target, ctx, false);
|
|
213
|
+
if (target) assign(target, contribution.props);
|
|
214
|
+
keep(contribution, target);
|
|
215
|
+
} else {
|
|
216
|
+
const target = targetOf(contribution.target, ctx, true);
|
|
217
|
+
target.entry.hoisted.push(contribution.node);
|
|
218
|
+
contribution.node.effectiveParent = target;
|
|
219
|
+
keep(contribution, target);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
const visit = (child, sink, owner, ctx, hoistedTo) => {
|
|
286
223
|
if (child.hidden) return;
|
|
287
224
|
if (child.kind === PREF_KIND) {
|
|
288
|
-
|
|
289
|
-
const entry2 = target ? effective.get(target) : void 0;
|
|
290
|
-
if (entry2) Object.assign(entry2.props, child.props);
|
|
225
|
+
contribute({ kind: "pref", target: child.target, props: child.props }, ctx);
|
|
291
226
|
return;
|
|
292
227
|
}
|
|
293
228
|
if (child.kind === HOIST_KIND) {
|
|
294
|
-
const target = (child.target
|
|
295
|
-
const
|
|
296
|
-
for (const grandchild of child.children) visit(grandchild, entry2.hoisted, ctx);
|
|
229
|
+
const target = targetOf(child.target, ctx, true);
|
|
230
|
+
for (const grandchild of child.children) visit(grandchild, target.entry.hoisted, target, ctx, child.target ?? "root");
|
|
297
231
|
return;
|
|
298
232
|
}
|
|
299
|
-
|
|
300
|
-
|
|
233
|
+
if (hoistedTo !== void 0) {
|
|
234
|
+
child.effectiveParent = owner;
|
|
235
|
+
keep({ kind: "hoist", target: hoistedTo ?? void 0, node: child }, owner);
|
|
236
|
+
}
|
|
301
237
|
sink.push(child);
|
|
238
|
+
if (!child.stale && child.entry) {
|
|
239
|
+
child.effectiveParent = owner;
|
|
240
|
+
child.shown = true;
|
|
241
|
+
for (const contribution of child.entry.escaping) contribute(contribution, ctx);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const entry = { props: child.props, base: child.props, children: [], hoisted: [], escaping: [] };
|
|
245
|
+
resolved.push([child, child.entry]);
|
|
246
|
+
child.entry = entry;
|
|
247
|
+
child.stale = false;
|
|
248
|
+
child.shown = true;
|
|
249
|
+
child.effectiveParent = owner;
|
|
250
|
+
child.resolvedIn = generation;
|
|
302
251
|
const next = child.kind === "navscreen" ? { ...ctx, navscreen: child } : child.kind === "sheet" ? { ...ctx, sheet: child } : ctx;
|
|
303
|
-
|
|
252
|
+
path.push(child);
|
|
253
|
+
for (const grandchild of child.children) visit(grandchild, entry.children, child, next, void 0);
|
|
254
|
+
path.pop();
|
|
304
255
|
};
|
|
305
|
-
for (const child of
|
|
306
|
-
|
|
256
|
+
for (const child of root.children) visit(child, rootEntry.children, root, {}, void 0);
|
|
257
|
+
root.stale = false;
|
|
258
|
+
if (rootEntry.hoisted.length > 0) rootEntry.children.push(...rootEntry.hoisted);
|
|
259
|
+
for (const [node] of resolved) {
|
|
260
|
+
const entry = node.entry;
|
|
307
261
|
if (entry.hoisted.length > 0) entry.children.push(...entry.hoisted);
|
|
308
262
|
}
|
|
309
|
-
for (const [node
|
|
310
|
-
if (node
|
|
311
|
-
}
|
|
312
|
-
const live = /* @__PURE__ */ new Set();
|
|
313
|
-
const parentOf = /* @__PURE__ */ new Map();
|
|
314
|
-
for (const [node, entry] of effective) {
|
|
315
|
-
for (const child of entry.children) {
|
|
316
|
-
live.add(child);
|
|
317
|
-
parentOf.set(child, node);
|
|
318
|
-
}
|
|
263
|
+
for (const [node] of resolved) {
|
|
264
|
+
if (node.kind === "navstack") inheritTitleModes(node.entry.children);
|
|
319
265
|
}
|
|
320
266
|
const ops = [];
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
267
|
+
const left = [];
|
|
268
|
+
const arrived = /* @__PURE__ */ new Set();
|
|
269
|
+
const compare = (before, after) => {
|
|
270
|
+
if (!before) {
|
|
271
|
+
for (const child of after) arrived.add(child);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
let same = before.length === after.length;
|
|
275
|
+
for (let i = 0; same && i < after.length; i++) if (before[i] !== after[i]) same = false;
|
|
276
|
+
if (same) return;
|
|
277
|
+
const now = new Set(after);
|
|
278
|
+
for (const child of before) if (!now.has(child)) left.push(child);
|
|
279
|
+
const then = new Set(before);
|
|
280
|
+
for (const child of after) if (!then.has(child)) arrived.add(child);
|
|
281
|
+
};
|
|
282
|
+
compare(previousRoot?.children, rootEntry.children);
|
|
283
|
+
for (const [node, previous] of resolved) compare(previous?.children, node.entry.children);
|
|
284
|
+
const gone = (instance) => {
|
|
329
285
|
this.live.delete(instance.id);
|
|
286
|
+
instance.shown = false;
|
|
330
287
|
instance.created = false;
|
|
331
288
|
instance.committedProps = null;
|
|
332
289
|
instance.committedParent = null;
|
|
333
290
|
instance.committedChildren = [];
|
|
291
|
+
instance.stale = true;
|
|
292
|
+
const entry = instance.entry;
|
|
293
|
+
if (entry) {
|
|
294
|
+
for (const child of entry.children) if (child.effectiveParent === instance) gone(child);
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
for (const instance of left) {
|
|
298
|
+
if (!instance.shown || arrived.has(instance)) continue;
|
|
299
|
+
ops.push({ op: "remove", id: instance.id });
|
|
300
|
+
gone(instance);
|
|
334
301
|
}
|
|
335
302
|
const emit = (parent, entry) => {
|
|
336
|
-
const current = parent.committedChildren.filter((child) =>
|
|
303
|
+
const current = parent.committedChildren.filter((child) => child.shown && child.effectiveParent === parent);
|
|
337
304
|
entry.children.forEach((child, index) => {
|
|
338
|
-
const childEntry =
|
|
305
|
+
const childEntry = child.entry;
|
|
339
306
|
if (!child.created) {
|
|
340
307
|
ops.push({ op: "create", id: child.id, kind: child.kind, props: childEntry.props });
|
|
341
308
|
child.created = true;
|
|
342
309
|
this.live.set(child.id, child);
|
|
343
|
-
} else if (!deepEqual(childEntry.props, child.committedProps)) {
|
|
310
|
+
} else if (childEntry.props !== child.committedProps && !deepEqual(childEntry.props, child.committedProps)) {
|
|
344
311
|
ops.push({ op: "update", id: child.id, props: childEntry.props });
|
|
345
312
|
}
|
|
346
313
|
child.committedProps = childEntry.props;
|
|
@@ -351,21 +318,20 @@ class HostTree {
|
|
|
351
318
|
current.splice(index, 0, child);
|
|
352
319
|
}
|
|
353
320
|
child.committedParent = parent;
|
|
354
|
-
emit(child, childEntry);
|
|
321
|
+
if (child.resolvedIn === generation) emit(child, childEntry);
|
|
355
322
|
});
|
|
356
323
|
parent.committedChildren = entry.children;
|
|
357
324
|
};
|
|
358
|
-
emit(
|
|
325
|
+
emit(root, rootEntry);
|
|
359
326
|
for (const id of this.retired) ops.push({ op: "remove", id });
|
|
360
327
|
this.retired = [];
|
|
361
|
-
this.committedLive = live;
|
|
362
328
|
if (this.options.remote) {
|
|
363
|
-
if (!deepEqual(
|
|
364
|
-
ops.push({ op: "update", id: 0, props:
|
|
365
|
-
this.committedRootProps =
|
|
329
|
+
if (!deepEqual(rootEntry.props, this.committedRootProps)) {
|
|
330
|
+
ops.push({ op: "update", id: 0, props: rootEntry.props });
|
|
331
|
+
this.committedRootProps = rootEntry.props;
|
|
366
332
|
}
|
|
367
333
|
} else {
|
|
368
|
-
const scheme =
|
|
334
|
+
const scheme = rootEntry.props["colorScheme"];
|
|
369
335
|
const next = scheme === void 0 ? this.committedColorScheme === void 0 ? void 0 : null : scheme;
|
|
370
336
|
if (next !== void 0 && next !== this.committedColorScheme) {
|
|
371
337
|
ops.push({ op: "update", id: 0, props: { colorScheme: next } });
|
|
@@ -422,6 +388,132 @@ function deepEqual(a, b) {
|
|
|
422
388
|
if (keys.length !== Object.keys(right).length) return false;
|
|
423
389
|
return keys.every((key) => key in right && deepEqual(left[key], right[key]));
|
|
424
390
|
}
|
|
391
|
+
let currentUpdatePriority = 0;
|
|
392
|
+
const hostConfig = {
|
|
393
|
+
supportsMutation: true,
|
|
394
|
+
supportsPersistence: false,
|
|
395
|
+
supportsHydration: false,
|
|
396
|
+
isPrimaryRenderer: true,
|
|
397
|
+
noTimeout: -1,
|
|
398
|
+
scheduleTimeout: setTimeout,
|
|
399
|
+
cancelTimeout: clearTimeout,
|
|
400
|
+
supportsMicrotasks: true,
|
|
401
|
+
scheduleMicrotask: queueMicrotask,
|
|
402
|
+
getRootHostContext: () => ({}),
|
|
403
|
+
getChildHostContext: (parent) => parent,
|
|
404
|
+
getPublicInstance: (instance) => instance,
|
|
405
|
+
prepareForCommit: () => null,
|
|
406
|
+
resetAfterCommit: (tree) => tree.commit(),
|
|
407
|
+
preparePortalMount: () => {
|
|
408
|
+
},
|
|
409
|
+
shouldSetTextContent: () => false,
|
|
410
|
+
createInstance: (type, props, tree) => {
|
|
411
|
+
if (type !== "sb") throw new Error(`Unknown host element <${type}>: only SwiftUI components render here.`);
|
|
412
|
+
return tree.createInstance(props);
|
|
413
|
+
},
|
|
414
|
+
createTextInstance: (text) => {
|
|
415
|
+
throw new Error(`Text strings must be rendered within a <Text> component (got ${JSON.stringify(text)}).`);
|
|
416
|
+
},
|
|
417
|
+
appendInitialChild: (parent, child) => attach(parent, child),
|
|
418
|
+
finalizeInitialChildren: () => false,
|
|
419
|
+
commitMount: () => {
|
|
420
|
+
},
|
|
421
|
+
commitUpdate: (instance, _type, _prev, next, handle) => {
|
|
422
|
+
const tree = treeOf(handle);
|
|
423
|
+
if (tree) tree.updateInstance(instance, next);
|
|
424
|
+
else {
|
|
425
|
+
instance.props = next.props ?? {};
|
|
426
|
+
instance.on = next.on;
|
|
427
|
+
instance.target = next.target;
|
|
428
|
+
markStale(instance);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
appendChild: (parent, child) => attach(parent, child),
|
|
432
|
+
appendChildToContainer: (tree, child) => attach(tree.root, child),
|
|
433
|
+
insertBefore: (parent, child, before) => {
|
|
434
|
+
detach(parent, child);
|
|
435
|
+
const at = parent.children.indexOf(before);
|
|
436
|
+
attach(parent, child, at < 0 ? parent.children.length : at);
|
|
437
|
+
},
|
|
438
|
+
insertInContainerBefore: (tree, child, before) => {
|
|
439
|
+
detach(tree.root, child);
|
|
440
|
+
const at = tree.root.children.indexOf(before);
|
|
441
|
+
attach(tree.root, child, at < 0 ? tree.root.children.length : at);
|
|
442
|
+
},
|
|
443
|
+
removeChild: (parent, child) => detach(parent, child),
|
|
444
|
+
removeChildFromContainer: (tree, child) => detach(tree.root, child),
|
|
445
|
+
clearContainer: (tree) => {
|
|
446
|
+
for (const child of tree.root.children) child.parent = null;
|
|
447
|
+
tree.root.children = [];
|
|
448
|
+
markStale(tree.root);
|
|
449
|
+
},
|
|
450
|
+
resetTextContent: () => {
|
|
451
|
+
},
|
|
452
|
+
commitTextUpdate: () => {
|
|
453
|
+
},
|
|
454
|
+
hideInstance: (instance) => {
|
|
455
|
+
instance.hidden = true;
|
|
456
|
+
markStale(instance);
|
|
457
|
+
},
|
|
458
|
+
unhideInstance: (instance) => {
|
|
459
|
+
instance.hidden = false;
|
|
460
|
+
markStale(instance);
|
|
461
|
+
},
|
|
462
|
+
hideTextInstance: () => {
|
|
463
|
+
},
|
|
464
|
+
unhideTextInstance: () => {
|
|
465
|
+
},
|
|
466
|
+
detachDeletedInstance: () => {
|
|
467
|
+
},
|
|
468
|
+
getInstanceFromNode: () => null,
|
|
469
|
+
beforeActiveInstanceBlur: () => {
|
|
470
|
+
},
|
|
471
|
+
afterActiveInstanceBlur: () => {
|
|
472
|
+
},
|
|
473
|
+
prepareScopeUpdate: () => {
|
|
474
|
+
},
|
|
475
|
+
getInstanceFromScope: () => null,
|
|
476
|
+
setCurrentUpdatePriority: (priority) => {
|
|
477
|
+
currentUpdatePriority = priority;
|
|
478
|
+
},
|
|
479
|
+
getCurrentUpdatePriority: () => currentUpdatePriority,
|
|
480
|
+
resolveUpdatePriority: () => currentUpdatePriority !== 0 ? currentUpdatePriority : DefaultEventPriority,
|
|
481
|
+
resetFormInstance: () => {
|
|
482
|
+
},
|
|
483
|
+
requestPostPaintCallback: () => {
|
|
484
|
+
},
|
|
485
|
+
shouldAttemptEagerTransition: () => false,
|
|
486
|
+
trackSchedulerEvent: () => {
|
|
487
|
+
},
|
|
488
|
+
resolveEventType: () => null,
|
|
489
|
+
resolveEventTimeStamp: () => -1.1,
|
|
490
|
+
maySuspendCommit: () => false,
|
|
491
|
+
maySuspendCommitOnUpdate: () => false,
|
|
492
|
+
maySuspendCommitInSyncRender: () => false,
|
|
493
|
+
suspendOnActiveViewTransition: () => {
|
|
494
|
+
},
|
|
495
|
+
getSuspendedCommitReason: () => null,
|
|
496
|
+
bindToConsole: (methodName, args) => () => console[methodName]?.(...args),
|
|
497
|
+
preloadInstance: () => true,
|
|
498
|
+
startSuspendingCommit: () => null,
|
|
499
|
+
suspendInstance: () => {
|
|
500
|
+
},
|
|
501
|
+
waitForCommitToBeReady: () => null,
|
|
502
|
+
NotPendingTransition: null,
|
|
503
|
+
HostTransitionContext: createContext(null),
|
|
504
|
+
rendererVersion: "0.3.1",
|
|
505
|
+
rendererPackageName: "@swiftbrowser/react",
|
|
506
|
+
extraDevToolsConfig: null
|
|
507
|
+
};
|
|
508
|
+
function treeOf(handle) {
|
|
509
|
+
let fiber = handle;
|
|
510
|
+
while (fiber) {
|
|
511
|
+
if (fiber.tag === 3) return fiber.stateNode.containerInfo;
|
|
512
|
+
fiber = fiber.return;
|
|
513
|
+
}
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
const reconciler = Reconciler(hostConfig);
|
|
425
517
|
const DEFAULT_ENVIRONMENT = { colorScheme: "light", dynamicTypeSize: "large", horizontalSizeClass: "compact", scenePhase: "active", platform: "ios" };
|
|
426
518
|
const roots = /* @__PURE__ */ new Set();
|
|
427
519
|
const HostTreeContext = createContext(null);
|
|
@@ -654,6 +746,37 @@ function sb(kind, props, on, children, target) {
|
|
|
654
746
|
if (target) hostProps.target = target;
|
|
655
747
|
return children === void 0 ? createElement("sb", hostProps) : createElement("sb", hostProps, children);
|
|
656
748
|
}
|
|
749
|
+
const INHERITED_STYLE_KEYS = /* @__PURE__ */ new Set([
|
|
750
|
+
"font",
|
|
751
|
+
"fontWeight",
|
|
752
|
+
"bold",
|
|
753
|
+
"monospacedDigit",
|
|
754
|
+
"tint",
|
|
755
|
+
"lineLimit",
|
|
756
|
+
"multilineTextAlignment",
|
|
757
|
+
"imageScale",
|
|
758
|
+
"defaultMinListRowHeight"
|
|
759
|
+
]);
|
|
760
|
+
const PRESENTATION_KEYS = /* @__PURE__ */ new Set(["sheet", "fullScreenCover", "popover"]);
|
|
761
|
+
const InheritedStylesContext = createContext([]);
|
|
762
|
+
function useInheritedStyles() {
|
|
763
|
+
return useContext(InheritedStylesContext);
|
|
764
|
+
}
|
|
765
|
+
function styleOf(node) {
|
|
766
|
+
if (!isValidElement(node) || node.props.kind !== "styled") return {};
|
|
767
|
+
return node.props.props?.style ?? {};
|
|
768
|
+
}
|
|
769
|
+
function InheritStyle({ style, children }) {
|
|
770
|
+
const parent = useContext(InheritedStylesContext);
|
|
771
|
+
const key = JSON.stringify(style);
|
|
772
|
+
const value = useMemo(() => key === "{}" ? parent : [...parent, style], [parent, key]);
|
|
773
|
+
return createElement(InheritedStylesContext.Provider, { value }, children);
|
|
774
|
+
}
|
|
775
|
+
function replayStyles(styles, content) {
|
|
776
|
+
if (styles.length === 0) return content;
|
|
777
|
+
const provided = createElement(InheritedStylesContext.Provider, { value: styles }, content);
|
|
778
|
+
return styles.reduceRight((child, style) => sb("styled", { style }, void 0, child), provided);
|
|
779
|
+
}
|
|
657
780
|
const NavigationContext = createContext(null);
|
|
658
781
|
const ScreenDepthContext = createContext(0);
|
|
659
782
|
function useScreenDepth() {
|
|
@@ -694,6 +817,10 @@ function renderNode(root, node, stack) {
|
|
|
694
817
|
const children = node.children.length ? node.children.map((child) => renderNode(root, child, stack)) : void 0;
|
|
695
818
|
return createElement(Fragment, { key: node.id }, sb(node.kind, node.props, root.handlersFor(node.id), children));
|
|
696
819
|
}
|
|
820
|
+
function renderSheet(root, node, stack, inherited) {
|
|
821
|
+
const children = node.children.map((child) => renderNode(root, child, stack));
|
|
822
|
+
return createElement(Fragment, { key: node.id }, sb(node.kind, node.props, root.handlersFor(node.id), replayStyles(inherited, children)));
|
|
823
|
+
}
|
|
697
824
|
function renderScreen(root, screen, stack) {
|
|
698
825
|
const out = [screenPrefs(screen.props, "$screen")];
|
|
699
826
|
for (const child of screen.children) {
|
|
@@ -712,6 +839,7 @@ function RemoteScreen({ root, id }) {
|
|
|
712
839
|
function RemoteTree({ root, initialPath }) {
|
|
713
840
|
useSyncExternalStore(root.subscribe, root.getVersion, root.getVersion);
|
|
714
841
|
const environment = useContext(EnvironmentContext);
|
|
842
|
+
const inherited = useInheritedStyles();
|
|
715
843
|
const tree = useContext(HostTreeContext);
|
|
716
844
|
const navigation = useNavigation();
|
|
717
845
|
const depth = useScreenDepth();
|
|
@@ -767,7 +895,7 @@ function RemoteTree({ root, initialPath }) {
|
|
|
767
895
|
if ("colorScheme" in root.rootProps)
|
|
768
896
|
out.push(createElement(Fragment, { key: "$scheme" }, sb(PREF_KIND, { colorScheme: root.rootProps["colorScheme"] }, void 0, void 0, "root")));
|
|
769
897
|
for (const child of root.root.children) {
|
|
770
|
-
const drawn = renderNode(root, child, stack);
|
|
898
|
+
const drawn = child.kind === "sheet" && inherited.length > 0 ? renderSheet(root, child, stack, inherited) : renderNode(root, child, stack);
|
|
771
899
|
if (child.kind === "sheet" || child.kind === "alert") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "root")));
|
|
772
900
|
else if (child.kind === "toolbar" || child.kind === "searchfield") out.push(createElement(Fragment, { key: child.id }, sb(HOIST_KIND, void 0, void 0, drawn, "navscreen")));
|
|
773
901
|
else out.push(drawn);
|
|
@@ -960,6 +1088,7 @@ function mount(screen, element, options = {}) {
|
|
|
960
1088
|
platform: options.platform === void 0 || options.platform === "auto" ? decidePlatform(width) : options.platform
|
|
961
1089
|
};
|
|
962
1090
|
renderer.contentHeight = options.contentHeight ?? false;
|
|
1091
|
+
if (options.sidebarTitleBar === false) renderer.sidebarTitleBar = false;
|
|
963
1092
|
if (options.assets) renderer.setAssetCatalog(options.assets);
|
|
964
1093
|
if (options.app) browserEnvironment.files?.setApp?.(options.app);
|
|
965
1094
|
renderer.setEnvironment({ colorScheme: environment.colorScheme, dynamicTypeSize: environment.dynamicTypeSize, platform: environment.platform });
|
|
@@ -1268,6 +1397,7 @@ function SwiftUIView({
|
|
|
1268
1397
|
safeArea,
|
|
1269
1398
|
history = true,
|
|
1270
1399
|
keyboard = fit === "fill",
|
|
1400
|
+
sidebarTitleBar = true,
|
|
1271
1401
|
className,
|
|
1272
1402
|
style
|
|
1273
1403
|
}) {
|
|
@@ -1295,6 +1425,9 @@ function SwiftUIView({
|
|
|
1295
1425
|
instance.unmount();
|
|
1296
1426
|
};
|
|
1297
1427
|
}, [fit, history, keyboard]);
|
|
1428
|
+
useLayoutEffect(() => {
|
|
1429
|
+
if (mounted.current) mounted.current.renderer.sidebarTitleBar = sidebarTitleBar;
|
|
1430
|
+
}, [sidebarTitleBar, fit, history, keyboard]);
|
|
1298
1431
|
useLayoutEffect(() => {
|
|
1299
1432
|
mounted.current?.root.render(tree);
|
|
1300
1433
|
});
|
|
@@ -2196,7 +2329,7 @@ function NavigationSplitView(props) {
|
|
|
2196
2329
|
const detail = isValidElement(own.detail) && own.detail.type === NavigationStack ? own.detail : /* @__PURE__ */ jsx(NavigationStack, { children: own.detail });
|
|
2197
2330
|
const sidebar = own.sidebarWidth !== void 0 ? sb("styled", { style: { splitColumnWidth: splitColumnWidthHint(own.sidebarWidth) } }, void 0, own.sidebar) : own.sidebar;
|
|
2198
2331
|
return applyModifiers(
|
|
2199
|
-
sb("navsplit", { sidebarVisible }, { tap: toggle }, [
|
|
2332
|
+
sb("navsplit", { sidebarVisible }, { tap: toggle, columnwidth: (event) => own.onSidebarWidthChange?.(event.width) }, [
|
|
2200
2333
|
/* @__PURE__ */ jsx(SplitColumn, { report, children: /* @__PURE__ */ jsx(NavigationStack, { children: sidebar }) }, "sidebar"),
|
|
2201
2334
|
/* @__PURE__ */ jsx(SplitColumn, { report: null, children: detail }, "detail")
|
|
2202
2335
|
]),
|
|
@@ -2242,7 +2375,8 @@ function useReportSplitSelection(split, selected, clear, active2 = true) {
|
|
|
2242
2375
|
function OutsideSplit({ children }) {
|
|
2243
2376
|
return /* @__PURE__ */ jsx(SplitSelectionContext.Provider, { value: null, children });
|
|
2244
2377
|
}
|
|
2245
|
-
function SheetPresenter({ isPresented, onDismiss, content, fullScreen }) {
|
|
2378
|
+
function SheetPresenter({ isPresented, onDismiss, content, fullScreen, inherited }) {
|
|
2379
|
+
const around = useInheritedStyles();
|
|
2246
2380
|
const [presented, setPresented] = readBinding(isPresented);
|
|
2247
2381
|
if (!presented) return null;
|
|
2248
2382
|
const dismiss = () => {
|
|
@@ -2258,7 +2392,10 @@ function SheetPresenter({ isPresented, onDismiss, content, fullScreen }) {
|
|
|
2258
2392
|
"sheet",
|
|
2259
2393
|
{ detents },
|
|
2260
2394
|
{ tap: dismiss },
|
|
2261
|
-
|
|
2395
|
+
replayStyles(
|
|
2396
|
+
inherited && inherited.length > 0 ? [...around, ...inherited] : around,
|
|
2397
|
+
/* @__PURE__ */ jsx(NavigationContext.Provider, { value: null, children: /* @__PURE__ */ jsx(OutsideSplit, { children: /* @__PURE__ */ jsx(DismissContext.Provider, { value: dismiss, children: content }) }) })
|
|
2398
|
+
)
|
|
2262
2399
|
),
|
|
2263
2400
|
"root"
|
|
2264
2401
|
);
|
|
@@ -2641,6 +2778,7 @@ const MODIFIER_KEYS = /* @__PURE__ */ new Set([
|
|
|
2641
2778
|
"coordinateSpace",
|
|
2642
2779
|
"contentTransition",
|
|
2643
2780
|
"scrollDisabled",
|
|
2781
|
+
"defaultMinListRowHeight",
|
|
2644
2782
|
"scrollEdgeEffectStyle",
|
|
2645
2783
|
"scrollEdgeEffectHidden",
|
|
2646
2784
|
"contentMargins",
|
|
@@ -2764,13 +2902,30 @@ function applyModifiers(element, modifiers) {
|
|
|
2764
2902
|
const isPreference = (side) => isValidElement(side) && side.props.kind === PREF_KIND;
|
|
2765
2903
|
function wrap(element, modifiers, sides) {
|
|
2766
2904
|
let node = element;
|
|
2905
|
+
const holds = holdsViews(element);
|
|
2906
|
+
const presentations = [];
|
|
2767
2907
|
for (const [key, value] of modifiers) {
|
|
2768
2908
|
const inactive = value === void 0 || value === null && key !== "lineLimit" && key !== "badge";
|
|
2909
|
+
const before = sides.length;
|
|
2769
2910
|
const next = inactive ? node : apply(key, value, node, sides);
|
|
2770
2911
|
node = next === node ? neutral(key, node) : next;
|
|
2912
|
+
if (INHERITED_STYLE_KEYS.has(key)) {
|
|
2913
|
+
const style = styleOf(node);
|
|
2914
|
+
if (Object.keys(style).length > 0) for (const presentation of presentations) presentation.after.push(style);
|
|
2915
|
+
if (holds) node = createElement(InheritStyle, { style }, node);
|
|
2916
|
+
}
|
|
2917
|
+
if (PRESENTATION_KEYS.has(key) && sides.length > before) presentations.push({ at: before, after: [] });
|
|
2918
|
+
}
|
|
2919
|
+
for (const { at, after } of presentations) {
|
|
2920
|
+
const side = sides[at];
|
|
2921
|
+
if (after.length > 0 && isValidElement(side)) sides[at] = cloneElement(side, { inherited: after.reverse() });
|
|
2771
2922
|
}
|
|
2772
2923
|
return node;
|
|
2773
2924
|
}
|
|
2925
|
+
function holdsViews(element) {
|
|
2926
|
+
if (!isValidElement(element)) return false;
|
|
2927
|
+
return element.type !== "sb" || element.props.children !== void 0;
|
|
2928
|
+
}
|
|
2774
2929
|
const STYLED_KEYS = /* @__PURE__ */ new Set([
|
|
2775
2930
|
"padding",
|
|
2776
2931
|
"font",
|
|
@@ -2830,7 +2985,8 @@ const STYLED_KEYS = /* @__PURE__ */ new Set([
|
|
|
2830
2985
|
"containerRelativeFrame",
|
|
2831
2986
|
"contentTransition",
|
|
2832
2987
|
"scrollDisabled",
|
|
2833
|
-
"textSelection"
|
|
2988
|
+
"textSelection",
|
|
2989
|
+
"defaultMinListRowHeight"
|
|
2834
2990
|
]);
|
|
2835
2991
|
const ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
|
|
2836
2992
|
"buttonStyle",
|
|
@@ -3254,6 +3410,8 @@ function apply(key, value, node, sides) {
|
|
|
3254
3410
|
}
|
|
3255
3411
|
case "scrollDisabled":
|
|
3256
3412
|
return styled({ scrollDisabled: value === true }, node);
|
|
3413
|
+
case "defaultMinListRowHeight":
|
|
3414
|
+
return typeof value === "number" && Number.isFinite(value) ? styled({ defaultMinListRowHeight: Math.max(0, value) }, node) : styled({}, node);
|
|
3257
3415
|
case "textSelection":
|
|
3258
3416
|
return styled({ textSelection: value === "enabled" }, node);
|
|
3259
3417
|
case "contentTransition": {
|
|
@@ -6231,7 +6389,7 @@ function Chart(props) {
|
|
|
6231
6389
|
const key = mark.props.foregroundStyleBy;
|
|
6232
6390
|
if (key !== void 0 && !series.includes(key)) series.push(key);
|
|
6233
6391
|
}
|
|
6234
|
-
const
|
|
6392
|
+
const styleOf2 = (mark) => {
|
|
6235
6393
|
if (mark.props.foregroundStyle !== void 0) return shapeStyle(mark.props.foregroundStyle);
|
|
6236
6394
|
const key = mark.props.foregroundStyleBy;
|
|
6237
6395
|
if (key !== void 0) return { name: PALETTE[series.indexOf(key) % PALETTE.length] };
|
|
@@ -6289,7 +6447,7 @@ function Chart(props) {
|
|
|
6289
6447
|
);
|
|
6290
6448
|
};
|
|
6291
6449
|
const common = (mark) => {
|
|
6292
|
-
const base = { style:
|
|
6450
|
+
const base = { style: styleOf2(mark) };
|
|
6293
6451
|
if (mark.props.opacity !== void 0) base.opacity = mark.props.opacity;
|
|
6294
6452
|
return base;
|
|
6295
6453
|
};
|