@eccenca/gui-elements 24.4.1-featurechatcomponentscmem6775.3 → 24.4.1-featurechatcomponentscmem6775.4

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +7 -3
  2. package/dist/cjs/components/Chat/ChatArea.js +1 -1
  3. package/dist/cjs/components/Chat/ChatArea.js.map +1 -1
  4. package/dist/cjs/components/Chat/ChatContent.js +4 -16
  5. package/dist/cjs/components/Chat/ChatContent.js.map +1 -1
  6. package/dist/cjs/components/Chat/ChatContentCollapsed.js +24 -0
  7. package/dist/cjs/components/Chat/ChatContentCollapsed.js.map +1 -0
  8. package/dist/cjs/components/Chat/ChatField.js +10 -4
  9. package/dist/cjs/components/Chat/ChatField.js.map +1 -1
  10. package/dist/cjs/components/Chat/index.js +1 -0
  11. package/dist/cjs/components/Chat/index.js.map +1 -1
  12. package/dist/cjs/components/{ContentShrinker/ContentShrinker.js → TextReducer/TextReducer.js} +21 -25
  13. package/dist/cjs/components/TextReducer/TextReducer.js.map +1 -0
  14. package/dist/cjs/components/Tooltip/Tooltip.js +3 -1
  15. package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
  16. package/dist/cjs/components/index.js +1 -1
  17. package/dist/cjs/components/index.js.map +1 -1
  18. package/dist/esm/components/Chat/ChatArea.js +1 -1
  19. package/dist/esm/components/Chat/ChatArea.js.map +1 -1
  20. package/dist/esm/components/Chat/ChatContent.js +4 -32
  21. package/dist/esm/components/Chat/ChatContent.js.map +1 -1
  22. package/dist/esm/components/Chat/ChatContentCollapsed.js +45 -0
  23. package/dist/esm/components/Chat/ChatContentCollapsed.js.map +1 -0
  24. package/dist/esm/components/Chat/ChatField.js +10 -4
  25. package/dist/esm/components/Chat/ChatField.js.map +1 -1
  26. package/dist/esm/components/Chat/index.js +1 -0
  27. package/dist/esm/components/Chat/index.js.map +1 -1
  28. package/dist/esm/components/{ContentShrinker/ContentShrinker.js → TextReducer/TextReducer.js} +20 -23
  29. package/dist/esm/components/TextReducer/TextReducer.js.map +1 -0
  30. package/dist/esm/components/Tooltip/Tooltip.js +3 -1
  31. package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
  32. package/dist/esm/components/index.js +1 -1
  33. package/dist/esm/components/index.js.map +1 -1
  34. package/dist/types/components/Chat/ChatContent.d.ts +6 -18
  35. package/dist/types/components/Chat/ChatContentCollapsed.d.ts +28 -0
  36. package/dist/types/components/Chat/ChatField.d.ts +1 -1
  37. package/dist/types/components/Chat/index.d.ts +1 -0
  38. package/dist/types/components/TextReducer/TextReducer.d.ts +28 -0
  39. package/dist/types/components/index.d.ts +1 -1
  40. package/package.json +1 -1
  41. package/src/components/Chat/ChatArea.tsx +2 -2
  42. package/src/components/Chat/ChatContent.tsx +9 -40
  43. package/src/components/Chat/ChatContentCollapsed.tsx +64 -0
  44. package/src/components/Chat/ChatField.tsx +18 -5
  45. package/src/components/Chat/index.ts +1 -0
  46. package/src/components/Chat/stories/ChatArea.stories.tsx +28 -3
  47. package/src/components/Chat/stories/ChatContent.stories.tsx +3 -2
  48. package/src/components/Chat/stories/ChatContentCollapsed.stories.tsx +24 -0
  49. package/src/components/TextReducer/TextReducer.stories.tsx +47 -0
  50. package/src/components/TextReducer/TextReducer.tsx +98 -0
  51. package/src/components/Tooltip/Tooltip.test.tsx +63 -0
  52. package/src/components/Tooltip/Tooltip.tsx +3 -1
  53. package/src/components/index.ts +1 -1
  54. package/dist/cjs/components/ContentShrinker/ContentShrinker.js.map +0 -1
  55. package/dist/esm/components/ContentShrinker/ContentShrinker.js.map +0 -1
  56. package/dist/types/components/ContentShrinker/ContentShrinker.d.ts +0 -9
  57. package/src/components/ContentShrinker/ContentShrinker.stories.tsx +0 -25
  58. package/src/components/ContentShrinker/ContentShrinker.tsx +0 -59
@@ -0,0 +1,98 @@
1
+ import React from "react";
2
+ import { renderToString } from "react-dom/server";
3
+ import * as ReactIs from "react-is";
4
+
5
+ import { CLASSPREFIX as eccgui } from "../../configuration/constants";
6
+
7
+ import { OverflowText, OverflowTextProps } from "./../Typography";
8
+
9
+ export interface TextReducerProps extends Pick<React.HTMLAttributes<HTMLElement>, "children"> {
10
+ /**
11
+ * Maximum number of nodes that are used from the HTML content.
12
+ * An HTML element with multiple sub elements is count as only 1 node.
13
+ */
14
+ maxNodes?: number;
15
+ /**
16
+ * Set maximum string length of returned content.
17
+ */
18
+ maxLength?: number;
19
+ /**
20
+ * Wrap returned content automatically in a `OverflowText` component.
21
+ * This way you always will get a element returned that displays only 1 single text line.
22
+ */
23
+ useOverflowTextWrapper?: boolean;
24
+ /**
25
+ * Specify more `OverflowText` properties used when `useOverflowTextWrapper` is set to `true`.
26
+ */
27
+ overflowTextProps?: Omit<OverflowTextProps, "passDown">;
28
+ }
29
+
30
+ /**
31
+ * Component to reduce HTML markup content to simple text.
32
+ * Display can be wrapped easily in `OverflowText`.
33
+ */
34
+ export const TextReducer = ({
35
+ children,
36
+ maxNodes,
37
+ maxLength,
38
+ useOverflowTextWrapper,
39
+ overflowTextProps,
40
+ }: TextReducerProps) => {
41
+ const nodesCount = 0;
42
+
43
+ const onlyText = (children: React.ReactNode | React.ReactNode[], maxNodes?: number): string => {
44
+ if (typeof maxNodes !== "undefined" && nodesCount >= maxNodes) {
45
+ return "";
46
+ }
47
+
48
+ if (children instanceof Array) {
49
+ return children
50
+ .slice(0, maxNodes)
51
+ .map((child: React.ReactNode) => {
52
+ return onlyText(child, maxNodes);
53
+ })
54
+ .join(" ");
55
+ }
56
+
57
+ return React.Children.toArray(children)
58
+ .slice(0, maxNodes)
59
+ .map((child) => {
60
+ if (ReactIs.isFragment(child)) {
61
+ return onlyText(child.props?.children, maxNodes);
62
+ }
63
+ if (typeof child === "string") {
64
+ return child;
65
+ }
66
+ if (typeof child === "number") {
67
+ return child.toString();
68
+ }
69
+ if (ReactIs.isElement(child)) {
70
+ // for some reasons `renderToString` returns empty string if not wrappe in a `span`
71
+ return renderToString(<span>{child}</span>);
72
+ }
73
+ return "";
74
+ })
75
+ .join(" ")
76
+ .replaceAll("\n", " ");
77
+ };
78
+
79
+ const shrinkedContent = onlyText(children, maxNodes)
80
+ .replaceAll(/<[^\s][^>]*>/g, "")
81
+ .slice(0, maxLength);
82
+
83
+ return useOverflowTextWrapper ? (
84
+ <OverflowText
85
+ {...overflowTextProps}
86
+ className={
87
+ `${eccgui}-textreducer` +
88
+ (overflowTextProps && overflowTextProps.className ? ` ${overflowTextProps.className}` : "")
89
+ }
90
+ >
91
+ {shrinkedContent}
92
+ </OverflowText>
93
+ ) : (
94
+ <>{shrinkedContent}</>
95
+ );
96
+ };
97
+
98
+ export default TextReducer;
@@ -0,0 +1,63 @@
1
+ import React from "react";
2
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
3
+
4
+ import "@testing-library/jest-dom";
5
+
6
+ import { CLASSPREFIX as eccgui } from "../../configuration/constants";
7
+
8
+ import Tooltip from "./Tooltip";
9
+ import { Default as TooltipStory } from "./Tooltip.stories";
10
+
11
+ const checkForPlaceholderClass = (container: HTMLElement, tobe: number) => {
12
+ expect(container.getElementsByClassName(`${eccgui}-tooltip__wrapper--placeholder`).length).toBe(tobe);
13
+ };
14
+
15
+ describe("Tooltip", () => {
16
+ it("should render placeholder automatically for text tooltip", () => {
17
+ const { container } = render(<Tooltip {...TooltipStory.args} content="this is a simple text tooltip" />);
18
+ checkForPlaceholderClass(container, 1);
19
+ });
20
+ it("should render no placeholder automatically for html tooltip", () => {
21
+ const { container } = render(
22
+ <Tooltip {...TooltipStory.args} content={<div>this is a simple text tooltip</div>} />
23
+ );
24
+ checkForPlaceholderClass(container, 0);
25
+ });
26
+ it("should render placeholder when `usePlaceholder===true`", () => {
27
+ const { container } = render(
28
+ <Tooltip {...TooltipStory.args} content={<div>this is a simple text tooltip</div>} usePlaceholder={true} />
29
+ );
30
+ checkForPlaceholderClass(container, 1);
31
+ });
32
+ it("should render no placeholder when `usePlaceholder===false`", () => {
33
+ const { container } = render(
34
+ <Tooltip {...TooltipStory.args} content="this is a simple text tooltip" usePlaceholder={false} />
35
+ );
36
+ checkForPlaceholderClass(container, 0);
37
+ });
38
+ it("should be displayed on first mouse hover when no placeholder is used", async () => {
39
+ const { container } = render(<Tooltip {...TooltipStory.args} usePlaceholder={false} />);
40
+ fireEvent.mouseEnter(container.getElementsByClassName(`${eccgui}-tooltip__wrapper`)[0]);
41
+ expect(await screen.findByText(TooltipStory.args.content)).toBeVisible();
42
+ });
43
+ it("should not be displayed on first mouse hover when placeholder is used but placeholder markup is swapped", async () => {
44
+ const { container } = render(<Tooltip {...TooltipStory.args} usePlaceholder={true} />);
45
+ fireEvent.mouseEnter(container.getElementsByClassName(`${eccgui}-tooltip__wrapper--placeholder`)[0]);
46
+ checkForPlaceholderClass(container, 1);
47
+ await waitFor(() => {
48
+ expect(screen.queryAllByText(TooltipStory.args.content)).toHaveLength(0);
49
+ checkForPlaceholderClass(container, 0);
50
+ });
51
+ });
52
+ it("should be displayed on two continues mouse hover when placeholder is used", async () => {
53
+ const { container } = render(<Tooltip {...TooltipStory.args} usePlaceholder={true} />);
54
+ fireEvent.mouseEnter(container.getElementsByClassName(`${eccgui}-tooltip__wrapper`)[0]);
55
+ checkForPlaceholderClass(container, 1);
56
+ await waitFor(async () => {
57
+ expect(screen.queryAllByText(TooltipStory.args.content)).toHaveLength(0);
58
+ checkForPlaceholderClass(container, 0);
59
+ fireEvent.mouseOver(container.getElementsByClassName(`${eccgui}-tooltip__wrapper`)[0]);
60
+ expect(await screen.findByText(TooltipStory.args.content)).toBeVisible();
61
+ });
62
+ });
63
+ });
@@ -199,7 +199,9 @@ export const Tooltip = ({
199
199
  targetProps={
200
200
  {
201
201
  ...otherTooltipProps.targetProps,
202
- "data-postplaceholder": `id${eventMemory.current}${searchId.current}`,
202
+ "data-postplaceholder": eventMemory.current
203
+ ? `id${eventMemory.current}${searchId.current}`
204
+ : undefined,
203
205
  } as React.HTMLProps<HTMLElement>
204
206
  }
205
207
  >
@@ -10,7 +10,7 @@ export * from "./Button/Button";
10
10
  export * from "./Card";
11
11
  export * from "./Chat";
12
12
  export * from "./Checkbox/Checkbox";
13
- export * from "./ContentShrinker/ContentShrinker";
13
+ export * from "./TextReducer/TextReducer";
14
14
  export * from "./ContextOverlay";
15
15
  export * from "./Depiction/Depiction";
16
16
  export * from "./Dialog";
@@ -1 +0,0 @@
1
- {"version":3,"file":"ContentShrinker.js","sourceRoot":"","sources":["../../../../src/components/ContentShrinker/ContentShrinker.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAA0B;AAC1B,6CAAkD;AAClD,kDAAoC;AAEpC,6DAAsE;AAEtE,6DAA0D;AAC1D,gDAAkE;AAIlE;;;GAGG;AACI,MAAM,eAAe,GAAG,CAAC,EAAoE,EAAE,EAAE;QAAxE,EAAE,SAAS,EAAE,QAAQ,OAA+C,EAA1C,kBAAkB,cAA5C,yBAA8C,CAAF;IACxE,MAAM,QAAQ,GAAG,CAAC,QAA6C,EAAU,EAAE;QACvE,IAAI,QAAQ,YAAY,KAAK,EAAE,CAAC;YAC5B,OAAO,QAAQ;iBACV,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE;gBAC5B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC,CAAC;iBACD,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,OAAO,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;aAClC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;;YACX,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,QAAQ,CAAC,MAAA,KAAK,CAAC,KAAK,0CAAE,QAAQ,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,mFAAmF;gBACnF,OAAO,IAAA,uBAAc,EAAC,4CAAO,KAAK,CAAQ,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,EAAE,CAAC;QACd,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC;aACT,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO,CACH,8BAAC,yBAAY,kBACT,SAAS,EAAE,GAAG,uBAAM,kBAAkB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IACvE,kBAAkB;QAEtB,8BAAC,mBAAQ,IAAC,YAAY,QAAC,YAAY,QAAC,eAAe,EAAE,EAAE,IAClD,QAAQ,CAAC,QAAQ,CAAC,CACZ,CACA,CAClB,CAAC;AACN,CAAC,CAAC;AAzCW,QAAA,eAAe,mBAyC1B;AAEF,kBAAe,uBAAe,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ContentShrinker.js","sourceRoot":"","sources":["../../../../src/components/ContentShrinker/ContentShrinker.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,WAAW,IAAI,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAqB,MAAM,iBAAiB,CAAC;AAIlE;;;GAGG;AACH,MAAM,CAAC,IAAM,eAAe,GAAG,UAAC,EAAoE;IAAlE,IAAA,SAAS,eAAA,EAAE,QAAQ,cAAA,EAAK,kBAAkB,cAA5C,yBAA8C,CAAF;IACxE,IAAM,QAAQ,GAAG,UAAC,QAA6C;QAC3D,IAAI,QAAQ,YAAY,KAAK,EAAE,CAAC;YAC5B,OAAO,QAAQ;iBACV,GAAG,CAAC,UAAC,KAAsB;gBACxB,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC,CAAC;iBACD,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;aAClC,GAAG,CAAC,UAAC,KAAK;;YACP,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,QAAQ,CAAC,MAAA,KAAK,CAAC,KAAK,0CAAE,QAAQ,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,mFAAmF;gBACnF,OAAO,cAAc,CAAC,kCAAO,KAAK,CAAQ,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,EAAE,CAAC;QACd,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC;aACT,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO,CACH,oBAAC,YAAY,aACT,SAAS,EAAE,UAAG,MAAM,qBAAkB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,WAAI,SAAS,CAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IACvE,kBAAkB;QAEtB,oBAAC,QAAQ,IAAC,YAAY,QAAC,YAAY,QAAC,eAAe,EAAE,EAAE,IAClD,QAAQ,CAAC,QAAQ,CAAC,CACZ,CACA,CAClB,CAAC;AACN,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,9 +0,0 @@
1
- import React from "react";
2
- import { OverflowTextProps } from "./../Typography";
3
- export type ContentShrinkerProps = Omit<OverflowTextProps, "passDown" | "useHtmlElement">;
4
- /**
5
- * Component to shrink HTML markup content to 1 single text line.
6
- * Display is based on `OverflowText`.
7
- */
8
- export declare const ContentShrinker: ({ className, children, ...otherOverflowProps }: ContentShrinkerProps) => React.JSX.Element;
9
- export default ContentShrinker;
@@ -1,25 +0,0 @@
1
- import React from "react";
2
- import { LoremIpsum } from "react-lorem-ipsum";
3
- import { Meta, StoryFn } from "@storybook/react";
4
-
5
- import { ContentShrinker, HtmlContentBlock } from "../../../index";
6
-
7
- export default {
8
- title: "Components/ContentShrinker",
9
- component: ContentShrinker,
10
- argTypes: {},
11
- } as Meta<typeof ContentShrinker>;
12
-
13
- const TemplateFull: StoryFn<typeof ContentShrinker> = (args) => <ContentShrinker {...args} />;
14
-
15
- export const Default = TemplateFull.bind({});
16
- Default.args = {
17
- children: (
18
- <>
19
- simple text child http://example.com/
20
- <HtmlContentBlock>
21
- <LoremIpsum p={10} avgSentencesPerParagraph={10} random={false} />
22
- </HtmlContentBlock>
23
- </>
24
- ),
25
- };
@@ -1,59 +0,0 @@
1
- import React from "react";
2
- import { renderToString } from "react-dom/server";
3
- import * as ReactIs from "react-is";
4
-
5
- import { CLASSPREFIX as eccgui } from "../../configuration/constants";
6
-
7
- import { Markdown } from "./../../cmem/markdown/Markdown";
8
- import { OverflowText, OverflowTextProps } from "./../Typography";
9
-
10
- export type ContentShrinkerProps = Omit<OverflowTextProps, "passDown" | "useHtmlElement">;
11
-
12
- /**
13
- * Component to shrink HTML markup content to 1 single text line.
14
- * Display is based on `OverflowText`.
15
- */
16
- export const ContentShrinker = ({ className, children, ...otherOverflowProps }: ContentShrinkerProps) => {
17
- const onlyText = (children: React.ReactNode | React.ReactNode[]): string => {
18
- if (children instanceof Array) {
19
- return children
20
- .map((child: React.ReactNode) => {
21
- return onlyText(child);
22
- })
23
- .join(" ");
24
- }
25
-
26
- return React.Children.toArray(children)
27
- .map((child) => {
28
- if (ReactIs.isFragment(child)) {
29
- return onlyText(child.props?.children);
30
- }
31
- if (typeof child === "string") {
32
- return child;
33
- }
34
- if (typeof child === "number") {
35
- return child.toString();
36
- }
37
- if (ReactIs.isElement(child)) {
38
- // for some reasons `renderToString` returns empty string if not wrappe in a `span`
39
- return renderToString(<span>{child}</span>);
40
- }
41
- return "";
42
- })
43
- .join(" ")
44
- .replaceAll("\n", " ");
45
- };
46
-
47
- return (
48
- <OverflowText
49
- className={`${eccgui}-contentshrinker` + (className ? ` ${className}` : "")}
50
- {...otherOverflowProps}
51
- >
52
- <Markdown removeMarkup inheritBlock allowedElements={[]}>
53
- {onlyText(children)}
54
- </Markdown>
55
- </OverflowText>
56
- );
57
- };
58
-
59
- export default ContentShrinker;