react-gif-picker-control
Version:
A GIF picker control built with and for React
760 lines (714 loc) • 39.9 kB
JavaScript
'use strict';
var React = require('react');
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z$b = ".rgp * {\r\n padding: 0;\r\n margin: 0;\r\n box-sizing: border-box;\r\n}\r\n\r\n.rgp-gif-picker {\r\n min-width: 150px;\r\n max-width: 500px;\r\n}\r\n\r\n.rgp-search-bar-container {\r\n padding: 0.5rem;\r\n}\r\n\r\n.rgp-divider {\r\n min-height: 1px;\r\n}\r\n\r\n.rgp-display-result-container {\r\n display: flex;\r\n justify-content: center;\r\n}\r\n";
styleInject(css_248z$b);
var ColorPalette = /** @class */ (function () {
function ColorPalette() {
this.primary = "#424242";
this.accent = "#FFA25F";
this.background = "#676767";
this.text = "#FFF";
}
return ColorPalette;
}());
var Dimension = /** @class */ (function () {
function Dimension(width, height) {
this.width = width;
this.height = height;
}
return Dimension;
}());
var gifPickerDefaultContext = {
tenorAPI: null,
colors: new ColorPalette(),
dimension: new Dimension(),
searchLimit: 0,
imageErrorUrl: "",
imageNoResultsUrl: "",
};
var GifPickerContext = React.createContext(gifPickerDefaultContext);
var css_248z$a = ".rgp-search-bar {\r\n padding: 0.5rem;\r\n border-radius: 5px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n}\r\n\r\n.rgp-search-input {\r\n width: 100%;\r\n outline: none;\r\n background: transparent;\r\n border: none;\r\n}\r\n";
styleInject(css_248z$a);
var css_248z$9 = ".rgp-icon {\r\n width: 20px;\r\n height: 20px;\r\n}\r\n\r\n.rgp-btn-icon {\r\n cursor: pointer;\r\n transition: transform 0.5s;\r\n}\r\n\r\n.rgp-btn-icon:hover {\r\n transform: rotate(90deg);\r\n}\r\n";
styleInject(css_248z$9);
//! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
var CloseIcon = function (props) {
var _a = props.color, color = _a === void 0 ? "#fff" : _a, _b = props.onClick, onClick = _b === void 0 ? function () { return undefined; } : _b;
return (React.createElement("svg", { className: "rgp-icon rgp-btn-icon", fill: color, onClick: onClick, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 384 512" },
React.createElement("path", { d: "M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z" })));
};
//! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
var SearchIcon = function (_a) {
var _b = _a.color, color = _b === void 0 ? "#fff" : _b;
return (React.createElement("svg", { className: "rgp-icon", fill: color, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" },
React.createElement("path", { d: "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" })));
};
var SearchBar = function (_a) {
var term = _a.term, onChange = _a.onChange, onClear = _a.onClear, autoFocus = _a.autoFocus;
var colors = React.useContext(GifPickerContext).colors;
var handleOnChangeInput = function (event) {
event.preventDefault();
onChange(event.target.value);
};
return (React.createElement("div", { className: "rgp-search-bar", style: { background: colors.primary } },
React.createElement("input", { className: "rgp-search-input", value: term, onChange: handleOnChangeInput, placeholder: "Search Tenor", style: { color: colors.text }, autoFocus: autoFocus }),
term.length > 0 ? (React.createElement(CloseIcon, { color: colors.accent, onClick: onClear })) : (React.createElement(SearchIcon, { color: colors.accent }))));
};
var Category = /** @class */ (function () {
function Category(name, image) {
this.name = name;
this.image = image;
}
return Category;
}());
var Gif = /** @class */ (function () {
function Gif(id, description, urlPreview, urlMedia, width, height, createdAtTimestampUnix) {
this.id = id;
this.description = description;
this.urlPreview = urlPreview;
this.urlMedia = urlMedia;
this.width = width;
this.height = height;
this.createdAt = new Date(createdAtTimestampUnix * 1000);
}
return Gif;
}());
var baseUrl = "https://tenor.googleapis.com/v2";
var TenorService = /** @class */ (function () {
function TenorService(tenorApiKey) {
this.tenorApiKey = tenorApiKey;
}
TenorService.prototype.getCategories = function () {
return fetch("".concat(baseUrl, "/categories?key=").concat(this.tenorApiKey))
.then(function (response) {
if (!response.ok) {
throw new Error("[".concat(response.status, "] ").concat(response.statusText));
}
return response.json();
})
.then(function (data) {
return data.tags.map(function (tag) { return new Category(tag.name.slice(1), tag.image); });
});
};
TenorService.prototype.getTrendingSearchTerms = function () {
return fetch("".concat(baseUrl, "/trending_terms?key=").concat(this.tenorApiKey))
.then(function (response) {
if (!response.ok) {
throw new Error("[".concat(response.status, "] ").concat(response.statusText));
}
return response.json();
})
.then(function (data) { return data.results; });
};
TenorService.prototype.getSearchSuggestion = function (term) {
return fetch("".concat(baseUrl, "/search_suggestions?q=").concat(term, "&key=").concat(this.tenorApiKey))
.then(function (response) {
if (!response.ok) {
throw new Error("[".concat(response.status, "] ").concat(response.statusText));
}
return response.json();
})
.then(function (data) { return data.results; });
};
TenorService.prototype.search = function (term, limit) {
if (limit === void 0) { limit = 50; }
return fetch("".concat(baseUrl, "/search?q=").concat(term, "&limit=").concat(limit, "&key=").concat(this.tenorApiKey))
.then(function (response) {
if (!response.ok) {
throw new Error("[".concat(response.status, "] ").concat(response.statusText));
}
return response.json();
})
.then(function (data) {
return data.results.map(function (gif) {
var gifMedia = gif.media_formats["gif"];
return new Gif(gif.id, gif.content_description, gifMedia.preview, gifMedia.url, gifMedia.dims[0], gifMedia.dims[1], gif.created);
});
});
};
return TenorService;
}());
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var css_248z$8 = ".rgp-categories-list {\r\n --scrollbar-color: #fff;\r\n --no-columns: 3;\r\n\r\n display: grid;\r\n grid-template-columns: repeat(var(--no-columns), 1fr);\r\n gap: 0.5rem;\r\n width: 100%;\r\n overflow-y: auto;\r\n padding: 1rem;\r\n}\r\n\r\n.rgp-categories-list::-webkit-scrollbar {\r\n width: 4px;\r\n}\r\n\r\n.rgp-categories-list::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n\r\n.rgp-categories-list::-webkit-scrollbar-thumb {\r\n background: var(--scrollbar-color);\r\n}\r\n";
styleInject(css_248z$8);
var css_248z$7 = ".rgp-loader {\r\n --scrollbar-color: #fff;\r\n --no-columns: 4;\r\n width: 100%;\r\n overflow-x: hidden;\r\n}\r\n\r\n.rgp-loader .rgp-loader-container {\r\n display: grid;\r\n grid-template-columns: repeat(var(--no-columns), 1fr);\r\n padding: 1rem;\r\n gap: 1rem;\r\n}\r\n\r\n.rgp-loader::-webkit-scrollbar {\r\n width: 4px;\r\n}\r\n\r\n.rgp-loader::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n\r\n.rgp-loader::-webkit-scrollbar-thumb {\r\n background: var(--scrollbar-color);\r\n}\r\n";
styleInject(css_248z$7);
var css_248z$6 = ".rgp-card-loader {\r\n background: white;\r\n opacity: 0.3;\r\n border-radius: 5px;\r\n display: inline-block;\r\n width: 100%;\r\n animation: opacityChange 1s infinite alternate;\r\n}\r\n\r\n@keyframes opacityChange {\r\n 0% {\r\n opacity: 0.1;\r\n }\r\n 100% {\r\n opacity: 0.4;\r\n }\r\n}\r\n";
styleInject(css_248z$6);
var CardLoader = function (_a) {
var height = _a.height;
var cardRef = React.useRef(null);
var _b = React.useState(0), spans = _b[0], setSpans = _b[1];
React.useEffect(function () {
getSpans();
}, []);
var getSpans = function () {
if (!cardRef.current) {
return;
}
var spansNeeded = Math.ceil(height / 100);
setSpans(spansNeeded);
};
return (React.createElement("div", { ref: cardRef, className: "rgp-card-loader", style: { gridRowEnd: "span ".concat(spans), height: height } }));
};
var Loader = function (_a) {
var type = _a.type;
var loaderRef = React.useRef(null);
var _b = React.useContext(GifPickerContext), colors = _b.colors, dimension = _b.dimension;
var _c = React.useState(0), noColumns = _c[0], setNoColumns = _c[1];
React.useEffect(function () {
if (!loaderRef.current) {
return;
}
loaderRef.current.style.setProperty("--scrollbar-color", colors.accent);
var width = Math.min(dimension.width, window.innerWidth);
var gridColumns = type === 0 ? 3 : 4;
if (type === 0) {
if (width < 250) {
gridColumns = 1;
}
else if (width < 450) {
gridColumns = 2;
}
}
else {
if (width < 450) {
gridColumns = 2;
}
else if (width < 250) {
gridColumns = 1;
}
else if (width < 400) {
gridColumns = 2;
}
else if (width < 490) {
gridColumns = 3;
}
}
loaderRef.current.style.setProperty("--no-columns", gridColumns.toString());
setNoColumns(gridColumns);
}, [dimension]);
var renderCardsLoader = function () {
return Array.from({ length: (dimension.height / 100) * noColumns }, function (_, index) {
return React.createElement(CardLoader, { key: index, height: 100 });
});
};
return (React.createElement("div", { ref: loaderRef, className: "rgp-loader", style: { height: dimension.height } },
React.createElement("div", { className: "rgp-loader-container" }, renderCardsLoader())));
};
var css_248z$5 = ".rgp-error-layout {\r\n padding: 1rem;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n text-align: center;\r\n gap: 1rem;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.rgp-error-layout .rgp-error-header {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.rgp-error-layout .rgp-error-media-content {\r\n max-width: 100%;\r\n}\r\n";
styleInject(css_248z$5);
var defaultErrorMessage = "Something went wrong!";
var ErrorLayout = function (_a) {
var _b = _a.errorMessage, errorMessage = _b === void 0 ? defaultErrorMessage : _b;
var _c = React.useContext(GifPickerContext), imageErrorUrl = _c.imageErrorUrl, colors = _c.colors;
return (React.createElement("div", { className: "rgp-error-layout" },
React.createElement("h4", { className: "rgp-error-header", style: { color: colors.accent } }, errorMessage),
imageErrorUrl.length > 0 && (React.createElement("img", { className: "rgp-error-media-content", src: imageErrorUrl, alt: errorMessage, title: "Error", loading: "lazy" }))));
};
var css_248z$4 = ".rgp-category-card {\r\n --background-image: transparent;\r\n --accent-color: transparent;\r\n --bg-color: transparent;\r\n --hCard: 120px;\r\n\r\n position: relative;\r\n border-radius: 5px;\r\n height: var(--hCard);\r\n cursor: pointer;\r\n border: 0.5px var(--bg-color) solid;\r\n}\r\n\r\n.rgp-category-card::before {\r\n content: \"\";\r\n position: absolute;\r\n background: var(--background-image);\r\n width: 100%;\r\n height: 100%;\r\n top: 0;\r\n left: 0;\r\n opacity: 0.5;\r\n border-radius: 5px;\r\n transition: all 0.4s linear;\r\n}\r\n\r\n.rgp-category-card > .rgp-title {\r\n z-index: 2;\r\n position: absolute;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n width: 100%;\r\n overflow: hidden;\r\n}\r\n\r\n.rgp-category-card:hover {\r\n border: 1px var(--accent-color) solid;\r\n}\r\n\r\n.rgp-category-card:hover::before {\r\n opacity: 0.1;\r\n}\r\n";
styleInject(css_248z$4);
var CategoryCard = function (_a) {
var category = _a.category, onSelectCategory = _a.onSelectCategory;
var categoryCardRef = React.useRef(null);
var _b = React.useContext(GifPickerContext), dimension = _b.dimension, colors = _b.colors;
React.useEffect(function () {
if (!categoryCardRef.current) {
return;
}
categoryCardRef.current.style.setProperty("--background-image", "url(".concat(category.image, ") no-repeat center center / cover"));
categoryCardRef.current.style.setProperty("--accent-color", colors.accent);
categoryCardRef.current.style.setProperty("--bg-color", colors.background);
var widthCard = Math.min(dimension.width, window.innerWidth);
var heightCard = "".concat(widthCard < 300 ? 50 : 120, "px");
categoryCardRef.current.style.setProperty("--hCard", heightCard);
}, []);
var handleOnSelectCategory = function () {
onSelectCategory(category);
};
return (React.createElement("div", { ref: categoryCardRef, className: "rgp-category-card", title: category.name, onClick: handleOnSelectCategory, style: { background: colors.primary } },
React.createElement("div", { className: "rgp-title" }, category.name)));
};
var CategoriesList = function (_a) {
var onSelectCategory = _a.onSelectCategory;
var categoryListRef = React.useRef(null);
var _b = React.useContext(GifPickerContext), tenorAPI = _b.tenorAPI, dimension = _b.dimension, colors = _b.colors;
var _c = React.useState([]), categories = _c[0], setCategories = _c[1];
var _d = React.useState(true), isLoading = _d[0], setIsLoading = _d[1];
var _e = React.useState(false), isError = _e[0], setIsError = _e[1];
React.useEffect(function () {
var getCategories = function () { return __awaiter(void 0, void 0, void 0, function () {
var rCategories, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, 3, 4]);
setIsLoading(true);
return [4 /*yield*/, tenorAPI.getCategories()];
case 1:
rCategories = _a.sent();
setCategories(rCategories);
setIsError(false);
return [3 /*break*/, 4];
case 2:
error_1 = _a.sent();
console.error("[Get Categories Error]", error_1);
setIsError(true);
return [3 /*break*/, 4];
case 3:
setIsLoading(false);
return [7 /*endfinally*/];
case 4: return [2 /*return*/];
}
});
}); };
getCategories();
}, []);
React.useEffect(function () {
if (isLoading || !categoryListRef.current) {
return;
}
categoryListRef.current.style.setProperty("--scrollbar-color", colors.accent);
var width = Math.min(dimension.width, window.innerWidth);
var gridColumns = 3;
if (width < 250) {
gridColumns = 1;
}
else if (width < 450) {
gridColumns = 2;
}
categoryListRef.current.style.setProperty("--no-columns", gridColumns.toString());
}, [isLoading]);
var handleOnSelectCategory = function (category) {
onSelectCategory(category.name);
};
if (isLoading) {
return React.createElement(Loader, { type: 0 });
}
if (isError) {
return React.createElement(ErrorLayout, null);
}
var renderCategories = function () {
return categories.map(function (category) { return (React.createElement(CategoryCard, { key: category.name, category: category, onSelectCategory: handleOnSelectCategory })); });
};
return (React.createElement("div", { ref: categoryListRef, className: "rgp-categories-list" }, renderCategories()));
};
var css_248z$3 = ".rgp-search-results {\r\n --scrollbar-color: #fff;\r\n --no-columns: 4;\r\n --grid-column-footer: 5;\r\n --overflow-y: hidden;\r\n width: 100%;\r\n overflow-y: var(--overflow-y);\r\n overflow-x: hidden;\r\n}\r\n\r\n.rgp-search-results .rgp-search-results-container {\r\n display: grid;\r\n grid-template-columns: repeat(var(--no-columns), 1fr);\r\n padding: 1rem;\r\n}\r\n\r\n.rgp-search-results .rgp-footer {\r\n grid-column-start: 1;\r\n grid-column: 1 / var(--grid-column-footer);\r\n display: flex;\r\n gap: 0.5rem;\r\n flex-direction: column;\r\n align-items: center;\r\n text-align: center;\r\n}\r\n\r\n.rgp-tags {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: center;\r\n align-items: center;\r\n gap: 0.2rem;\r\n}\r\n\r\n.rgp-search-results::-webkit-scrollbar {\r\n width: 4px;\r\n}\r\n\r\n.rgp-search-results::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n\r\n.rgp-search-results::-webkit-scrollbar-thumb {\r\n background: var(--scrollbar-color);\r\n}\r\n";
styleInject(css_248z$3);
var css_248z$2 = ".rgp-tag {\r\n --accent-color: transparent;\r\n --bg-color: transparent;\r\n padding: 0.2rem 0.5rem;\r\n border-radius: 5px;\r\n cursor: pointer;\r\n background: var(--bg-color);\r\n transition: background 0.5s;\r\n}\r\n\r\n.rgp-tag:hover {\r\n background: var(--accent-color);\r\n}\r\n";
styleInject(css_248z$2);
var Tag = function (_a) {
var label = _a.label, onClickTag = _a.onClickTag;
var tagRef = React.useRef(null);
var colors = React.useContext(GifPickerContext).colors;
React.useEffect(function () {
if (!tagRef.current) {
return;
}
tagRef.current.style.setProperty("--accent-color", colors.accent);
tagRef.current.style.setProperty("--bg-color", colors.primary);
}, []);
var handleOnClick = function () {
onClickTag(label);
};
return (React.createElement("div", { ref: tagRef, className: "rgp-tag", onClick: handleOnClick }, label));
};
var css_248z$1 = ".rgp-gif-card {\r\n --accent-color: transparent;\r\n --bg-color: transparent;\r\n --width-image: 110px;\r\n}\r\n\r\n.rgp-gif-card .rgp-gif-image {\r\n width: var(--width-image);\r\n padding: 0;\r\n border-radius: 5px;\r\n border: 2px var(--bg-color) solid;\r\n}\r\n\r\n.rgp-gif-card .rgp-gif-image:hover {\r\n border: 2px var(--accent-color) solid;\r\n}\r\n";
styleInject(css_248z$1);
var GifCard = function (_a) {
var gif = _a.gif, onSelectGif = _a.onSelectGif, gifsLoaded = _a.gifsLoaded, onLoadedGif = _a.onLoadedGif;
var gifCardRef = React.useRef(null);
var imageRef = React.useRef(null);
var _b = React.useContext(GifPickerContext), colors = _b.colors, dimension = _b.dimension;
var _c = React.useState(0), spans = _c[0], setSpans = _c[1];
React.useEffect(function () {
if (!gifCardRef.current) {
return;
}
gifCardRef.current.style.setProperty("--accent-color", colors.accent);
gifCardRef.current.style.setProperty("--bg-color", colors.background);
var width = Math.min(dimension.width, window.innerWidth);
var imageWidth = 110;
if (width < 300) {
imageWidth = 100;
}
else if (width < 350) {
imageWidth = 130;
}
else if (width < 400) {
imageWidth = 150;
}
else if (width < 450) {
imageWidth = 120;
}
else if (width < 500) {
imageWidth = 140;
}
gifCardRef.current.style.setProperty("--width-image", "".concat(imageWidth, "px"));
}, []);
var getSpans = function () {
if (!imageRef.current) {
return;
}
var height = imageRef.current.clientHeight;
var spansNeeded = Math.ceil(height / 10);
setSpans(spansNeeded);
};
var handleOnClick = function () {
onSelectGif(gif);
};
return (React.createElement("div", { ref: gifCardRef, className: "rgp-gif-card", style: {
cursor: gifsLoaded ? "pointer" : "default",
gridRowEnd: "span ".concat(spans),
}, onClick: handleOnClick },
React.createElement("img", { ref: imageRef, className: "rgp-gif-image", src: gif.urlMedia, title: gifsLoaded ? gif.description : "", alt: gifsLoaded ? gif.description : "", onLoad: function () {
getSpans();
onLoadedGif();
}, style: { opacity: gifsLoaded ? 1 : 0 } })));
};
var css_248z = ".rgp-no-results-layout {\r\n --width-media: 300px;\r\n padding: 1rem 2rem;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n gap: 1rem;\r\n}\r\n\r\n.rgp-no-results-layout .rgp-media-content {\r\n width: var(--width-media);\r\n}\r\n\r\n.rgp-no-results-layout .rgp-footer {\r\n text-align: center;\r\n}\r\n";
styleInject(css_248z);
var noResultsMessage = "I haven't found anything. Please try one of the suggested keywords below!";
var NoResults = function (_a) {
var onSelectTag = _a.onSelectTag;
var noResultsRef = React.useRef(null);
var _b = React.useContext(GifPickerContext), tenorAPI = _b.tenorAPI, imageNoResultsUrl = _b.imageNoResultsUrl, colors = _b.colors, dimension = _b.dimension;
var _c = React.useState(false), isLoading = _c[0], setIsLoading = _c[1];
var _d = React.useState(false), isError = _d[0], setIsError = _d[1];
var _e = React.useState([]), trendingTerms = _e[0], setTrendingTerms = _e[1];
React.useEffect(function () {
if (!noResultsRef.current) {
return;
}
var width = Math.min(dimension.width, window.innerWidth);
var widthMedia = 300;
if (width < 350) {
widthMedia = 130;
}
else if (width < 400) {
widthMedia = 250;
}
noResultsRef.current.style.setProperty("--width-media", "".concat(widthMedia, "px"));
}, [isLoading]);
React.useEffect(function () {
var getTrendingTerms = function () { return __awaiter(void 0, void 0, void 0, function () {
var rTrendingTerms, err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, 3, 4]);
setIsLoading(true);
return [4 /*yield*/, tenorAPI.getTrendingSearchTerms()];
case 1:
rTrendingTerms = _a.sent();
setTrendingTerms(rTrendingTerms);
setIsError(false);
return [3 /*break*/, 4];
case 2:
err_1 = _a.sent();
console.error("[Trending Terms Error]", err_1);
setIsError(true);
return [3 /*break*/, 4];
case 3:
setIsLoading(false);
return [7 /*endfinally*/];
case 4: return [2 /*return*/];
}
});
}); };
getTrendingTerms();
}, []);
if (isLoading) {
return React.createElement(Loader, { type: 1 });
}
if (isError) {
return React.createElement(ErrorLayout, null);
}
var renderTags = function () {
return trendingTerms.map(function (term) { return (React.createElement(Tag, { key: term, label: term, onClickTag: onSelectTag })); });
};
return (React.createElement("div", { ref: noResultsRef, className: "rgp-no-results-layout" },
React.createElement("h2", { className: "rgp-no-results-header", style: { color: colors.accent } }, "404"),
React.createElement("img", { className: "rgp-media-content", src: imageNoResultsUrl, alt: "No results", title: "Nothing happens", loading: "lazy" }),
React.createElement("h4", { className: "rgp-footer", style: { color: colors.accent } }, noResultsMessage),
React.createElement("div", { className: "rgp-tags" }, renderTags())));
};
var suggestionsMessage = "Haven't found what you're looking for? Try one of the suggested keywords below!";
var SearchResultsList = function (_a) {
var searchTerm = _a.searchTerm, onSelectGif = _a.onSelectGif, onSelectTag = _a.onSelectTag;
var resultsListRef = React.useRef(null);
var _b = React.useContext(GifPickerContext), tenorAPI = _b.tenorAPI, colors = _b.colors, dimension = _b.dimension, searchLimit = _b.searchLimit;
var _c = React.useState([]), searchGifResults = _c[0], setSearchGifResults = _c[1];
var _d = React.useState(0), noGifsLoaded = _d[0], setNoGifsLoaded = _d[1];
var _e = React.useState([]), searchSuggestions = _e[0], setSearchSuggestions = _e[1];
var _f = React.useState(true), isLoading = _f[0], setIsLoading = _f[1];
var _g = React.useState(false), isError = _g[0], setIsError = _g[1];
var gifsLoaded = !isLoading && noGifsLoaded === searchGifResults.length;
React.useEffect(function () {
if (isLoading || !resultsListRef.current) {
return;
}
resultsListRef.current.style.setProperty("--scrollbar-color", colors.accent);
var width = Math.min(dimension.width, window.innerWidth);
var gridColumns = 4;
var gridColumnFooter = 5;
if (width < 250) {
gridColumns = 1;
gridColumnFooter = 2;
}
else if (width < 400) {
gridColumns = 2;
gridColumnFooter = 3;
}
else if (width < 490) {
gridColumns = 3;
gridColumnFooter = 4;
}
resultsListRef.current.style.setProperty("--no-columns", gridColumns.toString());
resultsListRef.current.style.setProperty("--grid-column-footer", gridColumnFooter.toString());
}, [isLoading]);
React.useEffect(function () {
if (isLoading || !resultsListRef.current) {
return;
}
if (gifsLoaded) {
resultsListRef.current.style.setProperty("--overflow-y", "auto");
return;
}
resultsListRef.current.style.setProperty("--overflow-y", "hidden");
}, [gifsLoaded]);
React.useEffect(function () {
var getResults = function (term) { return __awaiter(void 0, void 0, void 0, function () {
var _a, rResults, rSearchSuggestions, suggestions, err_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 4, 5, 6]);
setIsLoading(true);
return [4 /*yield*/, Promise.all([
tenorAPI.search(term, searchLimit),
tenorAPI.getSearchSuggestion(term),
])];
case 1:
_a = _b.sent(), rResults = _a[0], rSearchSuggestions = _a[1];
suggestions = rSearchSuggestions;
if (!(suggestions.length === 0)) return [3 /*break*/, 3];
return [4 /*yield*/, tenorAPI.getTrendingSearchTerms()];
case 2:
suggestions = _b.sent();
_b.label = 3;
case 3:
setSearchGifResults(rResults);
setSearchSuggestions(suggestions);
setIsError(false);
return [3 /*break*/, 6];
case 4:
err_1 = _b.sent();
console.error("Search Error", err_1);
setIsError(true);
return [3 /*break*/, 6];
case 5:
setIsLoading(false);
return [7 /*endfinally*/];
case 6: return [2 /*return*/];
}
});
}); };
setNoGifsLoaded(0);
getResults(searchTerm);
var timer = setTimeout(function () {
if (!resultsListRef.current) {
return;
}
resultsListRef.current.scrollTo(0, 0);
}, 0.1);
return function () {
clearTimeout(timer);
};
}, [searchTerm]);
if (isLoading) {
return React.createElement(Loader, { type: 1 });
}
if (isError) {
return React.createElement(ErrorLayout, null);
}
var handleOnSelectGif = function (selectedGif) {
onSelectGif(selectedGif);
};
var handleOnLoadedGif = function () {
setNoGifsLoaded(function (prevNoGifsLoaded) { return prevNoGifsLoaded + 1; });
};
var renderGifResults = function () {
return searchGifResults.map(function (gif) {
return (React.createElement(GifCard, { key: gif.id, gif: gif, gifsLoaded: gifsLoaded, onSelectGif: handleOnSelectGif, onLoadedGif: handleOnLoadedGif }));
});
};
var renderTags = function () {
return searchSuggestions.map(function (suggestion) { return (React.createElement(Tag, { key: suggestion, label: suggestion, onClickTag: onSelectTag })); });
};
var renderList = function () {
if (searchGifResults.length === 0) {
return React.createElement(NoResults, { onSelectTag: onSelectTag });
}
return (React.createElement(React.Fragment, null,
!gifsLoaded && React.createElement(Loader, { type: 1 }),
React.createElement("div", { className: "rgp-search-results-container" },
renderGifResults(),
gifsLoaded && (React.createElement("div", { className: "rgp-footer" },
React.createElement("h4", { className: "rgp-footer-message", style: { color: colors.accent } }, suggestionsMessage),
React.createElement("div", { className: "rgp-tags" }, renderTags()))))));
};
return (React.createElement("div", { ref: resultsListRef, className: "rgp-search-results" }, renderList()));
};
// constants
var defaultSearchLimit = 50;
var defaultImageErrorUrl = "https://media.tenor.com/OxvVRFnPZO8AAAAC/error-the-simpsons.gif";
var defaultImageNoResultsUrl = "https://media.tenor.com/jJHoqBHOqVkAAAAC/animated-cartoon.gif";
var defaultWidth = 350;
var defaultHeight = 450;
var GifPicker = function (_a) {
var tenorApiKey = _a.tenorApiKey, onGifClick = _a.onGifClick, _b = _a.colors, colors = _b === void 0 ? new ColorPalette() : _b, _c = _a.width, width = _c === void 0 ? defaultWidth : _c, _d = _a.height, height = _d === void 0 ? defaultHeight : _d, _e = _a.searchLimit, searchLimit = _e === void 0 ? defaultSearchLimit : _e, _f = _a.imageErrorUrl, imageErrorUrl = _f === void 0 ? defaultImageErrorUrl : _f, _g = _a.imageNoResultsUrl, imageNoResultsUrl = _g === void 0 ? defaultImageNoResultsUrl : _g, _h = _a.hideCategories, hideCategories = _h === void 0 ? false : _h, _j = _a.autoFocus, autoFocus = _j === void 0 ? true : _j;
if (!tenorApiKey || !onGifClick) {
return (React.createElement("div", { style: {
background: colors.primary,
} },
React.createElement(ErrorLayout, { errorMessage: "You need to provide the following props: tenorApiKey and onSelectedGif" })));
}
var containerW = width < 150 ? 150 : width > 500 ? 500 : width;
var containerH = height > 500 ? 500 : height;
var _k = React.useState(gifPickerDefaultContext), gifPickerContext = _k[0], setGifPickerContext = _k[1];
var _l = React.useState(""), searchTerm = _l[0], setSearchTerm = _l[1];
var _m = React.useState(""), debouncedSearchTerm = _m[0], setDobouncedSearchTerm = _m[1];
React.useEffect(function () {
setGifPickerContext({
tenorAPI: new TenorService(tenorApiKey),
colors: colors,
dimension: new Dimension(containerW, containerH),
searchLimit: searchLimit,
imageErrorUrl: imageErrorUrl,
imageNoResultsUrl: imageNoResultsUrl,
});
}, []);
React.useEffect(function () {
var timerId = setTimeout(function () {
setDobouncedSearchTerm(searchTerm);
}, 1000);
return function () {
clearTimeout(timerId);
};
}, [searchTerm]);
var handleOnChangeSearchTerm = function (newTerm) {
setSearchTerm(newTerm);
};
var handleOnClearSearchTerm = function () {
setSearchTerm("");
setDobouncedSearchTerm("");
};
var handleOnSelectTerm = function (term) {
setSearchTerm(term);
setDobouncedSearchTerm(term);
};
var handleOnSelectGif = function (selectedGif) {
handleOnClearSearchTerm();
onGifClick(selectedGif);
};
var renderList = function () {
if (gifPickerContext.tenorAPI === null) {
return null;
}
if (debouncedSearchTerm.trim().length === 0) {
return (!hideCategories && (React.createElement(CategoriesList, { onSelectCategory: handleOnSelectTerm })));
}
return (React.createElement(SearchResultsList, { searchTerm: debouncedSearchTerm, onSelectTag: handleOnSelectTerm, onSelectGif: handleOnSelectGif }));
};
return (React.createElement(GifPickerContext.Provider, { value: gifPickerContext },
React.createElement("div", { className: "rgp", style: {
background: colors.background,
color: colors.text,
width: containerW,
} },
React.createElement("div", { className: "rgp-gif-picker" },
React.createElement("div", { className: "rgp-search-bar-container" },
React.createElement(SearchBar, { term: searchTerm, onChange: handleOnChangeSearchTerm, onClear: handleOnClearSearchTerm, autoFocus: autoFocus })),
(!hideCategories ||
debouncedSearchTerm.trim().length > 0) && (React.createElement("div", { className: "rgp-divider", style: {
background: colors.accent,
} })),
React.createElement("div", { className: "rgp-display-result-container", style: { maxHeight: containerH } }, renderList())))));
};
exports.GifPicker = GifPicker;
//# sourceMappingURL=index.js.map