@apify/ui-library 1.108.2 → 1.109.1

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 (27) hide show
  1. package/dist/src/components/card_container.d.ts +27 -0
  2. package/dist/src/components/card_container.d.ts.map +1 -0
  3. package/dist/src/components/card_container.js +46 -0
  4. package/dist/src/components/card_container.js.map +1 -0
  5. package/dist/src/components/card_container.stories.d.ts +10 -0
  6. package/dist/src/components/card_container.stories.d.ts.map +1 -0
  7. package/dist/src/components/card_container.stories.js +33 -0
  8. package/dist/src/components/card_container.stories.js.map +1 -0
  9. package/dist/src/components/code/action_button.d.ts +6 -1
  10. package/dist/src/components/code/action_button.d.ts.map +1 -1
  11. package/dist/src/components/code/action_button.js +10 -2
  12. package/dist/src/components/code/action_button.js.map +1 -1
  13. package/dist/src/components/code/one_line_code/one_line_code.d.ts +7 -1
  14. package/dist/src/components/code/one_line_code/one_line_code.d.ts.map +1 -1
  15. package/dist/src/components/code/one_line_code/one_line_code.js +2 -2
  16. package/dist/src/components/code/one_line_code/one_line_code.js.map +1 -1
  17. package/dist/src/components/index.d.ts +1 -0
  18. package/dist/src/components/index.d.ts.map +1 -1
  19. package/dist/src/components/index.js +1 -0
  20. package/dist/src/components/index.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/package.json +2 -2
  23. package/src/components/card_container.stories.tsx +63 -0
  24. package/src/components/card_container.tsx +78 -0
  25. package/src/components/code/action_button.tsx +22 -1
  26. package/src/components/code/one_line_code/one_line_code.tsx +26 -2
  27. package/src/components/index.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apify/ui-library",
3
- "version": "1.108.2",
3
+ "version": "1.109.1",
4
4
  "description": "React UI library used by apify.com",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -64,5 +64,5 @@
64
64
  "src",
65
65
  "style"
66
66
  ],
67
- "gitHead": "1f8d2e8f2da6545bf69f203409108df5e1b5964c"
67
+ "gitHead": "b5af68110c0fd0dc105337972f28da075d6e7143"
68
68
  }
@@ -0,0 +1,63 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import styled from 'styled-components';
3
+
4
+ import { DragIndicatorIcon } from '@apify/ui-icons';
5
+
6
+ import { CardContainer, type CardContainerProps } from './card_container.js';
7
+ import { IconButton } from './icon_button.js';
8
+
9
+ export default {
10
+ title: 'UI-Library/CardContainer',
11
+ component: CardContainer,
12
+ argTypes: {
13
+ headerPlacement: {
14
+ control: { type: 'select' },
15
+ options: ['TOP', 'BOTTOM'],
16
+ },
17
+ },
18
+ } as Meta<CardContainerProps>;
19
+
20
+ type Story = StoryObj<CardContainerProps>;
21
+
22
+ const StoryWrapper = styled.div`
23
+ display: grid;
24
+ gap: 1rem;
25
+ grid-template-columns: 1fr 1fr 1fr;
26
+ `;
27
+ /**
28
+ * Default color wheel gradient with standard settings
29
+ */
30
+ export const Default: Story = {
31
+ args: {
32
+ children: 'This is the content',
33
+ header: 'Recently viewed',
34
+ },
35
+ render: (args: CardContainerProps) => {
36
+ return <StoryWrapper>
37
+ <CardContainer {...args} />
38
+ <CardContainer {...args} headerPlacement='BOTTOM'/>
39
+ <CardContainer
40
+ {...args}
41
+ header={<>
42
+ <CardContainer.Heading>TEst</CardContainer.Heading>
43
+ <IconButton Icon={DragIndicatorIcon}/>
44
+ </>}
45
+ />
46
+ <CardContainer
47
+ {...args}
48
+ header={<>
49
+ <div>
50
+ <CardContainer.Heading># Videos with this hashtag</CardContainer.Heading>
51
+ <code style={{ marginLeft: 8 }}>Required</code>
52
+ </div>
53
+ </>}
54
+ />
55
+ <CardContainer
56
+ {...args}
57
+ header={<>
58
+ Completely custom header content
59
+ </>}
60
+ />
61
+ </StoryWrapper>;
62
+ },
63
+ };
@@ -0,0 +1,78 @@
1
+ import type React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { ValueOf } from '@apify-packages/types';
5
+
6
+ import { theme } from '../design_system/theme.js';
7
+ import { Box, type BoxProps } from './box.js';
8
+
9
+ const classNames = {
10
+ CONTENT: 'CardContainer-Content',
11
+ HEADER: 'CardContainer-Header',
12
+ };
13
+
14
+ const HEADER_PLACEMENT = {
15
+ TOP: 'TOP',
16
+ BOTTOM: 'BOTTOM',
17
+ } as const;
18
+
19
+ const Wrapper = styled(Box)<{$headerPlacement: ValueOf<typeof HEADER_PLACEMENT>}>`
20
+ background-color: ${theme.color.neutral.backgroundSubtle};
21
+ border-radius: ${theme.radius.radius12};
22
+
23
+ padding: ${theme.space.space2};
24
+
25
+ display: flex;
26
+ flex-direction: ${({ $headerPlacement }) => ($headerPlacement === HEADER_PLACEMENT.TOP ? 'column' : 'column-reverse')};
27
+
28
+ .${classNames.CONTENT} {
29
+ /* Inner radius = outer radius - padding */
30
+ border-radius: calc(${theme.radius.radius12} - ${theme.space.space2});
31
+ background-color: ${theme.color.neutral.background};
32
+
33
+ padding: ${theme.space.space16};
34
+ flex-grow: 1;
35
+ }
36
+
37
+ .${classNames.HEADER} {
38
+ padding: ${theme.space.space4} ${theme.space.space8};
39
+ display: flex;
40
+ justify-content: space-between;
41
+ align-items: center;
42
+ }
43
+ `;
44
+
45
+ const CardContainerHeading = styled.span`${theme.typography.shared.desktop.bodyMMedium}`;
46
+
47
+ export type CardContainerProps = BoxProps & {
48
+ /** The header can be placed on the bottom of the card or on the top. */
49
+ headerPlacement?: ValueOf<typeof HEADER_PLACEMENT>,
50
+ /**
51
+ * If string is passed, the correct styles are applied automatically.
52
+ * In case of custom component, use `CardContainer.Heading` component to get the same styles.
53
+ */
54
+ header: React.ReactNode,
55
+ };
56
+
57
+ /**
58
+ * CardContainer visually wraps it's children and shows a simple header.
59
+ *
60
+ * The header can be customized.
61
+ */
62
+ export const CardContainer = ({
63
+ children,
64
+ header,
65
+ headerPlacement = HEADER_PLACEMENT.TOP,
66
+ ...rest
67
+ }: CardContainerProps) => (
68
+ <Wrapper {...rest} $headerPlacement={headerPlacement}>
69
+ <div className={classNames.HEADER}>
70
+ {typeof header === 'string' ? <CardContainerHeading>{header}</CardContainerHeading> : header}
71
+ </div>
72
+ <div className={classNames.CONTENT}>
73
+ {children}
74
+ </div>
75
+ </Wrapper>
76
+ );
77
+
78
+ CardContainer.Heading = CardContainerHeading;
@@ -4,6 +4,7 @@ import styled, { css } from 'styled-components';
4
4
  import { CheckIcon, CopyIcon } from '@apify/ui-icons';
5
5
 
6
6
  import { theme } from '../../design_system/theme.js';
7
+ import { useSharedUiDependencies } from '../../ui_dependency_provider.js';
7
8
  import { useCopyToClipboard } from '../../utils/index.js';
8
9
  import { Text } from '../text/index.js';
9
10
 
@@ -62,19 +63,33 @@ const StyledButton = styled.button<StyledButtonProps>`
62
63
 
63
64
  interface ActionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
64
65
  successStyle?: boolean;
66
+ trackingId?: string;
67
+ trackingData?: Record<string, unknown>;
68
+ onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
65
69
  }
66
70
 
67
71
  export const ActionButton = ({
68
72
  successStyle,
69
73
  children,
74
+ trackingId,
75
+ trackingData,
76
+ onClick,
70
77
  ...props
71
78
  }: ActionButtonProps) => {
72
79
  const hasText = typeof children === 'string';
73
80
 
81
+ const { trackClick } = useSharedUiDependencies();
82
+
83
+ const trackedOnClick = (e: React.MouseEvent<HTMLButtonElement>) => {
84
+ if (trackClick && trackingId) trackClick(trackingId, trackingData);
85
+ if (onClick) onClick(e);
86
+ };
87
+
74
88
  return (
75
89
  <StyledButton
76
90
  $successStyle={successStyle}
77
91
  $hasText={hasText}
92
+ onClick={trackedOnClick}
78
93
  {...props}
79
94
  >
80
95
  {hasText ? <Text weight="bold">{children}</Text> : children}
@@ -84,12 +99,18 @@ export const ActionButton = ({
84
99
 
85
100
  interface CopyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
86
101
  code: string;
102
+ trackingId?: string;
103
+ trackingData?: Record<string, unknown>;
87
104
  }
88
105
 
89
106
  export const CopyButton = ({ code, ...props }: CopyButtonProps) => {
90
107
  const { isCopied, copyToClipboard } = useCopyToClipboard();
91
108
  return (
92
- <ActionButton onClick={async () => copyToClipboard(code)} data-test='copy_to_clipboard' aria-label="Copy to clipboard" {...props}>
109
+ <ActionButton
110
+ onClick={async () => copyToClipboard(code)}
111
+ data-test='copy_to_clipboard'
112
+ aria-label="Copy to clipboard"
113
+ {...props}>
93
114
  {isCopied ? <CheckIcon size="16" /> : <CopyIcon size="16" />}
94
115
  </ActionButton>
95
116
  );
@@ -137,6 +137,16 @@ const OneLineCodeWrapper = styled(SyntaxHighlighterBaseStylesWrapper)<OneLineCod
137
137
  }
138
138
  `;
139
139
 
140
+ export type TrackingBundleDataObject = {
141
+ trackingId: string;
142
+ trackingData?: Record<string, unknown>;
143
+ };
144
+
145
+ export type OneLineCodeTrackingBundle = Record<
146
+ 'secret' | 'copy' | 'action',
147
+ TrackingBundleDataObject
148
+ >;
149
+
140
150
  export type OneLineCodeProps = BoxProps & {
141
151
  children: string;
142
152
  language?: string;
@@ -149,6 +159,7 @@ export type OneLineCodeProps = BoxProps & {
149
159
  secret?: string;
150
160
  disabled?: boolean;
151
161
  hideCopyButton?: boolean;
162
+ trackingBundle?: OneLineCodeTrackingBundle;
152
163
  }
153
164
 
154
165
  export function OneLineCode({
@@ -163,6 +174,7 @@ export function OneLineCode({
163
174
  secret,
164
175
  disabled,
165
176
  hideCopyButton,
177
+ trackingBundle,
166
178
  ...rest
167
179
  }: OneLineCodeProps) {
168
180
  const hasSecret = secret !== undefined;
@@ -209,6 +221,8 @@ export function OneLineCode({
209
221
  {hasSecret && (
210
222
  <ActionButton
211
223
  onClick={() => setShowSecret((prev) => !prev)}
224
+ trackingId={trackingBundle?.secret?.trackingId}
225
+ trackingData={trackingBundle?.secret?.trackingData}
212
226
  data-test='toggle-visibility-button'
213
227
  >
214
228
  {showSecret ? (
@@ -218,9 +232,19 @@ export function OneLineCode({
218
232
  )}
219
233
  </ActionButton>
220
234
  )}
221
- {!hideCopyButton && <CopyButton code={codeWithSecret} />}
235
+ {!hideCopyButton && (
236
+ <CopyButton
237
+ code={codeWithSecret}
238
+ trackingId={trackingBundle?.copy?.trackingId}
239
+ trackingData={trackingBundle?.copy?.trackingData}
240
+ />
241
+ )}
222
242
  {!!onActionButtonClick && (
223
- <ActionButton onClick={onActionButtonClick}>
243
+ <ActionButton
244
+ onClick={onActionButtonClick}
245
+ trackingId={trackingBundle?.action?.trackingId}
246
+ trackingData={trackingBundle?.action?.trackingData}
247
+ >
224
248
  {actionButtonLabel}
225
249
  </ActionButton>
226
250
  )}
@@ -1,5 +1,6 @@
1
1
  export * from './text/index.js';
2
2
  export * from './box.js';
3
+ export * from './card_container.js';
3
4
  export * from './message.js';
4
5
  export * from './floating/index.js';
5
6
  export * from './button.js';