neiki-gallery 2.0.0 → 3.0.0
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/LICENSE +21 -21
- package/README.md +309 -36
- package/dist/neiki-gallery.css +2230 -1266
- package/dist/neiki-gallery.js +3586 -1325
- package/dist/neiki-gallery.min.css +1 -1
- package/dist/neiki-gallery.min.js +2 -2
- package/package.json +54 -45
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 neikiri
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 neikiri
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<img src="https://img.shields.io/badge/css-%23663399.svg?style=for-the-badge&logo=css&logoColor=white" alt="CSS">
|
|
11
11
|
<br>
|
|
12
12
|
<img src="https://img.shields.io/badge/License-MIT-2563EB?style=for-the-badge&logo=open-source-initiative&logoColor=white&labelColor=000F15&logoWidth=20" alt="License">
|
|
13
|
-
<img src="https://img.shields.io/badge/Version-
|
|
13
|
+
<img src="https://img.shields.io/badge/Version-3.0.0-2563EB?style=for-the-badge&logo=semantic-release&logoColor=white&labelColor=000F15&logoWidth=20" alt="Version">
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
16
|
<p align="center">
|
|
@@ -55,18 +55,43 @@
|
|
|
55
55
|
- **Multiple instances** — independent galleries on one page
|
|
56
56
|
- **Dark & light themes** — CSS custom properties + accent color system (`--neiki-accent`)
|
|
57
57
|
- **Accessibility** — ARIA attributes, focus management, `prefers-reduced-motion`
|
|
58
|
-
- **Event system** — `open`, `close`, `change`, `filter`, `select`, `slideshowStart`, `slideshowStop`
|
|
59
|
-
- **
|
|
58
|
+
- **Event system** — `open`, `close`, `change`, `filter`, `select`, `slideshowStart`, `slideshowStop`, `favorite`, `unfavorite`, `infoOpen`, `infoClose`, `print`, `editorOpen`, `editorExport`, `annotateOpen`, `annotateExport`, `append`, `remove`
|
|
59
|
+
- **Blurhash placeholders** — `data-blurhash` attribute decoded into blurred preview (replaces shimmer)
|
|
60
|
+
- **Story mode** — Instagram-like vertical fullscreen viewer with progress bars and tap navigation
|
|
61
|
+
- **Picture-in-Picture** — minimize lightbox to a resizable corner window
|
|
62
|
+
- **Image focus point** — `data-focus="0.3 0.7"` controls `object-position` for smart cropping
|
|
63
|
+
- **EXIF overlay** — camera model, focal length, aperture, shutter speed, ISO from JPEG binary
|
|
64
|
+
- **Color palette extraction** — k-means quantized 5-color palette strip in lightbox
|
|
65
|
+
- **Backdrop tint** — overlay adapts to dominant color of current image
|
|
66
|
+
- **FLIP morph transition** — smooth thumbnail-to-lightbox animation
|
|
67
|
+
- **Virtual scrolling** — `content-visibility` virtualization for large galleries (50+ items)
|
|
68
|
+
- **Drag & drop reorder** — HTML5 drag to reorder grid items
|
|
69
|
+
- **Aspect-ratio skeleton** — `data-width`/`data-height` for placeholder sizing
|
|
70
|
+
- **Web Share API** — native mobile sharing with clipboard fallback
|
|
71
|
+
- **Video & embeds** — auto-detect MP4/WebM/Ogg/MOV/M4V, YouTube and Vimeo URLs in lightbox
|
|
72
|
+
- **Plugin system** — `NeikiGallery.registerPlugin()` with `init`/`open`/`change`/`close`/`destroy` lifecycle hooks
|
|
73
|
+
- **Album groups** — `data-group="album"` links galleries; navigation traverses across all
|
|
74
|
+
- **Favorites** — heart button + localStorage persistence + `B` key shortcut
|
|
75
|
+
- **Info panel** — slide-out sidebar with metadata, EXIF, source URL (`I` key)
|
|
76
|
+
- **Image editor** — rotate / flip / export to PNG via `<canvas>`
|
|
77
|
+
- **Annotation layer** — freehand drawing with color picker, brush size, undo, clear, export
|
|
78
|
+
- **Print** — print current image with caption (`P` key)
|
|
79
|
+
- **Right-click context menu** — open original, copy link, download, share, print, favorite
|
|
80
|
+
- **Infinite scroll** — `loadMore` callback + `append()` / `remove()` API
|
|
81
|
+
- **Keyboard shortcuts overlay** — press `?` to view all shortcuts
|
|
82
|
+
- **System theme detection** — `theme: 'system'` follows OS `prefers-color-scheme`
|
|
83
|
+
- **Kenburns slideshow** — slow zoom-and-pan animation per slide
|
|
84
|
+
- **Configurable counter** — `counterFormat` with `{current}`/`{total}`/`{percent}` tokens
|
|
85
|
+
- **Cross-browser** — Chrome 80+, Firefox 75+, Safari 14+, Edge 80+
|
|
60
86
|
|
|
61
87
|
## 🚀 Quick Start
|
|
62
88
|
|
|
63
89
|
### CDN (Recommended)
|
|
64
90
|
|
|
65
|
-
Add
|
|
91
|
+
Add this single line to your HTML — that's all you need (CSS is included automatically):
|
|
66
92
|
|
|
67
93
|
```html
|
|
68
|
-
<
|
|
69
|
-
<script src="http://cdn.neiki.eu/neiki-gallery/neiki-gallery.min.js"></script>
|
|
94
|
+
<script src="https://cdn.neiki.eu/neiki-gallery/neiki-gallery.min.js"></script>
|
|
70
95
|
```
|
|
71
96
|
|
|
72
97
|
Then create your gallery markup:
|
|
@@ -84,16 +109,15 @@ Then create your gallery markup:
|
|
|
84
109
|
|
|
85
110
|
That's it — galleries with `data-neiki-gallery` auto-initialize on page load.
|
|
86
111
|
|
|
87
|
-
> **Unminified files** are also available if you need them for debugging:
|
|
112
|
+
> **Unminified files** are also available if you need them for debugging (require separate CSS):
|
|
88
113
|
> ```
|
|
89
|
-
>
|
|
90
|
-
>
|
|
114
|
+
> https://cdn.neiki.eu/neiki-gallery/neiki-gallery.js
|
|
115
|
+
> https://cdn.neiki.eu/neiki-gallery/neiki-gallery.css
|
|
91
116
|
> ```
|
|
92
117
|
|
|
93
118
|
> **Pin a specific version** to avoid unexpected changes:
|
|
94
119
|
> ```
|
|
95
|
-
>
|
|
96
|
-
> http://cdn.neiki.eu/neiki-gallery/2.0.0/neiki-gallery.min.css
|
|
120
|
+
> https://cdn.neiki.eu/neiki-gallery/3.0.0/neiki-gallery.min.js
|
|
97
121
|
> ```
|
|
98
122
|
|
|
99
123
|
### Self-Hosting (Local)
|
|
@@ -104,20 +128,26 @@ Download or clone the repository from GitHub:
|
|
|
104
128
|
git clone https://github.com/neikiri/neiki-gallery.git
|
|
105
129
|
```
|
|
106
130
|
|
|
107
|
-
|
|
131
|
+
For production, you only need one file — CSS is already included:
|
|
108
132
|
|
|
109
133
|
```html
|
|
110
|
-
<link rel="stylesheet" href="path/to/neiki-gallery.min.css">
|
|
111
134
|
<script src="path/to/neiki-gallery.min.js"></script>
|
|
112
135
|
```
|
|
113
136
|
|
|
114
|
-
|
|
137
|
+
For development / debugging, use the unminified versions (requires separate CSS):
|
|
138
|
+
|
|
139
|
+
```html
|
|
140
|
+
<link rel="stylesheet" href="path/to/neiki-gallery.css">
|
|
141
|
+
<script src="path/to/neiki-gallery.js"></script>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The `dist/` folder contains:
|
|
115
145
|
|
|
116
146
|
| File | Description |
|
|
117
147
|
|------|-------------|
|
|
118
|
-
| `neiki-gallery.min.js` | Minified JS (production) |
|
|
119
|
-
| `neiki-gallery.min.css` | Minified CSS (
|
|
120
|
-
| `neiki-gallery.js` | Full JS (development / debugging) |
|
|
148
|
+
| `neiki-gallery.min.js` | Minified JS + CSS included (production) |
|
|
149
|
+
| `neiki-gallery.min.css` | Minified CSS standalone (optional) |
|
|
150
|
+
| `neiki-gallery.js` | Full JS without CSS (development / debugging) |
|
|
121
151
|
| `neiki-gallery.css` | Full CSS (development / debugging) |
|
|
122
152
|
|
|
123
153
|
### Manual Initialization
|
|
@@ -131,14 +161,45 @@ const gallery = new NeikiGallery('#my-gallery', {
|
|
|
131
161
|
contextualZoom: false, // zoom to click point
|
|
132
162
|
fullscreen: true,
|
|
133
163
|
transition: 'fade', // 'fade' | 'slide'
|
|
134
|
-
theme: '
|
|
164
|
+
theme: 'system', // 'dark' | 'light' | 'system' (auto-detect) ← v3 default
|
|
135
165
|
hashNavigation: true,
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
166
|
+
counter: true,
|
|
167
|
+
counterFormat: '{current} / {total}', // v3 — tokens: {current}, {total}, {percent}
|
|
168
|
+
stagger: true,
|
|
169
|
+
slideshow: { // v3 — nested config (boolean still works)
|
|
170
|
+
interval: 4000,
|
|
171
|
+
pauseOnHover: true,
|
|
172
|
+
kenburns: false,
|
|
173
|
+
direction: 'forward' // or 'reverse'
|
|
174
|
+
},
|
|
175
|
+
share: true,
|
|
176
|
+
filter: false,
|
|
177
|
+
batchSelect: false,
|
|
178
|
+
// v2.1.0
|
|
179
|
+
focusPoint: true,
|
|
180
|
+
blurhash: true,
|
|
181
|
+
exif: false,
|
|
182
|
+
storyMode: false,
|
|
183
|
+
pip: false,
|
|
184
|
+
virtualScroll: false,
|
|
185
|
+
dragReorder: false,
|
|
186
|
+
backdropTint: false,
|
|
187
|
+
morphTransition: false,
|
|
188
|
+
colorPalette: false,
|
|
189
|
+
aspectSkeleton: true,
|
|
190
|
+
// v3.0.0
|
|
191
|
+
video: true, // detect MP4 / YouTube / Vimeo
|
|
192
|
+
plugins: ['watermark', { name: 'analytics', trackingId: 'X' }],
|
|
193
|
+
group: '', // album group name (or use data-group)
|
|
194
|
+
favorites: false, // ❤️ button + localStorage
|
|
195
|
+
favoritesKey: '', // custom localStorage key suffix
|
|
196
|
+
infoPanel: false, // sidebar with metadata (I key)
|
|
197
|
+
contextMenu: false, // right-click menu on items
|
|
198
|
+
shortcutsHelp: true, // overlay on '?' key
|
|
199
|
+
infiniteScroll: false, // auto-load more
|
|
200
|
+
loadMore: null, // function(currentLength) → array | Promise<array>
|
|
201
|
+
editor: false, // crop/rotate/flip toolbar
|
|
202
|
+
annotate: false // freehand drawing layer
|
|
142
203
|
});
|
|
143
204
|
```
|
|
144
205
|
|
|
@@ -149,14 +210,50 @@ const gallery = new NeikiGallery('#my-gallery', {
|
|
|
149
210
|
```js
|
|
150
211
|
gallery.open(index); // Open lightbox at image index
|
|
151
212
|
gallery.close(); // Close lightbox
|
|
152
|
-
gallery.next(); // Go to next image
|
|
153
|
-
gallery.prev(); // Go to previous image
|
|
213
|
+
gallery.next(); // Go to next image (group-aware)
|
|
214
|
+
gallery.prev(); // Go to previous image (group-aware)
|
|
154
215
|
gallery.startSlideshow(); // Start autoplay
|
|
155
216
|
gallery.stopSlideshow(); // Stop autoplay
|
|
217
|
+
gallery.pauseSlideshow(); // v3 — pause without emitting stop
|
|
156
218
|
gallery.toggleSlideshow(); // Toggle autoplay
|
|
157
219
|
gallery.filter('landscape'); // Filter by tag (null = show all)
|
|
158
220
|
gallery.getSelected(); // Get batch-selected items
|
|
159
221
|
gallery.clearSelection(); // Clear batch selection
|
|
222
|
+
gallery.getOrder(); // Get current item order (after drag reorder)
|
|
223
|
+
|
|
224
|
+
// v3.0.0 — Favorites
|
|
225
|
+
gallery.toggleFavorite(); // Toggle favorite for current image
|
|
226
|
+
gallery.isFavorite(index); // Check if image is favorited
|
|
227
|
+
gallery.getFavorites(); // Get array of favorited image src URLs
|
|
228
|
+
gallery.clearFavorites(); // Remove all favorites
|
|
229
|
+
|
|
230
|
+
// v3.0.0 — Info panel / overlays
|
|
231
|
+
gallery.toggleInfoPanel(force); // Toggle info sidebar (force = bool)
|
|
232
|
+
gallery.toggleShortcutsHelp(force); // Toggle keyboard shortcuts overlay
|
|
233
|
+
|
|
234
|
+
// v3.0.0 — Editor & annotation
|
|
235
|
+
gallery.openEditor(); // Open crop/rotate/flip editor
|
|
236
|
+
gallery.closeEditor();
|
|
237
|
+
gallery.getEditedBlob(); // Last exported edited image as Blob
|
|
238
|
+
|
|
239
|
+
gallery.openAnnotate(); // Open drawing layer
|
|
240
|
+
gallery.closeAnnotate();
|
|
241
|
+
gallery.getAnnotatedBlob();
|
|
242
|
+
|
|
243
|
+
// v3.0.0 — Print & dynamic content
|
|
244
|
+
gallery.print(index); // Print current or specified image
|
|
245
|
+
gallery.append([{src,...}]); // Append new items at runtime
|
|
246
|
+
gallery.remove(index); // Remove item by index
|
|
247
|
+
|
|
248
|
+
// v3.0.0 — Plugin access
|
|
249
|
+
gallery.plugin('watermark'); // Get plugin instance by name
|
|
250
|
+
|
|
251
|
+
// v3.0.0 — Event helpers
|
|
252
|
+
gallery.on('change', fn);
|
|
253
|
+
gallery.off('change', fn); // Remove specific listener
|
|
254
|
+
gallery.off('change'); // Remove all listeners for event
|
|
255
|
+
gallery.once('open', fn); // Auto-removed after first fire
|
|
256
|
+
|
|
160
257
|
gallery.destroy(); // Remove gallery, clean up all listeners & DOM
|
|
161
258
|
```
|
|
162
259
|
|
|
@@ -174,8 +271,75 @@ const slider = NeikiGallery.compare('#compare-container', {
|
|
|
174
271
|
|
|
175
272
|
slider.setPosition(30); // Move handle to 30%
|
|
176
273
|
slider.destroy(); // Clean up
|
|
274
|
+
|
|
275
|
+
// Color palette extraction (v2.1.0)
|
|
276
|
+
NeikiGallery.extractPalette('photo.jpg', 5, (colors) => {
|
|
277
|
+
console.log(colors); // [{r, g, b, hex}, ...]
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Dominant color (v2.1.0)
|
|
281
|
+
NeikiGallery.extractDominantColor('photo.jpg', (color) => {
|
|
282
|
+
console.log(color); // {r, g, b, hex}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// EXIF parsing (v2.1.0)
|
|
286
|
+
NeikiGallery.parseExif('photo.jpg', (tags) => {
|
|
287
|
+
console.log(tags); // {make, model, iso, fNumber, exposure, focalLength}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Blurhash decoding (v2.1.0)
|
|
291
|
+
const pixels = NeikiGallery.decodeBlurhash('LEHV6nWB2y...', 32, 32);
|
|
292
|
+
|
|
293
|
+
// Media type detection (v3.0.0)
|
|
294
|
+
NeikiGallery.detectMediaType('https://youtube.com/watch?v=abc'); // 'youtube'
|
|
295
|
+
NeikiGallery.detectMediaType('clip.mp4'); // 'video'
|
|
296
|
+
NeikiGallery.detectMediaType('photo.jpg'); // 'image'
|
|
297
|
+
|
|
298
|
+
// Plugin registration (v3.0.0)
|
|
299
|
+
NeikiGallery.registerPlugin('watermark', (gallery, options) => ({
|
|
300
|
+
init() { /* set up DOM, listeners */ },
|
|
301
|
+
open() { /* on lightbox open */ },
|
|
302
|
+
change(d){ /* on slide change, d = {index, item, prevIndex} */ },
|
|
303
|
+
close() { /* on lightbox close */ },
|
|
304
|
+
destroy(){ /* cleanup */ }
|
|
305
|
+
}));
|
|
306
|
+
|
|
307
|
+
NeikiGallery.unregisterPlugin('watermark');
|
|
308
|
+
NeikiGallery.getRegisteredPlugins(); // ['watermark', ...]
|
|
309
|
+
|
|
310
|
+
// Version
|
|
311
|
+
console.log(NeikiGallery.version); // '3.0.0'
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Plugin System
|
|
315
|
+
|
|
316
|
+
A plugin is a factory function that receives the gallery instance and an options
|
|
317
|
+
object, and returns an object with optional lifecycle methods:
|
|
318
|
+
|
|
319
|
+
```js
|
|
320
|
+
NeikiGallery.registerPlugin('analytics', (gallery, opts) => ({
|
|
321
|
+
init() {
|
|
322
|
+
console.log('[analytics] gallery initialized');
|
|
323
|
+
},
|
|
324
|
+
open(data) {
|
|
325
|
+
track('lightbox_open', { index: data.index });
|
|
326
|
+
},
|
|
327
|
+
change(data) {
|
|
328
|
+
track('slide_view', { src: data.item.src, index: data.index });
|
|
329
|
+
},
|
|
330
|
+
close() {
|
|
331
|
+
track('lightbox_close');
|
|
332
|
+
},
|
|
333
|
+
destroy() {
|
|
334
|
+
console.log('[analytics] cleanup');
|
|
335
|
+
}
|
|
336
|
+
}));
|
|
337
|
+
|
|
338
|
+
new NeikiGallery('#g', { plugins: [{ name: 'analytics', sampleRate: 0.5 }] });
|
|
177
339
|
```
|
|
178
340
|
|
|
341
|
+
You can access plugin instances on a gallery via `gallery.plugin('analytics')`.
|
|
342
|
+
|
|
179
343
|
### Events
|
|
180
344
|
|
|
181
345
|
```js
|
|
@@ -202,6 +366,23 @@ gallery.on('select', (indices) => {
|
|
|
202
366
|
gallery.on('slideshowStart', () => {
|
|
203
367
|
console.log('Slideshow started');
|
|
204
368
|
});
|
|
369
|
+
|
|
370
|
+
gallery.on('reorder', (order) => {
|
|
371
|
+
console.log('New order:', order);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
gallery.on('pipEnter', () => console.log('PiP on'));
|
|
375
|
+
gallery.on('storyEnter', () => console.log('Story opened'));
|
|
376
|
+
|
|
377
|
+
// v3.0.0 events
|
|
378
|
+
gallery.on('favorite', ({ index, src }) => console.log('★ favorited', src));
|
|
379
|
+
gallery.on('unfavorite', ({ index, src }) => console.log('☆ removed'));
|
|
380
|
+
gallery.on('infoOpen', () => console.log('info panel opened'));
|
|
381
|
+
gallery.on('print', ({ index, src }) => console.log('printed', src));
|
|
382
|
+
gallery.on('editorExport', ({ blob, url }) => console.log('edited blob', url));
|
|
383
|
+
gallery.on('annotateExport', ({ blob, url }) => console.log('annotated', url));
|
|
384
|
+
gallery.on('append', (items) => console.log('appended', items.length));
|
|
385
|
+
gallery.on('remove', ({ index }) => console.log('removed item', index));
|
|
205
386
|
```
|
|
206
387
|
|
|
207
388
|
### Options
|
|
@@ -215,18 +396,41 @@ gallery.on('slideshowStart', () => {
|
|
|
215
396
|
| `contextualZoom` | `boolean` | `false` | Zoom to cursor point instead of center |
|
|
216
397
|
| `fullscreen` | `boolean` | `true` | Show fullscreen button |
|
|
217
398
|
| `transition` | `string` | `'fade'` | `'fade'` or `'slide'` |
|
|
218
|
-
| `theme` | `string` | `'
|
|
399
|
+
| `theme` | `string` | `'system'` | `'dark'` · `'light'` · `'system'` (auto-detect) |
|
|
219
400
|
| `hashNavigation` | `boolean` | `true` | URL hash deep linking |
|
|
220
401
|
| `counter` | `boolean` | `true` | Show image counter |
|
|
402
|
+
| `counterFormat` | `string` | `'{current} / {total}'` | Counter format with `{current}`, `{total}`, `{percent}` tokens |
|
|
221
403
|
| `captions` | `boolean` | `true` | Show image captions |
|
|
222
404
|
| `preload` | `number` | `1` | Adjacent images to preload |
|
|
223
405
|
| `lazyLoad` | `boolean` | `true` | Lazy load grid thumbnails |
|
|
224
406
|
| `stagger` | `boolean` | `true` | Staggered entrance animation |
|
|
225
|
-
| `slideshow` | `boolean` | `false` |
|
|
226
|
-
| `slideshowInterval` | `number` | `4000` | Slideshow interval in ms |
|
|
407
|
+
| `slideshow` | `boolean \| object` | `false` | `true` or `{ interval, pauseOnHover, kenburns, direction }` |
|
|
227
408
|
| `share` | `boolean` | `true` | Show share button in lightbox |
|
|
228
409
|
| `filter` | `boolean` | `false` | Enable tag filtering bar |
|
|
229
410
|
| `batchSelect` | `boolean` | `false` | Enable Shift+click multi-select |
|
|
411
|
+
| `focusPoint` | `boolean` | `true` | Respect `data-focus` for `object-position` |
|
|
412
|
+
| `blurhash` | `boolean` | `true` | Decode `data-blurhash` placeholders |
|
|
413
|
+
| `exif` | `boolean` | `false` | Show EXIF data overlay in lightbox |
|
|
414
|
+
| `storyMode` | `boolean` | `false` | Enable story mode button in toolbar |
|
|
415
|
+
| `pip` | `boolean` | `false` | Enable PiP button in toolbar |
|
|
416
|
+
| `virtualScroll` | `boolean` | `false` | Virtualize grid for 50+ items |
|
|
417
|
+
| `dragReorder` | `boolean` | `false` | Enable drag & drop reorder |
|
|
418
|
+
| `backdropTint` | `boolean` | `false` | Tint overlay with dominant color |
|
|
419
|
+
| `morphTransition` | `boolean` | `false` | FLIP morph from grid to lightbox |
|
|
420
|
+
| `colorPalette` | `boolean` | `false` | Show extracted color palette |
|
|
421
|
+
| `aspectSkeleton` | `boolean` | `true` | Use `data-width`/`data-height` for skeleton |
|
|
422
|
+
| `video` | `boolean` | `true` | Auto-detect MP4 / YouTube / Vimeo URLs |
|
|
423
|
+
| `plugins` | `array` | `null` | Plugins to instantiate; e.g. `['name', { name, ...opts }]` |
|
|
424
|
+
| `group` | `string` | `''` | Album group name (also via `data-group`) |
|
|
425
|
+
| `favorites` | `boolean` | `false` | Heart button + localStorage |
|
|
426
|
+
| `favoritesKey` | `string` | `''` | Custom suffix for localStorage key |
|
|
427
|
+
| `infoPanel` | `boolean` | `false` | Slide-out metadata sidebar |
|
|
428
|
+
| `contextMenu` | `boolean` | `false` | Right-click menu on items |
|
|
429
|
+
| `shortcutsHelp` | `boolean` | `true` | `?` key shortcuts overlay |
|
|
430
|
+
| `infiniteScroll` | `boolean` | `false` | Auto-load more on scroll (with `loadMore`) |
|
|
431
|
+
| `loadMore` | `function` | `null` | `(currentLength) => array \| Promise<array>` |
|
|
432
|
+
| `editor` | `boolean` | `false` | Crop/rotate/flip toolbar |
|
|
433
|
+
| `annotate` | `boolean` | `false` | Freehand drawing layer |
|
|
230
434
|
|
|
231
435
|
### Data Attributes
|
|
232
436
|
|
|
@@ -241,12 +445,32 @@ All options can also be set via `data-` attributes on the container:
|
|
|
241
445
|
data-stagger="true"
|
|
242
446
|
data-slideshow="false"
|
|
243
447
|
data-slideshow-interval="5000"
|
|
448
|
+
data-slideshow-pause-on-hover="true"
|
|
449
|
+
data-slideshow-kenburns="true"
|
|
450
|
+
data-counter-format="{current} of {total}"
|
|
244
451
|
data-share="true"
|
|
245
452
|
data-filter="true"
|
|
246
453
|
data-batch-select="false"
|
|
247
|
-
data-contextual-zoom="true"
|
|
248
|
-
|
|
249
|
-
|
|
454
|
+
data-contextual-zoom="true"
|
|
455
|
+
data-story-mode="false"
|
|
456
|
+
data-pip="false"
|
|
457
|
+
data-exif="false"
|
|
458
|
+
data-backdrop-tint="false"
|
|
459
|
+
data-morph-transition="false"
|
|
460
|
+
data-color-palette="false"
|
|
461
|
+
data-drag-reorder="false"
|
|
462
|
+
data-virtual-scroll="false"
|
|
463
|
+
data-aspect-skeleton="true"
|
|
464
|
+
data-group="vacation"
|
|
465
|
+
data-favorites="true"
|
|
466
|
+
data-info-panel="true"
|
|
467
|
+
data-context-menu="true"
|
|
468
|
+
data-shortcuts-help="true"
|
|
469
|
+
data-editor="true"
|
|
470
|
+
data-annotate="true"
|
|
471
|
+
data-video="true">
|
|
472
|
+
<a href="full.jpg" data-tags="landscape,nature" data-size="large" data-width="1200" data-height="800" data-poster="poster.jpg" data-type="image">
|
|
473
|
+
<img src="thumb.jpg" alt="Photo" data-focus="0.5 0.3" data-blurhash="LEHV6nWB2y...">
|
|
250
474
|
</a>
|
|
251
475
|
</div>
|
|
252
476
|
```
|
|
@@ -283,10 +507,59 @@ Switch themes at runtime by setting `data-theme="light"` or `data-theme="dark"`
|
|
|
283
507
|
|
|
284
508
|
| Browser | Version |
|
|
285
509
|
|---------|---------|
|
|
286
|
-
| Chrome |
|
|
287
|
-
| Firefox |
|
|
288
|
-
| Safari |
|
|
289
|
-
| Edge |
|
|
510
|
+
| Chrome | 80+ |
|
|
511
|
+
| Firefox | 75+ |
|
|
512
|
+
| Safari | 14+ |
|
|
513
|
+
| Edge | 80+ |
|
|
514
|
+
|
|
515
|
+
> **v3.0.0** raised the minimum to take advantage of `aspect-ratio`, `backdrop-filter`,
|
|
516
|
+
> stable `IntersectionObserver`, and modern Canvas/Blob APIs. If you need older
|
|
517
|
+
> browser support, pin to v2.1.0.
|
|
518
|
+
|
|
519
|
+
## 🔁 Migration from v2.x to v3.0.0
|
|
520
|
+
|
|
521
|
+
**v3.0.0 contains breaking changes.** Most galleries will continue to work, but
|
|
522
|
+
review the following:
|
|
523
|
+
|
|
524
|
+
### Slideshow config is nested
|
|
525
|
+
|
|
526
|
+
```js
|
|
527
|
+
// v2.x
|
|
528
|
+
new NeikiGallery('#g', { slideshow: true, slideshowInterval: 5000 });
|
|
529
|
+
|
|
530
|
+
// v3.0.0 — preferred (fine-grained control)
|
|
531
|
+
new NeikiGallery('#g', {
|
|
532
|
+
slideshow: { interval: 5000, pauseOnHover: true, kenburns: true }
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// v3.0.0 — still works (uses defaults)
|
|
536
|
+
new NeikiGallery('#g', { slideshow: true });
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Default theme is `'system'`
|
|
540
|
+
|
|
541
|
+
If you relied on the old default `'dark'`, set it explicitly:
|
|
542
|
+
|
|
543
|
+
```js
|
|
544
|
+
new NeikiGallery('#g', { theme: 'dark' });
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Hash format changed
|
|
548
|
+
|
|
549
|
+
Old: `#neiki-1=3` → New: `#gallery-id-or-group-name/3`
|
|
550
|
+
|
|
551
|
+
If you have external links to the old format, update them or set
|
|
552
|
+
`hashNavigation: false` and implement custom routing.
|
|
553
|
+
|
|
554
|
+
### Counter format
|
|
555
|
+
|
|
556
|
+
Default output (`"3 / 12"`) is unchanged, but it's now formatted via
|
|
557
|
+
`counterFormat: '{current} / {total}'`. Override with custom tokens.
|
|
558
|
+
|
|
559
|
+
### Browser support
|
|
560
|
+
|
|
561
|
+
Minimum Chrome 80+ / Firefox 75+ / Safari 14+ / Edge 80+. If you need older
|
|
562
|
+
browser support, stay on v2.1.0.
|
|
290
563
|
|
|
291
564
|
## 📄 License
|
|
292
565
|
|