@zipify/wysiwyg 3.5.4-ai-prototype → 3.6.0-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/dist/cli.js +2 -2
- package/dist/wysiwyg.css +112 -248
- package/dist/wysiwyg.mjs +8128 -10207
- package/example/ExampleApp.vue +4 -4
- package/example/ai-component/AiComponent.vue +57 -0
- package/lib/Wysiwyg.vue +4 -6
- package/lib/components/base/Button.vue +10 -0
- package/lib/components/base/dropdown/Dropdown.vue +7 -1
- package/lib/components/base/dropdown/DropdownActivator.vue +22 -0
- package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +21 -1
- package/lib/components/base/index.js +0 -1
- package/lib/components/toolbar/Toolbar.vue +7 -1
- package/lib/components/toolbar/controls/AlignmentControl.vue +12 -1
- package/lib/components/toolbar/controls/FontColorControl.vue +12 -0
- package/lib/components/toolbar/controls/FontFamilyControl.vue +19 -4
- package/lib/components/toolbar/controls/FontSizeControl.vue +27 -4
- package/lib/components/toolbar/controls/FontWeightControl.vue +26 -4
- package/lib/components/toolbar/controls/ItalicControl.vue +11 -1
- package/lib/components/toolbar/controls/LineHeightControl.vue +11 -0
- package/lib/components/toolbar/controls/UnderlineControl.vue +10 -0
- package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +43 -1
- package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +22 -1
- package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +2 -0
- package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +9 -1
- package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +9 -1
- package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +23 -1
- package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +23 -1
- package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +31 -13
- package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +26 -1
- package/lib/components/toolbar/controls/index.js +1 -2
- package/lib/components/toolbar/controls/{StylePresetControl.vue → stylePreset/StylePresetControl.vue} +23 -8
- package/lib/components/toolbar/controls/stylePreset/StylePresetOption.vue +87 -0
- package/lib/components/toolbar/controls/stylePreset/index.js +1 -0
- package/lib/components/toolbar/layouts/ToolbarDesktop.vue +14 -5
- package/lib/components/toolbar/layouts/ToolbarPopup.vue +12 -0
- package/lib/entryLib.js +2 -0
- package/lib/extensions/index.js +0 -5
- package/lib/extensions/proseMirror/PastePlugin.js +4 -6
- package/lib/styles/dropdown.css +7 -0
- package/lib/styles/main.css +1 -0
- package/lib/styles/variables.css +1 -0
- package/package.json +1 -2
- package/example/aiAdapter.js +0 -52
- package/lib/assets/icons/loading.svg +0 -11
- package/lib/assets/icons/send.svg +0 -3
- package/lib/assets/icons/sparkles.svg +0 -3
- package/lib/components/base/TextArea.vue +0 -108
- package/lib/components/floatingMenu/AiWidgetSuggestionItem.vue +0 -74
- package/lib/components/floatingMenu/FloatingMenuControl.vue +0 -222
- package/lib/components/floatingMenu/index.js +0 -1
- package/lib/components/toolbar/controls/aiComponent/AiControl.vue +0 -204
- package/lib/components/toolbar/controls/aiComponent/AiControlHeader.vue +0 -28
- package/lib/components/toolbar/controls/aiComponent/AiSettings.vue +0 -153
- package/lib/components/toolbar/controls/aiComponent/AiSuggestionItem.vue +0 -84
- package/lib/extensions/AiComponent.js +0 -22
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Button
|
|
3
|
+
class="zw-position--relative"
|
|
3
4
|
skin="toolbar"
|
|
4
5
|
icon
|
|
5
6
|
:active="currentValue"
|
|
@@ -7,6 +8,13 @@
|
|
|
7
8
|
v-tooltip="{ text: 'Underline', hotkey: 'Mod U' }"
|
|
8
9
|
>
|
|
9
10
|
<Icon name="underline" size="28px" auto-color />
|
|
11
|
+
|
|
12
|
+
<span
|
|
13
|
+
v-if="isCustomized"
|
|
14
|
+
class="zw-button__customized-indicator"
|
|
15
|
+
data-test-selector="customizedIndicator"
|
|
16
|
+
v-tooltip.xs="'Style differs from Page Styles'"
|
|
17
|
+
/>
|
|
10
18
|
</Button>
|
|
11
19
|
</template>
|
|
12
20
|
|
|
@@ -32,11 +40,13 @@ export default {
|
|
|
32
40
|
const editor = inject(InjectionTokens.EDITOR);
|
|
33
41
|
|
|
34
42
|
const currentValue = editor.commands.isUnderline();
|
|
43
|
+
const isCustomized = editor.commands.isUnderlineCustomized();
|
|
35
44
|
|
|
36
45
|
const apply = () => editor.chain().focus().toggleUnderline().run();
|
|
37
46
|
|
|
38
47
|
return {
|
|
39
48
|
currentValue,
|
|
49
|
+
isCustomized,
|
|
40
50
|
apply
|
|
41
51
|
};
|
|
42
52
|
}
|
|
@@ -5,9 +5,14 @@ import { Alignments } from '../../../../enums';
|
|
|
5
5
|
import { ButtonToggle } from '../../../base';
|
|
6
6
|
import AlignmentControl from '../AlignmentControl';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const SELECTORS = {
|
|
9
|
+
INDICATOR: '[data-test-selector="customizedIndicator"]'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const createEditor = ({ alignment, isSettingCustomized } = {}) => ({
|
|
9
13
|
commands: {
|
|
10
14
|
getAlignment: () => ref(alignment),
|
|
15
|
+
isSettingCustomized: () => ref(isSettingCustomized ?? false),
|
|
11
16
|
focus: jest.fn().mockReturnThis(),
|
|
12
17
|
applyAlignment: jest.fn().mockReturnThis(),
|
|
13
18
|
run: jest.fn()
|
|
@@ -74,3 +79,40 @@ describe('selection value', () => {
|
|
|
74
79
|
expect(editor.commands.applyAlignment).toHaveBeenCalledWith(Alignments.CENTER);
|
|
75
80
|
});
|
|
76
81
|
});
|
|
82
|
+
|
|
83
|
+
describe('render indicator of customized styles', () => {
|
|
84
|
+
test('should render indicator', () => {
|
|
85
|
+
const editor = createEditor({
|
|
86
|
+
alignment: Alignments.LEFT,
|
|
87
|
+
isSettingCustomized: true
|
|
88
|
+
});
|
|
89
|
+
const wrapper = createComponent({
|
|
90
|
+
editor,
|
|
91
|
+
slotParams: {
|
|
92
|
+
option: {
|
|
93
|
+
id: Alignments.LEFT,
|
|
94
|
+
tooltip: { text: 'Align Left', hotkey: 'Mod Shift L' }
|
|
95
|
+
},
|
|
96
|
+
isActive: true
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
expect(wrapper).toVueContainComponent(SELECTORS.INDICATOR);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('should not render indicator', () => {
|
|
104
|
+
const editor = createEditor({ alignment: Alignments.LEFT });
|
|
105
|
+
const wrapper = createComponent({
|
|
106
|
+
editor,
|
|
107
|
+
slotParams: {
|
|
108
|
+
option: {
|
|
109
|
+
id: Alignments.LEFT,
|
|
110
|
+
tooltip: { text: 'Align Left', hotkey: 'Mod Shift L' }
|
|
111
|
+
},
|
|
112
|
+
isActive: true
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(wrapper).not.toVueContainComponent(SELECTORS.INDICATOR);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -4,9 +4,14 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { ColorPicker } from '../../../base';
|
|
5
5
|
import FontColorControl from '../FontColorControl';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const SELECTORS = {
|
|
8
|
+
INDICATOR: '[data-test-selector="customizedIndicator"]'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const createEditor = ({ fontColor, isSettingCustomized } = {}) => ({
|
|
8
12
|
commands: {
|
|
9
13
|
getFontColor: () => ref(fontColor),
|
|
14
|
+
isSettingCustomized: () => ref( isSettingCustomized ?? false),
|
|
10
15
|
focus: jest.fn().mockReturnThis(),
|
|
11
16
|
applyFontColor: jest.fn().mockReturnThis(),
|
|
12
17
|
run: jest.fn()
|
|
@@ -57,3 +62,19 @@ describe('selection value', () => {
|
|
|
57
62
|
expect(editor.commands.applyFontColor).toHaveBeenCalledWith('green');
|
|
58
63
|
});
|
|
59
64
|
});
|
|
65
|
+
|
|
66
|
+
describe('render indicator of customized styles', () => {
|
|
67
|
+
test('should render indicator', () => {
|
|
68
|
+
const editor = createEditor({ fontColor: 'red', isSettingCustomized: true });
|
|
69
|
+
const wrapper = createComponent({ editor });
|
|
70
|
+
|
|
71
|
+
expect(wrapper).toVueContainComponent(SELECTORS.INDICATOR);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('should not render indicator', () => {
|
|
75
|
+
const editor = createEditor({ fontColor: 'red' });
|
|
76
|
+
const wrapper = createComponent({ editor });
|
|
77
|
+
|
|
78
|
+
expect(wrapper).not.toVueContainComponent(SELECTORS.INDICATOR);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -7,6 +7,8 @@ import FontFamilyControl from '../FontFamilyControl';
|
|
|
7
7
|
const createEditor = ({ fontFamily } = {}) => ({
|
|
8
8
|
commands: {
|
|
9
9
|
getFont: () => ref({ name: fontFamily }),
|
|
10
|
+
getDefaultFontFamily: () => ref(fontFamily ?? 'Lato'),
|
|
11
|
+
isSettingCustomized: () => ref(false),
|
|
10
12
|
focus: jest.fn().mockReturnThis(),
|
|
11
13
|
applyFontFamily: jest.fn().mockReturnThis(),
|
|
12
14
|
run: jest.fn()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { ref } from 'vue';
|
|
2
|
+
import { h, ref } from 'vue';
|
|
3
3
|
import { InjectionTokens } from '../../../../injectionTokens';
|
|
4
4
|
import { Dropdown } from '../../../base';
|
|
5
5
|
import FontSizeControl from '../FontSizeControl';
|
|
@@ -7,6 +7,8 @@ import FontSizeControl from '../FontSizeControl';
|
|
|
7
7
|
const createEditor = ({ fontSize } = {}) => ({
|
|
8
8
|
commands: {
|
|
9
9
|
getFontSize: () => ref(fontSize),
|
|
10
|
+
getDefaultFontSize: () => ref(fontSize ?? '18'),
|
|
11
|
+
isSettingCustomized: () => ref(false),
|
|
10
12
|
focus: jest.fn().mockReturnThis(),
|
|
11
13
|
applyFontSize: jest.fn().mockReturnThis(),
|
|
12
14
|
run: jest.fn()
|
|
@@ -19,6 +21,12 @@ const createEditor = ({ fontSize } = {}) => ({
|
|
|
19
21
|
|
|
20
22
|
function createComponent({ editor }) {
|
|
21
23
|
return shallowMount(FontSizeControl, {
|
|
24
|
+
stubs: {
|
|
25
|
+
Dropdown: {
|
|
26
|
+
render: () => h('div'),
|
|
27
|
+
props: ['value']
|
|
28
|
+
}
|
|
29
|
+
},
|
|
22
30
|
provide: {
|
|
23
31
|
[InjectionTokens.EDITOR]: editor,
|
|
24
32
|
[InjectionTokens.FONT_SIZES]: ['12', '23']
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { ref } from 'vue';
|
|
2
|
+
import { h, ref } from 'vue';
|
|
3
3
|
import { InjectionTokens } from '../../../../injectionTokens';
|
|
4
4
|
import { Dropdown } from '../../../base';
|
|
5
5
|
import FontWeightControl from '../FontWeightControl';
|
|
@@ -7,6 +7,8 @@ import FontWeightControl from '../FontWeightControl';
|
|
|
7
7
|
const createEditor = ({ fontWeight, fontWeightList } = {}) => ({
|
|
8
8
|
commands: {
|
|
9
9
|
getFontWeight: () => ref(fontWeight ?? '400'),
|
|
10
|
+
getDefaultFontWeight: () => ref(fontWeight ?? '400'),
|
|
11
|
+
isSettingCustomized: () => ref(false),
|
|
10
12
|
getFont: () => ref({ weights: fontWeightList ?? ['400', '700'] }),
|
|
11
13
|
focus: jest.fn().mockReturnThis(),
|
|
12
14
|
applyFontWeight: jest.fn().mockReturnThis(),
|
|
@@ -20,6 +22,12 @@ const createEditor = ({ fontWeight, fontWeightList } = {}) => ({
|
|
|
20
22
|
|
|
21
23
|
function createComponent({ editor }) {
|
|
22
24
|
return shallowMount(FontWeightControl, {
|
|
25
|
+
stubs: {
|
|
26
|
+
Dropdown: {
|
|
27
|
+
render: () => h('div'),
|
|
28
|
+
props: ['value']
|
|
29
|
+
}
|
|
30
|
+
},
|
|
23
31
|
provide: { [InjectionTokens.EDITOR]: editor }
|
|
24
32
|
});
|
|
25
33
|
}
|
|
@@ -4,9 +4,14 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { Button } from '../../../base';
|
|
5
5
|
import ItalicControl from '../ItalicControl';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const SELECTORS = {
|
|
8
|
+
INDICATOR: '[data-test-selector="customizedIndicator"]'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const createEditor = ({ isItalic, isItalicAvailable, isSettingCustomized } = {}) => ({
|
|
8
12
|
commands: {
|
|
9
13
|
isItalic: () => ref(isItalic),
|
|
14
|
+
isSettingCustomized: () => ref(isSettingCustomized ?? false),
|
|
10
15
|
isItalicAvailable: () => ref(isItalicAvailable ?? true),
|
|
11
16
|
focus: jest.fn().mockReturnThis(),
|
|
12
17
|
toggleItalic: jest.fn().mockReturnThis(),
|
|
@@ -40,6 +45,23 @@ describe('rendering', () => {
|
|
|
40
45
|
|
|
41
46
|
expect(buttonWrapper.props('disabled')).toBe(true);
|
|
42
47
|
});
|
|
48
|
+
|
|
49
|
+
test('should render indicator of customized styles', () => {
|
|
50
|
+
const editor = createEditor({
|
|
51
|
+
isItalic: true,
|
|
52
|
+
isSettingCustomized: true
|
|
53
|
+
});
|
|
54
|
+
const wrapper = createComponent({ editor });
|
|
55
|
+
|
|
56
|
+
expect(wrapper).toVueContainComponent(SELECTORS.INDICATOR);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('should not render indicator of customized styles', () => {
|
|
60
|
+
const editor = createEditor({ isItalic: false });
|
|
61
|
+
const wrapper = createComponent({ editor });
|
|
62
|
+
|
|
63
|
+
expect(wrapper).not.toVueContainComponent(SELECTORS.INDICATOR);
|
|
64
|
+
});
|
|
43
65
|
});
|
|
44
66
|
|
|
45
67
|
describe('selection value', () => {
|
|
@@ -4,12 +4,17 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { Button, Modal, NumberField, Range } from '../../../base';
|
|
5
5
|
import LineHeightControl from '../LineHeightControl';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const SELECTORS = {
|
|
8
|
+
INDICATOR: '[data-test-selector="customizedIndicator"]'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const createEditor = ({ height, isSettingCustomized } = {}) => {
|
|
8
12
|
const heightRef = ref(height ?? '1.2');
|
|
9
13
|
|
|
10
14
|
return {
|
|
11
15
|
commands: {
|
|
12
16
|
getLineHeight: () => heightRef,
|
|
17
|
+
isSettingCustomized: () => ref(isSettingCustomized ?? false),
|
|
13
18
|
applyLineHeight: jest.fn(function (value) {
|
|
14
19
|
heightRef.value = value;
|
|
15
20
|
return this;
|
|
@@ -117,4 +122,21 @@ describe('rendering', () => {
|
|
|
117
122
|
expect(buttonWrapper.props('active')).toBe(true);
|
|
118
123
|
expect(modalWrapper.props('toggler').isOpened.value).toBe(true);
|
|
119
124
|
});
|
|
125
|
+
|
|
126
|
+
test('should render indicator of customized styles', () => {
|
|
127
|
+
const editor = createEditor({
|
|
128
|
+
height: '1.8',
|
|
129
|
+
isSettingCustomized: true
|
|
130
|
+
});
|
|
131
|
+
const wrapper = createComponent({ editor });
|
|
132
|
+
|
|
133
|
+
expect(wrapper).toVueContainComponent(SELECTORS.INDICATOR);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('should not render indicator of customized styles', () => {
|
|
137
|
+
const editor = createEditor({ height: '1.2' });
|
|
138
|
+
const wrapper = createComponent({ editor });
|
|
139
|
+
|
|
140
|
+
expect(wrapper).not.toVueContainComponent(SELECTORS.INDICATOR);
|
|
141
|
+
});
|
|
120
142
|
});
|
|
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
|
|
|
2
2
|
import { ref } from 'vue';
|
|
3
3
|
import { InjectionTokens } from '../../../../injectionTokens';
|
|
4
4
|
import { Button, Dropdown } from '../../../base';
|
|
5
|
-
import StylePresetControl from '../
|
|
5
|
+
import { StylePresetControl } from '../stylePreset';
|
|
6
6
|
import { TextSettings } from '../../../../enums';
|
|
7
7
|
|
|
8
8
|
const createEditor = ({ presets, preset, customization } = {}) => ({
|
|
@@ -31,27 +31,45 @@ function createComponent({ editor }) {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
function createPreset({ id, name } = {}) {
|
|
35
|
+
return {
|
|
36
|
+
id: id ?? 'regular-1',
|
|
37
|
+
name: name ?? 'Regular 1',
|
|
38
|
+
common: {
|
|
39
|
+
color: '#262626',
|
|
40
|
+
font_weight: 400,
|
|
41
|
+
font_family: 'Lato',
|
|
42
|
+
font_style: 'italic'
|
|
43
|
+
},
|
|
44
|
+
desktop: { font_size: 18 }
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
describe('rendering', () => {
|
|
35
49
|
test('should render dropdown options', () => {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
{ id: 'h1', name: 'H1' },
|
|
39
|
-
{ id: 'regular-1', name: 'Regular 1' }
|
|
40
|
-
]
|
|
41
|
-
});
|
|
50
|
+
const presets = [createPreset()];
|
|
51
|
+
const editor = createEditor({ presets });
|
|
42
52
|
const wrapper = createComponent({ editor });
|
|
43
53
|
const dropdownWrapper = wrapper.findComponent(Dropdown);
|
|
44
54
|
|
|
45
|
-
expect(dropdownWrapper.props('options')).toEqual([
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
expect(dropdownWrapper.props('options')).toEqual([{
|
|
56
|
+
id: 'regular-1',
|
|
57
|
+
title: 'Regular 1',
|
|
58
|
+
properties: {
|
|
59
|
+
color: '#262626',
|
|
60
|
+
fontFamily: 'Lato',
|
|
61
|
+
fontSize: 18,
|
|
62
|
+
fontStyle: 'italic',
|
|
63
|
+
fontWeight: 400
|
|
64
|
+
}
|
|
65
|
+
}]);
|
|
49
66
|
});
|
|
50
67
|
|
|
51
68
|
test('should render preset from selection', () => {
|
|
69
|
+
const presets = [createPreset()];
|
|
52
70
|
const editor = createEditor({
|
|
53
|
-
presets
|
|
54
|
-
preset:
|
|
71
|
+
presets,
|
|
72
|
+
preset: createPreset()
|
|
55
73
|
});
|
|
56
74
|
const wrapper = createComponent({ editor });
|
|
57
75
|
const dropdownWrapper = wrapper.findComponent(Dropdown);
|
|
@@ -4,9 +4,14 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { Button } from '../../../base';
|
|
5
5
|
import UnderlineControl from '../UnderlineControl';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const SELECTORS = {
|
|
8
|
+
INDICATOR: '[data-test-selector="customizedIndicator"]'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const createEditor = ({ isUnderline, isSettingCustomized } = {}) => ({
|
|
8
12
|
commands: {
|
|
9
13
|
isUnderline: () => ref(isUnderline),
|
|
14
|
+
isUnderlineCustomized: () => ref(isSettingCustomized ?? false),
|
|
10
15
|
focus: jest.fn().mockReturnThis(),
|
|
11
16
|
toggleUnderline: jest.fn().mockReturnThis(),
|
|
12
17
|
run: jest.fn()
|
|
@@ -46,3 +51,23 @@ describe('selection value', () => {
|
|
|
46
51
|
expect(editor.commands.toggleUnderline).toHaveBeenCalled();
|
|
47
52
|
});
|
|
48
53
|
});
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
describe('render indicator of customized styles', () => {
|
|
57
|
+
test('should render indicator', () => {
|
|
58
|
+
const editor = createEditor({
|
|
59
|
+
isUnderline: true,
|
|
60
|
+
isSettingCustomized: true
|
|
61
|
+
});
|
|
62
|
+
const wrapper = createComponent({ editor });
|
|
63
|
+
|
|
64
|
+
expect(wrapper).toVueContainComponent(SELECTORS.INDICATOR);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('should not render indicator', () => {
|
|
68
|
+
const editor = createEditor({ isUnderline: false });
|
|
69
|
+
const wrapper = createComponent({ editor });
|
|
70
|
+
|
|
71
|
+
expect(wrapper).not.toVueContainComponent(SELECTORS.INDICATOR);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { default as StylePresetControl } from './StylePresetControl';
|
|
2
1
|
export { default as FontFamilyControl } from './FontFamilyControl';
|
|
3
2
|
export { default as FontWeightControl } from './FontWeightControl';
|
|
4
3
|
export { default as FontSizeControl } from './FontSizeControl';
|
|
@@ -13,5 +12,5 @@ export { default as AlignmentControl } from './AlignmentControl';
|
|
|
13
12
|
export { default as LineHeightControl } from './LineHeightControl';
|
|
14
13
|
export { default as ListControl } from './ListControl';
|
|
15
14
|
export { default as RemoveFormatControl } from './RemoveFormatControl';
|
|
16
|
-
export { default as AiControl } from './aiComponent/AiControl';
|
|
17
15
|
export { LinkControl } from './link';
|
|
16
|
+
export { StylePresetControl } from './stylePreset';
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
<div class="zw-style-preset-control">
|
|
3
3
|
<Dropdown
|
|
4
4
|
class="zw-style-preset-control__dropdown"
|
|
5
|
+
:max-width="170"
|
|
5
6
|
:value="preset.id"
|
|
6
7
|
:options="options"
|
|
7
8
|
@change="apply"
|
|
8
9
|
v-tooltip="'Text Type'"
|
|
9
|
-
|
|
10
|
+
>
|
|
11
|
+
<template #option="{ option }">
|
|
12
|
+
<StylePresetOption :option="option" />
|
|
13
|
+
</template>
|
|
14
|
+
</Dropdown>
|
|
10
15
|
|
|
11
16
|
<Button
|
|
12
17
|
class="zw-style-preset-control__reset"
|
|
@@ -22,10 +27,11 @@
|
|
|
22
27
|
|
|
23
28
|
<script>
|
|
24
29
|
import { computed, inject, unref } from 'vue';
|
|
25
|
-
import { InjectionTokens } from '
|
|
26
|
-
import { Dropdown, Button, Icon } from '
|
|
27
|
-
import { tooltip } from '
|
|
28
|
-
import { TextSettings } from '
|
|
30
|
+
import { InjectionTokens } from '../../../../injectionTokens';
|
|
31
|
+
import { Dropdown, Button, Icon } from '../../../base';
|
|
32
|
+
import { tooltip } from '../../../../directives';
|
|
33
|
+
import { Devices, TextSettings } from '../../../../enums';
|
|
34
|
+
import StylePresetOption from './StylePresetOption';
|
|
29
35
|
|
|
30
36
|
const CLEAR_MARKS = [TextSettings.FONT_SIZE, TextSettings.FONT_WEIGHT];
|
|
31
37
|
|
|
@@ -33,9 +39,10 @@ export default {
|
|
|
33
39
|
name: 'StylePresetControl',
|
|
34
40
|
|
|
35
41
|
components: {
|
|
36
|
-
|
|
42
|
+
StylePresetOption,
|
|
43
|
+
Dropdown,
|
|
37
44
|
Button,
|
|
38
|
-
|
|
45
|
+
Icon
|
|
39
46
|
},
|
|
40
47
|
|
|
41
48
|
directives: {
|
|
@@ -58,7 +65,15 @@ export default {
|
|
|
58
65
|
const options = computed(() => {
|
|
59
66
|
return unref(presets).map((preset) => ({
|
|
60
67
|
id: preset.id,
|
|
61
|
-
title: preset.name
|
|
68
|
+
title: preset.name,
|
|
69
|
+
properties: {
|
|
70
|
+
color: preset.common.color,
|
|
71
|
+
fontWeight: preset.common.font_weight,
|
|
72
|
+
fontFamily: preset.common.font_family,
|
|
73
|
+
fontStyle: preset.common.font_style,
|
|
74
|
+
textDecoration: preset.common.text_decoration,
|
|
75
|
+
fontSize: preset[Devices.DESKTOP].font_size
|
|
76
|
+
}
|
|
62
77
|
}));
|
|
63
78
|
});
|
|
64
79
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DropdownOption
|
|
3
|
+
class="zw-style-preset-control__option"
|
|
4
|
+
:style="renderOptionStyles(option)"
|
|
5
|
+
:option="option"
|
|
6
|
+
v-tooltip="option.id"
|
|
7
|
+
>
|
|
8
|
+
<span class="zw-style-preset-control__color" />
|
|
9
|
+
<span class="zw-style-preset-control__title">{{ optionTitle }}</span>
|
|
10
|
+
<span class="zw-style-preset-control__size">{{ fontSizeTitle }}</span>
|
|
11
|
+
</DropdownOption>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import { computed } from 'vue';
|
|
16
|
+
import { DropdownOption } from '../../../base';
|
|
17
|
+
import { tooltip } from '../../../../directives';
|
|
18
|
+
|
|
19
|
+
export default {
|
|
20
|
+
name: 'StylePresetOption',
|
|
21
|
+
|
|
22
|
+
components: {
|
|
23
|
+
DropdownOption
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
directives: {
|
|
27
|
+
tooltip
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
props: {
|
|
31
|
+
option: {
|
|
32
|
+
type: Object,
|
|
33
|
+
required: true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
setup(props) {
|
|
38
|
+
const optionTitle = computed(() => props.option.title);
|
|
39
|
+
const fontSizeTitle = computed(() => props.option.properties.fontSize);
|
|
40
|
+
const renderOptionStyles = (option) => ({
|
|
41
|
+
'--zw-color-option': option.properties.color,
|
|
42
|
+
'--zw-font-style-option': option.properties.fontStyle,
|
|
43
|
+
'--zw-font-family-option': `"${option.properties.fontFamily}"`,
|
|
44
|
+
'--zw-font-weight-option': option.properties.fontWeight,
|
|
45
|
+
'--zw-text-decoration-option': option.properties.textDecoration
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
optionTitle,
|
|
50
|
+
fontSizeTitle,
|
|
51
|
+
renderOptionStyles
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<style scoped>
|
|
58
|
+
.zw-style-preset-control__option {
|
|
59
|
+
display: flex;
|
|
60
|
+
justify-content: space-between;
|
|
61
|
+
align-items: center;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.zw-style-preset-control__color {
|
|
65
|
+
width: 10px;
|
|
66
|
+
height: 10px;
|
|
67
|
+
border: 1px solid rgba(var(--zw-color-black), 0.15);
|
|
68
|
+
border-radius: 14.71%;
|
|
69
|
+
background-color: var(--zw-color-option);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.zw-style-preset-control__size {
|
|
73
|
+
font-size: 10px;
|
|
74
|
+
color: rgb(var(--zw-color-n70));
|
|
75
|
+
margin-left: var(--zw-offset-sm);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.zw-style-preset-control__title {
|
|
79
|
+
width: 82px;
|
|
80
|
+
margin-left: var(--zw-offset-xs);
|
|
81
|
+
font-size: var(--zw-font-size-xxs);
|
|
82
|
+
font-family: var(--zw-font-family-option);
|
|
83
|
+
font-style: var(--zw-font-style-option);
|
|
84
|
+
font-weight: var(--zw-font-weight-option);
|
|
85
|
+
text-decoration: var(--zw-text-decoration-option);
|
|
86
|
+
}
|
|
87
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as StylePresetControl } from './StylePresetControl';
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<ToolbarRow>
|
|
4
|
-
<
|
|
4
|
+
<template v-if="aiComponent">
|
|
5
|
+
<component :is="aiComponent" />
|
|
6
|
+
<ToolbarDivider vertical />
|
|
7
|
+
</template>
|
|
5
8
|
<StylePresetControl />
|
|
6
9
|
<ToolbarDivider vertical />
|
|
7
10
|
<FontFamilyControl />
|
|
@@ -65,8 +68,7 @@ import {
|
|
|
65
68
|
UnderlineControl,
|
|
66
69
|
ListControl,
|
|
67
70
|
RemoveFormatControl,
|
|
68
|
-
LinkControl
|
|
69
|
-
AiControl
|
|
71
|
+
LinkControl
|
|
70
72
|
} from '../controls';
|
|
71
73
|
|
|
72
74
|
export default {
|
|
@@ -91,8 +93,15 @@ export default {
|
|
|
91
93
|
LineHeightControl,
|
|
92
94
|
ListControl,
|
|
93
95
|
RemoveFormatControl,
|
|
94
|
-
LinkControl
|
|
95
|
-
|
|
96
|
+
LinkControl
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
props: {
|
|
100
|
+
aiComponent: {
|
|
101
|
+
type: Object,
|
|
102
|
+
required: false,
|
|
103
|
+
default: null
|
|
104
|
+
}
|
|
96
105
|
}
|
|
97
106
|
};
|
|
98
107
|
</script>
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<ToolbarRow>
|
|
4
|
+
<template v-if="aiComponent">
|
|
5
|
+
<component :is="aiComponent" />
|
|
6
|
+
<ToolbarDivider vertical />
|
|
7
|
+
</template>
|
|
4
8
|
<StylePresetControl />
|
|
5
9
|
<ToolbarDivider vertical />
|
|
6
10
|
<FontFamilyControl />
|
|
@@ -90,6 +94,14 @@ export default {
|
|
|
90
94
|
ListControl,
|
|
91
95
|
RemoveFormatControl,
|
|
92
96
|
LinkControl
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
props: {
|
|
100
|
+
aiComponent: {
|
|
101
|
+
type: Object,
|
|
102
|
+
required: false,
|
|
103
|
+
default: null
|
|
104
|
+
}
|
|
93
105
|
}
|
|
94
106
|
};
|
|
95
107
|
</script>
|
package/lib/entryLib.js
CHANGED
|
@@ -2,3 +2,5 @@ export { default as Wysiwyg } from './Wysiwyg';
|
|
|
2
2
|
export { NodeFactory, HtmlToJsonParser } from './services';
|
|
3
3
|
export { NodeTypes, TextSettings, Alignments } from './enums';
|
|
4
4
|
export { isWysiwygContent, unmarkWysiwygContent, markWysiwygContent } from './utils';
|
|
5
|
+
export * from './components/base';
|
|
6
|
+
export { InjectionTokens } from './injectionTokens';
|
package/lib/extensions/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { reactive, toRef, watch } from 'vue';
|
|
2
|
-
import FloatingMenu from '@tiptap/extension-floating-menu';
|
|
3
2
|
import { StylePresetRenderer } from '../services';
|
|
4
3
|
import { buildCoreExtensions } from './core';
|
|
5
4
|
import { FontFamily } from './FontFamily';
|
|
@@ -18,7 +17,6 @@ import { List } from './list';
|
|
|
18
17
|
import { Link } from './Link';
|
|
19
18
|
import { Superscript } from './Superscript';
|
|
20
19
|
import { Margin } from './Margin';
|
|
21
|
-
import { AiComponent } from './AiComponent';
|
|
22
20
|
|
|
23
21
|
export function buildExtensions(options) {
|
|
24
22
|
const getPresetById = (id) => options.presetsRef.value.find((preset) => preset.id === id);
|
|
@@ -39,9 +37,6 @@ export function buildExtensions(options) {
|
|
|
39
37
|
linkPresetId: options.linkPresetId
|
|
40
38
|
})
|
|
41
39
|
}),
|
|
42
|
-
AiComponent.configure({
|
|
43
|
-
aiComponent: options.aiComponent
|
|
44
|
-
}),
|
|
45
40
|
List.configure({
|
|
46
41
|
baseClass: options.baseListClass,
|
|
47
42
|
presetClass: options.basePresetClass + options.defaultPresetId
|
|
@@ -46,12 +46,10 @@ export class PastePlugin extends ProseMirrorPlugin {
|
|
|
46
46
|
return true;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
_insertPastedContent({ state
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return state.tr.replaceSelectionWith(slice.content, input.shiftKey);
|
|
49
|
+
_insertPastedContent({ state }, slice) {
|
|
50
|
+
return this._isFullBlockSelected(state)
|
|
51
|
+
? state.tr.replaceSelectionWith(slice.content, false)
|
|
52
|
+
: state.tr.replaceSelection(slice);
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
_isFullBlockSelected(state) {
|