@kubex/zinc 1.0.9 → 1.0.11
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/custom-elements.json +282 -83
- package/dist/vscode.html-custom-data.json +25 -13
- package/dist/web-types.json +84 -27
- package/dist/zn.d.ts +40 -2
- package/dist/zn.min.js +260 -243
- package/docs/pages/components/dropdown.md +6 -1
- package/docs/pages/components/table.md +1 -1
- package/package.json +1 -1
- package/src/components/button-menu/button-menu.component.ts +1 -0
- package/src/components/editor/editor.component.ts +110 -55
- package/src/components/editor/modules/context-menu/context-menu-component.ts +1 -0
- package/src/components/editor/modules/context-menu/context-menu.scss +1 -1
- package/src/components/editor/modules/context-menu/context-menu.ts +58 -26
- package/src/components/editor/modules/context-menu/quick-action/quick-action.component.ts +1 -0
- package/src/components/editor/modules/toolbar/toolbar.component.ts +61 -33
- package/src/components/editor/modules/toolbar/toolbar.ts +19 -4
- package/src/components/header/header.scss +1 -0
- package/src/components/menu/menu.component.ts +2 -1
- package/src/components/menu-item/menu-item.component.ts +4 -0
- package/src/components/note/note.component.ts +2 -25
- package/src/components/note/note.scss +0 -7
- package/src/components/order-table/order-table.scss +16 -10
- package/src/components/panel/panel.component.ts +4 -2
- package/src/components/panel/panel.scss +4 -0
- package/src/components/popup/popup.component.ts +11 -21
- package/src/components/settings-container/settings-container.component.ts +21 -15
- package/src/components/settings-container/settings-container.scss +5 -4
- package/src/components/tooltip/tooltip.component.ts +7 -7
- package/src/zinc.ts +7 -1
|
@@ -6,7 +6,12 @@ layout: component
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
```html:preview
|
|
9
|
-
<zn-dropdown
|
|
9
|
+
<zn-dropdown t="[object Object]" placement="bottom-start">
|
|
10
|
+
<zn-menu actions="[{"confirm":{"type":"success","trigger":"reactivate10","caption":"Reactivate Access","content":"Are you sure you want to reactivate access for John Doe?","action":"#"},"title":"Reactivate Access","style":"success"}]" t="[object Object]" role="menu"></zn-menu>
|
|
11
|
+
<button slot="trigger">
|
|
12
|
+
<zn-icon src="more_vert" t="[object Object]" size="24" library="material-symbols-outlined"></zn-icon>
|
|
13
|
+
</button>
|
|
14
|
+
</zn-dropdown>
|
|
10
15
|
```
|
|
11
16
|
|
|
12
17
|
## Examples
|
|
@@ -6,7 +6,7 @@ layout: component
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
```html:preview
|
|
9
|
-
<zn-table></zn-table>
|
|
9
|
+
<zn-table fixed-first="" t="light" has-actions="" data="{"header":["Full Name","User ID","Email","Type","Partner","State","Date Joined"],"items": [{"actions": [{"confirm": {"type": "success","trigger": "reactivate10","caption": "Reactivate Access","content": "Are you sure you want to reactivate access for John Doe?","action": "#"},"title": "Reactivate Access","style": "success"}],"caption": "John Doe","data": ["1","john.doe@example.com","Member","","<span class='zn-success'>Active</span>","2025-01-01 12:10:20"]}]}"></zn-table>
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
## Examples
|
package/package.json
CHANGED
|
@@ -307,6 +307,7 @@ export default class ZnButtonMenu extends ZincElement {
|
|
|
307
307
|
public setDynamicButtons(btns: NodeListOf<ZnButton>) {
|
|
308
308
|
// remove all buttons that have the zn-button-menu__added class
|
|
309
309
|
this.removeAllButtons();
|
|
310
|
+
if (!btns || btns.length === 0) return;
|
|
310
311
|
|
|
311
312
|
// add the new buttons
|
|
312
313
|
btns.forEach((button: ZnButton) => {
|
|
@@ -25,6 +25,18 @@ import type ToolbarComponent from "./modules/toolbar/toolbar.component";
|
|
|
25
25
|
|
|
26
26
|
import styles from './editor.scss';
|
|
27
27
|
|
|
28
|
+
export interface EditorFeatureConfig {
|
|
29
|
+
codeBlocksEnabled?: boolean;
|
|
30
|
+
dividersEnabled?: boolean;
|
|
31
|
+
linksEnabled?: boolean;
|
|
32
|
+
attachmentsEnabled?: boolean;
|
|
33
|
+
imagesEnabled?: boolean;
|
|
34
|
+
videosEnabled?: boolean;
|
|
35
|
+
datesEnabled?: boolean;
|
|
36
|
+
emojisEnabled?: boolean;
|
|
37
|
+
codeEnabled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
28
40
|
/**
|
|
29
41
|
* @summary Short summary of the component's intended use.
|
|
30
42
|
* @documentation https://zinc.style/components/editor
|
|
@@ -66,6 +78,17 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
|
|
|
66
78
|
@property({attribute: 'attachment-url', type: String})
|
|
67
79
|
uploadAttachmentUrl: string;
|
|
68
80
|
|
|
81
|
+
/* Feature Permission Attributes */
|
|
82
|
+
@property({attribute: 'code-blocks', type: Boolean}) codeBlocksEnabled: boolean = false;
|
|
83
|
+
@property({attribute: 'dividers', type: Boolean}) dividersEnabled: boolean = false;
|
|
84
|
+
@property({attribute: 'links', type: Boolean}) linksEnabled: boolean = false;
|
|
85
|
+
@property({attribute: 'attachments', type: Boolean}) attachmentsEnabled: boolean = false;
|
|
86
|
+
@property({attribute: 'images', type: Boolean}) imagesEnabled: boolean = false;
|
|
87
|
+
@property({attribute: 'videos', type: Boolean}) videosEnabled: boolean = false;
|
|
88
|
+
@property({attribute: 'dates', type: Boolean}) datesEnabled: boolean = false;
|
|
89
|
+
@property({attribute: 'emojis', type: Boolean}) emojisEnabled: boolean = false;
|
|
90
|
+
@property({attribute: 'code', type: Boolean}) codeEnabled: boolean = false;
|
|
91
|
+
@property({attribute: 'ai', type: Boolean}) aiEnabled: boolean = false;
|
|
69
92
|
@property({attribute: 'ai-path'}) aiPath: string = '';
|
|
70
93
|
|
|
71
94
|
private quillElement: Quill;
|
|
@@ -111,10 +134,16 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
|
|
|
111
134
|
});
|
|
112
135
|
|
|
113
136
|
Quill.register({'modules/toolbar': Toolbar}, true);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
137
|
+
if (this.datesEnabled) {
|
|
138
|
+
Quill.register({'modules/datePicker': DatePicker}, true);
|
|
139
|
+
}
|
|
140
|
+
if (this.emojisEnabled) {
|
|
141
|
+
Quill.register({'modules/emoji': Emoji}, true);
|
|
142
|
+
Quill.register({'modules/headlessEmoji': HeadlessEmoji}, true);
|
|
143
|
+
}
|
|
144
|
+
if (this.attachmentsEnabled) {
|
|
145
|
+
Quill.register({'modules/attachment': Attachment}, true);
|
|
146
|
+
}
|
|
118
147
|
Quill.register({'modules/timeTracking': TimeTracking}, true);
|
|
119
148
|
Quill.register({'modules/dragAndDrop': DragAndDrop}, true);
|
|
120
149
|
Quill.register({'modules/imageResize': ImageResize}, true);
|
|
@@ -122,80 +151,106 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
|
|
|
122
151
|
Quill.register({'modules/dialog': Dialog}, true);
|
|
123
152
|
|
|
124
153
|
/* AI Modules */
|
|
125
|
-
|
|
154
|
+
if (this.aiEnabled) {
|
|
155
|
+
Quill.register('modules/ai', QuillAI as any, true);
|
|
156
|
+
}
|
|
126
157
|
|
|
127
158
|
// Register a custom HR blot so we can insert an inline horizontal rule block
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
159
|
+
if (this.dividersEnabled) {
|
|
160
|
+
const BlockEmbed = Quill.import('blots/block/embed') as { new(...args: any[]): any };
|
|
161
|
+
|
|
162
|
+
class HrBlot extends BlockEmbed {
|
|
163
|
+
static blotName = 'hr';
|
|
164
|
+
static tagName = 'HR';
|
|
165
|
+
static className = 'ql-hr';
|
|
166
|
+
|
|
167
|
+
static create(): HTMLElement {
|
|
168
|
+
const node = document.createElement('hr');
|
|
169
|
+
node.classList.add('ql-hr');
|
|
170
|
+
return node;
|
|
171
|
+
}
|
|
139
172
|
}
|
|
140
|
-
}
|
|
141
173
|
|
|
142
|
-
|
|
174
|
+
Quill.register({'formats/hr': HrBlot}, true);
|
|
175
|
+
}
|
|
143
176
|
|
|
144
|
-
const attachmentInput = this.getForm()?.querySelector('input[name="attachments"]');
|
|
145
177
|
const startTimeInput = this.getForm()?.querySelector('input[name="startTime"]');
|
|
146
178
|
const openTimeInput = this.getForm()?.querySelector('input[name="openTime"]');
|
|
147
179
|
|
|
180
|
+
const featureConfig: EditorFeatureConfig = {
|
|
181
|
+
codeBlocksEnabled: this.codeBlocksEnabled,
|
|
182
|
+
dividersEnabled: this.dividersEnabled,
|
|
183
|
+
linksEnabled: this.linksEnabled,
|
|
184
|
+
attachmentsEnabled: this.attachmentsEnabled,
|
|
185
|
+
imagesEnabled: this.imagesEnabled,
|
|
186
|
+
videosEnabled: this.videosEnabled,
|
|
187
|
+
datesEnabled: this.datesEnabled,
|
|
188
|
+
emojisEnabled: this.emojisEnabled,
|
|
189
|
+
codeEnabled: this.codeEnabled,
|
|
190
|
+
};
|
|
191
|
+
|
|
148
192
|
const quill = new Quill(this.editor, {
|
|
149
193
|
modules: {
|
|
150
194
|
toolbar: {
|
|
151
195
|
container: this.toolbar,
|
|
196
|
+
config: featureConfig
|
|
197
|
+
},
|
|
198
|
+
contextMenu: {
|
|
199
|
+
config: featureConfig
|
|
152
200
|
},
|
|
153
|
-
contextMenu: {},
|
|
154
201
|
keyboard: {
|
|
155
202
|
bindings: bindings
|
|
156
203
|
},
|
|
157
204
|
dialog: {
|
|
158
205
|
editorId: this.id
|
|
159
206
|
},
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
207
|
+
...(this.datesEnabled && {
|
|
208
|
+
datePicker: {}
|
|
209
|
+
}),
|
|
210
|
+
...(this.emojisEnabled && {
|
|
211
|
+
emoji: {},
|
|
212
|
+
headlessEmoji: {},
|
|
213
|
+
}),
|
|
214
|
+
...(this.aiEnabled && {
|
|
215
|
+
ai: {
|
|
216
|
+
path: this.aiPath
|
|
217
|
+
}
|
|
218
|
+
}),
|
|
166
219
|
timeTracking: {
|
|
167
220
|
startTimeInput: startTimeInput as HTMLInputElement,
|
|
168
221
|
openTimeInput: openTimeInput as HTMLInputElement
|
|
169
222
|
},
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
223
|
+
...(this.attachmentsEnabled && {
|
|
224
|
+
attachment: {
|
|
225
|
+
attachmentInput: this.getForm()?.querySelector('input[name="attachments"]'),
|
|
226
|
+
onFileUploaded: () => {
|
|
227
|
+
window.onbeforeunload = () => null;
|
|
228
|
+
},
|
|
229
|
+
upload: (file: File) => {
|
|
230
|
+
window.onbeforeunload = () => 'You have unsaved changes. Are you sure you want to leave?';
|
|
231
|
+
return new Promise((resolve) => {
|
|
232
|
+
const fd = new FormData();
|
|
233
|
+
fd.append('filename', file.name);
|
|
234
|
+
fd.append('size', file.size.toString());
|
|
235
|
+
fd.append('mimeType', file.type);
|
|
236
|
+
|
|
237
|
+
const xhr = new XMLHttpRequest();
|
|
238
|
+
xhr.open('POST', this.uploadAttachmentUrl, true);
|
|
239
|
+
xhr.onload = () => {
|
|
240
|
+
if (xhr.status === 200) {
|
|
241
|
+
const response = JSON.parse(xhr.responseText) as {
|
|
242
|
+
uploadPath: string;
|
|
243
|
+
uploadUrl: string;
|
|
244
|
+
originalFilename: string;
|
|
245
|
+
};
|
|
246
|
+
resolve({path: response.uploadPath, url: response.uploadUrl, filename: response.originalFilename});
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
xhr.send(fd);
|
|
250
|
+
});
|
|
251
|
+
},
|
|
174
252
|
},
|
|
175
|
-
|
|
176
|
-
window.onbeforeunload = () => 'You have unsaved changes. Are you sure you want to leave?';
|
|
177
|
-
return new Promise((resolve) => {
|
|
178
|
-
const fd = new FormData();
|
|
179
|
-
fd.append('filename', file.name);
|
|
180
|
-
fd.append('size', file.size.toString());
|
|
181
|
-
fd.append('mimeType', file.type);
|
|
182
|
-
|
|
183
|
-
const xhr = new XMLHttpRequest();
|
|
184
|
-
xhr.open('POST', this.uploadAttachmentUrl, true);
|
|
185
|
-
xhr.onload = () => {
|
|
186
|
-
if (xhr.status === 200) {
|
|
187
|
-
const response = JSON.parse(xhr.responseText) as {
|
|
188
|
-
uploadPath: string;
|
|
189
|
-
uploadUrl: string;
|
|
190
|
-
originalFilename: string;
|
|
191
|
-
};
|
|
192
|
-
resolve({path: response.uploadPath, url: response.uploadUrl, filename: response.originalFilename});
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
xhr.send(fd);
|
|
196
|
-
});
|
|
197
|
-
},
|
|
198
|
-
},
|
|
253
|
+
}),
|
|
199
254
|
imageResize: {},
|
|
200
255
|
history: {}
|
|
201
256
|
},
|
|
@@ -339,7 +394,7 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
|
|
|
339
394
|
const emoji = this.quillElement.getModule('headlessEmoji') as HeadlessEmoji;
|
|
340
395
|
const menu = this.quillElement.getModule('contextMenu') as ContextMenu;
|
|
341
396
|
const dialog = this.quillElement.getModule('dialog') as Dialog;
|
|
342
|
-
if (emoji
|
|
397
|
+
if (emoji?.isOpen() || menu?.isOpen() || dialog?.isOpen()) {
|
|
343
398
|
return false;
|
|
344
399
|
}
|
|
345
400
|
|
|
@@ -4,6 +4,7 @@ import {litToHTML} from "../../../../utilities/lit-to-html";
|
|
|
4
4
|
import {type ResultItem} from "./context-menu-component";
|
|
5
5
|
import Quill, {Delta} from "quill";
|
|
6
6
|
import ZnEditorQuickAction from "./quick-action";
|
|
7
|
+
import type {EditorFeatureConfig} from "../../editor.component";
|
|
7
8
|
import type ContextMenuComponent from "./context-menu-component";
|
|
8
9
|
import type Toolbar from "../toolbar/toolbar";
|
|
9
10
|
|
|
@@ -14,10 +15,12 @@ class ContextMenu {
|
|
|
14
15
|
private _startIndex = -1;
|
|
15
16
|
private _keydownHandler = (e: KeyboardEvent) => this.onKeydown(e);
|
|
16
17
|
private _docClickHandler = (e: MouseEvent) => this.onDocumentClick(e);
|
|
18
|
+
private _featureConfig: EditorFeatureConfig = {};
|
|
17
19
|
|
|
18
|
-
constructor(quill: Quill) {
|
|
20
|
+
constructor(quill: Quill, options: { config: EditorFeatureConfig }) {
|
|
19
21
|
this._quill = quill;
|
|
20
22
|
this._toolbarModule = quill.getModule('toolbar') as Toolbar;
|
|
23
|
+
this._featureConfig = options.config || {};
|
|
21
24
|
|
|
22
25
|
this.initComponent();
|
|
23
26
|
this.attachEvents();
|
|
@@ -199,7 +202,7 @@ class ContextMenu {
|
|
|
199
202
|
Quill.sources.USER
|
|
200
203
|
);
|
|
201
204
|
|
|
202
|
-
setTimeout(() => this._quill.setSelection(insertIndex + contentDelta.length(), 0, Quill.sources.SILENT), 0);
|
|
205
|
+
setTimeout(() => this._quill.setSelection(insertIndex + contentDelta.length() + 1, 0, Quill.sources.SILENT), 0);
|
|
203
206
|
}
|
|
204
207
|
this._quill.focus();
|
|
205
208
|
this.hide();
|
|
@@ -225,6 +228,7 @@ class ContextMenu {
|
|
|
225
228
|
|
|
226
229
|
private _getOptions(): ResultItem[] {
|
|
227
230
|
const options: ResultItem[] = [];
|
|
231
|
+
let orderCounter = 0;
|
|
228
232
|
|
|
229
233
|
// 1) Quick Actions
|
|
230
234
|
const root = this._quill.container.getRootNode() as ShadowRoot;
|
|
@@ -236,41 +240,69 @@ class ContextMenu {
|
|
|
236
240
|
|
|
237
241
|
const {label, content, uri, icon, key} = quickAction;
|
|
238
242
|
|
|
243
|
+
let order: number;
|
|
244
|
+
if (typeof quickAction.order === 'number') {
|
|
245
|
+
order = quickAction.order!;
|
|
246
|
+
} else {
|
|
247
|
+
order = orderCounter++;
|
|
248
|
+
}
|
|
249
|
+
|
|
239
250
|
if (label && icon) {
|
|
240
251
|
if (key) {
|
|
241
|
-
options.push({icon, label, format: 'toolbar', key: key});
|
|
252
|
+
options.push({icon, label, format: 'toolbar', key: key, order});
|
|
242
253
|
} else if (uri) {
|
|
243
|
-
options.push({icon, label, format: 'dialog', value: uri});
|
|
254
|
+
options.push({icon, label, format: 'dialog', value: uri, order});
|
|
244
255
|
} else if (content) {
|
|
245
|
-
options.push({icon, label, format: 'insert', value: content});
|
|
256
|
+
options.push({icon, label, format: 'insert', value: content, order});
|
|
246
257
|
}
|
|
247
258
|
}
|
|
248
259
|
});
|
|
249
260
|
}
|
|
250
261
|
|
|
251
|
-
// 2) Built-in Actions
|
|
262
|
+
// 2) Built-in Actions (In order they should appear)
|
|
252
263
|
options.push(
|
|
253
|
-
{icon: 'format_bold', label: 'Bold', format: 'bold'},
|
|
254
|
-
{icon: 'format_italic', label: 'Italic', format: 'italic'},
|
|
255
|
-
{icon: 'format_underlined', label: 'Underline', format: 'underline'},
|
|
256
|
-
{icon: 'strikethrough_s', label: 'Strikethrough', format: 'strike'},
|
|
257
|
-
{icon: 'format_quote', label: 'Blockquote', format: 'blockquote'},
|
|
258
|
-
{icon: 'code', label: 'Inline Code', format: 'code'},
|
|
259
|
-
{icon: 'code_blocks', label: 'Code Block', format: 'code-block'},
|
|
260
|
-
{icon: 'format_h1', label: 'Heading 1', format: 'header', value: '1'},
|
|
261
|
-
{icon: 'format_h2', label: 'Heading 2', format: 'header', value: '2'},
|
|
262
|
-
{icon: 'match_case', label: 'Normal Text', format: 'header', value: ''},
|
|
263
|
-
{icon: 'format_list_bulleted', label: 'Bulleted List', format: 'list', value: 'bullet'},
|
|
264
|
-
{icon: 'format_list_numbered', label: 'Numbered List', format: 'list', value: 'ordered'},
|
|
265
|
-
{icon: 'checklist', label: 'Checklist', format: 'list', value: 'checked'},
|
|
266
|
-
{icon: 'link', label: 'Link', format: 'link', value: true},
|
|
267
|
-
{icon: 'horizontal_rule', label: 'Divider', format: 'divider'},
|
|
268
|
-
{icon: 'attachment', label: 'Attachment', format: 'attachment'},
|
|
269
|
-
{icon: 'image', label: 'Image', format: 'image'},
|
|
270
|
-
{icon: 'video_camera_back', label: 'Video', format: 'video'},
|
|
271
|
-
{icon: 'calendar_today', label: 'Date', format: 'date'},
|
|
272
|
-
{icon: 'format_clear', label: 'Clear Formatting', format: 'clean'}
|
|
264
|
+
{icon: 'format_bold', label: 'Bold', format: 'bold', order: orderCounter++},
|
|
265
|
+
{icon: 'format_italic', label: 'Italic', format: 'italic', order: orderCounter++},
|
|
266
|
+
{icon: 'format_underlined', label: 'Underline', format: 'underline', order: orderCounter++},
|
|
267
|
+
{icon: 'strikethrough_s', label: 'Strikethrough', format: 'strike', order: orderCounter++},
|
|
268
|
+
{icon: 'format_quote', label: 'Blockquote', format: 'blockquote', order: orderCounter++},
|
|
273
269
|
);
|
|
270
|
+
if (this._featureConfig.codeEnabled !== false) {
|
|
271
|
+
options.push({icon: 'code', label: 'Inline Code', format: 'code', order: orderCounter++});
|
|
272
|
+
}
|
|
273
|
+
if (this._featureConfig.codeBlocksEnabled !== false) {
|
|
274
|
+
options.push({icon: 'code_blocks', label: 'Code Block', format: 'code-block', order: orderCounter++});
|
|
275
|
+
}
|
|
276
|
+
options.push(
|
|
277
|
+
{icon: 'format_h1', label: 'Heading 1', format: 'header', value: '1', order: orderCounter++},
|
|
278
|
+
{icon: 'format_h2', label: 'Heading 2', format: 'header', value: '2', order: orderCounter++},
|
|
279
|
+
{icon: 'match_case', label: 'Normal Text', format: 'header', value: '', order: orderCounter++},
|
|
280
|
+
{icon: 'format_list_bulleted', label: 'Bulleted List', format: 'list', value: 'bullet', order: orderCounter++},
|
|
281
|
+
{icon: 'format_list_numbered', label: 'Numbered List', format: 'list', value: 'ordered', order: orderCounter++},
|
|
282
|
+
{icon: 'checklist', label: 'Checklist', format: 'list', value: 'checked', order: orderCounter++}
|
|
283
|
+
);
|
|
284
|
+
if (this._featureConfig.linksEnabled !== false) {
|
|
285
|
+
options.push({icon: 'link', label: 'Link', format: 'link', value: true, order: orderCounter++});
|
|
286
|
+
}
|
|
287
|
+
if (this._featureConfig.dividersEnabled !== false) {
|
|
288
|
+
options.push({icon: 'horizontal_rule', label: 'Divider', format: 'divider', order: orderCounter++});
|
|
289
|
+
}
|
|
290
|
+
if (this._featureConfig.attachmentsEnabled !== false) {
|
|
291
|
+
options.push({icon: 'attachment', label: 'Attachment', format: 'attachment', order: orderCounter++});
|
|
292
|
+
}
|
|
293
|
+
if (this._featureConfig.imagesEnabled !== false) {
|
|
294
|
+
options.push({icon: 'image', label: 'Image', format: 'image', order: orderCounter++});
|
|
295
|
+
}
|
|
296
|
+
if (this._featureConfig.videosEnabled !== false) {
|
|
297
|
+
options.push({icon: 'video_camera_back', label: 'Video', format: 'video', order: orderCounter++});
|
|
298
|
+
}
|
|
299
|
+
if (this._featureConfig.datesEnabled !== false) {
|
|
300
|
+
options.push({icon: 'calendar_today', label: 'Date', format: 'date', order: orderCounter++});
|
|
301
|
+
}
|
|
302
|
+
options.push({icon: 'format_clear', label: 'Clear Formatting', format: 'clean', order: orderCounter++});
|
|
303
|
+
|
|
304
|
+
// Sort options by order property
|
|
305
|
+
options.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
274
306
|
|
|
275
307
|
return options;
|
|
276
308
|
}
|
|
@@ -6,6 +6,7 @@ import ZnButton from "../../../button";
|
|
|
6
6
|
import ZnEditorTool from "./tool";
|
|
7
7
|
import ZnMenu from "../../../menu";
|
|
8
8
|
import ZnMenuItem from "../../../menu-item";
|
|
9
|
+
import type {EditorFeatureConfig} from "../../editor.component";
|
|
9
10
|
|
|
10
11
|
import styles from './toolbar.scss';
|
|
11
12
|
|
|
@@ -22,6 +23,7 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
22
23
|
@query('.toolbar__overflow-menu') private _overflowMenu!: HTMLElement;
|
|
23
24
|
@query('.toolbar__group--overflow') private _overflowGroup!: HTMLElement;
|
|
24
25
|
|
|
26
|
+
private _featureConfig: EditorFeatureConfig = {};
|
|
25
27
|
private _resizeObserver: ResizeObserver | null = null;
|
|
26
28
|
private _resizeId: number | null = null;
|
|
27
29
|
|
|
@@ -78,6 +80,10 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
public configureToolbar(config: EditorFeatureConfig) {
|
|
84
|
+
this._featureConfig = config;
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
private getToolbarWidth() {
|
|
82
88
|
const host = this as unknown as HTMLElement;
|
|
83
89
|
let width = host.getBoundingClientRect?.().width || host.offsetWidth || 0;
|
|
@@ -456,6 +462,13 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
456
462
|
}
|
|
457
463
|
|
|
458
464
|
render() {
|
|
465
|
+
const showInsertOptions = this._featureConfig.dividersEnabled ||
|
|
466
|
+
this._featureConfig.linksEnabled ||
|
|
467
|
+
this._featureConfig.attachmentsEnabled ||
|
|
468
|
+
this._featureConfig.imagesEnabled ||
|
|
469
|
+
this._featureConfig.videosEnabled;
|
|
470
|
+
const showInsertGroup = showInsertOptions || this._featureConfig.datesEnabled || this._featureConfig.emojisEnabled;
|
|
471
|
+
|
|
459
472
|
return html`
|
|
460
473
|
<div class="toolbar">
|
|
461
474
|
<div class="toolbar__group">${this._textOptions()}</div>
|
|
@@ -463,11 +476,12 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
463
476
|
<div class="toolbar__group">${this._historyOptions()}</div>
|
|
464
477
|
<div class="toolbar__group">${this._colorOptions()}</div>
|
|
465
478
|
<div class="toolbar__group">${this._listOptions()}</div>
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
479
|
+
${showInsertGroup ? html`
|
|
480
|
+
<div class="toolbar__group">
|
|
481
|
+
${showInsertOptions ? html`${this._insertOptions()}` : ''}
|
|
482
|
+
${this._featureConfig.datesEnabled ? html`${this._dateOption()}` : ''}
|
|
483
|
+
${this._featureConfig.emojisEnabled ? html`${this._emojiOptions()}` : ''}
|
|
484
|
+
</div>` : ''}
|
|
471
485
|
<div class="toolbar__group">
|
|
472
486
|
<slot></slot>
|
|
473
487
|
</div>
|
|
@@ -550,14 +564,18 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
550
564
|
<zn-icon src="format_quote" size="18" slot="prefix"></zn-icon>
|
|
551
565
|
Quote
|
|
552
566
|
</zn-menu-item>
|
|
553
|
-
|
|
554
|
-
<zn-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
567
|
+
${this._featureConfig.codeEnabled ? html`
|
|
568
|
+
<zn-menu-item type="checkbox" checked-position="right" data-format="code">
|
|
569
|
+
<zn-icon src="code" size="18" slot="prefix"></zn-icon>
|
|
570
|
+
Code
|
|
571
|
+
</zn-menu-item>
|
|
572
|
+
` : ''}
|
|
573
|
+
${this._featureConfig.codeBlocksEnabled ? html`
|
|
574
|
+
<zn-menu-item type="checkbox" checked-position="right" data-format="code-block">
|
|
575
|
+
<zn-icon src="code_blocks" size="18" slot="prefix"></zn-icon>
|
|
576
|
+
Code Block
|
|
577
|
+
</zn-menu-item>
|
|
578
|
+
` : ''}
|
|
561
579
|
<zn-menu-item data-format="clean">
|
|
562
580
|
<zn-icon src="format_clear" size="18" slot="prefix"></zn-icon>
|
|
563
581
|
Clear Formatting
|
|
@@ -680,26 +698,36 @@ export default class ToolbarComponent extends ZincElement {
|
|
|
680
698
|
<zn-icon src="add" size="18"></zn-icon>
|
|
681
699
|
</zn-button>
|
|
682
700
|
<zn-menu>
|
|
683
|
-
|
|
684
|
-
<zn-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
<zn-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
701
|
+
${this._featureConfig.dividersEnabled ? html`
|
|
702
|
+
<zn-menu-item checked-position="right" data-format="divider">
|
|
703
|
+
<zn-icon src="horizontal_rule" size="18" slot="prefix"></zn-icon>
|
|
704
|
+
Divider
|
|
705
|
+
</zn-menu-item>
|
|
706
|
+
` : ''}
|
|
707
|
+
${this._featureConfig.linksEnabled ? html`
|
|
708
|
+
<zn-menu-item checked-position="right" data-format="link">
|
|
709
|
+
<zn-icon src="link" size="18" slot="prefix"></zn-icon>
|
|
710
|
+
Link
|
|
711
|
+
</zn-menu-item>
|
|
712
|
+
` : ''}
|
|
713
|
+
${this._featureConfig.attachmentsEnabled ? html`
|
|
714
|
+
<zn-menu-item checked-position="right" data-format="attachment">
|
|
715
|
+
<zn-icon src="attachment" size="18" slot="prefix"></zn-icon>
|
|
716
|
+
Attachment
|
|
717
|
+
</zn-menu-item>
|
|
718
|
+
` : ''}
|
|
719
|
+
${this._featureConfig.imagesEnabled ? html`
|
|
720
|
+
<zn-menu-item checked-position="right" data-format="image">
|
|
721
|
+
<zn-icon src="image" size="18" slot="prefix"></zn-icon>
|
|
722
|
+
Image
|
|
723
|
+
</zn-menu-item>
|
|
724
|
+
` : ''}
|
|
725
|
+
${this._featureConfig.videosEnabled ? html`
|
|
726
|
+
<zn-menu-item checked-position="right" data-format="video">
|
|
727
|
+
<zn-icon src="video_camera_back" size="18" slot="prefix"></zn-icon>
|
|
728
|
+
Video
|
|
729
|
+
</zn-menu-item>
|
|
730
|
+
` : ''}
|
|
703
731
|
</zn-menu>
|
|
704
732
|
</zn-dropdown>`;
|
|
705
733
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import './toolbar.component';
|
|
2
2
|
import Quill from "quill";
|
|
3
3
|
import QuillToolbar from "quill/modules/toolbar";
|
|
4
|
+
import type {EditorFeatureConfig} from "../../editor.component";
|
|
4
5
|
import type Attachment from "../attachment/attachment";
|
|
5
6
|
import type DialogComponent from "../dialog/dialog.component";
|
|
6
7
|
import type Emoji from "../emoji/emoji";
|
|
@@ -17,20 +18,34 @@ class Toolbar extends QuillToolbar {
|
|
|
17
18
|
constructor(quill: Quill, options: {
|
|
18
19
|
container: ToolbarComponent;
|
|
19
20
|
handlers?: Record<string, (value?: any) => void>;
|
|
21
|
+
config?: EditorFeatureConfig;
|
|
20
22
|
}) {
|
|
21
23
|
super(quill, options);
|
|
22
24
|
|
|
25
|
+
const featureConfig = options.config;
|
|
26
|
+
|
|
23
27
|
// Add handlers after parent Toolbar initialization
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
if (featureConfig?.attachmentsEnabled) {
|
|
29
|
+
this.addHandler('attachment', () => null);
|
|
30
|
+
}
|
|
31
|
+
if (featureConfig?.datesEnabled) {
|
|
32
|
+
this.addHandler('date', () => this._openDatePicker());
|
|
33
|
+
}
|
|
34
|
+
if (featureConfig?.dividersEnabled) {
|
|
35
|
+
this.addHandler('divider', () => this._insertDivider());
|
|
36
|
+
}
|
|
37
|
+
if (featureConfig?.imagesEnabled) {
|
|
38
|
+
this.addHandler('image', () => this._addImage());
|
|
39
|
+
}
|
|
27
40
|
this.addHandler('redo', () => quill.history.redo());
|
|
28
41
|
this.addHandler('undo', () => quill.history.undo());
|
|
29
42
|
this.addHandler('dialog', (value: string) => this._openDialog(value));
|
|
30
|
-
this.addHandler('image', () => this._addImage());
|
|
31
43
|
|
|
32
44
|
this._quill = quill;
|
|
33
45
|
this._component = options.container;
|
|
46
|
+
if (featureConfig) {
|
|
47
|
+
this._component.configureToolbar(featureConfig)
|
|
48
|
+
}
|
|
34
49
|
|
|
35
50
|
this._component.updateComplete.then(() => {
|
|
36
51
|
this._attachToolbarHandlers();
|
|
@@ -112,7 +112,8 @@ export default class ZnMenu extends ZincElement {
|
|
|
112
112
|
action="${item.confirm?.action}"></zn-confirm>
|
|
113
113
|
<zn-menu-item @mousedown=${this.handleMouseDown}
|
|
114
114
|
@keydown=${this.handleKeyDown}
|
|
115
|
-
id="${item.confirm?.trigger}"
|
|
115
|
+
id="${item.confirm?.trigger}"
|
|
116
|
+
confirm>
|
|
116
117
|
${(item.icon) ? html`
|
|
117
118
|
<zn-icon src="${item.icon}" size="20" slot="prefix"></zn-icon>` : html``}
|
|
118
119
|
${item.title}
|