goodteditor-ui 1.0.61 → 1.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goodteditor-ui",
3
- "version": "1.0.61",
3
+ "version": "1.0.63",
4
4
  "main": "index.js",
5
5
  "homepage": "https://goodt-ui.netlify.app/",
6
6
  "scripts": {
@@ -51,9 +51,10 @@ import { Editor, EditorContent } from '@tiptap/vue-2';
51
51
  import { debounce } from '../utils/Helpers';
52
52
  import { resolveExtensions } from './extensions';
53
53
  import { buildToolGroups, bindContext } from './utils';
54
- import { DefaultTools, WysiwygAutofocus } from './constants';
54
+ import { DefaultTools, WysiwygAutofocus, EMPTY_PTAG_REGEXP } from './constants';
55
55
 
56
56
  /**
57
+ * @typedef {import('@tiptap/core').EditorEvents} EditorEvents
57
58
  * @typedef {Omit<import('@tiptap/extension-bubble-menu').BubbleMenuOptions, 'element'>} BubbleMenuOptions
58
59
  * @typedef {import('vue').PropOptions.<Boolean|BubbleMenuOptions>} BubbleMenuOptionsProp
59
60
  * @typedef {import('./constants').ITool} ITool
@@ -131,7 +132,8 @@ export default {
131
132
  * @return {string}
132
133
  */
133
134
  content() {
134
- return this.editor?.getHTML() ?? '';
135
+ const html = this.editor?.getHTML() ?? '';
136
+ return EMPTY_PTAG_REGEXP.test(html) ? '' : html;
135
137
  },
136
138
  /**
137
139
  * @return {{title: string, group: ITool[]}[]}
@@ -165,6 +167,16 @@ export default {
165
167
 
166
168
  this.editor.commands.setContent(value, false);
167
169
  },
170
+ editorContent() {
171
+ this.editor.setOptions({
172
+ editorProps: {
173
+ attributes: {
174
+ class: this.editorClass,
175
+ style: this.editorContent?.style ?? ''
176
+ }
177
+ }
178
+ })
179
+ }
168
180
  },
169
181
  created() {
170
182
  this.onSelectionUpdateDebounced = debounce(this.onSelectionUpdate, 300);
@@ -191,8 +203,18 @@ export default {
191
203
  },
192
204
  onUpdate: () => {
193
205
  this.onInput();
206
+ // case when the editor lost focus bc the editor menu form element (e.g. input)
207
+ // intercepted it & the editor value was updated from that element later
208
+ if (!this.editor.isFocused) {
209
+ this.onChange();
210
+ }
194
211
  },
195
212
  onBlur: () => {
213
+ const isSame = this.content === this.value;
214
+
215
+ if (isSame) {
216
+ return;
217
+ }
196
218
  this.onChange();
197
219
  },
198
220
  onSelectionUpdate: onSelectionUpdateDebounced
@@ -220,7 +242,8 @@ export default {
220
242
  this.$emit('change', this.content);
221
243
  },
222
244
  /**
223
- * @param {Transaction} transaction
245
+ * @param {EditorEvents.selectionUpdate} selectionUpdateEvent
246
+ * @param {EditorEvents.selectionUpdate.transaction} selectionUpdateEvent.transaction
224
247
  */
225
248
  onSelectionUpdate({ transaction }) {
226
249
  this.caretPosition = transaction.curSelection.to;
@@ -135,6 +135,8 @@ export type WysiwygAutofocus = Readonly<{
135
135
  DISABLED: false
136
136
  }>;
137
137
 
138
+ export const EMPTY_PTAG_REGEXP = /^<p\s*([^>]*)\s*>(\s*)<\/p\s*>$/;
139
+
138
140
  export type DefaultTools = Array<{
139
141
  title: string,
140
142
  group: Array<string|ITool>
@@ -194,6 +194,8 @@ export const WysiwygAutofocus = Object.freeze({
194
194
  DISABLED: false
195
195
  });
196
196
 
197
+ export const EMPTY_PTAG_REGEXP = /^<p\s*([^>]*)\s*>(\s*)<\/p\s*>$/;
198
+
197
199
  export const DefaultTools = [
198
200
  {
199
201
  title: 'Оформление',
@@ -11,11 +11,20 @@ import BubbleMenuToExtend from '@tiptap/extension-bubble-menu';
11
11
  */
12
12
  export const BubbleMenu = ({
13
13
  element = null,
14
- tippyOptions = { maxWidth: 'none', appendTo: () => document.body },
14
+ tippyOptions = {
15
+ maxWidth: 'none',
16
+ appendTo: () => document.body,
17
+ onClickOutside: (instance) => {
18
+ instance.hide();
19
+ },
20
+ },
15
21
  } = {}) => {
16
22
  const {
17
23
  maxWidth = 'none',
18
24
  appendTo = () => document.body,
25
+ onClickOutside = (instance) => {
26
+ instance.hide();
27
+ },
19
28
  ...restOptions
20
29
  } = tippyOptions;
21
30
 
@@ -24,6 +33,7 @@ export const BubbleMenu = ({
24
33
  tippyOptions: {
25
34
  maxWidth,
26
35
  appendTo,
36
+ onClickOutside,
27
37
  ...restOptions
28
38
  },
29
39
  });
@@ -23,6 +23,12 @@ import { useRender, RenderMixinTypes } from './mixins';
23
23
  export default {
24
24
  components: { ColorPicker, Popover },
25
25
  mixins: [useRender(), WithPopover],
26
+ props: {
27
+ appendToBody: {
28
+ type: Boolean,
29
+ default: false
30
+ }
31
+ },
26
32
  computed: {
27
33
  value() {
28
34
  return this.tool.getValue();
@@ -1,7 +1,13 @@
1
1
  <template>
2
2
  <div :title="title" class="autocomplete-tool">
3
3
  <input-autocomplete
4
- v-bind="{ value, options: tool.options, disabled: !isEnabled, size: 'small' }"
4
+ v-bind="{
5
+ value,
6
+ options: tool.options,
7
+ disabled: !isEnabled,
8
+ size: 'small',
9
+ appendToBody: false
10
+ }"
5
11
  @input="onInput" />
6
12
  </div>
7
13
  </template>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div :title="title" class="input-units-tool">
3
3
  <input-units
4
- v-bind="{ value, units, size: 'small', disabled: !isEnabled }"
4
+ v-bind="{ value, units, size: 'small', disabled: !isEnabled, appendToBody: false }"
5
5
  @change="onChange" />
6
6
  </div>
7
7
  </template>
@@ -1,7 +1,14 @@
1
1
  <template>
2
2
  <div :title="title" class="select-tool">
3
3
  <ui-select
4
- v-bind="{ value, options, valueObjects, disabled: !isEnabled, size: 'small' }"
4
+ v-bind="{
5
+ value,
6
+ options,
7
+ valueObjects,
8
+ disabled: !isEnabled,
9
+ size: 'small',
10
+ appendToBody: false
11
+ }"
5
12
  class="w-100"
6
13
  @change="onChange" />
7
14
  </div>
@@ -32,6 +32,12 @@ import { useRender, RenderMixinTypes } from './mixins';
32
32
  export default {
33
33
  components: { Popover, UiDatalist },
34
34
  mixins: [useRender(), WithPopover],
35
+ props: {
36
+ appendToBody: {
37
+ type: Boolean,
38
+ default: false
39
+ }
40
+ },
35
41
  methods: {
36
42
  ...RenderMixinTypes,
37
43
  onCommandExecuted() {