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

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,34 @@ 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
+
4674
3383
  // ../noya-schemas/src/jsonSchema.ts
4675
3384
  var jsonSchema = Type.Recursive(
4676
3385
  (This) => Type.Union(
@@ -4721,274 +3430,1560 @@ var jsonSchema = Type.Recursive(
4721
3430
  }
4722
3431
  );
4723
3432
 
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"
3433
+ // ../noya-schemas/src/input.ts
3434
+ function Nullable(type) {
3435
+ return Type.Union([type, Type.Null()]);
3436
+ }
3437
+ var inputSchemaBase = {
3438
+ id: Type.String({ format: "uuid", default: "" }),
3439
+ name: Type.String(),
3440
+ description: Nullable(Type.String()),
3441
+ required: Type.Boolean({ default: false })
3442
+ };
3443
+ var fileInputSchema = Type.Object({
3444
+ ...inputSchemaBase,
3445
+ kind: Type.Literal("file"),
3446
+ toolId: Nullable(Type.String())
3447
+ });
3448
+ var dataInputSchema = Type.Object({
3449
+ ...inputSchemaBase,
3450
+ kind: Type.Literal("data"),
3451
+ schema: Nullable(jsonSchema)
3452
+ });
3453
+ var secretInputSchema = Type.Object({
3454
+ ...inputSchemaBase,
3455
+ kind: Type.Literal("secret")
3456
+ });
3457
+ var inputSchema = Type.Union(
3458
+ [fileInputSchema, dataInputSchema, secretInputSchema],
3459
+ {
3460
+ discriminator: "kind"
3461
+ }
3462
+ );
3463
+ var outputTransformSchemaBase = {
3464
+ id: Type.String({ format: "uuid", default: "" }),
3465
+ order: Type.Number()
3466
+ };
3467
+ var scriptOutputTransformSchema = Type.Object({
3468
+ ...outputTransformSchemaBase,
3469
+ kind: Type.Literal("script"),
3470
+ location: Type.Union([Type.Literal("state"), Type.Literal("url")]),
3471
+ value: Type.String()
3472
+ });
3473
+ var jsonPointerOutputTransformSchema = Type.Object({
3474
+ ...outputTransformSchemaBase,
3475
+ kind: Type.Literal("jsonPointer"),
3476
+ value: Type.String()
3477
+ });
3478
+ var outputTransformSchema = Type.Union(
3479
+ [scriptOutputTransformSchema, jsonPointerOutputTransformSchema],
3480
+ { discriminator: "kind" }
3481
+ );
3482
+
3483
+ // ../../node_modules/@sinclair/typebox/build/esm/value/guard/guard.mjs
3484
+ function IsObject4(value) {
3485
+ return value !== null && typeof value === "object";
3486
+ }
3487
+ function IsArray4(value) {
3488
+ return Array.isArray(value) && !ArrayBuffer.isView(value);
3489
+ }
3490
+ function IsUndefined4(value) {
3491
+ return value === void 0;
3492
+ }
3493
+ function IsNumber4(value) {
3494
+ return typeof value === "number";
3495
+ }
3496
+
3497
+ // ../../node_modules/@sinclair/typebox/build/esm/system/policy.mjs
3498
+ var TypeSystemPolicy;
3499
+ (function(TypeSystemPolicy2) {
3500
+ TypeSystemPolicy2.ExactOptionalPropertyTypes = false;
3501
+ TypeSystemPolicy2.AllowArrayObject = false;
3502
+ TypeSystemPolicy2.AllowNaN = false;
3503
+ TypeSystemPolicy2.AllowNullVoid = false;
3504
+ function IsExactOptionalProperty(value, key) {
3505
+ return TypeSystemPolicy2.ExactOptionalPropertyTypes ? key in value : value[key] !== void 0;
3506
+ }
3507
+ TypeSystemPolicy2.IsExactOptionalProperty = IsExactOptionalProperty;
3508
+ function IsObjectLike(value) {
3509
+ const isObject = IsObject4(value);
3510
+ return TypeSystemPolicy2.AllowArrayObject ? isObject : isObject && !IsArray4(value);
3511
+ }
3512
+ TypeSystemPolicy2.IsObjectLike = IsObjectLike;
3513
+ function IsRecordLike(value) {
3514
+ return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array);
3515
+ }
3516
+ TypeSystemPolicy2.IsRecordLike = IsRecordLike;
3517
+ function IsNumberLike(value) {
3518
+ return TypeSystemPolicy2.AllowNaN ? IsNumber4(value) : Number.isFinite(value);
3519
+ }
3520
+ TypeSystemPolicy2.IsNumberLike = IsNumberLike;
3521
+ function IsVoidLike(value) {
3522
+ const isUndefined = IsUndefined4(value);
3523
+ return TypeSystemPolicy2.AllowNullVoid ? isUndefined || value === null : isUndefined;
3524
+ }
3525
+ TypeSystemPolicy2.IsVoidLike = IsVoidLike;
3526
+ })(TypeSystemPolicy || (TypeSystemPolicy = {}));
3527
+
3528
+ // ../../node_modules/@sinclair/typebox/build/esm/system/system.mjs
3529
+ var TypeSystemDuplicateTypeKind = class extends TypeBoxError {
3530
+ constructor(kind) {
3531
+ super(`Duplicate type kind '${kind}' detected`);
3532
+ }
3533
+ };
3534
+ var TypeSystemDuplicateFormat = class extends TypeBoxError {
3535
+ constructor(kind) {
3536
+ super(`Duplicate string format '${kind}' detected`);
3537
+ }
3538
+ };
3539
+ var TypeSystem;
3540
+ (function(TypeSystem2) {
3541
+ function Type2(kind, check) {
3542
+ if (type_exports2.Has(kind))
3543
+ throw new TypeSystemDuplicateTypeKind(kind);
3544
+ type_exports2.Set(kind, check);
3545
+ return (options = {}) => Unsafe({ ...options, [Kind]: kind });
3546
+ }
3547
+ TypeSystem2.Type = Type2;
3548
+ function Format(format, check) {
3549
+ if (format_exports.Has(format))
3550
+ throw new TypeSystemDuplicateFormat(format);
3551
+ format_exports.Set(format, check);
3552
+ return format;
3553
+ }
3554
+ TypeSystem2.Format = Format;
3555
+ })(TypeSystem || (TypeSystem = {}));
3556
+
3557
+ // ../../node_modules/@sinclair/typebox/build/esm/value/hash/hash.mjs
3558
+ var ByteMarker;
3559
+ (function(ByteMarker2) {
3560
+ ByteMarker2[ByteMarker2["Undefined"] = 0] = "Undefined";
3561
+ ByteMarker2[ByteMarker2["Null"] = 1] = "Null";
3562
+ ByteMarker2[ByteMarker2["Boolean"] = 2] = "Boolean";
3563
+ ByteMarker2[ByteMarker2["Number"] = 3] = "Number";
3564
+ ByteMarker2[ByteMarker2["String"] = 4] = "String";
3565
+ ByteMarker2[ByteMarker2["Object"] = 5] = "Object";
3566
+ ByteMarker2[ByteMarker2["Array"] = 6] = "Array";
3567
+ ByteMarker2[ByteMarker2["Date"] = 7] = "Date";
3568
+ ByteMarker2[ByteMarker2["Uint8Array"] = 8] = "Uint8Array";
3569
+ ByteMarker2[ByteMarker2["Symbol"] = 9] = "Symbol";
3570
+ ByteMarker2[ByteMarker2["BigInt"] = 10] = "BigInt";
3571
+ })(ByteMarker || (ByteMarker = {}));
3572
+ var Accumulator = BigInt("14695981039346656037");
3573
+ var [Prime, Size] = [BigInt("1099511628211"), BigInt("2") ** BigInt("64")];
3574
+ var Bytes = Array.from({ length: 256 }).map((_, i) => BigInt(i));
3575
+ var F64 = new Float64Array(1);
3576
+ var F64In = new DataView(F64.buffer);
3577
+ var F64Out = new Uint8Array(F64.buffer);
3578
+
3579
+ // ../../node_modules/@sinclair/typebox/build/esm/errors/errors.mjs
3580
+ var ValueErrorType;
3581
+ (function(ValueErrorType2) {
3582
+ ValueErrorType2[ValueErrorType2["ArrayContains"] = 0] = "ArrayContains";
3583
+ ValueErrorType2[ValueErrorType2["ArrayMaxContains"] = 1] = "ArrayMaxContains";
3584
+ ValueErrorType2[ValueErrorType2["ArrayMaxItems"] = 2] = "ArrayMaxItems";
3585
+ ValueErrorType2[ValueErrorType2["ArrayMinContains"] = 3] = "ArrayMinContains";
3586
+ ValueErrorType2[ValueErrorType2["ArrayMinItems"] = 4] = "ArrayMinItems";
3587
+ ValueErrorType2[ValueErrorType2["ArrayUniqueItems"] = 5] = "ArrayUniqueItems";
3588
+ ValueErrorType2[ValueErrorType2["Array"] = 6] = "Array";
3589
+ ValueErrorType2[ValueErrorType2["AsyncIterator"] = 7] = "AsyncIterator";
3590
+ ValueErrorType2[ValueErrorType2["BigIntExclusiveMaximum"] = 8] = "BigIntExclusiveMaximum";
3591
+ ValueErrorType2[ValueErrorType2["BigIntExclusiveMinimum"] = 9] = "BigIntExclusiveMinimum";
3592
+ ValueErrorType2[ValueErrorType2["BigIntMaximum"] = 10] = "BigIntMaximum";
3593
+ ValueErrorType2[ValueErrorType2["BigIntMinimum"] = 11] = "BigIntMinimum";
3594
+ ValueErrorType2[ValueErrorType2["BigIntMultipleOf"] = 12] = "BigIntMultipleOf";
3595
+ ValueErrorType2[ValueErrorType2["BigInt"] = 13] = "BigInt";
3596
+ ValueErrorType2[ValueErrorType2["Boolean"] = 14] = "Boolean";
3597
+ ValueErrorType2[ValueErrorType2["DateExclusiveMaximumTimestamp"] = 15] = "DateExclusiveMaximumTimestamp";
3598
+ ValueErrorType2[ValueErrorType2["DateExclusiveMinimumTimestamp"] = 16] = "DateExclusiveMinimumTimestamp";
3599
+ ValueErrorType2[ValueErrorType2["DateMaximumTimestamp"] = 17] = "DateMaximumTimestamp";
3600
+ ValueErrorType2[ValueErrorType2["DateMinimumTimestamp"] = 18] = "DateMinimumTimestamp";
3601
+ ValueErrorType2[ValueErrorType2["DateMultipleOfTimestamp"] = 19] = "DateMultipleOfTimestamp";
3602
+ ValueErrorType2[ValueErrorType2["Date"] = 20] = "Date";
3603
+ ValueErrorType2[ValueErrorType2["Function"] = 21] = "Function";
3604
+ ValueErrorType2[ValueErrorType2["IntegerExclusiveMaximum"] = 22] = "IntegerExclusiveMaximum";
3605
+ ValueErrorType2[ValueErrorType2["IntegerExclusiveMinimum"] = 23] = "IntegerExclusiveMinimum";
3606
+ ValueErrorType2[ValueErrorType2["IntegerMaximum"] = 24] = "IntegerMaximum";
3607
+ ValueErrorType2[ValueErrorType2["IntegerMinimum"] = 25] = "IntegerMinimum";
3608
+ ValueErrorType2[ValueErrorType2["IntegerMultipleOf"] = 26] = "IntegerMultipleOf";
3609
+ ValueErrorType2[ValueErrorType2["Integer"] = 27] = "Integer";
3610
+ ValueErrorType2[ValueErrorType2["IntersectUnevaluatedProperties"] = 28] = "IntersectUnevaluatedProperties";
3611
+ ValueErrorType2[ValueErrorType2["Intersect"] = 29] = "Intersect";
3612
+ ValueErrorType2[ValueErrorType2["Iterator"] = 30] = "Iterator";
3613
+ ValueErrorType2[ValueErrorType2["Kind"] = 31] = "Kind";
3614
+ ValueErrorType2[ValueErrorType2["Literal"] = 32] = "Literal";
3615
+ ValueErrorType2[ValueErrorType2["Never"] = 33] = "Never";
3616
+ ValueErrorType2[ValueErrorType2["Not"] = 34] = "Not";
3617
+ ValueErrorType2[ValueErrorType2["Null"] = 35] = "Null";
3618
+ ValueErrorType2[ValueErrorType2["NumberExclusiveMaximum"] = 36] = "NumberExclusiveMaximum";
3619
+ ValueErrorType2[ValueErrorType2["NumberExclusiveMinimum"] = 37] = "NumberExclusiveMinimum";
3620
+ ValueErrorType2[ValueErrorType2["NumberMaximum"] = 38] = "NumberMaximum";
3621
+ ValueErrorType2[ValueErrorType2["NumberMinimum"] = 39] = "NumberMinimum";
3622
+ ValueErrorType2[ValueErrorType2["NumberMultipleOf"] = 40] = "NumberMultipleOf";
3623
+ ValueErrorType2[ValueErrorType2["Number"] = 41] = "Number";
3624
+ ValueErrorType2[ValueErrorType2["ObjectAdditionalProperties"] = 42] = "ObjectAdditionalProperties";
3625
+ ValueErrorType2[ValueErrorType2["ObjectMaxProperties"] = 43] = "ObjectMaxProperties";
3626
+ ValueErrorType2[ValueErrorType2["ObjectMinProperties"] = 44] = "ObjectMinProperties";
3627
+ ValueErrorType2[ValueErrorType2["ObjectRequiredProperty"] = 45] = "ObjectRequiredProperty";
3628
+ ValueErrorType2[ValueErrorType2["Object"] = 46] = "Object";
3629
+ ValueErrorType2[ValueErrorType2["Promise"] = 47] = "Promise";
3630
+ ValueErrorType2[ValueErrorType2["RegExp"] = 48] = "RegExp";
3631
+ ValueErrorType2[ValueErrorType2["StringFormatUnknown"] = 49] = "StringFormatUnknown";
3632
+ ValueErrorType2[ValueErrorType2["StringFormat"] = 50] = "StringFormat";
3633
+ ValueErrorType2[ValueErrorType2["StringMaxLength"] = 51] = "StringMaxLength";
3634
+ ValueErrorType2[ValueErrorType2["StringMinLength"] = 52] = "StringMinLength";
3635
+ ValueErrorType2[ValueErrorType2["StringPattern"] = 53] = "StringPattern";
3636
+ ValueErrorType2[ValueErrorType2["String"] = 54] = "String";
3637
+ ValueErrorType2[ValueErrorType2["Symbol"] = 55] = "Symbol";
3638
+ ValueErrorType2[ValueErrorType2["TupleLength"] = 56] = "TupleLength";
3639
+ ValueErrorType2[ValueErrorType2["Tuple"] = 57] = "Tuple";
3640
+ ValueErrorType2[ValueErrorType2["Uint8ArrayMaxByteLength"] = 58] = "Uint8ArrayMaxByteLength";
3641
+ ValueErrorType2[ValueErrorType2["Uint8ArrayMinByteLength"] = 59] = "Uint8ArrayMinByteLength";
3642
+ ValueErrorType2[ValueErrorType2["Uint8Array"] = 60] = "Uint8Array";
3643
+ ValueErrorType2[ValueErrorType2["Undefined"] = 61] = "Undefined";
3644
+ ValueErrorType2[ValueErrorType2["Union"] = 62] = "Union";
3645
+ ValueErrorType2[ValueErrorType2["Void"] = 63] = "Void";
3646
+ })(ValueErrorType || (ValueErrorType = {}));
3647
+
3648
+ // ../../node_modules/@sinclair/typebox/build/esm/value/delta/delta.mjs
3649
+ var Insert = Object2({
3650
+ type: Literal("insert"),
3651
+ path: String(),
3652
+ value: Unknown()
4746
3653
  });
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()
3654
+ var Update = Object2({
3655
+ type: Literal("update"),
3656
+ path: String(),
3657
+ value: Unknown()
4756
3658
  });
4757
- var jsonPointerOutputTransformSchema = Type.Object({
4758
- ...outputTransformSchemaBase,
4759
- kind: Type.Literal("jsonPointer"),
4760
- value: Type.String()
3659
+ var Delete3 = Object2({
3660
+ type: Literal("delete"),
3661
+ path: String()
4761
3662
  });
4762
- var outputTransformSchema = Type.Union(
4763
- [scriptOutputTransformSchema, jsonPointerOutputTransformSchema],
4764
- { discriminator: "kind" }
4765
- );
3663
+ var Edit = Union([Insert, Update, Delete3]);
4766
3664
 
4767
- // ../../node_modules/@sinclair/typebox/build/esm/value/guard/guard.mjs
4768
- function IsObject4(value) {
4769
- return value !== null && typeof value === "object";
3665
+ // ../noya-schemas/src/SchemaTree.ts
3666
+ var import_tree_visit = __toESM(require_lib());
3667
+ var SchemaTree = (0, import_tree_visit.defineTree)((schema) => {
3668
+ if (type_exports.IsUnion(schema)) {
3669
+ return schema.anyOf;
3670
+ } else if (type_exports.IsObject(schema)) {
3671
+ return Object.values(schema.properties);
3672
+ } else if (type_exports.IsArray(schema)) {
3673
+ return [schema.items];
3674
+ }
3675
+ return [];
3676
+ }).withOptions({
3677
+ getLabel(node) {
3678
+ return node[Kind] ?? "<UnknownKind>";
3679
+ }
3680
+ });
3681
+ function findAllDefs(schema) {
3682
+ if (!schema) return [];
3683
+ return SchemaTree.flatMap(schema, (node) => {
3684
+ return node.$id ? [node] : [];
3685
+ });
4770
3686
  }
4771
- function IsArray4(value) {
4772
- return Array.isArray(value) && !ArrayBuffer.isView(value);
3687
+
3688
+ // ../noya-schemas/src/index.ts
3689
+ function validateUUID(value) {
3690
+ 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(
3691
+ value
3692
+ );
4773
3693
  }
4774
- function IsUndefined4(value) {
4775
- return value === void 0;
3694
+ format_exports.Set("color", () => true);
3695
+ format_exports.Set("uuid", validateUUID);
3696
+
3697
+ // src/noyaApp.ts
3698
+ import {
3699
+ createOrCastValue,
3700
+ isEmbeddedApp,
3701
+ localStorageSync,
3702
+ parentFrameSync,
3703
+ stubSync as stubSync2,
3704
+ TypeGuard,
3705
+ webSocketSync
3706
+ } from "@noya-app/state-manager";
3707
+ import { useMemo as useMemo3, useState as useState2 } from "react";
3708
+
3709
+ // src/hooks.ts
3710
+ import {
3711
+ NoyaManager,
3712
+ StateManager,
3713
+ stubSync
3714
+ } from "@noya-app/state-manager";
3715
+ import {
3716
+ createElement as createElement2,
3717
+ useCallback,
3718
+ useEffect as useEffect2,
3719
+ useMemo as useMemo2,
3720
+ useRef,
3721
+ useState,
3722
+ useSyncExternalStore as useSyncExternalStore2
3723
+ } from "react";
3724
+ import { createRoot as createRoot2 } from "react-dom/client";
3725
+
3726
+ // src/components/ErrorOverlay.tsx
3727
+ import * as React from "react";
3728
+ var ErrorOverlay = React.memo(function ErrorOverlay2({
3729
+ error
3730
+ }) {
3731
+ return /* @__PURE__ */ React.createElement(
3732
+ "div",
3733
+ {
3734
+ style: {
3735
+ position: "fixed",
3736
+ top: "20px",
3737
+ left: "50%",
3738
+ transform: "translateX(-50%)",
3739
+ maxWidth: "80%",
3740
+ width: "fit-content",
3741
+ padding: "12px 20px",
3742
+ background: "white",
3743
+ color: "black",
3744
+ zIndex: 1e4,
3745
+ display: "flex",
3746
+ flexDirection: "column",
3747
+ justifyContent: "center",
3748
+ borderRadius: "4px",
3749
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
3750
+ fontFamily: "'__Inter_6b0edc', '__Inter_Fallback_6b0edc', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
3751
+ fontSize: "14px",
3752
+ fontWeight: 400,
3753
+ lineHeight: "19px"
3754
+ }
3755
+ },
3756
+ 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(
3757
+ "code",
3758
+ {
3759
+ style: {
3760
+ background: "rgba(255, 0, 0, 0.1)",
3761
+ color: "rgba(255, 0, 0, 0.5)",
3762
+ padding: "2px 4px",
3763
+ borderRadius: "4px"
3764
+ }
3765
+ },
3766
+ error.reason
3767
+ ), ". 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.")),
3768
+ /* @__PURE__ */ React.createElement(
3769
+ "div",
3770
+ {
3771
+ style: {
3772
+ height: "1px",
3773
+ background: "rgba(0, 0, 0, 0.1)",
3774
+ margin: "12px -20px"
3775
+ }
3776
+ }
3777
+ ),
3778
+ /* @__PURE__ */ React.createElement(
3779
+ "button",
3780
+ {
3781
+ style: {
3782
+ background: "black",
3783
+ color: "white",
3784
+ padding: "8px 16px",
3785
+ borderRadius: "4px",
3786
+ cursor: "pointer",
3787
+ fontSize: "14px",
3788
+ fontWeight: 700,
3789
+ lineHeight: "19px"
3790
+ },
3791
+ onClick: () => {
3792
+ window.location.reload();
3793
+ }
3794
+ },
3795
+ "Reload"
3796
+ )
3797
+ );
3798
+ });
3799
+
3800
+ // src/inspector/useStateInspector.tsx
3801
+ import React4, { useLayoutEffect as useLayoutEffect2 } from "react";
3802
+ import { createRoot } from "react-dom/client";
3803
+
3804
+ // src/inspector/StateInspector.tsx
3805
+ import { memoGeneric } from "@noya-app/react-utils";
3806
+ import React3, {
3807
+ useEffect,
3808
+ useLayoutEffect
3809
+ } from "react";
3810
+ import {
3811
+ ObjectInspector,
3812
+ ObjectLabel,
3813
+ ObjectName,
3814
+ ObjectPreview,
3815
+ chromeDark,
3816
+ chromeLight
3817
+ } from "react-inspector";
3818
+
3819
+ // src/useObservable.ts
3820
+ import { useMemo, useSyncExternalStore } from "react";
3821
+ function useObservable(observable, pathOrSelector, options) {
3822
+ const { get, listen } = useMemo(() => {
3823
+ if (!observable) {
3824
+ return {
3825
+ get: () => void 0,
3826
+ listen: () => () => {
3827
+ }
3828
+ };
3829
+ }
3830
+ if (typeof pathOrSelector === "function") {
3831
+ const mappedObservable = observable.map(pathOrSelector, {
3832
+ isEqual: options?.isEqual
3833
+ });
3834
+ return {
3835
+ get: mappedObservable.get,
3836
+ listen: mappedObservable.subscribe
3837
+ };
3838
+ }
3839
+ const listen2 = pathOrSelector ? (callback) => observable.subscribe(pathOrSelector, callback) : observable.subscribe;
3840
+ const get2 = pathOrSelector ? () => observable.get(pathOrSelector) : observable.get;
3841
+ return { get: get2, listen: listen2 };
3842
+ }, [observable, pathOrSelector, options?.isEqual]);
3843
+ return useSyncExternalStore(listen, get, get);
4776
3844
  }
4777
- function IsNumber4(value) {
4778
- return typeof value === "number";
3845
+
3846
+ // src/inspector/useLocalStorageState.tsx
3847
+ import React2 from "react";
3848
+ var localStorage = typeof window !== "undefined" ? window.localStorage : null;
3849
+ function useLocalStorageState(key, defaultValue) {
3850
+ const [state, setState] = React2.useState(() => {
3851
+ const value = localStorage?.getItem(key);
3852
+ let result = defaultValue;
3853
+ if (value) {
3854
+ try {
3855
+ result = JSON.parse(value);
3856
+ } catch (error) {
3857
+ console.error("Error parsing localStorage value", error);
3858
+ }
3859
+ }
3860
+ return result;
3861
+ });
3862
+ const setLocalStorageState = (value) => {
3863
+ localStorage?.setItem(key, JSON.stringify(value));
3864
+ setState(value);
3865
+ };
3866
+ return [state, setLocalStorageState];
4779
3867
  }
4780
3868
 
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);
3869
+ // src/inspector/StateInspector.tsx
3870
+ var lightTheme = {
3871
+ ...chromeLight,
3872
+ BASE_BACKGROUND_COLOR: "transparent",
3873
+ OBJECT_NAME_COLOR: "rgba(0,0,0,0.7)"
3874
+ };
3875
+ var darkTheme = {
3876
+ ...chromeDark,
3877
+ BASE_BACKGROUND_COLOR: "transparent",
3878
+ OBJECT_NAME_COLOR: "rgba(255,255,255,0.7)"
3879
+ };
3880
+ var styles = {
3881
+ sectionInner: {
3882
+ flex: "1 1 0",
3883
+ overflowY: "auto",
3884
+ overflowX: "hidden",
3885
+ display: "flex",
3886
+ flexDirection: "column"
4803
3887
  }
4804
- TypeSystemPolicy2.IsNumberLike = IsNumberLike;
4805
- function IsVoidLike(value) {
4806
- const isUndefined = IsUndefined4(value);
4807
- return TypeSystemPolicy2.AllowNullVoid ? isUndefined || value === null : isUndefined;
3888
+ };
3889
+ function ToggleButton({
3890
+ showInspector,
3891
+ setShowInspector,
3892
+ theme,
3893
+ anchor
3894
+ }) {
3895
+ return /* @__PURE__ */ React3.createElement(
3896
+ "span",
3897
+ {
3898
+ role: "button",
3899
+ style: {
3900
+ flex: "0",
3901
+ appearance: "none",
3902
+ color: theme.BASE_COLOR,
3903
+ border: "none",
3904
+ fontSize: "12px",
3905
+ whiteSpace: "nowrap",
3906
+ display: "inline-flex",
3907
+ alignItems: "center",
3908
+ justifyContent: "center",
3909
+ padding: "2px 0"
3910
+ },
3911
+ onClick: (event) => {
3912
+ event.stopPropagation();
3913
+ setShowInspector(!showInspector);
3914
+ }
3915
+ },
3916
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, showInspector === (anchor === "right") ? /* @__PURE__ */ React3.createElement(
3917
+ "svg",
3918
+ {
3919
+ xmlns: "http://www.w3.org/2000/svg",
3920
+ fill: "none",
3921
+ viewBox: "0 0 24 24",
3922
+ strokeWidth: 1.5,
3923
+ stroke: "currentColor",
3924
+ className: "size-6"
3925
+ },
3926
+ /* @__PURE__ */ React3.createElement(
3927
+ "path",
3928
+ {
3929
+ strokeLinecap: "round",
3930
+ strokeLinejoin: "round",
3931
+ d: "m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"
3932
+ }
3933
+ )
3934
+ ) : /* @__PURE__ */ React3.createElement(
3935
+ "svg",
3936
+ {
3937
+ xmlns: "http://www.w3.org/2000/svg",
3938
+ fill: "none",
3939
+ viewBox: "0 0 24 24",
3940
+ strokeWidth: 1.5,
3941
+ stroke: "currentColor",
3942
+ className: "size-6"
3943
+ },
3944
+ /* @__PURE__ */ React3.createElement(
3945
+ "path",
3946
+ {
3947
+ strokeLinecap: "round",
3948
+ strokeLinejoin: "round",
3949
+ d: "m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5"
3950
+ }
3951
+ )
3952
+ ))
3953
+ );
3954
+ }
3955
+ function DisclosureSection({
3956
+ open,
3957
+ setOpen,
3958
+ title,
3959
+ right,
3960
+ children,
3961
+ colorScheme,
3962
+ isFirst,
3963
+ style
3964
+ }) {
3965
+ const theme = colorScheme === "light" ? lightTheme : darkTheme;
3966
+ const borderColor = colorScheme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)";
3967
+ return /* @__PURE__ */ React3.createElement(
3968
+ "div",
3969
+ {
3970
+ style: {
3971
+ flex: open ? "1 1 0" : "0",
3972
+ display: "flex",
3973
+ flexDirection: "column",
3974
+ ...style
3975
+ }
3976
+ },
3977
+ /* @__PURE__ */ React3.createElement(
3978
+ "div",
3979
+ {
3980
+ onClick: () => setOpen?.(!open),
3981
+ style: {
3982
+ cursor: "default",
3983
+ fontSize: "12px",
3984
+ padding: "4px 10px",
3985
+ display: "flex",
3986
+ alignItems: "center",
3987
+ ...!isFirst && { borderTop: `1px solid ${borderColor}` },
3988
+ ...open && { borderBottom: `1px solid ${borderColor}` }
3989
+ }
3990
+ },
3991
+ setOpen && /* @__PURE__ */ React3.createElement(
3992
+ Arrow,
3993
+ {
3994
+ expanded: open,
3995
+ style: {
3996
+ fontSize: theme.ARROW_FONT_SIZE,
3997
+ marginRight: theme.ARROW_MARGIN_RIGHT + 1,
3998
+ color: theme.ARROW_COLOR
3999
+ }
4000
+ }
4001
+ ),
4002
+ /* @__PURE__ */ React3.createElement("span", { style: { flex: "1 1 0", userSelect: "none" } }, title),
4003
+ right
4004
+ ),
4005
+ open && children
4006
+ );
4007
+ }
4008
+ function InspectorRow({
4009
+ children,
4010
+ colorScheme,
4011
+ selected,
4012
+ style,
4013
+ variant
4014
+ }) {
4015
+ const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
4016
+ return /* @__PURE__ */ React3.createElement(
4017
+ "div",
4018
+ {
4019
+ style: {
4020
+ borderBottom: `1px solid ${solidBorderColor}`,
4021
+ fontSize: "12px",
4022
+ fontFamily: "Menlo, monospace",
4023
+ padding: "2px 12px 1px",
4024
+ display: "flex",
4025
+ alignItems: "center",
4026
+ background: variant === "up" ? "rgba(0,255,0,0.1)" : variant === "down" ? "transparent" : selected ? "rgb(59 130 246 / 15%)" : void 0,
4027
+ // background:
4028
+ // colorScheme === "light"
4029
+ // ? "rgba(0,0,0,0.05)"
4030
+ // : "rgba(255,255,255,0.05)",
4031
+ ...style
4032
+ }
4033
+ },
4034
+ /* @__PURE__ */ React3.createElement(
4035
+ "span",
4036
+ {
4037
+ style: {
4038
+ fontFamily: "Menlo, monospace",
4039
+ fontSize: "11px",
4040
+ borderRadius: 4,
4041
+ display: "inline-block"
4042
+ }
4043
+ },
4044
+ children
4045
+ )
4046
+ );
4047
+ }
4048
+ var HISTORY_ELEMENT_PREFIX = "noya-multiplayer-history-";
4049
+ var StateInspector = memoGeneric(function StateInspector2({
4050
+ noyaManager,
4051
+ colorScheme = "light",
4052
+ anchor = "right",
4053
+ unstyled = false,
4054
+ ...props
4055
+ }) {
4056
+ const {
4057
+ multiplayerStateManager,
4058
+ assetManager,
4059
+ connectedUsersManager,
4060
+ secretManager,
4061
+ ephemeralUserDataManager,
4062
+ connectionEventManager,
4063
+ taskManager,
4064
+ ioManager
4065
+ } = noyaManager;
4066
+ const [didMount, setDidMount] = React3.useState(false);
4067
+ const tasks = useObservable(taskManager.tasks$);
4068
+ const inputs = useObservable(ioManager.inputs$);
4069
+ const outputTransforms = useObservable(ioManager.outputTransforms$);
4070
+ useLayoutEffect(() => {
4071
+ setDidMount(true);
4072
+ }, []);
4073
+ const eventsContainerRef = React3.useRef(null);
4074
+ const historyContainerRef = React3.useRef(null);
4075
+ const [showInspector, setShowInspector] = useLocalStorageState(
4076
+ "noya-multiplayer-react-show-inspector",
4077
+ true
4078
+ );
4079
+ const [showEvents, setShowEvents] = useLocalStorageState(
4080
+ "noya-multiplayer-react-show-events",
4081
+ false
4082
+ );
4083
+ const [showHistory, setShowHistory] = useLocalStorageState(
4084
+ "noya-multiplayer-react-show-history",
4085
+ false
4086
+ );
4087
+ const [showUsers, setShowUsers] = useLocalStorageState(
4088
+ "noya-multiplayer-react-show-users",
4089
+ true
4090
+ );
4091
+ const [showData, setShowData] = useLocalStorageState(
4092
+ "noya-multiplayer-react-show-data",
4093
+ true
4094
+ );
4095
+ const [showTasks, setShowTasks] = useLocalStorageState(
4096
+ "noya-multiplayer-react-show-tasks",
4097
+ false
4098
+ );
4099
+ const [showEphemeral, setShowEphemeral] = useLocalStorageState(
4100
+ "noya-multiplayer-react-show-ephemeral",
4101
+ false
4102
+ );
4103
+ const [showAssets, setShowAssets] = useLocalStorageState(
4104
+ "noya-multiplayer-react-show-assets",
4105
+ false
4106
+ );
4107
+ const [showSecrets, setShowSecrets] = useLocalStorageState(
4108
+ "noya-multiplayer-react-show-secrets",
4109
+ false
4110
+ );
4111
+ const [showInputs, setShowInputs] = useLocalStorageState(
4112
+ "noya-multiplayer-react-show-inputs",
4113
+ false
4114
+ );
4115
+ const [showOutputTransforms, setShowOutputTransforms] = useLocalStorageState(
4116
+ "noya-multiplayer-react-show-output-transforms",
4117
+ false
4118
+ );
4119
+ const connectionEvents = useObservable(connectionEventManager.events$);
4120
+ useEffect(() => {
4121
+ if (eventsContainerRef.current) {
4122
+ eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
4123
+ }
4124
+ }, [connectionEvents]);
4125
+ const multipeerStateInitialized = useObservable(
4126
+ multiplayerStateManager.isInitialized$
4127
+ );
4128
+ const ephemeral = useObservable(ephemeralUserDataManager.data$);
4129
+ const historySnapshot = useManagedHistory(multiplayerStateManager.sm);
4130
+ const assets = useObservable(assetManager.assets$);
4131
+ const assetsInitialized = useObservable(assetManager.isInitialized$);
4132
+ const secrets = useObservable(secretManager.secrets$);
4133
+ const secretsInitialized = useObservable(secretManager.isInitialized$);
4134
+ const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
4135
+ const userId = useObservable(connectedUsersManager.currentUserId$);
4136
+ const state = useObservable(multiplayerStateManager.optimisticState$);
4137
+ const inputsInitialized = useObservable(ioManager.inputsInitialized$);
4138
+ const outputTransformsInitialized = useObservable(
4139
+ ioManager.outputTransformsInitialized$
4140
+ );
4141
+ useEffect(() => {
4142
+ if (historyContainerRef.current) {
4143
+ historyContainerRef.current.scrollTop = historyContainerRef.current.scrollHeight;
4144
+ }
4145
+ }, [historySnapshot]);
4146
+ useEffect(() => {
4147
+ if (!historyContainerRef.current) return;
4148
+ const historyEntry = historyContainerRef.current.querySelector(
4149
+ `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
4150
+ );
4151
+ if (historyEntry) {
4152
+ historyEntry.scrollIntoView({
4153
+ block: "nearest",
4154
+ inline: "nearest"
4155
+ });
4156
+ }
4157
+ }, [historySnapshot.historyIndex]);
4158
+ const theme = colorScheme === "light" ? lightTheme : darkTheme;
4159
+ const solidBorderColor = colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)";
4160
+ const baseStyle = {
4161
+ position: "fixed",
4162
+ top: 12,
4163
+ ...anchor.includes("right") ? { right: 12 } : { left: 12 },
4164
+ bottom: 12,
4165
+ width: 400,
4166
+ background: colorScheme === "light" ? "rgba(255,255,255,0.95)" : "rgba(0,0,0,0.95)",
4167
+ backdropFilter: "blur(48px)",
4168
+ border: `1px solid ${solidBorderColor}`,
4169
+ // outlineOffset: -1,
4170
+ borderRadius: 4,
4171
+ display: "flex",
4172
+ flexDirection: "column",
4173
+ // gap: 12,
4174
+ color: theme.BASE_COLOR,
4175
+ overflow: "hidden",
4176
+ zIndex: 9999,
4177
+ lineHeight: "13px"
4178
+ };
4179
+ if (!didMount) return null;
4180
+ if (!showInspector) {
4181
+ return /* @__PURE__ */ React3.createElement(
4182
+ "div",
4183
+ {
4184
+ ...props,
4185
+ style: {
4186
+ ...baseStyle,
4187
+ padding: "4px 10px",
4188
+ width: void 0,
4189
+ ...anchor.includes("bottom") ? { bottom: 12, top: void 0 } : { bottom: void 0 }
4190
+ },
4191
+ onClick: () => setShowInspector(true)
4192
+ },
4193
+ /* @__PURE__ */ React3.createElement(
4194
+ ToggleButton,
4195
+ {
4196
+ showInspector,
4197
+ setShowInspector,
4198
+ theme,
4199
+ anchor
4200
+ }
4201
+ )
4202
+ );
4808
4203
  }
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`);
4204
+ return /* @__PURE__ */ React3.createElement(
4205
+ "div",
4206
+ {
4207
+ ...props,
4208
+ style: {
4209
+ ...!unstyled && baseStyle,
4210
+ ...props.style
4211
+ }
4212
+ },
4213
+ /* @__PURE__ */ React3.createElement(
4214
+ DisclosureSection,
4215
+ {
4216
+ isFirst: true,
4217
+ open: showUsers,
4218
+ setOpen: setShowUsers,
4219
+ title: "Users",
4220
+ colorScheme,
4221
+ style: {
4222
+ flex: "0 0 auto",
4223
+ maxHeight: "200px"
4224
+ },
4225
+ right: /* @__PURE__ */ React3.createElement(
4226
+ ToggleButton,
4227
+ {
4228
+ showInspector,
4229
+ setShowInspector,
4230
+ theme,
4231
+ anchor
4232
+ }
4233
+ )
4234
+ },
4235
+ /* @__PURE__ */ React3.createElement("div", { style: { ...styles.sectionInner, flex: "0 0 auto" } }, connectedUsers?.map((user) => /* @__PURE__ */ React3.createElement(
4236
+ InspectorRow,
4237
+ {
4238
+ key: user.id,
4239
+ colorScheme,
4240
+ variant: user.id === userId ? "up" : void 0
4241
+ },
4242
+ user.image && /* @__PURE__ */ React3.createElement(
4243
+ "img",
4244
+ {
4245
+ src: user.image,
4246
+ alt: user.name,
4247
+ style: {
4248
+ width: "13px",
4249
+ height: "13px",
4250
+ borderRadius: "50%",
4251
+ marginRight: "4px",
4252
+ display: "inline-block",
4253
+ position: "relative",
4254
+ background: solidBorderColor,
4255
+ verticalAlign: "middle"
4256
+ }
4257
+ }
4258
+ ),
4259
+ user.name,
4260
+ " (",
4261
+ ellipsis(user.id.toString(), 8, "middle"),
4262
+ ")"
4263
+ )), !connectedUsers && /* @__PURE__ */ React3.createElement(
4264
+ "div",
4265
+ {
4266
+ style: {
4267
+ padding: "12px",
4268
+ fontSize: "12px",
4269
+ display: "flex",
4270
+ flexDirection: "column",
4271
+ gap: "4px"
4272
+ }
4273
+ },
4274
+ /* @__PURE__ */ React3.createElement("span", null, "No connected users")
4275
+ ))
4276
+ ),
4277
+ /* @__PURE__ */ React3.createElement(
4278
+ DisclosureSection,
4279
+ {
4280
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Data", /* @__PURE__ */ React3.createElement(
4281
+ ColoredDot,
4282
+ {
4283
+ type: multipeerStateInitialized ? "success" : "error"
4284
+ }
4285
+ )),
4286
+ colorScheme,
4287
+ setOpen: setShowData,
4288
+ open: showData,
4289
+ right: /* @__PURE__ */ React3.createElement(
4290
+ "span",
4291
+ {
4292
+ style: {
4293
+ display: "flex",
4294
+ gap: "4px"
4295
+ }
4296
+ },
4297
+ /* @__PURE__ */ React3.createElement(
4298
+ SmallButton,
4299
+ {
4300
+ theme,
4301
+ onClick: () => {
4302
+ noyaManager.forceInit();
4303
+ }
4304
+ },
4305
+ "Reset"
4306
+ )
4307
+ )
4308
+ },
4309
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
4310
+ ObjectInspector,
4311
+ {
4312
+ name: multiplayerStateManager.schema ? "state" : void 0,
4313
+ data: state,
4314
+ theme
4315
+ }
4316
+ )), multiplayerStateManager.schema && /* @__PURE__ */ React3.createElement(InspectorRow, { colorScheme }, /* @__PURE__ */ React3.createElement(
4317
+ ObjectInspector,
4318
+ {
4319
+ name: "schema",
4320
+ data: multiplayerStateManager.schema,
4321
+ theme
4322
+ }
4323
+ )))
4324
+ ),
4325
+ /* @__PURE__ */ React3.createElement(
4326
+ DisclosureSection,
4327
+ {
4328
+ open: showHistory,
4329
+ setOpen: setShowHistory,
4330
+ title: "History",
4331
+ colorScheme,
4332
+ right: /* @__PURE__ */ React3.createElement(
4333
+ "span",
4334
+ {
4335
+ style: {
4336
+ display: "flex",
4337
+ gap: "4px"
4338
+ }
4339
+ },
4340
+ /* @__PURE__ */ React3.createElement(
4341
+ SmallButton,
4342
+ {
4343
+ disabled: !historySnapshot.canUndo,
4344
+ theme,
4345
+ onClick: () => {
4346
+ multiplayerStateManager.undo();
4347
+ }
4348
+ },
4349
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
4350
+ "svg",
4351
+ {
4352
+ xmlns: "http://www.w3.org/2000/svg",
4353
+ width: "1em",
4354
+ height: "1em",
4355
+ viewBox: "0 0 20 20"
4356
+ },
4357
+ /* @__PURE__ */ React3.createElement(
4358
+ "path",
4359
+ {
4360
+ fill: "currentColor",
4361
+ 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"
4362
+ }
4363
+ )
4364
+ ))
4365
+ ),
4366
+ /* @__PURE__ */ React3.createElement(
4367
+ SmallButton,
4368
+ {
4369
+ disabled: !historySnapshot.canRedo,
4370
+ theme,
4371
+ onClick: () => {
4372
+ multiplayerStateManager.redo();
4373
+ }
4374
+ },
4375
+ /* @__PURE__ */ React3.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React3.createElement(
4376
+ "svg",
4377
+ {
4378
+ xmlns: "http://www.w3.org/2000/svg",
4379
+ width: "1em",
4380
+ height: "1em",
4381
+ viewBox: "0 0 20 20"
4382
+ },
4383
+ /* @__PURE__ */ React3.createElement(
4384
+ "path",
4385
+ {
4386
+ fill: "currentColor",
4387
+ 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"
4388
+ }
4389
+ )
4390
+ ))
4391
+ )
4392
+ )
4393
+ },
4394
+ /* @__PURE__ */ React3.createElement("div", { ref: historyContainerRef, style: styles.sectionInner }, /* @__PURE__ */ React3.createElement(
4395
+ "div",
4396
+ {
4397
+ id: `${HISTORY_ELEMENT_PREFIX}0`,
4398
+ style: {
4399
+ borderBottom: `1px solid ${solidBorderColor}`,
4400
+ fontSize: "12px",
4401
+ fontFamily: "Menlo, monospace",
4402
+ padding: "2px 12px 1px",
4403
+ display: "flex",
4404
+ alignItems: "center",
4405
+ background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
4406
+ }
4407
+ },
4408
+ /* @__PURE__ */ React3.createElement(
4409
+ "span",
4410
+ {
4411
+ style: {
4412
+ fontFamily: "Menlo, monospace",
4413
+ fontSize: "11px",
4414
+ borderRadius: 4,
4415
+ display: "inline-block"
4416
+ }
4417
+ },
4418
+ "Initial state"
4419
+ )
4420
+ ), historySnapshot.history.map((entry, index) => /* @__PURE__ */ React3.createElement(
4421
+ "div",
4422
+ {
4423
+ id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
4424
+ key: index,
4425
+ style: {
4426
+ padding: "0px 12px 1px",
4427
+ borderBottom: `1px solid ${solidBorderColor}`,
4428
+ background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
4429
+ }
4430
+ },
4431
+ "name" in entry.metadata && typeof entry.metadata.name === "string" && /* @__PURE__ */ React3.createElement(
4432
+ "pre",
4433
+ {
4434
+ style: {
4435
+ fontSize: "11px",
4436
+ display: "flex",
4437
+ flexWrap: "wrap",
4438
+ margin: 0
4439
+ }
4440
+ },
4441
+ entry.metadata.name
4442
+ ),
4443
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React3.createElement(
4444
+ "pre",
4445
+ {
4446
+ key: j,
4447
+ style: {
4448
+ fontSize: "11px",
4449
+ display: "flex",
4450
+ flexWrap: "wrap",
4451
+ margin: 0
4452
+ }
4453
+ },
4454
+ 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 })),
4455
+ 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 })),
4456
+ 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))),
4457
+ 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)))
4458
+ ))
4459
+ )))
4460
+ ),
4461
+ /* @__PURE__ */ React3.createElement(
4462
+ DisclosureSection,
4463
+ {
4464
+ open: showAssets,
4465
+ setOpen: setShowAssets,
4466
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Assets", /* @__PURE__ */ React3.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
4467
+ colorScheme,
4468
+ right: /* @__PURE__ */ React3.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React3.createElement(
4469
+ SmallButton,
4470
+ {
4471
+ theme,
4472
+ onClick: () => {
4473
+ console.info(
4474
+ "[StateInspector] Reloading assets",
4475
+ noyaManager.id
4476
+ );
4477
+ assetManager.fetch();
4478
+ }
4479
+ },
4480
+ "Reload"
4481
+ ), /* @__PURE__ */ React3.createElement(
4482
+ SmallButton,
4483
+ {
4484
+ theme,
4485
+ onClick: () => {
4486
+ const input = document.createElement("input");
4487
+ input.type = "file";
4488
+ input.onchange = () => {
4489
+ const file = input.files?.[0];
4490
+ if (file) {
4491
+ const reader = new FileReader();
4492
+ reader.onload = () => {
4493
+ const buffer = reader.result;
4494
+ assetManager.create(new Uint8Array(buffer));
4495
+ };
4496
+ reader.readAsArrayBuffer(file);
4497
+ }
4498
+ };
4499
+ input.click();
4500
+ }
4501
+ },
4502
+ "Upload"
4503
+ ))
4504
+ },
4505
+ /* @__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(
4506
+ SmallButton,
4507
+ {
4508
+ theme,
4509
+ onClick: () => assetManager.delete(asset.id)
4510
+ },
4511
+ "Delete"
4512
+ ))))
4513
+ ),
4514
+ /* @__PURE__ */ React3.createElement(
4515
+ DisclosureSection,
4516
+ {
4517
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Secrets", /* @__PURE__ */ React3.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
4518
+ colorScheme,
4519
+ open: showSecrets,
4520
+ setOpen: setShowSecrets,
4521
+ right: /* @__PURE__ */ React3.createElement(
4522
+ SmallButton,
4523
+ {
4524
+ theme,
4525
+ onClick: () => {
4526
+ const name = prompt("Enter secret name");
4527
+ if (!name) return;
4528
+ const value = prompt("Enter secret value");
4529
+ if (!value) return;
4530
+ secretManager.createSecret(name, value);
4531
+ }
4532
+ },
4533
+ "Create"
4534
+ )
4535
+ },
4536
+ /* @__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(
4537
+ SmallButton,
4538
+ {
4539
+ theme,
4540
+ onClick: () => secretManager.deleteSecret(secret.name)
4541
+ },
4542
+ "Delete"
4543
+ ))))
4544
+ ),
4545
+ " ",
4546
+ /* @__PURE__ */ React3.createElement(
4547
+ DisclosureSection,
4548
+ {
4549
+ open: showInputs,
4550
+ setOpen: setShowInputs,
4551
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Inputs", /* @__PURE__ */ React3.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
4552
+ colorScheme
4553
+ },
4554
+ /* @__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(
4555
+ "div",
4556
+ {
4557
+ style: {
4558
+ padding: "12px",
4559
+ fontSize: "12px",
4560
+ display: "flex",
4561
+ flexDirection: "column",
4562
+ gap: "4px"
4563
+ }
4564
+ },
4565
+ /* @__PURE__ */ React3.createElement("span", null, "No inputs")
4566
+ ))
4567
+ ),
4568
+ /* @__PURE__ */ React3.createElement(
4569
+ DisclosureSection,
4570
+ {
4571
+ open: showOutputTransforms,
4572
+ setOpen: setShowOutputTransforms,
4573
+ title: /* @__PURE__ */ React3.createElement(TitleLabel, null, "Output Transforms", /* @__PURE__ */ React3.createElement(
4574
+ ColoredDot,
4575
+ {
4576
+ type: outputTransformsInitialized ? "success" : "error"
4577
+ }
4578
+ )),
4579
+ colorScheme
4580
+ },
4581
+ /* @__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(
4582
+ "div",
4583
+ {
4584
+ style: {
4585
+ padding: "12px",
4586
+ fontSize: "12px",
4587
+ display: "flex",
4588
+ flexDirection: "column",
4589
+ gap: "4px"
4590
+ }
4591
+ },
4592
+ /* @__PURE__ */ React3.createElement("span", null, "No output transforms")
4593
+ ))
4594
+ ),
4595
+ /* @__PURE__ */ React3.createElement(
4596
+ DisclosureSection,
4597
+ {
4598
+ title: "Tasks",
4599
+ colorScheme,
4600
+ open: showTasks,
4601
+ setOpen: setShowTasks
4602
+ },
4603
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, tasks?.map((task) => /* @__PURE__ */ React3.createElement(
4604
+ InspectorRow,
4605
+ {
4606
+ key: task.id,
4607
+ colorScheme,
4608
+ style: {
4609
+ backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
4610
+ }
4611
+ },
4612
+ /* @__PURE__ */ React3.createElement(
4613
+ ObjectInspector,
4614
+ {
4615
+ name: task.name,
4616
+ data: task.payload,
4617
+ theme
4618
+ }
4619
+ )
4620
+ )))
4621
+ ),
4622
+ /* @__PURE__ */ React3.createElement(
4623
+ DisclosureSection,
4624
+ {
4625
+ open: showEphemeral,
4626
+ setOpen: setShowEphemeral,
4627
+ title: "Ephemeral User Data",
4628
+ colorScheme
4629
+ },
4630
+ /* @__PURE__ */ React3.createElement("div", { style: styles.sectionInner }, Object.entries(ephemeral).map(([key, value]) => /* @__PURE__ */ React3.createElement(InspectorRow, { key, colorScheme }, /* @__PURE__ */ React3.createElement(
4631
+ ObjectInspector,
4632
+ {
4633
+ name: key,
4634
+ data: value,
4635
+ theme,
4636
+ expandLevel: 10
4637
+ }
4638
+ ))))
4639
+ ),
4640
+ /* @__PURE__ */ React3.createElement(
4641
+ DisclosureSection,
4642
+ {
4643
+ open: showEvents,
4644
+ setOpen: setShowEvents,
4645
+ title: "Events",
4646
+ colorScheme
4647
+ },
4648
+ /* @__PURE__ */ React3.createElement("div", { ref: eventsContainerRef, style: styles.sectionInner }, connectionEvents?.map(
4649
+ (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(
4650
+ InspectorRow,
4651
+ {
4652
+ key: index,
4653
+ colorScheme,
4654
+ variant: event.type === "send" ? "up" : "down",
4655
+ style: {
4656
+ padding: "0px 12px 1px"
4657
+ }
4658
+ },
4659
+ /* @__PURE__ */ React3.createElement(
4660
+ ObjectInspector,
4661
+ {
4662
+ data: event.type === "error" ? event.error : event.message,
4663
+ theme,
4664
+ nodeRenderer: ({
4665
+ depth,
4666
+ name,
4667
+ data,
4668
+ isNonenumerable
4669
+ }) => {
4670
+ const direction = event.type === "send" ? "up" : "down";
4671
+ return depth === 0 ? /* @__PURE__ */ React3.createElement(ObjectRootLabel, { direction, data }) : /* @__PURE__ */ React3.createElement(
4672
+ ObjectLabel,
4673
+ {
4674
+ direction,
4675
+ name,
4676
+ data,
4677
+ isNonenumerable
4678
+ }
4679
+ );
4680
+ }
4681
+ }
4682
+ )
4683
+ )
4684
+ ), !connectionEvents && /* @__PURE__ */ React3.createElement(
4685
+ "div",
4686
+ {
4687
+ style: {
4688
+ padding: "12px",
4689
+ fontSize: "12px",
4690
+ display: "flex",
4691
+ flexDirection: "column",
4692
+ gap: "4px"
4693
+ }
4694
+ },
4695
+ /* @__PURE__ */ React3.createElement("span", null, "No recorded events")
4696
+ ))
4697
+ )
4698
+ );
4699
+ });
4700
+ var ObjectRootLabel = ({ name, data, direction }) => {
4701
+ if (typeof name === "string") {
4702
+ return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(ObjectName, { name }), /* @__PURE__ */ React3.createElement("span", null, ": "), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
4816
4703
  }
4817
- };
4818
- var TypeSystemDuplicateFormat = class extends TypeBoxError {
4819
- constructor(kind) {
4820
- super(`Duplicate string format '${kind}' detected`);
4704
+ if (direction === "up" || direction === "down") {
4705
+ const arrow = direction === "up" ? "\u2191" : "\u2193";
4706
+ return /* @__PURE__ */ React3.createElement("span", null, /* @__PURE__ */ React3.createElement(
4707
+ "span",
4708
+ {
4709
+ style: {
4710
+ background: direction === "up" ? "rgba(0,255,0,0.2)" : "rgba(255,0,0,0.2)",
4711
+ // color: "white",
4712
+ width: 12,
4713
+ height: 12,
4714
+ borderRadius: 2,
4715
+ display: "inline-flex",
4716
+ justifyContent: "center",
4717
+ alignItems: "center",
4718
+ marginRight: 4,
4719
+ lineHeight: "12px"
4720
+ }
4721
+ },
4722
+ arrow
4723
+ ), /* @__PURE__ */ React3.createElement(ObjectPreview, { data }));
4724
+ } else {
4725
+ return /* @__PURE__ */ React3.createElement(ObjectPreview, { data });
4821
4726
  }
4822
4727
  };
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;
4728
+ function Arrow({
4729
+ expanded,
4730
+ onClick,
4731
+ style
4732
+ }) {
4733
+ return /* @__PURE__ */ React3.createElement(
4734
+ "span",
4735
+ {
4736
+ role: "button",
4737
+ onClick,
4738
+ style: {
4739
+ display: "inline-block",
4740
+ textAlign: "center",
4741
+ transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
4742
+ fontFamily: "Menlo, monospace",
4743
+ ...style
4744
+ }
4745
+ },
4746
+ "\u25BC"
4747
+ );
4748
+ }
4749
+ function pathToString(extendedPath) {
4750
+ return extendedPath.map(
4751
+ (key) => typeof key === "object" ? `:${ellipsis(key.id.toString(), 8, "middle")}` : key
4752
+ ).map(
4753
+ (key, index) => index === 0 || typeof key === "string" && key.startsWith(":") ? key : `.${key}`
4754
+ ).join("");
4755
+ }
4756
+ function ellipsis(str, maxLength, position = "end") {
4757
+ if (str.length <= maxLength) return str;
4758
+ switch (position) {
4759
+ case "start":
4760
+ return `\u2026${str.slice(str.length - maxLength)}`;
4761
+ case "middle":
4762
+ const halfLength = Math.floor(maxLength / 2);
4763
+ return `${str.slice(0, halfLength)}\u2026${str.slice(str.length - halfLength)}`;
4764
+ case "end":
4765
+ return `${str.slice(0, maxLength)}\u2026`;
4837
4766
  }
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]);
4767
+ }
4768
+ function SmallButton({
4769
+ children,
4770
+ onClick,
4771
+ style,
4772
+ theme,
4773
+ disabled
4774
+ }) {
4775
+ return /* @__PURE__ */ React3.createElement(
4776
+ "button",
4777
+ {
4778
+ type: "button",
4779
+ disabled,
4780
+ onClick: (event) => {
4781
+ event.stopPropagation();
4782
+ onClick();
4783
+ },
4784
+ style: {
4785
+ flex: "0",
4786
+ appearance: "none",
4787
+ background: "none",
4788
+ color: theme.BASE_COLOR,
4789
+ opacity: disabled ? 0.25 : 1,
4790
+ border: "none",
4791
+ fontSize: "12px",
4792
+ whiteSpace: "nowrap",
4793
+ display: "inline-flex",
4794
+ alignItems: "center",
4795
+ justifyContent: "center",
4796
+ padding: "0",
4797
+ cursor: "pointer",
4798
+ ...style
4799
+ }
4800
+ },
4801
+ children
4802
+ );
4803
+ }
4804
+ function ColoredDot({ type }) {
4805
+ return /* @__PURE__ */ React3.createElement(
4806
+ "span",
4807
+ {
4808
+ style: {
4809
+ display: "inline-block",
4810
+ width: 6,
4811
+ height: 6,
4812
+ background: type === "success" ? "rgba(0,200,0,0.8)" : "rgba(200,0,0,0.8)",
4813
+ borderRadius: "50%",
4814
+ verticalAlign: "middle"
4815
+ }
4816
+ }
4817
+ );
4818
+ }
4819
+ function TitleLabel({ children }) {
4820
+ return /* @__PURE__ */ React3.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
4821
+ }
4948
4822
 
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
- });
4823
+ // src/inspector/useStateInspector.tsx
4824
+ function createShadowRootElement() {
4825
+ const host = document.createElement("div");
4826
+ host.id = "noya-multiplayer-react-inspector-host";
4827
+ const shadowRoot = host.attachShadow({ mode: "open" });
4828
+ const container = document.createElement("div");
4829
+ shadowRoot.appendChild(container);
4830
+ return { host, container };
4831
+ }
4832
+ function useStateInspector({
4833
+ noyaManager,
4834
+ disabled = false,
4835
+ colorScheme,
4836
+ anchor
4837
+ }) {
4838
+ const [root, setRoot] = React4.useState(null);
4839
+ useLayoutEffect2(() => {
4840
+ if (disabled) return;
4841
+ const { host, container } = createShadowRootElement();
4842
+ const root2 = createRoot(container);
4843
+ document.body.appendChild(host);
4844
+ setRoot(root2);
4845
+ return () => {
4846
+ document.body.removeChild(host);
4847
+ };
4848
+ }, [disabled]);
4849
+ useLayoutEffect2(() => {
4850
+ if (!root) return;
4851
+ root.render(
4852
+ /* @__PURE__ */ React4.createElement(
4853
+ StateInspector,
4854
+ {
4855
+ colorScheme,
4856
+ anchor,
4857
+ noyaManager
4858
+ }
4859
+ )
4860
+ );
4861
+ }, [noyaManager, anchor, colorScheme, root]);
4970
4862
  }
4971
4863
 
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
4864
+ // src/hooks.ts
4865
+ function useSyncStateManager(stateManager, path) {
4866
+ const getSnapshot = useCallback(
4867
+ () => typeof path === "string" ? stateManager.getState(path) : stateManager.getState(),
4868
+ [stateManager, path]
4869
+ );
4870
+ return useSyncExternalStore2(
4871
+ stateManager.addListener,
4872
+ getSnapshot,
4873
+ getSnapshot
4976
4874
  );
4977
4875
  }
4978
- format_exports.Set("color", () => true);
4979
- format_exports.Set("uuid", validateUUID);
4876
+ function useManagedState(createInitialState, options) {
4877
+ const [stateManager] = useState(
4878
+ () => new StateManager(createInitialState(), options)
4879
+ );
4880
+ const state = useSyncStateManager(stateManager);
4881
+ const setState = useCallback(
4882
+ (...args) => {
4883
+ const [metadata, action] = args.length === 1 ? [void 0, args[0]] : args;
4884
+ if (metadata === void 0) {
4885
+ const performActionNoMetadata = stateManager.performAction;
4886
+ if (action instanceof Function) {
4887
+ performActionNoMetadata({
4888
+ run: action,
4889
+ undo: () => state
4890
+ });
4891
+ } else {
4892
+ performActionNoMetadata({
4893
+ run: () => action,
4894
+ undo: () => state
4895
+ });
4896
+ }
4897
+ } else {
4898
+ const performActionWithMetadata = stateManager.performAction;
4899
+ if (action instanceof Function) {
4900
+ performActionWithMetadata(metadata, {
4901
+ run: action,
4902
+ undo: () => state
4903
+ });
4904
+ } else {
4905
+ performActionWithMetadata(metadata, {
4906
+ run: () => action,
4907
+ undo: () => state
4908
+ });
4909
+ }
4910
+ }
4911
+ },
4912
+ [state, stateManager]
4913
+ );
4914
+ return [state, setState, stateManager];
4915
+ }
4916
+ function useManagedHistory(stateManager) {
4917
+ return useSyncExternalStore2(
4918
+ stateManager.historyEmittor.addListener,
4919
+ stateManager.getHistorySnapshot,
4920
+ stateManager.getHistorySnapshot
4921
+ );
4922
+ }
4923
+ var defaultStubSync = stubSync();
4924
+ function useMultiplayerState(initialState, options) {
4925
+ const {
4926
+ sync = defaultStubSync,
4927
+ inspector,
4928
+ ...rest
4929
+ } = options ?? {};
4930
+ const [noyaManager] = useState(
4931
+ () => new NoyaManager(initialState, rest)
4932
+ );
4933
+ const state = useObservable(
4934
+ noyaManager.multiplayerStateManager.optimisticState$
4935
+ );
4936
+ const assets = useObservable(noyaManager.assetManager.assets$);
4937
+ const extras = useMemo2(() => {
4938
+ return {
4939
+ noyaManager,
4940
+ taskManager: noyaManager.taskManager,
4941
+ connectionEventManager: noyaManager.connectionEventManager,
4942
+ connectedUsersManager: noyaManager.connectedUsersManager,
4943
+ ephemeralUserDataManager: noyaManager.ephemeralUserDataManager,
4944
+ multiplayerStateManager: noyaManager.multiplayerStateManager,
4945
+ assetManager: noyaManager.assetManager,
4946
+ aiManager: noyaManager.aiManager,
4947
+ rpcManager: noyaManager.rpcManager,
4948
+ pipelineManager: noyaManager.pipelineManager,
4949
+ secretManager: noyaManager.secretManager,
4950
+ menuItemsManager: noyaManager.menuManager,
4951
+ createAsset: noyaManager.assetManager.create,
4952
+ deleteAsset: noyaManager.assetManager.delete,
4953
+ assets
4954
+ };
4955
+ }, [noyaManager, assets]);
4956
+ const syncRef = useRef(sync);
4957
+ useEffect2(() => {
4958
+ if (syncRef.current) {
4959
+ return syncRef.current({ noyaManager });
4960
+ }
4961
+ }, [noyaManager]);
4962
+ useErrorOverlay(noyaManager);
4963
+ useStateInspector({
4964
+ noyaManager,
4965
+ disabled: !inspector,
4966
+ ...typeof inspector === "object" && inspector
4967
+ });
4968
+ return [state, noyaManager.multiplayerStateManager.setState, extras];
4969
+ }
4970
+ function useErrorOverlay(noyaManager) {
4971
+ const unrecoverableError = useObservable(noyaManager.unrecoverableError);
4972
+ useEffect2(() => {
4973
+ if (!unrecoverableError) return;
4974
+ const el = document.createElement("div");
4975
+ el.id = "noya-multiplayer-react-error-overlay";
4976
+ document.body.appendChild(el);
4977
+ const root = createRoot2(el);
4978
+ root.render(createElement2(ErrorOverlay, { error: unrecoverableError }));
4979
+ return () => {
4980
+ root.unmount();
4981
+ el.remove();
4982
+ };
4983
+ });
4984
+ }
4980
4985
 
4981
4986
  // 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
4987
  function createDefaultAppData(initialState) {
4993
4988
  return {
4994
4989
  theme: "light",
@@ -5037,7 +5032,7 @@ function useNoyaState(...args) {
5037
5032
  theme,
5038
5033
  viewType
5039
5034
  }
5040
- ] = useState3(() => {
5035
+ ] = useState2(() => {
5041
5036
  return getAppData(initialState, options?.schema, {
5042
5037
  overrideExistingState: options?.overrideExistingState
5043
5038
  });
@@ -5061,16 +5056,6 @@ function useNoyaState(...args) {
5061
5056
  }
5062
5057
 
5063
5058
  // 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
5059
  var AnyNoyaStateContext = createContext(void 0);
5075
5060
  function useAnyNoyaStateContext() {
5076
5061
  const value = useContext(AnyNoyaStateContext);
@@ -5219,17 +5204,17 @@ function createNoyaContext({
5219
5204
  }),
5220
5205
  [noyaManager, theme, viewType]
5221
5206
  );
5222
- return /* @__PURE__ */ React6.createElement(AnyNoyaStateContext.Provider, { value: contextValue }, /* @__PURE__ */ React6.createElement(
5207
+ return /* @__PURE__ */ React5.createElement(AnyNoyaStateContext.Provider, { value: contextValue }, /* @__PURE__ */ React5.createElement(
5223
5208
  ConnectedUsersContext.Provider,
5224
5209
  {
5225
5210
  value: noyaManager.connectedUsersManager
5226
5211
  },
5227
- /* @__PURE__ */ React6.createElement(
5212
+ /* @__PURE__ */ React5.createElement(
5228
5213
  EphemeralUserDataManagerContext.Provider,
5229
5214
  {
5230
5215
  value: noyaManager.ephemeralUserDataManager
5231
5216
  },
5232
- options.fallback !== void 0 ? /* @__PURE__ */ React6.createElement(FallbackUntilInitialized, { fallback: options.fallback }, children) : children
5217
+ options.fallback !== void 0 ? /* @__PURE__ */ React5.createElement(FallbackUntilInitialized, { fallback: options.fallback }, children) : children
5233
5218
  )
5234
5219
  ));
5235
5220
  }
@@ -5290,7 +5275,7 @@ function createNoyaContext({
5290
5275
  }
5291
5276
  function useSetLeftMenuItems(leftMenuItems) {
5292
5277
  const { menuManager } = useNoyaManager();
5293
- useEffect4(() => {
5278
+ useEffect3(() => {
5294
5279
  if (leftMenuItems) {
5295
5280
  menuManager.setLeftMenuItems(leftMenuItems);
5296
5281
  }
@@ -5302,7 +5287,7 @@ function createNoyaContext({
5302
5287
  }
5303
5288
  function useSetRightMenuItems(rightMenuItems) {
5304
5289
  const { menuManager } = useNoyaManager();
5305
- useEffect4(() => {
5290
+ useEffect3(() => {
5306
5291
  if (rightMenuItems) {
5307
5292
  menuManager.setRightMenuItems(rightMenuItems);
5308
5293
  }
@@ -5310,7 +5295,7 @@ function createNoyaContext({
5310
5295
  }
5311
5296
  function useHandleMenuItem(callback) {
5312
5297
  const { menuManager } = useNoyaManager();
5313
- useEffect4(() => {
5298
+ useEffect3(() => {
5314
5299
  return menuManager.addListener(callback);
5315
5300
  }, [menuManager, callback]);
5316
5301
  }
@@ -5345,6 +5330,75 @@ function createNoyaContext({
5345
5330
  };
5346
5331
  }
5347
5332
 
5333
+ // src/ai.ts
5334
+ function useRegisterAITool(tool) {
5335
+ const aiManager = useAIManager();
5336
+ useEffect4(() => {
5337
+ return aiManager.registerTool(tool);
5338
+ }, [aiManager, tool]);
5339
+ }
5340
+ function useCallableAITools() {
5341
+ const aiManager = useAIManager();
5342
+ return useObservable(aiManager.callableTools$);
5343
+ }
5344
+
5345
+ // src/components/UserPointersOverlay.tsx
5346
+ import { memoGeneric as memoGeneric2 } from "@noya-app/react-utils";
5347
+ import React6, { useEffect as useEffect5, useState as useState3 } from "react";
5348
+ function shouldShow(hideAfter, updatedAt) {
5349
+ return !!updatedAt && Date.now() - updatedAt < hideAfter;
5350
+ }
5351
+ var UserPointerInternal = memoGeneric2(function UserPointerInternal2({
5352
+ user,
5353
+ ephemeralUserDataManager,
5354
+ hideAfter = 5e3,
5355
+ renderUserPointer
5356
+ }) {
5357
+ const metadata = useObservable(ephemeralUserDataManager.metadata$, [
5358
+ user.id
5359
+ ]);
5360
+ const data = useObservable(ephemeralUserDataManager.data$, [
5361
+ user.id
5362
+ ]);
5363
+ const [, setForceUpdate] = useState3(0);
5364
+ const updatedAt = metadata?.updatedAt ?? 0;
5365
+ const show = shouldShow(hideAfter, updatedAt);
5366
+ useEffect5(() => {
5367
+ if (!show) return;
5368
+ const timeoutId = setTimeout(() => {
5369
+ setForceUpdate((prev) => prev + 1);
5370
+ }, hideAfter);
5371
+ return () => clearTimeout(timeoutId);
5372
+ }, [hideAfter, show, updatedAt]);
5373
+ if (!data?.pointer) return null;
5374
+ return renderUserPointer({
5375
+ userId: user.id,
5376
+ name: user.name,
5377
+ point: data.pointer,
5378
+ visible: show
5379
+ });
5380
+ });
5381
+ var UserPointersOverlay = memoGeneric2(function UserPointers({
5382
+ connectedUsersManager,
5383
+ ephemeralUserDataManager,
5384
+ renderUserPointer
5385
+ }) {
5386
+ const currentUserId = useObservable(ephemeralUserDataManager.currentUserId$);
5387
+ const connectedUsers = useObservable(connectedUsersManager.connectedUsers$);
5388
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, connectedUsers.map((user) => {
5389
+ if (user.id === currentUserId) return null;
5390
+ return /* @__PURE__ */ React6.createElement(
5391
+ UserPointerInternal,
5392
+ {
5393
+ key: user.id,
5394
+ user,
5395
+ ephemeralUserDataManager,
5396
+ renderUserPointer
5397
+ }
5398
+ );
5399
+ }));
5400
+ });
5401
+
5348
5402
  // src/WebSocketConnection.ts
5349
5403
  import {
5350
5404
  ReconnectingWebSocket,
@@ -5427,6 +5481,7 @@ var WebSocketConnection = class {
5427
5481
  };
5428
5482
  export {
5429
5483
  AnyEphemeralUserDataManagerContext,
5484
+ AnyNoyaStateContext,
5430
5485
  ConnectedUsersContext,
5431
5486
  FallbackUntilInitialized,
5432
5487
  StateInspector,
@@ -5444,6 +5499,7 @@ export {
5444
5499
  useAsset,
5445
5500
  useAssetManager,
5446
5501
  useAssets,
5502
+ useCallableAITools,
5447
5503
  useColorScheme,
5448
5504
  useConnectedUsersManager,
5449
5505
  useCurrentUserId,
@@ -5457,6 +5513,7 @@ export {
5457
5513
  useObservable,
5458
5514
  useOutputTransforms,
5459
5515
  usePipelineManager,
5516
+ useRegisterAITool,
5460
5517
  useSecret,
5461
5518
  useSecretManager,
5462
5519
  useSecrets,