@interlucent/pixel-stream-react 0.0.1

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,253 @@
1
+ /**
2
+ * React bindings for the <pixel-stream> web component.
3
+ *
4
+ * SSR-safe: renders an empty <pixel-stream> tag on the server, hydrates
5
+ * on the client by lazily importing the web component definition.
6
+ *
7
+ * Provides:
8
+ * - A <PixelStream> React component with typed props and event callbacks
9
+ * - JSX IntrinsicElements augmentation so bare <pixel-stream> also type-checks
10
+ * - Re-exports of key types from @interlucent/pixel-stream
11
+ */
12
+ import React, { type RefObject } from 'react';
13
+ import type { PixelStream as PixelStreamElement, PixelStreamStatus, ResolutionClampName, StreamResolutionClamp } from '@interlucent/pixel-stream';
14
+ export type { PixelStreamStatus, ResolutionClampName, StreamResolutionClamp, } from '@interlucent/pixel-stream';
15
+ export interface ChangeDetail<T = string | null> {
16
+ oldValue: T;
17
+ newValue: T;
18
+ }
19
+ export interface SessionStateChangeDetail {
20
+ oldState: string;
21
+ newState: string;
22
+ }
23
+ export interface StreamStateChangeDetail {
24
+ oldState: string;
25
+ newState: string;
26
+ detail?: string;
27
+ }
28
+ export interface StatusChangeDetail {
29
+ oldStatus: PixelStreamStatus;
30
+ newStatus: PixelStreamStatus;
31
+ }
32
+ export interface SessionErrorDetail {
33
+ message: string;
34
+ code?: string;
35
+ }
36
+ export interface AdmissionErrorDetail {
37
+ reason: string;
38
+ }
39
+ export interface StreamResolutionChangeDetail {
40
+ width: number;
41
+ height: number;
42
+ clamp?: StreamResolutionClamp | null;
43
+ }
44
+ export interface PeerDetail {
45
+ peerId: string;
46
+ }
47
+ export interface MuteChangeDetail {
48
+ oldValue: boolean;
49
+ newValue: boolean;
50
+ muted: boolean;
51
+ }
52
+ export interface PermissionChangeDetail {
53
+ permission: string;
54
+ status: string;
55
+ }
56
+ export interface ResizeModeDetectedDetail {
57
+ mode: string;
58
+ }
59
+ export interface XRStreamDetectedDetail {
60
+ isXRStream: boolean;
61
+ }
62
+ export interface PixelStreamEventProps {
63
+ onReady?: (e: CustomEvent) => void;
64
+ onAdmissionTokenChange?: (e: CustomEvent<ChangeDetail>) => void;
65
+ onAppIdChange?: (e: CustomEvent<ChangeDetail>) => void;
66
+ onAppVersionChange?: (e: CustomEvent<ChangeDetail>) => void;
67
+ onAdmitted?: (e: CustomEvent) => void;
68
+ onAdmissionRevoked?: (e: CustomEvent) => void;
69
+ onAdmissionError?: (e: CustomEvent<AdmissionErrorDetail>) => void;
70
+ onNoAutoConnectChange?: (e: CustomEvent<ChangeDetail<boolean>>) => void;
71
+ onSessionStateChange?: (e: CustomEvent<SessionStateChangeDetail>) => void;
72
+ onSessionError?: (e: CustomEvent<SessionErrorDetail>) => void;
73
+ onJobStateChange?: (e: CustomEvent) => void;
74
+ onStreamStateChange?: (e: CustomEvent<StreamStateChangeDetail>) => void;
75
+ onStreamResolutionChange?: (e: CustomEvent<StreamResolutionChangeDetail>) => void;
76
+ onStatusChange?: (e: CustomEvent<StatusChangeDetail>) => void;
77
+ onRendezvousStarted?: (e: CustomEvent) => void;
78
+ onRendezvousTimeout?: (e: CustomEvent) => void;
79
+ onRendezvousCancelled?: (e: CustomEvent) => void;
80
+ onLingerStarted?: (e: CustomEvent) => void;
81
+ onLingerTimeout?: (e: CustomEvent) => void;
82
+ onLingerCancelled?: (e: CustomEvent) => void;
83
+ onPeerConnected?: (e: CustomEvent<PeerDetail>) => void;
84
+ onPeerDisconnected?: (e: CustomEvent<PeerDetail>) => void;
85
+ onMuteChange?: (e: CustomEvent<MuteChangeDetail>) => void;
86
+ onVolumeChange?: (e: CustomEvent<ChangeDetail<number>>) => void;
87
+ onPermissionChange?: (e: CustomEvent<PermissionChangeDetail>) => void;
88
+ onRendezvousPreferenceChange?: (e: CustomEvent<ChangeDetail<number | null>>) => void;
89
+ onLingerPreferenceChange?: (e: CustomEvent<ChangeDetail<number | null>>) => void;
90
+ onLeftGracePeriodChange?: (e: CustomEvent<ChangeDetail<number | null>>) => void;
91
+ onApiEndpointChange?: (e: CustomEvent<ChangeDetail>) => void;
92
+ onResizeModeDetected?: (e: CustomEvent<ResizeModeDetectedDetail>) => void;
93
+ onXRStreamDetected?: (e: CustomEvent<XRStreamDetectedDetail>) => void;
94
+ onLog?: (e: CustomEvent) => void;
95
+ }
96
+ export interface PixelStreamAttributeProps {
97
+ admissionToken?: string | null;
98
+ appId?: string | null;
99
+ appVersion?: string | null;
100
+ noAutoConnect?: boolean;
101
+ nativeTouch?: boolean;
102
+ pointerLock?: boolean;
103
+ pointerLockRelease?: boolean;
104
+ suppressBrowserKeys?: boolean;
105
+ enableGamepad?: boolean;
106
+ enableXr?: boolean;
107
+ mute?: boolean;
108
+ volume?: number;
109
+ rendezvousPreference?: number;
110
+ lingerPreference?: number;
111
+ leftGracePeriod?: number;
112
+ apiEndpoint?: string;
113
+ forceRelay?: boolean;
114
+ queueWaitTolerance?: number;
115
+ webrtcNegotiationTolerance?: number;
116
+ reconnectMode?: 'none' | 'recover' | 'always';
117
+ reconnectAttempts?: number;
118
+ reconnectStrategy?: 'periodic' | 'exponential-backoff';
119
+ reconnectInterval?: number;
120
+ disconnectGraceMs?: number;
121
+ resizeMode?: 'none' | 'auto' | 'pureweb' | 'pre-5.4' | '5.4+';
122
+ dprCap?: number;
123
+ resolutionClamp?: ResolutionClampName;
124
+ debug?: boolean;
125
+ controls?: boolean;
126
+ swiftJobRequest?: boolean;
127
+ streamerId?: string;
128
+ lat?: number;
129
+ lng?: number;
130
+ streamQuality?: 'low-latency' | 'balanced' | 'quality';
131
+ videoBitrateMin?: number;
132
+ videoBitrateStart?: number;
133
+ videoBitrateMax?: number;
134
+ logLevel?: 'error' | 'warn' | 'info' | 'debug';
135
+ }
136
+ export interface PixelStreamProps extends PixelStreamAttributeProps, PixelStreamEventProps {
137
+ className?: string;
138
+ style?: React.CSSProperties;
139
+ children?: React.ReactNode;
140
+ }
141
+ /**
142
+ * React component wrapping the `<pixel-stream>` web component.
143
+ *
144
+ * - SSR-safe: renders `<pixel-stream>` on the server (no crash), hydrates on client
145
+ * - Full typed props for all 51 HTML attributes
146
+ * - Event callbacks for all custom events (`onStatusChange`, `onReady`, etc.)
147
+ * - Ref forwarding — access the underlying element for imperative methods
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * import { PixelStream } from '@interlucent/pixel-stream-react';
152
+ *
153
+ * function App() {
154
+ * const ref = useRef<PixelStreamElement>(null);
155
+ *
156
+ * return (
157
+ * <PixelStream
158
+ * ref={ref}
159
+ * admissionToken="tok_..."
160
+ * onStatusChange={(e) => console.log(e.detail.newStatus)}
161
+ * onReady={() => console.log('ready')}
162
+ * style={{ width: '100%', height: '100%' }}
163
+ * />
164
+ * );
165
+ * }
166
+ * ```
167
+ */
168
+ export declare const PixelStream: React.ForwardRefExoticComponent<PixelStreamProps & React.RefAttributes<PixelStreamElement>>;
169
+ /**
170
+ * Convenience hook providing a typed ref for the `<pixel-stream>` element.
171
+ *
172
+ * @example
173
+ * ```tsx
174
+ * function App() {
175
+ * const psRef = usePixelStreamRef();
176
+ * return <PixelStream ref={psRef} admissionToken="tok_..." />;
177
+ * }
178
+ * ```
179
+ */
180
+ export declare function usePixelStreamRef(): RefObject<PixelStreamElement | null>;
181
+ /**
182
+ * Hook that tracks the `status` of a `<pixel-stream>` element reactively.
183
+ *
184
+ * @example
185
+ * ```tsx
186
+ * function App() {
187
+ * const psRef = usePixelStreamRef();
188
+ * const status = usePixelStreamStatus(psRef);
189
+ * return (
190
+ * <div>
191
+ * <PixelStream ref={psRef} admissionToken="tok_..." />
192
+ * <p>Status: {status}</p>
193
+ * </div>
194
+ * );
195
+ * }
196
+ * ```
197
+ */
198
+ export declare function usePixelStreamStatus(ref: RefObject<PixelStreamElement | null>): PixelStreamStatus;
199
+ type PixelStreamHTMLAttributes = {
200
+ 'admission-token'?: string;
201
+ 'app-id'?: string;
202
+ 'app-version'?: string;
203
+ 'no-auto-connect'?: boolean | string;
204
+ 'native-touch'?: boolean | string;
205
+ 'pointer-lock'?: boolean | string;
206
+ 'pointer-lock-release'?: boolean | string;
207
+ 'suppress-browser-keys'?: boolean | string;
208
+ 'enable-gamepad'?: boolean | string;
209
+ 'enable-xr'?: boolean | string;
210
+ mute?: boolean | string;
211
+ volume?: number | string;
212
+ 'rendezvous-preference'?: number | string;
213
+ 'linger-preference'?: number | string;
214
+ 'left-grace-period'?: number | string;
215
+ 'api-endpoint'?: string;
216
+ 'force-relay'?: boolean | string;
217
+ 'queue-wait-tolerance'?: number | string;
218
+ 'webrtc-negotiation-tolerance'?: number | string;
219
+ 'reconnect-mode'?: 'none' | 'recover' | 'always';
220
+ 'reconnect-attempts'?: number | string;
221
+ 'reconnect-strategy'?: 'periodic' | 'exponential-backoff';
222
+ 'reconnect-interval'?: number | string;
223
+ 'disconnect-grace-ms'?: number | string;
224
+ 'resize-mode'?: 'none' | 'auto' | 'pureweb' | 'pre-5.4' | '5.4+';
225
+ 'dpr-cap'?: number | string;
226
+ 'resolution-clamp'?: ResolutionClampName;
227
+ debug?: boolean | string;
228
+ controls?: boolean | string;
229
+ 'swift-job-request'?: boolean | string;
230
+ 'streamer-id'?: string;
231
+ lat?: number | string;
232
+ lng?: number | string;
233
+ 'stream-quality'?: 'low-latency' | 'balanced' | 'quality';
234
+ 'video-bitrate-min'?: number | string;
235
+ 'video-bitrate-start'?: number | string;
236
+ 'video-bitrate-max'?: number | string;
237
+ 'log-level'?: 'error' | 'warn' | 'info' | 'debug';
238
+ class?: string;
239
+ className?: string;
240
+ id?: string;
241
+ style?: React.CSSProperties | string;
242
+ slot?: string;
243
+ children?: React.ReactNode;
244
+ ref?: React.Ref<PixelStreamElement>;
245
+ suppressHydrationWarning?: boolean;
246
+ };
247
+ declare global {
248
+ namespace JSX {
249
+ interface IntrinsicElements {
250
+ 'pixel-stream': PixelStreamHTMLAttributes;
251
+ }
252
+ }
253
+ }
package/dist/index.js ADDED
@@ -0,0 +1,283 @@
1
+ /**
2
+ * React bindings for the <pixel-stream> web component.
3
+ *
4
+ * SSR-safe: renders an empty <pixel-stream> tag on the server, hydrates
5
+ * on the client by lazily importing the web component definition.
6
+ *
7
+ * Provides:
8
+ * - A <PixelStream> React component with typed props and event callbacks
9
+ * - JSX IntrinsicElements augmentation so bare <pixel-stream> also type-checks
10
+ * - Re-exports of key types from @interlucent/pixel-stream
11
+ */
12
+ import React, { useRef, useEffect, useState, useImperativeHandle, forwardRef, } from 'react';
13
+ // ===== SSR guard =====
14
+ const isBrowser = typeof window !== 'undefined';
15
+ // Lazy web-component registration — called once on first mount
16
+ let _registered = false;
17
+ function ensureRegistered() {
18
+ if (_registered || !isBrowser)
19
+ return;
20
+ _registered = true;
21
+ // Dynamic import so Node.js never evaluates the web component at module scope
22
+ import('@interlucent/pixel-stream').catch(() => {
23
+ // Web component already registered or unavailable — not fatal
24
+ });
25
+ }
26
+ // ===== Mapping from callback prop to DOM event name =====
27
+ const EVENT_MAP = {
28
+ onReady: 'ready',
29
+ onAdmissionTokenChange: 'admission-token-change',
30
+ onAppIdChange: 'app-id-change',
31
+ onAppVersionChange: 'app-version-change',
32
+ onAdmitted: 'admitted',
33
+ onAdmissionRevoked: 'admission-revoked',
34
+ onAdmissionError: 'admission-error',
35
+ onNoAutoConnectChange: 'no-auto-connect-change',
36
+ onSessionStateChange: 'session-state-change',
37
+ onSessionError: 'session-error',
38
+ onJobStateChange: 'job-state-change',
39
+ onStreamStateChange: 'stream-state-change',
40
+ onStreamResolutionChange: 'stream-resolution-change',
41
+ onStatusChange: 'status-change',
42
+ onRendezvousStarted: 'rendezvous-started',
43
+ onRendezvousTimeout: 'rendezvous-timeout',
44
+ onRendezvousCancelled: 'rendezvous-cancelled',
45
+ onLingerStarted: 'linger-started',
46
+ onLingerTimeout: 'linger-timeout',
47
+ onLingerCancelled: 'linger-cancelled',
48
+ onPeerConnected: 'peer-connected',
49
+ onPeerDisconnected: 'peer-disconnected',
50
+ onMuteChange: 'mute-change',
51
+ onVolumeChange: 'volume-change',
52
+ onPermissionChange: 'permission-change',
53
+ onRendezvousPreferenceChange: 'rendezvous-preference-change',
54
+ onLingerPreferenceChange: 'linger-preference-change',
55
+ onLeftGracePeriodChange: 'left-grace-period-change',
56
+ onApiEndpointChange: 'api-endpoint-change',
57
+ onResizeModeDetected: 'resize-mode-detected',
58
+ onXRStreamDetected: 'xr-stream-detected',
59
+ onLog: 'interlucent:log',
60
+ };
61
+ // ===== Mapping from React prop to HTML attribute =====
62
+ const ATTR_MAP = {
63
+ admissionToken: 'admission-token',
64
+ appId: 'app-id',
65
+ appVersion: 'app-version',
66
+ noAutoConnect: 'no-auto-connect',
67
+ nativeTouch: 'native-touch',
68
+ pointerLock: 'pointer-lock',
69
+ pointerLockRelease: 'pointer-lock-release',
70
+ suppressBrowserKeys: 'suppress-browser-keys',
71
+ enableGamepad: 'enable-gamepad',
72
+ enableXr: 'enable-xr',
73
+ forceRelay: 'force-relay',
74
+ queueWaitTolerance: 'queue-wait-tolerance',
75
+ webrtcNegotiationTolerance: 'webrtc-negotiation-tolerance',
76
+ reconnectMode: 'reconnect-mode',
77
+ reconnectAttempts: 'reconnect-attempts',
78
+ reconnectStrategy: 'reconnect-strategy',
79
+ reconnectInterval: 'reconnect-interval',
80
+ disconnectGraceMs: 'disconnect-grace-ms',
81
+ resizeMode: 'resize-mode',
82
+ dprCap: 'dpr-cap',
83
+ resolutionClamp: 'resolution-clamp',
84
+ swiftJobRequest: 'swift-job-request',
85
+ streamerId: 'streamer-id',
86
+ streamQuality: 'stream-quality',
87
+ videoBitrateMin: 'video-bitrate-min',
88
+ videoBitrateStart: 'video-bitrate-start',
89
+ videoBitrateMax: 'video-bitrate-max',
90
+ logLevel: 'log-level',
91
+ rendezvousPreference: 'rendezvous-preference',
92
+ lingerPreference: 'linger-preference',
93
+ leftGracePeriod: 'left-grace-period',
94
+ apiEndpoint: 'api-endpoint',
95
+ };
96
+ // Props that are boolean HTML attributes (presence = true, absence = false)
97
+ const BOOLEAN_ATTRS = new Set([
98
+ 'noAutoConnect', 'nativeTouch', 'pointerLock', 'pointerLockRelease',
99
+ 'suppressBrowserKeys', 'enableGamepad', 'enableXr', 'mute', 'debug',
100
+ 'controls', 'forceRelay', 'swiftJobRequest',
101
+ ]);
102
+ // All known attribute prop names (for removal tracking)
103
+ const ALL_ATTR_NAMES = new Set([
104
+ ...Object.keys(ATTR_MAP),
105
+ 'mute', 'volume', 'debug', 'controls', 'lat', 'lng',
106
+ ]);
107
+ // Props handled separately (not attributes or events)
108
+ const SPECIAL_PROPS = new Set(['className', 'style', 'children']);
109
+ /**
110
+ * React component wrapping the `<pixel-stream>` web component.
111
+ *
112
+ * - SSR-safe: renders `<pixel-stream>` on the server (no crash), hydrates on client
113
+ * - Full typed props for all 51 HTML attributes
114
+ * - Event callbacks for all custom events (`onStatusChange`, `onReady`, etc.)
115
+ * - Ref forwarding — access the underlying element for imperative methods
116
+ *
117
+ * @example
118
+ * ```tsx
119
+ * import { PixelStream } from '@interlucent/pixel-stream-react';
120
+ *
121
+ * function App() {
122
+ * const ref = useRef<PixelStreamElement>(null);
123
+ *
124
+ * return (
125
+ * <PixelStream
126
+ * ref={ref}
127
+ * admissionToken="tok_..."
128
+ * onStatusChange={(e) => console.log(e.detail.newStatus)}
129
+ * onReady={() => console.log('ready')}
130
+ * style={{ width: '100%', height: '100%' }}
131
+ * />
132
+ * );
133
+ * }
134
+ * ```
135
+ */
136
+ export const PixelStream = forwardRef(function PixelStream(props, ref) {
137
+ const elementRef = useRef(null);
138
+ const [mounted, setMounted] = useState(false);
139
+ // Expose the raw element to the parent ref
140
+ useImperativeHandle(ref, () => elementRef.current, [mounted]);
141
+ // Register the web component on first client mount
142
+ useEffect(() => {
143
+ ensureRegistered();
144
+ setMounted(true);
145
+ }, []);
146
+ // Sync custom event listeners.
147
+ // We store the latest props in a ref so the effect doesn't need to
148
+ // teardown/re-add listeners on every render — only when the set of
149
+ // subscribed event names changes.
150
+ const propsRef = useRef(props);
151
+ propsRef.current = props;
152
+ // Compute which event names are currently subscribed
153
+ const activeEvents = Object.keys(EVENT_MAP)
154
+ .filter(k => typeof props[k] === 'function')
155
+ .join(',');
156
+ useEffect(() => {
157
+ const el = elementRef.current;
158
+ if (!el || !mounted)
159
+ return;
160
+ const listeners = [];
161
+ for (const [propName, eventName] of Object.entries(EVENT_MAP)) {
162
+ const handler = propsRef.current[propName];
163
+ if (typeof handler !== 'function')
164
+ continue;
165
+ // Wrap so we always call the latest prop version
166
+ const wrapped = (e) => {
167
+ const fn = propsRef.current[propName];
168
+ if (typeof fn === 'function')
169
+ fn(e);
170
+ };
171
+ el.addEventListener(eventName, wrapped);
172
+ listeners.push([eventName, wrapped]);
173
+ }
174
+ return () => {
175
+ for (const [eventName, handler] of listeners) {
176
+ el.removeEventListener(eventName, handler);
177
+ }
178
+ };
179
+ // eslint-disable-next-line react-hooks/exhaustive-deps
180
+ }, [mounted, activeEvents]);
181
+ // Sync HTML attributes from props
182
+ useEffect(() => {
183
+ const el = elementRef.current;
184
+ if (!el || !mounted)
185
+ return;
186
+ // Build desired attribute state
187
+ const desired = new Map();
188
+ for (const [propName, value] of Object.entries(props)) {
189
+ if (SPECIAL_PROPS.has(propName) || propName in EVENT_MAP)
190
+ continue;
191
+ if (!ALL_ATTR_NAMES.has(propName))
192
+ continue;
193
+ const attrName = ATTR_MAP[propName] ?? propName;
194
+ if (BOOLEAN_ATTRS.has(propName)) {
195
+ if (value)
196
+ desired.set(attrName, '');
197
+ }
198
+ else if (value != null) {
199
+ desired.set(attrName, String(value));
200
+ }
201
+ }
202
+ // Set desired attributes
203
+ for (const [attr, value] of desired) {
204
+ if (el.getAttribute(attr) !== value) {
205
+ el.setAttribute(attr, value);
206
+ }
207
+ }
208
+ // Remove attributes that are no longer in props
209
+ const allKnownAttrNames = [
210
+ ...Object.values(ATTR_MAP),
211
+ 'mute', 'volume', 'debug', 'controls', 'lat', 'lng',
212
+ ];
213
+ for (const attrName of allKnownAttrNames) {
214
+ if (!desired.has(attrName) && el.hasAttribute(attrName)) {
215
+ el.removeAttribute(attrName);
216
+ }
217
+ }
218
+ });
219
+ // On the server, render a bare <pixel-stream> tag.
220
+ // On the client, also render <pixel-stream> and let effects handle attrs/events.
221
+ return React.createElement('pixel-stream', {
222
+ ref: elementRef,
223
+ class: props.className,
224
+ style: props.style
225
+ ? Object.entries(props.style).reduce((css, [k, v]) => {
226
+ const kebab = k.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);
227
+ return `${css}${kebab}:${v};`;
228
+ }, '')
229
+ : undefined,
230
+ // Suppress React hydration warnings for attributes set by effects
231
+ suppressHydrationWarning: true,
232
+ }, props.children);
233
+ });
234
+ // ===== usePixelStreamRef hook =====
235
+ /**
236
+ * Convenience hook providing a typed ref for the `<pixel-stream>` element.
237
+ *
238
+ * @example
239
+ * ```tsx
240
+ * function App() {
241
+ * const psRef = usePixelStreamRef();
242
+ * return <PixelStream ref={psRef} admissionToken="tok_..." />;
243
+ * }
244
+ * ```
245
+ */
246
+ export function usePixelStreamRef() {
247
+ return useRef(null);
248
+ }
249
+ // ===== usePixelStreamStatus hook =====
250
+ /**
251
+ * Hook that tracks the `status` of a `<pixel-stream>` element reactively.
252
+ *
253
+ * @example
254
+ * ```tsx
255
+ * function App() {
256
+ * const psRef = usePixelStreamRef();
257
+ * const status = usePixelStreamStatus(psRef);
258
+ * return (
259
+ * <div>
260
+ * <PixelStream ref={psRef} admissionToken="tok_..." />
261
+ * <p>Status: {status}</p>
262
+ * </div>
263
+ * );
264
+ * }
265
+ * ```
266
+ */
267
+ export function usePixelStreamStatus(ref) {
268
+ const [status, setStatus] = useState('idle');
269
+ useEffect(() => {
270
+ const el = ref.current;
271
+ if (!el)
272
+ return;
273
+ // Read initial status
274
+ if (el.status)
275
+ setStatus(el.status);
276
+ const handler = (e) => {
277
+ setStatus(e.detail.newStatus);
278
+ };
279
+ el.addEventListener('status-change', handler);
280
+ return () => el.removeEventListener('status-change', handler);
281
+ }, [ref]);
282
+ return status;
283
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@interlucent/pixel-stream-react",
3
+ "version": "0.0.1",
4
+ "description": "React bindings for the @interlucent/pixel-stream web component",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "sideEffects": false,
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.build.json"
23
+ },
24
+ "dependencies": {
25
+ "@interlucent/pixel-stream": "workspace:*"
26
+ },
27
+ "peerDependencies": {
28
+ "react": ">=18.0.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/react": "^18.0.0",
32
+ "react": "^18.0.0",
33
+ "typescript": "^5.3.0"
34
+ },
35
+ "keywords": [
36
+ "pixel-streaming",
37
+ "react",
38
+ "webcomponent",
39
+ "webrtc",
40
+ "interlucent"
41
+ ],
42
+ "author": "Interlucent",
43
+ "license": "UNLICENSED",
44
+ "publishConfig": {
45
+ "access": "public"
46
+ }
47
+ }