@zipify/wysiwyg 3.1.0-0 → 3.1.0-2

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 (32) hide show
  1. package/config/build/cli.config.js +1 -1
  2. package/config/build/lib.config.js +1 -1
  3. package/dist/cli.js +3 -3
  4. package/dist/wysiwyg.css +25 -22
  5. package/dist/wysiwyg.mjs +1337 -1302
  6. package/example/ExampleApp.vue +1 -1
  7. package/example/presets.js +7 -7
  8. package/example/tooltip/Tooltip.js +3 -1
  9. package/example/tooltip/modifiers/TooltipCloseOnScrollModifier.js +5 -2
  10. package/lib/__tests__/utils/buildTestExtensions.js +24 -2
  11. package/lib/components/base/composables/useModalToggler.js +4 -1
  12. package/lib/components/base/dropdown/DropdownActivator.vue +4 -0
  13. package/lib/components/toolbar/controls/StylePresetControl.vue +1 -1
  14. package/lib/{entry-cli.js → entryCli.js} +0 -0
  15. package/lib/{entry-lib.js → entryLib.js} +0 -0
  16. package/lib/extensions/Alignment.js +6 -6
  17. package/lib/extensions/StylePreset.js +8 -46
  18. package/lib/extensions/__tests__/Alignment.test.js +1 -1
  19. package/lib/extensions/__tests__/StylePreset.test.js +90 -119
  20. package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +2 -2
  21. package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +0 -2
  22. package/lib/extensions/core/NodeProcessor.js +6 -2
  23. package/lib/extensions/index.js +7 -3
  24. package/lib/extensions/list/__tests__/List.test.js +6 -1
  25. package/lib/services/ContentSerializer.js +1 -1
  26. package/lib/services/{ContextWidnow.js → ContextWindow.js} +0 -0
  27. package/lib/services/StylePresetRenderer.js +73 -0
  28. package/lib/services/__tests__/StylePresetRenderer.test.js +98 -0
  29. package/lib/services/__tests__/__snapshots__/StylePresetRenderer.test.js.snap +5 -0
  30. package/lib/services/index.js +2 -1
  31. package/lib/styles/content.css +10 -10
  32. package/package.json +4 -4
@@ -50,7 +50,7 @@
50
50
 
51
51
  <script>
52
52
  import { computed, onMounted, ref, unref } from 'vue';
53
- import { Wysiwyg } from '../lib/entry-lib';
53
+ import { Wysiwyg } from '../lib/entryLib';
54
54
  import { FONTS } from './fonts';
55
55
  import { PRESETS, renderPresetVariable } from './presets';
56
56
  import { PAGE_BLOCKS } from './pageBlocks';
@@ -1,7 +1,7 @@
1
1
  export const PRESETS = [
2
2
  {
3
3
  'id': 'h1',
4
- 'name': 'H1',
4
+ 'name': 'Heading 1',
5
5
  'node': {
6
6
  'type': 'heading',
7
7
  'level': 1
@@ -31,7 +31,7 @@ export const PRESETS = [
31
31
  },
32
32
  {
33
33
  'id': 'h2',
34
- 'name': 'H2',
34
+ 'name': 'Heading 2',
35
35
  'node': {
36
36
  'type': 'heading',
37
37
  'level': 2
@@ -61,7 +61,7 @@ export const PRESETS = [
61
61
  },
62
62
  {
63
63
  'id': 'h3',
64
- 'name': 'H3',
64
+ 'name': 'Sub-heading 1',
65
65
  'node': {
66
66
  'type': 'heading',
67
67
  'level': 3
@@ -91,7 +91,7 @@ export const PRESETS = [
91
91
  },
92
92
  {
93
93
  'id': 'h4',
94
- 'name': 'H4',
94
+ 'name': 'Sub-heading 2',
95
95
  'node': {
96
96
  'type': 'heading',
97
97
  'level': 4
@@ -148,7 +148,7 @@ export const PRESETS = [
148
148
  },
149
149
  {
150
150
  'id': 'regular-1',
151
- 'name': 'Regular',
151
+ 'name': 'Body Copy 1',
152
152
  'desktop': {
153
153
  'alignment': null,
154
154
  'line_height': '1.43',
@@ -174,7 +174,7 @@ export const PRESETS = [
174
174
  },
175
175
  {
176
176
  'id': 'regular-2',
177
- 'name': 'Regular 2',
177
+ 'name': 'Body Copy 2',
178
178
  'fallbackClass': 'zpa-regular2',
179
179
  'desktop': {
180
180
  'alignment': null,
@@ -201,7 +201,7 @@ export const PRESETS = [
201
201
  },
202
202
  {
203
203
  'id': 'regular-3',
204
- 'name': 'Regular 3',
204
+ 'name': 'Body Copy 3',
205
205
  'fallbackClass': 'zpa-regular3',
206
206
  'desktop': {
207
207
  'alignment': null,
@@ -1,6 +1,7 @@
1
1
  import './tooltip.css';
2
2
 
3
3
  import { arrow, autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom';
4
+ import { TooltipCloseOnScrollModifier } from './modifiers';
4
5
 
5
6
  export class Tooltip {
6
7
  static get defaultOptions() {
@@ -133,7 +134,8 @@ export class Tooltip {
133
134
  flip(),
134
135
  offset({ mainAxis: 8 }),
135
136
  shift({ padding: 4 }),
136
- arrow({ element: this.elements.arrow })
137
+ arrow({ element: this.elements.arrow }),
138
+ TooltipCloseOnScrollModifier.init({ tooltip: this })
137
139
  ];
138
140
  }
139
141
 
@@ -21,7 +21,7 @@ export class TooltipCloseOnScrollModifier {
21
21
  /**
22
22
  * @param {Tooltip} tooltip - tooltip element
23
23
  *
24
- * @return {Partial<Modifier<any, any>>} - Popper modifier
24
+ * @return {Partial<Modifier<any, any>>} - Floating modifier
25
25
  * */
26
26
  static init({ tooltip }) {
27
27
  const modifier = new TooltipCloseOnScrollModifier(tooltip);
@@ -30,7 +30,10 @@ export class TooltipCloseOnScrollModifier {
30
30
  name: 'closeOnScroll',
31
31
  enabled: true,
32
32
  phase: 'main',
33
- fn: () => modifier.closeOnScroll()
33
+ fn: ({ x, y }) => {
34
+ modifier.closeOnScroll();
35
+ return { x, y };
36
+ }
34
37
  };
35
38
  }
36
39
 
@@ -1,6 +1,6 @@
1
1
  import { Mark } from '@tiptap/vue-2';
2
2
  import { buildCoreExtensions } from '../../extensions/core';
3
- import { MarkGroups } from '../../enums';
3
+ import { MarkGroups, TextSettings } from '../../enums';
4
4
 
5
5
  // each node allows using 'settings' group of marks,
6
6
  // and it fails when there are no nodes with this group
@@ -10,6 +10,28 @@ const SettingMark = Mark.create({
10
10
  renderHTML: () => []
11
11
  });
12
12
 
13
+ // NodeProcessor requires link mark
14
+ const LinkMark = Mark.create({
15
+ name: TextSettings.LINK,
16
+ renderHTML: () => []
17
+ });
18
+
19
+ const isMark = (extension) => extension && extension.type === 'mark';
20
+
13
21
  export function buildTestExtensions({ include } = {}) {
14
- return buildCoreExtensions().concat(SettingMark, include || []);
22
+ const extensions = buildCoreExtensions().concat(include || []);
23
+
24
+ const isSettingPreset = extensions.some((extension) => {
25
+ return isMark(extension) && extension.config.group === MarkGroups.SETTINGS;
26
+ });
27
+
28
+ if (!isSettingPreset) extensions.push(SettingMark);
29
+
30
+ const isLinkPreset = extensions.some((extension) => {
31
+ return isMark(extension) && extension.name === TextSettings.LINK;
32
+ });
33
+
34
+ if (!isLinkPreset) extensions.push(LinkMark);
35
+
36
+ return extensions;
15
37
  }
@@ -18,7 +18,8 @@ export function useModalToggler({ onBeforeOpened, onClosed, wrapperRef, modalRef
18
18
  strategy: 'fixed',
19
19
  middleware: [
20
20
  shift({ padding: 16, crossAxis: true, limiter: limitShift() }),
21
- offset({ mainAxis: 4 })]
21
+ offset({ mainAxis: 4 })
22
+ ]
22
23
  });
23
24
 
24
25
  const { x, y } = positioning;
@@ -31,6 +32,8 @@ export function useModalToggler({ onBeforeOpened, onClosed, wrapperRef, modalRef
31
32
  }
32
33
 
33
34
  async function open() {
35
+ if (isOpened.value) return;
36
+
34
37
  onBeforeOpened?.();
35
38
  editor.commands.storeSelection();
36
39
  isOpened.value = true;
@@ -82,6 +82,10 @@ export default {
82
82
  width: 100%;
83
83
  }
84
84
 
85
+ .zw-dropdown__activator-title {
86
+ margin-right: var(--zw-offset-xxs);
87
+ }
88
+
85
89
  .zw-dropdown__activator-arrow {
86
90
  margin-left: auto;
87
91
  }
@@ -96,7 +96,7 @@ export default {
96
96
  }
97
97
 
98
98
  .zw-style-preset-control__dropdown {
99
- width: 96px;
99
+ width: 120px;
100
100
  }
101
101
 
102
102
  .zw-style-preset-control__reset {
File without changes
File without changes
@@ -26,9 +26,9 @@ export const Alignment = Extension.create({
26
26
  return { desktop: textAlign, tablet: textAlign, mobile: textAlign };
27
27
  }
28
28
 
29
- const mobile = style.getPropertyValue('--zw-text-align-mobile') || null;
30
- const tablet = style.getPropertyValue('--zw-text-align-tablet') || null;
31
- const desktop = style.getPropertyValue('--zw-text-align-desktop') || null;
29
+ const mobile = style.getPropertyValue('--zw-alignment-mobile') || null;
30
+ const tablet = style.getPropertyValue('--zw-alignment-tablet') || null;
31
+ const desktop = style.getPropertyValue('--zw-alignment-desktop') || null;
32
32
 
33
33
  if (!mobile && !tablet && !desktop) return null;
34
34
 
@@ -39,9 +39,9 @@ export const Alignment = Extension.create({
39
39
  if (!attrs.alignment) return null;
40
40
 
41
41
  return renderInlineSetting({
42
- text_align_mobile: attrs.alignment.mobile,
43
- text_align_tablet: attrs.alignment.tablet,
44
- text_align_desktop: attrs.alignment.desktop
42
+ alignment_mobile: attrs.alignment.mobile,
43
+ alignment_tablet: attrs.alignment.tablet,
44
+ alignment_desktop: attrs.alignment.desktop
45
45
  });
46
46
  }
47
47
  }
@@ -1,22 +1,12 @@
1
1
  import { Extension } from '@tiptap/vue-2';
2
2
  import { computed, toRef, unref } from 'vue';
3
3
  import { createCommand } from '../utils';
4
- import { Devices, NodeTypes, TextSettings } from '../enums';
4
+ import { NodeTypes, TextSettings } from '../enums';
5
5
  import { ContextWindow } from '../services';
6
6
 
7
- function makePresetClass(base, preset) {
8
- const baseClass = base.split(' ').map((part) => `.${part}`).join('');
9
-
10
- return baseClass + preset.id;
11
- }
12
-
13
7
  export const StylePreset = Extension.create({
14
8
  name: TextSettings.STYLE_PRESET,
15
9
 
16
- addStorage: () => ({
17
- presetStyleEl: null
18
- }),
19
-
20
10
  addGlobalAttributes() {
21
11
  return [
22
12
  {
@@ -32,13 +22,13 @@ export const StylePreset = Extension.create({
32
22
  if (element.parentElement.tagName === 'LI') return null;
33
23
 
34
24
  for (const { id, node, fallbackClass } of presets) {
35
- const isFallback = fallbackClass && element.classList.contains(fallbackClass);
36
-
37
- if (isFallback) return { id };
25
+ if (fallbackClass && element.classList.contains(fallbackClass)) {
26
+ return { id };
27
+ }
38
28
 
39
- const className = makePresetClass(this.options.baseClass, { id });
29
+ const presetSelector = this.options.styleRenderer.makePresetCssClass({ id });
40
30
 
41
- if (element.matches(className)) return { id };
31
+ if (element.matches(presetSelector)) return { id };
42
32
  if (element.tagName === `H${node?.level}`) return { id };
43
33
  }
44
34
 
@@ -49,7 +39,7 @@ export const StylePreset = Extension.create({
49
39
  renderHTML: (attrs) => {
50
40
  if (!attrs.preset) return null;
51
41
 
52
- return { class: this.options.baseClass + attrs.preset.id };
42
+ return { class: this.options.styleRenderer.makePresetHtmlClass(attrs.preset) };
53
43
  }
54
44
  }
55
45
  }
@@ -208,34 +198,6 @@ export const StylePreset = Extension.create({
208
198
  },
209
199
 
210
200
  onCreate() {
211
- const existingStyleEl = ContextWindow.document.querySelector('[data-zw-styles]');
212
-
213
- if (existingStyleEl) {
214
- this.storage.presetStyleEl = existingStyleEl;
215
- return;
216
- }
217
-
218
- this.storage.presetStyleEl = ContextWindow.document.createElement('style');
219
- this.storage.presetStyleEl.dataset.zwStyles = '';
220
-
221
- for (const preset of this.options.presets) {
222
- const className = makePresetClass(this.options.baseClass, preset);
223
- const css = [` ${className} {`];
224
-
225
- for (const device of Devices.values) {
226
- for (const setting of Object.keys(preset[device])) {
227
- const variable = this.options.makeVariable({ device, preset, property: setting });
228
- const property = setting.replace(/_/i, '-');
229
- const prefix = device === Devices.COMMON ? 'preset' : `preset-${device}`;
230
-
231
- css.push(`--zw-${prefix}-${property}: var(${variable}, inherit);`);
232
- }
233
- }
234
-
235
- css.push('}');
236
- this.storage.presetStyleEl.innerHTML += css.join(' ');
237
- }
238
-
239
- ContextWindow.head.append(this.storage.presetStyleEl);
201
+ this.options.styleRenderer.inject(ContextWindow.head, this.options.presets);
240
202
  }
241
203
  });
@@ -144,7 +144,7 @@ describe('parsing html', () => {
144
144
 
145
145
  test('should get alignment from rendered view', () => {
146
146
  const editor = createEditor({
147
- content: '<p style="--zw-text-align-mobile:center;--zw-text-align-desktop:right">test</p>'
147
+ content: '<p style="--zw-alignment-mobile:center;--zw-alignment-desktop:right">test</p>'
148
148
  });
149
149
 
150
150
  expect(editor.getJSON()).toMatchSnapshot();