@zipify/wysiwyg 1.2.5-1 → 1.3.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.
Files changed (29) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/wysiwyg.css +42 -31
  3. package/dist/wysiwyg.mjs +125 -33
  4. package/lib/assets/icons/indicator.svg +5 -0
  5. package/lib/components/base/Button.vue +7 -0
  6. package/lib/components/base/dropdown/Dropdown.vue +7 -1
  7. package/lib/components/base/dropdown/DropdownActivator.vue +19 -4
  8. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +23 -1
  9. package/lib/components/toolbar/controls/AlignmentControl.vue +11 -1
  10. package/lib/components/toolbar/controls/FontColorControl.vue +13 -0
  11. package/lib/components/toolbar/controls/FontFamilyControl.vue +4 -0
  12. package/lib/components/toolbar/controls/FontSizeControl.vue +6 -1
  13. package/lib/components/toolbar/controls/FontWeightControl.vue +12 -0
  14. package/lib/components/toolbar/controls/ItalicControl.vue +13 -0
  15. package/lib/components/toolbar/controls/LineHeightControl.vue +14 -0
  16. package/lib/components/toolbar/controls/UnderlineControl.vue +12 -0
  17. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +72 -5
  18. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +22 -1
  19. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +1 -0
  20. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +1 -0
  21. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +1 -0
  22. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +23 -1
  23. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +23 -1
  24. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +25 -1
  25. package/lib/extensions/StylePreset.js +6 -0
  26. package/lib/extensions/TextDecoration.js +7 -0
  27. package/lib/extensions/__tests__/StylePreset.test.js +51 -0
  28. package/lib/extensions/__tests__/TextDecoration.test.js +20 -0
  29. package/package.json +1 -1
@@ -0,0 +1,5 @@
1
+ <svg width="9" height="9" viewBox="0 0 9 9" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M0 4.5C0 2.01472 2.01472 0 4.5 0C6.98528 0 9 2.01472 9 4.5C9 6.98528 6.98528 9 4.5 9C2.01472 9 0 6.98528 0 4.5Z" fill="#FFAB00"/>
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M5.0625 2.25H3.9375V5.625H5.0625V2.25Z" fill="white"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M3.9375 6.75C3.9375 6.43894 4.18894 6.1875 4.5 6.1875C4.8105 6.1875 5.0625 6.43894 5.0625 6.75C5.0625 7.06106 4.8105 7.3125 4.5 7.3125C4.18894 7.3125 3.9375 7.06106 3.9375 6.75Z" fill="white"/>
5
+ </svg>
@@ -135,4 +135,11 @@ export default {
135
135
  color: rgb(var(--zw-color-white));
136
136
  background-color: rgb(var(--zw-color-n5));
137
137
  }
138
+
139
+ .zw-button__customized-indicator {
140
+ display: inline-block !important;
141
+ position: absolute;
142
+ top: calc(0px - var(--zw-offset-xxs));
143
+ right: 2px;
144
+ }
138
145
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="zw-dropdown" ref="dropdownRef">
3
- <DropdownActivator :color="color">
3
+ <DropdownActivator :color="color" :is-customized="isCustomized">
4
4
  <template #default="attrs">
5
5
  <slot name="activator" v-bind="attrs" />
6
6
  </template>
@@ -60,6 +60,12 @@ export default {
60
60
  type: String,
61
61
  required: false,
62
62
  default: 'none'
63
+ },
64
+
65
+ isCustomized: {
66
+ type: Boolean,
67
+ required: false,
68
+ default: false
63
69
  }
64
70
  },
65
71
 
@@ -12,6 +12,14 @@
12
12
  {{ activeOptionTitle }}
13
13
  </span>
14
14
 
15
+ <Icon
16
+ v-if="isCustomized"
17
+ class="zw-dropdown__customized-indicator"
18
+ name="indicator"
19
+ size="9px"
20
+ data-test-selector="customizedIndicator"
21
+ />
22
+
15
23
  <Icon
16
24
  class="zw-dropdown__activator-arrow"
17
25
  name="arrow"
@@ -47,6 +55,12 @@ export default {
47
55
  type: String,
48
56
  required: false,
49
57
  default: 'none'
58
+ },
59
+
60
+ isCustomized: {
61
+ type: Boolean,
62
+ required: false,
63
+ default: false
50
64
  }
51
65
  },
52
66
 
@@ -77,10 +91,6 @@ export default {
77
91
  width: 100%;
78
92
  }
79
93
 
80
- .zw-dropdown__activator-title {
81
- margin-right: var(--zw-offset-xs);
82
- }
83
-
84
94
  .zw-dropdown__activator-arrow {
85
95
  margin-left: auto;
86
96
  }
@@ -94,4 +104,9 @@ export default {
94
104
  font-size: var(--zw-font-size-xxs);
95
105
  color: rgb(var(--zw-color-white));
96
106
  }
107
+
108
+ .zw-dropdown__customized-indicator {
109
+ position: relative;
110
+ top: calc(0px - var(--zw-offset-xs));
111
+ }
97
112
  </style>
@@ -4,6 +4,10 @@ import DropdownActivator from '../DropdownActivator';
4
4
  import { InjectionTokens } from '../injectionTokens';
5
5
  import Button from '../../Button';
6
6
 
7
+ const SELECTORS = {
8
+ INDICATOR: '[data-test-selector="customizedIndicator"]'
9
+ };
10
+
7
11
  const createToggler = ({ isOpened } = {}) => ({
8
12
  isOpened: ref(isOpened ?? false),
9
13
  open: jest.fn()
@@ -13,8 +17,12 @@ const createActiveOptionManager = ({ activeOption } = {}) => ({
13
17
  activeOption: ref(activeOption ?? { id: 'test' })
14
18
  });
15
19
 
16
- function createComponent({ toggler, activeOptionManager } = {}) {
20
+ function createComponent({ toggler, isCustomized, activeOptionManager } = {}) {
17
21
  return shallowMount(DropdownActivator, {
22
+ propsData: {
23
+ isCustomized: ref(isCustomized ?? false)
24
+ },
25
+
18
26
  provide: {
19
27
  [InjectionTokens.TOGGLER]: toggler ?? createToggler(),
20
28
  [InjectionTokens.ACTIVE_MANAGER]: activeOptionManager ?? createActiveOptionManager()
@@ -40,6 +48,20 @@ describe('rendering', () => {
40
48
  expect(buttonWrapper.props('active')).toBe(false);
41
49
  expect(buttonWrapper.classes('zw-dropdown__activator--active')).toBeFalsy();
42
50
  });
51
+
52
+ test('should render indicator of customized styles', () => {
53
+ const toggler = createToggler({ isOpened: false });
54
+ const wrapper = createComponent({ toggler, isCustomized: true });
55
+
56
+ expect(wrapper).toVueContainComponent(SELECTORS.INDICATOR);
57
+ });
58
+
59
+ test('should not render indicator of customized styles', () => {
60
+ const toggler = createToggler({ isOpened: false });
61
+ const wrapper = createComponent({ toggler });
62
+
63
+ expect(wrapper).not.toVueContainComponent(SELECTORS.INDICATOR);
64
+ });
43
65
  });
44
66
 
45
67
  describe('open dropdown', () => {
@@ -2,12 +2,20 @@
2
2
  <ButtonToggle :value="currentValue" :options="$options.alignments" @change="apply">
3
3
  <template #option="{ isActive, option, activate }">
4
4
  <Button
5
+ class="zw-position--relative"
5
6
  icon
6
7
  skin="toolbar"
7
8
  :active="isActive"
8
9
  @click="activate"
9
10
  v-tooltip="option.tooltip"
10
11
  >
12
+ <Icon
13
+ v-if="isCustomized && isActive"
14
+ class="zw-button__customized-indicator"
15
+ name="indicator"
16
+ size="9px"
17
+ data-test-selector="customizedIndicator"
18
+ />
11
19
  <Icon :name="`alignment-${option.id}`" size="28px" auto-color />
12
20
  </Button>
13
21
  </template>
@@ -17,7 +25,7 @@
17
25
  <script>
18
26
  import { inject } from 'vue';
19
27
  import { InjectionTokens } from '../../../injectionTokens';
20
- import { Alignments } from '../../../enums';
28
+ import { Alignments, TextSettings } from '../../../enums';
21
29
  import { ButtonToggle, Button, Icon } from '../../base';
22
30
  import { tooltip } from '../../../directives';
23
31
 
@@ -57,6 +65,7 @@ export default {
57
65
  const editor = inject(InjectionTokens.EDITOR);
58
66
 
59
67
  const currentValue = editor.commands.getAlignment();
68
+ const isCustomized = editor.commands.isSettingCustomized('attributes', TextSettings.ALIGNMENT);
60
69
 
61
70
  function apply(value) {
62
71
  editor.chain().focus().applyAlignment(value).run();
@@ -65,6 +74,7 @@ export default {
65
74
 
66
75
  return {
67
76
  currentValue,
77
+ isCustomized,
68
78
  apply
69
79
  };
70
80
  }
@@ -2,6 +2,7 @@
2
2
  <ColorPicker :value="currentValue" @change="apply">
3
3
  <template #activator="{ toggle, isOpened }">
4
4
  <Button
5
+ class="zw-position--relative"
5
6
  icon
6
7
  skin="toolbar"
7
8
  :active="isOpened"
@@ -9,6 +10,14 @@
9
10
  v-tooltip="'Font Color'"
10
11
  >
11
12
  <Icon name="font-color" size="28px" auto-color />
13
+
14
+ <Icon
15
+ v-if="isCustomized"
16
+ class="zw-button__customized-indicator"
17
+ name="indicator"
18
+ size="9px"
19
+ data-test-selector="customizedIndicator"
20
+ />
12
21
  </Button>
13
22
  </template>
14
23
  </ColorPicker>
@@ -19,6 +28,7 @@ import { inject } from 'vue';
19
28
  import { ColorPicker, Button, Icon } from '../../base';
20
29
  import { InjectionTokens } from '../../../injectionTokens';
21
30
  import { tooltip } from '../../../directives';
31
+ import { TextSettings } from '../../../enums';
22
32
 
23
33
  export default {
24
34
  name: 'FontColorControl',
@@ -37,10 +47,13 @@ export default {
37
47
  const editor = inject(InjectionTokens.EDITOR);
38
48
 
39
49
  const currentValue = editor.commands.getFontColor();
50
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_COLOR);
51
+
40
52
  const apply = (color) => editor.chain().applyFontColor(color).run();
41
53
 
42
54
  return {
43
55
  currentValue,
56
+ isCustomized,
44
57
  apply
45
58
  };
46
59
  }
@@ -3,6 +3,7 @@
3
3
  class="zw-font-family-control"
4
4
  :options="options"
5
5
  :value="currentValue"
6
+ :is-customized="isCustomized"
6
7
  @change="apply"
7
8
  v-tooltip="'Font Name'"
8
9
  >
@@ -22,6 +23,7 @@ import { computed, inject } from 'vue';
22
23
  import { InjectionTokens } from '../../../injectionTokens';
23
24
  import { tooltip } from '../../../directives';
24
25
  import { Dropdown, DropdownOption } from '../../base';
26
+ import { TextSettings } from '../../../enums';
25
27
  import { useRecentFonts } from './composables';
26
28
 
27
29
  export default {
@@ -67,6 +69,7 @@ export default {
67
69
  }
68
70
 
69
71
  const currentValue = editor.commands.getFontFamily();
72
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_FAMILY);
70
73
 
71
74
  const apply = (fontFamily) => {
72
75
  recentFontNames.add(fontFamily);
@@ -76,6 +79,7 @@ export default {
76
79
  return {
77
80
  options,
78
81
  currentValue,
82
+ isCustomized,
79
83
  renderOptionStyles,
80
84
  apply
81
85
  };
@@ -3,6 +3,7 @@
3
3
  class="zw-font-size-control"
4
4
  :options="options"
5
5
  :value="currentValue"
6
+ :is-customized="isCustomized"
6
7
  @change="apply"
7
8
  v-tooltip="{ text: 'Font Size', hotkey: 'Mod Shift +/-' }"
8
9
  />
@@ -13,6 +14,7 @@ import { computed, inject } from 'vue';
13
14
  import { Dropdown } from '../../base';
14
15
  import { InjectionTokens } from '../../../injectionTokens';
15
16
  import { tooltip } from '../../../directives';
17
+ import { TextSettings } from '../../../enums';
16
18
 
17
19
  export default {
18
20
  name: 'FontSizeControl',
@@ -34,11 +36,14 @@ export default {
34
36
  });
35
37
 
36
38
  const currentValue = editor.commands.getFontSize();
39
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_SIZE);
40
+
37
41
  const apply = (value) => editor.chain().focus().applyFontSize(value).run();
38
42
 
39
43
  return {
40
44
  options,
41
45
  currentValue,
46
+ isCustomized,
42
47
  apply
43
48
  };
44
49
  }
@@ -47,6 +52,6 @@ export default {
47
52
 
48
53
  <style scoped>
49
54
  .zw-font-size-control {
50
- width: 64px;
55
+ width: 72px;
51
56
  }
52
57
  </style>
@@ -1,7 +1,9 @@
1
1
  <template>
2
2
  <Dropdown
3
+ class="zw-font-weight-control"
3
4
  :options="options"
4
5
  :value="currentValue"
6
+ :is-customized="isCustomized"
5
7
  @change="apply"
6
8
  v-tooltip="{ text: 'Font Weight', hotkey: 'Mod B' }"
7
9
  />
@@ -12,6 +14,7 @@ import { computed, inject, unref } from 'vue';
12
14
  import { InjectionTokens } from '../../../injectionTokens';
13
15
  import { Dropdown } from '../../base';
14
16
  import { tooltip } from '../../../directives';
17
+ import { TextSettings } from '../../../enums';
15
18
 
16
19
  export default {
17
20
  name: 'FontWeightControl',
@@ -29,15 +32,24 @@ export default {
29
32
  const font = editor.commands.getFont();
30
33
 
31
34
  const options = computed(() => unref(font).weights.map((style) => ({ id: style })));
35
+
32
36
  const currentValue = editor.commands.getFontWeight();
37
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_WEIGHT);
33
38
 
34
39
  const apply = (value) => editor.chain().focus().applyFontWeight(value).run();
35
40
 
36
41
  return {
37
42
  options,
38
43
  currentValue,
44
+ isCustomized,
39
45
  apply
40
46
  };
41
47
  }
42
48
  };
43
49
  </script>
50
+
51
+ <style scoped>
52
+ .zw-font-weight-control {
53
+ width: 60px;
54
+ }
55
+ </style>
@@ -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"
@@ -8,6 +9,14 @@
8
9
  v-tooltip="{ text: 'Italic', hotkey: 'Mod I' }"
9
10
  >
10
11
  <Icon name="italic" size="28px" auto-color />
12
+
13
+ <Icon
14
+ v-if="isCustomized"
15
+ class="zw-button__customized-indicator"
16
+ name="indicator"
17
+ size="9px"
18
+ data-test-selector="customizedIndicator"
19
+ />
11
20
  </Button>
12
21
  </template>
13
22
 
@@ -16,6 +25,7 @@ import { inject } from 'vue';
16
25
  import { Button, Icon } from '../../base';
17
26
  import { InjectionTokens } from '../../../injectionTokens';
18
27
  import { tooltip } from '../../../directives';
28
+ import { TextSettings } from '../../../enums';
19
29
 
20
30
  export default {
21
31
  name: 'ItalicControl',
@@ -33,12 +43,15 @@ export default {
33
43
  const editor = inject(InjectionTokens.EDITOR);
34
44
 
35
45
  const currentValue = editor.commands.isItalic();
46
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_STYLE);
47
+
36
48
  const isAvailable = editor.commands.isItalicAvailable();
37
49
  const apply = () => editor.chain().focus().toggleItalic().run();
38
50
 
39
51
  return {
40
52
  isAvailable,
41
53
  currentValue,
54
+ isCustomized,
42
55
  apply
43
56
  };
44
57
  }
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div class="zw-position--relative" ref="wrapperRef">
3
3
  <Button
4
+ class="zw-position--relative"
4
5
  icon
5
6
  skin="toolbar"
6
7
  :active="isOpened"
@@ -8,6 +9,14 @@
8
9
  v-tooltip="'Line Height'"
9
10
  >
10
11
  <Icon name="line-height" size="28px" auto-color />
12
+
13
+ <Icon
14
+ v-if="isCustomized"
15
+ class="zw-button__customized-indicator"
16
+ name="indicator"
17
+ size="9px"
18
+ data-test-selector="customizedIndicator"
19
+ />
11
20
  </Button>
12
21
 
13
22
  <Modal class="zw-line-height-control__modal" ref="modalRef" :toggler="toggler">
@@ -44,6 +53,7 @@ import { inject, ref } from 'vue';
44
53
  import { Button, Icon, Modal, Range, NumberField, FieldLabel, useModalToggler } from '../../base';
45
54
  import { InjectionTokens } from '../../../injectionTokens';
46
55
  import { tooltip } from '../../../directives';
56
+ import { TextSettings } from '../../../enums';
47
57
 
48
58
  export default {
49
59
  name: 'LineHeightControl',
@@ -66,13 +76,17 @@ export default {
66
76
  const modalRef = ref(null);
67
77
  const editor = inject(InjectionTokens.EDITOR);
68
78
  const toggler = useModalToggler({ wrapperRef, modalRef });
79
+
69
80
  const currentValue = editor.commands.getLineHeight();
81
+ const isCustomized = editor.commands.isSettingCustomized('attributes', TextSettings.LINE_HEIGHT);
82
+
70
83
  const apply = (value) => editor.commands.applyLineHeight(String(value));
71
84
 
72
85
  return {
73
86
  wrapperRef,
74
87
  modalRef,
75
88
  isOpened: toggler.isOpened,
89
+ isCustomized,
76
90
  toggler,
77
91
  currentValue,
78
92
  apply
@@ -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,14 @@
7
8
  v-tooltip="{ text: 'Underline', hotkey: 'Mod U' }"
8
9
  >
9
10
  <Icon name="underline" size="28px" auto-color />
11
+
12
+ <Icon
13
+ v-if="isCustomized"
14
+ class="zw-button__customized-indicator"
15
+ name="indicator"
16
+ size="9px"
17
+ data-test-selector="customizedIndicator"
18
+ />
10
19
  </Button>
11
20
  </template>
12
21
 
@@ -32,10 +41,13 @@ export default {
32
41
  const editor = inject(InjectionTokens.EDITOR);
33
42
 
34
43
  const currentValue = editor.commands.isUnderline();
44
+ const isCustomized = editor.commands.isUnderlineCustomized();
45
+
35
46
  const apply = () => editor.chain().focus().toggleUnderline().run();
36
47
 
37
48
  return {
38
49
  currentValue,
50
+ isCustomized,
39
51
  apply
40
52
  };
41
53
  }
@@ -5,9 +5,14 @@ import { Alignments } from '../../../../enums';
5
5
  import { ButtonToggle } from '../../../base';
6
6
  import AlignmentControl from '../AlignmentControl';
7
7
 
8
- const createEditor = ({ alignment } = {}) => ({
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()
@@ -18,11 +23,18 @@ const createEditor = ({ alignment } = {}) => ({
18
23
  }
19
24
  });
20
25
 
21
- function createComponent({ editor }) {
26
+ function createComponent({ editor, slotParams }) {
22
27
  return shallowMount(AlignmentControl, {
23
28
  stubs: {
24
29
  ButtonToggle: {
25
- render: () => h('div'),
30
+ render() {
31
+ const children = this.$scopedSlots.option({
32
+ ...slotParams,
33
+ activate: jest.fn()
34
+ });
35
+
36
+ return h('div', null, children);
37
+ },
26
38
  props: ['value']
27
39
  }
28
40
  },
@@ -33,7 +45,16 @@ function createComponent({ editor }) {
33
45
  describe('selection value', () => {
34
46
  test('should render value from selection', () => {
35
47
  const editor = createEditor({ alignment: Alignments.RIGHT });
36
- const wrapper = createComponent({ editor });
48
+ const wrapper = createComponent({
49
+ editor,
50
+ slotParams: {
51
+ option: {
52
+ id: Alignments.RIGHT,
53
+ tooltip: { text: 'Align Right', hotkey: 'Mod Shift R' }
54
+ },
55
+ isActive: true
56
+ }
57
+ });
37
58
  const buttonWrapper = wrapper.findComponent(ButtonToggle);
38
59
 
39
60
  expect(buttonWrapper.props('value')).toBe(Alignments.RIGHT);
@@ -41,7 +62,16 @@ describe('selection value', () => {
41
62
 
42
63
  test('should apply new value', () => {
43
64
  const editor = createEditor({ alignment: Alignments.RIGHT });
44
- const wrapper = createComponent({ editor });
65
+ const wrapper = createComponent({
66
+ editor,
67
+ slotParams: {
68
+ option: {
69
+ id: Alignments.RIGHT,
70
+ tooltip: { text: 'Align Right', hotkey: 'Mod Shift R' }
71
+ },
72
+ isActive: true
73
+ }
74
+ });
45
75
  const buttonWrapper = wrapper.findComponent(ButtonToggle);
46
76
 
47
77
  buttonWrapper.vm.$emit('change', Alignments.CENTER);
@@ -49,3 +79,40 @@ describe('selection value', () => {
49
79
  expect(editor.commands.applyAlignment).toHaveBeenCalledWith(Alignments.CENTER);
50
80
  });
51
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 createEditor = ({ fontColor } = {}) => ({
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,7 @@ import FontFamilyControl from '../FontFamilyControl';
7
7
  const createEditor = ({ fontFamily } = {}) => ({
8
8
  commands: {
9
9
  getFontFamily: () => ref(fontFamily),
10
+ isSettingCustomized: () => ref(false),
10
11
  focus: jest.fn().mockReturnThis(),
11
12
  applyFontFamily: jest.fn().mockReturnThis(),
12
13
  run: jest.fn()
@@ -7,6 +7,7 @@ import FontSizeControl from '../FontSizeControl';
7
7
  const createEditor = ({ fontSize } = {}) => ({
8
8
  commands: {
9
9
  getFontSize: () => ref(fontSize),
10
+ isSettingCustomized: () => ref(false),
10
11
  focus: jest.fn().mockReturnThis(),
11
12
  applyFontSize: jest.fn().mockReturnThis(),
12
13
  run: jest.fn()
@@ -7,6 +7,7 @@ import FontWeightControl from '../FontWeightControl';
7
7
  const createEditor = ({ fontWeight, fontWeightList } = {}) => ({
8
8
  commands: {
9
9
  getFontWeight: () => ref(fontWeight ?? '400'),
10
+ isSettingCustomized: () => ref(false),
10
11
  getFont: () => ref({ weights: fontWeightList ?? ['400', '700'] }),
11
12
  focus: jest.fn().mockReturnThis(),
12
13
  applyFontWeight: jest.fn().mockReturnThis(),