@gravatar-com/hovercards
Version:
Add profile hovercards to Gravatar images.
544 lines (523 loc) • 24.5 kB
JavaScript
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
i: () => (/* reexport */ Hovercards)
});
;// CONCATENATED MODULE: ./src/compute-position.ts
var paddingMap = {
top: 'paddingBottom',
bottom: 'paddingTop',
left: 'paddingRight',
right: 'paddingLeft'
};
/**
* Computes the position of a card relative to a ref element.
*
* @param {HTMLElement} ref - The ref element.
* @param {HTMLDivElement} card - The card element.
* @param {Options} [options={}] - The placement, offset, and auto-flip options.
* @return {ReturnValues} - The computed position values.
*/
function computingPosition(ref, card, _temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$placement = _ref.placement,
placement = _ref$placement === void 0 ? 'right' : _ref$placement,
_ref$offset = _ref.offset,
offset = _ref$offset === void 0 ? 0 : _ref$offset,
_ref$autoFlip = _ref.autoFlip,
autoFlip = _ref$autoFlip === void 0 ? true : _ref$autoFlip;
var refRect = ref.getBoundingClientRect();
var cardRect = card.getBoundingClientRect();
var refScrollT = refRect.top + scrollY;
var refScrollB = refRect.bottom + scrollY;
var refScrollR = refRect.right + scrollX;
var refScrollL = refRect.left + scrollX;
var x = 0;
var y = 0;
var _placement$split = placement.split('-'),
dir = _placement$split[0],
align = _placement$split[1];
offset = Math.max(0, offset);
// Auto flip the card if there's not enough space
// If both sides have not enough space, then the card will be placed on the side with more space
if (autoFlip) {
var topSpace = refRect.top;
var bottomSpace = innerHeight - refRect.bottom;
var leftSpace = refRect.left;
var rightSpace = innerWidth - refRect.right;
var floatingSpaceV = cardRect.height + offset;
var floatingSpaceH = cardRect.width + offset;
if (dir === 'top' && topSpace < floatingSpaceV && bottomSpace > topSpace) {
dir = 'bottom';
}
if (dir === 'bottom' && bottomSpace < floatingSpaceV && topSpace > bottomSpace) {
dir = 'top';
}
if (dir === 'left' && leftSpace < floatingSpaceH && rightSpace > leftSpace) {
dir = 'right';
}
if (dir === 'right' && rightSpace < floatingSpaceH && leftSpace > rightSpace) {
dir = 'left';
}
}
// Calculate the position of the card
if (dir === 'top' || dir === 'bottom') {
x = refScrollL + refRect.width / 2 - cardRect.width / 2;
// The bottom offset will be filled with the card's padding
y = dir === 'top' ? refScrollT - cardRect.height - offset : refScrollB;
if (align === 'start') {
x = refScrollL;
}
if (align === 'end') {
x = refScrollR - cardRect.width;
}
} else {
// The right offset will be filled with the card's padding
x = dir === 'right' ? refScrollR : refScrollL - cardRect.width - offset;
y = refScrollT + refRect.height / 2 - cardRect.height / 2;
if (align === 'start') {
y = refScrollT;
}
if (align === 'end') {
y = refScrollB - cardRect.height;
}
}
return {
x: x,
y: y,
padding: paddingMap[dir],
paddingValue: offset
};
}
;// CONCATENATED MODULE: ./src/sanitizer.ts
function escHtml(str) {
var htmlEntities = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'`': '`'
};
// Don't escape if already escaped.
return str.replace(/&(amp|lt|gt|quot|#39|x60);|[\&<>"'`]/g, function (match) {
return match[0] === '&' ? match : htmlEntities[match];
});
}
function escUrl(url) {
return encodeURI(url);
}
;// CONCATENATED MODULE: ./src/i18n.ts
function __(i18n, key) {
return i18n[key] || key;
}
;// CONCATENATED MODULE: ./src/core.ts
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
var BASE_API_URL = 'https://secure.gravatar.com';
var socialLinksOrder = ['wordpress', 'mastodon', 'tumblr', 'github', 'twitter'];
var dc = document;
var Hovercards = /*#__PURE__*/function () {
function Hovercards(_temp) {
var _this = this;
var _ref = _temp === void 0 ? {} : _temp,
_ref$placement = _ref.placement,
placement = _ref$placement === void 0 ? 'right' : _ref$placement,
_ref$autoFlip = _ref.autoFlip,
autoFlip = _ref$autoFlip === void 0 ? true : _ref$autoFlip,
_ref$offset = _ref.offset,
offset = _ref$offset === void 0 ? 10 : _ref$offset,
_ref$delayToShow = _ref.delayToShow,
delayToShow = _ref$delayToShow === void 0 ? 500 : _ref$delayToShow,
_ref$delayToHide = _ref.delayToHide,
delayToHide = _ref$delayToHide === void 0 ? 300 : _ref$delayToHide,
_ref$additionalClass = _ref.additionalClass,
additionalClass = _ref$additionalClass === void 0 ? '' : _ref$additionalClass,
_ref$myHash = _ref.myHash,
myHash = _ref$myHash === void 0 ? '' : _ref$myHash,
_ref$onQueryHovercard = _ref.onQueryHovercardRef,
onQueryHovercardRef = _ref$onQueryHovercard === void 0 ? function (ref) {
return ref;
} : _ref$onQueryHovercard,
_ref$onFetchProfileSt = _ref.onFetchProfileStart,
onFetchProfileStart = _ref$onFetchProfileSt === void 0 ? function () {} : _ref$onFetchProfileSt,
_ref$onFetchProfileSu = _ref.onFetchProfileSuccess,
onFetchProfileSuccess = _ref$onFetchProfileSu === void 0 ? function () {} : _ref$onFetchProfileSu,
_ref$onFetchProfileFa = _ref.onFetchProfileFailure,
onFetchProfileFailure = _ref$onFetchProfileFa === void 0 ? function () {} : _ref$onFetchProfileFa,
_ref$onHovercardShown = _ref.onHovercardShown,
onHovercardShown = _ref$onHovercardShown === void 0 ? function () {} : _ref$onHovercardShown,
_ref$onHovercardHidde = _ref.onHovercardHidden,
onHovercardHidden = _ref$onHovercardHidde === void 0 ? function () {} : _ref$onHovercardHidde,
_ref$i18n = _ref.i18n,
i18n = _ref$i18n === void 0 ? {} : _ref$i18n;
// Options
this._i18n = {};
// Variables
this._hovercardRefs = [];
this._showHovercardTimeoutIds = new Map();
this._hideHovercardTimeoutIds = new Map();
this._cachedProfiles = new Map();
/**
* Attaches event listeners on or within the target element.
*
* @param {HTMLElement} target - The target element to set.
* @param {Object} [options={}] - The optional parameters.
* @param options.dataAttributeName - Data attribute name associated with Gravatar hashes.
* @param options.ignoreSelector - The selector to ignore certain elements.
* @return {void}
*/
this.attach = function (target, _temp2) {
var _ref2 = _temp2 === void 0 ? {} : _temp2,
_ref2$dataAttributeNa = _ref2.dataAttributeName,
dataAttributeName = _ref2$dataAttributeNa === void 0 ? 'gravatar-hash' : _ref2$dataAttributeNa,
ignoreSelector = _ref2.ignoreSelector;
if (!target) {
return;
}
_this.detach();
_this._queryHovercardRefs(target, dataAttributeName, ignoreSelector).forEach(function (hovercardRef) {
hovercardRef.ref.addEventListener('mouseenter', function (e) {
return _this._handleMouseEnter(e, hovercardRef);
});
hovercardRef.ref.addEventListener('mouseleave', function (e) {
return _this._handleMouseLeave(e, hovercardRef);
});
});
};
/**
* Removes event listeners from hovercard refs and resets the stored list of these refs.
*
* @return {void}
*/
this.detach = function () {
if (!_this._hovercardRefs.length) {
return;
}
_this._hovercardRefs.forEach(function (_ref3) {
var ref = _ref3.ref;
ref.removeEventListener('mouseenter', function () {
return _this._handleMouseEnter;
});
ref.removeEventListener('mouseleave', function () {
return _this._handleMouseLeave;
});
});
_this._hovercardRefs = [];
};
this._placement = placement;
this._autoFlip = autoFlip;
this._offset = offset;
this._delayToShow = delayToShow;
this._delayToHide = delayToHide;
this._additionalClass = additionalClass;
this._myHash = myHash;
this._onQueryHovercardRef = onQueryHovercardRef;
this._onFetchProfileStart = onFetchProfileStart;
this._onFetchProfileSuccess = onFetchProfileSuccess;
this._onFetchProfileFailure = onFetchProfileFailure;
this._onHovercardShown = onHovercardShown;
this._onHovercardHidden = onHovercardHidden;
this._i18n = i18n;
}
/**
* Queries hovercard refs on or within the target element
*
* @param {HTMLElement} target - The element to query.
* @param {string} dataAttributeName - Data attribute name associated with Gravatar hashes.
* @param {string} [ignoreSelector] - The selector to ignore certain elements.
* @return {HTMLElement[]} - The queried hovercard refs.
* @private
*/
var _proto = Hovercards.prototype;
_proto._queryHovercardRefs = function _queryHovercardRefs(target, dataAttributeName, ignoreSelector) {
var _this2 = this;
var refs = [];
var camelAttrName = dataAttributeName.replace(/-([a-z])/g, function (g) {
return g[1].toUpperCase();
});
var ignoreRefs = ignoreSelector ? Array.from(dc.querySelectorAll(ignoreSelector)) : [];
var matchPath = 'gravatar.com/avatar/';
if (target.dataset[camelAttrName] || target.tagName === 'IMG' && target.src.includes(matchPath)) {
refs = [target];
} else {
refs = Array.from(target.querySelectorAll("img[src*=\"" + matchPath + "\"]"));
if (dataAttributeName) {
refs = [].concat(refs.filter(function (img) {
return !img.hasAttribute("data-" + dataAttributeName);
}), Array.from(target.querySelectorAll("[data-" + dataAttributeName + "]")));
}
}
this._hovercardRefs = refs.map(function (ref, idx) {
if (ignoreRefs.includes(ref)) {
return null;
}
var hash;
var params;
var dataAttrValue = ref.dataset[camelAttrName];
if (dataAttrValue) {
hash = dataAttrValue.split('?')[0];
params = dataAttrValue;
} else if (ref.tagName === 'IMG') {
hash = ref.src.split('/').pop().split('?')[0];
params = ref.src;
}
if (!hash) {
return null;
}
var p = new URLSearchParams(params);
var d = p.get('d') || p.get('default');
var f = p.get('f') || p.get('forcedefault');
var r = p.get('r') || p.get('rating');
params = [d && "d=" + d, f && "f=" + f, r && "r=" + r].filter(Boolean).join('&');
return {
id: "gravatar-hovercard-" + hash + "-" + idx,
hash: hash,
params: params ? "?" + params : '',
ref: _this2._onQueryHovercardRef(ref) || ref
};
}).filter(Boolean);
return this._hovercardRefs;
}
/**
* Creates a skeleton hovercard element.
*
* @return {HTMLDivElement} The created skeleton hovercard element.
*/;
_proto._createHovercardSkeleton = function _createHovercardSkeleton() {
var hovercard = dc.createElement('div');
hovercard.className = "gravatar-hovercard gravatar-hovercard--skeleton" + (this._additionalClass ? " " + this._additionalClass : '');
hovercard.innerHTML = "\n\t\t\t<div class=\"gravatar-hovercard__inner\">\n\t\t\t\t<div class=\"gravatar-hovercard__header\">\n\t\t\t\t\t<div class=\"gravatar-hovercard__avatar-link\"></div>\n\t\t\t\t\t<div class=\"gravatar-hovercard__name-location-link\"></div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"gravatar-hovercard__footer\">\n\t\t\t\t\t<div class=\"gravatar-hovercard__social-link\"></div>\n\t\t\t\t\t<div class=\"gravatar-hovercard__profile-link\"\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n ";
return hovercard;
}
/**
* Creates a hovercard element with the provided profile data.
*
* @param {ProfileData} profileData - The profile data to populate the hovercard.
* @param {Object} [options] - Optional parameters for the hovercard.
* @param {string} [options.additionalClass] - Additional CSS class for the hovercard.
* @param {string} [options.myHash] - The hash of the current user.
* @param {Object} [options.i18n] - The i18n object.
* @return {HTMLDivElement} - The created hovercard element.
*/;
/**
* Waits for a specified delay and fetches the user's profile data,
* then shows the hovercard relative to the ref element.
*
* @param {HovercardRef} hovercardRef - The hovercard ref object.
* @return {void}
* @private
*/
_proto._showHovercard = function _showHovercard(_ref4) {
var _this3 = this;
var id = _ref4.id,
hash = _ref4.hash,
params = _ref4.params,
ref = _ref4.ref;
var timeoutId = setTimeout(function () {
if (dc.getElementById(id)) {
return;
}
var hovercard;
if (_this3._cachedProfiles.has(hash)) {
var profile = _this3._cachedProfiles.get(hash);
hovercard = Hovercards.createHovercard(_extends({}, profile, {
thumbnailUrl: profile.thumbnailUrl + params
}), {
additionalClass: _this3._additionalClass,
myHash: _this3._myHash,
i18n: _this3._i18n
});
} else {
hovercard = _this3._createHovercardSkeleton();
_this3._onFetchProfileStart(hash);
fetch(BASE_API_URL + "/" + hash + ".json").then(function (res) {
return res.json();
}).then(function (data) {
// API error handling
if (!(data != null && data.entry)) {
// The data will be an error message
throw new Error(data);
}
var _data$entry$ = data.entry[0],
fetchedHash = _data$entry$.hash,
thumbnailUrl = _data$entry$.thumbnailUrl,
preferredUsername = _data$entry$.preferredUsername,
displayName = _data$entry$.displayName,
currentLocation = _data$entry$.currentLocation,
aboutMe = _data$entry$.aboutMe,
accounts = _data$entry$.accounts;
_this3._cachedProfiles.set(hash, {
hash: fetchedHash,
thumbnailUrl: thumbnailUrl,
preferredUsername: preferredUsername,
displayName: displayName,
currentLocation: currentLocation,
aboutMe: aboutMe,
accounts: accounts == null ? void 0 : accounts.map(function (_ref5) {
var url = _ref5.url,
shortname = _ref5.shortname,
iconUrl = _ref5.iconUrl,
name = _ref5.name;
return {
url: url,
shortname: shortname,
iconUrl: iconUrl,
name: name
};
})
});
var profile = _this3._cachedProfiles.get(hash);
var hovercardInner = Hovercards.createHovercard(_extends({}, profile, {
thumbnailUrl: profile.thumbnailUrl + params
}), {
additionalClass: _this3._additionalClass,
myHash: _this3._myHash,
i18n: _this3._i18n
}).firstElementChild;
hovercard.classList.remove('gravatar-hovercard--skeleton');
hovercard.replaceChildren(hovercardInner);
_this3._onFetchProfileSuccess(hash, _this3._cachedProfiles.get(hash));
})["catch"](function (error) {
hovercard.firstElementChild.classList.add('gravatar-hovercard__inner--error');
hovercard.firstElementChild.innerHTML = "\n\t\t\t\t\t\t\t<img class=\"gravatar-hovercard__avatar\" src=\"https://2.gravatar.com/avatar/" + hash + params + "\" width=\"56\" height=\"56\" alt=\"Avatar\" />\n\t\t\t\t\t\t\t<i class=\"gravatar-hovercard__error-message\">" + (error.message === 'User not found' ? __(_this3._i18n, 'Sorry, we are unable to load this Gravatar profile.') : __(_this3._i18n, 'Sorry, we are unable to load this Gravatar profile. Please check your internet connection.')) + "</i>\n\t\t\t\t\t\t";
_this3._onFetchProfileFailure(hash, error);
});
}
// Set the hovercard ID here to avoid the show / hide side effect
hovercard.id = id;
// Don't hide the hovercard when the mouse is over the hovercard from the ref
hovercard.addEventListener('mouseenter', function () {
return clearInterval(_this3._hideHovercardTimeoutIds.get(id));
});
hovercard.addEventListener('mouseleave', function () {
return _this3._hideHovercard(id);
});
// Placing the hovercard at the top-level of the dc to avoid being clipped by overflow
dc.body.appendChild(hovercard);
var _computePosition = computingPosition(ref, hovercard, {
placement: _this3._placement,
offset: _this3._offset,
autoFlip: _this3._autoFlip
}),
x = _computePosition.x,
y = _computePosition.y,
padding = _computePosition.padding,
paddingValue = _computePosition.paddingValue;
hovercard.style.position = 'absolute';
hovercard.style.left = x + "px";
hovercard.style.top = y + "px";
// To bridge the gap between the ref and the hovercard,
// ensuring that the hovercard remains visible when the mouse hovers over the gap
hovercard.style[padding] = paddingValue + "px";
_this3._onHovercardShown(hash, hovercard);
}, this._delayToShow);
this._showHovercardTimeoutIds.set(id, timeoutId);
}
/**
* Waits for a specified delay and hides the hovercard.
*
* @param {string} id - The ID associated with the hovercard.
* @return {void}
* @private
*/;
_proto._hideHovercard = function _hideHovercard(id) {
var _this4 = this;
var timeoutId = setTimeout(function () {
var hovercard = dc.getElementById(id);
if (hovercard) {
hovercard.remove();
_this4._onHovercardHidden(id, hovercard);
}
}, this._delayToHide);
this._hideHovercardTimeoutIds.set(id, timeoutId);
}
/**
* Handles the mouseenter event for hovercard refs.
*
* @param {MouseEvent} e - The mouseenter event object.
* @param hovercardRef - The hovercard ref object.
* @return {void}
* @private
*/;
_proto._handleMouseEnter = function _handleMouseEnter(e, hovercardRef) {
e.stopImmediatePropagation();
// Don't hide the hovercard when the mouse is over the ref from the hovercard
clearInterval(this._hideHovercardTimeoutIds.get(hovercardRef.id));
this._showHovercard(hovercardRef);
}
/**
* Handles the mouseleave event for hovercard refs.
*
* @param {MouseEvent} e - The mouseleave event object.
* @param hovercardRef - The hovercard ref object.
* @param hovercardRef.id - The ID associated with the hovercard.
* @return {void}
* @private
*/;
_proto._handleMouseLeave = function _handleMouseLeave(e, _ref6) {
var id = _ref6.id;
e.stopImmediatePropagation();
clearInterval(this._showHovercardTimeoutIds.get(id));
this._hideHovercard(id);
};
return Hovercards;
}();
Hovercards.createHovercard = function (profileData, _temp3) {
var _ref7 = _temp3 === void 0 ? {} : _temp3,
additionalClass = _ref7.additionalClass,
myHash = _ref7.myHash,
_ref7$i18n = _ref7.i18n,
i18n = _ref7$i18n === void 0 ? {} : _ref7$i18n;
var hash = profileData.hash,
thumbnailUrl = profileData.thumbnailUrl,
preferredUsername = profileData.preferredUsername,
displayName = profileData.displayName,
currentLocation = profileData.currentLocation,
aboutMe = profileData.aboutMe,
_profileData$accounts = profileData.accounts,
accounts = _profileData$accounts === void 0 ? [] : _profileData$accounts;
var hovercard = dc.createElement('div');
hovercard.className = "gravatar-hovercard" + (additionalClass ? " " + additionalClass : '');
var profileUrl = escUrl("https://gravatar.com/" + preferredUsername + "?utm_source=hovercard");
var username = escHtml(displayName);
var isEditProfile = !aboutMe && myHash === hash;
var renderSocialLinks = accounts.reduce(function (links, _ref8) {
var url = _ref8.url,
shortname = _ref8.shortname,
iconUrl = _ref8.iconUrl,
name = _ref8.name;
var idx = socialLinksOrder.indexOf(shortname);
if (idx !== -1) {
links[idx] = "\n\t\t\t\t\t\t<a class=\"gravatar-hovercard__social-link\" href=\"" + escUrl(url) + "\" target=\"_blank\" data-service-name=\"" + shortname + "\">\n\t\t\t\t\t\t\t<img class=\"gravatar-hovercard__social-icon\" src=\"" + escUrl(iconUrl) + "\" width=\"32\" height=\"32\" alt=\"" + escHtml(name) + "\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t";
}
return links;
}, []).join('');
hovercard.innerHTML = "\n\t\t\t<div class=\"gravatar-hovercard__inner\">\n\t\t\t\t<div class=\"gravatar-hovercard__header\">\n\t\t\t\t\t<a class=\"gravatar-hovercard__avatar-link\" href=\"" + profileUrl + "\" target=\"_blank\">\n\t\t\t\t\t\t<img class=\"gravatar-hovercard__avatar\" src=\"" + escUrl(thumbnailUrl) + "\" width=\"56\" height=\"56\" alt=\"" + username + "\" />\n\t\t\t\t\t</a>\n\t\t\t\t\t<a class=\"gravatar-hovercard__name-location-link\" href=\"" + profileUrl + "\" target=\"_blank\">\n\t\t\t\t\t\t<h4 class=\"gravatar-hovercard__name\">" + username + "</h4>\n\t\t\t\t\t\t" + (currentLocation ? "<p class=\"gravatar-hovercard__location\">" + escHtml(currentLocation) + "</p>" : '') + "\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"gravatar-hovercard__body\">\n\t\t\t\t\t" + (aboutMe ? "<p class=\"gravatar-hovercard__about\">" + escHtml(aboutMe) + "</p>" : '') + "\n\t\t\t\t</div>\n\t\t\t\t<div class=\"gravatar-hovercard__footer\">\n\t\t\t\t\t<div class=\"gravatar-hovercard__social-links\">\n\t\t\t\t\t\t<a class=\"gravatar-hovercard__social-link\" href=\"" + profileUrl + "\" target=\"_blank\" data-service-name=\"gravatar\">\n\t\t\t\t\t\t\t<img class=\"gravatar-hovercard__social-icon\" src=\"https://secure.gravatar.com/icons/gravatar.svg\" width=\"32\" height=\"32\" alt=\"Gravatar\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t" + renderSocialLinks + "\n\t\t\t\t\t</div>\n\t\t\t\t\t<a\n\t\t\t\t\t\tclass=\"gravatar-hovercard__profile-link" + (isEditProfile ? ' gravatar-hovercard__profile-link--edit' : '') + "\"\n\t\t\t\t\t\thref=\"" + (isEditProfile ? 'https://gravatar.com/profiles/edit?utm_source=hovercard' : profileUrl) + "\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"gravatar-hovercard__profile-link-text\">\n\t\t\t\t\t\t\t" + (isEditProfile ? __(i18n, 'Edit your profile') : __(i18n, 'View profile')) + "\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\">\n\t\t\t\t\t\t\t<path d=\"M12.6667 8.33338L9.16666 12.1667M12.6667 8.33338L2.66666 8.33338M12.6667 8.33338L9.16666 4.83338\" stroke-width=\"1.5\"/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n ";
return hovercard;
};
;// CONCATENATED MODULE: ./src/index.ts
var __webpack_exports__Hovercards = __webpack_exports__.i;
export { __webpack_exports__Hovercards as Hovercards };
//# sourceMappingURL=index.mjs.map