@elasticias/ui 1.0.53 → 1.0.54
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/elasticias-ui-rich-text.mjs +336 -0
- package/fesm2022/elasticias-ui-rich-text.mjs.map +1 -0
- package/fesm2022/elasticias-ui.mjs +551 -67
- package/fesm2022/elasticias-ui.mjs.map +1 -1
- package/package.json +12 -2
- package/types/elasticias-ui-rich-text.d.ts +151 -0
- package/types/elasticias-ui.d.ts +316 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elasticias/ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^21.0.0",
|
|
6
6
|
"@angular/core": "^21.0.0",
|
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
"chart.js": "^4.5.0",
|
|
16
16
|
"primeng": "^21.0.0",
|
|
17
17
|
"rxjs": "~7.8.0",
|
|
18
|
-
"@angular/platform-browser": "21.2"
|
|
18
|
+
"@angular/platform-browser": "21.2",
|
|
19
|
+
"quill": "^2.0.3"
|
|
20
|
+
},
|
|
21
|
+
"peerDependenciesMeta": {
|
|
22
|
+
"quill": {
|
|
23
|
+
"optional": true
|
|
24
|
+
}
|
|
19
25
|
},
|
|
20
26
|
"sideEffects": false,
|
|
21
27
|
"repository": {
|
|
@@ -36,6 +42,10 @@
|
|
|
36
42
|
".": {
|
|
37
43
|
"types": "./types/elasticias-ui.d.ts",
|
|
38
44
|
"default": "./fesm2022/elasticias-ui.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./rich-text": {
|
|
47
|
+
"types": "./types/elasticias-ui-rich-text.d.ts",
|
|
48
|
+
"default": "./fesm2022/elasticias-ui-rich-text.mjs"
|
|
39
49
|
}
|
|
40
50
|
},
|
|
41
51
|
"type": "module",
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { DoCheck, EventEmitter, Provider } from '@angular/core';
|
|
3
|
+
import { ControlValueAccessor, NgControl } from '@angular/forms';
|
|
4
|
+
import { EditorInitEvent } from 'primeng/editor';
|
|
5
|
+
import { AbstractEfFormControl } from '@elasticias/ui';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A rich text field: PrimeNG's Editor (Quill 2) with a small toolbar (bold,
|
|
9
|
+
* italic, underline, bulleted and numbered lists, link, clear formatting) and
|
|
10
|
+
* sanitised HTML out (`sanitizeRichHtml`): the toolbar's tags only, safe links,
|
|
11
|
+
* no script, style, class or event attribute, and `''` for an empty editor.
|
|
12
|
+
*
|
|
13
|
+
* It lives in `@elasticias/ui/rich-text` so that only apps that use it bundle
|
|
14
|
+
* the editor and need `quill` (a peer dependency of this entry). PrimeNG loads
|
|
15
|
+
* Quill with a dynamic import the first time an editor renders, so a screen
|
|
16
|
+
* without one never downloads it. `ef-localized-input`'s `rich` mode renders
|
|
17
|
+
* it through `EF_RICH_TEXT`; provide that with `provideEfRichText()`.
|
|
18
|
+
*
|
|
19
|
+
* - `dir` and `lang` apply to the editing area only; the toolbar is page chrome.
|
|
20
|
+
* - Disabled by `[disabled]`, a form's `disable()` or `[efReadOnly]`; `readonly`
|
|
21
|
+
* keeps the text selectable. The toolbar is disabled with it.
|
|
22
|
+
* - The editing area is a `role="textbox"` named by the label and described
|
|
23
|
+
* by the hint, the errors and `describedByExtra`.
|
|
24
|
+
* - An incoming value equal to what it last emitted is ignored, so binding
|
|
25
|
+
* the output back never resets the caret.
|
|
26
|
+
*
|
|
27
|
+
* i18n keys the app's bundles must define (toolbar names and the link bubble,
|
|
28
|
+
* whose Quill texts are otherwise hardcoded English):
|
|
29
|
+
*
|
|
30
|
+
* | key | fr | ar | en |
|
|
31
|
+
* |---|---|---|---|
|
|
32
|
+
* | `ef_rich_text_bold` | Gras | غامق | Bold |
|
|
33
|
+
* | `ef_rich_text_italic` | Italique | مائل | Italic |
|
|
34
|
+
* | `ef_rich_text_underline` | Souligné | تسطير | Underline |
|
|
35
|
+
* | `ef_rich_text_bullet_list` | Liste à puces | قائمة نقطية | Bulleted list |
|
|
36
|
+
* | `ef_rich_text_ordered_list` | Liste numérotée | قائمة مرقمة | Numbered list |
|
|
37
|
+
* | `ef_rich_text_link` | Lien | رابط | Link |
|
|
38
|
+
* | `ef_rich_text_clean` | Effacer la mise en forme | مسح التنسيق | Clear formatting |
|
|
39
|
+
* | `ef_rich_text_toolbar` | Mise en forme | التنسيق | Formatting |
|
|
40
|
+
* | `ef_rich_text_link_enter` | Adresse du lien : | عنوان الرابط: | Link address: |
|
|
41
|
+
* | `ef_rich_text_link_visit` | Ouvrir : | فتح: | Open: |
|
|
42
|
+
* | `ef_rich_text_link_edit` | Modifier | تعديل | Edit |
|
|
43
|
+
* | `ef_rich_text_link_remove` | Retirer | إزالة | Remove |
|
|
44
|
+
* | `ef_rich_text_link_save` | Enregistrer | حفظ | Save |
|
|
45
|
+
*
|
|
46
|
+
* ```html
|
|
47
|
+
* <ef-rich-text name="description" labelKey="product_description" dir="rtl" lang="ar"
|
|
48
|
+
* [value]="html()" (valueChangeEvent)="html.set($event)" />
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare class EfRichTextComponent extends AbstractEfFormControl implements ControlValueAccessor, DoCheck {
|
|
52
|
+
readonly value: _angular_core.InputSignal<string | null | undefined>;
|
|
53
|
+
/** Direction of the text (`rtl` for Arabic), on the editing area only. */
|
|
54
|
+
readonly dir: _angular_core.InputSignal<"ltr" | "rtl" | "auto" | null>;
|
|
55
|
+
/** Language of the text, on the editing area only. */
|
|
56
|
+
readonly lang: _angular_core.InputSignal<string | null>;
|
|
57
|
+
/** Id(s) naming the editing area when the label is rendered elsewhere
|
|
58
|
+
* (`ef-localized-input` draws one label above its culture tabs). */
|
|
59
|
+
readonly labelledBy: _angular_core.InputSignal<string | null>;
|
|
60
|
+
/** Visible height of the editing area, in lines. */
|
|
61
|
+
readonly rows: _angular_core.InputSignal<number>;
|
|
62
|
+
/** Sanitised HTML, `''` when the editor holds no text. */
|
|
63
|
+
readonly valueChangeEvent: EventEmitter<string>;
|
|
64
|
+
readonly ngControl: NgControl | null;
|
|
65
|
+
private readonly host;
|
|
66
|
+
protected readonly formats: string[];
|
|
67
|
+
protected readonly modules: {
|
|
68
|
+
keyboard: {
|
|
69
|
+
bindings: {
|
|
70
|
+
tab: {
|
|
71
|
+
key: string;
|
|
72
|
+
handler: () => boolean;
|
|
73
|
+
};
|
|
74
|
+
'indent code-block': null;
|
|
75
|
+
'outdent code-block': null;
|
|
76
|
+
'remove tab': null;
|
|
77
|
+
indent: {
|
|
78
|
+
format: string[];
|
|
79
|
+
key: string;
|
|
80
|
+
handler: () => boolean;
|
|
81
|
+
};
|
|
82
|
+
outdent: {
|
|
83
|
+
shiftKey: boolean;
|
|
84
|
+
format: string[];
|
|
85
|
+
key: string;
|
|
86
|
+
handler: () => boolean;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
protected readonly labelId: string;
|
|
92
|
+
private readonly current;
|
|
93
|
+
private readonly quill;
|
|
94
|
+
private lastEmitted;
|
|
95
|
+
private onChange;
|
|
96
|
+
private onTouched;
|
|
97
|
+
constructor();
|
|
98
|
+
get isInvalid(): boolean;
|
|
99
|
+
get serverErrors(): string[] | null;
|
|
100
|
+
get showRequired(): boolean;
|
|
101
|
+
/** Read-only or disabled: Quill and the toolbar stop editing. */
|
|
102
|
+
protected locked(): boolean;
|
|
103
|
+
protected onInit(event: EditorInitEvent): void;
|
|
104
|
+
protected onTextChange(): void;
|
|
105
|
+
protected handleBlur(): void;
|
|
106
|
+
ngDoCheck(): void;
|
|
107
|
+
writeValue(v: string | null): void;
|
|
108
|
+
registerOnChange(fn: (v: string) => void): void;
|
|
109
|
+
registerOnTouched(fn: () => void): void;
|
|
110
|
+
setDisabledState(disabled: boolean): void;
|
|
111
|
+
/** Replaces the content unless it is our own echo or the same HTML. */
|
|
112
|
+
private apply;
|
|
113
|
+
/** Role, name, state, direction and language: everything that follows signals. */
|
|
114
|
+
private decorateFromInputs;
|
|
115
|
+
/** Validity and what describes the field, which follow the form control. */
|
|
116
|
+
private decorateFromForm;
|
|
117
|
+
/** Quill's link bubble texts are hardcoded English in its CSS; ours come from attributes. */
|
|
118
|
+
private translateBubble;
|
|
119
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfRichTextComponent, never>;
|
|
120
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfRichTextComponent, "ef-rich-text", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "dir": { "alias": "dir"; "required": false; "isSignal": true; }; "lang": { "alias": "lang"; "required": false; "isSignal": true; }; "labelledBy": { "alias": "labelledBy"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, { "valueChangeEvent": "valueChangeEvent"; }, never, never, true, never>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Turns on `ef-localized-input`'s `rich` mode for the app. Quill still loads
|
|
125
|
+
* lazily, the first time an editor renders.
|
|
126
|
+
*
|
|
127
|
+
* ```ts
|
|
128
|
+
* providers: [provideEfRichText()]
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function provideEfRichText(): Provider;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Whitelists the HTML an ef-rich-text produces: the toolbar's tags, a link's
|
|
135
|
+
* `href` when it is http(s), mailto or tel (with `rel` and `target` set by us),
|
|
136
|
+
* and no other attribute, so no style, class or event handler leaves the
|
|
137
|
+
* browser. Other tags are unwrapped, keeping their text; script, style and
|
|
138
|
+
* frames go with their content. Quill's non-breaking spaces between words
|
|
139
|
+
* become spaces. An editor holding no text returns `''`, never `<p><br></p>`.
|
|
140
|
+
*
|
|
141
|
+
* Browser only: it parses into a `<template>` and so needs `document`.
|
|
142
|
+
*
|
|
143
|
+
* Security note: `npm audit` flags quill 2.0.3 (GHSA-v3m3-f69x-jf25, XSS via
|
|
144
|
+
* HTML export; low severity, no patched release). It is mitigated here
|
|
145
|
+
* because every value ef-rich-text emits goes through this function, and
|
|
146
|
+
* incoming HTML goes through it before Quill parses it. Never render
|
|
147
|
+
* `getSemanticHTML()` without it.
|
|
148
|
+
*/
|
|
149
|
+
declare function sanitizeRichHtml(html: string | null | undefined): string;
|
|
150
|
+
|
|
151
|
+
export { EfRichTextComponent, provideEfRichText, sanitizeRichHtml };
|