@atlaskit/editor-plugin-placeholder 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.
- package/CHANGELOG.md +1 -0
- package/LICENSE.md +13 -0
- package/README.md +30 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/plugin.js +134 -0
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/plugin.js +122 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugin.js +123 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/plugin.d.ts +21 -0
- package/dist/types-ts4.5/index.d.ts +2 -0
- package/dist/types-ts4.5/plugin.d.ts +25 -0
- package/package.json +86 -0
- package/report.api.md +58 -0
- package/tmp/api-report-tmp.d.ts +31 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @atlaskit/editor-plugin-placeholder
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2023 Atlassian Pty Ltd
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Editor plugin placeholder
|
|
2
|
+
|
|
3
|
+
Placeholder plugin for @atlaskit/editor-core
|
|
4
|
+
|
|
5
|
+
**Note:** This component is designed for internal Atlassian development.
|
|
6
|
+
External contributors will be able to use this component but will not be able to submit issues.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
---
|
|
10
|
+
- **Install** - *yarn add @atlaskit/editor-plugin-placeholder*
|
|
11
|
+
- **npm** - [@atlaskit/editor-plugin-placeholder](https://www.npmjs.com/package/@atlaskit/editor-plugin-placeholder)
|
|
12
|
+
- **Source** - [Bitbucket](https://bitbucket.org/atlassian/atlassian-frontend/src/master/packages/editor/editor-plugin-placeholder)
|
|
13
|
+
- **Bundle** - [unpkg.com](https://unpkg.com/@atlaskit/editor-plugin-placeholder/dist/)
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
---
|
|
17
|
+
**Internal use only**
|
|
18
|
+
|
|
19
|
+
@atlaskit/editor-plugin-placeholder is intended for internal use by the @atlaskit/editor-core and as a plugin dependency of the Editor within your product.
|
|
20
|
+
|
|
21
|
+
Direct use of this component is not supported.
|
|
22
|
+
|
|
23
|
+
Please see [Atlaskit - Editor plugin placeholder](https://atlaskit.atlassian.com/packages/editor/editor-plugin-placeholder) for documentation and examples for this package.
|
|
24
|
+
|
|
25
|
+
## Support
|
|
26
|
+
---
|
|
27
|
+
For internal Atlassian, visit the slack channel [#help-editor](https://atlassian.slack.com/archives/CFG3PSQ9E) for support or visit [go/editor-help](https://go/editor-help) to submit a bug.
|
|
28
|
+
## License
|
|
29
|
+
---
|
|
30
|
+
Please see [Atlassian Frontend - License](https://developer.atlassian.com/cloud/framework/atlassian-frontend/#license) for more licensing information.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "placeholderPlugin", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _plugin.placeholderPlugin;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _plugin = require("./plugin");
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createPlaceholderDecoration = createPlaceholderDecoration;
|
|
7
|
+
exports.createPlugin = createPlugin;
|
|
8
|
+
exports.pluginKey = exports.placeholderTestId = exports.placeholderPlugin = void 0;
|
|
9
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
10
|
+
var _utils = require("@atlaskit/editor-common/utils");
|
|
11
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
12
|
+
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
13
|
+
var pluginKey = new _state.PluginKey('placeholderPlugin');
|
|
14
|
+
exports.pluginKey = pluginKey;
|
|
15
|
+
function getPlaceholderState(editorState) {
|
|
16
|
+
return pluginKey.getState(editorState);
|
|
17
|
+
}
|
|
18
|
+
var placeholderTestId = 'placeholder-test-id';
|
|
19
|
+
exports.placeholderTestId = placeholderTestId;
|
|
20
|
+
function createPlaceholderDecoration(editorState, placeholderText) {
|
|
21
|
+
var pos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
22
|
+
var placeholderDecoration = document.createElement('span');
|
|
23
|
+
var placeholderNodeWithText = placeholderDecoration;
|
|
24
|
+
placeholderDecoration.setAttribute('data-testid', placeholderTestId);
|
|
25
|
+
placeholderDecoration.className = 'placeholder-decoration';
|
|
26
|
+
|
|
27
|
+
// PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
|
|
28
|
+
// So adding an extra span which will contain the placeholder text
|
|
29
|
+
if (_utils.browser.gecko) {
|
|
30
|
+
var placeholderNode = document.createElement('span');
|
|
31
|
+
placeholderNode.setAttribute('contenteditable', 'true'); // explicitly overriding the default Decoration behaviour
|
|
32
|
+
placeholderDecoration.appendChild(placeholderNode);
|
|
33
|
+
placeholderNodeWithText = placeholderNode;
|
|
34
|
+
}
|
|
35
|
+
placeholderNodeWithText.textContent = placeholderText || ' ';
|
|
36
|
+
|
|
37
|
+
// ME-2289 Tapping on backspace in empty editor hides and displays the keyboard
|
|
38
|
+
// Add a editable buff node as the cursor moving forward is inevitable
|
|
39
|
+
// when backspace in GBoard composition
|
|
40
|
+
if (_utils.browser.android && _utils.browser.chrome) {
|
|
41
|
+
var buffNode = document.createElement('span');
|
|
42
|
+
buffNode.setAttribute('class', 'placeholder-android');
|
|
43
|
+
buffNode.setAttribute('contenteditable', 'true');
|
|
44
|
+
buffNode.textContent = ' ';
|
|
45
|
+
placeholderDecoration.appendChild(buffNode);
|
|
46
|
+
}
|
|
47
|
+
return _view.DecorationSet.create(editorState.doc, [_view.Decoration.widget(pos, placeholderDecoration, {
|
|
48
|
+
side: 0,
|
|
49
|
+
key: 'placeholder'
|
|
50
|
+
})]);
|
|
51
|
+
}
|
|
52
|
+
function setPlaceHolderState(placeholderText, pos) {
|
|
53
|
+
return {
|
|
54
|
+
hasPlaceholder: true,
|
|
55
|
+
placeholderText: placeholderText,
|
|
56
|
+
pos: pos ? pos : 1
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
var emptyPlaceholder = {
|
|
60
|
+
hasPlaceholder: false
|
|
61
|
+
};
|
|
62
|
+
function createPlaceHolderStateFrom(isEditorFocused, editorState, isTypeAheadOpen, defaultPlaceholderText, bracketPlaceholderText) {
|
|
63
|
+
if (isTypeAheadOpen !== null && isTypeAheadOpen !== void 0 && isTypeAheadOpen(editorState)) {
|
|
64
|
+
return emptyPlaceholder;
|
|
65
|
+
}
|
|
66
|
+
if (defaultPlaceholderText && (0, _utils.isEmptyDocument)(editorState.doc)) {
|
|
67
|
+
return setPlaceHolderState(defaultPlaceholderText);
|
|
68
|
+
}
|
|
69
|
+
if (bracketPlaceholderText && (0, _utils.bracketTyped)(editorState) && isEditorFocused) {
|
|
70
|
+
var $from = editorState.selection.$from;
|
|
71
|
+
// Space is to account for positioning of the bracket
|
|
72
|
+
var bracketHint = ' ' + bracketPlaceholderText;
|
|
73
|
+
return setPlaceHolderState(bracketHint, $from.pos - 1);
|
|
74
|
+
}
|
|
75
|
+
return emptyPlaceholder;
|
|
76
|
+
}
|
|
77
|
+
function createPlugin(defaultPlaceholderText, bracketPlaceholderText, api) {
|
|
78
|
+
if (!defaultPlaceholderText && !bracketPlaceholderText) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
return new _safePlugin.SafePlugin({
|
|
82
|
+
key: pluginKey,
|
|
83
|
+
state: {
|
|
84
|
+
init: function init(_, state) {
|
|
85
|
+
var _api$focus, _api$focus$sharedStat;
|
|
86
|
+
return createPlaceHolderStateFrom(Boolean(api === null || api === void 0 ? void 0 : (_api$focus = api.focus) === null || _api$focus === void 0 ? void 0 : (_api$focus$sharedStat = _api$focus.sharedState.currentState()) === null || _api$focus$sharedStat === void 0 ? void 0 : _api$focus$sharedStat.hasFocus), state, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
87
|
+
},
|
|
88
|
+
apply: function apply(tr, _oldPluginState, _oldEditorState, newEditorState) {
|
|
89
|
+
var _api$focus2, _api$focus2$sharedSta;
|
|
90
|
+
var meta = tr.getMeta(pluginKey);
|
|
91
|
+
var isEditorFocused = Boolean(api === null || api === void 0 ? void 0 : (_api$focus2 = api.focus) === null || _api$focus2 === void 0 ? void 0 : (_api$focus2$sharedSta = _api$focus2.sharedState.currentState()) === null || _api$focus2$sharedSta === void 0 ? void 0 : _api$focus2$sharedSta.hasFocus);
|
|
92
|
+
if (meta) {
|
|
93
|
+
if (meta.removePlaceholder) {
|
|
94
|
+
return emptyPlaceholder;
|
|
95
|
+
}
|
|
96
|
+
if (meta.applyPlaceholderIfEmpty) {
|
|
97
|
+
return createPlaceHolderStateFrom(isEditorFocused, newEditorState, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return createPlaceHolderStateFrom(isEditorFocused, newEditorState, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
props: {
|
|
104
|
+
decorations: function decorations(editorState) {
|
|
105
|
+
var _api$composition;
|
|
106
|
+
var _getPlaceholderState = getPlaceholderState(editorState),
|
|
107
|
+
hasPlaceholder = _getPlaceholderState.hasPlaceholder,
|
|
108
|
+
placeholderText = _getPlaceholderState.placeholderText,
|
|
109
|
+
pos = _getPlaceholderState.pos;
|
|
110
|
+
var compositionPluginState = api === null || api === void 0 ? void 0 : (_api$composition = api.composition) === null || _api$composition === void 0 ? void 0 : _api$composition.sharedState.currentState();
|
|
111
|
+
if (hasPlaceholder && placeholderText && pos !== undefined && !(compositionPluginState !== null && compositionPluginState !== void 0 && compositionPluginState.isComposing)) {
|
|
112
|
+
return createPlaceholderDecoration(editorState, placeholderText, pos);
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
var placeholderPlugin = function placeholderPlugin(_ref) {
|
|
120
|
+
var options = _ref.config,
|
|
121
|
+
api = _ref.api;
|
|
122
|
+
return {
|
|
123
|
+
name: 'placeholder',
|
|
124
|
+
pmPlugins: function pmPlugins() {
|
|
125
|
+
return [{
|
|
126
|
+
name: 'placeholder',
|
|
127
|
+
plugin: function plugin() {
|
|
128
|
+
return createPlugin(options && options.placeholder, options && options.placeholderBracketHint, api);
|
|
129
|
+
}
|
|
130
|
+
}];
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
exports.placeholderPlugin = placeholderPlugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { placeholderPlugin } from './plugin';
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { bracketTyped, browser, isEmptyDocument } from '@atlaskit/editor-common/utils';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
export const pluginKey = new PluginKey('placeholderPlugin');
|
|
6
|
+
function getPlaceholderState(editorState) {
|
|
7
|
+
return pluginKey.getState(editorState);
|
|
8
|
+
}
|
|
9
|
+
export const placeholderTestId = 'placeholder-test-id';
|
|
10
|
+
export function createPlaceholderDecoration(editorState, placeholderText, pos = 1) {
|
|
11
|
+
const placeholderDecoration = document.createElement('span');
|
|
12
|
+
let placeholderNodeWithText = placeholderDecoration;
|
|
13
|
+
placeholderDecoration.setAttribute('data-testid', placeholderTestId);
|
|
14
|
+
placeholderDecoration.className = 'placeholder-decoration';
|
|
15
|
+
|
|
16
|
+
// PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
|
|
17
|
+
// So adding an extra span which will contain the placeholder text
|
|
18
|
+
if (browser.gecko) {
|
|
19
|
+
const placeholderNode = document.createElement('span');
|
|
20
|
+
placeholderNode.setAttribute('contenteditable', 'true'); // explicitly overriding the default Decoration behaviour
|
|
21
|
+
placeholderDecoration.appendChild(placeholderNode);
|
|
22
|
+
placeholderNodeWithText = placeholderNode;
|
|
23
|
+
}
|
|
24
|
+
placeholderNodeWithText.textContent = placeholderText || ' ';
|
|
25
|
+
|
|
26
|
+
// ME-2289 Tapping on backspace in empty editor hides and displays the keyboard
|
|
27
|
+
// Add a editable buff node as the cursor moving forward is inevitable
|
|
28
|
+
// when backspace in GBoard composition
|
|
29
|
+
if (browser.android && browser.chrome) {
|
|
30
|
+
const buffNode = document.createElement('span');
|
|
31
|
+
buffNode.setAttribute('class', 'placeholder-android');
|
|
32
|
+
buffNode.setAttribute('contenteditable', 'true');
|
|
33
|
+
buffNode.textContent = ' ';
|
|
34
|
+
placeholderDecoration.appendChild(buffNode);
|
|
35
|
+
}
|
|
36
|
+
return DecorationSet.create(editorState.doc, [Decoration.widget(pos, placeholderDecoration, {
|
|
37
|
+
side: 0,
|
|
38
|
+
key: 'placeholder'
|
|
39
|
+
})]);
|
|
40
|
+
}
|
|
41
|
+
function setPlaceHolderState(placeholderText, pos) {
|
|
42
|
+
return {
|
|
43
|
+
hasPlaceholder: true,
|
|
44
|
+
placeholderText,
|
|
45
|
+
pos: pos ? pos : 1
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const emptyPlaceholder = {
|
|
49
|
+
hasPlaceholder: false
|
|
50
|
+
};
|
|
51
|
+
function createPlaceHolderStateFrom(isEditorFocused, editorState, isTypeAheadOpen, defaultPlaceholderText, bracketPlaceholderText) {
|
|
52
|
+
if (isTypeAheadOpen !== null && isTypeAheadOpen !== void 0 && isTypeAheadOpen(editorState)) {
|
|
53
|
+
return emptyPlaceholder;
|
|
54
|
+
}
|
|
55
|
+
if (defaultPlaceholderText && isEmptyDocument(editorState.doc)) {
|
|
56
|
+
return setPlaceHolderState(defaultPlaceholderText);
|
|
57
|
+
}
|
|
58
|
+
if (bracketPlaceholderText && bracketTyped(editorState) && isEditorFocused) {
|
|
59
|
+
const {
|
|
60
|
+
$from
|
|
61
|
+
} = editorState.selection;
|
|
62
|
+
// Space is to account for positioning of the bracket
|
|
63
|
+
const bracketHint = ' ' + bracketPlaceholderText;
|
|
64
|
+
return setPlaceHolderState(bracketHint, $from.pos - 1);
|
|
65
|
+
}
|
|
66
|
+
return emptyPlaceholder;
|
|
67
|
+
}
|
|
68
|
+
export function createPlugin(defaultPlaceholderText, bracketPlaceholderText, api) {
|
|
69
|
+
if (!defaultPlaceholderText && !bracketPlaceholderText) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
return new SafePlugin({
|
|
73
|
+
key: pluginKey,
|
|
74
|
+
state: {
|
|
75
|
+
init: (_, state) => {
|
|
76
|
+
var _api$focus, _api$focus$sharedStat;
|
|
77
|
+
return createPlaceHolderStateFrom(Boolean(api === null || api === void 0 ? void 0 : (_api$focus = api.focus) === null || _api$focus === void 0 ? void 0 : (_api$focus$sharedStat = _api$focus.sharedState.currentState()) === null || _api$focus$sharedStat === void 0 ? void 0 : _api$focus$sharedStat.hasFocus), state, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
78
|
+
},
|
|
79
|
+
apply: (tr, _oldPluginState, _oldEditorState, newEditorState) => {
|
|
80
|
+
var _api$focus2, _api$focus2$sharedSta;
|
|
81
|
+
const meta = tr.getMeta(pluginKey);
|
|
82
|
+
const isEditorFocused = Boolean(api === null || api === void 0 ? void 0 : (_api$focus2 = api.focus) === null || _api$focus2 === void 0 ? void 0 : (_api$focus2$sharedSta = _api$focus2.sharedState.currentState()) === null || _api$focus2$sharedSta === void 0 ? void 0 : _api$focus2$sharedSta.hasFocus);
|
|
83
|
+
if (meta) {
|
|
84
|
+
if (meta.removePlaceholder) {
|
|
85
|
+
return emptyPlaceholder;
|
|
86
|
+
}
|
|
87
|
+
if (meta.applyPlaceholderIfEmpty) {
|
|
88
|
+
return createPlaceHolderStateFrom(isEditorFocused, newEditorState, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return createPlaceHolderStateFrom(isEditorFocused, newEditorState, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
props: {
|
|
95
|
+
decorations(editorState) {
|
|
96
|
+
var _api$composition;
|
|
97
|
+
const {
|
|
98
|
+
hasPlaceholder,
|
|
99
|
+
placeholderText,
|
|
100
|
+
pos
|
|
101
|
+
} = getPlaceholderState(editorState);
|
|
102
|
+
const compositionPluginState = api === null || api === void 0 ? void 0 : (_api$composition = api.composition) === null || _api$composition === void 0 ? void 0 : _api$composition.sharedState.currentState();
|
|
103
|
+
if (hasPlaceholder && placeholderText && pos !== undefined && !(compositionPluginState !== null && compositionPluginState !== void 0 && compositionPluginState.isComposing)) {
|
|
104
|
+
return createPlaceholderDecoration(editorState, placeholderText, pos);
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export const placeholderPlugin = ({
|
|
112
|
+
config: options,
|
|
113
|
+
api
|
|
114
|
+
}) => ({
|
|
115
|
+
name: 'placeholder',
|
|
116
|
+
pmPlugins() {
|
|
117
|
+
return [{
|
|
118
|
+
name: 'placeholder',
|
|
119
|
+
plugin: () => createPlugin(options && options.placeholder, options && options.placeholderBracketHint, api)
|
|
120
|
+
}];
|
|
121
|
+
}
|
|
122
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { placeholderPlugin } from './plugin';
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { bracketTyped, browser, isEmptyDocument } from '@atlaskit/editor-common/utils';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
export var pluginKey = new PluginKey('placeholderPlugin');
|
|
6
|
+
function getPlaceholderState(editorState) {
|
|
7
|
+
return pluginKey.getState(editorState);
|
|
8
|
+
}
|
|
9
|
+
export var placeholderTestId = 'placeholder-test-id';
|
|
10
|
+
export function createPlaceholderDecoration(editorState, placeholderText) {
|
|
11
|
+
var pos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
12
|
+
var placeholderDecoration = document.createElement('span');
|
|
13
|
+
var placeholderNodeWithText = placeholderDecoration;
|
|
14
|
+
placeholderDecoration.setAttribute('data-testid', placeholderTestId);
|
|
15
|
+
placeholderDecoration.className = 'placeholder-decoration';
|
|
16
|
+
|
|
17
|
+
// PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
|
|
18
|
+
// So adding an extra span which will contain the placeholder text
|
|
19
|
+
if (browser.gecko) {
|
|
20
|
+
var placeholderNode = document.createElement('span');
|
|
21
|
+
placeholderNode.setAttribute('contenteditable', 'true'); // explicitly overriding the default Decoration behaviour
|
|
22
|
+
placeholderDecoration.appendChild(placeholderNode);
|
|
23
|
+
placeholderNodeWithText = placeholderNode;
|
|
24
|
+
}
|
|
25
|
+
placeholderNodeWithText.textContent = placeholderText || ' ';
|
|
26
|
+
|
|
27
|
+
// ME-2289 Tapping on backspace in empty editor hides and displays the keyboard
|
|
28
|
+
// Add a editable buff node as the cursor moving forward is inevitable
|
|
29
|
+
// when backspace in GBoard composition
|
|
30
|
+
if (browser.android && browser.chrome) {
|
|
31
|
+
var buffNode = document.createElement('span');
|
|
32
|
+
buffNode.setAttribute('class', 'placeholder-android');
|
|
33
|
+
buffNode.setAttribute('contenteditable', 'true');
|
|
34
|
+
buffNode.textContent = ' ';
|
|
35
|
+
placeholderDecoration.appendChild(buffNode);
|
|
36
|
+
}
|
|
37
|
+
return DecorationSet.create(editorState.doc, [Decoration.widget(pos, placeholderDecoration, {
|
|
38
|
+
side: 0,
|
|
39
|
+
key: 'placeholder'
|
|
40
|
+
})]);
|
|
41
|
+
}
|
|
42
|
+
function setPlaceHolderState(placeholderText, pos) {
|
|
43
|
+
return {
|
|
44
|
+
hasPlaceholder: true,
|
|
45
|
+
placeholderText: placeholderText,
|
|
46
|
+
pos: pos ? pos : 1
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
var emptyPlaceholder = {
|
|
50
|
+
hasPlaceholder: false
|
|
51
|
+
};
|
|
52
|
+
function createPlaceHolderStateFrom(isEditorFocused, editorState, isTypeAheadOpen, defaultPlaceholderText, bracketPlaceholderText) {
|
|
53
|
+
if (isTypeAheadOpen !== null && isTypeAheadOpen !== void 0 && isTypeAheadOpen(editorState)) {
|
|
54
|
+
return emptyPlaceholder;
|
|
55
|
+
}
|
|
56
|
+
if (defaultPlaceholderText && isEmptyDocument(editorState.doc)) {
|
|
57
|
+
return setPlaceHolderState(defaultPlaceholderText);
|
|
58
|
+
}
|
|
59
|
+
if (bracketPlaceholderText && bracketTyped(editorState) && isEditorFocused) {
|
|
60
|
+
var $from = editorState.selection.$from;
|
|
61
|
+
// Space is to account for positioning of the bracket
|
|
62
|
+
var bracketHint = ' ' + bracketPlaceholderText;
|
|
63
|
+
return setPlaceHolderState(bracketHint, $from.pos - 1);
|
|
64
|
+
}
|
|
65
|
+
return emptyPlaceholder;
|
|
66
|
+
}
|
|
67
|
+
export function createPlugin(defaultPlaceholderText, bracketPlaceholderText, api) {
|
|
68
|
+
if (!defaultPlaceholderText && !bracketPlaceholderText) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
return new SafePlugin({
|
|
72
|
+
key: pluginKey,
|
|
73
|
+
state: {
|
|
74
|
+
init: function init(_, state) {
|
|
75
|
+
var _api$focus, _api$focus$sharedStat;
|
|
76
|
+
return createPlaceHolderStateFrom(Boolean(api === null || api === void 0 ? void 0 : (_api$focus = api.focus) === null || _api$focus === void 0 ? void 0 : (_api$focus$sharedStat = _api$focus.sharedState.currentState()) === null || _api$focus$sharedStat === void 0 ? void 0 : _api$focus$sharedStat.hasFocus), state, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
77
|
+
},
|
|
78
|
+
apply: function apply(tr, _oldPluginState, _oldEditorState, newEditorState) {
|
|
79
|
+
var _api$focus2, _api$focus2$sharedSta;
|
|
80
|
+
var meta = tr.getMeta(pluginKey);
|
|
81
|
+
var isEditorFocused = Boolean(api === null || api === void 0 ? void 0 : (_api$focus2 = api.focus) === null || _api$focus2 === void 0 ? void 0 : (_api$focus2$sharedSta = _api$focus2.sharedState.currentState()) === null || _api$focus2$sharedSta === void 0 ? void 0 : _api$focus2$sharedSta.hasFocus);
|
|
82
|
+
if (meta) {
|
|
83
|
+
if (meta.removePlaceholder) {
|
|
84
|
+
return emptyPlaceholder;
|
|
85
|
+
}
|
|
86
|
+
if (meta.applyPlaceholderIfEmpty) {
|
|
87
|
+
return createPlaceHolderStateFrom(isEditorFocused, newEditorState, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return createPlaceHolderStateFrom(isEditorFocused, newEditorState, api === null || api === void 0 ? void 0 : api.typeAhead.actions.isOpen, defaultPlaceholderText, bracketPlaceholderText);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
props: {
|
|
94
|
+
decorations: function decorations(editorState) {
|
|
95
|
+
var _api$composition;
|
|
96
|
+
var _getPlaceholderState = getPlaceholderState(editorState),
|
|
97
|
+
hasPlaceholder = _getPlaceholderState.hasPlaceholder,
|
|
98
|
+
placeholderText = _getPlaceholderState.placeholderText,
|
|
99
|
+
pos = _getPlaceholderState.pos;
|
|
100
|
+
var compositionPluginState = api === null || api === void 0 ? void 0 : (_api$composition = api.composition) === null || _api$composition === void 0 ? void 0 : _api$composition.sharedState.currentState();
|
|
101
|
+
if (hasPlaceholder && placeholderText && pos !== undefined && !(compositionPluginState !== null && compositionPluginState !== void 0 && compositionPluginState.isComposing)) {
|
|
102
|
+
return createPlaceholderDecoration(editorState, placeholderText, pos);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export var placeholderPlugin = function placeholderPlugin(_ref) {
|
|
110
|
+
var options = _ref.config,
|
|
111
|
+
api = _ref.api;
|
|
112
|
+
return {
|
|
113
|
+
name: 'placeholder',
|
|
114
|
+
pmPlugins: function pmPlugins() {
|
|
115
|
+
return [{
|
|
116
|
+
name: 'placeholder',
|
|
117
|
+
plugin: function plugin() {
|
|
118
|
+
return createPlugin(options && options.placeholder, options && options.placeholderBracketHint, api);
|
|
119
|
+
}
|
|
120
|
+
}];
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { ExtractInjectionAPI, NextEditorPlugin } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { CompositionPlugin } from '@atlaskit/editor-plugin-composition';
|
|
4
|
+
import type { FocusPlugin } from '@atlaskit/editor-plugin-focus';
|
|
5
|
+
import type { TypeAheadPlugin } from '@atlaskit/editor-plugin-type-ahead';
|
|
6
|
+
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
9
|
+
export declare const pluginKey: PluginKey<any>;
|
|
10
|
+
export declare const placeholderTestId = "placeholder-test-id";
|
|
11
|
+
export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, pos?: number): DecorationSet;
|
|
12
|
+
export declare function createPlugin(defaultPlaceholderText?: string, bracketPlaceholderText?: string, api?: ExtractInjectionAPI<PlaceholderPlugin>): SafePlugin | undefined;
|
|
13
|
+
export interface PlaceholderPluginOptions {
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
placeholderBracketHint?: string;
|
|
16
|
+
}
|
|
17
|
+
export type PlaceholderPlugin = NextEditorPlugin<'placeholder', {
|
|
18
|
+
pluginConfiguration: PlaceholderPluginOptions | undefined;
|
|
19
|
+
dependencies: [FocusPlugin, CompositionPlugin, TypeAheadPlugin];
|
|
20
|
+
}>;
|
|
21
|
+
export declare const placeholderPlugin: PlaceholderPlugin;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import type { ExtractInjectionAPI, NextEditorPlugin } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { CompositionPlugin } from '@atlaskit/editor-plugin-composition';
|
|
4
|
+
import type { FocusPlugin } from '@atlaskit/editor-plugin-focus';
|
|
5
|
+
import type { TypeAheadPlugin } from '@atlaskit/editor-plugin-type-ahead';
|
|
6
|
+
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
9
|
+
export declare const pluginKey: PluginKey<any>;
|
|
10
|
+
export declare const placeholderTestId = "placeholder-test-id";
|
|
11
|
+
export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, pos?: number): DecorationSet;
|
|
12
|
+
export declare function createPlugin(defaultPlaceholderText?: string, bracketPlaceholderText?: string, api?: ExtractInjectionAPI<PlaceholderPlugin>): SafePlugin | undefined;
|
|
13
|
+
export interface PlaceholderPluginOptions {
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
placeholderBracketHint?: string;
|
|
16
|
+
}
|
|
17
|
+
export type PlaceholderPlugin = NextEditorPlugin<'placeholder', {
|
|
18
|
+
pluginConfiguration: PlaceholderPluginOptions | undefined;
|
|
19
|
+
dependencies: [
|
|
20
|
+
FocusPlugin,
|
|
21
|
+
CompositionPlugin,
|
|
22
|
+
TypeAheadPlugin
|
|
23
|
+
];
|
|
24
|
+
}>;
|
|
25
|
+
export declare const placeholderPlugin: PlaceholderPlugin;
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/editor-plugin-placeholder",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Placeholder plugin for @atlaskit/editor-core.",
|
|
5
|
+
"author": "Atlassian Pty Ltd",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
|
+
},
|
|
10
|
+
"atlassian": {
|
|
11
|
+
"team": "Editor: Scarlet",
|
|
12
|
+
"singleton": true,
|
|
13
|
+
"releaseModel": "continuous"
|
|
14
|
+
},
|
|
15
|
+
"repository": "https://bitbucket.org/atlassian/atlassian-frontend",
|
|
16
|
+
"main": "dist/cjs/index.js",
|
|
17
|
+
"module": "dist/esm/index.js",
|
|
18
|
+
"module:es2019": "dist/es2019/index.js",
|
|
19
|
+
"types": "dist/types/index.d.ts",
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
">=4.5 <4.9": {
|
|
22
|
+
"*": [
|
|
23
|
+
"dist/types-ts4.5/*",
|
|
24
|
+
"dist/types-ts4.5/index.d.ts"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"atlaskit:src": "src/index.ts",
|
|
30
|
+
"af:exports": {
|
|
31
|
+
".": "./src/index.ts"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@atlaskit/editor-common": "^74.56.0",
|
|
35
|
+
"@atlaskit/editor-plugin-composition": "^0.1.0",
|
|
36
|
+
"@atlaskit/editor-plugin-focus": "^0.2.0",
|
|
37
|
+
"@atlaskit/editor-plugin-type-ahead": "^0.3.0",
|
|
38
|
+
"@atlaskit/editor-prosemirror": "1.1.0",
|
|
39
|
+
"@babel/runtime": "^7.0.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"react": "^16.8.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
|
|
46
|
+
"@testing-library/react": "^12.1.5",
|
|
47
|
+
"react-dom": "^16.8.0",
|
|
48
|
+
"typescript": "~4.9.5"
|
|
49
|
+
},
|
|
50
|
+
"techstack": {
|
|
51
|
+
"@atlassian/frontend": {
|
|
52
|
+
"import-structure": [
|
|
53
|
+
"atlassian-conventions"
|
|
54
|
+
],
|
|
55
|
+
"circular-dependencies": [
|
|
56
|
+
"file-and-folder-level"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"@repo/internal": {
|
|
60
|
+
"dom-events": "use-bind-event-listener",
|
|
61
|
+
"analytics": [
|
|
62
|
+
"analytics-next"
|
|
63
|
+
],
|
|
64
|
+
"design-tokens": [
|
|
65
|
+
"color"
|
|
66
|
+
],
|
|
67
|
+
"theming": [
|
|
68
|
+
"react-context"
|
|
69
|
+
],
|
|
70
|
+
"ui-components": [
|
|
71
|
+
"lite-mode"
|
|
72
|
+
],
|
|
73
|
+
"deprecation": [
|
|
74
|
+
"no-deprecated-imports"
|
|
75
|
+
],
|
|
76
|
+
"styling": [
|
|
77
|
+
"static",
|
|
78
|
+
"emotion"
|
|
79
|
+
],
|
|
80
|
+
"imports": [
|
|
81
|
+
"import-no-extraneous-disable-for-examples-and-docs"
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.0"
|
|
86
|
+
}
|
package/report.api.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!-- API Report Version: 2.3 -->
|
|
2
|
+
|
|
3
|
+
## API Report File for "@atlaskit/editor-plugin-placeholder"
|
|
4
|
+
|
|
5
|
+
> Do not edit this file. This report is auto-generated using [API Extractor](https://api-extractor.com/).
|
|
6
|
+
> [Learn more about API reports](https://hello.atlassian.net/wiki/spaces/UR/pages/1825484529/Package+API+Reports)
|
|
7
|
+
|
|
8
|
+
### Table of contents
|
|
9
|
+
|
|
10
|
+
- [Main Entry Types](#main-entry-types)
|
|
11
|
+
- [Peer Dependencies](#peer-dependencies)
|
|
12
|
+
|
|
13
|
+
### Main Entry Types
|
|
14
|
+
|
|
15
|
+
<!--SECTION START: Main Entry Types-->
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import type { CompositionPlugin } from '@atlaskit/editor-plugin-composition';
|
|
19
|
+
import type { FocusPlugin } from '@atlaskit/editor-plugin-focus';
|
|
20
|
+
import type { NextEditorPlugin } from '@atlaskit/editor-common/types';
|
|
21
|
+
import type { TypeAheadPlugin } from '@atlaskit/editor-plugin-type-ahead';
|
|
22
|
+
|
|
23
|
+
// @public (undocumented)
|
|
24
|
+
export type PlaceholderPlugin = NextEditorPlugin<
|
|
25
|
+
'placeholder',
|
|
26
|
+
{
|
|
27
|
+
pluginConfiguration: PlaceholderPluginOptions | undefined;
|
|
28
|
+
dependencies: [FocusPlugin, CompositionPlugin, TypeAheadPlugin];
|
|
29
|
+
}
|
|
30
|
+
>;
|
|
31
|
+
|
|
32
|
+
// @public (undocumented)
|
|
33
|
+
export const placeholderPlugin: PlaceholderPlugin;
|
|
34
|
+
|
|
35
|
+
// @public (undocumented)
|
|
36
|
+
export interface PlaceholderPluginOptions {
|
|
37
|
+
// (undocumented)
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
// (undocumented)
|
|
40
|
+
placeholderBracketHint?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// (No @packageDocumentation comment for this package)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
<!--SECTION END: Main Entry Types-->
|
|
47
|
+
|
|
48
|
+
### Peer Dependencies
|
|
49
|
+
|
|
50
|
+
<!--SECTION START: Peer Dependencies-->
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"react": "^16.8.0"
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
<!--SECTION END: Peer Dependencies-->
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## API Report File for "@atlaskit/editor-plugin-placeholder"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import type { CompositionPlugin } from '@atlaskit/editor-plugin-composition';
|
|
8
|
+
import type { FocusPlugin } from '@atlaskit/editor-plugin-focus';
|
|
9
|
+
import type { NextEditorPlugin } from '@atlaskit/editor-common/types';
|
|
10
|
+
import type { TypeAheadPlugin } from '@atlaskit/editor-plugin-type-ahead';
|
|
11
|
+
|
|
12
|
+
// @public (undocumented)
|
|
13
|
+
export type PlaceholderPlugin = NextEditorPlugin<'placeholder', {
|
|
14
|
+
pluginConfiguration: PlaceholderPluginOptions | undefined;
|
|
15
|
+
dependencies: [FocusPlugin, CompositionPlugin, TypeAheadPlugin];
|
|
16
|
+
}>;
|
|
17
|
+
|
|
18
|
+
// @public (undocumented)
|
|
19
|
+
export const placeholderPlugin: PlaceholderPlugin;
|
|
20
|
+
|
|
21
|
+
// @public (undocumented)
|
|
22
|
+
export interface PlaceholderPluginOptions {
|
|
23
|
+
// (undocumented)
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
// (undocumented)
|
|
26
|
+
placeholderBracketHint?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// (No @packageDocumentation comment for this package)
|
|
30
|
+
|
|
31
|
+
```
|