├── .babelrc ├── .codesandbox └── ci.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── pull_request_template.md ├── .gitignore ├── .nvmrc ├── .prettierrc ├── .release-it.json ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bundlesize.config.json ├── cypress.json ├── cypress ├── .eslintrc.js ├── integration │ └── stories.spec.js ├── plugins │ └── index.js ├── snapshots │ └── stories.spec.js │ │ ├── attributes │ │ ├── data-zoom-src-1.snap.png │ │ ├── srcset-1.snap.png │ │ ├── srcset-and-data-zoom-src-1.snap.png │ │ └── svg-1.snap.png │ │ └── options │ │ ├── background-(dark)-1.snap.png │ │ ├── background-(transparent)-1.snap.png │ │ ├── container-(coordinates-object)-1.snap.png │ │ ├── container-(dom-element)-1.snap.png │ │ ├── default-1.snap.png │ │ ├── margin-1.snap.png │ │ ├── scrolloffset-1.snap.png │ │ ├── template-(dropbox-paper)-1.snap.png │ │ └── template-(facebook)-1.snap.png └── support │ ├── commands.js │ └── index.js ├── docs ├── container.md └── template.md ├── examples ├── dropbox-paper-template │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── src │ │ ├── images │ │ │ ├── image-1.jpg │ │ │ └── image-2.jpg │ │ ├── index.js │ │ ├── reset.css │ │ └── style.css │ └── yarn.lock ├── facebook-template │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── src │ │ ├── images │ │ │ ├── image-1.jpg │ │ │ └── image-2.jpg │ │ ├── index.js │ │ ├── reset.css │ │ └── style.css │ └── yarn.lock ├── react-markdown │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── image-1.jpg │ │ │ ├── image-2.jpg │ │ │ └── image-3.jpg │ ├── src │ │ ├── App.tsx │ │ ├── main.tsx │ │ ├── reset.css │ │ ├── style.css │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── vite.config.ts │ └── yarn.lock ├── react │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── image-1.jpg │ │ │ ├── image-2.jpg │ │ │ └── image-3.jpg │ ├── src │ │ ├── App.tsx │ │ ├── ImageZoom.tsx │ │ ├── main.tsx │ │ ├── reset.css │ │ ├── style.css │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── vite.config.ts │ └── yarn.lock ├── svelte │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── jsconfig.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── image-1.jpg │ │ │ ├── image-2.jpg │ │ │ └── image-3.jpg │ ├── src │ │ ├── App.svelte │ │ ├── app.css │ │ ├── lib │ │ │ └── ImageZoom.svelte │ │ ├── main.js │ │ ├── reset.css │ │ ├── style.css │ │ └── vite-env.d.ts │ ├── svelte.config.js │ ├── vite.config.js │ └── yarn.lock ├── vanilla │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── src │ │ ├── images │ │ │ ├── image-1.jpg │ │ │ └── image-2.jpg │ │ ├── index.js │ │ ├── reset.css │ │ └── style.css │ └── yarn.lock └── vue │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ ├── favicon.ico │ └── images │ │ ├── image-1.jpg │ │ ├── image-2.jpg │ │ └── image-3.jpg │ ├── src │ ├── App.vue │ ├── components │ │ └── ImageZoom.vue │ ├── main.ts │ ├── reset.css │ ├── style.css │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── vite.config.ts │ └── yarn.lock ├── husky.config.js ├── jest.config.js ├── logo.svg ├── netlify.toml ├── package.json ├── rollup.config.js ├── scripts ├── release-examples.sh └── update-examples.js ├── src ├── __mocks__ │ └── styleMock.js ├── __tests__ │ ├── __snapshots__ │ │ └── medium-zoom.test.js.snap │ ├── index.test.js │ └── medium-zoom.test.js ├── index.js ├── medium-zoom.css ├── medium-zoom.d.ts ├── medium-zoom.js └── utils.js ├── stories ├── attach.stories.js ├── attributes.stories.js ├── clone.stories.js ├── close.stories.js ├── config │ ├── addons.js │ ├── config.js │ ├── decorators.js │ ├── preview-head.html │ ├── style.css │ └── webpack.config.js ├── detach.stories.js ├── getImages.stories.js ├── getOptions.stories.js ├── getZoomedImage.stories.js ├── images │ ├── crab.svg │ ├── image-1.jpg │ ├── image-1.thumbnail.jpg │ ├── image-1x1000.jpg │ ├── image-1x1200.jpg │ ├── image-1x300.jpg │ ├── image-1x600.jpg │ ├── image-1x800.jpg │ ├── image-2.jpg │ ├── image-2.thumbnail.jpg │ ├── image-3.jpg │ ├── image-3.thumbnail.jpg │ ├── image-4.jpg │ ├── image-4.thumbnail.jpg │ ├── image-5.jpg │ ├── image-5.thumbnail.jpg │ ├── image-6.jpg │ ├── image-6.thumbnail.jpg │ ├── image-7.jpg │ └── image-7.thumbnail.jpg ├── off.stories.js ├── on.stories.js ├── open.stories.js ├── options.stories.js ├── toggle.stories.js └── update.stories.js ├── website ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── icons │ ├── favicon.ico │ └── favicon.png ├── index.html ├── manifest.webmanifest ├── package.json ├── src │ ├── images │ │ ├── image-1.jpg │ │ ├── image-2.jpg │ │ ├── image-3.jpg │ │ ├── image-4.jpg │ │ ├── image-5.jpg │ │ ├── image-6.jpg │ │ └── image-7.jpg │ ├── index.js │ ├── placeholders.js │ ├── reset.css │ └── style.css └── yarn.lock └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "loose": true, 6 | "targets": { 7 | "browsers": "ie >= 10" 8 | } 9 | }] 10 | ], 11 | "env": { 12 | "test": { 13 | "presets": [["env"]] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "sandboxes": ["/examples/vanilla"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules/** 2 | /coverage 3 | /dist 4 | /examples 5 | /stories 6 | /website 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint:recommended', 'airbnb-base', 'prettier'], 3 | parser: 'babel-eslint', 4 | env: { 5 | es6: true, 6 | browser: true, 7 | node: true, 8 | jest: true, 9 | }, 10 | globals: { 11 | __TEST__: false, 12 | }, 13 | rules: { 14 | 'no-underscore-dangle': 0, 15 | 'no-use-before-define': 0, 16 | 'no-shadow': 0, 17 | 'no-console': ['error', { allow: ['warn', 'error'] }], 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Did something not work? 4 | --- 5 | 6 | 10 | 11 | ## Bug description 12 | 13 | > A clear and concise description of what the bug is. 14 | 15 | ## How to reproduce 16 | 17 | > A list of the steps to reproduce the bug. 18 | 19 | 1. Run `mediumZoom(selector, options)` 20 | 1. Click on the image 21 | 1. See error 22 | 23 | ## Expected behavior 24 | 25 | > A clear and concise description of what you expected to happen. 26 | 27 | ## Reproducible example 28 | 29 | 35 | 36 | [Link to the bug reproduction](https://codesandbox.io/s/ADD_THE_SANDBOX_ID) 37 | 38 | ## Environment 39 | 40 | - Browser: name / version 41 | - `medium-zoom` version: 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Would you like to add something? 4 | --- 5 | 6 | 10 | 11 | ## The problem 12 | 13 | > A concise description of why you want a new feature. 14 | 15 | ## Solution 16 | 17 | > A clear description of what you want to happen. 18 | 19 | ## Implementation 20 | 21 | > Do you have an idea how it could be implemented? 22 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | ## Summary 7 | 8 | 9 | 10 | ## Result 11 | 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /coverage 3 | /cypress/screenshots 4 | /cypress/videos 5 | /dist 6 | /storybook 7 | 8 | .DS_Store 9 | package-lock.json 10 | *.log 11 | .vscode 12 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 10.16.0 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "increment": "conventional:angular", 3 | "scripts": { 4 | "beforeStart": "yarn run lint && yarn run test --colors && yarn run build && yarn run test:size && yarn run test:cypress" 5 | }, 6 | "git": { 7 | "requireUpstream": false, 8 | "requireCleanWorkingDir": false, 9 | "commitMessage": "chore(release): %s", 10 | "changelog": "yarn run changelog:update" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - ~/.cache 5 | before_install: 6 | - curl -o- -L yarnpkg.com/install.sh | bash -s -- --version 1.13.0 7 | - export PATH=$HOME/.yarn/bin:$PATH 8 | install: yarn install --frozen-lockfile 9 | before_script: yarn run build 10 | script: 11 | - '${SCRIPT}' 12 | env: 13 | matrix: 14 | - SCRIPT="yarn run lint" 15 | - SCRIPT="yarn run test --coverage --colors" 16 | # - SCRIPT="yarn run test:cypress:record $CYPRESS_RECORD_KEY" 17 | - SCRIPT="yarn run test:size" 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.1.0](https://github.com/francoischalifour/medium-zoom/compare/1.0.8...1.1.0) (2023-11-16) 2 | 3 | ### Features 4 | 5 | - introduce pure bundle (JS and CSS separated) ([#204](https://github.com/francoischalifour/medium-zoom/issues/204) and [#206](https://github.com/francoischalifour/medium-zoom/issues/206)) ([0a05b46](https://github.com/francoischalifour/medium-zoom/commit/0a05b4626b0f2820ae5bc3e2b0ef081244679750)) 6 | 7 | ## [1.0.8](https://github.com/francoischalifour/medium-zoom/compare/1.0.7...1.0.8) (2022-11-15) 8 | 9 | ### Bug Fixes 10 | 11 | - support images in `` elements with `currentSrc` ([#194](https://github.com/francoischalifour/medium-zoom/issues/194)) ([32ee39f](https://github.com/francoischalifour/medium-zoom/commit/32ee39f424f91e2f34e5e06e7ddc6bf8e4be9d23)) 12 | 13 | ## [1.0.7](https://github.com/francoischalifour/medium-zoom/compare/1.0.6...1.0.7) (2022-11-14) 14 | 15 | ### Bug Fixes 16 | 17 | - ensure zooming out doesn't happen ([#176](https://github.com/francoischalifour/medium-zoom/issues/176)) ([b920940](https://github.com/francoischalifour/medium-zoom/commit/b920940c061d2dcb280e873ac4ca577130d4efc1)) 18 | - remove `loading` attribute on HD target ([#186](https://github.com/francoischalifour/medium-zoom/issues/186)) ([dd01423](https://github.com/francoischalifour/medium-zoom/commit/dd01423b983a228be348c81ef9347d688a166cb6)) 19 | 20 | ## [1.0.6](https://github.com/francoischalifour/medium-zoom/compare/1.0.5...1.0.6) (2020-07-08) 21 | 22 | ### Bug Fixes 23 | 24 | - support lazy loading images on Firefox ([#158](https://github.com/francoischalifour/medium-zoom/issues/158)) ([aebb316](https://github.com/francoischalifour/medium-zoom/commit/aebb31636cb9e87f3a9b25f8bd0007f0269c1ae7)) 25 | 26 | ## [1.0.5](https://github.com/francoischalifour/medium-zoom/compare/1.0.4...1.0.5) (2019-12-07) 27 | 28 | ### Fixed 29 | 30 | - Give zoom transition higher priority ([#148](https://github.com/francoischalifour/medium-zoom/issues/148)) ([25b3524](https://github.com/francoischalifour/medium-zoom/commit/25b3524bb76e19a5e8dc46e32cadca3db7fedbef)), closes [#110](https://github.com/francoischalifour/medium-zoom/issues/110) 31 | 32 | ## [1.0.4](https://github.com/francoischalifour/medium-zoom/compare/1.0.3...1.0.4) (2019-04-06) 33 | 34 | ### Fixed 35 | 36 | - Bring SSR compatibility by not using window outside of main function ([#95](https://github.com/francoischalifour/medium-zoom/issues/95)) ([541e8f0](https://github.com/francoischalifour/medium-zoom/commit/541e8f0f9fb06cf9c72bb92541b87a5153a15d18)), closes [#94](https://github.com/francoischalifour/medium-zoom/issues/94) 37 | 38 | ## [1.0.3](https://github.com/francoischalifour/medium-zoom/compare/1.0.2...1.0.3) (2019-01-20) 39 | 40 | ### Changed 41 | 42 | - Export default export type as ESM module ([#82](https://github.com/francoischalifour/medium-zoom/issues/82)) ([ed45fcb](https://github.com/francoischalifour/medium-zoom/commit/ed45fcbe0ae318f70411d8975c0c557ccf81f92b)) 43 | 44 | ### Fixed 45 | 46 | - Use document viewport size ([#78](https://github.com/francoischalifour/medium-zoom/issues/78)) ([9a06f9b](https://github.com/francoischalifour/medium-zoom/commit/9a06f9b41d644b3d8b17c0782518036620f31a11)), closes [#75](https://github.com/francoischalifour/medium-zoom/issues/75) 47 | - Improve type definitions ([#85](https://github.com/francoischalifour/medium-zoom/issues/85)) ([702a767](https://github.com/francoischalifour/medium-zoom/commit/702a7670fa8f5a680c5d0abd1f2ea308f97ad395)) 48 | 49 | ## [1.0.2](https://github.com/francoischalifour/medium-zoom/compare/1.0.1...1.0.2) (2018-09-05) 50 | 51 | ### Added 52 | 53 | - Improve TypeScript definition (#73) 54 | 55 | ## [1.0.1](https://github.com/francoischalifour/medium-zoom/compare/1.0.0...1.0.1) (2018-08-29) 56 | 57 | ### Fixed 58 | 59 | - Don't prevent behavior of all clicks ([#72](https://github.com/francoischalifour/medium-zoom/issues/72)) ([71eebf9](https://github.com/francoischalifour/medium-zoom/commit/71eebf90f09a81c013731871b8cab92a4243a557)), closes [#71](https://github.com/francoischalifour/medium-zoom/issues/71) 60 | 61 | # [1.0.0](https://github.com/francoischalifour/medium-zoom/compare/v0.4.0...1.0.0) (2018-08-28) 62 | 63 | ### Added 64 | 65 | - **Methods become chainable**. All methods except getters and animation methods (`open()`, `close()` and `toggle()`) return the zoom object to allow method calls to be chained. 66 | 67 | ```js 68 | const zoom = mediumZoom() 69 | 70 | zoom 71 | .attach('#image-1', '#image-2') 72 | .on('open', () => zoom.update({ background: 'yellow' })) 73 | .open() 74 | ``` 75 | 76 | - **Animation methods return promises**. `open()`, `close()` and `toggle()` return promises resolving with the zoom for acting accordingly when the animation is completed. To remain compatible with IE10, promises are converted to no-operation functions if unavailable. 77 | 78 | ```js 79 | const zoom = mediumZoom('[data-zoom]') 80 | 81 | zoom.open().then(() => zoom.update({ background: 'yellow' })) 82 | ``` 83 | 84 | - **Options** 85 | 86 | - `background` supports the [`background` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/background) (not only `background-color`) 87 | 88 | - **Methods** 89 | 90 | - `attach(...selectors: string[]|Element[]|NodeList[]|Array[]) => Zoom` 91 | - `clone(options?: object) => Zoom` 92 | - `getOptions() => object` 93 | - `getImages() => Element[]` 94 | - `getZoomedImage() => Element` 95 | 96 | - **Events** 97 | 98 | - "update" is fired when the `update` method is called 99 | 100 | - Add **TypeScript definitions** 101 | 102 | - Improve **documentation** 103 | 104 | ### Fixed 105 | 106 | - HD image scales the first time on Firefox (264c81f9d54b7272fa260616f117c3149be89123) 107 | - Support `srcset` attribute (#51) 108 | - Support SVG sources (#56) 109 | 110 | ### Breaking changes 111 | 112 | - **Imports**. If you're using CommonJS, you'll need to change the require statement: 113 | 114 | ```diff 115 | - const mediumZoom = require('medium-zoom') 116 | + const mediumZoom = require('medium-zoom').default 117 | ``` 118 | 119 | - **No images selected by default**. Prior to version 1, all scaled images (via HTML or CSS properties) were added to the zoom when calling `mediumZoom()`. Now, calling `mediumZoom()` without selector does not attach any images to the zoom. This change is necessary for having a more predictable behavior and a more composable API. 120 | 121 | - **Options** 122 | 123 | - `metaClick` was removed 124 | 125 | - **Methods** 126 | 127 | - `show() => void` → `open({ target?: Element }) => Promise` 128 | - `hide() => void` → `close() => Promise` 129 | - `toggle() => void` → `toggle({ target?: Element }) => Promise` 130 | - `detach() => void` → `detach(...selectors: string[]|Element[]|NodeList[]|Array[]) => Zoom` 131 | - `update(options: object) => void` → `update(options: object) => Zoom` 132 | - `addEventListeners(type: string, listener: Function) => void` → `on(type: string, listener: Function, options?: object) => Zoom` 133 | - `removeEventListeners(type: string, listener: Function) => void` → `off(type: string, listener: Function, options?: object) => Zoom` 134 | 135 | - **Attributes** 136 | 137 | - `data-zoom-target` → `data-zoom-src` 138 | 139 | - **Events** 140 | - "show" → "open" 141 | - "shown" → "opened" 142 | - "hide" → "close" 143 | - "hidden" → "closed" 144 | 145 | # [0.4.0](https://github.com/francoischalifour/medium-zoom/compare/v0.3.0...v0.4.0) (2018-03-09) 146 | 147 | ### Added 148 | 149 | - Support for IE ([#35](https://github.com/francoischalifour/medium-zoom/issues/35)) ([bd485fc](https://github.com/francoischalifour/medium-zoom/commit/bd485fc0416b4d3f8d7d1b6fd4e523f42ca2d8d8)), closes [#34](https://github.com/francoischalifour/medium-zoom/issues/34) 150 | 151 | ### Fixed 152 | 153 | - Calling `.detach()` when having a zoomed image: 9fa798d3fe96ae7060f316995b84eaacf3ce8a11 154 | 155 | # [0.3.0](https://github.com/francoischalifour/medium-zoom/compare/v0.2.0...v0.3.0) (2017-12-07) 156 | 157 | ### Added 158 | 159 | - Add support for `template`s and `container`s: d0d1ec141ffe744d059dddcfc08b6e830b7c17c9 160 | 161 | # [0.2.0](https://github.com/francoischalifour/medium-zoom/compare/v0.1.8...v0.2.0) (2017-10-01) 162 | 163 | ### Added 164 | 165 | - Add HD support: 1db9607dce2aa348d9be465208395d125b16e728 166 | 167 | ### Changed 168 | 169 | - Rewrite core implementation: 5158cace958acee0e89a4c9358704ed504756254 170 | - Update library description: a6f424bae2da534563154c26b49046367d7db215 171 | - Use less restrictive CSS rules: acaeba4bf96576b65867c3effc2710bd9d029dc0 172 | - Reduce latency on click to unzoom: 3c4c2fef2c2fca2ce542e57e13ce3198fe7ba2bb 173 | 174 | ### Fixed 175 | 176 | - Fix `hide` event being thrown multiple times on scroll: 3c4c2fef2c2fca2ce542e57e13ce3198fe7ba2bb 177 | 178 | ## [0.1.8](https://github.com/francoischalifour/medium-zoom/compare/v0.1.7...v0.1.8) (2017-09-17) 179 | 180 | ### Fixed 181 | 182 | - Do not trigger the zoom when target is `null` (can happen on fast double click): 3f795b44877af341ed65ae7c1bc764cc5122cdfb 183 | 184 | ## [0.1.7](https://github.com/francoischalifour/medium-zoom/compare/v0.1.6...v0.1.7) (2017-07-21) 185 | 186 | ### Fixed 187 | 188 | - Don't ignore margin on floating images: 384f0b1576e66f16844e0482eb1653a0c9479ad2 189 | 190 | ## [0.1.6](https://github.com/francoischalifour/medium-zoom/compare/v0.1.5...v0.1.6) (2017-07-19) 191 | 192 | ### Fixed 193 | 194 | - Support `scrollTop` position on Firefox: ee13718c38a7a4ba486cacfb50f2861dd1adb8ad 195 | 196 | ## [0.1.5](https://github.com/francoischalifour/medium-zoom/compare/v0.1.4...v0.1.5) (2017-06-10) 197 | 198 | ### Changed 199 | 200 | - Wrong selector trows a `TypeError` instead of a `SyntaxError`: 38e6292ce83d1b54f4fd80cce03d737c3872a58f 201 | - Library now fully exported by webpack: 5c7944b5e2de19828c8f9298fdc7a03a9146e42b 202 | - Production version is used when importing the library: 3a7d8ebc0ddd2cb142ccb8519de6fc57e8e8ba3e 203 | 204 | ## [0.1.4](https://github.com/francoischalifour/medium-zoom/compare/v0.1.3...v0.1.4) (2017-05-31) 205 | 206 | ### Added 207 | 208 | - Support NodeLists, HTMLCollections and Nodes (#8): aa8ff0ff6743e0bc011ea162ff068a2ddbb0f9ab 209 | 210 | ### Changed 211 | 212 | - Apply the default selector only when the plugin is given none (#7): aa8ff0ff6743e0bc011ea162ff068a2ddbb0f9ab 213 | 214 | ## [0.1.3](https://github.com/francoischalifour/medium-zoom/compare/v0.1.2...v0.1.3) (2017-04-01) 215 | 216 | ### Fixed 217 | 218 | - Center image when the doctype is not declared (#4): 95be45a63837bcd282433728f8db8759bd5777cb 219 | - Ignore zero-pixel scroll offset: 3cd34640ab26b04b802ce39ce74f092180e3cb00 220 | 221 | ## [0.1.2](https://github.com/francoischalifour/medium-zoom/compare/v0.1.1...v0.1.2) (2017-03-04) 222 | 223 | ### Added 224 | 225 | - `.detach()` method that unsubscribe images from the zoom (#2): 2ceb5120ebc35bb457a08474e0d39430e253ab08 226 | 227 | ## [0.1.1](https://github.com/francoischalifour/medium-zoom/compare/v0.1.0...v0.1.1) (2016-10-06) 228 | 229 | ### Fixed 230 | 231 | - Export the plugin for npm usage (#1): affca211ac6999f1d2c554205d5b216c37fc7c1c 232 | 233 | # 0.1.0 (2016-07-28) 234 | 235 | Initial release. 236 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Medium Zoom 2 | 3 | Thank you for getting involved in Medium Zoom! 4 | 5 | ## Concept 6 | 7 | This module is meant to reproduce the zoom from [Medium](http://medium.com). We want to provide a great UX (User Experience) with a lightweight vanilla JavaScript solution. Thus, this package must remain focused on this core principle, yet be extended with a composable API. 8 | 9 | ## Folder structure 10 | 11 | ``` 12 | ▸ cypress The end-to-end tests written for Cypress 13 | ▸ examples The Medium Zoom featured examples available on CodeSandbox 14 | ▸ src The source code of the module 15 | ▸ __tests__ The tests for the module API 16 | ▸ stories The stories for the Medium Zoom Storybook 17 | ▸ website The Medium Zoom website source code 18 | ``` 19 | 20 | ## Requirements 21 | 22 | - [Node](https://nodejs.org) 23 | - [Yarn](https://yarnpkg.com) 24 | 25 | ## Conventions 26 | 27 | ### Commits 28 | 29 | This project follows the [conventional changelog](https://conventionalcommits.org/) guidelines. All commit messages should be formatted using the following scheme: 30 | 31 | ``` 32 | type(scope): description 33 | ``` 34 | 35 | ## Workflow 36 | 37 | ### Filing issues 38 | 39 | Reporting a bug or requesting a feature is always welcome. Feel free to [open an issue](https://github.com/francoischalifour/medium-zoom/issues/new/choose) with the according template which helps you create an effective report. 40 | 41 | ### Submit code 42 | 43 | After discussing in an issue about the need to change the code, you will need to follow these steps: 44 | 45 | - [Fork the repository](https://help.github.com/articles/fork-a-repo/) 46 | - Clone your fork 47 | - Install the dependencies: `yarn` 48 | - For a **documentation** change: 49 | - Create a branch `docs/what-you-change` 50 | - Make the changes 51 | - Run `yarn run format` 52 | - For a **bug fix**: 53 | - Create a branch `fix/issue-number` 54 | - [Write a test](src/__tests__/medium-zoom.test.js) to reproduce the bug (run `yarn run test`) 55 | - Fix the bug in the [source code](src/medium-zoom.js) 56 | - Make your test pass the previous bug 57 | - Run `yarn run format` and fix problems if any 58 | - For a **feature**: 59 | - Create a branch `feat/name-of-the-feature` 60 | - Add the feature to the [source code](src/medium-zoom.js) 61 | - Create a story in the [storybook](stories) showcasing the feature 62 | - [Write a test](src/__tests__/medium-zoom.test.js) to ensure it's working as expected (run `yarn run test`) 63 | - Run `yarn run format` and fix problems if any 64 | - [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) 65 | 66 | We will then review your pull request! 67 | 68 | ### Testing 69 | 70 | #### Unit and integration tests 71 | 72 | [Unit and integration tests](src/__tests__) with [Jest](https://jestjs.io) ensure that the API works as documented. 73 | 74 | ###### Commands 75 | 76 | - Run the tests: `yarn run test` 77 | - Watch the tests: `yarn run test --watch` 78 | - Run the tests with coverage: `yarn run test --coverage` 79 | 80 | #### End-to-end tests 81 | 82 | [End-to-end tests](cypress/integration) with [Cypress](https://cypress.io) take screenshots of the stories to ensure that the zoom looks as expected. 83 | 84 | ###### Commands 85 | 86 | - Open the Cypress UI: `yarn run test:cypress:open` 87 | - Run the Cypress tests: `yarn run test:cypress:run` 88 | 89 | ### Releasing 90 | 91 | We rely on [release-it](https://github.com/webpro/release-it) to release new versions of this package. 92 | 93 | #### Release flow 94 | 95 | The release flow goes through these steps: 96 | 97 | 1. Run acceptance tests 98 | 1. Bump the project version in [`package.json`](package.json) based on [the commits](#conventions) 99 | 1. Commit the release version 100 | 1. Create the new Git tag for this release 101 | 1. Push to GitHub 102 | 1. Publish to npm 103 | 104 | #### Release steps 105 | 106 | ##### Unstable version 107 | 108 | 1. Make sure you're on the `next` branch 109 | 1. Run `npm run release:next` (_do not_ use `yarn` for releasing) 110 | 1. Follow the command-line instructions 111 | 112 | ##### Stable version 113 | 114 | 1. Make sure you're on the `master` branch 115 | 1. Run `npm run release` (_do not_ use `yarn` for releasing) 116 | 1. Follow the command-line instructions 117 | 118 | --- 119 | 120 | Thank you for contributing! 121 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-present François Chalifour 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bundlesize.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "path": "dist/style.css", 5 | "maxSize": "250 B" 6 | }, 7 | { 8 | "path": "dist/medium-zoom.esm.js", 9 | "maxSize": "5 kB" 10 | }, 11 | { 12 | "path": "dist/medium-zoom.min.js", 13 | "maxSize": "3.25 kB" 14 | }, 15 | { 16 | "path": "dist/pure/index.js", 17 | "maxSize": "4.75 kB" 18 | }, 19 | { 20 | "path": "dist/pure/medium-zoom.min.umd.js", 21 | "maxSize": "2.75 kB" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectId": "w2qxb8", 3 | "baseUrl": "http://localhost:9001", 4 | "viewportWidth": 720, 5 | "viewportHeight": 480, 6 | "fixturesFolder": false 7 | } 8 | -------------------------------------------------------------------------------- /cypress/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['cypress'], 3 | env: { 4 | 'cypress/globals': true, 5 | }, 6 | rules: { 7 | 'import/no-extraneous-dependencies': 0, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /cypress/integration/stories.spec.js: -------------------------------------------------------------------------------- 1 | const LOADING_DURATION = 200 2 | const ANIMATION_DURATION = 400 3 | 4 | const storybook = [ 5 | { 6 | kind: 'attributes', 7 | stories: [ 8 | { name: 'data-zoom-src' }, 9 | { name: 'srcset' }, 10 | { name: 'srcset and data-zoom-src' }, 11 | { name: 'SVG' }, 12 | ], 13 | }, 14 | { 15 | kind: 'options', 16 | stories: [ 17 | { name: 'default' }, 18 | { name: 'background (dark)' }, 19 | { name: 'background (transparent)' }, 20 | { name: 'margin' }, 21 | { name: 'scrollOffset' }, 22 | { name: 'container (DOM element)' }, 23 | { name: 'container (coordinates object)' }, 24 | { name: 'template (Dropbox Paper)' }, 25 | { name: 'template (Facebook)' }, 26 | ], 27 | }, 28 | ] 29 | 30 | storybook.forEach(category => { 31 | describe(category.kind, () => { 32 | category.stories.forEach(story => { 33 | it(story.name, () => { 34 | const queryParams = { 35 | full: 1, 36 | addons: 0, 37 | stories: 0, 38 | selectedKind: encodeURI(category.kind), 39 | selectedStory: encodeURI(story.name), 40 | } 41 | 42 | const urlParams = Object.entries(queryParams) 43 | .map(param => param.join('=')) 44 | .join('&') 45 | 46 | cy.visit(`/?${urlParams}`) 47 | cy.wait(LOADING_DURATION) 48 | 49 | cy.findInStory('.medium-zoom-image').each(($image, index) => { 50 | $image.click() 51 | cy.wait(ANIMATION_DURATION) 52 | 53 | cy.matchImageSnapshot( 54 | `${category.kind}/${[ 55 | story.name.toLowerCase().replace(/\s/g, '-'), 56 | index + 1, 57 | ].join('-')}`, 58 | { 59 | failureThreshold: 0.26, // threshold for entire image to accept scrollbars depending on the OS (especially for Travis) 60 | failureThresholdType: 'percent', 61 | customDiffConfig: { 62 | threshold: 0.1, 63 | }, 64 | } 65 | ) 66 | 67 | const $zoomedImage = cy.getInStory('.medium-zoom-image--opened') 68 | 69 | if ($zoomedImage.length) { 70 | $zoomedImage.click() 71 | cy.wait(ANIMATION_DURATION) 72 | } 73 | }) 74 | }) 75 | }) 76 | }) 77 | }) 78 | -------------------------------------------------------------------------------- /cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin') 2 | 3 | module.exports = on => { 4 | addMatchImageSnapshotPlugin(on) 5 | } 6 | -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/attributes/data-zoom-src-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/attributes/data-zoom-src-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/attributes/srcset-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/attributes/srcset-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/attributes/srcset-and-data-zoom-src-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/attributes/srcset-and-data-zoom-src-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/attributes/svg-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/attributes/svg-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/background-(dark)-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/background-(dark)-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/background-(transparent)-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/background-(transparent)-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/container-(coordinates-object)-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/container-(coordinates-object)-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/container-(dom-element)-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/container-(dom-element)-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/default-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/default-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/margin-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/margin-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/scrolloffset-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/scrolloffset-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/template-(dropbox-paper)-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/template-(dropbox-paper)-1.snap.png -------------------------------------------------------------------------------- /cypress/snapshots/stories.spec.js/options/template-(facebook)-1.snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/cypress/snapshots/stories.spec.js/options/template-(facebook)-1.snap.png -------------------------------------------------------------------------------- /cypress/support/commands.js: -------------------------------------------------------------------------------- 1 | import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command' 2 | 3 | addMatchImageSnapshotCommand() 4 | 5 | Cypress.Commands.add('getInStory', getInStory) 6 | Cypress.Commands.add('findInStory', findInStory) 7 | 8 | function getInStory(selector) { 9 | return cy.get('#storybook-preview-iframe').then($iframe => { 10 | const doc = $iframe.contents() 11 | 12 | return cy.wrap(doc.get(selector)) 13 | }) 14 | } 15 | 16 | function findInStory(selector) { 17 | return cy.get('#storybook-preview-iframe').then($iframe => { 18 | const doc = $iframe.contents() 19 | 20 | return cy.wrap(doc.find(selector)) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /cypress/support/index.js: -------------------------------------------------------------------------------- 1 | import './commands' 2 | -------------------------------------------------------------------------------- /docs/container.md: -------------------------------------------------------------------------------- 1 | # Using a custom viewport 2 | 3 | The zoom is by default rendered in the window viewport. You can also render your image in any element of the DOM, or any custom coordinates with the `container` option. 4 | 5 | ## Rendering in a DOM Element 6 | 7 | ```html 8 |
9 |

My article...

10 | My image 11 |
12 |
13 | 14 | 19 | ``` 20 | 21 | [Check the example →](https://medium-zoom.francoischalifour.com/storybook/?selectedKind=options&selectedStory=container%20%28DOM%20element%29) 22 | 23 | ## Rendering with coordinates 24 | 25 | If you don't already have an element in your DOM to specify the position of the zoom, you can pass an object with the following properties as `number`s: 26 | 27 | ```js 28 | mediumZoom('img', { 29 | container: { 30 | width: 720, 31 | height: 480, 32 | top: 64, 33 | bottom: 64, 34 | right: 0, 35 | left: 0, 36 | }, 37 | }) 38 | ``` 39 | 40 | These properties behave very much like [`Element.getBoundingClientRect()`](https://developer.mozilla.org/docs/Web/API/Element/getBoundingClientRect). They will get merged with the default ones so you don't need to specify all of them. 41 | 42 | The default `width` and `height` are `window.innerWidth` and `window.innerHeight`. Others are set to `0`. 43 | 44 | [Check the example →](https://medium-zoom.francoischalifour.com/storybook/?selectedKind=options&selectedStory=container%20%28coordinates%20object%29) 45 | -------------------------------------------------------------------------------- /docs/template.md: -------------------------------------------------------------------------------- 1 | # Using a custom template 2 | 3 | You might want to render the zoom in your own template. You could reproduce zooms as seen on [Facebook](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/facebook-template) or [Dropbox Paper](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/dropbox-paper-template). This is possible with the `template` option. 4 | 5 | 1. Create a [`template`](https://developer.mozilla.org/docs/Web/HTML/Element/template) element 6 | 2. Add the template selector or the element to the `template` option 7 | 8 | ```html 9 | 16 | 17 | 23 | ``` 24 | 25 | [Using a container](container.md) within a template is possible. 26 | 27 | ## Examples 28 | 29 | - [Dropbox Paper](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/dropbox-paper-template) 30 | - [Facebook](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/facebook-template) 31 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /dist 3 | /.cache 4 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/README.md: -------------------------------------------------------------------------------- 1 | # Dropbox Paper template 2 | 3 | > Source code for a Dropbox Paper template example. 4 | 5 | [![Preview](https://user-images.githubusercontent.com/6137112/32421182-c55c3a76-c263-11e7-80ce-be7cb35efcc9.png)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/dropbox-paper-template?view=preview) 6 | 7 |

8 | 9 | Edit Dropbox Paper Template Example 10 | 11 |

12 | 13 | ## Usage 14 | 15 | * Install dependencies: `yarn` 16 | * Run: `yarn start` 17 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Medium Zoom | Dropbox Paper Demo 12 | 13 | 14 | 15 | 46 | 47 |
48 |

Dropbox Paper Demo

49 | 50 | Zoom 1 with Dropbox Paper template 54 | 55 |

56 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora 57 | praesentium cupiditate fugit voluptas, rem eligendi, voluptatem 58 | molestias pariatur atque amet, dicta, similique beatae optio quos! Hic 59 | necessitatibus dicta magni, tempore. 60 |

61 | 62 | Zoom 2 with Dropbox Paper template 66 |
67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/dropbox-paper-template-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "parcel index.html --open", 8 | "build": "parcel build index.html" 9 | }, 10 | "dependencies": { 11 | "medium-zoom": "1.0.8" 12 | }, 13 | "devDependencies": { 14 | "parcel-bundler": "1.12.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/src/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/dropbox-paper-template/src/images/image-1.jpg -------------------------------------------------------------------------------- /examples/dropbox-paper-template/src/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/dropbox-paper-template/src/images/image-2.jpg -------------------------------------------------------------------------------- /examples/dropbox-paper-template/src/index.js: -------------------------------------------------------------------------------- 1 | import mediumZoom from 'medium-zoom' 2 | 3 | const zoomPaper = mediumZoom('.container img', { 4 | background: 'rgba(247, 249, 250, 0.97)', 5 | margin: 16, 6 | template: '#template-dropbox-paper', 7 | container: '[data-zoom-container]', 8 | }) 9 | 10 | // You can start manipulating the DOM after the `opened` event has been triggered 11 | zoomPaper.on('opened', () => { 12 | const closeButton = document.querySelector('[data-zoom-close]') 13 | closeButton.addEventListener('click', () => zoomPaper.close()) 14 | }) 15 | 16 | // Block scroll on zoom 17 | zoomPaper.on('open', () => { 18 | document.body.style.overflow = 'hidden' 19 | }) 20 | zoomPaper.on('close', () => { 21 | document.body.style.overflow = '' 22 | }) 23 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | -------------------------------------------------------------------------------- /examples/dropbox-paper-template/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | 38 | .paper-wrapper { 39 | position: fixed; 40 | display: flex; 41 | top: 0; 42 | left: 0; 43 | width: 100%; 44 | height: 100vh; 45 | } 46 | 47 | .paper-container { 48 | width: 100%; 49 | height: calc(100% - 64px); 50 | margin: 0 auto; 51 | } 52 | 53 | .paper-header { 54 | display: flex; 55 | align-items: center; 56 | height: 64px; 57 | padding: 16px; 58 | } 59 | 60 | .paper-main { 61 | flex: 1; 62 | height: 100%; 63 | } 64 | 65 | .paper-close { 66 | width: 24px; 67 | cursor: pointer; 68 | fill: #637282; 69 | } 70 | 71 | .paper-sidebar { 72 | width: 290px; 73 | border-left: 1px solid #e6e8eb; 74 | background-color: #fff; 75 | padding: 32px 0 16px 0; 76 | } 77 | 78 | @media (max-width: 800px) { 79 | .paper-sidebar { 80 | display: none; 81 | } 82 | } 83 | 84 | .paper-sidebar__header, 85 | .paper-sidebar__content { 86 | padding: 16px; 87 | } 88 | 89 | .paper-sidebar__header { 90 | border-bottom: 1px solid #e6e8eb; 91 | } 92 | 93 | .paper-sidebar__textarea { 94 | outline: none; 95 | width: 100%; 96 | border: none; 97 | background: none; 98 | font: inherit; 99 | font-size: 0.9rem; 100 | color: #637282; 101 | } 102 | 103 | .paper-sidebar__textarea::placeholder { 104 | color: #c1c7cd; 105 | } 106 | 107 | .paper-sidebar__textarea_comment { 108 | width: 100%; 109 | padding: 16px; 110 | border-radius: 5px; 111 | border: 1px solid rgba(99, 114, 130, 0.4); 112 | } 113 | -------------------------------------------------------------------------------- /examples/facebook-template/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .cache 4 | -------------------------------------------------------------------------------- /examples/facebook-template/README.md: -------------------------------------------------------------------------------- 1 | # Facebook template 2 | 3 | > Source code for a Facebook template example. 4 | 5 | [![Preview](https://user-images.githubusercontent.com/6137112/32421170-9c37500e-c263-11e7-8ef0-07a388f36210.png)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/facebook-template?view=preview) 6 | 7 |

8 | 9 | Edit Facebook Template Example 10 | 11 |

12 | 13 | ## Usage 14 | 15 | * Install dependencies: `yarn` 16 | * Run: `yarn start` 17 | -------------------------------------------------------------------------------- /examples/facebook-template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Medium Zoom | Facebook Demo 12 | 13 | 14 | 15 | 27 | 28 |
29 |

Facebook Demo

30 | 31 | Zoom 1 with Facebook template 32 | 33 |

34 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora 35 | praesentium cupiditate fugit voluptas, rem eligendi, voluptatem 36 | molestias pariatur atque amet, dicta, similique beatae optio quos! Hic 37 | necessitatibus dicta magni, tempore. 38 |

39 | 40 | Zoom 2 with Facebook template 41 |
42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/facebook-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/facebook-template-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "parcel index.html --open", 8 | "build": "parcel build index.html" 9 | }, 10 | "dependencies": { 11 | "medium-zoom": "1.0.8" 12 | }, 13 | "devDependencies": { 14 | "parcel-bundler": "1.12.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/facebook-template/src/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/facebook-template/src/images/image-1.jpg -------------------------------------------------------------------------------- /examples/facebook-template/src/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/facebook-template/src/images/image-2.jpg -------------------------------------------------------------------------------- /examples/facebook-template/src/index.js: -------------------------------------------------------------------------------- 1 | import mediumZoom from 'medium-zoom' 2 | 3 | const zoomFacebook = mediumZoom('.container img', { 4 | background: 'rgba(0, 0, 0, 0.9)', 5 | template: '#template-facebook', 6 | container: '[data-zoom-container]', 7 | }) 8 | 9 | // You can start manipulating the DOM after the `opened` event has been triggered 10 | zoomFacebook.on('opened', () => { 11 | const closeButton = document.querySelector('[data-zoom-close]') 12 | closeButton.addEventListener('click', () => zoomFacebook.close()) 13 | }) 14 | 15 | // Block scroll on zoom 16 | zoomFacebook.on('open', () => { 17 | document.body.style.overflow = 'hidden' 18 | }) 19 | 20 | zoomFacebook.on('close', () => { 21 | document.body.style.overflow = '' 22 | }) 23 | -------------------------------------------------------------------------------- /examples/facebook-template/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | -------------------------------------------------------------------------------- /examples/facebook-template/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | 38 | .facebook-wrapper { 39 | position: fixed; 40 | display: flex; 41 | top: 0; 42 | height: 520px; 43 | top: 0; 44 | bottom: 0; 45 | left: 4rem; 46 | right: 4rem; 47 | margin: auto; 48 | box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3); 49 | } 50 | 51 | .facebook-main { 52 | flex: 1; 53 | height: 100%; 54 | background-color: #000; 55 | } 56 | 57 | .facebook-sidebar { 58 | width: 360px; 59 | background-color: #fff; 60 | padding: 32px 0 16px 0; 61 | } 62 | 63 | @media (max-width: 800px) { 64 | .facebook-sidebar { 65 | display: none; 66 | } 67 | } 68 | 69 | .facebook-close { 70 | position: fixed; 71 | top: 8px; 72 | right: 8px; 73 | width: 32px; 74 | cursor: pointer; 75 | fill: #ddd; 76 | } 77 | -------------------------------------------------------------------------------- /examples/react-markdown/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/react-markdown/README.md: -------------------------------------------------------------------------------- 1 | # Medium Zoom React Markdown Example 2 | 3 | This example reads Markdown in a React component and attaches the zoom on the Markdown images. 4 | 5 | [![Edit React Markdown Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/react-markdown?file=/src/App.tsx) 6 | 7 | ## Usage 8 | 9 | - Install dependencies: `yarn` 10 | - Run: `yarn dev` 11 | -------------------------------------------------------------------------------- /examples/react-markdown/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | Medium Zoom | React Markdown Demo 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/react-markdown/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/react-markdown-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "medium-zoom": "1.0.8", 13 | "react": "18.2.0", 14 | "react-dom": "18.2.0", 15 | "react-markdown": "8.0.6" 16 | }, 17 | "devDependencies": { 18 | "@types/react": "^18.0.28", 19 | "@types/react-dom": "^18.0.11", 20 | "@vitejs/plugin-react": "3.1.0", 21 | "typescript": "4.9.3", 22 | "vite": "4.2.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/react-markdown/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react-markdown/public/favicon.ico -------------------------------------------------------------------------------- /examples/react-markdown/public/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react-markdown/public/images/image-1.jpg -------------------------------------------------------------------------------- /examples/react-markdown/public/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react-markdown/public/images/image-2.jpg -------------------------------------------------------------------------------- /examples/react-markdown/public/images/image-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react-markdown/public/images/image-3.jpg -------------------------------------------------------------------------------- /examples/react-markdown/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react' 2 | import ReactMarkdown from 'react-markdown' 3 | import mediumZoom from 'medium-zoom' 4 | 5 | const markdown = ` 6 | ![Zoom 1](images/image-1.jpg) 7 | 8 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora praesentium cupiditate fugit voluptas, rem eligendi, voluptatem molestias. Doloremque sit voluptatum odio maiores provident consequuntur accusantium saepe. 9 | 10 | ![Zoom 2](images/image-2.jpg) 11 | 12 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. 13 | Ea dolores quaerat, quis modi nostrum sequi adipisci ratione esse blanditiis error beatae vel non vero dolor nemo. Animi nemo quisquam ducimus! 14 | 15 | ![Zoom 3](images/image-3.jpg) 16 | ` 17 | 18 | export function App() { 19 | useEffect(() => { 20 | const zoom = mediumZoom('.container img') 21 | 22 | return () => { 23 | zoom.detach() 24 | } 25 | }, []) 26 | 27 | return ( 28 |
29 |

Medium Zoom React Markdown demo

30 | 31 | 32 |
33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /examples/react-markdown/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | 4 | import { App } from './App' 5 | 6 | import './reset.css' 7 | import './style.css' 8 | 9 | ReactDOM.createRoot(document.getElementById('root')!).render( 10 | 11 | 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /examples/react-markdown/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, 7 | body, 8 | div, 9 | span, 10 | applet, 11 | object, 12 | iframe, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6, 19 | p, 20 | blockquote, 21 | pre, 22 | a, 23 | abbr, 24 | acronym, 25 | address, 26 | big, 27 | cite, 28 | code, 29 | del, 30 | dfn, 31 | em, 32 | img, 33 | ins, 34 | kbd, 35 | q, 36 | s, 37 | samp, 38 | small, 39 | strike, 40 | strong, 41 | sub, 42 | sup, 43 | tt, 44 | var, 45 | b, 46 | u, 47 | i, 48 | center, 49 | dl, 50 | dt, 51 | dd, 52 | ol, 53 | ul, 54 | li, 55 | fieldset, 56 | form, 57 | label, 58 | legend, 59 | table, 60 | caption, 61 | tbody, 62 | tfoot, 63 | thead, 64 | tr, 65 | th, 66 | td, 67 | article, 68 | aside, 69 | canvas, 70 | details, 71 | embed, 72 | figure, 73 | figcaption, 74 | footer, 75 | header, 76 | hgroup, 77 | menu, 78 | nav, 79 | output, 80 | ruby, 81 | section, 82 | summary, 83 | time, 84 | mark, 85 | audio, 86 | video { 87 | margin: 0; 88 | padding: 0; 89 | border: 0; 90 | font-size: 100%; 91 | font: inherit; 92 | vertical-align: baseline; 93 | } 94 | /* HTML5 display-role reset for older browsers */ 95 | article, 96 | aside, 97 | details, 98 | figcaption, 99 | figure, 100 | footer, 101 | header, 102 | hgroup, 103 | menu, 104 | nav, 105 | section { 106 | display: block; 107 | } 108 | body { 109 | line-height: 1; 110 | } 111 | ol, 112 | ul { 113 | list-style: none; 114 | } 115 | blockquote, 116 | q { 117 | quotes: none; 118 | } 119 | blockquote:before, 120 | blockquote:after, 121 | q:before, 122 | q:after { 123 | content: ''; 124 | content: none; 125 | } 126 | table { 127 | border-collapse: collapse; 128 | border-spacing: 0; 129 | } 130 | -------------------------------------------------------------------------------- /examples/react-markdown/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | -------------------------------------------------------------------------------- /examples/react-markdown/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/react-markdown/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/react-markdown/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/react-markdown/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /examples/react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/react/README.md: -------------------------------------------------------------------------------- 1 | # Medium Zoom React Example 2 | 3 | This example creates an `` component that attaches the zoom to the image. 4 | 5 | [![Edit React Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/react?file=/src/App.tsx) 6 | 7 | ## Usage 8 | 9 | - Install dependencies: `yarn` 10 | - Run: `yarn dev` 11 | -------------------------------------------------------------------------------- /examples/react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | Medium Zoom | React Demo 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/react-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "medium-zoom": "1.0.8", 13 | "react": "18.2.0", 14 | "react-dom": "18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^18.0.28", 18 | "@types/react-dom": "^18.0.11", 19 | "@vitejs/plugin-react": "3.1.0", 20 | "typescript": "4.9.3", 21 | "vite": "4.2.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react/public/favicon.ico -------------------------------------------------------------------------------- /examples/react/public/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react/public/images/image-1.jpg -------------------------------------------------------------------------------- /examples/react/public/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react/public/images/image-2.jpg -------------------------------------------------------------------------------- /examples/react/public/images/image-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/react/public/images/image-3.jpg -------------------------------------------------------------------------------- /examples/react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { ImageZoom } from './ImageZoom' 2 | 3 | export function App() { 4 | return ( 5 |
6 |

React demo

7 | 8 | 9 | 10 |

11 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora 12 | praesentium cupiditate fugit voluptas, rem eligendi, voluptatem 13 | molestias. Doloremque sit voluptatum odio maiores provident consequuntur 14 | accusantium saepe. 15 |

16 | 17 | 18 | 19 |

20 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea dolores 21 | quaerat, quis modi nostrum sequi adipisci ratione esse blanditiis error 22 | beatae vel non vero dolor nemo. Animi nemo quisquam ducimus! 23 |

24 | 25 | 30 |
31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /examples/react/src/ImageZoom.tsx: -------------------------------------------------------------------------------- 1 | import { useRef, ComponentProps, RefCallback } from 'react' 2 | import mediumZoom, { Zoom, ZoomOptions } from 'medium-zoom' 3 | 4 | type ImageZoomProps = ComponentProps<'img'> & { 5 | options?: ZoomOptions 6 | } 7 | 8 | export function ImageZoom({ options, ...props }: ImageZoomProps) { 9 | const zoomRef = useRef(null) 10 | 11 | function getZoom() { 12 | if (zoomRef.current === null) { 13 | zoomRef.current = mediumZoom(options) 14 | } 15 | 16 | return zoomRef.current 17 | } 18 | 19 | const attachZoom: RefCallback = node => { 20 | const zoom = getZoom() 21 | 22 | if (node) { 23 | zoom.attach(node) 24 | } else { 25 | zoom.detach() 26 | } 27 | } 28 | 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /examples/react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | 4 | import { App } from './App' 5 | 6 | import './reset.css' 7 | import './style.css' 8 | 9 | ReactDOM.createRoot(document.getElementById('root')!).render( 10 | 11 | 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /examples/react/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, 7 | body, 8 | div, 9 | span, 10 | applet, 11 | object, 12 | iframe, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6, 19 | p, 20 | blockquote, 21 | pre, 22 | a, 23 | abbr, 24 | acronym, 25 | address, 26 | big, 27 | cite, 28 | code, 29 | del, 30 | dfn, 31 | em, 32 | img, 33 | ins, 34 | kbd, 35 | q, 36 | s, 37 | samp, 38 | small, 39 | strike, 40 | strong, 41 | sub, 42 | sup, 43 | tt, 44 | var, 45 | b, 46 | u, 47 | i, 48 | center, 49 | dl, 50 | dt, 51 | dd, 52 | ol, 53 | ul, 54 | li, 55 | fieldset, 56 | form, 57 | label, 58 | legend, 59 | table, 60 | caption, 61 | tbody, 62 | tfoot, 63 | thead, 64 | tr, 65 | th, 66 | td, 67 | article, 68 | aside, 69 | canvas, 70 | details, 71 | embed, 72 | figure, 73 | figcaption, 74 | footer, 75 | header, 76 | hgroup, 77 | menu, 78 | nav, 79 | output, 80 | ruby, 81 | section, 82 | summary, 83 | time, 84 | mark, 85 | audio, 86 | video { 87 | margin: 0; 88 | padding: 0; 89 | border: 0; 90 | font-size: 100%; 91 | font: inherit; 92 | vertical-align: baseline; 93 | } 94 | /* HTML5 display-role reset for older browsers */ 95 | article, 96 | aside, 97 | details, 98 | figcaption, 99 | figure, 100 | footer, 101 | header, 102 | hgroup, 103 | menu, 104 | nav, 105 | section { 106 | display: block; 107 | } 108 | body { 109 | line-height: 1; 110 | } 111 | ol, 112 | ul { 113 | list-style: none; 114 | } 115 | blockquote, 116 | q { 117 | quotes: none; 118 | } 119 | blockquote:before, 120 | blockquote:after, 121 | q:before, 122 | q:after { 123 | content: ''; 124 | content: none; 125 | } 126 | table { 127 | border-collapse: collapse; 128 | border-spacing: 0; 129 | } 130 | -------------------------------------------------------------------------------- /examples/react/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | -------------------------------------------------------------------------------- /examples/react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/react/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /examples/svelte/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/svelte/README.md: -------------------------------------------------------------------------------- 1 | # Medium Zoom Svelte Example 2 | 3 | This example creates an `` component that attaches the zoom to the image. 4 | 5 | [![Edit Svelte Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/svelte?file=/src/App.svelte) 6 | 7 | ## Usage 8 | 9 | - Install dependencies: `yarn` 10 | - Run: `yarn dev` 11 | -------------------------------------------------------------------------------- /examples/svelte/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | Medium Zoom | Svelte Demo 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/svelte/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "Node", 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | /** 7 | * svelte-preprocess cannot figure out whether you have 8 | * a value or a type, so tell TypeScript to enforce using 9 | * `import type` instead of `import` for Types. 10 | */ 11 | "importsNotUsedAsValues": "error", 12 | "isolatedModules": true, 13 | "resolveJsonModule": true, 14 | /** 15 | * To have warnings / errors of the Svelte compiler at the 16 | * correct position, enable source maps by default. 17 | */ 18 | "sourceMap": true, 19 | "esModuleInterop": true, 20 | "skipLibCheck": true, 21 | "forceConsistentCasingInFileNames": true, 22 | /** 23 | * Typecheck JS in `.svelte` and `.js` files by default. 24 | * Disable this if you'd like to use dynamic types. 25 | */ 26 | "checkJs": true 27 | }, 28 | /** 29 | * Use global.d.ts instead of compilerOptions.types 30 | * to avoid limiting type declarations. 31 | */ 32 | "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] 33 | } 34 | -------------------------------------------------------------------------------- /examples/svelte/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/svelte-example", 3 | "private": true, 4 | "version": "0.1.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "medium-zoom": "1.0.8" 13 | }, 14 | "devDependencies": { 15 | "@sveltejs/vite-plugin-svelte": "2.0.3", 16 | "svelte": "3.55.1", 17 | "vite": "4.2.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/svelte/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/svelte/public/favicon.ico -------------------------------------------------------------------------------- /examples/svelte/public/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/svelte/public/images/image-1.jpg -------------------------------------------------------------------------------- /examples/svelte/public/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/svelte/public/images/image-2.jpg -------------------------------------------------------------------------------- /examples/svelte/public/images/image-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/svelte/public/images/image-3.jpg -------------------------------------------------------------------------------- /examples/svelte/src/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |

Medium Zoom Svelte demo

7 | 8 | 9 | 10 |

11 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora 12 | praesentium cupiditate fugit voluptas, rem eligendi, voluptatem molestias. 13 | Doloremque sit voluptatum odio maiores provident consequuntur accusantium 14 | saepe. 15 |

16 | 17 | 18 | 19 |

20 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea dolores 21 | quaerat, quis modi nostrum sequi adipisci ratione esse blanditiis error 22 | beatae vel non vero dolor nemo. Animi nemo quisquam ducimus! 23 |

24 | 25 | 30 |
31 | -------------------------------------------------------------------------------- /examples/svelte/src/app.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | color-scheme: light dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | -webkit-text-size-adjust: 100%; 15 | } 16 | 17 | a { 18 | font-weight: 500; 19 | color: #646cff; 20 | text-decoration: inherit; 21 | } 22 | a:hover { 23 | color: #535bf2; 24 | } 25 | 26 | body { 27 | margin: 0; 28 | display: flex; 29 | place-items: center; 30 | min-width: 320px; 31 | min-height: 100vh; 32 | } 33 | 34 | h1 { 35 | font-size: 3.2em; 36 | line-height: 1.1; 37 | } 38 | 39 | .card { 40 | padding: 2em; 41 | } 42 | 43 | #app { 44 | max-width: 1280px; 45 | margin: 0 auto; 46 | padding: 2rem; 47 | text-align: center; 48 | } 49 | 50 | button { 51 | border-radius: 8px; 52 | border: 1px solid transparent; 53 | padding: 0.6em 1.2em; 54 | font-size: 1em; 55 | font-weight: 500; 56 | font-family: inherit; 57 | background-color: #1a1a1a; 58 | cursor: pointer; 59 | transition: border-color 0.25s; 60 | } 61 | button:hover { 62 | border-color: #646cff; 63 | } 64 | button:focus, 65 | button:focus-visible { 66 | outline: 4px auto -webkit-focus-ring-color; 67 | } 68 | 69 | @media (prefers-color-scheme: light) { 70 | :root { 71 | color: #213547; 72 | background-color: #ffffff; 73 | } 74 | a:hover { 75 | color: #747bff; 76 | } 77 | button { 78 | background-color: #f9f9f9; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /examples/svelte/src/lib/ImageZoom.svelte: -------------------------------------------------------------------------------- 1 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/svelte/src/main.js: -------------------------------------------------------------------------------- 1 | import './reset.css' 2 | import './style.css' 3 | 4 | import App from './App.svelte' 5 | 6 | const app = new App({ 7 | target: document.getElementById('app'), 8 | }) 9 | 10 | export default app 11 | -------------------------------------------------------------------------------- /examples/svelte/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, 7 | body, 8 | div, 9 | span, 10 | applet, 11 | object, 12 | iframe, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6, 19 | p, 20 | blockquote, 21 | pre, 22 | a, 23 | abbr, 24 | acronym, 25 | address, 26 | big, 27 | cite, 28 | code, 29 | del, 30 | dfn, 31 | em, 32 | img, 33 | ins, 34 | kbd, 35 | q, 36 | s, 37 | samp, 38 | small, 39 | strike, 40 | strong, 41 | sub, 42 | sup, 43 | tt, 44 | var, 45 | b, 46 | u, 47 | i, 48 | center, 49 | dl, 50 | dt, 51 | dd, 52 | ol, 53 | ul, 54 | li, 55 | fieldset, 56 | form, 57 | label, 58 | legend, 59 | table, 60 | caption, 61 | tbody, 62 | tfoot, 63 | thead, 64 | tr, 65 | th, 66 | td, 67 | article, 68 | aside, 69 | canvas, 70 | details, 71 | embed, 72 | figure, 73 | figcaption, 74 | footer, 75 | header, 76 | hgroup, 77 | menu, 78 | nav, 79 | output, 80 | ruby, 81 | section, 82 | summary, 83 | time, 84 | mark, 85 | audio, 86 | video { 87 | margin: 0; 88 | padding: 0; 89 | border: 0; 90 | font-size: 100%; 91 | font: inherit; 92 | vertical-align: baseline; 93 | } 94 | /* HTML5 display-role reset for older browsers */ 95 | article, 96 | aside, 97 | details, 98 | figcaption, 99 | figure, 100 | footer, 101 | header, 102 | hgroup, 103 | menu, 104 | nav, 105 | section { 106 | display: block; 107 | } 108 | body { 109 | line-height: 1; 110 | } 111 | ol, 112 | ul { 113 | list-style: none; 114 | } 115 | blockquote, 116 | q { 117 | quotes: none; 118 | } 119 | blockquote:before, 120 | blockquote:after, 121 | q:before, 122 | q:after { 123 | content: ''; 124 | content: none; 125 | } 126 | table { 127 | border-collapse: collapse; 128 | border-spacing: 0; 129 | } 130 | -------------------------------------------------------------------------------- /examples/svelte/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | -------------------------------------------------------------------------------- /examples/svelte/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /examples/svelte/svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' 2 | 3 | export default { 4 | // Consult https://svelte.dev/docs#compile-time-svelte-preprocess 5 | // for more information about preprocessors 6 | preprocess: vitePreprocess(), 7 | } 8 | -------------------------------------------------------------------------------- /examples/svelte/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { svelte } from '@sveltejs/vite-plugin-svelte' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [svelte()], 7 | }) 8 | -------------------------------------------------------------------------------- /examples/svelte/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@esbuild/android-arm64@0.17.15": 6 | version "0.17.15" 7 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz#893ad71f3920ccb919e1757c387756a9bca2ef42" 8 | integrity sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA== 9 | 10 | "@esbuild/android-arm@0.17.15": 11 | version "0.17.15" 12 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.15.tgz#143e0d4e4c08c786ea410b9a7739779a9a1315d8" 13 | integrity sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg== 14 | 15 | "@esbuild/android-x64@0.17.15": 16 | version "0.17.15" 17 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.15.tgz#d2d12a7676b2589864281b2274355200916540bc" 18 | integrity sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ== 19 | 20 | "@esbuild/darwin-arm64@0.17.15": 21 | version "0.17.15" 22 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz#2e88e79f1d327a2a7d9d06397e5232eb0a473d61" 23 | integrity sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA== 24 | 25 | "@esbuild/darwin-x64@0.17.15": 26 | version "0.17.15" 27 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz#9384e64c0be91388c57be6d3a5eaf1c32a99c91d" 28 | integrity sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg== 29 | 30 | "@esbuild/freebsd-arm64@0.17.15": 31 | version "0.17.15" 32 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz#2ad5a35bc52ebd9ca6b845dbc59ba39647a93c1a" 33 | integrity sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg== 34 | 35 | "@esbuild/freebsd-x64@0.17.15": 36 | version "0.17.15" 37 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz#b513a48446f96c75fda5bef470e64d342d4379cd" 38 | integrity sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ== 39 | 40 | "@esbuild/linux-arm64@0.17.15": 41 | version "0.17.15" 42 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz#9697b168175bfd41fa9cc4a72dd0d48f24715f31" 43 | integrity sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA== 44 | 45 | "@esbuild/linux-arm@0.17.15": 46 | version "0.17.15" 47 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz#5b22062c54f48cd92fab9ffd993732a52db70cd3" 48 | integrity sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw== 49 | 50 | "@esbuild/linux-ia32@0.17.15": 51 | version "0.17.15" 52 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz#eb28a13f9b60b5189fcc9e98e1024f6b657ba54c" 53 | integrity sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q== 54 | 55 | "@esbuild/linux-loong64@0.17.15": 56 | version "0.17.15" 57 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz#32454bdfe144cf74b77895a8ad21a15cb81cfbe5" 58 | integrity sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ== 59 | 60 | "@esbuild/linux-mips64el@0.17.15": 61 | version "0.17.15" 62 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz#af12bde0d775a318fad90eb13a0455229a63987c" 63 | integrity sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ== 64 | 65 | "@esbuild/linux-ppc64@0.17.15": 66 | version "0.17.15" 67 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz#34c5ed145b2dfc493d3e652abac8bd3baa3865a5" 68 | integrity sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg== 69 | 70 | "@esbuild/linux-riscv64@0.17.15": 71 | version "0.17.15" 72 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz#87bd515e837f2eb004b45f9e6a94dc5b93f22b92" 73 | integrity sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA== 74 | 75 | "@esbuild/linux-s390x@0.17.15": 76 | version "0.17.15" 77 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz#20bf7947197f199ddac2ec412029a414ceae3aa3" 78 | integrity sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg== 79 | 80 | "@esbuild/linux-x64@0.17.15": 81 | version "0.17.15" 82 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz#31b93f9c94c195e852c20cd3d1914a68aa619124" 83 | integrity sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg== 84 | 85 | "@esbuild/netbsd-x64@0.17.15": 86 | version "0.17.15" 87 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz#8da299b3ac6875836ca8cdc1925826498069ac65" 88 | integrity sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA== 89 | 90 | "@esbuild/openbsd-x64@0.17.15": 91 | version "0.17.15" 92 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz#04a1ec3d4e919714dba68dcf09eeb1228ad0d20c" 93 | integrity sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w== 94 | 95 | "@esbuild/sunos-x64@0.17.15": 96 | version "0.17.15" 97 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz#6694ebe4e16e5cd7dab6505ff7c28f9c1c695ce5" 98 | integrity sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ== 99 | 100 | "@esbuild/win32-arm64@0.17.15": 101 | version "0.17.15" 102 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz#1f95b2564193c8d1fee8f8129a0609728171d500" 103 | integrity sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q== 104 | 105 | "@esbuild/win32-ia32@0.17.15": 106 | version "0.17.15" 107 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz#c362b88b3df21916ed7bcf75c6d09c6bf3ae354a" 108 | integrity sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w== 109 | 110 | "@esbuild/win32-x64@0.17.15": 111 | version "0.17.15" 112 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz#c2e737f3a201ebff8e2ac2b8e9f246b397ad19b8" 113 | integrity sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA== 114 | 115 | "@jridgewell/sourcemap-codec@^1.4.13": 116 | version "1.4.15" 117 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" 118 | integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== 119 | 120 | "@sveltejs/vite-plugin-svelte@2.0.3": 121 | version "2.0.3" 122 | resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.0.3.tgz#3d276eab341638dd58691a3de610774e155a7578" 123 | integrity sha512-o+cguBFdwIGtRbNkYOyqTM7KvRUffxh5bfK4oJsWKG2obu+v/cbpT03tJrGl58C7tRXo/aEC0/axN5FVHBj0nA== 124 | dependencies: 125 | debug "^4.3.4" 126 | deepmerge "^4.3.0" 127 | kleur "^4.1.5" 128 | magic-string "^0.29.0" 129 | svelte-hmr "^0.15.1" 130 | vitefu "^0.2.4" 131 | 132 | debug@^4.3.4: 133 | version "4.3.4" 134 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 135 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 136 | dependencies: 137 | ms "2.1.2" 138 | 139 | deepmerge@^4.3.0: 140 | version "4.3.1" 141 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" 142 | integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== 143 | 144 | esbuild@^0.17.5: 145 | version "0.17.15" 146 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.15.tgz#209ebc87cb671ffb79574db93494b10ffaf43cbc" 147 | integrity sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw== 148 | optionalDependencies: 149 | "@esbuild/android-arm" "0.17.15" 150 | "@esbuild/android-arm64" "0.17.15" 151 | "@esbuild/android-x64" "0.17.15" 152 | "@esbuild/darwin-arm64" "0.17.15" 153 | "@esbuild/darwin-x64" "0.17.15" 154 | "@esbuild/freebsd-arm64" "0.17.15" 155 | "@esbuild/freebsd-x64" "0.17.15" 156 | "@esbuild/linux-arm" "0.17.15" 157 | "@esbuild/linux-arm64" "0.17.15" 158 | "@esbuild/linux-ia32" "0.17.15" 159 | "@esbuild/linux-loong64" "0.17.15" 160 | "@esbuild/linux-mips64el" "0.17.15" 161 | "@esbuild/linux-ppc64" "0.17.15" 162 | "@esbuild/linux-riscv64" "0.17.15" 163 | "@esbuild/linux-s390x" "0.17.15" 164 | "@esbuild/linux-x64" "0.17.15" 165 | "@esbuild/netbsd-x64" "0.17.15" 166 | "@esbuild/openbsd-x64" "0.17.15" 167 | "@esbuild/sunos-x64" "0.17.15" 168 | "@esbuild/win32-arm64" "0.17.15" 169 | "@esbuild/win32-ia32" "0.17.15" 170 | "@esbuild/win32-x64" "0.17.15" 171 | 172 | fsevents@~2.3.2: 173 | version "2.3.2" 174 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 175 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 176 | 177 | function-bind@^1.1.1: 178 | version "1.1.1" 179 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 180 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 181 | 182 | has@^1.0.3: 183 | version "1.0.3" 184 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 185 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 186 | dependencies: 187 | function-bind "^1.1.1" 188 | 189 | is-core-module@^2.11.0: 190 | version "2.11.0" 191 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" 192 | integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== 193 | dependencies: 194 | has "^1.0.3" 195 | 196 | kleur@^4.1.5: 197 | version "4.1.5" 198 | resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" 199 | integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== 200 | 201 | magic-string@^0.29.0: 202 | version "0.29.0" 203 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.29.0.tgz#f034f79f8c43dba4ae1730ffb5e8c4e084b16cf3" 204 | integrity sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q== 205 | dependencies: 206 | "@jridgewell/sourcemap-codec" "^1.4.13" 207 | 208 | medium-zoom@1.0.8: 209 | version "1.0.8" 210 | resolved "https://registry.yarnpkg.com/medium-zoom/-/medium-zoom-1.0.8.tgz#2bd1fbcf2961fa7b0e318fe284462aa9b8608ed2" 211 | integrity sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA== 212 | 213 | ms@2.1.2: 214 | version "2.1.2" 215 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 216 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 217 | 218 | nanoid@^3.3.4: 219 | version "3.3.6" 220 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" 221 | integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== 222 | 223 | path-parse@^1.0.7: 224 | version "1.0.7" 225 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 226 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 227 | 228 | picocolors@^1.0.0: 229 | version "1.0.0" 230 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 231 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 232 | 233 | postcss@^8.4.21: 234 | version "8.4.21" 235 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" 236 | integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== 237 | dependencies: 238 | nanoid "^3.3.4" 239 | picocolors "^1.0.0" 240 | source-map-js "^1.0.2" 241 | 242 | resolve@^1.22.1: 243 | version "1.22.2" 244 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" 245 | integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== 246 | dependencies: 247 | is-core-module "^2.11.0" 248 | path-parse "^1.0.7" 249 | supports-preserve-symlinks-flag "^1.0.0" 250 | 251 | rollup@^3.18.0: 252 | version "3.20.2" 253 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.20.2.tgz#f798c600317f216de2e4ad9f4d9ab30a89b690ff" 254 | integrity sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg== 255 | optionalDependencies: 256 | fsevents "~2.3.2" 257 | 258 | source-map-js@^1.0.2: 259 | version "1.0.2" 260 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 261 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 262 | 263 | supports-preserve-symlinks-flag@^1.0.0: 264 | version "1.0.0" 265 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 266 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 267 | 268 | svelte-hmr@^0.15.1: 269 | version "0.15.1" 270 | resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.15.1.tgz#d11d878a0bbb12ec1cba030f580cd2049f4ec86b" 271 | integrity sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA== 272 | 273 | svelte@3.55.1: 274 | version "3.55.1" 275 | resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.55.1.tgz#6f93b153e5248039906ce5fe196efdb9e05dfce8" 276 | integrity sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ== 277 | 278 | vite@4.2.0: 279 | version "4.2.0" 280 | resolved "https://registry.yarnpkg.com/vite/-/vite-4.2.0.tgz#d4e6eafbc034f3faf0ab376bd5b76ac15775eb99" 281 | integrity sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g== 282 | dependencies: 283 | esbuild "^0.17.5" 284 | postcss "^8.4.21" 285 | resolve "^1.22.1" 286 | rollup "^3.18.0" 287 | optionalDependencies: 288 | fsevents "~2.3.2" 289 | 290 | vitefu@^0.2.4: 291 | version "0.2.4" 292 | resolved "https://registry.yarnpkg.com/vitefu/-/vitefu-0.2.4.tgz#212dc1a9d0254afe65e579351bed4e25d81e0b35" 293 | integrity sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g== 294 | -------------------------------------------------------------------------------- /examples/vanilla/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .cache 4 | -------------------------------------------------------------------------------- /examples/vanilla/README.md: -------------------------------------------------------------------------------- 1 | # Medium Zoom Vanilla JavaScript Example 2 | 3 | [![Edit JavaScript Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/vanilla?file=/src/index.js) 4 | 5 | ## Usage 6 | 7 | - Install dependencies: `yarn` 8 | - Run: `yarn dev` 9 | -------------------------------------------------------------------------------- /examples/vanilla/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Medium Zoom | Vanilla JavaScript demo 12 | 13 | 14 | 15 |
16 |

Vanilla JavaScript demo

17 | 18 | Zoom 1 19 | 20 |

21 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora 22 | praesentium cupiditate fugit voluptas, rem eligendi, voluptatem 23 | molestias pariatur atque amet, dicta, similique beatae optio quos! Hic 24 | necessitatibus dicta magni, tempore. 25 |

26 | 27 | Zoom 2 28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/vanilla/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/vanilla-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "parcel index.html --open", 8 | "build": "parcel build index.html --public-url ./" 9 | }, 10 | "dependencies": { 11 | "medium-zoom": "1.0.8" 12 | }, 13 | "devDependencies": { 14 | "parcel-bundler": "1.12.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/vanilla/src/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/vanilla/src/images/image-1.jpg -------------------------------------------------------------------------------- /examples/vanilla/src/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/vanilla/src/images/image-2.jpg -------------------------------------------------------------------------------- /examples/vanilla/src/index.js: -------------------------------------------------------------------------------- 1 | import mediumZoom from 'medium-zoom' 2 | 3 | mediumZoom('.container img') 4 | -------------------------------------------------------------------------------- /examples/vanilla/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | -------------------------------------------------------------------------------- /examples/vanilla/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | -------------------------------------------------------------------------------- /examples/vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/vue/README.md: -------------------------------------------------------------------------------- 1 | # Medium Zoom Vue Example 2 | 3 | This example creates an `` component that attaches the zoom to the image. 4 | 5 | [![Edit Vue Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/francoischalifour/medium-zoom/tree/master/examples/vue?file=/src/App.vue) 6 | 7 | ## Usage 8 | 9 | - Install dependencies: `yarn` 10 | - Run: `yarn dev` 11 | -------------------------------------------------------------------------------- /examples/vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | Medium Zoom | Vue Demo 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@medium-zoom/vue-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vue-tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "medium-zoom": "1.0.8", 13 | "vue": "3.2.47" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "4.1.0", 17 | "typescript": "4.9.3", 18 | "vite": "4.2.0", 19 | "vue-tsc": "1.2.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/vue/public/favicon.ico -------------------------------------------------------------------------------- /examples/vue/public/images/image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/vue/public/images/image-1.jpg -------------------------------------------------------------------------------- /examples/vue/public/images/image-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/vue/public/images/image-2.jpg -------------------------------------------------------------------------------- /examples/vue/public/images/image-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francoischalifour/medium-zoom/35b519fbdef97df69cc1d7daf46988effef0860b/examples/vue/public/images/image-3.jpg -------------------------------------------------------------------------------- /examples/vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 33 | -------------------------------------------------------------------------------- /examples/vue/src/components/ImageZoom.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 41 | -------------------------------------------------------------------------------- /examples/vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | 3 | import App from './App.vue' 4 | 5 | import './reset.css' 6 | import './style.css' 7 | 8 | createApp(App).mount('#app') 9 | -------------------------------------------------------------------------------- /examples/vue/src/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, 7 | body, 8 | div, 9 | span, 10 | applet, 11 | object, 12 | iframe, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6, 19 | p, 20 | blockquote, 21 | pre, 22 | a, 23 | abbr, 24 | acronym, 25 | address, 26 | big, 27 | cite, 28 | code, 29 | del, 30 | dfn, 31 | em, 32 | img, 33 | ins, 34 | kbd, 35 | q, 36 | s, 37 | samp, 38 | small, 39 | strike, 40 | strong, 41 | sub, 42 | sup, 43 | tt, 44 | var, 45 | b, 46 | u, 47 | i, 48 | center, 49 | dl, 50 | dt, 51 | dd, 52 | ol, 53 | ul, 54 | li, 55 | fieldset, 56 | form, 57 | label, 58 | legend, 59 | table, 60 | caption, 61 | tbody, 62 | tfoot, 63 | thead, 64 | tr, 65 | th, 66 | td, 67 | article, 68 | aside, 69 | canvas, 70 | details, 71 | embed, 72 | figure, 73 | figcaption, 74 | footer, 75 | header, 76 | hgroup, 77 | menu, 78 | nav, 79 | output, 80 | ruby, 81 | section, 82 | summary, 83 | time, 84 | mark, 85 | audio, 86 | video { 87 | margin: 0; 88 | padding: 0; 89 | border: 0; 90 | font-size: 100%; 91 | font: inherit; 92 | vertical-align: baseline; 93 | } 94 | /* HTML5 display-role reset for older browsers */ 95 | article, 96 | aside, 97 | details, 98 | figcaption, 99 | figure, 100 | footer, 101 | header, 102 | hgroup, 103 | menu, 104 | nav, 105 | section { 106 | display: block; 107 | } 108 | body { 109 | line-height: 1; 110 | } 111 | ol, 112 | ul { 113 | list-style: none; 114 | } 115 | blockquote, 116 | q { 117 | quotes: none; 118 | } 119 | blockquote:before, 120 | blockquote:after, 121 | q:before, 122 | q:after { 123 | content: ''; 124 | content: none; 125 | } 126 | table { 127 | border-collapse: collapse; 128 | border-spacing: 0; 129 | } 130 | -------------------------------------------------------------------------------- /examples/vue/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: 'AtlasGrotesk-dmc', -apple-system, BlinkMacSystemFont, 'Segoe UI', 7 | Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 8 | font-size: 20px; 9 | color: #212121; 10 | background-color: #fff; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | h1 { 17 | font-size: 2em; 18 | margin-bottom: 2em; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | margin: 2em 0; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 768px; 34 | margin: 48px auto; 35 | padding: 16px; 36 | } 37 | -------------------------------------------------------------------------------- /examples/vue/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true 15 | }, 16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /examples/vue/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | }) 8 | -------------------------------------------------------------------------------- /husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'pre-commit': 'pretty-quick --staged', 4 | }, 5 | } 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rootDir: process.cwd(), 3 | testRegex: 'src/(__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', 4 | collectCoverageFrom: ['src/**/*.js'], 5 | globals: { 6 | __TEST__: true, 7 | }, 8 | timers: 'fake', 9 | moduleNameMapper: { 10 | '\\.css$': '/src/__mocks__/styleMock.js', 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command="yarn run build:website" 3 | publish="website/dist" 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "medium-zoom", 3 | "version": "1.1.0", 4 | "description": "A JavaScript library for zooming images like Medium", 5 | "license": "MIT", 6 | "repository": "francoischalifour/medium-zoom", 7 | "author": { 8 | "name": "Francois Chalifour", 9 | "email": "francois.chalifour@gmail.com", 10 | "url": "https://francoischalifour.com" 11 | }, 12 | "main": "dist/medium-zoom.min.js", 13 | "module": "dist/medium-zoom.esm.js", 14 | "types": "dist/medium-zoom.d.ts", 15 | "sideEffects": false, 16 | "scripts": { 17 | "start": "yarn run dev", 18 | "dev": "rollup --config --watch", 19 | "prebuild": "yarn run clean", 20 | "build": "rollup --config", 21 | "postbuild": "cp ./src/medium-zoom.d.ts ./dist && cp ./src/medium-zoom.d.ts ./dist/pure/index.d.ts", 22 | "prepublishOnly": "npm run build", 23 | "lint": "eslint .", 24 | "format": "prettier --write *.{js,json,css,md} && yarn run lint --fix", 25 | "test": "jest", 26 | "test:cypress:run": "cypress run", 27 | "test:cypress:open": "cypress open", 28 | "test:cypress:update": "cypress run --env updateSnapshots=true", 29 | "test:cypress": "npm-run-all --parallel --race storybook test:cypress:run", 30 | "test:cypress:record": "npm-run-all --parallel --race storybook 'test:cypress:run -- --record --key {1}' --", 31 | "test:size": "bundlesize", 32 | "clean": "rimraf ./dist", 33 | "build:storybook": "build-storybook -o ./website/dist/storybook -c ./stories/config -s ./dist,./stories/images", 34 | "storybook": "start-storybook -p 9001 -c ./stories/config -s ./dist,./stories/images", 35 | "build:website": "(cd website && yarn && yarn run build) && yarn run build && yarn run build:storybook", 36 | "changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s", 37 | "release": "release-it", 38 | "release:next": "release-it --preRelease=next", 39 | "release:examples": "./scripts/release-examples.sh" 40 | }, 41 | "files": [ 42 | "dist" 43 | ], 44 | "keywords": [ 45 | "medium", 46 | "image", 47 | "zoom", 48 | "picture", 49 | "lightbox", 50 | "click", 51 | "scroll", 52 | "pure", 53 | "plain", 54 | "vanilla", 55 | "javascript", 56 | "ux", 57 | "performance", 58 | "event", 59 | "medium-zoom", 60 | "zoomable" 61 | ], 62 | "devDependencies": { 63 | "@storybook/addon-notes": "4.0.0-alpha.14", 64 | "@storybook/addon-options": "4.0.0-alpha.14", 65 | "@storybook/addon-storysource": "4.0.0-alpha.14", 66 | "@storybook/html": "4.0.0-alpha.14", 67 | "babel-core": "6.26.3", 68 | "babel-eslint": "10.0.3", 69 | "babel-plugin-external-helpers": "6.22.0", 70 | "babel-plugin-require-context-hook": "1.0.0", 71 | "babel-plugin-transform-object-rest-spread": "6.26.0", 72 | "babel-preset-env": "1.7.0", 73 | "bundlesize": "0.18.0", 74 | "conventional-changelog-cli": "2.0.28", 75 | "cssnano": "4.1.10", 76 | "cypress": "3.7.0", 77 | "cypress-image-snapshot": "3.1.1", 78 | "eslint": "5.12.1", 79 | "eslint-config-airbnb-base": "13.1.0", 80 | "eslint-config-prettier": "3.6.0", 81 | "eslint-plugin-cypress": "2.7.0", 82 | "eslint-plugin-import": "2.18.2", 83 | "husky": "3.1.0", 84 | "jest": "23.6.0", 85 | "npm-run-all": "4.1.5", 86 | "prettier": "1.19.1", 87 | "pretty-quick": "1.10.0", 88 | "release-it": "10.4.5", 89 | "rimraf": "3.0.0", 90 | "rollup": "1.27.8", 91 | "rollup-plugin-babel": "3.0.7", 92 | "rollup-plugin-filesize": "6.2.1", 93 | "rollup-plugin-license": "0.13.0", 94 | "rollup-plugin-postcss": "2.0.3", 95 | "rollup-plugin-replace": "2.2.0", 96 | "rollup-plugin-terser": "5.1.2", 97 | "rollup-plugin-uglify": "4.0.0", 98 | "rollup-watch": "4.3.1" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel' 2 | import { terser } from 'rollup-plugin-terser' 3 | import license from 'rollup-plugin-license' 4 | import replace from 'rollup-plugin-replace' 5 | import { uglify } from 'rollup-plugin-uglify' 6 | import postcss from 'rollup-plugin-postcss' 7 | import filesize from 'rollup-plugin-filesize' 8 | import cssnano from 'cssnano' 9 | 10 | import pkg from './package.json' 11 | 12 | const banner = `/*! ${pkg.name} ${pkg.version} | ${pkg.license} License | https://github.com/${pkg.repository} */` 13 | 14 | const sharedPlugins = [ 15 | postcss({ 16 | extensions: ['.css'], 17 | plugins: [cssnano()], 18 | }), 19 | replace({ 20 | __TEST__: process.env.NODE_ENV === 'test' ? 'true' : 'false', 21 | }), 22 | babel({ 23 | exclude: 'node_modules/**', 24 | plugins: ['external-helpers', 'transform-object-rest-spread'], 25 | }), 26 | filesize({ 27 | showMinifiedSize: false, 28 | showGzippedSize: true, 29 | }), 30 | ] 31 | const prettifyPlugin = uglify({ 32 | compress: false, 33 | mangle: false, 34 | output: { 35 | beautify: true, 36 | indent_level: 2, 37 | preamble: banner, 38 | }, 39 | }) 40 | 41 | export default [ 42 | { 43 | input: 'src/index.js', 44 | output: { 45 | file: pkg.module, 46 | format: 'es', 47 | }, 48 | plugins: [...sharedPlugins, license({ banner })], 49 | }, 50 | { 51 | input: 'src/index.js', 52 | output: { 53 | name: 'mediumZoom', 54 | file: pkg.main.replace('.min', ''), 55 | format: 'umd', 56 | }, 57 | plugins: [...sharedPlugins, prettifyPlugin], 58 | }, 59 | { 60 | input: 'src/index.js', 61 | output: { 62 | name: 'mediumZoom', 63 | file: pkg.main, 64 | format: 'umd', 65 | }, 66 | plugins: [...sharedPlugins, terser(), license({ banner })], 67 | }, 68 | // pure 69 | { 70 | input: 'src/medium-zoom.js', 71 | output: { 72 | file: 'dist/pure/index.js', 73 | format: 'es', 74 | }, 75 | plugins: [...sharedPlugins, license({ banner })], 76 | }, 77 | { 78 | input: 'src/medium-zoom.js', 79 | output: { 80 | name: 'mediumZoom', 81 | file: 'dist/pure/medium-zoom.umd.js', 82 | format: 'umd', 83 | }, 84 | plugins: [...sharedPlugins, prettifyPlugin], 85 | }, 86 | { 87 | input: 'src/medium-zoom.js', 88 | output: { 89 | name: 'mediumZoom', 90 | file: 'dist/pure/medium-zoom.min.umd.js', 91 | format: 'umd', 92 | }, 93 | plugins: [...sharedPlugins, terser(), license({ banner })], 94 | }, 95 | // style 96 | { 97 | input: 'src/medium-zoom.css', 98 | output: { 99 | file: 'dist/style.css', 100 | format: 'es', 101 | }, 102 | plugins: [ 103 | postcss({ 104 | extract: true, 105 | minimize: true, 106 | }), 107 | license({ banner }), 108 | ], 109 | }, 110 | ] 111 | -------------------------------------------------------------------------------- /scripts/release-examples.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | printf "\nUpdating 'medium-zoom' dependency in examples...\n" 6 | 7 | node ./scripts/update-examples 8 | 9 | git add examples 10 | git commit -m "chore(examples): update medium-zoom dependency" 11 | git push origin master 12 | -------------------------------------------------------------------------------- /scripts/update-examples.js: -------------------------------------------------------------------------------- 1 | const { readdirSync, statSync } = require('fs') 2 | const { join } = require('path') 3 | const { execSync } = require('child_process') 4 | const { version } = require('../package.json') 5 | 6 | const examples = readdirSync('examples') 7 | .map(file => join('examples', file)) 8 | .filter(file => statSync(file).isDirectory()) 9 | 10 | examples.forEach(path => { 11 | execSync(`cd ${path} && yarn upgrade medium-zoom@${version}`, { 12 | stdio: 'inherit', 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /src/__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/medium-zoom.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`attach() attach("") throws error 1`] = ` 4 | "The provided selector is invalid. 5 | Expects a CSS selector, a Node element, a NodeList or an array. 6 | See: https://github.com/francoischalifour/medium-zoom" 7 | `; 8 | 9 | exports[`browser events closes on escape 1`] = ` 10 | 13 | 16 | 17 | `; 18 | 19 | exports[`browser events closes zoom on click on the overlay 1`] = ` 20 | 23 | 26 | 27 | `; 28 | 29 | exports[`browser events does not close on other keys 1`] = ` 30 | 33 | 36 |
40 | 44 | 45 | `; 46 | 47 | exports[`browser events opens zoom on click on the image 1`] = ` 48 | 51 | 54 |
58 | 62 | 63 | `; 64 | 65 | exports[`close() close() twice does not throw and renders correctly 1`] = ` 66 | 69 | 72 | 73 | `; 74 | 75 | exports[`close() close() with \`data-zoom-src\` renders correctly 1`] = ` 76 | 79 | 83 | 84 | `; 85 | 86 | exports[`close() mediumZoom({ template }).close() renders correctly 1`] = ` 87 | 90 |