@bitrise/bitkit 13.64.1-alpha.0 → 13.64.3-alpha.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitrise/bitkit",
3
3
  "description": "Bitrise React component library",
4
- "version": "13.64.1-alpha.0",
4
+ "version": "13.64.3-alpha.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+ssh://git@github.com/bitrise-io/bitkit.git"
@@ -1,12 +1,101 @@
1
+ import { SystemStyleObject } from '@chakra-ui/styled-system';
2
+ import { BadgeColorScheme, BadgeProps } from './Badge';
3
+
4
+ const baseStyle: SystemStyleObject = {
5
+ borderRadius: '4',
6
+ display: 'inline-flex',
7
+ gap: '4',
8
+ padding: '4',
9
+ textStyle: 'comp/badge/sm',
10
+ };
11
+
12
+ type ColorsType = Record<'bold' | 'subtle', Record<BadgeColorScheme, Record<'color' | 'backgroundColor', string>>>;
13
+
14
+ const colors: ColorsType = {
15
+ subtle: {
16
+ progress: {
17
+ backgroundColor: 'sys/interactive/subtle',
18
+ color: 'sys/interactive/strong',
19
+ },
20
+ neutral: {
21
+ backgroundColor: 'sys/neutral/subtle',
22
+ color: 'sys/neutral/strong',
23
+ },
24
+ info: {
25
+ backgroundColor: 'sys/info/subtle',
26
+ color: 'sys/info/strong',
27
+ },
28
+ positive: {
29
+ backgroundColor: 'sys/success/subtle',
30
+ color: 'sys/success/strong',
31
+ },
32
+ negative: {
33
+ backgroundColor: 'sys/critical/subtle',
34
+ color: 'sys/critical/strong',
35
+ },
36
+ warning: {
37
+ backgroundColor: 'sys/warning/subtle',
38
+ color: 'sys/warning/strong',
39
+ },
40
+ orange: {
41
+ backgroundColor: 'sys/orange/subtle',
42
+ color: 'sys/orange/strong',
43
+ },
44
+ turquoise: {
45
+ backgroundColor: 'sys/turquoise/subtle',
46
+ color: 'sys/turquoise/strong',
47
+ },
48
+ },
49
+ bold: {
50
+ progress: {
51
+ backgroundColor: 'sys/interactive/bold',
52
+ color: 'text/on-color',
53
+ },
54
+ neutral: {
55
+ backgroundColor: 'sys/neutral/bold',
56
+ color: 'text/on-color',
57
+ },
58
+ info: {
59
+ backgroundColor: 'sys/info/bold',
60
+ color: 'text/on-color',
61
+ },
62
+ positive: {
63
+ backgroundColor: 'sys/success/bold',
64
+ color: 'text/on-color',
65
+ },
66
+ negative: {
67
+ backgroundColor: 'sys/critical/bold',
68
+ color: 'text/on-color',
69
+ },
70
+ warning: {
71
+ backgroundColor: 'sys/warning/muted',
72
+ color: 'text/primary',
73
+ },
74
+ orange: {
75
+ backgroundColor: 'sys/orange/bold',
76
+ color: 'text/on-color',
77
+ },
78
+ turquoise: {
79
+ backgroundColor: 'sys/turquoise/bold',
80
+ color: 'text/on-color',
81
+ },
82
+ },
83
+ };
84
+
85
+ const getVariant = (props: BadgeProps) => {
86
+ const { colorScheme, variant } = props;
87
+ return colors[variant || 'subtle'][colorScheme || 'neutral'];
88
+ };
89
+
1
90
  const BadgeTheme = {
2
- baseStyle: {
3
- borderRadius: '4',
4
- display: 'inline-block',
5
- paddingX: '8',
6
- paddingY: '4',
7
- textStyle: 'comp/badge/sm',
8
- color: 'text/on-color',
9
- backgroundColor: 'sys/primary/base',
91
+ baseStyle,
92
+ variants: {
93
+ bold: getVariant,
94
+ subtle: getVariant,
95
+ },
96
+ defaultProps: {
97
+ variant: 'subtle',
98
+ colorScheme: 'neutral',
10
99
  },
11
100
  };
12
101
 
@@ -1,10 +1,38 @@
1
1
  import { Badge as ChakraBadge, BadgeProps as ChakraBadgeProps, forwardRef } from '@chakra-ui/react';
2
+ import Icon, { TypeIconName } from '../Icon/Icon';
3
+ import Text from '../Text/Text';
2
4
 
3
- export type BadgeProps = ChakraBadgeProps;
5
+ export type BadgeColorScheme =
6
+ | 'neutral'
7
+ | 'info'
8
+ | 'positive'
9
+ | 'negative'
10
+ | 'warning'
11
+ | 'progress'
12
+ | 'orange'
13
+ | 'turquoise';
14
+ export interface BadgeProps extends ChakraBadgeProps {
15
+ children?: string | number;
16
+ colorScheme?: BadgeColorScheme;
17
+ iconName?: TypeIconName;
18
+ variant?: 'bold' | 'subtle';
19
+ }
4
20
 
5
21
  /**
6
22
  * Badges are used to highlight an item's status for quick recognition.
7
23
  */
8
- const Badge = forwardRef<BadgeProps, 'span'>((props, ref) => <ChakraBadge {...props} ref={ref} />);
24
+ const Badge = forwardRef<BadgeProps, 'span'>((props, ref) => {
25
+ const { children, iconName, ...rest } = props;
26
+ return (
27
+ <ChakraBadge {...rest} ref={ref} paddingInlineStart={iconName ? '4' : '8'} paddingInlineEnd={children ? '8' : '4'}>
28
+ {!!iconName && <Icon size="16" name={iconName} />}
29
+ {!!children && (
30
+ <Text hasEllipsis as="span">
31
+ {children}
32
+ </Text>
33
+ )}
34
+ </ChakraBadge>
35
+ );
36
+ });
9
37
 
10
38
  export default Badge;
@@ -0,0 +1,51 @@
1
+ import { createMultiStyleConfigHelpers } from '@chakra-ui/styled-system';
2
+
3
+ const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers([
4
+ 'container',
5
+ 'codeBox',
6
+ 'copyIcon',
7
+ ]);
8
+
9
+ const sizes = {
10
+ lg: definePartsStyle({
11
+ codeBox: {
12
+ textStyle: 'code/lg',
13
+ },
14
+ }),
15
+ md: definePartsStyle({
16
+ codeBox: {
17
+ textStyle: 'code/md',
18
+ },
19
+ }),
20
+ };
21
+
22
+ const CodeBlockTheme = defineMultiStyleConfig({
23
+ baseStyle: {
24
+ codeBox: {
25
+ bg: 'neutral.95',
26
+ border: '1px solid',
27
+ borderColor: 'separator.primary',
28
+ borderRadius: '8',
29
+ minHeight: '4rem',
30
+ overflowY: 'auto',
31
+ px: '12',
32
+ py: '8',
33
+ textWrap: 'wrap',
34
+ wordBreak: 'break-all',
35
+ },
36
+ container: {
37
+ position: 'relative',
38
+ },
39
+ copyIcon: {
40
+ position: 'absolute',
41
+ right: '1rem',
42
+ top: '1rem',
43
+ },
44
+ },
45
+ defaultProps: {
46
+ size: 'lg',
47
+ },
48
+ sizes,
49
+ });
50
+
51
+ export default CodeBlockTheme;
@@ -0,0 +1,37 @@
1
+ import { BoxProps, useClipboard, useMultiStyleConfig } from '@chakra-ui/react';
2
+ import Box from '../Box/Box';
3
+ import IconButton from '../IconButton/IconButton';
4
+
5
+ interface CodeBlockProps extends BoxProps {
6
+ children: string;
7
+ isCopiable?: boolean;
8
+ size?: 'md' | 'lg';
9
+ }
10
+
11
+ const CodeBlock = ({ children, isCopiable, ...props }: CodeBlockProps) => {
12
+ const style = useMultiStyleConfig('CodeBlock', props);
13
+
14
+ const { onCopy } = useClipboard(children);
15
+
16
+ const { maxHeight, ...otherProps } = props;
17
+
18
+ return (
19
+ <Box sx={style.container} {...otherProps}>
20
+ <Box as="pre" maxHeight={maxHeight} sx={style.codeBox}>
21
+ {children}
22
+ </Box>
23
+ {isCopiable && (
24
+ <IconButton
25
+ aria-label="Copy to clipboard"
26
+ iconName="Duplicate"
27
+ onClick={onCopy}
28
+ size="sm"
29
+ sx={style.copyIcon}
30
+ variant="secondary"
31
+ />
32
+ )}
33
+ </Box>
34
+ );
35
+ };
36
+
37
+ export default CodeBlock;
@@ -1,140 +1,45 @@
1
- import { defineStyle, defineStyleConfig, SystemStyleObject } from '@chakra-ui/styled-system';
2
- import { CodeSnippetProps } from './CodeSnippet';
1
+ import { defineStyle, defineStyleConfig } from '@chakra-ui/styled-system';
3
2
 
4
- const contentPadding = (variant: CodeSnippetProps['variant']) => {
5
- switch (variant) {
6
- case 'single':
7
- return {
8
- padding: '.75rem',
9
- paddingLeft: '1rem',
10
- paddingRight: '0',
11
- };
12
- case 'multi':
13
- return {
14
- padding: '1rem',
15
- };
16
- default:
17
- return {
18
- paddingX: '.375rem',
19
- paddingY: '.125rem',
20
- };
21
- }
3
+ const sizes = {
4
+ lg: defineStyle({
5
+ textStyle: 'code/lg',
6
+ }),
7
+ md: defineStyle({
8
+ textStyle: 'code/md',
9
+ }),
22
10
  };
23
11
 
24
- const baseStyle = defineStyle(({ variant, size, isExpanded }): SystemStyleObject => {
25
- return {
26
- wrapper: {
27
- display: 'flex',
28
- position: 'relative',
29
- width: 'fit-content',
30
- borderRadius: '2',
31
- },
32
- copyContainer: {
33
- _after:
34
- variant === 'single'
35
- ? {
36
- content: `""`,
37
- position: 'absolute',
38
- width: '8',
39
- top: '0',
40
- bottom: '0',
41
- right: '0',
42
- bgGradient: `linear(to-l, transparent, background/secondary)`,
43
- }
44
- : 'none',
45
- _focusVisible: {
46
- boxShadow: 'outline',
47
- zIndex: 1,
48
- },
49
- bg: 'background/secondary',
50
- borderRadius: '2',
51
- borderTopRightRadius: variant === 'single' ? '0' : '2',
52
- borderBottomRightRadius: variant === 'single' ? '0' : '2',
53
- cursor: 'pointer',
54
- '.chakra-collapse': {
55
- overflow: 'auto !important',
56
- },
57
- minHeight: variant === 'inline' ? '1.5rem' : '2.5rem',
58
- overflow: 'auto',
59
- scrollbarHeight: variant === 'single' ? 'none' : undefined,
60
- '::-webkit-scrollbar': {
61
- height: variant === 'single' ? 0 : undefined,
62
- },
63
- position: variant === 'single' ? 'relative' : 'static',
64
- textColor: 'text/body',
65
- textStyle: size === 'md' ? 'code/md' : 'code/lg',
66
- lineHeight: '1rem',
67
- width: '100%',
68
- whiteSpace: variant === 'single' ? 'nowrap' : 'pre',
69
- ...contentPadding(variant),
70
- },
71
- copyIcon: {
72
- bg: 'background/secondary',
73
- border: 'none',
74
- borderRadius: variant === 'multi' ? '2' : 'unset',
75
- borderTopRightRadius: '2',
76
- borderBottomRightRadius: '2',
77
- position: variant === 'multi' ? 'absolute' : 'relative',
78
- px: variant === 'multi' ? '4' : '12',
79
- py: variant === 'multi' ? '4' : '8',
80
- right: variant === 'multi' ? '4' : '0',
81
- svg: {
82
- color: 'icon/secondary',
83
- },
84
- top: variant === 'multi' ? '4' : '0',
85
- _hover: {
86
- bg: 'background/hover',
87
- svg: {
88
- color: 'text/primary',
89
- },
90
- },
91
- _active: {
92
- bg: 'background/active',
93
- svg: {
94
- color: 'text/primary',
95
- },
96
- },
97
- _focusVisible: {
98
- boxShadow: 'outline',
99
- zIndex: 1,
100
- },
101
- },
102
- showMoreButtonContainer: {
103
- background: 'background/secondary',
104
- borderRadius: 4,
105
- bottom: 4,
106
- button: {
107
- color: 'text/secondary',
108
- },
109
- padding: 4,
110
- position: 'absolute',
111
- right: 4,
112
- svg: {
113
- transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
114
- transition: '300ms',
115
- },
116
- textAlign: 'right',
117
- _hover: {
118
- bg: 'background/hover',
119
- button: {
120
- color: 'text/primary',
121
- },
122
- },
123
- _active: {
124
- bg: 'background/active',
125
- button: {
126
- color: 'text/primary',
127
- },
128
- },
129
- _focusVisible: {
130
- boxShadow: 'outline',
131
- },
132
- },
12
+ const copiableStyle = defineStyle({
13
+ cursor: 'pointer',
14
+ _hover: {
15
+ background: 'neutral.93',
16
+ },
17
+ _active: {
18
+ background: 'neutral.90',
19
+ },
20
+ _focusVisible: {
21
+ boxShadow: 'outline',
22
+ },
23
+ });
24
+
25
+ const baseStyle = defineStyle(({ isCopiable }) => {
26
+ const style = {
27
+ bg: 'neutral.95',
28
+ borderRadius: '2',
29
+ px: '6px',
30
+ py: '2px',
31
+ width: 'fit-content',
133
32
  };
33
+
34
+ return { ...style, ...(isCopiable ? copiableStyle : {}) };
134
35
  });
135
36
 
136
37
  const CodeSnippetTheme = defineStyleConfig({
137
38
  baseStyle,
39
+ defaultProps: {
40
+ size: 'lg',
41
+ },
42
+ sizes,
138
43
  });
139
44
 
140
45
  export default CodeSnippetTheme;
@@ -1,101 +1,37 @@
1
1
  import { useState } from 'react';
2
- import { useClipboard, useMultiStyleConfig } from '@chakra-ui/react';
2
+ import { useClipboard, useStyleConfig } from '@chakra-ui/react';
3
3
  import Box, { BoxProps } from '../Box/Box';
4
4
  import Tooltip from '../Tooltip/Tooltip';
5
- import Button from '../Button/Button';
6
- import Collapse from '../Collapse/Collapse';
7
- import IconButton from '../IconButton/IconButton';
8
5
 
9
6
  export interface CodeSnippetProps extends Omit<BoxProps, 'children'> {
10
7
  children: string;
11
- size?: 'md' | 'lg';
12
- startingHeight?: number;
8
+ isCopiable?: boolean;
13
9
  textToCopy?: string;
14
- variant: 'inline' | 'single' | 'multi';
10
+ size?: 'md' | 'lg';
15
11
  }
16
12
 
17
13
  const CodeSnippet = (props: CodeSnippetProps) => {
18
- const { children, variant, textToCopy, size = 'lg', startingHeight, ...rest } = props;
19
-
20
- const [isExpanded, setExpanded] = useState(false);
21
-
22
- const styles = useMultiStyleConfig('CodeSnippet', { variant, size, isExpanded });
23
-
14
+ const { children, isCopiable, textToCopy, ...rest } = props;
15
+ const css = useStyleConfig('CodeSnippet', props);
24
16
  const { hasCopied, onCopy } = useClipboard(textToCopy || children);
25
17
 
26
- const tooltipLabel = hasCopied ? 'Copied to clipboard' : 'Copy to clipboard';
27
- const isShowMoreButtonVisible = variant === 'multi' && startingHeight;
28
- const showMoreButtonText = isExpanded ? 'Show less' : 'Show more';
29
-
30
- switch (variant) {
31
- case 'inline':
32
- return (
33
- <Tooltip label={tooltipLabel} closeDelay={500}>
34
- <Box as="code" onClick={onCopy} sx={styles.copyContainer} {...rest}>
35
- {children}
36
- </Box>
37
- </Tooltip>
38
- );
39
- case 'single':
40
- return (
41
- <Box __css={styles.wrapper} {...rest}>
42
- <Box as="code" sx={styles.copyContainer}>
43
- {children}
44
- </Box>
45
- <IconButton
46
- aria-label={tooltipLabel}
47
- iconName="Duplicate"
48
- onClick={onCopy}
49
- size="md"
50
- tooltipCloseDelay={500}
51
- variant="secondary"
52
- sx={styles.copyIcon}
53
- />
54
- </Box>
55
- );
56
- case 'multi':
57
- return (
58
- <Box __css={styles.wrapper} {...rest}>
59
- <Box as="code" sx={styles.copyContainer}>
60
- {startingHeight ? (
61
- <Collapse
62
- in={isExpanded}
63
- startingHeight={startingHeight}
64
- endingHeight="100vh"
65
- transition={{ enter: { duration: 0.5 }, exit: { duration: 0.5 } }}
66
- >
67
- {children}
68
- </Collapse>
69
- ) : (
70
- children
71
- )}
72
- </Box>
73
- <IconButton
74
- aria-label={tooltipLabel}
75
- iconName="Duplicate"
76
- iconSize="24"
77
- onClick={onCopy}
78
- size="md"
79
- tooltipCloseDelay={500}
80
- variant="secondary"
81
- sx={styles.copyIcon}
82
- />
83
- {isShowMoreButtonVisible && (
84
- <Box __css={styles.showMoreButtonContainer}>
85
- <Button
86
- aria-label={showMoreButtonText}
87
- rightIconName="ChevronDown"
88
- onClick={() => setExpanded(!isExpanded)}
89
- size="sm"
90
- variant="tertiary"
91
- >
92
- {showMoreButtonText}
93
- </Button>
94
- </Box>
95
- )}
96
- </Box>
97
- );
98
- }
18
+ const [isTooltipOpen, setTooltipOpen] = useState(false);
19
+
20
+ return (
21
+ <Tooltip isOpen={isTooltipOpen} label={hasCopied ? 'Copied to clipboard' : 'Copy to clipboard'}>
22
+ <Box
23
+ __css={css}
24
+ as="code"
25
+ onClick={isCopiable ? onCopy : undefined}
26
+ onMouseEnter={() => (isCopiable ? setTooltipOpen(true) : undefined)}
27
+ onMouseLeave={() => (isCopiable ? setTooltipOpen(false) : undefined)}
28
+ tabIndex={0}
29
+ {...rest}
30
+ >
31
+ {children}
32
+ </Box>
33
+ </Tooltip>
34
+ );
99
35
  };
100
36
 
101
37
  export default CodeSnippet;
@@ -45,10 +45,7 @@ const FilterTheme = defineMultiStyleConfig({
45
45
  padding: '16',
46
46
  },
47
47
  formBadge: {
48
- backgroundColor: 'neutral.93',
49
- color: 'neutral.40',
50
48
  fontVariantNumeric: 'tabular-nums',
51
- fontWeight: 'bold',
52
49
  },
53
50
  formButtonGroup: {
54
51
  display: 'flex',
@@ -117,7 +117,11 @@ const FilterForm = (props: FilterFormProps) => {
117
117
  <Text as="h5" sx={filterStyle.formTitle}>
118
118
  {categoryName || category}
119
119
  </Text>
120
- {isMultiple && <Badge sx={filterStyle.formBadge}>{selected[0] === '' ? '0' : selected.length}</Badge>}
120
+ {isMultiple && (
121
+ <Badge variant="subtle" colorScheme="neutral" sx={filterStyle.formBadge}>
122
+ {selected[0] === '' ? '0' : selected.length}
123
+ </Badge>
124
+ )}
121
125
  </Box>
122
126
  {(withSearch || isAsync) && (
123
127
  <SearchInput
@@ -7,6 +7,7 @@ import ListItem from '../List/ListItem';
7
7
  import Box, { BoxProps } from '../Box/Box';
8
8
  import Divider from '../Divider/Divider';
9
9
  import Text from '../Text/Text';
10
+ import CodeBlock from '../CodeBlock/CodeBlock';
10
11
  import CodeSnippet from '../CodeSnippet/CodeSnippet';
11
12
 
12
13
  type GapType = Exclude<BoxProps['gap'], undefined>;
@@ -30,7 +31,7 @@ const defaultComponents = (size: 'sm' | 'md' | 'lg', gap: GapType = '16'): Compo
30
31
  </Box>
31
32
  ),
32
33
  code: ({ node, ...props }) => (
33
- <CodeSnippet variant="multi" {...props}>
34
+ <CodeSnippet size={codeSize} {...props}>
34
35
  {props.children as string}
35
36
  </CodeSnippet>
36
37
  ),
@@ -44,11 +45,7 @@ const defaultComponents = (size: 'sm' | 'md' | 'lg', gap: GapType = '16'): Compo
44
45
  li: ({ node, ...props }) => <ListItem {...props} />,
45
46
  ol: ({ node, ...props }) => <List isOrdered {...props} />,
46
47
  p: ({ node, ...props }) => <Text {...props} />,
47
- pre: ({ node, ...props }) => (
48
- <CodeSnippet variant="multi" size={codeSize}>
49
- {props.children as string}
50
- </CodeSnippet>
51
- ),
48
+ pre: ({ node, ...props }) => <CodeBlock size={codeSize}>{props.children as string}</CodeBlock>,
52
49
  ul: ({ node, ...props }) => <List {...props} />,
53
50
  };
54
51
  };
@@ -38,6 +38,7 @@ import SidebarItem from './Sidebar/SidebarItem.theme';
38
38
  import SegmentedControl from './SegmentedControl/SegmentedControl.theme';
39
39
  import Tag from './Tag/Tag.theme';
40
40
  import Note from './Note/Note.theme';
41
+ import CodeBlock from './CodeBlock/CodeBlock.theme';
41
42
  import CodeSnippet from './CodeSnippet/CodeSnippet.theme';
42
43
  import DefinitionTooltip from './DefinitionTooltip/DefinitionTooltip.theme';
43
44
  import ExpandableCard from './ExpandableCard/ExpandableCard.theme';
@@ -65,6 +66,7 @@ const components = {
65
66
  ...Form,
66
67
  Alert,
67
68
  CloseButton,
69
+ CodeBlock,
68
70
  CodeSnippet,
69
71
  DatePickerDay,
70
72
  DefinitionTooltip,
package/src/index.ts CHANGED
@@ -283,6 +283,7 @@ export { default as Tag } from './Components/Tag/Tag';
283
283
  export type { NoteProps } from './Components/Note/Note';
284
284
  export { default as Note } from './Components/Note/Note';
285
285
  export { default as MarkdownContent } from './Components/Note/NoteMarkdownContent';
286
+ export { default as CodeBlock } from './Components/CodeBlock/CodeBlock';
286
287
  export { default as CodeSnippet } from './Components/CodeSnippet/CodeSnippet';
287
288
 
288
289
  export type { DefinitionTooltipProps } from './Components/DefinitionTooltip/DefinitionTooltip';