@noya-app/noya-multiplayer-react 0.1.62 → 0.1.64

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/dist/index.mjs CHANGED
@@ -42,10 +42,10 @@ var require_access = __commonJS({
42
42
  const accessed = _getPath(node, indexPath, options);
43
43
  return accessed[accessed.length - 1];
44
44
  }
45
- let path = indexPath.slice();
46
- while (path.length > 0) {
47
- let index = path.shift();
48
- const children = options.getChildren(node, path);
45
+ let path2 = indexPath.slice();
46
+ while (path2.length > 0) {
47
+ let index = path2.shift();
48
+ const children = options.getChildren(node, path2);
49
49
  const child = children[index];
50
50
  if (!child) {
51
51
  return void 0;
@@ -58,12 +58,12 @@ var require_access = __commonJS({
58
58
  return _getPath(node, indexPath, options).slice(0, -1);
59
59
  }
60
60
  function _getPath(node, indexPath, options) {
61
- let path = indexPath.slice();
61
+ let path2 = indexPath.slice();
62
62
  let result = [node];
63
- while (path.length > 0) {
64
- let index = path.shift();
63
+ while (path2.length > 0) {
64
+ let index = path2.shift();
65
65
  const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
66
- const children = options.getChildren(node, path, context);
66
+ const children = options.getChildren(node, path2, context);
67
67
  const child = children[index];
68
68
  if (!child) {
69
69
  return result;
@@ -78,20 +78,20 @@ var require_access = __commonJS({
78
78
  const accessed = accessPath(node, indexPath, options);
79
79
  return accessed[accessed.length - 1];
80
80
  }
81
- let path = indexPath.slice();
82
- while (path.length > 0) {
83
- let index = path.shift();
84
- node = options.getChildren(node, path)[index];
81
+ let path2 = indexPath.slice();
82
+ while (path2.length > 0) {
83
+ let index = path2.shift();
84
+ node = options.getChildren(node, path2)[index];
85
85
  }
86
86
  return node;
87
87
  }
88
88
  function accessPath(node, indexPath, options) {
89
- let path = indexPath.slice();
89
+ let path2 = indexPath.slice();
90
90
  let result = [node];
91
- while (path.length > 0) {
92
- let index = path.shift();
91
+ while (path2.length > 0) {
92
+ let index = path2.shift();
93
93
  const context = options.includeTraversalContext ? makeTraversalContext(result) : void 0;
94
- node = options.getChildren(node, path, context)[index];
94
+ node = options.getChildren(node, path2, context)[index];
95
95
  result.push(node);
96
96
  }
97
97
  return result;
@@ -605,40 +605,40 @@ var require_transformPath = __commonJS({
605
605
  Object.defineProperty(exports, "__esModule", { value: true });
606
606
  exports.transformPath = transformPath;
607
607
  var sort_1 = require_sort();
608
- function commonAncestor(path, otherPath) {
609
- const length = Math.min(path.length, otherPath.length);
608
+ function commonAncestor(path2, otherPath) {
609
+ const length = Math.min(path2.length, otherPath.length);
610
610
  for (let i = 0; i < length; i++) {
611
- if (path[i] !== otherPath[i]) {
612
- return path.slice(0, i);
611
+ if (path2[i] !== otherPath[i]) {
612
+ return path2.slice(0, i);
613
613
  }
614
614
  }
615
- return path.slice(0, length);
615
+ return path2.slice(0, length);
616
616
  }
617
- function transformPath(path, operation, otherPath, count = 1) {
618
- if (otherPath.length > path.length || (0, sort_1.comparePathsByComponent)(otherPath, path) > 0) {
619
- return path;
617
+ function transformPath(path2, operation, otherPath, count = 1) {
618
+ if (otherPath.length > path2.length || (0, sort_1.comparePathsByComponent)(otherPath, path2) > 0) {
619
+ return path2;
620
620
  }
621
621
  if (otherPath.length === 0 && operation === "remove") {
622
622
  return void 0;
623
623
  }
624
- const common = commonAncestor(path, otherPath);
625
- const adjustmentIndex = common.length === path.length || common.length === otherPath.length ? common.length - 1 : common.length;
626
- const pathValue = path[adjustmentIndex];
624
+ const common = commonAncestor(path2, otherPath);
625
+ const adjustmentIndex = common.length === path2.length || common.length === otherPath.length ? common.length - 1 : common.length;
626
+ const pathValue = path2[adjustmentIndex];
627
627
  const otherPathValue = otherPath[adjustmentIndex];
628
628
  if (operation === "insert" && otherPathValue <= pathValue) {
629
- const newPath = [...path];
629
+ const newPath = [...path2];
630
630
  newPath[adjustmentIndex] += count;
631
631
  return newPath;
632
632
  } else if (operation === "remove") {
633
633
  if (otherPathValue === pathValue) {
634
634
  return void 0;
635
635
  } else if (otherPathValue < pathValue) {
636
- const newPath = [...path];
636
+ const newPath = [...path2];
637
637
  newPath[adjustmentIndex] -= count;
638
638
  return newPath;
639
639
  }
640
640
  }
641
- return path;
641
+ return path2;
642
642
  }
643
643
  }
644
644
  });
@@ -804,15 +804,15 @@ var require_operation = __commonJS({
804
804
  switch (operation.type) {
805
805
  case "insert": {
806
806
  const otherPath = parentPath.concat(operation.index);
807
- return transformedPaths.map((path) => path ? (0, transformPath_1.transformPath)(path, "insert", otherPath, operation.nodes.length) : void 0);
807
+ return transformedPaths.map((path2) => path2 ? (0, transformPath_1.transformPath)(path2, "insert", otherPath, operation.nodes.length) : void 0);
808
808
  }
809
809
  case "remove": {
810
810
  const otherPaths = [...operation.indexes].reverse().map((index) => parentPath.concat(index));
811
- return transformedPaths.map((path) => {
811
+ return transformedPaths.map((path2) => {
812
812
  for (const otherPath of otherPaths) {
813
- path = path ? (0, transformPath_1.transformPath)(path, "remove", otherPath) : void 0;
813
+ path2 = path2 ? (0, transformPath_1.transformPath)(path2, "remove", otherPath) : void 0;
814
814
  }
815
- return path;
815
+ return path2;
816
816
  });
817
817
  }
818
818
  case "removeThenInsert": {
@@ -949,22 +949,22 @@ var require_splice = __commonJS({
949
949
  return _spliceWithPathTracking(node, options);
950
950
  }
951
951
  function _spliceWithPathTracking(node, options) {
952
- const { path, deleteCount = 0, nodes, track } = options;
953
- if (path.length === 0) {
952
+ const { path: path2, deleteCount = 0, nodes, track } = options;
953
+ if (path2.length === 0) {
954
954
  throw new Error(`Can't splice at the root`);
955
955
  }
956
- const pathsToRemove = getPathsToRemove(path, deleteCount);
957
- const operations = (0, operation_1.getInsertionOperations)(path, nodes, (0, operation_1.getRemovalOperations)(pathsToRemove));
956
+ const pathsToRemove = getPathsToRemove(path2, deleteCount);
957
+ const operations = (0, operation_1.getInsertionOperations)(path2, nodes, (0, operation_1.getRemovalOperations)(pathsToRemove));
958
958
  const transformedPaths = track ? (0, operation_1.transformPathsByOperations)(track, operations) : [];
959
959
  return {
960
960
  node: (0, operation_1.applyOperations)(node, operations, options),
961
961
  paths: transformedPaths
962
962
  };
963
963
  }
964
- function getPathsToRemove(path, deleteCount) {
964
+ function getPathsToRemove(path2, deleteCount) {
965
965
  let pathsToRemove = [];
966
- let parentPath = path.slice(0, -1);
967
- let index = path[path.length - 1];
966
+ let parentPath = path2.slice(0, -1);
967
+ let index = path2[path2.length - 1];
968
968
  for (let i = 0; i < deleteCount; i++) {
969
969
  pathsToRemove.push(parentPath.concat(index + i));
970
970
  }
@@ -978,7 +978,7 @@ var require_defineTree = __commonJS({
978
978
  "../../node_modules/tree-visit/lib/defineTree.js"(exports) {
979
979
  "use strict";
980
980
  Object.defineProperty(exports, "__esModule", { value: true });
981
- exports.defineTree = defineTree2;
981
+ exports.defineTree = defineTree3;
982
982
  var access_1 = require_access();
983
983
  var diagram_1 = require_diagram();
984
984
  var entries_1 = require_entries();
@@ -1027,7 +1027,7 @@ var require_defineTree = __commonJS({
1027
1027
  this._getChildren = this.baseOptions.getChildren;
1028
1028
  }
1029
1029
  };
1030
- function defineTree2(getChildren) {
1030
+ function defineTree3(getChildren) {
1031
1031
  return new Tree(getChildren, {});
1032
1032
  }
1033
1033
  }
@@ -1104,24 +1104,396 @@ var require_lib = __commonJS({
1104
1104
  }
1105
1105
  });
1106
1106
 
1107
+ // ../../node_modules/imfs/lib/types.js
1108
+ var require_types = __commonJS({
1109
+ "../../node_modules/imfs/lib/types.js"(exports) {
1110
+ "use strict";
1111
+ Object.defineProperty(exports, "__esModule", { value: true });
1112
+ }
1113
+ });
1114
+
1115
+ // ../../node_modules/imfs/lib/node.js
1116
+ var require_node = __commonJS({
1117
+ "../../node_modules/imfs/lib/node.js"(exports) {
1118
+ "use strict";
1119
+ Object.defineProperty(exports, "__esModule", { value: true });
1120
+ exports.Nodes = void 0;
1121
+ function createFile(data, metadata) {
1122
+ return { type: "file", data, metadata };
1123
+ }
1124
+ function createDirectory(children = {}, metadata) {
1125
+ return { type: "directory", children, metadata };
1126
+ }
1127
+ function isFile(node) {
1128
+ return node.type === "file";
1129
+ }
1130
+ function isDirectory(node) {
1131
+ return node.type === "directory";
1132
+ }
1133
+ function getMetadata(node) {
1134
+ return node.metadata;
1135
+ }
1136
+ function readDirectory(directory) {
1137
+ return Object.keys(directory.children);
1138
+ }
1139
+ function getChild(directory, name) {
1140
+ return directory.children[name];
1141
+ }
1142
+ function hasChild(directory, name) {
1143
+ return name in directory.children;
1144
+ }
1145
+ exports.Nodes = {
1146
+ createDirectory,
1147
+ createFile,
1148
+ getChild,
1149
+ getMetadata,
1150
+ hasChild,
1151
+ isDirectory,
1152
+ isFile,
1153
+ readDirectory
1154
+ };
1155
+ }
1156
+ });
1157
+
1158
+ // ../../node_modules/imfs/lib/path.js
1159
+ var require_path = __commonJS({
1160
+ "../../node_modules/imfs/lib/path.js"(exports) {
1161
+ "use strict";
1162
+ Object.defineProperty(exports, "__esModule", { value: true });
1163
+ exports.dirname = exports.basename = exports.extname = exports.join = exports.normalize = exports.sep = void 0;
1164
+ exports.sep = "/";
1165
+ function preserveLeadingAndTrailingSlash(original, updated) {
1166
+ if (original.startsWith("/")) {
1167
+ updated = "/" + updated;
1168
+ }
1169
+ if (updated[updated.length - 1] !== "/" && original.endsWith("/")) {
1170
+ updated = updated + "/";
1171
+ }
1172
+ return updated;
1173
+ }
1174
+ function normalize(filename) {
1175
+ const components = filename.split(exports.sep).filter((component) => !!component);
1176
+ let i = 0;
1177
+ let length = components.length - 1;
1178
+ while (i < length) {
1179
+ if (components[i] === ".") {
1180
+ components.splice(i, 1);
1181
+ length--;
1182
+ } else if (components[i] === ".." && i !== 0) {
1183
+ components.splice(i - 1, 2);
1184
+ length -= 2;
1185
+ i -= 1;
1186
+ } else if (components[i] === "" && components[i + 1] === "") {
1187
+ components.splice(i, 1);
1188
+ length--;
1189
+ } else {
1190
+ i++;
1191
+ }
1192
+ }
1193
+ return preserveLeadingAndTrailingSlash(filename, components.join(exports.sep));
1194
+ }
1195
+ exports.normalize = normalize;
1196
+ function join(...components) {
1197
+ let result = normalize(components.join(exports.sep));
1198
+ if (result === "") {
1199
+ result = ".";
1200
+ }
1201
+ return result;
1202
+ }
1203
+ exports.join = join;
1204
+ function extname(filename) {
1205
+ const index = filename.lastIndexOf(".");
1206
+ return index !== -1 ? filename.slice(index) : filename;
1207
+ }
1208
+ exports.extname = extname;
1209
+ function basename(filename, extname2) {
1210
+ if (extname2 && filename.endsWith(extname2)) {
1211
+ filename = filename.slice(0, -extname2.length);
1212
+ }
1213
+ let sepIndex = filename.lastIndexOf(exports.sep);
1214
+ if (sepIndex === filename.length - 1) {
1215
+ filename = filename.slice(0, -1);
1216
+ return filename.length > 1 ? basename(filename) : filename;
1217
+ }
1218
+ return filename.slice(sepIndex + 1);
1219
+ }
1220
+ exports.basename = basename;
1221
+ function dirname(filename) {
1222
+ let base = basename(filename);
1223
+ let result = filename.slice(0, -(base.length + 1));
1224
+ if (result === "") {
1225
+ if (filename.startsWith(exports.sep)) {
1226
+ result = exports.sep;
1227
+ } else {
1228
+ result = ".";
1229
+ }
1230
+ }
1231
+ return result;
1232
+ }
1233
+ exports.dirname = dirname;
1234
+ }
1235
+ });
1236
+
1237
+ // ../../node_modules/imfs/lib/entries.js
1238
+ var require_entries2 = __commonJS({
1239
+ "../../node_modules/imfs/lib/entries.js"(exports) {
1240
+ "use strict";
1241
+ Object.defineProperty(exports, "__esModule", { value: true });
1242
+ exports.Entries = void 0;
1243
+ var node_1 = require_node();
1244
+ var path_1 = require_path();
1245
+ function getEntries(entry) {
1246
+ const [pathname, node] = entry;
1247
+ return node_1.Nodes.isDirectory(node) ? Object.entries(node.children).map(([key, value]) => [
1248
+ (0, path_1.join)(pathname, key),
1249
+ value
1250
+ ]) : [];
1251
+ }
1252
+ function createEntry(pathname, node) {
1253
+ return [pathname, node];
1254
+ }
1255
+ exports.Entries = {
1256
+ createEntry,
1257
+ getEntries
1258
+ };
1259
+ }
1260
+ });
1261
+
1262
+ // ../../node_modules/imfs/lib/volume/paths.js
1263
+ var require_paths = __commonJS({
1264
+ "../../node_modules/imfs/lib/volume/paths.js"(exports) {
1265
+ "use strict";
1266
+ Object.defineProperty(exports, "__esModule", { value: true });
1267
+ exports.getNewAndParentName = exports.normalizePathLikeInternal = exports.getPathComponents = void 0;
1268
+ var path_1 = require_path();
1269
+ function getPathComponents(filepath) {
1270
+ return getPathComponentsNormalized((0, path_1.normalize)(filepath));
1271
+ function getPathComponentsNormalized(filepath2) {
1272
+ if (filepath2.startsWith("..")) {
1273
+ throw new Error(`Invalid path ${filepath2}, can't go up past root.`);
1274
+ }
1275
+ if (filepath2.startsWith(".") || filepath2.startsWith("/")) {
1276
+ return getPathComponentsNormalized(filepath2.slice(1));
1277
+ }
1278
+ if (filepath2 === "")
1279
+ return [];
1280
+ return filepath2.split(path_1.sep).filter((component) => !!component);
1281
+ }
1282
+ }
1283
+ exports.getPathComponents = getPathComponents;
1284
+ function normalizePathLikeInternal(pathlike) {
1285
+ return typeof pathlike === "string" ? getPathComponents(pathlike) : pathlike;
1286
+ }
1287
+ exports.normalizePathLikeInternal = normalizePathLikeInternal;
1288
+ function getNewAndParentName(pathlike) {
1289
+ const parentName = typeof pathlike === "string" ? (0, path_1.dirname)(pathlike) : pathlike.slice(0, -1);
1290
+ const newName = typeof pathlike === "string" ? (0, path_1.basename)(pathlike) : pathlike[pathlike.length - 1];
1291
+ return { parentName, newName };
1292
+ }
1293
+ exports.getNewAndParentName = getNewAndParentName;
1294
+ }
1295
+ });
1296
+
1297
+ // ../../node_modules/imfs/lib/volume/read.js
1298
+ var require_read = __commonJS({
1299
+ "../../node_modules/imfs/lib/volume/read.js"(exports) {
1300
+ "use strict";
1301
+ Object.defineProperty(exports, "__esModule", { value: true });
1302
+ exports.getMetadata = exports.readDirectory = exports.readFile = exports.getNode = exports.getNodeInternal = void 0;
1303
+ var node_1 = require_node();
1304
+ var path_1 = require_path();
1305
+ var paths_1 = require_paths();
1306
+ function getNodeInternal(root, pathlike, options) {
1307
+ const components = (0, paths_1.normalizePathLikeInternal)(pathlike);
1308
+ let i = 0;
1309
+ let current = root;
1310
+ while (i < components.length) {
1311
+ let component = components[i];
1312
+ if (current.type !== "directory") {
1313
+ throw new Error(`File ${(0, path_1.join)(...components.slice(0, i))} is not a directory`);
1314
+ }
1315
+ let node = node_1.Nodes.getChild(current, component);
1316
+ if (!node) {
1317
+ if (options.makeIntermediateDirectoryMetadata) {
1318
+ const child = node_1.Nodes.createDirectory({}, options.makeIntermediateDirectoryMetadata((0, path_1.join)(...components.slice(0, i + 1))));
1319
+ current.children[component] = child;
1320
+ node = child;
1321
+ } else if (options.makeIntermediateDirectories) {
1322
+ const child = node_1.Nodes.createDirectory();
1323
+ current.children[component] = child;
1324
+ node = child;
1325
+ } else {
1326
+ throw new Error(`File ${(0, path_1.join)(...components.slice(0, i + 1))} not found`);
1327
+ }
1328
+ }
1329
+ current = node;
1330
+ i++;
1331
+ }
1332
+ return current;
1333
+ }
1334
+ exports.getNodeInternal = getNodeInternal;
1335
+ function getNode(root, pathlike) {
1336
+ return getNodeInternal(root, pathlike, {});
1337
+ }
1338
+ exports.getNode = getNode;
1339
+ function readFile(root, pathlike) {
1340
+ const components = (0, paths_1.normalizePathLikeInternal)(pathlike);
1341
+ const node = getNode(root, components);
1342
+ if (!node_1.Nodes.isFile(node)) {
1343
+ throw new Error(`Can't read, ${(0, path_1.join)(...components)} not a file`);
1344
+ }
1345
+ return node.data;
1346
+ }
1347
+ exports.readFile = readFile;
1348
+ function readDirectory(root, pathlike) {
1349
+ const components = (0, paths_1.normalizePathLikeInternal)(pathlike);
1350
+ const node = getNode(root, components);
1351
+ if (!node_1.Nodes.isDirectory(node)) {
1352
+ throw new Error(`Can't read, ${(0, path_1.join)(...components)} not a directory`);
1353
+ }
1354
+ return node_1.Nodes.readDirectory(node);
1355
+ }
1356
+ exports.readDirectory = readDirectory;
1357
+ function getMetadata(root, pathlike) {
1358
+ const components = (0, paths_1.normalizePathLikeInternal)(pathlike);
1359
+ const node = getNode(root, components);
1360
+ return node.metadata;
1361
+ }
1362
+ exports.getMetadata = getMetadata;
1363
+ }
1364
+ });
1365
+
1366
+ // ../../node_modules/imfs/lib/volume/write.js
1367
+ var require_write = __commonJS({
1368
+ "../../node_modules/imfs/lib/volume/write.js"(exports) {
1369
+ "use strict";
1370
+ Object.defineProperty(exports, "__esModule", { value: true });
1371
+ exports.create = exports.setMetadata = exports.removeFile = exports.makeDirectory = exports.writeFile = exports.setNode = void 0;
1372
+ var node_1 = require_node();
1373
+ var paths_1 = require_paths();
1374
+ var read_1 = require_read();
1375
+ function setNode(root, pathlike, node, options) {
1376
+ const { parentName, newName } = (0, paths_1.getNewAndParentName)(pathlike);
1377
+ const parent = (0, read_1.getNodeInternal)(root, parentName, options !== null && options !== void 0 ? options : {});
1378
+ if (!node_1.Nodes.isDirectory(parent)) {
1379
+ throw new Error(`Can't create ${newName}, ${parentName} not a directory`);
1380
+ }
1381
+ parent.children[newName] = node;
1382
+ }
1383
+ exports.setNode = setNode;
1384
+ function writeFile(root, pathlike, data, options) {
1385
+ var _a;
1386
+ setNode(root, pathlike, node_1.Nodes.createFile(data, (_a = options) === null || _a === void 0 ? void 0 : _a.metadata), options);
1387
+ }
1388
+ exports.writeFile = writeFile;
1389
+ function makeDirectory(root, pathlike, options) {
1390
+ var _a;
1391
+ const { parentName, newName } = (0, paths_1.getNewAndParentName)(pathlike);
1392
+ const parent = (0, read_1.getNodeInternal)(root, parentName, options !== null && options !== void 0 ? options : {});
1393
+ if (!node_1.Nodes.isDirectory(parent)) {
1394
+ throw new Error(`Can't create ${newName}, ${parentName} not a directory`);
1395
+ }
1396
+ const existing = node_1.Nodes.getChild(parent, newName);
1397
+ if (existing && node_1.Nodes.isDirectory(parent.children[newName])) {
1398
+ return;
1399
+ }
1400
+ parent.children[newName] = node_1.Nodes.createDirectory({}, (_a = options) === null || _a === void 0 ? void 0 : _a.metadata);
1401
+ }
1402
+ exports.makeDirectory = makeDirectory;
1403
+ function removeFile(root, pathlike) {
1404
+ const { parentName, newName } = (0, paths_1.getNewAndParentName)(pathlike);
1405
+ const parent = (0, read_1.getNode)(root, parentName);
1406
+ if (!node_1.Nodes.isDirectory(parent)) {
1407
+ throw new Error(`Can't remove file ${newName}, ${parentName} not a directory`);
1408
+ }
1409
+ delete parent.children[newName];
1410
+ }
1411
+ exports.removeFile = removeFile;
1412
+ function setMetadata(root, pathlike, metadata) {
1413
+ const node = (0, read_1.getNode)(root, pathlike);
1414
+ node.metadata = metadata;
1415
+ }
1416
+ exports.setMetadata = setMetadata;
1417
+ function create(options) {
1418
+ return node_1.Nodes.createDirectory({}, options && "metadata" in options ? options.metadata : void 0);
1419
+ }
1420
+ exports.create = create;
1421
+ }
1422
+ });
1423
+
1424
+ // ../../node_modules/imfs/lib/volume.js
1425
+ var require_volume = __commonJS({
1426
+ "../../node_modules/imfs/lib/volume.js"(exports) {
1427
+ "use strict";
1428
+ Object.defineProperty(exports, "__esModule", { value: true });
1429
+ exports.Volume = void 0;
1430
+ var paths_1 = require_paths();
1431
+ var read_1 = require_read();
1432
+ var write_1 = require_write();
1433
+ exports.Volume = {
1434
+ // paths
1435
+ getPathComponents: paths_1.getPathComponents,
1436
+ // read
1437
+ getMetadata: read_1.getMetadata,
1438
+ getNode: read_1.getNode,
1439
+ readDirectory: read_1.readDirectory,
1440
+ readFile: read_1.readFile,
1441
+ // write
1442
+ create: write_1.create,
1443
+ makeDirectory: write_1.makeDirectory,
1444
+ removeFile: write_1.removeFile,
1445
+ setMetadata: write_1.setMetadata,
1446
+ setNode: write_1.setNode,
1447
+ writeFile: write_1.writeFile
1448
+ };
1449
+ }
1450
+ });
1451
+
1452
+ // ../../node_modules/imfs/lib/index.js
1453
+ var require_lib2 = __commonJS({
1454
+ "../../node_modules/imfs/lib/index.js"(exports) {
1455
+ "use strict";
1456
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
1457
+ if (k2 === void 0) k2 = k;
1458
+ Object.defineProperty(o, k2, { enumerable: true, get: function() {
1459
+ return m[k];
1460
+ } });
1461
+ } : function(o, m, k, k2) {
1462
+ if (k2 === void 0) k2 = k;
1463
+ o[k2] = m[k];
1464
+ });
1465
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
1466
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1467
+ } : function(o, v) {
1468
+ o["default"] = v;
1469
+ });
1470
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
1471
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
1472
+ };
1473
+ var __importStar = exports && exports.__importStar || function(mod) {
1474
+ if (mod && mod.__esModule) return mod;
1475
+ var result = {};
1476
+ if (mod != null) {
1477
+ for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
1478
+ }
1479
+ __setModuleDefault(result, mod);
1480
+ return result;
1481
+ };
1482
+ Object.defineProperty(exports, "__esModule", { value: true });
1483
+ exports.path = void 0;
1484
+ __exportStar(require_types(), exports);
1485
+ __exportStar(require_node(), exports);
1486
+ __exportStar(require_entries2(), exports);
1487
+ __exportStar(require_volume(), exports);
1488
+ exports.path = __importStar(require_path());
1489
+ }
1490
+ });
1491
+
1107
1492
  // src/index.ts
1108
1493
  export * from "@noya-app/state-manager";
1109
1494
 
1110
1495
  // src/ai.ts
1111
- import { useEffect as useEffect4 } from "react";
1112
-
1113
- // src/NoyaStateContext.tsx
1114
- import {
1115
- Observable
1116
- } from "@noya-app/observable";
1117
- import { useStableCallback } from "@noya-app/react-utils";
1118
- import React5, {
1119
- createContext,
1120
- useCallback as useCallback2,
1121
- useContext,
1122
- useEffect as useEffect3,
1123
- useMemo as useMemo4
1124
- } from "react";
1496
+ import { useEffect as useEffect5 } from "react";
1125
1497
 
1126
1498
  // ../../node_modules/@sinclair/typebox/build/esm/type/symbols/symbols.mjs
1127
1499
  var TransformKind = Symbol.for("TypeBox.Transform");
@@ -1678,14 +2050,14 @@ function Number2(options = {}) {
1678
2050
  }
1679
2051
 
1680
2052
  // ../../node_modules/@sinclair/typebox/build/esm/type/string/string.mjs
1681
- function String(options = {}) {
2053
+ function String2(options = {}) {
1682
2054
  return { ...options, [Kind]: "String", type: "string" };
1683
2055
  }
1684
2056
 
1685
2057
  // ../../node_modules/@sinclair/typebox/build/esm/type/template-literal/syntax.mjs
1686
2058
  function* FromUnion(syntax) {
1687
2059
  const trim = syntax.trim().replace(/"|'/g, "");
1688
- return trim === "boolean" ? yield Boolean() : trim === "number" ? yield Number2() : trim === "bigint" ? yield BigInt2() : trim === "string" ? yield String() : yield (() => {
2060
+ return trim === "boolean" ? yield Boolean() : trim === "number" ? yield Number2() : trim === "bigint" ? yield BigInt2() : trim === "string" ? yield String2() : yield (() => {
1689
2061
  const literals = trim.split("|").map((literal) => Literal(literal.trim()));
1690
2062
  return literals.length === 0 ? Never() : literals.length === 1 ? literals[0] : UnionEvaluated(literals);
1691
2063
  })();
@@ -2774,7 +3146,7 @@ function FromPromise3(left, right) {
2774
3146
  return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) && IsObjectPromiseLike(right) ? ExtendsResult.True : !type_exports.IsPromise(right) ? ExtendsResult.False : IntoBooleanResult(Visit3(left.item, right.item));
2775
3147
  }
2776
3148
  function RecordKey(schema) {
2777
- return PatternNumberExact in schema.patternProperties ? Number2() : PatternStringExact in schema.patternProperties ? String() : Throw("Unknown record key pattern");
3149
+ return PatternNumberExact in schema.patternProperties ? Number2() : PatternStringExact in schema.patternProperties ? String2() : Throw("Unknown record key pattern");
2778
3150
  }
2779
3151
  function RecordValue(schema) {
2780
3152
  return PatternNumberExact in schema.patternProperties ? schema.patternProperties[PatternNumberExact] : PatternStringExact in schema.patternProperties ? schema.patternProperties[PatternStringExact] : Throw("Unable to get record value schema");
@@ -2794,8 +3166,8 @@ function FromRecord(left, right) {
2794
3166
  return IsStructuralRight(right) ? StructuralRight(left, right) : type_exports.IsObject(right) ? FromObjectRight(left, right) : !type_exports.IsRecord(right) ? ExtendsResult.False : Visit3(RecordValue(left), RecordValue(right));
2795
3167
  }
2796
3168
  function FromRegExp(left, right) {
2797
- const L = type_exports.IsRegExp(left) ? String() : left;
2798
- const R = type_exports.IsRegExp(right) ? String() : right;
3169
+ const L = type_exports.IsRegExp(left) ? String2() : left;
3170
+ const R = type_exports.IsRegExp(right) ? String2() : right;
2799
3171
  return Visit3(L, R);
2800
3172
  }
2801
3173
  function FromStringRight(left, right) {
@@ -3431,30 +3803,30 @@ var TransformDecodeBuilder = class {
3431
3803
  constructor(schema) {
3432
3804
  this.schema = schema;
3433
3805
  }
3434
- Decode(decode) {
3435
- return new TransformEncodeBuilder(this.schema, decode);
3806
+ Decode(decode2) {
3807
+ return new TransformEncodeBuilder(this.schema, decode2);
3436
3808
  }
3437
3809
  };
3438
3810
  var TransformEncodeBuilder = class {
3439
3811
  schema;
3440
3812
  decode;
3441
- constructor(schema, decode) {
3813
+ constructor(schema, decode2) {
3442
3814
  this.schema = schema;
3443
- this.decode = decode;
3815
+ this.decode = decode2;
3444
3816
  }
3445
- EncodeTransform(encode, schema) {
3446
- const Encode = (value) => schema[TransformKind].Encode(encode(value));
3817
+ EncodeTransform(encode2, schema) {
3818
+ const Encode = (value) => schema[TransformKind].Encode(encode2(value));
3447
3819
  const Decode = (value) => this.decode(schema[TransformKind].Decode(value));
3448
3820
  const Codec = { Encode, Decode };
3449
3821
  return { ...schema, [TransformKind]: Codec };
3450
3822
  }
3451
- EncodeSchema(encode, schema) {
3452
- const Codec = { Decode: this.decode, Encode: encode };
3823
+ EncodeSchema(encode2, schema) {
3824
+ const Codec = { Decode: this.decode, Encode: encode2 };
3453
3825
  return { ...schema, [TransformKind]: Codec };
3454
3826
  }
3455
- Encode(encode) {
3827
+ Encode(encode2) {
3456
3828
  const schema = CloneType(this.schema);
3457
- return IsTransform(schema) ? this.EncodeTransform(encode, schema) : this.EncodeSchema(encode, schema);
3829
+ return IsTransform(schema) ? this.EncodeTransform(encode2, schema) : this.EncodeSchema(encode2, schema);
3458
3830
  }
3459
3831
  };
3460
3832
  function Transform(schema) {
@@ -3520,7 +3892,7 @@ __export(type_exports3, {
3520
3892
  Rest: () => Rest,
3521
3893
  ReturnType: () => ReturnType,
3522
3894
  Strict: () => Strict,
3523
- String: () => String,
3895
+ String: () => String2,
3524
3896
  Symbol: () => Symbol2,
3525
3897
  TemplateLiteral: () => TemplateLiteral,
3526
3898
  Transform: () => Transform,
@@ -3547,6 +3919,134 @@ function Void(options = {}) {
3547
3919
  // ../../node_modules/@sinclair/typebox/build/esm/type/type/index.mjs
3548
3920
  var Type = type_exports3;
3549
3921
 
3922
+ // ../noya-schemas/src/nullable.ts
3923
+ var Nullable = (schema) => Type.Union([Type.Null(), schema]);
3924
+
3925
+ // ../noya-schemas/src/activityEventSchema.ts
3926
+ var userSelectSchema = Type.Object({
3927
+ id: Type.String(),
3928
+ name: Nullable(Type.String()),
3929
+ email: Nullable(Type.String()),
3930
+ image: Nullable(Type.String())
3931
+ });
3932
+ var workspaceSelectSchema = Type.Object({
3933
+ id: Type.String(),
3934
+ name: Type.String()
3935
+ });
3936
+ var fileSelectSchema = Type.Object({
3937
+ id: Type.String(),
3938
+ name: Nullable(Type.String())
3939
+ });
3940
+ var resourceSelectSchema = Type.Object({
3941
+ id: Type.String(),
3942
+ path: Type.String(),
3943
+ type: Type.Union([
3944
+ Type.Literal("asset"),
3945
+ Type.Literal("file"),
3946
+ Type.Literal("fileVersion"),
3947
+ Type.Literal("directory"),
3948
+ Type.Literal("resource")
3949
+ ])
3950
+ });
3951
+ var siteSelectSchema = Type.Object({
3952
+ id: Type.String(),
3953
+ subdomain: Nullable(Type.String())
3954
+ });
3955
+ var activityEventSchema = Type.Object({
3956
+ id: Type.String(),
3957
+ createdAt: Type.String(),
3958
+ actorId: Nullable(Type.String()),
3959
+ actor: Type.Optional(userSelectSchema),
3960
+ type: Type.Union([
3961
+ Type.Literal("file"),
3962
+ Type.Literal("resource"),
3963
+ Type.Literal("site"),
3964
+ Type.Literal("snapshot"),
3965
+ Type.Literal("restore")
3966
+ ]),
3967
+ workspaceId: Nullable(Type.String()),
3968
+ workspace: Type.Optional(workspaceSelectSchema),
3969
+ fileId: Nullable(Type.String()),
3970
+ file: Type.Optional(fileSelectSchema),
3971
+ fileVersionId: Nullable(Type.String()),
3972
+ resourceId: Nullable(Type.String()),
3973
+ resource: Type.Optional(resourceSelectSchema),
3974
+ siteId: Nullable(Type.String()),
3975
+ site: Type.Optional(siteSelectSchema),
3976
+ previousData: Nullable(Type.Any()),
3977
+ currentData: Nullable(Type.Any()),
3978
+ metadata: Nullable(Type.Any()),
3979
+ userAgent: Nullable(Type.String())
3980
+ });
3981
+
3982
+ // ../noya-schemas/src/asset.ts
3983
+ var assetSchema = Type.Object({
3984
+ id: Type.String(),
3985
+ url: Type.String(),
3986
+ createdAt: Type.String(),
3987
+ size: Type.Number(),
3988
+ contentType: Type.Optional(Type.String()),
3989
+ width: Type.Union([Type.Null(), Type.Number()]),
3990
+ height: Type.Union([Type.Null(), Type.Number()]),
3991
+ userId: Type.Union([Type.Null(), Type.String()])
3992
+ });
3993
+
3994
+ // ../noya-schemas/src/encode.ts
3995
+ var SchemaMap = /* @__PURE__ */ new Map([
3996
+ [Kind, "_kind"],
3997
+ [Hint, "_hint"]
3998
+ ]);
3999
+ var InverseSchemaMap = new Map(
4000
+ Array.from(SchemaMap.entries()).map(([key, value]) => [value, key])
4001
+ );
4002
+ function encodeSchema(obj, symMap = SchemaMap) {
4003
+ function replaceSymbols(item) {
4004
+ if (Array.isArray(item)) {
4005
+ return item.map(replaceSymbols);
4006
+ } else if (typeof item === "object" && item !== null) {
4007
+ const newObj = {};
4008
+ for (const key in item) {
4009
+ if (Object.prototype.hasOwnProperty.call(item, key)) {
4010
+ const value = item[key];
4011
+ newObj[key] = replaceSymbols(value);
4012
+ }
4013
+ }
4014
+ for (const sym of Object.getOwnPropertySymbols(item)) {
4015
+ const stringKey = symMap.get(sym);
4016
+ if (stringKey) {
4017
+ newObj[stringKey] = replaceSymbols(item[sym]);
4018
+ }
4019
+ }
4020
+ return newObj;
4021
+ }
4022
+ return item;
4023
+ }
4024
+ return replaceSymbols(obj);
4025
+ }
4026
+ function decodeSchema(obj, strMap = InverseSchemaMap) {
4027
+ function replaceStringKeys(item) {
4028
+ if (Array.isArray(item)) {
4029
+ return item.map(replaceStringKeys);
4030
+ } else if (typeof item === "object" && item !== null) {
4031
+ const newObj = {};
4032
+ for (const key in item) {
4033
+ if (Object.prototype.hasOwnProperty.call(item, key)) {
4034
+ const value = item[key];
4035
+ const symbolKey = strMap.get(key);
4036
+ if (symbolKey) {
4037
+ newObj[symbolKey] = replaceStringKeys(value);
4038
+ } else {
4039
+ newObj[key] = replaceStringKeys(value);
4040
+ }
4041
+ }
4042
+ }
4043
+ return newObj;
4044
+ }
4045
+ return item;
4046
+ }
4047
+ return replaceStringKeys(obj);
4048
+ }
4049
+
3550
4050
  // ../noya-schemas/src/filesSchema.ts
3551
4051
  var encodingSchema = Type.Union([
3552
4052
  Type.Literal("utf-8"),
@@ -3567,8 +4067,13 @@ var fileSchema = Type.Object({
3567
4067
  content: Type.String(),
3568
4068
  encoding: encodingSchema
3569
4069
  });
4070
+ var noyaFileSchema = Type.Object({
4071
+ id: Type.String({ format: "uuid", default: "" }),
4072
+ kind: Type.Literal("noyaFile"),
4073
+ fileId: Type.String()
4074
+ });
3570
4075
  var mediaItemSchema = Type.Union(
3571
- [folderMediaItemSchema, assetMediaItemSchema, fileSchema],
4076
+ [folderMediaItemSchema, assetMediaItemSchema, fileSchema, noyaFileSchema],
3572
4077
  {
3573
4078
  discriminator: "kind"
3574
4079
  }
@@ -3637,25 +4142,25 @@ var jsonSchema = Type.Recursive(
3637
4142
  );
3638
4143
 
3639
4144
  // ../noya-schemas/src/input.ts
3640
- function Nullable(type) {
4145
+ function Nullable2(type) {
3641
4146
  return Type.Union([type, Type.Null()], { default: null });
3642
4147
  }
3643
4148
  var inputSchemaBase = {
3644
4149
  id: Type.String({ format: "uuid", default: "" }),
3645
4150
  stableId: Type.String({ format: "uuid", default: "" }),
3646
4151
  name: Type.String(),
3647
- description: Nullable(Type.String()),
4152
+ description: Nullable2(Type.String()),
3648
4153
  required: Type.Boolean({ default: false })
3649
4154
  };
3650
4155
  var fileInputSchema = Type.Object({
3651
4156
  ...inputSchemaBase,
3652
4157
  kind: Type.Literal("file"),
3653
- toolId: Nullable(Type.String())
4158
+ toolId: Nullable2(Type.String())
3654
4159
  });
3655
4160
  var dataInputSchema = Type.Object({
3656
4161
  ...inputSchemaBase,
3657
4162
  kind: Type.Literal("data"),
3658
- schema: Nullable(jsonSchema)
4163
+ schema: Nullable2(jsonSchema)
3659
4164
  });
3660
4165
  var secretInputSchema = Type.Object({
3661
4166
  ...inputSchemaBase,
@@ -3665,7 +4170,7 @@ var secretInputSchema = Type.Object({
3665
4170
  default: null
3666
4171
  })
3667
4172
  ),
3668
- authScope: Type.Optional(Nullable(Type.String()))
4173
+ authScope: Type.Optional(Nullable2(Type.String()))
3669
4174
  });
3670
4175
  var inputSchema = Type.Union(
3671
4176
  [fileInputSchema, dataInputSchema, secretInputSchema],
@@ -3862,17 +4367,17 @@ var ValueErrorType;
3862
4367
  // ../../node_modules/@sinclair/typebox/build/esm/value/delta/delta.mjs
3863
4368
  var Insert = Object2({
3864
4369
  type: Literal("insert"),
3865
- path: String(),
4370
+ path: String2(),
3866
4371
  value: Unknown()
3867
4372
  });
3868
4373
  var Update = Object2({
3869
4374
  type: Literal("update"),
3870
- path: String(),
4375
+ path: String2(),
3871
4376
  value: Unknown()
3872
4377
  });
3873
4378
  var Delete3 = Object2({
3874
4379
  type: Literal("delete"),
3875
- path: String()
4380
+ path: String2()
3876
4381
  });
3877
4382
  var Edit = Union([Insert, Update, Delete3]);
3878
4383
 
@@ -3899,6 +4404,142 @@ function findAllDefs(schema) {
3899
4404
  });
3900
4405
  }
3901
4406
 
4407
+ // ../noya-schemas/src/resourceSchema.ts
4408
+ var baseSchemaProperties = {
4409
+ id: Type.String(),
4410
+ stableId: Type.String(),
4411
+ path: Type.String(),
4412
+ createdAt: Type.String(),
4413
+ updatedAt: Type.String(),
4414
+ accessibleByFileId: Nullable(Type.String()),
4415
+ accessibleByFile: Type.Optional(
4416
+ Type.Object({
4417
+ id: Type.String(),
4418
+ name: Type.String(),
4419
+ toolId: Type.String()
4420
+ })
4421
+ ),
4422
+ accessibleByFileVersionId: Nullable(Type.String()),
4423
+ url: Type.Optional(Type.String())
4424
+ };
4425
+ var uploadableAssetSchema = Type.Object({
4426
+ content: Type.String(),
4427
+ contentType: Type.String(),
4428
+ encoding: Type.Union([Type.Literal("utf-8"), Type.Literal("base64")])
4429
+ });
4430
+ var assetResourceSchema = Type.Object({
4431
+ ...baseSchemaProperties,
4432
+ type: Type.Literal("asset"),
4433
+ assetId: Type.String()
4434
+ });
4435
+ var assetResourceCreateSchema = Type.Object({
4436
+ ...baseSchemaProperties,
4437
+ type: Type.Literal("asset"),
4438
+ assetId: Type.Optional(Type.String()),
4439
+ asset: Type.Optional(uploadableAssetSchema)
4440
+ });
4441
+ var fileResourceSchema = Type.Object({
4442
+ ...baseSchemaProperties,
4443
+ type: Type.Literal("file"),
4444
+ fileId: Type.String()
4445
+ });
4446
+ var directoryResourceSchema = Type.Object({
4447
+ ...baseSchemaProperties,
4448
+ type: Type.Literal("directory")
4449
+ });
4450
+ var nestedResourceSchema = Type.Object({
4451
+ ...baseSchemaProperties,
4452
+ type: Type.Literal("resource"),
4453
+ fileId: Type.String(),
4454
+ resourceId: Type.String()
4455
+ });
4456
+ var resourceSchema = Type.Union(
4457
+ [
4458
+ assetResourceSchema,
4459
+ fileResourceSchema,
4460
+ directoryResourceSchema,
4461
+ nestedResourceSchema
4462
+ ],
4463
+ {
4464
+ discriminator: "type"
4465
+ }
4466
+ );
4467
+ var resourceCreateSchema = Type.Union(
4468
+ [
4469
+ assetResourceCreateSchema,
4470
+ fileResourceSchema,
4471
+ directoryResourceSchema,
4472
+ nestedResourceSchema
4473
+ ],
4474
+ {
4475
+ discriminator: "type"
4476
+ }
4477
+ );
4478
+ var flatResourceSchema = Type.Object({
4479
+ ...baseSchemaProperties,
4480
+ type: Type.Union([
4481
+ Type.Literal("asset"),
4482
+ Type.Literal("file"),
4483
+ Type.Literal("directory"),
4484
+ Type.Literal("resource")
4485
+ ]),
4486
+ assetId: Nullable(Type.String()),
4487
+ fileId: Nullable(Type.String()),
4488
+ resourceId: Nullable(Type.String())
4489
+ });
4490
+ function diffResourceMaps(resourceMap, newResourceMap, idProperty) {
4491
+ const oldIdToPathMap = new Map(
4492
+ Object.entries(resourceMap).map(([path2, entity]) => [
4493
+ entity[idProperty],
4494
+ path2
4495
+ ])
4496
+ );
4497
+ const newIdToPathMap = new Map(
4498
+ Object.entries(newResourceMap).map(([path2, entity]) => [
4499
+ entity[idProperty],
4500
+ path2
4501
+ ])
4502
+ );
4503
+ const oldIds = new Set(
4504
+ Object.values(resourceMap).map((entity) => entity[idProperty])
4505
+ );
4506
+ const newIds = new Set(
4507
+ Object.values(newResourceMap).map((entity) => entity[idProperty])
4508
+ );
4509
+ const sameIds = oldIds.intersection(newIds);
4510
+ const addedResources = Object.values(newResourceMap).filter(
4511
+ (entity) => !oldIds.has(entity[idProperty])
4512
+ );
4513
+ const removedResources = Object.values(resourceMap).filter(
4514
+ (entity) => !newIds.has(entity[idProperty])
4515
+ );
4516
+ const modifiedResources = [...sameIds].flatMap((id) => {
4517
+ const oldResource = Object.values(resourceMap).find(
4518
+ (resource) => resource[idProperty] === id
4519
+ );
4520
+ const newResource = Object.values(newResourceMap).find(
4521
+ (resource) => resource[idProperty] === id
4522
+ );
4523
+ if (!oldResource || !newResource) return [];
4524
+ const oldPath = oldIdToPathMap.get(id);
4525
+ const newPath = newIdToPathMap.get(id);
4526
+ const oldAssetId = oldResource.type === "asset" ? oldResource.assetId : void 0;
4527
+ const newAssetId = newResource.type === "asset" ? newResource.assetId : void 0;
4528
+ const changedProperties = {
4529
+ ...oldPath !== newPath ? { path: newPath } : {},
4530
+ ...oldAssetId !== newAssetId ? { assetId: newAssetId } : {},
4531
+ ...newResource.type === "asset" && newResource.asset !== void 0 ? { asset: newResource.asset } : {}
4532
+ };
4533
+ if (Object.keys(changedProperties).length === 0) return [];
4534
+ return [{ id, stableId: newResource.stableId, ...changedProperties }];
4535
+ });
4536
+ return { addedResources, removedResources, modifiedResources };
4537
+ }
4538
+
4539
+ // ../noya-schemas/src/resourceTree.ts
4540
+ var import_imfs = __toESM(require_lib2());
4541
+ var import_tree_visit2 = __toESM(require_lib());
4542
+
3902
4543
  // ../noya-schemas/src/index.ts
3903
4544
  function validateUUID(value) {
3904
4545
  return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(
@@ -3908,6 +4549,20 @@ function validateUUID(value) {
3908
4549
  format_exports.Set("color", () => true);
3909
4550
  format_exports.Set("uuid", validateUUID);
3910
4551
 
4552
+ // src/NoyaStateContext.tsx
4553
+ import {
4554
+ Observable
4555
+ } from "@noya-app/observable";
4556
+ import { useJsonMemo, useStableCallback } from "@noya-app/react-utils";
4557
+ import React16, {
4558
+ createContext,
4559
+ useCallback as useCallback3,
4560
+ useContext,
4561
+ useEffect as useEffect4,
4562
+ useMemo as useMemo4,
4563
+ useState as useState4
4564
+ } from "react";
4565
+
3911
4566
  // src/noyaApp.ts
3912
4567
  import {
3913
4568
  createOrCastValue,
@@ -3918,21 +4573,21 @@ import {
3918
4573
  TypeGuard,
3919
4574
  webSocketSync
3920
4575
  } from "@noya-app/state-manager";
3921
- import { useMemo as useMemo3, useState as useState2 } from "react";
4576
+ import { useMemo as useMemo3, useState as useState3 } from "react";
3922
4577
 
3923
4578
  // src/hooks.ts
3924
4579
  import {
3925
- NoyaManager,
4580
+ NoyaManager as NoyaManager2,
3926
4581
  StateManager,
3927
4582
  stubSync
3928
4583
  } from "@noya-app/state-manager";
3929
4584
  import {
3930
4585
  createElement as createElement2,
3931
- useCallback,
3932
- useEffect as useEffect2,
4586
+ useCallback as useCallback2,
4587
+ useEffect as useEffect3,
3933
4588
  useMemo as useMemo2,
3934
- useRef,
3935
- useState,
4589
+ useRef as useRef2,
4590
+ useState as useState2,
3936
4591
  useSyncExternalStore as useSyncExternalStore2
3937
4592
  } from "react";
3938
4593
  import { createRoot as createRoot2 } from "react-dom/client";
@@ -4012,24 +4667,126 @@ var ErrorOverlay = React.memo(function ErrorOverlay2({
4012
4667
  });
4013
4668
 
4014
4669
  // src/inspector/useStateInspector.tsx
4015
- import React4 from "react";
4670
+ import React15 from "react";
4016
4671
  import { createRoot } from "react-dom/client";
4017
4672
  import { useIsomorphicLayoutEffect } from "@noya-app/react-utils";
4018
4673
 
4674
+ // ../noya-utils/src/base64.ts
4675
+ function decode(base64String) {
4676
+ const binaryString = atob(base64String);
4677
+ const length = binaryString.length;
4678
+ const bytes = new Uint8Array(length);
4679
+ for (let i = 0; i < length; i++) {
4680
+ bytes[i] = binaryString.charCodeAt(i);
4681
+ }
4682
+ return bytes;
4683
+ }
4684
+ function encode(buffer) {
4685
+ const bytes = new Uint8Array(buffer);
4686
+ let binary = "";
4687
+ const length = bytes.byteLength;
4688
+ for (let i = 0; i < length; i++) {
4689
+ binary += String.fromCharCode(bytes[i]);
4690
+ }
4691
+ return globalThis.btoa(binary);
4692
+ }
4693
+ var Base64 = {
4694
+ encode,
4695
+ decode
4696
+ };
4697
+
4698
+ // ../noya-utils/src/invert.ts
4699
+ function invert(record) {
4700
+ return Object.fromEntries(
4701
+ Object.entries(record).map(([type, extension]) => [extension, type])
4702
+ );
4703
+ }
4704
+
4705
+ // ../noya-utils/src/fileType.ts
4706
+ var FILE_TYPE_TO_EXTENSION = {
4707
+ "image/png": "png",
4708
+ "image/jpeg": "jpg",
4709
+ "image/webp": "webp",
4710
+ "image/svg+xml": "svg",
4711
+ "application/pdf": "pdf",
4712
+ "application/zip": "zip",
4713
+ "application/x-7z-compressed": "7z"
4714
+ };
4715
+ var FILE_EXTENSION_TO_TYPE = invert(FILE_TYPE_TO_EXTENSION);
4716
+
4717
+ // ../noya-utils/src/memoizeDeep.ts
4718
+ var TOKEN_OBJECT = Symbol("object");
4719
+ var TOKEN_ARRAY = Symbol("array");
4720
+ var TOKEN_KEY = Symbol("key");
4721
+ var TOKEN_END = Symbol("end");
4722
+ var TOKEN_PRIMITIVE = Symbol("primitive");
4723
+ var TOKEN_ARGSEP = Symbol("argsep");
4724
+
4725
+ // ../../node_modules/uuid/dist/esm-node/rng.js
4726
+ import crypto from "crypto";
4727
+ var rnds8Pool = new Uint8Array(256);
4728
+ var poolPtr = rnds8Pool.length;
4729
+ function rng() {
4730
+ if (poolPtr > rnds8Pool.length - 16) {
4731
+ crypto.randomFillSync(rnds8Pool);
4732
+ poolPtr = 0;
4733
+ }
4734
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
4735
+ }
4736
+
4737
+ // ../../node_modules/uuid/dist/esm-node/regex.js
4738
+ var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
4739
+
4740
+ // ../../node_modules/uuid/dist/esm-node/validate.js
4741
+ function validate(uuid2) {
4742
+ return typeof uuid2 === "string" && regex_default.test(uuid2);
4743
+ }
4744
+ var validate_default = validate;
4745
+
4746
+ // ../../node_modules/uuid/dist/esm-node/stringify.js
4747
+ var byteToHex = [];
4748
+ for (let i = 0; i < 256; ++i) {
4749
+ byteToHex.push((i + 256).toString(16).substr(1));
4750
+ }
4751
+ function stringify(arr, offset = 0) {
4752
+ const uuid2 = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
4753
+ if (!validate_default(uuid2)) {
4754
+ throw TypeError("Stringified UUID is invalid");
4755
+ }
4756
+ return uuid2;
4757
+ }
4758
+ var stringify_default = stringify;
4759
+
4760
+ // ../../node_modules/uuid/dist/esm-node/v4.js
4761
+ function v4(options, buf, offset) {
4762
+ options = options || {};
4763
+ const rnds = options.random || (options.rng || rng)();
4764
+ rnds[6] = rnds[6] & 15 | 64;
4765
+ rnds[8] = rnds[8] & 63 | 128;
4766
+ if (buf) {
4767
+ offset = offset || 0;
4768
+ for (let i = 0; i < 16; ++i) {
4769
+ buf[offset + i] = rnds[i];
4770
+ }
4771
+ return buf;
4772
+ }
4773
+ return stringify_default(rnds);
4774
+ }
4775
+ var v4_default = v4;
4776
+
4777
+ // ../noya-utils/src/uuid.ts
4778
+ function uuid() {
4779
+ return v4_default();
4780
+ }
4781
+
4019
4782
  // src/inspector/StateInspector.tsx
4020
- import { memoGeneric } from "@noya-app/react-utils";
4021
- import React3, {
4022
- useEffect,
4783
+ import { downloadBlob, memoGeneric } from "@noya-app/react-utils";
4784
+ import React14, {
4785
+ useCallback,
4786
+ useEffect as useEffect2,
4023
4787
  useLayoutEffect
4024
4788
  } from "react";
4025
- import {
4026
- ObjectInspector,
4027
- ObjectLabel,
4028
- ObjectName,
4029
- ObjectPreview,
4030
- chromeDark,
4031
- chromeLight
4032
- } from "react-inspector";
4789
+ import { ObjectInspector as ObjectInspector4 } from "react-inspector";
4033
4790
 
4034
4791
  // src/useObservable.ts
4035
4792
  import { useMemo, useSyncExternalStore } from "react";
@@ -4058,57 +4815,1216 @@ function useObservable(observable, pathOrSelector, options) {
4058
4815
  return useSyncExternalStore(listen, get, get);
4059
4816
  }
4060
4817
 
4061
- // src/inspector/useLocalStorageState.tsx
4818
+ // src/inspector/ColoredDot.tsx
4062
4819
  import React2 from "react";
4063
- var localStorage = typeof window !== "undefined" ? window.localStorage : null;
4064
- function useLocalStorageState(key, defaultValue) {
4065
- const [state, setState] = React2.useState(() => {
4066
- const value = localStorage?.getItem(key);
4067
- let result = defaultValue;
4068
- if (value) {
4069
- try {
4070
- result = JSON.parse(value);
4071
- } catch (error) {
4072
- console.error("Error parsing localStorage value", error);
4820
+ function ColoredDot({ type }) {
4821
+ return /* @__PURE__ */ React2.createElement(
4822
+ "span",
4823
+ {
4824
+ style: {
4825
+ display: "inline-block",
4826
+ width: 6,
4827
+ height: 6,
4828
+ background: type === "success" ? "rgba(0,200,0,0.8)" : "rgba(200,0,0,0.8)",
4829
+ borderRadius: "50%",
4830
+ verticalAlign: "middle"
4073
4831
  }
4074
4832
  }
4075
- return result;
4076
- });
4077
- const setLocalStorageState = (value) => {
4078
- localStorage?.setItem(key, JSON.stringify(value));
4079
- setState(value);
4080
- };
4081
- return [state, setLocalStorageState];
4833
+ );
4834
+ }
4835
+
4836
+ // src/inspector/inspectorTheme.ts
4837
+ import { chromeDark, chromeLight } from "react-inspector";
4838
+ var lightInspectorTheme = {
4839
+ ...chromeLight,
4840
+ BASE_BACKGROUND_COLOR: "transparent",
4841
+ OBJECT_NAME_COLOR: "rgba(0,0,0,0.7)"
4842
+ };
4843
+ var darkInspectorTheme = {
4844
+ ...chromeDark,
4845
+ BASE_BACKGROUND_COLOR: "transparent",
4846
+ OBJECT_NAME_COLOR: "rgba(255,255,255,0.7)"
4847
+ };
4848
+ var getStateInspectorTheme = (colorScheme) => {
4849
+ return colorScheme === "light" ? lightInspectorTheme : darkInspectorTheme;
4850
+ };
4851
+ var getStateInspectorBorderColor = (colorScheme) => {
4852
+ return colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
4853
+ };
4854
+
4855
+ // src/inspector/sections/ActivityEventsSection.tsx
4856
+ import React7, { useState } from "react";
4857
+ import { ObjectInspector } from "react-inspector";
4858
+
4859
+ // src/inspector/StateInspectorButton.tsx
4860
+ import React3 from "react";
4861
+ function StateInspectorButton({
4862
+ children,
4863
+ onClick,
4864
+ style,
4865
+ theme,
4866
+ disabled
4867
+ }) {
4868
+ return /* @__PURE__ */ React3.createElement(
4869
+ "button",
4870
+ {
4871
+ type: "button",
4872
+ disabled,
4873
+ onClick: (event) => {
4874
+ event.stopPropagation();
4875
+ onClick();
4876
+ },
4877
+ style: {
4878
+ flex: "0",
4879
+ appearance: "none",
4880
+ background: "none",
4881
+ color: theme.BASE_COLOR,
4882
+ opacity: disabled ? 0.25 : 1,
4883
+ border: "none",
4884
+ fontSize: "12px",
4885
+ whiteSpace: "nowrap",
4886
+ display: "inline-flex",
4887
+ alignItems: "center",
4888
+ justifyContent: "center",
4889
+ padding: "0",
4890
+ cursor: "pointer",
4891
+ ...style
4892
+ }
4893
+ },
4894
+ children
4895
+ );
4896
+ }
4897
+
4898
+ // src/inspector/StateInspectorDisclosureSection.tsx
4899
+ import React5, {
4900
+ forwardRef
4901
+ } from "react";
4902
+
4903
+ // src/inspector/StateInspectorArrow.tsx
4904
+ import React4 from "react";
4905
+ function StateInspectorArrow({
4906
+ expanded,
4907
+ onClick,
4908
+ style
4909
+ }) {
4910
+ return /* @__PURE__ */ React4.createElement(
4911
+ "span",
4912
+ {
4913
+ role: "button",
4914
+ onClick,
4915
+ style: {
4916
+ display: "inline-block",
4917
+ textAlign: "center",
4918
+ transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
4919
+ fontFamily: "Menlo, monospace",
4920
+ ...style
4921
+ }
4922
+ },
4923
+ "\u25BC"
4924
+ );
4925
+ }
4926
+
4927
+ // src/inspector/StateInspectorDisclosureSection.tsx
4928
+ function StateInspectorDisclosureSection({
4929
+ open,
4930
+ setOpen,
4931
+ title,
4932
+ right,
4933
+ children,
4934
+ colorScheme,
4935
+ isFirst,
4936
+ style
4937
+ }) {
4938
+ const theme = colorScheme === "light" ? lightInspectorTheme : darkInspectorTheme;
4939
+ const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
4940
+ return /* @__PURE__ */ React5.createElement(
4941
+ "div",
4942
+ {
4943
+ style: {
4944
+ flex: open ? "1 1 0" : "0",
4945
+ display: "flex",
4946
+ flexDirection: "column",
4947
+ ...style
4948
+ }
4949
+ },
4950
+ /* @__PURE__ */ React5.createElement(
4951
+ "div",
4952
+ {
4953
+ onClick: () => setOpen?.(!open),
4954
+ style: {
4955
+ cursor: "default",
4956
+ fontSize: "12px",
4957
+ padding: "4px 10px",
4958
+ display: "flex",
4959
+ alignItems: "center",
4960
+ ...!isFirst && { borderTop: `1px solid ${borderColor}` },
4961
+ ...open && { borderBottom: `1px solid ${borderColor}` }
4962
+ }
4963
+ },
4964
+ setOpen && /* @__PURE__ */ React5.createElement(
4965
+ StateInspectorArrow,
4966
+ {
4967
+ expanded: open,
4968
+ style: {
4969
+ fontSize: theme.ARROW_FONT_SIZE,
4970
+ marginRight: theme.ARROW_MARGIN_RIGHT + 1,
4971
+ color: theme.ARROW_COLOR
4972
+ }
4973
+ }
4974
+ ),
4975
+ /* @__PURE__ */ React5.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
4976
+ right
4977
+ ),
4978
+ open && children
4979
+ );
4980
+ }
4981
+ var StateInspectorDisclosureRowInner = forwardRef(
4982
+ function StateInspectorDisclosureRowInner2(props, forwardedRef) {
4983
+ return /* @__PURE__ */ React5.createElement(
4984
+ "div",
4985
+ {
4986
+ style: {
4987
+ flex: "1 1 0",
4988
+ overflowY: "auto",
4989
+ overflowX: "hidden",
4990
+ display: "flex",
4991
+ flexDirection: "column",
4992
+ ...props.style
4993
+ },
4994
+ ...props,
4995
+ ref: forwardedRef
4996
+ }
4997
+ );
4998
+ }
4999
+ );
5000
+
5001
+ // src/inspector/StateInspectorRow.tsx
5002
+ import React6 from "react";
5003
+ function StateInspectorRow({
5004
+ children,
5005
+ colorScheme,
5006
+ selected,
5007
+ style,
5008
+ variant
5009
+ }) {
5010
+ const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
5011
+ return /* @__PURE__ */ React6.createElement(
5012
+ "div",
5013
+ {
5014
+ style: {
5015
+ borderBottom: `1px solid ${solidBorderColor}`,
5016
+ fontSize: "12px",
5017
+ fontFamily: "Menlo, monospace",
5018
+ padding: "2px 12px 1px",
5019
+ display: "flex",
5020
+ alignItems: "center",
5021
+ background: variant === "up" ? "rgba(0,255,0,0.1)" : variant === "down" ? "transparent" : selected ? "rgb(59 130 246 / 15%)" : void 0,
5022
+ // background:
5023
+ // colorScheme === "light"
5024
+ // ? "rgba(0,0,0,0.05)"
5025
+ // : "rgba(255,255,255,0.05)",
5026
+ ...style
5027
+ }
5028
+ },
5029
+ /* @__PURE__ */ React6.createElement(
5030
+ "span",
5031
+ {
5032
+ style: {
5033
+ fontFamily: "Menlo, monospace",
5034
+ fontSize: "11px",
5035
+ borderRadius: 4,
5036
+ display: "inline-block"
5037
+ }
5038
+ },
5039
+ children
5040
+ )
5041
+ );
5042
+ }
5043
+
5044
+ // src/inspector/sections/ActivityEventsSection.tsx
5045
+ function isResourceStreamFilter(streamFilter) {
5046
+ return typeof streamFilter === "object" && "resourceId" in streamFilter;
5047
+ }
5048
+ function isResourceActivityEvent(activityEvent) {
5049
+ return typeof activityEvent === "object" && activityEvent !== null && "type" in activityEvent && activityEvent.type === "resource" && "resourceId" in activityEvent && typeof activityEvent.resourceId === "string";
5050
+ }
5051
+ function ActivityEventsSection({
5052
+ showEvents,
5053
+ setShowEvents,
5054
+ colorScheme,
5055
+ activityEventsContainerRef,
5056
+ activityEventsManager
5057
+ }) {
5058
+ const [streamFilter, setStreamFilter] = useState("all");
5059
+ const streamFilterType = isResourceStreamFilter(streamFilter) ? "resource" : "all";
5060
+ const theme = getStateInspectorTheme(colorScheme);
5061
+ const activityEvents = useActivityEventsForManager(
5062
+ showEvents ? streamFilter : void 0,
5063
+ activityEventsManager
5064
+ );
5065
+ return /* @__PURE__ */ React7.createElement(
5066
+ StateInspectorDisclosureSection,
5067
+ {
5068
+ open: showEvents,
5069
+ setOpen: setShowEvents,
5070
+ title: `Activity Events`,
5071
+ colorScheme
5072
+ },
5073
+ /* @__PURE__ */ React7.createElement(StateInspectorDisclosureRowInner, { ref: activityEventsContainerRef }, /* @__PURE__ */ React7.createElement("div", { style: { padding: "4px 12px", display: "flex", gap: "4px" } }, /* @__PURE__ */ React7.createElement(
5074
+ "select",
5075
+ {
5076
+ name: "streamFilterType",
5077
+ value: streamFilterType,
5078
+ style: { flex: "0 0 auto", height: "19px" },
5079
+ onChange: (e) => {
5080
+ const value = e.target.value;
5081
+ if (value === "all") {
5082
+ setStreamFilter("all");
5083
+ } else {
5084
+ setStreamFilter({ resourceId: "" });
5085
+ }
5086
+ }
5087
+ },
5088
+ /* @__PURE__ */ React7.createElement("option", { value: "all" }, "All"),
5089
+ /* @__PURE__ */ React7.createElement("option", { value: "resource" }, "Resource")
5090
+ ), isResourceStreamFilter(streamFilter) && /* @__PURE__ */ React7.createElement(
5091
+ "input",
5092
+ {
5093
+ name: "resourceId",
5094
+ type: "text",
5095
+ placeholder: "Resource ID",
5096
+ value: streamFilter.resourceId,
5097
+ style: {
5098
+ flex: "1 1 auto",
5099
+ height: "19px",
5100
+ padding: "0px 4px",
5101
+ boxSizing: "border-box"
5102
+ },
5103
+ onChange: (e) => setStreamFilter({ ...streamFilter, resourceId: e.target.value })
5104
+ }
5105
+ )), activityEvents?.map((activityEvent, index) => /* @__PURE__ */ React7.createElement(
5106
+ StateInspectorRow,
5107
+ {
5108
+ key: index,
5109
+ colorScheme,
5110
+ style: {
5111
+ padding: "0px 12px 1px"
5112
+ }
5113
+ },
5114
+ /* @__PURE__ */ React7.createElement(ObjectInspector, { data: activityEvent, theme }),
5115
+ streamFilterType === "all" && isResourceActivityEvent(activityEvent) && /* @__PURE__ */ React7.createElement(
5116
+ StateInspectorButton,
5117
+ {
5118
+ theme,
5119
+ onClick: () => {
5120
+ setStreamFilter({ resourceId: activityEvent.resourceId });
5121
+ }
5122
+ },
5123
+ "Watch this resource"
5124
+ )
5125
+ )), !activityEvents && /* @__PURE__ */ React7.createElement(
5126
+ "div",
5127
+ {
5128
+ style: {
5129
+ padding: "12px",
5130
+ fontSize: "12px",
5131
+ display: "flex",
5132
+ flexDirection: "column",
5133
+ gap: "4px"
5134
+ }
5135
+ },
5136
+ /* @__PURE__ */ React7.createElement("span", null, "No activity events")
5137
+ ))
5138
+ );
5139
+ }
5140
+
5141
+ // src/inspector/sections/EventsSection.tsx
5142
+ import React9 from "react";
5143
+ import { ObjectInspector as ObjectInspector2, ObjectLabel } from "react-inspector";
5144
+
5145
+ // src/inspector/ObjectRootLabel.tsx
5146
+ import React8 from "react";
5147
+ import { ObjectName, ObjectPreview } from "react-inspector";
5148
+ var ObjectRootLabel = ({ name, data, direction }) => {
5149
+ if (typeof name === "string") {
5150
+ return /* @__PURE__ */ React8.createElement("span", null, /* @__PURE__ */ React8.createElement(ObjectName, { name }), /* @__PURE__ */ React8.createElement("span", null, ": "), /* @__PURE__ */ React8.createElement(ObjectPreview, { data }));
5151
+ }
5152
+ if (direction === "up" || direction === "down") {
5153
+ const arrow = direction === "up" ? "\u2191" : "\u2193";
5154
+ return /* @__PURE__ */ React8.createElement("span", null, /* @__PURE__ */ React8.createElement(
5155
+ "span",
5156
+ {
5157
+ style: {
5158
+ background: direction === "up" ? "rgba(0,255,0,0.2)" : "rgba(255,0,0,0.2)",
5159
+ // color: "white",
5160
+ width: 12,
5161
+ height: 12,
5162
+ borderRadius: 2,
5163
+ display: "inline-flex",
5164
+ justifyContent: "center",
5165
+ alignItems: "center",
5166
+ marginRight: 4,
5167
+ lineHeight: "12px"
5168
+ }
5169
+ },
5170
+ arrow
5171
+ ), /* @__PURE__ */ React8.createElement(ObjectPreview, { data }));
5172
+ } else {
5173
+ return /* @__PURE__ */ React8.createElement(ObjectPreview, { data });
5174
+ }
5175
+ };
5176
+
5177
+ // src/inspector/sections/EventsSection.tsx
5178
+ function EventsSection({
5179
+ showEvents,
5180
+ setShowEvents,
5181
+ colorScheme,
5182
+ eventsContainerRef,
5183
+ connectionEvents
5184
+ }) {
5185
+ const theme = getStateInspectorTheme(colorScheme);
5186
+ return /* @__PURE__ */ React9.createElement(
5187
+ StateInspectorDisclosureSection,
5188
+ {
5189
+ open: showEvents,
5190
+ setOpen: setShowEvents,
5191
+ title: "Events",
5192
+ colorScheme
5193
+ },
5194
+ /* @__PURE__ */ React9.createElement(StateInspectorDisclosureRowInner, { ref: eventsContainerRef }, connectionEvents?.map(
5195
+ (event, index) => event.type === "stateChange" ? /* @__PURE__ */ React9.createElement(StateInspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ React9.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ React9.createElement(
5196
+ StateInspectorRow,
5197
+ {
5198
+ key: index,
5199
+ colorScheme,
5200
+ variant: event.type === "send" ? "up" : "down",
5201
+ style: {
5202
+ padding: "0px 12px 1px"
5203
+ }
5204
+ },
5205
+ /* @__PURE__ */ React9.createElement(
5206
+ ObjectInspector2,
5207
+ {
5208
+ data: event.type === "error" ? event.error : event.message,
5209
+ theme,
5210
+ nodeRenderer: ({ depth, name, data, isNonenumerable }) => {
5211
+ const direction = event.type === "send" ? "up" : "down";
5212
+ return depth === 0 ? /* @__PURE__ */ React9.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React9.createElement(
5213
+ ObjectLabel,
5214
+ {
5215
+ direction,
5216
+ name,
5217
+ data,
5218
+ isNonenumerable
5219
+ }
5220
+ );
5221
+ }
5222
+ }
5223
+ )
5224
+ )
5225
+ ), !connectionEvents && /* @__PURE__ */ React9.createElement(
5226
+ "div",
5227
+ {
5228
+ style: {
5229
+ padding: "12px",
5230
+ fontSize: "12px",
5231
+ display: "flex",
5232
+ flexDirection: "column",
5233
+ gap: "4px"
5234
+ }
5235
+ },
5236
+ /* @__PURE__ */ React9.createElement("span", null, "No recorded events")
5237
+ ))
5238
+ );
5239
+ }
5240
+
5241
+ // src/inspector/sections/HistorySection.tsx
5242
+ import React10, { useEffect, useRef } from "react";
5243
+ import { ObjectInspector as ObjectInspector3 } from "react-inspector";
5244
+
5245
+ // src/inspector/utils.ts
5246
+ function pathToString(extendedPath) {
5247
+ return extendedPath.map(
5248
+ (key) => typeof key === "object" ? `:${ellipsis(key.id.toString(), 8, "middle")}` : key
5249
+ ).map(
5250
+ (key, index) => index === 0 || typeof key === "string" && key.startsWith(":") ? key : `.${key}`
5251
+ ).join("");
5252
+ }
5253
+ function ellipsis(str, maxLength, position = "end") {
5254
+ if (str.length <= maxLength) return str;
5255
+ switch (position) {
5256
+ case "start":
5257
+ return `\u2026${str.slice(str.length - maxLength)}`;
5258
+ case "middle": {
5259
+ const halfLength = Math.floor(maxLength / 2);
5260
+ return `${str.slice(0, halfLength)}\u2026${str.slice(str.length - halfLength)}`;
5261
+ }
5262
+ case "end":
5263
+ return `${str.slice(0, maxLength)}\u2026`;
5264
+ }
5265
+ }
5266
+ function uploadFile() {
5267
+ return new Promise((resolve, reject) => {
5268
+ const input = document.createElement("input");
5269
+ input.type = "file";
5270
+ input.onchange = () => {
5271
+ const file = input.files?.[0];
5272
+ if (file) {
5273
+ const reader = new FileReader();
5274
+ reader.onload = () => {
5275
+ const buffer = reader.result;
5276
+ const blob = new File([buffer], file.name, { type: file.type });
5277
+ resolve(blob);
5278
+ };
5279
+ reader.onerror = () => {
5280
+ reject(new Error("Failed to read file"));
5281
+ };
5282
+ reader.readAsArrayBuffer(file);
5283
+ }
5284
+ };
5285
+ input.click();
5286
+ });
5287
+ }
5288
+
5289
+ // src/inspector/sections/HistorySection.tsx
5290
+ var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
5291
+ function HistorySection({
5292
+ showHistory,
5293
+ setShowHistory,
5294
+ colorScheme,
5295
+ historySnapshot,
5296
+ multiplayerStateManager
5297
+ }) {
5298
+ const ref = useRef(null);
5299
+ const theme = getStateInspectorTheme(colorScheme);
5300
+ const solidBorderColor = getStateInspectorBorderColor(colorScheme);
5301
+ useEffect(() => {
5302
+ if (ref.current) {
5303
+ ref.current.scrollTop = ref.current.scrollHeight;
5304
+ }
5305
+ }, [historySnapshot]);
5306
+ useEffect(() => {
5307
+ if (!ref.current) return;
5308
+ const historyEntry = ref.current.querySelector(
5309
+ `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
5310
+ );
5311
+ if (historyEntry) {
5312
+ historyEntry.scrollIntoView({
5313
+ block: "nearest",
5314
+ inline: "nearest"
5315
+ });
5316
+ }
5317
+ }, [historySnapshot.historyIndex]);
5318
+ return /* @__PURE__ */ React10.createElement(
5319
+ StateInspectorDisclosureSection,
5320
+ {
5321
+ open: showHistory,
5322
+ setOpen: setShowHistory,
5323
+ title: "History",
5324
+ colorScheme,
5325
+ right: /* @__PURE__ */ React10.createElement(
5326
+ "span",
5327
+ {
5328
+ style: {
5329
+ display: "flex",
5330
+ gap: "4px"
5331
+ }
5332
+ },
5333
+ /* @__PURE__ */ React10.createElement(
5334
+ StateInspectorButton,
5335
+ {
5336
+ disabled: !historySnapshot.canUndo,
5337
+ theme,
5338
+ onClick: () => {
5339
+ multiplayerStateManager.undo();
5340
+ }
5341
+ },
5342
+ /* @__PURE__ */ React10.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React10.createElement(
5343
+ "svg",
5344
+ {
5345
+ xmlns: "http://www.w3.org/2000/svg",
5346
+ width: "1em",
5347
+ height: "1em",
5348
+ viewBox: "0 0 20 20"
5349
+ },
5350
+ /* @__PURE__ */ React10.createElement(
5351
+ "path",
5352
+ {
5353
+ fill: "currentColor",
5354
+ d: "M12 5H7V2L1 6l6 4V7h5c2.2 0 4 1.8 4 4s-1.8 4-4 4H7v2h5c3.3 0 6-2.7 6-6s-2.7-6-6-6"
5355
+ }
5356
+ )
5357
+ ))
5358
+ ),
5359
+ /* @__PURE__ */ React10.createElement(
5360
+ StateInspectorButton,
5361
+ {
5362
+ disabled: !historySnapshot.canRedo,
5363
+ theme,
5364
+ onClick: () => {
5365
+ multiplayerStateManager.redo();
5366
+ }
5367
+ },
5368
+ /* @__PURE__ */ React10.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React10.createElement(
5369
+ "svg",
5370
+ {
5371
+ xmlns: "http://www.w3.org/2000/svg",
5372
+ width: "1em",
5373
+ height: "1em",
5374
+ viewBox: "0 0 20 20"
5375
+ },
5376
+ /* @__PURE__ */ React10.createElement(
5377
+ "path",
5378
+ {
5379
+ fill: "currentColor",
5380
+ d: "M8 5h5V2l6 4l-6 4V7H8c-2.2 0-4 1.8-4 4s1.8 4 4 4h5v2H8c-3.3 0-6-2.7-6-6s2.7-6 6-6"
5381
+ }
5382
+ )
5383
+ ))
5384
+ )
5385
+ )
5386
+ },
5387
+ /* @__PURE__ */ React10.createElement(StateInspectorDisclosureRowInner, { ref }, /* @__PURE__ */ React10.createElement(
5388
+ "div",
5389
+ {
5390
+ id: `${HISTORY_ELEMENT_PREFIX}0`,
5391
+ style: {
5392
+ borderBottom: `1px solid ${solidBorderColor}`,
5393
+ fontSize: "12px",
5394
+ fontFamily: "Menlo, monospace",
5395
+ padding: "2px 12px 1px",
5396
+ display: "flex",
5397
+ alignItems: "center",
5398
+ background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
5399
+ }
5400
+ },
5401
+ /* @__PURE__ */ React10.createElement(
5402
+ "span",
5403
+ {
5404
+ style: {
5405
+ fontFamily: "Menlo, monospace",
5406
+ fontSize: "11px",
5407
+ borderRadius: 4,
5408
+ display: "inline-block"
5409
+ }
5410
+ },
5411
+ "Initial state"
5412
+ )
5413
+ ), historySnapshot.history.map((entry, index) => {
5414
+ const metadata = entry.metadata;
5415
+ const { id, name, timestamp, ...rest } = metadata;
5416
+ return /* @__PURE__ */ React10.createElement(
5417
+ "div",
5418
+ {
5419
+ id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
5420
+ key: index,
5421
+ style: {
5422
+ padding: "0px 12px 1px",
5423
+ borderBottom: `1px solid ${solidBorderColor}`,
5424
+ background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
5425
+ }
5426
+ },
5427
+ typeof name === "string" && /* @__PURE__ */ React10.createElement(
5428
+ "pre",
5429
+ {
5430
+ style: {
5431
+ fontSize: "11px",
5432
+ display: "flex",
5433
+ flexWrap: "wrap",
5434
+ margin: 0
5435
+ }
5436
+ },
5437
+ entry.metadata.name,
5438
+ Object.keys(rest).length > 0 && /* @__PURE__ */ React10.createElement(ObjectInspector3, { data: rest, theme })
5439
+ ),
5440
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React10.createElement(
5441
+ "pre",
5442
+ {
5443
+ key: j,
5444
+ style: {
5445
+ fontSize: "11px",
5446
+ display: "flex",
5447
+ flexWrap: "wrap",
5448
+ margin: 0
5449
+ }
5450
+ },
5451
+ patch.op === "add" && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React10.createElement(ObjectInspector3, { data: patch.value, theme })),
5452
+ patch.op === "replace" && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React10.createElement(ObjectInspector3, { data: patch.value, theme })),
5453
+ patch.op === "remove" && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React10.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
5454
+ patch.op === "move" && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React10.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
5455
+ ))
5456
+ );
5457
+ }))
5458
+ );
5459
+ }
5460
+
5461
+ // src/inspector/serialization.ts
5462
+ import { createHash } from "@noya-app/state-manager";
5463
+
5464
+ // src/inspector/zip/crc32.ts
5465
+ var CRC_TABLE = (() => {
5466
+ const t = new Uint32Array(256);
5467
+ for (let i = 0; i < 256; i++) {
5468
+ let c = i;
5469
+ for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
5470
+ t[i] = c >>> 0;
5471
+ }
5472
+ return t;
5473
+ })();
5474
+ function crc32(u8) {
5475
+ let c = 4294967295;
5476
+ for (let i = 0; i < u8.length; i++)
5477
+ c = CRC_TABLE[(c ^ u8[i]) & 255] ^ c >>> 8;
5478
+ return (c ^ 4294967295) >>> 0;
5479
+ }
5480
+
5481
+ // src/inspector/zip/struct.ts
5482
+ var defineSchema = (s) => s;
5483
+ var defineSchemas = (m) => m;
5484
+ function sizeofFieldSpec(f, ctx) {
5485
+ if (f.type === "bytes")
5486
+ return typeof f.length === "function" ? f.length(ctx) : f.length;
5487
+ return f.type === "u8" ? 1 : f.type === "u16" ? 2 : 4;
5488
+ }
5489
+ function writeStruct(schema, values) {
5490
+ let total = 0;
5491
+ const ctx = { ...values };
5492
+ for (const f of schema) total += sizeofFieldSpec(f, ctx);
5493
+ const out = new Uint8Array(total);
5494
+ const view = new DataView(out.buffer);
5495
+ let o = 0;
5496
+ const vals = values;
5497
+ for (const f of schema) {
5498
+ if (f.type === "bytes") {
5499
+ const b = vals[f.name];
5500
+ out.set(b, o);
5501
+ o += b.length;
5502
+ continue;
5503
+ }
5504
+ const n = Number(vals[f.name]) >>> 0;
5505
+ if (f.type === "u8") {
5506
+ view.setUint8(o, n);
5507
+ o += 1;
5508
+ } else if (f.type === "u16") {
5509
+ view.setUint16(o, n, true);
5510
+ o += 2;
5511
+ } else {
5512
+ view.setUint32(o, n, true);
5513
+ o += 4;
5514
+ }
5515
+ }
5516
+ return out;
5517
+ }
5518
+ function readStruct(view, offset, schema) {
5519
+ const ctx = {};
5520
+ let o = offset;
5521
+ for (const f of schema) {
5522
+ if (f.type === "bytes") {
5523
+ const len = typeof f.length === "function" ? f.length(ctx) : f.length;
5524
+ const u8 = new Uint8Array(view.buffer, view.byteOffset + o, len);
5525
+ ctx[f.name] = new Uint8Array(u8);
5526
+ o += len;
5527
+ } else if (f.type === "u8") {
5528
+ ctx[f.name] = view.getUint8(o);
5529
+ o += 1;
5530
+ } else if (f.type === "u16") {
5531
+ ctx[f.name] = view.getUint16(o, true);
5532
+ o += 2;
5533
+ } else {
5534
+ ctx[f.name] = view.getUint32(o, true);
5535
+ o += 4;
5536
+ }
5537
+ }
5538
+ return { value: ctx, offset: o };
5539
+ }
5540
+
5541
+ // src/inspector/zip/TinyZip.ts
5542
+ var te = new TextEncoder();
5543
+ function utf8(s) {
5544
+ return te.encode(s);
5545
+ }
5546
+ function dosDateTime(d = /* @__PURE__ */ new Date()) {
5547
+ const time = d.getHours() << 11 | d.getMinutes() << 5 | Math.floor(d.getSeconds() / 2);
5548
+ const date = d.getFullYear() - 1980 << 9 | d.getMonth() + 1 << 5 | d.getDate();
5549
+ return { time, date };
5550
+ }
5551
+ var SIG = {
5552
+ LocalFile: 67324752,
5553
+ CentralFile: 33639248,
5554
+ EOCD: 101010256
5555
+ };
5556
+ var SCHEMA = defineSchemas({
5557
+ LocalFile: defineSchema([
5558
+ { name: "signature", type: "u32" },
5559
+ { name: "versionNeeded", type: "u16" },
5560
+ { name: "flags", type: "u16" },
5561
+ { name: "method", type: "u16" },
5562
+ { name: "time", type: "u16" },
5563
+ { name: "date", type: "u16" },
5564
+ { name: "crc32", type: "u32" },
5565
+ { name: "compSize", type: "u32" },
5566
+ { name: "uncompSize", type: "u32" },
5567
+ { name: "nameLen", type: "u16" },
5568
+ { name: "extraLen", type: "u16" },
5569
+ { name: "name", type: "bytes", length: (c) => c.nameLen },
5570
+ { name: "extra", type: "bytes", length: (c) => c.extraLen }
5571
+ ]),
5572
+ CentralFile: defineSchema([
5573
+ { name: "signature", type: "u32" },
5574
+ { name: "versionMadeBy", type: "u16" },
5575
+ { name: "versionNeeded", type: "u16" },
5576
+ { name: "flags", type: "u16" },
5577
+ { name: "method", type: "u16" },
5578
+ { name: "time", type: "u16" },
5579
+ { name: "date", type: "u16" },
5580
+ { name: "crc32", type: "u32" },
5581
+ { name: "compSize", type: "u32" },
5582
+ { name: "uncompSize", type: "u32" },
5583
+ { name: "nameLen", type: "u16" },
5584
+ { name: "extraLen", type: "u16" },
5585
+ { name: "commentLen", type: "u16" },
5586
+ { name: "diskStart", type: "u16" },
5587
+ { name: "intAttrs", type: "u16" },
5588
+ { name: "extAttrs", type: "u32" },
5589
+ { name: "localHeaderOffset", type: "u32" },
5590
+ { name: "name", type: "bytes", length: (c) => c.nameLen },
5591
+ { name: "extra", type: "bytes", length: (c) => c.extraLen },
5592
+ { name: "comment", type: "bytes", length: (c) => c.commentLen }
5593
+ ]),
5594
+ EOCD: defineSchema([
5595
+ { name: "signature", type: "u32" },
5596
+ { name: "diskNum", type: "u16" },
5597
+ { name: "cdStartDisk", type: "u16" },
5598
+ { name: "cdRecordsOnDisk", type: "u16" },
5599
+ { name: "cdRecordsTotal", type: "u16" },
5600
+ { name: "cdSize", type: "u32" },
5601
+ { name: "cdOffset", type: "u32" },
5602
+ { name: "commentLen", type: "u16" },
5603
+ { name: "comment", type: "bytes", length: (c) => c.commentLen }
5604
+ ])
5605
+ });
5606
+ function ensureSig(v, expect, where) {
5607
+ if (v !== expect)
5608
+ throw new Error(`Invalid signature for ${where}: 0x${v.toString(16)}`);
5609
+ }
5610
+ var TinyZip = class _TinyZip {
5611
+ _chunks = [];
5612
+ _offset = 0;
5613
+ _files = [];
5614
+ _rootPrefix = "";
5615
+ // e.g. "my-archive/" or ""
5616
+ _rootDirAdded = false;
5617
+ constructor(opts = {}) {
5618
+ if (opts.root) {
5619
+ const r = opts.root.replace(/^\/+|\/+$/g, "");
5620
+ if (r) this._rootPrefix = r + "/";
5621
+ }
5622
+ }
5623
+ _push(...arrs) {
5624
+ for (const a of arrs) {
5625
+ this._chunks.push(a);
5626
+ this._offset += a.length;
5627
+ }
5628
+ }
5629
+ _withRoot(name) {
5630
+ return this._rootPrefix && !name.startsWith(this._rootPrefix) ? this._rootPrefix + name.replace(/^\/+/, "") : name;
5631
+ }
5632
+ _ensureRootDir(date = /* @__PURE__ */ new Date()) {
5633
+ if (!this._rootPrefix || this._rootDirAdded) return;
5634
+ this._rootDirAdded = true;
5635
+ const dirName = this._rootPrefix;
5636
+ const nameBytes = utf8(dirName);
5637
+ const { time, date: dosDate } = dosDateTime(date);
5638
+ const localHeader = writeStruct(SCHEMA.LocalFile, {
5639
+ signature: SIG.LocalFile,
5640
+ versionNeeded: 20,
5641
+ flags: 2048,
5642
+ method: 0,
5643
+ time,
5644
+ date: dosDate,
5645
+ crc32: 0,
5646
+ compSize: 0,
5647
+ uncompSize: 0,
5648
+ nameLen: nameBytes.length,
5649
+ extraLen: 0,
5650
+ name: nameBytes,
5651
+ extra: new Uint8Array(0)
5652
+ });
5653
+ const localHeaderOffset = this._offset;
5654
+ this._push(localHeader);
5655
+ this._files.push({
5656
+ nameBytes,
5657
+ crc: 0,
5658
+ compSize: 0,
5659
+ uncompSize: 0,
5660
+ method: 0,
5661
+ time,
5662
+ dosDate,
5663
+ localHeaderOffset,
5664
+ externalAttrs: 16
5665
+ });
5666
+ }
5667
+ /** Add a file to the zip. "name" uses forward slashes for paths (e.g., "dir/file.txt"). */
5668
+ addFile(name, data, opts = {}) {
5669
+ const { date = /* @__PURE__ */ new Date() } = opts;
5670
+ this._ensureRootDir(date);
5671
+ const u8 = toU8(data);
5672
+ const fullName = this._withRoot(name);
5673
+ const nameBytes = utf8(fullName);
5674
+ const { time, date: dosDate } = dosDateTime(date);
5675
+ const crc = crc32(u8);
5676
+ const compSize = u8.length >>> 0;
5677
+ const uncompSize = u8.length >>> 0;
5678
+ const localHeaderOffset = this._offset;
5679
+ const localHeader = writeStruct(SCHEMA.LocalFile, {
5680
+ signature: SIG.LocalFile,
5681
+ versionNeeded: 20,
5682
+ flags: 2048,
5683
+ method: 0,
5684
+ time,
5685
+ date: dosDate,
5686
+ crc32: crc,
5687
+ compSize,
5688
+ uncompSize,
5689
+ nameLen: nameBytes.length,
5690
+ extraLen: 0,
5691
+ name: nameBytes,
5692
+ extra: new Uint8Array(0)
5693
+ });
5694
+ this._push(localHeader, u8);
5695
+ this._files.push({
5696
+ nameBytes,
5697
+ crc,
5698
+ compSize,
5699
+ uncompSize,
5700
+ method: 0,
5701
+ time,
5702
+ dosDate,
5703
+ localHeaderOffset,
5704
+ externalAttrs: 0
5705
+ });
5706
+ }
5707
+ // Create an explicit directory entry (name should end with "/").
5708
+ addDirectory(name, opts = {}) {
5709
+ const { date = /* @__PURE__ */ new Date() } = opts;
5710
+ this._ensureRootDir(date);
5711
+ const dirNameRaw = name.endsWith("/") ? name : name + "/";
5712
+ const fullName = this._withRoot(dirNameRaw);
5713
+ const nameBytes = utf8(fullName);
5714
+ const { time, date: dosDate } = dosDateTime(date);
5715
+ const localHeader = writeStruct(SCHEMA.LocalFile, {
5716
+ signature: SIG.LocalFile,
5717
+ versionNeeded: 20,
5718
+ flags: 2048,
5719
+ method: 0,
5720
+ time,
5721
+ date: dosDate,
5722
+ crc32: 0,
5723
+ compSize: 0,
5724
+ uncompSize: 0,
5725
+ nameLen: nameBytes.length,
5726
+ extraLen: 0,
5727
+ name: nameBytes,
5728
+ extra: new Uint8Array(0)
5729
+ });
5730
+ const localHeaderOffset = this._offset;
5731
+ this._push(localHeader);
5732
+ this._files.push({
5733
+ nameBytes,
5734
+ crc: 0,
5735
+ compSize: 0,
5736
+ uncompSize: 0,
5737
+ method: 0,
5738
+ time,
5739
+ dosDate,
5740
+ localHeaderOffset,
5741
+ externalAttrs: 16
5742
+ });
5743
+ }
5744
+ finish() {
5745
+ const cdStart = this._offset;
5746
+ for (const f of this._files) {
5747
+ const central = writeStruct(SCHEMA.CentralFile, {
5748
+ signature: SIG.CentralFile,
5749
+ versionMadeBy: 20,
5750
+ versionNeeded: 20,
5751
+ flags: 2048,
5752
+ method: f.method,
5753
+ time: f.time,
5754
+ date: f.dosDate,
5755
+ crc32: f.crc,
5756
+ compSize: f.compSize,
5757
+ uncompSize: f.uncompSize,
5758
+ nameLen: f.nameBytes.length,
5759
+ extraLen: 0,
5760
+ commentLen: 0,
5761
+ diskStart: 0,
5762
+ intAttrs: 0,
5763
+ extAttrs: f.externalAttrs,
5764
+ localHeaderOffset: f.localHeaderOffset,
5765
+ name: f.nameBytes,
5766
+ extra: new Uint8Array(0),
5767
+ comment: new Uint8Array(0)
5768
+ });
5769
+ this._push(central);
5770
+ }
5771
+ const cdSize = this._offset - cdStart;
5772
+ const eocd = writeStruct(SCHEMA.EOCD, {
5773
+ signature: SIG.EOCD,
5774
+ diskNum: 0,
5775
+ cdStartDisk: 0,
5776
+ cdRecordsOnDisk: this._files.length,
5777
+ cdRecordsTotal: this._files.length,
5778
+ cdSize,
5779
+ cdOffset: cdStart,
5780
+ commentLen: 0,
5781
+ comment: new Uint8Array(0)
5782
+ });
5783
+ this._push(eocd);
5784
+ const merged = new Uint8Array(this._offset);
5785
+ let offset = 0;
5786
+ for (const chunk of this._chunks) {
5787
+ merged.set(chunk, offset);
5788
+ offset += chunk.length;
5789
+ }
5790
+ return merged;
5791
+ }
5792
+ static create(files, opts = {}) {
5793
+ const zip = new _TinyZip(opts);
5794
+ for (const [name, data] of Object.entries(files)) {
5795
+ if (name.endsWith("/")) zip.addDirectory(name);
5796
+ else zip.addFile(name, data);
5797
+ }
5798
+ return zip.finish();
5799
+ }
5800
+ static parse(input) {
5801
+ const u8 = toU8(input);
5802
+ const view = new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
5803
+ const eocdOff = findEOCDOffset(u8);
5804
+ const { value: eocd } = readStruct(view, eocdOff, SCHEMA.EOCD);
5805
+ ensureSig(eocd.signature, SIG.EOCD, "EOCD");
5806
+ if (eocd.commentLen !== 0) throw new Error("Unsupported: EOCD comment");
5807
+ if (eocd.diskNum !== 0 || eocd.cdStartDisk !== 0)
5808
+ throw new Error("Unsupported: multi-disk");
5809
+ const entries = [];
5810
+ let cdPtr = eocd.cdOffset;
5811
+ for (let i = 0; i < eocd.cdRecordsTotal; i++) {
5812
+ const { value: cdf, offset: next } = readStruct(
5813
+ view,
5814
+ cdPtr,
5815
+ SCHEMA.CentralFile
5816
+ );
5817
+ ensureSig(cdf.signature, SIG.CentralFile, "Central Directory");
5818
+ const name = new TextDecoder().decode(cdf.name);
5819
+ const isDir = (cdf.extAttrs & 16) !== 0 || name.endsWith("/");
5820
+ if (cdf.extraLen !== 0 || cdf.commentLen !== 0)
5821
+ throw new Error("Unsupported: extra/comment in central dir");
5822
+ entries.push({
5823
+ name,
5824
+ isDirectory: isDir,
5825
+ crc32: cdf.crc32 >>> 0,
5826
+ size: cdf.uncompSize >>> 0,
5827
+ compSize: cdf.compSize >>> 0,
5828
+ time: cdf.time >>> 0,
5829
+ dosDate: cdf.date >>> 0,
5830
+ localHeaderOffset: cdf.localHeaderOffset >>> 0
5831
+ });
5832
+ cdPtr = next;
5833
+ }
5834
+ const results = [];
5835
+ for (const e of entries) {
5836
+ const { value: lfh, offset: afterHeader } = readStruct(
5837
+ view,
5838
+ e.localHeaderOffset,
5839
+ SCHEMA.LocalFile
5840
+ );
5841
+ ensureSig(lfh.signature, SIG.LocalFile, "Local File");
5842
+ if (lfh.flags !== 2048)
5843
+ throw new Error("Unsupported: flags (expect UTF-8 only)");
5844
+ if (lfh.method !== 0)
5845
+ throw new Error("Unsupported: compression (expect store only)");
5846
+ if (lfh.extraLen !== 0)
5847
+ throw new Error("Unsupported: extra fields in local header");
5848
+ const dataStart = afterHeader;
5849
+ const dataEnd = dataStart + lfh.compSize;
5850
+ const data = e.isDirectory ? new Uint8Array(0) : new Uint8Array(u8.subarray(dataStart, dataEnd));
5851
+ results.push({ ...e, data });
5852
+ }
5853
+ return results;
5854
+ }
5855
+ // Quick utility: return a map of file data (directories omitted)
5856
+ static extract(input) {
5857
+ const entries = this.parse(input);
5858
+ const out = {};
5859
+ for (const e of entries) if (!e.isDirectory) out[e.name] = e.data;
5860
+ return out;
5861
+ }
5862
+ };
5863
+ function toU8(input) {
5864
+ if (typeof input === "string") return utf8(input);
5865
+ if (input instanceof Uint8Array) return input;
5866
+ return new Uint8Array(input);
5867
+ }
5868
+ function findEOCDOffset(u8) {
5869
+ const view = new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
5870
+ const minSize = 22;
5871
+ if (u8.length >= minSize) {
5872
+ const at = u8.length - minSize;
5873
+ if (view.getUint32(at, true) === SIG.EOCD) return at;
5874
+ }
5875
+ const start = Math.max(0, u8.length - 1024);
5876
+ for (let i = u8.length - 4; i >= start; i--) {
5877
+ if (view.getUint32(i, true) === SIG.EOCD) return i;
5878
+ }
5879
+ throw new Error("EOCD not found");
4082
5880
  }
4083
5881
 
4084
- // src/inspector/StateInspector.tsx
4085
- var lightTheme = {
4086
- ...chromeLight,
4087
- BASE_BACKGROUND_COLOR: "transparent",
4088
- OBJECT_NAME_COLOR: "rgba(0,0,0,0.7)"
4089
- };
4090
- var darkTheme = {
4091
- ...chromeDark,
4092
- BASE_BACKGROUND_COLOR: "transparent",
4093
- OBJECT_NAME_COLOR: "rgba(255,255,255,0.7)"
4094
- };
4095
- var styles = {
4096
- sectionInner: {
4097
- flex: "1 1 0",
4098
- overflowY: "auto",
4099
- overflowX: "hidden",
4100
- display: "flex",
4101
- flexDirection: "column"
5882
+ // src/inspector/serialization.ts
5883
+ async function fetchAssetMap(assets) {
5884
+ const res = await Promise.all(
5885
+ assets.map(async (asset) => {
5886
+ const url = asset.url;
5887
+ const response = await fetch(url);
5888
+ const data = await response.arrayBuffer();
5889
+ return [asset.id, data];
5890
+ })
5891
+ );
5892
+ return Object.fromEntries(res);
5893
+ }
5894
+ async function exportAll(noyaManager) {
5895
+ const { multiplayerStateManager, assetManager } = noyaManager;
5896
+ const assetMap = await fetchAssetMap(assetManager.assets$.get());
5897
+ return encodeAll({
5898
+ state: multiplayerStateManager.optimisticState$.get(),
5899
+ schema: multiplayerStateManager.schema,
5900
+ assets: assetManager.assets$.get(),
5901
+ assetMap
5902
+ });
5903
+ }
5904
+ function encodeAll({
5905
+ state,
5906
+ schema,
5907
+ assets,
5908
+ assetMap
5909
+ }) {
5910
+ const zip = new TinyZip();
5911
+ zip.addFile("state.json", JSON.stringify(state, null, 2));
5912
+ if (schema) {
5913
+ const encodedSchema = encodeSchema(schema);
5914
+ zip.addFile("schema.json", JSON.stringify(encodedSchema, null, 2));
4102
5915
  }
4103
- };
4104
- function ToggleButton({
5916
+ if (assets.length) {
5917
+ zip.addFile("assets.json", JSON.stringify(assets, null, 2));
5918
+ }
5919
+ for (const [id, data] of Object.entries(assetMap)) {
5920
+ zip.addFile(`assets/${id}`, data);
5921
+ }
5922
+ return zip.finish();
5923
+ }
5924
+ async function importAll(buffer, noyaManager, {
5925
+ shouldAllowSchemaChange
5926
+ } = {}) {
5927
+ let { state, schema, assets, assetMap } = await decodeAll(buffer);
5928
+ if (shouldAllowSchemaChange && noyaManager.options.schema && schema) {
5929
+ const oldSchemaHash = createHash(noyaManager.options.schema);
5930
+ const newSchemaHash = createHash(schema);
5931
+ if (oldSchemaHash !== newSchemaHash) {
5932
+ const shouldAllow = shouldAllowSchemaChange({
5933
+ oldSchema: noyaManager.options.schema,
5934
+ newSchema: schema
5935
+ });
5936
+ if (!shouldAllow) {
5937
+ throw new Error("Schema change not allowed");
5938
+ }
5939
+ }
5940
+ }
5941
+ if (assets.length) {
5942
+ await Promise.all(
5943
+ noyaManager.assetManager.assets$.get().map((asset) => noyaManager.assetManager.delete(asset.id))
5944
+ );
5945
+ const idPairs = await Promise.all(
5946
+ assets.map(async (asset) => {
5947
+ const newAsset = await noyaManager.assetManager.create({
5948
+ data: assetMap[asset.id],
5949
+ contentType: asset.contentType
5950
+ });
5951
+ return [asset.id, newAsset.id];
5952
+ })
5953
+ );
5954
+ const replacementMap = Object.fromEntries(idPairs);
5955
+ state = replaceDeep(state, replacementMap);
5956
+ }
5957
+ noyaManager.initialState = state;
5958
+ noyaManager.forceInit();
5959
+ }
5960
+ function decodeAll(buffer) {
5961
+ const zip = TinyZip.extract(buffer);
5962
+ const stateFile = zip["state.json"];
5963
+ const schemaFile = zip["schema.json"];
5964
+ const assetsFile = zip["assets.json"];
5965
+ if (!stateFile) {
5966
+ throw new Error("State file not found");
5967
+ }
5968
+ const state = JSON.parse(new TextDecoder().decode(stateFile));
5969
+ let schema;
5970
+ if (schemaFile) {
5971
+ const encodedSchema = JSON.parse(new TextDecoder().decode(schemaFile));
5972
+ schema = decodeSchema(encodedSchema);
5973
+ }
5974
+ let assets = [];
5975
+ let assetMap = {};
5976
+ if (assetsFile) {
5977
+ assets = JSON.parse(new TextDecoder().decode(assetsFile));
5978
+ for (const asset of assets) {
5979
+ const data = zip[`assets/${asset.id}`];
5980
+ if (!data) {
5981
+ throw new Error(`Asset ${asset.id} not found`);
5982
+ }
5983
+ assetMap[asset.id] = data;
5984
+ }
5985
+ }
5986
+ return { state, schema, assets, assetMap };
5987
+ }
5988
+ function replaceDeep(obj, replacementMap) {
5989
+ switch (typeof obj) {
5990
+ case "object":
5991
+ if (obj === null) {
5992
+ return obj;
5993
+ }
5994
+ if (Array.isArray(obj)) {
5995
+ return obj.map((item) => replaceDeep(item, replacementMap));
5996
+ }
5997
+ return Object.fromEntries(
5998
+ Object.entries(obj).map(([key, value]) => [
5999
+ key,
6000
+ replaceDeep(value, replacementMap)
6001
+ ])
6002
+ );
6003
+ case "string":
6004
+ return replacementMap[obj] ?? obj;
6005
+ default:
6006
+ return obj;
6007
+ }
6008
+ }
6009
+
6010
+ // src/inspector/StateInspectorTitleLabel.tsx
6011
+ import React11 from "react";
6012
+ function StateInspectorTitleLabel({
6013
+ children
6014
+ }) {
6015
+ return /* @__PURE__ */ React11.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
6016
+ }
6017
+
6018
+ // src/inspector/StateInspectorToggleButton.tsx
6019
+ import React12 from "react";
6020
+ function StateInspectorToggleButton({
4105
6021
  showInspector,
4106
6022
  setShowInspector,
4107
6023
  theme,
4108
6024
  anchor
4109
6025
  }) {
4110
6026
  const isRightAnchor = anchor === "right";
4111
- const rightIcon = /* @__PURE__ */ React3.createElement(
6027
+ const rightIcon = /* @__PURE__ */ React12.createElement(
4112
6028
  "svg",
4113
6029
  {
4114
6030
  xmlns: "http://www.w3.org/2000/svg",
@@ -4118,7 +6034,7 @@ function ToggleButton({
4118
6034
  stroke: "currentColor",
4119
6035
  className: "size-6"
4120
6036
  },
4121
- /* @__PURE__ */ React3.createElement(
6037
+ /* @__PURE__ */ React12.createElement(
4122
6038
  "path",
4123
6039
  {
4124
6040
  strokeLinecap: "round",
@@ -4127,7 +6043,7 @@ function ToggleButton({
4127
6043
  }
4128
6044
  )
4129
6045
  );
4130
- const leftIcon = /* @__PURE__ */ React3.createElement(
6046
+ const leftIcon = /* @__PURE__ */ React12.createElement(
4131
6047
  "svg",
4132
6048
  {
4133
6049
  xmlns: "http://www.w3.org/2000/svg",
@@ -4137,7 +6053,7 @@ function ToggleButton({
4137
6053
  stroke: "currentColor",
4138
6054
  className: "size-6"
4139
6055
  },
4140
- /* @__PURE__ */ React3.createElement(
6056
+ /* @__PURE__ */ React12.createElement(
4141
6057
  "path",
4142
6058
  {
4143
6059
  strokeLinecap: "round",
@@ -4146,7 +6062,7 @@ function ToggleButton({
4146
6062
  }
4147
6063
  )
4148
6064
  );
4149
- return /* @__PURE__ */ React3.createElement(
6065
+ return /* @__PURE__ */ React12.createElement(
4150
6066
  "span",
4151
6067
  {
4152
6068
  role: "button",
@@ -4167,103 +6083,34 @@ function ToggleButton({
4167
6083
  setShowInspector(!showInspector);
4168
6084
  }
4169
6085
  },
4170
- showInspector ? "Hide Inspector" : /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, isRightAnchor ? rightIcon : leftIcon)
4171
- );
4172
- }
4173
- function DisclosureSection({
4174
- open,
4175
- setOpen,
4176
- title,
4177
- right,
4178
- children,
4179
- colorScheme,
4180
- isFirst,
4181
- style
4182
- }) {
4183
- const theme = colorScheme === "light" ? lightTheme : darkTheme;
4184
- const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
4185
- return /* @__PURE__ */ React3.createElement(
4186
- "div",
4187
- {
4188
- style: {
4189
- flex: open ? "1 1 0" : "0",
4190
- display: "flex",
4191
- flexDirection: "column",
4192
- ...style
4193
- }
4194
- },
4195
- /* @__PURE__ */ React3.createElement(
4196
- "div",
4197
- {
4198
- onClick: () => setOpen?.(!open),
4199
- style: {
4200
- cursor: "default",
4201
- fontSize: "12px",
4202
- padding: "4px 10px",
4203
- display: "flex",
4204
- alignItems: "center",
4205
- ...!isFirst && { borderTop: `1px solid ${borderColor}` },
4206
- ...open && { borderBottom: `1px solid ${borderColor}` }
4207
- }
4208
- },
4209
- setOpen && /* @__PURE__ */ React3.createElement(
4210
- Arrow,
4211
- {
4212
- expanded: open,
4213
- style: {
4214
- fontSize: theme.ARROW_FONT_SIZE,
4215
- marginRight: theme.ARROW_MARGIN_RIGHT + 1,
4216
- color: theme.ARROW_COLOR
4217
- }
4218
- }
4219
- ),
4220
- /* @__PURE__ */ React3.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
4221
- right
4222
- ),
4223
- open && children
6086
+ showInspector ? "Hide Inspector" : /* @__PURE__ */ React12.createElement("span", { style: { width: "12px", height: "12px" } }, isRightAnchor ? rightIcon : leftIcon)
4224
6087
  );
4225
6088
  }
4226
- function InspectorRow({
4227
- children,
4228
- colorScheme,
4229
- selected,
4230
- style,
4231
- variant
4232
- }) {
4233
- const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
4234
- return /* @__PURE__ */ React3.createElement(
4235
- "div",
4236
- {
4237
- style: {
4238
- borderBottom: `1px solid ${solidBorderColor}`,
4239
- fontSize: "12px",
4240
- fontFamily: "Menlo, monospace",
4241
- padding: "2px 12px 1px",
4242
- display: "flex",
4243
- alignItems: "center",
4244
- background: variant === "up" ? "rgba(0,255,0,0.1)" : variant === "down" ? "transparent" : selected ? "rgb(59 130 246 / 15%)" : void 0,
4245
- // background:
4246
- // colorScheme === "light"
4247
- // ? "rgba(0,0,0,0.05)"
4248
- // : "rgba(255,255,255,0.05)",
4249
- ...style
6089
+
6090
+ // src/inspector/useLocalStorageState.tsx
6091
+ import React13 from "react";
6092
+ var localStorage = typeof window !== "undefined" ? window.localStorage : null;
6093
+ function useLocalStorageState(key, defaultValue) {
6094
+ const [state, setState] = React13.useState(() => {
6095
+ const value = localStorage?.getItem(key);
6096
+ let result = defaultValue;
6097
+ if (value) {
6098
+ try {
6099
+ result = JSON.parse(value);
6100
+ } catch (error) {
6101
+ console.error("Error parsing localStorage value", error);
4250
6102
  }
4251
- },
4252
- /* @__PURE__ */ React3.createElement(
4253
- "span",
4254
- {
4255
- style: {
4256
- fontFamily: "Menlo, monospace",
4257
- fontSize: "11px",
4258
- borderRadius: 4,
4259
- display: "inline-block"
4260
- }
4261
- },
4262
- children
4263
- )
4264
- );
6103
+ }
6104
+ return result;
6105
+ });
6106
+ const setLocalStorageState = (value) => {
6107
+ localStorage?.setItem(key, JSON.stringify(value));
6108
+ setState(value);
6109
+ };
6110
+ return [state, setLocalStorageState];
4265
6111
  }
4266
- var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
6112
+
6113
+ // src/inspector/StateInspector.tsx
4267
6114
  var StateInspector = memoGeneric(function StateInspector2({
4268
6115
  noyaManager,
4269
6116
  colorScheme = "light",
@@ -4279,17 +6126,19 @@ var StateInspector = memoGeneric(function StateInspector2({
4279
6126
  ephemeralUserDataManager,
4280
6127
  connectionEventManager,
4281
6128
  taskManager,
4282
- ioManager
6129
+ ioManager,
6130
+ resourceManager,
6131
+ activityEventsManager
4283
6132
  } = noyaManager;
4284
- const [didMount, setDidMount] = React3.useState(false);
6133
+ const [didMount, setDidMount] = React14.useState(false);
4285
6134
  const tasks = useObservable(taskManager.tasks$);
4286
6135
  const inputs = useObservable(ioManager.inputs$);
4287
6136
  const outputTransforms = useObservable(ioManager.outputTransforms$);
4288
6137
  useLayoutEffect(() => {
4289
6138
  setDidMount(true);
4290
6139
  }, []);
4291
- const eventsContainerRef = React3.useRef(null);
4292
- const historyContainerRef = React3.useRef(null);
6140
+ const eventsContainerRef = React14.useRef(null);
6141
+ const activityEventsContainerRef = React14.useRef(null);
4293
6142
  const [showInspector, setShowInspector] = useLocalStorageState(
4294
6143
  "noya-multiplayer-react-show-inspector",
4295
6144
  true
@@ -4322,6 +6171,10 @@ var StateInspector = memoGeneric(function StateInspector2({
4322
6171
  "noya-multiplayer-react-show-assets",
4323
6172
  false
4324
6173
  );
6174
+ const [showResources, setShowResources] = useLocalStorageState(
6175
+ "noya-multiplayer-react-show-resources",
6176
+ false
6177
+ );
4325
6178
  const [showSecrets, setShowSecrets] = useLocalStorageState(
4326
6179
  "noya-multiplayer-react-show-secrets",
4327
6180
  false
@@ -4334,8 +6187,12 @@ var StateInspector = memoGeneric(function StateInspector2({
4334
6187
  "noya-multiplayer-react-show-output-transforms",
4335
6188
  false
4336
6189
  );
6190
+ const [showActivityEvents, setShowActivityEvents] = useLocalStorageState(
6191
+ "noya-multiplayer-react-show-activity-events",
6192
+ false
6193
+ );
4337
6194
  const connectionEvents = useObservable(connectionEventManager.events$);
4338
- useEffect(() => {
6195
+ useEffect2(() => {
4339
6196
  if (eventsContainerRef.current) {
4340
6197
  eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
4341
6198
  }
@@ -4346,6 +6203,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4346
6203
  const ephemeral = useObservable(ephemeralUserDataManager.data$);
4347
6204
  const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
4348
6205
  const assets = useObservable(assetManager.assets$);
6206
+ const resources = useObservable(resourceManager.resources$);
6207
+ const resourcesInitialized = useObservable(resourceManager.isInitialized$);
4349
6208
  const assetsInitialized = useObservable(assetManager.isInitialized$);
4350
6209
  const secrets = useObservable(secretManager.secrets$);
4351
6210
  const secretsInitialized = useObservable(secretManager.isInitialized$);
@@ -4356,25 +6215,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4356
6215
  const outputTransformsInitialized = useObservable(
4357
6216
  ioManager.outputTransformsInitialized$
4358
6217
  );
4359
- useEffect(() => {
4360
- if (historyContainerRef.current) {
4361
- historyContainerRef.current.scrollTop = historyContainerRef.current.scrollHeight;
4362
- }
4363
- }, [historySnapshot]);
4364
- useEffect(() => {
4365
- if (!historyContainerRef.current) return;
4366
- const historyEntry = historyContainerRef.current.querySelector(
4367
- `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
4368
- );
4369
- if (historyEntry) {
4370
- historyEntry.scrollIntoView({
4371
- block: "nearest",
4372
- inline: "nearest"
4373
- });
4374
- }
4375
- }, [historySnapshot.historyIndex]);
4376
- const theme = colorScheme === "light" ? lightTheme : darkTheme;
4377
- const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
6218
+ const theme = getStateInspectorTheme(colorScheme);
6219
+ const solidBorderColor = getStateInspectorBorderColor(colorScheme);
4378
6220
  const baseStyle = {
4379
6221
  position: "fixed",
4380
6222
  top: 12,
@@ -4394,9 +6236,24 @@ var StateInspector = memoGeneric(function StateInspector2({
4394
6236
  zIndex: 9999,
4395
6237
  lineHeight: "13px"
4396
6238
  };
6239
+ const handleExportAll = useCallback(async () => {
6240
+ const buffer = await exportAll(noyaManager);
6241
+ downloadBlob(new Blob([buffer]), "state.zip");
6242
+ }, [noyaManager]);
6243
+ const handleImportAll = useCallback(async () => {
6244
+ const file = await uploadFile();
6245
+ const buffer = await file.arrayBuffer();
6246
+ importAll(buffer, noyaManager, {
6247
+ shouldAllowSchemaChange: () => {
6248
+ return confirm(
6249
+ `The imported state uses a different schema than the schema this app expects. Do you want to continue?`
6250
+ );
6251
+ }
6252
+ });
6253
+ }, [noyaManager]);
4397
6254
  if (!didMount) return null;
4398
6255
  if (!showInspector) {
4399
- return /* @__PURE__ */ React3.createElement(
6256
+ return /* @__PURE__ */ React14.createElement(
4400
6257
  "div",
4401
6258
  {
4402
6259
  ...props,
@@ -4408,8 +6265,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4408
6265
  },
4409
6266
  onClick: () => setShowInspector(true)
4410
6267
  },
4411
- /* @__PURE__ */ React3.createElement(
4412
- ToggleButton,
6268
+ /* @__PURE__ */ React14.createElement(
6269
+ StateInspectorToggleButton,
4413
6270
  {
4414
6271
  showInspector,
4415
6272
  setShowInspector,
@@ -4419,7 +6276,7 @@ var StateInspector = memoGeneric(function StateInspector2({
4419
6276
  )
4420
6277
  );
4421
6278
  }
4422
- return /* @__PURE__ */ React3.createElement(
6279
+ return /* @__PURE__ */ React14.createElement(
4423
6280
  "div",
4424
6281
  {
4425
6282
  ...props,
@@ -4428,8 +6285,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4428
6285
  ...props.style
4429
6286
  }
4430
6287
  },
4431
- /* @__PURE__ */ React3.createElement(
4432
- DisclosureSection,
6288
+ /* @__PURE__ */ React14.createElement(
6289
+ StateInspectorDisclosureSection,
4433
6290
  {
4434
6291
  isFirst: true,
4435
6292
  open: showUsers,
@@ -4440,8 +6297,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4440
6297
  flex: "0 0 auto",
4441
6298
  maxHeight: "200px"
4442
6299
  },
4443
- right: /* @__PURE__ */ React3.createElement(
4444
- ToggleButton,
6300
+ right: /* @__PURE__ */ React14.createElement(
6301
+ StateInspectorToggleButton,
4445
6302
  {
4446
6303
  showInspector,
4447
6304
  setShowInspector,
@@ -4450,14 +6307,14 @@ var StateInspector = memoGeneric(function StateInspector2({
4450
6307
  }
4451
6308
  )
4452
6309
  },
4453
- /* @__PURE__ */ React3.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React3.createElement(
4454
- InspectorRow,
6310
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, { style: { flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React14.createElement(
6311
+ StateInspectorRow,
4455
6312
  {
4456
6313
  key: user.id,
4457
6314
  colorScheme,
4458
6315
  variant: user.id === userId ? "up" : void 0
4459
6316
  },
4460
- user.image && /* @__PURE__ */ React3.createElement(
6317
+ user.image && /* @__PURE__ */ React14.createElement(
4461
6318
  "img",
4462
6319
  {
4463
6320
  src: user.image,
@@ -4478,7 +6335,7 @@ var StateInspector = memoGeneric(function StateInspector2({
4478
6335
  " (",
4479
6336
  ellipsis(user.id.toString(), 8, "middle"),
4480
6337
  ")"
4481
- )), !connectedUsers && /* @__PURE__ */ React3.createElement(
6338
+ )), !connectedUsers && /* @__PURE__ */ React14.createElement(
4482
6339
  "div",
4483
6340
  {
4484
6341
  style: {
@@ -4489,13 +6346,13 @@ var StateInspector = memoGeneric(function StateInspector2({
4489
6346
  gap: "4px"
4490
6347
  }
4491
6348
  },
4492
- /* @__PURE__ */ React3.createElement("span", null, "No connected users")
6349
+ /* @__PURE__ */ React14.createElement("span", null, "No connected users")
4493
6350
  ))
4494
6351
  ),
4495
- /* @__PURE__ */ React3.createElement(
4496
- DisclosureSection,
6352
+ /* @__PURE__ */ React14.createElement(
6353
+ StateInspectorDisclosureSection,
4497
6354
  {
4498
- title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Data", /* @__PURE__ */ React3.createElement(
6355
+ title: /* @__PURE__ */ React14.createElement(StateInspectorTitleLabel, null, "Data", /* @__PURE__ */ React14.createElement(
4499
6356
  ColoredDot,
4500
6357
  {
4501
6358
  type: multipeerStateInitialized ? "success" : "error"
@@ -4504,16 +6361,18 @@ var StateInspector = memoGeneric(function StateInspector2({
4504
6361
  colorScheme,
4505
6362
  setOpen: setShowData,
4506
6363
  open: showData,
4507
- right: /* @__PURE__ */ React3.createElement(
6364
+ right: /* @__PURE__ */ React14.createElement(
4508
6365
  "span",
4509
6366
  {
4510
6367
  style: {
4511
6368
  display: "flex",
4512
- gap: "4px"
6369
+ gap: "12px"
4513
6370
  }
4514
6371
  },
4515
- /* @__PURE__ */ React3.createElement(
4516
- SmallButton,
6372
+ /* @__PURE__ */ React14.createElement(StateInspectorButton, { theme, onClick: handleImportAll }, "Import"),
6373
+ /* @__PURE__ */ React14.createElement(StateInspectorButton, { theme, onClick: handleExportAll }, "Export"),
6374
+ /* @__PURE__ */ React14.createElement(
6375
+ StateInspectorButton,
4517
6376
  {
4518
6377
  theme,
4519
6378
  onClick: () => {
@@ -4524,167 +6383,56 @@ var StateInspector = memoGeneric(function StateInspector2({
4524
6383
  )
4525
6384
  )
4526
6385
  },
4527
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
4528
- ObjectInspector,
6386
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, /* @__PURE__ */ React14.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React14.createElement(
6387
+ ObjectInspector4,
4529
6388
  {
4530
6389
  name: multiplayerStateManager.schema ? "state" : void 0,
4531
6390
  data: state,
4532
6391
  theme
4533
6392
  }
4534
- )), multiplayerStateManager.schema && /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
4535
- ObjectInspector,
4536
- {
4537
- name: "schema",
4538
- data: multiplayerStateManager.schema,
4539
- theme
4540
- }
4541
- )))
4542
- ),
4543
- /* @__PURE__ */ React3.createElement(
4544
- DisclosureSection,
4545
- {
4546
- open: showHistory,
4547
- setOpen: setShowHistory,
4548
- title: "History",
4549
- colorScheme,
4550
- right: /* @__PURE__ */ React3.createElement(
4551
- "span",
4552
- {
4553
- style: {
4554
- display: "flex",
4555
- gap: "4px"
4556
- }
4557
- },
4558
- /* @__PURE__ */ React3.createElement(
4559
- SmallButton,
4560
- {
4561
- disabled: !historySnapshot.canUndo,
4562
- theme,
4563
- onClick: () => {
4564
- multiplayerStateManager.undo();
4565
- }
4566
- },
4567
- /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
4568
- "svg",
4569
- {
4570
- xmlns: "http://www.w3.org/2000/svg",
4571
- width: "1em",
4572
- height: "1em",
4573
- viewBox: "0 0 20 20"
4574
- },
4575
- /* @__PURE__ */ React3.createElement(
4576
- "path",
4577
- {
4578
- fill: "currentColor",
4579
- d: "M12 5H7V2L1 6l6 4V7h5c2.2 0 4 1.8 4 4s-1.8 4-4 4H7v2h5c3.3 0 6-2.7 6-6s-2.7-6-6-6"
4580
- }
4581
- )
4582
- ))
4583
- ),
4584
- /* @__PURE__ */ React3.createElement(
4585
- SmallButton,
4586
- {
4587
- disabled: !historySnapshot.canRedo,
4588
- theme,
4589
- onClick: () => {
4590
- multiplayerStateManager.redo();
4591
- }
4592
- },
4593
- /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
4594
- "svg",
4595
- {
4596
- xmlns: "http://www.w3.org/2000/svg",
4597
- width: "1em",
4598
- height: "1em",
4599
- viewBox: "0 0 20 20"
4600
- },
4601
- /* @__PURE__ */ React3.createElement(
4602
- "path",
4603
- {
4604
- fill: "currentColor",
4605
- d: "M8 5h5V2l6 4l-6 4V7H8c-2.2 0-4 1.8-4 4s1.8 4 4 4h5v2H8c-3.3 0-6-2.7-6-6s2.7-6 6-6"
4606
- }
4607
- )
4608
- ))
4609
- )
4610
- )
4611
- },
4612
- /* @__PURE__ */ React3.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(
4613
- "div",
4614
- {
4615
- id: `${HISTORY_ELEMENT_PREFIX}0`,
4616
- style: {
4617
- borderBottom: `1px solid ${solidBorderColor}`,
4618
- fontSize: "12px",
4619
- fontFamily: "Menlo, monospace",
4620
- padding: "2px 12px 1px",
4621
- display: "flex",
4622
- alignItems: "center",
4623
- background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
4624
- }
4625
- },
4626
- /* @__PURE__ */ React3.createElement(
4627
- "span",
4628
- {
4629
- style: {
4630
- fontFamily: "Menlo, monospace",
4631
- fontSize: "11px",
4632
- borderRadius: 4,
4633
- display: "inline-block"
4634
- }
4635
- },
4636
- "Initial state"
4637
- )
4638
- ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ React3.createElement(
4639
- "div",
4640
- {
4641
- id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
4642
- key: index,
4643
- style: {
4644
- padding: "0px 12px 1px",
4645
- borderBottom: `1px solid ${solidBorderColor}`,
4646
- background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
4647
- }
4648
- },
4649
- "name" in entry.metadata && typeof entry.metadata.name === "string" && /* @__PURE__ */ React3.createElement(
4650
- "pre",
4651
- {
4652
- style: {
4653
- fontSize: "11px",
4654
- display: "flex",
4655
- flexWrap: "wrap",
4656
- margin: 0
4657
- }
4658
- },
4659
- entry.metadata.name
4660
- ),
4661
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React3.createElement(
4662
- "pre",
4663
- {
4664
- key: j,
4665
- style: {
4666
- fontSize: "11px",
4667
- display: "flex",
4668
- flexWrap: "wrap",
4669
- margin: 0
4670
- }
4671
- },
4672
- patch.op === "add" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React3.createElement(ObjectInspector, { data: patch.value, theme })),
4673
- patch.op === "replace" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React3.createElement(ObjectInspector, { data: patch.value, theme })),
4674
- patch.op === "remove" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
4675
- patch.op === "move" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
4676
- ))
6393
+ )), multiplayerStateManager.schema && /* @__PURE__ */ React14.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React14.createElement(
6394
+ ObjectInspector4,
6395
+ {
6396
+ name: "schema",
6397
+ data: multiplayerStateManager.schema,
6398
+ theme
6399
+ }
4677
6400
  )))
4678
6401
  ),
4679
- /* @__PURE__ */ React3.createElement(
4680
- DisclosureSection,
6402
+ /* @__PURE__ */ React14.createElement(
6403
+ HistorySection,
6404
+ {
6405
+ showHistory,
6406
+ setShowHistory,
6407
+ colorScheme,
6408
+ historySnapshot,
6409
+ multiplayerStateManager
6410
+ }
6411
+ ),
6412
+ /* @__PURE__ */ React14.createElement(
6413
+ StateInspectorDisclosureSection,
4681
6414
  {
4682
6415
  open: showAssets,
4683
6416
  setOpen: setShowAssets,
4684
- title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Assets", /* @__PURE__ */ React3.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
6417
+ title: /* @__PURE__ */ React14.createElement(StateInspectorTitleLabel, null, "Assets (", assets.length, ")", /* @__PURE__ */ React14.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
4685
6418
  colorScheme,
4686
- right: /* @__PURE__ */ React3.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React3.createElement(
4687
- SmallButton,
6419
+ right: /* @__PURE__ */ React14.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React14.createElement(
6420
+ StateInspectorButton,
6421
+ {
6422
+ theme,
6423
+ onClick: async () => {
6424
+ const ok = confirm(
6425
+ "Are you sure you want to delete all assets?"
6426
+ );
6427
+ if (!ok) return;
6428
+ await Promise.all(
6429
+ assets.map((asset) => assetManager.delete(asset.id))
6430
+ );
6431
+ }
6432
+ },
6433
+ "Delete all"
6434
+ ), /* @__PURE__ */ React14.createElement(
6435
+ StateInspectorButton,
4688
6436
  {
4689
6437
  theme,
4690
6438
  onClick: () => {
@@ -4696,8 +6444,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4696
6444
  }
4697
6445
  },
4698
6446
  "Reload"
4699
- ), /* @__PURE__ */ React3.createElement(
4700
- SmallButton,
6447
+ ), /* @__PURE__ */ React14.createElement(
6448
+ StateInspectorButton,
4701
6449
  {
4702
6450
  theme,
4703
6451
  onClick: () => {
@@ -4720,8 +6468,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4720
6468
  "Upload"
4721
6469
  ))
4722
6470
  },
4723
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, assets.map((asset) => /* @__PURE__ */ React3.createElement(InspectorRow, { key: asset.id, colorScheme }, /* @__PURE__ */ React3.createElement(ObjectInspector, { name: asset.id, data: asset, theme }), /* @__PURE__ */ React3.createElement(
4724
- SmallButton,
6471
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, assets.map((asset) => /* @__PURE__ */ React14.createElement(StateInspectorRow, { key: asset.id, colorScheme }, /* @__PURE__ */ React14.createElement(ObjectInspector4, { name: asset.id, data: asset, theme }), /* @__PURE__ */ React14.createElement(
6472
+ StateInspectorButton,
4725
6473
  {
4726
6474
  theme,
4727
6475
  onClick: () => assetManager.delete(asset.id)
@@ -4729,15 +6477,99 @@ var StateInspector = memoGeneric(function StateInspector2({
4729
6477
  "Delete"
4730
6478
  ))))
4731
6479
  ),
4732
- /* @__PURE__ */ React3.createElement(
4733
- DisclosureSection,
6480
+ /* @__PURE__ */ React14.createElement(
6481
+ StateInspectorDisclosureSection,
6482
+ {
6483
+ title: /* @__PURE__ */ React14.createElement(StateInspectorTitleLabel, null, "Resources (", resources.length, ")", /* @__PURE__ */ React14.createElement(ColoredDot, { type: resourcesInitialized ? "success" : "error" })),
6484
+ colorScheme,
6485
+ open: showResources,
6486
+ setOpen: setShowResources,
6487
+ right: /* @__PURE__ */ React14.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React14.createElement(
6488
+ StateInspectorButton,
6489
+ {
6490
+ theme,
6491
+ onClick: async () => {
6492
+ const ok = confirm(
6493
+ "Are you sure you want to delete all resources?"
6494
+ );
6495
+ if (!ok) return;
6496
+ await Promise.all(
6497
+ resources.map(
6498
+ (resource) => resourceManager.deleteResource({ id: resource.id })
6499
+ )
6500
+ );
6501
+ }
6502
+ },
6503
+ "Delete all"
6504
+ ), /* @__PURE__ */ React14.createElement(
6505
+ StateInspectorButton,
6506
+ {
6507
+ theme,
6508
+ onClick: async () => {
6509
+ const path2 = prompt("Enter directory path") || uuid();
6510
+ await resourceManager.createResource({
6511
+ type: "directory",
6512
+ path: path2
6513
+ });
6514
+ }
6515
+ },
6516
+ "Create Directory"
6517
+ ), /* @__PURE__ */ React14.createElement(
6518
+ StateInspectorButton,
6519
+ {
6520
+ theme,
6521
+ onClick: async () => {
6522
+ const file = await uploadFile();
6523
+ resourceManager.createResource({
6524
+ type: "asset",
6525
+ path: file.name || uuid(),
6526
+ asset: {
6527
+ content: Base64.encode(await file.arrayBuffer()),
6528
+ contentType: file.type,
6529
+ encoding: "base64"
6530
+ }
6531
+ });
6532
+ }
6533
+ },
6534
+ "Create Asset"
6535
+ ))
6536
+ },
6537
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, resources?.map((resource) => /* @__PURE__ */ React14.createElement(StateInspectorRow, { key: resource.id, colorScheme }, /* @__PURE__ */ React14.createElement(
6538
+ ObjectInspector4,
6539
+ {
6540
+ name: resource.path,
6541
+ data: resource,
6542
+ theme
6543
+ }
6544
+ ), /* @__PURE__ */ React14.createElement("div", { style: { display: "flex", gap: "4px" } }, /* @__PURE__ */ React14.createElement(
6545
+ StateInspectorButton,
6546
+ {
6547
+ theme,
6548
+ onClick: () => resourceManager.deleteResource({ id: resource.id })
6549
+ },
6550
+ "Delete"
6551
+ ), /* @__PURE__ */ React14.createElement(
6552
+ StateInspectorButton,
6553
+ {
6554
+ theme,
6555
+ onClick: () => {
6556
+ const path2 = prompt("Enter new path", resource.path);
6557
+ if (!path2) return;
6558
+ resourceManager.updateResource({ id: resource.id, path: path2 });
6559
+ }
6560
+ },
6561
+ "Rename"
6562
+ )))))
6563
+ ),
6564
+ /* @__PURE__ */ React14.createElement(
6565
+ StateInspectorDisclosureSection,
4734
6566
  {
4735
- title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Secrets", /* @__PURE__ */ React3.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
6567
+ title: /* @__PURE__ */ React14.createElement(StateInspectorTitleLabel, null, "Secrets", /* @__PURE__ */ React14.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
4736
6568
  colorScheme,
4737
6569
  open: showSecrets,
4738
6570
  setOpen: setShowSecrets,
4739
- right: /* @__PURE__ */ React3.createElement(
4740
- SmallButton,
6571
+ right: /* @__PURE__ */ React14.createElement(
6572
+ StateInspectorButton,
4741
6573
  {
4742
6574
  theme,
4743
6575
  onClick: () => {
@@ -4751,8 +6583,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4751
6583
  "Create"
4752
6584
  )
4753
6585
  },
4754
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, secrets.map((secret) => /* @__PURE__ */ React3.createElement(InspectorRow, { key: secret.id, colorScheme }, /* @__PURE__ */ React3.createElement(ObjectInspector, { data: secret, theme }), /* @__PURE__ */ React3.createElement(
4755
- SmallButton,
6586
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, secrets.map((secret) => /* @__PURE__ */ React14.createElement(StateInspectorRow, { key: secret.id, colorScheme }, /* @__PURE__ */ React14.createElement(ObjectInspector4, { data: secret, theme }), /* @__PURE__ */ React14.createElement(
6587
+ StateInspectorButton,
4756
6588
  {
4757
6589
  theme,
4758
6590
  onClick: () => secretManager.deleteSecret(secret.id)
@@ -4761,15 +6593,15 @@ var StateInspector = memoGeneric(function StateInspector2({
4761
6593
  ))))
4762
6594
  ),
4763
6595
  " ",
4764
- /* @__PURE__ */ React3.createElement(
4765
- DisclosureSection,
6596
+ /* @__PURE__ */ React14.createElement(
6597
+ StateInspectorDisclosureSection,
4766
6598
  {
4767
6599
  open: showInputs,
4768
6600
  setOpen: setShowInputs,
4769
- title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Inputs", /* @__PURE__ */ React3.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
6601
+ title: /* @__PURE__ */ React14.createElement(StateInspectorTitleLabel, null, "Inputs", /* @__PURE__ */ React14.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
4770
6602
  colorScheme
4771
6603
  },
4772
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, inputs?.map((input) => /* @__PURE__ */ React3.createElement(InspectorRow, { key: input.id, colorScheme }, /* @__PURE__ */ React3.createElement(ObjectInspector, { data: input, theme }))), !inputs?.length && /* @__PURE__ */ React3.createElement(
6604
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, inputs?.map((input) => /* @__PURE__ */ React14.createElement(StateInspectorRow, { key: input.id, colorScheme }, /* @__PURE__ */ React14.createElement(ObjectInspector4, { data: input, theme }))), !inputs?.length && /* @__PURE__ */ React14.createElement(
4773
6605
  "div",
4774
6606
  {
4775
6607
  style: {
@@ -4780,15 +6612,15 @@ var StateInspector = memoGeneric(function StateInspector2({
4780
6612
  gap: "4px"
4781
6613
  }
4782
6614
  },
4783
- /* @__PURE__ */ React3.createElement("span", null, "No inputs")
6615
+ /* @__PURE__ */ React14.createElement("span", null, "No inputs")
4784
6616
  ))
4785
6617
  ),
4786
- /* @__PURE__ */ React3.createElement(
4787
- DisclosureSection,
6618
+ /* @__PURE__ */ React14.createElement(
6619
+ StateInspectorDisclosureSection,
4788
6620
  {
4789
6621
  open: showOutputTransforms,
4790
6622
  setOpen: setShowOutputTransforms,
4791
- title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Output Transforms", /* @__PURE__ */ React3.createElement(
6623
+ title: /* @__PURE__ */ React14.createElement(StateInspectorTitleLabel, null, "Output Transforms", /* @__PURE__ */ React14.createElement(
4792
6624
  ColoredDot,
4793
6625
  {
4794
6626
  type: outputTransformsInitialized ? "success" : "error"
@@ -4796,7 +6628,7 @@ var StateInspector = memoGeneric(function StateInspector2({
4796
6628
  )),
4797
6629
  colorScheme
4798
6630
  },
4799
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, outputTransforms?.map((transform) => /* @__PURE__ */ React3.createElement(InspectorRow, { key: transform.id, colorScheme }, /* @__PURE__ */ React3.createElement(ObjectInspector, { data: transform, theme }))), !outputTransforms?.length && /* @__PURE__ */ React3.createElement(
6631
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, outputTransforms?.map((transform) => /* @__PURE__ */ React14.createElement(StateInspectorRow, { key: transform.id, colorScheme }, /* @__PURE__ */ React14.createElement(ObjectInspector4, { data: transform, theme }))), !outputTransforms?.length && /* @__PURE__ */ React14.createElement(
4800
6632
  "div",
4801
6633
  {
4802
6634
  style: {
@@ -4807,19 +6639,19 @@ var StateInspector = memoGeneric(function StateInspector2({
4807
6639
  gap: "4px"
4808
6640
  }
4809
6641
  },
4810
- /* @__PURE__ */ React3.createElement("span", null, "No output transforms")
6642
+ /* @__PURE__ */ React14.createElement("span", null, "No output transforms")
4811
6643
  ))
4812
6644
  ),
4813
- /* @__PURE__ */ React3.createElement(
4814
- DisclosureSection,
6645
+ /* @__PURE__ */ React14.createElement(
6646
+ StateInspectorDisclosureSection,
4815
6647
  {
4816
6648
  title: "Tasks",
4817
6649
  colorScheme,
4818
6650
  open: showTasks,
4819
6651
  setOpen: setShowTasks
4820
6652
  },
4821
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ React3.createElement(
4822
- InspectorRow,
6653
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, tasks?.map((task) => /* @__PURE__ */ React14.createElement(
6654
+ StateInspectorRow,
4823
6655
  {
4824
6656
  key: task.id,
4825
6657
  colorScheme,
@@ -4827,8 +6659,8 @@ var StateInspector = memoGeneric(function StateInspector2({
4827
6659
  backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
4828
6660
  }
4829
6661
  },
4830
- /* @__PURE__ */ React3.createElement(
4831
- ObjectInspector,
6662
+ /* @__PURE__ */ React14.createElement(
6663
+ ObjectInspector4,
4832
6664
  {
4833
6665
  name: task.name,
4834
6666
  data: task.payload,
@@ -4837,16 +6669,16 @@ var StateInspector = memoGeneric(function StateInspector2({
4837
6669
  )
4838
6670
  )))
4839
6671
  ),
4840
- /* @__PURE__ */ React3.createElement(
4841
- DisclosureSection,
6672
+ /* @__PURE__ */ React14.createElement(
6673
+ StateInspectorDisclosureSection,
4842
6674
  {
4843
6675
  open: showEphemeral,
4844
6676
  setOpen: setShowEphemeral,
4845
6677
  title: "Ephemeral User Data",
4846
6678
  colorScheme
4847
6679
  },
4848
- /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React3.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ React3.createElement(
4849
- ObjectInspector,
6680
+ /* @__PURE__ */ React14.createElement(StateInspectorDisclosureRowInner, null, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React14.createElement(StateInspectorRow, { key, colorScheme }, /* @__PURE__ */ React14.createElement(
6681
+ ObjectInspector4,
4850
6682
  {
4851
6683
  name: key,
4852
6684
  data: value,
@@ -4855,188 +6687,28 @@ var StateInspector = memoGeneric(function StateInspector2({
4855
6687
  }
4856
6688
  ))))
4857
6689
  ),
4858
- /* @__PURE__ */ React3.createElement(
4859
- DisclosureSection,
4860
- {
4861
- open: showEvents,
4862
- setOpen: setShowEvents,
4863
- title: "Events",
4864
- colorScheme
4865
- },
4866
- /* @__PURE__ */ React3.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
4867
- (event, index) => event.type === "stateChange" ? /* @__PURE__ */ React3.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ React3.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ React3.createElement(
4868
- InspectorRow,
4869
- {
4870
- key: index,
4871
- colorScheme,
4872
- variant: event.type === "send" ? "up" : "down",
4873
- style: {
4874
- padding: "0px 12px 1px"
4875
- }
4876
- },
4877
- /* @__PURE__ */ React3.createElement(
4878
- ObjectInspector,
4879
- {
4880
- data: event.type === "error" ? event.error : event.message,
4881
- theme,
4882
- nodeRenderer: ({
4883
- depth,
4884
- name,
4885
- data,
4886
- isNonenumerable
4887
- }) => {
4888
- const direction = event.type === "send" ? "up" : "down";
4889
- return depth === 0 ? /* @__PURE__ */ React3.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React3.createElement(
4890
- ObjectLabel,
4891
- {
4892
- direction,
4893
- name,
4894
- data,
4895
- isNonenumerable
4896
- }
4897
- );
4898
- }
4899
- }
4900
- )
4901
- )
4902
- ), !connectionEvents && /* @__PURE__ */ React3.createElement(
4903
- "div",
4904
- {
4905
- style: {
4906
- padding: "12px",
4907
- fontSize: "12px",
4908
- display: "flex",
4909
- flexDirection: "column",
4910
- gap: "4px"
4911
- }
4912
- },
4913
- /* @__PURE__ */ React3.createElement("span", null, "No recorded events")
4914
- ))
4915
- )
4916
- );
4917
- });
4918
- var ObjectRootLabel = ({ name, data, direction }) => {
4919
- if (typeof name === "string") {
4920
- return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(ObjectName, { name }), /* @__PURE__ */ React3.createElement("span", null, ": "), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
4921
- }
4922
- if (direction === "up" || direction === "down") {
4923
- const arrow = direction === "up" ? "\u2191" : "\u2193";
4924
- return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(
4925
- "span",
6690
+ /* @__PURE__ */ React14.createElement(
6691
+ ActivityEventsSection,
4926
6692
  {
4927
- style: {
4928
- background: direction === "up" ? "rgba(0,255,0,0.2)" : "rgba(255,0,0,0.2)",
4929
- // color: "white",
4930
- width: 12,
4931
- height: 12,
4932
- borderRadius: 2,
4933
- display: "inline-flex",
4934
- justifyContent: "center",
4935
- alignItems: "center",
4936
- marginRight: 4,
4937
- lineHeight: "12px"
4938
- }
4939
- },
4940
- arrow
4941
- ), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
4942
- } else {
4943
- return /* @__PURE__ */ React3.createElement(ObjectPreview, { data });
4944
- }
4945
- };
4946
- function Arrow({
4947
- expanded,
4948
- onClick,
4949
- style
4950
- }) {
4951
- return /* @__PURE__ */ React3.createElement(
4952
- "span",
4953
- {
4954
- role: "button",
4955
- onClick,
4956
- style: {
4957
- display: "inline-block",
4958
- textAlign: "center",
4959
- transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
4960
- fontFamily: "Menlo, monospace",
4961
- ...style
4962
- }
4963
- },
4964
- "\u25BC"
4965
- );
4966
- }
4967
- function pathToString(extendedPath) {
4968
- return extendedPath.map(
4969
- (key) => typeof key === "object" ? `:${ellipsis(key.id.toString(), 8, "middle")}` : key
4970
- ).map(
4971
- (key, index) => index === 0 || typeof key === "string" && key.startsWith(":") ? key : `.${key}`
4972
- ).join("");
4973
- }
4974
- function ellipsis(str, maxLength, position = "end") {
4975
- if (str.length <= maxLength) return str;
4976
- switch (position) {
4977
- case "start":
4978
- return `\u2026${str.slice(str.length - maxLength)}`;
4979
- case "middle":
4980
- const halfLength = Math.floor(maxLength / 2);
4981
- return `${str.slice(0, halfLength)}\u2026${str.slice(str.length - halfLength)}`;
4982
- case "end":
4983
- return `${str.slice(0, maxLength)}\u2026`;
4984
- }
4985
- }
4986
- function SmallButton({
4987
- children,
4988
- onClick,
4989
- style,
4990
- theme,
4991
- disabled
4992
- }) {
4993
- return /* @__PURE__ */ React3.createElement(
4994
- "button",
4995
- {
4996
- type: "button",
4997
- disabled,
4998
- onClick: (event) => {
4999
- event.stopPropagation();
5000
- onClick();
5001
- },
5002
- style: {
5003
- flex: "0",
5004
- appearance: "none",
5005
- background: "none",
5006
- color: theme.BASE_COLOR,
5007
- opacity: disabled ? 0.25 : 1,
5008
- border: "none",
5009
- fontSize: "12px",
5010
- whiteSpace: "nowrap",
5011
- display: "inline-flex",
5012
- alignItems: "center",
5013
- justifyContent: "center",
5014
- padding: "0",
5015
- cursor: "pointer",
5016
- ...style
6693
+ colorScheme,
6694
+ activityEventsContainerRef,
6695
+ showEvents: showActivityEvents,
6696
+ setShowEvents: setShowActivityEvents,
6697
+ activityEventsManager
5017
6698
  }
5018
- },
5019
- children
5020
- );
5021
- }
5022
- function ColoredDot({ type }) {
5023
- return /* @__PURE__ */ React3.createElement(
5024
- "span",
5025
- {
5026
- style: {
5027
- display: "inline-block",
5028
- width: 6,
5029
- height: 6,
5030
- background: type === "success" ? "rgba(0,200,0,0.8)" : "rgba(200,0,0,0.8)",
5031
- borderRadius: "50%",
5032
- verticalAlign: "middle"
6699
+ ),
6700
+ /* @__PURE__ */ React14.createElement(
6701
+ EventsSection,
6702
+ {
6703
+ connectionEvents,
6704
+ colorScheme,
6705
+ eventsContainerRef,
6706
+ showEvents,
6707
+ setShowEvents
5033
6708
  }
5034
- }
6709
+ )
5035
6710
  );
5036
- }
5037
- function TitleLabel({ children }) {
5038
- return /* @__PURE__ */ React3.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
5039
- }
6711
+ });
5040
6712
 
5041
6713
  // src/inspector/useStateInspector.tsx
5042
6714
  function createShadowRootElement() {
@@ -5053,7 +6725,7 @@ function useStateInspector({
5053
6725
  colorScheme,
5054
6726
  anchor
5055
6727
  }) {
5056
- const [root, setRoot] = React4.useState(null);
6728
+ const [root, setRoot] = React15.useState(null);
5057
6729
  useIsomorphicLayoutEffect(() => {
5058
6730
  if (disabled) return;
5059
6731
  const { host, container } = createShadowRootElement();
@@ -5067,7 +6739,7 @@ function useStateInspector({
5067
6739
  useIsomorphicLayoutEffect(() => {
5068
6740
  if (!root) return;
5069
6741
  root.render(
5070
- /* @__PURE__ */ React4.createElement(
6742
+ /* @__PURE__ */ React15.createElement(
5071
6743
  StateInspector,
5072
6744
  {
5073
6745
  colorScheme,
@@ -5080,10 +6752,10 @@ function useStateInspector({
5080
6752
  }
5081
6753
 
5082
6754
  // src/hooks.ts
5083
- function useSyncStateManager(stateManager, path) {
5084
- const getSnapshot = useCallback(
5085
- () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
5086
- [stateManager, path]
6755
+ function useSyncStateManager(stateManager, path2) {
6756
+ const getSnapshot = useCallback2(
6757
+ () => typeof path2 === "string" ? stateManager.getState(path2) : stateManager.getState(),
6758
+ [stateManager, path2]
5087
6759
  );
5088
6760
  return useSyncExternalStore2(
5089
6761
  stateManager.addListener,
@@ -5092,11 +6764,11 @@ function useSyncStateManager(stateManager, path) {
5092
6764
  );
5093
6765
  }
5094
6766
  function useManagedState(createInitialState, options) {
5095
- const [stateManager] = useState(
6767
+ const [stateManager] = useState2(
5096
6768
  () => new StateManager(createInitialState(), options)
5097
6769
  );
5098
6770
  const state = useSyncStateManager(stateManager);
5099
- const setState = useCallback(
6771
+ const setState = useCallback2(
5100
6772
  (...args) => {
5101
6773
  const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
5102
6774
  if (metadata === void 0) {
@@ -5144,8 +6816,8 @@ function useMultiplayerState(initialState, options) {
5144
6816
  inspector,
5145
6817
  ...rest
5146
6818
  } = options ?? {};
5147
- const [noyaManager] = useState(
5148
- () => new NoyaManager(initialState, rest)
6819
+ const [noyaManager] = useState2(
6820
+ () => new NoyaManager2(initialState, rest)
5149
6821
  );
5150
6822
  const state = useObservable(
5151
6823
  noyaManager.multiplayerStateManager.optimisticState$
@@ -5170,8 +6842,8 @@ function useMultiplayerState(initialState, options) {
5170
6842
  assets
5171
6843
  };
5172
6844
  }, [noyaManager, assets]);
5173
- const syncRef = useRef(sync);
5174
- useEffect2(() => {
6845
+ const syncRef = useRef2(sync);
6846
+ useEffect3(() => {
5175
6847
  if (syncRef.current) {
5176
6848
  return syncRef.current({ noyaManager });
5177
6849
  }
@@ -5186,7 +6858,7 @@ function useMultiplayerState(initialState, options) {
5186
6858
  }
5187
6859
  function useErrorOverlay(noyaManager) {
5188
6860
  const unrecoverableError = useObservable(noyaManager.unrecoverableError);
5189
- useEffect2(() => {
6861
+ useEffect3(() => {
5190
6862
  if (!unrecoverableError) return;
5191
6863
  const el = document.createElement("div");
5192
6864
  el.id = "noya-multiplayer-react-error-overlay";
@@ -5233,7 +6905,7 @@ function parseAppDataParameter(options) {
5233
6905
  function getAppData(initialState, schema, options) {
5234
6906
  const resolvedInitialState = initialState instanceof Function ? initialState() : initialState;
5235
6907
  let appData = parseAppDataParameter(options) ?? createDefaultAppData(resolvedInitialState);
5236
- if (options?.overrideExistingState) {
6908
+ if (options?.overrideExistingState || appData.initialState === null) {
5237
6909
  appData.initialState = resolvedInitialState;
5238
6910
  }
5239
6911
  appData.initialState = enforceSchema(appData.initialState, schema);
@@ -5249,7 +6921,7 @@ function useNoyaState(...args) {
5249
6921
  theme,
5250
6922
  viewType
5251
6923
  }
5252
- ] = useState2(() => {
6924
+ ] = useState3(() => {
5253
6925
  return getAppData(initialState, options?.schema, {
5254
6926
  overrideExistingState: options?.overrideExistingState
5255
6927
  });
@@ -5337,7 +7009,7 @@ function useSecret(name) {
5337
7009
  const { noyaManager } = useAnyNoyaStateContext();
5338
7010
  return useObservable(
5339
7011
  noyaManager.secretManager.secrets$,
5340
- useCallback2((secrets) => secrets.find((s) => s.name === name), [name])
7012
+ useCallback3((secrets) => secrets.find((s) => s.name === name), [name])
5341
7013
  );
5342
7014
  }
5343
7015
  function useInputs() {
@@ -5355,7 +7027,7 @@ function useIOManager() {
5355
7027
  function usePublish(callback) {
5356
7028
  const { noyaManager } = useAnyNoyaStateContext();
5357
7029
  const stableCallback = useStableCallback(callback);
5358
- useEffect3(() => {
7030
+ useEffect4(() => {
5359
7031
  noyaManager.publishingManager.setPublishingEnabled(true);
5360
7032
  noyaManager.publishingManager.getFilesToPublish = stableCallback;
5361
7033
  return () => {
@@ -5387,6 +7059,25 @@ var ConnectedUsersContext = createContext(void 0);
5387
7059
  function useConnectedUsersManager() {
5388
7060
  return useContext(ConnectedUsersContext);
5389
7061
  }
7062
+ function useConnectedUsers() {
7063
+ const connectedUsersManager = useConnectedUsersManager();
7064
+ return useObservable(connectedUsersManager?.connectedUsers$);
7065
+ }
7066
+ function useConnectedUser(userId) {
7067
+ const connectedUsersManager = useConnectedUsersManager();
7068
+ return useObservable(
7069
+ connectedUsersManager?.connectedUsers$,
7070
+ useCallback3(
7071
+ (users) => {
7072
+ return users.find((user) => {
7073
+ const prefix = user.id.slice(0, 8);
7074
+ return userId?.includes(prefix);
7075
+ });
7076
+ },
7077
+ [userId]
7078
+ )
7079
+ );
7080
+ }
5390
7081
  var AnyEphemeralUserDataManagerContext = createContext(void 0);
5391
7082
  function useAnyEphemeralUserData() {
5392
7083
  return useContext(AnyEphemeralUserDataManagerContext);
@@ -5395,6 +7086,125 @@ function useCurrentUserId() {
5395
7086
  const connectedUsersManager = useConnectedUsersManager();
5396
7087
  return useObservable(connectedUsersManager?.currentUserId$);
5397
7088
  }
7089
+ function useIsProcessing() {
7090
+ const { noyaManager } = useAnyNoyaStateContext();
7091
+ return useObservable(noyaManager.isProcessing$);
7092
+ }
7093
+ function useResourceManager() {
7094
+ const { noyaManager } = useAnyNoyaStateContext();
7095
+ return noyaManager.resourceManager;
7096
+ }
7097
+ function resourceToMediaItem(resource) {
7098
+ switch (resource.type) {
7099
+ case "asset":
7100
+ return { kind: "asset", id: resource.id, assetId: resource.assetId };
7101
+ case "file":
7102
+ return { kind: "noyaFile", id: resource.id, fileId: resource.fileId };
7103
+ default:
7104
+ return { kind: "folder", id: resource.id };
7105
+ }
7106
+ }
7107
+ function useResources({
7108
+ shouldDeleteAssets = true
7109
+ } = {}) {
7110
+ const resourceManager = useResourceManager();
7111
+ const assetManager = useAssetManager();
7112
+ const resourceMap = useObservable(
7113
+ resourceManager.optimisticResources$,
7114
+ useCallback3((resources) => {
7115
+ return Object.fromEntries(
7116
+ resources.map((resource) => [resource.path, resource])
7117
+ );
7118
+ }, [])
7119
+ );
7120
+ const setResourceMap = useCallback3(
7121
+ async (action) => {
7122
+ const newResourceMap = action instanceof Function ? action(resourceMap) : action;
7123
+ const { addedResources, removedResources, modifiedResources } = diffResourceMaps(resourceMap, newResourceMap, "id");
7124
+ if (addedResources.length > 0) {
7125
+ const payload = addedResources.map((resource) => {
7126
+ switch (resource.type) {
7127
+ case "directory":
7128
+ return {
7129
+ path: resource.path,
7130
+ type: "directory"
7131
+ };
7132
+ case "asset":
7133
+ return {
7134
+ path: resource.path,
7135
+ type: "asset",
7136
+ assetId: resource.assetId,
7137
+ asset: resource.asset
7138
+ };
7139
+ case "file":
7140
+ return {
7141
+ path: resource.path,
7142
+ type: "file",
7143
+ fileId: resource.fileId
7144
+ };
7145
+ case "resource":
7146
+ return {
7147
+ path: resource.path,
7148
+ type: "resource",
7149
+ fileId: resource.fileId,
7150
+ resourceId: resource.resourceId
7151
+ };
7152
+ default:
7153
+ throw new Error(
7154
+ `Unknown resource type: ${resource.type}`
7155
+ );
7156
+ }
7157
+ });
7158
+ await resourceManager.createResource(payload);
7159
+ }
7160
+ for (const resource of removedResources) {
7161
+ await resourceManager.deleteResource({ id: resource.id });
7162
+ if (shouldDeleteAssets && resource.type === "asset") {
7163
+ try {
7164
+ await assetManager.delete(resource.assetId);
7165
+ } catch (error) {
7166
+ console.error("Failed to delete asset:", error);
7167
+ }
7168
+ }
7169
+ }
7170
+ await Promise.all(
7171
+ modifiedResources.map(
7172
+ ({ id, path: path2, assetId, asset }) => resourceManager.updateResource({
7173
+ id,
7174
+ path: path2,
7175
+ assetId,
7176
+ asset
7177
+ })
7178
+ )
7179
+ );
7180
+ },
7181
+ [resourceMap, resourceManager, shouldDeleteAssets, assetManager]
7182
+ );
7183
+ return [resourceMap, setResourceMap];
7184
+ }
7185
+ var emptyArray = [];
7186
+ function useActivityEvents(streamFilter) {
7187
+ const { noyaManager } = useAnyNoyaStateContext();
7188
+ return useActivityEventsForManager(
7189
+ streamFilter,
7190
+ noyaManager.activityEventsManager
7191
+ );
7192
+ }
7193
+ function useActivityEventsForManager(streamFilter, activityEventsManager) {
7194
+ const [streamId, setStreamId] = useState4(void 0);
7195
+ const stableStreamFilter = useJsonMemo(streamFilter);
7196
+ useEffect4(() => {
7197
+ if (!stableStreamFilter) return;
7198
+ const streamId2 = activityEventsManager.subscribe(stableStreamFilter);
7199
+ setStreamId(streamId2);
7200
+ return () => {
7201
+ setStreamId(void 0);
7202
+ activityEventsManager.unsubscribe(streamId2);
7203
+ };
7204
+ }, [activityEventsManager, stableStreamFilter]);
7205
+ const observable = streamId ? activityEventsManager.getStream(streamId) : void 0;
7206
+ return useObservable(observable) ?? emptyArray;
7207
+ }
5398
7208
  var FallbackUntilInitialized = ({
5399
7209
  children,
5400
7210
  fallback
@@ -5411,6 +7221,24 @@ function createNoyaContext({
5411
7221
  }) {
5412
7222
  const NoyaStateContext = AnyNoyaStateContext;
5413
7223
  const EphemeralUserDataManagerContext = AnyEphemeralUserDataManagerContext;
7224
+ function NoyaContextProvider({
7225
+ children,
7226
+ contextValue
7227
+ }) {
7228
+ return /* @__PURE__ */ React16.createElement(AnyNoyaStateContext.Provider, { value: contextValue }, /* @__PURE__ */ React16.createElement(
7229
+ ConnectedUsersContext.Provider,
7230
+ {
7231
+ value: contextValue.noyaManager.connectedUsersManager
7232
+ },
7233
+ /* @__PURE__ */ React16.createElement(
7234
+ EphemeralUserDataManagerContext.Provider,
7235
+ {
7236
+ value: contextValue.noyaManager.ephemeralUserDataManager
7237
+ },
7238
+ children
7239
+ )
7240
+ ));
7241
+ }
5414
7242
  function NoyaStateProvider({
5415
7243
  children,
5416
7244
  initialState,
@@ -5435,53 +7263,41 @@ function createNoyaContext({
5435
7263
  }),
5436
7264
  [noyaManager, theme, viewType]
5437
7265
  );
5438
- return /* @__PURE__ */ React5.createElement(AnyNoyaStateContext.Provider, { value: contextValue }, /* @__PURE__ */ React5.createElement(
5439
- ConnectedUsersContext.Provider,
5440
- {
5441
- value: noyaManager.connectedUsersManager
5442
- },
5443
- /* @__PURE__ */ React5.createElement(
5444
- EphemeralUserDataManagerContext.Provider,
5445
- {
5446
- value: noyaManager.ephemeralUserDataManager
5447
- },
5448
- options.fallback !== void 0 ? /* @__PURE__ */ React5.createElement(FallbackUntilInitialized, { fallback: options.fallback }, children) : children
5449
- )
5450
- ));
7266
+ return /* @__PURE__ */ React16.createElement(NoyaContextProvider, { contextValue }, options.fallback !== void 0 ? /* @__PURE__ */ React16.createElement(FallbackUntilInitialized, { fallback: options.fallback }, children) : children);
5451
7267
  }
5452
- function useValue(path, options) {
7268
+ function useValue(path2, options) {
5453
7269
  const { noyaManager } = useAnyNoyaStateContext();
5454
- let actualPath = typeof path === "function" || !path ? "" : path;
7270
+ let actualPath = typeof path2 === "function" || !path2 ? "" : path2;
5455
7271
  const mappedObservable = useMemo4(() => {
5456
- if (typeof path === "function") {
5457
- return noyaManager.multiplayerStateManager.optimisticState$.map(path, {
7272
+ if (typeof path2 === "function") {
7273
+ return noyaManager.multiplayerStateManager.optimisticState$.map(path2, {
5458
7274
  isEqual: options?.isEqual
5459
7275
  });
5460
7276
  }
5461
7277
  return noyaManager.multiplayerStateManager.optimisticState$;
5462
- }, [noyaManager, path, options?.isEqual]);
7278
+ }, [noyaManager, path2, options?.isEqual]);
5463
7279
  const value = useObservable(mappedObservable, actualPath);
5464
7280
  return value;
5465
7281
  }
5466
- function useSetValue(path) {
7282
+ function useSetValue(path2) {
5467
7283
  const { noyaManager } = useAnyNoyaStateContext();
5468
- const setValue = useCallback2(
7284
+ const setValue = useCallback3(
5469
7285
  (...args) => {
5470
7286
  const [metadata, value] = args.length === 2 ? args : [{}, args[0]];
5471
7287
  noyaManager.multiplayerStateManager.setStateAtPath(
5472
7288
  metadata,
5473
- path ?? "",
7289
+ path2 ?? "",
5474
7290
  value
5475
7291
  );
5476
7292
  },
5477
- [noyaManager, path]
7293
+ [noyaManager, path2]
5478
7294
  );
5479
7295
  return setValue;
5480
7296
  }
5481
7297
  function useValueState(...args) {
5482
- const [selector, options, path] = args.length >= 1 && typeof args[0] === "function" ? [args[0], args[1], void 0] : [void 0, void 0, args[0]];
5483
- const value = useValue(selector ?? path ?? "", options);
5484
- const setValue = useSetValue(path ?? "");
7298
+ const [selector, options, path2] = args.length >= 1 && typeof args[0] === "function" ? [args[0], args[1], void 0] : [void 0, void 0, args[0]];
7299
+ const value = useValue(selector ?? path2 ?? "", options);
7300
+ const setValue = useSetValue(path2 ?? "");
5485
7301
  return [value, setValue];
5486
7302
  }
5487
7303
  function useStateManager() {
@@ -5506,7 +7322,7 @@ function createNoyaContext({
5506
7322
  }
5507
7323
  function useSetLeftMenuItems(leftMenuItems) {
5508
7324
  const { menuManager } = useNoyaManager();
5509
- useEffect3(() => {
7325
+ useEffect4(() => {
5510
7326
  if (leftMenuItems) {
5511
7327
  menuManager.setLeftMenuItems(leftMenuItems);
5512
7328
  }
@@ -5518,7 +7334,7 @@ function createNoyaContext({
5518
7334
  }
5519
7335
  function useSetRightMenuItems(rightMenuItems) {
5520
7336
  const { menuManager } = useNoyaManager();
5521
- useEffect3(() => {
7337
+ useEffect4(() => {
5522
7338
  if (rightMenuItems) {
5523
7339
  menuManager.setRightMenuItems(rightMenuItems);
5524
7340
  }
@@ -5526,25 +7342,26 @@ function createNoyaContext({
5526
7342
  }
5527
7343
  function useHandleMenuItem(callback) {
5528
7344
  const { menuManager } = useNoyaManager();
5529
- useEffect3(() => {
7345
+ useEffect4(() => {
5530
7346
  return menuManager.addListener(callback);
5531
7347
  }, [menuManager, callback]);
5532
7348
  }
5533
7349
  function useOnSelectMenuItemCallback() {
5534
7350
  const { menuManager } = useNoyaManager();
5535
- return useCallback2((type) => menuManager.emit(type), [menuManager]);
7351
+ return useCallback3((type) => menuManager.emit(type), [menuManager]);
5536
7352
  }
5537
7353
  function useMenu(options) {
5538
7354
  const { leftMenuItems, rightMenuItems, onSelectMenuItem } = options;
5539
7355
  useSetLeftMenuItems(leftMenuItems);
5540
7356
  useSetRightMenuItems(rightMenuItems);
5541
- const noop = useCallback2(() => {
7357
+ const noop = useCallback3(() => {
5542
7358
  }, []);
5543
7359
  useHandleMenuItem(onSelectMenuItem ?? noop);
5544
7360
  }
5545
7361
  return {
5546
7362
  Context: NoyaStateContext,
5547
7363
  Provider: NoyaStateProvider,
7364
+ NoyaContextProvider,
5548
7365
  useValue,
5549
7366
  useSetValue,
5550
7367
  useValueState,
@@ -5564,7 +7381,7 @@ function createNoyaContext({
5564
7381
  // src/ai.ts
5565
7382
  function useRegisterAITool(tool) {
5566
7383
  const aiManager = useAIManager();
5567
- useEffect4(() => {
7384
+ useEffect5(() => {
5568
7385
  return aiManager.registerTool(tool);
5569
7386
  }, [aiManager, tool]);
5570
7387
  }
@@ -5576,7 +7393,7 @@ function useCallableAITools() {
5576
7393
  // src/components/UserPointersOverlay.tsx
5577
7394
  import { Observable as Observable2 } from "@noya-app/observable";
5578
7395
  import { memoGeneric as memoGeneric2 } from "@noya-app/react-utils";
5579
- import React6, { useEffect as useEffect5, useMemo as useMemo5, useState as useState3 } from "react";
7396
+ import React17, { useEffect as useEffect6, useMemo as useMemo5, useState as useState5 } from "react";
5580
7397
  function shouldShow(hideAfter, updatedAt) {
5581
7398
  return !!updatedAt && Date.now() - updatedAt < hideAfter;
5582
7399
  }
@@ -5594,10 +7411,10 @@ var UserPointerInternal = memoGeneric2(function UserPointerInternal2({
5594
7411
  });
5595
7412
  }, [ephemeralUserDataManager, user.id]);
5596
7413
  const { metadata, data } = useObservable(observable);
5597
- const [, setForceUpdate] = useState3(0);
7414
+ const [, setForceUpdate] = useState5(0);
5598
7415
  const updatedAt = metadata?.updatedAt ?? 0;
5599
7416
  const show = shouldShow(hideAfter, updatedAt);
5600
- useEffect5(() => {
7417
+ useEffect6(() => {
5601
7418
  if (!show) return;
5602
7419
  const timeoutId = setTimeout(() => {
5603
7420
  setForceUpdate((prev) => prev + 1);
@@ -5619,9 +7436,9 @@ var UserPointersOverlay = memoGeneric2(function UserPointers({
5619
7436
  }) {
5620
7437
  const currentUserId = useObservable(ephemeralUserDataManager.currentUserId$);
5621
7438
  const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
5622
- return /* @__PURE__ */ React6.createElement(React6.Fragment, null, connectedUsers.map((user) => {
7439
+ return /* @__PURE__ */ React17.createElement(React17.Fragment, null, connectedUsers.map((user) => {
5623
7440
  if (user.id === currentUserId) return null;
5624
- return /* @__PURE__ */ React6.createElement(
7441
+ return /* @__PURE__ */ React17.createElement(
5625
7442
  UserPointerInternal,
5626
7443
  {
5627
7444
  key: user.id,
@@ -5723,10 +7540,19 @@ export {
5723
7540
  WebSocketConnection,
5724
7541
  createDefaultAppData,
5725
7542
  createNoyaContext,
7543
+ decodeAll,
7544
+ encodeAll,
5726
7545
  enforceSchema,
7546
+ exportAll,
7547
+ fetchAssetMap,
5727
7548
  getAppData,
7549
+ importAll,
5728
7550
  parseAppDataParameter,
7551
+ replaceDeep,
7552
+ resourceToMediaItem,
5729
7553
  useAIManager,
7554
+ useActivityEvents,
7555
+ useActivityEventsForManager,
5730
7556
  useAnyEphemeralUserData,
5731
7557
  useAnyNoyaManager,
5732
7558
  useAnyNoyaStateContext,
@@ -5735,11 +7561,14 @@ export {
5735
7561
  useAssets,
5736
7562
  useCallableAITools,
5737
7563
  useColorScheme,
7564
+ useConnectedUser,
7565
+ useConnectedUsers,
5738
7566
  useConnectedUsersManager,
5739
7567
  useCurrentUserId,
5740
7568
  useIOManager,
5741
7569
  useInputs,
5742
7570
  useIsInitialized,
7571
+ useIsProcessing,
5743
7572
  useManagedHistory,
5744
7573
  useManagedState,
5745
7574
  useMultiplayerState,
@@ -5749,6 +7578,8 @@ export {
5749
7578
  usePipelineManager,
5750
7579
  usePublish,
5751
7580
  useRegisterAITool,
7581
+ useResourceManager,
7582
+ useResources,
5752
7583
  useSecret,
5753
7584
  useSecretManager,
5754
7585
  useSecrets,