rnxsim 0.1.519 → 0.1.521
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/cli/cloud-client.ts +419 -287
- package/cli/cloud-dispatch.ts +2 -21
- package/cli/cloud-session.ts +31 -85
- package/cli/commands/box.ts +15 -11
- package/cli/commands/inspect.ts +34 -1
- package/cli/commands/platform.ts +184 -232
- package/cli/main.ts +10 -2
- package/cli/outbound-endpoints.ts +21 -6
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +7 -2
- package/dist-lib/bridge-contract-input.mjs +7 -2
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud.cjs +18 -2
- package/dist-lib/cloud.mjs +18 -2
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +112 -39
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +44 -117
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +30 -1
- package/dist-lib/menu.mjs +27 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +41 -4
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +138 -164
- package/dist-lib/swift.cjs +766 -24
- package/dist-lib/vite.cjs +103 -30
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +72 -5
- package/src/bridge-contract-input.ts +10 -0
- package/src/bridge-contract.ts +5 -0
- package/src/cloud-contract.ts +7 -1
- package/src/cloud.ts +45 -6
- package/src/connect.ts +1 -1
- package/src/menu.ts +44 -0
- package/src/swift.ts +2 -0
- package/src/vite-plugin-one.ts +12 -0
- package/src/vite-plugin-swift.ts +141 -39
package/dist-lib/swift.cjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.521 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
|
+
var __create = Object.create;
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
5
6
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
7
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
9
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
10
|
var __export = (target, all) => {
|
|
9
11
|
for (var name in all)
|
|
@@ -17,19 +19,32 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
19
|
}
|
|
18
20
|
return to;
|
|
19
21
|
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
20
30
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
31
|
|
|
22
32
|
// src/swift.ts
|
|
23
33
|
var swift_exports = {};
|
|
24
34
|
__export(swift_exports, {
|
|
25
|
-
createSwiftModule: () => createSwiftModule
|
|
35
|
+
createSwiftModule: () => createSwiftModule,
|
|
36
|
+
createSwiftView: () => createSwiftView
|
|
26
37
|
});
|
|
27
38
|
module.exports = __toCommonJS(swift_exports);
|
|
28
39
|
|
|
29
40
|
// ../sootsim-swift/src/mount.tsx
|
|
41
|
+
var import_native = require("@react-navigation/native");
|
|
42
|
+
var import_native_stack = require("@react-navigation/native-stack");
|
|
43
|
+
var import_runtime = require("contrast-kit/runtime");
|
|
30
44
|
var import_ui = require("contrast-kit/ui");
|
|
31
45
|
var import_react = require("react");
|
|
32
46
|
var import_react_native = require("react-native");
|
|
47
|
+
var import_react_native_bottom_tabs = __toESM(require("react-native-bottom-tabs"), 1);
|
|
33
48
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
34
49
|
function isRecord(value) {
|
|
35
50
|
return typeof value === "object" && value !== null;
|
|
@@ -78,6 +93,7 @@ function readTree(text) {
|
|
|
78
93
|
return value.map(readNode);
|
|
79
94
|
}
|
|
80
95
|
var WASI_BADF = 8;
|
|
96
|
+
var WASI_INVAL = 28;
|
|
81
97
|
function wasiImports(host) {
|
|
82
98
|
return {
|
|
83
99
|
args_get: () => 0,
|
|
@@ -94,10 +110,18 @@ function wasiImports(host) {
|
|
|
94
110
|
},
|
|
95
111
|
fd_close: () => WASI_BADF,
|
|
96
112
|
fd_fdstat_get: () => WASI_BADF,
|
|
113
|
+
fd_fdstat_set_flags: () => WASI_BADF,
|
|
114
|
+
fd_filestat_get: () => WASI_BADF,
|
|
115
|
+
fd_filestat_set_size: () => WASI_BADF,
|
|
116
|
+
fd_filestat_set_times: () => WASI_BADF,
|
|
117
|
+
fd_pread: () => WASI_BADF,
|
|
97
118
|
fd_prestat_get: () => WASI_BADF,
|
|
98
119
|
fd_prestat_dir_name: () => WASI_BADF,
|
|
99
120
|
fd_read: () => WASI_BADF,
|
|
121
|
+
fd_readdir: () => WASI_BADF,
|
|
100
122
|
fd_seek: () => WASI_BADF,
|
|
123
|
+
fd_sync: () => WASI_BADF,
|
|
124
|
+
fd_tell: () => WASI_BADF,
|
|
101
125
|
fd_write: (_fd, iovsPtr, iovsLen, writtenPtr) => {
|
|
102
126
|
const view = new DataView(host.bytes().buffer);
|
|
103
127
|
let written = 0;
|
|
@@ -107,7 +131,39 @@ function wasiImports(host) {
|
|
|
107
131
|
host.writeU32(writtenPtr, written);
|
|
108
132
|
return 0;
|
|
109
133
|
},
|
|
134
|
+
path_create_directory: () => WASI_BADF,
|
|
135
|
+
path_filestat_get: () => WASI_BADF,
|
|
136
|
+
path_filestat_set_times: () => WASI_BADF,
|
|
137
|
+
path_link: () => WASI_BADF,
|
|
110
138
|
path_open: () => WASI_BADF,
|
|
139
|
+
path_readlink: () => WASI_BADF,
|
|
140
|
+
path_remove_directory: () => WASI_BADF,
|
|
141
|
+
path_rename: () => WASI_BADF,
|
|
142
|
+
path_symlink: () => WASI_BADF,
|
|
143
|
+
path_unlink_file: () => WASI_BADF,
|
|
144
|
+
// the 6.3 sdk's libraries call the clocks even when the app never reads
|
|
145
|
+
// the time, so instantiation fails without them. clock 0 is realtime
|
|
146
|
+
// and clock 1 is monotonic, the only two swift asks for here; anything
|
|
147
|
+
// else is a loud inval. the resolutions are wasi-libc's for those two:
|
|
148
|
+
// a millisecond for the wall clock and a nanosecond for the monotonic one.
|
|
149
|
+
clock_res_get: (clockId, resolutionPtr) => {
|
|
150
|
+
const resolution = clockId === 1 ? 1n : clockId === 0 ? 1000000n : null;
|
|
151
|
+
if (resolution === null) return WASI_INVAL;
|
|
152
|
+
host.writeU64(resolutionPtr, resolution);
|
|
153
|
+
return 0;
|
|
154
|
+
},
|
|
155
|
+
clock_time_get: (clockId, _precision, timePtr) => {
|
|
156
|
+
const nanos = clockId === 1 ? BigInt(Math.round(performance.now() * 1e6)) : clockId === 0 ? BigInt(Date.now()) * 1000000n : null;
|
|
157
|
+
if (nanos === null) return WASI_INVAL;
|
|
158
|
+
host.writeU64(timePtr, nanos);
|
|
159
|
+
return 0;
|
|
160
|
+
},
|
|
161
|
+
// a poll is the one call the tenant cannot answer: there is no descriptor
|
|
162
|
+
// to wait on and no clock to sleep against, so it says so instead of
|
|
163
|
+
// returning an event nobody subscribed to.
|
|
164
|
+
poll_oneoff: () => {
|
|
165
|
+
throw new Error("swift app polled for events, which the tenant has no source for");
|
|
166
|
+
},
|
|
111
167
|
proc_exit: (code) => {
|
|
112
168
|
throw new Error(`swift app exited with code ${code}`);
|
|
113
169
|
},
|
|
@@ -134,6 +190,20 @@ function pointerExport(exports2, name) {
|
|
|
134
190
|
return result;
|
|
135
191
|
};
|
|
136
192
|
}
|
|
193
|
+
function maybePointerExport(exports2, name) {
|
|
194
|
+
const value = exports2[name];
|
|
195
|
+
if (value === void 0) return void 0;
|
|
196
|
+
if (typeof value !== "function") {
|
|
197
|
+
throw new Error(`swift export ${name} is not a function`);
|
|
198
|
+
}
|
|
199
|
+
return (...args) => {
|
|
200
|
+
const result = Reflect.apply(value, void 0, args);
|
|
201
|
+
if (typeof result !== "number") {
|
|
202
|
+
throw new Error(`swift export ${name} returned ${typeof result}`);
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
137
207
|
function voidExport(exports2, name) {
|
|
138
208
|
const fn = rawExport(exports2, name);
|
|
139
209
|
return (...args) => {
|
|
@@ -150,6 +220,9 @@ function instantiate(module2) {
|
|
|
150
220
|
writeU32(ptr, value) {
|
|
151
221
|
new DataView(requireMemory().buffer).setUint32(ptr, value, true);
|
|
152
222
|
},
|
|
223
|
+
writeU64(ptr, value) {
|
|
224
|
+
new DataView(requireMemory().buffer).setBigUint64(ptr, value, true);
|
|
225
|
+
},
|
|
153
226
|
bytes: () => new Uint8Array(requireMemory().buffer)
|
|
154
227
|
};
|
|
155
228
|
const instance = new WebAssembly.Instance(module2, {
|
|
@@ -163,6 +236,8 @@ function instantiate(module2) {
|
|
|
163
236
|
const initialize = voidExport(instance.exports, "_initialize");
|
|
164
237
|
const mainArgv = voidExport(instance.exports, "__main_argc_argv");
|
|
165
238
|
const mount = pointerExport(instance.exports, "rnx_mount");
|
|
239
|
+
const mountViewExport = maybePointerExport(instance.exports, "rnx_mount_view");
|
|
240
|
+
const hasViewExport = maybePointerExport(instance.exports, "rnx_has_view");
|
|
166
241
|
const event = pointerExport(instance.exports, "rnx_event");
|
|
167
242
|
const stateExport = pointerExport(instance.exports, "rnx_state_export");
|
|
168
243
|
const stateImport = voidExport(instance.exports, "rnx_state_import");
|
|
@@ -186,7 +261,30 @@ function instantiate(module2) {
|
|
|
186
261
|
initialize();
|
|
187
262
|
mainArgv(0, 0);
|
|
188
263
|
return {
|
|
189
|
-
mount: () =>
|
|
264
|
+
mount: () => {
|
|
265
|
+
if ((hasViewExport?.() ?? 0) === 1) {
|
|
266
|
+
throw new Error(
|
|
267
|
+
"swift package has an RNXPackage entry, not an App entry; mount it as a view or make its @main type conform to App"
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return readTree(readBuffer(mount()));
|
|
271
|
+
},
|
|
272
|
+
mountView: (props) => {
|
|
273
|
+
if (!mountViewExport) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
"swift artifact has no rnx_mount_view export; rebuild the swift package"
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
if ((hasViewExport?.() ?? 0) !== 1) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
"swift package has no RNXPackage entry; its @main type must conform to RNXPackage to mount as a view"
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
return readTree(
|
|
284
|
+
readBuffer(withPayload(props, (ptr, length) => mountViewExport(ptr, length)))
|
|
285
|
+
);
|
|
286
|
+
},
|
|
287
|
+
hasView: () => (hasViewExport?.() ?? 0) === 1,
|
|
190
288
|
deliver: (handlerId2, payload) => readTree(
|
|
191
289
|
readBuffer(
|
|
192
290
|
withPayload(
|
|
@@ -281,24 +379,41 @@ function resolveModifier(modifier) {
|
|
|
281
379
|
return { ...modifier, color: resolveColor(color) };
|
|
282
380
|
}
|
|
283
381
|
var NODE_COMPONENTS = {
|
|
382
|
+
Alert: SwiftAlert,
|
|
383
|
+
BottomSheet: import_ui.BottomSheet,
|
|
284
384
|
Button: import_ui.Button,
|
|
285
385
|
Capsule: import_ui.Capsule,
|
|
286
386
|
Circle: import_ui.Circle,
|
|
387
|
+
ConfirmationDialog: import_ui.ConfirmationDialog,
|
|
388
|
+
ContextMenu: import_ui.ContextMenu,
|
|
389
|
+
DatePicker: import_ui.DatePicker,
|
|
287
390
|
Divider: import_ui.Divider,
|
|
391
|
+
Ellipse: import_ui.Ellipse,
|
|
288
392
|
Form: import_ui.Form,
|
|
393
|
+
GlassEffectContainer: import_ui.GlassEffectContainer,
|
|
289
394
|
Group: import_ui.Group,
|
|
290
395
|
HStack: import_ui.HStack,
|
|
291
396
|
Image: import_ui.Image,
|
|
397
|
+
Label: import_ui.Label,
|
|
398
|
+
LazyVStack: import_ui.LazyVStack,
|
|
292
399
|
List: import_ui.List,
|
|
400
|
+
Menu: import_ui.Menu,
|
|
401
|
+
Picker: import_ui.Picker,
|
|
402
|
+
ProgressView: import_ui.ProgressView,
|
|
293
403
|
Rectangle: import_ui.Rectangle,
|
|
294
404
|
RoundedRectangle: import_ui.RoundedRectangle,
|
|
295
405
|
ScrollView: import_ui.ScrollView,
|
|
296
406
|
Section: import_ui.Section,
|
|
407
|
+
SecureField: import_ui.SecureField,
|
|
297
408
|
Slider: import_ui.Slider,
|
|
298
409
|
Spacer: import_ui.Spacer,
|
|
410
|
+
Stepper: import_ui.Stepper,
|
|
411
|
+
SwipeActions: import_ui.SwipeActions,
|
|
299
412
|
Text: import_ui.Text,
|
|
300
413
|
TextField: import_ui.TextField,
|
|
301
414
|
Toggle: import_ui.Toggle,
|
|
415
|
+
Tab: SwiftTabScene,
|
|
416
|
+
TabView: SwiftTabView,
|
|
302
417
|
VStack: import_ui.VStack,
|
|
303
418
|
ZStack: import_ui.ZStack
|
|
304
419
|
};
|
|
@@ -346,9 +461,142 @@ function fontStyle(font) {
|
|
|
346
461
|
}
|
|
347
462
|
return style;
|
|
348
463
|
}
|
|
464
|
+
function sameValue(a, b) {
|
|
465
|
+
if (a === b) return true;
|
|
466
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
467
|
+
if (a.length !== b.length) return false;
|
|
468
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
469
|
+
if (!sameValue(a[index], b[index])) return false;
|
|
470
|
+
}
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
if (isRecord(a) && isRecord(b)) {
|
|
474
|
+
const keys = Object.keys(a);
|
|
475
|
+
if (keys.length !== Object.keys(b).length) return false;
|
|
476
|
+
for (const key of keys) {
|
|
477
|
+
if (!sameValue(a[key], b[key])) return false;
|
|
478
|
+
}
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
function sameNode(a, b) {
|
|
484
|
+
if (a === b) return true;
|
|
485
|
+
if (a.t !== b.t || a.id !== b.id) return false;
|
|
486
|
+
if (!sameValue(a.p, b.p) || !sameValue(a.m, b.m) || !sameValue(a.h, b.h)) return false;
|
|
487
|
+
const left = a.c ?? [];
|
|
488
|
+
const right = b.c ?? [];
|
|
489
|
+
if (left.length !== right.length) return false;
|
|
490
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
491
|
+
if (!sameNode(left[index], right[index])) return false;
|
|
492
|
+
}
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
349
495
|
function handlerId(node, name) {
|
|
350
496
|
return node.h?.[name];
|
|
351
497
|
}
|
|
498
|
+
function pressProps(node, deliver) {
|
|
499
|
+
const presses = [];
|
|
500
|
+
for (const name of ["onPress", "onTap"]) {
|
|
501
|
+
const id = handlerId(node, name);
|
|
502
|
+
if (id !== void 0) presses.push(id);
|
|
503
|
+
}
|
|
504
|
+
if (presses.length === 0) return {};
|
|
505
|
+
return {
|
|
506
|
+
onPress: () => {
|
|
507
|
+
for (const id of presses) deliver(id, null);
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
function SwiftTabScene({ children }) {
|
|
512
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
|
|
513
|
+
}
|
|
514
|
+
function SwiftTabView({
|
|
515
|
+
tabs,
|
|
516
|
+
selection,
|
|
517
|
+
onSelect,
|
|
518
|
+
modifiers,
|
|
519
|
+
children
|
|
520
|
+
}) {
|
|
521
|
+
const scenes = import_react.Children.toArray(children);
|
|
522
|
+
const routes = tabs.map((tab, index2) => ({
|
|
523
|
+
key: tab.testID,
|
|
524
|
+
name: tab.title ?? `tab-${index2}`,
|
|
525
|
+
title: tab.title,
|
|
526
|
+
sfSymbol: tab.systemImage,
|
|
527
|
+
testID: tab.testID
|
|
528
|
+
}));
|
|
529
|
+
const index = selection >= 0 && selection < routes.length ? selection : 0;
|
|
530
|
+
(0, import_react.useEffect)(() => {
|
|
531
|
+
if (selection !== index) onSelect?.(index);
|
|
532
|
+
}, [selection, index, onSelect]);
|
|
533
|
+
const bar = (0, import_react.createElement)(import_react_native_bottom_tabs.default, {
|
|
534
|
+
navigationState: { index, routes },
|
|
535
|
+
renderScene: ({ route }) => scenes[routes.findIndex((candidate) => candidate.key === route.key)],
|
|
536
|
+
onIndexChange: (next) => onSelect?.(next),
|
|
537
|
+
getLabelText: ({ route }) => route.title ?? route.key,
|
|
538
|
+
getIcon: ({ route }) => route.sfSymbol ? { sfSymbol: route.sfSymbol } : void 0,
|
|
539
|
+
getTestID: ({ route }) => route.testID
|
|
540
|
+
});
|
|
541
|
+
return (0, import_react.createElement)(
|
|
542
|
+
import_ui.VStack,
|
|
543
|
+
{
|
|
544
|
+
...modifiers?.length ? { modifiers } : {},
|
|
545
|
+
style: {
|
|
546
|
+
alignSelf: "stretch",
|
|
547
|
+
alignItems: "stretch",
|
|
548
|
+
flexGrow: 1,
|
|
549
|
+
flexShrink: 1,
|
|
550
|
+
flexBasis: "auto"
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
bar
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
function SwiftAlert({
|
|
557
|
+
title,
|
|
558
|
+
message,
|
|
559
|
+
buttons,
|
|
560
|
+
onButtonPress,
|
|
561
|
+
onDismiss
|
|
562
|
+
}) {
|
|
563
|
+
const latest = (0, import_react.useRef)({ title, message, buttons, onButtonPress, onDismiss });
|
|
564
|
+
(0, import_react.useEffect)(() => {
|
|
565
|
+
latest.current = { title, message, buttons, onButtonPress, onDismiss };
|
|
566
|
+
});
|
|
567
|
+
(0, import_react.useEffect)(() => {
|
|
568
|
+
const handle = (0, import_runtime.getNativeAlerts)().show(
|
|
569
|
+
latest.current.title,
|
|
570
|
+
latest.current.message,
|
|
571
|
+
latest.current.buttons.map((button, index) => ({
|
|
572
|
+
text: button.text,
|
|
573
|
+
style: button.role === "destructive" ? "destructive" : button.role === "cancel" ? "cancel" : "default",
|
|
574
|
+
// the tapped action runs its swift closure and clears isPresented,
|
|
575
|
+
// which is the order the system alert uses on the way out: the action
|
|
576
|
+
// body is the last thing that runs with the alert still up. the
|
|
577
|
+
// handlers come off the ref at tap time, not from this render.
|
|
578
|
+
onPress: () => {
|
|
579
|
+
latest.current.onButtonPress?.(index);
|
|
580
|
+
latest.current.onDismiss?.();
|
|
581
|
+
}
|
|
582
|
+
}))
|
|
583
|
+
);
|
|
584
|
+
return () => {
|
|
585
|
+
(0, import_runtime.getNativeAlerts)().dismiss(handle);
|
|
586
|
+
};
|
|
587
|
+
}, []);
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
590
|
+
function readAlertButtons(value) {
|
|
591
|
+
if (!Array.isArray(value)) return [];
|
|
592
|
+
return value.map((entry) => {
|
|
593
|
+
if (!isRecord(entry)) return {};
|
|
594
|
+
return {
|
|
595
|
+
...typeof entry.text === "string" ? { text: entry.text } : {},
|
|
596
|
+
...typeof entry.role === "string" ? { role: entry.role } : {}
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
}
|
|
352
600
|
function nodeProps(node, deliver) {
|
|
353
601
|
const props = node.p ?? {};
|
|
354
602
|
switch (node.t) {
|
|
@@ -356,7 +604,8 @@ function nodeProps(node, deliver) {
|
|
|
356
604
|
const style = fontStyle(fontModifier(node.m));
|
|
357
605
|
return {
|
|
358
606
|
children: typeof props.children === "string" ? props.children : "",
|
|
359
|
-
...style ? { style } : {}
|
|
607
|
+
...style ? { style } : {},
|
|
608
|
+
...pressProps(node, deliver)
|
|
360
609
|
};
|
|
361
610
|
}
|
|
362
611
|
case "Image": {
|
|
@@ -364,14 +613,18 @@ function nodeProps(node, deliver) {
|
|
|
364
613
|
const size = typeof font?.size === "number" ? font.size : void 0;
|
|
365
614
|
return {
|
|
366
615
|
...typeof props.systemName === "string" ? { systemName: props.systemName } : {},
|
|
367
|
-
...size === void 0 ? {} : { size }
|
|
616
|
+
...size === void 0 ? {} : { size },
|
|
617
|
+
...pressProps(node, deliver)
|
|
368
618
|
};
|
|
369
619
|
}
|
|
370
620
|
case "Toggle": {
|
|
371
621
|
const onValueChange = handlerId(node, "onValueChange");
|
|
372
622
|
return {
|
|
373
623
|
isOn: props.value === true,
|
|
374
|
-
...onValueChange === void 0 ? {} : { onIsOnChange: (value) => deliver(onValueChange, value) }
|
|
624
|
+
...onValueChange === void 0 ? {} : { onIsOnChange: (value) => deliver(onValueChange, value) },
|
|
625
|
+
// the gesture replaces the row's own press (a label tap runs it and
|
|
626
|
+
// does not toggle); the switch keeps toggling through onValueChange.
|
|
627
|
+
...pressProps(node, deliver)
|
|
375
628
|
};
|
|
376
629
|
}
|
|
377
630
|
case "TextField": {
|
|
@@ -388,17 +641,264 @@ function nodeProps(node, deliver) {
|
|
|
388
641
|
value: typeof props.value === "number" ? props.value : 0,
|
|
389
642
|
min: typeof props.min === "number" ? props.min : 0,
|
|
390
643
|
max: typeof props.max === "number" ? props.max : 1,
|
|
391
|
-
...onValueChange === void 0 ? {} : { onValueChange: (value) => deliver(onValueChange, value) }
|
|
644
|
+
...onValueChange === void 0 ? {} : { onValueChange: (value) => deliver(onValueChange, value) },
|
|
645
|
+
// a tap runs the gesture and leaves the value alone: only a drag
|
|
646
|
+
// moves it, so the gesture rides onPress beside the drag handler.
|
|
647
|
+
...pressProps(node, deliver)
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
case "Button":
|
|
651
|
+
return pressProps(node, deliver);
|
|
652
|
+
case "TabView": {
|
|
653
|
+
const onSelect = handlerId(node, "onSelect");
|
|
654
|
+
const tabs = (node.c ?? []).map((tab, index) => {
|
|
655
|
+
const tabProps = tab.p ?? {};
|
|
656
|
+
return {
|
|
657
|
+
...typeof tabProps.title === "string" ? { title: tabProps.title } : {},
|
|
658
|
+
...typeof tabProps.systemImage === "string" ? { systemImage: tabProps.systemImage } : {},
|
|
659
|
+
...typeof tabProps.role === "string" ? { role: tabProps.role } : {},
|
|
660
|
+
testID: `swift-tab-${index}`
|
|
661
|
+
};
|
|
662
|
+
});
|
|
663
|
+
return {
|
|
664
|
+
tabs,
|
|
665
|
+
selection: typeof props.selection === "number" ? props.selection : 0,
|
|
666
|
+
...onSelect === void 0 ? {} : { onSelect: (index) => deliver(onSelect, index) }
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
case "BottomSheet": {
|
|
670
|
+
const onDismiss = handlerId(node, "onDismiss");
|
|
671
|
+
const detents = (node.c ?? []).flatMap((child) => nodeModifiers(child) ?? []).filter((modifier) => modifier.$type === "presentationDetents");
|
|
672
|
+
return {
|
|
673
|
+
isOpened: props.isOpened === true,
|
|
674
|
+
...detents.length === 0 ? {} : { modifiers: detents },
|
|
675
|
+
...onDismiss === void 0 ? {} : { onDismiss: () => deliver(onDismiss, null) }
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
case "ConfirmationDialog": {
|
|
679
|
+
return { isPresented: props.isPresented === true };
|
|
680
|
+
}
|
|
681
|
+
case "Alert": {
|
|
682
|
+
const onButtonPress = handlerId(node, "onButtonPress");
|
|
683
|
+
const onDismiss = handlerId(node, "onDismiss");
|
|
684
|
+
return {
|
|
685
|
+
title: typeof props.title === "string" ? props.title : "",
|
|
686
|
+
...typeof props.message === "string" ? { message: props.message } : {},
|
|
687
|
+
buttons: readAlertButtons(props.buttons),
|
|
688
|
+
...onButtonPress === void 0 ? {} : { onButtonPress: (index) => deliver(onButtonPress, index) },
|
|
689
|
+
...onDismiss === void 0 ? {} : { onDismiss: () => deliver(onDismiss, null) }
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
case "SecureField": {
|
|
693
|
+
const onChangeText = handlerId(node, "onChangeText");
|
|
694
|
+
return {
|
|
695
|
+
...typeof props.placeholder === "string" ? { placeholder: props.placeholder } : {},
|
|
696
|
+
...typeof props.prompt === "string" ? { prompt: props.prompt } : {},
|
|
697
|
+
...typeof props.defaultValue === "string" ? { defaultValue: props.defaultValue } : {},
|
|
698
|
+
...onChangeText === void 0 ? {} : { onChangeText: (value) => deliver(onChangeText, value) }
|
|
392
699
|
};
|
|
393
700
|
}
|
|
394
|
-
case "
|
|
395
|
-
const
|
|
396
|
-
return
|
|
701
|
+
case "Picker": {
|
|
702
|
+
const onSelectionChange = handlerId(node, "onSelectionChange");
|
|
703
|
+
return {
|
|
704
|
+
...typeof props.title === "string" ? { label: props.title } : {},
|
|
705
|
+
...props.selection === void 0 ? {} : { selection: props.selection },
|
|
706
|
+
...onSelectionChange === void 0 ? {} : {
|
|
707
|
+
onSelectionChange: (value) => deliver(onSelectionChange, value)
|
|
708
|
+
}
|
|
709
|
+
};
|
|
397
710
|
}
|
|
711
|
+
case "DatePicker": {
|
|
712
|
+
return {
|
|
713
|
+
...typeof props.title === "string" ? { label: props.title } : {},
|
|
714
|
+
// the wire carries epoch seconds; the kit takes a Date and formats it
|
|
715
|
+
...typeof props.value === "number" ? { value: new Date(props.value * 1e3) } : {},
|
|
716
|
+
...Array.isArray(props.components) ? { components: props.components } : {}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
case "GlassEffectContainer":
|
|
720
|
+
return {};
|
|
721
|
+
case "ProgressView":
|
|
722
|
+
return {
|
|
723
|
+
...typeof props.title === "string" ? { label: props.title } : {},
|
|
724
|
+
...typeof props.value === "number" || props.value === null ? { value: props.value } : {},
|
|
725
|
+
...typeof props.total === "number" ? { total: props.total } : {}
|
|
726
|
+
};
|
|
398
727
|
default:
|
|
399
|
-
return props;
|
|
728
|
+
return { ...props, ...pressProps(node, deliver) };
|
|
400
729
|
}
|
|
401
730
|
}
|
|
731
|
+
function numberProp(node, name) {
|
|
732
|
+
const value = node.p?.[name];
|
|
733
|
+
return typeof value === "number" ? value : 0;
|
|
734
|
+
}
|
|
735
|
+
function menuItemLabel(node) {
|
|
736
|
+
const [only] = node.c ?? [];
|
|
737
|
+
if (node.t !== "Button" || node.c?.length !== 1 || !only) return void 0;
|
|
738
|
+
if (only.t === "Text" && typeof only.p?.children === "string") {
|
|
739
|
+
return { label: only.p.children };
|
|
740
|
+
}
|
|
741
|
+
if (only.t === "Label" && typeof only.p?.title === "string" && (only.p?.systemImage === void 0 || typeof only.p?.systemImage === "string")) {
|
|
742
|
+
return {
|
|
743
|
+
label: only.p.title,
|
|
744
|
+
...typeof only.p?.systemImage === "string" ? { systemImage: only.p.systemImage } : {}
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
return void 0;
|
|
748
|
+
}
|
|
749
|
+
function renderMenuItem(node, deliver, cache) {
|
|
750
|
+
const item = menuItemLabel(node);
|
|
751
|
+
if (item !== void 0) {
|
|
752
|
+
const modifiers = nodeModifiers(node);
|
|
753
|
+
return (0, import_react.createElement)(import_ui.Button, {
|
|
754
|
+
key: node.id,
|
|
755
|
+
...item,
|
|
756
|
+
...modifiers === void 0 ? {} : { modifiers },
|
|
757
|
+
...pressProps(node, deliver)
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
return renderNode(node, deliver, cache);
|
|
761
|
+
}
|
|
762
|
+
function renderMenu(node, deliver, cache) {
|
|
763
|
+
const labelCount = numberProp(node, "labelCount");
|
|
764
|
+
const kids = node.c ?? [];
|
|
765
|
+
const labels = kids.slice(0, labelCount);
|
|
766
|
+
const items = kids.slice(labelCount);
|
|
767
|
+
const [only] = labels;
|
|
768
|
+
const onlyText = labels.length === 1 && only.t === "Text" && typeof only.p?.children === "string" ? only.p.children : void 0;
|
|
769
|
+
const onlyLabel = labels.length === 1 && only.t === "Label" && typeof only.p?.title === "string" && (only.p?.systemImage === void 0 || typeof only.p?.systemImage === "string") ? only : void 0;
|
|
770
|
+
const label = onlyText !== void 0 || onlyLabel !== void 0 ? void 0 : (0, import_react.createElement)(
|
|
771
|
+
import_react.Fragment,
|
|
772
|
+
null,
|
|
773
|
+
...labels.map((child) => renderNode(child, deliver, cache))
|
|
774
|
+
);
|
|
775
|
+
const labelModifiers = labels.length === 1 ? nodeModifiers(only) : void 0;
|
|
776
|
+
const modifiers = nodeModifiers(node);
|
|
777
|
+
const combined = [...labelModifiers ?? [], ...modifiers ?? []];
|
|
778
|
+
return (0, import_react.createElement)(
|
|
779
|
+
import_ui.Menu,
|
|
780
|
+
{
|
|
781
|
+
key: node.id,
|
|
782
|
+
...combined.length > 0 ? { modifiers: combined } : {},
|
|
783
|
+
...onlyText !== void 0 ? { label: onlyText } : {},
|
|
784
|
+
...onlyLabel !== void 0 ? {
|
|
785
|
+
label: onlyLabel.p?.title,
|
|
786
|
+
...typeof onlyLabel.p?.systemImage === "string" ? { systemImage: onlyLabel.p.systemImage } : {}
|
|
787
|
+
} : {},
|
|
788
|
+
...label === void 0 ? {} : { label }
|
|
789
|
+
},
|
|
790
|
+
...items.map((child) => renderMenuItem(child, deliver))
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
function renderContextMenu(node, deliver, cache) {
|
|
794
|
+
const kids = node.c ?? [];
|
|
795
|
+
const contentCount = numberProp(node, "contentCount");
|
|
796
|
+
const itemCount = numberProp(node, "itemCount");
|
|
797
|
+
const content = kids.slice(0, contentCount);
|
|
798
|
+
const items = kids.slice(contentCount, contentCount + itemCount);
|
|
799
|
+
const preview = kids.slice(contentCount + itemCount);
|
|
800
|
+
const modifiers = nodeModifiers(node);
|
|
801
|
+
return (0, import_react.createElement)(
|
|
802
|
+
import_ui.ContextMenu,
|
|
803
|
+
{
|
|
804
|
+
key: node.id,
|
|
805
|
+
...modifiers === void 0 ? {} : { modifiers }
|
|
806
|
+
},
|
|
807
|
+
(0, import_react.createElement)(
|
|
808
|
+
import_ui.Trigger,
|
|
809
|
+
{ key: `${node.id}/trigger` },
|
|
810
|
+
...content.map((child) => renderNode(child, deliver, cache))
|
|
811
|
+
),
|
|
812
|
+
(0, import_react.createElement)(
|
|
813
|
+
import_ui.Items,
|
|
814
|
+
{ key: `${node.id}/items` },
|
|
815
|
+
...items.map((child) => renderMenuItem(child, deliver))
|
|
816
|
+
),
|
|
817
|
+
...preview.length > 0 ? [
|
|
818
|
+
(0, import_react.createElement)(
|
|
819
|
+
import_ui.Preview,
|
|
820
|
+
{ key: `${node.id}/preview` },
|
|
821
|
+
...preview.map((child) => renderNode(child, deliver, cache))
|
|
822
|
+
)
|
|
823
|
+
] : []
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
function renderSwipeActions(node, deliver, cache) {
|
|
827
|
+
const kids = node.c ?? [];
|
|
828
|
+
const content = kids.slice(0, numberProp(node, "contentCount"));
|
|
829
|
+
const actions = kids.slice(numberProp(node, "contentCount"));
|
|
830
|
+
const modifiers = nodeModifiers(node);
|
|
831
|
+
const { Actions } = import_ui.SwipeActions;
|
|
832
|
+
return (0, import_react.createElement)(
|
|
833
|
+
import_ui.SwipeActions,
|
|
834
|
+
{
|
|
835
|
+
key: node.id,
|
|
836
|
+
...modifiers === void 0 ? {} : { modifiers }
|
|
837
|
+
},
|
|
838
|
+
...content.map((child) => renderNode(child, deliver, cache)),
|
|
839
|
+
...actions.length > 0 ? [
|
|
840
|
+
(0, import_react.createElement)(
|
|
841
|
+
Actions,
|
|
842
|
+
{
|
|
843
|
+
key: `${node.id}/actions`,
|
|
844
|
+
edge: node.p?.edge === "leading" ? "leading" : "trailing",
|
|
845
|
+
...typeof node.p?.allowsFullSwipe === "boolean" ? { allowsFullSwipe: node.p.allowsFullSwipe } : {}
|
|
846
|
+
},
|
|
847
|
+
...actions.map((child) => renderNode(child, deliver, cache))
|
|
848
|
+
)
|
|
849
|
+
] : []
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
function ClosureStepper({
|
|
853
|
+
deliver,
|
|
854
|
+
onIncrement,
|
|
855
|
+
onDecrement,
|
|
856
|
+
...rest
|
|
857
|
+
}) {
|
|
858
|
+
const last = (0, import_react.useRef)(0);
|
|
859
|
+
return (0, import_react.createElement)(import_ui.Stepper, {
|
|
860
|
+
...rest,
|
|
861
|
+
onValueChange: (next) => {
|
|
862
|
+
if (next > last.current && onIncrement !== void 0) {
|
|
863
|
+
deliver(onIncrement, null);
|
|
864
|
+
} else if (next < last.current && onDecrement !== void 0) {
|
|
865
|
+
deliver(onDecrement, null);
|
|
866
|
+
}
|
|
867
|
+
last.current = next;
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
function renderStepper(node, deliver, cache) {
|
|
872
|
+
const kids = node.c ?? [];
|
|
873
|
+
const label = kids.length === 0 ? void 0 : (0, import_react.createElement)(
|
|
874
|
+
import_react.Fragment,
|
|
875
|
+
null,
|
|
876
|
+
...kids.map((child) => renderNode(child, deliver, cache))
|
|
877
|
+
);
|
|
878
|
+
const modifiers = nodeModifiers(node);
|
|
879
|
+
const shared = {
|
|
880
|
+
key: node.id,
|
|
881
|
+
...modifiers === void 0 ? {} : { modifiers },
|
|
882
|
+
...label === void 0 ? {} : { label },
|
|
883
|
+
...typeof node.p?.min === "number" ? { min: node.p.min } : {},
|
|
884
|
+
...typeof node.p?.max === "number" ? { max: node.p.max } : {},
|
|
885
|
+
...typeof node.p?.step === "number" ? { step: node.p.step } : {}
|
|
886
|
+
};
|
|
887
|
+
const onValueChange = handlerId(node, "onValueChange");
|
|
888
|
+
if (onValueChange !== void 0) {
|
|
889
|
+
return (0, import_react.createElement)(import_ui.Stepper, {
|
|
890
|
+
...shared,
|
|
891
|
+
...typeof node.p?.value === "number" ? { value: node.p.value } : {},
|
|
892
|
+
onValueChange: (value) => deliver(onValueChange, value)
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
return (0, import_react.createElement)(ClosureStepper, {
|
|
896
|
+
...shared,
|
|
897
|
+
deliver,
|
|
898
|
+
...handlerId(node, "onIncrement") === void 0 ? {} : { onIncrement: handlerId(node, "onIncrement") },
|
|
899
|
+
...handlerId(node, "onDecrement") === void 0 ? {} : { onDecrement: handlerId(node, "onDecrement") }
|
|
900
|
+
});
|
|
901
|
+
}
|
|
402
902
|
function buttonModifier(modifier) {
|
|
403
903
|
if (modifier.$type === "glassEffect") {
|
|
404
904
|
const glass = modifier.glass;
|
|
@@ -415,11 +915,195 @@ function nodeModifiers(node) {
|
|
|
415
915
|
if (node.t !== "Button") return resolved;
|
|
416
916
|
return resolved?.map(buttonModifier);
|
|
417
917
|
}
|
|
418
|
-
function
|
|
918
|
+
function dialogChildren(node, deliver) {
|
|
919
|
+
const children = node.c?.map((child) => renderNode(child, deliver));
|
|
920
|
+
const props = node.p ?? {};
|
|
921
|
+
if (props.showsTitle !== true || typeof props.title !== "string") return children;
|
|
922
|
+
const title = (0, import_react.createElement)(import_ui.Text, { key: `${node.id}/title`, children: props.title });
|
|
923
|
+
return [title, ...children ?? []];
|
|
924
|
+
}
|
|
925
|
+
var Stack = (0, import_native_stack.createNativeStackNavigator)();
|
|
926
|
+
var NAVIGATOR_FILL = { flex: 1, alignSelf: "stretch" };
|
|
927
|
+
function readNodes(value) {
|
|
928
|
+
if (!Array.isArray(value)) return [];
|
|
929
|
+
return value.map(readNode);
|
|
930
|
+
}
|
|
931
|
+
function hasPrefix(names, of) {
|
|
932
|
+
return names.every((name, index) => of[index] === name);
|
|
933
|
+
}
|
|
934
|
+
function sameNames(a, b) {
|
|
935
|
+
return a.length === b.length && a.every((name, index) => b[index] === name);
|
|
936
|
+
}
|
|
937
|
+
function commonPrefixLength(a, b) {
|
|
938
|
+
let length = 0;
|
|
939
|
+
while (length < a.length && length < b.length && a[length] === b[length]) length++;
|
|
940
|
+
return length;
|
|
941
|
+
}
|
|
942
|
+
function reconcilePlan(names, desired) {
|
|
943
|
+
const common = commonPrefixLength(names, desired);
|
|
944
|
+
if (common === names.length && common === desired.length) return { kind: "in-step" };
|
|
945
|
+
if (common === names.length) return { kind: "push" };
|
|
946
|
+
if (common === desired.length) return { kind: "pop" };
|
|
947
|
+
const top = desired[desired.length - 1];
|
|
948
|
+
return { kind: "replace", replaceAnimation: names.includes(top) ? "pop" : "push" };
|
|
949
|
+
}
|
|
950
|
+
function resolveLargeTitles(modes) {
|
|
951
|
+
let previous = true;
|
|
952
|
+
return modes.map((mode) => {
|
|
953
|
+
const large = mode === "inline" ? false : mode === "large" ? true : previous;
|
|
954
|
+
previous = large;
|
|
955
|
+
return large;
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
function screenOptions(node, deliver, largeTitle, replaceAnimation) {
|
|
959
|
+
const props = node.p ?? {};
|
|
960
|
+
const options = {
|
|
961
|
+
title: typeof props.title === "string" ? props.title : "",
|
|
962
|
+
headerLargeTitleEnabled: largeTitle
|
|
963
|
+
};
|
|
964
|
+
if (replaceAnimation !== void 0) options.animationTypeForReplace = replaceAnimation;
|
|
965
|
+
const leading = readNodes(props.leading);
|
|
966
|
+
const trailing = readNodes(props.trailing);
|
|
967
|
+
const principal = readNodes(props.principal);
|
|
968
|
+
const render = (nodes) => () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: nodes.map((child) => renderNode(child, deliver)) });
|
|
969
|
+
if (leading.length > 0) {
|
|
970
|
+
options.headerLeft = render(leading);
|
|
971
|
+
options.headerBackVisible = true;
|
|
972
|
+
}
|
|
973
|
+
if (trailing.length > 0) options.headerRight = render(trailing);
|
|
974
|
+
if (principal.length > 0) options.headerTitle = render(principal);
|
|
975
|
+
return options;
|
|
976
|
+
}
|
|
977
|
+
function SwiftScreen({
|
|
978
|
+
node,
|
|
979
|
+
navigation,
|
|
980
|
+
deliver,
|
|
981
|
+
report
|
|
982
|
+
}) {
|
|
983
|
+
const routes = (0, import_native.useNavigationState)(
|
|
984
|
+
(state) => state.routes.map((route) => route.name).join("\0")
|
|
985
|
+
);
|
|
986
|
+
(0, import_react.useEffect)(() => {
|
|
987
|
+
report(navigation, routes === "" ? [] : routes.split("\0"));
|
|
988
|
+
});
|
|
989
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: node.c?.map((child) => renderNode(child, deliver)) });
|
|
990
|
+
}
|
|
991
|
+
function NavigationStackHost({ node, deliver }) {
|
|
992
|
+
const screens = (node.c ?? []).filter((child) => child.t === "NavigationScreen");
|
|
993
|
+
const desired = screens.map((screen) => screen.id);
|
|
994
|
+
const largeTitles = resolveLargeTitles(
|
|
995
|
+
screens.map((screen) => {
|
|
996
|
+
const mode = screen.p?.titleDisplayMode;
|
|
997
|
+
return typeof mode === "string" ? mode : void 0;
|
|
998
|
+
})
|
|
999
|
+
);
|
|
1000
|
+
const onPop = node.h?.onPop;
|
|
1001
|
+
const reportRef = (0, import_react.useRef)(null);
|
|
1002
|
+
const reportedRef = (0, import_react.useRef)([]);
|
|
1003
|
+
const expectedRef = (0, import_react.useRef)(null);
|
|
1004
|
+
const syncedRef = (0, import_react.useRef)(null);
|
|
1005
|
+
const [, rerender] = (0, import_react.useReducer)((count) => count + 1, 0);
|
|
1006
|
+
const report = (0, import_react.useCallback)((navigation, names) => {
|
|
1007
|
+
const previous = reportRef.current;
|
|
1008
|
+
reportRef.current = { navigation, names };
|
|
1009
|
+
if (previous && sameNames(previous.names, names)) return;
|
|
1010
|
+
rerender();
|
|
1011
|
+
}, []);
|
|
1012
|
+
const reported = reportRef.current?.names ?? [];
|
|
1013
|
+
const plan = reportRef.current ? reconcilePlan(reported, desired) : null;
|
|
1014
|
+
const replaceTop = plan?.kind === "replace" ? desired[desired.length - 1] : void 0;
|
|
1015
|
+
(0, import_react.useEffect)(() => {
|
|
1016
|
+
const current = reportRef.current;
|
|
1017
|
+
if (!current) return;
|
|
1018
|
+
const names = current.names;
|
|
1019
|
+
const previous = reportedRef.current;
|
|
1020
|
+
const isReport = !sameNames(previous, names);
|
|
1021
|
+
if (isReport) reportedRef.current = names;
|
|
1022
|
+
const expected = expectedRef.current;
|
|
1023
|
+
if (expected) {
|
|
1024
|
+
if (sameNames(expected, names)) expectedRef.current = null;
|
|
1025
|
+
else if (!isReport) return;
|
|
1026
|
+
else expectedRef.current = null;
|
|
1027
|
+
}
|
|
1028
|
+
const dropped = previous.slice(names.length);
|
|
1029
|
+
const settled = syncedRef.current;
|
|
1030
|
+
const navigatorPopped = isReport && dropped.length > 0 && settled !== null && sameNames(settled, desired) && hasPrefix(names, desired) && hasPrefix(desired.slice(names.length), dropped);
|
|
1031
|
+
if (navigatorPopped && onPop !== void 0) {
|
|
1032
|
+
deliver(onPop, { count: dropped.length });
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
const next = reconcilePlan(names, desired);
|
|
1036
|
+
if (next.kind === "in-step") {
|
|
1037
|
+
expectedRef.current = null;
|
|
1038
|
+
syncedRef.current = desired;
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
expectedRef.current = desired;
|
|
1042
|
+
if (next.kind === "push") {
|
|
1043
|
+
for (const name of desired.slice(names.length)) current.navigation.push(name);
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
if (next.kind === "pop") {
|
|
1047
|
+
current.navigation.pop(names.length - desired.length);
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
current.navigation.reset({
|
|
1051
|
+
index: Math.max(0, desired.length - 1),
|
|
1052
|
+
routes: desired.map((name) => ({ name }))
|
|
1053
|
+
});
|
|
1054
|
+
});
|
|
1055
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stack.Navigator, { initialRouteName: desired[0], children: screens.map((screen, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1056
|
+
Stack.Screen,
|
|
1057
|
+
{
|
|
1058
|
+
name: screen.id,
|
|
1059
|
+
options: screenOptions(
|
|
1060
|
+
screen,
|
|
1061
|
+
deliver,
|
|
1062
|
+
largeTitles[index],
|
|
1063
|
+
screen.id === replaceTop ? plan?.kind === "replace" ? plan.replaceAnimation : void 0 : void 0
|
|
1064
|
+
),
|
|
1065
|
+
children: (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1066
|
+
SwiftScreen,
|
|
1067
|
+
{
|
|
1068
|
+
node: screen,
|
|
1069
|
+
navigation: props.navigation,
|
|
1070
|
+
deliver,
|
|
1071
|
+
report
|
|
1072
|
+
}
|
|
1073
|
+
)
|
|
1074
|
+
},
|
|
1075
|
+
screen.id
|
|
1076
|
+
)) });
|
|
1077
|
+
}
|
|
1078
|
+
function renderNode(node, deliver, cache) {
|
|
1079
|
+
const cached = cache?.entries.get(node.id);
|
|
1080
|
+
if (cached && sameNode(cached.node, node)) return cached.element;
|
|
1081
|
+
const element = buildNode(node, deliver, cache);
|
|
1082
|
+
cache?.entries.set(node.id, { node, element });
|
|
1083
|
+
return element;
|
|
1084
|
+
}
|
|
1085
|
+
function buildNode(node, deliver, cache) {
|
|
1086
|
+
if (node.t === "Menu") return renderMenu(node, deliver, cache);
|
|
1087
|
+
if (node.t === "ContextMenu") return renderContextMenu(node, deliver, cache);
|
|
1088
|
+
if (node.t === "SwipeActions") return renderSwipeActions(node, deliver, cache);
|
|
1089
|
+
if (node.t === "Stepper") return renderStepper(node, deliver, cache);
|
|
1090
|
+
if (node.t === "NavigationStack") {
|
|
1091
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: NAVIGATOR_FILL, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node, deliver }) }, node.id);
|
|
1092
|
+
}
|
|
1093
|
+
if (node.t === "NavigationLink") {
|
|
1094
|
+
return (0, import_react.createElement)(
|
|
1095
|
+
import_ui.Button,
|
|
1096
|
+
{
|
|
1097
|
+
key: node.id,
|
|
1098
|
+
...pressProps(node, deliver)
|
|
1099
|
+
},
|
|
1100
|
+
...(node.c ?? []).map((child) => renderNode(child, deliver, cache))
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
419
1103
|
const component = NODE_COMPONENTS[node.t];
|
|
420
1104
|
if (!component) throw new Error(`swift view ${node.t} has no rnx kit component`);
|
|
421
1105
|
const modifiers = nodeModifiers(node);
|
|
422
|
-
const children = node.c?.map((child) => renderNode(child, deliver));
|
|
1106
|
+
const children = node.t === "ConfirmationDialog" ? dialogChildren(node, deliver) : node.c?.map((child) => renderNode(child, deliver));
|
|
423
1107
|
return (0, import_react.createElement)(
|
|
424
1108
|
component,
|
|
425
1109
|
{
|
|
@@ -430,6 +1114,25 @@ function renderNode(node, deliver) {
|
|
|
430
1114
|
...children ?? []
|
|
431
1115
|
);
|
|
432
1116
|
}
|
|
1117
|
+
function SwiftTree({
|
|
1118
|
+
tree,
|
|
1119
|
+
deliver,
|
|
1120
|
+
cache
|
|
1121
|
+
}) {
|
|
1122
|
+
return (
|
|
1123
|
+
// a navigation stack at the root lays its own bar out under the status
|
|
1124
|
+
// bar and insets each screen itself, so the host must not also pad it
|
|
1125
|
+
// down: that pad would move the whole stack a status bar lower
|
|
1126
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1127
|
+
import_ui.Host,
|
|
1128
|
+
{
|
|
1129
|
+
style: { flex: 1 },
|
|
1130
|
+
ignoreSafeArea: tree.some((node) => node.t === "NavigationStack"),
|
|
1131
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationIndependentTree, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationContainer, { children: tree.map((node) => renderNode(node, deliver, cache)) }) })
|
|
1132
|
+
}
|
|
1133
|
+
)
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
433
1136
|
var ROOT_KEY = "__rnx_swift_roots__";
|
|
434
1137
|
function rootRegistry() {
|
|
435
1138
|
const existing = Reflect.get(globalThis, ROOT_KEY);
|
|
@@ -438,12 +1141,22 @@ function rootRegistry() {
|
|
|
438
1141
|
Reflect.set(globalThis, ROOT_KEY, created);
|
|
439
1142
|
return created;
|
|
440
1143
|
}
|
|
441
|
-
function
|
|
1144
|
+
function slotFor(rootId, mountTree, props) {
|
|
1145
|
+
const registry = rootRegistry();
|
|
1146
|
+
const existing = registry.get(rootId);
|
|
1147
|
+
if (existing) return existing;
|
|
1148
|
+
const created = { root: createRoot(mountTree, props), props };
|
|
1149
|
+
registry.set(rootId, created);
|
|
1150
|
+
return created;
|
|
1151
|
+
}
|
|
1152
|
+
function createRoot(mountTree, props) {
|
|
442
1153
|
let instance = null;
|
|
443
1154
|
let source = null;
|
|
1155
|
+
let refresh;
|
|
444
1156
|
let state = { tree: null, error: null };
|
|
445
1157
|
let swap = Promise.resolve();
|
|
446
1158
|
const listeners = /* @__PURE__ */ new Set();
|
|
1159
|
+
const cache = { entries: /* @__PURE__ */ new Map() };
|
|
447
1160
|
const publish = (next) => {
|
|
448
1161
|
state = next;
|
|
449
1162
|
for (const listener of listeners) listener();
|
|
@@ -454,7 +1167,7 @@ function createRoot() {
|
|
|
454
1167
|
if (carried !== null) created.importState(carried);
|
|
455
1168
|
if (source !== options) return;
|
|
456
1169
|
instance = created;
|
|
457
|
-
publish({ tree: created.
|
|
1170
|
+
publish({ tree: mountTree(created, props.current), error: null });
|
|
458
1171
|
};
|
|
459
1172
|
const component = function SwiftRoot() {
|
|
460
1173
|
const rendered = (0, import_react.useSyncExternalStore)(
|
|
@@ -470,14 +1183,15 @@ function createRoot() {
|
|
|
470
1183
|
if (!instance) throw new Error("swift app received an event before it mounted");
|
|
471
1184
|
publish({ tree: instance.deliver(handlerId2, payload), error: null });
|
|
472
1185
|
};
|
|
473
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwiftTree, { tree: rendered.tree, deliver, cache });
|
|
474
1187
|
};
|
|
475
1188
|
return {
|
|
476
1189
|
component,
|
|
477
|
-
use(options) {
|
|
478
|
-
const changed = source === null || source.hash !== options.hash || source.url !== options.url;
|
|
1190
|
+
use(options, refreshKey) {
|
|
1191
|
+
const changed = source === null || source.hash !== options.hash || source.url !== options.url || refreshKey !== void 0 && refreshKey !== refresh;
|
|
479
1192
|
if (changed) {
|
|
480
1193
|
source = options;
|
|
1194
|
+
refresh = refreshKey;
|
|
481
1195
|
swap = swap.then(
|
|
482
1196
|
() => apply(options),
|
|
483
1197
|
() => apply(options)
|
|
@@ -495,13 +1209,41 @@ function createRoot() {
|
|
|
495
1209
|
}
|
|
496
1210
|
function createSwiftModule(options) {
|
|
497
1211
|
const rootId = options.rootId ?? "root";
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
1212
|
+
const slot = slotFor(rootId, (instance) => instance.mount(), { current: {} });
|
|
1213
|
+
return slot.root.use(options);
|
|
1214
|
+
}
|
|
1215
|
+
function propsSignature(props) {
|
|
1216
|
+
try {
|
|
1217
|
+
return JSON.stringify(props, (_key, value) => {
|
|
1218
|
+
if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
|
|
1219
|
+
throw new Error(`swift view props must be json; found ${typeof value}`);
|
|
1220
|
+
}
|
|
1221
|
+
return value;
|
|
1222
|
+
}) ?? "null";
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
if (error instanceof Error && error.message.startsWith("swift view props"))
|
|
1225
|
+
throw error;
|
|
1226
|
+
throw new Error(
|
|
1227
|
+
`swift view props must be json: ${error instanceof Error ? error.message : String(error)}`
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
function createSwiftView(options) {
|
|
1232
|
+
const rootId = options.rootId ?? "view";
|
|
1233
|
+
const slot = slotFor(rootId, (instance, props) => instance.mountView(props), {
|
|
1234
|
+
current: {}
|
|
1235
|
+
});
|
|
1236
|
+
return function SwiftView(props) {
|
|
1237
|
+
if (props.children !== void 0) {
|
|
1238
|
+
throw new Error("swift views take data props, not children");
|
|
1239
|
+
}
|
|
1240
|
+
slot.props.current = props;
|
|
1241
|
+
const component = slot.root.use(options, propsSignature(props));
|
|
1242
|
+
return (0, import_react.createElement)(component);
|
|
1243
|
+
};
|
|
503
1244
|
}
|
|
504
1245
|
// Annotate the CommonJS export names for ESM import in node:
|
|
505
1246
|
0 && (module.exports = {
|
|
506
|
-
createSwiftModule
|
|
1247
|
+
createSwiftModule,
|
|
1248
|
+
createSwiftView
|
|
507
1249
|
});
|