@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.
- package/CHANGELOG.md +28 -0
- package/dist/cjs/constants.js +15 -1
- package/dist/cjs/extractors/flexible/index.js +2 -0
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/FlexibleCard/components/actions/{delete-action → action}/index.js +40 -25
- package/dist/cjs/view/FlexibleCard/components/actions/{types.js → action/types.js} +0 -0
- package/dist/cjs/view/FlexibleCard/components/actions/index.js +3 -1
- package/dist/cjs/view/FlexibleCard/components/actions/utils.js +34 -6
- package/dist/cjs/view/FlexibleCard/components/blocks/action-group/index.js +1 -1
- package/dist/cjs/view/FlexibleCard/components/blocks/metadata-block/index.js +17 -3
- package/dist/cjs/view/FlexibleCard/components/blocks/utils.js +27 -7
- package/dist/cjs/view/FlexibleCard/components/elements/avatar-group/index.js +24 -2
- package/dist/cjs/view/FlexibleCard/components/elements/index.js +3 -1
- package/dist/cjs/view/FlexibleCard/components/elements/text/index.js +6 -2
- package/dist/cjs/view/FlexibleCard/components/elements/utils.js +62 -39
- package/dist/es2019/constants.js +14 -1
- package/dist/es2019/extractors/flexible/index.js +3 -1
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/FlexibleCard/components/actions/{delete-action → action}/index.js +31 -15
- package/dist/es2019/view/FlexibleCard/components/actions/{types.js → action/types.js} +0 -0
- package/dist/es2019/view/FlexibleCard/components/actions/index.js +5 -3
- package/dist/es2019/view/FlexibleCard/components/actions/utils.js +27 -4
- package/dist/es2019/view/FlexibleCard/components/blocks/action-group/index.js +1 -1
- package/dist/es2019/view/FlexibleCard/components/blocks/metadata-block/index.js +17 -3
- package/dist/es2019/view/FlexibleCard/components/blocks/utils.js +37 -6
- package/dist/es2019/view/FlexibleCard/components/elements/avatar-group/index.js +28 -2
- package/dist/es2019/view/FlexibleCard/components/elements/index.js +1 -0
- package/dist/es2019/view/FlexibleCard/components/elements/text/index.js +5 -3
- package/dist/es2019/view/FlexibleCard/components/elements/utils.js +63 -37
- package/dist/esm/constants.js +14 -1
- package/dist/esm/extractors/flexible/index.js +3 -1
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/FlexibleCard/components/actions/action/index.js +82 -0
- package/dist/esm/view/FlexibleCard/components/actions/{types.js → action/types.js} +0 -0
- package/dist/esm/view/FlexibleCard/components/actions/index.js +5 -3
- package/dist/esm/view/FlexibleCard/components/actions/utils.js +26 -4
- package/dist/esm/view/FlexibleCard/components/blocks/action-group/index.js +1 -1
- package/dist/esm/view/FlexibleCard/components/blocks/metadata-block/index.js +17 -3
- package/dist/esm/view/FlexibleCard/components/blocks/utils.js +25 -7
- package/dist/esm/view/FlexibleCard/components/elements/avatar-group/index.js +24 -2
- package/dist/esm/view/FlexibleCard/components/elements/index.js +1 -0
- package/dist/esm/view/FlexibleCard/components/elements/text/index.js +7 -2
- package/dist/esm/view/FlexibleCard/components/elements/utils.js +62 -39
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/state/flexible-ui-context/types.d.ts +3 -2
- package/dist/types/view/FlexibleCard/components/actions/action/index.d.ts +5 -0
- package/dist/types/view/FlexibleCard/components/actions/action/types.d.ts +18 -0
- package/dist/types/view/FlexibleCard/components/actions/index.d.ts +1 -1
- package/dist/types/view/FlexibleCard/components/actions/utils.d.ts +2 -1
- package/dist/types/view/FlexibleCard/components/blocks/utils.d.ts +4 -2
- package/dist/types/view/FlexibleCard/components/elements/avatar-group/index.d.ts +1 -0
- package/dist/types/view/FlexibleCard/components/elements/avatar-group/types.d.ts +1 -2
- package/dist/types/view/FlexibleCard/components/elements/index.d.ts +1 -0
- package/dist/types/view/FlexibleCard/components/elements/text/types.d.ts +1 -0
- package/package.json +1 -1
- package/dist/esm/view/FlexibleCard/components/actions/delete-action/index.js +0 -64
- package/dist/types/view/FlexibleCard/components/actions/delete-action/index.d.ts +0 -5
- package/dist/types/view/FlexibleCard/components/actions/types.d.ts +0 -10
package/dist/es2019/constants.js
CHANGED
|
@@ -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,
|
package/dist/es2019/version.json
CHANGED
|
@@ -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
|
|
24
|
+
const getIconStyles = size => css`
|
|
28
25
|
color: ${tokens.actionIcon};
|
|
29
26
|
${getIconSizeStyles(getWidth(size))};
|
|
30
27
|
`;
|
|
31
28
|
|
|
32
|
-
const
|
|
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
|
|
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:
|
|
63
|
+
content: tooltipMessage
|
|
45
64
|
}, jsx(Button, {
|
|
46
65
|
spacing: "none",
|
|
47
66
|
appearance: appearance,
|
|
48
67
|
testId: testId,
|
|
49
|
-
onClick: handleOnClick(onClick)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
|
74
|
+
export default Action;
|
|
File without changes
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ActionName } from '../../../../constants';
|
|
2
|
-
import {
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
};
|
|
@@ -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.
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
6
|
+
|
|
7
|
+
const getStyles = maxLines => css`
|
|
7
8
|
color: ${tokens.text};
|
|
8
9
|
font-size: 0.75rem;
|
|
9
10
|
line-height: 1rem;
|
|
10
|
-
${getTruncateStyles(
|
|
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:
|
|
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
|
|
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
|
|
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.
|
|
117
|
-
return
|
|
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,
|
package/dist/esm/constants.js
CHANGED
|
@@ -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,
|
package/dist/esm/version.json
CHANGED