• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / ui5-webcomponents-react / 9777522743

03 Jul 2024 12:07PM CUT coverage: 81.143% (-0.04%) from 81.187%
9777522743

Pull #6015

github

web-flow
Merge 3ab9fe413 into 671cfaade
Pull Request #6015: fix(MessageViewItem): enable details view if `titleText` is overflowing

2630 of 3831 branches covered (68.65%)

11 of 15 new or added lines in 1 file covered. (73.33%)

1 existing line in 1 file now uncovered.

4742 of 5844 relevant lines covered (81.14%)

65850.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.97
/packages/main/src/components/MessageView/MessageItem.tsx
1
'use client';
2

3
import ListItemType from '@ui5/webcomponents/dist/types/ListItemType.js';
4
import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js';
5
import iconArrowRight from '@ui5/webcomponents-icons/dist/slim-arrow-right.js';
6
import { useStylesheet } from '@ui5/webcomponents-react-base';
7
import { clsx } from 'clsx';
8
import type { ReactNode } from 'react';
9
import { Children, forwardRef, useContext, useEffect, useRef, useState } from 'react';
10
import { FlexBoxAlignItems, FlexBoxDirection } from '../../enums/index.js';
11
import { MessageViewContext } from '../../internal/MessageViewContext.js';
12
import type { CommonProps } from '../../types/index.js';
13
import { Icon } from '../../webComponents/Icon/index.js';
14
import { Label } from '../../webComponents/Label/index.js';
15
import type { ListItemCustomDomRef } from '../../webComponents/ListItemCustom/index.js';
16
import { ListItemCustom } from '../../webComponents/ListItemCustom/index.js';
17
import { FlexBox } from '../FlexBox/index.js';
18
import { classNames, styleData } from './MessageItem.module.css.js';
19
import { getIconNameForType } from './utils.js';
20

21
export interface MessageItemPropTypes extends CommonProps {
22
  /**
23
   * Specifies the title of the message
24
   *
25
   * __Note:__ Although this prop accepts all HTML Elements, it is strongly recommended that you only use text or `Link` in order to preserve the intended design.
26
   */
27
  titleText: ReactNode;
28

29
  /**
30
   * Specifies the subtitle of the message
31
   *
32
   * __Note:__ Although this prop accepts all HTML Elements, it is strongly recommended that you only use text in order to preserve the intended design.
33
   */
34
  subtitleText?: ReactNode;
35

36
  /**
37
   * Defines the number of messages for a given message type.
38
   */
39
  counter?: number;
40

41
  /**
42
   * Specifies the type of the message
43
   */
44
  type?: ValueState | keyof typeof ValueState;
45

46
  /**
47
   * Name of a message group the current item belongs to.
48
   */
49
  groupName?: string;
50

51
  /**
52
   * Specifies detailed description of the message
53
   */
54
  children?: ReactNode | ReactNode[];
55
}
56

57
/**
58
 * A component used to hold different types of system messages inside the `MessageView` component.
59
 */
60
const MessageItem = forwardRef<ListItemCustomDomRef, MessageItemPropTypes>((props, ref) => {
398✔
61
  const { titleText, subtitleText, counter, type = ValueState.Negative, children, className, ...rest } = props;
277!
62
  const [isTitleTextOverflowing, setIsTitleTextIsOverflowing] = useState(false);
277✔
63
  const titleTextRef = useRef<HTMLSpanElement>(null);
277✔
64
  const hasDetails = !!(children || isTitleTextOverflowing);
277!
65

66
  useStylesheet(styleData, MessageItem.displayName);
277✔
67

68
  const { selectMessage } = useContext(MessageViewContext);
277✔
69

70
  const listItemClasses = clsx(
277✔
71
    classNames.listItem,
72
    Reflect.get(classNames, `type${type}`),
73
    className,
74
    subtitleText && classNames.withSubtitle
281✔
75
  );
76

77
  const messageClasses = clsx(classNames.message, hasDetails && classNames.withChildren);
277✔
78

79
  const handleListItemClick = (e) => {
277✔
80
    if (hasDetails) {
10✔
81
      selectMessage(props);
10✔
82
      if (typeof rest.onClick === 'function') {
10!
83
        rest.onClick(e);
×
84
      }
85
    }
86
  };
87

88
  const handleKeyDown = (e) => {
277✔
89
    if (typeof rest.onKeyDown === 'function') {
×
90
      rest.onKeyDown(e);
×
91
    }
92
    if (e.code === 'Enter') {
×
93
      handleListItemClick(e);
×
94
    }
95
  };
96

97
  const hasChildren = Children.count(children);
277✔
98
  useEffect(() => {
277✔
99
    const titleTextObserver = new ResizeObserver(([titleTextSpan]) => {
156✔
NEW
100
      if (titleTextSpan.target.scrollWidth > titleTextSpan.target.clientWidth) {
×
NEW
101
        setIsTitleTextIsOverflowing(true);
×
102
      } else {
NEW
103
        setIsTitleTextIsOverflowing(false);
×
104
      }
105
    });
106
    if (!hasChildren && titleTextRef.current) {
156!
NEW
107
      titleTextObserver.observe(titleTextRef.current);
×
108
    }
109
    return () => {
156✔
110
      titleTextObserver.disconnect();
144✔
111
    };
112
  }, [hasChildren]);
113

114
  return (
277✔
115
    <ListItemCustom
116
      onClick={handleListItemClick}
117
      onKeyDown={handleKeyDown}
118
      data-title={titleText}
119
      data-type={type}
120
      type={hasDetails ? ListItemType.Active : ListItemType.Inactive}
277!
121
      {...rest}
122
      className={listItemClasses}
123
      ref={ref}
124
    >
125
      <FlexBox alignItems={FlexBoxAlignItems.Center} className={messageClasses}>
126
        <div className={classNames.iconContainer}>
127
          <Icon name={getIconNameForType(type as ValueState)} className={classNames.icon} />
128
        </div>
129
        <FlexBox
130
          direction={FlexBoxDirection.Column}
131
          style={{ flex: 'auto', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}
132
        >
133
          {titleText && (
554✔
134
            <span className={classNames.title} ref={titleTextRef}>
135
              {titleText}
136
            </span>
137
          )}
138
          {titleText && subtitleText && <Label className={classNames.subtitle}>{subtitleText}</Label>}
558✔
139
        </FlexBox>
140
        {counter != null && <span className={classNames.counter}>{counter}</span>}
281✔
141
        {hasDetails && <Icon className={classNames.navigation} name={iconArrowRight} />}
554✔
142
      </FlexBox>
143
    </ListItemCustom>
144
  );
145
});
146

147
MessageItem.displayName = 'MessageItem';
398✔
148

149
export { MessageItem };
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc