@apify/ui-library 1.138.1 → 1.138.2-featpublictasks-2f3d3c.52
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/dist/src/components/actor_example/actor_example.utils.d.ts +17 -0
- package/dist/src/components/actor_example/actor_example.utils.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example.utils.js +41 -0
- package/dist/src/components/actor_example/actor_example.utils.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_avatar.d.ts +13 -0
- package/dist/src/components/actor_example/actor_example_avatar.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_avatar.js +34 -0
- package/dist/src/components/actor_example/actor_example_avatar.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_card.d.ts +28 -0
- package/dist/src/components/actor_example/actor_example_card.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_card.js +79 -0
- package/dist/src/components/actor_example/actor_example_card.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_preview.d.ts +28 -0
- package/dist/src/components/actor_example/actor_example_preview.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_preview.js +208 -0
- package/dist/src/components/actor_example/actor_example_preview.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_run_button.d.ts +33 -0
- package/dist/src/components/actor_example/actor_example_run_button.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_run_button.js +12 -0
- package/dist/src/components/actor_example/actor_example_run_button.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema.d.ts +20 -0
- package/dist/src/components/actor_example/actor_example_schema.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema.js +27 -0
- package/dist/src/components/actor_example/actor_example_schema.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_field.d.ts +19 -0
- package/dist/src/components/actor_example/actor_example_schema_field.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_field.js +33 -0
- package/dist/src/components/actor_example/actor_example_schema_field.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_field_badge.d.ts +9 -0
- package/dist/src/components/actor_example/actor_example_schema_field_badge.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_field_badge.js +48 -0
- package/dist/src/components/actor_example/actor_example_schema_field_badge.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_legend.d.ts +10 -0
- package/dist/src/components/actor_example/actor_example_schema_legend.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_legend.js +29 -0
- package/dist/src/components/actor_example/actor_example_schema_legend.js.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_property.d.ts +24 -0
- package/dist/src/components/actor_example/actor_example_schema_property.d.ts.map +1 -0
- package/dist/src/components/actor_example/actor_example_schema_property.js +122 -0
- package/dist/src/components/actor_example/actor_example_schema_property.js.map +1 -0
- package/dist/src/components/actor_example/index.d.ts +11 -0
- package/dist/src/components/actor_example/index.d.ts.map +1 -0
- package/dist/src/components/actor_example/index.js +11 -0
- package/dist/src/components/actor_example/index.js.map +1 -0
- package/dist/src/components/browser_window/browser_window.d.ts +20 -0
- package/dist/src/components/browser_window/browser_window.d.ts.map +1 -0
- package/dist/src/components/browser_window/browser_window.js +72 -0
- package/dist/src/components/browser_window/browser_window.js.map +1 -0
- package/dist/src/components/browser_window/index.d.ts +2 -0
- package/dist/src/components/browser_window/index.d.ts.map +1 -0
- package/dist/src/components/browser_window/index.js +2 -0
- package/dist/src/components/browser_window/index.js.map +1 -0
- package/dist/src/components/chip.d.ts.map +1 -1
- package/dist/src/components/chip.js +25 -2
- package/dist/src/components/chip.js.map +1 -1
- package/dist/src/components/collapsible_card/collapsible_card.d.ts +3 -2
- package/dist/src/components/collapsible_card/collapsible_card.d.ts.map +1 -1
- package/dist/src/components/collapsible_card/collapsible_card.js +2 -2
- package/dist/src/components/collapsible_card/collapsible_card.js.map +1 -1
- package/dist/src/components/floating/floating_component_base.d.ts +72 -1
- package/dist/src/components/floating/floating_component_base.d.ts.map +1 -1
- package/dist/src/components/floating/floating_component_base.js +66 -36
- package/dist/src/components/floating/floating_component_base.js.map +1 -1
- package/dist/src/components/floating/tooltip.d.ts +10 -3
- package/dist/src/components/floating/tooltip.d.ts.map +1 -1
- package/dist/src/components/floating/tooltip.js +24 -20
- package/dist/src/components/floating/tooltip.js.map +1 -1
- package/dist/src/components/index.d.ts +2 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +2 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/components/actor_example/actor_example.utils.ts +52 -0
- package/src/components/actor_example/actor_example_avatar.tsx +69 -0
- package/src/components/actor_example/actor_example_card.tsx +149 -0
- package/src/components/actor_example/actor_example_preview.tsx +295 -0
- package/src/components/actor_example/actor_example_run_button.tsx +61 -0
- package/src/components/actor_example/actor_example_schema.tsx +60 -0
- package/src/components/actor_example/actor_example_schema_field.tsx +87 -0
- package/src/components/actor_example/actor_example_schema_field_badge.tsx +66 -0
- package/src/components/actor_example/actor_example_schema_legend.tsx +49 -0
- package/src/components/actor_example/actor_example_schema_property.tsx +242 -0
- package/src/components/actor_example/index.ts +10 -0
- package/src/components/browser_window/browser_window.tsx +106 -0
- package/src/components/browser_window/index.ts +1 -0
- package/src/components/chip.tsx +27 -1
- package/src/components/collapsible_card/collapsible_card.tsx +6 -4
- package/src/components/floating/floating_component_base.tsx +89 -47
- package/src/components/floating/tooltip.tsx +53 -25
- package/src/components/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apify/ui-library",
|
|
3
|
-
"version": "1.138.
|
|
3
|
+
"version": "1.138.2-featpublictasks-2f3d3c.52+68e3cd48a51",
|
|
4
4
|
"description": "React UI library used by apify.com",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"type-check": "tsc --noEmit",
|
|
21
21
|
"generate-theme": "node src/codemods/generate_typograpy_tokens_files.mjs && pnpm run lint:fix",
|
|
22
22
|
"build-color-tokens": "node src/design_system/colors/build_color_tokens.js",
|
|
23
|
-
"postpublish": "
|
|
23
|
+
"postpublish": "rimraf ./dist"
|
|
24
24
|
},
|
|
25
25
|
"//": [
|
|
26
26
|
"Storybook for the components lives in a separate package ui-storybook.",
|
|
27
27
|
"It's not nice, but helps us to get around the problem of multiple react instances."
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@apify/ui-icons": "^1.38.
|
|
30
|
+
"@apify/ui-icons": "^1.38.2-featpublictasks-2f3d3c.52+68e3cd48a51",
|
|
31
31
|
"@floating-ui/react": "^0.27.19",
|
|
32
32
|
"@floating-ui/react-dom": "^2.1.8",
|
|
33
33
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"styled-components": "^6.1.19"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@apify-packages/types": "^3.353.
|
|
61
|
+
"@apify-packages/types": "^3.353.2-featpublictasks-2f3d3c.52+68e3cd48a51",
|
|
62
62
|
"@storybook/react-vite": "^10.3.5",
|
|
63
63
|
"@types/hast": "^3.0.4",
|
|
64
64
|
"@types/lodash": "^4.14.200",
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"src",
|
|
73
73
|
"style"
|
|
74
74
|
],
|
|
75
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "68e3cd48a5189a18f916ad456f1f15d2767d3382"
|
|
76
76
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { IconComponent } from '@apify/ui-icons';
|
|
2
|
+
import { AnyIcon, BooleanIcon, MenuIcon, NumberIcon, ObjectIcon, TextIcon } from '@apify/ui-icons';
|
|
3
|
+
|
|
4
|
+
import type { ActorExampleSchemaFieldType } from '@apify-packages/types';
|
|
5
|
+
|
|
6
|
+
export type ActorExampleSchemaPropertyConfig = {
|
|
7
|
+
Icon: IconComponent;
|
|
8
|
+
title: string;
|
|
9
|
+
backgroundColor: string;
|
|
10
|
+
textColor: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Per-type display config used by the schema field components (badge icon, hover tooltip,
|
|
15
|
+
* background/text colors). The `var(--actor-schema-field-*)` references are declared on the
|
|
16
|
+
* `ActorExampleSchemaFieldBadgeWrapper` styled component itself (with a dark-mode override via
|
|
17
|
+
* `html[data-theme='dark'] &`), so the vars are scoped to the badge — no globals are injected.
|
|
18
|
+
*/
|
|
19
|
+
export const actorExampleSchemaPropertyMap: Record<ActorExampleSchemaFieldType, ActorExampleSchemaPropertyConfig> = {
|
|
20
|
+
string: {
|
|
21
|
+
Icon: TextIcon,
|
|
22
|
+
title: 'Text',
|
|
23
|
+
backgroundColor: 'var(--actor-schema-field-string-background)',
|
|
24
|
+
textColor: 'var(--actor-schema-field-string-text)',
|
|
25
|
+
},
|
|
26
|
+
number: {
|
|
27
|
+
Icon: NumberIcon,
|
|
28
|
+
title: 'Number',
|
|
29
|
+
backgroundColor: 'var(--actor-schema-field-number-background)',
|
|
30
|
+
textColor: 'var(--actor-schema-field-number-text)',
|
|
31
|
+
},
|
|
32
|
+
boolean: {
|
|
33
|
+
Icon: BooleanIcon,
|
|
34
|
+
title: 'Boolean',
|
|
35
|
+
backgroundColor: 'var(--actor-schema-field-boolean-background)',
|
|
36
|
+
textColor: 'var(--actor-schema-field-boolean-text)',
|
|
37
|
+
},
|
|
38
|
+
array: {
|
|
39
|
+
Icon: MenuIcon,
|
|
40
|
+
title: 'List',
|
|
41
|
+
backgroundColor: 'var(--actor-schema-field-array-background)',
|
|
42
|
+
textColor: 'var(--actor-schema-field-array-text)',
|
|
43
|
+
},
|
|
44
|
+
object: {
|
|
45
|
+
Icon: ObjectIcon,
|
|
46
|
+
title: 'Object',
|
|
47
|
+
backgroundColor: 'var(--actor-schema-field-object-background)',
|
|
48
|
+
textColor: 'var(--actor-schema-field-object-text)',
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const actorExampleSchemaPropertyDefaultIcon = AnyIcon;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
import { useCallback, useMemo } from 'react';
|
|
4
|
+
import styled from 'styled-components';
|
|
5
|
+
|
|
6
|
+
import { useSharedUiDependencies } from '../../ui_dependency_provider.js';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_SIZE = 36;
|
|
9
|
+
|
|
10
|
+
export const actorExampleAvatarClassNames = {
|
|
11
|
+
ROOT: 'actor-example-avatar',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const ActorExampleAvatarWrapper = styled.img`
|
|
15
|
+
flex-shrink: 0;
|
|
16
|
+
object-fit: cover;
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export type ActorExampleAvatarProps = {
|
|
20
|
+
title?: string;
|
|
21
|
+
name: string;
|
|
22
|
+
pictureUrl?: string;
|
|
23
|
+
fallbackPictureUrl: string;
|
|
24
|
+
size?: number;
|
|
25
|
+
className?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const ActorExampleAvatar = ({
|
|
29
|
+
title,
|
|
30
|
+
name,
|
|
31
|
+
pictureUrl,
|
|
32
|
+
fallbackPictureUrl,
|
|
33
|
+
size = DEFAULT_SIZE,
|
|
34
|
+
className,
|
|
35
|
+
}: ActorExampleAvatarProps) => {
|
|
36
|
+
const { generateProxyImageUrl } = useSharedUiDependencies();
|
|
37
|
+
|
|
38
|
+
// Mirrors apify-web's `<Image defaultSrc=…>` behaviour: if the primary src fails to load,
|
|
39
|
+
// swap in the fallback so the `<img>` element is always present.
|
|
40
|
+
const handlePictureError = useCallback(
|
|
41
|
+
(event: React.SyntheticEvent<HTMLImageElement>) => {
|
|
42
|
+
if (!event.currentTarget.src.endsWith(fallbackPictureUrl)) {
|
|
43
|
+
// eslint-disable-next-line no-param-reassign
|
|
44
|
+
event.currentTarget.src = fallbackPictureUrl;
|
|
45
|
+
// eslint-disable-next-line no-param-reassign
|
|
46
|
+
event.currentTarget.srcset = fallbackPictureUrl;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
[fallbackPictureUrl],
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const proxyPictureUrl = useMemo(() => {
|
|
53
|
+
if (!generateProxyImageUrl || !pictureUrl) return pictureUrl;
|
|
54
|
+
return generateProxyImageUrl(pictureUrl, { resize: { height: size * 2, width: size * 2 } });
|
|
55
|
+
}, [pictureUrl, generateProxyImageUrl, size]);
|
|
56
|
+
|
|
57
|
+
const src = proxyPictureUrl || fallbackPictureUrl;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<ActorExampleAvatarWrapper
|
|
61
|
+
src={src}
|
|
62
|
+
alt={title ?? name}
|
|
63
|
+
width={size}
|
|
64
|
+
height={size}
|
|
65
|
+
className={clsx(actorExampleAvatarClassNames.ROOT, className)}
|
|
66
|
+
onError={handlePictureError}
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import { ExternalLinkIcon } from '@apify/ui-icons';
|
|
5
|
+
|
|
6
|
+
import { theme } from '../../design_system/theme.js';
|
|
7
|
+
import { Badge } from '../badge.js';
|
|
8
|
+
import { Box } from '../box.js';
|
|
9
|
+
import { Button } from '../button.js';
|
|
10
|
+
import { Heading } from '../text/index.js';
|
|
11
|
+
import { ActorExampleRunButton, ActorExampleRunButtonLightningIcon } from './actor_example_run_button.js';
|
|
12
|
+
|
|
13
|
+
export const actorExampleCardClassNames = {
|
|
14
|
+
ROOT: 'actor-example-card',
|
|
15
|
+
CONTENT: 'actor-example-card__content',
|
|
16
|
+
BADGE: 'actor-example-card__badge',
|
|
17
|
+
TITLE: 'actor-example-card__title',
|
|
18
|
+
FOOTER: 'actor-example-card__footer',
|
|
19
|
+
RUN_BUTTON: 'actor-example-card__run-button',
|
|
20
|
+
DETAIL_BUTTON: 'actor-example-card__detail-button',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const ActorExampleCardWrapper = styled(Box)`
|
|
24
|
+
min-width: 0;
|
|
25
|
+
background-color: ${theme.color.neutral.background};
|
|
26
|
+
border: 1px solid ${theme.color.neutral.border};
|
|
27
|
+
border-radius: ${theme.radius.radius12};
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
|
|
30
|
+
.${actorExampleCardClassNames.CONTENT} {
|
|
31
|
+
padding: ${theme.space.space16};
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: ${theme.space.space8};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.${actorExampleCardClassNames.BADGE} {
|
|
38
|
+
min-width: 0;
|
|
39
|
+
max-width: 100%;
|
|
40
|
+
|
|
41
|
+
span {
|
|
42
|
+
min-width: 0;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
text-overflow: ellipsis;
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.${actorExampleCardClassNames.TITLE} {
|
|
50
|
+
min-height: 7.2rem; /* 3 lines of text with line-height 2.4rem */
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
text-overflow: ellipsis;
|
|
53
|
+
display: -webkit-box;
|
|
54
|
+
-webkit-line-clamp: 3;
|
|
55
|
+
-webkit-box-orient: vertical;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.${actorExampleCardClassNames.FOOTER} {
|
|
59
|
+
padding: ${theme.space.space12} ${theme.space.space16};
|
|
60
|
+
background-color: ${theme.color.neutral.backgroundMuted};
|
|
61
|
+
display: grid;
|
|
62
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
63
|
+
gap: ${theme.space.space4};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.${actorExampleCardClassNames.RUN_BUTTON}, .${actorExampleCardClassNames.DETAIL_BUTTON} {
|
|
67
|
+
min-width: 0;
|
|
68
|
+
|
|
69
|
+
span {
|
|
70
|
+
min-width: 0;
|
|
71
|
+
overflow: hidden;
|
|
72
|
+
text-overflow: ellipsis;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
svg {
|
|
77
|
+
flex-shrink: 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
export type ActorExampleCardProps = {
|
|
83
|
+
title: string;
|
|
84
|
+
badge?: string;
|
|
85
|
+
/** Owning actor's id — flows into the run button's analytics event. */
|
|
86
|
+
actorId: string;
|
|
87
|
+
runUrl: string;
|
|
88
|
+
runLabel: string;
|
|
89
|
+
/**
|
|
90
|
+
* Tracking element id for the run button (e.g. `actorInfo.examples.run`). The card's
|
|
91
|
+
* `title` is forwarded as `cardTitle` automatically.
|
|
92
|
+
*/
|
|
93
|
+
runTrackingElement: string;
|
|
94
|
+
detailUrl?: string;
|
|
95
|
+
detailLabel: string;
|
|
96
|
+
detailOpensInNewTab?: boolean;
|
|
97
|
+
className?: string;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const ActorExampleCard = ({
|
|
101
|
+
title,
|
|
102
|
+
badge,
|
|
103
|
+
actorId,
|
|
104
|
+
runUrl,
|
|
105
|
+
runLabel,
|
|
106
|
+
runTrackingElement,
|
|
107
|
+
detailUrl,
|
|
108
|
+
detailLabel,
|
|
109
|
+
detailOpensInNewTab = true,
|
|
110
|
+
className,
|
|
111
|
+
}: ActorExampleCardProps) => (
|
|
112
|
+
<ActorExampleCardWrapper className={clsx(actorExampleCardClassNames.ROOT, className)}>
|
|
113
|
+
<Box className={actorExampleCardClassNames.CONTENT}>
|
|
114
|
+
{badge && (
|
|
115
|
+
<Badge size="extra_small" variant="primary_blue" className={actorExampleCardClassNames.BADGE}>
|
|
116
|
+
{badge}
|
|
117
|
+
</Badge>
|
|
118
|
+
)}
|
|
119
|
+
<Heading as="h2" className={actorExampleCardClassNames.TITLE}>
|
|
120
|
+
{title}
|
|
121
|
+
</Heading>
|
|
122
|
+
</Box>
|
|
123
|
+
<Box className={actorExampleCardClassNames.FOOTER}>
|
|
124
|
+
<ActorExampleRunButton
|
|
125
|
+
size="small"
|
|
126
|
+
variant="secondary"
|
|
127
|
+
actorId={actorId}
|
|
128
|
+
consoleUrl={runUrl}
|
|
129
|
+
trackingProps={{ element: runTrackingElement, cardTitle: title }}
|
|
130
|
+
className={actorExampleCardClassNames.RUN_BUTTON}
|
|
131
|
+
LeftIcon={ActorExampleRunButtonLightningIcon}
|
|
132
|
+
>
|
|
133
|
+
{runLabel}
|
|
134
|
+
</ActorExampleRunButton>
|
|
135
|
+
{detailUrl && detailLabel && (
|
|
136
|
+
<Button
|
|
137
|
+
size="small"
|
|
138
|
+
variant="tertiary"
|
|
139
|
+
to={detailUrl}
|
|
140
|
+
target={detailOpensInNewTab ? '_blank' : undefined}
|
|
141
|
+
className={actorExampleCardClassNames.DETAIL_BUTTON}
|
|
142
|
+
RightIcon={ExternalLinkIcon}
|
|
143
|
+
>
|
|
144
|
+
{detailLabel}
|
|
145
|
+
</Button>
|
|
146
|
+
)}
|
|
147
|
+
</Box>
|
|
148
|
+
</ActorExampleCardWrapper>
|
|
149
|
+
);
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import styled, { keyframes } from 'styled-components';
|
|
2
|
+
|
|
3
|
+
import { theme } from '../../design_system/theme.js';
|
|
4
|
+
import { Heading, Text } from '../text/index.js';
|
|
5
|
+
import { ActorExampleAvatar } from './actor_example_avatar.js';
|
|
6
|
+
|
|
7
|
+
const MAX_VISIBLE_FIELDS = 4;
|
|
8
|
+
const BADGE_PICTURE_SIZE = 36;
|
|
9
|
+
|
|
10
|
+
export const actorExamplePreviewClassNames = {
|
|
11
|
+
CONTAINER: 'actor-example-preview',
|
|
12
|
+
CONTENT: 'actor-example-preview__content',
|
|
13
|
+
BADGE: 'actor-example-preview__badge',
|
|
14
|
+
BADGE_PICTURE: 'actor-example-preview__badge-picture',
|
|
15
|
+
BADGE_CONTENT: 'actor-example-preview__badge-content',
|
|
16
|
+
BADGE_NAME: 'actor-example-preview__badge-name',
|
|
17
|
+
BADGE_TECHNICAL_NAME: 'actor-example-preview__badge-technical-name',
|
|
18
|
+
SCHEMA: 'actor-example-preview__schema',
|
|
19
|
+
SCHEMA_FIELD: 'actor-example-preview__schema-field',
|
|
20
|
+
SCHEMA_FIELD_NAME: 'actor-example-preview__schema-field-name',
|
|
21
|
+
SCHEMA_MORE: 'actor-example-preview__schema-more',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const VISUAL_SEPARATOR_SIZE = '0.6rem';
|
|
25
|
+
const VISUAL_CONNECTOR_LENGTH = '2.4rem';
|
|
26
|
+
|
|
27
|
+
const noisePulse = keyframes`
|
|
28
|
+
0%, 100% { opacity: 0.1; }
|
|
29
|
+
50% { opacity: 0.4; }
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const ActorExamplePreviewWrapper = styled.div<{ $noiseImageUrl: string }>`
|
|
33
|
+
@property --noise-cx {
|
|
34
|
+
syntax: '<percentage>';
|
|
35
|
+
inherits: false;
|
|
36
|
+
initial-value: 50%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@property --noise-cy {
|
|
40
|
+
syntax: '<percentage>';
|
|
41
|
+
inherits: false;
|
|
42
|
+
initial-value: 50%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
position: relative;
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
flex-shrink: 0;
|
|
51
|
+
|
|
52
|
+
&::before {
|
|
53
|
+
content: '';
|
|
54
|
+
position: absolute;
|
|
55
|
+
top: -${theme.space.space32};
|
|
56
|
+
bottom: 0;
|
|
57
|
+
inset-inline: -${theme.space.space32};
|
|
58
|
+
background-image: url(${({ $noiseImageUrl }) => $noiseImageUrl});
|
|
59
|
+
background-position: center;
|
|
60
|
+
background-repeat: repeat;
|
|
61
|
+
mask-image:
|
|
62
|
+
linear-gradient(to bottom, transparent, black 30%, black 70%, transparent),
|
|
63
|
+
linear-gradient(to right, transparent, black 30%, black 70%, transparent);
|
|
64
|
+
mask-composite: intersect;
|
|
65
|
+
-webkit-mask-image:
|
|
66
|
+
linear-gradient(to bottom, transparent, black 30%, black 70%, transparent),
|
|
67
|
+
linear-gradient(to right, transparent, black 30%, black 70%, transparent);
|
|
68
|
+
-webkit-mask-composite: destination-in;
|
|
69
|
+
animation: ${noisePulse} 4s ease-in-out infinite;
|
|
70
|
+
opacity: 0.1;
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
|
|
73
|
+
@media ${theme.device.desktop} {
|
|
74
|
+
inset: 0;
|
|
75
|
+
mask-image: radial-gradient(circle at var(--noise-cx) var(--noise-cy), black 30%, transparent 70%);
|
|
76
|
+
-webkit-mask-image: radial-gradient(circle at var(--noise-cx) var(--noise-cy), black 30%, transparent 70%);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@media (prefers-reduced-motion: reduce) {
|
|
80
|
+
animation: none;
|
|
81
|
+
mask-image: none;
|
|
82
|
+
-webkit-mask-image: none;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.${actorExamplePreviewClassNames.CONTENT} {
|
|
87
|
+
max-width: 100%;
|
|
88
|
+
display: flex;
|
|
89
|
+
gap: ${theme.space.space32};
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.${actorExamplePreviewClassNames.BADGE} {
|
|
96
|
+
width: 100%;
|
|
97
|
+
min-width: 0;
|
|
98
|
+
padding: ${theme.space.space12};
|
|
99
|
+
border: 1px solid ${theme.color.neutral.separatorSubtle};
|
|
100
|
+
border-radius: ${theme.radius.radius12};
|
|
101
|
+
background-color: ${theme.color.neutral.background};
|
|
102
|
+
display: flex;
|
|
103
|
+
gap: ${theme.space.space8};
|
|
104
|
+
align-items: center;
|
|
105
|
+
position: relative;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.${actorExamplePreviewClassNames.BADGE_PICTURE} {
|
|
109
|
+
border: 1px solid ${theme.color.neutral.separatorSubtle};
|
|
110
|
+
border-radius: ${theme.radius.radius8};
|
|
111
|
+
flex-shrink: 0;
|
|
112
|
+
object-fit: cover;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.${actorExamplePreviewClassNames.BADGE_CONTENT} {
|
|
116
|
+
min-width: 0;
|
|
117
|
+
display: flex;
|
|
118
|
+
flex-direction: column;
|
|
119
|
+
flex-grow: 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.${actorExamplePreviewClassNames.BADGE_NAME}, .${actorExamplePreviewClassNames.BADGE_TECHNICAL_NAME} {
|
|
123
|
+
text-overflow: ellipsis;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
overflow: hidden;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.${actorExamplePreviewClassNames.SCHEMA} {
|
|
129
|
+
width: 100%;
|
|
130
|
+
min-width: 0;
|
|
131
|
+
padding: ${theme.space.space8};
|
|
132
|
+
border: 1px solid ${theme.color.primary.text};
|
|
133
|
+
border-radius: ${theme.radius.radius12};
|
|
134
|
+
background-color: ${theme.color.neutral.background};
|
|
135
|
+
display: flex;
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
align-items: center;
|
|
138
|
+
gap: ${theme.space.space4};
|
|
139
|
+
position: relative;
|
|
140
|
+
|
|
141
|
+
&::before {
|
|
142
|
+
bottom: calc(100% + 0.5rem);
|
|
143
|
+
left: calc(50% - 0.5px);
|
|
144
|
+
width: 1px;
|
|
145
|
+
height: ${VISUAL_CONNECTOR_LENGTH};
|
|
146
|
+
background-color: ${theme.color.primary.text};
|
|
147
|
+
content: '';
|
|
148
|
+
display: block;
|
|
149
|
+
position: absolute;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
&::after {
|
|
153
|
+
bottom: calc(100% + 0.5rem);
|
|
154
|
+
left: calc(50% - (${VISUAL_SEPARATOR_SIZE} / 2));
|
|
155
|
+
margin: 0 auto;
|
|
156
|
+
width: ${VISUAL_SEPARATOR_SIZE};
|
|
157
|
+
height: ${VISUAL_CONNECTOR_LENGTH};
|
|
158
|
+
border-block: 1px solid ${theme.color.primary.text};
|
|
159
|
+
box-sizing: border-box;
|
|
160
|
+
content: '';
|
|
161
|
+
display: block;
|
|
162
|
+
position: absolute;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.${actorExamplePreviewClassNames.SCHEMA_FIELD} {
|
|
167
|
+
width: 100%;
|
|
168
|
+
padding: ${theme.space.space4};
|
|
169
|
+
border: 1px solid ${theme.color.primary.borderSubtle};
|
|
170
|
+
border-radius: ${theme.radius.radius6};
|
|
171
|
+
display: flex;
|
|
172
|
+
gap: ${theme.space.space8};
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.${actorExamplePreviewClassNames.SCHEMA_FIELD_NAME} {
|
|
178
|
+
min-width: 0;
|
|
179
|
+
text-overflow: ellipsis;
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
overflow: hidden;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.${actorExamplePreviewClassNames.SCHEMA_MORE} {
|
|
185
|
+
height: 2.4rem;
|
|
186
|
+
margin-top: 2rem;
|
|
187
|
+
padding: 0 ${theme.space.space8};
|
|
188
|
+
border: 1px solid ${theme.color.primary.borderSubtle};
|
|
189
|
+
border-radius: ${theme.radius.radius12};
|
|
190
|
+
background-color: ${theme.color.primary.background};
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
justify-content: center;
|
|
194
|
+
position: relative;
|
|
195
|
+
|
|
196
|
+
&::before {
|
|
197
|
+
top: calc(-1px - 1.6rem);
|
|
198
|
+
left: calc(50% - 0.5px);
|
|
199
|
+
width: 1px;
|
|
200
|
+
height: 0.8rem;
|
|
201
|
+
background-color: ${theme.color.primary.text};
|
|
202
|
+
content: '';
|
|
203
|
+
display: block;
|
|
204
|
+
position: absolute;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
`;
|
|
208
|
+
|
|
209
|
+
export type ActorExamplePreviewField = {
|
|
210
|
+
name: string;
|
|
211
|
+
title?: string;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export type ActorExamplePreviewProps = {
|
|
215
|
+
actorName: string;
|
|
216
|
+
actorTitle: string | undefined;
|
|
217
|
+
actorPictureUrl: string | undefined;
|
|
218
|
+
actorPictureFallbackUrl: string;
|
|
219
|
+
outputFields: ActorExamplePreviewField[];
|
|
220
|
+
staticWebUrl: string;
|
|
221
|
+
username: string;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const ActorExamplePreview = ({
|
|
225
|
+
actorName,
|
|
226
|
+
actorTitle,
|
|
227
|
+
actorPictureUrl,
|
|
228
|
+
actorPictureFallbackUrl,
|
|
229
|
+
outputFields,
|
|
230
|
+
staticWebUrl,
|
|
231
|
+
username,
|
|
232
|
+
}: ActorExamplePreviewProps) => {
|
|
233
|
+
const visibleFields = outputFields.slice(0, MAX_VISIBLE_FIELDS);
|
|
234
|
+
const remainingCount = Math.max(0, outputFields.length - MAX_VISIBLE_FIELDS);
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
<ActorExamplePreviewWrapper
|
|
238
|
+
className={actorExamplePreviewClassNames.CONTAINER}
|
|
239
|
+
$noiseImageUrl={`${staticWebUrl}/img/pattern/noise.svg`}
|
|
240
|
+
>
|
|
241
|
+
<div className={actorExamplePreviewClassNames.CONTENT}>
|
|
242
|
+
<div className={actorExamplePreviewClassNames.BADGE}>
|
|
243
|
+
<ActorExampleAvatar
|
|
244
|
+
title={actorTitle}
|
|
245
|
+
name={actorName}
|
|
246
|
+
pictureUrl={actorPictureUrl}
|
|
247
|
+
fallbackPictureUrl={actorPictureFallbackUrl}
|
|
248
|
+
size={BADGE_PICTURE_SIZE}
|
|
249
|
+
className={actorExamplePreviewClassNames.BADGE_PICTURE}
|
|
250
|
+
/>
|
|
251
|
+
<div className={actorExamplePreviewClassNames.BADGE_CONTENT}>
|
|
252
|
+
<Heading as="span" type="titleS" className={actorExamplePreviewClassNames.BADGE_NAME}>
|
|
253
|
+
{actorTitle ?? actorName}
|
|
254
|
+
</Heading>
|
|
255
|
+
<Text
|
|
256
|
+
as="span"
|
|
257
|
+
type="code"
|
|
258
|
+
size="small"
|
|
259
|
+
color={theme.color.neutral.textSubtle}
|
|
260
|
+
className={actorExamplePreviewClassNames.BADGE_TECHNICAL_NAME}
|
|
261
|
+
>
|
|
262
|
+
{username}/{actorName}
|
|
263
|
+
</Text>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
{visibleFields.length > 0 && (
|
|
267
|
+
<div className={actorExamplePreviewClassNames.SCHEMA}>
|
|
268
|
+
{visibleFields.map((field) => (
|
|
269
|
+
<div key={field.name} className={actorExamplePreviewClassNames.SCHEMA_FIELD}>
|
|
270
|
+
<Text
|
|
271
|
+
as="span"
|
|
272
|
+
size="small"
|
|
273
|
+
color={theme.color.neutral.text}
|
|
274
|
+
className={actorExamplePreviewClassNames.SCHEMA_FIELD_NAME}
|
|
275
|
+
>
|
|
276
|
+
{field.title ?? field.name}
|
|
277
|
+
</Text>
|
|
278
|
+
</div>
|
|
279
|
+
))}
|
|
280
|
+
{remainingCount > 0 && (
|
|
281
|
+
<Text
|
|
282
|
+
as="span"
|
|
283
|
+
size="small"
|
|
284
|
+
color={theme.color.primary.text}
|
|
285
|
+
className={actorExamplePreviewClassNames.SCHEMA_MORE}
|
|
286
|
+
>
|
|
287
|
+
+{remainingCount} {remainingCount === 1 ? 'field' : 'fields'}
|
|
288
|
+
</Text>
|
|
289
|
+
)}
|
|
290
|
+
</div>
|
|
291
|
+
)}
|
|
292
|
+
</div>
|
|
293
|
+
</ActorExamplePreviewWrapper>
|
|
294
|
+
);
|
|
295
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
|
|
3
|
+
import { type IconProps, LightningIcon } from '@apify/ui-icons';
|
|
4
|
+
|
|
5
|
+
import { theme } from '../../design_system/theme.js';
|
|
6
|
+
import { type ButtonProps, Button } from '../button.js';
|
|
7
|
+
import type { SharedTextProps } from '../text/text_shared.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Brand-coloured lightning icon — the standard leading slot for the card variant of the run
|
|
11
|
+
* button. Hero-style call sites typically render without an icon; pass this explicitly via
|
|
12
|
+
* `LeftIcon` when you want it.
|
|
13
|
+
*/
|
|
14
|
+
export const ActorExampleRunButtonLightningIcon = (props: IconProps) => (
|
|
15
|
+
<LightningIcon {...props} color={theme.color.primary.action} />
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* "Run example" CTA shared by the actor-detail Examples tab (apify-core Console) and the
|
|
20
|
+
* public actor-example landing/hero pages (apify-web). Encapsulates two universal defaults
|
|
21
|
+
* for this CTA — `target="_self"` so external `console.apify.com` links don't open in a new
|
|
22
|
+
* tab, and `hideExternalIcon` so the lightning leading icon (when present) is the only
|
|
23
|
+
* action affordance — and pins the analytics shape to `{ element, cardTitle, actorId }`.
|
|
24
|
+
*
|
|
25
|
+
* Tracking flows through the host app's `trackClick` (apify-web's analytics, console's
|
|
26
|
+
* client tracker) via the underlying `Button`.
|
|
27
|
+
*/
|
|
28
|
+
export type ActorExampleRunButtonProps = Pick<ButtonProps, 'size' | 'variant' | 'LeftIcon' | 'RightIcon'> & {
|
|
29
|
+
actorId: string;
|
|
30
|
+
consoleUrl: string;
|
|
31
|
+
trackingProps: {
|
|
32
|
+
element: string;
|
|
33
|
+
cardTitle: string;
|
|
34
|
+
};
|
|
35
|
+
textSize?: SharedTextProps['size'];
|
|
36
|
+
className?: string;
|
|
37
|
+
children: React.ReactNode;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const ActorExampleRunButton = ({
|
|
41
|
+
actorId,
|
|
42
|
+
consoleUrl,
|
|
43
|
+
size = 'extraLarge',
|
|
44
|
+
variant = 'primary',
|
|
45
|
+
trackingProps,
|
|
46
|
+
children,
|
|
47
|
+
...buttonProps
|
|
48
|
+
}: ActorExampleRunButtonProps) => (
|
|
49
|
+
<Button
|
|
50
|
+
{...buttonProps}
|
|
51
|
+
to={consoleUrl}
|
|
52
|
+
size={size}
|
|
53
|
+
variant={variant}
|
|
54
|
+
target="_self"
|
|
55
|
+
hideExternalIcon
|
|
56
|
+
trackingId={trackingProps.element}
|
|
57
|
+
trackingData={{ cardTitle: trackingProps.cardTitle, actorId }}
|
|
58
|
+
>
|
|
59
|
+
{children}
|
|
60
|
+
</Button>
|
|
61
|
+
);
|