@atlaskit/avatar 22.0.0 → 23.0.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 (40) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/cjs/avatar-content.js +217 -0
  3. package/dist/cjs/avatar.js +55 -103
  4. package/dist/cjs/context.js +31 -1
  5. package/dist/cjs/index.js +7 -0
  6. package/dist/cjs/{avatar-image.js → internal/avatar-image.js} +1 -1
  7. package/dist/cjs/{icon-wrapper.js → internal/icon-wrapper.js} +1 -1
  8. package/dist/cjs/presence.js +1 -1
  9. package/dist/cjs/status.js +1 -1
  10. package/dist/es2019/avatar-content.js +213 -0
  11. package/dist/es2019/avatar.js +38 -169
  12. package/dist/es2019/context.js +29 -1
  13. package/dist/es2019/index.js +1 -0
  14. package/dist/es2019/{avatar-image.js → internal/avatar-image.js} +1 -1
  15. package/dist/es2019/{icon-wrapper.js → internal/icon-wrapper.js} +1 -1
  16. package/dist/es2019/presence.js +1 -1
  17. package/dist/es2019/status.js +1 -1
  18. package/dist/esm/avatar-content.js +209 -0
  19. package/dist/esm/avatar.js +58 -103
  20. package/dist/esm/context.js +30 -0
  21. package/dist/esm/index.js +1 -0
  22. package/dist/esm/{avatar-image.js → internal/avatar-image.js} +1 -1
  23. package/dist/esm/{icon-wrapper.js → internal/icon-wrapper.js} +1 -1
  24. package/dist/esm/presence.js +1 -1
  25. package/dist/esm/status.js +1 -1
  26. package/dist/types/avatar-content.d.ts +21 -0
  27. package/dist/types/avatar.d.ts +2 -15
  28. package/dist/types/context.d.ts +33 -2
  29. package/dist/types/index.d.ts +2 -1
  30. package/dist/types/{avatar-image.d.ts → internal/avatar-image.d.ts} +1 -1
  31. package/dist/types/utilities.d.ts +1 -1
  32. package/dist/types-ts4.5/avatar-content.d.ts +21 -0
  33. package/dist/types-ts4.5/avatar.d.ts +2 -15
  34. package/dist/types-ts4.5/context.d.ts +33 -2
  35. package/dist/types-ts4.5/index.d.ts +2 -1
  36. package/dist/types-ts4.5/{avatar-image.d.ts → internal/avatar-image.d.ts} +1 -1
  37. package/dist/types-ts4.5/utilities.d.ts +1 -1
  38. package/package.json +3 -3
  39. /package/dist/types/{icon-wrapper.d.ts → internal/icon-wrapper.d.ts} +0 -0
  40. /package/dist/types-ts4.5/{icon-wrapper.d.ts → internal/icon-wrapper.d.ts} +0 -0
@@ -0,0 +1,209 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ /**
4
+ * @jsxRuntime classic
5
+ * @jsx jsx
6
+ * @jsxFrag
7
+ */
8
+ import { forwardRef } from 'react';
9
+ import { css, jsx } from '@emotion/react';
10
+ import { fg } from '@atlaskit/platform-feature-flags';
11
+ import { N0, N70A } from '@atlaskit/theme/colors';
12
+ import { useAvatarContent, useEnsureIsInsideAvatar } from './context';
13
+ var boxShadowCssVar = '--avatar-box-shadow';
14
+ var bgColorCssVar = '--avatar-bg-color';
15
+ var styles = {
16
+ root: css({
17
+ display: 'flex',
18
+ boxSizing: 'content-box',
19
+ position: 'static',
20
+ alignItems: 'stretch',
21
+ justifyContent: 'center',
22
+ flexDirection: 'column',
23
+ backgroundColor: "var(".concat(bgColorCssVar, ")"),
24
+ border: 'none',
25
+ boxShadow: "var(".concat(boxShadowCssVar, ")"),
26
+ cursor: 'inherit',
27
+ marginBlockEnd: "var(--ds-space-025, 2px)",
28
+ marginBlockStart: "var(--ds-space-025, 2px)",
29
+ marginInlineEnd: "var(--ds-space-025, 2px)",
30
+ marginInlineStart: "var(--ds-space-025, 2px)",
31
+ outline: 'none',
32
+ overflow: 'hidden',
33
+ paddingBlockEnd: "var(--ds-space-0, 0px)",
34
+ paddingBlockStart: "var(--ds-space-0, 0px)",
35
+ paddingInlineEnd: "var(--ds-space-0, 0px)",
36
+ paddingInlineStart: "var(--ds-space-0, 0px)",
37
+ transform: 'translateZ(0)',
38
+ transition: 'transform 200ms, opacity 200ms',
39
+ '&::after': {
40
+ width: '100%',
41
+ position: 'absolute',
42
+ inset: "var(--ds-space-0, 0px)",
43
+ backgroundColor: 'transparent',
44
+ content: "' '",
45
+ opacity: 0,
46
+ pointerEvents: 'none',
47
+ transition: 'opacity 200ms'
48
+ },
49
+ '&:focus-visible': {
50
+ boxShadow: 'none',
51
+ outlineColor: "var(--ds-border-focused, #2684FF)",
52
+ outlineOffset: "var(--ds-border-width-outline, 2px)",
53
+ outlineStyle: 'solid',
54
+ outlineWidth: "var(--ds-border-width-outline, 2px)"
55
+ },
56
+ '@media screen and (forced-colors: active), screen and (-ms-high-contrast: active)': {
57
+ '&:focus-visible': {
58
+ outlineWidth: "var(--ds-border-width, 1px)"
59
+ }
60
+ }
61
+ }),
62
+ circle: css({
63
+ borderRadius: "var(--ds-border-radius-circle, 50%)",
64
+ '&::after': {
65
+ borderRadius: "var(--ds-border-radius-circle, 50%)"
66
+ }
67
+ }),
68
+ positionRelative: css({
69
+ position: 'relative'
70
+ }),
71
+ interactive: css({
72
+ cursor: 'pointer',
73
+ '&:hover': {
74
+ '&::after': {
75
+ backgroundColor: "var(--ds-interaction-hovered, ".concat(N70A, ")"),
76
+ opacity: 1
77
+ }
78
+ },
79
+ '&:active': {
80
+ transform: "scale(0.9)",
81
+ '&::after': {
82
+ backgroundColor: "var(--ds-interaction-pressed, ".concat(N70A, ")"),
83
+ opacity: 1
84
+ }
85
+ },
86
+ '@media screen and (forced-colors: active)': {
87
+ '&:focus-visible': {
88
+ outlineWidth: 1
89
+ }
90
+ }
91
+ }),
92
+ disabled: css({
93
+ cursor: 'not-allowed',
94
+ '&::after': {
95
+ backgroundColor: "var(--ds-surface, ".concat(N0, ")"),
96
+ opacity: "var(--ds-opacity-disabled, 0.7)"
97
+ }
98
+ })
99
+ };
100
+ var widthHeightMap = {
101
+ xsmall: css({
102
+ width: '16px',
103
+ height: '16px'
104
+ }),
105
+ small: css({
106
+ width: '24px',
107
+ height: '24px'
108
+ }),
109
+ medium: css({
110
+ width: '32px',
111
+ height: '32px'
112
+ }),
113
+ large: css({
114
+ width: '40px',
115
+ height: '40px'
116
+ }),
117
+ xlarge: css({
118
+ width: '96px',
119
+ height: '96px'
120
+ }),
121
+ xxlarge: css({
122
+ width: '128px',
123
+ height: '128px'
124
+ })
125
+ };
126
+ var borderRadiusMap = {
127
+ xsmall: css({
128
+ borderRadius: '2px',
129
+ '&::after': {
130
+ borderRadius: '2px'
131
+ }
132
+ }),
133
+ small: css({
134
+ borderRadius: '2px',
135
+ '&::after': {
136
+ borderRadius: '2px'
137
+ }
138
+ }),
139
+ medium: css({
140
+ borderRadius: '3px',
141
+ '&::after': {
142
+ borderRadius: '3px'
143
+ }
144
+ }),
145
+ large: css({
146
+ borderRadius: '3px',
147
+ '&::after': {
148
+ borderRadius: '3px'
149
+ }
150
+ }),
151
+ xlarge: css({
152
+ borderRadius: '6px',
153
+ '&::after': {
154
+ borderRadius: '6px'
155
+ }
156
+ }),
157
+ xxlarge: css({
158
+ borderRadius: '12px',
159
+ '&::after': {
160
+ borderRadius: '12px'
161
+ }
162
+ })
163
+ };
164
+ /**
165
+ * __Avatar content__
166
+ *
167
+ * Avatar content renders the avatar content. It can be composed with the Avatar component
168
+ * to create a custom avatar.
169
+ *
170
+ * - [Examples](https://atlassian.design/components/avatar/examples)
171
+ * - [Code](https://atlassian.design/components/avatar/code)
172
+ * - [Usage](https://atlassian.design/components/avatar/usage)
173
+ */
174
+ export var AvatarContent = /*#__PURE__*/forwardRef(function (_ref, ref) {
175
+ var children = _ref.children;
176
+ useEnsureIsInsideAvatar();
177
+ var _useAvatarContent = useAvatarContent(),
178
+ Container = _useAvatarContent.as,
179
+ appearance = _useAvatarContent.appearance,
180
+ avatarImage = _useAvatarContent.avatarImage,
181
+ _useAvatarContent$bor = _useAvatarContent.borderColor,
182
+ borderColor = _useAvatarContent$bor === void 0 ? fg('platform-component-visual-refresh') ? "var(--ds-surface, #FFFFFF)" : "var(--ds-surface-overlay, ".concat(N0, ")") : _useAvatarContent$bor,
183
+ href = _useAvatarContent.href,
184
+ isDisabled = _useAvatarContent.isDisabled,
185
+ label = _useAvatarContent.label,
186
+ onClick = _useAvatarContent.onClick,
187
+ contextRef = _useAvatarContent.ref,
188
+ tabIndex = _useAvatarContent.tabIndex,
189
+ target = _useAvatarContent.target,
190
+ testId = _useAvatarContent.testId,
191
+ size = _useAvatarContent.size,
192
+ stackIndex = _useAvatarContent.stackIndex;
193
+ var isInteractive = Boolean(onClick || href || isDisabled);
194
+ return jsx(Container, _extends({
195
+ css: [styles.root, borderRadiusMap[size], appearance === 'circle' && styles.circle, widthHeightMap[size], stackIndex !== undefined && styles.positionRelative, isInteractive && !isDisabled && styles.interactive, isDisabled && styles.disabled],
196
+ style: _defineProperty(_defineProperty({}, bgColorCssVar, borderColor), boxShadowCssVar, "0 0 0 2px ".concat(borderColor)),
197
+ ref: ref || contextRef,
198
+ "aria-label": isInteractive ? label : undefined,
199
+ onClick: onClick,
200
+ tabIndex: tabIndex,
201
+ "data-testid": testId,
202
+ disabled: isDisabled,
203
+ type: Container === 'button' ? 'button' : undefined
204
+ }, href && {
205
+ href: href,
206
+ target: target,
207
+ rel: target === '_blank' ? 'noopener noreferrer' : undefined
208
+ }), children || avatarImage);
209
+ });
@@ -1,51 +1,32 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
3
- var _templateObject;
4
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
4
  /**
7
5
  * @jsxRuntime classic
8
6
  * @jsx jsx
9
7
  */
10
- import { createElement, forwardRef, isValidElement, useCallback, useEffect, useRef } from 'react';
11
- import { ClassNames, jsx } from '@emotion/react';
8
+ import { forwardRef, isValidElement, useCallback, useEffect, useRef } from 'react';
9
+
10
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
11
+ import { css, jsx } from '@emotion/react';
12
12
  import { useAnalyticsEvents } from '@atlaskit/analytics-next';
13
13
  import { useId } from '@atlaskit/ds-lib/use-id';
14
- import FocusRing from '@atlaskit/focus-ring';
15
- import { fg } from '@atlaskit/platform-feature-flags';
16
- import { N0, N70A } from '@atlaskit/theme/colors';
17
- import AvatarImage from './avatar-image';
18
- import { ACTIVE_SCALE_FACTOR, AVATAR_RADIUS, AVATAR_SIZES, BORDER_WIDTH } from './constants';
19
- import { useAvatarContext } from './context';
14
+ import { AvatarContent } from './avatar-content';
15
+ import { AvatarContentContext, EnsureIsInsideAvatarContext, useAvatarContext } from './context';
16
+ import AvatarImage from './internal/avatar-image';
20
17
  import { PresenceWrapper } from './presence';
21
18
  import { StatusWrapper } from './status';
22
- import { getButtonProps, getCustomElement, getLinkProps } from './utilities';
19
+ import { getCustomElement } from './utilities';
23
20
  var packageName = "@atlaskit/avatar";
24
- var packageVersion = "22.0.0";
25
- var getTestId = function getTestId(testId, children) {
26
- return !children ? {
27
- 'data-testid': "".concat(testId, "--inner")
28
- } : {
29
- testId: "".concat(testId, "--inner")
30
- };
31
- };
21
+ var packageVersion = "23.0.0";
22
+ var containerStyles = css({
23
+ display: 'inline-block',
24
+ position: 'relative',
25
+ outline: 0
26
+ });
32
27
 
33
28
  // eslint-disable-next-line @repo/internal/react/consistent-types-definitions
34
29
 
35
- var getStyles = function getStyles(css, _ref) {
36
- var size = _ref.size,
37
- radius = _ref.radius,
38
- appearance = _ref.appearance,
39
- _ref$borderColor = _ref.borderColor,
40
- borderColor = _ref$borderColor === void 0 ? fg('platform-component-visual-refresh') ? "var(--ds-surface, #FFFFFF)" : "var(--ds-surface-overlay, ".concat(N0, ")") : _ref$borderColor,
41
- stackIndex = _ref.stackIndex,
42
- isInteractive = _ref.isInteractive,
43
- isDisabled = _ref.isDisabled;
44
- return (//eslint-disable-next-line @repo/internal/react/no-css-string-literals
45
- css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n\t\theight: ", "px;\n\t\twidth: ", "px;\n\t\talign-items: stretch;\n\t\tbackground-color: ", ";\n\t\tborder-radius: ", ";\n\t\tbox-sizing: content-box;\n\t\tcursor: inherit;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: center;\n\t\toutline: none;\n\t\toverflow: hidden;\n\t\tposition: static;\n\t\ttransform: translateZ(0);\n\t\ttransition:\n\t\t\ttransform 200ms,\n\t\t\topacity 200ms;\n\t\tbox-shadow: 0 0 0 ", "px ", ";\n\t\tborder: none;\n\t\tmargin: ", ";\n\t\tpadding: ", ";\n\n\t\t&::-moz-focus-inner {\n\t\t\tborder: 0;\n\t\t\tmargin: ", ";\n\t\t\tpadding: ", ";\n\t\t}\n\n\t\t&::after {\n\t\t\tbackground-color: transparent;\n\t\t\tinset: 0px;\n\n\t\t\t/* Added border-radius style to fix hover issue in safari */\n\t\t\tborder-radius: ", ";\n\t\t\tcontent: ' ';\n\t\t\topacity: 0;\n\t\t\tpointer-events: none;\n\t\t\tposition: absolute;\n\t\t\ttransition: opacity 200ms;\n\t\t\twidth: 100%;\n\t\t}\n\n\t\t:focus-visible {\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t", "\n\n\t\t", "\n\n ", "\n\t"])), size, size, borderColor, appearance === 'circle' ? '50%' : "".concat(radius, "px"), BORDER_WIDTH, borderColor, "var(--ds-space-025, 2px)", "var(--ds-space-0, 0px)", "var(--ds-space-0, 0px)", "var(--ds-space-0, 0px)", appearance === 'circle' ? '50%' : "".concat(radius, "px"), stackIndex && "position: relative;", isInteractive && "\n cursor: pointer;\n\n :hover {\n &::after {\n background-color: ".concat("var(--ds-interaction-hovered, ".concat(N70A, ")"), ";\n opacity: 1;\n }\n }\n\n :active {\n &::after {\n background-color: ", "var(--ds-interaction-pressed, ".concat(N70A, ")"), ";\n opacity: 1;\n }\n }\n\n :active {\n transform: scale(", ACTIVE_SCALE_FACTOR, ");\n }\n\n @media screen and (forced-colors: active) {\n &:focus-visible {\n outline: 1px solid\n }\n }\n "), isDisabled && "\n cursor: not-allowed;\n\n &::after {\n opacity: ".concat("var(--ds-opacity-disabled, 0.7)", ";\n pointer-events: none;\n background-color: ", "var(--ds-surface, ".concat(N0, ")"), ";\n }\n "))
46
- );
47
- };
48
-
49
30
  /**
50
31
  * __Avatar__
51
32
  *
@@ -55,31 +36,30 @@ var getStyles = function getStyles(css, _ref) {
55
36
  * - [Code](https://atlassian.design/components/avatar/code)
56
37
  * - [Usage](https://atlassian.design/components/avatar/usage)
57
38
  */
58
- var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
59
- var _ref3;
60
- var analyticsContext = _ref2.analyticsContext,
61
- _ref2$appearance = _ref2.appearance,
62
- appearance = _ref2$appearance === void 0 ? 'circle' : _ref2$appearance,
63
- label = _ref2.label,
64
- borderColor = _ref2.borderColor,
65
- children = _ref2.children,
66
- href = _ref2.href,
67
- isDisabled = _ref2.isDisabled,
68
- name = _ref2.name,
69
- onClick = _ref2.onClick,
70
- presence = _ref2.presence,
71
- sizeProp = _ref2.size,
72
- src = _ref2.src,
73
- stackIndex = _ref2.stackIndex,
74
- status = _ref2.status,
75
- target = _ref2.target,
76
- testId = _ref2.testId,
77
- _ref2$as = _ref2.as,
78
- AvatarContainer = _ref2$as === void 0 ? 'div' : _ref2$as;
39
+ var Avatar = /*#__PURE__*/forwardRef(function (_ref, ref) {
40
+ var analyticsContext = _ref.analyticsContext,
41
+ _ref$appearance = _ref.appearance,
42
+ appearance = _ref$appearance === void 0 ? 'circle' : _ref$appearance,
43
+ label = _ref.label,
44
+ borderColor = _ref.borderColor,
45
+ children = _ref.children,
46
+ href = _ref.href,
47
+ isDisabled = _ref.isDisabled,
48
+ name = _ref.name,
49
+ onClick = _ref.onClick,
50
+ presence = _ref.presence,
51
+ sizeProp = _ref.size,
52
+ src = _ref.src,
53
+ stackIndex = _ref.stackIndex,
54
+ status = _ref.status,
55
+ target = _ref.target,
56
+ testId = _ref.testId,
57
+ _ref$as = _ref.as,
58
+ AvatarContainer = _ref$as === void 0 ? 'div' : _ref$as;
79
59
  var _useAnalyticsEvents = useAnalyticsEvents(),
80
60
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
81
61
  var context = useAvatarContext();
82
- var size = (_ref3 = sizeProp !== null && sizeProp !== void 0 ? sizeProp : context === null || context === void 0 ? void 0 : context.size) !== null && _ref3 !== void 0 ? _ref3 : 'medium';
62
+ var size = sizeProp || (context === null || context === void 0 ? void 0 : context.size) || 'medium';
83
63
  var customPresenceNode = /*#__PURE__*/isValidElement(presence) ? presence : null;
84
64
  var customStatusNode = /*#__PURE__*/isValidElement(status) ? status : null;
85
65
  var isValidIconSize = size !== 'xxlarge' && size !== 'xsmall';
@@ -122,18 +102,6 @@ var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
122
102
  }
123
103
  onClick(event, analyticsEvent);
124
104
  }, [createAnalyticsEvent, isDisabled, onClick]);
125
- var componentProps = function componentProps() {
126
- if (isDisabled) {
127
- return {
128
- disabled: true
129
- };
130
- }
131
-
132
- // return only relevant props for either anchor or button elements
133
- return _objectSpread(_objectSpread({}, href && getLinkProps(href, target)), onClick && !href ? getButtonProps(onClickHandler) : {
134
- onClick: onClick
135
- });
136
- };
137
105
  var isPresence = isValidIconSize && presence && !status;
138
106
  var isStatus = isValidIconSize && status;
139
107
 
@@ -142,52 +110,39 @@ var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
142
110
  var defaultLabel = [name, isStatus && !customStatusNode && "(".concat(status, ")"), isPresence && !customPresenceNode && "(".concat(presence, ")")].filter(Boolean).join(' ');
143
111
  var isInteractive = onClick || href || isDisabled;
144
112
  var containerShouldBeImage = Boolean(!isInteractive && defaultLabel);
145
- return jsx(AvatarContainer, {
113
+ return jsx(EnsureIsInsideAvatarContext.Provider, {
114
+ value: true
115
+ }, jsx(AvatarContainer, {
146
116
  "data-testid": testId,
147
117
  role: containerShouldBeImage ? 'img' : undefined,
148
118
  "aria-labelledby": containerShouldBeImage ? labelId : undefined,
119
+ css: containerStyles,
149
120
  style: {
150
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
151
- display: 'inline-block',
152
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
153
- position: 'relative',
154
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
155
- outline: 0,
156
121
  zIndex: stackIndex
157
122
  }
158
- }, jsx(ClassNames, null, function (_ref4) {
159
- var css = _ref4.css;
160
- var props = _objectSpread(_objectSpread(_objectSpread(_objectSpread({
161
- className: getStyles(css, {
162
- size: AVATAR_SIZES[size],
163
- radius: AVATAR_RADIUS[size],
164
- appearance: appearance,
165
- borderColor: borderColor,
166
- stackIndex: stackIndex,
167
- isInteractive: Boolean(href || onClick) && !isDisabled,
168
- isDisabled: isDisabled
169
- })
170
- }, componentProps()), testId && getTestId(testId, children)), (isInteractive || children) && {
171
- 'aria-label': label || defaultLabel
172
- }), {}, {
173
- children: jsx(AvatarImage
174
- // Only pass in the name if an image is provided and the
175
- // container is not being used as an `img` role
176
- , {
123
+ }, jsx(AvatarContentContext.Provider, {
124
+ value: {
125
+ as: getCustomElement(isDisabled, href, onClick),
126
+ appearance: appearance,
127
+ borderColor: borderColor,
128
+ href: href,
129
+ isDisabled: isDisabled,
130
+ label: label || defaultLabel,
131
+ onClick: isInteractive ? onClickHandler : undefined,
132
+ ref: ref,
133
+ size: size,
134
+ stackIndex: stackIndex,
135
+ target: target,
136
+ testId: testId ? "".concat(testId, "--inner") : undefined,
137
+ avatarImage: jsx(AvatarImage, {
177
138
  alt: !containerShouldBeImage && src ? name : undefined,
139
+ src: src,
178
140
  appearance: appearance,
179
141
  size: size,
180
- src: src,
181
142
  testId: testId
182
- }),
183
- ref: ref
184
- });
185
- if (children) {
186
- return children(props);
143
+ })
187
144
  }
188
- var element = getCustomElement(isDisabled, href, onClick);
189
- return element === 'a' || element === 'button' ? jsx(FocusRing, null, /*#__PURE__*/createElement(element, props)) : ( /*#__PURE__*/createElement(element, props));
190
- }), isPresence && jsx(PresenceWrapper, {
145
+ }, children || jsx(AvatarContent, null)), isPresence && jsx(PresenceWrapper, {
191
146
  appearance: appearance,
192
147
  size: size,
193
148
  presence: typeof presence === 'string' ? presence : undefined,
@@ -202,7 +157,7 @@ var Avatar = /*#__PURE__*/forwardRef(function (_ref2, ref) {
202
157
  "data-testid": testId && "".concat(testId, "--label"),
203
158
  id: labelId,
204
159
  hidden: true
205
- }, defaultLabel) : undefined);
160
+ }, defaultLabel) : undefined));
206
161
  });
207
162
  Avatar.displayName = 'Avatar';
208
163
  export default Avatar;
@@ -15,4 +15,34 @@ import { createContext, useContext } from 'react';
15
15
  export var AvatarContext = /*#__PURE__*/createContext(undefined);
16
16
  export var useAvatarContext = function useAvatarContext() {
17
17
  return useContext(AvatarContext);
18
+ };
19
+ var defaultAvatarContentProps = {
20
+ as: 'span',
21
+ appearance: 'circle',
22
+ avatarImage: null,
23
+ ref: null,
24
+ size: 'medium'
25
+ };
26
+
27
+ /**
28
+ * __Avatar content context__
29
+ *
30
+ * This context provides the props for the AvatarContent component, enabling
31
+ * consumers to compose the AvatarContent with the Avatar component.
32
+ */
33
+ export var AvatarContentContext = /*#__PURE__*/createContext(defaultAvatarContentProps);
34
+ export var useAvatarContent = function useAvatarContent() {
35
+ return useContext(AvatarContentContext);
36
+ };
37
+
38
+ /**
39
+ * Used to ensure Avatar sub-components are used within a Avatar component,
40
+ * and provide a useful error message if not.
41
+ */
42
+ export var EnsureIsInsideAvatarContext = /*#__PURE__*/createContext(false);
43
+ export var useEnsureIsInsideAvatar = function useEnsureIsInsideAvatar() {
44
+ var context = useContext(EnsureIsInsideAvatarContext);
45
+ if (!context) {
46
+ throw new Error('Avatar sub-components must be used within a Avatar component.');
47
+ }
18
48
  };
package/dist/esm/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default } from './avatar';
2
+ export { AvatarContent } from './avatar-content';
2
3
  export { default as AvatarItem } from './avatar-item';
3
4
  export { default as Presence } from './presence';
4
5
  export { default as Status } from './status';
@@ -14,7 +14,7 @@ import PersonIcon from '@atlaskit/icon/core/person';
14
14
  import ReleaseIcon from '@atlaskit/icon/core/release';
15
15
  import { fg } from '@atlaskit/platform-feature-flags';
16
16
  import { N0, N90 } from '@atlaskit/theme/colors';
17
- import { AVATAR_RADIUS, AVATAR_SIZES } from './constants';
17
+ import { AVATAR_RADIUS, AVATAR_SIZES } from '../constants';
18
18
  var avatarDefaultIconStyles = css({
19
19
  display: 'flex',
20
20
  width: '100%',
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { css, jsx } from '@emotion/react';
7
7
  import { N0 } from '@atlaskit/theme/colors';
8
- import { BORDER_WIDTH } from './constants';
8
+ import { BORDER_WIDTH } from '../constants';
9
9
  var iconWrapperStyles = css({
10
10
  display: 'flex',
11
11
  boxSizing: 'border-box',
@@ -1,7 +1,7 @@
1
1
  import React, { Fragment } from 'react';
2
2
  import { G300, N0, N200, N40, P300, R300 } from '@atlaskit/theme/colors';
3
3
  import { ICON_OFFSET, ICON_SIZES } from './constants';
4
- import IconWrapper from './icon-wrapper';
4
+ import IconWrapper from './internal/icon-wrapper';
5
5
  var BusyIndicator = /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("circle", {
6
6
  fill: "var(--ds-icon-danger, ".concat(R300, ")"),
7
7
  cx: "4",
@@ -1,7 +1,7 @@
1
1
  import React, { Fragment } from 'react';
2
2
  import { G400, N0, N40, N500, R400 } from '@atlaskit/theme/colors';
3
3
  import { ICON_OFFSET, ICON_SIZES } from './constants';
4
- import IconWrapper from './icon-wrapper';
4
+ import IconWrapper from './internal/icon-wrapper';
5
5
  var ApprovedIndicator = /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("circle", {
6
6
  fill: "var(--ds-icon-success, ".concat(G400, ")"),
7
7
  cx: "4",
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ * @jsxFrag
5
+ */
6
+ import { type ReactNode } from 'react';
7
+ type AvatarContentProps = {
8
+ children?: ReactNode;
9
+ };
10
+ /**
11
+ * __Avatar content__
12
+ *
13
+ * Avatar content renders the avatar content. It can be composed with the Avatar component
14
+ * to create a custom avatar.
15
+ *
16
+ * - [Examples](https://atlassian.design/components/avatar/examples)
17
+ * - [Code](https://atlassian.design/components/avatar/code)
18
+ * - [Usage](https://atlassian.design/components/avatar/usage)
19
+ */
20
+ export declare const AvatarContent: import("react").ForwardRefExoticComponent<AvatarContentProps & import("react").RefAttributes<HTMLElement>>;
21
+ export {};
@@ -2,21 +2,8 @@
2
2
  * @jsxRuntime classic
3
3
  * @jsx jsx
4
4
  */
5
- import { type MouseEventHandler, type ReactNode, type Ref } from 'react';
5
+ import { type ReactNode } from 'react';
6
6
  import { type AppearanceType, type AvatarClickEventHandler, type Presence, type SizeType, type Status } from './types';
7
- export interface CustomAvatarProps {
8
- /**
9
- * This is used in render props so is okay to be defined.
10
- */
11
- 'aria-label'?: string;
12
- tabIndex?: number;
13
- testId?: string;
14
- onClick?: MouseEventHandler;
15
- className?: string;
16
- href?: string;
17
- children: ReactNode;
18
- ref: Ref<HTMLElement>;
19
- }
20
7
  export interface AvatarPropTypes {
21
8
  /**
22
9
  * Indicates the shape of the avatar. Most avatars are circular, but square avatars
@@ -37,7 +24,7 @@ export interface AvatarPropTypes {
37
24
  /**
38
25
  * Supply a custom avatar component instead of the default.
39
26
  */
40
- children?: (props: CustomAvatarProps) => ReactNode;
27
+ children?: ReactNode;
41
28
  /**
42
29
  * Provides a url for avatars being used as a link.
43
30
  */
@@ -1,5 +1,5 @@
1
- /// <reference types="react" />
2
- import { type SizeType } from './types';
1
+ import { type ForwardedRef, type MouseEventHandler, type ReactNode } from 'react';
2
+ import { type AppearanceType, type SizeType } from './types';
3
3
  export type AvatarContextProps = {
4
4
  size: SizeType;
5
5
  };
@@ -18,3 +18,34 @@ export type AvatarContextProps = {
18
18
  */
19
19
  export declare const AvatarContext: import("react").Context<AvatarContextProps | undefined>;
20
20
  export declare const useAvatarContext: () => AvatarContextProps | undefined;
21
+ type AvatarContentContextProps = {
22
+ as: 'a' | 'button' | 'span';
23
+ appearance: AppearanceType;
24
+ avatarImage: ReactNode;
25
+ borderColor?: string;
26
+ href?: string;
27
+ isDisabled?: boolean;
28
+ label?: string;
29
+ onClick?: MouseEventHandler;
30
+ ref: ForwardedRef<HTMLElement>;
31
+ tabIndex?: number;
32
+ target?: '_blank' | '_self' | '_top' | '_parent';
33
+ testId?: string;
34
+ size: SizeType;
35
+ stackIndex?: number;
36
+ };
37
+ /**
38
+ * __Avatar content context__
39
+ *
40
+ * This context provides the props for the AvatarContent component, enabling
41
+ * consumers to compose the AvatarContent with the Avatar component.
42
+ */
43
+ export declare const AvatarContentContext: import("react").Context<AvatarContentContextProps>;
44
+ export declare const useAvatarContent: () => AvatarContentContextProps;
45
+ /**
46
+ * Used to ensure Avatar sub-components are used within a Avatar component,
47
+ * and provide a useful error message if not.
48
+ */
49
+ export declare const EnsureIsInsideAvatarContext: import("react").Context<boolean>;
50
+ export declare const useEnsureIsInsideAvatar: () => void;
51
+ export {};
@@ -1,5 +1,6 @@
1
1
  export { default } from './avatar';
2
- export type { AvatarPropTypes, CustomAvatarProps } from './avatar';
2
+ export type { AvatarPropTypes } from './avatar';
3
+ export { AvatarContent } from './avatar-content';
3
4
  export { default as AvatarItem } from './avatar-item';
4
5
  export type { AvatarItemProps, CustomAvatarItemProps } from './avatar-item';
5
6
  export { default as Presence } from './presence';
@@ -3,7 +3,7 @@
3
3
  * @jsx jsx
4
4
  */
5
5
  import { type FC } from 'react';
6
- import { type AppearanceType, type SizeType } from './types';
6
+ import { type AppearanceType, type SizeType } from '../types';
7
7
  interface AvatarImageProps {
8
8
  appearance: AppearanceType;
9
9
  size: SizeType;
@@ -8,4 +8,4 @@ export declare const getButtonProps: (onClick: MouseEventHandler) => {
8
8
  type: string;
9
9
  onClick: MouseEventHandler;
10
10
  };
11
- export declare const getCustomElement: (isDisabled?: boolean, href?: string, onClick?: MouseEventHandler) => "button" | "a" | "span";
11
+ export declare const getCustomElement: (isDisabled?: boolean, href?: string, onClick?: MouseEventHandler) => "a" | "button" | "span";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ * @jsxFrag
5
+ */
6
+ import { type ReactNode } from 'react';
7
+ type AvatarContentProps = {
8
+ children?: ReactNode;
9
+ };
10
+ /**
11
+ * __Avatar content__
12
+ *
13
+ * Avatar content renders the avatar content. It can be composed with the Avatar component
14
+ * to create a custom avatar.
15
+ *
16
+ * - [Examples](https://atlassian.design/components/avatar/examples)
17
+ * - [Code](https://atlassian.design/components/avatar/code)
18
+ * - [Usage](https://atlassian.design/components/avatar/usage)
19
+ */
20
+ export declare const AvatarContent: import("react").ForwardRefExoticComponent<AvatarContentProps & import("react").RefAttributes<HTMLElement>>;
21
+ export {};