@chayns-components/core 5.5.24 → 5.5.26
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 +44 -0
- package/lib/cjs/components/copyable-content/CopyableContent.js +10 -1
- package/lib/cjs/components/copyable-content/CopyableContent.js.map +1 -1
- package/lib/cjs/components/copyable-content/CopyableContent.styles.js +62 -40
- package/lib/cjs/components/copyable-content/CopyableContent.styles.js.map +1 -1
- package/lib/cjs/components/copyable-content/CopyableContent.test.js +38 -4
- package/lib/cjs/components/copyable-content/CopyableContent.test.js.map +1 -1
- package/lib/cjs/components/truncation/Truncation.js +61 -149
- package/lib/cjs/components/truncation/Truncation.js.map +1 -1
- package/lib/cjs/components/truncation/Truncation.styles.js +3 -4
- package/lib/cjs/components/truncation/Truncation.styles.js.map +1 -1
- package/lib/cjs/components/truncation/Truncation.test.js +61 -0
- package/lib/cjs/components/truncation/Truncation.test.js.map +1 -0
- package/lib/esm/components/copyable-content/CopyableContent.js +11 -2
- package/lib/esm/components/copyable-content/CopyableContent.js.map +1 -1
- package/lib/esm/components/copyable-content/CopyableContent.styles.js +61 -39
- package/lib/esm/components/copyable-content/CopyableContent.styles.js.map +1 -1
- package/lib/esm/components/copyable-content/CopyableContent.test.js +38 -4
- package/lib/esm/components/copyable-content/CopyableContent.test.js.map +1 -1
- package/lib/esm/components/truncation/Truncation.js +61 -149
- package/lib/esm/components/truncation/Truncation.js.map +1 -1
- package/lib/esm/components/truncation/Truncation.styles.js +2 -3
- package/lib/esm/components/truncation/Truncation.styles.js.map +1 -1
- package/lib/esm/components/truncation/Truncation.test.js +58 -0
- package/lib/esm/components/truncation/Truncation.test.js.map +1 -0
- package/lib/types/components/copyable-content/CopyableContent.styles.d.ts +16 -6
- package/lib/types/components/truncation/Truncation.d.ts +1 -1
- package/lib/types/components/truncation/Truncation.styles.d.ts +1 -1
- package/package.json +2 -2
- package/lib/cjs/utils/truncation.js +0 -42
- package/lib/cjs/utils/truncation.js.map +0 -1
- package/lib/esm/utils/truncation.js +0 -35
- package/lib/esm/utils/truncation.js.map +0 -1
- package/lib/types/utils/truncation.d.ts +0 -1
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
import { CopyableContentAppearance } from './CopyableContent.types';
|
|
3
|
+
export let CopyableContentColorMode = /*#__PURE__*/function (CopyableContentColorMode) {
|
|
4
|
+
CopyableContentColorMode["Dark"] = "dark";
|
|
5
|
+
CopyableContentColorMode["Light"] = "light";
|
|
6
|
+
return CopyableContentColorMode;
|
|
7
|
+
}({});
|
|
3
8
|
const getBackgroundColor = ({
|
|
4
9
|
$appearance,
|
|
5
|
-
|
|
10
|
+
$colorMode
|
|
6
11
|
}) => {
|
|
7
12
|
if ($appearance === CopyableContentAppearance.Chat) {
|
|
8
13
|
return 'rgba(0, 0, 0, 0.12)';
|
|
9
14
|
}
|
|
10
|
-
|
|
11
|
-
const opacity = theme.cardBackgroundOpacity ?? 1;
|
|
12
|
-
return `rgba(${secondaryColor}, ${opacity})`;
|
|
15
|
+
return $colorMode === CopyableContentColorMode.Dark ? '#282c34' : '#fafafa';
|
|
13
16
|
};
|
|
17
|
+
const getTextColor = ({
|
|
18
|
+
$colorMode
|
|
19
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#f4f6f8' : '#333333';
|
|
14
20
|
export const StyledCopyableContent = styled.section`
|
|
15
21
|
--copyable-content-action-size: 32px;
|
|
16
22
|
--copyable-content-action-inset: 8px;
|
|
@@ -25,11 +31,39 @@ export const StyledCopyableContent = styled.section`
|
|
|
25
31
|
);
|
|
26
32
|
border-radius: 8px;
|
|
27
33
|
background-color: ${getBackgroundColor};
|
|
28
|
-
color: ${
|
|
29
|
-
theme
|
|
30
|
-
}) => theme.text};
|
|
34
|
+
color: ${getTextColor};
|
|
31
35
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.16);
|
|
32
36
|
`;
|
|
37
|
+
const getActionGroupBorder = ({
|
|
38
|
+
$colorMode,
|
|
39
|
+
$isSticky
|
|
40
|
+
}) => {
|
|
41
|
+
if (!$isSticky) {
|
|
42
|
+
return 'transparent';
|
|
43
|
+
}
|
|
44
|
+
return $colorMode === CopyableContentColorMode.Dark ? '#5a6474' : '#d4d4d4';
|
|
45
|
+
};
|
|
46
|
+
const getActionGroupBackground = ({
|
|
47
|
+
$colorMode,
|
|
48
|
+
$isSticky
|
|
49
|
+
}) => {
|
|
50
|
+
if (!$isSticky) {
|
|
51
|
+
return 'transparent';
|
|
52
|
+
}
|
|
53
|
+
return $colorMode === CopyableContentColorMode.Dark ? '#343a46' : '#fafafa';
|
|
54
|
+
};
|
|
55
|
+
const getButtonHoverBackground = ({
|
|
56
|
+
$colorMode
|
|
57
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#454c59' : 'rgba(128, 128, 128, 0.2)';
|
|
58
|
+
const getButtonActiveBackground = ({
|
|
59
|
+
$colorMode
|
|
60
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#545d6d' : 'rgba(128, 128, 128, 0.3)';
|
|
61
|
+
const getButtonHoverBorder = ({
|
|
62
|
+
$colorMode
|
|
63
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#6a7485' : '#c2c2c2';
|
|
64
|
+
const getButtonColor = ({
|
|
65
|
+
$colorMode
|
|
66
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#f4f6f8' : '#999999';
|
|
33
67
|
export const StyledCopyableContentActions = styled.div`
|
|
34
68
|
position: sticky;
|
|
35
69
|
top: var(--copyable-content-action-inset);
|
|
@@ -49,22 +83,14 @@ export const StyledCopyableContentActionGroup = styled.div`
|
|
|
49
83
|
`;
|
|
50
84
|
export const StyledCopyableContentButton = styled.button`
|
|
51
85
|
box-sizing: border-box;
|
|
52
|
-
border: 1px solid ${
|
|
53
|
-
$isSticky,
|
|
54
|
-
theme
|
|
55
|
-
}) => $isSticky ? theme['202'] : 'transparent'};
|
|
86
|
+
border: 1px solid ${getActionGroupBorder};
|
|
56
87
|
border-radius: 4px;
|
|
57
88
|
width: var(--copyable-content-action-size);
|
|
58
89
|
height: var(--copyable-content-action-size);
|
|
59
90
|
padding: 0;
|
|
60
91
|
cursor: pointer;
|
|
61
|
-
background-color: ${
|
|
62
|
-
|
|
63
|
-
theme
|
|
64
|
-
}) => $isSticky ? theme['100'] : 'transparent'};
|
|
65
|
-
color: ${({
|
|
66
|
-
theme
|
|
67
|
-
}) => theme.text};
|
|
92
|
+
background-color: ${getActionGroupBackground};
|
|
93
|
+
color: ${getButtonColor};
|
|
68
94
|
box-shadow: ${({
|
|
69
95
|
$isSticky
|
|
70
96
|
}) => $isSticky ? '0 2px 8px rgba(0, 0, 0, 0.28)' : 'none'};
|
|
@@ -75,31 +101,33 @@ export const StyledCopyableContentButton = styled.button`
|
|
|
75
101
|
transform 0.15s ease;
|
|
76
102
|
|
|
77
103
|
&:hover {
|
|
78
|
-
border-color:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
background-color: rgba(${({
|
|
82
|
-
theme
|
|
83
|
-
}) => theme['text-rgb']}, 0.1);
|
|
84
|
-
box-shadow: inset 0 0 0 1px rgba(${({
|
|
85
|
-
theme
|
|
86
|
-
}) => theme['text-rgb']}, 0.06);
|
|
104
|
+
border-color: ${getButtonHoverBorder};
|
|
105
|
+
background-color: ${getButtonHoverBackground};
|
|
106
|
+
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
|
|
87
107
|
}
|
|
88
108
|
|
|
89
109
|
&:active {
|
|
110
|
+
background-color: ${getButtonActiveBackground};
|
|
90
111
|
transform: scale(0.94);
|
|
91
112
|
}
|
|
92
113
|
|
|
93
114
|
&:focus-visible {
|
|
94
|
-
outline: 2px solid
|
|
95
|
-
theme
|
|
96
|
-
}) => theme.buttonBackgroundColor};
|
|
115
|
+
outline: 2px solid currentColor;
|
|
97
116
|
outline-offset: 2px;
|
|
98
117
|
}
|
|
99
118
|
`;
|
|
100
119
|
export const StyledCopyableContentTruncation = styled.div`
|
|
101
120
|
padding: 0 12px 12px;
|
|
102
121
|
`;
|
|
122
|
+
const getHeadlineColor = ({
|
|
123
|
+
$colorMode
|
|
124
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#e5e5e5' : '#333333';
|
|
125
|
+
const getBlockquoteBorderColor = ({
|
|
126
|
+
$colorMode
|
|
127
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#5a6474' : '#d4d4d4';
|
|
128
|
+
const getLinkColor = ({
|
|
129
|
+
$colorMode
|
|
130
|
+
}) => $colorMode === CopyableContentColorMode.Dark ? '#7cb3ff' : '#0066cc';
|
|
103
131
|
export const StyledCopyableContentBody = styled.div`
|
|
104
132
|
min-width: 0;
|
|
105
133
|
max-width: 100%;
|
|
@@ -127,9 +155,7 @@ export const StyledCopyableContentBody = styled.div`
|
|
|
127
155
|
h4,
|
|
128
156
|
h5,
|
|
129
157
|
h6 {
|
|
130
|
-
color: ${
|
|
131
|
-
theme
|
|
132
|
-
}) => theme.headline};
|
|
158
|
+
color: ${getHeadlineColor};
|
|
133
159
|
}
|
|
134
160
|
|
|
135
161
|
ul,
|
|
@@ -139,15 +165,11 @@ export const StyledCopyableContentBody = styled.div`
|
|
|
139
165
|
|
|
140
166
|
blockquote {
|
|
141
167
|
padding-left: 12px;
|
|
142
|
-
border-left: 3px solid ${
|
|
143
|
-
theme
|
|
144
|
-
}) => theme['202']};
|
|
168
|
+
border-left: 3px solid ${getBlockquoteBorderColor};
|
|
145
169
|
}
|
|
146
170
|
|
|
147
171
|
a {
|
|
148
|
-
color: ${
|
|
149
|
-
theme
|
|
150
|
-
}) => theme.primary};
|
|
172
|
+
color: ${getLinkColor};
|
|
151
173
|
overflow-wrap: anywhere;
|
|
152
174
|
}
|
|
153
175
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopyableContent.styles.js","names":["styled","CopyableContentAppearance","getBackgroundColor","$appearance","
|
|
1
|
+
{"version":3,"file":"CopyableContent.styles.js","names":["styled","CopyableContentAppearance","CopyableContentColorMode","getBackgroundColor","$appearance","$colorMode","Chat","Dark","getTextColor","StyledCopyableContent","section","getActionGroupBorder","$isSticky","getActionGroupBackground","getButtonHoverBackground","getButtonActiveBackground","getButtonHoverBorder","getButtonColor","StyledCopyableContentActions","div","StyledCopyableContentActionGroup","StyledCopyableContentButton","button","StyledCopyableContentTruncation","getHeadlineColor","getBlockquoteBorderColor","getLinkColor","StyledCopyableContentBody","$shouldShowPadding"],"sources":["../../../../src/components/copyable-content/CopyableContent.styles.ts"],"sourcesContent":["import type { WithTheme } from '../color-scheme-provider/ColorSchemeProvider';\nimport styled from 'styled-components';\nimport { CopyableContentAppearance } from './CopyableContent.types';\n\nexport enum CopyableContentColorMode {\n Dark = 'dark',\n Light = 'light',\n}\n\ntype StyledCopyableContentProps = WithTheme<{\n $appearance: CopyableContentAppearance;\n $colorMode: CopyableContentColorMode;\n}>;\n\nconst getBackgroundColor = ({ $appearance, $colorMode }: StyledCopyableContentProps) => {\n if ($appearance === CopyableContentAppearance.Chat) {\n return 'rgba(0, 0, 0, 0.12)';\n }\n\n return $colorMode === CopyableContentColorMode.Dark ? '#282c34' : '#fafafa';\n};\n\nconst getTextColor = ({ $colorMode }: StyledCopyableContentProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#f4f6f8' : '#333333';\n\nexport const StyledCopyableContent = styled.section<StyledCopyableContentProps>`\n --copyable-content-action-size: 32px;\n --copyable-content-action-inset: 8px;\n\n margin: 4px 0;\n min-width: 0;\n max-width: 100%;\n overflow-x: clip;\n overflow-wrap: anywhere;\n padding-top: calc(\n var(--copyable-content-action-size) + var(--copyable-content-action-inset) * 2\n );\n border-radius: 8px;\n background-color: ${getBackgroundColor};\n color: ${getTextColor};\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.16);\n`;\n\ntype StyledCopyableContentButtonProps = WithTheme<{\n $colorMode: CopyableContentColorMode;\n $isSticky: boolean;\n}>;\n\nconst getActionGroupBorder = ({ $colorMode, $isSticky }: StyledCopyableContentButtonProps) => {\n if (!$isSticky) {\n return 'transparent';\n }\n\n return $colorMode === CopyableContentColorMode.Dark ? '#5a6474' : '#d4d4d4';\n};\n\nconst getActionGroupBackground = ({ $colorMode, $isSticky }: StyledCopyableContentButtonProps) => {\n if (!$isSticky) {\n return 'transparent';\n }\n\n return $colorMode === CopyableContentColorMode.Dark ? '#343a46' : '#fafafa';\n};\n\nconst getButtonHoverBackground = ({ $colorMode }: StyledCopyableContentButtonProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#454c59' : 'rgba(128, 128, 128, 0.2)';\n\nconst getButtonActiveBackground = ({ $colorMode }: StyledCopyableContentButtonProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#545d6d' : 'rgba(128, 128, 128, 0.3)';\n\nconst getButtonHoverBorder = ({ $colorMode }: StyledCopyableContentButtonProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#6a7485' : '#c2c2c2';\n\nconst getButtonColor = ({ $colorMode }: StyledCopyableContentButtonProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#f4f6f8' : '#999999';\n\nexport const StyledCopyableContentActions = styled.div`\n position: sticky;\n top: var(--copyable-content-action-inset);\n z-index: 1;\n display: flex;\n justify-content: flex-end;\n height: calc(var(--copyable-content-action-size) + var(--copyable-content-action-inset));\n margin-top: calc(\n (var(--copyable-content-action-size) + var(--copyable-content-action-inset)) * -1\n );\n padding-right: var(--copyable-content-action-inset);\n`;\n\nexport const StyledCopyableContentActionGroup = styled.div`\n display: flex;\n gap: 4px;\n height: var(--copyable-content-action-size);\n`;\n\nexport const StyledCopyableContentButton = styled.button<StyledCopyableContentButtonProps>`\n box-sizing: border-box;\n border: 1px solid ${getActionGroupBorder};\n border-radius: 4px;\n width: var(--copyable-content-action-size);\n height: var(--copyable-content-action-size);\n padding: 0;\n cursor: pointer;\n background-color: ${getActionGroupBackground};\n color: ${getButtonColor};\n box-shadow: ${({ $isSticky }) => ($isSticky ? '0 2px 8px rgba(0, 0, 0, 0.28)' : 'none')};\n transition:\n background-color 0.15s ease,\n border-color 0.15s ease,\n box-shadow 0.15s ease,\n transform 0.15s ease;\n\n &:hover {\n border-color: ${getButtonHoverBorder};\n background-color: ${getButtonHoverBackground};\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);\n }\n\n &:active {\n background-color: ${getButtonActiveBackground};\n transform: scale(0.94);\n }\n\n &:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n`;\n\nexport const StyledCopyableContentTruncation = styled.div`\n padding: 0 12px 12px;\n`;\n\ntype StyledCopyableContentBodyProps = WithTheme<{\n $colorMode: CopyableContentColorMode;\n $shouldShowPadding?: boolean;\n}>;\n\nconst getHeadlineColor = ({ $colorMode }: StyledCopyableContentBodyProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#e5e5e5' : '#333333';\n\nconst getBlockquoteBorderColor = ({ $colorMode }: StyledCopyableContentBodyProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#5a6474' : '#d4d4d4';\n\nconst getLinkColor = ({ $colorMode }: StyledCopyableContentBodyProps) =>\n $colorMode === CopyableContentColorMode.Dark ? '#7cb3ff' : '#0066cc';\n\nexport const StyledCopyableContentBody = styled.div<StyledCopyableContentBodyProps>`\n min-width: 0;\n max-width: 100%;\n overflow-wrap: anywhere;\n padding: ${({ $shouldShowPadding = true }) => ($shouldShowPadding ? '0 12px 12px' : '0')};\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6,\n p,\n ul,\n ol,\n blockquote {\n margin: 0 0 12px;\n }\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n color: ${getHeadlineColor};\n }\n\n ul,\n ol {\n padding-left: 24px;\n }\n\n blockquote {\n padding-left: 12px;\n border-left: 3px solid ${getBlockquoteBorderColor};\n }\n\n a {\n color: ${getLinkColor};\n overflow-wrap: anywhere;\n }\n\n > :last-child {\n margin-bottom: 0;\n }\n`;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,6 +3,37 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { describe, expect, it, vi } from 'vitest';
|
|
5
5
|
import CopyableContent from './CopyableContent';
|
|
6
|
+
vi.mock('@chayns-components/textstring', () => ({
|
|
7
|
+
Textstring: ({
|
|
8
|
+
textstring
|
|
9
|
+
}) => textstring.fallback,
|
|
10
|
+
TextstringProvider: ({
|
|
11
|
+
children
|
|
12
|
+
}) => children,
|
|
13
|
+
ttsToITextString: textstring => textstring,
|
|
14
|
+
useTextstringValue: ({
|
|
15
|
+
textstring
|
|
16
|
+
}) => textstring.fallback
|
|
17
|
+
}));
|
|
18
|
+
const resizeObserverCallbacks = [];
|
|
19
|
+
class ResizeObserverMock {
|
|
20
|
+
constructor(callback) {
|
|
21
|
+
resizeObserverCallbacks.push(callback);
|
|
22
|
+
}
|
|
23
|
+
disconnect() {}
|
|
24
|
+
observe() {}
|
|
25
|
+
unobserve() {}
|
|
26
|
+
}
|
|
27
|
+
vi.stubGlobal('ResizeObserver', ResizeObserverMock);
|
|
28
|
+
const triggerResize = height => {
|
|
29
|
+
resizeObserverCallbacks.forEach(callback => {
|
|
30
|
+
callback([{
|
|
31
|
+
contentRect: {
|
|
32
|
+
height
|
|
33
|
+
}
|
|
34
|
+
}]);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
6
37
|
vi.mock('../icon/Icon', () => ({
|
|
7
38
|
default: ({
|
|
8
39
|
icons
|
|
@@ -84,14 +115,17 @@ describe('CopyableContent', () => {
|
|
|
84
115
|
expect(container.querySelector('[data-copy-action="false"]')).toBeInTheDocument();
|
|
85
116
|
expect(container.querySelector('[data-calling-code-action="false"]')).toBeInTheDocument();
|
|
86
117
|
});
|
|
87
|
-
it('supports collapsed content', () => {
|
|
118
|
+
it('supports collapsed content', async () => {
|
|
88
119
|
render(/*#__PURE__*/React.createElement(CopyableContent, {
|
|
89
120
|
collapsedHeight: 100,
|
|
90
121
|
content: Array(20).fill('Long content').join('\n\n')
|
|
91
122
|
}));
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
123
|
+
triggerResize(240);
|
|
124
|
+
await waitFor(() => {
|
|
125
|
+
expect(screen.getByRole('button', {
|
|
126
|
+
name: 'Mehr'
|
|
127
|
+
})).toBeInTheDocument();
|
|
128
|
+
});
|
|
95
129
|
});
|
|
96
130
|
});
|
|
97
131
|
//# sourceMappingURL=CopyableContent.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopyableContent.test.js","names":["fireEvent","render","screen","waitFor","React","describe","expect","it","vi","CopyableContent","mock","default","icons","createElement","join","children","shouldShowCallingCodeAction","shouldShowCopyAction","importOriginal","createDialog","fn","open","readBlob","blob","Promise","resolve","reject","reader","FileReader","onerror","error","onload","result","readAsText","content","getByRole","name","toBeInTheDocument","toHaveAttribute","document","querySelector","not","write","spyOn","navigator","clipboard","mockResolvedValue","click","toHaveBeenCalled","item","calls","getType","resolves","toBe","container","collapsedHeight","Array","fill"],"sources":["../../../../src/components/copyable-content/CopyableContent.test.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-call */\nimport { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { describe, expect, it, vi } from 'vitest';\nimport CopyableContent from './CopyableContent';\n\nvi.mock('../icon/Icon', () => ({\n default: ({ icons }: { icons: string[] }) => <span data-icons={icons.join(' ')} />,\n}));\n\nvi.mock('../sharing-context-menu/SharingContextMenu', () => ({\n default: ({\n children,\n shouldShowCallingCodeAction,\n shouldShowCopyAction,\n }: {\n children: React.ReactNode;\n shouldShowCallingCodeAction?: boolean;\n shouldShowCopyAction?: boolean;\n }) => (\n <div\n data-calling-code-action={shouldShowCallingCodeAction}\n data-copy-action={shouldShowCopyAction}\n >\n {children}\n </div>\n ),\n}));\n\nvi.mock('chayns-api', async (importOriginal) => ({\n ...(await importOriginal<typeof import('chayns-api')>()),\n createDialog: vi.fn(() => ({ open: vi.fn() })),\n}));\n\nconst readBlob = (blob: Blob) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error);\n reader.onload = () => resolve(reader.result as string);\n reader.readAsText(blob);\n });\n\ndescribe('CopyableContent', () => {\n it('renders formatted markdown without active input HTML', () => {\n render(\n <CopyableContent\n content={\n '# Heading\\n\\n- Entry\\n\\n[Link](https://example.com)\\n<script onload=\"x\">bad</script>'\n }\n />,\n );\n\n expect(screen.getByRole('heading', { name: 'Heading' })).toBeInTheDocument();\n expect(screen.getByRole('link', { name: 'Link' })).toHaveAttribute(\n 'href',\n 'https://example.com',\n );\n expect(document.querySelector('script')).not.toBeInTheDocument();\n expect(document.querySelector('[onload]')).not.toBeInTheDocument();\n });\n\n it('copies content instead of custom children', async () => {\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n render(<CopyableContent content=\"source markdown\">Visible replacement</CopyableContent>);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => expect(write).toHaveBeenCalled());\n const item = write.mock.calls[0][0][0] as unknown as ClipboardItem;\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe('source markdown');\n });\n\n it('shows a checkmark after a successful copy', async () => {\n vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n const { container } = render(<CopyableContent content=\"source\" />);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => {\n expect(container.querySelector('[data-icons=\"fa fa-check\"]')).toBeInTheDocument();\n });\n });\n\n it('offers sharing actions', () => {\n const { container } = render(<CopyableContent content=\"source\" />);\n\n expect(screen.getByRole('button', { name: 'Teilen' })).toBeInTheDocument();\n expect(container.querySelector('[data-copy-action=\"false\"]')).toBeInTheDocument();\n expect(container.querySelector('[data-calling-code-action=\"false\"]')).toBeInTheDocument();\n });\n\n it('supports collapsed content', () => {\n render(\n <CopyableContent\n collapsedHeight={100}\n content={Array(20).fill('Long content').join('\\n\\n')}\n />,\n );\n\n expect(screen.getByRole('button', { name: 'Mehr anzeigen' })).toBeInTheDocument();\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"CopyableContent.test.js","names":["fireEvent","render","screen","waitFor","React","describe","expect","it","vi","CopyableContent","mock","Textstring","textstring","fallback","TextstringProvider","children","ttsToITextString","useTextstringValue","resizeObserverCallbacks","ResizeObserverMock","constructor","callback","push","disconnect","observe","unobserve","stubGlobal","triggerResize","height","forEach","contentRect","default","icons","createElement","join","shouldShowCallingCodeAction","shouldShowCopyAction","importOriginal","createDialog","fn","open","readBlob","blob","Promise","resolve","reject","reader","FileReader","onerror","error","onload","result","readAsText","content","getByRole","name","toBeInTheDocument","toHaveAttribute","document","querySelector","not","write","spyOn","navigator","clipboard","mockResolvedValue","click","toHaveBeenCalled","item","calls","getType","resolves","toBe","container","collapsedHeight","Array","fill"],"sources":["../../../../src/components/copyable-content/CopyableContent.test.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-call */\nimport { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { describe, expect, it, vi } from 'vitest';\nimport CopyableContent from './CopyableContent';\n\nvi.mock('@chayns-components/textstring', () => ({\n Textstring: ({ textstring }: { textstring: { fallback: string } }) => textstring.fallback,\n TextstringProvider: ({ children }: { children: React.ReactNode }) => children,\n ttsToITextString: (textstring: { fallback: string }) => textstring,\n useTextstringValue: ({ textstring }: { textstring: { fallback: string } }) =>\n textstring.fallback,\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\nvi.mock('../icon/Icon', () => ({\n default: ({ icons }: { icons: string[] }) => <span data-icons={icons.join(' ')} />,\n}));\n\nvi.mock('../sharing-context-menu/SharingContextMenu', () => ({\n default: ({\n children,\n shouldShowCallingCodeAction,\n shouldShowCopyAction,\n }: {\n children: React.ReactNode;\n shouldShowCallingCodeAction?: boolean;\n shouldShowCopyAction?: boolean;\n }) => (\n <div\n data-calling-code-action={shouldShowCallingCodeAction}\n data-copy-action={shouldShowCopyAction}\n >\n {children}\n </div>\n ),\n}));\n\nvi.mock('chayns-api', async (importOriginal) => ({\n ...(await importOriginal<typeof import('chayns-api')>()),\n createDialog: vi.fn(() => ({ open: vi.fn() })),\n}));\n\nconst readBlob = (blob: Blob) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error);\n reader.onload = () => resolve(reader.result as string);\n reader.readAsText(blob);\n });\n\ndescribe('CopyableContent', () => {\n it('renders formatted markdown without active input HTML', () => {\n render(\n <CopyableContent\n content={\n '# Heading\\n\\n- Entry\\n\\n[Link](https://example.com)\\n<script onload=\"x\">bad</script>'\n }\n />,\n );\n\n expect(screen.getByRole('heading', { name: 'Heading' })).toBeInTheDocument();\n expect(screen.getByRole('link', { name: 'Link' })).toHaveAttribute(\n 'href',\n 'https://example.com',\n );\n expect(document.querySelector('script')).not.toBeInTheDocument();\n expect(document.querySelector('[onload]')).not.toBeInTheDocument();\n });\n\n it('copies content instead of custom children', async () => {\n const write = vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n render(<CopyableContent content=\"source markdown\">Visible replacement</CopyableContent>);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => expect(write).toHaveBeenCalled());\n const item = write.mock.calls[0][0][0] as unknown as ClipboardItem;\n await expect(readBlob(await item.getType('text/plain'))).resolves.toBe('source markdown');\n });\n\n it('shows a checkmark after a successful copy', async () => {\n vi.spyOn(navigator.clipboard, 'write').mockResolvedValue();\n const { container } = render(<CopyableContent content=\"source\" />);\n\n fireEvent.click(screen.getByRole('button', { name: 'Kopieren' }));\n\n await waitFor(() => {\n expect(container.querySelector('[data-icons=\"fa fa-check\"]')).toBeInTheDocument();\n });\n });\n\n it('offers sharing actions', () => {\n const { container } = render(<CopyableContent content=\"source\" />);\n\n expect(screen.getByRole('button', { name: 'Teilen' })).toBeInTheDocument();\n expect(container.querySelector('[data-copy-action=\"false\"]')).toBeInTheDocument();\n expect(container.querySelector('[data-calling-code-action=\"false\"]')).toBeInTheDocument();\n });\n\n it('supports collapsed content', async () => {\n render(\n <CopyableContent\n collapsedHeight={100}\n content={Array(20).fill('Long content').join('\\n\\n')}\n />,\n );\n\n triggerResize(240);\n\n await waitFor(() => {\n expect(screen.getByRole('button', { name: 'Mehr' })).toBeInTheDocument();\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,57 +1,69 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { ClampPosition } from '../../types/truncation';
|
|
3
|
-
import { debounce } from '../../utils/debounce';
|
|
4
|
-
import { truncateElement } from '../../utils/truncation';
|
|
5
|
-
import { StyledMotionTruncationContent, StyledTruncation, StyledTruncationClamp, StyledTruncationClampFocusWrapper, StyledTruncationClampWrapper, StyledTruncationPseudoContent } from './Truncation.styles';
|
|
6
1
|
import { Textstring, TextstringProvider, ttsToITextString } from '@chayns-components/textstring';
|
|
7
|
-
import
|
|
2
|
+
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
8
3
|
import { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';
|
|
4
|
+
import textStrings from '../../constants/textStrings';
|
|
5
|
+
import { ClampPosition } from '../../types/truncation';
|
|
6
|
+
import { StyledMotionTruncationContent, StyledTruncation, StyledTruncationClamp, StyledTruncationClampFocusWrapper, StyledTruncationClampWrapper, StyledTruncationContent } from './Truncation.styles';
|
|
9
7
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
10
8
|
const Truncation = ({
|
|
11
9
|
collapsedHeight = 150,
|
|
12
10
|
clampPosition = ClampPosition.Right,
|
|
13
11
|
isOpen,
|
|
14
|
-
moreLabel,
|
|
15
12
|
lessLabel,
|
|
13
|
+
moreLabel,
|
|
16
14
|
onChange,
|
|
17
15
|
children,
|
|
18
16
|
shouldEnableKeyboardHighlighting
|
|
19
17
|
}) => {
|
|
20
18
|
const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(shouldEnableKeyboardHighlighting);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const [
|
|
24
|
-
const [
|
|
25
|
-
const [shouldShowCollapsedElement, setShouldShowCollapsedElement] = useState(true);
|
|
26
|
-
const [hasSizeChanged, setHasSizeChanged] = useState(false);
|
|
27
|
-
const [initialRender, setInitialRender] = useState(true);
|
|
28
|
-
const [shouldSkipChangeCheck, setShouldSkipChangeCheck] = useState(false);
|
|
29
|
-
const [originalSmallHeight, setOriginalSmallHeight] = useState(0);
|
|
30
|
-
const [originalBigHeight, setOriginalBigHeight] = useState(0);
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
setInitialRender(false);
|
|
33
|
-
}, []);
|
|
34
|
-
const parentRef = useRef(null);
|
|
35
|
-
const pseudoChildrenRef = useRef(null);
|
|
36
|
-
const childrenRef = useRef(null);
|
|
37
|
-
const originalChildrenRef = useRef(null);
|
|
38
|
-
const hasCollapsed = useRef(false);
|
|
39
|
-
const isAnimating = useRef(false);
|
|
40
|
-
const hasSizeRecentlyChanged = useRef(false);
|
|
41
|
-
const canResetSizeChanged = useRef(true);
|
|
19
|
+
const contentRef = useRef(null);
|
|
20
|
+
const pendingObservedHeight = useRef(0);
|
|
21
|
+
const [internalIsOpen, setInternalIsOpen] = useState(Boolean(isOpen));
|
|
22
|
+
const [contentHeight, setContentHeight] = useState(0);
|
|
42
23
|
useEffect(() => {
|
|
43
24
|
if (typeof isOpen === 'boolean') {
|
|
44
25
|
setInternalIsOpen(isOpen);
|
|
45
|
-
setShowClamp(!isOpen);
|
|
46
26
|
}
|
|
47
27
|
}, [isOpen]);
|
|
48
|
-
|
|
49
|
-
|
|
28
|
+
useIsomorphicLayoutEffect(() => {
|
|
29
|
+
if (!contentRef.current) {
|
|
30
|
+
return () => {};
|
|
31
|
+
}
|
|
32
|
+
let frame;
|
|
33
|
+
const updateContentHeight = entries => {
|
|
34
|
+
pendingObservedHeight.current = Math.max(pendingObservedHeight.current, entries?.[0]?.contentRect.height ?? 0);
|
|
35
|
+
if (frame !== undefined) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
frame = window.requestAnimationFrame(() => {
|
|
39
|
+
frame = undefined;
|
|
40
|
+
if (!contentRef.current) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
setContentHeight(Math.max(pendingObservedHeight.current, contentRef.current.scrollHeight, contentRef.current.getBoundingClientRect().height));
|
|
44
|
+
pendingObservedHeight.current = 0;
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const resizeObserver = new ResizeObserver(entries => updateContentHeight(entries));
|
|
48
|
+
const mutationObserver = new MutationObserver(() => updateContentHeight());
|
|
49
|
+
resizeObserver.observe(contentRef.current);
|
|
50
|
+
mutationObserver.observe(contentRef.current, {
|
|
51
|
+
characterData: true,
|
|
52
|
+
childList: true,
|
|
53
|
+
subtree: true
|
|
54
|
+
});
|
|
55
|
+
updateContentHeight();
|
|
56
|
+
return () => {
|
|
57
|
+
resizeObserver.disconnect();
|
|
58
|
+
mutationObserver.disconnect();
|
|
59
|
+
if (frame !== undefined) {
|
|
60
|
+
window.cancelAnimationFrame(frame);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}, [children]);
|
|
50
64
|
const handleClampClick = useCallback(event => {
|
|
51
65
|
setInternalIsOpen(current => {
|
|
52
|
-
|
|
53
|
-
onChange(event, !current);
|
|
54
|
-
}
|
|
66
|
+
onChange?.(event, !current);
|
|
55
67
|
return !current;
|
|
56
68
|
});
|
|
57
69
|
}, [onChange]);
|
|
@@ -61,129 +73,29 @@ const Truncation = ({
|
|
|
61
73
|
event.currentTarget.click();
|
|
62
74
|
}
|
|
63
75
|
}, []);
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
if (children) {
|
|
66
|
-
setShouldSkipChangeCheck(true);
|
|
67
|
-
window.setTimeout(() => {
|
|
68
|
-
setShouldSkipChangeCheck(false);
|
|
69
|
-
}, 200);
|
|
70
|
-
}
|
|
71
|
-
}, [children]);
|
|
72
|
-
const handleAnimationEnd = useCallback(() => {
|
|
73
|
-
hasCollapsed.current = true;
|
|
74
|
-
isAnimating.current = false;
|
|
75
|
-
if (canResetSizeChanged.current) {
|
|
76
|
-
setHasSizeChanged(false);
|
|
77
|
-
canResetSizeChanged.current = false;
|
|
78
|
-
}
|
|
79
|
-
window.setTimeout(() => {
|
|
80
|
-
hasSizeRecentlyChanged.current = false;
|
|
81
|
-
}, 10);
|
|
82
|
-
setShouldShowCollapsedElement(!internalIsOpen);
|
|
83
|
-
window.setTimeout(() => {
|
|
84
|
-
hasCollapsed.current = false;
|
|
85
|
-
}, 30);
|
|
86
|
-
}, [internalIsOpen]);
|
|
87
|
-
useEffect(() => {
|
|
88
|
-
if (!pseudoChildrenRef.current) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
setOriginalHeight(pseudoChildrenRef.current.offsetHeight);
|
|
92
|
-
setOriginalBigHeight(pseudoChildrenRef.current.offsetHeight);
|
|
93
|
-
truncateElement(pseudoChildrenRef.current, collapsedHeight);
|
|
94
|
-
setNewCollapsedHeight(pseudoChildrenRef.current.offsetHeight);
|
|
95
|
-
setOriginalSmallHeight(pseudoChildrenRef.current.offsetHeight);
|
|
96
|
-
}, [collapsedHeight, pseudoChildrenRef, children]);
|
|
97
|
-
|
|
98
|
-
// Checks if the clamp should be shown
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
if (pseudoChildrenRef.current && (!hasSizeChanged || shouldSkipChangeCheck) && !initialRender) {
|
|
101
|
-
setShowClamp(originalHeight > newCollapsedHeight);
|
|
102
|
-
}
|
|
103
|
-
}, [shouldSkipChangeCheck, collapsedHeight, hasSizeChanged, initialRender, newCollapsedHeight, originalHeight, children]);
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
if (childrenRef.current && pseudoChildrenRef.current && originalChildrenRef.current) {
|
|
106
|
-
while (childrenRef.current.firstChild) {
|
|
107
|
-
childrenRef.current.removeChild(childrenRef.current.firstChild);
|
|
108
|
-
}
|
|
109
|
-
childrenRef.current.appendChild(shouldShowCollapsedElement && !internalIsOpen ? pseudoChildrenRef.current : originalChildrenRef.current);
|
|
110
|
-
parentRef.current?.appendChild(shouldShowCollapsedElement && !internalIsOpen ? originalChildrenRef.current : pseudoChildrenRef.current);
|
|
111
|
-
childrenRef.current.children[0].style.visibility = 'visible';
|
|
112
|
-
}
|
|
113
|
-
}, [children, internalIsOpen, shouldShowCollapsedElement]);
|
|
114
|
-
useIsomorphicLayoutEffect(() => {
|
|
115
|
-
if (originalChildrenRef.current) {
|
|
116
|
-
const resizeObserver = new ResizeObserver(entries => {
|
|
117
|
-
if (entries && entries[0]) {
|
|
118
|
-
const observedHeight = entries[0].contentRect.height;
|
|
119
|
-
setOriginalHeight(observedHeight < originalBigHeight ? originalBigHeight : observedHeight);
|
|
120
|
-
if (!hasCollapsed.current && !isAnimating.current && !hasSizeRecentlyChanged.current) {
|
|
121
|
-
void debounce(() => {
|
|
122
|
-
canResetSizeChanged.current = true;
|
|
123
|
-
}, 250)();
|
|
124
|
-
setHasSizeChanged(true);
|
|
125
|
-
hasSizeRecentlyChanged.current = true;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
resizeObserver.observe(originalChildrenRef.current);
|
|
130
|
-
return () => {
|
|
131
|
-
resizeObserver.disconnect();
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
return () => {};
|
|
135
|
-
}, [originalBigHeight, children]);
|
|
136
|
-
useIsomorphicLayoutEffect(() => {
|
|
137
|
-
if (pseudoChildrenRef.current) {
|
|
138
|
-
const resizeObserver = new ResizeObserver(entries => {
|
|
139
|
-
if (entries && entries[0]) {
|
|
140
|
-
const observedHeight = entries[0].contentRect.height;
|
|
141
|
-
setNewCollapsedHeight(observedHeight < originalSmallHeight ? originalSmallHeight : observedHeight);
|
|
142
|
-
if (!hasCollapsed.current && !isAnimating.current && !hasSizeRecentlyChanged.current) {
|
|
143
|
-
void debounce(() => {
|
|
144
|
-
canResetSizeChanged.current = true;
|
|
145
|
-
}, 250)();
|
|
146
|
-
setHasSizeChanged(true);
|
|
147
|
-
hasSizeRecentlyChanged.current = true;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
resizeObserver.observe(pseudoChildrenRef.current);
|
|
152
|
-
return () => {
|
|
153
|
-
resizeObserver.disconnect();
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
return () => {};
|
|
157
|
-
}, [originalSmallHeight, children]);
|
|
158
|
-
const ts = textStrings.components.truncation;
|
|
159
76
|
const internalMoreLabel = moreLabel ?? /*#__PURE__*/React.createElement(Textstring, {
|
|
160
|
-
textstring: ttsToITextString(
|
|
77
|
+
textstring: ttsToITextString(textStrings.components.truncation.more)
|
|
161
78
|
});
|
|
162
79
|
const internalLessLabel = lessLabel ?? /*#__PURE__*/React.createElement(Textstring, {
|
|
163
|
-
textstring: ttsToITextString(
|
|
80
|
+
textstring: ttsToITextString(textStrings.components.truncation.less)
|
|
164
81
|
});
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
},
|
|
171
|
-
ref: originalChildrenRef
|
|
172
|
-
}, children), /*#__PURE__*/React.createElement(StyledMotionTruncationContent, {
|
|
82
|
+
const hasOverflow = contentHeight > collapsedHeight;
|
|
83
|
+
const collapsedContentHeight = Math.min(contentHeight || collapsedHeight, collapsedHeight);
|
|
84
|
+
const targetHeight = internalIsOpen ? contentHeight || collapsedHeight : collapsedContentHeight;
|
|
85
|
+
return /*#__PURE__*/React.createElement(StyledTruncation, {
|
|
86
|
+
className: "beta-chayns-truncation"
|
|
87
|
+
}, /*#__PURE__*/React.createElement(StyledMotionTruncationContent, {
|
|
173
88
|
animate: {
|
|
174
|
-
height:
|
|
89
|
+
height: targetHeight
|
|
175
90
|
},
|
|
176
91
|
initial: false,
|
|
177
92
|
transition: {
|
|
178
93
|
type: 'tween',
|
|
179
|
-
duration:
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
},
|
|
185
|
-
ref: childrenRef
|
|
186
|
-
}), showClamp && /*#__PURE__*/React.createElement(StyledTruncationClampWrapper, {
|
|
94
|
+
duration: 0.2
|
|
95
|
+
}
|
|
96
|
+
}, /*#__PURE__*/React.createElement(StyledTruncationContent, {
|
|
97
|
+
ref: contentRef
|
|
98
|
+
}, children)), hasOverflow && /*#__PURE__*/React.createElement(StyledTruncationClampWrapper, {
|
|
187
99
|
$position: clampPosition
|
|
188
100
|
}, /*#__PURE__*/React.createElement(TextstringProvider, {
|
|
189
101
|
libraryName: "@chayns-components-core"
|
|
@@ -194,7 +106,7 @@ const Truncation = ({
|
|
|
194
106
|
onKeyDown: handleClampKeyDown,
|
|
195
107
|
role: "button",
|
|
196
108
|
tabIndex: 0
|
|
197
|
-
}, internalIsOpen ? internalLessLabel : internalMoreLabel)))))
|
|
109
|
+
}, internalIsOpen ? internalLessLabel : internalMoreLabel)))));
|
|
198
110
|
};
|
|
199
111
|
export default Truncation;
|
|
200
112
|
//# sourceMappingURL=Truncation.js.map
|