@lesjoursfr/edith 2.1.2 → 2.1.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/build/edith.css +1 -0
- package/build/edith.js +1 -0
- package/dist/core/edit.d.ts +44 -0
- package/dist/core/edit.js +327 -0
- package/dist/core/events.d.ts +4 -0
- package/dist/core/events.js +5 -0
- package/dist/core/history.d.ts +14 -0
- package/dist/core/history.js +24 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +5 -0
- package/dist/core/mode.d.ts +4 -0
- package/dist/core/mode.js +5 -0
- package/dist/core/range.d.ts +45 -0
- package/dist/core/range.js +86 -0
- package/dist/css/edith.scss +283 -0
- package/dist/edith-options.d.ts +17 -0
- package/dist/edith-options.js +56 -0
- package/dist/edith.d.ts +30 -0
- package/dist/edith.js +77 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/ui/button.d.ts +25 -0
- package/dist/ui/button.js +166 -0
- package/dist/ui/editor.d.ts +37 -0
- package/dist/ui/editor.js +323 -0
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/index.js +3 -0
- package/dist/ui/modal.d.ts +32 -0
- package/dist/ui/modal.js +145 -0
- package/package.json +12 -9
- package/src/core/edit.ts +94 -2
- package/src/core/events.ts +0 -144
- package/src/core/index.ts +0 -2
- package/src/core/range.ts +1 -1
- package/src/edith.ts +2 -1
- package/src/ui/button.ts +2 -1
- package/src/ui/editor.ts +12 -9
- package/src/ui/modal.ts +1 -1
- package/src/core/dom.ts +0 -584
- package/src/core/throttle.ts +0 -172
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
@use "sass:color";
|
|
2
|
+
|
|
3
|
+
$color-toolbar: #212529;
|
|
4
|
+
$color-toolbar-border: #212529;
|
|
5
|
+
$color-button: #e9ecef;
|
|
6
|
+
$color-button-border: #ced4da;
|
|
7
|
+
$color-button-text: #212529;
|
|
8
|
+
$color-tooltip: #000;
|
|
9
|
+
$color-tooltip-text: #fff;
|
|
10
|
+
$color-editor: #fff;
|
|
11
|
+
$color-editor-text: #212529;
|
|
12
|
+
$color-modal: #fff;
|
|
13
|
+
$color-modal-border: #ced4da;
|
|
14
|
+
$color-modal-title: #000;
|
|
15
|
+
$color-modal-text: #212529;
|
|
16
|
+
$color-input-border: #bfbfbf;
|
|
17
|
+
$color-checkbox-background: #0d6efd;
|
|
18
|
+
$color-checkbox-border: #bfbfbf;
|
|
19
|
+
$color-modal-cancel-background: #fff;
|
|
20
|
+
$color-modal-cancel-color: #212529;
|
|
21
|
+
$color-modal-cancel-border: #212529;
|
|
22
|
+
$color-modal-submit-background: #0d6efd;
|
|
23
|
+
$color-modal-submit-color: #fff;
|
|
24
|
+
$color-modal-submit-border: #0d6efd;
|
|
25
|
+
|
|
26
|
+
.edith {
|
|
27
|
+
background-color: $color-toolbar;
|
|
28
|
+
border: 1px solid $color-toolbar-border;
|
|
29
|
+
border-radius: 0.25rem;
|
|
30
|
+
padding: 5px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.edith-toolbar {
|
|
34
|
+
background-color: $color-toolbar;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.edith-btn {
|
|
38
|
+
background-color: $color-button;
|
|
39
|
+
border: 1px solid $color-button-border;
|
|
40
|
+
border-radius: 0.25rem;
|
|
41
|
+
color: $color-button-text;
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
display: inline-block;
|
|
44
|
+
font-size: 1rem;
|
|
45
|
+
font-weight: 900;
|
|
46
|
+
line-height: 1.5;
|
|
47
|
+
padding: 0.375rem 0.75rem;
|
|
48
|
+
text-align: center;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
user-select: none;
|
|
51
|
+
vertical-align: middle;
|
|
52
|
+
|
|
53
|
+
&:disabled {
|
|
54
|
+
color: color.scale($color-button-text, $lightness: 70%);
|
|
55
|
+
cursor: not-allowed;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.edith-btn-group {
|
|
60
|
+
display: inline-flex;
|
|
61
|
+
position: relative;
|
|
62
|
+
vertical-align: middle;
|
|
63
|
+
|
|
64
|
+
&:not(:first-child) {
|
|
65
|
+
margin-left: 10px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:not(:first-child) {
|
|
69
|
+
margin-left: -1px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.edith-btn:not(:last-child) {
|
|
73
|
+
border-bottom-right-radius: 0;
|
|
74
|
+
border-top-right-radius: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.edith-btn:not(:first-child) {
|
|
78
|
+
border-bottom-left-radius: 0;
|
|
79
|
+
border-top-left-radius: 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.edith-btn-nbsp {
|
|
84
|
+
&::before {
|
|
85
|
+
content: "\0020";
|
|
86
|
+
display: block;
|
|
87
|
+
height: 16px;
|
|
88
|
+
width: 12px;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.edith-tooltip {
|
|
93
|
+
background: $color-tooltip;
|
|
94
|
+
border-radius: 4px;
|
|
95
|
+
color: $color-tooltip-text;
|
|
96
|
+
font-size: 13px;
|
|
97
|
+
font-weight: bold;
|
|
98
|
+
padding: 4px 8px;
|
|
99
|
+
z-index: 10;
|
|
100
|
+
|
|
101
|
+
.arrow,
|
|
102
|
+
.arrow::before {
|
|
103
|
+
background: inherit;
|
|
104
|
+
height: 8px;
|
|
105
|
+
position: absolute;
|
|
106
|
+
width: 8px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.arrow {
|
|
110
|
+
visibility: hidden;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.arrow::before {
|
|
114
|
+
content: "";
|
|
115
|
+
transform: rotate(45deg);
|
|
116
|
+
visibility: visible;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&[data-popper-placement^="top"] > .arrow {
|
|
120
|
+
bottom: -4px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&[data-popper-placement^="bottom"] > .arrow {
|
|
124
|
+
top: -4px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&[data-popper-placement^="left"] > .arrow {
|
|
128
|
+
right: -4px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
&[data-popper-placement^="right"] > .arrow {
|
|
132
|
+
left: -4px;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.edith-editing-area {
|
|
137
|
+
background-color: $color-editor;
|
|
138
|
+
border-radius: 0.25rem;
|
|
139
|
+
margin-top: 5px;
|
|
140
|
+
padding: 5px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.edith-visual,
|
|
144
|
+
.edith-code {
|
|
145
|
+
height: 100%;
|
|
146
|
+
outline: none;
|
|
147
|
+
overflow: auto;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.edith-hidden {
|
|
151
|
+
display: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.edith-visual {
|
|
155
|
+
color: $color-editor-text;
|
|
156
|
+
|
|
157
|
+
.edith-nbsp {
|
|
158
|
+
color: color.scale($color-button-text, $lightness: 70%);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.edith-modal {
|
|
163
|
+
background: $color-modal;
|
|
164
|
+
border: 2px solid $color-modal-border;
|
|
165
|
+
border-radius: 10px;
|
|
166
|
+
left: calc(50% - 200px);
|
|
167
|
+
position: fixed;
|
|
168
|
+
top: 20%;
|
|
169
|
+
width: 400px;
|
|
170
|
+
z-index: 10;
|
|
171
|
+
|
|
172
|
+
.edith-modal-header {
|
|
173
|
+
border-bottom: 1px solid $color-modal-border;
|
|
174
|
+
color: $color-modal-title;
|
|
175
|
+
font-size: 20px;
|
|
176
|
+
font-weight: 700;
|
|
177
|
+
line-height: 1.4;
|
|
178
|
+
padding: 5px 10px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.edith-modal-content {
|
|
182
|
+
color: $color-modal-text;
|
|
183
|
+
margin: 10px;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.edith-modal-input {
|
|
187
|
+
display: flex;
|
|
188
|
+
flex-wrap: wrap;
|
|
189
|
+
margin: 10px 0;
|
|
190
|
+
|
|
191
|
+
label,
|
|
192
|
+
input {
|
|
193
|
+
width: 100%;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
input {
|
|
197
|
+
appearance: none;
|
|
198
|
+
background-clip: padding-box;
|
|
199
|
+
background-color: $color-modal;
|
|
200
|
+
border: 1px solid $color-checkbox-border;
|
|
201
|
+
border-radius: 0.25rem;
|
|
202
|
+
font-size: 1rem;
|
|
203
|
+
font-weight: 400;
|
|
204
|
+
line-height: 1.5;
|
|
205
|
+
outline: 0;
|
|
206
|
+
padding: 0.375rem 0.75rem;
|
|
207
|
+
width: 100%;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
label {
|
|
211
|
+
font-size: 16px;
|
|
212
|
+
font-weight: 700;
|
|
213
|
+
margin-bottom: 5px;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.edith-modal-checkbox {
|
|
218
|
+
margin: 10px 0;
|
|
219
|
+
|
|
220
|
+
label {
|
|
221
|
+
display: flex;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
input {
|
|
225
|
+
appearance: none;
|
|
226
|
+
background-color: $color-modal;
|
|
227
|
+
background-position: 50%;
|
|
228
|
+
background-repeat: no-repeat;
|
|
229
|
+
background-size: contain;
|
|
230
|
+
border: 1px solid $color-checkbox-border;
|
|
231
|
+
border-radius: 0.25em;
|
|
232
|
+
height: 1em;
|
|
233
|
+
margin-top: 0.25em;
|
|
234
|
+
vertical-align: top;
|
|
235
|
+
width: 1em;
|
|
236
|
+
|
|
237
|
+
&:checked {
|
|
238
|
+
background-color: $color-checkbox-background;
|
|
239
|
+
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3E%3C/svg%3E");
|
|
240
|
+
border-color: $color-checkbox-background;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.edith-modal-footer {
|
|
246
|
+
border-top: 1px solid $color-modal-border;
|
|
247
|
+
display: flex;
|
|
248
|
+
justify-content: flex-end;
|
|
249
|
+
padding: 5px 10px;
|
|
250
|
+
|
|
251
|
+
:not(:last-child) {
|
|
252
|
+
margin-right: 10px;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.edith-modal-cancel,
|
|
257
|
+
.edith-modal-submit {
|
|
258
|
+
border: 1px solid transparent;
|
|
259
|
+
border-radius: 0.25rem;
|
|
260
|
+
cursor: pointer;
|
|
261
|
+
display: inline-block;
|
|
262
|
+
font-size: 1rem;
|
|
263
|
+
font-weight: 400;
|
|
264
|
+
line-height: 1.5;
|
|
265
|
+
padding: 0.375rem 0.75rem;
|
|
266
|
+
text-align: center;
|
|
267
|
+
text-decoration: none;
|
|
268
|
+
user-select: none;
|
|
269
|
+
vertical-align: middle;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.edith-modal-cancel {
|
|
273
|
+
background-color: $color-modal-cancel-background;
|
|
274
|
+
border-color: $color-modal-cancel-border;
|
|
275
|
+
color: $color-modal-cancel-color;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.edith-modal-submit {
|
|
279
|
+
background-color: $color-modal-submit-background;
|
|
280
|
+
border-color: $color-modal-submit-border;
|
|
281
|
+
color: $color-modal-submit-color;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Edith } from "./edith.js";
|
|
2
|
+
import { EdithButton } from "./ui/index.js";
|
|
3
|
+
export type EdithToolbarOption = [string, string[]][];
|
|
4
|
+
export type EdithButtonsOption = {
|
|
5
|
+
[keyof: string]: (context: Edith) => EdithButton;
|
|
6
|
+
};
|
|
7
|
+
export type EdithOptions = {
|
|
8
|
+
height: number;
|
|
9
|
+
resizable: boolean;
|
|
10
|
+
toolbar: EdithToolbarOption;
|
|
11
|
+
buttons: EdithButtonsOption;
|
|
12
|
+
initialContent: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Edith default options
|
|
16
|
+
*/
|
|
17
|
+
export declare const DefaultOptions: EdithOptions;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edith default options
|
|
3
|
+
*/
|
|
4
|
+
export const DefaultOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* The editor's height
|
|
7
|
+
*
|
|
8
|
+
* @type {number}
|
|
9
|
+
* @default 80
|
|
10
|
+
*/
|
|
11
|
+
height: 80,
|
|
12
|
+
/**
|
|
13
|
+
* Control if the editor can be resized by the user
|
|
14
|
+
*
|
|
15
|
+
* @type {boolean}
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
resizable: false,
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* An array that define which button is shown in the toolbar and how they are grouped.
|
|
22
|
+
*
|
|
23
|
+
* @type {EdithToolbarOption}
|
|
24
|
+
* @example
|
|
25
|
+
* toolbar: [
|
|
26
|
+
* ["style", ["bold", "italic", "underline", "strikethrough"]],
|
|
27
|
+
* ["extra", ["subscript", "superscript"]]
|
|
28
|
+
* ]
|
|
29
|
+
*/
|
|
30
|
+
toolbar: [["style", ["bold", "italic", "underline", "strikethrough"]]],
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* Associative object with the button name and builder to create it.
|
|
34
|
+
*
|
|
35
|
+
* @type {EdithButtonsOption}
|
|
36
|
+
* @example
|
|
37
|
+
* buttons: {
|
|
38
|
+
* bold: (context: Edith) =>
|
|
39
|
+
* new EdithButton(context, {
|
|
40
|
+
* icon: "fa-solid fa-bold",
|
|
41
|
+
* title: "Gras",
|
|
42
|
+
* onclick: (ctx: Edith, event: Event) => {
|
|
43
|
+
* ctx.editor.wrapInsideTag("b");
|
|
44
|
+
* },
|
|
45
|
+
* }),
|
|
46
|
+
* }
|
|
47
|
+
*/
|
|
48
|
+
buttons: {},
|
|
49
|
+
/**
|
|
50
|
+
* The editor's initial content
|
|
51
|
+
*
|
|
52
|
+
* @type {string}
|
|
53
|
+
* @default ""
|
|
54
|
+
*/
|
|
55
|
+
initialContent: "",
|
|
56
|
+
};
|
package/dist/edith.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Events } from "./core/index.js";
|
|
2
|
+
import { EdithOptions } from "./edith-options.js";
|
|
3
|
+
import { EdithButton, EdithEditor } from "./ui/index.js";
|
|
4
|
+
declare global {
|
|
5
|
+
interface HTMLElement {
|
|
6
|
+
edith?: Edith;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export { EdithButton };
|
|
10
|
+
export declare class Edith {
|
|
11
|
+
private readonly element;
|
|
12
|
+
readonly toolbar: HTMLDivElement;
|
|
13
|
+
readonly editor: EdithEditor;
|
|
14
|
+
readonly modals: HTMLDivElement;
|
|
15
|
+
/**
|
|
16
|
+
* Create a new editor
|
|
17
|
+
* @constructor
|
|
18
|
+
* @param {HTMLElement} element - The <input> element to add the Wysiwyg to.
|
|
19
|
+
* @param {Object} options - Options for the editor.
|
|
20
|
+
*/
|
|
21
|
+
constructor(element: HTMLElement, options: Partial<EdithOptions>);
|
|
22
|
+
on(type: string, listener: EventListenerOrEventListenerObject): void;
|
|
23
|
+
off(type: string, listener: EventListenerOrEventListenerObject): void;
|
|
24
|
+
trigger(type: Events, payload?: {
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}): void;
|
|
27
|
+
setContent(content: string): void;
|
|
28
|
+
getContent(): string;
|
|
29
|
+
destroy(): void;
|
|
30
|
+
}
|
package/dist/edith.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { addClass, createNodeWith, off, on, removeClass, trigger } from "@lesjoursfr/browser-tools";
|
|
2
|
+
import { Events } from "./core/index.js";
|
|
3
|
+
import { DefaultOptions } from "./edith-options.js";
|
|
4
|
+
import { EdithButton, EdithButtons, EdithEditor } from "./ui/index.js";
|
|
5
|
+
export { EdithButton };
|
|
6
|
+
export class Edith {
|
|
7
|
+
element;
|
|
8
|
+
toolbar;
|
|
9
|
+
editor;
|
|
10
|
+
modals;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new editor
|
|
13
|
+
* @constructor
|
|
14
|
+
* @param {HTMLElement} element - The <input> element to add the Wysiwyg to.
|
|
15
|
+
* @param {Object} options - Options for the editor.
|
|
16
|
+
*/
|
|
17
|
+
constructor(element, options) {
|
|
18
|
+
// Render the editor in the element
|
|
19
|
+
this.element = element;
|
|
20
|
+
addClass(this.element, "edith");
|
|
21
|
+
// Create the toolbar
|
|
22
|
+
this.toolbar = createNodeWith("div", { attributes: { class: "edith-toolbar" } });
|
|
23
|
+
this.element.append(this.toolbar);
|
|
24
|
+
// Create buttons
|
|
25
|
+
const buttons = options.buttons ?? DefaultOptions.buttons;
|
|
26
|
+
const toolbar = options.toolbar ?? DefaultOptions.toolbar;
|
|
27
|
+
for (const { 0: group, 1: btns } of toolbar) {
|
|
28
|
+
// Create the button group
|
|
29
|
+
const btnGroup = document.createElement("div");
|
|
30
|
+
btnGroup.setAttribute("id", group);
|
|
31
|
+
btnGroup.setAttribute("class", "edith-btn-group");
|
|
32
|
+
this.toolbar.append(btnGroup);
|
|
33
|
+
// Add buttons
|
|
34
|
+
for (const btnId of btns) {
|
|
35
|
+
// Render the button
|
|
36
|
+
const buttonBuilder = buttons[btnId] ?? EdithButtons[btnId];
|
|
37
|
+
btnGroup.append(buttonBuilder(this).render());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Create the editor
|
|
41
|
+
this.editor = new EdithEditor(this, {
|
|
42
|
+
initialContent: options.initialContent ?? DefaultOptions.initialContent,
|
|
43
|
+
height: options.height ?? DefaultOptions.height,
|
|
44
|
+
resizable: options.resizable ?? DefaultOptions.resizable,
|
|
45
|
+
});
|
|
46
|
+
this.element.append(this.editor.render());
|
|
47
|
+
// Create the modals
|
|
48
|
+
this.modals = createNodeWith("div", { attributes: { class: "edith-modals" } });
|
|
49
|
+
this.element.append(this.modals);
|
|
50
|
+
// Add the Edith instance to the DOM
|
|
51
|
+
this.element.edith = this;
|
|
52
|
+
// Trigger the initialized event once its initialized
|
|
53
|
+
this.trigger(Events.initialized);
|
|
54
|
+
}
|
|
55
|
+
on(type, listener) {
|
|
56
|
+
on(this.element, type, listener);
|
|
57
|
+
}
|
|
58
|
+
off(type, listener) {
|
|
59
|
+
off(this.element, type, listener);
|
|
60
|
+
}
|
|
61
|
+
trigger(type, payload) {
|
|
62
|
+
trigger(this.element, type, payload);
|
|
63
|
+
}
|
|
64
|
+
setContent(content) {
|
|
65
|
+
this.editor.setContent(content);
|
|
66
|
+
}
|
|
67
|
+
getContent() {
|
|
68
|
+
return this.editor.getContent();
|
|
69
|
+
}
|
|
70
|
+
destroy() {
|
|
71
|
+
removeClass(this.element, "edith");
|
|
72
|
+
this.modals.remove();
|
|
73
|
+
this.editor.destroy();
|
|
74
|
+
this.toolbar.remove();
|
|
75
|
+
this.element.remove();
|
|
76
|
+
}
|
|
77
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./edith.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./edith.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EdithButtonsOption } from "../edith-options.js";
|
|
2
|
+
import { Edith } from "../edith.js";
|
|
3
|
+
export type EdithButtonCallback = (ctx: Edith, event: Event) => void;
|
|
4
|
+
export declare class EdithButton {
|
|
5
|
+
private el;
|
|
6
|
+
private ctx;
|
|
7
|
+
private icon;
|
|
8
|
+
private title;
|
|
9
|
+
private onclick;
|
|
10
|
+
private showOnCodeView;
|
|
11
|
+
private popperEl;
|
|
12
|
+
private popper;
|
|
13
|
+
constructor(ctx: Edith, options: {
|
|
14
|
+
icon: string;
|
|
15
|
+
title: string;
|
|
16
|
+
onclick: EdithButtonCallback;
|
|
17
|
+
showOnCodeView?: boolean;
|
|
18
|
+
});
|
|
19
|
+
click(event: Event): void;
|
|
20
|
+
showTooltip(): void;
|
|
21
|
+
hideTooltip(): void;
|
|
22
|
+
onEditorModeChange(event: CustomEvent): void;
|
|
23
|
+
render(): HTMLButtonElement;
|
|
24
|
+
}
|
|
25
|
+
export declare const EdithButtons: Readonly<EdithButtonsOption>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { createNodeWith } from "@lesjoursfr/browser-tools";
|
|
2
|
+
import { createPopper } from "@popperjs/core";
|
|
3
|
+
import { EditorModes, Events } from "../core/index.js";
|
|
4
|
+
export class EdithButton {
|
|
5
|
+
el;
|
|
6
|
+
ctx;
|
|
7
|
+
icon;
|
|
8
|
+
title;
|
|
9
|
+
onclick;
|
|
10
|
+
showOnCodeView;
|
|
11
|
+
popperEl;
|
|
12
|
+
popper;
|
|
13
|
+
constructor(ctx, options) {
|
|
14
|
+
this.ctx = ctx;
|
|
15
|
+
this.icon = options.icon;
|
|
16
|
+
this.title = options.title;
|
|
17
|
+
this.onclick = options.onclick;
|
|
18
|
+
this.showOnCodeView = options.showOnCodeView === true;
|
|
19
|
+
}
|
|
20
|
+
click(event) {
|
|
21
|
+
// Prevent default
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
// Call the callback
|
|
24
|
+
this.onclick(this.ctx, event);
|
|
25
|
+
}
|
|
26
|
+
showTooltip() {
|
|
27
|
+
if (this.popper !== undefined) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Add the tooltip content to the DOM
|
|
31
|
+
this.popperEl = createNodeWith("div", {
|
|
32
|
+
textContent: this.title,
|
|
33
|
+
attributes: { class: "edith-tooltip" },
|
|
34
|
+
});
|
|
35
|
+
const arrowEl = createNodeWith("div", {
|
|
36
|
+
attributes: { class: "arrow", "data-popper-arrow": "" },
|
|
37
|
+
});
|
|
38
|
+
this.popperEl.append(arrowEl);
|
|
39
|
+
this.ctx.toolbar.append(this.popperEl);
|
|
40
|
+
// Create the tooltip
|
|
41
|
+
this.popper = createPopper(this.el, this.popperEl, {
|
|
42
|
+
placement: "bottom",
|
|
43
|
+
modifiers: [
|
|
44
|
+
{
|
|
45
|
+
name: "arrow",
|
|
46
|
+
options: {
|
|
47
|
+
padding: 5, // 5px from the edges of the popper
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "offset",
|
|
52
|
+
options: {
|
|
53
|
+
offset: [0, 8],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
hideTooltip() {
|
|
60
|
+
if (this.popper === undefined) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Destroy the tooltip
|
|
64
|
+
this.popper.destroy();
|
|
65
|
+
this.popper = undefined;
|
|
66
|
+
// Remove the tooltip content from the DOM
|
|
67
|
+
this.popperEl?.remove();
|
|
68
|
+
}
|
|
69
|
+
onEditorModeChange(event) {
|
|
70
|
+
if (event.detail.mode === EditorModes.Code) {
|
|
71
|
+
this.el.setAttribute("disabled", "disabled");
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.el.removeAttribute("disabled");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
render() {
|
|
78
|
+
// Create the button
|
|
79
|
+
this.el = createNodeWith("button", {
|
|
80
|
+
attributes: { class: `edith-btn ${this.icon}`, type: "button" },
|
|
81
|
+
});
|
|
82
|
+
// Bind events
|
|
83
|
+
this.el.onclick = this.click.bind(this);
|
|
84
|
+
this.el.onmouseenter = this.showTooltip.bind(this);
|
|
85
|
+
this.el.onmouseleave = this.hideTooltip.bind(this);
|
|
86
|
+
// Check if we have to disable the button on the code view
|
|
87
|
+
if (this.showOnCodeView !== true) {
|
|
88
|
+
this.ctx.on(Events.modeChanged, this.onEditorModeChange.bind(this));
|
|
89
|
+
}
|
|
90
|
+
// Return the button
|
|
91
|
+
return this.el;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export const EdithButtons = Object.freeze({
|
|
95
|
+
bold: (context) => new EdithButton(context, {
|
|
96
|
+
icon: "fa-solid fa-bold",
|
|
97
|
+
title: "Gras",
|
|
98
|
+
onclick: (ctx) => {
|
|
99
|
+
ctx.editor.wrapInsideTag("b");
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
italic: (context) => new EdithButton(context, {
|
|
103
|
+
icon: "fa-solid fa-italic",
|
|
104
|
+
title: "Italique",
|
|
105
|
+
onclick: (ctx) => {
|
|
106
|
+
ctx.editor.wrapInsideTag("i");
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
underline: (context) => new EdithButton(context, {
|
|
110
|
+
icon: "fa-solid fa-underline",
|
|
111
|
+
title: "Souligner",
|
|
112
|
+
onclick: (ctx) => {
|
|
113
|
+
ctx.editor.wrapInsideTag("u");
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
strikethrough: (context) => new EdithButton(context, {
|
|
117
|
+
icon: "fa-solid fa-strikethrough",
|
|
118
|
+
title: "Barrer",
|
|
119
|
+
onclick: (ctx) => {
|
|
120
|
+
ctx.editor.wrapInsideTag("s");
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
subscript: (context) => new EdithButton(context, {
|
|
124
|
+
icon: "fa-solid fa-subscript",
|
|
125
|
+
title: "Indice",
|
|
126
|
+
onclick: (ctx) => {
|
|
127
|
+
ctx.editor.wrapInsideTag("sub");
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
superscript: (context) => new EdithButton(context, {
|
|
131
|
+
icon: "fa-solid fa-superscript",
|
|
132
|
+
title: "Exposant",
|
|
133
|
+
onclick: (ctx) => {
|
|
134
|
+
ctx.editor.wrapInsideTag("sup");
|
|
135
|
+
},
|
|
136
|
+
}),
|
|
137
|
+
nbsp: (context) => new EdithButton(context, {
|
|
138
|
+
icon: "edith-btn-nbsp",
|
|
139
|
+
title: "Ajouter une espace insécable",
|
|
140
|
+
onclick: (ctx) => {
|
|
141
|
+
ctx.editor.replaceByHtml('<span class="edith-nbsp" contenteditable="false">¶</span>');
|
|
142
|
+
},
|
|
143
|
+
}),
|
|
144
|
+
clear: (context) => new EdithButton(context, {
|
|
145
|
+
icon: "fa-solid fa-eraser",
|
|
146
|
+
title: "Effacer la mise en forme",
|
|
147
|
+
onclick: (ctx) => {
|
|
148
|
+
ctx.editor.clearStyle();
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
link: (context) => new EdithButton(context, {
|
|
152
|
+
icon: "fa-solid fa-link",
|
|
153
|
+
title: "Lien",
|
|
154
|
+
onclick: (ctx) => {
|
|
155
|
+
ctx.editor.insertLink();
|
|
156
|
+
},
|
|
157
|
+
}),
|
|
158
|
+
codeview: (context) => new EdithButton(context, {
|
|
159
|
+
icon: "fa-solid fa-code",
|
|
160
|
+
title: "Afficher le code HTML",
|
|
161
|
+
onclick: (ctx) => {
|
|
162
|
+
ctx.editor.toggleCodeView();
|
|
163
|
+
},
|
|
164
|
+
showOnCodeView: true,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { throttle } from "@lesjoursfr/browser-tools";
|
|
2
|
+
import { Edith } from "../edith.js";
|
|
3
|
+
export declare class EdithEditor {
|
|
4
|
+
private el;
|
|
5
|
+
private ctx;
|
|
6
|
+
private content;
|
|
7
|
+
private height;
|
|
8
|
+
private resizable;
|
|
9
|
+
private mode;
|
|
10
|
+
private visualEditor;
|
|
11
|
+
private codeEditor;
|
|
12
|
+
private codeMirror;
|
|
13
|
+
private history;
|
|
14
|
+
throttledSnapshots: ReturnType<typeof throttle>;
|
|
15
|
+
constructor(ctx: Edith, options: {
|
|
16
|
+
initialContent: string;
|
|
17
|
+
height: number;
|
|
18
|
+
resizable: boolean;
|
|
19
|
+
});
|
|
20
|
+
render(): HTMLDivElement;
|
|
21
|
+
getVisualEditorElement(): HTMLElement;
|
|
22
|
+
getCodeEditorElement(): HTMLElement;
|
|
23
|
+
setContent(content: string): void;
|
|
24
|
+
getContent(): string;
|
|
25
|
+
takeSnapshot(): void;
|
|
26
|
+
restoreSnapshot(): void;
|
|
27
|
+
wrapInsideTag<K extends keyof HTMLElementTagNameMap>(tag: K): void;
|
|
28
|
+
replaceByHtml(html: string): void;
|
|
29
|
+
clearStyle(): void;
|
|
30
|
+
insertLink(): void;
|
|
31
|
+
toggleCodeView(): void;
|
|
32
|
+
onKeyEvent(e: KeyboardEvent): void;
|
|
33
|
+
private _processKeyEvent;
|
|
34
|
+
private _processKeyEventWithMeta;
|
|
35
|
+
onPasteEvent(e: ClipboardEvent): void;
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|