UNPKG

@hhgtech/hhg-components

Version:
437 lines (415 loc) • 27.3 kB
import { _ as __rest } from './tslib.es6-ea4dfe68.js'; import React__default, { createContext, useContext, useMemo, useCallback, useState } from 'react'; import { u as useTranslations } from './index-9d21b711.js'; import { I as Icon } from './index-5d841202.js'; import './index-5d405c0d.js'; import { Box, createStyles } from '@mantine/core'; import '@mantine/dates'; import { d as DATE_FNS_LOCALE } from './index-5e947517.js'; import './index-90813715.js'; import './index-ebe66e27.js'; import './useMantineLocale-0c6bea99.js'; import { T as Text } from './index-9f5659e8.js'; import './index-c68a0fa7.js'; import { theme } from './miscTheme.js'; import './index.styles-770020ac.js'; import '@mantine/hooks'; import { M as MediaQueries } from './utils-cb7242c7.js'; import './other-4ccb5568.js'; import './index-c2190f6e.js'; import { u as useScreenSize } from './useScreenSize-981e5b51.js'; import { T as TogetherComponentGlobalContext, k as getCurrentBaseUrl } from './utils-40e61585.js'; import { format } from 'date-fns'; import { L as LOCALE } from './Locale-f270bd9d.js'; import styled from '@emotion/styled'; import { H as Heading } from './index-dcc517ff.js'; import { P as PopoverMenu, S as StyledTree } from './index-8d014768.js'; const CardReactionsContext = createContext({}); var styles$1 = {"wrapper":"vvR-m49"}; const LikeWrapper = (_a) => { var { children, className = '' } = _a, boxProps = __rest(_a, ["children", "className"]); const { isReplied, trackingCategory, trackingLabel, onLikeClick } = useContext(CardReactionsContext); return (React__default.createElement(Box, Object.assign({ className: `${styles$1.wrapper} ${className}`, "data-event-category": trackingCategory, "data-event-action": isReplied ? 'Like Comment Click' : 'Like Post Click', "data-event-label": trackingLabel }, boxProps, { onClick: () => { onLikeClick === null || onLikeClick === void 0 ? void 0 : onLikeClick(); } }), children)); }; const ShareWrapper = (_a) => { var { children, className = '' } = _a, boxProps = __rest(_a, ["children", "className"]); const { trackingCategory, trackingLabel, onShareClick } = useContext(CardReactionsContext); return (React__default.createElement(Box, Object.assign({ className: `${styles$1.wrapper} ${className}`, "data-event-category": trackingCategory, "data-event-action": "Share Icon Click", "data-event-label": trackingLabel }, boxProps, { onClick: () => { onShareClick === null || onShareClick === void 0 ? void 0 : onShareClick(); } }), children)); }; const CommentWrapper = (_a) => { var { children, className = '' } = _a, boxProps = __rest(_a, ["children", "className"]); const { isReplied, trackingCategory, trackingLabel, onCommentClick } = useContext(CardReactionsContext); return (React__default.createElement(Box, Object.assign({ className: `${styles$1.wrapper} ${className}`, "data-event-category": trackingCategory, "data-event-action": isReplied ? 'Reply Comment Click' : 'Comment Text Click', "data-event-label": trackingLabel }, boxProps, { onClick: (e) => { e.preventDefault(); e.stopPropagation(); onCommentClick === null || onCommentClick === void 0 ? void 0 : onCommentClick(); } }), children)); }; const SaveWrapper = (_a) => { var { children, className = '' } = _a, boxProps = __rest(_a, ["children", "className"]); const { trackingCategory, trackingLabel, onSaveClick } = useContext(CardReactionsContext); return (React__default.createElement(Box, Object.assign({ className: `${styles$1.wrapper} ${className}`, "data-event-category": trackingCategory, "data-event-action": "Save Post Click", "data-event-label": trackingLabel }, boxProps, { onClick: (e) => { e.preventDefault(); e.stopPropagation(); onSaveClick === null || onSaveClick === void 0 ? void 0 : onSaveClick(); } }), children)); }; var styles = {"wrapper":"UhiT4m5","inner":"oEfeTkV","column":"OlbikxJ","iconTxt":"_9GXHCn3","clickableIcon":"HCsrR0N","count":"MV3lNuh","labelReaction":"Ierg-Fq","actions":"_674BTR4","statistical":"XlkglSM","releatedStatistical":"KyekKc3","statisticalNoAction":"TTfvZpR"}; var CardReactionType; (function (CardReactionType) { CardReactionType[CardReactionType["post"] = 1] = "post"; CardReactionType[CardReactionType["reply"] = 2] = "reply"; })(CardReactionType || (CardReactionType = {})); const CardReactions = (_a) => { var { type, viewCount = 0, loveCount = 0, replyCount = 0, replyPadding, liked, isReplied, isSaved, onCommentClick, onLikeClick, onShareClick, onSaveClick, onGoToUrl, className, style, // hideCommentIcon, showingMostEngaging, isMarryBaby: isMarryBabyInit, hasShare = true, hasSave = true, hasActionStatistical = true, hasShowAction = true, isReleatedPost = false, isVertical = false, trackingCategory = 'Together', trackingLabel = '', children } = _a, rest = __rest(_a, ["type", "viewCount", "loveCount", "replyCount", "replyPadding", "liked", "isReplied", "isSaved", "onCommentClick", "onLikeClick", "onShareClick", "onSaveClick", "onGoToUrl", "className", "style", "showingMostEngaging", "isMarryBaby", "hasShare", "hasSave", "hasActionStatistical", "hasShowAction", "isReleatedPost", "isVertical", "trackingCategory", "trackingLabel", "children"]); const { data: { env: { isMarryBaby: isMarryBabyEnv }, }, } = useContext(TogetherComponentGlobalContext); const isMarryBaby = Boolean(isMarryBabyInit) ? isMarryBabyInit : isMarryBabyEnv; const { t } = useTranslations(); const { isMobile } = useScreenSize(); const hasStatisticalReleated = useMemo(() => { return viewCount > 0 || replyCount > 0; }, [viewCount, replyCount]); const hasStatistical = useMemo(() => { return viewCount > 0 || loveCount > 0 || replyCount > 0; }, [viewCount, loveCount, replyCount]); const statisticalReleatedPost = useCallback(() => { return (React__default.createElement("div", { className: `${styles.releatedStatistical} ${hasActionStatistical ? '' : styles.statisticalNoAction} session-statistical` }, React__default.createElement("div", { className: "releated-post-statistical" }, React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(); } } }, viewCount > 0 && (React__default.createElement(React__default.Fragment, null, React__default.createElement(Icon.Eye, { size: 18, isMarryBaby: isMarryBaby }), React__default.createElement("div", { className: styles.labelReaction }, viewCount)))), React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(replyCount > 0 ? '' : '?action=comment'); } } }, React__default.createElement("div", { className: styles.labelReaction }, replyCount > 0 ? t('comment.count', { count: replyCount }) : t('comment.now')))))); }, [ hasStatisticalReleated, hasActionStatistical, isMarryBaby, viewCount, replyCount, ]); const statisticalCommonPost = useCallback(() => { if (!hasStatistical) return ''; return (React__default.createElement("div", { className: `${styles.statistical} ${hasActionStatistical ? '' : styles.statisticalNoAction} session-statistical` }, React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(); } } }, viewCount > 0 && (React__default.createElement(React__default.Fragment, null, React__default.createElement(Icon.Eye, { size: 18, isMarryBaby: isMarryBaby }), React__default.createElement("div", { className: styles.labelReaction }, viewCount)))), isMobile || isVertical ? (React__default.createElement("div", { className: "wrapper-list-statistical" }, loveCount > 0 ? (React__default.createElement(Text, { className: styles.iconTxt, size: "p3", as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(); } } }, React__default.createElement("div", { className: styles.labelReaction }, loveCount, " ", t('cardReactions.like')))) : (React__default.createElement("div", null)), replyCount > 0 && (React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(); } } }, React__default.createElement("div", { className: styles.labelReaction }, replyCount, " ", t('cardReactions.comment')))))) : (React__default.createElement(React__default.Fragment, null, loveCount > 0 ? (React__default.createElement(Text, { className: styles.iconTxt, size: "p3", as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(); } } }, React__default.createElement(Icon.Heart, { isMarryBaby: isMarryBaby, isSolid: false, size: 18, color: '#737373' }), React__default.createElement("div", { className: styles.labelReaction }, loveCount))) : (React__default.createElement("div", null)), replyCount > 0 && (React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div", onClick: () => { if (hasActionStatistical) { onGoToUrl === null || onGoToUrl === void 0 ? void 0 : onGoToUrl(); } } }, React__default.createElement(Icon.Comment, { size: 18, className: "txt-icon", isMarryBaby: isMarryBaby }), React__default.createElement("div", { className: styles.labelReaction }, replyCount))))))); }, [ hasStatistical, hasActionStatistical, isMarryBaby, isMobile, viewCount, loveCount, replyCount, ]); return (React__default.createElement(CardReactionsContext.Provider, { value: { liked, loveCount, trackingCategory, trackingLabel, isReplied, onLikeClick, onShareClick, onCommentClick, onSaveClick, } }, children || (React__default.createElement("div", Object.assign({ className: `${styles.wrapper} ${className}`, "data-show-most-engaging": showingMostEngaging, "data-type": type === CardReactionType.post ? 'post' : 'reply', "data-reply-padding": type === CardReactionType.reply && replyPadding, "data-is-marrybaby": isMarryBaby, style: style }, rest), React__default.createElement("div", { className: `${styles.inner} ${isVertical ? 'direction-vertical' : ''}` }, hasShowAction && (React__default.createElement("div", { className: `${styles.actions} session-action` }, React__default.createElement(LikeWrapper, { className: `${styles.clickableIcon} wrapper-action` }, React__default.createElement(Text, { className: styles.iconTxt, size: "p3", as: "div" }, React__default.createElement(Icon.Heart, { isMarryBaby: isMarryBaby, isSolid: liked, size: 18, color: liked ? isMarryBaby ? theme.mbColors.pink : theme.colors.red800 : '#737373' }), React__default.createElement("div", { className: styles.labelReaction }, t('cardReactions.like')))), hasShare && (React__default.createElement(ShareWrapper, { className: `${styles.clickableIcon} wrapper-action` }, React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div" }, React__default.createElement(Icon.Share, { size: 18, isMarryBaby: isMarryBaby }), React__default.createElement("div", { className: styles.labelReaction }, t('share.title'))))), hasSave && (React__default.createElement(SaveWrapper, { className: `${styles.clickableIcon} wrapper-action` }, React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div" }, isSaved ? (React__default.createElement(Icon.Bookmark, { size: 18, isMarryBaby: isMarryBaby, color: isMarryBaby ? '#3E3F58' : '#737373' })) : (React__default.createElement(Icon.Save, { size: 18, isMarryBaby: isMarryBaby, color: isMarryBaby ? '#3E3F58' : '#737373' })), React__default.createElement("div", { className: styles.labelReaction }, isSaved ? t('cardReactions.unSave') : t('cardReactions.save'))))), React__default.createElement(CommentWrapper, { className: `${styles.clickableIcon} wrapper-action` }, React__default.createElement(Text, { size: "p3", className: styles.iconTxt, as: "div" }, React__default.createElement(Icon.Comment, { size: 18, className: "txt-icon", isMarryBaby: isMarryBaby }), React__default.createElement("div", { className: styles.labelReaction }, t('cardReactions.comment')))))), isReleatedPost ? statisticalReleatedPost() : statisticalCommonPost()))))); }; CardReactions.LikeWrapper = LikeWrapper; CardReactions.ShareWrapper = ShareWrapper; CardReactions.CommentWrapper = CommentWrapper; const useStyles = createStyles((theme) => ({ wrapper: { display: 'flex', flexWrap: 'wrap', width: '100%', padding: '0.5rem 0', gap: '0.5rem', }, item: { position: 'relative', whiteSpace: 'nowrap', padding: '5px 12px', // border: '1px solid #e4e8ec', background: theme.colors.gray[0], borderRadius: '2rem', cursor: 'pointer', '-webkit-user-drag': 'none', userSelect: 'none', textDecoration: 'none', '*': { pointerEvents: 'none', }, '&:first-child': { marginLeft: 0, }, }, text: {}, })); const TagTopic = (_a) => { var { topics = [], onClick, className, style, trackingCategory = 'Together', locale = 'vi-VN', classNames, styles, unstyled, shortenedNumber = 3, shortenedStyle } = _a, rest = __rest(_a, ["topics", "onClick", "className", "style", "trackingCategory", "locale", "classNames", "styles", "unstyled", "shortenedNumber", "shortenedStyle"]); const { t } = useTranslations(); const { classes } = useStyles(undefined, { name: 'TagTopic', classNames, styles, unstyled, }); const { data: { env: { togetherBasePath }, }, action: { sanitizeFunction }, } = useContext(TogetherComponentGlobalContext); const [showAll, setShowAll] = useState(!shortenedStyle); return (React__default.createElement("div", Object.assign({ onClick: onClick, className: `${classes.wrapper} ${className}`, style: style }, rest), (showAll ? topics : topics.slice(0, shortenedNumber)).map((topic, index) => { const isMonthTopic = (topic === null || topic === void 0 ? void 0 : topic.dueDateMonth) && (topic === null || topic === void 0 ? void 0 : topic.dueDateMonth) !== 0 && (topic === null || topic === void 0 ? void 0 : topic.dueDateYear) && (topic === null || topic === void 0 ? void 0 : topic.dueDateYear) !== 0; return (React__default.createElement("a", { className: classes.item, key: index, "data-event-category": trackingCategory, "data-event-action": "Topic in Post Click", "data-event-label": `${getCurrentBaseUrl(locale)}${togetherBasePath}${topic.url}`, href: topic.isActive && !topic.isHidden ? `${togetherBasePath}${topic.url}/` : undefined }, React__default.createElement(Text, { size: "p4" }, React__default.createElement("span", { style: Object.assign({}, (isMonthTopic && { textTransform: 'capitalize', })), dangerouslySetInnerHTML: { __html: isMonthTopic ? `${format(new Date(2020, Number(topic.dueDateMonth) - 1, 1), 'MMMM', { locale: DATE_FNS_LOCALE[locale], })}${locale === LOCALE.Vietnam ? '/' : ' '}${topic === null || topic === void 0 ? void 0 : topic.dueDateYear}` : (sanitizeFunction === null || sanitizeFunction === void 0 ? void 0 : sanitizeFunction(topic.name)) || topic.name, } })))); }), !showAll && topics.length > shortenedNumber && (React__default.createElement("a", { className: classes.item, href: "#", onClick: (e) => { e.preventDefault(); setShowAll(true); } }, React__default.createElement(Text, { size: "p4" }, "+", t('tagTopic.moreTopics', { number: topics.length - shortenedNumber, })))))); }; const StyledLabelSortPin = styled.div ` display: flex; align-items: center; justify-content: space-between; padding: 16px; cursor: pointer; &[data-color='gray'] { background: ${theme.colors.neutral50}; } &[data-color='white'] { border-bottom: 1px solid #e4e8ec; background: ${theme.colors.white}; } .popover-menu__btn { display: flex; min-width: 2rem; height: 2rem; align-items: center; padding: 8px 0 !important; border: none; margin-left: 0.5rem; background: transparent; > span { display: flex; align-items: center; } &:hover { background: transparent !important; } } &.label-pinned { border-radius: ${theme.borderRadius} 6px 0 0; .label-sort-pin-icon { width: 16px; height: 16px; vertical-align: middle; } } &[data-is-marrybaby='true'] { padding: 0.75rem 1rem; border-radius: 16px 16px 0px 0px; &[data-color='white'] { border-bottom: none; } &[data-color='gray'] { background: #f3f3f3; } .popover-menu__btn { width: unset; } &.label-pinned { border-bottom: none; background: #fff9eb; border-radius: 1rem 1rem 0 0; .label-sort-pin-icon { margin-right: 8px; } .label-sort-pin-heading { color: #fb8c00; } } &.label-sorting { ${MediaQueries.tdUp} { padding-bottom: 1.5rem; margin-bottom: -0.75rem; } } } `; const LabelSortPin = ({ label, rightLabel, onClick, color, className, style, }) => { const { data: { env: { isMarryBaby }, }, } = useContext(TogetherComponentGlobalContext); return (React__default.createElement(StyledLabelSortPin, { "data-is-marrybaby": isMarryBaby, "data-color": color, onClick: onClick, className: className, style: style }, React__default.createElement(Text, { className: "label-sort-pin-heading", size: isMarryBaby ? 'p4' : 'p3', weight: "bold" }, label), rightLabel)); }; var img$4 = "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3e%3cpath stroke='%23FB8C00' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m3.5 20 4.37-4.37'/%3e%3cpath stroke='%23FB8C00' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M4.956 11.294a1 1 0 0 0 0 1.414l2.918 2.918 2.918 2.918a1 1 0 0 0 1.414 0l1.175-1.175a1 1 0 0 0 .293-.707v-3.936l2.9-2.9 2.31.123c.282.015.56-.091.76-.291l.573-.574a1 1 0 0 0 0-1.414l-4.386-4.386a1 1 0 0 0-1.414 0l-.574.574a1 1 0 0 0-.29.76l.122 2.309-2.9 2.9H6.838a1 1 0 0 0-.707.293z' clip-rule='evenodd'/%3e%3cpath stroke='%23FB8C00' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m16.57 9.83-2.9-2.9'/%3e%3c/svg%3e"; var MBPinOrange = img$4; var img$3 = "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3e%3cpath stroke='%23FEA21E' stroke-linecap='round' d='m7.186 7.682-3.504 6.132'/%3e%3cpath fill='%23FEA21E' stroke='%23FEA21E' stroke-linejoin='round' stroke-width='.5' d='M3.246 7.784a.25.25 0 0 0 .091.342l5.447 3.145a.25.25 0 0 0 .342-.092 3.39 3.39 0 0 0 .11-3.186l1.622-2.808a2.66 2.66 0 0 0 1.606-1.239.25.25 0 0 0-.092-.341l-4.19-2.42a.25.25 0 0 0-.341.092 2.66 2.66 0 0 0-.27 2.01L5.949 6.095a3.39 3.39 0 0 0-2.703 1.69Z'/%3e%3c/svg%3e"; var IconPinYellow = img$3; const LabelPin = ({ onClick, color, className, style }) => { const { data: { env: { isMarryBaby }, }, } = useContext(TogetherComponentGlobalContext); const { t } = useTranslations(); return (React__default.createElement(LabelSortPin, { label: React__default.createElement(React__default.Fragment, null, isMarryBaby && (React__default.createElement("img", { className: "label-sort-pin-icon", src: MBPinOrange, loading: "lazy" })), ' ', t('label.pinnedPost')), rightLabel: !isMarryBaby && (React__default.createElement("img", { className: "label-sort-pin-icon", src: IconPinYellow, loading: "lazy" })), onClick: onClick, color: 'white' , className: `label-pinned ${className}`, style: style })); }; var img$2 = "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3e%3cpath stroke='%238C8C8C' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M13.333 4 6 11.333 2.667 8'/%3e%3c/svg%3e"; var IconCheckGray = img$2; var img$1 = "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3e%3cpath stroke='%23262626' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.75' d='m15 18-6-6 6-6'/%3e%3c/svg%3e"; var IconChevronLeftDark = img$1; var img = "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none'%3e%3cpath stroke='%23595959' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 12 4-4-4-4'/%3e%3c/svg%3e"; var IconChevronRightDark = img; const TreePopoverMenu = (_a) => { var { data } = _a, popoverProps = __rest(_a, ["data"]); return (React__default.createElement(PopoverMenu, Object.assign({}, popoverProps), ({ setShow }) => React__default.createElement(Tree, { data: data, setShow: setShow }))); }; const getCurrentDataFromPath = (data, path) => { const pathItems = path.split('.'); let currentData = data; pathItems.forEach((pathItem) => { var _a, _b; if (!pathItem || !currentData || (currentData === null || currentData === void 0 ? void 0 : currentData.type) !== 'list') return; currentData = (_b = (_a = currentData === null || currentData === void 0 ? void 0 : currentData.list) === null || _a === void 0 ? void 0 : _a[Number(pathItem)]) === null || _b === void 0 ? void 0 : _b.subTree; }); return currentData; }; const Tree = ({ data, setShow }) => { var _a; const [path, setPath] = useState(''); const currentData = useMemo(() => data && getCurrentDataFromPath(data, path), [data, path]); if (!data) return null; if (!currentData) return null; const handleItemClick = (index, { subTree, onClick = () => null }) => { if (onClick) onClick(); if (!subTree) setShow && setShow(false); else setPath((p) => p.split('.').concat(String(index)).join('.')); }; return (React__default.createElement(StyledTree, null, currentData.isShowheader ? (React__default.createElement("div", { className: "__header" }, path ? (React__default.createElement("img", { className: "__back-btn", src: IconChevronLeftDark, onClick: () => setPath((p) => p.split('.').slice(0, -1).join('.')), loading: "lazy" })) : null, currentData.title ? (React__default.createElement(Heading, { className: "__title", tag: "h6" }, currentData.title)) : null)) : null, currentData.description ? (React__default.createElement(Text, { className: "tree-text-description", color: theme.colors.gray600, size: "p3", weight: "regular" }, currentData.description)) : null, React__default.createElement("div", { className: "__content" }, currentData.type === 'jsx' ? (_a = currentData === null || currentData === void 0 ? void 0 : currentData.jsxRenderer) === null || _a === void 0 ? void 0 : _a.call(currentData, setShow) : null, currentData.type === 'list' ? (React__default.createElement("ul", { className: "__list" }, Array.isArray(currentData.list) ? currentData.list.map((item, index) => (React__default.createElement("li", { key: index, style: item.style, className: `__item ${item.className}` }, ' ', React__default.createElement("div", { className: `__btn ${item.selected ? '--checked' : ''}`, onClick: () => handleItemClick(index, item), "data-event-category": item.dataEventCategory, "data-event-action": item.dataEventAction, "data-event-label": item.dataEventLabel }, item.icon && (React__default.createElement("img", { className: "__icon", src: item.icon, loading: "lazy" })), React__default.createElement("span", null, item.label)), item.subTree ? (React__default.createElement("img", { className: "__toggle", src: IconChevronRightDark, loading: "lazy" })) : null, item.selected ? (React__default.createElement("img", { className: "__toggle", src: IconCheckGray, loading: "lazy" })) : null))) : null)) : null))); }; export { CardReactions as C, LabelSortPin as L, TagTopic as T, LabelPin as a, TreePopoverMenu as b, CardReactionType as c };