neiki-gallery 2.1.0 โ 3.1.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 +255 -43
- package/dist/neiki-gallery.css +668 -3
- package/dist/neiki-gallery.js +1489 -25
- package/dist/neiki-gallery.min.css +1 -1
- package/dist/neiki-gallery.min.js +2 -2
- package/package.json +57 -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
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
<h1 align="center">Neiki Gallery</h1>
|
|
2
|
-
|
|
3
1
|
<p align="center">
|
|
4
|
-
<img src="logo.png" alt="
|
|
2
|
+
<img src="logo.png" alt="Neiki's Gallery" width="400">
|
|
5
3
|
</p>
|
|
6
4
|
|
|
5
|
+
<h1 align="center">Neiki's Gallery</h1>
|
|
6
|
+
|
|
7
7
|
<p align="center">
|
|
8
8
|
<img src="https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E" alt="JavaScript">
|
|
9
9
|
<img src="https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white" alt="HTML5">
|
|
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.1.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">
|
|
@@ -25,11 +25,24 @@
|
|
|
25
25
|
<img src="https://img.shields.io/badge/Size-Lightweight-f97316?style=flat&labelColor=383C43" />
|
|
26
26
|
</p>
|
|
27
27
|
|
|
28
|
+
|
|
29
|
+
<p align="center">
|
|
30
|
+
<a href="https://sourceforge.net/projects/neiki-gallery/files/latest/download"><img alt="Download Neiki's Gallery" src="https://a.fsdn.com/con/app/sf-download-button" width=276 height=48 srcset="https://a.fsdn.com/con/app/sf-download-button?button_size=2x 2x"></a>
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<img src="preview.png" width="900px">
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
**Live demo:** [https://neikiri.dev/gallery](https://neikiri.dev/gallery)
|
|
40
|
+
|
|
28
41
|
---
|
|
29
42
|
|
|
30
43
|
## ๐ About
|
|
31
44
|
|
|
32
|
-
**Neiki Gallery** is a production-ready image gallery and lightbox library built with vanilla JavaScript and CSS. No frameworks, no dependencies โ just drop two files into your project and you're ready to go.
|
|
45
|
+
**Neiki's Gallery** is a production-ready image gallery and lightbox library built with vanilla JavaScript and CSS. No frameworks, no dependencies โ just drop two files into your project and you're ready to go.
|
|
33
46
|
|
|
34
47
|
## โจ Features
|
|
35
48
|
|
|
@@ -55,7 +68,7 @@
|
|
|
55
68
|
- **Multiple instances** โ independent galleries on one page
|
|
56
69
|
- **Dark & light themes** โ CSS custom properties + accent color system (`--neiki-accent`)
|
|
57
70
|
- **Accessibility** โ ARIA attributes, focus management, `prefers-reduced-motion`
|
|
58
|
-
- **Event system** โ `open`, `close`, `change`, `filter`, `select`, `slideshowStart`, `slideshowStop`
|
|
71
|
+
- **Event system** โ `open`, `close`, `change`, `filter`, `select`, `slideshowStart`, `slideshowStop`, `favorite`, `unfavorite`, `infoOpen`, `infoClose`, `print`, `editorOpen`, `editorExport`, `annotateOpen`, `annotateExport`, `append`, `remove`
|
|
59
72
|
- **Blurhash placeholders** โ `data-blurhash` attribute decoded into blurred preview (replaces shimmer)
|
|
60
73
|
- **Story mode** โ Instagram-like vertical fullscreen viewer with progress bars and tap navigation
|
|
61
74
|
- **Picture-in-Picture** โ minimize lightbox to a resizable corner window
|
|
@@ -68,7 +81,21 @@
|
|
|
68
81
|
- **Drag & drop reorder** โ HTML5 drag to reorder grid items
|
|
69
82
|
- **Aspect-ratio skeleton** โ `data-width`/`data-height` for placeholder sizing
|
|
70
83
|
- **Web Share API** โ native mobile sharing with clipboard fallback
|
|
71
|
-
- **
|
|
84
|
+
- **Video & embeds** โ auto-detect MP4/WebM/Ogg/MOV/M4V, YouTube and Vimeo URLs in lightbox
|
|
85
|
+
- **Plugin system** โ `NeikiGallery.registerPlugin()` with `init`/`open`/`change`/`close`/`destroy` lifecycle hooks
|
|
86
|
+
- **Album groups** โ `data-group="album"` links galleries; navigation traverses across all
|
|
87
|
+
- **Favorites** โ heart button + localStorage persistence + `B` key shortcut
|
|
88
|
+
- **Info panel** โ slide-out sidebar with metadata, EXIF, source URL (`I` key)
|
|
89
|
+
- **Image editor** โ rotate / flip / export to PNG via `<canvas>`
|
|
90
|
+
- **Annotation layer** โ freehand drawing with color picker, brush size, undo, clear, export
|
|
91
|
+
- **Print** โ print current image with caption (`P` key)
|
|
92
|
+
- **Right-click context menu** โ open original, copy link, download, share, print, favorite
|
|
93
|
+
- **Infinite scroll** โ `loadMore` callback + `append()` / `remove()` API
|
|
94
|
+
- **Keyboard shortcuts overlay** โ press `?` to view all shortcuts
|
|
95
|
+
- **System theme detection** โ `theme: 'system'` follows OS `prefers-color-scheme`
|
|
96
|
+
- **Kenburns slideshow** โ slow zoom-and-pan animation per slide
|
|
97
|
+
- **Configurable counter** โ `counterFormat` with `{current}`/`{total}`/`{percent}` tokens
|
|
98
|
+
- **Cross-browser** โ Chrome 80+, Firefox 75+, Safari 14+, Edge 80+
|
|
72
99
|
|
|
73
100
|
## ๐ Quick Start
|
|
74
101
|
|
|
@@ -77,7 +104,7 @@
|
|
|
77
104
|
Add this single line to your HTML โ that's all you need (CSS is included automatically):
|
|
78
105
|
|
|
79
106
|
```html
|
|
80
|
-
<script src="https://cdn.
|
|
107
|
+
<script src="https://cdn.neikiri.dev/neiki-gallery/neiki-gallery.min.js"></script>
|
|
81
108
|
```
|
|
82
109
|
|
|
83
110
|
Then create your gallery markup:
|
|
@@ -97,13 +124,13 @@ That's it โ galleries with `data-neiki-gallery` auto-initialize on page load.
|
|
|
97
124
|
|
|
98
125
|
> **Unminified files** are also available if you need them for debugging (require separate CSS):
|
|
99
126
|
> ```
|
|
100
|
-
> https://cdn.
|
|
101
|
-
> https://cdn.
|
|
127
|
+
> https://cdn.neikiri.dev/neiki-gallery/neiki-gallery.js
|
|
128
|
+
> https://cdn.neikiri.dev/neiki-gallery/neiki-gallery.css
|
|
102
129
|
> ```
|
|
103
130
|
|
|
104
131
|
> **Pin a specific version** to avoid unexpected changes:
|
|
105
132
|
> ```
|
|
106
|
-
> https://cdn.
|
|
133
|
+
> https://cdn.neikiri.dev/neiki-gallery/3.1.0/neiki-gallery.min.js
|
|
107
134
|
> ```
|
|
108
135
|
|
|
109
136
|
### Self-Hosting (Local)
|
|
@@ -147,26 +174,45 @@ const gallery = new NeikiGallery('#my-gallery', {
|
|
|
147
174
|
contextualZoom: false, // zoom to click point
|
|
148
175
|
fullscreen: true,
|
|
149
176
|
transition: 'fade', // 'fade' | 'slide'
|
|
150
|
-
theme: '
|
|
177
|
+
theme: 'system', // 'dark' | 'light' | 'system' (auto-detect) โ v3 default
|
|
151
178
|
hashNavigation: true,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
179
|
+
counter: true,
|
|
180
|
+
counterFormat: '{current} / {total}', // v3 โ tokens: {current}, {total}, {percent}
|
|
181
|
+
stagger: true,
|
|
182
|
+
slideshow: { // v3 โ nested config (boolean still works)
|
|
183
|
+
interval: 4000,
|
|
184
|
+
pauseOnHover: true,
|
|
185
|
+
kenburns: false,
|
|
186
|
+
direction: 'forward' // or 'reverse'
|
|
187
|
+
},
|
|
188
|
+
share: true,
|
|
189
|
+
filter: false,
|
|
190
|
+
batchSelect: false,
|
|
158
191
|
// v2.1.0
|
|
159
|
-
focusPoint: true,
|
|
160
|
-
blurhash: true,
|
|
161
|
-
exif: false,
|
|
162
|
-
storyMode: false,
|
|
163
|
-
pip: false,
|
|
164
|
-
virtualScroll: false,
|
|
165
|
-
dragReorder: false,
|
|
166
|
-
backdropTint: false,
|
|
167
|
-
morphTransition: false,
|
|
168
|
-
colorPalette: false,
|
|
169
|
-
aspectSkeleton: true,
|
|
192
|
+
focusPoint: true,
|
|
193
|
+
blurhash: true,
|
|
194
|
+
exif: false,
|
|
195
|
+
storyMode: false,
|
|
196
|
+
pip: false,
|
|
197
|
+
virtualScroll: false,
|
|
198
|
+
dragReorder: false,
|
|
199
|
+
backdropTint: false,
|
|
200
|
+
morphTransition: false,
|
|
201
|
+
colorPalette: false,
|
|
202
|
+
aspectSkeleton: true,
|
|
203
|
+
// v3.0.0
|
|
204
|
+
video: true, // detect MP4 / YouTube / Vimeo
|
|
205
|
+
plugins: ['watermark', { name: 'analytics', trackingId: 'X' }],
|
|
206
|
+
group: '', // album group name (or use data-group)
|
|
207
|
+
favorites: false, // โค๏ธ button + localStorage
|
|
208
|
+
favoritesKey: '', // custom localStorage key suffix
|
|
209
|
+
infoPanel: false, // sidebar with metadata (I key)
|
|
210
|
+
contextMenu: false, // right-click menu on items
|
|
211
|
+
shortcutsHelp: true, // overlay on '?' key
|
|
212
|
+
infiniteScroll: false, // auto-load more
|
|
213
|
+
loadMore: null, // function(currentLength) โ array | Promise<array>
|
|
214
|
+
editor: false, // crop/rotate/flip toolbar
|
|
215
|
+
annotate: false // freehand drawing layer
|
|
170
216
|
});
|
|
171
217
|
```
|
|
172
218
|
|
|
@@ -177,15 +223,50 @@ const gallery = new NeikiGallery('#my-gallery', {
|
|
|
177
223
|
```js
|
|
178
224
|
gallery.open(index); // Open lightbox at image index
|
|
179
225
|
gallery.close(); // Close lightbox
|
|
180
|
-
gallery.next(); // Go to next image
|
|
181
|
-
gallery.prev(); // Go to previous image
|
|
226
|
+
gallery.next(); // Go to next image (group-aware)
|
|
227
|
+
gallery.prev(); // Go to previous image (group-aware)
|
|
182
228
|
gallery.startSlideshow(); // Start autoplay
|
|
183
229
|
gallery.stopSlideshow(); // Stop autoplay
|
|
230
|
+
gallery.pauseSlideshow(); // v3 โ pause without emitting stop
|
|
184
231
|
gallery.toggleSlideshow(); // Toggle autoplay
|
|
185
232
|
gallery.filter('landscape'); // Filter by tag (null = show all)
|
|
186
233
|
gallery.getSelected(); // Get batch-selected items
|
|
187
234
|
gallery.clearSelection(); // Clear batch selection
|
|
188
235
|
gallery.getOrder(); // Get current item order (after drag reorder)
|
|
236
|
+
|
|
237
|
+
// v3.0.0 โ Favorites
|
|
238
|
+
gallery.toggleFavorite(); // Toggle favorite for current image
|
|
239
|
+
gallery.isFavorite(index); // Check if image is favorited
|
|
240
|
+
gallery.getFavorites(); // Get array of favorited image src URLs
|
|
241
|
+
gallery.clearFavorites(); // Remove all favorites
|
|
242
|
+
|
|
243
|
+
// v3.0.0 โ Info panel / overlays
|
|
244
|
+
gallery.toggleInfoPanel(force); // Toggle info sidebar (force = bool)
|
|
245
|
+
gallery.toggleShortcutsHelp(force); // Toggle keyboard shortcuts overlay
|
|
246
|
+
|
|
247
|
+
// v3.0.0 โ Editor & annotation
|
|
248
|
+
gallery.openEditor(); // Open crop/rotate/flip editor
|
|
249
|
+
gallery.closeEditor();
|
|
250
|
+
gallery.getEditedBlob(); // Last exported edited image as Blob
|
|
251
|
+
|
|
252
|
+
gallery.openAnnotate(); // Open drawing layer
|
|
253
|
+
gallery.closeAnnotate();
|
|
254
|
+
gallery.getAnnotatedBlob();
|
|
255
|
+
|
|
256
|
+
// v3.0.0 โ Print & dynamic content
|
|
257
|
+
gallery.print(index); // Print current or specified image
|
|
258
|
+
gallery.append([{src,...}]); // Append new items at runtime
|
|
259
|
+
gallery.remove(index); // Remove item by index
|
|
260
|
+
|
|
261
|
+
// v3.0.0 โ Plugin access
|
|
262
|
+
gallery.plugin('watermark'); // Get plugin instance by name
|
|
263
|
+
|
|
264
|
+
// v3.0.0 โ Event helpers
|
|
265
|
+
gallery.on('change', fn);
|
|
266
|
+
gallery.off('change', fn); // Remove specific listener
|
|
267
|
+
gallery.off('change'); // Remove all listeners for event
|
|
268
|
+
gallery.once('open', fn); // Auto-removed after first fire
|
|
269
|
+
|
|
189
270
|
gallery.destroy(); // Remove gallery, clean up all listeners & DOM
|
|
190
271
|
```
|
|
191
272
|
|
|
@@ -221,8 +302,57 @@ NeikiGallery.parseExif('photo.jpg', (tags) => {
|
|
|
221
302
|
|
|
222
303
|
// Blurhash decoding (v2.1.0)
|
|
223
304
|
const pixels = NeikiGallery.decodeBlurhash('LEHV6nWB2y...', 32, 32);
|
|
305
|
+
|
|
306
|
+
// Media type detection (v3.0.0)
|
|
307
|
+
NeikiGallery.detectMediaType('https://youtube.com/watch?v=abc'); // 'youtube'
|
|
308
|
+
NeikiGallery.detectMediaType('clip.mp4'); // 'video'
|
|
309
|
+
NeikiGallery.detectMediaType('photo.jpg'); // 'image'
|
|
310
|
+
|
|
311
|
+
// Plugin registration (v3.0.0)
|
|
312
|
+
NeikiGallery.registerPlugin('watermark', (gallery, options) => ({
|
|
313
|
+
init() { /* set up DOM, listeners */ },
|
|
314
|
+
open() { /* on lightbox open */ },
|
|
315
|
+
change(d){ /* on slide change, d = {index, item, prevIndex} */ },
|
|
316
|
+
close() { /* on lightbox close */ },
|
|
317
|
+
destroy(){ /* cleanup */ }
|
|
318
|
+
}));
|
|
319
|
+
|
|
320
|
+
NeikiGallery.unregisterPlugin('watermark');
|
|
321
|
+
NeikiGallery.getRegisteredPlugins(); // ['watermark', ...]
|
|
322
|
+
|
|
323
|
+
// Version
|
|
324
|
+
console.log(NeikiGallery.version); // '3.1.0'
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Plugin System
|
|
328
|
+
|
|
329
|
+
A plugin is a factory function that receives the gallery instance and an options
|
|
330
|
+
object, and returns an object with optional lifecycle methods:
|
|
331
|
+
|
|
332
|
+
```js
|
|
333
|
+
NeikiGallery.registerPlugin('analytics', (gallery, opts) => ({
|
|
334
|
+
init() {
|
|
335
|
+
console.log('[analytics] gallery initialized');
|
|
336
|
+
},
|
|
337
|
+
open(data) {
|
|
338
|
+
track('lightbox_open', { index: data.index });
|
|
339
|
+
},
|
|
340
|
+
change(data) {
|
|
341
|
+
track('slide_view', { src: data.item.src, index: data.index });
|
|
342
|
+
},
|
|
343
|
+
close() {
|
|
344
|
+
track('lightbox_close');
|
|
345
|
+
},
|
|
346
|
+
destroy() {
|
|
347
|
+
console.log('[analytics] cleanup');
|
|
348
|
+
}
|
|
349
|
+
}));
|
|
350
|
+
|
|
351
|
+
new NeikiGallery('#g', { plugins: [{ name: 'analytics', sampleRate: 0.5 }] });
|
|
224
352
|
```
|
|
225
353
|
|
|
354
|
+
You can access plugin instances on a gallery via `gallery.plugin('analytics')`.
|
|
355
|
+
|
|
226
356
|
### Events
|
|
227
357
|
|
|
228
358
|
```js
|
|
@@ -256,6 +386,16 @@ gallery.on('reorder', (order) => {
|
|
|
256
386
|
|
|
257
387
|
gallery.on('pipEnter', () => console.log('PiP on'));
|
|
258
388
|
gallery.on('storyEnter', () => console.log('Story opened'));
|
|
389
|
+
|
|
390
|
+
// v3.0.0 events
|
|
391
|
+
gallery.on('favorite', ({ index, src }) => console.log('โ
favorited', src));
|
|
392
|
+
gallery.on('unfavorite', ({ index, src }) => console.log('โ removed'));
|
|
393
|
+
gallery.on('infoOpen', () => console.log('info panel opened'));
|
|
394
|
+
gallery.on('print', ({ index, src }) => console.log('printed', src));
|
|
395
|
+
gallery.on('editorExport', ({ blob, url }) => console.log('edited blob', url));
|
|
396
|
+
gallery.on('annotateExport', ({ blob, url }) => console.log('annotated', url));
|
|
397
|
+
gallery.on('append', (items) => console.log('appended', items.length));
|
|
398
|
+
gallery.on('remove', ({ index }) => console.log('removed item', index));
|
|
259
399
|
```
|
|
260
400
|
|
|
261
401
|
### Options
|
|
@@ -269,15 +409,15 @@ gallery.on('storyEnter', () => console.log('Story opened'));
|
|
|
269
409
|
| `contextualZoom` | `boolean` | `false` | Zoom to cursor point instead of center |
|
|
270
410
|
| `fullscreen` | `boolean` | `true` | Show fullscreen button |
|
|
271
411
|
| `transition` | `string` | `'fade'` | `'fade'` or `'slide'` |
|
|
272
|
-
| `theme` | `string` | `'
|
|
412
|
+
| `theme` | `string` | `'system'` | `'dark'` ยท `'light'` ยท `'system'` (auto-detect) |
|
|
273
413
|
| `hashNavigation` | `boolean` | `true` | URL hash deep linking |
|
|
274
414
|
| `counter` | `boolean` | `true` | Show image counter |
|
|
415
|
+
| `counterFormat` | `string` | `'{current} / {total}'` | Counter format with `{current}`, `{total}`, `{percent}` tokens |
|
|
275
416
|
| `captions` | `boolean` | `true` | Show image captions |
|
|
276
417
|
| `preload` | `number` | `1` | Adjacent images to preload |
|
|
277
418
|
| `lazyLoad` | `boolean` | `true` | Lazy load grid thumbnails |
|
|
278
419
|
| `stagger` | `boolean` | `true` | Staggered entrance animation |
|
|
279
|
-
| `slideshow` | `boolean` | `false` |
|
|
280
|
-
| `slideshowInterval` | `number` | `4000` | Slideshow interval in ms |
|
|
420
|
+
| `slideshow` | `boolean \| object` | `false` | `true` or `{ interval, pauseOnHover, kenburns, direction }` |
|
|
281
421
|
| `share` | `boolean` | `true` | Show share button in lightbox |
|
|
282
422
|
| `filter` | `boolean` | `false` | Enable tag filtering bar |
|
|
283
423
|
| `batchSelect` | `boolean` | `false` | Enable Shift+click multi-select |
|
|
@@ -292,6 +432,18 @@ gallery.on('storyEnter', () => console.log('Story opened'));
|
|
|
292
432
|
| `morphTransition` | `boolean` | `false` | FLIP morph from grid to lightbox |
|
|
293
433
|
| `colorPalette` | `boolean` | `false` | Show extracted color palette |
|
|
294
434
|
| `aspectSkeleton` | `boolean` | `true` | Use `data-width`/`data-height` for skeleton |
|
|
435
|
+
| `video` | `boolean` | `true` | Auto-detect MP4 / YouTube / Vimeo URLs |
|
|
436
|
+
| `plugins` | `array` | `null` | Plugins to instantiate; e.g. `['name', { name, ...opts }]` |
|
|
437
|
+
| `group` | `string` | `''` | Album group name (also via `data-group`) |
|
|
438
|
+
| `favorites` | `boolean` | `false` | Heart button + localStorage |
|
|
439
|
+
| `favoritesKey` | `string` | `''` | Custom suffix for localStorage key |
|
|
440
|
+
| `infoPanel` | `boolean` | `false` | Slide-out metadata sidebar |
|
|
441
|
+
| `contextMenu` | `boolean` | `false` | Right-click menu on items |
|
|
442
|
+
| `shortcutsHelp` | `boolean` | `true` | `?` key shortcuts overlay |
|
|
443
|
+
| `infiniteScroll` | `boolean` | `false` | Auto-load more on scroll (with `loadMore`) |
|
|
444
|
+
| `loadMore` | `function` | `null` | `(currentLength) => array \| Promise<array>` |
|
|
445
|
+
| `editor` | `boolean` | `false` | Crop/rotate/flip toolbar |
|
|
446
|
+
| `annotate` | `boolean` | `false` | Freehand drawing layer |
|
|
295
447
|
|
|
296
448
|
### Data Attributes
|
|
297
449
|
|
|
@@ -306,6 +458,9 @@ All options can also be set via `data-` attributes on the container:
|
|
|
306
458
|
data-stagger="true"
|
|
307
459
|
data-slideshow="false"
|
|
308
460
|
data-slideshow-interval="5000"
|
|
461
|
+
data-slideshow-pause-on-hover="true"
|
|
462
|
+
data-slideshow-kenburns="true"
|
|
463
|
+
data-counter-format="{current} of {total}"
|
|
309
464
|
data-share="true"
|
|
310
465
|
data-filter="true"
|
|
311
466
|
data-batch-select="false"
|
|
@@ -318,8 +473,16 @@ All options can also be set via `data-` attributes on the container:
|
|
|
318
473
|
data-color-palette="false"
|
|
319
474
|
data-drag-reorder="false"
|
|
320
475
|
data-virtual-scroll="false"
|
|
321
|
-
data-aspect-skeleton="true"
|
|
322
|
-
|
|
476
|
+
data-aspect-skeleton="true"
|
|
477
|
+
data-group="vacation"
|
|
478
|
+
data-favorites="true"
|
|
479
|
+
data-info-panel="true"
|
|
480
|
+
data-context-menu="true"
|
|
481
|
+
data-shortcuts-help="true"
|
|
482
|
+
data-editor="true"
|
|
483
|
+
data-annotate="true"
|
|
484
|
+
data-video="true">
|
|
485
|
+
<a href="full.jpg" data-tags="landscape,nature" data-size="large" data-width="1200" data-height="800" data-poster="poster.jpg" data-type="image">
|
|
323
486
|
<img src="thumb.jpg" alt="Photo" data-focus="0.5 0.3" data-blurhash="LEHV6nWB2y...">
|
|
324
487
|
</a>
|
|
325
488
|
</div>
|
|
@@ -327,7 +490,7 @@ All options can also be set via `data-` attributes on the container:
|
|
|
327
490
|
|
|
328
491
|
## ๐จ Theming
|
|
329
492
|
|
|
330
|
-
Neiki Gallery uses CSS custom properties for full theming control:
|
|
493
|
+
Neiki's Gallery uses CSS custom properties for full theming control:
|
|
331
494
|
|
|
332
495
|
```css
|
|
333
496
|
:root {
|
|
@@ -357,10 +520,59 @@ Switch themes at runtime by setting `data-theme="light"` or `data-theme="dark"`
|
|
|
357
520
|
|
|
358
521
|
| Browser | Version |
|
|
359
522
|
|---------|---------|
|
|
360
|
-
| Chrome |
|
|
361
|
-
| Firefox |
|
|
362
|
-
| Safari |
|
|
363
|
-
| Edge |
|
|
523
|
+
| Chrome | 80+ |
|
|
524
|
+
| Firefox | 75+ |
|
|
525
|
+
| Safari | 14+ |
|
|
526
|
+
| Edge | 80+ |
|
|
527
|
+
|
|
528
|
+
> **v3.0.0** raised the minimum to take advantage of `aspect-ratio`, `backdrop-filter`,
|
|
529
|
+
> stable `IntersectionObserver`, and modern Canvas/Blob APIs. If you need older
|
|
530
|
+
> browser support, pin to v2.1.0.
|
|
531
|
+
|
|
532
|
+
## ๐ Migration from v2.x to v3.0.0
|
|
533
|
+
|
|
534
|
+
**v3.0.0 contains breaking changes.** Most galleries will continue to work, but
|
|
535
|
+
review the following:
|
|
536
|
+
|
|
537
|
+
### Slideshow config is nested
|
|
538
|
+
|
|
539
|
+
```js
|
|
540
|
+
// v2.x
|
|
541
|
+
new NeikiGallery('#g', { slideshow: true, slideshowInterval: 5000 });
|
|
542
|
+
|
|
543
|
+
// v3.0.0 โ preferred (fine-grained control)
|
|
544
|
+
new NeikiGallery('#g', {
|
|
545
|
+
slideshow: { interval: 5000, pauseOnHover: true, kenburns: true }
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// v3.0.0 โ still works (uses defaults)
|
|
549
|
+
new NeikiGallery('#g', { slideshow: true });
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Default theme is `'system'`
|
|
553
|
+
|
|
554
|
+
If you relied on the old default `'dark'`, set it explicitly:
|
|
555
|
+
|
|
556
|
+
```js
|
|
557
|
+
new NeikiGallery('#g', { theme: 'dark' });
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Hash format changed
|
|
561
|
+
|
|
562
|
+
Old: `#neiki-1=3` โ New: `#gallery-id-or-group-name/3`
|
|
563
|
+
|
|
564
|
+
If you have external links to the old format, update them or set
|
|
565
|
+
`hashNavigation: false` and implement custom routing.
|
|
566
|
+
|
|
567
|
+
### Counter format
|
|
568
|
+
|
|
569
|
+
Default output (`"3 / 12"`) is unchanged, but it's now formatted via
|
|
570
|
+
`counterFormat: '{current} / {total}'`. Override with custom tokens.
|
|
571
|
+
|
|
572
|
+
### Browser support
|
|
573
|
+
|
|
574
|
+
Minimum Chrome 80+ / Firefox 75+ / Safari 14+ / Edge 80+. If you need older
|
|
575
|
+
browser support, stay on v2.1.0.
|
|
364
576
|
|
|
365
577
|
## ๐ License
|
|
366
578
|
|
|
@@ -368,10 +580,10 @@ This project is licensed under the MIT License โ see the [LICENSE](LICENSE) fi
|
|
|
368
580
|
|
|
369
581
|
## ๐ฌ Contact
|
|
370
582
|
|
|
371
|
-
- **Email:** [
|
|
583
|
+
- **Email:** [neikiri@neikiri.dev](mailto:neikiri@neikiri.dev)
|
|
372
584
|
|
|
373
585
|
---
|
|
374
586
|
|
|
375
587
|
<p align="center">
|
|
376
588
|
Made with โค๏ธ for the web community
|
|
377
|
-
</p>
|
|
589
|
+
</p>
|