@zipify/wysiwyg 2.0.0-1 → 2.0.0-10

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 (97) hide show
  1. package/config/build/cli.config.js +8 -2
  2. package/dist/cli.js +3 -3
  3. package/dist/wysiwyg.css +41 -31
  4. package/dist/wysiwyg.mjs +2002 -1362
  5. package/example/ExampleApp.vue +10 -1
  6. package/lib/Wysiwyg.vue +3 -2
  7. package/lib/__tests__/utils/buildTestExtensions.js +2 -1
  8. package/lib/assets/icons/indicator.svg +4 -0
  9. package/lib/cli/commands/Command.js +39 -0
  10. package/lib/cli/commands/ToJsonCommand.js +46 -0
  11. package/lib/cli/commands/VersionCommand.js +11 -0
  12. package/lib/cli/commands/index.js +2 -0
  13. package/lib/cli/index.js +1 -0
  14. package/lib/components/base/Button.vue +6 -0
  15. package/lib/components/base/dropdown/Dropdown.vue +7 -1
  16. package/lib/components/base/dropdown/DropdownActivator.vue +25 -4
  17. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +23 -1
  18. package/lib/components/toolbar/controls/AlignmentControl.vue +12 -1
  19. package/lib/components/toolbar/controls/FontColorControl.vue +14 -0
  20. package/lib/components/toolbar/controls/FontFamilyControl.vue +4 -0
  21. package/lib/components/toolbar/controls/FontSizeControl.vue +6 -1
  22. package/lib/components/toolbar/controls/FontWeightControl.vue +12 -0
  23. package/lib/components/toolbar/controls/ItalicControl.vue +14 -0
  24. package/lib/components/toolbar/controls/LineHeightControl.vue +15 -0
  25. package/lib/components/toolbar/controls/UnderlineControl.vue +13 -0
  26. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +72 -5
  27. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +22 -1
  28. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +1 -0
  29. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +1 -0
  30. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +1 -0
  31. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +23 -1
  32. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +23 -1
  33. package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +4 -4
  34. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +25 -1
  35. package/lib/composables/__tests__/useEditor.test.js +1 -1
  36. package/lib/composables/useEditor.js +9 -8
  37. package/lib/directives/__tests__/tooltip.test.js +22 -4
  38. package/lib/directives/tooltip.js +4 -1
  39. package/lib/entry-cli.js +7 -20
  40. package/lib/entry-lib.js +1 -1
  41. package/lib/enums/MarkGroups.js +4 -0
  42. package/lib/enums/TextSettings.js +1 -1
  43. package/lib/enums/index.js +1 -0
  44. package/lib/extensions/BackgroundColor.js +0 -1
  45. package/lib/extensions/FontColor.js +2 -2
  46. package/lib/extensions/FontFamily.js +3 -3
  47. package/lib/extensions/FontSize.js +2 -2
  48. package/lib/extensions/FontStyle.js +2 -2
  49. package/lib/extensions/FontWeight.js +2 -2
  50. package/lib/extensions/StylePreset.js +8 -2
  51. package/lib/extensions/Superscript.js +5 -2
  52. package/lib/extensions/TextDecoration.js +7 -0
  53. package/lib/extensions/__tests__/Alignment.test.js +2 -2
  54. package/lib/extensions/__tests__/BackgroundColor.test.js +4 -3
  55. package/lib/extensions/__tests__/FontColor.test.js +4 -3
  56. package/lib/extensions/__tests__/FontFamily.test.js +6 -6
  57. package/lib/extensions/__tests__/FontSize.test.js +9 -8
  58. package/lib/extensions/__tests__/FontStyle.test.js +6 -5
  59. package/lib/extensions/__tests__/LineHeight.test.js +2 -1
  60. package/lib/extensions/__tests__/StylePreset.test.js +51 -0
  61. package/lib/extensions/__tests__/Superscript.test.js +102 -0
  62. package/lib/extensions/__tests__/TextDecoration.test.js +20 -0
  63. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +25 -25
  64. package/lib/extensions/__tests__/__snapshots__/Superscript.test.js.snap +107 -0
  65. package/lib/extensions/core/Document.js +2 -1
  66. package/lib/extensions/core/Heading.js +2 -1
  67. package/lib/extensions/core/NodeProcessor.js +42 -21
  68. package/lib/extensions/core/Paragraph.js +2 -1
  69. package/lib/extensions/core/__tests__/NodeProcessor.test.js +309 -11
  70. package/lib/extensions/core/__tests__/TextProcessor.test.js +1 -1
  71. package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +249 -0
  72. package/lib/extensions/core/steps/AddNodeMarkStep.js +6 -0
  73. package/lib/extensions/core/steps/AttrStep.js +6 -0
  74. package/lib/extensions/core/steps/RemoveNodeMarkStep.js +6 -0
  75. package/lib/extensions/list/List.js +70 -9
  76. package/lib/extensions/list/ListItem.js +2 -2
  77. package/lib/extensions/list/__tests__/List.test.js +26 -17
  78. package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +36 -36
  79. package/lib/services/NodeFactory.js +69 -3
  80. package/lib/services/__tests__/NodeFactory.test.js +124 -0
  81. package/lib/services/__tests__/__snapshots__/NodeFactory.test.js.snap +326 -0
  82. package/lib/services/normalizer/HtmlNormalizer.js +54 -2
  83. package/lib/services/normalizer/JsonNormalizer.js +6 -5
  84. package/lib/services/normalizer/__tests__/HtmlNormalizer.test.js +14 -0
  85. package/lib/services/normalizer/__tests__/JsonNormalizer.test.js +20 -3
  86. package/lib/services/normalizer/__tests__/__snapshots__/JsonNormalizer.test.js.snap +37 -0
  87. package/lib/utils/__tests__/findMarkByType.test.js +17 -0
  88. package/lib/utils/__tests__/isMarkAppliedToParent.test.js +53 -0
  89. package/lib/utils/__tests__/isNodeFullySelected.test.js +44 -0
  90. package/lib/utils/__tests__/resolveTextPosition.test.js +39 -0
  91. package/lib/utils/copyMark.js +5 -0
  92. package/lib/utils/index.js +1 -1
  93. package/lib/utils/isMarkAppliedToParent.js +1 -1
  94. package/lib/utils/isNodeFullySelected.js +4 -7
  95. package/lib/utils/resolveTextPosition.js +4 -6
  96. package/package.json +29 -27
  97. package/lib/utils/resolveNodePosition.js +0 -6
@@ -12,6 +12,10 @@
12
12
  </option>
13
13
  </select>
14
14
 
15
+ <button type="button" class="zw-load-content" @click="saveContent">
16
+ Save Content
17
+ </button>
18
+
15
19
  <button type="button" class="zw-load-content" @click="loadContent">
16
20
  Load Content
17
21
  </button>
@@ -45,7 +49,7 @@
45
49
  </template>
46
50
 
47
51
  <script>
48
- import { computed, onMounted, ref } from 'vue';
52
+ import { computed, onMounted, ref, unref } from 'vue';
49
53
  import { Wysiwyg } from '../lib/entry-lib';
50
54
  import { FONTS } from './fonts';
51
55
  import { PRESETS, renderPresetVariable } from './presets';
@@ -109,6 +113,10 @@ export default {
109
113
  window.location.reload();
110
114
  }
111
115
 
116
+ function saveContent() {
117
+ sessionStorage.setItem('wswg-data', JSON.stringify(unref(content)));
118
+ }
119
+
112
120
  document.addEventListener('click', (event) => {
113
121
  isActive.value = wswgRef.value.$el.contains(event.target);
114
122
  });
@@ -121,6 +129,7 @@ export default {
121
129
  favoriteColors,
122
130
  updateFavoriteColors,
123
131
  loadContent,
132
+ saveContent,
124
133
  device,
125
134
  updatedAt,
126
135
  presets,
package/lib/Wysiwyg.vue CHANGED
@@ -163,7 +163,7 @@ export default {
163
163
 
164
164
  const pageBlocks = toRef(props, 'pageBlocks');
165
165
 
166
- const editor = useEditor({
166
+ const { editor, getContent } = useEditor({
167
167
  content: toRef(props, 'value'),
168
168
  onChange: (content) => onChange(content),
169
169
  isReadonlyRef: toRef(props, 'readonly'),
@@ -206,7 +206,8 @@ export default {
206
206
  toolbarRef,
207
207
  wysiwygRef,
208
208
  toolbar,
209
- updateToolbar
209
+ updateToolbar,
210
+ getContent
210
211
  };
211
212
  }
212
213
  };
@@ -1,11 +1,12 @@
1
1
  import { Mark } from '@tiptap/vue-2';
2
2
  import { buildCoreExtensions } from '../../extensions/core';
3
+ import { MarkGroups } from '../../enums';
3
4
 
4
5
  // each node allows using 'settings' group of marks,
5
6
  // and it fails when there are no nodes with this group
6
7
  const SettingMark = Mark.create({
7
8
  name: 'placeholder_setting',
8
- group: 'settings',
9
+ group: MarkGroups.SETTINGS,
9
10
  renderHTML: () => []
10
11
  });
11
12
 
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 9 9">
2
+ <path fill="#FFAB00" d="M0 4.5a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0Z"/>
3
+ <path fill="#fff" fill-rule="evenodd" d="M5.063 2.25H3.938v3.375h1.124V2.25Zm-1.125 4.5a.562.562 0 1 1 1.123-.001.562.562 0 0 1-1.123.001Z" clip-rule="evenodd"/>
4
+ </svg>
@@ -0,0 +1,39 @@
1
+ export class Command {
2
+ name;
3
+ description;
4
+ argument;
5
+ options = [];
6
+
7
+ doCommand() {
8
+ throw new Error('Command "doCommand" is required');
9
+ }
10
+
11
+ install(program) {
12
+ if (!this.name) {
13
+ throw new Error('Command "name" is required');
14
+ }
15
+
16
+ let building = program.command(this.name);
17
+
18
+ if (this.description) {
19
+ building = building.description(this.description);
20
+ }
21
+
22
+ if (this.argument) {
23
+ building = building.argument(this.argument);
24
+ }
25
+
26
+ if (this.options.length) {
27
+ for (const option of this.options) {
28
+ building = building.option(option.flags, option.description, option.default);
29
+ }
30
+ }
31
+
32
+ building.action(this.doCommand.bind(this));
33
+ }
34
+
35
+ output(data) {
36
+ // eslint-disable-next-line no-console
37
+ console.log(data);
38
+ }
39
+ }
@@ -0,0 +1,46 @@
1
+ import { resolve } from 'path';
2
+ import { ContentSerializer } from '../ContentSerializer';
3
+ import { Command } from './Command';
4
+
5
+ export class ToJsonCommand extends Command {
6
+ name = 'to-json';
7
+ description = 'migrate html to json';
8
+ argument = '<html>';
9
+
10
+ options = [
11
+ {
12
+ flags: '--config <path>',
13
+ description: 'Generator config',
14
+ // Relative to dist folder
15
+ default: resolve(__dirname, '../bin/zp.config.json')
16
+ }
17
+ ];
18
+
19
+ doCommand(html, { config }) {
20
+ const configPath = resolve(process.cwd(), config);
21
+ const serializer = ContentSerializer.build(require(configPath).editor);
22
+ const json = serializer.toJSON(this.#formatInputHtml(html));
23
+
24
+ this.output(this.#formatOutputJson(json));
25
+ }
26
+
27
+ #formatInputHtml(html) {
28
+ return html
29
+ .replace(/\\(["'])/g, '$1')
30
+ .replace(/rgba\(\d{1,3}, ?\d{1,3}, ?\d{1,3}, (\d{1,2}%)\)/g, (substring, alpha) => {
31
+ return substring.replace(alpha, parseFloat(alpha) / 100);
32
+ });
33
+ }
34
+
35
+ #formatOutputJson(object) {
36
+ const skipNullValue = (_, value) => value === null ? undefined : value;
37
+ const json = JSON.stringify(object, skipNullValue, 2);
38
+
39
+ return json
40
+ .replace(/\\"/g, '"')
41
+ .replace(/font-family: ?'(.+)'/g, 'font-family: "$1"')
42
+ .replace(/'/g, '\\\'')
43
+ .replace(/^[\t ]*"[^:\n\r]+(?<!\\)":/gm, (match) => match.replace(/"/g, ''))
44
+ .replace(/: "(.+)"([,\n])/g, ': \'$1\'$2');
45
+ }
46
+ }
@@ -0,0 +1,11 @@
1
+ import { version } from '../../../package.json';
2
+ import { Command } from './Command';
3
+
4
+ export class VersionCommand extends Command {
5
+ name = 'version';
6
+ description = 'display cli version';
7
+
8
+ doCommand() {
9
+ this.output(version);
10
+ }
11
+ }
@@ -0,0 +1,2 @@
1
+ export { ToJsonCommand } from './ToJsonCommand';
2
+ export { VersionCommand } from './VersionCommand';
package/lib/cli/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { ContentSerializer } from './ContentSerializer';
2
+ export * from './commands';
@@ -135,4 +135,10 @@ 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
+ position: absolute;
141
+ top: 0;
142
+ right: 2px;
143
+ }
138
144
  </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,15 @@
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
+ v-tooltip.xs="'Default parameter setting is changed'"
22
+ />
23
+
15
24
  <Icon
16
25
  class="zw-dropdown__activator-arrow"
17
26
  name="arrow"
@@ -27,6 +36,7 @@
27
36
  import { computed, inject, toRef } from 'vue';
28
37
  import Button from '../Button';
29
38
  import Icon from '../Icon';
39
+ import { tooltip } from '../../../directives';
30
40
  import { InjectionTokens } from './injectionTokens';
31
41
  import { useDropdownEntityTitle } from './composables';
32
42
 
@@ -38,6 +48,10 @@ export default {
38
48
  Button
39
49
  },
40
50
 
51
+ directives: {
52
+ tooltip
53
+ },
54
+
41
55
  model: {
42
56
  event: 'change'
43
57
  },
@@ -47,6 +61,12 @@ export default {
47
61
  type: String,
48
62
  required: false,
49
63
  default: 'none'
64
+ },
65
+
66
+ isCustomized: {
67
+ type: Boolean,
68
+ required: false,
69
+ default: false
50
70
  }
51
71
  },
52
72
 
@@ -77,10 +97,6 @@ export default {
77
97
  width: 100%;
78
98
  }
79
99
 
80
- .zw-dropdown__activator-title {
81
- margin-right: var(--zw-offset-xs);
82
- }
83
-
84
100
  .zw-dropdown__activator-arrow {
85
101
  margin-left: auto;
86
102
  }
@@ -94,4 +110,9 @@ export default {
94
110
  font-size: var(--zw-font-size-xxs);
95
111
  color: rgb(var(--zw-color-white));
96
112
  }
113
+
114
+ .zw-dropdown__customized-indicator {
115
+ position: relative;
116
+ top: calc(0px - var(--zw-offset-xs));
117
+ }
97
118
  </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,21 @@
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
+ v-tooltip.xs="'Default parameter setting is changed'"
19
+ />
11
20
  <Icon :name="`alignment-${option.id}`" size="28px" auto-color />
12
21
  </Button>
13
22
  </template>
@@ -17,7 +26,7 @@
17
26
  <script>
18
27
  import { inject } from 'vue';
19
28
  import { InjectionTokens } from '../../../injectionTokens';
20
- import { Alignments } from '../../../enums';
29
+ import { Alignments, TextSettings } from '../../../enums';
21
30
  import { ButtonToggle, Button, Icon } from '../../base';
22
31
  import { tooltip } from '../../../directives';
23
32
 
@@ -57,6 +66,7 @@ export default {
57
66
  const editor = inject(InjectionTokens.EDITOR);
58
67
 
59
68
  const currentValue = editor.commands.getAlignment();
69
+ const isCustomized = editor.commands.isSettingCustomized('attributes', TextSettings.ALIGNMENT);
60
70
 
61
71
  function apply(value) {
62
72
  editor.chain().focus().applyAlignment(value).run();
@@ -65,6 +75,7 @@ export default {
65
75
 
66
76
  return {
67
77
  currentValue,
78
+ isCustomized,
68
79
  apply
69
80
  };
70
81
  }
@@ -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,15 @@
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
+ v-tooltip.xs="'Default parameter setting is changed'"
21
+ />
12
22
  </Button>
13
23
  </template>
14
24
  </ColorPicker>
@@ -19,6 +29,7 @@ import { inject } from 'vue';
19
29
  import { ColorPicker, Button, Icon } from '../../base';
20
30
  import { InjectionTokens } from '../../../injectionTokens';
21
31
  import { tooltip } from '../../../directives';
32
+ import { TextSettings } from '../../../enums';
22
33
 
23
34
  export default {
24
35
  name: 'FontColorControl',
@@ -37,10 +48,13 @@ export default {
37
48
  const editor = inject(InjectionTokens.EDITOR);
38
49
 
39
50
  const currentValue = editor.commands.getFontColor();
51
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_COLOR);
52
+
40
53
  const apply = (color) => editor.chain().applyFontColor(color).run();
41
54
 
42
55
  return {
43
56
  currentValue,
57
+ isCustomized,
44
58
  apply
45
59
  };
46
60
  }
@@ -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,15 @@
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
+ v-tooltip.xs="'Default parameter setting is changed'"
20
+ />
11
21
  </Button>
12
22
  </template>
13
23
 
@@ -16,6 +26,7 @@ import { inject } from 'vue';
16
26
  import { Button, Icon } from '../../base';
17
27
  import { InjectionTokens } from '../../../injectionTokens';
18
28
  import { tooltip } from '../../../directives';
29
+ import { TextSettings } from '../../../enums';
19
30
 
20
31
  export default {
21
32
  name: 'ItalicControl',
@@ -33,12 +44,15 @@ export default {
33
44
  const editor = inject(InjectionTokens.EDITOR);
34
45
 
35
46
  const currentValue = editor.commands.isItalic();
47
+ const isCustomized = editor.commands.isSettingCustomized('marks', TextSettings.FONT_STYLE);
48
+
36
49
  const isAvailable = editor.commands.isItalicAvailable();
37
50
  const apply = () => editor.chain().focus().toggleItalic().run();
38
51
 
39
52
  return {
40
53
  isAvailable,
41
54
  currentValue,
55
+ isCustomized,
42
56
  apply
43
57
  };
44
58
  }
@@ -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,15 @@
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
+ v-tooltip.xs="'Default parameter setting is changed'"
20
+ />
11
21
  </Button>
12
22
 
13
23
  <Modal class="zw-line-height-control__modal" ref="modalRef" :toggler="toggler">
@@ -44,6 +54,7 @@ import { inject, ref } from 'vue';
44
54
  import { Button, Icon, Modal, Range, NumberField, FieldLabel, useModalToggler } from '../../base';
45
55
  import { InjectionTokens } from '../../../injectionTokens';
46
56
  import { tooltip } from '../../../directives';
57
+ import { TextSettings } from '../../../enums';
47
58
 
48
59
  export default {
49
60
  name: 'LineHeightControl',
@@ -66,13 +77,17 @@ export default {
66
77
  const modalRef = ref(null);
67
78
  const editor = inject(InjectionTokens.EDITOR);
68
79
  const toggler = useModalToggler({ wrapperRef, modalRef });
80
+
69
81
  const currentValue = editor.commands.getLineHeight();
82
+ const isCustomized = editor.commands.isSettingCustomized('attributes', TextSettings.LINE_HEIGHT);
83
+
70
84
  const apply = (value) => editor.commands.applyLineHeight(String(value));
71
85
 
72
86
  return {
73
87
  wrapperRef,
74
88
  modalRef,
75
89
  isOpened: toggler.isOpened,
90
+ isCustomized,
76
91
  toggler,
77
92
  currentValue,
78
93
  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,15 @@
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
+ v-tooltip.xs="'Default parameter setting is changed'"
19
+ />
10
20
  </Button>
11
21
  </template>
12
22
 
@@ -32,10 +42,13 @@ export default {
32
42
  const editor = inject(InjectionTokens.EDITOR);
33
43
 
34
44
  const currentValue = editor.commands.isUnderline();
45
+ const isCustomized = editor.commands.isUnderlineCustomized();
46
+
35
47
  const apply = () => editor.chain().focus().toggleUnderline().run();
36
48
 
37
49
  return {
38
50
  currentValue,
51
+ isCustomized,
39
52
  apply
40
53
  };
41
54
  }