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

V0.0.0.1 #4

Merged
merged 10 commits into from
Jan 7, 2018
Merged
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ typings/
# dotenv environment variables file
.env

example/bundle.js
example/bundle.js.map
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
example/
docs/
111 changes: 110 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,111 @@
# react-giphy-selector
A search modal for picking the perfect giphy.
A search and select React.JS component for picking the perfect giphy.

![Example selector](./docs/example_1.gif)

> This component is highly-customizable and only provides basic styling out-of-box. The example above includes simple customization to a few elements. You can view this example in `/example/src`.

## Table of Contents

- [Installation](#installation)
- [Usage](#usage)

## Installation

You just install `react-giphy-selector` the good ole' fashion way through NPM:

```
npm install --save react-giphy-selector
```

## Usage

This package exports the `Selector` React component and then two helper `enums`:

```js
import {Selector, ResultSort, Rating} from "react-giphy-selector";

```

- [Selector](#selector)
- [Rating](#rating)
- [ResultSort](#resultSort)

### Selector

The selector component contains all of the search, display, and selection logic. The only required properties are `apiKey` and `onGifSelected`.

```jsx
<Selector
apiKey={'myKey'}
onGifSelected={this.saveGif} />
```

That said, there are a bunch of props that allow you to make this component your own. Note: the `?` included at the end of a property name denotes it as optional.

- `apiKey: string`: [Your Giphy Project API Key](https://developers.giphy.com/).
- `onGifSelected?: (gifObject: IGifObject) => void`: The function to fire when a gif search result has been selected. The `IGifObject` represents the full [GIF Object](https://developers.giphy.com/docs/#gif-object) returned via the Giphy API.
- `rating?: Rating`: The maximum rating you want to allow in your search results. Use the exported [Rating](#rating) enum for help. Default: `Rating.G`.
- `sort?: ResultSort`: The sort order of the search results. Use the helper enum [ResultSort](#resultsort). Default: `ResultSort.Relevant`.
- `limit?: number`: The number of results to return. Default: `20`.
- `suggestions?: string[]`: An array containing one-click searches to make it easy for your user. Will not show suggestions section if none are passed. Default: `[]`.
- `queryInputPlaceholder?: string`: The placeholder text for the search bar text input. Default `'Enter search text'`.
- `resultColumns?: number`: The number of columns to divide the search results into. Default: `3`.
- `showGiphyMark?: boolean`: Indicates whether to show the "powered by Giphy" mark in the selector. This is required when [using a Giphy Production API Key](https://developers.giphy.com/docs/#production-key). Default: `true`.

#### Styling your Selector

There are a bunch of `props` to help you customize the style of the the selector. Both the `className` and the `style` methods are available. `react-giphy-selector` is very intentionally unopinionated about how exactly each section of the selector should look. Instead, the package offers a lot of customization and flexibility through the props below.

The images below will help you understand the nomenclature of the components:

![Diagram of component nomenclature for query form, suggestions, and footer](./docs/components_1.png)
![Diagram of component nomenclature for search results](./docs/components_2.png)

Here are all the props available for styling the component:

- `queryFormClassName?: string`: Additional `className` for the query form section of the component. You can find the default style applied in `src/components/QueryForm.css`.
- `queryFormInputClassName?: string`: Additional `className` for the text input in the query form. You can find the default style applied in `src/components/QueryForm.css`.
- `queryFormSubmitClassName?: string`: Additional `className` for the submit button in the query form. You can find the default style applied in `src/components/QueryForm.css`.
- `queryFormStyle?: object`: A style object to add to the query form style. You can find the default style applied in `src/components/QueryForm.css`.
- `queryFormInputStyle?: object`: A style object to add to the text input in the query form. You can find the default style applied in `src/components/QueryForm.css`.
- `queryFormSubmitStyle?: object`: A style object to add to the submit button in the query form. You can find the default style applied in `src/components/QueryForm.css`.
- `queryFormSubmitContent?: string or Component`: You can pass in a `string` or your own component to render inside the submit button in the query form. This allows you to pass in things like custom icons. Default: `'Search'`.
- `searchResultsClassName?: string`: Additional `className` for the search results component. You can find the default style in `src/components/SearchResults.css`.
- `searchResultsStyle?: object`: A style object to the add to the search results container. You can find the default style in `src/components/SearchResults.css`.
- `searchResultClassName?: string`: Additional `className` to add to a search result. Search results are `a` elements. You can find the default style in `src/components/SearchResult.css`.
- `searchResultStyle?: object`: A style object to add to a search result. Search results are `a` elements. You can find the default style in `src/components/SearchResult.css`.
- `suggestionsClassName?: string`: Additional `className` to add to the suggestions container. You can find the default style in `src/components/Suggestions.css`.
- `suggestionsStyle?: object`: A style object to add to the suggestions container. You can find the default style in `src/components/Suggestions.css`.
- `suggestionClassName?: string`: Additional `className` to add to a suggestion. This is an `a` element. You can find the default style in `src/components/Suggestion.css`.
- `suggestionStyle?: object`: A style object to add to a suggestion. This is an `a` element. You can find the default style in `src/components/Suggestion.css`.
- `loaderClassName?: string`: Additional `className` to add to the loader container. You can find the default style in `src/components/Selector.css`.
- `loaderStyle?: object`: A style object to add to the loader container. You can find the default style in `src/components/Selector.css`.
- `loaderContent?: string or Component`: You can pass in a `string` or customer component to display when results are loading. Default `'Loading'...`.
- `searchErrorClassName?: string`: Additional `className` to add to the error message shown on broken searches. You can find the default style in `src/components/Selector.css`.
- `searchErrorStyle?: object`: A style object to add to the error message shown on broken searches. You can find the default style in `src/components/Selector.css`.
- `footerClassName?: string`: Additional `className` to add to footer of selector. You can find the default style in `src/components/Selector.css`.
- `footerStyle?: object`: A style object to add to footer of selector. You can find the default style in `src/components/Selector.css`.

If you have a cool style you'd like to share, please [make an issue](https://github.com/tshaddix/react-giphy-selector/issues).

### Rating

The `Rating` enum contains all the possible ratings you can limit searches to:

```js
Rating.Y
Rating.G
Rating.PG
Rating.PG13
Rating.R
```

### ResultSort

The `ResultSort` enum contains the different sort methods supported by the Giphy API.

```js
ResultSort.Recent // ordered by most recent
ResultSort.Relevant // ordered by relevance
```
Binary file added docs/components_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/components_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/example_1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions example/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React Giphy Selector - Example</title>
</head>
<body>
<div id="example"></div>

<!-- Main -->
<script src="./bundle.js"></script>
</body>
</html>
39 changes: 39 additions & 0 deletions example/src/example.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.customQueryFormSubmit {
background: #0097cf;
color: #fff;
border: 0;
padding: 10px 20px;
font-size: 16px;
font-weight: bold;
}

.customQueryFormInput {
padding-left: 10px;
padding-right: 10px;
border: 1px solid #e0e0e0;
border-right: 0;
box-shadow: none;
}

.customSearchResults {
max-height: 400px;
margin-top: 10px;
margin-bottom: 10px;
}

/********************************
CSS classes for example fake modal
********************************/

body {
background: #333;
font-family: sans-serif;
}

.modal {
max-width: 600px;
margin: 60px auto;
background: #fff;
padding: 20px;
border-bottom: 5px solid #111;
}
98 changes: 98 additions & 0 deletions example/src/example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Selector, Rating } from "../../lib";
import * as React from "react";
import * as ReactDOM from "react-dom";

const customStyle = require("./example.css");

// feel free to change these :)
const suggestions = [
"watching",
"quiz",
"stop it",
"nice one",
"learning",
"reading",
"working"
];

interface IExampleProps {
suggestions: string[];
}

interface IExampleState {
apiKey: string;
isKeySubmitted: boolean;
}

class ExampleApp extends React.Component<IExampleProps, IExampleState> {
state: IExampleState;

constructor(props: IExampleProps) {
super(props);

this.state = {
apiKey: "",
isKeySubmitted: false
};

this.onKeyChange = this.onKeyChange.bind(this);
this.onKeySubmit = this.onKeySubmit.bind(this);
this.onGifSelected = this.onGifSelected.bind(this);
}

public onKeyChange(event: any): void {
this.setState({ apiKey: event.target.value });
}

public onKeySubmit(event: any): void {
event.preventDefault();

this.setState({
isKeySubmitted: true
});
}

public onGifSelected(gifObject: any): void {
alert(`You selected a gif! id: ${gifObject.id}`);
}

public render(): JSX.Element {
const { apiKey, isKeySubmitted } = this.state;
const { suggestions } = this.props;

if (!isKeySubmitted) {
return (
<form onSubmit={this.onKeySubmit}>
<input
type="text"
placeholder="Enter your Giphy API Key"
value={apiKey}
onChange={this.onKeyChange}
/>
<button type="submit">Set API Key</button>
</form>
);
}

return (
<div className={customStyle.modal}>
<Selector
apiKey={apiKey}
suggestions={suggestions}
onGifSelected={this.onGifSelected}
rating={Rating.G}
limit={40}
queryFormInputClassName={customStyle.customQueryFormInput}
queryFormSubmitClassName={customStyle.customQueryFormSubmit}
searchResultsClassName={customStyle.customSearchResults}
searchResultClassName={customStyle.customSearchResult}
/>
</div>
);
}
}

ReactDOM.render(
<ExampleApp suggestions={suggestions} />,
document.getElementById("example")
);
30 changes: 30 additions & 0 deletions example/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
entry: "./example/src/example.tsx",
output: {
filename: "bundle.js",
path: __dirname
},

// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",

resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},

module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },

// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

{
test: /\.css$/,
loader: ["style-loader", "css-loader?sourceMap&modules"]
}
]
}
};
2 changes: 2 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export {Rating, ResultSort, IGifImage, IGifObject} from './src/types';
export {Selector, ISelectorProps} from './src/components/Selector';
Loading