@zipify/wysiwyg 1.0.0-dev.61 → 1.0.0-dev.64
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/dist/wysiwyg.mjs +476 -452
- package/example/ExampleApp.vue +21 -2
- package/lib/Wysiwyg.vue +23 -1
- package/lib/assets/icons/background-color.svg +3 -1
- package/lib/assets/icons/font-color.svg +1 -3
- package/lib/components/toolbar/ToolbarFull.vue +31 -8
- package/lib/composables/__tests__/useEditor.test.js +2 -1
- package/lib/composables/useEditor.js +3 -1
- package/lib/extensions/index.js +1 -1
- package/lib/injectionTokens.js +2 -1
- package/package.json +1 -1
package/example/ExampleApp.vue
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
Load Content
|
|
17
17
|
</button>
|
|
18
18
|
|
|
19
|
+
<label class="zw-readonly-switcher">
|
|
20
|
+
<input type="checkbox" v-model="isReadonly">
|
|
21
|
+
readonly
|
|
22
|
+
</label>
|
|
23
|
+
|
|
19
24
|
<span>Deployed at {{ updatedAt }}</span>
|
|
20
25
|
|
|
21
26
|
<Wysiwyg
|
|
@@ -23,6 +28,7 @@
|
|
|
23
28
|
base-list-class="zpa-text__list--"
|
|
24
29
|
base-preset-class="zp ts-"
|
|
25
30
|
default-preset-id="regular-1"
|
|
31
|
+
link-preset-id="link"
|
|
26
32
|
ref="wswgRef"
|
|
27
33
|
:fonts="fonts"
|
|
28
34
|
:presets="presets"
|
|
@@ -31,7 +37,8 @@
|
|
|
31
37
|
:device="device"
|
|
32
38
|
:page-blocks="pageBlocks"
|
|
33
39
|
:active="isActive"
|
|
34
|
-
|
|
40
|
+
:readonly="isReadonly"
|
|
41
|
+
@update-favorite-colors="updateFavoriteColors"
|
|
35
42
|
/>
|
|
36
43
|
<pre class="zw-content-structure" v-html="structurePreview" />
|
|
37
44
|
</div>
|
|
@@ -71,6 +78,7 @@ export default {
|
|
|
71
78
|
const device = ref('desktop');
|
|
72
79
|
const updatedAt = new Date(ZW_UPDATED_AT).toLocaleString('ua-UA');
|
|
73
80
|
const isActive = ref(false);
|
|
81
|
+
const isReadonly = ref(false);
|
|
74
82
|
|
|
75
83
|
const structurePreview = computed(() => {
|
|
76
84
|
const json = JSON.stringify(content.value, null, ' ');
|
|
@@ -115,7 +123,8 @@ export default {
|
|
|
115
123
|
updatedAt,
|
|
116
124
|
presets,
|
|
117
125
|
isActive,
|
|
118
|
-
pageBlocks
|
|
126
|
+
pageBlocks,
|
|
127
|
+
isReadonly
|
|
119
128
|
};
|
|
120
129
|
}
|
|
121
130
|
};
|
|
@@ -141,6 +150,16 @@ body {
|
|
|
141
150
|
margin-right: 20px;
|
|
142
151
|
}
|
|
143
152
|
|
|
153
|
+
.zw-readonly-switcher {
|
|
154
|
+
margin-right: 20px;
|
|
155
|
+
display: inline-flex;
|
|
156
|
+
align-items: center;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.zw-readonly-switcher input {
|
|
160
|
+
margin-right: 5px;
|
|
161
|
+
}
|
|
162
|
+
|
|
144
163
|
.zw-content-structure {
|
|
145
164
|
background-color: #F1F1F1;
|
|
146
165
|
padding: 8px;
|
package/lib/Wysiwyg.vue
CHANGED
|
@@ -53,6 +53,11 @@ export default {
|
|
|
53
53
|
required: true
|
|
54
54
|
},
|
|
55
55
|
|
|
56
|
+
linkPresetId: {
|
|
57
|
+
type: [Number, String],
|
|
58
|
+
required: true
|
|
59
|
+
},
|
|
60
|
+
|
|
56
61
|
basePresetClass: {
|
|
57
62
|
type: String,
|
|
58
63
|
required: true
|
|
@@ -102,6 +107,19 @@ export default {
|
|
|
102
107
|
required: true
|
|
103
108
|
},
|
|
104
109
|
|
|
110
|
+
readonly: {
|
|
111
|
+
type: Boolean,
|
|
112
|
+
required: false,
|
|
113
|
+
default: false
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// Temporary until migrations static accordion to sidebar
|
|
117
|
+
popupMode: {
|
|
118
|
+
type: Boolean,
|
|
119
|
+
required: false,
|
|
120
|
+
default: false
|
|
121
|
+
},
|
|
122
|
+
|
|
105
123
|
// Requires Window type but it different in iframe and outside
|
|
106
124
|
// eslint-disable-next-line vue/require-prop-types
|
|
107
125
|
window: {
|
|
@@ -122,10 +140,11 @@ export default {
|
|
|
122
140
|
const toolbarRef = ref(null);
|
|
123
141
|
const wysiwygRef = ref(null);
|
|
124
142
|
const wrapperRef = computed(() => wysiwygRef.value?.$el || document.body);
|
|
143
|
+
const isToolbarActiveRef = computed(() => props.active && !props.readonly);
|
|
125
144
|
|
|
126
145
|
const toolbar = useToolbar({
|
|
127
146
|
wrapperRef: wysiwygRef,
|
|
128
|
-
isActiveRef:
|
|
147
|
+
isActiveRef: isToolbarActiveRef,
|
|
129
148
|
offsets: props.toolbarOffsets
|
|
130
149
|
});
|
|
131
150
|
const updateToolbar = () => toolbar.update();
|
|
@@ -140,6 +159,7 @@ export default {
|
|
|
140
159
|
const editor = useEditor({
|
|
141
160
|
content: toRef(props, 'value'),
|
|
142
161
|
onChange: (content) => onChange(content),
|
|
162
|
+
isReadonlyRef: toRef(props, 'readonly'),
|
|
143
163
|
|
|
144
164
|
extensions: buildExtensions({
|
|
145
165
|
fonts,
|
|
@@ -147,6 +167,7 @@ export default {
|
|
|
147
167
|
maxFontSize: MAX_FONT_SIZE,
|
|
148
168
|
presetsRef: toRef(props, 'presets'),
|
|
149
169
|
defaultPresetId: props.defaultPresetId,
|
|
170
|
+
linkPresetId: props.linkPresetId,
|
|
150
171
|
makePresetVariable: props.makePresetVariable,
|
|
151
172
|
basePresetClass: props.basePresetClass,
|
|
152
173
|
baseListClass: props.baseListClass,
|
|
@@ -171,6 +192,7 @@ export default {
|
|
|
171
192
|
provide(InjectionTokens.LOCAL_STORAGE, new Storage(localStorage));
|
|
172
193
|
provide(InjectionTokens.FAVORITE_COLORS, favoriteColors);
|
|
173
194
|
provide(InjectionTokens.PAGE_BLOCKS, pageBlocks);
|
|
195
|
+
provide(InjectionTokens.POPUP_MODE, props.popupMode);
|
|
174
196
|
|
|
175
197
|
return {
|
|
176
198
|
editor,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" style="width:var(--zw-icon-width);height:var(--zw-icon-height)" viewBox="0 0 28 28">
|
|
2
|
-
<path fill="
|
|
2
|
+
<path fill="#fff" stroke="#B3B3B3" d="M4.5 4.5h19v19h-19z"/>
|
|
3
|
+
<path fill="#3B3B3B" d="M26 20.7a2.51 2.51 0 0 1-5 0c0-1.31 2.5-4.7 2.5-4.7s2.5 3.39 2.5 4.7Z"/>
|
|
4
|
+
<path fill="#3B3B3B" fill-rule="evenodd" d="M19.64 19.93h-1.715a.75.75 0 0 1-.475-.145.82.82 0 0 1-.268-.359l-.89-2.433h-4.943l-.89 2.433a.78.78 0 0 1-.26.347.73.73 0 0 1-.475.157H8L12.686 8h2.269l4.686 11.93Zm-7.721-4.505h3.803l-1.452-3.968a18.048 18.048 0 0 1-.219-.623c-.08-.24-.158-.5-.235-.78-.077.28-.152.542-.227.784a8.742 8.742 0 0 1-.218.635l-1.452 3.952Z" clip-rule="evenodd"/>
|
|
3
5
|
</svg>
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" style="width:var(--zw-icon-width);height:var(--zw-icon-height)" viewBox="0 0 28 28">
|
|
2
|
-
<path fill="
|
|
3
|
-
<path fill="#3B3B3B" d="M26 20.7a2.51 2.51 0 0 1-5 0c0-1.31 2.5-4.7 2.5-4.7s2.5 3.39 2.5 4.7Z"/>
|
|
4
|
-
<path fill="#3B3B3B" fill-rule="evenodd" d="M19.64 19.93h-1.715a.75.75 0 0 1-.475-.145.82.82 0 0 1-.268-.359l-.89-2.433h-4.943l-.89 2.433a.78.78 0 0 1-.26.347.73.73 0 0 1-.475.157H8L12.686 8h2.269l4.686 11.93Zm-7.721-4.505h3.803l-1.452-3.968a18.048 18.048 0 0 1-.219-.623c-.08-.24-.158-.5-.235-.78-.077.28-.152.542-.227.784a8.742 8.742 0 0 1-.218.635l-1.452 3.952Z" clip-rule="evenodd"/>
|
|
2
|
+
<path fill="var(--zw-icon-foreground)" fill-rule="evenodd" d="M22 20.62a2.42 2.42 0 0 1-4.84 0c0-1.25 2.42-4.54 2.42-4.54S22 19.37 22 20.62ZM9.92 15.425l1.452-3.951c.071-.182.145-.394.219-.636.074-.242.149-.503.226-.783a17.223 17.223 0 0 0 .454 1.402l1.452 3.968H9.919Zm5.411 4.199c.226-.795.658-1.684 1.184-2.562L12.955 8h-2.269L6 19.93h1.725a.736.736 0 0 0 .474-.157.792.792 0 0 0 .26-.347l.891-2.434h4.941l.891 2.434c.031.079.097.134.148.198Z" clip-rule="evenodd"/>
|
|
5
3
|
</svg>
|
|
@@ -14,20 +14,35 @@
|
|
|
14
14
|
<FontColorControl />
|
|
15
15
|
<BackgroundColorControl />
|
|
16
16
|
</ToolbarGroup>
|
|
17
|
+
|
|
18
|
+
<template v-if="isPopupMode">
|
|
19
|
+
<ToolbarDivider vertical />
|
|
20
|
+
|
|
21
|
+
<ToolbarGroup>
|
|
22
|
+
<ItalicControl />
|
|
23
|
+
<UnderlineControl />
|
|
24
|
+
<StrikeThroughControl />
|
|
25
|
+
<SuperscriptControl />
|
|
26
|
+
<CaseStyleControl />
|
|
27
|
+
</ToolbarGroup>
|
|
28
|
+
</template>
|
|
17
29
|
</ToolbarRow>
|
|
18
30
|
|
|
19
31
|
<ToolbarDivider horizontal />
|
|
20
32
|
|
|
21
33
|
<ToolbarRow>
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
<template v-if="!isPopupMode">
|
|
35
|
+
<ToolbarGroup>
|
|
36
|
+
<ItalicControl />
|
|
37
|
+
<UnderlineControl />
|
|
38
|
+
<StrikeThroughControl />
|
|
39
|
+
<SuperscriptControl />
|
|
40
|
+
<CaseStyleControl />
|
|
41
|
+
</ToolbarGroup>
|
|
42
|
+
|
|
43
|
+
<ToolbarDivider vertical />
|
|
44
|
+
</template>
|
|
29
45
|
|
|
30
|
-
<ToolbarDivider vertical />
|
|
31
46
|
<AlignmentControl />
|
|
32
47
|
<ToolbarDivider vertical />
|
|
33
48
|
|
|
@@ -52,6 +67,8 @@
|
|
|
52
67
|
</template>
|
|
53
68
|
|
|
54
69
|
<script>
|
|
70
|
+
import { inject } from 'vue';
|
|
71
|
+
import { InjectionTokens } from '../../injectionTokens';
|
|
55
72
|
import ToolbarDivider from './ToolbarDivider';
|
|
56
73
|
import ToolbarRow from './ToolbarRow';
|
|
57
74
|
import ToolbarGroup from './ToolbarGroup';
|
|
@@ -97,6 +114,12 @@ export default {
|
|
|
97
114
|
ListControl,
|
|
98
115
|
RemoveFormatControl,
|
|
99
116
|
LinkControl
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
setup() {
|
|
120
|
+
const isPopupMode = inject(InjectionTokens.POPUP_MODE);
|
|
121
|
+
|
|
122
|
+
return { isPopupMode };
|
|
100
123
|
}
|
|
101
124
|
};
|
|
102
125
|
</script>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h, toRef } from 'vue';
|
|
1
|
+
import { h, ref, toRef } from 'vue';
|
|
2
2
|
import { EditorContent } from '@tiptap/vue-2';
|
|
3
3
|
import { shallowMount } from '@vue/test-utils';
|
|
4
4
|
import { useEditor } from '../useEditor';
|
|
@@ -18,6 +18,7 @@ const TestComponent = {
|
|
|
18
18
|
|
|
19
19
|
setup(props, { emit }) {
|
|
20
20
|
const editor = useEditor({
|
|
21
|
+
isReadonlyRef: ref(false),
|
|
21
22
|
content: toRef(props, 'value'),
|
|
22
23
|
extensions: buildCoreExtensions(),
|
|
23
24
|
onChange: (content) => emit('input', content),
|
|
@@ -2,7 +2,7 @@ import { Editor } from '@tiptap/vue-2';
|
|
|
2
2
|
import { onUnmounted, watch, reactive } from 'vue';
|
|
3
3
|
import { ContentNormalizer } from '../services';
|
|
4
4
|
|
|
5
|
-
export function useEditor({ content, onChange, extensions }) {
|
|
5
|
+
export function useEditor({ content, onChange, extensions, isReadonlyRef }) {
|
|
6
6
|
const editor = reactive(new Editor({
|
|
7
7
|
content: ContentNormalizer.normalize(content.value),
|
|
8
8
|
onUpdate: () => onChange(editor.getJSON()),
|
|
@@ -22,5 +22,7 @@ export function useEditor({ content, onChange, extensions }) {
|
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
watch(isReadonlyRef, (isReadonly) => editor.setEditable(!isReadonly), { immediate: true });
|
|
26
|
+
|
|
25
27
|
return editor;
|
|
26
28
|
}
|
package/lib/extensions/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { buildCoreExtensions } from './core';
|
|
|
18
18
|
export function buildExtensions(options) {
|
|
19
19
|
const getPresetById = (id) => options.presetsRef.value.find((preset) => preset.id === id);
|
|
20
20
|
const defaultPreset = getPresetById(options.defaultPresetId);
|
|
21
|
-
const linkPreset = getPresetById(
|
|
21
|
+
const linkPreset = getPresetById(options.linkPresetId);
|
|
22
22
|
|
|
23
23
|
return buildCoreExtensions(options).concat([
|
|
24
24
|
StylePreset.configure({
|
package/lib/injectionTokens.js
CHANGED
|
@@ -4,5 +4,6 @@ export const InjectionTokens = Object.freeze({
|
|
|
4
4
|
EDITOR: Symbol('editor'),
|
|
5
5
|
LOCAL_STORAGE: Symbol('localStorage'),
|
|
6
6
|
FAVORITE_COLORS: Symbol('favoriteColors'),
|
|
7
|
-
PAGE_BLOCKS: Symbol('pageBlocks')
|
|
7
|
+
PAGE_BLOCKS: Symbol('pageBlocks'),
|
|
8
|
+
POPUP_MODE: Symbol('popupMode')
|
|
8
9
|
});
|