@webex/widgets 1.28.1 → 1.28.2
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/dist/webexWidgets.esm.js
CHANGED
|
@@ -4,6 +4,36 @@ import Webex from 'webex';
|
|
|
4
4
|
import require$$2, { createPortal } from 'react-dom';
|
|
5
5
|
import { deconstructHydraId, SDK_EVENT, constructHydraId } from '@webex/common';
|
|
6
6
|
|
|
7
|
+
function _arrayLikeToArray(r, a) {
|
|
8
|
+
(null == a || a > r.length) && (a = r.length);
|
|
9
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
10
|
+
return n;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function _arrayWithoutHoles(r) {
|
|
14
|
+
if (Array.isArray(r)) return _arrayLikeToArray(r);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function _iterableToArray(r) {
|
|
18
|
+
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function _unsupportedIterableToArray(r, a) {
|
|
22
|
+
if (r) {
|
|
23
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
24
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
25
|
+
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function _nonIterableSpread() {
|
|
30
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function _toConsumableArray(r) {
|
|
34
|
+
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
|
|
35
|
+
}
|
|
36
|
+
|
|
7
37
|
function _classCallCheck(a, n) {
|
|
8
38
|
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
|
|
9
39
|
}
|
|
@@ -3235,36 +3265,6 @@ var TapSubscriber = /*@__PURE__*/function (_super) {
|
|
|
3235
3265
|
return TapSubscriber;
|
|
3236
3266
|
}(Subscriber);
|
|
3237
3267
|
|
|
3238
|
-
function _arrayLikeToArray(r, a) {
|
|
3239
|
-
(null == a || a > r.length) && (a = r.length);
|
|
3240
|
-
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
3241
|
-
return n;
|
|
3242
|
-
}
|
|
3243
|
-
|
|
3244
|
-
function _arrayWithoutHoles(r) {
|
|
3245
|
-
if (Array.isArray(r)) return _arrayLikeToArray(r);
|
|
3246
|
-
}
|
|
3247
|
-
|
|
3248
|
-
function _iterableToArray(r) {
|
|
3249
|
-
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
|
|
3250
|
-
}
|
|
3251
|
-
|
|
3252
|
-
function _unsupportedIterableToArray(r, a) {
|
|
3253
|
-
if (r) {
|
|
3254
|
-
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
3255
|
-
var t = {}.toString.call(r).slice(8, -1);
|
|
3256
|
-
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
3257
|
-
}
|
|
3258
|
-
}
|
|
3259
|
-
|
|
3260
|
-
function _nonIterableSpread() {
|
|
3261
|
-
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
function _toConsumableArray(r) {
|
|
3265
|
-
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
|
|
3266
|
-
}
|
|
3267
|
-
|
|
3268
3268
|
function _arrayWithHoles(r) {
|
|
3269
3269
|
if (Array.isArray(r)) return r;
|
|
3270
3270
|
}
|
|
@@ -56954,11 +56954,159 @@ var WebexMeetingsWidget = /*#__PURE__*/function (_Component) {
|
|
|
56954
56954
|
_classCallCheck(this, WebexMeetingsWidget);
|
|
56955
56955
|
return _callSuper(this, WebexMeetingsWidget, [props]);
|
|
56956
56956
|
}
|
|
56957
|
+
/**
|
|
56958
|
+
* Temporary custom accessibility fix:
|
|
56959
|
+
* - Redirects focus to the first actionable control inside the meeting
|
|
56960
|
+
* - Makes video layout focusable and supports left/right arrow navigation
|
|
56961
|
+
* - Prevents focus from escaping to the browser URL bar
|
|
56962
|
+
*
|
|
56963
|
+
* NOTE: This is a workaround because the base @webex/components WebexMeeting
|
|
56964
|
+
* does not yet support these accessibility features.
|
|
56965
|
+
* Once the upstream component is fixed, we must remove this custom code
|
|
56966
|
+
* from our repo to avoid duplication and ensure long-term maintainability.
|
|
56967
|
+
*/
|
|
56957
56968
|
_inherits(WebexMeetingsWidget, _Component);
|
|
56958
56969
|
return _createClass(WebexMeetingsWidget, [{
|
|
56970
|
+
key: "componentDidMount",
|
|
56971
|
+
value: function componentDidMount() {
|
|
56972
|
+
var _this = this;
|
|
56973
|
+
// When focus comes to the widget container, move to the correct media container before and after joining
|
|
56974
|
+
if (this.widgetDiv) {
|
|
56975
|
+
if (!this._mediaContainerTabHandler) {
|
|
56976
|
+
this._mediaContainerTabHandler = function (evt) {
|
|
56977
|
+
var mediaContainer = evt.currentTarget;
|
|
56978
|
+
// Only handle if the media container itself is focused
|
|
56979
|
+
if ((evt.code === 'Tab' || evt.key === 'Tab') && document.activeElement === mediaContainer) {
|
|
56980
|
+
if (!evt.shiftKey) {
|
|
56981
|
+
evt.preventDefault();
|
|
56982
|
+
var joinButton = _this.widgetDiv.querySelector('button[aria-label="Join meeting"]');
|
|
56983
|
+
if (!joinButton) {
|
|
56984
|
+
joinButton = _this.widgetDiv.querySelector('.wxc-meeting-control button, .wxc-meeting-control [tabindex]:not([tabindex="-1"])');
|
|
56985
|
+
}
|
|
56986
|
+
if (joinButton) {
|
|
56987
|
+
joinButton.focus();
|
|
56988
|
+
}
|
|
56989
|
+
} else {
|
|
56990
|
+
evt.preventDefault();
|
|
56991
|
+
// Move focus back to the widget container
|
|
56992
|
+
if (_this.widgetDiv) {
|
|
56993
|
+
_this.widgetDiv.tabIndex = 0;
|
|
56994
|
+
_this.widgetDiv.focus();
|
|
56995
|
+
}
|
|
56996
|
+
}
|
|
56997
|
+
}
|
|
56998
|
+
};
|
|
56999
|
+
}
|
|
57000
|
+
this.widgetDiv.addEventListener('focus', function () {
|
|
57001
|
+
setTimeout(function () {
|
|
57002
|
+
// Attach handler to both possible media containers if they exist
|
|
57003
|
+
var containers = _toConsumableArray(_this.widgetDiv.querySelectorAll('.wxc-interstitial-meeting__media-container, .wxc-in-meeting__media-container'));
|
|
57004
|
+
if (containers.length > 0) {
|
|
57005
|
+
containers.forEach(function (mediaContainer) {
|
|
57006
|
+
mediaContainer.tabIndex = 0;
|
|
57007
|
+
mediaContainer.removeEventListener('keydown', _this._mediaContainerTabHandler, true);
|
|
57008
|
+
mediaContainer.addEventListener('keydown', _this._mediaContainerTabHandler, true);
|
|
57009
|
+
});
|
|
57010
|
+
} else {
|
|
57011
|
+
// fallback to Join meeting button or first .wxc-meeting-control button
|
|
57012
|
+
var joinButton = _this.widgetDiv.querySelector('button[aria-label="Join meeting"]');
|
|
57013
|
+
if (!joinButton) {
|
|
57014
|
+
joinButton = _this.widgetDiv.querySelector('.wxc-meeting-control button, .wxc-meeting-control [tabindex]:not([tabindex="-1"])');
|
|
57015
|
+
}
|
|
57016
|
+
if (joinButton) {
|
|
57017
|
+
joinButton.focus();
|
|
57018
|
+
}
|
|
57019
|
+
}
|
|
57020
|
+
}, 0);
|
|
57021
|
+
});
|
|
57022
|
+
|
|
57023
|
+
// Arrow key navigation for all meeting control buttons, with MutationObserver
|
|
57024
|
+
var attachArrowNav = function attachArrowNav() {
|
|
57025
|
+
// Gather all focusable meeting controls, including Join meeting button if present
|
|
57026
|
+
var buttons = [];
|
|
57027
|
+
var controlBar = _this.widgetDiv.querySelector('.wxc-meeting-control-bar__controls');
|
|
57028
|
+
if (controlBar) {
|
|
57029
|
+
buttons = Array.from(controlBar.querySelectorAll('button, [tabindex]:not([tabindex="-1"])'));
|
|
57030
|
+
}
|
|
57031
|
+
// Add Join meeting button if present and not already in the list
|
|
57032
|
+
var joinButton = _this.widgetDiv.querySelector('button[aria-label="Join meeting"]');
|
|
57033
|
+
if (joinButton && !buttons.includes(joinButton)) {
|
|
57034
|
+
buttons = [joinButton].concat(_toConsumableArray(buttons));
|
|
57035
|
+
}
|
|
57036
|
+
// Remove any previous listeners to avoid duplicates
|
|
57037
|
+
buttons.forEach(function (btn) {
|
|
57038
|
+
btn.onkeydown = null;
|
|
57039
|
+
});
|
|
57040
|
+
// Attach arrow key listeners to all buttons (including Join meeting)
|
|
57041
|
+
buttons.forEach(function (btn, idx) {
|
|
57042
|
+
btn.onkeydown = function (evt) {
|
|
57043
|
+
if (evt.key === 'ArrowRight') {
|
|
57044
|
+
evt.preventDefault();
|
|
57045
|
+
var next = buttons[(idx + 1) % buttons.length];
|
|
57046
|
+
if (next) next.focus();
|
|
57047
|
+
} else if (evt.key === 'ArrowLeft') {
|
|
57048
|
+
evt.preventDefault();
|
|
57049
|
+
var prev = buttons[(idx - 1 + buttons.length) % buttons.length];
|
|
57050
|
+
if (prev) prev.focus();
|
|
57051
|
+
}
|
|
57052
|
+
};
|
|
57053
|
+
});
|
|
57054
|
+
};
|
|
57055
|
+
// Initial setup
|
|
57056
|
+
setTimeout(attachArrowNav, 700);
|
|
57057
|
+
|
|
57058
|
+
// Observe DOM changes to re-attach listeners if buttons change
|
|
57059
|
+
var observer = new window.MutationObserver(function () {
|
|
57060
|
+
attachArrowNav();
|
|
57061
|
+
});
|
|
57062
|
+
observer.observe(this.widgetDiv, {
|
|
57063
|
+
childList: true,
|
|
57064
|
+
subtree: true
|
|
57065
|
+
});
|
|
57066
|
+
// Clean up observer on unmount
|
|
57067
|
+
this._arrowNavObserver = observer;
|
|
57068
|
+
}
|
|
57069
|
+
|
|
57070
|
+
// When focus comes to the content, wait for .wxc-meeting__inner-meeting and move focus
|
|
57071
|
+
if (this.widgetDiv) {
|
|
57072
|
+
var contentDiv = this.widgetDiv.querySelector('.webex-meetings-widget__content');
|
|
57073
|
+
if (contentDiv) {
|
|
57074
|
+
contentDiv.addEventListener('focus', function () {
|
|
57075
|
+
// Poll for .wxc-meeting__inner-meeting up to 500ms
|
|
57076
|
+
var attempts = 0;
|
|
57077
|
+
var tryFocusInnerMeeting = function tryFocusInnerMeeting() {
|
|
57078
|
+
var innerMeeting = contentDiv.querySelector('.wxc-in-meeting__media-container');
|
|
57079
|
+
if (innerMeeting) {
|
|
57080
|
+
innerMeeting.tabIndex = 0;
|
|
57081
|
+
innerMeeting.focus();
|
|
57082
|
+
// On Tab, move to first interactive element
|
|
57083
|
+
var handleTab = function handleTab(evt) {
|
|
57084
|
+
if (evt.key === 'Tab' && !evt.shiftKey) {
|
|
57085
|
+
evt.preventDefault();
|
|
57086
|
+
var nextInteractive = innerMeeting.querySelector('button, [tabindex]:not([tabindex="-1"])');
|
|
57087
|
+
if (nextInteractive) {
|
|
57088
|
+
nextInteractive.focus();
|
|
57089
|
+
}
|
|
57090
|
+
innerMeeting.removeEventListener('keydown', handleTab);
|
|
57091
|
+
}
|
|
57092
|
+
};
|
|
57093
|
+
innerMeeting.addEventListener('keydown', handleTab);
|
|
57094
|
+
} else if (attempts < 10) {
|
|
57095
|
+
attempts++;
|
|
57096
|
+
setTimeout(tryFocusInnerMeeting, 50);
|
|
57097
|
+
}
|
|
57098
|
+
};
|
|
57099
|
+
tryFocusInnerMeeting();
|
|
57100
|
+
});
|
|
57101
|
+
}
|
|
57102
|
+
}
|
|
57103
|
+
}
|
|
57104
|
+
}, {
|
|
56959
57105
|
key: "render",
|
|
56960
57106
|
value: function render() {
|
|
56961
|
-
var _meeting$localAudio,
|
|
57107
|
+
var _meeting$localAudio,
|
|
57108
|
+
_meeting$localVideo,
|
|
57109
|
+
_this2 = this;
|
|
56962
57110
|
var meeting = this.props.meeting;
|
|
56963
57111
|
var audioPermission = (_meeting$localAudio = meeting.localAudio) === null || _meeting$localAudio === void 0 ? void 0 : _meeting$localAudio.permission;
|
|
56964
57112
|
var videoPermission = (_meeting$localVideo = meeting.localVideo) === null || _meeting$localVideo === void 0 ? void 0 : _meeting$localVideo.permission;
|
|
@@ -56994,9 +57142,22 @@ var WebexMeetingsWidget = /*#__PURE__*/function (_Component) {
|
|
|
56994
57142
|
}
|
|
56995
57143
|
return /*#__PURE__*/S.createElement("div", {
|
|
56996
57144
|
className: "webex-meetings-widget ".concat(this.props.className),
|
|
56997
|
-
style: this.props.style
|
|
57145
|
+
style: this.props.style,
|
|
57146
|
+
ref: function ref(div) {
|
|
57147
|
+
_this2.widgetDiv = div;
|
|
57148
|
+
},
|
|
57149
|
+
tabIndex: 0
|
|
56998
57150
|
}, content);
|
|
56999
57151
|
}
|
|
57152
|
+
}, {
|
|
57153
|
+
key: "componentWillUnmount",
|
|
57154
|
+
value: function componentWillUnmount() {
|
|
57155
|
+
// Clean up MutationObserver if present
|
|
57156
|
+
if (this._arrowNavObserver) {
|
|
57157
|
+
this._arrowNavObserver.disconnect();
|
|
57158
|
+
this._arrowNavObserver = null;
|
|
57159
|
+
}
|
|
57160
|
+
}
|
|
57000
57161
|
}]);
|
|
57001
57162
|
}(Component);
|
|
57002
57163
|
WebexMeetingsWidget.propTypes = {
|
|
@@ -57031,7 +57192,7 @@ var WebexMeetings = Ic(Pc(WebexMeetingsWidget), function (props) {
|
|
|
57031
57192
|
},
|
|
57032
57193
|
config: {
|
|
57033
57194
|
appName: appName,
|
|
57034
|
-
appVersion: "1.28.
|
|
57195
|
+
appVersion: "1.28.1",
|
|
57035
57196
|
fedramp: props.fedramp,
|
|
57036
57197
|
meetings: {
|
|
57037
57198
|
experimental: {
|