├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── .travis.yml
├── CITATION.cff
├── README.md
├── babel.config.js
├── basic-vue-chat.png
├── build
└── rollup.config.js
├── jest.config.js
├── package-lock.json
├── package.json
├── preview.png
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── assets
│ └── scss
│ │ ├── main.scss
│ │ ├── modules
│ │ ├── _all.scss
│ │ ├── _animations.scss
│ │ ├── _colors.scss
│ │ ├── _defaults.scss
│ │ ├── _mixins.scss
│ │ ├── _responsiveness.scss
│ │ ├── _typography.scss
│ │ └── _variables.scss
│ │ └── partials
│ │ ├── _base.scss
│ │ ├── _features.scss
│ │ ├── _header.scss
│ │ ├── _input.scss
│ │ ├── _message.scss
│ │ ├── _messages.scss
│ │ ├── _picker.scss
│ │ └── _window.scss
├── components
│ └── basic-vue-chat
│ │ ├── BasicVueChat.vue
│ │ ├── entry.js
│ │ ├── input
│ │ ├── InputButton.vue
│ │ ├── InputContainer.vue
│ │ └── InputField.vue
│ │ ├── messages
│ │ ├── MessageForeign.vue
│ │ ├── MessageOwn.vue
│ │ └── MessagesList.vue
│ │ └── mocks
│ │ └── mock-messages-list.js
├── helpers
│ └── scroll.js
├── main.js
└── wrapper.js
└── tests
└── unit
├── .eslintrc.js
├── messages
└── messages-list.spec.js
├── mocks
└── mock-messages-list.js
└── props.spec.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: [
7 | 'plugin:vue/recommended',
8 | '@vue/standard'
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 | parserOptions: {
15 | parser: 'babel-eslint'
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
63 | .DS_Store
64 | node_modules
65 | /dist
66 |
67 | /tests/e2e/videos/
68 | /tests/e2e/screenshots/
69 |
70 | # local env files
71 | .env.local
72 | .env.*.local
73 |
74 | # Log files
75 | npm-debug.log*
76 | yarn-debug.log*
77 | yarn-error.log*
78 |
79 | # Editor directories and files
80 | .idea
81 | .vscode
82 | *.suo
83 | *.ntvs*
84 | *.njsproj
85 | *.sln
86 | *.sw*
87 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "node"
4 | cache: npm
--------------------------------------------------------------------------------
/CITATION.cff:
--------------------------------------------------------------------------------
1 | cff-version: 1.2.0
2 | message: "If you use this software, please cite it as below."
3 | authors:
4 | - family-names: "Maczan"
5 | given-names: "Jędrzej Paweł"
6 | orcid: "https://orcid.org/0000-0003-1741-6064"
7 | title: "Basic Vue Chat"
8 | date-released: 2022-09-08
9 | url: "https://github.com/jmaczan/basic-vue-chat"
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 | # basic-vue-chat
4 |
5 | [](https://www.npmjs.com/package/basic-vue-chat)
6 |
7 |
8 |
9 | Implementation of Vue-based chat.
10 |
11 | - [basic-vue-chat](#basic-vue-chat)
12 | * [Installation](#installation)
13 | + [npm](#npm)
14 | + [yarn](#yarn)
15 | + [using repository](#using-repository)
16 | * [Dependencies](#dependencies)
17 | * [Usage](#usage)
18 | + [Pushing messages](#pushing-messages)
19 | + [Handling messages from user](#handling-messages-from-user)
20 | + [Images](#images)
21 | + [Commands](#commands)
22 | + [Mock data](#mock-data)
23 | * [Customization](#customization)
24 | + [Styles](#styles)
25 | + [Title](#title)
26 | + [Initial data](#initial-data)
27 | + [Styling](#styling)
28 | * [Code structure](#code-structure)
29 | * [Technologies used](#technologies-used)
30 |
31 | ## Installation
32 |
33 | You can install the component using package managers, such as npm or yarn or install component from the repository.
34 |
35 | ### npm
36 | ```bash
37 | npm i basic-vue-chat
38 | ```
39 |
40 | ### yarn
41 | ```bash
42 | yarn add basic-vue-chat
43 | ```
44 |
45 | ### using repository
46 | ```bash
47 | git clone https://github.com/jmaczan/basic-vue-chat.git
48 | cd basic-vue-chat
49 | npm i
50 | ```
51 |
52 | ## Dependencies
53 |
54 | Components uses Vue (`vue` package), Fontawesome and Moment.js for Vue (`vue-moment`).
55 |
56 | ## Usage
57 |
58 | Chat is a single Vue component, which you can find in `/src/components/basic-vue-chat/`. To start, just import BasicVueChat component and put the following line into your html code:
59 | ```html
60 |
61 | ```
62 |
63 | ### Pushing messages
64 |
65 | To push message to chat, just **pass newMessage prop to BasicVueChat**. Example:
66 | ```html
67 |
68 | ```
69 |
70 | The `message` object above may be part of `data` in your Vue component in which you will use BasicVueChat.
71 |
72 | Example of correct message structure:
73 | ```javascript
74 | {
75 | id: 0,
76 | author: 'Person',
77 | imageUrl: 'http://path/to/image',
78 | image: '',
79 | contents: 'hi there',
80 | date: '16:30'
81 | }
82 | ```
83 |
84 | You can find example of message pushing in `App.vue` file.
85 |
86 | ### Handling messages from user
87 |
88 | When user sends message, **the message is propagated to BasicVueChat component** and **event newOwnMessage is emitted**. To handle this event, you can for example do this:
89 | ```html
90 |
91 | ```
92 | where `onNewOwnMessage(message)` is a method in your Vue component in which you will use BasicVueChat.
93 |
94 | Example of correct event payload structure:
95 | ```javascript
96 | {
97 | id: 1,
98 | imageUrl: 'http://path/to/image',
99 | image: File(),
100 | contents: 'hello',
101 | date: '16:31'
102 | }
103 | ```
104 |
105 | ### Images
106 |
107 | You can upload and receive images. To attach image, use paperclip button. Image will be emitted in message on `image` (as `File` object) and `imageUrl` (path `string`) properties.
108 |
109 | ### Commands
110 |
111 | To start development, you can use hot reload mode:
112 | ```
113 | npm run serve
114 | ```
115 |
116 | To build production version:
117 | ```
118 | npm run build
119 | ```
120 |
121 | To run tests:
122 | ```
123 | npm test
124 | ```
125 |
126 | ### Mock data
127 |
128 | To attach mock data, just pass logic prop `attachMock` to BasicVueChat.
129 |
130 | ## Customization
131 |
132 | ### Styles
133 | Styles are imported in main `BasicVueChat` component and variables have `!default` values, so it means that you can override default values by defining your own variables before styles import.
134 |
135 | ```scss
136 |
141 | ```
142 |
143 | ### Title
144 |
145 | Pass prop `title` to BasicVueChat component.
146 | ```html
147 |
148 | ```
149 |
150 | ### Initial data
151 |
152 | Pass prop `initialFeed` to BasicVueChat component.
153 | ```html
154 |
155 | ```
156 | Example of correct data structure:
157 | ```javascript
158 | const feed = [
159 | {
160 | id: 1,
161 | author: 'Person',
162 | imageUrl: 'http://path/to/image',
163 | contents: 'hi there',
164 | date: '16:30'
165 | },
166 | {
167 | id: 0,
168 | author: 'Me',
169 | contents: 'hello',
170 | date: '16:30'
171 | }
172 | ]
173 | ```
174 |
175 | Pass prop `initialAuthorId` to BasicVueChat component to define current user's ID. Default value is `0`.
176 |
177 | ### Styling
178 |
179 | Chat uses SCSS, so you can easily override variables used in project. You can find them in `/src/assets/scss/modules/_variables.scss`. All variables have default values.
180 |
181 | | Description | Variable | Default value |
182 | |---|---|---|
183 | | Primary color | $primary | $slate-blue (#6B63D8) |
184 | | Secondary color | $secondary | $lavender (#B284ED) |
185 | | Header color | $header-color | $ghost-white (#FAF9FF) |
186 | | Input background color | $input-background-color | $alice-blue (#F2EFFF) |
187 | | Font family | $font-family | 'Source Sans Pro', sans-serif |
188 | | Font weight | $font-weight | 400 |
189 | | Font size | $font-size | 14px |
190 | | Dark text color | $dark-text-color | $madison (#2C3E50) |
191 | | Light text color | $light-text-color | $ghost-white (#FAF9FF) |
192 | | Dark background color | $dark-bg | $madison (#2C3E50) |
193 | | Light background color | $light-bg | $white (#FFFFFF) |
194 | | Chat window width | $window-width | 500px |
195 | | Chat window height | $window-height | 400px |
196 | | Message max width | $message-max-width | 200px |
197 |
198 | ## Code structure
199 |
200 | 1. assets
201 | - Sass standard CSS code structure
202 | - Components styles in `partials` directory
203 | - Variables and settings in `modules` directory
204 | 2. components
205 | - chat's components are in subdirectories of `basic-vue-chat` directory
206 | 3. helpers
207 | - reusable helpers for scrolling functionalities
208 | 4. App.vue - runner file
209 | 5. main.js - project config
210 |
211 |
212 | ## Technologies used
213 |
214 | 1. JavaScript
215 | * Vue
216 | * Moment.js
217 | 2. HTML5
218 | 3. CSS
219 | * SCSS
220 | * BEM
221 | 4. Tests
222 | * Jest
223 | * Vue test utils
224 | 5. Tooling
225 | * npm
226 | 6. Continuous Integration
227 | * Travis CI
228 | 7. Linting
229 | * ESLint standard config
230 |
231 | Developed and tested under macOS High Sierra 10.13 and Google Chrome 69.
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/basic-vue-chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmaczan/basic-vue-chat/723a6281188e6a6cbb0bc6fe494b93c537f8d711/basic-vue-chat.png
--------------------------------------------------------------------------------
/build/rollup.config.js:
--------------------------------------------------------------------------------
1 | import vue from 'rollup-plugin-vue' // Handle .vue SFC files
2 | import buble from 'rollup-plugin-buble' // Transpile/polyfill with reasonable browser support
3 |
4 | export default {
5 | input: 'src/wrapper.js', // Path relative to package.json
6 | output: {
7 | name: 'BasicVueChat',
8 | exports: 'named'
9 | },
10 | plugins: [
11 | vue({
12 | css: true, // Dynamically inject css as a
25 |
--------------------------------------------------------------------------------
/src/assets/scss/main.scss:
--------------------------------------------------------------------------------
1 | @import "partials/base";
2 |
3 | @import "partials/header";
4 | @import "partials/features";
5 | @import "partials/input";
6 | @import "partials/message";
7 | @import "partials/messages";
8 | @import "partials/picker";
9 | @import "partials/window";
--------------------------------------------------------------------------------
/src/assets/scss/modules/_all.scss:
--------------------------------------------------------------------------------
1 | @import "animations";
2 | @import "colors";
3 | @import "typography";
4 | @import "mixins";
5 | @import "variables";
6 | @import "responsiveness";
--------------------------------------------------------------------------------
/src/assets/scss/modules/_animations.scss:
--------------------------------------------------------------------------------
1 | .messages-list-item {
2 | transition: all 0.2s;
3 | }
4 |
5 | .messages-list-enter, .messages-list-leave-to
6 | /* .messages-list-leave-active below version 2.1.8 */ {
7 | opacity: 0;
8 | transform: translateY(30px);
9 | }
10 | .messages-list-leave-active {
11 | position: absolute;
12 | }
--------------------------------------------------------------------------------
/src/assets/scss/modules/_colors.scss:
--------------------------------------------------------------------------------
1 | $liberty: #5F5AA2;
2 | $amethyst: #9067C6;
3 | $purple-navy: #4E4A85;
4 | $slate-blue: #6B63D8;
5 | $lavender: #B284ED;
6 | $lavender-gray: #CBC9D6;
7 | $white: #FFFFFF;
8 | $ghost-white: #FAF9FF;
9 | $alice-blue: #F2EFFF;
10 | $madison: #2C3E50;
--------------------------------------------------------------------------------
/src/assets/scss/modules/_defaults.scss:
--------------------------------------------------------------------------------
1 | $base-font-family: $source-sans-pro-font !default;
2 | $base-font-weight: $regular !default;
3 | $base-font-size: 14px !default;
4 |
5 | $base-window-width: 500px !default;
6 | $base-window-height: 400px !default;
7 | $base-message-max-width: 200px !default;
--------------------------------------------------------------------------------
/src/assets/scss/modules/_mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin just-flex {
2 | display: -webkit-flex;
3 | display: flex;
4 | }
5 |
6 | @mixin flex($direction: column, $justify-content: center) {
7 | @include just-flex;
8 | flex-direction: $direction;
9 | justify-content: $justify-content;
10 | }
11 |
12 | @mixin box-shadow($values...) {
13 | @each $val in $values {
14 | -webkit-box-shadow: #{$val};
15 | box-shadow: #{$val};
16 | }
17 | }
--------------------------------------------------------------------------------
/src/assets/scss/modules/_responsiveness.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmaczan/basic-vue-chat/723a6281188e6a6cbb0bc6fe494b93c537f8d711/src/assets/scss/modules/_responsiveness.scss
--------------------------------------------------------------------------------
/src/assets/scss/modules/_typography.scss:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');
2 |
3 | $light: 100;
4 | $regular: 400;
5 | $bold: 600;
6 |
7 | $source-sans-pro-font: 'Source Sans Pro', sans-serif;
--------------------------------------------------------------------------------
/src/assets/scss/modules/_variables.scss:
--------------------------------------------------------------------------------
1 | @import "defaults";
2 |
3 | $primary: $slate-blue !default;
4 | $secondary: $lavender !default;
5 |
6 | $header-color: $ghost-white !default;
7 |
8 | $input-background-color: $alice-blue !default;
9 |
10 | $font-family: $base-font-family;
11 | $font-weight: $base-font-weight;
12 | $font-size: $base-font-size;
13 |
14 | $dark-text-color: $madison !default;
15 | $light-text-color: $ghost-white !default;
16 |
17 | $dark-bg: $madison !default;
18 | $light-bg: $white !default;
19 |
20 | $window-width: $base-window-width !default;
21 | $window-height: $base-window-height !default;
22 | $message-max-width: $base-message-max-width !default;
--------------------------------------------------------------------------------
/src/assets/scss/partials/_base.scss:
--------------------------------------------------------------------------------
1 | @import "../modules/all";
2 |
3 | body {
4 | font-family: $font-family;
5 | font-weight: $base-font-weight;
6 | font-size: $base-font-size;
7 | background-color: $light-bg;
8 | color: $dark-text-color;
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 | text-align: center;
12 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_features.scss:
--------------------------------------------------------------------------------
1 | .features {
2 | &__container {
3 | @include just-flex;
4 | position: relative;
5 | bottom: 0;
6 | }
7 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_header.scss:
--------------------------------------------------------------------------------
1 | .window {
2 | &__header {
3 |
4 | &__container {
5 | background: linear-gradient(90deg, $primary, $secondary);
6 | padding: 10px 5px;
7 | color: $header-color;
8 | font-weight: $bold;
9 | z-index: 1;
10 |
11 | @include box-shadow(0 2px 2px -2px $madison);
12 | }
13 |
14 | }
15 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_input.scss:
--------------------------------------------------------------------------------
1 | .window {
2 | &__input {
3 |
4 | &__container {
5 | position: relative;
6 | bottom: 0;
7 |
8 | input[type="file"] {
9 | height: 0.1px !important;
10 | width: 0.1px !important;
11 | opacity: 0;
12 | overflow: hidden;
13 | position: absolute;
14 | z-index: -1;
15 | }
16 |
17 | input[type="text"] {
18 | font-size: 12px;
19 | }
20 |
21 | .image {
22 | &--uploaded {
23 | max-width: 50px;
24 | max-height: 50px;
25 | margin-right: 5px;
26 | border-radius: 12px;
27 | }
28 | }
29 |
30 | .image + label {
31 | @include just-flex;
32 | align-self: center;
33 | margin-right: 5px;
34 | color: $primary;
35 | cursor: pointer;
36 | }
37 |
38 | .image:focus + label,
39 | .image + label:hover {
40 | color: $secondary;
41 | cursor: pointer;
42 | }
43 |
44 | .input {
45 | &__container {
46 | @include flex(row, space-between);
47 | padding: 7px 5px;
48 | align-items: center;
49 | }
50 |
51 | &-images-upload {
52 | @include just-flex;
53 | align-self: center;
54 | margin-right: 5px;
55 | color: $primary;
56 | cursor: pointer;
57 | }
58 |
59 | &-emoji-picker {
60 |
61 | &__container {
62 | position: absolute;
63 | bottom: 30px;
64 | right: 5px;
65 | z-index: 3;
66 | }
67 | }
68 |
69 | &__field {
70 | @include just-flex;
71 | flex-grow: 9999;
72 | padding: 5px 10px;
73 | margin-right: 5px;
74 | border-radius: 12px;
75 | background-color: $input-background-color;
76 |
77 | input {
78 | border: none;
79 | background-color: inherit;
80 | color: $dark-text-color;
81 | width: 100%;
82 |
83 | &:focus {
84 | outline: none;
85 | }
86 | }
87 | }
88 |
89 | &__button {
90 | @include just-flex;
91 | padding: 5px 10px;
92 | border-radius: 12px;
93 | background-color: $primary;
94 | color: $light-text-color;
95 | font-weight: $bold;
96 | cursor: pointer;
97 | }
98 | }
99 | }
100 | }
101 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_message.scss:
--------------------------------------------------------------------------------
1 | .window {
2 |
3 | %message {
4 | padding: 3px 5px;
5 |
6 | &__contents {
7 | max-width: $message-max-width !important;
8 | word-wrap: break-word;
9 | }
10 | }
11 |
12 | .message {
13 |
14 | @mixin message__contents($border-color: $alice-blue, $color: inherit, $background-color: $ghost-white) {
15 | border: 1px solid $border-color;
16 | border-radius: 12px;
17 | color: $color;
18 | background-color: $background-color;
19 | padding: 3px 5px;
20 | }
21 |
22 | &--foreign {
23 | @extend %message;
24 | @include flex(row, flex-start);
25 |
26 | .message {
27 | &__author {
28 | @include flex(column, center);
29 | font-weight: $bold;
30 | margin-right: 5px;
31 | }
32 |
33 | &__contents {
34 | @include message__contents(transparent);
35 | margin-right: 5px;
36 | }
37 |
38 | &__date {
39 | @include flex(column, center);
40 | color: $lavender-gray;
41 | }
42 | }
43 | }
44 |
45 | &--own {
46 | @extend %message;
47 | @include flex(row, flex-end);
48 |
49 | .message {
50 | &__contents {
51 | @extend %message__contents;
52 | @include message__contents(transparent, $ghost-white, $secondary);
53 | }
54 |
55 | &__date {
56 | @include flex(column, center);
57 | color: $lavender-gray;
58 | margin-right: 5px;
59 | }
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_messages.scss:
--------------------------------------------------------------------------------
1 | .window {
2 | &__messages {
3 |
4 | &__container {
5 | @include flex(column, flex-start);
6 | flex-grow: 999;
7 | overflow: auto;
8 | padding: 3px 0;
9 | border-left: 1px solid $alice-blue;
10 | border-right: 1px solid $alice-blue;
11 | border-bottom: 1px solid $alice-blue;
12 | transition: all 0.5s;
13 | overflow: scroll;
14 | overflow-x: hidden;
15 |
16 | &::-webkit-scrollbar {
17 | width: 0px; /* remove scrollbar space */
18 | background: transparent; /* optional: just make scrollbar invisible */
19 | }
20 |
21 | &::-webkit-scrollbar {
22 | width: 0;
23 | }
24 |
25 | &::-webkit-scrollbar-track {
26 | }
27 |
28 | &::-webkit-scrollbar-thumb {
29 | background-color: transparent;
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_picker.scss:
--------------------------------------------------------------------------------
1 | .emoji-mart {
2 | height: 250px !important;
3 | }
--------------------------------------------------------------------------------
/src/assets/scss/partials/_window.scss:
--------------------------------------------------------------------------------
1 | .window {
2 | @include flex(column);
3 | @include box-shadow(0 0 2px $madison);
4 | max-width: $window-width;
5 | height: $window-height;
6 | border: 0px solid transparent;
7 | border-radius: 15px;
8 | overflow: hidden;
9 | }
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/BasicVueChat.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
133 |
134 |
137 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/entry.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import BasicVueChat from './BasicVueChat.vue'
3 |
4 | const Components = {
5 | BasicVueChat
6 | }
7 |
8 | Object.keys(Components).forEach(name => {
9 | Vue.component(name, Components[name])
10 | })
11 |
12 | export default Components
13 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/input/InputButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 | Send
6 |
7 |
8 |
9 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/input/InputContainer.vue:
--------------------------------------------------------------------------------
1 |
2 |
52 |
53 |
54 |
121 |
122 |
127 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/input/InputField.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
16 |
33 |
34 |
37 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/messages/MessageForeign.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | {{ author }}
6 |
7 |
8 |
![]()
13 | {{ contents }}
14 |
15 |
16 | {{ date }}
17 |
18 |
19 |
20 |
21 |
48 |
49 |
52 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/messages/MessageOwn.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | {{ date }}
6 |
7 |
8 |
![]()
13 | {{ contents }}
14 |
15 |
16 |
17 |
18 |
45 |
46 |
49 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/messages/MessagesList.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
14 |
20 |
21 |
22 |
23 |
24 |
50 |
51 |
54 |
--------------------------------------------------------------------------------
/src/components/basic-vue-chat/mocks/mock-messages-list.js:
--------------------------------------------------------------------------------
1 | export default {
2 | authorId: 1,
3 | feed: [
4 | {
5 | id: 0,
6 | author: 'Person',
7 | contents: 'hi there',
8 | date: '16:30'
9 | },
10 | {
11 | id: 1,
12 | author: 'Me',
13 | contents: 'hello',
14 | date: '16:30'
15 | },
16 | {
17 | id: 1,
18 | author: 'Me',
19 | contents: 'lol',
20 | date: '16:31'
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/src/helpers/scroll.js:
--------------------------------------------------------------------------------
1 | export function scrollToBottom () {
2 | setTimeout(function () {
3 | var scrollContainer = document.getElementById('window__messages__container')
4 | var isScrolledToBottom = scrollContainer.scrollHeight - scrollContainer.clientHeight <= scrollContainer.scrollTop + 1
5 | if (!isScrolledToBottom) { scrollContainer.scrollTop = scrollContainer.scrollHeight }
6 | }, 201)
7 | }
8 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import { library } from '@fortawesome/fontawesome-svg-core'
4 | import { faPaperclip, faSmile } from '@fortawesome/free-solid-svg-icons'
5 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
6 |
7 | Vue.use(require('vue-moment'))
8 |
9 | library.add(faPaperclip)
10 | library.add(faSmile)
11 |
12 | Vue.component('font-awesome-icon', FontAwesomeIcon)
13 |
14 | Vue.config.productionTip = false
15 |
16 | new Vue({
17 | render: h => h(App)
18 | }).$mount('#app')
19 |
--------------------------------------------------------------------------------
/src/wrapper.js:
--------------------------------------------------------------------------------
1 | // Import vue component
2 | import BasicVueChat from './components/basic-vue-chat/BasicVueChat.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('BasicVueChat', BasicVueChat)
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