mirror of
https://github.com/tenrok/vue-tribute.git
synced 2026-05-17 03:39:40 +03:00
1.0 release
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1 @@
|
||||
* text=auto
|
||||
@@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "7"
|
||||
- "8"
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- node_modules
|
||||
before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
sudo: false
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Collin Henderson
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,59 @@
|
||||
# vue-tribute
|
||||
|
||||
[](https://travis-ci.org/syropian/vue-tribute)
|
||||
|
||||
> A Vue.js wrapper for Zurb's [Tribute](https://github.com/zurb/tribute) library for native @mentions.
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ yarn add vue-tribute
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ npm install vue-tribute --save
|
||||
```
|
||||
|
||||
**or** include the UMD build, hosted by [unpkg](https://unpkg.com) in a `<script>` tag. You will also need to include the main Zurb Tribute library:
|
||||
|
||||
```js
|
||||
<script src="js/tribute.js"></script>
|
||||
<script src="//unpkg.com/vue-tribute"></script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Import and register the component.
|
||||
|
||||
```js
|
||||
import VueTribute from 'vue-tribute'
|
||||
|
||||
export default {
|
||||
...
|
||||
components: {
|
||||
VueTribute
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In your template, wrap an `input`, `textarea` or `contenteditable` element in the `vue-tribute` component, and pass your Tribute options in.
|
||||
|
||||
```html
|
||||
<div>
|
||||
<vue-tribute :options="tributeOptions">
|
||||
<input type="text" placeholder="@..." />
|
||||
</vue-tribute>
|
||||
</div>
|
||||
```
|
||||
|
||||
See the available Tribute options [here](https://github.com/zurb/tribute#a-collection).
|
||||
|
||||
## Events
|
||||
|
||||
Tribute broadcasts two events — a `tribute-replaced` event, and a `tribute-no-match` event (see docs [here](https://github.com/zurb/tribute#replace-event)). For your convenience, whenever Tribute triggers these events, the vue-tribute component also [emits](http://vuejs.org/api/#vm-emit) these events.
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Collin Henderson](https://github.com/syropian)
|
||||
@@ -0,0 +1,73 @@
|
||||
import { mount } from 'vue-test-utils'
|
||||
import VueTribute from '../src'
|
||||
|
||||
describe('VueTribute', () => {
|
||||
let testData = {
|
||||
options: {
|
||||
values: [
|
||||
{ key: 'Phil Heartman', value: 'pheartman' },
|
||||
{ key: 'Gordon Ramsey', value: 'gramsey' }
|
||||
]
|
||||
}
|
||||
}
|
||||
it('has a name', () => {
|
||||
const wrapper = mount(VueTribute, {
|
||||
slots: {
|
||||
default: '<input type="text" placeholder="Testo" />'
|
||||
},
|
||||
propsData: testData
|
||||
})
|
||||
expect(wrapper.name()).toBe('vue-tribute')
|
||||
})
|
||||
|
||||
it('accepts an options prop', () => {
|
||||
const wrapper = mount(VueTribute, {
|
||||
slots: {
|
||||
default: '<input type="text" placeholder="Testo" />'
|
||||
},
|
||||
propsData: testData
|
||||
})
|
||||
|
||||
expect(wrapper.props()).toBe(testData)
|
||||
})
|
||||
|
||||
it('fires an event when there are no matches', () => {
|
||||
const wrapper = mount(VueTribute, {
|
||||
slots: {
|
||||
default: '<input type="text" placeholder="Testo" />'
|
||||
},
|
||||
propsData: testData
|
||||
})
|
||||
|
||||
const $input = wrapper.find('input[type=text]')
|
||||
$input.element.value = '@foobar'
|
||||
const evt = new CustomEvent('tribute-no-match')
|
||||
$input.element.dispatchEvent(evt)
|
||||
|
||||
expect(wrapper.emitted('tribute-no-match')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('fires an event when when the target Tribute element has been updated', () => {
|
||||
const wrapper = mount(VueTribute, {
|
||||
slots: {
|
||||
default: '<input type="text" placeholder="Testo" />'
|
||||
},
|
||||
propsData: testData
|
||||
})
|
||||
|
||||
const $input = wrapper.find('input[type=text]')
|
||||
|
||||
const evt = new CustomEvent('tribute-replaced')
|
||||
|
||||
$input.element.dispatchEvent(evt)
|
||||
|
||||
expect(wrapper.emitted('tribute-replaced')).toBeTruthy()
|
||||
})
|
||||
|
||||
function CustomEvent(event, params) {
|
||||
params = params || { bubbles: false, cancelable: false, detail: undefined }
|
||||
var evt = document.createEvent('CustomEvent')
|
||||
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
|
||||
return evt
|
||||
}
|
||||
})
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
webpackJsonp([1],[,function(t,e,n){"use strict";var a=n(11);e.a={components:{VueTribute:a.a},data:function(){return{options:{values:[{key:"Collin Henderson",value:"syropian"},{key:"Sarah Drasner",value:"sarah_edo"},{key:"Evan You",value:"youyuxi"},{key:"Adam Wathan",value:"adamwathan"}]}}},methods:{append:function(){var t=Math.random().toString(36).slice(2);this.options.values.push({key:t,value:t})}}}},function(t,e,n){t.exports=n(3)},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n(4),i=n(8);new a.a({el:"#app",render:function(t){return t(i.a)}})},,,,,function(t,e,n){"use strict";function a(t){n(9)}var i=n(1),r=n(13),o=n(10),u=a,s=o(i.a,r.a,!1,u,null,null);e.a=s.exports},function(t,e){},,function(t,e,n){"use strict";var a=n(12),i=n.n(a),r={name:"vue-tribute",props:{options:{type:Object,required:!0}},data:function(){return{tribute:null}},mounted:function(){var t=this,e=this.$slots.default[0].elm;this.tribute=new i.a(this.options),this.tribute.attach(e),e.addEventListener("tribute-replaced",function(e){t.$emit("tribute-replaced",e)}),e.addEventListener("tribute-no-match",function(e){t.$emit("tribute-no-match",e)})},render:function(t){return t("div",{staticClass:"v-tribute"},this.$slots.default)}};"undefined"!=typeof window&&window.Vue&&window.Vue.component(r.name,r),e.a=r},,function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"container"},[n("h1",[t._v("vue-tribute Demo")]),t._v(" "),n("h3",[t._v("Simple text input")]),t._v(" "),n("vue-tribute",{attrs:{options:t.options}},[n("input",{attrs:{type:"text",placeholder:"@..."}})]),t._v(" "),n("br"),t._v(" "),n("h3",[t._v("Textarea")]),t._v(" "),n("vue-tribute",{attrs:{options:t.options}},[n("textarea",{attrs:{placeholder:"@..."}})]),t._v(" "),n("br"),t._v(" "),n("h3",[t._v("contenteditable element")]),t._v(" "),n("vue-tribute",{attrs:{options:t.options}},[n("div",{staticClass:"content-editable",attrs:{contenteditable:"true",placeholder:"@..."}})]),t._v(" "),n("br"),t._v(" "),n("button",{staticClass:"btn",on:{click:t.append}},[t._v("Append New Item")])],1)},i=[],r={render:a,staticRenderFns:i};e.a=r}],[2]);
|
||||
//# sourceMappingURL=client.2ed01ca6.js.map
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
*{-webkit-box-sizing:border-box;box-sizing:border-box}body,html{height:100vh;width:100vw}body{background:-webkit-gradient(linear,left top,right top,from(#fc466b),to(#3f5efb));background:linear-gradient(90deg,#fc466b,#3f5efb);color:#fff;font-family:Helvetica Neue,Arial,sans-serif}.container,body{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.container{max-width:500px;width:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:0 20px}.v-tribute{width:100%}.content-editable,input[type=text]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;background:#eee;padding:1rem;color:#666;width:100%;border-radius:.25rem;font-size:16px;outline:none}.content-editable:focus,input[type=text]:focus{background:#fff}.content-editable:empty:before{content:attr(placeholder);display:block;color:#666}textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;background:#eee;padding:1rem;width:100%;border-radius:.25rem;font-size:16px;height:100px;outline:none}textarea:focus{background:#fff}.btn{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;cursor:pointer;margin:20px 0;background:#fc466b;color:#fff;font-size:16px;padding:8px 16px;border-radius:3px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.18);box-shadow:0 1px 3px rgba(0,0,0,.18)}.btn:hover{background:#fc375f}.tribute-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;border-radius:4px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.13);box-shadow:0 1px 4px rgba(0,0,0,.13)}.tribute-container ul{margin:0;margin-top:2px;padding:0;list-style:none;background:#fff;border-radius:4px;border:1px solid rgba(0,0,0,.13);background-clip:padding-box;overflow:hidden}.tribute-container li{color:#3f5efb;padding:5px 10px;cursor:pointer;font-size:14px}.tribute-container li.highlight,.tribute-container li:hover{background:#3f5efb;color:#fff}.tribute-container li span{font-weight:700}.tribute-container li.no-match{cursor:default}.tribute-container .menu-highlighted{font-weight:700}
|
||||
/*# sourceMappingURL=client.90c53eaf.css.map*/
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///./example/App.vue"],"names":[],"mappings":"AACA,EACE,8BACQ,qBAAuB,CAEjC,UAEE,aACA,WAAa,CAEf,KACE,iFACA,kDAUA,WACA,2CAAmD,CAErD,gBAZE,oBACA,oBACA,aACA,yBACI,sBACI,mBACR,wBACI,qBACI,sBAAwB,CAqBjC,WAhBC,gBACA,WAUA,4BACA,6BACI,0BACI,sBACR,cAAgB,CAElB,WACE,UAAY,CAEd,mCAEE,wBACG,qBACK,gBACR,YACA,gBACA,aACA,WACA,WACA,qBACA,eACA,YAAc,CAEhB,+CAEI,eAAiB,CAErB,+BACE,0BACA,cACA,UAAY,CAEd,SACE,wBACG,qBACK,gBACR,YACA,gBACA,aACA,WACA,qBACA,eACA,aACA,YAAc,CAEhB,eACI,eAAiB,CAErB,KACE,wBACG,qBACK,gBACR,YACA,eACA,cACA,mBACA,WACA,eACA,iBACA,kBACA,6CACQ,oCAA0C,CAEpD,WACI,kBAAoB,CAExB,mBACE,kBACA,MACA,OACA,YACA,iBACA,gBACA,cACA,cACA,eACA,kBACA,6CACQ,oCAA0C,CAEpD,sBACE,SACA,eACA,UACA,gBACA,gBACA,kBACA,iCACA,4BACA,eAAiB,CAEnB,sBACE,cACA,iBACA,eACA,cAAgB,CAElB,4DAEE,mBACA,UAAY,CAEd,2BACE,eAAkB,CAEpB,+BACE,cAAgB,CAElB,qCACE,eAAkB","file":"client.90c53eaf.css","sourcesContent":["\n* {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml,\nbody {\n height: 100vh;\n width: 100vw;\n}\nbody {\n background: -webkit-gradient(linear, left top, right top, from(#fc466b), to(#3f5efb));\n background: linear-gradient(to right, #fc466b, #3f5efb);\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n color: #fff;\n font-family: 'Helvetica Neue', 'Arial', sans-serif;\n}\n.container {\n max-width: 500px;\n width: 100%;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n padding: 0 20px;\n}\n.v-tribute {\n width: 100%;\n}\ninput[type='text'],\n.content-editable {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: none;\n background: #eee;\n padding: 1rem 1rem;\n color: #666;\n width: 100%;\n border-radius: 0.25rem;\n font-size: 16px;\n outline: none;\n}\ninput[type='text']:focus,\n .content-editable:focus {\n background: #fff;\n}\n.content-editable:empty:before {\n content: attr(placeholder);\n display: block;\n color: #666;\n}\ntextarea {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: none;\n background: #eee;\n padding: 1rem;\n width: 100%;\n border-radius: 0.25rem;\n font-size: 16px;\n height: 100px;\n outline: none;\n}\ntextarea:focus {\n background: #fff;\n}\n.btn {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n border: none;\n cursor: pointer;\n margin: 20px 0;\n background: #fc466b;\n color: #fff;\n font-size: 16px;\n padding: 8px 16px;\n border-radius: 3px;\n -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);\n}\n.btn:hover {\n background: #fc375f;\n}\n.tribute-container {\n position: absolute;\n top: 0;\n left: 0;\n height: auto;\n max-height: 300px;\n max-width: 500px;\n overflow: auto;\n display: block;\n z-index: 999999;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.13);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.13);\n}\n.tribute-container ul {\n margin: 0;\n margin-top: 2px;\n padding: 0;\n list-style: none;\n background: #fff;\n border-radius: 4px;\n border: 1px solid rgba(0, 0, 0, 0.13);\n background-clip: padding-box;\n overflow: hidden;\n}\n.tribute-container li {\n color: #3f5efb;\n padding: 5px 10px;\n cursor: pointer;\n font-size: 14px;\n}\n.tribute-container li.highlight,\n.tribute-container li:hover {\n background: #3f5efb;\n color: #fff;\n}\n.tribute-container li span {\n font-weight: bold;\n}\n.tribute-container li.no-match {\n cursor: default;\n}\n.tribute-container .menu-highlighted {\n font-weight: bold;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./example/App.vue"],"sourceRoot":""}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><meta http-equiv="Content-type" content="text/html; charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>vue-tribute</title><meta name="description" content="A Vue.js wrapper for Zurb's Tribute library for native @mentions"><link href="/client.90c53eaf.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="app"></div><script type="text/javascript" src="/manifest.95292176.js"></script><script type="text/javascript" src="/vendor.72774014.js"></script><script type="text/javascript" src="/client.2ed01ca6.js"></script></body></html>
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
(function(r){function n(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return r[e].call(t.exports,t,t.exports,n),t.l=!0,t.exports}var e=window.webpackJsonp;window.webpackJsonp=function(o,u,c){for(var f,i,p,a=0,l=[];a<o.length;a++)i=o[a],t[i]&&l.push(t[i][0]),t[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(e&&e(o,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=n(n.s=c[a]);return p};var o={},t={2:0};n.m=r,n.c=o,n.d=function(r,e,o){n.o(r,e)||Object.defineProperty(r,e,{configurable:!1,enumerable:!0,get:o})},n.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(e,"a",e),e},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="/",n.oe=function(r){throw console.error(r),r}})([]);
|
||||
//# sourceMappingURL=manifest.95292176.js.map
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+2
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+178
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<h1>vue-tribute Demo</h1>
|
||||
<h3>Simple text input</h3>
|
||||
<vue-tribute :options="options">
|
||||
<input type="text" placeholder="@...">
|
||||
</vue-tribute>
|
||||
<br />
|
||||
<h3>Textarea</h3>
|
||||
<vue-tribute :options="options">
|
||||
<textarea placeholder="@..."></textarea>
|
||||
</vue-tribute>
|
||||
<br />
|
||||
<h3>contenteditable element</h3>
|
||||
<vue-tribute :options="options">
|
||||
<div class="content-editable" contenteditable="true" placeholder="@..."></div>
|
||||
</vue-tribute>
|
||||
<br />
|
||||
<button @click="append" class="btn">Append New Item</button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import VueTribute from '../src'
|
||||
export default {
|
||||
components: {
|
||||
VueTribute
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
values: [
|
||||
{ key: 'Collin Henderson', value: 'syropian' },
|
||||
{ key: 'Sarah Drasner', value: 'sarah_edo' },
|
||||
{ key: 'Evan You', value: 'youyuxi' },
|
||||
{ key: 'Adam Wathan', value: 'adamwathan' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
append() {
|
||||
let kv = Math.random()
|
||||
.toString(36)
|
||||
.slice(2)
|
||||
this.options.values.push({
|
||||
key: kv,
|
||||
value: kv
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
body {
|
||||
background: linear-gradient(to right, #fc466b, #3f5efb);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-family: 'Helvetica Neue', 'Arial', sans-serif;
|
||||
}
|
||||
.container {
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.v-tribute {
|
||||
width: 100%;
|
||||
}
|
||||
input[type='text'],
|
||||
.content-editable {
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: #eee;
|
||||
padding: 1rem 1rem;
|
||||
color: #666;
|
||||
width: 100%;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 16px;
|
||||
outline: none;
|
||||
&:focus {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
.content-editable:empty:before {
|
||||
content: attr(placeholder);
|
||||
display: block;
|
||||
color: #666;
|
||||
}
|
||||
textarea {
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: #eee;
|
||||
padding: 1rem;
|
||||
width: 100%;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 16px;
|
||||
height: 100px;
|
||||
outline: none;
|
||||
&:focus {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
appearance: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
margin: 20px 0;
|
||||
background: #fc466b;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 1px 3px rgba(#000, 0.18);
|
||||
&:hover {
|
||||
background: darken(#fc466b, 3%);
|
||||
}
|
||||
}
|
||||
|
||||
// Tribute-specific styles
|
||||
.tribute-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: auto;
|
||||
max-height: 300px;
|
||||
max-width: 500px;
|
||||
overflow: auto;
|
||||
display: block;
|
||||
z-index: 999999;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 4px rgba(#000, 0.13);
|
||||
}
|
||||
.tribute-container ul {
|
||||
margin: 0;
|
||||
margin-top: 2px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(#000, 0.13);
|
||||
background-clip: padding-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tribute-container li {
|
||||
color: #3f5efb;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
.tribute-container li.highlight,
|
||||
.tribute-container li:hover {
|
||||
background: #3f5efb;
|
||||
color: #fff;
|
||||
}
|
||||
.tribute-container li span {
|
||||
font-weight: bold;
|
||||
}
|
||||
.tribute-container li.no-match {
|
||||
cursor: default;
|
||||
}
|
||||
.tribute-container .menu-highlighted {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
render(h) {
|
||||
return h(App)
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "vue-tribute",
|
||||
"version": "0.3.0",
|
||||
"description":
|
||||
"A Vue.js wrapper for Zurb's Tribute library for native @mentions",
|
||||
"main": "dist/vue-tribute.cjs.js",
|
||||
"module": "dist/vue-tribute.es.js",
|
||||
"unpkg": "dist/vue-tribute.min.js",
|
||||
"files": ["dist"],
|
||||
"repository": "https://github.com/syropian/vue-tribute",
|
||||
"author": "Collin Henderson <collin@syropia.net>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "bili",
|
||||
"test": "jest",
|
||||
"watch-test": "jest --watchAll",
|
||||
"example": "poi example/index.js",
|
||||
"example:build": "poi build"
|
||||
},
|
||||
"poi": {
|
||||
"entry": "example/index.js",
|
||||
"outDir": "example/dist"
|
||||
},
|
||||
"bili": {
|
||||
"format": ["cjs", "umd", "umd-min", "es"],
|
||||
"moduleName": "VueTribute"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-jest": "^22.4.1",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"bili": "^3.0.4",
|
||||
"jest": "^22.4.2",
|
||||
"node-sass": "^4.8.3",
|
||||
"poi": "^9.6.13",
|
||||
"rollup-plugin-vue": "^3.0.0",
|
||||
"sass-loader": "^6.0.7",
|
||||
"tributejs": "^3.2.0",
|
||||
"vue-test-utils": "^1.0.0-beta.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tributejs": "^2.0.0 || ^3.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import Tribute from 'tributejs'
|
||||
|
||||
const VueTribute = {
|
||||
name: 'vue-tribute',
|
||||
props: {
|
||||
options: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tribute: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const $el = this.$slots.default[0].elm
|
||||
|
||||
this.tribute = new Tribute(this.options)
|
||||
this.tribute.attach($el)
|
||||
|
||||
$el.addEventListener('tribute-replaced', e => {
|
||||
this.$emit('tribute-replaced', e)
|
||||
})
|
||||
|
||||
$el.addEventListener('tribute-no-match', e => {
|
||||
this.$emit('tribute-no-match', e)
|
||||
})
|
||||
},
|
||||
render(h) {
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
staticClass: 'v-tribute'
|
||||
},
|
||||
this.$slots.default
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && window.Vue) {
|
||||
window.Vue.component(VueTribute.name, VueTribute)
|
||||
}
|
||||
|
||||
export default VueTribute
|
||||
Reference in New Issue
Block a user