@device-portal/react 0.1.2 → 0.2.0

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/README.md CHANGED
@@ -81,6 +81,42 @@ const ConsumerComponent = () => {
81
81
  }
82
82
  ```
83
83
 
84
+ ### Public rooms (lobby)
85
+
86
+ A provider can list its room under a `group`; `useGroupRooms` subscribes to the
87
+ live list of such rooms — enough for a lobby of public game servers. Each entry
88
+ carries the number of connected `clients`, the provider's `maxClients` and the
89
+ `meta` JSON the provider published.
90
+
91
+ ```jsx
92
+ import { useDevicePortalProvider, useGroupRooms } from '@device-portal/react'
93
+
94
+ const GameHost = () => {
95
+ useDevicePortalProvider('arena-42', {
96
+ value: 'welcome',
97
+ group: 'my-game',
98
+ meta: { name: 'Arena' },
99
+ maxClients: 4,
100
+ })
101
+ return <h1>Hosting Arena</h1>
102
+ }
103
+
104
+ const Lobby = ({ onJoin }) => {
105
+ const { rooms, isConnected } = useGroupRooms('my-game')
106
+ if (rooms === null) return <p>Loading…</p>
107
+ return (
108
+ <ul>
109
+ {rooms.map(({ room, clients, maxClients, meta }) => (
110
+ <li key={room}>
111
+ {meta?.name ?? room} — {clients}/{maxClients ?? '∞'}{' '}
112
+ <button onClick={() => onJoin(room)}>Join</button>
113
+ </li>
114
+ ))}
115
+ </ul>
116
+ )
117
+ }
118
+ ```
119
+
84
120
  ### Per-peer Values
85
121
 
86
122
  Instead of broadcasting the same value to all consumers, you can pass a function that returns a different value for each peer:
package/dist/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from './provider/useDevicePortalProvider';
3
3
  export * from './provider/useDevicePortalPeer';
4
4
  export * from './consumer/DevicePortalConsumer';
5
5
  export * from './consumer/useDevicePortalConsumer';
6
- export { type PeerId, type Host } from '@device-portal/client';
6
+ export * from './useGroupRooms';
7
+ export { type GroupRoom, type PeerId, type Host, type WebRtcOption, } from '@device-portal/client';
package/dist/index.js CHANGED
@@ -3,4 +3,5 @@ export { useDevicePortalProvider } from './provider/useDevicePortalProvider.js';
3
3
  export { useDevicePortalPeer } from './provider/useDevicePortalPeer.js';
4
4
  export { DevicePortalConsumer } from './consumer/DevicePortalConsumer.js';
5
5
  export { useDevicePortalConsumer } from './consumer/useDevicePortalConsumer.js';
6
+ export { useGroupRooms } from './useGroupRooms.js';
6
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
@@ -15,6 +15,13 @@ export type DevicePortalProviderOptions = {
15
15
  maxClients?: number;
16
16
  /** Browser direct signaling options. */
17
17
  browserDirect?: BrowserDirectOption;
18
+ /** Lists the room under this group on the signaling server for `useGroupRooms`. */
19
+ group?: string;
20
+ /**
21
+ * Arbitrary JSON published with the group listing, e.g. a game name. Kept
22
+ * under 1 kB. Changes are pushed to the listing without reconnecting.
23
+ */
24
+ meta?: unknown;
18
25
  };
19
26
  /**
20
27
  * A React hook that creates a Device Portal room and shares a value with all joining consumers.
@@ -10,7 +10,7 @@ import { useState, useRef, useEffect } from 'react';
10
10
  * @returns An object containing the list of connected peers and the underlying Provider instance.
11
11
  */
12
12
  var useDevicePortalProvider = function useDevicePortalProvider(room) {
13
- var _options$sendLastValu;
13
+ var _options$sendLastValu, _JSON$stringify;
14
14
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
15
15
  var _useState = useState(null),
16
16
  _useState2 = _slicedToArray(_useState, 2),
@@ -27,6 +27,10 @@ var useDevicePortalProvider = function useDevicePortalProvider(room) {
27
27
  var sendLastValueOnConnectAndReconnect = (_options$sendLastValu = options.sendLastValueOnConnectAndReconnect) !== null && _options$sendLastValu !== void 0 ? _options$sendLastValu : true;
28
28
  var valueRef = useRef(options.value);
29
29
  valueRef.current = options.value;
30
+ // Compared by content so an inline object literal does not re-send meta.
31
+ var metaKey = (_JSON$stringify = JSON.stringify(options.meta)) !== null && _JSON$stringify !== void 0 ? _JSON$stringify : '';
32
+ var metaRef = useRef(options.meta);
33
+ metaRef.current = options.meta;
30
34
  useEffect(function () {
31
35
  var newProvider = new Host(room, {
32
36
  onMessage: function onMessage(value, peerId) {
@@ -45,6 +49,8 @@ var useDevicePortalProvider = function useDevicePortalProvider(room) {
45
49
  webSocketSignalingServer: options.webSocketSignalingServer,
46
50
  maxClients: options.maxClients,
47
51
  browserDirect: options.browserDirect,
52
+ group: options.group,
53
+ meta: metaRef.current,
48
54
  peerId: peerIdRef.current
49
55
  });
50
56
  setProvider(newProvider);
@@ -54,7 +60,10 @@ var useDevicePortalProvider = function useDevicePortalProvider(room) {
54
60
  setProvider(null);
55
61
  setPeers([]);
56
62
  };
57
- }, [room, sendLastValueOnConnectAndReconnect, options.webSocketSignalingServer, options.maxClients, options.browserDirect]);
63
+ }, [room, sendLastValueOnConnectAndReconnect, options.webSocketSignalingServer, options.maxClients, options.browserDirect, options.group]);
64
+ useEffect(function () {
65
+ provider === null || provider === void 0 || provider.setMeta(metaRef.current);
66
+ }, [metaKey, provider]);
58
67
  useEffect(function () {
59
68
  if (options.value === undefined || !provider) return;
60
69
  if (typeof options.value === 'function') {
@@ -1 +1 @@
1
- {"version":3,"file":"useDevicePortalProvider.js","sources":["../../src/provider/useDevicePortalProvider.ts"],"sourcesContent":["import {\n\tHost,\n\tgeneratePeerId,\n\ttype BrowserDirectOption,\n\ttype PeerId,\n} from '@device-portal/client'\nimport { useEffect, useRef, useState } from 'react'\n\n// @TODO: warn if one room is used by multiple useDevicePortalProvider hooks more than once at the same time\n\n/**\n * Configuration options for the Device Portal Provider.\n */\nexport type DevicePortalProviderOptions = {\n\t/** The value to share with connected consumers. A function receives the peerId and can return a per-peer value. */\n\tvalue?: string | ((peerId: PeerId) => string)\n\t/** URL of the signaling server, or null to disable. */\n\twebSocketSignalingServer?: string | null\n\t/** Callback when a consumer sends a message back to the provider. */\n\tonMessageFromConsumer?: (value: string, peerId: PeerId) => void\n\t/** Whether to automatically send the last 'value' to new consumers. Default: true. */\n\tsendLastValueOnConnectAndReconnect?: boolean\n\t/** Maximum number of concurrent consumer connections. Default: 1. */\n\tmaxClients?: number\n\t/** Browser direct signaling options. */\n\tbrowserDirect?: BrowserDirectOption\n}\n\n/**\n * A React hook that creates a Device Portal room and shares a value with all joining consumers.\n *\n * @param room - The unique room ID.\n * @param options - Provider configuration options.\n * @returns An object containing the list of connected peers and the underlying Provider instance.\n */\nexport const useDevicePortalProvider = (\n\troom: string,\n\toptions: DevicePortalProviderOptions = {},\n) => {\n\tconst [provider, setProvider] = useState<Host | null>(null)\n\tconst [peers, setPeers] = useState<PeerId[]>([])\n\tconst onMessageFromConsumerRef = useRef(options.onMessageFromConsumer)\n\tonMessageFromConsumerRef.current = options.onMessageFromConsumer\n\t// Stable peer ID that survives React Strict Mode unmount/remount cycles\n\tconst peerIdRef = useRef<PeerId>(generatePeerId())\n\tconst sendLastValueOnConnectAndReconnect =\n\t\toptions.sendLastValueOnConnectAndReconnect ?? true\n\n\tconst valueRef = useRef(options.value)\n\tvalueRef.current = options.value\n\n\tuseEffect(() => {\n\t\tconst newProvider = new Host(room, {\n\t\t\tonMessage: (value, peerId) => {\n\t\t\t\tonMessageFromConsumerRef.current?.(value, peerId)\n\t\t\t},\n\t\t\tonPeersChange: (peers) => {\n\t\t\t\tsetPeers(peers)\n\t\t\t},\n\t\t\tonPeerConnected: (peerId) => {\n\t\t\t\tif (!sendLastValueOnConnectAndReconnect) return\n\t\t\t\tconst v = valueRef.current\n\t\t\t\tif (v === undefined) return\n\t\t\t\tnewProvider.sendToPeer(peerId, typeof v === 'function' ? v(peerId) : v)\n\t\t\t},\n\t\t\twebSocketSignalingServer: options.webSocketSignalingServer,\n\t\t\tmaxClients: options.maxClients,\n\t\t\tbrowserDirect: options.browserDirect,\n\t\t\tpeerId: peerIdRef.current,\n\t\t})\n\t\tsetProvider(newProvider)\n\t\tsetPeers(newProvider.peers)\n\n\t\treturn () => {\n\t\t\tnewProvider.destroy()\n\t\t\tsetProvider(null)\n\t\t\tsetPeers([])\n\t\t}\n\t}, [\n\t\troom,\n\t\tsendLastValueOnConnectAndReconnect,\n\t\toptions.webSocketSignalingServer,\n\t\toptions.maxClients,\n\t\toptions.browserDirect,\n\t])\n\n\tuseEffect(() => {\n\t\tif (options.value === undefined || !provider) return\n\t\tif (typeof options.value === 'function') {\n\t\t\tconst fn = options.value\n\t\t\tfor (const peerId of provider.peers) {\n\t\t\t\tprovider.sendToPeer(peerId, fn(peerId))\n\t\t\t}\n\t\t} else {\n\t\t\tprovider.send(options.value)\n\t\t}\n\t}, [options.value, provider])\n\n\treturn { peers, provider }\n}\n"],"names":["useDevicePortalProvider","room","_options$sendLastValu","options","arguments","length","undefined","_useState","useState","_useState2","_slicedToArray","provider","setProvider","_useState3","_useState4","peers","setPeers","onMessageFromConsumerRef","useRef","onMessageFromConsumer","current","peerIdRef","generatePeerId","sendLastValueOnConnectAndReconnect","valueRef","value","useEffect","newProvider","Host","onMessage","peerId","_onMessageFromConsume","call","onPeersChange","onPeerConnected","v","sendToPeer","webSocketSignalingServer","maxClients","browserDirect","destroy","fn","_iterator","_createForOfIteratorHelper","_step","s","n","done","err","e","f","send"],"mappings":"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"}
1
+ {"version":3,"file":"useDevicePortalProvider.js","sources":["../../src/provider/useDevicePortalProvider.ts"],"sourcesContent":["import {\n\tHost,\n\tgeneratePeerId,\n\ttype BrowserDirectOption,\n\ttype PeerId,\n} from '@device-portal/client'\nimport { useEffect, useRef, useState } from 'react'\n\n// @TODO: warn if one room is used by multiple useDevicePortalProvider hooks more than once at the same time\n\n/**\n * Configuration options for the Device Portal Provider.\n */\nexport type DevicePortalProviderOptions = {\n\t/** The value to share with connected consumers. A function receives the peerId and can return a per-peer value. */\n\tvalue?: string | ((peerId: PeerId) => string)\n\t/** URL of the signaling server, or null to disable. */\n\twebSocketSignalingServer?: string | null\n\t/** Callback when a consumer sends a message back to the provider. */\n\tonMessageFromConsumer?: (value: string, peerId: PeerId) => void\n\t/** Whether to automatically send the last 'value' to new consumers. Default: true. */\n\tsendLastValueOnConnectAndReconnect?: boolean\n\t/** Maximum number of concurrent consumer connections. Default: 1. */\n\tmaxClients?: number\n\t/** Browser direct signaling options. */\n\tbrowserDirect?: BrowserDirectOption\n\t/** Lists the room under this group on the signaling server for `useGroupRooms`. */\n\tgroup?: string\n\t/**\n\t * Arbitrary JSON published with the group listing, e.g. a game name. Kept\n\t * under 1 kB. Changes are pushed to the listing without reconnecting.\n\t */\n\tmeta?: unknown\n}\n\n/**\n * A React hook that creates a Device Portal room and shares a value with all joining consumers.\n *\n * @param room - The unique room ID.\n * @param options - Provider configuration options.\n * @returns An object containing the list of connected peers and the underlying Provider instance.\n */\nexport const useDevicePortalProvider = (\n\troom: string,\n\toptions: DevicePortalProviderOptions = {},\n) => {\n\tconst [provider, setProvider] = useState<Host | null>(null)\n\tconst [peers, setPeers] = useState<PeerId[]>([])\n\tconst onMessageFromConsumerRef = useRef(options.onMessageFromConsumer)\n\tonMessageFromConsumerRef.current = options.onMessageFromConsumer\n\t// Stable peer ID that survives React Strict Mode unmount/remount cycles\n\tconst peerIdRef = useRef<PeerId>(generatePeerId())\n\tconst sendLastValueOnConnectAndReconnect =\n\t\toptions.sendLastValueOnConnectAndReconnect ?? true\n\n\tconst valueRef = useRef(options.value)\n\tvalueRef.current = options.value\n\t// Compared by content so an inline object literal does not re-send meta.\n\tconst metaKey = JSON.stringify(options.meta) ?? ''\n\tconst metaRef = useRef(options.meta)\n\tmetaRef.current = options.meta\n\n\tuseEffect(() => {\n\t\tconst newProvider = new Host(room, {\n\t\t\tonMessage: (value, peerId) => {\n\t\t\t\tonMessageFromConsumerRef.current?.(value, peerId)\n\t\t\t},\n\t\t\tonPeersChange: (peers) => {\n\t\t\t\tsetPeers(peers)\n\t\t\t},\n\t\t\tonPeerConnected: (peerId) => {\n\t\t\t\tif (!sendLastValueOnConnectAndReconnect) return\n\t\t\t\tconst v = valueRef.current\n\t\t\t\tif (v === undefined) return\n\t\t\t\tnewProvider.sendToPeer(peerId, typeof v === 'function' ? v(peerId) : v)\n\t\t\t},\n\t\t\twebSocketSignalingServer: options.webSocketSignalingServer,\n\t\t\tmaxClients: options.maxClients,\n\t\t\tbrowserDirect: options.browserDirect,\n\t\t\tgroup: options.group,\n\t\t\tmeta: metaRef.current,\n\t\t\tpeerId: peerIdRef.current,\n\t\t})\n\t\tsetProvider(newProvider)\n\t\tsetPeers(newProvider.peers)\n\n\t\treturn () => {\n\t\t\tnewProvider.destroy()\n\t\t\tsetProvider(null)\n\t\t\tsetPeers([])\n\t\t}\n\t}, [\n\t\troom,\n\t\tsendLastValueOnConnectAndReconnect,\n\t\toptions.webSocketSignalingServer,\n\t\toptions.maxClients,\n\t\toptions.browserDirect,\n\t\toptions.group,\n\t])\n\n\tuseEffect(() => {\n\t\tprovider?.setMeta(metaRef.current)\n\t}, [metaKey, provider])\n\n\tuseEffect(() => {\n\t\tif (options.value === undefined || !provider) return\n\t\tif (typeof options.value === 'function') {\n\t\t\tconst fn = options.value\n\t\t\tfor (const peerId of provider.peers) {\n\t\t\t\tprovider.sendToPeer(peerId, fn(peerId))\n\t\t\t}\n\t\t} else {\n\t\t\tprovider.send(options.value)\n\t\t}\n\t}, [options.value, provider])\n\n\treturn { peers, provider }\n}\n"],"names":["useDevicePortalProvider","room","_options$sendLastValu","_JSON$stringify","options","arguments","length","undefined","_useState","useState","_useState2","_slicedToArray","provider","setProvider","_useState3","_useState4","peers","setPeers","onMessageFromConsumerRef","useRef","onMessageFromConsumer","current","peerIdRef","generatePeerId","sendLastValueOnConnectAndReconnect","valueRef","value","metaKey","JSON","stringify","meta","metaRef","useEffect","newProvider","Host","onMessage","peerId","_onMessageFromConsume","call","onPeersChange","onPeerConnected","v","sendToPeer","webSocketSignalingServer","maxClients","browserDirect","group","destroy","setMeta","fn","_iterator","_createForOfIteratorHelper","_step","s","n","done","err","e","f","send"],"mappings":";;;;AAmCA;;;;;;AAMG;IACUA,uBAAuB,GAAG,SAA1BA,uBAAuBA,CACnCC,IAAY,EAET;EAAA,IAAAC,qBAAA,EAAAC,eAAA;AAAA,EAAA,IADHC,OAAA,GAAAC,SAAA,CAAAC,MAAA,GAAA,CAAA,IAAAD,SAAA,CAAA,CAAA,CAAA,KAAAE,SAAA,GAAAF,SAAA,CAAA,CAAA,CAAA,GAAuC,EAAE;AAEzC,EAAA,IAAAG,SAAA,GAAgCC,QAAQ,CAAc,IAAI,CAAC;IAAAC,UAAA,GAAAC,cAAA,CAAAH,SAAA,EAAA,CAAA,CAAA;AAApDI,IAAAA,QAAQ,GAAAF,UAAA,CAAA,CAAA,CAAA;AAAEG,IAAAA,WAAW,GAAAH,UAAA,CAAA,CAAA,CAAA;AAC5B,EAAA,IAAAI,UAAA,GAA0BL,QAAQ,CAAW,EAAE,CAAC;IAAAM,UAAA,GAAAJ,cAAA,CAAAG,UAAA,EAAA,CAAA,CAAA;AAAzCE,IAAAA,KAAK,GAAAD,UAAA,CAAA,CAAA,CAAA;AAAEE,IAAAA,QAAQ,GAAAF,UAAA,CAAA,CAAA,CAAA;AACtB,EAAA,IAAMG,wBAAwB,GAAGC,MAAM,CAACf,OAAO,CAACgB,qBAAqB,CAAC;AACtEF,EAAAA,wBAAwB,CAACG,OAAO,GAAGjB,OAAO,CAACgB,qBAAqB;AAChE;AACA,EAAA,IAAME,SAAS,GAAGH,MAAM,CAASI,cAAc,EAAE,CAAC;AAClD,EAAA,IAAMC,kCAAkC,GAAA,CAAAtB,qBAAA,GACvCE,OAAO,CAACoB,kCAAkC,MAAA,IAAA,IAAAtB,qBAAA,KAAA,MAAA,GAAAA,qBAAA,GAAI,IAAI;AAEnD,EAAA,IAAMuB,QAAQ,GAAGN,MAAM,CAACf,OAAO,CAACsB,KAAK,CAAC;AACtCD,EAAAA,QAAQ,CAACJ,OAAO,GAAGjB,OAAO,CAACsB,KAAK;AAChC;AACA,EAAA,IAAMC,OAAO,GAAAxB,CAAAA,eAAA,GAAGyB,IAAI,CAACC,SAAS,CAACzB,OAAO,CAAC0B,IAAI,CAAC,MAAA,IAAA,IAAA3B,eAAA,KAAAA,MAAAA,GAAAA,eAAA,GAAI,EAAE;AAClD,EAAA,IAAM4B,OAAO,GAAGZ,MAAM,CAACf,OAAO,CAAC0B,IAAI,CAAC;AACpCC,EAAAA,OAAO,CAACV,OAAO,GAAGjB,OAAO,CAAC0B,IAAI;AAE9BE,EAAAA,SAAS,CAAC,YAAK;AACd,IAAA,IAAMC,WAAW,GAAG,IAAIC,IAAI,CAACjC,IAAI,EAAE;AAClCkC,MAAAA,SAAS,EAAE,SAAXA,SAASA,CAAGT,KAAK,EAAEU,MAAM,EAAI;AAAA,QAAA,IAAAC,qBAAA;AAC5B,QAAA,CAAAA,qBAAA,GAAAnB,wBAAwB,CAACG,OAAO,cAAAgB,qBAAA,KAAA,MAAA,IAAhCA,qBAAA,CAAAC,IAAA,CAAApB,wBAAwB,EAAWQ,KAAK,EAAEU,MAAM,CAAC;OACjD;AACDG,MAAAA,aAAa,EAAE,SAAfA,aAAaA,CAAGvB,OAAK,EAAI;QACxBC,QAAQ,CAACD,OAAK,CAAC;OACf;AACDwB,MAAAA,eAAe,EAAE,SAAjBA,eAAeA,CAAGJ,QAAM,EAAI;QAC3B,IAAI,CAACZ,kCAAkC,EAAE;AACzC,QAAA,IAAMiB,CAAC,GAAGhB,QAAQ,CAACJ,OAAO;QAC1B,IAAIoB,CAAC,KAAKlC,SAAS,EAAE;AACrB0B,QAAAA,WAAW,CAACS,UAAU,CAACN,QAAM,EAAE,OAAOK,CAAC,KAAK,UAAU,GAAGA,CAAC,CAACL,QAAM,CAAC,GAAGK,CAAC,CAAC;OACvE;MACDE,wBAAwB,EAAEvC,OAAO,CAACuC,wBAAwB;MAC1DC,UAAU,EAAExC,OAAO,CAACwC,UAAU;MAC9BC,aAAa,EAAEzC,OAAO,CAACyC,aAAa;MACpCC,KAAK,EAAE1C,OAAO,CAAC0C,KAAK;MACpBhB,IAAI,EAAEC,OAAO,CAACV,OAAO;MACrBe,MAAM,EAAEd,SAAS,CAACD;AAClB,KAAA,CAAC;IACFR,WAAW,CAACoB,WAAW,CAAC;AACxBhB,IAAAA,QAAQ,CAACgB,WAAW,CAACjB,KAAK,CAAC;AAE3B,IAAA,OAAO,YAAK;MACXiB,WAAW,CAACc,OAAO,EAAE;MACrBlC,WAAW,CAAC,IAAI,CAAC;MACjBI,QAAQ,CAAC,EAAE,CAAC;KACZ;GACD,EAAE,CACFhB,IAAI,EACJuB,kCAAkC,EAClCpB,OAAO,CAACuC,wBAAwB,EAChCvC,OAAO,CAACwC,UAAU,EAClBxC,OAAO,CAACyC,aAAa,EACrBzC,OAAO,CAAC0C,KAAK,CACb,CAAC;AAEFd,EAAAA,SAAS,CAAC,YAAK;IACdpB,QAAQ,KAAA,IAAA,IAARA,QAAQ,KAAA,MAAA,IAARA,QAAQ,CAAEoC,OAAO,CAACjB,OAAO,CAACV,OAAO,CAAC;AACnC,GAAC,EAAE,CAACM,OAAO,EAAEf,QAAQ,CAAC,CAAC;AAEvBoB,EAAAA,SAAS,CAAC,YAAK;IACd,IAAI5B,OAAO,CAACsB,KAAK,KAAKnB,SAAS,IAAI,CAACK,QAAQ,EAAE;AAC9C,IAAA,IAAI,OAAOR,OAAO,CAACsB,KAAK,KAAK,UAAU,EAAE;AACxC,MAAA,IAAMuB,EAAE,GAAG7C,OAAO,CAACsB,KAAK;AAAA,MAAA,IAAAwB,SAAA,GAAAC,0BAAA,CACHvC,QAAQ,CAACI,KAAK,CAAA;QAAAoC,KAAA;AAAA,MAAA,IAAA;QAAnC,KAAAF,SAAA,CAAAG,CAAA,EAAAD,EAAAA,CAAAA,CAAAA,KAAA,GAAAF,SAAA,CAAAI,CAAA,EAAAC,EAAAA,IAAA,GAAqC;AAAA,UAAA,IAA1BnB,QAAM,GAAAgB,KAAA,CAAA1B,KAAA;UAChBd,QAAQ,CAAC8B,UAAU,CAACN,QAAM,EAAEa,EAAE,CAACb,QAAM,CAAC,CAAC;AACxC;AAAC,OAAA,CAAA,OAAAoB,GAAA,EAAA;QAAAN,SAAA,CAAAO,CAAA,CAAAD,GAAA,CAAA;AAAA,OAAA,SAAA;AAAAN,QAAAA,SAAA,CAAAQ,CAAA,EAAA;AAAA;AACF,KAAC,MAAM;AACN9C,MAAAA,QAAQ,CAAC+C,IAAI,CAACvD,OAAO,CAACsB,KAAK,CAAC;AAC7B;GACA,EAAE,CAACtB,OAAO,CAACsB,KAAK,EAAEd,QAAQ,CAAC,CAAC;EAE7B,OAAO;AAAEI,IAAAA,KAAK,EAALA,KAAK;AAAEJ,IAAAA,QAAQ,EAARA;GAAU;AAC3B;;;;"}
@@ -0,0 +1,21 @@
1
+ export type UseGroupRoomsOptions = {
2
+ /** URL of the signaling server. Defaults to the public example server. */
3
+ webSocketSignalingServer?: string;
4
+ };
5
+ /**
6
+ * Subscribes to the live list of rooms a signaling server lists under
7
+ * `group`. Rooms appear when their provider was created with the same `group`
8
+ * and disappear once nobody is connected to them.
9
+ *
10
+ * @returns `rooms` — `null` until the first list arrives, then the current
11
+ * list; `isConnected` — whether the subscription socket is up.
12
+ */
13
+ export declare const useGroupRooms: (group: string, options?: UseGroupRoomsOptions) => {
14
+ rooms: {
15
+ room: string;
16
+ clients: number;
17
+ maxClients?: number | undefined;
18
+ meta?: unknown;
19
+ }[] | null;
20
+ isConnected: boolean;
21
+ };
@@ -0,0 +1,77 @@
1
+ import { slicedToArray as _slicedToArray } from './_virtual/_rollupPluginBabelHelpers.js';
2
+ import { c } from 'react/compiler-runtime';
3
+ import { subscribeToGroup } from '@device-portal/client';
4
+ import { useState, useEffect } from 'react';
5
+
6
+ /**
7
+ * Subscribes to the live list of rooms a signaling server lists under
8
+ * `group`. Rooms appear when their provider was created with the same `group`
9
+ * and disappear once nobody is connected to them.
10
+ *
11
+ * @returns `rooms` — `null` until the first list arrives, then the current
12
+ * list; `isConnected` — whether the subscription socket is up.
13
+ */
14
+ var useGroupRooms = function useGroupRooms(group, t0) {
15
+ var $ = c(9);
16
+ var t1;
17
+ if ($[0] !== t0) {
18
+ t1 = t0 === undefined ? {} : t0;
19
+ $[0] = t0;
20
+ $[1] = t1;
21
+ } else {
22
+ t1 = $[1];
23
+ }
24
+ var options = t1;
25
+ var _useState = useState(null),
26
+ _useState2 = _slicedToArray(_useState, 2),
27
+ rooms = _useState2[0],
28
+ setRooms = _useState2[1];
29
+ var _useState3 = useState(false),
30
+ _useState4 = _slicedToArray(_useState3, 2),
31
+ isConnected = _useState4[0],
32
+ setIsConnected = _useState4[1];
33
+ var t2;
34
+ var t3;
35
+ if ($[2] !== group || $[3] !== options.webSocketSignalingServer) {
36
+ t2 = function t2() {
37
+ setRooms(null);
38
+ setIsConnected(false);
39
+ var unsubscribe = subscribeToGroup(group, {
40
+ webSocketSignalingServer: options.webSocketSignalingServer,
41
+ onRooms: function onRooms(rooms_0) {
42
+ setRooms(rooms_0);
43
+ setIsConnected(true);
44
+ },
45
+ onDisconnected: function onDisconnected() {
46
+ setIsConnected(false);
47
+ }
48
+ });
49
+ return unsubscribe;
50
+ };
51
+ t3 = [group, options.webSocketSignalingServer];
52
+ $[2] = group;
53
+ $[3] = options.webSocketSignalingServer;
54
+ $[4] = t2;
55
+ $[5] = t3;
56
+ } else {
57
+ t2 = $[4];
58
+ t3 = $[5];
59
+ }
60
+ useEffect(t2, t3);
61
+ var t4;
62
+ if ($[6] !== isConnected || $[7] !== rooms) {
63
+ t4 = {
64
+ rooms: rooms,
65
+ isConnected: isConnected
66
+ };
67
+ $[6] = isConnected;
68
+ $[7] = rooms;
69
+ $[8] = t4;
70
+ } else {
71
+ t4 = $[8];
72
+ }
73
+ return t4;
74
+ };
75
+
76
+ export { useGroupRooms };
77
+ //# sourceMappingURL=useGroupRooms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGroupRooms.js","sources":["../src/useGroupRooms.ts"],"sourcesContent":["import { subscribeToGroup, type GroupRoom } from '@device-portal/client'\nimport { useEffect, useState } from 'react'\n\nexport type UseGroupRoomsOptions = {\n\t/** URL of the signaling server. Defaults to the public example server. */\n\twebSocketSignalingServer?: string\n}\n\n/**\n * Subscribes to the live list of rooms a signaling server lists under\n * `group`. Rooms appear when their provider was created with the same `group`\n * and disappear once nobody is connected to them.\n *\n * @returns `rooms` — `null` until the first list arrives, then the current\n * list; `isConnected` — whether the subscription socket is up.\n */\nexport const useGroupRooms = (\n\tgroup: string,\n\toptions: UseGroupRoomsOptions = {},\n) => {\n\tconst [rooms, setRooms] = useState<GroupRoom[] | null>(null)\n\tconst [isConnected, setIsConnected] = useState(false)\n\n\tuseEffect(() => {\n\t\tsetRooms(null)\n\t\tsetIsConnected(false)\n\t\tconst unsubscribe = subscribeToGroup(group, {\n\t\t\twebSocketSignalingServer: options.webSocketSignalingServer,\n\t\t\tonRooms: (rooms) => {\n\t\t\t\tsetRooms(rooms)\n\t\t\t\tsetIsConnected(true)\n\t\t\t},\n\t\t\tonDisconnected: () => {\n\t\t\t\tsetIsConnected(false)\n\t\t\t},\n\t\t})\n\t\treturn unsubscribe\n\t}, [group, options.webSocketSignalingServer])\n\n\treturn { rooms, isConnected }\n}\n"],"names":["useGroupRooms","group","t0","$","_c","t1","undefined","options","_useState","useState","_useState2","_slicedToArray","rooms","setRooms","_useState3","_useState4","isConnected","setIsConnected","t2","t3","webSocketSignalingServer","unsubscribe","subscribeToGroup","onRooms","rooms_0","onDisconnected","useEffect","t4"],"mappings":";;;;;AAQA;;;;;;;AAOG;AACI,IAAMA,aAAa,GAAG,SAAhBA,aAAaA,CAAAC,KAAA,EAAAC,EAAA,EAAA;EAAA,IAAAC,CAAA,GAAAC,CAAA,CAAA,CAAA,CAAA;AAAA,EAAA,IAAAC,EAAA;EAAA,IAAAF,CAAA,QAAAD,EAAA,EAAA;IAEzBG,EAAA,GAAAH,EAAkC,KAAlCI,SAAkC,GAAlC,EAAkC,GAAlCJ,EAAkC;AAAAC,IAAAA,CAAA,MAAAD,EAAA;AAAAC,IAAAA,CAAA,MAAAE,EAAA;AAAA,GAAA,MAAA;AAAAA,IAAAA,EAAA,GAAAF,CAAA,CAAA,CAAA,CAAA;AAAA;EAAlC,IAAAI,OAAA,GAAAF,EAAkC;AAElC,EAAA,IAAAG,SAAA,GAA0BC,QAAQ,CAAqB,IAAI,CAAC;IAAAC,UAAA,GAAAC,cAAA,CAAAH,SAAA,EAAA,CAAA,CAAA;AAAAI,IAAAA,KAAA,GAAAF,UAAA,CAAA,CAAA,CAAA;AAAAG,IAAAA,QAAA,GAAAH,UAAA,CAAA,CAAA,CAAA;AAC5D,EAAA,IAAAI,UAAA,GAAsCL,QAAQ,CAAC,KAAK,CAAC;IAAAM,UAAA,GAAAJ,cAAA,CAAAG,UAAA,EAAA,CAAA,CAAA;AAAAE,IAAAA,WAAA,GAAAD,UAAA,CAAA,CAAA,CAAA;AAAAE,IAAAA,cAAA,GAAAF,UAAA,CAAA,CAAA,CAAA;AAAA,EAAA,IAAAG,EAAA;AAAA,EAAA,IAAAC,EAAA;EAAA,IAAAhB,CAAA,QAAAF,KAAA,IAAAE,CAAA,CAAAI,CAAAA,CAAAA,KAAAA,OAAA,CAAAa,wBAAA,EAAA;AAE3CF,IAAAA,EAAA,YAAAA,EAAA,GAAA;MACTL,QAAQ,CAAC,IAAI,CAAC;MACdI,cAAc,CAAC,KAAK,CAAC;AACrB,MAAA,IAAAI,WAAA,GAAoBC,gBAAgB,CAACrB,KAAK,EAAE;QAAAmB,wBAAA,EACjBb,OAAO,CAAAa,wBAAyB;QAAAG,OAAA,EACjD,SAAAA,OAAAA,CAAAC,OAAA,EAAA;UACRX,QAAQ,CAACD,OAAK,CAAC;UACfK,cAAc,CAAC,IAAI,CAAC;SACpB;QAAAQ,cAAA,EACe,SAAAA,cAAA,GAAA;UACfR,cAAc,CAAC,KAAK,CAAC;AAAA;AAEtB,OAAA,CAAC;AAAA,MAAA,OACKI,WAAW;KAClB;AAAEF,IAAAA,EAAA,IAAClB,KAAK,EAAEM,OAAO,CAAAa,wBAAyB,CAAC;AAAAjB,IAAAA,CAAA,MAAAF,KAAA;IAAAE,CAAA,CAAA,CAAA,CAAA,GAAAI,OAAA,CAAAa,wBAAA;AAAAjB,IAAAA,CAAA,MAAAe,EAAA;AAAAf,IAAAA,CAAA,MAAAgB,EAAA;AAAA,GAAA,MAAA;AAAAD,IAAAA,EAAA,GAAAf,CAAA,CAAA,CAAA,CAAA;AAAAgB,IAAAA,EAAA,GAAAhB,CAAA,CAAA,CAAA,CAAA;AAAA;AAd5CuB,EAAAA,SAAS,CAACR,EAcT,EAAEC,EAAyC,CAAC;AAAA,EAAA,IAAAQ,EAAA;AAAA,EAAA,IAAAxB,CAAA,CAAAa,CAAAA,CAAAA,KAAAA,WAAA,IAAAb,CAAA,QAAAS,KAAA,EAAA;IAEtCe,EAAA,GAAA;AAAAf,MAAAA,KAAA,EAAEA,KAAK;AAAAI,MAAAA,WAAA,EAAEA;KAAa;AAAAb,IAAAA,CAAA,MAAAa,WAAA;AAAAb,IAAAA,CAAA,MAAAS,KAAA;AAAAT,IAAAA,CAAA,MAAAwB,EAAA;AAAA,GAAA,MAAA;AAAAA,IAAAA,EAAA,GAAAxB,CAAA,CAAA,CAAA,CAAA;AAAA;AAAA,EAAA,OAAtBwB,EAAsB;AAAA;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@device-portal/react",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Simple WebRTC data channel for React.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,7 +39,7 @@
39
39
  "react": ">=19"
40
40
  },
41
41
  "dependencies": {
42
- "@device-portal/client": "^0.1.2"
42
+ "@device-portal/client": "^0.2.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@babel/core": "^7.24.0",