@noya-app/noya-multiplayer-react 0.1.38 → 0.1.39
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/.turbo/turbo-build.log +11 -12
- package/CHANGELOG.md +9 -0
- package/dist/index.bundle.js +7 -7
- package/dist/index.d.mts +52 -16
- package/dist/index.d.ts +52 -16
- package/dist/index.js +120 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/NoyaStateContext.tsx +218 -0
- package/src/__tests__/NoyaStateContext.test.ts +43 -0
- package/src/hooks.ts +12 -3
- package/src/index.ts +1 -0
- package/src/useObservable.ts +6 -6
package/dist/index.mjs
CHANGED
|
@@ -54,7 +54,7 @@ import React, { memo, useEffect, useMemo as useMemo2, useState } from "react";
|
|
|
54
54
|
import { useMemo, useSyncExternalStore } from "react";
|
|
55
55
|
function useObservable(observable, path) {
|
|
56
56
|
const { get, listen } = useMemo(() => {
|
|
57
|
-
const listen2 = path ? (callback) => observable.
|
|
57
|
+
const listen2 = path ? (callback) => observable.subscribe(path, callback) : observable.subscribe;
|
|
58
58
|
const get2 = path ? () => observable.get(path) : observable.get;
|
|
59
59
|
return { get: get2, listen: listen2 };
|
|
60
60
|
}, [observable, path]);
|
|
@@ -1349,6 +1349,7 @@ function useMultiplayerState(initialState, options) {
|
|
|
1349
1349
|
ephemeralUserData,
|
|
1350
1350
|
multiplayerStateManager,
|
|
1351
1351
|
assets,
|
|
1352
|
+
assetManager,
|
|
1352
1353
|
createAsset: assetManager.create,
|
|
1353
1354
|
deleteAsset: assetManager.delete
|
|
1354
1355
|
// evaluate: async (code: string) => {
|
|
@@ -1418,7 +1419,15 @@ function useMultiplayerState(initialState, options) {
|
|
|
1418
1419
|
const [unrecoverableError, setUnrecoverableError] = useState2();
|
|
1419
1420
|
useEffect3(() => {
|
|
1420
1421
|
return multiplayerStateManager.errorEmitter.addListener((error) => {
|
|
1421
|
-
|
|
1422
|
+
switch (error.reason) {
|
|
1423
|
+
case "invalidDataType":
|
|
1424
|
+
case "schemaMismatch":
|
|
1425
|
+
case "outdatedSchema":
|
|
1426
|
+
case "dataMigrationFailure":
|
|
1427
|
+
case "schemaMigration":
|
|
1428
|
+
setUnrecoverableError(error);
|
|
1429
|
+
break;
|
|
1430
|
+
}
|
|
1422
1431
|
});
|
|
1423
1432
|
}, [multiplayerStateManager]);
|
|
1424
1433
|
useEffect3(() => {
|
|
@@ -1564,6 +1573,112 @@ function useNoyaState(...args) {
|
|
|
1564
1573
|
}, [extras, theme, viewType]);
|
|
1565
1574
|
return [result[0], result[1], mergedExtras];
|
|
1566
1575
|
}
|
|
1576
|
+
|
|
1577
|
+
// src/NoyaStateContext.tsx
|
|
1578
|
+
import React6, {
|
|
1579
|
+
createContext,
|
|
1580
|
+
useCallback as useCallback2,
|
|
1581
|
+
useContext,
|
|
1582
|
+
useMemo as useMemo5
|
|
1583
|
+
} from "react";
|
|
1584
|
+
var AnyNoyaStateContext = createContext(void 0);
|
|
1585
|
+
function useAnyNoyaStateContext() {
|
|
1586
|
+
const value = useContext(AnyNoyaStateContext);
|
|
1587
|
+
if (!value) {
|
|
1588
|
+
throw new Error(
|
|
1589
|
+
"useNoyaStateContext must be used within a NoyaStateProvider"
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
return value;
|
|
1593
|
+
}
|
|
1594
|
+
function useAssets() {
|
|
1595
|
+
const { assetManager } = useAnyNoyaStateContext();
|
|
1596
|
+
return useObservable(assetManager.assets$);
|
|
1597
|
+
}
|
|
1598
|
+
function useAsset(id) {
|
|
1599
|
+
const { assetManager } = useAnyNoyaStateContext();
|
|
1600
|
+
const observable = useMemo5(
|
|
1601
|
+
() => assetManager.assets$.map((assets) => assets.find((a) => a.id === id)),
|
|
1602
|
+
[assetManager, id]
|
|
1603
|
+
);
|
|
1604
|
+
return useObservable(observable);
|
|
1605
|
+
}
|
|
1606
|
+
function useAssetManager() {
|
|
1607
|
+
const { assetManager } = useAnyNoyaStateContext();
|
|
1608
|
+
return useMemo5(
|
|
1609
|
+
() => ({
|
|
1610
|
+
create: assetManager.create,
|
|
1611
|
+
delete: assetManager.delete
|
|
1612
|
+
}),
|
|
1613
|
+
[assetManager]
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1616
|
+
function createNoyaContext({
|
|
1617
|
+
schema
|
|
1618
|
+
}) {
|
|
1619
|
+
const NoyaStateContext = AnyNoyaStateContext;
|
|
1620
|
+
function NoyaStateProvider({
|
|
1621
|
+
children,
|
|
1622
|
+
initialState,
|
|
1623
|
+
...options
|
|
1624
|
+
}) {
|
|
1625
|
+
const [, , { multiplayerStateManager, assetManager }] = useNoyaState(
|
|
1626
|
+
initialState,
|
|
1627
|
+
{
|
|
1628
|
+
...options,
|
|
1629
|
+
schema
|
|
1630
|
+
}
|
|
1631
|
+
);
|
|
1632
|
+
const value = useMemo5(
|
|
1633
|
+
() => ({
|
|
1634
|
+
ms: multiplayerStateManager,
|
|
1635
|
+
assetManager
|
|
1636
|
+
}),
|
|
1637
|
+
[multiplayerStateManager, assetManager]
|
|
1638
|
+
);
|
|
1639
|
+
return /* @__PURE__ */ React6.createElement(AnyNoyaStateContext.Provider, { value }, children);
|
|
1640
|
+
}
|
|
1641
|
+
function useValue(path, options) {
|
|
1642
|
+
const { ms } = useAnyNoyaStateContext();
|
|
1643
|
+
let actualPath = typeof path === "function" || !path ? "" : path;
|
|
1644
|
+
const mappedObservable = useMemo5(() => {
|
|
1645
|
+
if (typeof path === "function") {
|
|
1646
|
+
return ms.optimisticState$.map(path, { isEqual: options?.isEqual });
|
|
1647
|
+
}
|
|
1648
|
+
return ms.optimisticState$;
|
|
1649
|
+
}, [ms, path, options?.isEqual]);
|
|
1650
|
+
const value = useObservable(mappedObservable, actualPath);
|
|
1651
|
+
return value;
|
|
1652
|
+
}
|
|
1653
|
+
function useSetValue(path) {
|
|
1654
|
+
const { ms } = useAnyNoyaStateContext();
|
|
1655
|
+
const setValue = useCallback2(
|
|
1656
|
+
(...args) => {
|
|
1657
|
+
const [metadata, value] = args.length === 2 ? args : [void 0, args[0]];
|
|
1658
|
+
const setStateAtPath = ms.setStateAtPath;
|
|
1659
|
+
setStateAtPath(metadata, path ?? "", value);
|
|
1660
|
+
},
|
|
1661
|
+
[ms, path]
|
|
1662
|
+
);
|
|
1663
|
+
return setValue;
|
|
1664
|
+
}
|
|
1665
|
+
function useValueState(...args) {
|
|
1666
|
+
const [selector, options, path] = args.length >= 1 && typeof args[0] === "function" ? [args[0], args[1], void 0] : [void 0, void 0, args[0]];
|
|
1667
|
+
const value = useValue(selector ?? path ?? "", options);
|
|
1668
|
+
const setValue = useSetValue(path ?? "");
|
|
1669
|
+
return [value, setValue];
|
|
1670
|
+
}
|
|
1671
|
+
return {
|
|
1672
|
+
Context: NoyaStateContext,
|
|
1673
|
+
Provider: NoyaStateProvider,
|
|
1674
|
+
useValue,
|
|
1675
|
+
useSetValue,
|
|
1676
|
+
useValueState
|
|
1677
|
+
// useAssets,
|
|
1678
|
+
// useAssetManager,
|
|
1679
|
+
// useAsset,
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1567
1682
|
export {
|
|
1568
1683
|
StateInspector,
|
|
1569
1684
|
UserNameTag,
|
|
@@ -1572,12 +1687,16 @@ export {
|
|
|
1572
1687
|
UserPointerIcon,
|
|
1573
1688
|
UserPointersOverlay,
|
|
1574
1689
|
createDefaultAppData,
|
|
1690
|
+
createNoyaContext,
|
|
1575
1691
|
enforceSchema,
|
|
1576
1692
|
getAppData,
|
|
1577
1693
|
getAvatarInitials,
|
|
1578
1694
|
getAvatarStyle,
|
|
1579
1695
|
isEmbeddedApp,
|
|
1580
1696
|
parseAppDataParameter,
|
|
1697
|
+
useAsset,
|
|
1698
|
+
useAssetManager,
|
|
1699
|
+
useAssets,
|
|
1581
1700
|
useBroadcastConnectedUsers,
|
|
1582
1701
|
useBroadcastMenuItems,
|
|
1583
1702
|
useEphemeralUserData,
|