@hoangyell/gallery 1.0.3 → 1.0.6

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
@@ -2,9 +2,32 @@
2
2
 
3
3
  [Astro](https://astro.build/) image gallery component with lightbox, pyramid multi-row layout, and accessible controls.
4
4
 
5
+ **Live demo → [gallery.hoangyell.com](https://gallery.hoangyell.com)**
6
+
7
+ <p align="center">
8
+ <a href="https://gallery.hoangyell.com">
9
+ <img
10
+ src="https://raw.githubusercontent.com/HoangYell/hoangyell-gallery/main/packages/astro/docs/site-hero.jpg"
11
+ alt="@hoangyell/gallery landing page hero — The friendly Astro image gallery"
12
+ width="720"
13
+ />
14
+ </a>
15
+ </p>
16
+
17
+ <p align="center">
18
+ <em>Click any image to open the lightbox — keyboard arrows, swipe, ESC to close.</em>
19
+ <br />
20
+ <img
21
+ src="https://raw.githubusercontent.com/HoangYell/hoangyell-gallery/main/packages/astro/docs/gallery-lightbox.jpg"
22
+ alt="Lightbox view with page indicator, close button, and next-image arrow"
23
+ width="640"
24
+ />
25
+ </p>
26
+
5
27
  ## Features
6
28
 
7
29
  - **Pyramid layout** — distribute images across rows with `rows` prop
30
+ - **Two fit modes** — `cover` (default, uniform photo grid) or `contain` (natural aspect, for diagrams and tall portraits)
8
31
  - **Lightbox** — click to open, keyboard arrows, swipe, ESC to close
9
32
  - **Corner rounding** — only the four outer corners of each group are rounded
10
33
  - **Hover zoom** — image scales inside its cell without changing layout
@@ -57,9 +80,46 @@ import { Gallery } from "@hoangyell/gallery";
57
80
  | `rows` | `number` | auto (~3 per row) | Number of visual rows |
58
81
  | `orientation` | `"landscape" \| "portrait"` | `"landscape"` | Item aspect ratio hint |
59
82
  | `scale` | `number` | `1` | Gallery width scale (0–1) |
60
- | `fit` | `ObjectFit` | `"cover"` | Default CSS object-fit |
83
+ | `fit` | `ObjectFit` | `"cover"` | Default CSS object-fit — see Fit modes below |
61
84
  | `class` | `string` | — | Extra wrapper class |
62
85
 
86
+ ## Fit modes
87
+
88
+ The `fit` prop controls **both** the image's `object-fit` **and** the
89
+ container's aspect ratio. Pick the right one for your content:
90
+
91
+ | Mode | What you get | When to use |
92
+ |---|---|---|
93
+ | `"cover"` (default) | Uniform 4:3 grid (1:1 on mobile). Images are cropped to fill. | Photo galleries — travel, products, faces. The Pinterest aesthetic. |
94
+ | `"contain"` | Container hugs each image's natural aspect ratio. No cropping. | Diagrams, charts, screenshots, comics, tall portraits. |
95
+
96
+ Set it at the gallery level:
97
+
98
+ ```mdx
99
+ <Gallery items={["/diagram.png"]} rows={1} fit="contain" />
100
+ ```
101
+
102
+ Or per-item (mix and match in the same gallery):
103
+
104
+ ```mdx
105
+ <Gallery
106
+ items={[
107
+ "/cover-photo.jpg",
108
+ { src: "/architecture-diagram.png", fit: "contain" },
109
+ ]}
110
+ />
111
+ ```
112
+
113
+ ## Dark mode
114
+
115
+ The component auto-themes via three mechanisms (last one wins):
116
+
117
+ 1. `prefers-color-scheme: dark` — OS preference (default).
118
+ 2. `<html class="dark">` or `<html data-theme="dark">` — Tailwind-style class toggle.
119
+ 3. `<html class="light">` or `<html data-theme="light">` — explicit light theme override.
120
+
121
+ This means it Just Works™ with manual theme toggles **and** OS preference.
122
+
63
123
  ## Customization
64
124
 
65
125
  Override CSS custom properties on `.hy-gallery`:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoangyell/gallery",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "Astro image gallery with lightbox, pyramid multi-row layout, and accessible controls.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  "photo-gallery"
24
24
  ],
25
25
  "author": "Hoang Yell <hoangyell@gmail.com> (https://hoangyell.com)",
26
- "homepage": "https://github.com/HoangYell/hoangyell-gallery#readme",
26
+ "homepage": "https://gallery.hoangyell.com",
27
27
  "repository": {
28
28
  "type": "git",
29
29
  "url": "https://github.com/HoangYell/hoangyell-gallery.git",
package/src/Gallery.astro CHANGED
@@ -100,6 +100,7 @@ if (resolvedRows <= 1 || galleryItems.length <= 1) {
100
100
  class={`hy-gallery ${className}`}
101
101
  data-hy-gallery
102
102
  data-orientation={orientation}
103
+ data-fit={fit}
103
104
  style={scale !== 1 ? `width: ${scale * 100}%; margin: 2rem auto;` : undefined}
104
105
  >
105
106
  {groupedItems.map((group, rowIdx) => {
@@ -124,6 +125,7 @@ if (resolvedRows <= 1 || galleryItems.length <= 1) {
124
125
  class={`hy-gallery-item ${cornerClasses}`}
125
126
  data-zoom-src={item.src}
126
127
  data-alt={item.alt}
128
+ data-fit={item.fit}
127
129
  aria-label={
128
130
  item.alt ? `View full size: ${item.alt}` : "View full size image"
129
131
  }
@@ -159,6 +161,7 @@ if (resolvedRows <= 1 || galleryItems.length <= 1) {
159
161
  --hy-gallery-control-bg: rgba(255, 255, 255, 0.95);
160
162
  }
161
163
 
164
+ /* OS-level dark preference. */
162
165
  @media (prefers-color-scheme: dark) {
163
166
  .hy-gallery {
164
167
  --hy-gallery-bg: #0f172a;
@@ -170,6 +173,28 @@ if (resolvedRows <= 1 || galleryItems.length <= 1) {
170
173
  }
171
174
  }
172
175
 
176
+ /* Explicit light theme on any ancestor wins over OS preference.
177
+ Supports Tailwind-style `.light` class and `[data-theme="light"]`. */
178
+ :where(.light, [data-theme="light"]) .hy-gallery {
179
+ --hy-gallery-bg: #f8fafc;
180
+ --hy-gallery-overlay-bg: rgba(255, 255, 255, 0.7);
181
+ --hy-gallery-accent: #2563eb;
182
+ --hy-gallery-border: #e2e8f0;
183
+ --hy-gallery-text: #334155;
184
+ --hy-gallery-control-bg: rgba(255, 255, 255, 0.95);
185
+ }
186
+
187
+ /* Explicit dark theme on any ancestor wins over OS preference.
188
+ Supports Tailwind-style `.dark` class and `[data-theme="dark"]`. */
189
+ :where(.dark, [data-theme="dark"]) .hy-gallery {
190
+ --hy-gallery-bg: #0f172a;
191
+ --hy-gallery-overlay-bg: rgba(2, 6, 23, 0.8);
192
+ --hy-gallery-accent: #60a5fa;
193
+ --hy-gallery-border: #334155;
194
+ --hy-gallery-text: #e2e8f0;
195
+ --hy-gallery-control-bg: rgba(30, 41, 59, 0.95);
196
+ }
197
+
173
198
  .hy-gallery {
174
199
  display: flex;
175
200
  flex-direction: column;
@@ -240,6 +265,16 @@ if (resolvedRows <= 1 || galleryItems.length <= 1) {
240
265
  }
241
266
  }
242
267
 
268
+ /* fit="contain" — show the whole image at its natural aspect ratio.
269
+ Drops the forced 4:3 / 1:1 container so diagrams, charts, screenshots,
270
+ and tall portraits render fully without cropping or letterboxing.
271
+ Applied either at the wrapper (global) or per-item via data-fit. */
272
+ .hy-gallery[data-fit="contain"] .hy-gallery-item,
273
+ .hy-gallery .hy-gallery-item[data-fit="contain"] {
274
+ aspect-ratio: auto;
275
+ background: transparent;
276
+ }
277
+
243
278
  .hy-gallery-img {
244
279
  position: absolute;
245
280
  inset: 0;
@@ -256,6 +291,16 @@ if (resolvedRows <= 1 || galleryItems.length <= 1) {
256
291
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
257
292
  }
258
293
 
294
+ /* In contain mode the image is the primary content — let it drive height
295
+ instead of being absolutely positioned inside a fixed-aspect box. */
296
+ .hy-gallery[data-fit="contain"] .hy-gallery-img,
297
+ .hy-gallery .hy-gallery-item[data-fit="contain"] .hy-gallery-img {
298
+ position: static;
299
+ width: 100%;
300
+ height: auto;
301
+ inset: auto;
302
+ }
303
+
259
304
  .hy-gallery-item:hover .hy-gallery-img,
260
305
  .hy-gallery-item:focus-visible .hy-gallery-img {
261
306
  will-change: transform;