@atlaskit/smart-card 21.1.3 → 21.3.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/extractors/block/index.js +3 -2
- package/dist/cjs/extractors/common/actions/extractPreviewAction.js +2 -0
- package/dist/cjs/state/hooks-external/useSmartLinkActions.js +12 -2
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/BlockCard/actions/PreviewAction.js +1 -1
- package/dist/cjs/view/BlockCard/index.js +10 -0
- package/dist/cjs/view/CardWithUrl/component.js +1 -1
- package/dist/cjs/view/EmbedModal/components/size-experiment/index.js +41 -0
- package/dist/cjs/view/EmbedModal/components/size-experiment/types.js +5 -0
- package/dist/cjs/view/EmbedModal/index.js +7 -3
- package/dist/cjs/view/FlexibleCard/components/blocks/block/index.js +17 -3
- package/dist/cjs/view/FlexibleCard/components/blocks/preview-block/index.js +5 -2
- package/dist/cjs/view/FlexibleCard/components/common/atlaskit-icon/index.js +20 -8
- package/dist/cjs/view/FlexibleCard/components/common/image-icon/index.js +4 -2
- package/dist/cjs/view/FlexibleCard/components/common/loading-skeleton/index.js +1 -2
- package/dist/cjs/view/FlexibleCard/components/elements/media/index.js +5 -2
- package/dist/cjs/view/HoverCard/components/HoverCardContent.js +21 -4
- package/dist/cjs/view/HoverCard/components/SnippetOrPreview.js +74 -0
- package/dist/cjs/view/HoverCard/styled.js +11 -3
- package/dist/es2019/extractors/block/index.js +2 -1
- package/dist/es2019/extractors/common/actions/extractPreviewAction.js +2 -1
- package/dist/es2019/state/hooks-external/useSmartLinkActions.js +11 -2
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/BlockCard/actions/PreviewAction.js +1 -1
- package/dist/es2019/view/BlockCard/index.js +9 -0
- package/dist/es2019/view/CardWithUrl/component.js +1 -1
- package/dist/es2019/view/EmbedModal/components/size-experiment/index.js +28 -0
- package/dist/es2019/view/EmbedModal/components/size-experiment/types.js +1 -0
- package/dist/es2019/view/EmbedModal/index.js +5 -3
- package/dist/es2019/view/FlexibleCard/components/blocks/block/index.js +17 -7
- package/dist/es2019/view/FlexibleCard/components/blocks/preview-block/index.js +4 -1
- package/dist/es2019/view/FlexibleCard/components/common/atlaskit-icon/index.js +17 -6
- package/dist/es2019/view/FlexibleCard/components/common/image-icon/index.js +4 -2
- package/dist/es2019/view/FlexibleCard/components/common/loading-skeleton/index.js +2 -3
- package/dist/es2019/view/FlexibleCard/components/elements/media/index.js +5 -2
- package/dist/es2019/view/HoverCard/components/HoverCardContent.js +21 -6
- package/dist/es2019/view/HoverCard/components/SnippetOrPreview.js +42 -0
- package/dist/es2019/view/HoverCard/styled.js +8 -0
- package/dist/esm/extractors/block/index.js +3 -2
- package/dist/esm/extractors/common/actions/extractPreviewAction.js +2 -0
- package/dist/esm/state/hooks-external/useSmartLinkActions.js +11 -2
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/BlockCard/actions/PreviewAction.js +1 -1
- package/dist/esm/view/BlockCard/index.js +9 -0
- package/dist/esm/view/CardWithUrl/component.js +1 -1
- package/dist/esm/view/EmbedModal/components/size-experiment/index.js +28 -0
- package/dist/esm/view/EmbedModal/components/size-experiment/types.js +1 -0
- package/dist/esm/view/EmbedModal/index.js +6 -3
- package/dist/esm/view/FlexibleCard/components/blocks/block/index.js +11 -3
- package/dist/esm/view/FlexibleCard/components/blocks/preview-block/index.js +5 -2
- package/dist/esm/view/FlexibleCard/components/common/atlaskit-icon/index.js +18 -8
- package/dist/esm/view/FlexibleCard/components/common/image-icon/index.js +4 -2
- package/dist/esm/view/FlexibleCard/components/common/loading-skeleton/index.js +1 -2
- package/dist/esm/view/FlexibleCard/components/elements/media/index.js +5 -2
- package/dist/esm/view/HoverCard/components/HoverCardContent.js +21 -6
- package/dist/esm/view/HoverCard/components/SnippetOrPreview.js +53 -0
- package/dist/esm/view/HoverCard/styled.js +6 -2
- package/dist/types/extractors/block/types.d.ts +2 -0
- package/dist/types/extractors/common/actions/extractPreviewAction.d.ts +2 -1
- package/dist/types/view/BlockCard/actions/PreviewAction.d.ts +4 -2
- package/dist/types/view/Card/index.d.ts +1 -1
- package/dist/types/view/EmbedModal/components/size-experiment/index.d.ts +6 -0
- package/dist/types/view/EmbedModal/components/size-experiment/types.d.ts +4 -0
- package/dist/types/view/EmbedModal/index.d.ts +1 -1
- package/dist/types/view/EmbedModal/types.d.ts +4 -0
- package/dist/types/view/FlexibleCard/components/blocks/preview-block/types.d.ts +7 -1
- package/dist/types/view/FlexibleCard/components/blocks/types.d.ts +15 -0
- package/dist/types/view/FlexibleCard/components/common/image-icon/types.d.ts +1 -0
- package/dist/types/view/FlexibleCard/components/elements/media/types.d.ts +5 -0
- package/dist/types/view/HoverCard/components/SnippetOrPreview.d.ts +4 -0
- package/dist/types/view/HoverCard/styled.d.ts +2 -0
- package/dist/types/view/HoverCard/types.d.ts +5 -0
- package/package.json +5 -5
- package/report.api.md +23 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import uuid from 'uuid';
|
|
3
|
+
import { useFeatureFlag } from '@atlaskit/link-provider';
|
|
3
4
|
import { extractBlockProps as extractCardProps } from '../../extractors/block';
|
|
4
5
|
import { useSmartCardActions as useLinkActions } from '../actions';
|
|
5
6
|
import { useSmartLinkAnalytics as useLinkAnalytics } from '../analytics';
|
|
@@ -15,13 +16,21 @@ export function useSmartLinkActions({
|
|
|
15
16
|
const [actions, setActions] = useState([]);
|
|
16
17
|
const linkState = useLinkState(url);
|
|
17
18
|
const linkAnalytics = useLinkAnalytics(url, analyticsHandler, id);
|
|
18
|
-
const linkActions = useLinkActions(id, url, linkAnalytics);
|
|
19
|
+
const linkActions = useLinkActions(id, url, linkAnalytics); // Actions do not have access to the react tree, so we need to obtain
|
|
20
|
+
// feature flags here where we still can access SmartLinkContext context
|
|
21
|
+
// and pass the flags down to the extractor. See PreviewAction.tsx for details.
|
|
22
|
+
|
|
23
|
+
const embedModalSize = useFeatureFlag('embedModalSize');
|
|
19
24
|
useEffect(() => {
|
|
20
25
|
if (!linkState.details) {
|
|
21
26
|
return;
|
|
22
27
|
}
|
|
23
28
|
|
|
29
|
+
const featureFlags = {
|
|
30
|
+
embedModalSize
|
|
31
|
+
};
|
|
24
32
|
const cardProperties = extractCardProps(linkState.details.data, linkState.details.meta, {
|
|
33
|
+
featureFlags,
|
|
25
34
|
handleInvoke: opts => linkActions.invoke(opts, appearance),
|
|
26
35
|
handleAnalytics: analyticsHandler,
|
|
27
36
|
extensionKey: getExtensionKey(linkState.details),
|
|
@@ -38,6 +47,6 @@ export function useSmartLinkActions({
|
|
|
38
47
|
invoke: action.promise
|
|
39
48
|
}));
|
|
40
49
|
setActions(cardActions);
|
|
41
|
-
}, [linkState, linkActions, analyticsHandler, appearance, platform]);
|
|
50
|
+
}, [linkState, linkActions, analyticsHandler, appearance, platform, embedModalSize]);
|
|
42
51
|
return actions;
|
|
43
52
|
}
|
package/dist/es2019/version.json
CHANGED
|
@@ -32,7 +32,7 @@ export async function previewFunction({
|
|
|
32
32
|
document.body.appendChild(popupMountPoint);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
let Modal = await import('../../
|
|
35
|
+
let Modal = await import('../../EmbedModal');
|
|
36
36
|
ReactDOM.render( /*#__PURE__*/React.createElement(IntlProvider, {
|
|
37
37
|
locale: "en"
|
|
38
38
|
}, /*#__PURE__*/React.createElement(Modal.default, _extends({}, rest, {
|
|
@@ -14,6 +14,7 @@ import { ResolvingView as BlockCardResolvingView } from './views/ResolvingView';
|
|
|
14
14
|
import { UnauthorizedView as BlockCardUnauthorisedView } from './views/UnauthorizedView';
|
|
15
15
|
import { ForbiddenView as BlockCardForbiddenView } from './views/ForbiddenView';
|
|
16
16
|
import { ErroredView as BlockCardErroredView } from './views/ErroredView';
|
|
17
|
+
import { useFeatureFlag } from '@atlaskit/link-provider';
|
|
17
18
|
export { ForbiddenAction, AuthorizeAction, BlockCardResolvedView, BlockCardResolvingView, BlockCardUnauthorisedView, BlockCardForbiddenView, BlockCardErroredView, BlockCardNotFoundView };
|
|
18
19
|
export const BlockCard = ({
|
|
19
20
|
url,
|
|
@@ -37,9 +38,17 @@ export const BlockCard = ({
|
|
|
37
38
|
}) => {
|
|
38
39
|
var _details$meta, _forbiddenViewProps$c;
|
|
39
40
|
|
|
41
|
+
// Actions do not have access to the react tree, so we need to obtain
|
|
42
|
+
// feature flags here where we still can access SmartLinkContext context
|
|
43
|
+
// and pass the flags down to the extractor. See PreviewAction.tsx for details.
|
|
44
|
+
const embedModalSize = useFeatureFlag('embedModalSize');
|
|
45
|
+
const featureFlags = {
|
|
46
|
+
embedModalSize
|
|
47
|
+
};
|
|
40
48
|
const data = details && details.data || getEmptyJsonLd();
|
|
41
49
|
const meta = details && details.meta;
|
|
42
50
|
const extractorOpts = {
|
|
51
|
+
featureFlags,
|
|
43
52
|
handleAnalytics,
|
|
44
53
|
handleInvoke,
|
|
45
54
|
extensionKey: getExtensionKey(details)
|
|
@@ -51,7 +51,7 @@ export function CardWithUrlContent({
|
|
|
51
51
|
const showHoverPreviewFlag = useFeatureFlag('showHoverPreview');
|
|
52
52
|
|
|
53
53
|
if (showHoverPreview === undefined && showHoverPreviewFlag !== undefined) {
|
|
54
|
-
showHoverPreview = showHoverPreviewFlag;
|
|
54
|
+
showHoverPreview = Boolean(showHoverPreviewFlag);
|
|
55
55
|
} // Setup UI handlers.
|
|
56
56
|
|
|
57
57
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Modal from '../../../common/Modal';
|
|
4
|
+
import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from '../../constants';
|
|
5
|
+
|
|
6
|
+
const withSizeExperiment = Component => props => {
|
|
7
|
+
const {
|
|
8
|
+
featureFlags = {},
|
|
9
|
+
closeLabel = 'Close Preview'
|
|
10
|
+
} = props;
|
|
11
|
+
const {
|
|
12
|
+
embedModalSize
|
|
13
|
+
} = featureFlags; // Experiment
|
|
14
|
+
|
|
15
|
+
if (embedModalSize === 'large' || embedModalSize === 'small') {
|
|
16
|
+
const size = embedModalSize === 'large' ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
17
|
+
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
18
|
+
size: size
|
|
19
|
+
}));
|
|
20
|
+
} // Control
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
return /*#__PURE__*/React.createElement(Modal, _extends({}, props, {
|
|
24
|
+
closeLabel: closeLabel
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default withSizeExperiment;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,7 @@ import LinkInfo from './components/link-info';
|
|
|
4
4
|
import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from './constants';
|
|
5
5
|
import EmbedContent from './components/embed-content';
|
|
6
6
|
import withErrorBoundary from './components/error-boundary';
|
|
7
|
+
import withSizeExperiment from './components/size-experiment';
|
|
7
8
|
|
|
8
9
|
const EmbedModal = ({
|
|
9
10
|
download: downloadUrl,
|
|
@@ -16,13 +17,14 @@ const EmbedModal = ({
|
|
|
16
17
|
onViewActionClick,
|
|
17
18
|
providerName,
|
|
18
19
|
showModal,
|
|
20
|
+
size: defaultSize = MIN_MODAL_SIZE,
|
|
19
21
|
src,
|
|
20
|
-
testId = 'smart-
|
|
22
|
+
testId = 'smart-embed-preview-modal',
|
|
21
23
|
title,
|
|
22
24
|
url
|
|
23
25
|
}) => {
|
|
24
26
|
const [isOpen, setIsOpen] = useState(showModal);
|
|
25
|
-
const [size, setSize] = useState(
|
|
27
|
+
const [size, setSize] = useState(defaultSize);
|
|
26
28
|
const handleOnClose = useCallback(() => setIsOpen(false), []);
|
|
27
29
|
const handleOnSizeClick = useCallback(() => {
|
|
28
30
|
const newSize = size === MIN_MODAL_SIZE ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
@@ -54,4 +56,4 @@ const EmbedModal = ({
|
|
|
54
56
|
}))));
|
|
55
57
|
};
|
|
56
58
|
|
|
57
|
-
export default withErrorBoundary(EmbedModal);
|
|
59
|
+
export default withSizeExperiment(withErrorBoundary(EmbedModal));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
3
|
import { css, jsx } from '@emotion/core';
|
|
4
4
|
import { ElementName, SmartLinkDirection, SmartLinkSize } from '../../../../../constants';
|
|
5
5
|
import { getBaseStyles, getGapSize, highlightRemoveStyles, renderChildren } from '../utils';
|
|
@@ -37,11 +37,21 @@ const Block = ({
|
|
|
37
37
|
direction = SmartLinkDirection.Horizontal,
|
|
38
38
|
size = SmartLinkSize.Medium,
|
|
39
39
|
testId = 'smart-block',
|
|
40
|
-
overrideCss
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
overrideCss,
|
|
41
|
+
blockRef,
|
|
42
|
+
onRender,
|
|
43
|
+
onTransitionEnd
|
|
44
|
+
}) => {
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
onRender && onRender();
|
|
47
|
+
}, [onRender]);
|
|
48
|
+
return jsx("div", {
|
|
49
|
+
css: [getBlockStyles(direction, size), overrideCss],
|
|
50
|
+
"data-smart-block": true,
|
|
51
|
+
"data-testid": testId,
|
|
52
|
+
onTransitionEnd: onTransitionEnd,
|
|
53
|
+
ref: blockRef
|
|
54
|
+
}, renderChildren(children, size));
|
|
55
|
+
};
|
|
46
56
|
|
|
47
57
|
export default Block;
|
|
@@ -13,6 +13,7 @@ import { Preview } from '../../elements';
|
|
|
13
13
|
const PreviewBlock = ({
|
|
14
14
|
status = SmartLinkStatus.Fallback,
|
|
15
15
|
testId = 'smart-block-preview',
|
|
16
|
+
onError,
|
|
16
17
|
...blockProps
|
|
17
18
|
}) => {
|
|
18
19
|
if (status !== SmartLinkStatus.Resolved) {
|
|
@@ -21,7 +22,9 @@ const PreviewBlock = ({
|
|
|
21
22
|
|
|
22
23
|
return /*#__PURE__*/React.createElement(Block, _extends({}, blockProps, {
|
|
23
24
|
testId: `${testId}-resolved-view`
|
|
24
|
-
}), /*#__PURE__*/React.createElement(Preview,
|
|
25
|
+
}), /*#__PURE__*/React.createElement(Preview, {
|
|
26
|
+
onError: onError
|
|
27
|
+
}));
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
export default PreviewBlock;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Loadable from 'react-loadable';
|
|
3
3
|
import { B200, B400, N700, R400 } from '@atlaskit/theme/colors';
|
|
4
|
+
import DocumentIcon from '@atlaskit/icon-file-type/glyph/document/16';
|
|
5
|
+
import BlogIcon from '@atlaskit/icon-object/glyph/blog/16';
|
|
4
6
|
import { IconType } from '../../../../../constants';
|
|
5
7
|
import { token } from '@atlaskit/tokens'; // prettier-ignore
|
|
6
8
|
|
|
@@ -11,15 +13,9 @@ const importIconMapper = {
|
|
|
11
13
|
[IconType.Audio]: () => import(
|
|
12
14
|
/* webpackChunkName: "glyphAudio" */
|
|
13
15
|
'@atlaskit/icon-file-type/glyph/audio/16'),
|
|
14
|
-
[IconType.Blog]: () => import(
|
|
15
|
-
/* webpackChunkName: "glyphBlog" */
|
|
16
|
-
'@atlaskit/icon-object/glyph/blog/16'),
|
|
17
16
|
[IconType.Code]: () => import(
|
|
18
17
|
/* webpackChunkName: "glyphCode" */
|
|
19
18
|
'@atlaskit/icon-file-type/glyph/source-code/16'),
|
|
20
|
-
[IconType.Document]: () => import(
|
|
21
|
-
/* webpackChunkName: "glyphDocument" */
|
|
22
|
-
'@atlaskit/icon-file-type/glyph/document/16'),
|
|
23
19
|
[IconType.Executable]: () => import(
|
|
24
20
|
/* webpackChunkName: "glyphExecutable" */
|
|
25
21
|
'@atlaskit/icon-file-type/glyph/executable/16'),
|
|
@@ -214,6 +210,21 @@ const AtlaskitIcon = ({
|
|
|
214
210
|
label,
|
|
215
211
|
testId
|
|
216
212
|
}) => {
|
|
213
|
+
// Check for synchonously loaded icons first for SSR purposes
|
|
214
|
+
switch (icon) {
|
|
215
|
+
case IconType.Document:
|
|
216
|
+
return /*#__PURE__*/React.createElement(DocumentIcon, {
|
|
217
|
+
label: label || 'document',
|
|
218
|
+
testId: testId
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
case IconType.Blog:
|
|
222
|
+
return /*#__PURE__*/React.createElement(BlogIcon, {
|
|
223
|
+
label: label || 'blog',
|
|
224
|
+
testId: testId
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
217
228
|
const importFn = getIconImportFn(icon);
|
|
218
229
|
|
|
219
230
|
if (!importFn) {
|
|
@@ -7,7 +7,8 @@ import LoadingSkeleton from '../loading-skeleton';
|
|
|
7
7
|
const ImageIcon = ({
|
|
8
8
|
defaultIcon,
|
|
9
9
|
testId,
|
|
10
|
-
url
|
|
10
|
+
url,
|
|
11
|
+
onError
|
|
11
12
|
}) => jsx(ImageLoader, {
|
|
12
13
|
src: url,
|
|
13
14
|
loading: jsx(LoadingSkeleton, {
|
|
@@ -17,7 +18,8 @@ const ImageIcon = ({
|
|
|
17
18
|
src: url,
|
|
18
19
|
"data-testid": `${testId}-image`
|
|
19
20
|
}),
|
|
20
|
-
errored: defaultIcon
|
|
21
|
+
errored: defaultIcon,
|
|
22
|
+
onError: onError
|
|
21
23
|
});
|
|
22
24
|
|
|
23
25
|
export default ImageIcon;
|
|
@@ -8,10 +8,9 @@ const LoadingSkeleton = ({
|
|
|
8
8
|
width,
|
|
9
9
|
height
|
|
10
10
|
}) => {
|
|
11
|
-
const animationWidth = width ? `${width}rem` : '20px';
|
|
12
11
|
const animationNameStyles = keyframes`
|
|
13
|
-
0% { background-position:
|
|
14
|
-
100% { background-position:
|
|
12
|
+
0% { background-position: 50% 0; }
|
|
13
|
+
100% { background-position: -50% 0; }
|
|
15
14
|
`;
|
|
16
15
|
const styles = css`
|
|
17
16
|
width: ${width}rem;
|
|
@@ -59,7 +59,8 @@ const Media = ({
|
|
|
59
59
|
overrideCss,
|
|
60
60
|
testId = 'smart-element-media',
|
|
61
61
|
type,
|
|
62
|
-
url
|
|
62
|
+
url,
|
|
63
|
+
onError
|
|
63
64
|
}) => {
|
|
64
65
|
if (!type || !url) {
|
|
65
66
|
return null;
|
|
@@ -72,7 +73,9 @@ const Media = ({
|
|
|
72
73
|
"data-testid": testId
|
|
73
74
|
}, jsx(ImageIcon, {
|
|
74
75
|
testId: `${testId}-image`,
|
|
75
|
-
url: url
|
|
76
|
+
url: url,
|
|
77
|
+
onError: onError,
|
|
78
|
+
defaultIcon: null
|
|
76
79
|
}));
|
|
77
80
|
};
|
|
78
81
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
|
|
2
2
|
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
3
|
-
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
3
|
+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { ActionName, SmartLinkPosition, SmartLinkSize } from '../../../constants';
|
|
5
|
-
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
6
5
|
import { extractMetadata } from '../../../extractors/hover/extractMetadata';
|
|
7
6
|
import { useSmartCardActions } from '../../../state/actions';
|
|
8
7
|
import { getExtensionKey } from '../../../state/helpers';
|
|
9
8
|
import { isSpecialEvent } from '../../../utils';
|
|
10
9
|
import FlexibleCard from '../../FlexibleCard';
|
|
11
|
-
import { FooterBlock, MetadataBlock,
|
|
12
|
-
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss } from '../styled';
|
|
10
|
+
import { FooterBlock, MetadataBlock, SnippetBlock, TitleBlock } from '../../FlexibleCard/components/blocks';
|
|
11
|
+
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss, hiddenSnippetStyles } from '../styled';
|
|
13
12
|
import { getSimulatedMetadata, SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
14
13
|
import HoverCardLoadingView from './HoverCardLoadingView';
|
|
14
|
+
import SnippetOrPreview from './SnippetOrPreview';
|
|
15
15
|
export const getOpenAction = (url, analytics, onActionClick) => ({
|
|
16
16
|
name: ActionName.CustomAction,
|
|
17
17
|
icon: /*#__PURE__*/React.createElement(ShortcutIcon, {
|
|
@@ -79,7 +79,17 @@ const HoverCardContent = ({
|
|
|
79
79
|
subtitle
|
|
80
80
|
} = extractMetadata(getSimulatedMetadata(extensionKey, types));
|
|
81
81
|
const titleMaxLines = subtitle && subtitle.length > 0 ? 1 : 2;
|
|
82
|
-
const
|
|
82
|
+
const snippetHeight = React.useRef(0);
|
|
83
|
+
const snippetBlockRef = useRef(null);
|
|
84
|
+
const onSnippetRender = useCallback(() => {
|
|
85
|
+
var _snippetBlockRef$curr, _snippetBlockRef$curr2;
|
|
86
|
+
|
|
87
|
+
snippetHeight.current = (_snippetBlockRef$curr = (_snippetBlockRef$curr2 = snippetBlockRef.current) === null || _snippetBlockRef$curr2 === void 0 ? void 0 : _snippetBlockRef$curr2.getBoundingClientRect().height) !== null && _snippetBlockRef$curr !== void 0 ? _snippetBlockRef$curr : 0;
|
|
88
|
+
}, []);
|
|
89
|
+
const body = SnippetOrPreview({
|
|
90
|
+
data: data,
|
|
91
|
+
snippetHeight: snippetHeight.current
|
|
92
|
+
});
|
|
83
93
|
const titleBlockProps = {
|
|
84
94
|
actions: titleActions,
|
|
85
95
|
maxLines: titleMaxLines,
|
|
@@ -112,7 +122,12 @@ const HoverCardContent = ({
|
|
|
112
122
|
size: SmartLinkSize.Large,
|
|
113
123
|
overrideCss: metadataBlockCss,
|
|
114
124
|
maxLines: 1
|
|
115
|
-
}), body, /*#__PURE__*/React.createElement(
|
|
125
|
+
}), body, /*#__PURE__*/React.createElement(SnippetBlock, {
|
|
126
|
+
testId: 'hidden-snippet',
|
|
127
|
+
onRender: onSnippetRender,
|
|
128
|
+
blockRef: snippetBlockRef,
|
|
129
|
+
overrideCss: hiddenSnippetStyles
|
|
130
|
+
}), /*#__PURE__*/React.createElement(FooterBlock, {
|
|
116
131
|
actions: footerActions,
|
|
117
132
|
size: SmartLinkSize.Large,
|
|
118
133
|
overrideCss: footerBlockCss
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useCallback, useState, useRef } from 'react';
|
|
2
|
+
import { css } from '@emotion/core';
|
|
3
|
+
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
4
|
+
import { PreviewBlock, SnippetBlock } from '../../FlexibleCard/components/blocks';
|
|
5
|
+
import { getTransitionStyles } from '../styled';
|
|
6
|
+
|
|
7
|
+
const SnippetOrPreview = ({
|
|
8
|
+
data,
|
|
9
|
+
snippetHeight
|
|
10
|
+
}) => {
|
|
11
|
+
const transitionStarted = useRef(false);
|
|
12
|
+
const previewBlockRef = useRef(null);
|
|
13
|
+
const [showSnippet, setShowSnippet] = useState(false);
|
|
14
|
+
const [previewCss, setPreviewCss] = useState(); // Set Preview to a fixed height to enable transitions
|
|
15
|
+
|
|
16
|
+
const onPreviewRender = useCallback(() => {
|
|
17
|
+
var _previewBlockRef$curr;
|
|
18
|
+
|
|
19
|
+
previewBlockRef.current && setPreviewCss(css`
|
|
20
|
+
height: ${(_previewBlockRef$curr = previewBlockRef.current) === null || _previewBlockRef$curr === void 0 ? void 0 : _previewBlockRef$curr.getBoundingClientRect().height}px;
|
|
21
|
+
`);
|
|
22
|
+
}, []); // On error set Preview to Snippet height with transition
|
|
23
|
+
|
|
24
|
+
const onPreviewError = useCallback(() => {
|
|
25
|
+
if (transitionStarted.current === false) {
|
|
26
|
+
setPreviewCss(getTransitionStyles(snippetHeight));
|
|
27
|
+
transitionStarted.current = true;
|
|
28
|
+
}
|
|
29
|
+
}, [snippetHeight]);
|
|
30
|
+
const onPreviewTransitionEnd = useCallback(() => {
|
|
31
|
+
setShowSnippet(true);
|
|
32
|
+
}, []);
|
|
33
|
+
return !showSnippet && data && extractPreview(data) ? /*#__PURE__*/React.createElement(PreviewBlock, {
|
|
34
|
+
onError: onPreviewError,
|
|
35
|
+
overrideCss: previewCss,
|
|
36
|
+
onTransitionEnd: onPreviewTransitionEnd,
|
|
37
|
+
blockRef: previewBlockRef,
|
|
38
|
+
onRender: onPreviewRender
|
|
39
|
+
}) : /*#__PURE__*/React.createElement(SnippetBlock, null);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default SnippetOrPreview;
|
|
@@ -83,4 +83,12 @@ export const skeletonContainer = css`
|
|
|
83
83
|
flex-direction: column;
|
|
84
84
|
gap: 0.625rem;
|
|
85
85
|
align-items: center;
|
|
86
|
+
`;
|
|
87
|
+
export const hiddenSnippetStyles = css`
|
|
88
|
+
visibility: hidden;
|
|
89
|
+
position: absolute;
|
|
90
|
+
`;
|
|
91
|
+
export const getTransitionStyles = snippetHeight => css`
|
|
92
|
+
transition: height 300ms ease-in-out;
|
|
93
|
+
height: ${snippetHeight}px;
|
|
86
94
|
`;
|
|
@@ -37,13 +37,14 @@ var extractBlockDetails = function extractBlockDetails(jsonLd) {
|
|
|
37
37
|
|
|
38
38
|
export var extractBlockActions = function extractBlockActions(props, jsonLd, opts, platform) {
|
|
39
39
|
if (opts) {
|
|
40
|
-
var
|
|
40
|
+
var featureFlags = opts.featureFlags,
|
|
41
|
+
handleInvoke = opts.handleInvoke,
|
|
41
42
|
handleAnalytics = opts.handleAnalytics,
|
|
42
43
|
extensionKey = opts.extensionKey,
|
|
43
44
|
source = opts.source,
|
|
44
45
|
testId = opts.testId;
|
|
45
46
|
var actions = extractActions(jsonLd, handleInvoke);
|
|
46
|
-
var previewAction = extractPreviewAction(extensionKey, props, jsonLd, handleInvoke, handleAnalytics, testId, platform, source); // The previewAction should always be the last action
|
|
47
|
+
var previewAction = extractPreviewAction(extensionKey, props, jsonLd, handleInvoke, handleAnalytics, testId, platform, source, featureFlags); // The previewAction should always be the last action
|
|
47
48
|
|
|
48
49
|
if (previewAction) {
|
|
49
50
|
actions.push(previewAction);
|
|
@@ -60,6 +60,7 @@ export var extractPreviewAction = function extractPreviewAction() {
|
|
|
60
60
|
var testId = arguments.length > 5 ? arguments[5] : undefined;
|
|
61
61
|
var platform = arguments.length > 6 ? arguments[6] : undefined;
|
|
62
62
|
var source = arguments.length > 7 ? arguments[7] : undefined;
|
|
63
|
+
var featureFlags = arguments.length > 8 ? arguments[8] : undefined;
|
|
63
64
|
// Extract metadata from view props & raw JSON-LD.
|
|
64
65
|
var metadataFromJsonLd = getMetadataFromJsonLd(jsonLd, platform);
|
|
65
66
|
var metadataFromViewProps = getMetadataFromResolvedProps(viewProps);
|
|
@@ -71,6 +72,7 @@ export var extractPreviewAction = function extractPreviewAction() {
|
|
|
71
72
|
// Build action using instrumentation hooks.
|
|
72
73
|
var key = extensionKey;
|
|
73
74
|
var previewAction = PreviewAction(_objectSpread(_objectSpread({}, metadata), {}, {
|
|
75
|
+
featureFlags: featureFlags,
|
|
74
76
|
testId: testId,
|
|
75
77
|
onOpen: function onOpen() {
|
|
76
78
|
handleAnalytics(uiRenderSuccessEvent('preview', 'resolved', key));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import uuid from 'uuid';
|
|
4
|
+
import { useFeatureFlag } from '@atlaskit/link-provider';
|
|
4
5
|
import { extractBlockProps as extractCardProps } from '../../extractors/block';
|
|
5
6
|
import { useSmartCardActions as useLinkActions } from '../actions';
|
|
6
7
|
import { useSmartLinkAnalytics as useLinkAnalytics } from '../analytics';
|
|
@@ -23,13 +24,21 @@ export function useSmartLinkActions(_ref) {
|
|
|
23
24
|
|
|
24
25
|
var linkState = useLinkState(url);
|
|
25
26
|
var linkAnalytics = useLinkAnalytics(url, analyticsHandler, id);
|
|
26
|
-
var linkActions = useLinkActions(id, url, linkAnalytics);
|
|
27
|
+
var linkActions = useLinkActions(id, url, linkAnalytics); // Actions do not have access to the react tree, so we need to obtain
|
|
28
|
+
// feature flags here where we still can access SmartLinkContext context
|
|
29
|
+
// and pass the flags down to the extractor. See PreviewAction.tsx for details.
|
|
30
|
+
|
|
31
|
+
var embedModalSize = useFeatureFlag('embedModalSize');
|
|
27
32
|
useEffect(function () {
|
|
28
33
|
if (!linkState.details) {
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
var featureFlags = {
|
|
38
|
+
embedModalSize: embedModalSize
|
|
39
|
+
};
|
|
32
40
|
var cardProperties = extractCardProps(linkState.details.data, linkState.details.meta, {
|
|
41
|
+
featureFlags: featureFlags,
|
|
33
42
|
handleInvoke: function handleInvoke(opts) {
|
|
34
43
|
return linkActions.invoke(opts, appearance);
|
|
35
44
|
},
|
|
@@ -50,6 +59,6 @@ export function useSmartLinkActions(_ref) {
|
|
|
50
59
|
};
|
|
51
60
|
});
|
|
52
61
|
setActions(cardActions);
|
|
53
|
-
}, [linkState, linkActions, analyticsHandler, appearance, platform]);
|
|
62
|
+
}, [linkState, linkActions, analyticsHandler, appearance, platform, embedModalSize]);
|
|
54
63
|
return actions;
|
|
55
64
|
}
|
package/dist/esm/version.json
CHANGED
|
@@ -14,6 +14,7 @@ import { ResolvingView as BlockCardResolvingView } from './views/ResolvingView';
|
|
|
14
14
|
import { UnauthorizedView as BlockCardUnauthorisedView } from './views/UnauthorizedView';
|
|
15
15
|
import { ForbiddenView as BlockCardForbiddenView } from './views/ForbiddenView';
|
|
16
16
|
import { ErroredView as BlockCardErroredView } from './views/ErroredView';
|
|
17
|
+
import { useFeatureFlag } from '@atlaskit/link-provider';
|
|
17
18
|
export { ForbiddenAction, AuthorizeAction, BlockCardResolvedView, BlockCardResolvingView, BlockCardUnauthorisedView, BlockCardForbiddenView, BlockCardErroredView, BlockCardNotFoundView };
|
|
18
19
|
export var BlockCard = function BlockCard(_ref) {
|
|
19
20
|
var _details$meta, _forbiddenViewProps$c;
|
|
@@ -35,9 +36,17 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
35
36
|
testId = _ref.testId,
|
|
36
37
|
showActions = _ref.showActions,
|
|
37
38
|
platform = _ref.platform;
|
|
39
|
+
// Actions do not have access to the react tree, so we need to obtain
|
|
40
|
+
// feature flags here where we still can access SmartLinkContext context
|
|
41
|
+
// and pass the flags down to the extractor. See PreviewAction.tsx for details.
|
|
42
|
+
var embedModalSize = useFeatureFlag('embedModalSize');
|
|
43
|
+
var featureFlags = {
|
|
44
|
+
embedModalSize: embedModalSize
|
|
45
|
+
};
|
|
38
46
|
var data = details && details.data || getEmptyJsonLd();
|
|
39
47
|
var meta = details && details.meta;
|
|
40
48
|
var extractorOpts = {
|
|
49
|
+
featureFlags: featureFlags,
|
|
41
50
|
handleAnalytics: handleAnalytics,
|
|
42
51
|
handleInvoke: handleInvoke,
|
|
43
52
|
extensionKey: getExtensionKey(details)
|
|
@@ -53,7 +53,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
53
53
|
var showHoverPreviewFlag = useFeatureFlag('showHoverPreview');
|
|
54
54
|
|
|
55
55
|
if (showHoverPreview === undefined && showHoverPreviewFlag !== undefined) {
|
|
56
|
-
showHoverPreview = showHoverPreviewFlag;
|
|
56
|
+
showHoverPreview = Boolean(showHoverPreviewFlag);
|
|
57
57
|
} // Setup UI handlers.
|
|
58
58
|
|
|
59
59
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Modal from '../../../common/Modal';
|
|
4
|
+
import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from '../../constants';
|
|
5
|
+
|
|
6
|
+
var withSizeExperiment = function withSizeExperiment(Component) {
|
|
7
|
+
return function (props) {
|
|
8
|
+
var _props$featureFlags = props.featureFlags,
|
|
9
|
+
featureFlags = _props$featureFlags === void 0 ? {} : _props$featureFlags,
|
|
10
|
+
_props$closeLabel = props.closeLabel,
|
|
11
|
+
closeLabel = _props$closeLabel === void 0 ? 'Close Preview' : _props$closeLabel;
|
|
12
|
+
var embedModalSize = featureFlags.embedModalSize; // Experiment
|
|
13
|
+
|
|
14
|
+
if (embedModalSize === 'large' || embedModalSize === 'small') {
|
|
15
|
+
var size = embedModalSize === 'large' ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
16
|
+
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
17
|
+
size: size
|
|
18
|
+
}));
|
|
19
|
+
} // Control
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
return /*#__PURE__*/React.createElement(Modal, _extends({}, props, {
|
|
23
|
+
closeLabel: closeLabel
|
|
24
|
+
}));
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default withSizeExperiment;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,6 +5,7 @@ import LinkInfo from './components/link-info';
|
|
|
5
5
|
import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from './constants';
|
|
6
6
|
import EmbedContent from './components/embed-content';
|
|
7
7
|
import withErrorBoundary from './components/error-boundary';
|
|
8
|
+
import withSizeExperiment from './components/size-experiment';
|
|
8
9
|
|
|
9
10
|
var EmbedModal = function EmbedModal(_ref) {
|
|
10
11
|
var downloadUrl = _ref.download,
|
|
@@ -18,9 +19,11 @@ var EmbedModal = function EmbedModal(_ref) {
|
|
|
18
19
|
onViewActionClick = _ref.onViewActionClick,
|
|
19
20
|
providerName = _ref.providerName,
|
|
20
21
|
showModal = _ref.showModal,
|
|
22
|
+
_ref$size = _ref.size,
|
|
23
|
+
defaultSize = _ref$size === void 0 ? MIN_MODAL_SIZE : _ref$size,
|
|
21
24
|
src = _ref.src,
|
|
22
25
|
_ref$testId = _ref.testId,
|
|
23
|
-
testId = _ref$testId === void 0 ? 'smart-
|
|
26
|
+
testId = _ref$testId === void 0 ? 'smart-embed-preview-modal' : _ref$testId,
|
|
24
27
|
title = _ref.title,
|
|
25
28
|
url = _ref.url;
|
|
26
29
|
|
|
@@ -29,7 +32,7 @@ var EmbedModal = function EmbedModal(_ref) {
|
|
|
29
32
|
isOpen = _useState2[0],
|
|
30
33
|
setIsOpen = _useState2[1];
|
|
31
34
|
|
|
32
|
-
var _useState3 = useState(
|
|
35
|
+
var _useState3 = useState(defaultSize),
|
|
33
36
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
34
37
|
size = _useState4[0],
|
|
35
38
|
setSize = _useState4[1];
|
|
@@ -67,4 +70,4 @@ var EmbedModal = function EmbedModal(_ref) {
|
|
|
67
70
|
}))));
|
|
68
71
|
};
|
|
69
72
|
|
|
70
|
-
export default withErrorBoundary(EmbedModal);
|
|
73
|
+
export default withSizeExperiment(withErrorBoundary(EmbedModal));
|
|
@@ -3,7 +3,7 @@ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral
|
|
|
3
3
|
var _templateObject;
|
|
4
4
|
|
|
5
5
|
/** @jsx jsx */
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useEffect } from 'react';
|
|
7
7
|
import { css, jsx } from '@emotion/core';
|
|
8
8
|
import { ElementName, SmartLinkDirection, SmartLinkSize } from '../../../../../constants';
|
|
9
9
|
import { getBaseStyles, getGapSize, highlightRemoveStyles, renderChildren } from '../utils';
|
|
@@ -28,11 +28,19 @@ var Block = function Block(_ref) {
|
|
|
28
28
|
size = _ref$size === void 0 ? SmartLinkSize.Medium : _ref$size,
|
|
29
29
|
_ref$testId = _ref.testId,
|
|
30
30
|
testId = _ref$testId === void 0 ? 'smart-block' : _ref$testId,
|
|
31
|
-
overrideCss = _ref.overrideCss
|
|
31
|
+
overrideCss = _ref.overrideCss,
|
|
32
|
+
blockRef = _ref.blockRef,
|
|
33
|
+
onRender = _ref.onRender,
|
|
34
|
+
onTransitionEnd = _ref.onTransitionEnd;
|
|
35
|
+
useEffect(function () {
|
|
36
|
+
onRender && onRender();
|
|
37
|
+
}, [onRender]);
|
|
32
38
|
return jsx("div", {
|
|
33
39
|
css: [getBlockStyles(direction, size), overrideCss],
|
|
34
40
|
"data-smart-block": true,
|
|
35
|
-
"data-testid": testId
|
|
41
|
+
"data-testid": testId,
|
|
42
|
+
onTransitionEnd: onTransitionEnd,
|
|
43
|
+
ref: blockRef
|
|
36
44
|
}, renderChildren(children, size));
|
|
37
45
|
};
|
|
38
46
|
|