|
1 |
| -import { FC, ReactNode, useRef, useState } from 'react'; |
| 1 | +import { forwardRef, ReactNode, useRef, useState } from 'react'; |
2 | 2 |
|
3 | 3 | import { Typography } from '@equinor/eds-core-react';
|
4 | 4 | import {
|
@@ -26,6 +26,7 @@ const Container = styled.div`
|
26 | 26 | border: 1px solid ${colors.ui.background__heavy.rgba};
|
27 | 27 | border-radius: ${shape.corners.borderRadius};
|
28 | 28 | min-width: 800px;
|
| 29 | + width: 100%; |
29 | 30 | overflow: hidden;
|
30 | 31 | > h4 {
|
31 | 32 | margin-top: ${spacings.large};
|
@@ -53,80 +54,97 @@ export type ReleaseNoteProps = {
|
53 | 54 | startExpanded?: boolean;
|
54 | 55 | } & ReleaseNoteDto;
|
55 | 56 |
|
56 |
| -export const ReleaseNote: FC<ReleaseNoteProps> = ({ |
57 |
| - applicationName, |
58 |
| - releaseDate, |
59 |
| - createdDate, |
60 |
| - tags, |
61 |
| - version, |
62 |
| - title, |
63 |
| - body, |
64 |
| - actionMenu, |
65 |
| - startExpanded = false, |
66 |
| -}) => { |
67 |
| - const usingDate = usingReleaseNoteDate({ releaseDate, createdDate }); |
68 |
| - const [richTextWrapper, setRichTextWrapper] = useState<HTMLDivElement | null>( |
69 |
| - null |
70 |
| - ); |
71 |
| - const initialHeight = useRef( |
72 |
| - startExpanded ? 'auto' : RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT |
73 |
| - ); |
74 |
| - const [expanded, setExpanded] = useState(startExpanded); |
75 |
| - const needsExpand = |
76 |
| - (richTextWrapper?.firstElementChild && |
77 |
| - richTextWrapper.firstElementChild.clientHeight > |
78 |
| - RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT) ?? |
79 |
| - true; |
| 57 | +export const ReleaseNote = forwardRef<HTMLDivElement, ReleaseNoteProps>( |
| 58 | + ( |
| 59 | + { |
| 60 | + applicationName, |
| 61 | + releaseDate, |
| 62 | + createdDate, |
| 63 | + tags, |
| 64 | + version, |
| 65 | + title, |
| 66 | + body, |
| 67 | + actionMenu, |
| 68 | + startExpanded = false, |
| 69 | + }, |
| 70 | + ref |
| 71 | + ) => { |
| 72 | + const usingDate = usingReleaseNoteDate({ releaseDate, createdDate }); |
| 73 | + const initialHeight = useRef( |
| 74 | + startExpanded ? 'auto' : RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT |
| 75 | + ); |
| 76 | + const [expanded, setExpanded] = useState(startExpanded); |
| 77 | + const [needsShowMore, setNeedsShowMore] = useState(false); |
| 78 | + const resizeObserver = useRef( |
| 79 | + new ResizeObserver((entries) => { |
| 80 | + if ( |
| 81 | + entries.at(0) && |
| 82 | + entries[0].target.scrollHeight > |
| 83 | + RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT |
| 84 | + ) { |
| 85 | + setNeedsShowMore(true); |
| 86 | + } |
| 87 | + }) |
| 88 | + ); |
80 | 89 |
|
81 |
| - const handleOnToggleExpand = () => { |
82 |
| - setExpanded((prev) => !prev); |
83 |
| - if (initialHeight.current === 'auto') { |
84 |
| - initialHeight.current = RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT; |
85 |
| - } |
86 |
| - }; |
| 90 | + const handleOnToggleExpand = () => { |
| 91 | + setExpanded((prev) => !prev); |
| 92 | + if (initialHeight.current === 'auto') { |
| 93 | + initialHeight.current = RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT; |
| 94 | + } |
| 95 | + }; |
87 | 96 |
|
88 |
| - return ( |
89 |
| - <Container> |
90 |
| - <Header> |
91 |
| - <HeaderLeft> |
92 |
| - <Typography |
93 |
| - variant="caption" |
94 |
| - color={colors.text.static_icons__secondary.rgba} |
95 |
| - > |
96 |
| - {applicationName} |
97 |
| - </Typography> |
98 |
| - <Typography |
99 |
| - variant="overline" |
100 |
| - color={colors.text.static_icons__tertiary.rgba} |
101 |
| - > |
102 |
| - {formatRelativeDateTime(usingDate)} |
103 |
| - {version ? ` ・ ${version}` : ''} ・ {timeToRead(body)} |
104 |
| - </Typography> |
105 |
| - </HeaderLeft> |
106 |
| - <MetaTags tags={tags}>{actionMenu}</MetaTags> |
107 |
| - </Header> |
108 |
| - <Typography variant="h4">{title}</Typography> |
109 |
| - <motion.div |
110 |
| - ref={setRichTextWrapper} |
111 |
| - initial={{ |
112 |
| - height: initialHeight.current, |
113 |
| - }} |
114 |
| - animate={{ |
115 |
| - height: expanded ? 'auto' : RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT, |
116 |
| - }} |
117 |
| - > |
118 |
| - <RichTextDisplay |
119 |
| - value={body} |
120 |
| - onImageRead={ReleaseNotesService.getReleaseNoteImage} |
121 |
| - padding="none" |
122 |
| - /> |
123 |
| - </motion.div> |
124 |
| - {needsExpand && ( |
125 |
| - <ToggleExpanded |
126 |
| - expanded={expanded} |
127 |
| - onToggleExpanded={handleOnToggleExpand} |
128 |
| - /> |
129 |
| - )} |
130 |
| - </Container> |
131 |
| - ); |
132 |
| -}; |
| 97 | + const handleOnSetRef = (element: HTMLDivElement | null) => { |
| 98 | + if (element) { |
| 99 | + resizeObserver.current.observe(element); |
| 100 | + } |
| 101 | + }; |
| 102 | + |
| 103 | + return ( |
| 104 | + <Container ref={ref}> |
| 105 | + <Header> |
| 106 | + <HeaderLeft> |
| 107 | + <Typography |
| 108 | + variant="caption" |
| 109 | + color={colors.text.static_icons__secondary.rgba} |
| 110 | + > |
| 111 | + {applicationName} |
| 112 | + </Typography> |
| 113 | + <Typography |
| 114 | + variant="overline" |
| 115 | + color={colors.text.static_icons__tertiary.rgba} |
| 116 | + > |
| 117 | + {formatRelativeDateTime(usingDate)} |
| 118 | + {version ? ` ・ ${version}` : ''} ・ {timeToRead(body)} |
| 119 | + </Typography> |
| 120 | + </HeaderLeft> |
| 121 | + <MetaTags tags={tags}>{actionMenu}</MetaTags> |
| 122 | + </Header> |
| 123 | + <Typography variant="h4">{title}</Typography> |
| 124 | + <motion.div |
| 125 | + ref={handleOnSetRef} |
| 126 | + initial={{ |
| 127 | + height: initialHeight.current, |
| 128 | + }} |
| 129 | + animate={{ |
| 130 | + height: expanded ? 'auto' : RELEASE_NOTE_RICH_TEXT_COLLAPSED_HEIGHT, |
| 131 | + }} |
| 132 | + > |
| 133 | + <RichTextDisplay |
| 134 | + value={body} |
| 135 | + onImageRead={ReleaseNotesService.getReleaseNoteImage} |
| 136 | + padding="none" |
| 137 | + /> |
| 138 | + </motion.div> |
| 139 | + {needsShowMore && ( |
| 140 | + <ToggleExpanded |
| 141 | + expanded={expanded} |
| 142 | + onToggleExpanded={handleOnToggleExpand} |
| 143 | + /> |
| 144 | + )} |
| 145 | + </Container> |
| 146 | + ); |
| 147 | + } |
| 148 | +); |
| 149 | + |
| 150 | +ReleaseNote.displayName = 'ReleaseNote'; |
0 commit comments