neiki-gallery 1.0.0 → 2.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/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-1.0.0-2563EB?style=for-the-badge&logo=semantic-release&logoColor=white&labelColor=000F15&logoWidth=20" alt="Version">
13
+ <img src="https://img.shields.io/badge/Version-2.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">
@@ -19,7 +19,7 @@
19
19
  </p>
20
20
 
21
21
  <p align="center">
22
- <img src="https://img.shields.io/badge/Layouts-Masonry%20%26%20Grid-3b82f6?style=flat&labelColor=383C43" />
22
+ <img src="https://img.shields.io/badge/Layouts-Masonry%20·%20Grid%20·%20Mosaic%20·%20Filmstrip-3b82f6?style=flat&labelColor=383C43" />
23
23
  <img src="https://img.shields.io/badge/Themes-Light%20%26%20Dark-8b5cf6?style=flat&labelColor=383C43" />
24
24
  <img src="https://img.shields.io/badge/Setup-Zero%20Config-22c55e?style=flat&labelColor=383C43" />
25
25
  <img src="https://img.shields.io/badge/Size-Lightweight-f97316?style=flat&labelColor=383C43" />
@@ -33,36 +33,51 @@
33
33
 
34
34
  ## ✨ Features
35
35
 
36
- - **Masonry & Grid layouts** — switchable via option or `data-` attribute
37
- - **Lightbox** — smooth open/close animations with fade or slide transitions
38
- - **Keyboard navigation** — arrow keys, Escape, Home/End, F for fullscreen
39
- - **Touch / swipe support** — mobile-friendly left/right swipe to navigate
40
- - **Lazy loading** — IntersectionObserver-powered with shimmer placeholders
41
- - **Image captions** — via `data-caption` attribute
42
- - **Thumbnail strip** — optional scrollable thumbnails in lightbox
43
- - **Zoom** — click to toggle zoom in/out
44
- - **Fullscreen mode** — native Fullscreen API
45
- - **Image counter** — e.g. "3 / 12"
46
- - **Loading spinner** — pure CSS spinner while images load
47
- - **Deep linking** — URL hash support (`#neiki-1=3` opens image 3)
36
+ - **4 Layouts** — Masonry, Grid, Mosaic (`data-size`), and Filmstrip (horizontal scroll)
37
+ - **Glassmorphism lightbox** — backdrop-blur overlay with floating toolbar
38
+ - **Slideshow / Autoplay** — animated progress bar, play/pause, configurable interval
39
+ - **Comparison slider** — `NeikiGallery.compare()` for before/after image comparison
40
+ - **Share popup** — copy link to clipboard or download image from lightbox
41
+ - **Contextual zoom** — zoom to clicked point with pan support
42
+ - **Batch select** — Shift+click multi-select with checkmark overlays
43
+ - **Tag filtering** — auto-generated pill filter bar from `data-tags`
44
+ - **Staggered entrance** — sequential fade-in animation on load
45
+ - **Keyboard navigation** — arrows, Escape, Home/End, F (fullscreen), Space (slideshow)
46
+ - **Touch / swipe** — mobile-friendly left/right swipe navigation
47
+ - **Lazy loading** — IntersectionObserver with shimmer placeholders
48
+ - **Image captions** — bottom-sheet style on mobile
49
+ - **Thumbnail strip** — scrollable thumbnails with scale hover effect
50
+ - **Zoom** — click to toggle zoom, or contextual zoom to cursor point
51
+ - **Fullscreen** — native Fullscreen API
52
+ - **Pill counter** — glassmorphism pill-shaped counter badge
53
+ - **Toast notifications** — for share/copy actions
54
+ - **Deep linking** — URL hash navigation
48
55
  - **Multiple instances** — independent galleries on one page
49
- - **Dark & light themes** — via CSS custom properties and `data-theme`
56
+ - **Dark & light themes** — CSS custom properties + accent color system (`--neiki-accent`)
50
57
  - **Accessibility** — ARIA attributes, focus management, `prefers-reduced-motion`
51
- - **Preloading** — adjacent images preloaded for instant navigation
52
- - **Infinite loop** — optional wrap-around navigation
53
- - **Event system** — `open`, `close`, `change` events
54
- - **Clean destroy** — full cleanup of DOM nodes and event listeners
55
- - **Cross-browser** — Chrome, Firefox, Safari, Edge
58
+ - **Event system** — `open`, `close`, `change`, `filter`, `select`, `slideshowStart`, `slideshowStop`
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
+ - **Cross-browser** — Chrome 60+, Firefox 55+, Safari 12+, Edge 79+
56
72
 
57
73
  ## 🚀 Quick Start
58
74
 
59
75
  ### CDN (Recommended)
60
76
 
61
- Add these two lines to your HTML — that's all you need:
77
+ Add this single line to your HTML — that's all you need (CSS is included automatically):
62
78
 
63
79
  ```html
64
- <link rel="stylesheet" href="http://cdn.neiki.eu/neiki-gallery/neiki-gallery.min.css">
65
- <script src="http://cdn.neiki.eu/neiki-gallery/neiki-gallery.min.js"></script>
80
+ <script src="https://cdn.neiki.eu/neiki-gallery/neiki-gallery.min.js"></script>
66
81
  ```
67
82
 
68
83
  Then create your gallery markup:
@@ -80,16 +95,15 @@ Then create your gallery markup:
80
95
 
81
96
  That's it — galleries with `data-neiki-gallery` auto-initialize on page load.
82
97
 
83
- > **Unminified files** are also available if you need them for debugging:
98
+ > **Unminified files** are also available if you need them for debugging (require separate CSS):
84
99
  > ```
85
- > http://cdn.neiki.eu/neiki-gallery/neiki-gallery.js
86
- > http://cdn.neiki.eu/neiki-gallery/neiki-gallery.css
100
+ > https://cdn.neiki.eu/neiki-gallery/neiki-gallery.js
101
+ > https://cdn.neiki.eu/neiki-gallery/neiki-gallery.css
87
102
  > ```
88
103
 
89
104
  > **Pin a specific version** to avoid unexpected changes:
90
105
  > ```
91
- > http://cdn.neiki.eu/neiki-gallery/1.0.0/neiki-gallery.min.js
92
- > http://cdn.neiki.eu/neiki-gallery/1.0.0/neiki-gallery.min.css
106
+ > https://cdn.neiki.eu/neiki-gallery/2.1.0/neiki-gallery.min.js
93
107
  > ```
94
108
 
95
109
  ### Self-Hosting (Local)
@@ -100,34 +114,59 @@ Download or clone the repository from GitHub:
100
114
  git clone https://github.com/neikiri/neiki-gallery.git
101
115
  ```
102
116
 
103
- Copy the files from the `dist/` folder into your project and link them directly:
117
+ For production, you only need one file CSS is already included:
104
118
 
105
119
  ```html
106
- <link rel="stylesheet" href="path/to/neiki-gallery.min.css">
107
120
  <script src="path/to/neiki-gallery.min.js"></script>
108
121
  ```
109
122
 
110
- The `dist/` folder contains both minified and unminified versions:
123
+ For development / debugging, use the unminified versions (requires separate CSS):
124
+
125
+ ```html
126
+ <link rel="stylesheet" href="path/to/neiki-gallery.css">
127
+ <script src="path/to/neiki-gallery.js"></script>
128
+ ```
129
+
130
+ The `dist/` folder contains:
111
131
 
112
132
  | File | Description |
113
133
  |------|-------------|
114
- | `neiki-gallery.min.js` | Minified JS (production) |
115
- | `neiki-gallery.min.css` | Minified CSS (production) |
116
- | `neiki-gallery.js` | Full JS (development / debugging) |
134
+ | `neiki-gallery.min.js` | Minified JS + CSS included (production) |
135
+ | `neiki-gallery.min.css` | Minified CSS standalone (optional) |
136
+ | `neiki-gallery.js` | Full JS without CSS (development / debugging) |
117
137
  | `neiki-gallery.css` | Full CSS (development / debugging) |
118
138
 
119
139
  ### Manual Initialization
120
140
 
121
141
  ```js
122
142
  const gallery = new NeikiGallery('#my-gallery', {
123
- layout: 'masonry', // 'masonry' | 'grid'
143
+ layout: 'masonry', // 'masonry' | 'grid' | 'mosaic' | 'filmstrip'
124
144
  loop: true,
125
145
  thumbnails: true,
126
146
  zoom: true,
147
+ contextualZoom: false, // zoom to click point
127
148
  fullscreen: true,
128
- transition: 'fade', // 'fade' | 'slide'
129
- theme: 'dark', // 'dark' | 'light'
149
+ transition: 'fade', // 'fade' | 'slide'
150
+ theme: 'dark', // 'dark' | 'light'
130
151
  hashNavigation: true,
152
+ stagger: true, // entrance animation
153
+ slideshow: false, // auto-start slideshow on open
154
+ slideshowInterval: 4000, // ms between slides
155
+ share: true, // share/download popup
156
+ filter: false, // tag filtering
157
+ batchSelect: false, // Shift+click multi-select
158
+ // v2.1.0
159
+ focusPoint: true, // respect data-focus for object-position
160
+ blurhash: true, // decode data-blurhash placeholders
161
+ exif: false, // show EXIF overlay in lightbox
162
+ storyMode: false, // vertical fullscreen story viewer
163
+ pip: false, // picture-in-picture lightbox
164
+ virtualScroll: false, // virtualize grid for large galleries
165
+ dragReorder: false, // drag-and-drop reorder
166
+ backdropTint: false, // tint overlay with dominant color
167
+ morphTransition: false, // FLIP morph from grid to lightbox
168
+ colorPalette: false, // extract dominant colors
169
+ aspectSkeleton: true, // data-width/data-height skeleton
131
170
  });
132
171
  ```
133
172
 
@@ -136,11 +175,52 @@ const gallery = new NeikiGallery('#my-gallery', {
136
175
  ### Methods
137
176
 
138
177
  ```js
139
- gallery.open(index); // Open lightbox at image index
140
- gallery.close(); // Close lightbox
141
- gallery.next(); // Go to next image
142
- gallery.prev(); // Go to previous image
143
- gallery.destroy(); // Remove gallery, clean up all listeners & DOM
178
+ gallery.open(index); // Open lightbox at image index
179
+ gallery.close(); // Close lightbox
180
+ gallery.next(); // Go to next image
181
+ gallery.prev(); // Go to previous image
182
+ gallery.startSlideshow(); // Start autoplay
183
+ gallery.stopSlideshow(); // Stop autoplay
184
+ gallery.toggleSlideshow(); // Toggle autoplay
185
+ gallery.filter('landscape'); // Filter by tag (null = show all)
186
+ gallery.getSelected(); // Get batch-selected items
187
+ gallery.clearSelection(); // Clear batch selection
188
+ gallery.getOrder(); // Get current item order (after drag reorder)
189
+ gallery.destroy(); // Remove gallery, clean up all listeners & DOM
190
+ ```
191
+
192
+ ### Static Utilities
193
+
194
+ ```js
195
+ // Comparison slider
196
+ const slider = NeikiGallery.compare('#compare-container', {
197
+ before: 'before.jpg',
198
+ after: 'after.jpg',
199
+ labelBefore: 'Before',
200
+ labelAfter: 'After',
201
+ startPosition: 50
202
+ });
203
+
204
+ slider.setPosition(30); // Move handle to 30%
205
+ slider.destroy(); // Clean up
206
+
207
+ // Color palette extraction (v2.1.0)
208
+ NeikiGallery.extractPalette('photo.jpg', 5, (colors) => {
209
+ console.log(colors); // [{r, g, b, hex}, ...]
210
+ });
211
+
212
+ // Dominant color (v2.1.0)
213
+ NeikiGallery.extractDominantColor('photo.jpg', (color) => {
214
+ console.log(color); // {r, g, b, hex}
215
+ });
216
+
217
+ // EXIF parsing (v2.1.0)
218
+ NeikiGallery.parseExif('photo.jpg', (tags) => {
219
+ console.log(tags); // {make, model, iso, fNumber, exposure, focalLength}
220
+ });
221
+
222
+ // Blurhash decoding (v2.1.0)
223
+ const pixels = NeikiGallery.decodeBlurhash('LEHV6nWB2y...', 32, 32);
144
224
  ```
145
225
 
146
226
  ### Events
@@ -157,24 +237,61 @@ gallery.on('close', () => {
157
237
  gallery.on('change', (index) => {
158
238
  console.log('Now showing image', index);
159
239
  });
240
+
241
+ gallery.on('filter', (tag) => {
242
+ console.log('Filtered by:', tag);
243
+ });
244
+
245
+ gallery.on('select', (indices) => {
246
+ console.log('Selected:', indices);
247
+ });
248
+
249
+ gallery.on('slideshowStart', () => {
250
+ console.log('Slideshow started');
251
+ });
252
+
253
+ gallery.on('reorder', (order) => {
254
+ console.log('New order:', order);
255
+ });
256
+
257
+ gallery.on('pipEnter', () => console.log('PiP on'));
258
+ gallery.on('storyEnter', () => console.log('Story opened'));
160
259
  ```
161
260
 
162
261
  ### Options
163
262
 
164
263
  | Option | Type | Default | Description |
165
264
  |--------|------|---------|-------------|
166
- | `layout` | `string` | `'masonry'` | Grid layout: `'masonry'` or `'grid'` |
265
+ | `layout` | `string` | `'masonry'` | `'masonry'` · `'grid'` · `'mosaic'` · `'filmstrip'` |
167
266
  | `loop` | `boolean` | `false` | Enable infinite loop navigation |
168
267
  | `thumbnails` | `boolean` | `true` | Show thumbnail strip in lightbox |
169
268
  | `zoom` | `boolean` | `true` | Enable zoom on image click |
269
+ | `contextualZoom` | `boolean` | `false` | Zoom to cursor point instead of center |
170
270
  | `fullscreen` | `boolean` | `true` | Show fullscreen button |
171
- | `transition` | `string` | `'fade'` | Transition effect: `'fade'` or `'slide'` |
172
- | `theme` | `string` | `'dark'` | Theme: `'dark'` or `'light'` |
173
- | `hashNavigation` | `boolean` | `true` | Enable URL hash deep linking |
271
+ | `transition` | `string` | `'fade'` | `'fade'` or `'slide'` |
272
+ | `theme` | `string` | `'dark'` | `'dark'` or `'light'` |
273
+ | `hashNavigation` | `boolean` | `true` | URL hash deep linking |
174
274
  | `counter` | `boolean` | `true` | Show image counter |
175
275
  | `captions` | `boolean` | `true` | Show image captions |
176
- | `preload` | `number` | `1` | Number of adjacent images to preload |
276
+ | `preload` | `number` | `1` | Adjacent images to preload |
177
277
  | `lazyLoad` | `boolean` | `true` | Lazy load grid thumbnails |
278
+ | `stagger` | `boolean` | `true` | Staggered entrance animation |
279
+ | `slideshow` | `boolean` | `false` | Auto-start slideshow on open |
280
+ | `slideshowInterval` | `number` | `4000` | Slideshow interval in ms |
281
+ | `share` | `boolean` | `true` | Show share button in lightbox |
282
+ | `filter` | `boolean` | `false` | Enable tag filtering bar |
283
+ | `batchSelect` | `boolean` | `false` | Enable Shift+click multi-select |
284
+ | `focusPoint` | `boolean` | `true` | Respect `data-focus` for `object-position` |
285
+ | `blurhash` | `boolean` | `true` | Decode `data-blurhash` placeholders |
286
+ | `exif` | `boolean` | `false` | Show EXIF data overlay in lightbox |
287
+ | `storyMode` | `boolean` | `false` | Enable story mode button in toolbar |
288
+ | `pip` | `boolean` | `false` | Enable PiP button in toolbar |
289
+ | `virtualScroll` | `boolean` | `false` | Virtualize grid for 50+ items |
290
+ | `dragReorder` | `boolean` | `false` | Enable drag & drop reorder |
291
+ | `backdropTint` | `boolean` | `false` | Tint overlay with dominant color |
292
+ | `morphTransition` | `boolean` | `false` | FLIP morph from grid to lightbox |
293
+ | `colorPalette` | `boolean` | `false` | Show extracted color palette |
294
+ | `aspectSkeleton` | `boolean` | `true` | Use `data-width`/`data-height` for skeleton |
178
295
 
179
296
  ### Data Attributes
180
297
 
@@ -182,14 +299,30 @@ All options can also be set via `data-` attributes on the container:
182
299
 
183
300
  ```html
184
301
  <div data-neiki-gallery
185
- data-layout="grid"
302
+ data-layout="mosaic"
186
303
  data-theme="light"
187
304
  data-transition="slide"
188
305
  data-loop="true"
189
- data-thumbnails="true"
190
- data-zoom="true"
191
- data-fullscreen="true"
192
- data-hash-navigation="true">
306
+ data-stagger="true"
307
+ data-slideshow="false"
308
+ data-slideshow-interval="5000"
309
+ data-share="true"
310
+ data-filter="true"
311
+ data-batch-select="false"
312
+ data-contextual-zoom="true"
313
+ data-story-mode="false"
314
+ data-pip="false"
315
+ data-exif="false"
316
+ data-backdrop-tint="false"
317
+ data-morph-transition="false"
318
+ data-color-palette="false"
319
+ data-drag-reorder="false"
320
+ data-virtual-scroll="false"
321
+ data-aspect-skeleton="true">
322
+ <a href="full.jpg" data-tags="landscape,nature" data-size="large" data-width="1200" data-height="800">
323
+ <img src="thumb.jpg" alt="Photo" data-focus="0.5 0.3" data-blurhash="LEHV6nWB2y...">
324
+ </a>
325
+ </div>
193
326
  ```
194
327
 
195
328
  ## 🎨 Theming
@@ -199,15 +332,20 @@ Neiki Gallery uses CSS custom properties for full theming control:
199
332
  ```css
200
333
  :root {
201
334
  --neiki-columns: 4;
202
- --neiki-gap: 12px;
203
- --neiki-border-radius: 6px;
204
- --neiki-overlay-bg: rgba(0, 0, 0, 0.92);
205
- --neiki-btn-bg: rgba(255, 255, 255, 0.12);
335
+ --neiki-gap: 14px;
336
+ --neiki-border-radius: 14px;
337
+ --neiki-accent: #3b82f6;
338
+ --neiki-overlay-bg: rgba(8, 8, 12, 0.85);
339
+ --neiki-overlay-backdrop: blur(24px) saturate(1.2);
340
+ --neiki-btn-bg: rgba(255, 255, 255, 0.1);
206
341
  --neiki-btn-color: #fff;
207
342
  --neiki-caption-color: #fff;
208
- --neiki-spinner-color: #fff;
209
- --neiki-thumb-size: 56px;
343
+ --neiki-spinner-color: var(--neiki-accent);
344
+ --neiki-thumb-size: 52px;
210
345
  --neiki-zoom-scale: 2;
346
+ --neiki-stagger-delay: 0.04s;
347
+ --neiki-hover-lift: -4px;
348
+ --neiki-hover-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
211
349
  --neiki-transition-duration: 0.3s;
212
350
  /* ... and more */
213
351
  }
@@ -231,3 +369,9 @@ This project is licensed under the MIT License — see the [LICENSE](LICENSE) fi
231
369
  ## 📬 Contact
232
370
 
233
371
  - **Email:** [dev@neiki.eu](mailto:dev@neiki.eu)
372
+
373
+ ---
374
+
375
+ <p align="center">
376
+ Made with ❤️ for the web community
377
+ </p>