@noya-app/noya-multiplayer-react 0.1.31 → 0.1.33

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.d.mts CHANGED
@@ -106,9 +106,10 @@ type GetAppDataOptions = {
106
106
  hash: string;
107
107
  };
108
108
  };
109
+ overrideExistingState?: boolean;
109
110
  };
110
111
  declare function enforceSchema<State>(initialState: State, schema?: TSchema): State;
111
- declare function parseAppDataParameter(options?: GetAppDataOptions): any;
112
+ declare function parseAppDataParameter(options?: GetAppDataOptions): AppData<unknown> | null;
112
113
  declare function getAppData<State>(initialState: State | (() => State), schema?: TSchema, options?: GetAppDataOptions): AppData<State>;
113
114
  type IframeToHostMessage = {
114
115
  type: "application.setMenuItems";
package/dist/index.d.ts CHANGED
@@ -106,9 +106,10 @@ type GetAppDataOptions = {
106
106
  hash: string;
107
107
  };
108
108
  };
109
+ overrideExistingState?: boolean;
109
110
  };
110
111
  declare function enforceSchema<State>(initialState: State, schema?: TSchema): State;
111
- declare function parseAppDataParameter(options?: GetAppDataOptions): any;
112
+ declare function parseAppDataParameter(options?: GetAppDataOptions): AppData<unknown> | null;
112
113
  declare function getAppData<State>(initialState: State | (() => State), schema?: TSchema, options?: GetAppDataOptions): AppData<State>;
113
114
  type IframeToHostMessage = {
114
115
  type: "application.setMenuItems";
package/dist/index.js CHANGED
@@ -1454,15 +1454,12 @@ function parseAppDataParameter(options) {
1454
1454
  }
1455
1455
  function getAppData(initialState, schema, options) {
1456
1456
  const resolvedInitialState = initialState instanceof Function ? initialState() : initialState;
1457
- try {
1458
- const appData = parseAppDataParameter(options) ?? createDefaultAppData(resolvedInitialState);
1459
- return {
1460
- ...appData,
1461
- initialState: enforceSchema(appData.initialState, schema)
1462
- };
1463
- } catch (e) {
1464
- return createDefaultAppData(enforceSchema(resolvedInitialState, schema));
1457
+ let appData = parseAppDataParameter(options) ?? createDefaultAppData(resolvedInitialState);
1458
+ if (options?.overrideExistingState) {
1459
+ appData.initialState = resolvedInitialState;
1465
1460
  }
1461
+ appData.initialState = enforceSchema(appData.initialState, schema);
1462
+ return appData;
1466
1463
  }
1467
1464
  function useBroadcastConnectedUsers(connectedUsers) {
1468
1465
  (0, import_react8.useEffect)(() => {
@@ -1508,7 +1505,9 @@ function useNoyaAppState(initialState, options) {
1508
1505
  viewType
1509
1506
  }
1510
1507
  ] = (0, import_react8.useState)(() => {
1511
- return getAppData(initialState, options?.schema);
1508
+ return getAppData(initialState, options?.schema, {
1509
+ overrideExistingState: options?.overrideExistingState
1510
+ });
1512
1511
  });
1513
1512
  const sync = (0, import_react8.useMemo)(() => {
1514
1513
  return multiplayerUrl ? (0, import_state_manager2.webSocketSync)(multiplayerUrl) : options?.localStorageKey ? (0, import_state_manager2.localStorageSync)({ key: options.localStorageKey }) : (0, import_state_manager2.stubSync)();
@@ -1516,7 +1515,7 @@ function useNoyaAppState(initialState, options) {
1516
1515
  const result = useMultiplayerState(noyaAppInitialState, {
1517
1516
  ...options,
1518
1517
  inspector: options?.inspector ?? inspector,
1519
- sync
1518
+ sync: options?.sync ?? sync
1520
1519
  });
1521
1520
  const [, , extras] = result;
1522
1521
  useBroadcastConnectedUsers(extras.connectedUsers);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/avatarStyle.ts","../src/components/UserPointersOverlay.tsx","../src/useObservable.ts","../src/hooks.ts","../src/components/ErrorOverlay.tsx","../src/globals.ts","../src/inspector/useStateInspector.tsx","../src/inspector/StateInspector.tsx","../src/inspector/useLocalStorageState.tsx","../src/noyaApp.ts"],"sourcesContent":["export * from \"@noya-app/state-manager\";\nexport * from \"./avatarStyle\";\nexport * from \"./components/UserPointersOverlay\";\nexport * from \"./hooks\";\nexport * from \"./inspector/StateInspector\";\nexport * from \"./noyaApp\";\nexport * from \"./useObservable\";\n","function hashCode(string: string) {\n let hash = 0;\n\n for (const char of string) {\n hash = char.charCodeAt(0) + ((hash << 5) - hash);\n }\n\n return hash;\n}\n\nfunction elementFromHash<T>(array: T[], hash: number): T {\n return array[Math.abs(hash) % array.length];\n}\n\nexport function getAvatarInitials(name: string) {\n return name\n .split(\" \")\n .filter((c) => c.length > 0)\n .map((c) => c[0])\n .join(\"\")\n .toLocaleUpperCase();\n}\n\n/**\n * Create a background color and initials from a name\n *\n * Adapted from https://mui.com/material-ui/react-avatar/\n */\nexport function getAvatarStyle(name: string) {\n const hash = hashCode(name);\n const color = elementFromHash(Object.values(colors500), hash);\n // const darkerColor = elementFromHash(Object.values(colors800), hash);\n\n return {\n color: \"white\",\n backgroundColor: color,\n // primaryColors: {\n // \"500\": color,\n // \"800\": darkerColor,\n // },\n };\n}\n\nconst colors500 = {\n red500: \"#ef4444\",\n orange500: \"#f97316\",\n amber500: \"#f59e0b\",\n yellow500: \"#eab308\",\n lime500: \"#84cc16\",\n green500: \"#22c55e\",\n emerald500: \"#10b981\",\n teal500: \"#14b8a6\",\n cyan500: \"#06b6d4\",\n sky500: \"#0ea5e9\",\n blue500: \"#3b82f6\",\n indigo500: \"#6366f1\",\n violet500: \"#8b5cf6\",\n purple500: \"#a855f7\",\n fuchsia500: \"#d946ef\",\n pink500: \"#ec4899\",\n rose500: \"#f43f5e\",\n};\n\n// const colors800 = {\n// red800: \"#991b1b\",\n// orange800: \"#9a3412\",\n// amber800: \"#92400e\",\n// yellow800: \"#854d0e\",\n// lime800: \"#3f6212\",\n// green800: \"#166534\",\n// emerald800: \"#065f46\",\n// teal800: \"#115e59\",\n// cyan800: \"#155e75\",\n// sky800: \"#075985\",\n// blue800: \"#1e40af\",\n// indigo800: \"#3730a3\",\n// violet800: \"#5b21b6\",\n// purple800: \"#6b21a8\",\n// fuchsia800: \"#86198f\",\n// pink800: \"#9d174d\",\n// rose800: \"#9f1239\",\n// };\n","\"use client\";\n\nimport { EphemeralUserData, MultiplayerUser } from \"@noya-app/state-manager\";\nimport React, { memo, useEffect, useMemo, useState } from \"react\";\nimport { getAvatarStyle } from \"../avatarStyle\";\nimport { useObservable } from \"../useObservable\";\n\ntype Point = { x: number; y: number };\n\nexport type UserPointerData = { pointer?: Point };\n\nexport type UserPointerProps<E extends UserPointerData> = {\n user: MultiplayerUser;\n ephemeralUserData: EphemeralUserData<E>;\n hideAfter?: number;\n};\n\nfunction shouldShow(hideAfter: number, updatedAt: number) {\n return !!updatedAt && Date.now() - updatedAt < hideAfter;\n}\n\nconst UserPointer_ = function UserPointer<E extends UserPointerData>({\n user,\n ephemeralUserData,\n hideAfter = 5000,\n}: UserPointerProps<E>) {\n const metadata = useObservable(ephemeralUserData.metadata$, [\n user.id,\n ] as const);\n const data = useObservable(ephemeralUserData.data$, [user.id] as const);\n const avatarStyle = useMemo(() => getAvatarStyle(user.id), [user.id]);\n\n const [, setForceUpdate] = useState(0);\n\n const updatedAt = metadata?.updatedAt ?? 0;\n\n useEffect(() => {\n if (!shouldShow(hideAfter, updatedAt)) return;\n\n const timeoutId = setTimeout(() => {\n setForceUpdate((prev) => prev + 1);\n }, hideAfter);\n\n return () => clearTimeout(timeoutId);\n }, [hideAfter, updatedAt]);\n\n const show = shouldShow(hideAfter, updatedAt);\n\n if (!data || !data.pointer) return null;\n\n return (\n <UserPointerContainer key={user.id} point={data.pointer} show={show}>\n <UserPointerIcon color={avatarStyle.backgroundColor} />\n <UserNameTag background={avatarStyle.backgroundColor}>\n {user.name}\n </UserNameTag>\n </UserPointerContainer>\n );\n};\n\nexport const UserPointer = memo(UserPointer_) as typeof UserPointer_;\n\nexport const UserPointerContainer = memo(function UserPointerContainer({\n point,\n children,\n show = true,\n}: {\n point: Point;\n children: React.ReactNode;\n show?: boolean;\n}) {\n return (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n transform: `translate(${Math.round(point.x)}px, ${Math.round(\n point.y\n )}px)`,\n opacity: show ? 1 : 0,\n transition: \"transform 0.1s, opacity 0.2s\",\n }}\n >\n {children}\n </div>\n );\n});\n\nexport const UserNameTag = memo(function UserNameTag({\n background,\n children,\n}: {\n background: string;\n children: React.ReactNode;\n}) {\n return (\n <span\n style={{\n position: \"relative\",\n top: \"8px\",\n left: \"15px\",\n fontSize: 11,\n lineHeight: \"1\",\n fontWeight: 500,\n boxShadow: \"0 1px 1px rgba(0,0,0,0.1)\",\n padding: \"2px 4px 3px\",\n pointerEvents: \"none\",\n letterSpacing: \"-0.3px\",\n outline: `1px solid rgba(255,255,255,0.3)`,\n outlineOffset: \"-1px\",\n background,\n color: \"white\",\n }}\n >\n {children}\n </span>\n );\n});\n\nexport type UserPointersOverlayProps<E extends UserPointerData> = {\n connectedUsers: MultiplayerUser[];\n ephemeralUserData: EphemeralUserData<E>;\n};\n\nexport const UserPointersOverlay = memo(function UserPointers<\n E extends UserPointerData,\n>({ connectedUsers, ephemeralUserData }: UserPointersOverlayProps<E>) {\n const currentUserId = useObservable(ephemeralUserData.currentUserId$);\n\n return (\n <>\n {connectedUsers.map((user) => {\n if (user.id === currentUserId) return null;\n\n return (\n <UserPointer\n key={user.id}\n user={user}\n ephemeralUserData={\n ephemeralUserData as unknown as EphemeralUserData<E>\n }\n />\n );\n })}\n </>\n );\n});\n\nexport const UserPointerIcon = memo(function CursorIcon({\n color = \"black\",\n}: {\n color?: string;\n}) {\n return (\n <svg\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n position: \"absolute\",\n filter: \"drop-shadow(0 1px 1px rgba(0,0,0,0.1))\",\n // filter: \"drop-shadow(0 1px 1px rgba(0,0,0,0.6))\",\n }}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M3.29227 0.0451998C3.47033 -0.0361222 3.67946 -0.00606629 3.8274 0.122107L12.8587 7.94648C13.0134 8.08054 13.0708 8.29538 13.0035 8.48873C12.9362 8.68208 12.7578 8.81488 12.5533 8.8239L9.21887 8.97096L11.1504 13.2149C11.2648 13.4662 11.1538 13.7626 10.9026 13.877L8.75024 14.8575C8.499 14.972 8.20255 14.8611 8.08802 14.6099L6.15339 10.3665L3.86279 12.7817C3.72196 12.9302 3.50487 12.9779 3.31479 12.9021C3.1247 12.8263 3 12.6423 3 12.4376V0.500008C3 0.304264 3.11422 0.126522 3.29227 0.0451998Z\"\n fill={color}\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M3.29227 0.048984C3.47033 -0.032338 3.67946 -0.00228211 3.8274 0.125891L12.8587 7.95026C13.0134 8.08432 13.0708 8.29916 13.0035 8.49251C12.9362 8.68586 12.7578 8.81866 12.5533 8.82768L9.21887 8.97474L11.1504 13.2187C11.2648 13.47 11.1538 13.7664 10.9026 13.8808L8.75024 14.8613C8.499 14.9758 8.20255 14.8649 8.08802 14.6137L6.15339 10.3703L3.86279 12.7855C3.72196 12.934 3.50487 12.9817 3.31479 12.9059C3.1247 12.8301 3 12.6461 3 12.4414V0.503792C3 0.308048 3.11422 0.130306 3.29227 0.048984ZM4 1.59852V11.1877L5.93799 9.14425C6.05238 9.02363 6.21924 8.96776 6.38319 8.99516C6.54715 9.02256 6.68677 9.12965 6.75573 9.2809L8.79056 13.7441L10.0332 13.178L8.00195 8.71497C7.93313 8.56376 7.94391 8.38824 8.03072 8.24659C8.11753 8.10494 8.26903 8.01566 8.435 8.00834L11.2549 7.88397L4 1.59852Z\"\n fill=\"rgba(255,255,255,0.5)\"\n />\n </svg>\n );\n});\n","import { GetWithPath, Observable, PathKey } from \"@noya-app/observable\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nexport function useObservable<T>(observable: Observable<T>): T;\nexport function useObservable<T, P extends PathKey[]>(\n observable: Observable<T>,\n path: P\n): GetWithPath<T, P>;\nexport function useObservable<T, P extends PathKey[]>(\n observable: Observable<T>,\n path?: P\n) {\n const { get, listen } = useMemo(() => {\n const listen = path\n ? (callback: (value: GetWithPath<T, P>) => void) =>\n observable.listen(path, callback)\n : observable.listen;\n\n const get: () => void = path ? () => observable.get(path) : observable.get;\n\n return { get, listen };\n }, [observable, path]);\n\n return useSyncExternalStore(listen, get, get);\n}\n","\"use client\";\n\nimport {\n ActionHandler,\n ConnectionEvent,\n EphemeralUserData,\n Get,\n MultiplayerStateManager,\n MultiplayerStateManagerError,\n MultiplayerStateManagerOptions,\n MultiplayerUser,\n StateManager,\n StateManagerOptions,\n stubSync,\n SyncAdapter,\n SyncAdapterOptions,\n Task,\n} from \"@noya-app/state-manager\";\nimport {\n createElement,\n SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { ErrorOverlay } from \"./components/ErrorOverlay\";\nimport { shouldTrackEvents$, shouldTrackTasks$ } from \"./globals\";\nimport { StateInspectorOptions } from \"./inspector/StateInspector\";\nimport { useStateInspector } from \"./inspector/useStateInspector\";\nimport { useObservable } from \"./useObservable\";\n\nexport function useSyncStateManager<S, M>(stateManager: StateManager<S, M>): S;\nexport function useSyncStateManager<S, M, P extends string>(\n stateManager: StateManager<S, M>,\n path: P\n): Get<S, P, unknown>;\nexport function useSyncStateManager<S, M>(\n stateManager: StateManager<S, M>,\n path?: string\n) {\n const getSnapshot = useCallback(\n () =>\n typeof path === \"string\"\n ? stateManager.getState(path)\n : stateManager.getState(),\n [stateManager, path]\n );\n\n return useSyncExternalStore(\n stateManager.addListener,\n getSnapshot,\n getSnapshot\n );\n}\n\nexport function useManagedState<S, M = void>(\n createInitialState: () => S,\n options?: StateManagerOptions<S, M>\n) {\n const [stateManager] = useState(\n () => new StateManager<S, M>(createInitialState(), options)\n );\n\n const state = useSyncStateManager(stateManager);\n\n const setState = useCallback(\n (\n ...args: M extends {}\n ? [metadata: M, action: SetStateAction<S>]\n : [action: SetStateAction<S>]\n ) => {\n const [metadata, action] =\n args.length === 1 ? [undefined, args[0]] : args;\n\n if (metadata === undefined) {\n const performActionNoMetadata = stateManager.performAction as (\n handler: ActionHandler<S>\n ) => void;\n\n if (action instanceof Function) {\n performActionNoMetadata({\n run: action,\n undo: () => state,\n });\n } else {\n performActionNoMetadata({\n run: () => action,\n undo: () => state,\n });\n }\n } else {\n const performActionWithMetadata = stateManager.performAction as (\n metadata: M,\n handler: ActionHandler<S>\n ) => void;\n\n if (action instanceof Function) {\n performActionWithMetadata(metadata, {\n run: action,\n undo: () => state,\n });\n } else {\n performActionWithMetadata(metadata, {\n run: () => action,\n undo: () => state,\n });\n }\n }\n },\n [state, stateManager]\n );\n\n return [state, setState, stateManager] as const;\n}\n\nexport function useManagedHistory<S, M = void>(\n stateManager: StateManager<S, M>\n) {\n return useSyncExternalStore(\n stateManager.historyEmittor.addListener,\n stateManager.getHistorySnapshot,\n stateManager.getHistorySnapshot\n );\n}\n\nexport function useSyncMultiplayerStateManager<S, M = void>(\n multiplayerStateManager: MultiplayerStateManager<S, M>\n) {\n return useSyncExternalStore(\n multiplayerStateManager.addListener,\n multiplayerStateManager.getOptimisticState,\n multiplayerStateManager.getOptimisticState\n );\n}\n\nfunction throttle<F extends (...args: any[]) => any>(fn: F, ms: number) {\n let lastCall = 0;\n let timeoutId: number | null = null;\n return (...args: Parameters<F>) => {\n const now = Date.now();\n if (now - lastCall < ms) {\n if (timeoutId) clearTimeout(timeoutId);\n timeoutId = setTimeout(\n () => {\n lastCall = now;\n fn(...args);\n },\n ms - (now - lastCall)\n ) as unknown as number;\n return;\n }\n lastCall = now;\n return fn(...args);\n };\n}\n\nexport function useEphemeralUserData<E>(\n ephemeralUserData: EphemeralUserData<E>,\n options?: {\n throttle?: number;\n }\n) {\n const throttledAddListener = useMemo(() => {\n const throttleMs = options?.throttle ?? 0;\n\n if (throttleMs > 0) {\n const addListener = (\n fn: Parameters<typeof ephemeralUserData.addListener>[0]\n ) => {\n const throttledFn = throttle(fn, throttleMs);\n return ephemeralUserData.addListener(throttledFn);\n };\n\n return addListener;\n }\n\n return ephemeralUserData.addListener;\n }, [ephemeralUserData, options?.throttle]);\n\n return useSyncExternalStore(\n throttledAddListener,\n ephemeralUserData.getSnapshot,\n ephemeralUserData.getSnapshot\n );\n}\n\nconst defaultStubSync = stubSync();\n\nexport type UseMultiplayerStateOptions<\n S,\n M = void,\n E = void,\n> = MultiplayerStateManagerOptions<S, M> & {\n sync?: (\n options: Pick<SyncAdapterOptions<S, M, E>, \"ms\" | \"ephemeralUserData\">\n ) => void;\n trackConnectionEvents?: boolean;\n trackTasks?: boolean;\n inspector?: boolean | StateInspectorOptions;\n};\n\nexport function useMultiplayerState<S, M = void, E = void>(\n initialState: S | (() => S),\n options?: UseMultiplayerStateOptions<S, M, E>\n) {\n const { sync = defaultStubSync as unknown as SyncAdapter<S, M, E>, ...rest } =\n options ?? {};\n\n const [multiplayerStateManager] = useState(\n () => new MultiplayerStateManager<S, M>(initialState, rest)\n );\n const syncRef = useRef(sync);\n\n const [connectionEvents, setConnectionEvents] = useState<\n ConnectionEvent<S>[] | undefined\n >();\n\n const [connectedUsers, setConnectedUsers] = useState<MultiplayerUser[]>([]);\n const [ephemeralUserData] = useState<EphemeralUserData<E>>(\n () => new EphemeralUserData()\n );\n const [tasks, setTasks] = useState<Task[]>([]);\n const [userId, setUserId] = useState<string | undefined>();\n\n const extras = useMemo(() => {\n return {\n tasks,\n userId,\n connectionEvents,\n connectedUsers,\n ephemeralUserData,\n multiplayerStateManager,\n // evaluate: async (code: string) => {\n // const payload = await rpcManager.request({ type: \"eval\", code });\n\n // if (payload.type !== \"eval\") {\n // throw new Error(`Unexpected rpc response type: ${payload.type}`);\n // }\n // },\n };\n }, [\n tasks,\n userId,\n connectionEvents,\n connectedUsers,\n ephemeralUserData,\n multiplayerStateManager,\n ]);\n\n const globalTrackEvents = useObservable(shouldTrackEvents$);\n const globalTrackTasks = useObservable(shouldTrackTasks$);\n\n const shouldTrackEvents = options?.trackConnectionEvents ?? globalTrackEvents;\n const shouldTrackTasks = options?.trackTasks ?? globalTrackTasks;\n\n const trackEventsCallbackRef = useRef<\n ((e: ConnectionEvent<S>) => void) | undefined\n >();\n const trackConnectedUsersCallbackRef = useRef<\n ((users: MultiplayerUser[], userId: string) => void) | undefined\n >();\n const trackTasksCallbackRef = useRef<((tasks: Task[]) => void) | undefined>();\n\n useEffect(() => {\n trackEventsCallbackRef.current = shouldTrackEvents\n ? (e) =>\n setConnectionEvents((events) => {\n const updated = events ? [...events, e] : [e];\n return updated.length > 50 ? updated.slice(-50) : updated;\n })\n : undefined;\n }, [shouldTrackEvents]);\n\n useEffect(() => {\n trackConnectedUsersCallbackRef.current = (users, userId) => {\n setConnectedUsers(users);\n setUserId(userId);\n };\n }, []);\n\n useEffect(() => {\n trackTasksCallbackRef.current = shouldTrackTasks\n ? (tasks) => {\n setTasks((old) => {\n const newIds = new Set(tasks.map((t) => t.id));\n\n // merge old and new tasks, preferring new tasks\n const unchanged = old.filter((t) => !newIds.has(t.id));\n\n return [...unchanged, ...tasks];\n });\n }\n : undefined;\n }, [shouldTrackTasks]);\n\n useEffect(() => {\n if (syncRef.current) {\n return syncRef.current({\n ms: multiplayerStateManager,\n ephemeralUserData,\n onConnectionEvent: (e) => trackEventsCallbackRef.current?.(e),\n onChangeConnectedUsers: (users, userId) =>\n trackConnectedUsersCallbackRef.current?.(users, userId),\n onChangeTasks: (tasks) => trackTasksCallbackRef.current?.(tasks),\n });\n }\n }, [ephemeralUserData, multiplayerStateManager]);\n\n const state = useSyncMultiplayerStateManager(multiplayerStateManager);\n\n const forceInit = useCallback(() => {\n const state =\n initialState instanceof Function ? initialState() : initialState;\n const schema = options?.schema;\n multiplayerStateManager.sm.clearHistory();\n multiplayerStateManager.sendInit({ force: true, state, schema });\n }, [initialState, multiplayerStateManager, options?.schema]);\n\n const [unrecoverableError, setUnrecoverableError] = useState<\n MultiplayerStateManagerError | undefined\n >();\n\n useEffect(() => {\n return multiplayerStateManager.errorEmitter.addListener((error) => {\n setUnrecoverableError(error);\n });\n }, [multiplayerStateManager]);\n\n useEffect(() => {\n if (!unrecoverableError) return;\n const el = document.createElement(\"div\");\n el.id = \"noya-multiplayer-react-error-overlay\";\n document.body.appendChild(el);\n const root = createRoot(el);\n root.render(createElement(ErrorOverlay, { error: unrecoverableError }));\n return () => {\n root.unmount();\n el.remove();\n };\n });\n\n useStateInspector({\n ephemeralUserData,\n multiplayerStateManager,\n state,\n connectionEvents,\n connectedUsers,\n tasks,\n userId,\n forceInit,\n disabled: !options?.inspector,\n ...(typeof options?.inspector === \"object\" && options.inspector),\n });\n\n return [state, multiplayerStateManager.setState, extras] as const;\n}\n","import { MultiplayerStateManagerError } from \"@noya-app/state-manager\";\nimport React from \"react\";\n\nexport function ErrorOverlay({\n error,\n}: {\n error: MultiplayerStateManagerError;\n}) {\n return (\n <div\n style={{\n position: \"fixed\",\n top: \"20px\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n maxWidth: \"80%\",\n width: \"fit-content\",\n padding: \"12px 20px\",\n background: \"white\",\n color: \"black\",\n zIndex: 10000,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n borderRadius: \"4px\",\n boxShadow: \"0 4px 6px rgba(0, 0, 0, 0.1)\",\n fontFamily:\n \"'__Inter_6b0edc', '__Inter_Fallback_6b0edc', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\",\n fontSize: \"14px\",\n fontWeight: 400,\n lineHeight: \"19px\",\n }}\n >\n {error.reason === \"schemaMigration\" ? (\n <>\n <p>\n An updated version of Noya is available. Please reload the page to\n continue.\n </p>\n </>\n ) : (\n <>\n <p>\n An error occurred:{\" \"}\n <code\n style={{\n background: \"rgba(255, 0, 0, 0.1)\",\n color: \"rgba(255, 0, 0, 0.5)\",\n padding: \"2px 4px\",\n borderRadius: \"4px\",\n }}\n >\n {error.reason}\n </code>\n . Please reload the page to continue.\n <br />\n <br />\n If this happens repeatedly, please get in touch and the Noya team\n can help.\n </p>\n </>\n )}\n <div\n style={{\n height: \"1px\",\n background: \"rgba(0, 0, 0, 0.1)\",\n margin: \"12px -20px\",\n }}\n />\n <button\n style={{\n background: \"black\",\n color: \"white\",\n padding: \"8px 16px\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n fontWeight: 700,\n lineHeight: \"19px\",\n }}\n onClick={() => {\n window.location.reload();\n }}\n >\n Reload\n </button>\n </div>\n );\n}\n","import { Observable } from \"@noya-app/observable\";\n\nexport const shouldTrackEvents$ = new Observable(false);\nexport const shouldTrackTasks$ = new Observable(false);\n","\"use client\";\n\nimport {\n ConnectionEvent,\n EphemeralUserData,\n MultiplayerStateManager,\n MultiplayerUser,\n Task,\n} from \"@noya-app/state-manager\";\nimport React, { ComponentProps, useLayoutEffect } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nimport { Root } from \"react-dom/client\";\nimport { StateInspector } from \"./StateInspector\";\n\nfunction createPortalElement() {\n const el = document.createElement(\"div\");\n el.id = \"noya-multiplayer-react-inspector-portal\";\n return el;\n}\n\nexport function useStateInspector<S, M, E>({\n state,\n connectionEvents,\n connectedUsers,\n tasks,\n userId,\n disabled = false,\n colorScheme,\n anchor,\n multiplayerStateManager,\n ephemeralUserData,\n forceInit,\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n connectedUsers?: MultiplayerUser[];\n tasks?: Task[];\n userId?: string;\n disabled: boolean;\n multiplayerStateManager: MultiplayerStateManager<S, M>;\n ephemeralUserData: EphemeralUserData<E>;\n forceInit: () => void;\n} & Pick<ComponentProps<typeof StateInspector>, \"colorScheme\" | \"anchor\">) {\n const [root, setRoot] = React.useState<Root | null>(null);\n\n useLayoutEffect(() => {\n if (disabled) return;\n\n const portalElement = createPortalElement();\n\n const root = createRoot(portalElement);\n\n document.body.appendChild(portalElement);\n\n setRoot(root);\n\n return () => {\n document.body.removeChild(portalElement);\n };\n }, [disabled]);\n\n useLayoutEffect(() => {\n if (!root) return;\n\n root.render(\n <StateInspector\n state={state}\n connectionEvents={connectionEvents}\n connectedUsers={connectedUsers}\n tasks={tasks}\n userId={userId}\n colorScheme={colorScheme}\n anchor={anchor}\n forceInit={forceInit}\n multiplayerStateManager={\n multiplayerStateManager as MultiplayerStateManager<any, any>\n }\n ephemeralUserData={ephemeralUserData as EphemeralUserData<any>}\n />\n );\n }, [\n anchor,\n colorScheme,\n connectedUsers,\n connectionEvents,\n root,\n state,\n multiplayerStateManager,\n userId,\n tasks,\n forceInit,\n ephemeralUserData,\n ]);\n}\n","\"use client\";\n\nimport {\n ConnectionEvent,\n EphemeralUserData,\n ExtendedPathKey,\n MultiplayerStateManager,\n MultiplayerUser,\n Task,\n} from \"@noya-app/state-manager\";\nimport React, {\n CSSProperties,\n ComponentPropsWithoutRef,\n FC,\n memo,\n useEffect,\n useLayoutEffect,\n} from \"react\";\nimport {\n ObjectInspector,\n ObjectLabel,\n ObjectName,\n ObjectPreview,\n chromeDark,\n chromeLight,\n} from \"react-inspector\";\nimport { shouldTrackEvents$, shouldTrackTasks$ } from \"../globals\";\nimport { useEphemeralUserData, useManagedHistory } from \"../hooks\";\nimport { useLocalStorageState } from \"./useLocalStorageState\";\n\nconst lightTheme = {\n ...chromeLight,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(0,0,0,0.7)\",\n} as any;\n\nconst darkTheme = {\n ...chromeDark,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(255,255,255,0.7)\",\n} as any;\n\nconst styles = {\n sectionInner: {\n flex: \"1 1 0\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n },\n} as const;\n\nfunction ToggleButton({\n showInspector,\n setShowInspector,\n theme,\n anchor,\n}: {\n showInspector: boolean;\n setShowInspector: (value: boolean) => void;\n theme: typeof chromeLight;\n anchor: StateInspectorAnchor;\n}) {\n return (\n <span\n role=\"button\"\n style={{\n flex: \"0\",\n appearance: \"none\",\n color: theme.BASE_COLOR,\n border: \"none\",\n fontSize: \"12px\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2px 0\",\n }}\n onClick={(event) => {\n event.stopPropagation();\n\n setShowInspector(!showInspector);\n }}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n {showInspector === (anchor === \"right\") ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\"\n />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\"\n />\n </svg>\n )}\n </span>\n </span>\n );\n}\n\nfunction DisclosureSection({\n open,\n setOpen,\n title,\n right,\n children,\n colorScheme,\n isFirst,\n style,\n}: {\n open: boolean;\n setOpen?: (value: boolean) => void;\n title: string;\n right?: React.ReactNode;\n children: React.ReactNode;\n colorScheme: \"light\" | \"dark\";\n isFirst?: boolean;\n style?: CSSProperties;\n}) {\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n\n const borderColor =\n colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n\n return (\n <div\n style={{\n flex: open ? \"1 1 0\" : \"0\",\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n >\n <div\n onClick={() => setOpen?.(!open)}\n style={{\n cursor: \"default\",\n fontSize: \"12px\",\n padding: \"4px 10px\",\n display: \"flex\",\n alignItems: \"center\",\n ...(!isFirst && { borderTop: `1px solid ${borderColor}` }),\n ...(open && { borderBottom: `1px solid ${borderColor}` }),\n }}\n >\n {setOpen && (\n <Arrow\n expanded={open}\n style={{\n fontSize: theme.ARROW_FONT_SIZE,\n marginRight: theme.ARROW_MARGIN_RIGHT + 1,\n color: theme.ARROW_COLOR,\n }}\n />\n )}\n <span style={{ flex: \"1 1 0\", userSelect: \"none\" }}>{title}</span>\n {right}\n </div>\n {open && children}\n </div>\n );\n}\n\nfunction InspectorRow({\n children,\n colorScheme,\n selected,\n style,\n variant,\n}: {\n children: React.ReactNode;\n colorScheme: \"light\" | \"dark\";\n selected?: boolean;\n style?: CSSProperties;\n variant?: \"up\" | \"down\";\n}) {\n const solidBorderColor =\n colorScheme === \"light\" ? \"rgb(223 223 223)\" : \"rgb(29 29 29)\";\n\n return (\n <div\n style={{\n borderBottom: `1px solid ${solidBorderColor}`,\n fontSize: \"12px\",\n fontFamily: \"Menlo, monospace\",\n padding: \"2px 12px 1px\",\n display: \"flex\",\n alignItems: \"center\",\n background:\n variant === \"up\"\n ? \"rgba(0,255,0,0.1)\"\n : variant === \"down\"\n ? \"rgba(255,0,0,0.1)\"\n : selected\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n // background:\n // colorScheme === \"light\"\n // ? \"rgba(0,0,0,0.05)\"\n // : \"rgba(255,255,255,0.05)\",\n ...style,\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n {children}\n </span>\n </div>\n );\n}\n\nconst HISTORY_ELEMENT_PREFIX = \"noya-multiplayer-history-\";\n\nexport type StateInspectorAnchor =\n | \"left\"\n | \"right\"\n | \"bottom left\"\n | \"bottom right\";\n\nexport type StateInspectorOptions = {\n colorScheme?: \"light\" | \"dark\";\n anchor?: StateInspectorAnchor;\n};\n\nexport const StateInspector = memo(function StateInspector<S, M, E>({\n state,\n connectionEvents,\n connectedUsers,\n tasks,\n userId,\n unstyled,\n colorScheme = \"light\",\n multiplayerStateManager,\n ephemeralUserData,\n anchor = \"right\",\n forceInit,\n ...props\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n connectedUsers?: MultiplayerUser[];\n tasks?: Task[];\n userId?: string;\n unstyled?: boolean;\n multiplayerStateManager: MultiplayerStateManager<S, M>;\n ephemeralUserData: EphemeralUserData<E>;\n forceInit: () => void;\n} & StateInspectorOptions &\n ComponentPropsWithoutRef<\"div\">) {\n const [didMount, setDidMount] = React.useState(false);\n\n useLayoutEffect(() => {\n setDidMount(true);\n }, []);\n\n const eventsContainerRef = React.useRef<HTMLDivElement>(null);\n const historyContainerRef = React.useRef<HTMLDivElement>(null);\n\n const [showInspector, setShowInspector] = useLocalStorageState(\n \"noya-multiplayer-react-show-inspector\",\n true\n );\n const [showEvents, setShowEvents] = useLocalStorageState(\n \"noya-multiplayer-react-show-events\",\n false\n );\n const [showHistory, setShowHistory] = useLocalStorageState(\n \"noya-multiplayer-react-show-history\",\n false\n );\n const [showUsers, setShowUsers] = useLocalStorageState(\n \"noya-multiplayer-react-show-users\",\n true\n );\n const [showData, setShowData] = useLocalStorageState(\n \"noya-multiplayer-react-show-data\",\n true\n );\n const [showTasks, setShowTasks] = useLocalStorageState(\n \"noya-multiplayer-react-show-tasks\",\n false\n );\n const [showEphemeral, setShowEphemeral] = useLocalStorageState(\n \"noya-multiplayer-react-show-ephemeral\",\n false\n );\n\n useEffect(() => {\n shouldTrackEvents$.set(showEvents);\n }, [showEvents]);\n\n useEffect(() => {\n shouldTrackTasks$.set(showTasks);\n }, [showTasks]);\n\n useEffect(() => {\n if (eventsContainerRef.current) {\n eventsContainerRef.current.scrollTop =\n eventsContainerRef.current.scrollHeight;\n }\n }, [connectionEvents]);\n\n const ephemeral = useEphemeralUserData(ephemeralUserData);\n const historySnapshot = useManagedHistory(multiplayerStateManager.sm);\n\n useEffect(() => {\n if (historyContainerRef.current) {\n historyContainerRef.current.scrollTop =\n historyContainerRef.current.scrollHeight;\n }\n }, [historySnapshot]);\n\n // If history index changes, scroll to the new history entry into view\n useEffect(() => {\n if (!historyContainerRef.current) return;\n\n const historyEntry = historyContainerRef.current.querySelector(\n `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`\n );\n\n if (historyEntry) {\n historyEntry.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n }\n }, [historySnapshot.historyIndex]);\n\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n // const borderColor =\n // colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n const solidBorderColor =\n colorScheme === \"light\" ? \"rgb(223 223 223)\" : \"rgb(29 29 29)\";\n\n const baseStyle: CSSProperties = {\n position: \"fixed\",\n top: 12,\n ...(anchor.includes(\"right\") ? { right: 12 } : { left: 12 }),\n bottom: 12,\n width: 400,\n background:\n colorScheme === \"light\" ? \"rgba(255,255,255,0.95)\" : \"rgba(0,0,0,0.95)\",\n backdropFilter: \"blur(48px)\",\n border: `1px solid ${solidBorderColor}`,\n // outlineOffset: -1,\n borderRadius: 4,\n display: \"flex\",\n flexDirection: \"column\",\n // gap: 12,\n color: theme.BASE_COLOR,\n overflow: \"hidden\",\n zIndex: 9999,\n lineHeight: \"13px\",\n };\n\n if (!didMount) return null;\n\n if (!showInspector) {\n return (\n <div\n {...props}\n style={{\n ...baseStyle,\n padding: \"4px 10px\",\n width: undefined,\n ...(anchor.includes(\"bottom\")\n ? { bottom: 12, top: undefined }\n : { bottom: undefined }),\n }}\n onClick={() => setShowInspector(true)}\n >\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n anchor={anchor}\n />\n </div>\n );\n }\n\n return (\n <div\n {...props}\n style={{\n ...(!unstyled && baseStyle),\n ...props.style,\n }}\n >\n <DisclosureSection\n isFirst\n open={showUsers}\n setOpen={setShowUsers}\n title=\"Users\"\n colorScheme={colorScheme}\n style={{\n flex: \"0 0 auto\",\n maxHeight: \"200px\",\n }}\n right={\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n anchor={anchor}\n />\n }\n >\n <div style={{ ...styles.sectionInner, flex: \"0 0 auto\" }}>\n {connectedUsers?.map((user) => (\n <InspectorRow\n key={user.id}\n colorScheme={colorScheme}\n variant={user.id === userId ? \"up\" : undefined}\n >\n {user.image && (\n <img\n src={user.image}\n alt={user.name}\n style={{\n width: \"12px\",\n height: \"12px\",\n borderRadius: \"50%\",\n marginRight: \"4px\",\n display: \"inline-block\",\n position: \"relative\",\n top: \"-1px\",\n background: solidBorderColor,\n }}\n />\n )}\n {user.name} ({ellipsis(user.id.toString(), 8, \"middle\")})\n </InspectorRow>\n ))}\n {!connectedUsers && (\n <div\n style={{\n padding: \"12px\",\n fontSize: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n }}\n >\n <span>No connected users</span>\n </div>\n )}\n </div>\n </DisclosureSection>\n <DisclosureSection\n title=\"Data\"\n colorScheme={colorScheme}\n setOpen={setShowData}\n open={showData}\n right={\n <span\n style={{\n display: \"flex\",\n gap: \"4px\",\n }}\n >\n <SmallButton\n // disabled={!historySnapshot.canUndo}\n theme={theme}\n onClick={() => {\n forceInit();\n }}\n >\n Reset\n </SmallButton>\n </span>\n }\n >\n <div style={styles.sectionInner}>\n <InspectorRow colorScheme={colorScheme}>\n <ObjectInspector\n name={multiplayerStateManager.schema ? \"state\" : undefined}\n data={state}\n theme={theme}\n />\n </InspectorRow>\n {multiplayerStateManager.schema && (\n <InspectorRow colorScheme={colorScheme}>\n <ObjectInspector\n name=\"schema\"\n data={multiplayerStateManager.schema}\n theme={theme}\n />\n </InspectorRow>\n )}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showHistory}\n setOpen={setShowHistory}\n title=\"History\"\n colorScheme={colorScheme}\n right={\n <span\n style={{\n display: \"flex\",\n gap: \"4px\",\n }}\n >\n <SmallButton\n disabled={!historySnapshot.canUndo}\n theme={theme}\n onClick={() => {\n multiplayerStateManager.undo();\n }}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fill=\"currentColor\"\n 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\"\n />\n </svg>\n </span>\n </SmallButton>\n <SmallButton\n disabled={!historySnapshot.canRedo}\n theme={theme}\n onClick={() => {\n multiplayerStateManager.redo();\n }}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fill=\"currentColor\"\n 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\"\n />\n </svg>\n </span>\n </SmallButton>\n </span>\n }\n >\n <div ref={historyContainerRef} style={styles.sectionInner}>\n <div\n id={`${HISTORY_ELEMENT_PREFIX}0`}\n style={{\n borderBottom: `1px solid ${solidBorderColor}`,\n fontSize: \"12px\",\n fontFamily: \"Menlo, monospace\",\n padding: \"2px 12px 1px\",\n display: \"flex\",\n alignItems: \"center\",\n background:\n historySnapshot.historyIndex === 0\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n Initial state\n </span>\n </div>\n {historySnapshot.history.map((entry, index) => (\n <div\n id={`${HISTORY_ELEMENT_PREFIX}${index + 1}`}\n key={index}\n style={{\n padding: \"0px 12px 1px\",\n borderBottom: `1px solid ${solidBorderColor}`,\n background:\n index + 1 === historySnapshot.historyIndex\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n {\"name\" in entry.metadata &&\n typeof entry.metadata.name === \"string\" && (\n <pre\n style={{\n fontSize: \"11px\",\n display: \"flex\",\n flexWrap: \"wrap\",\n }}\n >\n {entry.metadata.name}\n </pre>\n )}\n {entry.redoPatches?.map((patch, j) => (\n <pre\n key={j}\n style={{\n fontSize: \"11px\",\n display: \"flex\",\n flexWrap: \"wrap\",\n }}\n >\n {patch.op === \"add\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"replace\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"remove\" && (\n <>\n <span style={{ color: theme.OBJECT_VALUE_STRING_COLOR }}>\n delete{\" \"}\n </span>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n </>\n )}\n {patch.op === \"move\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.from!)}\n </span>\n {\" -> \"}\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n </>\n )}\n </pre>\n ))}\n </div>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n title=\"Tasks\"\n colorScheme={colorScheme}\n open={showTasks}\n setOpen={setShowTasks}\n >\n <div style={styles.sectionInner}>\n {tasks?.map((task) => (\n <InspectorRow\n key={task.id}\n colorScheme={colorScheme}\n style={{\n backgroundColor:\n task.status === \"done\"\n ? \"rgba(0,255,0,0.2)\"\n : task.status === \"error\"\n ? \"rgba(255,0,0,0.2)\"\n : undefined,\n }}\n >\n <ObjectInspector\n name={task.name}\n data={task.payload}\n theme={theme}\n />\n </InspectorRow>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showEphemeral}\n setOpen={setShowEphemeral}\n title=\"Ephemeral User Data\"\n colorScheme={colorScheme}\n >\n <div style={styles.sectionInner}>\n {Object.entries(ephemeral).map(([key, value]) => (\n <InspectorRow key={key} colorScheme={colorScheme}>\n <ObjectInspector\n name={key}\n data={value}\n theme={theme}\n expandLevel={10}\n />\n </InspectorRow>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showEvents}\n setOpen={setShowEvents}\n title=\"Events\"\n colorScheme={colorScheme}\n >\n <div ref={eventsContainerRef} style={styles.sectionInner}>\n {connectionEvents?.map((event, index) =>\n event.type === \"stateChange\" ? (\n <InspectorRow key={index} colorScheme={colorScheme}>\n connection:{\" \"}\n <span style={{ fontStyle: \"italic\" }}>\n {event.state.toLowerCase()}\n </span>\n </InspectorRow>\n ) : (\n <InspectorRow\n key={index}\n colorScheme={colorScheme}\n variant={event.type === \"send\" ? \"up\" : \"down\"}\n style={{\n padding: \"0px 12px 1px\",\n }}\n >\n <ObjectInspector\n data={event.type === \"error\" ? event.error : event.message}\n theme={theme}\n nodeRenderer={({\n depth,\n name,\n data,\n isNonenumerable,\n expanded,\n }: any) => {\n const direction = event.type === \"send\" ? \"up\" : \"down\";\n\n return depth === 0 ? (\n <ObjectRootLabel direction={direction} data={data} />\n ) : (\n <ObjectLabel\n direction={direction}\n name={name}\n data={data}\n isNonenumerable={isNonenumerable}\n />\n );\n }}\n />\n </InspectorRow>\n )\n )}\n {!connectionEvents && (\n <div\n style={{\n padding: \"12px\",\n fontSize: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n }}\n >\n <span>No recorded events</span>\n </div>\n )}\n </div>\n </DisclosureSection>\n </div>\n );\n});\n\ntype MessageDirection = \"up\" | \"down\";\n\nconst ObjectRootLabel: FC<{\n name?: string;\n data: any;\n direction?: MessageDirection;\n}> = ({ name, data, direction }) => {\n if (typeof name === \"string\") {\n return (\n <span>\n <ObjectName name={name} />\n <span>: </span>\n <ObjectPreview data={data} />\n </span>\n );\n }\n if (direction === \"up\" || direction === \"down\") {\n const arrow = direction === \"up\" ? \"↑\" : \"↓\";\n\n return (\n <span>\n <span\n style={{\n background:\n direction === \"up\" ? \"rgba(0,255,0,0.2)\" : \"rgba(255,0,0,0.2)\",\n // color: \"white\",\n width: 12,\n height: 12,\n borderRadius: 2,\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n marginRight: 4,\n lineHeight: \"12px\",\n }}\n >\n {arrow}\n </span>\n <ObjectPreview data={data} />\n </span>\n );\n } else {\n return <ObjectPreview data={data} />;\n }\n};\n\n// Rotates ▶️ or ▼ based on expanded state\nfunction Arrow({\n expanded,\n onClick,\n style,\n}: {\n expanded: boolean;\n onClick?: () => void;\n style?: CSSProperties;\n}) {\n return (\n <span\n role=\"button\"\n onClick={onClick}\n style={{\n display: \"inline-block\",\n textAlign: \"center\",\n transform: expanded ? \"rotate(0deg)\" : \"rotate(-90deg)\",\n fontFamily: \"Menlo, monospace\",\n ...style,\n }}\n >\n {\"▼\"}\n </span>\n );\n}\n\nfunction pathToString(extendedPath: ExtendedPathKey[]) {\n return extendedPath\n .map((key) =>\n typeof key === \"object\"\n ? `:${ellipsis(key.id.toString(), 8, \"middle\")}`\n : key\n )\n .map((key, index) =>\n index === 0 || (typeof key === \"string\" && key.startsWith(\":\"))\n ? key\n : `.${key}`\n )\n .join(\"\");\n}\n\ntype EllipsisPosition = \"start\" | \"middle\" | \"end\";\n\nfunction ellipsis(\n str: string,\n maxLength: number,\n position: EllipsisPosition = \"end\"\n) {\n if (str.length <= maxLength) return str;\n\n switch (position) {\n case \"start\":\n return `…${str.slice(str.length - maxLength)}`;\n case \"middle\":\n const halfLength = Math.floor(maxLength / 2);\n return `${str.slice(0, halfLength)}…${str.slice(str.length - halfLength)}`;\n case \"end\":\n return `${str.slice(0, maxLength)}…`;\n }\n}\n\nfunction SmallButton({\n children,\n onClick,\n style,\n theme,\n disabled,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n style?: CSSProperties;\n theme: typeof chromeLight;\n disabled?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={(event) => {\n event.stopPropagation();\n onClick();\n }}\n style={{\n flex: \"0\",\n appearance: \"none\",\n background: \"none\",\n color: theme.BASE_COLOR,\n opacity: disabled ? 0.25 : 1,\n border: \"none\",\n fontSize: \"12px\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2px 0\",\n cursor: \"pointer\",\n ...style,\n }}\n >\n {children}\n </button>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\n\nconst localStorage = typeof window !== \"undefined\" ? window.localStorage : null;\n\nexport function useLocalStorageState<S>(\n key: string,\n defaultValue: S\n): [S, (value: S) => void] {\n const [state, setState] = React.useState<S>(() => {\n const value = localStorage?.getItem(key);\n let result = defaultValue;\n if (value) {\n try {\n result = JSON.parse(value);\n } catch (error) {\n console.error(\"Error parsing localStorage value\", error);\n }\n }\n return result;\n });\n\n const setLocalStorageState = (value: S) => {\n localStorage?.setItem(key, JSON.stringify(value));\n setState(value);\n };\n\n return [state, setLocalStorageState];\n}\n","/* eslint-disable no-restricted-globals */\nimport {\n createOrCastValue,\n findAllDefs,\n localStorageSync,\n MultiplayerUser,\n stubSync,\n SyncAdapter,\n TSchema,\n webSocketSync,\n} from \"@noya-app/state-manager\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useMultiplayerState, UseMultiplayerStateOptions } from \"./hooks\";\nimport { StateInspectorOptions } from \"./inspector/StateInspector\";\n\nexport type AppViewType = \"editable\" | \"readOnly\" | \"preview\";\n\nexport type AppTheme = \"light\" | \"dark\";\n\nexport type AppData<State> = {\n multiplayerUrl?: string;\n theme: AppTheme;\n viewType: AppViewType;\n initialState: State;\n inspector: boolean | StateInspectorOptions;\n};\n\nexport function createDefaultAppData<State>(\n initialState: State\n): AppData<State> {\n return {\n theme: \"light\",\n viewType: \"editable\",\n initialState,\n inspector: false,\n };\n}\n\nexport type GetAppDataOptions = {\n window?: { location: { hash: string } };\n};\n\nexport function enforceSchema<State>(\n initialState: State,\n schema?: TSchema\n): State {\n return schema\n ? (createOrCastValue({\n schema,\n value: initialState,\n defs: findAllDefs(schema),\n }) as State)\n : initialState;\n}\n\nexport function parseAppDataParameter(options?: GetAppDataOptions) {\n const window = options?.window ?? globalThis;\n const urlHash = (window.location.hash || \"\").replace(/^#/, \"\");\n const params = new URLSearchParams(urlHash);\n const data = params.get(\"data\");\n if (!data) return null;\n try {\n return JSON.parse(data);\n } catch (e) {\n return null;\n }\n}\n\nexport function getAppData<State>(\n initialState: State | (() => State),\n schema?: TSchema,\n options?: GetAppDataOptions\n): AppData<State> {\n const resolvedInitialState =\n initialState instanceof Function ? initialState() : initialState;\n\n try {\n const appData: AppData<unknown> =\n parseAppDataParameter(options) ??\n createDefaultAppData(resolvedInitialState);\n\n return {\n ...appData,\n initialState: enforceSchema(appData.initialState, schema) as State,\n };\n } catch (e) {\n return createDefaultAppData(enforceSchema(resolvedInitialState, schema));\n }\n}\n\nexport type IframeToHostMessage =\n | {\n type: \"application.setMenuItems\";\n payload: {\n menuItems: any[];\n };\n }\n | {\n type: \"multiplayer.setUsers\";\n payload: {\n users: any[];\n };\n };\n\nexport type HostToIframeMessage = {\n type: \"application.selectMenuItem\";\n payload: {\n value: string;\n };\n};\n\nexport function useBroadcastConnectedUsers(connectedUsers: MultiplayerUser[]) {\n useEffect(() => {\n if (!isEmbeddedApp()) return;\n\n const message: IframeToHostMessage = {\n type: \"multiplayer.setUsers\",\n payload: { users: connectedUsers },\n };\n\n parent?.postMessage(message, \"*\");\n }, [connectedUsers]);\n}\n\nexport function useBroadcastMenuItems<T>(\n menuItems: any[],\n handleSelectMenuItem: (value: T) => void\n) {\n useEffect(() => {\n if (!isEmbeddedApp()) return;\n\n const message: IframeToHostMessage = {\n type: \"application.setMenuItems\",\n payload: { menuItems },\n };\n\n parent?.postMessage(message, \"*\");\n\n const listener = (event: MessageEvent<HostToIframeMessage>) => {\n if (event.data.type === \"application.selectMenuItem\") {\n handleSelectMenuItem(event.data.payload.value as T);\n }\n };\n\n window.addEventListener(\"message\", listener);\n\n return () => {\n window.removeEventListener(\"message\", listener);\n };\n }, [handleSelectMenuItem, menuItems]);\n}\n\nexport function isEmbeddedApp() {\n return window.self !== window.top;\n}\n\nexport function useNoyaAppState<S, M = void, E = void>(\n initialState: S | (() => S),\n options?: UseMultiplayerStateOptions<S, M, E> & {\n localStorageKey?: string;\n }\n) {\n // Keep these stable after initial render\n const [\n {\n multiplayerUrl,\n inspector,\n initialState: noyaAppInitialState,\n theme,\n viewType,\n },\n ] = useState(() => {\n return getAppData(initialState, options?.schema);\n });\n\n const sync = useMemo((): SyncAdapter<S, M, E> => {\n return multiplayerUrl\n ? webSocketSync(multiplayerUrl)\n : options?.localStorageKey\n ? localStorageSync({ key: options.localStorageKey })\n : stubSync();\n }, [multiplayerUrl, options?.localStorageKey]);\n\n const result = useMultiplayerState(noyaAppInitialState, {\n ...options,\n inspector: options?.inspector ?? inspector,\n sync,\n });\n\n const [, , extras] = result;\n\n useBroadcastConnectedUsers(extras.connectedUsers);\n\n const mergedExtras = useMemo(() => {\n return { ...extras, theme, viewType } as const;\n }, [extras, theme, viewType]);\n\n return [result[0], result[1], mergedExtras] as const;\n}\n"],"mappings":"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","names":["UserPointer","import_react","listen","get","React","UserPointer","UserPointerContainer","UserNameTag","import_react","import_client","import_react","React","import_react","import_react","import_react","React","React","StateInspector","React","root","userId","tasks","state","import_state_manager","import_react","window"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/avatarStyle.ts","../src/components/UserPointersOverlay.tsx","../src/useObservable.ts","../src/hooks.ts","../src/components/ErrorOverlay.tsx","../src/globals.ts","../src/inspector/useStateInspector.tsx","../src/inspector/StateInspector.tsx","../src/inspector/useLocalStorageState.tsx","../src/noyaApp.ts"],"sourcesContent":["export * from \"@noya-app/state-manager\";\nexport * from \"./avatarStyle\";\nexport * from \"./components/UserPointersOverlay\";\nexport * from \"./hooks\";\nexport * from \"./inspector/StateInspector\";\nexport * from \"./noyaApp\";\nexport * from \"./useObservable\";\n","function hashCode(string: string) {\n let hash = 0;\n\n for (const char of string) {\n hash = char.charCodeAt(0) + ((hash << 5) - hash);\n }\n\n return hash;\n}\n\nfunction elementFromHash<T>(array: T[], hash: number): T {\n return array[Math.abs(hash) % array.length];\n}\n\nexport function getAvatarInitials(name: string) {\n return name\n .split(\" \")\n .filter((c) => c.length > 0)\n .map((c) => c[0])\n .join(\"\")\n .toLocaleUpperCase();\n}\n\n/**\n * Create a background color and initials from a name\n *\n * Adapted from https://mui.com/material-ui/react-avatar/\n */\nexport function getAvatarStyle(name: string) {\n const hash = hashCode(name);\n const color = elementFromHash(Object.values(colors500), hash);\n // const darkerColor = elementFromHash(Object.values(colors800), hash);\n\n return {\n color: \"white\",\n backgroundColor: color,\n // primaryColors: {\n // \"500\": color,\n // \"800\": darkerColor,\n // },\n };\n}\n\nconst colors500 = {\n red500: \"#ef4444\",\n orange500: \"#f97316\",\n amber500: \"#f59e0b\",\n yellow500: \"#eab308\",\n lime500: \"#84cc16\",\n green500: \"#22c55e\",\n emerald500: \"#10b981\",\n teal500: \"#14b8a6\",\n cyan500: \"#06b6d4\",\n sky500: \"#0ea5e9\",\n blue500: \"#3b82f6\",\n indigo500: \"#6366f1\",\n violet500: \"#8b5cf6\",\n purple500: \"#a855f7\",\n fuchsia500: \"#d946ef\",\n pink500: \"#ec4899\",\n rose500: \"#f43f5e\",\n};\n\n// const colors800 = {\n// red800: \"#991b1b\",\n// orange800: \"#9a3412\",\n// amber800: \"#92400e\",\n// yellow800: \"#854d0e\",\n// lime800: \"#3f6212\",\n// green800: \"#166534\",\n// emerald800: \"#065f46\",\n// teal800: \"#115e59\",\n// cyan800: \"#155e75\",\n// sky800: \"#075985\",\n// blue800: \"#1e40af\",\n// indigo800: \"#3730a3\",\n// violet800: \"#5b21b6\",\n// purple800: \"#6b21a8\",\n// fuchsia800: \"#86198f\",\n// pink800: \"#9d174d\",\n// rose800: \"#9f1239\",\n// };\n","\"use client\";\n\nimport { EphemeralUserData, MultiplayerUser } from \"@noya-app/state-manager\";\nimport React, { memo, useEffect, useMemo, useState } from \"react\";\nimport { getAvatarStyle } from \"../avatarStyle\";\nimport { useObservable } from \"../useObservable\";\n\ntype Point = { x: number; y: number };\n\nexport type UserPointerData = { pointer?: Point };\n\nexport type UserPointerProps<E extends UserPointerData> = {\n user: MultiplayerUser;\n ephemeralUserData: EphemeralUserData<E>;\n hideAfter?: number;\n};\n\nfunction shouldShow(hideAfter: number, updatedAt: number) {\n return !!updatedAt && Date.now() - updatedAt < hideAfter;\n}\n\nconst UserPointer_ = function UserPointer<E extends UserPointerData>({\n user,\n ephemeralUserData,\n hideAfter = 5000,\n}: UserPointerProps<E>) {\n const metadata = useObservable(ephemeralUserData.metadata$, [\n user.id,\n ] as const);\n const data = useObservable(ephemeralUserData.data$, [user.id] as const);\n const avatarStyle = useMemo(() => getAvatarStyle(user.id), [user.id]);\n\n const [, setForceUpdate] = useState(0);\n\n const updatedAt = metadata?.updatedAt ?? 0;\n\n useEffect(() => {\n if (!shouldShow(hideAfter, updatedAt)) return;\n\n const timeoutId = setTimeout(() => {\n setForceUpdate((prev) => prev + 1);\n }, hideAfter);\n\n return () => clearTimeout(timeoutId);\n }, [hideAfter, updatedAt]);\n\n const show = shouldShow(hideAfter, updatedAt);\n\n if (!data || !data.pointer) return null;\n\n return (\n <UserPointerContainer key={user.id} point={data.pointer} show={show}>\n <UserPointerIcon color={avatarStyle.backgroundColor} />\n <UserNameTag background={avatarStyle.backgroundColor}>\n {user.name}\n </UserNameTag>\n </UserPointerContainer>\n );\n};\n\nexport const UserPointer = memo(UserPointer_) as typeof UserPointer_;\n\nexport const UserPointerContainer = memo(function UserPointerContainer({\n point,\n children,\n show = true,\n}: {\n point: Point;\n children: React.ReactNode;\n show?: boolean;\n}) {\n return (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n transform: `translate(${Math.round(point.x)}px, ${Math.round(\n point.y\n )}px)`,\n opacity: show ? 1 : 0,\n transition: \"transform 0.1s, opacity 0.2s\",\n }}\n >\n {children}\n </div>\n );\n});\n\nexport const UserNameTag = memo(function UserNameTag({\n background,\n children,\n}: {\n background: string;\n children: React.ReactNode;\n}) {\n return (\n <span\n style={{\n position: \"relative\",\n top: \"8px\",\n left: \"15px\",\n fontSize: 11,\n lineHeight: \"1\",\n fontWeight: 500,\n boxShadow: \"0 1px 1px rgba(0,0,0,0.1)\",\n padding: \"2px 4px 3px\",\n pointerEvents: \"none\",\n letterSpacing: \"-0.3px\",\n outline: `1px solid rgba(255,255,255,0.3)`,\n outlineOffset: \"-1px\",\n background,\n color: \"white\",\n }}\n >\n {children}\n </span>\n );\n});\n\nexport type UserPointersOverlayProps<E extends UserPointerData> = {\n connectedUsers: MultiplayerUser[];\n ephemeralUserData: EphemeralUserData<E>;\n};\n\nexport const UserPointersOverlay = memo(function UserPointers<\n E extends UserPointerData,\n>({ connectedUsers, ephemeralUserData }: UserPointersOverlayProps<E>) {\n const currentUserId = useObservable(ephemeralUserData.currentUserId$);\n\n return (\n <>\n {connectedUsers.map((user) => {\n if (user.id === currentUserId) return null;\n\n return (\n <UserPointer\n key={user.id}\n user={user}\n ephemeralUserData={\n ephemeralUserData as unknown as EphemeralUserData<E>\n }\n />\n );\n })}\n </>\n );\n});\n\nexport const UserPointerIcon = memo(function CursorIcon({\n color = \"black\",\n}: {\n color?: string;\n}) {\n return (\n <svg\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n position: \"absolute\",\n filter: \"drop-shadow(0 1px 1px rgba(0,0,0,0.1))\",\n // filter: \"drop-shadow(0 1px 1px rgba(0,0,0,0.6))\",\n }}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M3.29227 0.0451998C3.47033 -0.0361222 3.67946 -0.00606629 3.8274 0.122107L12.8587 7.94648C13.0134 8.08054 13.0708 8.29538 13.0035 8.48873C12.9362 8.68208 12.7578 8.81488 12.5533 8.8239L9.21887 8.97096L11.1504 13.2149C11.2648 13.4662 11.1538 13.7626 10.9026 13.877L8.75024 14.8575C8.499 14.972 8.20255 14.8611 8.08802 14.6099L6.15339 10.3665L3.86279 12.7817C3.72196 12.9302 3.50487 12.9779 3.31479 12.9021C3.1247 12.8263 3 12.6423 3 12.4376V0.500008C3 0.304264 3.11422 0.126522 3.29227 0.0451998Z\"\n fill={color}\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M3.29227 0.048984C3.47033 -0.032338 3.67946 -0.00228211 3.8274 0.125891L12.8587 7.95026C13.0134 8.08432 13.0708 8.29916 13.0035 8.49251C12.9362 8.68586 12.7578 8.81866 12.5533 8.82768L9.21887 8.97474L11.1504 13.2187C11.2648 13.47 11.1538 13.7664 10.9026 13.8808L8.75024 14.8613C8.499 14.9758 8.20255 14.8649 8.08802 14.6137L6.15339 10.3703L3.86279 12.7855C3.72196 12.934 3.50487 12.9817 3.31479 12.9059C3.1247 12.8301 3 12.6461 3 12.4414V0.503792C3 0.308048 3.11422 0.130306 3.29227 0.048984ZM4 1.59852V11.1877L5.93799 9.14425C6.05238 9.02363 6.21924 8.96776 6.38319 8.99516C6.54715 9.02256 6.68677 9.12965 6.75573 9.2809L8.79056 13.7441L10.0332 13.178L8.00195 8.71497C7.93313 8.56376 7.94391 8.38824 8.03072 8.24659C8.11753 8.10494 8.26903 8.01566 8.435 8.00834L11.2549 7.88397L4 1.59852Z\"\n fill=\"rgba(255,255,255,0.5)\"\n />\n </svg>\n );\n});\n","import { GetWithPath, Observable, PathKey } from \"@noya-app/observable\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nexport function useObservable<T>(observable: Observable<T>): T;\nexport function useObservable<T, P extends PathKey[]>(\n observable: Observable<T>,\n path: P\n): GetWithPath<T, P>;\nexport function useObservable<T, P extends PathKey[]>(\n observable: Observable<T>,\n path?: P\n) {\n const { get, listen } = useMemo(() => {\n const listen = path\n ? (callback: (value: GetWithPath<T, P>) => void) =>\n observable.listen(path, callback)\n : observable.listen;\n\n const get: () => void = path ? () => observable.get(path) : observable.get;\n\n return { get, listen };\n }, [observable, path]);\n\n return useSyncExternalStore(listen, get, get);\n}\n","\"use client\";\n\nimport {\n ActionHandler,\n ConnectionEvent,\n EphemeralUserData,\n Get,\n MultiplayerStateManager,\n MultiplayerStateManagerError,\n MultiplayerStateManagerOptions,\n MultiplayerUser,\n StateManager,\n StateManagerOptions,\n stubSync,\n SyncAdapter,\n SyncAdapterOptions,\n Task,\n} from \"@noya-app/state-manager\";\nimport {\n createElement,\n SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { ErrorOverlay } from \"./components/ErrorOverlay\";\nimport { shouldTrackEvents$, shouldTrackTasks$ } from \"./globals\";\nimport { StateInspectorOptions } from \"./inspector/StateInspector\";\nimport { useStateInspector } from \"./inspector/useStateInspector\";\nimport { useObservable } from \"./useObservable\";\n\nexport function useSyncStateManager<S, M>(stateManager: StateManager<S, M>): S;\nexport function useSyncStateManager<S, M, P extends string>(\n stateManager: StateManager<S, M>,\n path: P\n): Get<S, P, unknown>;\nexport function useSyncStateManager<S, M>(\n stateManager: StateManager<S, M>,\n path?: string\n) {\n const getSnapshot = useCallback(\n () =>\n typeof path === \"string\"\n ? stateManager.getState(path)\n : stateManager.getState(),\n [stateManager, path]\n );\n\n return useSyncExternalStore(\n stateManager.addListener,\n getSnapshot,\n getSnapshot\n );\n}\n\nexport function useManagedState<S, M = void>(\n createInitialState: () => S,\n options?: StateManagerOptions<S, M>\n) {\n const [stateManager] = useState(\n () => new StateManager<S, M>(createInitialState(), options)\n );\n\n const state = useSyncStateManager(stateManager);\n\n const setState = useCallback(\n (\n ...args: M extends {}\n ? [metadata: M, action: SetStateAction<S>]\n : [action: SetStateAction<S>]\n ) => {\n const [metadata, action] =\n args.length === 1 ? [undefined, args[0]] : args;\n\n if (metadata === undefined) {\n const performActionNoMetadata = stateManager.performAction as (\n handler: ActionHandler<S>\n ) => void;\n\n if (action instanceof Function) {\n performActionNoMetadata({\n run: action,\n undo: () => state,\n });\n } else {\n performActionNoMetadata({\n run: () => action,\n undo: () => state,\n });\n }\n } else {\n const performActionWithMetadata = stateManager.performAction as (\n metadata: M,\n handler: ActionHandler<S>\n ) => void;\n\n if (action instanceof Function) {\n performActionWithMetadata(metadata, {\n run: action,\n undo: () => state,\n });\n } else {\n performActionWithMetadata(metadata, {\n run: () => action,\n undo: () => state,\n });\n }\n }\n },\n [state, stateManager]\n );\n\n return [state, setState, stateManager] as const;\n}\n\nexport function useManagedHistory<S, M = void>(\n stateManager: StateManager<S, M>\n) {\n return useSyncExternalStore(\n stateManager.historyEmittor.addListener,\n stateManager.getHistorySnapshot,\n stateManager.getHistorySnapshot\n );\n}\n\nexport function useSyncMultiplayerStateManager<S, M = void>(\n multiplayerStateManager: MultiplayerStateManager<S, M>\n) {\n return useSyncExternalStore(\n multiplayerStateManager.addListener,\n multiplayerStateManager.getOptimisticState,\n multiplayerStateManager.getOptimisticState\n );\n}\n\nfunction throttle<F extends (...args: any[]) => any>(fn: F, ms: number) {\n let lastCall = 0;\n let timeoutId: number | null = null;\n return (...args: Parameters<F>) => {\n const now = Date.now();\n if (now - lastCall < ms) {\n if (timeoutId) clearTimeout(timeoutId);\n timeoutId = setTimeout(\n () => {\n lastCall = now;\n fn(...args);\n },\n ms - (now - lastCall)\n ) as unknown as number;\n return;\n }\n lastCall = now;\n return fn(...args);\n };\n}\n\nexport function useEphemeralUserData<E>(\n ephemeralUserData: EphemeralUserData<E>,\n options?: {\n throttle?: number;\n }\n) {\n const throttledAddListener = useMemo(() => {\n const throttleMs = options?.throttle ?? 0;\n\n if (throttleMs > 0) {\n const addListener = (\n fn: Parameters<typeof ephemeralUserData.addListener>[0]\n ) => {\n const throttledFn = throttle(fn, throttleMs);\n return ephemeralUserData.addListener(throttledFn);\n };\n\n return addListener;\n }\n\n return ephemeralUserData.addListener;\n }, [ephemeralUserData, options?.throttle]);\n\n return useSyncExternalStore(\n throttledAddListener,\n ephemeralUserData.getSnapshot,\n ephemeralUserData.getSnapshot\n );\n}\n\nconst defaultStubSync = stubSync();\n\nexport type UseMultiplayerStateOptions<\n S,\n M = void,\n E = void,\n> = MultiplayerStateManagerOptions<S, M> & {\n sync?: (\n options: Pick<SyncAdapterOptions<S, M, E>, \"ms\" | \"ephemeralUserData\">\n ) => void;\n trackConnectionEvents?: boolean;\n trackTasks?: boolean;\n inspector?: boolean | StateInspectorOptions;\n};\n\nexport function useMultiplayerState<S, M = void, E = void>(\n initialState: S | (() => S),\n options?: UseMultiplayerStateOptions<S, M, E>\n) {\n const { sync = defaultStubSync as unknown as SyncAdapter<S, M, E>, ...rest } =\n options ?? {};\n\n const [multiplayerStateManager] = useState(\n () => new MultiplayerStateManager<S, M>(initialState, rest)\n );\n const syncRef = useRef(sync);\n\n const [connectionEvents, setConnectionEvents] = useState<\n ConnectionEvent<S>[] | undefined\n >();\n\n const [connectedUsers, setConnectedUsers] = useState<MultiplayerUser[]>([]);\n const [ephemeralUserData] = useState<EphemeralUserData<E>>(\n () => new EphemeralUserData()\n );\n const [tasks, setTasks] = useState<Task[]>([]);\n const [userId, setUserId] = useState<string | undefined>();\n\n const extras = useMemo(() => {\n return {\n tasks,\n userId,\n connectionEvents,\n connectedUsers,\n ephemeralUserData,\n multiplayerStateManager,\n // evaluate: async (code: string) => {\n // const payload = await rpcManager.request({ type: \"eval\", code });\n\n // if (payload.type !== \"eval\") {\n // throw new Error(`Unexpected rpc response type: ${payload.type}`);\n // }\n // },\n };\n }, [\n tasks,\n userId,\n connectionEvents,\n connectedUsers,\n ephemeralUserData,\n multiplayerStateManager,\n ]);\n\n const globalTrackEvents = useObservable(shouldTrackEvents$);\n const globalTrackTasks = useObservable(shouldTrackTasks$);\n\n const shouldTrackEvents = options?.trackConnectionEvents ?? globalTrackEvents;\n const shouldTrackTasks = options?.trackTasks ?? globalTrackTasks;\n\n const trackEventsCallbackRef = useRef<\n ((e: ConnectionEvent<S>) => void) | undefined\n >();\n const trackConnectedUsersCallbackRef = useRef<\n ((users: MultiplayerUser[], userId: string) => void) | undefined\n >();\n const trackTasksCallbackRef = useRef<((tasks: Task[]) => void) | undefined>();\n\n useEffect(() => {\n trackEventsCallbackRef.current = shouldTrackEvents\n ? (e) =>\n setConnectionEvents((events) => {\n const updated = events ? [...events, e] : [e];\n return updated.length > 50 ? updated.slice(-50) : updated;\n })\n : undefined;\n }, [shouldTrackEvents]);\n\n useEffect(() => {\n trackConnectedUsersCallbackRef.current = (users, userId) => {\n setConnectedUsers(users);\n setUserId(userId);\n };\n }, []);\n\n useEffect(() => {\n trackTasksCallbackRef.current = shouldTrackTasks\n ? (tasks) => {\n setTasks((old) => {\n const newIds = new Set(tasks.map((t) => t.id));\n\n // merge old and new tasks, preferring new tasks\n const unchanged = old.filter((t) => !newIds.has(t.id));\n\n return [...unchanged, ...tasks];\n });\n }\n : undefined;\n }, [shouldTrackTasks]);\n\n useEffect(() => {\n if (syncRef.current) {\n return syncRef.current({\n ms: multiplayerStateManager,\n ephemeralUserData,\n onConnectionEvent: (e) => trackEventsCallbackRef.current?.(e),\n onChangeConnectedUsers: (users, userId) =>\n trackConnectedUsersCallbackRef.current?.(users, userId),\n onChangeTasks: (tasks) => trackTasksCallbackRef.current?.(tasks),\n });\n }\n }, [ephemeralUserData, multiplayerStateManager]);\n\n const state = useSyncMultiplayerStateManager(multiplayerStateManager);\n\n const forceInit = useCallback(() => {\n const state =\n initialState instanceof Function ? initialState() : initialState;\n const schema = options?.schema;\n multiplayerStateManager.sm.clearHistory();\n multiplayerStateManager.sendInit({ force: true, state, schema });\n }, [initialState, multiplayerStateManager, options?.schema]);\n\n const [unrecoverableError, setUnrecoverableError] = useState<\n MultiplayerStateManagerError | undefined\n >();\n\n useEffect(() => {\n return multiplayerStateManager.errorEmitter.addListener((error) => {\n setUnrecoverableError(error);\n });\n }, [multiplayerStateManager]);\n\n useEffect(() => {\n if (!unrecoverableError) return;\n const el = document.createElement(\"div\");\n el.id = \"noya-multiplayer-react-error-overlay\";\n document.body.appendChild(el);\n const root = createRoot(el);\n root.render(createElement(ErrorOverlay, { error: unrecoverableError }));\n return () => {\n root.unmount();\n el.remove();\n };\n });\n\n useStateInspector({\n ephemeralUserData,\n multiplayerStateManager,\n state,\n connectionEvents,\n connectedUsers,\n tasks,\n userId,\n forceInit,\n disabled: !options?.inspector,\n ...(typeof options?.inspector === \"object\" && options.inspector),\n });\n\n return [state, multiplayerStateManager.setState, extras] as const;\n}\n","import { MultiplayerStateManagerError } from \"@noya-app/state-manager\";\nimport React from \"react\";\n\nexport function ErrorOverlay({\n error,\n}: {\n error: MultiplayerStateManagerError;\n}) {\n return (\n <div\n style={{\n position: \"fixed\",\n top: \"20px\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n maxWidth: \"80%\",\n width: \"fit-content\",\n padding: \"12px 20px\",\n background: \"white\",\n color: \"black\",\n zIndex: 10000,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n borderRadius: \"4px\",\n boxShadow: \"0 4px 6px rgba(0, 0, 0, 0.1)\",\n fontFamily:\n \"'__Inter_6b0edc', '__Inter_Fallback_6b0edc', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\",\n fontSize: \"14px\",\n fontWeight: 400,\n lineHeight: \"19px\",\n }}\n >\n {error.reason === \"schemaMigration\" ? (\n <>\n <p>\n An updated version of Noya is available. Please reload the page to\n continue.\n </p>\n </>\n ) : (\n <>\n <p>\n An error occurred:{\" \"}\n <code\n style={{\n background: \"rgba(255, 0, 0, 0.1)\",\n color: \"rgba(255, 0, 0, 0.5)\",\n padding: \"2px 4px\",\n borderRadius: \"4px\",\n }}\n >\n {error.reason}\n </code>\n . Please reload the page to continue.\n <br />\n <br />\n If this happens repeatedly, please get in touch and the Noya team\n can help.\n </p>\n </>\n )}\n <div\n style={{\n height: \"1px\",\n background: \"rgba(0, 0, 0, 0.1)\",\n margin: \"12px -20px\",\n }}\n />\n <button\n style={{\n background: \"black\",\n color: \"white\",\n padding: \"8px 16px\",\n borderRadius: \"4px\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n fontWeight: 700,\n lineHeight: \"19px\",\n }}\n onClick={() => {\n window.location.reload();\n }}\n >\n Reload\n </button>\n </div>\n );\n}\n","import { Observable } from \"@noya-app/observable\";\n\nexport const shouldTrackEvents$ = new Observable(false);\nexport const shouldTrackTasks$ = new Observable(false);\n","\"use client\";\n\nimport {\n ConnectionEvent,\n EphemeralUserData,\n MultiplayerStateManager,\n MultiplayerUser,\n Task,\n} from \"@noya-app/state-manager\";\nimport React, { ComponentProps, useLayoutEffect } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nimport { Root } from \"react-dom/client\";\nimport { StateInspector } from \"./StateInspector\";\n\nfunction createPortalElement() {\n const el = document.createElement(\"div\");\n el.id = \"noya-multiplayer-react-inspector-portal\";\n return el;\n}\n\nexport function useStateInspector<S, M, E>({\n state,\n connectionEvents,\n connectedUsers,\n tasks,\n userId,\n disabled = false,\n colorScheme,\n anchor,\n multiplayerStateManager,\n ephemeralUserData,\n forceInit,\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n connectedUsers?: MultiplayerUser[];\n tasks?: Task[];\n userId?: string;\n disabled: boolean;\n multiplayerStateManager: MultiplayerStateManager<S, M>;\n ephemeralUserData: EphemeralUserData<E>;\n forceInit: () => void;\n} & Pick<ComponentProps<typeof StateInspector>, \"colorScheme\" | \"anchor\">) {\n const [root, setRoot] = React.useState<Root | null>(null);\n\n useLayoutEffect(() => {\n if (disabled) return;\n\n const portalElement = createPortalElement();\n\n const root = createRoot(portalElement);\n\n document.body.appendChild(portalElement);\n\n setRoot(root);\n\n return () => {\n document.body.removeChild(portalElement);\n };\n }, [disabled]);\n\n useLayoutEffect(() => {\n if (!root) return;\n\n root.render(\n <StateInspector\n state={state}\n connectionEvents={connectionEvents}\n connectedUsers={connectedUsers}\n tasks={tasks}\n userId={userId}\n colorScheme={colorScheme}\n anchor={anchor}\n forceInit={forceInit}\n multiplayerStateManager={\n multiplayerStateManager as MultiplayerStateManager<any, any>\n }\n ephemeralUserData={ephemeralUserData as EphemeralUserData<any>}\n />\n );\n }, [\n anchor,\n colorScheme,\n connectedUsers,\n connectionEvents,\n root,\n state,\n multiplayerStateManager,\n userId,\n tasks,\n forceInit,\n ephemeralUserData,\n ]);\n}\n","\"use client\";\n\nimport {\n ConnectionEvent,\n EphemeralUserData,\n ExtendedPathKey,\n MultiplayerStateManager,\n MultiplayerUser,\n Task,\n} from \"@noya-app/state-manager\";\nimport React, {\n CSSProperties,\n ComponentPropsWithoutRef,\n FC,\n memo,\n useEffect,\n useLayoutEffect,\n} from \"react\";\nimport {\n ObjectInspector,\n ObjectLabel,\n ObjectName,\n ObjectPreview,\n chromeDark,\n chromeLight,\n} from \"react-inspector\";\nimport { shouldTrackEvents$, shouldTrackTasks$ } from \"../globals\";\nimport { useEphemeralUserData, useManagedHistory } from \"../hooks\";\nimport { useLocalStorageState } from \"./useLocalStorageState\";\n\nconst lightTheme = {\n ...chromeLight,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(0,0,0,0.7)\",\n} as any;\n\nconst darkTheme = {\n ...chromeDark,\n BASE_BACKGROUND_COLOR: \"transparent\",\n OBJECT_NAME_COLOR: \"rgba(255,255,255,0.7)\",\n} as any;\n\nconst styles = {\n sectionInner: {\n flex: \"1 1 0\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n },\n} as const;\n\nfunction ToggleButton({\n showInspector,\n setShowInspector,\n theme,\n anchor,\n}: {\n showInspector: boolean;\n setShowInspector: (value: boolean) => void;\n theme: typeof chromeLight;\n anchor: StateInspectorAnchor;\n}) {\n return (\n <span\n role=\"button\"\n style={{\n flex: \"0\",\n appearance: \"none\",\n color: theme.BASE_COLOR,\n border: \"none\",\n fontSize: \"12px\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2px 0\",\n }}\n onClick={(event) => {\n event.stopPropagation();\n\n setShowInspector(!showInspector);\n }}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n {showInspector === (anchor === \"right\") ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\"\n />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-6\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\"\n />\n </svg>\n )}\n </span>\n </span>\n );\n}\n\nfunction DisclosureSection({\n open,\n setOpen,\n title,\n right,\n children,\n colorScheme,\n isFirst,\n style,\n}: {\n open: boolean;\n setOpen?: (value: boolean) => void;\n title: string;\n right?: React.ReactNode;\n children: React.ReactNode;\n colorScheme: \"light\" | \"dark\";\n isFirst?: boolean;\n style?: CSSProperties;\n}) {\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n\n const borderColor =\n colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n\n return (\n <div\n style={{\n flex: open ? \"1 1 0\" : \"0\",\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n >\n <div\n onClick={() => setOpen?.(!open)}\n style={{\n cursor: \"default\",\n fontSize: \"12px\",\n padding: \"4px 10px\",\n display: \"flex\",\n alignItems: \"center\",\n ...(!isFirst && { borderTop: `1px solid ${borderColor}` }),\n ...(open && { borderBottom: `1px solid ${borderColor}` }),\n }}\n >\n {setOpen && (\n <Arrow\n expanded={open}\n style={{\n fontSize: theme.ARROW_FONT_SIZE,\n marginRight: theme.ARROW_MARGIN_RIGHT + 1,\n color: theme.ARROW_COLOR,\n }}\n />\n )}\n <span style={{ flex: \"1 1 0\", userSelect: \"none\" }}>{title}</span>\n {right}\n </div>\n {open && children}\n </div>\n );\n}\n\nfunction InspectorRow({\n children,\n colorScheme,\n selected,\n style,\n variant,\n}: {\n children: React.ReactNode;\n colorScheme: \"light\" | \"dark\";\n selected?: boolean;\n style?: CSSProperties;\n variant?: \"up\" | \"down\";\n}) {\n const solidBorderColor =\n colorScheme === \"light\" ? \"rgb(223 223 223)\" : \"rgb(29 29 29)\";\n\n return (\n <div\n style={{\n borderBottom: `1px solid ${solidBorderColor}`,\n fontSize: \"12px\",\n fontFamily: \"Menlo, monospace\",\n padding: \"2px 12px 1px\",\n display: \"flex\",\n alignItems: \"center\",\n background:\n variant === \"up\"\n ? \"rgba(0,255,0,0.1)\"\n : variant === \"down\"\n ? \"rgba(255,0,0,0.1)\"\n : selected\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n // background:\n // colorScheme === \"light\"\n // ? \"rgba(0,0,0,0.05)\"\n // : \"rgba(255,255,255,0.05)\",\n ...style,\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n {children}\n </span>\n </div>\n );\n}\n\nconst HISTORY_ELEMENT_PREFIX = \"noya-multiplayer-history-\";\n\nexport type StateInspectorAnchor =\n | \"left\"\n | \"right\"\n | \"bottom left\"\n | \"bottom right\";\n\nexport type StateInspectorOptions = {\n colorScheme?: \"light\" | \"dark\";\n anchor?: StateInspectorAnchor;\n};\n\nexport const StateInspector = memo(function StateInspector<S, M, E>({\n state,\n connectionEvents,\n connectedUsers,\n tasks,\n userId,\n unstyled,\n colorScheme = \"light\",\n multiplayerStateManager,\n ephemeralUserData,\n anchor = \"right\",\n forceInit,\n ...props\n}: {\n state: S;\n connectionEvents?: ConnectionEvent<S>[];\n connectedUsers?: MultiplayerUser[];\n tasks?: Task[];\n userId?: string;\n unstyled?: boolean;\n multiplayerStateManager: MultiplayerStateManager<S, M>;\n ephemeralUserData: EphemeralUserData<E>;\n forceInit: () => void;\n} & StateInspectorOptions &\n ComponentPropsWithoutRef<\"div\">) {\n const [didMount, setDidMount] = React.useState(false);\n\n useLayoutEffect(() => {\n setDidMount(true);\n }, []);\n\n const eventsContainerRef = React.useRef<HTMLDivElement>(null);\n const historyContainerRef = React.useRef<HTMLDivElement>(null);\n\n const [showInspector, setShowInspector] = useLocalStorageState(\n \"noya-multiplayer-react-show-inspector\",\n true\n );\n const [showEvents, setShowEvents] = useLocalStorageState(\n \"noya-multiplayer-react-show-events\",\n false\n );\n const [showHistory, setShowHistory] = useLocalStorageState(\n \"noya-multiplayer-react-show-history\",\n false\n );\n const [showUsers, setShowUsers] = useLocalStorageState(\n \"noya-multiplayer-react-show-users\",\n true\n );\n const [showData, setShowData] = useLocalStorageState(\n \"noya-multiplayer-react-show-data\",\n true\n );\n const [showTasks, setShowTasks] = useLocalStorageState(\n \"noya-multiplayer-react-show-tasks\",\n false\n );\n const [showEphemeral, setShowEphemeral] = useLocalStorageState(\n \"noya-multiplayer-react-show-ephemeral\",\n false\n );\n\n useEffect(() => {\n shouldTrackEvents$.set(showEvents);\n }, [showEvents]);\n\n useEffect(() => {\n shouldTrackTasks$.set(showTasks);\n }, [showTasks]);\n\n useEffect(() => {\n if (eventsContainerRef.current) {\n eventsContainerRef.current.scrollTop =\n eventsContainerRef.current.scrollHeight;\n }\n }, [connectionEvents]);\n\n const ephemeral = useEphemeralUserData(ephemeralUserData);\n const historySnapshot = useManagedHistory(multiplayerStateManager.sm);\n\n useEffect(() => {\n if (historyContainerRef.current) {\n historyContainerRef.current.scrollTop =\n historyContainerRef.current.scrollHeight;\n }\n }, [historySnapshot]);\n\n // If history index changes, scroll to the new history entry into view\n useEffect(() => {\n if (!historyContainerRef.current) return;\n\n const historyEntry = historyContainerRef.current.querySelector(\n `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`\n );\n\n if (historyEntry) {\n historyEntry.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n }\n }, [historySnapshot.historyIndex]);\n\n const theme = colorScheme === \"light\" ? lightTheme : darkTheme;\n // const borderColor =\n // colorScheme === \"light\" ? \"rgba(0,0,0,0.1)\" : \"rgba(255,255,255,0.1)\";\n const solidBorderColor =\n colorScheme === \"light\" ? \"rgb(223 223 223)\" : \"rgb(29 29 29)\";\n\n const baseStyle: CSSProperties = {\n position: \"fixed\",\n top: 12,\n ...(anchor.includes(\"right\") ? { right: 12 } : { left: 12 }),\n bottom: 12,\n width: 400,\n background:\n colorScheme === \"light\" ? \"rgba(255,255,255,0.95)\" : \"rgba(0,0,0,0.95)\",\n backdropFilter: \"blur(48px)\",\n border: `1px solid ${solidBorderColor}`,\n // outlineOffset: -1,\n borderRadius: 4,\n display: \"flex\",\n flexDirection: \"column\",\n // gap: 12,\n color: theme.BASE_COLOR,\n overflow: \"hidden\",\n zIndex: 9999,\n lineHeight: \"13px\",\n };\n\n if (!didMount) return null;\n\n if (!showInspector) {\n return (\n <div\n {...props}\n style={{\n ...baseStyle,\n padding: \"4px 10px\",\n width: undefined,\n ...(anchor.includes(\"bottom\")\n ? { bottom: 12, top: undefined }\n : { bottom: undefined }),\n }}\n onClick={() => setShowInspector(true)}\n >\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n anchor={anchor}\n />\n </div>\n );\n }\n\n return (\n <div\n {...props}\n style={{\n ...(!unstyled && baseStyle),\n ...props.style,\n }}\n >\n <DisclosureSection\n isFirst\n open={showUsers}\n setOpen={setShowUsers}\n title=\"Users\"\n colorScheme={colorScheme}\n style={{\n flex: \"0 0 auto\",\n maxHeight: \"200px\",\n }}\n right={\n <ToggleButton\n showInspector={showInspector}\n setShowInspector={setShowInspector}\n theme={theme}\n anchor={anchor}\n />\n }\n >\n <div style={{ ...styles.sectionInner, flex: \"0 0 auto\" }}>\n {connectedUsers?.map((user) => (\n <InspectorRow\n key={user.id}\n colorScheme={colorScheme}\n variant={user.id === userId ? \"up\" : undefined}\n >\n {user.image && (\n <img\n src={user.image}\n alt={user.name}\n style={{\n width: \"12px\",\n height: \"12px\",\n borderRadius: \"50%\",\n marginRight: \"4px\",\n display: \"inline-block\",\n position: \"relative\",\n top: \"-1px\",\n background: solidBorderColor,\n }}\n />\n )}\n {user.name} ({ellipsis(user.id.toString(), 8, \"middle\")})\n </InspectorRow>\n ))}\n {!connectedUsers && (\n <div\n style={{\n padding: \"12px\",\n fontSize: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n }}\n >\n <span>No connected users</span>\n </div>\n )}\n </div>\n </DisclosureSection>\n <DisclosureSection\n title=\"Data\"\n colorScheme={colorScheme}\n setOpen={setShowData}\n open={showData}\n right={\n <span\n style={{\n display: \"flex\",\n gap: \"4px\",\n }}\n >\n <SmallButton\n // disabled={!historySnapshot.canUndo}\n theme={theme}\n onClick={() => {\n forceInit();\n }}\n >\n Reset\n </SmallButton>\n </span>\n }\n >\n <div style={styles.sectionInner}>\n <InspectorRow colorScheme={colorScheme}>\n <ObjectInspector\n name={multiplayerStateManager.schema ? \"state\" : undefined}\n data={state}\n theme={theme}\n />\n </InspectorRow>\n {multiplayerStateManager.schema && (\n <InspectorRow colorScheme={colorScheme}>\n <ObjectInspector\n name=\"schema\"\n data={multiplayerStateManager.schema}\n theme={theme}\n />\n </InspectorRow>\n )}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showHistory}\n setOpen={setShowHistory}\n title=\"History\"\n colorScheme={colorScheme}\n right={\n <span\n style={{\n display: \"flex\",\n gap: \"4px\",\n }}\n >\n <SmallButton\n disabled={!historySnapshot.canUndo}\n theme={theme}\n onClick={() => {\n multiplayerStateManager.undo();\n }}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fill=\"currentColor\"\n 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\"\n />\n </svg>\n </span>\n </SmallButton>\n <SmallButton\n disabled={!historySnapshot.canRedo}\n theme={theme}\n onClick={() => {\n multiplayerStateManager.redo();\n }}\n >\n <span style={{ width: \"12px\", height: \"12px\" }}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fill=\"currentColor\"\n 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\"\n />\n </svg>\n </span>\n </SmallButton>\n </span>\n }\n >\n <div ref={historyContainerRef} style={styles.sectionInner}>\n <div\n id={`${HISTORY_ELEMENT_PREFIX}0`}\n style={{\n borderBottom: `1px solid ${solidBorderColor}`,\n fontSize: \"12px\",\n fontFamily: \"Menlo, monospace\",\n padding: \"2px 12px 1px\",\n display: \"flex\",\n alignItems: \"center\",\n background:\n historySnapshot.historyIndex === 0\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n <span\n style={{\n fontFamily: \"Menlo, monospace\",\n fontSize: \"11px\",\n borderRadius: 4,\n display: \"inline-block\",\n }}\n >\n Initial state\n </span>\n </div>\n {historySnapshot.history.map((entry, index) => (\n <div\n id={`${HISTORY_ELEMENT_PREFIX}${index + 1}`}\n key={index}\n style={{\n padding: \"0px 12px 1px\",\n borderBottom: `1px solid ${solidBorderColor}`,\n background:\n index + 1 === historySnapshot.historyIndex\n ? \"rgb(59 130 246 / 15%)\"\n : undefined,\n }}\n >\n {\"name\" in entry.metadata &&\n typeof entry.metadata.name === \"string\" && (\n <pre\n style={{\n fontSize: \"11px\",\n display: \"flex\",\n flexWrap: \"wrap\",\n }}\n >\n {entry.metadata.name}\n </pre>\n )}\n {entry.redoPatches?.map((patch, j) => (\n <pre\n key={j}\n style={{\n fontSize: \"11px\",\n display: \"flex\",\n flexWrap: \"wrap\",\n }}\n >\n {patch.op === \"add\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"replace\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n {\" = \"}\n <ObjectInspector data={patch.value} theme={theme} />\n </>\n )}\n {patch.op === \"remove\" && (\n <>\n <span style={{ color: theme.OBJECT_VALUE_STRING_COLOR }}>\n delete{\" \"}\n </span>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n </>\n )}\n {patch.op === \"move\" && (\n <>\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.from!)}\n </span>\n {\" -> \"}\n <span style={{ fontStyle: \"italic\" }}>\n {pathToString(patch.path)}\n </span>\n </>\n )}\n </pre>\n ))}\n </div>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n title=\"Tasks\"\n colorScheme={colorScheme}\n open={showTasks}\n setOpen={setShowTasks}\n >\n <div style={styles.sectionInner}>\n {tasks?.map((task) => (\n <InspectorRow\n key={task.id}\n colorScheme={colorScheme}\n style={{\n backgroundColor:\n task.status === \"done\"\n ? \"rgba(0,255,0,0.2)\"\n : task.status === \"error\"\n ? \"rgba(255,0,0,0.2)\"\n : undefined,\n }}\n >\n <ObjectInspector\n name={task.name}\n data={task.payload}\n theme={theme}\n />\n </InspectorRow>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showEphemeral}\n setOpen={setShowEphemeral}\n title=\"Ephemeral User Data\"\n colorScheme={colorScheme}\n >\n <div style={styles.sectionInner}>\n {Object.entries(ephemeral).map(([key, value]) => (\n <InspectorRow key={key} colorScheme={colorScheme}>\n <ObjectInspector\n name={key}\n data={value}\n theme={theme}\n expandLevel={10}\n />\n </InspectorRow>\n ))}\n </div>\n </DisclosureSection>\n <DisclosureSection\n open={showEvents}\n setOpen={setShowEvents}\n title=\"Events\"\n colorScheme={colorScheme}\n >\n <div ref={eventsContainerRef} style={styles.sectionInner}>\n {connectionEvents?.map((event, index) =>\n event.type === \"stateChange\" ? (\n <InspectorRow key={index} colorScheme={colorScheme}>\n connection:{\" \"}\n <span style={{ fontStyle: \"italic\" }}>\n {event.state.toLowerCase()}\n </span>\n </InspectorRow>\n ) : (\n <InspectorRow\n key={index}\n colorScheme={colorScheme}\n variant={event.type === \"send\" ? \"up\" : \"down\"}\n style={{\n padding: \"0px 12px 1px\",\n }}\n >\n <ObjectInspector\n data={event.type === \"error\" ? event.error : event.message}\n theme={theme}\n nodeRenderer={({\n depth,\n name,\n data,\n isNonenumerable,\n expanded,\n }: any) => {\n const direction = event.type === \"send\" ? \"up\" : \"down\";\n\n return depth === 0 ? (\n <ObjectRootLabel direction={direction} data={data} />\n ) : (\n <ObjectLabel\n direction={direction}\n name={name}\n data={data}\n isNonenumerable={isNonenumerable}\n />\n );\n }}\n />\n </InspectorRow>\n )\n )}\n {!connectionEvents && (\n <div\n style={{\n padding: \"12px\",\n fontSize: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n }}\n >\n <span>No recorded events</span>\n </div>\n )}\n </div>\n </DisclosureSection>\n </div>\n );\n});\n\ntype MessageDirection = \"up\" | \"down\";\n\nconst ObjectRootLabel: FC<{\n name?: string;\n data: any;\n direction?: MessageDirection;\n}> = ({ name, data, direction }) => {\n if (typeof name === \"string\") {\n return (\n <span>\n <ObjectName name={name} />\n <span>: </span>\n <ObjectPreview data={data} />\n </span>\n );\n }\n if (direction === \"up\" || direction === \"down\") {\n const arrow = direction === \"up\" ? \"↑\" : \"↓\";\n\n return (\n <span>\n <span\n style={{\n background:\n direction === \"up\" ? \"rgba(0,255,0,0.2)\" : \"rgba(255,0,0,0.2)\",\n // color: \"white\",\n width: 12,\n height: 12,\n borderRadius: 2,\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n marginRight: 4,\n lineHeight: \"12px\",\n }}\n >\n {arrow}\n </span>\n <ObjectPreview data={data} />\n </span>\n );\n } else {\n return <ObjectPreview data={data} />;\n }\n};\n\n// Rotates ▶️ or ▼ based on expanded state\nfunction Arrow({\n expanded,\n onClick,\n style,\n}: {\n expanded: boolean;\n onClick?: () => void;\n style?: CSSProperties;\n}) {\n return (\n <span\n role=\"button\"\n onClick={onClick}\n style={{\n display: \"inline-block\",\n textAlign: \"center\",\n transform: expanded ? \"rotate(0deg)\" : \"rotate(-90deg)\",\n fontFamily: \"Menlo, monospace\",\n ...style,\n }}\n >\n {\"▼\"}\n </span>\n );\n}\n\nfunction pathToString(extendedPath: ExtendedPathKey[]) {\n return extendedPath\n .map((key) =>\n typeof key === \"object\"\n ? `:${ellipsis(key.id.toString(), 8, \"middle\")}`\n : key\n )\n .map((key, index) =>\n index === 0 || (typeof key === \"string\" && key.startsWith(\":\"))\n ? key\n : `.${key}`\n )\n .join(\"\");\n}\n\ntype EllipsisPosition = \"start\" | \"middle\" | \"end\";\n\nfunction ellipsis(\n str: string,\n maxLength: number,\n position: EllipsisPosition = \"end\"\n) {\n if (str.length <= maxLength) return str;\n\n switch (position) {\n case \"start\":\n return `…${str.slice(str.length - maxLength)}`;\n case \"middle\":\n const halfLength = Math.floor(maxLength / 2);\n return `${str.slice(0, halfLength)}…${str.slice(str.length - halfLength)}`;\n case \"end\":\n return `${str.slice(0, maxLength)}…`;\n }\n}\n\nfunction SmallButton({\n children,\n onClick,\n style,\n theme,\n disabled,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n style?: CSSProperties;\n theme: typeof chromeLight;\n disabled?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={(event) => {\n event.stopPropagation();\n onClick();\n }}\n style={{\n flex: \"0\",\n appearance: \"none\",\n background: \"none\",\n color: theme.BASE_COLOR,\n opacity: disabled ? 0.25 : 1,\n border: \"none\",\n fontSize: \"12px\",\n whiteSpace: \"nowrap\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2px 0\",\n cursor: \"pointer\",\n ...style,\n }}\n >\n {children}\n </button>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\n\nconst localStorage = typeof window !== \"undefined\" ? window.localStorage : null;\n\nexport function useLocalStorageState<S>(\n key: string,\n defaultValue: S\n): [S, (value: S) => void] {\n const [state, setState] = React.useState<S>(() => {\n const value = localStorage?.getItem(key);\n let result = defaultValue;\n if (value) {\n try {\n result = JSON.parse(value);\n } catch (error) {\n console.error(\"Error parsing localStorage value\", error);\n }\n }\n return result;\n });\n\n const setLocalStorageState = (value: S) => {\n localStorage?.setItem(key, JSON.stringify(value));\n setState(value);\n };\n\n return [state, setLocalStorageState];\n}\n","/* eslint-disable no-restricted-globals */\nimport {\n createOrCastValue,\n findAllDefs,\n localStorageSync,\n MultiplayerUser,\n stubSync,\n SyncAdapter,\n TSchema,\n webSocketSync,\n} from \"@noya-app/state-manager\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useMultiplayerState, UseMultiplayerStateOptions } from \"./hooks\";\nimport { StateInspectorOptions } from \"./inspector/StateInspector\";\n\nexport type AppViewType = \"editable\" | \"readOnly\" | \"preview\";\n\nexport type AppTheme = \"light\" | \"dark\";\n\nexport type AppData<State> = {\n multiplayerUrl?: string;\n theme: AppTheme;\n viewType: AppViewType;\n initialState: State;\n inspector: boolean | StateInspectorOptions;\n};\n\nexport function createDefaultAppData<State>(\n initialState: State\n): AppData<State> {\n return {\n theme: \"light\",\n viewType: \"editable\",\n initialState,\n inspector: false,\n };\n}\n\nexport type GetAppDataOptions = {\n window?: { location: { hash: string } };\n overrideExistingState?: boolean;\n};\n\nexport function enforceSchema<State>(\n initialState: State,\n schema?: TSchema\n): State {\n return schema\n ? (createOrCastValue({\n schema,\n value: initialState,\n defs: findAllDefs(schema),\n }) as State)\n : initialState;\n}\n\nexport function parseAppDataParameter(\n options?: GetAppDataOptions\n): AppData<unknown> | null {\n const window = options?.window ?? globalThis;\n const urlHash = (window.location.hash || \"\").replace(/^#/, \"\");\n const params = new URLSearchParams(urlHash);\n const data = params.get(\"data\");\n if (!data) return null;\n try {\n return JSON.parse(data);\n } catch (e) {\n return null;\n }\n}\n\nexport function getAppData<State>(\n initialState: State | (() => State),\n schema?: TSchema,\n options?: GetAppDataOptions\n): AppData<State> {\n const resolvedInitialState =\n initialState instanceof Function ? initialState() : initialState;\n\n let appData =\n parseAppDataParameter(options) ??\n createDefaultAppData(resolvedInitialState);\n\n if (options?.overrideExistingState) {\n appData.initialState = resolvedInitialState;\n }\n\n appData.initialState = enforceSchema(appData.initialState, schema) as State;\n\n return appData as AppData<State>;\n}\n\nexport type IframeToHostMessage =\n | {\n type: \"application.setMenuItems\";\n payload: {\n menuItems: any[];\n };\n }\n | {\n type: \"multiplayer.setUsers\";\n payload: {\n users: any[];\n };\n };\n\nexport type HostToIframeMessage = {\n type: \"application.selectMenuItem\";\n payload: {\n value: string;\n };\n};\n\nexport function useBroadcastConnectedUsers(connectedUsers: MultiplayerUser[]) {\n useEffect(() => {\n if (!isEmbeddedApp()) return;\n\n const message: IframeToHostMessage = {\n type: \"multiplayer.setUsers\",\n payload: { users: connectedUsers },\n };\n\n parent?.postMessage(message, \"*\");\n }, [connectedUsers]);\n}\n\nexport function useBroadcastMenuItems<T>(\n menuItems: any[],\n handleSelectMenuItem: (value: T) => void\n) {\n useEffect(() => {\n if (!isEmbeddedApp()) return;\n\n const message: IframeToHostMessage = {\n type: \"application.setMenuItems\",\n payload: { menuItems },\n };\n\n parent?.postMessage(message, \"*\");\n\n const listener = (event: MessageEvent<HostToIframeMessage>) => {\n if (event.data.type === \"application.selectMenuItem\") {\n handleSelectMenuItem(event.data.payload.value as T);\n }\n };\n\n window.addEventListener(\"message\", listener);\n\n return () => {\n window.removeEventListener(\"message\", listener);\n };\n }, [handleSelectMenuItem, menuItems]);\n}\n\nexport function isEmbeddedApp() {\n return window.self !== window.top;\n}\n\nexport function useNoyaAppState<S, M = void, E = void>(\n initialState: S | (() => S),\n options?: UseMultiplayerStateOptions<S, M, E> & {\n localStorageKey?: string;\n }\n) {\n // Keep these stable after initial render\n const [\n {\n multiplayerUrl,\n inspector,\n initialState: noyaAppInitialState,\n theme,\n viewType,\n },\n ] = useState(() => {\n return getAppData(initialState, options?.schema, {\n overrideExistingState: options?.overrideExistingState,\n });\n });\n\n const sync = useMemo((): SyncAdapter<S, M, E> => {\n return multiplayerUrl\n ? webSocketSync(multiplayerUrl)\n : options?.localStorageKey\n ? localStorageSync({ key: options.localStorageKey })\n : stubSync();\n }, [multiplayerUrl, options?.localStorageKey]);\n\n const result = useMultiplayerState(noyaAppInitialState, {\n ...options,\n inspector: options?.inspector ?? inspector,\n sync: options?.sync ?? sync,\n });\n\n const [, , extras] = result;\n\n useBroadcastConnectedUsers(extras.connectedUsers);\n\n const mergedExtras = useMemo(() => {\n return { ...extras, theme, viewType } as const;\n }, [extras, theme, viewType]);\n\n return [result[0], result[1], mergedExtras] as const;\n}\n"],"mappings":"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","names":["UserPointer","import_react","listen","get","React","UserPointer","UserPointerContainer","UserNameTag","import_react","import_client","import_react","React","import_react","import_react","import_react","React","React","StateInspector","React","root","userId","tasks","state","import_state_manager","import_react","window"]}
package/dist/index.mjs CHANGED
@@ -1427,15 +1427,12 @@ function parseAppDataParameter(options) {
1427
1427
  }
1428
1428
  function getAppData(initialState, schema, options) {
1429
1429
  const resolvedInitialState = initialState instanceof Function ? initialState() : initialState;
1430
- try {
1431
- const appData = parseAppDataParameter(options) ?? createDefaultAppData(resolvedInitialState);
1432
- return {
1433
- ...appData,
1434
- initialState: enforceSchema(appData.initialState, schema)
1435
- };
1436
- } catch (e) {
1437
- return createDefaultAppData(enforceSchema(resolvedInitialState, schema));
1430
+ let appData = parseAppDataParameter(options) ?? createDefaultAppData(resolvedInitialState);
1431
+ if (options?.overrideExistingState) {
1432
+ appData.initialState = resolvedInitialState;
1438
1433
  }
1434
+ appData.initialState = enforceSchema(appData.initialState, schema);
1435
+ return appData;
1439
1436
  }
1440
1437
  function useBroadcastConnectedUsers(connectedUsers) {
1441
1438
  useEffect4(() => {
@@ -1481,7 +1478,9 @@ function useNoyaAppState(initialState, options) {
1481
1478
  viewType
1482
1479
  }
1483
1480
  ] = useState3(() => {
1484
- return getAppData(initialState, options?.schema);
1481
+ return getAppData(initialState, options?.schema, {
1482
+ overrideExistingState: options?.overrideExistingState
1483
+ });
1485
1484
  });
1486
1485
  const sync = useMemo4(() => {
1487
1486
  return multiplayerUrl ? webSocketSync(multiplayerUrl) : options?.localStorageKey ? localStorageSync({ key: options.localStorageKey }) : stubSync2();
@@ -1489,7 +1488,7 @@ function useNoyaAppState(initialState, options) {
1489
1488
  const result = useMultiplayerState(noyaAppInitialState, {
1490
1489
  ...options,
1491
1490
  inspector: options?.inspector ?? inspector,
1492
- sync
1491
+ sync: options?.sync ?? sync
1493
1492
  });
1494
1493
  const [, , extras] = result;
1495
1494
  useBroadcastConnectedUsers(extras.connectedUsers);