peachsim 0.1.527 → 0.1.570

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 (158) hide show
  1. package/README.md +26 -26
  2. package/cli/app-fonts.ts +1 -1
  3. package/cli/app-splash.ts +1 -1
  4. package/cli/bin.ts +1 -1
  5. package/cli/bridge-diagnostics.ts +1 -1
  6. package/cli/bridge-flow-runner.ts +57 -5
  7. package/cli/cloud-client.ts +273 -6
  8. package/cli/cloud-dispatch.ts +22 -2
  9. package/cli/cloud-session.ts +60 -4
  10. package/cli/cloud-test-tunnel.ts +354 -0
  11. package/cli/commands/box/bundle-plane.ts +2 -2
  12. package/cli/commands/box/checkout-plane.ts +1 -1
  13. package/cli/commands/box/rnx-command.ts +2 -2
  14. package/cli/commands/box/search-command.ts +2 -2
  15. package/cli/commands/box.ts +8 -8
  16. package/cli/commands/compat.ts +1 -1
  17. package/cli/commands/control.ts +22 -3
  18. package/cli/commands/detox.ts +1 -1
  19. package/cli/commands/device.ts +1 -1
  20. package/cli/commands/diagnose.ts +1 -1
  21. package/cli/commands/film.ts +1 -1
  22. package/cli/commands/flow.ts +60 -3
  23. package/cli/commands/inspect/actions.ts +1 -1
  24. package/cli/commands/inspect/core.ts +6 -7
  25. package/cli/commands/inspect/find.ts +2 -1
  26. package/cli/commands/inspect/resolve-target.ts +5 -3
  27. package/cli/commands/inspect/shared.ts +1 -1
  28. package/cli/commands/inspect/wait-event.ts +1 -1
  29. package/cli/commands/inspect/wait-selector.ts +15 -4
  30. package/cli/commands/inspect.ts +19 -14
  31. package/cli/commands/maestro.ts +464 -43
  32. package/cli/commands/permissions.ts +1 -1
  33. package/cli/commands/platform.ts +205 -8
  34. package/cli/commands/preview.ts +2 -2
  35. package/cli/commands/record.ts +2 -2
  36. package/cli/commands/report-issue.ts +2 -2
  37. package/cli/commands/screenshot-layers.ts +1 -1
  38. package/cli/commands/screenshot.ts +1 -1
  39. package/cli/commands/setup.ts +2 -2
  40. package/cli/commands/test.ts +440 -115
  41. package/cli/commands/three-mode.ts +1 -1
  42. package/cli/commands/upload.ts +5 -5
  43. package/cli/commands/what-happened.ts +1 -1
  44. package/cli/desktop-companion.ts +3 -3
  45. package/cli/drivers/playwright-sim-host.ts +2 -2
  46. package/cli/flow-file.ts +7 -0
  47. package/cli/flow-live-status.ts +65 -8
  48. package/cli/help-core.ts +3 -3
  49. package/cli/hidden-runtime-alias.ts +1 -1
  50. package/cli/maestro-report.ts +178 -0
  51. package/cli/main.ts +1 -1
  52. package/cli/outbound-endpoints.ts +185 -136
  53. package/cli/parse-args.ts +1 -1
  54. package/cli/registry.ts +1 -1
  55. package/cli/resolve-assets.ts +1 -1
  56. package/cli/run-registry.ts +8 -0
  57. package/cli/send-to-box.ts +4 -4
  58. package/cli/ws-bridge.ts +3 -5
  59. package/detox/expectations.ts +1 -1
  60. package/detox/gestures.ts +2 -2
  61. package/detox/index.ts +71 -29
  62. package/detox/jest-preset.cjs +3 -3
  63. package/detox/jest-setup-after-env.cjs +1 -1
  64. package/dist-lib/agent-daemon-client.cjs +2 -2
  65. package/dist-lib/agent-events.cjs +1 -1
  66. package/dist-lib/agent-identity.cjs +1 -1
  67. package/dist-lib/agent-sessions.cjs +2 -2
  68. package/dist-lib/attached-projects.cjs +2 -2
  69. package/dist-lib/auth/shared-session.cjs +1 -1
  70. package/dist-lib/backend-origin.cjs +1 -1
  71. package/dist-lib/beta.cjs +1 -1
  72. package/dist-lib/beta.mjs +1 -1
  73. package/dist-lib/bridge-constants.cjs +1 -1
  74. package/dist-lib/bridge-contract-input.cjs +1 -1
  75. package/dist-lib/bridge-contract-input.mjs +1 -1
  76. package/dist-lib/bridge-contract.cjs +1 -1
  77. package/dist-lib/bridge-contract.mjs +1 -1
  78. package/dist-lib/capture-contract.cjs +94 -3
  79. package/dist-lib/capture-contract.mjs +93 -3
  80. package/dist-lib/cli-constants.cjs +1 -1
  81. package/dist-lib/cloud-contract.cjs +1 -1
  82. package/dist-lib/cloud-contract.mjs +1 -1
  83. package/dist-lib/cloud.cjs +2 -2
  84. package/dist-lib/cloud.mjs +2 -2
  85. package/dist-lib/config.cjs +1 -1
  86. package/dist-lib/detox/index.cjs +106 -25
  87. package/dist-lib/detox/jest-preset.cjs +3 -3
  88. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  89. package/dist-lib/home-paths.cjs +1 -1
  90. package/dist-lib/host/bridge-host.cjs +137 -61
  91. package/dist-lib/host/fetch-proxy-handler.cjs +28 -2
  92. package/dist-lib/host/fetch-proxy-overrides.cjs +33 -3
  93. package/dist-lib/host/fetch-proxy-overrides.mjs +30 -2
  94. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  95. package/dist-lib/host/websocket-proxy.cjs +1 -1
  96. package/dist-lib/index.cjs +209 -16
  97. package/dist-lib/jump-to-source-babel.cjs +1 -1
  98. package/dist-lib/jump-to-source-native.cjs +1 -1
  99. package/dist-lib/menu.cjs +2 -2
  100. package/dist-lib/menu.mjs +2 -2
  101. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  102. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  103. package/dist-lib/metro-production-bundle.cjs +3 -3
  104. package/dist-lib/metro-production-bundle.mjs +3 -3
  105. package/dist-lib/metro.cjs +8 -8
  106. package/dist-lib/profiles.cjs +1 -1
  107. package/dist-lib/public-brand.cjs +2 -2
  108. package/dist-lib/react-native-host-modules.cjs +1 -1
  109. package/dist-lib/react-native-host-modules.mjs +1 -1
  110. package/dist-lib/render-mode.cjs +1 -1
  111. package/dist-lib/scripts/dev-server-scanner.cjs +31 -15
  112. package/dist-lib/sdk.cjs +3 -2
  113. package/dist-lib/sdk.mjs +3 -2
  114. package/dist-lib/skills.cjs +362 -163
  115. package/dist-lib/swift-submit.cjs +1 -1
  116. package/dist-lib/swift-submit.mjs +1 -1
  117. package/dist-lib/swift.cjs +583 -16
  118. package/dist-lib/vite.cjs +29 -14
  119. package/package.json +9 -9
  120. package/scripts/dev-server-scanner.ts +41 -14
  121. package/scripts/optional-demo-registry.ts +3 -3
  122. package/skills/contrast/SKILL.md +9 -9
  123. package/skills/rnx-debug/SKILL.md +14 -4
  124. package/skills/rnx-perf/SKILL.md +5 -5
  125. package/skills/rnx-setup/SKILL.md +11 -11
  126. package/skills/rnx-test/SKILL.md +11 -11
  127. package/skills/rnx-visual/SKILL.md +6 -6
  128. package/src/agent-sessions.ts +3 -3
  129. package/src/attached-projects.ts +1 -1
  130. package/src/bridge-contract-input.ts +1 -1
  131. package/src/bridge-contract.ts +23 -5
  132. package/src/capture-contract.ts +145 -3
  133. package/src/config.ts +2 -2
  134. package/src/connect.ts +2 -2
  135. package/src/home-paths.ts +3 -3
  136. package/src/host/bridge-host.ts +2 -2
  137. package/src/host/fetch-proxy-handler.ts +4 -3
  138. package/src/host/fetch-proxy-overrides.ts +41 -0
  139. package/src/host/plane-host.ts +2 -2
  140. package/src/index.ts +3 -0
  141. package/src/metro-plugin.ts +4 -4
  142. package/src/metro-production-bundle.ts +2 -2
  143. package/src/native-seam-manifest.ts +6 -6
  144. package/src/public-brand.ts +1 -1
  145. package/src/rolldown-plugin-swift.ts +8 -5
  146. package/src/runtime-assets.ts +8 -6
  147. package/src/screenshots/frame-compose.ts +24 -56
  148. package/src/screenshots/org-deck.ts +1 -1
  149. package/src/screenshots/registry.ts +4 -4
  150. package/src/screenshots/schema.ts +1 -1
  151. package/src/sdk.ts +2 -2
  152. package/src/settings-bundle.ts +1 -1
  153. package/src/sim-client.ts +2 -4
  154. package/src/skills/builtin/compat-check.ts +1 -1
  155. package/src/vite-plugin-one.ts +1 -1
  156. package/src/vite-plugin-swift.ts +11 -6
  157. package/src/vite-plugin.ts +30 -17
  158. package/src/worklets-babel.ts +2 -2
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.527 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.570 | (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
4
  var __create = Object.create;
@@ -44,6 +44,7 @@ var import_ui = require("contrast-kit/ui");
44
44
  var import_react = require("react");
45
45
  var import_react_native = require("react-native");
46
46
  var import_react_native_bottom_tabs = __toESM(require("react-native-bottom-tabs"), 1);
47
+ var import_react_native_pager_view = __toESM(require("react-native-pager-view"), 1);
47
48
 
48
49
  // ../sootsim-swift/src/bundleAssets.ts
49
50
  function resolveImageSource(source, table, onMiss) {
@@ -294,6 +295,9 @@ function createResFs(files) {
294
295
 
295
296
  // ../sootsim-swift/src/mount.tsx
296
297
  var import_jsx_runtime = require("react/jsx-runtime");
298
+ function rnSvg() {
299
+ return require("react-native-svg");
300
+ }
297
301
  function isRecord(value) {
298
302
  return typeof value === "object" && value !== null;
299
303
  }
@@ -419,7 +423,7 @@ function wasiImports(host, argv, resFiles) {
419
423
  return 0;
420
424
  },
421
425
  clock_time_get: (clockId, _precision, timePtr) => {
422
- const nanos = clockId === 1 ? BigInt(Math.round(performance.now() * 1e6)) : clockId === 0 ? BigInt(Date.now()) * 1000000n : null;
426
+ const nanos = clockId === 1 ? BigInt(Math.round(performance.now() * 1e6)) : clockId === 0 ? BigInt(Math.floor(Date.now())) * 1000000n : null;
423
427
  if (nanos === null) return WASI_INVAL;
424
428
  host.writeU64(timePtr, nanos);
425
429
  return 0;
@@ -699,16 +703,427 @@ function SwiftImage(props) {
699
703
  ...source === void 0 ? {} : { source: resolved }
700
704
  });
701
705
  }
706
+ function readCanvasNumber(op, field, id) {
707
+ const value = op[field];
708
+ if (typeof value !== "number" || !Number.isFinite(value)) {
709
+ throw new Error(`swift canvas ${id} op ${op.op} has no numeric ${field}`);
710
+ }
711
+ return value;
712
+ }
713
+ function readCanvasString(op, field, id) {
714
+ const value = op[field];
715
+ if (typeof value !== "string") {
716
+ throw new Error(`swift canvas ${id} op ${op.op} has no string ${field}`);
717
+ }
718
+ return value;
719
+ }
720
+ function readCanvasOps(value, id) {
721
+ if (!Array.isArray(value)) throw new Error(`swift canvas ${id} has non-array ops`);
722
+ return value.map((op) => {
723
+ if (!isRecord(op) || typeof op.op !== "string") {
724
+ throw new Error(`swift canvas ${id} has an op with no name`);
725
+ }
726
+ return { ...op, op: op.op };
727
+ });
728
+ }
729
+ function readCanvasShading(op, id) {
730
+ const shading = op.shading;
731
+ if (!isRecord(shading))
732
+ throw new Error(`swift canvas ${id} op ${op.op} has no shading object`);
733
+ if (shading.kind !== "radial") {
734
+ throw new Error(
735
+ `swift canvas ${id} op ${op.op} shading ${String(shading.kind)} is not lowerable`
736
+ );
737
+ }
738
+ const center = shading.center;
739
+ if (!isRecord(center) || typeof center.x !== "number" || typeof center.y !== "number") {
740
+ throw new Error(`swift canvas ${id} op ${op.op} shading has no numeric center`);
741
+ }
742
+ for (const field of ["startRadius", "endRadius"]) {
743
+ if (typeof shading[field] !== "number") {
744
+ throw new Error(`swift canvas ${id} op ${op.op} shading has no numeric ${field}`);
745
+ }
746
+ }
747
+ const stops = shading.stops;
748
+ if (!Array.isArray(stops) || stops.length === 0) {
749
+ throw new Error(`swift canvas ${id} op ${op.op} shading has no stops`);
750
+ }
751
+ return {
752
+ kind: "radial",
753
+ center: { x: center.x, y: center.y },
754
+ startRadius: shading.startRadius,
755
+ endRadius: shading.endRadius,
756
+ stops: stops.map((stop) => {
757
+ if (!isRecord(stop) || typeof stop.color !== "string" || typeof stop.location !== "number") {
758
+ throw new Error(`swift canvas ${id} op ${op.op} shading has a malformed stop`);
759
+ }
760
+ return { color: resolveColor(stop.color), location: stop.location };
761
+ })
762
+ };
763
+ }
764
+ function resolveCanvasOp(op, id) {
765
+ if (op.op === "fill" || op.op === "stroke") {
766
+ if (op.color !== void 0) {
767
+ return { ...op, color: resolveColor(readCanvasString(op, "color", id)) };
768
+ }
769
+ return { ...op, shading: readCanvasShading(op, id) };
770
+ }
771
+ if (op.op === "layer") {
772
+ return {
773
+ ...op,
774
+ ops: readCanvasOps(op.ops, id).map((inner) => resolveCanvasOp(inner, id))
775
+ };
776
+ }
777
+ if (op.op === "drawImage") {
778
+ const anchor = op.anchor;
779
+ if (!isRecord(anchor) || typeof anchor.x !== "number" || typeof anchor.y !== "number") {
780
+ throw new Error(`swift canvas ${id} op drawImage has no numeric anchor`);
781
+ }
782
+ if (op.kind !== "asset" && op.kind !== "symbol") {
783
+ throw new Error(
784
+ `swift canvas ${id} drawImage kind ${String(op.kind)} is not lowerable`
785
+ );
786
+ }
787
+ return op;
788
+ }
789
+ return op;
790
+ }
791
+ function lowerCanvasOps(ops, size, id) {
792
+ const defs = [];
793
+ const cx = size.width / 2;
794
+ const cy = size.height / 2;
795
+ const toSvgList = (entries) => entries.map((entry) => {
796
+ if ("translateX" in entry) return `translate(${entry.translateX} 0)`;
797
+ if ("translateY" in entry) return `translate(0 ${entry.translateY})`;
798
+ if ("scaleX" in entry) return `scale(${entry.scaleX} 1)`;
799
+ if ("scaleY" in entry) return `scale(1 ${entry.scaleY})`;
800
+ return `rotate(${entry.rotate.replace("deg", "")})`;
801
+ }).join(" ");
802
+ const lowerList = (list, state) => {
803
+ const layers = [];
804
+ const snap = () => ({
805
+ ...state.opacity === 1 ? {} : { opacity: state.opacity },
806
+ ...state.transform.length === 0 ? {} : {
807
+ transformSvg: toSvgList(state.transform),
808
+ transformRN: state.transform.map((entry) => ({ ...entry }))
809
+ }
810
+ });
811
+ for (const op of list) {
812
+ if (op.op === "opacity") {
813
+ state.opacity = readCanvasNumber(op, "value", id);
814
+ continue;
815
+ }
816
+ if (op.op === "translate") {
817
+ state.transform.push({ translateX: readCanvasNumber(op, "x", id) });
818
+ state.transform.push({ translateY: readCanvasNumber(op, "y", id) });
819
+ continue;
820
+ }
821
+ if (op.op === "scale") {
822
+ const x = readCanvasNumber(op, "x", id);
823
+ const y = readCanvasNumber(op, "y", id);
824
+ state.transform.push(
825
+ { translateX: cx },
826
+ { translateY: cy },
827
+ { scaleX: x },
828
+ { scaleY: y },
829
+ { translateX: -cx },
830
+ { translateY: -cy }
831
+ );
832
+ continue;
833
+ }
834
+ if (op.op === "rotate") {
835
+ const degrees = readCanvasNumber(op, "degrees", id);
836
+ state.transform.push(
837
+ { translateX: cx },
838
+ { translateY: cy },
839
+ { rotate: `${degrees}deg` },
840
+ { translateX: -cx },
841
+ { translateY: -cy }
842
+ );
843
+ continue;
844
+ }
845
+ if (op.op === "layer") {
846
+ if (!Array.isArray(op.ops))
847
+ throw new Error(`swift canvas ${id} layer has non-array ops`);
848
+ layers.push(
849
+ ...lowerList(readCanvasOps(op.ops, id), {
850
+ opacity: state.opacity,
851
+ transform: state.transform.map((entry) => ({ ...entry }))
852
+ })
853
+ );
854
+ continue;
855
+ }
856
+ const shot = snap();
857
+ if (op.op === "fill" || op.op === "stroke") {
858
+ const d = readCanvasString(op, "d", id);
859
+ const shading = op.shading;
860
+ if (isRecord(shading)) {
861
+ if (op.op === "stroke") {
862
+ throw new Error(`swift canvas ${id} stroke with shading is not lowerable`);
863
+ }
864
+ const center = shading.center;
865
+ const stops = shading.stops;
866
+ if (shading.kind !== "radial" || !isRecord(center) || typeof center.x !== "number" || typeof center.y !== "number" || typeof shading.startRadius !== "number" || typeof shading.endRadius !== "number" || !Array.isArray(stops) || stops.length === 0) {
867
+ throw new Error(`swift canvas ${id} fill shading is not lowerable`);
868
+ }
869
+ if (shading.startRadius !== 0) {
870
+ throw new Error(
871
+ `swift canvas ${id} radial startRadius ${shading.startRadius} is not lowerable`
872
+ );
873
+ }
874
+ const gradientId = `cgr${defs.length}`;
875
+ defs.push({
876
+ id: gradientId,
877
+ cx: center.x,
878
+ cy: center.y,
879
+ r: shading.endRadius,
880
+ fx: center.x,
881
+ fy: center.y,
882
+ stops: stops.map((stop) => {
883
+ if (!isRecord(stop) || typeof stop.location !== "number" || stop.color === void 0) {
884
+ throw new Error(`swift canvas ${id} fill shading has a malformed stop`);
885
+ }
886
+ return { color: stop.color, location: stop.location };
887
+ })
888
+ });
889
+ layers.push({
890
+ ...shot,
891
+ svg: { kind: "path", d, fill: { gradient: gradientId } }
892
+ });
893
+ continue;
894
+ }
895
+ if (op.color === void 0) {
896
+ throw new Error(`swift canvas ${id} op ${op.op} has no resolved color`);
897
+ }
898
+ layers.push({
899
+ ...shot,
900
+ svg: {
901
+ kind: "path",
902
+ d,
903
+ ...op.op === "fill" ? { fill: op.color } : { stroke: op.color, strokeWidth: readCanvasNumber(op, "lineWidth", id) }
904
+ }
905
+ });
906
+ continue;
907
+ }
908
+ if (op.op === "drawImage") {
909
+ const x = readCanvasNumber(op, "x", id);
910
+ const y = readCanvasNumber(op, "y", id);
911
+ const anchor = op.anchor;
912
+ if (!isRecord(anchor) || typeof anchor.x !== "number" || typeof anchor.y !== "number") {
913
+ throw new Error(`swift canvas ${id} op drawImage has no numeric anchor`);
914
+ }
915
+ const name = readCanvasString(op, "name", id);
916
+ if (op.kind === "symbol") {
917
+ layers.push({
918
+ ...shot,
919
+ overlay: {
920
+ kind: "symbol",
921
+ name,
922
+ left: x - 17 * anchor.x,
923
+ top: y - 17 * anchor.y
924
+ }
925
+ });
926
+ continue;
927
+ }
928
+ if (op.kind !== "asset") {
929
+ throw new Error(
930
+ `swift canvas ${id} drawImage kind ${String(op.kind)} is not lowerable`
931
+ );
932
+ }
933
+ layers.push({
934
+ ...shot,
935
+ svg: {
936
+ kind: "asset",
937
+ source: name,
938
+ x,
939
+ y,
940
+ anchor: { x: anchor.x, y: anchor.y }
941
+ }
942
+ });
943
+ continue;
944
+ }
945
+ if (op.op === "drawText") {
946
+ layers.push({
947
+ ...shot,
948
+ overlay: {
949
+ kind: "text",
950
+ text: readCanvasString(op, "text", id),
951
+ left: readCanvasNumber(op, "x", id),
952
+ top: readCanvasNumber(op, "y", id)
953
+ }
954
+ });
955
+ continue;
956
+ }
957
+ throw new Error(`swift canvas ${id} op ${op.op} is not lowerable`);
958
+ }
959
+ return layers;
960
+ };
961
+ return { defs, layers: lowerList(ops, { opacity: 1, transform: [] }) };
962
+ }
963
+ function SwiftCanvasAsset({
964
+ name,
965
+ x,
966
+ y,
967
+ anchor
968
+ }) {
969
+ const table = (0, import_react.useContext)(SwiftResourcesContext);
970
+ const [dims, setDims] = (0, import_react.useState)(null);
971
+ const uri = table?.[name];
972
+ (0, import_react.useEffect)(() => {
973
+ if (uri === void 0) {
974
+ console.error(`swift: no bundle asset named '${name}' in this mount's resources`);
975
+ return;
976
+ }
977
+ let live = true;
978
+ import_react_native.Image.getSize(
979
+ uri,
980
+ (width, height) => {
981
+ if (live) setDims({ width, height });
982
+ },
983
+ () => {
984
+ }
985
+ );
986
+ return () => {
987
+ live = false;
988
+ };
989
+ }, [uri, name]);
990
+ if (uri === void 0 || dims === null) return null;
991
+ const { Image: SvgImage } = rnSvg();
992
+ return (0, import_react.createElement)(SvgImage, {
993
+ x: x - dims.width * anchor.x,
994
+ y: y - dims.height * anchor.y,
995
+ width: dims.width,
996
+ height: dims.height,
997
+ href: { uri }
998
+ });
999
+ }
1000
+ function SwiftCanvas({
1001
+ size,
1002
+ ops,
1003
+ modifiers
1004
+ }) {
1005
+ const { defs, layers } = lowerCanvasOps(ops, size, "canvas");
1006
+ const { default: Svg, Defs, G, Path: SvgPath, RadialGradient, Stop } = rnSvg();
1007
+ const svgLayers = [];
1008
+ const overlays = [];
1009
+ layers.forEach((layer, index) => {
1010
+ if (layer.svg !== void 0) {
1011
+ const content = layer.svg.kind === "path" ? (
1012
+ // resolved colors are unknown-typed (platform colors, dynamics);
1013
+ // the seam takes any brush, like the pager/tab seams take any props.
1014
+ (0, import_react.createElement)(SvgPath, {
1015
+ d: layer.svg.d,
1016
+ ...isRecord(layer.svg.fill) && typeof layer.svg.fill.gradient === "string" ? { fill: `url(#${layer.svg.fill.gradient})` } : layer.svg.fill !== void 0 ? { fill: layer.svg.fill } : {},
1017
+ ...layer.svg.stroke !== void 0 ? { stroke: layer.svg.stroke } : {},
1018
+ ...layer.svg.strokeWidth !== void 0 ? { strokeWidth: layer.svg.strokeWidth } : {}
1019
+ })
1020
+ ) : (0, import_react.createElement)(SwiftCanvasAsset, {
1021
+ name: layer.svg.source,
1022
+ x: layer.svg.x,
1023
+ y: layer.svg.y,
1024
+ anchor: layer.svg.anchor
1025
+ });
1026
+ svgLayers.push(
1027
+ (0, import_react.createElement)(
1028
+ G,
1029
+ {
1030
+ key: `op-${index}`,
1031
+ ...layer.opacity === void 0 ? {} : { opacity: layer.opacity },
1032
+ ...layer.transformSvg === void 0 ? {} : { transform: layer.transformSvg }
1033
+ },
1034
+ content
1035
+ )
1036
+ );
1037
+ return;
1038
+ }
1039
+ if (layer.overlay !== void 0) {
1040
+ const content = layer.overlay.kind === "symbol" ? (0, import_react.createElement)(import_ui.Image, { systemName: layer.overlay.name, size: 17 }) : (0, import_react.createElement)(import_ui.Text, null, layer.overlay.text);
1041
+ overlays.push(
1042
+ (0, import_react.createElement)(
1043
+ import_react_native.View,
1044
+ {
1045
+ key: `op-${index}`,
1046
+ style: {
1047
+ position: "absolute",
1048
+ left: 0,
1049
+ top: 0,
1050
+ width: size.width,
1051
+ height: size.height,
1052
+ ...layer.opacity === void 0 ? {} : { opacity: layer.opacity },
1053
+ ...layer.transformRN === void 0 ? {} : { transform: layer.transformRN }
1054
+ }
1055
+ },
1056
+ (0, import_react.createElement)(
1057
+ import_react_native.View,
1058
+ {
1059
+ style: {
1060
+ position: "absolute",
1061
+ left: layer.overlay.left,
1062
+ top: layer.overlay.top
1063
+ }
1064
+ },
1065
+ content
1066
+ )
1067
+ )
1068
+ );
1069
+ }
1070
+ });
1071
+ return (0, import_react.createElement)(
1072
+ import_react_native.View,
1073
+ {
1074
+ ...modifiers?.length ? { modifiers } : {},
1075
+ style: {
1076
+ width: size.width,
1077
+ height: size.height,
1078
+ overflow: "hidden"
1079
+ }
1080
+ },
1081
+ (0, import_react.createElement)(
1082
+ Svg,
1083
+ { width: size.width, height: size.height },
1084
+ defs.length === 0 ? null : (0, import_react.createElement)(
1085
+ Defs,
1086
+ null,
1087
+ ...defs.map(
1088
+ (def) => (0, import_react.createElement)(
1089
+ RadialGradient,
1090
+ {
1091
+ key: def.id,
1092
+ id: def.id,
1093
+ gradientUnits: "userSpaceOnUse",
1094
+ cx: def.cx,
1095
+ cy: def.cy,
1096
+ r: def.r,
1097
+ fx: def.fx,
1098
+ fy: def.fy
1099
+ },
1100
+ ...def.stops.map(
1101
+ (stop, stopIndex) => (0, import_react.createElement)(Stop, {
1102
+ key: `stop-${stopIndex}`,
1103
+ offset: stop.location,
1104
+ stopColor: stop.color
1105
+ })
1106
+ )
1107
+ )
1108
+ )
1109
+ ),
1110
+ ...svgLayers
1111
+ ),
1112
+ ...overlays
1113
+ );
1114
+ }
702
1115
  var NODE_COMPONENTS = {
703
1116
  Alert: SwiftAlert,
704
1117
  BottomSheet: import_ui.BottomSheet,
705
1118
  Button: import_ui.Button,
1119
+ Canvas: SwiftCanvas,
706
1120
  Capsule: import_ui.Capsule,
707
1121
  Circle: import_ui.Circle,
708
1122
  ConfirmationDialog: import_ui.ConfirmationDialog,
709
1123
  ContextMenu: import_ui.ContextMenu,
710
1124
  DatePicker: import_ui.DatePicker,
711
1125
  Divider: import_ui.Divider,
1126
+ EditButton: import_ui.Button,
712
1127
  Ellipse: import_ui.Ellipse,
713
1128
  Form: import_ui.Form,
714
1129
  GeometryReader: import_ui.GeometryReader,
@@ -719,7 +1134,9 @@ var NODE_COMPONENTS = {
719
1134
  Label: import_ui.Label,
720
1135
  LazyVStack: import_ui.LazyVStack,
721
1136
  LinearGradient: import_ui.LinearGradient,
1137
+ Link: import_ui.Link,
722
1138
  List: import_ui.List,
1139
+ Map: import_ui.Map,
723
1140
  Menu: import_ui.Menu,
724
1141
  Path: import_ui.Path,
725
1142
  Picker: import_ui.Picker,
@@ -765,6 +1182,11 @@ var FONT_WEIGHTS = /* @__PURE__ */ new Map([
765
1182
  ["heavy", "800"],
766
1183
  ["black", "900"]
767
1184
  ]);
1185
+ var TEXT_ALIGNS = /* @__PURE__ */ new Map([
1186
+ ["leading", "left"],
1187
+ ["center", "center"],
1188
+ ["trailing", "right"]
1189
+ ]);
768
1190
  function fontModifier(modifiers) {
769
1191
  return modifiers?.find((modifier) => modifier.$type === "font");
770
1192
  }
@@ -785,6 +1207,13 @@ function fontStyle(font) {
785
1207
  }
786
1208
  return style;
787
1209
  }
1210
+ function textAlign(alignment) {
1211
+ if (!alignment || typeof alignment.alignment !== "string") return void 0;
1212
+ const align = TEXT_ALIGNS.get(alignment.alignment);
1213
+ if (align === void 0)
1214
+ throw new Error(`swift text alignment ${alignment.alignment} has no value`);
1215
+ return { textAlign: align };
1216
+ }
788
1217
  function sameValue(a, b) {
789
1218
  if (a === b) return true;
790
1219
  if (Array.isArray(a) && Array.isArray(b)) {
@@ -835,10 +1264,69 @@ function pressProps(node, deliver) {
835
1264
  function SwiftTabScene({ children }) {
836
1265
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
837
1266
  }
1267
+ function SwiftPageView({
1268
+ selection,
1269
+ onSelect,
1270
+ indexDisplayMode,
1271
+ modifiers,
1272
+ children
1273
+ }) {
1274
+ const scenes = import_react.Children.toArray(children);
1275
+ const count = scenes.length;
1276
+ const index = selection >= 0 && selection < count ? selection : 0;
1277
+ const pagerRef = (0, import_react.useRef)(null);
1278
+ (0, import_react.useEffect)(() => {
1279
+ if (selection !== index) onSelect?.(index);
1280
+ }, [selection, index, onSelect]);
1281
+ (0, import_react.useEffect)(() => {
1282
+ pagerRef.current?.setPageWithoutAnimation?.(index);
1283
+ }, [index]);
1284
+ const showDots = indexDisplayMode !== "never" && (indexDisplayMode === "always" || count > 1);
1285
+ return (0, import_react.createElement)(
1286
+ import_ui.VStack,
1287
+ {
1288
+ ...modifiers?.length ? { modifiers } : {},
1289
+ style: {
1290
+ alignSelf: "stretch",
1291
+ alignItems: "stretch",
1292
+ flexGrow: 1,
1293
+ flexShrink: 1,
1294
+ flexBasis: "auto"
1295
+ }
1296
+ },
1297
+ (0, import_react.createElement)(
1298
+ import_ui.ZStack,
1299
+ { style: { flexGrow: 1 } },
1300
+ (0, import_react.createElement)(
1301
+ import_react_native_pager_view.default,
1302
+ {
1303
+ ref: pagerRef,
1304
+ initialPage: index,
1305
+ style: { flex: 1 },
1306
+ onPageSelected: (event) => onSelect?.(event.nativeEvent.position)
1307
+ },
1308
+ ...scenes
1309
+ ),
1310
+ showDots ? (0, import_react.createElement)(
1311
+ import_react_native.View,
1312
+ {
1313
+ style: {
1314
+ flex: 1,
1315
+ justifyContent: "flex-end",
1316
+ alignItems: "center",
1317
+ paddingBottom: 8
1318
+ }
1319
+ },
1320
+ (0, import_react.createElement)(import_ui.PageControl, { count, current: index, onSelect })
1321
+ ) : null
1322
+ )
1323
+ );
1324
+ }
838
1325
  function SwiftTabView({
839
1326
  tabs,
840
1327
  selection,
841
1328
  onSelect,
1329
+ page,
842
1330
  modifiers,
843
1331
  children
844
1332
  }) {
@@ -851,9 +1339,19 @@ function SwiftTabView({
851
1339
  testID: tab.testID
852
1340
  }));
853
1341
  const index = selection >= 0 && selection < routes.length ? selection : 0;
1342
+ const isPage = page !== void 0;
854
1343
  (0, import_react.useEffect)(() => {
855
- if (selection !== index) onSelect?.(index);
856
- }, [selection, index, onSelect]);
1344
+ if (!isPage && selection !== index) onSelect?.(index);
1345
+ }, [isPage, selection, index, onSelect]);
1346
+ if (page !== void 0) {
1347
+ return (0, import_react.createElement)(SwiftPageView, {
1348
+ selection,
1349
+ onSelect,
1350
+ indexDisplayMode: page.indexDisplayMode,
1351
+ modifiers,
1352
+ children
1353
+ });
1354
+ }
857
1355
  const bar = (0, import_react.createElement)(import_react_native_bottom_tabs.default, {
858
1356
  navigationState: { index, routes },
859
1357
  renderScene: ({ route }) => scenes[routes.findIndex((candidate) => candidate.key === route.key)],
@@ -925,22 +1423,30 @@ function nodeProps(node, deliver) {
925
1423
  const props = node.p ?? {};
926
1424
  switch (node.t) {
927
1425
  case "Text": {
928
- const style = fontStyle(fontModifier(node.m));
1426
+ const style = {
1427
+ ...fontStyle(fontModifier(node.m)),
1428
+ ...textAlign(
1429
+ node.m?.find((modifier) => modifier.$type === "multilineTextAlignment")
1430
+ )
1431
+ };
929
1432
  return {
930
1433
  children: typeof props.children === "string" ? props.children : "",
931
- ...style ? { style } : {},
1434
+ ...Object.keys(style).length > 0 ? { style } : {},
932
1435
  ...pressProps(node, deliver)
933
1436
  };
934
1437
  }
935
1438
  case "Image": {
936
1439
  const font = fontModifier(node.m);
937
1440
  const size = typeof font?.size === "number" ? font.size : void 0;
1441
+ const symbolVariant = node.m?.find((modifier) => modifier.$type === "symbolVariant");
1442
+ const systemName = typeof props.systemName === "string" && symbolVariant?.fill === true && !props.systemName.endsWith(".fill") ? `${props.systemName}.fill` : props.systemName;
938
1443
  return {
939
- ...typeof props.systemName === "string" ? { systemName: props.systemName } : {},
1444
+ ...typeof systemName === "string" ? { systemName } : {},
940
1445
  // a bundle asset name rides as the kit image source; the kit paints
941
1446
  // resolved { uri } sources and keeps its placeholder for names the
942
1447
  // table could not resolve.
943
1448
  ...typeof props.name === "string" ? { source: props.name } : {},
1449
+ ...typeof props.url === "string" ? { source: { uri: props.url } } : {},
944
1450
  ...props.resizable === true ? { resizable: true } : {},
945
1451
  ...typeof props.renderingMode === "string" ? { renderingMode: props.renderingMode } : {},
946
1452
  ...size === void 0 ? {} : { size },
@@ -952,8 +1458,9 @@ function nodeProps(node, deliver) {
952
1458
  return {
953
1459
  isOn: props.value === true,
954
1460
  ...onValueChange === void 0 ? {} : { onIsOnChange: (value) => deliver(onValueChange, value) },
955
- // the gesture replaces the row's own press (a label tap runs it and
956
- // does not toggle); the switch keeps toggling through onValueChange.
1461
+ // the gesture is the row's only press (a label tap runs it and does
1462
+ // not toggle; without one the row is inert); the switch keeps toggling
1463
+ // through onValueChange.
957
1464
  ...pressProps(node, deliver)
958
1465
  };
959
1466
  }
@@ -992,12 +1499,49 @@ function nodeProps(node, deliver) {
992
1499
  testID: `swift-tab-${index}`
993
1500
  };
994
1501
  });
1502
+ const tabViewStyle = (node.m ?? []).find(
1503
+ (modifier) => modifier.$type === "tabViewStyle"
1504
+ );
995
1505
  return {
996
1506
  tabs,
997
1507
  selection: typeof props.selection === "number" ? props.selection : 0,
1508
+ ...tabViewStyle?.style === "page" ? {
1509
+ page: {
1510
+ indexDisplayMode: typeof tabViewStyle.indexDisplayMode === "string" ? tabViewStyle.indexDisplayMode : "automatic"
1511
+ }
1512
+ } : {},
998
1513
  ...onSelect === void 0 ? {} : { onSelect: (index) => deliver(onSelect, index) }
999
1514
  };
1000
1515
  }
1516
+ case "Map": {
1517
+ const mode = props.mode;
1518
+ if (mode !== "region" && mode !== "camera" && mode !== "rect") {
1519
+ throw new Error(
1520
+ `swift map ${node.id} has position ${JSON.stringify(mode)}, which needs live context the paint cannot solve`
1521
+ );
1522
+ }
1523
+ const names = mode === "region" ? ["latitude", "longitude", "latitudeDelta", "longitudeDelta"] : mode === "camera" ? ["latitude", "longitude", "distance", "pitch", "heading"] : ["x", "y", "width", "height"];
1524
+ const out = {};
1525
+ for (const name of names) {
1526
+ const value = props[name];
1527
+ if (typeof value !== "number" || !Number.isFinite(value)) {
1528
+ throw new Error(`swift map ${node.id} has no numeric ${name}`);
1529
+ }
1530
+ out[name] = value;
1531
+ }
1532
+ return { mode, ...out, testID: node.id };
1533
+ }
1534
+ case "Canvas": {
1535
+ const sizeValue = props.size;
1536
+ if (!isRecord(sizeValue) || typeof sizeValue.width !== "number" || !Number.isFinite(sizeValue.width) || typeof sizeValue.height !== "number" || !Number.isFinite(sizeValue.height)) {
1537
+ throw new Error(`swift canvas ${node.id} has no numeric size`);
1538
+ }
1539
+ const size = { width: sizeValue.width, height: sizeValue.height };
1540
+ const ops = readCanvasOps(props.ops, node.id).map(
1541
+ (op) => resolveCanvasOp(op, node.id)
1542
+ );
1543
+ return { size, ops };
1544
+ }
1001
1545
  case "BottomSheet": {
1002
1546
  const onDismiss = handlerId(node, "onDismiss");
1003
1547
  const detents = (node.c ?? []).flatMap((child) => nodeModifiers(child) ?? []).filter((modifier) => modifier.$type === "presentationDetents");
@@ -1244,7 +1788,7 @@ function buttonModifier(modifier) {
1244
1788
  }
1245
1789
  function nodeModifiers(node) {
1246
1790
  const resolved = node.m?.map(resolveModifier);
1247
- if (node.t !== "Button") return resolved;
1791
+ if (node.t !== "Button" && node.t !== "EditButton") return resolved;
1248
1792
  return resolved?.map(buttonModifier);
1249
1793
  }
1250
1794
  function dialogChildren(node, deliver) {
@@ -1291,7 +1835,8 @@ function screenOptions(node, deliver, largeTitle, replaceAnimation) {
1291
1835
  const props = node.p ?? {};
1292
1836
  const options = {
1293
1837
  title: typeof props.title === "string" ? props.title : "",
1294
- headerLargeTitleEnabled: largeTitle
1838
+ headerLargeTitleEnabled: largeTitle,
1839
+ contentStyle: { backgroundColor: (0, import_react_native.PlatformColor)("systemBackground") }
1295
1840
  };
1296
1841
  if (replaceAnimation !== void 0) options.animationTypeForReplace = replaceAnimation;
1297
1842
  const leading = readNodes(props.leading);
@@ -1321,6 +1866,7 @@ function SwiftScreen({
1321
1866
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: node.c?.map((child) => renderNode(child, deliver)) });
1322
1867
  }
1323
1868
  function NavigationStackHost({ node, deliver }) {
1869
+ const scheme = (0, import_react_native.useColorScheme)();
1324
1870
  const screens = (node.c ?? []).filter((child) => child.t === "NavigationScreen");
1325
1871
  const desired = screens.map((screen) => screen.id);
1326
1872
  const largeTitles = resolveLargeTitles(
@@ -1384,7 +1930,7 @@ function NavigationStackHost({ node, deliver }) {
1384
1930
  routes: desired.map((name) => ({ name }))
1385
1931
  });
1386
1932
  });
1387
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stack.Navigator, { initialRouteName: desired[0], children: screens.map((screen, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1933
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationIndependentTree, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationContainer, { theme: scheme === "dark" ? import_native.DarkTheme : import_native.DefaultTheme, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stack.Navigator, { initialRouteName: desired[0], children: screens.map((screen, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1388
1934
  Stack.Screen,
1389
1935
  {
1390
1936
  name: screen.id,
@@ -1405,7 +1951,7 @@ function NavigationStackHost({ node, deliver }) {
1405
1951
  )
1406
1952
  },
1407
1953
  screen.id
1408
- )) });
1954
+ )) }) }) });
1409
1955
  }
1410
1956
  var REGULAR_WIDTH = 768;
1411
1957
  function SplitViewHost({
@@ -1423,8 +1969,22 @@ function SplitViewHost({
1423
1969
  const detailProp = node.p?.detail;
1424
1970
  const detail = isRecord(detailProp) && detailProp.t === "SplitDetail" ? readNodes(detailProp.c) : [];
1425
1971
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: { flex: 1, flexDirection: "row", alignSelf: "stretch" }, children: [
1426
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { width: 320 }, children: sidebar ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node: { ...node, c: [sidebar] }, deliver }) : null }),
1427
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { flex: 1 }, children: pushed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node: { ...node, c: pushed }, deliver }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: detail.map((child) => renderNode(child, deliver, cache)) }) })
1972
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { width: 320 }, children: sidebar ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1973
+ NavigationStackHost,
1974
+ {
1975
+ node: { ...node, c: [sidebar] },
1976
+ deliver
1977
+ },
1978
+ "sidebar"
1979
+ ) : null }),
1980
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { flex: 1 }, children: pushed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1981
+ NavigationStackHost,
1982
+ {
1983
+ node: { ...node, c: pushed },
1984
+ deliver
1985
+ },
1986
+ "pushed"
1987
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: detail.map((child) => renderNode(child, deliver, cache)) }) })
1428
1988
  ] });
1429
1989
  }
1430
1990
  function SwiftAppear({
@@ -1455,6 +2015,13 @@ function buildNode(node, deliver, cache) {
1455
2015
  if (node.t === "ContextMenu") return renderContextMenu(node, deliver, cache);
1456
2016
  if (node.t === "SwipeActions") return renderSwipeActions(node, deliver, cache);
1457
2017
  if (node.t === "Stepper") return renderStepper(node, deliver, cache);
2018
+ if (node.t === "Chart") {
2019
+ return (0, import_react.createElement)(import_ui.Chart, {
2020
+ key: node.id,
2021
+ marks: (node.c ?? []).map((mark) => ({ ...mark.p ?? {} })),
2022
+ ...node.m === void 0 ? {} : { modifiers: nodeModifiers(node) }
2023
+ });
2024
+ }
1458
2025
  if (node.t === "NavigationStack") {
1459
2026
  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);
1460
2027
  }
@@ -1510,7 +2077,7 @@ function SwiftTree({
1510
2077
  ignoreSafeArea: tree.some(
1511
2078
  (node) => node.t === "NavigationStack" || node.t === "NavigationSplitView"
1512
2079
  ),
1513
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationIndependentTree, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwiftResourcesContext.Provider, { value: resources, children: tree.map((node) => renderNode(node, deliver, cache)) }) }) })
2080
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwiftResourcesContext.Provider, { value: resources, children: tree.map((node) => renderNode(node, deliver, cache)) })
1514
2081
  }
1515
2082
  )
1516
2083
  );