@chayns-components/core
Version:
A set of beautiful React components for developing your own applications with chayns.
209 lines (206 loc) • 9.98 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _truncation = require("../../types/truncation");
var _debounce = require("../../utils/debounce");
var _truncation2 = require("../../utils/truncation");
var _Truncation = require("./Truncation.styles");
var _textstring = require("@chayns-components/textstring");
var _textStrings = _interopRequireDefault(require("../../constants/textStrings"));
var _useKeyboardFocusHighlighting = require("../../hooks/useKeyboardFocusHighlighting");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? _react.useLayoutEffect : _react.useEffect;
const Truncation = ({
collapsedHeight = 150,
clampPosition = _truncation.ClampPosition.Right,
isOpen,
moreLabel,
lessLabel,
onChange,
children,
shouldEnableKeyboardHighlighting
}) => {
const shouldShowKeyboardHighlighting = (0, _useKeyboardFocusHighlighting.useKeyboardFocusHighlighting)(shouldEnableKeyboardHighlighting);
const [internalIsOpen, setInternalIsOpen] = (0, _react.useState)(false);
const [showClamp, setShowClamp] = (0, _react.useState)(true);
const [newCollapsedHeight, setNewCollapsedHeight] = (0, _react.useState)(collapsedHeight);
const [originalHeight, setOriginalHeight] = (0, _react.useState)(0);
const [shouldShowCollapsedElement, setShouldShowCollapsedElement] = (0, _react.useState)(true);
const [hasSizeChanged, setHasSizeChanged] = (0, _react.useState)(false);
const [initialRender, setInitialRender] = (0, _react.useState)(true);
const [shouldSkipChangeCheck, setShouldSkipChangeCheck] = (0, _react.useState)(false);
const [originalSmallHeight, setOriginalSmallHeight] = (0, _react.useState)(0);
const [originalBigHeight, setOriginalBigHeight] = (0, _react.useState)(0);
(0, _react.useEffect)(() => {
setInitialRender(false);
}, []);
const parentRef = (0, _react.useRef)(null);
const pseudoChildrenRef = (0, _react.useRef)(null);
const childrenRef = (0, _react.useRef)(null);
const originalChildrenRef = (0, _react.useRef)(null);
const hasCollapsed = (0, _react.useRef)(false);
const isAnimating = (0, _react.useRef)(false);
const hasSizeRecentlyChanged = (0, _react.useRef)(false);
const canResetSizeChanged = (0, _react.useRef)(true);
(0, _react.useEffect)(() => {
if (typeof isOpen === 'boolean') {
setInternalIsOpen(isOpen);
setShowClamp(!isOpen);
}
}, [isOpen]);
// Changes the state of the truncation
const handleClampClick = (0, _react.useCallback)(event => {
setInternalIsOpen(current => {
if (typeof onChange === 'function') {
onChange(event, !current);
}
return !current;
});
}, [onChange]);
const handleClampKeyDown = (0, _react.useCallback)(event => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
event.currentTarget.click();
}
}, []);
(0, _react.useEffect)(() => {
if (children) {
setShouldSkipChangeCheck(true);
window.setTimeout(() => {
setShouldSkipChangeCheck(false);
}, 200);
}
}, [children]);
const handleAnimationEnd = (0, _react.useCallback)(() => {
hasCollapsed.current = true;
isAnimating.current = false;
if (canResetSizeChanged.current) {
setHasSizeChanged(false);
canResetSizeChanged.current = false;
}
window.setTimeout(() => {
hasSizeRecentlyChanged.current = false;
}, 10);
setShouldShowCollapsedElement(!internalIsOpen);
window.setTimeout(() => {
hasCollapsed.current = false;
}, 30);
}, [internalIsOpen]);
(0, _react.useEffect)(() => {
if (!pseudoChildrenRef.current) {
return;
}
setOriginalHeight(pseudoChildrenRef.current.offsetHeight);
setOriginalBigHeight(pseudoChildrenRef.current.offsetHeight);
(0, _truncation2.truncateElement)(pseudoChildrenRef.current, collapsedHeight);
setNewCollapsedHeight(pseudoChildrenRef.current.offsetHeight);
setOriginalSmallHeight(pseudoChildrenRef.current.offsetHeight);
}, [collapsedHeight, pseudoChildrenRef, children]);
// Checks if the clamp should be shown
(0, _react.useEffect)(() => {
if (pseudoChildrenRef.current && (!hasSizeChanged || shouldSkipChangeCheck) && !initialRender) {
setShowClamp(originalHeight > newCollapsedHeight);
}
}, [shouldSkipChangeCheck, collapsedHeight, hasSizeChanged, initialRender, newCollapsedHeight, originalHeight, children]);
(0, _react.useEffect)(() => {
if (childrenRef.current && pseudoChildrenRef.current && originalChildrenRef.current) {
var _parentRef$current;
while (childrenRef.current.firstChild) {
childrenRef.current.removeChild(childrenRef.current.firstChild);
}
childrenRef.current.appendChild(shouldShowCollapsedElement && !internalIsOpen ? pseudoChildrenRef.current : originalChildrenRef.current);
(_parentRef$current = parentRef.current) === null || _parentRef$current === void 0 || _parentRef$current.appendChild(shouldShowCollapsedElement && !internalIsOpen ? originalChildrenRef.current : pseudoChildrenRef.current);
childrenRef.current.children[0].style.visibility = 'visible';
}
}, [children, internalIsOpen, shouldShowCollapsedElement]);
useIsomorphicLayoutEffect(() => {
if (originalChildrenRef.current) {
const resizeObserver = new ResizeObserver(entries => {
if (entries && entries[0]) {
const observedHeight = entries[0].contentRect.height;
setOriginalHeight(observedHeight < originalBigHeight ? originalBigHeight : observedHeight);
if (!hasCollapsed.current && !isAnimating.current && !hasSizeRecentlyChanged.current) {
void (0, _debounce.debounce)(() => {
canResetSizeChanged.current = true;
}, 250)();
setHasSizeChanged(true);
hasSizeRecentlyChanged.current = true;
}
}
});
resizeObserver.observe(originalChildrenRef.current);
return () => {
resizeObserver.disconnect();
};
}
return () => {};
}, [originalBigHeight, children]);
useIsomorphicLayoutEffect(() => {
if (pseudoChildrenRef.current) {
const resizeObserver = new ResizeObserver(entries => {
if (entries && entries[0]) {
const observedHeight = entries[0].contentRect.height;
setNewCollapsedHeight(observedHeight < originalSmallHeight ? originalSmallHeight : observedHeight);
if (!hasCollapsed.current && !isAnimating.current && !hasSizeRecentlyChanged.current) {
void (0, _debounce.debounce)(() => {
canResetSizeChanged.current = true;
}, 250)();
setHasSizeChanged(true);
hasSizeRecentlyChanged.current = true;
}
}
});
resizeObserver.observe(pseudoChildrenRef.current);
return () => {
resizeObserver.disconnect();
};
}
return () => {};
}, [originalSmallHeight, children]);
const ts = _textStrings.default.components.truncation;
const internalMoreLabel = moreLabel ?? /*#__PURE__*/_react.default.createElement(_textstring.Textstring, {
textstring: (0, _textstring.ttsToITextString)(ts.more)
});
const internalLessLabel = lessLabel ?? /*#__PURE__*/_react.default.createElement(_textstring.Textstring, {
textstring: (0, _textstring.ttsToITextString)(ts.less)
});
return (0, _react.useMemo)(() => /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncation, {
className: "beta-chayns-truncation",
ref: parentRef
}, /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncationPseudoContent, {
ref: pseudoChildrenRef
}, children), /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncationPseudoContent, {
ref: originalChildrenRef
}, children), /*#__PURE__*/_react.default.createElement(_Truncation.StyledMotionTruncationContent, {
animate: {
height: internalIsOpen ? originalHeight : newCollapsedHeight
},
initial: false,
transition: {
type: 'tween',
duration: hasSizeChanged ? 0 : 0.2
},
onAnimationComplete: handleAnimationEnd,
onAnimationStart: () => {
isAnimating.current = true;
},
ref: childrenRef
}), showClamp && /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncationClampWrapper, {
$position: clampPosition
}, /*#__PURE__*/_react.default.createElement(_textstring.TextstringProvider, {
libraryName: "@chayns-components-core"
}, /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncationClampFocusWrapper, {
$shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting
}, /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncationClamp, {
onClick: handleClampClick,
onKeyDown: handleClampKeyDown,
role: "button",
tabIndex: 0
}, internalIsOpen ? internalLessLabel : internalMoreLabel))))), [children, clampPosition, handleAnimationEnd, handleClampClick, handleClampKeyDown, hasSizeChanged, internalIsOpen, lessLabel, moreLabel, newCollapsedHeight, originalHeight, shouldShowKeyboardHighlighting, showClamp]);
};
var _default = exports.default = Truncation;
//# sourceMappingURL=Truncation.js.map