Repository: fuxingloh/vue-masonry-wall Branch: master Commit: a02d49c78cfd Files: 21 Total size: 24.4 KB Directory structure: gitextract_pvs8vdpn/ ├── .browserslistrc ├── .github/ │ ├── PULL_REQUEST_TEMPLATE.md │ ├── auto_assign.yml │ ├── pr-labeler.yml │ ├── release-drafter.yml │ └── workflows/ │ ├── ci.yml │ ├── publish.yml │ ├── release-drafter.yml │ └── triage.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── babel.config.js ├── build/ │ └── rollup.config.js ├── examples/ │ ├── index.vue │ ├── package.json │ └── serve.js ├── package.json └── src/ ├── entry.js └── vue-masonry-wall.vue ================================================ FILE CONTENTS ================================================ ================================================ FILE: .browserslistrc ================================================ current node last 2 versions and > 2% ie > 10 ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ================================================ FILE: .github/auto_assign.yml ================================================ addAssignees: author addReviewers: true reviewers: - fuxingloh numberOfReviewers: 0 ================================================ FILE: .github/pr-labeler.yml ================================================ feature: [ 'feature/*', 'feat/*', 'enhancement/*' ] fix: [ 'fix/*', 'bug/*', 'bugfix/*' ] chore: [ 'chore/*', 'docs/*' , 'doc/*', 'ci/*' ] ================================================ FILE: .github/release-drafter.yml ================================================ name-template: 'v$RESOLVED_VERSION 🌈' tag-template: 'v$RESOLVED_VERSION' categories: - title: '🚀 Features' labels: - 'feature' - 'enhancement' - title: '🐛 Bug Fixes' labels: - 'fix' - 'bugfix' - 'bug' - title: '🧰 Maintenance' labels: - 'chore' - 'docs' change-template: '- $TITLE @$AUTHOR (#$NUMBER)' change-title-escapes: '\<*_&' version-resolver: minor: labels: - 'feature' - 'enhancement' patch: labels: - 'patch' - 'bug' - 'bugfix' - 'fix' default: patch template: | ## Changes $CHANGES ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: pull_request: branches: [ master ] jobs: yarn: name: Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: '14' registry-url: 'https://registry.npmjs.org' - run: yarn install --frozen-lockfile - run: yarn build ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish on: release: types: [ published ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: '14' registry-url: 'https://registry.npmjs.org' - run: yarn install --frozen-lockfile - name: Check package version uses: technote-space/package-version-check-action@v1 with: COMMIT_MESSAGE: 'release: update package version' - run: yarn build - run: yarn publish --non-interactive env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .github/workflows/release-drafter.yml ================================================ name: Release Drafter on: push: branches: [ master ] jobs: draft-release: runs-on: ubuntu-latest steps: - uses: release-drafter/release-drafter@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/triage.yml ================================================ name: "Triage" on: pull_request: types: [ opened, reopened, ready_for_review ] branches: [ master ] jobs: triage: name: Triage runs-on: ubuntu-latest steps: - uses: TimonVS/pr-labeler-action@v3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: kentaro-m/auto-assign-action@v1.1.2 ================================================ FILE: .gitignore ================================================ .DS_Store node_modules /dist # local env files .env.local .env.*.local # Log files npm-debug.log* yarn-debug.log* yarn-error.log* # Editor directories and files .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.sw? ================================================ FILE: .npmignore ================================================ * !dist/* !src/vue-masonry-wall.vue ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2020 Fuxing Loh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # vue-masonry-wall A pure vue responsive masonry implementation without direct dom manipulation, ssr friendly with lazy appending. I created this because other libraries has no SSR support, and I needed a pure vue implementation. * [Live Demo: Image](https://nuxt-app.now.sh/vue-masonry-wall-image) and the [Source](https://github.com/fuxingloh/nuxt-app/blob/0725466dcf2d3d5338573ca7612f38ecd8fa2fa0/components/examples/ExampleMasonryImage.vue) * [Live Demo: Text](https://nuxt-app.now.sh/vue-masonry-wall) and the [Source](https://github.com/fuxingloh/nuxt-app/blob/0725466dcf2d3d5338573ca7612f38ecd8fa2fa0/components/examples/ExampleMasonry.vue) [![vue-masonry-wall screenshot](example.png)](https://nuxt-app.now.sh/vue-masonry-wall-image) ## Installation ```shell script npm i vue-masonry-wall # or yarn yarn add vue-masonry-wall ``` ## Features * No Direct DOM Manipulation * SSR friendly, able to load and re hydrate later * 1 dependency only, no legacy dependencies * Auto lazy appending, scroll to auto load more * Auto item placement, will find best column * Responsive design ## Usage ```vue ``` ```js const items = [] const options = { width: 300, padding: { default: 12, 1: 6, 2: 8 } } const append = () => { // API call and add items this.items.push(...[]) } ``` ### Basic ```vue ``` ### Nuxt SSR Add `:ssr="{columns: 2}"` to masonry so that during SSR, it will be load in 2 columns. SSR has no clue what is the size of your height of your element or width of the browser. You can however guess based on user-agent: https://github.com/nuxt-community/device-module This param allow you to preload a config for SSR rendering, it will distribute your items into all columns evenly. ```vue ``` ## Dependencies - [vue-observe-visibility](https://github.com/Akryum/vue-observe-visibility) for [IntersectionObserver](https://github.com/w3c/IntersectionObserver/tree/master/polyfill) ## Contributing For any question or feature request please feel free to create an [issue](https://github.com/fuxingloh/vue-masonry-wall/issues/new) or [pull request](https://github.com/fuxingloh/vue-masonry-wall/pulls). ## TODO > These were features from my original project that I removed for brevity of this package. * [ ] [nuxt-community/device-module](https://github.com/nuxt-community/device-module) to detect the browser for better SSR support. * [ ] [vue-scrollto](https://www.npmjs.com/package/vue-scrollto) to scroll to an item in masonry. ## [Vue Horizontal](https://github.com/fuxingloh/vue-horizontal) I also maintain another project called [Vue Horizontal](https://github.com/fuxingloh/vue-horizontal). At its core, Vue Horizontal is an ultra simple pure vue horizontal layout for modern responsive web with zero dependencies. Vue Horizontal is also an ultra complex code snippet dossier with over 100 SPA/SSR/SSG friendly recipes for your design needs. Do check it out, might be useful for you! ================================================ FILE: babel.config.js ================================================ const devPresets = ['@vue/babel-preset-app']; const buildPresets = ['@babel/preset-env']; module.exports = { presets: (process.env.NODE_ENV === 'development' ? devPresets : buildPresets), }; ================================================ FILE: build/rollup.config.js ================================================ // rollup.config.js import fs from 'fs'; import path from 'path'; import vue from 'rollup-plugin-vue'; import alias from '@rollup/plugin-alias'; import commonjs from '@rollup/plugin-commonjs'; import replace from '@rollup/plugin-replace'; import babel from 'rollup-plugin-babel'; import { terser } from 'rollup-plugin-terser'; import minimist from 'minimist'; // Get browserslist config and remove ie from es build targets const esbrowserslist = fs.readFileSync('./.browserslistrc') .toString() .split('\n') .filter((entry) => entry && entry.substring(0, 2) !== 'ie'); const argv = minimist(process.argv.slice(2)); const projectRoot = path.resolve(__dirname, '..'); const baseConfig = { input: 'src/entry.js', plugins: { preVue: [ alias({ resolve: ['.js', '.jsx', '.ts', '.tsx', '.vue'], entries: { '@': path.resolve(projectRoot, 'src'), }, }), ], replace: { 'process.env.NODE_ENV': JSON.stringify('production'), 'process.env.ES_BUILD': JSON.stringify('false'), }, vue: { css: true, template: { isProduction: true, }, }, babel: { exclude: 'node_modules/**', extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'], }, }, }; // ESM/UMD/IIFE shared settings: externals // Refer to https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency const external = [ // list external dependencies, exactly the way it is written in the import statement. // eg. 'jquery' 'vue', ]; // UMD/IIFE shared settings: output.globals // Refer to https://rollupjs.org/guide/en#output-globals for details const globals = { // Provide global variable names to replace your external imports // eg. jquery: '$' vue: 'Vue', }; // Customize configs for individual targets const buildFormats = []; if (!argv.format || argv.format === 'es') { const esConfig = { ...baseConfig, external, output: { file: 'dist/vue-masonry-wall.esm.js', format: 'esm', exports: 'named', }, plugins: [ replace({ ...baseConfig.plugins.replace, 'process.env.ES_BUILD': JSON.stringify('true'), }), ...baseConfig.plugins.preVue, vue(baseConfig.plugins.vue), babel({ ...baseConfig.plugins.babel, presets: [ [ '@babel/preset-env', { targets: esbrowserslist, }, ], ], }), commonjs(), ], }; buildFormats.push(esConfig); } if (!argv.format || argv.format === 'cjs') { const umdConfig = { ...baseConfig, external, output: { compact: true, file: 'dist/vue-masonry-wall.ssr.js', format: 'cjs', name: 'VueMasonryWall', exports: 'named', globals, }, plugins: [ replace(baseConfig.plugins.replace), ...baseConfig.plugins.preVue, vue({ ...baseConfig.plugins.vue, template: { ...baseConfig.plugins.vue.template, optimizeSSR: true, }, }), babel(baseConfig.plugins.babel), commonjs(), ], }; buildFormats.push(umdConfig); } if (!argv.format || argv.format === 'iife') { const unpkgConfig = { ...baseConfig, external, output: { compact: true, file: 'dist/vue-masonry-wall.min.js', format: 'iife', name: 'VueMasonryWall', exports: 'named', globals, }, plugins: [ replace(baseConfig.plugins.replace), ...baseConfig.plugins.preVue, vue(baseConfig.plugins.vue), babel(baseConfig.plugins.babel), commonjs(), terser({ output: { ecma: 5, }, }), ], }; buildFormats.push(unpkgConfig); } // Export config export default buildFormats; ================================================ FILE: examples/index.vue ================================================ ================================================ FILE: examples/package.json ================================================ { "name": "abc", "version": "1.0.0", "description": "", "main": "dist/abc.ssr.js", "browser": "dist/abc.esm.js", "module": "dist/abc.esm.js", "unpkg": "dist/abc.min.js", "files": [ "dist/*", "src/**/*.vue" ], "scripts": { "serve": "vue-cli-service serve dev/serve.js", "build": "cross-env NODE_ENV=production rollup --config build/rollup.config.js", "build:ssr": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format cjs", "build:es": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format es", "build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife" }, "dependencies": { }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.5", "@rollup/plugin-alias": "^2.2.0", "@rollup/plugin-commonjs": "^11.1.0", "@rollup/plugin-replace": "^2.3.2", "@vue/cli-plugin-babel": "^4.3.1", "@vue/cli-service": "^4.3.1", "cross-env": "^7.0.2", "minimist": "^1.2.5", "rollup": "^2.7.3", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-terser": "^5.3.0", "rollup-plugin-vue": "^5.1.6", "vue": "^2.6.11", "vue-template-compiler": "^2.6.11" }, "peerDependencies": { "vue": "^2.6.11" }, "engines": { "node": ">=10" } } ================================================ FILE: examples/serve.js ================================================ import Vue from "vue"; import Index from "./index.vue"; Vue.config.productionTip = false; new Vue({ render: (h) => h(Index), }).$mount("#app"); ================================================ FILE: package.json ================================================ { "name": "vue-masonry-wall", "version": "0.2.5", "description": "100% vue masonry without direct dom manipulation, ssr friendly.", "author": "Fuxing Loh", "repository": { "type": "git", "url": "https://github.com/fuxingloh/vue-masonry-wall.git" }, "bugs": "https://github.com/fuxingloh/vue-masonry-wall/issues", "keywords": [ "vue", "vuejs", "masonry", "pinterest" ], "license": "MIT", "private": false, "main": "dist/vue-masonry-wall.ssr.js", "browser": "dist/vue-masonry-wall.esm.js", "module": "dist/vue-masonry-wall.esm.js", "unpkg": "dist/vue-masonry-wall.min.js", "files": [ "dist/*", "src/**/*.vue" ], "scripts": { "build": "cross-env NODE_ENV=production rollup --config build/rollup.config.js", "build:ssr": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format cjs", "build:es": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format es", "build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife", "examples:serve": "vue-cli-service serve examples/serve.js", "examples:build": "vue-cli-service build examples/serve.js", "prepublishOnly": "yarn build" }, "dependencies": { "vue-observe-visibility": "^0.4.6" }, "peerDependencies": { "lodash": "^4.17.15", "vue": "^2.6.10" }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.5", "@rollup/plugin-alias": "^2.2.0", "@rollup/plugin-commonjs": "^11.1.0", "@rollup/plugin-replace": "^2.3.2", "@vue/cli-plugin-babel": "^4.3.1", "@vue/cli-service": "^4.3.1", "cross-env": "^7.0.2", "minimist": "^1.2.5", "rollup": "^2.7.3", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-terser": "^5.3.0", "rollup-plugin-vue": "^5.1.6", "vue": "^2.6.11", "vue-template-compiler": "^2.6.11" }, "engines": { "node": ">=10" } } ================================================ FILE: src/entry.js ================================================ // Import vue component import component from '@/vue-masonry-wall.vue'; // install function executed by Vue.use() const install = function installVueMasonryWall(Vue) { if (install.installed) return; install.installed = true; Vue.component('VueMasonryWall', component); }; // Create module definition for Vue.use() const plugin = { install, }; // To auto-install on non-es builds, when vue is found // eslint-disable-next-line no-redeclare /* global window, global */ if ("false" === process.env.ES_BUILD) { let GlobalVue = null; if (typeof window !== "undefined") { GlobalVue = window.Vue; } else if (typeof global !== "undefined") { GlobalVue = global.Vue; } if (GlobalVue) { GlobalVue.use(plugin); } } // Inject install function into component - allows component // to be registered via Vue.use() as well as Vue.component() component.install = install; // Export component by default export default component; // It's possible to expose named exports when writing components that can // also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo'; // export const RollupDemoDirective = component; ================================================ FILE: src/vue-masonry-wall.vue ================================================