@apify/ui-library 1.92.1-featimprovetooltip-7e1224.86 → 1.93.1-featimprovetooltip-7e1224.59

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apify/ui-library",
3
- "version": "1.92.1-featimprovetooltip-7e1224.86+42ab7a23a31",
3
+ "version": "1.93.1-featimprovetooltip-7e1224.59+10162d57e72",
4
4
  "description": "React UI library used by apify.com",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -66,5 +66,5 @@
66
66
  "src",
67
67
  "style"
68
68
  ],
69
- "gitHead": "42ab7a23a314c6d9052bbeee53f667f127fa017f"
69
+ "gitHead": "10162d57e72870723b901e5274c5e8b1d769787f"
70
70
  }
@@ -7,6 +7,10 @@ import { Tooltip } from './tooltip.tsx';
7
7
  const Child = () => <div style={{ padding: '8px', border: '1px solid black', borderRadius: '4px' }}>Hover me</div>;
8
8
 
9
9
  const longText = 'This is a tooltip with a longer text. This is a tooltip with a longer text. This is a tooltip with a longer text.';
10
+ const longTextWithLinks = <div style={{ display: 'inline' }}>
11
+ This is a tooltip with a longer text. This is a tooltip with a longer text. This is a tooltip with a longer text and finally we have a{' '}
12
+ <a href="https://www.example.com">link</a>.
13
+ </div>;
10
14
 
11
15
  export default {
12
16
  title: 'UI-Library/Tooltip',
@@ -72,16 +76,13 @@ export const Default = (args) => {
72
76
  imageUrl='https://picsum.photos/id/1/1024'
73
77
  subtleText="This is some subtle text"
74
78
  placement={FLOATING_PLACEMENT.BOTTOM}
75
- content={longText}
79
+ content={longTextWithLinks}
76
80
  ><Child /></Tooltip>
77
81
  With everything
78
82
  </div>
79
83
  </DefaultStoryWrapper>
80
84
  );
81
85
  };
82
- Default.args = {
83
- persistent: { isOpenOverride: true },
84
- };
85
86
 
86
87
  export const Sizes = () => {
87
88
  return (<DefaultStoryWrapper>
@@ -28,15 +28,9 @@ export const TOOLTIP_SIZES = {
28
28
 
29
29
  export type TooltipSize = typeof TOOLTIP_SIZES[keyof typeof TOOLTIP_SIZES];
30
30
 
31
- interface PersistentTooltipProps {
32
- isOpenOverride?: boolean;
33
- CloseButtonComponent?: ComponentType;
34
- }
35
-
36
31
  export interface TooltipProps extends Omit<FloatingComponentBaseProps, 'isOpen' | 'size'> {
37
32
  as?: keyof JSX.IntrinsicElements | ComponentType<unknown>;
38
33
  className?: string;
39
- persistent?: PersistentTooltipProps;
40
34
  delayShow?: number;
41
35
  delayHide?: number;
42
36
  shortcuts?: string[];
@@ -70,7 +64,6 @@ const StyledFloatingComponentBase = styled(FloatingComponentBase)<{ $isDarkTheme
70
64
  export const Tooltip = ({
71
65
  as,
72
66
  className,
73
- persistent,
74
67
  delayShow = 500,
75
68
  delayHide = 50,
76
69
  shortcuts = [],
@@ -80,8 +73,7 @@ export const Tooltip = ({
80
73
  textAlign = TOOLTIP_TEXT_ALIGNS.LEFT,
81
74
  ...rest
82
75
  }: TooltipProps) => {
83
- const { uiTheme } = useSharedUiDependencies();
84
- const { isOpenOverride, CloseButtonComponent } = persistent || {};
76
+ const { uiTheme, tooltipSafeHtml } = useSharedUiDependencies();
85
77
  const [open, setOpen] = useState(false);
86
78
 
87
79
  const { refs, context } = useFloating({
@@ -100,9 +92,9 @@ export const Tooltip = ({
100
92
 
101
93
  const tooltipProps = {
102
94
  ...rest,
103
- isOpen: isOpenOverride !== undefined ? isOpenOverride : open,
95
+ isOpen: open,
104
96
  content: <TooltipContent
105
- content={rest.content}
97
+ content={tooltipSafeHtml(rest.content)}
106
98
  shortcuts={shortcuts}
107
99
  imageUrl={imageUrl}
108
100
  subtleText={subtleText}
@@ -124,7 +116,6 @@ export const Tooltip = ({
124
116
  >
125
117
  <StyledFloatingComponentBase
126
118
  {...tooltipProps}
127
- CloseButtonComponent={CloseButtonComponent}
128
119
  $isDarkTheme={uiTheme === 'DARK'}
129
120
  />
130
121
  </div>
@@ -23,7 +23,7 @@ export const ShortcutComponent = () => {
23
23
  <Shortcut>Shift</Shortcut>
24
24
  </div>
25
25
  Dark:
26
- <div style={{ display: 'flex', gap: '4px', backgroundColor: theme.colorPalette.dark.neutral700, padding: '16px' }}>
26
+ <div style={{ display: 'flex', gap: '4px', backgroundColor: theme.colorPalette.dark.neutral950, padding: '16px' }}>
27
27
  <Shortcut dark>F</Shortcut>
28
28
  <Shortcut dark>Ctrl / ⌘</Shortcut>
29
29
  <Shortcut dark>Shift</Shortcut>
@@ -25,8 +25,8 @@ const darkColors = css`
25
25
  `;
26
26
 
27
27
  const StyledShortcut = styled(Text)<{ $dark?: boolean }>`
28
- min-width: 10px; /* 20 - paddings - borders */
29
- height: 14px; /* 20 - paddings - borders */
28
+ min-width: 20px;
29
+ height: 20px;
30
30
  display: inline-flex;
31
31
  align-items: center;
32
32
  justify-content: center;
@@ -14,6 +14,7 @@ import { visit } from 'unist-util-visit';
14
14
  import { theme } from '../../design_system/theme.js';
15
15
  import { useSharedUiDependencies } from '../../ui_dependency_provider.js';
16
16
  import { Box } from '../box.js';
17
+ import { Image } from '../image.js';
17
18
  import { isUrlExternal } from '../link.js';
18
19
  import { cleanMarkdown } from '../readme_renderer/utils.js';
19
20
  import { Heading, HeadingContent, Text, TextContent } from '../text/index.js';
@@ -106,6 +107,28 @@ const getUnsupportedRehypeTagsSanitationPlugIn = (
106
107
  });
107
108
  };
108
109
 
110
+ const MarkdownImage = ({
111
+ src,
112
+ alt,
113
+ height,
114
+ width,
115
+ }: {
116
+ src?: string | null;
117
+ alt?: string;
118
+ height?: number | string;
119
+ width?: number | string;
120
+ }) => {
121
+ if (!src) return null; // If no src, do not render the image
122
+ return (
123
+ <Image
124
+ src={src || ''}
125
+ alt={alt}
126
+ height={height ? Number.parseInt(height.toString(), 10) : undefined}
127
+ width={width ? Number.parseInt(width.toString(), 10) : undefined}
128
+ />
129
+ );
130
+ };
131
+
109
132
  export const defaultRehypePlugins = [rehypeRaw];
110
133
  export const defaultRemarkPlugins = [remarkGfm];
111
134
 
@@ -128,6 +151,7 @@ const regularMarkdownSizeComponents: Components = {
128
151
  li: ({ children }) => <TextContent as='li' mt='space4'>{children}</TextContent>,
129
152
  a: ({ children, href }) => <MarkdownLink to={href}>{children}</MarkdownLink>,
130
153
  code: ({ children, inline }) => <MarkdownCode inline={inline} size='regular'>{children}</MarkdownCode>,
154
+ img: ({ src, alt, height, width }) => <MarkdownImage src={src} alt={alt} height={height} width={width} />,
131
155
  };
132
156
 
133
157
  const smallMarkdownSizeComponents: Components = {
@@ -148,6 +172,7 @@ const smallMarkdownSizeComponents: Components = {
148
172
  li: ({ children }) => <Text as='li' mt='space4'>{children}</Text>,
149
173
  a: ({ children, href }) => <MarkdownLink to={href}>{children}</MarkdownLink>,
150
174
  code: ({ children, inline }) => <MarkdownCode inline={inline} size='small'>{children}</MarkdownCode>,
175
+ img: ({ src, alt, height, width }) => <MarkdownImage src={src} alt={alt} height={height} width={width} />,
151
176
  };
152
177
 
153
178
  type MarkdownSize = 'regular' | 'small';
@@ -1,4 +1,5 @@
1
1
  import type React from 'react';
2
+ import type { ReactNode } from 'react';
2
3
  import { createContext, useContext } from 'react';
3
4
 
4
5
  import type { UiThemeOption } from './design_system/theme.js';
@@ -32,6 +33,8 @@ export interface UiDependencies {
32
33
  uiTheme?: UiThemeOption, // Optional - as we can just fallback to light theme on the web
33
34
  // TODO: Make required once we add it on the web
34
35
  generateProxyImageUrl?: (url: string, options: ImageProxyOptions) => string
36
+ // Sanitize HTML for tooltips with SafeHtml component
37
+ tooltipSafeHtml: (content: ReactNode | string) => ReactNode,
35
38
  }
36
39
 
37
40
  interface UiDependencyProviderProps {