@atlaskit/smart-card 17.2.0 → 17.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/cjs/constants.js +15 -1
  3. package/dist/cjs/extractors/flexible/index.js +2 -0
  4. package/dist/cjs/version.json +1 -1
  5. package/dist/cjs/view/FlexibleCard/components/actions/{delete-action → action}/index.js +40 -25
  6. package/dist/cjs/view/FlexibleCard/components/actions/{types.js → action/types.js} +0 -0
  7. package/dist/cjs/view/FlexibleCard/components/actions/index.js +3 -1
  8. package/dist/cjs/view/FlexibleCard/components/actions/utils.js +34 -6
  9. package/dist/cjs/view/FlexibleCard/components/blocks/action-group/index.js +1 -1
  10. package/dist/cjs/view/FlexibleCard/components/blocks/metadata-block/index.js +17 -3
  11. package/dist/cjs/view/FlexibleCard/components/blocks/utils.js +27 -7
  12. package/dist/cjs/view/FlexibleCard/components/elements/avatar-group/index.js +24 -2
  13. package/dist/cjs/view/FlexibleCard/components/elements/index.js +3 -1
  14. package/dist/cjs/view/FlexibleCard/components/elements/text/index.js +6 -2
  15. package/dist/cjs/view/FlexibleCard/components/elements/utils.js +62 -39
  16. package/dist/es2019/constants.js +14 -1
  17. package/dist/es2019/extractors/flexible/index.js +3 -1
  18. package/dist/es2019/version.json +1 -1
  19. package/dist/es2019/view/FlexibleCard/components/actions/{delete-action → action}/index.js +31 -15
  20. package/dist/es2019/view/FlexibleCard/components/actions/{types.js → action/types.js} +0 -0
  21. package/dist/es2019/view/FlexibleCard/components/actions/index.js +5 -3
  22. package/dist/es2019/view/FlexibleCard/components/actions/utils.js +27 -4
  23. package/dist/es2019/view/FlexibleCard/components/blocks/action-group/index.js +1 -1
  24. package/dist/es2019/view/FlexibleCard/components/blocks/metadata-block/index.js +17 -3
  25. package/dist/es2019/view/FlexibleCard/components/blocks/utils.js +37 -6
  26. package/dist/es2019/view/FlexibleCard/components/elements/avatar-group/index.js +28 -2
  27. package/dist/es2019/view/FlexibleCard/components/elements/index.js +1 -0
  28. package/dist/es2019/view/FlexibleCard/components/elements/text/index.js +5 -3
  29. package/dist/es2019/view/FlexibleCard/components/elements/utils.js +63 -37
  30. package/dist/esm/constants.js +14 -1
  31. package/dist/esm/extractors/flexible/index.js +3 -1
  32. package/dist/esm/version.json +1 -1
  33. package/dist/esm/view/FlexibleCard/components/actions/action/index.js +82 -0
  34. package/dist/esm/view/FlexibleCard/components/actions/{types.js → action/types.js} +0 -0
  35. package/dist/esm/view/FlexibleCard/components/actions/index.js +5 -3
  36. package/dist/esm/view/FlexibleCard/components/actions/utils.js +26 -4
  37. package/dist/esm/view/FlexibleCard/components/blocks/action-group/index.js +1 -1
  38. package/dist/esm/view/FlexibleCard/components/blocks/metadata-block/index.js +17 -3
  39. package/dist/esm/view/FlexibleCard/components/blocks/utils.js +25 -7
  40. package/dist/esm/view/FlexibleCard/components/elements/avatar-group/index.js +24 -2
  41. package/dist/esm/view/FlexibleCard/components/elements/index.js +1 -0
  42. package/dist/esm/view/FlexibleCard/components/elements/text/index.js +7 -2
  43. package/dist/esm/view/FlexibleCard/components/elements/utils.js +62 -39
  44. package/dist/types/constants.d.ts +1 -0
  45. package/dist/types/state/flexible-ui-context/types.d.ts +3 -2
  46. package/dist/types/view/FlexibleCard/components/actions/action/index.d.ts +5 -0
  47. package/dist/types/view/FlexibleCard/components/actions/action/types.d.ts +18 -0
  48. package/dist/types/view/FlexibleCard/components/actions/index.d.ts +1 -1
  49. package/dist/types/view/FlexibleCard/components/actions/utils.d.ts +2 -1
  50. package/dist/types/view/FlexibleCard/components/blocks/utils.d.ts +4 -2
  51. package/dist/types/view/FlexibleCard/components/elements/avatar-group/index.d.ts +1 -0
  52. package/dist/types/view/FlexibleCard/components/elements/avatar-group/types.d.ts +1 -2
  53. package/dist/types/view/FlexibleCard/components/elements/index.d.ts +1 -0
  54. package/dist/types/view/FlexibleCard/components/elements/text/types.d.ts +1 -0
  55. package/package.json +1 -1
  56. package/dist/esm/view/FlexibleCard/components/actions/delete-action/index.js +0 -64
  57. package/dist/types/view/FlexibleCard/components/actions/delete-action/index.d.ts +0 -5
  58. package/dist/types/view/FlexibleCard/components/actions/types.d.ts +0 -10
@@ -48,7 +48,19 @@ export let SmartLinkTheme;
48
48
  SmartLinkTheme["Link"] = "link";
49
49
  })(SmartLinkTheme || (SmartLinkTheme = {}));
50
50
 
51
- export let SmartLinkWidth;
51
+ export let SmartLinkWidth; // When adding an element...
52
+ // 1) Create base element if it doesn't already existed.
53
+ // Base element are inside src/view/FlexibleCard/components/elements.
54
+ // E.g. Badge,DateTime, Icon, Lozenge, etc.
55
+ // 2) Update FlexibleUiContext with the new prop for data representing
56
+ // the element, preferably with the same name as the element itself.
57
+ // (src/state/flexible-ui-context/types.ts)
58
+ // 3) Update Flexible UI extractor (src/extractors/flexible/index.ts)
59
+ // 4) Set base element and data mapping.
60
+ // (src/view/FlexibleCard/components/elements/utils.tsx)
61
+ // 5) Create element. (src/view/FlexibleCard/components/elements/index.ts)
62
+ // 6) Update element ElementDisplaySchema for inline/block display
63
+ // (src/view/FlexibleCard/components/blocks/utils.tsx)
52
64
 
53
65
  (function (SmartLinkWidth) {
54
66
  SmartLinkWidth["FitToContent"] = "fit-to-content";
@@ -68,6 +80,7 @@ export let ElementName;
68
80
  ElementName["ModifiedOn"] = "ModifiedOn";
69
81
  ElementName["Priority"] = "Priority";
70
82
  ElementName["ProgrammingLanguage"] = "ProgrammingLanguage";
83
+ ElementName["Snippet"] = "Snippet";
71
84
  ElementName["State"] = "State";
72
85
  ElementName["SubscriberCount"] = "SubscriberCount";
73
86
  ElementName["Title"] = "Title";
@@ -1,4 +1,4 @@
1
- import { extractLink, extractTitle } from '../common/primitives';
1
+ import { extractLink, extractSummary, extractTitle } from '../common/primitives';
2
2
  import { extractLozenge } from '../common/lozenge';
3
3
  import { extractLinkIcon } from './icon';
4
4
  import { extractCommentCount, extractCreatedBy, extractModifiedBy, extractProgrammingLanguage, extractSubscriberCount } from './utils';
@@ -26,6 +26,8 @@ const extractFlexibleUiContext = (response, renderers) => {
26
26
  modifiedOn: extractDateUpdated(data),
27
27
  priority: extractPriority(data),
28
28
  programmingLanguage: extractProgrammingLanguage(data),
29
+ snippet: extractSummary(data) || undefined,
30
+ // Explicitly set here to remove an empty string
29
31
  state: extractLozenge(data),
30
32
  subscriberCount: extractSubscriberCount(data),
31
33
  title: extractTitle(data) || url,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "17.2.0",
3
+ "version": "17.3.2",
4
4
  "sideEffects": false
5
5
  }
@@ -1,13 +1,10 @@
1
1
  /** @jsx jsx */
2
2
  import React from 'react';
3
- import { FormattedMessage } from 'react-intl-next';
4
3
  import { css, jsx } from '@emotion/core';
5
4
  import Button from '@atlaskit/button/custom-theme-button';
6
- import CrossIcon from '@atlaskit/icon/glyph/cross';
7
5
  import { SmartLinkSize } from '../../../../../constants';
8
6
  import Tooltip from '@atlaskit/tooltip';
9
7
  import { getIconSizeStyles } from '../../utils';
10
- import { messages } from '../../../../../messages';
11
8
  import { tokens } from '../../../../../utils/token';
12
9
  import { handleOnClick } from '../../../../../utils';
13
10
 
@@ -24,35 +21,54 @@ const getWidth = size => {
24
21
  }
25
22
  };
26
23
 
27
- const getStyles = size => css`
24
+ const getIconStyles = size => css`
28
25
  color: ${tokens.actionIcon};
29
26
  ${getIconSizeStyles(getWidth(size))};
30
27
  `;
31
28
 
32
- const DeleteAction = ({
29
+ const ActionIcon = ({
30
+ size,
31
+ testId,
32
+ icon
33
+ }) => jsx("span", {
34
+ css: getIconStyles(size),
35
+ "data-testid": `${testId}-icon`
36
+ }, icon);
37
+
38
+ const Action = ({
33
39
  appearance = 'subtle',
34
40
  content,
35
41
  onClick,
36
42
  size = SmartLinkSize.Medium,
37
- testId = 'smart-action-delete-action'
43
+ testId = 'smart-action',
44
+ icon,
45
+ iconPosition = 'before',
46
+ tooltipMessage
38
47
  }) => {
39
48
  if (!onClick) {
40
49
  return null;
41
50
  }
42
51
 
52
+ const iconBefore = iconPosition === 'before' ? jsx(ActionIcon, {
53
+ size: size,
54
+ testId: testId,
55
+ icon: icon
56
+ }) : undefined;
57
+ const iconAfter = iconPosition === 'after' ? jsx(ActionIcon, {
58
+ size: size,
59
+ testId: testId,
60
+ icon: icon
61
+ }) : undefined;
43
62
  return jsx(Tooltip, {
44
- content: jsx(FormattedMessage, messages.delete)
63
+ content: tooltipMessage
45
64
  }, jsx(Button, {
46
65
  spacing: "none",
47
66
  appearance: appearance,
48
67
  testId: testId,
49
- onClick: handleOnClick(onClick)
50
- }, content || jsx("span", {
51
- css: getStyles(size),
52
- "data-testid": `${testId}-icon`
53
- }, jsx(CrossIcon, {
54
- label: "Delete"
55
- }))));
68
+ onClick: handleOnClick(onClick),
69
+ iconBefore: iconBefore,
70
+ iconAfter: iconAfter
71
+ }, content));
56
72
  };
57
73
 
58
- export default DeleteAction;
74
+ export default Action;
@@ -1,6 +1,8 @@
1
1
  import { ActionName } from '../../../../constants';
2
- import { createAction } from './utils';
3
- // Attention: Keep the export name and action name the same.
2
+ import { createUIAction } from './utils'; // Attention: Keep the export name and action name the same.
4
3
  // This will help reducing the code for mapping action inside
5
4
  // createAction and renderActionItems
6
- export const DeleteAction = createAction(ActionName.DeleteAction);
5
+ // UIActions infer that you do not need to get any data from the context.
6
+ // DataActions infer that the action depends on the data from the context.
7
+
8
+ export const DeleteAction = createUIAction(ActionName.DeleteAction);
@@ -2,10 +2,20 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import { ActionName } from '../../../../constants';
3
3
  import { FlexibleUiContext } from '../../../../state/flexible-ui-context';
4
4
  import React, { useContext } from 'react';
5
- import DeleteAction from './delete-action';
5
+ import Action from './action';
6
+ import { FormattedMessage } from 'react-intl-next';
7
+ import { messages } from '../../../../messages';
8
+ import CrossIcon from '@atlaskit/icon/glyph/cross';
6
9
  const actionMappings = {
7
10
  [ActionName.DeleteAction]: {
8
- component: DeleteAction
11
+ component: Action,
12
+ props: {
13
+ testId: 'smart-action-delete-action',
14
+ icon: /*#__PURE__*/React.createElement(CrossIcon, {
15
+ label: "Delete"
16
+ }),
17
+ toolTipMessage: /*#__PURE__*/React.createElement(FormattedMessage, messages.delete)
18
+ }
9
19
  }
10
20
  };
11
21
 
@@ -23,13 +33,12 @@ const getActionData = (actionName, contextKey, context) => {
23
33
  const data = context[contextKey];
24
34
 
25
35
  switch (actionName) {
26
- case ActionName.DeleteAction:
27
36
  default:
28
37
  return data;
29
38
  }
30
39
  };
31
40
 
32
- export const createAction = name => {
41
+ export const createDataAction = name => {
33
42
  const {
34
43
  component: BaseAction,
35
44
  props
@@ -45,4 +54,18 @@ export const createAction = name => {
45
54
  const data = getActionData(name, contextKey, context);
46
55
  return /*#__PURE__*/React.createElement(BaseAction, _extends({}, props, data, overrides));
47
56
  };
57
+ };
58
+ export const createUIAction = name => {
59
+ const {
60
+ component: BaseAction,
61
+ props
62
+ } = actionMappings[name] || {};
63
+
64
+ if (!BaseAction) {
65
+ throw Error(`Action ${name} does not exist.`);
66
+ }
67
+
68
+ return overrides => {
69
+ return /*#__PURE__*/React.createElement(BaseAction, _extends({}, props, overrides));
70
+ };
48
71
  };
@@ -5,7 +5,7 @@ import { renderActionItems } from '../utils';
5
5
  import { SmartLinkSize } from '../../../../../constants';
6
6
  const styles = css`
7
7
  display: inline-flex;
8
- line-height: 0;
8
+ line-height: 1rem;
9
9
  `;
10
10
 
11
11
  const ActionGroup = ({
@@ -13,12 +13,11 @@ const getElementGroupStyles = (size, maxLines) => {
13
13
  // MetadataBlock allows metadata elements to be displayed in
14
14
  // multiple lines, with maximum of 2 lines.
15
15
  // a) We need the height of the line to be equal on both left and right
16
- // sides so they line up nicely. 1.75 is the The maximum height of
17
- // all elements in specific size. This height belongs to AvatarGroup.
16
+ // sides so they line up nicely.
18
17
  // b) There is no way to truncate non-text elements nicely. Here
19
18
  // it's fix max height of the element group so that anything that is
20
19
  // overflown will not be visible.
21
- const lineHeight = 1.75;
20
+ const lineHeight = getLineHeight(size);
22
21
  const gap = getGapSize(size);
23
22
  const gapHeight = gap * (maxLines - 1);
24
23
  const height = lineHeight * maxLines + gapHeight;
@@ -35,6 +34,21 @@ const getElementGroupStyles = (size, maxLines) => {
35
34
  `;
36
35
  };
37
36
 
37
+ const getLineHeight = size => {
38
+ // The maximum height of all elements in specific size.
39
+ // These heights belongs to AvatarGroup.
40
+ switch (size) {
41
+ case SmartLinkSize.XLarge:
42
+ case SmartLinkSize.Large:
43
+ return 1.75;
44
+
45
+ case SmartLinkSize.Medium:
46
+ case SmartLinkSize.Small:
47
+ default:
48
+ return 1.5;
49
+ }
50
+ };
51
+
38
52
  const getMaxLines = maxLines => {
39
53
  if (maxLines > MAXIMUM_MAX_LINES) {
40
54
  return DEFAULT_MAX_LINES;
@@ -1,12 +1,29 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import React from 'react';
3
3
  import { css } from '@emotion/core';
4
- import { SmartLinkDirection, SmartLinkSize } from '../../../../constants';
4
+ import { ElementName, SmartLinkDirection, SmartLinkSize } from '../../../../constants';
5
5
  import * as Elements from '../elements';
6
6
  import * as Actions from '../actions';
7
7
  import { isFlexibleUiElement } from '../../../../utils/flexible';
8
8
  import ActionGroup from './action-group';
9
- import ElementGroup from './element-group';
9
+ import ElementGroup from './element-group'; // Determine whether the element can be display as inline/block.
10
+
11
+ export const ElementDisplaySchema = {
12
+ [ElementName.AuthorGroup]: ['inline'],
13
+ [ElementName.CollaboratorGroup]: ['inline'],
14
+ [ElementName.CommentCount]: ['inline'],
15
+ [ElementName.CreatedBy]: ['inline'],
16
+ [ElementName.CreatedOn]: ['inline'],
17
+ [ElementName.LinkIcon]: ['inline'],
18
+ [ElementName.ModifiedBy]: ['inline'],
19
+ [ElementName.ModifiedOn]: ['inline'],
20
+ [ElementName.Priority]: ['inline'],
21
+ [ElementName.ProgrammingLanguage]: ['inline'],
22
+ [ElementName.Snippet]: ['block'],
23
+ [ElementName.State]: ['inline'],
24
+ [ElementName.SubscriberCount]: ['inline'],
25
+ [ElementName.Title]: ['inline']
26
+ };
10
27
 
11
28
  const getDirectionStyles = direction => {
12
29
  switch (direction) {
@@ -62,6 +79,16 @@ export const getBaseStyles = (direction, size) => css`
62
79
 
63
80
  const isActionGroup = node => /*#__PURE__*/React.isValidElement(node) && node.type === ActionGroup;
64
81
 
82
+ const isElementDisplayValid = (name, display) => {
83
+ var _ElementDisplaySchema, _ElementDisplaySchema2;
84
+
85
+ return (_ElementDisplaySchema = (_ElementDisplaySchema2 = ElementDisplaySchema[name]) === null || _ElementDisplaySchema2 === void 0 ? void 0 : _ElementDisplaySchema2.includes(display)) !== null && _ElementDisplaySchema !== void 0 ? _ElementDisplaySchema : false;
86
+ };
87
+
88
+ const isElementNull = children => {
89
+ return Boolean(children.type() === null);
90
+ };
91
+
65
92
  const isElementOrElementGroup = node => /*#__PURE__*/React.isValidElement(node) && (isFlexibleUiElement(node) || node.type === ElementGroup);
66
93
 
67
94
  export const renderChildren = (children, size) => React.Children.map(children, child => {
@@ -77,7 +104,7 @@ export const renderChildren = (children, size) => React.Children.map(children, c
77
104
 
78
105
  return child;
79
106
  });
80
- export const renderElementItems = (items = []) => {
107
+ export const renderElementItems = (items = [], display = 'inline') => {
81
108
  const elements = items.reduce((acc, curr, idx) => {
82
109
  const {
83
110
  name,
@@ -85,10 +112,14 @@ export const renderElementItems = (items = []) => {
85
112
  } = curr;
86
113
  const Element = Elements[name];
87
114
 
88
- if (Element) {
89
- return [...acc, /*#__PURE__*/React.createElement(Element, _extends({
115
+ if (Element && isElementDisplayValid(name, display)) {
116
+ const element = /*#__PURE__*/React.createElement(Element, _extends({
90
117
  key: idx
91
- }, props))];
118
+ }, props));
119
+
120
+ if (!isElementNull(element)) {
121
+ return [...acc, element];
122
+ }
92
123
  }
93
124
 
94
125
  return acc;
@@ -1,8 +1,32 @@
1
+ /** @jsx jsx */
1
2
  import React from 'react';
3
+ import { css, jsx } from '@emotion/core';
2
4
  import AtlaskitAvatarGroup from '@atlaskit/avatar-group';
3
5
  import { SmartLinkSize } from '../../../../../constants';
4
6
  const MAX_COUNT = 4;
5
7
 
8
+ const getStyles = size => {
9
+ switch (size) {
10
+ case SmartLinkSize.XLarge:
11
+ case SmartLinkSize.Large:
12
+ // Default AK small size
13
+ return;
14
+
15
+ case SmartLinkSize.Medium:
16
+ case SmartLinkSize.Small:
17
+ default:
18
+ return css`
19
+ li {
20
+ span,
21
+ svg {
22
+ max-height: 1.25rem;
23
+ max-width: 1.25rem;
24
+ }
25
+ }
26
+ `;
27
+ }
28
+ };
29
+
6
30
  const AvatarGroup = ({
7
31
  items = [],
8
32
  maxCount = MAX_COUNT,
@@ -13,13 +37,15 @@ const AvatarGroup = ({
13
37
  return null;
14
38
  }
15
39
 
16
- return /*#__PURE__*/React.createElement(AtlaskitAvatarGroup, {
40
+ return jsx("span", {
41
+ css: getStyles(size)
42
+ }, jsx(AtlaskitAvatarGroup, {
17
43
  maxCount: maxCount,
18
44
  appearance: "stack",
19
45
  size: "small",
20
46
  data: items,
21
47
  testId: testId
22
- });
48
+ }));
23
49
  };
24
50
 
25
51
  export default AvatarGroup;
@@ -13,6 +13,7 @@ export const ModifiedBy = createElement(ElementName.ModifiedBy);
13
13
  export const ModifiedOn = createElement(ElementName.ModifiedOn);
14
14
  export const Priority = createElement(ElementName.Priority);
15
15
  export const ProgrammingLanguage = createElement(ElementName.ProgrammingLanguage);
16
+ export const Snippet = createElement(ElementName.Snippet);
16
17
  export const State = createElement(ElementName.State);
17
18
  export const SubscriberCount = createElement(ElementName.SubscriberCount);
18
19
  export const Title = createElement(ElementName.Title);
@@ -3,15 +3,17 @@ import React from 'react';
3
3
  import { css, jsx } from '@emotion/core';
4
4
  import { getFormattedMessage, getTruncateStyles } from '../../utils';
5
5
  import { tokens } from '../../../../../utils/token';
6
- const styles = css`
6
+
7
+ const getStyles = maxLines => css`
7
8
  color: ${tokens.text};
8
9
  font-size: 0.75rem;
9
10
  line-height: 1rem;
10
- ${getTruncateStyles(1)}
11
+ ${getTruncateStyles(maxLines)}
11
12
  `;
12
13
 
13
14
  const Text = ({
14
15
  content,
16
+ maxLines = 1,
15
17
  message,
16
18
  testId = 'smart-element-text'
17
19
  }) => {
@@ -20,7 +22,7 @@ const Text = ({
20
22
  }
21
23
 
22
24
  return jsx("span", {
23
- css: styles,
25
+ css: getStyles(maxLines),
24
26
  "data-smart-element-text": true,
25
27
  "data-testid": testId
26
28
  }, getFormattedMessage(message) || content);
@@ -41,6 +41,12 @@ const elementMappings = {
41
41
  icon: IconType.ProgrammingLanguage
42
42
  }
43
43
  },
44
+ [ElementName.Snippet]: {
45
+ component: Text,
46
+ props: {
47
+ maxLines: 3
48
+ }
49
+ },
44
50
  [ElementName.State]: {
45
51
  component: Lozenge
46
52
  },
@@ -67,15 +73,6 @@ const getContextKey = name => {
67
73
  return name.length > 0 ? name.charAt(0).toLowerCase() + name.slice(1) : undefined;
68
74
  };
69
75
 
70
- const getFormattedMessage = (descriptor, value) => value ? {
71
- message: {
72
- descriptor,
73
- values: {
74
- context: value
75
- }
76
- }
77
- } : undefined;
78
-
79
76
  const getData = (elementName, contextKey, context) => {
80
77
  if (!context) {
81
78
  return undefined;
@@ -84,52 +81,81 @@ const getData = (elementName, contextKey, context) => {
84
81
  const data = context[contextKey];
85
82
 
86
83
  switch (elementName) {
84
+ case ElementName.AuthorGroup:
85
+ case ElementName.CollaboratorGroup:
86
+ return toAvatarGroupProps(data);
87
+
87
88
  case ElementName.CommentCount:
88
89
  case ElementName.ProgrammingLanguage:
89
90
  case ElementName.SubscriberCount:
90
- return {
91
- label: data
92
- };
93
-
94
- case ElementName.AuthorGroup:
95
- return {
96
- items: context.authorGroup
97
- };
98
-
99
- case ElementName.CollaboratorGroup:
100
- return {
101
- items: context.collaboratorGroup
102
- };
91
+ return toBadgeProps(data);
103
92
 
104
93
  case ElementName.CreatedBy:
105
- return getFormattedMessage(messages.created_by, context.createdBy);
94
+ return toFormattedTextProps(messages.created_by, context.createdBy);
95
+
96
+ case ElementName.CreatedOn:
97
+ return toDateTimeProps('created', context.createdOn);
106
98
 
107
99
  case ElementName.ModifiedBy:
108
- return getFormattedMessage(messages.modified_by, context.modifiedBy);
100
+ return toFormattedTextProps(messages.modified_by, context.modifiedBy);
109
101
 
110
102
  case ElementName.ModifiedOn:
111
- return context.modifiedOn ? {
112
- date: new Date(context.modifiedOn),
113
- type: 'modified'
114
- } : undefined;
103
+ return toDateTimeProps('modified', context.modifiedOn);
115
104
 
116
- case ElementName.CreatedOn:
117
- return context.createdOn ? {
118
- date: new Date(context.createdOn),
119
- type: 'created'
120
- } : undefined;
105
+ case ElementName.Snippet:
106
+ return toTextProps(data);
121
107
 
122
108
  case ElementName.Title:
123
- return {
124
- text: context.title,
125
- url: context.url
126
- };
109
+ return toLinkProps(context.title, context.url);
127
110
 
128
111
  default:
129
112
  return data;
130
113
  }
131
114
  };
132
115
 
116
+ const toAvatarGroupProps = items => {
117
+ return items ? {
118
+ items
119
+ } : undefined;
120
+ };
121
+
122
+ const toBadgeProps = label => {
123
+ return label ? {
124
+ label
125
+ } : undefined;
126
+ };
127
+
128
+ const toDateTimeProps = (type, dateString) => {
129
+ return dateString ? {
130
+ date: new Date(dateString),
131
+ type
132
+ } : undefined;
133
+ };
134
+
135
+ const toFormattedTextProps = (descriptor, context) => {
136
+ return context ? {
137
+ message: {
138
+ descriptor,
139
+ values: {
140
+ context
141
+ }
142
+ }
143
+ } : undefined;
144
+ };
145
+
146
+ const toLinkProps = (text, url) => {
147
+ return text ? {
148
+ text,
149
+ url
150
+ } : undefined;
151
+ };
152
+
153
+ const toTextProps = content => {
154
+ return content ? {
155
+ content
156
+ } : undefined;
157
+ };
158
+
133
159
  export const createElement = name => {
134
160
  const {
135
161
  component: BaseElement,
@@ -48,7 +48,19 @@ export var SmartLinkTheme;
48
48
  SmartLinkTheme["Link"] = "link";
49
49
  })(SmartLinkTheme || (SmartLinkTheme = {}));
50
50
 
51
- export var SmartLinkWidth;
51
+ export var SmartLinkWidth; // When adding an element...
52
+ // 1) Create base element if it doesn't already existed.
53
+ // Base element are inside src/view/FlexibleCard/components/elements.
54
+ // E.g. Badge,DateTime, Icon, Lozenge, etc.
55
+ // 2) Update FlexibleUiContext with the new prop for data representing
56
+ // the element, preferably with the same name as the element itself.
57
+ // (src/state/flexible-ui-context/types.ts)
58
+ // 3) Update Flexible UI extractor (src/extractors/flexible/index.ts)
59
+ // 4) Set base element and data mapping.
60
+ // (src/view/FlexibleCard/components/elements/utils.tsx)
61
+ // 5) Create element. (src/view/FlexibleCard/components/elements/index.ts)
62
+ // 6) Update element ElementDisplaySchema for inline/block display
63
+ // (src/view/FlexibleCard/components/blocks/utils.tsx)
52
64
 
53
65
  (function (SmartLinkWidth) {
54
66
  SmartLinkWidth["FitToContent"] = "fit-to-content";
@@ -68,6 +80,7 @@ export var ElementName;
68
80
  ElementName["ModifiedOn"] = "ModifiedOn";
69
81
  ElementName["Priority"] = "Priority";
70
82
  ElementName["ProgrammingLanguage"] = "ProgrammingLanguage";
83
+ ElementName["Snippet"] = "Snippet";
71
84
  ElementName["State"] = "State";
72
85
  ElementName["SubscriberCount"] = "SubscriberCount";
73
86
  ElementName["Title"] = "Title";
@@ -1,4 +1,4 @@
1
- import { extractLink, extractTitle } from '../common/primitives';
1
+ import { extractLink, extractSummary, extractTitle } from '../common/primitives';
2
2
  import { extractLozenge } from '../common/lozenge';
3
3
  import { extractLinkIcon } from './icon';
4
4
  import { extractCommentCount, extractCreatedBy, extractModifiedBy, extractProgrammingLanguage, extractSubscriberCount } from './utils';
@@ -26,6 +26,8 @@ var extractFlexibleUiContext = function extractFlexibleUiContext(response, rende
26
26
  modifiedOn: extractDateUpdated(data),
27
27
  priority: extractPriority(data),
28
28
  programmingLanguage: extractProgrammingLanguage(data),
29
+ snippet: extractSummary(data) || undefined,
30
+ // Explicitly set here to remove an empty string
29
31
  state: extractLozenge(data),
30
32
  subscriberCount: extractSubscriberCount(data),
31
33
  title: extractTitle(data) || url,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "17.2.0",
3
+ "version": "17.3.2",
4
4
  "sideEffects": false
5
5
  }