Categories
Top Vue Packages

Top Vue Packages for Adding Fragments, Icons, Download Excel Files, and More

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how the best packages for adding fragments, icons, download JSON data as Excel files, and detecting idle and resizing.

vue-fragment

vue-fragment lets us render fragments in Vue apps.

A fragment is a component that doesn’t render any wrapper element.

To use it, we run:

npm i vue-fragment

to install it.

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import { Plugin } from "vue-fragment";
Vue.use(Plugin);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <fragment>
      <p>hello</p>
    </fragment>
  </div>
</template>

<script>
export default {};
</script>

Vue Material Design Icon Components

Vue Material Design Icon Components is a package with Material Design icons that we can use.

To use it, we run:

npm i vue-material-design-icons

to install it.

Then we use it by writing:

<template>
  <div id="app">
    <menu-icon/>
  </div>
</template>

<script>
import MenuIcon from "vue-material-design-icons/Menu.vue";

export default {
  components: {
    MenuIcon
  }
};
</script>

We import the icon component so that we can use it in our template.

Also, we can change the size:

<template>
  <div id="app">
    <menu-icon :size="48"/>
  </div>
</template>

<script>
import MenuIcon from "vue-material-design-icons/Menu.vue";

export default {
  components: {
    MenuIcon
  }
};
</script>

vue-json-excel

JSON to Excel for VUE 2 is a package that lets us convert JSON data to Excel files and download it.

To use it, first we install it by running:

npm i vue-json-excel

Then we can use it by writing:

<template>
  <div id="app">
    <download-excel name="filename.xls" :fields="jsonFields" :data="jsonData">Download Data</download-excel>
  </div>
</template>

<script>
export default {
  data() {
    return {
      jsonFields: {
        "first name": "name",
        phone: {
          field: "phone.landline",
          callback: value => {
            return `landline Phone - ${value}`;
          }
        }
      },
      jsonData: [
        {
          name: "james",
          phone: {
            landline: "(541) 754-3010"
          }
        },
        {
          name: "alex",
          phone: {
            landline: "(463) 582-2244"
          }
        }
      ]
    };
  }
};
</script>

We use the download-excel component to add an element that downloads some JSON to our computer.

name is the file name,

fields is the fields that we have as headings.

It’s an object with the key being the heading. The value is a property in our jsonData array entries.

It can also be a callback that formats the data the way we like.

If it’s nested, then we need to specify the field property with the path to the property.

jsonData is the data we want to have in our Excel file.

The fields can be any structure.

idle-vue

idle-vue is a Vue plugin that can detect situations when a user hasn’t interacted with our app in a while.

To use it, we can install it by running:

npm i idle-vue

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import IdleVue from "idle-vue";

const eventsHub = new Vue();

Vue.use(IdleVue, {
  eventEmitter: eventsHub,
  idleTime: 2000
});
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

We register the plugin by passing in an object with the eventEmitter property set to a new Vue instance.

This lets us send app-wide events.

idleTime lets us set the idle timeout in milliseconds.

The idle event will be emitted when the timeout is up.

App.vue

<template>
  <div id="app">{{messageStr}}</div>
</template>

<script>
export default {
  data() {
    return {
      messageStr: ""
    };
  },
  onIdle() {
    this.messageStr = "idle";
  },
  onActive() {
    this.messageStr = "hello";
  }
};
</script>

vue-resize-sensor

vue-resize-sensor is a Vue plugin that detects element resizing.

We install it by running:

npm i vue-resize-sensor

Then we can use it by writing:

<template>
  <div id="app">
    <resize-sensor @resize="resize"></resize-sensor>
  </div>
</template>

<script>
import ResizeSensor from "vue-resize-sensor";

export default {
  components: {
    ResizeSensor
  },
  methods: {
    resize({ width, height }) {
      console.log(width, height);
    }
  }
};
</script>

We use the resize-sensor component.

Whenever the component resizes, resize is called.

Conclusion

vue-fragment is a component that lets us add wrapper components that don’t render anything.

Vue Material Design Icon Components provides us with icons we can use in our Vue app.

vue-json-excel lets us download JSON data as Excel spreadsheets.

idle-vue lets us detect when a Vue app is idle.

vue-resize-sensor lets us detect resizing of elements.

Categories
Top Vue Packages

Top Vue Packages for Watching Resizing, Display Relative Time, and More

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how the best packages for watching element resizing, display relative time, adding split panes, and copying data to the clipboard.

Vue.resize

Vue.resize is a package that lets us detect HTML resize events.

To install it, we run:

npm i vue-resize-directive

Then we can use it by writing:

<template>
  <div id="app">
    <div
      v-resize="onResize"
    >Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc nec elit ornare, sollicitudin lacus vel, volutpat ipsum. Aliquam vel erat sodales, faucibus dolor vel, ultricies augue. Morbi a posuere eros. Nulla bibendum tristique massa vel volutpat. Aenean in odio erat. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam eros dolor, viverra ac arcu ac, venenatis commodo lectus.</div>
  </div>
</template>

<script>
import resize from "vue-resize-directive";

export default {
  directives: {
    resize
  },
  methods: {
    onResize(e) {
      console.log(e);
    }
  }
};
</script>

We register the directive and use the v-resize directive.

We can throttle or denounce the listeners being called.

vue-numeric

vue-numeric is an input field component to display a formatted currency value.

To use it, we run:

npm i vue-numeric

Then we can use it by writing

<template>
  <div>
    <vue-numeric currency="$" separator="," v-model="price"></vue-numeric>
    <p>{{price}}</p>
  </div>
</template>

<script>
import VueNumeric from "vue-numeric";

export default {
  name: "App",
  components: {
    VueNumeric
  },
  data() {
    return {
      price: ""
    };
  }
};
</script>

We use the vue-numeric component.

The currency is the currency symbol to display on the left.

separator is the thousands separator.

v-model binds the inputted value to the price state.

We can also change the precision, enable or disable negative values, and more.

Vue Split Pane

Vue Split Pane is a component that lets us display split panes.

To install it, we run:

npm i vue-splitpane

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import splitPane from "vue-splitpane";
Vue.component("split-pane", splitPane);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div>
    <split-pane v-on:resize="resize" :min-percent="20" :default-percent="30" split="vertical">
      <template slot="paneL">left</template>
      <template slot="paneR">right</template>
    </split-pane>
  </div>
</template>

<script>
export default {
  methods: {
    resize() {}
  }
};
</script>

We use the split-pane component by populating the bundled slots with our own content.

panelL is the left panel.

panelR is the right panel.

The panes can be nested.

v-clipboard

v-clipboard is a plugin that lets us copy the content that we want from our Vue app to the user’s clipboard.

To install it, we run:

npm i v-clipboard

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import Clipboard from "v-clipboard";

Vue.use(Clipboard);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <button v-clipboard="value">Copy to clipboard</button>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: "foo"
    };
  }
};
</script>

Whatever we passed into the v-clipboard directive will be copied.

It also emits success and error events.

We can listen to them by writing:

<template>
  <div id="app">
    <button
      v-clipboard="value"
      v-clipboard:success="clipboardSuccessHandler"
      v-clipboard:error="clipboardErrorHandler"
    >Copy to clipboard</button>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: "foo"
    };
  },

  methods: {
    clipboardSuccessHandler({ value, event }) {
      console.log("success", value);
    },

  clipboardErrorHandler({ value, event }) {
      console.log("error", value);
    }
  }
};
</script>

We can also use the this.$clipboard property to the copying:

<template>
  <div id="app">
    <button @click="copy">Copy to clipboard</button>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: "foo"
    };
  },

  methods: {
    copy() {
      this.$clipboard(this.value);
    }
  }
};
</script>

vue-timeago

vue-timeago is a component that lets us display relative time from today.

To install it, we run:

npm i vue-timeago

Then we can use it bu writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueTimeago from "vue-timeago";

Vue.use(VueTimeago, {
  name: "Timeago",
  locale: "en"
});

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <timeago :datetime="time"></timeago>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      time: new Date(2020, 1, 1)
    };
  }
};
</script>

We register the plugin and set the locale as we do it.

Then we can use the timeago component.

The datetime prop is passed in to calculate and display the relative time from today.

Conclusion

Vue.resize lets us watch for element resize events.

vue-numeric is a numeric input for entering currencies.

Vue Split Pane lets us create split panes with ease.

v-clipboard is a plugin for letting users copy data to the clipboard.

vue-timeago lets us display relative time from today.

Categories
Top Vue Packages

Top Vue Packages for Handling Events, Adding Progress Bars, and Truncate Text

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at the best packages for handling events, adding utility methods, progress bars, and truncating text.

vue-events

vue-events is a simple event to send and receive events.

To install it, we run:

npm i vue-events

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueEvents from "vue-events";
Vue.use(VueEvents);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div></div>
</template>

<script>
export default {
  name: "app",
  data() {
    return {
      eventData: { foo: "bar" }
    };
  },
  created() {
    this.$events.fire("event", this.eventData);
    this.$events.emit("event", this.eventData);
    this.$events.$emit("event", this.eventData);
  },
  mounted() {
    this.$events.on("event", eventData => console.log(eventData));
  },

  beforeDestroy() {
    this.$events.$off("event");
    this.$events.off("event");
    this.$events.remove("event");
  }
};
</script>

We register the VueEvents plugin.

Then we send events with fire , emit , or $emit with some data in the 2nd argument.

We listen to events with on .

And we clear event listeners with $off , off , or remove .

vue-underscore

We can use vue-underscore to add underscore to a Vue app.

To use it, we run:

npm i vue-underscore

to install it.

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import underscore from "vue-underscore";
Vue.use(underscore);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div></div>
</template>

<script>
export default {
  mounted() {
    const arr = [{ id: 1 }, { id: 2 }];
    const found = this.$_.findWhere(arr, { id: 1 });
    console.log(found);
  }
};
</script>

Once we registered the plugin, we can use the this.$_ property to access its methods.

We can also access the library directly:

<template>
  <div></div>
</template>

<script>
import { _ } from "vue-underscore";

export default {
  mounted() {
    const arr = [{ id: 1 }, { id: 2 }];
    const found = _.findWhere(arr, { id: 1 });
    console.log(found);
  }
};
</script>

Vue Masked Input

Vue Masked Input is a masked input component for Vue apps.

To install it, we run:

npm i vue-masked-input

Then we can use it by writing:

<template>
  <div>
    <masked-input v-model="date" mask="11/11/1111" placeholder="dd/mm/yyyy"/>
  </div>
</template>

<script>
import MaskedInput from "vue-masked-input";

export default {
  data() {
    return {
      date: ""
    };
  },
  components: {
    MaskedInput
  }
};
</script>

We register the masked-input component and used it.

It can bind the input value to a state with v-model .

Also, the input format is restricted by the mask prop.

It has to be the same format.

The mask can have alphabets or other characters in addition to numbers.

vue-top-progress

vue-top-progress is a progress bar component for Vue apps.

To install it, we run:

npm i vue-top-progress

Then we write:

<template>
  <div>
    <vue-topprogress ref="topProgress"></vue-topprogress>
  </div>
</template>

<script>
import { vueTopprogress } from "vue-top-progress";

export default {
  mounted() {
    this.$refs.topProgress.start();

    setTimeout(() => {
      this.$refs.topProgress.done();
    }, 2000);
  },

  components: {
    vueTopprogress
  }
};
</script>

to use it.

We add the vue-topprogress component.

The ref is set to topProgress so we can call start to display the progress bar.

We call done to make it disappear.

Color and speed can be changed.

Vue Line Clamp

Vue Line Clamp is a directive that lets us truncate text.

To install it, we run:

npm i vue-line-clamp

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import lineClamp from "vue-line-clamp";

Vue.use(lineClamp, {});
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div>
    <p
      v-line-clamp:20="2"
    >Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sit amet tortor vulputate, faucibus nulla eu, fringilla ligula. Nunc et aliquet justo. Nulla sit amet risus eu metus volutpat tincidunt. Pellentesque vehicula, erat eu dignissim maximus, diam leo egestas massa, non tincidunt arcu quam placerat eros. Nullam at nunc id ante cursus dignissim non ac libero. Praesent posuere, velit ut varius feugiat, arcu enim sollicitudin odio, eu sagittis dolor massa eget urna. Pellentesque in faucibus arcu, non dignissim arcu. Integer porta sodales tortor sed cursus. Suspendisse at finibus urna. Sed id venenatis ex. Nunc quis dictum velit, a hendrerit enim. Phasellus interdum, tellus quis congue fringilla, tortor sem maximus ante, vel tempus lorem risus nec est. Proin ullamcorper non felis sed gravida. In feugiat laoreet tellus, eget dictum lectus laoreet in. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum in blandit metus.</p>
  </div>
</template>

<script>
export default {};
</script>

We registered the lineClamp plugin.

Then we used the v-line-clamp directive to truncate the text.

Conclusion

vue-events lets us emit and listen to custom events.

vue-underscore lets us incorporate underscore into our app.

vue-top-progress lets us display a progress bar.

Vue Line Clamp lets us truncate text.

Categories
Top Vue Packages

Top Vue Packages for Adding Mixins, Date Pickers, Input Masks, and Carousels

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps. In this article, we’ll look at the best packages for adding mixins, date pickers, input masks, and carousels.

vue-mixins

vue-mixins is a set of mixins that we can use in Vue.

To install it, we run:

npm i vue-mixins

Then we can write:

App.vue

<template>
  <div id="app"></div>
</template>

<script>
export default {
  mixins: [require("vue-mixins/onClick")],
  mounted() {
    this.onClick = function(){
      console.log('clicked')
    }
    this.click();
  }
};
</script>

We include the mixin that comes with the package.

Then we set the onClick method to what we want so that we can use it.

Then we can call the this.click method that comes with the mixin to trigger it.

It can listen and trigger to many other events like window resize, element resizes, scroll, setting dynamic CSS, and much more.

Flickity for Vue.js

Flickity for Vue.js is a package that lets us add a carousel to display whatever we want.

To install it, we run:

npm i vue-flickity

Then we can use it by writing:

<template>
  <div id="app">
    <flickity ref="flickity" :options="flickityOptions">
      <div class="carousel-cell" v-for="n in 10" :key="n">{{n}}</div>
    </flickity>
    <button @click="previous()">Previous</button>
    <button @click="next()">Next</button>
  </div>
</template>

<script>
import Flickity from "vue-flickity";

export default {
  components: {
    Flickity
  },
  data() {
    return {
      flickityOptions: {
        initialIndex: 3,
        prevNextButtons: false,
        pageDots: false,
        wrapAround: true
      }
    };
  },
  methods: {
    next() {
      this.$refs.flickity.next();
    },

    previous() {
      this.$refs.flickity.previous();
    }
  }
};
</script>

We use the flickity component to display the carousel.

We also add buttons to navigate through the slides.

Vue input mask

Vue input mask is an input mask directive that’s added onto the input element to create an input mask.

To install it, we run:

npm i v-mask

Then we can use it by writing:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueMask from "v-mask";
Vue.use(VueMask);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <input type="text" v-mask="'###-###'" v-model="num">
  </div>
</template>

<script>
export default {
  data() {
    return {
      num: 0
    };
  }
};
</script>

We have the v-mask directive to format the number.

Also, we can use it as a filter:

<template>
  <div id="app">
    <span>{{ '1234567890' | VMask('(###) ###-####') }}</span>
  </div>
</template>

<script>
export default {};
</script>

We can set the format using the VMask filter.

Also, we can it to letters, numbers, or make characters optional.

vue-datepicker

We can use the vue-datepicker package to display a date picker that we can use to let users select dates.

To use it, we install it by running:

npm i vue-datepicker

Then we can use it by writing:

<template>
  <div id="app">
    <date-picker :date="startTime" :option="option" :limit="limit"></date-picker>
  </div>
</template>

<script>
import myDatepicker from "vue-datepicker";

export default {
  data() {
    return {
      startTime: {
        time: ""
      },
      endtime: {
        time: ""
      },
      option: {
        type: "day",
        week: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
        month: [
          "January",
          "February",
          "March",
          "April",
          "May",
          "June",
          "July",
          "August",
          "September",
          "October",
          "November",
          "December"
        ],
        format: "YYYY-MM-DD",
        placeholder: "start time",
        inputStyle: {
          padding: "6px",
          "line-height": "22px",
          color: "#5F5F5F"
        },
        color: {
          header: "#ccc",
          headerText: "#f00"
        },
        buttons: {
          ok: "Ok",
          cancel: "Cancel"
        },
        overlayOpacity: 0.5,
        dismissible: true
      },
      timeoption: {
        type: "min",
        week: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
        month: [
          "January",
          "February",
          "March",
          "April",
          "May",
          "June",
          "July",
          "August",
          "September",
          "October",
          "November",
          "December"
        ],
        format: "YYYY-MM-DD HH:mm"
      },
      multiOption: {
        type: "multi-day",
        week: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
        month: [
          "January",
          "February",
          "March",
          "April",
          "May",
          "June",
          "July",
          "August",
          "September",
          "October",
          "November",
          "December"
        ],
        format: "YYYY-MM-DD HH:mm"
      },
      limit: [
        {
          type: "weekday",
          available: [1, 2, 3, 4, 5]
        },
        {
          type: "fromto",
          from: "2020-02-01",
          to: "2020-12-20"
        }
      ]
    };
  },
  components: {
    "date-picker": myDatepicker
  }
};
</script>

We can set many options. The month and day names can be set. placeholder sets the placeholder. inputStyle sets the input style. Also, we can use the limit property to limit the date range.

Conclusion

vue-mixins provides with a set of mixins to trigger and watch events. Flickity for Vue.js lets us add carousels to our code. Vue input mask lets us add an input mask to an input. vue-datepicker is a date picker that we can use to let users select dates.

Categories
Top Vue Packages

Top Vue Packages for Animating Numbers, Handling Clicks, Edit Markdown, and More

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at the best packages for animating numbers, handling clicks outside an element, adding a Markdown editor, and a customizable dropdown.

vue-countup-v2

vue-countup-v2 lets us add a display for animating numbers.

To use it, we install it by running:

npm install --save countup.js vue-countup-v2

We’ve to add countup.js to use vue-countup-v2.

Then we can use it by writing:

<template>
  <div id="app">
    <ICountUp :delay="delay" :endVal="endVal" :options="options" @ready="onReady"/>
  </div>
</template>

<script>
import ICountUp from "vue-countup-v2";
export default {
  components: {
    ICountUp
  },
  data() {
    return {
      delay: 1000,
      endVal: 45373,
      options: {
        useEasing: true,
        useGrouping: true,
        separator: ",",
        decimal: ".",
        prefix: "",
        suffix: ""
      }
    };
  },
  methods: {
    onReady(instance, CountUp) {
      const that = this;
      instance.update(that.endVal + 100);
    }
  }
};
</script>

We can set many options.

We set the endVal to set the end value to animate.

delay is the delay for the animation.

useEasing lets us animate in a nonlinear fashion.

useGrouping groups the digits.

decimal is the decimal digits separator.

prefix and suffix are prefixes and suffixes that are added to the number.

Vue-SimpleMDE

Vue-SimpleMDE is a simple Markdown editor component for Vue apps.

To use it, we first install it by running:

npm i vue-simplemde

Then we can use it by writing:

<template>
  <vue-simplemde v-model="content" ref="markdownEditor"/>
</template>

<script>
import VueSimplemde from "vue-simplemde";
import "simplemde/dist/simplemde.min.css";

export default {
  components: {
    VueSimplemde
  },
  data() {
    return {
      content: ""
    };
  }
};
</script>

We just add the vue-simplemde component to our app.

Also, we imported the CSS for the package.

The inputted value is bound to the content with the v-model .

vue-search-select

vue-search-select provides us with a dropdown that’s customizable.

To use it, we run:

npm i vue-search-select

to install it.

Then we can use it by writing:

<template>
  <model-select :options="options" v-model="item" placeholder="select item"></model-select>
</template>

<script>
import { ModelSelect } from "vue-search-select";
import "vue-search-select/dist/VueSearchSelect.css";

export default {
  data() {
    return {
      options: [
        { value: "1", text: "foo" },
        { value: "2", text: "bar" },
        { value: "3", text: "baz" }
      ],
      item: {
        value: "",
        text: ""
      }
    };
  },
  components: {
    ModelSelect
  }
};
</script>

We use the model-select component.

The options prop sets the dropdown options.

v-model binds the item to the item .

vue-tel-input

vue-tel-input lets us ad a telephone number to our Vue app.

To use it, we install it by running:

npm i vue-tel-input

Then we can use it by writing:

<template>
  <div>
    <vue-tel-input v-model="phone"></vue-tel-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      phone: ""
    };
  }
};
</script>

We see a dropdown with the list of country prefixes for the phone numbers.

And we can type what we want into the vue-tel-input component.

v-model lets us bind the input value to the phone state.

vue-on-click-outside

vue-on-click-outside is a Vue directive that lets us call a method whenever a click is triggered outside the element.

To install it, we run:

npm i vue-on-click-outside

Then we can use it by writing:

<template>
  <div>
    <button type="button" @click="open">open</button>
    <div v-if="showPopover" v-on-click-outside="close">
      <span>hello</span>
    </div>
  </div>
</template>

<script>
import { mixin as onClickOutside } from "vue-on-click-outside";
export default {
  mixins: [onClickOutside],
  data() {
    return { showPopover: false };
  },
  methods: {
    open() {
      this.showPopover = true;
    },
    close() {
      this.showPopover = false;
    }
  }
};
</script>

We have a button to open a popup.

The popup has the v-on-click-outside directive to close it when we click outside the popup.

The closing is done by calling the close method.

Conclusion

vue-countup-v2 lets us animate numbers.

Vue-SimpleMDE lets us add a Markdown editor to our Vue app.

vue-tel-input is a useful telephone input.

vue-on-click-outside lets us handle clicks outside an element.