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 LoremHeading #17

Open
wants to merge 1 commit 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
11 changes: 11 additions & 0 deletions examples/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';
import Header from './header';
import Footer from './footer';
import Lipsum from './lipsum';
import Heading from './heading';
import User from './user';
import './style.scss';

Expand All @@ -19,6 +20,13 @@ const App = () => {
>
Lorem Ipsum
</button>
<button
type="button"
className={tab === 'heading' ? 'active' : ''}
onClick={() => setTab('heading')}
>
Lorem Heading
</button>
<button
type="button"
className={tab === 'user' ? 'active' : ''}
Expand All @@ -30,6 +38,9 @@ const App = () => {
<div className={`content${tab === 'lipsum' ? ' active' : ''}`}>
<Lipsum />
</div>
<div className={`content${tab === 'heading' ? ' active' : ''}`}>
<Heading />
</div>
<div className={`content${tab === 'user' ? ' active' : ''}`}>
<User />
</div>
Expand Down
102 changes: 102 additions & 0 deletions examples/src/heading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { useState } from 'react';
import { LoremHeading } from '../../src';

const defaultComponentProps = {
p: 1,
avgWordsPerHeading: 3,
includeEndPunctuation: false,
};

const Heading = () => {
const [componentProps, setComponentProps] = useState(defaultComponentProps);

const handleComponentPropsChange = e => {
const { type, name, value, checked } = e.target;
const { [name]: v, ...others } = componentProps;
setComponentProps({ [name]: type === 'checkbox' ? checked : parseInt(value, 10), ...others });
};

const resetComponentProps = () => {
setComponentProps(defaultComponentProps);
};

const areAllComponentPropsDefault = Object.keys(defaultComponentProps).every(
prop => componentProps[prop] === defaultComponentProps[prop]
);

return (
<div className="lorem-ipsum-wrapper">
<div className="top">
<section className="props">
<h2>Props</h2>
<div className="prop">
<label>
{`Average Words Per Heading (${componentProps.avgWordsPerHeading})`}
<input
className="slider"
type="range"
name="avgWordsPerHeading"
min="4"
max="20"
value={componentProps.avgWordsPerHeading}
onChange={handleComponentPropsChange}
/>
</label>
</div>
<div className="prop same-line">
<label>
Include end punctuation
<input
className="checkbox"
type="checkbox"
name="includeEndPunctuation"
checked={componentProps.includeEndPunctuation}
onChange={handleComponentPropsChange}
/>
</label>
</div>
<button
className="reset"
type="button"
onClick={resetComponentProps}
disabled={areAllComponentPropsDefault}
>
Reset to Default Props
</button>
</section>
<section className="component">
<h2>Component</h2>
<div className="code">
<div className="line">{'import { LoremHeading } from "react-lorem-ipsum";'}</div>
</div>
<div className="code">
<div className="line">{`<LoremHeading${areAllComponentPropsDefault ? ' />' : ''}`}</div>
{componentProps.p !== defaultComponentProps.p && (
<div className="line">{`p={${componentProps.p}}`}</div>
)}
{componentProps.avgWordsPerHeading !== defaultComponentProps.avgWordsPerHeading && (
<div className="line">{`avgWordsPerHeading={${componentProps.avgWordsPerHeading}}`}</div>
)}
{componentProps.includeEndPunctuation !==
defaultComponentProps.includeEndPunctuation && (
<div className="line">{`includeEndPunctuation${
componentProps.includeEndPunctuation && '="true"'
}`}</div>
)}
{!areAllComponentPropsDefault && <div className="line">{'/>'}</div>}
</div>
</section>
</div>
<h2>Output</h2>
<section className="output">
<LoremHeading
p={componentProps.p}
avgWordsPerHeading={componentProps.avgWordsPerHeading}
includeEndPunctuation={componentProps.includeEndPunctuation}
/>
</section>
</div>
);
};

export default Heading;
24 changes: 22 additions & 2 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ export const surname: () => string;
*/
export const username: () => string;

interface LoremHeadingProps {
p?: string | number;
avgWordsPerHeading?: string | number;
includeEndPunctuation?: boolean;
}

/**
* LoremHeading (Component) generates JSX
*
* Props :
* - P = 1 - Number of paragraphs
* - avgWordsPerHeading = 3 - Average number of words per heading
* - includeEndPunctuation = true - If disabled removes end punctuation
*/
export const LoremHeading: React.FC<LoremHeadingProps>;
/**
* loremHeading (function) returns plain text
*/
export const loremHeading: (LoremHeadingProps?: LoremHeadingProps) => string[];

interface LoremIpsumProps {
p?: string | number;
avgWordsPerSentence?: string | number;
Expand All @@ -51,8 +71,8 @@ interface LoremIpsumProps {
*
* Props :
* - P = 1 - Number of paragraphs
* - avgWordsPerSentence = 8 - Avarage number of words per sentence
* - avgSentencesPerParagraph = 8 - Avarage number of sentences per paragraph
* - avgWordsPerSentence = 8 - Average number of words per sentence
* - avgSentencesPerParagraph = 8 - Average number of sentences per paragraph
* - startWithLoremIpsum = true - Start with 'Lorem ipsum odor amet...' to first sentence of first paragraph
* - random = true - If disabled always generates the same text.
*/
Expand Down
13 changes: 12 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import { LoremIpsum, loremIpsum } from './lorem-ipsum';
import { LoremHeading, loremHeading } from './lorem-heading';
import { Avatar, name, surname, fullname, username } from './user';

export { LoremIpsum, loremIpsum, Avatar, name, surname, fullname, username };
export {
LoremIpsum,
loremIpsum,
LoremHeading,
loremHeading,
Avatar,
name,
surname,
fullname,
username,
};
export default LoremIpsum;
66 changes: 66 additions & 0 deletions src/lorem-heading/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import PropTypes from 'prop-types';

import {
randomFromRange,
randomPositiveFromRange,
getStandardDeviation,
parseIntWithDefault,
} from '../utils';
import words from '../data/words.json';

// Default Props of the Component
const defaultProps = {
p: 1,
avgWordsPerHeading: 3,
includeEndPunctuation: false,
};

// Standard deviation percentage for words
const stDevPercentage = 0.25;

// Get a random word from Latin word list
const getRandomWord = () => words[randomFromRange(0, words.length - 1)];

// Get a punctuation for end of the heading randomly
const endPunctuation = includeEndPunctuation => {
if (includeEndPunctuation) {
const random = Math.random();
// 1% probability exclamation mark, 4% probability question mark, 95% probability dot
if (random > 0.99) return '!';
if (random > 0.95) return '?';
return '.';
}
return '';
};

// Create a Heading by using random words
const loremHeading = ({ avgWordsPerHeading, includeEndPunctuation }) => {
const awps = parseIntWithDefault(avgWordsPerHeading, defaultProps.avgWordsPerHeading);
const stDev = getStandardDeviation(awps, stDevPercentage);
const headingLength = randomPositiveFromRange(awps - stDev, awps + stDev);

let heading = '';
for (let i = 0; i < headingLength; i += 1) {
heading += `${getRandomWord()} `;
}
heading = `${heading.charAt(0).toUpperCase() + heading.substr(1).trim()}${endPunctuation(
includeEndPunctuation
)}`;
return heading;
};

// Component create Lorem Heading as HTML
const LoremHeading = props => {
const heading = loremHeading(props);
return heading;
};

LoremHeading.propTypes = {
p: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
avgWordsPerHeading: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
includeEndPunctuation: PropTypes.bool,
};

LoremHeading.defaultProps = defaultProps;

export { LoremHeading, loremHeading };