Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
name: publish
on:
workflow_dispatch:
push:
branches:
- publish
workflow_dispatch:
push:
branches:
- publish
jobs:
publish:
runs-on: ubuntu-latest
environment: publish
steps:
- uses: actions/checkout@v2
- run: yarn
- run: yarn build
- run: yarn publish
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
publish:
runs-on: ubuntu-latest
environment: publish
steps:
- uses: actions/checkout@v2
- run: yarn
- run: yarn build
- run: yarn publish
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
20 changes: 20 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"singleQuote": true,
"jsxSingleQuote": false,
"printWidth": 120,
"proseWrap": "preserve",
"trailingComma": "es5",
"endOfLine": "lf",
"tabWidth": 4,
"useTabs": false,
"semi": true,
"overrides": [
{
"files": ["*.yml", "*.yaml"],
"options": {
"singleQuote": false,
"tabWidth": 2
}
}
]
}
7 changes: 1 addition & 6 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@
},
"prettier.enable": true,
"prettier.tabWidth": 4,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"eslint.packageManager": "yarn",
"css.validate": true,
"scss.validate": true,
Expand Down
8 changes: 8 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.unstyled-textarea-autosize {
cursor: text;
}

.unstyled-textarea-autosize:empty::before {
content: attr(data-placeholder);
opacity: 0.75;
}
68 changes: 23 additions & 45 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import React, {
ComponentProps,
FormEvent,
forwardRef,
KeyboardEvent,
useCallback,
useEffect,
} from "react";
import { useRefWithForwarding } from "use-ref-with-forwarding";

export type UnstyledTextareaAutosizeProps = ComponentProps<"div"> & {
import React, { ComponentProps, FormEvent, forwardRef, KeyboardEvent, useCallback, useEffect } from 'react';
import { useRefWithForwarding } from 'use-ref-with-forwarding';
import './index.css';

export type UnstyledTextareaAutosizeProps = ComponentProps<'div'> & {
readOnly?: boolean;
value?: string;
initialValue?: string;
placeholder?: string;
onValueChange?: (value: string) => void;
};

export type UnstyledTextareaAutosizeElement = HTMLDivElement & {
value: string;
};

const INVALID_CTRL_KEYS = ["b", "i", "u"];
const INVALID_CTRL_KEYS = ['b', 'i', 'u'];

function initElement(element: UnstyledTextareaAutosizeElement | null) {
if (element) {
Object.defineProperty(element, "value", {
Object.defineProperty(element, 'value', {
get: function () {
return element.innerText;
},
Expand All @@ -38,13 +33,11 @@ function isElementInitialized(
element: UnstyledTextareaAutosizeElement | null
): element is UnstyledTextareaAutosizeElement {
if (!element) {
console.error("unstyled-textarea-autosize: unexpected null ref");
console.error('unstyled-textarea-autosize: unexpected null ref');
return false;
}
if (Object.getOwnPropertyDescriptor(element, "value") === undefined) {
console.error(
"unstyled-textarea-autosize: value property not configured"
);
if (Object.getOwnPropertyDescriptor(element, 'value') === undefined) {
console.error('unstyled-textarea-autosize: value property not configured');
return false;
}
return true;
Expand All @@ -54,24 +47,13 @@ export const UnstyledTextareaAutosize = forwardRef<
UnstyledTextareaAutosizeElement | null,
UnstyledTextareaAutosizeProps
>(function UnstyledTextareaAutosize(
{
readOnly,
value,
initialValue,
onValueChange,
onInput,
onKeyDown,
...props
},
{ readOnly, value, initialValue, placeholder, className, onValueChange, onInput, onKeyDown, ...props },
outerRef
) {
// initialize dom element with the value property

// reference to the root element
const ref = useRefWithForwarding<UnstyledTextareaAutosizeElement | null>(
null,
[initElement, outerRef]
);
const ref = useRefWithForwarding<UnstyledTextareaAutosizeElement | null>(null, [initElement, outerRef]);

// update the text when the value changes (controlled mode)
useEffect(() => {
Expand Down Expand Up @@ -122,14 +104,12 @@ export const UnstyledTextareaAutosize = forwardRef<

// propagate the value change
const newValue = ref.current.value;
if (newValue !== value && onValueChange) {
onValueChange(newValue);
if (newValue !== value) {
onValueChange?.(newValue);
}

// call outer onInput handler for full transparency
if (onInput) {
onInput(event);
}
onInput?.(event);
},
[ref, value, onValueChange, onInput]
);
Expand All @@ -143,22 +123,18 @@ export const UnstyledTextareaAutosize = forwardRef<
}

// block formatting shortcuts
if (
(event.ctrlKey || event.metaKey) &&
INVALID_CTRL_KEYS.includes(event.key)
) {
if ((event.ctrlKey || event.metaKey) && INVALID_CTRL_KEYS.includes(event.key)) {
event.preventDefault();
}

// blur on escape
if (event.key === "Escape") {
// blur on escape and unselect all text
if (event.key === 'Escape') {
ref.current.blur();
getSelection()?.removeAllRanges();
}

// call outer onKeyDown handler for full transparency
if (onKeyDown) {
onKeyDown(event);
}
onKeyDown?.(event);
},
[ref, onKeyDown]
);
Expand All @@ -168,6 +144,8 @@ export const UnstyledTextareaAutosize = forwardRef<
<div
{...props}
ref={ref}
data-placeholder={placeholder}
className={`${className ?? ''} unstyled-textarea-autosize`}
contentEditable={!readOnly}
onInput={onInternalInput}
onKeyDown={onInternalKeyDown}
Expand Down