@hhgtech/hhg-components
Version:
Hello Health Group common components
573 lines (522 loc) • 24.1 kB
JavaScript
;
var React = require('react');
var styled = require('@emotion/styled');
var utils = require('./utils-5e3a8440.js');
var miscTheme = require('./miscTheme.js');
var tslib_es6 = require('./tslib.es6-af09a0ba.js');
var index = require('./index-6a888e0c.js');
var constantsDomainLocales = require('./constantsDomainLocales.js');
var index$1 = require('./index-2b476eb9.js');
var index$2 = require('./index-3424862e.js');
require('@mantine/core');
require('@mantine/dates');
require('./index-ec32050c.js');
require('./index-0a047edc.js');
require('./index-9301f298.js');
require('./index-4d838fd2.js');
require('./index-d4ad3f79.js');
require('./index-515469d0.js');
require('./index-04864074.js');
require('./index.styles-5f6a7ac0.js');
require('./translationsContext-4698cb34.js');
require('@mantine/hooks');
require('./index-a985d53b.js');
var index$3 = require('./index-78a4fbc3.js');
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespace(React);
var styled__default = /*#__PURE__*/_interopDefault(styled);
/* eslint-disable prettier/prettier */
const Search2 = (props) => (React__namespace.createElement("svg", Object.assign({ width: "1em", height: "1em", viewBox: "0 0 24 25", fill: "none" }, props),
React__namespace.createElement("path", { d: "M11 18.957C14.866 18.957 18 15.823 18 11.957C18 8.09104 14.866 4.95703 11 4.95703C7.13401 4.95703 4 8.09104 4 11.957C4 15.823 7.13401 18.957 11 18.957Z", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" }),
React__namespace.createElement("path", { d: "M20 20.957L16 16.957", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" })));
const StyledCheckbox = styled__default["default"].div `
display: flex;
cursor: pointer;
&[data-theme='marryBaby'] {
input {
width: 20px;
height: 20px;
border: 1.3px solid ${miscTheme.theme.mbColors.midGray};
border-radius: 9px;
cursor: inherit;
transition: border-color 0.4s, box-shadow 0.4s;
&:hover,
&:active {
border-color: ${miscTheme.theme.mbColors.cobalt};
box-shadow: 0 0 2px 2px ${miscTheme.theme.mbColors.cobalt};
}
&:focus-visible {
border: 2px solid ${miscTheme.theme.mbColors.cobalt};
}
&:checked {
border: 0;
background: ${miscTheme.theme.mbColors.cobalt}
url("data:image/svg+xml,%3Csvg width='9' height='7' viewBox='0 0 9 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1.5 4L3.45455 6L8 1' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A")
no-repeat center center;
}
}
label {
max-width: 15rem;
margin-left: 8px;
width: calc(100% - 24px);
cursor: inherit;
font-weight: 600;
font-size: 12px;
line-height: 20px;
letter-spacing: -0.2px;
color: ${miscTheme.theme.mbColors.gray};
}
}
input {
width: 20px;
height: 20px;
border: solid 1px ${miscTheme.theme.colors.gray500};
border-radius: 2px;
cursor: inherit;
transition: border-color 0.4s, box-shadow 0.4s;
&:hover,
&:active {
border-color: ${miscTheme.theme.colors.primaryBase};
box-shadow: 0 0 2px 2px ${miscTheme.theme.colors.primary200};
}
&:focus-visible {
border: 2px solid ${miscTheme.theme.colors.primaryActive};
}
&:checked {
border: 0;
background: ${miscTheme.theme.colors.primaryBase}
url("data:image/svg+xml,%3Csvg width='12' height='9' viewBox='0 0 12 9' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 1L4.125 8L1 4.81819' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A")
no-repeat center center;
}
}
label {
max-width: 15rem;
margin-left: 8px;
font-weight: ${miscTheme.theme.sizes.fwRegular};
width: calc(100% - 24px);
cursor: inherit;
${utils.MediaQueries.mbDown} {
font-size: 14px;
line-height: 24px;
}
${utils.MediaQueries.mbUp} {
font-size: 16px;
line-height: 22px;
}
}
&[data-is-rectangle] > input {
position: relative;
width: unset;
height: unset;
padding: 5px 12px;
border: 1px solid ${miscTheme.theme.colors.neutral100};
border-radius: 32px;
&::after {
color: ${miscTheme.theme.colors.gray800};
content: attr(data-label-text);
font-size: 13px;
}
&:checked {
border-color: ${miscTheme.theme.colors.primary50};
&::after {
color: ${miscTheme.theme.colors.primaryBase};
}
}
&:checked {
background: ${miscTheme.theme.colors.primary50};
}
}
&[data-disabled] {
color: ${miscTheme.theme.colors.gray300};
cursor: not-allowed;
input {
border-color: ${miscTheme.theme.colors.gray300};
&:hover {
border-color: ${miscTheme.theme.colors.gray300};
box-shadow: none;
}
}
}
`;
/**
* @deprecated Consider to use at '@hhgtech/hhg-components/mantine'
*/
const Checkbox = ({ label, name, checked, className, isDisabled, onChange, value, isRectangle, inputDataTestId, siteType, }) => {
return (React__namespace["default"].createElement(StyledCheckbox, { className: className, "data-disabled": isDisabled || undefined, "data-is-rectangle": isRectangle || undefined, "data-label-text": label, "data-theme": siteType },
React__namespace["default"].createElement("input", { type: "checkbox", checked: checked, name: name, onChange: () => onChange(value, !checked), disabled: isDisabled, value: value, id: `${name}-${value}`, "data-label-text": label, "data-testid": inputDataTestId }),
!isRectangle && React__namespace["default"].createElement("label", { htmlFor: `${name}-${value}` }, label)));
};
const StyledPagination = styled__default["default"].div `
display: flex;
align-items: center;
justify-content: space-between;
user-select: none;
li {
transition: all 0.3s ease;
}
[data-page-active] {
background: ${miscTheme.theme.colors.primaryBase};
color: ${miscTheme.theme.colors.white};
> a {
color: ${miscTheme.theme.colors.white};
}
}
`;
const StyledPageBlock = styled__default["default"].div `
display: flex;
width: 32px;
height: 32px;
box-sizing: border-box;
align-items: center;
justify-content: center;
border: 1px solid ${miscTheme.theme.colors.gray200};
margin: 0 2px;
border-radius: 4px;
color: ${miscTheme.theme.colors.gray800};
cursor: pointer;
font-size: 14px;
font-weight: ${miscTheme.theme.sizes.fwBold};
&[data-last-page] {
border: none;
background-color: ${miscTheme.theme.colors.gray100};
cursor: not-allowed;
pointer-events: none;
svg {
path {
stroke: ${miscTheme.theme.colors.gray300};
}
}
}
`;
const StyledPaginationBlock = styled__default["default"].li `
display: flex;
width: 32px;
height: 32px;
align-items: center;
justify-content: center;
margin: 0 2px;
border-radius: 4px;
color: ${miscTheme.theme.colors.gray800};
cursor: pointer;
font-size: 14px;
font-weight: ${miscTheme.theme.sizes.fwBold};
> a {
color: ${miscTheme.theme.colors.gray800};
text-decoration: unset;
display: block;
width: 100%;
height: 100%;
line-height: 32px;
text-align: center;
}
`;
const RenderPagiWithDots = ({ pagesAmount, activePage, handlePageChange, handleClick, href, queryPageName = 'page', }) => {
const pages = [...Array(pagesAmount)].map((__v, i) => i + 1);
const [visiblePages, setVisiblePages] = React.useState(activePage <= 4
? pages.slice(0, 5)
: activePage >= pages.length - 3
? pages.slice(pages.length - 5, pages.length)
: pages.slice(activePage - 2, activePage + 1));
React.useEffect(() => {
if (activePage <= 4) {
setVisiblePages(pages.slice(0, 5));
}
else if (activePage >= pages.length - 3) {
setVisiblePages(pages.slice(pages.length - 5, pages.length));
}
else {
setVisiblePages(pages.slice(activePage - 2, activePage + 1));
}
}, [activePage]);
return (React__namespace["default"].createElement(React.Fragment, null,
activePage > 4 && (React__namespace["default"].createElement(React.Fragment, null,
React__namespace["default"].createElement(StyledPaginationBlock, { onClick: () => handlePageChange(1) }, href ? (React__namespace["default"].createElement("a", { href: href, onClick: handleClick }, 1)) : (1)),
React__namespace["default"].createElement(StyledPaginationBlock, null, "..."))),
visiblePages.map((i) => (React__namespace["default"].createElement(StyledPaginationBlock, { key: `${'pagination'}+${i}`, "data-page-active": i === activePage || undefined, onClick: () => handlePageChange(i) }, href ? (React__namespace["default"].createElement("a", { href: utils.formatUrlWithPageParam(href, i, queryPageName), onClick: handleClick }, i)) : (i)))),
activePage < pages.length - 3 && (React__namespace["default"].createElement(React.Fragment, null,
React__namespace["default"].createElement(StyledPaginationBlock, null, "..."),
React__namespace["default"].createElement(StyledPaginationBlock, { onClick: () => handlePageChange(pages.length) }, href ? (React__namespace["default"].createElement("a", { href: utils.formatUrlWithPageParam(href, pages.length, queryPageName), onClick: handleClick }, pages.length)) : (pages.length))))));
};
const Pagination = ({ className, pagesAmount, currentPage, onChange, onClick, style, href: _href, queryPageName = 'page', }) => {
const pages = [...Array(pagesAmount)].map((__v, i) => i + 1);
const [activePage, setActivePage] = React.useState(currentPage);
const href = React.useMemo(() => {
// Props `href` is updated from the version 1.8.4 and later. Please change the way to use this props properly
// - To avoid crash app, transform href for the old way and remove the part &page=
// /care/ho-chi-minh/hospital/da-khoa/&page=
// -> /care/ho-chi-minh/hospital/da-khoa/
if (_href && _href.endsWith('&page=')) {
return _href.replace('&page=', '');
}
return _href;
}, [_href]);
const totalArray = pagesAmount - 1;
const handlePageChange = (p) => {
if (p <= pagesAmount && p > 0) {
setActivePage(p);
onChange(p);
}
};
const handleClick = (e) => {
onClick && onClick(e);
};
React.useEffect(() => {
setActivePage(currentPage);
}, [currentPage]);
return (React__namespace["default"].createElement(StyledPagination, { className: className, style: style },
React__namespace["default"].createElement(StyledPageBlock, { className: "prev-page", onClick: () => handlePageChange(activePage - 1), "data-last-page": activePage === 1 || undefined }, href ? (React__namespace["default"].createElement("a", { href: utils.formatUrlWithPageParam(href, activePage, queryPageName), onClick: handleClick },
React__namespace["default"].createElement("svg", { width: "7", height: "10", viewBox: "0 0 7 10", fill: "none" },
React__namespace["default"].createElement("path", { d: "M5.5 9L1.5 5L5.5 1", stroke: "#2D87F3", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })))) : (React__namespace["default"].createElement("svg", { width: "7", height: "10", viewBox: "0 0 7 10", fill: "none" },
React__namespace["default"].createElement("path", { d: "M5.5 9L1.5 5L5.5 1", stroke: "#2D87F3", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })))),
pages.length > 8 ? (React__namespace["default"].createElement(RenderPagiWithDots, { pagesAmount: pagesAmount, activePage: activePage, handlePageChange: handlePageChange, handleClick: handleClick, href: href, queryPageName: queryPageName })) : (pages.map((i) => (React__namespace["default"].createElement(StyledPaginationBlock, { key: `${'pagination'}+${i}`, "data-page-active": i === activePage || undefined, onClick: () => handlePageChange(i) }, href ? (React__namespace["default"].createElement("a", { href: utils.formatUrlWithPageParam(href, i, queryPageName), onClick: handleClick }, i)) : (i))))),
React__namespace["default"].createElement(StyledPageBlock, { className: "next-page", onClick: () => handlePageChange(activePage + 1), "data-last-page": activePage === totalArray + 1 || undefined }, href ? (React__namespace["default"].createElement("a", { href: utils.formatUrlWithPageParam(href, activePage, queryPageName), onClick: handleClick },
React__namespace["default"].createElement("svg", { width: "7", height: "10", viewBox: "0 0 7 10", fill: "none" },
React__namespace["default"].createElement("path", { d: "M1.5 9L5.5 5L1.5 1", stroke: "#2D87F3", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })))) : (React__namespace["default"].createElement("svg", { width: "7", height: "10", viewBox: "0 0 7 10", fill: "none" },
React__namespace["default"].createElement("path", { d: "M1.5 9L5.5 5L1.5 1", stroke: "#2D87F3", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }))))));
};
const StyledInput$1 = styled__default["default"].div `
position: relative;
width: 100%;
&[data-has-error] {
input {
border-color: ${miscTheme.theme.colors.red700};
}
}
input {
width: 100%;
padding: 12px 16px;
border: solid 1px ${miscTheme.theme.colors.gray200};
border-radius: ${miscTheme.theme.borderRadius};
&:active,
&:focus,
.focused & {
border-color: ${miscTheme.theme.colors.primaryBase};
box-shadow: 0px 0px 2px 2px ${miscTheme.theme.colors.primary200};
}
&:disabled {
background-color: ${miscTheme.theme.colors.gray100};
cursor: not-allowed;
}
}
&[data-has-action-icon] {
input {
padding: 12px 48px 12px 16px;
}
}
&[data-has-display-icon] {
input {
padding: 12px 16px 12px 48px;
}
}
&[data-has-action-icon][data-has-display-icon] {
input {
padding: 12px 48px;
}
}
&[data-size='lg'] {
input {
font-size: 16px;
font-weight: ${miscTheme.theme.sizes.fwRegular};
${utils.MediaQueries.mbDown} {
font-size: 22px;
line-height: 1.2;
}
${utils.MediaQueries.mbUp} {
font-size: 26px;
line-height: 1.2;
}
}
}
&[data-size='md'] {
input {
font-weight: ${miscTheme.theme.sizes.fwRegular};
${utils.MediaQueries.mbDown} {
font-size: 14px;
line-height: 1.2;
}
${utils.MediaQueries.mbUp} {
font-size: 16px;
line-height: 1.2;
}
}
}
&[data-size='sm'] {
input {
font-weight: ${miscTheme.theme.sizes.fwRegular};
${utils.MediaQueries.mbDown} {
font-size: 13px;
line-height: 1.5;
}
${utils.MediaQueries.mbUp} {
font-size: 13px;
line-height: 1.5;
}
}
}
`;
/**
* @deprecated Consider to use at '@hhgtech/hhg-components/mantine'
*/
const PureInput = React__namespace["default"].forwardRef((_a, ref) => {
var { name, errorMessage, autoComplete = 'off', defaultValue, actionIcon: ActionIcon, displayIcon: DisplayIcon, isDeleteAction, onActionClick, label, placeholder, className, onChange, onKeyPress, isDisabled, CustomInput, size, style, autoFocus, type = 'text', isNumerousKeyboard = false, onFocus, enterKeyHint, nativeOnChange } = _a, other = tslib_es6.__rest(_a, ["name", "errorMessage", "autoComplete", "defaultValue", "actionIcon", "displayIcon", "isDeleteAction", "onActionClick", "label", "placeholder", "className", "onChange", "onKeyPress", "isDisabled", "CustomInput", "size", "style", "autoFocus", "type", "isNumerousKeyboard", "onFocus", "enterKeyHint", "nativeOnChange"]);
const [localValue, setLocalValue] = React.useState(defaultValue);
const handleOnChange = (v) => {
setLocalValue(v);
onChange(v);
};
const handleOnActionClick = () => {
var _a;
if (isDeleteAction) {
setLocalValue('');
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.focus();
}
onActionClick && onActionClick();
};
return (React__namespace["default"].createElement(StyledInput$1, { "data-size": size, className: className, "data-has-action-icon": !!ActionIcon || undefined, "data-has-display-icon": !!DisplayIcon || undefined, "data-has-error": (errorMessage && errorMessage.length > 0) || undefined, style: style },
label && (React__namespace["default"].createElement(index.Label, { size: "label2", htmlFor: name, className: "inputLabel" }, label)),
React__namespace["default"].createElement("div", { style: { position: 'relative' } },
CustomInput ? (CustomInput) : (React__namespace["default"].createElement("input", Object.assign({ id: name, name: name, placeholder: placeholder, onChange: nativeOnChange !== null && nativeOnChange !== void 0 ? nativeOnChange : ((e) => handleOnChange(e.target.value)), onKeyPress: onKeyPress, type: type, "aria-label": type, disabled: isDisabled, value: localValue, autoComplete: autoComplete, ref: ref, autoFocus: autoFocus, inputMode: isNumerousKeyboard || type === 'number' ? 'numeric' : type, pattern: isNumerousKeyboard ? '[0-9]*' : '.*', onFocus: onFocus, enterKeyHint: enterKeyHint }, other))),
DisplayIcon && (React__namespace["default"].createElement(index.StyledDisplayIcon, { className: "displayIcon" }, DisplayIcon)),
ActionIcon && (React__namespace["default"].createElement(index.StyledActionIcon, { className: "actionIcon", onClick: handleOnActionClick }, ActionIcon))),
errorMessage && errorMessage.length > 0 && (React__namespace["default"].createElement(index.StyledErrorLabel, { className: "errorLabel" }, errorMessage))));
});
PureInput.displayName = 'PureInput';
const DEFAULT_DEVICE_SIZES = [
320, 420, 640, 750, 828, 1080, 1200, 1440, 1920, 2048,
];
const defaultLoader = ({ src, width, quality, locale }) => {
try {
const baseDomain = typeof window !== 'undefined'
? window.location.origin
: constantsDomainLocales.domainLocales[locale]
? `https://${constantsDomainLocales.domainLocales[locale]}`
: '';
if (!baseDomain) {
return src;
}
const url = new URL(src, baseDomain);
url.searchParams.set('w', String(width));
url.searchParams.set('q', String(quality !== null && quality !== void 0 ? quality : 75));
return url.toString();
}
catch (error) {
return src;
}
};
function getWidths(opts) {
if (opts.sizes)
return DEFAULT_DEVICE_SIZES;
if (opts.width) {
const w = Math.max(1, Math.round(opts.width));
return Array.from(new Set([w, Math.min(w * 2, 2048)])).sort((a, b) => a - b);
}
return DEFAULT_DEVICE_SIZES;
}
const ImageWrapV2 = (_a) => {
var { alt, backupSrc, src, placeholderSrc, style, ref, unoptimized = false, quality, sizes, width } = _a, props = tslib_es6.__rest(_a, ["alt", "backupSrc", "src", "placeholderSrc", "style", "ref", "unoptimized", "quality", "sizes", "width"]);
const [hasError, setHasError] = React.useState(false);
const { locale = 'vi-VN' } = index$1.useTranslations();
const widths = React.useMemo(() => (unoptimized ? [] : getWidths({ sizes, width })), [sizes, width, unoptimized]);
const srcSet = React.useMemo(() => {
if (unoptimized)
return undefined;
return widths
.map((w) => `${defaultLoader({ src, width: w, quality, locale })} ${w}w`)
.join(', ');
}, [unoptimized, widths, src, quality]);
const computedSrc = React.useMemo(() => {
if (unoptimized)
return src;
// pick the largest width in the set for the base `src`
const w = widths.length ? widths[widths.length - 1] : width !== null && width !== void 0 ? width : 1920;
return defaultLoader({ src, width: w, quality, locale });
}, [unoptimized, widths, src, quality, width]);
return (React__namespace["default"].createElement(StyledImage, Object.assign({ loading: "lazy", alt: alt, srcSet: srcSet, onError: () => !hasError && setHasError(true), src: hasError ? backupSrc || computedSrc : computedSrc || backupSrc, style: Object.assign(Object.assign({}, (placeholderSrc
? {
backgroundImage: `url(${placeholderSrc})`,
}
: {})), style), "data-has-placeholder": !!placeholderSrc, sizes: sizes, ref: ref }, props)));
};
const StyledImage = styled__default["default"].img `
&[data-has-placeholder='true'] {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
`;
const StyledInput = styled__default["default"](index$2.Input) `
box-shadow: 0px 0px 1px 0px #0000000a, 0px 2px 8px 0px #0000000a,
0px 10px 16px 0px #0000000a;
border-radius: 0.75rem;
overflow: hidden;
input.mantine-Input-input {
border: none;
font-size: 0.8125rem;
line-height: 1.25rem;
}
.close-icon-wrapper {
display: none;
background-color: ${miscTheme.theme.colors.gray400};
border-radius: 100%;
cursor: pointer;
width: 20px;
height: 20px;
padding: 2px;
svg {
pointer-events: none;
}
&[data-is-disabled='true'] {
opacity: 0.2;
cursor: not-allowed;
pointer-events: none;
}
}
input.mantine-Input-input:focus
~ .mantine-Input-rightSection
.close-icon-wrapper,
input.mantine-Input-input:not(:placeholder-shown)
~ .mantine-Input-rightSection
.close-icon-wrapper {
display: flex;
}
`;
const StyledSearchIcon = styled__default["default"](Search2) `
color: ${miscTheme.theme.colors.primaryBase};
width: 20px;
height: 20px;
`;
const SearchInput = (props) => {
const { loading, disabled, placeholder, value, onChange, icon = React__namespace["default"].createElement(StyledSearchIcon, null), className, style, enableClear } = props, restProps = tslib_es6.__rest(props, ["loading", "disabled", "placeholder", "value", "onChange", "icon", "className", "style", "enableClear"]);
const handleChange = (e) => {
onChange(e.currentTarget.value);
};
const handleClear = () => {
onChange('');
};
return (React__namespace["default"].createElement(StyledInput, Object.assign({ disabled: loading || disabled, size: "lg", value: value, onChangeRaw: handleChange, type: "text", placeholder: placeholder, className: className, icon: icon, style: style, rightSection: enableClear ? (React__namespace["default"].createElement("div", { className: "close-icon-wrapper", onClick: handleClear, "data-is-disabled": !value },
React__namespace["default"].createElement(index$3.Close, { fill: "white", width: "100%", height: "100%" }))) : undefined }, restProps, { "data-event-label": value })));
};
exports.Checkbox = Checkbox;
exports.ImageWrapV2 = ImageWrapV2;
exports.Pagination = Pagination;
exports.PureInput = PureInput;
exports.Search2 = Search2;
exports.SearchInput = SearchInput;
exports.StyledSearchIcon = StyledSearchIcon;