@zipify/wysiwyg 4.1.0-0 → 4.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.
- package/config/build/settings.js +1 -1
- package/config/jest/setupTests.js +3 -0
- package/dist/cli.js +2 -3
- package/dist/wysiwyg.css +37 -37
- package/dist/wysiwyg.mjs +920 -846
- package/example/ai-component/AiComponent.vue +16 -50
- package/lib/Wysiwyg.vue +9 -17
- package/lib/components/base/Modal.vue +19 -18
- package/lib/components/base/ModalFloating.vue +32 -0
- package/lib/components/base/__tests__/Modal.test.js +2 -19
- package/lib/components/base/composables/useModalToggler.js +3 -34
- package/lib/components/base/dropdown/Dropdown.vue +7 -6
- package/lib/components/base/dropdown/DropdownActivator.vue +4 -5
- package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +1 -1
- package/lib/components/base/dropdown/__tests__/DropdownOption.test.js +1 -1
- package/lib/components/toolbar/Toolbar.vue +29 -13
- package/lib/components/toolbar/ToolbarFloating.vue +42 -0
- package/lib/components/toolbar/__tests__/Toolbar.test.js +4 -6
- package/lib/components/toolbar/controls/LineHeightControl.vue +9 -7
- package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +2 -4
- package/lib/components/toolbar/controls/link/LinkControl.vue +13 -14
- package/lib/components/toolbar/controls/link/destination/LinkControlDestination.vue +1 -1
- package/lib/components/toolbar/controls/link/destination/LinkControlPageBlock.vue +1 -1
- package/lib/composables/__tests__/useEditor.test.js +26 -5
- package/lib/composables/index.js +0 -1
- package/lib/composables/useEditor.js +7 -2
- package/lib/styles/content.css +0 -1
- package/package.json +50 -51
- package/lib/components/base/composables/__tests__/useModalToggler.test.js +0 -59
- package/lib/composables/useToolbar.js +0 -36
- /package/config/build/{example.config.js → example.config.mjs} +0 -0
- /package/config/build/{lib.config.js → lib.config.mjs} +0 -0
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
<Icon name="link" size="28px" auto-color />
|
|
5
5
|
</Button>
|
|
6
6
|
|
|
7
|
-
<Modal
|
|
7
|
+
<Modal
|
|
8
|
+
class="zw-link-modal"
|
|
9
|
+
:toggler="toggler"
|
|
10
|
+
:reference-ref="wrapperRef"
|
|
11
|
+
focus-first-control
|
|
12
|
+
>
|
|
8
13
|
<LinkControlHeader @remove-link="removeLink" />
|
|
9
14
|
|
|
10
15
|
<form class="zw-link-modal__body" @submit.prevent="applyLink" data-test-selector="form">
|
|
@@ -50,11 +55,9 @@ import LinkControlHeader from './LinkControlHeader';
|
|
|
50
55
|
import { useLink } from './composables';
|
|
51
56
|
import { LinkControlDestination } from './destination';
|
|
52
57
|
|
|
53
|
-
const wrapperRef = ref(null);
|
|
54
|
-
const modalRef = ref(null);
|
|
55
|
-
|
|
56
58
|
const editor = inject(InjectionTokens.EDITOR);
|
|
57
59
|
|
|
60
|
+
const wrapperRef = ref(null);
|
|
58
61
|
const link = useLink();
|
|
59
62
|
|
|
60
63
|
const isEmpty = () => {
|
|
@@ -88,20 +91,16 @@ const resetErrors = () => {
|
|
|
88
91
|
urlValidator.reset();
|
|
89
92
|
};
|
|
90
93
|
|
|
91
|
-
const onBeforeOpened = () => {
|
|
92
|
-
editor.commands.extendMarkRange(TextSettings.LINK);
|
|
93
|
-
resetErrors();
|
|
94
|
-
link.prepareInitialFields();
|
|
95
|
-
};
|
|
96
|
-
|
|
97
94
|
const toggler = useModalToggler({
|
|
98
|
-
onBeforeOpened: () =>
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
onBeforeOpened: () => {
|
|
96
|
+
editor.commands.extendMarkRange(TextSettings.LINK);
|
|
97
|
+
resetErrors();
|
|
98
|
+
link.prepareInitialFields();
|
|
99
|
+
}
|
|
101
100
|
});
|
|
102
101
|
|
|
103
102
|
const isLink = editor.commands.isLink();
|
|
104
|
-
const isActive = computed(() =>
|
|
103
|
+
const isActive = computed(() => toggler.isOpened || unref(isLink));
|
|
105
104
|
|
|
106
105
|
const updateLinkText = (value) => {
|
|
107
106
|
resetErrors();
|
|
@@ -61,7 +61,7 @@ const emit = defineEmits(['reset-errors']);
|
|
|
61
61
|
|
|
62
62
|
const destinationTypes = [
|
|
63
63
|
{ id: LinkDestinations.URL, title: 'URL' },
|
|
64
|
-
{ id: LinkDestinations.BLOCK, title: 'Page
|
|
64
|
+
{ id: LinkDestinations.BLOCK, title: 'Page Section' }
|
|
65
65
|
];
|
|
66
66
|
|
|
67
67
|
const link = toRef(props, 'link');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h,
|
|
1
|
+
import { h, toRef } from 'vue';
|
|
2
2
|
import { EditorContent } from '@tiptap/vue-3';
|
|
3
3
|
import { shallowMount } from '@vue/test-utils';
|
|
4
4
|
import { buildTestExtensions } from '../../__tests__/utils';
|
|
@@ -14,11 +14,11 @@ const TestComponent = {
|
|
|
14
14
|
});
|
|
15
15
|
},
|
|
16
16
|
|
|
17
|
-
props: ['value'],
|
|
17
|
+
props: ['value', 'readonly'],
|
|
18
18
|
|
|
19
19
|
setup(props, { emit }) {
|
|
20
20
|
const { editor } = useEditor({
|
|
21
|
-
isReadonlyRef:
|
|
21
|
+
isReadonlyRef: toRef(props, 'readonly'),
|
|
22
22
|
content: toRef(props, 'value'),
|
|
23
23
|
extensions: buildTestExtensions(),
|
|
24
24
|
onChange: (content) => emit('input', content),
|
|
@@ -33,9 +33,12 @@ const createContent = (text = 'test') => NodeFactory.doc([
|
|
|
33
33
|
NodeFactory.paragraph(text)
|
|
34
34
|
]);
|
|
35
35
|
|
|
36
|
-
function createComponent({ content } = {}) {
|
|
36
|
+
function createComponent({ content, isReadonly } = {}) {
|
|
37
37
|
const wrapper = shallowMount(TestComponent, {
|
|
38
|
-
props: {
|
|
38
|
+
props: {
|
|
39
|
+
value: content || createContent('test'),
|
|
40
|
+
readonly: isReadonly ?? false
|
|
41
|
+
}
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
return {
|
|
@@ -75,3 +78,21 @@ describe('life cycle', () => {
|
|
|
75
78
|
expect(editor.getHTML()).toBe('<p class="zw-style">new</p>');
|
|
76
79
|
});
|
|
77
80
|
});
|
|
81
|
+
|
|
82
|
+
describe('readonly', () => {
|
|
83
|
+
test('should change readonly', async () => {
|
|
84
|
+
const { wrapper, editor } = createComponent({ isReadonly: false });
|
|
85
|
+
|
|
86
|
+
await wrapper.setProps({ readonly: true });
|
|
87
|
+
|
|
88
|
+
expect(editor.isEditable).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('should not emit change on readonly update', async () => {
|
|
92
|
+
const { wrapper, editor } = createComponent({ isReadonly: false });
|
|
93
|
+
|
|
94
|
+
await wrapper.setProps({ readonly: true });
|
|
95
|
+
|
|
96
|
+
expect(wrapper.emitted('input')).toBeFalsy();
|
|
97
|
+
});
|
|
98
|
+
});
|
package/lib/composables/index.js
CHANGED
|
@@ -13,7 +13,12 @@ export function useEditor({ content, onChange, extensions, isReadonlyRef }) {
|
|
|
13
13
|
onUpdate: () => onChange(getContent()),
|
|
14
14
|
extensions,
|
|
15
15
|
injectCSS: false,
|
|
16
|
-
editable: !unref(isReadonlyRef)
|
|
16
|
+
editable: !unref(isReadonlyRef),
|
|
17
|
+
editorProps: {
|
|
18
|
+
attributes: {
|
|
19
|
+
class: 'zw-wysiwyg__content'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
17
22
|
}));
|
|
18
23
|
|
|
19
24
|
onUnmounted(() => editor.destroy());
|
|
@@ -26,7 +31,7 @@ export function useEditor({ content, onChange, extensions, isReadonlyRef }) {
|
|
|
26
31
|
}
|
|
27
32
|
});
|
|
28
33
|
|
|
29
|
-
watch(isReadonlyRef, (isReadonly) => editor.setEditable(!isReadonly));
|
|
34
|
+
watch(isReadonlyRef, (isReadonly) => editor.setEditable(!isReadonly, false));
|
|
30
35
|
|
|
31
36
|
return { editor, getContent };
|
|
32
37
|
}
|
package/lib/styles/content.css
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zipify/wysiwyg",
|
|
3
|
-
"version": "4.1.0-
|
|
3
|
+
"version": "4.1.0-2",
|
|
4
4
|
"description": "Zipify modification of TipTap text editor",
|
|
5
5
|
"main": "dist/wysiwyg.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"url": "https://github.com/ZipifyApps/ZipifyWysiwyg/issues"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
|
-
"lib:build": "vite build --config config/build/lib.config.
|
|
21
|
-
"lib:release": "export $(cat
|
|
20
|
+
"lib:build": "vite build --config config/build/lib.config.mjs",
|
|
21
|
+
"lib:release": "[ -f .env ] && export $(cat .env | xargs) && release-it",
|
|
22
22
|
"cli:build": "NODE_ENV=production rollup --config config/build/cli.config.js --bundleConfigAsCjs",
|
|
23
23
|
"cli:dev": "NODE_ENV=development rollup --config config/build/cli.config.js --bundleConfigAsCjs --watch",
|
|
24
|
-
"example:start": "NODE_ENV=development vite serve --config config/build/example.config.
|
|
25
|
-
"example:build": "NODE_ENV=production vite build --config config/build/example.config.
|
|
24
|
+
"example:start": "NODE_ENV=development vite serve --config config/build/example.config.mjs",
|
|
25
|
+
"example:build": "NODE_ENV=production vite build --config config/build/example.config.mjs",
|
|
26
26
|
"test:unit": "jest .",
|
|
27
27
|
"lint:js": "eslint ./lib",
|
|
28
28
|
"lint:css": "stylelint ./lib/**/*.{css,vue}",
|
|
@@ -30,25 +30,24 @@
|
|
|
30
30
|
"prepare": "husky install"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@floating-ui/
|
|
34
|
-
"@
|
|
35
|
-
"@tiptap/
|
|
36
|
-
"@tiptap/extension-
|
|
37
|
-
"@tiptap/extension-
|
|
38
|
-
"@tiptap/extension-
|
|
39
|
-
"@tiptap/extension-
|
|
40
|
-
"@tiptap/extension-
|
|
41
|
-
"@tiptap/extension-
|
|
42
|
-
"@tiptap/
|
|
43
|
-
"@tiptap/
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"jsdom": "^21.1.1",
|
|
33
|
+
"@floating-ui/vue": "^1.0.2",
|
|
34
|
+
"@tiptap/core": "^2.1.13",
|
|
35
|
+
"@tiptap/extension-document": "^2.1.13",
|
|
36
|
+
"@tiptap/extension-heading": "^2.1.13",
|
|
37
|
+
"@tiptap/extension-history": "^2.1.13",
|
|
38
|
+
"@tiptap/extension-link": "^2.1.13",
|
|
39
|
+
"@tiptap/extension-list-item": "^2.1.13",
|
|
40
|
+
"@tiptap/extension-paragraph": "^2.1.13",
|
|
41
|
+
"@tiptap/extension-text": "^2.1.13",
|
|
42
|
+
"@tiptap/pm": "^2.1.13",
|
|
43
|
+
"@tiptap/vue-3": "^2.1.13",
|
|
44
|
+
"commander": "^11.1.0",
|
|
45
|
+
"jsdom": "^23.0.1",
|
|
47
46
|
"lodash": "^4.17.21",
|
|
48
|
-
"simplebar": "^6.2.
|
|
47
|
+
"simplebar": "^6.2.5"
|
|
49
48
|
},
|
|
50
49
|
"peerDependencies": {
|
|
51
|
-
"@zipify/colorpicker": "^3.
|
|
50
|
+
"@zipify/colorpicker": "^3.1",
|
|
52
51
|
"vue": "^3.2"
|
|
53
52
|
},
|
|
54
53
|
"peerDependenciesMeta": {
|
|
@@ -60,39 +59,39 @@
|
|
|
60
59
|
}
|
|
61
60
|
},
|
|
62
61
|
"devDependencies": {
|
|
63
|
-
"@babel/core": "^7.
|
|
64
|
-
"@babel/eslint-parser": "^7.
|
|
65
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
66
|
-
"@babel/preset-env": "^7.
|
|
67
|
-
"@babel/runtime": "^7.
|
|
68
|
-
"@optimize-lodash/rollup-plugin": "^4.0.
|
|
69
|
-
"@rollup/plugin-babel": "^6.0.
|
|
70
|
-
"@rollup/plugin-commonjs": "^
|
|
71
|
-
"@rollup/plugin-json": "^6.0.
|
|
72
|
-
"@rollup/plugin-node-resolve": "^15.
|
|
73
|
-
"@rollup/plugin-replace": "^5.0.
|
|
74
|
-
"@rollup/plugin-terser": "^0.4.
|
|
75
|
-
"@vitejs/plugin-vue": "^4.2
|
|
76
|
-
"@vue/test-utils": "^2.3
|
|
77
|
-
"@vue/vue3-jest": "^29.2.
|
|
78
|
-
"@zipify/colorpicker": "^3.
|
|
79
|
-
"@zipify/eslint-config": "^1.
|
|
80
|
-
"babel-jest": "^29.
|
|
81
|
-
"eslint": "8.
|
|
82
|
-
"eslint-plugin-import": "^2.
|
|
83
|
-
"eslint-plugin-jest": "^27.
|
|
84
|
-
"eslint-plugin-vue": "^9.
|
|
62
|
+
"@babel/core": "^7.23.5",
|
|
63
|
+
"@babel/eslint-parser": "^7.23.3",
|
|
64
|
+
"@babel/plugin-transform-runtime": "^7.23.4",
|
|
65
|
+
"@babel/preset-env": "^7.23.5",
|
|
66
|
+
"@babel/runtime": "^7.23.5",
|
|
67
|
+
"@optimize-lodash/rollup-plugin": "^4.0.4",
|
|
68
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
69
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
70
|
+
"@rollup/plugin-json": "^6.0.1",
|
|
71
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
72
|
+
"@rollup/plugin-replace": "^5.0.5",
|
|
73
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
74
|
+
"@vitejs/plugin-vue": "^4.5.2",
|
|
75
|
+
"@vue/test-utils": "^2.4.3",
|
|
76
|
+
"@vue/vue3-jest": "^29.2.6",
|
|
77
|
+
"@zipify/colorpicker": "^3.1.0",
|
|
78
|
+
"@zipify/eslint-config": "^1.4.1",
|
|
79
|
+
"babel-jest": "^29.7.0",
|
|
80
|
+
"eslint": "^8.55.0",
|
|
81
|
+
"eslint-plugin-import": "^2.29.0",
|
|
82
|
+
"eslint-plugin-jest": "^27.6.0",
|
|
83
|
+
"eslint-plugin-vue": "^9.19.2",
|
|
85
84
|
"husky": "^8.0.3",
|
|
86
|
-
"jest": "^29.
|
|
87
|
-
"jest-environment-jsdom": "^29.
|
|
88
|
-
"lint-staged": "^
|
|
85
|
+
"jest": "^29.7.0",
|
|
86
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
87
|
+
"lint-staged": "^15.2.0",
|
|
89
88
|
"postcss-html": "^1.5.0",
|
|
90
|
-
"release-it": "^
|
|
91
|
-
"rollup": "^
|
|
89
|
+
"release-it": "^17.0.0",
|
|
90
|
+
"rollup": "^4.6.1",
|
|
92
91
|
"stylelint": "^14.16.1",
|
|
93
|
-
"svgo": "^3.0.
|
|
94
|
-
"vite": "^
|
|
95
|
-
"vue": "3.3.
|
|
92
|
+
"svgo": "^3.0.5",
|
|
93
|
+
"vite": "^5.0.6",
|
|
94
|
+
"vue": "3.3.10"
|
|
96
95
|
},
|
|
97
96
|
"engines": {
|
|
98
97
|
"node": ">=18.12.0"
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { ref } from 'vue';
|
|
2
|
-
import { withComponentContext } from '../../../../__tests__/utils';
|
|
3
|
-
import { InjectionTokens } from '../../../../injectionTokens';
|
|
4
|
-
import { useModalToggler } from '../useModalToggler';
|
|
5
|
-
import { useElementRef } from '../useElementRef';
|
|
6
|
-
|
|
7
|
-
jest.mock('@floating-ui/dom');
|
|
8
|
-
|
|
9
|
-
const createEditor = () => ({
|
|
10
|
-
commands: {
|
|
11
|
-
storeSelection: jest.fn(),
|
|
12
|
-
restoreSelection: jest.fn()
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const el = document.createElement('div');
|
|
17
|
-
const elementRef = useElementRef(ref(el));
|
|
18
|
-
|
|
19
|
-
function createWrapper() {
|
|
20
|
-
return withComponentContext(() => {
|
|
21
|
-
return useModalToggler({
|
|
22
|
-
onClosed: jest.fn(),
|
|
23
|
-
onBeforeOpened: jest.fn(),
|
|
24
|
-
wrapperRef: elementRef,
|
|
25
|
-
modalRef: elementRef
|
|
26
|
-
});
|
|
27
|
-
}, {
|
|
28
|
-
global: {
|
|
29
|
-
provide: { [InjectionTokens.EDITOR]: createEditor() }
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
describe('manage opened state', () => {
|
|
35
|
-
test('should open modal', () => {
|
|
36
|
-
const toggler = createWrapper();
|
|
37
|
-
|
|
38
|
-
toggler.open();
|
|
39
|
-
|
|
40
|
-
expect(toggler.isOpened.value).toBe(true);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('should close modal', () => {
|
|
44
|
-
const toggler = createWrapper();
|
|
45
|
-
|
|
46
|
-
toggler.open();
|
|
47
|
-
toggler.close();
|
|
48
|
-
|
|
49
|
-
expect(toggler.isOpened.value).toBe(false);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('should toggle modal', () => {
|
|
53
|
-
const toggler = createWrapper();
|
|
54
|
-
|
|
55
|
-
toggler.toggle(true);
|
|
56
|
-
|
|
57
|
-
expect(toggler.isOpened.value).toBe(true);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { onUnmounted } from 'vue';
|
|
2
|
-
import { autoUpdate, computePosition, limitShift, offset, shift } from '@floating-ui/dom';
|
|
3
|
-
import { useElementRef } from '../components/base';
|
|
4
|
-
|
|
5
|
-
export function useToolbar({ wrapperRef, offsets, isActiveRef, placementRef }) {
|
|
6
|
-
const wrapperEl = useElementRef(wrapperRef);
|
|
7
|
-
let floatingInstance;
|
|
8
|
-
|
|
9
|
-
function mount(element) {
|
|
10
|
-
floatingInstance = autoUpdate(wrapperEl.value, element, async () => {
|
|
11
|
-
const positioning = await computePosition(wrapperEl.value, element, {
|
|
12
|
-
placement: placementRef.value,
|
|
13
|
-
strategy: 'fixed',
|
|
14
|
-
middleware: [
|
|
15
|
-
shift({ padding: 16, crossAxis: true, limiter: limitShift() }),
|
|
16
|
-
offset({ crossAxis: offsets[0], mainAxis: offsets[1] })
|
|
17
|
-
]
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const { x, y } = positioning;
|
|
21
|
-
|
|
22
|
-
Object.assign(element.style, {
|
|
23
|
-
left: `${x}px`,
|
|
24
|
-
top: `${y}px`
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
onUnmounted(() => floatingInstance?.());
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
mount,
|
|
33
|
-
isActiveRef,
|
|
34
|
-
offsets
|
|
35
|
-
};
|
|
36
|
-
}
|
|
File without changes
|
|
File without changes
|