@neroom/nevision 0.1.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 +71 -0
- package/dist/index.d.mts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +180 -0
- package/dist/index.mjs +146 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# ne-room-react
|
|
2
|
+
|
|
3
|
+
React SDK for Ne-Room session recording.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install ne-room-react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Add the `NeRoomRecorder` component to your app's root layout:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { NeRoomRecorder } from 'ne-room-react';
|
|
17
|
+
|
|
18
|
+
export default function RootLayout({ children }) {
|
|
19
|
+
return (
|
|
20
|
+
<html>
|
|
21
|
+
<body>
|
|
22
|
+
<NeRoomRecorder
|
|
23
|
+
siteId="your-site-id"
|
|
24
|
+
apiKey="your-api-key"
|
|
25
|
+
/>
|
|
26
|
+
{children}
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Prop | Type | Required | Description |
|
|
36
|
+
|------|------|----------|-------------|
|
|
37
|
+
| `siteId` | `string` | Yes | Your Ne-Room site ID |
|
|
38
|
+
| `apiKey` | `string` | Yes | Your Ne-Room API key |
|
|
39
|
+
| `apiUrl` | `string` | No | Custom API URL (default: `https://api.ne-room.io`) |
|
|
40
|
+
| `sampling` | `object` | No | Sampling options for performance |
|
|
41
|
+
| `privacy` | `object` | No | Privacy masking options |
|
|
42
|
+
| `onStart` | `(sessionId: string) => void` | No | Callback when recording starts |
|
|
43
|
+
| `onError` | `(error: Error) => void` | No | Callback on error |
|
|
44
|
+
|
|
45
|
+
## Privacy Masking
|
|
46
|
+
|
|
47
|
+
By default, password and email inputs are masked. You can customize this:
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<NeRoomRecorder
|
|
51
|
+
siteId="your-site-id"
|
|
52
|
+
apiKey="your-api-key"
|
|
53
|
+
privacy={{
|
|
54
|
+
maskAllInputs: true,
|
|
55
|
+
maskTextSelector: '.sensitive-data',
|
|
56
|
+
blockSelector: '.do-not-record',
|
|
57
|
+
}}
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### CSS Classes
|
|
62
|
+
|
|
63
|
+
Add these classes to elements for privacy control:
|
|
64
|
+
|
|
65
|
+
- `.rr-mask` - Masks text content (shows asterisks)
|
|
66
|
+
- `.rr-block` - Blocks the entire element from recording
|
|
67
|
+
- `.rr-ignore` - Ignores changes to this element
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
interface NeRoomRecorderProps {
|
|
2
|
+
siteId: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
apiUrl?: string;
|
|
5
|
+
/** Sampling options for performance */
|
|
6
|
+
sampling?: {
|
|
7
|
+
mousemove?: boolean | number;
|
|
8
|
+
mouseInteraction?: boolean;
|
|
9
|
+
scroll?: number;
|
|
10
|
+
media?: number;
|
|
11
|
+
input?: "all" | "last";
|
|
12
|
+
};
|
|
13
|
+
/** Privacy masking options */
|
|
14
|
+
privacy?: {
|
|
15
|
+
maskAllInputs?: boolean;
|
|
16
|
+
maskInputOptions?: {
|
|
17
|
+
password?: boolean;
|
|
18
|
+
email?: boolean;
|
|
19
|
+
text?: boolean;
|
|
20
|
+
tel?: boolean;
|
|
21
|
+
};
|
|
22
|
+
maskTextSelector?: string;
|
|
23
|
+
blockSelector?: string;
|
|
24
|
+
};
|
|
25
|
+
/** Callback when recording starts */
|
|
26
|
+
onStart?: (sessionId: string) => void;
|
|
27
|
+
/** Callback on error */
|
|
28
|
+
onError?: (error: Error) => void;
|
|
29
|
+
}
|
|
30
|
+
declare function NeRoomRecorder({ siteId, apiKey, apiUrl, sampling, privacy, onStart, onError, }: NeRoomRecorderProps): null;
|
|
31
|
+
|
|
32
|
+
export { NeRoomRecorder, type NeRoomRecorderProps, NeRoomRecorder as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
interface NeRoomRecorderProps {
|
|
2
|
+
siteId: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
apiUrl?: string;
|
|
5
|
+
/** Sampling options for performance */
|
|
6
|
+
sampling?: {
|
|
7
|
+
mousemove?: boolean | number;
|
|
8
|
+
mouseInteraction?: boolean;
|
|
9
|
+
scroll?: number;
|
|
10
|
+
media?: number;
|
|
11
|
+
input?: "all" | "last";
|
|
12
|
+
};
|
|
13
|
+
/** Privacy masking options */
|
|
14
|
+
privacy?: {
|
|
15
|
+
maskAllInputs?: boolean;
|
|
16
|
+
maskInputOptions?: {
|
|
17
|
+
password?: boolean;
|
|
18
|
+
email?: boolean;
|
|
19
|
+
text?: boolean;
|
|
20
|
+
tel?: boolean;
|
|
21
|
+
};
|
|
22
|
+
maskTextSelector?: string;
|
|
23
|
+
blockSelector?: string;
|
|
24
|
+
};
|
|
25
|
+
/** Callback when recording starts */
|
|
26
|
+
onStart?: (sessionId: string) => void;
|
|
27
|
+
/** Callback on error */
|
|
28
|
+
onError?: (error: Error) => void;
|
|
29
|
+
}
|
|
30
|
+
declare function NeRoomRecorder({ siteId, apiKey, apiUrl, sampling, privacy, onStart, onError, }: NeRoomRecorderProps): null;
|
|
31
|
+
|
|
32
|
+
export { NeRoomRecorder, type NeRoomRecorderProps, NeRoomRecorder as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/index.tsx
|
|
32
|
+
var index_exports = {};
|
|
33
|
+
__export(index_exports, {
|
|
34
|
+
NeRoomRecorder: () => NeRoomRecorder,
|
|
35
|
+
default: () => index_default
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
var import_react = require("react");
|
|
39
|
+
var DEFAULT_API_URL = "https://api.ne-room.io";
|
|
40
|
+
var CHUNK_INTERVAL = 1e4;
|
|
41
|
+
var MAX_EVENTS_PER_CHUNK = 100;
|
|
42
|
+
function NeRoomRecorder({
|
|
43
|
+
siteId,
|
|
44
|
+
apiKey,
|
|
45
|
+
apiUrl = DEFAULT_API_URL,
|
|
46
|
+
sampling,
|
|
47
|
+
privacy,
|
|
48
|
+
onStart,
|
|
49
|
+
onError
|
|
50
|
+
}) {
|
|
51
|
+
const sessionIdRef = (0, import_react.useRef)(null);
|
|
52
|
+
const eventsBufferRef = (0, import_react.useRef)([]);
|
|
53
|
+
const stopFnRef = (0, import_react.useRef)(null);
|
|
54
|
+
const chunkIndexRef = (0, import_react.useRef)(0);
|
|
55
|
+
(0, import_react.useEffect)(() => {
|
|
56
|
+
let intervalId;
|
|
57
|
+
const init = async () => {
|
|
58
|
+
try {
|
|
59
|
+
const { record } = await import("rrweb");
|
|
60
|
+
const startResponse = await fetch(`${apiUrl}/public/recordings/start`, {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: {
|
|
63
|
+
"Content-Type": "application/json"
|
|
64
|
+
},
|
|
65
|
+
body: JSON.stringify({
|
|
66
|
+
siteId,
|
|
67
|
+
apiKey,
|
|
68
|
+
url: window.location.href,
|
|
69
|
+
userAgent: navigator.userAgent,
|
|
70
|
+
screenWidth: window.screen.width,
|
|
71
|
+
screenHeight: window.screen.height,
|
|
72
|
+
viewportWidth: window.innerWidth,
|
|
73
|
+
viewportHeight: window.innerHeight
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
if (!startResponse.ok) {
|
|
77
|
+
throw new Error(`Failed to start recording: ${startResponse.status}`);
|
|
78
|
+
}
|
|
79
|
+
const { sessionId } = await startResponse.json();
|
|
80
|
+
sessionIdRef.current = sessionId;
|
|
81
|
+
onStart?.(sessionId);
|
|
82
|
+
const recordConfig = {
|
|
83
|
+
emit: (event) => {
|
|
84
|
+
eventsBufferRef.current.push(event);
|
|
85
|
+
},
|
|
86
|
+
sampling: sampling ? {
|
|
87
|
+
mousemove: sampling.mousemove,
|
|
88
|
+
mouseInteraction: sampling.mouseInteraction,
|
|
89
|
+
scroll: sampling.scroll,
|
|
90
|
+
media: sampling.media,
|
|
91
|
+
input: sampling.input
|
|
92
|
+
} : {
|
|
93
|
+
mousemove: 50,
|
|
94
|
+
scroll: 150
|
|
95
|
+
},
|
|
96
|
+
maskAllInputs: privacy?.maskAllInputs ?? true,
|
|
97
|
+
maskInputOptions: privacy?.maskInputOptions ?? {
|
|
98
|
+
password: true,
|
|
99
|
+
email: true
|
|
100
|
+
},
|
|
101
|
+
maskTextSelector: privacy?.maskTextSelector,
|
|
102
|
+
blockSelector: privacy?.blockSelector
|
|
103
|
+
};
|
|
104
|
+
const stopFn = record(recordConfig);
|
|
105
|
+
if (stopFn) {
|
|
106
|
+
stopFnRef.current = stopFn;
|
|
107
|
+
}
|
|
108
|
+
intervalId = setInterval(() => {
|
|
109
|
+
sendChunk(apiUrl, sessionId);
|
|
110
|
+
}, CHUNK_INTERVAL);
|
|
111
|
+
const handleUnload = () => {
|
|
112
|
+
if (sessionIdRef.current && eventsBufferRef.current.length > 0) {
|
|
113
|
+
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
114
|
+
endSession(apiUrl, sessionIdRef.current);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
window.addEventListener("beforeunload", handleUnload);
|
|
118
|
+
document.addEventListener("visibilitychange", () => {
|
|
119
|
+
if (document.visibilityState === "hidden") {
|
|
120
|
+
handleUnload();
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
} catch (error) {
|
|
124
|
+
onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const sendChunk = async (url, sessionId, isBeacon = false) => {
|
|
128
|
+
if (eventsBufferRef.current.length === 0) return;
|
|
129
|
+
const events = eventsBufferRef.current.splice(0, MAX_EVENTS_PER_CHUNK);
|
|
130
|
+
const chunkIndex = chunkIndexRef.current++;
|
|
131
|
+
const payload = JSON.stringify({
|
|
132
|
+
sessionId,
|
|
133
|
+
siteId,
|
|
134
|
+
apiKey,
|
|
135
|
+
events,
|
|
136
|
+
chunkIndex
|
|
137
|
+
});
|
|
138
|
+
if (isBeacon && navigator.sendBeacon) {
|
|
139
|
+
navigator.sendBeacon(
|
|
140
|
+
`${url}/public/recordings/chunk`,
|
|
141
|
+
new Blob([payload], { type: "application/json" })
|
|
142
|
+
);
|
|
143
|
+
} else {
|
|
144
|
+
try {
|
|
145
|
+
await fetch(`${url}/public/recordings/chunk`, {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: { "Content-Type": "application/json" },
|
|
148
|
+
body: payload
|
|
149
|
+
});
|
|
150
|
+
} catch {
|
|
151
|
+
eventsBufferRef.current.unshift(...events);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const endSession = (url, sessionId) => {
|
|
156
|
+
navigator.sendBeacon?.(
|
|
157
|
+
`${url}/public/recordings/end`,
|
|
158
|
+
new Blob(
|
|
159
|
+
[JSON.stringify({ sessionId, siteId, apiKey })],
|
|
160
|
+
{ type: "application/json" }
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
init();
|
|
165
|
+
return () => {
|
|
166
|
+
clearInterval(intervalId);
|
|
167
|
+
stopFnRef.current?.();
|
|
168
|
+
if (sessionIdRef.current) {
|
|
169
|
+
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
170
|
+
endSession(apiUrl, sessionIdRef.current);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}, [siteId, apiKey, apiUrl, sampling, privacy, onStart, onError]);
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
var index_default = NeRoomRecorder;
|
|
177
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
178
|
+
0 && (module.exports = {
|
|
179
|
+
NeRoomRecorder
|
|
180
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/index.tsx
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
var DEFAULT_API_URL = "https://api.ne-room.io";
|
|
6
|
+
var CHUNK_INTERVAL = 1e4;
|
|
7
|
+
var MAX_EVENTS_PER_CHUNK = 100;
|
|
8
|
+
function NeRoomRecorder({
|
|
9
|
+
siteId,
|
|
10
|
+
apiKey,
|
|
11
|
+
apiUrl = DEFAULT_API_URL,
|
|
12
|
+
sampling,
|
|
13
|
+
privacy,
|
|
14
|
+
onStart,
|
|
15
|
+
onError
|
|
16
|
+
}) {
|
|
17
|
+
const sessionIdRef = useRef(null);
|
|
18
|
+
const eventsBufferRef = useRef([]);
|
|
19
|
+
const stopFnRef = useRef(null);
|
|
20
|
+
const chunkIndexRef = useRef(0);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
let intervalId;
|
|
23
|
+
const init = async () => {
|
|
24
|
+
try {
|
|
25
|
+
const { record } = await import("rrweb");
|
|
26
|
+
const startResponse = await fetch(`${apiUrl}/public/recordings/start`, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: {
|
|
29
|
+
"Content-Type": "application/json"
|
|
30
|
+
},
|
|
31
|
+
body: JSON.stringify({
|
|
32
|
+
siteId,
|
|
33
|
+
apiKey,
|
|
34
|
+
url: window.location.href,
|
|
35
|
+
userAgent: navigator.userAgent,
|
|
36
|
+
screenWidth: window.screen.width,
|
|
37
|
+
screenHeight: window.screen.height,
|
|
38
|
+
viewportWidth: window.innerWidth,
|
|
39
|
+
viewportHeight: window.innerHeight
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
if (!startResponse.ok) {
|
|
43
|
+
throw new Error(`Failed to start recording: ${startResponse.status}`);
|
|
44
|
+
}
|
|
45
|
+
const { sessionId } = await startResponse.json();
|
|
46
|
+
sessionIdRef.current = sessionId;
|
|
47
|
+
onStart?.(sessionId);
|
|
48
|
+
const recordConfig = {
|
|
49
|
+
emit: (event) => {
|
|
50
|
+
eventsBufferRef.current.push(event);
|
|
51
|
+
},
|
|
52
|
+
sampling: sampling ? {
|
|
53
|
+
mousemove: sampling.mousemove,
|
|
54
|
+
mouseInteraction: sampling.mouseInteraction,
|
|
55
|
+
scroll: sampling.scroll,
|
|
56
|
+
media: sampling.media,
|
|
57
|
+
input: sampling.input
|
|
58
|
+
} : {
|
|
59
|
+
mousemove: 50,
|
|
60
|
+
scroll: 150
|
|
61
|
+
},
|
|
62
|
+
maskAllInputs: privacy?.maskAllInputs ?? true,
|
|
63
|
+
maskInputOptions: privacy?.maskInputOptions ?? {
|
|
64
|
+
password: true,
|
|
65
|
+
email: true
|
|
66
|
+
},
|
|
67
|
+
maskTextSelector: privacy?.maskTextSelector,
|
|
68
|
+
blockSelector: privacy?.blockSelector
|
|
69
|
+
};
|
|
70
|
+
const stopFn = record(recordConfig);
|
|
71
|
+
if (stopFn) {
|
|
72
|
+
stopFnRef.current = stopFn;
|
|
73
|
+
}
|
|
74
|
+
intervalId = setInterval(() => {
|
|
75
|
+
sendChunk(apiUrl, sessionId);
|
|
76
|
+
}, CHUNK_INTERVAL);
|
|
77
|
+
const handleUnload = () => {
|
|
78
|
+
if (sessionIdRef.current && eventsBufferRef.current.length > 0) {
|
|
79
|
+
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
80
|
+
endSession(apiUrl, sessionIdRef.current);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
window.addEventListener("beforeunload", handleUnload);
|
|
84
|
+
document.addEventListener("visibilitychange", () => {
|
|
85
|
+
if (document.visibilityState === "hidden") {
|
|
86
|
+
handleUnload();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const sendChunk = async (url, sessionId, isBeacon = false) => {
|
|
94
|
+
if (eventsBufferRef.current.length === 0) return;
|
|
95
|
+
const events = eventsBufferRef.current.splice(0, MAX_EVENTS_PER_CHUNK);
|
|
96
|
+
const chunkIndex = chunkIndexRef.current++;
|
|
97
|
+
const payload = JSON.stringify({
|
|
98
|
+
sessionId,
|
|
99
|
+
siteId,
|
|
100
|
+
apiKey,
|
|
101
|
+
events,
|
|
102
|
+
chunkIndex
|
|
103
|
+
});
|
|
104
|
+
if (isBeacon && navigator.sendBeacon) {
|
|
105
|
+
navigator.sendBeacon(
|
|
106
|
+
`${url}/public/recordings/chunk`,
|
|
107
|
+
new Blob([payload], { type: "application/json" })
|
|
108
|
+
);
|
|
109
|
+
} else {
|
|
110
|
+
try {
|
|
111
|
+
await fetch(`${url}/public/recordings/chunk`, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: { "Content-Type": "application/json" },
|
|
114
|
+
body: payload
|
|
115
|
+
});
|
|
116
|
+
} catch {
|
|
117
|
+
eventsBufferRef.current.unshift(...events);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const endSession = (url, sessionId) => {
|
|
122
|
+
navigator.sendBeacon?.(
|
|
123
|
+
`${url}/public/recordings/end`,
|
|
124
|
+
new Blob(
|
|
125
|
+
[JSON.stringify({ sessionId, siteId, apiKey })],
|
|
126
|
+
{ type: "application/json" }
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
init();
|
|
131
|
+
return () => {
|
|
132
|
+
clearInterval(intervalId);
|
|
133
|
+
stopFnRef.current?.();
|
|
134
|
+
if (sessionIdRef.current) {
|
|
135
|
+
sendChunk(apiUrl, sessionIdRef.current, true);
|
|
136
|
+
endSession(apiUrl, sessionIdRef.current);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}, [siteId, apiKey, apiUrl, sampling, privacy, onStart, onError]);
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
var index_default = NeRoomRecorder;
|
|
143
|
+
export {
|
|
144
|
+
NeRoomRecorder,
|
|
145
|
+
index_default as default
|
|
146
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neroom/nevision",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React SDK for Neroom session recording",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup src/index.tsx --format cjs,esm --dts --external react",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"react": ">=17.0.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"rrweb": "^2.0.0-alpha.11"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/react": "^18.2.0",
|
|
23
|
+
"react": "^18.2.0",
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "^5.0.0"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"session-recording",
|
|
29
|
+
"rrweb",
|
|
30
|
+
"react",
|
|
31
|
+
"analytics",
|
|
32
|
+
"user-behavior"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/yourusername/nevision-app"
|
|
38
|
+
}
|
|
39
|
+
}
|