@broadcastingplatforms/react-hooks 0.0.0-dev.ca53abc

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.
@@ -0,0 +1,69 @@
1
+ import { SdkClient, RealtimeConnectionState } from '@broadcastingplatforms/sdk';
2
+ import { ReactNode, ReactElement } from 'react';
3
+
4
+ /**
5
+ * Props for {@link BPProvider}.
6
+ */
7
+ interface BPProviderProps {
8
+ /**
9
+ * Configured SDK client instance.
10
+ */
11
+ client: SdkClient;
12
+ /**
13
+ * React children to render inside the provider.
14
+ */
15
+ children: ReactNode;
16
+ }
17
+ /**
18
+ * Provider component that stores the configured SDK client instance.
19
+ */
20
+ declare const BPProvider: ({ client, children }: BPProviderProps) => ReactElement;
21
+ /**
22
+ * Access the configured SDK client from context.
23
+ * @throws Error when the provider is missing.
24
+ */
25
+ declare const useClient: () => SdkClient;
26
+ /**
27
+ * Status values exposed by {@link useRealtime}.
28
+ */
29
+ type RealtimeHookStatus = RealtimeConnectionState | "inactive";
30
+ /**
31
+ * Options for {@link useRealtime}.
32
+ */
33
+ interface UseRealtimeOptions<TEvent = unknown> {
34
+ /**
35
+ * Channel name to subscribe to.
36
+ */
37
+ channel: string;
38
+ /**
39
+ * Topic/event name to listen for.
40
+ */
41
+ topic: string;
42
+ /**
43
+ * Toggle subscription lifecycle.
44
+ */
45
+ enabled?: boolean;
46
+ /**
47
+ * Optional event callback invoked for each payload.
48
+ */
49
+ onEvent?: (payload: TEvent) => void;
50
+ }
51
+ /**
52
+ * Result payload from {@link useRealtime}.
53
+ */
54
+ interface UseRealtimeResult<TEvent = unknown> {
55
+ /**
56
+ * Last event payload received.
57
+ */
58
+ lastEvent: TEvent | null;
59
+ /**
60
+ * Current realtime connection status.
61
+ */
62
+ status: RealtimeHookStatus;
63
+ }
64
+ /**
65
+ * Subscribe to a realtime channel topic with automatic cleanup.
66
+ */
67
+ declare const useRealtime: <TEvent>(options: UseRealtimeOptions<TEvent>) => UseRealtimeResult<TEvent>;
68
+
69
+ export { BPProvider, type BPProviderProps, type RealtimeHookStatus, type UseRealtimeOptions, type UseRealtimeResult, useClient, useRealtime };
@@ -0,0 +1,69 @@
1
+ import { SdkClient, RealtimeConnectionState } from '@broadcastingplatforms/sdk';
2
+ import { ReactNode, ReactElement } from 'react';
3
+
4
+ /**
5
+ * Props for {@link BPProvider}.
6
+ */
7
+ interface BPProviderProps {
8
+ /**
9
+ * Configured SDK client instance.
10
+ */
11
+ client: SdkClient;
12
+ /**
13
+ * React children to render inside the provider.
14
+ */
15
+ children: ReactNode;
16
+ }
17
+ /**
18
+ * Provider component that stores the configured SDK client instance.
19
+ */
20
+ declare const BPProvider: ({ client, children }: BPProviderProps) => ReactElement;
21
+ /**
22
+ * Access the configured SDK client from context.
23
+ * @throws Error when the provider is missing.
24
+ */
25
+ declare const useClient: () => SdkClient;
26
+ /**
27
+ * Status values exposed by {@link useRealtime}.
28
+ */
29
+ type RealtimeHookStatus = RealtimeConnectionState | "inactive";
30
+ /**
31
+ * Options for {@link useRealtime}.
32
+ */
33
+ interface UseRealtimeOptions<TEvent = unknown> {
34
+ /**
35
+ * Channel name to subscribe to.
36
+ */
37
+ channel: string;
38
+ /**
39
+ * Topic/event name to listen for.
40
+ */
41
+ topic: string;
42
+ /**
43
+ * Toggle subscription lifecycle.
44
+ */
45
+ enabled?: boolean;
46
+ /**
47
+ * Optional event callback invoked for each payload.
48
+ */
49
+ onEvent?: (payload: TEvent) => void;
50
+ }
51
+ /**
52
+ * Result payload from {@link useRealtime}.
53
+ */
54
+ interface UseRealtimeResult<TEvent = unknown> {
55
+ /**
56
+ * Last event payload received.
57
+ */
58
+ lastEvent: TEvent | null;
59
+ /**
60
+ * Current realtime connection status.
61
+ */
62
+ status: RealtimeHookStatus;
63
+ }
64
+ /**
65
+ * Subscribe to a realtime channel topic with automatic cleanup.
66
+ */
67
+ declare const useRealtime: <TEvent>(options: UseRealtimeOptions<TEvent>) => UseRealtimeResult<TEvent>;
68
+
69
+ export { BPProvider, type BPProviderProps, type RealtimeHookStatus, type UseRealtimeOptions, type UseRealtimeResult, useClient, useRealtime };
package/dist/index.js ADDED
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.tsx
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BPProvider: () => BPProvider,
24
+ useClient: () => useClient,
25
+ useRealtime: () => useRealtime
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var import_react = require("react");
29
+ var import_jsx_runtime = require("react/jsx-runtime");
30
+ var BPClientContext = (0, import_react.createContext)(null);
31
+ var BPProvider = ({ client, children }) => {
32
+ const value = (0, import_react.useMemo)(() => client, [client]);
33
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BPClientContext.Provider, { value, children });
34
+ };
35
+ var useClient = () => {
36
+ const client = (0, import_react.useContext)(BPClientContext);
37
+ if (!client) {
38
+ throw new Error("BPProvider is missing. Wrap your component tree with <BPProvider />.");
39
+ }
40
+ return client;
41
+ };
42
+ var resolveRealtimeChannel = (client, channelName) => {
43
+ if (channelName.startsWith("private-")) {
44
+ return { channel: client.realtime.private(channelName), leaveName: channelName };
45
+ }
46
+ if (channelName.startsWith("presence-")) {
47
+ return { channel: client.realtime.join(channelName), leaveName: channelName };
48
+ }
49
+ return { channel: client.realtime.channel(channelName), leaveName: channelName };
50
+ };
51
+ var useRealtime = (options) => {
52
+ const { channel, topic, enabled = true, onEvent } = options;
53
+ const client = useClient();
54
+ const [lastEvent, setLastEvent] = (0, import_react.useState)(null);
55
+ const [status, setStatus] = (0, import_react.useState)(
56
+ enabled ? "connecting" : "inactive"
57
+ );
58
+ const onEventRef = (0, import_react.useRef)(onEvent);
59
+ (0, import_react.useEffect)(() => {
60
+ onEventRef.current = onEvent;
61
+ }, [onEvent]);
62
+ (0, import_react.useEffect)(() => {
63
+ if (!enabled) {
64
+ setStatus("inactive");
65
+ return void 0;
66
+ }
67
+ setStatus("connecting");
68
+ setLastEvent(null);
69
+ const unsubscribeConnection = client.realtime.onConnectionStateChange(
70
+ (state) => setStatus(state)
71
+ );
72
+ const { channel: realtimeChannel, leaveName } = resolveRealtimeChannel(
73
+ client,
74
+ channel
75
+ );
76
+ const handler = (payload) => {
77
+ setLastEvent(payload);
78
+ onEventRef.current?.(payload);
79
+ };
80
+ realtimeChannel.listen(topic, handler);
81
+ return () => {
82
+ realtimeChannel.stopListening(topic, handler);
83
+ client.realtime.leave(leaveName);
84
+ unsubscribeConnection();
85
+ };
86
+ }, [channel, client, enabled, topic]);
87
+ return { lastEvent, status };
88
+ };
89
+ // Annotate the CommonJS export names for ESM import in node:
90
+ 0 && (module.exports = {
91
+ BPProvider,
92
+ useClient,
93
+ useRealtime
94
+ });
95
+ //# sourceMappingURL=index.js.map
package/dist/index.mjs ADDED
@@ -0,0 +1,75 @@
1
+ // src/index.tsx
2
+ import {
3
+ createContext,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState
9
+ } from "react";
10
+ import { jsx } from "react/jsx-runtime";
11
+ var BPClientContext = createContext(null);
12
+ var BPProvider = ({ client, children }) => {
13
+ const value = useMemo(() => client, [client]);
14
+ return /* @__PURE__ */ jsx(BPClientContext.Provider, { value, children });
15
+ };
16
+ var useClient = () => {
17
+ const client = useContext(BPClientContext);
18
+ if (!client) {
19
+ throw new Error("BPProvider is missing. Wrap your component tree with <BPProvider />.");
20
+ }
21
+ return client;
22
+ };
23
+ var resolveRealtimeChannel = (client, channelName) => {
24
+ if (channelName.startsWith("private-")) {
25
+ return { channel: client.realtime.private(channelName), leaveName: channelName };
26
+ }
27
+ if (channelName.startsWith("presence-")) {
28
+ return { channel: client.realtime.join(channelName), leaveName: channelName };
29
+ }
30
+ return { channel: client.realtime.channel(channelName), leaveName: channelName };
31
+ };
32
+ var useRealtime = (options) => {
33
+ const { channel, topic, enabled = true, onEvent } = options;
34
+ const client = useClient();
35
+ const [lastEvent, setLastEvent] = useState(null);
36
+ const [status, setStatus] = useState(
37
+ enabled ? "connecting" : "inactive"
38
+ );
39
+ const onEventRef = useRef(onEvent);
40
+ useEffect(() => {
41
+ onEventRef.current = onEvent;
42
+ }, [onEvent]);
43
+ useEffect(() => {
44
+ if (!enabled) {
45
+ setStatus("inactive");
46
+ return void 0;
47
+ }
48
+ setStatus("connecting");
49
+ setLastEvent(null);
50
+ const unsubscribeConnection = client.realtime.onConnectionStateChange(
51
+ (state) => setStatus(state)
52
+ );
53
+ const { channel: realtimeChannel, leaveName } = resolveRealtimeChannel(
54
+ client,
55
+ channel
56
+ );
57
+ const handler = (payload) => {
58
+ setLastEvent(payload);
59
+ onEventRef.current?.(payload);
60
+ };
61
+ realtimeChannel.listen(topic, handler);
62
+ return () => {
63
+ realtimeChannel.stopListening(topic, handler);
64
+ client.realtime.leave(leaveName);
65
+ unsubscribeConnection();
66
+ };
67
+ }, [channel, client, enabled, topic]);
68
+ return { lastEvent, status };
69
+ };
70
+ export {
71
+ BPProvider,
72
+ useClient,
73
+ useRealtime
74
+ };
75
+ //# sourceMappingURL=index.mjs.map
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@broadcastingplatforms/react-hooks",
3
+ "version": "0.0.0-dev.ca53abc",
4
+ "description": "React adapter for the Broadcasting Platform SDK",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist/",
10
+ "!**/*.map"
11
+ ],
12
+ "sideEffects": false,
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.mjs",
20
+ "require": "./dist/index.js"
21
+ }
22
+ },
23
+ "tsup": {
24
+ "entry": [
25
+ "src/index.tsx"
26
+ ],
27
+ "format": [
28
+ "esm",
29
+ "cjs"
30
+ ],
31
+ "dts": true,
32
+ "sourcemap": true,
33
+ "clean": true,
34
+ "splitting": false,
35
+ "target": "es2020"
36
+ },
37
+ "peerDependencies": {
38
+ "@broadcastingplatforms/sdk": "^0.1.0",
39
+ "react": ">=18",
40
+ "react-dom": ">=18"
41
+ },
42
+ "engines": {
43
+ "node": ">=22"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^20.19.30",
47
+ "@types/react": "^19.2.2",
48
+ "@types/react-dom": "^19.2.2",
49
+ "@typescript-eslint/eslint-plugin": "^8.33.0",
50
+ "@typescript-eslint/parser": "^8.33.0",
51
+ "@vitejs/plugin-react": "^4.3.4",
52
+ "eslint": "^9.0.0",
53
+ "eslint-plugin-react-hooks": "^5.1.0",
54
+ "eslint-plugin-simple-import-sort": "^12.1.1",
55
+ "react": "^19.2.0",
56
+ "react-dom": "^19.2.0",
57
+ "tsup": "^8.0.2",
58
+ "tsx": "^4.19.2",
59
+ "typescript": "^5.0.0",
60
+ "vite": "^6.0.4",
61
+ "vitest": "^2.1.8",
62
+ "@broadcastingplatforms/sdk": "0.0.0-dev.ca53abc"
63
+ },
64
+ "scripts": {
65
+ "build": "tsup",
66
+ "build:watch": "tsup --watch",
67
+ "lint": "eslint -c ./eslint.config.mjs \"{src,tests,test-app}/**/*.{ts,tsx,js,jsx}\" --fix",
68
+ "test": "vitest run",
69
+ "test-app:dev": "vite --config test-app/vite.config.ts",
70
+ "test-app:build": "vite build --config test-app/vite.config.ts",
71
+ "test-app:preview": "vite preview --config test-app/vite.config.ts"
72
+ }
73
+ }