@libs-ui/components-gallery 0.2.355-9 → 0.2.356-1
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 +219 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,3 +1,220 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Gallery Component
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Version**: 0.2.355-15
|
|
4
|
+
|
|
5
|
+
Component hiển thị gallery ảnh với lightbox viewer, hỗ trợ zoom, drag, fullscreen và keyboard navigation.
|
|
6
|
+
|
|
7
|
+
## Tính năng
|
|
8
|
+
|
|
9
|
+
- ✅ **Thumbnail Grid**: Hiển thị danh sách ảnh dạng thumbnail
|
|
10
|
+
- ✅ **Lightbox Viewer**: Viewer fullscreen với zoom, drag và navigate
|
|
11
|
+
- ✅ **String Array Support**: Tự động convert Array<string> sang object format
|
|
12
|
+
- ✅ **Overlay Count**: Hiển thị số ảnh còn lại (+N) trên thumbnail cuối
|
|
13
|
+
- ✅ **Keyboard Navigation**: Escape (đóng), ArrowLeft/ArrowRight (chuyển ảnh)
|
|
14
|
+
- ✅ **Zoom & Drag**: Zoom in/out và drag ảnh trong viewer
|
|
15
|
+
- ✅ **Fullscreen**: Chế độ xem fullscreen trong viewer
|
|
16
|
+
- ✅ **FunctionsControl**: Điều khiển mở viewer từ bên ngoài
|
|
17
|
+
- ✅ **Sub-component Viewer**: Viewer component có thể được export riêng
|
|
18
|
+
|
|
19
|
+
## Khi nào sử dụng
|
|
20
|
+
|
|
21
|
+
- Khi cần hiển thị danh sách ảnh dạng thumbnail grid
|
|
22
|
+
- Khi cần lightbox viewer với zoom, drag và fullscreen
|
|
23
|
+
- Khi cần hiển thị gallery ảnh từ array URLs đơn giản
|
|
24
|
+
- Khi cần điều khiển mở viewer từ bên ngoài (FunctionsControl)
|
|
25
|
+
- Khi cần hiển thị overlay đếm số ảnh còn lại (+N)
|
|
26
|
+
|
|
27
|
+
## Important Notes
|
|
28
|
+
|
|
29
|
+
⚠️ `[images]` là model (two-way binding) — component có thể thay đổi giá trị khi dùng `imageArrayStringConvert`
|
|
30
|
+
|
|
31
|
+
⚠️ Sử dụng `[imageArrayStringConvert]` khi data là `Array<string>` — component tự convert sang `Array<Record<string, any>>`
|
|
32
|
+
|
|
33
|
+
⚠️ `[fieldDisplaySrcImage]` xác định key chứa URL ảnh trong object (mặc định `"url"`)
|
|
34
|
+
|
|
35
|
+
⚠️ Viewer hỗ trợ keyboard: Escape (đóng), ArrowLeft/ArrowRight (chuyển ảnh)
|
|
36
|
+
|
|
37
|
+
⚠️ Viewer là dynamic component — được inject vào body, không nằm trong DOM tree của gallery
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @libs-ui/components-gallery
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### Basic Gallery
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Component } from '@angular/core';
|
|
51
|
+
import { LibsUiComponentsGalleryComponent } from '@libs-ui/components-gallery';
|
|
52
|
+
|
|
53
|
+
@Component({
|
|
54
|
+
selector: 'app-example',
|
|
55
|
+
standalone: true,
|
|
56
|
+
imports: [LibsUiComponentsGalleryComponent],
|
|
57
|
+
template: `
|
|
58
|
+
<div class="w-[300px] h-[80px]">
|
|
59
|
+
<libs_ui-components-gallery
|
|
60
|
+
[images]="images"
|
|
61
|
+
[fieldDisplaySrcImage]="'url'"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
`,
|
|
65
|
+
})
|
|
66
|
+
export class ExampleComponent {
|
|
67
|
+
images = [
|
|
68
|
+
{ url: 'https://example.com/image1.jpg' },
|
|
69
|
+
{ url: 'https://example.com/image2.jpg' },
|
|
70
|
+
{ url: 'https://example.com/image3.jpg' },
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### String Array Convert
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
@Component({
|
|
79
|
+
// ...
|
|
80
|
+
template: `
|
|
81
|
+
<div class="w-[300px] h-[80px]">
|
|
82
|
+
<libs_ui-components-gallery
|
|
83
|
+
[images]="[]"
|
|
84
|
+
[fieldDisplaySrcImage]="'url'"
|
|
85
|
+
[imageArrayStringConvert]="imageUrls"
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
88
|
+
`,
|
|
89
|
+
})
|
|
90
|
+
export class ExampleComponent {
|
|
91
|
+
imageUrls = [
|
|
92
|
+
'https://example.com/image1.jpg',
|
|
93
|
+
'https://example.com/image2.jpg',
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### FunctionsControl
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { Component, signal } from '@angular/core';
|
|
102
|
+
import { LibsUiComponentsGalleryComponent, IGalleryFunctionsControlEvent } from '@libs-ui/components-gallery';
|
|
103
|
+
|
|
104
|
+
@Component({
|
|
105
|
+
selector: 'app-example',
|
|
106
|
+
standalone: true,
|
|
107
|
+
imports: [LibsUiComponentsGalleryComponent],
|
|
108
|
+
template: `
|
|
109
|
+
<libs_ui-components-gallery
|
|
110
|
+
[images]="images"
|
|
111
|
+
[fieldDisplaySrcImage]="'url'"
|
|
112
|
+
(outFunctionsControl)="controls.set($event)"
|
|
113
|
+
/>
|
|
114
|
+
<button (click)="controls()?.open(images[0])">Open Viewer</button>
|
|
115
|
+
`,
|
|
116
|
+
})
|
|
117
|
+
export class ExampleComponent {
|
|
118
|
+
controls = signal<IGalleryFunctionsControlEvent | null>(null);
|
|
119
|
+
images = [{ url: 'https://example.com/image1.jpg' }];
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## API
|
|
124
|
+
|
|
125
|
+
### libs_ui-components-gallery
|
|
126
|
+
|
|
127
|
+
#### Inputs
|
|
128
|
+
|
|
129
|
+
| Property | Type | Default | Description |
|
|
130
|
+
| ---------------------------- | ----------------------------- | ----------- | ------------------------------------------------------- |
|
|
131
|
+
| `[end]` | `number` | `3` | Index kết thúc để hiển thị thumbnails (slice end) |
|
|
132
|
+
| `[fieldDisplaySrcImage]` | `string` | `'url'` | Key trong object chứa URL ảnh |
|
|
133
|
+
| `[ignoreOverlayCountImage]` | `boolean` | `false` | Ẩn overlay đếm số ảnh còn lại (+N) |
|
|
134
|
+
| `[imageArrayStringConvert]` | `Array<string>` | `undefined` | Array URL strings — tự động convert sang images format |
|
|
135
|
+
| `[(images)]` | `Array<Record<string, any>>` | `required` | Danh sách ảnh (model — two-way binding) |
|
|
136
|
+
| `[start]` | `number` | `0` | Index bắt đầu để hiển thị thumbnails (slice start) |
|
|
137
|
+
| `[zIndex]` | `number` | `1200` | z-index của viewer overlay |
|
|
138
|
+
|
|
139
|
+
#### Outputs
|
|
140
|
+
|
|
141
|
+
| Property | Type | Description |
|
|
142
|
+
| ----------------------- | ------------------------------- | ---------------------------------------------------- |
|
|
143
|
+
| `(outFunctionsControl)` | `IGalleryFunctionsControlEvent` | Emit functions để điều khiển gallery từ bên ngoài |
|
|
144
|
+
| `(outViewerEvent)` | `'show' \| 'remove'` | Event khi viewer được mở hoặc đóng |
|
|
145
|
+
|
|
146
|
+
#### FunctionsControl Methods
|
|
147
|
+
|
|
148
|
+
| Method | Description |
|
|
149
|
+
| -------------------- | -------------------------------------------------------- |
|
|
150
|
+
| `open(imageSelected)`| Mở viewer với ảnh được chọn (`Record<string, any>`) |
|
|
151
|
+
| `viewerRef` | Tham chiếu đến `ComponentRef` của viewer |
|
|
152
|
+
|
|
153
|
+
### libs_ui-components-gallery-viewer (Sub-component)
|
|
154
|
+
|
|
155
|
+
Viewer component hiển thị ảnh fullscreen với zoom, drag, fullscreen và navigation.
|
|
156
|
+
|
|
157
|
+
#### Inputs
|
|
158
|
+
|
|
159
|
+
| Property | Type | Default | Description |
|
|
160
|
+
| ------------------------ | ----------------------------- | ----------- | ------------------------------------ |
|
|
161
|
+
| `[classContainerInclude]`| `string` | `undefined` | CSS class thêm vào container |
|
|
162
|
+
| `[fieldDisplaySrcImage]` | `string` | `required` | Key trong object chứa URL ảnh |
|
|
163
|
+
| `[(imageSelected)]` | `Record<string, any>` | `undefined` | Ảnh đang được chọn (model) |
|
|
164
|
+
| `[images]` | `Array<Record<string, any>>` | `required` | Danh sách tất cả ảnh |
|
|
165
|
+
| `[removeBackdrop]` | `boolean` | `false` | Ẩn backdrop overlay |
|
|
166
|
+
| `[singleImage]` | `boolean` | `false` | Chế độ xem 1 ảnh (ẩn thumbnail list) |
|
|
167
|
+
| `[zIndex]` | `number` | `1200` | z-index của viewer |
|
|
168
|
+
|
|
169
|
+
#### Outputs
|
|
170
|
+
|
|
171
|
+
| Property | Type | Description |
|
|
172
|
+
| ------------ | ------ | ---------------------- |
|
|
173
|
+
| `(outClose)` | `void` | Event khi đóng viewer |
|
|
174
|
+
|
|
175
|
+
## Types
|
|
176
|
+
|
|
177
|
+
### IGalleryFunctionsControlEvent
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
export interface IGalleryFunctionsControlEvent {
|
|
181
|
+
open: (imageSelected: Record<string, any>) => Promise<void>;
|
|
182
|
+
viewerRef: ComponentRef<any> | undefined;
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### IZoomDragHTMLElement
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
export interface IZoomDragHTMLElement extends HTMLElement {
|
|
190
|
+
stopDraggableBehavior?(): IZoomDragHTMLElement | null;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Hidden Logic
|
|
195
|
+
|
|
196
|
+
### imageArrayStringConvert → images Conversion
|
|
197
|
+
|
|
198
|
+
Khi truyền `[imageArrayStringConvert]`, component sử dụng `effect()` để tự động convert `Array<string>` thành `Array<Record<string, any>>` với key là `fieldDisplaySrcImage`. Kết quả được set vào model `images()`.
|
|
199
|
+
|
|
200
|
+
### Dynamic Viewer Component
|
|
201
|
+
|
|
202
|
+
Gallery viewer không render inline — nó được lazy-import và inject vào `document.body` thông qua `LibsUiDynamicComponentService`. Điều này đảm bảo viewer luôn hiển thị fullscreen trên tất cả content.
|
|
203
|
+
|
|
204
|
+
### Overlay Count Logic
|
|
205
|
+
|
|
206
|
+
Khi số ảnh nhiều hơn `[end]`, thumbnail cuối cùng hiển thị overlay "+N" (N = tổng ảnh - end). Có thể tắt bằng `[ignoreOverlayCountImage]="true"`.
|
|
207
|
+
|
|
208
|
+
## Demo
|
|
209
|
+
|
|
210
|
+
- **Local**: [http://localhost:4500/gallery](http://localhost:4500/gallery)
|
|
211
|
+
|
|
212
|
+
## Test
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
nx test components-gallery
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-gallery",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.356-1",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": ">=18.0.0",
|
|
6
6
|
"@angular/core": ">=18.0.0",
|
|
7
|
-
"@libs-ui/icons": "0.2.
|
|
8
|
-
"@libs-ui/interfaces-types": "0.2.
|
|
9
|
-
"@libs-ui/services-dynamic-component": "0.2.
|
|
10
|
-
"@libs-ui/utils": "0.2.
|
|
7
|
+
"@libs-ui/icons": "0.2.356-1",
|
|
8
|
+
"@libs-ui/interfaces-types": "0.2.356-1",
|
|
9
|
+
"@libs-ui/services-dynamic-component": "0.2.356-1",
|
|
10
|
+
"@libs-ui/utils": "0.2.356-1",
|
|
11
11
|
"dayjs": "1.11.5",
|
|
12
12
|
"rxjs": "~7.8.0",
|
|
13
|
-
"@libs-ui/components-popover": "0.2.
|
|
13
|
+
"@libs-ui/components-popover": "0.2.356-1",
|
|
14
14
|
"@ngx-translate/core": "^15.0.0"
|
|
15
15
|
},
|
|
16
16
|
"sideEffects": false,
|