This commit is contained in:
Joshua Peek 2018-08-08 15:02:33 -07:00
Коммит 93fedfbbf6
11 изменённых файлов: 276 добавлений и 0 удалений

4
.eslintrc.json Normal file
Просмотреть файл

@ -0,0 +1,4 @@
{
"extends": ["plugin:github/es6", "plugin:github/browser"],
"parser": "babel-eslint"
}

4
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
dist/
node_modules/
package-lock.json
yarn.lock

9
.travis.yml Normal file
Просмотреть файл

@ -0,0 +1,9 @@
language: node_js
sudo: required
node_js:
- "node"
addons:
chrome: stable
cache:
directories:
- node_modules

20
LICENSE Normal file
Просмотреть файл

@ -0,0 +1,20 @@
Copyright (c) 2018 GitHub, Inc.
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.

27
README.md Normal file
Просмотреть файл

@ -0,0 +1,27 @@
# Textarea Autosize
Autosizes textarea to size of it's contents.
## Installation
```
$ npm install @github/textarea-autosize
```
## Usage
```js
import autosize from '@github/textarea-autosize'
autosize(document.querySelector('textarea.foo'))
```
## Development
```
npm install
npm test
```
## License
Distributed under the MIT license. See LICENSE for details.

64
examples/index.html Normal file
Просмотреть файл

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
font: 20px Helvetica;
padding: 20px;
}
textarea {
width: 500px;
min-height: 100px;
display: block;
}
.styled {
box-sizing: border-box;
padding: 10px;
border: 1px solid #ddd;
font-family: Helvetica, sans-serif;
font-size: 23px;
}
</style>
</head>
<body>
<form>
<textarea autofocus></textarea>
<textarea class="styled"></textarea>
<p>
<button>Load long text</button>
<input type=reset>
</p>
<div id="long-text" hidden>Long and well reasoned argument
about talking about long and well reasoned arguments
and how they long
and well reasoned
and argue things of value.
Maybe.
Honestly, though, this is just long.
Long enough, in any case.
</div>
</form>
<script type="module">
import autosize from '../dist/textarea-autosize.esm.js'
for (const textarea of document.getElementsByTagName('textarea')) {
autosize(textarea)
}
document.querySelector('button').addEventListener('click', event => {
event.preventDefault()
for (const textarea of document.getElementsByTagName('textarea')) {
textarea.value = document.getElementById('long-text').textContent
textarea.dispatchEvent(new Event('change'))
}
})
</script>
</body>
</html>

29
package.json Normal file
Просмотреть файл

@ -0,0 +1,29 @@
{
"name": "@github/textarea-autosize",
"description": "Autosizes textarea to size of it's contents.",
"version": "0.0.0",
"main": "dist/textarea-autosize.umd.js",
"module": "dist/textarea-autosize.esm.js",
"license": "MIT",
"repository": "github/textarea-autosize",
"files": ["dist"],
"scripts": {
"clean": "rm -rf dist",
"lint": "eslint textarea-autosize.js",
"prebuild": "npm run clean && npm run lint && mkdir dist",
"build": "rollup -c && npm run build-flow",
"build-flow":
"cp textarea-autosize.js.flow dist/textarea-autosize.esm.js.flow && cp textarea-autosize.js.flow dist/textarea-autosize.umd.js.flow",
"test": "echo",
"pretest": "npm run build",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-es2015-rollup": "^3.0.0",
"eslint": "^5.1.0",
"eslint-plugin-github": "^1.1.3",
"rollup": "^0.64.0",
"rollup-plugin-babel": "^3.0.7"
}
}

1
prettier.config.js Normal file
Просмотреть файл

@ -0,0 +1 @@
module.exports = require('eslint-plugin-github/prettier.config')

23
rollup.config.js Normal file
Просмотреть файл

@ -0,0 +1,23 @@
import babel from 'rollup-plugin-babel'
const pkg = require('./package.json')
export default {
input: 'textarea-autosize.js',
output: [
{
file: pkg['module'],
format: 'es'
},
{
file: pkg['main'],
format: 'umd',
name: 'textareaAutosize'
}
],
plugins: [
babel({
presets: ['es2015-rollup']
})
]
}

88
textarea-autosize.js Normal file
Просмотреть файл

@ -0,0 +1,88 @@
export default function autosize(textarea) {
let previousValue = null
let isUserResized = false
let x
let y
let height
function onUserResize(event) {
if (x !== event.clientX || y !== event.clientY) {
const newHeight = textarea.style.height
if (height && height !== newHeight) {
isUserResized = true
textarea.style.maxHeight = ''
textarea.removeEventListener('mousemove', onUserResize)
}
height = newHeight
}
x = event.clientX
y = event.clientY
}
const document = textarea.ownerDocument
const documentElement = document.documentElement
function overflowOffset() {
let offsetTop = 0
let el = textarea
while (el !== document.body && el !== null) {
offsetTop += el.offsetTop || 0
el = el.offsetParent
}
const top = offsetTop - document.defaultView.pageYOffset
const bottom = documentElement.clientHeight - (top + textarea.offsetHeight)
return {top, bottom}
}
function sizeToFit() {
if (isUserResized) return
if (textarea.value === previousValue) return
if (textarea.offsetWidth <= 0 && textarea.offsetHeight <= 0) return
const {top, bottom} = overflowOffset()
if (top < 0 || bottom < 0) {
return
}
const maxHeight = Number(getComputedStyle(textarea).height.replace(/px/, '')) + bottom
textarea.style.maxHeight = `${maxHeight - 100}px`
const container = textarea.parentElement
if (container instanceof HTMLElement) {
const containerHeight = container.style.height
container.style.height = getComputedStyle(container).height
textarea.style.height = 'auto'
textarea.style.height = `${textarea.scrollHeight}px`
container.style.height = containerHeight
height = textarea.style.height
}
previousValue = textarea.value
}
function onFormReset() {
isUserResized = false
textarea.style.height = ''
textarea.style.maxHeight = ''
}
textarea.addEventListener('mousemove', onUserResize)
textarea.addEventListener('input', sizeToFit)
textarea.addEventListener('change', sizeToFit)
const form = textarea.form
if (form) form.addEventListener('reset', onFormReset)
if (textarea.value) sizeToFit()
return {
unsubscribe() {
textarea.removeEventListener('mousemove', onUserResize)
textarea.removeEventListener('input', sizeToFit)
textarea.removeEventListener('change', sizeToFit)
if (form) form.removeEventListener('reset', onFormReset)
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
/* @flow strict */
declare export default function autosize(textarea: HTMLTextAreaElement): Subscription;
interface Subscription {
unsubscribe(): void;
}