@atlaskit/smart-card 23.4.7 → 23.5.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/constants.js +10 -2
  3. package/dist/cjs/index.js +6 -0
  4. package/dist/cjs/state/flexible-ui-context/utils.js +16 -0
  5. package/dist/cjs/utils/flexible.js +8 -2
  6. package/dist/cjs/version.json +1 -1
  7. package/dist/cjs/view/BlockCard/components/flexible/footer/index.js +2 -2
  8. package/dist/cjs/view/BlockCard/index.js +83 -12
  9. package/dist/cjs/view/BlockCard/views/flexible/FlexibleResolvedView.js +108 -0
  10. package/dist/cjs/view/BlockCard/views/flexible/FlexibleUnauthorisedView.js +1 -1
  11. package/dist/cjs/view/CardWithUrl/component.js +4 -2
  12. package/dist/cjs/view/EmbedModal/components/link-info/index.js +2 -1
  13. package/dist/cjs/view/FlexibleCard/components/blocks/preview-block/index.js +6 -9
  14. package/dist/cjs/view/FlexibleCard/components/blocks/preview-block/resolved/index.js +109 -0
  15. package/dist/cjs/view/FlexibleCard/components/common/image-icon/index.js +4 -2
  16. package/dist/cjs/view/FlexibleCard/components/container/index.js +40 -4
  17. package/dist/cjs/view/FlexibleCard/components/elements/media/index.js +2 -0
  18. package/dist/es2019/constants.js +8 -1
  19. package/dist/es2019/index.js +1 -1
  20. package/dist/es2019/state/flexible-ui-context/utils.js +5 -0
  21. package/dist/es2019/utils/flexible.js +3 -2
  22. package/dist/es2019/version.json +1 -1
  23. package/dist/es2019/view/BlockCard/components/flexible/footer/index.js +2 -2
  24. package/dist/es2019/view/BlockCard/index.js +80 -13
  25. package/dist/es2019/view/BlockCard/views/flexible/FlexibleErroredView.js +2 -2
  26. package/dist/es2019/view/BlockCard/views/flexible/FlexibleForbiddenView.js +2 -2
  27. package/dist/es2019/view/BlockCard/views/flexible/FlexibleNotFoundView.js +2 -2
  28. package/dist/es2019/view/BlockCard/views/flexible/FlexibleResolvedView.js +81 -0
  29. package/dist/es2019/view/BlockCard/views/flexible/FlexibleUnauthorisedView.js +3 -3
  30. package/dist/es2019/view/CardWithUrl/component.js +4 -2
  31. package/dist/es2019/view/EmbedModal/components/link-info/index.js +2 -1
  32. package/dist/es2019/view/FlexibleCard/components/blocks/preview-block/index.js +6 -7
  33. package/dist/es2019/view/FlexibleCard/components/blocks/preview-block/resolved/index.js +103 -0
  34. package/dist/es2019/view/FlexibleCard/components/common/image-icon/index.js +4 -2
  35. package/dist/es2019/view/FlexibleCard/components/container/index.js +73 -21
  36. package/dist/es2019/view/FlexibleCard/components/elements/media/index.js +2 -0
  37. package/dist/esm/constants.js +8 -1
  38. package/dist/esm/index.js +1 -1
  39. package/dist/esm/state/flexible-ui-context/utils.js +7 -0
  40. package/dist/esm/utils/flexible.js +4 -1
  41. package/dist/esm/version.json +1 -1
  42. package/dist/esm/view/BlockCard/components/flexible/footer/index.js +2 -2
  43. package/dist/esm/view/BlockCard/index.js +77 -12
  44. package/dist/esm/view/BlockCard/views/flexible/FlexibleErroredView.js +2 -2
  45. package/dist/esm/view/BlockCard/views/flexible/FlexibleForbiddenView.js +2 -2
  46. package/dist/esm/view/BlockCard/views/flexible/FlexibleNotFoundView.js +2 -2
  47. package/dist/esm/view/BlockCard/views/flexible/FlexibleResolvedView.js +87 -0
  48. package/dist/esm/view/BlockCard/views/flexible/FlexibleUnauthorisedView.js +3 -3
  49. package/dist/esm/view/CardWithUrl/component.js +4 -2
  50. package/dist/esm/view/EmbedModal/components/link-info/index.js +2 -1
  51. package/dist/esm/view/FlexibleCard/components/blocks/preview-block/index.js +7 -8
  52. package/dist/esm/view/FlexibleCard/components/blocks/preview-block/resolved/index.js +86 -0
  53. package/dist/esm/view/FlexibleCard/components/common/image-icon/index.js +4 -2
  54. package/dist/esm/view/FlexibleCard/components/container/index.js +42 -6
  55. package/dist/esm/view/FlexibleCard/components/elements/media/index.js +2 -0
  56. package/dist/types/constants.d.ts +4 -0
  57. package/dist/types/index.d.ts +1 -1
  58. package/dist/types/state/flexible-ui-context/utils.d.ts +6 -0
  59. package/dist/types/utils/flexible.d.ts +1 -0
  60. package/dist/types/view/BlockCard/components/flexible/footer/index.d.ts +2 -2
  61. package/dist/types/view/BlockCard/index.d.ts +1 -0
  62. package/dist/types/view/BlockCard/types.d.ts +1 -0
  63. package/dist/types/view/BlockCard/views/flexible/FlexibleResolvedView.d.ts +9 -0
  64. package/dist/types/view/BlockCard/views/flexible/FlexibleUnauthorisedView.d.ts +1 -1
  65. package/dist/types/view/FlexibleCard/components/blocks/preview-block/index.d.ts +1 -0
  66. package/dist/types/view/FlexibleCard/components/blocks/preview-block/resolved/index.d.ts +11 -0
  67. package/dist/types/view/FlexibleCard/components/blocks/preview-block/types.d.ts +15 -0
  68. package/dist/types/view/FlexibleCard/components/common/image-icon/types.d.ts +1 -0
  69. package/dist/types/view/FlexibleCard/components/container/index.d.ts +2 -2
  70. package/dist/types/view/FlexibleCard/components/container/types.d.ts +4 -0
  71. package/dist/types/view/FlexibleCard/components/elements/media/types.d.ts +1 -0
  72. package/package.json +2 -2
  73. package/report.api.md +10 -0
  74. package/tmp/api-report-tmp.d.ts +10 -0
@@ -25,7 +25,9 @@ var _flexibleUiContext = require("../../../../state/flexible-ui-context");
25
25
 
26
26
  var _layeredLink = _interopRequireDefault(require("./layered-link"));
27
27
 
28
- var _templateObject, _templateObject2, _templateObject3;
28
+ var _utils = require("../../../../state/flexible-ui-context/utils");
29
+
30
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4;
29
31
 
30
32
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
31
33
 
@@ -69,8 +71,41 @@ var getPadding = function getPadding(size) {
69
71
 
70
72
  var clickableContainerStyles = (0, _react2.css)(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2.default)(["\n // Position any interactive elements at the top of the z-index stack.\n a,\n button,\n .has-action {\n position: relative;\n z-index: 1;\n }\n"])));
71
73
 
72
- var getContainerStyles = function getContainerStyles(size, hideBackground, hideElevation, hidePadding, clickableContainer) {
73
- return (0, _react2.css)(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n gap: ", " 0;\n flex-direction: column;\n min-width: 0;\n overflow-x: hidden;\n position: relative;\n ", "\n ", "\n ", "\n ", "\n &:hover ~ .actions-button-group {\n opacity: 1;\n }\n a:focus,\n .has-action:focus {\n outline-offset: -2px;\n }\n"])), getGap(size), hideBackground ? '' : "background-color: ".concat(_token.tokens.background, ";"), hidePadding ? '' : "padding: ".concat(getPadding(size), ";"), hideElevation ? '' : elevationStyles, clickableContainer ? clickableContainerStyles : '');
74
+ var getContainerPaddingStyles = function getContainerPaddingStyles(size, hidePadding, childrenOptions) {
75
+ var padding = hidePadding ? '0rem' : getPadding(size);
76
+ var gap = getGap(size);
77
+ var previewOnLeft = childrenOptions.previewOnLeft,
78
+ previewOnRight = childrenOptions.previewOnRight;
79
+ return (0, _react2.css)(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2.default)(["\n // Set variables for PreviewBlock to use.\n --container-padding: ", ";\n --container-gap-left: ", ";\n --container-gap-right: ", ";\n --preview-block-width: 30%;\n\n padding: ", ";\n ", "\n ", "\n "])), padding, previewOnLeft ? gap : padding, previewOnRight ? gap : padding, padding, previewOnLeft ? "padding-left: calc(var(--preview-block-width) + ".concat(gap, ");") : '', previewOnRight ? "padding-right: calc(var(--preview-block-width) + ".concat(gap, ");") : '');
80
+ };
81
+
82
+ var getChildrenOptions = function getChildrenOptions(children, context) {
83
+ var options = {};
84
+
85
+ if ((0, _utils.isFlexUiPreviewPresent)(context)) {
86
+ _react.default.Children.map(children, function (child) {
87
+ if ( /*#__PURE__*/_react.default.isValidElement(child)) {
88
+ if ((0, _flexible.isFlexibleUiPreviewBlock)(child)) {
89
+ var placement = child.props.placement;
90
+
91
+ if (placement === _constants.MediaPlacement.Left) {
92
+ options.previewOnLeft = true;
93
+ }
94
+
95
+ if (placement === _constants.MediaPlacement.Right) {
96
+ options.previewOnRight = true;
97
+ }
98
+ }
99
+ }
100
+ });
101
+ }
102
+
103
+ return options;
104
+ };
105
+
106
+ var getContainerStyles = function getContainerStyles(size, hideBackground, hideElevation, hidePadding, clickableContainer, childrenOptions) {
107
+ var paddingCss = getContainerPaddingStyles(size, hidePadding, childrenOptions);
108
+ return (0, _react2.css)(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n gap: ", " 0;\n flex-direction: column;\n min-width: 0;\n overflow-x: hidden;\n position: relative;\n ", "\n ", "\n ", "\n ", "\n &:hover ~ .actions-button-group {\n opacity: 1;\n }\n a:focus,\n .has-action:focus {\n outline-offset: -2px;\n }\n "])), getGap(size), hideBackground ? '' : "background-color: ".concat(_token.tokens.background, ";"), paddingCss, hideElevation ? '' : elevationStyles, clickableContainer ? clickableContainerStyles : '');
74
109
  };
75
110
 
76
111
  exports.getContainerStyles = getContainerStyles;
@@ -157,8 +192,9 @@ var Container = function Container(_ref3) {
157
192
  _ref3$theme = _ref3.theme,
158
193
  theme = _ref3$theme === void 0 ? _constants.SmartLinkTheme.Link : _ref3$theme;
159
194
  var context = (0, _react.useContext)(_flexibleUiContext.FlexibleUiContext);
195
+ var childrenOptions = getChildrenOptions(children, context);
160
196
  return (0, _react2.jsx)("div", {
161
- css: getContainerStyles(size, hideBackground, hideElevation, hidePadding, clickableContainer),
197
+ css: getContainerStyles(size, hideBackground, hideElevation, hidePadding, clickableContainer, childrenOptions),
162
198
  "data-smart-link-container": true,
163
199
  "data-testid": testId
164
200
  }, clickableContainer ? getLayeredLink(testId, context, children, onClick) : null, renderChildren(children, size, theme, status, retry, onClick));
@@ -42,6 +42,7 @@ var Media = function Media(_ref) {
42
42
  testId = _ref$testId === void 0 ? 'smart-element-media' : _ref$testId,
43
43
  type = _ref.type,
44
44
  url = _ref.url,
45
+ onLoad = _ref.onLoad,
45
46
  onError = _ref.onError;
46
47
 
47
48
  if (!type || !url) {
@@ -57,6 +58,7 @@ var Media = function Media(_ref) {
57
58
  testId: "".concat(testId, "-image"),
58
59
  url: url,
59
60
  onError: onError,
61
+ onLoad: onLoad,
60
62
  defaultIcon: null
61
63
  }));
62
64
  };
@@ -221,4 +221,11 @@ export let MediaType;
221
221
 
222
222
  (function (MediaType) {
223
223
  MediaType["Image"] = "image";
224
- })(MediaType || (MediaType = {}));
224
+ })(MediaType || (MediaType = {}));
225
+
226
+ export let MediaPlacement;
227
+
228
+ (function (MediaPlacement) {
229
+ MediaPlacement["Left"] = "left";
230
+ MediaPlacement["Right"] = "right";
231
+ })(MediaPlacement || (MediaPlacement = {}));
@@ -12,5 +12,5 @@ export { useSmartLinkEvents } from './view/SmartLinkEvents/useSmartLinkEvents';
12
12
  export { contentFooterClassName, metadataListClassName, blockCardResolvingViewClassName, blockCardResolvedViewClassName, blockCardForbiddenViewClassName, blockCardIconImageClassName, blockCardResolvedViewByClassName, blockCardForbiddenViewLinkClassName, blockCardContentClassName, blockCardContentHeaderClassName, blockCardContentHeaderNameClassName, blockCardNotFoundViewClassName, blockCardErroredViewClassName } from './classNames';
13
13
  export { loadingPlaceholderClassName } from './view/CardWithUrl/component-lazy/LazyFallback'; // Flexible UI
14
14
 
15
- export { ActionName, ElementName, SmartLinkDirection, SmartLinkPosition, SmartLinkSize, SmartLinkTheme } from './constants';
15
+ export { ActionName, ElementName, MediaPlacement, SmartLinkDirection, SmartLinkPosition, SmartLinkSize, SmartLinkTheme } from './constants';
16
16
  export { MetadataBlock, PreviewBlock, SnippetBlock, TitleBlock, FooterBlock } from './view/FlexibleCard/components/blocks';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns true if preview data is available in the FlexibleUiDataContext
3
+ * @param context is the FlexibleUiDataContext
4
+ */
5
+ export const isFlexUiPreviewPresent = context => Boolean(context && context.preview);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import * as Blocks from '../view/FlexibleCard/components/blocks';
3
- import { TitleBlock } from '../view/FlexibleCard/components/blocks';
3
+ import { PreviewBlock, TitleBlock } from '../view/FlexibleCard/components/blocks';
4
4
  import * as Elements from '../view/FlexibleCard/components/elements';
5
5
  export const isFlexibleUiCard = children => {
6
6
  if (children && React.Children.toArray(children).some(child => isFlexibleUiTitleBlock(child))) {
@@ -11,4 +11,5 @@ export const isFlexibleUiCard = children => {
11
11
  };
12
12
  export const isFlexibleUiBlock = node => /*#__PURE__*/React.isValidElement(node) && Object.values(Blocks).some(type => type === node.type);
13
13
  export const isFlexibleUiElement = node => /*#__PURE__*/React.isValidElement(node) && Object.values(Elements).some(type => type === node.type);
14
- export const isFlexibleUiTitleBlock = node => /*#__PURE__*/React.isValidElement(node) && node.type === TitleBlock;
14
+ export const isFlexibleUiTitleBlock = node => /*#__PURE__*/React.isValidElement(node) && node.type === TitleBlock;
15
+ export const isFlexibleUiPreviewBlock = node => /*#__PURE__*/React.isValidElement(node) && node.type === PreviewBlock;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "23.4.7",
3
+ "version": "23.5.0",
4
4
  "sideEffects": false
5
5
  }
@@ -30,7 +30,7 @@ const providerStyles = css`
30
30
  * @param props are the data required for the block, such as actions to be displayed.
31
31
  */
32
32
 
33
- const Footer = props => {
33
+ const BlockCardFooter = props => {
34
34
  const {
35
35
  actions,
36
36
  size = SmartLinkSize.Medium,
@@ -51,4 +51,4 @@ const Footer = props => {
51
51
  })) : null);
52
52
  };
53
53
 
54
- export default Footer;
54
+ export default BlockCardFooter;
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React from 'react';
2
+
3
+ /** @jsx jsx */
3
4
  import { getExtensionKey } from '../../state/helpers';
4
5
  import { extractBlockProps } from '../../extractors/block';
5
6
  import { getEmptyJsonLd, getForbiddenJsonLd } from '../../utils/jsonld';
@@ -13,14 +14,23 @@ import { ResolvingView as BlockCardResolvingView } from './views/ResolvingView';
13
14
  import { UnauthorizedView as BlockCardUnauthorisedView } from './views/UnauthorizedView';
14
15
  import { ForbiddenView as BlockCardForbiddenView } from './views/ForbiddenView';
15
16
  import { ErroredView as BlockCardErroredView } from './views/ErroredView';
17
+ import FlexibleResolvedView from './views/flexible/FlexibleResolvedView';
18
+ import FlexibleUnauthorisedView from './views/flexible/FlexibleUnauthorisedView';
19
+ import FlexibleNotFoundView from './views/flexible/FlexibleNotFoundView';
20
+ import FlexibleErroredView from './views/flexible/FlexibleErroredView';
21
+ import FlexibleForbiddenView from './views/flexible/FlexibleForbiddenView';
22
+ import { tokens } from '../../utils/token';
23
+ import { css, jsx } from '@emotion/react';
16
24
  export { default as PreviewAction } from './actions/PreviewAction';
17
25
  export { ForbiddenAction, AuthorizeAction, BlockCardResolvedView, BlockCardResolvingView, BlockCardUnauthorisedView, BlockCardForbiddenView, BlockCardErroredView, BlockCardNotFoundView };
26
+ const flexibleBlockCardElevationStyle = css`
27
+ border-radius: 1.5px;
28
+ box-shadow: ${tokens.elevation};
29
+ margin: 2px;
30
+ `;
18
31
  export const BlockCard = ({
19
32
  url,
20
- cardState: {
21
- status,
22
- details
23
- },
33
+ cardState,
24
34
  authFlow,
25
35
  handleAuthorize,
26
36
  handleErrorRetry,
@@ -33,10 +43,15 @@ export const BlockCard = ({
33
43
  testId,
34
44
  showActions,
35
45
  platform,
36
- analytics
46
+ analytics,
47
+ enableFlexibleBlockCard
37
48
  }) => {
38
49
  var _details$meta, _forbiddenViewProps$c;
39
50
 
51
+ const {
52
+ status,
53
+ details
54
+ } = cardState;
40
55
  const data = details && details.data || getEmptyJsonLd();
41
56
  const meta = details && details.meta;
42
57
  const extractorOpts = {
@@ -46,10 +61,62 @@ export const BlockCard = ({
46
61
  extensionKey: getExtensionKey(details)
47
62
  };
48
63
 
64
+ if (enableFlexibleBlockCard) {
65
+ const ui = {
66
+ hideElevation: true
67
+ };
68
+ const flexibleProps = {
69
+ cardState,
70
+ url,
71
+ testId,
72
+ onError,
73
+ renderers,
74
+ ui
75
+ };
76
+
77
+ switch (status) {
78
+ case 'pending':
79
+ case 'resolving':
80
+ case 'resolved':
81
+ return jsx("div", {
82
+ css: flexibleBlockCardElevationStyle
83
+ }, jsx(FlexibleResolvedView, flexibleProps));
84
+
85
+ case 'unauthorized':
86
+ return jsx("div", {
87
+ css: flexibleBlockCardElevationStyle
88
+ }, jsx(FlexibleUnauthorisedView, _extends({}, flexibleProps, {
89
+ onAuthorize: handleAuthorize
90
+ })));
91
+
92
+ case 'forbidden':
93
+ return jsx("div", {
94
+ css: flexibleBlockCardElevationStyle
95
+ }, jsx(FlexibleForbiddenView, _extends({}, flexibleProps, {
96
+ onAuthorize: handleAuthorize
97
+ })));
98
+
99
+ case 'not_found':
100
+ return jsx("div", {
101
+ css: flexibleBlockCardElevationStyle
102
+ }, jsx(FlexibleNotFoundView, _extends({}, flexibleProps, {
103
+ onAuthorize: handleAuthorize
104
+ })));
105
+
106
+ case 'fallback':
107
+ case 'errored':
108
+ return jsx("div", {
109
+ css: flexibleBlockCardElevationStyle
110
+ }, jsx(FlexibleErroredView, _extends({}, flexibleProps, {
111
+ onAuthorize: handleAuthorize
112
+ })));
113
+ }
114
+ }
115
+
49
116
  switch (status) {
50
117
  case 'pending':
51
118
  case 'resolving':
52
- return /*#__PURE__*/React.createElement(BlockCardResolvingView, {
119
+ return jsx(BlockCardResolvingView, {
53
120
  testId: testId,
54
121
  isSelected: isSelected
55
122
  });
@@ -64,7 +131,7 @@ export const BlockCard = ({
64
131
  });
65
132
  }
66
133
 
67
- return /*#__PURE__*/React.createElement(BlockCardResolvedView, _extends({}, resolvedViewProps, {
134
+ return jsx(BlockCardResolvedView, _extends({}, resolvedViewProps, {
68
135
  isSelected: isSelected,
69
136
  testId: testId,
70
137
  showActions: showActions,
@@ -80,7 +147,7 @@ export const BlockCard = ({
80
147
  }
81
148
 
82
149
  const unauthorizedViewProps = extractBlockProps(data, meta, extractorOpts);
83
- return /*#__PURE__*/React.createElement(BlockCardUnauthorisedView, _extends({}, unauthorizedViewProps, {
150
+ return jsx(BlockCardUnauthorisedView, _extends({}, unauthorizedViewProps, {
84
151
  isSelected: isSelected,
85
152
  testId: testId,
86
153
  showActions: showActions,
@@ -103,7 +170,7 @@ export const BlockCard = ({
103
170
  url,
104
171
  context: (_forbiddenViewProps$c = forbiddenViewProps.context) === null || _forbiddenViewProps$c === void 0 ? void 0 : _forbiddenViewProps$c.text
105
172
  });
106
- return /*#__PURE__*/React.createElement(BlockCardForbiddenView, _extends({}, forbiddenViewProps, {
173
+ return jsx(BlockCardForbiddenView, _extends({}, forbiddenViewProps, {
107
174
  isSelected: isSelected,
108
175
  showActions: showActions,
109
176
  actions: handleAuthorize ? [ForbiddenAction(handleAuthorize)] : [],
@@ -120,7 +187,7 @@ export const BlockCard = ({
120
187
  }
121
188
 
122
189
  const notFoundViewProps = extractBlockProps(data, meta, extractorOpts);
123
- return /*#__PURE__*/React.createElement(BlockCardNotFoundView, _extends({}, notFoundViewProps, {
190
+ return jsx(BlockCardNotFoundView, _extends({}, notFoundViewProps, {
124
191
  isSelected: isSelected,
125
192
  testId: testId,
126
193
  onClick: handleFrameClick
@@ -137,7 +204,7 @@ export const BlockCard = ({
137
204
  }
138
205
 
139
206
  if (authFlow && authFlow === 'disabled') {
140
- return /*#__PURE__*/React.createElement(CardLinkView, {
207
+ return jsx(CardLinkView, {
141
208
  link: url,
142
209
  isSelected: isSelected,
143
210
  onClick: handleFrameClick,
@@ -145,7 +212,7 @@ export const BlockCard = ({
145
212
  });
146
213
  }
147
214
 
148
- return /*#__PURE__*/React.createElement(BlockCardErroredView, {
215
+ return jsx(BlockCardErroredView, {
149
216
  link: url,
150
217
  isSelected: isSelected,
151
218
  onRetry: handleErrorRetry,
@@ -5,7 +5,7 @@ import { messages } from '../../../../messages';
5
5
  import { token } from '@atlaskit/tokens';
6
6
  import { R300 } from '@atlaskit/theme/colors';
7
7
  import WarningIcon from '@atlaskit/icon/glyph/warning';
8
- import Footer from '../../components/flexible/footer';
8
+ import BlockCardFooter from '../../components/flexible/footer';
9
9
  import { RetryAction } from '../../actions/flexible/RetryAction';
10
10
  import { CustomBlock } from '../../../FlexibleCard/components/blocks';
11
11
  import Text from '../../../FlexibleCard/components/elements/text';
@@ -46,7 +46,7 @@ const FlexibleErroredView = ({
46
46
  message: {
47
47
  descriptor: messages.could_not_load_link
48
48
  }
49
- })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(Footer, {
49
+ })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(BlockCardFooter, {
50
50
  actions: actions,
51
51
  status: status
52
52
  })));
@@ -6,7 +6,7 @@ import { token } from '@atlaskit/tokens';
6
6
  import { R300 } from '@atlaskit/theme/colors';
7
7
  import { messages } from '../../../../messages';
8
8
  import LockIcon from '@atlaskit/icon/glyph/lock-filled';
9
- import Footer from '../../components/flexible/footer';
9
+ import BlockCardFooter from '../../components/flexible/footer';
10
10
  import { ForbiddenAction } from '../../actions/flexible/ForbiddenAction';
11
11
  import Text from '../../../FlexibleCard/components/elements/text';
12
12
 
@@ -48,7 +48,7 @@ const FlexibleForbiddenView = ({
48
48
  message: {
49
49
  descriptor: messages.invalid_permissions_description
50
50
  }
51
- })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(Footer, {
51
+ })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(BlockCardFooter, {
52
52
  actions: actions,
53
53
  status: status
54
54
  })));
@@ -5,7 +5,7 @@ import { messages } from '../../../../messages';
5
5
  import WarningIcon from '@atlaskit/icon/glyph/warning';
6
6
  import { token } from '@atlaskit/tokens';
7
7
  import { R300 } from '@atlaskit/theme/colors';
8
- import Footer from '../../components/flexible/footer';
8
+ import BlockCardFooter from '../../components/flexible/footer';
9
9
  import Text from '../../../FlexibleCard/components/elements/text';
10
10
  import { CustomBlock } from '../../../FlexibleCard/components/blocks';
11
11
 
@@ -46,7 +46,7 @@ const FlexibleNotFoundView = ({
46
46
  descriptor: messages.not_found_description
47
47
  },
48
48
  testId: testId
49
- })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(Footer, {
49
+ })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(BlockCardFooter, {
50
50
  status: status
51
51
  })));
52
52
  };
@@ -0,0 +1,81 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import FlexibleCard from '../../../FlexibleCard';
3
+ import TitleBlock from '../../../FlexibleCard/components/blocks/title-block';
4
+ import { FooterBlock, MetadataBlock, PreviewBlock, SnippetBlock } from '../../../FlexibleCard/components/blocks';
5
+ import { ActionName, ElementName, MediaPlacement, SmartLinkPosition } from '../../../../constants';
6
+
7
+ /**
8
+ * This view represents a Block card that has an 'Resolved' status.
9
+ * @see SmartLinkStatus
10
+ * @see FlexibleCardProps
11
+ */
12
+ const FlexibleResolvedView = ({
13
+ cardState,
14
+ onClick,
15
+ onError,
16
+ testId = 'smart-block-resolved-view',
17
+ ui,
18
+ url
19
+ }) => {
20
+ const [isPreviewBlockErrored, setIsPreviewBlockErrored] = useState(false);
21
+ useEffect(() => {
22
+ setIsPreviewBlockErrored(false);
23
+ }, [url, cardState]);
24
+ return /*#__PURE__*/React.createElement(FlexibleCard, {
25
+ appearance: "block",
26
+ cardState: cardState,
27
+ onClick: onClick,
28
+ onError: onError,
29
+ testId: testId,
30
+ ui: ui,
31
+ url: url
32
+ }, /*#__PURE__*/React.createElement(TitleBlock, {
33
+ position: SmartLinkPosition.Center,
34
+ metadata: [{
35
+ name: ElementName.AuthorGroup
36
+ }, {
37
+ name: ElementName.Priority
38
+ }, {
39
+ name: ElementName.State
40
+ }],
41
+ hideRetry: true
42
+ }), /*#__PURE__*/React.createElement(MetadataBlock, {
43
+ primary: [{
44
+ name: ElementName.ModifiedBy
45
+ }, {
46
+ name: ElementName.ModifiedOn
47
+ }],
48
+ secondary: [{
49
+ name: ElementName.AttachmentCount
50
+ }, {
51
+ name: ElementName.CommentCount
52
+ }, {
53
+ name: ElementName.ReactCount
54
+ }, {
55
+ name: ElementName.SubscriberCount
56
+ }, {
57
+ name: ElementName.ViewCount
58
+ }, {
59
+ name: ElementName.VoteCount
60
+ }, {
61
+ name: ElementName.DueOn
62
+ }],
63
+ maxLines: 1
64
+ }), /*#__PURE__*/React.createElement(MetadataBlock, null), /*#__PURE__*/React.createElement(SnippetBlock, null), !isPreviewBlockErrored ? /*#__PURE__*/React.createElement(PreviewBlock, {
65
+ placement: MediaPlacement.Right,
66
+ ignoreContainerPadding: true,
67
+ onError: () => {
68
+ setIsPreviewBlockErrored(true);
69
+ }
70
+ }) : null, /*#__PURE__*/React.createElement(FooterBlock, {
71
+ actions: [{
72
+ name: ActionName.PreviewAction
73
+ }, {
74
+ name: ActionName.ViewAction
75
+ }, {
76
+ name: ActionName.DownloadAction
77
+ }]
78
+ }));
79
+ };
80
+
81
+ export default FlexibleResolvedView;
@@ -4,7 +4,7 @@ import TitleBlock from '../../../FlexibleCard/components/blocks/title-block';
4
4
  import { messages } from '../../../../messages';
5
5
  import Text from '../../../FlexibleCard/components/elements/text';
6
6
  import { AuthorizeAction } from '../../actions/flexible/AuthorizeAction';
7
- import Footer from '../../components/flexible/footer';
7
+ import BlockCardFooter from '../../components/flexible/footer';
8
8
  import { CustomBlock } from '../../../FlexibleCard/components/blocks';
9
9
 
10
10
  /**
@@ -12,7 +12,7 @@ import { CustomBlock } from '../../../FlexibleCard/components/blocks';
12
12
  * It should have a "Connect" button that will allow a user to connect their account and view the block card.
13
13
  *
14
14
  * @see SmartLinkStatus
15
- * @see UnauthorisedViewProps
15
+ * @see FlexibleCardProps
16
16
  */
17
17
  const FlexibleUnauthorisedView = ({
18
18
  cardState,
@@ -44,7 +44,7 @@ const FlexibleUnauthorisedView = ({
44
44
  context: providerName
45
45
  }
46
46
  }
47
- })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(Footer, {
47
+ })), /*#__PURE__*/React.createElement(CustomBlock, null, /*#__PURE__*/React.createElement(BlockCardFooter, {
48
48
  actions: actions,
49
49
  status: status
50
50
  })));
@@ -52,8 +52,9 @@ export function CardWithUrlContent({
52
52
 
53
53
  if (showHoverPreview === undefined && showHoverPreviewFlag !== undefined) {
54
54
  showHoverPreview = Boolean(showHoverPreviewFlag);
55
- } // Setup UI handlers.
55
+ }
56
56
 
57
+ const enableFlexibleBlockCardFlag = Boolean(useFeatureFlag('enableFlexibleBlockCard')); // Setup UI handlers.
57
58
 
58
59
  const handleClick = useCallback(event => {
59
60
  const clickUrl = getClickUrl(url, state.details);
@@ -182,7 +183,8 @@ export function CardWithUrlContent({
182
183
  onError: onError,
183
184
  testId: testId,
184
185
  showActions: showActions,
185
- platform: platform
186
+ platform: platform,
187
+ enableFlexibleBlockCard: enableFlexibleBlockCardFlag
186
188
  });
187
189
 
188
190
  case 'embed':
@@ -38,7 +38,8 @@ const LinkInfo = ({
38
38
  label: messages.download.defaultMessage
39
39
  }),
40
40
  onClick: onDownloadButtonClick,
41
- testId: `${testId}-download`
41
+ testId: `${testId}-download`,
42
+ target: "_blank"
42
43
  });
43
44
  }
44
45
  }, [downloadUrl, onDownloadButtonClick, testId]);
@@ -1,8 +1,10 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
+
3
+ /** @jsx jsx */
2
4
  import React from 'react';
5
+ import { jsx } from '@emotion/react';
3
6
  import { SmartLinkStatus } from '../../../../../constants';
4
- import Block from '../block';
5
- import { Preview } from '../../elements';
7
+ import PreviewBlockResolvedView from './resolved';
6
8
  /**
7
9
  * Represents a PreviewBlock, which typically contains media or other large format content.
8
10
  * @public
@@ -13,17 +15,14 @@ import { Preview } from '../../elements';
13
15
  const PreviewBlock = ({
14
16
  status = SmartLinkStatus.Fallback,
15
17
  testId = 'smart-block-preview',
16
- onError,
17
18
  ...blockProps
18
19
  }) => {
19
20
  if (status !== SmartLinkStatus.Resolved) {
20
21
  return null;
21
22
  }
22
23
 
23
- return /*#__PURE__*/React.createElement(Block, _extends({}, blockProps, {
24
- testId: `${testId}-resolved-view`
25
- }), /*#__PURE__*/React.createElement(Preview, {
26
- onError: onError
24
+ return jsx(PreviewBlockResolvedView, _extends({}, blockProps, {
25
+ testId: testId
27
26
  }));
28
27
  };
29
28
 
@@ -0,0 +1,103 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+
3
+ /** @jsx jsx */
4
+ import React, { useCallback, useEffect, useState } from 'react';
5
+ import { css, jsx } from '@emotion/react';
6
+ import { MediaPlacement } from '../../../../../../constants';
7
+ import Block from '../../block';
8
+ import { Preview } from '../../../elements';
9
+ /**
10
+ * Due to its placement on the left/right and ignoreContainerPadding prop
11
+ * rely on its parent container styling, css variables are declared in
12
+ * <Container /> to preset the base values for the preview block styling.
13
+ *
14
+ * `--container-padding` is the padding of the Container. This value is based
15
+ * on size and hidePadding.
16
+ * `--container-gap-left` and `--container-gap-right` are the gap or padding of
17
+ * the Container depending on whether the container has other preview blocks
18
+ * with left/right positioning.
19
+ * `--preview-block-width` is the size of the preview image in relation to
20
+ * the Container width when the placement is left/right.
21
+ * @param placement
22
+ * @param ignoreContainerPadding
23
+ */
24
+
25
+ const getPreviewBlockStyles = (placement, ignoreContainerPadding) => {
26
+ if (placement === MediaPlacement.Left || placement === MediaPlacement.Right) {
27
+ const containerPadding = ignoreContainerPadding ? '0rem' : 'var(--container-padding)';
28
+ return css`
29
+ position: absolute;
30
+ top: ${containerPadding};
31
+ bottom: ${containerPadding};
32
+ width: calc(var(--preview-block-width) - ${containerPadding});
33
+
34
+ ${placement === MediaPlacement.Left ? `left: ${containerPadding};` : ''}
35
+ ${placement === MediaPlacement.Right ? `right: ${containerPadding};` : ''}
36
+
37
+ [data-smart-element-media='image'] {
38
+ aspect-ratio: unset;
39
+ padding-top: unset;
40
+ width: 100%;
41
+ height: 100%;
42
+ object-fit: cover;
43
+ }
44
+ `;
45
+ }
46
+
47
+ if (ignoreContainerPadding) {
48
+ return css`
49
+ margin-left: calc(var(--container-gap-left) * -1);
50
+ margin-right: calc(var(--container-gap-right) * -1);
51
+ &:first-of-type {
52
+ margin-top: calc(var(--container-padding) * -1);
53
+ }
54
+ &:last-of-type {
55
+ margin-bottom: calc(var(--container-padding) * -1);
56
+ }
57
+ `;
58
+ }
59
+ };
60
+ /**
61
+ * Represents a resolved PreviewBlock, which typically contains media or other large format content.
62
+ * @public
63
+ * @param {PreviewBlock} PreviewBlock
64
+ * @see Block
65
+ */
66
+
67
+
68
+ const PreviewBlockResolvedView = ({
69
+ ignoreContainerPadding = false,
70
+ onError,
71
+ overrideCss,
72
+ placement,
73
+ testId,
74
+ ...blockProps
75
+ }) => {
76
+ const [styles, setStyles] = useState(overrideCss);
77
+ const updateStyles = useCallback(() => {
78
+ setStyles(css`
79
+ ${getPreviewBlockStyles(placement, ignoreContainerPadding)}
80
+ ${overrideCss}
81
+ `);
82
+ }, [ignoreContainerPadding, overrideCss, placement]);
83
+ useEffect(() => {
84
+ updateStyles();
85
+ }, [ignoreContainerPadding, overrideCss, placement, updateStyles]);
86
+ const handleOnLoad = useCallback(() => {
87
+ updateStyles();
88
+ }, [updateStyles]);
89
+ const handleOnError = useCallback(() => {
90
+ if (onError) {
91
+ onError();
92
+ }
93
+ }, [onError]);
94
+ return jsx(Block, _extends({}, blockProps, {
95
+ overrideCss: styles,
96
+ testId: `${testId}-resolved-view`
97
+ }), jsx(Preview, {
98
+ onError: handleOnError,
99
+ onLoad: handleOnLoad
100
+ }));
101
+ };
102
+
103
+ export default PreviewBlockResolvedView;