@atlaskit/editor-plugin-avatar-group 0.1.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 (59) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +13 -0
  3. package/README.md +33 -0
  4. package/dist/cjs/index.js +12 -0
  5. package/dist/cjs/messages.js +14 -0
  6. package/dist/cjs/plugin.js +58 -0
  7. package/dist/cjs/ui/AvatarGroupPluginWrapper.js +52 -0
  8. package/dist/cjs/ui/avatars-with-plugin-state.js +42 -0
  9. package/dist/cjs/ui/avatars.js +73 -0
  10. package/dist/cjs/ui/colored-avatar-item.js +23 -0
  11. package/dist/cjs/ui/index.js +16 -0
  12. package/dist/cjs/ui/invite-to-edit.js +48 -0
  13. package/dist/cjs/ui/styles.js +17 -0
  14. package/dist/cjs/ui/to-avatar.js +30 -0
  15. package/dist/es2019/index.js +1 -0
  16. package/dist/es2019/messages.js +8 -0
  17. package/dist/es2019/plugin.js +54 -0
  18. package/dist/es2019/ui/AvatarGroupPluginWrapper.js +57 -0
  19. package/dist/es2019/ui/avatars-with-plugin-state.js +38 -0
  20. package/dist/es2019/ui/avatars.js +66 -0
  21. package/dist/es2019/ui/colored-avatar-item.js +16 -0
  22. package/dist/es2019/ui/index.js +3 -0
  23. package/dist/es2019/ui/invite-to-edit.js +35 -0
  24. package/dist/es2019/ui/styles.js +46 -0
  25. package/dist/es2019/ui/to-avatar.js +16 -0
  26. package/dist/esm/index.js +1 -0
  27. package/dist/esm/messages.js +8 -0
  28. package/dist/esm/plugin.js +51 -0
  29. package/dist/esm/ui/AvatarGroupPluginWrapper.js +46 -0
  30. package/dist/esm/ui/avatars-with-plugin-state.js +35 -0
  31. package/dist/esm/ui/avatars.js +66 -0
  32. package/dist/esm/ui/colored-avatar-item.js +16 -0
  33. package/dist/esm/ui/index.js +3 -0
  34. package/dist/esm/ui/invite-to-edit.js +37 -0
  35. package/dist/esm/ui/styles.js +10 -0
  36. package/dist/esm/ui/to-avatar.js +23 -0
  37. package/dist/types/index.d.ts +2 -0
  38. package/dist/types/messages.d.ts +7 -0
  39. package/dist/types/plugin.d.ts +27 -0
  40. package/dist/types/ui/AvatarGroupPluginWrapper.d.ts +18 -0
  41. package/dist/types/ui/avatars-with-plugin-state.d.ts +80 -0
  42. package/dist/types/ui/avatars.d.ts +20 -0
  43. package/dist/types/ui/colored-avatar-item.d.ts +10 -0
  44. package/dist/types/ui/index.d.ts +3 -0
  45. package/dist/types/ui/invite-to-edit.d.ts +10 -0
  46. package/dist/types/ui/styles.d.ts +3 -0
  47. package/dist/types/ui/to-avatar.d.ts +30 -0
  48. package/dist/types-ts4.5/index.d.ts +2 -0
  49. package/dist/types-ts4.5/messages.d.ts +7 -0
  50. package/dist/types-ts4.5/plugin.d.ts +27 -0
  51. package/dist/types-ts4.5/ui/AvatarGroupPluginWrapper.d.ts +18 -0
  52. package/dist/types-ts4.5/ui/avatars-with-plugin-state.d.ts +96 -0
  53. package/dist/types-ts4.5/ui/avatars.d.ts +22 -0
  54. package/dist/types-ts4.5/ui/colored-avatar-item.d.ts +12 -0
  55. package/dist/types-ts4.5/ui/index.d.ts +3 -0
  56. package/dist/types-ts4.5/ui/invite-to-edit.d.ts +10 -0
  57. package/dist/types-ts4.5/ui/styles.d.ts +3 -0
  58. package/dist/types-ts4.5/ui/to-avatar.d.ts +37 -0
  59. package/package.json +110 -0
@@ -0,0 +1,66 @@
1
+ /** @jsx jsx */
2
+
3
+ import React from 'react';
4
+ import { jsx } from '@emotion/react';
5
+ import AvatarGroup from '@atlaskit/avatar-group';
6
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
7
+ import { Selection } from '@atlaskit/editor-prosemirror/state';
8
+ import { avatarContainer } from './styles';
9
+ import toAvatar from './to-avatar';
10
+ export const scrollToCollabCursor = (editorView, participants, sessionId, index, editorAnalyticsAPI) => {
11
+ const selectedUser = participants[index];
12
+ if (selectedUser && selectedUser.cursorPos !== undefined && selectedUser.sessionId !== sessionId) {
13
+ const {
14
+ state
15
+ } = editorView;
16
+ let tr = state.tr;
17
+ const analyticsPayload = {
18
+ action: ACTION.MATCHED,
19
+ actionSubject: ACTION_SUBJECT.SELECTION,
20
+ eventType: EVENT_TYPE.TRACK
21
+ };
22
+ tr.setSelection(Selection.near(tr.doc.resolve(selectedUser.cursorPos)));
23
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(analyticsPayload)(tr);
24
+ tr.scrollIntoView();
25
+ editorView.dispatch(tr);
26
+ if (!editorView.hasFocus()) {
27
+ editorView.focus();
28
+ }
29
+ }
30
+ };
31
+ export const Avatars = /*#__PURE__*/React.memo(props => {
32
+ var _props$participants;
33
+ const {
34
+ sessionId,
35
+ editorView,
36
+ featureFlags,
37
+ editorAPI
38
+ } = props;
39
+ const participants = (_props$participants = props.participants) === null || _props$participants === void 0 ? void 0 : _props$participants.toArray();
40
+ const avatars = participants.sort(p => p.sessionId === sessionId ? -1 : 1).map(participant => toAvatar(participant, editorAPI));
41
+ if (!avatars.length) {
42
+ return null;
43
+ }
44
+ return (
45
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
46
+ jsx("div", {
47
+ css: avatarContainer
48
+ }, jsx(AvatarGroup, {
49
+ appearance: "stack",
50
+ size: "medium",
51
+ data: avatars,
52
+ maxCount: 3,
53
+ onAvatarClick: (_event, _analytics, index) => {
54
+ if (!editorView) {
55
+ return;
56
+ }
57
+ const allowCollabAvatarScroll = featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.collabAvatarScroll;
58
+
59
+ // user does not need to scroll to their own position (index 0)
60
+ if (allowCollabAvatarScroll && index > 0) {
61
+ scrollToCollabCursor(editorView, participants, props.sessionId, index, props.editorAnalyticsAPI);
62
+ }
63
+ }
64
+ }), props.children)
65
+ );
66
+ });
@@ -0,0 +1,16 @@
1
+ /** @jsx jsx */
2
+ import { jsx } from '@emotion/react';
3
+ import { R100 } from '@atlaskit/theme/colors';
4
+ import { badge } from './styles';
5
+ export const ColoredAvatarItem = props => {
6
+ var _props$api, _props$api$collabEdit, _props$api$collabEdit2;
7
+ const color = (_props$api = props.api) === null || _props$api === void 0 ? void 0 : (_props$api$collabEdit = _props$api.collabEdit) === null || _props$api$collabEdit === void 0 ? void 0 : (_props$api$collabEdit2 = _props$api$collabEdit.actions) === null || _props$api$collabEdit2 === void 0 ? void 0 : _props$api$collabEdit2.getAvatarColor(props.sessionId).color.solid;
8
+ const avatar = props.name.substr(0, 1).toUpperCase();
9
+ return (
10
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
11
+ jsx("div", {
12
+ css: badge(color || R100),
13
+ "data-testid": "editor-collab-badge"
14
+ }, avatar)
15
+ );
16
+ };
@@ -0,0 +1,3 @@
1
+ import AvatarsWithPluginState from './avatars-with-plugin-state';
2
+ export default AvatarsWithPluginState;
3
+ export { default as AvatarGroupPluginWrapper } from './AvatarGroupPluginWrapper';
@@ -0,0 +1,35 @@
1
+ /** @jsx jsx */
2
+ import React, { Fragment } from 'react';
3
+ import { jsx } from '@emotion/react';
4
+ import { ToolbarButton } from '@atlaskit/editor-common/ui-menu';
5
+ import InviteTeamIcon from '@atlaskit/icon/glyph/editor/add';
6
+ import { inviteTeamWrapper } from './styles';
7
+ const ID = props => jsx(Fragment, null, props.children);
8
+ export const InviteToEditButton = props => {
9
+ const {
10
+ Component,
11
+ onClick,
12
+ selected,
13
+ title
14
+ } = props;
15
+ const iconBefore = React.useMemo(() => jsx(InviteTeamIcon, {
16
+ label: title
17
+ }), [title]);
18
+ if (!Component && !onClick) {
19
+ return null;
20
+ }
21
+ const Wrapper = Component ? Component : ID;
22
+ return (
23
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
24
+ jsx("div", {
25
+ css: inviteTeamWrapper
26
+ }, jsx(Wrapper, null, jsx(ToolbarButton, {
27
+ className: "invite-to-edit",
28
+ onClick: onClick,
29
+ selected: selected,
30
+ title: title,
31
+ titlePosition: "bottom",
32
+ iconBefore: iconBefore
33
+ })))
34
+ );
35
+ };
@@ -0,0 +1,46 @@
1
+ import { css } from '@emotion/react';
2
+ import { akEditorSmallZIndex, relativeFontSizeToBase16 } from '@atlaskit/editor-shared-styles';
3
+ import { N20 } from '@atlaskit/theme/colors';
4
+ export const inviteTeamWrapper = css`
5
+ background: ${`var(--ds-background-neutral, ${N20})`};
6
+ border-radius: 50%;
7
+ min-width: ${"var(--ds-space-400, 32px)"};
8
+ margin-left: ${"var(--ds-space-negative-050, -4px)"};
9
+ `;
10
+ export const avatarContainer = css`
11
+ margin-right: ${"var(--ds-space-100, 8px)"};
12
+ display: flex;
13
+ align-items: center;
14
+
15
+ // ED-13102: This is to override list styles that come from the
16
+ // .wiki-content class in Confluence that should not apply within
17
+ // the toolbar. Has to be extra specific to override.
18
+ && > ul {
19
+ list-style-type: none;
20
+ }
21
+
22
+ div:last-child button.invite-to-edit {
23
+ border-radius: 50%;
24
+ height: 32px;
25
+ width: 32px;
26
+ padding: ${"var(--ds-space-025, 2px)"};
27
+ }
28
+ `;
29
+ export const badge = color => css`
30
+ display: block;
31
+ position: absolute;
32
+ right: 1px;
33
+ bottom: 1px;
34
+ width: 13px;
35
+ height: 13px;
36
+ z-index: ${akEditorSmallZIndex};
37
+ border-radius: 3px;
38
+ background: ${color};
39
+ color: ${"var(--ds-text-inverse, #fff)"};
40
+ font-size: ${relativeFontSizeToBase16(9)};
41
+ line-height: 0;
42
+ padding-top: 7px;
43
+ text-align: center;
44
+ box-shadow: 0 0 1px ${"var(--ds-border-inverse, #fff)"};
45
+ box-sizing: border-box;
46
+ `;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import memoizeOne from 'memoize-one';
3
+ import { ColoredAvatarItem } from './colored-avatar-item';
4
+ const toAvatar = (participant, api) => ({
5
+ name: participant.name,
6
+ src: participant.avatar,
7
+ size: 'medium',
8
+ presence: /*#__PURE__*/React.createElement(ColoredAvatarItem, {
9
+ api: api,
10
+ name: participant.name,
11
+ sessionId: participant.sessionId
12
+ })
13
+ });
14
+ export default memoizeOne(toAvatar, function participantEquals([a], [b]) {
15
+ return a.name === b.name && a.avatar === b.avatar && a.sessionId === b.sessionId;
16
+ });
@@ -0,0 +1 @@
1
+ export { avatarGroupPlugin } from './plugin';
@@ -0,0 +1,8 @@
1
+ import { defineMessages } from 'react-intl-next';
2
+ export var avatarGroupMessages = defineMessages({
3
+ editors: {
4
+ id: 'fabric.editor.editors',
5
+ defaultMessage: 'Editors',
6
+ description: 'classifying the people that are currently editing the document'
7
+ }
8
+ });
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import AvatarGroupPluginWrapper from './ui/AvatarGroupPluginWrapper';
3
+ import AvatarsWithPluginState from './ui/avatars-with-plugin-state';
4
+ export var avatarGroupPlugin = function avatarGroupPlugin(_ref) {
5
+ var _api$featureFlags;
6
+ var props = _ref.config,
7
+ api = _ref.api;
8
+ var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
9
+ return {
10
+ name: 'avatarGroup',
11
+ primaryToolbarComponent: props.showAvatarGroup ? function (_ref2) {
12
+ var _api$analytics;
13
+ var editorView = _ref2.editorView,
14
+ popupsMountPoint = _ref2.popupsMountPoint,
15
+ popupsBoundariesElement = _ref2.popupsBoundariesElement,
16
+ popupsScrollableElement = _ref2.popupsScrollableElement,
17
+ disabled = _ref2.disabled,
18
+ isToolbarReducedSpacing = _ref2.isToolbarReducedSpacing,
19
+ eventDispatcher = _ref2.eventDispatcher,
20
+ dispatchAnalyticsEvent = _ref2.dispatchAnalyticsEvent;
21
+ return /*#__PURE__*/React.createElement(AvatarGroupPluginWrapper, {
22
+ dispatchAnalyticsEvent: dispatchAnalyticsEvent,
23
+ editorView: editorView,
24
+ eventDispatcher: eventDispatcher,
25
+ collabEdit: props === null || props === void 0 ? void 0 : props.collabEdit,
26
+ takeFullWidth: props === null || props === void 0 ? void 0 : props.takeFullWidth,
27
+ featureFlags: featureFlags,
28
+ editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions,
29
+ editorAPI: api
30
+ });
31
+ } : undefined,
32
+ actions: {
33
+ getToolbarItem: function getToolbarItem(_ref3) {
34
+ var _api$featureFlags$sha, _api$featureFlags2, _api$analytics2;
35
+ var editorView = _ref3.editorView,
36
+ inviteToEditHandler = _ref3.inviteToEditHandler,
37
+ isInviteToEditButtonSelected = _ref3.isInviteToEditButtonSelected,
38
+ inviteToEditComponent = _ref3.inviteToEditComponent;
39
+ return /*#__PURE__*/React.createElement(AvatarsWithPluginState, {
40
+ editorView: editorView,
41
+ featureFlags: (_api$featureFlags$sha = api === null || api === void 0 || (_api$featureFlags2 = api.featureFlags) === null || _api$featureFlags2 === void 0 ? void 0 : _api$featureFlags2.sharedState.currentState()) !== null && _api$featureFlags$sha !== void 0 ? _api$featureFlags$sha : {},
42
+ editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions,
43
+ editorAPI: api,
44
+ inviteToEditHandler: inviteToEditHandler,
45
+ isInviteToEditButtonSelected: isInviteToEditButtonSelected,
46
+ inviteToEditComponent: inviteToEditComponent
47
+ });
48
+ }
49
+ }
50
+ };
51
+ };
@@ -0,0 +1,46 @@
1
+ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
+ var _templateObject, _templateObject2;
3
+ /** @jsx jsx */
4
+ import { useEffect } from 'react';
5
+ import { css, jsx } from '@emotion/react';
6
+ import { useIntl } from 'react-intl-next';
7
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
8
+ import { avatarGroupMessages } from '../messages';
9
+ import AvatarsWithPluginState from './avatars-with-plugin-state';
10
+
11
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
12
+ var toolbarButtonWrapper = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n justify-content: flex-end;\n flex-grow: 0;\n align-items: center;\n & > div {\n margin-right: 0;\n }\n"])));
13
+
14
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
15
+ var toolbarButtonWrapperFullWidth = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n ", "\n flex-grow: 1;\n"])), toolbarButtonWrapper);
16
+ var AvatarGroupPluginWrapper = function AvatarGroupPluginWrapper(props) {
17
+ var dispatchAnalyticsEvent = props.dispatchAnalyticsEvent,
18
+ featureFlags = props.featureFlags;
19
+ var intl = useIntl();
20
+ useEffect(function () {
21
+ if (!dispatchAnalyticsEvent) {
22
+ return;
23
+ }
24
+ dispatchAnalyticsEvent({
25
+ action: ACTION.VIEWED,
26
+ actionSubject: ACTION_SUBJECT.BUTTON,
27
+ actionSubjectId: ACTION_SUBJECT_ID.AVATAR_GROUP_PLUGIN,
28
+ eventType: EVENT_TYPE.UI
29
+ });
30
+ }, [dispatchAnalyticsEvent]);
31
+ return jsx("div", {
32
+ "aria-label": intl.formatMessage(avatarGroupMessages.editors),
33
+ "data-testid": 'avatar-group-in-plugin',
34
+ css: props.takeFullWidth ? toolbarButtonWrapperFullWidth : toolbarButtonWrapper
35
+ }, jsx(AvatarsWithPluginState, {
36
+ editorView: props.editorView,
37
+ eventDispatcher: props.eventDispatcher,
38
+ inviteToEditComponent: props.collabEdit && props.collabEdit.inviteToEditComponent,
39
+ inviteToEditHandler: props.collabEdit && props.collabEdit.inviteToEditHandler,
40
+ isInviteToEditButtonSelected: props.collabEdit && props.collabEdit.isInviteToEditButtonSelected,
41
+ featureFlags: featureFlags,
42
+ editorAnalyticsAPI: props.editorAnalyticsAPI,
43
+ editorAPI: props.editorAPI
44
+ }));
45
+ };
46
+ export default AvatarGroupPluginWrapper;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { injectIntl } from 'react-intl-next';
3
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
4
+ import messages from '@atlaskit/editor-common/messages';
5
+ import { Avatars } from './avatars';
6
+ import { InviteToEditButton } from './invite-to-edit';
7
+ var AvatarsWithPluginState = function AvatarsWithPluginState(props) {
8
+ var title = props.intl.formatMessage(messages.inviteToEditButtonTitle);
9
+ var selected = props.isInviteToEditButtonSelected,
10
+ onClick = props.inviteToEditHandler,
11
+ Component = props.inviteToEditComponent,
12
+ editorView = props.editorView,
13
+ featureFlags = props.featureFlags,
14
+ editorAnalyticsAPI = props.editorAnalyticsAPI,
15
+ editorAPI = props.editorAPI;
16
+ var _useSharedPluginState = useSharedPluginState(editorAPI, ['collabEdit']),
17
+ collabEditState = _useSharedPluginState.collabEditState;
18
+ if (!collabEditState) {
19
+ return null;
20
+ }
21
+ return /*#__PURE__*/React.createElement(Avatars, {
22
+ sessionId: collabEditState.sessionId,
23
+ participants: collabEditState.activeParticipants,
24
+ editorView: editorView,
25
+ featureFlags: featureFlags,
26
+ editorAnalyticsAPI: editorAnalyticsAPI,
27
+ editorAPI: editorAPI
28
+ }, /*#__PURE__*/React.createElement(InviteToEditButton, {
29
+ title: title,
30
+ selected: selected,
31
+ onClick: onClick,
32
+ Component: Component
33
+ }));
34
+ };
35
+ export default injectIntl(AvatarsWithPluginState);
@@ -0,0 +1,66 @@
1
+ /** @jsx jsx */
2
+
3
+ import React from 'react';
4
+ import { jsx } from '@emotion/react';
5
+ import AvatarGroup from '@atlaskit/avatar-group';
6
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
7
+ import { Selection } from '@atlaskit/editor-prosemirror/state';
8
+ import { avatarContainer } from './styles';
9
+ import toAvatar from './to-avatar';
10
+ export var scrollToCollabCursor = function scrollToCollabCursor(editorView, participants, sessionId, index, editorAnalyticsAPI) {
11
+ var selectedUser = participants[index];
12
+ if (selectedUser && selectedUser.cursorPos !== undefined && selectedUser.sessionId !== sessionId) {
13
+ var state = editorView.state;
14
+ var tr = state.tr;
15
+ var analyticsPayload = {
16
+ action: ACTION.MATCHED,
17
+ actionSubject: ACTION_SUBJECT.SELECTION,
18
+ eventType: EVENT_TYPE.TRACK
19
+ };
20
+ tr.setSelection(Selection.near(tr.doc.resolve(selectedUser.cursorPos)));
21
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(analyticsPayload)(tr);
22
+ tr.scrollIntoView();
23
+ editorView.dispatch(tr);
24
+ if (!editorView.hasFocus()) {
25
+ editorView.focus();
26
+ }
27
+ }
28
+ };
29
+ export var Avatars = /*#__PURE__*/React.memo(function (props) {
30
+ var _props$participants;
31
+ var sessionId = props.sessionId,
32
+ editorView = props.editorView,
33
+ featureFlags = props.featureFlags,
34
+ editorAPI = props.editorAPI;
35
+ var participants = (_props$participants = props.participants) === null || _props$participants === void 0 ? void 0 : _props$participants.toArray();
36
+ var avatars = participants.sort(function (p) {
37
+ return p.sessionId === sessionId ? -1 : 1;
38
+ }).map(function (participant) {
39
+ return toAvatar(participant, editorAPI);
40
+ });
41
+ if (!avatars.length) {
42
+ return null;
43
+ }
44
+ return (
45
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
46
+ jsx("div", {
47
+ css: avatarContainer
48
+ }, jsx(AvatarGroup, {
49
+ appearance: "stack",
50
+ size: "medium",
51
+ data: avatars,
52
+ maxCount: 3,
53
+ onAvatarClick: function onAvatarClick(_event, _analytics, index) {
54
+ if (!editorView) {
55
+ return;
56
+ }
57
+ var allowCollabAvatarScroll = featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.collabAvatarScroll;
58
+
59
+ // user does not need to scroll to their own position (index 0)
60
+ if (allowCollabAvatarScroll && index > 0) {
61
+ scrollToCollabCursor(editorView, participants, props.sessionId, index, props.editorAnalyticsAPI);
62
+ }
63
+ }
64
+ }), props.children)
65
+ );
66
+ });
@@ -0,0 +1,16 @@
1
+ /** @jsx jsx */
2
+ import { jsx } from '@emotion/react';
3
+ import { R100 } from '@atlaskit/theme/colors';
4
+ import { badge } from './styles';
5
+ export var ColoredAvatarItem = function ColoredAvatarItem(props) {
6
+ var _props$api;
7
+ var color = (_props$api = props.api) === null || _props$api === void 0 || (_props$api = _props$api.collabEdit) === null || _props$api === void 0 || (_props$api = _props$api.actions) === null || _props$api === void 0 ? void 0 : _props$api.getAvatarColor(props.sessionId).color.solid;
8
+ var avatar = props.name.substr(0, 1).toUpperCase();
9
+ return (
10
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
11
+ jsx("div", {
12
+ css: badge(color || R100),
13
+ "data-testid": "editor-collab-badge"
14
+ }, avatar)
15
+ );
16
+ };
@@ -0,0 +1,3 @@
1
+ import AvatarsWithPluginState from './avatars-with-plugin-state';
2
+ export default AvatarsWithPluginState;
3
+ export { default as AvatarGroupPluginWrapper } from './AvatarGroupPluginWrapper';
@@ -0,0 +1,37 @@
1
+ /** @jsx jsx */
2
+ import React, { Fragment } from 'react';
3
+ import { jsx } from '@emotion/react';
4
+ import { ToolbarButton } from '@atlaskit/editor-common/ui-menu';
5
+ import InviteTeamIcon from '@atlaskit/icon/glyph/editor/add';
6
+ import { inviteTeamWrapper } from './styles';
7
+ var ID = function ID(props) {
8
+ return jsx(Fragment, null, props.children);
9
+ };
10
+ export var InviteToEditButton = function InviteToEditButton(props) {
11
+ var Component = props.Component,
12
+ onClick = props.onClick,
13
+ selected = props.selected,
14
+ title = props.title;
15
+ var iconBefore = React.useMemo(function () {
16
+ return jsx(InviteTeamIcon, {
17
+ label: title
18
+ });
19
+ }, [title]);
20
+ if (!Component && !onClick) {
21
+ return null;
22
+ }
23
+ var Wrapper = Component ? Component : ID;
24
+ return (
25
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
26
+ jsx("div", {
27
+ css: inviteTeamWrapper
28
+ }, jsx(Wrapper, null, jsx(ToolbarButton, {
29
+ className: "invite-to-edit",
30
+ onClick: onClick,
31
+ selected: selected,
32
+ title: title,
33
+ titlePosition: "bottom",
34
+ iconBefore: iconBefore
35
+ })))
36
+ );
37
+ };
@@ -0,0 +1,10 @@
1
+ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
+ var _templateObject, _templateObject2, _templateObject3;
3
+ import { css } from '@emotion/react';
4
+ import { akEditorSmallZIndex, relativeFontSizeToBase16 } from '@atlaskit/editor-shared-styles';
5
+ import { N20 } from '@atlaskit/theme/colors';
6
+ export var inviteTeamWrapper = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n background: ", ";\n border-radius: 50%;\n min-width: ", ";\n margin-left: ", ";\n"])), "var(--ds-background-neutral, ".concat(N20, ")"), "var(--ds-space-400, 32px)", "var(--ds-space-negative-050, -4px)");
7
+ export var avatarContainer = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n margin-right: ", ";\n display: flex;\n align-items: center;\n\n // ED-13102: This is to override list styles that come from the\n // .wiki-content class in Confluence that should not apply within\n // the toolbar. Has to be extra specific to override.\n && > ul {\n list-style-type: none;\n }\n\n div:last-child button.invite-to-edit {\n border-radius: 50%;\n height: 32px;\n width: 32px;\n padding: ", ";\n }\n"])), "var(--ds-space-100, 8px)", "var(--ds-space-025, 2px)");
8
+ export var badge = function badge(color) {
9
+ return css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n display: block;\n position: absolute;\n right: 1px;\n bottom: 1px;\n width: 13px;\n height: 13px;\n z-index: ", ";\n border-radius: 3px;\n background: ", ";\n color: ", ";\n font-size: ", ";\n line-height: 0;\n padding-top: 7px;\n text-align: center;\n box-shadow: 0 0 1px ", ";\n box-sizing: border-box;\n"])), akEditorSmallZIndex, color, "var(--ds-text-inverse, #fff)", relativeFontSizeToBase16(9), "var(--ds-border-inverse, #fff)");
10
+ };
@@ -0,0 +1,23 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import React from 'react';
3
+ import memoizeOne from 'memoize-one';
4
+ import { ColoredAvatarItem } from './colored-avatar-item';
5
+ var toAvatar = function toAvatar(participant, api) {
6
+ return {
7
+ name: participant.name,
8
+ src: participant.avatar,
9
+ size: 'medium',
10
+ presence: /*#__PURE__*/React.createElement(ColoredAvatarItem, {
11
+ api: api,
12
+ name: participant.name,
13
+ sessionId: participant.sessionId
14
+ })
15
+ };
16
+ };
17
+ export default memoizeOne(toAvatar, function participantEquals(_ref, _ref2) {
18
+ var _ref3 = _slicedToArray(_ref, 1),
19
+ a = _ref3[0];
20
+ var _ref4 = _slicedToArray(_ref2, 1),
21
+ b = _ref4[0];
22
+ return a.name === b.name && a.avatar === b.avatar && a.sessionId === b.sessionId;
23
+ });
@@ -0,0 +1,2 @@
1
+ export type { AvatarGroupPlugin } from './plugin';
2
+ export { avatarGroupPlugin } from './plugin';
@@ -0,0 +1,7 @@
1
+ export declare const avatarGroupMessages: {
2
+ editors: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ };
@@ -0,0 +1,27 @@
1
+ /// <reference types="react" />
2
+ import type { CollabEditOptions, CollabInviteToEditProps } from '@atlaskit/editor-common/collab';
3
+ import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
4
+ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
5
+ import type { CollabEditPlugin } from '@atlaskit/editor-plugin-collab-edit';
6
+ import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
7
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
8
+ type Config = {
9
+ collabEdit?: CollabEditOptions;
10
+ takeFullWidth: boolean;
11
+ showAvatarGroup?: boolean;
12
+ };
13
+ export type AvatarGroupPlugin = NextEditorPlugin<'avatarGroup', {
14
+ pluginConfiguration: Config;
15
+ dependencies: [
16
+ OptionalPlugin<FeatureFlagsPlugin>,
17
+ OptionalPlugin<AnalyticsPlugin>,
18
+ OptionalPlugin<CollabEditPlugin>
19
+ ];
20
+ actions: {
21
+ getToolbarItem: ({ editorView, inviteToEditHandler, isInviteToEditButtonSelected, inviteToEditComponent, }: {
22
+ editorView: EditorView;
23
+ } & CollabInviteToEditProps) => JSX.Element | null;
24
+ };
25
+ }>;
26
+ export declare const avatarGroupPlugin: AvatarGroupPlugin;
27
+ export {};
@@ -0,0 +1,18 @@
1
+ import { jsx } from '@emotion/react';
2
+ import type { DispatchAnalyticsEvent, EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
+ import type { CollabEditOptions } from '@atlaskit/editor-common/collab';
4
+ import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
5
+ import type { ExtractInjectionAPI, FeatureFlags } from '@atlaskit/editor-common/types';
6
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
+ import type { AvatarGroupPlugin } from '../index';
8
+ declare const AvatarGroupPluginWrapper: (props: {
9
+ collabEdit?: CollabEditOptions | undefined;
10
+ editorView: EditorView;
11
+ eventDispatcher: EventDispatcher<any>;
12
+ dispatchAnalyticsEvent?: DispatchAnalyticsEvent | undefined;
13
+ takeFullWidth: boolean;
14
+ featureFlags: FeatureFlags;
15
+ editorAnalyticsAPI: EditorAnalyticsAPI | undefined;
16
+ editorAPI: ExtractInjectionAPI<AvatarGroupPlugin> | undefined;
17
+ }) => jsx.JSX.Element;
18
+ export default AvatarGroupPluginWrapper;
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+ import type { WrappedComponentProps } from 'react-intl-next';
3
+ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
4
+ import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
5
+ import type { FeatureFlags, OptionalPlugin, PublicPluginAPI } from '@atlaskit/editor-common/types';
6
+ import type { CollabEditPlugin, CollabInviteToEditProps } from '@atlaskit/editor-plugin-collab-edit';
7
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
8
+ export type AvatarsWithPluginStateProps = {
9
+ editorView?: EditorView;
10
+ eventDispatcher?: EventDispatcher;
11
+ featureFlags: FeatureFlags;
12
+ editorAnalyticsAPI: EditorAnalyticsAPI | undefined;
13
+ editorAPI: PublicPluginAPI<[OptionalPlugin<CollabEditPlugin>]> | undefined;
14
+ } & CollabInviteToEditProps;
15
+ declare const _default: React.FC<import("react-intl-next").WithIntlProps<{
16
+ editorView?: EditorView | undefined;
17
+ eventDispatcher?: EventDispatcher<any> | undefined;
18
+ featureFlags: FeatureFlags;
19
+ editorAnalyticsAPI: EditorAnalyticsAPI | undefined;
20
+ editorAPI: PublicPluginAPI<[OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"collabEdit", {
21
+ pluginConfiguration: import("@atlaskit/editor-plugin-collab-edit").PrivateCollabEditOptions;
22
+ dependencies: [OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"featureFlags", {
23
+ pluginConfiguration: FeatureFlags;
24
+ sharedState: FeatureFlags;
25
+ }, FeatureFlags>>, OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"analytics", {
26
+ pluginConfiguration: import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions;
27
+ sharedState: {
28
+ createAnalyticsEvent: import("@atlaskit/analytics-next").CreateUIAnalyticsEvent | null;
29
+ attachAnalyticsEvent: import("@atlaskit/editor-plugin-analytics").CreateAttachPayloadIntoTransaction | null;
30
+ performanceTracking: import("@atlaskit/editor-common/types").PerformanceTracking | undefined;
31
+ };
32
+ dependencies: [OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"featureFlags", {
33
+ pluginConfiguration: FeatureFlags;
34
+ sharedState: FeatureFlags;
35
+ }, FeatureFlags>>];
36
+ actions: EditorAnalyticsAPI;
37
+ }, import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions>>];
38
+ sharedState: import("@atlaskit/editor-plugin-collab-edit").CollabEditPluginSharedState;
39
+ actions: {
40
+ getAvatarColor: (str: string) => {
41
+ index: number;
42
+ color: import("@atlaskit/editor-common/collab").Color;
43
+ };
44
+ };
45
+ }, import("@atlaskit/editor-plugin-collab-edit").PrivateCollabEditOptions>>]> | undefined;
46
+ } & CollabInviteToEditProps & WrappedComponentProps<"intl">>> & {
47
+ WrappedComponent: React.ComponentType<{
48
+ editorView?: EditorView | undefined;
49
+ eventDispatcher?: EventDispatcher<any> | undefined;
50
+ featureFlags: FeatureFlags;
51
+ editorAnalyticsAPI: EditorAnalyticsAPI | undefined;
52
+ editorAPI: PublicPluginAPI<[OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"collabEdit", {
53
+ pluginConfiguration: import("@atlaskit/editor-plugin-collab-edit").PrivateCollabEditOptions;
54
+ dependencies: [OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"featureFlags", {
55
+ pluginConfiguration: FeatureFlags;
56
+ sharedState: FeatureFlags;
57
+ }, FeatureFlags>>, OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"analytics", {
58
+ pluginConfiguration: import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions;
59
+ sharedState: {
60
+ createAnalyticsEvent: import("@atlaskit/analytics-next").CreateUIAnalyticsEvent | null;
61
+ attachAnalyticsEvent: import("@atlaskit/editor-plugin-analytics").CreateAttachPayloadIntoTransaction | null;
62
+ performanceTracking: import("@atlaskit/editor-common/types").PerformanceTracking | undefined;
63
+ };
64
+ dependencies: [OptionalPlugin<import("@atlaskit/editor-common/types").NextEditorPluginFunctionOptionalConfigDefinition<"featureFlags", {
65
+ pluginConfiguration: FeatureFlags;
66
+ sharedState: FeatureFlags;
67
+ }, FeatureFlags>>];
68
+ actions: EditorAnalyticsAPI;
69
+ }, import("@atlaskit/editor-plugin-analytics").AnalyticsPluginOptions>>];
70
+ sharedState: import("@atlaskit/editor-plugin-collab-edit").CollabEditPluginSharedState;
71
+ actions: {
72
+ getAvatarColor: (str: string) => {
73
+ index: number;
74
+ color: import("@atlaskit/editor-common/collab").Color;
75
+ };
76
+ };
77
+ }, import("@atlaskit/editor-plugin-collab-edit").PrivateCollabEditOptions>>]> | undefined;
78
+ } & CollabInviteToEditProps & WrappedComponentProps<"intl">>;
79
+ };
80
+ export default _default;