@atlaskit/editor-plugin-text-color 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/commands/change-color.js +61 -0
- package/dist/cjs/commands/remove-color.js +59 -0
- package/dist/cjs/commands/toggle-color.js +36 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/plugin.js +87 -0
- package/dist/cjs/pm-plugins/main.js +88 -0
- package/dist/cjs/types.js +5 -0
- package/dist/cjs/ui/ToolbarTextColor/icon.js +29 -0
- package/dist/cjs/ui/ToolbarTextColor/index.js +296 -0
- package/dist/cjs/ui/ToolbarTextColor/styles.js +35 -0
- package/dist/cjs/utils/color.js +54 -0
- package/dist/cjs/utils/disabled.js +32 -0
- package/dist/es2019/commands/change-color.js +54 -0
- package/dist/es2019/commands/remove-color.js +57 -0
- package/dist/es2019/commands/toggle-color.js +30 -0
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/plugin.js +75 -0
- package/dist/es2019/pm-plugins/main.js +74 -0
- package/dist/es2019/types.js +1 -0
- package/dist/es2019/ui/ToolbarTextColor/icon.js +20 -0
- package/dist/es2019/ui/ToolbarTextColor/index.js +274 -0
- package/dist/es2019/ui/ToolbarTextColor/styles.js +48 -0
- package/dist/es2019/utils/color.js +48 -0
- package/dist/es2019/utils/disabled.js +39 -0
- package/dist/esm/commands/change-color.js +56 -0
- package/dist/esm/commands/remove-color.js +53 -0
- package/dist/esm/commands/toggle-color.js +30 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugin.js +75 -0
- package/dist/esm/pm-plugins/main.js +74 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/ui/ToolbarTextColor/icon.js +22 -0
- package/dist/esm/ui/ToolbarTextColor/index.js +290 -0
- package/dist/esm/ui/ToolbarTextColor/styles.js +28 -0
- package/dist/esm/utils/color.js +48 -0
- package/dist/esm/utils/disabled.js +26 -0
- package/dist/types/commands/change-color.d.ts +3 -0
- package/dist/types/commands/remove-color.d.ts +2 -0
- package/dist/types/commands/toggle-color.d.ts +2 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/plugin.d.ts +6 -0
- package/dist/types/pm-plugins/main.d.ts +25 -0
- package/dist/types/types.d.ts +14 -0
- package/dist/types/ui/ToolbarTextColor/icon.d.ts +2 -0
- package/dist/types/ui/ToolbarTextColor/index.d.ts +53 -0
- package/dist/types/ui/ToolbarTextColor/styles.d.ts +3 -0
- package/dist/types/utils/color.d.ts +6 -0
- package/dist/types/utils/disabled.d.ts +2 -0
- package/dist/types-ts4.5/commands/change-color.d.ts +3 -0
- package/dist/types-ts4.5/commands/remove-color.d.ts +2 -0
- package/dist/types-ts4.5/commands/toggle-color.d.ts +2 -0
- package/dist/types-ts4.5/index.d.ts +3 -0
- package/dist/types-ts4.5/plugin.d.ts +6 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +25 -0
- package/dist/types-ts4.5/types.d.ts +16 -0
- package/dist/types-ts4.5/ui/ToolbarTextColor/icon.d.ts +2 -0
- package/dist/types-ts4.5/ui/ToolbarTextColor/index.d.ts +53 -0
- package/dist/types-ts4.5/ui/ToolbarTextColor/styles.d.ts +3 -0
- package/dist/types-ts4.5/utils/color.d.ts +6 -0
- package/dist/types-ts4.5/utils/disabled.d.ts +2 -0
- package/package.json +98 -0
- package/report.api.md +82 -0
- package/tmp/api-report-tmp.d.ts +54 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { DEFAULT_BORDER_COLOR, textColorPalette } from '@atlaskit/editor-common/ui-color';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { DEFAULT_COLOR, getActiveColor } from '../utils/color';
|
|
5
|
+
import { getDisabledState } from '../utils/disabled';
|
|
6
|
+
export { DEFAULT_COLOR } from '../utils/color';
|
|
7
|
+
function createInitialPluginState(editorState, pluginConfig) {
|
|
8
|
+
const defaultColor = (pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.defaultColor) || DEFAULT_COLOR;
|
|
9
|
+
const palette = [{
|
|
10
|
+
value: defaultColor.color,
|
|
11
|
+
label: defaultColor.label,
|
|
12
|
+
border: DEFAULT_BORDER_COLOR
|
|
13
|
+
}, ...textColorPalette];
|
|
14
|
+
const state = {
|
|
15
|
+
color: getActiveColor(editorState),
|
|
16
|
+
disabled: getDisabledState(editorState),
|
|
17
|
+
palette,
|
|
18
|
+
defaultColor: defaultColor.color
|
|
19
|
+
};
|
|
20
|
+
return state;
|
|
21
|
+
}
|
|
22
|
+
export let ACTIONS = /*#__PURE__*/function (ACTIONS) {
|
|
23
|
+
ACTIONS[ACTIONS["RESET_COLOR"] = 0] = "RESET_COLOR";
|
|
24
|
+
ACTIONS[ACTIONS["SET_COLOR"] = 1] = "SET_COLOR";
|
|
25
|
+
ACTIONS[ACTIONS["DISABLE"] = 2] = "DISABLE";
|
|
26
|
+
return ACTIONS;
|
|
27
|
+
}({});
|
|
28
|
+
export const pluginKey = new PluginKey('textColorPlugin');
|
|
29
|
+
export function createPlugin(dispatch, pluginConfig) {
|
|
30
|
+
return new SafePlugin({
|
|
31
|
+
key: pluginKey,
|
|
32
|
+
state: {
|
|
33
|
+
init(_config, editorState) {
|
|
34
|
+
return createInitialPluginState(editorState, pluginConfig);
|
|
35
|
+
},
|
|
36
|
+
apply(tr, pluginState, _, newState) {
|
|
37
|
+
const meta = tr.getMeta(pluginKey) || {};
|
|
38
|
+
let nextState;
|
|
39
|
+
switch (meta.action) {
|
|
40
|
+
case ACTIONS.RESET_COLOR:
|
|
41
|
+
nextState = {
|
|
42
|
+
...pluginState,
|
|
43
|
+
color: pluginState.defaultColor
|
|
44
|
+
};
|
|
45
|
+
break;
|
|
46
|
+
case ACTIONS.SET_COLOR:
|
|
47
|
+
nextState = {
|
|
48
|
+
...pluginState,
|
|
49
|
+
color: meta.color,
|
|
50
|
+
disabled: false
|
|
51
|
+
};
|
|
52
|
+
break;
|
|
53
|
+
case ACTIONS.DISABLE:
|
|
54
|
+
nextState = {
|
|
55
|
+
...pluginState,
|
|
56
|
+
disabled: true
|
|
57
|
+
};
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
nextState = {
|
|
61
|
+
...pluginState,
|
|
62
|
+
color: getActiveColor(newState),
|
|
63
|
+
disabled: getDisabledState(newState)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (pluginState && pluginState.color !== nextState.color || pluginState && pluginState.disabled !== nextState.disabled) {
|
|
67
|
+
dispatch(pluginKey, nextState);
|
|
68
|
+
return nextState;
|
|
69
|
+
}
|
|
70
|
+
return pluginState;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
5
|
+
import Icon from '@atlaskit/icon/base';
|
|
6
|
+
const textColorGlyph = props => /*#__PURE__*/React.createElement("svg", _extends({}, props, {
|
|
7
|
+
width: "24",
|
|
8
|
+
height: "24",
|
|
9
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
10
|
+
}), /*#__PURE__*/React.createElement("path", {
|
|
11
|
+
d: "M14 12.5h-4l-.874 2.186A.5.5 0 0 1 8.66 15H7.273a.5.5 0 0 1-.456-.705l4.05-9A.5.5 0 0 1 11.323 5h1.354a.5.5 0 0 1 .456.295l4.05 9a.5.5 0 0 1-.456.705h-1.388a.5.5 0 0 1-.465-.314L14 12.5zm-.6-1.5L12 7.5 10.6 11h2.8z",
|
|
12
|
+
fill: "currentColor",
|
|
13
|
+
fillRule: "evenodd"
|
|
14
|
+
}));
|
|
15
|
+
export const EditorTextColorIcon = () => {
|
|
16
|
+
return /*#__PURE__*/React.createElement(Icon, {
|
|
17
|
+
glyph: textColorGlyph,
|
|
18
|
+
label: ""
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
/** @jsx jsx */
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { jsx } from '@emotion/react';
|
|
5
|
+
import { defineMessages, injectIntl } from 'react-intl-next';
|
|
6
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
7
|
+
import { expandIconWrapperStyle, separatorStyles, triggerWrapperStyles, wrapperStyle } from '@atlaskit/editor-common/styles';
|
|
8
|
+
import { ColorPalette, getSelectedRowAndColumnFromPalette, textPaletteTooltipMessages } from '@atlaskit/editor-common/ui-color';
|
|
9
|
+
import { ArrowKeyNavigationType, DropdownContainer as Dropdown, TOOLBAR_BUTTON, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
|
|
10
|
+
import { hexToEditorTextPaletteColor } from '@atlaskit/editor-palette';
|
|
11
|
+
import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
|
|
12
|
+
import ExpandIcon from '@atlaskit/icon/glyph/chevron-down';
|
|
13
|
+
import { changeColor as changeColorWithAnalytics } from '../../commands/change-color';
|
|
14
|
+
import { EditorTextColorIcon } from './icon';
|
|
15
|
+
import { backgroundDisabled, textColorIconBar, textColorIconWrapper } from './styles';
|
|
16
|
+
const EXPERIMENT_NAME = 'editor.toolbarTextColor.moreColors';
|
|
17
|
+
const EXPERIMENT_GROUP_CONTROL = 'control';
|
|
18
|
+
export const messages = defineMessages({
|
|
19
|
+
textColor: {
|
|
20
|
+
id: 'fabric.editor.textColor',
|
|
21
|
+
defaultMessage: 'Text color',
|
|
22
|
+
description: ''
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
// eslint-disable-next-line @repo/internal/react/no-class-components
|
|
26
|
+
export class ToolbarTextColor extends React.Component {
|
|
27
|
+
constructor(...args) {
|
|
28
|
+
super(...args);
|
|
29
|
+
_defineProperty(this, "state", {
|
|
30
|
+
isOpen: false,
|
|
31
|
+
isOpenedByKeyboard: false
|
|
32
|
+
});
|
|
33
|
+
_defineProperty(this, "toolbarItemRef", /*#__PURE__*/React.createRef());
|
|
34
|
+
_defineProperty(this, "changeColor", (color, editorAnalyticsApi) => changeColorWithAnalytics(color, editorAnalyticsApi)(this.props.editorView.state, this.props.editorView.dispatch));
|
|
35
|
+
_defineProperty(this, "onOpenChange", attrs => {
|
|
36
|
+
this.handleOpenChange({
|
|
37
|
+
isOpen: attrs.isOpen,
|
|
38
|
+
logCloseEvent: true,
|
|
39
|
+
event: attrs.event
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
_defineProperty(this, "changeTextColor", (color, editorAnalyticsApi, disabled) => {
|
|
43
|
+
if (!disabled) {
|
|
44
|
+
var _this$props$editorVie;
|
|
45
|
+
const {
|
|
46
|
+
pluginState: {
|
|
47
|
+
palette
|
|
48
|
+
}
|
|
49
|
+
} = this.props;
|
|
50
|
+
|
|
51
|
+
// we store color names in analytics
|
|
52
|
+
const swatch = palette.find(sw => sw.value === color);
|
|
53
|
+
this.dispatchAnalyticsEvent(this.buildAnalyticsSelectColor({
|
|
54
|
+
color: (swatch ? swatch.label : color).toLowerCase()
|
|
55
|
+
}));
|
|
56
|
+
this.handleOpenChange({
|
|
57
|
+
isOpen: false,
|
|
58
|
+
logCloseEvent: false
|
|
59
|
+
});
|
|
60
|
+
this.changeColor(color, editorAnalyticsApi);
|
|
61
|
+
//To set the focus on the textcolor button when the menu is closed by 'Esc' only to meet aria guidelines
|
|
62
|
+
(_this$props$editorVie = this.props.editorView) === null || _this$props$editorVie === void 0 ? void 0 : _this$props$editorVie.focus();
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
});
|
|
66
|
+
_defineProperty(this, "toggleOpen", () => {
|
|
67
|
+
this.handleOpenChange({
|
|
68
|
+
isOpen: !this.state.isOpen,
|
|
69
|
+
logCloseEvent: true
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
_defineProperty(this, "onKeyDown", event => {
|
|
73
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
this.setState({
|
|
76
|
+
isOpenedByKeyboard: true
|
|
77
|
+
});
|
|
78
|
+
this.toggleOpen();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
_defineProperty(this, "handleOpenChange", ({
|
|
82
|
+
isOpen,
|
|
83
|
+
logCloseEvent,
|
|
84
|
+
event
|
|
85
|
+
}) => {
|
|
86
|
+
this.setState({
|
|
87
|
+
isOpen
|
|
88
|
+
});
|
|
89
|
+
if (!isOpen) {
|
|
90
|
+
this.setState({
|
|
91
|
+
isOpenedByKeyboard: false
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (logCloseEvent) {
|
|
95
|
+
this.dispatchAnalyticsEvent(this.buildAnalyticsPalette(isOpen ? ACTION.OPENED : ACTION.CLOSED, {
|
|
96
|
+
noSelect: isOpen === false
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
if (!isOpen && event instanceof KeyboardEvent && (event === null || event === void 0 ? void 0 : event.key) === 'Escape') {
|
|
100
|
+
var _this$toolbarItemRef, _this$toolbarItemRef$;
|
|
101
|
+
(_this$toolbarItemRef = this.toolbarItemRef) === null || _this$toolbarItemRef === void 0 ? void 0 : (_this$toolbarItemRef$ = _this$toolbarItemRef.current) === null || _this$toolbarItemRef$ === void 0 ? void 0 : _this$toolbarItemRef$.focus();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
_defineProperty(this, "hide", e => {
|
|
105
|
+
const {
|
|
106
|
+
isOpen
|
|
107
|
+
} = this.state;
|
|
108
|
+
if (isOpen === true) {
|
|
109
|
+
this.dispatchAnalyticsEvent(this.buildAnalyticsPalette(ACTION.CLOSED, {
|
|
110
|
+
noSelect: true
|
|
111
|
+
}));
|
|
112
|
+
this.setState({
|
|
113
|
+
isOpen: false
|
|
114
|
+
});
|
|
115
|
+
if (e instanceof KeyboardEvent && e.key === 'Escape') {
|
|
116
|
+
var _this$toolbarItemRef2, _this$toolbarItemRef3;
|
|
117
|
+
(_this$toolbarItemRef2 = this.toolbarItemRef) === null || _this$toolbarItemRef2 === void 0 ? void 0 : (_this$toolbarItemRef3 = _this$toolbarItemRef2.current) === null || _this$toolbarItemRef3 === void 0 ? void 0 : _this$toolbarItemRef3.focus();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
_defineProperty(this, "hideonEsc", e => {
|
|
122
|
+
var _this$toolbarItemRef4, _this$toolbarItemRef5;
|
|
123
|
+
this.hide(e);
|
|
124
|
+
(_this$toolbarItemRef4 = this.toolbarItemRef) === null || _this$toolbarItemRef4 === void 0 ? void 0 : (_this$toolbarItemRef5 = _this$toolbarItemRef4.current) === null || _this$toolbarItemRef5 === void 0 ? void 0 : _this$toolbarItemRef5.focus();
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
render() {
|
|
128
|
+
const {
|
|
129
|
+
isOpen,
|
|
130
|
+
isOpenedByKeyboard
|
|
131
|
+
} = this.state;
|
|
132
|
+
const {
|
|
133
|
+
popupsMountPoint,
|
|
134
|
+
popupsBoundariesElement,
|
|
135
|
+
popupsScrollableElement,
|
|
136
|
+
isReducedSpacing,
|
|
137
|
+
pluginState,
|
|
138
|
+
intl: {
|
|
139
|
+
formatMessage
|
|
140
|
+
},
|
|
141
|
+
disabled,
|
|
142
|
+
pluginInjectionApi
|
|
143
|
+
} = this.props;
|
|
144
|
+
const labelTextColor = formatMessage(messages.textColor);
|
|
145
|
+
const palette = pluginState.palette;
|
|
146
|
+
let fitWidth;
|
|
147
|
+
if (document.body.clientWidth <= 740) {
|
|
148
|
+
// This was originally hard-coded, but moved here to a const
|
|
149
|
+
// My guess is it's based off (width of button * columns) + left/right padding
|
|
150
|
+
// 240 = (32 * 7) + (8 + 8)
|
|
151
|
+
// Not sure where the extra 2px comes from
|
|
152
|
+
fitWidth = 242;
|
|
153
|
+
}
|
|
154
|
+
const selectedColor = this.getSelectedColor(pluginState);
|
|
155
|
+
const {
|
|
156
|
+
selectedRowIndex,
|
|
157
|
+
selectedColumnIndex
|
|
158
|
+
} = getSelectedRowAndColumnFromPalette(palette, pluginState.color);
|
|
159
|
+
return (
|
|
160
|
+
// eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
|
|
161
|
+
jsx("span", {
|
|
162
|
+
css: wrapperStyle
|
|
163
|
+
}, jsx(Dropdown, {
|
|
164
|
+
mountTo: popupsMountPoint,
|
|
165
|
+
boundariesElement: popupsBoundariesElement,
|
|
166
|
+
scrollableElement: popupsScrollableElement,
|
|
167
|
+
isOpen: isOpen && !pluginState.disabled,
|
|
168
|
+
handleClickOutside: this.hide,
|
|
169
|
+
handleEscapeKeydown: this.hideonEsc,
|
|
170
|
+
zIndex: akEditorMenuZIndex,
|
|
171
|
+
fitWidth: fitWidth,
|
|
172
|
+
onOpenChange: this.onOpenChange,
|
|
173
|
+
closeOnTab: true,
|
|
174
|
+
arrowKeyNavigationProviderOptions: {
|
|
175
|
+
type: ArrowKeyNavigationType.COLOR,
|
|
176
|
+
selectedRowIndex,
|
|
177
|
+
selectedColumnIndex,
|
|
178
|
+
isOpenedByKeyboard,
|
|
179
|
+
isPopupPositioned: true
|
|
180
|
+
},
|
|
181
|
+
trigger: jsx(ToolbarButton, {
|
|
182
|
+
buttonId: TOOLBAR_BUTTON.TEXT_COLOR,
|
|
183
|
+
spacing: isReducedSpacing ? 'none' : 'default',
|
|
184
|
+
disabled: disabled || pluginState.disabled,
|
|
185
|
+
selected: isOpen,
|
|
186
|
+
"aria-label": labelTextColor,
|
|
187
|
+
"aria-expanded": isOpen,
|
|
188
|
+
"aria-haspopup": true,
|
|
189
|
+
title: labelTextColor,
|
|
190
|
+
onClick: this.toggleOpen,
|
|
191
|
+
onKeyDown: this.onKeyDown,
|
|
192
|
+
ref: this.toolbarItemRef,
|
|
193
|
+
iconBefore:
|
|
194
|
+
// eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
|
|
195
|
+
jsx("div", {
|
|
196
|
+
css: triggerWrapperStyles
|
|
197
|
+
}, jsx("div", {
|
|
198
|
+
css: textColorIconWrapper
|
|
199
|
+
}, jsx(EditorTextColorIcon, null), jsx("div", {
|
|
200
|
+
css: [
|
|
201
|
+
// eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
|
|
202
|
+
textColorIconBar, selectedColor ?
|
|
203
|
+
// eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
|
|
204
|
+
`background: ${selectedColor};` :
|
|
205
|
+
// eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
|
|
206
|
+
pluginState.disabled && backgroundDisabled]
|
|
207
|
+
})), jsx("span", {
|
|
208
|
+
css: expandIconWrapperStyle
|
|
209
|
+
}, jsx(ExpandIcon, {
|
|
210
|
+
label: ""
|
|
211
|
+
})))
|
|
212
|
+
})
|
|
213
|
+
}, jsx("div", {
|
|
214
|
+
"data-testid": "text-color-palette"
|
|
215
|
+
}, jsx(ColorPalette, {
|
|
216
|
+
onClick: color => {
|
|
217
|
+
var _pluginInjectionApi$a;
|
|
218
|
+
return this.changeTextColor(color, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions, pluginState.disabled);
|
|
219
|
+
},
|
|
220
|
+
selectedColor: pluginState.color,
|
|
221
|
+
paletteOptions: {
|
|
222
|
+
palette,
|
|
223
|
+
hexToPaletteColor: hexToEditorTextPaletteColor,
|
|
224
|
+
paletteColorTooltipMessages: textPaletteTooltipMessages
|
|
225
|
+
}
|
|
226
|
+
}))), jsx("span", {
|
|
227
|
+
css: separatorStyles
|
|
228
|
+
}))
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
getSelectedColor(pluginState) {
|
|
232
|
+
const selectedColor = pluginState.color !== pluginState.defaultColor && (pluginState.color ? hexToEditorTextPaletteColor(pluginState.color) : pluginState.color);
|
|
233
|
+
return selectedColor;
|
|
234
|
+
}
|
|
235
|
+
getCommonAnalyticsAttributes() {
|
|
236
|
+
return {
|
|
237
|
+
experiment: EXPERIMENT_NAME,
|
|
238
|
+
experimentGroup: EXPERIMENT_GROUP_CONTROL
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
buildAnalyticsPalette(action, data) {
|
|
242
|
+
return {
|
|
243
|
+
action,
|
|
244
|
+
actionSubject: ACTION_SUBJECT.TOOLBAR,
|
|
245
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_COLOR,
|
|
246
|
+
eventType: EVENT_TYPE.TRACK,
|
|
247
|
+
attributes: {
|
|
248
|
+
...this.getCommonAnalyticsAttributes(),
|
|
249
|
+
...data
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
buildAnalyticsSelectColor(data) {
|
|
254
|
+
return {
|
|
255
|
+
action: ACTION.FORMATTED,
|
|
256
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
257
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_COLOR,
|
|
258
|
+
eventType: EVENT_TYPE.TRACK,
|
|
259
|
+
attributes: {
|
|
260
|
+
...this.getCommonAnalyticsAttributes(),
|
|
261
|
+
...data
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
dispatchAnalyticsEvent(payload) {
|
|
266
|
+
const {
|
|
267
|
+
dispatchAnalyticsEvent
|
|
268
|
+
} = this.props;
|
|
269
|
+
if (dispatchAnalyticsEvent) {
|
|
270
|
+
dispatchAnalyticsEvent(payload);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
export default injectIntl(ToolbarTextColor);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
import { N40, N60, N80, P300, R400, T300, Y400 } from '@atlaskit/theme/colors';
|
|
3
|
+
import { borderRadius } from '@atlaskit/theme/constants';
|
|
4
|
+
const createSteppedRainbow = colors => {
|
|
5
|
+
return `
|
|
6
|
+
linear-gradient(
|
|
7
|
+
to right,
|
|
8
|
+
${colors.map((color, i) => {
|
|
9
|
+
const inc = 100 / colors.length;
|
|
10
|
+
const pos = i + 1;
|
|
11
|
+
if (i === 0) {
|
|
12
|
+
return `${color} ${pos * inc}%,`;
|
|
13
|
+
}
|
|
14
|
+
if (i === colors.length - 1) {
|
|
15
|
+
return `${color} ${(pos - 1) * inc}%`;
|
|
16
|
+
}
|
|
17
|
+
return `
|
|
18
|
+
${color} ${(pos - 1) * inc}%,
|
|
19
|
+
${color} ${pos * inc}%,
|
|
20
|
+
`;
|
|
21
|
+
}).join('\n')}
|
|
22
|
+
);
|
|
23
|
+
`;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// TODO: https://product-fabric.atlassian.net/browse/DSP-4137
|
|
27
|
+
/* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
|
|
28
|
+
const rainbow = createSteppedRainbow([P300, T300, Y400, R400]);
|
|
29
|
+
const disabledRainbow = createSteppedRainbow([N80, N60, N40, N60]);
|
|
30
|
+
/* eslint-enable @atlaskit/design-system/ensure-design-token-usage */
|
|
31
|
+
|
|
32
|
+
export const textColorIconWrapper = css`
|
|
33
|
+
position: relative;
|
|
34
|
+
`;
|
|
35
|
+
export const textColorIconBar = css`
|
|
36
|
+
position: absolute;
|
|
37
|
+
left: 0;
|
|
38
|
+
right: 0;
|
|
39
|
+
top: ${"var(--ds-space-200, 16px)"};
|
|
40
|
+
margin: auto;
|
|
41
|
+
width: 12px;
|
|
42
|
+
height: 3px;
|
|
43
|
+
border-radius: ${borderRadius() + 'px'};
|
|
44
|
+
background: ${rainbow};
|
|
45
|
+
`;
|
|
46
|
+
export const backgroundDisabled = css`
|
|
47
|
+
background: ${disabledRainbow};
|
|
48
|
+
`;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { N800 } from '@atlaskit/theme/colors';
|
|
2
|
+
export const DEFAULT_COLOR = {
|
|
3
|
+
// TODO: https://product-fabric.atlassian.net/browse/DSP-4137
|
|
4
|
+
/* eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage */
|
|
5
|
+
color: N800.toLowerCase(),
|
|
6
|
+
label: 'Dark gray'
|
|
7
|
+
};
|
|
8
|
+
export const getActiveColor = state => {
|
|
9
|
+
const {
|
|
10
|
+
$from,
|
|
11
|
+
$to,
|
|
12
|
+
$cursor
|
|
13
|
+
} = state.selection;
|
|
14
|
+
const {
|
|
15
|
+
textColor
|
|
16
|
+
} = state.schema.marks;
|
|
17
|
+
|
|
18
|
+
// Filter out other marks
|
|
19
|
+
let marks = [];
|
|
20
|
+
if ($cursor) {
|
|
21
|
+
marks.push(textColor.isInSet(state.storedMarks || $cursor.marks()) || undefined);
|
|
22
|
+
} else {
|
|
23
|
+
state.doc.nodesBetween($from.pos, $to.pos, currentNode => {
|
|
24
|
+
if (currentNode.isLeaf) {
|
|
25
|
+
const mark = textColor.isInSet(currentNode.marks) || undefined;
|
|
26
|
+
marks.push(mark);
|
|
27
|
+
return !mark;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Merge consecutive same color marks
|
|
34
|
+
let prevMark;
|
|
35
|
+
marks = marks.filter(mark => {
|
|
36
|
+
if (mark && prevMark && mark.attrs.color === prevMark.attrs.color) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
prevMark = mark;
|
|
40
|
+
return true;
|
|
41
|
+
});
|
|
42
|
+
const marksWithColor = marks.filter(mark => !!mark);
|
|
43
|
+
// When multiple colors are selected revert back to default color
|
|
44
|
+
if (marksWithColor.length > 1 || marksWithColor.length === 1 && marks.length > 1) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return marksWithColor.length ? marksWithColor[0].attrs.color : DEFAULT_COLOR.color;
|
|
48
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isMarkAllowedInRange, isMarkExcluded } from '@atlaskit/editor-common/mark';
|
|
2
|
+
const hasLinkMark = $pos => {
|
|
3
|
+
const {
|
|
4
|
+
doc: {
|
|
5
|
+
type: {
|
|
6
|
+
schema: {
|
|
7
|
+
marks: {
|
|
8
|
+
link: linkMarkType
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
pos
|
|
14
|
+
} = $pos;
|
|
15
|
+
if (!linkMarkType) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return $pos.doc.rangeHasMark(pos, Math.min(pos + 1, $pos.doc.content.size), linkMarkType);
|
|
19
|
+
};
|
|
20
|
+
export const getDisabledState = state => {
|
|
21
|
+
const {
|
|
22
|
+
textColor
|
|
23
|
+
} = state.schema.marks;
|
|
24
|
+
if (textColor) {
|
|
25
|
+
const {
|
|
26
|
+
empty,
|
|
27
|
+
ranges,
|
|
28
|
+
$cursor
|
|
29
|
+
} = state.selection;
|
|
30
|
+
if (empty && !$cursor || $cursor && hasLinkMark($cursor) || isMarkAllowedInRange(state.doc, ranges, textColor) === false) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (isMarkExcluded(textColor, state.storedMarks || $cursor && $cursor.marks())) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
|
|
3
|
+
import { pluginKey } from '../pm-plugins/main';
|
|
4
|
+
import { getActiveColor } from '../utils/color';
|
|
5
|
+
import { removeColor } from './remove-color';
|
|
6
|
+
import { toggleColor } from './toggle-color';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Helper to create a higher order analytics command
|
|
10
|
+
* @param newColor - Color to be change in hex code
|
|
11
|
+
* @param previousColor - Active color in hex code
|
|
12
|
+
* @param palette - Current palette of colors
|
|
13
|
+
* @return Higher order command with analytics logic inside.
|
|
14
|
+
*/
|
|
15
|
+
function createWithColorAnalytics(newColor, previousColor, palette, editorAnalyticsApi) {
|
|
16
|
+
var newColorFromPalette = palette.find(function (_ref) {
|
|
17
|
+
var value = _ref.value;
|
|
18
|
+
return value === newColor;
|
|
19
|
+
});
|
|
20
|
+
var previousColorFromPalette = palette.find(function (_ref2) {
|
|
21
|
+
var value = _ref2.value;
|
|
22
|
+
return value === previousColor;
|
|
23
|
+
});
|
|
24
|
+
var newColorLabel = newColorFromPalette ? newColorFromPalette.label : newColor;
|
|
25
|
+
var previousColorLabel = previousColorFromPalette ? previousColorFromPalette.label : previousColor || '';
|
|
26
|
+
return withAnalytics(editorAnalyticsApi, {
|
|
27
|
+
action: ACTION.FORMATTED,
|
|
28
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
29
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_COLOR,
|
|
30
|
+
eventType: EVENT_TYPE.TRACK,
|
|
31
|
+
attributes: {
|
|
32
|
+
newColor: newColorLabel.toLowerCase(),
|
|
33
|
+
previousColor: previousColorLabel.toLowerCase()
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export var changeColor = function changeColor(color, editorAnalyticsApi) {
|
|
38
|
+
return function (state, dispatch) {
|
|
39
|
+
var textColor = state.schema.marks.textColor;
|
|
40
|
+
if (textColor) {
|
|
41
|
+
var pluginState = pluginKey.getState(state);
|
|
42
|
+
var activeColor = getActiveColor(state);
|
|
43
|
+
var withColorAnalytics = createWithColorAnalytics(color, activeColor, (pluginState === null || pluginState === void 0 ? void 0 : pluginState.palette) || [], editorAnalyticsApi);
|
|
44
|
+
if (pluginState !== null && pluginState !== void 0 && pluginState.disabled) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (color === (pluginState === null || pluginState === void 0 ? void 0 : pluginState.defaultColor)) {
|
|
48
|
+
withColorAnalytics(removeColor())(state, dispatch);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
withColorAnalytics(toggleColor(color))(state, dispatch);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
3
|
+
import { ACTIONS, pluginKey } from '../pm-plugins/main';
|
|
4
|
+
export var removeColor = function removeColor() {
|
|
5
|
+
return function (state, dispatch) {
|
|
6
|
+
var schema = state.schema,
|
|
7
|
+
selection = state.selection;
|
|
8
|
+
var textColor = schema.marks.textColor;
|
|
9
|
+
var tr = state.tr;
|
|
10
|
+
if (selection instanceof TextSelection) {
|
|
11
|
+
var from = selection.from,
|
|
12
|
+
to = selection.to,
|
|
13
|
+
$cursor = selection.$cursor;
|
|
14
|
+
if ($cursor) {
|
|
15
|
+
tr = state.tr.removeStoredMark(textColor);
|
|
16
|
+
} else {
|
|
17
|
+
tr = state.tr.removeMark(from, to, textColor);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (selection instanceof CellSelection) {
|
|
21
|
+
/**
|
|
22
|
+
* This is a slight abstraction from `src/utils/commands.ts`
|
|
23
|
+
* The main difference is we can't toggle the default from another (since they are different marks),
|
|
24
|
+
* we want to remove all text color marks on the selection, so we slightly modify the cell selection
|
|
25
|
+
* part here.
|
|
26
|
+
*/
|
|
27
|
+
selection.forEachCell(function (cell, cellPos) {
|
|
28
|
+
var from = cellPos;
|
|
29
|
+
var to = cellPos + cell.nodeSize;
|
|
30
|
+
tr.doc.nodesBetween(tr.mapping.map(from), tr.mapping.map(to), function (node, pos) {
|
|
31
|
+
if (!node.isText) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// This is an issue when the user selects some text.
|
|
36
|
+
// We need to check if the current node position is less than the range selection from.
|
|
37
|
+
// If it’s true, that means we should apply the mark using the range selection,
|
|
38
|
+
// not the current node position.
|
|
39
|
+
var nodeBetweenFrom = Math.max(pos, tr.mapping.map(from));
|
|
40
|
+
var nodeBetweenTo = Math.min(pos + node.nodeSize, tr.mapping.map(to));
|
|
41
|
+
tr.removeMark(nodeBetweenFrom, nodeBetweenTo, textColor);
|
|
42
|
+
return true;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (dispatch) {
|
|
47
|
+
dispatch(tr.setMeta(pluginKey, {
|
|
48
|
+
action: ACTIONS.RESET_COLOR
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { toggleMark } from '@atlaskit/editor-common/mark';
|
|
2
|
+
import { editorCommandToPMCommand } from '@atlaskit/editor-common/preset';
|
|
3
|
+
import { ACTIONS, pluginKey } from '../pm-plugins/main';
|
|
4
|
+
import { getDisabledState } from '../utils/disabled';
|
|
5
|
+
export var toggleColor = function toggleColor(color) {
|
|
6
|
+
return function (state, dispatch) {
|
|
7
|
+
var textColor = state.schema.marks.textColor;
|
|
8
|
+
var tr = state.tr;
|
|
9
|
+
var disabledState = getDisabledState(state);
|
|
10
|
+
if (disabledState) {
|
|
11
|
+
if (dispatch) {
|
|
12
|
+
dispatch(tr.setMeta(pluginKey, {
|
|
13
|
+
action: ACTIONS.DISABLE
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (dispatch) {
|
|
19
|
+
state.tr.setMeta(pluginKey, {
|
|
20
|
+
action: ACTIONS.SET_COLOR,
|
|
21
|
+
color: color
|
|
22
|
+
});
|
|
23
|
+
state.tr.scrollIntoView();
|
|
24
|
+
editorCommandToPMCommand(toggleMark(textColor, {
|
|
25
|
+
color: color
|
|
26
|
+
}))(state, dispatch);
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { textColorPlugin } from './plugin';
|