├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── commitlint.config.js ├── docs ├── README.md ├── _config.yml └── simple-vue-timeline.png ├── index.d.ts ├── jest.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── src ├── App.vue ├── assets │ ├── logo.png │ └── scss │ │ ├── simple-vue-timeline.scss │ │ └── vendor.scss ├── components │ ├── SimpleTimeline.vue │ ├── SimpleTimelineControl.vue │ ├── SimpleTimelineItem.vue │ ├── index.d.ts │ ├── index.js │ ├── simple-timeline-control.component.ts │ ├── simple-timeline-control.model.ts │ ├── simple-timeline-item.component.ts │ ├── simple-timeline-item.model.ts │ ├── simple-timeline-status.model.ts │ └── simple-timeline.component.ts ├── demo.ts ├── main.ts ├── plugins │ └── bootstrap-vue.js ├── shims-tsx.d.ts └── shims-vue.d.ts ├── tests └── unit │ ├── simple-timeline-item.spec.ts │ └── simple-timeline.spec.ts └── tsconfig.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | env: { 5 | node: true 6 | }, 7 | 8 | extends: ["plugin:vue/essential", "@vue/prettier", "@vue/typescript"], 9 | 10 | rules: { 11 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off", 12 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off" 13 | }, 14 | 15 | parserOptions: { 16 | parser: "@typescript-eslint/parser" 17 | }, 18 | 19 | overrides: [ 20 | { 21 | files: [ 22 | '**/__tests__/*.{j,t}s?(x)', 23 | '**/tests/unit/**/*.spec.{j,t}s?(x)' 24 | ], 25 | env: { 26 | jest: true 27 | } 28 | } 29 | ] 30 | }; 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /coverage 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | target 3 | package-lock.json 4 | .git 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | # Prettier configuration 2 | 3 | printWidth: 140 4 | singleQuote: true 5 | tabWidth: 2 6 | useTabs: false 7 | 8 | # js and ts rules: 9 | arrowParens: avoid 10 | 11 | # jsx and tsx rules: 12 | jsxBracketSameLine: false 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | - "11" 5 | cache: 6 | directories: 7 | - node_modules 8 | script: 9 | - npm run test:unit 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [2.0.9](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.8...v2.0.9) (2021-08-23) 6 | 7 | ### [2.0.8](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.7...v2.0.8) (2020-09-23) 8 | 9 | ### [2.0.7](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.6...v2.0.7) (2020-08-06) 10 | 11 | ### [2.0.6](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.5...v2.0.6) (2020-07-26) 12 | 13 | ### [2.0.5](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.4...v2.0.5) (2020-06-17) 14 | 15 | ### [2.0.4](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.3...v2.0.4) (2020-04-18) 16 | 17 | ### [2.0.3](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.2...v2.0.3) (2020-04-18) 18 | 19 | ### [2.0.2](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.1...v2.0.2) (2020-04-17) 20 | 21 | ### [2.0.1](https://github.com/scottie34/simple-vue-timeline/compare/v2.0.0...v2.0.1) (2020-04-17) 22 | 23 | ## [2.0.0](https://github.com/scottie34/simple-vue-timeline/compare/v1.12.0...v2.0.0) (2020-04-17) 24 | 25 | 26 | ### ⚠ BREAKING CHANGES 27 | 28 | * Usage declaration of bootstrap-vue and font-awesome is now the responsability of 29 | the project in which it is used. 30 | 31 | * use vue plugin, add test and reduce package size ([cdeb498](https://github.com/scottie34/simple-vue-timeline/commit/cdeb49821a0e214ec7563a7fb1dbfecd09ce6fa8)) 32 | 33 | ## 1.12.0 (2020-04-17) 34 | 35 | 36 | ### Features 37 | 38 | * 0.3.0 version ([6007c2b](https://github.com/scottie34/simple-vue-timeline/commit/6007c2b9e69bec6b1e4b8468595f5c6e1cf2cb60)) 39 | * 1.0.0 version ([d65d7d0](https://github.com/scottie34/simple-vue-timeline/commit/d65d7d08c3c3b0ed96ce0853c1c2bd0d149f0078)) 40 | * 1.1.0 version ([a6021d9](https://github.com/scottie34/simple-vue-timeline/commit/a6021d9aa5adeec57645dd90cf6945ad6a6b194a)) 41 | * add MIT licence ([0dc3166](https://github.com/scottie34/simple-vue-timeline/commit/0dc31663897d61862c1746fcf91600270e8acbb7)) 42 | * add travis ci configuration and change flex layout ([d2f00b6](https://github.com/scottie34/simple-vue-timeline/commit/d2f00b6c0b96f460fdec0b4e098a31a323004155)) 43 | * demo and doc ([e8993ee](https://github.com/scottie34/simple-vue-timeline/commit/e8993ee23fce03452f92c6352fe1c3b6c738baff)) 44 | * emit event from Timeline Control to App ([92b0c8a](https://github.com/scottie34/simple-vue-timeline/commit/92b0c8a89b25cf898cd65963d15ba3b02f5e467e)) 45 | * enhance package.json metadata ([4f0ccd4](https://github.com/scottie34/simple-vue-timeline/commit/4f0ccd4808906fdc56161c5c88b9112ca500ad73)) 46 | * initial commit ([194a799](https://github.com/scottie34/simple-vue-timeline/commit/194a799405324e4e53e6f2a88c0d6f0c09ba5afd)) 47 | * manage z-index on icon ([e0319d3](https://github.com/scottie34/simple-vue-timeline/commit/e0319d3aa42c123c7963cd01833c77517f62c088)) 48 | * MIT license ([8fd0d86](https://github.com/scottie34/simple-vue-timeline/commit/8fd0d8695ccf9c068cdc646032a89a5f8c92ce49)) 49 | * readme.md absolute image link ([bcbcb5e](https://github.com/scottie34/simple-vue-timeline/commit/bcbcb5e8b32072a0b7066ce7041d6a9549e4082b)) 50 | * several enhancements (use bootstrap icons, momentjs) ([bb493a3](https://github.com/scottie34/simple-vue-timeline/commit/bb493a371449895c4b871974b4e2df8e23927d9e)) 51 | * several enhancements (use bootstrap icons, momentjs) ([7fe5c04](https://github.com/scottie34/simple-vue-timeline/commit/7fe5c04ae9648b01ef97bc1eadb9898cdc1a1fc0)) 52 | * update README ([c08b39d](https://github.com/scottie34/simple-vue-timeline/commit/c08b39d31b265aede8bdfb5020d5c9a721fb5228)) 53 | 54 | 55 | ### Bug Fixes 56 | 57 | * bad namespace ([454f35a](https://github.com/scottie34/simple-vue-timeline/commit/454f35a7e4e7bfe2ffe1193804422dad9b884d88)) 58 | * change cast method to Item in App ([22b05d7](https://github.com/scottie34/simple-vue-timeline/commit/22b05d7c23c93572c9f86a9b62629befd9cd9fb8)) 59 | * css timeline-container ([d04777b](https://github.com/scottie34/simple-vue-timeline/commit/d04777b3418a3eb0c56fa745477c353448ed82ad)) 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 scottie34 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 | # simple-vue-timeline 2 | ![CI](https://img.shields.io/travis/com/scottie34/simple-vue-timeline/master.svg?style=flat-square) 3 | ![download](https://img.shields.io/npm/dm/simple-vue-timeline.svg?style=flat-square) 4 | ![version](https://img.shields.io/npm/v/simple-vue-timeline.svg?style=flat-square) 5 | ![license](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square) 6 | 7 | A simple but customizable and reactive timeline vue component which leverages the use of common libraries: 8 | * [bootstrap vue components](https://bootstrap-vue.js.org/), 9 | * [vue-fontawesome](https://github.com/FortAwesome/vue-fontawesome) 10 | * and [fecha](https://github.com/taylorhakes/fecha) date formatting. 11 | 12 | If you find it useful, give it a [star](https://github.com/scottie34/simple-vue-timeline) and please consider [buying me a coffee](https://www.buymeacoffee.com/scottie34). 13 | 14 | Refer to the [documentation](https://scottie34.github.io/simple-vue-timeline/) for further details. 15 | 16 | Use [github](https://github.com/scottie34/simple-vue-timeline) for any issue you encountered or to give me some feedback of your usage. 17 | 18 | ![sample](https://raw.githubusercontent.com/scottie34/simple-vue-timeline/master/docs/simple-vue-timeline.png) 19 | 20 | 21 | ## Getting Started 22 | 23 | ### Installation 24 | ```shell script 25 | npm install --save simple-vue-timeline 26 | ``` 27 | 28 | ```ts 29 | import { Vue } from "vue"; 30 | import { SimpleTimelinePlugin } from 'simple-vue-timeline'; 31 | 32 | Vue.use(SimpleTimelinePlugin); 33 | ``` 34 | 35 | ### Declare third party libraries usage 36 | Since 2.x version, third party usages are no more declared by the simple-vue-timeline itself. 37 | It is thus your responsibility to declare them in your vue project which uses simple-vue-timeline. 38 | 39 | #### vue-fontawesome 40 | Refer to [vue-fontawesome](https://github.com/FortAwesome/vue-fontawesome#usage) documentation. 41 | ```ts 42 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; 43 | import { Vue } from "vue"; 44 | 45 | Vue.component('font-awesome-icon', FontAwesomeIcon); 46 | ``` 47 | 48 | #### bootstrap-vue 49 | Refer to [bootstrap-vue](https://bootstrap-vue.js.org/docs/) documentation. 50 | The following plugins must be declared: 51 | * BadgePlugin 52 | * ButtonPlugin 53 | * CardPlugin 54 | * LayoutPlugin 55 | 56 | ```ts 57 | import { Vue } from "vue"; 58 | import { BadgePlugin, ButtonPlugin, CardPlugin, LayoutPlugin } from 'bootstrap-vue'; 59 | 60 | Vue.use(BadgePlugin); 61 | Vue.use(ButtonPlugin); 62 | Vue.use(CardPlugin); 63 | Vue.use(LayoutPlugin); 64 | ``` 65 | 66 | ### Style 67 | ```ts 68 | @import '~simple-vue-timeline/dist/simple-vue-timeline'; 69 | ``` 70 | 71 | You must also add the bootstrap style: 72 | ```ts 73 | @import '~bootstrap/scss/bootstrap'; 74 | ``` 75 | 76 | ### Template Element 77 | Add the element as follows: 78 | 79 | `template` 80 | ```vue 81 | 82 | ``` 83 | 84 | Refer to the `Vue Class Component Sample` section below for a complete sample. 85 | 86 | ## Contribute 87 | Once cloned, you can run the following commands to serve the [demo.ts](https://github.com/scottie34/simple-vue-timeline/blob/master/src/demo.ts) 88 | entry point. 89 | 90 | ```shell script 91 | npm install 92 | npm run serve 93 | ``` 94 | 95 | ### Commit messages 96 | Commit messages must follow the [AngularJS's commit message convention](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) also known as [conventional-changelog](https://github.com/ajoslin/conventional-changelog). 97 | This repo is [commitizen-friendly](https://github.com/commitizen/cz-cli). 98 | 99 | ### Local Test with npm link 100 | You can use [npm link](https://docs.npmjs.com/cli/link.html) to try the lib integration locally. 101 | 102 | Note that you must add a `vue.config.js` in the project using the lib with the following content 103 | 104 | ```js 105 | const path = require("path"); 106 | 107 | // npm link https://github.com/vuejs/vue-cli/issues/4271#issuecomment-585299391 108 | module.exports = { 109 | configureWebpack: { 110 | resolve: { 111 | alias: { 112 | vue$: path.resolve("./node_modules/vue/dist/vue.runtime.esm.js") 113 | } 114 | } 115 | } 116 | }; 117 | ``` 118 | 119 | ## Vue Class Component Sample 120 | 121 | ```vue 122 | 134 | 135 | 197 | ``` 198 | 199 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@vue/app', 5 | { 6 | useBuiltIns: 'entry' 7 | } 8 | ] 9 | ] 10 | }; 11 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # simple-vue-timeline 2 | ![CI](https://img.shields.io/travis/com/scottie34/simple-vue-timeline/master.svg?style=flat-square) 3 | ![download](https://img.shields.io/npm/dm/simple-vue-timeline.svg?style=flat-square) 4 | ![version](https://img.shields.io/npm/v/simple-vue-timeline.svg?style=flat-square) 5 | ![license](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square) 6 | 7 | A simple but customizable and reactive timeline vue component which leverages the use of common libraries: 8 | * [bootstrap vue components](https://bootstrap-vue.js.org/), 9 | * [vue-fontawesome](https://github.com/FortAwesome/vue-fontawesome) 10 | * and [fecha](https://github.com/taylorhakes/fecha) date formatting. 11 | 12 | If you find it useful, give it a [star](https://github.com/scottie34/simple-vue-timeline) and please consider [buying me a coffee](https://www.buymeacoffee.com/scottie34). 13 | 14 | Use [github](https://github.com/scottie34/simple-vue-timeline) for any issue you encountered or to give me some feedback of your usage. 15 | 16 | ![sample](https://raw.githubusercontent.com/scottie34/simple-vue-timeline/master/docs/simple-vue-timeline.png) 17 | 18 | * TOC 19 | {:toc} 20 | 21 | ## Getting Started 22 | 23 | ### Installation 24 | ``` 25 | npm install --save simple-vue-timeline 26 | ``` 27 | 28 | ```ts 29 | import { Vue } from "vue"; 30 | import { SimpleTimelinePlugin } from 'simple-vue-timeline'; 31 | 32 | Vue.use(SimpleTimelinePlugin); 33 | ``` 34 | 35 | ### Declare third party libraries usage 36 | Since 2.x version, third party usages are no more declared by the simple-vue-timeline itself. 37 | It is thus your responsibility to declare them in your vue project which uses simple-vue-timeline. 38 | 39 | #### vue-fontawesome 40 | Refer to [vue-fontawesome](https://github.com/FortAwesome/vue-fontawesome#usage) documentation. 41 | ```ts 42 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; 43 | import { Vue } from "vue"; 44 | 45 | Vue.component('font-awesome-icon', FontAwesomeIcon); 46 | ``` 47 | 48 | #### bootstrap-vue 49 | Refer to [bootstrap-vue](https://bootstrap-vue.js.org/docs/) documentation. 50 | The following plugins must be declared: 51 | * BadgePlugin 52 | * ButtonPlugin 53 | * CardPlugin 54 | * LayoutPlugin 55 | 56 | ```ts 57 | import { Vue } from "vue"; 58 | import { BadgePlugin, ButtonPlugin, CardPlugin, LayoutPlugin } from 'bootstrap-vue'; 59 | 60 | Vue.use(BadgePlugin); 61 | Vue.use(ButtonPlugin); 62 | Vue.use(CardPlugin); 63 | Vue.use(LayoutPlugin); 64 | ``` 65 | 66 | ### Style 67 | ```ts 68 | @import '~simple-vue-timeline/dist/simple-vue-timeline'; 69 | ``` 70 | 71 | You must also add the bootstrap style: 72 | ```ts 73 | @import '~bootstrap/scss/bootstrap'; 74 | ``` 75 | 76 | ### Template Element 77 | Add the element as follows: 78 | 79 | `template` 80 | ```vue 81 | 82 | ``` 83 | 84 | Refer to the `Vue Class Component Sample` section below for a complete sample. 85 | 86 | ## Props 87 | 88 | | Name | Type | Description | 89 | | --- | --- | --- | 90 | | `items` | `Item[]` | An item array containing your timeline items | 91 | | `dateformat` | `string` | The [fecha](https://github.com/taylorhakes/fecha) pattern to use to format date | 92 | | `v-on` | `Listener[]` | This one must be set to `$listeners` to be able to react on event emitted by Control (see Controls below) | 93 | | `@timeline-` | `string` | The method to be called to react on `` events (see Controls below) | 94 | 95 | ## items 96 | Component expects an array of Items 97 | 98 | | Variable | Type | Description | 99 | | --- | --- | --- | 100 | | `id` | `number` | An unique id for your Item | 101 | | `icon` | `string` | The id of the `fontawesome` icon to use | 102 | | `status` | `Status` | A field of the Status enum related to [bootstrap color variant](https://bootstrap-vue.js.org/docs/reference/color-variants/#base-variants) (used for icon and card). | 103 | | `title` | `string` | The Item title | 104 | | `controls` | `Control[]` | An array of control for this Item (see Controls below) | 105 | | `createdDate` | `Date` | Date of your Item (`dateFormat` used to format it) | 106 | | `body` | `string` | The Item content | 107 | 108 | ## Controls 109 | It allows to add buttons on your Item. 110 | 111 | | Variable | Type | Description | 112 | | --- | --- | --- | 113 | | `method` | `string` | A method name used when emitting events | 114 | | `icon` | `string` | The id of the `fontawesome` icon to use | 115 | 116 | ### Event 117 | On button click, an event is emitting using the identifier `timeline-`. 118 | 119 | Events are emitted with the following object as parameter 120 | ```vue 121 | { eventId: this.eventId } 122 | ``` 123 | (`this.eventId` matches the id of the Item). 124 | 125 | #### Example 126 | For instance adding the following control 127 | ```vue 128 | new Control("edit", "pencil-alt") 129 | ``` 130 | will generate `timeline-edit` event. 131 | 132 | To react on such event, one should provide: 133 | * the following prop to the timeline component: 134 | ```vue 135 | @timeline-edit="edit"` 136 | ``` 137 | 138 | * the associated `edit` method which will be called 139 | ```ts 140 | public edit(e: any) { 141 | console.log("edit " + e["eventId"]); 142 | } 143 | ``` 144 | 145 | ## Contribute 146 | Once cloned, you can run the following commands to serve the [demo.ts](https://github.com/scottie34/simple-vue-timeline/blob/master/src/demo.ts) 147 | entry point. 148 | 149 | ```shell 150 | npm install 151 | npm run serve 152 | ``` 153 | 154 | ### Commit messages 155 | Commit messages must follow the [AngularJS's commit message convention](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) also known as [conventional-changelog](https://github.com/ajoslin/conventional-changelog). 156 | This repo is [commitizen-friendly](https://github.com/commitizen/cz-cli). 157 | 158 | ### Local Test with npm link 159 | You can use [npm link](https://docs.npmjs.com/cli/link.html) to try the lib integration locally. 160 | 161 | Note that you must add a `vue.config.js` in the project using the lib with the following content 162 | 163 | ```js 164 | const path = require("path"); 165 | 166 | // npm link https://github.com/vuejs/vue-cli/issues/4271#issuecomment-585299391 167 | module.exports = { 168 | configureWebpack: { 169 | resolve: { 170 | alias: { 171 | vue$: path.resolve("./node_modules/vue/dist/vue.runtime.esm.js") 172 | } 173 | } 174 | } 175 | }; 176 | ``` 177 | 178 | ## Vue Class Component Sample 179 | 180 | ```vue 181 | 193 | 194 | 256 | ``` 257 | 258 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | title: simple-vue-timeline 3 | description: A simple and customizable timeline vue component 4 | show_downloads: true 5 | google_analytics: UA-162059172-1 6 | markdown: kramdown 7 | -------------------------------------------------------------------------------- /docs/simple-vue-timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottie34/simple-vue-timeline/2c5dd8381a1567c13c133597c1fc334628af5dab/docs/simple-vue-timeline.png -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './src/main'; 2 | 3 | declare module 'simple-vue-timeline'; 4 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel', 3 | collectCoverage: true, 4 | collectCoverageFrom: [ 5 | 'src/**/*.{vue,ts}', 6 | '!src/**/*.d.ts', 7 | '!src/App.vue', 8 | '!src/demo.ts', 9 | '!src/config/**', 10 | '!**/node_modules/**', 11 | '!dist/**', 12 | '!src/plugins/**', 13 | '!src/config/**', 14 | '!tests/unit/**' 15 | ], 16 | coverageReporters: ['lcov', 'text-summary'] 17 | }; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple-vue-timeline", 3 | "version": "2.0.9", 4 | "private": false, 5 | "description": "A timeline vue component", 6 | "scripts": { 7 | "serve": "vue-cli-service serve ./src/demo.ts", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint", 10 | "build-bundle": "vue-cli-service build --target lib --name simple-vue-timeline ./src/main.ts --mode production", 11 | "test:unit": "vue-cli-service test:unit", 12 | "release": "standard-version" 13 | }, 14 | "main": "./dist/simple-vue-timeline.common.js", 15 | "files": [ 16 | "dist/*", 17 | "src/*", 18 | "public/*", 19 | "*.json", 20 | "*.js", 21 | "*.ts" 22 | ], 23 | "dependencies": { 24 | "@fortawesome/fontawesome-svg-core": "^1.2.28", 25 | "@fortawesome/free-solid-svg-icons": "^5.13.0", 26 | "@fortawesome/vue-fontawesome": "^0.1.9", 27 | "bootstrap-vue": "^2.17.3", 28 | "core-js": "^2.6.11", 29 | "fecha": "^4.2.0", 30 | "postcss-import": "^12.0.1", 31 | "postcss-url": "^8.0.0", 32 | "vue": "^2.6.12", 33 | "vue-class-component": "^7.2.6", 34 | "vue-property-decorator": "^8.4.1" 35 | }, 36 | "devDependencies": { 37 | "@babel/polyfill": "^7.11.5", 38 | "@commitlint/cli": "^11.0.0", 39 | "@commitlint/config-conventional": "^11.0.0", 40 | "@types/jest": "^24.0.19", 41 | "@vue/cli-plugin-babel": "^5.0.8", 42 | "@vue/cli-plugin-eslint": "^3.12.1", 43 | "@vue/cli-plugin-typescript": "^3.12.1", 44 | "@vue/cli-plugin-unit-jest": "^5.0.8", 45 | "@vue/cli-service": "^5.0.8", 46 | "@vue/eslint-config-prettier": "^5.1.0", 47 | "@vue/eslint-config-typescript": "^4.0.0", 48 | "@vue/test-utils": "1.0.0-beta.31", 49 | "babel-eslint": "^10.1.0", 50 | "bootstrap": "^4.4.1", 51 | "cz-conventional-changelog": "^3.3.0", 52 | "eslint": "^5.16.0", 53 | "eslint-plugin-prettier": "^3.1.2", 54 | "eslint-plugin-vue": "^5.0.0", 55 | "husky": "^4.3.0", 56 | "lint-staged": "^13.1.0", 57 | "mutationobserver-shim": "^0.3.5", 58 | "node-sass": "^7.0.0", 59 | "popper.js": "^1.16.1", 60 | "portal-vue": "^2.1.7", 61 | "prettier": "^1.19.1", 62 | "sass-loader": "^7.3.1", 63 | "standard-version": "^9.0.0", 64 | "typescript": "^3.8.3", 65 | "vue-cli-plugin-bootstrap-vue": "^0.4.0", 66 | "vue-template-compiler": "^2.6.12" 67 | }, 68 | "homepage": "https://scottie34.github.io/simple-vue-timeline/", 69 | "keywords": [ 70 | "vue", 71 | "timeline", 72 | "bootstrap", 73 | "fontawesome" 74 | ], 75 | "license": "MIT", 76 | "lint-staged": { 77 | "*.{js,vue,ts}": [ 78 | "vue-cli-service lint", 79 | "git add" 80 | ], 81 | "{,src/**/}*.{md,json,js,ts,css,scss}": [ 82 | "prettier --write", 83 | "git add" 84 | ] 85 | }, 86 | "husky": { 87 | "hooks": { 88 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 89 | } 90 | }, 91 | "repository": { 92 | "type": "git", 93 | "url": "https://github.com/scottie34/simple-vue-timeline.git" 94 | }, 95 | "config": { 96 | "commitizen": { 97 | "path": "node_modules/cz-conventional-changelog" 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | plugins: { 5 | 'postcss-import': {}, 6 | 'postcss-url': {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | autoprefixer: {} 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 68 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottie34/simple-vue-timeline/2c5dd8381a1567c13c133597c1fc334628af5dab/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/scss/simple-vue-timeline.scss: -------------------------------------------------------------------------------- 1 | .timeline { 2 | position: relative; 3 | } 4 | 5 | .timeline:before { 6 | background-color: #eee; 7 | bottom: 0; 8 | content: ''; 9 | margin-left: -2px; 10 | position: absolute; 11 | top: 0; 12 | width: 4px; 13 | z-index: 1; 14 | height: 100%; 15 | } 16 | 17 | .timeline-icon { 18 | z-index: 2; 19 | } 20 | 21 | .timeline-container { 22 | text-align: center; 23 | } 24 | -------------------------------------------------------------------------------- /src/assets/scss/vendor.scss: -------------------------------------------------------------------------------- 1 | @import '~bootstrap/scss/bootstrap'; 2 | -------------------------------------------------------------------------------- /src/components/SimpleTimeline.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/components/SimpleTimelineControl.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | -------------------------------------------------------------------------------- /src/components/SimpleTimelineItem.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | -------------------------------------------------------------------------------- /src/components/index.d.ts: -------------------------------------------------------------------------------- 1 | import SimpleTimeline from './simple-timeline.component'; 2 | import SimpleTimelineItem from './simple-timeline-item.component'; 3 | import SimpleTimelineControl from './simple-timeline-control.component'; 4 | import { Status } from './simple-timeline-status.model'; 5 | import { Item } from './simple-timeline-item.model'; 6 | import { Control } from './simple-timeline-control.model'; 7 | 8 | export { SimpleTimeline, SimpleTimelineItem, SimpleTimelineControl, Status, Item, Control }; 9 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import SimpleTimeline from './SimpleTimeline'; 2 | import SimpleTimelineItem from './SimpleTimelineItem'; 3 | import SimpleTimelineControl from './SimpleTimelineControl'; 4 | import { Status } from './simple-timeline-status.model'; 5 | import { Item } from './simple-timeline-item.model'; 6 | import { Control } from './simple-timeline-control.model'; 7 | 8 | export { SimpleTimeline, SimpleTimelineItem, SimpleTimelineControl, Status, Item, Control }; 9 | -------------------------------------------------------------------------------- /src/components/simple-timeline-control.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Prop, Vue } from 'vue-property-decorator'; 2 | import { Control } from './simple-timeline-control.model'; 3 | 4 | @Component({}) 5 | export default class SimpleTimelineControl extends Vue { 6 | @Prop() 7 | public control!: Control; 8 | 9 | @Prop() 10 | public eventId!: number; 11 | 12 | public handleClick() { 13 | this.$parent.$emit('timeline-' + this.control.method, { eventId: this.eventId }); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/components/simple-timeline-control.model.ts: -------------------------------------------------------------------------------- 1 | export class Control { 2 | method: string; 3 | icon: string; 4 | 5 | constructor(method: string, icon: string) { 6 | this.method = method; 7 | this.icon = icon; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/components/simple-timeline-item.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Prop, Vue } from 'vue-property-decorator'; 2 | import { Item } from './simple-timeline-item.model'; 3 | import SimpleTimelineControl from './SimpleTimelineControl.vue'; 4 | import { format } from 'fecha'; 5 | 6 | @Component({ 7 | components: { 8 | timelineControl: SimpleTimelineControl 9 | } 10 | }) 11 | export default class SimpleTimelineItem extends Vue { 12 | @Prop() 13 | public item!: Item; 14 | 15 | @Prop() 16 | public dateFormat!: string; 17 | 18 | get formattedDate() { 19 | return format(this.item.createdDate, this.dateFormat); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/simple-timeline-item.model.ts: -------------------------------------------------------------------------------- 1 | import { Control } from './simple-timeline-control.model'; 2 | import { Status } from './simple-timeline-status.model'; 3 | 4 | export class Item { 5 | id: number; 6 | icon: string; 7 | status: Status; 8 | title: string; 9 | controls: Control[]; 10 | createdDate: Date; 11 | body: string; 12 | 13 | constructor(id: number, icon: string, status: Status, title: string, controls: Control[], createdDate: Date, body: string) { 14 | this.id = id; 15 | this.icon = icon; 16 | this.status = status; 17 | this.title = title; 18 | this.controls = controls; 19 | this.createdDate = createdDate; 20 | this.body = body; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/components/simple-timeline-status.model.ts: -------------------------------------------------------------------------------- 1 | export const enum Status { 2 | PRIMARY = 'primary', 3 | SUCCESS = 'success', 4 | WARNING = 'warning', 5 | DANGER = 'danger', 6 | INFO = 'info' 7 | } 8 | -------------------------------------------------------------------------------- /src/components/simple-timeline.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Prop, Vue } from 'vue-property-decorator'; 2 | import { Item } from './simple-timeline-item.model'; 3 | import SimpleTimelineItem from './SimpleTimelineItem.vue'; 4 | 5 | @Component({ 6 | components: { 7 | timeline: SimpleTimeline, 8 | timelineItem: SimpleTimelineItem 9 | } 10 | }) 11 | export default class SimpleTimeline extends Vue { 12 | @Prop({ default: () => [] }) 13 | public items!: Item[]; 14 | 15 | @Prop({ default: 'DD/MM/YY' }) 16 | public dateFormat!: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/demo.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import './assets/scss/vendor.scss'; 4 | import './assets/scss/simple-vue-timeline.scss'; 5 | import { SimpleTimelinePlugin } from '@/main'; 6 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; 7 | import { BadgePlugin, ButtonPlugin, CardPlugin, LayoutPlugin } from 'bootstrap-vue'; 8 | import { library } from '@fortawesome/fontawesome-svg-core'; 9 | import { faTrash } from '@fortawesome/free-solid-svg-icons/faTrash'; 10 | import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus'; 11 | import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt'; 12 | import { faTasks } from '@fortawesome/free-solid-svg-icons/faTasks'; 13 | import { faBell } from '@fortawesome/free-solid-svg-icons/faBell'; 14 | import { faHome } from '@fortawesome/free-solid-svg-icons/faHome'; 15 | import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons/faCalendarAlt'; 16 | 17 | Vue.config.productionTip = false; 18 | 19 | // font-awesome 20 | library.add(faTrash, faPlus, faPencilAlt, faTasks, faBell, faHome, faCalendarAlt); 21 | Vue.component('font-awesome-icon', FontAwesomeIcon); 22 | 23 | // bootstrap 24 | Vue.use(BadgePlugin); 25 | Vue.use(ButtonPlugin); 26 | Vue.use(CardPlugin); 27 | Vue.use(LayoutPlugin); 28 | 29 | // simpleTimeLine 30 | Vue.use(SimpleTimelinePlugin); 31 | 32 | new Vue({ 33 | render: h => h(App) 34 | }).$mount('#app'); 35 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import * as components from './components'; 2 | import { VueConstructor } from 'vue'; 3 | import './assets/scss/simple-vue-timeline.scss'; 4 | import { Status, Item, Control } from './components'; 5 | 6 | const SimpleTimelinePlugin = { 7 | install(vue: VueConstructor, options = {}) { 8 | for (const component in components) { 9 | // @ts-ignore 10 | if (vue && component && components[component]) { 11 | // @ts-ignore 12 | vue.component(component, components[component]); 13 | } 14 | } 15 | } 16 | }; 17 | 18 | export { SimpleTimelinePlugin, Control, Item, Status }; 19 | 20 | if (typeof window !== 'undefined' && window.Vue) { 21 | window.Vue.use(SimpleTimelinePlugin); 22 | } 23 | -------------------------------------------------------------------------------- /src/plugins/bootstrap-vue.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | import BootstrapVue from 'bootstrap-vue'; 4 | import 'bootstrap/dist/css/bootstrap.min.css'; 5 | import 'bootstrap-vue/dist/bootstrap-vue.css'; 6 | 7 | Vue.use(BootstrapVue); 8 | -------------------------------------------------------------------------------- /src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, {VNode} from 'vue'; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue'; 3 | export default Vue; 4 | } 5 | -------------------------------------------------------------------------------- /tests/unit/simple-timeline-item.spec.ts: -------------------------------------------------------------------------------- 1 | import { createLocalVue, mount, Wrapper, WrapperArray } from '@vue/test-utils'; 2 | import SimpleTimelineItem from '@/components/SimpleTimelineItem.vue'; 3 | import { Item } from '@/components/simple-timeline-item.model'; 4 | import { Status } from '@/components/simple-timeline-status.model'; 5 | import { Control } from '@/components/simple-timeline-control.model'; 6 | import Vue, { VueConstructor } from 'vue'; 7 | import { SimpleTimelinePlugin } from '@/main'; 8 | import { BadgePlugin, ButtonPlugin, CardPlugin, LayoutPlugin } from "bootstrap-vue"; 9 | 10 | const localVue: VueConstructor = createLocalVue(); 11 | // bootstrap 12 | Vue.use(BadgePlugin); 13 | Vue.use(ButtonPlugin); 14 | Vue.use(CardPlugin); 15 | Vue.use(LayoutPlugin); 16 | 17 | localVue.use(SimpleTimelinePlugin); 18 | 19 | describe('SimpleTimelineItem.vue', () => { 20 | it('renders passed props', () => { 21 | const title = 'Event Title'; 22 | const body = 'Here is the body message of item 0'; 23 | const controls = [new Control('edit', 'pencil-alt'), new Control('copy', 'plus')]; 24 | const itemIcon = 'calendar-alt'; 25 | 26 | const wrapper = mount(SimpleTimelineItem, { 27 | localVue, 28 | propsData: { 29 | item: new Item(0, itemIcon, Status.DANGER, title, controls, new Date(2020, 10, 8), body), 30 | dateFormat: 'YY/MM/DD' 31 | }, 32 | stubs: { 33 | FontAwesomeIcon: true 34 | } 35 | }); 36 | verifyIcon(wrapper.get('.timeline-icon'), itemIcon); 37 | expect(wrapper.get('.text-muted').text()).toBe('20/11/08'); 38 | expect(wrapper.get('.card-header').text()).toBe(title); 39 | expect(wrapper.get('.card-body').text()).toBe(body); 40 | 41 | let wrapperArray: WrapperArray = wrapper.get('.card-footer').findAll('button'); 42 | expect(wrapperArray.length).toBe(controls.length); 43 | controls.forEach((control, index) => { 44 | verifyIcon(wrapperArray.at(index), control.icon); 45 | }); 46 | }); 47 | }); 48 | 49 | function verifyIcon(wrapper: Wrapper, icon: string) { 50 | expect(wrapper.get('fontawesomeicon-stub').attributes('icon')).toBe(icon); 51 | } 52 | -------------------------------------------------------------------------------- /tests/unit/simple-timeline.spec.ts: -------------------------------------------------------------------------------- 1 | import { createLocalVue, mount, Wrapper, WrapperArray } from '@vue/test-utils'; 2 | import { Item } from '@/components/simple-timeline-item.model'; 3 | import { Status } from '@/components/simple-timeline-status.model'; 4 | import { Control } from '@/components/simple-timeline-control.model'; 5 | import Vue, { VueConstructor } from 'vue'; 6 | import SimpleTimeline from '@/components/SimpleTimeline.vue'; 7 | import { SimpleTimelinePlugin } from '@/main'; 8 | import { BadgePlugin, ButtonPlugin, CardPlugin, LayoutPlugin } from "bootstrap-vue"; 9 | 10 | const localVue: VueConstructor = createLocalVue(); 11 | // bootstrap 12 | Vue.use(BadgePlugin); 13 | Vue.use(ButtonPlugin); 14 | Vue.use(CardPlugin); 15 | Vue.use(LayoutPlugin); 16 | 17 | localVue.use(SimpleTimelinePlugin); 18 | 19 | describe('SimpleTimeline.vue', () => { 20 | it('renders passed props to SimpleTimeline', () => { 21 | const title = 'Event Title'; 22 | const body = 'Here is the body message of item 0'; 23 | const controls = [new Control('edit', 'pencil-alt'), new Control('copy', 'plus')]; 24 | const itemIcon = 'calendar-alt'; 25 | 26 | const wrapper = mount(SimpleTimeline, { 27 | localVue, 28 | propsData: { 29 | items: [ 30 | new Item(0, itemIcon, Status.DANGER, title, controls, new Date(2020, 10, 8), body), 31 | new Item(1, itemIcon, Status.INFO, title, controls, new Date(2019, 8, 12), body) 32 | ], 33 | dateFormat: 'YY/MM/DD' 34 | }, 35 | stubs: { 36 | FontAwesomeIcon: true 37 | } 38 | }); 39 | verifyIcon(wrapper.get('.timeline-icon'), itemIcon); 40 | expect(wrapper.get('.text-muted').text()).toBe('20/11/08'); 41 | expect(wrapper.get('.card-header').text()).toBe(title); 42 | expect(wrapper.get('.card-body').text()).toBe(body); 43 | 44 | let wrapperArray: WrapperArray = wrapper.get('.card-footer').findAll('button'); 45 | expect(wrapperArray.length).toBe(controls.length); 46 | controls.forEach((control, index) => { 47 | verifyIcon(wrapperArray.at(index), control.icon); 48 | }); 49 | }); 50 | }); 51 | 52 | function verifyIcon(wrapper: Wrapper, icon: string) { 53 | expect(wrapper.get('fontawesomeicon-stub').attributes('icon')).toBe(icon); 54 | } 55 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env", 16 | "jest" 17 | ], 18 | "paths": { 19 | "@/*": [ 20 | "src/*" 21 | ] 22 | }, 23 | "lib": [ 24 | "esnext", 25 | "dom", 26 | "dom.iterable", 27 | "scripthost" 28 | ] 29 | }, 30 | "include": [ 31 | "src/**/*.ts", 32 | "src/**/*.tsx", 33 | "src/**/*.vue", 34 | "tests/**/*.ts", 35 | "tests/**/*.tsx" 36 | ], 37 | "exclude": [ 38 | "node_modules" 39 | ] 40 | } --------------------------------------------------------------------------------