@signalwire/web-components 4.0.0-beta.8 → 4.0.0-dev-20260515133934
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 +48 -55
- package/dist/_virtual/_commonjsHelpers.js +9 -0
- package/dist/_virtual/_commonjsHelpers.js.map +1 -0
- package/dist/_virtual/prism-python.js +28 -0
- package/dist/_virtual/prism-python.js.map +1 -0
- package/dist/_virtual/prism-python2.js +5 -0
- package/dist/_virtual/prism-python2.js.map +1 -0
- package/dist/_virtual/prism-typescript.js +28 -0
- package/dist/_virtual/prism-typescript.js.map +1 -0
- package/dist/_virtual/prism-typescript2.js +5 -0
- package/dist/_virtual/prism-typescript2.js.map +1 -0
- package/dist/_virtual/prism.js +28 -0
- package/dist/_virtual/prism.js.map +1 -0
- package/dist/_virtual/prism2.js +5 -0
- package/dist/_virtual/prism2.js.map +1 -0
- package/dist/assets/sw_background.webp.js +5 -0
- package/dist/assets/sw_background.webp.js.map +1 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.d.ts +4 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.d.ts.map +1 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.js +5 -0
- package/dist/components/UI/DEFAULT_BACKGROUND.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-control-bar.d.ts +114 -0
- package/dist/components/UI/controls/sw-ui-control-bar.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-control-bar.js +324 -0
- package/dist/components/UI/controls/sw-ui-control-bar.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-dialpad.d.ts +67 -0
- package/dist/components/UI/controls/sw-ui-dialpad.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-dialpad.js +360 -0
- package/dist/components/UI/controls/sw-ui-dialpad.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-dropup.d.ts +42 -0
- package/dist/components/UI/controls/sw-ui-dropup.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-dropup.js +138 -0
- package/dist/components/UI/controls/sw-ui-dropup.js.map +1 -0
- package/dist/components/UI/controls/sw-ui-split-button.d.ts +44 -0
- package/dist/components/UI/controls/sw-ui-split-button.d.ts.map +1 -0
- package/dist/components/UI/controls/sw-ui-split-button.js +178 -0
- package/dist/components/UI/controls/sw-ui-split-button.js.map +1 -0
- package/dist/components/UI/host-reset.d.ts +16 -0
- package/dist/components/UI/host-reset.d.ts.map +1 -0
- package/dist/components/UI/host-reset.js +20 -0
- package/dist/components/UI/host-reset.js.map +1 -0
- package/dist/components/UI/icons/backspace.svg.js +10 -0
- package/dist/components/UI/icons/backspace.svg.js.map +1 -0
- package/dist/components/UI/icons/camera-off.svg.js +8 -0
- package/dist/components/UI/icons/camera-off.svg.js.map +1 -0
- package/dist/components/UI/icons/camera-on.svg.js +8 -0
- package/dist/components/UI/icons/camera-on.svg.js.map +1 -0
- package/dist/components/UI/icons/check-circle.svg.js +6 -0
- package/dist/components/UI/icons/check-circle.svg.js.map +1 -0
- package/dist/components/UI/icons/chevron-up.svg.js +8 -0
- package/dist/components/UI/icons/chevron-up.svg.js.map +1 -0
- package/dist/components/UI/icons/close.svg.js +6 -0
- package/dist/components/UI/icons/close.svg.js.map +1 -0
- package/dist/components/UI/icons/copy.svg.js +6 -0
- package/dist/components/UI/icons/copy.svg.js.map +1 -0
- package/dist/components/UI/icons/download.svg.js +6 -0
- package/dist/components/UI/icons/download.svg.js.map +1 -0
- package/dist/components/UI/icons/fullscreen-exit.svg.js +8 -0
- package/dist/components/UI/icons/fullscreen-exit.svg.js.map +1 -0
- package/dist/components/UI/icons/fullscreen.svg.js +8 -0
- package/dist/components/UI/icons/fullscreen.svg.js.map +1 -0
- package/dist/components/UI/icons/hand-raise.svg.js +6 -0
- package/dist/components/UI/icons/hand-raise.svg.js.map +1 -0
- package/dist/components/UI/icons/icons.d.ts +31 -0
- package/dist/components/UI/icons/icons.d.ts.map +1 -0
- package/dist/components/UI/icons/icons.js +60 -0
- package/dist/components/UI/icons/icons.js.map +1 -0
- package/dist/components/UI/icons/index.d.ts +4 -0
- package/dist/components/UI/icons/index.d.ts.map +1 -0
- package/dist/components/UI/icons/info-circle.svg.js +6 -0
- package/dist/components/UI/icons/info-circle.svg.js.map +1 -0
- package/dist/components/UI/icons/mic-off.svg.js +8 -0
- package/dist/components/UI/icons/mic-off.svg.js.map +1 -0
- package/dist/components/UI/icons/mic-on.svg.js +8 -0
- package/dist/components/UI/icons/mic-on.svg.js.map +1 -0
- package/dist/components/UI/icons/person.svg.js +8 -0
- package/dist/components/UI/icons/person.svg.js.map +1 -0
- package/dist/components/UI/icons/phone-call.svg.js +8 -0
- package/dist/components/UI/icons/phone-call.svg.js.map +1 -0
- package/dist/components/UI/icons/phone-end.svg.js +8 -0
- package/dist/components/UI/icons/phone-end.svg.js.map +1 -0
- package/dist/components/UI/icons/room.svg.js +8 -0
- package/dist/components/UI/icons/room.svg.js.map +1 -0
- package/dist/components/UI/icons/screen-share-off.svg.js +9 -0
- package/dist/components/UI/icons/screen-share-off.svg.js.map +1 -0
- package/dist/components/UI/icons/screen-share.svg.js +9 -0
- package/dist/components/UI/icons/screen-share.svg.js.map +1 -0
- package/dist/components/UI/icons/sendIcon.svg.js +9 -0
- package/dist/components/UI/icons/sendIcon.svg.js.map +1 -0
- package/dist/components/UI/icons/settings.svg.js +8 -0
- package/dist/components/UI/icons/settings.svg.js.map +1 -0
- package/dist/components/UI/icons/speaker-off.svg.js +8 -0
- package/dist/components/UI/icons/speaker-off.svg.js.map +1 -0
- package/dist/components/UI/icons/speaker-on.svg.js +8 -0
- package/dist/components/UI/icons/speaker-on.svg.js.map +1 -0
- package/dist/components/UI/icons/spinner.svg.js +9 -0
- package/dist/components/UI/icons/spinner.svg.js.map +1 -0
- package/dist/components/UI/icons/sw-logo.svg.js +11 -0
- package/dist/components/UI/icons/sw-logo.svg.js.map +1 -0
- package/dist/components/UI/icons/sw-ui-icon.d.ts +28 -0
- package/dist/components/UI/icons/sw-ui-icon.d.ts.map +1 -0
- package/dist/components/UI/icons/sw-ui-icon.js +47 -0
- package/dist/components/UI/icons/sw-ui-icon.js.map +1 -0
- package/dist/components/UI/icons/transcript.svg.js +10 -0
- package/dist/components/UI/icons/transcript.svg.js.map +1 -0
- package/dist/components/UI/index.d.ts +18 -0
- package/dist/components/UI/index.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-background.d.ts +33 -0
- package/dist/components/UI/layout/sw-ui-background.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-background.js +106 -0
- package/dist/components/UI/layout/sw-ui-background.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-call-layout.d.ts +69 -0
- package/dist/components/UI/layout/sw-ui-call-layout.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-call-layout.js +278 -0
- package/dist/components/UI/layout/sw-ui-call-layout.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.d.ts +50 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.js +413 -0
- package/dist/components/UI/layout/sw-ui-content-drawer.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-modal.d.ts +31 -0
- package/dist/components/UI/layout/sw-ui-modal.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-modal.js +150 -0
- package/dist/components/UI/layout/sw-ui-modal.js.map +1 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.d.ts +15 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.d.ts.map +1 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.js +78 -0
- package/dist/components/UI/layout/sw-ui-responsive-container.js.map +1 -0
- package/dist/components/UI/sw-ui-alert.d.ts +37 -0
- package/dist/components/UI/sw-ui-alert.d.ts.map +1 -0
- package/dist/components/UI/sw-ui-alert.js +127 -0
- package/dist/components/UI/sw-ui-alert.js.map +1 -0
- package/dist/components/UI/sw-ui-transcript-view.d.ts +56 -0
- package/dist/components/UI/sw-ui-transcript-view.d.ts.map +1 -0
- package/dist/components/UI/sw-ui-transcript-view.js +342 -0
- package/dist/components/UI/sw-ui-transcript-view.js.map +1 -0
- package/dist/components/{audio-level.d.ts → sw-audio-level.d.ts} +44 -4
- package/dist/components/sw-audio-level.d.ts.map +1 -0
- package/dist/components/sw-audio-level.js +252 -0
- package/dist/components/sw-audio-level.js.map +1 -0
- package/dist/components/sw-call-controls.d.ts +58 -0
- package/dist/components/sw-call-controls.d.ts.map +1 -0
- package/dist/components/sw-call-controls.js +186 -0
- package/dist/components/sw-call-controls.js.map +1 -0
- package/dist/components/sw-call-dialpad.d.ts +52 -0
- package/dist/components/sw-call-dialpad.d.ts.map +1 -0
- package/dist/components/sw-call-dialpad.js +70 -0
- package/dist/components/sw-call-dialpad.js.map +1 -0
- package/dist/components/sw-call-media.d.ts +59 -0
- package/dist/components/sw-call-media.d.ts.map +1 -0
- package/dist/components/sw-call-media.js +178 -0
- package/dist/components/sw-call-media.js.map +1 -0
- package/dist/components/sw-call-provider.d.ts +41 -0
- package/dist/components/sw-call-provider.d.ts.map +1 -0
- package/dist/components/sw-call-provider.js +37 -0
- package/dist/components/sw-call-provider.js.map +1 -0
- package/dist/components/sw-call-status.d.ts +50 -0
- package/dist/components/sw-call-status.d.ts.map +1 -0
- package/dist/components/sw-call-status.js +204 -0
- package/dist/components/sw-call-status.js.map +1 -0
- package/dist/components/sw-call-widget/client-factory.d.ts +6 -0
- package/dist/components/sw-call-widget/client-factory.d.ts.map +1 -0
- package/dist/components/sw-call-widget/client-factory.js +25 -0
- package/dist/components/sw-call-widget/client-factory.js.map +1 -0
- package/dist/components/sw-call-widget/sw-call-widget.d.ts +110 -0
- package/dist/components/sw-call-widget/sw-call-widget.d.ts.map +1 -0
- package/dist/components/sw-call-widget/sw-call-widget.js +251 -0
- package/dist/components/sw-call-widget/sw-call-widget.js.map +1 -0
- package/dist/components/sw-call-widget/sw-call-widget.templates.d.ts +17 -0
- package/dist/components/sw-call-widget/sw-call-widget.templates.d.ts.map +1 -0
- package/dist/components/sw-call-widget/sw-call-widget.templates.js +80 -0
- package/dist/components/sw-call-widget/sw-call-widget.templates.js.map +1 -0
- package/dist/components/sw-click-to-call.d.ts +39 -0
- package/dist/components/sw-click-to-call.d.ts.map +1 -0
- package/dist/components/sw-click-to-call.js +88 -0
- package/dist/components/sw-click-to-call.js.map +1 -0
- package/dist/components/sw-device-selector/index.d.ts +2 -0
- package/dist/components/sw-device-selector/index.d.ts.map +1 -0
- package/dist/components/sw-device-selector/sw-device-selector.d.ts +69 -0
- package/dist/components/sw-device-selector/sw-device-selector.d.ts.map +1 -0
- package/dist/components/sw-device-selector/sw-device-selector.js +278 -0
- package/dist/components/sw-device-selector/sw-device-selector.js.map +1 -0
- package/dist/components/sw-device-selector/sw-device-selector.styles.d.ts +2 -0
- package/dist/components/sw-device-selector/sw-device-selector.styles.d.ts.map +1 -0
- package/dist/components/sw-device-selector/sw-device-selector.styles.js +238 -0
- package/dist/components/sw-device-selector/sw-device-selector.styles.js.map +1 -0
- package/dist/components/{directory.d.ts → sw-directory.d.ts} +18 -4
- package/dist/components/sw-directory.d.ts.map +1 -0
- package/dist/components/sw-directory.js +435 -0
- package/dist/components/sw-directory.js.map +1 -0
- package/dist/components/sw-local-camera.d.ts +53 -0
- package/dist/components/sw-local-camera.d.ts.map +1 -0
- package/dist/components/sw-local-camera.js +147 -0
- package/dist/components/sw-local-camera.js.map +1 -0
- package/dist/components/sw-participant-controls.d.ts +58 -0
- package/dist/components/sw-participant-controls.d.ts.map +1 -0
- package/dist/components/sw-participant-controls.js +306 -0
- package/dist/components/sw-participant-controls.js.map +1 -0
- package/dist/components/sw-participants.d.ts +55 -0
- package/dist/components/sw-participants.d.ts.map +1 -0
- package/dist/components/sw-participants.js +320 -0
- package/dist/components/sw-participants.js.map +1 -0
- package/dist/components/sw-self-media.d.ts +46 -0
- package/dist/components/sw-self-media.d.ts.map +1 -0
- package/dist/components/sw-self-media.js +106 -0
- package/dist/components/sw-self-media.js.map +1 -0
- package/dist/context/CallStateContextController.d.ts +31 -0
- package/dist/context/CallStateContextController.d.ts.map +1 -0
- package/dist/context/CallStateContextController.js +125 -0
- package/dist/context/CallStateContextController.js.map +1 -0
- package/dist/context/DevicesContextController.d.ts +38 -0
- package/dist/context/DevicesContextController.d.ts.map +1 -0
- package/dist/context/DevicesContextController.js +124 -0
- package/dist/context/DevicesContextController.js.map +1 -0
- package/dist/context/TranscriptController.d.ts +32 -0
- package/dist/context/TranscriptController.d.ts.map +1 -0
- package/dist/context/TranscriptController.js +113 -0
- package/dist/context/TranscriptController.js.map +1 -0
- package/dist/context/UserEventController.d.ts +26 -0
- package/dist/context/UserEventController.d.ts.map +1 -0
- package/dist/context/UserEventController.js +55 -0
- package/dist/context/UserEventController.js.map +1 -0
- package/dist/context/call-state-context.d.ts +75 -0
- package/dist/context/call-state-context.d.ts.map +1 -0
- package/dist/context/call-state-context.js +39 -0
- package/dist/context/call-state-context.js.map +1 -0
- package/dist/context/chat-state.d.ts +41 -0
- package/dist/context/chat-state.d.ts.map +1 -0
- package/dist/context/chat-state.js +61 -0
- package/dist/context/chat-state.js.map +1 -0
- package/dist/context/devices-context.d.ts +28 -0
- package/dist/context/devices-context.d.ts.map +1 -0
- package/dist/context/devices-context.js +6 -0
- package/dist/context/devices-context.js.map +1 -0
- package/dist/context/index.d.ts +9 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/transcript-context.d.ts +9 -0
- package/dist/context/transcript-context.d.ts.map +1 -0
- package/dist/context/transcript-context.js +6 -0
- package/dist/context/transcript-context.js.map +1 -0
- package/dist/context/types.d.ts +9 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/embed/signalwire-web-components-embed.iife.js +3237 -0
- package/dist/embed/signalwire-web-components-embed.iife.js.map +1 -0
- package/dist/embed/signalwire-web-components-embed.umd.cjs +3237 -0
- package/dist/embed/signalwire-web-components-embed.umd.cjs.map +1 -0
- package/dist/embed.d.ts +20 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/index.d.ts +19 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -35
- package/dist/index.js.map +1 -1
- package/dist/node_modules/dompurify/dist/purify.es.js +597 -0
- package/dist/node_modules/dompurify/dist/purify.es.js.map +1 -0
- package/dist/node_modules/marked/lib/marked.esm.js +1475 -0
- package/dist/node_modules/marked/lib/marked.esm.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-bash.js +220 -0
- package/dist/node_modules/prismjs/components/prism-bash.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-css.js +56 -0
- package/dist/node_modules/prismjs/components/prism-css.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-javascript.js +138 -0
- package/dist/node_modules/prismjs/components/prism-javascript.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-json.js +26 -0
- package/dist/node_modules/prismjs/components/prism-json.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-markdown.js +301 -0
- package/dist/node_modules/prismjs/components/prism-markdown.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-python.js +69 -0
- package/dist/node_modules/prismjs/components/prism-python.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-sql.js +34 -0
- package/dist/node_modules/prismjs/components/prism-sql.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-typescript.js +53 -0
- package/dist/node_modules/prismjs/components/prism-typescript.js.map +1 -0
- package/dist/node_modules/prismjs/components/prism-yaml.js +67 -0
- package/dist/node_modules/prismjs/components/prism-yaml.js.map +1 -0
- package/dist/node_modules/prismjs/prism.js +1165 -0
- package/dist/node_modules/prismjs/prism.js.map +1 -0
- package/dist/react.d.ts +96 -46
- package/dist/theme.css +451 -0
- package/dist/theme.css.js +5 -0
- package/dist/theme.css.js.map +1 -0
- package/dist/types/index.d.ts +9 -33
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/prism.d.ts +4 -0
- package/dist/utils/prism.d.ts.map +1 -0
- package/dist/utils/prism.js +34 -0
- package/dist/utils/prism.js.map +1 -0
- package/dist/utils/theme-loader.d.ts +11 -0
- package/dist/utils/theme-loader.d.ts.map +1 -0
- package/dist/utils/theme-loader.js +17 -0
- package/dist/utils/theme-loader.js.map +1 -0
- package/dist/utils/transcriptToMarkdown.d.ts +14 -0
- package/dist/utils/transcriptToMarkdown.d.ts.map +1 -0
- package/dist/utils/transcriptToMarkdown.js +59 -0
- package/dist/utils/transcriptToMarkdown.js.map +1 -0
- package/dist/utils/use-google-font.d.ts +18 -0
- package/dist/utils/use-google-font.d.ts.map +1 -0
- package/dist/utils/use-google-font.js +12 -0
- package/dist/utils/use-google-font.js.map +1 -0
- package/dist/utils/user-variables.d.ts +20 -0
- package/dist/utils/user-variables.d.ts.map +1 -0
- package/dist/utils/user-variables.js +37 -0
- package/dist/utils/user-variables.js.map +1 -0
- package/dist/utils/video.js +6 -21
- package/dist/utils/video.js.map +1 -1
- package/package.json +105 -42
- package/dist/components/audio-level.d.ts.map +0 -1
- package/dist/components/audio-level.js +0 -203
- package/dist/components/audio-level.js.map +0 -1
- package/dist/components/call-controls.d.ts +0 -163
- package/dist/components/call-controls.d.ts.map +0 -1
- package/dist/components/call-controls.js +0 -606
- package/dist/components/call-controls.js.map +0 -1
- package/dist/components/call-media.d.ts +0 -114
- package/dist/components/call-media.d.ts.map +0 -1
- package/dist/components/call-media.js +0 -219
- package/dist/components/call-media.js.map +0 -1
- package/dist/components/call-status.d.ts +0 -68
- package/dist/components/call-status.d.ts.map +0 -1
- package/dist/components/call-status.js +0 -254
- package/dist/components/call-status.js.map +0 -1
- package/dist/components/click-to-call.d.ts +0 -123
- package/dist/components/click-to-call.d.ts.map +0 -1
- package/dist/components/click-to-call.js +0 -428
- package/dist/components/click-to-call.js.map +0 -1
- package/dist/components/device-selector.d.ts +0 -224
- package/dist/components/device-selector.d.ts.map +0 -1
- package/dist/components/device-selector.js +0 -685
- package/dist/components/device-selector.js.map +0 -1
- package/dist/components/dialpad.d.ts +0 -60
- package/dist/components/dialpad.d.ts.map +0 -1
- package/dist/components/dialpad.js +0 -372
- package/dist/components/dialpad.js.map +0 -1
- package/dist/components/directory.d.ts.map +0 -1
- package/dist/components/directory.js +0 -503
- package/dist/components/directory.js.map +0 -1
- package/dist/components/example-button.d.ts +0 -20
- package/dist/components/example-button.d.ts.map +0 -1
- package/dist/components/example-button.js +0 -74
- package/dist/components/example-button.js.map +0 -1
- package/dist/components/participant-controls.d.ts +0 -94
- package/dist/components/participant-controls.d.ts.map +0 -1
- package/dist/components/participant-controls.js +0 -468
- package/dist/components/participant-controls.js.map +0 -1
- package/dist/components/participants.d.ts +0 -116
- package/dist/components/participants.d.ts.map +0 -1
- package/dist/components/participants.js +0 -394
- package/dist/components/participants.js.map +0 -1
- package/dist/components/self-media.d.ts +0 -78
- package/dist/components/self-media.d.ts.map +0 -1
- package/dist/components/self-media.js +0 -129
- package/dist/components/self-media.js.map +0 -1
- package/dist/constants.js +0 -5
- package/dist/constants.js.map +0 -1
- package/dist/context/call-context.d.ts +0 -13
- package/dist/context/call-context.d.ts.map +0 -1
- package/dist/context/call-context.js +0 -6
- package/dist/context/call-context.js.map +0 -1
- package/dist/types/index.js +0 -12
- package/dist/types/index.js.map +0 -1
- package/dist/utils/debounce.js +0 -13
- package/dist/utils/debounce.js.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { LitElement as p, html as n, css as m } from "lit";
|
|
2
|
+
import { property as l, state as d, customElement as f } from "lit/decorators.js";
|
|
3
|
+
import { consume as h } from "@lit/context";
|
|
4
|
+
import { attachMediaStream as v, detachMediaStream as _ } from "../utils/video.js";
|
|
5
|
+
import { callStateContext as S } from "../context/call-state-context.js";
|
|
6
|
+
import { devicesContext as b } from "../context/devices-context.js";
|
|
7
|
+
var y = Object.defineProperty, w = Object.getOwnPropertyDescriptor, c = (t, e, s, r) => {
|
|
8
|
+
for (var i = r > 1 ? void 0 : r ? w(e, s) : e, o = t.length - 1, u; o >= 0; o--)
|
|
9
|
+
(u = t[o]) && (i = (r ? u(e, s, i) : u(i)) || i);
|
|
10
|
+
return r && i && y(e, s, i), i;
|
|
11
|
+
};
|
|
12
|
+
let a = class extends p {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments), this.stream = null, this.mirror = !1, this._directLocalStream = null, this._directSubscriptions = [], this._aspectRatio = "16 / 9", this._attachedStream = null;
|
|
15
|
+
}
|
|
16
|
+
get _effectiveStream() {
|
|
17
|
+
var t;
|
|
18
|
+
return this.stream ? this.stream : this.call ? this._directLocalStream : ((t = this._callState) == null ? void 0 : t.localStream) ?? null;
|
|
19
|
+
}
|
|
20
|
+
get _effectiveMuted() {
|
|
21
|
+
var t;
|
|
22
|
+
return this.videoMuted ?? ((t = this._devicesState) == null ? void 0 : t.videoMuted) ?? !1;
|
|
23
|
+
}
|
|
24
|
+
firstUpdated() {
|
|
25
|
+
var e;
|
|
26
|
+
const t = (e = this.shadowRoot) == null ? void 0 : e.querySelector("video");
|
|
27
|
+
t && t.addEventListener("pause", () => {
|
|
28
|
+
this._effectiveMuted || t.play().catch(() => {
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
updated(t) {
|
|
33
|
+
var r, i;
|
|
34
|
+
super.updated(t), t.has("call") && (this._teardownDirect(), this.call && this._setupDirect(this.call));
|
|
35
|
+
const e = this._effectiveStream, s = t.has("stream") || t.has("call") || t.has("_directLocalStream") || t.has("_callState") && e !== this._attachedStream;
|
|
36
|
+
if (s) {
|
|
37
|
+
const o = (r = this.shadowRoot) == null ? void 0 : r.querySelector("video");
|
|
38
|
+
o && (this._attachedStream = e, v(o, e), this._detectAspectRatio());
|
|
39
|
+
}
|
|
40
|
+
if ((t.has("videoMuted") || t.has("_devicesState") || s) && !this._effectiveMuted) {
|
|
41
|
+
const o = (i = this.shadowRoot) == null ? void 0 : i.querySelector("video");
|
|
42
|
+
o && o.play().catch(() => {
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
disconnectedCallback() {
|
|
47
|
+
var e;
|
|
48
|
+
super.disconnectedCallback();
|
|
49
|
+
const t = (e = this.shadowRoot) == null ? void 0 : e.querySelector("video");
|
|
50
|
+
t && _(t), this._teardownDirect();
|
|
51
|
+
}
|
|
52
|
+
_setupDirect(t) {
|
|
53
|
+
this._directSubscriptions.push(
|
|
54
|
+
t.localStream$.subscribe((e) => this._directLocalStream = e)
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
_teardownDirect() {
|
|
58
|
+
this._directSubscriptions.forEach((t) => t.unsubscribe()), this._directSubscriptions = [], this._directLocalStream = null;
|
|
59
|
+
}
|
|
60
|
+
/** Read the video track settings and set the CSS custom property. */
|
|
61
|
+
_detectAspectRatio() {
|
|
62
|
+
const t = this._effectiveStream;
|
|
63
|
+
if (!t) return;
|
|
64
|
+
const e = t.getVideoTracks()[0];
|
|
65
|
+
if (!e) return;
|
|
66
|
+
const s = e.getSettings(), r = s.width, i = s.height;
|
|
67
|
+
r && i && r > 0 && i > 0 && (this._aspectRatio = `${r} / ${i}`, this.style.setProperty("--sw-local-camera-aspect", this._aspectRatio));
|
|
68
|
+
}
|
|
69
|
+
render() {
|
|
70
|
+
return n`
|
|
71
|
+
<video part="video" autoplay playsinline muted></video>
|
|
72
|
+
${this._effectiveMuted ? n`<div part="placeholder" class="muted-overlay">
|
|
73
|
+
<sw-ui-icon name="camera-off" size="28"></sw-ui-icon>
|
|
74
|
+
</div>` : null}
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
a.styles = m`
|
|
79
|
+
:host {
|
|
80
|
+
display: block;
|
|
81
|
+
width: 100%;
|
|
82
|
+
aspect-ratio: var(--sw-local-camera-aspect, 16 / 9);
|
|
83
|
+
position: relative;
|
|
84
|
+
background: #000;
|
|
85
|
+
border-radius: inherit;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
video {
|
|
89
|
+
width: 100%;
|
|
90
|
+
height: 100%;
|
|
91
|
+
object-fit: cover;
|
|
92
|
+
display: block;
|
|
93
|
+
border-radius: inherit;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
:host([mirror]) video {
|
|
97
|
+
transform: scaleX(-1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.muted-overlay {
|
|
101
|
+
position: absolute;
|
|
102
|
+
inset: 0;
|
|
103
|
+
z-index: 1;
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
background: var(--bg-page);
|
|
108
|
+
border-radius: inherit;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.muted-overlay sw-ui-icon {
|
|
112
|
+
color: var(--bg-surface-raised);
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
c([
|
|
116
|
+
l({ attribute: !1 })
|
|
117
|
+
], a.prototype, "stream", 2);
|
|
118
|
+
c([
|
|
119
|
+
l({ type: Boolean, reflect: !0, attribute: "video-muted" })
|
|
120
|
+
], a.prototype, "videoMuted", 2);
|
|
121
|
+
c([
|
|
122
|
+
l({ type: Object })
|
|
123
|
+
], a.prototype, "call", 2);
|
|
124
|
+
c([
|
|
125
|
+
l({ type: Boolean, reflect: !0 })
|
|
126
|
+
], a.prototype, "mirror", 2);
|
|
127
|
+
c([
|
|
128
|
+
h({ context: S, subscribe: !0 }),
|
|
129
|
+
d()
|
|
130
|
+
], a.prototype, "_callState", 2);
|
|
131
|
+
c([
|
|
132
|
+
h({ context: b, subscribe: !0 }),
|
|
133
|
+
d()
|
|
134
|
+
], a.prototype, "_devicesState", 2);
|
|
135
|
+
c([
|
|
136
|
+
d()
|
|
137
|
+
], a.prototype, "_directLocalStream", 2);
|
|
138
|
+
c([
|
|
139
|
+
d()
|
|
140
|
+
], a.prototype, "_aspectRatio", 2);
|
|
141
|
+
a = c([
|
|
142
|
+
f("sw-local-camera")
|
|
143
|
+
], a);
|
|
144
|
+
export {
|
|
145
|
+
a as SwLocalCamera
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=sw-local-camera.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sw-local-camera.js","sources":["../../src/components/sw-local-camera.ts"],"sourcesContent":["import { LitElement, html, css } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\nimport { Subscription } from 'rxjs';\nimport { attachMediaStream, detachMediaStream } from '../utils/video.js';\nimport { callStateContext, type CallState } from '../context/call-state-context.js';\nimport { devicesContext, type DevicesState } from '../context/devices-context.js';\nimport type { Call } from '../types/index.js';\nimport './UI/icons/sw-ui-icon.js';\n\n/**\n * Local camera preview. Adapts its aspect-ratio to match the actual\n * video track (landscape or portrait).\n *\n * Input precedence : `.stream`/`.videoMuted` > `.call` > context.\n *\n * @prop {MediaStream|null} stream - explicit stream (overrides .call and context)\n * @prop {boolean} videoMuted - explicit muted flag (overrides context)\n * @prop {Call} call - explicit Call object (overrides context)\n * @prop {boolean} mirror - mirror the video horizontally\n *\n * @csspart video - The `<video>` element.\n * @csspart placeholder - Camera-off overlay shown while muted.\n *\n * @cssprop [--sw-local-camera-aspect=16/9] - Aspect ratio; auto-set from track settings when available.\n */\n@customElement('sw-local-camera')\nexport class SwLocalCamera extends LitElement {\n /** Explicit stream — highest precedence. */\n @property({ attribute: false }) stream: MediaStream | null = null;\n\n /** Explicit muted flag — overrides devicesContext.videoMuted. */\n @property({ type: Boolean, reflect: true, attribute: 'video-muted' }) videoMuted?: boolean;\n\n /** Explicit Call — used when `.stream` is not set. Bypasses context. */\n @property({ type: Object }) call?: Call;\n\n @property({ type: Boolean, reflect: true }) mirror = false;\n\n @consume({ context: callStateContext, subscribe: true })\n @state()\n private _callState?: CallState;\n\n @consume({ context: devicesContext, subscribe: true })\n @state()\n private _devicesState?: DevicesState;\n\n @state() private _directLocalStream: MediaStream | null = null;\n\n private _directSubscriptions: Subscription[] = [];\n\n /** Detected aspect ratio from the video track, e.g. \"16 / 9\" or \"9 / 16\". */\n @state() private _aspectRatio = '16 / 9';\n\n /** Last stream reference attached to the video element — used to skip no-op re-attaches. */\n private _attachedStream: MediaStream | null = null;\n\n static styles = css`\n :host {\n display: block;\n width: 100%;\n aspect-ratio: var(--sw-local-camera-aspect, 16 / 9);\n position: relative;\n background: #000;\n border-radius: inherit;\n }\n\n video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n border-radius: inherit;\n }\n\n :host([mirror]) video {\n transform: scaleX(-1);\n }\n\n .muted-overlay {\n position: absolute;\n inset: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--bg-page);\n border-radius: inherit;\n }\n\n .muted-overlay sw-ui-icon {\n color: var(--bg-surface-raised);\n }\n `;\n\n private get _effectiveStream(): MediaStream | null {\n if (this.stream) return this.stream;\n if (this.call) return this._directLocalStream;\n return this._callState?.localStream ?? null;\n }\n\n private get _effectiveMuted(): boolean {\n return this.videoMuted ?? this._devicesState?.videoMuted ?? false;\n }\n\n protected firstUpdated(): void {\n // Mirror the anti-pause handler from createVideoElement so Safari/Firefox\n // camera-switch pauses don't leave the preview stuck.\n const video = this.shadowRoot?.querySelector('video') as HTMLVideoElement | null;\n if (video) {\n video.addEventListener('pause', () => {\n if (!this._effectiveMuted) {\n video.play().catch(() => {});\n }\n });\n }\n }\n\n protected updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('call')) {\n this._teardownDirect();\n if (this.call) this._setupDirect(this.call);\n }\n\n const effectiveStream = this._effectiveStream;\n\n // Only re-attach when the stream reference genuinely changes.\n // The SDK mutates the same MediaStream object (adds/removes tracks) so\n // setting srcObject to the same reference is a browser no-op and can\n // cause a black frame flash on every unrelated context update.\n const streamRefChanged =\n changedProperties.has('stream') ||\n changedProperties.has('call') ||\n changedProperties.has('_directLocalStream') ||\n (changedProperties.has('_callState') && effectiveStream !== this._attachedStream);\n\n if (streamRefChanged) {\n const video = this.shadowRoot?.querySelector('video') as HTMLVideoElement | null;\n if (video) {\n this._attachedStream = effectiveStream;\n attachMediaStream(video, effectiveStream);\n this._detectAspectRatio();\n }\n }\n\n // Ensure playback resumes after unmute or after a new stream is attached.\n // Do NOT guard with video.paused — after mute/unmute the element can be in\n // a \"stalled\" or \"waiting\" state where paused===false but nothing plays.\n if (\n changedProperties.has('videoMuted') ||\n changedProperties.has('_devicesState') ||\n streamRefChanged\n ) {\n if (!this._effectiveMuted) {\n const video = this.shadowRoot?.querySelector('video') as HTMLVideoElement | null;\n if (video) {\n video.play().catch(() => {});\n }\n }\n }\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n const video = this.shadowRoot?.querySelector('video') as HTMLVideoElement | null;\n if (video) detachMediaStream(video);\n this._teardownDirect();\n }\n\n private _setupDirect(call: Call): void {\n this._directSubscriptions.push(\n call.localStream$.subscribe((s) => (this._directLocalStream = s))\n );\n }\n\n private _teardownDirect(): void {\n this._directSubscriptions.forEach((s) => s.unsubscribe());\n this._directSubscriptions = [];\n this._directLocalStream = null;\n }\n\n /** Read the video track settings and set the CSS custom property. */\n private _detectAspectRatio(): void {\n const stream = this._effectiveStream;\n if (!stream) return;\n\n const track = stream.getVideoTracks()[0];\n if (!track) return;\n\n const settings = track.getSettings();\n const w = settings.width;\n const h = settings.height;\n\n if (w && h && w > 0 && h > 0) {\n this._aspectRatio = `${w} / ${h}`;\n this.style.setProperty('--sw-local-camera-aspect', this._aspectRatio);\n }\n }\n\n render() {\n return html`\n <video part=\"video\" autoplay playsinline muted></video>\n ${this._effectiveMuted\n ? html`<div part=\"placeholder\" class=\"muted-overlay\">\n <sw-ui-icon name=\"camera-off\" size=\"28\"></sw-ui-icon>\n </div>`\n : null}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-local-camera': SwLocalCamera;\n }\n}\n"],"names":["SwLocalCamera","LitElement","_a","video","changedProperties","effectiveStream","streamRefChanged","attachMediaStream","_b","call","s","stream","track","settings","w","h","html","css","__decorateClass","property","consume","callStateContext","state","devicesContext","customElement"],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-participant control panel.
|
|
3
|
+
*
|
|
4
|
+
* Takes a `participant-id` and looks up the participant.
|
|
5
|
+
* Shows mute audio, mute video, volume, pin, and remove actions based on
|
|
6
|
+
* the `capabilities` list from the call state.
|
|
7
|
+
*
|
|
8
|
+
* Input precedence (most specific wins): `.call` > context.
|
|
9
|
+
*
|
|
10
|
+
* @prop {string} participantId - ID of the participant to control
|
|
11
|
+
* @prop {Call} call - explicit Call object (overrides context)
|
|
12
|
+
* @prop {boolean} showVolume - show volume slider
|
|
13
|
+
* @prop {boolean} showPin - show pin/spotlight button
|
|
14
|
+
*
|
|
15
|
+
* @fires sw-participant-volume-change - Volume slider changed. Detail: `{ participantId: string, volume: number }`.
|
|
16
|
+
* @fires sw-participant-pin-toggle - Pin/unpin clicked. Detail: `{ participantId: string, pinned: boolean }`.
|
|
17
|
+
*
|
|
18
|
+
* Themed via the SignalWire DTCG tokens (`--bg-page`, `--bg-surface`, `--bg-surface-raised`,
|
|
19
|
+
* `--fg-default`, `--border-default`, `--radius-md`, `--shadow-md`, `--type-family-body`,
|
|
20
|
+
* `--type-size-small`, `--interactive-button-destructive-bg`,
|
|
21
|
+
* `--interactive-button-destructive-hover`, `--transition-fast`).
|
|
22
|
+
*/
|
|
23
|
+
import { LitElement } from 'lit';
|
|
24
|
+
import type { Call } from '../types/index.js';
|
|
25
|
+
import './UI/icons/sw-ui-icon.js';
|
|
26
|
+
export declare class SwParticipantControls extends LitElement {
|
|
27
|
+
static styles: import("lit").CSSResult[];
|
|
28
|
+
participantId: string;
|
|
29
|
+
showVolume: boolean;
|
|
30
|
+
showPin: boolean;
|
|
31
|
+
private _callState?;
|
|
32
|
+
/** Explicit Call — when set, subscribes directly and bypasses context. */
|
|
33
|
+
call?: Call;
|
|
34
|
+
private _directParticipants;
|
|
35
|
+
private _directCapabilities;
|
|
36
|
+
private _directSubscriptions;
|
|
37
|
+
private _volume;
|
|
38
|
+
private _isPinned;
|
|
39
|
+
protected updated(changed: Map<string, unknown>): void;
|
|
40
|
+
disconnectedCallback(): void;
|
|
41
|
+
private get _participant();
|
|
42
|
+
private get _capabilities();
|
|
43
|
+
private get _canMuteAudio();
|
|
44
|
+
private get _canMuteVideo();
|
|
45
|
+
private get _canRemove();
|
|
46
|
+
private _toggleAudioMute;
|
|
47
|
+
private _toggleVideoMute;
|
|
48
|
+
private _remove;
|
|
49
|
+
private _onVolumeChange;
|
|
50
|
+
private _togglePin;
|
|
51
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
52
|
+
}
|
|
53
|
+
declare global {
|
|
54
|
+
interface HTMLElementTagNameMap {
|
|
55
|
+
'sw-participant-controls': SwParticipantControls;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=sw-participant-controls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sw-participant-controls.d.ts","sourceRoot":"","sources":["../../src/components/sw-participant-controls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAMrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,0BAA0B,CAAC;AAKlC,qBACa,qBAAsB,SAAQ,UAAU;IACnD,MAAM,CAAC,MAAM,4BAyHV;IAGH,aAAa,SAAM;IAGnB,UAAU,UAAS;IAGnB,OAAO,UAAS;IAIhB,OAAO,CAAC,UAAU,CAAC,CAAY;IAE/B,0EAA0E;IAC9C,IAAI,CAAC,EAAE,IAAI,CAAC;IAE/B,OAAO,CAAC,mBAAmB,CAAyB;IACpD,OAAO,CAAC,mBAAmB,CAAgB;IAEpD,OAAO,CAAC,oBAAoB,CAAsB;IAEzC,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,SAAS,CAAS;IAEnC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAgBtD,oBAAoB;IAQpB,OAAO,KAAK,YAAY,GAGvB;IAED,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,UAAU,GAErB;YAIa,gBAAgB;YAchB,gBAAgB;YAchB,OAAO;IAUrB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,UAAU;IAalB,MAAM;CAsEP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,yBAAyB,EAAE,qBAAqB,CAAC;KAClD;CACF"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { LitElement as b, html as r, nothing as s, css as m } from "lit";
|
|
2
|
+
import { property as l, state as c, customElement as v } from "lit/decorators.js";
|
|
3
|
+
import { consume as g } from "@lit/context";
|
|
4
|
+
import { callStateContext as f } from "../context/call-state-context.js";
|
|
5
|
+
import { getLogger as _ } from "@signalwire/js";
|
|
6
|
+
import { hostReset as w } from "./UI/host-reset.js";
|
|
7
|
+
var y = Object.defineProperty, x = Object.getOwnPropertyDescriptor, a = (t, i, n, p) => {
|
|
8
|
+
for (var o = p > 1 ? void 0 : p ? x(i, n) : i, u = t.length - 1, d; u >= 0; u--)
|
|
9
|
+
(d = t[u]) && (o = (p ? d(i, n, o) : d(o)) || o);
|
|
10
|
+
return p && o && y(i, n, o), o;
|
|
11
|
+
};
|
|
12
|
+
const h = _();
|
|
13
|
+
let e = class extends b {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments), this.participantId = "", this.showVolume = !1, this.showPin = !1, this._directParticipants = [], this._directCapabilities = [], this._directSubscriptions = [], this._volume = 100, this._isPinned = !1;
|
|
16
|
+
}
|
|
17
|
+
updated(t) {
|
|
18
|
+
super.updated(t), t.has("call") && (this._directSubscriptions.forEach((i) => i.unsubscribe()), this._directSubscriptions = [], this._directParticipants = [], this._directCapabilities = [], this.call && this._directSubscriptions.push(
|
|
19
|
+
this.call.participants$.subscribe((i) => this._directParticipants = i),
|
|
20
|
+
this.call.capabilities$.subscribe((i) => this._directCapabilities = i)
|
|
21
|
+
));
|
|
22
|
+
}
|
|
23
|
+
disconnectedCallback() {
|
|
24
|
+
super.disconnectedCallback(), this._directSubscriptions.forEach((t) => t.unsubscribe()), this._directSubscriptions = [];
|
|
25
|
+
}
|
|
26
|
+
// ── Derived state ──────────────────────────────────────────────────
|
|
27
|
+
get _participant() {
|
|
28
|
+
var i;
|
|
29
|
+
return (this.call ? this._directParticipants : ((i = this._callState) == null ? void 0 : i.participants) ?? []).find((n) => n.id === this.participantId);
|
|
30
|
+
}
|
|
31
|
+
get _capabilities() {
|
|
32
|
+
var t;
|
|
33
|
+
return this.call ? this._directCapabilities : ((t = this._callState) == null ? void 0 : t.capabilities) ?? [];
|
|
34
|
+
}
|
|
35
|
+
get _canMuteAudio() {
|
|
36
|
+
return this._capabilities.includes("memberMuteAudio");
|
|
37
|
+
}
|
|
38
|
+
get _canMuteVideo() {
|
|
39
|
+
return this._capabilities.includes("memberMuteVideo");
|
|
40
|
+
}
|
|
41
|
+
get _canRemove() {
|
|
42
|
+
return this._capabilities.includes("memberRemove");
|
|
43
|
+
}
|
|
44
|
+
// ── Actions ────────────────────────────────────────────────────────
|
|
45
|
+
async _toggleAudioMute() {
|
|
46
|
+
const t = this._participant;
|
|
47
|
+
if (t)
|
|
48
|
+
try {
|
|
49
|
+
t.audioMuted ? await t.unmute() : await t.mute();
|
|
50
|
+
} catch (i) {
|
|
51
|
+
h.error("[ParticipantControls] Toggle audio failed:", i);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async _toggleVideoMute() {
|
|
55
|
+
const t = this._participant;
|
|
56
|
+
if (t)
|
|
57
|
+
try {
|
|
58
|
+
t.videoMuted ? await t.unmuteVideo() : await t.muteVideo();
|
|
59
|
+
} catch (i) {
|
|
60
|
+
h.error("[ParticipantControls] Toggle video failed:", i);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async _remove() {
|
|
64
|
+
const t = this._participant;
|
|
65
|
+
if (t != null && t.remove)
|
|
66
|
+
try {
|
|
67
|
+
await t.remove();
|
|
68
|
+
} catch (i) {
|
|
69
|
+
h.error("[ParticipantControls] Remove failed:", i);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
_onVolumeChange(t) {
|
|
73
|
+
this._volume = parseInt(t.target.value, 10), this.dispatchEvent(
|
|
74
|
+
new CustomEvent("sw-participant-volume-change", {
|
|
75
|
+
detail: { participantId: this.participantId, volume: this._volume },
|
|
76
|
+
bubbles: !0,
|
|
77
|
+
composed: !0
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
_togglePin() {
|
|
82
|
+
this._isPinned = !this._isPinned, this.dispatchEvent(
|
|
83
|
+
new CustomEvent("sw-participant-pin-toggle", {
|
|
84
|
+
detail: { participantId: this.participantId, pinned: this._isPinned },
|
|
85
|
+
bubbles: !0,
|
|
86
|
+
composed: !0
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
// ── Render ─────────────────────────────────────────────────────────
|
|
91
|
+
render() {
|
|
92
|
+
const t = this._participant;
|
|
93
|
+
if (!t) return r`<div class="panel"><div class="empty">Participant not found</div></div>`;
|
|
94
|
+
const i = this._canMuteAudio || this._canMuteVideo || this._canRemove || this.showVolume || this.showPin;
|
|
95
|
+
return r`
|
|
96
|
+
<div class="panel" part="panel">
|
|
97
|
+
<div class="name" part="name">${t.name ?? "Participant"}</div>
|
|
98
|
+
|
|
99
|
+
<div class="actions">
|
|
100
|
+
${i ? s : r`<div class="empty">No actions available</div>`}
|
|
101
|
+
|
|
102
|
+
${this._canMuteAudio ? r`
|
|
103
|
+
<button class=${t.audioMuted ? "active" : ""} @click=${this._toggleAudioMute}>
|
|
104
|
+
<sw-ui-icon name=${t.audioMuted ? "mic-off" : "mic-on"} size="14"></sw-ui-icon>
|
|
105
|
+
${t.audioMuted ? "Unmute" : "Mute"}
|
|
106
|
+
</button>
|
|
107
|
+
` : s}
|
|
108
|
+
|
|
109
|
+
${this._canMuteVideo ? r`
|
|
110
|
+
<button class=${t.videoMuted ? "active" : ""} @click=${this._toggleVideoMute}>
|
|
111
|
+
<sw-ui-icon name=${t.videoMuted ? "camera-off" : "camera-on"} size="14"></sw-ui-icon>
|
|
112
|
+
${t.videoMuted ? "Enable video" : "Disable video"}
|
|
113
|
+
</button>
|
|
114
|
+
` : s}
|
|
115
|
+
|
|
116
|
+
${this.showVolume ? r`
|
|
117
|
+
<div class="volume-control">
|
|
118
|
+
<label class="volume-label">
|
|
119
|
+
<sw-ui-icon name="speaker-on" size="14"></sw-ui-icon>
|
|
120
|
+
Volume: ${this._volume}%
|
|
121
|
+
</label>
|
|
122
|
+
<input
|
|
123
|
+
type="range"
|
|
124
|
+
min="0"
|
|
125
|
+
max="100"
|
|
126
|
+
.value=${String(this._volume)}
|
|
127
|
+
@input=${this._onVolumeChange}
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
130
|
+
` : s}
|
|
131
|
+
|
|
132
|
+
${this.showPin ? r`
|
|
133
|
+
<button class=${this._isPinned ? "active" : ""} @click=${this._togglePin}>
|
|
134
|
+
<sw-ui-icon name="settings" size="14"></sw-ui-icon>
|
|
135
|
+
${this._isPinned ? "Unpin" : "Pin"}
|
|
136
|
+
</button>
|
|
137
|
+
` : s}
|
|
138
|
+
|
|
139
|
+
${this._canRemove ? r`
|
|
140
|
+
<button class="danger" @click=${this._remove}>
|
|
141
|
+
<sw-ui-icon name="close" size="14"></sw-ui-icon>
|
|
142
|
+
Remove
|
|
143
|
+
</button>
|
|
144
|
+
` : s}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
`;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
e.styles = [w, m`
|
|
151
|
+
:host {
|
|
152
|
+
display: block;
|
|
153
|
+
font-family: var(--type-family-body);
|
|
154
|
+
font-size: var(--type-size-small);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.panel {
|
|
158
|
+
display: flex;
|
|
159
|
+
flex-direction: column;
|
|
160
|
+
gap: 6px;
|
|
161
|
+
padding: 10px;
|
|
162
|
+
background: var(--bg-page);
|
|
163
|
+
border: 1px solid var(--border-default);
|
|
164
|
+
border-radius: var(--radius-md);
|
|
165
|
+
min-width: 180px;
|
|
166
|
+
box-shadow: var(--shadow-md);
|
|
167
|
+
color: var(--fg-default);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.name {
|
|
171
|
+
font-size: 0.8125rem;
|
|
172
|
+
font-weight: 500;
|
|
173
|
+
padding-bottom: 6px;
|
|
174
|
+
border-bottom: 1px solid var(--border-default);
|
|
175
|
+
overflow: hidden;
|
|
176
|
+
text-overflow: ellipsis;
|
|
177
|
+
white-space: nowrap;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.actions {
|
|
181
|
+
display: flex;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
gap: 4px;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
button {
|
|
187
|
+
all: unset;
|
|
188
|
+
display: flex;
|
|
189
|
+
align-items: center;
|
|
190
|
+
gap: 8px;
|
|
191
|
+
padding: 6px 10px;
|
|
192
|
+
border-radius: var(--radius-md);
|
|
193
|
+
font-size: 0.75rem;
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
background: var(--bg-surface);
|
|
196
|
+
color: var(--fg-default);
|
|
197
|
+
transition: background var(--transition-fast);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
button:hover {
|
|
201
|
+
background: var(--bg-surface-raised);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
button.active {
|
|
205
|
+
background: var(--interactive-button-destructive-bg);
|
|
206
|
+
color: #fff;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
button.active:hover {
|
|
210
|
+
background: var(--interactive-button-destructive-hover);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
button.danger {
|
|
214
|
+
color: var(--interactive-button-destructive-bg);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
button.danger:hover {
|
|
218
|
+
background: var(--interactive-button-destructive-bg);
|
|
219
|
+
color: #fff;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.volume-control {
|
|
223
|
+
display: flex;
|
|
224
|
+
flex-direction: column;
|
|
225
|
+
gap: 4px;
|
|
226
|
+
padding: 4px 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.volume-label {
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
gap: 6px;
|
|
233
|
+
font-size: 0.7rem;
|
|
234
|
+
color: color-mix(in srgb, var(--fg-default) 50%, transparent);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
input[type='range'] {
|
|
238
|
+
width: 100%;
|
|
239
|
+
height: 4px;
|
|
240
|
+
appearance: none;
|
|
241
|
+
background: var(--border-default);
|
|
242
|
+
border-radius: 2px;
|
|
243
|
+
outline: none;
|
|
244
|
+
cursor: pointer;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
input[type='range']::-webkit-slider-thumb {
|
|
248
|
+
appearance: none;
|
|
249
|
+
width: 12px;
|
|
250
|
+
height: 12px;
|
|
251
|
+
background: #3b82f6;
|
|
252
|
+
border-radius: 50%;
|
|
253
|
+
cursor: pointer;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
input[type='range']::-moz-range-thumb {
|
|
257
|
+
width: 12px;
|
|
258
|
+
height: 12px;
|
|
259
|
+
background: #3b82f6;
|
|
260
|
+
border-radius: 50%;
|
|
261
|
+
border: none;
|
|
262
|
+
cursor: pointer;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.empty {
|
|
266
|
+
font-size: 0.7rem;
|
|
267
|
+
color: color-mix(in srgb, var(--fg-default) 50%, transparent);
|
|
268
|
+
text-align: center;
|
|
269
|
+
padding: 6px;
|
|
270
|
+
}
|
|
271
|
+
`];
|
|
272
|
+
a([
|
|
273
|
+
l({ type: String, attribute: "participant-id" })
|
|
274
|
+
], e.prototype, "participantId", 2);
|
|
275
|
+
a([
|
|
276
|
+
l({ type: Boolean, reflect: !0, attribute: "show-volume" })
|
|
277
|
+
], e.prototype, "showVolume", 2);
|
|
278
|
+
a([
|
|
279
|
+
l({ type: Boolean, reflect: !0, attribute: "show-pin" })
|
|
280
|
+
], e.prototype, "showPin", 2);
|
|
281
|
+
a([
|
|
282
|
+
g({ context: f, subscribe: !0 }),
|
|
283
|
+
c()
|
|
284
|
+
], e.prototype, "_callState", 2);
|
|
285
|
+
a([
|
|
286
|
+
l({ type: Object })
|
|
287
|
+
], e.prototype, "call", 2);
|
|
288
|
+
a([
|
|
289
|
+
c()
|
|
290
|
+
], e.prototype, "_directParticipants", 2);
|
|
291
|
+
a([
|
|
292
|
+
c()
|
|
293
|
+
], e.prototype, "_directCapabilities", 2);
|
|
294
|
+
a([
|
|
295
|
+
c()
|
|
296
|
+
], e.prototype, "_volume", 2);
|
|
297
|
+
a([
|
|
298
|
+
c()
|
|
299
|
+
], e.prototype, "_isPinned", 2);
|
|
300
|
+
e = a([
|
|
301
|
+
v("sw-participant-controls")
|
|
302
|
+
], e);
|
|
303
|
+
export {
|
|
304
|
+
e as SwParticipantControls
|
|
305
|
+
};
|
|
306
|
+
//# sourceMappingURL=sw-participant-controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sw-participant-controls.js","sources":["../../src/components/sw-participant-controls.ts"],"sourcesContent":["/**\n * Per-participant control panel.\n *\n * Takes a `participant-id` and looks up the participant.\n * Shows mute audio, mute video, volume, pin, and remove actions based on\n * the `capabilities` list from the call state.\n *\n * Input precedence (most specific wins): `.call` > context.\n *\n * @prop {string} participantId - ID of the participant to control\n * @prop {Call} call - explicit Call object (overrides context)\n * @prop {boolean} showVolume - show volume slider\n * @prop {boolean} showPin - show pin/spotlight button\n *\n * @fires sw-participant-volume-change - Volume slider changed. Detail: `{ participantId: string, volume: number }`.\n * @fires sw-participant-pin-toggle - Pin/unpin clicked. Detail: `{ participantId: string, pinned: boolean }`.\n *\n * Themed via the SignalWire DTCG tokens (`--bg-page`, `--bg-surface`, `--bg-surface-raised`,\n * `--fg-default`, `--border-default`, `--radius-md`, `--shadow-md`, `--type-family-body`,\n * `--type-size-small`, `--interactive-button-destructive-bg`,\n * `--interactive-button-destructive-hover`, `--transition-fast`).\n */\n\nimport { LitElement, html, css, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\nimport { Subscription } from 'rxjs';\nimport type { CallParticipant } from '@signalwire/js';\nimport { callStateContext, type CallState } from '../context/call-state-context.js';\nimport type { Call } from '../types/index.js';\nimport { getLogger } from '@signalwire/js';\nimport './UI/icons/sw-ui-icon.js';\nimport { hostReset } from './UI/host-reset.js';\n\nconst logger = getLogger();\n\n@customElement('sw-participant-controls')\nexport class SwParticipantControls extends LitElement {\n static styles = [hostReset, css`\n :host {\n display: block;\n font-family: var(--type-family-body);\n font-size: var(--type-size-small);\n }\n\n .panel {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px;\n background: var(--bg-page);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n min-width: 180px;\n box-shadow: var(--shadow-md);\n color: var(--fg-default);\n }\n\n .name {\n font-size: 0.8125rem;\n font-weight: 500;\n padding-bottom: 6px;\n border-bottom: 1px solid var(--border-default);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .actions {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n button {\n all: unset;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n border-radius: var(--radius-md);\n font-size: 0.75rem;\n cursor: pointer;\n background: var(--bg-surface);\n color: var(--fg-default);\n transition: background var(--transition-fast);\n }\n\n button:hover {\n background: var(--bg-surface-raised);\n }\n\n button.active {\n background: var(--interactive-button-destructive-bg);\n color: #fff;\n }\n\n button.active:hover {\n background: var(--interactive-button-destructive-hover);\n }\n\n button.danger {\n color: var(--interactive-button-destructive-bg);\n }\n\n button.danger:hover {\n background: var(--interactive-button-destructive-bg);\n color: #fff;\n }\n\n .volume-control {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 4px 0;\n }\n\n .volume-label {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.7rem;\n color: color-mix(in srgb, var(--fg-default) 50%, transparent);\n }\n\n input[type='range'] {\n width: 100%;\n height: 4px;\n appearance: none;\n background: var(--border-default);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n }\n\n input[type='range']::-webkit-slider-thumb {\n appearance: none;\n width: 12px;\n height: 12px;\n background: #3b82f6;\n border-radius: 50%;\n cursor: pointer;\n }\n\n input[type='range']::-moz-range-thumb {\n width: 12px;\n height: 12px;\n background: #3b82f6;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n }\n\n .empty {\n font-size: 0.7rem;\n color: color-mix(in srgb, var(--fg-default) 50%, transparent);\n text-align: center;\n padding: 6px;\n }\n `];\n\n @property({ type: String, attribute: 'participant-id' })\n participantId = '';\n\n @property({ type: Boolean, reflect: true, attribute: 'show-volume' })\n showVolume = false;\n\n @property({ type: Boolean, reflect: true, attribute: 'show-pin' })\n showPin = false;\n\n @consume({ context: callStateContext, subscribe: true })\n @state()\n private _callState?: CallState;\n\n /** Explicit Call — when set, subscribes directly and bypasses context. */\n @property({ type: Object }) call?: Call;\n\n @state() private _directParticipants: CallParticipant[] = [];\n @state() private _directCapabilities: string[] = [];\n\n private _directSubscriptions: Subscription[] = [];\n\n @state() private _volume = 100;\n @state() private _isPinned = false;\n\n protected updated(changed: Map<string, unknown>): void {\n super.updated(changed);\n if (changed.has('call')) {\n this._directSubscriptions.forEach((s) => s.unsubscribe());\n this._directSubscriptions = [];\n this._directParticipants = [];\n this._directCapabilities = [];\n if (this.call) {\n this._directSubscriptions.push(\n this.call.participants$.subscribe((p) => (this._directParticipants = p)),\n this.call.capabilities$.subscribe((c) => (this._directCapabilities = c))\n );\n }\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this._directSubscriptions.forEach((s) => s.unsubscribe());\n this._directSubscriptions = [];\n }\n\n // ── Derived state ──────────────────────────────────────────────────\n\n private get _participant() {\n const participants = this.call ? this._directParticipants : this._callState?.participants ?? [];\n return participants.find((p) => p.id === this.participantId);\n }\n\n private get _capabilities(): string[] {\n return this.call ? this._directCapabilities : this._callState?.capabilities ?? [];\n }\n\n private get _canMuteAudio(): boolean {\n return this._capabilities.includes('memberMuteAudio');\n }\n\n private get _canMuteVideo(): boolean {\n return this._capabilities.includes('memberMuteVideo');\n }\n\n private get _canRemove(): boolean {\n return this._capabilities.includes('memberRemove');\n }\n\n // ── Actions ────────────────────────────────────────────────────────\n\n private async _toggleAudioMute() {\n const p = this._participant;\n if (!p) return;\n try {\n if (p.audioMuted) {\n await p.unmute();\n } else {\n await p.mute();\n }\n } catch (err) {\n logger.error('[ParticipantControls] Toggle audio failed:', err);\n }\n }\n\n private async _toggleVideoMute() {\n const p = this._participant;\n if (!p) return;\n try {\n if (p.videoMuted) {\n await p.unmuteVideo();\n } else {\n await p.muteVideo();\n }\n } catch (err) {\n logger.error('[ParticipantControls] Toggle video failed:', err);\n }\n }\n\n private async _remove() {\n const p = this._participant;\n if (!p?.remove) return;\n try {\n await p.remove();\n } catch (err) {\n logger.error('[ParticipantControls] Remove failed:', err);\n }\n }\n\n private _onVolumeChange(e: Event) {\n this._volume = parseInt((e.target as HTMLInputElement).value, 10);\n this.dispatchEvent(\n new CustomEvent('sw-participant-volume-change', {\n detail: { participantId: this.participantId, volume: this._volume },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private _togglePin() {\n this._isPinned = !this._isPinned;\n this.dispatchEvent(\n new CustomEvent('sw-participant-pin-toggle', {\n detail: { participantId: this.participantId, pinned: this._isPinned },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n // ── Render ─────────────────────────────────────────────────────────\n\n render() {\n const p = this._participant;\n if (!p) return html`<div class=\"panel\"><div class=\"empty\">Participant not found</div></div>`;\n\n const hasActions = this._canMuteAudio || this._canMuteVideo || this._canRemove || this.showVolume || this.showPin;\n\n return html`\n <div class=\"panel\" part=\"panel\">\n <div class=\"name\" part=\"name\">${p.name ?? 'Participant'}</div>\n\n <div class=\"actions\">\n ${!hasActions ? html`<div class=\"empty\">No actions available</div>` : nothing}\n\n ${this._canMuteAudio\n ? html`\n <button class=${p.audioMuted ? 'active' : ''} @click=${this._toggleAudioMute}>\n <sw-ui-icon name=${p.audioMuted ? 'mic-off' : 'mic-on'} size=\"14\"></sw-ui-icon>\n ${p.audioMuted ? 'Unmute' : 'Mute'}\n </button>\n `\n : nothing}\n\n ${this._canMuteVideo\n ? html`\n <button class=${p.videoMuted ? 'active' : ''} @click=${this._toggleVideoMute}>\n <sw-ui-icon name=${p.videoMuted ? 'camera-off' : 'camera-on'} size=\"14\"></sw-ui-icon>\n ${p.videoMuted ? 'Enable video' : 'Disable video'}\n </button>\n `\n : nothing}\n\n ${this.showVolume\n ? html`\n <div class=\"volume-control\">\n <label class=\"volume-label\">\n <sw-ui-icon name=\"speaker-on\" size=\"14\"></sw-ui-icon>\n Volume: ${this._volume}%\n </label>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n .value=${String(this._volume)}\n @input=${this._onVolumeChange}\n />\n </div>\n `\n : nothing}\n\n ${this.showPin\n ? html`\n <button class=${this._isPinned ? 'active' : ''} @click=${this._togglePin}>\n <sw-ui-icon name=\"settings\" size=\"14\"></sw-ui-icon>\n ${this._isPinned ? 'Unpin' : 'Pin'}\n </button>\n `\n : nothing}\n\n ${this._canRemove\n ? html`\n <button class=\"danger\" @click=${this._remove}>\n <sw-ui-icon name=\"close\" size=\"14\"></sw-ui-icon>\n Remove\n </button>\n `\n : nothing}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-participant-controls': SwParticipantControls;\n }\n}\n"],"names":["logger","getLogger","SwParticipantControls","LitElement","changed","s","p","c","_a","err","e","html","hasActions","nothing","hostReset","css","__decorateClass","property","consume","callStateContext","state","customElement"],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SwParticipants Component
|
|
3
|
+
*
|
|
4
|
+
* Renders member overlays based on layoutLayers.
|
|
5
|
+
* Excludes self member and provides slot for <self-media> child component.
|
|
6
|
+
*
|
|
7
|
+
* Input precedence (most specific wins): `.call` > context.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```html
|
|
11
|
+
* <sw-participants></sw-participants>
|
|
12
|
+
* <sw-participants .call=${call}></sw-participants>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @slot - Default slot for overlay content.
|
|
16
|
+
* @slot controls-{memberId} - Per-participant menu content (e.g. `sw-participant-controls`).
|
|
17
|
+
*
|
|
18
|
+
* @fires sw-participant-mute-audio - User muted/unmuted a participant's audio. Detail: `{ participant, memberId }`.
|
|
19
|
+
* @fires sw-participant-mute-video - User muted/unmuted a participant's video. Detail: `{ participant, memberId }`.
|
|
20
|
+
* @fires sw-participant-remove - User removed a participant. Detail: `{ participant, memberId }`.
|
|
21
|
+
*/
|
|
22
|
+
import { LitElement } from 'lit';
|
|
23
|
+
import type { Call } from '../types/index.js';
|
|
24
|
+
export declare class SwParticipants extends LitElement {
|
|
25
|
+
static styles: import("lit").CSSResult[];
|
|
26
|
+
private _callState?;
|
|
27
|
+
/** Explicit Call — when set, subscribes directly and bypasses context. */
|
|
28
|
+
call?: Call;
|
|
29
|
+
private _directLayoutLayers;
|
|
30
|
+
private _directParticipants;
|
|
31
|
+
private _directSelf;
|
|
32
|
+
private _directSubscriptions;
|
|
33
|
+
private _openMenuId;
|
|
34
|
+
private _handleOutsideClick;
|
|
35
|
+
private _handleEscape;
|
|
36
|
+
connectedCallback(): void;
|
|
37
|
+
disconnectedCallback(): void;
|
|
38
|
+
protected updated(changed: Map<string, unknown>): void;
|
|
39
|
+
private _teardownDirect;
|
|
40
|
+
private _toggleMenu;
|
|
41
|
+
private _getParticipant;
|
|
42
|
+
private _handleMuteAudio;
|
|
43
|
+
private _handleMuteVideo;
|
|
44
|
+
private _handleRemove;
|
|
45
|
+
private _renderMenuIcon;
|
|
46
|
+
private _renderMenuDropdown;
|
|
47
|
+
private _renderOverlay;
|
|
48
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
49
|
+
}
|
|
50
|
+
declare global {
|
|
51
|
+
interface HTMLElementTagNameMap {
|
|
52
|
+
'sw-participants': SwParticipants;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=sw-participants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sw-participants.d.ts","sourceRoot":"","sources":["../../src/components/sw-participants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAK5C,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,mBAAmB,CAAC;AAI3D,qBACa,cAAe,SAAQ,UAAU;IAC5C,MAAM,CAAC,MAAM,4BAiHV;IAIH,OAAO,CAAC,UAAU,CAAC,CAAY;IAE/B,0EAA0E;IAC9C,IAAI,CAAC,EAAE,IAAI,CAAC;IAE/B,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,mBAAmB,CAAyB;IACpD,OAAO,CAAC,WAAW,CAAoC;IAEhE,OAAO,CAAC,oBAAoB,CAAsB;IAGlD,OAAO,CAAC,WAAW,CAAuB;IAE1C,OAAO,CAAC,mBAAmB,CAKzB;IAEF,OAAO,CAAC,aAAa,CAInB;IAEF,iBAAiB;IAMjB,oBAAoB;IAOpB,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IActD,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,eAAe;YAKT,gBAAgB;YAuBhB,gBAAgB;YAuBhB,aAAa;IAqB3B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;IAsC3B,OAAO,CAAC,cAAc;IAuCtB,MAAM;CAaP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,cAAc,CAAC;KACnC;CACF"}
|