@noya-app/noya-multiplayer-react 0.1.51 → 0.1.53

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
@@ -71,8 +71,8 @@ var require_sort = __commonJS({
71
71
  "../../node_modules/tree-visit/lib/sort.js"(exports) {
72
72
  "use strict";
73
73
  Object.defineProperty(exports, "__esModule", { value: true });
74
- exports.sortIndexPaths = exports.compareIndexPaths = void 0;
75
- function compareIndexPaths(a, b) {
74
+ exports.sortPaths = exports.comparePathsByComponent = void 0;
75
+ function comparePathsByComponent(a, b) {
76
76
  for (let i = 0; i < Math.min(a.length, b.length); i++) {
77
77
  if (a[i] < b[i])
78
78
  return -1;
@@ -81,11 +81,11 @@ var require_sort = __commonJS({
81
81
  }
82
82
  return a.length - b.length;
83
83
  }
84
- exports.compareIndexPaths = compareIndexPaths;
85
- function sortIndexPaths(indexPaths) {
86
- return indexPaths.sort(compareIndexPaths);
84
+ exports.comparePathsByComponent = comparePathsByComponent;
85
+ function sortPaths(indexPaths) {
86
+ return [...indexPaths].sort(comparePathsByComponent);
87
87
  }
88
- exports.sortIndexPaths = sortIndexPaths;
88
+ exports.sortPaths = sortPaths;
89
89
  }
90
90
  });
91
91
 
@@ -94,23 +94,25 @@ var require_ancestors = __commonJS({
94
94
  "../../node_modules/tree-visit/lib/ancestors.js"(exports) {
95
95
  "use strict";
96
96
  Object.defineProperty(exports, "__esModule", { value: true });
97
- exports.ancestorIndexPaths = void 0;
97
+ exports.ancestorPaths = void 0;
98
98
  var sort_1 = require_sort();
99
- function ancestorIndexPaths(indexPaths) {
100
- const paths = /* @__PURE__ */ new Map();
101
- const sortedIndexPaths = (0, sort_1.sortIndexPaths)(indexPaths);
99
+ function ancestorPaths(paths, options) {
100
+ var _a;
101
+ const result = /* @__PURE__ */ new Map();
102
+ const compare = (_a = options === null || options === void 0 ? void 0 : options.compare) !== null && _a !== void 0 ? _a : sort_1.comparePathsByComponent;
103
+ const sortedIndexPaths = paths.sort(compare);
102
104
  for (const indexPath of sortedIndexPaths) {
103
105
  const foundParent = indexPath.some((_, index) => {
104
106
  const parentKey = indexPath.slice(0, index).join();
105
- return paths.has(parentKey);
107
+ return result.has(parentKey);
106
108
  });
107
109
  if (foundParent)
108
110
  continue;
109
- paths.set(indexPath.join(), indexPath);
111
+ result.set(indexPath.join(), indexPath);
110
112
  }
111
- return Array.from(paths.values());
113
+ return Array.from(result.values());
112
114
  }
113
- exports.ancestorIndexPaths = ancestorIndexPaths;
115
+ exports.ancestorPaths = ancestorPaths;
114
116
  }
115
117
  });
116
118
 
@@ -616,7 +618,7 @@ var require_operation = __commonJS({
616
618
  exports.getInsertionOperations = getInsertionOperations;
617
619
  function getRemovalOperations(indexPaths) {
618
620
  var _a, _b;
619
- const _ancestorIndexPaths = (0, ancestors_1.ancestorIndexPaths)(indexPaths);
621
+ const _ancestorIndexPaths = (0, ancestors_1.ancestorPaths)(indexPaths);
620
622
  const indexesToRemove = /* @__PURE__ */ new Map();
621
623
  for (const indexPath of _ancestorIndexPaths) {
622
624
  const parentKey = indexPath.slice(0, -1).join();
@@ -742,7 +744,7 @@ var require_move = __commonJS({
742
744
  if (options.to.length === 0) {
743
745
  throw new Error(`Can't move nodes to the root`);
744
746
  }
745
- const _ancestorIndexPaths = (0, ancestors_1.ancestorIndexPaths)(options.indexPaths);
747
+ const _ancestorIndexPaths = (0, ancestors_1.ancestorPaths)(options.indexPaths);
746
748
  const nodesToInsert = _ancestorIndexPaths.map((indexPath) => (0, access_1.access)(node, indexPath, options));
747
749
  const operations = (0, operation_1.getInsertionOperations)(options.to, nodesToInsert, (0, operation_1.getRemovalOperations)(_ancestorIndexPaths));
748
750
  return (0, operation_1.applyOperations)(node, operations, options);
@@ -911,1436 +913,115 @@ var require_lib = __commonJS({
911
913
  // src/index.ts
912
914
  export * from "@noya-app/state-manager";
913
915
 
914
- // src/components/UserPointersOverlay.tsx
915
- import { memoGeneric } from "@noya-app/react-utils";
916
- import React, { useEffect, useState } from "react";
917
-
918
- // src/useObservable.ts
919
- import { useMemo, useSyncExternalStore } from "react";
920
- function useObservable(observable, pathOrSelector, options) {
921
- const { get, listen } = useMemo(() => {
922
- if (!observable) {
923
- return {
924
- get: () => void 0,
925
- listen: () => () => {
926
- }
927
- };
928
- }
929
- if (typeof pathOrSelector === "function") {
930
- const mappedObservable = observable.map(pathOrSelector, {
931
- isEqual: options?.isEqual
932
- });
933
- return {
934
- get: mappedObservable.get,
935
- listen: mappedObservable.subscribe
936
- };
937
- }
938
- const listen2 = pathOrSelector ? (callback) => observable.subscribe(pathOrSelector, callback) : observable.subscribe;
939
- const get2 = pathOrSelector ? () => observable.get(pathOrSelector) : observable.get;
940
- return { get: get2, listen: listen2 };
941
- }, [observable, pathOrSelector, options?.isEqual]);
942
- return useSyncExternalStore(listen, get, get);
943
- }
944
-
945
- // src/components/UserPointersOverlay.tsx
946
- function shouldShow(hideAfter, updatedAt) {
947
- return !!updatedAt && Date.now() - updatedAt < hideAfter;
948
- }
949
- var UserPointerInternal = memoGeneric(function UserPointerInternal2({
950
- user,
951
- ephemeralUserDataManager,
952
- hideAfter = 5e3,
953
- renderUserPointer
954
- }) {
955
- const metadata = useObservable(ephemeralUserDataManager.metadata$, [
956
- user.id
957
- ]);
958
- const data = useObservable(ephemeralUserDataManager.data$, [
959
- user.id
960
- ]);
961
- const [, setForceUpdate] = useState(0);
962
- const updatedAt = metadata?.updatedAt ?? 0;
963
- const show = shouldShow(hideAfter, updatedAt);
964
- useEffect(() => {
965
- if (!show) return;
966
- const timeoutId = setTimeout(() => {
967
- setForceUpdate((prev) => prev + 1);
968
- }, hideAfter);
969
- return () => clearTimeout(timeoutId);
970
- }, [hideAfter, show, updatedAt]);
971
- if (!data?.pointer) return null;
972
- return renderUserPointer({
973
- userId: user.id,
974
- name: user.name,
975
- point: data.pointer,
976
- visible: show
977
- });
978
- });
979
- var UserPointersOverlay = memoGeneric(function UserPointers({
980
- connectedUsersManager,
981
- ephemeralUserDataManager,
982
- renderUserPointer
983
- }) {
984
- const currentUserId = useObservable(ephemeralUserDataManager.currentUserId$);
985
- const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
986
- return /* @__PURE__ */ React.createElement(React.Fragment, null, connectedUsers.map((user) => {
987
- if (user.id === currentUserId) return null;
988
- return /* @__PURE__ */ React.createElement(
989
- UserPointerInternal,
990
- {
991
- key: user.id,
992
- user,
993
- ephemeralUserDataManager,
994
- renderUserPointer
995
- }
996
- );
997
- }));
998
- });
916
+ // src/ai.ts
917
+ import { useEffect as useEffect4 } from "react";
999
918
 
1000
- // src/hooks.ts
1001
- import {
1002
- NoyaManager,
1003
- StateManager,
1004
- stubSync
1005
- } from "@noya-app/state-manager";
919
+ // src/NoyaStateContext.tsx
1006
920
  import {
1007
- createElement as createElement2,
1008
- useCallback,
921
+ Observable
922
+ } from "@noya-app/observable";
923
+ import React5, {
924
+ createContext,
925
+ useCallback as useCallback2,
926
+ useContext,
1009
927
  useEffect as useEffect3,
1010
- useMemo as useMemo2,
1011
- useRef,
1012
- useState as useState2,
1013
- useSyncExternalStore as useSyncExternalStore2
928
+ useMemo as useMemo4
1014
929
  } from "react";
1015
- import { createRoot as createRoot2 } from "react-dom/client";
1016
-
1017
- // src/components/ErrorOverlay.tsx
1018
- import * as React2 from "react";
1019
- var ErrorOverlay = React2.memo(function ErrorOverlay2({
1020
- error
1021
- }) {
1022
- return /* @__PURE__ */ React2.createElement(
1023
- "div",
1024
- {
1025
- style: {
1026
- position: "fixed",
1027
- top: "20px",
1028
- left: "50%",
1029
- transform: "translateX(-50%)",
1030
- maxWidth: "80%",
1031
- width: "fit-content",
1032
- padding: "12px 20px",
1033
- background: "white",
1034
- color: "black",
1035
- zIndex: 1e4,
1036
- display: "flex",
1037
- flexDirection: "column",
1038
- justifyContent: "center",
1039
- borderRadius: "4px",
1040
- boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
1041
- fontFamily: "'__Inter_6b0edc', '__Inter_Fallback_6b0edc', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
1042
- fontSize: "14px",
1043
- fontWeight: 400,
1044
- lineHeight: "19px"
1045
- }
1046
- },
1047
- error.reason === "schemaMigration" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("p", null, "An updated version of Noya is available. Please reload the page to continue.")) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("p", null, "An error occurred:", " ", /* @__PURE__ */ React2.createElement(
1048
- "code",
1049
- {
1050
- style: {
1051
- background: "rgba(255, 0, 0, 0.1)",
1052
- color: "rgba(255, 0, 0, 0.5)",
1053
- padding: "2px 4px",
1054
- borderRadius: "4px"
1055
- }
1056
- },
1057
- error.reason
1058
- ), ". Please reload the page to continue.", /* @__PURE__ */ React2.createElement("br", null), /* @__PURE__ */ React2.createElement("br", null), "If this happens repeatedly, please get in touch and the Noya team can help.")),
1059
- /* @__PURE__ */ React2.createElement(
1060
- "div",
1061
- {
1062
- style: {
1063
- height: "1px",
1064
- background: "rgba(0, 0, 0, 0.1)",
1065
- margin: "12px -20px"
1066
- }
1067
- }
1068
- ),
1069
- /* @__PURE__ */ React2.createElement(
1070
- "button",
1071
- {
1072
- style: {
1073
- background: "black",
1074
- color: "white",
1075
- padding: "8px 16px",
1076
- borderRadius: "4px",
1077
- cursor: "pointer",
1078
- fontSize: "14px",
1079
- fontWeight: 700,
1080
- lineHeight: "19px"
1081
- },
1082
- onClick: () => {
1083
- window.location.reload();
1084
- }
1085
- },
1086
- "Reload"
1087
- )
1088
- );
1089
- });
1090
-
1091
- // src/inspector/useStateInspector.tsx
1092
- import React5, { useLayoutEffect as useLayoutEffect2 } from "react";
1093
- import { createRoot } from "react-dom/client";
1094
930
 
1095
- // src/inspector/StateInspector.tsx
1096
- import { memoGeneric as memoGeneric2 } from "@noya-app/react-utils";
1097
- import React4, {
1098
- useEffect as useEffect2,
1099
- useLayoutEffect
1100
- } from "react";
1101
- import {
1102
- ObjectInspector,
1103
- ObjectLabel,
1104
- ObjectName,
1105
- ObjectPreview,
1106
- chromeDark,
1107
- chromeLight
1108
- } from "react-inspector";
931
+ // ../../node_modules/@sinclair/typebox/build/esm/type/symbols/symbols.mjs
932
+ var TransformKind = Symbol.for("TypeBox.Transform");
933
+ var ReadonlyKind = Symbol.for("TypeBox.Readonly");
934
+ var OptionalKind = Symbol.for("TypeBox.Optional");
935
+ var Hint = Symbol.for("TypeBox.Hint");
936
+ var Kind = Symbol.for("TypeBox.Kind");
1109
937
 
1110
- // src/inspector/useLocalStorageState.tsx
1111
- import React3 from "react";
1112
- var localStorage = typeof window !== "undefined" ? window.localStorage : null;
1113
- function useLocalStorageState(key, defaultValue) {
1114
- const [state, setState] = React3.useState(() => {
1115
- const value = localStorage?.getItem(key);
1116
- let result = defaultValue;
1117
- if (value) {
1118
- try {
1119
- result = JSON.parse(value);
1120
- } catch (error) {
1121
- console.error("Error parsing localStorage value", error);
1122
- }
1123
- }
1124
- return result;
1125
- });
1126
- const setLocalStorageState = (value) => {
1127
- localStorage?.setItem(key, JSON.stringify(value));
1128
- setState(value);
1129
- };
1130
- return [state, setLocalStorageState];
938
+ // ../../node_modules/@sinclair/typebox/build/esm/type/any/any.mjs
939
+ function Any(options = {}) {
940
+ return { ...options, [Kind]: "Any" };
1131
941
  }
1132
942
 
1133
- // src/inspector/StateInspector.tsx
1134
- var lightTheme = {
1135
- ...chromeLight,
1136
- BASE_BACKGROUND_COLOR: "transparent",
1137
- OBJECT_NAME_COLOR: "rgba(0,0,0,0.7)"
1138
- };
1139
- var darkTheme = {
1140
- ...chromeDark,
1141
- BASE_BACKGROUND_COLOR: "transparent",
1142
- OBJECT_NAME_COLOR: "rgba(255,255,255,0.7)"
1143
- };
1144
- var styles = {
1145
- sectionInner: {
1146
- flex: "1 1 0",
1147
- overflowY: "auto",
1148
- overflowX: "hidden",
1149
- display: "flex",
1150
- flexDirection: "column"
1151
- }
1152
- };
1153
- function ToggleButton({
1154
- showInspector,
1155
- setShowInspector,
1156
- theme,
1157
- anchor
1158
- }) {
1159
- return /* @__PURE__ */ React4.createElement(
1160
- "span",
1161
- {
1162
- role: "button",
1163
- style: {
1164
- flex: "0",
1165
- appearance: "none",
1166
- color: theme.BASE_COLOR,
1167
- border: "none",
1168
- fontSize: "12px",
1169
- whiteSpace: "nowrap",
1170
- display: "inline-flex",
1171
- alignItems: "center",
1172
- justifyContent: "center",
1173
- padding: "2px 0"
1174
- },
1175
- onClick: (event) => {
1176
- event.stopPropagation();
1177
- setShowInspector(!showInspector);
1178
- }
1179
- },
1180
- /* @__PURE__ */ React4.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ React4.createElement(
1181
- "svg",
1182
- {
1183
- xmlns: "http://www.w3.org/2000/svg",
1184
- fill: "none",
1185
- viewBox: "0 0 24 24",
1186
- strokeWidth: 1.5,
1187
- stroke: "currentColor",
1188
- className: "size-6"
1189
- },
1190
- /* @__PURE__ */ React4.createElement(
1191
- "path",
1192
- {
1193
- strokeLinecap: "round",
1194
- strokeLinejoin: "round",
1195
- d: "m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
1196
- }
1197
- )
1198
- ) : /* @__PURE__ */ React4.createElement(
1199
- "svg",
1200
- {
1201
- xmlns: "http://www.w3.org/2000/svg",
1202
- fill: "none",
1203
- viewBox: "0 0 24 24",
1204
- strokeWidth: 1.5,
1205
- stroke: "currentColor",
1206
- className: "size-6"
1207
- },
1208
- /* @__PURE__ */ React4.createElement(
1209
- "path",
1210
- {
1211
- strokeLinecap: "round",
1212
- strokeLinejoin: "round",
1213
- d: "m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5"
1214
- }
1215
- )
1216
- ))
1217
- );
943
+ // ../../node_modules/@sinclair/typebox/build/esm/type/guard/value.mjs
944
+ var value_exports = {};
945
+ __export(value_exports, {
946
+ IsArray: () => IsArray,
947
+ IsAsyncIterator: () => IsAsyncIterator,
948
+ IsBigInt: () => IsBigInt,
949
+ IsBoolean: () => IsBoolean,
950
+ IsDate: () => IsDate,
951
+ IsFunction: () => IsFunction,
952
+ IsIterator: () => IsIterator,
953
+ IsNull: () => IsNull,
954
+ IsNumber: () => IsNumber,
955
+ IsObject: () => IsObject,
956
+ IsRegExp: () => IsRegExp,
957
+ IsString: () => IsString,
958
+ IsSymbol: () => IsSymbol,
959
+ IsUint8Array: () => IsUint8Array,
960
+ IsUndefined: () => IsUndefined
961
+ });
962
+ function IsAsyncIterator(value) {
963
+ return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.asyncIterator in value;
1218
964
  }
1219
- function DisclosureSection({
1220
- open,
1221
- setOpen,
1222
- title,
1223
- right,
1224
- children,
1225
- colorScheme,
1226
- isFirst,
1227
- style
1228
- }) {
1229
- const theme = colorScheme === "light" ? lightTheme : darkTheme;
1230
- const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
1231
- return /* @__PURE__ */ React4.createElement(
1232
- "div",
1233
- {
1234
- style: {
1235
- flex: open ? "1 1 0" : "0",
1236
- display: "flex",
1237
- flexDirection: "column",
1238
- ...style
1239
- }
1240
- },
1241
- /* @__PURE__ */ React4.createElement(
1242
- "div",
1243
- {
1244
- onClick: () => setOpen?.(!open),
1245
- style: {
1246
- cursor: "default",
1247
- fontSize: "12px",
1248
- padding: "4px 10px",
1249
- display: "flex",
1250
- alignItems: "center",
1251
- ...!isFirst && { borderTop: `1px solid ${borderColor}` },
1252
- ...open && { borderBottom: `1px solid ${borderColor}` }
1253
- }
1254
- },
1255
- setOpen && /* @__PURE__ */ React4.createElement(
1256
- Arrow,
1257
- {
1258
- expanded: open,
1259
- style: {
1260
- fontSize: theme.ARROW_FONT_SIZE,
1261
- marginRight: theme.ARROW_MARGIN_RIGHT + 1,
1262
- color: theme.ARROW_COLOR
1263
- }
1264
- }
1265
- ),
1266
- /* @__PURE__ */ React4.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
1267
- right
1268
- ),
1269
- open && children
1270
- );
965
+ function IsArray(value) {
966
+ return Array.isArray(value);
1271
967
  }
1272
- function InspectorRow({
1273
- children,
1274
- colorScheme,
1275
- selected,
1276
- style,
1277
- variant
1278
- }) {
1279
- const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
1280
- return /* @__PURE__ */ React4.createElement(
1281
- "div",
1282
- {
1283
- style: {
1284
- borderBottom: `1px solid ${solidBorderColor}`,
1285
- fontSize: "12px",
1286
- fontFamily: "Menlo, monospace",
1287
- padding: "2px 12px 1px",
1288
- display: "flex",
1289
- alignItems: "center",
1290
- background: variant === "up" ? "rgba(0,255,0,0.1)" : variant === "down" ? "transparent" : selected ? "rgb(59 130 246 / 15%)" : void 0,
1291
- // background:
1292
- // colorScheme === "light"
1293
- // ? "rgba(0,0,0,0.05)"
1294
- // : "rgba(255,255,255,0.05)",
1295
- ...style
1296
- }
1297
- },
1298
- /* @__PURE__ */ React4.createElement(
1299
- "span",
1300
- {
1301
- style: {
1302
- fontFamily: "Menlo, monospace",
1303
- fontSize: "11px",
1304
- borderRadius: 4,
1305
- display: "inline-block"
1306
- }
1307
- },
1308
- children
1309
- )
1310
- );
968
+ function IsBigInt(value) {
969
+ return typeof value === "bigint";
1311
970
  }
1312
- var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
1313
- var StateInspector = memoGeneric2(function StateInspector2({
1314
- noyaManager,
1315
- colorScheme = "light",
1316
- anchor = "right",
1317
- unstyled = false,
1318
- ...props
1319
- }) {
1320
- const {
1321
- multiplayerStateManager,
1322
- assetManager,
1323
- connectedUsersManager,
1324
- secretManager,
1325
- ephemeralUserDataManager,
1326
- connectionEventManager,
1327
- taskManager,
1328
- ioManager
1329
- } = noyaManager;
1330
- const [didMount, setDidMount] = React4.useState(false);
1331
- const tasks = useObservable(taskManager.tasks$);
1332
- const inputs = useObservable(ioManager.inputs$);
1333
- const outputTransforms = useObservable(ioManager.outputTransforms$);
1334
- useLayoutEffect(() => {
1335
- setDidMount(true);
1336
- }, []);
1337
- const eventsContainerRef = React4.useRef(null);
1338
- const historyContainerRef = React4.useRef(null);
1339
- const [showInspector, setShowInspector] = useLocalStorageState(
1340
- "noya-multiplayer-react-show-inspector",
1341
- true
1342
- );
1343
- const [showEvents, setShowEvents] = useLocalStorageState(
1344
- "noya-multiplayer-react-show-events",
1345
- false
1346
- );
1347
- const [showHistory, setShowHistory] = useLocalStorageState(
1348
- "noya-multiplayer-react-show-history",
1349
- false
1350
- );
1351
- const [showUsers, setShowUsers] = useLocalStorageState(
1352
- "noya-multiplayer-react-show-users",
1353
- true
1354
- );
1355
- const [showData, setShowData] = useLocalStorageState(
1356
- "noya-multiplayer-react-show-data",
1357
- true
1358
- );
1359
- const [showTasks, setShowTasks] = useLocalStorageState(
1360
- "noya-multiplayer-react-show-tasks",
1361
- false
1362
- );
1363
- const [showEphemeral, setShowEphemeral] = useLocalStorageState(
1364
- "noya-multiplayer-react-show-ephemeral",
1365
- false
1366
- );
1367
- const [showAssets, setShowAssets] = useLocalStorageState(
1368
- "noya-multiplayer-react-show-assets",
1369
- false
1370
- );
1371
- const [showSecrets, setShowSecrets] = useLocalStorageState(
1372
- "noya-multiplayer-react-show-secrets",
1373
- false
1374
- );
1375
- const [showInputs, setShowInputs] = useLocalStorageState(
1376
- "noya-multiplayer-react-show-inputs",
1377
- false
1378
- );
1379
- const [showOutputTransforms, setShowOutputTransforms] = useLocalStorageState(
1380
- "noya-multiplayer-react-show-output-transforms",
1381
- false
1382
- );
1383
- const connectionEvents = useObservable(connectionEventManager.events$);
1384
- useEffect2(() => {
1385
- if (eventsContainerRef.current) {
1386
- eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
1387
- }
1388
- }, [connectionEvents]);
1389
- const multipeerStateInitialized = useObservable(
1390
- multiplayerStateManager.isInitialized$
1391
- );
1392
- const ephemeral = useObservable(ephemeralUserDataManager.data$);
1393
- const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
1394
- const assets = useObservable(assetManager.assets$);
1395
- const assetsInitialized = useObservable(assetManager.isInitialized$);
1396
- const secrets = useObservable(secretManager.secrets$);
1397
- const secretsInitialized = useObservable(secretManager.isInitialized$);
1398
- const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
1399
- const userId = useObservable(connectedUsersManager.currentUserId$);
1400
- const state = useObservable(multiplayerStateManager.optimisticState$);
1401
- const inputsInitialized = useObservable(ioManager.inputsInitialized$);
1402
- const outputTransformsInitialized = useObservable(
1403
- ioManager.outputTransformsInitialized$
1404
- );
1405
- useEffect2(() => {
1406
- if (historyContainerRef.current) {
1407
- historyContainerRef.current.scrollTop = historyContainerRef.current.scrollHeight;
1408
- }
1409
- }, [historySnapshot]);
1410
- useEffect2(() => {
1411
- if (!historyContainerRef.current) return;
1412
- const historyEntry = historyContainerRef.current.querySelector(
1413
- `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
1414
- );
1415
- if (historyEntry) {
1416
- historyEntry.scrollIntoView({
1417
- block: "nearest",
1418
- inline: "nearest"
1419
- });
1420
- }
1421
- }, [historySnapshot.historyIndex]);
1422
- const theme = colorScheme === "light" ? lightTheme : darkTheme;
1423
- const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
1424
- const baseStyle = {
1425
- position: "fixed",
1426
- top: 12,
1427
- ...anchor.includes("right") ? { right: 12 } : { left: 12 },
1428
- bottom: 12,
1429
- width: 400,
1430
- background: colorScheme === "light" ? "rgba(255,255,255,0.95)" : "rgba(0,0,0,0.95)",
1431
- backdropFilter: "blur(48px)",
1432
- border: `1px solid ${solidBorderColor}`,
1433
- // outlineOffset: -1,
1434
- borderRadius: 4,
1435
- display: "flex",
1436
- flexDirection: "column",
1437
- // gap: 12,
1438
- color: theme.BASE_COLOR,
1439
- overflow: "hidden",
1440
- zIndex: 9999,
1441
- lineHeight: "13px"
1442
- };
1443
- if (!didMount) return null;
1444
- if (!showInspector) {
1445
- return /* @__PURE__ */ React4.createElement(
1446
- "div",
1447
- {
1448
- ...props,
1449
- style: {
1450
- ...baseStyle,
1451
- padding: "4px 10px",
1452
- width: void 0,
1453
- ...anchor.includes("bottom") ? { bottom: 12, top: void 0 } : { bottom: void 0 }
1454
- },
1455
- onClick: () => setShowInspector(true)
1456
- },
1457
- /* @__PURE__ */ React4.createElement(
1458
- ToggleButton,
1459
- {
1460
- showInspector,
1461
- setShowInspector,
1462
- theme,
1463
- anchor
1464
- }
1465
- )
1466
- );
1467
- }
1468
- return /* @__PURE__ */ React4.createElement(
1469
- "div",
1470
- {
1471
- ...props,
1472
- style: {
1473
- ...!unstyled && baseStyle,
1474
- ...props.style
1475
- }
1476
- },
1477
- /* @__PURE__ */ React4.createElement(
1478
- DisclosureSection,
1479
- {
1480
- isFirst: true,
1481
- open: showUsers,
1482
- setOpen: setShowUsers,
1483
- title: "Users",
1484
- colorScheme,
1485
- style: {
1486
- flex: "0 0 auto",
1487
- maxHeight: "200px"
1488
- },
1489
- right: /* @__PURE__ */ React4.createElement(
1490
- ToggleButton,
1491
- {
1492
- showInspector,
1493
- setShowInspector,
1494
- theme,
1495
- anchor
1496
- }
1497
- )
1498
- },
1499
- /* @__PURE__ */ React4.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React4.createElement(
1500
- InspectorRow,
1501
- {
1502
- key: user.id,
1503
- colorScheme,
1504
- variant: user.id === userId ? "up" : void 0
1505
- },
1506
- user.image && /* @__PURE__ */ React4.createElement(
1507
- "img",
1508
- {
1509
- src: user.image,
1510
- alt: user.name,
1511
- style: {
1512
- width: "13px",
1513
- height: "13px",
1514
- borderRadius: "50%",
1515
- marginRight: "4px",
1516
- display: "inline-block",
1517
- position: "relative",
1518
- background: solidBorderColor,
1519
- verticalAlign: "middle"
1520
- }
1521
- }
1522
- ),
1523
- user.name,
1524
- " (",
1525
- ellipsis(user.id.toString(), 8, "middle"),
1526
- ")"
1527
- )), !connectedUsers && /* @__PURE__ */ React4.createElement(
1528
- "div",
1529
- {
1530
- style: {
1531
- padding: "12px",
1532
- fontSize: "12px",
1533
- display: "flex",
1534
- flexDirection: "column",
1535
- gap: "4px"
1536
- }
1537
- },
1538
- /* @__PURE__ */ React4.createElement("span", null, "No connected users")
1539
- ))
1540
- ),
1541
- /* @__PURE__ */ React4.createElement(
1542
- DisclosureSection,
1543
- {
1544
- title: /* @__PURE__ */ React4.createElement(TitleLabel, null, "Data", /* @__PURE__ */ React4.createElement(
1545
- ColoredDot,
1546
- {
1547
- type: multipeerStateInitialized ? "success" : "error"
1548
- }
1549
- )),
1550
- colorScheme,
1551
- setOpen: setShowData,
1552
- open: showData,
1553
- right: /* @__PURE__ */ React4.createElement(
1554
- "span",
1555
- {
1556
- style: {
1557
- display: "flex",
1558
- gap: "4px"
1559
- }
1560
- },
1561
- /* @__PURE__ */ React4.createElement(
1562
- SmallButton,
1563
- {
1564
- theme,
1565
- onClick: () => {
1566
- noyaManager.forceInit();
1567
- }
1568
- },
1569
- "Reset"
1570
- )
1571
- )
1572
- },
1573
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ React4.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React4.createElement(
1574
- ObjectInspector,
1575
- {
1576
- name: multiplayerStateManager.schema ? "state" : void 0,
1577
- data: state,
1578
- theme
1579
- }
1580
- )), multiplayerStateManager.schema && /* @__PURE__ */ React4.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React4.createElement(
1581
- ObjectInspector,
1582
- {
1583
- name: "schema",
1584
- data: multiplayerStateManager.schema,
1585
- theme
1586
- }
1587
- )))
1588
- ),
1589
- /* @__PURE__ */ React4.createElement(
1590
- DisclosureSection,
1591
- {
1592
- open: showHistory,
1593
- setOpen: setShowHistory,
1594
- title: "History",
1595
- colorScheme,
1596
- right: /* @__PURE__ */ React4.createElement(
1597
- "span",
1598
- {
1599
- style: {
1600
- display: "flex",
1601
- gap: "4px"
1602
- }
1603
- },
1604
- /* @__PURE__ */ React4.createElement(
1605
- SmallButton,
1606
- {
1607
- disabled: !historySnapshot.canUndo,
1608
- theme,
1609
- onClick: () => {
1610
- multiplayerStateManager.undo();
1611
- }
1612
- },
1613
- /* @__PURE__ */ React4.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React4.createElement(
1614
- "svg",
1615
- {
1616
- xmlns: "http://www.w3.org/2000/svg",
1617
- width: "1em",
1618
- height: "1em",
1619
- viewBox: "0 0 20 20"
1620
- },
1621
- /* @__PURE__ */ React4.createElement(
1622
- "path",
1623
- {
1624
- fill: "currentColor",
1625
- 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"
1626
- }
1627
- )
1628
- ))
1629
- ),
1630
- /* @__PURE__ */ React4.createElement(
1631
- SmallButton,
1632
- {
1633
- disabled: !historySnapshot.canRedo,
1634
- theme,
1635
- onClick: () => {
1636
- multiplayerStateManager.redo();
1637
- }
1638
- },
1639
- /* @__PURE__ */ React4.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React4.createElement(
1640
- "svg",
1641
- {
1642
- xmlns: "http://www.w3.org/2000/svg",
1643
- width: "1em",
1644
- height: "1em",
1645
- viewBox: "0 0 20 20"
1646
- },
1647
- /* @__PURE__ */ React4.createElement(
1648
- "path",
1649
- {
1650
- fill: "currentColor",
1651
- 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"
1652
- }
1653
- )
1654
- ))
1655
- )
1656
- )
1657
- },
1658
- /* @__PURE__ */ React4.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ React4.createElement(
1659
- "div",
1660
- {
1661
- id: `${HISTORY_ELEMENT_PREFIX}0`,
1662
- style: {
1663
- borderBottom: `1px solid ${solidBorderColor}`,
1664
- fontSize: "12px",
1665
- fontFamily: "Menlo, monospace",
1666
- padding: "2px 12px 1px",
1667
- display: "flex",
1668
- alignItems: "center",
1669
- background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
1670
- }
1671
- },
1672
- /* @__PURE__ */ React4.createElement(
1673
- "span",
1674
- {
1675
- style: {
1676
- fontFamily: "Menlo, monospace",
1677
- fontSize: "11px",
1678
- borderRadius: 4,
1679
- display: "inline-block"
1680
- }
1681
- },
1682
- "Initial state"
1683
- )
1684
- ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ React4.createElement(
1685
- "div",
1686
- {
1687
- id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
1688
- key: index,
1689
- style: {
1690
- padding: "0px 12px 1px",
1691
- borderBottom: `1px solid ${solidBorderColor}`,
1692
- background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
1693
- }
1694
- },
1695
- "name" in entry.metadata && typeof entry.metadata.name === "string" && /* @__PURE__ */ React4.createElement(
1696
- "pre",
1697
- {
1698
- style: {
1699
- fontSize: "11px",
1700
- display: "flex",
1701
- flexWrap: "wrap",
1702
- margin: 0
1703
- }
1704
- },
1705
- entry.metadata.name
1706
- ),
1707
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React4.createElement(
1708
- "pre",
1709
- {
1710
- key: j,
1711
- style: {
1712
- fontSize: "11px",
1713
- display: "flex",
1714
- flexWrap: "wrap",
1715
- margin: 0
1716
- }
1717
- },
1718
- patch.op === "add" && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React4.createElement(ObjectInspector, { data: patch.value, theme })),
1719
- patch.op === "replace" && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React4.createElement(ObjectInspector, { data: patch.value, theme })),
1720
- patch.op === "remove" && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", { style: { color: theme.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React4.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
1721
- patch.op === "move" && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React4.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
1722
- ))
1723
- )))
1724
- ),
1725
- /* @__PURE__ */ React4.createElement(
1726
- DisclosureSection,
1727
- {
1728
- open: showAssets,
1729
- setOpen: setShowAssets,
1730
- title: /* @__PURE__ */ React4.createElement(TitleLabel, null, "Assets", /* @__PURE__ */ React4.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
1731
- colorScheme,
1732
- right: /* @__PURE__ */ React4.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React4.createElement(
1733
- SmallButton,
1734
- {
1735
- theme,
1736
- onClick: () => {
1737
- console.info(
1738
- "[StateInspector] Reloading assets",
1739
- noyaManager.id
1740
- );
1741
- assetManager.fetch();
1742
- }
1743
- },
1744
- "Reload"
1745
- ), /* @__PURE__ */ React4.createElement(
1746
- SmallButton,
1747
- {
1748
- theme,
1749
- onClick: () => {
1750
- const input = document.createElement("input");
1751
- input.type = "file";
1752
- input.onchange = () => {
1753
- const file = input.files?.[0];
1754
- if (file) {
1755
- const reader = new FileReader();
1756
- reader.onload = () => {
1757
- const buffer = reader.result;
1758
- assetManager.create(new Uint8Array(buffer));
1759
- };
1760
- reader.readAsArrayBuffer(file);
1761
- }
1762
- };
1763
- input.click();
1764
- }
1765
- },
1766
- "Upload"
1767
- ))
1768
- },
1769
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, assets.map((asset) => /* @__PURE__ */ React4.createElement(InspectorRow, { key: asset.id, colorScheme }, /* @__PURE__ */ React4.createElement(ObjectInspector, { name: asset.id, data: asset, theme }), /* @__PURE__ */ React4.createElement(
1770
- SmallButton,
1771
- {
1772
- theme,
1773
- onClick: () => assetManager.delete(asset.id)
1774
- },
1775
- "Delete"
1776
- ))))
1777
- ),
1778
- /* @__PURE__ */ React4.createElement(
1779
- DisclosureSection,
1780
- {
1781
- title: /* @__PURE__ */ React4.createElement(TitleLabel, null, "Secrets", /* @__PURE__ */ React4.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
1782
- colorScheme,
1783
- open: showSecrets,
1784
- setOpen: setShowSecrets,
1785
- right: /* @__PURE__ */ React4.createElement(
1786
- SmallButton,
1787
- {
1788
- theme,
1789
- onClick: () => {
1790
- const name = prompt("Enter secret name");
1791
- if (!name) return;
1792
- const value = prompt("Enter secret value");
1793
- if (!value) return;
1794
- secretManager.createSecret(name, value);
1795
- }
1796
- },
1797
- "Create"
1798
- )
1799
- },
1800
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, secrets.map((secret) => /* @__PURE__ */ React4.createElement(InspectorRow, { key: secret.id, colorScheme }, /* @__PURE__ */ React4.createElement(ObjectInspector, { data: secret, theme }), /* @__PURE__ */ React4.createElement(
1801
- SmallButton,
1802
- {
1803
- theme,
1804
- onClick: () => secretManager.deleteSecret(secret.name)
1805
- },
1806
- "Delete"
1807
- ))))
1808
- ),
1809
- " ",
1810
- /* @__PURE__ */ React4.createElement(
1811
- DisclosureSection,
1812
- {
1813
- open: showInputs,
1814
- setOpen: setShowInputs,
1815
- title: /* @__PURE__ */ React4.createElement(TitleLabel, null, "Inputs", /* @__PURE__ */ React4.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
1816
- colorScheme
1817
- },
1818
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, inputs?.map((input) => /* @__PURE__ */ React4.createElement(InspectorRow, { key: input.id, colorScheme }, /* @__PURE__ */ React4.createElement(ObjectInspector, { data: input, theme }))), !inputs?.length && /* @__PURE__ */ React4.createElement(
1819
- "div",
1820
- {
1821
- style: {
1822
- padding: "12px",
1823
- fontSize: "12px",
1824
- display: "flex",
1825
- flexDirection: "column",
1826
- gap: "4px"
1827
- }
1828
- },
1829
- /* @__PURE__ */ React4.createElement("span", null, "No inputs")
1830
- ))
1831
- ),
1832
- /* @__PURE__ */ React4.createElement(
1833
- DisclosureSection,
1834
- {
1835
- open: showOutputTransforms,
1836
- setOpen: setShowOutputTransforms,
1837
- title: /* @__PURE__ */ React4.createElement(TitleLabel, null, "Output Transforms", /* @__PURE__ */ React4.createElement(
1838
- ColoredDot,
1839
- {
1840
- type: outputTransformsInitialized ? "success" : "error"
1841
- }
1842
- )),
1843
- colorScheme
1844
- },
1845
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, outputTransforms?.map((transform) => /* @__PURE__ */ React4.createElement(InspectorRow, { key: transform.id, colorScheme }, /* @__PURE__ */ React4.createElement(ObjectInspector, { data: transform, theme }))), !outputTransforms?.length && /* @__PURE__ */ React4.createElement(
1846
- "div",
1847
- {
1848
- style: {
1849
- padding: "12px",
1850
- fontSize: "12px",
1851
- display: "flex",
1852
- flexDirection: "column",
1853
- gap: "4px"
1854
- }
1855
- },
1856
- /* @__PURE__ */ React4.createElement("span", null, "No output transforms")
1857
- ))
1858
- ),
1859
- /* @__PURE__ */ React4.createElement(
1860
- DisclosureSection,
1861
- {
1862
- title: "Tasks",
1863
- colorScheme,
1864
- open: showTasks,
1865
- setOpen: setShowTasks
1866
- },
1867
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ React4.createElement(
1868
- InspectorRow,
1869
- {
1870
- key: task.id,
1871
- colorScheme,
1872
- style: {
1873
- backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
1874
- }
1875
- },
1876
- /* @__PURE__ */ React4.createElement(
1877
- ObjectInspector,
1878
- {
1879
- name: task.name,
1880
- data: task.payload,
1881
- theme
1882
- }
1883
- )
1884
- )))
1885
- ),
1886
- /* @__PURE__ */ React4.createElement(
1887
- DisclosureSection,
1888
- {
1889
- open: showEphemeral,
1890
- setOpen: setShowEphemeral,
1891
- title: "Ephemeral User Data",
1892
- colorScheme
1893
- },
1894
- /* @__PURE__ */ React4.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React4.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ React4.createElement(
1895
- ObjectInspector,
1896
- {
1897
- name: key,
1898
- data: value,
1899
- theme,
1900
- expandLevel: 10
1901
- }
1902
- ))))
1903
- ),
1904
- /* @__PURE__ */ React4.createElement(
1905
- DisclosureSection,
1906
- {
1907
- open: showEvents,
1908
- setOpen: setShowEvents,
1909
- title: "Events",
1910
- colorScheme
1911
- },
1912
- /* @__PURE__ */ React4.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
1913
- (event, index) => event.type === "stateChange" ? /* @__PURE__ */ React4.createElement(InspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ React4.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ React4.createElement(
1914
- InspectorRow,
1915
- {
1916
- key: index,
1917
- colorScheme,
1918
- variant: event.type === "send" ? "up" : "down",
1919
- style: {
1920
- padding: "0px 12px 1px"
1921
- }
1922
- },
1923
- /* @__PURE__ */ React4.createElement(
1924
- ObjectInspector,
1925
- {
1926
- data: event.type === "error" ? event.error : event.message,
1927
- theme,
1928
- nodeRenderer: ({
1929
- depth,
1930
- name,
1931
- data,
1932
- isNonenumerable
1933
- }) => {
1934
- const direction = event.type === "send" ? "up" : "down";
1935
- return depth === 0 ? /* @__PURE__ */ React4.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React4.createElement(
1936
- ObjectLabel,
1937
- {
1938
- direction,
1939
- name,
1940
- data,
1941
- isNonenumerable
1942
- }
1943
- );
1944
- }
1945
- }
1946
- )
1947
- )
1948
- ), !connectionEvents && /* @__PURE__ */ React4.createElement(
1949
- "div",
1950
- {
1951
- style: {
1952
- padding: "12px",
1953
- fontSize: "12px",
1954
- display: "flex",
1955
- flexDirection: "column",
1956
- gap: "4px"
1957
- }
1958
- },
1959
- /* @__PURE__ */ React4.createElement("span", null, "No recorded events")
1960
- ))
1961
- )
1962
- );
1963
- });
1964
- var ObjectRootLabel = ({ name, data, direction }) => {
1965
- if (typeof name === "string") {
1966
- return /* @__PURE__ */ React4.createElement("span", null, /* @__PURE__ */ React4.createElement(ObjectName, { name }), /* @__PURE__ */ React4.createElement("span", null, ": "), /* @__PURE__ */ React4.createElement(ObjectPreview, { data }));
1967
- }
1968
- if (direction === "up" || direction === "down") {
1969
- const arrow = direction === "up" ? "\u2191" : "\u2193";
1970
- return /* @__PURE__ */ React4.createElement("span", null, /* @__PURE__ */ React4.createElement(
1971
- "span",
1972
- {
1973
- style: {
1974
- background: direction === "up" ? "rgba(0,255,0,0.2)" : "rgba(255,0,0,0.2)",
1975
- // color: "white",
1976
- width: 12,
1977
- height: 12,
1978
- borderRadius: 2,
1979
- display: "inline-flex",
1980
- justifyContent: "center",
1981
- alignItems: "center",
1982
- marginRight: 4,
1983
- lineHeight: "12px"
1984
- }
1985
- },
1986
- arrow
1987
- ), /* @__PURE__ */ React4.createElement(ObjectPreview, { data }));
1988
- } else {
1989
- return /* @__PURE__ */ React4.createElement(ObjectPreview, { data });
1990
- }
1991
- };
1992
- function Arrow({
1993
- expanded,
1994
- onClick,
1995
- style
1996
- }) {
1997
- return /* @__PURE__ */ React4.createElement(
1998
- "span",
1999
- {
2000
- role: "button",
2001
- onClick,
2002
- style: {
2003
- display: "inline-block",
2004
- textAlign: "center",
2005
- transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
2006
- fontFamily: "Menlo, monospace",
2007
- ...style
2008
- }
2009
- },
2010
- "\u25BC"
2011
- );
2012
- }
2013
- function pathToString(extendedPath) {
2014
- return extendedPath.map(
2015
- (key) => typeof key === "object" ? `:${ellipsis(key.id.toString(), 8, "middle")}` : key
2016
- ).map(
2017
- (key, index) => index === 0 || typeof key === "string" && key.startsWith(":") ? key : `.${key}`
2018
- ).join("");
2019
- }
2020
- function ellipsis(str, maxLength, position = "end") {
2021
- if (str.length <= maxLength) return str;
2022
- switch (position) {
2023
- case "start":
2024
- return `\u2026${str.slice(str.length - maxLength)}`;
2025
- case "middle":
2026
- const halfLength = Math.floor(maxLength / 2);
2027
- return `${str.slice(0, halfLength)}\u2026${str.slice(str.length - halfLength)}`;
2028
- case "end":
2029
- return `${str.slice(0, maxLength)}\u2026`;
2030
- }
2031
- }
2032
- function SmallButton({
2033
- children,
2034
- onClick,
2035
- style,
2036
- theme,
2037
- disabled
2038
- }) {
2039
- return /* @__PURE__ */ React4.createElement(
2040
- "button",
2041
- {
2042
- type: "button",
2043
- disabled,
2044
- onClick: (event) => {
2045
- event.stopPropagation();
2046
- onClick();
2047
- },
2048
- style: {
2049
- flex: "0",
2050
- appearance: "none",
2051
- background: "none",
2052
- color: theme.BASE_COLOR,
2053
- opacity: disabled ? 0.25 : 1,
2054
- border: "none",
2055
- fontSize: "12px",
2056
- whiteSpace: "nowrap",
2057
- display: "inline-flex",
2058
- alignItems: "center",
2059
- justifyContent: "center",
2060
- padding: "0",
2061
- cursor: "pointer",
2062
- ...style
2063
- }
2064
- },
2065
- children
2066
- );
2067
- }
2068
- function ColoredDot({ type }) {
2069
- return /* @__PURE__ */ React4.createElement(
2070
- "span",
2071
- {
2072
- style: {
2073
- display: "inline-block",
2074
- width: 6,
2075
- height: 6,
2076
- background: type === "success" ? "rgba(0,200,0,0.8)" : "rgba(200,0,0,0.8)",
2077
- borderRadius: "50%",
2078
- verticalAlign: "middle"
2079
- }
2080
- }
2081
- );
2082
- }
2083
- function TitleLabel({ children }) {
2084
- return /* @__PURE__ */ React4.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
2085
- }
2086
-
2087
- // src/inspector/useStateInspector.tsx
2088
- function createShadowRootElement() {
2089
- const host = document.createElement("div");
2090
- host.id = "noya-multiplayer-react-inspector-host";
2091
- const shadowRoot = host.attachShadow({ mode: "open" });
2092
- const container = document.createElement("div");
2093
- shadowRoot.appendChild(container);
2094
- return { host, container };
2095
- }
2096
- function useStateInspector({
2097
- noyaManager,
2098
- disabled = false,
2099
- colorScheme,
2100
- anchor
2101
- }) {
2102
- const [root, setRoot] = React5.useState(null);
2103
- useLayoutEffect2(() => {
2104
- if (disabled) return;
2105
- const { host, container } = createShadowRootElement();
2106
- const root2 = createRoot(container);
2107
- document.body.appendChild(host);
2108
- setRoot(root2);
2109
- return () => {
2110
- document.body.removeChild(host);
2111
- };
2112
- }, [disabled]);
2113
- useLayoutEffect2(() => {
2114
- if (!root) return;
2115
- root.render(
2116
- /* @__PURE__ */ React5.createElement(
2117
- StateInspector,
2118
- {
2119
- colorScheme,
2120
- anchor,
2121
- noyaManager
2122
- }
2123
- )
2124
- );
2125
- }, [noyaManager, anchor, colorScheme, root]);
2126
- }
2127
-
2128
- // src/hooks.ts
2129
- function useSyncStateManager(stateManager, path) {
2130
- const getSnapshot = useCallback(
2131
- () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
2132
- [stateManager, path]
2133
- );
2134
- return useSyncExternalStore2(
2135
- stateManager.addListener,
2136
- getSnapshot,
2137
- getSnapshot
2138
- );
2139
- }
2140
- function useManagedState(createInitialState, options) {
2141
- const [stateManager] = useState2(
2142
- () => new StateManager(createInitialState(), options)
2143
- );
2144
- const state = useSyncStateManager(stateManager);
2145
- const setState = useCallback(
2146
- (...args) => {
2147
- const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
2148
- if (metadata === void 0) {
2149
- const performActionNoMetadata = stateManager.performAction;
2150
- if (action instanceof Function) {
2151
- performActionNoMetadata({
2152
- run: action,
2153
- undo: () => state
2154
- });
2155
- } else {
2156
- performActionNoMetadata({
2157
- run: () => action,
2158
- undo: () => state
2159
- });
2160
- }
2161
- } else {
2162
- const performActionWithMetadata = stateManager.performAction;
2163
- if (action instanceof Function) {
2164
- performActionWithMetadata(metadata, {
2165
- run: action,
2166
- undo: () => state
2167
- });
2168
- } else {
2169
- performActionWithMetadata(metadata, {
2170
- run: () => action,
2171
- undo: () => state
2172
- });
2173
- }
2174
- }
2175
- },
2176
- [state, stateManager]
2177
- );
2178
- return [state, setState, stateManager];
2179
- }
2180
- function useManagedHistory(stateManager) {
2181
- return useSyncExternalStore2(
2182
- stateManager.historyEmittor.addListener,
2183
- stateManager.getHistorySnapshot,
2184
- stateManager.getHistorySnapshot
2185
- );
2186
- }
2187
- var defaultStubSync = stubSync();
2188
- function useMultiplayerState(initialState, options) {
2189
- const {
2190
- sync = defaultStubSync,
2191
- inspector,
2192
- ...rest
2193
- } = options ?? {};
2194
- const [noyaManager] = useState2(
2195
- () => new NoyaManager(initialState, rest)
2196
- );
2197
- const state = useObservable(
2198
- noyaManager.multiplayerStateManager.optimisticState$
2199
- );
2200
- const assets = useObservable(noyaManager.assetManager.assets$);
2201
- const extras = useMemo2(() => {
2202
- return {
2203
- noyaManager,
2204
- taskManager: noyaManager.taskManager,
2205
- connectionEventManager: noyaManager.connectionEventManager,
2206
- connectedUsersManager: noyaManager.connectedUsersManager,
2207
- ephemeralUserDataManager: noyaManager.ephemeralUserDataManager,
2208
- multiplayerStateManager: noyaManager.multiplayerStateManager,
2209
- assetManager: noyaManager.assetManager,
2210
- aiManager: noyaManager.aiManager,
2211
- rpcManager: noyaManager.rpcManager,
2212
- pipelineManager: noyaManager.pipelineManager,
2213
- secretManager: noyaManager.secretManager,
2214
- menuItemsManager: noyaManager.menuManager,
2215
- createAsset: noyaManager.assetManager.create,
2216
- deleteAsset: noyaManager.assetManager.delete,
2217
- assets
2218
- };
2219
- }, [noyaManager, assets]);
2220
- const syncRef = useRef(sync);
2221
- useEffect3(() => {
2222
- if (syncRef.current) {
2223
- return syncRef.current({ noyaManager });
2224
- }
2225
- }, [noyaManager]);
2226
- useErrorOverlay(noyaManager);
2227
- useStateInspector({
2228
- noyaManager,
2229
- disabled: !inspector,
2230
- ...typeof inspector === "object" && inspector
2231
- });
2232
- return [state, noyaManager.multiplayerStateManager.setState, extras];
2233
- }
2234
- function useErrorOverlay(noyaManager) {
2235
- const unrecoverableError = useObservable(noyaManager.unrecoverableError);
2236
- useEffect3(() => {
2237
- if (!unrecoverableError) return;
2238
- const el = document.createElement("div");
2239
- el.id = "noya-multiplayer-react-error-overlay";
2240
- document.body.appendChild(el);
2241
- const root = createRoot2(el);
2242
- root.render(createElement2(ErrorOverlay, { error: unrecoverableError }));
2243
- return () => {
2244
- root.unmount();
2245
- el.remove();
2246
- };
2247
- });
2248
- }
2249
-
2250
- // ../../node_modules/@sinclair/typebox/build/esm/type/symbols/symbols.mjs
2251
- var TransformKind = Symbol.for("TypeBox.Transform");
2252
- var ReadonlyKind = Symbol.for("TypeBox.Readonly");
2253
- var OptionalKind = Symbol.for("TypeBox.Optional");
2254
- var Hint = Symbol.for("TypeBox.Hint");
2255
- var Kind = Symbol.for("TypeBox.Kind");
2256
-
2257
- // ../../node_modules/@sinclair/typebox/build/esm/type/any/any.mjs
2258
- function Any(options = {}) {
2259
- return { ...options, [Kind]: "Any" };
2260
- }
2261
-
2262
- // ../../node_modules/@sinclair/typebox/build/esm/type/guard/value.mjs
2263
- var value_exports = {};
2264
- __export(value_exports, {
2265
- IsArray: () => IsArray,
2266
- IsAsyncIterator: () => IsAsyncIterator,
2267
- IsBigInt: () => IsBigInt,
2268
- IsBoolean: () => IsBoolean,
2269
- IsDate: () => IsDate,
2270
- IsFunction: () => IsFunction,
2271
- IsIterator: () => IsIterator,
2272
- IsNull: () => IsNull,
2273
- IsNumber: () => IsNumber,
2274
- IsObject: () => IsObject,
2275
- IsRegExp: () => IsRegExp,
2276
- IsString: () => IsString,
2277
- IsSymbol: () => IsSymbol,
2278
- IsUint8Array: () => IsUint8Array,
2279
- IsUndefined: () => IsUndefined
2280
- });
2281
- function IsAsyncIterator(value) {
2282
- return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.asyncIterator in value;
2283
- }
2284
- function IsArray(value) {
2285
- return Array.isArray(value);
2286
- }
2287
- function IsBigInt(value) {
2288
- return typeof value === "bigint";
2289
- }
2290
- function IsBoolean(value) {
2291
- return typeof value === "boolean";
2292
- }
2293
- function IsDate(value) {
2294
- return value instanceof globalThis.Date;
2295
- }
2296
- function IsFunction(value) {
2297
- return typeof value === "function";
2298
- }
2299
- function IsIterator(value) {
2300
- return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.iterator in value;
2301
- }
2302
- function IsNull(value) {
2303
- return value === null;
2304
- }
2305
- function IsNumber(value) {
2306
- return typeof value === "number";
2307
- }
2308
- function IsObject(value) {
2309
- return typeof value === "object" && value !== null;
2310
- }
2311
- function IsRegExp(value) {
2312
- return value instanceof globalThis.RegExp;
2313
- }
2314
- function IsString(value) {
2315
- return typeof value === "string";
2316
- }
2317
- function IsSymbol(value) {
2318
- return typeof value === "symbol";
2319
- }
2320
- function IsUint8Array(value) {
2321
- return value instanceof globalThis.Uint8Array;
2322
- }
2323
- function IsUndefined(value) {
2324
- return value === void 0;
2325
- }
2326
-
2327
- // ../../node_modules/@sinclair/typebox/build/esm/type/clone/value.mjs
2328
- function ArrayType(value) {
2329
- return value.map((value2) => Visit(value2));
2330
- }
2331
- function DateType(value) {
2332
- return new Date(value.getTime());
2333
- }
2334
- function Uint8ArrayType(value) {
2335
- return new Uint8Array(value);
2336
- }
2337
- function RegExpType(value) {
2338
- return new RegExp(value.source, value.flags);
2339
- }
2340
- function ObjectType(value) {
2341
- const result = {};
2342
- for (const key of Object.getOwnPropertyNames(value)) {
2343
- result[key] = Visit(value[key]);
971
+ function IsBoolean(value) {
972
+ return typeof value === "boolean";
973
+ }
974
+ function IsDate(value) {
975
+ return value instanceof globalThis.Date;
976
+ }
977
+ function IsFunction(value) {
978
+ return typeof value === "function";
979
+ }
980
+ function IsIterator(value) {
981
+ return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.iterator in value;
982
+ }
983
+ function IsNull(value) {
984
+ return value === null;
985
+ }
986
+ function IsNumber(value) {
987
+ return typeof value === "number";
988
+ }
989
+ function IsObject(value) {
990
+ return typeof value === "object" && value !== null;
991
+ }
992
+ function IsRegExp(value) {
993
+ return value instanceof globalThis.RegExp;
994
+ }
995
+ function IsString(value) {
996
+ return typeof value === "string";
997
+ }
998
+ function IsSymbol(value) {
999
+ return typeof value === "symbol";
1000
+ }
1001
+ function IsUint8Array(value) {
1002
+ return value instanceof globalThis.Uint8Array;
1003
+ }
1004
+ function IsUndefined(value) {
1005
+ return value === void 0;
1006
+ }
1007
+
1008
+ // ../../node_modules/@sinclair/typebox/build/esm/type/clone/value.mjs
1009
+ function ArrayType(value) {
1010
+ return value.map((value2) => Visit(value2));
1011
+ }
1012
+ function DateType(value) {
1013
+ return new Date(value.getTime());
1014
+ }
1015
+ function Uint8ArrayType(value) {
1016
+ return new Uint8Array(value);
1017
+ }
1018
+ function RegExpType(value) {
1019
+ return new RegExp(value.source, value.flags);
1020
+ }
1021
+ function ObjectType(value) {
1022
+ const result = {};
1023
+ for (const key of Object.getOwnPropertyNames(value)) {
1024
+ result[key] = Visit(value[key]);
2344
1025
  }
2345
1026
  for (const key of Object.getOwnPropertySymbols(value)) {
2346
1027
  result[key] = Visit(value[key]);
@@ -4671,6 +3352,45 @@ function Void(options = {}) {
4671
3352
  // ../../node_modules/@sinclair/typebox/build/esm/type/type/index.mjs
4672
3353
  var Type = type_exports3;
4673
3354
 
3355
+ // ../noya-schemas/src/filesSchema.ts
3356
+ var encodingSchema = Type.Union([
3357
+ Type.Literal("utf-8"),
3358
+ Type.Literal("base64")
3359
+ ]);
3360
+ var folderMediaItemSchema = Type.Object({
3361
+ id: Type.String({ format: "uuid", default: "" }),
3362
+ kind: Type.Literal("folder")
3363
+ });
3364
+ var assetMediaItemSchema = Type.Object({
3365
+ id: Type.String({ format: "uuid", default: "" }),
3366
+ kind: Type.Literal("asset"),
3367
+ assetId: Type.String()
3368
+ });
3369
+ var fileSchema = Type.Object({
3370
+ id: Type.String({ format: "uuid", default: "" }),
3371
+ kind: Type.Literal("file"),
3372
+ content: Type.String(),
3373
+ encoding: encodingSchema
3374
+ });
3375
+ var mediaItemSchema = Type.Union(
3376
+ [folderMediaItemSchema, assetMediaItemSchema, fileSchema],
3377
+ {
3378
+ discriminator: "kind"
3379
+ }
3380
+ );
3381
+ var mediaMapSchema = Type.Record(Type.String(), mediaItemSchema);
3382
+
3383
+ // ../noya-schemas/src/gitHubSchema.ts
3384
+ var repositorySchema = Type.Object({
3385
+ owner: Type.Optional(Type.String()),
3386
+ name: Type.Optional(Type.String()),
3387
+ ref: Type.Optional(Type.String()),
3388
+ path: Type.Optional(Type.String())
3389
+ });
3390
+ var gistSchema = Type.Object({
3391
+ id: Type.Optional(Type.String())
3392
+ });
3393
+
4674
3394
  // ../noya-schemas/src/jsonSchema.ts
4675
3395
  var jsonSchema = Type.Recursive(
4676
3396
  (This) => Type.Union(
@@ -4721,274 +3441,1560 @@ var jsonSchema = Type.Recursive(
4721
3441
  }
4722
3442
  );
4723
3443
 
4724
- // ../noya-schemas/src/input.ts
4725
- function Nullable(type) {
4726
- return Type.Union([type, Type.Null()]);
4727
- }
4728
- var inputSchemaBase = {
4729
- id: Type.String({ format: "uuid", default: "" }),
4730
- name: Type.String(),
4731
- description: Nullable(Type.String()),
4732
- required: Type.Boolean({ default: false })
4733
- };
4734
- var fileInputSchema = Type.Object({
4735
- ...inputSchemaBase,
4736
- kind: Type.Literal("file"),
4737
- toolId: Nullable(Type.String())
4738
- });
4739
- var dataInputSchema = Type.Object({
4740
- ...inputSchemaBase,
4741
- kind: Type.Literal("data"),
4742
- schema: Nullable(jsonSchema)
4743
- });
4744
- var inputSchema = Type.Union([fileInputSchema, dataInputSchema], {
4745
- discriminator: "kind"
3444
+ // ../noya-schemas/src/input.ts
3445
+ function Nullable(type) {
3446
+ return Type.Union([type, Type.Null()]);
3447
+ }
3448
+ var inputSchemaBase = {
3449
+ id: Type.String({ format: "uuid", default: "" }),
3450
+ name: Type.String(),
3451
+ description: Nullable(Type.String()),
3452
+ required: Type.Boolean({ default: false })
3453
+ };
3454
+ var fileInputSchema = Type.Object({
3455
+ ...inputSchemaBase,
3456
+ kind: Type.Literal("file"),
3457
+ toolId: Nullable(Type.String())
3458
+ });
3459
+ var dataInputSchema = Type.Object({
3460
+ ...inputSchemaBase,
3461
+ kind: Type.Literal("data"),
3462
+ schema: Nullable(jsonSchema)
3463
+ });
3464
+ var secretInputSchema = Type.Object({
3465
+ ...inputSchemaBase,
3466
+ kind: Type.Literal("secret")
3467
+ });
3468
+ var inputSchema = Type.Union(
3469
+ [fileInputSchema, dataInputSchema, secretInputSchema],
3470
+ {
3471
+ discriminator: "kind"
3472
+ }
3473
+ );
3474
+ var outputTransformSchemaBase = {
3475
+ id: Type.String({ format: "uuid", default: "" }),
3476
+ order: Type.Number()
3477
+ };
3478
+ var scriptOutputTransformSchema = Type.Object({
3479
+ ...outputTransformSchemaBase,
3480
+ kind: Type.Literal("script"),
3481
+ location: Type.Union([Type.Literal("state"), Type.Literal("url")]),
3482
+ value: Type.String()
3483
+ });
3484
+ var jsonPointerOutputTransformSchema = Type.Object({
3485
+ ...outputTransformSchemaBase,
3486
+ kind: Type.Literal("jsonPointer"),
3487
+ value: Type.String()
3488
+ });
3489
+ var outputTransformSchema = Type.Union(
3490
+ [scriptOutputTransformSchema, jsonPointerOutputTransformSchema],
3491
+ { discriminator: "kind" }
3492
+ );
3493
+
3494
+ // ../../node_modules/@sinclair/typebox/build/esm/value/guard/guard.mjs
3495
+ function IsObject4(value) {
3496
+ return value !== null && typeof value === "object";
3497
+ }
3498
+ function IsArray4(value) {
3499
+ return Array.isArray(value) && !ArrayBuffer.isView(value);
3500
+ }
3501
+ function IsUndefined4(value) {
3502
+ return value === void 0;
3503
+ }
3504
+ function IsNumber4(value) {
3505
+ return typeof value === "number";
3506
+ }
3507
+
3508
+ // ../../node_modules/@sinclair/typebox/build/esm/system/policy.mjs
3509
+ var TypeSystemPolicy;
3510
+ (function(TypeSystemPolicy2) {
3511
+ TypeSystemPolicy2.ExactOptionalPropertyTypes = false;
3512
+ TypeSystemPolicy2.AllowArrayObject = false;
3513
+ TypeSystemPolicy2.AllowNaN = false;
3514
+ TypeSystemPolicy2.AllowNullVoid = false;
3515
+ function IsExactOptionalProperty(value, key) {
3516
+ return TypeSystemPolicy2.ExactOptionalPropertyTypes ? key in value : value[key] !== void 0;
3517
+ }
3518
+ TypeSystemPolicy2.IsExactOptionalProperty = IsExactOptionalProperty;
3519
+ function IsObjectLike(value) {
3520
+ const isObject = IsObject4(value);
3521
+ return TypeSystemPolicy2.AllowArrayObject ? isObject : isObject && !IsArray4(value);
3522
+ }
3523
+ TypeSystemPolicy2.IsObjectLike = IsObjectLike;
3524
+ function IsRecordLike(value) {
3525
+ return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array);
3526
+ }
3527
+ TypeSystemPolicy2.IsRecordLike = IsRecordLike;
3528
+ function IsNumberLike(value) {
3529
+ return TypeSystemPolicy2.AllowNaN ? IsNumber4(value) : Number.isFinite(value);
3530
+ }
3531
+ TypeSystemPolicy2.IsNumberLike = IsNumberLike;
3532
+ function IsVoidLike(value) {
3533
+ const isUndefined = IsUndefined4(value);
3534
+ return TypeSystemPolicy2.AllowNullVoid ? isUndefined || value === null : isUndefined;
3535
+ }
3536
+ TypeSystemPolicy2.IsVoidLike = IsVoidLike;
3537
+ })(TypeSystemPolicy || (TypeSystemPolicy = {}));
3538
+
3539
+ // ../../node_modules/@sinclair/typebox/build/esm/system/system.mjs
3540
+ var TypeSystemDuplicateTypeKind = class extends TypeBoxError {
3541
+ constructor(kind) {
3542
+ super(`Duplicate type kind '${kind}' detected`);
3543
+ }
3544
+ };
3545
+ var TypeSystemDuplicateFormat = class extends TypeBoxError {
3546
+ constructor(kind) {
3547
+ super(`Duplicate string format '${kind}' detected`);
3548
+ }
3549
+ };
3550
+ var TypeSystem;
3551
+ (function(TypeSystem2) {
3552
+ function Type2(kind, check) {
3553
+ if (type_exports2.Has(kind))
3554
+ throw new TypeSystemDuplicateTypeKind(kind);
3555
+ type_exports2.Set(kind, check);
3556
+ return (options = {}) => Unsafe({ ...options, [Kind]: kind });
3557
+ }
3558
+ TypeSystem2.Type = Type2;
3559
+ function Format(format, check) {
3560
+ if (format_exports.Has(format))
3561
+ throw new TypeSystemDuplicateFormat(format);
3562
+ format_exports.Set(format, check);
3563
+ return format;
3564
+ }
3565
+ TypeSystem2.Format = Format;
3566
+ })(TypeSystem || (TypeSystem = {}));
3567
+
3568
+ // ../../node_modules/@sinclair/typebox/build/esm/value/hash/hash.mjs
3569
+ var ByteMarker;
3570
+ (function(ByteMarker2) {
3571
+ ByteMarker2[ByteMarker2["Undefined"] = 0] = "Undefined";
3572
+ ByteMarker2[ByteMarker2["Null"] = 1] = "Null";
3573
+ ByteMarker2[ByteMarker2["Boolean"] = 2] = "Boolean";
3574
+ ByteMarker2[ByteMarker2["Number"] = 3] = "Number";
3575
+ ByteMarker2[ByteMarker2["String"] = 4] = "String";
3576
+ ByteMarker2[ByteMarker2["Object"] = 5] = "Object";
3577
+ ByteMarker2[ByteMarker2["Array"] = 6] = "Array";
3578
+ ByteMarker2[ByteMarker2["Date"] = 7] = "Date";
3579
+ ByteMarker2[ByteMarker2["Uint8Array"] = 8] = "Uint8Array";
3580
+ ByteMarker2[ByteMarker2["Symbol"] = 9] = "Symbol";
3581
+ ByteMarker2[ByteMarker2["BigInt"] = 10] = "BigInt";
3582
+ })(ByteMarker || (ByteMarker = {}));
3583
+ var Accumulator = BigInt("14695981039346656037");
3584
+ var [Prime, Size] = [BigInt("1099511628211"), BigInt("2") ** BigInt("64")];
3585
+ var Bytes = Array.from({ length: 256 }).map((_, i) => BigInt(i));
3586
+ var F64 = new Float64Array(1);
3587
+ var F64In = new DataView(F64.buffer);
3588
+ var F64Out = new Uint8Array(F64.buffer);
3589
+
3590
+ // ../../node_modules/@sinclair/typebox/build/esm/errors/errors.mjs
3591
+ var ValueErrorType;
3592
+ (function(ValueErrorType2) {
3593
+ ValueErrorType2[ValueErrorType2["ArrayContains"] = 0] = "ArrayContains";
3594
+ ValueErrorType2[ValueErrorType2["ArrayMaxContains"] = 1] = "ArrayMaxContains";
3595
+ ValueErrorType2[ValueErrorType2["ArrayMaxItems"] = 2] = "ArrayMaxItems";
3596
+ ValueErrorType2[ValueErrorType2["ArrayMinContains"] = 3] = "ArrayMinContains";
3597
+ ValueErrorType2[ValueErrorType2["ArrayMinItems"] = 4] = "ArrayMinItems";
3598
+ ValueErrorType2[ValueErrorType2["ArrayUniqueItems"] = 5] = "ArrayUniqueItems";
3599
+ ValueErrorType2[ValueErrorType2["Array"] = 6] = "Array";
3600
+ ValueErrorType2[ValueErrorType2["AsyncIterator"] = 7] = "AsyncIterator";
3601
+ ValueErrorType2[ValueErrorType2["BigIntExclusiveMaximum"] = 8] = "BigIntExclusiveMaximum";
3602
+ ValueErrorType2[ValueErrorType2["BigIntExclusiveMinimum"] = 9] = "BigIntExclusiveMinimum";
3603
+ ValueErrorType2[ValueErrorType2["BigIntMaximum"] = 10] = "BigIntMaximum";
3604
+ ValueErrorType2[ValueErrorType2["BigIntMinimum"] = 11] = "BigIntMinimum";
3605
+ ValueErrorType2[ValueErrorType2["BigIntMultipleOf"] = 12] = "BigIntMultipleOf";
3606
+ ValueErrorType2[ValueErrorType2["BigInt"] = 13] = "BigInt";
3607
+ ValueErrorType2[ValueErrorType2["Boolean"] = 14] = "Boolean";
3608
+ ValueErrorType2[ValueErrorType2["DateExclusiveMaximumTimestamp"] = 15] = "DateExclusiveMaximumTimestamp";
3609
+ ValueErrorType2[ValueErrorType2["DateExclusiveMinimumTimestamp"] = 16] = "DateExclusiveMinimumTimestamp";
3610
+ ValueErrorType2[ValueErrorType2["DateMaximumTimestamp"] = 17] = "DateMaximumTimestamp";
3611
+ ValueErrorType2[ValueErrorType2["DateMinimumTimestamp"] = 18] = "DateMinimumTimestamp";
3612
+ ValueErrorType2[ValueErrorType2["DateMultipleOfTimestamp"] = 19] = "DateMultipleOfTimestamp";
3613
+ ValueErrorType2[ValueErrorType2["Date"] = 20] = "Date";
3614
+ ValueErrorType2[ValueErrorType2["Function"] = 21] = "Function";
3615
+ ValueErrorType2[ValueErrorType2["IntegerExclusiveMaximum"] = 22] = "IntegerExclusiveMaximum";
3616
+ ValueErrorType2[ValueErrorType2["IntegerExclusiveMinimum"] = 23] = "IntegerExclusiveMinimum";
3617
+ ValueErrorType2[ValueErrorType2["IntegerMaximum"] = 24] = "IntegerMaximum";
3618
+ ValueErrorType2[ValueErrorType2["IntegerMinimum"] = 25] = "IntegerMinimum";
3619
+ ValueErrorType2[ValueErrorType2["IntegerMultipleOf"] = 26] = "IntegerMultipleOf";
3620
+ ValueErrorType2[ValueErrorType2["Integer"] = 27] = "Integer";
3621
+ ValueErrorType2[ValueErrorType2["IntersectUnevaluatedProperties"] = 28] = "IntersectUnevaluatedProperties";
3622
+ ValueErrorType2[ValueErrorType2["Intersect"] = 29] = "Intersect";
3623
+ ValueErrorType2[ValueErrorType2["Iterator"] = 30] = "Iterator";
3624
+ ValueErrorType2[ValueErrorType2["Kind"] = 31] = "Kind";
3625
+ ValueErrorType2[ValueErrorType2["Literal"] = 32] = "Literal";
3626
+ ValueErrorType2[ValueErrorType2["Never"] = 33] = "Never";
3627
+ ValueErrorType2[ValueErrorType2["Not"] = 34] = "Not";
3628
+ ValueErrorType2[ValueErrorType2["Null"] = 35] = "Null";
3629
+ ValueErrorType2[ValueErrorType2["NumberExclusiveMaximum"] = 36] = "NumberExclusiveMaximum";
3630
+ ValueErrorType2[ValueErrorType2["NumberExclusiveMinimum"] = 37] = "NumberExclusiveMinimum";
3631
+ ValueErrorType2[ValueErrorType2["NumberMaximum"] = 38] = "NumberMaximum";
3632
+ ValueErrorType2[ValueErrorType2["NumberMinimum"] = 39] = "NumberMinimum";
3633
+ ValueErrorType2[ValueErrorType2["NumberMultipleOf"] = 40] = "NumberMultipleOf";
3634
+ ValueErrorType2[ValueErrorType2["Number"] = 41] = "Number";
3635
+ ValueErrorType2[ValueErrorType2["ObjectAdditionalProperties"] = 42] = "ObjectAdditionalProperties";
3636
+ ValueErrorType2[ValueErrorType2["ObjectMaxProperties"] = 43] = "ObjectMaxProperties";
3637
+ ValueErrorType2[ValueErrorType2["ObjectMinProperties"] = 44] = "ObjectMinProperties";
3638
+ ValueErrorType2[ValueErrorType2["ObjectRequiredProperty"] = 45] = "ObjectRequiredProperty";
3639
+ ValueErrorType2[ValueErrorType2["Object"] = 46] = "Object";
3640
+ ValueErrorType2[ValueErrorType2["Promise"] = 47] = "Promise";
3641
+ ValueErrorType2[ValueErrorType2["RegExp"] = 48] = "RegExp";
3642
+ ValueErrorType2[ValueErrorType2["StringFormatUnknown"] = 49] = "StringFormatUnknown";
3643
+ ValueErrorType2[ValueErrorType2["StringFormat"] = 50] = "StringFormat";
3644
+ ValueErrorType2[ValueErrorType2["StringMaxLength"] = 51] = "StringMaxLength";
3645
+ ValueErrorType2[ValueErrorType2["StringMinLength"] = 52] = "StringMinLength";
3646
+ ValueErrorType2[ValueErrorType2["StringPattern"] = 53] = "StringPattern";
3647
+ ValueErrorType2[ValueErrorType2["String"] = 54] = "String";
3648
+ ValueErrorType2[ValueErrorType2["Symbol"] = 55] = "Symbol";
3649
+ ValueErrorType2[ValueErrorType2["TupleLength"] = 56] = "TupleLength";
3650
+ ValueErrorType2[ValueErrorType2["Tuple"] = 57] = "Tuple";
3651
+ ValueErrorType2[ValueErrorType2["Uint8ArrayMaxByteLength"] = 58] = "Uint8ArrayMaxByteLength";
3652
+ ValueErrorType2[ValueErrorType2["Uint8ArrayMinByteLength"] = 59] = "Uint8ArrayMinByteLength";
3653
+ ValueErrorType2[ValueErrorType2["Uint8Array"] = 60] = "Uint8Array";
3654
+ ValueErrorType2[ValueErrorType2["Undefined"] = 61] = "Undefined";
3655
+ ValueErrorType2[ValueErrorType2["Union"] = 62] = "Union";
3656
+ ValueErrorType2[ValueErrorType2["Void"] = 63] = "Void";
3657
+ })(ValueErrorType || (ValueErrorType = {}));
3658
+
3659
+ // ../../node_modules/@sinclair/typebox/build/esm/value/delta/delta.mjs
3660
+ var Insert = Object2({
3661
+ type: Literal("insert"),
3662
+ path: String(),
3663
+ value: Unknown()
4746
3664
  });
4747
- var outputTransformSchemaBase = {
4748
- id: Type.String({ format: "uuid", default: "" }),
4749
- order: Type.Number()
4750
- };
4751
- var scriptOutputTransformSchema = Type.Object({
4752
- ...outputTransformSchemaBase,
4753
- kind: Type.Literal("script"),
4754
- location: Type.Union([Type.Literal("state"), Type.Literal("url")]),
4755
- value: Type.String()
3665
+ var Update = Object2({
3666
+ type: Literal("update"),
3667
+ path: String(),
3668
+ value: Unknown()
4756
3669
  });
4757
- var jsonPointerOutputTransformSchema = Type.Object({
4758
- ...outputTransformSchemaBase,
4759
- kind: Type.Literal("jsonPointer"),
4760
- value: Type.String()
3670
+ var Delete3 = Object2({
3671
+ type: Literal("delete"),
3672
+ path: String()
4761
3673
  });
4762
- var outputTransformSchema = Type.Union(
4763
- [scriptOutputTransformSchema, jsonPointerOutputTransformSchema],
4764
- { discriminator: "kind" }
4765
- );
3674
+ var Edit = Union([Insert, Update, Delete3]);
4766
3675
 
4767
- // ../../node_modules/@sinclair/typebox/build/esm/value/guard/guard.mjs
4768
- function IsObject4(value) {
4769
- return value !== null && typeof value === "object";
3676
+ // ../noya-schemas/src/SchemaTree.ts
3677
+ var import_tree_visit = __toESM(require_lib());
3678
+ var SchemaTree = (0, import_tree_visit.defineTree)((schema) => {
3679
+ if (type_exports.IsUnion(schema)) {
3680
+ return schema.anyOf;
3681
+ } else if (type_exports.IsObject(schema)) {
3682
+ return Object.values(schema.properties);
3683
+ } else if (type_exports.IsArray(schema)) {
3684
+ return [schema.items];
3685
+ }
3686
+ return [];
3687
+ }).withOptions({
3688
+ getLabel(node) {
3689
+ return node[Kind] ?? "<UnknownKind>";
3690
+ }
3691
+ });
3692
+ function findAllDefs(schema) {
3693
+ if (!schema) return [];
3694
+ return SchemaTree.flatMap(schema, (node) => {
3695
+ return node.$id ? [node] : [];
3696
+ });
4770
3697
  }
4771
- function IsArray4(value) {
4772
- return Array.isArray(value) && !ArrayBuffer.isView(value);
3698
+
3699
+ // ../noya-schemas/src/index.ts
3700
+ function validateUUID(value) {
3701
+ 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(
3702
+ value
3703
+ );
4773
3704
  }
4774
- function IsUndefined4(value) {
4775
- return value === void 0;
3705
+ format_exports.Set("color", () => true);
3706
+ format_exports.Set("uuid", validateUUID);
3707
+
3708
+ // src/noyaApp.ts
3709
+ import {
3710
+ createOrCastValue,
3711
+ isEmbeddedApp,
3712
+ localStorageSync,
3713
+ parentFrameSync,
3714
+ stubSync as stubSync2,
3715
+ TypeGuard,
3716
+ webSocketSync
3717
+ } from "@noya-app/state-manager";
3718
+ import { useMemo as useMemo3, useState as useState2 } from "react";
3719
+
3720
+ // src/hooks.ts
3721
+ import {
3722
+ NoyaManager,
3723
+ StateManager,
3724
+ stubSync
3725
+ } from "@noya-app/state-manager";
3726
+ import {
3727
+ createElement as createElement2,
3728
+ useCallback,
3729
+ useEffect as useEffect2,
3730
+ useMemo as useMemo2,
3731
+ useRef,
3732
+ useState,
3733
+ useSyncExternalStore as useSyncExternalStore2
3734
+ } from "react";
3735
+ import { createRoot as createRoot2 } from "react-dom/client";
3736
+
3737
+ // src/components/ErrorOverlay.tsx
3738
+ import * as React from "react";
3739
+ var ErrorOverlay = React.memo(function ErrorOverlay2({
3740
+ error
3741
+ }) {
3742
+ return /* @__PURE__ */ React.createElement(
3743
+ "div",
3744
+ {
3745
+ style: {
3746
+ position: "fixed",
3747
+ top: "20px",
3748
+ left: "50%",
3749
+ transform: "translateX(-50%)",
3750
+ maxWidth: "80%",
3751
+ width: "fit-content",
3752
+ padding: "12px 20px",
3753
+ background: "white",
3754
+ color: "black",
3755
+ zIndex: 1e4,
3756
+ display: "flex",
3757
+ flexDirection: "column",
3758
+ justifyContent: "center",
3759
+ borderRadius: "4px",
3760
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
3761
+ fontFamily: "'__Inter_6b0edc', '__Inter_Fallback_6b0edc', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
3762
+ fontSize: "14px",
3763
+ fontWeight: 400,
3764
+ lineHeight: "19px"
3765
+ }
3766
+ },
3767
+ error.reason === "schemaMigration" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", null, "An updated version of Noya is available. Please reload the page to continue.")) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", null, "An error occurred:", " ", /* @__PURE__ */ React.createElement(
3768
+ "code",
3769
+ {
3770
+ style: {
3771
+ background: "rgba(255, 0, 0, 0.1)",
3772
+ color: "rgba(255, 0, 0, 0.5)",
3773
+ padding: "2px 4px",
3774
+ borderRadius: "4px"
3775
+ }
3776
+ },
3777
+ error.reason
3778
+ ), ". Please reload the page to continue.", /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("br", null), "If this happens repeatedly, please get in touch and the Noya team can help.")),
3779
+ /* @__PURE__ */ React.createElement(
3780
+ "div",
3781
+ {
3782
+ style: {
3783
+ height: "1px",
3784
+ background: "rgba(0, 0, 0, 0.1)",
3785
+ margin: "12px -20px"
3786
+ }
3787
+ }
3788
+ ),
3789
+ /* @__PURE__ */ React.createElement(
3790
+ "button",
3791
+ {
3792
+ style: {
3793
+ background: "black",
3794
+ color: "white",
3795
+ padding: "8px 16px",
3796
+ borderRadius: "4px",
3797
+ cursor: "pointer",
3798
+ fontSize: "14px",
3799
+ fontWeight: 700,
3800
+ lineHeight: "19px"
3801
+ },
3802
+ onClick: () => {
3803
+ window.location.reload();
3804
+ }
3805
+ },
3806
+ "Reload"
3807
+ )
3808
+ );
3809
+ });
3810
+
3811
+ // src/inspector/useStateInspector.tsx
3812
+ import React4, { useLayoutEffect as useLayoutEffect2 } from "react";
3813
+ import { createRoot } from "react-dom/client";
3814
+
3815
+ // src/inspector/StateInspector.tsx
3816
+ import { memoGeneric } from "@noya-app/react-utils";
3817
+ import React3, {
3818
+ useEffect,
3819
+ useLayoutEffect
3820
+ } from "react";
3821
+ import {
3822
+ ObjectInspector,
3823
+ ObjectLabel,
3824
+ ObjectName,
3825
+ ObjectPreview,
3826
+ chromeDark,
3827
+ chromeLight
3828
+ } from "react-inspector";
3829
+
3830
+ // src/useObservable.ts
3831
+ import { useMemo, useSyncExternalStore } from "react";
3832
+ function useObservable(observable, pathOrSelector, options) {
3833
+ const { get, listen } = useMemo(() => {
3834
+ if (!observable) {
3835
+ return {
3836
+ get: () => void 0,
3837
+ listen: () => () => {
3838
+ }
3839
+ };
3840
+ }
3841
+ if (typeof pathOrSelector === "function") {
3842
+ const mappedObservable = observable.map(pathOrSelector, {
3843
+ isEqual: options?.isEqual
3844
+ });
3845
+ return {
3846
+ get: mappedObservable.get,
3847
+ listen: mappedObservable.subscribe
3848
+ };
3849
+ }
3850
+ const listen2 = pathOrSelector ? (callback) => observable.subscribe(pathOrSelector, callback) : observable.subscribe;
3851
+ const get2 = pathOrSelector ? () => observable.get(pathOrSelector) : observable.get;
3852
+ return { get: get2, listen: listen2 };
3853
+ }, [observable, pathOrSelector, options?.isEqual]);
3854
+ return useSyncExternalStore(listen, get, get);
4776
3855
  }
4777
- function IsNumber4(value) {
4778
- return typeof value === "number";
3856
+
3857
+ // src/inspector/useLocalStorageState.tsx
3858
+ import React2 from "react";
3859
+ var localStorage = typeof window !== "undefined" ? window.localStorage : null;
3860
+ function useLocalStorageState(key, defaultValue) {
3861
+ const [state, setState] = React2.useState(() => {
3862
+ const value = localStorage?.getItem(key);
3863
+ let result = defaultValue;
3864
+ if (value) {
3865
+ try {
3866
+ result = JSON.parse(value);
3867
+ } catch (error) {
3868
+ console.error("Error parsing localStorage value", error);
3869
+ }
3870
+ }
3871
+ return result;
3872
+ });
3873
+ const setLocalStorageState = (value) => {
3874
+ localStorage?.setItem(key, JSON.stringify(value));
3875
+ setState(value);
3876
+ };
3877
+ return [state, setLocalStorageState];
4779
3878
  }
4780
3879
 
4781
- // ../../node_modules/@sinclair/typebox/build/esm/system/policy.mjs
4782
- var TypeSystemPolicy;
4783
- (function(TypeSystemPolicy2) {
4784
- TypeSystemPolicy2.ExactOptionalPropertyTypes = false;
4785
- TypeSystemPolicy2.AllowArrayObject = false;
4786
- TypeSystemPolicy2.AllowNaN = false;
4787
- TypeSystemPolicy2.AllowNullVoid = false;
4788
- function IsExactOptionalProperty(value, key) {
4789
- return TypeSystemPolicy2.ExactOptionalPropertyTypes ? key in value : value[key] !== void 0;
4790
- }
4791
- TypeSystemPolicy2.IsExactOptionalProperty = IsExactOptionalProperty;
4792
- function IsObjectLike(value) {
4793
- const isObject = IsObject4(value);
4794
- return TypeSystemPolicy2.AllowArrayObject ? isObject : isObject && !IsArray4(value);
4795
- }
4796
- TypeSystemPolicy2.IsObjectLike = IsObjectLike;
4797
- function IsRecordLike(value) {
4798
- return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array);
4799
- }
4800
- TypeSystemPolicy2.IsRecordLike = IsRecordLike;
4801
- function IsNumberLike(value) {
4802
- return TypeSystemPolicy2.AllowNaN ? IsNumber4(value) : Number.isFinite(value);
3880
+ // src/inspector/StateInspector.tsx
3881
+ var lightTheme = {
3882
+ ...chromeLight,
3883
+ BASE_BACKGROUND_COLOR: "transparent",
3884
+ OBJECT_NAME_COLOR: "rgba(0,0,0,0.7)"
3885
+ };
3886
+ var darkTheme = {
3887
+ ...chromeDark,
3888
+ BASE_BACKGROUND_COLOR: "transparent",
3889
+ OBJECT_NAME_COLOR: "rgba(255,255,255,0.7)"
3890
+ };
3891
+ var styles = {
3892
+ sectionInner: {
3893
+ flex: "1 1 0",
3894
+ overflowY: "auto",
3895
+ overflowX: "hidden",
3896
+ display: "flex",
3897
+ flexDirection: "column"
4803
3898
  }
4804
- TypeSystemPolicy2.IsNumberLike = IsNumberLike;
4805
- function IsVoidLike(value) {
4806
- const isUndefined = IsUndefined4(value);
4807
- return TypeSystemPolicy2.AllowNullVoid ? isUndefined || value === null : isUndefined;
3899
+ };
3900
+ function ToggleButton({
3901
+ showInspector,
3902
+ setShowInspector,
3903
+ theme,
3904
+ anchor
3905
+ }) {
3906
+ return /* @__PURE__ */ React3.createElement(
3907
+ "span",
3908
+ {
3909
+ role: "button",
3910
+ style: {
3911
+ flex: "0",
3912
+ appearance: "none",
3913
+ color: theme.BASE_COLOR,
3914
+ border: "none",
3915
+ fontSize: "12px",
3916
+ whiteSpace: "nowrap",
3917
+ display: "inline-flex",
3918
+ alignItems: "center",
3919
+ justifyContent: "center",
3920
+ padding: "2px 0"
3921
+ },
3922
+ onClick: (event) => {
3923
+ event.stopPropagation();
3924
+ setShowInspector(!showInspector);
3925
+ }
3926
+ },
3927
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ React3.createElement(
3928
+ "svg",
3929
+ {
3930
+ xmlns: "http://www.w3.org/2000/svg",
3931
+ fill: "none",
3932
+ viewBox: "0 0 24 24",
3933
+ strokeWidth: 1.5,
3934
+ stroke: "currentColor",
3935
+ className: "size-6"
3936
+ },
3937
+ /* @__PURE__ */ React3.createElement(
3938
+ "path",
3939
+ {
3940
+ strokeLinecap: "round",
3941
+ strokeLinejoin: "round",
3942
+ d: "m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
3943
+ }
3944
+ )
3945
+ ) : /* @__PURE__ */ React3.createElement(
3946
+ "svg",
3947
+ {
3948
+ xmlns: "http://www.w3.org/2000/svg",
3949
+ fill: "none",
3950
+ viewBox: "0 0 24 24",
3951
+ strokeWidth: 1.5,
3952
+ stroke: "currentColor",
3953
+ className: "size-6"
3954
+ },
3955
+ /* @__PURE__ */ React3.createElement(
3956
+ "path",
3957
+ {
3958
+ strokeLinecap: "round",
3959
+ strokeLinejoin: "round",
3960
+ d: "m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5"
3961
+ }
3962
+ )
3963
+ ))
3964
+ );
3965
+ }
3966
+ function DisclosureSection({
3967
+ open,
3968
+ setOpen,
3969
+ title,
3970
+ right,
3971
+ children,
3972
+ colorScheme,
3973
+ isFirst,
3974
+ style
3975
+ }) {
3976
+ const theme = colorScheme === "light" ? lightTheme : darkTheme;
3977
+ const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
3978
+ return /* @__PURE__ */ React3.createElement(
3979
+ "div",
3980
+ {
3981
+ style: {
3982
+ flex: open ? "1 1 0" : "0",
3983
+ display: "flex",
3984
+ flexDirection: "column",
3985
+ ...style
3986
+ }
3987
+ },
3988
+ /* @__PURE__ */ React3.createElement(
3989
+ "div",
3990
+ {
3991
+ onClick: () => setOpen?.(!open),
3992
+ style: {
3993
+ cursor: "default",
3994
+ fontSize: "12px",
3995
+ padding: "4px 10px",
3996
+ display: "flex",
3997
+ alignItems: "center",
3998
+ ...!isFirst && { borderTop: `1px solid ${borderColor}` },
3999
+ ...open && { borderBottom: `1px solid ${borderColor}` }
4000
+ }
4001
+ },
4002
+ setOpen && /* @__PURE__ */ React3.createElement(
4003
+ Arrow,
4004
+ {
4005
+ expanded: open,
4006
+ style: {
4007
+ fontSize: theme.ARROW_FONT_SIZE,
4008
+ marginRight: theme.ARROW_MARGIN_RIGHT + 1,
4009
+ color: theme.ARROW_COLOR
4010
+ }
4011
+ }
4012
+ ),
4013
+ /* @__PURE__ */ React3.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
4014
+ right
4015
+ ),
4016
+ open && children
4017
+ );
4018
+ }
4019
+ function InspectorRow({
4020
+ children,
4021
+ colorScheme,
4022
+ selected,
4023
+ style,
4024
+ variant
4025
+ }) {
4026
+ const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
4027
+ return /* @__PURE__ */ React3.createElement(
4028
+ "div",
4029
+ {
4030
+ style: {
4031
+ borderBottom: `1px solid ${solidBorderColor}`,
4032
+ fontSize: "12px",
4033
+ fontFamily: "Menlo, monospace",
4034
+ padding: "2px 12px 1px",
4035
+ display: "flex",
4036
+ alignItems: "center",
4037
+ background: variant === "up" ? "rgba(0,255,0,0.1)" : variant === "down" ? "transparent" : selected ? "rgb(59 130 246 / 15%)" : void 0,
4038
+ // background:
4039
+ // colorScheme === "light"
4040
+ // ? "rgba(0,0,0,0.05)"
4041
+ // : "rgba(255,255,255,0.05)",
4042
+ ...style
4043
+ }
4044
+ },
4045
+ /* @__PURE__ */ React3.createElement(
4046
+ "span",
4047
+ {
4048
+ style: {
4049
+ fontFamily: "Menlo, monospace",
4050
+ fontSize: "11px",
4051
+ borderRadius: 4,
4052
+ display: "inline-block"
4053
+ }
4054
+ },
4055
+ children
4056
+ )
4057
+ );
4058
+ }
4059
+ var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
4060
+ var StateInspector = memoGeneric(function StateInspector2({
4061
+ noyaManager,
4062
+ colorScheme = "light",
4063
+ anchor = "right",
4064
+ unstyled = false,
4065
+ ...props
4066
+ }) {
4067
+ const {
4068
+ multiplayerStateManager,
4069
+ assetManager,
4070
+ connectedUsersManager,
4071
+ secretManager,
4072
+ ephemeralUserDataManager,
4073
+ connectionEventManager,
4074
+ taskManager,
4075
+ ioManager
4076
+ } = noyaManager;
4077
+ const [didMount, setDidMount] = React3.useState(false);
4078
+ const tasks = useObservable(taskManager.tasks$);
4079
+ const inputs = useObservable(ioManager.inputs$);
4080
+ const outputTransforms = useObservable(ioManager.outputTransforms$);
4081
+ useLayoutEffect(() => {
4082
+ setDidMount(true);
4083
+ }, []);
4084
+ const eventsContainerRef = React3.useRef(null);
4085
+ const historyContainerRef = React3.useRef(null);
4086
+ const [showInspector, setShowInspector] = useLocalStorageState(
4087
+ "noya-multiplayer-react-show-inspector",
4088
+ true
4089
+ );
4090
+ const [showEvents, setShowEvents] = useLocalStorageState(
4091
+ "noya-multiplayer-react-show-events",
4092
+ false
4093
+ );
4094
+ const [showHistory, setShowHistory] = useLocalStorageState(
4095
+ "noya-multiplayer-react-show-history",
4096
+ false
4097
+ );
4098
+ const [showUsers, setShowUsers] = useLocalStorageState(
4099
+ "noya-multiplayer-react-show-users",
4100
+ true
4101
+ );
4102
+ const [showData, setShowData] = useLocalStorageState(
4103
+ "noya-multiplayer-react-show-data",
4104
+ true
4105
+ );
4106
+ const [showTasks, setShowTasks] = useLocalStorageState(
4107
+ "noya-multiplayer-react-show-tasks",
4108
+ false
4109
+ );
4110
+ const [showEphemeral, setShowEphemeral] = useLocalStorageState(
4111
+ "noya-multiplayer-react-show-ephemeral",
4112
+ false
4113
+ );
4114
+ const [showAssets, setShowAssets] = useLocalStorageState(
4115
+ "noya-multiplayer-react-show-assets",
4116
+ false
4117
+ );
4118
+ const [showSecrets, setShowSecrets] = useLocalStorageState(
4119
+ "noya-multiplayer-react-show-secrets",
4120
+ false
4121
+ );
4122
+ const [showInputs, setShowInputs] = useLocalStorageState(
4123
+ "noya-multiplayer-react-show-inputs",
4124
+ false
4125
+ );
4126
+ const [showOutputTransforms, setShowOutputTransforms] = useLocalStorageState(
4127
+ "noya-multiplayer-react-show-output-transforms",
4128
+ false
4129
+ );
4130
+ const connectionEvents = useObservable(connectionEventManager.events$);
4131
+ useEffect(() => {
4132
+ if (eventsContainerRef.current) {
4133
+ eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
4134
+ }
4135
+ }, [connectionEvents]);
4136
+ const multipeerStateInitialized = useObservable(
4137
+ multiplayerStateManager.isInitialized$
4138
+ );
4139
+ const ephemeral = useObservable(ephemeralUserDataManager.data$);
4140
+ const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
4141
+ const assets = useObservable(assetManager.assets$);
4142
+ const assetsInitialized = useObservable(assetManager.isInitialized$);
4143
+ const secrets = useObservable(secretManager.secrets$);
4144
+ const secretsInitialized = useObservable(secretManager.isInitialized$);
4145
+ const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
4146
+ const userId = useObservable(connectedUsersManager.currentUserId$);
4147
+ const state = useObservable(multiplayerStateManager.optimisticState$);
4148
+ const inputsInitialized = useObservable(ioManager.inputsInitialized$);
4149
+ const outputTransformsInitialized = useObservable(
4150
+ ioManager.outputTransformsInitialized$
4151
+ );
4152
+ useEffect(() => {
4153
+ if (historyContainerRef.current) {
4154
+ historyContainerRef.current.scrollTop = historyContainerRef.current.scrollHeight;
4155
+ }
4156
+ }, [historySnapshot]);
4157
+ useEffect(() => {
4158
+ if (!historyContainerRef.current) return;
4159
+ const historyEntry = historyContainerRef.current.querySelector(
4160
+ `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
4161
+ );
4162
+ if (historyEntry) {
4163
+ historyEntry.scrollIntoView({
4164
+ block: "nearest",
4165
+ inline: "nearest"
4166
+ });
4167
+ }
4168
+ }, [historySnapshot.historyIndex]);
4169
+ const theme = colorScheme === "light" ? lightTheme : darkTheme;
4170
+ const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
4171
+ const baseStyle = {
4172
+ position: "fixed",
4173
+ top: 12,
4174
+ ...anchor.includes("right") ? { right: 12 } : { left: 12 },
4175
+ bottom: 12,
4176
+ width: 400,
4177
+ background: colorScheme === "light" ? "rgba(255,255,255,0.95)" : "rgba(0,0,0,0.95)",
4178
+ backdropFilter: "blur(48px)",
4179
+ border: `1px solid ${solidBorderColor}`,
4180
+ // outlineOffset: -1,
4181
+ borderRadius: 4,
4182
+ display: "flex",
4183
+ flexDirection: "column",
4184
+ // gap: 12,
4185
+ color: theme.BASE_COLOR,
4186
+ overflow: "hidden",
4187
+ zIndex: 9999,
4188
+ lineHeight: "13px"
4189
+ };
4190
+ if (!didMount) return null;
4191
+ if (!showInspector) {
4192
+ return /* @__PURE__ */ React3.createElement(
4193
+ "div",
4194
+ {
4195
+ ...props,
4196
+ style: {
4197
+ ...baseStyle,
4198
+ padding: "4px 10px",
4199
+ width: void 0,
4200
+ ...anchor.includes("bottom") ? { bottom: 12, top: void 0 } : { bottom: void 0 }
4201
+ },
4202
+ onClick: () => setShowInspector(true)
4203
+ },
4204
+ /* @__PURE__ */ React3.createElement(
4205
+ ToggleButton,
4206
+ {
4207
+ showInspector,
4208
+ setShowInspector,
4209
+ theme,
4210
+ anchor
4211
+ }
4212
+ )
4213
+ );
4808
4214
  }
4809
- TypeSystemPolicy2.IsVoidLike = IsVoidLike;
4810
- })(TypeSystemPolicy || (TypeSystemPolicy = {}));
4811
-
4812
- // ../../node_modules/@sinclair/typebox/build/esm/system/system.mjs
4813
- var TypeSystemDuplicateTypeKind = class extends TypeBoxError {
4814
- constructor(kind) {
4815
- super(`Duplicate type kind '${kind}' detected`);
4215
+ return /* @__PURE__ */ React3.createElement(
4216
+ "div",
4217
+ {
4218
+ ...props,
4219
+ style: {
4220
+ ...!unstyled && baseStyle,
4221
+ ...props.style
4222
+ }
4223
+ },
4224
+ /* @__PURE__ */ React3.createElement(
4225
+ DisclosureSection,
4226
+ {
4227
+ isFirst: true,
4228
+ open: showUsers,
4229
+ setOpen: setShowUsers,
4230
+ title: "Users",
4231
+ colorScheme,
4232
+ style: {
4233
+ flex: "0 0 auto",
4234
+ maxHeight: "200px"
4235
+ },
4236
+ right: /* @__PURE__ */ React3.createElement(
4237
+ ToggleButton,
4238
+ {
4239
+ showInspector,
4240
+ setShowInspector,
4241
+ theme,
4242
+ anchor
4243
+ }
4244
+ )
4245
+ },
4246
+ /* @__PURE__ */ React3.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React3.createElement(
4247
+ InspectorRow,
4248
+ {
4249
+ key: user.id,
4250
+ colorScheme,
4251
+ variant: user.id === userId ? "up" : void 0
4252
+ },
4253
+ user.image && /* @__PURE__ */ React3.createElement(
4254
+ "img",
4255
+ {
4256
+ src: user.image,
4257
+ alt: user.name,
4258
+ style: {
4259
+ width: "13px",
4260
+ height: "13px",
4261
+ borderRadius: "50%",
4262
+ marginRight: "4px",
4263
+ display: "inline-block",
4264
+ position: "relative",
4265
+ background: solidBorderColor,
4266
+ verticalAlign: "middle"
4267
+ }
4268
+ }
4269
+ ),
4270
+ user.name,
4271
+ " (",
4272
+ ellipsis(user.id.toString(), 8, "middle"),
4273
+ ")"
4274
+ )), !connectedUsers && /* @__PURE__ */ React3.createElement(
4275
+ "div",
4276
+ {
4277
+ style: {
4278
+ padding: "12px",
4279
+ fontSize: "12px",
4280
+ display: "flex",
4281
+ flexDirection: "column",
4282
+ gap: "4px"
4283
+ }
4284
+ },
4285
+ /* @__PURE__ */ React3.createElement("span", null, "No connected users")
4286
+ ))
4287
+ ),
4288
+ /* @__PURE__ */ React3.createElement(
4289
+ DisclosureSection,
4290
+ {
4291
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Data", /* @__PURE__ */ React3.createElement(
4292
+ ColoredDot,
4293
+ {
4294
+ type: multipeerStateInitialized ? "success" : "error"
4295
+ }
4296
+ )),
4297
+ colorScheme,
4298
+ setOpen: setShowData,
4299
+ open: showData,
4300
+ right: /* @__PURE__ */ React3.createElement(
4301
+ "span",
4302
+ {
4303
+ style: {
4304
+ display: "flex",
4305
+ gap: "4px"
4306
+ }
4307
+ },
4308
+ /* @__PURE__ */ React3.createElement(
4309
+ SmallButton,
4310
+ {
4311
+ theme,
4312
+ onClick: () => {
4313
+ noyaManager.forceInit();
4314
+ }
4315
+ },
4316
+ "Reset"
4317
+ )
4318
+ )
4319
+ },
4320
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
4321
+ ObjectInspector,
4322
+ {
4323
+ name: multiplayerStateManager.schema ? "state" : void 0,
4324
+ data: state,
4325
+ theme
4326
+ }
4327
+ )), multiplayerStateManager.schema && /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
4328
+ ObjectInspector,
4329
+ {
4330
+ name: "schema",
4331
+ data: multiplayerStateManager.schema,
4332
+ theme
4333
+ }
4334
+ )))
4335
+ ),
4336
+ /* @__PURE__ */ React3.createElement(
4337
+ DisclosureSection,
4338
+ {
4339
+ open: showHistory,
4340
+ setOpen: setShowHistory,
4341
+ title: "History",
4342
+ colorScheme,
4343
+ right: /* @__PURE__ */ React3.createElement(
4344
+ "span",
4345
+ {
4346
+ style: {
4347
+ display: "flex",
4348
+ gap: "4px"
4349
+ }
4350
+ },
4351
+ /* @__PURE__ */ React3.createElement(
4352
+ SmallButton,
4353
+ {
4354
+ disabled: !historySnapshot.canUndo,
4355
+ theme,
4356
+ onClick: () => {
4357
+ multiplayerStateManager.undo();
4358
+ }
4359
+ },
4360
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
4361
+ "svg",
4362
+ {
4363
+ xmlns: "http://www.w3.org/2000/svg",
4364
+ width: "1em",
4365
+ height: "1em",
4366
+ viewBox: "0 0 20 20"
4367
+ },
4368
+ /* @__PURE__ */ React3.createElement(
4369
+ "path",
4370
+ {
4371
+ fill: "currentColor",
4372
+ 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"
4373
+ }
4374
+ )
4375
+ ))
4376
+ ),
4377
+ /* @__PURE__ */ React3.createElement(
4378
+ SmallButton,
4379
+ {
4380
+ disabled: !historySnapshot.canRedo,
4381
+ theme,
4382
+ onClick: () => {
4383
+ multiplayerStateManager.redo();
4384
+ }
4385
+ },
4386
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
4387
+ "svg",
4388
+ {
4389
+ xmlns: "http://www.w3.org/2000/svg",
4390
+ width: "1em",
4391
+ height: "1em",
4392
+ viewBox: "0 0 20 20"
4393
+ },
4394
+ /* @__PURE__ */ React3.createElement(
4395
+ "path",
4396
+ {
4397
+ fill: "currentColor",
4398
+ 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"
4399
+ }
4400
+ )
4401
+ ))
4402
+ )
4403
+ )
4404
+ },
4405
+ /* @__PURE__ */ React3.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(
4406
+ "div",
4407
+ {
4408
+ id: `${HISTORY_ELEMENT_PREFIX}0`,
4409
+ style: {
4410
+ borderBottom: `1px solid ${solidBorderColor}`,
4411
+ fontSize: "12px",
4412
+ fontFamily: "Menlo, monospace",
4413
+ padding: "2px 12px 1px",
4414
+ display: "flex",
4415
+ alignItems: "center",
4416
+ background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
4417
+ }
4418
+ },
4419
+ /* @__PURE__ */ React3.createElement(
4420
+ "span",
4421
+ {
4422
+ style: {
4423
+ fontFamily: "Menlo, monospace",
4424
+ fontSize: "11px",
4425
+ borderRadius: 4,
4426
+ display: "inline-block"
4427
+ }
4428
+ },
4429
+ "Initial state"
4430
+ )
4431
+ ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ React3.createElement(
4432
+ "div",
4433
+ {
4434
+ id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
4435
+ key: index,
4436
+ style: {
4437
+ padding: "0px 12px 1px",
4438
+ borderBottom: `1px solid ${solidBorderColor}`,
4439
+ background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
4440
+ }
4441
+ },
4442
+ "name" in entry.metadata && typeof entry.metadata.name === "string" && /* @__PURE__ */ React3.createElement(
4443
+ "pre",
4444
+ {
4445
+ style: {
4446
+ fontSize: "11px",
4447
+ display: "flex",
4448
+ flexWrap: "wrap",
4449
+ margin: 0
4450
+ }
4451
+ },
4452
+ entry.metadata.name
4453
+ ),
4454
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React3.createElement(
4455
+ "pre",
4456
+ {
4457
+ key: j,
4458
+ style: {
4459
+ fontSize: "11px",
4460
+ display: "flex",
4461
+ flexWrap: "wrap",
4462
+ margin: 0
4463
+ }
4464
+ },
4465
+ 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 })),
4466
+ 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 })),
4467
+ 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))),
4468
+ 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)))
4469
+ ))
4470
+ )))
4471
+ ),
4472
+ /* @__PURE__ */ React3.createElement(
4473
+ DisclosureSection,
4474
+ {
4475
+ open: showAssets,
4476
+ setOpen: setShowAssets,
4477
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Assets", /* @__PURE__ */ React3.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
4478
+ colorScheme,
4479
+ right: /* @__PURE__ */ React3.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React3.createElement(
4480
+ SmallButton,
4481
+ {
4482
+ theme,
4483
+ onClick: () => {
4484
+ console.info(
4485
+ "[StateInspector] Reloading assets",
4486
+ noyaManager.id
4487
+ );
4488
+ assetManager.fetch();
4489
+ }
4490
+ },
4491
+ "Reload"
4492
+ ), /* @__PURE__ */ React3.createElement(
4493
+ SmallButton,
4494
+ {
4495
+ theme,
4496
+ onClick: () => {
4497
+ const input = document.createElement("input");
4498
+ input.type = "file";
4499
+ input.onchange = () => {
4500
+ const file = input.files?.[0];
4501
+ if (file) {
4502
+ const reader = new FileReader();
4503
+ reader.onload = () => {
4504
+ const buffer = reader.result;
4505
+ assetManager.create(new Uint8Array(buffer));
4506
+ };
4507
+ reader.readAsArrayBuffer(file);
4508
+ }
4509
+ };
4510
+ input.click();
4511
+ }
4512
+ },
4513
+ "Upload"
4514
+ ))
4515
+ },
4516
+ /* @__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(
4517
+ SmallButton,
4518
+ {
4519
+ theme,
4520
+ onClick: () => assetManager.delete(asset.id)
4521
+ },
4522
+ "Delete"
4523
+ ))))
4524
+ ),
4525
+ /* @__PURE__ */ React3.createElement(
4526
+ DisclosureSection,
4527
+ {
4528
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Secrets", /* @__PURE__ */ React3.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
4529
+ colorScheme,
4530
+ open: showSecrets,
4531
+ setOpen: setShowSecrets,
4532
+ right: /* @__PURE__ */ React3.createElement(
4533
+ SmallButton,
4534
+ {
4535
+ theme,
4536
+ onClick: () => {
4537
+ const name = prompt("Enter secret name");
4538
+ if (!name) return;
4539
+ const value = prompt("Enter secret value");
4540
+ if (!value) return;
4541
+ secretManager.createSecret(name, value);
4542
+ }
4543
+ },
4544
+ "Create"
4545
+ )
4546
+ },
4547
+ /* @__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(
4548
+ SmallButton,
4549
+ {
4550
+ theme,
4551
+ onClick: () => secretManager.deleteSecret(secret.name)
4552
+ },
4553
+ "Delete"
4554
+ ))))
4555
+ ),
4556
+ " ",
4557
+ /* @__PURE__ */ React3.createElement(
4558
+ DisclosureSection,
4559
+ {
4560
+ open: showInputs,
4561
+ setOpen: setShowInputs,
4562
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Inputs", /* @__PURE__ */ React3.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
4563
+ colorScheme
4564
+ },
4565
+ /* @__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(
4566
+ "div",
4567
+ {
4568
+ style: {
4569
+ padding: "12px",
4570
+ fontSize: "12px",
4571
+ display: "flex",
4572
+ flexDirection: "column",
4573
+ gap: "4px"
4574
+ }
4575
+ },
4576
+ /* @__PURE__ */ React3.createElement("span", null, "No inputs")
4577
+ ))
4578
+ ),
4579
+ /* @__PURE__ */ React3.createElement(
4580
+ DisclosureSection,
4581
+ {
4582
+ open: showOutputTransforms,
4583
+ setOpen: setShowOutputTransforms,
4584
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Output Transforms", /* @__PURE__ */ React3.createElement(
4585
+ ColoredDot,
4586
+ {
4587
+ type: outputTransformsInitialized ? "success" : "error"
4588
+ }
4589
+ )),
4590
+ colorScheme
4591
+ },
4592
+ /* @__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(
4593
+ "div",
4594
+ {
4595
+ style: {
4596
+ padding: "12px",
4597
+ fontSize: "12px",
4598
+ display: "flex",
4599
+ flexDirection: "column",
4600
+ gap: "4px"
4601
+ }
4602
+ },
4603
+ /* @__PURE__ */ React3.createElement("span", null, "No output transforms")
4604
+ ))
4605
+ ),
4606
+ /* @__PURE__ */ React3.createElement(
4607
+ DisclosureSection,
4608
+ {
4609
+ title: "Tasks",
4610
+ colorScheme,
4611
+ open: showTasks,
4612
+ setOpen: setShowTasks
4613
+ },
4614
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ React3.createElement(
4615
+ InspectorRow,
4616
+ {
4617
+ key: task.id,
4618
+ colorScheme,
4619
+ style: {
4620
+ backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
4621
+ }
4622
+ },
4623
+ /* @__PURE__ */ React3.createElement(
4624
+ ObjectInspector,
4625
+ {
4626
+ name: task.name,
4627
+ data: task.payload,
4628
+ theme
4629
+ }
4630
+ )
4631
+ )))
4632
+ ),
4633
+ /* @__PURE__ */ React3.createElement(
4634
+ DisclosureSection,
4635
+ {
4636
+ open: showEphemeral,
4637
+ setOpen: setShowEphemeral,
4638
+ title: "Ephemeral User Data",
4639
+ colorScheme
4640
+ },
4641
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React3.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ React3.createElement(
4642
+ ObjectInspector,
4643
+ {
4644
+ name: key,
4645
+ data: value,
4646
+ theme,
4647
+ expandLevel: 10
4648
+ }
4649
+ ))))
4650
+ ),
4651
+ /* @__PURE__ */ React3.createElement(
4652
+ DisclosureSection,
4653
+ {
4654
+ open: showEvents,
4655
+ setOpen: setShowEvents,
4656
+ title: "Events",
4657
+ colorScheme
4658
+ },
4659
+ /* @__PURE__ */ React3.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
4660
+ (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(
4661
+ InspectorRow,
4662
+ {
4663
+ key: index,
4664
+ colorScheme,
4665
+ variant: event.type === "send" ? "up" : "down",
4666
+ style: {
4667
+ padding: "0px 12px 1px"
4668
+ }
4669
+ },
4670
+ /* @__PURE__ */ React3.createElement(
4671
+ ObjectInspector,
4672
+ {
4673
+ data: event.type === "error" ? event.error : event.message,
4674
+ theme,
4675
+ nodeRenderer: ({
4676
+ depth,
4677
+ name,
4678
+ data,
4679
+ isNonenumerable
4680
+ }) => {
4681
+ const direction = event.type === "send" ? "up" : "down";
4682
+ return depth === 0 ? /* @__PURE__ */ React3.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React3.createElement(
4683
+ ObjectLabel,
4684
+ {
4685
+ direction,
4686
+ name,
4687
+ data,
4688
+ isNonenumerable
4689
+ }
4690
+ );
4691
+ }
4692
+ }
4693
+ )
4694
+ )
4695
+ ), !connectionEvents && /* @__PURE__ */ React3.createElement(
4696
+ "div",
4697
+ {
4698
+ style: {
4699
+ padding: "12px",
4700
+ fontSize: "12px",
4701
+ display: "flex",
4702
+ flexDirection: "column",
4703
+ gap: "4px"
4704
+ }
4705
+ },
4706
+ /* @__PURE__ */ React3.createElement("span", null, "No recorded events")
4707
+ ))
4708
+ )
4709
+ );
4710
+ });
4711
+ var ObjectRootLabel = ({ name, data, direction }) => {
4712
+ if (typeof name === "string") {
4713
+ return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(ObjectName, { name }), /* @__PURE__ */ React3.createElement("span", null, ": "), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
4816
4714
  }
4817
- };
4818
- var TypeSystemDuplicateFormat = class extends TypeBoxError {
4819
- constructor(kind) {
4820
- super(`Duplicate string format '${kind}' detected`);
4715
+ if (direction === "up" || direction === "down") {
4716
+ const arrow = direction === "up" ? "\u2191" : "\u2193";
4717
+ return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(
4718
+ "span",
4719
+ {
4720
+ style: {
4721
+ background: direction === "up" ? "rgba(0,255,0,0.2)" : "rgba(255,0,0,0.2)",
4722
+ // color: "white",
4723
+ width: 12,
4724
+ height: 12,
4725
+ borderRadius: 2,
4726
+ display: "inline-flex",
4727
+ justifyContent: "center",
4728
+ alignItems: "center",
4729
+ marginRight: 4,
4730
+ lineHeight: "12px"
4731
+ }
4732
+ },
4733
+ arrow
4734
+ ), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
4735
+ } else {
4736
+ return /* @__PURE__ */ React3.createElement(ObjectPreview, { data });
4821
4737
  }
4822
4738
  };
4823
- var TypeSystem;
4824
- (function(TypeSystem2) {
4825
- function Type2(kind, check) {
4826
- if (type_exports2.Has(kind))
4827
- throw new TypeSystemDuplicateTypeKind(kind);
4828
- type_exports2.Set(kind, check);
4829
- return (options = {}) => Unsafe({ ...options, [Kind]: kind });
4830
- }
4831
- TypeSystem2.Type = Type2;
4832
- function Format(format, check) {
4833
- if (format_exports.Has(format))
4834
- throw new TypeSystemDuplicateFormat(format);
4835
- format_exports.Set(format, check);
4836
- return format;
4739
+ function Arrow({
4740
+ expanded,
4741
+ onClick,
4742
+ style
4743
+ }) {
4744
+ return /* @__PURE__ */ React3.createElement(
4745
+ "span",
4746
+ {
4747
+ role: "button",
4748
+ onClick,
4749
+ style: {
4750
+ display: "inline-block",
4751
+ textAlign: "center",
4752
+ transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
4753
+ fontFamily: "Menlo, monospace",
4754
+ ...style
4755
+ }
4756
+ },
4757
+ "\u25BC"
4758
+ );
4759
+ }
4760
+ function pathToString(extendedPath) {
4761
+ return extendedPath.map(
4762
+ (key) => typeof key === "object" ? `:${ellipsis(key.id.toString(), 8, "middle")}` : key
4763
+ ).map(
4764
+ (key, index) => index === 0 || typeof key === "string" && key.startsWith(":") ? key : `.${key}`
4765
+ ).join("");
4766
+ }
4767
+ function ellipsis(str, maxLength, position = "end") {
4768
+ if (str.length <= maxLength) return str;
4769
+ switch (position) {
4770
+ case "start":
4771
+ return `\u2026${str.slice(str.length - maxLength)}`;
4772
+ case "middle":
4773
+ const halfLength = Math.floor(maxLength / 2);
4774
+ return `${str.slice(0, halfLength)}\u2026${str.slice(str.length - halfLength)}`;
4775
+ case "end":
4776
+ return `${str.slice(0, maxLength)}\u2026`;
4837
4777
  }
4838
- TypeSystem2.Format = Format;
4839
- })(TypeSystem || (TypeSystem = {}));
4840
-
4841
- // ../../node_modules/@sinclair/typebox/build/esm/value/hash/hash.mjs
4842
- var ByteMarker;
4843
- (function(ByteMarker2) {
4844
- ByteMarker2[ByteMarker2["Undefined"] = 0] = "Undefined";
4845
- ByteMarker2[ByteMarker2["Null"] = 1] = "Null";
4846
- ByteMarker2[ByteMarker2["Boolean"] = 2] = "Boolean";
4847
- ByteMarker2[ByteMarker2["Number"] = 3] = "Number";
4848
- ByteMarker2[ByteMarker2["String"] = 4] = "String";
4849
- ByteMarker2[ByteMarker2["Object"] = 5] = "Object";
4850
- ByteMarker2[ByteMarker2["Array"] = 6] = "Array";
4851
- ByteMarker2[ByteMarker2["Date"] = 7] = "Date";
4852
- ByteMarker2[ByteMarker2["Uint8Array"] = 8] = "Uint8Array";
4853
- ByteMarker2[ByteMarker2["Symbol"] = 9] = "Symbol";
4854
- ByteMarker2[ByteMarker2["BigInt"] = 10] = "BigInt";
4855
- })(ByteMarker || (ByteMarker = {}));
4856
- var Accumulator = BigInt("14695981039346656037");
4857
- var [Prime, Size] = [BigInt("1099511628211"), BigInt("2") ** BigInt("64")];
4858
- var Bytes = Array.from({ length: 256 }).map((_, i) => BigInt(i));
4859
- var F64 = new Float64Array(1);
4860
- var F64In = new DataView(F64.buffer);
4861
- var F64Out = new Uint8Array(F64.buffer);
4862
-
4863
- // ../../node_modules/@sinclair/typebox/build/esm/errors/errors.mjs
4864
- var ValueErrorType;
4865
- (function(ValueErrorType2) {
4866
- ValueErrorType2[ValueErrorType2["ArrayContains"] = 0] = "ArrayContains";
4867
- ValueErrorType2[ValueErrorType2["ArrayMaxContains"] = 1] = "ArrayMaxContains";
4868
- ValueErrorType2[ValueErrorType2["ArrayMaxItems"] = 2] = "ArrayMaxItems";
4869
- ValueErrorType2[ValueErrorType2["ArrayMinContains"] = 3] = "ArrayMinContains";
4870
- ValueErrorType2[ValueErrorType2["ArrayMinItems"] = 4] = "ArrayMinItems";
4871
- ValueErrorType2[ValueErrorType2["ArrayUniqueItems"] = 5] = "ArrayUniqueItems";
4872
- ValueErrorType2[ValueErrorType2["Array"] = 6] = "Array";
4873
- ValueErrorType2[ValueErrorType2["AsyncIterator"] = 7] = "AsyncIterator";
4874
- ValueErrorType2[ValueErrorType2["BigIntExclusiveMaximum"] = 8] = "BigIntExclusiveMaximum";
4875
- ValueErrorType2[ValueErrorType2["BigIntExclusiveMinimum"] = 9] = "BigIntExclusiveMinimum";
4876
- ValueErrorType2[ValueErrorType2["BigIntMaximum"] = 10] = "BigIntMaximum";
4877
- ValueErrorType2[ValueErrorType2["BigIntMinimum"] = 11] = "BigIntMinimum";
4878
- ValueErrorType2[ValueErrorType2["BigIntMultipleOf"] = 12] = "BigIntMultipleOf";
4879
- ValueErrorType2[ValueErrorType2["BigInt"] = 13] = "BigInt";
4880
- ValueErrorType2[ValueErrorType2["Boolean"] = 14] = "Boolean";
4881
- ValueErrorType2[ValueErrorType2["DateExclusiveMaximumTimestamp"] = 15] = "DateExclusiveMaximumTimestamp";
4882
- ValueErrorType2[ValueErrorType2["DateExclusiveMinimumTimestamp"] = 16] = "DateExclusiveMinimumTimestamp";
4883
- ValueErrorType2[ValueErrorType2["DateMaximumTimestamp"] = 17] = "DateMaximumTimestamp";
4884
- ValueErrorType2[ValueErrorType2["DateMinimumTimestamp"] = 18] = "DateMinimumTimestamp";
4885
- ValueErrorType2[ValueErrorType2["DateMultipleOfTimestamp"] = 19] = "DateMultipleOfTimestamp";
4886
- ValueErrorType2[ValueErrorType2["Date"] = 20] = "Date";
4887
- ValueErrorType2[ValueErrorType2["Function"] = 21] = "Function";
4888
- ValueErrorType2[ValueErrorType2["IntegerExclusiveMaximum"] = 22] = "IntegerExclusiveMaximum";
4889
- ValueErrorType2[ValueErrorType2["IntegerExclusiveMinimum"] = 23] = "IntegerExclusiveMinimum";
4890
- ValueErrorType2[ValueErrorType2["IntegerMaximum"] = 24] = "IntegerMaximum";
4891
- ValueErrorType2[ValueErrorType2["IntegerMinimum"] = 25] = "IntegerMinimum";
4892
- ValueErrorType2[ValueErrorType2["IntegerMultipleOf"] = 26] = "IntegerMultipleOf";
4893
- ValueErrorType2[ValueErrorType2["Integer"] = 27] = "Integer";
4894
- ValueErrorType2[ValueErrorType2["IntersectUnevaluatedProperties"] = 28] = "IntersectUnevaluatedProperties";
4895
- ValueErrorType2[ValueErrorType2["Intersect"] = 29] = "Intersect";
4896
- ValueErrorType2[ValueErrorType2["Iterator"] = 30] = "Iterator";
4897
- ValueErrorType2[ValueErrorType2["Kind"] = 31] = "Kind";
4898
- ValueErrorType2[ValueErrorType2["Literal"] = 32] = "Literal";
4899
- ValueErrorType2[ValueErrorType2["Never"] = 33] = "Never";
4900
- ValueErrorType2[ValueErrorType2["Not"] = 34] = "Not";
4901
- ValueErrorType2[ValueErrorType2["Null"] = 35] = "Null";
4902
- ValueErrorType2[ValueErrorType2["NumberExclusiveMaximum"] = 36] = "NumberExclusiveMaximum";
4903
- ValueErrorType2[ValueErrorType2["NumberExclusiveMinimum"] = 37] = "NumberExclusiveMinimum";
4904
- ValueErrorType2[ValueErrorType2["NumberMaximum"] = 38] = "NumberMaximum";
4905
- ValueErrorType2[ValueErrorType2["NumberMinimum"] = 39] = "NumberMinimum";
4906
- ValueErrorType2[ValueErrorType2["NumberMultipleOf"] = 40] = "NumberMultipleOf";
4907
- ValueErrorType2[ValueErrorType2["Number"] = 41] = "Number";
4908
- ValueErrorType2[ValueErrorType2["ObjectAdditionalProperties"] = 42] = "ObjectAdditionalProperties";
4909
- ValueErrorType2[ValueErrorType2["ObjectMaxProperties"] = 43] = "ObjectMaxProperties";
4910
- ValueErrorType2[ValueErrorType2["ObjectMinProperties"] = 44] = "ObjectMinProperties";
4911
- ValueErrorType2[ValueErrorType2["ObjectRequiredProperty"] = 45] = "ObjectRequiredProperty";
4912
- ValueErrorType2[ValueErrorType2["Object"] = 46] = "Object";
4913
- ValueErrorType2[ValueErrorType2["Promise"] = 47] = "Promise";
4914
- ValueErrorType2[ValueErrorType2["RegExp"] = 48] = "RegExp";
4915
- ValueErrorType2[ValueErrorType2["StringFormatUnknown"] = 49] = "StringFormatUnknown";
4916
- ValueErrorType2[ValueErrorType2["StringFormat"] = 50] = "StringFormat";
4917
- ValueErrorType2[ValueErrorType2["StringMaxLength"] = 51] = "StringMaxLength";
4918
- ValueErrorType2[ValueErrorType2["StringMinLength"] = 52] = "StringMinLength";
4919
- ValueErrorType2[ValueErrorType2["StringPattern"] = 53] = "StringPattern";
4920
- ValueErrorType2[ValueErrorType2["String"] = 54] = "String";
4921
- ValueErrorType2[ValueErrorType2["Symbol"] = 55] = "Symbol";
4922
- ValueErrorType2[ValueErrorType2["TupleLength"] = 56] = "TupleLength";
4923
- ValueErrorType2[ValueErrorType2["Tuple"] = 57] = "Tuple";
4924
- ValueErrorType2[ValueErrorType2["Uint8ArrayMaxByteLength"] = 58] = "Uint8ArrayMaxByteLength";
4925
- ValueErrorType2[ValueErrorType2["Uint8ArrayMinByteLength"] = 59] = "Uint8ArrayMinByteLength";
4926
- ValueErrorType2[ValueErrorType2["Uint8Array"] = 60] = "Uint8Array";
4927
- ValueErrorType2[ValueErrorType2["Undefined"] = 61] = "Undefined";
4928
- ValueErrorType2[ValueErrorType2["Union"] = 62] = "Union";
4929
- ValueErrorType2[ValueErrorType2["Void"] = 63] = "Void";
4930
- })(ValueErrorType || (ValueErrorType = {}));
4931
-
4932
- // ../../node_modules/@sinclair/typebox/build/esm/value/delta/delta.mjs
4933
- var Insert = Object2({
4934
- type: Literal("insert"),
4935
- path: String(),
4936
- value: Unknown()
4937
- });
4938
- var Update = Object2({
4939
- type: Literal("update"),
4940
- path: String(),
4941
- value: Unknown()
4942
- });
4943
- var Delete3 = Object2({
4944
- type: Literal("delete"),
4945
- path: String()
4946
- });
4947
- var Edit = Union([Insert, Update, Delete3]);
4778
+ }
4779
+ function SmallButton({
4780
+ children,
4781
+ onClick,
4782
+ style,
4783
+ theme,
4784
+ disabled
4785
+ }) {
4786
+ return /* @__PURE__ */ React3.createElement(
4787
+ "button",
4788
+ {
4789
+ type: "button",
4790
+ disabled,
4791
+ onClick: (event) => {
4792
+ event.stopPropagation();
4793
+ onClick();
4794
+ },
4795
+ style: {
4796
+ flex: "0",
4797
+ appearance: "none",
4798
+ background: "none",
4799
+ color: theme.BASE_COLOR,
4800
+ opacity: disabled ? 0.25 : 1,
4801
+ border: "none",
4802
+ fontSize: "12px",
4803
+ whiteSpace: "nowrap",
4804
+ display: "inline-flex",
4805
+ alignItems: "center",
4806
+ justifyContent: "center",
4807
+ padding: "0",
4808
+ cursor: "pointer",
4809
+ ...style
4810
+ }
4811
+ },
4812
+ children
4813
+ );
4814
+ }
4815
+ function ColoredDot({ type }) {
4816
+ return /* @__PURE__ */ React3.createElement(
4817
+ "span",
4818
+ {
4819
+ style: {
4820
+ display: "inline-block",
4821
+ width: 6,
4822
+ height: 6,
4823
+ background: type === "success" ? "rgba(0,200,0,0.8)" : "rgba(200,0,0,0.8)",
4824
+ borderRadius: "50%",
4825
+ verticalAlign: "middle"
4826
+ }
4827
+ }
4828
+ );
4829
+ }
4830
+ function TitleLabel({ children }) {
4831
+ return /* @__PURE__ */ React3.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
4832
+ }
4948
4833
 
4949
- // ../noya-schemas/src/SchemaTree.ts
4950
- var import_tree_visit = __toESM(require_lib());
4951
- var SchemaTree = (0, import_tree_visit.defineTree)((schema) => {
4952
- if (type_exports.IsUnion(schema)) {
4953
- return schema.anyOf;
4954
- } else if (type_exports.IsObject(schema)) {
4955
- return Object.values(schema.properties);
4956
- } else if (type_exports.IsArray(schema)) {
4957
- return [schema.items];
4958
- }
4959
- return [];
4960
- }).withOptions({
4961
- getLabel(node) {
4962
- return node[Kind] ?? "<UnknownKind>";
4963
- }
4964
- });
4965
- function findAllDefs(schema) {
4966
- if (!schema) return [];
4967
- return SchemaTree.flatMap(schema, (node) => {
4968
- return node.$id ? [node] : [];
4969
- });
4834
+ // src/inspector/useStateInspector.tsx
4835
+ function createShadowRootElement() {
4836
+ const host = document.createElement("div");
4837
+ host.id = "noya-multiplayer-react-inspector-host";
4838
+ const shadowRoot = host.attachShadow({ mode: "open" });
4839
+ const container = document.createElement("div");
4840
+ shadowRoot.appendChild(container);
4841
+ return { host, container };
4842
+ }
4843
+ function useStateInspector({
4844
+ noyaManager,
4845
+ disabled = false,
4846
+ colorScheme,
4847
+ anchor
4848
+ }) {
4849
+ const [root, setRoot] = React4.useState(null);
4850
+ useLayoutEffect2(() => {
4851
+ if (disabled) return;
4852
+ const { host, container } = createShadowRootElement();
4853
+ const root2 = createRoot(container);
4854
+ document.body.appendChild(host);
4855
+ setRoot(root2);
4856
+ return () => {
4857
+ document.body.removeChild(host);
4858
+ };
4859
+ }, [disabled]);
4860
+ useLayoutEffect2(() => {
4861
+ if (!root) return;
4862
+ root.render(
4863
+ /* @__PURE__ */ React4.createElement(
4864
+ StateInspector,
4865
+ {
4866
+ colorScheme,
4867
+ anchor,
4868
+ noyaManager
4869
+ }
4870
+ )
4871
+ );
4872
+ }, [noyaManager, anchor, colorScheme, root]);
4970
4873
  }
4971
4874
 
4972
- // ../noya-schemas/src/index.ts
4973
- function validateUUID(value) {
4974
- 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(
4975
- value
4875
+ // src/hooks.ts
4876
+ function useSyncStateManager(stateManager, path) {
4877
+ const getSnapshot = useCallback(
4878
+ () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
4879
+ [stateManager, path]
4880
+ );
4881
+ return useSyncExternalStore2(
4882
+ stateManager.addListener,
4883
+ getSnapshot,
4884
+ getSnapshot
4976
4885
  );
4977
4886
  }
4978
- format_exports.Set("color", () => true);
4979
- format_exports.Set("uuid", validateUUID);
4887
+ function useManagedState(createInitialState, options) {
4888
+ const [stateManager] = useState(
4889
+ () => new StateManager(createInitialState(), options)
4890
+ );
4891
+ const state = useSyncStateManager(stateManager);
4892
+ const setState = useCallback(
4893
+ (...args) => {
4894
+ const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
4895
+ if (metadata === void 0) {
4896
+ const performActionNoMetadata = stateManager.performAction;
4897
+ if (action instanceof Function) {
4898
+ performActionNoMetadata({
4899
+ run: action,
4900
+ undo: () => state
4901
+ });
4902
+ } else {
4903
+ performActionNoMetadata({
4904
+ run: () => action,
4905
+ undo: () => state
4906
+ });
4907
+ }
4908
+ } else {
4909
+ const performActionWithMetadata = stateManager.performAction;
4910
+ if (action instanceof Function) {
4911
+ performActionWithMetadata(metadata, {
4912
+ run: action,
4913
+ undo: () => state
4914
+ });
4915
+ } else {
4916
+ performActionWithMetadata(metadata, {
4917
+ run: () => action,
4918
+ undo: () => state
4919
+ });
4920
+ }
4921
+ }
4922
+ },
4923
+ [state, stateManager]
4924
+ );
4925
+ return [state, setState, stateManager];
4926
+ }
4927
+ function useManagedHistory(stateManager) {
4928
+ return useSyncExternalStore2(
4929
+ stateManager.historyEmittor.addListener,
4930
+ stateManager.getHistorySnapshot,
4931
+ stateManager.getHistorySnapshot
4932
+ );
4933
+ }
4934
+ var defaultStubSync = stubSync();
4935
+ function useMultiplayerState(initialState, options) {
4936
+ const {
4937
+ sync = defaultStubSync,
4938
+ inspector,
4939
+ ...rest
4940
+ } = options ?? {};
4941
+ const [noyaManager] = useState(
4942
+ () => new NoyaManager(initialState, rest)
4943
+ );
4944
+ const state = useObservable(
4945
+ noyaManager.multiplayerStateManager.optimisticState$
4946
+ );
4947
+ const assets = useObservable(noyaManager.assetManager.assets$);
4948
+ const extras = useMemo2(() => {
4949
+ return {
4950
+ noyaManager,
4951
+ taskManager: noyaManager.taskManager,
4952
+ connectionEventManager: noyaManager.connectionEventManager,
4953
+ connectedUsersManager: noyaManager.connectedUsersManager,
4954
+ ephemeralUserDataManager: noyaManager.ephemeralUserDataManager,
4955
+ multiplayerStateManager: noyaManager.multiplayerStateManager,
4956
+ assetManager: noyaManager.assetManager,
4957
+ aiManager: noyaManager.aiManager,
4958
+ rpcManager: noyaManager.rpcManager,
4959
+ pipelineManager: noyaManager.pipelineManager,
4960
+ secretManager: noyaManager.secretManager,
4961
+ menuItemsManager: noyaManager.menuManager,
4962
+ createAsset: noyaManager.assetManager.create,
4963
+ deleteAsset: noyaManager.assetManager.delete,
4964
+ assets
4965
+ };
4966
+ }, [noyaManager, assets]);
4967
+ const syncRef = useRef(sync);
4968
+ useEffect2(() => {
4969
+ if (syncRef.current) {
4970
+ return syncRef.current({ noyaManager });
4971
+ }
4972
+ }, [noyaManager]);
4973
+ useErrorOverlay(noyaManager);
4974
+ useStateInspector({
4975
+ noyaManager,
4976
+ disabled: !inspector,
4977
+ ...typeof inspector === "object" && inspector
4978
+ });
4979
+ return [state, noyaManager.multiplayerStateManager.setState, extras];
4980
+ }
4981
+ function useErrorOverlay(noyaManager) {
4982
+ const unrecoverableError = useObservable(noyaManager.unrecoverableError);
4983
+ useEffect2(() => {
4984
+ if (!unrecoverableError) return;
4985
+ const el = document.createElement("div");
4986
+ el.id = "noya-multiplayer-react-error-overlay";
4987
+ document.body.appendChild(el);
4988
+ const root = createRoot2(el);
4989
+ root.render(createElement2(ErrorOverlay, { error: unrecoverableError }));
4990
+ return () => {
4991
+ root.unmount();
4992
+ el.remove();
4993
+ };
4994
+ });
4995
+ }
4980
4996
 
4981
4997
  // src/noyaApp.ts
4982
- import {
4983
- createOrCastValue,
4984
- isEmbeddedApp,
4985
- localStorageSync,
4986
- parentFrameSync,
4987
- stubSync as stubSync2,
4988
- TypeGuard,
4989
- webSocketSync
4990
- } from "@noya-app/state-manager";
4991
- import { useMemo as useMemo3, useState as useState3 } from "react";
4992
4998
  function createDefaultAppData(initialState) {
4993
4999
  return {
4994
5000
  theme: "light",
@@ -5037,7 +5043,7 @@ function useNoyaState(...args) {
5037
5043
  theme,
5038
5044
  viewType
5039
5045
  }
5040
- ] = useState3(() => {
5046
+ ] = useState2(() => {
5041
5047
  return getAppData(initialState, options?.schema, {
5042
5048
  overrideExistingState: options?.overrideExistingState
5043
5049
  });
@@ -5061,16 +5067,6 @@ function useNoyaState(...args) {
5061
5067
  }
5062
5068
 
5063
5069
  // src/NoyaStateContext.tsx
5064
- import {
5065
- Observable
5066
- } from "@noya-app/observable";
5067
- import React6, {
5068
- createContext,
5069
- useCallback as useCallback2,
5070
- useContext,
5071
- useEffect as useEffect4,
5072
- useMemo as useMemo4
5073
- } from "react";
5074
5070
  var AnyNoyaStateContext = createContext(void 0);
5075
5071
  function useAnyNoyaStateContext() {
5076
5072
  const value = useContext(AnyNoyaStateContext);
@@ -5219,17 +5215,17 @@ function createNoyaContext({
5219
5215
  }),
5220
5216
  [noyaManager, theme, viewType]
5221
5217
  );
5222
- return /* @__PURE__ */ React6.createElement(AnyNoyaStateContext.Provider, { value: contextValue }, /* @__PURE__ */ React6.createElement(
5218
+ return /* @__PURE__ */ React5.createElement(AnyNoyaStateContext.Provider, { value: contextValue }, /* @__PURE__ */ React5.createElement(
5223
5219
  ConnectedUsersContext.Provider,
5224
5220
  {
5225
5221
  value: noyaManager.connectedUsersManager
5226
5222
  },
5227
- /* @__PURE__ */ React6.createElement(
5223
+ /* @__PURE__ */ React5.createElement(
5228
5224
  EphemeralUserDataManagerContext.Provider,
5229
5225
  {
5230
5226
  value: noyaManager.ephemeralUserDataManager
5231
5227
  },
5232
- options.fallback !== void 0 ? /* @__PURE__ */ React6.createElement(FallbackUntilInitialized, { fallback: options.fallback }, children) : children
5228
+ options.fallback !== void 0 ? /* @__PURE__ */ React5.createElement(FallbackUntilInitialized, { fallback: options.fallback }, children) : children
5233
5229
  )
5234
5230
  ));
5235
5231
  }
@@ -5290,7 +5286,7 @@ function createNoyaContext({
5290
5286
  }
5291
5287
  function useSetLeftMenuItems(leftMenuItems) {
5292
5288
  const { menuManager } = useNoyaManager();
5293
- useEffect4(() => {
5289
+ useEffect3(() => {
5294
5290
  if (leftMenuItems) {
5295
5291
  menuManager.setLeftMenuItems(leftMenuItems);
5296
5292
  }
@@ -5302,7 +5298,7 @@ function createNoyaContext({
5302
5298
  }
5303
5299
  function useSetRightMenuItems(rightMenuItems) {
5304
5300
  const { menuManager } = useNoyaManager();
5305
- useEffect4(() => {
5301
+ useEffect3(() => {
5306
5302
  if (rightMenuItems) {
5307
5303
  menuManager.setRightMenuItems(rightMenuItems);
5308
5304
  }
@@ -5310,7 +5306,7 @@ function createNoyaContext({
5310
5306
  }
5311
5307
  function useHandleMenuItem(callback) {
5312
5308
  const { menuManager } = useNoyaManager();
5313
- useEffect4(() => {
5309
+ useEffect3(() => {
5314
5310
  return menuManager.addListener(callback);
5315
5311
  }, [menuManager, callback]);
5316
5312
  }
@@ -5345,6 +5341,75 @@ function createNoyaContext({
5345
5341
  };
5346
5342
  }
5347
5343
 
5344
+ // src/ai.ts
5345
+ function useRegisterAITool(tool) {
5346
+ const aiManager = useAIManager();
5347
+ useEffect4(() => {
5348
+ return aiManager.registerTool(tool);
5349
+ }, [aiManager, tool]);
5350
+ }
5351
+ function useCallableAITools() {
5352
+ const aiManager = useAIManager();
5353
+ return useObservable(aiManager.callableTools$);
5354
+ }
5355
+
5356
+ // src/components/UserPointersOverlay.tsx
5357
+ import { memoGeneric as memoGeneric2 } from "@noya-app/react-utils";
5358
+ import React6, { useEffect as useEffect5, useState as useState3 } from "react";
5359
+ function shouldShow(hideAfter, updatedAt) {
5360
+ return !!updatedAt && Date.now() - updatedAt < hideAfter;
5361
+ }
5362
+ var UserPointerInternal = memoGeneric2(function UserPointerInternal2({
5363
+ user,
5364
+ ephemeralUserDataManager,
5365
+ hideAfter = 5e3,
5366
+ renderUserPointer
5367
+ }) {
5368
+ const metadata = useObservable(ephemeralUserDataManager.metadata$, [
5369
+ user.id
5370
+ ]);
5371
+ const data = useObservable(ephemeralUserDataManager.data$, [
5372
+ user.id
5373
+ ]);
5374
+ const [, setForceUpdate] = useState3(0);
5375
+ const updatedAt = metadata?.updatedAt ?? 0;
5376
+ const show = shouldShow(hideAfter, updatedAt);
5377
+ useEffect5(() => {
5378
+ if (!show) return;
5379
+ const timeoutId = setTimeout(() => {
5380
+ setForceUpdate((prev) => prev + 1);
5381
+ }, hideAfter);
5382
+ return () => clearTimeout(timeoutId);
5383
+ }, [hideAfter, show, updatedAt]);
5384
+ if (!data?.pointer) return null;
5385
+ return renderUserPointer({
5386
+ userId: user.id,
5387
+ name: user.name,
5388
+ point: data.pointer,
5389
+ visible: show
5390
+ });
5391
+ });
5392
+ var UserPointersOverlay = memoGeneric2(function UserPointers({
5393
+ connectedUsersManager,
5394
+ ephemeralUserDataManager,
5395
+ renderUserPointer
5396
+ }) {
5397
+ const currentUserId = useObservable(ephemeralUserDataManager.currentUserId$);
5398
+ const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
5399
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, connectedUsers.map((user) => {
5400
+ if (user.id === currentUserId) return null;
5401
+ return /* @__PURE__ */ React6.createElement(
5402
+ UserPointerInternal,
5403
+ {
5404
+ key: user.id,
5405
+ user,
5406
+ ephemeralUserDataManager,
5407
+ renderUserPointer
5408
+ }
5409
+ );
5410
+ }));
5411
+ });
5412
+
5348
5413
  // src/WebSocketConnection.ts
5349
5414
  import {
5350
5415
  ReconnectingWebSocket,
@@ -5427,6 +5492,7 @@ var WebSocketConnection = class {
5427
5492
  };
5428
5493
  export {
5429
5494
  AnyEphemeralUserDataManagerContext,
5495
+ AnyNoyaStateContext,
5430
5496
  ConnectedUsersContext,
5431
5497
  FallbackUntilInitialized,
5432
5498
  StateInspector,
@@ -5444,6 +5510,7 @@ export {
5444
5510
  useAsset,
5445
5511
  useAssetManager,
5446
5512
  useAssets,
5513
+ useCallableAITools,
5447
5514
  useColorScheme,
5448
5515
  useConnectedUsersManager,
5449
5516
  useCurrentUserId,
@@ -5457,6 +5524,7 @@ export {
5457
5524
  useObservable,
5458
5525
  useOutputTransforms,
5459
5526
  usePipelineManager,
5527
+ useRegisterAITool,
5460
5528
  useSecret,
5461
5529
  useSecretManager,
5462
5530
  useSecrets,