├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.js
├── demo
├── Demo.vue
├── index.html
└── main.js
├── deploy-docs.sh
├── dist
├── vue-textarea-autosize.common.js
├── vue-textarea-autosize.esm.js
├── vue-textarea-autosize.umd.js
└── vue-textarea-autosize.umd.min.js
├── docs
├── .vuepress
│ ├── config.js
│ └── plugin.js
├── README.md
└── guide.md
├── package-lock.json
├── package.json
└── src
├── App.vue
├── assets
└── logo.png
├── components
└── TextareaAutosize.vue
├── index.js
├── main.js
└── plugin.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | public
4 | dist/*.gz
5 | dist/*.map
6 | coverage
7 | docs/.vuepress/dist
8 |
9 | # local env files
10 | .env.local
11 | .env.*.local
12 |
13 | # related test files
14 | /tests/e2e/reports
15 | /tests/e2e/videos
16 | /tests/e2e/screenshots
17 |
18 | # editor directories and files
19 | .idea
20 | .vscode
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw*
26 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 | ## [1.1.0] - 2019-09-07
8 | ### Changed
9 | - make `minHeight` and `maxHeight` props reactive. by [#17](https://github.com/devstark-com/vue-textarea-autosize/issues/17) from [@deathg0d](https://github.com/deathg0d)
10 | - rewrite textarea height updating in the data-first manner. by [#15](https://github.com/devstark-com/vue-textarea-autosize/issues/15) from [@danielSONCCO](https://github.com/danielSONCCO)
11 | - rebuild the plugin with [vue-cli-plugin-p11n](https://github.com/kazupon/vue-cli-plugin-p11n)
12 | - update README.md
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-textarea-autosize
2 |
3 | [ ](https://www.npmjs.com/package/vue-textarea-autosize)
4 | [](https://vuejs.org/)
5 |
6 | ---
7 |
8 | The plugin for [Vue.js](http://vuejs.org) provides the Vue component implements textarea with automatically adjustable height and without any wrappers and dependencies.
9 |
10 | # Demo
11 | HERE
12 |
13 | # Docs
14 | HERE
15 |
16 | ---
17 |
18 | ## License
19 |
20 | [MIT](http://opensource.org/licenses/MIT)
21 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/demo/Demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
vue-textarea-autosize demo
4 |
7 |
8 |
9 |
19 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-textarea-autosize demo
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from '../src/App.vue'
3 | import plugin from '../src/index'
4 |
5 | Vue.use(plugin)
6 |
7 | Vue.config.productionTip = false
8 |
9 | new Vue({
10 | // NOTE: if you need to inject as option, you can set here!
11 | plugin,
12 | render: h => h(App)
13 | }).$mount('#app')
14 |
--------------------------------------------------------------------------------
/deploy-docs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # abort on errors
4 | set -e
5 |
6 | # build
7 | npm run docs:build
8 |
9 | # navigate into the build output directory
10 | cd docs/.vuepress/dist
11 |
12 | # if you are deploying to a custom domain
13 | # echo 'www.example.com' > CNAME
14 |
15 | git init
16 | git add -A
17 | git commit -m 'deploy'
18 |
19 | # if you are deploying to https://.github.io
20 | # git push -f git@github.com:/.github.io.git master
21 |
22 | # if you are deploying to https://.github.io/
23 | git push -f git@github.com:devstark-com/vue-textarea-autosize.git master:gh-pages
24 |
--------------------------------------------------------------------------------
/dist/vue-textarea-autosize.common.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-textarea-autosize v1.1.1
3 | * (c) 2019 Saymon
4 | * Released under the MIT License.
5 | */
6 | 'use strict';
7 |
8 | //
9 | //
10 | //
11 | //
12 | //
13 | //
14 | //
15 | var script = {
16 | name: 'TextareaAutosize',
17 | props: {
18 | value: {
19 | type: [String, Number],
20 | default: ''
21 | },
22 | autosize: {
23 | type: Boolean,
24 | default: true
25 | },
26 | minHeight: {
27 | type: [Number],
28 | 'default': null
29 | },
30 | maxHeight: {
31 | type: [Number],
32 | 'default': null
33 | },
34 |
35 | /*
36 | * Force !important for style properties
37 | */
38 | important: {
39 | type: [Boolean, Array],
40 | default: false
41 | }
42 | },
43 | data: function data() {
44 | return {
45 | // data property for v-model binding with real textarea tag
46 | val: null,
47 | // works when content height becomes more then value of the maxHeight property
48 | maxHeightScroll: false,
49 | height: 'auto'
50 | };
51 | },
52 | computed: {
53 | computedStyles: function computedStyles() {
54 | if (!this.autosize) return {};
55 | return {
56 | resize: !this.isResizeImportant ? 'none' : 'none !important',
57 | height: this.height,
58 | overflow: this.maxHeightScroll ? 'auto' : !this.isOverflowImportant ? 'hidden' : 'hidden !important'
59 | };
60 | },
61 | isResizeImportant: function isResizeImportant() {
62 | var imp = this.important;
63 | return imp === true || Array.isArray(imp) && imp.includes('resize');
64 | },
65 | isOverflowImportant: function isOverflowImportant() {
66 | var imp = this.important;
67 | return imp === true || Array.isArray(imp) && imp.includes('overflow');
68 | },
69 | isHeightImportant: function isHeightImportant() {
70 | var imp = this.important;
71 | return imp === true || Array.isArray(imp) && imp.includes('height');
72 | }
73 | },
74 | watch: {
75 | value: function value(val) {
76 | this.val = val;
77 | },
78 | val: function val(_val) {
79 | this.$nextTick(this.resize);
80 | this.$emit('input', _val);
81 | },
82 | minHeight: function minHeight() {
83 | this.$nextTick(this.resize);
84 | },
85 | maxHeight: function maxHeight() {
86 | this.$nextTick(this.resize);
87 | },
88 | autosize: function autosize(val) {
89 | if (val) this.resize();
90 | }
91 | },
92 | methods: {
93 | resize: function resize() {
94 | var _this = this;
95 |
96 | var important = this.isHeightImportant ? 'important' : '';
97 | this.height = "auto".concat(important ? ' !important' : '');
98 | this.$nextTick(function () {
99 | var contentHeight = _this.$el.scrollHeight + 1;
100 |
101 | if (_this.minHeight) {
102 | contentHeight = contentHeight < _this.minHeight ? _this.minHeight : contentHeight;
103 | }
104 |
105 | if (_this.maxHeight) {
106 | if (contentHeight > _this.maxHeight) {
107 | contentHeight = _this.maxHeight;
108 | _this.maxHeightScroll = true;
109 | } else {
110 | _this.maxHeightScroll = false;
111 | }
112 | }
113 |
114 | var heightVal = contentHeight + 'px';
115 | _this.height = "".concat(heightVal).concat(important ? ' !important' : '');
116 | });
117 | return this;
118 | }
119 | },
120 | created: function created() {
121 | this.val = this.value;
122 | },
123 | mounted: function mounted() {
124 | this.resize();
125 | }
126 | };
127 |
128 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier
129 | /* server only */
130 | , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
131 | if (typeof shadowMode !== 'boolean') {
132 | createInjectorSSR = createInjector;
133 | createInjector = shadowMode;
134 | shadowMode = false;
135 | } // Vue.extend constructor export interop.
136 |
137 |
138 | var options = typeof script === 'function' ? script.options : script; // render functions
139 |
140 | if (template && template.render) {
141 | options.render = template.render;
142 | options.staticRenderFns = template.staticRenderFns;
143 | options._compiled = true; // functional template
144 |
145 | if (isFunctionalTemplate) {
146 | options.functional = true;
147 | }
148 | } // scopedId
149 |
150 |
151 | if (scopeId) {
152 | options._scopeId = scopeId;
153 | }
154 |
155 | var hook;
156 |
157 | if (moduleIdentifier) {
158 | // server build
159 | hook = function hook(context) {
160 | // 2.3 injection
161 | context = context || // cached call
162 | this.$vnode && this.$vnode.ssrContext || // stateful
163 | this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional
164 | // 2.2 with runInNewContext: true
165 |
166 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
167 | context = __VUE_SSR_CONTEXT__;
168 | } // inject component styles
169 |
170 |
171 | if (style) {
172 | style.call(this, createInjectorSSR(context));
173 | } // register component module identifier for async chunk inference
174 |
175 |
176 | if (context && context._registeredComponents) {
177 | context._registeredComponents.add(moduleIdentifier);
178 | }
179 | }; // used by ssr in case component is cached and beforeCreate
180 | // never gets called
181 |
182 |
183 | options._ssrRegister = hook;
184 | } else if (style) {
185 | hook = shadowMode ? function () {
186 | style.call(this, createInjectorShadow(this.$root.$options.shadowRoot));
187 | } : function (context) {
188 | style.call(this, createInjector(context));
189 | };
190 | }
191 |
192 | if (hook) {
193 | if (options.functional) {
194 | // register for functional component in vue file
195 | var originalRender = options.render;
196 |
197 | options.render = function renderWithStyleInjection(h, context) {
198 | hook.call(context);
199 | return originalRender(h, context);
200 | };
201 | } else {
202 | // inject component registration as beforeCreate hook
203 | var existing = options.beforeCreate;
204 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
205 | }
206 | }
207 |
208 | return script;
209 | }
210 |
211 | var normalizeComponent_1 = normalizeComponent;
212 |
213 | /* script */
214 | const __vue_script__ = script;
215 |
216 | /* template */
217 | var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('textarea',{directives:[{name:"model",rawName:"v-model",value:(_vm.val),expression:"val"}],style:(_vm.computedStyles),domProps:{"value":(_vm.val)},on:{"focus":_vm.resize,"input":function($event){if($event.target.composing){ return; }_vm.val=$event.target.value;}}})};
218 | var __vue_staticRenderFns__ = [];
219 |
220 | /* style */
221 | const __vue_inject_styles__ = undefined;
222 | /* scoped */
223 | const __vue_scope_id__ = undefined;
224 | /* module identifier */
225 | const __vue_module_identifier__ = undefined;
226 | /* functional template */
227 | const __vue_is_functional_template__ = false;
228 | /* style inject */
229 |
230 | /* style inject SSR */
231 |
232 |
233 |
234 | var TextareaAutosize = normalizeComponent_1(
235 | { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
236 | __vue_inject_styles__,
237 | __vue_script__,
238 | __vue_scope_id__,
239 | __vue_is_functional_template__,
240 | __vue_module_identifier__,
241 | undefined,
242 | undefined
243 | );
244 |
245 | var version = '1.1.1';
246 |
247 | var install = function install(Vue) {
248 | Vue.component('TextareaAutosize', TextareaAutosize);
249 | };
250 |
251 | var plugin = {
252 | install: install,
253 | version: version
254 | };
255 |
256 | if (typeof window !== 'undefined' && window.Vue) {
257 | window.Vue.use(plugin);
258 | }
259 |
260 | module.exports = plugin;
261 |
--------------------------------------------------------------------------------
/dist/vue-textarea-autosize.esm.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-textarea-autosize v1.1.1
3 | * (c) 2019 Saymon
4 | * Released under the MIT License.
5 | */
6 | //
7 | //
8 | //
9 | //
10 | //
11 | //
12 | //
13 | var script = {
14 | name: 'TextareaAutosize',
15 | props: {
16 | value: {
17 | type: [String, Number],
18 | default: ''
19 | },
20 | autosize: {
21 | type: Boolean,
22 | default: true
23 | },
24 | minHeight: {
25 | type: [Number],
26 | 'default': null
27 | },
28 | maxHeight: {
29 | type: [Number],
30 | 'default': null
31 | },
32 |
33 | /*
34 | * Force !important for style properties
35 | */
36 | important: {
37 | type: [Boolean, Array],
38 | default: false
39 | }
40 | },
41 | data: function data() {
42 | return {
43 | // data property for v-model binding with real textarea tag
44 | val: null,
45 | // works when content height becomes more then value of the maxHeight property
46 | maxHeightScroll: false,
47 | height: 'auto'
48 | };
49 | },
50 | computed: {
51 | computedStyles: function computedStyles() {
52 | if (!this.autosize) return {};
53 | return {
54 | resize: !this.isResizeImportant ? 'none' : 'none !important',
55 | height: this.height,
56 | overflow: this.maxHeightScroll ? 'auto' : !this.isOverflowImportant ? 'hidden' : 'hidden !important'
57 | };
58 | },
59 | isResizeImportant: function isResizeImportant() {
60 | var imp = this.important;
61 | return imp === true || Array.isArray(imp) && imp.includes('resize');
62 | },
63 | isOverflowImportant: function isOverflowImportant() {
64 | var imp = this.important;
65 | return imp === true || Array.isArray(imp) && imp.includes('overflow');
66 | },
67 | isHeightImportant: function isHeightImportant() {
68 | var imp = this.important;
69 | return imp === true || Array.isArray(imp) && imp.includes('height');
70 | }
71 | },
72 | watch: {
73 | value: function value(val) {
74 | this.val = val;
75 | },
76 | val: function val(_val) {
77 | this.$nextTick(this.resize);
78 | this.$emit('input', _val);
79 | },
80 | minHeight: function minHeight() {
81 | this.$nextTick(this.resize);
82 | },
83 | maxHeight: function maxHeight() {
84 | this.$nextTick(this.resize);
85 | },
86 | autosize: function autosize(val) {
87 | if (val) this.resize();
88 | }
89 | },
90 | methods: {
91 | resize: function resize() {
92 | var _this = this;
93 |
94 | var important = this.isHeightImportant ? 'important' : '';
95 | this.height = "auto".concat(important ? ' !important' : '');
96 | this.$nextTick(function () {
97 | var contentHeight = _this.$el.scrollHeight + 1;
98 |
99 | if (_this.minHeight) {
100 | contentHeight = contentHeight < _this.minHeight ? _this.minHeight : contentHeight;
101 | }
102 |
103 | if (_this.maxHeight) {
104 | if (contentHeight > _this.maxHeight) {
105 | contentHeight = _this.maxHeight;
106 | _this.maxHeightScroll = true;
107 | } else {
108 | _this.maxHeightScroll = false;
109 | }
110 | }
111 |
112 | var heightVal = contentHeight + 'px';
113 | _this.height = "".concat(heightVal).concat(important ? ' !important' : '');
114 | });
115 | return this;
116 | }
117 | },
118 | created: function created() {
119 | this.val = this.value;
120 | },
121 | mounted: function mounted() {
122 | this.resize();
123 | }
124 | };
125 |
126 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier
127 | /* server only */
128 | , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
129 | if (typeof shadowMode !== 'boolean') {
130 | createInjectorSSR = createInjector;
131 | createInjector = shadowMode;
132 | shadowMode = false;
133 | } // Vue.extend constructor export interop.
134 |
135 |
136 | var options = typeof script === 'function' ? script.options : script; // render functions
137 |
138 | if (template && template.render) {
139 | options.render = template.render;
140 | options.staticRenderFns = template.staticRenderFns;
141 | options._compiled = true; // functional template
142 |
143 | if (isFunctionalTemplate) {
144 | options.functional = true;
145 | }
146 | } // scopedId
147 |
148 |
149 | if (scopeId) {
150 | options._scopeId = scopeId;
151 | }
152 |
153 | var hook;
154 |
155 | if (moduleIdentifier) {
156 | // server build
157 | hook = function hook(context) {
158 | // 2.3 injection
159 | context = context || // cached call
160 | this.$vnode && this.$vnode.ssrContext || // stateful
161 | this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional
162 | // 2.2 with runInNewContext: true
163 |
164 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
165 | context = __VUE_SSR_CONTEXT__;
166 | } // inject component styles
167 |
168 |
169 | if (style) {
170 | style.call(this, createInjectorSSR(context));
171 | } // register component module identifier for async chunk inference
172 |
173 |
174 | if (context && context._registeredComponents) {
175 | context._registeredComponents.add(moduleIdentifier);
176 | }
177 | }; // used by ssr in case component is cached and beforeCreate
178 | // never gets called
179 |
180 |
181 | options._ssrRegister = hook;
182 | } else if (style) {
183 | hook = shadowMode ? function () {
184 | style.call(this, createInjectorShadow(this.$root.$options.shadowRoot));
185 | } : function (context) {
186 | style.call(this, createInjector(context));
187 | };
188 | }
189 |
190 | if (hook) {
191 | if (options.functional) {
192 | // register for functional component in vue file
193 | var originalRender = options.render;
194 |
195 | options.render = function renderWithStyleInjection(h, context) {
196 | hook.call(context);
197 | return originalRender(h, context);
198 | };
199 | } else {
200 | // inject component registration as beforeCreate hook
201 | var existing = options.beforeCreate;
202 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
203 | }
204 | }
205 |
206 | return script;
207 | }
208 |
209 | var normalizeComponent_1 = normalizeComponent;
210 |
211 | /* script */
212 | const __vue_script__ = script;
213 |
214 | /* template */
215 | var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('textarea',{directives:[{name:"model",rawName:"v-model",value:(_vm.val),expression:"val"}],style:(_vm.computedStyles),domProps:{"value":(_vm.val)},on:{"focus":_vm.resize,"input":function($event){if($event.target.composing){ return; }_vm.val=$event.target.value;}}})};
216 | var __vue_staticRenderFns__ = [];
217 |
218 | /* style */
219 | const __vue_inject_styles__ = undefined;
220 | /* scoped */
221 | const __vue_scope_id__ = undefined;
222 | /* module identifier */
223 | const __vue_module_identifier__ = undefined;
224 | /* functional template */
225 | const __vue_is_functional_template__ = false;
226 | /* style inject */
227 |
228 | /* style inject SSR */
229 |
230 |
231 |
232 | var TextareaAutosize = normalizeComponent_1(
233 | { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
234 | __vue_inject_styles__,
235 | __vue_script__,
236 | __vue_scope_id__,
237 | __vue_is_functional_template__,
238 | __vue_module_identifier__,
239 | undefined,
240 | undefined
241 | );
242 |
243 | var version = '1.1.1';
244 |
245 | var install = function install(Vue) {
246 | Vue.component('TextareaAutosize', TextareaAutosize);
247 | };
248 |
249 | var plugin = {
250 | install: install,
251 | version: version
252 | };
253 |
254 | if (typeof window !== 'undefined' && window.Vue) {
255 | window.Vue.use(plugin);
256 | }
257 |
258 | export default plugin;
259 |
--------------------------------------------------------------------------------
/dist/vue-textarea-autosize.umd.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-textarea-autosize v1.1.1
3 | * (c) 2019 Saymon
4 | * Released under the MIT License.
5 | */
6 | (function (global, factory) {
7 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8 | typeof define === 'function' && define.amd ? define(factory) :
9 | (global = global || self, global.VueTextareaAutosize = factory());
10 | }(this, function () { 'use strict';
11 |
12 | //
13 | //
14 | //
15 | //
16 | //
17 | //
18 | //
19 | var script = {
20 | name: 'TextareaAutosize',
21 | props: {
22 | value: {
23 | type: [String, Number],
24 | default: ''
25 | },
26 | autosize: {
27 | type: Boolean,
28 | default: true
29 | },
30 | minHeight: {
31 | type: [Number],
32 | 'default': null
33 | },
34 | maxHeight: {
35 | type: [Number],
36 | 'default': null
37 | },
38 |
39 | /*
40 | * Force !important for style properties
41 | */
42 | important: {
43 | type: [Boolean, Array],
44 | default: false
45 | }
46 | },
47 | data: function data() {
48 | return {
49 | // data property for v-model binding with real textarea tag
50 | val: null,
51 | // works when content height becomes more then value of the maxHeight property
52 | maxHeightScroll: false,
53 | height: 'auto'
54 | };
55 | },
56 | computed: {
57 | computedStyles: function computedStyles() {
58 | if (!this.autosize) return {};
59 | return {
60 | resize: !this.isResizeImportant ? 'none' : 'none !important',
61 | height: this.height,
62 | overflow: this.maxHeightScroll ? 'auto' : !this.isOverflowImportant ? 'hidden' : 'hidden !important'
63 | };
64 | },
65 | isResizeImportant: function isResizeImportant() {
66 | var imp = this.important;
67 | return imp === true || Array.isArray(imp) && imp.includes('resize');
68 | },
69 | isOverflowImportant: function isOverflowImportant() {
70 | var imp = this.important;
71 | return imp === true || Array.isArray(imp) && imp.includes('overflow');
72 | },
73 | isHeightImportant: function isHeightImportant() {
74 | var imp = this.important;
75 | return imp === true || Array.isArray(imp) && imp.includes('height');
76 | }
77 | },
78 | watch: {
79 | value: function value(val) {
80 | this.val = val;
81 | },
82 | val: function val(_val) {
83 | this.$nextTick(this.resize);
84 | this.$emit('input', _val);
85 | },
86 | minHeight: function minHeight() {
87 | this.$nextTick(this.resize);
88 | },
89 | maxHeight: function maxHeight() {
90 | this.$nextTick(this.resize);
91 | },
92 | autosize: function autosize(val) {
93 | if (val) this.resize();
94 | }
95 | },
96 | methods: {
97 | resize: function resize() {
98 | var _this = this;
99 |
100 | var important = this.isHeightImportant ? 'important' : '';
101 | this.height = "auto".concat(important ? ' !important' : '');
102 | this.$nextTick(function () {
103 | var contentHeight = _this.$el.scrollHeight + 1;
104 |
105 | if (_this.minHeight) {
106 | contentHeight = contentHeight < _this.minHeight ? _this.minHeight : contentHeight;
107 | }
108 |
109 | if (_this.maxHeight) {
110 | if (contentHeight > _this.maxHeight) {
111 | contentHeight = _this.maxHeight;
112 | _this.maxHeightScroll = true;
113 | } else {
114 | _this.maxHeightScroll = false;
115 | }
116 | }
117 |
118 | var heightVal = contentHeight + 'px';
119 | _this.height = "".concat(heightVal).concat(important ? ' !important' : '');
120 | });
121 | return this;
122 | }
123 | },
124 | created: function created() {
125 | this.val = this.value;
126 | },
127 | mounted: function mounted() {
128 | this.resize();
129 | }
130 | };
131 |
132 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier
133 | /* server only */
134 | , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
135 | if (typeof shadowMode !== 'boolean') {
136 | createInjectorSSR = createInjector;
137 | createInjector = shadowMode;
138 | shadowMode = false;
139 | } // Vue.extend constructor export interop.
140 |
141 |
142 | var options = typeof script === 'function' ? script.options : script; // render functions
143 |
144 | if (template && template.render) {
145 | options.render = template.render;
146 | options.staticRenderFns = template.staticRenderFns;
147 | options._compiled = true; // functional template
148 |
149 | if (isFunctionalTemplate) {
150 | options.functional = true;
151 | }
152 | } // scopedId
153 |
154 |
155 | if (scopeId) {
156 | options._scopeId = scopeId;
157 | }
158 |
159 | var hook;
160 |
161 | if (moduleIdentifier) {
162 | // server build
163 | hook = function hook(context) {
164 | // 2.3 injection
165 | context = context || // cached call
166 | this.$vnode && this.$vnode.ssrContext || // stateful
167 | this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional
168 | // 2.2 with runInNewContext: true
169 |
170 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
171 | context = __VUE_SSR_CONTEXT__;
172 | } // inject component styles
173 |
174 |
175 | if (style) {
176 | style.call(this, createInjectorSSR(context));
177 | } // register component module identifier for async chunk inference
178 |
179 |
180 | if (context && context._registeredComponents) {
181 | context._registeredComponents.add(moduleIdentifier);
182 | }
183 | }; // used by ssr in case component is cached and beforeCreate
184 | // never gets called
185 |
186 |
187 | options._ssrRegister = hook;
188 | } else if (style) {
189 | hook = shadowMode ? function () {
190 | style.call(this, createInjectorShadow(this.$root.$options.shadowRoot));
191 | } : function (context) {
192 | style.call(this, createInjector(context));
193 | };
194 | }
195 |
196 | if (hook) {
197 | if (options.functional) {
198 | // register for functional component in vue file
199 | var originalRender = options.render;
200 |
201 | options.render = function renderWithStyleInjection(h, context) {
202 | hook.call(context);
203 | return originalRender(h, context);
204 | };
205 | } else {
206 | // inject component registration as beforeCreate hook
207 | var existing = options.beforeCreate;
208 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
209 | }
210 | }
211 |
212 | return script;
213 | }
214 |
215 | var normalizeComponent_1 = normalizeComponent;
216 |
217 | /* script */
218 | const __vue_script__ = script;
219 |
220 | /* template */
221 | var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('textarea',{directives:[{name:"model",rawName:"v-model",value:(_vm.val),expression:"val"}],style:(_vm.computedStyles),domProps:{"value":(_vm.val)},on:{"focus":_vm.resize,"input":function($event){if($event.target.composing){ return; }_vm.val=$event.target.value;}}})};
222 | var __vue_staticRenderFns__ = [];
223 |
224 | /* style */
225 | const __vue_inject_styles__ = undefined;
226 | /* scoped */
227 | const __vue_scope_id__ = undefined;
228 | /* module identifier */
229 | const __vue_module_identifier__ = undefined;
230 | /* functional template */
231 | const __vue_is_functional_template__ = false;
232 | /* style inject */
233 |
234 | /* style inject SSR */
235 |
236 |
237 |
238 | var TextareaAutosize = normalizeComponent_1(
239 | { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
240 | __vue_inject_styles__,
241 | __vue_script__,
242 | __vue_scope_id__,
243 | __vue_is_functional_template__,
244 | __vue_module_identifier__,
245 | undefined,
246 | undefined
247 | );
248 |
249 | var version = '1.1.1';
250 |
251 | var install = function install(Vue) {
252 | Vue.component('TextareaAutosize', TextareaAutosize);
253 | };
254 |
255 | var plugin = {
256 | install: install,
257 | version: version
258 | };
259 |
260 | if (typeof window !== 'undefined' && window.Vue) {
261 | window.Vue.use(plugin);
262 | }
263 |
264 | return plugin;
265 |
266 | }));
267 |
--------------------------------------------------------------------------------
/dist/vue-textarea-autosize.umd.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-textarea-autosize v1.1.1
3 | * (c) 2019 Saymon
4 | * Released under the MIT License.
5 | */
6 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self,t.VueTextareaAutosize=e())}(this,function(){"use strict";function t(t,e,i,n,o,r,a,s,u,c){"boolean"!=typeof a&&(u=s,s=a,a=!1);var h="function"==typeof i?i.options:i;t&&t.render&&(h.render=t.render,h.staticRenderFns=t.staticRenderFns,h._compiled=!0,o&&(h.functional=!0)),n&&(h._scopeId=n);var l;if(r?(l=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,u(t)),t&&t._registeredComponents&&t._registeredComponents.add(r)},h._ssrRegister=l):e&&(l=a?function(){e.call(this,c(this.$root.$options.shadowRoot))}:function(t){e.call(this,s(t))}),l)if(h.functional){var d=h.render;h.render=function(t,e){return l.call(e),d(t,e)}}else{var f=h.beforeCreate;h.beforeCreate=f?[].concat(f,l):[l]}return i}var e={name:"TextareaAutosize",props:{value:{type:[String,Number],default:""},autosize:{type:Boolean,default:!0},minHeight:{type:[Number],default:null},maxHeight:{type:[Number],default:null},important:{type:[Boolean,Array],default:!1}},data:function(){return{val:null,maxHeightScroll:!1,height:"auto"}},computed:{computedStyles:function(){return this.autosize?{resize:this.isResizeImportant?"none !important":"none",height:this.height,overflow:this.maxHeightScroll?"auto":this.isOverflowImportant?"hidden !important":"hidden"}:{}},isResizeImportant:function(){var t=this.important;return!0===t||Array.isArray(t)&&t.includes("resize")},isOverflowImportant:function(){var t=this.important;return!0===t||Array.isArray(t)&&t.includes("overflow")},isHeightImportant:function(){var t=this.important;return!0===t||Array.isArray(t)&&t.includes("height")}},watch:{value:function(t){this.val=t},val:function(t){this.$nextTick(this.resize),this.$emit("input",t)},minHeight:function(){this.$nextTick(this.resize)},maxHeight:function(){this.$nextTick(this.resize)},autosize:function(t){t&&this.resize()}},methods:{resize:function(){var t=this,e=this.isHeightImportant?"important":"";return this.height="auto".concat(e?" !important":""),this.$nextTick(function(){var i=t.$el.scrollHeight+1;t.minHeight&&(i=it.maxHeight?(i=t.maxHeight,t.maxHeightScroll=!0):t.maxHeightScroll=!1);var n=i+"px";t.height="".concat(n).concat(e?" !important":"")}),this}},created:function(){this.val=this.value},mounted:function(){this.resize()}},i=t;const n=e;var o=function(){var t=this,e=t.$createElement;return(t._self._c||e)("textarea",{directives:[{name:"model",rawName:"v-model",value:t.val,expression:"val"}],style:t.computedStyles,domProps:{value:t.val},on:{focus:t.resize,input:function(e){e.target.composing||(t.val=e.target.value)}}})},r=[];var a=i({render:o,staticRenderFns:r},void 0,n,void 0,!1,void 0,void 0,void 0),s=function(t){t.component("TextareaAutosize",a)},u={install:s,version:"1.1.1"};return"undefined"!=typeof window&&window.Vue&&window.Vue.use(u),u});
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | base: '/vue-textarea-autosize/',
3 | plugins: [
4 | require('./plugin.js')
5 | ],
6 | locales: {
7 | '/': {
8 | lang: 'en-US',
9 | title: 'VueTextareaAutosize',
10 | description: 'TextareaAutosize plugin for Vue.js'
11 | }
12 | },
13 | themeConfig: {
14 | repo: 'https://github.com/devstark-com/vue-textarea-autosize/',
15 | docsDir: 'docs',
16 | locales: {
17 | '/': {
18 | label: 'English',
19 | selectText: 'Languages',
20 | editLinkText: 'Edit this page on GitHub',
21 | nav: [{
22 | text: 'Release Notes',
23 | link: 'https://github.com/devstark-com/vue-textarea-autosize/releases'
24 | }],
25 | sidebar: [
26 | '/',
27 | '/guide.md'
28 | ]
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/docs/.vuepress/plugin.js:
--------------------------------------------------------------------------------
1 | const { version } = require('../../package.json')
2 |
3 | module.exports = (/*options, ctx*/) => ({
4 | async enhanceAppFiles () {
5 | const code = `export default ({ Vue }) => {
6 | Vue.mixin({
7 | computed: {
8 | $version () {
9 | return '${version}'
10 | }
11 | }
12 | })
13 | }`
14 | return [{
15 | name: 'vuepress-plugin-vue-cli-plugin-p11n',
16 | content: code
17 | }]
18 | }
19 | })
20 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | The plugin for [Vue.js](http://vuejs.org) provides the dead-simple Vue component implements textarea with automatically adjustable height.
4 |
5 | ---
6 |
7 | # 🛠 Features
8 |
9 | - Bind with `v-model`
10 | - Set min/max height limits with appropriate reactive props
11 | - Enable/disable auto resizing dynamically
12 | - Trigger resize manually with `$refs.myTextarea.resize()`
13 | - Handle all native events with `.native` modifier [read more](https://vuejs.org/v2/guide/components.html#Binding-Native-Events-to-Components)
14 | - Use native attrs like this ``
15 | - Force `!important` for style properties e.g. when using [http://cleanslatecss.com/](http://cleanslatecss.com/)
16 | - There is no CSS out of the box, so feel free to style it as you wish
17 |
18 | ---
19 |
20 | [GitHub](https://github.com/devstark-com/vue-textarea-autosize/) |
21 | [Demo](https://codesandbox.io/s/vuetextareaautosize-demo-vikj3?fontsize=14) | [More packages](https://github.com/devstark-com) by [DevStark](https://devstark.com/)
22 |
--------------------------------------------------------------------------------
/docs/guide.md:
--------------------------------------------------------------------------------
1 | # Guide
2 |
3 | ## Installation
4 |
5 | ### NPM
6 |
7 | ```sh
8 | $ npm i -S vue-textarea-autosize
9 | ```
10 |
11 | ### Yarn
12 |
13 | ```sh
14 | $ yarn add vue-textarea-autosize
15 | ```
16 |
17 | ### Register the plugin
18 |
19 | ```javascript
20 | import Vue from 'vue'
21 | import VueTextareaAutosize from 'vue-textarea-autosize'
22 |
23 | Vue.use(VueTextareaAutosize)
24 | ```
25 | ## Usage
26 |
27 | ```html
28 |
36 | ```
37 |
38 | ```js
39 | this.$refs.myTextarea.$el.focus()
40 | this.$refs.myTextarea.$el.blur()
41 | this.$refs.myTextarea.$el.select()
42 | ```
43 | ## Interface
44 |
45 | ### Props
46 |
47 | | Props | Required | Type | Default | Description |
48 | | ---------------- | --------- | --------------- | --------- | -------------|
49 | | `v-model` | no | String, Number | '' | value binding |
50 | | `value` | no | String, Number | '' | part of the `v-model` binding |
51 | | `autosize` | no | Boolean | true | allows to enable/disable auto resizing dynamically |
52 | | `minHeight` | no | Number | null | min textarea height (reactive behavior) |
53 | | `maxHeight` | no | Number | null | max textarea height (reactive behavior) |
54 | | `important` | no | Boolean, Array | false | Forces `!important` for style properties e.g. when using [http://cleanslatecss.com/](http://cleanslatecss.com/).
Allowed values: `true`, `false` and
all or some of
`['resize', 'overflow', 'height']`|
55 |
56 | ### Events
57 |
58 | | Name | Params | Description |
59 | | ----------|:---------|--------------|
60 | | input | value | fires on textarea content changed. part of the `v-model` binding. [read more](https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events) |
61 |
62 | ### Slots
63 |
64 | There are no slots available
65 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-textarea-autosize",
3 | "description": "Vue component provides textarea with automatically adjustable height and without any wrappers and dependencies",
4 | "version": "1.1.1",
5 | "author": {
6 | "name": "Saymon",
7 | "email": "saymon.biz@gmail.com"
8 | },
9 | "scripts": {
10 | "serve": "vue-cli-service serve",
11 | "build": "vue-cli-service build",
12 | "lint": "vue-cli-service lint",
13 | "demo": "vue-cli-service demo",
14 | "docs": "npm run docs:serve",
15 | "docs:build": "vue-cli-service docs --mode build",
16 | "docs:serve": "vue-cli-service docs --mode serve",
17 | "prepublish": "vue-cli-service lint && vue-cli-service docs --mode build && vue-cli-service build",
18 | "start": "vue-cli-service serve"
19 | },
20 | "main": "dist/vue-textarea-autosize.common.js",
21 | "module": "dist/vue-textarea-autosize.esm.js",
22 | "unpkg": "dist/vue-textarea-autosize.umd.min.js",
23 | "files": [
24 | "dist/vue-textarea-autosize.common.js",
25 | "dist/vue-textarea-autosize.umd.min.js",
26 | "dist/vue-textarea-autosize.umd.js",
27 | "dist/vue-textarea-autosize.esm.js",
28 | "src"
29 | ],
30 | "dependencies": {
31 | "core-js": "^2.6.5"
32 | },
33 | "devDependencies": {
34 | "@vue/cli-plugin-babel": "^3.11.0",
35 | "@vue/cli-plugin-eslint": "^3.11.0",
36 | "@vue/cli-service": "^3.11.0",
37 | "babel-eslint": "^10.0.1",
38 | "eslint": "^5.16.0",
39 | "eslint-plugin-vue": "^5.0.0",
40 | "vue-cli-plugin-p11n": "^0.4.0",
41 | "vue-template-compiler": "^2.6.10",
42 | "vue": "^2.6.10"
43 | },
44 | "eslintConfig": {
45 | "root": true,
46 | "env": {
47 | "node": true
48 | },
49 | "extends": [
50 | "plugin:vue/essential",
51 | "eslint:recommended"
52 | ],
53 | "rules": {},
54 | "parserOptions": {
55 | "parser": "babel-eslint"
56 | }
57 | },
58 | "postcss": {
59 | "plugins": {
60 | "autoprefixer": {}
61 | }
62 | },
63 | "browserslist": [
64 | "> 1%",
65 | "last 2 versions"
66 | ],
67 | "jsdelivr": "dist/textarea-autosize.umd.min.js",
68 | "sideeffects": false,
69 | "keywords": [
70 | "vue",
71 | "vuejs",
72 | "plugin",
73 | "textarea",
74 | "size",
75 | "auto",
76 | "autosize",
77 | "height"
78 | ],
79 | "license": "MIT",
80 | "repository": {
81 | "type": "git",
82 | "url": "git+https://github.com/devstark-com/vue-textarea-autosize.git"
83 | },
84 | "bugs": {
85 | "url": "https://github.com/devstark-com/vue-textarea-autosize/issues"
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
vue-textarea-autosize
5 |
10 |
11 |
12 |
24 |
34 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devstark-com/vue-textarea-autosize/8e767ea21863b3e8607b1808b89e7b5a0e3aa98c/src/assets/logo.png
--------------------------------------------------------------------------------
/src/components/TextareaAutosize.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
120 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import TextareaAutosize from './components/TextareaAutosize.vue'
2 | const version = '__VERSION__'
3 |
4 | const install = Vue => {
5 | Vue.component('TextareaAutosize', TextareaAutosize)
6 | }
7 |
8 | const plugin = {
9 | install,
10 | version
11 | }
12 |
13 | export default plugin
14 |
15 | if (typeof window !== 'undefined' && window.Vue) {
16 | window.Vue.use(plugin)
17 | }
18 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import './plugin'
4 |
5 | Vue.config.productionTip = false
6 |
7 | new Vue({
8 | render: h => h(App),
9 | }).$mount('#app')
10 |
--------------------------------------------------------------------------------
/src/plugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is plugin stub for main.js
3 | */
4 |
5 | import Vue from 'vue'
6 | import plugin from './index'
7 |
8 | Vue.use(plugin)
9 |
--------------------------------------------------------------------------------