react-select-media-devices-modal 0.0.9 → 0.0.10

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
@@ -12,6 +12,7 @@ A React component library for select media devices.
12
12
  ## Features
13
13
 
14
14
  - Select audio input, audio output, and video input device.
15
+ - Show preview media stream get from selected device.
15
16
 
16
17
  ## Demo
17
18
 
@@ -25,6 +26,8 @@ npm install --save react-select-media-devices-modal
25
26
 
26
27
  ## Usage
27
28
 
29
+ ### SelectMediaDevicesModal
30
+
28
31
  ```jsx
29
32
  import { useState } from 'react';
30
33
  import { SelectMediaDevicesModal } from 'react-select-media-devices-modal';
@@ -65,6 +68,48 @@ function App() {
65
68
  export default App;
66
69
  ```
67
70
 
71
+ ### SelectMediaDevicesPreviewModal
72
+
73
+ ```jsx
74
+ import { useState } from 'react';
75
+ import { SelectMediaDevicesPreviewModal } from 'react-select-media-devices-modal';
76
+
77
+ function App() {
78
+ const [modalOpen, setModalOpen] = useState(false);
79
+
80
+ const handleDeviceSelected = (devices) => {
81
+ setModalOpen(false);
82
+ console.log(devices);
83
+ };
84
+
85
+ const handleDeviceSelectCanceled = () => {
86
+ setModalOpen(false);
87
+ };
88
+
89
+ return (
90
+ <div>
91
+ <button onClick={() => setModalOpen((current) => !current)}>Select Device</button>
92
+ <SelectMediaDevicesPreviewModal
93
+ isSelectAudioInput
94
+ isSelectAudioOutput
95
+ isSelectVideoInput
96
+ open={modalOpen}
97
+ audioInputDeviceLabel="Audio input device"
98
+ audioOutputDeviceLabel="Audio output device"
99
+ videoInputDeviceLabel="Video input device"
100
+ confirmButtonText="Confirm"
101
+ cancelButtonText="Cancel"
102
+ allowOutsideClick={false}
103
+ onDeviceSelected={handleDeviceSelected}
104
+ onDeviceSelectCanceled={handleDeviceSelectCanceled}
105
+ ></SelectMediaDevicesPreviewModal>
106
+ </div>
107
+ );
108
+ }
109
+
110
+ export default App;
111
+ ```
112
+
68
113
  ## Props
69
114
 
70
115
  ### `SelectMediaDevicesModalProps`
@@ -84,6 +129,23 @@ export default App;
84
129
  | onDeviceSelected | `function` | `(devices: { audioInput?: MediaDeviceInfo; audioOutput?: MediaDeviceInfo; videoInput?: MediaDeviceInfo; }) => void` | Handler function called when devices are selected. |
85
130
  | onDeviceSelectCanceled | `function` | `() => void` | Handler function called when selection canceled. |
86
131
 
132
+ ### `SelectMediaDevicesPreviewModalProps`
133
+
134
+ | Name | Type | Default | Description |
135
+ | :--- | :--- | :------ | :---------- |
136
+ | isSelectAudioInput | `boolean` | `true` | Flag that select an audio input device or not. |
137
+ | isSelectAudioOutput | `boolean` | `true` | Flag that select an audio output device or not. |
138
+ | isSelectVideoInput | `boolean` | `true` | Flag that select a video input device or not. |
139
+ | open | `boolean` | `false` | Flag that open the modal or not. |
140
+ | audioInputDeviceLabel | `string` | `'audio input device'` | Label for list of audio input devices. |
141
+ | audioOutputDeviceLabel | `string` | `'audio output device'` | Label for list of audio output devices. |
142
+ | videoInputDeviceLabel | `string` | `'video input device'` | Label for list of video input devices. |
143
+ | confirmButtonText | `string` | `'Confirm'` | Label for the confirm button. |
144
+ | cancelButtonText | `string` | `'Cancel'` | Label for the cancel button. |
145
+ | allowOutsideClick | `boolean` | `true` | Flag that cancel selection when clicking outside of the modal. |
146
+ | onDeviceSelected | `function` | `(devices: { audioInput?: MediaDeviceInfo; audioOutput?: MediaDeviceInfo; videoInput?: MediaDeviceInfo; }) => void` | Handler function called when devices are selected. |
147
+ | onDeviceSelectCanceled | `function` | `() => void` | Handler function called when selection canceled. |
148
+
87
149
  ## LICENSE
88
150
 
89
151
  [MIT](https://github.com/kadoshita/react-select-media-devices-modal/blob/master/LICENSE)
@@ -1,99 +1,209 @@
1
- import e, { useState as l, useEffect as V } from "react";
2
- const x = "_background_1djbv_1", G = "_modal_1djbv_13", P = "_deviceLists_1djbv_20", R = "_buttons_1djbv_24", S = "_chancelButton_1djbv_31", T = "_confirmButton_1djbv_33", d = {
3
- background: x,
4
- modal: G,
5
- deviceLists: P,
6
- buttons: R,
7
- chancelButton: S,
8
- confirmButton: T
9
- }, U = () => {
10
- const [n, c] = l([]);
11
- return [n, () => {
1
+ import e, { useState as m, useEffect as O, useRef as z, useMemo as T } from "react";
2
+ const H = "_background_1djbv_1", J = "_modal_1djbv_13", K = "_deviceLists_1djbv_20", Q = "_buttons_1djbv_24", W = "_chancelButton_1djbv_31", X = "_confirmButton_1djbv_33", g = {
3
+ background: H,
4
+ modal: J,
5
+ deviceLists: K,
6
+ buttons: Q,
7
+ chancelButton: W,
8
+ confirmButton: X
9
+ }, G = () => {
10
+ const [i, o] = m([]);
11
+ return [i, () => {
12
12
  (async () => {
13
- const o = await navigator.mediaDevices.getUserMedia({ audio: !0, video: !0 }), a = await navigator.mediaDevices.enumerateDevices();
14
- c(a), o.getTracks().forEach((i) => i.stop());
13
+ const n = await navigator.mediaDevices.getUserMedia({ audio: !0, video: !0 }), a = await navigator.mediaDevices.enumerateDevices();
14
+ o(a), n.getTracks().forEach((s) => s.stop());
15
15
  })();
16
16
  }];
17
- }, z = ({ name: n, value: c }) => /* @__PURE__ */ e.createElement("option", { value: c }, n), H = "_deviceList_1bfq1_1", J = "_select_1bfq1_5", C = {
18
- deviceList: H,
19
- select: J
20
- }, b = ({ devices: n, label: c, onChange: s }) => {
21
- if (n === void 0)
17
+ }, Y = ({ name: i, value: o }) => /* @__PURE__ */ e.createElement("option", { value: o }, i), Z = "_deviceList_1bfq1_1", ee = "_select_1bfq1_5", q = {
18
+ deviceList: Z,
19
+ select: ee
20
+ }, k = ({ devices: i, label: o, onChange: u }) => {
21
+ if (i === void 0)
22
22
  return /* @__PURE__ */ e.createElement(e.Fragment, null);
23
- const o = (i) => {
24
- s(i.target.value);
25
- }, a = `device-select-${c.toLowerCase().replace(/\s/g, "-")}`;
26
- return /* @__PURE__ */ e.createElement("div", { className: C.deviceList }, /* @__PURE__ */ e.createElement("label", { htmlFor: a }, c), /* @__PURE__ */ e.createElement("select", { className: C.select, id: a, onChange: o }, n.map((i, r) => /* @__PURE__ */ e.createElement(z, { value: i.deviceId, name: i.label, key: r }))));
27
- }, K = "_button_keu24_1", Q = {
28
- button: K
29
- }, k = ({ className: n, children: c, onClick: s }) => /* @__PURE__ */ e.createElement("button", { onClick: s, className: [Q.button, n].filter(Boolean).join(" ") }, c), X = ({
30
- isSelectAudioInput: n = !0,
31
- isSelectAudioOutput: c = !0,
32
- isSelectVideoInput: s = !0,
33
- open: o,
23
+ const n = (s) => {
24
+ u(s.target.value);
25
+ }, a = `device-select-${o.toLowerCase().replace(/\s/g, "-")}`;
26
+ return /* @__PURE__ */ e.createElement("div", { className: q.deviceList }, /* @__PURE__ */ e.createElement("label", { htmlFor: a }, o), /* @__PURE__ */ e.createElement("select", { className: q.select, id: a, onChange: n }, i.map((s, h) => /* @__PURE__ */ e.createElement(Y, { value: s.deviceId, name: s.label, key: h }))));
27
+ }, te = "_button_keu24_1", ne = {
28
+ button: te
29
+ }, S = ({ className: i, children: o, onClick: u }) => /* @__PURE__ */ e.createElement("button", { onClick: u, className: [ne.button, i].filter(Boolean).join(" ") }, o), pe = ({
30
+ isSelectAudioInput: i = !0,
31
+ isSelectAudioOutput: o = !0,
32
+ isSelectVideoInput: u = !0,
33
+ open: n,
34
34
  audioInputDeviceLabel: a = "audio input device",
35
- audioOutputDeviceLabel: i = "audio output device",
36
- videoInputDeviceLabel: r = "video input device",
37
- confirmButtonText: I = "Confirm",
38
- cancelButtonText: L = "Cancel",
39
- allowOutsideClick: g = !0,
40
- onDeviceSelected: B,
35
+ audioOutputDeviceLabel: s = "audio output device",
36
+ videoInputDeviceLabel: h = "video input device",
37
+ confirmButtonText: w = "Confirm",
38
+ cancelButtonText: M = "Cancel",
39
+ allowOutsideClick: C = !0,
40
+ onDeviceSelected: j,
41
41
  onDeviceSelectCanceled: D
42
42
  }) => {
43
- const [v, N] = U(), [f, j] = l(), [h, O] = l(), [E, A] = l(), m = v.filter((t) => t.kind === "audioinput"), p = v.filter((t) => t.kind === "audiooutput"), _ = v.filter((t) => t.kind === "videoinput");
44
- V(() => {
45
- o && N();
46
- }, [o]);
47
- const F = () => {
48
- B({
49
- audioInput: f !== void 0 ? f : m[0],
50
- audioOutput: h !== void 0 ? h : p[0],
51
- videoInput: E !== void 0 ? E : _[0]
43
+ const [d, $] = G(), [E, V] = m(), [I, A] = m(), [B, y] = m(), _ = d.filter((c) => c.kind === "audioinput"), b = d.filter((c) => c.kind === "audiooutput"), f = d.filter((c) => c.kind === "videoinput");
44
+ O(() => {
45
+ n && $();
46
+ }, [n]);
47
+ const N = () => {
48
+ j({
49
+ audioInput: E !== void 0 ? E : _[0],
50
+ audioOutput: I !== void 0 ? I : b[0],
51
+ videoInput: B !== void 0 ? B : f[0]
52
52
  });
53
- }, M = () => {
53
+ }, L = () => {
54
54
  D();
55
- }, $ = (t) => {
56
- j(m.find((u) => u.deviceId === t));
57
- }, q = (t) => {
58
- O(p.find((u) => u.deviceId === t));
59
- }, w = (t) => {
60
- A(_.find((u) => u.deviceId === t));
61
- }, y = () => {
55
+ }, l = (c) => {
56
+ V(_.find((p) => p.deviceId === c));
57
+ }, P = (c) => {
58
+ A(b.find((p) => p.deviceId === c));
59
+ }, F = (c) => {
60
+ y(f.find((p) => p.deviceId === c));
61
+ }, R = () => {
62
62
  D();
63
63
  };
64
- return o ? /* @__PURE__ */ e.createElement("div", { className: d.background, ...g ? { onClick: y } : {} }, /* @__PURE__ */ e.createElement(
64
+ return n ? /* @__PURE__ */ e.createElement("div", { className: g.background, ...C ? { onClick: R } : {} }, /* @__PURE__ */ e.createElement(
65
65
  "div",
66
66
  {
67
- className: d.modal,
68
- ...g ? {
69
- onClick: (t) => t.stopPropagation()
67
+ className: g.modal,
68
+ ...C ? {
69
+ onClick: (c) => c.stopPropagation()
70
70
  } : {}
71
71
  },
72
- /* @__PURE__ */ e.createElement("div", { className: d.deviceLists }, n && /* @__PURE__ */ e.createElement(
73
- b,
72
+ /* @__PURE__ */ e.createElement("div", { className: g.deviceLists }, i && /* @__PURE__ */ e.createElement(
73
+ k,
74
74
  {
75
75
  label: a,
76
- devices: m,
77
- onChange: $
76
+ devices: _,
77
+ onChange: l
78
78
  }
79
- ), c && /* @__PURE__ */ e.createElement(
80
- b,
79
+ ), o && /* @__PURE__ */ e.createElement(
80
+ k,
81
81
  {
82
- label: i,
83
- devices: p,
84
- onChange: q
82
+ label: s,
83
+ devices: b,
84
+ onChange: P
85
85
  }
86
- ), s && /* @__PURE__ */ e.createElement(
87
- b,
86
+ ), u && /* @__PURE__ */ e.createElement(
87
+ k,
88
88
  {
89
- label: r,
90
- devices: _,
91
- onChange: w
89
+ label: h,
90
+ devices: f,
91
+ onChange: F
92
92
  }
93
93
  )),
94
- /* @__PURE__ */ e.createElement("div", { className: d.buttons }, /* @__PURE__ */ e.createElement(k, { className: d.cancelButton, onClick: M }, L), /* @__PURE__ */ e.createElement(k, { className: d.confirmButton, onClick: F }, I))
94
+ /* @__PURE__ */ e.createElement("div", { className: g.buttons }, /* @__PURE__ */ e.createElement(S, { className: g.cancelButton, onClick: L }, M), /* @__PURE__ */ e.createElement(S, { className: g.confirmButton, onClick: N }, w))
95
+ )) : /* @__PURE__ */ e.createElement(e.Fragment, null);
96
+ }, ie = "_background_kb025_1", ce = "_modal_kb025_13", oe = "_deviceSelectContainer_kb025_19", ae = "_preview_kb025_31", se = "_previewVideo_kb025_39", de = "_deviceLists_kb025_44", ue = "_buttons_kb025_50", re = "_chancelButton_kb025_57", le = "_confirmButton_kb025_59", r = {
97
+ background: ie,
98
+ modal: ce,
99
+ deviceSelectContainer: oe,
100
+ preview: ae,
101
+ previewVideo: se,
102
+ deviceLists: de,
103
+ buttons: ue,
104
+ chancelButton: re,
105
+ confirmButton: le
106
+ }, ve = () => {
107
+ const [i, o] = m();
108
+ return O(() => () => {
109
+ i !== void 0 && i.getTracks().forEach((n) => n.stop());
110
+ }, []), [i, (n) => {
111
+ n.kind !== "audiooutput" && (async () => {
112
+ const a = await navigator.mediaDevices.getUserMedia(
113
+ n.kind === "audioinput" ? { video: !1, audio: { deviceId: n.deviceId } } : { video: { deviceId: n.deviceId }, audio: !1 }
114
+ );
115
+ o(a);
116
+ })();
117
+ }];
118
+ }, _e = ({
119
+ isSelectAudioInput: i = !0,
120
+ isSelectAudioOutput: o = !0,
121
+ isSelectVideoInput: u = !0,
122
+ open: n,
123
+ audioInputDeviceLabel: a = "audio input device",
124
+ audioOutputDeviceLabel: s = "audio output device",
125
+ videoInputDeviceLabel: h = "video input device",
126
+ confirmButtonText: w = "Confirm",
127
+ cancelButtonText: M = "Cancel",
128
+ allowOutsideClick: C = !0,
129
+ onDeviceSelected: j,
130
+ onDeviceSelectCanceled: D
131
+ }) => {
132
+ const [d, $] = G(), [E, V] = m(), [I, A] = m(), [B, y] = m(), [_, b] = ve(), f = z(), N = T(() => d.filter((t) => t.kind === "audioinput"), [d]), L = T(() => d.filter((t) => t.kind === "audiooutput"), [d]), l = T(() => d.filter((t) => t.kind === "videoinput"), [d]);
133
+ O(() => {
134
+ n && $();
135
+ }, [n]), O(() => {
136
+ if (l.length < 1)
137
+ return;
138
+ const [t] = l;
139
+ b(t);
140
+ }, [l]);
141
+ const P = () => {
142
+ j({
143
+ audioInput: E !== void 0 ? E : N[0],
144
+ audioOutput: I !== void 0 ? I : L[0],
145
+ videoInput: B !== void 0 ? B : l[0]
146
+ });
147
+ }, F = () => {
148
+ D();
149
+ }, R = (t) => {
150
+ V(N.find((v) => v.deviceId === t));
151
+ }, c = (t) => {
152
+ A(L.find((v) => v.deviceId === t));
153
+ }, p = (t) => {
154
+ const v = l.find((x) => x.deviceId === t);
155
+ y(v), b(v);
156
+ };
157
+ O(() => {
158
+ const { current: t } = f;
159
+ t !== void 0 && (t.srcObject !== null && t.srcObject instanceof MediaStream && (t.srcObject.getTracks().forEach((v) => v.stop()), t.pause()), t.srcObject = _, t.play());
160
+ }, [_]);
161
+ const U = () => {
162
+ D();
163
+ };
164
+ return n ? /* @__PURE__ */ e.createElement("div", { className: r.background, ...C ? { onClick: U } : {} }, /* @__PURE__ */ e.createElement(
165
+ "div",
166
+ {
167
+ className: r.modal,
168
+ ...C ? {
169
+ onClick: (t) => t.stopPropagation()
170
+ } : {}
171
+ },
172
+ /* @__PURE__ */ e.createElement("div", { className: r.deviceSelectContainer }, /* @__PURE__ */ e.createElement("div", { className: r.preview }, /* @__PURE__ */ e.createElement(
173
+ "video",
174
+ {
175
+ className: r.previewVideo,
176
+ ref: f,
177
+ autoPlay: !0,
178
+ muted: !0,
179
+ playsInline: !0
180
+ }
181
+ )), /* @__PURE__ */ e.createElement("div", { className: r.deviceLists }, i && /* @__PURE__ */ e.createElement(
182
+ k,
183
+ {
184
+ label: a,
185
+ devices: N,
186
+ onChange: R
187
+ }
188
+ ), o && /* @__PURE__ */ e.createElement(
189
+ k,
190
+ {
191
+ label: s,
192
+ devices: L,
193
+ onChange: c
194
+ }
195
+ ), u && /* @__PURE__ */ e.createElement(
196
+ k,
197
+ {
198
+ label: h,
199
+ devices: l,
200
+ onChange: p
201
+ }
202
+ ))),
203
+ /* @__PURE__ */ e.createElement("div", { className: r.buttons }, /* @__PURE__ */ e.createElement(S, { className: r.cancelButton, onClick: F }, M), /* @__PURE__ */ e.createElement(S, { className: r.confirmButton, onClick: P }, w))
95
204
  )) : /* @__PURE__ */ e.createElement(e.Fragment, null);
96
205
  };
97
206
  export {
98
- X as SelectMediaDevicesModal
207
+ pe as SelectMediaDevicesModal,
208
+ _e as SelectMediaDevicesPreviewModal
99
209
  };
@@ -1 +1 @@
1
- (function(c,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],e):(c=typeof globalThis<"u"?globalThis:c||self,e(c.ReactSelectMediaDevicesModal={},c.React))})(this,function(c,e){"use strict";const d={background:"_background_1djbv_1",modal:"_modal_1djbv_13",deviceLists:"_deviceLists_1djbv_20",buttons:"_buttons_1djbv_24",chancelButton:"_chancelButton_1djbv_31",confirmButton:"_confirmButton_1djbv_33"},I=()=>{const[n,i]=e.useState([]);return[n,()=>{(async()=>{const s=await navigator.mediaDevices.getUserMedia({audio:!0,video:!0}),a=await navigator.mediaDevices.enumerateDevices();i(a),s.getTracks().forEach(o=>o.stop())})()}]},L=({name:n,value:i})=>e.createElement("option",{value:i},n),_={deviceList:"_deviceList_1bfq1_1",select:"_select_1bfq1_5"},r=({devices:n,label:i,onChange:u})=>{if(n===void 0)return e.createElement(e.Fragment,null);const s=o=>{u(o.target.value)},a=`device-select-${i.toLowerCase().replace(/\s/g,"-")}`;return e.createElement("div",{className:_.deviceList},e.createElement("label",{htmlFor:a},i),e.createElement("select",{className:_.select,id:a,onChange:s},n.map((o,v)=>e.createElement(L,{value:o.deviceId,name:o.label,key:v}))))},B={button:"_button_keu24_1"},g=({className:n,children:i,onClick:u})=>e.createElement("button",{onClick:u,className:[B.button,n].filter(Boolean).join(" ")},i),j=({isSelectAudioInput:n=!0,isSelectAudioOutput:i=!0,isSelectVideoInput:u=!0,open:s,audioInputDeviceLabel:a="audio input device",audioOutputDeviceLabel:o="audio output device",videoInputDeviceLabel:v="video input device",confirmButtonText:N="Confirm",cancelButtonText:M="Cancel",allowOutsideClick:h=!0,onDeviceSelected:S,onDeviceSelectCanceled:D})=>{const[m,y]=I(),[E,O]=e.useState(),[C,A]=e.useState(),[k,T]=e.useState(),f=m.filter(t=>t.kind==="audioinput"),p=m.filter(t=>t.kind==="audiooutput"),b=m.filter(t=>t.kind==="videoinput");e.useEffect(()=>{s&&y()},[s]);const q=()=>{S({audioInput:E!==void 0?E:f[0],audioOutput:C!==void 0?C:p[0],videoInput:k!==void 0?k:b[0]})},F=()=>{D()},$=t=>{O(f.find(l=>l.deviceId===t))},w=t=>{A(p.find(l=>l.deviceId===t))},x=t=>{T(b.find(l=>l.deviceId===t))},P=()=>{D()};return s?e.createElement("div",{className:d.background,...h?{onClick:P}:{}},e.createElement("div",{className:d.modal,...h?{onClick:t=>t.stopPropagation()}:{}},e.createElement("div",{className:d.deviceLists},n&&e.createElement(r,{label:a,devices:f,onChange:$}),i&&e.createElement(r,{label:o,devices:p,onChange:w}),u&&e.createElement(r,{label:v,devices:b,onChange:x})),e.createElement("div",{className:d.buttons},e.createElement(g,{className:d.cancelButton,onClick:F},M),e.createElement(g,{className:d.confirmButton,onClick:q},N)))):e.createElement(e.Fragment,null)};c.SelectMediaDevicesModal=j,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
1
+ (function(l,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],e):(l=typeof globalThis<"u"?globalThis:l||self,e(l.ReactSelectMediaDevicesModal={},l.React))})(this,function(l,e){"use strict";const p={background:"_background_1djbv_1",modal:"_modal_1djbv_13",deviceLists:"_deviceLists_1djbv_20",buttons:"_buttons_1djbv_24",chancelButton:"_chancelButton_1djbv_31",confirmButton:"_confirmButton_1djbv_33"},F=()=>{const[i,c]=e.useState([]);return[i,()=>{(async()=>{const n=await navigator.mediaDevices.getUserMedia({audio:!0,video:!0}),s=await navigator.mediaDevices.enumerateDevices();c(s),n.getTracks().forEach(d=>d.stop())})()}]},G=({name:i,value:c})=>e.createElement("option",{value:c},i),q={deviceList:"_deviceList_1bfq1_1",select:"_select_1bfq1_5"},b=({devices:i,label:c,onChange:r})=>{if(i===void 0)return e.createElement(e.Fragment,null);const n=d=>{r(d.target.value)},s=`device-select-${c.toLowerCase().replace(/\s/g,"-")}`;return e.createElement("div",{className:q.deviceList},e.createElement("label",{htmlFor:s},c),e.createElement("select",{className:q.select,id:s,onChange:n},i.map((d,h)=>e.createElement(G,{value:d.deviceId,name:d.label,key:h}))))},U={button:"_button_keu24_1"},L=({className:i,children:c,onClick:r})=>e.createElement("button",{onClick:r,className:[U.button,i].filter(Boolean).join(" ")},c),x=({isSelectAudioInput:i=!0,isSelectAudioOutput:c=!0,isSelectVideoInput:r=!0,open:n,audioInputDeviceLabel:s="audio input device",audioOutputDeviceLabel:d="audio output device",videoInputDeviceLabel:h="video input device",confirmButtonText:N="Confirm",cancelButtonText:$="Cancel",allowOutsideClick:D=!0,onDeviceSelected:w,onDeviceSelectCanceled:C})=>{const[u,O]=F(),[E,j]=e.useState(),[I,y]=e.useState(),[S,V]=e.useState(),_=u.filter(o=>o.kind==="audioinput"),g=u.filter(o=>o.kind==="audiooutput"),k=u.filter(o=>o.kind==="videoinput");e.useEffect(()=>{n&&O()},[n]);const B=()=>{w({audioInput:E!==void 0?E:_[0],audioOutput:I!==void 0?I:g[0],videoInput:S!==void 0?S:k[0]})},M=()=>{C()},v=o=>{j(_.find(f=>f.deviceId===o))},A=o=>{y(g.find(f=>f.deviceId===o))},P=o=>{V(k.find(f=>f.deviceId===o))},T=()=>{C()};return n?e.createElement("div",{className:p.background,...D?{onClick:T}:{}},e.createElement("div",{className:p.modal,...D?{onClick:o=>o.stopPropagation()}:{}},e.createElement("div",{className:p.deviceLists},i&&e.createElement(b,{label:s,devices:_,onChange:v}),c&&e.createElement(b,{label:d,devices:g,onChange:A}),r&&e.createElement(b,{label:h,devices:k,onChange:P})),e.createElement("div",{className:p.buttons},e.createElement(L,{className:p.cancelButton,onClick:M},$),e.createElement(L,{className:p.confirmButton,onClick:B},N)))):e.createElement(e.Fragment,null)},a={background:"_background_kb025_1",modal:"_modal_kb025_13",deviceSelectContainer:"_deviceSelectContainer_kb025_19",preview:"_preview_kb025_31",previewVideo:"_previewVideo_kb025_39",deviceLists:"_deviceLists_kb025_44",buttons:"_buttons_kb025_50",chancelButton:"_chancelButton_kb025_57",confirmButton:"_confirmButton_kb025_59"},z=()=>{const[i,c]=e.useState();return e.useEffect(()=>()=>{i!==void 0&&i.getTracks().forEach(n=>n.stop())},[]),[i,n=>{n.kind!=="audiooutput"&&(async()=>{const s=await navigator.mediaDevices.getUserMedia(n.kind==="audioinput"?{video:!1,audio:{deviceId:n.deviceId}}:{video:{deviceId:n.deviceId},audio:!1});c(s)})()}]},H=({isSelectAudioInput:i=!0,isSelectAudioOutput:c=!0,isSelectVideoInput:r=!0,open:n,audioInputDeviceLabel:s="audio input device",audioOutputDeviceLabel:d="audio output device",videoInputDeviceLabel:h="video input device",confirmButtonText:N="Confirm",cancelButtonText:$="Cancel",allowOutsideClick:D=!0,onDeviceSelected:w,onDeviceSelectCanceled:C})=>{const[u,O]=F(),[E,j]=e.useState(),[I,y]=e.useState(),[S,V]=e.useState(),[_,g]=z(),k=e.useRef(),B=e.useMemo(()=>u.filter(t=>t.kind==="audioinput"),[u]),M=e.useMemo(()=>u.filter(t=>t.kind==="audiooutput"),[u]),v=e.useMemo(()=>u.filter(t=>t.kind==="videoinput"),[u]);e.useEffect(()=>{n&&O()},[n]),e.useEffect(()=>{if(v.length<1)return;const[t]=v;g(t)},[v]);const A=()=>{w({audioInput:E!==void 0?E:B[0],audioOutput:I!==void 0?I:M[0],videoInput:S!==void 0?S:v[0]})},P=()=>{C()},T=t=>{j(B.find(m=>m.deviceId===t))},o=t=>{y(M.find(m=>m.deviceId===t))},f=t=>{const m=v.find(K=>K.deviceId===t);V(m),g(m)};e.useEffect(()=>{const{current:t}=k;t!==void 0&&(t.srcObject!==null&&t.srcObject instanceof MediaStream&&(t.srcObject.getTracks().forEach(m=>m.stop()),t.pause()),t.srcObject=_,t.play())},[_]);const J=()=>{C()};return n?e.createElement("div",{className:a.background,...D?{onClick:J}:{}},e.createElement("div",{className:a.modal,...D?{onClick:t=>t.stopPropagation()}:{}},e.createElement("div",{className:a.deviceSelectContainer},e.createElement("div",{className:a.preview},e.createElement("video",{className:a.previewVideo,ref:k,autoPlay:!0,muted:!0,playsInline:!0})),e.createElement("div",{className:a.deviceLists},i&&e.createElement(b,{label:s,devices:B,onChange:T}),c&&e.createElement(b,{label:d,devices:M,onChange:o}),r&&e.createElement(b,{label:h,devices:v,onChange:f}))),e.createElement("div",{className:a.buttons},e.createElement(L,{className:a.cancelButton,onClick:P},$),e.createElement(L,{className:a.confirmButton,onClick:A},N)))):e.createElement(e.Fragment,null)};l.SelectMediaDevicesModal=x,l.SelectMediaDevicesPreviewModal=H,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- ._background_1djbv_1{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0000004d;display:flex;align-items:center;justify-content:center}._modal_1djbv_13{background:white;padding:16px;border-radius:8px;min-width:270px}._deviceLists_1djbv_20{display:grid}._buttons_1djbv_24{padding-top:16px;display:flex;align-items:center;justify-content:right}._confirmButton_1djbv_33{margin-left:4px}._deviceList_1bfq1_1{padding-top:8px}._select_1bfq1_5{margin-top:4px;border-radius:4px;height:32px;display:flex;align-items:center;justify-content:right;width:100%}._button_keu24_1{border-radius:4px;height:32px;padding-left:16px;padding-right:16px;background-color:#fff;border-width:1px}
1
+ ._background_1djbv_1{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0000004d;display:flex;align-items:center;justify-content:center}._modal_1djbv_13{background:white;padding:16px;border-radius:8px;min-width:270px}._deviceLists_1djbv_20{display:grid}._buttons_1djbv_24{padding-top:16px;display:flex;align-items:center;justify-content:right}._confirmButton_1djbv_33{margin-left:4px}._deviceList_1bfq1_1{padding-top:8px}._select_1bfq1_5{margin-top:4px;border-radius:4px;height:32px;display:flex;align-items:center;justify-content:right;width:100%}._button_keu24_1{border-radius:4px;height:32px;padding-left:16px;padding-right:16px;background-color:#fff;border-width:1px}._background_kb025_1{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#0000004d;display:flex;align-items:center;justify-content:center}._modal_kb025_13{background:white;padding:16px;border-radius:8px}._deviceSelectContainer_kb025_19{display:grid;grid-template-columns:50% 50%}@media (max-width: 640px){._deviceSelectContainer_kb025_19{display:grid;grid-template-columns:100%}}._preview_kb025_31{min-width:270px;min-height:180px;max-width:270px;max-height:180px;margin-right:4px}._previewVideo_kb025_39{width:270px;height:180px}._deviceLists_kb025_44{display:grid;min-width:270px;margin-left:8px}._buttons_kb025_50{padding-top:16px;display:flex;align-items:center;justify-content:right}._confirmButton_kb025_59{margin-left:4px}
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  interface SelectMediaDevicesModalProps {
3
2
  isSelectAudioInput: boolean;
4
3
  isSelectAudioOutput: boolean;
@@ -0,0 +1,20 @@
1
+ interface SelectMediaDevicesPreviewModalProps {
2
+ isSelectAudioInput: boolean;
3
+ isSelectAudioOutput: boolean;
4
+ isSelectVideoInput: boolean;
5
+ open: boolean;
6
+ audioInputDeviceLabel: string;
7
+ audioOutputDeviceLabel: string;
8
+ videoInputDeviceLabel: string;
9
+ confirmButtonText: string;
10
+ cancelButtonText: string;
11
+ allowOutsideClick: boolean;
12
+ onDeviceSelected: (devices: {
13
+ audioInput?: MediaDeviceInfo;
14
+ audioOutput?: MediaDeviceInfo;
15
+ videoInput?: MediaDeviceInfo;
16
+ }) => void;
17
+ onDeviceSelectCanceled: () => void;
18
+ }
19
+ declare const SelectMediaDevicesPreviewModal: ({ isSelectAudioInput, isSelectAudioOutput, isSelectVideoInput, open, audioInputDeviceLabel, audioOutputDeviceLabel, videoInputDeviceLabel, confirmButtonText, cancelButtonText, allowOutsideClick, onDeviceSelected, onDeviceSelectCanceled, }: SelectMediaDevicesPreviewModalProps) => JSX.Element;
20
+ export default SelectMediaDevicesPreviewModal;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  interface DeviceItemProps {
3
2
  name: string;
4
3
  value: string;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  interface DeviceListProps {
3
2
  devices: MediaDeviceInfo[];
4
3
  label: string;
@@ -0,0 +1 @@
1
+ export declare const useGetMediaStream: () => [MediaStream, (device: MediaDeviceInfo) => void];
@@ -1 +1,2 @@
1
1
  export { default as SelectMediaDevicesModal } from './SelectMediaDevicesModal';
2
+ export { default as SelectMediaDevicesPreviewModal } from './SelectMediaDevicesPreviewModal';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-select-media-devices-modal",
3
3
  "description": "A React component library for select media devices",
4
- "version": "0.0.9",
4
+ "version": "0.0.10",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -34,9 +34,10 @@
34
34
  "scripts": {
35
35
  "dev": "vite serve example",
36
36
  "build": "vite build",
37
- "test": "vitest",
37
+ "test": "vitest run",
38
38
  "coverage": "vitest run --coverage",
39
- "test:e2e": "vitest run -c vitest.e2e.config.ts"
39
+ "test:e2e": "vitest run -c vitest.e2e.config.ts",
40
+ "test:e2e:watch": "vitest watch -c vitest.e2e.config.ts"
40
41
  },
41
42
  "dependencies": {
42
43
  "react": "^18.2.0",