@3ddv/software-division-components 2.0.4 → 2.0.6
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/fesm2022/3ddv-software-division-components-generic-rich-text-editor.mjs +605 -0
- package/fesm2022/3ddv-software-division-components-generic-rich-text-editor.mjs.map +1 -0
- package/package.json +1 -1
- package/styles.css +2 -2
- package/types/3ddv-software-division-components-generic-rich-text-editor.d.ts +348 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { OnInit, AfterViewInit, OnDestroy } from '@angular/core';
|
|
3
|
+
import { FormGroup, AbstractControl, FormControl, ValidationErrors } from '@angular/forms';
|
|
4
|
+
import { Extension, Editor } from '@tiptap/core';
|
|
5
|
+
import * as _3ddv_software_division_components_generic_rich_text_editor from '@3ddv/software-division-components/generic/rich-text-editor';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Custom toolbar button configuration for extending the toolbar
|
|
9
|
+
*/
|
|
10
|
+
interface CustomToolbarButton {
|
|
11
|
+
/** Unique identifier for the button */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Icon to display (SVG string or icon name) */
|
|
14
|
+
icon: string;
|
|
15
|
+
/** Tooltip text */
|
|
16
|
+
title: string;
|
|
17
|
+
/** Click handler function */
|
|
18
|
+
action: () => void;
|
|
19
|
+
/** Function to determine active state */
|
|
20
|
+
isActive?: () => boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for the rich text editor toolbar
|
|
24
|
+
*/
|
|
25
|
+
interface ToolbarConfig {
|
|
26
|
+
/** Enable bold formatting */
|
|
27
|
+
bold?: boolean;
|
|
28
|
+
/** Enable italic formatting */
|
|
29
|
+
italic?: boolean;
|
|
30
|
+
/** Enable underline formatting */
|
|
31
|
+
underline?: boolean;
|
|
32
|
+
/** Enable strikethrough formatting */
|
|
33
|
+
strike?: boolean;
|
|
34
|
+
/** Enable bullet list */
|
|
35
|
+
bulletList?: boolean;
|
|
36
|
+
/** Enable ordered list */
|
|
37
|
+
orderedList?: boolean;
|
|
38
|
+
/** Heading levels to enable (1-6) */
|
|
39
|
+
headings?: (1 | 2 | 3 | 4 | 5 | 6)[];
|
|
40
|
+
/** Enable horizontal rule insertion */
|
|
41
|
+
horizontalRule?: boolean;
|
|
42
|
+
/** Enable link insertion/editing */
|
|
43
|
+
link?: boolean;
|
|
44
|
+
/** Enable blockquote formatting */
|
|
45
|
+
blockquote?: boolean;
|
|
46
|
+
/** Enable inline code formatting */
|
|
47
|
+
code?: boolean;
|
|
48
|
+
/** Enable code block */
|
|
49
|
+
codeBlock?: boolean;
|
|
50
|
+
/** Enable undo button */
|
|
51
|
+
undo?: boolean;
|
|
52
|
+
/** Enable redo button */
|
|
53
|
+
redo?: boolean;
|
|
54
|
+
/** Custom buttons to add to the toolbar */
|
|
55
|
+
customButtons?: CustomToolbarButton[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Preset name for toolbar configuration
|
|
59
|
+
*/
|
|
60
|
+
type ToolbarPreset = 'minimal' | 'standard' | 'full';
|
|
61
|
+
/**
|
|
62
|
+
* Predefined toolbar presets
|
|
63
|
+
*/
|
|
64
|
+
declare const TOOLBAR_PRESETS: Record<ToolbarPreset, ToolbarConfig>;
|
|
65
|
+
/**
|
|
66
|
+
* Default toolbar configuration (standard preset)
|
|
67
|
+
*/
|
|
68
|
+
declare const DEFAULT_TOOLBAR_CONFIG: ToolbarConfig;
|
|
69
|
+
/**
|
|
70
|
+
* Configuration for link behavior in the editor
|
|
71
|
+
*/
|
|
72
|
+
interface LinkConfig {
|
|
73
|
+
/** Whether links open on click (default: false) */
|
|
74
|
+
openOnClick?: boolean;
|
|
75
|
+
/** CSS classes to apply to links */
|
|
76
|
+
linkClass?: string;
|
|
77
|
+
/** Whether to add rel="noopener noreferrer" to external links */
|
|
78
|
+
addNoopener?: boolean;
|
|
79
|
+
/** Whether to add target="_blank" to links */
|
|
80
|
+
openInNewTab?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Default link configuration
|
|
84
|
+
*/
|
|
85
|
+
declare const DEFAULT_LINK_CONFIG: LinkConfig;
|
|
86
|
+
/**
|
|
87
|
+
* Error display mode for the editor
|
|
88
|
+
*/
|
|
89
|
+
type ErrorDisplayMode = 'always' | 'after-submit';
|
|
90
|
+
/**
|
|
91
|
+
* Full editor configuration options
|
|
92
|
+
*/
|
|
93
|
+
interface EditorConfig {
|
|
94
|
+
/** Placeholder text when editor is empty */
|
|
95
|
+
placeholder?: string;
|
|
96
|
+
/** Minimum height of the editor */
|
|
97
|
+
minHeight?: string;
|
|
98
|
+
/** Maximum height of the editor (enables scrolling) */
|
|
99
|
+
maxHeight?: string;
|
|
100
|
+
/** Whether the editor should auto-focus on initialization */
|
|
101
|
+
autoFocus?: boolean;
|
|
102
|
+
/** Custom TipTap extensions to add or override defaults */
|
|
103
|
+
extensions?: Extension[];
|
|
104
|
+
/** Link behavior configuration */
|
|
105
|
+
linkConfig?: LinkConfig;
|
|
106
|
+
/** Whether to enable spellcheck */
|
|
107
|
+
spellcheck?: boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Default editor configuration
|
|
111
|
+
*/
|
|
112
|
+
declare const DEFAULT_EDITOR_CONFIG: EditorConfig;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Link data structure for link insertion
|
|
116
|
+
*/
|
|
117
|
+
interface LinkData {
|
|
118
|
+
url: string;
|
|
119
|
+
text: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Modal component for inserting/editing links in the rich text editor
|
|
123
|
+
*/
|
|
124
|
+
declare class LinkModalComponent {
|
|
125
|
+
private readonly fb;
|
|
126
|
+
/** Whether the modal is visible */
|
|
127
|
+
readonly visible: _angular_core.InputSignal<boolean>;
|
|
128
|
+
/** Pre-selected text to use as link text */
|
|
129
|
+
readonly selectedText: _angular_core.InputSignal<string>;
|
|
130
|
+
/** Existing URL when editing a link */
|
|
131
|
+
readonly existingUrl: _angular_core.InputSignal<string>;
|
|
132
|
+
/** Event emitted when a link is added/updated */
|
|
133
|
+
readonly linkAdded: _angular_core.OutputEmitterRef<LinkData>;
|
|
134
|
+
/** Event emitted when the modal is closed */
|
|
135
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
136
|
+
/** Form group for link data */
|
|
137
|
+
readonly linkForm: FormGroup;
|
|
138
|
+
/** Track if form was submitted to show validation errors */
|
|
139
|
+
protected readonly submitted: _angular_core.WritableSignal<boolean>;
|
|
140
|
+
/** Computed title based on whether we're editing or adding */
|
|
141
|
+
protected readonly modalTitle: _angular_core.Signal<"Edit Link" | "Add Link">;
|
|
142
|
+
constructor();
|
|
143
|
+
/** Submit the form and emit link data */
|
|
144
|
+
addLink(): void;
|
|
145
|
+
/** Close the modal and reset form */
|
|
146
|
+
closeModal(): void;
|
|
147
|
+
/** Check if a field has errors and should show them */
|
|
148
|
+
hasError(fieldName: string): boolean;
|
|
149
|
+
/** Get specific error for a field */
|
|
150
|
+
getError(fieldName: string, errorType: string): boolean;
|
|
151
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<LinkModalComponent, never>;
|
|
152
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<LinkModalComponent, "sdc-link-modal", never, { "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "selectedText": { "alias": "selectedText"; "required": false; "isSignal": true; }; "existingUrl": { "alias": "existingUrl"; "required": false; "isSignal": true; }; }, { "linkAdded": "linkAdded"; "closed": "closed"; }, never, never, true, never>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* A rich text editor component built on TipTap
|
|
157
|
+
*
|
|
158
|
+
* This component provides a WYSIWYG editor with configurable toolbar,
|
|
159
|
+
* form integration, and theme support.
|
|
160
|
+
*
|
|
161
|
+
* @since 1.5.0
|
|
162
|
+
*/
|
|
163
|
+
declare class RichTextEditorComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
164
|
+
/** Editor content container element */
|
|
165
|
+
private readonly editorContent;
|
|
166
|
+
/** TipTap editor instance (signal for change detection) */
|
|
167
|
+
readonly editorSignal: _angular_core.WritableSignal<Editor | null>;
|
|
168
|
+
/** Getter for backward compatibility */
|
|
169
|
+
get editor(): Editor | null;
|
|
170
|
+
/** Theme class to apply */
|
|
171
|
+
readonly theme: _angular_core.InputSignal<"theme-backoffice" | "theme-sdc">;
|
|
172
|
+
/** Form control for two-way binding */
|
|
173
|
+
readonly control: _angular_core.InputSignal<AbstractControl<string | null, string | null, any> | FormControl<any> | null>;
|
|
174
|
+
/** Placeholder text when editor is empty */
|
|
175
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
176
|
+
/** Whether the editor is disabled */
|
|
177
|
+
readonly disabled: _angular_core.InputSignal<boolean>;
|
|
178
|
+
/** Minimum height of the editor */
|
|
179
|
+
readonly minHeight: _angular_core.InputSignal<string>;
|
|
180
|
+
/** Maximum height of the editor (enables scrolling) */
|
|
181
|
+
readonly maxHeight: _angular_core.InputSignal<string | null>;
|
|
182
|
+
/** Toolbar configuration object */
|
|
183
|
+
readonly toolbarConfig: _angular_core.InputSignal<ToolbarConfig>;
|
|
184
|
+
/** Toolbar preset name (overrides toolbarConfig) */
|
|
185
|
+
readonly toolbarPreset: _angular_core.InputSignal<ToolbarPreset | null>;
|
|
186
|
+
/** Link behavior configuration */
|
|
187
|
+
readonly linkConfig: _angular_core.InputSignal<LinkConfig>;
|
|
188
|
+
/** Error display mode */
|
|
189
|
+
readonly errorDisplayMode: _angular_core.InputSignal<ErrorDisplayMode>;
|
|
190
|
+
/** Custom error message */
|
|
191
|
+
readonly errorMessage: _angular_core.InputSignal<string>;
|
|
192
|
+
/** Label text */
|
|
193
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
194
|
+
/** Label position */
|
|
195
|
+
readonly labelPosition: _angular_core.InputSignal<"top" | "left">;
|
|
196
|
+
/** Name attribute for form control */
|
|
197
|
+
readonly name: _angular_core.InputSignal<string>;
|
|
198
|
+
/** Whether to autofocus the editor on init */
|
|
199
|
+
readonly autoFocus: _angular_core.InputSignal<boolean>;
|
|
200
|
+
/** Emits when the editor is ready */
|
|
201
|
+
readonly editorReady: _angular_core.OutputEmitterRef<Editor>;
|
|
202
|
+
/** Emits HTML content on change */
|
|
203
|
+
readonly contentChange: _angular_core.OutputEmitterRef<string>;
|
|
204
|
+
/** Emits on focus */
|
|
205
|
+
readonly onFocus: _angular_core.OutputEmitterRef<FocusEvent>;
|
|
206
|
+
/** Emits on blur */
|
|
207
|
+
readonly onBlur: _angular_core.OutputEmitterRef<FocusEvent>;
|
|
208
|
+
/** Form control state for validation display */
|
|
209
|
+
readonly controlState: _angular_core.WritableSignal<{
|
|
210
|
+
invalid: boolean;
|
|
211
|
+
touched: boolean;
|
|
212
|
+
dirty: boolean;
|
|
213
|
+
errors: ValidationErrors | null;
|
|
214
|
+
isFormSubmitted: boolean;
|
|
215
|
+
}>;
|
|
216
|
+
/** Link modal visibility state */
|
|
217
|
+
protected readonly showLinkModal: _angular_core.WritableSignal<boolean>;
|
|
218
|
+
/** Selected text for link modal */
|
|
219
|
+
protected readonly selectedText: _angular_core.WritableSignal<string>;
|
|
220
|
+
/** Existing URL when editing a link */
|
|
221
|
+
protected readonly existingLinkUrl: _angular_core.WritableSignal<string>;
|
|
222
|
+
/** Subscriptions for cleanup */
|
|
223
|
+
private readonly subscriptions;
|
|
224
|
+
/** Flag to prevent update loops */
|
|
225
|
+
private isUpdatingFromEditor;
|
|
226
|
+
/** Cached form control reference (to avoid calling signals in callbacks) */
|
|
227
|
+
private formControlRef;
|
|
228
|
+
/** Computed toolbar config using preset or custom config */
|
|
229
|
+
protected readonly computedToolbarConfig: _angular_core.Signal<ToolbarConfig>;
|
|
230
|
+
/** Computed class string for the component */
|
|
231
|
+
protected readonly computedClass: _angular_core.Signal<string>;
|
|
232
|
+
/** Computed label class */
|
|
233
|
+
protected readonly labelClass: _angular_core.Signal<"sdc-rich-text-editor__label left" | "sdc-rich-text-editor__label top">;
|
|
234
|
+
/** Whether to show the label */
|
|
235
|
+
protected readonly showLabel: _angular_core.Signal<boolean | "">;
|
|
236
|
+
/** Current error message to display */
|
|
237
|
+
protected readonly currentErrorMessage: _angular_core.Signal<string>;
|
|
238
|
+
/** Whether to show error */
|
|
239
|
+
protected readonly showError: _angular_core.Signal<boolean>;
|
|
240
|
+
/** Computed editor styles */
|
|
241
|
+
protected readonly editorStyles: _angular_core.Signal<Record<string, string>>;
|
|
242
|
+
constructor();
|
|
243
|
+
ngOnInit(): void;
|
|
244
|
+
ngAfterViewInit(): void;
|
|
245
|
+
ngOnDestroy(): void;
|
|
246
|
+
/** Initialize the TipTap editor */
|
|
247
|
+
private initializeEditor;
|
|
248
|
+
/** Update error state from form control */
|
|
249
|
+
private updateErrors;
|
|
250
|
+
/** Get error message for validator */
|
|
251
|
+
private getValidatorErrorMessage;
|
|
252
|
+
/** Handle link button click from toolbar */
|
|
253
|
+
protected handleLinkRequested(): void;
|
|
254
|
+
/** Handle link added from modal */
|
|
255
|
+
protected handleLinkAdded(data: LinkData): void;
|
|
256
|
+
/** Handle link modal close */
|
|
257
|
+
protected handleLinkModalClose(): void;
|
|
258
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RichTextEditorComponent, never>;
|
|
259
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<RichTextEditorComponent, "sdc-rich-text-editor", never, { "theme": { "alias": "theme"; "required": false; "isSignal": true; }; "control": { "alias": "control"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "toolbarConfig": { "alias": "toolbarConfig"; "required": false; "isSignal": true; }; "toolbarPreset": { "alias": "toolbarPreset"; "required": false; "isSignal": true; }; "linkConfig": { "alias": "linkConfig"; "required": false; "isSignal": true; }; "errorDisplayMode": { "alias": "errorDisplayMode"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelPosition": { "alias": "labelPosition"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; }, { "editorReady": "editorReady"; "contentChange": "contentChange"; "onFocus": "onFocus"; "onBlur": "onBlur"; }, never, never, true, never>;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Toolbar component for the rich text editor
|
|
264
|
+
* Provides formatting buttons with responsive design and active state tracking
|
|
265
|
+
*/
|
|
266
|
+
declare class EditorToolbarComponent {
|
|
267
|
+
/** The TipTap editor instance */
|
|
268
|
+
readonly editor: _angular_core.InputSignal<Editor>;
|
|
269
|
+
/** Toolbar configuration */
|
|
270
|
+
readonly config: _angular_core.InputSignal<ToolbarConfig>;
|
|
271
|
+
/** Event emitted when link button is clicked */
|
|
272
|
+
readonly linkRequested: _angular_core.OutputEmitterRef<void>;
|
|
273
|
+
/** Mobile menu visibility state */
|
|
274
|
+
readonly showMobileMenu: _angular_core.WritableSignal<boolean>;
|
|
275
|
+
/** Computed config with defaults applied */
|
|
276
|
+
protected readonly mergedConfig: _angular_core.Signal<{
|
|
277
|
+
bold?: boolean;
|
|
278
|
+
italic?: boolean;
|
|
279
|
+
underline?: boolean;
|
|
280
|
+
strike?: boolean;
|
|
281
|
+
bulletList?: boolean;
|
|
282
|
+
orderedList?: boolean;
|
|
283
|
+
headings?: (1 | 2 | 3 | 4 | 5 | 6)[];
|
|
284
|
+
horizontalRule?: boolean;
|
|
285
|
+
link?: boolean;
|
|
286
|
+
blockquote?: boolean;
|
|
287
|
+
code?: boolean;
|
|
288
|
+
codeBlock?: boolean;
|
|
289
|
+
undo?: boolean;
|
|
290
|
+
redo?: boolean;
|
|
291
|
+
customButtons?: _3ddv_software_division_components_generic_rich_text_editor.CustomToolbarButton[];
|
|
292
|
+
}>;
|
|
293
|
+
/** Check if any formatting option is enabled */
|
|
294
|
+
protected readonly hasFormattingOptions: _angular_core.Signal<boolean | undefined>;
|
|
295
|
+
/** Check if any list option is enabled */
|
|
296
|
+
protected readonly hasListOptions: _angular_core.Signal<boolean | undefined>;
|
|
297
|
+
/** Check if any heading is enabled */
|
|
298
|
+
protected readonly hasHeadings: _angular_core.Signal<boolean | undefined>;
|
|
299
|
+
/** Check if history buttons are enabled */
|
|
300
|
+
protected readonly hasHistory: _angular_core.Signal<boolean | undefined>;
|
|
301
|
+
/** Check if code options are enabled */
|
|
302
|
+
protected readonly hasCodeOptions: _angular_core.Signal<boolean | undefined>;
|
|
303
|
+
/** Toggle mobile menu visibility */
|
|
304
|
+
toggleMobileMenu(): void;
|
|
305
|
+
/** Toggle heading with smart selection handling */
|
|
306
|
+
toggleHeading(level: 1 | 2 | 3 | 4 | 5 | 6): void;
|
|
307
|
+
/** Request link insertion/editing */
|
|
308
|
+
setLink(): void;
|
|
309
|
+
/** Toggle bold formatting */
|
|
310
|
+
toggleBold(): void;
|
|
311
|
+
/** Toggle italic formatting */
|
|
312
|
+
toggleItalic(): void;
|
|
313
|
+
/** Toggle underline formatting */
|
|
314
|
+
toggleUnderline(): void;
|
|
315
|
+
/** Toggle strikethrough formatting */
|
|
316
|
+
toggleStrike(): void;
|
|
317
|
+
/** Toggle bullet list */
|
|
318
|
+
toggleBulletList(): void;
|
|
319
|
+
/** Toggle ordered list */
|
|
320
|
+
toggleOrderedList(): void;
|
|
321
|
+
/** Insert horizontal rule */
|
|
322
|
+
insertHorizontalRule(): void;
|
|
323
|
+
/** Toggle blockquote */
|
|
324
|
+
toggleBlockquote(): void;
|
|
325
|
+
/** Toggle inline code */
|
|
326
|
+
toggleCode(): void;
|
|
327
|
+
/** Toggle code block */
|
|
328
|
+
toggleCodeBlock(): void;
|
|
329
|
+
/** Undo last action */
|
|
330
|
+
undo(): void;
|
|
331
|
+
/** Redo last undone action */
|
|
332
|
+
redo(): void;
|
|
333
|
+
/** Remove link from selection */
|
|
334
|
+
unsetLink(): void;
|
|
335
|
+
/** Check if a formatting type is active */
|
|
336
|
+
isActive(type: string, options?: Record<string, unknown>): boolean;
|
|
337
|
+
/** Track function for heading levels */
|
|
338
|
+
trackByLevel(index: number, level: number): number;
|
|
339
|
+
/** Track function for custom buttons */
|
|
340
|
+
trackByButtonId(index: number, btn: {
|
|
341
|
+
id: string;
|
|
342
|
+
}): string;
|
|
343
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorToolbarComponent, never>;
|
|
344
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EditorToolbarComponent, "sdc-editor-toolbar", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; }, { "linkRequested": "linkRequested"; }, never, never, true, never>;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export { DEFAULT_EDITOR_CONFIG, DEFAULT_LINK_CONFIG, DEFAULT_TOOLBAR_CONFIG, EditorToolbarComponent, LinkModalComponent, RichTextEditorComponent, TOOLBAR_PRESETS };
|
|
348
|
+
export type { CustomToolbarButton, EditorConfig, ErrorDisplayMode, LinkConfig, LinkData, ToolbarConfig, ToolbarPreset };
|