@atlaskit/editor-plugin-media 1.13.4 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/nodeviews/mediaNodeView/media.js +59 -1
- package/dist/cjs/nodeviews/mediaSingle.js +44 -22
- package/dist/cjs/pm-plugins/keymap.js +13 -1
- package/dist/cjs/pm-plugins/main.js +50 -1
- package/dist/cjs/ui/CommentBadge/index.js +48 -0
- package/dist/es2019/nodeviews/mediaNodeView/media.js +56 -1
- package/dist/es2019/nodeviews/mediaSingle.js +22 -2
- package/dist/es2019/pm-plugins/keymap.js +14 -2
- package/dist/es2019/pm-plugins/main.js +54 -1
- package/dist/es2019/ui/CommentBadge/index.js +50 -0
- package/dist/esm/nodeviews/mediaNodeView/media.js +59 -1
- package/dist/esm/nodeviews/mediaSingle.js +44 -22
- package/dist/esm/pm-plugins/keymap.js +14 -2
- package/dist/esm/pm-plugins/main.js +50 -1
- package/dist/esm/ui/CommentBadge/index.js +39 -0
- package/dist/types/nodeviews/mediaNodeView/media.d.ts +4 -0
- package/dist/types/nodeviews/mediaSingle.d.ts +1 -0
- package/dist/types/pm-plugins/types.d.ts +2 -1
- package/dist/types/ui/CommentBadge/index.d.ts +18 -0
- package/dist/types-ts4.5/nodeviews/mediaNodeView/media.d.ts +4 -0
- package/dist/types-ts4.5/nodeviews/mediaSingle.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/types.d.ts +2 -1
- package/dist/types-ts4.5/ui/CommentBadge/index.d.ts +18 -0
- package/package.json +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-media
|
|
2
2
|
|
|
3
|
+
## 1.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#73901](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/73901) [`2aefab5730ab`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/2aefab5730ab) - ECA11Y-207 Added Tab navigation for video panel controls and handling key press on them
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
13
|
+
## 1.13.5
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#87596](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/87596) [`e0b95c3a4fba`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/e0b95c3a4fba) - Add new UI badge for media node to trigger comments
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 1.13.4
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -16,11 +16,13 @@ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime
|
|
|
16
16
|
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
17
17
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
18
18
|
var _react = _interopRequireWildcard(require("react"));
|
|
19
|
+
var _bindEventListener = require("bind-event-listener");
|
|
19
20
|
var _analyticsNamespacedContext = require("@atlaskit/analytics-namespaced-context");
|
|
20
21
|
var _analyticsNext = require("@atlaskit/analytics-next");
|
|
21
22
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
22
23
|
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
|
|
23
24
|
var _mediaCard = require("@atlaskit/media-card");
|
|
25
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
24
26
|
var _pluginKey = require("../../pm-plugins/plugin-key");
|
|
25
27
|
var _styles = require("../styles");
|
|
26
28
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
@@ -39,6 +41,8 @@ var MediaNode = exports.MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
39
41
|
(0, _classCallCheck2.default)(this, MediaNode);
|
|
40
42
|
_this = _super.call(this, _props);
|
|
41
43
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", {});
|
|
44
|
+
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "videoControlsWrapperRef", /*#__PURE__*/_react.default.createRef());
|
|
45
|
+
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "unbindKeyDown", null);
|
|
42
46
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "setViewMediaClientConfig", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
43
47
|
var mediaProvider, viewMediaClientConfig;
|
|
44
48
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
@@ -150,6 +154,9 @@ var MediaNode = exports.MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
150
154
|
var _this$mediaPluginStat3;
|
|
151
155
|
var node = this.props.node;
|
|
152
156
|
(_this$mediaPluginStat3 = this.mediaPluginState) === null || _this$mediaPluginStat3 === void 0 || _this$mediaPluginStat3.handleMediaNodeUnmount(node);
|
|
157
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh') && this.unbindKeyDown && typeof this.unbindKeyDown === 'function') {
|
|
158
|
+
this.unbindKeyDown();
|
|
159
|
+
}
|
|
153
160
|
}
|
|
154
161
|
}, {
|
|
155
162
|
key: "componentDidUpdate",
|
|
@@ -162,6 +169,56 @@ var MediaNode = exports.MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
162
169
|
}
|
|
163
170
|
(_this$mediaPluginStat5 = this.mediaPluginState) === null || _this$mediaPluginStat5 === void 0 || _this$mediaPluginStat5.updateElement();
|
|
164
171
|
this.setViewMediaClientConfig();
|
|
172
|
+
// this.videoControlsWrapperRef is null on componentDidMount. We need to wait until it has value
|
|
173
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh') && this.videoControlsWrapperRef && this.videoControlsWrapperRef.current) {
|
|
174
|
+
var _this$mediaPluginStat6;
|
|
175
|
+
if (!((_this$mediaPluginStat6 = this.mediaPluginState) !== null && _this$mediaPluginStat6 !== void 0 && _this$mediaPluginStat6.videoControlsWrapperRef)) {
|
|
176
|
+
var _this$mediaPluginStat7;
|
|
177
|
+
this.bindKeydown();
|
|
178
|
+
(_this$mediaPluginStat7 = this.mediaPluginState) === null || _this$mediaPluginStat7 === void 0 || _this$mediaPluginStat7.updateAndDispatch({
|
|
179
|
+
videoControlsWrapperRef: this.videoControlsWrapperRef.current
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}, {
|
|
185
|
+
key: "bindKeydown",
|
|
186
|
+
value: function bindKeydown() {
|
|
187
|
+
var _this2 = this;
|
|
188
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
189
|
+
var _this$videoControlsWr;
|
|
190
|
+
var onKeydown = function onKeydown(event) {
|
|
191
|
+
if (event.key === 'Tab') {
|
|
192
|
+
var _this2$videoControlsW;
|
|
193
|
+
// Add focus trap for controls panel
|
|
194
|
+
var firstElement;
|
|
195
|
+
var lastElement;
|
|
196
|
+
var focusableElements = (_this2$videoControlsW = _this2.videoControlsWrapperRef) === null || _this2$videoControlsW === void 0 || (_this2$videoControlsW = _this2$videoControlsW.current) === null || _this2$videoControlsW === void 0 ? void 0 : _this2$videoControlsW.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');
|
|
197
|
+
if (focusableElements && focusableElements.length) {
|
|
198
|
+
firstElement = focusableElements[0];
|
|
199
|
+
lastElement = focusableElements[focusableElements.length - 1];
|
|
200
|
+
if (event.shiftKey && document.activeElement === firstElement) {
|
|
201
|
+
event.preventDefault();
|
|
202
|
+
lastElement.focus();
|
|
203
|
+
} else if (!event.shiftKey && document.activeElement === lastElement) {
|
|
204
|
+
var _firstElement;
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
(_firstElement = firstElement) === null || _firstElement === void 0 || _firstElement.focus();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
if ((_this$videoControlsWr = this.videoControlsWrapperRef) !== null && _this$videoControlsWr !== void 0 && _this$videoControlsWr.current) {
|
|
212
|
+
this.unbindKeyDown = (0, _bindEventListener.bind)(this.videoControlsWrapperRef.current, {
|
|
213
|
+
type: 'keydown',
|
|
214
|
+
listener: onKeydown,
|
|
215
|
+
options: {
|
|
216
|
+
capture: true,
|
|
217
|
+
passive: false
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
165
222
|
}
|
|
166
223
|
}, {
|
|
167
224
|
key: "render",
|
|
@@ -233,7 +290,8 @@ var MediaNode = exports.MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
233
290
|
isLazy: mediaOptions && mediaOptions.allowLazyLoading,
|
|
234
291
|
featureFlags: mediaOptions && mediaOptions.featureFlags,
|
|
235
292
|
contextId: contextId,
|
|
236
|
-
alt: alt
|
|
293
|
+
alt: alt,
|
|
294
|
+
videoControlsWrapperRef: this.videoControlsWrapperRef
|
|
237
295
|
})));
|
|
238
296
|
}
|
|
239
297
|
}]);
|
|
@@ -33,6 +33,7 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
|
33
33
|
var _captions = require("../commands/captions");
|
|
34
34
|
var _main = require("../pm-plugins/main");
|
|
35
35
|
var _CaptionPlaceholder = _interopRequireDefault(require("../ui/CaptionPlaceholder"));
|
|
36
|
+
var _CommentBadge = require("../ui/CommentBadge");
|
|
36
37
|
var _MediaViewerContainer = require("../ui/MediaViewer/MediaViewerContainer");
|
|
37
38
|
var _ResizableMediaSingle = _interopRequireDefault(require("../ui/ResizableMediaSingle"));
|
|
38
39
|
var _ResizableMediaSingleNext = _interopRequireDefault(require("../ui/ResizableMediaSingle/ResizableMediaSingleNext"));
|
|
@@ -328,7 +329,7 @@ var MediaSingleNode = exports.default = /*#__PURE__*/function (_Component) {
|
|
|
328
329
|
}, {
|
|
329
330
|
key: "render",
|
|
330
331
|
value: function render() {
|
|
331
|
-
var _pluginInjectionApi$m;
|
|
332
|
+
var _mediaOptions$getEdit, _pluginInjectionApi$m;
|
|
332
333
|
var _this$props2 = this.props,
|
|
333
334
|
selected = _this$props2.selected,
|
|
334
335
|
getPos = _this$props2.getPos,
|
|
@@ -344,10 +345,13 @@ var MediaSingleNode = exports.default = /*#__PURE__*/function (_Component) {
|
|
|
344
345
|
editorViewMode = _this$props2.editorViewMode,
|
|
345
346
|
mediaPluginState = _this$props2.mediaPluginState,
|
|
346
347
|
editorDisabled = _this$props2.editorDisabled;
|
|
347
|
-
var _ref4 =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
348
|
+
var _ref4 = (mediaOptions === null || mediaOptions === void 0 || (_mediaOptions$getEdit = mediaOptions.getEditorFeatureFlags) === null || _mediaOptions$getEdit === void 0 ? void 0 : _mediaOptions$getEdit.call(mediaOptions)) || {},
|
|
349
|
+
_ref4$commentsOnMedia = _ref4.commentsOnMedia,
|
|
350
|
+
commentsOnMedia = _ref4$commentsOnMedia === void 0 ? false : _ref4$commentsOnMedia;
|
|
351
|
+
var _ref5 = node.attrs,
|
|
352
|
+
layout = _ref5.layout,
|
|
353
|
+
widthType = _ref5.widthType,
|
|
354
|
+
mediaSingleWidthAttribute = _ref5.width;
|
|
351
355
|
var childNode = node.firstChild;
|
|
352
356
|
var attrs = (childNode === null || childNode === void 0 ? void 0 : childNode.attrs) || {};
|
|
353
357
|
|
|
@@ -431,7 +435,12 @@ var MediaSingleNode = exports.default = /*#__PURE__*/function (_Component) {
|
|
|
431
435
|
css: figureWrapperStyles,
|
|
432
436
|
className: _styles.MediaSingleNodeSelector,
|
|
433
437
|
onClick: this.onMediaSingleClicked
|
|
434
|
-
}, (0, _react2.jsx)(
|
|
438
|
+
}, commentsOnMedia && (0, _react2.jsx)(_CommentBadge.CommentBadge, {
|
|
439
|
+
view: view,
|
|
440
|
+
api: pluginInjectionApi,
|
|
441
|
+
mediaNode: node === null || node === void 0 ? void 0 : node.firstChild,
|
|
442
|
+
getPos: getPos
|
|
443
|
+
}), (0, _react2.jsx)("div", {
|
|
435
444
|
ref: this.props.forwardRef
|
|
436
445
|
}), shouldShowPlaceholder && (0, _react2.jsx)(_CaptionPlaceholder.default, {
|
|
437
446
|
ref: this.captionPlaceHolderRef,
|
|
@@ -463,19 +472,19 @@ var MediaSingleNode = exports.default = /*#__PURE__*/function (_Component) {
|
|
|
463
472
|
mediaOptions: {}
|
|
464
473
|
});
|
|
465
474
|
(0, _defineProperty2.default)(MediaSingleNode, "displayName", 'MediaSingleNode');
|
|
466
|
-
var MediaSingleNodeWrapper = function MediaSingleNodeWrapper(
|
|
467
|
-
var pluginInjectionApi =
|
|
468
|
-
mediaProvider =
|
|
469
|
-
contextIdentifierProvider =
|
|
470
|
-
node =
|
|
471
|
-
getPos =
|
|
472
|
-
mediaOptions =
|
|
473
|
-
view =
|
|
474
|
-
fullWidthMode =
|
|
475
|
-
selected =
|
|
476
|
-
eventDispatcher =
|
|
477
|
-
dispatchAnalyticsEvent =
|
|
478
|
-
forwardRef =
|
|
475
|
+
var MediaSingleNodeWrapper = function MediaSingleNodeWrapper(_ref6) {
|
|
476
|
+
var pluginInjectionApi = _ref6.pluginInjectionApi,
|
|
477
|
+
mediaProvider = _ref6.mediaProvider,
|
|
478
|
+
contextIdentifierProvider = _ref6.contextIdentifierProvider,
|
|
479
|
+
node = _ref6.node,
|
|
480
|
+
getPos = _ref6.getPos,
|
|
481
|
+
mediaOptions = _ref6.mediaOptions,
|
|
482
|
+
view = _ref6.view,
|
|
483
|
+
fullWidthMode = _ref6.fullWidthMode,
|
|
484
|
+
selected = _ref6.selected,
|
|
485
|
+
eventDispatcher = _ref6.eventDispatcher,
|
|
486
|
+
dispatchAnalyticsEvent = _ref6.dispatchAnalyticsEvent,
|
|
487
|
+
forwardRef = _ref6.forwardRef;
|
|
479
488
|
var _useSharedPluginState = (0, _hooks.useSharedPluginState)(pluginInjectionApi, ['width', 'media', 'annotation', 'editorDisabled', 'editorViewMode']),
|
|
480
489
|
widthState = _useSharedPluginState.widthState,
|
|
481
490
|
mediaState = _useSharedPluginState.mediaState,
|
|
@@ -590,6 +599,19 @@ var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
590
599
|
}
|
|
591
600
|
return undefined;
|
|
592
601
|
}
|
|
602
|
+
}, {
|
|
603
|
+
key: "stopEvent",
|
|
604
|
+
value: function stopEvent(event) {
|
|
605
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
606
|
+
if (this.isNodeSelected() && event instanceof KeyboardEvent && (event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) {
|
|
607
|
+
var targetType = event.target.type;
|
|
608
|
+
if (event.key === 'Enter' && targetType === 'button') {
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
593
615
|
}, {
|
|
594
616
|
key: "update",
|
|
595
617
|
value: function update(node, decorations, _innerDecorations, isValidUpdate) {
|
|
@@ -618,9 +640,9 @@ var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
618
640
|
return (0, _react2.jsx)(_providerFactory.WithProviders, {
|
|
619
641
|
providers: ['mediaProvider', 'contextIdentifierProvider'],
|
|
620
642
|
providerFactory: providerFactory,
|
|
621
|
-
renderNode: function renderNode(
|
|
622
|
-
var mediaProvider =
|
|
623
|
-
contextIdentifierProvider =
|
|
643
|
+
renderNode: function renderNode(_ref7) {
|
|
644
|
+
var mediaProvider = _ref7.mediaProvider,
|
|
645
|
+
contextIdentifierProvider = _ref7.contextIdentifierProvider;
|
|
624
646
|
return (0, _react2.jsx)(MediaSingleNodeWrapper, {
|
|
625
647
|
pluginInjectionApi: pluginInjectionApi,
|
|
626
648
|
mediaProvider: mediaProvider,
|
|
@@ -20,7 +20,6 @@ var _utils = require("../toolbar/utils");
|
|
|
20
20
|
function keymapPlugin(options, editorAnalyticsAPI, editorSelectionAPI, widthPlugin, getIntl) {
|
|
21
21
|
var list = {};
|
|
22
22
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.undo.common, ignoreLinksInSteps, list);
|
|
23
|
-
(0, _keymaps.bindKeymapWithCommand)(_keymaps.enter.common, splitMediaGroup, list);
|
|
24
23
|
if (options !== null && options !== void 0 && options.allowCaptions) {
|
|
25
24
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.moveDown.common, insertAndSelectCaption(editorAnalyticsAPI), list);
|
|
26
25
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.tab.common, insertAndSelectCaption(editorAnalyticsAPI), list);
|
|
@@ -28,12 +27,16 @@ function keymapPlugin(options, editorAnalyticsAPI, editorSelectionAPI, widthPlug
|
|
|
28
27
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.moveRight.common, arrowRightFromMediaSingle(editorSelectionAPI), list);
|
|
29
28
|
}
|
|
30
29
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.insertNewLine.common, splitMediaGroup, list);
|
|
30
|
+
(0, _keymaps.bindKeymapWithCommand)(_keymaps.enter.common, splitMediaGroup, list);
|
|
31
31
|
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.media.extended-resize-experience')) {
|
|
32
32
|
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y-media-resizing_b5v0o')) {
|
|
33
33
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.increaseMediaSize.common, handleMediaIncrease(editorAnalyticsAPI, widthPlugin, options, getIntl), list);
|
|
34
34
|
(0, _keymaps.bindKeymapWithCommand)(_keymaps.decreaseMediaSize.common, handleMediaDecrease(editorAnalyticsAPI, widthPlugin, options, getIntl), list);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
38
|
+
(0, _keymaps.bindKeymapWithCommand)(_keymaps.activateVideoControls.common, focusPlayButton, list);
|
|
39
|
+
}
|
|
37
40
|
return (0, _keymap.keymap)(list);
|
|
38
41
|
}
|
|
39
42
|
var ignoreLinksInSteps = function ignoreLinksInSteps(state) {
|
|
@@ -45,6 +48,15 @@ var splitMediaGroup = function splitMediaGroup(state) {
|
|
|
45
48
|
var mediaPluginState = _pluginKey.stateKey.getState(state);
|
|
46
49
|
return mediaPluginState.splitMediaGroup();
|
|
47
50
|
};
|
|
51
|
+
var focusPlayButton = function focusPlayButton(state) {
|
|
52
|
+
var _stateKey$getState;
|
|
53
|
+
var videoControlsWrapperRef = (_stateKey$getState = _pluginKey.stateKey.getState(state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.element;
|
|
54
|
+
if (videoControlsWrapperRef) {
|
|
55
|
+
var firstButton = videoControlsWrapperRef === null || videoControlsWrapperRef === void 0 ? void 0 : videoControlsWrapperRef.querySelector('button, [tabindex]:not([tabindex="-1"])');
|
|
56
|
+
firstButton === null || firstButton === void 0 || firstButton.focus();
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
};
|
|
48
60
|
var validationMaxMin = function validationMaxMin(newWidth, maxWidth, minWidth, validation) {
|
|
49
61
|
var newWidthValidated;
|
|
50
62
|
if (newWidth > maxWidth) {
|
|
@@ -848,7 +848,23 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
848
848
|
return _view2.DecorationSet.create(state.doc, dropPlaceholders);
|
|
849
849
|
},
|
|
850
850
|
nodeViews: options.nodeViews,
|
|
851
|
-
handleTextInput: function handleTextInput(view) {
|
|
851
|
+
handleTextInput: function handleTextInput(view, from, to, text) {
|
|
852
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
853
|
+
var selection = view.state.selection;
|
|
854
|
+
if (text === ' ' && selection instanceof _state2.NodeSelection && selection.node.type.name === 'mediaSingle') {
|
|
855
|
+
var _stateKey$getState;
|
|
856
|
+
var videoControlsWrapperRef = (_stateKey$getState = _pluginKey.stateKey.getState(view.state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.element;
|
|
857
|
+
var videoControls = videoControlsWrapperRef === null || videoControlsWrapperRef === void 0 ? void 0 : videoControlsWrapperRef.querySelectorAll('button, [tabindex]:not([tabindex="-1"])');
|
|
858
|
+
if (videoControls) {
|
|
859
|
+
var isVideoControl = Array.from(videoControls).some(function (videoControl) {
|
|
860
|
+
return document.activeElement === videoControl;
|
|
861
|
+
});
|
|
862
|
+
if (isVideoControl) {
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
852
868
|
getMediaPluginState(view.state).splitMediaGroup();
|
|
853
869
|
return false;
|
|
854
870
|
},
|
|
@@ -870,6 +886,39 @@ var createPlugin = exports.createPlugin = function createPlugin(_schema, options
|
|
|
870
886
|
return !!((_event$target2 = event.target) !== null && _event$target2 !== void 0 && _event$target2.closest("[class=\"".concat(MEDIA_CONTENT_WRAP_CLASS_NAME, "\"]")));
|
|
871
887
|
}
|
|
872
888
|
return false;
|
|
889
|
+
},
|
|
890
|
+
handleDOMEvents: {
|
|
891
|
+
keydown: function keydown(view, event) {
|
|
892
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
893
|
+
var selection = view.state.selection;
|
|
894
|
+
if (selection instanceof _state2.NodeSelection && selection.node.type.name === 'mediaSingle') {
|
|
895
|
+
// handle keydown events for video controls panel to prevent fire of rest prosemirror listeners;
|
|
896
|
+
if ((event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) {
|
|
897
|
+
var a11yDefaultKeys = ['Tab', 'Space', 'Enter', 'Shift', 'Esc'];
|
|
898
|
+
var targetsAndButtons = {
|
|
899
|
+
button: a11yDefaultKeys,
|
|
900
|
+
range: [].concat(a11yDefaultKeys, ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight']),
|
|
901
|
+
text: [].concat(a11yDefaultKeys, ['ArrowDown', 'ArrowUp', 'Esc'])
|
|
902
|
+
};
|
|
903
|
+
var targetType = event.target.type;
|
|
904
|
+
// only if targeting button or range/text input
|
|
905
|
+
if (targetType && targetType in targetsAndButtons) {
|
|
906
|
+
var targetRelatedA11YKeys = targetsAndButtons[targetType];
|
|
907
|
+
var allowedKeys = new Set(targetRelatedA11YKeys);
|
|
908
|
+
if (allowedKeys.has(event.key) || allowedKeys.has(event.code)) {
|
|
909
|
+
// allow event to bubble to be handled by react handlers
|
|
910
|
+
return true;
|
|
911
|
+
} else {
|
|
912
|
+
// otherwise focus editor to allow setting gapCursor. (e.g.: arrowRightFromMediaSingle)
|
|
913
|
+
view.focus();
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
// fire regular prosemirror listeners;
|
|
919
|
+
return false;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
873
922
|
}
|
|
874
923
|
}
|
|
875
924
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.CommentBadge = void 0;
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _reactIntlNext = require("react-intl-next");
|
|
10
|
+
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
11
|
+
var _mediaSingle = require("@atlaskit/editor-common/media-single");
|
|
12
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
13
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
14
|
+
var CommentBadgeWrapper = function CommentBadgeWrapper(_ref) {
|
|
15
|
+
var api = _ref.api,
|
|
16
|
+
mediaNode = _ref.mediaNode,
|
|
17
|
+
view = _ref.view,
|
|
18
|
+
getPos = _ref.getPos,
|
|
19
|
+
intl = _ref.intl;
|
|
20
|
+
var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['annotation']),
|
|
21
|
+
annotationState = _useSharedPluginState.annotationState;
|
|
22
|
+
var _view$state$schema = view.state.schema,
|
|
23
|
+
media = _view$state$schema.nodes.media,
|
|
24
|
+
annotation = _view$state$schema.marks.annotation,
|
|
25
|
+
state = view.state,
|
|
26
|
+
dispatch = view.dispatch;
|
|
27
|
+
var onClick = (0, _react.useCallback)(function () {
|
|
28
|
+
if (api.annotation && mediaNode) {
|
|
29
|
+
var showCommentForBlockNode = api.annotation.actions.showCommentForBlockNode;
|
|
30
|
+
showCommentForBlockNode(mediaNode)(state, dispatch);
|
|
31
|
+
}
|
|
32
|
+
}, [api.annotation, dispatch, mediaNode, state]);
|
|
33
|
+
var pos = getPos();
|
|
34
|
+
if (!Number.isFinite(pos) || !annotationState || !mediaNode || mediaNode.type !== media || mediaNode.marks.every(function (maybeAnnotation) {
|
|
35
|
+
return maybeAnnotation.type !== annotation || !(maybeAnnotation.attrs.id in annotationState.annotations) || annotationState.annotations[maybeAnnotation.attrs.id];
|
|
36
|
+
})) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
var mediaElement = view.domAtPos(pos + 1).node;
|
|
40
|
+
return /*#__PURE__*/_react.default.createElement(_mediaSingle.CommentBadge, {
|
|
41
|
+
view: view,
|
|
42
|
+
mediaNode: mediaNode,
|
|
43
|
+
onClick: onClick,
|
|
44
|
+
mediaElement: mediaElement,
|
|
45
|
+
intl: intl
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
var CommentBadge = exports.CommentBadge = (0, _reactIntlNext.injectIntl)(CommentBadgeWrapper);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import React, { Component } from 'react';
|
|
3
|
+
import { bind } from 'bind-event-listener';
|
|
3
4
|
import { MEDIA_CONTEXT } from '@atlaskit/analytics-namespaced-context';
|
|
4
5
|
import { AnalyticsContext } from '@atlaskit/analytics-next';
|
|
5
6
|
import { setNodeSelection, setTextSelection, withImageLoader } from '@atlaskit/editor-common/utils';
|
|
6
7
|
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
7
8
|
import { Card, CardLoading } from '@atlaskit/media-card';
|
|
9
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
8
10
|
import { stateKey as mediaStateKey } from '../../pm-plugins/plugin-key';
|
|
9
11
|
import { MediaCardWrapper } from '../styles';
|
|
10
12
|
|
|
@@ -16,6 +18,8 @@ export class MediaNode extends Component {
|
|
|
16
18
|
constructor(_props) {
|
|
17
19
|
super(_props);
|
|
18
20
|
_defineProperty(this, "state", {});
|
|
21
|
+
_defineProperty(this, "videoControlsWrapperRef", /*#__PURE__*/React.createRef());
|
|
22
|
+
_defineProperty(this, "unbindKeyDown", null);
|
|
19
23
|
_defineProperty(this, "setViewMediaClientConfig", async () => {
|
|
20
24
|
const mediaProvider = await this.props.mediaProvider;
|
|
21
25
|
if (mediaProvider) {
|
|
@@ -95,6 +99,9 @@ export class MediaNode extends Component {
|
|
|
95
99
|
node
|
|
96
100
|
} = this.props;
|
|
97
101
|
(_this$mediaPluginStat3 = this.mediaPluginState) === null || _this$mediaPluginStat3 === void 0 ? void 0 : _this$mediaPluginStat3.handleMediaNodeUnmount(node);
|
|
102
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh') && this.unbindKeyDown && typeof this.unbindKeyDown === 'function') {
|
|
103
|
+
this.unbindKeyDown();
|
|
104
|
+
}
|
|
98
105
|
}
|
|
99
106
|
componentDidUpdate(prevProps) {
|
|
100
107
|
var _this$mediaPluginStat5;
|
|
@@ -105,6 +112,53 @@ export class MediaNode extends Component {
|
|
|
105
112
|
}
|
|
106
113
|
(_this$mediaPluginStat5 = this.mediaPluginState) === null || _this$mediaPluginStat5 === void 0 ? void 0 : _this$mediaPluginStat5.updateElement();
|
|
107
114
|
this.setViewMediaClientConfig();
|
|
115
|
+
// this.videoControlsWrapperRef is null on componentDidMount. We need to wait until it has value
|
|
116
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh') && this.videoControlsWrapperRef && this.videoControlsWrapperRef.current) {
|
|
117
|
+
var _this$mediaPluginStat6;
|
|
118
|
+
if (!((_this$mediaPluginStat6 = this.mediaPluginState) !== null && _this$mediaPluginStat6 !== void 0 && _this$mediaPluginStat6.videoControlsWrapperRef)) {
|
|
119
|
+
var _this$mediaPluginStat7;
|
|
120
|
+
this.bindKeydown();
|
|
121
|
+
(_this$mediaPluginStat7 = this.mediaPluginState) === null || _this$mediaPluginStat7 === void 0 ? void 0 : _this$mediaPluginStat7.updateAndDispatch({
|
|
122
|
+
videoControlsWrapperRef: this.videoControlsWrapperRef.current
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
bindKeydown() {
|
|
128
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
129
|
+
var _this$videoControlsWr3;
|
|
130
|
+
const onKeydown = event => {
|
|
131
|
+
if (event.key === 'Tab') {
|
|
132
|
+
var _this$videoControlsWr, _this$videoControlsWr2;
|
|
133
|
+
// Add focus trap for controls panel
|
|
134
|
+
let firstElement;
|
|
135
|
+
let lastElement;
|
|
136
|
+
const focusableElements = (_this$videoControlsWr = this.videoControlsWrapperRef) === null || _this$videoControlsWr === void 0 ? void 0 : (_this$videoControlsWr2 = _this$videoControlsWr.current) === null || _this$videoControlsWr2 === void 0 ? void 0 : _this$videoControlsWr2.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');
|
|
137
|
+
if (focusableElements && focusableElements.length) {
|
|
138
|
+
firstElement = focusableElements[0];
|
|
139
|
+
lastElement = focusableElements[focusableElements.length - 1];
|
|
140
|
+
if (event.shiftKey && document.activeElement === firstElement) {
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
lastElement.focus();
|
|
143
|
+
} else if (!event.shiftKey && document.activeElement === lastElement) {
|
|
144
|
+
var _firstElement;
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
(_firstElement = firstElement) === null || _firstElement === void 0 ? void 0 : _firstElement.focus();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
if ((_this$videoControlsWr3 = this.videoControlsWrapperRef) !== null && _this$videoControlsWr3 !== void 0 && _this$videoControlsWr3.current) {
|
|
152
|
+
this.unbindKeyDown = bind(this.videoControlsWrapperRef.current, {
|
|
153
|
+
type: 'keydown',
|
|
154
|
+
listener: onKeydown,
|
|
155
|
+
options: {
|
|
156
|
+
capture: true,
|
|
157
|
+
passive: false
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
108
162
|
}
|
|
109
163
|
render() {
|
|
110
164
|
const {
|
|
@@ -175,7 +229,8 @@ export class MediaNode extends Component {
|
|
|
175
229
|
isLazy: mediaOptions && mediaOptions.allowLazyLoading,
|
|
176
230
|
featureFlags: mediaOptions && mediaOptions.featureFlags,
|
|
177
231
|
contextId: contextId,
|
|
178
|
-
alt: alt
|
|
232
|
+
alt: alt,
|
|
233
|
+
videoControlsWrapperRef: this.videoControlsWrapperRef
|
|
179
234
|
})));
|
|
180
235
|
}
|
|
181
236
|
}
|
|
@@ -18,6 +18,7 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
|
18
18
|
import { insertAndSelectCaptionFromMediaSinglePos } from '../commands/captions';
|
|
19
19
|
import { MEDIA_CONTENT_WRAP_CLASS_NAME } from '../pm-plugins/main';
|
|
20
20
|
import CaptionPlaceholder from '../ui/CaptionPlaceholder';
|
|
21
|
+
import { CommentBadge } from '../ui/CommentBadge';
|
|
21
22
|
import { MediaViewerContainer } from '../ui/MediaViewer/MediaViewerContainer';
|
|
22
23
|
import ResizableMediaSingle from '../ui/ResizableMediaSingle';
|
|
23
24
|
import ResizableMediaSingleNext from '../ui/ResizableMediaSingle/ResizableMediaSingleNext';
|
|
@@ -229,7 +230,7 @@ export default class MediaSingleNode extends Component {
|
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
232
|
render() {
|
|
232
|
-
var _pluginInjectionApi$m, _pluginInjectionApi$m2;
|
|
233
|
+
var _mediaOptions$getEdit, _pluginInjectionApi$m, _pluginInjectionApi$m2;
|
|
233
234
|
const {
|
|
234
235
|
selected,
|
|
235
236
|
getPos,
|
|
@@ -248,6 +249,9 @@ export default class MediaSingleNode extends Component {
|
|
|
248
249
|
mediaPluginState,
|
|
249
250
|
editorDisabled
|
|
250
251
|
} = this.props;
|
|
252
|
+
const {
|
|
253
|
+
commentsOnMedia = false
|
|
254
|
+
} = (mediaOptions === null || mediaOptions === void 0 ? void 0 : (_mediaOptions$getEdit = mediaOptions.getEditorFeatureFlags) === null || _mediaOptions$getEdit === void 0 ? void 0 : _mediaOptions$getEdit.call(mediaOptions)) || {};
|
|
251
255
|
const {
|
|
252
256
|
layout,
|
|
253
257
|
widthType,
|
|
@@ -344,7 +348,12 @@ export default class MediaSingleNode extends Component {
|
|
|
344
348
|
css: figureWrapperStyles,
|
|
345
349
|
className: MediaSingleNodeSelector,
|
|
346
350
|
onClick: this.onMediaSingleClicked
|
|
347
|
-
}, jsx(
|
|
351
|
+
}, commentsOnMedia && jsx(CommentBadge, {
|
|
352
|
+
view: view,
|
|
353
|
+
api: pluginInjectionApi,
|
|
354
|
+
mediaNode: node === null || node === void 0 ? void 0 : node.firstChild,
|
|
355
|
+
getPos: getPos
|
|
356
|
+
}), jsx("div", {
|
|
348
357
|
ref: this.props.forwardRef
|
|
349
358
|
}), shouldShowPlaceholder && jsx(CaptionPlaceholder, {
|
|
350
359
|
ref: this.captionPlaceHolderRef,
|
|
@@ -489,6 +498,17 @@ class MediaSingleNodeView extends ReactNodeView {
|
|
|
489
498
|
}
|
|
490
499
|
return undefined;
|
|
491
500
|
}
|
|
501
|
+
stopEvent(event) {
|
|
502
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
503
|
+
if (this.isNodeSelected() && event instanceof KeyboardEvent && (event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) {
|
|
504
|
+
const targetType = event.target.type;
|
|
505
|
+
if (event.key === 'Enter' && targetType === 'button') {
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
492
512
|
update(node, decorations, _innerDecorations, isValidUpdate) {
|
|
493
513
|
if (!isValidUpdate) {
|
|
494
514
|
isValidUpdate = (currentNode, newNode) => this.getNodeMediaId(currentNode) === this.getNodeMediaId(newNode);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bindKeymapWithCommand, decreaseMediaSize, enter, increaseMediaSize, insertNewLine, moveDown, moveLeft, moveRight, tab, undo } from '@atlaskit/editor-common/keymaps';
|
|
1
|
+
import { activateVideoControls, bindKeymapWithCommand, decreaseMediaSize, enter, increaseMediaSize, insertNewLine, moveDown, moveLeft, moveRight, tab, undo } from '@atlaskit/editor-common/keymaps';
|
|
2
2
|
import { mediaResizeAnnouncerMessMessages as mediaResizeAnnouncerMess } from '@atlaskit/editor-common/media';
|
|
3
3
|
import { calcMediaSingleMaxWidth, MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH } from '@atlaskit/editor-common/media-single';
|
|
4
4
|
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
|
|
@@ -13,7 +13,6 @@ import { calcNewLayout, getSelectedMediaSingle } from '../toolbar/utils';
|
|
|
13
13
|
export function keymapPlugin(options, editorAnalyticsAPI, editorSelectionAPI, widthPlugin, getIntl) {
|
|
14
14
|
const list = {};
|
|
15
15
|
bindKeymapWithCommand(undo.common, ignoreLinksInSteps, list);
|
|
16
|
-
bindKeymapWithCommand(enter.common, splitMediaGroup, list);
|
|
17
16
|
if (options !== null && options !== void 0 && options.allowCaptions) {
|
|
18
17
|
bindKeymapWithCommand(moveDown.common, insertAndSelectCaption(editorAnalyticsAPI), list);
|
|
19
18
|
bindKeymapWithCommand(tab.common, insertAndSelectCaption(editorAnalyticsAPI), list);
|
|
@@ -21,12 +20,16 @@ export function keymapPlugin(options, editorAnalyticsAPI, editorSelectionAPI, wi
|
|
|
21
20
|
bindKeymapWithCommand(moveRight.common, arrowRightFromMediaSingle(editorSelectionAPI), list);
|
|
22
21
|
}
|
|
23
22
|
bindKeymapWithCommand(insertNewLine.common, splitMediaGroup, list);
|
|
23
|
+
bindKeymapWithCommand(enter.common, splitMediaGroup, list);
|
|
24
24
|
if (getBooleanFF('platform.editor.media.extended-resize-experience')) {
|
|
25
25
|
if (getBooleanFF('platform.editor.a11y-media-resizing_b5v0o')) {
|
|
26
26
|
bindKeymapWithCommand(increaseMediaSize.common, handleMediaIncrease(editorAnalyticsAPI, widthPlugin, options, getIntl), list);
|
|
27
27
|
bindKeymapWithCommand(decreaseMediaSize.common, handleMediaDecrease(editorAnalyticsAPI, widthPlugin, options, getIntl), list);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
31
|
+
bindKeymapWithCommand(activateVideoControls.common, focusPlayButton, list);
|
|
32
|
+
}
|
|
30
33
|
return keymap(list);
|
|
31
34
|
}
|
|
32
35
|
const ignoreLinksInSteps = state => {
|
|
@@ -38,6 +41,15 @@ const splitMediaGroup = state => {
|
|
|
38
41
|
const mediaPluginState = stateKey.getState(state);
|
|
39
42
|
return mediaPluginState.splitMediaGroup();
|
|
40
43
|
};
|
|
44
|
+
const focusPlayButton = state => {
|
|
45
|
+
var _stateKey$getState;
|
|
46
|
+
const videoControlsWrapperRef = (_stateKey$getState = stateKey.getState(state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.element;
|
|
47
|
+
if (videoControlsWrapperRef) {
|
|
48
|
+
const firstButton = videoControlsWrapperRef === null || videoControlsWrapperRef === void 0 ? void 0 : videoControlsWrapperRef.querySelector('button, [tabindex]:not([tabindex="-1"])');
|
|
49
|
+
firstButton === null || firstButton === void 0 ? void 0 : firstButton.focus();
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
};
|
|
41
53
|
const validationMaxMin = (newWidth, maxWidth, minWidth, validation) => {
|
|
42
54
|
let newWidthValidated;
|
|
43
55
|
if (newWidth > maxWidth) {
|
|
@@ -733,7 +733,25 @@ export const createPlugin = (_schema, options, reactContext, getIntl, pluginInje
|
|
|
733
733
|
return DecorationSet.create(state.doc, dropPlaceholders);
|
|
734
734
|
},
|
|
735
735
|
nodeViews: options.nodeViews,
|
|
736
|
-
handleTextInput(view) {
|
|
736
|
+
handleTextInput(view, from, to, text) {
|
|
737
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
738
|
+
const {
|
|
739
|
+
selection
|
|
740
|
+
} = view.state;
|
|
741
|
+
if (text === ' ' && selection instanceof NodeSelection && selection.node.type.name === 'mediaSingle') {
|
|
742
|
+
var _stateKey$getState;
|
|
743
|
+
const videoControlsWrapperRef = (_stateKey$getState = stateKey.getState(view.state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.element;
|
|
744
|
+
const videoControls = videoControlsWrapperRef === null || videoControlsWrapperRef === void 0 ? void 0 : videoControlsWrapperRef.querySelectorAll('button, [tabindex]:not([tabindex="-1"])');
|
|
745
|
+
if (videoControls) {
|
|
746
|
+
const isVideoControl = Array.from(videoControls).some(videoControl => {
|
|
747
|
+
return document.activeElement === videoControl;
|
|
748
|
+
});
|
|
749
|
+
if (isVideoControl) {
|
|
750
|
+
return true;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
737
755
|
getMediaPluginState(view.state).splitMediaGroup();
|
|
738
756
|
return false;
|
|
739
757
|
},
|
|
@@ -755,6 +773,41 @@ export const createPlugin = (_schema, options, reactContext, getIntl, pluginInje
|
|
|
755
773
|
return !!((_event$target2 = event.target) !== null && _event$target2 !== void 0 && _event$target2.closest(`[class="${MEDIA_CONTENT_WRAP_CLASS_NAME}"]`));
|
|
756
774
|
}
|
|
757
775
|
return false;
|
|
776
|
+
},
|
|
777
|
+
handleDOMEvents: {
|
|
778
|
+
keydown: (view, event) => {
|
|
779
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
780
|
+
const {
|
|
781
|
+
selection
|
|
782
|
+
} = view.state;
|
|
783
|
+
if (selection instanceof NodeSelection && selection.node.type.name === 'mediaSingle') {
|
|
784
|
+
// handle keydown events for video controls panel to prevent fire of rest prosemirror listeners;
|
|
785
|
+
if ((event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) {
|
|
786
|
+
const a11yDefaultKeys = ['Tab', 'Space', 'Enter', 'Shift', 'Esc'];
|
|
787
|
+
const targetsAndButtons = {
|
|
788
|
+
button: a11yDefaultKeys,
|
|
789
|
+
range: [...a11yDefaultKeys, 'ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'],
|
|
790
|
+
text: [...a11yDefaultKeys, 'ArrowDown', 'ArrowUp', 'Esc']
|
|
791
|
+
};
|
|
792
|
+
const targetType = event.target.type;
|
|
793
|
+
// only if targeting button or range/text input
|
|
794
|
+
if (targetType && targetType in targetsAndButtons) {
|
|
795
|
+
let targetRelatedA11YKeys = targetsAndButtons[targetType];
|
|
796
|
+
const allowedKeys = new Set(targetRelatedA11YKeys);
|
|
797
|
+
if (allowedKeys.has(event.key) || allowedKeys.has(event.code)) {
|
|
798
|
+
// allow event to bubble to be handled by react handlers
|
|
799
|
+
return true;
|
|
800
|
+
} else {
|
|
801
|
+
// otherwise focus editor to allow setting gapCursor. (e.g.: arrowRightFromMediaSingle)
|
|
802
|
+
view.focus();
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
// fire regular prosemirror listeners;
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
758
811
|
}
|
|
759
812
|
}
|
|
760
813
|
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { injectIntl } from 'react-intl-next';
|
|
3
|
+
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
4
|
+
import { CommentBadge as CommentBadgeComponent } from '@atlaskit/editor-common/media-single';
|
|
5
|
+
const CommentBadgeWrapper = ({
|
|
6
|
+
api,
|
|
7
|
+
mediaNode,
|
|
8
|
+
view,
|
|
9
|
+
getPos,
|
|
10
|
+
intl
|
|
11
|
+
}) => {
|
|
12
|
+
const {
|
|
13
|
+
annotationState
|
|
14
|
+
} = useSharedPluginState(api, ['annotation']);
|
|
15
|
+
const {
|
|
16
|
+
state: {
|
|
17
|
+
schema: {
|
|
18
|
+
nodes: {
|
|
19
|
+
media
|
|
20
|
+
},
|
|
21
|
+
marks: {
|
|
22
|
+
annotation
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
state,
|
|
27
|
+
dispatch
|
|
28
|
+
} = view;
|
|
29
|
+
const onClick = useCallback(() => {
|
|
30
|
+
if (api.annotation && mediaNode) {
|
|
31
|
+
const {
|
|
32
|
+
showCommentForBlockNode
|
|
33
|
+
} = api.annotation.actions;
|
|
34
|
+
showCommentForBlockNode(mediaNode)(state, dispatch);
|
|
35
|
+
}
|
|
36
|
+
}, [api.annotation, dispatch, mediaNode, state]);
|
|
37
|
+
const pos = getPos();
|
|
38
|
+
if (!Number.isFinite(pos) || !annotationState || !mediaNode || mediaNode.type !== media || mediaNode.marks.every(maybeAnnotation => maybeAnnotation.type !== annotation || !(maybeAnnotation.attrs.id in annotationState.annotations) || annotationState.annotations[maybeAnnotation.attrs.id])) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const mediaElement = view.domAtPos(pos + 1).node;
|
|
42
|
+
return /*#__PURE__*/React.createElement(CommentBadgeComponent, {
|
|
43
|
+
view: view,
|
|
44
|
+
mediaNode: mediaNode,
|
|
45
|
+
onClick: onClick,
|
|
46
|
+
mediaElement: mediaElement,
|
|
47
|
+
intl: intl
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
export const CommentBadge = injectIntl(CommentBadgeWrapper);
|
|
@@ -10,11 +10,13 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
|
10
10
|
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
11
11
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
12
12
|
import React, { Component } from 'react';
|
|
13
|
+
import { bind } from 'bind-event-listener';
|
|
13
14
|
import { MEDIA_CONTEXT } from '@atlaskit/analytics-namespaced-context';
|
|
14
15
|
import { AnalyticsContext } from '@atlaskit/analytics-next';
|
|
15
16
|
import { setNodeSelection, setTextSelection, withImageLoader } from '@atlaskit/editor-common/utils';
|
|
16
17
|
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
17
18
|
import { Card, CardLoading } from '@atlaskit/media-card';
|
|
19
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
18
20
|
import { stateKey as mediaStateKey } from '../../pm-plugins/plugin-key';
|
|
19
21
|
import { MediaCardWrapper } from '../styles';
|
|
20
22
|
|
|
@@ -30,6 +32,8 @@ export var MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
30
32
|
_classCallCheck(this, MediaNode);
|
|
31
33
|
_this = _super.call(this, _props);
|
|
32
34
|
_defineProperty(_assertThisInitialized(_this), "state", {});
|
|
35
|
+
_defineProperty(_assertThisInitialized(_this), "videoControlsWrapperRef", /*#__PURE__*/React.createRef());
|
|
36
|
+
_defineProperty(_assertThisInitialized(_this), "unbindKeyDown", null);
|
|
33
37
|
_defineProperty(_assertThisInitialized(_this), "setViewMediaClientConfig", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
34
38
|
var mediaProvider, viewMediaClientConfig;
|
|
35
39
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
@@ -141,6 +145,9 @@ export var MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
141
145
|
var _this$mediaPluginStat3;
|
|
142
146
|
var node = this.props.node;
|
|
143
147
|
(_this$mediaPluginStat3 = this.mediaPluginState) === null || _this$mediaPluginStat3 === void 0 || _this$mediaPluginStat3.handleMediaNodeUnmount(node);
|
|
148
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh') && this.unbindKeyDown && typeof this.unbindKeyDown === 'function') {
|
|
149
|
+
this.unbindKeyDown();
|
|
150
|
+
}
|
|
144
151
|
}
|
|
145
152
|
}, {
|
|
146
153
|
key: "componentDidUpdate",
|
|
@@ -153,6 +160,56 @@ export var MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
153
160
|
}
|
|
154
161
|
(_this$mediaPluginStat5 = this.mediaPluginState) === null || _this$mediaPluginStat5 === void 0 || _this$mediaPluginStat5.updateElement();
|
|
155
162
|
this.setViewMediaClientConfig();
|
|
163
|
+
// this.videoControlsWrapperRef is null on componentDidMount. We need to wait until it has value
|
|
164
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh') && this.videoControlsWrapperRef && this.videoControlsWrapperRef.current) {
|
|
165
|
+
var _this$mediaPluginStat6;
|
|
166
|
+
if (!((_this$mediaPluginStat6 = this.mediaPluginState) !== null && _this$mediaPluginStat6 !== void 0 && _this$mediaPluginStat6.videoControlsWrapperRef)) {
|
|
167
|
+
var _this$mediaPluginStat7;
|
|
168
|
+
this.bindKeydown();
|
|
169
|
+
(_this$mediaPluginStat7 = this.mediaPluginState) === null || _this$mediaPluginStat7 === void 0 || _this$mediaPluginStat7.updateAndDispatch({
|
|
170
|
+
videoControlsWrapperRef: this.videoControlsWrapperRef.current
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}, {
|
|
176
|
+
key: "bindKeydown",
|
|
177
|
+
value: function bindKeydown() {
|
|
178
|
+
var _this2 = this;
|
|
179
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
180
|
+
var _this$videoControlsWr;
|
|
181
|
+
var onKeydown = function onKeydown(event) {
|
|
182
|
+
if (event.key === 'Tab') {
|
|
183
|
+
var _this2$videoControlsW;
|
|
184
|
+
// Add focus trap for controls panel
|
|
185
|
+
var firstElement;
|
|
186
|
+
var lastElement;
|
|
187
|
+
var focusableElements = (_this2$videoControlsW = _this2.videoControlsWrapperRef) === null || _this2$videoControlsW === void 0 || (_this2$videoControlsW = _this2$videoControlsW.current) === null || _this2$videoControlsW === void 0 ? void 0 : _this2$videoControlsW.querySelectorAll('button, input, [tabindex]:not([tabindex="-1"])');
|
|
188
|
+
if (focusableElements && focusableElements.length) {
|
|
189
|
+
firstElement = focusableElements[0];
|
|
190
|
+
lastElement = focusableElements[focusableElements.length - 1];
|
|
191
|
+
if (event.shiftKey && document.activeElement === firstElement) {
|
|
192
|
+
event.preventDefault();
|
|
193
|
+
lastElement.focus();
|
|
194
|
+
} else if (!event.shiftKey && document.activeElement === lastElement) {
|
|
195
|
+
var _firstElement;
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
(_firstElement = firstElement) === null || _firstElement === void 0 || _firstElement.focus();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
if ((_this$videoControlsWr = this.videoControlsWrapperRef) !== null && _this$videoControlsWr !== void 0 && _this$videoControlsWr.current) {
|
|
203
|
+
this.unbindKeyDown = bind(this.videoControlsWrapperRef.current, {
|
|
204
|
+
type: 'keydown',
|
|
205
|
+
listener: onKeydown,
|
|
206
|
+
options: {
|
|
207
|
+
capture: true,
|
|
208
|
+
passive: false
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
156
213
|
}
|
|
157
214
|
}, {
|
|
158
215
|
key: "render",
|
|
@@ -224,7 +281,8 @@ export var MediaNode = /*#__PURE__*/function (_Component) {
|
|
|
224
281
|
isLazy: mediaOptions && mediaOptions.allowLazyLoading,
|
|
225
282
|
featureFlags: mediaOptions && mediaOptions.featureFlags,
|
|
226
283
|
contextId: contextId,
|
|
227
|
-
alt: alt
|
|
284
|
+
alt: alt,
|
|
285
|
+
videoControlsWrapperRef: this.videoControlsWrapperRef
|
|
228
286
|
})));
|
|
229
287
|
}
|
|
230
288
|
}]);
|
|
@@ -31,6 +31,7 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
|
31
31
|
import { insertAndSelectCaptionFromMediaSinglePos } from '../commands/captions';
|
|
32
32
|
import { MEDIA_CONTENT_WRAP_CLASS_NAME } from '../pm-plugins/main';
|
|
33
33
|
import CaptionPlaceholder from '../ui/CaptionPlaceholder';
|
|
34
|
+
import { CommentBadge } from '../ui/CommentBadge';
|
|
34
35
|
import { MediaViewerContainer } from '../ui/MediaViewer/MediaViewerContainer';
|
|
35
36
|
import ResizableMediaSingle from '../ui/ResizableMediaSingle';
|
|
36
37
|
import ResizableMediaSingleNext from '../ui/ResizableMediaSingle/ResizableMediaSingleNext';
|
|
@@ -320,7 +321,7 @@ var MediaSingleNode = /*#__PURE__*/function (_Component) {
|
|
|
320
321
|
}, {
|
|
321
322
|
key: "render",
|
|
322
323
|
value: function render() {
|
|
323
|
-
var _pluginInjectionApi$m;
|
|
324
|
+
var _mediaOptions$getEdit, _pluginInjectionApi$m;
|
|
324
325
|
var _this$props2 = this.props,
|
|
325
326
|
selected = _this$props2.selected,
|
|
326
327
|
getPos = _this$props2.getPos,
|
|
@@ -336,10 +337,13 @@ var MediaSingleNode = /*#__PURE__*/function (_Component) {
|
|
|
336
337
|
editorViewMode = _this$props2.editorViewMode,
|
|
337
338
|
mediaPluginState = _this$props2.mediaPluginState,
|
|
338
339
|
editorDisabled = _this$props2.editorDisabled;
|
|
339
|
-
var _ref4 =
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
340
|
+
var _ref4 = (mediaOptions === null || mediaOptions === void 0 || (_mediaOptions$getEdit = mediaOptions.getEditorFeatureFlags) === null || _mediaOptions$getEdit === void 0 ? void 0 : _mediaOptions$getEdit.call(mediaOptions)) || {},
|
|
341
|
+
_ref4$commentsOnMedia = _ref4.commentsOnMedia,
|
|
342
|
+
commentsOnMedia = _ref4$commentsOnMedia === void 0 ? false : _ref4$commentsOnMedia;
|
|
343
|
+
var _ref5 = node.attrs,
|
|
344
|
+
layout = _ref5.layout,
|
|
345
|
+
widthType = _ref5.widthType,
|
|
346
|
+
mediaSingleWidthAttribute = _ref5.width;
|
|
343
347
|
var childNode = node.firstChild;
|
|
344
348
|
var attrs = (childNode === null || childNode === void 0 ? void 0 : childNode.attrs) || {};
|
|
345
349
|
|
|
@@ -423,7 +427,12 @@ var MediaSingleNode = /*#__PURE__*/function (_Component) {
|
|
|
423
427
|
css: figureWrapperStyles,
|
|
424
428
|
className: MediaSingleNodeSelector,
|
|
425
429
|
onClick: this.onMediaSingleClicked
|
|
426
|
-
}, jsx(
|
|
430
|
+
}, commentsOnMedia && jsx(CommentBadge, {
|
|
431
|
+
view: view,
|
|
432
|
+
api: pluginInjectionApi,
|
|
433
|
+
mediaNode: node === null || node === void 0 ? void 0 : node.firstChild,
|
|
434
|
+
getPos: getPos
|
|
435
|
+
}), jsx("div", {
|
|
427
436
|
ref: this.props.forwardRef
|
|
428
437
|
}), shouldShowPlaceholder && jsx(CaptionPlaceholder, {
|
|
429
438
|
ref: this.captionPlaceHolderRef,
|
|
@@ -456,19 +465,19 @@ _defineProperty(MediaSingleNode, "defaultProps", {
|
|
|
456
465
|
});
|
|
457
466
|
_defineProperty(MediaSingleNode, "displayName", 'MediaSingleNode');
|
|
458
467
|
export { MediaSingleNode as default };
|
|
459
|
-
var MediaSingleNodeWrapper = function MediaSingleNodeWrapper(
|
|
460
|
-
var pluginInjectionApi =
|
|
461
|
-
mediaProvider =
|
|
462
|
-
contextIdentifierProvider =
|
|
463
|
-
node =
|
|
464
|
-
getPos =
|
|
465
|
-
mediaOptions =
|
|
466
|
-
view =
|
|
467
|
-
fullWidthMode =
|
|
468
|
-
selected =
|
|
469
|
-
eventDispatcher =
|
|
470
|
-
dispatchAnalyticsEvent =
|
|
471
|
-
forwardRef =
|
|
468
|
+
var MediaSingleNodeWrapper = function MediaSingleNodeWrapper(_ref6) {
|
|
469
|
+
var pluginInjectionApi = _ref6.pluginInjectionApi,
|
|
470
|
+
mediaProvider = _ref6.mediaProvider,
|
|
471
|
+
contextIdentifierProvider = _ref6.contextIdentifierProvider,
|
|
472
|
+
node = _ref6.node,
|
|
473
|
+
getPos = _ref6.getPos,
|
|
474
|
+
mediaOptions = _ref6.mediaOptions,
|
|
475
|
+
view = _ref6.view,
|
|
476
|
+
fullWidthMode = _ref6.fullWidthMode,
|
|
477
|
+
selected = _ref6.selected,
|
|
478
|
+
eventDispatcher = _ref6.eventDispatcher,
|
|
479
|
+
dispatchAnalyticsEvent = _ref6.dispatchAnalyticsEvent,
|
|
480
|
+
forwardRef = _ref6.forwardRef;
|
|
472
481
|
var _useSharedPluginState = useSharedPluginState(pluginInjectionApi, ['width', 'media', 'annotation', 'editorDisabled', 'editorViewMode']),
|
|
473
482
|
widthState = _useSharedPluginState.widthState,
|
|
474
483
|
mediaState = _useSharedPluginState.mediaState,
|
|
@@ -583,6 +592,19 @@ var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
583
592
|
}
|
|
584
593
|
return undefined;
|
|
585
594
|
}
|
|
595
|
+
}, {
|
|
596
|
+
key: "stopEvent",
|
|
597
|
+
value: function stopEvent(event) {
|
|
598
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
599
|
+
if (this.isNodeSelected() && event instanceof KeyboardEvent && (event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) {
|
|
600
|
+
var targetType = event.target.type;
|
|
601
|
+
if (event.key === 'Enter' && targetType === 'button') {
|
|
602
|
+
return true;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
586
608
|
}, {
|
|
587
609
|
key: "update",
|
|
588
610
|
value: function update(node, decorations, _innerDecorations, isValidUpdate) {
|
|
@@ -611,9 +633,9 @@ var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
611
633
|
return jsx(WithProviders, {
|
|
612
634
|
providers: ['mediaProvider', 'contextIdentifierProvider'],
|
|
613
635
|
providerFactory: providerFactory,
|
|
614
|
-
renderNode: function renderNode(
|
|
615
|
-
var mediaProvider =
|
|
616
|
-
contextIdentifierProvider =
|
|
636
|
+
renderNode: function renderNode(_ref7) {
|
|
637
|
+
var mediaProvider = _ref7.mediaProvider,
|
|
638
|
+
contextIdentifierProvider = _ref7.contextIdentifierProvider;
|
|
617
639
|
return jsx(MediaSingleNodeWrapper, {
|
|
618
640
|
pluginInjectionApi: pluginInjectionApi,
|
|
619
641
|
mediaProvider: mediaProvider,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bindKeymapWithCommand, decreaseMediaSize, enter, increaseMediaSize, insertNewLine, moveDown, moveLeft, moveRight, tab, undo } from '@atlaskit/editor-common/keymaps';
|
|
1
|
+
import { activateVideoControls, bindKeymapWithCommand, decreaseMediaSize, enter, increaseMediaSize, insertNewLine, moveDown, moveLeft, moveRight, tab, undo } from '@atlaskit/editor-common/keymaps';
|
|
2
2
|
import { mediaResizeAnnouncerMessMessages as mediaResizeAnnouncerMess } from '@atlaskit/editor-common/media';
|
|
3
3
|
import { calcMediaSingleMaxWidth, MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH } from '@atlaskit/editor-common/media-single';
|
|
4
4
|
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
|
|
@@ -13,7 +13,6 @@ import { calcNewLayout, getSelectedMediaSingle } from '../toolbar/utils';
|
|
|
13
13
|
export function keymapPlugin(options, editorAnalyticsAPI, editorSelectionAPI, widthPlugin, getIntl) {
|
|
14
14
|
var list = {};
|
|
15
15
|
bindKeymapWithCommand(undo.common, ignoreLinksInSteps, list);
|
|
16
|
-
bindKeymapWithCommand(enter.common, splitMediaGroup, list);
|
|
17
16
|
if (options !== null && options !== void 0 && options.allowCaptions) {
|
|
18
17
|
bindKeymapWithCommand(moveDown.common, insertAndSelectCaption(editorAnalyticsAPI), list);
|
|
19
18
|
bindKeymapWithCommand(tab.common, insertAndSelectCaption(editorAnalyticsAPI), list);
|
|
@@ -21,12 +20,16 @@ export function keymapPlugin(options, editorAnalyticsAPI, editorSelectionAPI, wi
|
|
|
21
20
|
bindKeymapWithCommand(moveRight.common, arrowRightFromMediaSingle(editorSelectionAPI), list);
|
|
22
21
|
}
|
|
23
22
|
bindKeymapWithCommand(insertNewLine.common, splitMediaGroup, list);
|
|
23
|
+
bindKeymapWithCommand(enter.common, splitMediaGroup, list);
|
|
24
24
|
if (getBooleanFF('platform.editor.media.extended-resize-experience')) {
|
|
25
25
|
if (getBooleanFF('platform.editor.a11y-media-resizing_b5v0o')) {
|
|
26
26
|
bindKeymapWithCommand(increaseMediaSize.common, handleMediaIncrease(editorAnalyticsAPI, widthPlugin, options, getIntl), list);
|
|
27
27
|
bindKeymapWithCommand(decreaseMediaSize.common, handleMediaDecrease(editorAnalyticsAPI, widthPlugin, options, getIntl), list);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
31
|
+
bindKeymapWithCommand(activateVideoControls.common, focusPlayButton, list);
|
|
32
|
+
}
|
|
30
33
|
return keymap(list);
|
|
31
34
|
}
|
|
32
35
|
var ignoreLinksInSteps = function ignoreLinksInSteps(state) {
|
|
@@ -38,6 +41,15 @@ var splitMediaGroup = function splitMediaGroup(state) {
|
|
|
38
41
|
var mediaPluginState = stateKey.getState(state);
|
|
39
42
|
return mediaPluginState.splitMediaGroup();
|
|
40
43
|
};
|
|
44
|
+
var focusPlayButton = function focusPlayButton(state) {
|
|
45
|
+
var _stateKey$getState;
|
|
46
|
+
var videoControlsWrapperRef = (_stateKey$getState = stateKey.getState(state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.element;
|
|
47
|
+
if (videoControlsWrapperRef) {
|
|
48
|
+
var firstButton = videoControlsWrapperRef === null || videoControlsWrapperRef === void 0 ? void 0 : videoControlsWrapperRef.querySelector('button, [tabindex]:not([tabindex="-1"])');
|
|
49
|
+
firstButton === null || firstButton === void 0 || firstButton.focus();
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
};
|
|
41
53
|
var validationMaxMin = function validationMaxMin(newWidth, maxWidth, minWidth, validation) {
|
|
42
54
|
var newWidthValidated;
|
|
43
55
|
if (newWidth > maxWidth) {
|
|
@@ -833,7 +833,23 @@ export var createPlugin = function createPlugin(_schema, options, reactContext,
|
|
|
833
833
|
return DecorationSet.create(state.doc, dropPlaceholders);
|
|
834
834
|
},
|
|
835
835
|
nodeViews: options.nodeViews,
|
|
836
|
-
handleTextInput: function handleTextInput(view) {
|
|
836
|
+
handleTextInput: function handleTextInput(view, from, to, text) {
|
|
837
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
838
|
+
var selection = view.state.selection;
|
|
839
|
+
if (text === ' ' && selection instanceof NodeSelection && selection.node.type.name === 'mediaSingle') {
|
|
840
|
+
var _stateKey$getState;
|
|
841
|
+
var videoControlsWrapperRef = (_stateKey$getState = stateKey.getState(view.state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.element;
|
|
842
|
+
var videoControls = videoControlsWrapperRef === null || videoControlsWrapperRef === void 0 ? void 0 : videoControlsWrapperRef.querySelectorAll('button, [tabindex]:not([tabindex="-1"])');
|
|
843
|
+
if (videoControls) {
|
|
844
|
+
var isVideoControl = Array.from(videoControls).some(function (videoControl) {
|
|
845
|
+
return document.activeElement === videoControl;
|
|
846
|
+
});
|
|
847
|
+
if (isVideoControl) {
|
|
848
|
+
return true;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
837
853
|
getMediaPluginState(view.state).splitMediaGroup();
|
|
838
854
|
return false;
|
|
839
855
|
},
|
|
@@ -855,6 +871,39 @@ export var createPlugin = function createPlugin(_schema, options, reactContext,
|
|
|
855
871
|
return !!((_event$target2 = event.target) !== null && _event$target2 !== void 0 && _event$target2.closest("[class=\"".concat(MEDIA_CONTENT_WRAP_CLASS_NAME, "\"]")));
|
|
856
872
|
}
|
|
857
873
|
return false;
|
|
874
|
+
},
|
|
875
|
+
handleDOMEvents: {
|
|
876
|
+
keydown: function keydown(view, event) {
|
|
877
|
+
if (getBooleanFF('platform.editor.a11y_video_controls_keyboard_support_yhcxh')) {
|
|
878
|
+
var selection = view.state.selection;
|
|
879
|
+
if (selection instanceof NodeSelection && selection.node.type.name === 'mediaSingle') {
|
|
880
|
+
// handle keydown events for video controls panel to prevent fire of rest prosemirror listeners;
|
|
881
|
+
if ((event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) {
|
|
882
|
+
var a11yDefaultKeys = ['Tab', 'Space', 'Enter', 'Shift', 'Esc'];
|
|
883
|
+
var targetsAndButtons = {
|
|
884
|
+
button: a11yDefaultKeys,
|
|
885
|
+
range: [].concat(a11yDefaultKeys, ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight']),
|
|
886
|
+
text: [].concat(a11yDefaultKeys, ['ArrowDown', 'ArrowUp', 'Esc'])
|
|
887
|
+
};
|
|
888
|
+
var targetType = event.target.type;
|
|
889
|
+
// only if targeting button or range/text input
|
|
890
|
+
if (targetType && targetType in targetsAndButtons) {
|
|
891
|
+
var targetRelatedA11YKeys = targetsAndButtons[targetType];
|
|
892
|
+
var allowedKeys = new Set(targetRelatedA11YKeys);
|
|
893
|
+
if (allowedKeys.has(event.key) || allowedKeys.has(event.code)) {
|
|
894
|
+
// allow event to bubble to be handled by react handlers
|
|
895
|
+
return true;
|
|
896
|
+
} else {
|
|
897
|
+
// otherwise focus editor to allow setting gapCursor. (e.g.: arrowRightFromMediaSingle)
|
|
898
|
+
view.focus();
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
// fire regular prosemirror listeners;
|
|
904
|
+
return false;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
858
907
|
}
|
|
859
908
|
}
|
|
860
909
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { injectIntl } from 'react-intl-next';
|
|
3
|
+
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
4
|
+
import { CommentBadge as CommentBadgeComponent } from '@atlaskit/editor-common/media-single';
|
|
5
|
+
var CommentBadgeWrapper = function CommentBadgeWrapper(_ref) {
|
|
6
|
+
var api = _ref.api,
|
|
7
|
+
mediaNode = _ref.mediaNode,
|
|
8
|
+
view = _ref.view,
|
|
9
|
+
getPos = _ref.getPos,
|
|
10
|
+
intl = _ref.intl;
|
|
11
|
+
var _useSharedPluginState = useSharedPluginState(api, ['annotation']),
|
|
12
|
+
annotationState = _useSharedPluginState.annotationState;
|
|
13
|
+
var _view$state$schema = view.state.schema,
|
|
14
|
+
media = _view$state$schema.nodes.media,
|
|
15
|
+
annotation = _view$state$schema.marks.annotation,
|
|
16
|
+
state = view.state,
|
|
17
|
+
dispatch = view.dispatch;
|
|
18
|
+
var onClick = useCallback(function () {
|
|
19
|
+
if (api.annotation && mediaNode) {
|
|
20
|
+
var showCommentForBlockNode = api.annotation.actions.showCommentForBlockNode;
|
|
21
|
+
showCommentForBlockNode(mediaNode)(state, dispatch);
|
|
22
|
+
}
|
|
23
|
+
}, [api.annotation, dispatch, mediaNode, state]);
|
|
24
|
+
var pos = getPos();
|
|
25
|
+
if (!Number.isFinite(pos) || !annotationState || !mediaNode || mediaNode.type !== media || mediaNode.marks.every(function (maybeAnnotation) {
|
|
26
|
+
return maybeAnnotation.type !== annotation || !(maybeAnnotation.attrs.id in annotationState.annotations) || annotationState.annotations[maybeAnnotation.attrs.id];
|
|
27
|
+
})) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
var mediaElement = view.domAtPos(pos + 1).node;
|
|
31
|
+
return /*#__PURE__*/React.createElement(CommentBadgeComponent, {
|
|
32
|
+
view: view,
|
|
33
|
+
mediaNode: mediaNode,
|
|
34
|
+
onClick: onClick,
|
|
35
|
+
mediaElement: mediaElement,
|
|
36
|
+
intl: intl
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
export var CommentBadge = injectIntl(CommentBadgeWrapper);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { Component } from 'react';
|
|
2
|
+
import type { UnbindFn } from 'bind-event-listener';
|
|
2
3
|
import type { ContextIdentifierProvider, MediaProvider } from '@atlaskit/editor-common/provider-factory';
|
|
3
4
|
import type { ImageLoaderProps } from '@atlaskit/editor-common/utils';
|
|
4
5
|
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
@@ -28,11 +29,14 @@ interface MediaNodeState {
|
|
|
28
29
|
export declare class MediaNode extends Component<MediaNodeProps, MediaNodeState> {
|
|
29
30
|
private mediaPluginState;
|
|
30
31
|
state: MediaNodeState;
|
|
32
|
+
videoControlsWrapperRef: React.RefObject<HTMLDivElement>;
|
|
33
|
+
unbindKeyDown: UnbindFn | null;
|
|
31
34
|
constructor(props: MediaNodeProps);
|
|
32
35
|
shouldComponentUpdate(nextProps: MediaNodeProps, nextState: MediaNodeState): boolean;
|
|
33
36
|
componentDidMount(): Promise<void>;
|
|
34
37
|
componentWillUnmount(): void;
|
|
35
38
|
componentDidUpdate(prevProps: Readonly<MediaNodeProps>): void;
|
|
39
|
+
bindKeydown(): void;
|
|
36
40
|
private setViewMediaClientConfig;
|
|
37
41
|
private selectMediaSingleFromCard;
|
|
38
42
|
private selectMediaSingle;
|
|
@@ -54,6 +54,7 @@ declare class MediaSingleNodeView extends ReactNodeView<MediaSingleNodeViewProps
|
|
|
54
54
|
checkAndUpdateSelectionType: () => import("@atlaskit/editor-common/utils").SelectedState | null;
|
|
55
55
|
isNodeSelected: () => boolean;
|
|
56
56
|
getNodeMediaId(node: PMNode): string | undefined;
|
|
57
|
+
stopEvent(event: Event): boolean;
|
|
57
58
|
update(node: PMNode, decorations: readonly Decoration[], _innerDecorations?: DecorationSource, isValidUpdate?: (currentNode: PMNode, newNode: PMNode) => boolean): boolean;
|
|
58
59
|
render(props: MediaSingleNodeViewProps, forwardRef?: ForwardRef): jsx.JSX.Element;
|
|
59
60
|
ignoreMutation(): boolean;
|
|
@@ -22,6 +22,7 @@ export interface MediaPluginState {
|
|
|
22
22
|
showDropzone: boolean;
|
|
23
23
|
isFullscreen: boolean;
|
|
24
24
|
element?: HTMLElement;
|
|
25
|
+
videoControlsWrapperRef?: HTMLElement;
|
|
25
26
|
layout: MediaSingleLayout;
|
|
26
27
|
mediaNodes: MediaNodeWithPosHandler[];
|
|
27
28
|
options: MediaPluginOptions;
|
|
@@ -64,7 +65,7 @@ export interface MediaPluginState {
|
|
|
64
65
|
setResizingWidth(width: number): void;
|
|
65
66
|
setView(view: EditorView): void;
|
|
66
67
|
destroy(): void;
|
|
67
|
-
updateAndDispatch(props: Partial<Pick<this, 'allowsUploads' | 'allUploadsFinished' | 'isFullscreen'>>): void;
|
|
68
|
+
updateAndDispatch(props: Partial<Pick<this, 'allowsUploads' | 'allUploadsFinished' | 'isFullscreen' | 'videoControlsWrapperRef'>>): void;
|
|
68
69
|
clone(): MediaPluginState;
|
|
69
70
|
subscribeToUploadInProgressState(fn: (isUploading: boolean) => void): void;
|
|
70
71
|
unsubscribeFromUploadInProgressState(fn: (isUploading: boolean) => void): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { IntlShape } from 'react-intl-next';
|
|
3
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
import type { MediaNextEditorPluginType } from '../../next-plugin-type';
|
|
7
|
+
import type { getPosHandler } from '../../types';
|
|
8
|
+
type CommentBadgeProps = {
|
|
9
|
+
intl: IntlShape;
|
|
10
|
+
api: ExtractInjectionAPI<MediaNextEditorPluginType>;
|
|
11
|
+
mediaNode: PMNode | null;
|
|
12
|
+
view: EditorView;
|
|
13
|
+
getPos: getPosHandler;
|
|
14
|
+
};
|
|
15
|
+
export declare const CommentBadge: React.FC<import("react-intl-next").WithIntlProps<CommentBadgeProps>> & {
|
|
16
|
+
WrappedComponent: React.ComponentType<CommentBadgeProps>;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { Component } from 'react';
|
|
2
|
+
import type { UnbindFn } from 'bind-event-listener';
|
|
2
3
|
import type { ContextIdentifierProvider, MediaProvider } from '@atlaskit/editor-common/provider-factory';
|
|
3
4
|
import type { ImageLoaderProps } from '@atlaskit/editor-common/utils';
|
|
4
5
|
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
@@ -28,11 +29,14 @@ interface MediaNodeState {
|
|
|
28
29
|
export declare class MediaNode extends Component<MediaNodeProps, MediaNodeState> {
|
|
29
30
|
private mediaPluginState;
|
|
30
31
|
state: MediaNodeState;
|
|
32
|
+
videoControlsWrapperRef: React.RefObject<HTMLDivElement>;
|
|
33
|
+
unbindKeyDown: UnbindFn | null;
|
|
31
34
|
constructor(props: MediaNodeProps);
|
|
32
35
|
shouldComponentUpdate(nextProps: MediaNodeProps, nextState: MediaNodeState): boolean;
|
|
33
36
|
componentDidMount(): Promise<void>;
|
|
34
37
|
componentWillUnmount(): void;
|
|
35
38
|
componentDidUpdate(prevProps: Readonly<MediaNodeProps>): void;
|
|
39
|
+
bindKeydown(): void;
|
|
36
40
|
private setViewMediaClientConfig;
|
|
37
41
|
private selectMediaSingleFromCard;
|
|
38
42
|
private selectMediaSingle;
|
|
@@ -54,6 +54,7 @@ declare class MediaSingleNodeView extends ReactNodeView<MediaSingleNodeViewProps
|
|
|
54
54
|
checkAndUpdateSelectionType: () => import("@atlaskit/editor-common/utils").SelectedState | null;
|
|
55
55
|
isNodeSelected: () => boolean;
|
|
56
56
|
getNodeMediaId(node: PMNode): string | undefined;
|
|
57
|
+
stopEvent(event: Event): boolean;
|
|
57
58
|
update(node: PMNode, decorations: readonly Decoration[], _innerDecorations?: DecorationSource, isValidUpdate?: (currentNode: PMNode, newNode: PMNode) => boolean): boolean;
|
|
58
59
|
render(props: MediaSingleNodeViewProps, forwardRef?: ForwardRef): jsx.JSX.Element;
|
|
59
60
|
ignoreMutation(): boolean;
|
|
@@ -22,6 +22,7 @@ export interface MediaPluginState {
|
|
|
22
22
|
showDropzone: boolean;
|
|
23
23
|
isFullscreen: boolean;
|
|
24
24
|
element?: HTMLElement;
|
|
25
|
+
videoControlsWrapperRef?: HTMLElement;
|
|
25
26
|
layout: MediaSingleLayout;
|
|
26
27
|
mediaNodes: MediaNodeWithPosHandler[];
|
|
27
28
|
options: MediaPluginOptions;
|
|
@@ -64,7 +65,7 @@ export interface MediaPluginState {
|
|
|
64
65
|
setResizingWidth(width: number): void;
|
|
65
66
|
setView(view: EditorView): void;
|
|
66
67
|
destroy(): void;
|
|
67
|
-
updateAndDispatch(props: Partial<Pick<this, 'allowsUploads' | 'allUploadsFinished' | 'isFullscreen'>>): void;
|
|
68
|
+
updateAndDispatch(props: Partial<Pick<this, 'allowsUploads' | 'allUploadsFinished' | 'isFullscreen' | 'videoControlsWrapperRef'>>): void;
|
|
68
69
|
clone(): MediaPluginState;
|
|
69
70
|
subscribeToUploadInProgressState(fn: (isUploading: boolean) => void): void;
|
|
70
71
|
unsubscribeFromUploadInProgressState(fn: (isUploading: boolean) => void): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { IntlShape } from 'react-intl-next';
|
|
3
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
import type { MediaNextEditorPluginType } from '../../next-plugin-type';
|
|
7
|
+
import type { getPosHandler } from '../../types';
|
|
8
|
+
type CommentBadgeProps = {
|
|
9
|
+
intl: IntlShape;
|
|
10
|
+
api: ExtractInjectionAPI<MediaNextEditorPluginType>;
|
|
11
|
+
mediaNode: PMNode | null;
|
|
12
|
+
view: EditorView;
|
|
13
|
+
getPos: getPosHandler;
|
|
14
|
+
};
|
|
15
|
+
export declare const CommentBadge: React.FC<import("react-intl-next").WithIntlProps<CommentBadgeProps>> & {
|
|
16
|
+
WrappedComponent: React.ComponentType<CommentBadgeProps>;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-media",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Media plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"@atlaskit/adf-schema": "^35.8.0",
|
|
37
37
|
"@atlaskit/analytics-namespaced-context": "^6.9.0",
|
|
38
38
|
"@atlaskit/analytics-next": "^9.2.0",
|
|
39
|
-
"@atlaskit/button": "^17.
|
|
39
|
+
"@atlaskit/button": "^17.11.0",
|
|
40
40
|
"@atlaskit/editor-common": "^78.23.0",
|
|
41
41
|
"@atlaskit/editor-palette": "1.5.3",
|
|
42
42
|
"@atlaskit/editor-plugin-analytics": "^1.0.0",
|
|
43
|
-
"@atlaskit/editor-plugin-annotation": "1.5.
|
|
43
|
+
"@atlaskit/editor-plugin-annotation": "1.5.7",
|
|
44
44
|
"@atlaskit/editor-plugin-decorations": "^1.0.0",
|
|
45
45
|
"@atlaskit/editor-plugin-editor-disabled": "^1.0.0",
|
|
46
46
|
"@atlaskit/editor-plugin-editor-viewmode": "^1.0.0",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@atlaskit/media-common": "^11.1.0",
|
|
62
62
|
"@atlaskit/media-filmstrip": "^47.0.0",
|
|
63
63
|
"@atlaskit/media-picker": "^66.4.0",
|
|
64
|
-
"@atlaskit/media-ui": "^25.
|
|
64
|
+
"@atlaskit/media-ui": "^25.6.0",
|
|
65
65
|
"@atlaskit/media-viewer": "^48.4.0",
|
|
66
66
|
"@atlaskit/platform-feature-flags": "^0.2.0",
|
|
67
67
|
"@atlaskit/primitives": "^5.5.0",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"@atlaskit/tooltip": "^18.1.0",
|
|
72
72
|
"@babel/runtime": "^7.0.0",
|
|
73
73
|
"@emotion/react": "^11.7.1",
|
|
74
|
+
"bind-event-listener": "^2.1.1",
|
|
74
75
|
"classnames": "^2.2.5",
|
|
75
76
|
"lodash": "^4.17.21",
|
|
76
77
|
"memoize-one": "^6.0.0",
|
|
@@ -141,6 +142,9 @@
|
|
|
141
142
|
"platform.editor.allow-extended-panel": {
|
|
142
143
|
"type": "boolean"
|
|
143
144
|
},
|
|
145
|
+
"platform.editor.a11y_video_controls_keyboard_support_yhcxh": {
|
|
146
|
+
"type": "boolean"
|
|
147
|
+
},
|
|
144
148
|
"platform.editor.media.fix-copy-paste-excel_62g4s": {
|
|
145
149
|
"type": "boolean"
|
|
146
150
|
},
|