@libs-ui/components-inputs-quill2x-preview 0.2.356-42 → 0.2.356-43
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/README.md
CHANGED
|
@@ -1,26 +1,35 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @libs-ui/components-inputs-quill2x-preview
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Component hiển thị nội dung Rich Text HTML từ trình soạn thảo Quill2x một cách an toàn, với tính năng Xem thêm / Thu gọn thông minh.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Giới thiệu
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- 🛡️ **HTML Security**: Sử dụng `LibsUiPipesSecurityTrustPipe` để sanitize nội dung HTML, ngăn chặn các cuộc tấn công XSS.
|
|
9
|
-
- 📉 **View More / Collapse**: Tự động kiểm tra độ cao của nội dung. Nếu vượt quá `maxHeight`, component sẽ hiển thị nút "Xem thêm" và hiệu ứng gradient mờ dần ở đáy.
|
|
10
|
-
- 🎨 **Custom Styling**: Cho phép truyền thêm class tùy biến cho container thông qua input `containerClass`.
|
|
11
|
-
- ⚡ **Performance**: Sử dụng `ChangeDetectionStrategy.OnPush` để tối ưu hiệu năng render.
|
|
7
|
+
`@libs-ui/components-inputs-quill2x-preview` là component chuyên dụng để render nội dung HTML được tạo ra bởi trình soạn thảo Quill2x. Component tự động sanitize nội dung qua `LibsUiPipesSecurityTrustPipe` để ngăn chặn XSS, đồng thời hỗ trợ cơ chế thu gọn / mở rộng thông minh khi nội dung quá dài. Styling được kế thừa từ Quill Snow theme đảm bảo nội dung hiển thị nhất quán với trình soạn thảo.
|
|
12
8
|
|
|
13
|
-
##
|
|
9
|
+
## Tính năng
|
|
10
|
+
|
|
11
|
+
- ✅ **Hiển thị nhất quán** — Kế thừa Quill Snow theme styles, đảm bảo nội dung render giống hệt trình soạn thảo
|
|
12
|
+
- ✅ **Bảo mật XSS** — Tự động sanitize HTML qua `LibsUiPipesSecurityTrustPipe` với `useXssFilter: true`
|
|
13
|
+
- ✅ **Xem thêm / Thu gọn** — Tự động phát hiện nội dung vượt `maxHeight`, hiển thị nút điều khiển và hiệu ứng gradient mờ
|
|
14
|
+
- ✅ **Two-way binding** — `expand` là `model()` hỗ trợ kiểm soát trạng thái mở rộng từ bên ngoài
|
|
15
|
+
- ✅ **Custom class** — Cho phép truyền thêm CSS class vào container qua `containerClass`
|
|
16
|
+
- ✅ **Label tùy biến** — Nhãn nút Xem thêm / Thu gọn có thể tùy chỉnh hoặc dùng i18n key mặc định
|
|
17
|
+
- ✅ **Performance** — `ChangeDetectionStrategy.OnPush` + Signal API tối ưu hiệu năng render
|
|
18
|
+
|
|
19
|
+
## Khi nào sử dụng
|
|
20
|
+
|
|
21
|
+
- Khi cần hiển thị nội dung được tạo ra bởi trình soạn thảo Quill2x (rich text, HTML)
|
|
22
|
+
- Khi cần render HTML từ API một cách an toàn mà không lo XSS
|
|
23
|
+
- Khi muốn giới hạn không gian hiển thị cho bài viết dài trong danh sách hoặc feed
|
|
24
|
+
- Khi cần hiển thị preview nội dung email, mô tả sản phẩm, bài viết blog có định dạng phong phú
|
|
14
25
|
|
|
15
|
-
|
|
26
|
+
## Cài đặt
|
|
16
27
|
|
|
17
28
|
```bash
|
|
18
29
|
npm install @libs-ui/components-inputs-quill2x-preview
|
|
19
30
|
```
|
|
20
31
|
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
### Import Module
|
|
32
|
+
## Import
|
|
24
33
|
|
|
25
34
|
```typescript
|
|
26
35
|
import { LibsUiComponentsInputsQuill2xPreviewComponent } from '@libs-ui/components-inputs-quill2x-preview';
|
|
@@ -33,43 +42,175 @@ import { LibsUiComponentsInputsQuill2xPreviewComponent } from '@libs-ui/componen
|
|
|
33
42
|
export class YourComponent {}
|
|
34
43
|
```
|
|
35
44
|
|
|
36
|
-
|
|
45
|
+
## Ví dụ sử dụng
|
|
46
|
+
|
|
47
|
+
### Ví dụ 1 — Hiển thị cơ bản
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// component.ts
|
|
51
|
+
import { Component, signal } from '@angular/core';
|
|
52
|
+
import { LibsUiComponentsInputsQuill2xPreviewComponent } from '@libs-ui/components-inputs-quill2x-preview';
|
|
53
|
+
|
|
54
|
+
@Component({
|
|
55
|
+
standalone: true,
|
|
56
|
+
imports: [LibsUiComponentsInputsQuill2xPreviewComponent],
|
|
57
|
+
templateUrl: './article-detail.component.html',
|
|
58
|
+
})
|
|
59
|
+
export class ArticleDetailComponent {
|
|
60
|
+
protected articleContent = signal<string>(
|
|
61
|
+
'<h2>Tiêu đề bài viết</h2><p>Đây là nội dung bài viết với <strong>in đậm</strong> và <em>in nghiêng</em>.</p>'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
37
65
|
|
|
38
66
|
```html
|
|
39
|
-
|
|
67
|
+
<!-- article-detail.component.html -->
|
|
68
|
+
<libs_ui-components-inputs-quill2x-preview
|
|
69
|
+
[data]="articleContent()">
|
|
70
|
+
</libs_ui-components-inputs-quill2x-preview>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Ví dụ 2 — Xem thêm / Thu gọn cho nội dung dài
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// component.ts
|
|
77
|
+
import { Component, signal } from '@angular/core';
|
|
78
|
+
import { LibsUiComponentsInputsQuill2xPreviewComponent } from '@libs-ui/components-inputs-quill2x-preview';
|
|
79
|
+
|
|
80
|
+
@Component({
|
|
81
|
+
standalone: true,
|
|
82
|
+
imports: [LibsUiComponentsInputsQuill2xPreviewComponent],
|
|
83
|
+
templateUrl: './news-feed.component.html',
|
|
84
|
+
})
|
|
85
|
+
export class NewsFeedComponent {
|
|
86
|
+
protected postContent = signal<string>(`
|
|
87
|
+
<h3>Thông báo quan trọng</h3>
|
|
88
|
+
<p>Đây là nội dung bài viết rất dài với nhiều đoạn văn...</p>
|
|
89
|
+
<ul>
|
|
90
|
+
<li>Điểm thứ nhất cần chú ý</li>
|
|
91
|
+
<li>Điểm thứ hai cần chú ý</li>
|
|
92
|
+
<li>Điểm thứ ba cần chú ý</li>
|
|
93
|
+
<li>Điểm thứ tư cần chú ý</li>
|
|
94
|
+
<li>Điểm thứ năm cần chú ý</li>
|
|
95
|
+
</ul>
|
|
96
|
+
<p>Kết luận của bài viết.</p>
|
|
97
|
+
`);
|
|
98
|
+
protected isExpanded = signal<boolean>(false);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<!-- news-feed.component.html -->
|
|
104
|
+
<libs_ui-components-inputs-quill2x-preview
|
|
105
|
+
[data]="postContent()"
|
|
106
|
+
[maxHeight]="120"
|
|
107
|
+
[hasButtonCollapseExpand]="true"
|
|
108
|
+
[labelButtonViewMore]="'Xem toàn bộ bài viết'"
|
|
109
|
+
[labelButtonCollapse]="'Thu gọn bài viết'"
|
|
110
|
+
[(expand)]="isExpanded()">
|
|
111
|
+
</libs_ui-components-inputs-quill2x-preview>
|
|
40
112
|
```
|
|
41
113
|
|
|
42
|
-
###
|
|
114
|
+
### Ví dụ 3 — Tùy biến CSS class và kiểm soát expand từ bên ngoài
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// component.ts
|
|
118
|
+
import { Component, signal } from '@angular/core';
|
|
119
|
+
import { LibsUiComponentsInputsQuill2xPreviewComponent } from '@libs-ui/components-inputs-quill2x-preview';
|
|
120
|
+
|
|
121
|
+
@Component({
|
|
122
|
+
standalone: true,
|
|
123
|
+
imports: [LibsUiComponentsInputsQuill2xPreviewComponent],
|
|
124
|
+
templateUrl: './product-description.component.html',
|
|
125
|
+
})
|
|
126
|
+
export class ProductDescriptionComponent {
|
|
127
|
+
protected description = signal<string>(
|
|
128
|
+
'<p style="color: #ee2d41; font-size: 18px;"><strong>Sản phẩm nổi bật</strong></p><p>Mô tả chi tiết sản phẩm với nhiều thông tin hữu ích.</p>'
|
|
129
|
+
);
|
|
130
|
+
protected isOpen = signal<boolean>(false);
|
|
131
|
+
|
|
132
|
+
protected handlerToggleExpand(event: Event): void {
|
|
133
|
+
event.stopPropagation();
|
|
134
|
+
this.isOpen.update((val) => !val);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
43
138
|
|
|
44
139
|
```html
|
|
140
|
+
<!-- product-description.component.html -->
|
|
141
|
+
<button (click)="handlerToggleExpand($event)">
|
|
142
|
+
{{ isOpen() ? 'Thu gọn' : 'Mở rộng' }}
|
|
143
|
+
</button>
|
|
144
|
+
|
|
45
145
|
<libs_ui-components-inputs-quill2x-preview
|
|
46
|
-
[data]="
|
|
146
|
+
[data]="description()"
|
|
147
|
+
[containerClass]="'border border-gray-200 rounded p-2'"
|
|
47
148
|
[maxHeight]="200"
|
|
48
149
|
[hasButtonCollapseExpand]="true"
|
|
49
|
-
[
|
|
50
|
-
|
|
150
|
+
[(expand)]="isOpen()">
|
|
151
|
+
</libs_ui-components-inputs-quill2x-preview>
|
|
51
152
|
```
|
|
52
153
|
|
|
53
|
-
##
|
|
154
|
+
## @Input()
|
|
155
|
+
|
|
156
|
+
| Input | Type | Default | Mô tả | Ví dụ |
|
|
157
|
+
|---|---|---|---|---|
|
|
158
|
+
| `data` | `string` | **(Required)** | Chuỗi HTML cần hiển thị. Nội dung sẽ được tự động sanitize trước khi render | `[data]="articleHtml()"` |
|
|
159
|
+
| `containerClass` | `string` | `undefined` | Class CSS bổ sung cho thẻ `.ql-container` bên trong. Dùng để override style hoặc thêm border/padding | `[containerClass]="'border rounded p-2'"` |
|
|
160
|
+
| `expand` | `boolean` | `undefined` | Trạng thái mở rộng / thu gọn. Là `model()` — hỗ trợ two-way binding `[(expand)]` | `[(expand)]="isExpanded()"` |
|
|
161
|
+
| `hasButtonCollapseExpand` | `boolean` | `undefined` (falsy) | Bật tính năng giới hạn chiều cao và nút Xem thêm / Thu gọn. Khi `true`, component đo chiều cao sau render | `[hasButtonCollapseExpand]="true"` |
|
|
162
|
+
| `maxHeight` | `number` | `160` | Chiều cao tối đa tính bằng pixel trước khi kích hoạt nút Xem thêm. Nếu truyền `undefined` hoặc `0`, mặc định về `160` | `[maxHeight]="200"` |
|
|
163
|
+
| `labelButtonViewMore` | `string` | `'i18n_view_more'` | Nhãn hiển thị trên nút Xem thêm. Nếu không truyền, dùng i18n key `i18n_view_more` | `[labelButtonViewMore]="'Xem toàn bộ'"` |
|
|
164
|
+
| `labelButtonCollapse` | `string` | `'i18n_collapse'` | Nhãn hiển thị trên nút Thu gọn. Nếu không truyền, dùng i18n key `i18n_collapse` | `[labelButtonCollapse]="'Thu gọn lại'"` |
|
|
54
165
|
|
|
55
|
-
|
|
166
|
+
## Logic ngầm quan trọng
|
|
56
167
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
168
|
+
### Tự động phát hiện nội dung dài
|
|
169
|
+
|
|
170
|
+
Khi `hasButtonCollapseExpand` là `true`, trong `ngAfterViewInit` component dùng `timer(250)` chờ DOM render xong rồi so sánh `offsetHeight` của container với `maxHeight + 28`:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
timer(250)
|
|
174
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
175
|
+
.subscribe(() => {
|
|
176
|
+
this.hasShowMore.set(
|
|
177
|
+
this.previewRef().nativeElement.offsetHeight > this.maxHeight() + 28
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
```
|
|
66
181
|
|
|
67
|
-
|
|
182
|
+
Delay 250ms là cần thiết để Quill styles được áp dụng đầy đủ trước khi đo chiều cao. Nếu nội dung **không** vượt ngưỡng, nút Xem thêm **không** xuất hiện dù `hasButtonCollapseExpand = true`.
|
|
68
183
|
|
|
69
|
-
|
|
70
|
-
- **Styles**: Quill "snow" theme compatible styles
|
|
71
|
-
- **Pipes**: `@libs-ui/pipes-security-trust`
|
|
184
|
+
### Hiệu ứng gradient fade
|
|
72
185
|
|
|
73
|
-
|
|
186
|
+
Khi nội dung bị thu gọn (`hasShowMore() && !expand()`), một lớp overlay gradient trắng được chèn tuyệt đối ở đáy container tạo hiệu ứng chuyển tiếp mượt mà:
|
|
187
|
+
|
|
188
|
+
```html
|
|
189
|
+
<div class="absolute bottom-[28px] w-full h-[40px] opacity-[0.5]
|
|
190
|
+
bg-[linear-gradient(180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.95)_51.56%,#fff_100%)]">
|
|
191
|
+
</div>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### CSS fix Quill 2.x list rendering
|
|
195
|
+
|
|
196
|
+
Component có SCSS override phức tạp để sửa lỗi đánh số tự động bị sai trong Quill 2.x khi xen kẽ giữa danh sách ordered và bullet. Sử dụng `counter-reset` và `counter-increment` tùy chỉnh thay vì dựa vào CSS mặc định của Quill.
|
|
197
|
+
|
|
198
|
+
## Lưu ý quan trọng
|
|
199
|
+
|
|
200
|
+
⚠️ **Sanitization tự động**: Component dùng `LibsUiPipesSecurityTrustPipe` với `useXssFilter: true` để sanitize HTML. Không cần sanitize thủ công trước khi truyền vào `[data]`.
|
|
201
|
+
|
|
202
|
+
⚠️ **Quill CSS dependency**: Component yêu cầu Quill Snow theme CSS được load trên trang để styles hiển thị đúng. Nếu không có, nội dung vẫn render nhưng có thể mất một số định dạng.
|
|
203
|
+
|
|
204
|
+
⚠️ **maxHeight transform**: Input `maxHeight` có transform — nếu truyền `undefined` hoặc `0`, giá trị sẽ tự động về `160`. Đây là hành vi có chủ đích để tránh container bị thu gọn về 0px.
|
|
205
|
+
|
|
206
|
+
⚠️ **expand là model()**: `expand` dùng `model()` thay vì `input()`. Sử dụng `[(expand)]` cho two-way binding. Nếu chỉ cần one-way, dùng `[expand]`.
|
|
207
|
+
|
|
208
|
+
⚠️ **hasButtonCollapseExpand + ngAfterViewInit**: Nút Xem thêm chỉ hiển thị sau khi DOM render xong (sau 250ms). Không nên kiểm tra `hasShowMore` đồng bộ ngay khi component khởi tạo.
|
|
209
|
+
|
|
210
|
+
## Demo
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npx nx serve core-ui
|
|
214
|
+
```
|
|
74
215
|
|
|
75
|
-
|
|
216
|
+
Truy cập: http://localhost:4500/components/inputs/quill2x-preview
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncPipe } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { computed, signal, inject, DestroyRef, input, model, viewChild,
|
|
3
|
+
import { computed, signal, inject, DestroyRef, input, model, viewChild, Component, ChangeDetectionStrategy } from '@angular/core';
|
|
4
4
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
5
|
import { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';
|
|
6
6
|
import { LibsUiPipesSecurityTrustPipe } from '@libs-ui/pipes-security-trust';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libs-ui-components-inputs-quill2x-preview.mjs","sources":["../../../../../../libs-ui/components/inputs/quill2x-preview/src/inputs-quill2x-preview.component.ts","../../../../../../libs-ui/components/inputs/quill2x-preview/src/inputs-quill2x-preview.component.html","../../../../../../libs-ui/components/inputs/quill2x-preview/src/libs-ui-components-inputs-quill2x-preview.ts"],"sourcesContent":["import { AsyncPipe } from '@angular/common';\nimport { AfterViewInit, ChangeDetectionStrategy, Component, computed, DestroyRef, ElementRef, inject, input, model, signal, viewChild } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';\nimport { LibsUiPipesSecurityTrustPipe } from '@libs-ui/pipes-security-trust';\nimport { timer } from 'rxjs';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-inputs-quill2x-preview',\n standalone: true,\n templateUrl: './inputs-quill2x-preview.component.html',\n styleUrl: './inputs-quill2x-preview.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LibsUiPipesSecurityTrustPipe, AsyncPipe, LibsUiComponentsButtonsButtonComponent],\n})\nexport class LibsUiComponentsInputsQuill2xPreviewComponent implements AfterViewInit {\n //region Protected\n protected containerStyleComputed = computed(() => {\n if (this.hasShowMore() && !this.expand()) {\n return { 'max-height': `${this.maxHeight()}px` };\n }\n\n return {};\n });\n protected containerClassComputed = computed(() => {\n if (this.hasShowMore() && !this.expand()) {\n return `ql-container ${this.containerClass() || ''} overflow-hidden`;\n }\n\n return `ql-container ${this.containerClass() || ''}`;\n });\n protected hasShowMore = signal<boolean>(false);\n //endregion\n //region Private\n protected destroyRef = inject(DestroyRef);\n //endregion\n //region Inputs\n readonly data = input.required<string>();\n readonly containerClass = input<string>();\n readonly expand = model<boolean>();\n readonly hasButtonCollapseExpand = input<boolean>();\n readonly maxHeight = input<number, number | undefined>(160, { transform: (value) => value || 160 });\n readonly labelButtonCollapse = input<string>();\n readonly labelButtonViewMore = input<string>();\n //endregion\n //region View child\n readonly previewRef = viewChild.required<ElementRef>('preview');\n //endregion\n\n ngAfterViewInit() {\n if (!this.hasButtonCollapseExpand()) {\n return;\n }\n timer(250)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.hasShowMore.set(this.previewRef().nativeElement.offsetHeight > this.maxHeight() + 28));\n }\n\n protected handlerExpand() {\n this.expand.update((value) => !value);\n }\n}\n","<div\n #preview\n class=\"relative\">\n <div\n [style]=\"containerStyleComputed()\"\n [class]=\"containerClassComputed()\"\n [innerHTML]=\"data() | LibsUiPipesSecurityTrustPipe: 'html' : true | async\"></div>\n @if (hasShowMore() && !expand()) {\n <div class=\"absolute bottom-[28px] w-full h-[40px] opacity-[0.5] bg-[linear-gradient(180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.95)_51.56%,#fff_100%)]\"></div>\n }\n @if (hasShowMore()) {\n <libs_ui-components-buttons-button\n [sizeButton]=\"'smaller'\"\n [type]=\"'button-link-primary'\"\n [label]=\"expand() ? labelButtonCollapse() || 'i18n_collapse' : labelButtonViewMore() || 'i18n_view_more'\"\n [classInclude]=\"'!p-0 mt-[12px]'\"\n (outClick)=\"handlerExpand()\" />\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;MAgBa,6CAA6C,CAAA;;AAE9C,IAAA,sBAAsB,GAAG,QAAQ,CAAC,MAAK;QAC/C,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;YACxC,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"libs-ui-components-inputs-quill2x-preview.mjs","sources":["../../../../../../libs-ui/components/inputs/quill2x-preview/src/inputs-quill2x-preview.component.ts","../../../../../../libs-ui/components/inputs/quill2x-preview/src/inputs-quill2x-preview.component.html","../../../../../../libs-ui/components/inputs/quill2x-preview/src/libs-ui-components-inputs-quill2x-preview.ts"],"sourcesContent":["import { AsyncPipe } from '@angular/common';\nimport { AfterViewInit, ChangeDetectionStrategy, Component, computed, DestroyRef, ElementRef, inject, input, model, signal, viewChild } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';\nimport { LibsUiPipesSecurityTrustPipe } from '@libs-ui/pipes-security-trust';\nimport { timer } from 'rxjs';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-inputs-quill2x-preview',\n standalone: true,\n templateUrl: './inputs-quill2x-preview.component.html',\n styleUrl: './inputs-quill2x-preview.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LibsUiPipesSecurityTrustPipe, AsyncPipe, LibsUiComponentsButtonsButtonComponent],\n})\nexport class LibsUiComponentsInputsQuill2xPreviewComponent implements AfterViewInit {\n //region Protected\n protected containerStyleComputed = computed(() => {\n if (this.hasShowMore() && !this.expand()) {\n return { 'max-height': `${this.maxHeight()}px` };\n }\n\n return {};\n });\n protected containerClassComputed = computed(() => {\n if (this.hasShowMore() && !this.expand()) {\n return `ql-container ${this.containerClass() || ''} overflow-hidden`;\n }\n\n return `ql-container ${this.containerClass() || ''}`;\n });\n protected hasShowMore = signal<boolean>(false);\n //endregion\n //region Private\n protected destroyRef = inject(DestroyRef);\n //endregion\n //region Inputs\n readonly data = input.required<string>();\n readonly containerClass = input<string>();\n readonly expand = model<boolean>();\n readonly hasButtonCollapseExpand = input<boolean>();\n readonly maxHeight = input<number, number | undefined>(160, { transform: (value) => value || 160 });\n readonly labelButtonCollapse = input<string>();\n readonly labelButtonViewMore = input<string>();\n //endregion\n //region View child\n readonly previewRef = viewChild.required<ElementRef>('preview');\n //endregion\n\n ngAfterViewInit() {\n if (!this.hasButtonCollapseExpand()) {\n return;\n }\n timer(250)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.hasShowMore.set(this.previewRef().nativeElement.offsetHeight > this.maxHeight() + 28));\n }\n\n protected handlerExpand() {\n this.expand.update((value) => !value);\n }\n}\n","<div\n #preview\n class=\"relative\">\n <div\n [style]=\"containerStyleComputed()\"\n [class]=\"containerClassComputed()\"\n [innerHTML]=\"data() | LibsUiPipesSecurityTrustPipe: 'html' : true | async\"></div>\n @if (hasShowMore() && !expand()) {\n <div class=\"absolute bottom-[28px] w-full h-[40px] opacity-[0.5] bg-[linear-gradient(180deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.95)_51.56%,#fff_100%)]\"></div>\n }\n @if (hasShowMore()) {\n <libs_ui-components-buttons-button\n [sizeButton]=\"'smaller'\"\n [type]=\"'button-link-primary'\"\n [label]=\"expand() ? labelButtonCollapse() || 'i18n_collapse' : labelButtonViewMore() || 'i18n_view_more'\"\n [classInclude]=\"'!p-0 mt-[12px]'\"\n (outClick)=\"handlerExpand()\" />\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-inputs-quill2x-preview",
|
|
3
|
-
"version": "0.2.356-
|
|
3
|
+
"version": "0.2.356-43",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^18.2.0",
|
|
6
6
|
"@angular/core": "^18.2.0",
|
|
7
|
-
"@libs-ui/components-buttons-button": "0.2.356-
|
|
8
|
-
"@libs-ui/pipes-security-trust": "0.2.356-
|
|
7
|
+
"@libs-ui/components-buttons-button": "0.2.356-43",
|
|
8
|
+
"@libs-ui/pipes-security-trust": "0.2.356-43",
|
|
9
9
|
"rxjs": "~7.8.0"
|
|
10
10
|
},
|
|
11
11
|
"sideEffects": false,
|