@libs-ui/components-line-clamp 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,102 +1,300 @@
1
- # Line Clamp Component
1
+ # @libs-ui/components-line-clamp
2
2
 
3
- `@libs-ui/components-line-clamp` một component hữu ích dùng để giới hạn số dòng hiển thị của một đoạn văn bản dài, cung cấp tính năng "Xem thêm" (View more) và "Thu gọn" (Collapse), cùng với hỗ trợ hiển thị Tooltip cho nội dung đầy đủ.
3
+ > Component giới hạn số dòng văn bản, hỗ trợ nút Xem thêm / Thu gọn Tooltip tích hợp sẵn.
4
4
 
5
- ## Tính năng nổi bật
5
+ ## Giới thiệu
6
6
 
7
- - ✂️ **Giới hạn dòng (Line Clamping)**: Trực tiếp giới hạn số dòng dựa trên `maxHeight`.
8
- - 🔗 **View More / Collapse**: Tự động hiển thị nút điều khiển khi nội dung vượt quá giới hạn.
9
- - 💬 **Tooltip Support**: Tích hợp sẵn Tooltip để người dùng xem nhanh nội dung đầy đủ khi hover mà không cần mở rộng.
10
- - 🎨 **Custom Styling**: Dễ dàng tùy chỉnh class cho nội dung và các nút điều khiển thông qua `ngClassObject`.
11
- - 🔒 **Security**: Hỗ trợ lọc XSS thông qua `useXssFilter` và hỗ trợ cả `innerHTML` lẫn `innerText`.
12
- - 🌈 **Gradient Effect**: Tùy chọn hiển thị hiệu ứng mờ dần (gradient) ở cuối đoạn văn bản bị cắt.
7
+ `@libs-ui/components-line-clamp` component Angular dùng để cắt ngắn đoạn văn bản dài theo chiều cao tối đa (px) tự động hiển thị nút điều khiển "Xem thêm" / "Thu gọn" khi nội dung vượt giới hạn. Component hỗ trợ render cả HTML (có lọc XSS) lẫn plain text, tích hợp Tooltip khi hover, hiệu ứng gradient mờ dần, và cung cấp `FunctionsControl` để component cha điều khiển trực tiếp qua `ViewChild`.
13
8
 
14
- ## Cài đặt
9
+ ## Tính năng
10
+
11
+ - Giới hạn chiều cao hiển thị dựa trên `maxHeight` (px) — tính toán thực tế từ DOM
12
+ - Tự động hiển thị / ẩn nút "Xem thêm" và "Thu gọn" khi nội dung thay đổi
13
+ - Hỗ trợ render HTML an toàn qua `useXssFilter` hoặc plain text qua `isInnerText`
14
+ - Tích hợp Tooltip (Popover) hiển thị nội dung đầy đủ khi hover
15
+ - Hiệu ứng gradient mờ dần ở cuối đoạn văn bị cắt (`hasBackgroundGradient`)
16
+ - Tự động refresh khi cửa sổ trình duyệt resize (`window:resize`)
17
+ - Cho phép tùy chỉnh nhãn nút, CSS class nội dung và nút điều khiển
18
+ - Cung cấp `FunctionsControl` (refresh, viewMore, hiddenMore, checkIsDisplayLineClamp) để điều khiển từ bên ngoài
19
+ - Hỗ trợ i18n thông qua `@ngx-translate/core`
20
+
21
+ ## Khi nào sử dụng
15
22
 
16
- Sử dụng npm hoặc yarn để cài đặt:
23
+ - Hiển thị phần giới thiệu ngắn trong danh sách thẻ (Card list) khi không đủ không gian
24
+ - Cắt bớt bình luận, mô tả sản phẩm hoặc ghi chú dài trong giao diện Dashboard
25
+ - Cần render HTML từ backend nhưng vẫn đảm bảo an toàn XSS và hỗ trợ rút gọn
26
+ - Muốn người dùng xem nhanh nội dung đầy đủ qua Tooltip mà không cần mở rộng trang
27
+
28
+ ## Cài đặt
17
29
 
18
30
  ```bash
19
31
  npm install @libs-ui/components-line-clamp
20
32
  ```
21
33
 
22
- ## Cách sử dụng
23
-
24
- ### Import Module
34
+ ## Import
25
35
 
26
36
  ```typescript
27
37
  import { LibsUiComponentsLineClampComponent } from '@libs-ui/components-line-clamp';
38
+ import { ILineClampFunctionControlEvent, ILineClampConfig } from '@libs-ui/components-line-clamp';
28
39
 
29
40
  @Component({
30
41
  standalone: true,
31
42
  imports: [LibsUiComponentsLineClampComponent],
32
- // ...
33
43
  })
34
44
  export class YourComponent {}
35
45
  ```
36
46
 
37
- ### Ví dụ bản (Giới hạn độ cao)
47
+ ## Ví dụ sử dụng
38
48
 
39
- ```html
40
- <libs_ui-components-line_clamp
41
- [content]="longText"
42
- [maxHeight]="48"
43
- [labelButtonViewMore]="'Xem thêm'"
44
- [labelButtonCollapse]="'Thu gọn'"></libs_ui-components-line_clamp>
49
+ ### Cắt dòng cơ bản (2 dòng, line-height 20px)
50
+
51
+ ```typescript
52
+ // your.component.ts
53
+ import { Component } from '@angular/core';
54
+ import { LibsUiComponentsLineClampComponent } from '@libs-ui/components-line-clamp';
55
+
56
+ @Component({
57
+ standalone: true,
58
+ imports: [LibsUiComponentsLineClampComponent],
59
+ template: `
60
+ <libs_ui-components-line_clamp
61
+ [content]="longText"
62
+ [maxHeight]="40"
63
+ [labelButtonViewMore]="'Xem thêm nội dung'"
64
+ [labelButtonCollapse]="'Thu gọn lại'">
65
+ </libs_ui-components-line_clamp>
66
+ `,
67
+ })
68
+ export class BasicExampleComponent {
69
+ readonly longText = `Angular là một nền tảng và framework để xây dựng các ứng dụng khách đơn trang
70
+ sử dụng HTML và TypeScript. Nó triển khai chức năng cốt lõi và tùy chọn dưới dạng
71
+ một tập hợp các thư viện TypeScript mà bạn import vào ứng dụng của mình.`;
72
+ }
73
+ ```
74
+
75
+ ### Tooltip và hiệu ứng gradient
76
+
77
+ ```typescript
78
+ // your.component.ts
79
+ import { Component } from '@angular/core';
80
+ import { LibsUiComponentsLineClampComponent } from '@libs-ui/components-line-clamp';
81
+
82
+ @Component({
83
+ standalone: true,
84
+ imports: [LibsUiComponentsLineClampComponent],
85
+ template: `
86
+ <libs_ui-components-line_clamp
87
+ [content]="htmlContent"
88
+ [maxHeight]="60"
89
+ [showTooltip]="true"
90
+ [hasBackgroundGradient]="true"
91
+ [maxWidthTooltip]="350"
92
+ [directionTooltip]="'bottom'">
93
+ </libs_ui-components-line_clamp>
94
+ `,
95
+ })
96
+ export class TooltipExampleComponent {
97
+ readonly htmlContent = `
98
+ <p style="color: #ef4444; font-weight: bold;">Nội dung HTML quan trọng:</p>
99
+ <ul>
100
+ <li>Signal là một cách mới để quản lý state.</li>
101
+ <li>Control Flow Syntax giúp template sạch hơn.</li>
102
+ <li>Deferrable Views giúp tối ưu lazy loading.</li>
103
+ </ul>
104
+ `;
105
+ }
106
+ ```
107
+
108
+ ### Plain text mode (không render HTML)
109
+
110
+ ```typescript
111
+ // your.component.ts
112
+ import { Component } from '@angular/core';
113
+ import { LibsUiComponentsLineClampComponent } from '@libs-ui/components-line-clamp';
114
+
115
+ @Component({
116
+ standalone: true,
117
+ imports: [LibsUiComponentsLineClampComponent],
118
+ template: `
119
+ <libs_ui-components-line_clamp
120
+ [content]="plainText"
121
+ [maxHeight]="40"
122
+ [isInnerText]="true"
123
+ [ngClassObject]="{ 'text-gray-500 italic': true }">
124
+ </libs_ui-components-line_clamp>
125
+ `,
126
+ })
127
+ export class PlainTextExampleComponent {
128
+ readonly plainText = `Đây là văn bản thuần túy, sẽ được render bằng innerText.
129
+ Mọi thẻ HTML trong chuỗi này sẽ hiển thị dưới dạng ký tự thay vì được phân tích cú pháp.`;
130
+ }
131
+ ```
132
+
133
+ ### Điều khiển từ component cha qua FunctionsControl
134
+
135
+ ```typescript
136
+ // parent.component.ts
137
+ import { Component, signal, viewChild } from '@angular/core';
138
+ import {
139
+ LibsUiComponentsLineClampComponent,
140
+ ILineClampFunctionControlEvent,
141
+ } from '@libs-ui/components-line-clamp';
142
+
143
+ @Component({
144
+ standalone: true,
145
+ imports: [LibsUiComponentsLineClampComponent],
146
+ template: `
147
+ <libs_ui-components-line_clamp
148
+ [content]="description"
149
+ [maxHeight]="60"
150
+ (outFunctionControl)="handlerFunctionControl($event)"
151
+ (outAction)="handlerAction($event)"
152
+ (outDisplayLineClamp)="handlerDisplayLineClamp($event)">
153
+ </libs_ui-components-line_clamp>
154
+
155
+ <button (click)="handlerRefresh()">Refresh</button>
156
+ <button (click)="handlerExpandAll()">Mở rộng tất cả</button>
157
+ `,
158
+ })
159
+ export class ParentExampleComponent {
160
+ protected description = `Mô tả dài của sản phẩm sẽ được cắt sau 3 dòng (60px với line-height 20px).
161
+ Nhấn nút bên dưới để điều khiển trạng thái từ component cha.`;
162
+
163
+ private lineClampControl: ILineClampFunctionControlEvent | undefined;
164
+
165
+ protected handlerFunctionControl(control: ILineClampFunctionControlEvent): void {
166
+ this.lineClampControl = control;
167
+ }
168
+
169
+ protected handlerAction(action: string): void {
170
+ // action: 'view-more' | 'hidden-more'
171
+ console.log('Line clamp action:', action);
172
+ }
173
+
174
+ protected handlerDisplayLineClamp(isCollapsed: boolean): void {
175
+ console.log('Is collapsed:', isCollapsed);
176
+ }
177
+
178
+ protected handlerRefresh(): void {
179
+ this.lineClampControl?.refresh();
180
+ }
181
+
182
+ protected handlerExpandAll(): void {
183
+ this.lineClampControl?.viewMore();
184
+ }
185
+ }
45
186
  ```
46
187
 
47
- ### dụ Tooltip Gradient
188
+ ### Ẩn nút thu gọn (chỉ hiển thị "Xem thêm")
48
189
 
49
190
  ```html
50
191
  <libs_ui-components-line_clamp
51
- [content]="htmlContent"
52
- [maxHeight]="60"
53
- [showTooltip]="true"
54
- [hasBackgroundGradient]="true"
55
- [maxWidthTooltip]="300"></libs_ui-components-line_clamp>
192
+ [content]="shortDescription"
193
+ [maxHeight]="40"
194
+ [ignoreShowButtonCollapse]="true"
195
+ [labelButtonViewMore]="'Đọc thêm'">
196
+ </libs_ui-components-line_clamp>
197
+ ```
198
+
199
+ ## @Input()
200
+
201
+ | Input | Type | Default | Mô tả | Ví dụ |
202
+ |---|---|---|---|---|
203
+ | `classClassIncludeButtonCollapseExpand` | `string` | `'!p-0'` | Class CSS cho container wrapper của nút collapse/expand | `[classClassIncludeButtonCollapseExpand]="'mt-2 !p-0'"` |
204
+ | `classClassLabelButtonCollapseExpand` | `string` | `'libs-ui-font-h5r'` | Class CSS typography cho nhãn nút collapse/expand | `[classClassLabelButtonCollapseExpand]="'libs-ui-font-h6r'"` |
205
+ | `content` | `string` | **bắt buộc** | Nội dung văn bản hoặc HTML cần hiển thị và cắt ngắn | `[content]="description"` |
206
+ | `defaultIsCollapse` | `boolean` | `true` | Trạng thái thu gọn mặc định khi nội dung vượt `maxHeight` | `[defaultIsCollapse]="false"` |
207
+ | `directionTooltip` | `TYPE_POPOVER_DIRECTION` | `'top'` | Hướng xuất hiện của Tooltip (top, bottom, left, right) | `[directionTooltip]="'bottom'"` |
208
+ | `hasBackgroundGradient` | `boolean` | `false` | Hiển thị hiệu ứng mờ dần gradient ở cuối đoạn văn bị cắt | `[hasBackgroundGradient]="true"` |
209
+ | `ignoreShowButtonCollapse` | `boolean` | `undefined` | Ẩn nút "Thu gọn", chỉ giữ lại nút "Xem thêm" | `[ignoreShowButtonCollapse]="true"` |
210
+ | `ignoreShowButtonCollapseExpand` | `boolean` | `false` | Ẩn hoàn toàn cả hai nút Xem thêm và Thu gọn | `[ignoreShowButtonCollapseExpand]="true"` |
211
+ | `ignoreStopPropagationTooltipEvent` | `boolean` | `false` | Cho phép sự kiện Tooltip nổi bọt lên component cha | `[ignoreStopPropagationTooltipEvent]="true"` |
212
+ | `isInnerText` | `boolean` | `undefined` | Render nội dung bằng `innerText` thay vì `innerHTML`, mọi thẻ HTML sẽ hiển thị dạng ký tự | `[isInnerText]="true"` |
213
+ | `labelButtonCollapse` | `string` | `undefined` (dùng i18n `i18n_collapse`) | Nhãn tùy chỉnh cho nút Thu gọn | `[labelButtonCollapse]="'Thu gọn lại'"` |
214
+ | `labelButtonViewMore` | `string` | `undefined` (dùng i18n `i18n_view_more`) | Nhãn tùy chỉnh cho nút Xem thêm | `[labelButtonViewMore]="'Xem thêm nội dung'"` |
215
+ | `lengthLimitDisplay` | `number` | `200` | Giới hạn số ký tự dùng để tính toán cắt chuỗi ban đầu trước khi đo DOM | `[lengthLimitDisplay]="300"` |
216
+ | `maxHeight` | `number` | **bắt buộc** | Chiều cao tối đa (px) trước khi cắt. Công thức: `line-height × số dòng`. Ví dụ: `20px × 3 dòng = 60` | `[maxHeight]="60"` |
217
+ | `maxHeightTooltip` | `number` | `150` | Chiều cao tối đa (px) của Tooltip | `[maxHeightTooltip]="200"` |
218
+ | `maxWidthTooltip` | `number` | `250` | Chiều rộng tối đa (px) của Tooltip | `[maxWidthTooltip]="350"` |
219
+ | `ngClassObject` | `TYPE_OBJECT` | `{ 'libs-ui-line-clamp-content libs-ui-font-h5r': true }` | Object `ngClass` để apply class CSS vào div chứa nội dung | `[ngClassObject]="{ 'libs-ui-font-h6r text-gray-700': true }"` |
220
+ | `showTooltip` | `boolean` | `undefined` | Bật Tooltip hiển thị toàn bộ nội dung khi hover vào vùng văn bản đã cắt | `[showTooltip]="true"` |
221
+ | `timeHidePopoverOnMouseout` | `number` | `50` | Thời gian delay (ms) trước khi ẩn Tooltip sau sự kiện `mouseout` | `[timeHidePopoverOnMouseout]="100"` |
222
+ | `useXssFilter` | `boolean` | `true` | Bật bộ lọc XSS cho nội dung HTML (chỉ có hiệu lực khi `isInnerText` là `false`) | `[useXssFilter]="false"` |
223
+ | `zIndexPopover` | `number` | `1001` | Giá trị `z-index` của Tooltip/Popover | `[zIndexPopover]="1050"` |
224
+
225
+ ## @Output()
226
+
227
+ | Output | Type | Mô tả | Handler TS | Binding HTML |
228
+ |---|---|---|---|---|
229
+ | `(outAction)` | `string` | Phát ra chuỗi `'view-more'` khi nhấn nút Xem thêm, hoặc `'hidden-more'` khi nhấn nút Thu gọn | `handlerAction(action: string): void { action.stopPropagation?.(); console.log(action); }` | `(outAction)="handlerAction($event)"` |
230
+ | `(outClick)` | `Event \| TYPE_POPOVER_EVENT` | Phát ra khi người dùng click vào vùng nội dung hoặc Tooltip được click | `handlerClick(event: Event): void { event.stopPropagation(); }` | `(outClick)="handlerClick($event)"` |
231
+ | `(outDisplayLineClamp)` | `boolean` | Phát ra trạng thái thu gọn hiện tại (`true` = đang thu gọn, `false` = đã mở rộng). Kích hoạt khi nội dung vượt `maxHeight` | `handlerDisplayLineClamp(isCollapsed: boolean): void { this.isCollapsed.set(isCollapsed); }` | `(outDisplayLineClamp)="handlerDisplayLineClamp($event)"` |
232
+ | `(outFunctionControl)` | `ILineClampFunctionControlEvent` | Phát ra ngay khi component khởi tạo (`ngOnInit`), cung cấp các method điều khiển để component cha gọi từ bên ngoài | `handlerFunctionControl(control: ILineClampFunctionControlEvent): void { this.lineClampControl = control; }` | `(outFunctionControl)="handlerFunctionControl($event)"` |
233
+
234
+ ## Types & Interfaces
235
+
236
+ ```typescript
237
+ import {
238
+ ILineClampFunctionControlEvent,
239
+ ILineClampConfig,
240
+ } from '@libs-ui/components-line-clamp';
241
+ ```
242
+
243
+ ### ILineClampFunctionControlEvent
244
+
245
+ Interface nhận được qua event `(outFunctionControl)`, dùng để điều khiển component từ bên ngoài:
246
+
247
+ ```typescript
248
+ export interface ILineClampFunctionControlEvent {
249
+ /** Làm mới trạng thái, tính toán lại từ đầu */
250
+ refresh: () => Promise<void>;
251
+
252
+ /** Kiểm tra component có đang ở trạng thái clamp (nội dung bị cắt) không */
253
+ checkIsDisplayLineClamp: () => Promise<boolean>;
254
+
255
+ /** Mở rộng nội dung (tương đương nhấn nút "Xem thêm") */
256
+ viewMore: () => Promise<void>;
257
+
258
+ /** Thu gọn nội dung (tương đương nhấn nút "Thu gọn") */
259
+ hiddenMore: () => Promise<void>;
260
+ }
261
+ ```
262
+
263
+ ### ILineClampConfig
264
+
265
+ Interface cấu hình tùy chọn (dùng cho các trường hợp cần type hóa config object):
266
+
267
+ ```typescript
268
+ import { TYPE_OBJECT } from '@libs-ui/interfaces-types';
269
+
270
+ export interface ILineClampConfig {
271
+ maxHeight?: number;
272
+ class?: string;
273
+ ignoreShowButtonCollapseExpand?: boolean;
274
+ showTooltip?: boolean;
275
+ maxWidthTooltip?: number;
276
+ maxHeightTooltip?: number;
277
+ ngClassObject?: TYPE_OBJECT;
278
+ isInnerText?: boolean;
279
+ }
280
+ ```
281
+
282
+ ## Lưu ý quan trọng
283
+
284
+ ⚠️ **Tính toán maxHeight**: `maxHeight` phải bằng `line-height (px) × số dòng mong muốn`. Ví dụ: text có `line-height: 20px`, muốn hiển thị 3 dòng thì set `[maxHeight]="60"`. Sai giá trị này sẽ khiến việc phát hiện clamp không chính xác.
285
+
286
+ ⚠️ **isInnerText và useXssFilter**: Khi bật `[isInnerText]="true"`, nội dung được render bằng `innerText` — mọi thẻ HTML đều hiển thị dưới dạng ký tự. Trong trường hợp này `useXssFilter` không có tác dụng. Chỉ dùng `useXssFilter` khi render HTML (mặc định).
287
+
288
+ ⚠️ **ngClassObject — CSS typography**: Object `ngClassObject` được apply vào thẻ div bao quanh nội dung. Mặc định là `{ 'libs-ui-line-clamp-content libs-ui-font-h5r': true }`. Khi ghi đè, cần bao gồm cả class layout cần thiết, không chỉ class typography.
289
+
290
+ ⚠️ **outFunctionControl phát ra khi ngOnInit**: Event `(outFunctionControl)` chỉ phát ra một lần duy nhất khi component khởi tạo. Cần lưu lại reference để dùng sau: `private lineClampControl: ILineClampFunctionControlEvent | undefined`.
291
+
292
+ ⚠️ **Resize tự động**: Component lắng nghe sự kiện `window:resize` và tự động gọi `refresh()`. Việc này đảm bảo trạng thái clamp luôn chính xác khi kích thước viewport thay đổi.
293
+
294
+ ## Demo
295
+
296
+ ```bash
297
+ npx nx serve core-ui
56
298
  ```
57
299
 
58
- ## API Reference
59
-
60
- ### Inputs
61
-
62
- | Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |
63
- | :-------------------------------------- | :----------------------- | :----------------- | :------------------------------------------------------------ |
64
- | `classClassIncludeButtonCollapseExpand` | `string` | `'!p-0'` | Class CSS cho container nút collapse/expand. |
65
- | `classClassLabelButtonCollapseExpand` | `string` | `libs-...` | Class CSS cho nhãn nút collapse/expand. |
66
- | `content` | `string` | `required` | Nội dung văn bản hoặc HTML cần hiển thị. |
67
- | `defaultIsCollapse` | `boolean` | `true` | Mặc định thu gọn khi khởi tạo. |
68
- | `directionTooltip` | `TYPE_POPOVER_DIRECTION` | `'top'` | Hướng hiển thị tooltip. |
69
- | `hasBackgroundGradient` | `boolean` | `false` | Hiển thị hiệu ứng mờ dần ở phía dưới khi bị cắt. |
70
- | `ignoreShowButtonCollapse` | `boolean` | `undefined` | Ẩn nút Thu gọn (chỉ hiện nút Xem thêm). |
71
- | `ignoreShowButtonCollapseExpand` | `boolean` | `false` | Ẩn hoàn toàn nút Xem thêm / Thu gọn. |
72
- | `ignoreStopPropagationTooltipEvent` | `boolean` | `false` | Ngăn chặn nổi bọt sự kiện tooltip. |
73
- | `isInnerText` | `boolean` | `false` | Nếu true, sẽ render dưới dạng `innerText` (không xử lý HTML). |
74
- | `labelButtonCollapse` | `string` | `'i18n_collapse'` | Nhãn cho nút Thu gọn. |
75
- | `labelButtonViewMore` | `string` | `'i18n_view_more'` | Nhãn cho nút Xem thêm. |
76
- | `lengthLimitDisplay` | `number` | `200` | Giới hạn số ký tự để tính toán cắt chuỗi ban đầu. |
77
- | `maxHeight` | `number` | `required` | Độ cao tối đa (px). Công thức: (line-height) \* (số dòng). |
78
- | `maxHeightTooltip` | `number` | `150` | Chiều cao tối đa của tooltip. |
79
- | `maxWidthTooltip` | `number` | `250` | Chiều rộng tối đa của tooltip. |
80
- | `ngClassObject` | `TYPE_OBJECT` | `...` | Đối tượng class CSS để apply vào div chứa nội dung. |
81
- | `showTooltip` | `boolean` | `false` | Bật/tắt hiển thị tooltip khi nội dung bị cắt. |
82
- | `timeHidePopoverOnMouseout` | `number` | `50` | Thời gian ẩn tooltip sau khi mouseout (ms). |
83
- | `useXssFilter` | `boolean` | `true` | Bật bộ lọc XSS cho nội dung HTML. |
84
- | `zIndexPopover` | `number` | `1001` | Z-index của tooltip. |
85
-
86
- ### Outputs
87
-
88
- | Sự kiện | Kiểu dữ liệu | Mô tả |
89
- | :-------------------- | :------------------------------- | :----------------------------------------------------------- |
90
- | `outAction` | `string` | Phát ra khi người dùng nhấn 'view-more' hoặc 'hidden-more'. |
91
- | `outClick` | `Event \| TYPE_POPOVER_EVENT` | Phát ra khi người dùng click vào vùng nội dung hoặc tooltip. |
92
- | `outDisplayLineClamp` | `boolean` | Phát ra trạng thái đang thu gọn hay mở rộng. |
93
- | `outFunctionControl` | `ILineClampFunctionControlEvent` | Cung cấp các phương thức điều khiển component (refresh). |
94
-
95
- ## Tech Stack
96
-
97
- - **Core**: Angular 18+, Signals
98
- - **Dependencies**: `@libs-ui/components-popover`, `@libs-ui/components-buttons-button`, `@libs-ui/pipes-security-trust`.
99
-
100
- ## License
101
-
102
- MIT
300
+ Truy cập: http://localhost:4500/components/line-clamp
@@ -1,6 +1,6 @@
1
1
  import { NgClass, AsyncPipe } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { signal, input, output, inject, ElementRef, effect, untracked, Directive, HostListener, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { signal, input, output, inject, ElementRef, effect, untracked, Directive, Component, ChangeDetectionStrategy, HostListener } from '@angular/core';
4
4
  import { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';
5
5
  import { LibsUiComponentsPopoverComponent } from '@libs-ui/components-popover';
6
6
  import { LibsUiPipesEscapeHtmlPipe } from '@libs-ui/pipes-escape-html';
@@ -1 +1 @@
1
- {"version":3,"file":"libs-ui-components-line-clamp.mjs","sources":["../../../../../libs-ui/components/line-clamp/src/line-clamp.directive.ts","../../../../../libs-ui/components/line-clamp/src/line-clamp.component.ts","../../../../../libs-ui/components/line-clamp/src/line-clamp.component.html","../../../../../libs-ui/components/line-clamp/src/libs-ui-components-line-clamp.ts"],"sourcesContent":["import { Directive, effect, ElementRef, inject, input, OnDestroy, output, signal, untracked } from '@angular/core';\n\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[LibsUiComponentsLineClampDirective]',\n standalone: true,\n})\nexport class LibsUiComponentsLineClampDirective implements OnDestroy {\n /** PROPERTY */\n private readonly timeInterval = signal<number | undefined>(undefined);\n private readonly textView = signal<string>('');\n\n /** INPUT */\n readonly lengthLimitDisplay = input.required<number>();\n readonly methodDisplay = input.required<string>();\n readonly content = input.required<string>();\n readonly ignoreThreeDots = input<boolean>();\n\n /** OUTPUT */\n readonly outContentSub = output<string>();\n\n /** INJECT */\n private readonly elementRef = inject(ElementRef);\n\n constructor() {\n effect(() => {\n if (!this.content() || !this.methodDisplay() || !this.lengthLimitDisplay()) {\n return;\n }\n untracked(() => {\n this.textView.set(this.content());\n if (this.textView().length > this.lengthLimitDisplay()) {\n this.textView.update((val) => val.substring(0, this.lengthLimitDisplay()));\n }\n\n if (!this.textView()) {\n return;\n }\n this.process();\n this.timeInterval.set(\n setInterval(() => {\n this.process();\n }, 250)\n );\n });\n });\n }\n\n /** FUNCTIONS */\n\n private process() {\n if (this.elementRef?.nativeElement[this.methodDisplay()]) {\n clearInterval(this.timeInterval());\n this.truncate();\n }\n }\n\n private truncate() {\n let content = this.textView();\n while (this.elementRef.nativeElement.scrollHeight - 2 > this.elementRef.nativeElement.offsetHeight) {\n if (!content) {\n return;\n }\n content = content.substring(0, content.length - 3);\n this.elementRef.nativeElement[this.methodDisplay()] = this.ignoreThreeDots() ? content : `${content}...`;\n }\n if (content !== this.textView()) {\n this.outContentSub.emit(this.ignoreThreeDots() ? content : `${content}...`);\n }\n }\n ngOnDestroy() {\n clearInterval(this.timeInterval());\n }\n}\n","import { AsyncPipe, NgClass } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, HostListener, OnDestroy, OnInit, effect, input, output, signal, untracked } from '@angular/core';\nimport { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';\nimport { LibsUiComponentsPopoverComponent, TYPE_POPOVER_DIRECTION, TYPE_POPOVER_EVENT } from '@libs-ui/components-popover';\nimport { TYPE_OBJECT } from '@libs-ui/interfaces-types';\nimport { LibsUiPipesEscapeHtmlPipe } from '@libs-ui/pipes-escape-html';\nimport { LibsUiPipesSecurityTrustPipe } from '@libs-ui/pipes-security-trust';\nimport { isNil } from '@libs-ui/utils';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { ILineClampFunctionControlEvent } from './interfaces';\nimport { LibsUiComponentsLineClampDirective } from './line-clamp.directive';\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-line_clamp',\n templateUrl: './line-clamp.component.html',\n styleUrls: ['./line-clamp.component.scss'],\n standalone: true,\n imports: [NgClass, TranslateModule, AsyncPipe, LibsUiComponentsLineClampDirective, LibsUiPipesSecurityTrustPipe, LibsUiPipesEscapeHtmlPipe, LibsUiComponentsPopoverComponent, LibsUiComponentsButtonsButtonComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LibsUiComponentsLineClampComponent implements OnInit, OnDestroy {\n /** PROPERTY */\n protected displayLineClamp = signal<boolean>(false);\n protected isCollapse = signal<boolean>(false);\n protected contentClamp = signal<string>('');\n protected contentDisplay = signal<string>('');\n\n /** INPUT */\n readonly content = input.required<string>();\n readonly lengthLimitDisplay = input<number, number | undefined>(200, { transform: (val) => val || 200 });\n readonly maxHeight = input.required<number>(); // maxHeight = (line-height của text)*(số dòng mong muốn)\n readonly ignoreShowButtonCollapseExpand = input<boolean>();\n readonly ignoreShowButtonCollapse = input<boolean>();\n readonly showTooltip = input<boolean>();\n readonly timeHidePopoverOnMouseout = input<number, number | undefined>(50, { transform: (val) => val ?? 50 });\n readonly maxWidthTooltip = input<number, number | undefined>(250, { transform: (val) => val ?? 250 });\n readonly maxHeightTooltip = input<number, number | undefined>(150, { transform: (val) => val ?? 150 });\n readonly zIndexPopover = input<number, number | undefined>(1001, { transform: (val) => val ?? 1001 });\n readonly isInnerText = input<boolean>(); // không cần escapeHTML content khi biến bằng true\n readonly classClassLabelButtonCollapseExpand = input<string, string | undefined>('libs-ui-font-h5r', { transform: (val) => val ?? 'libs-ui-font-h5r' });\n readonly classClassIncludeButtonCollapseExpand = input<string, string | undefined>('!p-0', { transform: (val) => val ?? '!p-0' });\n readonly ignoreStopPropagationTooltipEvent = input<boolean, boolean | undefined>(false, { transform: (val) => val ?? false });\n readonly ngClassObject = input<TYPE_OBJECT, TYPE_OBJECT | undefined>({ 'libs-ui-line-clamp-content libs-ui-font-h5r': true }, { transform: (val) => val || { 'libs-ui-line-clamp-content lib-ui-font-h5r': true } }); // object ngClass\n readonly hasBackgroundGradient = input<boolean, boolean | undefined>(false, { transform: (val) => val ?? false });\n readonly labelButtonViewMore = input<string>();\n readonly labelButtonCollapse = input<string>();\n readonly directionTooltip = input<TYPE_POPOVER_DIRECTION, TYPE_POPOVER_DIRECTION | undefined>('top', { transform: (val) => val ?? 'top' });\n readonly useXssFilter = input<boolean, boolean | undefined>(true, { transform: (val) => val ?? true });\n readonly defaultIsCollapse = input<boolean, boolean | undefined>(true, { transform: (val) => val ?? true });\n\n /** OUTPUT */\n protected readonly outDisplayLineClamp = output<boolean>();\n protected readonly outAction = output<string>();\n protected readonly outClick = output<Event | TYPE_POPOVER_EVENT>();\n protected readonly outFunctionControl = output<ILineClampFunctionControlEvent>();\n\n constructor() {\n effect(() => {\n if (!isNil(this.content())) {\n untracked(() => {\n this.contentDisplay.set('');\n this.displayLineClamp.set(false);\n this.isCollapse.set(false);\n });\n }\n });\n }\n\n async ngOnInit() {\n this.outFunctionControl.emit(this.FunctionsControl);\n }\n\n /** FUNCTIONS */\n public get FunctionsControl(): ILineClampFunctionControlEvent {\n return {\n refresh: this.refresh.bind(this),\n checkIsDisplayLineClamp: async () => this.displayLineClamp(),\n viewMore: this.viewMore.bind(this),\n hiddenMore: this.hiddenMore.bind(this),\n };\n }\n\n protected async handlerContentSub(content: string) {\n if (this.content() !== content) {\n this.displayLineClamp.set(true);\n this.isCollapse.set(this.defaultIsCollapse());\n this.contentClamp.set(content);\n this.contentDisplay.set(this.isCollapse() ? content : this.content());\n this.outDisplayLineClamp.emit(this.isCollapse());\n }\n }\n\n protected async viewMore(e?: Event) {\n e?.stopPropagation();\n this.isCollapse.set(false);\n this.contentDisplay.set(this.content());\n e?.preventDefault();\n this.outAction.emit('view-more');\n }\n\n protected async hiddenMore(e?: Event) {\n e?.stopPropagation();\n this.isCollapse.set(true);\n this.contentDisplay.set(this.contentClamp());\n e?.preventDefault();\n this.outAction.emit('hidden-more');\n }\n\n @HostListener('window:resize', ['$event'])\n protected async resize() {\n this.refresh();\n }\n\n protected async refresh() {\n this.contentDisplay.set(this.content());\n this.displayLineClamp.set(false);\n this.isCollapse.set(false);\n }\n\n protected async handlerClick(event: Event | TYPE_POPOVER_EVENT) {\n if (typeof event === 'string' && event !== 'click') {\n return;\n }\n this.outClick.emit(event);\n }\n\n ngOnDestroy() {\n this.displayLineClamp.set(false);\n }\n}\n","@if (!displayLineClamp()) {\n @if (!isInnerText()) {\n <div\n LibsUiComponentsLineClampDirective\n [lengthLimitDisplay]=\"lengthLimitDisplay()\"\n [ignoreThreeDots]=\"hasBackgroundGradient()\"\n methodDisplay=\"innerHTML\"\n class=\"overflow-hidden\"\n [content]=\"content()\"\n [ngClass]=\"ngClassObject()\"\n [style.maxHeight.px]=\"maxHeight()\"\n [innerHtml]=\"content() | translate | LibsUiPipesSecurityTrustPipe: 'html' : useXssFilter() | async\"\n (click)=\"handlerClick($event)\"\n (keydown.enter)=\"handlerClick($event)\"\n (outContentSub)=\"handlerContentSub($event)\"></div>\n } @else {\n <div\n LibsUiComponentsLineClampDirective\n [lengthLimitDisplay]=\"lengthLimitDisplay()\"\n [ignoreThreeDots]=\"hasBackgroundGradient()\"\n methodDisplay=\"innerText\"\n class=\"overflow-hidden\"\n [content]=\"content()\"\n [ngClass]=\"ngClassObject()\"\n [style.maxHeight.px]=\"maxHeight()\"\n [innerText]=\"content() | translate\"\n (click)=\"handlerClick($event)\"\n (keydown.enter)=\"handlerClick($event)\"\n (outContentSub)=\"handlerContentSub($event)\"></div>\n }\n} @else {\n <libs_ui-components-popover\n class=\"relative\"\n type=\"other\"\n [ignoreShowPopover]=\"!showTooltip()\"\n [ignoreStopPropagationEvent]=\"ignoreStopPropagationTooltipEvent()\"\n [config]=\"{\n timerDestroy: timeHidePopoverOnMouseout(),\n maxWidth: maxWidthTooltip(),\n maxHeight: maxHeightTooltip(),\n direction: directionTooltip(),\n content: isInnerText() ? (this.content() | LibsUiPipesEscapeHtmlPipe) : this.content(),\n zIndex: zIndexPopover(),\n }\"\n (outEvent)=\"handlerClick($event)\">\n @if (isCollapse() && hasBackgroundGradient()) {\n <div class=\"h-[40px] libs-ui-line-clamp-bg-gradient\"></div>\n }\n @if (!isInnerText()) {\n <div\n [ngClass]=\"ngClassObject()\"\n [innerHtml]=\"contentDisplay() | translate | LibsUiPipesSecurityTrustPipe: 'html' : useXssFilter() | async\"></div>\n } @else {\n <div\n [ngClass]=\"ngClassObject()\"\n [innerText]=\"contentDisplay() | translate\"></div>\n }\n </libs_ui-components-popover>\n\n @if (!ignoreShowButtonCollapseExpand()) {\n @if (isCollapse()) {\n <libs_ui-components-buttons-button\n type=\"button-link-primary\"\n [label]=\"labelButtonViewMore() || 'i18n_view_more'\"\n [classInclude]=\"classClassIncludeButtonCollapseExpand()\"\n [classLabel]=\"classClassLabelButtonCollapseExpand()\"\n (outClick)=\"viewMore($event)\" />\n } @else {\n @if (!ignoreShowButtonCollapse()) {\n <libs_ui-components-buttons-button\n type=\"button-link-primary\"\n [label]=\"labelButtonCollapse() || 'i18n_collapse'\"\n [classInclude]=\"classClassIncludeButtonCollapseExpand()\"\n [classLabel]=\"classClassLabelButtonCollapseExpand()\"\n (outClick)=\"hiddenMore($event)\" />\n }\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"libs-ui-components-line-clamp.mjs","sources":["../../../../../libs-ui/components/line-clamp/src/line-clamp.directive.ts","../../../../../libs-ui/components/line-clamp/src/line-clamp.component.ts","../../../../../libs-ui/components/line-clamp/src/line-clamp.component.html","../../../../../libs-ui/components/line-clamp/src/libs-ui-components-line-clamp.ts"],"sourcesContent":["import { Directive, effect, ElementRef, inject, input, OnDestroy, output, signal, untracked } from '@angular/core';\n\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[LibsUiComponentsLineClampDirective]',\n standalone: true,\n})\nexport class LibsUiComponentsLineClampDirective implements OnDestroy {\n /** PROPERTY */\n private readonly timeInterval = signal<number | undefined>(undefined);\n private readonly textView = signal<string>('');\n\n /** INPUT */\n readonly lengthLimitDisplay = input.required<number>();\n readonly methodDisplay = input.required<string>();\n readonly content = input.required<string>();\n readonly ignoreThreeDots = input<boolean>();\n\n /** OUTPUT */\n readonly outContentSub = output<string>();\n\n /** INJECT */\n private readonly elementRef = inject(ElementRef);\n\n constructor() {\n effect(() => {\n if (!this.content() || !this.methodDisplay() || !this.lengthLimitDisplay()) {\n return;\n }\n untracked(() => {\n this.textView.set(this.content());\n if (this.textView().length > this.lengthLimitDisplay()) {\n this.textView.update((val) => val.substring(0, this.lengthLimitDisplay()));\n }\n\n if (!this.textView()) {\n return;\n }\n this.process();\n this.timeInterval.set(\n setInterval(() => {\n this.process();\n }, 250)\n );\n });\n });\n }\n\n /** FUNCTIONS */\n\n private process() {\n if (this.elementRef?.nativeElement[this.methodDisplay()]) {\n clearInterval(this.timeInterval());\n this.truncate();\n }\n }\n\n private truncate() {\n let content = this.textView();\n while (this.elementRef.nativeElement.scrollHeight - 2 > this.elementRef.nativeElement.offsetHeight) {\n if (!content) {\n return;\n }\n content = content.substring(0, content.length - 3);\n this.elementRef.nativeElement[this.methodDisplay()] = this.ignoreThreeDots() ? content : `${content}...`;\n }\n if (content !== this.textView()) {\n this.outContentSub.emit(this.ignoreThreeDots() ? content : `${content}...`);\n }\n }\n ngOnDestroy() {\n clearInterval(this.timeInterval());\n }\n}\n","import { AsyncPipe, NgClass } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, HostListener, OnDestroy, OnInit, effect, input, output, signal, untracked } from '@angular/core';\nimport { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';\nimport { LibsUiComponentsPopoverComponent, TYPE_POPOVER_DIRECTION, TYPE_POPOVER_EVENT } from '@libs-ui/components-popover';\nimport { TYPE_OBJECT } from '@libs-ui/interfaces-types';\nimport { LibsUiPipesEscapeHtmlPipe } from '@libs-ui/pipes-escape-html';\nimport { LibsUiPipesSecurityTrustPipe } from '@libs-ui/pipes-security-trust';\nimport { isNil } from '@libs-ui/utils';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { ILineClampFunctionControlEvent } from './interfaces';\nimport { LibsUiComponentsLineClampDirective } from './line-clamp.directive';\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-line_clamp',\n templateUrl: './line-clamp.component.html',\n styleUrls: ['./line-clamp.component.scss'],\n standalone: true,\n imports: [NgClass, TranslateModule, AsyncPipe, LibsUiComponentsLineClampDirective, LibsUiPipesSecurityTrustPipe, LibsUiPipesEscapeHtmlPipe, LibsUiComponentsPopoverComponent, LibsUiComponentsButtonsButtonComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LibsUiComponentsLineClampComponent implements OnInit, OnDestroy {\n /** PROPERTY */\n protected displayLineClamp = signal<boolean>(false);\n protected isCollapse = signal<boolean>(false);\n protected contentClamp = signal<string>('');\n protected contentDisplay = signal<string>('');\n\n /** INPUT */\n readonly content = input.required<string>();\n readonly lengthLimitDisplay = input<number, number | undefined>(200, { transform: (val) => val || 200 });\n readonly maxHeight = input.required<number>(); // maxHeight = (line-height của text)*(số dòng mong muốn)\n readonly ignoreShowButtonCollapseExpand = input<boolean>();\n readonly ignoreShowButtonCollapse = input<boolean>();\n readonly showTooltip = input<boolean>();\n readonly timeHidePopoverOnMouseout = input<number, number | undefined>(50, { transform: (val) => val ?? 50 });\n readonly maxWidthTooltip = input<number, number | undefined>(250, { transform: (val) => val ?? 250 });\n readonly maxHeightTooltip = input<number, number | undefined>(150, { transform: (val) => val ?? 150 });\n readonly zIndexPopover = input<number, number | undefined>(1001, { transform: (val) => val ?? 1001 });\n readonly isInnerText = input<boolean>(); // không cần escapeHTML content khi biến bằng true\n readonly classClassLabelButtonCollapseExpand = input<string, string | undefined>('libs-ui-font-h5r', { transform: (val) => val ?? 'libs-ui-font-h5r' });\n readonly classClassIncludeButtonCollapseExpand = input<string, string | undefined>('!p-0', { transform: (val) => val ?? '!p-0' });\n readonly ignoreStopPropagationTooltipEvent = input<boolean, boolean | undefined>(false, { transform: (val) => val ?? false });\n readonly ngClassObject = input<TYPE_OBJECT, TYPE_OBJECT | undefined>({ 'libs-ui-line-clamp-content libs-ui-font-h5r': true }, { transform: (val) => val || { 'libs-ui-line-clamp-content lib-ui-font-h5r': true } }); // object ngClass\n readonly hasBackgroundGradient = input<boolean, boolean | undefined>(false, { transform: (val) => val ?? false });\n readonly labelButtonViewMore = input<string>();\n readonly labelButtonCollapse = input<string>();\n readonly directionTooltip = input<TYPE_POPOVER_DIRECTION, TYPE_POPOVER_DIRECTION | undefined>('top', { transform: (val) => val ?? 'top' });\n readonly useXssFilter = input<boolean, boolean | undefined>(true, { transform: (val) => val ?? true });\n readonly defaultIsCollapse = input<boolean, boolean | undefined>(true, { transform: (val) => val ?? true });\n\n /** OUTPUT */\n protected readonly outDisplayLineClamp = output<boolean>();\n protected readonly outAction = output<string>();\n protected readonly outClick = output<Event | TYPE_POPOVER_EVENT>();\n protected readonly outFunctionControl = output<ILineClampFunctionControlEvent>();\n\n constructor() {\n effect(() => {\n if (!isNil(this.content())) {\n untracked(() => {\n this.contentDisplay.set('');\n this.displayLineClamp.set(false);\n this.isCollapse.set(false);\n });\n }\n });\n }\n\n async ngOnInit() {\n this.outFunctionControl.emit(this.FunctionsControl);\n }\n\n /** FUNCTIONS */\n public get FunctionsControl(): ILineClampFunctionControlEvent {\n return {\n refresh: this.refresh.bind(this),\n checkIsDisplayLineClamp: async () => this.displayLineClamp(),\n viewMore: this.viewMore.bind(this),\n hiddenMore: this.hiddenMore.bind(this),\n };\n }\n\n protected async handlerContentSub(content: string) {\n if (this.content() !== content) {\n this.displayLineClamp.set(true);\n this.isCollapse.set(this.defaultIsCollapse());\n this.contentClamp.set(content);\n this.contentDisplay.set(this.isCollapse() ? content : this.content());\n this.outDisplayLineClamp.emit(this.isCollapse());\n }\n }\n\n protected async viewMore(e?: Event) {\n e?.stopPropagation();\n this.isCollapse.set(false);\n this.contentDisplay.set(this.content());\n e?.preventDefault();\n this.outAction.emit('view-more');\n }\n\n protected async hiddenMore(e?: Event) {\n e?.stopPropagation();\n this.isCollapse.set(true);\n this.contentDisplay.set(this.contentClamp());\n e?.preventDefault();\n this.outAction.emit('hidden-more');\n }\n\n @HostListener('window:resize', ['$event'])\n protected async resize() {\n this.refresh();\n }\n\n protected async refresh() {\n this.contentDisplay.set(this.content());\n this.displayLineClamp.set(false);\n this.isCollapse.set(false);\n }\n\n protected async handlerClick(event: Event | TYPE_POPOVER_EVENT) {\n if (typeof event === 'string' && event !== 'click') {\n return;\n }\n this.outClick.emit(event);\n }\n\n ngOnDestroy() {\n this.displayLineClamp.set(false);\n }\n}\n","@if (!displayLineClamp()) {\n @if (!isInnerText()) {\n <div\n LibsUiComponentsLineClampDirective\n [lengthLimitDisplay]=\"lengthLimitDisplay()\"\n [ignoreThreeDots]=\"hasBackgroundGradient()\"\n methodDisplay=\"innerHTML\"\n class=\"overflow-hidden\"\n [content]=\"content()\"\n [ngClass]=\"ngClassObject()\"\n [style.maxHeight.px]=\"maxHeight()\"\n [innerHtml]=\"content() | translate | LibsUiPipesSecurityTrustPipe: 'html' : useXssFilter() | async\"\n (click)=\"handlerClick($event)\"\n (keydown.enter)=\"handlerClick($event)\"\n (outContentSub)=\"handlerContentSub($event)\"></div>\n } @else {\n <div\n LibsUiComponentsLineClampDirective\n [lengthLimitDisplay]=\"lengthLimitDisplay()\"\n [ignoreThreeDots]=\"hasBackgroundGradient()\"\n methodDisplay=\"innerText\"\n class=\"overflow-hidden\"\n [content]=\"content()\"\n [ngClass]=\"ngClassObject()\"\n [style.maxHeight.px]=\"maxHeight()\"\n [innerText]=\"content() | translate\"\n (click)=\"handlerClick($event)\"\n (keydown.enter)=\"handlerClick($event)\"\n (outContentSub)=\"handlerContentSub($event)\"></div>\n }\n} @else {\n <libs_ui-components-popover\n class=\"relative\"\n type=\"other\"\n [ignoreShowPopover]=\"!showTooltip()\"\n [ignoreStopPropagationEvent]=\"ignoreStopPropagationTooltipEvent()\"\n [config]=\"{\n timerDestroy: timeHidePopoverOnMouseout(),\n maxWidth: maxWidthTooltip(),\n maxHeight: maxHeightTooltip(),\n direction: directionTooltip(),\n content: isInnerText() ? (this.content() | LibsUiPipesEscapeHtmlPipe) : this.content(),\n zIndex: zIndexPopover(),\n }\"\n (outEvent)=\"handlerClick($event)\">\n @if (isCollapse() && hasBackgroundGradient()) {\n <div class=\"h-[40px] libs-ui-line-clamp-bg-gradient\"></div>\n }\n @if (!isInnerText()) {\n <div\n [ngClass]=\"ngClassObject()\"\n [innerHtml]=\"contentDisplay() | translate | LibsUiPipesSecurityTrustPipe: 'html' : useXssFilter() | async\"></div>\n } @else {\n <div\n [ngClass]=\"ngClassObject()\"\n [innerText]=\"contentDisplay() | translate\"></div>\n }\n </libs_ui-components-popover>\n\n @if (!ignoreShowButtonCollapseExpand()) {\n @if (isCollapse()) {\n <libs_ui-components-buttons-button\n type=\"button-link-primary\"\n [label]=\"labelButtonViewMore() || 'i18n_view_more'\"\n [classInclude]=\"classClassIncludeButtonCollapseExpand()\"\n [classLabel]=\"classClassLabelButtonCollapseExpand()\"\n (outClick)=\"viewMore($event)\" />\n } @else {\n @if (!ignoreShowButtonCollapse()) {\n <libs_ui-components-buttons-button\n type=\"button-link-primary\"\n [label]=\"labelButtonCollapse() || 'i18n_collapse'\"\n [classInclude]=\"classClassIncludeButtonCollapseExpand()\"\n [classLabel]=\"classClassLabelButtonCollapseExpand()\"\n (outClick)=\"hiddenMore($event)\" />\n }\n }\n }\n}\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,16 +1,16 @@
1
1
  {
2
2
  "name": "@libs-ui/components-line-clamp",
3
- "version": "0.2.356-42",
3
+ "version": "0.2.356-43",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=18.0.0",
6
6
  "@angular/core": ">=18.0.0",
7
- "@libs-ui/interfaces-types": "0.2.356-42",
8
- "@libs-ui/components-buttons-button": "0.2.356-42",
9
- "@libs-ui/components-popover": "0.2.356-42",
10
- "@libs-ui/pipes-escape-html": "0.2.356-42",
11
- "@libs-ui/pipes-security-trust": "0.2.356-42",
7
+ "@libs-ui/interfaces-types": "0.2.356-43",
8
+ "@libs-ui/components-buttons-button": "0.2.356-43",
9
+ "@libs-ui/components-popover": "0.2.356-43",
10
+ "@libs-ui/pipes-escape-html": "0.2.356-43",
11
+ "@libs-ui/pipes-security-trust": "0.2.356-43",
12
12
  "@ngx-translate/core": "^15.0.0",
13
- "@libs-ui/utils": "0.2.356-42"
13
+ "@libs-ui/utils": "0.2.356-43"
14
14
  },
15
15
  "sideEffects": false,
16
16
  "module": "fesm2022/libs-ui-components-line-clamp.mjs",