@apify/ui-library 1.168.2 → 1.169.0

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 (117) hide show
  1. package/dist/components/avatar/bordered_actor_avatar.d.ts +9 -0
  2. package/dist/components/avatar/bordered_actor_avatar.d.ts.map +1 -0
  3. package/dist/components/avatar/bordered_actor_avatar.js +43 -0
  4. package/dist/components/avatar/index.d.ts +1 -0
  5. package/dist/components/avatar/index.d.ts.map +1 -1
  6. package/dist/components/index.d.ts +1 -0
  7. package/dist/components/index.d.ts.map +1 -1
  8. package/dist/components/skeleton/index.d.ts +6 -0
  9. package/dist/components/skeleton/index.d.ts.map +1 -0
  10. package/dist/components/skeleton/skeleton.d.ts +18 -0
  11. package/dist/components/skeleton/skeleton.d.ts.map +1 -0
  12. package/dist/components/skeleton/skeleton.js +19 -0
  13. package/dist/components/skeleton/skeleton.styled.d.ts +13 -0
  14. package/dist/components/skeleton/skeleton.styled.d.ts.map +1 -0
  15. package/dist/components/skeleton/skeleton.styled.js +55 -0
  16. package/dist/components/skeleton/skeleton.test_ids.d.ts +6 -0
  17. package/dist/components/skeleton/skeleton.test_ids.d.ts.map +1 -0
  18. package/dist/components/skeleton/skeleton.test_ids.js +8 -0
  19. package/dist/components/skeleton/skeleton.type-test.d.ts +2 -0
  20. package/dist/components/skeleton/skeleton.type-test.d.ts.map +1 -0
  21. package/dist/components/skeleton/skeleton_fade_in.d.ts +9 -0
  22. package/dist/components/skeleton/skeleton_fade_in.d.ts.map +1 -0
  23. package/dist/components/skeleton/skeleton_fade_in.js +15 -0
  24. package/dist/components/skeleton/skeleton_group.d.ts +13 -0
  25. package/dist/components/skeleton/skeleton_group.d.ts.map +1 -0
  26. package/dist/components/skeleton/skeleton_group.js +19 -0
  27. package/dist/design_system/colors/generated/colors_theme.dark.d.ts +13 -0
  28. package/dist/design_system/colors/generated/colors_theme.dark.d.ts.map +1 -1
  29. package/dist/design_system/colors/generated/colors_theme.dark.js +13 -0
  30. package/dist/design_system/colors/generated/colors_theme.light.d.ts +13 -0
  31. package/dist/design_system/colors/generated/colors_theme.light.d.ts.map +1 -1
  32. package/dist/design_system/colors/generated/colors_theme.light.js +13 -0
  33. package/dist/design_system/theme.d.ts +26 -0
  34. package/dist/design_system/theme.d.ts.map +1 -1
  35. package/dist/files_hash_at_build.txt +1 -1
  36. package/dist/index.js +7 -1
  37. package/dist/src/components/avatar/bordered_actor_avatar.d.ts +9 -0
  38. package/dist/src/components/avatar/bordered_actor_avatar.d.ts.map +1 -0
  39. package/dist/src/components/avatar/bordered_actor_avatar.js +28 -0
  40. package/dist/src/components/avatar/bordered_actor_avatar.js.map +1 -0
  41. package/dist/src/components/avatar/index.d.ts +1 -0
  42. package/dist/src/components/avatar/index.d.ts.map +1 -1
  43. package/dist/src/components/avatar/index.js +1 -0
  44. package/dist/src/components/avatar/index.js.map +1 -1
  45. package/dist/src/components/index.d.ts +1 -0
  46. package/dist/src/components/index.d.ts.map +1 -1
  47. package/dist/src/components/index.js +1 -0
  48. package/dist/src/components/index.js.map +1 -1
  49. package/dist/src/components/skeleton/index.d.ts +6 -0
  50. package/dist/src/components/skeleton/index.d.ts.map +1 -0
  51. package/dist/src/components/skeleton/index.js +6 -0
  52. package/dist/src/components/skeleton/index.js.map +1 -0
  53. package/dist/src/components/skeleton/skeleton.d.ts +18 -0
  54. package/dist/src/components/skeleton/skeleton.d.ts.map +1 -0
  55. package/dist/src/components/skeleton/skeleton.js +10 -0
  56. package/dist/src/components/skeleton/skeleton.js.map +1 -0
  57. package/dist/src/components/skeleton/skeleton.styled.d.ts +13 -0
  58. package/dist/src/components/skeleton/skeleton.styled.d.ts.map +1 -0
  59. package/dist/src/components/skeleton/skeleton.styled.js +55 -0
  60. package/dist/src/components/skeleton/skeleton.styled.js.map +1 -0
  61. package/dist/src/components/skeleton/skeleton.test_ids.d.ts +6 -0
  62. package/dist/src/components/skeleton/skeleton.test_ids.d.ts.map +1 -0
  63. package/dist/src/components/skeleton/skeleton.test_ids.js +6 -0
  64. package/dist/src/components/skeleton/skeleton.test_ids.js.map +1 -0
  65. package/dist/src/components/skeleton/skeleton.type-test.d.ts +2 -0
  66. package/dist/src/components/skeleton/skeleton.type-test.d.ts.map +1 -0
  67. package/dist/src/components/skeleton/skeleton.type-test.js +25 -0
  68. package/dist/src/components/skeleton/skeleton.type-test.js.map +1 -0
  69. package/dist/src/components/skeleton/skeleton_fade_in.d.ts +9 -0
  70. package/dist/src/components/skeleton/skeleton_fade_in.d.ts.map +1 -0
  71. package/dist/src/components/skeleton/skeleton_fade_in.js +9 -0
  72. package/dist/src/components/skeleton/skeleton_fade_in.js.map +1 -0
  73. package/dist/src/components/skeleton/skeleton_group.d.ts +13 -0
  74. package/dist/src/components/skeleton/skeleton_group.d.ts.map +1 -0
  75. package/dist/src/components/skeleton/skeleton_group.js +10 -0
  76. package/dist/src/components/skeleton/skeleton_group.js.map +1 -0
  77. package/dist/src/design_system/colors/generated/colors_theme.dark.d.ts +13 -0
  78. package/dist/src/design_system/colors/generated/colors_theme.dark.d.ts.map +1 -1
  79. package/dist/src/design_system/colors/generated/colors_theme.dark.js +13 -0
  80. package/dist/src/design_system/colors/generated/colors_theme.dark.js.map +1 -1
  81. package/dist/src/design_system/colors/generated/colors_theme.light.d.ts +13 -0
  82. package/dist/src/design_system/colors/generated/colors_theme.light.d.ts.map +1 -1
  83. package/dist/src/design_system/colors/generated/colors_theme.light.js +13 -0
  84. package/dist/src/design_system/colors/generated/colors_theme.light.js.map +1 -1
  85. package/dist/src/design_system/theme.d.ts +26 -0
  86. package/dist/src/design_system/theme.d.ts.map +1 -1
  87. package/dist/src/test_ids.d.ts +1 -0
  88. package/dist/src/test_ids.d.ts.map +1 -1
  89. package/dist/src/test_ids.js +1 -0
  90. package/dist/src/test_ids.js.map +1 -1
  91. package/dist/test_ids.d.ts +1 -0
  92. package/dist/test_ids.d.ts.map +1 -1
  93. package/dist/test_ids.js +2 -1
  94. package/dist/tsconfig.build.tsbuildinfo +1 -1
  95. package/package.json +3 -3
  96. package/src/components/avatar/bordered_actor_avatar.stories.tsx +54 -0
  97. package/src/components/avatar/bordered_actor_avatar.tsx +45 -0
  98. package/src/components/avatar/index.ts +1 -0
  99. package/src/components/index.ts +1 -0
  100. package/src/components/skeleton/examples/actor_idea_cards_skeleton.example.tsx +67 -0
  101. package/src/components/skeleton/examples/new_actor_wizard_cards_skeleton.example.tsx +55 -0
  102. package/src/components/skeleton/examples/publication_categories_skeleton.example.tsx +50 -0
  103. package/src/components/skeleton/examples/store_actor_cards_loading.example.tsx +74 -0
  104. package/src/components/skeleton/examples/store_actor_cards_skeleton.example.tsx +94 -0
  105. package/src/components/skeleton/index.ts +5 -0
  106. package/src/components/skeleton/skeleton.stories.tsx +221 -0
  107. package/src/components/skeleton/skeleton.styled.ts +66 -0
  108. package/src/components/skeleton/skeleton.test_ids.ts +5 -0
  109. package/src/components/skeleton/skeleton.tsx +34 -0
  110. package/src/components/skeleton/skeleton.type-test.ts +32 -0
  111. package/src/components/skeleton/skeleton_fade_in.tsx +21 -0
  112. package/src/components/skeleton/skeleton_group.tsx +32 -0
  113. package/src/design_system/colors/build_color_tokens.js +4 -2
  114. package/src/design_system/colors/colors.stories.tsx +9 -1
  115. package/src/design_system/colors/generated/colors_theme.dark.ts +13 -0
  116. package/src/design_system/colors/generated/colors_theme.light.ts +13 -0
  117. package/src/test_ids.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apify/ui-library",
3
- "version": "1.168.2",
3
+ "version": "1.169.0",
4
4
  "description": "React UI library used by apify.com",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -42,7 +42,7 @@
42
42
  "It's not nice, but helps us to get around the problem of multiple react instances."
43
43
  ],
44
44
  "dependencies": {
45
- "@apify/ui-icons": "^1.54.0",
45
+ "@apify/ui-icons": "^1.55.0",
46
46
  "@floating-ui/react": "^0.27.19",
47
47
  "@floating-ui/react-dom": "^2.1.8",
48
48
  "@radix-ui/react-checkbox": "^1.3.3",
@@ -94,5 +94,5 @@
94
94
  "src",
95
95
  "style"
96
96
  ],
97
- "gitHead": "9b5709c7d03526fdda3f4ad091c5890b4e745891"
97
+ "gitHead": "7519bd1e0002f8cef068f52e90f3aff203d15bec"
98
98
  }
@@ -0,0 +1,54 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { BorderedActorAvatar } from './bordered_actor_avatar';
4
+
5
+ const AVATAR_SIZES = [24, 32, 40, 44] as const;
6
+
7
+ export default {
8
+ title: 'UI-Library/Avatar/BorderedActorAvatar',
9
+ component: BorderedActorAvatar,
10
+ argTypes: {
11
+ size: { control: 'select', options: AVATAR_SIZES },
12
+ name: { control: 'text' },
13
+ url: { control: 'text' },
14
+ },
15
+ args: {
16
+ name: 'Web Scraper',
17
+ size: 24,
18
+ },
19
+ tags: ['new'],
20
+ } as Meta<typeof BorderedActorAvatar>;
21
+
22
+ type Story = StoryObj<typeof BorderedActorAvatar>;
23
+
24
+ export const Default: Story = {};
25
+
26
+ export const Sizes: Story = {
27
+ render: () => (
28
+ <div style={{ display: 'flex', gap: '16px', alignItems: 'flex-end' }}>
29
+ {AVATAR_SIZES.map((size) => (
30
+ <div key={size} style={{ textAlign: 'center' }}>
31
+ <BorderedActorAvatar name="Web Scraper" size={size} />
32
+ <p style={{ marginTop: '8px', fontSize: '12px' }}>{size}px</p>
33
+ </div>
34
+ ))}
35
+ </div>
36
+ ),
37
+ };
38
+
39
+ export const WithImageUrl: Story = {
40
+ render: () => (
41
+ <div style={{ display: 'flex', gap: '16px', alignItems: 'flex-end' }}>
42
+ {AVATAR_SIZES.map((size) => (
43
+ <div key={size} style={{ textAlign: 'center' }}>
44
+ <BorderedActorAvatar
45
+ name="Actors MCP Server"
46
+ url="https://apify.github.io/apify-web/img/apify-logo/logomark-32x32.svg"
47
+ size={size}
48
+ />
49
+ <p style={{ marginTop: '8px', fontSize: '12px' }}>{size}px</p>
50
+ </div>
51
+ ))}
52
+ </div>
53
+ ),
54
+ };
@@ -0,0 +1,45 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { theme } from '../../design_system/theme';
4
+ import { Box, type BoxProps } from '../box';
5
+ import { ActorAvatar, getActorAvatarBorderRadius } from './actor_avatar';
6
+
7
+ const BORDER_WIDTH = 1;
8
+
9
+ /** Computes border, padding, and radius dimensions for the bordered wrapper. */
10
+ const getBorderedStyle = (size: number) => {
11
+ const padding = size < 40 ? 2 : 3;
12
+ const outerRadius = getActorAvatarBorderRadius(size);
13
+ const innerRadius = Math.max(outerRadius - 3, 2);
14
+ const innerSize = Math.max(size - (BORDER_WIDTH + padding) * 2, 1);
15
+
16
+ return { padding, outerRadius, innerRadius, innerSize };
17
+ };
18
+
19
+ type StyledBorderProps = { $outerRadius: number; $padding: number };
20
+
21
+ const StyledBorder = styled(Box)<StyledBorderProps>`
22
+ display: inline-flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ border: ${BORDER_WIDTH}px solid ${theme.color.neutral.border};
26
+ border-radius: ${({ $outerRadius }) => $outerRadius}px;
27
+ padding: ${({ $padding }) => $padding}px;
28
+ overflow: hidden;
29
+ `;
30
+
31
+ type BorderedActorAvatarProps = BoxProps & {
32
+ name?: string;
33
+ url?: string | null;
34
+ size: 24 | 32 | 40 | 44;
35
+ };
36
+
37
+ export const BorderedActorAvatar = ({ size, name, url, ...rest }: BorderedActorAvatarProps) => {
38
+ const { padding, outerRadius, innerRadius, innerSize } = getBorderedStyle(size);
39
+
40
+ return (
41
+ <StyledBorder $outerRadius={outerRadius} $padding={padding} {...rest}>
42
+ <ActorAvatar size={innerSize} borderRadius={`${innerRadius}px`} name={name} url={url} />
43
+ </StyledBorder>
44
+ );
45
+ };
@@ -1,2 +1,3 @@
1
1
  export * from './actor_avatar';
2
+ export * from './bordered_actor_avatar';
2
3
  export * from './user_avatar';
@@ -30,6 +30,7 @@ export * from './tabs';
30
30
  export * from './shortcut';
31
31
  export * from './icon_button';
32
32
  export * from './brand_icon';
33
+ export * from './skeleton';
33
34
  export * from './spinner';
34
35
  export * from './store';
35
36
  export * from './checkbox';
@@ -0,0 +1,67 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { Box, Skeleton, SkeletonGroup, theme } from '@apify/ui-library';
4
+
5
+ // apify.com Ideas search results: avatar, heading, a three-line paragraph and two footer chips.
6
+
7
+ const StyledGrid = styled(SkeletonGroup)`
8
+ display: grid;
9
+ grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr));
10
+ gap: ${theme.space.space16};
11
+ `;
12
+
13
+ const StyledCard = styled(Box)`
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: ${theme.space.space16};
17
+ padding: ${theme.space.space16} ${theme.space.space24};
18
+ border: 1px solid ${theme.color.neutral.separatorSubtle};
19
+ border-radius: ${theme.radius.radius16};
20
+ background-color: ${theme.color.neutral.cardBackground};
21
+ `;
22
+
23
+ const StyledHeader = styled(Box)`
24
+ display: flex;
25
+ align-items: center;
26
+ gap: ${theme.space.space8};
27
+ `;
28
+
29
+ const StyledLines = styled(Box)`
30
+ display: flex;
31
+ flex-direction: column;
32
+ gap: ${theme.space.space12};
33
+ `;
34
+
35
+ const StyledFooter = styled(Box)`
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: space-between;
39
+ gap: ${theme.space.space12};
40
+ margin-top: auto;
41
+ `;
42
+
43
+ const ActorIdeaCardSkeleton = () => (
44
+ <StyledCard>
45
+ <StyledHeader>
46
+ <Skeleton width={theme.space.space40} height={theme.space.space40} />
47
+ <Skeleton width="52%" height="2rem" />
48
+ </StyledHeader>
49
+ <StyledLines>
50
+ <Skeleton height={theme.space.space16} />
51
+ <Skeleton width="94%" height={theme.space.space16} />
52
+ <Skeleton width="68%" height={theme.space.space16} />
53
+ </StyledLines>
54
+ <StyledFooter>
55
+ <Skeleton width="52%" height="2rem" />
56
+ <Skeleton width="34%" height={theme.space.space16} />
57
+ </StyledFooter>
58
+ </StyledCard>
59
+ );
60
+
61
+ export const ActorIdeaCardsSkeleton = ({ count = 6 }: { count?: number }) => (
62
+ <StyledGrid label="Loading Actor ideas">
63
+ {Array.from({ length: count }, (_, index) => (
64
+ <ActorIdeaCardSkeleton key={index} />
65
+ ))}
66
+ </StyledGrid>
67
+ );
@@ -0,0 +1,55 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { Box, Skeleton, SkeletonGroup, theme } from '@apify/ui-library';
4
+
5
+ // Console new Actor wizard: the use-case, language and recommendation cards of a step.
6
+
7
+ const StyledGrid = styled(SkeletonGroup)`
8
+ display: grid;
9
+ grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
10
+ gap: ${theme.space.space16};
11
+ `;
12
+
13
+ const StyledCard = styled(Box)`
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: ${theme.space.space16};
17
+ min-height: 23rem;
18
+ padding: ${theme.space.space24};
19
+ border: 1px solid ${theme.color.neutral.separatorSubtle};
20
+ border-radius: ${theme.radius.radius12};
21
+ background-color: ${theme.color.neutral.cardBackground};
22
+ `;
23
+
24
+ const StyledLines = styled(Box)`
25
+ display: flex;
26
+ flex-direction: column;
27
+ gap: ${theme.space.space4};
28
+ `;
29
+
30
+ const StyledActions = styled(StyledLines)`
31
+ margin-top: auto;
32
+ `;
33
+
34
+ const NewActorWizardCardSkeleton = () => (
35
+ <StyledCard>
36
+ <Skeleton width={theme.space.space32} height={theme.space.space32} />
37
+ <Skeleton width="40%" height={theme.space.space12} />
38
+ <StyledLines>
39
+ <Skeleton width="90%" height={theme.space.space8} />
40
+ <Skeleton width="70%" height={theme.space.space8} />
41
+ </StyledLines>
42
+ <StyledActions>
43
+ <Skeleton height={theme.space.space32} />
44
+ <Skeleton height={theme.space.space32} />
45
+ </StyledActions>
46
+ </StyledCard>
47
+ );
48
+
49
+ export const NewActorWizardCardsSkeleton = ({ count = 4 }: { count?: number }) => (
50
+ <StyledGrid label="Loading recommendations">
51
+ {Array.from({ length: count }, (_, index) => (
52
+ <NewActorWizardCardSkeleton key={index} />
53
+ ))}
54
+ </StyledGrid>
55
+ );
@@ -0,0 +1,50 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { Box, Skeleton, SkeletonGroup, Text, theme } from '@apify/ui-library';
4
+
5
+ // Actor publication tab while the LLM assigns categories: the labels are real text, only the values load.
6
+
7
+ const CATEGORY_ROWS = [
8
+ { label: 'Use case', width: '49%' },
9
+ { label: 'Industry', width: '60%' },
10
+ { label: 'Output', width: '49%' },
11
+ { label: 'Domain', width: '60%' },
12
+ { label: 'Label', width: '55%' },
13
+ ];
14
+
15
+ const StyledPanel = styled(SkeletonGroup)`
16
+ max-width: 48rem;
17
+ border: 1px solid ${theme.color.neutral.separatorSubtle};
18
+ border-radius: ${theme.radius.radius12};
19
+ background-color: ${theme.color.neutral.cardBackground};
20
+ `;
21
+
22
+ const StyledRow = styled(Box)`
23
+ display: flex;
24
+ align-items: center;
25
+ gap: ${theme.space.space16};
26
+ min-height: 5.2rem;
27
+ padding: ${theme.space.space16};
28
+
29
+ & + & {
30
+ border-top: 1px solid ${theme.color.neutral.separatorSubtle};
31
+ }
32
+ `;
33
+
34
+ const StyledLabel = styled(Text)`
35
+ flex: none;
36
+ width: 9.2rem;
37
+ `;
38
+
39
+ export const PublicationCategoriesSkeleton = () => (
40
+ <StyledPanel label="Assigning categories">
41
+ {CATEGORY_ROWS.map(({ label, width }) => (
42
+ <StyledRow key={label}>
43
+ <StyledLabel size="small" color={theme.color.neutral.textSubtle}>
44
+ {label}
45
+ </StyledLabel>
46
+ <Skeleton width={width} height={theme.space.space12} />
47
+ </StyledRow>
48
+ ))}
49
+ </StyledPanel>
50
+ );
@@ -0,0 +1,74 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { Box, SkeletonFadeIn, Text, theme } from '@apify/ui-library';
4
+
5
+ import {
6
+ StoreActorCardsSkeleton,
7
+ StyledStoreCardBody,
8
+ StyledStoreCardFooter,
9
+ StyledStoreCardShell,
10
+ } from './store_actor_cards_skeleton.example';
11
+
12
+ // Show the skeleton only while the request is in flight, swap it for the content the moment the data lands,
13
+ // and let the content fade in. The skeleton mirrors the card, so the swap does not move the page.
14
+
15
+ type StoreActor = { id: string; title: string; name: string; description: string; author: string; stats: string };
16
+
17
+ const StyledGrid = styled(Box)`
18
+ display: grid;
19
+ grid-template-columns: repeat(auto-fill, minmax(28rem, 1fr));
20
+ gap: ${theme.space.space16};
21
+ `;
22
+
23
+ const StyledHeader = styled(Box)`
24
+ display: flex;
25
+ align-items: center;
26
+ gap: ${theme.space.space12};
27
+ `;
28
+
29
+ const StyledAvatar = styled(Box)`
30
+ flex: none;
31
+ width: ${theme.space.space40};
32
+ height: ${theme.space.space40};
33
+ border-radius: ${theme.radius.radius12};
34
+ background-color: ${theme.color.primary.background};
35
+ `;
36
+
37
+ const StoreActorCard = ({ actor }: { actor: StoreActor }) => (
38
+ <StyledStoreCardShell>
39
+ <StyledStoreCardBody>
40
+ <StyledHeader>
41
+ <StyledAvatar />
42
+ <Box>
43
+ <Text weight="bold">{actor.title}</Text>
44
+ <Text size="small" color={theme.color.neutral.textSubtle}>
45
+ {actor.name}
46
+ </Text>
47
+ </Box>
48
+ </StyledHeader>
49
+ <Text size="small">{actor.description}</Text>
50
+ </StyledStoreCardBody>
51
+ <StyledStoreCardFooter>
52
+ <Text size="small" color={theme.color.neutral.textSubtle}>
53
+ {actor.author}
54
+ </Text>
55
+ <Text size="small" color={theme.color.neutral.textSubtle}>
56
+ {actor.stats}
57
+ </Text>
58
+ </StyledStoreCardFooter>
59
+ </StyledStoreCardShell>
60
+ );
61
+
62
+ export const StoreActorCardsLoading = ({ actors }: { actors?: StoreActor[] }) => {
63
+ if (!actors) return <StoreActorCardsSkeleton count={2} />;
64
+
65
+ return (
66
+ <SkeletonFadeIn>
67
+ <StyledGrid>
68
+ {actors.map((actor) => (
69
+ <StoreActorCard key={actor.id} actor={actor} />
70
+ ))}
71
+ </StyledGrid>
72
+ </SkeletonFadeIn>
73
+ );
74
+ };
@@ -0,0 +1,94 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { Box, Skeleton, SkeletonGroup, theme } from '@apify/ui-library';
4
+
5
+ // Store home sections, Store search and Actor collections. The card has two surfaces: the body is inset in a
6
+ // `backgroundSubtle` shell and the footer sits on the shell. The translucent skeleton stays visible on both.
7
+
8
+ const StyledGrid = styled(SkeletonGroup)`
9
+ display: grid;
10
+ grid-template-columns: repeat(auto-fill, minmax(28rem, 1fr));
11
+ gap: ${theme.space.space16};
12
+ `;
13
+
14
+ export const StyledStoreCardShell = styled(Box)`
15
+ display: flex;
16
+ flex-direction: column;
17
+ gap: ${theme.space.space2};
18
+ padding: ${theme.space.space2};
19
+ border-radius: ${theme.radius.radius8};
20
+ background-color: ${theme.color.neutral.backgroundSubtle};
21
+ `;
22
+
23
+ export const StyledStoreCardBody = styled(Box)`
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: ${theme.space.space8};
27
+ padding: ${theme.space.space16};
28
+ border-radius: ${theme.radius.radius6};
29
+ background-color: ${theme.color.neutral.cardBackground};
30
+ `;
31
+
32
+ export const StyledStoreCardFooter = styled(Box)`
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: space-between;
36
+ gap: ${theme.space.space8};
37
+ padding: ${theme.space.space4} ${theme.space.space8};
38
+ `;
39
+
40
+ const StyledRow = styled(Box)`
41
+ display: flex;
42
+ align-items: center;
43
+ gap: ${theme.space.space8};
44
+ `;
45
+
46
+ const StyledHeader = styled(StyledRow)`
47
+ gap: ${theme.space.space12};
48
+ `;
49
+
50
+ const StyledTitle = styled(Box)`
51
+ flex: 1;
52
+ min-width: 0;
53
+ `;
54
+
55
+ const StyledLines = styled(Box)`
56
+ display: flex;
57
+ flex-direction: column;
58
+ gap: ${theme.space.space8};
59
+ `;
60
+
61
+ const StoreActorCardSkeleton = () => (
62
+ <StyledStoreCardShell>
63
+ <StyledStoreCardBody>
64
+ <StyledHeader>
65
+ <Skeleton width={theme.space.space40} height={theme.space.space40} />
66
+ <StyledTitle>
67
+ <Skeleton width="70%" height="2rem" />
68
+ </StyledTitle>
69
+ </StyledHeader>
70
+ <StyledLines>
71
+ <Skeleton height={theme.space.space12} />
72
+ <Skeleton width="62%" height={theme.space.space12} />
73
+ </StyledLines>
74
+ </StyledStoreCardBody>
75
+ <StyledStoreCardFooter>
76
+ <StyledRow>
77
+ <Skeleton width="2rem" height="2rem" />
78
+ <Skeleton width="3.8rem" height={theme.space.space16} />
79
+ </StyledRow>
80
+ <StyledRow>
81
+ <Skeleton width="5.6rem" height={theme.space.space16} />
82
+ <Skeleton width={theme.space.space40} height={theme.space.space16} />
83
+ </StyledRow>
84
+ </StyledStoreCardFooter>
85
+ </StyledStoreCardShell>
86
+ );
87
+
88
+ export const StoreActorCardsSkeleton = ({ count = 4 }: { count?: number }) => (
89
+ <StyledGrid label="Loading Actors">
90
+ {Array.from({ length: count }, (_, index) => (
91
+ <StoreActorCardSkeleton key={index} />
92
+ ))}
93
+ </StyledGrid>
94
+ );
@@ -0,0 +1,5 @@
1
+ export { Skeleton, type SkeletonProps } from './skeleton';
2
+ export { SkeletonFadeIn, type SkeletonFadeInProps } from './skeleton_fade_in';
3
+ export { SkeletonGroup, type SkeletonGroupProps } from './skeleton_group';
4
+ export { skeletonClassNames } from './skeleton.styled';
5
+ export { skeletonTestIds } from './skeleton.test_ids';