@atlaskit/editor-common 76.33.2 → 76.35.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.
- package/CHANGELOG.md +54 -0
- package/dist/cjs/collab/index.js +27 -2
- package/dist/cjs/core-utils/document-logger.js +171 -0
- package/dist/cjs/core-utils/index.js +8 -1
- package/dist/cjs/extensibility/Extension/Extension/index.js +151 -0
- package/dist/cjs/extensibility/Extension/Extension/styles.js +17 -0
- package/dist/cjs/extensibility/Extension/InlineExtension/index.js +50 -0
- package/dist/cjs/extensibility/Extension/InlineExtension/styles.js +12 -0
- package/dist/cjs/extensibility/Extension/Lozenge.js +95 -0
- package/dist/cjs/extensibility/Extension/styles.js +30 -0
- package/dist/cjs/extensibility/Extension.js +79 -0
- package/dist/cjs/extensibility/ExtensionComponent.js +252 -0
- package/dist/cjs/extensibility/ExtensionNodeWrapper.js +21 -0
- package/dist/cjs/extensibility/MultiBodiedExtension/index.js +264 -0
- package/dist/cjs/extensibility/extensionNodeView.js +91 -0
- package/dist/cjs/extensibility/index.js +42 -0
- package/dist/cjs/extensibility/types.js +5 -0
- package/dist/cjs/media-inline/media-inline-image-card.js +24 -19
- package/dist/cjs/monitoring/error.js +3 -2
- package/dist/cjs/ui/DropList/index.js +1 -1
- package/dist/cjs/utils/index.js +7 -0
- package/dist/cjs/utils/insert-node-into-ordered-list.js +91 -0
- package/dist/es2019/collab/index.js +54 -1
- package/dist/es2019/core-utils/document-logger.js +161 -0
- package/dist/es2019/core-utils/index.js +2 -1
- package/dist/es2019/extensibility/Extension/Extension/index.js +155 -0
- package/dist/es2019/extensibility/Extension/Extension/styles.js +42 -0
- package/dist/es2019/extensibility/Extension/InlineExtension/index.js +26 -0
- package/dist/es2019/extensibility/Extension/InlineExtension/styles.js +26 -0
- package/dist/es2019/extensibility/Extension/Lozenge.js +71 -0
- package/dist/es2019/extensibility/Extension/styles.js +62 -0
- package/dist/es2019/extensibility/Extension.js +52 -0
- package/dist/es2019/extensibility/ExtensionComponent.js +204 -0
- package/dist/es2019/extensibility/ExtensionNodeWrapper.js +13 -0
- package/dist/es2019/extensibility/MultiBodiedExtension/index.js +283 -0
- package/dist/es2019/extensibility/extensionNodeView.js +62 -0
- package/dist/es2019/extensibility/index.js +4 -0
- package/dist/es2019/extensibility/types.js +1 -0
- package/dist/es2019/media-inline/media-inline-image-card.js +24 -19
- package/dist/es2019/monitoring/error.js +3 -2
- package/dist/es2019/ui/DropList/index.js +1 -1
- package/dist/es2019/utils/index.js +1 -0
- package/dist/es2019/utils/insert-node-into-ordered-list.js +84 -0
- package/dist/esm/collab/index.js +23 -1
- package/dist/esm/core-utils/document-logger.js +165 -0
- package/dist/esm/core-utils/index.js +2 -1
- package/dist/esm/extensibility/Extension/Extension/index.js +146 -0
- package/dist/esm/extensibility/Extension/Extension/styles.js +10 -0
- package/dist/esm/extensibility/Extension/InlineExtension/index.js +43 -0
- package/dist/esm/extensibility/Extension/InlineExtension/styles.js +5 -0
- package/dist/esm/extensibility/Extension/Lozenge.js +90 -0
- package/dist/esm/extensibility/Extension/styles.js +11 -0
- package/dist/esm/extensibility/Extension.js +69 -0
- package/dist/esm/extensibility/ExtensionComponent.js +243 -0
- package/dist/esm/extensibility/ExtensionNodeWrapper.js +14 -0
- package/dist/esm/extensibility/MultiBodiedExtension/index.js +257 -0
- package/dist/esm/extensibility/extensionNodeView.js +83 -0
- package/dist/esm/extensibility/index.js +4 -0
- package/dist/esm/extensibility/types.js +1 -0
- package/dist/esm/media-inline/media-inline-image-card.js +24 -19
- package/dist/esm/monitoring/error.js +3 -2
- package/dist/esm/ui/DropList/index.js +1 -1
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/insert-node-into-ordered-list.js +84 -0
- package/dist/types/collab/index.d.ts +7 -0
- package/dist/types/core-utils/document-logger.d.ts +6 -0
- package/dist/types/core-utils/index.d.ts +1 -0
- package/dist/types/extensibility/Extension/Extension/index.d.ts +108 -0
- package/dist/types/extensibility/Extension/Extension/styles.d.ts +5 -0
- package/dist/types/extensibility/Extension/InlineExtension/index.d.ts +12 -0
- package/dist/types/extensibility/Extension/InlineExtension/styles.d.ts +1 -0
- package/dist/types/extensibility/Extension/Lozenge.d.ts +14 -0
- package/dist/types/extensibility/Extension/styles.d.ts +7 -0
- package/dist/types/extensibility/Extension.d.ts +29 -0
- package/dist/types/extensibility/ExtensionComponent.d.ts +53 -0
- package/dist/types/extensibility/ExtensionNodeWrapper.d.ts +14 -0
- package/dist/types/extensibility/MultiBodiedExtension/index.d.ts +26 -0
- package/dist/types/extensibility/extensionNodeView.d.ts +31 -0
- package/dist/types/extensibility/index.d.ts +4 -0
- package/dist/types/extensibility/types.d.ts +6 -0
- package/dist/types/extensions/types/extension-handler.d.ts +2 -0
- package/dist/types/media-inline/media-inline-image-card.d.ts +3 -2
- package/dist/types/media-inline/types.d.ts +6 -2
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/next-editor-plugin.d.ts +0 -1
- package/dist/types/ui/DropList/index.d.ts +1 -1
- package/dist/types/ui-menu/ColorPickerButton/index.d.ts +1 -1
- package/dist/types/ui-menu/ToolbarButton/index.d.ts +1 -1
- package/dist/types/utils/index.d.ts +1 -0
- package/dist/types/utils/insert-node-into-ordered-list.d.ts +3 -0
- package/dist/types-ts4.5/collab/index.d.ts +7 -0
- package/dist/types-ts4.5/core-utils/document-logger.d.ts +6 -0
- package/dist/types-ts4.5/core-utils/index.d.ts +1 -0
- package/dist/types-ts4.5/extensibility/Extension/Extension/index.d.ts +108 -0
- package/dist/types-ts4.5/extensibility/Extension/Extension/styles.d.ts +5 -0
- package/dist/types-ts4.5/extensibility/Extension/InlineExtension/index.d.ts +12 -0
- package/dist/types-ts4.5/extensibility/Extension/InlineExtension/styles.d.ts +1 -0
- package/dist/types-ts4.5/extensibility/Extension/Lozenge.d.ts +14 -0
- package/dist/types-ts4.5/extensibility/Extension/styles.d.ts +7 -0
- package/dist/types-ts4.5/extensibility/Extension.d.ts +29 -0
- package/dist/types-ts4.5/extensibility/ExtensionComponent.d.ts +53 -0
- package/dist/types-ts4.5/extensibility/ExtensionNodeWrapper.d.ts +14 -0
- package/dist/types-ts4.5/extensibility/MultiBodiedExtension/index.d.ts +26 -0
- package/dist/types-ts4.5/extensibility/extensionNodeView.d.ts +31 -0
- package/dist/types-ts4.5/extensibility/index.d.ts +4 -0
- package/dist/types-ts4.5/extensibility/types.d.ts +8 -0
- package/dist/types-ts4.5/extensions/types/extension-handler.d.ts +2 -0
- package/dist/types-ts4.5/media-inline/media-inline-image-card.d.ts +3 -2
- package/dist/types-ts4.5/media-inline/types.d.ts +6 -2
- package/dist/types-ts4.5/types/index.d.ts +1 -1
- package/dist/types-ts4.5/types/next-editor-plugin.d.ts +0 -3
- package/dist/types-ts4.5/ui/DropList/index.d.ts +1 -1
- package/dist/types-ts4.5/ui-menu/ColorPickerButton/index.d.ts +1 -1
- package/dist/types-ts4.5/ui-menu/ToolbarButton/index.d.ts +1 -1
- package/dist/types-ts4.5/utils/index.d.ts +1 -0
- package/dist/types-ts4.5/utils/insert-node-into-ordered-list.d.ts +3 -0
- package/extensibility/package.json +15 -0
- package/package.json +6 -5
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
/** @jsx jsx */
|
|
3
|
+
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { jsx } from '@emotion/react';
|
|
6
|
+
import classnames from 'classnames';
|
|
7
|
+
import { WithPluginState } from '../../..//with-plugin-state';
|
|
8
|
+
import { useSharedPluginState } from '../../../hooks';
|
|
9
|
+
import { overflowShadow } from '../../../ui';
|
|
10
|
+
import { calculateBreakoutStyles } from '../../../utils';
|
|
11
|
+
import ExtensionLozenge from '../Lozenge';
|
|
12
|
+
import { overlay } from '../styles';
|
|
13
|
+
import { content, contentWrapper, header, widerLayoutClassName, wrapperStyle } from './styles';
|
|
14
|
+
function ExtensionWithPluginState(props) {
|
|
15
|
+
const {
|
|
16
|
+
node,
|
|
17
|
+
handleContentDOMRef,
|
|
18
|
+
children,
|
|
19
|
+
widthState = {
|
|
20
|
+
width: 0
|
|
21
|
+
},
|
|
22
|
+
handleRef,
|
|
23
|
+
shadowClassNames,
|
|
24
|
+
hideFrame,
|
|
25
|
+
editorAppearance
|
|
26
|
+
} = props;
|
|
27
|
+
const hasBody = ['bodiedExtension', 'multiBodiedExtension'].includes(node.type.name);
|
|
28
|
+
const isMobile = editorAppearance === 'mobile';
|
|
29
|
+
const hasChildren = !!children;
|
|
30
|
+
const removeBorder = hideFrame && !isMobile && !hasBody || false;
|
|
31
|
+
const {
|
|
32
|
+
getPos,
|
|
33
|
+
view
|
|
34
|
+
} = props;
|
|
35
|
+
const isTopLevelNode = React.useMemo(() => {
|
|
36
|
+
const pos = typeof getPos === 'function' ? getPos() : undefined;
|
|
37
|
+
return typeof pos !== 'undefined' && !isNaN(pos) && view.state.doc.resolve(pos).depth === 0;
|
|
38
|
+
return false;
|
|
39
|
+
}, [view, getPos]);
|
|
40
|
+
const shouldBreakout =
|
|
41
|
+
// Extension should breakout when the layout is set to 'full-width' or 'wide'.
|
|
42
|
+
['full-width', 'wide'].includes(node.attrs.layout) &&
|
|
43
|
+
// Extension breakout state should only be respected for top level nodes.
|
|
44
|
+
isTopLevelNode &&
|
|
45
|
+
// Extension breakout state should not be respected when the editor appearance is full-width mode
|
|
46
|
+
editorAppearance !== 'full-width';
|
|
47
|
+
const classNames = classnames('extension-container', 'block', shadowClassNames, {
|
|
48
|
+
'with-overlay': !hasBody,
|
|
49
|
+
'without-frame': removeBorder,
|
|
50
|
+
[widerLayoutClassName]: shouldBreakout
|
|
51
|
+
});
|
|
52
|
+
const headerClassNames = classnames({
|
|
53
|
+
'with-children': hasChildren,
|
|
54
|
+
'without-frame': removeBorder
|
|
55
|
+
});
|
|
56
|
+
let customContainerStyles = {
|
|
57
|
+
width: '100%'
|
|
58
|
+
};
|
|
59
|
+
let newContentStyles = {};
|
|
60
|
+
if (shouldBreakout) {
|
|
61
|
+
const {
|
|
62
|
+
type,
|
|
63
|
+
...breakoutStyles
|
|
64
|
+
} = calculateBreakoutStyles({
|
|
65
|
+
mode: node.attrs.layout,
|
|
66
|
+
widthStateWidth: widthState.width,
|
|
67
|
+
widthStateLineLength: widthState.lineLength
|
|
68
|
+
});
|
|
69
|
+
newContentStyles = {
|
|
70
|
+
...breakoutStyles
|
|
71
|
+
};
|
|
72
|
+
customContainerStyles = breakoutStyles;
|
|
73
|
+
}
|
|
74
|
+
newContentStyles = {
|
|
75
|
+
...newContentStyles,
|
|
76
|
+
...contentWrapper
|
|
77
|
+
};
|
|
78
|
+
return jsx("div", {
|
|
79
|
+
ref: handleRef,
|
|
80
|
+
"data-layout": node.attrs.layout,
|
|
81
|
+
className: classNames,
|
|
82
|
+
css: wrapperStyle,
|
|
83
|
+
style: customContainerStyles
|
|
84
|
+
}, jsx("div", {
|
|
85
|
+
className: `extension-overflow-wrapper ${hasBody ? 'with-body' : ''}`
|
|
86
|
+
}, jsx("div", {
|
|
87
|
+
css: overlay,
|
|
88
|
+
className: "extension-overlay"
|
|
89
|
+
}), jsx("div", {
|
|
90
|
+
css: header,
|
|
91
|
+
contentEditable: false,
|
|
92
|
+
className: headerClassNames
|
|
93
|
+
}, !removeBorder && jsx(ExtensionLozenge, {
|
|
94
|
+
node: node
|
|
95
|
+
}), children), hasBody && jsx("div", {
|
|
96
|
+
css: newContentStyles
|
|
97
|
+
}, jsx("div", {
|
|
98
|
+
css: content,
|
|
99
|
+
ref: handleContentDOMRef,
|
|
100
|
+
className: "extension-content block"
|
|
101
|
+
}))));
|
|
102
|
+
}
|
|
103
|
+
const Extension = props => {
|
|
104
|
+
// TODO: ED-17836 This code is here because confluence injects
|
|
105
|
+
// the `editor-referentiality` plugin via `dangerouslyAppendPlugins`
|
|
106
|
+
// which cannot access the `pluginInjectionApi`. When we move
|
|
107
|
+
// Confluence to using presets we can remove this workaround.
|
|
108
|
+
const {
|
|
109
|
+
pluginInjectionApi
|
|
110
|
+
} = props;
|
|
111
|
+
return pluginInjectionApi === undefined ? jsx(ExtensionDeprecated, props) : jsx(ExtensionWithSharedState, props);
|
|
112
|
+
};
|
|
113
|
+
const ExtensionWithSharedState = props => {
|
|
114
|
+
const {
|
|
115
|
+
pluginInjectionApi
|
|
116
|
+
} = props;
|
|
117
|
+
const {
|
|
118
|
+
widthState
|
|
119
|
+
} = useSharedPluginState(pluginInjectionApi, ['width']);
|
|
120
|
+
return jsx(ExtensionWithPluginState, _extends({
|
|
121
|
+
widthState: widthState
|
|
122
|
+
}, props));
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// TODO: ED-17836 This code is here because Confluence injects
|
|
126
|
+
// the `editor-referentiality` plugin via `dangerouslyAppendPlugins`
|
|
127
|
+
// which cannot access the `pluginInjectionApi`. When we move
|
|
128
|
+
// Confluence to using presets we can remove this workaround.
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
const widthPluginKey = {
|
|
131
|
+
key: 'widthPlugin$',
|
|
132
|
+
getState: state => {
|
|
133
|
+
return state['widthPlugin$'];
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const ExtensionDeprecated = props => {
|
|
137
|
+
return jsx(WithPluginState, {
|
|
138
|
+
editorView: props.view,
|
|
139
|
+
plugins: {
|
|
140
|
+
widthState: widthPluginKey
|
|
141
|
+
},
|
|
142
|
+
render: ({
|
|
143
|
+
widthState
|
|
144
|
+
}) => jsx(ExtensionWithPluginState, _extends({
|
|
145
|
+
widthState: widthState
|
|
146
|
+
}, props))
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* End workaround
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
export default overflowShadow(Extension, {
|
|
154
|
+
overflowSelector: '.extension-overflow-wrapper'
|
|
155
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
import { N30 } from '@atlaskit/theme/colors';
|
|
3
|
+
import { padding, wrapperDefault } from '../styles';
|
|
4
|
+
export const widerLayoutClassName = 'wider-layout';
|
|
5
|
+
export const wrapperStyle = css`
|
|
6
|
+
${wrapperDefault}
|
|
7
|
+
|
|
8
|
+
&.without-frame {
|
|
9
|
+
background: transparent;
|
|
10
|
+
}
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
width: 100%;
|
|
13
|
+
|
|
14
|
+
.extension-overflow-wrapper:not(.with-body) {
|
|
15
|
+
overflow-x: auto;
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
export const header = css`
|
|
19
|
+
padding: ${padding / 2}px ${padding / 2}px 0px;
|
|
20
|
+
vertical-align: middle;
|
|
21
|
+
|
|
22
|
+
&.with-children:not(.without-frame) {
|
|
23
|
+
padding: ${"var(--ds-space-050, 4px)"} ${"var(--ds-space-100, 8px)"}
|
|
24
|
+
${"var(--ds-space-100, 8px)"};
|
|
25
|
+
}
|
|
26
|
+
&.without-frame {
|
|
27
|
+
padding: 0;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
export const content = css`
|
|
31
|
+
padding: ${padding}px;
|
|
32
|
+
background: ${"var(--ds-surface, white)"};
|
|
33
|
+
border: 1px solid ${`var(--ds-border, ${N30})`};
|
|
34
|
+
border-radius: ${"var(--ds-border-radius, 3px)"};
|
|
35
|
+
cursor: initial;
|
|
36
|
+
width: 100%;
|
|
37
|
+
`;
|
|
38
|
+
export const contentWrapper = css`
|
|
39
|
+
padding: 0 ${padding}px ${padding}px;
|
|
40
|
+
display: flex;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
`;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Component } from 'react';
|
|
4
|
+
import { jsx } from '@emotion/react';
|
|
5
|
+
import ExtensionLozenge from '../Lozenge';
|
|
6
|
+
import { overlay } from '../styles';
|
|
7
|
+
import { wrapperStyle } from './styles';
|
|
8
|
+
export default class InlineExtension extends Component {
|
|
9
|
+
render() {
|
|
10
|
+
const {
|
|
11
|
+
node,
|
|
12
|
+
children
|
|
13
|
+
} = this.props;
|
|
14
|
+
const hasChildren = !!children;
|
|
15
|
+
const className = hasChildren ? 'with-overlay with-children' : 'with-overlay';
|
|
16
|
+
return jsx("div", {
|
|
17
|
+
css: wrapperStyle,
|
|
18
|
+
className: `extension-container inline ${className}`
|
|
19
|
+
}, jsx("div", {
|
|
20
|
+
css: overlay,
|
|
21
|
+
className: "extension-overlay"
|
|
22
|
+
}), children ? children : jsx(ExtensionLozenge, {
|
|
23
|
+
node: node
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
import { wrapperDefault } from '../styles';
|
|
3
|
+
export const wrapperStyle = css`
|
|
4
|
+
${wrapperDefault}
|
|
5
|
+
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
display: inline-flex;
|
|
8
|
+
margin: 1px 1px ${"var(--ds-space-050, 4px)"};
|
|
9
|
+
|
|
10
|
+
> img {
|
|
11
|
+
border-radius: ${"var(--ds-border-radius, 3px)"};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&::after,
|
|
15
|
+
&::before {
|
|
16
|
+
vertical-align: text-top;
|
|
17
|
+
display: inline-block;
|
|
18
|
+
width: 1px;
|
|
19
|
+
content: '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&.with-children {
|
|
23
|
+
padding: 0;
|
|
24
|
+
background: ${"var(--ds-background-neutral-subtle, white)"};
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
/** @jsx jsx */
|
|
3
|
+
import { Component } from 'react';
|
|
4
|
+
import { jsx } from '@emotion/react';
|
|
5
|
+
import EditorFileIcon from '@atlaskit/icon/glyph/editor/file';
|
|
6
|
+
import { getExtensionLozengeData } from '../../utils';
|
|
7
|
+
import { placeholderFallback, placeholderFallbackParams, styledImage } from './styles';
|
|
8
|
+
export const capitalizeFirstLetter = str => {
|
|
9
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
10
|
+
};
|
|
11
|
+
export const ICON_SIZE = 24;
|
|
12
|
+
export default class ExtensionLozenge extends Component {
|
|
13
|
+
render() {
|
|
14
|
+
const {
|
|
15
|
+
node
|
|
16
|
+
} = this.props;
|
|
17
|
+
const imageData = getExtensionLozengeData({
|
|
18
|
+
node,
|
|
19
|
+
type: 'image'
|
|
20
|
+
});
|
|
21
|
+
if (imageData && node.type.name !== 'extension') {
|
|
22
|
+
return this.renderImage(imageData);
|
|
23
|
+
}
|
|
24
|
+
const iconData = getExtensionLozengeData({
|
|
25
|
+
node,
|
|
26
|
+
type: 'icon'
|
|
27
|
+
});
|
|
28
|
+
return this.renderFallback(iconData);
|
|
29
|
+
}
|
|
30
|
+
renderImage(lozengeData) {
|
|
31
|
+
const {
|
|
32
|
+
extensionKey
|
|
33
|
+
} = this.props.node.attrs;
|
|
34
|
+
const {
|
|
35
|
+
url,
|
|
36
|
+
...rest
|
|
37
|
+
} = lozengeData;
|
|
38
|
+
return jsx("img", _extends({
|
|
39
|
+
css: styledImage,
|
|
40
|
+
src: url
|
|
41
|
+
}, rest, {
|
|
42
|
+
alt: extensionKey
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
renderFallback(lozengeData) {
|
|
46
|
+
const {
|
|
47
|
+
parameters,
|
|
48
|
+
extensionKey
|
|
49
|
+
} = this.props.node.attrs;
|
|
50
|
+
const {
|
|
51
|
+
name
|
|
52
|
+
} = this.props.node.type;
|
|
53
|
+
const params = parameters && parameters.macroParams;
|
|
54
|
+
const title = parameters && parameters.extensionTitle || parameters && parameters.macroMetadata && parameters.macroMetadata.title || extensionKey;
|
|
55
|
+
const isBlockExtension = name === 'extension';
|
|
56
|
+
return jsx("div", {
|
|
57
|
+
"data-testid": "lozenge-fallback",
|
|
58
|
+
css: placeholderFallback
|
|
59
|
+
}, lozengeData && !isBlockExtension ? this.renderImage({
|
|
60
|
+
height: ICON_SIZE,
|
|
61
|
+
width: ICON_SIZE,
|
|
62
|
+
...lozengeData
|
|
63
|
+
}) : jsx(EditorFileIcon, {
|
|
64
|
+
label: title
|
|
65
|
+
}), jsx("span", {
|
|
66
|
+
className: "extension-title"
|
|
67
|
+
}, capitalizeFirstLetter(title)), params && !isBlockExtension && jsx("span", {
|
|
68
|
+
css: placeholderFallbackParams
|
|
69
|
+
}, Object.keys(params).map(key => key && ` | ${key} = ${params[key].value}`)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
import { B200, N20, N20A, N70 } from '@atlaskit/theme/colors';
|
|
3
|
+
import { BODIED_EXT_PADDING, EXTENSION_PADDING } from '../../styles';
|
|
4
|
+
export { EXTENSION_PADDING as padding, BODIED_EXT_PADDING };
|
|
5
|
+
export const wrapperDefault = css`
|
|
6
|
+
background: ${`var(--ds-background-neutral, ${N20})`};
|
|
7
|
+
border-radius: ${"var(--ds-border-radius, 3px)"};
|
|
8
|
+
position: relative;
|
|
9
|
+
vertical-align: middle;
|
|
10
|
+
|
|
11
|
+
.ProseMirror-selectednode > span > & > .extension-overlay {
|
|
12
|
+
box-shadow: inset 0px 0px 0px 2px ${`var(--ds-border-selected, ${B200})`};
|
|
13
|
+
opacity: 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&.with-overlay {
|
|
17
|
+
.extension-overlay {
|
|
18
|
+
background: ${`var(--ds-background-neutral-hovered, ${N20A})`};
|
|
19
|
+
color: transparent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:hover .extension-overlay {
|
|
23
|
+
opacity: 1;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
export const overlay = css`
|
|
28
|
+
border-radius: ${"var(--ds-border-radius, 3px)"};
|
|
29
|
+
position: absolute;
|
|
30
|
+
width: 100%;
|
|
31
|
+
height: 100%;
|
|
32
|
+
opacity: 0;
|
|
33
|
+
pointer-events: none;
|
|
34
|
+
transition: opacity 0.3s;
|
|
35
|
+
`;
|
|
36
|
+
export const placeholderFallback = css`
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
|
|
40
|
+
& > img {
|
|
41
|
+
margin: 0 ${"var(--ds-space-050, 4px)"};
|
|
42
|
+
}
|
|
43
|
+
/* TODO: fix in develop: https://atlassian.slack.com/archives/CFG3PSQ9E/p1647395052443259?thread_ts=1647394572.556029&cid=CFG3PSQ9E */
|
|
44
|
+
/* stylelint-disable-next-line */
|
|
45
|
+
label: placeholder-fallback;
|
|
46
|
+
`;
|
|
47
|
+
export const placeholderFallbackParams = css`
|
|
48
|
+
display: inline-block;
|
|
49
|
+
max-width: 200px;
|
|
50
|
+
margin-left: 5px;
|
|
51
|
+
color: ${`var(--ds-text-subtlest, ${N70})`};
|
|
52
|
+
text-overflow: ellipsis;
|
|
53
|
+
white-space: nowrap;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
`;
|
|
56
|
+
export const styledImage = css`
|
|
57
|
+
max-height: 16px;
|
|
58
|
+
max-width: 16px;
|
|
59
|
+
/* TODO: fix in develop: https://atlassian.slack.com/archives/CFG3PSQ9E/p1647395052443259?thread_ts=1647394572.556029&cid=CFG3PSQ9E */
|
|
60
|
+
/* stylelint-disable-next-line */
|
|
61
|
+
label: lozenge-image;
|
|
62
|
+
`;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import React, { Component } from 'react';
|
|
3
|
+
import { ProviderFactory, WithProviders } from '../provider-factory';
|
|
4
|
+
import { ExtensionComponent } from './ExtensionComponent';
|
|
5
|
+
export class Extension extends Component {
|
|
6
|
+
constructor(props) {
|
|
7
|
+
super(props);
|
|
8
|
+
_defineProperty(this, "renderWithProvider", ({
|
|
9
|
+
extensionProvider
|
|
10
|
+
}) => {
|
|
11
|
+
const {
|
|
12
|
+
node,
|
|
13
|
+
getPos,
|
|
14
|
+
editorView,
|
|
15
|
+
handleContentDOMRef,
|
|
16
|
+
extensionHandlers,
|
|
17
|
+
references,
|
|
18
|
+
editorAppearance,
|
|
19
|
+
pluginInjectionApi,
|
|
20
|
+
eventDispatcher
|
|
21
|
+
} = this.props;
|
|
22
|
+
return /*#__PURE__*/React.createElement(ExtensionComponent, {
|
|
23
|
+
editorView: editorView,
|
|
24
|
+
node: node,
|
|
25
|
+
getPos: getPos,
|
|
26
|
+
references: references,
|
|
27
|
+
extensionProvider: extensionProvider,
|
|
28
|
+
handleContentDOMRef: handleContentDOMRef,
|
|
29
|
+
extensionHandlers: extensionHandlers,
|
|
30
|
+
editorAppearance: editorAppearance,
|
|
31
|
+
pluginInjectionApi: pluginInjectionApi,
|
|
32
|
+
eventDispatcher: eventDispatcher
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
this.providerFactory = props.providerFactory || new ProviderFactory();
|
|
36
|
+
}
|
|
37
|
+
componentWillUnmount() {
|
|
38
|
+
if (!this.props.providerFactory) {
|
|
39
|
+
// new ProviderFactory is created if no `providers` has been set
|
|
40
|
+
// in this case when component is unmounted it's safe to destroy this providerFactory
|
|
41
|
+
this.providerFactory.destroy();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
render() {
|
|
45
|
+
return /*#__PURE__*/React.createElement(WithProviders, {
|
|
46
|
+
providers: ['extensionProvider'],
|
|
47
|
+
providerFactory: this.providerFactory,
|
|
48
|
+
renderNode: this.renderWithProvider
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
_defineProperty(Extension, "displayName", 'Extension');
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Component } from 'react';
|
|
4
|
+
import memoizeOne from 'memoize-one';
|
|
5
|
+
import { getExtensionModuleNodePrivateProps, getNodeRenderer } from '../extensions';
|
|
6
|
+
import { getExtensionRenderer } from '../utils';
|
|
7
|
+
import Extension from './Extension/Extension';
|
|
8
|
+
import InlineExtension from './Extension/InlineExtension';
|
|
9
|
+
import MultiBodiedExtension from './MultiBodiedExtension';
|
|
10
|
+
export class ExtensionComponent extends Component {
|
|
11
|
+
constructor(...args) {
|
|
12
|
+
super(...args);
|
|
13
|
+
_defineProperty(this, "privatePropsParsed", false);
|
|
14
|
+
_defineProperty(this, "state", {});
|
|
15
|
+
_defineProperty(this, "mounted", false);
|
|
16
|
+
// memoized to avoid rerender on extension state changes
|
|
17
|
+
_defineProperty(this, "getNodeRenderer", memoizeOne(getNodeRenderer));
|
|
18
|
+
_defineProperty(this, "getExtensionModuleNodePrivateProps", memoizeOne(getExtensionModuleNodePrivateProps));
|
|
19
|
+
_defineProperty(this, "setStateFromPromise", (stateKey, promise) => {
|
|
20
|
+
promise && promise.then(p => {
|
|
21
|
+
if (!this.mounted) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this.setState({
|
|
25
|
+
[stateKey]: p
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Parses any private nodes once an extension provider is available.
|
|
31
|
+
*
|
|
32
|
+
* We do this separately from resolving a node renderer component since the
|
|
33
|
+
* private props come from extension provider, rather than an extension
|
|
34
|
+
* handler which only handles `render`/component concerns.
|
|
35
|
+
*/
|
|
36
|
+
_defineProperty(this, "parsePrivateNodePropsIfNeeded", async () => {
|
|
37
|
+
if (this.privatePropsParsed || !this.state.extensionProvider) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.privatePropsParsed = true;
|
|
41
|
+
const {
|
|
42
|
+
extensionType,
|
|
43
|
+
extensionKey
|
|
44
|
+
} = this.props.node.attrs;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* getExtensionModuleNodePrivateProps can throw if there are issues in the
|
|
48
|
+
* manifest
|
|
49
|
+
*/
|
|
50
|
+
try {
|
|
51
|
+
const privateProps = await this.getExtensionModuleNodePrivateProps(this.state.extensionProvider, extensionType, extensionKey);
|
|
52
|
+
this.setState({
|
|
53
|
+
_privateProps: privateProps
|
|
54
|
+
});
|
|
55
|
+
} catch (e) {
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
console.error('Provided extension handler has thrown an error\n', e);
|
|
58
|
+
/** We don't want this error to block renderer */
|
|
59
|
+
/** We keep rendering the default content */
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
_defineProperty(this, "handleExtension", (pmNode, actions) => {
|
|
63
|
+
var _pmNode$marks, _pmNode$marks$find, _pmNode$marks$find$at;
|
|
64
|
+
const {
|
|
65
|
+
extensionHandlers,
|
|
66
|
+
editorView
|
|
67
|
+
} = this.props;
|
|
68
|
+
const {
|
|
69
|
+
extensionType,
|
|
70
|
+
extensionKey,
|
|
71
|
+
parameters,
|
|
72
|
+
text
|
|
73
|
+
} = pmNode.attrs;
|
|
74
|
+
const isBodiedExtension = pmNode.type.name === 'bodiedExtension';
|
|
75
|
+
if (isBodiedExtension) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const fragmentLocalId = pmNode === null || pmNode === void 0 ? void 0 : (_pmNode$marks = pmNode.marks) === null || _pmNode$marks === void 0 ? void 0 : (_pmNode$marks$find = _pmNode$marks.find(m => m.type.name === 'fragment')) === null || _pmNode$marks$find === void 0 ? void 0 : (_pmNode$marks$find$at = _pmNode$marks$find.attrs) === null || _pmNode$marks$find$at === void 0 ? void 0 : _pmNode$marks$find$at.localId;
|
|
79
|
+
const node = {
|
|
80
|
+
type: pmNode.type.name,
|
|
81
|
+
extensionType,
|
|
82
|
+
extensionKey,
|
|
83
|
+
parameters,
|
|
84
|
+
content: text,
|
|
85
|
+
localId: pmNode.attrs.localId,
|
|
86
|
+
fragmentLocalId
|
|
87
|
+
};
|
|
88
|
+
let result;
|
|
89
|
+
if (extensionHandlers && extensionHandlers[extensionType]) {
|
|
90
|
+
const render = getExtensionRenderer(extensionHandlers[extensionType]);
|
|
91
|
+
result = render(node, editorView.state.doc, actions);
|
|
92
|
+
}
|
|
93
|
+
if (!result) {
|
|
94
|
+
const extensionHandlerFromProvider = this.state.extensionProvider && this.getNodeRenderer(this.state.extensionProvider, extensionType, extensionKey);
|
|
95
|
+
if (extensionHandlerFromProvider) {
|
|
96
|
+
const NodeRenderer = extensionHandlerFromProvider;
|
|
97
|
+
if (node.type === 'multiBodiedExtension') {
|
|
98
|
+
return /*#__PURE__*/React.createElement(NodeRenderer, {
|
|
99
|
+
node: node,
|
|
100
|
+
references: this.props.references,
|
|
101
|
+
actions: actions
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
return /*#__PURE__*/React.createElement(NodeRenderer, {
|
|
105
|
+
node: node,
|
|
106
|
+
references: this.props.references
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
UNSAFE_componentWillMount() {
|
|
115
|
+
this.mounted = true;
|
|
116
|
+
}
|
|
117
|
+
componentDidMount() {
|
|
118
|
+
const {
|
|
119
|
+
extensionProvider
|
|
120
|
+
} = this.props;
|
|
121
|
+
if (extensionProvider) {
|
|
122
|
+
this.setStateFromPromise('extensionProvider', extensionProvider);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
componentDidUpdate() {
|
|
126
|
+
this.parsePrivateNodePropsIfNeeded();
|
|
127
|
+
}
|
|
128
|
+
componentWillUnmount() {
|
|
129
|
+
this.mounted = false;
|
|
130
|
+
}
|
|
131
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
132
|
+
const {
|
|
133
|
+
extensionProvider
|
|
134
|
+
} = nextProps;
|
|
135
|
+
if (extensionProvider && this.props.extensionProvider !== extensionProvider) {
|
|
136
|
+
this.setStateFromPromise('extensionProvider', extensionProvider);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
render() {
|
|
140
|
+
var _this$state$_privateP;
|
|
141
|
+
const {
|
|
142
|
+
node,
|
|
143
|
+
handleContentDOMRef,
|
|
144
|
+
editorView,
|
|
145
|
+
references,
|
|
146
|
+
editorAppearance,
|
|
147
|
+
pluginInjectionApi,
|
|
148
|
+
getPos,
|
|
149
|
+
eventDispatcher
|
|
150
|
+
} = this.props;
|
|
151
|
+
if (node.type.name === 'multiBodiedExtension') {
|
|
152
|
+
return /*#__PURE__*/React.createElement(MultiBodiedExtension, {
|
|
153
|
+
node: node,
|
|
154
|
+
editorView: editorView,
|
|
155
|
+
getPos: getPos,
|
|
156
|
+
handleContentDOMRef: handleContentDOMRef,
|
|
157
|
+
tryExtensionHandler: this.tryExtensionHandler.bind(this),
|
|
158
|
+
eventDispatcher: eventDispatcher,
|
|
159
|
+
pluginInjectionApi: pluginInjectionApi,
|
|
160
|
+
editorAppearance: editorAppearance
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const extensionHandlerResult = this.tryExtensionHandler(undefined);
|
|
164
|
+
switch (node.type.name) {
|
|
165
|
+
case 'extension':
|
|
166
|
+
case 'bodiedExtension':
|
|
167
|
+
return /*#__PURE__*/React.createElement(Extension, {
|
|
168
|
+
node: node,
|
|
169
|
+
getPos: this.props.getPos,
|
|
170
|
+
references: references,
|
|
171
|
+
extensionProvider: this.state.extensionProvider,
|
|
172
|
+
handleContentDOMRef: handleContentDOMRef,
|
|
173
|
+
view: editorView,
|
|
174
|
+
editorAppearance: editorAppearance,
|
|
175
|
+
hideFrame: (_this$state$_privateP = this.state._privateProps) === null || _this$state$_privateP === void 0 ? void 0 : _this$state$_privateP.__hideFrame,
|
|
176
|
+
pluginInjectionApi: pluginInjectionApi
|
|
177
|
+
}, extensionHandlerResult);
|
|
178
|
+
case 'inlineExtension':
|
|
179
|
+
return /*#__PURE__*/React.createElement(InlineExtension, {
|
|
180
|
+
node: node
|
|
181
|
+
}, extensionHandlerResult);
|
|
182
|
+
default:
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
tryExtensionHandler(actions) {
|
|
187
|
+
const {
|
|
188
|
+
node
|
|
189
|
+
} = this.props;
|
|
190
|
+
try {
|
|
191
|
+
const extensionContent = this.handleExtension(node, actions);
|
|
192
|
+
if (extensionContent && /*#__PURE__*/React.isValidElement(extensionContent)) {
|
|
193
|
+
return extensionContent;
|
|
194
|
+
}
|
|
195
|
+
} catch (e) {
|
|
196
|
+
// eslint-disable-next-line no-console
|
|
197
|
+
console.error('Provided extension handler has thrown an error\n', e);
|
|
198
|
+
/** We don't want this error to block renderer */
|
|
199
|
+
/** We keep rendering the default content */
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ZERO_WIDTH_SPACE } from '../utils';
|
|
3
|
+
/**
|
|
4
|
+
* If inlineExtension, add zero width space to the end of the nodes and wrap with span;
|
|
5
|
+
* else wrap with a div (for multi bodied extensions)
|
|
6
|
+
*
|
|
7
|
+
* @param param0
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
export const ExtensionNodeWrapper = ({
|
|
11
|
+
children,
|
|
12
|
+
nodeType
|
|
13
|
+
}) => /*#__PURE__*/React.createElement("span", null, children, nodeType === 'inlineExtension' && ZERO_WIDTH_SPACE);
|