Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TSDoc and simplify components [fixes #103] #118

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
159 changes: 79 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ Some of the unique features this component offers include:
- Minimalistic, visually pleasing style
- Variable content length


## Used by

- [caseconverter.pro](https://caseconverter.pro/app)
Expand All @@ -35,38 +34,40 @@ Some of the unique features this component offers include:
<details>
<summary>Install via NPM</summary>

```bash
npm install --save react-in-out-textarea
# You might want to install react-tooltip if you activate the max length option
npm install --save react-tooltip
```
```bash
npm install --save react-in-out-textarea
# You might want to install react-tooltip if you activate the max length option
npm install --save react-tooltip
```

</details>

<details>
<summary>Install via yarn</summary>

```bash
yarn add react-in-out-textarea
# You might want to install react-tooltip if you activate the max length option
yarn add react-tooltip
```
```bash
yarn add react-in-out-textarea
# You might want to install react-tooltip if you activate the max length option
yarn add react-tooltip
```

</details>

## Props

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| inValue | string | ✔️ | The value that is shown on the left-handed side. |
| outValue | string | ✔️ | The value that is shown on the right-handed side. |
| inOptions | array | ✔️ | An array of options filled with names marked true or false |
| onInInput | function | ✔️ | Called to listen to when the text on the left-hand side changes | ✔️ |
| onInOptionsUpdate | function | ✔️ | Updated with new options as the parameter when inOptions language clicked |
| outOptions | array | ✔️ | An array of options filled with names marked true or false and an activeClicked boolean |
| onOutOptionsUpdate | function | ✔️ | Updated with new options as the parameter when outOptions language clicked |
| maxContentLength | number | ❌ | Value that defines the maximum number of characters allowed in the text area. |
| maxContentLengthIndicator | Object | ❌ | An Object describing how the length indicator is shown. |
| onCopy | function | ❌ | A function that is called when you have copied the content of `InOutTextarea`. |
| autoCloseMenuOnOptionSelection | boolean | ❌ | Boolean that defines whether an option menu should self-close after selection. |
| Name | Type | Required | Description |
| ------------------------------ | -------- | -------- | ------------------------------------------------------------------------------ |
| inValue | string | ✔️ | The value that is shown on the left-handed side. |
| outValue | string | ✔️ | The value that is shown on the right-handed side. |
| inOptions | array | ✔️ | An array of options filled with names marked true or false |
| onInInput | function | ✔️ | Called to listen to when the text on the left-hand side changes |
| onInOptionsUpdate | function | ✔️ | Updated with new options as the parameter when inOptions language clicked |
| outOptions | array | ✔️ | An array of options filled with names marked true or false |
| onOutOptionsUpdate | function | ✔️ | Updated with new options as the parameter when outOptions language clicked |
| maxContentLength | number | ❌ | Value that defines the maximum number of characters allowed in the text area. |
| maxContentLengthIndicator | Object | ❌ | An Object describing how the length indicator is shown. |
| onCopy | function | ❌ | A function that is called when you have copied the content of `InOutTextarea`. |
| autoCloseMenuOnOptionSelection | boolean | ❌ | Boolean that defines whether an option menu should self-close after selection. |

## Usage

Expand All @@ -84,7 +85,7 @@ import { InOutTextarea, InOptions, OutOptions } from 'react-in-out-textarea';
export const ExampleComponent = () => {
const [inValue, setInValue] = useState<string>('');
const [outValue, setOutValue] = useState<string>('');
const [inOptions, setInOptions] = useState<InOptions>([
const [inOptions, setInOptions] = useState<Options>([
{
name: 'English',
active: true,
Expand All @@ -94,28 +95,27 @@ export const ExampleComponent = () => {
active: false,
},
]);
const [outOptions, setOutOptions] = useState<OutOptions>([
const [outOptions, setOutOptions] = useState<Options>([
{
name: 'Chinese',
active: true,
activeClicked: false,
},
]);

return (
<InOutTextarea
inValue={inValue}
outValue={outValue}
onInInput={(newValue) => {
onInInput={newValue => {
setInValue(newValue);
setOutValue(newValue);
}}
inOptions={inOptions}
onInOptionsUpdate={(newInOptions) => {
onInOptionsUpdate={newInOptions => {
setInOptions(newInOptions);
}}
outOptions={outOptions}
onOutOptionsUpdate={(newOutOptions) => {
onOutOptionsUpdate={newOutOptions => {
setOutOptions(newOutOptions);
}}
/>
Expand All @@ -128,57 +128,56 @@ export const ExampleComponent = () => {
<details>
<summary>React + Javascript</summary>

[CodeSandbox Example](https://codesandbox.io/s/react-in-out-textarea-javascript-react-kcl37?file=/src/ExampleComponent.js)

Code Example:

```js
import React, { useState } from "react";
import { InOutTextarea } from "react-in-out-textarea";

export const ExampleComponent = () => {
const [inValue, setInValue] = useState("");
const [outValue, setOutValue] = useState("");
const [inOptions, setInOptions] = useState([
{
name: "English",
active: true
},
{
name: "German",
active: false
}
]);
const [outOptions, setOutOptions] = useState([
{
name: "Chinese",
active: true,
activeClicked: false
}
]);

return (
<InOutTextarea
inValue={inValue}
outValue={outValue}
onInInput={(newValue) => {
setInValue(newValue);
setOutValue(newValue);
}}
inOptions={inOptions}
onInOptionsUpdate={(newInOptions) => {
setInOptions(newInOptions);
}}
outOptions={outOptions}
onOutOptionsUpdate={(newOutOptions) => {
setOutOptions(newOutOptions);
}}
/>
);
};
```
</details>
[CodeSandbox Example](https://codesandbox.io/s/react-in-out-textarea-javascript-react-kcl37?file=/src/ExampleComponent.js)

Code Example:

```js
import React, { useState } from 'react';
import { InOutTextarea } from 'react-in-out-textarea';

export const ExampleComponent = () => {
const [inValue, setInValue] = useState('');
const [outValue, setOutValue] = useState('');
const [inOptions, setInOptions] = useState([
{
name: 'English',
active: true,
},
{
name: 'German',
active: false,
},
]);
const [outOptions, setOutOptions] = useState([
{
name: 'Chinese',
active: true,
},
]);

return (
<InOutTextarea
inValue={inValue}
outValue={outValue}
onInInput={newValue => {
setInValue(newValue);
setOutValue(newValue);
}}
inOptions={inOptions}
onInOptionsUpdate={newInOptions => {
setInOptions(newInOptions);
}}
outOptions={outOptions}
onOutOptionsUpdate={newOutOptions => {
setOutOptions(newOutOptions);
}}
/>
);
};
```

</details>

## Development

Expand Down
9 changes: 3 additions & 6 deletions src/CaseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import styled from 'styled-components';

type CaseButtonProps = {
active?: boolean;
activeClicked?: boolean;
};

export const CaseButton = styled.div<CaseButtonProps>`
Expand All @@ -14,13 +13,13 @@ export const CaseButton = styled.div<CaseButtonProps>`
cursor: pointer;
color: ${props => {
if (props.theme.main === 'dark') {
if (props.active || props.activeClicked) {
if (props.active) {
return '#fff';
} else {
return '#E5E5E5';
}
} else {
if (props.active || props.activeClicked) {
if (props.active) {
return '#14213d';
} else {
return 'color: rgba(20,33,61,0.4);';
Expand All @@ -29,9 +28,7 @@ export const CaseButton = styled.div<CaseButtonProps>`
}};
border-bottom: ${props => {
if (props.active) {
return '2px solid #fca311';
} else if (props.activeClicked) {
return '2px solid #5ba4ca';
return '2px solid var(--border-active-color)';
} else {
return '2px solid transparent';
}
Expand Down
65 changes: 5 additions & 60 deletions src/InMenuOptionStuff.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,6 @@
import React from 'react';
import useDimensions, { IDimensionValues } from 'react-use-dimensions';
import { CaseButton } from './CaseButton';
import { IInOption, InOptions } from './types';
import styled from 'styled-components';
import { MenuOptionStuff } from './MenuOptionStuff';

interface IInMenuOptionStuff {
inOptionsMenuRefSizes: IDimensionValues;
liveMeasure: boolean;
menuOptions: InOptions;
option: IInOption;
inOptions: InOptions;
onInOptionsUpdate: (newInOptions: InOptions) => void;
setMenuOptions: React.Dispatch<React.SetStateAction<InOptions>>;
}

export const InMenuOptionStuff = (props: IInMenuOptionStuff) => {
const {
inOptionsMenuRefSizes,
liveMeasure,
menuOptions,
option,
inOptions,
onInOptionsUpdate,
setMenuOptions,
} = props;

const [suuuRef, suuSizes] = useDimensions({ liveMeasure });
if (!inOptionsMenuRefSizes) return null;

const shouldHide = suuSizes.x + suuSizes.width > inOptionsMenuRefSizes.x;

if (shouldHide) {
if (menuOptions.find((e: IInOption) => e.name === option.name)) {
return null;
}
setMenuOptions([...menuOptions, option]);
return null;
} else {
if (menuOptions.find((e: IInOption) => e.name === option.name)) {
setMenuOptions([...menuOptions.filter(e => e.name !== option.name)]);
}
}

return (
<CaseButton
ref={suuuRef}
active={option.active}
onClick={() => {
const updatedOptions: InOptions = [
...inOptions.map((inOption: IInOption) => ({
...inOption,
active: inOption.name === option.name,
})),
];
onInOptionsUpdate(updatedOptions);
}}
>
{option.name}
</CaseButton>
);
};
export const InMenuOptionStuff = styled(MenuOptionStuff)`
--border-active-color: #fca311;
`;
64 changes: 64 additions & 0 deletions src/MenuOptionStuff.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import useDimensions, { IDimensionValues } from 'react-use-dimensions';
import { CaseButton } from './CaseButton';
import { IOption, Options } from './types';

export interface IMenuOptionStuff {
optionsMenuRefSizes: IDimensionValues;
liveMeasure: boolean;
menuOptions: Options;
option: IOption;
options: Options;
onOptionsUpdate: (newOptions: Options) => void;
setMenuOptions: React.Dispatch<React.SetStateAction<Options>>;
className?: string;
}

export const MenuOptionStuff = (props: IMenuOptionStuff) => {
const {
optionsMenuRefSizes,
liveMeasure,
menuOptions,
option,
options,
onOptionsUpdate,
setMenuOptions,
className,
} = props;

const [suuuRef, suuSizes] = useDimensions({ liveMeasure });
if (!optionsMenuRefSizes) return null;

const shouldHide = suuSizes.x + suuSizes.width > optionsMenuRefSizes.x;

if (shouldHide) {
if (menuOptions.find((e: IOption) => e.name === option.name)) {
return null;
}
setMenuOptions([...menuOptions, option]);
return null;
} else {
if (menuOptions.find((e: IOption) => e.name === option.name)) {
setMenuOptions([...menuOptions.filter(e => e.name !== option.name)]);
}
}

return (
<CaseButton
ref={suuuRef}
className={className}
active={option.active}
onClick={() => {
const updatedOptions: Options = [
...options.map((inOption: IOption) => ({
...inOption,
active: inOption.name === option.name,
})),
];
onOptionsUpdate(updatedOptions);
}}
>
{option.name}
</CaseButton>
);
};
Loading