Full Code of dimsemenov/PhotoSwipe for AI

master cd41cb587a46 cached
159 files
1000.8 KB
272.9k tokens
1171 symbols
1 requests
Download .txt
Showing preview only (1,053K chars total). Download the full file or copy to clipboard to get everything.
Repository: dimsemenov/PhotoSwipe
Branch: master
Commit: cd41cb587a46
Files: 159
Total size: 1000.8 KB

Directory structure:
gitextract_0u2e7_9t/

├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── build.yml
├── .gitignore
├── LICENSE
├── README.md
├── build/
│   ├── config-builder.js
│   ├── rollup.config.js
│   └── rollup.config.watch.js
├── demo-docs-website/
│   ├── .gitignore
│   ├── babel.config.js
│   ├── docusaurus.config.js
│   ├── package.json
│   ├── repo-data.json
│   ├── sidebars.js
│   ├── src/
│   │   ├── components/
│   │   │   ├── HomepageFeatures/
│   │   │   │   ├── index.js
│   │   │   │   └── styles.module.css
│   │   │   └── PswpCodePreview/
│   │   │       ├── demo-images.js
│   │   │       ├── gallery-templates/
│   │   │       │   ├── basic--badges.js
│   │   │       │   ├── basic--cropped.js
│   │   │       │   ├── basic.js
│   │   │       │   ├── caption.js
│   │   │       │   ├── content-types.js
│   │   │       │   ├── custom-html-markup-data-source.js
│   │   │       │   ├── getting-started.js
│   │   │       │   └── srcset-test.js
│   │   │       └── index.js
│   │   ├── css/
│   │   │   ├── custom.css
│   │   │   ├── docs-page.css
│   │   │   ├── example-code-block.css
│   │   │   ├── header.css
│   │   │   ├── home.css
│   │   │   ├── scrollbar.css
│   │   │   └── sidebar-menu.css
│   │   ├── pages/
│   │   │   ├── _index-deep-zoom-demo.js
│   │   │   ├── _index-gallery-header.js
│   │   │   ├── index.js
│   │   │   └── index.module.css
│   │   └── theme/
│   │       ├── CodeBlock/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocItem/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocItemFooter/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocPage/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocSidebar/
│   │       │   ├── index.js
│   │       │   ├── is-same-path.ts
│   │       │   └── styles.module.css
│   │       ├── EditThisPage/
│   │       │   └── index.js
│   │       ├── Footer/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── Logo/
│   │       │   └── index.js
│   │       ├── MDXComponents/
│   │       │   ├── index.js
│   │       │   └── styles.css
│   │       └── Navbar/
│   │           ├── github-stars.js
│   │           ├── index.js
│   │           └── styles.module.css
│   └── static/
│       ├── .nojekyll
│       └── photoswipe/
│           ├── photoswipe-lightbox.esm.js
│           ├── photoswipe.css
│           └── photoswipe.esm.js
├── dist/
│   ├── photoswipe-lightbox.esm.js
│   ├── photoswipe.css
│   ├── photoswipe.esm.js
│   ├── types/
│   │   ├── core/
│   │   │   ├── base.d.ts
│   │   │   └── eventable.d.ts
│   │   ├── gestures/
│   │   │   ├── drag-handler.d.ts
│   │   │   ├── gestures.d.ts
│   │   │   ├── tap-handler.d.ts
│   │   │   └── zoom-handler.d.ts
│   │   ├── keyboard.d.ts
│   │   ├── lightbox/
│   │   │   └── lightbox.d.ts
│   │   ├── main-scroll.d.ts
│   │   ├── opener.d.ts
│   │   ├── photoswipe.d.ts
│   │   ├── scroll-wheel.d.ts
│   │   ├── slide/
│   │   │   ├── content.d.ts
│   │   │   ├── get-thumb-bounds.d.ts
│   │   │   ├── loader.d.ts
│   │   │   ├── pan-bounds.d.ts
│   │   │   ├── placeholder.d.ts
│   │   │   ├── slide.d.ts
│   │   │   └── zoom-level.d.ts
│   │   ├── types.d.ts
│   │   ├── ui/
│   │   │   ├── button-arrow.d.ts
│   │   │   ├── button-close.d.ts
│   │   │   ├── button-zoom.d.ts
│   │   │   ├── counter-indicator.d.ts
│   │   │   ├── loading-indicator.d.ts
│   │   │   ├── ui-element.d.ts
│   │   │   └── ui.d.ts
│   │   └── util/
│   │       ├── animations.d.ts
│   │       ├── css-animation.d.ts
│   │       ├── dom-events.d.ts
│   │       ├── spring-animation.d.ts
│   │       ├── spring-easer.d.ts
│   │       ├── util.d.ts
│   │       └── viewport-size.d.ts
│   └── umd/
│       └── README.md
├── docs/
│   ├── adding-ui-elements.md
│   ├── adjusting-zoom-level.md
│   ├── caption.md
│   ├── click-and-tap-actions.md
│   ├── custom-content.md
│   ├── data-sources.md
│   ├── events.md
│   ├── filters.md
│   ├── getting-started.md
│   ├── methods.md
│   ├── native-fullscreen-on-open.md
│   ├── opening-or-closing-transition.md
│   ├── options.md
│   ├── properties.md
│   ├── react-image-gallery.md
│   ├── styling.md
│   ├── svelte-image-gallery.md
│   └── vue-image-gallery.md
├── global.d.ts
├── package.json
├── src/
│   ├── js/
│   │   ├── core/
│   │   │   ├── base.js
│   │   │   └── eventable.js
│   │   ├── gestures/
│   │   │   ├── drag-handler.js
│   │   │   ├── gestures.js
│   │   │   ├── tap-handler.js
│   │   │   └── zoom-handler.js
│   │   ├── keyboard.js
│   │   ├── lightbox/
│   │   │   └── lightbox.js
│   │   ├── main-scroll.js
│   │   ├── opener.js
│   │   ├── photoswipe.js
│   │   ├── scroll-wheel.js
│   │   ├── slide/
│   │   │   ├── content.js
│   │   │   ├── get-thumb-bounds.js
│   │   │   ├── loader.js
│   │   │   ├── pan-bounds.js
│   │   │   ├── placeholder.js
│   │   │   ├── slide.js
│   │   │   └── zoom-level.js
│   │   ├── types.ts
│   │   ├── ui/
│   │   │   ├── button-arrow.js
│   │   │   ├── button-close.js
│   │   │   ├── button-zoom.js
│   │   │   ├── counter-indicator.js
│   │   │   ├── loading-indicator.js
│   │   │   ├── ui-element.js
│   │   │   └── ui.js
│   │   └── util/
│   │       ├── animations.js
│   │       ├── css-animation.js
│   │       ├── dom-events.js
│   │       ├── spring-animation.js
│   │       ├── spring-easer.js
│   │       ├── util.js
│   │       └── viewport-size.js
│   └── photoswipe.css
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
  "plugins": [
    "@babel/plugin-transform-optional-chaining",
    "@babel/plugin-transform-nullish-coalescing-operator"
  ]
}


================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

================================================
FILE: .eslintignore
================================================
node_modules
!.*.js
.eslintrc.js
*.d.ts
*.ts


================================================
FILE: .eslintrc.json
================================================
{
    "env": {
        "browser": true,
        "es6": true
    },
    "extends": "airbnb-base",
    "parser": "@babel/eslint-parser",
    "parserOptions": {
        "sourceType": "module",
        "requireConfigFile": false,
        "babelOptions": {
          "plugins": ["@babel/plugin-syntax-class-properties"]
        }
    },
    "overrides": [
        {
            "files": [
                "website/static/es6/**/*.js"
            ]
        }
    ],
    "rules": {
        "max-len": ["error", { "code": 100, "comments": 140 }],
        "comma-dangle": "off",
        "no-param-reassign": 0,
        "import/extensions": 0,
        "no-underscore-dangle": 0,
        "consistent-return": 0,
        "no-trailing-spaces": "warn",
        "spaced-comment": 0,
        "no-plusplus": 0,
        "prefer-template": 0,
        "object-curly-newline": 0,
        "arrow-body-style": 0,
        "import/prefer-default-export": 0,
        "no-else-return": 0,
        "no-lonely-if": 0,
        "default-case": 0,
        "linebreak-style": 0,
        "class-methods-use-this": 0,
        "max-classes-per-file": 0,
        "arrow-parens": 0,
        "no-multiple-empty-lines": 0,
        "no-mixed-operators": 0,
        "function-paren-newline": 0
    }
}


================================================
FILE: .github/FUNDING.yml
================================================
open_collective: photoswipe

================================================
FILE: .github/workflows/build.yml
================================================
name: PhotoSwipe Jobs

on: [workflow_dispatch]

jobs:
  build:
    name: Publish docs
    runs-on: ubuntu-latest
    steps:
      - name: "checkout repository"
        uses: actions/checkout@v2

      - name: "setup node"
        uses: actions/setup-node@v2
        with:
          node-version: 16

      - name: "github api fetch (for stars count)"
        working-directory: demo-docs-website
        run: curl -s https://api.github.com/repos/dimsemenov/photoswipe -o ./repo-data.json 

      - name: "npm install & build docs"
        working-directory: demo-docs-website
        run: |
          npm install
          npm run build

      - name: "install ssh key"
        uses: shimataro/ssh-key-action@v2
        with:
          key: ${{ secrets.SSH_PRIVATE_KEY }} 
          known_hosts: ${{ secrets.KNOWN_HOSTS }}

      - name: "deploy with rsync"
        run: rsync -avz ./demo-docs-website/build/ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.RSYNC_DIR }}

================================================
FILE: .gitignore
================================================
node_modules/
release/
Gemfile.lock
test/dest
*.gem
pkg/
*.swp
*~
_site/
.bundle/
website/static/photoswipe/
.DS_Store
bbin/
sftp-config*
_site
.htaccess
private-*
__article/
_site/*
website/build/
node_modules
_production
all.min.css
aws-keys.json
*.sublime-project
*.sublime-workspace
website/dist/
*.idea
/.idea
.vscode
.node-version
.sass-cache/


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014-2022 Dmitry Semenov, https://dimsemenov.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

================================================
FILE: README.md
================================================
**FEEDBACK NEEDED** I am developing the new version - PhotoSwipe v6, please [read about upcoming changes and leave feedback](https://github.com/dimsemenov/PhotoSwipe/discussions/2170).



PhotoSwipe v5 — JavaScript image gallery and lightbox

**[Demo](https://photoswipe.com)** | **[Documentation](https://photoswipe.com/getting-started/)**

[![Sponsor via OpenCollective](https://img.shields.io/opencollective/all/photoswipe?label=Sponsor%20via%20OpenCollective)](https://opencollective.com/photoswipe)
[![Follow on Twitter](https://img.shields.io/twitter/follow/photoswipe?style=social)](https://twitter.com/intent/user?screen_name=photoswipe)


### Repo structure

- `dist/` - main JS and CSS
- `src/` - source JS and CSS.
  - `src/js/photoswipe.js` - entry for PhotoSwipe Core.
  - `src/js/lightbox/lightbox.js` - entry for PhotoSwipe Lightbox.
- `docs/` - documentation markdown files.
- `demo-docs-website/` - website with documentation, demos and manual tests.
- `build/` - rollup build config.

To build JS and CSS in `dist/` directory, run `npm run build`.

To run the demo website and automatically rebuild files during development, run `npm install` in `demo-docs-website/` and `npm run watch` in the root directory.

### Older versions

Documentation for the old version (v4) can be found [here](https://photoswipe.com/v4-docs/getting-started.html) and [the code for 4.1.3 is here](https://github.com/dimsemenov/PhotoSwipe/tree/v4.1.3).

[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://savelife.in.ua/en/)

---

This project is tested with [BrowserStack](https://www.browserstack.com/).


================================================
FILE: build/config-builder.js
================================================
// eslint-disable-next-line import/no-extraneous-dependencies
import { terser } from 'rollup-plugin-terser';
import { babel } from '@rollup/plugin-babel';

import pkg from '../package.json';

const year = new Date().getFullYear();

function getBanner(name) {
  return `/*!
  * ${name} ${pkg.version} - https://photoswipe.com
  * (c) ${year} Dmytro Semenov
  */`;
}

function getMinifyPlugin() {
  return terser({
    output: {
      comments: /^\**!/i,
    },
    mangle: {
      properties: {
        // mangle properties and func names that start with underscore
        regex: /^_/,
      }
    }
  });
}

function getBabelPlugin() {
  return babel({
    exclude: 'node_modules/**'
  })
}

const baseOutputDir = 'demo-docs-website/static/photoswipe/';
export const lightboxJS = {
  input: 'src/js/lightbox/lightbox.js',
  output: {
    banner: getBanner('PhotoSwipe Lightbox'),
    file: baseOutputDir + 'photoswipe-lightbox.esm.js',
    format: 'esm',
    sourcemap: true
  },
  plugins: [getBabelPlugin()]
};

export const coreJS = {
  input: 'src/js/photoswipe.js',
  output: {
    banner: getBanner('PhotoSwipe'),
    file: baseOutputDir + 'photoswipe.esm.js',
    format: 'esm',
    sourcemap: true
  },
  plugins: [getBabelPlugin()]
};

export const minLightboxJS = {
  input: 'src/js/lightbox/lightbox.js',
  output: {
    banner: getBanner('PhotoSwipe Lightbox'),
    file: baseOutputDir + 'photoswipe-lightbox.esm.min.js',
    format: 'esm'
  },
  plugins: [getBabelPlugin(), getMinifyPlugin()]
};

export const minCoreJS = {
  input: 'src/js/photoswipe.js',
  output: {
    banner: getBanner('PhotoSwipe'),
    file: baseOutputDir + 'photoswipe.esm.min.js',
    format: 'esm',
  },
  plugins: [getBabelPlugin(), getMinifyPlugin()]
};

// UMD config
const umdBaseOutputDir = 'demo-docs-website/static/photoswipe/umd/';
export const umdMinLightboxJS = {
  input: 'src/js/lightbox/lightbox.js',
  output: {
    name: 'PhotoSwipeLightbox',
    banner: getBanner('PhotoSwipe Lightbox'),
    file: umdBaseOutputDir + 'photoswipe-lightbox.umd.min.js',
    format: 'umd'
  },
  plugins: [getBabelPlugin(), getMinifyPlugin()]
};

export const umdMinCoreJS = {
  input: 'src/js/photoswipe.js',
  output: {
    name: 'PhotoSwipe',
    banner: getBanner('PhotoSwipe'),
    file: umdBaseOutputDir + 'photoswipe.umd.min.js',
    format: 'umd',
  },
  plugins: [getBabelPlugin(), getMinifyPlugin()]
};


================================================
FILE: build/rollup.config.js
================================================
import { 
  lightboxJS,
  coreJS,
  minLightboxJS,
  minCoreJS,
  umdMinLightboxJS,
  umdMinCoreJS
} from './config-builder';

export default [lightboxJS, coreJS, minLightboxJS, minCoreJS, umdMinLightboxJS, umdMinCoreJS];


================================================
FILE: build/rollup.config.watch.js
================================================
import { lightboxJS, coreJS } from './config-builder';

export default [lightboxJS, coreJS];


================================================
FILE: demo-docs-website/.gitignore
================================================
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: demo-docs-website/babel.config.js
================================================
module.exports = {
  presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};


================================================
FILE: demo-docs-website/docusaurus.config.js
================================================
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const path = require('path');
const lightCodeTheme = require('prism-react-renderer/themes/github');

/** @type {import('@docusaurus/types').Config} */
const config = {
  title: 'PhotoSwipe',
  tagline: '',
  url: 'https://photoswipe.com',
  baseUrl: '/',
  onBrokenLinks: 'throw',
  onBrokenMarkdownLinks: 'warn',
  favicon: 'img/favicon-16x16.png',
  organizationName: 'dimsemenov', // Usually your GitHub org/user name.
  projectName: 'photoswipe', // Usually your repo name.


  // scripts: [
  //   'https://docusaurus.io/slash.js',
  //   {
  //     src:
  //       'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js',
  //     async: true,
  //   },
  // ],
  stylesheets: [
    {
      href: '/photoswipe/photoswipe.css',
      type: 'text/css',
    },
  ],

  plugins: [
    [
      '@docusaurus/plugin-google-gtag',
      {
        trackingID: 'G-57MLE6HBT9',
      },
    ],
  ],
  presets: [
    [
      'classic',
      /** @type {import('@docusaurus/preset-classic').Options} */
      ({
        docs: {
          path: '../docs/',
          routeBasePath: '/',
          sidebarPath: require.resolve('./sidebars.js'),
          // Please change this to your repo.
          editUrl: 'https://github.com/dimsemenov/PhotoSwipe/tree/master/docs',
          breadcrumbs: false
        },
        theme: {
          customCss: require.resolve('./src/css/custom.css'),
        },
      }),
    ],
  ],

  themeConfig:
    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    ({
      colorMode: {
        defaultMode: 'light',
        disableSwitch: true,
        respectPrefersColorScheme: false,
      },
      navbar: {
        title: 'PhotoSwipe',
        
        // logo: {
        //   alt: 'My Site Logo',
        //   src: 'img/logo.svg',
        // },
        items: [
          {
            type: 'doc',
            docId: 'getting-started',
            position: 'left',
            label: 'Docs',
          }
        ],
      },
      footer: {
        style: 'dark',
        links: [
          {

          },
          {
            title: 'Community',
            items: [
              {
                label: 'Twitter',
                href: 'https://twitter.com/photoswipe',
              },
            ],
          },
          {
            title: 'More',
            items: [
              {
                label: 'Blog',
                to: '/blog',
              },
              {
                label: 'GitHub',
                href: 'https://github.com/dimsemenov/photoswipe',
              },
            ],
          },
        ],
        copyright: 'Made in Ukraine<span class="ukraine-flag"></span> by <a href="https://twitter.com/dimsemenov">Dmytro Semenov</a>',
      },
      prism: {
        theme: lightCodeTheme,
      },

    }),
};

module.exports = config;


================================================
FILE: demo-docs-website/package.json
================================================
{
  "name": "demo-docs-website",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "docusaurus": "docusaurus",
    "start": "docusaurus start",
    "build": "docusaurus build",
    "build-and-analyze": "docusaurus build --bundle-analyzer",
    "swizzle": "docusaurus swizzle",
    "deploy": "docusaurus deploy",
    "clear": "docusaurus clear",
    "serve": "docusaurus serve",
    "write-translations": "docusaurus write-translations",
    "write-heading-ids": "docusaurus write-heading-ids"
  },
  "dependencies": {
    "@docsearch/react": "^3.0.0",
    "@docusaurus/core": "2.0.0-beta.17",
    "@docusaurus/plugin-google-gtag": "^2.0.0-beta.17",
    "@docusaurus/preset-classic": "2.0.0-beta.17",
    "@docusaurus/theme-live-codeblock": "^2.0.0-beta.17",
    "@mdx-js/react": "^1.6.22",
    "clsx": "^1.1.1",
    "photoswipe-deep-zoom-plugin": "^1.1.1",
    "photoswipe-dynamic-caption-plugin": "^1.1.1",
    "prism-react-renderer": "^1.2.1",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "browserslist": {
    "production": [
      ">0.5%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}


================================================
FILE: demo-docs-website/repo-data.json
================================================
{
  "id": 1580851,
  "name": "PhotoSwipe",
  "full_name": "dimsemenov/PhotoSwipe",
  "private": false,
  "owner": {
    "login": "dimsemenov",
    "id": 1061115,
    "avatar_url": "https://avatars.githubusercontent.com/u/1061115?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/dimsemenov",
    "html_url": "https://github.com/dimsemenov",
    "followers_url": "https://api.github.com/users/dimsemenov/followers",
    "following_url": "https://api.github.com/users/dimsemenov/following{/other_user}",
    "gists_url": "https://api.github.com/users/dimsemenov/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/dimsemenov/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/dimsemenov/subscriptions",
    "organizations_url": "https://api.github.com/users/dimsemenov/orgs",
    "repos_url": "https://api.github.com/users/dimsemenov/repos",
    "events_url": "https://api.github.com/users/dimsemenov/events{/privacy}",
    "received_events_url": "https://api.github.com/users/dimsemenov/received_events",
    "type": "User",
    "site_admin": false
  },
  "html_url": "https://github.com/dimsemenov/PhotoSwipe",
  "description": "JavaScript image gallery for mobile and desktop, modular, framework independent",
  "fork": false,
  "url": "https://api.github.com/repos/dimsemenov/PhotoSwipe",
  "forks_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/forks",
  "keys_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/keys{/key_id}",
  "collaborators_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/collaborators{/collaborator}",
  "teams_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/teams",
  "hooks_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/hooks",
  "issue_events_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/issues/events{/number}",
  "events_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/events",
  "assignees_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/assignees{/user}",
  "branches_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/branches{/branch}",
  "tags_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/tags",
  "blobs_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/git/blobs{/sha}",
  "git_tags_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/git/tags{/sha}",
  "git_refs_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/git/refs{/sha}",
  "trees_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/git/trees{/sha}",
  "statuses_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/statuses/{sha}",
  "languages_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/languages",
  "stargazers_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/stargazers",
  "contributors_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/contributors",
  "subscribers_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/subscribers",
  "subscription_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/subscription",
  "commits_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/commits{/sha}",
  "git_commits_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/git/commits{/sha}",
  "comments_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/comments{/number}",
  "issue_comment_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/issues/comments{/number}",
  "contents_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/contents/{+path}",
  "compare_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/compare/{base}...{head}",
  "merges_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/merges",
  "archive_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/{archive_format}{/ref}",
  "downloads_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/downloads",
  "issues_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/issues{/number}",
  "pulls_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/pulls{/number}",
  "milestones_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/milestones{/number}",
  "notifications_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/notifications{?since,all,participating}",
  "labels_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/labels{/name}",
  "releases_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/releases{/id}",
  "deployments_url": "https://api.github.com/repos/dimsemenov/PhotoSwipe/deployments",
  "created_at": "2011-04-07T05:46:29Z",
  "updated_at": "2022-03-27T01:05:17Z",
  "pushed_at": "2022-03-26T14:18:32Z",
  "git_url": "git://github.com/dimsemenov/PhotoSwipe.git",
  "ssh_url": "git@github.com:dimsemenov/PhotoSwipe.git",
  "clone_url": "https://github.com/dimsemenov/PhotoSwipe.git",
  "svn_url": "https://github.com/dimsemenov/PhotoSwipe",
  "homepage": "http://photoswipe.com",
  "size": 31451,
  "stargazers_count": 21653,
  "watchers_count": 21653,
  "language": "JavaScript",
  "has_issues": true,
  "has_projects": true,
  "has_downloads": true,
  "has_wiki": true,
  "has_pages": false,
  "forks_count": 3271,
  "mirror_url": null,
  "archived": false,
  "disabled": false,
  "open_issues_count": 564,
  "license": {
    "key": "mit",
    "name": "MIT License",
    "spdx_id": "MIT",
    "url": "https://api.github.com/licenses/mit",
    "node_id": "MDc6TGljZW5zZTEz"
  },
  "allow_forking": true,
  "is_template": false,
  "topics": [
    "gallery",
    "image",
    "javascript",
    "lightbox"
  ],
  "visibility": "public",
  "forks": 3271,
  "open_issues": 564,
  "watchers": 21655,
  "default_branch": "master",
  "temp_clone_token": null,
  "network_count": 3271,
  "subscribers_count": 556
}

================================================
FILE: demo-docs-website/sidebars.js
================================================
/**
 * Creating a sidebar enables you to:
 - create an ordered group of docs
 - render a sidebar for each doc of that group
 - provide next/previous navigation

 The sidebars can be generated from the filesystem, or explicitly defined here.

 Create as many sidebars as you want.
 */

// @ts-check

/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
  // By default, Docusaurus generates a sidebar from the docs folder structure
  // tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],

  mainSidebar: [
    {
      type: 'doc',
      id: 'getting-started',
    },
    {
      type: 'category',
      label: 'Examples',
      items: [
        {
          type: 'doc',
          id: 'styling',
        },
        {
          type: 'doc',
          id: 'opening-or-closing-transition',
        },
        {
          type: 'doc',
          id: 'adding-ui-elements',
        },
        {
          type: 'doc',
          id: 'adjusting-zoom-level',
        },
        {
          type: 'doc',
          id: 'caption',
        },
        {
          type: 'doc',
          id: 'click-and-tap-actions',
        },
        {
          type: 'doc',
          id: 'custom-content',
        },
        {
          type: 'doc',
          id: 'data-sources',
        },
        {
          type: 'doc',
          id: 'native-fullscreen-on-open',
        },
      ],
    },

    {
      type: 'category',
      label: 'API',
      items: [
        {
          type: 'doc',
          id: 'options',
        },
        {
          type: 'doc',
          id: 'events',
        },
        {
          type: 'doc',
          id: 'filters',
        },
        {
          type: 'doc',
          id: 'methods',
        },
      ],
    },

    {
      type: 'category',
      label: 'Frameworks',
      items: [
        {
          type: 'doc',
          id: 'react-image-gallery',
        },
        {
          type: 'doc',
          id: 'vue-image-gallery',
        },
        {
          type: 'doc',
          id: 'svelte-image-gallery',
        },
      ],
    },
  ]

  // But you can create a sidebar manually
  /*
  tutorialSidebar: [
    {
      type: 'category',
      label: 'Tutorial',
      items: ['hello'],
    },
  ],
   */
};

module.exports = sidebars;


================================================
FILE: demo-docs-website/src/components/HomepageFeatures/index.js
================================================
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';

const FeatureList = [
  {
    title: 'Easy to Use',
    Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
    description: (
      <>
        Docusaurus was designed from the ground up to be easily installed and
        used to get your website up and running quickly.
      </>
    ),
  },
  {
    title: 'Focus on What Matters',
    Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
    description: (
      <>
        Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go
        ahead and move your docs into the <code>docs</code> directory.
      </>
    ),
  },
  {
    title: 'Powered by React',
    Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
    description: (
      <>
        Extend or customize your website layout by reusing React. Docusaurus can
        be extended while reusing the same header and footer.
      </>
    ),
  },
];

function Feature({Svg, title, description}) {
  return (
    <div className={clsx('col col--4')}>
      <div className="text--center">
        <Svg className={styles.featureSvg} role="img" />
      </div>
      <div className="text--center padding-horiz--md">
        <h3>{title}</h3>
        <p>{description}</p>
      </div>
    </div>
  );
}

export default function HomepageFeatures() {
  return (
    <section className={styles.features}>
      <div className="container">
        <div className="row">
          {FeatureList.map((props, idx) => (
            <Feature key={idx} {...props} />
          ))}
        </div>
      </div>
    </section>
  );
}


================================================
FILE: demo-docs-website/src/components/HomepageFeatures/styles.module.css
================================================
.features {
  display: flex;
  align-items: center;
  padding: 2rem 0;
  width: 100%;
}

.featureSvg {
  height: 200px;
  width: 200px;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/demo-images.js
================================================
export const pswpDemoImages = [{"sizes":[{"height":2500,"width":1875,"type":"jpg","src":"1/img-2500.jpg"},{"height":2000,"width":1500,"type":"jpg","src":"1/img-2000.jpg"},{"height":1500,"width":1125,"type":"jpg","src":"1/img-1500.jpg"},{"height":1000,"width":750,"type":"jpg","src":"1/img-1000.jpg"},{"height":700,"width":525,"type":"jpg","src":"1/img-700.jpg"},{"height":400,"width":300,"type":"jpg","src":"1/img-400.jpg"},{"height":200,"width":150,"type":"jpg","src":"1/img-200.jpg"}]},{"sizes":[{"height":2500,"width":1669,"type":"jpg","src":"2/img-2500.jpg"},{"height":2000,"width":1335,"type":"jpg","src":"2/img-2000.jpg"},{"height":1500,"width":1001,"type":"jpg","src":"2/img-1500.jpg"},{"height":1000,"width":668,"type":"jpg","src":"2/img-1000.jpg"},{"height":700,"width":467,"type":"jpg","src":"2/img-700.jpg"},{"height":400,"width":267,"type":"jpg","src":"2/img-400.jpg"},{"height":200,"width":134,"type":"jpg","src":"2/img-200.jpg"}]},{"sizes":[{"height":1666,"width":2500,"type":"jpg","src":"3/img-2500.jpg"},{"height":1333,"width":2000,"type":"jpg","src":"3/img-2000.jpg"},{"height":1000,"width":1500,"type":"jpg","src":"3/img-1500.jpg"},{"height":667,"width":1000,"type":"jpg","src":"3/img-1000.jpg"},{"height":467,"width":700,"type":"jpg","src":"3/img-700.jpg"},{"height":267,"width":400,"type":"jpg","src":"3/img-400.jpg"},{"height":133,"width":200,"type":"jpg","src":"3/img-200.jpg"}]},{"sizes":[{"height":1667,"width":2500,"type":"jpg","src":"4/img-2500.jpg"},{"height":1333,"width":2000,"type":"jpg","src":"4/img-2000.jpg"},{"height":1000,"width":1500,"type":"jpg","src":"4/img-1500.jpg"},{"height":667,"width":1000,"type":"jpg","src":"4/img-1000.jpg"},{"height":467,"width":700,"type":"jpg","src":"4/img-700.jpg"},{"height":267,"width":400,"type":"jpg","src":"4/img-400.jpg"},{"height":133,"width":200,"type":"jpg","src":"4/img-200.jpg"}]},{"sizes":[{"height":1668,"width":2500,"type":"jpg","src":"5/img-2500.jpg"},{"height":1334,"width":2000,"type":"jpg","src":"5/img-2000.jpg"},{"height":1001,"width":1500,"type":"jpg","src":"5/img-1500.jpg"},{"height":667,"width":1000,"type":"jpg","src":"5/img-1000.jpg"},{"height":467,"width":700,"type":"jpg","src":"5/img-700.jpg"},{"height":267,"width":400,"type":"jpg","src":"5/img-400.jpg"},{"height":133,"width":200,"type":"jpg","src":"5/img-200.jpg"}]},{"sizes":[{"height":1667,"width":2500,"type":"jpg","src":"6/img-2500.jpg"},{"height":1333,"width":2000,"type":"jpg","src":"6/img-2000.jpg"},{"height":1000,"width":1500,"type":"jpg","src":"6/img-1500.jpg"},{"height":667,"width":1000,"type":"jpg","src":"6/img-1000.jpg"},{"height":467,"width":700,"type":"jpg","src":"6/img-700.jpg"},{"height":267,"width":400,"type":"jpg","src":"6/img-400.jpg"},{"height":133,"width":200,"type":"jpg","src":"6/img-200.jpg"}]},{"sizes":[{"height":2500,"width":1875,"type":"jpg","src":"7/img-2500.jpg"},{"height":2000,"width":1500,"type":"jpg","src":"7/img-2000.jpg"},{"height":1500,"width":1125,"type":"jpg","src":"7/img-1500.jpg"},{"height":1000,"width":750,"type":"jpg","src":"7/img-1000.jpg"},{"height":700,"width":525,"type":"jpg","src":"7/img-700.jpg"},{"height":400,"width":300,"type":"jpg","src":"7/img-400.jpg"},{"height":200,"width":150,"type":"jpg","src":"7/img-200.jpg"}]},{"sizes":[{"height":1667,"width":2500,"type":"jpg","src":"8/img-2500.jpg"},{"height":1334,"width":2000,"type":"jpg","src":"8/img-2000.jpg"},{"height":1000,"width":1500,"type":"jpg","src":"8/img-1500.jpg"},{"height":667,"width":1000,"type":"jpg","src":"8/img-1000.jpg"},{"height":467,"width":700,"type":"jpg","src":"8/img-700.jpg"},{"height":267,"width":400,"type":"jpg","src":"8/img-400.jpg"},{"height":133,"width":200,"type":"jpg","src":"8/img-200.jpg"}]},{"sizes":[{"height":1667,"width":2500,"type":"jpg","src":"9/img-2500.jpg"},{"height":1333,"width":2000,"type":"jpg","src":"9/img-2000.jpg"},{"height":1000,"width":1500,"type":"jpg","src":"9/img-1500.jpg"},{"height":667,"width":1000,"type":"jpg","src":"9/img-1000.jpg"},{"height":467,"width":700,"type":"jpg","src":"9/img-700.jpg"},{"height":267,"width":400,"type":"jpg","src":"9/img-400.jpg"},{"height":133,"width":200,"type":"jpg","src":"9/img-200.jpg"}]},{"sizes":[{"height":2500,"width":2000,"type":"jpg","src":"10/img-2500.jpg"},{"height":2000,"width":1600,"type":"jpg","src":"10/img-2000.jpg"},{"height":1500,"width":1200,"type":"jpg","src":"10/img-1500.jpg"},{"height":1000,"width":800,"type":"jpg","src":"10/img-1000.jpg"},{"height":700,"width":560,"type":"jpg","src":"10/img-700.jpg"},{"height":400,"width":320,"type":"jpg","src":"10/img-400.jpg"},{"height":200,"width":160,"type":"jpg","src":"10/img-200.jpg"}]},{"sizes":[{"height":2500,"width":2000,"type":"jpg","src":"11/img-2500.jpg"},{"height":2000,"width":1600,"type":"jpg","src":"11/img-2000.jpg"},{"height":1500,"width":1200,"type":"jpg","src":"11/img-1500.jpg"},{"height":1000,"width":800,"type":"jpg","src":"11/img-1000.jpg"},{"height":700,"width":560,"type":"jpg","src":"11/img-700.jpg"},{"height":400,"width":320,"type":"jpg","src":"11/img-400.jpg"},{"height":200,"width":160,"type":"jpg","src":"11/img-200.jpg"}]}];

================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic--badges.js
================================================
export function basicBadgesTemplate(props) {
  let out = `<div class="pswp-gallery pswp-gallery--single-column" id="gallery--${props.id}">`;
  for (let i = 0; i < (props.numItems || 4); i++) {
    out += `<a href="${props.img[i].src}" 
    data-pswp-width="${props.img[i].width}" 
    data-pswp-height="${props.img[i].height}" 
    target="_blank">
    <img src="${props.img[i].thumbSrc}" alt="" />
    <div class="badge">Badge ${i + 1}</div>
  </a>`;
  }
  out += '</div>';
  return out;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic--cropped.js
================================================
export function basicCroppedTemplate(props) {
  let out = `<div class="pswp-gallery" id="gallery--${props.id}">`;
  for (let i = 0; i < (props.numItems || 3); i++) {
    out += `<a href="${props.img[i].src}" 
    data-pswp-width="${props.img[i].width}" 
    data-pswp-height="${props.img[i].height}" 
    target="_blank"
    data-cropped="true">
    <img src="${props.img[i].thumbSrc}" alt="" />
  </a>`;
  }
  out += '</div>';
  return out;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic.js
================================================
export function basicTemplate(props) {
  let out = `<div class="pswp-gallery" id="gallery--${props.id}">\n`;
  for (let i = 0; i < (props.numItems || 3); i++) {
    out += `  <a href="${props.img[i].src}" 
    data-pswp-width="${props.img[i].width}" 
    data-pswp-height="${props.img[i].height}" 
    target="_blank">
    <img src="${props.img[i].thumbSrc}" alt="" />
  </a>\n`;
  }
  out += '</div>';
  return out;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/caption.js
================================================
export function captionTemplate(props) {
  return `<div class="pswp-gallery pswp-gallery--with-caption" id="gallery--${props.id}">
  <div class="pswp-gallery__item">
    <a  
      href="${props.img[1].src}" 
      data-pswp-width="${props.img[1].width}" 
      data-pswp-height="${props.img[1].height}" 
      target="_blank">
      <img src="${props.img[1].thumbSrc}" alt="Caption 1" />
    </a>
    <div class="hidden-caption-content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. <a href="https://example.com" target="_blank" rel="nofollow">Test link &rarr;</a></div>
  </div>

  <div class="pswp-gallery__item">
    <a  
      href="${props.img[2].src}" 
      data-pswp-width="${props.img[2].width}" 
      data-pswp-height="${props.img[2].height}" 
      target="_blank">
      <img src="${props.img[2].thumbSrc}" alt="Caption 2" />
    </a>
  </div>

  <div class="pswp-gallery__item">
    <a  
      href="${props.img[3].src}" 
      data-pswp-width="${props.img[3].width}" 
      data-pswp-height="${props.img[3].height}" 
      target="_blank">
      <img src="${props.img[3].thumbSrc}" alt="Caption 3" />
    </a>
  </div>
  
  <div class="pswp-gallery__item">
    <a  
      href="${props.img[4].src}" 
      data-pswp-width="${props.img[4].width}" 
      data-pswp-height="${props.img[4].height}" 
      target="_blank">
      <img src="${props.img[4].thumbSrc}" alt="Caption 4" />
    </a>
  </div>

  
</div>`;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/content-types.js
================================================
export function contentTypesTemplate(props) {
  return `<div class="pswp-gallery" id="gallery--${props.id}">
    <a  
      href="${props.img[0].src}" 
      data-pswp-width="${props.img[0].width}" 
      data-pswp-height="${props.img[0].height}" 
      data-pswp-webp-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-2500.webp"
      target="_blank">
      <img src="${props.img[0].thumbSrc}" alt="" />
    </a>

    <a  
      href="${props.img[2].src}" 
      data-pswp-width="${props.img[2].width}" 
      data-pswp-height="${props.img[2].height}" 
      target="_blank">
      <img src="${props.img[2].thumbSrc}" alt="" />
    </a>

    <a  
      href="${props.img[3].src}" 
      data-pswp-width="${props.img[3].width}" 
      data-pswp-height="${props.img[3].height}" 
      target="_blank">
      <img src="${props.img[3].thumbSrc}" alt="" />
    </a>
  
</div>`;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/custom-html-markup-data-source.js
================================================
export function customHTMLDataSourceTemplate(props) {
  let out = `<div class="pswp-gallery pswp-gallery--single-column" id="gallery--${props.id}">\n`;
  for (let i = 0; i < (props.numItems || 3); i++) {
    out += `  <a href="${props.img[i].src}" 
    data-my-size="${props.img[i].width}x${props.img[i].height}" 
    data-thumb-src="${props.img[i].thumbSrc}"
    style="background-image:url(${props.img[i].thumbSrc})"
    target="_blank">Test ${i + 1}</a>\n`;
  }
  out += '</div>';
  return out;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/getting-started.js
================================================
export function gettingStartedTemplate(props) {
  return `<div class="pswp-gallery pswp-gallery--single-column" id="gallery--${props.id}">
  <a href="${props.img[1].src}" 
    data-pswp-width="${props.img[1].width}" 
    data-pswp-height="${props.img[1].height}" 
    target="_blank">
    <img src="${props.img[1].thumbSrc}" alt="" />
  </a>
  <!-- cropped thumbnail: -->
  <a href="${props.img[6].src}" 
    data-pswp-width="${props.img[6].width}" 
    data-pswp-height="${props.img[6].height}" 
    data-cropped="true" 
    target="_blank">
    <img src="${props.img[6].thumbSrc}" alt="" />
    Cropped
  </a>
  <!-- data-pswp-src with custom URL in href -->
  <a href="https://unsplash.com" 
    data-pswp-src="${props.img[2].src}"
    data-pswp-width="${props.img[2].width}" 
    data-pswp-height="${props.img[2].height}" 
    target="_blank">
    <img src="${props.img[2].thumbSrc}" alt="" />
  </a>
  <!-- Without thumbnail: -->
  <a href="http://example.com" 
    data-pswp-src="${props.img[4].src}"
    data-pswp-width="${props.img[4].width}" 
    data-pswp-height="${props.img[4].height}" 
    target="_blank">
    No thumbnail
  </a>
  <!-- wrapped with any element: -->
  <div>
    <a href="${props.img[5].src}"
      data-pswp-width="${props.img[5].width}" 
      data-pswp-height="${props.img[5].height}" 
      target="_blank">
      <img src="${props.img[5].thumbSrc}" alt="" />
    </a>
  </div>
</div>`;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/srcset-test.js
================================================
export function srcsetTemplate(props) {
  const items = [{ thumbSrc: '1-300x200.png', largeSrc: '1-1500x1000.png', width: 1500, height: 1000, srcset: '%1-600x400.png 600w, %1-1200x800.png 1200w, %1-1500x1000.png 1500w' }, { thumbSrc: '2-300x200.png', largeSrc: '2-1500x1000.png', width: 1500, height: 1000, srcset: '%2-600x400.png 600w, %2-1200x800.png 1200w, %2-1500x1000.png 1500w' }, { thumbSrc: '3-300x300.png', largeSrc: '3-1500x1500.png', width: 1500, height: 1500, srcset: '%3-600x600.png 600w, %3-1200x1200.png 1200w, %3-1500x1500.png 1500w' }, { thumbSrc: '4-200x300.png', largeSrc: '4-1000x1500.png', width: 1000, height: 1500, srcset: '%4-400x600.png 400w, %4-800x1200.png 800w, %4-1000x1500.png 1000w' }];
  let out = `<div class="pswp-gallery" id="gallery--${props.id}">\n`;
  const baseURL = props.cdnURL + 'srcset-test/';
  items.forEach((item) => {
    const srcset = item.srcset.replace(/%/g, baseURL);
    out += `  <a href="${baseURL + item.largeSrc}" 
    data-pswp-width="${item.width}" 
    data-pswp-height="${item.height}" 
    data-pswp-srcset="${srcset}" 
    target="_blank">
    <img src="${baseURL + item.thumbSrc}" alt="" />
  </a>\n`;
  });
  out += '</div>';
  return out;
}


================================================
FILE: demo-docs-website/src/components/PswpCodePreview/index.js
================================================
import React from 'react';
import CodeBlock from '../../theme/CodeBlock';
import { pswpDemoImages } from './demo-images';
import { basicTemplate } from './gallery-templates/basic';

let uidCounter = 1;

/**
 * Get the smallest size (but not smaller than minSize)
 *
 * @param {Array} sizes
 * @param {Integer} minSize
 */
const getSmallestImageSize = (sizes, minSize) => {
  sizes = sizes.filter(size => size.width >= minSize);
  return sizes.reduce((a, b) => (a.width < b.width ? a : b));
};

/**
 * Generates gallery for demo
 * 
 * Supported params:
 *   displayHTML: false|true (whether HTML code block should be visible)
 *   numItems: Integer (number of images to display)
 *   galleryID: String (ID attribute)
*/
function generateGallery(galleryData) {
  

  const thumbnailSize = 70;
  const cdnURL = 'https://cdn.photoswipe.com/photoswipe-demo-images/photos/';
  const templateProps = {
    numItems: Math.min(parseInt(galleryData.numItems, 10) || 3, 11),
    id: galleryData.galleryID || (uidCounter++),
    img: [],
    cdnURL
  };
  const { orientation } = galleryData;
  let demoImages = [ ...pswpDemoImages ];

  if (orientation === 'landscape') {
    demoImages = demoImages.filter((imageData) => {
      return imageData.sizes[0].width >= imageData.sizes[0].height;
    });
  } else if (orientation === 'portrait') {
    demoImages = demoImages.filter((imageData) => {
      return imageData.sizes[0].width <= imageData.sizes[0].height;
    });
  }

  demoImages.forEach((imageData, index) => {
    const largest = imageData.sizes[0];
    const thumbnail = getSmallestImageSize(imageData.sizes, thumbnailSize);
    templateProps.img.push({
      index,
      width: largest.width,
      height: largest.height,
      src: cdnURL + largest.src,
      thumbSrc: cdnURL + thumbnail.src
    });
  });

  if (galleryData.templateFn) {
    return galleryData.templateFn(templateProps);
  }
  
  
  return basicTemplate(templateProps);
}

export default function PswpCodePreview(props) {
  return (
    <div className='pswp-example'>
      { props.children }
      { props.galleryID && <CodeBlock language='html' pswpcode displayHTML={props.displayHTML}>{generateGallery(props)}</CodeBlock> }
    </div>
  );
}


================================================
FILE: demo-docs-website/src/css/custom.css
================================================
/**
 * Any CSS included here will be global. The classic template
 * bundles Infima by default. Infima is a CSS framework designed to
 * work well for content-centric websites.
 */

/* You can override the default Infima variables here. */
:root {
  --ifm-color-primary: #2e8555;
  --ifm-color-primary-dark: #29784c;
  --ifm-color-primary-darker: #277148;
  --ifm-color-primary-darkest: #205d3b;
  --ifm-color-primary-light: #33925d;
  --ifm-color-primary-lighter: #359962;
  --ifm-color-primary-lightest: #3cad6e; 
  --ifm-code-font-size: 95%;

  --ifm-toc-border-color: rgba(0, 0, 0, 0.065);
  --ifm-code-background: rgb(250, 250, 250);

  --ifm-link-color: #3169B3;
  --ifm-link-hover-color: #C00;
  --ifm-link-decoration: underline;
  --ifm-link-hover-decoration: underline;

  --ifm-navbar-link-hover-color: var(--ifm-link-hover-color);

  --ifm-footer-background-color: none;
  --ifm-footer-color: auto;
  --ifm-footer-padding-horizontal: calc(var(--ifm-spacing-horizontal) * 2);
  --ifm-footer-padding-vertical: calc(var(--ifm-spacing-vertical) * 2);

  --pswp-docs-main-content-width: 1100px;

  --ifm-heading-font-weight: var(--ifm-font-weight-semibold);


}

a {
  transition: none;
}

a:hover {
  color: var(--ifm-link-hover-color);
  /* autoprefixer: ignore next */
  text-decoration: var(--ifm-link-hover-decoration);
}

pre code,
.pswp-example__preview {
  background: var(--ifm-code-background);
}

code {
  border: 0;
}

.docusaurus-highlight-code-line {
  background-color: rgba(0, 0, 0, 0.1);
  display: block;
  margin: 0 calc(-1 * var(--ifm-pre-padding));
  padding: 0 var(--ifm-pre-padding);
}

.ukraine-flag {
  width: 21px;
  height: 14px;
  position: relative;
  background: #ffcc00;
  top: 2px;
  display: inline-block;
  margin-left: 3px;
  margin-right: 2px;
}
.ukraine-flag:before {
 content:'';
 position: absolute;
 width: 21px;
 height: 7px;
 left:0;
 top:0;
 background: #0066cc;
}

a.hash-link {
  text-decoration: none;
  transition: none;
  padding: 0.5rem 0.7rem;
}

.theme-code-block--hidden {
  display: none;
}


.navbar,
.footer,
.main-wrapper {
  width: 100%;
  max-width: var(--pswp-docs-main-content-width);
  margin: 0 auto;
}
.navbar {
  z-index: 20;
  box-shadow: none;
  border-bottom: 1px solid var(--ifm-toc-border-color);
}
.footer {
  margin-top: 60px;
  border-top: 1px solid var(--ifm-toc-border-color);
}
.docs-wrapper {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: center;
}
.pswp-docs__main-column > article {
  max-width: 700px;
}
.pswp-docs__sidebar-menu {
  width: 30%;
  width: 250px;
}

/*.pswp-docs__main-column {
  width: 70%;
} */
.theme-doc-markdown {
  /* max-width: 670px; */
}

@import './sidebar-menu.css';
@import './docs-page.css';
@import './example-code-block.css';
@import './scrollbar.css';
@import './header.css';
@import './home.css';

================================================
FILE: demo-docs-website/src/css/docs-page.css
================================================
/* .theme-doc-footer,
.pagination-nav,
.theme-doc-markdown > * {
  max-width: 650px;
} */

.theme-doc-markdown iframe {
  width: 100%;
  height: 450px;
}

.theme-doc-footer {
  border-top: 1px solid var(--ifm-toc-border-color);
  padding: var(--ifm-global-spacing) 0;
}
nav.pagination-nav {
  border-top: 1px solid var(--ifm-toc-border-color);
  margin-top: 0;
}
a.pagination-nav__link {
  border: 0;
  text-decoration: none;
  padding: var(--ifm-global-spacing) 0;
}
a.pagination-nav__link .pagination-nav__sublabel {
  text-decoration: none;
}
.pagination-nav__label {
  font-size: var(--ifm-h3-font-size);
}
.pagination-nav__label::after,
.pagination-nav__label::before {
  content: none !important;
}
    

================================================
FILE: demo-docs-website/src/css/example-code-block.css
================================================
.pswp-example {
  width: 100%;
  position: relative;
  margin-bottom: 1rem;
  
}

span.docusaurus-highlight-code-line {
  background: rgba(255, 217, 109, .3);
}


.pswp-example .theme-code-block {
  width: calc(100% - 204px);
  margin-bottom: 4px;
}
.pswp-example__preview {
  width: 200px;
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  overflow-y: auto;
  margin-left: 4px;
}

.pswp-example__preview {
  padding: var(--ifm-pre-padding);
}
.pswp-example .pswp-gallery {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  flex-wrap: wrap;
  position: relative;
  width: 155px;
  
}

.pswp-example .pswp-gallery img {
  display: block;
}
.pswp-gallery {
  display: flex;
}
.pswp-gallery > * {
  display: block;
  position: relative;
  margin-bottom: 4px;
  margin-right: 4px;
  width: 70px;
}
.pswp-example .pswp-gallery > *:nth-child(2n) {
  margin-right: 0;
}

.pswp-example .pswp-gallery--single-column > * {
  width: 120px;
  margin-bottom: 18px;
  font-size: 14px;
}

button.pswp-example__hide-html-btn {
  position: absolute;
  cursor: pointer;
  z-index: 10;
  font-size: 12px;
  right: 0;
  bottom: 0;
  color: var(--ifm-link-color);
  background: none;
  border: 0;
  padding: 2px 5px;
  background: var(--ifm-pre-background);
}
button.pswp-example__hide-html-btn:hover {
  color: var(--ifm-link-hover-color);
}

[data-cropped] img {
  width: 100%;
  height: 70px;
  object-fit: cover;
}

@media only screen and (max-width: 600px) {
  .pswp-example .theme-code-block {
      width: 100%;
  }
  .pswp-example__preview {
      width: 100%;
      height: auto;
      position: relative;
  }
  .pswp-example__preview .pswp-gallery {
      max-width: 150px;
  }
}

.pswp-example__code--hidden {
  display: none;
}


input[type="checkbox"].hidden-cb {
  width: 1px;
  height: 1px;
  opacity: 0.01;
  overflow: hidden;
  position: absolute;
  right: 0;
  bottom: 0;
}
label.pswp-example__toggle {
  position: absolute;
  right: 0;
  bottom: -25px;
  padding: 0 0;
  border-radius: 0;
  font-size: 14px;
  color: #1B57A5;
  cursor: pointer;
  z-index: 20;
}
label.pswp-example__toggle:hover {
  color: #c00;
}
input[type="checkbox"]:focus + label {
  outline: 1px dotted #212121;
  outline: 5px auto -webkit-focus-ring-color;
}
input[type="checkbox"]:checked {
  display: none;
}
input[type="checkbox"]:checked + label {
  display: none;
}
input[type="checkbox"]:checked + label + .pswp-example__code--hidden {
  display: block !important;
}

================================================
FILE: demo-docs-website/src/css/header.css
================================================
a.navbar__brand {
  text-decoration: none;
  font-size: 20px;
  line-height: 1;
  white-space: nowrap;
  transform: translate(0, -2px);
}
a.navbar__link {
  color: var(--ifm-link-color);
  text-decoration: none;
}
a.navbar__link--active {
  color: var(--ifm-font-color-base);
}
.navbar__link svg {
  display: none;
}

a.pswp-docs__github-link {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  text-decoration: none;
  font-weight: var(--ifm-font-weight-semibold);
}
a.pswp-docs__github-link:hover {
  text-decoration: none;
}
.pswp-docs__github-link svg {
  transform: translate(0, 2px);
  margin-right: 3px;
}
.pswp-docs__github-link-left {
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;
  padding: 2px 8px;
  border: 1px solid #D5D5D5;
}
.pswp-docs__github-link-right {
  background: #fff;
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
  padding: 2px 8px;
  border: 1px solid #D5D5D5;
  border-left: 0;
  color: #222;
}

.navbar__brand span {
  font-size: 12px;
  margin-left: 4px;
  margin-top: -12px;
  line-height: 1;
}
button.DocSearch {
  --docsearch-searchbox-background: #e9e9e9;
  --docsearch-primary-color: var(--ifm-link-color);
  --docsearch-text-color: #222;
  --docsearch-muted-color: #222;
  --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
  --docsearch-highlight-color: var(--ifm-link-color);
  height: 35px;
}
button .DocSearch-Button-Placeholder {
  font-size: 16px;
  font-weight: 400;
}
button .DocSearch-Button-Keys {
  display: none !important;
}

================================================
FILE: demo-docs-website/src/css/home.css
================================================
.pswp-docs__home .navbar__brand {
  display: none;
}
.pswp-docs__header-title-text {
  margin: 60px 0px 50px;
  font-size: 22px;
  text-align: center;
}
.pswp-docs__whats-new {
  margin-top: 50px;
}
.pswp-docs__whats-new h4 {
  margin: 50px auto 12px;
  font-size: 24px;
}

.pswp-docs__home-block-main-col > * {
  max-width: 600px;
  margin-left: auto;
  margin-right: auto;
}

.pswp-docs__home-block-full-width-col {
  max-width: 1068px;
}



.pswp-docs__header-title-text a svg {
  display: inline-block;
  width: 16px;
  fill: var(--ifm-link-color);
  transform: translate(0px, 3px);
  margin-left: 0.2em;
}
.pswp-docs__header-title-text a:hover svg {
  fill: var(--ifm-link-hover-color);
}


.pswp-docs__header-title-text a {
  font-weight: bold;
  text-decoration: none;
}

.pswp-docs__header-title-text h1 {
  font-weight: bold;
  font-size: 64px;
  line-height: 1;
  margin-bottom: 14px;
}

.pswp-docs__header-title-text h1 span {
  position: absolute;
  vertical-align: super;
  font-size: 16px;
  text-decoration: none;
}

.pswp-docs__header-title-text p {
  margin-bottom: 0;
}




.pswp-docs__home-gallery {
  position: relative;
  display: grid;
  width: 100%;
  grid-template-columns: 1fr 0.5fr 0.5fr;
  grid-gap: 10px;
}
.pswp-docs__home-gallery-credit {
  position: absolute;
  right: 0;
  bottom: -21px;
  font-size: 12px;
}
.pswp-docs__home-gallery .pswp-docs__home-gallery-item {
  position: relative;
}
figure.pswp-docs__home-gallery-item {
  display: block;
  margin: 0;
  padding: 0;
}
.pswp-docs__home-gallery-item figcaption {
  display: none;
}

.pswp-docs__home-gallery .pswp-docs__home-gallery-item img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pswp-docs__home-gallery .pswp-docs__home-gallery-item:first-child {
  grid-row: span 2;
}
.pswp-docs__home-gallery .pswp-docs__home-gallery-item a {
  display: block;
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
  padding-bottom: 100%;
}


.pswp-docs__home-gallery-example {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  flex-wrap: wrap;
  width: 100%;
}
.pswp-docs__home-gallery-example a {
  position: relative;
  margin: 0 4px 4px 0;
  line-height: 0;
  display: block;
}
.pswp-docs__home-gallery-example img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  max-width: none;
}

.pswp-docs__home-block h2 {
  font-weight: bold;
  font-size: 40px;
  line-height: 1.1;
  margin: 70px auto 36px;
}

.pswp__dynamic-caption {
  font-size: 14px;
  line-height: 1.5;
}

#gallery--deep-zoom {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: baseline;
}
#gallery--deep-zoom figure {
  display: block;
  margin: 0;
  padding: 0;
  margin-right: 4px;
  min-width: 100px;
  max-width: 180px;
}
@media (max-width: 900px) {
  .pswp__dynamic-caption.pswp__dynamic-caption--aside {
    margin-top: 0;
  }
}
@media (max-width: 700px) {
  #gallery--deep-zoom {
    max-width: 296px;
  }
}



#gallery--deep-zoom figure:last-child {
  margin-right: 0;
}
#gallery--deep-zoom figure > a {
  display: block;
  position: relative;
}
#gallery--deep-zoom img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
}
figcaption.caption {
  font-size: 12px;
  margin-top: 6px;
}



@media (max-width: 650px) {
  .pswp-docs__home-gallery {
    grid-gap: 5px;
  }
  .pswp-docs__header-title-text h1 {
    font-size: 36px;
  }
  .pswp-docs__header-title-text {
    margin: 40px 0px 30px;
    font-size: 18px;
    text-align: center;
  }
  .pswp-docs__home-block h2 {
    font-size: 26px;
    margin: 40px auto 12px;
  }
  .pswp-docs__whats-new h4 {
    margin: 24px auto 12px;
    font-size: var(--ifm-font-size-base);
  }
  #gallery--deep-zoom {
    max-width: 296px;
  }
}

================================================
FILE: demo-docs-website/src/css/scrollbar.css
================================================
/* style scrollbar */
.docs-styled-scrollbar::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.docs-styled-scrollbar::-webkit-scrollbar-button {
  width: 0px;
  height: 0px;
}
.docs-styled-scrollbar::-webkit-scrollbar-thumb {
  background: #C2C2C2;
  border: 0;
  border-radius: 0;
}
.docs-styled-scrollbar::-webkit-scrollbar-thumb:hover {
  background: #aaa;
}
.docs-styled-scrollbar::-webkit-scrollbar-thumb:active {
  background: #999;
}
.docs-styled-scrollbar::-webkit-scrollbar-track {
background: none;
border: 0;
border-radius: 0;
background: #eee;
}
.docs-styled-scrollbar::-webkit-scrollbar-track:hover {
  background: #ddd;
}
.docs-styled-scrollbar::-webkit-scrollbar-corner {
background: none;
}


================================================
FILE: demo-docs-website/src/css/sidebar-menu.css
================================================
aside.theme-doc-sidebar-container {
  border: 0;
  margin-top: 0;
}

aside.theme-doc-sidebar-container {
  position: sticky;
  margin-top: 30px;
  top: 30px;
}
.pswp-docs__sidebar-menu {
  position: relative;
  border-right: 1px solid var(--ifm-toc-border-color);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 0 var(--ifm-navbar-padding-horizontal)
}
.pswp-docs__sidebar-menu--mobile {
  position: relative;
  margin-top: 0;
  top: auto;
}

.pswp-docs__sidebar-menu-item  {
  text-decoration: none;
  font-size: 16px;
  line-height: 22px;
  padding: 4px 0;
}

.pswp-docs__sidebar-menu-item--category {
  color: #393939;
  opacity: 0.5;
  margin-top: 16px;
}
.pswp-docs__sidebar-menu-item--category:first-child {
  margin-top: 0;;
}

a.pswp-docs__sidebar-menu-item--active {
  color: var(--ifm-font-color-base);
}


.docSidebarContainer {
  display: none;
}


@media (max-width: 996px) {
  .pswp-docs__sidebar-menu {
    border-right: 0;
  }
  .theme-doc-sidebar-container > .pswp-docs__sidebar-menu {
    display: none;
  }
}

@media (min-width: 997px) {

}

================================================
FILE: demo-docs-website/src/pages/_index-deep-zoom-demo.js
================================================
import React, { useEffect } from 'react';
import Lightbox from '../../static/photoswipe/photoswipe-lightbox.esm.js';

//import PhotoSwipeDeepZoom from 'photoswipe-deep-zoom-plugin';

const galleryHTML = `
  <figure style="flex: 132.13213213213;">
    <a style="padding-bottom:75.6818%" href="https://cdn.photoswipe.com/photoswipe-deep-zoom/old-map/full.jpg" data-pswp-width="1700" data-pswp-height="1285" data-pswp-tile-url="https://cdn.photoswipe.com/photoswipe-deep-zoom/old-map/{z}/{x}_{y}.jpeg" data-pswp-tile-size="254" data-pswp-tile-overlap="1" data-pswp-max-width="5832" data-pswp-max-height="4409" target="_blank">
      <img src="https://cdn.photoswipe.com/photoswipe-deep-zoom/old-map/thumb.jpg" alt="">
    </a>
    <figcaption class="caption">
      <a href="https://en.wikipedia.org/wiki/Cambriae_Typus"><strong>Cambriae Typus</strong></a>
      <br>
      Humphrey Llwyd
      <br>
      5,832px x 4,409px
    </figcaption>
  </figure>

  <figure style="flex: 80;">
    <a style="padding-bottom:124.7%" href="https://cdn.photoswipe.com/photoswipe-deep-zoom/a-sergeant-of-the-light-horse/full.jpg" data-pswp-width="1635" data-pswp-height="2048" data-pswp-tile-type="zoomify" data-pswp-tile-url="https://cdn.photoswipe.com/photoswipe-deep-zoom/a-sergeant-of-the-light-horse/TileGroup{zoomify_group}/{z}-{x}-{y}.jpg" data-pswp-tile-size="256" data-pswp-max-width="4578" data-pswp-max-height="5736" target="_blank">
      <img src="https://cdn.photoswipe.com/photoswipe-deep-zoom/a-sergeant-of-the-light-horse/thumb.jpg" alt="A sergeant of the Light Horse">
    </a>
    <figcaption class="caption">
      <a href="https://en.wikipedia.org/wiki/A_Sergeant_of_the_Light_Horse"><strong>A sergeant of the Light Horse</strong></a>
      <br>
      George Lambert
      <br>
      4,578px x 5,736px
    </figcaption>
  </figure>

  <figure style="flex: 126.34408602151;">
    <a style="padding-bottom:79.15%" href="https://cdn.photoswipe.com/photoswipe-deep-zoom/starry/starry_files/full.jpg" data-pswp-width="1700" data-pswp-height="1346" data-pswp-tile-url="https://cdn.photoswipe.com/photoswipe-deep-zoom/starry/starry_files/{z}/{x}_{y}.jpeg" data-pswp-tile-size="254" data-pswp-tile-overlap="1" data-pswp-max-width="30000" data-pswp-max-height="23756" target="_blank">
      <img src="https://cdn.photoswipe.com/photoswipe-deep-zoom/starry/thumb.jpg" alt="">
    </a>
    <figcaption class="caption">
      <a href="https://en.wikipedia.org/wiki/The_Starry_Night"><strong>The Starry Night</strong></a>
      <br>
      Vincent van Gogh
      <br>
      30,000px x 23,756px
    </figcaption>
  </figure>

  <figure style="flex: 93.418259023355;">
    <a style="padding-bottom:107%" data-pswp-group-id="1" href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/chen-hongshou/large.jpg" data-pswp-width="1820" data-pswp-height="1948" target="_blank">
      <img src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/chen-hongshou/thumb.jpg" alt="">
    </a>
    <figcaption class="caption">
      <a href="https://en.wikipedia.org/wiki/Chen_Hongshou"><strong>Magnolia and Erect Rock</strong></a>
      <br>
      Chen Hongshou
      <br>
      1,820px x 1,948px (not tiled)
    </figcaption>
  </figure>

`;

export default function DeepZoomGalleryDemo() {

  useEffect(() => {
    let deepZoomPlugin;
    let lightbox = new Lightbox({
      gallery: '#gallery--deep-zoom',
      children: 'figure > a',
      pswpModule: () => import('../../static/photoswipe/photoswipe.esm.js'),

      // dynamically load deep zoom plugin
      openPromise: () => {
        // make sure it's initialized only once per lightbox
        if (!deepZoomPlugin) {
          return import('photoswipe-deep-zoom-plugin').then((deepZoomPluginModule) => {
            deepZoomPlugin = new deepZoomPluginModule.default(lightbox, {
              // deep zoom plugin options
            });
          })
        }
      },
      
      // Recommended PhotoSwipe options for this plugin
      allowPanToNext: false, // prevent swiping to the next slide when image is zoomed
      allowMouseDrag: true, // display dragging cursor at max zoom level
      wheelToZoom: true, // enable wheel-based zoom
      zoom: false // disable default zoom button
    });
    lightbox.init();

    return function cleanup() {
      if (lightbox) {
        lightbox.destroy();
        lightbox = null;
      }
      
      if (deepZoomPlugin) {
        deepZoomPlugin.destroy();
        deepZoomPlugin = null;
      }
    };
  }, []);

  return (
    <div id="gallery--deep-zoom" dangerouslySetInnerHTML={{__html: galleryHTML}} />
  )
}


================================================
FILE: demo-docs-website/src/pages/_index-gallery-header.js
================================================
import React, { useEffect } from 'react';
import Lightbox from '../../static/photoswipe/photoswipe-lightbox.esm.js';
import PhotoSwipe from '../../static/photoswipe/photoswipe.esm.js'

import PhotoSwipeDynamicCaption from 'photoswipe-dynamic-caption-plugin';
import 'photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css';

const baseCdnUrl = 'https://cdn.photoswipe.com/photoswipe-demo-images/photos/home-demo/';
const imagesData = [
  {
    caption: `<strong>Test Caption</strong><br>
    Dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.`,
    width: 2500,
    height: 3125,
    src: `${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_2500.jpg`,
    thumbSrc: `${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_664.jpg`,
    thumbSrcset: `${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/thumb.jpg 524w,
    ${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_664.jpg 664w,
    ${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_932.jpg 932w`,
    srcset: `${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_664.jpg 664w,
    ${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_932.jpg 932w,
    ${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_1355.jpg 1355w,
    ${baseCdnUrl}luca-bravo-ny6qxqv_m04-unsplash_snrzpf/luca-bravo-ny6qxqv_m04-unsplash_snrzpf_c_scale,w_2500.jpg 2500w`
  },


  {
    width: 2500,
    height: 1667,
    caption: `<strong>Another Test Caption</strong><br>
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.`, 
    src: `${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_2500.jpg`,
    thumbSrc: `${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_300.jpg`,
    thumbSrcset: `${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/thumb.jpg 393w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_612.jpg 612w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_826.jpg 826w`,
    srcset: `${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_612.jpg 612w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_826.jpg 826w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_1115.jpg 1115w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_1400.jpg 1400w,
    ${baseCdnUrl}luca-bravo-O453M2Liufs-unsplash_qqt53u/luca-bravo-O453M2Liufs-unsplash_qqt53u_c_scale,w_2500.jpg 2500w`
  },
  {
    width: 2500,
    height: 1667,
    caption: `<strong>Long caption</strong><br>
    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore.Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?`, 
    src: `${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_2500.jpg`,
    thumbSrc: `${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_300.jpg`,
    thumbSrcset: `${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/thumb.jpg 393w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_639.jpg 639w`,
    srcset: `${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_639.jpg 639w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_1176.jpg 1176w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_1200.jpg 1200w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_1385.jpg 1385w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_1834.jpg 1834w,
    ${baseCdnUrl}luca-bravo-VowIFDxogG4-unsplash_ibrktu/luca-bravo-VowIFDxogG4-unsplash_ibrktu_c_scale,w_2500.jpg 2500w`
  },

  {
    width: 2500,
    height: 1667,
    caption: `<strong>Lorem Ipsum</strong><br>Unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.`, 
    src: `${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_2500.jpg`,
    thumbSrc: `${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_300.jpg`,
    thumbSrcset: `${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/thumb.jpg 393w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_627.jpg 627w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_861.jpg 861w`,
    srcset: `${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_627.jpg 627w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_861.jpg 861w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_1057.jpg 1057w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_1441.jpg 1441w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_1881.jpg 1881w,
    ${baseCdnUrl}luca-bravo-zAjdgNXsMeg-unsplash_q6zdih/luca-bravo-zAjdgNXsMeg-unsplash_q6zdih_c_scale,w_2500.jpg 2500w`
  },


  {
    width: 2500,
    height: 1667,
    caption: `<strong>Test Caption</strong><br/>
    Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?<br/>`, 
    src: `${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_2500.jpg`,
    thumbSrc: `${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_300.jpg`,
    thumbSrcset: `${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/thumb.jpg 393w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_649.jpg 649w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_996.jpg 996w`,
    srcset: `${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_300.jpg 300w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_649.jpg 649w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_996.jpg 996w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_1188.jpg 1188w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_1303.jpg 1303w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_1840.jpg 1840w,
    ${baseCdnUrl}luca-bravo-A-fubu9QJxE-unsplash_jxy5p8/luca-bravo-A-fubu9QJxE-unsplash_jxy5p8_c_scale,w_2500.jpg 2500w`
  },


];

function GalleryItem(props) {
  const attributes = {
    style: { 
      paddingBottom:  props.cropped ? 1 / props.aspectRatio * 100 + '%'  : props.height / props.width * 100 + '%'
    },
    href: props.src,
    'data-pswp-srcset': props.srcset,
    'data-pswp-width': props.width,
    'data-pswp-height': props.height,
    target: '_blank',
    ...( props.cropped && { 'data-cropped': true } )
  };

  const figureAttributes = {
    style: {},
    className: 'pswp-docs__home-gallery-item'
  };

  let sizes = props.sizes;
  if (props.justifiedRow) {
    figureAttributes.style.flex = props.width / props.height * 100;
    const widthRatio = ( props.width / props.height) / props.aspectRatioSumm;
    sizes = `(min-width: 1124px) ${Math.ceil(600 * widthRatio)}px, ${Math.ceil(100 * widthRatio)}vw`;
  }

  return (
    <figure {...figureAttributes}>
      <a {...attributes}>
      <img
        sizes={sizes}
        srcSet={props.thumbSrcset}
        src={props.thumbSrc}
        alt="" />
      { props.caption && <figcaption dangerouslySetInnerHTML={{__html: props.caption}}></figcaption> }
      </a>
    </figure>
  );
}

export function GalleryExampleOpenZoomed(props) {
  useEffect(() => {
    let lightbox = new Lightbox({
      gallery: '#gallery--open-zooomed figure > a',
      initialZoomLevel: 'fill',
      secondaryZoomLevel: 'fill',
      maxZoomLevel: 3,
      pswpModule: PhotoSwipe
    });
    lightbox.init();

    return function cleanup() {
      lightbox.destroy();
      lightbox = null;
    };
  }, []);

  return (
    <GalleryExample id="gallery--open-zooomed" items={[3, 4]} cropped={false} justifiedRow={true} />
  )
}


export function GalleryExampleDynamicCaptionPlugin(props) {
  useEffect(() => {
    const smallScreenPadding = {
      top: 0, bottom: 0, left: 0, right: 0
    };
    const largeScreenPadding = {
      top: 20, bottom: 20, left: 50, right: 50
    };
    let lightbox = new Lightbox({
      gallery: '#gallery--dynamic-caption',
      children: '.pswp-docs__home-gallery-item > a',
      paddingFn: (viewportSize) => {
        return viewportSize.x < 700 ? smallScreenPadding : largeScreenPadding
      },
      pswpModule: () => import('../../static/photoswipe/photoswipe.esm.js')
    });
    lightbox.init();

    let captionPlugin = new PhotoSwipeDynamicCaption(lightbox, {
      type: 'auto',
      captionContent: 'figcaption'
    });

    return function cleanup() {
      lightbox.destroy();
      lightbox = null;
      captionPlugin = null;
    };
  }, []);

  return (
    <GalleryExample id="gallery--dynamic-caption" items={[0,1,2]} cropped={false} justifiedRow={true} />
  )
}


export function GalleryExample(props) {

  const aspectRatioSumm = imagesData.reduce((summ, image, index) => {
    if (props.items && !props.items.includes(index)) {
      return summ;
    }
    return summ + image.width / image.height;
  }, 0);

  const galleryItems = imagesData.map((image, index) => {
    if (props.items && !props.items.includes(index)) {
      return;
    }

    return <GalleryItem 
      key={index} 
      {...image} 
      cropped={props.cropped} 
      aspectRatio={1} 
      aspectRatioSumm={aspectRatioSumm}
      justifiedRow={props.justifiedRow} />
  });

  return (
    <div className="pswp-docs__home-gallery-example" id={props.id} data-summ={aspectRatioSumm}>
      {galleryItems}
    </div>
  );
}

export default function GalleryHeader() {
  useEffect(() => {
    let lightbox = new Lightbox({
      gallery: '#gallery--header-home',
      children: '.pswp-docs__home-gallery-item > a',
      pswpModule: () => import('../../static/photoswipe/photoswipe.esm.js')
    });
    lightbox.init();

    return function cleanup() {
      lightbox.destroy();
      lightbox = null;
    };
  }, []);

  return (
    <div className="pswp-docs__home-gallery" id="gallery--header-home">
      <GalleryItem {...imagesData[0]}
        aspectRatio={1} 
        cropped={true}
        sizes="(min-width: 1124px) 524px, 50vw" />
      <GalleryItem {...imagesData[1]}
        aspectRatio={1} 
        cropped={true}
        sizes="(min-width: 1124px) 393px, 35vw" />
      <GalleryItem {...imagesData[2]}
        aspectRatio={1} 
        cropped={true}
        sizes="(min-width: 1124px) 393px, 35vw" />
      <GalleryItem {...imagesData[3]}
        aspectRatio={1}
        cropped={true}
        sizes="(min-width: 1124px) 393px, 35vw" />
      <GalleryItem {...imagesData[4]}
        aspectRatio={1} 
        cropped={true}
        sizes="(min-width: 1124px) 393px, 35vw" />
      <div className='pswp-docs__home-gallery-credit'>Photos by Luca Bravo</div>
    </div>
  );
}


================================================
FILE: demo-docs-website/src/pages/index.js
================================================
import React, { useEffect } from 'react';
import Layout from '@theme/Layout';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import GalleryHeader, { GalleryExampleDynamicCaptionPlugin, GalleryExampleOpenZoomed } from './_index-gallery-header';
import CodeBlock from '../theme/CodeBlock';
import packageInfo from '../../../package.json';
import DeepZoomGalleryDemo from './_index-deep-zoom-demo';
import Head from '@docusaurus/Head';

function HomepageHeader() {
  return (
    <div className="pswp-docs__home-block pswp-docs__header-intro container">
      <Head>
        <html className="pswp-docs__home" />
        <title>PhotoSwipe: Responsive JavaScript Image Gallery</title>
      </Head>
      <div className="row">
        <div className="col col--12 pswp-docs__header-title-text">
          <h1>PhotoSwipe <span>{packageInfo.version}</span></h1>
          <p>JavaScript image gallery and lightbox</p>
          <a href="/getting-started">Documentation and examples<svg viewBox="0 0 448 512"><path d="M438.6 278.6l-160 160C272.4 444.9 264.2 448 256 448s-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L338.8 288H32C14.33 288 .0016 273.7 .0016 256S14.33 224 32 224h306.8l-105.4-105.4c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l160 160C451.1 245.9 451.1 266.1 438.6 278.6z"/></svg></a>
        </div>
      </div>
      <div className="row">
        <div className="col col--12">
          <GalleryHeader />
        </div>
      </div>
    </div>
  );
}

function WhatsNew() {
  const initCodeExample = `<script type="module">
import Lightbox from './photoswipe-lightbox.esm.js';
const lightbox = new Lightbox({
  gallery: '#my-gallery',
  children: 'a',
  pswpModule: () => import('./photoswipe.esm.js')
});
lightbox.init();
</script>`;

  return (
    <div className="pswp-docs__home-block container pswp-docs__whats-new">
      <div className="row">
        <div className="col col--12 pswp-docs__home-block-main-col">
          <h2>What’s new in v5</h2>

          <h4>Code quality and rewrite in ES6</h4>
          <p>The script is now distributed as an ES module and does not require a build step to use. <a href="/getting-started">The documentation</a> is also updated and now includes more examples.</p>

          <h4>Simpler initialization and dynamic import support</h4>
          <p>PhotoSwipe now supports dynamic import and does not block page rendering.</p>
          <CodeBlock language="html">{initCodeExample}</CodeBlock>

          <h4>Animation and gesture engine update</h4>
          <p>Improved performance of most animations, touch gestures should feel more fluid now. 
            The initial opening or closing <a href="/opening-or-closing-transition#animating-from-cropped-thumbnail">transition can be run from a CSS-cropped thumbnail</a>, as you can see on the top of this page.</p>

          <h4>Single CSS file and no external assets</h4>
          <p>Using CSS variables, default icons are dynamically generated and tiny.<br/><a href="/styling">Styling guide &rarr;</a></p>

          <h4>Built-in responsive images support</h4>
          <p>PhotoSwipe also dynamically loads larger images as a user zooms via srcset.</p>

          <h4>Open images in a zoomed state</h4>
          <p>It's now much easier to control zoom level, refer to the <a href="/adjusting-zoom-level">Adjusting Zoom Level</a> section of docs for more info. The example below opens images in a zoomed state and individually.</p>
          <GalleryExampleOpenZoomed />

          <h4>Removed features from the core</h4>
          <p>Some built-in features were removed in v5, either because they are using outdated technology or just rarely used. Some of them are or will be replaced by a plugin. These include:</p>
          <ul>
            <li>History API (#hash-based navigation is outdated)</li>
            <li>Social sharing (unreliable URL, lack of Opengraph support)</li>
            <li>Fullscreen button (rarely used, double fullscreen). <a href="/native-fullscreen-on-open">Related example in docs &rarr;</a></li>
            <li>Caption (accessibility problems). Refer to the <a href="/caption">caption section of docs</a>.</li>
            <li>Inline gallery support (v5 is mainly designed to be used as a dialog).</li>
          </ul>

          <h2>Plugins</h2>

          <h4><a href="https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin">Dynamic Caption plugin</a></h4>
          
          <p>
            A plugin that dynamically positions the caption below or aside 
            depending on the available free space.<br/>
          </p>
          <GalleryExampleDynamicCaptionPlugin />

          <h4><a href="https://github.com/dimsemenov/photoswipe-deep-zoom-plugin">Tiled Deep Zoom plugin</a> (experimental)</h4>
          <p>
            Tile-based image viewer that allows displaying of extremely large images.
            Unlike conventional tile-viewers (such as Leaflet or OpenSeaDragon) 
            it displays tiles only after the user zooms beyond the primary image,
            and keeps all default PhotoSwipe navigation between slides.<br/>
          </p>
          <DeepZoomGalleryDemo />


          <h2>License</h2>

          <p>PhotoSwipe is free for personal or commercial projects (MIT license).<br/>Please <a href="https://opencollective.com/photoswipe">support the development on Open Collective</a> if you find it useful.</p>

        </div>
      </div>
    </div>
  );
}

export default function Home() {
  const {siteConfig} = useDocusaurusContext();
  return (
    <Layout
      description="Open-source JavaScript image gallery and lightbox.">
      <HomepageHeader />
      <WhatsNew />
    </Layout>
  );
}


================================================
FILE: demo-docs-website/src/pages/index.module.css
================================================
/**
 * CSS files with the .module.css suffix will be treated as CSS modules
 * and scoped locally.
 */

================================================
FILE: demo-docs-website/src/theme/CodeBlock/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React, {isValidElement, useEffect, useState} from 'react';
import clsx from 'clsx';
import Highlight, {defaultProps} from 'prism-react-renderer';
import {
  useThemeConfig,
  parseCodeBlockTitle,
  parseLanguage,
  parseLines,
  ThemeClassNames,
  usePrismTheme,
} from '@docusaurus/theme-common';
import styles from './styles.module.css';
export default function CodeBlock({
  children,
  className: blockClassName = '',
  metastring,
  title,
  pswpcode,
  pswpdisplayhtml,
  displayHTML,
  language: languageProp,
}) {
  const {prism} = useThemeConfig();
  const [mounted, setMounted] = useState(false); // The Prism theme on SSR is always the default theme but the site theme
  // can be in a different mode. React hydration doesn't update DOM styles
  // that come from SSR. Hence force a re-render after mounting to apply the
  // current relevant styles. There will be a flash seen of the original
  // styles seen using this current approach but that's probably ok. Fixing
  // the flash will require changing the theming approach and is not worth it
  // at this point.

  let esModuleScript;

  useEffect(() => {
    setMounted(true);
    if (pswpcode && language === 'js' && !esModuleScript) {
      esModuleScript = document.createElement('script');
      esModuleScript.type = 'module';
      esModuleScript.innerHTML = children;           
      document.body.appendChild(esModuleScript);
    }

    return () => {
      if (esModuleScript) {
        esModuleScript.remove();
        esModuleScript = null;
      }
    };
  }, []); // We still parse the metastring in case we want to support more syntax in the
  // future. Note that MDX doesn't strip quotes when parsing metastring:
  // "title=\"xyz\"" => title: "\"xyz\""

  const codeBlockTitle = parseCodeBlockTitle(metastring) || title;
  const prismTheme = usePrismTheme(); // <pre> tags in markdown map to CodeBlocks and they may contain JSX children.
  // When the children is not a simple string, we just return a styled block
  // without actually highlighting.

  if (React.Children.toArray(children).some((el) => isValidElement(el))) {
    return (
      <Highlight
        {...defaultProps}
        key={String(mounted)}
        theme={prismTheme}
        code=""
        language={'text'}>
        {({className, style}) => (
          <pre
            /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
            tabIndex={0}
            className={clsx(
              className,
              styles.codeBlockStandalone,
              'docs-styled-scrollbar',
              styles.codeBlockContainer,
              blockClassName,
              ThemeClassNames.common.codeBlock,
            )}
            style={style}>
            <code className={styles.codeBlockLines}>{children}</code>
          </pre>
        )}
      </Highlight>
    );
  } // The children is now guaranteed to be one/more plain strings

  const content = Array.isArray(children) ? children.join('') : children;
  const language =
    languageProp ?? parseLanguage(blockClassName) ?? prism.defaultLanguage;
  const {highlightLines, code} = parseLines(content, metastring, language);

  let hideCodeBlock = false;

  if (language === 'html' && pswpcode && !displayHTML && !pswpdisplayhtml) {
    hideCodeBlock = true;
  }
  

  return (
    <React.Fragment>
      {!hideCodeBlock && <Highlight
        {...defaultProps}
        key={String(mounted)}
        theme={prismTheme}
        code={code}
        language={language ?? 'text'}>
        {({className, style, tokens, getLineProps, getTokenProps}) => (
          <div
            className={clsx(
              styles.codeBlockContainer,
              blockClassName,
              hideCodeBlock ? 'theme-code-block--hidden' : '',
              {
                [`language-${language}`]:
                  language && !blockClassName.includes(`language-${language}`),
              },
              ThemeClassNames.common.codeBlock,
            )}>
            {codeBlockTitle && (
              <div style={style} className={styles.codeBlockTitle}>
                {codeBlockTitle}
              </div>
            )}
            <div className={clsx(styles.codeBlockContent, language)}>
              <pre
                /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
                tabIndex={0}
                className={clsx(className, styles.codeBlock, 'docs-styled-scrollbar')}
                style={style}>
                <code className={styles.codeBlockLines}>
                  {tokens.map((line, i) => {
                    if (line.length === 1 && line[0].content === '\n') {
                      line[0].content = '';
                    }

                    const lineProps = getLineProps({
                      line,
                      key: i,
                    });

                    if (highlightLines.includes(i)) {
                      lineProps.className += ' docusaurus-highlight-code-line';
                    }

                    return (
                      <span key={i} {...lineProps}>
                        {line.map((token, key) => (
                          <span
                            key={key}
                            {...getTokenProps({
                              token,
                              key,
                            })}
                          />
                        ))}
                        <br />
                      </span>
                    );
                  })}
                </code>
              </pre>
            </div>
          </div>
        )}
      </Highlight> }
      {language === 'css' && pswpcode &&
        <style>{children}</style>
      }
      {language === 'html' && pswpcode && 
        <div className="pswp-example__preview docs-styled-scrollbar" role="region" aria-label="Code preview" dangerouslySetInnerHTML={{__html: children}}></div>
      }
    </React.Fragment>
  );
}


================================================
FILE: demo-docs-website/src/theme/CodeBlock/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

.codeBlockContainer {
  margin-bottom: var(--ifm-leading);
}

.codeBlockContent {
  position: relative;
  /* rtl:ignore */
  direction: ltr;
}

.codeBlockContent pre {
  border-radius: 0;
}

.codeBlockTitle {
  border-bottom: 1px solid var(--ifm-color-emphasis-300);
  font-size: var(--ifm-code-font-size);
  font-weight: 500;
  padding: 0.75rem var(--ifm-pre-padding);
  border-top-left-radius: var(--ifm-global-radius);
  border-top-right-radius: var(--ifm-global-radius);
}

.codeBlock {
  margin: 0;
  padding: 0;
}

.codeBlockTitle + .codeBlockContent .codeBlock {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

.codeBlockStandalone {
  padding: 0;
  border-radius: var(--ifm-global-radius);
}

.codeBlockLines {
  font: inherit;
  /* rtl:ignore */
  float: left;
  min-width: 100%;
  padding: var(--ifm-pre-padding);
}

@media print {
  .codeBlockLines {
    white-space: pre-wrap;
  }
}


================================================
FILE: demo-docs-website/src/theme/DocItem/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React from 'react';
import clsx from 'clsx';
import DocPaginator from '@theme/DocPaginator';
import DocVersionBanner from '@theme/DocVersionBanner';
import DocVersionBadge from '@theme/DocVersionBadge';
import Seo from '@theme/Seo';
import DocItemFooter from '@theme/DocItemFooter';
import TOC from '@theme/TOC';
import TOCCollapsible from '@theme/TOCCollapsible';
import Heading from '@theme/Heading';
import styles from './styles.module.css';
import {ThemeClassNames, useWindowSize} from '@docusaurus/theme-common';
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
export default function DocItem(props) {
  const {content: DocContent} = props;
  const {metadata, frontMatter, assets} = DocContent;
  const {
    keywords,
    hide_title: hideTitle,
    hide_table_of_contents: hideTableOfContents,
    toc_min_heading_level: tocMinHeadingLevel,
    toc_max_heading_level: tocMaxHeadingLevel,
  } = frontMatter;
  const {description, title} = metadata;
  const image = assets.image ?? frontMatter.image; // We only add a title if:
  // - user asks to hide it with front matter
  // - the markdown content does not already contain a top-level h1 heading

  const shouldAddTitle =
    !hideTitle && typeof DocContent.contentTitle === 'undefined';
  const windowSize = useWindowSize();
  const canRenderTOC =
    !hideTableOfContents && DocContent.toc && DocContent.toc.length > 0;
  const renderTocDesktop =
    canRenderTOC && (windowSize === 'desktop' || windowSize === 'ssr');
  return (
    <>
      <Seo
        {...{
          title,
          description,
          keywords,
          image,
        }}
      />
    
      <DocVersionBanner />
        <article>
          <DocBreadcrumbs />
          <DocVersionBadge />

          <div
            className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
            {/*
            Title can be declared inside md content or declared through
            front matter and added manually. To make both cases consistent,
            the added title is added under the same div.markdown block
            See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120
            */}
            {shouldAddTitle && (
              <header>
                <Heading as="h1">{title}</Heading>
              </header>
            )}

            <DocContent />
          </div>

          <DocItemFooter {...props} />
        </article>
    </>
  );
}


================================================
FILE: demo-docs-website/src/theme/DocItem/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

.docItemContainer header + *,
.docItemContainer article > *:first-child {
  margin-top: 0;
}

@media (min-width: 997px) {
  /* Prevent hydration FOUC, as the mobile TOC needs to be server-rendered */
  .tocMobile {
    display: none;
  }
}


================================================
FILE: demo-docs-website/src/theme/DocItemFooter/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React from 'react';
import clsx from 'clsx';
import LastUpdated from '@theme/LastUpdated';
import EditThisPage from '@theme/EditThisPage';
import TagsListInline from '@theme/TagsListInline';
import styles from './styles.module.css';
import {ThemeClassNames} from '@docusaurus/theme-common';

function TagsRow(props) {
  return (
    <div
      className={clsx(
        ThemeClassNames.docs.docFooterTagsRow,
        'row margin-bottom--sm',
      )}>
      <div className="col">
        <TagsListInline {...props} />
      </div>
    </div>
  );
}

function EditMetaRow({
  editUrl,
  lastUpdatedAt,
  lastUpdatedBy,
  formattedLastUpdatedAt,
}) {
  return (
    <div className={clsx(ThemeClassNames.docs.docFooterEditMetaRow, 'row')}>
      <div className="col">
        {editUrl && <EditThisPage editUrl={editUrl} />}
        <br/>
        Updates on <a href="https://twitter.com/photoswipe">Twitter</a>
        <br/>  
        Code on <a href="https://github.com/dimsemenov/photoswipe">GitHub</a>
        <br/>
        Sponsor on <a href="https://opencollective.com/photoswipe">Open Collective</a>
      </div>

      <div className={clsx('col', styles.lastUpdated)}>
        {(lastUpdatedAt || lastUpdatedBy) && (
          <LastUpdated
            lastUpdatedAt={lastUpdatedAt}
            formattedLastUpdatedAt={formattedLastUpdatedAt}
            lastUpdatedBy={lastUpdatedBy}
          />
        )}
      </div>
    </div>
  );
}

export default function DocItemFooter(props) {
  const {content: DocContent} = props;
  const {metadata} = DocContent;
  const {editUrl, lastUpdatedAt, formattedLastUpdatedAt, lastUpdatedBy, tags} =
    metadata;
  const canDisplayTagsRow = tags.length > 0;
  const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy);
  const canDisplayFooter = canDisplayTagsRow || canDisplayEditMetaRow;

  if (!canDisplayFooter) {
    return null;
  }

  return (
    <footer
      className={clsx(ThemeClassNames.docs.docFooter, 'docusaurus-mt-lg')}>
      {canDisplayTagsRow && <TagsRow tags={tags} />}
      {canDisplayEditMetaRow && (
        <EditMetaRow
          editUrl={editUrl}
          lastUpdatedAt={lastUpdatedAt}
          lastUpdatedBy={lastUpdatedBy}
          formattedLastUpdatedAt={formattedLastUpdatedAt}
        />
      )}
    </footer>
  );
}


================================================
FILE: demo-docs-website/src/theme/DocItemFooter/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

.lastUpdated {
  margin-top: 0.2rem;
  font-style: italic;
  font-size: smaller;
}

@media (min-width: 997px) {
  .lastUpdated {
    text-align: right;
  }
}


================================================
FILE: demo-docs-website/src/theme/DocPage/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React, {useState, useCallback} from 'react';
import {MDXProvider} from '@mdx-js/react';
import renderRoutes from '@docusaurus/renderRoutes';
import Layout from '@theme/Layout';
import DocSidebar from '@theme/DocSidebar';
import MDXComponents from '@theme/MDXComponents';
import NotFound from '@theme/NotFound';
import IconArrow from '@theme/IconArrow';
import {matchPath} from '@docusaurus/router';
import {translate} from '@docusaurus/Translate';
import clsx from 'clsx';
import styles from './styles.module.css';
import {
  ThemeClassNames,
  docVersionSearchTag,
  DocsSidebarProvider,
  useDocsSidebar,
  DocsVersionProvider,
} from '@docusaurus/theme-common';
import Head from '@docusaurus/Head';

function DocPageContent({
  currentDocRoute,
  versionMetadata,
  children,
  sidebarName,
}) {
  const sidebar = useDocsSidebar();
  const {pluginId, version} = versionMetadata;
  const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false);
  const [hiddenSidebar, setHiddenSidebar] = useState(false);
  const toggleSidebar = useCallback(() => {
    if (hiddenSidebar) {
      setHiddenSidebar(false);
    }

    setHiddenSidebarContainer((value) => !value);
  }, [hiddenSidebar]);
  return (
    <Layout
      wrapperClassName={ThemeClassNames.wrapper.docsPages}
      pageClassName={ThemeClassNames.page.docsDocPage}
      searchMetadata={{
        version,
        tag: docVersionSearchTag(pluginId, version),
      }}>
        {sidebar && (
          <aside
            className={clsx(
              ThemeClassNames.docs.docSidebarContainer,
              styles.docSidebarContainer,
              {
                [styles.docSidebarContainerHidden]: hiddenSidebarContainer,
              },
            )}
            onTransitionEnd={(e) => {
              if (
                !e.currentTarget.classList.contains(styles.docSidebarContainer)
              ) {
                return;
              }

              if (hiddenSidebarContainer) {
                setHiddenSidebar(true);
              }
            }}>
            <DocSidebar
              key={
                // Reset sidebar state on sidebar changes
                // See https://github.com/facebook/docusaurus/issues/3414
                sidebarName
              }
              sidebar={sidebar}
              path={currentDocRoute.path}
              onCollapse={toggleSidebar}
              isHidden={hiddenSidebar}
            />

            {hiddenSidebar && (
              <div
                className={styles.collapsedDocSidebar}
                title={translate({
                  id: 'theme.docs.sidebar.expandButtonTitle',
                  message: 'Expand sidebar',
                  description:
                    'The ARIA label and title attribute for expand button of doc sidebar',
                })}
                aria-label={translate({
                  id: 'theme.docs.sidebar.expandButtonAriaLabel',
                  message: 'Expand sidebar',
                  description:
                    'The ARIA label and title attribute for expand button of doc sidebar',
                })}
                tabIndex={0}
                role="button"
                onKeyDown={toggleSidebar}
                onClick={toggleSidebar}>
                <IconArrow className={styles.expandSidebarButtonIcon} />
              </div>
            )}
          </aside>
        )}
        <main
          className={clsx('pswp-docs__main-column container padding-top--md padding-bottom--lg', styles.docMainContainer, {
            [styles.docMainContainerEnhanced]:
              hiddenSidebarContainer || !sidebar,
          })}>
            <MDXProvider components={MDXComponents}>{children}</MDXProvider>
        </main>
    </Layout>
  );
}

export default function DocPage(props) {
  const {
    route: {routes: docRoutes},
    versionMetadata,
    location,
  } = props;
  const currentDocRoute = docRoutes.find((docRoute) =>
    matchPath(location.pathname, docRoute),
  );

  if (!currentDocRoute) {
    return <NotFound />;
  } // For now, the sidebarName is added as route config: not ideal!

  const sidebarName = currentDocRoute.sidebar;
  const sidebar = sidebarName
    ? versionMetadata.docsSidebars[sidebarName]
    : null;
  return (
    <>
      <Head>
        {/* TODO we should add a core addRoute({htmlClassName}) action */}
        <html className={versionMetadata.className} />
      </Head>
      <DocsVersionProvider version={versionMetadata}>
        <DocsSidebarProvider sidebar={sidebar}>
          <DocPageContent
            currentDocRoute={currentDocRoute}
            versionMetadata={versionMetadata}
            sidebarName={sidebarName}>
            {renderRoutes(docRoutes, {
              versionMetadata,
            })}
          </DocPageContent>
        </DocsSidebarProvider>
      </DocsVersionProvider>
    </>
  );
}


================================================
FILE: demo-docs-website/src/theme/DocPage/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

================================================
FILE: demo-docs-website/src/theme/DocSidebar/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React, {useState} from 'react';
import clsx from 'clsx';
import {useLocation} from '@docusaurus/router';


import {
  useThemeConfig,
  useAnnouncementBar,
  MobileSecondaryMenuFiller,
  ThemeClassNames,
  useScrollPosition,
  useWindowSize,
} from '@docusaurus/theme-common';

import styles from './styles.module.css';

function useShowAnnouncementBar() {
  const {isActive} = useAnnouncementBar();
  const [showAnnouncementBar, setShowAnnouncementBar] = useState(isActive);
  useScrollPosition(
    ({scrollY}) => {
      if (isActive) {
        setShowAnnouncementBar(scrollY === 0);
      }
    },
    [isActive],
  );
  return isActive && showAnnouncementBar;
}

function SimpleSidebarCategory(props) {
  return (
    <div className="pswp-docs__sidebar-menu-item pswp-docs__sidebar-menu-item--category">{props.label}</div>
  );
}
function SimpleSidebarItem(props) {
  const location = useLocation();
  const isActive = (props.href.toLowerCase() === location.pathname.toLowerCase());
    return (
    <a href={props.href} className={clsx(
      'pswp-docs__sidebar-menu-item',
      (isActive ? 'pswp-docs__sidebar-menu-item--active' : '')
    )}>{props.label}</a>
  );
}
function SimpleSidebar(props) {
  const sidebarItems = [];

  let index = 0;
  props.sidebar.forEach((sidebarItem) => {
    if (sidebarItem.type === 'category') {
      sidebarItems.push(<SimpleSidebarCategory {...sidebarItem} key={index} />);
      index++;

      sidebarItem.items.forEach((subItem) => {
        sidebarItems.push(<SimpleSidebarItem {...subItem} key={index} />);
        index++;
      });
    } else if (sidebarItem.type === 'link') {
      sidebarItems.push(<SimpleSidebarItem {...sidebarItem} key={index} />);
      index++;
    }
  });

  return (
    <>
      {sidebarItems}
    </>
  );
}

function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) {
  const showAnnouncementBar = useShowAnnouncementBar();
  const {
    navbar: {hideOnScroll},
    hideableSidebar,
  } = useThemeConfig();
  
  return (
    <div className="pswp-docs__sidebar-menu">
      <SimpleSidebar sidebar={sidebar} />
    </div>
  );
} // eslint-disable-next-line react/function-component-definition

const DocSidebarMobileSecondaryMenu = ({toggleSidebar, sidebar, path}) => (
  <div className="pswp-docs__sidebar-menu pswp-docs__sidebar-menu--mobile">
    <SimpleSidebar sidebar={sidebar} />
  </div>
);

function DocSidebarMobile(props) {
  return (
    <MobileSecondaryMenuFiller
      component={DocSidebarMobileSecondaryMenu}
      props={props}
    />
  );
}

const DocSidebarDesktopMemo = React.memo(DocSidebarDesktop);
const DocSidebarMobileMemo = React.memo(DocSidebarMobile);
export default function DocSidebar(props) {
  const windowSize = useWindowSize(); // Desktop sidebar visible on hydration: need SSR rendering

  const shouldRenderSidebarDesktop =
    windowSize === 'desktop' || windowSize === 'ssr'; // Mobile sidebar not visible on hydration: can avoid SSR rendering

  const shouldRenderSidebarMobile = windowSize === 'mobile';
  return (
    <>
      {shouldRenderSidebarDesktop && <DocSidebarDesktopMemo {...props} />}
      {shouldRenderSidebarMobile && <DocSidebarMobileMemo {...props} />}
    </>
  );
}


================================================
FILE: demo-docs-website/src/theme/DocSidebar/is-same-path.ts
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

// Compare the 2 paths, case insensitive and ignoring trailing slash
export const isSamePath = (
  path1: string | undefined,
  path2: string | undefined,
): boolean => {
  const normalize = (pathname: string | undefined) =>
    (!pathname || pathname?.endsWith('/')
      ? pathname
      : `${pathname}/`
    )?.toLowerCase();
  return normalize(path1) === normalize(path2);
};

================================================
FILE: demo-docs-website/src/theme/DocSidebar/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

:root {
  --collapse-button-bg-color-dark: #2e333a;
}

@media (min-width: 997px) {
  .sidebar {
    display: flex;
    flex-direction: column;
    max-height: 100vh;
    height: 100%;
    position: sticky;
    top: 0;
    padding-top: var(--ifm-navbar-height);
    transition: opacity 50ms ease;
  }

  .sidebarWithHideableNavbar {
    padding-top: 0;
  }

  .sidebarHidden {
    opacity: 0;
    height: 0;
    overflow: hidden;
    visibility: hidden;
  }

  .sidebarLogo {
    display: flex !important;
    align-items: center;
    margin: 0 var(--ifm-navbar-padding-horizontal);
    min-height: var(--ifm-navbar-height);
    max-height: var(--ifm-navbar-height);
    color: inherit !important;
    text-decoration: none !important;
  }

  .sidebarLogo img {
    margin-right: 0.5rem;
    height: 2rem;
  }

  .menu {
    flex-grow: 1;
    padding: 0.5rem;
  }

  .menuWithAnnouncementBar {
    margin-bottom: var(--docusaurus-announcement-bar-height);
  }

  .collapseSidebarButton {
    display: block !important;
    background-color: var(--ifm-button-background-color);
    height: 40px;
    position: sticky;
    bottom: 0;
    border-radius: 0;
    border: 1px solid var(--ifm-toc-border-color);
  }

  .collapseSidebarButtonIcon {
    transform: rotate(180deg);
    margin-top: 4px;
  }

  [dir='rtl'] .collapseSidebarButtonIcon {
    transform: rotate(0);
  }

  [data-theme='dark'] .collapseSidebarButton {
    background-color: var(--collapse-button-bg-color-dark);
  }

  [data-theme='dark'] .collapseSidebarButton:hover,
  [data-theme='dark'] .collapseSidebarButton:focus {
    background-color: var(--ifm-color-emphasis-200);
  }
}

.sidebarLogo,
.collapseSidebarButton {
  display: none;
}

.sidebarMenuIcon {
  vertical-align: middle;
}

.sidebarMenuCloseIcon {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  height: 24px;
  font-size: 1.5rem;
  font-weight: var(--ifm-font-weight-bold);
  line-height: 0.9;
  width: 24px;
}


================================================
FILE: demo-docs-website/src/theme/EditThisPage/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React from 'react';
import {ThemeClassNames} from '@docusaurus/theme-common';
export default function EditThisPage({editUrl}) {
  return (
    <>Found a typo? <a href={editUrl}
        target="_blank"
        rel="noreferrer noopener"
        className={ThemeClassNames.common.editThisPage}>Edit this page</a></>
  );
}


================================================
FILE: demo-docs-website/src/theme/Footer/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import {useThemeConfig} from '@docusaurus/theme-common';
import useBaseUrl from '@docusaurus/useBaseUrl';
import styles from './styles.module.css';
import ThemedImage from '@theme/ThemedImage';

function FooterLogo({sources, alt, width, height}) {
  return (
    <ThemedImage
      className="footer__logo"
      alt={alt}
      sources={sources}
      width={width}
      height={height}
    />
  );
}

function Footer() {
  const {footer} = useThemeConfig();
  const {copyright, links = [], logo = {}} = footer || {};
  const sources = {
    light: useBaseUrl(logo.src),
    dark: useBaseUrl(logo.srcDark || logo.src),
  };

  if (!footer) {
    return null;
  }

  return (
    <footer
      className={'footer'}>
      <div className="container container-fluid">
        {(logo || copyright) && (
          <div className="footer__bottom text--center">
            {copyright ? (
              <div
                className="footer__copyright" // Developer provided the HTML, so assume it's safe.
                // eslint-disable-next-line react/no-danger
                dangerouslySetInnerHTML={{
                  __html: copyright,
                }}
              />
            ) : null}
          </div>
        )}
      </div>
    </footer>
  );
}

export default React.memo(Footer);


================================================
FILE: demo-docs-website/src/theme/Footer/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

.footerLogoLink {
  opacity: 0.5;
  transition: opacity var(--ifm-transition-fast)
    var(--ifm-transition-timing-default);
}

.footerLogoLink:hover {
  opacity: 1;
}


================================================
FILE: demo-docs-website/src/theme/Logo/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React from 'react';
import Link from '@docusaurus/Link';
import ThemedImage from '@theme/ThemedImage';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import {useThemeConfig} from '@docusaurus/theme-common';
import packageInfo from '../../../../package.json';

export default function Logo(props) {
  const {
    siteConfig: {title},
  } = useDocusaurusContext();
  const {
    navbar: {
      title: navbarTitle,
      logo = {
        src: '',
      },
    },
  } = useThemeConfig();
  const {imageClassName, titleClassName, ...propsRest} = props;
  const logoLink = useBaseUrl(logo.href || '/');
  const sources = {
    light: useBaseUrl(logo.src),
    dark: useBaseUrl(logo.srcDark || logo.src),
  };
  const themedImage = (
    <ThemedImage
      sources={sources}
      height={logo.height}
      width={logo.width}
      alt={logo.alt || navbarTitle || title}
    />
  );
  return (
    <Link
      to={logoLink}
      {...propsRest}
      {...(logo.target && {
        target: logo.target,
      })}>
      {logo.src &&
        (imageClassName ? (
          <div className={imageClassName}>{themedImage}</div>
        ) : (
          themedImage
        ))}
      {navbarTitle != null && <b className={titleClassName}>{navbarTitle}</b>}
      <span>{packageInfo.version}</span>
    </Link>
  );
}


================================================
FILE: demo-docs-website/src/theme/MDXComponents/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React, {isValidElement} from 'react';
import Head from '@docusaurus/Head';
import Link from '@docusaurus/Link';
import CodeBlock from '@theme/CodeBlock';
import Heading from '@theme/Heading';
import Details from '@theme/Details';
import PswpCodePreview from '@site/src/components/PswpCodePreview';

import './styles.css'; // MDX elements are wrapped through the MDX pragma. In some cases (notably usage
// with Head/Helmet) we need to unwrap those elements.

function unwrapMDXElement(element) {
  if (element?.props?.mdxType && element?.props?.originalType) {
    const {mdxType, originalType, ...newProps} = element.props;
    return React.createElement(element.props.originalType, newProps);
  }

  return element;
}

const MDXComponents = {
  head: (props) => {
    const unwrappedChildren = React.Children.map(props.children, (child) =>
      unwrapMDXElement(child),
    );
    return <Head {...props}>{unwrappedChildren}</Head>;
  },
  code: (props) => {
    const inlineElements = [
      'a',
      'b',
      'big',
      'i',
      'span',
      'em',
      'strong',
      'sup',
      'sub',
      'small',
    ];
    const shouldBeInline = React.Children.toArray(props.children).every(
      (el) =>
        (typeof el === 'string' && !el.includes('\n')) ||
        (React.isValidElement(el) && inlineElements.includes(el.props.mdxType)),
    );
    return shouldBeInline ? <code {...props} /> : <CodeBlock {...props} />;
  },
  a: (props) => <Link {...props} />,
  pre: (props) => (
    <CodeBlock // If this pre is created by a ``` fenced codeblock, unwrap the children
      {...(isValidElement(props.children) &&
      props.children.props.originalType === 'code'
        ? props.children?.props
        : {...props})}
    />
  ),
  details: (props) => {
    const items = React.Children.toArray(props.children); // Split summary item from the rest to pass it as a separate prop to the
    // Details theme component

    const summary = items.find((item) => item?.props?.mdxType === 'summary');
    const children = <>{items.filter((item) => item !== summary)}</>;
    return (
      <Details {...props} summary={summary}>
        {children}
      </Details>
    );
  },
  h1: (props) => <Heading as="h1" {...props} />,
  h2: (props) => <Heading as="h2" {...props} />,
  h3: (props) => <Heading as="h3" {...props} />,
  h4: (props) => <Heading as="h4" {...props} />,
  h5: (props) => <Heading as="h5" {...props} />,
  h6: (props) => <Heading as="h6" {...props} />,
  PswpCodePreview: (props) => <PswpCodePreview {...props} />
};
export default MDXComponents;


================================================
FILE: demo-docs-website/src/theme/MDXComponents/styles.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

ul.contains-task-list {
  padding-left: 0;
  list-style: none;
}

img {
  height: auto;
}


================================================
FILE: demo-docs-website/src/theme/Navbar/github-stars.js
================================================
import React from 'react'

import repoData from '../../../repo-data.json';

export default function ReactGithubStars() {
  return (
    <a href="https://github.com/dimsemenov/photoswipe" className="pswp-docs__github-link">
      <span className="pswp-docs__github-link-left">Github</span>
      <span className='pswp-docs__github-link-right'>
        <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16">
          <path fillRule="evenodd" d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25zm0 2.445L6.615 5.5a.75.75 0 01-.564.41l-3.097.45 2.24 2.184a.75.75 0 01.216.664l-.528 3.084 2.769-1.456a.75.75 0 01.698 0l2.77 1.456-.53-3.084a.75.75 0 01.216-.664l2.24-2.183-3.096-.45a.75.75 0 01-.564-.41L8 2.694v.001z"></path>
        </svg>
        <span className="pswp-docs__github-link-star-count">{
          (repoData 
            && repoData.stargazers_count
            && parseInt(repoData.stargazers_count, 10) > 100) ? parseInt(repoData.stargazers_count, 10).toLocaleString() : ''
        }</span>
      </span>
    </a>
  )
}


================================================
FILE: demo-docs-website/src/theme/Navbar/index.js
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
import React, { useCallback, useState, useEffect } from "react";
import clsx from "clsx";
import Translate from "@docusaurus/Translate";
import ColorModeToggle from "@theme/ColorModeToggle";
import {
  useThemeConfig,
  useMobileSecondaryMenuRenderer,
  usePrevious,
  useHistoryPopHandler,
  useHideableNavbar,
  useLockBodyScroll,
  useWindowSize,
  useColorMode,
} from "@docusaurus/theme-common";
import { useActivePlugin } from "@docusaurus/plugin-content-docs/client";
import NavbarItem from "@theme/NavbarItem";
import Logo from "@theme/Logo";
import IconMenu from "@theme/IconMenu";
import IconClose from "@theme/IconClose";
import styles from "./styles.module.css"; // retrocompatible with v1
import ReactGithubStars from "./github-stars";

import { DocSearch } from "@docsearch/react";

import "@docsearch/css";

const DefaultNavItemPosition = "right";

function useNavbarItems() {
  // TODO temporary casting until ThemeConfig type is improved
  return useThemeConfig().navbar.items;
} // If split links by left/right
// if position is unspecified, fallback to right (as v1)

function splitNavItemsByPosition(items) {
  const leftItems = items.filter(
    (item) => (item.position ?? DefaultNavItemPosition) === "left"
  );
  const rightItems = items.filter(
    (item) => (item.position ?? DefaultNavItemPosition) === "right"
  );
  return {
    leftItems,
    rightItems,
  };
}

function useMobileSidebar() {
  const windowSize = useWindowSize(); // Mobile sidebar not visible on hydration: can avoid SSR rendering

  const shouldRender = windowSize === "mobile"; // || windowSize === 'ssr';

  const [shown, setShown] = useState(false); // Close mobile sidebar on navigation pop
  // Most likely firing when using the Android back button (but not only)

  useHistoryPopHandler(() => {
    if (shown) {
      setShown(false); // Should we prevent the navigation here?
      // See https://github.com/facebook/docusaurus/pull/5462#issuecomment-911699846

      return false; // prevent pop navigation
    }

    return undefined;
  });
  const toggle = useCallback(() => {
    setShown((s) => !s);
  }, []);
  useEffect(() => {
    if (windowSize === "desktop") {
      setShown(false);
    }
  }, [windowSize]);
  return {
    shouldRender,
    toggle,
    shown,
  };
}

function useColorModeToggle() {
  const {
    colorMode: { disableSwitch },
  } = useThemeConfig();
  const { isDarkTheme, setLightTheme, setDarkTheme } = useColorMode();
  const toggle = useCallback(
    (e) => (e.target.checked ? setDarkTheme() : setLightTheme()),
    [setLightTheme, setDarkTheme]
  );
  return {
    isDarkTheme,
    toggle,
    disabled: disableSwitch,
  };
}

const TwitterLink = () => {
  return (
    <a
      className="navbar__item navbar__link"
      href="https://twitter.com/photoswipe"
    >
      Twitter
    </a>
  );
};

function useSecondaryMenu({ sidebarShown, toggleSidebar }) {
  const content = useMobileSecondaryMenuRenderer()?.({
    toggleSidebar,
  });
  const previousContent = usePrevious(content);
  const [shown, setShown] = useState(
    () =>
      // /!\ content is set with useEffect,
      // so it's not available on mount anyway
      // "return !!content" => always returns false
      false
  ); // When content is become available for the first time (set in useEffect)
  // we set this content to be shown!

  useEffect(() => {
    const contentBecameAvailable = content && !previousContent;

    if (contentBecameAvailable) {
      setShown(true);
    }
  }, [content, previousContent]);
  const hasContent = !!content; // On sidebar close, secondary menu is set to be shown on next re-opening
  // (if any secondary menu content available)

  useEffect(() => {
    if (!hasContent) {
      setShown(false);
      return;
    }

    if (!sidebarShown) {
      setShown(true);
    }
  }, [sidebarShown, hasContent]);
  const hide = useCallback(() => {
    setShown(false);
  }, []);
  return {
    shown,
    hide,
    content,
  };
}

function NavbarMobileSidebar({ sidebarShown, toggleSidebar }) {
  useLockBodyScroll(sidebarShown);
  const items = useNavbarItems();
  const colorModeToggle = useColorModeToggle();
  const secondaryMenu = useSecondaryMenu({
    sidebarShown,
    toggleSidebar,
  });
  return (
    <div className="navbar-sidebar">
      <div className="navbar-sidebar__brand">
        <Logo
          className="navbar__brand"
          imageClassName="navbar__logo"
          titleClassName="navbar__title"
        />
        {!colorModeToggle.disabled && (
          <ColorModeToggle
            className={styles.navbarSidebarToggle}
            checked={colorModeToggle.isDarkTheme}
            onChange={colorModeToggle.toggle}
          />
        )}
        <button
          type="button"
          className="clean-btn navbar-sidebar__close"
          onClick={toggleSidebar}
        >
          <IconClose
            color="var(--ifm-color-emphasis-600)"
            className={styles.navbarSidebarCloseSvg}
          />
        </button>
      </div>

      <div
        className={clsx("navbar-sidebar__items", {
          "navbar-sidebar__items--show-secondary": secondaryMenu.shown,
        })}
      >
        <div className="navbar-sidebar__item menu">
          <ul className="menu__list">
            {items.map((item, i) => (
              <NavbarItem mobile {...item} onClick={toggleSidebar} key={i} />
            ))}
          </ul>
        </div>

        <div className="navbar-sidebar__item menu">
          {items.length > 0 && (
            <button
              type="button"
              className="clean-btn navbar-sidebar__back"
              onClick={secondaryMenu.hide}
            >
              <Translate
                id="theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel"
                description="The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
              >
                ← Back to main menu
              </Translate>
            </button>
          )}
          {secondaryMenu.content}
        </div>
      </div>
    </div>
  );
}

export default function Navbar() {
  const {
    navbar: { hideOnScroll, style },
  } = useThemeConfig();
  const mobileSidebar = useMobileSidebar();
  const colorModeToggle = useColorModeToggle();
  const activeDocPlugin = useActivePlugin();
  const { navbarRef, isNavbarVisible } = useHideableNavbar(hideOnScroll);
  const items = useNavbarItems();
  const { leftItems, rightItems } = splitNavItemsByPosition(items);
  return (
    <nav
      ref={navbarRef}
      className={clsx("navbar", {
        "navbar--dark": style === "dark",
        "navbar--primary": style === "primary",
        "navbar-sidebar--show": mobileSidebar.shown,
        [styles.navbarHideable]: hideOnScroll,
        [styles.navbarHidden]: hideOnScroll && !isNavbarVisible,
      })}
    >
      <div className="navbar__inner">
        <div className="navbar__items">
          {(items?.length > 0 || activeDocPlugin) && (
            <button
              aria-label="Navigation bar toggle"
              className="navbar__toggle clean-btn"
              type="button"
              tabIndex={0}
              onClick={mobileSidebar.toggle}
              onKeyDown={mobileSidebar.toggle}
            >
              <IconMenu />
            </button>
          )}
          <Logo
            className="navbar__brand"
            imageClassName="navbar__logo"
            titleClassName="navbar__title"
          />
          {leftItems.map((item, i) => (
            <NavbarItem {...item} key={i} />
          ))}
          <DocSearch
            appId="M9RBCSJL4H"
            indexName="photoswipe"
            apiKey="a8151d869decf80b4e64c7103b1ea00a"
          />
          <div
            className="v6-feedback"
            style={{ fontWeight: 700, marginLeft: 4 }}
          >
            <a href="https://github.com/dimsemenov/PhotoSwipe/discussions/2170">
              v6 feedback
            </a>
          </div>
        </div>
        <div className="navbar__items navbar__items--right">
          <TwitterLink />
          <ReactGithubStars />
          {rightItems.map((item, i) => (
            <NavbarItem {...item} key={i} />
          ))}
          {!colorModeToggle.disabled && (
            <ColorModeToggle
              className={styles.toggle}
              checked={colorModeToggle.isDarkTheme}
              onChange={colorModeToggle.toggle}
            />
          )}
        </div>
      </div>

      <div
        role="presentation"
        className="navbar-sidebar__backdrop"
        onClick={mobileSidebar.toggle}
      />

      {mobileSidebar.shouldRender && (
        <NavbarMobileSidebar
          sidebarShown={mobileSidebar.shown}
          toggleSidebar={mobileSidebar.toggle}
        />
      )}
    </nav>
  );
}


================================================
FILE: demo-docs-website/src/theme/Navbar/styles.module.css
================================================
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/*
Hide toggle in small viewports
 */
@media (max-width: 996px) {
  .toggle {
    display: none;
  }
}

.navbarHideable {
  transition: transform var(--ifm-transition-fast) ease;
}

.navbarHidden {
  transform: translate3d(0, calc(-100% - 2px), 0);
}

.navbarSidebarToggle {
  margin-right: 1rem;
}


================================================
FILE: demo-docs-website/static/.nojekyll
================================================


================================================
FILE: demo-docs-website/static/photoswipe/photoswipe-lightbox.esm.js
================================================
/*!
  * PhotoSwipe Lightbox 5.4.4 - https://photoswipe.com
  * (c) 2024 Dmytro Semenov
  */
/** @typedef {import('../photoswipe.js').Point} Point */

/**
 * @template {keyof HTMLElementTagNameMap} T
 * @param {string} className
 * @param {T} tagName
 * @param {Node} [appendToEl]
 * @returns {HTMLElementTagNameMap[T]}
 */
function createElement(className, tagName, appendToEl) {
  const el = document.createElement(tagName);

  if (className) {
    el.className = className;
  }

  if (appendToEl) {
    appendToEl.appendChild(el);
  }

  return el;
}
/**
 * Get transform string
 *
 * @param {number} x
 * @param {number} [y]
 * @param {number} [scale]
 * @returns {string}
 */

function toTransformString(x, y, scale) {
  let propValue = `translate3d(${x}px,${y || 0}px,0)`;

  if (scale !== undefined) {
    propValue += ` scale3d(${scale},${scale},1)`;
  }

  return propValue;
}
/**
 * Apply width and height CSS properties to element
 *
 * @param {HTMLElement} el
 * @param {string | number} w
 * @param {string | number} h
 */

function setWidthHeight(el, w, h) {
  el.style.width = typeof w === 'number' ? `${w}px` : w;
  el.style.height = typeof h === 'number' ? `${h}px` : h;
}
/** @typedef {LOAD_STATE[keyof LOAD_STATE]} LoadState */

/** @type {{ IDLE: 'idle'; LOADING: 'loading'; LOADED: 'loaded'; ERROR: 'error' }} */

const LOAD_STATE = {
  IDLE: 'idle',
  LOADING: 'loading',
  LOADED: 'loaded',
  ERROR: 'error'
};
/**
 * Check if click or keydown event was dispatched
 * with a special key or via mouse wheel.
 *
 * @param {MouseEvent | KeyboardEvent} e
 * @returns {boolean}
 */

function specialKeyUsed(e) {
  return 'button' in e && e.button === 1 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey;
}
/**
 * Parse `gallery` or `children` options.
 *
 * @param {import('../photoswipe.js').ElementProvider} [option]
 * @param {string} [legacySelector]
 * @param {HTMLElement | Document} [parent]
 * @returns HTMLElement[]
 */

function getElementsFromOption(option, legacySelector, parent = document) {
  /** @type {HTMLElement[]} */
  let elements = [];

  if (option instanceof Element) {
    elements = [option];
  } else if (option instanceof NodeList || Array.isArray(option)) {
    elements = Array.from(option);
  } else {
    const selector = typeof option === 'string' ? option : legacySelector;

    if (selector) {
      elements = Array.from(parent.querySelectorAll(selector));
    }
  }

  return elements;
}
/**
 * Check if variable is PhotoSwipe class
 *
 * @param {any} fn
 * @returns {boolean}
 */

function isPswpClass(fn) {
  return typeof fn === 'function' && fn.prototype && fn.prototype.goTo;
}
/**
 * Check if browser is Safari
 *
 * @returns {boolean}
 */

function isSafari() {
  return !!(navigator.vendor && navigator.vendor.match(/apple/i));
}

/** @typedef {import('../lightbox/lightbox.js').default} PhotoSwipeLightbox */

/** @typedef {import('../photoswipe.js').default} PhotoSwipe */

/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */

/** @typedef {import('../photoswipe.js').DataSource} DataSource */

/** @typedef {import('../ui/ui-element.js').UIElementData} UIElementData */

/** @typedef {import('../slide/content.js').default} ContentDefault */

/** @typedef {import('../slide/slide.js').default} Slide */

/** @typedef {import('../slide/slide.js').SlideData} SlideData */

/** @typedef {import('../slide/zoom-level.js').default} ZoomLevel */

/** @typedef {import('../slide/get-thumb-bounds.js').Bounds} Bounds */

/**
 * Allow adding an arbitrary props to the Content
 * https://photoswipe.com/custom-content/#using-webp-image-format
 * @typedef {ContentDefault & Record<string, any>} Content
 */

/** @typedef {{ x?: number; y?: number }} Point */

/**
 * @typedef {Object} PhotoSwipeEventsMap https://photoswipe.com/events/
 *
 *
 * https://photoswipe.com/adding-ui-elements/
 *
 * @prop {undefined} uiRegister
 * @prop {{ data: UIElementData }} uiElementCreate
 *
 *
 * https://photoswipe.com/events/#initialization-events
 *
 * @prop {undefined} beforeOpen
 * @prop {undefined} firstUpdate
 * @prop {undefined} initialLayout
 * @prop {undefined} change
 * @prop {undefined} afterInit
 * @prop {undefined} bindEvents
 *
 *
 * https://photoswipe.com/events/#opening-or-closing-transition-events
 *
 * @prop {undefined} openingAnimationStart
 * @prop {undefined} openingAnimationEnd
 * @prop {undefined} closingAnimationStart
 * @prop {undefined} closingAnimationEnd
 *
 *
 * https://photoswipe.com/events/#closing-events
 *
 * @prop {undefined} close
 * @prop {undefined} destroy
 *
 *
 * https://photoswipe.com/events/#pointer-and-gesture-events
 *
 * @prop {{ originalEvent: PointerEvent }} pointerDown
 * @prop {{ originalEvent: PointerEvent }} pointerMove
 * @prop {{ originalEvent: PointerEvent }} pointerUp
 * @prop {{ bgOpacity: number }} pinchClose can be default prevented
 * @prop {{ panY: number }} verticalDrag can be default prevented
 *
 *
 * https://photoswipe.com/events/#slide-content-events
 *
 * @prop {{ content: Content }} contentInit
 * @prop {{ content: Content; isLazy: boolean }} contentLoad can be default prevented
 * @prop {{ content: Content; isLazy: boolean }} contentLoadImage can be default prevented
 * @prop {{ content: Content; slide: Slide; isError?: boolean }} loadComplete
 * @prop {{ content: Content; slide: Slide }} loadError
 * @prop {{ content: Content; width: number; height: number }} contentResize can be default prevented
 * @prop {{ content: Content; width: number; height: number; slide: Slide }} imageSizeChange
 * @prop {{ content: Content }} contentLazyLoad can be default prevented
 * @prop {{ content: Content }} contentAppend can be default prevented
 * @prop {{ content: Content }} contentActivate can be default prevented
 * @prop {{ content: Content }} contentDeactivate can be default prevented
 * @prop {{ content: Content }} contentRemove can be default prevented
 * @prop {{ content: Content }} contentDestroy can be default prevented
 *
 *
 * undocumented
 *
 * @prop {{ point: Point; originalEvent: PointerEvent }} imageClickAction can be default prevented
 * @prop {{ point: Point; originalEvent: PointerEvent }} bgClickAction can be default prevented
 * @prop {{ point: Point; originalEvent: PointerEvent }} tapAction can be default prevented
 * @prop {{ point: Point; originalEvent: PointerEvent }} doubleTapAction can be default prevented
 *
 * @prop {{ originalEvent: KeyboardEvent }} keydown can be default prevented
 * @prop {{ x: number; dragging: boolean }} moveMainScroll
 * @prop {{ slide: Slide }} firstZoomPan
 * @prop {{ slide: Slide | undefined, data: SlideData, index: number }} gettingData
 * @prop {undefined} beforeResize
 * @prop {undefined} resize
 * @prop {undefined} viewportSize
 * @prop {undefined} updateScrollOffset
 * @prop {{ slide: Slide }} slideInit
 * @prop {{ slide: Slide }} afterSetContent
 * @prop {{ slide: Slide }} slideLoad
 * @prop {{ slide: Slide }} appendHeavy can be default prevented
 * @prop {{ slide: Slide }} appendHeavyContent
 * @prop {{ slide: Slide }} slideActivate
 * @prop {{ slide: Slide }} slideDeactivate
 * @prop {{ slide: Slide }} slideDestroy
 * @prop {{ destZoomLevel: number, centerPoint: Point | undefined, transitionDuration: number | false | undefined }} beforeZoomTo
 * @prop {{ slide: Slide }} zoomPanUpdate
 * @prop {{ slide: Slide }} initialZoomPan
 * @prop {{ slide: Slide }} calcSlideSize
 * @prop {undefined} resolutionChanged
 * @prop {{ originalEvent: WheelEvent }} wheel can be default prevented
 * @prop {{ content: Content }} contentAppendImage can be default prevented
 * @prop {{ index: number; itemData: SlideData }} lazyLoadSlide can be default prevented
 * @prop {undefined} lazyLoad
 * @prop {{ slide: Slide }} calcBounds
 * @prop {{ zoomLevels: ZoomLevel, slideData: SlideData }} zoomLevelsUpdate
 *
 *
 * legacy
 *
 * @prop {undefined} init
 * @prop {undefined} initialZoomIn
 * @prop {undefined} initialZoomOut
 * @prop {undefined} initialZoomInEnd
 * @prop {undefined} initialZoomOutEnd
 * @prop {{ dataSource: DataSource | undefined, numItems: number }} numItems
 * @prop {{ itemData: SlideData; index: number }} itemData
 * @prop {{ index: number, itemData: SlideData, instance: PhotoSwipe }} thumbBounds
 */

/**
 * @typedef {Object} PhotoSwipeFiltersMap https://photoswipe.com/filters/
 *
 * @prop {(numItems: number, dataSource: DataSource | undefined) => number} numItems
 * Modify the total amount of slides. Example on Data sources page.
 * https://photoswipe.com/filters/#numitems
 *
 * @prop {(itemData: SlideData, index: number) => SlideData} itemData
 * Modify slide item data. Example on Data sources page.
 * https://photoswipe.com/filters/#itemdata
 *
 * @prop {(itemData: SlideData, element: HTMLElement, linkEl: HTMLAnchorElement) => SlideData} domItemData
 * Modify item data when it's parsed from DOM element. Example on Data sources page.
 * https://photoswipe.com/filters/#domitemdata
 *
 * @prop {(clickedIndex: number, e: MouseEvent, instance: PhotoSwipeLightbox) => number} clickedIndex
 * Modify clicked gallery item index.
 * https://photoswipe.com/filters/#clickedindex
 *
 * @prop {(placeholderSrc: string | false, content: Content) => string | false} placeholderSrc
 * Modify placeholder image source.
 * https://photoswipe.com/filters/#placeholdersrc
 *
 * @prop {(isContentLoading: boolean, content: Content) => boolean} isContentLoading
 * Modify if the content is currently loading.
 * https://photoswipe.com/filters/#iscontentloading
 *
 * @prop {(isContentZoomable: boolean, content: Content) => boolean} isContentZoomable
 * Modify if the content can be zoomed.
 * https://photoswipe.com/filters/#iscontentzoomable
 *
 * @prop {(useContentPlaceholder: boolean, content: Content) => boolean} useContentPlaceholder
 * Modify if the placeholder should be used for the content.
 * https://photoswipe.com/filters/#usecontentplaceholder
 *
 * @prop {(isKeepingPlaceholder: boolean, content: Content) => boolean} isKeepingPlaceholder
 * Modify if the placeholder should be kept after the content is loaded.
 * https://photoswipe.com/filters/#iskeepingplaceholder
 *
 *
 * @prop {(contentErrorElement: HTMLElement, content: Content) => HTMLElement} contentErrorElement
 * Modify an element when the content has error state (for example, if image cannot be loaded).
 * https://photoswipe.com/filters/#contenterrorelement
 *
 * @prop {(element: HTMLElement, data: UIElementData) => HTMLElement} uiElement
 * Modify a UI element that's being created.
 * https://photoswipe.com/filters/#uielement
 *
 * @prop {(thumbnail: HTMLElement | null | undefined, itemData: SlideData, index: number) => HTMLElement} thumbEl
 * Modify the thumbnail element from which opening zoom animation starts or ends.
 * https://photoswipe.com/filters/#thumbel
 *
 * @prop {(thumbBounds: Bounds | undefined, itemData: SlideData, index: number) => Bounds} thumbBounds
 * Modify the thumbnail bounds from which opening zoom animation starts or ends.
 * https://photoswipe.com/filters/#thumbbounds
 *
 * @prop {(srcsetSizesWidth: number, content: Content) => number} srcsetSizesWidth
 *
 * @prop {(preventPointerEvent: boolean, event: PointerEvent, pointerType: string) => boolean} preventPointerEvent
 *
 */

/**
 * @template {keyof PhotoSwipeFiltersMap} T
 * @typedef {{ fn: PhotoSwipeFiltersMap[T], priority: number }} Filter
 */

/**
 * @template {keyof PhotoSwipeEventsMap} T
 * @typedef {PhotoSwipeEventsMap[T] extends undefined ? PhotoSwipeEvent<T> : PhotoSwipeEvent<T> & PhotoSwipeEventsMap[T]} AugmentedEvent
 */

/**
 * @template {keyof PhotoSwipeEventsMap} T
 * @typedef {(event: AugmentedEvent<T>) => void} EventCallback
 */

/**
 * Base PhotoSwipe event object
 *
 * @template {keyof PhotoSwipeEventsMap} T
 */
class PhotoSwipeEvent {
  /**
   * @param {T} type
   * @param {PhotoSwipeEventsMap[T]} [details]
   */
  constructor(type, details) {
    this.type = type;
    this.defaultPrevented = false;

    if (details) {
      Object.assign(this, details);
    }
  }

  preventDefault() {
    this.defaultPrevented = true;
  }

}
/**
 * PhotoSwipe base class that can listen and dispatch for events.
 * Shared by PhotoSwipe Core and PhotoSwipe Lightbox, extended by base.js
 */


class Eventable {
  constructor() {
    /**
     * @type {{ [T in keyof PhotoSwipeEventsMap]?: ((event: AugmentedEvent<T>) => void)[] }}
     */
    this._listeners = {};
    /**
     * @type {{ [T in keyof PhotoSwipeFiltersMap]?: Filter<T>[] }}
     */

    this._filters = {};
    /** @type {PhotoSwipe | undefined} */

    this.pswp = undefined;
    /** @type {PhotoSwipeOptions | undefined} */

    this.options = undefined;
  }
  /**
   * @template {keyof PhotoSwipeFiltersMap} T
   * @param {T} name
   * @param {PhotoSwipeFiltersMap[T]} fn
   * @param {number} priority
   */


  addFilter(name, fn, priority = 100) {
    var _this$_filters$name, _this$_filters$name2, _this$pswp;

    if (!this._filters[name]) {
      this._filters[name] = [];
    }

    (_this$_filters$name = this._filters[name]) === null || _this$_filters$name === void 0 || _this$_filters$name.push({
      fn,
      priority
    });
    (_this$_filters$name2 = this._filters[name]) === null || _this$_filters$name2 === void 0 || _this$_filters$name2.sort((f1, f2) => f1.priority - f2.priority);
    (_this$pswp = this.pswp) === null || _this$pswp === void 0 || _this$pswp.addFilter(name, fn, priority);
  }
  /**
   * @template {keyof PhotoSwipeFiltersMap} T
   * @param {T} name
   * @param {PhotoSwipeFiltersMap[T]} fn
   */


  removeFilter(name, fn) {
    if (this._filters[name]) {
      // @ts-expect-error
      this._filters[name] = this._filters[name].filter(filter => filter.fn !== fn);
    }

    if (this.pswp) {
      this.pswp.removeFilter(name, fn);
    }
  }
  /**
   * @template {keyof PhotoSwipeFiltersMap} T
   * @param {T} name
   * @param {Parameters<PhotoSwipeFiltersMap[T]>} args
   * @returns {Parameters<PhotoSwipeFiltersMap[T]>[0]}
   */


  applyFilters(name, ...args) {
    var _this$_filters$name3;

    (_this$_filters$name3 = this._filters[name]) === null || _this$_filters$name3 === void 0 || _this$_filters$name3.forEach(filter => {
      // @ts-expect-error
      args[0] = filter.fn.apply(this, args);
    });
    return args[0];
  }
  /**
   * @template {keyof PhotoSwipeEventsMap} T
   * @param {T} name
   * @param {EventCallback<T>} fn
   */


  on(name, fn) {
    var _this$_listeners$name, _this$pswp2;

    if (!this._listeners[name]) {
      this._listeners[name] = [];
    }

    (_this$_listeners$name = this._listeners[name]) === null || _this$_listeners$name === void 0 || _this$_listeners$name.push(fn); // When binding events to lightbox,
    // also bind events to PhotoSwipe Core,
    // if it's open.

    (_this$pswp2 = this.pswp) === null || _this$pswp2 === void 0 || _this$pswp2.on(name, fn);
  }
  /**
   * @template {keyof PhotoSwipeEventsMap} T
   * @param {T} name
   * @param {EventCallback<T>} fn
   */


  off(name, fn) {
    var _this$pswp3;

    if (this._listeners[name]) {
      // @ts-expect-error
      this._listeners[name] = this._listeners[name].filter(listener => fn !== listener);
    }

    (_this$pswp3 = this.pswp) === null || _this$pswp3 === void 0 || _this$pswp3.off(name, fn);
  }
  /**
   * @template {keyof PhotoSwipeEventsMap} T
   * @param {T} name
   * @param {PhotoSwipeEventsMap[T]} [details]
   * @returns {AugmentedEvent<T>}
   */


  dispatch(name, details) {
    var _this$_listeners$name2;

    if (this.pswp) {
      return this.pswp.dispatch(name, details);
    }

    const event =
    /** @type {AugmentedEvent<T>} */
    new PhotoSwipeEvent(name, details);
    (_this$_listeners$name2 = this._listeners[name]) === null || _this$_listeners$name2 === void 0 || _this$_listeners$name2.forEach(listener => {
      listener.call(this, event);
    });
    return event;
  }

}

class Placeholder {
  /**
   * @param {string | false} imageSrc
   * @param {HTMLElement} container
   */
  constructor(imageSrc, container) {
    // Create placeholder
    // (stretched thumbnail or simple div behind the main image)

    /** @type {HTMLImageElement | HTMLDivElement | null} */
    this.element = createElement('pswp__img pswp__img--placeholder', imageSrc ? 'img' : 'div', container);

    if (imageSrc) {
      const imgEl =
      /** @type {HTMLImageElement} */
      this.element;
      imgEl.decoding = 'async';
      imgEl.alt = '';
      imgEl.src = imageSrc;
      imgEl.setAttribute('role', 'presentation');
    }

    this.element.setAttribute('aria-hidden', 'true');
  }
  /**
   * @param {number} width
   * @param {number} height
   */


  setDisplayedSize(width, height) {
    if (!this.element) {
      return;
    }

    if (this.element.tagName === 'IMG') {
      // Use transform scale() to modify img placeholder size
      // (instead of changing width/height directly).
      // This helps with performance, specifically in iOS15 Safari.
      setWidthHeight(this.element, 250, 'auto');
      this.element.style.transformOrigin = '0 0';
      this.element.style.transform = toTransformString(0, 0, width / 250);
    } else {
      setWidthHeight(this.element, width, height);
    }
  }

  destroy() {
    var _this$element;

    if ((_this$element = this.element) !== null && _this$element !== void 0 && _this$element.parentNode) {
      this.element.remove();
    }

    this.element = null;
  }

}

/** @typedef {import('./slide.js').default} Slide */

/** @typedef {import('./slide.js').SlideData} SlideData */

/** @typedef {import('../core/base.js').default} PhotoSwipeBase */

/** @typedef {import('../util/util.js').LoadState} LoadState */

class Content {
  /**
   * @param {SlideData} itemData Slide data
   * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox instance
   * @param {number} index
   */
  constructor(itemData, instance, index) {
    this.instance = instance;
    this.data = itemData;
    this.index = index;
    /** @type {HTMLImageElement | HTMLDivElement | undefined} */

    this.element = undefined;
    /** @type {Placeholder | undefined} */

    this.placeholder = undefined;
    /** @type {Slide | undefined} */

    this.slide = undefined;
    this.displayedImageWidth = 0;
    this.displayedImageHeight = 0;
    this.width = Number(this.data.w) || Number(this.data.width) || 0;
    this.height = Number(this.data.h) || Number(this.data.height) || 0;
    this.isAttached = false;
    this.hasSlide = false;
    this.isDecoding = false;
    /** @type {LoadState} */

    this.state = LOAD_STATE.IDLE;

    if (this.data.type) {
      this.type = this.data.type;
    } else if (this.data.src) {
      this.type = 'image';
    } else {
      this.type = 'html';
    }

    this.instance.dispatch('contentInit', {
      content: this
    });
  }

  removePlaceholder() {
    if (this.placeholder && !this.keepPlaceholder()) {
      // With delay, as image might be loaded, but not rendered
      setTimeout(() => {
        if (this.placeholder) {
          this.placeholder.destroy();
          this.placeholder = undefined;
        }
      }, 1000);
    }
  }
  /**
   * Preload content
   *
   * @param {boolean} isLazy
   * @param {boolean} [reload]
   */


  load(isLazy, reload) {
    if (this.slide && this.usePlaceholder()) {
      if (!this.placeholder) {
        const placeholderSrc = this.instance.applyFilters('placeholderSrc', // use  image-based placeholder only for the first slide,
        // as rendering (even small stretched thumbnail) is an expensive operation
        this.data.msrc && this.slide.isFirstSlide ? this.data.msrc : false, this);
        this.placeholder = new Placeholder(placeholderSrc, this.slide.container);
      } else {
        const placeholderEl = this.placeholder.element; // Add placeholder to DOM if it was already created

        if (placeholderEl && !placeholderEl.parentElement) {
          this.slide.container.prepend(placeholderEl);
        }
      }
    }

    if (this.element && !reload) {
      return;
    }

    if (this.instance.dispatch('contentLoad', {
      content: this,
      isLazy
    }).defaultPrevented) {
      return;
    }

    if (this.isImageContent()) {
      this.element = createElement('pswp__img', 'img'); // Start loading only after width is defined, as sizes might depend on it.
      // Due to Safari feature, we must define sizes before srcset.

      if (this.displayedImageWidth) {
        this.loadImage(isLazy);
      }
    } else {
      this.element = createElement('pswp__content', 'div');
      this.element.innerHTML = this.data.html || '';
    }

    if (reload && this.slide) {
      this.slide.updateContentSize(true);
    }
  }
  /**
   * Preload image
   *
   * @param {boolean} isLazy
   */


  loadImage(isLazy) {
    var _this$data$src, _this$data$alt;

    if (!this.isImageContent() || !this.element || this.instance.dispatch('contentLoadImage', {
      content: this,
      isLazy
    }).defaultPrevented) {
      return;
    }

    const imageElement =
    /** @type HTMLImageElement */
    this.element;
    this.updateSrcsetSizes();

    if (this.data.srcset) {
      imageElement.srcset = this.data.srcset;
    }

    imageElement.src = (_this$data$src = this.data.src) !== null && _this$data$src !== void 0 ? _this$data$src : '';
    imageElement.alt = (_this$data$alt = this.data.alt) !== null && _this$data$alt !== void 0 ? _this$data$alt : '';
    this.state = LOAD_STATE.LOADING;

    if (imageElement.complete) {
      this.onLoaded();
    } else {
      imageElement.onload = () => {
        this.onLoaded();
      };

      imageElement.onerror = () => {
        this.onError();
      };
    }
  }
  /**
   * Assign slide to content
   *
   * @param {Slide} slide
   */


  setSlide(slide) {
    this.slide = slide;
    this.hasSlide = true;
    this.instance = slide.pswp; // todo: do we need to unset slide?
  }
  /**
   * Content load success handler
   */


  onLoaded() {
    this.state = LOAD_STATE.LOADED;

    if (this.slide && this.element) {
      this.instance.dispatch('loadComplete', {
        slide: this.slide,
        content: this
      }); // if content is reloaded

      if (this.slide.isActive && this.slide.heavyAppended && !this.element.parentNode) {
        this.append();
        this.slide.updateContentSize(true);
      }

      if (this.state === LOAD_STATE.LOADED || this.state === LOAD_STATE.ERROR) {
        this.removePlaceholder();
      }
    }
  }
  /**
   * Content load error handler
   */


  onError() {
    this.state = LOAD_STATE.ERROR;

    if (this.slide) {
      this.displayError();
      this.instance.dispatch('loadComplete', {
        slide: this.slide,
        isError: true,
        content: this
      });
      this.instance.dispatch('loadError', {
        slide: this.slide,
        content: this
      });
    }
  }
  /**
   * @returns {Boolean} If the content is currently loading
   */


  isLoading() {
    return this.instance.applyFilters('isContentLoading', this.state === LOAD_STATE.LOADING, this);
  }
  /**
   * @returns {Boolean} If the content is in error state
   */


  isError() {
    return this.state === LOAD_STATE.ERROR;
  }
  /**
   * @returns {boolean} If the content is image
   */


  isImageContent() {
    return this.type === 'image';
  }
  /**
   * Update content size
   *
   * @param {Number} width
   * @param {Number} height
   */


  setDisplayedSize(width, height) {
    if (!this.element) {
      return;
    }

    if (this.placeholder) {
      this.placeholder.setDisplayedSize(width, height);
    }

    if (this.instance.dispatch('contentResize', {
      content: this,
      width,
      height
    }).defaultPrevented) {
      return;
    }

    setWidthHeight(this.element, width, height);

    if (this.isImageContent() && !this.isError()) {
      const isInitialSizeUpdate = !this.displayedImageWidth && width;
      this.displayedImageWidth = width;
      this.displayedImageHeight = height;

      if (isInitialSizeUpdate) {
        this.loadImage(false);
      } else {
        this.updateSrcsetSizes();
      }

      if (this.slide) {
        this.instance.dispatch('imageSizeChange', {
          slide: this.slide,
          width,
          height,
          content: this
        });
      }
    }
  }
  /**
   * @returns {boolean} If the content can be zoomed
   */


  isZoomable() {
    return this.instance.applyFilters('isContentZoomable', this.isImageContent() && this.state !== LOAD_STATE.ERROR, this);
  }
  /**
   * Update image srcset sizes attribute based on width and height
   */


  updateSrcsetSizes() {
    // Handle srcset sizes attribute.
    //
    // Never lower quality, if it was increased previously.
    // Chrome does this automatically, Firefox and Safari do not,
    // so we store largest used size in dataset.
    if (!this.isImageContent() || !this.element || !this.data.srcset) {
      return;
    }

    const image =
    /** @type HTMLImageElement */
    this.element;
    const sizesWidth = this.instance.applyFilters('srcsetSizesWidth', this.displayedImageWidth, this);

    if (!image.dataset.largestUsedSize || sizesWidth > parseInt(image.dataset.largestUsedSize, 10)) {
      image.sizes = sizesWidth + 'px';
      image.dataset.largestUsedSize = String(sizesWidth);
    }
  }
  /**
   * @returns {boolean} If content should use a placeholder (from msrc by default)
   */


  usePlaceholder() {
    return this.instance.applyFilters('useContentPlaceholder', this.isImageContent(), this);
  }
  /**
   * Preload content with lazy-loading param
   */


  lazyLoad() {
    if (this.instance.dispatch('contentLazyLoad', {
      content: this
    }).defaultPrevented) {
      return;
    }

    this.load(true);
  }
  /**
   * @returns {boolean} If placeholder should be kept after content is loaded
   */


  keepPlaceholder() {
    return this.instance.applyFilters('isKeepingPlaceholder', this.isLoading(), this);
  }
  /**
   * Destroy the content
   */


  destroy() {
    this.hasSlide = false;
    this.slide = undefined;

    if (this.instance.dispatch('contentDestroy', {
      content: this
    }).defaultPrevented) {
      return;
    }

    this.remove();

    if (this.placeholder) {
      this.placeholder.destroy();
      this.placeholder = undefined;
    }

    if (this.isImageContent() && this.element) {
      this.element.onload = null;
      this.element.onerror = null;
      this.element = undefined;
    }
  }
  /**
   * Display error message
   */


  displayError() {
    if (this.slide) {
      var _this$instance$option, _this$instance$option2;

      let errorMsgEl = createElement('pswp__error-msg', 'div');
      errorMsgEl.innerText = (_this$instance$option = (_this$instance$option2 = this.instance.options) === null || _this$instance$option2 === void 0 ? void 0 : _this$instance$option2.errorMsg) !== null && _this$instance$option !== void 0 ? _this$instance$option : '';
      errorMsgEl =
      /** @type {HTMLDivElement} */
      this.instance.applyFilters('contentErrorElement', errorMsgEl, this);
      this.element = createElement('pswp__content pswp__error-msg-container', 'div');
      this.element.appendChild(errorMsgEl);
      this.slide.container.innerText = '';
      this.slide.container.appendChild(this.element);
      this.slide.updateContentSize(true);
      this.removePlaceholder();
    }
  }
  /**
   * Append the content
   */


  append() {
    if (this.isAttached || !this.element) {
      return;
    }

    this.isAttached = true;

    if (this.state === LOAD_STATE.ERROR) {
      this.displayError();
      return;
    }

    if (this.instance.dispatch('contentAppend', {
      content: this
    }).defaultPrevented) {
      return;
    }

    const supportsDecode = ('decode' in this.element);

    if (this.isImageContent()) {
      // Use decode() on nearby slides
      //
      // Nearby slide images are in DOM and not hidden via display:none.
      // However, they are placed offscreen (to the left and right side).
      //
      // Some browsers do not composite the image until it's actually visible,
      // using decode() helps.
      //
      // You might ask "why dont you just decode() and then append all images",
      // that's because I want to show image before it's fully loaded,
      // as browser can render parts of image while it is loading.
      // We do not do this in Safari due to partial loading bug.
      if (supportsDecode && this.slide && (!this.slide.isActive || isSafari())) {
        this.isDecoding = true; // purposefully using finally instead of then,
        // as if srcset sizes changes dynamically - it may cause decode error

        /** @type {HTMLImageElement} */

        this.element.decode().catch(() => {}).finally(() => {
          this.isDecoding = false;
          this.appendImage();
        });
      } else {
        this.appendImage();
      }
    } else if (this.slide && !this.element.parentNode) {
      this.slide.container.appendChild(this.element);
    }
  }
  /**
   * Activate the slide,
   * active slide is generally the current one,
   * meaning the user can see it.
   */


  activate() {
    if (this.instance.dispatch('contentActivate', {
      content: this
    }).defaultPrevented || !this.slide) {
      return;
    }

    if (this.isImageContent() && this.isDecoding && !isSafari()) {
      // add image to slide when it becomes active,
      // even if it's not finished decoding
      this.appendImage();
    } else if (this.isError()) {
      this.load(false, true); // try to reload
    }

    if (this.slide.holderElement) {
      this.slide.holderElement.setAttribute('aria-hidden', 'false');
    }
  }
  /**
   * Deactivate the content
   */


  deactivate() {
    this.instance.dispatch('contentDeactivate', {
      content: this
    });

    if (this.slide && this.slide.holderElement) {
      this.slide.holderElement.setAttribute('aria-hidden', 'true');
    }
  }
  /**
   * Remove the content from DOM
   */


  remove() {
    this.isAttached = false;

    if (this.instance.dispatch('contentRemove', {
      content: this
    }).defaultPrevented) {
      return;
    }

    if (this.element && this.element.parentNode) {
      this.element.remove();
    }

    if (this.placeholder && this.placeholder.element) {
      this.placeholder.element.remove();
    }
  }
  /**
   * Append the image content to slide container
   */


  appendImage() {
    if (!this.isAttached) {
      return;
    }

    if (this.instance.dispatch('contentAppendImage', {
      content: this
    }).defaultPrevented) {
      return;
    } // ensure that element exists and is not already appended


    if (this.slide && this.element && !this.element.parentNode) {
      this.slide.container.appendChild(this.element);
    }

    if (this.state === LOAD_STATE.LOADED || this.state === LOAD_STATE.ERROR) {
      this.removePlaceholder();
    }
  }

}

/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */

/** @typedef {import('../core/base.js').default} PhotoSwipeBase */

/** @typedef {import('../photoswipe.js').Point} Point */

/** @typedef {import('../slide/slide.js').SlideData} SlideData */

/**
 * @param {PhotoSwipeOptions} options
 * @param {PhotoSwipeBase} pswp
 * @returns {Point}
 */
function getViewportSize(options, pswp) {
  if (options.getViewportSizeFn) {
    const newViewportSize = options.getViewportSizeFn(options, pswp);

    if (newViewportSize) {
      return newViewportSize;
    }
  }

  return {
    x: document.documentElement.clientWidth,
    // TODO: height on mobile is very incosistent due to toolbar
    // find a way to improve this
    //
    // document.documentElement.clientHeight - doesn't seem to work well
    y: window.innerHeight
  };
}
/**
 * Parses padding option.
 * Supported formats:
 *
 * // Object
 * padding: {
 *  top: 0,
 *  bottom: 0,
 *  left: 0,
 *  right: 0
 * }
 *
 * // A function that returns the object
 * paddingFn: (viewportSize, itemData, index) => {
 *  return {
 *    top: 0,
 *    bottom: 0,
 *    left: 0,
 *    right: 0
 *  };
 * }
 *
 * // Legacy variant
 * paddingLeft: 0,
 * paddingRight: 0,
 * paddingTop: 0,
 * paddingBottom: 0,
 *
 * @param {'left' | 'top' | 'bottom' | 'right'} prop
 * @param {PhotoSwipeOptions} options PhotoSwipe options
 * @param {Point} viewportSize PhotoSwipe viewport size, for example: { x:800, y:600 }
 * @param {SlideData} itemData Data about the slide
 * @param {number} index Slide index
 * @returns {number}
 */

function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  let paddingValue = 0;

  if (options.paddingFn) {
    paddingValue = options.paddingFn(viewportSize, itemData, index)[prop];
  } else if (options.padding) {
    paddingValue = options.padding[prop];
  } else {
    const legacyPropName = 'padding' + prop[0].toUpperCase() + prop.slice(1); // @ts-expect-error

    if (options[legacyPropName]) {
      // @ts-expect-error
      paddingValue = options[legacyPropName];
    }
  }

  return Number(paddingValue) || 0;
}
/**
 * @param {PhotoSwipeOptions} options
 * @param {Point} viewportSize
 * @param {SlideData} itemData
 * @param {number} index
 * @returns {Point}
 */

function getPanAreaSize(options, viewportSize, itemData, index) {
  return {
    x: viewportSize.x - parsePaddingOption('left', options, viewportSize, itemData, index) - parsePaddingOption('right', options, viewportSize, itemData, index),
    y: viewportSize.y - parsePaddingOption('top', options, viewportSize, itemData, index) - parsePaddingOption('bottom', options, viewportSize, itemData, index)
  };
}

const MAX_IMAGE_WIDTH = 4000;
/** @typedef {import('../photoswipe.js').default} PhotoSwipe */

/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */

/** @typedef {import('../photoswipe.js').Point} Point */

/** @typedef {import('../slide/slide.js').SlideData} SlideData */

/** @typedef {'fit' | 'fill' | number | ((zoomLevelObject: ZoomLevel) => number)} ZoomLevelOption */

/**
 * Calculates zoom levels for specific slide.
 * Depends on viewport size and image size.
 */

class ZoomLevel {
  /**
   * @param {PhotoSwipeOptions} options PhotoSwipe options
   * @param {SlideData} itemData Slide data
   * @param {number} index Slide index
   * @param {PhotoSwipe} [pswp] PhotoSwipe instance, can be undefined if not initialized yet
   */
  constructor(options, itemData, index, pswp) {
    this.pswp = pswp;
    this.options = options;
    this.itemData = itemData;
    this.index = index;
    /** @type { Point | null } */

    this.panAreaSize = null;
    /** @type { Point | null } */

    this.elementSize = null;
    this.fit = 1;
    this.fill = 1;
    this.vFill = 1;
    this.initial = 1;
    this.secondary = 1;
    this.max = 1;
    this.min = 1;
  }
  /**
   * Calculate initial, secondary and maximum zoom level for the specified slide.
   *
   * It should be called when either image or viewport size changes.
   *
   * @param {number} maxWidth
   * @param {number} maxHeight
   * @param {Point} panAreaSize
   */


  update(maxWidth, maxHeight, panAreaSize) {
    /** @type {Point} */
    const elementSize = {
      x: maxWidth,
      y: maxHeight
    };
    this.elementSize = elementSize;
    this.panAreaSize = panAreaSize;
    const hRatio = panAreaSize.x / elementSize.x;
    const vRatio = panAreaSize.y / elementSize.y;
    this.fit = Math.min(1, hRatio < vRatio ? hRatio : vRatio);
    this.fill = Math.min(1, hRatio > vRatio ? hRatio : vRatio); // zoom.vFill defines zoom level of the image
    // when it has 100% of viewport vertical space (height)

    this.vFill = Math.min(1, vRatio);
    this.initial = this._getInitial();
    this.secondary = this._getSecondary();
    this.max = Math.max(this.initial, this.secondary, this._getMax());
    this.min = Math.min(this.fit, this.initial, this.secondary);

    if (this.pswp) {
      this.pswp.dispatch('zoomLevelsUpdate', {
        zoomLevels: this,
        slideData: this.itemData
      });
    }
  }
  /**
   * Parses user-defined zoom option.
   *
   * @private
   * @param {'initial' | 'secondary' | 'max'} optionPrefix Zoom level option prefix (initial, secondary, max)
   * @returns { number | undefined }
   */


  _parseZoomLevelOption(optionPrefix) {
    const optionName =
    /** @type {'initialZoomLevel' | 'secondaryZoomLevel' | 'maxZoomLevel'} */
    optionPrefix + 'ZoomLevel';
    const optionValue = this.options[optionName];

    if (!optionValue) {
      return;
    }

    if (typeof optionValue === 'function') {
      return optionValue(this);
    }

    if (optionValue === 'fill') {
      return this.fill;
    }

    if (optionValue === 'fit') {
      return this.fit;
    }

    return Number(optionValue);
  }
  /**
   * Get zoom level to which image will be zoomed after double-tap gesture,
   * or when user clicks on zoom icon,
   * or mouse-click on image itself.
   * If you return 1 image will be zoomed to its original size.
   *
   * @private
   * @return {number}
   */


  _getSecondary() {
    let currZoomLevel = this._parseZoomLevelOption('secondary');

    if (currZoomLevel) {
      return currZoomLevel;
    } // 3x of "fit" state, but not larger than original


    currZoomLevel = Math.min(1, this.fit * 3);

    if (this.elementSize && currZoomLevel * this.elementSize.x > MAX_IMAGE_WIDTH) {
      currZoomLevel = MAX_IMAGE_WIDTH / this.elementSize.x;
    }

    return currZoomLevel;
  }
  /**
   * Get initial image zoom level.
   *
   * @private
   * @return {number}
   */


  _getInitial() {
    return this._parseZoomLevelOption('initial') || this.fit;
  }
  /**
   * Maximum zoom level when user zooms
   * via zoom/pinch gesture,
   * via cmd/ctrl-wheel or via trackpad.
   *
   * @private
   * @return {number}
   */


  _getMax() {
    // max zoom level is x4 from "fit state",
    // used for zoom gesture and ctrl/trackpad zoom
    return this._parseZoomLevelOption('max') || Math.max(1, this.fit * 4);
  }

}

/**
 * Lazy-load an image
 * This function is used both by Lightbox and PhotoSwipe core,
 * thus it can be called before dialog is opened.
 *
 * @param {SlideData} itemData Data about the slide
 * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox instance
 * @param {number} index
 * @returns {Content} Image that is being decoded or false.
 */

function lazyLoadData(itemData, instance, index) {
  const content = instance.createContentFromData(itemData, index);
  /** @type {ZoomLevel | undefined} */

  let zoomLevel;
  const {
    options
  } = instance; // We need to know dimensions of the image to preload it,
  // as it might use srcset, and we need to define sizes

  if (options) {
    zoomLevel = new ZoomLevel(options, itemData, -1);
    let viewportSize;

    if (instance.pswp) {
      viewportSize = instance.pswp.viewportSize;
    } else {
      viewportSize = getViewportSize(options, instance);
    }

    const panAreaSize = getPanAreaSize(options, viewportSize, itemData, index);
    zoomLevel.update(content.width, content.height, panAreaSize);
  }

  content.lazyLoad();

  if (zoomLevel) {
    content.setDisplayedSize(Math.ceil(content.width * zoomLevel.initial), Math.ceil(content.height * zoomLevel.initial));
  }

  return content;
}
/**
 * Lazy-loads specific slide.
 * This function is used both by Lightbox and PhotoSwipe core,
 * thus it can be called before dialog is opened.
 *
 * By default, it loads image based on viewport size and initial zoom level.
 *
 * @param {number} index Slide index
 * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox eventable instance
 * @returns {Content | undefined}
 */

function lazyLoadSlide(index, instance) {
  const itemData = instance.getItemData(index);

  if (instance.dispatch('lazyLoadSlide', {
    index,
    itemData
  }).defaultPrevented) {
    return;
  }

  return lazyLoadData(itemData, instance, index);
}

/** @typedef {import("../photoswipe.js").default} PhotoSwipe */

/** @typedef {import("../slide/slide.js").SlideData} SlideData */

/**
 * PhotoSwipe base class that can retrieve data about every slide.
 * Shared by PhotoSwipe Core and PhotoSwipe Lightbox
 */

class PhotoSwipeBase extends Eventable {
  /**
   * Get total number of slides
   *
   * @returns {number}
   */
  getNumItems() {
    var _this$options;

    let numItems = 0;
    const dataSource = (_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.dataSource;

    if (dataSource && 'length' in dataSource) {
      // may be an array or just object with length property
      numItems = dataSource.length;
    } else if (dataSource && 'gallery' in dataSource) {
      // query DOM elements
      if (!dataSource.items) {
        dataSource.items = this._getGalleryDOMElements(dataSource.gallery);
      }

      if (dataSource.items) {
        numItems = dataSource.items.length;
      }
    } // legacy event, before filters were introduced


    const event = this.dispatch('numItems', {
      dataSource,
      numItems
    });
    return this.applyFilters('numItems', event.numItems, dataSource);
  }
  /**
   * @param {SlideData} slideData
   * @param {number} index
   * @returns {Content}
   */


  createContentFromData(slideData, index) {
    return new Content(slideData, this, index);
  }
  /**
   * Get item data by index.
   *
   * "item data" should contain normalized information that PhotoSwipe needs to generate a slide.
   * For example, it may contain properties like
   * `src`, `srcset`, `w`, `h`, which will be used to generate a slide with image.
   *
   * @param {number} index
   * @returns {SlideData}
   */


  getItemData(index) {
    var _this$options2;

    const dataSource = (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.dataSource;
    /** @type {SlideData | HTMLElement} */

    let dataSourceItem = {};

    if (Array.isArray(dataSource)) {
      // Datasource is an array of elements
      dataSourceItem = dataSource[index];
    } else if (dataSource && 'gallery' in dataSource) {
      // dataSource has gallery property,
      // thus it was created by Lightbox, based on
      // gallery and children options
      // query DOM elements
      if (!dataSource.items) {
        dataSource.items = this._getGalleryDOMElements(dataSource.gallery);
      }

      dataSourceItem = dataSource.items[index];
    }

    let itemData = dataSourceItem;

    if (itemData instanceof Element) {
      itemData = this._domElementToItemData(itemData);
    } // Dispatching the itemData event,
    // it's a legacy verion before filters were introduced


    const event = this.dispatch('itemData', {
      itemData: itemData || {},
      index
    });
    return this.applyFilters('itemData', event.itemData, index);
  }
  /**
   * Get array of gallery DOM elements,
   * based on childSelector and gallery element.
   *
   * @param {HTMLElement} galleryElement
   * @returns {HTMLElement[]}
   */


  _getGalleryDOMElements(galleryElement) {
    var _this$options3, _this$options4;

    if ((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.children || (_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.childSelector) {
      return getElementsFromOption(this.options.children, this.options.childSelector, galleryElement) || [];
    }

    return [galleryElement];
  }
  /**
   * Converts DOM element to item data object.
   *
   * @param {HTMLElement} element DOM element
   * @returns {SlideData}
   */


  _domElementToItemData(element) {
    /** @type {SlideData} */
    const itemData = {
      element
    };
    const linkEl =
    /** @type {HTMLAnchorElement} */
    element.tagName === 'A' ? element : element.querySelector('a');

    if (linkEl) {
      // src comes from data-pswp-src attribute,
      // if it's empty link href is used
      itemData.src = linkEl.dataset.pswpSrc || linkEl.href;

      if (linkEl.dataset.pswpSrcset) {
        itemData.srcset = linkEl.dataset.pswpSrcset;
      }

      itemData.width = linkEl.dataset.pswpWidth ? parseInt(linkEl.dataset.pswpWidth, 10) : 0;
      itemData.height = linkEl.dataset.pswpHeight ? parseInt(linkEl.dataset.pswpHeight, 10) : 0; // support legacy w & h properties

      itemData.w = itemData.width;
      itemData.h = itemData.height;

      if (linkEl.dataset.pswpType) {
        itemData.type = linkEl.dataset.pswpType;
      }

      const thumbnailEl = element.querySelector('img');

      if (thumbnailEl) {
        var _thumbnailEl$getAttri;

        // msrc is URL to placeholder image that's displayed before large image is loaded
        // by default it's displayed only for the first slide
        itemData.msrc = thumbnailEl.currentSrc || thumbnailEl.src;
        itemData.alt = (_thumbnailEl$getAttri = thumbnailEl.getAttribute('alt')) !== null && _thumbnailEl$getAttri !== void 0 ? _thumbnailEl$getAttri : '';
      }

      if (linkEl.dataset.pswpCropped || linkEl.dataset.cropped) {
        itemData.thumbCropped = true;
      }
    }

    return this.applyFilters('domItemData', itemData, element, linkEl);
  }
  /**
   * Lazy-load by slide data
   *
   * @param {SlideData} itemData Data about the slide
   * @param {number} index
   * @returns {Content} Image that is being decoded or false.
   */


  lazyLoadData(itemData, index) {
    return lazyLoadData(itemData, this, index);
  }

}

/**
 * @template T
 * @typedef {import('../types.js').Type<T>} Type<T>
 */

/** @typedef {import('../photoswipe.js').default} PhotoSwipe */

/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */

/** @typedef {import('../photoswipe.js').DataSource} DataSource */

/** @typedef {import('../photoswipe.js').Point} Point */

/** @typedef {import('../slide/content.js').default} Content */

/** @typedef {import('../core/eventable.js').PhotoSwipeEventsMap} PhotoSwipeEventsMap */

/** @typedef {import('../core/eventable.js').PhotoSwipeFiltersMap} PhotoSwipeFiltersMap */

/**
 * @template {keyof PhotoSwipeEventsMap} T
 * @typedef {import('../core/eventable.js').EventCallback<T>} EventCallback<T>
 */

/**
 * PhotoSwipe Lightbox
 *
 * - If user has unsupported browser it falls back to default browser action (just opens URL)
 * - Binds click event to links that should open PhotoSwipe
 * - parses DOM strcture for PhotoSwipe (retrieves large image URLs and sizes)
 * - Initializes PhotoSwipe
 *
 *
 * Loader options use the same object as PhotoSwipe, and supports such options:
 *
 * gallery - Element | Element[] | NodeList | string selector for the gallery element
 * children - Element | Element[] | NodeList | string selector for the gallery children
 *
 */

class PhotoSwipeLightbox extends PhotoSwipeBase {
  /**
   * @param {PhotoSwipeOptions} [options]
   */
  constructor(options) {
    super();
    /** @type {PhotoSwipeOptions} */

    this.options = options || {};
    this._uid = 0;
    this.shouldOpen = false;
    /**
     * @private
     * @type {Content | undefined}
     */

    this._preloadedContent = undefined;
    this.onThumbnailsClick = this.onThumbnailsClick.bind(this);
  }
  /**
   * Initialize lightbox, should be called only once.
   * It's not included in the main constructor, so you may bind events before it.
   */


  init() {
    // Bind click events to each gallery
    getElementsFromOption(this.options.gallery, this.options.gallerySelector).forEach(galleryElement => {
      galleryElement.addEventListener('click', this.onThumbnailsClick, false);
    });
  }
  /**
   * @param {MouseEvent} e
   */


  onThumbnailsClick(e) {
    // Exit and allow default browser action if:
    if (specialKeyUsed(e) // ... if clicked with a special key (ctrl/cmd...)
    || window.pswp) {
      // ... if PhotoSwipe is already open
      return;
    } // If both clientX and clientY are 0 or not defined,
    // the event is likely triggered by keyboard,
    // so we do not pass the initialPoint
    //
    // Note that some screen readers emulate the mouse position,
    // so it's not the ideal way to detect them.
    //

    /** @type {Point | null} */


    let initialPoint = {
      x: e.clientX,
      y: e.clientY
    };

    if (!initialPoint.x && !initialPoint.y) {
      initialPoint = null;
    }

    let clickedIndex = this.getClickedIndex(e);
    clickedIndex = this.applyFilters('clickedIndex', clickedIndex, e, this);
    /** @type {DataSource} */

    const dataSource = {
      gallery:
      /** @type {HTMLElement} */
      e.currentTarget
    };

    if (clickedIndex >= 0) {
      e.preventDefault();
      this.loadAndOpen(clickedIndex, dataSource, initialPoint);
    }
  }
  /**
   * Get index of gallery item that was clicked.
   *
   * @param {MouseEvent} e click event
   * @returns {number}
   */


  getClickedIndex(e) {
    // legacy option
    if (this.options.getClickedIndexFn) {
      return this.options.getClickedIndexFn.call(this, e);
    }

    const clickedTarget =
    /** @type {HTMLElement} */
    e.target;
    const childElements = getElementsFromOption(this.options.children, this.options.childSelector,
    /** @type {HTMLElement} */
    e.currentTarget);
    const clickedChildIndex = childElements.findIndex(child => child === clickedTarget || child.contains(clickedTarget));

    if (clickedChildIndex !== -1) {
      return clickedChildIndex;
    } else if (this.options.children || this.options.childSelector) {
      // click wasn't on a child element
      return -1;
    } // There is only one item (which is the gallery)


    return 0;
  }
  /**
   * Load and open PhotoSwipe
   *
   * @param {number} index
   * @param {DataSource} [dataSource]
   * @param {Point | null} [initialPoint]
   * @returns {boolean}
   */


  loadAndOpen(index, dataSource, initialPoint) {
    // Check if the gallery is already open
    if (window.pswp || !this.options) {
      return false;
    } // Use the first gallery element if dataSource is not provided


    if (!dataSource && this.options.gallery && this.options.children) {
      const galleryElements = getElementsFromOption(this.options.gallery);

      if (galleryElements[0]) {
        dataSource = {
          gallery: galleryElements[0]
        };
      }
    } // set initial index


    this.options.index = index; // define options for PhotoSwipe constructor

    this.options.initialPointerPos = initialPoint;
    this.shouldOpen = true;
    this.preload(index, dataSource);
    return true;
  }
  /**
   * Load the main module and the slide content by index
   *
   * @param {number} index
   * @param {DataSource} [dataSource]
   */


  preload(index, dataSource) {
    const {
      options
    } = this;

    if (dataSource) {
      options.dataSource = dataSource;
    } // Add the main module

    /** @type {Promise<Type<PhotoSwipe>>[]} */


    const promiseArray = [];
    const pswpModuleType = typeof options.pswpModule;

    if (isPswpClass(options.pswpModule)) {
      promiseArray.push(Promise.resolve(
      /** @type {Type<PhotoSwipe>} */
      options.pswpModule));
    } else if (pswpModuleType === 'string') {
      throw new Error('pswpModule as string is no longer supported');
    } else if (pswpModuleType === 'function') {
      promiseArray.push(
      /** @type {() => Promise<Type<PhotoSwipe>>} */
      options.pswpModule());
    } else {
      throw new Error('pswpModule is not valid');
    } // Add custom-defined promise, if any


    if (typeof options.openPromise === 'function') {
      // allow developers to perform some task before opening
      promiseArray.push(options.openPromise());
    }

    if (options.preloadFirstSlide !== false && index >= 0) {
      this._preloadedContent = lazyLoadSlide(index, this);
    } // Wait till all promises resolve and open PhotoSwipe


    const uid = ++this._uid;
    Promise.all(promiseArray).then(iterableModules => {
      if (this.shouldOpen) {
        const mainModule = iterableModules[0];

        this._openPhotoswipe(mainModule, uid);
      }
    });
  }
  /**
   * @private
   * @param {Type<PhotoSwipe> | { default: Type<PhotoSwipe> }} module
   * @param {number} uid
   */


  _openPhotoswipe(module, uid) {
    // Cancel opening if UID doesn't match the current one
    // (if user clicked on another gallery item before current was loaded).
    //
    // Or if shouldOpen flag is set to false
    // (developer may modify it via public API)
    if (uid !== this._uid && this.shouldOpen) {
      return;
    }

    this.shouldOpen = false; // PhotoSwipe is already open

    if (window.pswp) {
      return;
    }
    /**
     * Pass data to PhotoSwipe and open init
     *
     * @type {PhotoSwipe}
     */


    const pswp = typeof module === 'object' ? new module.default(this.options) // eslint-disable-line
    : new module(this.options); // eslint-disable-line

    this.pswp = pswp;
    window.pswp = pswp; // map listeners from Lightbox to PhotoSwipe Core

    /** @type {(keyof PhotoSwipeEventsMap)[]} */

    Object.keys(this._listeners).forEach(name => {
      var _this$_listeners$name;

      (_this$_listeners$name = this._listeners[name]) === null || _this$_listeners$name === void 0 || _this$_listeners$name.forEach(fn => {
        pswp.on(name,
        /** @type {EventCallback<typeof name>} */
        fn);
      });
    }); // same with filters

    /** @type {(keyof PhotoSwipeFiltersMap)[]} */

    Object.keys(this._filters).forEach(name => {
      var _this$_filters$name;

      (_this$_filters$name = this._filters[name]) === null || _this$_filters$name === void 0 || _this$_filters$name.forEach(filter => {
        pswp.addFilter(name, filter.fn, filter.priority);
      });
    });

    if (this._preloadedContent) {
      pswp.contentLoader.addToCache(this._preloadedContent);
      this._preloadedContent = undefined;
    }

    pswp.on('destroy', () => {
      // clean up public variables
      this.pswp = undefined;
      delete window.pswp;
    });
    pswp.init();
  }
  /**
   * Unbinds all events, closes PhotoSwipe if it's open.
   */


  destroy() {
    var _this$pswp;

    (_this$pswp = this.pswp) === null || _this$pswp === void 0 || _this$pswp.destroy();
    this.shouldOpen = false;
    this._listeners = {};
    getElementsFromOption(this.options.gallery, this.options.gallerySelector).forEach(galleryElement => {
      galleryElement.removeEventListener('click', this.onThumbnailsClick, false);
    });
  }

}

export { PhotoSwipeLightbox as default };
//# sourceMappingURL=photoswipe-lightbox.esm.js.map


================================================
FILE: demo-docs-website/static/photoswipe/photoswipe.css
================================================
/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */

.pswp {
  --pswp-bg: #000;
  --pswp-placeholder-bg: #222;
  

  --pswp-root-z-index: 100000;
  
  --pswp-preloader-color: rgba(79, 79, 79, 0.4);
  --pswp-preloader-color-secondary: rgba(255, 255, 255, 0.9);
  
  /* defined via js:
  --pswp-transition-duration: 333ms; */
  
  --pswp-icon-color: #fff;
  --pswp-icon-color-secondary: #4f4f4f;
  --pswp-icon-stroke-color: #4f4f4f;
  --pswp-icon-stroke-width: 2px;

  --pswp-error-text-color: var(--pswp-icon-color);
}


/*
	Styles for basic PhotoSwipe (pswp) functionality (sliding area, open/close transitions)
*/

.pswp {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: var(--pswp-root-z-index);
	display: none;
	touch-action: none;
	outline: 0;
	opacity: 0.003;
	contain: layout style size;
	-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

/* Prevents focus outline on the root element,
  (it may be focused initially) */
.pswp:focus {
  outline: 0;
}

.pswp * {
  box-sizing: border-box;
}

.pswp img {
  max-width: none;
}

.pswp--open {
	display: block;
}

.pswp,
.pswp__bg {
	transform: translateZ(0);
	will-change: opacity;
}

.pswp__bg {
  opacity: 0.005;
	background: var(--pswp-bg);
}

.pswp,
.pswp__scroll-wrap {
	overflow: hidden;
}

.pswp__scroll-wrap,
.pswp__bg,
.pswp__container,
.pswp__item,
.pswp__content,
.pswp__img,
.pswp__zoom-wrap {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}

.pswp__img,
.pswp__zoom-wrap {
	width: auto;
	height: auto;
}

.pswp--click-to-zoom.pswp--zoom-allowed .pswp__img {
	cursor: -webkit-zoom-in;
	cursor: -moz-zoom-in;
	cursor: zoom-in;
}

.pswp--click-to-zoom.pswp--zoomed-in .pswp__img {
	cursor: move;
	cursor: -webkit-grab;
	cursor: -moz-grab;
	cursor: grab;
}

.pswp--click-to-zoom.pswp--zoomed-in .pswp__img:active {
  cursor: -webkit-grabbing;
  cursor: -moz-grabbing;
  cursor: grabbing;
}

/* :active to override grabbing cursor */
.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img,
.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img:active,
.pswp__img {
	cursor: -webkit-zoom-out;
	cursor: -moz-zoom-out;
	cursor: zoom-out;
}


/* Prevent selection and tap highlights */
.pswp__container,
.pswp__img,
.pswp__button,
.pswp__counter {
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}

.pswp__item {
	/* z-index for fade transition */
	z-index: 1;
	overflow: hidden;
}

.pswp__hidden {
	display: none !important;
}

/* Allow to click through pswp__content element, but not its children */
.pswp__content {
  pointer-events: none;
}
.pswp__content > * {
  pointer-events: auto;
}


/*

  PhotoSwipe UI

*/

/*
	Error message appears when image is not loaded
	(JS option errorMsg controls markup)
*/
.pswp__error-msg-container {
  display: grid;
}
.pswp__error-msg {
	margin: auto;
	font-size: 1em;
	line-height: 1;
	color: var(--pswp-error-text-color);
}

/*
class pswp__hide-on-close is applied to elements that
should hide (for example fade out) when PhotoSwipe is closed
and show (for example fade in) when PhotoSwipe is opened
 */
.pswp .pswp__hide-on-close {
	opacity: 0.005;
	will-change: opacity;
	transition: opacity var(--pswp-transition-duration) cubic-bezier(0.4, 0, 0.22, 1);
	z-index: 10; /* always overlap slide content */
	pointer-events: none; /* hidden elements should not be clickable */
}

/* class pswp--ui-visible is added when opening or closing transition starts */
.pswp--ui-visible .pswp__hide-on-close {
	opacity: 1;
	pointer-events: auto;
}

/* <button> styles, including css reset */
.pswp__button {
	position: relative;
	display: block;
	width: 50px;
	height: 60px;
	padding: 0;
	margin: 0;
	overflow: hidden;
	cursor: pointer;
	background: none;
	border: 0;
	box-shadow: none;
	opacity: 0.85;
	-webkit-appearance: none;
	-webkit-touch-callout: none;
}

.pswp__button:hover,
.pswp__button:active,
.pswp__button:focus {
  transition: none;
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  opacity: 1;
}

.pswp__button:disabled {
  opacity: 0.3;
  cursor: auto;
}

.pswp__icn {
  fill: var(--pswp-icon-color);
  color: var(--pswp-icon-color-secondary);
}

.pswp__icn {
  position: absolute;
  top: 14px;
  left: 9px;
  width: 32px;
  height: 32px;
  overflow: hidden;
  pointer-events: none;
}

.pswp__icn-shadow {
  stroke: var(--pswp-icon-stroke-color);
  stroke-width: var(--pswp-icon-stroke-width);
  fill: none;
}

.pswp__icn:focus {
	outline: 0;
}

/*
	div element that matches size of large image,
	large image loads on top of it,
	used when msrc is not provided
*/
div.pswp__img--placeholder,
.pswp__img--with-bg {
	background: var(--pswp-placeholder-bg);
}

.pswp__top-bar {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 60px;
	display: flex;
  flex-direction: row;
  justify-content: flex-end;
	z-index: 10;

	/* allow events to pass through top bar itself */
	pointer-events: none !important;
}
.pswp__top-bar > * {
  pointer-events: auto;
  /* this makes transition significantly more smooth,
     even though inner elements are not animated */
  will-change: opacity;
}


/*

  Close button

*/
.pswp__button--close {
  margin-right: 6px;
}


/*

  Arrow buttons

*/
.pswp__button--arrow {
  position: absolute;
  top: 0;
  width: 75px;
  height: 100px;
  top: 50%;
  margin-top: -50px;
}

.pswp__button--arrow:disabled {
  display: none;
  cursor: default;
}

.pswp__button--arrow .pswp__icn {
  top: 50%;
  margin-top: -30px;
  width: 60px;
  height: 60px;
  background: none;
  border-radius: 0;
}

.pswp--one-slide .pswp__button--arrow {
  display: none;
}

/* hide arrows on touch screens */
.pswp--touch .pswp__button--arrow {
  visibility: hidden;
}

/* show arrows only after mouse was used */
.pswp--has_mouse .pswp__button--arrow {
  visibility: visible;
}

.pswp__button--arrow--prev {
  right: auto;
  left: 0px;
}

.pswp__button--arrow--next {
  right: 0px;
}
.pswp__button--arrow--next .pswp__icn {
  left: auto;
  right: 14px;
  /* flip horizontally */
  transform: scale(-1, 1);
}

/*

  Zoom button

*/
.pswp__button--zoom {
  display: none;
}

.pswp--zoom-allowed .pswp__button--zoom {
  display: block;
}

/* "+" => "-" */
.pswp--zoomed-in .pswp__zoom-icn-bar-v {
  display: none;
}


/*

  Loading indicator

*/
.pswp__preloader {
  position: relative;
  overflow: hidden;
  width: 50px;
  height: 60px;
  margin-right: auto;
}

.pswp__preloader .pswp__icn {
  opacity: 0;
  transition: opacity 0.2s linear;
  animation: pswp-clockwise 600ms linear infinite;
}

.pswp__preloader--active .pswp__icn {
  opacity: 0.85;
}

@keyframes pswp-clockwise {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}


/*

  "1 of 10" counter

*/
.pswp__counter {
  height: 30px;
  margin-top: 15px;
  margin-inline-start: 20px;
  font-size: 14px;
  line-height: 30px;
  color: var(--pswp-icon-color);
  text-shadow: 1px 1px 3px var(--pswp-icon-color-secondary);
  opacity: 0.85;
}

.pswp--one-slide .pswp__counter {
  display: none;
}


================================================
FILE: demo-docs-website/static/photoswipe/photoswipe.esm.js
================================================
/*!
  * PhotoSwipe 5.4.4 - https://photoswipe.com
  * (c) 2024 Dmytro Semenov
  */
/** @typedef {import('../photoswipe.js').Point} Point */

/**
 * @template {keyof HTMLElementTagNameMap} T
 * @param {string} className
 * @param {T} tagName
 * @param {Node} [appendToEl]
 * @returns {HTMLElementTagNameMap[T]}
 */
function createElement(className, tagName, appendToEl) {
  const el = document.createElement(tagName);

  if (className) {
    el.className = className;
  }

  if (appendToEl) {
    appendToEl.appendChild(el);
  }

  return el;
}
/**
 * @param {Point} p1
 * @param {Point} p2
 * @returns {Point}
 */

function equalizePoints(p1, p2) {
  p1.x = p2.x;
  p1.y = p2.y;

  if (p2.id !== undefined) {
    p1.id = p2.id;
  }

  return p1;
}
/**
 * @param {Point} p
 */

function roundPoint(p) {
  p.x = Math.round(p.x);
  p.y = Math.round(p.y);
}
/**
 * Returns distance between two points.
 *
 * @param {Point} p1
 * @param {Point} p2
 * @returns {number}
 */

function getDistanceBetween(p1, p2) {
  const x = Math.abs(p1.x - p2.x);
  const y = Math.abs(p1.y - p2.y);
  return Math.sqrt(x * x + y * y);
}
/**
 * Whether X and Y positions of points are equal
 *
 * @param {Point} p1
 * @param {Point} p2
 * @returns {boolean}
 */

function pointsEqual(p1, p2) {
  return p1.x === p2.x && p1.y === p2.y;
}
/**
 * The float result between the min and max values.
 *
 * @param {number} val
 * @param {number} min
 * @param {number} max
 * @returns {number}
 */

function clamp(val, min, max) {
  return Math.min(Math.max(val, min), max);
}
/**
 * Get transform string
 *
 * @param {number} x
 * @param {number} [y]
 * @param {number} [scale]
 * @returns {string}
 */

function toTransformString(x, y, scale) {
  let propValue = `translate3d(${x}px,${y || 0}px,0)`;

  if (scale !== undefined) {
    propValue += ` scale3d(${scale},${scale},1)`;
  }

  return propValue;
}
/**
 * Apply transform:translate(x, y) scale(scale) to element
 *
 * @param {HTMLElement} el
 * @param {number} x
 * @param {number} [y]
 * @param {number} [scale]
 */

function setTransform(el, x, y, scale) {
  el.style.transform = toTransformString(x, y, scale);
}
const defaultCSSEasing = 'cubic-bezier(.4,0,.22,1)';
/**
 * Apply CSS transition to element
 *
 * @param {HTMLElement} el
 * @param {string} [prop] CSS property to animate
 * @param {number} [duration] in ms
 * @param {string} [ease] CSS easing function
 */

function setTransitionStyle(el, prop, duration, ease) {
  // inOut: 'cubic-bezier(.4, 0, .22, 1)', // for "toggle state" transitions
  // out: 'cubic-bezier(0, 0, .22, 1)', // for "show" transitions
  // in: 'cubic-bezier(.4, 0, 1, 1)'// for "hide" transitions
  el.style.transition = prop ? `${prop} ${duration}ms ${ease || defaultCSSEasing}` : 'none';
}
/**
 * Apply width and height CSS properties to element
 *
 * @param {HTMLElement} el
 * @param {string | number} w
 * @param {string | number} h
 */

function setWidthHeight(el, w, h) {
  el.style.width = typeof w === 'number' ? `${w}px` : w;
  el.style.height = typeof h === 'number' ? `${h}px` : h;
}
/**
 * @param {HTMLElement} el
 */

function removeTransitionStyle(el) {
  setTransitionStyle(el);
}
/**
 * @param {HTMLImageElement} img
 * @returns {Promise<HTMLImageElement | void>}
 */

function decodeImage(img) {
  if ('decode' in img) {
    return img.decode().catch(() => {});
  }

  if (img.complete) {
    return Promise.resolve(img);
  }

  return new Promise((resolve, reject) => {
    img.onload = () => resolve(img);

    img.onerror = reject;
  });
}
/** @typedef {LOAD_STATE[keyof LOAD_STATE]} LoadState */

/** @type {{ IDLE: 'idle'; LOADING: 'loading'; LOADED: 'loaded'; ERROR: 'error' }} */

const LOAD_STATE = {
  IDLE: 'idle',
  LOADING: 'loading',
  LOADED: 'loaded',
  ERROR: 'error'
};
/**
 * Check if click or keydown event was dispatched
 * with a special key or via mouse wheel.
 *
 * @param {MouseEvent | KeyboardEvent} e
 * @returns {boolean}
 */

function specialKeyUsed(e) {
  return 'button' in e && e.button === 1 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey;
}
/**
 * Parse `gallery` or `children` options.
 *
 * @param {import('../photoswipe.js').ElementProvider} [option]
 * @param {string} [legacySelector]
 * @param {HTMLElement | Document} [parent]
 * @returns HTMLElement[]
 */

function getElementsFromOption(option, legacySelector, parent = document) {
  /** @type {HTMLElement[]} */
  let elements = [];

  if (option instanceof Element) {
    elements = [option];
  } else if (option instanceof NodeList || Array.isArray(option)) {
    elements = Array.from(option);
  } else {
    const selector = typeof option === 'string' ? option : legacySelector;

    if (selector) {
      elements = Array.from(parent.querySelectorAll(selector));
    }
  }

  return elements;
}
/**
 * Check if browser is Safari
 *
 * @returns {boolean}
 */

function isSafari() {
  return !!(navigator.vendor && navigator.vendor.match(/apple/i));
}

// Detect passive event listener support
let supportsPassive = false;
/* eslint-disable */

try {
  /* @ts-ignore */
  window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
    get: () => {
      supportsPassive = true;
    }
  }));
} catch (e) {}
/* eslint-enable */

/**
 * @typedef {Object} PoolItem
 * @prop {HTMLElement | Window | Document | undefined | null} target
 * @prop {string} type
 * @prop {EventListenerOrEventListenerObject} listener
 * @prop {boolean} [passive]
 */


class DOMEvents {
  constructor() {
    /**
     * @type {PoolItem[]}
     * @private
     */
    this._pool = [];
  }
  /**
   * Adds event listeners
   *
   * @param {PoolItem['target']} target
   * @param {PoolItem['type']} type Can be multiple, separated by space.
   * @param {PoolItem['listener']} listener
   * @param {PoolItem['passive']} [passive]
   */


  add(target, type, listener, passive) {
    this._toggleListener(target, type, listener, passive);
  }
  /**
   * Removes event listeners
   *
   * @param {PoolItem['target']} target
   * @param {PoolItem['type']} type
   * @param {PoolItem['listener']} listener
   * @param {PoolItem['passive']} [passive]
   */


  remove(target, type, listener, passive) {
    this._toggleListener(target, type, listener, passive, true);
  }
  /**
   * Removes all bound events
   */


  removeAll() {
    this._pool.forEach(poolItem => {
      this._toggleListener(poolItem.target, poolItem.type, poolItem.listener, poolItem.passive, true, true);
    });

    this._pool = [];
  }
  /**
   * Adds or removes event
   *
   * @private
   * @param {PoolItem['target']} target
   * @param {PoolItem['type']} type
   * @param {PoolItem['listener']} listener
   * @param {PoolItem['passive']} [passive]
   * @param {boolean} [unbind] Whether the event should be added or removed
   * @param {boolean} [skipPool] Whether events pool should be skipped
   */


  _toggleListener(target, type, listener, passive, unbind, skipPool) {
    if (!target) {
      return;
    }

    const methodName = unbind ? 'removeEventListener' : 'addEventListener';
    const types = type.split(' ');
    types.forEach(eType => {
      if (eType) {
        // Events pool is used to easily unbind all events when PhotoSwipe is closed,
        // so developer doesn't need to do this manually
        if (!skipPool) {
          if (unbind) {
            // Remove from the events pool
            this._pool = this._pool.filter(poolItem => {
              return poolItem.type !== eType || poolItem.listener !== listener || poolItem.target !== target;
            });
          } else {
            // Add to the events pool
            this._pool.push({
              target,
              type: eType,
              listener,
              passive
            });
          }
        } // most PhotoSwipe events call preventDefault,
        // and we do not need browser to scroll the page


        const eventOptions = supportsPassive ? {
          passive: passive || false
        } : false;
        target[methodName](eType, listener, eventOptions);
      }
    });
  }

}

/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */

/** @typedef {import('../core/base.js').default} PhotoSwipeBase */

/** @typedef {import('../photoswipe.js').Point} Point */

/** @typedef {import('../slide/slide.js').SlideData} SlideData */

/**
 * @param {PhotoSwipeOptions} options
 * @param {PhotoSwipeBase} pswp
 * @returns {Point}
 */
function getViewportSize(options, pswp) {
  if (options.getViewportSizeFn) {
    const newViewportSize = options.getViewportSizeFn(options, pswp);

    if (newViewportSize) {
      return newViewportSize;
    }
  }

  return {
    x: document.documentElement.clientWidth,
    // TODO: height on mobile is very incosistent due to toolbar
    // find a way to improve this
    //
    // document.documentElement.clientHeight - doesn't seem to work well
    y: window.innerHeight
  };
}
/**
 * Parses padding option.
 * Supported formats:
 *
 * // Object
 * padding: {
 *  top: 0,
 *  bottom: 0,
 *  left: 0,
 *  right: 0
 * }
 *
 * // A function that returns the object
 * paddingFn: (viewportSize, itemData, index) => {
 *  return {
 *    top: 0,
 *    bottom: 0,
 *    left: 0,
 *    right: 0
 *  };
 * }
 *
 * // Legacy variant
 * paddingLeft: 0,
 * paddingRight: 0,
 * paddingTop: 0,
 * paddingBottom: 0,
 *
 * @param {'left' | 'top' | 'bottom' | 'right'} prop
 * @param {PhotoSwipeOptions} options PhotoSwipe options
 * @param {Point} viewportSize PhotoSwipe viewport size, for example: { x:800, y:600 }
 * @param {SlideData} itemData Data about the slide
 * @param {number} index Slide index
 * @returns {number}
 */

function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  let paddingValue = 0;

  if (options.paddingFn) {
    paddingValue = options.paddingFn(viewportSize, itemData, index)[prop];
  } else if (options.padding) {
    paddingValue = options.padding[prop];
  } else {
    const legacyPropName = 'padding' + prop[0].toUpperCase() + prop.slice(1); // @ts-expect-error

    if (options[legacyPropName]) {
      // @ts-expect-error
      paddingValue = options[legacyPropName];
    }
  }

  return Number(paddingValue) || 0;
}
/**
 * @param {PhotoSwipeOptions} options
 * @param {Point} viewportSize
 * @param {SlideData} itemData
 * @param {number} index
 * @returns {Point}
 */

function getPanAreaSize(options, viewportSize, itemData, index) {
  return {
    x: viewportSize.x - parsePaddingOption('left', options, viewportSize, itemData, index) - parsePaddingOption('right', options, viewportSize, itemData, index),
    y: viewportSize.y - parsePaddingOption('top', options, viewportSize, itemData, index) - parsePaddingOption('bottom', options, viewportSize, itemData, index)
  };
}

/** @typedef {import('./slide.js').default} Slide */

/** @typedef {Record<Axis, number>} Point */

/** @typedef {'x' | 'y'} Axis */

/**
 * Calculates minimum, maximum and initial (center) bounds of a slide
 */

class PanBounds {
  /**
   * @param {Slide} slide
   */
  constructor(slide) {
    this.slide = slide;
    this.currZoomLevel = 1;
    this.center =
    /** @type {Point} */
    {
      x: 0,
      y: 0
    };
    this.max =
    /** @type {Point} */
    {
      x: 0,
      y: 0
    };
    this.min =
    /** @type {Point} */
    {
      x: 0,
      y: 0
    };
  }
  /**
   * _getItemBounds
   *
   * @param {number} currZoomLevel
   */


  update(currZoomLevel) {
    this.currZoomLevel = currZoomLevel;

    if (!this.slide.width) {
      this.reset();
    } else {
      this._updateAxis('x');

      this._updateAxis('y');

      this.slide.pswp.dispatch('calcBounds', {
        slide: this.slide
      });
    }
  }
  /**
   * _calculateItemBoundsForAxis
   *
   * @param {Axis} axis
   */


  _updateAxis(axis) {
    const {
      pswp
    } = this.slide;
    const elSize = this.slide[axis === 'x' ? 'width' : 'height'] * this.currZoomLevel;
    const paddingPr
Download .txt
gitextract_0u2e7_9t/

├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── build.yml
├── .gitignore
├── LICENSE
├── README.md
├── build/
│   ├── config-builder.js
│   ├── rollup.config.js
│   └── rollup.config.watch.js
├── demo-docs-website/
│   ├── .gitignore
│   ├── babel.config.js
│   ├── docusaurus.config.js
│   ├── package.json
│   ├── repo-data.json
│   ├── sidebars.js
│   ├── src/
│   │   ├── components/
│   │   │   ├── HomepageFeatures/
│   │   │   │   ├── index.js
│   │   │   │   └── styles.module.css
│   │   │   └── PswpCodePreview/
│   │   │       ├── demo-images.js
│   │   │       ├── gallery-templates/
│   │   │       │   ├── basic--badges.js
│   │   │       │   ├── basic--cropped.js
│   │   │       │   ├── basic.js
│   │   │       │   ├── caption.js
│   │   │       │   ├── content-types.js
│   │   │       │   ├── custom-html-markup-data-source.js
│   │   │       │   ├── getting-started.js
│   │   │       │   └── srcset-test.js
│   │   │       └── index.js
│   │   ├── css/
│   │   │   ├── custom.css
│   │   │   ├── docs-page.css
│   │   │   ├── example-code-block.css
│   │   │   ├── header.css
│   │   │   ├── home.css
│   │   │   ├── scrollbar.css
│   │   │   └── sidebar-menu.css
│   │   ├── pages/
│   │   │   ├── _index-deep-zoom-demo.js
│   │   │   ├── _index-gallery-header.js
│   │   │   ├── index.js
│   │   │   └── index.module.css
│   │   └── theme/
│   │       ├── CodeBlock/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocItem/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocItemFooter/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocPage/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── DocSidebar/
│   │       │   ├── index.js
│   │       │   ├── is-same-path.ts
│   │       │   └── styles.module.css
│   │       ├── EditThisPage/
│   │       │   └── index.js
│   │       ├── Footer/
│   │       │   ├── index.js
│   │       │   └── styles.module.css
│   │       ├── Logo/
│   │       │   └── index.js
│   │       ├── MDXComponents/
│   │       │   ├── index.js
│   │       │   └── styles.css
│   │       └── Navbar/
│   │           ├── github-stars.js
│   │           ├── index.js
│   │           └── styles.module.css
│   └── static/
│       ├── .nojekyll
│       └── photoswipe/
│           ├── photoswipe-lightbox.esm.js
│           ├── photoswipe.css
│           └── photoswipe.esm.js
├── dist/
│   ├── photoswipe-lightbox.esm.js
│   ├── photoswipe.css
│   ├── photoswipe.esm.js
│   ├── types/
│   │   ├── core/
│   │   │   ├── base.d.ts
│   │   │   └── eventable.d.ts
│   │   ├── gestures/
│   │   │   ├── drag-handler.d.ts
│   │   │   ├── gestures.d.ts
│   │   │   ├── tap-handler.d.ts
│   │   │   └── zoom-handler.d.ts
│   │   ├── keyboard.d.ts
│   │   ├── lightbox/
│   │   │   └── lightbox.d.ts
│   │   ├── main-scroll.d.ts
│   │   ├── opener.d.ts
│   │   ├── photoswipe.d.ts
│   │   ├── scroll-wheel.d.ts
│   │   ├── slide/
│   │   │   ├── content.d.ts
│   │   │   ├── get-thumb-bounds.d.ts
│   │   │   ├── loader.d.ts
│   │   │   ├── pan-bounds.d.ts
│   │   │   ├── placeholder.d.ts
│   │   │   ├── slide.d.ts
│   │   │   └── zoom-level.d.ts
│   │   ├── types.d.ts
│   │   ├── ui/
│   │   │   ├── button-arrow.d.ts
│   │   │   ├── button-close.d.ts
│   │   │   ├── button-zoom.d.ts
│   │   │   ├── counter-indicator.d.ts
│   │   │   ├── loading-indicator.d.ts
│   │   │   ├── ui-element.d.ts
│   │   │   └── ui.d.ts
│   │   └── util/
│   │       ├── animations.d.ts
│   │       ├── css-animation.d.ts
│   │       ├── dom-events.d.ts
│   │       ├── spring-animation.d.ts
│   │       ├── spring-easer.d.ts
│   │       ├── util.d.ts
│   │       └── viewport-size.d.ts
│   └── umd/
│       └── README.md
├── docs/
│   ├── adding-ui-elements.md
│   ├── adjusting-zoom-level.md
│   ├── caption.md
│   ├── click-and-tap-actions.md
│   ├── custom-content.md
│   ├── data-sources.md
│   ├── events.md
│   ├── filters.md
│   ├── getting-started.md
│   ├── methods.md
│   ├── native-fullscreen-on-open.md
│   ├── opening-or-closing-transition.md
│   ├── options.md
│   ├── properties.md
│   ├── react-image-gallery.md
│   ├── styling.md
│   ├── svelte-image-gallery.md
│   └── vue-image-gallery.md
├── global.d.ts
├── package.json
├── src/
│   ├── js/
│   │   ├── core/
│   │   │   ├── base.js
│   │   │   └── eventable.js
│   │   ├── gestures/
│   │   │   ├── drag-handler.js
│   │   │   ├── gestures.js
│   │   │   ├── tap-handler.js
│   │   │   └── zoom-handler.js
│   │   ├── keyboard.js
│   │   ├── lightbox/
│   │   │   └── lightbox.js
│   │   ├── main-scroll.js
│   │   ├── opener.js
│   │   ├── photoswipe.js
│   │   ├── scroll-wheel.js
│   │   ├── slide/
│   │   │   ├── content.js
│   │   │   ├── get-thumb-bounds.js
│   │   │   ├── loader.js
│   │   │   ├── pan-bounds.js
│   │   │   ├── placeholder.js
│   │   │   ├── slide.js
│   │   │   └── zoom-level.js
│   │   ├── types.ts
│   │   ├── ui/
│   │   │   ├── button-arrow.js
│   │   │   ├── button-close.js
│   │   │   ├── button-zoom.js
│   │   │   ├── counter-indicator.js
│   │   │   ├── loading-indicator.js
│   │   │   ├── ui-element.js
│   │   │   └── ui.js
│   │   └── util/
│   │       ├── animations.js
│   │       ├── css-animation.js
│   │       ├── dom-events.js
│   │       ├── spring-animation.js
│   │       ├── spring-easer.js
│   │       ├── util.js
│   │       └── viewport-size.js
│   └── photoswipe.css
└── tsconfig.json
Download .txt
SYMBOL INDEX (1171 symbols across 90 files)

FILE: build/config-builder.js
  function getBanner (line 9) | function getBanner(name) {
  function getMinifyPlugin (line 16) | function getMinifyPlugin() {
  function getBabelPlugin (line 30) | function getBabelPlugin() {

FILE: demo-docs-website/src/components/HomepageFeatures/index.js
  function Feature (line 38) | function Feature({Svg, title, description}) {
  function HomepageFeatures (line 52) | function HomepageFeatures() {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic--badges.js
  function basicBadgesTemplate (line 1) | function basicBadgesTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic--cropped.js
  function basicCroppedTemplate (line 1) | function basicCroppedTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic.js
  function basicTemplate (line 1) | function basicTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/caption.js
  function captionTemplate (line 1) | function captionTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/content-types.js
  function contentTypesTemplate (line 1) | function contentTypesTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/custom-html-markup-data-source.js
  function customHTMLDataSourceTemplate (line 1) | function customHTMLDataSourceTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/getting-started.js
  function gettingStartedTemplate (line 1) | function gettingStartedTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/gallery-templates/srcset-test.js
  function srcsetTemplate (line 1) | function srcsetTemplate(props) {

FILE: demo-docs-website/src/components/PswpCodePreview/index.js
  function generateGallery (line 27) | function generateGallery(galleryData) {
  function PswpCodePreview (line 71) | function PswpCodePreview(props) {

FILE: demo-docs-website/src/pages/_index-deep-zoom-demo.js
  function DeepZoomGalleryDemo (line 61) | function DeepZoomGalleryDemo() {

FILE: demo-docs-website/src/pages/_index-gallery-header.js
  function GalleryItem (line 108) | function GalleryItem(props) {
  function GalleryExampleOpenZoomed (line 147) | function GalleryExampleOpenZoomed(props) {
  function GalleryExampleDynamicCaptionPlugin (line 170) | function GalleryExampleDynamicCaptionPlugin(props) {
  function GalleryExample (line 206) | function GalleryExample(props) {
  function GalleryHeader (line 236) | function GalleryHeader() {

FILE: demo-docs-website/src/pages/index.js
  function HomepageHeader (line 10) | function HomepageHeader() {
  function WhatsNew (line 33) | function WhatsNew() {
  function Home (line 111) | function Home() {

FILE: demo-docs-website/src/theme/CodeBlock/index.js
  function CodeBlock (line 19) | function CodeBlock({

FILE: demo-docs-website/src/theme/DocItem/index.js
  function DocItem (line 20) | function DocItem(props) {

FILE: demo-docs-website/src/theme/DocItemFooter/index.js
  function TagsRow (line 15) | function TagsRow(props) {
  function EditMetaRow (line 29) | function EditMetaRow({
  function DocItemFooter (line 60) | function DocItemFooter(props) {

FILE: demo-docs-website/src/theme/DocPage/index.js
  function DocPageContent (line 28) | function DocPageContent({
  function DocPage (line 120) | function DocPage(props) {

FILE: demo-docs-website/src/theme/DocSidebar/index.js
  function useShowAnnouncementBar (line 23) | function useShowAnnouncementBar() {
  function SimpleSidebarCategory (line 37) | function SimpleSidebarCategory(props) {
  function SimpleSidebarItem (line 42) | function SimpleSidebarItem(props) {
  function SimpleSidebar (line 52) | function SimpleSidebar(props) {
  function DocSidebarDesktop (line 78) | function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) {
  function DocSidebarMobile (line 98) | function DocSidebarMobile(props) {
  function DocSidebar (line 109) | function DocSidebar(props) {

FILE: demo-docs-website/src/theme/EditThisPage/index.js
  function EditThisPage (line 9) | function EditThisPage({editUrl}) {

FILE: demo-docs-website/src/theme/Footer/index.js
  function FooterLogo (line 15) | function FooterLogo({sources, alt, width, height}) {
  function Footer (line 27) | function Footer() {

FILE: demo-docs-website/src/theme/Logo/index.js
  function Logo (line 15) | function Logo(props) {

FILE: demo-docs-website/src/theme/MDXComponents/index.js
  function unwrapMDXElement (line 18) | function unwrapMDXElement(element) {

FILE: demo-docs-website/src/theme/Navbar/github-stars.js
  function ReactGithubStars (line 5) | function ReactGithubStars() {

FILE: demo-docs-website/src/theme/Navbar/index.js
  function useNavbarItems (line 35) | function useNavbarItems() {
  function splitNavItemsByPosition (line 41) | function splitNavItemsByPosition(items) {
  function useMobileSidebar (line 54) | function useMobileSidebar() {
  function useColorModeToggle (line 87) | function useColorModeToggle() {
  function useSecondaryMenu (line 114) | function useSecondaryMenu({ sidebarShown, toggleSidebar }) {
  function NavbarMobileSidebar (line 158) | function NavbarMobileSidebar({ sidebarShown, toggleSidebar }) {
  function Navbar (line 228) | function Navbar() {

FILE: demo-docs-website/static/photoswipe/photoswipe-lightbox.esm.js
  function createElement (line 14) | function createElement(className, tagName, appendToEl) {
  function toTransformString (line 36) | function toTransformString(x, y, scale) {
  function setWidthHeight (line 53) | function setWidthHeight(el, w, h) {
  constant LOAD_STATE (line 61) | const LOAD_STATE = {
  function specialKeyUsed (line 75) | function specialKeyUsed(e) {
  function getElementsFromOption (line 87) | function getElementsFromOption(option, legacySelector, parent = document) {
  function isPswpClass (line 112) | function isPswpClass(fn) {
  function isSafari (line 121) | function isSafari() {
  class PhotoSwipeEvent (line 343) | class PhotoSwipeEvent {
    method constructor (line 348) | constructor(type, details) {
    method preventDefault (line 357) | preventDefault() {
  class Eventable (line 368) | class Eventable {
    method constructor (line 369) | constructor() {
    method addFilter (line 394) | addFilter(name, fn, priority = 100) {
    method removeFilter (line 415) | removeFilter(name, fn) {
    method applyFilters (line 433) | applyFilters(name, ...args) {
    method on (line 449) | on(name, fn) {
    method off (line 469) | off(name, fn) {
    method dispatch (line 487) | dispatch(name, details) {
  class Placeholder (line 505) | class Placeholder {
    method constructor (line 510) | constructor(imageSrc, container) {
    method setDisplayedSize (line 535) | setDisplayedSize(width, height) {
    method destroy (line 552) | destroy() {
  class Content (line 572) | class Content {
    method constructor (line 578) | constructor(itemData, instance, index) {
    method removePlaceholder (line 615) | removePlaceholder() {
    method load (line 634) | load(isLazy, reload) {
    method loadImage (line 684) | loadImage(isLazy) {
    method setSlide (line 726) | setSlide(slide) {
    method onLoaded (line 736) | onLoaded() {
    method onError (line 760) | onError() {
    method isLoading (line 781) | isLoading() {
    method isError (line 789) | isError() {
    method isImageContent (line 797) | isImageContent() {
    method setDisplayedSize (line 808) | setDisplayedSize(width, height) {
    method isZoomable (line 853) | isZoomable() {
    method updateSrcsetSizes (line 861) | updateSrcsetSizes() {
    method usePlaceholder (line 886) | usePlaceholder() {
    method lazyLoad (line 894) | lazyLoad() {
    method keepPlaceholder (line 908) | keepPlaceholder() {
    method destroy (line 916) | destroy() {
    method displayError (line 944) | displayError() {
    method append (line 966) | append() {
    method activate (line 1023) | activate() {
    method deactivate (line 1047) | deactivate() {
    method remove (line 1061) | remove() {
    method appendImage (line 1083) | appendImage() {
  function getViewportSize (line 1119) | function getViewportSize(options, pswp) {
  function parsePaddingOption (line 1173) | function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  function getPanAreaSize (line 1199) | function getPanAreaSize(options, viewportSize, itemData, index) {
  constant MAX_IMAGE_WIDTH (line 1206) | const MAX_IMAGE_WIDTH = 4000;
  class ZoomLevel (line 1222) | class ZoomLevel {
    method constructor (line 1229) | constructor(options, itemData, index, pswp) {
    method update (line 1259) | update(maxWidth, maxHeight, panAreaSize) {
    method _parseZoomLevelOption (line 1295) | _parseZoomLevelOption(optionPrefix) {
    method _getSecondary (line 1330) | _getSecondary() {
    method _getInitial (line 1354) | _getInitial() {
    method _getMax (line 1367) | _getMax() {
  function lazyLoadData (line 1386) | function lazyLoadData(itemData, instance, index) {
  function lazyLoadSlide (line 1430) | function lazyLoadSlide(index, instance) {
  class PhotoSwipeBase (line 1452) | class PhotoSwipeBase extends Eventable {
    method getNumItems (line 1458) | getNumItems() {
    method createContentFromData (line 1492) | createContentFromData(slideData, index) {
    method getItemData (line 1507) | getItemData(index) {
    method _getGalleryDOMElements (line 1553) | _getGalleryDOMElements(galleryElement) {
    method _domElementToItemData (line 1570) | _domElementToItemData(element) {
    method lazyLoadData (line 1625) | lazyLoadData(itemData, index) {
  class PhotoSwipeLightbox (line 1671) | class PhotoSwipeLightbox extends PhotoSwipeBase {
    method constructor (line 1675) | constructor(options) {
    method init (line 1696) | init() {
    method onThumbnailsClick (line 1707) | onThumbnailsClick(e) {
    method getClickedIndex (line 1756) | getClickedIndex(e) {
    method loadAndOpen (line 1790) | loadAndOpen(index, dataSource, initialPoint) {
    method preload (line 1823) | preload(index, dataSource) {
    method _openPhotoswipe (line 1879) | _openPhotoswipe(module, uid) {
    method destroy (line 1946) | destroy() {

FILE: demo-docs-website/static/photoswipe/photoswipe.esm.js
  function createElement (line 14) | function createElement(className, tagName, appendToEl) {
  function equalizePoints (line 33) | function equalizePoints(p1, p2) {
  function roundPoint (line 47) | function roundPoint(p) {
  function getDistanceBetween (line 59) | function getDistanceBetween(p1, p2) {
  function pointsEqual (line 72) | function pointsEqual(p1, p2) {
  function clamp (line 84) | function clamp(val, min, max) {
  function toTransformString (line 96) | function toTransformString(x, y, scale) {
  function setTransform (line 114) | function setTransform(el, x, y, scale) {
  function setTransitionStyle (line 127) | function setTransitionStyle(el, prop, duration, ease) {
  function setWidthHeight (line 141) | function setWidthHeight(el, w, h) {
  function removeTransitionStyle (line 149) | function removeTransitionStyle(el) {
  function decodeImage (line 157) | function decodeImage(img) {
  constant LOAD_STATE (line 176) | const LOAD_STATE = {
  function specialKeyUsed (line 190) | function specialKeyUsed(e) {
  function getElementsFromOption (line 202) | function getElementsFromOption(option, legacySelector, parent = document) {
  function isSafari (line 226) | function isSafari() {
  class DOMEvents (line 253) | class DOMEvents {
    method constructor (line 254) | constructor() {
    method add (line 271) | add(target, type, listener, passive) {
    method remove (line 284) | remove(target, type, listener, passive) {
    method removeAll (line 292) | removeAll() {
    method _toggleListener (line 312) | _toggleListener(target, type, listener, passive, unbind, skipPool) {
  function getViewportSize (line 365) | function getViewportSize(options, pswp) {
  function parsePaddingOption (line 419) | function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  function getPanAreaSize (line 445) | function getPanAreaSize(options, viewportSize, itemData, index) {
  class PanBounds (line 462) | class PanBounds {
    method constructor (line 466) | constructor(slide) {
    method update (line 495) | update(currZoomLevel) {
    method _updateAxis (line 517) | _updateAxis(axis) {
    method reset (line 535) | reset() {
    method correctPan (line 552) | correctPan(axis, panOffset) {
  constant MAX_IMAGE_WIDTH (line 559) | const MAX_IMAGE_WIDTH = 4000;
  class ZoomLevel (line 575) | class ZoomLevel {
    method constructor (line 582) | constructor(options, itemData, index, pswp) {
    method update (line 612) | update(maxWidth, maxHeight, panAreaSize) {
    method _parseZoomLevelOption (line 648) | _parseZoomLevelOption(optionPrefix) {
    method _getSecondary (line 683) | _getSecondary() {
    method _getInitial (line 707) | _getInitial() {
    method _getMax (line 720) | _getMax() {
  class Slide (line 733) | class Slide {
    method constructor (line 739) | constructor(data, index, pswp) {
    method setIsActive (line 791) | setIsActive(isActive) {
    method append (line 807) | append(holderElement) {
    method load (line 834) | load() {
    method appendHeavy (line 848) | appendHeavy() {
    method activate (line 879) | activate() {
    method deactivate (line 894) | deactivate() {
    method destroy (line 918) | destroy() {
    method resize (line 927) | resize() {
    method updateContentSize (line 952) | updateContentSize(force) {
    method sizeChanged (line 976) | sizeChanged(width, height) {
    method getPlaceholderElement (line 988) | getPlaceholderElement() {
    method zoomTo (line 1004) | zoomTo(destZoomLevel, centerPoint, transitionDuration, ignoreBounds) {
    method toggleZoom (line 1062) | toggleZoom(centerPoint) {
    method setZoomLevel (line 1073) | setZoomLevel(currZoomLevel) {
    method calculateZoomToPanOffset (line 1092) | calculateZoomToPanOffset(axis, point, prevZoomLevel) {
    method panTo (line 1118) | panTo(panX, panY) {
    method isPannable (line 1129) | isPannable() {
    method isZoomable (line 1138) | isZoomable() {
    method applyCurrentZoomPan (line 1147) | applyCurrentZoomPan() {
    method zoomAndPanToInitial (line 1157) | zoomAndPanToInitial() {
    method _applyZoomTransform (line 1176) | _applyZoomTransform(x, y, zoom) {
    method calculateSize (line 1181) | calculateSize() {
    method getCurrentTransform (line 1194) | getCurrentTransform() {
    method _setResolution (line 1215) | _setResolution(newResolution) {
  constant PAN_END_FRICTION (line 1231) | const PAN_END_FRICTION = 0.35;
  constant VERTICAL_DRAG_FRICTION (line 1232) | const VERTICAL_DRAG_FRICTION = 0.6;
  constant MIN_RATIO_TO_CLOSE (line 1234) | const MIN_RATIO_TO_CLOSE = 0.4;
  constant MIN_NEXT_SLIDE_SPEED (line 1237) | const MIN_NEXT_SLIDE_SPEED = 0.5;
  function project (line 1244) | function project(initialVelocity, decelerationRate) {
  class DragHandler (line 1252) | class DragHandler {
    method constructor (line 1256) | constructor(gestures) {
    method start (line 1267) | start() {
    method change (line 1275) | change() {
    method end (line 1312) | end() {
    method _finishPanGestureForAxis (line 1371) | _finishPanGestureForAxis(axis) {
    method _panOrMoveMainScroll (line 1456) | _panOrMoveMainScroll(axis) {
    method _getVerticalDragRatio (line 1567) | _getVerticalDragRatio(panY) {
    method _setPanWithFriction (line 1584) | _setPanWithFriction(axis, potentialPan, customFriction) {
  constant UPPER_ZOOM_FRICTION (line 1613) | const UPPER_ZOOM_FRICTION = 0.05;
  constant LOWER_ZOOM_FRICTION (line 1614) | const LOWER_ZOOM_FRICTION = 0.15;
  function getZoomPointsCenter (line 1624) | function getZoomPointsCenter(p, p1, p2) {
  class ZoomHandler (line 1630) | class ZoomHandler {
    method constructor (line 1634) | constructor(gestures) {
    method start (line 1671) | start() {
    method change (line 1685) | change() {
    method end (line 1743) | end() {
    method _calculatePanForZoomLevel (line 1765) | _calculatePanForZoomLevel(axis, currZoomLevel) {
    method correctZoomPan (line 1779) | correctZoomPan(ignoreGesture) {
  function didTapOnMainContent (line 1919) | function didTapOnMainContent(event) {
  class TapHandler (line 1929) | class TapHandler {
    method constructor (line 1933) | constructor(gestures) {
    method click (line 1942) | click(point, originalEvent) {
    method tap (line 1961) | tap(point, originalEvent) {
    method doubleTap (line 1972) | doubleTap(point, originalEvent) {
    method _doClickOrTapAction (line 1985) | _doClickOrTapAction(actionName, point, originalEvent) {
  constant AXIS_SWIPE_HYSTERISIS (line 2051) | const AXIS_SWIPE_HYSTERISIS = 10;
  constant DOUBLE_TAP_DELAY (line 2053) | const DOUBLE_TAP_DELAY = 300;
  constant MIN_TAP_DISTANCE (line 2055) | const MIN_TAP_DISTANCE = 25;
  class Gestures (line 2065) | class Gestures {
    method constructor (line 2069) | constructor(pswp) {
    method _bindEvents (line 2216) | _bindEvents(pref, down, up, cancel) {
    method onPointerDown (line 2245) | onPointerDown(e) {
    method onPointerMove (line 2307) | onPointerMove(e) {
    method _finishDrag (line 2373) | _finishDrag() {
    method onPointerUp (line 2391) | onPointerUp(e) {
    method _rafRenderLoop (line 2432) | _rafRenderLoop() {
    method _updateVelocity (line 2462) | _updateVelocity(force) {
    method _finishTap (line 2482) | _finishTap(e) {
    method _clearTapTimer (line 2531) | _clearTapTimer() {
    method _getVelocity (line 2547) | _getVelocity(axis, duration) {
    method _rafStopLoop (line 2562) | _rafStopLoop() {
    method _preventPointerEventBehaviour (line 2575) | _preventPointerEventBehaviour(e, pointerType) {
    method _updatePoints (line 2592) | _updatePoints(e, pointerType) {
    method _updatePrevPoints (line 2666) | _updatePrevPoints() {
    method _updateStartPoints (line 2675) | _updateStartPoints() {
    method _calculateDragDirection (line 2684) | _calculateDragDirection() {
    method _convertEventPosToPoint (line 2713) | _convertEventPosToPoint(e, p) {
    method _onClick (line 2731) | _onClick(e) {
  constant MAIN_SCROLL_END_FRICTION (line 2747) | const MAIN_SCROLL_END_FRICTION = 0.35;
  class MainScroll (line 2758) | class MainScroll {
    method constructor (line 2762) | constructor(pswp) {
    method resize (line 2787) | resize(resizeSlides) {
    method resetPosition (line 2817) | resetPosition() {
    method appendHolders (line 2833) | appendHolders() {
    method canBeSwiped (line 2856) | canBeSwiped() {
    method moveIndexBy (line 2876) | moveIndexBy(diff, animate, velocityX) {
    method getCurrSlideX (line 2959) | getCurrSlideX() {
    method isShifted (line 2969) | isShifted() {
    method updateCurrItem (line 2977) | updateCurrItem() {
    method moveTo (line 3068) | moveTo(x, dragging) {
  class Keyboard (line 3126) | class Keyboard {
    method constructor (line 3130) | constructor(pswp) {
    method _focusRoot (line 3166) | _focusRoot() {
    method _onKeyDown (line 3178) | _onKeyDown(e) {
    method _onFocusIn (line 3275) | _onFocusIn(e) {
  constant DEFAULT_EASING (line 3290) | const DEFAULT_EASING = 'cubic-bezier(.4,0,.22,1)';
  class CSSAnimation (line 3308) | class CSSAnimation {
    method constructor (line 3314) | constructor(props) {
    method _onTransitionEnd (line 3372) | _onTransitionEnd(e) {
    method _finalizeAnimation (line 3382) | _finalizeAnimation() {
    method destroy (line 3394) | destroy() {
  constant DEFAULT_NATURAL_FREQUENCY (line 3412) | const DEFAULT_NATURAL_FREQUENCY = 12;
  constant DEFAULT_DAMPING_RATIO (line 3413) | const DEFAULT_DAMPING_RATIO = 0.75;
  class SpringEaser (line 3418) | class SpringEaser {
    method constructor (line 3434) | constructor(initialVelocity, dampingRatio, naturalFrequency) {
    method easeFrame (line 3455) | easeFrame(deltaPosition, deltaTime) {
  class SpringAnimation (line 3498) | class SpringAnimation {
    method constructor (line 3502) | constructor(props) {
    method destroy (line 3545) | destroy() {
  class Animations (line 3575) | class Animations {
    method constructor (line 3576) | constructor() {
    method startSpring (line 3585) | startSpring(props) {
    method startTransition (line 3593) | startTransition(props) {
    method _start (line 3604) | _start(props, isSpring) {
    method stop (line 3621) | stop(animation) {
    method stopAll (line 3630) | stopAll() {
    method stopAllPan (line 3642) | stopAllPan() {
    method stopMainScroll (line 3653) | stopMainScroll() {
    method isPanRunning (line 3677) | isPanRunning() {
  class ScrollWheel (line 3691) | class ScrollWheel {
    method constructor (line 3695) | constructor(pswp) {
    method _onWheel (line 3707) | _onWheel(e) {
  function addElementHTML (line 3804) | function addElementHTML(htmlData) {
  class UIElement (line 3840) | class UIElement {
    method constructor (line 3845) | constructor(pswp, data) {
  function initArrowButton (line 3974) | function initArrowButton(element, pswp, isNextButton) {
  function setZoomedIn (line 4159) | function setZoomedIn(el, isZoomedIn) {
  class UI (line 4163) | class UI {
    method constructor (line 4167) | constructor(pswp) {
    method init (line 4188) | init() {
    method registerElement (line 4217) | registerElement(elementData) {
    method _onZoomPanUpdate (line 4232) | _onZoomPanUpdate() {
  function getBoundsByElement (line 4286) | function getBoundsByElement(el) {
  function getCroppedBoundsByElement (line 4302) | function getCroppedBoundsByElement(el, imageWidth, imageHeight) {
  function getThumbBounds (line 4345) | function getThumbBounds(index, itemData, instance) {
  class PhotoSwipeEvent (line 4606) | class PhotoSwipeEvent {
    method constructor (line 4611) | constructor(type, details) {
    method preventDefault (line 4620) | preventDefault() {
  class Eventable (line 4631) | class Eventable {
    method constructor (line 4632) | constructor() {
    method addFilter (line 4657) | addFilter(name, fn, priority = 100) {
    method removeFilter (line 4678) | removeFilter(name, fn) {
    method applyFilters (line 4696) | applyFilters(name, ...args) {
    method on (line 4712) | on(name, fn) {
    method off (line 4732) | off(name, fn) {
    method dispatch (line 4750) | dispatch(name, details) {
  class Placeholder (line 4768) | class Placeholder {
    method constructor (line 4773) | constructor(imageSrc, container) {
    method setDisplayedSize (line 4798) | setDisplayedSize(width, height) {
    method destroy (line 4815) | destroy() {
  class Content (line 4835) | class Content {
    method constructor (line 4841) | constructor(itemData, instance, index) {
    method removePlaceholder (line 4878) | removePlaceholder() {
    method load (line 4897) | load(isLazy, reload) {
    method loadImage (line 4947) | loadImage(isLazy) {
    method setSlide (line 4989) | setSlide(slide) {
    method onLoaded (line 4999) | onLoaded() {
    method onError (line 5023) | onError() {
    method isLoading (line 5044) | isLoading() {
    method isError (line 5052) | isError() {
    method isImageContent (line 5060) | isImageContent() {
    method setDisplayedSize (line 5071) | setDisplayedSize(width, height) {
    method isZoomable (line 5116) | isZoomable() {
    method updateSrcsetSizes (line 5124) | updateSrcsetSizes() {
    method usePlaceholder (line 5149) | usePlaceholder() {
    method lazyLoad (line 5157) | lazyLoad() {
    method keepPlaceholder (line 5171) | keepPlaceholder() {
    method destroy (line 5179) | destroy() {
    method displayError (line 5207) | displayError() {
    method append (line 5229) | append() {
    method activate (line 5286) | activate() {
    method deactivate (line 5310) | deactivate() {
    method remove (line 5324) | remove() {
    method appendImage (line 5346) | appendImage() {
  constant MIN_SLIDES_TO_CACHE (line 5379) | const MIN_SLIDES_TO_CACHE = 5;
  function lazyLoadData (line 5391) | function lazyLoadData(itemData, instance, index) {
  function lazyLoadSlide (line 5435) | function lazyLoadSlide(index, instance) {
  class ContentLoader (line 5448) | class ContentLoader {
    method constructor (line 5452) | constructor(pswp) {
    method updateLazy (line 5467) | updateLazy(diff) {
    method loadSlideByIndex (line 5496) | loadSlideByIndex(initialIndex) {
    method getContentBySlide (line 5516) | getContentBySlide(slide) {
    method addToCache (line 5534) | addToCache(content) {
    method removeByIndex (line 5560) | removeByIndex(index) {
    method getContentByIndex (line 5573) | getContentByIndex(index) {
    method destroy (line 5577) | destroy() {
  class PhotoSwipeBase (line 5594) | class PhotoSwipeBase extends Eventable {
    method getNumItems (line 5600) | getNumItems() {
    method createContentFromData (line 5634) | createContentFromData(slideData, index) {
    method getItemData (line 5649) | getItemData(index) {
    method _getGalleryDOMElements (line 5695) | _getGalleryDOMElements(galleryElement) {
    method _domElementToItemData (line 5712) | _domElementToItemData(element) {
    method lazyLoadData (line 5767) | lazyLoadData(itemData, index) {
  constant MIN_OPACITY (line 5783) | const MIN_OPACITY = 0.003;
  class Opener (line 5790) | class Opener {
    method constructor (line 5794) | constructor(pswp) {
    method open (line 5853) | open() {
    method close (line 5859) | close() {
    method _prepareOpen (line 5886) | _prepareOpen() {
    method _applyStartProps (line 5905) | _applyStartProps() {
    method _start (line 6035) | _start() {
    method _initiate (line 6071) | _initiate() {
    method _onAnimationComplete (line 6100) | _onAnimationComplete() {
    method _animateToOpenState (line 6130) | _animateToOpenState() {
    method _animateToClosedState (line 6160) | _animateToClosedState() {
    method _setClosedStateZoomPan (line 6184) | _setClosedStateZoomPan(animate) {
    method _animateTo (line 6232) | _animateTo(target, prop, propValue) {
  class PhotoSwipe (line 6512) | class PhotoSwipe extends PhotoSwipeBase {
    method constructor (line 6516) | constructor(options) {
    method init (line 6596) | init() {
    method getLoopedIndex (line 6691) | getLoopedIndex(index) {
    method appendHeavy (line 6707) | appendHeavy() {
    method goTo (line 6720) | goTo(index) {
    method next (line 6728) | next() {
    method prev (line 6736) | prev() {
    method zoomTo (line 6746) | zoomTo(...args) {
    method toggleZoom (line 6756) | toggleZoom() {
    method close (line 6767) | close() {
    method destroy (line 6786) | destroy() {
    method refreshSlideContent (line 6819) | refreshSlideContent(slideIndex) {
    method setContent (line 6853) | setContent(holder, index, force) {
    method getViewportCenterPoint (line 6887) | getViewportCenterPoint() {
    method updateSize (line 6901) | updateSize(force) {
    method applyBgOpacity (line 6943) | applyBgOpacity(opacity) {
    method mouseDetected (line 6955) | mouseDetected() {
    method _handlePageResize (line 6970) | _handlePageResize() {
    method _updatePageScrollOffset (line 6992) | _updatePageScrollOffset() {
    method setScrollOffset (line 7001) | setScrollOffset(x, y) {
    method _createMainStructure (line 7014) | _createMainStructure() {
    method getThumbBounds (line 7046) | getThumbBounds() {
    method canLoop (line 7055) | canLoop() {
    method _prepareOptions (line 7065) | _prepareOptions(options) {

FILE: dist/photoswipe-lightbox.esm.js
  function createElement (line 14) | function createElement(className, tagName, appendToEl) {
  function toTransformString (line 36) | function toTransformString(x, y, scale) {
  function setWidthHeight (line 53) | function setWidthHeight(el, w, h) {
  constant LOAD_STATE (line 61) | const LOAD_STATE = {
  function specialKeyUsed (line 75) | function specialKeyUsed(e) {
  function getElementsFromOption (line 87) | function getElementsFromOption(option, legacySelector, parent = document) {
  function isPswpClass (line 112) | function isPswpClass(fn) {
  function isSafari (line 121) | function isSafari() {
  class PhotoSwipeEvent (line 343) | class PhotoSwipeEvent {
    method constructor (line 348) | constructor(type, details) {
    method preventDefault (line 357) | preventDefault() {
  class Eventable (line 368) | class Eventable {
    method constructor (line 369) | constructor() {
    method addFilter (line 394) | addFilter(name, fn, priority = 100) {
    method removeFilter (line 415) | removeFilter(name, fn) {
    method applyFilters (line 433) | applyFilters(name, ...args) {
    method on (line 449) | on(name, fn) {
    method off (line 469) | off(name, fn) {
    method dispatch (line 487) | dispatch(name, details) {
  class Placeholder (line 505) | class Placeholder {
    method constructor (line 510) | constructor(imageSrc, container) {
    method setDisplayedSize (line 535) | setDisplayedSize(width, height) {
    method destroy (line 552) | destroy() {
  class Content (line 572) | class Content {
    method constructor (line 578) | constructor(itemData, instance, index) {
    method removePlaceholder (line 615) | removePlaceholder() {
    method load (line 634) | load(isLazy, reload) {
    method loadImage (line 684) | loadImage(isLazy) {
    method setSlide (line 726) | setSlide(slide) {
    method onLoaded (line 736) | onLoaded() {
    method onError (line 760) | onError() {
    method isLoading (line 781) | isLoading() {
    method isError (line 789) | isError() {
    method isImageContent (line 797) | isImageContent() {
    method setDisplayedSize (line 808) | setDisplayedSize(width, height) {
    method isZoomable (line 853) | isZoomable() {
    method updateSrcsetSizes (line 861) | updateSrcsetSizes() {
    method usePlaceholder (line 886) | usePlaceholder() {
    method lazyLoad (line 894) | lazyLoad() {
    method keepPlaceholder (line 908) | keepPlaceholder() {
    method destroy (line 916) | destroy() {
    method displayError (line 944) | displayError() {
    method append (line 966) | append() {
    method activate (line 1023) | activate() {
    method deactivate (line 1047) | deactivate() {
    method remove (line 1061) | remove() {
    method appendImage (line 1083) | appendImage() {
  function getViewportSize (line 1119) | function getViewportSize(options, pswp) {
  function parsePaddingOption (line 1173) | function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  function getPanAreaSize (line 1199) | function getPanAreaSize(options, viewportSize, itemData, index) {
  constant MAX_IMAGE_WIDTH (line 1206) | const MAX_IMAGE_WIDTH = 4000;
  class ZoomLevel (line 1222) | class ZoomLevel {
    method constructor (line 1229) | constructor(options, itemData, index, pswp) {
    method update (line 1259) | update(maxWidth, maxHeight, panAreaSize) {
    method _parseZoomLevelOption (line 1295) | _parseZoomLevelOption(optionPrefix) {
    method _getSecondary (line 1330) | _getSecondary() {
    method _getInitial (line 1354) | _getInitial() {
    method _getMax (line 1367) | _getMax() {
  function lazyLoadData (line 1386) | function lazyLoadData(itemData, instance, index) {
  function lazyLoadSlide (line 1430) | function lazyLoadSlide(index, instance) {
  class PhotoSwipeBase (line 1452) | class PhotoSwipeBase extends Eventable {
    method getNumItems (line 1458) | getNumItems() {
    method createContentFromData (line 1492) | createContentFromData(slideData, index) {
    method getItemData (line 1507) | getItemData(index) {
    method _getGalleryDOMElements (line 1553) | _getGalleryDOMElements(galleryElement) {
    method _domElementToItemData (line 1570) | _domElementToItemData(element) {
    method lazyLoadData (line 1625) | lazyLoadData(itemData, index) {
  class PhotoSwipeLightbox (line 1671) | class PhotoSwipeLightbox extends PhotoSwipeBase {
    method constructor (line 1675) | constructor(options) {
    method init (line 1696) | init() {
    method onThumbnailsClick (line 1707) | onThumbnailsClick(e) {
    method getClickedIndex (line 1756) | getClickedIndex(e) {
    method loadAndOpen (line 1790) | loadAndOpen(index, dataSource, initialPoint) {
    method preload (line 1823) | preload(index, dataSource) {
    method _openPhotoswipe (line 1879) | _openPhotoswipe(module, uid) {
    method destroy (line 1946) | destroy() {

FILE: dist/photoswipe.esm.js
  function createElement (line 14) | function createElement(className, tagName, appendToEl) {
  function equalizePoints (line 33) | function equalizePoints(p1, p2) {
  function roundPoint (line 47) | function roundPoint(p) {
  function getDistanceBetween (line 59) | function getDistanceBetween(p1, p2) {
  function pointsEqual (line 72) | function pointsEqual(p1, p2) {
  function clamp (line 84) | function clamp(val, min, max) {
  function toTransformString (line 96) | function toTransformString(x, y, scale) {
  function setTransform (line 114) | function setTransform(el, x, y, scale) {
  function setTransitionStyle (line 127) | function setTransitionStyle(el, prop, duration, ease) {
  function setWidthHeight (line 141) | function setWidthHeight(el, w, h) {
  function removeTransitionStyle (line 149) | function removeTransitionStyle(el) {
  function decodeImage (line 157) | function decodeImage(img) {
  constant LOAD_STATE (line 176) | const LOAD_STATE = {
  function specialKeyUsed (line 190) | function specialKeyUsed(e) {
  function getElementsFromOption (line 202) | function getElementsFromOption(option, legacySelector, parent = document) {
  function isSafari (line 226) | function isSafari() {
  class DOMEvents (line 253) | class DOMEvents {
    method constructor (line 254) | constructor() {
    method add (line 271) | add(target, type, listener, passive) {
    method remove (line 284) | remove(target, type, listener, passive) {
    method removeAll (line 292) | removeAll() {
    method _toggleListener (line 312) | _toggleListener(target, type, listener, passive, unbind, skipPool) {
  function getViewportSize (line 365) | function getViewportSize(options, pswp) {
  function parsePaddingOption (line 419) | function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  function getPanAreaSize (line 445) | function getPanAreaSize(options, viewportSize, itemData, index) {
  class PanBounds (line 462) | class PanBounds {
    method constructor (line 466) | constructor(slide) {
    method update (line 495) | update(currZoomLevel) {
    method _updateAxis (line 517) | _updateAxis(axis) {
    method reset (line 535) | reset() {
    method correctPan (line 552) | correctPan(axis, panOffset) {
  constant MAX_IMAGE_WIDTH (line 559) | const MAX_IMAGE_WIDTH = 4000;
  class ZoomLevel (line 575) | class ZoomLevel {
    method constructor (line 582) | constructor(options, itemData, index, pswp) {
    method update (line 612) | update(maxWidth, maxHeight, panAreaSize) {
    method _parseZoomLevelOption (line 648) | _parseZoomLevelOption(optionPrefix) {
    method _getSecondary (line 683) | _getSecondary() {
    method _getInitial (line 707) | _getInitial() {
    method _getMax (line 720) | _getMax() {
  class Slide (line 733) | class Slide {
    method constructor (line 739) | constructor(data, index, pswp) {
    method setIsActive (line 791) | setIsActive(isActive) {
    method append (line 807) | append(holderElement) {
    method load (line 834) | load() {
    method appendHeavy (line 848) | appendHeavy() {
    method activate (line 879) | activate() {
    method deactivate (line 894) | deactivate() {
    method destroy (line 918) | destroy() {
    method resize (line 927) | resize() {
    method updateContentSize (line 952) | updateContentSize(force) {
    method sizeChanged (line 976) | sizeChanged(width, height) {
    method getPlaceholderElement (line 988) | getPlaceholderElement() {
    method zoomTo (line 1004) | zoomTo(destZoomLevel, centerPoint, transitionDuration, ignoreBounds) {
    method toggleZoom (line 1062) | toggleZoom(centerPoint) {
    method setZoomLevel (line 1073) | setZoomLevel(currZoomLevel) {
    method calculateZoomToPanOffset (line 1092) | calculateZoomToPanOffset(axis, point, prevZoomLevel) {
    method panTo (line 1118) | panTo(panX, panY) {
    method isPannable (line 1129) | isPannable() {
    method isZoomable (line 1138) | isZoomable() {
    method applyCurrentZoomPan (line 1147) | applyCurrentZoomPan() {
    method zoomAndPanToInitial (line 1157) | zoomAndPanToInitial() {
    method _applyZoomTransform (line 1176) | _applyZoomTransform(x, y, zoom) {
    method calculateSize (line 1181) | calculateSize() {
    method getCurrentTransform (line 1194) | getCurrentTransform() {
    method _setResolution (line 1215) | _setResolution(newResolution) {
  constant PAN_END_FRICTION (line 1231) | const PAN_END_FRICTION = 0.35;
  constant VERTICAL_DRAG_FRICTION (line 1232) | const VERTICAL_DRAG_FRICTION = 0.6;
  constant MIN_RATIO_TO_CLOSE (line 1234) | const MIN_RATIO_TO_CLOSE = 0.4;
  constant MIN_NEXT_SLIDE_SPEED (line 1237) | const MIN_NEXT_SLIDE_SPEED = 0.5;
  function project (line 1244) | function project(initialVelocity, decelerationRate) {
  class DragHandler (line 1252) | class DragHandler {
    method constructor (line 1256) | constructor(gestures) {
    method start (line 1267) | start() {
    method change (line 1275) | change() {
    method end (line 1312) | end() {
    method _finishPanGestureForAxis (line 1371) | _finishPanGestureForAxis(axis) {
    method _panOrMoveMainScroll (line 1456) | _panOrMoveMainScroll(axis) {
    method _getVerticalDragRatio (line 1567) | _getVerticalDragRatio(panY) {
    method _setPanWithFriction (line 1584) | _setPanWithFriction(axis, potentialPan, customFriction) {
  constant UPPER_ZOOM_FRICTION (line 1613) | const UPPER_ZOOM_FRICTION = 0.05;
  constant LOWER_ZOOM_FRICTION (line 1614) | const LOWER_ZOOM_FRICTION = 0.15;
  function getZoomPointsCenter (line 1624) | function getZoomPointsCenter(p, p1, p2) {
  class ZoomHandler (line 1630) | class ZoomHandler {
    method constructor (line 1634) | constructor(gestures) {
    method start (line 1671) | start() {
    method change (line 1685) | change() {
    method end (line 1743) | end() {
    method _calculatePanForZoomLevel (line 1765) | _calculatePanForZoomLevel(axis, currZoomLevel) {
    method correctZoomPan (line 1779) | correctZoomPan(ignoreGesture) {
  function didTapOnMainContent (line 1919) | function didTapOnMainContent(event) {
  class TapHandler (line 1929) | class TapHandler {
    method constructor (line 1933) | constructor(gestures) {
    method click (line 1942) | click(point, originalEvent) {
    method tap (line 1961) | tap(point, originalEvent) {
    method doubleTap (line 1972) | doubleTap(point, originalEvent) {
    method _doClickOrTapAction (line 1985) | _doClickOrTapAction(actionName, point, originalEvent) {
  constant AXIS_SWIPE_HYSTERISIS (line 2051) | const AXIS_SWIPE_HYSTERISIS = 10;
  constant DOUBLE_TAP_DELAY (line 2053) | const DOUBLE_TAP_DELAY = 300;
  constant MIN_TAP_DISTANCE (line 2055) | const MIN_TAP_DISTANCE = 25;
  class Gestures (line 2065) | class Gestures {
    method constructor (line 2069) | constructor(pswp) {
    method _bindEvents (line 2216) | _bindEvents(pref, down, up, cancel) {
    method onPointerDown (line 2245) | onPointerDown(e) {
    method onPointerMove (line 2307) | onPointerMove(e) {
    method _finishDrag (line 2373) | _finishDrag() {
    method onPointerUp (line 2391) | onPointerUp(e) {
    method _rafRenderLoop (line 2432) | _rafRenderLoop() {
    method _updateVelocity (line 2462) | _updateVelocity(force) {
    method _finishTap (line 2482) | _finishTap(e) {
    method _clearTapTimer (line 2531) | _clearTapTimer() {
    method _getVelocity (line 2547) | _getVelocity(axis, duration) {
    method _rafStopLoop (line 2562) | _rafStopLoop() {
    method _preventPointerEventBehaviour (line 2575) | _preventPointerEventBehaviour(e, pointerType) {
    method _updatePoints (line 2592) | _updatePoints(e, pointerType) {
    method _updatePrevPoints (line 2666) | _updatePrevPoints() {
    method _updateStartPoints (line 2675) | _updateStartPoints() {
    method _calculateDragDirection (line 2684) | _calculateDragDirection() {
    method _convertEventPosToPoint (line 2713) | _convertEventPosToPoint(e, p) {
    method _onClick (line 2731) | _onClick(e) {
  constant MAIN_SCROLL_END_FRICTION (line 2747) | const MAIN_SCROLL_END_FRICTION = 0.35;
  class MainScroll (line 2758) | class MainScroll {
    method constructor (line 2762) | constructor(pswp) {
    method resize (line 2787) | resize(resizeSlides) {
    method resetPosition (line 2817) | resetPosition() {
    method appendHolders (line 2833) | appendHolders() {
    method canBeSwiped (line 2856) | canBeSwiped() {
    method moveIndexBy (line 2876) | moveIndexBy(diff, animate, velocityX) {
    method getCurrSlideX (line 2959) | getCurrSlideX() {
    method isShifted (line 2969) | isShifted() {
    method updateCurrItem (line 2977) | updateCurrItem() {
    method moveTo (line 3068) | moveTo(x, dragging) {
  class Keyboard (line 3126) | class Keyboard {
    method constructor (line 3130) | constructor(pswp) {
    method _focusRoot (line 3166) | _focusRoot() {
    method _onKeyDown (line 3178) | _onKeyDown(e) {
    method _onFocusIn (line 3275) | _onFocusIn(e) {
  constant DEFAULT_EASING (line 3290) | const DEFAULT_EASING = 'cubic-bezier(.4,0,.22,1)';
  class CSSAnimation (line 3308) | class CSSAnimation {
    method constructor (line 3314) | constructor(props) {
    method _onTransitionEnd (line 3372) | _onTransitionEnd(e) {
    method _finalizeAnimation (line 3382) | _finalizeAnimation() {
    method destroy (line 3394) | destroy() {
  constant DEFAULT_NATURAL_FREQUENCY (line 3412) | const DEFAULT_NATURAL_FREQUENCY = 12;
  constant DEFAULT_DAMPING_RATIO (line 3413) | const DEFAULT_DAMPING_RATIO = 0.75;
  class SpringEaser (line 3418) | class SpringEaser {
    method constructor (line 3434) | constructor(initialVelocity, dampingRatio, naturalFrequency) {
    method easeFrame (line 3455) | easeFrame(deltaPosition, deltaTime) {
  class SpringAnimation (line 3498) | class SpringAnimation {
    method constructor (line 3502) | constructor(props) {
    method destroy (line 3545) | destroy() {
  class Animations (line 3575) | class Animations {
    method constructor (line 3576) | constructor() {
    method startSpring (line 3585) | startSpring(props) {
    method startTransition (line 3593) | startTransition(props) {
    method _start (line 3604) | _start(props, isSpring) {
    method stop (line 3621) | stop(animation) {
    method stopAll (line 3630) | stopAll() {
    method stopAllPan (line 3642) | stopAllPan() {
    method stopMainScroll (line 3653) | stopMainScroll() {
    method isPanRunning (line 3677) | isPanRunning() {
  class ScrollWheel (line 3691) | class ScrollWheel {
    method constructor (line 3695) | constructor(pswp) {
    method _onWheel (line 3707) | _onWheel(e) {
  function addElementHTML (line 3804) | function addElementHTML(htmlData) {
  class UIElement (line 3840) | class UIElement {
    method constructor (line 3845) | constructor(pswp, data) {
  function initArrowButton (line 3974) | function initArrowButton(element, pswp, isNextButton) {
  function setZoomedIn (line 4159) | function setZoomedIn(el, isZoomedIn) {
  class UI (line 4163) | class UI {
    method constructor (line 4167) | constructor(pswp) {
    method init (line 4188) | init() {
    method registerElement (line 4217) | registerElement(elementData) {
    method _onZoomPanUpdate (line 4232) | _onZoomPanUpdate() {
  function getBoundsByElement (line 4286) | function getBoundsByElement(el) {
  function getCroppedBoundsByElement (line 4302) | function getCroppedBoundsByElement(el, imageWidth, imageHeight) {
  function getThumbBounds (line 4345) | function getThumbBounds(index, itemData, instance) {
  class PhotoSwipeEvent (line 4606) | class PhotoSwipeEvent {
    method constructor (line 4611) | constructor(type, details) {
    method preventDefault (line 4620) | preventDefault() {
  class Eventable (line 4631) | class Eventable {
    method constructor (line 4632) | constructor() {
    method addFilter (line 4657) | addFilter(name, fn, priority = 100) {
    method removeFilter (line 4678) | removeFilter(name, fn) {
    method applyFilters (line 4696) | applyFilters(name, ...args) {
    method on (line 4712) | on(name, fn) {
    method off (line 4732) | off(name, fn) {
    method dispatch (line 4750) | dispatch(name, details) {
  class Placeholder (line 4768) | class Placeholder {
    method constructor (line 4773) | constructor(imageSrc, container) {
    method setDisplayedSize (line 4798) | setDisplayedSize(width, height) {
    method destroy (line 4815) | destroy() {
  class Content (line 4835) | class Content {
    method constructor (line 4841) | constructor(itemData, instance, index) {
    method removePlaceholder (line 4878) | removePlaceholder() {
    method load (line 4897) | load(isLazy, reload) {
    method loadImage (line 4947) | loadImage(isLazy) {
    method setSlide (line 4989) | setSlide(slide) {
    method onLoaded (line 4999) | onLoaded() {
    method onError (line 5023) | onError() {
    method isLoading (line 5044) | isLoading() {
    method isError (line 5052) | isError() {
    method isImageContent (line 5060) | isImageContent() {
    method setDisplayedSize (line 5071) | setDisplayedSize(width, height) {
    method isZoomable (line 5116) | isZoomable() {
    method updateSrcsetSizes (line 5124) | updateSrcsetSizes() {
    method usePlaceholder (line 5149) | usePlaceholder() {
    method lazyLoad (line 5157) | lazyLoad() {
    method keepPlaceholder (line 5171) | keepPlaceholder() {
    method destroy (line 5179) | destroy() {
    method displayError (line 5207) | displayError() {
    method append (line 5229) | append() {
    method activate (line 5286) | activate() {
    method deactivate (line 5310) | deactivate() {
    method remove (line 5324) | remove() {
    method appendImage (line 5346) | appendImage() {
  constant MIN_SLIDES_TO_CACHE (line 5379) | const MIN_SLIDES_TO_CACHE = 5;
  function lazyLoadData (line 5391) | function lazyLoadData(itemData, instance, index) {
  function lazyLoadSlide (line 5435) | function lazyLoadSlide(index, instance) {
  class ContentLoader (line 5448) | class ContentLoader {
    method constructor (line 5452) | constructor(pswp) {
    method updateLazy (line 5467) | updateLazy(diff) {
    method loadSlideByIndex (line 5496) | loadSlideByIndex(initialIndex) {
    method getContentBySlide (line 5516) | getContentBySlide(slide) {
    method addToCache (line 5534) | addToCache(content) {
    method removeByIndex (line 5560) | removeByIndex(index) {
    method getContentByIndex (line 5573) | getContentByIndex(index) {
    method destroy (line 5577) | destroy() {
  class PhotoSwipeBase (line 5594) | class PhotoSwipeBase extends Eventable {
    method getNumItems (line 5600) | getNumItems() {
    method createContentFromData (line 5634) | createContentFromData(slideData, index) {
    method getItemData (line 5649) | getItemData(index) {
    method _getGalleryDOMElements (line 5695) | _getGalleryDOMElements(galleryElement) {
    method _domElementToItemData (line 5712) | _domElementToItemData(element) {
    method lazyLoadData (line 5767) | lazyLoadData(itemData, index) {
  constant MIN_OPACITY (line 5783) | const MIN_OPACITY = 0.003;
  class Opener (line 5790) | class Opener {
    method constructor (line 5794) | constructor(pswp) {
    method open (line 5853) | open() {
    method close (line 5859) | close() {
    method _prepareOpen (line 5886) | _prepareOpen() {
    method _applyStartProps (line 5905) | _applyStartProps() {
    method _start (line 6035) | _start() {
    method _initiate (line 6071) | _initiate() {
    method _onAnimationComplete (line 6100) | _onAnimationComplete() {
    method _animateToOpenState (line 6130) | _animateToOpenState() {
    method _animateToClosedState (line 6160) | _animateToClosedState() {
    method _setClosedStateZoomPan (line 6184) | _setClosedStateZoomPan(animate) {
    method _animateTo (line 6232) | _animateTo(target, prop, propValue) {
  class PhotoSwipe (line 6512) | class PhotoSwipe extends PhotoSwipeBase {
    method constructor (line 6516) | constructor(options) {
    method init (line 6596) | init() {
    method getLoopedIndex (line 6691) | getLoopedIndex(index) {
    method appendHeavy (line 6707) | appendHeavy() {
    method goTo (line 6720) | goTo(index) {
    method next (line 6728) | next() {
    method prev (line 6736) | prev() {
    method zoomTo (line 6746) | zoomTo(...args) {
    method toggleZoom (line 6756) | toggleZoom() {
    method close (line 6767) | close() {
    method destroy (line 6786) | destroy() {
    method refreshSlideContent (line 6819) | refreshSlideContent(slideIndex) {
    method setContent (line 6853) | setContent(holder, index, force) {
    method getViewportCenterPoint (line 6887) | getViewportCenterPoint() {
    method updateSize (line 6901) | updateSize(force) {
    method applyBgOpacity (line 6943) | applyBgOpacity(opacity) {
    method mouseDetected (line 6955) | mouseDetected() {
    method _handlePageResize (line 6970) | _handlePageResize() {
    method _updatePageScrollOffset (line 6992) | _updatePageScrollOffset() {
    method setScrollOffset (line 7001) | setScrollOffset(x, y) {
    method _createMainStructure (line 7014) | _createMainStructure() {
    method getThumbBounds (line 7046) | getThumbBounds() {
    method canLoop (line 7055) | canLoop() {
    method _prepareOptions (line 7065) | _prepareOptions(options) {

FILE: dist/types/core/base.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import("../photoswipe.js").default;
  type SlideData (line 3) | type SlideData = import("../slide/slide.js").SlideData;
  class PhotoSwipeBase (line 10) | class PhotoSwipeBase extends Eventable {

FILE: dist/types/core/eventable.d.ts
  type PhotoSwipeLightbox (line 2) | type PhotoSwipeLightbox = import('../lightbox/lightbox.js').default;
  type PhotoSwipe (line 3) | type PhotoSwipe = import('../photoswipe.js').default;
  type PhotoSwipeOptions (line 4) | type PhotoSwipeOptions = import('../photoswipe.js').PhotoSwipeOptions;
  type DataSource (line 5) | type DataSource = import('../photoswipe.js').DataSource;
  type UIElementData (line 6) | type UIElementData = import('../ui/ui-element.js').UIElementData;
  type ContentDefault (line 7) | type ContentDefault = import('../slide/content.js').default;
  type Slide (line 8) | type Slide = import('../slide/slide.js').default;
  type SlideData (line 9) | type SlideData = import('../slide/slide.js').SlideData;
  type ZoomLevel (line 10) | type ZoomLevel = import('../slide/zoom-level.js').default;
  type Bounds (line 11) | type Bounds = import('../slide/get-thumb-bounds.js').Bounds;
  type Content (line 16) | type Content = ContentDefault & Record<string, any>;
  type Point (line 17) | type Point = {
  type PhotoSwipeEventsMap (line 27) | type PhotoSwipeEventsMap = {
  type PhotoSwipeFiltersMap (line 303) | type PhotoSwipeFiltersMap = {
  type Filter (line 372) | type Filter<T extends keyof PhotoSwipeFiltersMap> = {
  type AugmentedEvent (line 376) | type AugmentedEvent<T extends keyof PhotoSwipeEventsMap> = PhotoSwipeEve...
  type EventCallback (line 377) | type EventCallback<T extends keyof PhotoSwipeEventsMap> = (event: Augmen...
  class Eventable (line 382) | class Eventable {
  class PhotoSwipeEvent (line 976) | class PhotoSwipeEvent<T extends keyof PhotoSwipeEventsMap> {

FILE: dist/types/gestures/drag-handler.d.ts
  type Point (line 2) | type Point = import('../photoswipe.js').Point;
  type Gestures (line 3) | type Gestures = import('./gestures.js').default;
  class DragHandler (line 7) | class DragHandler {

FILE: dist/types/gestures/gestures.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('../photoswipe.js').default;
  type Point (line 3) | type Point = import('../photoswipe.js').Point;
  class Gestures (line 11) | class Gestures {

FILE: dist/types/gestures/tap-handler.d.ts
  type AddPostfix (line 5) | type AddPostfix<T extends string, P extends string> = import('../types.j...
  type Gestures (line 6) | type Gestures = import('./gestures.js').default;
  type Point (line 7) | type Point = import('../photoswipe.js').Point;
  type Actions (line 8) | type Actions = 'imageClick' | 'bgClick' | 'tap' | 'doubleTap';
  class TapHandler (line 12) | class TapHandler {

FILE: dist/types/gestures/zoom-handler.d.ts
  type Point (line 2) | type Point = import('../photoswipe.js').Point;
  type Gestures (line 3) | type Gestures = import('./gestures.js').default;
  class ZoomHandler (line 4) | class ZoomHandler {

FILE: dist/types/keyboard.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('./photoswipe.js').default;
  type Methods (line 6) | type Methods<T> = import('./types.js').Methods
  class Keyboard (line 11) | class Keyboard {

FILE: dist/types/lightbox/lightbox.d.ts
  type Type (line 5) | type Type<T> = import('../types.js').Type
  type PhotoSwipe (line 6) | type PhotoSwipe = import('../photoswipe.js').default;
  type PhotoSwipeOptions (line 7) | type PhotoSwipeOptions = import('../photoswipe.js').PhotoSwipeOptions;
  type DataSource (line 8) | type DataSource = import('../photoswipe.js').DataSource;
  type Point (line 9) | type Point = import('../photoswipe.js').Point;
  type Content (line 10) | type Content = import('../slide/content.js').default;
  type PhotoSwipeEventsMap (line 11) | type PhotoSwipeEventsMap = import('../core/eventable.js').PhotoSwipeEven...
  type PhotoSwipeFiltersMap (line 12) | type PhotoSwipeFiltersMap = import('../core/eventable.js').PhotoSwipeFil...
  class PhotoSwipeLightbox (line 47) | class PhotoSwipeLightbox extends PhotoSwipeBase {

FILE: dist/types/main-scroll.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('./photoswipe.js').default;
  type Slide (line 3) | type Slide = import('./slide/slide.js').default;
  type ItemHolder (line 4) | type ItemHolder = {
  class MainScroll (line 14) | class MainScroll {

FILE: dist/types/opener.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('./photoswipe.js').default;
  type Bounds (line 3) | type Bounds = import('./slide/get-thumb-bounds.js').Bounds;
  type AnimationProps (line 4) | type AnimationProps = import('./util/animations.js').AnimationProps;
  class Opener (line 10) | class Opener {

FILE: dist/types/photoswipe.d.ts
  type Type (line 5) | type Type<T> = import('./types.js').Type
  type SlideData (line 6) | type SlideData = import('./slide/slide.js').SlideData;
  type ZoomLevelOption (line 7) | type ZoomLevelOption = import('./slide/zoom-level.js').ZoomLevelOption;
  type UIElementData (line 8) | type UIElementData = import('./ui/ui-element.js').UIElementData;
  type ItemHolder (line 9) | type ItemHolder = import('./main-scroll.js').ItemHolder;
  type PhotoSwipeEventsMap (line 10) | type PhotoSwipeEventsMap = import('./core/eventable.js').PhotoSwipeEvent...
  type PhotoSwipeFiltersMap (line 11) | type PhotoSwipeFiltersMap = import('./core/eventable.js').PhotoSwipeFilt...
  type Bounds (line 12) | type Bounds = import('./slide/get-thumb-bounds').Bounds;

FILE: dist/types/scroll-wheel.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('./photoswipe.js').default;
  class ScrollWheel (line 8) | class ScrollWheel {

FILE: dist/types/slide/content.d.ts
  type Slide (line 2) | type Slide = import('./slide.js').default;
  type SlideData (line 3) | type SlideData = import('./slide.js').SlideData;
  type PhotoSwipeBase (line 4) | type PhotoSwipeBase = import('../core/base.js').default;
  type LoadState (line 5) | type LoadState = import('../util/util.js').LoadState;
  class Content (line 10) | class Content {

FILE: dist/types/slide/get-thumb-bounds.d.ts
  type SlideData (line 11) | type SlideData = import('./slide.js').SlideData;
  type PhotoSwipe (line 12) | type PhotoSwipe = import('../photoswipe.js').default;
  type Bounds (line 13) | type Bounds = {

FILE: dist/types/slide/loader.d.ts
  type Content (line 25) | type Content = import('./content.js').default;
  type Slide (line 26) | type Slide = import('./slide.js').default;
  type SlideData (line 27) | type SlideData = import('./slide.js').SlideData;
  type PhotoSwipeBase (line 28) | type PhotoSwipeBase = import('../core/base.js').default;
  type PhotoSwipe (line 29) | type PhotoSwipe = import('../photoswipe.js').default;
  class ContentLoader (line 30) | class ContentLoader {

FILE: dist/types/slide/pan-bounds.d.ts
  type Slide (line 2) | type Slide = import('./slide.js').default;
  type Point (line 3) | type Point = Record<Axis, number>;
  type Axis (line 4) | type Axis = 'x' | 'y';
  class PanBounds (line 11) | class PanBounds {

FILE: dist/types/slide/placeholder.d.ts
  class Placeholder (line 2) | class Placeholder {

FILE: dist/types/slide/slide.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('../photoswipe.js').default;
  type Point (line 3) | type Point = import('../photoswipe.js').Point;
  type SlideData (line 4) | type SlideData = _SlideData & Record<string, any>;
  type _SlideData (line 5) | type _SlideData = {
  class Slide (line 58) | class Slide {

FILE: dist/types/slide/zoom-level.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('../photoswipe.js').default;
  type PhotoSwipeOptions (line 3) | type PhotoSwipeOptions = import('../photoswipe.js').PhotoSwipeOptions;
  type Point (line 4) | type Point = import('../photoswipe.js').Point;
  type SlideData (line 5) | type SlideData = import('../slide/slide.js').SlideData;
  type ZoomLevelOption (line 6) | type ZoomLevelOption = number | "fit" | "fill" | ((zoomLevelObject: Zoom...
  class ZoomLevel (line 16) | class ZoomLevel {

FILE: dist/types/types.d.ts
  type Methods (line 1) | type Methods<T> = {
  type AddPostfix (line 4) | type AddPostfix<T extends string, P extends string> = `${T}${P}`;
  type Type (line 5) | interface Type<T> extends Function {

FILE: dist/types/ui/button-arrow.d.ts
  type UIElementData (line 5) | type UIElementData = import('./ui-element.js').UIElementData;
  type PhotoSwipe (line 6) | type PhotoSwipe = import('../photoswipe.js').default;

FILE: dist/types/ui/ui-element.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('../photoswipe.js').default;
  type Methods (line 6) | type Methods<T> = import('../types.js').Methods
  type UIElementMarkupProps (line 7) | type UIElementMarkupProps = {
  type UIElementData (line 13) | type UIElementData = {
  type DefaultUIElements (line 26) | type DefaultUIElements = 'arrowPrev' | 'arrowNext' | 'close' | 'zoom' | ...
  type UIElementMarkup (line 27) | type UIElementMarkup = string | UIElementMarkupProps;
  class UIElement (line 28) | class UIElement {

FILE: dist/types/ui/ui.d.ts
  type PhotoSwipe (line 2) | type PhotoSwipe = import('../photoswipe.js').default;
  type UIElementData (line 3) | type UIElementData = import('./ui-element.js').UIElementData;
  class UI (line 4) | class UI {

FILE: dist/types/util/animations.d.ts
  type CssAnimationProps (line 2) | type CssAnimationProps = import('./css-animation.js').CssAnimationProps;
  type SpringAnimationProps (line 3) | type SpringAnimationProps = import('./spring-animation.js').SpringAnimat...
  type SharedAnimationProps (line 4) | type SharedAnimationProps = {
  type Animation (line 11) | type Animation = SpringAnimation | CSSAnimation;
  type AnimationProps (line 12) | type AnimationProps = SpringAnimationProps | CssAnimationProps;
  class Animations (line 27) | class Animations {

FILE: dist/types/util/css-animation.d.ts
  type SharedAnimationProps (line 2) | type SharedAnimationProps = import('./animations.js').SharedAnimationProps;
  type DefaultCssAnimationProps (line 3) | type DefaultCssAnimationProps = {
  type CssAnimationProps (line 10) | type CssAnimationProps = SharedAnimationProps & DefaultCssAnimationProps;
  class CSSAnimation (line 24) | class CSSAnimation {

FILE: dist/types/util/dom-events.d.ts
  type PoolItem (line 2) | type PoolItem = {
  class DOMEvents (line 15) | class DOMEvents {

FILE: dist/types/util/spring-animation.d.ts
  type SharedAnimationProps (line 2) | type SharedAnimationProps = import('./animations.js').SharedAnimationProps;
  type DefaultSpringAnimationProps (line 3) | type DefaultSpringAnimationProps = {
  type SpringAnimationProps (line 11) | type SpringAnimationProps = SharedAnimationProps & DefaultSpringAnimatio...
  class SpringAnimation (line 24) | class SpringAnimation {

FILE: dist/types/util/spring-easer.d.ts
  class SpringEaser (line 5) | class SpringEaser {

FILE: dist/types/util/util.d.ts
  constant LOAD_STATE (line 121) | const LOAD_STATE: {
  type Point (line 127) | type Point = import('../photoswipe.js').Point;
  type LoadState (line 128) | type LoadState = {

FILE: dist/types/util/viewport-size.d.ts
  type PhotoSwipeOptions (line 55) | type PhotoSwipeOptions = import('../photoswipe.js').PhotoSwipeOptions;
  type PhotoSwipeBase (line 56) | type PhotoSwipeBase = import('../core/base.js').default;
  type Point (line 57) | type Point = import('../photoswipe.js').Point;
  type SlideData (line 58) | type SlideData = import('../slide/slide.js').SlideData;

FILE: global.d.ts
  type Window (line 4) | interface Window {

FILE: src/js/core/base.js
  class PhotoSwipeBase (line 13) | class PhotoSwipeBase extends Eventable {
    method getNumItems (line 19) | getNumItems() {
    method createContentFromData (line 50) | createContentFromData(slideData, index) {
    method getItemData (line 64) | getItemData(index) {
    method _getGalleryDOMElements (line 107) | _getGalleryDOMElements(galleryElement) {
    method _domElementToItemData (line 125) | _domElementToItemData(element) {
    method lazyLoadData (line 181) | lazyLoadData(itemData, index) {

FILE: src/js/core/eventable.js
  class PhotoSwipeEvent (line 209) | class PhotoSwipeEvent {
    method constructor (line 214) | constructor(type, details) {
    method preventDefault (line 222) | preventDefault() {
  class Eventable (line 231) | class Eventable {
    method constructor (line 232) | constructor() {
    method addFilter (line 256) | addFilter(name, fn, priority = 100) {
    method removeFilter (line 272) | removeFilter(name, fn) {
    method applyFilters (line 289) | applyFilters(name, ...args) {
    method on (line 302) | on(name, fn) {
    method off (line 319) | off(name, fn) {
    method dispatch (line 334) | dispatch(name, details) {

FILE: src/js/gestures/drag-handler.js
  constant PAN_END_FRICTION (line 8) | const PAN_END_FRICTION = 0.35;
  constant VERTICAL_DRAG_FRICTION (line 9) | const VERTICAL_DRAG_FRICTION = 0.6;
  constant MIN_RATIO_TO_CLOSE (line 12) | const MIN_RATIO_TO_CLOSE = 0.4;
  constant MIN_NEXT_SLIDE_SPEED (line 16) | const MIN_NEXT_SLIDE_SPEED = 0.5;
  function project (line 23) | function project(initialVelocity, decelerationRate) {
  class DragHandler (line 30) | class DragHandler {
    method constructor (line 34) | constructor(gestures) {
    method start (line 41) | start() {
    method change (line 48) | change() {
    method end (line 77) | end() {
    method _finishPanGestureForAxis (line 136) | _finishPanGestureForAxis(axis) {
    method _panOrMoveMainScroll (line 222) | _panOrMoveMainScroll(axis) {
    method _getVerticalDragRatio (line 326) | _getVerticalDragRatio(panY) {
    method _setPanWithFriction (line 340) | _setPanWithFriction(axis, potentialPan, customFriction) {

FILE: src/js/gestures/gestures.js
  constant AXIS_SWIPE_HYSTERISIS (line 14) | const AXIS_SWIPE_HYSTERISIS = 10;
  constant DOUBLE_TAP_DELAY (line 17) | const DOUBLE_TAP_DELAY = 300;
  constant MIN_TAP_DISTANCE (line 18) | const MIN_TAP_DISTANCE = 25;
  class Gestures (line 27) | class Gestures {
    method constructor (line 31) | constructor(pswp) {
    method _bindEvents (line 136) | _bindEvents(pref, down, up, cancel) {
    method onPointerDown (line 161) | onPointerDown(e) {
    method onPointerMove (line 220) | onPointerMove(e) {
    method _finishDrag (line 279) | _finishDrag() {
    method onPointerUp (line 297) | onPointerUp(e) {
    method _rafRenderLoop (line 334) | _rafRenderLoop() {
    method _updateVelocity (line 361) | _updateVelocity(force) {
    method _finishTap (line 382) | _finishTap(e) {
    method _clearTapTimer (line 428) | _clearTapTimer() {
    method _getVelocity (line 443) | _getVelocity(axis, duration) {
    method _rafStopLoop (line 457) | _rafStopLoop() {
    method _preventPointerEventBehaviour (line 469) | _preventPointerEventBehaviour(e, pointerType) {
    method _updatePoints (line 484) | _updatePoints(e, pointerType) {
    method _updatePrevPoints (line 545) | _updatePrevPoints() {
    method _updateStartPoints (line 553) | _updateStartPoints() {
    method _calculateDragDirection (line 560) | _calculateDragDirection() {
    method _convertEventPosToPoint (line 588) | _convertEventPosToPoint(e, p) {
    method _onClick (line 605) | _onClick(e) {

FILE: src/js/gestures/tap-handler.js
  function didTapOnMainContent (line 19) | function didTapOnMainContent(event) {
  class TapHandler (line 26) | class TapHandler {
    method constructor (line 30) | constructor(gestures) {
    method click (line 38) | click(point, originalEvent) {
    method tap (line 55) | tap(point, originalEvent) {
    method doubleTap (line 65) | doubleTap(point, originalEvent) {
    method _doClickOrTapAction (line 77) | _doClickOrTapAction(actionName, point, originalEvent) {

FILE: src/js/gestures/zoom-handler.js
  constant UPPER_ZOOM_FRICTION (line 8) | const UPPER_ZOOM_FRICTION = 0.05;
  constant LOWER_ZOOM_FRICTION (line 9) | const LOWER_ZOOM_FRICTION = 0.15;
  function getZoomPointsCenter (line 20) | function getZoomPointsCenter(p, p1, p2) {
  class ZoomHandler (line 26) | class ZoomHandler {
    method constructor (line 30) | constructor(gestures) {
    method start (line 53) | start() {
    method change (line 64) | change() {
    method end (line 116) | end() {
    method _calculatePanForZoomLevel (line 134) | _calculatePanForZoomLevel(axis, currZoomLevel) {
    method correctZoomPan (line 148) | correctZoomPan(ignoreGesture) {

FILE: src/js/keyboard.js
  class Keyboard (line 34) | class Keyboard {
    method constructor (line 38) | constructor(pswp) {
    method _focusRoot (line 74) | _focusRoot() {
    method _onKeyDown (line 85) | _onKeyDown(e) {
    method _onFocusIn (line 169) | _onFocusIn(e) {

FILE: src/js/lightbox/lightbox.js
  class PhotoSwipeLightbox (line 43) | class PhotoSwipeLightbox extends PhotoSwipeBase {
    method constructor (line 47) | constructor(options) {
    method init (line 66) | init() {
    method onThumbnailsClick (line 77) | onThumbnailsClick(e) {
    method getClickedIndex (line 117) | getClickedIndex(e) {
    method loadAndOpen (line 152) | loadAndOpen(index, dataSource, initialPoint) {
    method preload (line 185) | preload(index, dataSource) {
    method _openPhotoswipe (line 232) | _openPhotoswipe(module, uid) {
    method destroy (line 294) | destroy() {

FILE: src/js/main-scroll.js
  constant MAIN_SCROLL_END_FRICTION (line 11) | const MAIN_SCROLL_END_FRICTION = 0.35;
  class MainScroll (line 24) | class MainScroll {
    method constructor (line 28) | constructor(pswp) {
    method resize (line 49) | resize(resizeSlides) {
    method resetPosition (line 79) | resetPosition() {
    method appendHolders (line 96) | appendHolders() {
    method canBeSwiped (line 121) | canBeSwiped() {
    method moveIndexBy (line 140) | moveIndexBy(diff, animate, velocityX) {
    method getCurrSlideX (line 217) | getCurrSlideX() {
    method isShifted (line 226) | isShifted() {
    method updateCurrItem (line 233) | updateCurrItem() {
    method moveTo (line 323) | moveTo(x, dragging) {

FILE: src/js/opener.js
  constant MIN_OPACITY (line 16) | const MIN_OPACITY = 0.003;
  class Opener (line 23) | class Opener {
    method constructor (line 27) | constructor(pswp) {
    method open (line 80) | open() {
    method close (line 85) | close() {
    method _prepareOpen (line 111) | _prepareOpen() {
    method _applyStartProps (line 126) | _applyStartProps() {
    method _start (line 243) | _start() {
    method _initiate (line 277) | _initiate() {
    method _onAnimationComplete (line 308) | _onAnimationComplete() {
    method _animateToOpenState (line 337) | _animateToOpenState() {
    method _animateToClosedState (line 365) | _animateToClosedState() {
    method _setClosedStateZoomPan (line 386) | _setClosedStateZoomPan(animate) {
    method _animateTo (line 435) | _animateTo(target, prop, propValue) {

FILE: src/js/photoswipe.js
  class PhotoSwipe (line 259) | class PhotoSwipe extends PhotoSwipeBase {
    method constructor (line 263) | constructor(options) {
    method init (line 329) | init() {
    method getLoopedIndex (line 429) | getLoopedIndex(index) {
    method appendHeavy (line 445) | appendHeavy() {
    method goTo (line 455) | goTo(index) {
    method next (line 464) | next() {
    method prev (line 471) | prev() {
    method zoomTo (line 480) | zoomTo(...args) {
    method toggleZoom (line 487) | toggleZoom() {
    method close (line 495) | close() {
    method destroy (line 515) | destroy() {
    method refreshSlideContent (line 546) | refreshSlideContent(slideIndex) {
    method setContent (line 576) | setContent(holder, index, force) {
    method getViewportCenterPoint (line 610) | getViewportCenterPoint() {
    method updateSize (line 623) | updateSize(force) {
    method applyBgOpacity (line 669) | applyBgOpacity(opacity) {
    method mouseDetected (line 679) | mouseDetected() {
    method _handlePageResize (line 691) | _handlePageResize() {
    method _updatePageScrollOffset (line 713) | _updatePageScrollOffset() {
    method setScrollOffset (line 721) | setScrollOffset(x, y) {
    method _createMainStructure (line 733) | _createMainStructure() {
    method getThumbBounds (line 771) | getThumbBounds() {
    method canLoop (line 783) | canLoop() {
    method _prepareOptions (line 792) | _prepareOptions(options) {

FILE: src/js/scroll-wheel.js
  class ScrollWheel (line 7) | class ScrollWheel {
    method constructor (line 11) | constructor(pswp) {
    method _onWheel (line 20) | _onWheel(e) {

FILE: src/js/slide/content.js
  class Content (line 9) | class Content {
    method constructor (line 15) | constructor(itemData, instance, index) {
    method removePlaceholder (line 50) | removePlaceholder() {
    method load (line 72) | load(isLazy, reload) {
    method loadImage (line 125) | loadImage(isLazy) {
    method setSlide (line 163) | setSlide(slide) {
    method onLoaded (line 174) | onLoaded() {
    method onError (line 197) | onError() {
    method isLoading (line 210) | isLoading() {
    method isError (line 221) | isError() {
    method isImageContent (line 228) | isImageContent() {
    method setDisplayedSize (line 238) | setDisplayedSize(width, height) {
    method isZoomable (line 280) | isZoomable() {
    method updateSrcsetSizes (line 291) | updateSrcsetSizes() {
    method usePlaceholder (line 320) | usePlaceholder() {
    method lazyLoad (line 331) | lazyLoad() {
    method keepPlaceholder (line 342) | keepPlaceholder() {
    method destroy (line 353) | destroy() {
    method displayError (line 378) | displayError() {
    method append (line 399) | append() {
    method activate (line 452) | activate() {
    method deactivate (line 474) | deactivate() {
    method remove (line 485) | remove() {
    method appendImage (line 504) | appendImage() {

FILE: src/js/slide/get-thumb-bounds.js
  function getBoundsByElement (line 10) | function getBoundsByElement(el) {
  function getCroppedBoundsByElement (line 25) | function getCroppedBoundsByElement(el, imageWidth, imageHeight) {
  function getThumbBounds (line 71) | function getThumbBounds(index, itemData, instance) {

FILE: src/js/slide/loader.js
  constant MIN_SLIDES_TO_CACHE (line 10) | const MIN_SLIDES_TO_CACHE = 5;
  function lazyLoadData (line 22) | function lazyLoadData(itemData, instance, index) {
  function lazyLoadSlide (line 69) | function lazyLoadSlide(index, instance) {
  class ContentLoader (line 79) | class ContentLoader {
    method constructor (line 83) | constructor(pswp) {
    method updateLazy (line 99) | updateLazy(diff) {
    method loadSlideByIndex (line 124) | loadSlideByIndex(initialIndex) {
    method getContentBySlide (line 142) | getContentBySlide(slide) {
    method addToCache (line 159) | addToCache(content) {
    method removeByIndex (line 181) | removeByIndex(index) {
    method getContentByIndex (line 192) | getContentByIndex(index) {
    method destroy (line 196) | destroy() {

FILE: src/js/slide/pan-bounds.js
  class PanBounds (line 11) | class PanBounds {
    method constructor (line 15) | constructor(slide) {
    method update (line 28) | update(currZoomLevel) {
    method _updateAxis (line 45) | _updateAxis(axis) {
    method reset (line 75) | reset() {
    method correctPan (line 91) | correctPan(axis, panOffset) { // checkPanBounds

FILE: src/js/slide/placeholder.js
  class Placeholder (line 3) | class Placeholder {
    method constructor (line 8) | constructor(imageSrc, container) {
    method setDisplayedSize (line 33) | setDisplayedSize(width, height) {
    method destroy (line 50) | destroy() {

FILE: src/js/slide/slide.js
  class Slide (line 37) | class Slide {
    method constructor (line 43) | constructor(data, index, pswp) {
    method setIsActive (line 88) | setIsActive(isActive) {
    method append (line 103) | append(holderElement) {
    method load (line 134) | load() {
    method appendHeavy (line 145) | appendHeavy() {
    method activate (line 174) | activate() {
    method deactivate (line 186) | deactivate() {
    method destroy (line 208) | destroy() {
    method resize (line 215) | resize() {
    method updateContentSize (line 241) | updateContentSize(force) {
    method sizeChanged (line 263) | sizeChanged(width, height) {
    method getPlaceholderElement (line 275) | getPlaceholderElement() {
    method zoomTo (line 288) | zoomTo(destZoomLevel, centerPoint, transitionDuration, ignoreBounds) {
    method toggleZoom (line 344) | toggleZoom(centerPoint) {
    method setZoomLevel (line 359) | setZoomLevel(currZoomLevel) {
    method calculateZoomToPanOffset (line 377) | calculateZoomToPanOffset(axis, point, prevZoomLevel) {
    method panTo (line 404) | panTo(panX, panY) {
    method isPannable (line 414) | isPannable() {
    method isZoomable (line 422) | isZoomable() {
    method applyCurrentZoomPan (line 430) | applyCurrentZoomPan() {
    method zoomAndPanToInitial (line 437) | zoomAndPanToInitial() {
    method _applyZoomTransform (line 454) | _applyZoomTransform(x, y, zoom) {
    method calculateSize (line 459) | calculateSize() {
    method getCurrentTransform (line 475) | getCurrentTransform() {
    method _setResolution (line 495) | _setResolution(newResolution) {

FILE: src/js/slide/zoom-level.js
  constant MAX_IMAGE_WIDTH (line 1) | const MAX_IMAGE_WIDTH = 4000;
  class ZoomLevel (line 14) | class ZoomLevel {
    method constructor (line 21) | constructor(options, itemData, index, pswp) {
    method update (line 48) | update(maxWidth, maxHeight, panAreaSize) {
    method _parseZoomLevelOption (line 90) | _parseZoomLevelOption(optionPrefix) {
    method _getSecondary (line 124) | _getSecondary() {
    method _getInitial (line 147) | _getInitial() {
    method _getMax (line 159) | _getMax() {

FILE: src/js/types.ts
  type Methods (line 1) | type Methods<T> = {[M in keyof T]: T[M] extends (...a: any) => any ? M :...
  type AddPostfix (line 3) | type AddPostfix<T extends string, P extends string> = `${T}${P}`
  type Type (line 5) | interface Type<T> extends Function {

FILE: src/js/ui/button-arrow.js
  function initArrowButton (line 14) | function initArrowButton(element, pswp, isNextButton) {

FILE: src/js/ui/ui-element.js
  function addElementHTML (line 41) | function addElementHTML(htmlData) {
  class UIElement (line 78) | class UIElement {
    method constructor (line 83) | constructor(pswp, data) {

FILE: src/js/ui/ui.js
  function setZoomedIn (line 20) | function setZoomedIn(el, isZoomedIn) {
  class UI (line 24) | class UI {
    method constructor (line 28) | constructor(pswp) {
    method init (line 45) | init() {
    method registerElement (line 82) | registerElement(elementData) {
    method _onZoomPanUpdate (line 98) | _onZoomPanUpdate() {

FILE: src/js/util/animations.js
  class Animations (line 21) | class Animations {
    method constructor (line 22) | constructor() {
    method startSpring (line 30) | startSpring(props) {
    method startTransition (line 37) | startTransition(props) {
    method _start (line 47) | _start(props, isSpring) {
    method stop (line 61) | stop(animation) {
    method stopAll (line 69) | stopAll() { // _stopAllAnimations
    method stopAllPan (line 79) | stopAllPan() {
    method stopMainScroll (line 90) | stopMainScroll() {
    method isPanRunning (line 113) | isPanRunning() {

FILE: src/js/util/css-animation.js
  constant DEFAULT_EASING (line 3) | const DEFAULT_EASING = 'cubic-bezier(.4,0,.22,1)';
  class CSSAnimation (line 21) | class CSSAnimation {
    method constructor (line 27) | constructor(props) {
    method _onTransitionEnd (line 83) | _onTransitionEnd(e) {
    method _finalizeAnimation (line 92) | _finalizeAnimation() {
    method destroy (line 103) | destroy() {

FILE: src/js/util/dom-events.js
  class DOMEvents (line 22) | class DOMEvents {
    method constructor (line 23) | constructor() {
    method add (line 39) | add(target, type, listener, passive) {
    method remove (line 51) | remove(target, type, listener, passive) {
    method removeAll (line 58) | removeAll() {
    method _toggleListener (line 83) | _toggleListener(target, type, listener, passive, unbind, skipPool) {

FILE: src/js/util/spring-animation.js
  class SpringAnimation (line 18) | class SpringAnimation {
    method constructor (line 22) | constructor(props) {
    method destroy (line 67) | destroy() {

FILE: src/js/util/spring-easer.js
  constant DEFAULT_NATURAL_FREQUENCY (line 1) | const DEFAULT_NATURAL_FREQUENCY = 12;
  constant DEFAULT_DAMPING_RATIO (line 2) | const DEFAULT_DAMPING_RATIO = 0.75;
  class SpringEaser (line 7) | class SpringEaser {
    method constructor (line 23) | constructor(initialVelocity, dampingRatio, naturalFrequency) {
    method easeFrame (line 45) | easeFrame(deltaPosition, deltaTime) {

FILE: src/js/util/util.js
  function createElement (line 10) | function createElement(className, tagName, appendToEl) {
  function equalizePoints (line 26) | function equalizePoints(p1, p2) {
  function roundPoint (line 38) | function roundPoint(p) {
  function getDistanceBetween (line 50) | function getDistanceBetween(p1, p2) {
  function pointsEqual (line 63) | function pointsEqual(p1, p2) {
  function clamp (line 75) | function clamp(val, min, max) {
  function toTransformString (line 87) | function toTransformString(x, y, scale) {
  function setTransform (line 105) | function setTransform(el, x, y, scale) {
  function setTransitionStyle (line 119) | function setTransitionStyle(el, prop, duration, ease) {
  function setWidthHeight (line 135) | function setWidthHeight(el, w, h) {
  function removeTransitionStyle (line 143) | function removeTransitionStyle(el) {
  function decodeImage (line 151) | function decodeImage(img) {
  constant LOAD_STATE (line 168) | const LOAD_STATE = {
  function specialKeyUsed (line 183) | function specialKeyUsed(e) {
  function getElementsFromOption (line 195) | function getElementsFromOption(option, legacySelector, parent = document) {
  function isPswpClass (line 219) | function isPswpClass(fn) {
  function isSafari (line 230) | function isSafari() {

FILE: src/js/util/viewport-size.js
  function getViewportSize (line 11) | function getViewportSize(options, pswp) {
  function parsePaddingOption (line 65) | function parsePaddingOption(prop, options, viewportSize, itemData, index) {
  function getPanAreaSize (line 91) | function getPanAreaSize(options, viewportSize, itemData, index) {
Condensed preview — 159 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,076K chars).
[
  {
    "path": ".babelrc",
    "chars": 130,
    "preview": "{\n  \"plugins\": [\n    \"@babel/plugin-transform-optional-chaining\",\n    \"@babel/plugin-transform-nullish-coalescing-operat"
  },
  {
    "path": ".editorconfig",
    "chars": 129,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newli"
  },
  {
    "path": ".eslintignore",
    "chars": 45,
    "preview": "node_modules\n!.*.js\n.eslintrc.js\n*.d.ts\n*.ts\n"
  },
  {
    "path": ".eslintrc.json",
    "chars": 1260,
    "preview": "{\n    \"env\": {\n        \"browser\": true,\n        \"es6\": true\n    },\n    \"extends\": \"airbnb-base\",\n    \"parser\": \"@babel/e"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 27,
    "preview": "open_collective: photoswipe"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 981,
    "preview": "name: PhotoSwipe Jobs\n\non: [workflow_dispatch]\n\njobs:\n  build:\n    name: Publish docs\n    runs-on: ubuntu-latest\n    ste"
  },
  {
    "path": ".gitignore",
    "chars": 382,
    "preview": "node_modules/\r\nrelease/\r\nGemfile.lock\r\ntest/dest\r\n*.gem\r\npkg/\r\n*.swp\r\n*~\r\n_site/\r\n.bundle/\r\nwebsite/static/photoswipe/\r\n"
  },
  {
    "path": "LICENSE",
    "chars": 1109,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014-2022 Dmitry Semenov, https://dimsemenov.com\n\nPermission is hereby granted, fre"
  },
  {
    "path": "README.md",
    "chars": 1670,
    "preview": "**FEEDBACK NEEDED** I am developing the new version - PhotoSwipe v6, please [read about upcoming changes and leave feedb"
  },
  {
    "path": "build/config-builder.js",
    "chars": 2400,
    "preview": "// eslint-disable-next-line import/no-extraneous-dependencies\nimport { terser } from 'rollup-plugin-terser';\nimport { ba"
  },
  {
    "path": "build/rollup.config.js",
    "chars": 222,
    "preview": "import { \n  lightboxJS,\n  coreJS,\n  minLightboxJS,\n  minCoreJS,\n  umdMinLightboxJS,\n  umdMinCoreJS\n} from './config-buil"
  },
  {
    "path": "build/rollup.config.watch.js",
    "chars": 93,
    "preview": "import { lightboxJS, coreJS } from './config-builder';\n\nexport default [lightboxJS, coreJS];\n"
  },
  {
    "path": "demo-docs-website/.gitignore",
    "chars": 233,
    "preview": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.lo"
  },
  {
    "path": "demo-docs-website/babel.config.js",
    "chars": 89,
    "preview": "module.exports = {\n  presets: [require.resolve('@docusaurus/core/lib/babel/preset')],\n};\n"
  },
  {
    "path": "demo-docs-website/docusaurus.config.js",
    "chars": 2933,
    "preview": "// @ts-check\n// Note: type annotations allow type checking and IDEs autocompletion\nconst path = require('path');\nconst l"
  },
  {
    "path": "demo-docs-website/package.json",
    "chars": 1242,
    "preview": "{\n  \"name\": \"demo-docs-website\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\","
  },
  {
    "path": "demo-docs-website/repo-data.json",
    "chars": 5727,
    "preview": "{\n  \"id\": 1580851,\n  \"name\": \"PhotoSwipe\",\n  \"full_name\": \"dimsemenov/PhotoSwipe\",\n  \"private\": false,\n  \"owner\": {\n    "
  },
  {
    "path": "demo-docs-website/sidebars.js",
    "chars": 2298,
    "preview": "/**\n * Creating a sidebar enables you to:\n - create an ordered group of docs\n - render a sidebar for each doc of that gr"
  },
  {
    "path": "demo-docs-website/src/components/HomepageFeatures/index.js",
    "chars": 1692,
    "preview": "import React from 'react';\nimport clsx from 'clsx';\nimport styles from './styles.module.css';\n\nconst FeatureList = [\n  {"
  },
  {
    "path": "demo-docs-website/src/components/HomepageFeatures/styles.module.css",
    "chars": 138,
    "preview": ".features {\n  display: flex;\n  align-items: center;\n  padding: 2rem 0;\n  width: 100%;\n}\n\n.featureSvg {\n  height: 200px;\n"
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/demo-images.js",
    "chars": 5073,
    "preview": "export const pswpDemoImages = [{\"sizes\":[{\"height\":2500,\"width\":1875,\"type\":\"jpg\",\"src\":\"1/img-2500.jpg\"},{\"height\":2000"
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic--badges.js",
    "chars": 491,
    "preview": "export function basicBadgesTemplate(props) {\n  let out = `<div class=\"pswp-gallery pswp-gallery--single-column\" id=\"gall"
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic--cropped.js",
    "chars": 444,
    "preview": "export function basicCroppedTemplate(props) {\n  let out = `<div class=\"pswp-gallery\" id=\"gallery--${props.id}\">`;\n  for "
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/basic.js",
    "chars": 419,
    "preview": "export function basicTemplate(props) {\n  let out = `<div class=\"pswp-gallery\" id=\"gallery--${props.id}\">\\n`;\n  for (let "
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/caption.js",
    "chars": 1440,
    "preview": "export function captionTemplate(props) {\n  return `<div class=\"pswp-gallery pswp-gallery--with-caption\" id=\"gallery--${p"
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/content-types.js",
    "chars": 894,
    "preview": "export function contentTypesTemplate(props) {\n  return `<div class=\"pswp-gallery\" id=\"gallery--${props.id}\">\n    <a  \n  "
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/custom-html-markup-data-source.js",
    "chars": 500,
    "preview": "export function customHTMLDataSourceTemplate(props) {\n  let out = `<div class=\"pswp-gallery pswp-gallery--single-column\""
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/getting-started.js",
    "chars": 1423,
    "preview": "export function gettingStartedTemplate(props) {\n  return `<div class=\"pswp-gallery pswp-gallery--single-column\" id=\"gall"
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/gallery-templates/srcset-test.js",
    "chars": 1207,
    "preview": "export function srcsetTemplate(props) {\n  const items = [{ thumbSrc: '1-300x200.png', largeSrc: '1-1500x1000.png', width"
  },
  {
    "path": "demo-docs-website/src/components/PswpCodePreview/index.js",
    "chars": 2220,
    "preview": "import React from 'react';\nimport CodeBlock from '../../theme/CodeBlock';\nimport { pswpDemoImages } from './demo-images'"
  },
  {
    "path": "demo-docs-website/src/css/custom.css",
    "chars": 2852,
    "preview": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framewor"
  },
  {
    "path": "demo-docs-website/src/css/docs-page.css",
    "chars": 709,
    "preview": "/* .theme-doc-footer,\n.pagination-nav,\n.theme-doc-markdown > * {\n  max-width: 650px;\n} */\n\n.theme-doc-markdown iframe {\n"
  },
  {
    "path": "demo-docs-website/src/css/example-code-block.css",
    "chars": 2474,
    "preview": ".pswp-example {\n  width: 100%;\n  position: relative;\n  margin-bottom: 1rem;\n  \n}\n\nspan.docusaurus-highlight-code-line {\n"
  },
  {
    "path": "demo-docs-website/src/css/header.css",
    "chars": 1559,
    "preview": "a.navbar__brand {\n  text-decoration: none;\n  font-size: 20px;\n  line-height: 1;\n  white-space: nowrap;\n  transform: tran"
  },
  {
    "path": "demo-docs-website/src/css/home.css",
    "chars": 3770,
    "preview": ".pswp-docs__home .navbar__brand {\n  display: none;\n}\n.pswp-docs__header-title-text {\n  margin: 60px 0px 50px;\n  font-siz"
  },
  {
    "path": "demo-docs-website/src/css/scrollbar.css",
    "chars": 710,
    "preview": "/* style scrollbar */\n.docs-styled-scrollbar::-webkit-scrollbar {\n  width: 6px;\n  height: 6px;\n}\n.docs-styled-scrollbar:"
  },
  {
    "path": "demo-docs-website/src/css/sidebar-menu.css",
    "chars": 1092,
    "preview": "aside.theme-doc-sidebar-container {\n  border: 0;\n  margin-top: 0;\n}\n\naside.theme-doc-sidebar-container {\n  position: sti"
  },
  {
    "path": "demo-docs-website/src/pages/_index-deep-zoom-demo.js",
    "chars": 4615,
    "preview": "import React, { useEffect } from 'react';\nimport Lightbox from '../../static/photoswipe/photoswipe-lightbox.esm.js';\n\n//"
  },
  {
    "path": "demo-docs-website/src/pages/_index-gallery-header.js",
    "chars": 13641,
    "preview": "import React, { useEffect } from 'react';\nimport Lightbox from '../../static/photoswipe/photoswipe-lightbox.esm.js';\nimp"
  },
  {
    "path": "demo-docs-website/src/pages/index.js",
    "chars": 5715,
    "preview": "import React, { useEffect } from 'react';\nimport Layout from '@theme/Layout';\nimport useDocusaurusContext from '@docusau"
  },
  {
    "path": "demo-docs-website/src/pages/index.module.css",
    "chars": 102,
    "preview": "/**\n * CSS files with the .module.css suffix will be treated as CSS modules\n * and scoped locally.\n */"
  },
  {
    "path": "demo-docs-website/src/theme/CodeBlock/index.js",
    "chars": 6152,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/CodeBlock/styles.module.css",
    "chars": 1099,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocItem/index.js",
    "chars": 2624,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocItem/styles.module.css",
    "chars": 430,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocItemFooter/index.js",
    "chars": 2509,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocItemFooter/styles.module.css",
    "chars": 348,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocPage/index.js",
    "chars": 5077,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocPage/styles.module.css",
    "chars": 188,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocSidebar/index.js",
    "chars": 3409,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocSidebar/is-same-path.ts",
    "chars": 569,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/DocSidebar/styles.module.css",
    "chars": 2161,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/EditThisPage/index.js",
    "chars": 516,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/Footer/index.js",
    "chars": 1576,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/Footer/styles.module.css",
    "chars": 358,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/Logo/index.js",
    "chars": 1571,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/MDXComponents/index.js",
    "chars": 2774,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/MDXComponents/styles.css",
    "chars": 280,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/Navbar/github-stars.js",
    "chars": 1247,
    "preview": "import React from 'react'\n\nimport repoData from '../../../repo-data.json';\n\nexport default function ReactGithubStars() {"
  },
  {
    "path": "demo-docs-website/src/theme/Navbar/index.js",
    "chars": 9080,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/src/theme/Navbar/styles.module.css",
    "chars": 489,
    "preview": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found i"
  },
  {
    "path": "demo-docs-website/static/.nojekyll",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "demo-docs-website/static/photoswipe/photoswipe-lightbox.esm.js",
    "chars": 54556,
    "preview": "/*!\n  * PhotoSwipe Lightbox 5.4.4 - https://photoswipe.com\n  * (c) 2024 Dmytro Semenov\n  */\n/** @typedef {import('../pho"
  },
  {
    "path": "demo-docs-website/static/photoswipe/photoswipe.css",
    "chars": 7003,
    "preview": "/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */\n\n.pswp {\n  --pswp-bg: #000;\n  --pswp-placeholder-bg: #222;"
  },
  {
    "path": "demo-docs-website/static/photoswipe/photoswipe.esm.js",
    "chars": 187712,
    "preview": "/*!\n  * PhotoSwipe 5.4.4 - https://photoswipe.com\n  * (c) 2024 Dmytro Semenov\n  */\n/** @typedef {import('../photoswipe.j"
  },
  {
    "path": "dist/photoswipe-lightbox.esm.js",
    "chars": 54556,
    "preview": "/*!\n  * PhotoSwipe Lightbox 5.4.4 - https://photoswipe.com\n  * (c) 2024 Dmytro Semenov\n  */\n/** @typedef {import('../pho"
  },
  {
    "path": "dist/photoswipe.css",
    "chars": 7003,
    "preview": "/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */\n\n.pswp {\n  --pswp-bg: #000;\n  --pswp-placeholder-bg: #222;"
  },
  {
    "path": "dist/photoswipe.esm.js",
    "chars": 187712,
    "preview": "/*!\n  * PhotoSwipe 5.4.4 - https://photoswipe.com\n  * (c) 2024 Dmytro Semenov\n  */\n/** @typedef {import('../photoswipe.j"
  },
  {
    "path": "dist/types/core/base.d.ts",
    "chars": 1970,
    "preview": "export default PhotoSwipeBase;\nexport type PhotoSwipe = import(\"../photoswipe.js\").default;\nexport type SlideData = impo"
  },
  {
    "path": "dist/types/core/eventable.d.ts",
    "chars": 36236,
    "preview": "export default Eventable;\nexport type PhotoSwipeLightbox = import('../lightbox/lightbox.js').default;\nexport type PhotoS"
  },
  {
    "path": "dist/types/gestures/drag-handler.d.ts",
    "chars": 1671,
    "preview": "export default DragHandler;\nexport type Point = import('../photoswipe.js').Point;\nexport type Gestures = import('./gestu"
  },
  {
    "path": "dist/types/gestures/gestures.d.ts",
    "chars": 4036,
    "preview": "export default Gestures;\nexport type PhotoSwipe = import('../photoswipe.js').default;\nexport type Point = import('../pho"
  },
  {
    "path": "dist/types/gestures/tap-handler.d.ts",
    "chars": 1139,
    "preview": "export default TapHandler;\n/**\n * <T, P>\n */\nexport type AddPostfix<T extends string, P extends string> = import('../typ"
  },
  {
    "path": "dist/types/gestures/zoom-handler.d.ts",
    "chars": 1194,
    "preview": "export default ZoomHandler;\nexport type Point = import('../photoswipe.js').Point;\nexport type Gestures = import('./gestu"
  },
  {
    "path": "dist/types/keyboard.d.ts",
    "chars": 700,
    "preview": "export default Keyboard;\nexport type PhotoSwipe = import('./photoswipe.js').default;\n/**\n * <T>\n */\nexport type Methods<"
  },
  {
    "path": "dist/types/lightbox/lightbox.d.ts",
    "chars": 3875,
    "preview": "export default PhotoSwipeLightbox;\n/**\n * <T>\n */\nexport type Type<T> = import('../types.js').Type<T>;\nexport type Photo"
  },
  {
    "path": "dist/types/main-scroll.d.ts",
    "chars": 2737,
    "preview": "export default MainScroll;\nexport type PhotoSwipe = import('./photoswipe.js').default;\nexport type Slide = import('./sli"
  },
  {
    "path": "dist/types/opener.d.ts",
    "chars": 2112,
    "preview": "export default Opener;\nexport type PhotoSwipe = import('./photoswipe.js').default;\nexport type Bounds = import('./slide/"
  },
  {
    "path": "dist/types/photoswipe.d.ts",
    "chars": 14069,
    "preview": "export default PhotoSwipe;\n/**\n * <T>\n */\nexport type Type<T> = import('./types.js').Type<T>;\nexport type SlideData = im"
  },
  {
    "path": "dist/types/scroll-wheel.d.ts",
    "chars": 466,
    "preview": "export default ScrollWheel;\nexport type PhotoSwipe = import('./photoswipe.js').default;\n/** @typedef {import('./photoswi"
  },
  {
    "path": "dist/types/slide/content.d.ts",
    "chars": 3641,
    "preview": "export default Content;\nexport type Slide = import('./slide.js').default;\nexport type SlideData = import('./slide.js').S"
  },
  {
    "path": "dist/types/slide/get-thumb-bounds.d.ts",
    "chars": 649,
    "preview": "/**\n * Get dimensions of thumbnail image\n * (click on which opens photoswipe or closes photoswipe to)\n *\n * @param {numb"
  },
  {
    "path": "dist/types/slide/loader.d.ts",
    "chars": 2361,
    "preview": "/**\n * Lazy-load an image\n * This function is used both by Lightbox and PhotoSwipe core,\n * thus it can be called before"
  },
  {
    "path": "dist/types/slide/pan-bounds.d.ts",
    "chars": 1183,
    "preview": "export default PanBounds;\nexport type Slide = import('./slide.js').default;\nexport type Point = Record<Axis, number>;\nex"
  },
  {
    "path": "dist/types/slide/placeholder.d.ts",
    "chars": 489,
    "preview": "export default Placeholder;\ndeclare class Placeholder {\n    /**\n     * @param {string | false} imageSrc\n     * @param {H"
  },
  {
    "path": "dist/types/slide/slide.d.ts",
    "chars": 6912,
    "preview": "export default Slide;\nexport type PhotoSwipe = import('../photoswipe.js').default;\nexport type Point = import('../photos"
  },
  {
    "path": "dist/types/slide/zoom-level.d.ts",
    "chars": 3001,
    "preview": "export default ZoomLevel;\nexport type PhotoSwipe = import('../photoswipe.js').default;\nexport type PhotoSwipeOptions = i"
  },
  {
    "path": "dist/types/types.d.ts",
    "chars": 268,
    "preview": "export declare type Methods<T> = {\n    [M in keyof T]: T[M] extends (...a: any) => any ? M : never;\n}[keyof T];\nexport d"
  },
  {
    "path": "dist/types/ui/button-arrow.d.ts",
    "chars": 266,
    "preview": "/** @type {UIElementData} */\nexport const arrowPrev: UIElementData;\n/** @type {UIElementData} */\nexport const arrowNext:"
  },
  {
    "path": "dist/types/ui/button-close.d.ts",
    "chars": 165,
    "preview": "export default closeButton;\n/** @type {import('./ui-element.js').UIElementData} UIElementData */\ndeclare const closeButt"
  },
  {
    "path": "dist/types/ui/button-zoom.d.ts",
    "chars": 163,
    "preview": "export default zoomButton;\n/** @type {import('./ui-element.js').UIElementData} UIElementData */\ndeclare const zoomButton"
  },
  {
    "path": "dist/types/ui/counter-indicator.d.ts",
    "chars": 141,
    "preview": "/** @type {import('./ui-element.js').UIElementData} UIElementData */\nexport const counterIndicator: import('./ui-element"
  },
  {
    "path": "dist/types/ui/loading-indicator.d.ts",
    "chars": 141,
    "preview": "/** @type {import('./ui-element.js').UIElementData} UIElementData */\nexport const loadingIndicator: import('./ui-element"
  },
  {
    "path": "dist/types/ui/ui-element.d.ts",
    "chars": 1277,
    "preview": "export default UIElement;\nexport type PhotoSwipe = import('../photoswipe.js').default;\n/**\n * <T>\n */\nexport type Method"
  },
  {
    "path": "dist/types/ui/ui.d.ts",
    "chars": 1038,
    "preview": "export default UI;\nexport type PhotoSwipe = import('../photoswipe.js').default;\nexport type UIElementData = import('./ui"
  },
  {
    "path": "dist/types/util/animations.d.ts",
    "chars": 2059,
    "preview": "export default Animations;\nexport type CssAnimationProps = import('./css-animation.js').CssAnimationProps;\nexport type S"
  },
  {
    "path": "dist/types/util/css-animation.d.ts",
    "chars": 1426,
    "preview": "export default CSSAnimation;\nexport type SharedAnimationProps = import('./animations.js').SharedAnimationProps;\nexport t"
  },
  {
    "path": "dist/types/util/dom-events.d.ts",
    "chars": 1780,
    "preview": "export default DOMEvents;\nexport type PoolItem = {\n    target: HTMLElement | Window | Document | undefined | null;\n    t"
  },
  {
    "path": "dist/types/util/spring-animation.d.ts",
    "chars": 1086,
    "preview": "export default SpringAnimation;\nexport type SharedAnimationProps = import('./animations.js').SharedAnimationProps;\nexpor"
  },
  {
    "path": "dist/types/util/spring-easer.d.ts",
    "chars": 1208,
    "preview": "export default SpringEaser;\n/**\n * Spring easing helper\n */\ndeclare class SpringEaser {\n    /**\n     * @param {number} i"
  },
  {
    "path": "dist/types/util/util.d.ts",
    "chars": 3981,
    "preview": "/** @typedef {import('../photoswipe.js').Point} Point */\n/**\n * @template {keyof HTMLElementTagNameMap} T\n * @param {str"
  },
  {
    "path": "dist/types/util/viewport-size.d.ts",
    "chars": 1904,
    "preview": "/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */\n/** @typedef {import('../core/base.js')"
  },
  {
    "path": "dist/umd/README.md",
    "chars": 1316,
    "preview": "`umd/` folder contains transpiled version of PhotoSwipe in universal module definition format.\n\nUse it only if you are u"
  },
  {
    "path": "docs/adding-ui-elements.md",
    "chars": 7582,
    "preview": "---\nid: adding-ui-elements\ntitle: Adding UI elements\nsidebar_label: Adding UI elements\n---\n\nUse method `pswp.ui.register"
  },
  {
    "path": "docs/adjusting-zoom-level.md",
    "chars": 5801,
    "preview": "---\nid: adjusting-zoom-level\ntitle: Adjusting Zoom Level\nsidebar_label: Adjusting zoom level\n---\n\nPhotoswipe has three z"
  },
  {
    "path": "docs/caption.md",
    "chars": 2417,
    "preview": "---\nid: caption\ntitle: Caption\nsidebar_label: Caption\n---\n\nPhotoSwipe does not support caption out of box, but you may i"
  },
  {
    "path": "docs/click-and-tap-actions.md",
    "chars": 2040,
    "preview": "---\nid: click-and-tap-actions\ntitle: Click Actions\nsidebar_label: Click actions\n---\n\nList of options:\n\n- `imageClickActi"
  },
  {
    "path": "docs/custom-content.md",
    "chars": 6780,
    "preview": "---\nid: custom-content\ntitle: Custom Content in Slides\nsidebar_label: Custom content\n---\n\nBy default PhotoSwipe can only"
  },
  {
    "path": "docs/data-sources.md",
    "chars": 11007,
    "preview": "---\nid: data-sources\ntitle: Data Sources\nsidebar_label: Data sources\n---\n\n## From an Array (or NodeList)\n\nPass an array "
  },
  {
    "path": "docs/events.md",
    "chars": 6310,
    "preview": "---\nid: events\ntitle: Events\nsidebar_label: Events\n---\n\n```js\nconst lightbox = new PhotoSwipeLightbox({\n  // options...\n"
  },
  {
    "path": "docs/filters.md",
    "chars": 4850,
    "preview": "---\nid: filters\ntitle: Filters\nsidebar_label: Filters\n---\n\nFilters allow to modify data, they expect to have something r"
  },
  {
    "path": "docs/getting-started.md",
    "chars": 6715,
    "preview": "---\nid: getting-started\ntitle: Getting Started\nsidebar_label: Getting Started\n---\n\n**PhotoSwipe v6 is under development*"
  },
  {
    "path": "docs/methods.md",
    "chars": 7257,
    "preview": "---\nid: methods\ntitle: Methods\nsidebar_label: Methods\n---\n\n## PhotoSwipeLightbox methods\n\n### `init()`\n\nInitialize  the "
  },
  {
    "path": "docs/native-fullscreen-on-open.md",
    "chars": 5286,
    "preview": "---\nid: native-fullscreen-on-open\ntitle: Trigger native fullscreen when lightbox opens\nsidebar_label: Native fullscreen "
  },
  {
    "path": "docs/opening-or-closing-transition.md",
    "chars": 6329,
    "preview": "---\nid: opening-or-closing-transition\ntitle: Opening or closing transition\nsidebar_label: Opening or closing transition\n"
  },
  {
    "path": "docs/options.md",
    "chars": 15793,
    "preview": "---\nid: options\ntitle: Options\nsidebar_label: Options\n---\n\n### bgOpacity\n\nNumber, `0.8`. \n\nBackground backdrop opacity, "
  },
  {
    "path": "docs/properties.md",
    "chars": 1145,
    "preview": "---\nid: properties\ntitle: Properties\nsidebar_label: Properties\n---\n\n\n*page is under construction*\n\nWhen PhotoSwipe is op"
  },
  {
    "path": "docs/react-image-gallery.md",
    "chars": 823,
    "preview": "---\nid: react-image-gallery\ntitle: Image Gallery with Lightbox for React\nsidebar_label: for React\n---\n\nHere's a basic ex"
  },
  {
    "path": "docs/styling.md",
    "chars": 4272,
    "preview": "---\nid: styling\ntitle: Styling PhotoSwipe\nsidebar_label: Styling\n---\n\n\n## Modifying icons\n\nBy default PhotoSwipe include"
  },
  {
    "path": "docs/svelte-image-gallery.md",
    "chars": 648,
    "preview": "---\nid: svelte-image-gallery\ntitle: Image Gallery for Svelte\nsidebar_label: for Svelte\n---\n\nHere's a basic example on ho"
  },
  {
    "path": "docs/vue-image-gallery.md",
    "chars": 514,
    "preview": "---\nid: vue-image-gallery\ntitle: Image Gallery for Vue.js\nsidebar_label: for Vue\n---\n\nHere's an example on how to use Ph"
  },
  {
    "path": "global.d.ts",
    "chars": 107,
    "preview": "export {}\n\ndeclare global {\n  interface Window {\n      pswp?: import('./src/js/photoswipe').default;\n  }\n}\n"
  },
  {
    "path": "package.json",
    "chars": 2951,
    "preview": "{\n  \"name\": \"photoswipe\",\n  \"version\": \"5.4.4\",\n  \"main\": \"dist/photoswipe.esm.js\",\n  \"style\": \"dist/photoswipe.css\",\n  "
  },
  {
    "path": "src/js/core/base.js",
    "chars": 5294,
    "preview": "import Eventable from './eventable.js';\nimport { getElementsFromOption } from '../util/util.js';\nimport Content from '.."
  },
  {
    "path": "src/js/core/eventable.js",
    "chars": 12240,
    "preview": "/** @typedef {import('../lightbox/lightbox.js').default} PhotoSwipeLightbox */\n/** @typedef {import('../photoswipe.js')."
  },
  {
    "path": "src/js/gestures/drag-handler.js",
    "chars": 11581,
    "preview": "import {\n  equalizePoints, roundPoint, clamp\n} from '../util/util.js';\n\n/** @typedef {import('../photoswipe.js').Point} "
  },
  {
    "path": "src/js/gestures/gestures.js",
    "chars": 16825,
    "preview": "import {\n  equalizePoints, pointsEqual, getDistanceBetween\n} from '../util/util.js';\n\nimport DragHandler from './drag-ha"
  },
  {
    "path": "src/js/gestures/tap-handler.js",
    "chars": 3342,
    "preview": "/**\n * @template {string} T\n * @template {string} P\n * @typedef {import('../types.js').AddPostfix<T, P>} AddPostfix<T, P"
  },
  {
    "path": "src/js/gestures/zoom-handler.js",
    "chars": 7684,
    "preview": "import {\n  equalizePoints, getDistanceBetween, clamp, pointsEqual\n} from '../util/util.js';\n\n/** @typedef {import('../ph"
  },
  {
    "path": "src/js/keyboard.js",
    "chars": 4592,
    "preview": "import { specialKeyUsed } from './util/util.js';\n\n/** @typedef {import('./photoswipe.js').default} PhotoSwipe */\n\n/**\n *"
  },
  {
    "path": "src/js/lightbox/lightbox.js",
    "chars": 8924,
    "preview": "import {\n  specialKeyUsed,\n  getElementsFromOption,\n  isPswpClass\n} from '../util/util.js';\n\nimport PhotoSwipeBase from "
  },
  {
    "path": "src/js/main-scroll.js",
    "chars": 9616,
    "preview": "import {\n  setTransform,\n  createElement,\n} from './util/util.js';\n\n/** @typedef {import('./photoswipe.js').default} Pho"
  },
  {
    "path": "src/js/opener.js",
    "chars": 12974,
    "preview": "import {\n  setTransform,\n  equalizePoints,\n  decodeImage,\n  toTransformString\n} from './util/util.js';\n\n/** @typedef {im"
  },
  {
    "path": "src/js/photoswipe.js",
    "chars": 22447,
    "preview": "import {\n  createElement,\n  equalizePoints,\n  pointsEqual,\n  clamp,\n} from './util/util.js';\n\nimport DOMEvents from './u"
  },
  {
    "path": "src/js/scroll-wheel.js",
    "chars": 1535,
    "preview": "/** @typedef {import('./photoswipe.js').default} PhotoSwipe */\n\n/**\n * Handles scroll wheel.\n * Can pan and zoom current"
  },
  {
    "path": "src/js/slide/content.js",
    "chars": 13464,
    "preview": "import { createElement, isSafari, LOAD_STATE, setWidthHeight } from '../util/util.js';\nimport Placeholder from './placeh"
  },
  {
    "path": "src/js/slide/get-thumb-bounds.js",
    "chars": 3037,
    "preview": "/** @typedef {import('./slide.js').SlideData} SlideData */\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe "
  },
  {
    "path": "src/js/slide/loader.js",
    "chars": 5577,
    "preview": "import { getViewportSize, getPanAreaSize } from '../util/viewport-size.js';\nimport ZoomLevel from './zoom-level.js';\n\n/*"
  },
  {
    "path": "src/js/slide/pan-bounds.js",
    "chars": 2321,
    "preview": "import { clamp } from '../util/util.js';\nimport { parsePaddingOption } from '../util/viewport-size.js';\n\n/** @typedef {i"
  },
  {
    "path": "src/js/slide/placeholder.js",
    "chars": 1566,
    "preview": "import { createElement, setWidthHeight, toTransformString } from '../util/util.js';\n\nclass Placeholder {\n  /**\n   * @par"
  },
  {
    "path": "src/js/slide/slide.js",
    "chars": 13511,
    "preview": "/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\n/** @typedef {import('../photoswipe.js').Point} Point */"
  },
  {
    "path": "src/js/slide/zoom-level.js",
    "chars": 4419,
    "preview": "const MAX_IMAGE_WIDTH = 4000;\n\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\n/** @typedef {import('../"
  },
  {
    "path": "src/js/types.ts",
    "chars": 242,
    "preview": "export type Methods<T> = {[M in keyof T]: T[M] extends (...a: any) => any ? M : never}[keyof T]\n\nexport type AddPostfix<"
  },
  {
    "path": "src/js/ui/button-arrow.js",
    "chars": 1670,
    "preview": "/*\n  Backward and forward arrow buttons\n */\n\n/** @typedef {import('./ui-element.js').UIElementData} UIElementData */\n/**"
  },
  {
    "path": "src/js/ui/button-close.js",
    "chars": 379,
    "preview": "/** @type {import('./ui-element.js').UIElementData} UIElementData */\nconst closeButton = {\n  name: 'close',\n  title: 'Cl"
  },
  {
    "path": "src/js/ui/button-zoom.js",
    "chars": 608,
    "preview": "/** @type {import('./ui-element.js').UIElementData} UIElementData */\nconst zoomButton = {\n  name: 'zoom',\n  title: 'Zoom"
  },
  {
    "path": "src/js/ui/counter-indicator.js",
    "chars": 394,
    "preview": "/** @type {import('./ui-element.js').UIElementData} UIElementData */\nexport const counterIndicator = {\n  name: 'counter'"
  },
  {
    "path": "src/js/ui/loading-indicator.js",
    "chars": 1885,
    "preview": "/** @type {import('./ui-element.js').UIElementData} UIElementData */\nexport const loadingIndicator = {\n  name: 'preloade"
  },
  {
    "path": "src/js/ui/ui-element.js",
    "chars": 5243,
    "preview": "import { createElement } from '../util/util.js';\n\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\n\n/**\n "
  },
  {
    "path": "src/js/ui/ui.js",
    "chars": 3661,
    "preview": "import UIElement from './ui-element.js';\nimport { arrowPrev, arrowNext } from './button-arrow.js';\nimport closeButton fr"
  },
  {
    "path": "src/js/util/animations.js",
    "chars": 2738,
    "preview": "import CSSAnimation from './css-animation.js';\nimport SpringAnimation from './spring-animation.js';\n\n/** @typedef {impor"
  },
  {
    "path": "src/js/util/css-animation.js",
    "chars": 3172,
    "preview": "import { setTransitionStyle, removeTransitionStyle } from './util.js';\n\nconst DEFAULT_EASING = 'cubic-bezier(.4,0,.22,1)"
  },
  {
    "path": "src/js/util/dom-events.js",
    "chars": 3258,
    "preview": "// Detect passive event listener support\nlet supportsPassive = false;\n/* eslint-disable */\ntry {\n  /* @ts-ignore */\n  wi"
  },
  {
    "path": "src/js/util/spring-animation.js",
    "chars": 1833,
    "preview": "import SpringEaser from './spring-easer.js';\n\n/** @typedef {import('./animations.js').SharedAnimationProps} SharedAnimat"
  },
  {
    "path": "src/js/util/spring-easer.js",
    "chars": 3129,
    "preview": "const DEFAULT_NATURAL_FREQUENCY = 12;\nconst DEFAULT_DAMPING_RATIO = 0.75;\n\n/**\n * Spring easing helper\n */\nclass SpringE"
  },
  {
    "path": "src/js/util/util.js",
    "chars": 5191,
    "preview": "/** @typedef {import('../photoswipe.js').Point} Point */\n\n/**\n * @template {keyof HTMLElementTagNameMap} T\n * @param {st"
  },
  {
    "path": "src/js/util/viewport-size.js",
    "chars": 2744,
    "preview": "/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */\n/** @typedef {import('../core/base.js')"
  },
  {
    "path": "src/photoswipe.css",
    "chars": 7003,
    "preview": "/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */\n\n.pswp {\n  --pswp-bg: #000;\n  --pswp-placeholder-bg: #222;"
  },
  {
    "path": "tsconfig.json",
    "chars": 316,
    "preview": "{\n  \"compilerOptions\": {\n    \"outDir\": \"dist/types\",\n    \"declaration\": true,\n    \"emitDeclarationOnly\": true,\n    \"stri"
  }
]

About this extraction

This page contains the full source code of the dimsemenov/PhotoSwipe GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 159 files (1000.8 KB), approximately 272.9k tokens, and a symbol index with 1171 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!