@studiocms/wysiwyg 0.1.0-experimental.2 → 0.1.0-experimental.4
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/components/Editor.astro +24 -38
- package/dist/wysiwyg/editorPlugins/blocks/blocks.d.ts +3 -0
- package/dist/wysiwyg/editorPlugins/blocks/blocks.js +239 -0
- package/dist/wysiwyg/editorPlugins/blocks/index.d.ts +80 -0
- package/dist/wysiwyg/editorPlugins/blocks/index.js +26 -0
- package/dist/wysiwyg/editorPlugins/code/blocks.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/code/blocks.js +20 -0
- package/dist/wysiwyg/editorPlugins/code/commands.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/code/commands.js +109 -0
- package/dist/wysiwyg/editorPlugins/code/components.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/code/components.js +88 -0
- package/dist/wysiwyg/editorPlugins/code/index.d.ts +47 -0
- package/dist/wysiwyg/editorPlugins/code/index.js +28 -0
- package/dist/wysiwyg/editorPlugins/code/utils.d.ts +3 -0
- package/dist/wysiwyg/editorPlugins/code/utils.js +8 -0
- package/dist/wysiwyg/editorPlugins/countdown.d.ts +86 -0
- package/dist/wysiwyg/editorPlugins/countdown.js +163 -0
- package/dist/wysiwyg/editorPlugins/forms/blocks.d.ts +3 -0
- package/dist/wysiwyg/editorPlugins/forms/blocks.js +93 -0
- package/dist/wysiwyg/editorPlugins/forms/components.d.ts +11 -0
- package/dist/wysiwyg/editorPlugins/forms/components.js +284 -0
- package/dist/wysiwyg/editorPlugins/forms/index.d.ts +21 -0
- package/dist/wysiwyg/editorPlugins/forms/index.js +18 -0
- package/dist/wysiwyg/editorPlugins/forms/traits.d.ts +2 -0
- package/dist/wysiwyg/editorPlugins/forms/traits.js +47 -0
- package/dist/wysiwyg/editorPlugins/index.d.ts +9 -0
- package/dist/wysiwyg/editorPlugins/index.js +20 -0
- package/dist/wysiwyg/editorPlugins/rte/colorPicker.d.ts +95 -0
- package/dist/wysiwyg/editorPlugins/rte/colorPicker.js +185 -0
- package/dist/wysiwyg/editorPlugins/rte/index.d.ts +48 -0
- package/dist/wysiwyg/editorPlugins/rte/index.js +369 -0
- package/dist/wysiwyg/editorPlugins/rte/styles.css +63 -0
- package/dist/wysiwyg/editorPlugins/tabs/blocks.d.ts +3 -0
- package/dist/wysiwyg/editorPlugins/tabs/blocks.js +19 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/Tab.d.ts +10 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/Tab.js +100 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/TabContainer.d.ts +5 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/TabContainer.js +23 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/TabContent.d.ts +5 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/TabContent.js +23 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/TabContents.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/TabContents.js +19 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/Tabs.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/Tabs.js +169 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/index.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/tabs/components/index.js +29 -0
- package/dist/wysiwyg/editorPlugins/tabs/index.d.ts +5 -0
- package/dist/wysiwyg/editorPlugins/tabs/index.js +15 -0
- package/dist/wysiwyg/editorPlugins/tabs/options.d.ts +5 -0
- package/dist/wysiwyg/editorPlugins/tabs/options.js +80 -0
- package/dist/wysiwyg/editorPlugins/tabs/types.d.ts +81 -0
- package/dist/wysiwyg/editorPlugins/tabs/types.js +0 -0
- package/dist/wysiwyg/editorPlugins/tooltip.d.ts +68 -0
- package/dist/wysiwyg/editorPlugins/tooltip.js +318 -0
- package/dist/wysiwyg/editorPlugins/tuiImageEditor.d.ts +86 -0
- package/dist/wysiwyg/editorPlugins/tuiImageEditor.js +204 -0
- package/dist/wysiwyg/editorPlugins/typed/blocks.d.ts +4 -0
- package/dist/wysiwyg/editorPlugins/typed/blocks.js +15 -0
- package/dist/wysiwyg/editorPlugins/typed/components.d.ts +9 -0
- package/dist/wysiwyg/editorPlugins/typed/components.js +109 -0
- package/dist/wysiwyg/editorPlugins/typed/index.d.ts +35 -0
- package/dist/wysiwyg/editorPlugins/typed/index.js +18 -0
- package/dist/wysiwyg/editorPlugins/typed/traits.d.ts +3 -0
- package/dist/wysiwyg/editorPlugins/typed/traits.js +18 -0
- package/dist/wysiwyg/editorPlugins/typed/utils.d.ts +2 -0
- package/dist/wysiwyg/editorPlugins/typed/utils.js +6 -0
- package/package.json +5 -17
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
const plugin = (editor, opts = {}) => {
|
|
2
|
+
const options = {
|
|
3
|
+
// The ID used to create tooltip block and component
|
|
4
|
+
id: "tooltip",
|
|
5
|
+
// Label of the tooltip. Used for the block and component name
|
|
6
|
+
labelTooltip: "Tooltip",
|
|
7
|
+
// Object to extend the default tooltip block, eg. { label: 'Tooltip', category: 'Extra', ... }.
|
|
8
|
+
// Pass a falsy value to avoid adding the block
|
|
9
|
+
blockTooltip: {},
|
|
10
|
+
// Object to extend the default tooltip properties, eg. `{ name: 'Tooltip', droppable: false, ... }`
|
|
11
|
+
propsTooltip: {},
|
|
12
|
+
// A function which allows to extend default traits by receiving the original array and returning a new one
|
|
13
|
+
extendTraits: (traits) => traits,
|
|
14
|
+
// Tooltip attribute prefix
|
|
15
|
+
attrTooltip: "data-tooltip",
|
|
16
|
+
// Tooltip class prefix
|
|
17
|
+
classTooltip: "tooltip-component",
|
|
18
|
+
// Custom CSS styles, this will replace the default one
|
|
19
|
+
style: "",
|
|
20
|
+
// Additional CSS styles
|
|
21
|
+
styleAdditional: "",
|
|
22
|
+
// Make all tooltip relative classes private
|
|
23
|
+
privateClasses: true,
|
|
24
|
+
// Indicate if the tooltip can be styled. You can also pass an array
|
|
25
|
+
// of which properties can be styled. Eg. `['color', 'background-color']`
|
|
26
|
+
stylableTooltip: [
|
|
27
|
+
"background-color",
|
|
28
|
+
"padding",
|
|
29
|
+
"padding-top",
|
|
30
|
+
"padding-right",
|
|
31
|
+
"padding-bottom",
|
|
32
|
+
"padding-left",
|
|
33
|
+
"font-family",
|
|
34
|
+
"font-size",
|
|
35
|
+
"font-weight",
|
|
36
|
+
"letter-spacing",
|
|
37
|
+
"color",
|
|
38
|
+
"line-height",
|
|
39
|
+
"text-align",
|
|
40
|
+
"border-radius",
|
|
41
|
+
"border-top-left-radius",
|
|
42
|
+
"border-top-right-radius",
|
|
43
|
+
"border-bottom-left-radius",
|
|
44
|
+
"border-bottom-right-radius",
|
|
45
|
+
"border",
|
|
46
|
+
"border-width",
|
|
47
|
+
"border-style",
|
|
48
|
+
"border-color"
|
|
49
|
+
],
|
|
50
|
+
// If true, force the tooltip to be shown
|
|
51
|
+
showTooltipOnStyle: true,
|
|
52
|
+
...opts
|
|
53
|
+
};
|
|
54
|
+
const {
|
|
55
|
+
propsTooltip,
|
|
56
|
+
classTooltip,
|
|
57
|
+
style,
|
|
58
|
+
styleAdditional,
|
|
59
|
+
privateClasses,
|
|
60
|
+
stylableTooltip,
|
|
61
|
+
showTooltipOnStyle,
|
|
62
|
+
blockTooltip,
|
|
63
|
+
extendTraits
|
|
64
|
+
} = options;
|
|
65
|
+
const id = options.id;
|
|
66
|
+
const labelTooltip = options.labelTooltip;
|
|
67
|
+
const attrTooltip = options.attrTooltip;
|
|
68
|
+
if (blockTooltip) {
|
|
69
|
+
editor.BlockManager.add(id, {
|
|
70
|
+
media: `<svg viewBox="0 0 24 24">
|
|
71
|
+
<path d="M4 2h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2h-4l-4 4-4-4H4c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2m0 2v12h4.83L12 19.17 15.17 16H20V4H4z"></path>
|
|
72
|
+
</svg>`,
|
|
73
|
+
label: labelTooltip,
|
|
74
|
+
category: "Extra",
|
|
75
|
+
select: true,
|
|
76
|
+
content: { type: id },
|
|
77
|
+
...blockTooltip
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const classTooltipBody = `${classTooltip}__body`;
|
|
81
|
+
const classTooltipEmpty = `${classTooltip}--empty`;
|
|
82
|
+
const attrTooltipVis = `${attrTooltip}-visible`;
|
|
83
|
+
const attrTooltipPos = `${attrTooltip}-pos`;
|
|
84
|
+
const attrTooltipLen = `${attrTooltip}-length`;
|
|
85
|
+
const traitIdStyleTooltip = "style-tooltip";
|
|
86
|
+
if (privateClasses) {
|
|
87
|
+
editor.SelectorManager.getAll().add([
|
|
88
|
+
{ private: 1, name: classTooltip },
|
|
89
|
+
{ private: 1, name: classTooltipBody },
|
|
90
|
+
{ private: 1, name: classTooltipEmpty }
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
editor.Components.addType(id, {
|
|
94
|
+
isComponent: (el) => el.hasAttribute?.(attrTooltip),
|
|
95
|
+
model: {
|
|
96
|
+
defaults: {
|
|
97
|
+
name: labelTooltip,
|
|
98
|
+
classes: [classTooltip],
|
|
99
|
+
attributes: { [attrTooltip]: labelTooltip },
|
|
100
|
+
styles: (style || `
|
|
101
|
+
.${classTooltip} {
|
|
102
|
+
position: relative;
|
|
103
|
+
display: inline-block;
|
|
104
|
+
vertical-align: top;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.${classTooltipEmpty} {
|
|
108
|
+
width: 50px;
|
|
109
|
+
height: 50px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.${classTooltipBody},
|
|
113
|
+
[${attrTooltip}]::after {
|
|
114
|
+
font-family: Helvetica, sans-serif;
|
|
115
|
+
background: rgba(55, 61, 73, 0.95);
|
|
116
|
+
border-radius: 3px;
|
|
117
|
+
bottom: 100%;
|
|
118
|
+
color: #fff;
|
|
119
|
+
content: attr(${attrTooltip});
|
|
120
|
+
display: block;
|
|
121
|
+
font-size: 12px;
|
|
122
|
+
left: 50%;
|
|
123
|
+
line-height: normal;
|
|
124
|
+
max-width: 32rem;
|
|
125
|
+
opacity: 0;
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
padding: 8px 16px;
|
|
128
|
+
pointer-events: none;
|
|
129
|
+
position: absolute;
|
|
130
|
+
text-overflow: ellipsis;
|
|
131
|
+
transform: translate(-50%, 0);
|
|
132
|
+
transition: opacity 0.25s, transform 0.25s;
|
|
133
|
+
white-space: nowrap;
|
|
134
|
+
box-sizing: border-box;
|
|
135
|
+
z-index: 10;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
[${attrTooltipVis}=true]::after,
|
|
139
|
+
[${attrTooltip}]:focus::after,
|
|
140
|
+
[${attrTooltip}]:hover::after {
|
|
141
|
+
opacity: 1;
|
|
142
|
+
transform: translate(-50%, -0.5rem);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
[${attrTooltipPos}=right]::after {
|
|
146
|
+
bottom: 50%;
|
|
147
|
+
left: 100%;
|
|
148
|
+
transform: translate(0, 50%);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
[${attrTooltipPos}=right]:focus::after,
|
|
152
|
+
[${attrTooltipPos}=right]:hover::after,
|
|
153
|
+
[${attrTooltipVis}=true][${attrTooltipPos}=right]::after {
|
|
154
|
+
transform: translate(0.5rem, 50%);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
[${attrTooltipPos}=bottom]::after {
|
|
158
|
+
bottom: auto;
|
|
159
|
+
top: 100%;
|
|
160
|
+
transform: translate(-50%, 0);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
[${attrTooltipPos}=bottom]:focus::after,
|
|
164
|
+
[${attrTooltipPos}=bottom]:hover::after,
|
|
165
|
+
[${attrTooltipVis}=true][${attrTooltipPos}=bottom]::after {
|
|
166
|
+
transform: translate(-50%, 0.5rem);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
[${attrTooltipPos}=left]::after {
|
|
170
|
+
bottom: 50%;
|
|
171
|
+
left: auto;
|
|
172
|
+
right: 100%;
|
|
173
|
+
transform: translate(0, 50%);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
[${attrTooltipPos}=left]:focus::after,
|
|
177
|
+
[${attrTooltipPos}=left]:hover::after,
|
|
178
|
+
[${attrTooltipVis}=true][${attrTooltipPos}=left]::after {
|
|
179
|
+
transform: translate(-0.5rem, 50%);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
[${attrTooltipLen}=small]::after {
|
|
183
|
+
white-space: normal;
|
|
184
|
+
width: 80px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
[${attrTooltipLen}=medium]::after {
|
|
188
|
+
white-space: normal;
|
|
189
|
+
width: 150px;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
[${attrTooltipLen}=large]::after {
|
|
193
|
+
white-space: normal;
|
|
194
|
+
width: 300px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
[${attrTooltipLen}=fit]::after {
|
|
198
|
+
white-space: normal;
|
|
199
|
+
width: 100%;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// IE 11 bugfix
|
|
203
|
+
button[${attrTooltip}] {
|
|
204
|
+
overflow: visible;
|
|
205
|
+
}
|
|
206
|
+
`) + styleAdditional,
|
|
207
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
208
|
+
traits: extendTraits([
|
|
209
|
+
{
|
|
210
|
+
name: attrTooltip,
|
|
211
|
+
label: "Text"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: attrTooltipPos,
|
|
215
|
+
label: "Position",
|
|
216
|
+
type: "select",
|
|
217
|
+
options: [
|
|
218
|
+
{
|
|
219
|
+
value: "top",
|
|
220
|
+
name: "Top",
|
|
221
|
+
id: ""
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
value: "right",
|
|
225
|
+
name: "Right",
|
|
226
|
+
id: ""
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
value: "bottom",
|
|
230
|
+
name: "Bottom",
|
|
231
|
+
id: ""
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
value: "left",
|
|
235
|
+
name: "Left",
|
|
236
|
+
id: ""
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: attrTooltipLen,
|
|
242
|
+
label: "Length",
|
|
243
|
+
type: "select",
|
|
244
|
+
options: [
|
|
245
|
+
{
|
|
246
|
+
value: "",
|
|
247
|
+
name: "One line",
|
|
248
|
+
id: ""
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
value: "small",
|
|
252
|
+
name: "Small",
|
|
253
|
+
id: ""
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
value: "medium",
|
|
257
|
+
name: "Medium",
|
|
258
|
+
id: ""
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
value: "large",
|
|
262
|
+
name: "Large",
|
|
263
|
+
id: ""
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
value: "fit",
|
|
267
|
+
name: "Fit",
|
|
268
|
+
id: ""
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: attrTooltipVis,
|
|
274
|
+
label: "Visible",
|
|
275
|
+
type: "checkbox",
|
|
276
|
+
valueTrue: "true"
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: traitIdStyleTooltip,
|
|
280
|
+
labelButton: "Style tooltip",
|
|
281
|
+
type: "button",
|
|
282
|
+
full: true,
|
|
283
|
+
command: (editor2) => {
|
|
284
|
+
const openSm = editor2.Panels.getButton("views", "open-sm");
|
|
285
|
+
openSm?.set("active", true);
|
|
286
|
+
const ruleTooltip = editor2.Css.getRules(`.${classTooltipBody}`)[0];
|
|
287
|
+
ruleTooltip.set("stylable", stylableTooltip);
|
|
288
|
+
editor2.StyleManager.select(ruleTooltip);
|
|
289
|
+
if (showTooltipOnStyle) {
|
|
290
|
+
const selected = editor2.getSelected();
|
|
291
|
+
if (selected?.is(id)) {
|
|
292
|
+
selected.addAttributes({ [attrTooltipVis]: "true" });
|
|
293
|
+
editor2.once("style:target", () => {
|
|
294
|
+
selected.addAttributes({ [attrTooltipVis]: "false" });
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
]),
|
|
301
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
302
|
+
...propsTooltip
|
|
303
|
+
},
|
|
304
|
+
init() {
|
|
305
|
+
this.listenTo(this.components(), "add remove", this.checkEmpty);
|
|
306
|
+
this.checkEmpty();
|
|
307
|
+
},
|
|
308
|
+
checkEmpty() {
|
|
309
|
+
const empty = !this.components().length;
|
|
310
|
+
this[empty ? "addClass" : "removeClass"](`${classTooltipEmpty}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
var tooltip_default = plugin;
|
|
316
|
+
export {
|
|
317
|
+
tooltip_default as default
|
|
318
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Component, Plugin } from 'grapesjs';
|
|
2
|
+
type ImageEditor = tuiImageEditor.ImageEditor;
|
|
3
|
+
type IOptions = tuiImageEditor.IOptions;
|
|
4
|
+
export type PluginOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* TOAST UI's configurations
|
|
7
|
+
* https://nhn.github.io/tui.image-editor/latest/ImageEditor
|
|
8
|
+
*/
|
|
9
|
+
config?: IOptions;
|
|
10
|
+
/**
|
|
11
|
+
* Pass the editor constructor.
|
|
12
|
+
* By default, the `tui.ImageEditor` will be used.
|
|
13
|
+
*/
|
|
14
|
+
constructor?: any;
|
|
15
|
+
/**
|
|
16
|
+
* Label for the image editor (used in the modal)
|
|
17
|
+
* @default 'Image Editor'
|
|
18
|
+
*/
|
|
19
|
+
labelImageEditor?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Label used on the apply button
|
|
22
|
+
* @default 'Apply'
|
|
23
|
+
*/
|
|
24
|
+
labelApply?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Default editor height
|
|
27
|
+
* @default '650px'
|
|
28
|
+
*/
|
|
29
|
+
height?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Default editor width
|
|
32
|
+
* @default '100%'
|
|
33
|
+
*/
|
|
34
|
+
width?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Id to use to create the image editor command
|
|
37
|
+
* @default 'tui-image-editor'
|
|
38
|
+
*/
|
|
39
|
+
commandId?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Icon used in the image component toolbar. Pass an empty string to avoid adding the icon.
|
|
42
|
+
*/
|
|
43
|
+
toolbarIcon?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Hide the default editor header
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
hideHeader?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* By default, GrapesJS takes the modified image, adds it to the Asset Manager and update the target.
|
|
51
|
+
* If you need some custom logic you can use this custom 'onApply' function.
|
|
52
|
+
* @example
|
|
53
|
+
* onApply: (imageEditor, imageModel) => {
|
|
54
|
+
* const dataUrl = imageEditor.toDataURL();
|
|
55
|
+
* editor.AssetManager.add({ src: dataUrl }); // Add it to Assets
|
|
56
|
+
* imageModel.set('src', dataUrl); // Update the image component
|
|
57
|
+
* }
|
|
58
|
+
*/
|
|
59
|
+
onApply?: ((imageEditor: ImageEditor, imageModel: Component) => void) | null;
|
|
60
|
+
/**
|
|
61
|
+
* If no custom `onApply` is passed and this option is `true`, the result image will be added to assets
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
addToAssets?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* If no custom `onApply` is passed, on confirm, the edited image, will be passed to the
|
|
67
|
+
* AssetManager's uploader and the result (eg. instead of having the dataURL you'll have the URL)
|
|
68
|
+
* will be passed to the default `onApply` process (update target, etc.)
|
|
69
|
+
*/
|
|
70
|
+
upload?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The apply button (HTMLElement) will be passed as an argument to this function, once created.
|
|
73
|
+
* This will allow you a higher customization.
|
|
74
|
+
*/
|
|
75
|
+
onApplyButton?: (btn: HTMLElement) => void;
|
|
76
|
+
/**
|
|
77
|
+
* Scripts to load dynamically in case no TOAST UI editor instance was found
|
|
78
|
+
*/
|
|
79
|
+
script?: string[];
|
|
80
|
+
/**
|
|
81
|
+
* In case the script is loaded this style will be loaded too
|
|
82
|
+
*/
|
|
83
|
+
style?: string[];
|
|
84
|
+
};
|
|
85
|
+
declare const plugin: Plugin<PluginOptions>;
|
|
86
|
+
export default plugin;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
const plugin = (editor, options = {}) => {
|
|
2
|
+
const opts = {
|
|
3
|
+
config: {},
|
|
4
|
+
constructor: "",
|
|
5
|
+
labelImageEditor: "Image Editor",
|
|
6
|
+
labelApply: "Apply",
|
|
7
|
+
height: "650px",
|
|
8
|
+
width: "100%",
|
|
9
|
+
commandId: "tui-image-editor",
|
|
10
|
+
toolbarIcon: `<svg viewBox="0 0 24 24">
|
|
11
|
+
<path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z">
|
|
12
|
+
</path>
|
|
13
|
+
</svg>`,
|
|
14
|
+
hideHeader: true,
|
|
15
|
+
addToAssets: true,
|
|
16
|
+
upload: false,
|
|
17
|
+
onApplyButton: () => {
|
|
18
|
+
},
|
|
19
|
+
onApply: null,
|
|
20
|
+
script: [
|
|
21
|
+
"https://uicdn.toast.com/tui.code-snippet/v1.5.2/tui-code-snippet.min.js",
|
|
22
|
+
"https://uicdn.toast.com/tui-color-picker/v2.2.7/tui-color-picker.min.js",
|
|
23
|
+
"https://uicdn.toast.com/tui-image-editor/v3.15.2/tui-image-editor.min.js"
|
|
24
|
+
],
|
|
25
|
+
style: [
|
|
26
|
+
"https://uicdn.toast.com/tui-color-picker/v2.2.7/tui-color-picker.min.css",
|
|
27
|
+
"https://uicdn.toast.com/tui-image-editor/v3.15.2/tui-image-editor.min.css"
|
|
28
|
+
],
|
|
29
|
+
...options
|
|
30
|
+
};
|
|
31
|
+
const { script, style, height, width, hideHeader, onApply, upload, addToAssets, commandId } = opts;
|
|
32
|
+
const hasWindow = typeof window !== "undefined";
|
|
33
|
+
const getConstructor = () => {
|
|
34
|
+
return opts.constructor || hasWindow && window.tui?.ImageEditor;
|
|
35
|
+
};
|
|
36
|
+
let constr = getConstructor();
|
|
37
|
+
if (!constr && script?.length && hasWindow) {
|
|
38
|
+
const { head } = document;
|
|
39
|
+
const scripts = Array.isArray(script) ? [...script] : [script];
|
|
40
|
+
const styles = Array.isArray(style) ? [...style] : [style];
|
|
41
|
+
const appendStyle = (styles2) => {
|
|
42
|
+
if (styles2.length) {
|
|
43
|
+
const link = document.createElement("link");
|
|
44
|
+
link.href = styles2.shift();
|
|
45
|
+
link.rel = "stylesheet";
|
|
46
|
+
head.appendChild(link);
|
|
47
|
+
appendStyle(styles2);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const appendScript = (scripts2) => {
|
|
51
|
+
if (scripts2.length) {
|
|
52
|
+
const scr = document.createElement("script");
|
|
53
|
+
scr.src = scripts2.shift();
|
|
54
|
+
scr.onerror = scr.onload = appendScript.bind(null, scripts2);
|
|
55
|
+
head.appendChild(scr);
|
|
56
|
+
} else {
|
|
57
|
+
constr = getConstructor();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
appendStyle(styles);
|
|
61
|
+
appendScript(scripts);
|
|
62
|
+
}
|
|
63
|
+
if (opts.toolbarIcon) {
|
|
64
|
+
editor.Components.addType("image", {
|
|
65
|
+
extendFn: ["initToolbar"],
|
|
66
|
+
model: {
|
|
67
|
+
initToolbar() {
|
|
68
|
+
const tb = this.get("toolbar");
|
|
69
|
+
const tbExists = tb?.some((item) => item.command === commandId);
|
|
70
|
+
if (!tbExists) {
|
|
71
|
+
tb?.unshift({
|
|
72
|
+
command: commandId,
|
|
73
|
+
label: opts.toolbarIcon
|
|
74
|
+
});
|
|
75
|
+
this.set("toolbar", tb);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const errorOpts = { level: "error", ns: commandId };
|
|
82
|
+
editor.Commands.add(commandId, {
|
|
83
|
+
imageEditor: null,
|
|
84
|
+
run(ed, s, options2 = {}) {
|
|
85
|
+
if (!constr) {
|
|
86
|
+
ed.log("TOAST UI Image editor not found", errorOpts);
|
|
87
|
+
return ed.stopCommand(commandId);
|
|
88
|
+
}
|
|
89
|
+
const target = options2.target || ed.getSelected();
|
|
90
|
+
if (!target) {
|
|
91
|
+
ed.log("Target not available", errorOpts);
|
|
92
|
+
return ed.stopCommand(commandId);
|
|
93
|
+
}
|
|
94
|
+
const content = this.createContent();
|
|
95
|
+
const title = opts.labelImageEditor;
|
|
96
|
+
const btn = content.children[1];
|
|
97
|
+
ed.Modal.open({ title, content }).onceClose(() => ed.stopCommand(commandId));
|
|
98
|
+
const editorConfig = this.getEditorConfig(target.get("src"));
|
|
99
|
+
this.imageEditor = new constr(content.children[0], editorConfig);
|
|
100
|
+
ed.getModel().setEditing(true);
|
|
101
|
+
btn.onclick = () => this.applyChanges(target);
|
|
102
|
+
opts.onApplyButton(btn);
|
|
103
|
+
},
|
|
104
|
+
stop(ed) {
|
|
105
|
+
this.imageEditor?.destroy();
|
|
106
|
+
ed.getModel().setEditing(false);
|
|
107
|
+
},
|
|
108
|
+
getEditorConfig(path) {
|
|
109
|
+
const config = { ...opts.config };
|
|
110
|
+
if (!config.includeUI) config.includeUI = {};
|
|
111
|
+
config.includeUI = {
|
|
112
|
+
theme: {},
|
|
113
|
+
...config.includeUI,
|
|
114
|
+
loadImage: { path, name: "1" },
|
|
115
|
+
uiSize: { height, width }
|
|
116
|
+
};
|
|
117
|
+
if (hideHeader) {
|
|
118
|
+
config.includeUI.theme["header.display"] = "none";
|
|
119
|
+
}
|
|
120
|
+
return config;
|
|
121
|
+
},
|
|
122
|
+
createContent() {
|
|
123
|
+
const content = document.createElement("div");
|
|
124
|
+
content.style.position = "relative";
|
|
125
|
+
content.innerHTML = `
|
|
126
|
+
<div></div>
|
|
127
|
+
<button class="tui-image-editor__apply-btn" style="
|
|
128
|
+
position: absolute;
|
|
129
|
+
top: 0; right: 0;
|
|
130
|
+
margin: 10px;
|
|
131
|
+
background-color: #fff;
|
|
132
|
+
font-size: 1rem;
|
|
133
|
+
border-radius: 3px;
|
|
134
|
+
border: none;
|
|
135
|
+
padding: 10px 20px;
|
|
136
|
+
cursor: pointer
|
|
137
|
+
">
|
|
138
|
+
${opts.labelApply}
|
|
139
|
+
</button>
|
|
140
|
+
`;
|
|
141
|
+
return content;
|
|
142
|
+
},
|
|
143
|
+
applyChanges(target) {
|
|
144
|
+
const ied = this.imageEditor;
|
|
145
|
+
if (onApply) {
|
|
146
|
+
onApply(ied, target);
|
|
147
|
+
} else {
|
|
148
|
+
if (ied.getDrawingMode() === "CROPPER") {
|
|
149
|
+
ied.crop(ied.getCropzoneRect()).then(() => {
|
|
150
|
+
this.uploadImage(ied, target);
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
this.uploadImage(ied, target);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
uploadImage(imageEditor, target) {
|
|
158
|
+
const am = editor.Assets;
|
|
159
|
+
const dataURL = imageEditor.toDataURL();
|
|
160
|
+
if (upload) {
|
|
161
|
+
const file = this.dataUrlToBlob(dataURL);
|
|
162
|
+
am.FileUploader().uploadFile(
|
|
163
|
+
{
|
|
164
|
+
dataTransfer: {
|
|
165
|
+
// @ts-ignore
|
|
166
|
+
files: [file]
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
170
|
+
(res) => {
|
|
171
|
+
const obj = res?.data?.[0];
|
|
172
|
+
const src = obj && (typeof obj === "string" ? obj : obj.src);
|
|
173
|
+
src && this.applyToTarget(src, target);
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
addToAssets && am.add({
|
|
178
|
+
src: dataURL,
|
|
179
|
+
name: (target.get("src") || "").split("/").pop()
|
|
180
|
+
});
|
|
181
|
+
this.applyToTarget(dataURL, target);
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
applyToTarget(result, target) {
|
|
185
|
+
target.set("src", result);
|
|
186
|
+
editor.Modal.close();
|
|
187
|
+
},
|
|
188
|
+
dataUrlToBlob(dataURL) {
|
|
189
|
+
const data = dataURL.split(",");
|
|
190
|
+
const byteStr = window.atob(data[1]);
|
|
191
|
+
const type = data[0].split(":")[1].split(";")[0];
|
|
192
|
+
const ab = new ArrayBuffer(byteStr.length);
|
|
193
|
+
const ia = new Uint8Array(ab);
|
|
194
|
+
for (let i = 0; i < byteStr.length; i++) {
|
|
195
|
+
ia[i] = byteStr.charCodeAt(i);
|
|
196
|
+
}
|
|
197
|
+
return new Blob([ab], { type });
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
var tuiImageEditor_default = plugin;
|
|
202
|
+
export {
|
|
203
|
+
tuiImageEditor_default as default
|
|
204
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cmpId } from "./utils.js";
|
|
2
|
+
var blocks_default = (editor, opts) => {
|
|
3
|
+
const bm = editor.BlockManager;
|
|
4
|
+
const { block } = opts;
|
|
5
|
+
block && bm.add(cmpId, {
|
|
6
|
+
label: "Typed",
|
|
7
|
+
media: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><path d="M212.3 44l2.3 49.6h-6A60 60 0 00204 75c-3.2-6-7.5-10.5-12.9-13.3a44.9 44.9 0 00-21.1-4.3h-29.8V219c0 13 1.4 21 4.2 24.3 4 4.4 10 6.6 18.2 6.6h7.4v5.7H80.2V250h7.5c9 0 15.3-2.7 19-8.2 2.4-3.3 3.5-10.9 3.5-22.7V57.3H84.8a71 71 0 00-21.1 2.2 29 29 0 00-13.9 11.3 46.1 46.1 0 00-6.9 22.8H37L39.5 44h172.8zM245 22h18v256h-18z"/></svg>',
|
|
8
|
+
content: { type: cmpId },
|
|
9
|
+
select: true,
|
|
10
|
+
...block
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
blocks_default as default
|
|
15
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Editor } from 'grapesjs';
|
|
2
|
+
import type { RequiredPluginOptions } from './index.js';
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
Typed: any;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
declare const _default: (editor: Editor, opts: RequiredPluginOptions) => void;
|
|
9
|
+
export default _default;
|