@zipify/wysiwyg 1.0.0-dev.1

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 (255) hide show
  1. package/.editorconfig +18 -0
  2. package/.eslintrc.js +253 -0
  3. package/.github/actions/deploy-example/action.yaml +61 -0
  4. package/.github/actions/lint-css/action.yaml +15 -0
  5. package/.github/actions/lint-js/action.yaml +22 -0
  6. package/.github/actions/setup/action.yaml +19 -0
  7. package/.github/actions/unit-tests/action.yaml +13 -0
  8. package/.github/actions/unit-tests/jest.config.js +8 -0
  9. package/.github/dependabot.yaml +17 -0
  10. package/.github/pull_request_template.md +17 -0
  11. package/.github/workflows/frontend-ci.yaml +120 -0
  12. package/.husky/pre-commit +4 -0
  13. package/.lintstagedrc +12 -0
  14. package/.release-it.json +6 -0
  15. package/.stylelintrc +110 -0
  16. package/README.md +61 -0
  17. package/babel.config.js +15 -0
  18. package/ci/example/deploy.sh +25 -0
  19. package/config/jest/TestEnvironment.js +27 -0
  20. package/config/jest/matchers/index.js +6 -0
  21. package/config/jest/matchers/toElementHasStyle.js +27 -0
  22. package/config/jest/matchers/toVueContainComponent.js +20 -0
  23. package/config/jest/matchers/toVueContainElement.js +34 -0
  24. package/config/jest/matchers/toVueContainLazyComponent.js +19 -0
  25. package/config/jest/matchers/toVueEmpty.js +16 -0
  26. package/config/jest/matchers/toVuexActionHasBeenDispatched.js +19 -0
  27. package/config/jest/setupMatchers.js +4 -0
  28. package/config/jest/setupTests.js +32 -0
  29. package/config/jest/typing.d.ts +14 -0
  30. package/config/svgo.js +22 -0
  31. package/config/webpack/example.config.js +86 -0
  32. package/config/webpack/loaders/index.js +6 -0
  33. package/config/webpack/loaders/js-loader.js +5 -0
  34. package/config/webpack/loaders/style-loader.js +7 -0
  35. package/config/webpack/loaders/svg-loader.js +4 -0
  36. package/config/webpack/loaders/vue-loader.js +4 -0
  37. package/config/webpack/settings.js +9 -0
  38. package/example/ExampleApp.vue +136 -0
  39. package/example/example.html +17 -0
  40. package/example/example.js +19 -0
  41. package/example/fonts.js +474 -0
  42. package/example/presets.js +245 -0
  43. package/example/tooltip/Tooltip.js +241 -0
  44. package/example/tooltip/TooltipManager.js +132 -0
  45. package/example/tooltip/index.js +3 -0
  46. package/example/tooltip/modifiers/TooltipCloseOnScrollModifier.js +73 -0
  47. package/example/tooltip/modifiers/index.js +1 -0
  48. package/example/tooltip/tooltip.css +95 -0
  49. package/jest.config.js +17 -0
  50. package/lib/Wysiwyg.vue +156 -0
  51. package/lib/__mocks__/svgMock.js +1 -0
  52. package/lib/__tests__/utils/NodeFactory.js +67 -0
  53. package/lib/__tests__/utils/index.js +4 -0
  54. package/lib/__tests__/utils/setReadonlyProperty.js +9 -0
  55. package/lib/__tests__/utils/waitAsyncOperation.js +6 -0
  56. package/lib/__tests__/utils/withComponentContext.js +14 -0
  57. package/lib/assets/icons.svg +69 -0
  58. package/lib/components/base/Button.vue +117 -0
  59. package/lib/components/base/ButtonToggle.vue +40 -0
  60. package/lib/components/base/FieldLabel.vue +28 -0
  61. package/lib/components/base/Icon.vue +67 -0
  62. package/lib/components/base/Modal.vue +116 -0
  63. package/lib/components/base/NumberField.vue +242 -0
  64. package/lib/components/base/Range.vue +196 -0
  65. package/lib/components/base/ScrollView.vue +60 -0
  66. package/lib/components/base/__tests__/Button.test.js +50 -0
  67. package/lib/components/base/__tests__/Icon.test.js +56 -0
  68. package/lib/components/base/__tests__/Modal.test.js +69 -0
  69. package/lib/components/base/__tests__/Range.test.js +39 -0
  70. package/lib/components/base/colorPicker/ColorPicker.vue +93 -0
  71. package/lib/components/base/colorPicker/composables/__tests__/usePickerApi.test.js +81 -0
  72. package/lib/components/base/colorPicker/composables/index.js +2 -0
  73. package/lib/components/base/colorPicker/composables/usePickerApi.js +35 -0
  74. package/lib/components/base/colorPicker/composables/usePickerHotkeys.js +25 -0
  75. package/lib/components/base/colorPicker/index.js +1 -0
  76. package/lib/components/base/composables/__tests__/useActivatedListener.test.js +89 -0
  77. package/lib/components/base/composables/__tests__/useDeselectionLock.test.js +80 -0
  78. package/lib/components/base/composables/__tests__/useElementRef.test.js +29 -0
  79. package/lib/components/base/composables/__tests__/useModalToggler.test.js +55 -0
  80. package/lib/components/base/composables/__tests__/useNumberValue.test.js +153 -0
  81. package/lib/components/base/composables/__tests__/useScrollView.test.js +43 -0
  82. package/lib/components/base/composables/__tests__/useTempValue.test.js +38 -0
  83. package/lib/components/base/composables/index.js +7 -0
  84. package/lib/components/base/composables/useActivatedListener.js +23 -0
  85. package/lib/components/base/composables/useDeselectionLock.js +35 -0
  86. package/lib/components/base/composables/useElementRef.js +5 -0
  87. package/lib/components/base/composables/useModalToggler.js +58 -0
  88. package/lib/components/base/composables/useNumberValue.js +53 -0
  89. package/lib/components/base/composables/useScrollView.js +22 -0
  90. package/lib/components/base/composables/useTempValue.js +11 -0
  91. package/lib/components/base/dropdown/Dropdown.vue +88 -0
  92. package/lib/components/base/dropdown/DropdownActivator.vue +81 -0
  93. package/lib/components/base/dropdown/DropdownDivider.vue +21 -0
  94. package/lib/components/base/dropdown/DropdownGroup.vue +55 -0
  95. package/lib/components/base/dropdown/DropdownMenu.vue +62 -0
  96. package/lib/components/base/dropdown/DropdownOption.vue +91 -0
  97. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +54 -0
  98. package/lib/components/base/dropdown/__tests__/DropdownMenu.test.js +67 -0
  99. package/lib/components/base/dropdown/__tests__/DropdownOption.test.js +81 -0
  100. package/lib/components/base/dropdown/composables/__tests__/useActiveOptionManager.test.js +41 -0
  101. package/lib/components/base/dropdown/composables/__tests__/useDropdownEntityTitle.test.js +24 -0
  102. package/lib/components/base/dropdown/composables/index.js +2 -0
  103. package/lib/components/base/dropdown/composables/useActiveOptionManager.js +25 -0
  104. package/lib/components/base/dropdown/composables/useDropdownEntityTitle.js +5 -0
  105. package/lib/components/base/dropdown/index.js +2 -0
  106. package/lib/components/base/dropdown/injectionTokens.js +5 -0
  107. package/lib/components/base/index.js +11 -0
  108. package/lib/components/index.js +1 -0
  109. package/lib/components/toolbar/Toolbar.vue +56 -0
  110. package/lib/components/toolbar/ToolbarDevice.vue +35 -0
  111. package/lib/components/toolbar/ToolbarDivider.vue +50 -0
  112. package/lib/components/toolbar/ToolbarFull.vue +94 -0
  113. package/lib/components/toolbar/ToolbarGroup.vue +18 -0
  114. package/lib/components/toolbar/ToolbarRow.vue +19 -0
  115. package/lib/components/toolbar/__tests__/Toolbar.test.js +33 -0
  116. package/lib/components/toolbar/__tests__/ToolbarDivider.test.js +26 -0
  117. package/lib/components/toolbar/controls/AlignmentControl.vue +72 -0
  118. package/lib/components/toolbar/controls/AlignmentDeviceControl.vue +67 -0
  119. package/lib/components/toolbar/controls/BackgroundColorControl.vue +48 -0
  120. package/lib/components/toolbar/controls/CaseStyleControl.vue +54 -0
  121. package/lib/components/toolbar/controls/FontColorControl.vue +48 -0
  122. package/lib/components/toolbar/controls/FontFamilyControl.vue +96 -0
  123. package/lib/components/toolbar/controls/FontSizeControl.vue +45 -0
  124. package/lib/components/toolbar/controls/FontWeightControl.vue +43 -0
  125. package/lib/components/toolbar/controls/ItalicControl.vue +47 -0
  126. package/lib/components/toolbar/controls/LineHeightControl.vue +102 -0
  127. package/lib/components/toolbar/controls/ListControl.vue +86 -0
  128. package/lib/components/toolbar/controls/RemoveFormatControl.vue +37 -0
  129. package/lib/components/toolbar/controls/StrikeThroughControl.vue +44 -0
  130. package/lib/components/toolbar/controls/StylePresetControl.vue +95 -0
  131. package/lib/components/toolbar/controls/SuperscriptControl.vue +44 -0
  132. package/lib/components/toolbar/controls/UnderlineControl.vue +44 -0
  133. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +51 -0
  134. package/lib/components/toolbar/controls/__tests__/AlignmentDeviceControl.test.js +77 -0
  135. package/lib/components/toolbar/controls/__tests__/BackgroundColorControl.test.js +59 -0
  136. package/lib/components/toolbar/controls/__tests__/CaseStyleControl.test.js +43 -0
  137. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +59 -0
  138. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +57 -0
  139. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +47 -0
  140. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +45 -0
  141. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +63 -0
  142. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +120 -0
  143. package/lib/components/toolbar/controls/__tests__/ListControl.test.js +82 -0
  144. package/lib/components/toolbar/controls/__tests__/RemoveFormatControl.test.js +34 -0
  145. package/lib/components/toolbar/controls/__tests__/StrikeThroughControl.test.js +44 -0
  146. package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +129 -0
  147. package/lib/components/toolbar/controls/__tests__/SuperscriptControl.test.js +44 -0
  148. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +44 -0
  149. package/lib/components/toolbar/controls/composables/__tests__/useRecentFonts.test.js +69 -0
  150. package/lib/components/toolbar/controls/composables/index.js +1 -0
  151. package/lib/components/toolbar/controls/composables/useRecentFonts.js +18 -0
  152. package/lib/components/toolbar/controls/index.js +16 -0
  153. package/lib/components/toolbar/index.js +1 -0
  154. package/lib/composables/__tests__/__snapshots__/useEditor.test.js.snap +24 -0
  155. package/lib/composables/__tests__/useEditor.test.js +67 -0
  156. package/lib/composables/__tests__/useToolbar.test.js +56 -0
  157. package/lib/composables/index.js +2 -0
  158. package/lib/composables/useEditor.js +21 -0
  159. package/lib/composables/useToolbar.js +44 -0
  160. package/lib/directives/__tests__/outClick.test.js +86 -0
  161. package/lib/directives/__tests__/tooltip.test.js +39 -0
  162. package/lib/directives/index.js +2 -0
  163. package/lib/directives/outClick.js +37 -0
  164. package/lib/directives/tooltip.js +7 -0
  165. package/lib/enums/Alignments.js +6 -0
  166. package/lib/enums/CaseStyles.js +5 -0
  167. package/lib/enums/Devices.js +15 -0
  168. package/lib/enums/ListTypes.js +23 -0
  169. package/lib/enums/NodeTypes.js +12 -0
  170. package/lib/enums/TextSettings.js +30 -0
  171. package/lib/enums/index.js +6 -0
  172. package/lib/extensions/Alignment.js +67 -0
  173. package/lib/extensions/BackgroundColor.js +28 -0
  174. package/lib/extensions/CaseStyle.js +36 -0
  175. package/lib/extensions/DeviceManager.js +16 -0
  176. package/lib/extensions/FontColor.js +36 -0
  177. package/lib/extensions/FontFamily.js +62 -0
  178. package/lib/extensions/FontSize.js +74 -0
  179. package/lib/extensions/FontStyle.js +62 -0
  180. package/lib/extensions/FontWeight.js +56 -0
  181. package/lib/extensions/LineHeight.js +60 -0
  182. package/lib/extensions/StylePreset.js +168 -0
  183. package/lib/extensions/Superscript.js +5 -0
  184. package/lib/extensions/TextDecoration.js +97 -0
  185. package/lib/extensions/__tests__/Alignment.test.js +107 -0
  186. package/lib/extensions/__tests__/BackgroundColor.test.js +75 -0
  187. package/lib/extensions/__tests__/CaseStyle.test.js +58 -0
  188. package/lib/extensions/__tests__/FontColor.test.js +85 -0
  189. package/lib/extensions/__tests__/FontFamily.test.js +171 -0
  190. package/lib/extensions/__tests__/FontSize.test.js +183 -0
  191. package/lib/extensions/__tests__/FontStyle.test.js +136 -0
  192. package/lib/extensions/__tests__/FontWeight.test.js +151 -0
  193. package/lib/extensions/__tests__/LineHeight.test.js +106 -0
  194. package/lib/extensions/__tests__/StylePreset.test.js +400 -0
  195. package/lib/extensions/__tests__/TextDecoration.test.js +258 -0
  196. package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +29 -0
  197. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +28 -0
  198. package/lib/extensions/__tests__/__snapshots__/CaseStyle.test.js.snap +69 -0
  199. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +28 -0
  200. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +158 -0
  201. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +140 -0
  202. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +87 -0
  203. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +140 -0
  204. package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +29 -0
  205. package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +310 -0
  206. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +206 -0
  207. package/lib/extensions/core/NodeProcessor.js +32 -0
  208. package/lib/extensions/core/SelectionProcessor.js +37 -0
  209. package/lib/extensions/core/TextProcessor.js +57 -0
  210. package/lib/extensions/core/__tests__/NodeProcessor.test.js +120 -0
  211. package/lib/extensions/core/__tests__/SelectionProcessor.test.js +78 -0
  212. package/lib/extensions/core/__tests__/TextProcessor.test.js +61 -0
  213. package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +93 -0
  214. package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +43 -0
  215. package/lib/extensions/core/index.js +17 -0
  216. package/lib/extensions/core/inputRules/closeDoubleQuote.js +6 -0
  217. package/lib/extensions/core/inputRules/closeSingleQuote.js +6 -0
  218. package/lib/extensions/core/inputRules/copyright.js +6 -0
  219. package/lib/extensions/core/inputRules/ellipsis.js +6 -0
  220. package/lib/extensions/core/inputRules/emDash.js +6 -0
  221. package/lib/extensions/core/inputRules/index.js +9 -0
  222. package/lib/extensions/core/inputRules/openDoubleQuote.js +6 -0
  223. package/lib/extensions/core/inputRules/openSingleQuote.js +6 -0
  224. package/lib/extensions/core/inputRules/registeredTrademark.js +6 -0
  225. package/lib/extensions/core/inputRules/trademark.js +6 -0
  226. package/lib/extensions/index.js +49 -0
  227. package/lib/extensions/list/List.js +81 -0
  228. package/lib/extensions/list/ListItem.js +12 -0
  229. package/lib/extensions/list/__tests__/List.test.js +130 -0
  230. package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +212 -0
  231. package/lib/extensions/list/index.js +1 -0
  232. package/lib/index.js +1 -0
  233. package/lib/injectionTokens.js +7 -0
  234. package/lib/models/Font.js +37 -0
  235. package/lib/models/__tests__/Font.test.js +58 -0
  236. package/lib/models/index.js +1 -0
  237. package/lib/services/FavoriteColors.js +6 -0
  238. package/lib/services/JsonSerializer.js +15 -0
  239. package/lib/services/Storage.js +49 -0
  240. package/lib/services/index.js +3 -0
  241. package/lib/styles/content.css +39 -0
  242. package/lib/styles/helpers/common.css +3 -0
  243. package/lib/styles/helpers/offsets.css +3 -0
  244. package/lib/styles/helpers/text.css +6 -0
  245. package/lib/styles/main.css +5 -0
  246. package/lib/styles/variables.css +57 -0
  247. package/lib/utils/__tests__/__snapshots__/renderInlineSetting.test.js.snap +40 -0
  248. package/lib/utils/__tests__/capitalize.test.js +11 -0
  249. package/lib/utils/__tests__/renderInlineSetting.test.js +39 -0
  250. package/lib/utils/capitalize.js +3 -0
  251. package/lib/utils/createCommand.js +3 -0
  252. package/lib/utils/createKeyboardShortcut.js +6 -0
  253. package/lib/utils/index.js +4 -0
  254. package/lib/utils/renderInlineSetting.js +17 -0
  255. package/package.json +75 -0
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div class="zw-toolbar__divider" :class="classes" />
3
+ </template>
4
+
5
+ <script>
6
+ import { computed } from '@vue/composition-api';
7
+
8
+ export default {
9
+ name: 'ToolbarDivider',
10
+
11
+ props: {
12
+ vertical: {
13
+ type: Boolean,
14
+ required: false,
15
+ default: false
16
+ },
17
+
18
+ horizontal: {
19
+ type: Boolean,
20
+ required: false,
21
+ default: false
22
+ }
23
+ },
24
+
25
+ setup(props) {
26
+ const classes = computed(() => ({
27
+ 'zw-toolbar__divider--vertical': props.vertical,
28
+ 'zw-toolbar__divider--horizontal': props.horizontal
29
+ }));
30
+
31
+ return { classes };
32
+ }
33
+ };
34
+ </script>
35
+
36
+ <style scoped>
37
+ .zw-toolbar__divider {
38
+ border-color: rgba(var(--zw-color-n90), 0.1);
39
+ border-style: solid;
40
+ border-width: 0;
41
+ }
42
+
43
+ .zw-toolbar__divider--vertical {
44
+ border-left-width: 1px;
45
+ }
46
+
47
+ .zw-toolbar__divider--horizontal {
48
+ border-bottom-width: 1px;
49
+ }
50
+ </style>
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <div>
3
+ <ToolbarRow>
4
+ <StylePresetControl />
5
+ <ToolbarDivider vertical />
6
+ <FontFamilyControl />
7
+ <ToolbarDivider vertical />
8
+ <FontWeightControl />
9
+ <ToolbarDivider vertical />
10
+ <FontSizeControl />
11
+ <ToolbarDivider vertical />
12
+
13
+ <ToolbarGroup>
14
+ <FontColorControl />
15
+ <BackgroundColorControl />
16
+ </ToolbarGroup>
17
+ </ToolbarRow>
18
+
19
+ <ToolbarDivider horizontal />
20
+
21
+ <ToolbarRow>
22
+ <ToolbarGroup>
23
+ <ItalicControl />
24
+ <UnderlineControl />
25
+ <StrikeThroughControl />
26
+ <SuperscriptControl />
27
+ <CaseStyleControl />
28
+ </ToolbarGroup>
29
+
30
+ <ToolbarDivider vertical />
31
+ <AlignmentControl />
32
+ <ToolbarDivider vertical />
33
+
34
+ <ToolbarGroup>
35
+ <LineHeightControl />
36
+ <ListControl />
37
+ </ToolbarGroup>
38
+
39
+ <ToolbarDivider vertical />
40
+
41
+ <ToolbarGroup>
42
+ <RemoveFormatControl />
43
+ </ToolbarGroup>
44
+ </ToolbarRow>
45
+ </div>
46
+ </template>
47
+
48
+ <script>
49
+ import ToolbarDivider from './ToolbarDivider';
50
+ import ToolbarRow from './ToolbarRow';
51
+ import ToolbarGroup from './ToolbarGroup';
52
+ import {
53
+ StylePresetControl,
54
+ AlignmentControl,
55
+ BackgroundColorControl,
56
+ CaseStyleControl,
57
+ FontColorControl,
58
+ FontFamilyControl,
59
+ FontSizeControl,
60
+ FontWeightControl,
61
+ ItalicControl,
62
+ LineHeightControl,
63
+ StrikeThroughControl,
64
+ SuperscriptControl,
65
+ UnderlineControl,
66
+ ListControl,
67
+ RemoveFormatControl
68
+ } from './controls';
69
+
70
+ export default {
71
+ name: 'ToolbarFull',
72
+
73
+ components: {
74
+ ToolbarRow,
75
+ ToolbarGroup,
76
+ ToolbarDivider,
77
+ StylePresetControl,
78
+ CaseStyleControl,
79
+ FontFamilyControl,
80
+ FontWeightControl,
81
+ FontSizeControl,
82
+ FontColorControl,
83
+ BackgroundColorControl,
84
+ ItalicControl,
85
+ UnderlineControl,
86
+ SuperscriptControl,
87
+ StrikeThroughControl,
88
+ AlignmentControl,
89
+ LineHeightControl,
90
+ ListControl,
91
+ RemoveFormatControl
92
+ }
93
+ };
94
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div class="zw-toolbar__group">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'ToolbarGroup'
10
+ };
11
+ </script>
12
+
13
+ <style scoped>
14
+ .zw-toolbar__group {
15
+ display: flex;
16
+ column-gap: var(--zw-offset-xxs);
17
+ }
18
+ </style>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <div class="zw-toolbar__row">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'ToolbarRow'
10
+ };
11
+ </script>
12
+
13
+ <style scoped>
14
+ .zw-toolbar__row {
15
+ display: flex;
16
+ column-gap: var(--zw-offset-xs);
17
+ padding: var(--zw-offset-xxs) var(--zw-offset-xs);
18
+ }
19
+ </style>
@@ -0,0 +1,33 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import { Devices } from '../../../enums';
3
+ import Toolbar from '../Toolbar';
4
+ import ToolbarFull from '../ToolbarFull';
5
+ import ToolbarDevice from '../ToolbarDevice';
6
+
7
+ function createComponent({ device }) {
8
+ return shallowMount(Toolbar, {
9
+ propsData: {
10
+ device: device ?? Devices.DESKTOP
11
+ }
12
+ });
13
+ }
14
+
15
+ describe('rendering', () => {
16
+ test('should render desktop toolbar', () => {
17
+ const wrapper = createComponent({ device: Devices.DESKTOP });
18
+
19
+ expect(wrapper).toVueContainComponent(ToolbarFull);
20
+ });
21
+
22
+ test('should render tablet toolbar', () => {
23
+ const wrapper = createComponent({ device: Devices.TABLET });
24
+
25
+ expect(wrapper).toVueContainComponent(ToolbarDevice);
26
+ });
27
+
28
+ test('should render mobile toolbar', () => {
29
+ const wrapper = createComponent({ device: Devices.MOBILE });
30
+
31
+ expect(wrapper).toVueContainComponent(ToolbarDevice);
32
+ });
33
+ });
@@ -0,0 +1,26 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import ToolbarDivider from '../ToolbarDivider';
3
+
4
+ function createComponent({ isVertical, isHorizontal }) {
5
+ return shallowMount(ToolbarDivider, {
6
+ propsData: {
7
+ vertical: isVertical ?? false,
8
+ horizontal: isHorizontal ?? false
9
+ }
10
+ });
11
+ }
12
+
13
+ describe('rendering', () => {
14
+ test('should render vertical divider', () => {
15
+ const wrapper = createComponent({ isVertical: true });
16
+
17
+ expect(wrapper.classes('zw-toolbar__divider--vertical')).toBeTruthy();
18
+ });
19
+
20
+
21
+ test('should render vertical divider', () => {
22
+ const wrapper = createComponent({ isHorizontal: true });
23
+
24
+ expect(wrapper.classes('zw-toolbar__divider--horizontal')).toBeTruthy();
25
+ });
26
+ });
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <ButtonToggle :value="currentValue" :options="$options.alignments" @change="apply">
3
+ <template #option="{ isActive, option, activate }">
4
+ <Button
5
+ icon
6
+ skin="toolbar"
7
+ :active="isActive"
8
+ @click="activate"
9
+ v-tooltip="option.tooltip"
10
+ >
11
+ <Icon :name="`alignment-${option.id}`" size="28px" auto-color />
12
+ </Button>
13
+ </template>
14
+ </ButtonToggle>
15
+ </template>
16
+
17
+ <script>
18
+ import { inject } from '@vue/composition-api';
19
+ import { InjectionTokens } from '../../../injectionTokens';
20
+ import { Alignments } from '../../../enums';
21
+ import { ButtonToggle, Button, Icon } from '../../base';
22
+ import { tooltip } from '../../../directives';
23
+
24
+ export default {
25
+ name: 'AlignmentControl',
26
+
27
+ alignments: [
28
+ {
29
+ id: Alignments.LEFT,
30
+ tooltip: { text: 'Align Left', hotkey: 'Mod Shift L' }
31
+ },
32
+ {
33
+ id: Alignments.CENTER,
34
+ tooltip: { text: 'Align Center', hotkey: 'Mod Shift E' }
35
+ },
36
+ {
37
+ id: Alignments.RIGHT,
38
+ tooltip: { text: 'Align Right', hotkey: 'Mod Shift R' }
39
+ },
40
+ {
41
+ id: Alignments.JUSTIFY,
42
+ tooltip: { text: 'Justify', hotkey: 'Mod Shift J' }
43
+ }
44
+ ],
45
+
46
+ components: {
47
+ ButtonToggle,
48
+ Button,
49
+ Icon
50
+ },
51
+
52
+ directives: {
53
+ tooltip
54
+ },
55
+
56
+ setup(_, { emit }) {
57
+ const editor = inject(InjectionTokens.EDITOR);
58
+
59
+ const currentValue = editor.commands.getAlignment();
60
+
61
+ function apply(value) {
62
+ editor.chain().focus().applyAlignment(value).run();
63
+ emit('applied');
64
+ }
65
+
66
+ return {
67
+ currentValue,
68
+ apply
69
+ };
70
+ }
71
+ };
72
+ </script>
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <div class="zw-position--relative" ref="wrapperRef">
3
+ <Button
4
+ icon
5
+ skin="toolbar"
6
+ :active="isOpened"
7
+ @click="toggler.open"
8
+ v-tooltip="'Alignment'"
9
+ >
10
+ <Icon :name="`alignment-${currentValue}`" size="28px" auto-color />
11
+ </Button>
12
+
13
+ <Modal class="zw-alignment-control__modal" ref="modalRef" :toggler="toggler">
14
+ <AlignmentControl class="zw-alignment-control__toggle" @applied="toggler.close" />
15
+ </Modal>
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import { inject, ref } from '@vue/composition-api';
21
+ import { InjectionTokens } from '../../../injectionTokens';
22
+ import { Button, Icon, Modal, useModalToggler } from '../../base';
23
+ import { tooltip } from '../../../directives';
24
+ import AlignmentControl from './AlignmentControl';
25
+
26
+ export default {
27
+ name: 'AlignmentDeviceControl',
28
+
29
+ components: {
30
+ Button,
31
+ Icon,
32
+ Modal,
33
+ AlignmentControl
34
+ },
35
+
36
+ directives: {
37
+ tooltip
38
+ },
39
+
40
+ setup() {
41
+ const editor = inject(InjectionTokens.EDITOR);
42
+ const currentValue = editor.commands.getAlignment();
43
+ const wrapperRef = ref(null);
44
+ const modalRef = ref(null);
45
+
46
+ const toggler = useModalToggler({ wrapperRef, modalRef });
47
+
48
+ return {
49
+ wrapperRef,
50
+ modalRef,
51
+ currentValue,
52
+ toggler,
53
+ isOpened: toggler.isOpened
54
+ };
55
+ }
56
+ };
57
+ </script>
58
+
59
+ <style scoped>
60
+ .zw-alignment-control__modal {
61
+ padding: var(--zw-offset-xxs);
62
+ }
63
+
64
+ .zw-alignment-control__toggle {
65
+ flex-direction: column;
66
+ }
67
+ </style>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <ColorPicker :value="currentValue" @change="apply">
3
+ <template #activator="{ toggle, isOpened }">
4
+ <Button
5
+ icon
6
+ skin="toolbar"
7
+ :active="isOpened"
8
+ @click="toggle"
9
+ v-tooltip="'Background Color'"
10
+ >
11
+ <Icon name="background-color" size="28px" auto-color />
12
+ </Button>
13
+ </template>
14
+ </ColorPicker>
15
+ </template>
16
+
17
+ <script>
18
+ import { inject } from '@vue/composition-api';
19
+ import { ColorPicker, Button, Icon } from '../../base';
20
+ import { InjectionTokens } from '../../../injectionTokens';
21
+ import { tooltip } from '../../../directives';
22
+
23
+ export default {
24
+ name: 'BackgroundColorControl',
25
+
26
+ components: {
27
+ ColorPicker,
28
+ Button,
29
+ Icon
30
+ },
31
+
32
+ directives: {
33
+ tooltip
34
+ },
35
+
36
+ setup() {
37
+ const editor = inject(InjectionTokens.EDITOR);
38
+
39
+ const currentValue = editor.commands.getBackgroundColor();
40
+ const apply = (color) => editor.chain().applyBackgroundColor(color).run();
41
+
42
+ return {
43
+ currentValue,
44
+ apply
45
+ };
46
+ }
47
+ };
48
+ </script>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <Dropdown
3
+ :options="$options.styles"
4
+ @change="apply"
5
+ >
6
+ <template #activator="{ open, isOpened }">
7
+ <Button
8
+ icon
9
+ skin="toolbar"
10
+ :active="isOpened"
11
+ @click="open"
12
+ v-tooltip="'Case Styles'"
13
+ >
14
+ <Icon name="case-style" size="28px" auto-color />
15
+ </Button>
16
+ </template>
17
+ </Dropdown>
18
+ </template>
19
+
20
+ <script>
21
+ import { inject } from '@vue/composition-api';
22
+ import { CaseStyles } from '../../../enums';
23
+ import { Dropdown, Button, Icon } from '../../base';
24
+ import { InjectionTokens } from '../../../injectionTokens';
25
+ import { tooltip } from '../../../directives';
26
+
27
+ export default {
28
+ name: 'CaseStyleControl',
29
+
30
+ components: {
31
+ Dropdown,
32
+ Button,
33
+ Icon
34
+ },
35
+
36
+ directives: {
37
+ tooltip
38
+ },
39
+
40
+ styles: [
41
+ { id: CaseStyles.UPPERCASE, title: 'UPPERCASE' },
42
+ { id: CaseStyles.LOWERCASE, title: 'lowercase' },
43
+ { id: CaseStyles.CAPITALIZE, title: 'Capitalize' }
44
+ ],
45
+
46
+ setup() {
47
+ const editor = inject(InjectionTokens.EDITOR);
48
+
49
+ const apply = (value) => editor.chain().focus().applyCaseStyle(value).run();
50
+
51
+ return { apply };
52
+ }
53
+ };
54
+ </script>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <ColorPicker :value="currentValue" @change="apply">
3
+ <template #activator="{ toggle, isOpened }">
4
+ <Button
5
+ icon
6
+ skin="toolbar"
7
+ :active="isOpened"
8
+ @click="toggle"
9
+ v-tooltip="'Font Color'"
10
+ >
11
+ <Icon name="font-color" size="28px" auto-color />
12
+ </Button>
13
+ </template>
14
+ </ColorPicker>
15
+ </template>
16
+
17
+ <script>
18
+ import { inject } from '@vue/composition-api';
19
+ import { ColorPicker, Button, Icon } from '../../base';
20
+ import { InjectionTokens } from '../../../injectionTokens';
21
+ import { tooltip } from '../../../directives';
22
+
23
+ export default {
24
+ name: 'FontColorControl',
25
+
26
+ components: {
27
+ ColorPicker,
28
+ Button,
29
+ Icon
30
+ },
31
+
32
+ directives: {
33
+ tooltip
34
+ },
35
+
36
+ setup() {
37
+ const editor = inject(InjectionTokens.EDITOR);
38
+
39
+ const currentValue = editor.commands.getFontColor();
40
+ const apply = (color) => editor.chain().applyFontColor(color).run();
41
+
42
+ return {
43
+ currentValue,
44
+ apply
45
+ };
46
+ }
47
+ };
48
+ </script>
@@ -0,0 +1,96 @@
1
+ <template>
2
+ <Dropdown
3
+ class="zw-font-family-control"
4
+ :options="options"
5
+ :value="currentValue"
6
+ @change="apply"
7
+ v-tooltip="'Font Name'"
8
+ >
9
+ <template #option="{ option }">
10
+ <DropdownOption
11
+ class="zw-font-family-control__option"
12
+ :option="option"
13
+ :style="renderOptionStyles(option)"
14
+ v-tooltip="option.id"
15
+ />
16
+ </template>
17
+ </Dropdown>
18
+ </template>
19
+
20
+ <script>
21
+ import { computed, inject } from '@vue/composition-api';
22
+ import { InjectionTokens } from '../../../injectionTokens';
23
+ import { tooltip } from '../../../directives';
24
+ import { Dropdown, DropdownOption } from '../../base';
25
+ import { useRecentFonts } from './composables';
26
+
27
+ export default {
28
+ name: 'FontFamilyControl',
29
+
30
+ components: {
31
+ Dropdown,
32
+ DropdownOption
33
+ },
34
+
35
+ directives: {
36
+ tooltip
37
+ },
38
+
39
+ setup() {
40
+ const fonts = inject(InjectionTokens.FONTS);
41
+ const editor = inject(InjectionTokens.EDITOR);
42
+
43
+ const recentFontNames = useRecentFonts({ limit: 5 });
44
+
45
+ const recentFontsCategory = computed(() => ({
46
+ id: 'Recently Used',
47
+ options: recentFontNames.fonts.value.map((name) => ({ id: name }))
48
+ }));
49
+
50
+ const options = computed(() => {
51
+ const list = {};
52
+
53
+ for (const font of fonts) {
54
+ list[font.category] ??= { id: font.category, options: [] };
55
+ list[font.category].options.push({ id: font.name });
56
+ }
57
+
58
+ if (recentFontNames.isEmpty.value) {
59
+ return Object.values(list);
60
+ }
61
+
62
+ return [recentFontsCategory.value, ...Object.values(list)];
63
+ });
64
+
65
+ function renderOptionStyles(option) {
66
+ return { '--zw-font-family-option': `"${option.id}"` };
67
+ }
68
+
69
+ const currentValue = editor.commands.getFontFamily();
70
+
71
+ const apply = (fontFamily) => {
72
+ recentFontNames.add(fontFamily);
73
+ editor.chain().focus().applyFontFamily(fontFamily).run();
74
+ };
75
+
76
+ return {
77
+ options,
78
+ currentValue,
79
+ renderOptionStyles,
80
+ apply
81
+ };
82
+ }
83
+ };
84
+ </script>
85
+
86
+ <style scoped>
87
+ .zw-font-family-control {
88
+ width: 96px;
89
+ }
90
+
91
+ .zw-font-family-control__option {
92
+ font-weight: 400;
93
+ font-family: var(--zw-font-family-option);
94
+ width: 150px;
95
+ }
96
+ </style>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <Dropdown
3
+ :options="options"
4
+ :value="currentValue"
5
+ @change="apply"
6
+ v-tooltip="{ text: 'Font Size', hotkey: 'Mod Shift +/-' }"
7
+ />
8
+ </template>
9
+
10
+ <script>
11
+ import { computed, inject } from '@vue/composition-api';
12
+ import { Dropdown } from '../../base';
13
+ import { InjectionTokens } from '../../../injectionTokens';
14
+ import { tooltip } from '../../../directives';
15
+
16
+ export default {
17
+ name: 'FontSizeControl',
18
+
19
+ components: {
20
+ Dropdown
21
+ },
22
+
23
+ directives: {
24
+ tooltip
25
+ },
26
+
27
+ setup() {
28
+ const fontSizes = inject(InjectionTokens.FONT_SIZES);
29
+ const editor = inject(InjectionTokens.EDITOR);
30
+
31
+ const options = computed(() => {
32
+ return fontSizes.map((size) => ({ id: size, title: `${size}px` }));
33
+ });
34
+
35
+ const currentValue = editor.commands.getFontSize();
36
+ const apply = (value) => editor.chain().focus().applyFontSize(value).run();
37
+
38
+ return {
39
+ options,
40
+ currentValue,
41
+ apply
42
+ };
43
+ }
44
+ };
45
+ </script>