@blockslides/vue-3 0.3.0 → 0.4.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.
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +92 -299
- package/package.json +2 -14
- package/src/index.ts +1 -4
- package/dist/FloatingMenu-AygIYJQV.js +0 -226
- package/dist/FloatingMenu-Un--4r7A.cjs +0 -1
- package/dist/menus/BubbleMenu.d.ts +0 -6
- package/dist/menus/FloatingMenu.d.ts +0 -6
- package/dist/menus/index.d.ts +0 -3
- package/dist/menus.cjs +0 -1
- package/dist/menus.d.ts +0 -1
- package/dist/menus.js +0 -6
- package/dist/useSlideEditor.d.ts +0 -53
- package/src/SlideEditor.vue +0 -54
- package/src/menus/BubbleMenu.ts +0 -111
- package/src/menus/BubbleMenuPreset.vue +0 -137
- package/src/menus/FloatingMenu.ts +0 -84
- package/src/menus/index.ts +0 -3
- package/src/useSlideEditor.ts +0 -255
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockslides/vue-3",
|
|
3
3
|
"description": "Vue 3 components for blockslides",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.1",
|
|
5
5
|
"homepage": "https://github.com/keivanmojmali/blockslides",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"blockslides",
|
|
@@ -18,14 +18,6 @@
|
|
|
18
18
|
},
|
|
19
19
|
"import": "./dist/index.js",
|
|
20
20
|
"require": "./dist/index.cjs"
|
|
21
|
-
},
|
|
22
|
-
"./menus": {
|
|
23
|
-
"types": {
|
|
24
|
-
"import": "./dist/menus/index.d.ts",
|
|
25
|
-
"require": "./dist/menus/index.d.cts"
|
|
26
|
-
},
|
|
27
|
-
"import": "./dist/menus/index.js",
|
|
28
|
-
"require": "./dist/menus/index.cjs"
|
|
29
21
|
}
|
|
30
22
|
},
|
|
31
23
|
"main": "dist/index.cjs",
|
|
@@ -38,7 +30,7 @@
|
|
|
38
30
|
],
|
|
39
31
|
"dependencies": {
|
|
40
32
|
"@blockslides/ai-context": "^0.3.1",
|
|
41
|
-
"@blockslides/extension-kit": "^0.7.
|
|
33
|
+
"@blockslides/extension-kit": "^0.7.3"
|
|
42
34
|
},
|
|
43
35
|
"devDependencies": {
|
|
44
36
|
"@floating-ui/dom": "^1.0.0",
|
|
@@ -49,10 +41,6 @@
|
|
|
49
41
|
"@blockslides/core": "^0.3.3",
|
|
50
42
|
"@blockslides/pm": "^0.1.1"
|
|
51
43
|
},
|
|
52
|
-
"optionalDependencies": {
|
|
53
|
-
"@blockslides/extension-bubble-menu": "^0.1.1",
|
|
54
|
-
"@blockslides/extension-floating-menu": "^0.1.1"
|
|
55
|
-
},
|
|
56
44
|
"peerDependencies": {
|
|
57
45
|
"@floating-ui/dom": "^1.0.0",
|
|
58
46
|
"vue": "^3.0.0",
|
package/src/index.ts
CHANGED
|
@@ -3,10 +3,7 @@ export * from './EditorContent.js'
|
|
|
3
3
|
export * from './NodeViewContent.js'
|
|
4
4
|
export * from './NodeViewWrapper.js'
|
|
5
5
|
export * from './useEditor.js'
|
|
6
|
-
export * from './useSlideEditor.js'
|
|
7
|
-
export { default as SlideEditor } from './SlideEditor.vue'
|
|
8
6
|
export * from './VueMarkViewRenderer.js'
|
|
9
7
|
export * from './VueNodeViewRenderer.js'
|
|
10
8
|
export * from './VueRenderer.js'
|
|
11
|
-
export * from '@blockslides/core'
|
|
12
|
-
export * from './menus/index.js'
|
|
9
|
+
export * from '@blockslides/core'
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import { defineComponent as m, ref as f, onMounted as g, watch as D, onBeforeUnmount as y, openBlock as _, createElementBlock as A, createCommentVNode as F, nextTick as M, h as v } from "vue";
|
|
2
|
-
import { BubbleMenuPlugin as E } from "@blockslides/extension-bubble-menu";
|
|
3
|
-
import { NodeSelection as N } from "@blockslides/pm/state";
|
|
4
|
-
import { buildMenuElement as C, DEFAULT_ALIGNMENTS as x, DEFAULT_FONT_SIZES as B, DEFAULT_FONTS as P, DEFAULT_HIGHLIGHT_PALETTE as j, DEFAULT_COLOR_PALETTE as L, DEFAULT_ITEMS as O } from "@blockslides/extension-bubble-menu-preset";
|
|
5
|
-
import { isTextSelection as R } from "@blockslides/core";
|
|
6
|
-
import { FloatingMenuPlugin as w } from "@blockslides/extension-floating-menu";
|
|
7
|
-
const z = {
|
|
8
|
-
key: 0,
|
|
9
|
-
style: { display: "none" }
|
|
10
|
-
}, S = "bubbleMenuPreset", H = /* @__PURE__ */ m({
|
|
11
|
-
__name: "BubbleMenuPreset",
|
|
12
|
-
props: {
|
|
13
|
-
editor: {},
|
|
14
|
-
updateDelay: {},
|
|
15
|
-
resizeDelay: {},
|
|
16
|
-
appendTo: {},
|
|
17
|
-
shouldShow: {},
|
|
18
|
-
getReferencedVirtualElement: {},
|
|
19
|
-
options: {},
|
|
20
|
-
items: {},
|
|
21
|
-
className: {},
|
|
22
|
-
injectStyles: { type: Boolean, default: !0 },
|
|
23
|
-
textColors: {},
|
|
24
|
-
highlightColors: {},
|
|
25
|
-
fonts: {},
|
|
26
|
-
fontSizes: {},
|
|
27
|
-
alignments: {},
|
|
28
|
-
onTextAction: {},
|
|
29
|
-
onImageReplace: {}
|
|
30
|
-
},
|
|
31
|
-
setup(r) {
|
|
32
|
-
const e = r, l = f(null);
|
|
33
|
-
let o;
|
|
34
|
-
const n = () => {
|
|
35
|
-
const t = e.editor;
|
|
36
|
-
if (!t || t.isDestroyed)
|
|
37
|
-
return;
|
|
38
|
-
o && (o(), o = void 0);
|
|
39
|
-
const { element: a, cleanup: s } = C(t, {
|
|
40
|
-
items: e.items ?? O,
|
|
41
|
-
className: e.className ?? "",
|
|
42
|
-
injectStyles: e.injectStyles !== !1,
|
|
43
|
-
textColors: e.textColors ?? L,
|
|
44
|
-
highlightColors: e.highlightColors ?? j,
|
|
45
|
-
fonts: e.fonts ?? P,
|
|
46
|
-
fontSizes: e.fontSizes ?? B,
|
|
47
|
-
alignments: e.alignments ?? x,
|
|
48
|
-
onTextAction: e.onTextAction,
|
|
49
|
-
onImageReplace: e.onImageReplace
|
|
50
|
-
});
|
|
51
|
-
l.value = a, o = s;
|
|
52
|
-
const d = ({ state: c, editor: p }) => {
|
|
53
|
-
var b, T;
|
|
54
|
-
const i = c.selection, h = i instanceof N && ["image", "imageBlock"].includes((T = (b = i.node) == null ? void 0 : b.type) == null ? void 0 : T.name) || p.isActive("image") || p.isActive("imageBlock");
|
|
55
|
-
return !!(h || R(i) && !i.empty && !h);
|
|
56
|
-
}, u = E({
|
|
57
|
-
editor: t,
|
|
58
|
-
element: a,
|
|
59
|
-
updateDelay: e.updateDelay,
|
|
60
|
-
resizeDelay: e.resizeDelay,
|
|
61
|
-
appendTo: e.appendTo,
|
|
62
|
-
pluginKey: S,
|
|
63
|
-
shouldShow: e.shouldShow ?? d,
|
|
64
|
-
getReferencedVirtualElement: e.getReferencedVirtualElement,
|
|
65
|
-
options: e.options
|
|
66
|
-
});
|
|
67
|
-
t.registerPlugin(u);
|
|
68
|
-
};
|
|
69
|
-
return g(() => {
|
|
70
|
-
n();
|
|
71
|
-
}), D(
|
|
72
|
-
() => [
|
|
73
|
-
e.editor,
|
|
74
|
-
e.updateDelay,
|
|
75
|
-
e.resizeDelay,
|
|
76
|
-
e.appendTo,
|
|
77
|
-
e.shouldShow,
|
|
78
|
-
e.getReferencedVirtualElement,
|
|
79
|
-
e.options,
|
|
80
|
-
e.items,
|
|
81
|
-
e.className,
|
|
82
|
-
e.injectStyles,
|
|
83
|
-
e.textColors,
|
|
84
|
-
e.highlightColors,
|
|
85
|
-
e.fonts,
|
|
86
|
-
e.fontSizes,
|
|
87
|
-
e.alignments,
|
|
88
|
-
e.onTextAction,
|
|
89
|
-
e.onImageReplace
|
|
90
|
-
],
|
|
91
|
-
() => {
|
|
92
|
-
n();
|
|
93
|
-
}
|
|
94
|
-
), y(() => {
|
|
95
|
-
var t;
|
|
96
|
-
e.editor && e.editor.unregisterPlugin(S), o && o(), (t = l.value) != null && t.parentNode && l.value.parentNode.removeChild(l.value);
|
|
97
|
-
}), (t, a) => l.value ? (_(), A("div", z)) : F("", !0);
|
|
98
|
-
}
|
|
99
|
-
}), q = m({
|
|
100
|
-
name: "BubbleMenu",
|
|
101
|
-
inheritAttrs: !1,
|
|
102
|
-
props: {
|
|
103
|
-
pluginKey: {
|
|
104
|
-
type: [String, Object],
|
|
105
|
-
default: "bubbleMenu"
|
|
106
|
-
},
|
|
107
|
-
editor: {
|
|
108
|
-
type: Object,
|
|
109
|
-
required: !0
|
|
110
|
-
},
|
|
111
|
-
updateDelay: {
|
|
112
|
-
type: Number,
|
|
113
|
-
default: void 0
|
|
114
|
-
},
|
|
115
|
-
resizeDelay: {
|
|
116
|
-
type: Number,
|
|
117
|
-
default: void 0
|
|
118
|
-
},
|
|
119
|
-
options: {
|
|
120
|
-
type: Object,
|
|
121
|
-
default: () => ({})
|
|
122
|
-
},
|
|
123
|
-
appendTo: {
|
|
124
|
-
type: [Object, Function],
|
|
125
|
-
default: void 0
|
|
126
|
-
},
|
|
127
|
-
shouldShow: {
|
|
128
|
-
type: Function,
|
|
129
|
-
default: null
|
|
130
|
-
},
|
|
131
|
-
getReferencedVirtualElement: {
|
|
132
|
-
type: Function,
|
|
133
|
-
default: void 0
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
setup(r, { slots: e, attrs: l }) {
|
|
137
|
-
const o = f(null);
|
|
138
|
-
return g(() => {
|
|
139
|
-
const {
|
|
140
|
-
editor: n,
|
|
141
|
-
options: t,
|
|
142
|
-
pluginKey: a,
|
|
143
|
-
resizeDelay: s,
|
|
144
|
-
appendTo: d,
|
|
145
|
-
shouldShow: u,
|
|
146
|
-
getReferencedVirtualElement: c,
|
|
147
|
-
updateDelay: p
|
|
148
|
-
} = r, i = o.value;
|
|
149
|
-
i && (i.style.visibility = "hidden", i.style.position = "absolute", i.remove(), M(() => {
|
|
150
|
-
n.registerPlugin(
|
|
151
|
-
E({
|
|
152
|
-
editor: n,
|
|
153
|
-
element: i,
|
|
154
|
-
options: t,
|
|
155
|
-
pluginKey: a,
|
|
156
|
-
resizeDelay: s,
|
|
157
|
-
appendTo: d,
|
|
158
|
-
shouldShow: u,
|
|
159
|
-
getReferencedVirtualElement: c,
|
|
160
|
-
updateDelay: p
|
|
161
|
-
})
|
|
162
|
-
);
|
|
163
|
-
}));
|
|
164
|
-
}), y(() => {
|
|
165
|
-
const { pluginKey: n, editor: t } = r;
|
|
166
|
-
t.unregisterPlugin(n);
|
|
167
|
-
}), () => {
|
|
168
|
-
var n;
|
|
169
|
-
return v("div", { ref: o, ...l }, (n = e.default) == null ? void 0 : n.call(e));
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
}), Z = m({
|
|
173
|
-
name: "FloatingMenu",
|
|
174
|
-
inheritAttrs: !1,
|
|
175
|
-
props: {
|
|
176
|
-
pluginKey: {
|
|
177
|
-
// TODO: TypeScript breaks
|
|
178
|
-
// type: [String, Object as PropType<Exclude<FloatingMenuPluginProps['pluginKey'], string>>],
|
|
179
|
-
type: null,
|
|
180
|
-
default: "floatingMenu"
|
|
181
|
-
},
|
|
182
|
-
editor: {
|
|
183
|
-
type: Object,
|
|
184
|
-
required: !0
|
|
185
|
-
},
|
|
186
|
-
options: {
|
|
187
|
-
type: Object,
|
|
188
|
-
default: () => ({})
|
|
189
|
-
},
|
|
190
|
-
appendTo: {
|
|
191
|
-
type: [Object, Function],
|
|
192
|
-
default: void 0
|
|
193
|
-
},
|
|
194
|
-
shouldShow: {
|
|
195
|
-
type: Function,
|
|
196
|
-
default: null
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
|
-
setup(r, { slots: e, attrs: l }) {
|
|
200
|
-
const o = f(null);
|
|
201
|
-
return g(() => {
|
|
202
|
-
const { pluginKey: n, editor: t, options: a, appendTo: s, shouldShow: d } = r, u = o.value;
|
|
203
|
-
u && (u.style.visibility = "hidden", u.style.position = "absolute", u.remove(), t.registerPlugin(
|
|
204
|
-
w({
|
|
205
|
-
pluginKey: n,
|
|
206
|
-
editor: t,
|
|
207
|
-
element: u,
|
|
208
|
-
options: a,
|
|
209
|
-
appendTo: s,
|
|
210
|
-
shouldShow: d
|
|
211
|
-
})
|
|
212
|
-
));
|
|
213
|
-
}), y(() => {
|
|
214
|
-
const { pluginKey: n, editor: t } = r;
|
|
215
|
-
t.unregisterPlugin(n);
|
|
216
|
-
}), () => {
|
|
217
|
-
var n;
|
|
218
|
-
return v("div", { ref: o, ...l }, (n = e.default) == null ? void 0 : n.call(e));
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
export {
|
|
223
|
-
q as B,
|
|
224
|
-
Z as F,
|
|
225
|
-
H as _
|
|
226
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";const t=require("vue"),T=require("@blockslides/extension-bubble-menu"),S=require("@blockslides/pm/state"),c=require("@blockslides/extension-bubble-menu-preset"),v=require("@blockslides/core"),E=require("@blockslides/extension-floating-menu"),M={key:0,style:{display:"none"}},b="bubbleMenuPreset",D=t.defineComponent({__name:"BubbleMenuPreset",props:{editor:{},updateDelay:{},resizeDelay:{},appendTo:{},shouldShow:{},getReferencedVirtualElement:{},options:{},items:{},className:{},injectStyles:{type:Boolean,default:!0},textColors:{},highlightColors:{},fonts:{},fontSizes:{},alignments:{},onTextAction:{},onImageReplace:{}},setup(s){const e=s,u=t.ref(null);let i;const o=()=>{const n=e.editor;if(!n||n.isDestroyed)return;i&&(i(),i=void 0);const{element:a,cleanup:d}=c.buildMenuElement(n,{items:e.items??c.DEFAULT_ITEMS,className:e.className??"",injectStyles:e.injectStyles!==!1,textColors:e.textColors??c.DEFAULT_COLOR_PALETTE,highlightColors:e.highlightColors??c.DEFAULT_HIGHLIGHT_PALETTE,fonts:e.fonts??c.DEFAULT_FONTS,fontSizes:e.fontSizes??c.DEFAULT_FONT_SIZES,alignments:e.alignments??c.DEFAULT_ALIGNMENTS,onTextAction:e.onTextAction,onImageReplace:e.onImageReplace});u.value=a,i=d;const p=({state:g,editor:f})=>{var y,h;const l=g.selection,m=l instanceof S.NodeSelection&&["image","imageBlock"].includes((h=(y=l.node)==null?void 0:y.type)==null?void 0:h.name)||f.isActive("image")||f.isActive("imageBlock");return!!(m||v.isTextSelection(l)&&!l.empty&&!m)},r=T.BubbleMenuPlugin({editor:n,element:a,updateDelay:e.updateDelay,resizeDelay:e.resizeDelay,appendTo:e.appendTo,pluginKey:b,shouldShow:e.shouldShow??p,getReferencedVirtualElement:e.getReferencedVirtualElement,options:e.options});n.registerPlugin(r)};return t.onMounted(()=>{o()}),t.watch(()=>[e.editor,e.updateDelay,e.resizeDelay,e.appendTo,e.shouldShow,e.getReferencedVirtualElement,e.options,e.items,e.className,e.injectStyles,e.textColors,e.highlightColors,e.fonts,e.fontSizes,e.alignments,e.onTextAction,e.onImageReplace],()=>{o()}),t.onBeforeUnmount(()=>{var n;e.editor&&e.editor.unregisterPlugin(b),i&&i(),(n=u.value)!=null&&n.parentNode&&u.value.parentNode.removeChild(u.value)}),(n,a)=>u.value?(t.openBlock(),t.createElementBlock("div",M)):t.createCommentVNode("",!0)}}),_=t.defineComponent({name:"BubbleMenu",inheritAttrs:!1,props:{pluginKey:{type:[String,Object],default:"bubbleMenu"},editor:{type:Object,required:!0},updateDelay:{type:Number,default:void 0},resizeDelay:{type:Number,default:void 0},options:{type:Object,default:()=>({})},appendTo:{type:[Object,Function],default:void 0},shouldShow:{type:Function,default:null},getReferencedVirtualElement:{type:Function,default:void 0}},setup(s,{slots:e,attrs:u}){const i=t.ref(null);return t.onMounted(()=>{const{editor:o,options:n,pluginKey:a,resizeDelay:d,appendTo:p,shouldShow:r,getReferencedVirtualElement:g,updateDelay:f}=s,l=i.value;l&&(l.style.visibility="hidden",l.style.position="absolute",l.remove(),t.nextTick(()=>{o.registerPlugin(T.BubbleMenuPlugin({editor:o,element:l,options:n,pluginKey:a,resizeDelay:d,appendTo:p,shouldShow:r,getReferencedVirtualElement:g,updateDelay:f}))}))}),t.onBeforeUnmount(()=>{const{pluginKey:o,editor:n}=s;n.unregisterPlugin(o)}),()=>{var o;return t.h("div",{ref:i,...u},(o=e.default)==null?void 0:o.call(e))}}}),F=t.defineComponent({name:"FloatingMenu",inheritAttrs:!1,props:{pluginKey:{type:null,default:"floatingMenu"},editor:{type:Object,required:!0},options:{type:Object,default:()=>({})},appendTo:{type:[Object,Function],default:void 0},shouldShow:{type:Function,default:null}},setup(s,{slots:e,attrs:u}){const i=t.ref(null);return t.onMounted(()=>{const{pluginKey:o,editor:n,options:a,appendTo:d,shouldShow:p}=s,r=i.value;r&&(r.style.visibility="hidden",r.style.position="absolute",r.remove(),n.registerPlugin(E.FloatingMenuPlugin({pluginKey:o,editor:n,element:r,options:a,appendTo:d,shouldShow:p})))}),t.onBeforeUnmount(()=>{const{pluginKey:o,editor:n}=s;n.unregisterPlugin(o)}),()=>{var o;return t.h("div",{ref:i,...u},(o=e.default)==null?void 0:o.call(e))}}});exports.BubbleMenu=_;exports.FloatingMenu=F;exports._sfc_main=D;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { BubbleMenuPluginProps } from '../../../extension-bubble-menu/src';
|
|
2
|
-
|
|
3
|
-
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
|
4
|
-
export type BubbleMenuProps = Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>;
|
|
5
|
-
export declare const BubbleMenu: any;
|
|
6
|
-
export {};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { FloatingMenuPluginProps } from '../../../extension-floating-menu/src';
|
|
2
|
-
|
|
3
|
-
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
|
4
|
-
export type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element'>;
|
|
5
|
-
export declare const FloatingMenu: any;
|
|
6
|
-
export {};
|
package/dist/menus/index.d.ts
DELETED
package/dist/menus.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./FloatingMenu-Un--4r7A.cjs");exports.BubbleMenu=e.BubbleMenu;exports.BubbleMenuPreset=e._sfc_main;exports.FloatingMenu=e.FloatingMenu;
|
package/dist/menus.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './menus/index'
|
package/dist/menus.js
DELETED
package/dist/useSlideEditor.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { templatesV1 } from '../../ai-context/src';
|
|
2
|
-
import { AnyExtension, Editor, JSONContent, EditorOptions } from '../../core/src';
|
|
3
|
-
import { ExtensionKitOptions } from '../../extension-kit/src';
|
|
4
|
-
|
|
5
|
-
type PresetTemplates = ReturnType<typeof templatesV1.listPresetTemplates>;
|
|
6
|
-
export interface UseSlideEditorProps {
|
|
7
|
-
/**
|
|
8
|
-
* Initial content for the editor. If omitted, a single preset slide is used.
|
|
9
|
-
*/
|
|
10
|
-
content?: EditorOptions['content'];
|
|
11
|
-
/**
|
|
12
|
-
* Called on every update with the current JSON document.
|
|
13
|
-
*/
|
|
14
|
-
onChange?: (doc: JSONContent, editor: Editor) => void;
|
|
15
|
-
/**
|
|
16
|
-
* Additional extensions to append after the ExtensionKit bundle.
|
|
17
|
-
*/
|
|
18
|
-
extensions?: AnyExtension[];
|
|
19
|
-
/**
|
|
20
|
-
* Customize or disable pieces of ExtensionKit (e.g., bubbleMenu: false).
|
|
21
|
-
*/
|
|
22
|
-
extensionKitOptions?: ExtensionKitOptions;
|
|
23
|
-
/**
|
|
24
|
-
* Optional preset list to power the add-slide button.
|
|
25
|
-
*/
|
|
26
|
-
presetTemplates?: PresetTemplates;
|
|
27
|
-
/**
|
|
28
|
-
* Called once when an editor instance is ready.
|
|
29
|
-
*/
|
|
30
|
-
onEditorReady?: (editor: Editor) => void;
|
|
31
|
-
/**
|
|
32
|
-
* Editor theme for UI styling
|
|
33
|
-
*/
|
|
34
|
-
theme?: EditorOptions['theme'];
|
|
35
|
-
/**
|
|
36
|
-
* The editor's props
|
|
37
|
-
*/
|
|
38
|
-
editorProps?: EditorOptions['editorProps'];
|
|
39
|
-
/**
|
|
40
|
-
* Called on every update
|
|
41
|
-
*/
|
|
42
|
-
onUpdate?: EditorOptions['onUpdate'];
|
|
43
|
-
/**
|
|
44
|
-
* Additional editor options to pass through to the core editor.
|
|
45
|
-
* This allows passing any EditorOptions without Vue auto-initializing them.
|
|
46
|
-
*/
|
|
47
|
-
editorOptions?: Partial<EditorOptions>;
|
|
48
|
-
}
|
|
49
|
-
export declare const useSlideEditor: (props?: UseSlideEditorProps) => {
|
|
50
|
-
editor: import('vue').ShallowRef<import('./Editor.js').Editor | undefined, import('./Editor.js').Editor | undefined>;
|
|
51
|
-
presets: import('vue').ComputedRef<templatesV1.PresetTemplate[]>;
|
|
52
|
-
};
|
|
53
|
-
export {};
|
package/src/SlideEditor.vue
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, watch, onMounted } from 'vue'
|
|
3
|
-
import { EditorContent } from './EditorContent'
|
|
4
|
-
import BubbleMenuPreset from './menus/BubbleMenuPreset.vue'
|
|
5
|
-
import { useSlideEditor, type UseSlideEditorProps } from './useSlideEditor'
|
|
6
|
-
import type { Editor } from '@blockslides/core'
|
|
7
|
-
|
|
8
|
-
export interface BubbleMenuPresetProps {
|
|
9
|
-
editor: Editor
|
|
10
|
-
[key: string]: any
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface SlideEditorProps extends UseSlideEditorProps {
|
|
14
|
-
/**
|
|
15
|
-
* Toggle or customize the built-in BubbleMenuPreset.
|
|
16
|
-
* - true (default): render with defaults
|
|
17
|
-
* - false: disable entirely
|
|
18
|
-
* - object: pass through to BubbleMenuPreset
|
|
19
|
-
*/
|
|
20
|
-
bubbleMenuPreset?: boolean | BubbleMenuPresetProps
|
|
21
|
-
className?: string
|
|
22
|
-
style?: any
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const props = withDefaults(defineProps<SlideEditorProps>(), {
|
|
26
|
-
bubbleMenuPreset: true,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const {
|
|
30
|
-
bubbleMenuPreset,
|
|
31
|
-
className,
|
|
32
|
-
style,
|
|
33
|
-
...hookProps
|
|
34
|
-
} = props
|
|
35
|
-
|
|
36
|
-
const { editor } = useSlideEditor(hookProps)
|
|
37
|
-
|
|
38
|
-
const bubbleMenuProps = computed(() => {
|
|
39
|
-
if (props.bubbleMenuPreset === false) return null
|
|
40
|
-
if (props.bubbleMenuPreset === true) return {}
|
|
41
|
-
return props.bubbleMenuPreset
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
</script>
|
|
45
|
-
|
|
46
|
-
<template>
|
|
47
|
-
<div v-if="editor" :class="className" :style="style">
|
|
48
|
-
<div class="bs-viewport">
|
|
49
|
-
<EditorContent :editor="editor" />
|
|
50
|
-
<BubbleMenuPreset v-if="bubbleMenuProps" :editor="editor" v-bind="bubbleMenuProps" />
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
</template>
|
|
54
|
-
|
package/src/menus/BubbleMenu.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import type { BubbleMenuPluginProps } from '@blockslides/extension-bubble-menu'
|
|
2
|
-
import { BubbleMenuPlugin } from '@blockslides/extension-bubble-menu'
|
|
3
|
-
import type { PropType } from 'vue'
|
|
4
|
-
import { defineComponent, h, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
|
5
|
-
|
|
6
|
-
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
|
|
7
|
-
|
|
8
|
-
export type BubbleMenuProps = Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>
|
|
9
|
-
|
|
10
|
-
export const BubbleMenu = defineComponent({
|
|
11
|
-
name: 'BubbleMenu',
|
|
12
|
-
|
|
13
|
-
inheritAttrs: false,
|
|
14
|
-
|
|
15
|
-
props: {
|
|
16
|
-
pluginKey: {
|
|
17
|
-
type: [String, Object] as PropType<BubbleMenuPluginProps['pluginKey']>,
|
|
18
|
-
default: 'bubbleMenu',
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
editor: {
|
|
22
|
-
type: Object as PropType<BubbleMenuPluginProps['editor']>,
|
|
23
|
-
required: true,
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
updateDelay: {
|
|
27
|
-
type: Number as PropType<BubbleMenuPluginProps['updateDelay']>,
|
|
28
|
-
default: undefined,
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
resizeDelay: {
|
|
32
|
-
type: Number as PropType<BubbleMenuPluginProps['resizeDelay']>,
|
|
33
|
-
default: undefined,
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
options: {
|
|
37
|
-
type: Object as PropType<BubbleMenuPluginProps['options']>,
|
|
38
|
-
default: () => ({}),
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
appendTo: {
|
|
42
|
-
type: [Object, Function] as PropType<BubbleMenuPluginProps['appendTo']>,
|
|
43
|
-
default: undefined,
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
shouldShow: {
|
|
47
|
-
type: Function as PropType<Exclude<Required<BubbleMenuPluginProps>['shouldShow'], null>>,
|
|
48
|
-
default: null,
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
getReferencedVirtualElement: {
|
|
52
|
-
type: Function as PropType<Exclude<Required<BubbleMenuPluginProps>['getReferencedVirtualElement'], null>>,
|
|
53
|
-
default: undefined,
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
setup(props, { slots, attrs }) {
|
|
58
|
-
const root = ref<HTMLElement | null>(null)
|
|
59
|
-
|
|
60
|
-
onMounted(() => {
|
|
61
|
-
const {
|
|
62
|
-
editor,
|
|
63
|
-
options,
|
|
64
|
-
pluginKey,
|
|
65
|
-
resizeDelay,
|
|
66
|
-
appendTo,
|
|
67
|
-
shouldShow,
|
|
68
|
-
getReferencedVirtualElement,
|
|
69
|
-
updateDelay,
|
|
70
|
-
} = props
|
|
71
|
-
|
|
72
|
-
const el = root.value
|
|
73
|
-
|
|
74
|
-
if (!el) {
|
|
75
|
-
return
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
el.style.visibility = 'hidden'
|
|
79
|
-
el.style.position = 'absolute'
|
|
80
|
-
|
|
81
|
-
// Remove element from DOM; plugin will re-parent it when shown
|
|
82
|
-
el.remove()
|
|
83
|
-
|
|
84
|
-
nextTick(() => {
|
|
85
|
-
editor.registerPlugin(
|
|
86
|
-
BubbleMenuPlugin({
|
|
87
|
-
editor,
|
|
88
|
-
element: el,
|
|
89
|
-
options,
|
|
90
|
-
pluginKey,
|
|
91
|
-
resizeDelay,
|
|
92
|
-
appendTo,
|
|
93
|
-
shouldShow,
|
|
94
|
-
getReferencedVirtualElement,
|
|
95
|
-
updateDelay,
|
|
96
|
-
}),
|
|
97
|
-
)
|
|
98
|
-
})
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
onBeforeUnmount(() => {
|
|
102
|
-
const { pluginKey, editor } = props
|
|
103
|
-
|
|
104
|
-
editor.unregisterPlugin(pluginKey)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
// Vue owns this element; attrs are applied reactively by Vue
|
|
108
|
-
// Plugin re-parents it when showing the menu
|
|
109
|
-
return () => h('div', { ref: root, ...attrs }, slots.default?.())
|
|
110
|
-
},
|
|
111
|
-
}) as any
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
3
|
-
import { BubbleMenuPlugin, type BubbleMenuPluginProps } from '@blockslides/extension-bubble-menu'
|
|
4
|
-
import { NodeSelection } from '@blockslides/pm/state'
|
|
5
|
-
import {
|
|
6
|
-
type BubbleMenuPresetOptions,
|
|
7
|
-
buildMenuElement,
|
|
8
|
-
DEFAULT_ITEMS,
|
|
9
|
-
DEFAULT_COLOR_PALETTE,
|
|
10
|
-
DEFAULT_HIGHLIGHT_PALETTE,
|
|
11
|
-
DEFAULT_FONTS,
|
|
12
|
-
DEFAULT_FONT_SIZES,
|
|
13
|
-
DEFAULT_ALIGNMENTS,
|
|
14
|
-
} from '@blockslides/extension-bubble-menu-preset'
|
|
15
|
-
import { isTextSelection, type Editor } from '@blockslides/core'
|
|
16
|
-
|
|
17
|
-
export interface BubbleMenuPresetProps extends Omit<BubbleMenuPresetOptions, 'element' | 'pluginKey'> {
|
|
18
|
-
editor: Editor
|
|
19
|
-
updateDelay?: number
|
|
20
|
-
resizeDelay?: number
|
|
21
|
-
appendTo?: HTMLElement | (() => HTMLElement)
|
|
22
|
-
shouldShow?: BubbleMenuPluginProps['shouldShow']
|
|
23
|
-
getReferencedVirtualElement?: () => any
|
|
24
|
-
options?: any
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const props = withDefaults(defineProps<BubbleMenuPresetProps>(), {
|
|
28
|
-
injectStyles: true,
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
const pluginKey = 'bubbleMenuPreset'
|
|
32
|
-
const menuEl = ref<HTMLElement | null>(null)
|
|
33
|
-
let cleanup: (() => void) | undefined
|
|
34
|
-
|
|
35
|
-
const setupBubbleMenu = () => {
|
|
36
|
-
const attachToEditor = props.editor
|
|
37
|
-
|
|
38
|
-
if (!attachToEditor || (attachToEditor as any).isDestroyed) {
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Cleanup previous instance if any
|
|
43
|
-
if (cleanup) {
|
|
44
|
-
cleanup()
|
|
45
|
-
cleanup = undefined
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const { element, cleanup: elementCleanup } = buildMenuElement(attachToEditor, {
|
|
49
|
-
items: props.items ?? DEFAULT_ITEMS,
|
|
50
|
-
className: props.className ?? '',
|
|
51
|
-
injectStyles: props.injectStyles !== false,
|
|
52
|
-
textColors: props.textColors ?? DEFAULT_COLOR_PALETTE,
|
|
53
|
-
highlightColors: props.highlightColors ?? DEFAULT_HIGHLIGHT_PALETTE,
|
|
54
|
-
fonts: props.fonts ?? DEFAULT_FONTS,
|
|
55
|
-
fontSizes: props.fontSizes ?? DEFAULT_FONT_SIZES,
|
|
56
|
-
alignments: props.alignments ?? DEFAULT_ALIGNMENTS,
|
|
57
|
-
onTextAction: props.onTextAction,
|
|
58
|
-
onImageReplace: props.onImageReplace,
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
menuEl.value = element
|
|
62
|
-
cleanup = elementCleanup
|
|
63
|
-
|
|
64
|
-
const defaultShouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null> = ({ state, editor }) => {
|
|
65
|
-
const sel = state.selection
|
|
66
|
-
const imageSelection =
|
|
67
|
-
(sel instanceof NodeSelection && ['image', 'imageBlock'].includes((sel as any).node?.type?.name)) ||
|
|
68
|
-
editor.isActive('image') ||
|
|
69
|
-
editor.isActive('imageBlock')
|
|
70
|
-
|
|
71
|
-
if (imageSelection) return true
|
|
72
|
-
if (isTextSelection(sel) && !sel.empty && !imageSelection) return true
|
|
73
|
-
return false
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const plugin = BubbleMenuPlugin({
|
|
77
|
-
editor: attachToEditor,
|
|
78
|
-
element,
|
|
79
|
-
updateDelay: props.updateDelay,
|
|
80
|
-
resizeDelay: props.resizeDelay,
|
|
81
|
-
appendTo: props.appendTo,
|
|
82
|
-
pluginKey,
|
|
83
|
-
shouldShow: props.shouldShow ?? defaultShouldShow,
|
|
84
|
-
getReferencedVirtualElement: props.getReferencedVirtualElement,
|
|
85
|
-
options: props.options,
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
attachToEditor.registerPlugin(plugin)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
onMounted(() => {
|
|
92
|
-
setupBubbleMenu()
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
// Watch for prop changes and rebuild
|
|
96
|
-
watch(
|
|
97
|
-
() => [
|
|
98
|
-
props.editor,
|
|
99
|
-
props.updateDelay,
|
|
100
|
-
props.resizeDelay,
|
|
101
|
-
props.appendTo,
|
|
102
|
-
props.shouldShow,
|
|
103
|
-
props.getReferencedVirtualElement,
|
|
104
|
-
props.options,
|
|
105
|
-
props.items,
|
|
106
|
-
props.className,
|
|
107
|
-
props.injectStyles,
|
|
108
|
-
props.textColors,
|
|
109
|
-
props.highlightColors,
|
|
110
|
-
props.fonts,
|
|
111
|
-
props.fontSizes,
|
|
112
|
-
props.alignments,
|
|
113
|
-
props.onTextAction,
|
|
114
|
-
props.onImageReplace,
|
|
115
|
-
],
|
|
116
|
-
() => {
|
|
117
|
-
setupBubbleMenu()
|
|
118
|
-
}
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
onBeforeUnmount(() => {
|
|
122
|
-
if (props.editor) {
|
|
123
|
-
props.editor.unregisterPlugin(pluginKey)
|
|
124
|
-
}
|
|
125
|
-
if (cleanup) {
|
|
126
|
-
cleanup()
|
|
127
|
-
}
|
|
128
|
-
if (menuEl.value?.parentNode) {
|
|
129
|
-
menuEl.value.parentNode.removeChild(menuEl.value)
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
</script>
|
|
133
|
-
|
|
134
|
-
<template>
|
|
135
|
-
<!-- Vue doesn't need portal here as buildMenuElement handles DOM placement -->
|
|
136
|
-
<div v-if="menuEl" style="display: none"></div>
|
|
137
|
-
</template>
|