@buoy-gg/shared-ui 3.0.1 → 3.0.2

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 (89) hide show
  1. package/lib/commonjs/JsModal.js +2 -1
  2. package/lib/commonjs/clipboard/clipboard-impl.js +28 -2
  3. package/lib/commonjs/dataViewer/VirtualizedDataExplorer.js +3 -5
  4. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  5. package/lib/commonjs/icons/lucide-icons.js +104 -22
  6. package/lib/commonjs/index.js +7 -0
  7. package/lib/commonjs/license/DeviceLimitModal.js +2 -1
  8. package/lib/commonjs/license/LicenseEntryModal.js +2 -1
  9. package/lib/commonjs/license/ManageDevicesModal.js +2 -1
  10. package/lib/commonjs/stores/BaseEventStore.js +72 -2
  11. package/lib/commonjs/ui/components/CompactRow.js +62 -65
  12. package/lib/commonjs/ui/components/EventHistoryViewer/EventPickerModal.js +3 -2
  13. package/lib/commonjs/ui/components/ExpandableSectionWithModal.js +2 -1
  14. package/lib/commonjs/ui/components/WindowControls.js +9 -3
  15. package/lib/commonjs/ui/console/CyberpunkConsoleSection.js +6 -5
  16. package/lib/commonjs/ui/console/GalaxyButton.js +2 -1
  17. package/lib/commonjs/ui/gameUI/components/GameUIStatusHeader.js +2 -1
  18. package/lib/commonjs/utils/absoluteFill.js +28 -0
  19. package/lib/commonjs/utils/index.js +7 -0
  20. package/lib/module/JsModal.js +2 -1
  21. package/lib/module/clipboard/clipboard-impl.js +28 -2
  22. package/lib/module/dataViewer/VirtualizedDataExplorer.js +3 -5
  23. package/lib/module/hooks/safe-area-impl.js +1 -1
  24. package/lib/module/icons/lucide-icons.js +100 -19
  25. package/lib/module/index.js +2 -0
  26. package/lib/module/license/DeviceLimitModal.js +2 -1
  27. package/lib/module/license/LicenseEntryModal.js +2 -1
  28. package/lib/module/license/ManageDevicesModal.js +2 -1
  29. package/lib/module/stores/BaseEventStore.js +72 -2
  30. package/lib/module/ui/components/CompactRow.js +62 -65
  31. package/lib/module/ui/components/EventHistoryViewer/EventPickerModal.js +3 -2
  32. package/lib/module/ui/components/ExpandableSectionWithModal.js +2 -1
  33. package/lib/module/ui/components/WindowControls.js +10 -4
  34. package/lib/module/ui/console/CyberpunkConsoleSection.js +6 -5
  35. package/lib/module/ui/console/GalaxyButton.js +2 -1
  36. package/lib/module/ui/gameUI/components/GameUIStatusHeader.js +2 -1
  37. package/lib/module/utils/absoluteFill.js +24 -0
  38. package/lib/module/utils/index.js +1 -0
  39. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  40. package/lib/typescript/commonjs/clipboard/clipboard-impl.d.ts +3 -2
  41. package/lib/typescript/commonjs/clipboard/clipboard-impl.d.ts.map +1 -1
  42. package/lib/typescript/commonjs/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
  43. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  44. package/lib/typescript/commonjs/icons/lucide-icons.d.ts +4 -2
  45. package/lib/typescript/commonjs/icons/lucide-icons.d.ts.map +1 -1
  46. package/lib/typescript/commonjs/index.d.ts +1 -1
  47. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  48. package/lib/typescript/commonjs/license/DeviceLimitModal.d.ts.map +1 -1
  49. package/lib/typescript/commonjs/license/LicenseEntryModal.d.ts.map +1 -1
  50. package/lib/typescript/commonjs/license/ManageDevicesModal.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/stores/BaseEventStore.d.ts +28 -0
  52. package/lib/typescript/commonjs/stores/BaseEventStore.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/ui/components/CompactRow.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/ui/components/EventHistoryViewer/EventPickerModal.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/ui/components/ExpandableSectionWithModal.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/ui/console/CyberpunkConsoleSection.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/ui/console/GalaxyButton.d.ts.map +1 -1
  59. package/lib/typescript/commonjs/ui/gameUI/components/GameUIStatusHeader.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/utils/absoluteFill.d.ts +18 -0
  61. package/lib/typescript/commonjs/utils/absoluteFill.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/utils/index.d.ts +1 -0
  63. package/lib/typescript/commonjs/utils/index.d.ts.map +1 -1
  64. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  65. package/lib/typescript/module/clipboard/clipboard-impl.d.ts +3 -2
  66. package/lib/typescript/module/clipboard/clipboard-impl.d.ts.map +1 -1
  67. package/lib/typescript/module/dataViewer/VirtualizedDataExplorer.d.ts.map +1 -1
  68. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  69. package/lib/typescript/module/icons/lucide-icons.d.ts +4 -2
  70. package/lib/typescript/module/icons/lucide-icons.d.ts.map +1 -1
  71. package/lib/typescript/module/index.d.ts +1 -1
  72. package/lib/typescript/module/index.d.ts.map +1 -1
  73. package/lib/typescript/module/license/DeviceLimitModal.d.ts.map +1 -1
  74. package/lib/typescript/module/license/LicenseEntryModal.d.ts.map +1 -1
  75. package/lib/typescript/module/license/ManageDevicesModal.d.ts.map +1 -1
  76. package/lib/typescript/module/stores/BaseEventStore.d.ts +28 -0
  77. package/lib/typescript/module/stores/BaseEventStore.d.ts.map +1 -1
  78. package/lib/typescript/module/ui/components/CompactRow.d.ts.map +1 -1
  79. package/lib/typescript/module/ui/components/EventHistoryViewer/EventPickerModal.d.ts.map +1 -1
  80. package/lib/typescript/module/ui/components/ExpandableSectionWithModal.d.ts.map +1 -1
  81. package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
  82. package/lib/typescript/module/ui/console/CyberpunkConsoleSection.d.ts.map +1 -1
  83. package/lib/typescript/module/ui/console/GalaxyButton.d.ts.map +1 -1
  84. package/lib/typescript/module/ui/gameUI/components/GameUIStatusHeader.d.ts.map +1 -1
  85. package/lib/typescript/module/utils/absoluteFill.d.ts +18 -0
  86. package/lib/typescript/module/utils/absoluteFill.d.ts.map +1 -0
  87. package/lib/typescript/module/utils/index.d.ts +1 -0
  88. package/lib/typescript/module/utils/index.d.ts.map +1 -1
  89. package/package.json +4 -4
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.JsModal = void 0;
7
7
  var _react = require("react");
8
8
  var _reactNative = require("react-native");
9
+ var _absoluteFill = require("./utils/absoluteFill.js");
9
10
  var _useSafeAreaInsets = require("./hooks/useSafeAreaInsets.js");
10
11
  var _index = require("./ui/gameUI/index.js");
11
12
  var _index2 = require("./ui/components/index.js");
@@ -1241,7 +1242,7 @@ const JsModalComponent = ({
1241
1242
  // ============================================================================
1242
1243
  const styles = _reactNative.StyleSheet.create({
1243
1244
  fullScreenContainer: {
1244
- ..._reactNative.StyleSheet.absoluteFillObject,
1245
+ ..._absoluteFill.absoluteFill,
1245
1246
  zIndex: 1000
1246
1247
  },
1247
1248
  bottomSheetWrapper: {
@@ -20,9 +20,17 @@ exports.isClipboardAvailable = exports.clipboardType = exports.clipboardFunction
20
20
  * Fallback chain:
21
21
  * 1. expo-clipboard
22
22
  * 2. @react-native-clipboard/clipboard
23
- * 3. Graceful failure
23
+ * 3. Web clipboard API (navigator.clipboard)
24
+ * 4. Graceful failure
24
25
  */
25
26
 
27
+ // navigator.clipboard isn't in React Native's TS lib — narrow it manually
28
+
29
+ function getWebClipboard() {
30
+ if (typeof navigator === "undefined") return null;
31
+ const clipboard = navigator.clipboard;
32
+ return clipboard && typeof clipboard.writeText === "function" ? clipboard : null;
33
+ }
26
34
  // Grab module references at load time (top-level try-catch for Metro)
27
35
  // Always require both — we decide which actually works at call time
28
36
  let _expoClipboard = null;
@@ -67,6 +75,21 @@ async function detect(text) {
67
75
  return true;
68
76
  } catch {/* rn-clipboard not functional */}
69
77
  }
78
+
79
+ // 3. Web fallback (react-native-web / desktop dashboard / browsers)
80
+ const webClipboard = getWebClipboard();
81
+ if (webClipboard) {
82
+ try {
83
+ await webClipboard.writeText(text);
84
+ _detectedType = "web";
85
+ _clipboardFn = async t => {
86
+ await webClipboard.writeText(t);
87
+ return true;
88
+ };
89
+ _detected = true;
90
+ return true;
91
+ } catch {/* clipboard permission denied */}
92
+ }
70
93
  _detected = true;
71
94
  return false;
72
95
  }
@@ -76,7 +99,10 @@ const clipboardType = () => {
76
99
  exports.clipboardType = clipboardType;
77
100
  const isClipboardAvailable = () => {
78
101
  // Before first use, optimistically return true if we have a module ref
79
- if (!_detected) return _expoClipboard != null || _rnClipboard != null;
102
+ // or the web clipboard API is present
103
+ if (!_detected) {
104
+ return _expoClipboard != null || _rnClipboard != null || getWebClipboard() != null;
105
+ }
80
106
  return _clipboardFn != null;
81
107
  };
82
108
  exports.isClipboardAvailable = isClipboardAvailable;
@@ -726,7 +726,6 @@ const useDataFlattening = (data, maxDepth = 10, autoExpandFirstLevel = false) =>
726
726
  const VirtualizedItemComponent = ({
727
727
  item,
728
728
  onToggleExpanded,
729
- data,
730
729
  index,
731
730
  onSelect,
732
731
  isSelected
@@ -790,9 +789,9 @@ const VirtualizedItemComponent = ({
790
789
  children: formatValue(item.value, item.valueType)
791
790
  })]
792
791
  })]
793
- }), item.id === "root" && data !== undefined && data !== null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CopyButton.CopyButton, {
794
- value: data,
795
- size: 16,
792
+ }), item.value !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CopyButton.CopyButton, {
793
+ value: item.value,
794
+ size: 14,
796
795
  buttonStyle: {
797
796
  marginLeft: 8,
798
797
  marginRight: 8
@@ -877,7 +876,6 @@ const VirtualizedDataExplorer = ({
877
876
  item: item,
878
877
  index: index,
879
878
  onToggleExpanded: toggleExpanded,
880
- data: data,
881
879
  onSelect: setSelectedIndex,
882
880
  isSelected: selectedIndex === index
883
881
  });
@@ -7,7 +7,7 @@ exports.useNativeSafeAreaInsets = exports.safeAreaType = exports.hasSafeAreaPack
7
7
  /**
8
8
  * Auto-generated safe area implementation
9
9
  * Detected: none
10
- * Generated at: 2026-05-28T20:48:12.491Z
10
+ * Generated at: 2026-06-23T21:16:34.896Z
11
11
  *
12
12
  * DO NOT EDIT - This file is generated by scripts/detect-safe-area.js
13
13
  *
@@ -3,8 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PlusIcon = exports.Plus = exports.PlayIcon = exports.Play = exports.PhoneIcon = exports.Phone = exports.PauseIcon = exports.Pause = exports.PaletteIcon = exports.Palette = exports.NavigationIcon = exports.Navigation = exports.MusicIcon = exports.Music = exports.MinusIcon = exports.Minus = exports.Maximize2Icon = exports.Maximize2 = exports.LockIcon = exports.Lock = exports.LinkIcon = exports.Link = exports.LayersIcon = exports.Layers = exports.KeyIcon = exports.Key = exports.InfoIcon = exports.Info = exports.ImageIcon = exports.Image = exports.HelpCircle = exports.HashIcon = exports.Hash = exports.HardDriveIcon = exports.HardDrive = exports.HandIcon = exports.Hand = exports.GlobeIcon = exports.Globe = exports.GitBranchIcon = exports.GitBranch = exports.FloatWindow = exports.FlaskConicalIcon = exports.FlaskConical = exports.FilterIcon = exports.Filter = exports.FilmIcon = exports.Film = exports.FileTextIcon = exports.FileText = exports.FileJsonIcon = exports.FileJson = exports.FileCodeIcon = exports.FileCode = exports.EyeOffIcon = exports.EyeOff = exports.EyeIcon = exports.Eye = exports.Edit3Icon = exports.Edit3 = exports.DownloadIcon = exports.Download = exports.DockBottom = exports.DatabaseIcon = exports.Database = exports.CopyIcon = exports.Copy = exports.CloudIcon = exports.Cloud = exports.ClockIcon = exports.Clock = exports.ChevronUpIcon = exports.ChevronUp = exports.ChevronRightIcon = exports.ChevronRight = exports.ChevronLeftIcon = exports.ChevronLeft = exports.ChevronDownIcon = exports.ChevronDown = exports.CheckSquareIcon = exports.CheckSquare = exports.CheckIcon = exports.CheckCircleIcon = exports.CheckCircle2Icon = exports.CheckCircle2 = exports.CheckCircle = exports.Check = exports.BugIcon = exports.Bug = exports.BoxIcon = exports.Box = exports.BarChart3Icon = exports.BarChart3 = exports.AlertTriangleIcon = exports.AlertTriangle = exports.AlertOctagon = exports.AlertCircleIcon = exports.AlertCircle = exports.ActivityIcon = exports.Activity = void 0;
7
- exports.ZapIcon = exports.Zap = exports.XIcon = exports.XCircleIcon = exports.XCircle = exports.X = exports.WifiIcon = exports.Wifi = exports.VolumeIcon = exports.Volume = exports.UsersIcon = exports.Users = exports.UserIcon = exports.User = exports.UploadIcon = exports.Upload = exports.UnlockIcon = exports.Unlock = exports.TriangleAlertIcon = exports.TriangleAlert = exports.TrashIcon = exports.Trash2Icon = exports.Trash2 = exports.Trash = exports.TouchpadIcon = exports.Touchpad = exports.TimerIcon = exports.Timer = exports.TestTube2Icon = exports.TestTube2 = exports.SquareIcon = exports.SquareDashedIcon = exports.SquareDashed = exports.Square = exports.SmartphoneIcon = exports.Smartphone = exports.ShieldIcon = exports.Shield = exports.SettingsIcon = exports.Settings = exports.ServerIcon = exports.Server = exports.SearchIcon = exports.Search = exports.RouteIcon = exports.Route = exports.RefreshCwIcon = exports.RefreshCw = exports.PowerIcon = exports.Power = void 0;
6
+ exports.PlayIcon = exports.Play = exports.PhoneIcon = exports.Phone = exports.PauseIcon = exports.Pause = exports.PaletteIcon = exports.Palette = exports.NavigationIcon = exports.Navigation = exports.MusicIcon = exports.Music = exports.MinusIcon = exports.Minus = exports.Maximize2Icon = exports.Maximize2 = exports.LockIcon = exports.Lock = exports.LinkIcon = exports.Link = exports.LayersIcon = exports.Layers = exports.KeyIcon = exports.Key = exports.InfoIcon = exports.Info = exports.ImageIcon = exports.Image = exports.HomeIcon = exports.Home = exports.HelpCircle = exports.HashIcon = exports.Hash = exports.HardDriveIcon = exports.HardDrive = exports.HandIcon = exports.Hand = exports.GlobeIcon = exports.Globe = exports.GitBranchIcon = exports.GitBranch = exports.FloatWindow = exports.FlaskConicalIcon = exports.FlaskConical = exports.FilterIcon = exports.Filter = exports.FilmIcon = exports.Film = exports.FileTextIcon = exports.FileText = exports.FileJsonIcon = exports.FileJson = exports.FileCodeIcon = exports.FileCode = exports.EyeOffIcon = exports.EyeOff = exports.EyeIcon = exports.Eye = exports.Edit3Icon = exports.Edit3 = exports.DownloadIcon = exports.Download = exports.DockBottom = exports.DatabaseIcon = exports.Database = exports.CopyIcon = exports.Copy = exports.CloudIcon = exports.Cloud = exports.ClockIcon = exports.Clock = exports.ChevronUpIcon = exports.ChevronUp = exports.ChevronRightIcon = exports.ChevronRight = exports.ChevronLeftIcon = exports.ChevronLeft = exports.ChevronDownIcon = exports.ChevronDown = exports.CheckSquareIcon = exports.CheckSquare = exports.CheckIcon = exports.CheckCircleIcon = exports.CheckCircle2Icon = exports.CheckCircle2 = exports.CheckCircle = exports.Check = exports.BugIcon = exports.Bug = exports.BoxIcon = exports.Box = exports.BarChart3Icon = exports.BarChart3 = exports.AlertTriangleIcon = exports.AlertTriangle = exports.AlertOctagon = exports.AlertCircleIcon = exports.AlertCircle = exports.ActivityIcon = exports.Activity = void 0;
7
+ exports.ZapIcon = exports.Zap = exports.XIcon = exports.XCircleIcon = exports.XCircle = exports.X = exports.WifiIcon = exports.Wifi = exports.VolumeIcon = exports.Volume = exports.UsersIcon = exports.Users = exports.UserIcon = exports.User = exports.UploadIcon = exports.Upload = exports.UnlockIcon = exports.Unlock = exports.TriangleAlertIcon = exports.TriangleAlert = exports.TrashIcon = exports.Trash2Icon = exports.Trash2 = exports.Trash = exports.TouchpadIcon = exports.Touchpad = exports.TimerIcon = exports.Timer = exports.TestTube2Icon = exports.TestTube2 = exports.SquareIcon = exports.SquareDashedIcon = exports.SquareDashed = exports.Square = exports.SmartphoneIcon = exports.Smartphone = exports.ShieldIcon = exports.Shield = exports.SettingsIcon = exports.Settings = exports.ServerIcon = exports.Server = exports.SearchIcon = exports.Search = exports.RouteIcon = exports.Route = exports.RefreshCwIcon = exports.RefreshCw = exports.PowerIcon = exports.Power = exports.PlusIcon = exports.Plus = void 0;
8
8
  var _reactNative = require("react-native");
9
9
  var OriginalIcons = _interopRequireWildcard(require("./lucide-icons-original-full.js"));
10
10
  var _jsxRuntime = require("react/jsx-runtime");
@@ -1398,8 +1398,67 @@ const Plus = ({
1398
1398
  strokeWidth: strokeWidth
1399
1399
  })]
1400
1400
  });
1401
+
1402
+ // Refresh / reload icon: a smooth 270° ring (open on the right) with a
1403
+ // clockwise triangle arrowhead. Built from the buoy icon-editor design
1404
+ // (smootharc ring + triangle) using the View-based border trick so it stays
1405
+ // crisp at any size. `strokeWidth` is accepted for API compatibility but the
1406
+ // proportions are fixed to keep the perfected look.
1401
1407
  exports.Plus = Plus;
1402
1408
  const RefreshCw = ({
1409
+ size = 24,
1410
+ color = "currentColor",
1411
+ strokeWidth: _strokeWidth = 2,
1412
+ ...props
1413
+ }) => {
1414
+ const RING_RADIUS = 7; // outer radius, centered in the 24x24 viewBox
1415
+ const RING_STROKE = 2.4;
1416
+ const ARROW_SIZE = 5.2;
1417
+ const ARROW_HALF = ARROW_SIZE * 0.577; // equilateral-ish half-width
1418
+ // Arrowhead anchor (from the editor design, mapped into the 0..24 viewBox)
1419
+ const arrowLeft = 12 + 3.162277660168379;
1420
+ const arrowTop = 12 - 2.846049894151541 - ARROW_HALF;
1421
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
1422
+ width: size,
1423
+ height: size,
1424
+ viewBox: "0 0 24 24",
1425
+ ...props,
1426
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1427
+ style: {
1428
+ position: "absolute",
1429
+ left: 12 - RING_RADIUS,
1430
+ top: 12 - RING_RADIUS,
1431
+ width: RING_RADIUS * 2,
1432
+ height: RING_RADIUS * 2,
1433
+ borderRadius: RING_RADIUS,
1434
+ borderWidth: RING_STROKE,
1435
+ borderTopColor: color,
1436
+ borderLeftColor: color,
1437
+ borderBottomColor: color,
1438
+ borderRightColor: "transparent"
1439
+ }
1440
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1441
+ style: {
1442
+ position: "absolute",
1443
+ left: arrowLeft,
1444
+ top: arrowTop,
1445
+ width: 0,
1446
+ height: 0,
1447
+ borderTopWidth: ARROW_HALF,
1448
+ borderBottomWidth: ARROW_HALF,
1449
+ borderLeftWidth: ARROW_SIZE,
1450
+ borderTopColor: "transparent",
1451
+ borderBottomColor: "transparent",
1452
+ borderLeftColor: color,
1453
+ transform: [{
1454
+ rotate: "45deg"
1455
+ }]
1456
+ }
1457
+ })]
1458
+ });
1459
+ };
1460
+ exports.RefreshCw = RefreshCw;
1461
+ const Home = ({
1403
1462
  size = 24,
1404
1463
  color = "currentColor",
1405
1464
  strokeWidth = 2,
@@ -1410,42 +1469,65 @@ const RefreshCw = ({
1410
1469
  viewBox: "0 0 24 24",
1411
1470
  ...props,
1412
1471
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1413
- x1: 23,
1414
- y1: 4,
1415
- x2: 23,
1416
- y2: 10,
1472
+ x1: 3,
1473
+ y1: 10,
1474
+ x2: 12,
1475
+ y2: 3,
1417
1476
  stroke: color,
1418
1477
  strokeWidth: strokeWidth
1419
1478
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1420
- x1: 23,
1421
- y1: 10,
1422
- x2: 17,
1479
+ x1: 12,
1480
+ y1: 3,
1481
+ x2: 21,
1423
1482
  y2: 10,
1424
1483
  stroke: color,
1425
1484
  strokeWidth: strokeWidth
1426
1485
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1427
- x1: 1,
1428
- y1: 20,
1429
- x2: 1,
1430
- y2: 14,
1486
+ x1: 5,
1487
+ y1: 9,
1488
+ x2: 5,
1489
+ y2: 21,
1431
1490
  stroke: color,
1432
1491
  strokeWidth: strokeWidth
1433
1492
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1434
- x1: 1,
1435
- y1: 14,
1436
- x2: 7,
1437
- y2: 14,
1493
+ x1: 19,
1494
+ y1: 9,
1495
+ x2: 19,
1496
+ y2: 21,
1438
1497
  stroke: color,
1439
1498
  strokeWidth: strokeWidth
1440
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Circle, {
1441
- cx: 12,
1442
- cy: 12,
1443
- r: 9,
1499
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1500
+ x1: 5,
1501
+ y1: 21,
1502
+ x2: 19,
1503
+ y2: 21,
1504
+ stroke: color,
1505
+ strokeWidth: strokeWidth
1506
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1507
+ x1: 10,
1508
+ y1: 21,
1509
+ x2: 10,
1510
+ y2: 15,
1511
+ stroke: color,
1512
+ strokeWidth: strokeWidth
1513
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1514
+ x1: 10,
1515
+ y1: 15,
1516
+ x2: 14,
1517
+ y2: 15,
1518
+ stroke: color,
1519
+ strokeWidth: strokeWidth
1520
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
1521
+ x1: 14,
1522
+ y1: 15,
1523
+ x2: 14,
1524
+ y2: 21,
1444
1525
  stroke: color,
1445
1526
  strokeWidth: strokeWidth
1446
1527
  })]
1447
1528
  });
1448
- exports.RefreshCw = RefreshCw;
1529
+ exports.Home = Home;
1530
+ const HomeIcon = exports.HomeIcon = Home;
1449
1531
  const Search = ({
1450
1532
  size = 24,
1451
1533
  color = "currentColor",
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  var _exportNames = {
7
+ absoluteFill: true,
7
8
  displayValue: true,
8
9
  parseDisplayValue: true,
9
10
  getSafeAreaInsets: true,
@@ -143,6 +144,12 @@ Object.defineProperty(exports, "UpgradePrompt", {
143
144
  return _index12.UpgradePrompt;
144
145
  }
145
146
  });
147
+ Object.defineProperty(exports, "absoluteFill", {
148
+ enumerable: true,
149
+ get: function () {
150
+ return _index3.absoluteFill;
151
+ }
152
+ });
146
153
  Object.defineProperty(exports, "buoyColors", {
147
154
  enumerable: true,
148
155
  get: function () {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.DeviceLimitModal = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
+ var _absoluteFill = require("../utils/absoluteFill.js");
9
10
  var _macOSDesignSystemColors = require("../ui/gameUI/constants/macOSDesignSystemColors.js");
10
11
  var _lucideIcons = require("../icons/lucide-icons.js");
11
12
  var _jsxRuntime = require("react/jsx-runtime");
@@ -272,7 +273,7 @@ const styles = _reactNative.StyleSheet.create({
272
273
  alignItems: "center"
273
274
  },
274
275
  backdrop: {
275
- ..._reactNative.StyleSheet.absoluteFillObject,
276
+ ..._absoluteFill.absoluteFill,
276
277
  backgroundColor: "rgba(0, 0, 0, 0.8)"
277
278
  },
278
279
  modal: {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.LicenseEntryModal = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
+ var _absoluteFill = require("../utils/absoluteFill.js");
9
10
  var _macOSDesignSystemColors = require("../ui/gameUI/constants/macOSDesignSystemColors.js");
10
11
  var _lucideIcons = require("../icons/lucide-icons.js");
11
12
  var _jsxRuntime = require("react/jsx-runtime");
@@ -199,7 +200,7 @@ const styles = _reactNative.StyleSheet.create({
199
200
  alignItems: "center"
200
201
  },
201
202
  backdrop: {
202
- ..._reactNative.StyleSheet.absoluteFillObject,
203
+ ..._absoluteFill.absoluteFill,
203
204
  backgroundColor: "rgba(0, 0, 0, 0.8)"
204
205
  },
205
206
  modal: {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ManageDevicesModal = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
+ var _absoluteFill = require("../utils/absoluteFill.js");
9
10
  var _gameUIColors = require("../ui/gameUI/constants/gameUIColors.js");
10
11
  var _lucideIcons = require("../icons/lucide-icons.js");
11
12
  var _jsxRuntime = require("react/jsx-runtime");
@@ -343,7 +344,7 @@ const styles = _reactNative.StyleSheet.create({
343
344
  alignItems: "center"
344
345
  },
345
346
  backdrop: {
346
- ..._reactNative.StyleSheet.absoluteFillObject,
347
+ ..._absoluteFill.absoluteFill,
347
348
  backgroundColor: "rgba(0, 0, 0, 0.7)"
348
349
  },
349
350
  modal: {
@@ -62,6 +62,8 @@ var _subscriberCountNotifier = require("../utils/subscriberCountNotifier.js");
62
62
  class BaseEventStore extends _subscribable.Subscribable {
63
63
  events = [];
64
64
  arrayListeners = new Set();
65
+ captureSuppressed = false;
66
+ clearListeners = new Set();
65
67
  constructor(options) {
66
68
  super();
67
69
  this.maxEvents = options.maxEvents ?? 500;
@@ -95,7 +97,7 @@ class BaseEventStore extends _subscribable.Subscribable {
95
97
  * Starts capturing if no one was subscribed.
96
98
  */
97
99
  onSubscribe() {
98
- if (this.getTotalSubscriberCount() === 1) {
100
+ if (this.getTotalSubscriberCount() === 1 && !this.captureSuppressed) {
99
101
  this.startCapturing();
100
102
  }
101
103
  (0, _subscriberCountNotifier.notifySubscriberCountChange)(this.storeName);
@@ -135,7 +137,7 @@ class BaseEventStore extends _subscribable.Subscribable {
135
137
  this.arrayListeners.add(listener);
136
138
 
137
139
  // Start capturing if this is the first subscriber
138
- if (wasEmpty) {
140
+ if (wasEmpty && !this.captureSuppressed) {
139
141
  this.startCapturing();
140
142
  }
141
143
 
@@ -226,6 +228,74 @@ class BaseEventStore extends _subscribable.Subscribable {
226
228
  clearEvents() {
227
229
  this.events = [];
228
230
  this.notifyArrayListeners();
231
+ this.clearListeners.forEach(listener => {
232
+ try {
233
+ listener();
234
+ } catch {
235
+ // Ignore listener errors
236
+ }
237
+ });
238
+ }
239
+
240
+ /**
241
+ * Listen for clearEvents() calls. Used in remote mirror mode to forward a
242
+ * clear performed in the dashboard UI to the synced device.
243
+ */
244
+ onClear(listener) {
245
+ this.clearListeners.add(listener);
246
+ return () => {
247
+ this.clearListeners.delete(listener);
248
+ };
249
+ }
250
+
251
+ // ===========================================================================
252
+ // REMOTE MIRROR MODE
253
+ // ===========================================================================
254
+
255
+ /**
256
+ * Suppress the auto start/stop capture lifecycle. Use when this store acts
257
+ * as a mirror of a remote device's events (e.g. the desktop dashboard):
258
+ * events arrive via replaceEvents() and the local interceptors must never
259
+ * start — on the dashboard they would capture the dashboard's own traffic.
260
+ */
261
+ disableCapture() {
262
+ this.captureSuppressed = true;
263
+ if (this.isCapturing()) {
264
+ this.stopCapturing();
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Replace the entire event list and notify array listeners. Used in remote
270
+ * mirror mode where full snapshots arrive from a synced device.
271
+ */
272
+ replaceEvents(events) {
273
+ this.events = this.dedupeById(events).slice(0, this.maxEvents);
274
+ this.notifyArrayListeners();
275
+ }
276
+
277
+ /**
278
+ * Drop events that share an `id` with an earlier event, keeping the first
279
+ * (newest, since events are newest-first) occurrence. Remote snapshots can
280
+ * momentarily carry duplicate ids — e.g. a device's request counter resets
281
+ * on reload while older events with the same id are still in the buffer —
282
+ * which makes React list keys (keyed on `id`) collide. Events without an
283
+ * `id` are passed through untouched.
284
+ */
285
+ dedupeById(events) {
286
+ const seen = new Set();
287
+ const result = [];
288
+ for (const event of events) {
289
+ const id = event?.id;
290
+ if (id == null) {
291
+ result.push(event);
292
+ continue;
293
+ }
294
+ if (seen.has(id)) continue;
295
+ seen.add(id);
296
+ result.push(event);
297
+ }
298
+ return result;
229
299
  }
230
300
 
231
301
  /**
@@ -28,77 +28,77 @@ function CompactRow({
28
28
  }) {
29
29
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
30
30
  style: styles.rowWrapper,
31
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
31
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
32
32
  style: [styles.row, isSelected && styles.selectedRow, isExpanded && [styles.expandedRowActive, {
33
33
  borderColor: expandedGlowColor || _gameUIColors.buoyColors.primary,
34
34
  shadowColor: expandedGlowColor || _gameUIColors.buoyColors.primary
35
35
  }]],
36
- onPress: onPress,
37
- activeOpacity: 0.8,
38
- disabled: disabled || !onPress,
39
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
40
- style: styles.rowContent,
41
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
42
- style: styles.statusSection,
43
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
44
- style: [styles.statusDot, {
45
- backgroundColor: statusDotColor
46
- }]
36
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
37
+ onPress: onPress,
38
+ activeOpacity: 0.8,
39
+ disabled: disabled || !onPress,
40
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
41
+ style: styles.rowContent,
42
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
43
+ style: styles.statusSection,
44
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
45
+ style: [styles.statusDot, {
46
+ backgroundColor: statusDotColor
47
+ }]
48
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
49
+ style: styles.statusInfo,
50
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
51
+ style: [styles.statusLabel, {
52
+ color: statusDotColor
53
+ }],
54
+ numberOfLines: 1,
55
+ children: statusLabel
56
+ }), statusSublabel ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
57
+ style: styles.observerText,
58
+ numberOfLines: 1,
59
+ children: statusSublabel
60
+ }) : null]
61
+ })]
47
62
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
48
- style: styles.statusInfo,
63
+ style: styles.querySection,
49
64
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
50
- style: [styles.statusLabel, {
51
- color: statusDotColor
52
- }],
53
- numberOfLines: 1,
54
- children: statusLabel
55
- }), statusSublabel && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
56
- style: styles.observerText,
65
+ style: styles.queryHash,
66
+ numberOfLines: isExpanded ? undefined : 2,
67
+ children: primaryText
68
+ }), !isExpanded && secondaryText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
69
+ style: styles.secondaryText,
57
70
  numberOfLines: 1,
58
- children: statusSublabel
71
+ children: secondaryText
72
+ }) : null]
73
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
74
+ style: styles.rightSection,
75
+ children: [(customBadge || badgeText !== undefined || !isExpanded && bottomRightText) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
76
+ style: styles.badgeContainer,
77
+ children: [customBadge ? customBadge : badgeText !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
78
+ style: [styles.statusBadge, {
79
+ color: badgeColor || statusDotColor
80
+ }],
81
+ children: badgeText
82
+ }) : null, !isExpanded && bottomRightText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
83
+ style: styles.bottomRightText,
84
+ numberOfLines: 1,
85
+ children: bottomRightText
86
+ }) : null]
87
+ }), showChevron && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
88
+ style: styles.chevronContainer,
89
+ children: isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.ChevronDown, {
90
+ size: 14,
91
+ color: _gameUIColors.buoyColors.textMuted
92
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.ChevronRight, {
93
+ size: 14,
94
+ color: _gameUIColors.buoyColors.textMuted
95
+ })
59
96
  })]
60
97
  })]
61
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
62
- style: styles.querySection,
63
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
64
- style: styles.queryHash,
65
- numberOfLines: isExpanded ? undefined : 2,
66
- children: primaryText
67
- }), !isExpanded && secondaryText && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
68
- style: styles.secondaryText,
69
- numberOfLines: 1,
70
- children: secondaryText
71
- })]
72
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
73
- style: styles.rightSection,
74
- children: [(customBadge || badgeText !== undefined) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
75
- style: styles.badgeContainer,
76
- children: customBadge ? customBadge : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
77
- style: [styles.statusBadge, {
78
- color: badgeColor || statusDotColor
79
- }],
80
- children: badgeText
81
- })
82
- }), showChevron && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
83
- style: styles.chevronContainer,
84
- children: isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.ChevronDown, {
85
- size: 14,
86
- color: _gameUIColors.buoyColors.textMuted
87
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.ChevronRight, {
88
- size: 14,
89
- color: _gameUIColors.buoyColors.textMuted
90
- })
91
- })]
92
- })]
98
+ })
93
99
  }), isExpanded && expandedContent && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
94
100
  style: styles.expandedContent,
95
101
  children: expandedContent
96
- }), !isExpanded && bottomRightText && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
97
- style: styles.bottomRightContainer,
98
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
99
- style: styles.bottomRightText,
100
- children: bottomRightText
101
- })
102
102
  })]
103
103
  })
104
104
  });
@@ -200,7 +200,9 @@ const styles = _reactNative.StyleSheet.create({
200
200
  gap: 8
201
201
  },
202
202
  badgeContainer: {
203
- alignItems: "flex-end"
203
+ flexDirection: "column",
204
+ alignItems: "flex-end",
205
+ gap: 2
204
206
  },
205
207
  statusBadge: {
206
208
  fontSize: 12,
@@ -217,11 +219,6 @@ const styles = _reactNative.StyleSheet.create({
217
219
  borderTopColor: _gameUIColors.buoyColors.border + "20",
218
220
  marginLeft: 24 // Align with content after status dot
219
221
  },
220
- bottomRightContainer: {
221
- position: "absolute",
222
- bottom: 4,
223
- right: 8
224
- },
225
222
  bottomRightText: {
226
223
  fontSize: 9,
227
224
  color: _gameUIColors.buoyColors.textMuted,
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.EventPickerModal = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
+ var _absoluteFill = require("../../../utils/absoluteFill.js");
9
10
  var _macOSDesignSystemColors = require("../../gameUI/constants/macOSDesignSystemColors.js");
10
11
  var _lucideIcons = require("../../../icons/lucide-icons.js");
11
12
  var _jsxRuntime = require("react/jsx-runtime");
@@ -82,13 +83,13 @@ const EventPickerModal = exports.EventPickerModal = /*#__PURE__*/(0, _react.memo
82
83
  });
83
84
  const styles = _reactNative.StyleSheet.create({
84
85
  overlay: {
85
- ..._reactNative.StyleSheet.absoluteFillObject,
86
+ ..._absoluteFill.absoluteFill,
86
87
  zIndex: 20,
87
88
  justifyContent: "center",
88
89
  alignItems: "center"
89
90
  },
90
91
  backdrop: {
91
- ..._reactNative.StyleSheet.absoluteFillObject,
92
+ ..._absoluteFill.absoluteFill,
92
93
  backgroundColor: "rgba(0,0,0,0.65)"
93
94
  },
94
95
  card: {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ExpandableSectionWithModal = ExpandableSectionWithModal;
7
7
  var _react = require("react");
8
8
  var _reactNative = require("react-native");
9
+ var _absoluteFill = require("../../utils/absoluteFill.js");
9
10
  var _useSafeAreaInsets = require("../../hooks/useSafeAreaInsets.js");
10
11
  var _index = require("../../icons/index.js");
11
12
  var _ExpandableSection = require("./ExpandableSection.js");
@@ -125,7 +126,7 @@ const styles = _reactNative.StyleSheet.create({
125
126
  flex: 1
126
127
  },
127
128
  backdrop: {
128
- ..._reactNative.StyleSheet.absoluteFillObject,
129
+ ..._absoluteFill.absoluteFill,
129
130
  backgroundColor: "rgba(0, 0, 0, 0.8)"
130
131
  },
131
132
  backdropTouchable: {