{"_id":"@archpublicwebsite/gallery","_rev":"2-f2bdfa4c3e07cef07b20ebaad16218a0","name":"@archpublicwebsite/gallery","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@archpublicwebsite/gallery","version":"1.0.0","keywords":["vue","vue3","gallery","lightbox","image-gallery","swiper"],"author":{"name":"Archipelago International"},"license":"MIT","_id":"@archpublicwebsite/gallery@1.0.0","maintainers":[{"name":"archpublicwebsite","email":"archpublicwebsite@gmail.com"}],"homepage":"https://github.com/ArchipelagoInternational/archi-ui#readme","bugs":{"url":"https://github.com/ArchipelagoInternational/archi-ui/issues"},"dist":{"shasum":"cef90bc7375921516be6b81abd26840f615209ca","tarball":"https://registry.npmjs.org/@archpublicwebsite/gallery/-/gallery-1.0.0.tgz","fileCount":10,"integrity":"sha512-qmA2V5keRuEZvqGlrovYkoklimWCoaMJYL4fX53W2KOo6zeNEpO01c69G2ow+REwrt7Q4Z12VVgbp++whQXFhA==","signatures":[{"sig":"MEYCIQDEIa4VJSWmpHjqCkuEG4U7MeeY2iNPP2Zo8NqZEFlEXQIhAPw+yD1SOceO/aurDyvyRMEcaQXT2BWLMwM79ZTmazyn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":462823},"main":"./dist/gallery.umd.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/gallery.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/gallery.js","require":"./dist/gallery.umd.cjs"},"./style.css":"./dist/style.css"},"gitHead":"dfa2045f981510d6403e038a38a145af6336c222","private":false,"scripts":{"dev":"vite build --watch","lint":"eslint ./src --ext .ts,.vue,.js","build":"rm -rf dist && vite build && tsc --emitDeclarationOnly --declaration --project tsconfig.json && rm -f dist/Gallery.stories.d.ts","lint:fix":"eslint ./src --ext .ts,.vue,.js --fix","typecheck":"vue-tsc --noEmit","version:major":"node ../../scripts/bump-version.mjs major","version:minor":"node ../../scripts/bump-version.mjs minor","version:patch":"node ../../scripts/bump-version.mjs patch","prepublishOnly":"pnpm build"},"_npmUser":{"name":"archpublicwebsite","email":"archpublicwebsite@gmail.com"},"repository":{"url":"git+https://github.com/ArchipelagoInternational/archi-ui.git","type":"git","directory":"packages/gallery"},"_npmVersion":"10.9.3","description":"Gallery lightbox component for Archipelago hotel websites","directories":{},"_nodeVersion":"22.20.0","dependencies":{"swiper":"^11.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"vue":"^3.5.22"},"_npmOperationalInternal":{"tmp":"tmp/gallery_1.0.0_1777950145816_0.8910708664561666","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@archpublicwebsite/gallery","type":"module","version":"1.0.1","private":false,"description":"Gallery lightbox component for Archipelago hotel websites","author":{"name":"Archipelago International"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ArchipelagoInternational/archi-ui.git","directory":"packages/gallery"},"keywords":["vue","vue3","gallery","lightbox","image-gallery","swiper"],"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/gallery.js","require":"./dist/gallery.umd.cjs"},"./style.css":"./dist/style.css"},"main":"./dist/gallery.umd.cjs","module":"./dist/gallery.js","types":"./dist/index.d.ts","scripts":{"dev":"vite build --watch","build":"rm -rf dist && vite build && tsc --emitDeclarationOnly --declaration --project tsconfig.json && rm -f dist/Gallery.stories.d.ts","lint":"eslint ./src --ext .ts,.vue,.js","lint:fix":"eslint ./src --ext .ts,.vue,.js --fix","typecheck":"vue-tsc --noEmit","prepublishOnly":"pnpm build","version:patch":"node ../../scripts/bump-version.mjs patch","version:minor":"node ../../scripts/bump-version.mjs minor","version:major":"node ../../scripts/bump-version.mjs major"},"peerDependencies":{"vue":"^3.5.22"},"dependencies":{"swiper":"^11.2.1"},"publishConfig":{"access":"public"},"_id":"@archpublicwebsite/gallery@1.0.1","gitHead":"e28b56eb86d5398f3c869f6da892191813aba51e","bugs":{"url":"https://github.com/ArchipelagoInternational/archi-ui/issues"},"homepage":"https://github.com/ArchipelagoInternational/archi-ui#readme","_nodeVersion":"22.20.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-5rzWrIESqQmjz+VXJQJgqglRO/aknpbcIpV4mHizgSVV1wK8t35t+uEt5zWW/2A+vPdxe3T7uzLGhfcZz5+RLw==","shasum":"d71d4f32214fba4d840db3a2f45f307bb598577d","tarball":"https://registry.npmjs.org/@archpublicwebsite/gallery/-/gallery-1.0.1.tgz","fileCount":10,"unpackedSize":464483,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC7NzloV9y2b64gt8FmDIXDtB5X8cI6DPM+RgwsoFjuVgIhAM8r5ygS5wBeV/T/3sLc/4iyqCIPLJeKjxuiOETIC8Gk"}]},"_npmUser":{"name":"archpublicwebsite","email":"archpublicwebsite@gmail.com"},"directories":{},"maintainers":[{"name":"archpublicwebsite","email":"archpublicwebsite@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/gallery_1.0.1_1777951505657_0.3010924803266779"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-05T03:02:25.717Z","modified":"2026-05-05T03:25:05.948Z","1.0.0":"2026-05-05T03:02:25.954Z","1.0.1":"2026-05-05T03:25:05.830Z"},"bugs":{"url":"https://github.com/ArchipelagoInternational/archi-ui/issues"},"author":{"name":"Archipelago International"},"license":"MIT","homepage":"https://github.com/ArchipelagoInternational/archi-ui#readme","keywords":["vue","vue3","gallery","lightbox","image-gallery","swiper"],"repository":{"type":"git","url":"git+https://github.com/ArchipelagoInternational/archi-ui.git","directory":"packages/gallery"},"description":"Gallery lightbox component for Archipelago hotel websites","maintainers":[{"name":"archpublicwebsite","email":"archpublicwebsite@gmail.com"}],"readme":"# @archpublicwebsite/gallery\n\nFull-screen image lightbox gallery component for Vue 3 — works in plain Vue, Nuxt, Vuetify, and any other Vue-based framework.\n\n## Features\n\n- **Fully typed** — strict TypeScript interfaces for all props, emits, and composable return values\n- **FLIP animations** — smooth open/close transitions matched to the source image position\n- **Swiper-powered** — swipe, keyboard navigation, fade/slide effect, accessibility module\n- **Zoom** — click or pinch to zoom, configurable max ratio\n- **Thumbnail strip** — responsive breakpoints, active indicator\n- **Framework-agnostic styling** — Tailwind compiled to plain CSS at build time; no Tailwind required by consumers\n- **SSR compatible** — Swiper mounted only after `onMounted`; safe for Nuxt\n- **Accessible** — ARIA labels, keyboard navigation (`←` `→`), `prefers-reduced-motion` respected\n- **Zero peer deps besides Vue** — Swiper is bundled; nothing else to install\n\n## Installation\n\n```bash\nnpm install @archpublicwebsite/gallery\n# or\npnpm add @archpublicwebsite/gallery\n# or\nyarn add @archpublicwebsite/gallery\n```\n\n## Quick Start\n\n```vue\n<script setup lang=\"ts\">\nimport type { GalleryImageInput } from \"@archpublicwebsite/gallery\";\n\nimport { ModalGallery, useGallery } from \"@archpublicwebsite/gallery\";\nimport '@archpublicwebsite/gallery/style.css';\n\nconst images: GalleryImageInput[] = [\n  { id: '1', url: 'https://...', alt: 'Pool', caption: 'Infinity Pool' },\n  { id: '2', url: 'https://...', alt: 'Lobby', caption: 'Grand Lobby' },\n]\n\nconst { isOpen, currentIndex, galleryContent, openGallery, closeGallery }\n  = useGallery(images)\n</script>\n\n<template>\n  <!-- trigger — can be a grid, a single button, anything -->\n  <img\n    v-for=\"(item, i) in galleryContent.items\"\n    :key=\"item.id\"\n    :src=\"item.thumbnail || item.url\"\n    :alt=\"item.alt\"\n    @click=\"openGallery(i)\"\n  />\n\n  <!-- lightbox -->\n  <ModalGallery\n    v-if=\"isOpen\"\n    :content=\"galleryContent\"\n    :current-index=\"currentIndex\"\n    style=\"position: fixed; inset: 0; z-index: 9999\"\n    @close=\"closeGallery\"\n  />\n</template>\n```\n\n## Framework Examples\n\n### Nuxt 3\n\nNo plugin needed — import directly in the component.\n\n```vue\n<script setup lang=\"ts\">\nimport { ModalGallery, useGallery } from '@archpublicwebsite/gallery';\nimport '@archpublicwebsite/gallery/style.css';\n// ...same as quick start\n</script>\n```\n\n### Vuetify (inside `v-dialog`)\n\n```vue\n<template>\n  <v-dialog v-model=\"isOpen\" fullscreen>\n    <ModalGallery\n      :content=\"galleryContent\"\n      :current-index=\"currentIndex\"\n      @close=\"closeGallery\"\n    />\n  </v-dialog>\n</template>\n```\n\n### React (via any Vue-in-React bridge)\n\nThe component is a standard Vue 3 SFC and follows the same composition pattern as `@archpublicwebsite/modal` and `@archpublicwebsite/rangepicker`.\n\n---\n\n## `useGallery(images)` Composable\n\nThe composable is the recommended way to manage gallery state. It accepts a **static or reactive array** of `GalleryImageInput` objects and returns everything needed to wire up `<ModalGallery>`.\n\n### Input type — `GalleryImageInput`\n\n| Field           | Type      | Required | Description                                  |\n| --------------- | --------- | -------- | -------------------------------------------- |\n| `id`            | `string`  | ✅       | Unique identifier                            |\n| `url`           | `string`  | ✅       | Full-resolution image URL                    |\n| `thumbnail`     | `string`  | —        | Thumbnail URL; derived from `url` if omitted |\n| `alt`           | `string`  | —        | Accessible alt text; falls back to `title`   |\n| `caption`       | `string`  | —        | Short label shown in the overlay             |\n| `title`         | `string`  | —        | Secondary label; used as alt fallback        |\n| `description`   | `string`  | —        | Longer text shown below caption              |\n| `[key: string]` | `unknown` | —        | Extra API fields are silently ignored        |\n\n```ts\n// TypeScript enforces id + url at compile time\nconst images: GalleryImageInput[] = [\n  { id: '1', url: 'https://...', alt: 'Pool' }, // ✅\n  { url: 'https://...' }, // ✗ missing id\n  { id: 1, url: \"https://...\" }, // ✗ id must be string\n]\n```\n\n### Return value — `UseGalleryReturn`\n\n| Property              | Type                          | Description                           |\n| --------------------- | ----------------------------- | ------------------------------------- |\n| `isOpen`              | `Ref<boolean>`                | Whether the lightbox is visible       |\n| `currentIndex`        | `Ref<number>`                 | Active slide index                    |\n| `galleryContent`      | `ComputedRef<GalleryContent>` | Structured data to pass to `:content` |\n| `openGallery(index?)` | `(index?: number) => void`    | Open at a given index (default: 0)    |\n| `closeGallery()`      | `() => void`                  | Close the lightbox                    |\n\nReactive images example (fetched from an API):\n\n```ts\nconst { data: rooms } = await useFetch('/api/rooms');\n\nconst { isOpen, galleryContent, openGallery, closeGallery } = useGallery(\n  () =>\n    rooms.value?.map(r => ({ id: r.id, url: r.image, alt: r.name })) ?? [],\n)\n```\n\n---\n\n## `<ModalGallery>` Props\n\n| Prop              | Type              | Default   | Description                                       |\n| ----------------- | ----------------- | --------- | ------------------------------------------------- |\n| `content`         | `GalleryContent`  | required  | Gallery data — use `useGallery()` to produce this |\n| `currentIndex`    | `number`          | `0`       | Active slide on mount                             |\n| `lightboxOptions` | `LightboxOptions` | see below | Behaviour overrides                               |\n\n### `LightboxOptions`\n\n| Option           | Type                             | Default    | Description                           |\n| ---------------- | -------------------------------- | ---------- | ------------------------------------- |\n| `showThumbnails` | `boolean`                        | `true`     | Show thumbnail strip at the bottom    |\n| `showNavigation` | `boolean`                        | `true`     | Show prev/next arrows                 |\n| `showPagination` | `boolean`                        | `true`     | Show fraction counter (e.g. \"3 / 12\") |\n| `showCaption`    | `boolean`                        | `true`     | Show caption and description overlay  |\n| `enableZoom`     | `boolean`                        | `true`     | Enable click/pinch to zoom            |\n| `thumbnailSize`  | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Thumbnail strip size                  |\n| `effect`         | `'slide' \\| 'fade'`              | `'slide'`  | Slide transition effect               |\n| `maxZoom`        | `number`                         | `3`        | Maximum zoom ratio                    |\n\nAll options have TypeScript autocomplete and hover documentation.\n\n```ts\n// ✗ TypeScript catches this at compile time:\n<ModalGallery :lightbox-options=\"{ thumbnailSize: 'huge' }\" />\n//                                                  ^^^^^^ not assignable to ThumbnailSize\n```\n\n---\n\n## Events\n\n| Event          | Payload                              | Description                                                            |\n| -------------- | ------------------------------------ | ---------------------------------------------------------------------- |\n| `close`        | —                                    | Fired when the user closes the gallery (close button or animation end) |\n| `image-change` | `(index: number, item: GalleryItem)` | Fired when the active slide changes                                    |\n\n```vue\n<ModalGallery\n  ...\n  @close=\"closeGallery\"\n  @image-change=\"\n    (index, item) => analytics.track('gallery_view', { id: item.id })\n  \"\n/>\n```\n\n---\n\n## Animations\n\nThe gallery uses **FLIP animations** to match the position and size of the source image on open, creating a natural expand-from-thumbnail effect. On close, a ghost image animates back to the original position.\n\n- Detects the source `<img>` element in the DOM by matching the URL\n- Falls back to a simple fade if the source cannot be found\n- Respects `prefers-reduced-motion`: uses a short opacity fade instead\n\n---\n\n## Auto-hiding Chrome\n\nWhen `content.items` has only **one** image, navigation arrows, pagination, and the thumbnail strip are automatically hidden regardless of `lightboxOptions`. No extra config needed.\n\n---\n\n## Styling & Theming\n\nThe package ships a single compiled CSS file — import it once at the top of your app or in the component:\n\n```ts\nimport '@archpublicwebsite/gallery/style.css';\n```\n\nThe gallery uses scoped class names prefixed with `arch-gallery-` to avoid collisions with Vuetify, Bootstrap, or any other UI framework.\n\n---\n\n## Publishing a new version\n\n```bash\ncd packages/gallery\n\npnpm version:patch   # 1.0.0 → 1.0.1\npnpm version:minor   # 1.0.0 → 1.1.0\npnpm version:major   # 1.0.0 → 2.0.0\n\nnpm publish\n```\n\n`prepublishOnly` runs `pnpm build` automatically before publishing.\n","readmeFilename":"README.md"}