@atlaskit/editor-plugin-media 1.37.3 → 1.38.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 +25 -0
- package/dist/cjs/nodeviews/mediaSingle.js +3 -3
- package/dist/cjs/nodeviews/mediaSingleNext.js +2 -2
- package/dist/cjs/pm-plugins/main.js +17 -2
- package/dist/cjs/toolbar/assets/commentWithDotIcon.js +31 -1
- package/dist/cjs/ui/CaptionPlaceholder/index.js +9 -3
- package/dist/cjs/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +556 -5
- package/dist/cjs/utils/media-common.js +23 -1
- package/dist/es2019/nodeviews/mediaSingle.js +3 -3
- package/dist/es2019/nodeviews/mediaSingleNext.js +2 -2
- package/dist/es2019/pm-plugins/main.js +20 -4
- package/dist/es2019/toolbar/assets/commentWithDotIcon.js +32 -2
- package/dist/es2019/ui/CaptionPlaceholder/index.js +14 -3
- package/dist/es2019/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +546 -4
- package/dist/es2019/utils/media-common.js +22 -0
- package/dist/esm/nodeviews/mediaSingle.js +3 -3
- package/dist/esm/nodeviews/mediaSingleNext.js +2 -2
- package/dist/esm/pm-plugins/main.js +20 -4
- package/dist/esm/toolbar/assets/commentWithDotIcon.js +32 -2
- package/dist/esm/ui/CaptionPlaceholder/index.js +9 -3
- package/dist/esm/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +552 -4
- package/dist/esm/utils/media-common.js +22 -0
- package/dist/types/ui/ResizableMediaSingle/ResizableMediaSingleNext.d.ts +3 -56
- package/dist/types/utils/media-common.d.ts +1 -0
- package/dist/types-ts4.5/ui/ResizableMediaSingle/ResizableMediaSingleNext.d.ts +3 -56
- package/dist/types-ts4.5/utils/media-common.d.ts +1 -0
- package/package.json +10 -7
|
@@ -3,7 +3,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
3
3
|
* @jsxRuntime classic
|
|
4
4
|
* @jsx jsx
|
|
5
5
|
*/
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
9
9
|
import { jsx } from '@emotion/react';
|
|
@@ -16,8 +16,10 @@ import { ResizerNext } from '@atlaskit/editor-common/resizer';
|
|
|
16
16
|
import { resizerStyles, richMediaClassName } from '@atlaskit/editor-common/styles';
|
|
17
17
|
import { calcPctFromPx, handleSides, imageAlignmentMap, wrappedLayouts } from '@atlaskit/editor-common/ui';
|
|
18
18
|
import { nonWrappedLayouts, setNodeSelection } from '@atlaskit/editor-common/utils';
|
|
19
|
+
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
19
20
|
import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
20
21
|
import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorGutterPaddingDynamic } from '@atlaskit/editor-shared-styles';
|
|
22
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
21
23
|
import { MEDIA_PLUGIN_IS_RESIZING_KEY, MEDIA_PLUGIN_RESIZING_WIDTH_KEY } from '../../pm-plugins/main';
|
|
22
24
|
import { getMediaResizeAnalyticsEvent } from '../../utils/analytics';
|
|
23
25
|
import { checkMediaType } from '../../utils/check-media-type';
|
|
@@ -65,7 +67,7 @@ class ResizableMediaSingleNext extends React.Component {
|
|
|
65
67
|
return layout;
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
|
-
return this.calcUnwrappedLayout(newWidth, containerWidth, lineLength, fullWidthMode, this.isNestedNode());
|
|
70
|
+
return this.calcUnwrappedLayout(newWidth, containerWidth || 0, lineLength, fullWidthMode, this.isNestedNode());
|
|
69
71
|
});
|
|
70
72
|
_defineProperty(this, "calcUnwrappedLayout", (width, containerWidth, contentWidth, fullWidthMode, isNestedNode) => {
|
|
71
73
|
if (isNestedNode) {
|
|
@@ -375,7 +377,7 @@ class ResizableMediaSingleNext extends React.Component {
|
|
|
375
377
|
} = this.props;
|
|
376
378
|
|
|
377
379
|
// disable guidelines for nested media single node
|
|
378
|
-
return this.isNestedNode() ? [] : generateDefaultGuidelines(lineLength, containerWidth, fullWidthMode);
|
|
380
|
+
return this.isNestedNode() ? [] : generateDefaultGuidelines(lineLength, containerWidth || 0, fullWidthMode);
|
|
379
381
|
}
|
|
380
382
|
async checkVideoFile(viewMediaClientConfig) {
|
|
381
383
|
if (this.pos === null || !viewMediaClientConfig) {
|
|
@@ -460,4 +462,544 @@ class ResizableMediaSingleNext extends React.Component {
|
|
|
460
462
|
}, children, showLegacyNotification && jsx(ResizableMediaMigrationNotification, null)));
|
|
461
463
|
}
|
|
462
464
|
}
|
|
463
|
-
|
|
465
|
+
const calcPxHeight = props => {
|
|
466
|
+
const {
|
|
467
|
+
newWidth,
|
|
468
|
+
previousWidth,
|
|
469
|
+
previousHeight
|
|
470
|
+
} = props;
|
|
471
|
+
return Math.round(previousHeight / previousWidth * newWidth);
|
|
472
|
+
};
|
|
473
|
+
const calcMinWidth = ({
|
|
474
|
+
isVideoFile,
|
|
475
|
+
contentWidth
|
|
476
|
+
}) => {
|
|
477
|
+
return Math.min(contentWidth || akEditorDefaultLayoutWidth, isVideoFile ? MEDIA_SINGLE_VIDEO_MIN_PIXEL_WIDTH : MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH);
|
|
478
|
+
};
|
|
479
|
+
const calcMaxWidth = ({
|
|
480
|
+
containerWidth,
|
|
481
|
+
editorAppearance
|
|
482
|
+
}) => {
|
|
483
|
+
return calcMediaSingleMaxWidth(containerWidth, editorAppearance);
|
|
484
|
+
};
|
|
485
|
+
const setIsResizingPluginState = ({
|
|
486
|
+
isResizing,
|
|
487
|
+
nodePosition,
|
|
488
|
+
initialWidth
|
|
489
|
+
}) => (state, dispatch) => {
|
|
490
|
+
const tr = state.tr;
|
|
491
|
+
tr.setMeta(MEDIA_PLUGIN_IS_RESIZING_KEY, isResizing);
|
|
492
|
+
tr.setMeta('is-resizer-resizing', isResizing);
|
|
493
|
+
if (isResizing && typeof nodePosition === 'number') {
|
|
494
|
+
tr.setSelection(NodeSelection.create(state.doc, nodePosition));
|
|
495
|
+
}
|
|
496
|
+
if (isResizing && typeof initialWidth === 'number') {
|
|
497
|
+
tr.setMeta(MEDIA_PLUGIN_RESIZING_WIDTH_KEY, initialWidth);
|
|
498
|
+
}
|
|
499
|
+
if (dispatch) {
|
|
500
|
+
dispatch(tr);
|
|
501
|
+
}
|
|
502
|
+
return true;
|
|
503
|
+
};
|
|
504
|
+
const calcUnwrappedLayout = (width, containerWidth, contentWidth, fullWidthMode, isNestedNode) => {
|
|
505
|
+
if (isNestedNode) {
|
|
506
|
+
return 'center';
|
|
507
|
+
}
|
|
508
|
+
if (fullWidthMode) {
|
|
509
|
+
if (width < contentWidth) {
|
|
510
|
+
return 'center';
|
|
511
|
+
}
|
|
512
|
+
return 'full-width';
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// handle top-level node in fixed-width editor
|
|
516
|
+
if (width <= contentWidth) {
|
|
517
|
+
return 'center';
|
|
518
|
+
}
|
|
519
|
+
if (width < Math.min(containerWidth - akEditorGutterPaddingDynamic() * 2, akEditorFullWidthLayoutWidth)) {
|
|
520
|
+
return 'wide';
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// set full width to be containerWidth - akEditorGutterPaddingDynamic() * 2
|
|
524
|
+
// instead of containerWidth - akEditorBreakoutPadding,
|
|
525
|
+
// so that we have image aligned with text
|
|
526
|
+
return 'full-width';
|
|
527
|
+
};
|
|
528
|
+
const calcNewLayout = ({
|
|
529
|
+
layout,
|
|
530
|
+
containerWidth,
|
|
531
|
+
lineLength,
|
|
532
|
+
fullWidthMode,
|
|
533
|
+
isNestedNode
|
|
534
|
+
}) => (newWidth, stop) => {
|
|
535
|
+
const newPct = calcPctFromPx(newWidth, lineLength) * 100;
|
|
536
|
+
const wrappedLayout = wrappedLayouts.indexOf(layout) > -1;
|
|
537
|
+
if (newPct <= 100 && wrappedLayout) {
|
|
538
|
+
if (!stop || newPct !== 100) {
|
|
539
|
+
return layout;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return calcUnwrappedLayout(newWidth, containerWidth, lineLength, fullWidthMode, isNestedNode);
|
|
543
|
+
};
|
|
544
|
+
const calculateSizeState = props => (size, delta, onResizeStop = false, aspectRatio) => {
|
|
545
|
+
const calculatedWidth = Math.round(size.width + delta.width);
|
|
546
|
+
const calculatedWidthWithLayout = calcNewLayout(props)(calculatedWidth, onResizeStop);
|
|
547
|
+
return {
|
|
548
|
+
width: calculatedWidth,
|
|
549
|
+
height: calculatedWidth / aspectRatio,
|
|
550
|
+
layout: calculatedWidthWithLayout
|
|
551
|
+
};
|
|
552
|
+
};
|
|
553
|
+
const getAspectRatio = ({
|
|
554
|
+
width,
|
|
555
|
+
height
|
|
556
|
+
}) => {
|
|
557
|
+
if (width && height > 0) {
|
|
558
|
+
return width / height;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// TODO handle this case
|
|
562
|
+
return 1;
|
|
563
|
+
};
|
|
564
|
+
const updateSizeInPluginState = throttle(({
|
|
565
|
+
width,
|
|
566
|
+
view
|
|
567
|
+
}) => {
|
|
568
|
+
const {
|
|
569
|
+
state,
|
|
570
|
+
dispatch
|
|
571
|
+
} = view;
|
|
572
|
+
const tr = state.tr;
|
|
573
|
+
tr.setMeta(MEDIA_PLUGIN_RESIZING_WIDTH_KEY, width);
|
|
574
|
+
return dispatch(tr);
|
|
575
|
+
}, MEDIA_SINGLE_RESIZE_THROTTLE_TIME);
|
|
576
|
+
export const ResizableMediaSingleNextFunctional = props => {
|
|
577
|
+
const {
|
|
578
|
+
width: origWidth,
|
|
579
|
+
children,
|
|
580
|
+
containerWidth,
|
|
581
|
+
fullWidthMode,
|
|
582
|
+
layout,
|
|
583
|
+
selected,
|
|
584
|
+
showLegacyNotification,
|
|
585
|
+
className,
|
|
586
|
+
dispatchAnalyticsEvent,
|
|
587
|
+
editorAppearance,
|
|
588
|
+
getPos,
|
|
589
|
+
lineLength,
|
|
590
|
+
mediaSingleWidth,
|
|
591
|
+
height,
|
|
592
|
+
nodeType,
|
|
593
|
+
pluginInjectionApi,
|
|
594
|
+
updateSize,
|
|
595
|
+
view,
|
|
596
|
+
viewMediaClientConfig
|
|
597
|
+
} = props;
|
|
598
|
+
const initialWidth = useMemo(() => {
|
|
599
|
+
return mediaSingleWidth || DEFAULT_IMAGE_WIDTH;
|
|
600
|
+
}, [mediaSingleWidth]);
|
|
601
|
+
const [dimensions, setDimensions] = useState({
|
|
602
|
+
width: initialWidth,
|
|
603
|
+
height: calcPxHeight({
|
|
604
|
+
newWidth: initialWidth,
|
|
605
|
+
previousWidth: initialWidth,
|
|
606
|
+
previousHeight: height
|
|
607
|
+
})
|
|
608
|
+
});
|
|
609
|
+
const dimensionsRef = useRef(dimensions);
|
|
610
|
+
const lastSnappedGuidelineKeysRef = useRef([]);
|
|
611
|
+
const [snaps, setSnaps] = useState({});
|
|
612
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
613
|
+
const [isVideoFile, setIsVideoFile] = useState(true);
|
|
614
|
+
const nodePosition = useMemo(() => {
|
|
615
|
+
if (typeof getPos !== 'function') {
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
const pos = getPos();
|
|
619
|
+
if (Number.isNaN(pos) || typeof pos !== 'number') {
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
return pos;
|
|
623
|
+
}, [getPos]);
|
|
624
|
+
const isNestedNode = useMemo(() => {
|
|
625
|
+
if (nodePosition === null) {
|
|
626
|
+
return false;
|
|
627
|
+
}
|
|
628
|
+
const $pos = view.state.doc.resolve(nodePosition);
|
|
629
|
+
return !!($pos && $pos.depth !== 0);
|
|
630
|
+
}, [nodePosition, view]);
|
|
631
|
+
const maybeContainerWidth = containerWidth || origWidth;
|
|
632
|
+
const memoizedCss = useMemo(() => {
|
|
633
|
+
return wrapperStyle({
|
|
634
|
+
layout,
|
|
635
|
+
containerWidth: maybeContainerWidth,
|
|
636
|
+
fullWidthMode,
|
|
637
|
+
mediaSingleWidth: dimensions.width,
|
|
638
|
+
isNestedNode,
|
|
639
|
+
isExtendedResizeExperienceOn: true
|
|
640
|
+
});
|
|
641
|
+
}, [layout, maybeContainerWidth, fullWidthMode, dimensions.width, isNestedNode]);
|
|
642
|
+
const maxWidth = useMemo(() => {
|
|
643
|
+
if (!isResizing && isNestedNode) {
|
|
644
|
+
return undefined;
|
|
645
|
+
}
|
|
646
|
+
if (isNestedNode || fullWidthMode) {
|
|
647
|
+
return lineLength;
|
|
648
|
+
}
|
|
649
|
+
return calcMaxWidth({
|
|
650
|
+
containerWidth,
|
|
651
|
+
editorAppearance
|
|
652
|
+
});
|
|
653
|
+
}, [isNestedNode, fullWidthMode, lineLength, editorAppearance, containerWidth, isResizing]);
|
|
654
|
+
const minWidth = calcMinWidth({
|
|
655
|
+
isVideoFile,
|
|
656
|
+
contentWidth: lineLength
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
// while is not resizing, we take 100% as min-width if the container width is less than the min-width
|
|
660
|
+
const minViewWidth = isResizing ? minWidth : `min(${minWidth}px, 100%)`;
|
|
661
|
+
const resizerNextClassName = useMemo(() => {
|
|
662
|
+
// TODO: Clean up where this lives and how it gets generated
|
|
663
|
+
const classNameNext = classnames(richMediaClassName, `image-${layout}`, isResizing ? 'is-resizing' : 'not-resizing', className, {
|
|
664
|
+
'richMedia-selected': selected,
|
|
665
|
+
'rich-media-wrapped': layout === 'wrap-left' || layout === 'wrap-right'
|
|
666
|
+
});
|
|
667
|
+
return classnames(classNameNext, resizerStyles);
|
|
668
|
+
}, [className, isResizing, layout, selected]);
|
|
669
|
+
const isInsideInlineLike = useMemo(() => {
|
|
670
|
+
if (nodePosition === null) {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
const $pos = view.state.doc.resolve(nodePosition);
|
|
674
|
+
const {
|
|
675
|
+
listItem
|
|
676
|
+
} = view.state.schema.nodes;
|
|
677
|
+
return !!findParentNodeOfTypeClosestToPos($pos, [listItem]);
|
|
678
|
+
}, [nodePosition, view]);
|
|
679
|
+
const enable = useMemo(() => {
|
|
680
|
+
return handleSides.reduce((acc, side) => {
|
|
681
|
+
const oppositeSide = side === 'left' ? 'right' : 'left';
|
|
682
|
+
acc[side] = nonWrappedLayouts.concat(`wrap-${oppositeSide}`).concat(`align-${imageAlignmentMap[oppositeSide]}`).indexOf(layout) > -1;
|
|
683
|
+
if (side === 'left' && isInsideInlineLike) {
|
|
684
|
+
acc[side] = false;
|
|
685
|
+
}
|
|
686
|
+
return acc;
|
|
687
|
+
}, {});
|
|
688
|
+
}, [layout, isInsideInlineLike]);
|
|
689
|
+
const defaultGuidelines = useMemo(() => {
|
|
690
|
+
if (isNestedNode) {
|
|
691
|
+
return [];
|
|
692
|
+
}
|
|
693
|
+
return generateDefaultGuidelines(lineLength, containerWidth, fullWidthMode);
|
|
694
|
+
}, [isNestedNode, lineLength, containerWidth, fullWidthMode]);
|
|
695
|
+
const relativeGuidesRef = useRef({});
|
|
696
|
+
const guidelinesRef = useRef([]);
|
|
697
|
+
const updateGuidelines = useCallback(() => {
|
|
698
|
+
const {
|
|
699
|
+
relativeGuides,
|
|
700
|
+
dynamicGuides
|
|
701
|
+
} = generateDynamicGuidelines(view.state, lineLength, {
|
|
702
|
+
styles: {
|
|
703
|
+
lineStyle: 'dashed'
|
|
704
|
+
},
|
|
705
|
+
show: false
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
// disable guidelines for nested media single node
|
|
709
|
+
const dynamicGuidelines = isNestedNode ? [] : dynamicGuides;
|
|
710
|
+
relativeGuidesRef.current = relativeGuides;
|
|
711
|
+
guidelinesRef.current = [...defaultGuidelines, ...dynamicGuidelines];
|
|
712
|
+
}, [view, lineLength, defaultGuidelines, isNestedNode]);
|
|
713
|
+
const isGuidelineEnabled = useMemo(() => {
|
|
714
|
+
return !!(pluginInjectionApi !== null && pluginInjectionApi !== void 0 && pluginInjectionApi.guideline);
|
|
715
|
+
}, [pluginInjectionApi]);
|
|
716
|
+
const handleResizeStart = useCallback(() => {
|
|
717
|
+
setIsResizing(true);
|
|
718
|
+
setIsResizingPluginState({
|
|
719
|
+
isResizing: true,
|
|
720
|
+
nodePosition,
|
|
721
|
+
initialWidth: dimensionsRef.current.width
|
|
722
|
+
})(view.state, view.dispatch);
|
|
723
|
+
if (isGuidelineEnabled) {
|
|
724
|
+
updateGuidelines();
|
|
725
|
+
}
|
|
726
|
+
}, [view, nodePosition, updateGuidelines, isGuidelineEnabled]);
|
|
727
|
+
const getRelativeGuides = useCallback(() => {
|
|
728
|
+
var _pluginInjectionApi$g, _pluginInjectionApi$g2;
|
|
729
|
+
if (typeof nodePosition !== 'number') {
|
|
730
|
+
return [];
|
|
731
|
+
}
|
|
732
|
+
const guidelinePluginState = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$g = pluginInjectionApi.guideline) === null || _pluginInjectionApi$g === void 0 ? void 0 : (_pluginInjectionApi$g2 = _pluginInjectionApi$g.sharedState) === null || _pluginInjectionApi$g2 === void 0 ? void 0 : _pluginInjectionApi$g2.currentState();
|
|
733
|
+
const {
|
|
734
|
+
top: topOffset
|
|
735
|
+
} = (guidelinePluginState === null || guidelinePluginState === void 0 ? void 0 : guidelinePluginState.rect) || {
|
|
736
|
+
top: 0,
|
|
737
|
+
left: 0
|
|
738
|
+
};
|
|
739
|
+
const $pos = view.state.doc.resolve(nodePosition);
|
|
740
|
+
const relativeGuides = $pos && $pos.nodeAfter && dimensionsRef.current.width ? getRelativeGuidelines(relativeGuidesRef.current, {
|
|
741
|
+
node: $pos.nodeAfter,
|
|
742
|
+
pos: $pos.pos
|
|
743
|
+
}, view, lineLength, topOffset, dimensionsRef.current) : [];
|
|
744
|
+
return relativeGuides;
|
|
745
|
+
}, [pluginInjectionApi, nodePosition, view, lineLength]);
|
|
746
|
+
const updateActiveGuidelines = useCallback((width = 0, guidelines, guidelineSnapsReference) => {
|
|
747
|
+
var _pluginInjectionApi$g3, _pluginInjectionApi$g4;
|
|
748
|
+
if (!guidelineSnapsReference.snaps.x) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const {
|
|
752
|
+
gap,
|
|
753
|
+
keys: activeGuidelineKeys
|
|
754
|
+
} = findClosestSnap(width, guidelineSnapsReference.snaps.x, guidelineSnapsReference.guidelineReference, MEDIA_SINGLE_SNAP_GAP);
|
|
755
|
+
const relativeGuidelines = activeGuidelineKeys.length ? [] : getRelativeGuides();
|
|
756
|
+
lastSnappedGuidelineKeysRef.current = activeGuidelineKeys.length ? activeGuidelineKeys : relativeGuidelines.map(rg => rg.key);
|
|
757
|
+
const nextGuideLines = [...getGuidelinesWithHighlights(gap, MEDIA_SINGLE_SNAP_GAP, activeGuidelineKeys, guidelines), ...relativeGuidelines];
|
|
758
|
+
pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$g3 = pluginInjectionApi.guideline) === null || _pluginInjectionApi$g3 === void 0 ? void 0 : (_pluginInjectionApi$g4 = _pluginInjectionApi$g3.actions) === null || _pluginInjectionApi$g4 === void 0 ? void 0 : _pluginInjectionApi$g4.displayGuideline(view)({
|
|
759
|
+
guidelines: nextGuideLines
|
|
760
|
+
});
|
|
761
|
+
}, [getRelativeGuides, pluginInjectionApi, view]);
|
|
762
|
+
const aspectRatioRef = useRef(getAspectRatio({
|
|
763
|
+
width: props.width,
|
|
764
|
+
height: props.height
|
|
765
|
+
}));
|
|
766
|
+
const handleResize = useCallback((size, delta) => {
|
|
767
|
+
const {
|
|
768
|
+
width,
|
|
769
|
+
height,
|
|
770
|
+
layout: newLayout
|
|
771
|
+
} = calculateSizeState({
|
|
772
|
+
layout,
|
|
773
|
+
containerWidth,
|
|
774
|
+
lineLength,
|
|
775
|
+
fullWidthMode,
|
|
776
|
+
isNestedNode
|
|
777
|
+
})(size, delta, false, aspectRatioRef.current);
|
|
778
|
+
if (isGuidelineEnabled) {
|
|
779
|
+
const guidelineSnaps = getGuidelineSnaps(guidelinesRef.current, lineLength, layout);
|
|
780
|
+
updateActiveGuidelines(width, guidelinesRef.current, guidelineSnaps);
|
|
781
|
+
const relativeSnaps = getRelativeGuideSnaps(relativeGuidesRef.current, aspectRatioRef.current);
|
|
782
|
+
setSnaps({
|
|
783
|
+
x: [...(guidelineSnaps.snaps.x || []), ...relativeSnaps]
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
setDimensions({
|
|
787
|
+
width,
|
|
788
|
+
height
|
|
789
|
+
});
|
|
790
|
+
updateSizeInPluginState({
|
|
791
|
+
width,
|
|
792
|
+
view
|
|
793
|
+
});
|
|
794
|
+
if (newLayout !== layout) {
|
|
795
|
+
updateSize(width, newLayout);
|
|
796
|
+
}
|
|
797
|
+
}, [view, updateSize, layout, isGuidelineEnabled, containerWidth, lineLength, fullWidthMode, isNestedNode, updateActiveGuidelines]);
|
|
798
|
+
const handleResizeStop = useCallback((size, delta) => {
|
|
799
|
+
var _pluginInjectionApi$g5, _pluginInjectionApi$g6;
|
|
800
|
+
if (typeof nodePosition !== 'number') {
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
const {
|
|
804
|
+
width,
|
|
805
|
+
height,
|
|
806
|
+
layout: newLayout
|
|
807
|
+
} = calculateSizeState({
|
|
808
|
+
layout,
|
|
809
|
+
containerWidth,
|
|
810
|
+
lineLength,
|
|
811
|
+
fullWidthMode,
|
|
812
|
+
isNestedNode
|
|
813
|
+
})(size, delta, false, aspectRatioRef.current);
|
|
814
|
+
if (dispatchAnalyticsEvent) {
|
|
815
|
+
const $pos = view.state.doc.resolve(nodePosition);
|
|
816
|
+
const event = getMediaResizeAnalyticsEvent(nodeType || 'mediaSingle', {
|
|
817
|
+
width,
|
|
818
|
+
layout: newLayout,
|
|
819
|
+
widthType: 'pixel',
|
|
820
|
+
snapType: getGuidelineTypeFromKey(lastSnappedGuidelineKeysRef.current, guidelinesRef.current),
|
|
821
|
+
parentNode: $pos ? $pos.parent.type.name : undefined,
|
|
822
|
+
inputMethod: 'mouse'
|
|
823
|
+
});
|
|
824
|
+
if (event) {
|
|
825
|
+
dispatchAnalyticsEvent(event);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
setIsResizing(false);
|
|
829
|
+
setIsResizingPluginState({
|
|
830
|
+
isResizing: false
|
|
831
|
+
})(view.state, view.dispatch);
|
|
832
|
+
pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$g5 = pluginInjectionApi.guideline) === null || _pluginInjectionApi$g5 === void 0 ? void 0 : (_pluginInjectionApi$g6 = _pluginInjectionApi$g5.actions) === null || _pluginInjectionApi$g6 === void 0 ? void 0 : _pluginInjectionApi$g6.displayGuideline(view)({
|
|
833
|
+
guidelines: []
|
|
834
|
+
});
|
|
835
|
+
let newWidth = width;
|
|
836
|
+
if (newLayout === 'full-width') {
|
|
837
|
+
// When a node reaches full width in current viewport,
|
|
838
|
+
// update its width with 1800 to align with pixel entry
|
|
839
|
+
newWidth = akEditorFullWidthLayoutWidth;
|
|
840
|
+
}
|
|
841
|
+
setDimensions({
|
|
842
|
+
width: newWidth,
|
|
843
|
+
height
|
|
844
|
+
});
|
|
845
|
+
updateSize(newWidth, newLayout);
|
|
846
|
+
}, [nodeType, dispatchAnalyticsEvent, containerWidth, fullWidthMode, isNestedNode, layout, lineLength, view, nodePosition, pluginInjectionApi, updateSize]);
|
|
847
|
+
const mountedRef = React.useRef(true);
|
|
848
|
+
useLayoutEffect(() => {
|
|
849
|
+
mountedRef.current = true;
|
|
850
|
+
return () => {
|
|
851
|
+
mountedRef.current = false;
|
|
852
|
+
};
|
|
853
|
+
}, []);
|
|
854
|
+
useLayoutEffect(() => {
|
|
855
|
+
setDimensions({
|
|
856
|
+
width: initialWidth,
|
|
857
|
+
height: calcPxHeight({
|
|
858
|
+
newWidth: initialWidth,
|
|
859
|
+
previousWidth: initialWidth,
|
|
860
|
+
previousHeight: height
|
|
861
|
+
})
|
|
862
|
+
});
|
|
863
|
+
}, [initialWidth, height]);
|
|
864
|
+
useEffect(() => {
|
|
865
|
+
dimensionsRef.current = dimensions;
|
|
866
|
+
}, [dimensions]);
|
|
867
|
+
useEffect(() => {
|
|
868
|
+
if (!viewMediaClientConfig || typeof nodePosition !== 'number') {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const mediaNode = view.state.doc.nodeAt(nodePosition + 1);
|
|
872
|
+
if (!mediaNode) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
checkMediaType(mediaNode, viewMediaClientConfig).then(mediaType => {
|
|
876
|
+
if (mountedRef.current) {
|
|
877
|
+
const isVideoFile = mediaType !== 'external' && mediaType !== 'image';
|
|
878
|
+
setIsVideoFile(isVideoFile);
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
}, [view, viewMediaClientConfig, nodePosition]);
|
|
882
|
+
return jsx("div", {
|
|
883
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
884
|
+
css: memoizedCss
|
|
885
|
+
}, jsx(ResizerNext, {
|
|
886
|
+
minWidth: minViewWidth,
|
|
887
|
+
maxWidth: maxWidth
|
|
888
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
889
|
+
,
|
|
890
|
+
className: resizerNextClassName,
|
|
891
|
+
snapGap: MEDIA_SINGLE_SNAP_GAP,
|
|
892
|
+
enable: enable,
|
|
893
|
+
width: dimensions.width,
|
|
894
|
+
handleResizeStart: handleResizeStart,
|
|
895
|
+
handleResize: handleResize,
|
|
896
|
+
handleResizeStop: handleResizeStop,
|
|
897
|
+
snap: snaps,
|
|
898
|
+
resizeRatio: nonWrappedLayouts.includes(layout) ? 2 : 1,
|
|
899
|
+
"data-testid": resizerNextTestId,
|
|
900
|
+
isHandleVisible: selected,
|
|
901
|
+
handlePositioning: isNestedNode ? 'adjacent' : undefined,
|
|
902
|
+
handleHighlight: "full-height"
|
|
903
|
+
}, children, showLegacyNotification && jsx(ResizableMediaMigrationNotification, null)));
|
|
904
|
+
};
|
|
905
|
+
const ResizableMediaSingleToggle = ({
|
|
906
|
+
allowBreakoutSnapPoints,
|
|
907
|
+
children,
|
|
908
|
+
className,
|
|
909
|
+
containerWidth,
|
|
910
|
+
dataAttributes,
|
|
911
|
+
disableHandles,
|
|
912
|
+
dispatchAnalyticsEvent,
|
|
913
|
+
editorAppearance,
|
|
914
|
+
fullWidthMode,
|
|
915
|
+
getPos,
|
|
916
|
+
gridSize,
|
|
917
|
+
handleMediaSingleRef,
|
|
918
|
+
hasFallbackContainer,
|
|
919
|
+
height,
|
|
920
|
+
isInsideOfInlineExtension,
|
|
921
|
+
isLoading,
|
|
922
|
+
layout,
|
|
923
|
+
lineLength,
|
|
924
|
+
mediaSingleWidth,
|
|
925
|
+
nodeType,
|
|
926
|
+
pctWidth,
|
|
927
|
+
pluginInjectionApi,
|
|
928
|
+
selected,
|
|
929
|
+
showLegacyNotification,
|
|
930
|
+
size,
|
|
931
|
+
updateSize,
|
|
932
|
+
view,
|
|
933
|
+
viewMediaClientConfig,
|
|
934
|
+
width
|
|
935
|
+
}) => {
|
|
936
|
+
if (fg('platform_editor_react18_phase2__media_single')) {
|
|
937
|
+
return jsx(ResizableMediaSingleNextFunctional, {
|
|
938
|
+
allowBreakoutSnapPoints: allowBreakoutSnapPoints,
|
|
939
|
+
children: children
|
|
940
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
941
|
+
,
|
|
942
|
+
className: className,
|
|
943
|
+
containerWidth: containerWidth,
|
|
944
|
+
dataAttributes: dataAttributes,
|
|
945
|
+
disableHandles: disableHandles,
|
|
946
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
947
|
+
editorAppearance: editorAppearance,
|
|
948
|
+
fullWidthMode: fullWidthMode,
|
|
949
|
+
getPos: getPos,
|
|
950
|
+
gridSize: gridSize,
|
|
951
|
+
handleMediaSingleRef: handleMediaSingleRef,
|
|
952
|
+
hasFallbackContainer: hasFallbackContainer,
|
|
953
|
+
height: height,
|
|
954
|
+
isInsideOfInlineExtension: isInsideOfInlineExtension,
|
|
955
|
+
isLoading: isLoading,
|
|
956
|
+
layout: layout,
|
|
957
|
+
lineLength: lineLength,
|
|
958
|
+
mediaSingleWidth: mediaSingleWidth,
|
|
959
|
+
nodeType: nodeType,
|
|
960
|
+
pctWidth: pctWidth,
|
|
961
|
+
pluginInjectionApi: pluginInjectionApi,
|
|
962
|
+
selected: selected,
|
|
963
|
+
showLegacyNotification: showLegacyNotification,
|
|
964
|
+
size: size,
|
|
965
|
+
updateSize: updateSize,
|
|
966
|
+
view: view,
|
|
967
|
+
viewMediaClientConfig: viewMediaClientConfig,
|
|
968
|
+
width: width
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
return jsx(ResizableMediaSingleNext, {
|
|
972
|
+
allowBreakoutSnapPoints: allowBreakoutSnapPoints,
|
|
973
|
+
children: children
|
|
974
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
975
|
+
,
|
|
976
|
+
className: className,
|
|
977
|
+
containerWidth: containerWidth,
|
|
978
|
+
dataAttributes: dataAttributes,
|
|
979
|
+
disableHandles: disableHandles,
|
|
980
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
981
|
+
editorAppearance: editorAppearance,
|
|
982
|
+
fullWidthMode: fullWidthMode,
|
|
983
|
+
getPos: getPos,
|
|
984
|
+
gridSize: gridSize,
|
|
985
|
+
handleMediaSingleRef: handleMediaSingleRef,
|
|
986
|
+
hasFallbackContainer: hasFallbackContainer,
|
|
987
|
+
height: height,
|
|
988
|
+
isInsideOfInlineExtension: isInsideOfInlineExtension,
|
|
989
|
+
isLoading: isLoading,
|
|
990
|
+
layout: layout,
|
|
991
|
+
lineLength: lineLength,
|
|
992
|
+
mediaSingleWidth: mediaSingleWidth,
|
|
993
|
+
nodeType: nodeType,
|
|
994
|
+
pctWidth: pctWidth,
|
|
995
|
+
pluginInjectionApi: pluginInjectionApi,
|
|
996
|
+
selected: selected,
|
|
997
|
+
showLegacyNotification: showLegacyNotification,
|
|
998
|
+
size: size,
|
|
999
|
+
updateSize: updateSize,
|
|
1000
|
+
view: view,
|
|
1001
|
+
viewMediaClientConfig: viewMediaClientConfig,
|
|
1002
|
+
width: width
|
|
1003
|
+
});
|
|
1004
|
+
};
|
|
1005
|
+
export default ResizableMediaSingleToggle;
|
|
@@ -233,6 +233,28 @@ export const getMediaFromSupportedMediaNodesFromSelection = state => {
|
|
|
233
233
|
return null;
|
|
234
234
|
}
|
|
235
235
|
};
|
|
236
|
+
export const isNodeDoubleClickSupportedInLivePagesViewMode = (isViewMode, node) => {
|
|
237
|
+
if (!node) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
// Double Click is not supported for video nodes on both views
|
|
241
|
+
if (isVideo(node.attrs.__fileMimeType)) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Double click is supported for all editor media nodes
|
|
246
|
+
if (!isViewMode) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Double Click is not supported for mediaGroup and mediaInline nodes that are file
|
|
251
|
+
if (node.type === node.type.schema.nodes.mediaGroup || node.type === node.type.schema.nodes.mediaInline && node.attrs.type === 'file') {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Double Click supported for all other media nodes
|
|
256
|
+
return true;
|
|
257
|
+
};
|
|
236
258
|
export const getIdentifier = attrs => {
|
|
237
259
|
if (isExternalMedia(attrs)) {
|
|
238
260
|
return {
|
|
@@ -71,7 +71,7 @@ var MediaSingleNode = /*#__PURE__*/function (_Component) {
|
|
|
71
71
|
isCopying: false
|
|
72
72
|
});
|
|
73
73
|
_defineProperty(_assertThisInitialized(_this), "mediaSingleWrapperRef", /*#__PURE__*/React.createRef());
|
|
74
|
-
//
|
|
74
|
+
// platform_editor_typography_ugc clean up
|
|
75
75
|
// remove HTMLSpanElement type
|
|
76
76
|
_defineProperty(_assertThisInitialized(_this), "captionPlaceHolderRef", /*#__PURE__*/React.createRef());
|
|
77
77
|
_defineProperty(_assertThisInitialized(_this), "createOrUpdateMediaNodeUpdater", function (props) {
|
|
@@ -505,8 +505,8 @@ var MediaSingleNode = /*#__PURE__*/function (_Component) {
|
|
|
505
505
|
isDrafting: isCurrentNodeDrafting
|
|
506
506
|
}), jsx("div", {
|
|
507
507
|
ref: this.props.forwardRef
|
|
508
|
-
}), shouldShowPlaceholder && (
|
|
509
|
-
//
|
|
508
|
+
}), shouldShowPlaceholder && (fg('platform_editor_typography_ugc') ? jsx(CaptionPlaceholderButton
|
|
509
|
+
// platform_editor_typography_ugc clean up
|
|
510
510
|
// remove typecasting
|
|
511
511
|
, {
|
|
512
512
|
ref: this.captionPlaceHolderRef,
|
|
@@ -511,8 +511,8 @@ export var MediaSingleNodeNext = function MediaSingleNodeNext(mediaSingleNodeNex
|
|
|
511
511
|
isDrafting: isCurrentNodeDrafting
|
|
512
512
|
}), jsx("div", {
|
|
513
513
|
ref: forwardRef
|
|
514
|
-
}), shouldShowPlaceholder && (
|
|
515
|
-
//
|
|
514
|
+
}), shouldShowPlaceholder && (fg('platform_editor_typography_ugc') ? jsx(CaptionPlaceholderButton
|
|
515
|
+
// platform_editor_typography_ugc clean up
|
|
516
516
|
// remove typecasting
|
|
517
517
|
, {
|
|
518
518
|
ref: captionPlaceHolderRef,
|