diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..3bff21e
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": [ "es2015-rollup" ]
+}
diff --git a/README.md b/README.md
index e6ee52a..b757952 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-# vue-prosemirror
+# vue-input-autosize
-> A simple Vue.js wrapper around the ProseMirror editor
+> A simple Vue.js directive for autosizing a text input based on its content.
## Install
```js
-$ npm install vue-prosemirror --save
+$ npm install vue-input-autosize --save
```
## Usage
@@ -19,4 +19,4 @@ Coming soon...
## TODO
- [ ] Tests
-- [ ] Tidy up example
+- [ ] Improve the example
diff --git a/example/app.vue b/example/app.vue
index fef3f73..f63afc7 100644
--- a/example/app.vue
+++ b/example/app.vue
@@ -1,40 +1,21 @@
-
-
+
-
diff --git a/index.js b/index.js
index cc1bac5..343496f 100644
--- a/index.js
+++ b/index.js
@@ -1,81 +1,55 @@
'use strict';
-function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
+exports.install = function (Vue, options) {
+ Vue.directive("input-autosize", {
+ mirror: null,
+ val: " ",
+ options: {},
+ bind: function bind() {
+ var _this = this;
-var prosemirror = _interopDefault(require('prosemirror'));
-var prosemirror_dist_schemaBasic = require('prosemirror/dist/schema-basic');
-var prosemirror_dist_markdown = require('prosemirror/dist/markdown');
-var prosemirror_dist_exampleSetup = require('prosemirror/dist/example-setup');
-var prosemirror_dist_menu = require('prosemirror/dist/menu');
+ var defaults = { maxWidth: 500, minWidth: 20, comfortZone: 0 };
+ this.options = Object.assign(defaults, options || {});
-var index = { template: "
",
- name: "ProseMirror",
- props: {
- content: String,
- onChange: Function,
- menuType: {
- type: String,
- default: "bar"
+ this.mirror = document.createElement("span");
+ this.mirror.classList.add("vue-input-autosize-mirror");
+ document.body.appendChild(this.mirror);
+
+ this.el.addEventListener("input", this.check.bind(this, this.el), false);
+ setTimeout(function () {
+ var styles = window.getComputedStyle(_this.el, null);
+ Object.assign(_this.mirror.style, {
+ position: "absolute",
+ top: "-9999px",
+ left: "-9999px",
+ width: "auto",
+ whiteSpace: "nowrap",
+ fontSize: styles.getPropertyValue("font-size"),
+ fontFamily: styles.getPropertyValue("font-family"),
+ fontWeight: styles.getPropertyValue("font-weight"),
+ letterSpacing: styles.getPropertyValue("letter-spacing"),
+ textTransform: styles.getPropertyValue("text-transform"),
+ ariaHidden: true
+ });
+ _this.check(_this.el);
+ }, 0);
},
- options: Object
- },
- data: function data() {
- return {
- editor: null
- };
- },
-
- computed: {
- rawMarkdown: function rawMarkdown() {
- return prosemirror_dist_markdown.defaultMarkdownSerializer.serialize(this.editor.doc);
+ update: function update() {
+ this.check(this.el);
},
- renderedContent: function renderedContent() {
- var docFrag = this.editor.doc.content.toDOM();
- var div = document.createElement("div");
- div.appendChild(docFrag.cloneNode(true));
- return div.innerHTML;
- }
- },
- ready: function ready() {
- var _this = this;
-
- var editorOptions = Object.assign({
- schema: prosemirror_dist_schemaBasic.schema,
- place: this.el,
- doc: prosemirror_dist_markdown.defaultMarkdownParser.parse(this.content),
- plugins: [prosemirror_dist_exampleSetup.exampleSetup.config({ menuBar: false, tooltipMenu: false })]
- }, this.options);
-
- if (editorOptions.doc === undefined || editorOptions.doc === null) {
- editorOptions.doc = null;
- editorOptions.docFormat = null;
- }
-
- this.editor = new prosemirror.ProseMirror(editorOptions);
-
- var menu = prosemirror_dist_exampleSetup.buildMenuItems(prosemirror_dist_schemaBasic.schema);
- if (this.menuType === "bar") {
- prosemirror_dist_menu.tooltipMenu.detach(this.editor);
- prosemirror_dist_menu.menuBar.config({ float: true, content: menu.fullMenu }).attach(this.editor);
- } else {
- prosemirror_dist_menu.menuBar.detach(this.editor);
- prosemirror_dist_menu.tooltipMenu.config({
- selectedBlockMenu: true,
- inlineContent: menu.inlineMenu,
- blockContent: menu.blockMenu
- }).attach(this.editor);
- }
-
- this.editor.on.change.add(function () {
- if (_this.onChange && typeof _this.onChange === "function") {
- _this.onChange.apply(null, [_this.rawMarkdown, _this.renderedContent]);
+ check: function check(el) {
+ this.val = el.value;
+ if (!this.val) this.val = el.placeholder || "";
+ this.mirror.innerHTML = this.val.replace(/&/g, "&").replace(/\s/g, " ").replace(//g, ">");
+ var newWidth = this.mirror.getBoundingClientRect().width + this.options.comfortZone;
+ if (newWidth > this.options.maxWidth) {
+ newWidth = this.options.maxWidth;
+ } else if (newWidth < this.options.minWidth) {
+ newWidth = this.options.minWidth;
}
- });
-
- this.$watch("content", function (val) {
- _this.editor.setDoc(prosemirror_dist_markdown.defaultMarkdownParser.parse(val));
- });
- }
-};
-
-module.exports = index;
\ No newline at end of file
+ if (newWidth != el.getBoundingClientRect().width) {
+ el.style.width = newWidth + "px";
+ }
+ }
+ });
+};
\ No newline at end of file
diff --git a/index.umd.js b/index.umd.js
new file mode 100644
index 0000000..54e8ab4
--- /dev/null
+++ b/index.umd.js
@@ -0,0 +1,61 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (factory());
+}(this, function () { 'use strict';
+
+ exports.install = function (Vue, options) {
+ Vue.directive("input-autosize", {
+ mirror: null,
+ val: " ",
+ options: {},
+ bind: function bind() {
+ var _this = this;
+
+ var defaults = { maxWidth: 500, minWidth: 20, comfortZone: 0 };
+ this.options = Object.assign(defaults, options || {});
+
+ this.mirror = document.createElement("span");
+ this.mirror.classList.add("vue-input-autosize-mirror");
+ document.body.appendChild(this.mirror);
+
+ this.el.addEventListener("input", this.check.bind(this, this.el), false);
+ setTimeout(function () {
+ var styles = window.getComputedStyle(_this.el, null);
+ Object.assign(_this.mirror.style, {
+ position: "absolute",
+ top: "-9999px",
+ left: "-9999px",
+ width: "auto",
+ whiteSpace: "nowrap",
+ fontSize: styles.getPropertyValue("font-size"),
+ fontFamily: styles.getPropertyValue("font-family"),
+ fontWeight: styles.getPropertyValue("font-weight"),
+ letterSpacing: styles.getPropertyValue("letter-spacing"),
+ textTransform: styles.getPropertyValue("text-transform"),
+ ariaHidden: true
+ });
+ _this.check(_this.el);
+ }, 0);
+ },
+ update: function update() {
+ this.check(this.el);
+ },
+ check: function check(el) {
+ this.val = el.value;
+ if (!this.val) this.val = el.placeholder || "";
+ this.mirror.innerHTML = this.val.replace(/&/g, "&").replace(/\s/g, " ").replace(//g, ">");
+ var newWidth = this.mirror.getBoundingClientRect().width + this.options.comfortZone;
+ if (newWidth > this.options.maxWidth) {
+ newWidth = this.options.maxWidth;
+ } else if (newWidth < this.options.minWidth) {
+ newWidth = this.options.minWidth;
+ }
+ if (newWidth != el.getBoundingClientRect().width) {
+ el.style.width = newWidth + "px";
+ }
+ }
+ });
+ };
+
+}));
\ No newline at end of file
diff --git a/package.json b/package.json
index 23d6c30..ad1cb3f 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,9 @@
{
- "name": "vue-prosemirror",
- "version": "0.1.2",
- "description": "A simple Vue.js wrapper around the ProseMirror editor",
+ "name": "vue-input-autosize",
+ "version": "0.1.0",
+ "description": "A simple Vue.js directive to autosize text input fields",
"license": "MIT",
- "repository": "syropian/vue-prosemirror",
+ "repository": "syropian/vue-input-autosize",
"author": {
"name": "Collin Henderson",
"email": "collin@syropia.net",
@@ -13,9 +13,11 @@
"node": ">=4"
},
"scripts": {
+ "build:all": "npm run build && npm run build:umd",
"build": "BUILD_ENV=cjs rollup -c",
+ "build:umd": "BUILD_ENV=umd rollup -c",
"example": "vbuild --dev -e example",
- "example:build": "vbuild -e example -t VueProsemirror"
+ "example:build": "vbuild -e example -t VueInputAutosize"
},
"main": "index.js",
"files": [
@@ -23,18 +25,16 @@
"index.umd.js"
],
"keywords": [
- "prosemirror",
- "editor",
- "markdown",
+ "autosize",
+ "autogrow",
+ "autoshrink",
+ "input",
"Vue"
],
- "dependencies": {
- "prosemirror": "^0.8.3"
- },
+ "dependencies": {},
"devDependencies": {
"babel-preset-es2015-rollup": "^1.1.1",
"rollup": "^0.33.0",
- "rollup-plugin-babel": "^2.6.1",
- "rollup-plugin-vue": "^2.0.1"
+ "rollup-plugin-babel": "^2.6.1"
}
}
diff --git a/rollup.config.js b/rollup.config.js
index 0daa655..29a8a8a 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,16 +1,17 @@
import { rollup } from "rollup"
import babel from "rollup-plugin-babel"
-import vue from "rollup-plugin-vue";
const env = process.env.BUILD_ENV
const dest = env === "cjs" ? "index.js" : "index.umd.js"
export default {
- entry: "./src/index.vue",
- dest,
+ entry: "./src/index.js",
plugins: [
- vue()
+ babel({
+ exclude: "node_modules/**"
+ })
],
+ dest,
format: env,
- moduleName: "VueProseMirror"
+ moduleName: "VueInputAutosize"
}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..8e8616a
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,49 @@
+"use strict";
+
+exports.install = function(Vue, options){
+ Vue.directive("input-autosize", {
+ mirror: null,
+ val: " ",
+ options: {},
+ bind(){
+ const defaults = { maxWidth: 500, minWidth: 20, comfortZone: 0 };
+ this.options = Object.assign(defaults, options || {});
+
+ this.mirror = document.createElement("span");
+ this.mirror.classList.add("vue-input-autosize-mirror");
+ document.body.appendChild(this.mirror);
+
+ this.el.addEventListener("input", this.check.bind(this, this.el), false);
+ setTimeout(() => {
+ let styles = window.getComputedStyle(this.el, null);
+ Object.assign(this.mirror.style, {
+ position: "absolute",
+ top: "-9999px",
+ left: "-9999px",
+ width: "auto",
+ whiteSpace: "nowrap",
+ fontSize: styles.getPropertyValue("font-size"),
+ fontFamily: styles.getPropertyValue("font-family"),
+ fontWeight: styles.getPropertyValue("font-weight"),
+ letterSpacing: styles.getPropertyValue("letter-spacing"),
+ textTransform: styles.getPropertyValue("text-transform"),
+ ariaHidden: true
+ });
+ this.check(this.el);
+ }, 0)
+ },
+ update(){
+ this.check(this.el);
+ },
+ check(el){
+ this.val = el.value;
+ if (!this.val) this.val = el.placeholder || "";
+ this.mirror.innerHTML = this.val.replace(/&/g, "&").replace(/\s/g, " ").replace(//g, ">");
+ let newWidth = this.mirror.getBoundingClientRect().width + this.options.comfortZone;
+ if( newWidth > this.options.maxWidth ){ newWidth = this.options.maxWidth; }
+ else if (newWidth < this.options.minWidth){ newWidth = this.options.minWidth; }
+ if( newWidth != el.getBoundingClientRect().width ){ el.style.width = `${newWidth}px`; }
+ }
+ });
+
+}
diff --git a/src/index.vue b/src/index.vue
deleted file mode 100644
index a826996..0000000
--- a/src/index.vue
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-