@chayns-components/core 5.5.41 → 5.5.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -5
- package/lib/cjs/components/truncation/Truncation.js +16 -4
- package/lib/cjs/components/truncation/Truncation.js.map +1 -1
- package/lib/cjs/components/truncation/Truncation.test.js +3 -0
- package/lib/cjs/components/truncation/Truncation.test.js.map +1 -1
- package/lib/esm/components/truncation/Truncation.js +16 -4
- package/lib/esm/components/truncation/Truncation.js.map +1 -1
- package/lib/esm/components/truncation/Truncation.test.js +3 -0
- package/lib/esm/components/truncation/Truncation.test.js.map +1 -1
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -5854,7 +5854,7 @@ import { Button, Truncation } from '@chayns-components/core';
|
|
|
5854
5854
|
|
|
5855
5855
|
```tsx
|
|
5856
5856
|
<Truncation
|
|
5857
|
-
collapsedHeight={
|
|
5857
|
+
collapsedHeight={125}
|
|
5858
5858
|
>
|
|
5859
5859
|
{
|
|
5860
5860
|
<div>
|
|
@@ -5879,7 +5879,7 @@ import { Button, Truncation } from '@chayns-components/core';
|
|
|
5879
5879
|
|
|
5880
5880
|
```tsx
|
|
5881
5881
|
<Truncation
|
|
5882
|
-
collapsedHeight={
|
|
5882
|
+
collapsedHeight={125}
|
|
5883
5883
|
>
|
|
5884
5884
|
{
|
|
5885
5885
|
<>
|
|
@@ -5912,7 +5912,7 @@ import { Button, Truncation } from '@chayns-components/core';
|
|
|
5912
5912
|
|
|
5913
5913
|
```tsx
|
|
5914
5914
|
<Truncation
|
|
5915
|
-
collapsedHeight={
|
|
5915
|
+
collapsedHeight={125}
|
|
5916
5916
|
>
|
|
5917
5917
|
{
|
|
5918
5918
|
<div>
|
|
@@ -5937,7 +5937,7 @@ import { Button, Truncation } from '@chayns-components/core';
|
|
|
5937
5937
|
|
|
5938
5938
|
```tsx
|
|
5939
5939
|
<Truncation
|
|
5940
|
-
collapsedHeight={
|
|
5940
|
+
collapsedHeight={125}
|
|
5941
5941
|
>
|
|
5942
5942
|
{<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>}
|
|
5943
5943
|
</Truncation>
|
|
@@ -5947,7 +5947,7 @@ import { Button, Truncation } from '@chayns-components/core';
|
|
|
5947
5947
|
|
|
5948
5948
|
```tsx
|
|
5949
5949
|
<Truncation
|
|
5950
|
-
collapsedHeight={
|
|
5950
|
+
collapsedHeight={125}
|
|
5951
5951
|
>
|
|
5952
5952
|
{
|
|
5953
5953
|
<p>
|
|
@@ -14,6 +14,16 @@ var _Truncation = require("./Truncation.styles");
|
|
|
14
14
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
15
|
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); }
|
|
16
16
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? _react.useLayoutEffect : _react.useEffect;
|
|
17
|
+
const getHeightAtLineBoundary = (element, height, contentHeight) => {
|
|
18
|
+
const elementTop = element.getBoundingClientRect().top;
|
|
19
|
+
const targetBottom = elementTop + height;
|
|
20
|
+
const range = element.ownerDocument.createRange();
|
|
21
|
+
range.selectNodeContents(element);
|
|
22
|
+
const lineRects = typeof range.getClientRects === 'function' ? Array.from(range.getClientRects()) : [];
|
|
23
|
+
const lineBottom = lineRects.map(rect => rect.bottom).filter(bottom => bottom >= targetBottom).sort((first, second) => first - second)[0];
|
|
24
|
+
range.detach();
|
|
25
|
+
return lineBottom === undefined ? Math.min(contentHeight, height) : Math.min(contentHeight, lineBottom - elementTop);
|
|
26
|
+
};
|
|
17
27
|
const Truncation = ({
|
|
18
28
|
collapsedHeight = 150,
|
|
19
29
|
clampPosition = _truncation.ClampPosition.Right,
|
|
@@ -30,6 +40,7 @@ const Truncation = ({
|
|
|
30
40
|
const pendingObservedHeight = (0, _react.useRef)(0);
|
|
31
41
|
const [internalIsOpen, setInternalIsOpen] = (0, _react.useState)(Boolean(isOpen));
|
|
32
42
|
const [contentHeight, setContentHeight] = (0, _react.useState)(0);
|
|
43
|
+
const [collapsedContentHeight, setCollapsedContentHeight] = (0, _react.useState)(collapsedHeight);
|
|
33
44
|
(0, _react.useEffect)(() => {
|
|
34
45
|
if (typeof isOpen === 'boolean') {
|
|
35
46
|
setInternalIsOpen(isOpen);
|
|
@@ -55,7 +66,9 @@ const Truncation = ({
|
|
|
55
66
|
if (!contentRef.current) {
|
|
56
67
|
return;
|
|
57
68
|
}
|
|
58
|
-
|
|
69
|
+
const measuredContentHeight = Math.max(pendingObservedHeight.current, contentRef.current.scrollHeight, contentRef.current.getBoundingClientRect().height);
|
|
70
|
+
setContentHeight(measuredContentHeight);
|
|
71
|
+
setCollapsedContentHeight(getHeightAtLineBoundary(contentRef.current, collapsedHeight, measuredContentHeight));
|
|
59
72
|
pendingObservedHeight.current = 0;
|
|
60
73
|
});
|
|
61
74
|
};
|
|
@@ -75,7 +88,7 @@ const Truncation = ({
|
|
|
75
88
|
window.cancelAnimationFrame(frame);
|
|
76
89
|
}
|
|
77
90
|
};
|
|
78
|
-
}, [children]);
|
|
91
|
+
}, [children, collapsedHeight]);
|
|
79
92
|
const handleClampClick = (0, _react.useCallback)(event => {
|
|
80
93
|
setInternalIsOpen(current => {
|
|
81
94
|
onChange === null || onChange === void 0 || onChange(event, !current);
|
|
@@ -94,8 +107,7 @@ const Truncation = ({
|
|
|
94
107
|
const internalLessLabel = lessLabel ?? /*#__PURE__*/_react.default.createElement(_textstrings.Translation, {
|
|
95
108
|
textString: _textStrings.default.components.truncation.less
|
|
96
109
|
});
|
|
97
|
-
const
|
|
98
|
-
const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : collapsedContentHeight;
|
|
110
|
+
const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : Math.min(contentHeight || collapsedHeight, collapsedContentHeight);
|
|
99
111
|
return /*#__PURE__*/_react.default.createElement(_Truncation.StyledTruncation, {
|
|
100
112
|
className: "beta-chayns-truncation"
|
|
101
113
|
}, /*#__PURE__*/_react.default.createElement(_Truncation.StyledMotionTruncationContent, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Truncation.js","names":["_textstrings","require","_react","_interopRequireWildcard","_textStrings","_interopRequireDefault","_useFocusRingPortal","_useKeyboardFocusHighlighting","_truncation","_Truncation","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","Truncation","collapsedHeight","clampPosition","ClampPosition","Right","isOpen","lessLabel","moreLabel","onChange","children","shouldEnableKeyboardHighlighting","shouldShowKeyboardHighlighting","useKeyboardFocusHighlighting","contentRef","useRef","clampRef","pendingObservedHeight","internalIsOpen","setInternalIsOpen","useState","Boolean","contentHeight","setContentHeight","hasOverflow","useFocusRingPortal","isEnabled","current","frame","updateContentHeight","entries","_entries$","Math","max","contentRect","height","undefined","requestAnimationFrame","scrollHeight","getBoundingClientRect","resizeObserver","ResizeObserver","mutationObserver","MutationObserver","observe","characterData","childList","subtree","disconnect","cancelAnimationFrame","handleClampClick","useCallback","event","handleClampKeyDown","key","preventDefault","currentTarget","click","internalMoreLabel","createElement","Translation","textString","textStrings","components","truncation","more","internalLessLabel","less","collapsedContentHeight","min","targetHeight","StyledTruncation","className","StyledMotionTruncationContent","animate","initial","transition","type","duration","StyledTruncationContent","ref","StyledTruncationClampWrapper","$position","TextStringProviderSSR","libraries","id","StyledTruncationClampFocusWrapper","StyledTruncationClamp","onClick","onKeyDown","role","tabIndex","_default","exports"],"sources":["../../../../src/components/truncation/Truncation.tsx"],"sourcesContent":["import { TextStringProviderSSR, Translation } from '@chayns/textstrings';\nimport React, {\n FC,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport textStrings from '../../constants/textStrings';\nimport { useFocusRingPortal } from '../../hooks/useFocusRingPortal';\nimport { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';\nimport { ClampPosition } from '../../types/truncation';\nimport {\n StyledMotionTruncationContent,\n StyledTruncation,\n StyledTruncationClamp,\n StyledTruncationClampFocusWrapper,\n StyledTruncationClampWrapper,\n StyledTruncationContent,\n} from './Truncation.styles';\n\nexport type TruncationProps = {\n /**\n * The elements that should be expanding or collapsing.\n */\n children: ReactElement;\n /**\n * The position of the clamp.\n */\n clampPosition?: ClampPosition;\n /**\n * The height of the children element in its collapsed state.\n */\n collapsedHeight?: number;\n /**\n * If set to true, the content is exposed.\n */\n isOpen?: boolean;\n /**\n * A text that should be displayed if the content is expanded.\n */\n lessLabel?: string;\n /**\n * A text that should be displayed if the content is collapsed.\n */\n moreLabel?: string;\n /**\n * Function to be executed when the component is expanding or collapsing.\n */\n onChange?: (event: MouseEvent<HTMLAnchorElement>, isOpen: boolean) => void;\n /**\n * Enables keyboard-only focus highlighting.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n};\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\nconst Truncation: FC<TruncationProps> = ({\n collapsedHeight = 150,\n clampPosition = ClampPosition.Right,\n isOpen,\n lessLabel,\n moreLabel,\n onChange,\n children,\n shouldEnableKeyboardHighlighting,\n}) => {\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n const contentRef = useRef<HTMLDivElement>(null);\n const clampRef = useRef<HTMLAnchorElement>(null);\n const pendingObservedHeight = useRef(0);\n const [internalIsOpen, setInternalIsOpen] = useState(Boolean(isOpen));\n const [contentHeight, setContentHeight] = useState(0);\n\n useEffect(() => {\n if (typeof isOpen === 'boolean') {\n setInternalIsOpen(isOpen);\n }\n }, [isOpen]);\n\n const hasOverflow = contentHeight > collapsedHeight;\n\n useFocusRingPortal(clampRef, {\n isEnabled: shouldShowKeyboardHighlighting && hasOverflow,\n });\n\n useIsomorphicLayoutEffect(() => {\n if (!contentRef.current) {\n return () => {};\n }\n\n let frame: number | undefined;\n const updateContentHeight = (entries?: ResizeObserverEntry[]) => {\n pendingObservedHeight.current = Math.max(\n pendingObservedHeight.current,\n entries?.[0]?.contentRect.height ?? 0,\n );\n\n if (frame !== undefined) {\n return;\n }\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n\n if (!contentRef.current) {\n return;\n }\n\n setContentHeight(\n Math.max(\n pendingObservedHeight.current,\n contentRef.current.scrollHeight,\n contentRef.current.getBoundingClientRect().height,\n ),\n );\n pendingObservedHeight.current = 0;\n });\n };\n\n const resizeObserver = new ResizeObserver((entries) => updateContentHeight(entries));\n const mutationObserver = new MutationObserver(() => updateContentHeight());\n\n resizeObserver.observe(contentRef.current);\n mutationObserver.observe(contentRef.current, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n updateContentHeight();\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n\n if (frame !== undefined) {\n window.cancelAnimationFrame(frame);\n }\n };\n }, [children]);\n\n const handleClampClick = useCallback<MouseEventHandler<HTMLAnchorElement>>(\n (event) => {\n setInternalIsOpen((current) => {\n onChange?.(event, !current);\n return !current;\n });\n },\n [onChange],\n );\n\n const handleClampKeyDown = useCallback<KeyboardEventHandler<HTMLAnchorElement>>((event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.currentTarget.click();\n }\n }, []);\n\n const internalMoreLabel = moreLabel ?? (\n <Translation textString={textStrings.components.truncation.more} />\n );\n const internalLessLabel = lessLabel ?? (\n <Translation textString={textStrings.components.truncation.less} />\n );\n const collapsedContentHeight = Math.min(contentHeight || collapsedHeight, collapsedHeight);\n const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : collapsedContentHeight;\n\n return (\n <StyledTruncation className=\"beta-chayns-truncation\">\n <StyledMotionTruncationContent\n animate={{ height: targetHeight }}\n initial={false}\n transition={{ type: 'tween', duration: 0.2 }}\n >\n <StyledTruncationContent ref={contentRef}>{children}</StyledTruncationContent>\n </StyledMotionTruncationContent>\n {hasOverflow && (\n <StyledTruncationClampWrapper $position={clampPosition}>\n <TextStringProviderSSR libraries=\"chayns-components-v5-core\" id=\"truncation\">\n <StyledTruncationClampFocusWrapper>\n <StyledTruncationClamp\n ref={clampRef}\n onClick={handleClampClick}\n onKeyDown={handleClampKeyDown}\n role=\"button\"\n tabIndex={0}\n >\n {internalIsOpen ? internalLessLabel : internalMoreLabel}\n </StyledTruncationClamp>\n </StyledTruncationClampFocusWrapper>\n </TextStringProviderSSR>\n </StyledTruncationClampWrapper>\n )}\n </StyledTruncation>\n );\n};\n\nexport default Truncation;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Truncation.js","names":["_textstrings","require","_react","_interopRequireWildcard","_textStrings","_interopRequireDefault","_useFocusRingPortal","_useKeyboardFocusHighlighting","_truncation","_Truncation","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","getHeightAtLineBoundary","element","height","contentHeight","elementTop","getBoundingClientRect","top","targetBottom","range","ownerDocument","createRange","selectNodeContents","lineRects","getClientRects","Array","from","lineBottom","map","rect","bottom","filter","sort","first","second","detach","undefined","Math","min","Truncation","collapsedHeight","clampPosition","ClampPosition","Right","isOpen","lessLabel","moreLabel","onChange","children","shouldEnableKeyboardHighlighting","shouldShowKeyboardHighlighting","useKeyboardFocusHighlighting","contentRef","useRef","clampRef","pendingObservedHeight","internalIsOpen","setInternalIsOpen","useState","Boolean","setContentHeight","collapsedContentHeight","setCollapsedContentHeight","hasOverflow","useFocusRingPortal","isEnabled","current","frame","updateContentHeight","entries","_entries$","max","contentRect","requestAnimationFrame","measuredContentHeight","scrollHeight","resizeObserver","ResizeObserver","mutationObserver","MutationObserver","observe","characterData","childList","subtree","disconnect","cancelAnimationFrame","handleClampClick","useCallback","event","handleClampKeyDown","key","preventDefault","currentTarget","click","internalMoreLabel","createElement","Translation","textString","textStrings","components","truncation","more","internalLessLabel","less","targetHeight","StyledTruncation","className","StyledMotionTruncationContent","animate","initial","transition","type","duration","StyledTruncationContent","ref","StyledTruncationClampWrapper","$position","TextStringProviderSSR","libraries","id","StyledTruncationClampFocusWrapper","StyledTruncationClamp","onClick","onKeyDown","role","tabIndex","_default","exports"],"sources":["../../../../src/components/truncation/Truncation.tsx"],"sourcesContent":["import { TextStringProviderSSR, Translation } from '@chayns/textstrings';\nimport React, {\n FC,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport textStrings from '../../constants/textStrings';\nimport { useFocusRingPortal } from '../../hooks/useFocusRingPortal';\nimport { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';\nimport { ClampPosition } from '../../types/truncation';\nimport {\n StyledMotionTruncationContent,\n StyledTruncation,\n StyledTruncationClamp,\n StyledTruncationClampFocusWrapper,\n StyledTruncationClampWrapper,\n StyledTruncationContent,\n} from './Truncation.styles';\n\nexport type TruncationProps = {\n /**\n * The elements that should be expanding or collapsing.\n */\n children: ReactElement;\n /**\n * The position of the clamp.\n */\n clampPosition?: ClampPosition;\n /**\n * The height of the children element in its collapsed state.\n */\n collapsedHeight?: number;\n /**\n * If set to true, the content is exposed.\n */\n isOpen?: boolean;\n /**\n * A text that should be displayed if the content is expanded.\n */\n lessLabel?: string;\n /**\n * A text that should be displayed if the content is collapsed.\n */\n moreLabel?: string;\n /**\n * Function to be executed when the component is expanding or collapsing.\n */\n onChange?: (event: MouseEvent<HTMLAnchorElement>, isOpen: boolean) => void;\n /**\n * Enables keyboard-only focus highlighting.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n};\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\nconst getHeightAtLineBoundary = (element: HTMLElement, height: number, contentHeight: number) => {\n const elementTop = element.getBoundingClientRect().top;\n const targetBottom = elementTop + height;\n const range = element.ownerDocument.createRange();\n\n range.selectNodeContents(element);\n\n const lineRects =\n typeof range.getClientRects === 'function' ? Array.from(range.getClientRects()) : [];\n const lineBottom = lineRects\n .map((rect) => rect.bottom)\n .filter((bottom) => bottom >= targetBottom)\n .sort((first, second) => first - second)[0];\n\n range.detach();\n\n return lineBottom === undefined\n ? Math.min(contentHeight, height)\n : Math.min(contentHeight, lineBottom - elementTop);\n};\n\nconst Truncation: FC<TruncationProps> = ({\n collapsedHeight = 150,\n clampPosition = ClampPosition.Right,\n isOpen,\n lessLabel,\n moreLabel,\n onChange,\n children,\n shouldEnableKeyboardHighlighting,\n}) => {\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n const contentRef = useRef<HTMLDivElement>(null);\n const clampRef = useRef<HTMLAnchorElement>(null);\n const pendingObservedHeight = useRef(0);\n const [internalIsOpen, setInternalIsOpen] = useState(Boolean(isOpen));\n const [contentHeight, setContentHeight] = useState(0);\n const [collapsedContentHeight, setCollapsedContentHeight] = useState(collapsedHeight);\n\n useEffect(() => {\n if (typeof isOpen === 'boolean') {\n setInternalIsOpen(isOpen);\n }\n }, [isOpen]);\n\n const hasOverflow = contentHeight > collapsedHeight;\n\n useFocusRingPortal(clampRef, {\n isEnabled: shouldShowKeyboardHighlighting && hasOverflow,\n });\n\n useIsomorphicLayoutEffect(() => {\n if (!contentRef.current) {\n return () => {};\n }\n\n let frame: number | undefined;\n const updateContentHeight = (entries?: ResizeObserverEntry[]) => {\n pendingObservedHeight.current = Math.max(\n pendingObservedHeight.current,\n entries?.[0]?.contentRect.height ?? 0,\n );\n\n if (frame !== undefined) {\n return;\n }\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n\n if (!contentRef.current) {\n return;\n }\n\n const measuredContentHeight = Math.max(\n pendingObservedHeight.current,\n contentRef.current.scrollHeight,\n contentRef.current.getBoundingClientRect().height,\n );\n\n setContentHeight(measuredContentHeight);\n setCollapsedContentHeight(\n getHeightAtLineBoundary(\n contentRef.current,\n collapsedHeight,\n measuredContentHeight,\n ),\n );\n pendingObservedHeight.current = 0;\n });\n };\n\n const resizeObserver = new ResizeObserver((entries) => updateContentHeight(entries));\n const mutationObserver = new MutationObserver(() => updateContentHeight());\n\n resizeObserver.observe(contentRef.current);\n mutationObserver.observe(contentRef.current, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n updateContentHeight();\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n\n if (frame !== undefined) {\n window.cancelAnimationFrame(frame);\n }\n };\n }, [children, collapsedHeight]);\n\n const handleClampClick = useCallback<MouseEventHandler<HTMLAnchorElement>>(\n (event) => {\n setInternalIsOpen((current) => {\n onChange?.(event, !current);\n return !current;\n });\n },\n [onChange],\n );\n\n const handleClampKeyDown = useCallback<KeyboardEventHandler<HTMLAnchorElement>>((event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.currentTarget.click();\n }\n }, []);\n\n const internalMoreLabel = moreLabel ?? (\n <Translation textString={textStrings.components.truncation.more} />\n );\n const internalLessLabel = lessLabel ?? (\n <Translation textString={textStrings.components.truncation.less} />\n );\n const targetHeight = internalIsOpen\n ? contentHeight || collapsedHeight\n : Math.min(contentHeight || collapsedHeight, collapsedContentHeight);\n\n return (\n <StyledTruncation className=\"beta-chayns-truncation\">\n <StyledMotionTruncationContent\n animate={{ height: targetHeight }}\n initial={false}\n transition={{ type: 'tween', duration: 0.2 }}\n >\n <StyledTruncationContent ref={contentRef}>{children}</StyledTruncationContent>\n </StyledMotionTruncationContent>\n {hasOverflow && (\n <StyledTruncationClampWrapper $position={clampPosition}>\n <TextStringProviderSSR libraries=\"chayns-components-v5-core\" id=\"truncation\">\n <StyledTruncationClampFocusWrapper>\n <StyledTruncationClamp\n ref={clampRef}\n onClick={handleClampClick}\n onKeyDown={handleClampKeyDown}\n role=\"button\"\n tabIndex={0}\n >\n {internalIsOpen ? internalLessLabel : internalMoreLabel}\n </StyledTruncationClamp>\n </StyledTruncationClampFocusWrapper>\n </TextStringProviderSSR>\n </StyledTruncationClampWrapper>\n )}\n </StyledTruncation>\n );\n};\n\nexport default Truncation;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Truncation.test.js","names":["_react","require","_react2","_interopRequireDefault","_vitest","_Truncation","e","__esModule","default","vi","mock","Translation","TextStringProvider","children","resizeObserverCallbacks","ResizeObserverMock","constructor","callback","push","disconnect","observe","unobserve","stubGlobal","triggerResize","height","forEach","contentRect","afterEach","length","describe","it","render","createElement","collapsedHeight","waitFor","expect","screen","getByRole","name","toBeInTheDocument","queryByRole","not"],"sources":["../../../../src/components/truncation/Truncation.test.tsx"],"sourcesContent":["import { render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport Truncation from './Truncation';\n\nvi.mock('@chayns/textstrings', () => ({\n Translation: () => 'Mehr anzeigen',\n TextStringProvider: ({ children }: { children: React.ReactNode }) => children,\n}));\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[]) => void;\n\nconst resizeObserverCallbacks: ResizeObserverCallback[] = [];\n\nclass ResizeObserverMock {\n constructor(callback: ResizeObserverCallback) {\n resizeObserverCallbacks.push(callback);\n }\n\n disconnect() {}\n\n observe() {}\n\n unobserve() {}\n}\n\nvi.stubGlobal('ResizeObserver', ResizeObserverMock);\n\nconst triggerResize = (height: number) => {\n resizeObserverCallbacks.forEach((callback) => {\n callback([\n {\n contentRect: { height } as DOMRectReadOnly,\n } as ResizeObserverEntry,\n ]);\n });\n};\n\nafterEach(() => {\n resizeObserverCallbacks.length = 0;\n});\n\ndescribe('Truncation', () => {\n it('shows the more action when content exceeds the collapsed height', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Long content</div>\n </Truncation>,\n );\n\n triggerResize(240);\n\n await waitFor(() => {\n expect(screen.getByRole('button', { name: 'Mehr anzeigen' })).toBeInTheDocument();\n });\n });\n\n it('keeps short content expanded without a more action', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Short content</div>\n </Truncation>,\n );\n\n triggerResize(64);\n\n await waitFor(() => {\n expect(screen.queryByRole('button', { name: 'Mehr anzeigen' })).not.toBeInTheDocument();\n });\n });\n});\n"],"mappings":";;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,WAAA,GAAAF,sBAAA,CAAAF,OAAA;AAAsC,SAAAE,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEtCG,UAAE,CAACC,IAAI,CAAC,qBAAqB,EAAE,OAAO;EAClCC,WAAW,EAAEA,CAAA,KAAM,eAAe;EAClCC,kBAAkB,EAAEA,CAAC;IAAEC;EAAwC,CAAC,KAAKA;
|
|
1
|
+
{"version":3,"file":"Truncation.test.js","names":["_react","require","_react2","_interopRequireDefault","_vitest","_Truncation","e","__esModule","default","vi","mock","Translation","TextStringProvider","children","TextStringProviderSSR","resizeObserverCallbacks","ResizeObserverMock","constructor","callback","push","disconnect","observe","unobserve","stubGlobal","triggerResize","height","forEach","contentRect","afterEach","length","describe","it","render","createElement","collapsedHeight","waitFor","expect","screen","getByRole","name","toBeInTheDocument","queryByRole","not"],"sources":["../../../../src/components/truncation/Truncation.test.tsx"],"sourcesContent":["import { render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport Truncation from './Truncation';\n\nvi.mock('@chayns/textstrings', () => ({\n Translation: () => 'Mehr anzeigen',\n TextStringProvider: ({ children }: { children: React.ReactNode }) => children,\n TextStringProviderSSR: ({ children }: { children: React.ReactNode }) => children,\n}));\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[]) => void;\n\nconst resizeObserverCallbacks: ResizeObserverCallback[] = [];\n\nclass ResizeObserverMock {\n constructor(callback: ResizeObserverCallback) {\n resizeObserverCallbacks.push(callback);\n }\n\n disconnect() {}\n\n observe() {}\n\n unobserve() {}\n}\n\nvi.stubGlobal('ResizeObserver', ResizeObserverMock);\n\nconst triggerResize = (height: number) => {\n resizeObserverCallbacks.forEach((callback) => {\n callback([\n {\n contentRect: { height } as DOMRectReadOnly,\n } as ResizeObserverEntry,\n ]);\n });\n};\n\nafterEach(() => {\n resizeObserverCallbacks.length = 0;\n});\n\ndescribe('Truncation', () => {\n it('shows the more action when content exceeds the collapsed height', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Long content</div>\n </Truncation>,\n );\n\n triggerResize(240);\n\n await waitFor(() => {\n expect(screen.getByRole('button', { name: 'Mehr anzeigen' })).toBeInTheDocument();\n });\n });\n\n it('keeps short content expanded without a more action', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Short content</div>\n </Truncation>,\n );\n\n triggerResize(64);\n\n await waitFor(() => {\n expect(screen.queryByRole('button', { name: 'Mehr anzeigen' })).not.toBeInTheDocument();\n });\n });\n});\n"],"mappings":";;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,WAAA,GAAAF,sBAAA,CAAAF,OAAA;AAAsC,SAAAE,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEtCG,UAAE,CAACC,IAAI,CAAC,qBAAqB,EAAE,OAAO;EAClCC,WAAW,EAAEA,CAAA,KAAM,eAAe;EAClCC,kBAAkB,EAAEA,CAAC;IAAEC;EAAwC,CAAC,KAAKA,QAAQ;EAC7EC,qBAAqB,EAAEA,CAAC;IAAED;EAAwC,CAAC,KAAKA;AAC5E,CAAC,CAAC,CAAC;AAIH,MAAME,uBAAiD,GAAG,EAAE;AAE5D,MAAMC,kBAAkB,CAAC;EACrBC,WAAWA,CAACC,QAAgC,EAAE;IAC1CH,uBAAuB,CAACI,IAAI,CAACD,QAAQ,CAAC;EAC1C;EAEAE,UAAUA,CAAA,EAAG,CAAC;EAEdC,OAAOA,CAAA,EAAG,CAAC;EAEXC,SAASA,CAAA,EAAG,CAAC;AACjB;AAEAb,UAAE,CAACc,UAAU,CAAC,gBAAgB,EAAEP,kBAAkB,CAAC;AAEnD,MAAMQ,aAAa,GAAIC,MAAc,IAAK;EACtCV,uBAAuB,CAACW,OAAO,CAAER,QAAQ,IAAK;IAC1CA,QAAQ,CAAC,CACL;MACIS,WAAW,EAAE;QAAEF;MAAO;IAC1B,CAAC,CACJ,CAAC;EACN,CAAC,CAAC;AACN,CAAC;AAED,IAAAG,iBAAS,EAAC,MAAM;EACZb,uBAAuB,CAACc,MAAM,GAAG,CAAC;AACtC,CAAC,CAAC;AAEF,IAAAC,gBAAQ,EAAC,YAAY,EAAE,MAAM;EACzB,IAAAC,UAAE,EAAC,iEAAiE,EAAE,YAAY;IAC9E,IAAAC,aAAM,eACF9B,OAAA,CAAAM,OAAA,CAAAyB,aAAA,CAAC5B,WAAA,CAAAG,OAAU;MAAC0B,eAAe,EAAE;IAAI,gBAC7BhC,OAAA,CAAAM,OAAA,CAAAyB,aAAA,cAAK,cAAiB,CACd,CAChB,CAAC;IAEDT,aAAa,CAAC,GAAG,CAAC;IAElB,MAAM,IAAAW,cAAO,EAAC,MAAM;MAChB,IAAAC,cAAM,EAACC,aAAM,CAACC,SAAS,CAAC,QAAQ,EAAE;QAAEC,IAAI,EAAE;MAAgB,CAAC,CAAC,CAAC,CAACC,iBAAiB,CAAC,CAAC;IACrF,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAAT,UAAE,EAAC,oDAAoD,EAAE,YAAY;IACjE,IAAAC,aAAM,eACF9B,OAAA,CAAAM,OAAA,CAAAyB,aAAA,CAAC5B,WAAA,CAAAG,OAAU;MAAC0B,eAAe,EAAE;IAAI,gBAC7BhC,OAAA,CAAAM,OAAA,CAAAyB,aAAA,cAAK,eAAkB,CACf,CAChB,CAAC;IAEDT,aAAa,CAAC,EAAE,CAAC;IAEjB,MAAM,IAAAW,cAAO,EAAC,MAAM;MAChB,IAAAC,cAAM,EAACC,aAAM,CAACI,WAAW,CAAC,QAAQ,EAAE;QAAEF,IAAI,EAAE;MAAgB,CAAC,CAAC,CAAC,CAACG,GAAG,CAACF,iBAAiB,CAAC,CAAC;IAC3F,CAAC,CAAC;EACN,CAAC,CAAC;AACN,CAAC,CAAC","ignoreList":[]}
|
|
@@ -6,6 +6,16 @@ import { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighli
|
|
|
6
6
|
import { ClampPosition } from '../../types/truncation';
|
|
7
7
|
import { StyledMotionTruncationContent, StyledTruncation, StyledTruncationClamp, StyledTruncationClampFocusWrapper, StyledTruncationClampWrapper, StyledTruncationContent } from './Truncation.styles';
|
|
8
8
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
9
|
+
const getHeightAtLineBoundary = (element, height, contentHeight) => {
|
|
10
|
+
const elementTop = element.getBoundingClientRect().top;
|
|
11
|
+
const targetBottom = elementTop + height;
|
|
12
|
+
const range = element.ownerDocument.createRange();
|
|
13
|
+
range.selectNodeContents(element);
|
|
14
|
+
const lineRects = typeof range.getClientRects === 'function' ? Array.from(range.getClientRects()) : [];
|
|
15
|
+
const lineBottom = lineRects.map(rect => rect.bottom).filter(bottom => bottom >= targetBottom).sort((first, second) => first - second)[0];
|
|
16
|
+
range.detach();
|
|
17
|
+
return lineBottom === undefined ? Math.min(contentHeight, height) : Math.min(contentHeight, lineBottom - elementTop);
|
|
18
|
+
};
|
|
9
19
|
const Truncation = ({
|
|
10
20
|
collapsedHeight = 150,
|
|
11
21
|
clampPosition = ClampPosition.Right,
|
|
@@ -22,6 +32,7 @@ const Truncation = ({
|
|
|
22
32
|
const pendingObservedHeight = useRef(0);
|
|
23
33
|
const [internalIsOpen, setInternalIsOpen] = useState(Boolean(isOpen));
|
|
24
34
|
const [contentHeight, setContentHeight] = useState(0);
|
|
35
|
+
const [collapsedContentHeight, setCollapsedContentHeight] = useState(collapsedHeight);
|
|
25
36
|
useEffect(() => {
|
|
26
37
|
if (typeof isOpen === 'boolean') {
|
|
27
38
|
setInternalIsOpen(isOpen);
|
|
@@ -46,7 +57,9 @@ const Truncation = ({
|
|
|
46
57
|
if (!contentRef.current) {
|
|
47
58
|
return;
|
|
48
59
|
}
|
|
49
|
-
|
|
60
|
+
const measuredContentHeight = Math.max(pendingObservedHeight.current, contentRef.current.scrollHeight, contentRef.current.getBoundingClientRect().height);
|
|
61
|
+
setContentHeight(measuredContentHeight);
|
|
62
|
+
setCollapsedContentHeight(getHeightAtLineBoundary(contentRef.current, collapsedHeight, measuredContentHeight));
|
|
50
63
|
pendingObservedHeight.current = 0;
|
|
51
64
|
});
|
|
52
65
|
};
|
|
@@ -66,7 +79,7 @@ const Truncation = ({
|
|
|
66
79
|
window.cancelAnimationFrame(frame);
|
|
67
80
|
}
|
|
68
81
|
};
|
|
69
|
-
}, [children]);
|
|
82
|
+
}, [children, collapsedHeight]);
|
|
70
83
|
const handleClampClick = useCallback(event => {
|
|
71
84
|
setInternalIsOpen(current => {
|
|
72
85
|
onChange?.(event, !current);
|
|
@@ -85,8 +98,7 @@ const Truncation = ({
|
|
|
85
98
|
const internalLessLabel = lessLabel ?? /*#__PURE__*/React.createElement(Translation, {
|
|
86
99
|
textString: textStrings.components.truncation.less
|
|
87
100
|
});
|
|
88
|
-
const
|
|
89
|
-
const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : collapsedContentHeight;
|
|
101
|
+
const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : Math.min(contentHeight || collapsedHeight, collapsedContentHeight);
|
|
90
102
|
return /*#__PURE__*/React.createElement(StyledTruncation, {
|
|
91
103
|
className: "beta-chayns-truncation"
|
|
92
104
|
}, /*#__PURE__*/React.createElement(StyledMotionTruncationContent, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Truncation.js","names":["TextStringProviderSSR","Translation","React","useCallback","useEffect","useLayoutEffect","useRef","useState","textStrings","useFocusRingPortal","useKeyboardFocusHighlighting","ClampPosition","StyledMotionTruncationContent","StyledTruncation","StyledTruncationClamp","StyledTruncationClampFocusWrapper","StyledTruncationClampWrapper","StyledTruncationContent","useIsomorphicLayoutEffect","window","Truncation","collapsedHeight","clampPosition","Right","isOpen","lessLabel","moreLabel","onChange","children","shouldEnableKeyboardHighlighting","shouldShowKeyboardHighlighting","contentRef","clampRef","pendingObservedHeight","internalIsOpen","setInternalIsOpen","Boolean","contentHeight","setContentHeight","hasOverflow","isEnabled","current","frame","updateContentHeight","entries","Math","max","contentRect","height","undefined","requestAnimationFrame","scrollHeight","getBoundingClientRect","resizeObserver","ResizeObserver","mutationObserver","MutationObserver","observe","characterData","childList","subtree","disconnect","cancelAnimationFrame","handleClampClick","event","handleClampKeyDown","key","preventDefault","currentTarget","click","internalMoreLabel","createElement","textString","components","truncation","more","internalLessLabel","less","collapsedContentHeight","min","targetHeight","className","animate","initial","transition","type","duration","ref","$position","libraries","id","onClick","onKeyDown","role","tabIndex"],"sources":["../../../../src/components/truncation/Truncation.tsx"],"sourcesContent":["import { TextStringProviderSSR, Translation } from '@chayns/textstrings';\nimport React, {\n FC,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport textStrings from '../../constants/textStrings';\nimport { useFocusRingPortal } from '../../hooks/useFocusRingPortal';\nimport { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';\nimport { ClampPosition } from '../../types/truncation';\nimport {\n StyledMotionTruncationContent,\n StyledTruncation,\n StyledTruncationClamp,\n StyledTruncationClampFocusWrapper,\n StyledTruncationClampWrapper,\n StyledTruncationContent,\n} from './Truncation.styles';\n\nexport type TruncationProps = {\n /**\n * The elements that should be expanding or collapsing.\n */\n children: ReactElement;\n /**\n * The position of the clamp.\n */\n clampPosition?: ClampPosition;\n /**\n * The height of the children element in its collapsed state.\n */\n collapsedHeight?: number;\n /**\n * If set to true, the content is exposed.\n */\n isOpen?: boolean;\n /**\n * A text that should be displayed if the content is expanded.\n */\n lessLabel?: string;\n /**\n * A text that should be displayed if the content is collapsed.\n */\n moreLabel?: string;\n /**\n * Function to be executed when the component is expanding or collapsing.\n */\n onChange?: (event: MouseEvent<HTMLAnchorElement>, isOpen: boolean) => void;\n /**\n * Enables keyboard-only focus highlighting.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n};\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\nconst Truncation: FC<TruncationProps> = ({\n collapsedHeight = 150,\n clampPosition = ClampPosition.Right,\n isOpen,\n lessLabel,\n moreLabel,\n onChange,\n children,\n shouldEnableKeyboardHighlighting,\n}) => {\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n const contentRef = useRef<HTMLDivElement>(null);\n const clampRef = useRef<HTMLAnchorElement>(null);\n const pendingObservedHeight = useRef(0);\n const [internalIsOpen, setInternalIsOpen] = useState(Boolean(isOpen));\n const [contentHeight, setContentHeight] = useState(0);\n\n useEffect(() => {\n if (typeof isOpen === 'boolean') {\n setInternalIsOpen(isOpen);\n }\n }, [isOpen]);\n\n const hasOverflow = contentHeight > collapsedHeight;\n\n useFocusRingPortal(clampRef, {\n isEnabled: shouldShowKeyboardHighlighting && hasOverflow,\n });\n\n useIsomorphicLayoutEffect(() => {\n if (!contentRef.current) {\n return () => {};\n }\n\n let frame: number | undefined;\n const updateContentHeight = (entries?: ResizeObserverEntry[]) => {\n pendingObservedHeight.current = Math.max(\n pendingObservedHeight.current,\n entries?.[0]?.contentRect.height ?? 0,\n );\n\n if (frame !== undefined) {\n return;\n }\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n\n if (!contentRef.current) {\n return;\n }\n\n setContentHeight(\n Math.max(\n pendingObservedHeight.current,\n contentRef.current.scrollHeight,\n contentRef.current.getBoundingClientRect().height,\n ),\n );\n pendingObservedHeight.current = 0;\n });\n };\n\n const resizeObserver = new ResizeObserver((entries) => updateContentHeight(entries));\n const mutationObserver = new MutationObserver(() => updateContentHeight());\n\n resizeObserver.observe(contentRef.current);\n mutationObserver.observe(contentRef.current, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n updateContentHeight();\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n\n if (frame !== undefined) {\n window.cancelAnimationFrame(frame);\n }\n };\n }, [children]);\n\n const handleClampClick = useCallback<MouseEventHandler<HTMLAnchorElement>>(\n (event) => {\n setInternalIsOpen((current) => {\n onChange?.(event, !current);\n return !current;\n });\n },\n [onChange],\n );\n\n const handleClampKeyDown = useCallback<KeyboardEventHandler<HTMLAnchorElement>>((event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.currentTarget.click();\n }\n }, []);\n\n const internalMoreLabel = moreLabel ?? (\n <Translation textString={textStrings.components.truncation.more} />\n );\n const internalLessLabel = lessLabel ?? (\n <Translation textString={textStrings.components.truncation.less} />\n );\n const collapsedContentHeight = Math.min(contentHeight || collapsedHeight, collapsedHeight);\n const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : collapsedContentHeight;\n\n return (\n <StyledTruncation className=\"beta-chayns-truncation\">\n <StyledMotionTruncationContent\n animate={{ height: targetHeight }}\n initial={false}\n transition={{ type: 'tween', duration: 0.2 }}\n >\n <StyledTruncationContent ref={contentRef}>{children}</StyledTruncationContent>\n </StyledMotionTruncationContent>\n {hasOverflow && (\n <StyledTruncationClampWrapper $position={clampPosition}>\n <TextStringProviderSSR libraries=\"chayns-components-v5-core\" id=\"truncation\">\n <StyledTruncationClampFocusWrapper>\n <StyledTruncationClamp\n ref={clampRef}\n onClick={handleClampClick}\n onKeyDown={handleClampKeyDown}\n role=\"button\"\n tabIndex={0}\n >\n {internalIsOpen ? internalLessLabel : internalMoreLabel}\n </StyledTruncationClamp>\n </StyledTruncationClampFocusWrapper>\n </TextStringProviderSSR>\n </StyledTruncationClampWrapper>\n )}\n </StyledTruncation>\n );\n};\n\nexport default Truncation;\n"],"mappings":"AAAA,SAASA,qBAAqB,EAAEC,WAAW,QAAQ,qBAAqB;AACxE,OAAOC,KAAK,IAMRC,WAAW,EACXC,SAAS,EACTC,eAAe,EACfC,MAAM,EACNC,QAAQ,QACL,OAAO;AACd,OAAOC,WAAW,MAAM,6BAA6B;AACrD,SAASC,kBAAkB,QAAQ,gCAAgC;AACnE,SAASC,4BAA4B,QAAQ,0CAA0C;AACvF,SAASC,aAAa,QAAQ,wBAAwB;AACtD,SACIC,6BAA6B,EAC7BC,gBAAgB,EAChBC,qBAAqB,EACrBC,iCAAiC,EACjCC,4BAA4B,EAC5BC,uBAAuB,QACpB,qBAAqB;AAqC5B,MAAMC,yBAAyB,GAAG,OAAOC,MAAM,KAAK,WAAW,GAAGd,eAAe,GAAGD,SAAS;AAE7F,MAAMgB,UAA+B,GAAGA,CAAC;EACrCC,eAAe,GAAG,GAAG;EACrBC,aAAa,GAAGX,aAAa,CAACY,KAAK;EACnCC,MAAM;EACNC,SAAS;EACTC,SAAS;EACTC,QAAQ;EACRC,QAAQ;EACRC;AACJ,CAAC,KAAK;EACF,MAAMC,8BAA8B,GAAGpB,4BAA4B,CAC/DmB,gCACJ,CAAC;EACD,MAAME,UAAU,GAAGzB,MAAM,CAAiB,IAAI,CAAC;EAC/C,MAAM0B,QAAQ,GAAG1B,MAAM,CAAoB,IAAI,CAAC;EAChD,MAAM2B,qBAAqB,GAAG3B,MAAM,CAAC,CAAC,CAAC;EACvC,MAAM,CAAC4B,cAAc,EAAEC,iBAAiB,CAAC,GAAG5B,QAAQ,CAAC6B,OAAO,CAACZ,MAAM,CAAC,CAAC;EACrE,MAAM,CAACa,aAAa,EAAEC,gBAAgB,CAAC,GAAG/B,QAAQ,CAAC,CAAC,CAAC;EAErDH,SAAS,CAAC,MAAM;IACZ,IAAI,OAAOoB,MAAM,KAAK,SAAS,EAAE;MAC7BW,iBAAiB,CAACX,MAAM,CAAC;IAC7B;EACJ,CAAC,EAAE,CAACA,MAAM,CAAC,CAAC;EAEZ,MAAMe,WAAW,GAAGF,aAAa,GAAGhB,eAAe;EAEnDZ,kBAAkB,CAACuB,QAAQ,EAAE;IACzBQ,SAAS,EAAEV,8BAA8B,IAAIS;EACjD,CAAC,CAAC;EAEFrB,yBAAyB,CAAC,MAAM;IAC5B,IAAI,CAACa,UAAU,CAACU,OAAO,EAAE;MACrB,OAAO,MAAM,CAAC,CAAC;IACnB;IAEA,IAAIC,KAAyB;IAC7B,MAAMC,mBAAmB,GAAIC,OAA+B,IAAK;MAC7DX,qBAAqB,CAACQ,OAAO,GAAGI,IAAI,CAACC,GAAG,CACpCb,qBAAqB,CAACQ,OAAO,EAC7BG,OAAO,GAAG,CAAC,CAAC,EAAEG,WAAW,CAACC,MAAM,IAAI,CACxC,CAAC;MAED,IAAIN,KAAK,KAAKO,SAAS,EAAE;QACrB;MACJ;MAEAP,KAAK,GAAGvB,MAAM,CAAC+B,qBAAqB,CAAC,MAAM;QACvCR,KAAK,GAAGO,SAAS;QAEjB,IAAI,CAAClB,UAAU,CAACU,OAAO,EAAE;UACrB;QACJ;QAEAH,gBAAgB,CACZO,IAAI,CAACC,GAAG,CACJb,qBAAqB,CAACQ,OAAO,EAC7BV,UAAU,CAACU,OAAO,CAACU,YAAY,EAC/BpB,UAAU,CAACU,OAAO,CAACW,qBAAqB,CAAC,CAAC,CAACJ,MAC/C,CACJ,CAAC;QACDf,qBAAqB,CAACQ,OAAO,GAAG,CAAC;MACrC,CAAC,CAAC;IACN,CAAC;IAED,MAAMY,cAAc,GAAG,IAAIC,cAAc,CAAEV,OAAO,IAAKD,mBAAmB,CAACC,OAAO,CAAC,CAAC;IACpF,MAAMW,gBAAgB,GAAG,IAAIC,gBAAgB,CAAC,MAAMb,mBAAmB,CAAC,CAAC,CAAC;IAE1EU,cAAc,CAACI,OAAO,CAAC1B,UAAU,CAACU,OAAO,CAAC;IAC1Cc,gBAAgB,CAACE,OAAO,CAAC1B,UAAU,CAACU,OAAO,EAAE;MACzCiB,aAAa,EAAE,IAAI;MACnBC,SAAS,EAAE,IAAI;MACfC,OAAO,EAAE;IACb,CAAC,CAAC;IACFjB,mBAAmB,CAAC,CAAC;IAErB,OAAO,MAAM;MACTU,cAAc,CAACQ,UAAU,CAAC,CAAC;MAC3BN,gBAAgB,CAACM,UAAU,CAAC,CAAC;MAE7B,IAAInB,KAAK,KAAKO,SAAS,EAAE;QACrB9B,MAAM,CAAC2C,oBAAoB,CAACpB,KAAK,CAAC;MACtC;IACJ,CAAC;EACL,CAAC,EAAE,CAACd,QAAQ,CAAC,CAAC;EAEd,MAAMmC,gBAAgB,GAAG5D,WAAW,CAC/B6D,KAAK,IAAK;IACP7B,iBAAiB,CAAEM,OAAO,IAAK;MAC3Bd,QAAQ,GAAGqC,KAAK,EAAE,CAACvB,OAAO,CAAC;MAC3B,OAAO,CAACA,OAAO;IACnB,CAAC,CAAC;EACN,CAAC,EACD,CAACd,QAAQ,CACb,CAAC;EAED,MAAMsC,kBAAkB,GAAG9D,WAAW,CAA2C6D,KAAK,IAAK;IACvF,IAAIA,KAAK,CAACE,GAAG,KAAK,OAAO,IAAIF,KAAK,CAACE,GAAG,KAAK,GAAG,EAAE;MAC5CF,KAAK,CAACG,cAAc,CAAC,CAAC;MACtBH,KAAK,CAACI,aAAa,CAACC,KAAK,CAAC,CAAC;IAC/B;EACJ,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,iBAAiB,GAAG5C,SAAS,iBAC/BxB,KAAA,CAAAqE,aAAA,CAACtE,WAAW;IAACuE,UAAU,EAAEhE,WAAW,CAACiE,UAAU,CAACC,UAAU,CAACC;EAAK,CAAE,CACrE;EACD,MAAMC,iBAAiB,GAAGnD,SAAS,iBAC/BvB,KAAA,CAAAqE,aAAA,CAACtE,WAAW;IAACuE,UAAU,EAAEhE,WAAW,CAACiE,UAAU,CAACC,UAAU,CAACG;EAAK,CAAE,CACrE;EACD,MAAMC,sBAAsB,GAAGjC,IAAI,CAACkC,GAAG,CAAC1C,aAAa,IAAIhB,eAAe,EAAEA,eAAe,CAAC;EAC1F,MAAM2D,YAAY,GAAG9C,cAAc,GAAGG,aAAa,IAAIhB,eAAe,GAAGyD,sBAAsB;EAE/F,oBACI5E,KAAA,CAAAqE,aAAA,CAAC1D,gBAAgB;IAACoE,SAAS,EAAC;EAAwB,gBAChD/E,KAAA,CAAAqE,aAAA,CAAC3D,6BAA6B;IAC1BsE,OAAO,EAAE;MAAElC,MAAM,EAAEgC;IAAa,CAAE;IAClCG,OAAO,EAAE,KAAM;IACfC,UAAU,EAAE;MAAEC,IAAI,EAAE,OAAO;MAAEC,QAAQ,EAAE;IAAI;EAAE,gBAE7CpF,KAAA,CAAAqE,aAAA,CAACtD,uBAAuB;IAACsE,GAAG,EAAExD;EAAW,GAAEH,QAAkC,CAClD,CAAC,EAC/BW,WAAW,iBACRrC,KAAA,CAAAqE,aAAA,CAACvD,4BAA4B;IAACwE,SAAS,EAAElE;EAAc,gBACnDpB,KAAA,CAAAqE,aAAA,CAACvE,qBAAqB;IAACyF,SAAS,EAAC,2BAA2B;IAACC,EAAE,EAAC;EAAY,gBACxExF,KAAA,CAAAqE,aAAA,CAACxD,iCAAiC,qBAC9Bb,KAAA,CAAAqE,aAAA,CAACzD,qBAAqB;IAClByE,GAAG,EAAEvD,QAAS;IACd2D,OAAO,EAAE5B,gBAAiB;IAC1B6B,SAAS,EAAE3B,kBAAmB;IAC9B4B,IAAI,EAAC,QAAQ;IACbC,QAAQ,EAAE;EAAE,GAEX5D,cAAc,GAAG0C,iBAAiB,GAAGN,iBACnB,CACQ,CAChB,CACG,CAEpB,CAAC;AAE3B,CAAC;AAED,eAAelD,UAAU","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Truncation.js","names":["TextStringProviderSSR","Translation","React","useCallback","useEffect","useLayoutEffect","useRef","useState","textStrings","useFocusRingPortal","useKeyboardFocusHighlighting","ClampPosition","StyledMotionTruncationContent","StyledTruncation","StyledTruncationClamp","StyledTruncationClampFocusWrapper","StyledTruncationClampWrapper","StyledTruncationContent","useIsomorphicLayoutEffect","window","getHeightAtLineBoundary","element","height","contentHeight","elementTop","getBoundingClientRect","top","targetBottom","range","ownerDocument","createRange","selectNodeContents","lineRects","getClientRects","Array","from","lineBottom","map","rect","bottom","filter","sort","first","second","detach","undefined","Math","min","Truncation","collapsedHeight","clampPosition","Right","isOpen","lessLabel","moreLabel","onChange","children","shouldEnableKeyboardHighlighting","shouldShowKeyboardHighlighting","contentRef","clampRef","pendingObservedHeight","internalIsOpen","setInternalIsOpen","Boolean","setContentHeight","collapsedContentHeight","setCollapsedContentHeight","hasOverflow","isEnabled","current","frame","updateContentHeight","entries","max","contentRect","requestAnimationFrame","measuredContentHeight","scrollHeight","resizeObserver","ResizeObserver","mutationObserver","MutationObserver","observe","characterData","childList","subtree","disconnect","cancelAnimationFrame","handleClampClick","event","handleClampKeyDown","key","preventDefault","currentTarget","click","internalMoreLabel","createElement","textString","components","truncation","more","internalLessLabel","less","targetHeight","className","animate","initial","transition","type","duration","ref","$position","libraries","id","onClick","onKeyDown","role","tabIndex"],"sources":["../../../../src/components/truncation/Truncation.tsx"],"sourcesContent":["import { TextStringProviderSSR, Translation } from '@chayns/textstrings';\nimport React, {\n FC,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport textStrings from '../../constants/textStrings';\nimport { useFocusRingPortal } from '../../hooks/useFocusRingPortal';\nimport { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';\nimport { ClampPosition } from '../../types/truncation';\nimport {\n StyledMotionTruncationContent,\n StyledTruncation,\n StyledTruncationClamp,\n StyledTruncationClampFocusWrapper,\n StyledTruncationClampWrapper,\n StyledTruncationContent,\n} from './Truncation.styles';\n\nexport type TruncationProps = {\n /**\n * The elements that should be expanding or collapsing.\n */\n children: ReactElement;\n /**\n * The position of the clamp.\n */\n clampPosition?: ClampPosition;\n /**\n * The height of the children element in its collapsed state.\n */\n collapsedHeight?: number;\n /**\n * If set to true, the content is exposed.\n */\n isOpen?: boolean;\n /**\n * A text that should be displayed if the content is expanded.\n */\n lessLabel?: string;\n /**\n * A text that should be displayed if the content is collapsed.\n */\n moreLabel?: string;\n /**\n * Function to be executed when the component is expanding or collapsing.\n */\n onChange?: (event: MouseEvent<HTMLAnchorElement>, isOpen: boolean) => void;\n /**\n * Enables keyboard-only focus highlighting.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n};\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\nconst getHeightAtLineBoundary = (element: HTMLElement, height: number, contentHeight: number) => {\n const elementTop = element.getBoundingClientRect().top;\n const targetBottom = elementTop + height;\n const range = element.ownerDocument.createRange();\n\n range.selectNodeContents(element);\n\n const lineRects =\n typeof range.getClientRects === 'function' ? Array.from(range.getClientRects()) : [];\n const lineBottom = lineRects\n .map((rect) => rect.bottom)\n .filter((bottom) => bottom >= targetBottom)\n .sort((first, second) => first - second)[0];\n\n range.detach();\n\n return lineBottom === undefined\n ? Math.min(contentHeight, height)\n : Math.min(contentHeight, lineBottom - elementTop);\n};\n\nconst Truncation: FC<TruncationProps> = ({\n collapsedHeight = 150,\n clampPosition = ClampPosition.Right,\n isOpen,\n lessLabel,\n moreLabel,\n onChange,\n children,\n shouldEnableKeyboardHighlighting,\n}) => {\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n const contentRef = useRef<HTMLDivElement>(null);\n const clampRef = useRef<HTMLAnchorElement>(null);\n const pendingObservedHeight = useRef(0);\n const [internalIsOpen, setInternalIsOpen] = useState(Boolean(isOpen));\n const [contentHeight, setContentHeight] = useState(0);\n const [collapsedContentHeight, setCollapsedContentHeight] = useState(collapsedHeight);\n\n useEffect(() => {\n if (typeof isOpen === 'boolean') {\n setInternalIsOpen(isOpen);\n }\n }, [isOpen]);\n\n const hasOverflow = contentHeight > collapsedHeight;\n\n useFocusRingPortal(clampRef, {\n isEnabled: shouldShowKeyboardHighlighting && hasOverflow,\n });\n\n useIsomorphicLayoutEffect(() => {\n if (!contentRef.current) {\n return () => {};\n }\n\n let frame: number | undefined;\n const updateContentHeight = (entries?: ResizeObserverEntry[]) => {\n pendingObservedHeight.current = Math.max(\n pendingObservedHeight.current,\n entries?.[0]?.contentRect.height ?? 0,\n );\n\n if (frame !== undefined) {\n return;\n }\n\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n\n if (!contentRef.current) {\n return;\n }\n\n const measuredContentHeight = Math.max(\n pendingObservedHeight.current,\n contentRef.current.scrollHeight,\n contentRef.current.getBoundingClientRect().height,\n );\n\n setContentHeight(measuredContentHeight);\n setCollapsedContentHeight(\n getHeightAtLineBoundary(\n contentRef.current,\n collapsedHeight,\n measuredContentHeight,\n ),\n );\n pendingObservedHeight.current = 0;\n });\n };\n\n const resizeObserver = new ResizeObserver((entries) => updateContentHeight(entries));\n const mutationObserver = new MutationObserver(() => updateContentHeight());\n\n resizeObserver.observe(contentRef.current);\n mutationObserver.observe(contentRef.current, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n updateContentHeight();\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n\n if (frame !== undefined) {\n window.cancelAnimationFrame(frame);\n }\n };\n }, [children, collapsedHeight]);\n\n const handleClampClick = useCallback<MouseEventHandler<HTMLAnchorElement>>(\n (event) => {\n setInternalIsOpen((current) => {\n onChange?.(event, !current);\n return !current;\n });\n },\n [onChange],\n );\n\n const handleClampKeyDown = useCallback<KeyboardEventHandler<HTMLAnchorElement>>((event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.currentTarget.click();\n }\n }, []);\n\n const internalMoreLabel = moreLabel ?? (\n <Translation textString={textStrings.components.truncation.more} />\n );\n const internalLessLabel = lessLabel ?? (\n <Translation textString={textStrings.components.truncation.less} />\n );\n const targetHeight = internalIsOpen\n ? contentHeight || collapsedHeight\n : Math.min(contentHeight || collapsedHeight, collapsedContentHeight);\n\n return (\n <StyledTruncation className=\"beta-chayns-truncation\">\n <StyledMotionTruncationContent\n animate={{ height: targetHeight }}\n initial={false}\n transition={{ type: 'tween', duration: 0.2 }}\n >\n <StyledTruncationContent ref={contentRef}>{children}</StyledTruncationContent>\n </StyledMotionTruncationContent>\n {hasOverflow && (\n <StyledTruncationClampWrapper $position={clampPosition}>\n <TextStringProviderSSR libraries=\"chayns-components-v5-core\" id=\"truncation\">\n <StyledTruncationClampFocusWrapper>\n <StyledTruncationClamp\n ref={clampRef}\n onClick={handleClampClick}\n onKeyDown={handleClampKeyDown}\n role=\"button\"\n tabIndex={0}\n >\n {internalIsOpen ? internalLessLabel : internalMoreLabel}\n </StyledTruncationClamp>\n </StyledTruncationClampFocusWrapper>\n </TextStringProviderSSR>\n </StyledTruncationClampWrapper>\n )}\n </StyledTruncation>\n );\n};\n\nexport default Truncation;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Truncation.test.js","names":["render","screen","waitFor","React","afterEach","describe","expect","it","vi","Truncation","mock","Translation","TextStringProvider","children","resizeObserverCallbacks","ResizeObserverMock","constructor","callback","push","disconnect","observe","unobserve","stubGlobal","triggerResize","height","forEach","contentRect","length","createElement","collapsedHeight","getByRole","name","toBeInTheDocument","queryByRole","not"],"sources":["../../../../src/components/truncation/Truncation.test.tsx"],"sourcesContent":["import { render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport Truncation from './Truncation';\n\nvi.mock('@chayns/textstrings', () => ({\n Translation: () => 'Mehr anzeigen',\n TextStringProvider: ({ children }: { children: React.ReactNode }) => children,\n}));\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[]) => void;\n\nconst resizeObserverCallbacks: ResizeObserverCallback[] = [];\n\nclass ResizeObserverMock {\n constructor(callback: ResizeObserverCallback) {\n resizeObserverCallbacks.push(callback);\n }\n\n disconnect() {}\n\n observe() {}\n\n unobserve() {}\n}\n\nvi.stubGlobal('ResizeObserver', ResizeObserverMock);\n\nconst triggerResize = (height: number) => {\n resizeObserverCallbacks.forEach((callback) => {\n callback([\n {\n contentRect: { height } as DOMRectReadOnly,\n } as ResizeObserverEntry,\n ]);\n });\n};\n\nafterEach(() => {\n resizeObserverCallbacks.length = 0;\n});\n\ndescribe('Truncation', () => {\n it('shows the more action when content exceeds the collapsed height', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Long content</div>\n </Truncation>,\n );\n\n triggerResize(240);\n\n await waitFor(() => {\n expect(screen.getByRole('button', { name: 'Mehr anzeigen' })).toBeInTheDocument();\n });\n });\n\n it('keeps short content expanded without a more action', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Short content</div>\n </Truncation>,\n );\n\n triggerResize(64);\n\n await waitFor(() => {\n expect(screen.queryByRole('button', { name: 'Mehr anzeigen' })).not.toBeInTheDocument();\n });\n });\n});\n"],"mappings":"AAAA,SAASA,MAAM,EAAEC,MAAM,EAAEC,OAAO,QAAQ,wBAAwB;AAChE,OAAOC,KAAK,MAAM,OAAO;AACzB,SAASC,SAAS,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,QAAQ;AAC5D,OAAOC,UAAU,MAAM,cAAc;AAErCD,EAAE,CAACE,IAAI,CAAC,qBAAqB,EAAE,OAAO;EAClCC,WAAW,EAAEA,CAAA,KAAM,eAAe;EAClCC,kBAAkB,EAAEA,CAAC;IAAEC;EAAwC,CAAC,KAAKA;
|
|
1
|
+
{"version":3,"file":"Truncation.test.js","names":["render","screen","waitFor","React","afterEach","describe","expect","it","vi","Truncation","mock","Translation","TextStringProvider","children","TextStringProviderSSR","resizeObserverCallbacks","ResizeObserverMock","constructor","callback","push","disconnect","observe","unobserve","stubGlobal","triggerResize","height","forEach","contentRect","length","createElement","collapsedHeight","getByRole","name","toBeInTheDocument","queryByRole","not"],"sources":["../../../../src/components/truncation/Truncation.test.tsx"],"sourcesContent":["import { render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport Truncation from './Truncation';\n\nvi.mock('@chayns/textstrings', () => ({\n Translation: () => 'Mehr anzeigen',\n TextStringProvider: ({ children }: { children: React.ReactNode }) => children,\n TextStringProviderSSR: ({ children }: { children: React.ReactNode }) => children,\n}));\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[]) => void;\n\nconst resizeObserverCallbacks: ResizeObserverCallback[] = [];\n\nclass ResizeObserverMock {\n constructor(callback: ResizeObserverCallback) {\n resizeObserverCallbacks.push(callback);\n }\n\n disconnect() {}\n\n observe() {}\n\n unobserve() {}\n}\n\nvi.stubGlobal('ResizeObserver', ResizeObserverMock);\n\nconst triggerResize = (height: number) => {\n resizeObserverCallbacks.forEach((callback) => {\n callback([\n {\n contentRect: { height } as DOMRectReadOnly,\n } as ResizeObserverEntry,\n ]);\n });\n};\n\nafterEach(() => {\n resizeObserverCallbacks.length = 0;\n});\n\ndescribe('Truncation', () => {\n it('shows the more action when content exceeds the collapsed height', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Long content</div>\n </Truncation>,\n );\n\n triggerResize(240);\n\n await waitFor(() => {\n expect(screen.getByRole('button', { name: 'Mehr anzeigen' })).toBeInTheDocument();\n });\n });\n\n it('keeps short content expanded without a more action', async () => {\n render(\n <Truncation collapsedHeight={100}>\n <div>Short content</div>\n </Truncation>,\n );\n\n triggerResize(64);\n\n await waitFor(() => {\n expect(screen.queryByRole('button', { name: 'Mehr anzeigen' })).not.toBeInTheDocument();\n });\n });\n});\n"],"mappings":"AAAA,SAASA,MAAM,EAAEC,MAAM,EAAEC,OAAO,QAAQ,wBAAwB;AAChE,OAAOC,KAAK,MAAM,OAAO;AACzB,SAASC,SAAS,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,QAAQ;AAC5D,OAAOC,UAAU,MAAM,cAAc;AAErCD,EAAE,CAACE,IAAI,CAAC,qBAAqB,EAAE,OAAO;EAClCC,WAAW,EAAEA,CAAA,KAAM,eAAe;EAClCC,kBAAkB,EAAEA,CAAC;IAAEC;EAAwC,CAAC,KAAKA,QAAQ;EAC7EC,qBAAqB,EAAEA,CAAC;IAAED;EAAwC,CAAC,KAAKA;AAC5E,CAAC,CAAC,CAAC;AAIH,MAAME,uBAAiD,GAAG,EAAE;AAE5D,MAAMC,kBAAkB,CAAC;EACrBC,WAAWA,CAACC,QAAgC,EAAE;IAC1CH,uBAAuB,CAACI,IAAI,CAACD,QAAQ,CAAC;EAC1C;EAEAE,UAAUA,CAAA,EAAG,CAAC;EAEdC,OAAOA,CAAA,EAAG,CAAC;EAEXC,SAASA,CAAA,EAAG,CAAC;AACjB;AAEAd,EAAE,CAACe,UAAU,CAAC,gBAAgB,EAAEP,kBAAkB,CAAC;AAEnD,MAAMQ,aAAa,GAAIC,MAAc,IAAK;EACtCV,uBAAuB,CAACW,OAAO,CAAER,QAAQ,IAAK;IAC1CA,QAAQ,CAAC,CACL;MACIS,WAAW,EAAE;QAAEF;MAAO;IAC1B,CAAC,CACJ,CAAC;EACN,CAAC,CAAC;AACN,CAAC;AAEDrB,SAAS,CAAC,MAAM;EACZW,uBAAuB,CAACa,MAAM,GAAG,CAAC;AACtC,CAAC,CAAC;AAEFvB,QAAQ,CAAC,YAAY,EAAE,MAAM;EACzBE,EAAE,CAAC,iEAAiE,EAAE,YAAY;IAC9EP,MAAM,cACFG,KAAA,CAAA0B,aAAA,CAACpB,UAAU;MAACqB,eAAe,EAAE;IAAI,gBAC7B3B,KAAA,CAAA0B,aAAA,cAAK,cAAiB,CACd,CAChB,CAAC;IAEDL,aAAa,CAAC,GAAG,CAAC;IAElB,MAAMtB,OAAO,CAAC,MAAM;MAChBI,MAAM,CAACL,MAAM,CAAC8B,SAAS,CAAC,QAAQ,EAAE;QAAEC,IAAI,EAAE;MAAgB,CAAC,CAAC,CAAC,CAACC,iBAAiB,CAAC,CAAC;IACrF,CAAC,CAAC;EACN,CAAC,CAAC;EAEF1B,EAAE,CAAC,oDAAoD,EAAE,YAAY;IACjEP,MAAM,cACFG,KAAA,CAAA0B,aAAA,CAACpB,UAAU;MAACqB,eAAe,EAAE;IAAI,gBAC7B3B,KAAA,CAAA0B,aAAA,cAAK,eAAkB,CACf,CAChB,CAAC;IAEDL,aAAa,CAAC,EAAE,CAAC;IAEjB,MAAMtB,OAAO,CAAC,MAAM;MAChBI,MAAM,CAACL,MAAM,CAACiC,WAAW,CAAC,QAAQ,EAAE;QAAEF,IAAI,EAAE;MAAgB,CAAC,CAAC,CAAC,CAACG,GAAG,CAACF,iBAAiB,CAAC,CAAC;IAC3F,CAAC,CAAC;EACN,CAAC,CAAC;AACN,CAAC,CAAC","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chayns-components/core",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.42",
|
|
4
4
|
"description": "A set of beautiful React components for developing your own applications with chayns.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"browserslist": [
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"publishConfig": {
|
|
94
94
|
"access": "public"
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "c319b7cea48a7f51172e657f756aa44580e81784"
|
|
97
97
|
}
|