├── .gitignore
├── .idea
├── .gitignore
├── modules.xml
├── vcs.xml
└── vue-image-browser.iml
├── LICENSE
├── README.md
├── build
└── rollup.config.js
├── dist
├── vue-image-browser.esm.js
├── vue-image-browser.min.js
└── vue-image-browser.umd.js
├── images
├── example-image-1.png
└── example-image-2.png
├── package-lock.json
├── package.json
├── postcss.config.js
└── src
├── vue-image-browser.vue
└── wrapper.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vue-image-browser.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Akash Mitra
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # An Image Browser Component Built with VueJs
2 |
3 | 
4 |
5 | A JavaScript Image Browser written in [VueJS](https://vuejs.org/) and styled with [TailwindCSS](https://tailwindcss.com/docs/installation/).
6 |
7 | ## Features
8 | - Image Upload
9 | - Local or Remote Image Search
10 | - Show larger image (Photo Pane view)
11 | - Delete Image
12 | - Show arbitrary information about the image
13 | - Generate Or Capture Image Caption
14 | - Lazy Load Images on scroll
15 |
16 | ## Usage
17 |
18 | Install as npm package
19 |
20 | ```
21 | npm install @akashmitra/vue-image-browser
22 | ```
23 |
24 | `import` this as a component. You may also use this inside another Vue component.
25 |
26 | ```javascript
27 |
28 |
29 |
35 |
36 |
37 |
38 |
59 |
60 | ```
61 |
62 | ## Image Object
63 |
64 | The `images` attribute in `VueImageBrowser` accepts an array containing one or more "image objects" with following mandatory fields - `id`, `name` and `url`. The image object can contain other fields as well. You can specify the additional fields in `image-properties` as key-value pairs, where the `key` is the attribute name and the `value` is the attribute title.
65 |
66 |
67 |
68 | ## Image Upload Response
69 |
70 | 
71 |
72 | It is possible to upload an image to a specified API endpoint (`save-url`) via POST.
73 | When an image is uploaded successfully, a 200 HTTP Status code response must be sent back from the server with a response JSON. After the image is uploaded successfully, a `saved` event will be generated and the response JSON will be passed with the event. Please see the example section below.
74 |
75 |
76 | ## Options
77 |
78 | | Parameter | Type | Default Value | Description |
79 | |------------------------|---------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
80 | | `images` | Array | `[]` | An array containing the image objects. Each image object must contain `id`, `name` and `url` of the image |
81 | | `image-properties` | Object | | An object containing all the fields in image object along with the field titles |
82 | | `allow-upload` | Boolean | false | (OPTIONAL) Whether or not to provide provision for image upload. If this is `true`, a `save-url` must be provided. |
83 | | `save-url` | String | /api/photos | Specify the URL endpoint for posting the uploaded images. |
84 | | `save-request-headers` | Object | `{}` | (OPTIONAL) If you need to pass any additional HTTP headers, you may do so by providing the header names and values in this object |
85 | | `allow-photo-pane` | Boolean | false | (OPTIONAL) When this attribute is true, clicking on an image in the gallery will show a larger version of the image in a Photo pane, along with any additional image information. |
86 | | `allow-delete` | Boolean | false | (OPTIONAL) Whether or not to provide a provision for deleting an image in Photo Pane view. If this is true, delete button will be shown and a `deleted` event will be generated |
87 | | `allow-choose` | Boolean | false | (OPTIONAL) Whether or not to provide a provision for chosing the image inside Photo Pane view. If this is true, a "Choose" button will be displayed and a `chosen` event will be generated |
88 | | `allow-copy` | Boolean | true | (OPTIONAL) Whether or not to provide a provision for copying the image URL in the Photo Pane View. If this is true, a `Copy Link` button will be shown and image `url` will be copied to clipboard |
89 | | `captionable` | Boolean | false | (OPTIONAL) Whether or not to provide a provision for specifying the image caption after selecting an image. If this is true, a prompt will be shown for image caption when users select an image |
90 | | `enable-lazy-load` | Boolean | true | (OPTIONAL) Uses IntersectionObserver to ensure the images are only loaded to browser when the image comes near the browser viewport |
91 | | `search-delay` | Number | 500 | (OPTIONAL) A delay in miliseconds after which the search event is fired. |
92 | | `max-images-per-row` | Number | 5 | (OPTIONAL) Maximum number of images to be displayed in each row in image gallery. Must be a value from 1 to 6. Actual number of displayed images will vary based on screen-size |
93 | | `post-key` | String | image | (OPTIONAL) The name of the post request parameter to be used while posting file to the server. |
94 |
95 |
96 | ## Events
97 |
98 | Following events are generated when performing various interactions with the images.
99 |
100 | | Event | Parameter Type | Parameter Value | Description |
101 | |---------------|-----------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
102 | | `searched` | String | seach phrase | This event is generated when users search in the search box. The search phrase is passed to the event handler, which can be used to filter the images array |
103 | | `selected` | Object | image | This event is generated when users click on an image in the Gallery. The image is passed to the event handler. |
104 | | `chosen` | Object | image | This event is generated when users select an image. The image is passed to the event handler. |
105 | | `saved` | Object | image | This event is generated when users successfully upload an image. The image is passed to the event handler. |
106 | | `deleted` | Object | image | This event is generated when users delete an image. The image is passed to the event handler. |
107 |
108 |
109 | ## Example
110 |
111 | ```javascript
112 |
113 |
114 |
115 |
131 |
132 |
133 |
134 |
135 |
136 |
197 |
198 |
199 | ```
200 |
201 | ## Dependency
202 |
203 | [TailwindCSS](https://tailwindcss.com/docs/installation/) must be present for the styling.
--------------------------------------------------------------------------------
/build/rollup.config.js:
--------------------------------------------------------------------------------
1 | import commonjs from '@rollup/plugin-commonjs'; // Convert CommonJS modules to ES6
2 | import vue from 'rollup-plugin-vue'; // Handle .vue SFC files
3 | import buble from '@rollup/plugin-buble'; // Transpile/polyfill with reasonable browser support
4 |
5 | export default {
6 | input: 'src/wrapper.js', // Path relative to package.json
7 | output: {
8 | name: 'VueImageBrowser',
9 | exports: 'named',
10 | },
11 | external: [],
12 | plugins: [
13 | commonjs(),
14 | vue({
15 | css: true, // Dynamically inject css as a \n"]
1166 | },
1167 | media: undefined
1168 | });
1169 |
1170 | };
1171 | /* scoped */
1172 | var __vue_scope_id__ = undefined;
1173 | /* module identifier */
1174 | var __vue_module_identifier__ = undefined;
1175 | /* functional template */
1176 | var __vue_is_functional_template__ = false;
1177 | /* style inject SSR */
1178 |
1179 | /* style inject shadow dom */
1180 |
1181 |
1182 |
1183 | var __vue_component__ = /*#__PURE__*/normalizeComponent(
1184 | { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
1185 | __vue_inject_styles__,
1186 | __vue_script__,
1187 | __vue_scope_id__,
1188 | __vue_is_functional_template__,
1189 | __vue_module_identifier__,
1190 | false,
1191 | createInjector,
1192 | undefined,
1193 | undefined
1194 | );
1195 |
1196 | // Import vue component
1197 |
1198 | // Declare install function executed by Vue.use()
1199 | function install(Vue) {
1200 | if (install.installed) { return; }
1201 | install.installed = true;
1202 | Vue.component('VueImageBrowser', __vue_component__);
1203 | }
1204 |
1205 | // Create module definition for Vue.use()
1206 | var plugin = {
1207 | install: install,
1208 | };
1209 |
1210 | // Auto-install when vue is found (eg. in browser via \n\n\n"]}, media: undefined });
1159 |
1160 | };
1161 | /* scoped */
1162 | var __vue_scope_id__ = undefined;
1163 | /* module identifier */
1164 | var __vue_module_identifier__ = undefined;
1165 | /* functional template */
1166 | var __vue_is_functional_template__ = false;
1167 | /* style inject SSR */
1168 |
1169 | /* style inject shadow dom */
1170 |
1171 |
1172 |
1173 | var __vue_component__ = /*#__PURE__*/normalizeComponent(
1174 | { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
1175 | __vue_inject_styles__,
1176 | __vue_script__,
1177 | __vue_scope_id__,
1178 | __vue_is_functional_template__,
1179 | __vue_module_identifier__,
1180 | false,
1181 | createInjector,
1182 | undefined,
1183 | undefined
1184 | );
1185 |
1186 | // Import vue component
1187 |
1188 | // Declare install function executed by Vue.use()
1189 | function install(Vue) {
1190 | if (install.installed) { return; }
1191 | install.installed = true;
1192 | Vue.component('VueImageBrowser', __vue_component__);
1193 | }
1194 |
1195 | // Create module definition for Vue.use()
1196 | var plugin = {
1197 | install: install,
1198 | };
1199 |
1200 | // Auto-install when vue is found (eg. in browser via \n\n\n"]
1172 | },
1173 | media: undefined
1174 | });
1175 |
1176 | };
1177 | /* scoped */
1178 | var __vue_scope_id__ = undefined;
1179 | /* module identifier */
1180 | var __vue_module_identifier__ = undefined;
1181 | /* functional template */
1182 | var __vue_is_functional_template__ = false;
1183 | /* style inject SSR */
1184 |
1185 | /* style inject shadow dom */
1186 |
1187 |
1188 |
1189 | var __vue_component__ = /*#__PURE__*/normalizeComponent(
1190 | { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
1191 | __vue_inject_styles__,
1192 | __vue_script__,
1193 | __vue_scope_id__,
1194 | __vue_is_functional_template__,
1195 | __vue_module_identifier__,
1196 | false,
1197 | createInjector,
1198 | undefined,
1199 | undefined
1200 | );
1201 |
1202 | // Import vue component
1203 |
1204 | // Declare install function executed by Vue.use()
1205 | function install(Vue) {
1206 | if (install.installed) { return; }
1207 | install.installed = true;
1208 | Vue.component('VueImageBrowser', __vue_component__);
1209 | }
1210 |
1211 | // Create module definition for Vue.use()
1212 | var plugin = {
1213 | install: install,
1214 | };
1215 |
1216 | // Auto-install when vue is found (eg. in browser via
516 |
517 |
549 |
--------------------------------------------------------------------------------
/src/wrapper.js:
--------------------------------------------------------------------------------
1 | // Import vue component
2 | import component from './vue-image-browser.vue';
3 |
4 | // Declare install function executed by Vue.use()
5 | export function install(Vue) {
6 | if (install.installed) return;
7 | install.installed = true;
8 | Vue.component('VueImageBrowser', component);
9 | }
10 |
11 | // Create module definition for Vue.use()
12 | const plugin = {
13 | install,
14 | };
15 |
16 | // Auto-install when vue is found (eg. in browser via