goodteditor-ui 1.0.51 → 1.0.53
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/index.d.ts +60 -0
- package/index.js +3 -3
- package/package.json +1 -1
- package/src/App.vue +3 -1
- package/src/components/ui/WysiwygEditor/WysiwygEditor.md +74 -0
- package/src/components/ui/{WysiwygEditor.vue → WysiwygEditor/WysiwygEditor.vue} +13 -16
- package/src/components/ui/WysiwygEditor/{WysiwygEditor.d.ts → constants.d.ts} +14 -5
- package/src/components/ui/WysiwygEditor/constants.js +29 -99
- package/src/components/ui/WysiwygEditor/index.d.ts +3 -4
- package/src/components/ui/WysiwygEditor/index.js +3 -4
- package/src/components/ui/WysiwygEditor/renders/Button.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/ColorPicker.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/Image.vue +3 -2
- package/src/components/ui/WysiwygEditor/renders/InputAuto.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/InputUnits.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/Link.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/Select.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/ToolbarPopover.vue +2 -1
- package/src/components/ui/WysiwygEditor/renders/mixins/RenderMixin.d.ts +20 -0
- package/src/components/ui/WysiwygEditor/renders/mixins/RenderMixin.js +10 -1
- package/src/components/ui/WysiwygEditor/renders/mixins/index.d.ts +1 -0
- package/src/components/ui/WysiwygEditor/renders/mixins/index.js +1 -1
- package/src/components/ui/WysiwygEditor/tools-and-commands.js +50 -49
- package/src/components/ui/WysiwygEditor/utils.js +20 -6
- package/styleguide.config.js +7 -1
- package/src/components/ui/WysiwygEditor.md +0 -18
package/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Avatar from './src/components/ui/Avatar.vue';
|
|
2
|
+
import Badge from './src/components/ui/Badge.vue';
|
|
3
|
+
import Collapse from './src/components/ui/Collapse.vue';
|
|
4
|
+
import ColorPicker from './src/components/ui/ColorPicker.vue';
|
|
5
|
+
import Datalist from './src/components/ui/Datalist.vue';
|
|
6
|
+
import DatePicker from './src/components/ui/DatePicker.vue';
|
|
7
|
+
import FileSelector from './src/components/ui/FileSelector.vue';
|
|
8
|
+
import Image from './src/components/ui/Image.vue';
|
|
9
|
+
import InputAutocomplete from './src/components/ui/InputAutocomplete.vue';
|
|
10
|
+
import InputColorPicker from './src/components/ui/InputColorPicker.vue';
|
|
11
|
+
import InputDatePicker from './src/components/ui/InputDatePicker.vue';
|
|
12
|
+
import InputTags from './src/components/ui/InputTags.vue';
|
|
13
|
+
import InputTimePicker from './src/components/ui/InputTimePicker.vue';
|
|
14
|
+
import InputUnits from './src/components/ui/InputUnits.vue';
|
|
15
|
+
import Lazy from './src/components/ui/Lazy.vue';
|
|
16
|
+
import Pagination from './src/components/ui/Pagination.vue';
|
|
17
|
+
import Paginator from './src/components/ui/Paginator.vue';
|
|
18
|
+
import Popover from './src/components/ui/Popover.vue';
|
|
19
|
+
import Popup from './src/components/ui/Popup.vue';
|
|
20
|
+
import ResponsiveContainer from './src/components/ui/ResponsiveContainer.vue';
|
|
21
|
+
import Select from './src/components/ui/Select.vue';
|
|
22
|
+
import TimePicker from './src/components/ui/TimePicker.vue';
|
|
23
|
+
import Tooltip from './src/components/ui/Tooltip.vue';
|
|
24
|
+
import Grid from './src/components/ui/Grid.vue';
|
|
25
|
+
import { WysiwygEditor, WysiwygConsts, WysiwygRenderMixins } from './src/components/ui/WysiwygEditor';
|
|
26
|
+
// utils stuff
|
|
27
|
+
import FormComponent from './src/components/ui/utils/FormComponent';
|
|
28
|
+
|
|
29
|
+
const Utils = { FormComponent, ...WysiwygRenderMixins };
|
|
30
|
+
const Constants = { ...WysiwygConsts };
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
Utils,
|
|
34
|
+
Constants,
|
|
35
|
+
Avatar,
|
|
36
|
+
Badge,
|
|
37
|
+
Collapse,
|
|
38
|
+
ColorPicker,
|
|
39
|
+
Datalist,
|
|
40
|
+
DatePicker,
|
|
41
|
+
FileSelector,
|
|
42
|
+
Image,
|
|
43
|
+
InputAutocomplete,
|
|
44
|
+
InputColorPicker,
|
|
45
|
+
InputDatePicker,
|
|
46
|
+
InputTags,
|
|
47
|
+
InputTimePicker,
|
|
48
|
+
InputUnits,
|
|
49
|
+
Lazy,
|
|
50
|
+
Pagination,
|
|
51
|
+
Paginator,
|
|
52
|
+
Popover,
|
|
53
|
+
Popup,
|
|
54
|
+
ResponsiveContainer,
|
|
55
|
+
Select,
|
|
56
|
+
TimePicker,
|
|
57
|
+
Tooltip,
|
|
58
|
+
Grid,
|
|
59
|
+
WysiwygEditor
|
|
60
|
+
};
|
package/index.js
CHANGED
|
@@ -22,12 +22,12 @@ import Select from './src/components/ui/Select.vue';
|
|
|
22
22
|
import TimePicker from './src/components/ui/TimePicker.vue';
|
|
23
23
|
import Tooltip from './src/components/ui/Tooltip.vue';
|
|
24
24
|
import Grid from './src/components/ui/Grid.vue';
|
|
25
|
-
import WysiwygEditor,
|
|
25
|
+
import { WysiwygEditor, WysiwygConsts, WysiwygRenderMixins } from './src/components/ui/WysiwygEditor';
|
|
26
26
|
// utils stuff
|
|
27
27
|
import FormComponent from './src/components/ui/utils/FormComponent';
|
|
28
28
|
|
|
29
|
-
const Utils = { FormComponent };
|
|
30
|
-
const Constants = {
|
|
29
|
+
const Utils = { FormComponent, ...WysiwygRenderMixins };
|
|
30
|
+
const Constants = { ...WysiwygConsts };
|
|
31
31
|
|
|
32
32
|
export {
|
|
33
33
|
Utils,
|
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Simple example
|
|
2
|
+
```vue
|
|
3
|
+
<template>
|
|
4
|
+
<div class="pad-l5">
|
|
5
|
+
<ui-wysiwyg-editor v-model="model"></ui-wysiwyg-editor>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
<script>
|
|
9
|
+
import UiWysiwygEditor from './WysiwygEditor.vue';
|
|
10
|
+
export default {
|
|
11
|
+
components: { UiWysiwygEditor },
|
|
12
|
+
data: () => ({
|
|
13
|
+
model: `<p>This WYSIWYG is based on
|
|
14
|
+
<a target="_blank" rel="noopener noreferrer nofollow" href="https://tiptap.dev/" class="color-link">tiptap</a>
|
|
15
|
+
editor framework.</p>`
|
|
16
|
+
})
|
|
17
|
+
};
|
|
18
|
+
</script>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Advanced example. Using custom tool groups, bubble menu and 'change' event instead of 'input'
|
|
22
|
+
|
|
23
|
+
```vue
|
|
24
|
+
<template>
|
|
25
|
+
<div class="pad-l5">
|
|
26
|
+
<ui-wysiwyg-editor
|
|
27
|
+
v-bind="{
|
|
28
|
+
value: model,
|
|
29
|
+
tools,
|
|
30
|
+
focusVisible: false,
|
|
31
|
+
bubbleMenu: { isEnabled: true}
|
|
32
|
+
}"
|
|
33
|
+
@change="onChange"></ui-wysiwyg-editor>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
<script>
|
|
37
|
+
import UiWysiwygEditor from './WysiwygEditor.vue';
|
|
38
|
+
import { createTool, ToolType } from './constants';
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
components: { UiWysiwygEditor },
|
|
42
|
+
data: () => ({
|
|
43
|
+
model: `<p><strong>select text</strong> to see a formatting menu pop up</p>`,
|
|
44
|
+
tools: [
|
|
45
|
+
{
|
|
46
|
+
title: '',
|
|
47
|
+
group: [
|
|
48
|
+
ToolType.UNDO,
|
|
49
|
+
ToolType.REDO,
|
|
50
|
+
ToolType.PARAGRAPH_STYLE,
|
|
51
|
+
ToolType.TEXT_COLOR,
|
|
52
|
+
createTool({
|
|
53
|
+
name: ToolType.HORIZONTAL_RULE,
|
|
54
|
+
icon: 'minus',
|
|
55
|
+
title: 'Вертикальный разделитель',
|
|
56
|
+
exec() {
|
|
57
|
+
this.editor.chain().focus().setHorizontalRule().run();
|
|
58
|
+
},
|
|
59
|
+
isEnabled() {
|
|
60
|
+
return this.editor.can().setHorizontalRule();
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}),
|
|
67
|
+
methods: {
|
|
68
|
+
onChange(value) {
|
|
69
|
+
this.model = value;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
</script>
|
|
74
|
+
```
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
:key="groupIndex"
|
|
18
18
|
class="col col-vmid col-auto">
|
|
19
19
|
<div class="d-flex flex-col flex-v-center">
|
|
20
|
-
<div class="group-header">
|
|
20
|
+
<div v-if="resolveGroupTitle(title, groupIndex) !== ''" class="group-header">
|
|
21
21
|
<!--
|
|
22
22
|
@slot Group header slot
|
|
23
23
|
@binding {number} groupIndex index of the tools group
|
|
@@ -60,19 +60,17 @@
|
|
|
60
60
|
<script>
|
|
61
61
|
import { Editor, EditorContent } from '@tiptap/vue-2';
|
|
62
62
|
|
|
63
|
-
import { debounce } from '
|
|
64
|
-
import Grid from '
|
|
65
|
-
import { resolveExtensions } from './
|
|
66
|
-
import { buildToolGroups, bindContext } from './
|
|
67
|
-
import { DefaultTools } from './
|
|
68
|
-
|
|
69
|
-
export { ToolType } from './WysiwygEditor/constants';
|
|
63
|
+
import { debounce } from '../utils/Helpers';
|
|
64
|
+
import Grid from '../Grid.vue';
|
|
65
|
+
import { resolveExtensions } from './extensions';
|
|
66
|
+
import { buildToolGroups, bindContext } from './utils';
|
|
67
|
+
import { DefaultTools } from './constants';
|
|
70
68
|
|
|
71
69
|
/**
|
|
72
70
|
* @typedef {Omit<import('@tiptap/extension-bubble-menu').BubbleMenuOptions, 'element'>} BubbleMenuOptions
|
|
73
71
|
* @property {boolean} isEnabled
|
|
74
72
|
* @typedef {import('vue').PropOptions.<BubbleMenuOptions>} BubbleMenuOptionsProp
|
|
75
|
-
* @typedef {import('./
|
|
73
|
+
* @typedef {import('./constants').ITool} ITool
|
|
76
74
|
*/
|
|
77
75
|
|
|
78
76
|
export default {
|
|
@@ -89,11 +87,11 @@ export default {
|
|
|
89
87
|
default: '',
|
|
90
88
|
},
|
|
91
89
|
/**
|
|
92
|
-
* array of using tools: { title: string, group: string
|
|
90
|
+
* array of using tools: { title: string, group: Array<string|ITool> }
|
|
93
91
|
*/
|
|
94
92
|
tools: {
|
|
95
93
|
type: Array,
|
|
96
|
-
default: () =>
|
|
94
|
+
default: () => DefaultTools,
|
|
97
95
|
validator: (tools) => tools.every((tool) => typeof tool === 'object' && Array.isArray(tool) === false)
|
|
98
96
|
},
|
|
99
97
|
/**
|
|
@@ -136,11 +134,10 @@ export default {
|
|
|
136
134
|
return this.editor?.getHTML() ?? '';
|
|
137
135
|
},
|
|
138
136
|
/**
|
|
139
|
-
* @return {{title: string, group:
|
|
137
|
+
* @return {{title: string, group: ITool[]}[]}
|
|
140
138
|
*/
|
|
141
139
|
toolGroups() {
|
|
142
|
-
|
|
143
|
-
return buildToolGroups(tools);
|
|
140
|
+
return buildToolGroups(this.tools);
|
|
144
141
|
},
|
|
145
142
|
editorClass() {
|
|
146
143
|
const classes = ['pad-3', 'scroll-y'];
|
|
@@ -231,8 +228,8 @@ export default {
|
|
|
231
228
|
this.caretPosition = transaction.curSelection.to;
|
|
232
229
|
},
|
|
233
230
|
/**
|
|
234
|
-
* @param {
|
|
235
|
-
* @return
|
|
231
|
+
* @param {ITool} tool
|
|
232
|
+
* @return {ITool}
|
|
236
233
|
*/
|
|
237
234
|
buildToolBinds(tool) {
|
|
238
235
|
const { editor, toolGroups } = this;
|
|
@@ -20,15 +20,15 @@ export type Render = Readonly<{
|
|
|
20
20
|
IMAGE: Image;
|
|
21
21
|
}>;
|
|
22
22
|
|
|
23
|
-
export
|
|
23
|
+
export interface ICommand {
|
|
24
24
|
name: String;
|
|
25
25
|
title: String;
|
|
26
26
|
exec: () => void;
|
|
27
27
|
isActive: () => Boolean;
|
|
28
28
|
isEnabled: () => Boolean;
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
30
|
|
|
31
|
-
export
|
|
31
|
+
export interface ITool {
|
|
32
32
|
name: String;
|
|
33
33
|
render: Render;
|
|
34
34
|
title: String;
|
|
@@ -37,9 +37,9 @@ export type ToolDef = {
|
|
|
37
37
|
isActive: () => Boolean;
|
|
38
38
|
isEnabled: () => Boolean;
|
|
39
39
|
getValue?: () => String | Record<String, any>;
|
|
40
|
-
options?: Array<String |
|
|
40
|
+
options?: Array<String | ITool | ICommand>;
|
|
41
41
|
units?: Array<String>
|
|
42
|
-
}
|
|
42
|
+
}
|
|
43
43
|
|
|
44
44
|
export type NodeType = Readonly<{
|
|
45
45
|
BLOCKQUOTE: 'blockquote',
|
|
@@ -126,3 +126,12 @@ export type ToolType = Readonly<{
|
|
|
126
126
|
TOGGLE_ZEBRA: 'toggleZebra',
|
|
127
127
|
INSERT_IMAGE: 'insertImage'
|
|
128
128
|
}>;
|
|
129
|
+
|
|
130
|
+
export type DefaultTools = Array<{
|
|
131
|
+
title: string,
|
|
132
|
+
group: Array<string|ITool>
|
|
133
|
+
}>;
|
|
134
|
+
|
|
135
|
+
export function createTool(toolOptions: Partial<ITool>): ITool;
|
|
136
|
+
|
|
137
|
+
export function createCommand(commandOptions: Partial<ICommand>): ICommand;
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
} from './renders';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @typedef {import('./
|
|
14
|
-
* @typedef {import('./
|
|
15
|
-
* @typedef {import('./
|
|
16
|
-
* @typedef {import('./
|
|
17
|
-
* @typedef {import('./
|
|
18
|
-
* @typedef {import('./
|
|
19
|
-
* @typedef {import('./
|
|
13
|
+
* @typedef {import('./constants').NodeType} NodeType
|
|
14
|
+
* @typedef {import('./constants').MarkType} MarkType
|
|
15
|
+
* @typedef {import('./constants').CommandType} CommandType
|
|
16
|
+
* @typedef {import('./constants').ToolType} ToolType
|
|
17
|
+
* @typedef {import('./constants').Render} Render
|
|
18
|
+
* @typedef {import('./constants').ICommand} ICommand
|
|
19
|
+
* @typedef {import('./constants').ITool} ITool
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -129,16 +129,16 @@ export const ToolType = Object.freeze({
|
|
|
129
129
|
});
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
|
-
* @param {
|
|
133
|
-
* @return
|
|
132
|
+
* @param {Partial<ICommand>} command
|
|
133
|
+
* @return {ICommand}
|
|
134
134
|
*/
|
|
135
135
|
export const createCommand = ({
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
name = '',
|
|
137
|
+
title = 'Unknown command',
|
|
138
|
+
exec = () => {},
|
|
139
|
+
isActive = () => false,
|
|
140
|
+
isEnabled = () => true
|
|
141
|
+
}) => ({
|
|
142
142
|
name,
|
|
143
143
|
title,
|
|
144
144
|
exec,
|
|
@@ -161,97 +161,27 @@ export const Render = Object.freeze({
|
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
/**
|
|
164
|
-
* @param {
|
|
165
|
-
* @return
|
|
164
|
+
* @param {Partial<ITool>} tool
|
|
165
|
+
* @return {ITool}
|
|
166
166
|
*/
|
|
167
|
-
export const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
167
|
+
export const createTool = ({
|
|
168
|
+
name = '',
|
|
169
|
+
render = Render.BUTTON,
|
|
170
|
+
title = 'Unknown tool',
|
|
171
|
+
icon = 'help-circle-outline',
|
|
172
|
+
exec = () => {},
|
|
173
|
+
isActive = () => false,
|
|
174
|
+
isEnabled = () => true,
|
|
175
|
+
...optionalRest
|
|
176
|
+
}) => ({
|
|
176
177
|
name,
|
|
177
178
|
render,
|
|
178
179
|
title,
|
|
179
180
|
icon,
|
|
180
181
|
exec,
|
|
181
182
|
isActive,
|
|
182
|
-
isEnabled
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* @param {Tool} toolOptions
|
|
187
|
-
* @return Tool
|
|
188
|
-
*/
|
|
189
|
-
export const createButtonTool = (toolOptions) => createBaseTool(toolOptions);
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* @param {Tool} tool
|
|
193
|
-
* @return Tool
|
|
194
|
-
*/
|
|
195
|
-
export const createSelectTool = ({ getValue = () => null, options = [], ...toolOptions }) => ({
|
|
196
|
-
...createBaseTool({ render: Render.SELECT, ...toolOptions }),
|
|
197
|
-
getValue,
|
|
198
|
-
options
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* @param {Tool} tool
|
|
203
|
-
* @return Tool
|
|
204
|
-
*/
|
|
205
|
-
export const createColorPickerTool = ({ getValue = () => null, ...toolOptions }) => ({
|
|
206
|
-
...createBaseTool({ render: Render.COLOR_PICKER, ...toolOptions }),
|
|
207
|
-
getValue
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* @param {Tool} tool
|
|
212
|
-
* @return Tool
|
|
213
|
-
*/
|
|
214
|
-
export const createInputUnitsTool = ({ getValue = () => null, units = [], ...toolOptions }) => ({
|
|
215
|
-
...createBaseTool({ render: Render.INPUT_UNITS, ...toolOptions }),
|
|
216
|
-
getValue,
|
|
217
|
-
units
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* @param {Tool} tool
|
|
222
|
-
* @return Tool
|
|
223
|
-
*/
|
|
224
|
-
export const createToolbarPopoverTool = ({ options = [], ...toolOptions }) => ({
|
|
225
|
-
...createBaseTool({ render: Render.TOOLBAR_POPOVER, ...toolOptions }),
|
|
226
|
-
options
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* @param {Tool} tool
|
|
231
|
-
* @return Tool
|
|
232
|
-
*/
|
|
233
|
-
export const createInputAutoTool = ({ getValue = () => null, options = [], ...toolOptions }) => ({
|
|
234
|
-
...createBaseTool({ render: Render.INPUT_AUTO, ...toolOptions }),
|
|
235
|
-
getValue,
|
|
236
|
-
options
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* @param {Tool} tool
|
|
241
|
-
* @return Tool
|
|
242
|
-
*/
|
|
243
|
-
export const createImageTool = ({ getValue = () => null, ...toolOptions }) => ({
|
|
244
|
-
...createBaseTool({ render: Render.IMAGE, ...toolOptions }),
|
|
245
|
-
getValue
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* @param {Tool} tool
|
|
250
|
-
* @return Tool
|
|
251
|
-
*/
|
|
252
|
-
export const createLinkTool = ({ getValue = () => null, ...toolOptions }) => ({
|
|
253
|
-
...createBaseTool({ render: Render.LINK, ...toolOptions }),
|
|
254
|
-
getValue
|
|
183
|
+
isEnabled,
|
|
184
|
+
...optionalRest
|
|
255
185
|
});
|
|
256
186
|
|
|
257
187
|
export const DefaultTools = [
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { default as WysiwygEditor } from '
|
|
2
|
-
export * from './constants'
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './tools-and-commands';
|
|
1
|
+
export { default as WysiwygEditor } from './WysiwygEditor.vue';
|
|
2
|
+
export * as WysiwygConsts from './constants';
|
|
3
|
+
export * as WysiwygRenderMixins from './renders/mixins';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { default as WysiwygEditor } from '
|
|
2
|
-
export * from './constants'
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './tools-and-commands';
|
|
1
|
+
export { default as WysiwygEditor } from './WysiwygEditor.vue';
|
|
2
|
+
export * as WysiwygConsts from './constants';
|
|
3
|
+
export * as WysiwygRenderMixins from './renders/mixins';
|
|
@@ -14,11 +14,12 @@
|
|
|
14
14
|
</template>
|
|
15
15
|
|
|
16
16
|
<script>
|
|
17
|
-
import { useRender } from './mixins';
|
|
17
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
18
18
|
|
|
19
19
|
export default {
|
|
20
20
|
mixins: [useRender()],
|
|
21
21
|
methods: {
|
|
22
|
+
...RenderMixinTypes,
|
|
22
23
|
onClick() {
|
|
23
24
|
this.tool.exec();
|
|
24
25
|
this.emitExecuted();
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import ColorPicker from '../../ColorPicker.vue';
|
|
19
19
|
import Popover from '../../Popover.vue';
|
|
20
20
|
import WithPopover from '../../utils/WithPopover';
|
|
21
|
-
import { useRender } from './mixins';
|
|
21
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
22
22
|
|
|
23
23
|
export default {
|
|
24
24
|
components: { ColorPicker, Popover },
|
|
@@ -29,6 +29,7 @@ export default {
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
methods: {
|
|
32
|
+
...RenderMixinTypes,
|
|
32
33
|
onSubmit({ rgba }) {
|
|
33
34
|
const { r: red, g: green, b: blue, a: alpha } = rgba;
|
|
34
35
|
const color = `rgba(${red}, ${green}, ${blue}, ${alpha})`;
|
|
@@ -106,9 +106,9 @@ import InputAutocomplete from '../../InputAutocomplete.vue';
|
|
|
106
106
|
import InputUnits from '../../InputUnits.vue';
|
|
107
107
|
import UiSelect from '../../Select.vue';
|
|
108
108
|
import WithPopover from './components/WithPopover.vue';
|
|
109
|
-
import { useRender } from './mixins';
|
|
109
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
110
110
|
|
|
111
|
-
const SizeUnits = [
|
|
111
|
+
const SizeUnits = ['rem', 'em', '%', 'px', 'vh', 'vw'];
|
|
112
112
|
const AlignOptions = [
|
|
113
113
|
{ value: null, label: 'По левому краю' },
|
|
114
114
|
{ value: 'mar-h-auto', label: 'По центру' },
|
|
@@ -163,6 +163,7 @@ export default {
|
|
|
163
163
|
AlignOptions
|
|
164
164
|
},
|
|
165
165
|
methods: {
|
|
166
|
+
...RenderMixinTypes,
|
|
166
167
|
setImageSettings() {
|
|
167
168
|
const attrs = this.tool.getValue();
|
|
168
169
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
10
|
import InputAutocomplete from '../../InputAutocomplete.vue';
|
|
11
|
-
import { useRender } from './mixins';
|
|
11
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
14
|
components: { InputAutocomplete },
|
|
@@ -19,6 +19,7 @@ export default {
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
methods: {
|
|
22
|
+
...RenderMixinTypes,
|
|
22
23
|
onInput(value) {
|
|
23
24
|
this.tool.exec(value);
|
|
24
25
|
this.emitExecuted();
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
10
|
import InputUnits from '../../InputUnits.vue';
|
|
11
|
-
import { useRender } from './mixins';
|
|
11
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
14
|
components: { InputUnits },
|
|
@@ -22,6 +22,7 @@ export default {
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
methods: {
|
|
25
|
+
...RenderMixinTypes,
|
|
25
26
|
onChange(value) {
|
|
26
27
|
this.tool.exec(value);
|
|
27
28
|
this.emitExecuted();
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
import InputAutocomplete from '../../InputAutocomplete.vue';
|
|
40
40
|
import UiSelect from '../../Select.vue';
|
|
41
41
|
import WithPopover from './components/WithPopover.vue';
|
|
42
|
-
import { useRender } from './mixins';
|
|
42
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
43
43
|
|
|
44
44
|
const TargetType = {
|
|
45
45
|
BLANK: '_blank',
|
|
@@ -74,6 +74,7 @@ export default {
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
methods: {
|
|
77
|
+
...RenderMixinTypes,
|
|
77
78
|
execute() {
|
|
78
79
|
const { tool, url, target } = this;
|
|
79
80
|
tool.exec({ url, target });
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<script>
|
|
11
11
|
import UiSelect from '../../Select.vue';
|
|
12
|
-
import { useRender } from './mixins';
|
|
12
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
13
13
|
|
|
14
14
|
export default {
|
|
15
15
|
components: { UiSelect },
|
|
@@ -32,6 +32,7 @@ export default {
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
methods: {
|
|
35
|
+
...RenderMixinTypes,
|
|
35
36
|
onChange(option) {
|
|
36
37
|
this.tool.exec(this.valueObjects ? option.value : option);
|
|
37
38
|
this.emitExecuted();
|
|
@@ -27,12 +27,13 @@
|
|
|
27
27
|
import Popover from '../../Popover.vue';
|
|
28
28
|
import UiDatalist from '../../Datalist.vue';
|
|
29
29
|
import WithPopover from '../../utils/WithPopover';
|
|
30
|
-
import { useRender } from './mixins';
|
|
30
|
+
import { useRender, RenderMixinTypes } from './mixins';
|
|
31
31
|
|
|
32
32
|
export default {
|
|
33
33
|
components: { Popover, UiDatalist },
|
|
34
34
|
mixins: [useRender(), WithPopover],
|
|
35
35
|
methods: {
|
|
36
|
+
...RenderMixinTypes,
|
|
36
37
|
onCommandExecuted() {
|
|
37
38
|
this.popoverShow = false;
|
|
38
39
|
this.emitExecuted();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ComponentOptions } from 'vue';
|
|
2
|
+
import { ITool } from '../../constants';
|
|
3
|
+
|
|
4
|
+
interface IRenderMixinInstance {
|
|
5
|
+
// props
|
|
6
|
+
tool: ITool;
|
|
7
|
+
|
|
8
|
+
// computed
|
|
9
|
+
readonly icon: string;
|
|
10
|
+
readonly title: string;
|
|
11
|
+
readonly isActive: boolean;
|
|
12
|
+
readonly isEnabled: boolean;
|
|
13
|
+
|
|
14
|
+
/** to notify the wysiwyg-editor that a command was executed */
|
|
15
|
+
emitExecuted(): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const RenderMixinTypes: IRenderMixinInstance = undefined;
|
|
19
|
+
|
|
20
|
+
export function useRender(): ComponentOptions;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
/** @return {import('vue').ComponentOptions} */
|
|
1
2
|
export const useRender = () => ({
|
|
2
3
|
props: {
|
|
4
|
+
/** @type {import('vue').PropOptions<import('../../constants').ITool>}*/
|
|
3
5
|
tool: {
|
|
4
6
|
type: Object,
|
|
5
7
|
default: null
|
|
6
8
|
}
|
|
7
9
|
},
|
|
8
10
|
computed: {
|
|
11
|
+
/** @return {string} */
|
|
9
12
|
icon() {
|
|
10
13
|
const { tool } = this;
|
|
11
14
|
|
|
@@ -15,6 +18,7 @@ export const useRender = () => ({
|
|
|
15
18
|
|
|
16
19
|
return [null, undefined, ''].includes(tool.icon) ? 'mdi-help-box' : `mdi-${tool.icon}`;
|
|
17
20
|
},
|
|
21
|
+
/** @return {string} */
|
|
18
22
|
title() {
|
|
19
23
|
const { tool } = this;
|
|
20
24
|
|
|
@@ -24,16 +28,21 @@ export const useRender = () => ({
|
|
|
24
28
|
|
|
25
29
|
return tool.title ?? tool.name ?? 'Unknown tool';
|
|
26
30
|
},
|
|
31
|
+
/** @return {boolean} */
|
|
27
32
|
isActive() {
|
|
28
33
|
return this.tool.isActive();
|
|
29
34
|
},
|
|
35
|
+
/** @return {boolean} */
|
|
30
36
|
isEnabled() {
|
|
31
37
|
return this.tool.isEnabled();
|
|
32
38
|
}
|
|
33
39
|
},
|
|
34
40
|
methods: {
|
|
41
|
+
/** to notify the wysiwyg-editor that a command was executed */
|
|
35
42
|
emitExecuted() {
|
|
36
43
|
this.$emit('command-executed');
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
|
-
})
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const RenderMixinTypes = undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './RenderMixin';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './RenderMixin';
|
|
@@ -3,15 +3,9 @@ import {
|
|
|
3
3
|
MarkType,
|
|
4
4
|
CommandType,
|
|
5
5
|
ToolType,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
Render,
|
|
7
|
+
createTool,
|
|
8
8
|
createCommand,
|
|
9
|
-
createInputUnitsTool,
|
|
10
|
-
createSelectTool,
|
|
11
|
-
createToolbarPopoverTool,
|
|
12
|
-
createInputAutoTool,
|
|
13
|
-
createLinkTool,
|
|
14
|
-
createImageTool,
|
|
15
9
|
} from './constants';
|
|
16
10
|
|
|
17
11
|
export const CommandMap = {
|
|
@@ -164,7 +158,7 @@ export const CommandMap = {
|
|
|
164
158
|
};
|
|
165
159
|
|
|
166
160
|
export const TableOptionsMap = {
|
|
167
|
-
[ToolType.INSERT_TABLE]:
|
|
161
|
+
[ToolType.INSERT_TABLE]: createTool({
|
|
168
162
|
name: ToolType.INSERT_TABLE,
|
|
169
163
|
icon: 'table',
|
|
170
164
|
title: 'Вставить таблицу',
|
|
@@ -179,7 +173,7 @@ export const TableOptionsMap = {
|
|
|
179
173
|
return this.editor.can().insertTable();
|
|
180
174
|
}
|
|
181
175
|
}),
|
|
182
|
-
[ToolType.DELETE_TABLE]:
|
|
176
|
+
[ToolType.DELETE_TABLE]: createTool({
|
|
183
177
|
name: ToolType.DELETE_TABLE,
|
|
184
178
|
icon: 'table-remove',
|
|
185
179
|
title: 'Удалить таблицу',
|
|
@@ -190,7 +184,7 @@ export const TableOptionsMap = {
|
|
|
190
184
|
return this.editor.can().deleteTable();
|
|
191
185
|
}
|
|
192
186
|
}),
|
|
193
|
-
[ToolType.ADD_COLUMN_BEFORE]:
|
|
187
|
+
[ToolType.ADD_COLUMN_BEFORE]: createTool({
|
|
194
188
|
name: ToolType.ADD_COLUMN_BEFORE,
|
|
195
189
|
icon: 'table-column-plus-before',
|
|
196
190
|
title: 'Добавить колонку перед',
|
|
@@ -201,7 +195,7 @@ export const TableOptionsMap = {
|
|
|
201
195
|
return this.editor.can().addColumnBefore();
|
|
202
196
|
}
|
|
203
197
|
}),
|
|
204
|
-
[ToolType.ADD_COLUMN_AFTER]:
|
|
198
|
+
[ToolType.ADD_COLUMN_AFTER]: createTool({
|
|
205
199
|
name: ToolType.ADD_COLUMN_AFTER,
|
|
206
200
|
icon: 'table-column-plus-after',
|
|
207
201
|
title: 'Добавить колонку после',
|
|
@@ -212,7 +206,7 @@ export const TableOptionsMap = {
|
|
|
212
206
|
return this.editor.can().addColumnAfter();
|
|
213
207
|
}
|
|
214
208
|
}),
|
|
215
|
-
[ToolType.DELETE_COLUMN]:
|
|
209
|
+
[ToolType.DELETE_COLUMN]: createTool({
|
|
216
210
|
name: ToolType.DELETE_COLUMN,
|
|
217
211
|
icon: 'table-column-remove',
|
|
218
212
|
title: 'Удалить колонку',
|
|
@@ -223,7 +217,7 @@ export const TableOptionsMap = {
|
|
|
223
217
|
return this.editor.can().deleteColumn();
|
|
224
218
|
}
|
|
225
219
|
}),
|
|
226
|
-
[ToolType.ADD_ROW_BEFORE]:
|
|
220
|
+
[ToolType.ADD_ROW_BEFORE]: createTool({
|
|
227
221
|
name: ToolType.ADD_ROW_BEFORE,
|
|
228
222
|
icon: 'table-row-plus-before',
|
|
229
223
|
title: 'Добавить строку перед',
|
|
@@ -234,7 +228,7 @@ export const TableOptionsMap = {
|
|
|
234
228
|
return this.editor.can().addRowBefore();
|
|
235
229
|
}
|
|
236
230
|
}),
|
|
237
|
-
[ToolType.ADD_ROW_AFTER]:
|
|
231
|
+
[ToolType.ADD_ROW_AFTER]: createTool({
|
|
238
232
|
name: ToolType.ADD_ROW_AFTER,
|
|
239
233
|
icon: 'table-row-plus-after',
|
|
240
234
|
title: 'Добавить строку после',
|
|
@@ -245,7 +239,7 @@ export const TableOptionsMap = {
|
|
|
245
239
|
return this.editor.can().addRowAfter();
|
|
246
240
|
}
|
|
247
241
|
}),
|
|
248
|
-
[ToolType.DELETE_ROW]:
|
|
242
|
+
[ToolType.DELETE_ROW]: createTool({
|
|
249
243
|
name: ToolType.DELETE_ROW,
|
|
250
244
|
icon: 'table-row-remove',
|
|
251
245
|
title: 'Удалить строку',
|
|
@@ -256,7 +250,7 @@ export const TableOptionsMap = {
|
|
|
256
250
|
return this.editor.can().deleteRow();
|
|
257
251
|
}
|
|
258
252
|
}),
|
|
259
|
-
[ToolType.MERGE_CELLS]:
|
|
253
|
+
[ToolType.MERGE_CELLS]: createTool({
|
|
260
254
|
name: ToolType.MERGE_CELLS,
|
|
261
255
|
icon: 'table-merge-cells',
|
|
262
256
|
title: 'Объединить ячейки',
|
|
@@ -267,7 +261,7 @@ export const TableOptionsMap = {
|
|
|
267
261
|
return this.editor.can().mergeCells();
|
|
268
262
|
}
|
|
269
263
|
}),
|
|
270
|
-
[ToolType.SPLIT_CELL]:
|
|
264
|
+
[ToolType.SPLIT_CELL]: createTool({
|
|
271
265
|
name: ToolType.SPLIT_CELL,
|
|
272
266
|
icon: 'table-split-cell',
|
|
273
267
|
title: 'Разделить ячейки',
|
|
@@ -278,7 +272,7 @@ export const TableOptionsMap = {
|
|
|
278
272
|
return this.editor.can().splitCell();
|
|
279
273
|
}
|
|
280
274
|
}),
|
|
281
|
-
[ToolType.TOGGLE_HEADER_ROW]:
|
|
275
|
+
[ToolType.TOGGLE_HEADER_ROW]: createTool({
|
|
282
276
|
name: ToolType.TOGGLE_HEADER_ROW,
|
|
283
277
|
icon: 'table-row-height',
|
|
284
278
|
title: 'Переключить строку заголовка',
|
|
@@ -289,7 +283,7 @@ export const TableOptionsMap = {
|
|
|
289
283
|
return this.editor.can().toggleHeaderRow();
|
|
290
284
|
}
|
|
291
285
|
}),
|
|
292
|
-
[ToolType.TOGGLE_HEADER_COLUMN]:
|
|
286
|
+
[ToolType.TOGGLE_HEADER_COLUMN]: createTool({
|
|
293
287
|
name: ToolType.TOGGLE_HEADER_COLUMN,
|
|
294
288
|
icon: 'table-column-width',
|
|
295
289
|
title: 'Переключить колонку заголовка',
|
|
@@ -300,7 +294,7 @@ export const TableOptionsMap = {
|
|
|
300
294
|
return this.editor.can().toggleHeaderColumn();
|
|
301
295
|
}
|
|
302
296
|
}),
|
|
303
|
-
[ToolType.ALIGN_V_TOP]:
|
|
297
|
+
[ToolType.ALIGN_V_TOP]: createTool({
|
|
304
298
|
name: ToolType.ALIGN_V_TOP,
|
|
305
299
|
icon: 'align-vertical-top',
|
|
306
300
|
title: 'Выровнять по верхнему краю',
|
|
@@ -316,7 +310,7 @@ export const TableOptionsMap = {
|
|
|
316
310
|
return classNames?.includes('table-vtop') ?? false;
|
|
317
311
|
}
|
|
318
312
|
}),
|
|
319
|
-
[ToolType.ALIGN_V_MID]:
|
|
313
|
+
[ToolType.ALIGN_V_MID]: createTool({
|
|
320
314
|
name: ToolType.ALIGN_V_MID,
|
|
321
315
|
icon: 'align-vertical-center',
|
|
322
316
|
title: 'Выровнять по центру',
|
|
@@ -332,7 +326,7 @@ export const TableOptionsMap = {
|
|
|
332
326
|
return classNames?.includes('table-vmid') ?? false;
|
|
333
327
|
}
|
|
334
328
|
}),
|
|
335
|
-
[ToolType.ALIGN_V_BOT]:
|
|
329
|
+
[ToolType.ALIGN_V_BOT]: createTool({
|
|
336
330
|
name: ToolType.ALIGN_V_BOT,
|
|
337
331
|
icon: 'align-vertical-bottom',
|
|
338
332
|
title: 'Выровнять по нижнему краю',
|
|
@@ -348,7 +342,7 @@ export const TableOptionsMap = {
|
|
|
348
342
|
return classNames?.includes('table-vbot') ?? false;
|
|
349
343
|
}
|
|
350
344
|
}),
|
|
351
|
-
[ToolType.TOGGLE_BORDERS]:
|
|
345
|
+
[ToolType.TOGGLE_BORDERS]: createTool({
|
|
352
346
|
name: ToolType.TOGGLE_BORDERS,
|
|
353
347
|
icon: 'border-all',
|
|
354
348
|
title: 'Границы',
|
|
@@ -364,7 +358,7 @@ export const TableOptionsMap = {
|
|
|
364
358
|
return classNames?.includes('table-borders') ?? false;
|
|
365
359
|
}
|
|
366
360
|
}),
|
|
367
|
-
[ToolType.TOGGLE_ZEBRA]:
|
|
361
|
+
[ToolType.TOGGLE_ZEBRA]: createTool({
|
|
368
362
|
name: ToolType.TOGGLE_ZEBRA,
|
|
369
363
|
icon: 'view-stream',
|
|
370
364
|
title: 'Стиль "зебра"',
|
|
@@ -383,7 +377,7 @@ export const TableOptionsMap = {
|
|
|
383
377
|
};
|
|
384
378
|
|
|
385
379
|
export const ToolsMap = {
|
|
386
|
-
[ToolType.UNDO]:
|
|
380
|
+
[ToolType.UNDO]: createTool({
|
|
387
381
|
name: ToolType.UNDO,
|
|
388
382
|
icon: 'undo-variant',
|
|
389
383
|
title: 'Назад',
|
|
@@ -394,7 +388,7 @@ export const ToolsMap = {
|
|
|
394
388
|
return this.editor.can().undo();
|
|
395
389
|
}
|
|
396
390
|
}),
|
|
397
|
-
[ToolType.REDO]:
|
|
391
|
+
[ToolType.REDO]: createTool({
|
|
398
392
|
name: ToolType.REDO,
|
|
399
393
|
icon: 'redo-variant',
|
|
400
394
|
title: 'Вперед',
|
|
@@ -405,7 +399,7 @@ export const ToolsMap = {
|
|
|
405
399
|
return this.editor.can().redo();
|
|
406
400
|
}
|
|
407
401
|
}),
|
|
408
|
-
[ToolType.SAVE]:
|
|
402
|
+
[ToolType.SAVE]: createTool({
|
|
409
403
|
name: ToolType.SAVE,
|
|
410
404
|
icon: 'content-save',
|
|
411
405
|
title: 'Сохранить',
|
|
@@ -413,8 +407,9 @@ export const ToolsMap = {
|
|
|
413
407
|
this.onChange();
|
|
414
408
|
}
|
|
415
409
|
}),
|
|
416
|
-
[ToolType.PARAGRAPH_STYLE]:
|
|
410
|
+
[ToolType.PARAGRAPH_STYLE]: createTool({
|
|
417
411
|
name: ToolType.PARAGRAPH_STYLE,
|
|
412
|
+
render: Render.SELECT,
|
|
418
413
|
title: 'Стиль параграфа',
|
|
419
414
|
exec(command) {
|
|
420
415
|
if (command.name in CommandMap && command.isEnabled()) {
|
|
@@ -435,8 +430,9 @@ export const ToolsMap = {
|
|
|
435
430
|
CommandMap[CommandType.CODE_BLOCK]
|
|
436
431
|
]
|
|
437
432
|
}),
|
|
438
|
-
[ToolType.FONT_SIZE]:
|
|
433
|
+
[ToolType.FONT_SIZE]: createTool({
|
|
439
434
|
name: ToolType.FONT_SIZE,
|
|
435
|
+
render: Render.INPUT_UNITS,
|
|
440
436
|
title: 'Размер шрифта',
|
|
441
437
|
exec(value) {
|
|
442
438
|
this.editor.commands.setFontSize(value);
|
|
@@ -455,8 +451,9 @@ export const ToolsMap = {
|
|
|
455
451
|
},
|
|
456
452
|
units: ["rem", "em", "%", "px", "vh", "vw"]
|
|
457
453
|
}),
|
|
458
|
-
[ToolType.TEXT_COLOR]:
|
|
454
|
+
[ToolType.TEXT_COLOR]: createTool({
|
|
459
455
|
name: ToolType.TEXT_COLOR,
|
|
456
|
+
render: Render.COLOR_PICKER,
|
|
460
457
|
icon: 'format-color-fill',
|
|
461
458
|
title: 'Цвет',
|
|
462
459
|
exec(value) {
|
|
@@ -466,8 +463,9 @@ export const ToolsMap = {
|
|
|
466
463
|
return this.editor.getAttributes(MarkType.TEXT_STYLE).color;
|
|
467
464
|
}
|
|
468
465
|
}),
|
|
469
|
-
[ToolType.FONT_FAMILY]:
|
|
466
|
+
[ToolType.FONT_FAMILY]: createTool({
|
|
470
467
|
name: ToolType.FONT_FAMILY,
|
|
468
|
+
render: Render.INPUT_AUTO,
|
|
471
469
|
title: 'Семейство шрифта',
|
|
472
470
|
exec(value) {
|
|
473
471
|
this.editor.commands.setFontFamily(value);
|
|
@@ -477,7 +475,7 @@ export const ToolsMap = {
|
|
|
477
475
|
},
|
|
478
476
|
options: ['serif', 'sans-serif']
|
|
479
477
|
}),
|
|
480
|
-
[ToolType.BLOCKQUOTE]:
|
|
478
|
+
[ToolType.BLOCKQUOTE]: createTool({
|
|
481
479
|
name: ToolType.BLOCKQUOTE,
|
|
482
480
|
icon: 'format-quote-close-outline',
|
|
483
481
|
title: 'Цитата',
|
|
@@ -492,7 +490,7 @@ export const ToolsMap = {
|
|
|
492
490
|
return this.editor.isActive(NodeType.BLOCKQUOTE);
|
|
493
491
|
}
|
|
494
492
|
}),
|
|
495
|
-
[ToolType.HARD_BREAK]:
|
|
493
|
+
[ToolType.HARD_BREAK]: createTool({
|
|
496
494
|
name: ToolType.HARD_BREAK,
|
|
497
495
|
title: 'Перевод строки',
|
|
498
496
|
icon: 'keyboard-return',
|
|
@@ -500,7 +498,7 @@ export const ToolsMap = {
|
|
|
500
498
|
this.editor.chain().focus().setHardBreak().run();
|
|
501
499
|
}
|
|
502
500
|
}),
|
|
503
|
-
[ToolType.CODE]:
|
|
501
|
+
[ToolType.CODE]: createTool({
|
|
504
502
|
name: ToolType.CODE,
|
|
505
503
|
icon: 'code-not-equal-variant',
|
|
506
504
|
title: 'Код',
|
|
@@ -511,8 +509,9 @@ export const ToolsMap = {
|
|
|
511
509
|
return this.editor.isActive(MarkType.CODE);
|
|
512
510
|
}
|
|
513
511
|
}),
|
|
514
|
-
[ToolType.IMAGE]:
|
|
512
|
+
[ToolType.IMAGE]: createTool({
|
|
515
513
|
name: ToolType.IMAGE,
|
|
514
|
+
render: Render.IMAGE,
|
|
516
515
|
icon: 'image-plus',
|
|
517
516
|
title: 'Изображение',
|
|
518
517
|
async exec({ url = null, isResponsive, align, width, height }) {
|
|
@@ -548,7 +547,7 @@ export const ToolsMap = {
|
|
|
548
547
|
return this.editor.getAttributes(NodeType.IMAGE);
|
|
549
548
|
}
|
|
550
549
|
}),
|
|
551
|
-
[ToolType.ORDERED_LIST]:
|
|
550
|
+
[ToolType.ORDERED_LIST]: createTool({
|
|
552
551
|
name: ToolType.ORDERED_LIST,
|
|
553
552
|
icon: 'format-list-numbered',
|
|
554
553
|
title: 'Нумерованный список',
|
|
@@ -559,7 +558,7 @@ export const ToolsMap = {
|
|
|
559
558
|
return this.editor.isActive(NodeType.ORDERED_LIST);
|
|
560
559
|
}
|
|
561
560
|
}),
|
|
562
|
-
[ToolType.BULLET_LIST]:
|
|
561
|
+
[ToolType.BULLET_LIST]: createTool({
|
|
563
562
|
name: ToolType.BULLET_LIST,
|
|
564
563
|
icon: 'format-list-bulleted',
|
|
565
564
|
title: 'Маркированный список',
|
|
@@ -570,7 +569,7 @@ export const ToolsMap = {
|
|
|
570
569
|
return this.editor.isActive(NodeType.BULLET_LIST);
|
|
571
570
|
}
|
|
572
571
|
}),
|
|
573
|
-
[ToolType.TEXT_ALIGN_LEFT]:
|
|
572
|
+
[ToolType.TEXT_ALIGN_LEFT]: createTool({
|
|
574
573
|
name: ToolType.TEXT_ALIGN_LEFT,
|
|
575
574
|
icon: 'format-align-left',
|
|
576
575
|
title: 'По левому краю',
|
|
@@ -581,7 +580,7 @@ export const ToolsMap = {
|
|
|
581
580
|
return this.editor.isActive({ textAlign: 'left' });
|
|
582
581
|
}
|
|
583
582
|
}),
|
|
584
|
-
[ToolType.TEXT_ALIGN_CENTER]:
|
|
583
|
+
[ToolType.TEXT_ALIGN_CENTER]: createTool({
|
|
585
584
|
name: ToolType.TEXT_ALIGN_CENTER,
|
|
586
585
|
icon: 'format-align-center',
|
|
587
586
|
title: 'По центру',
|
|
@@ -592,7 +591,7 @@ export const ToolsMap = {
|
|
|
592
591
|
return this.editor.isActive({ textAlign: 'center' });
|
|
593
592
|
}
|
|
594
593
|
}),
|
|
595
|
-
[ToolType.TEXT_ALIGN_RIGHT]:
|
|
594
|
+
[ToolType.TEXT_ALIGN_RIGHT]: createTool({
|
|
596
595
|
name: ToolType.TEXT_ALIGN_RIGHT,
|
|
597
596
|
icon: 'format-align-right',
|
|
598
597
|
title: 'По правому краю',
|
|
@@ -603,7 +602,7 @@ export const ToolsMap = {
|
|
|
603
602
|
return this.editor.isActive({ textAlign: 'right' });
|
|
604
603
|
}
|
|
605
604
|
}),
|
|
606
|
-
[ToolType.HORIZONTAL_RULE]:
|
|
605
|
+
[ToolType.HORIZONTAL_RULE]: createTool({
|
|
607
606
|
name: ToolType.HORIZONTAL_RULE,
|
|
608
607
|
icon: 'minus',
|
|
609
608
|
title: 'Вертикальный разделитель',
|
|
@@ -614,8 +613,9 @@ export const ToolsMap = {
|
|
|
614
613
|
return this.editor.can().setHorizontalRule();
|
|
615
614
|
}
|
|
616
615
|
}),
|
|
617
|
-
[ToolType.LINK]:
|
|
616
|
+
[ToolType.LINK]: createTool({
|
|
618
617
|
name: ToolType.LINK,
|
|
618
|
+
render: Render.LINK,
|
|
619
619
|
icon: 'link-plus',
|
|
620
620
|
title: 'Ссылка',
|
|
621
621
|
getValue() {
|
|
@@ -648,7 +648,7 @@ export const ToolsMap = {
|
|
|
648
648
|
.run();
|
|
649
649
|
}
|
|
650
650
|
}),
|
|
651
|
-
[ToolType.BOLD]:
|
|
651
|
+
[ToolType.BOLD]: createTool({
|
|
652
652
|
name: ToolType.BOLD,
|
|
653
653
|
icon: 'format-bold',
|
|
654
654
|
title: 'Жирный',
|
|
@@ -659,7 +659,7 @@ export const ToolsMap = {
|
|
|
659
659
|
return this.editor.isActive(MarkType.BOLD);
|
|
660
660
|
}
|
|
661
661
|
}),
|
|
662
|
-
[ToolType.ITALIC]:
|
|
662
|
+
[ToolType.ITALIC]: createTool({
|
|
663
663
|
name: ToolType.ITALIC,
|
|
664
664
|
icon: 'format-italic',
|
|
665
665
|
title: 'Курсив',
|
|
@@ -670,7 +670,7 @@ export const ToolsMap = {
|
|
|
670
670
|
return this.editor.isActive(MarkType.ITALIC);
|
|
671
671
|
}
|
|
672
672
|
}),
|
|
673
|
-
[ToolType.STRIKE]:
|
|
673
|
+
[ToolType.STRIKE]: createTool({
|
|
674
674
|
name: ToolType.STRIKE,
|
|
675
675
|
icon: 'format-strikethrough-variant',
|
|
676
676
|
title: 'Зачеркивание',
|
|
@@ -681,7 +681,7 @@ export const ToolsMap = {
|
|
|
681
681
|
return this.editor.isActive(MarkType.STRIKE);
|
|
682
682
|
}
|
|
683
683
|
}),
|
|
684
|
-
[ToolType.UNDERLINE]:
|
|
684
|
+
[ToolType.UNDERLINE]: createTool({
|
|
685
685
|
name: ToolType.UNDERLINE,
|
|
686
686
|
icon: 'format-underline',
|
|
687
687
|
title: 'Подчеркивание',
|
|
@@ -692,13 +692,14 @@ export const ToolsMap = {
|
|
|
692
692
|
return this.editor.isActive(MarkType.UNDERLINE);
|
|
693
693
|
}
|
|
694
694
|
}),
|
|
695
|
-
[ToolType.TABLE]:
|
|
695
|
+
[ToolType.TABLE]: createTool({
|
|
696
696
|
name: ToolType.TABLE,
|
|
697
|
+
render: Render.TOOLBAR_POPOVER,
|
|
697
698
|
icon: 'table-plus',
|
|
698
699
|
title: 'таблица',
|
|
699
700
|
options: Object.values(TableOptionsMap)
|
|
700
701
|
}),
|
|
701
|
-
[ToolType.CLEAR_FORMATTING]:
|
|
702
|
+
[ToolType.CLEAR_FORMATTING]: createTool({
|
|
702
703
|
name: ToolType.CLEAR_FORMATTING,
|
|
703
704
|
icon: 'eraser',
|
|
704
705
|
title: 'Очистить форматирование',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ToolsMap } from './tools-and-commands';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {import('./
|
|
5
|
-
* @typedef {import('./
|
|
4
|
+
* @typedef {import('./constants').ToolDef} Tool
|
|
5
|
+
* @typedef {import('./constants').CommandDef} Command
|
|
6
6
|
* @typedef {Object} ToolGroup
|
|
7
7
|
* @property {string} title
|
|
8
8
|
* @property {string[]} group
|
|
@@ -13,11 +13,25 @@ import { ToolsMap } from './tools-and-commands';
|
|
|
13
13
|
* @return {{title:string, group: Tool[]}[]}
|
|
14
14
|
*/
|
|
15
15
|
export const buildToolGroups = (toolGroups) => {
|
|
16
|
-
const
|
|
17
|
-
const availableTools = Object
|
|
18
|
-
|
|
16
|
+
const toolsFlatted = toolGroups.flatMap(({ group }) => group);
|
|
17
|
+
const availableTools = Object
|
|
18
|
+
.values(ToolsMap)
|
|
19
|
+
.filter(({ name: toolName }) => toolsFlatted.some(
|
|
20
|
+
(tool) => typeof tool === 'string' ? toolName === tool : tool?.name === toolName)
|
|
21
|
+
);
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @param {Tool[]} toolsGroup
|
|
25
|
+
* @return Tool[]
|
|
26
|
+
*/
|
|
27
|
+
const populateToolsGroup = (toolsGroup) =>
|
|
28
|
+
toolsGroup.reduce((acc, tool) => {
|
|
29
|
+
const { name = tool, ...rest } = typeof tool === 'string' ? {} : tool;
|
|
30
|
+
const foundTool = availableTools.find(({ name: toolName }) => toolName === name);
|
|
31
|
+
|
|
32
|
+
return [...acc, { ...foundTool, ...rest }];
|
|
33
|
+
}, []);
|
|
34
|
+
return toolGroups.reduce((acc, { group, title }) => [...acc, { title, group: populateToolsGroup(group) }], []);
|
|
21
35
|
};
|
|
22
36
|
|
|
23
37
|
/**
|
package/styleguide.config.js
CHANGED
|
@@ -2,7 +2,7 @@ const path = require('path');
|
|
|
2
2
|
const { version } = require('./package.json');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
components: 'src/components/ui
|
|
5
|
+
components: 'src/components/ui/**/[A-Z]*.vue',
|
|
6
6
|
require: ['goodt-framework-css'],
|
|
7
7
|
title: 'UI',
|
|
8
8
|
version,
|
|
@@ -11,6 +11,12 @@ module.exports = {
|
|
|
11
11
|
const name = path.basename(componentPath, '.vue');
|
|
12
12
|
return `import { ${name} } from 'goodteditor-ui';`;
|
|
13
13
|
},
|
|
14
|
+
ignore: [
|
|
15
|
+
'src/components/ui/ColorPicker/**',
|
|
16
|
+
'src/components/ui/utils/**',
|
|
17
|
+
'src/components/ui/WysiwygEditor/extensions/**',
|
|
18
|
+
'src/components/ui/WysiwygEditor/renders/**',
|
|
19
|
+
],
|
|
14
20
|
template: {
|
|
15
21
|
head: {
|
|
16
22
|
links: [
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
```vue
|
|
2
|
-
<template>
|
|
3
|
-
<div class="pad-l5">
|
|
4
|
-
<ui-wysiwyg-editor v-model="model"></ui-wysiwyg-editor>
|
|
5
|
-
</div>
|
|
6
|
-
</template>
|
|
7
|
-
<script>
|
|
8
|
-
import UiWysiwygEditor from './WysiwygEditor.vue';
|
|
9
|
-
export default {
|
|
10
|
-
components: { UiWysiwygEditor },
|
|
11
|
-
data: () => ({
|
|
12
|
-
model: `<p>This WYSIWYG is based on
|
|
13
|
-
<a target="_blank" rel="noopener noreferrer nofollow" href="https://tiptap.dev/" class="color-link">tiptap</a>
|
|
14
|
-
editor framework.</p>`
|
|
15
|
-
})
|
|
16
|
-
};
|
|
17
|
-
</script>
|
|
18
|
-
```
|