@bitrise/bitkit 13.93.0 → 13.95.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 +21 -21
- package/src/Components/Filter/Filter.tsx +11 -5
- package/src/Components/Filter/FilterDate/FilterDate.tsx +4 -7
- package/src/Components/Filter/FilterItem/FilterItem.tsx +1 -1
- package/src/Components/Filter/FilterSearch/FilterSearch.tsx +8 -4
- package/src/Components/SelectableTag/SelectableTag.theme.ts +35 -0
- package/src/Components/SelectableTag/SelectableTag.tsx +21 -0
- package/src/Components/SelectableTag/SelectableTagGroup.tsx +27 -0
- package/src/Components/Tabs/Tabs.tsx +2 -1
- package/src/Components/components.theme.ts +2 -0
- package/src/index.ts +6 -0
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.
|
|
4
|
+
"version": "13.95.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+ssh://git@github.com/bitrise-io/bitkit.git"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@floating-ui/react-dom-interactions": "^0.8.1",
|
|
39
39
|
"@fontsource/figtree": "^5.0.20",
|
|
40
40
|
"@fontsource/source-code-pro": "^5.0.18",
|
|
41
|
-
"framer-motion": "^11.2.
|
|
41
|
+
"framer-motion": "^11.2.11",
|
|
42
42
|
"luxon": "^3.4.4",
|
|
43
43
|
"react": "^18.3.1",
|
|
44
44
|
"react-dom": "^18.3.1",
|
|
@@ -57,38 +57,38 @@
|
|
|
57
57
|
"@babel/preset-typescript": "^7.24.7",
|
|
58
58
|
"@bitrise/eslint-plugin": "^2.12.0",
|
|
59
59
|
"@chakra-ui/cli": "^2.4.1",
|
|
60
|
-
"@google-cloud/storage": "^7.11.
|
|
61
|
-
"@storybook/addon-actions": "^8.1.
|
|
62
|
-
"@storybook/addon-essentials": "^8.1.
|
|
63
|
-
"@storybook/addon-interactions": "^8.1.
|
|
64
|
-
"@storybook/addon-links": "^8.1.
|
|
65
|
-
"@storybook/addon-webpack5-compiler-swc": "^1.0.
|
|
66
|
-
"@storybook/blocks": "^8.1.
|
|
67
|
-
"@storybook/react": "^8.1.
|
|
68
|
-
"@storybook/react-webpack5": "^8.1.
|
|
69
|
-
"@storybook/theming": "^8.1.
|
|
60
|
+
"@google-cloud/storage": "^7.11.2",
|
|
61
|
+
"@storybook/addon-actions": "^8.1.10",
|
|
62
|
+
"@storybook/addon-essentials": "^8.1.10",
|
|
63
|
+
"@storybook/addon-interactions": "^8.1.10",
|
|
64
|
+
"@storybook/addon-links": "^8.1.10",
|
|
65
|
+
"@storybook/addon-webpack5-compiler-swc": "^1.0.4",
|
|
66
|
+
"@storybook/blocks": "^8.1.10",
|
|
67
|
+
"@storybook/react": "^8.1.10",
|
|
68
|
+
"@storybook/react-webpack5": "^8.1.10",
|
|
69
|
+
"@storybook/theming": "^8.1.10",
|
|
70
70
|
"@testing-library/dom": "^10.1.0",
|
|
71
|
-
"@testing-library/jest-dom": "^6.4.
|
|
71
|
+
"@testing-library/jest-dom": "^6.4.6",
|
|
72
72
|
"@testing-library/react": "^16.0.0",
|
|
73
73
|
"@testing-library/user-event": "^14.5.2",
|
|
74
74
|
"@types/jest": "^29.5.12",
|
|
75
75
|
"@types/luxon": "^3.4.2",
|
|
76
76
|
"@types/react": "^18.3.3",
|
|
77
77
|
"@types/react-dom": "^18.3.0",
|
|
78
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
79
|
-
"@typescript-eslint/parser": "^7.
|
|
78
|
+
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
|
79
|
+
"@typescript-eslint/parser": "^7.13.1",
|
|
80
80
|
"axios": "^1.7.2",
|
|
81
81
|
"eslint": "^8.57.0",
|
|
82
|
-
"glob": "^10.4.
|
|
82
|
+
"glob": "^10.4.2",
|
|
83
83
|
"jest": "^29.7.0",
|
|
84
84
|
"jest-environment-jsdom": "^29.7.0",
|
|
85
85
|
"jsdom": "^24.1.0",
|
|
86
|
-
"prettier": "^3.3.
|
|
87
|
-
"react-hook-form": "^7.
|
|
86
|
+
"prettier": "^3.3.2",
|
|
87
|
+
"react-hook-form": "^7.52.0",
|
|
88
88
|
"release-it": "^17.3.0",
|
|
89
|
-
"storybook": "^8.1.
|
|
90
|
-
"ts-jest": "^29.1.
|
|
91
|
-
"typescript": "^5.
|
|
89
|
+
"storybook": "^8.1.10",
|
|
90
|
+
"ts-jest": "^29.1.5",
|
|
91
|
+
"typescript": "^5.5.2"
|
|
92
92
|
},
|
|
93
93
|
"files": [
|
|
94
94
|
"src",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode, useMemo, useState } from 'react';
|
|
2
2
|
import { Modal, ModalOverlay, useMultiStyleConfig } from '@chakra-ui/react';
|
|
3
3
|
import { isEqual } from '../../utils/utils';
|
|
4
4
|
import Box, { BoxProps } from '../Box/Box';
|
|
@@ -28,6 +28,7 @@ export interface FilterProps extends Omit<BoxProps, 'onChange'> {
|
|
|
28
28
|
filtersDependOn?: string[];
|
|
29
29
|
isLoading?: boolean;
|
|
30
30
|
onChange: (state: FilterState) => void;
|
|
31
|
+
searchTooltip?: ReactNode;
|
|
31
32
|
showAdd?: boolean;
|
|
32
33
|
showFilterIcon?: boolean;
|
|
33
34
|
showSearch?: boolean;
|
|
@@ -41,6 +42,7 @@ const Filter = (props: FilterProps) => {
|
|
|
41
42
|
filtersDependOn,
|
|
42
43
|
isLoading,
|
|
43
44
|
onChange,
|
|
45
|
+
searchTooltip,
|
|
44
46
|
showAdd = true,
|
|
45
47
|
showFilterIcon = true,
|
|
46
48
|
showSearch,
|
|
@@ -61,7 +63,7 @@ const Filter = (props: FilterProps) => {
|
|
|
61
63
|
}
|
|
62
64
|
});
|
|
63
65
|
|
|
64
|
-
const stateToRestore =
|
|
66
|
+
const stateToRestore = useMemo<FilterState>(() => defaultState || cleanState, [defaultState, cleanState]);
|
|
65
67
|
|
|
66
68
|
const [isPopoverOpen, setPopoverOpen] = useState<boolean>(false);
|
|
67
69
|
|
|
@@ -99,7 +101,7 @@ const Filter = (props: FilterProps) => {
|
|
|
99
101
|
};
|
|
100
102
|
|
|
101
103
|
const onClearFilters = () => {
|
|
102
|
-
onChange(stateToRestore
|
|
104
|
+
onChange(stateToRestore || {});
|
|
103
105
|
};
|
|
104
106
|
|
|
105
107
|
const filters = {
|
|
@@ -114,7 +116,7 @@ const Filter = (props: FilterProps) => {
|
|
|
114
116
|
filters[value.type || 'tag'][category] = value;
|
|
115
117
|
});
|
|
116
118
|
|
|
117
|
-
const showClearFilters = !isEqual(stateToRestore
|
|
119
|
+
const showClearFilters = !isEqual(stateToRestore, state);
|
|
118
120
|
|
|
119
121
|
const contextValue: FilterContextType = useMemo(
|
|
120
122
|
() => ({
|
|
@@ -175,7 +177,11 @@ const Filter = (props: FilterProps) => {
|
|
|
175
177
|
{showSearch && (
|
|
176
178
|
<>
|
|
177
179
|
<Divider flexShrink="0" orientation="vertical" size="1" variant="solid" />
|
|
178
|
-
<FilterSearch
|
|
180
|
+
<FilterSearch
|
|
181
|
+
onChange={onFilterChange}
|
|
182
|
+
value={cleanState.search?.length ? cleanState.search[0] : ''}
|
|
183
|
+
searchTooltip={searchTooltip}
|
|
184
|
+
/>
|
|
179
185
|
</>
|
|
180
186
|
)}
|
|
181
187
|
</Box>
|
|
@@ -6,7 +6,6 @@ import Box from '../../Box/Box';
|
|
|
6
6
|
import DatePicker, { DateRange, useDateRange } from '../../DatePicker/DatePicker';
|
|
7
7
|
import Icon from '../../Icon/Icon';
|
|
8
8
|
import Text from '../../Text/Text';
|
|
9
|
-
import Tooltip from '../../Tooltip/Tooltip';
|
|
10
9
|
import { useFilterContext } from '../Filter.context';
|
|
11
10
|
import { FilterStyle } from '../Filter.theme';
|
|
12
11
|
|
|
@@ -65,12 +64,10 @@ const FilterDate = (props: FilterDateProps) => {
|
|
|
65
64
|
mode="range"
|
|
66
65
|
>
|
|
67
66
|
<Box position={isOpen ? 'relative' : undefined} sx={filterStyle.item} zIndex={isOpen ? 'dialog' : undefined}>
|
|
68
|
-
<
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</Text>
|
|
73
|
-
</Tooltip>
|
|
67
|
+
<Text as="button" disabled={isLoading} onClick={onToggle} size="2" sx={filterStyle.tagEdit}>
|
|
68
|
+
<Icon color="neutral.60" name="Calendar" size="16" /> {label}
|
|
69
|
+
<Icon name="ChevronDown" size="16" />
|
|
70
|
+
</Text>
|
|
74
71
|
</Box>
|
|
75
72
|
</DatePicker>
|
|
76
73
|
);
|
|
@@ -67,7 +67,7 @@ const FilterItem = (props: FilterItemProps) => {
|
|
|
67
67
|
<Popover isLazy isOpen={isOpen} onClose={onClose}>
|
|
68
68
|
<PopoverTrigger>
|
|
69
69
|
<Box position={isOpen ? 'relative' : undefined} sx={filterStyle.item} zIndex={isOpen ? 'dialog' : undefined}>
|
|
70
|
-
<Tooltip isDisabled={isLoading} label="Edit">
|
|
70
|
+
<Tooltip isDisabled={isLoading || type !== 'tag'} label="Edit">
|
|
71
71
|
<Text as="button" disabled={isLoading} onClick={onToggle} size="2" sx={filterStyle.tagEdit}>
|
|
72
72
|
{getText()}
|
|
73
73
|
{type === 'select' && <Icon name="ChevronDown" size="16" />}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChangeEvent, useEffect, useState } from 'react';
|
|
1
|
+
import { ChangeEvent, ReactNode, useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Input,
|
|
4
4
|
InputGroup,
|
|
@@ -9,16 +9,18 @@ import {
|
|
|
9
9
|
} from '@chakra-ui/react';
|
|
10
10
|
import Icon from '../../Icon/Icon';
|
|
11
11
|
import IconButton from '../../IconButton/IconButton';
|
|
12
|
+
import Tooltip from '../../Tooltip/Tooltip';
|
|
12
13
|
import { FilterStyle } from '../Filter.theme';
|
|
13
14
|
import { FilterValue } from '../Filter.types';
|
|
14
15
|
|
|
15
16
|
export interface FilterSearchProps extends Omit<InputProps, 'onChange' | 'value'> {
|
|
16
17
|
onChange: (category: string, selected: FilterValue) => void;
|
|
18
|
+
searchTooltip?: ReactNode;
|
|
17
19
|
value: string;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
const FilterSearch = (props: FilterSearchProps) => {
|
|
21
|
-
const { onChange, value, ...rest } = props;
|
|
23
|
+
const { onChange, placeholder, searchTooltip, value, ...rest } = props;
|
|
22
24
|
const filterStyle = useMultiStyleConfig('Filter') as FilterStyle;
|
|
23
25
|
|
|
24
26
|
const [searchValue, setSearchValue] = useState(value);
|
|
@@ -44,7 +46,7 @@ const FilterSearch = (props: FilterSearchProps) => {
|
|
|
44
46
|
|
|
45
47
|
const inputProps: InputProps = {
|
|
46
48
|
onChange: onInputChange,
|
|
47
|
-
placeholder: 'Search...',
|
|
49
|
+
placeholder: placeholder || 'Search...',
|
|
48
50
|
sx: filterStyle.searchInput,
|
|
49
51
|
value: searchValue,
|
|
50
52
|
...rest,
|
|
@@ -54,7 +56,9 @@ const FilterSearch = (props: FilterSearchProps) => {
|
|
|
54
56
|
<InputLeftElement margin="8">
|
|
55
57
|
<Icon color="neutral.60" name="Magnifier" size="16" />
|
|
56
58
|
</InputLeftElement>
|
|
57
|
-
<
|
|
59
|
+
<Tooltip isDisabled={!searchTooltip} label={searchTooltip}>
|
|
60
|
+
<Input {...inputProps} />
|
|
61
|
+
</Tooltip>
|
|
58
62
|
{!!searchValue && (
|
|
59
63
|
<InputRightElement>
|
|
60
64
|
<IconButton aria-label="Clear" iconName="CloseSmall" onClick={onClearClick} size="sm" variant="tertiary" />
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineStyleConfig } from '@chakra-ui/styled-system';
|
|
2
|
+
import tokensToTheme from '../../tokens/tokensToTheme.json';
|
|
3
|
+
|
|
4
|
+
const SelectableTagTheme = defineStyleConfig({
|
|
5
|
+
baseStyle: {
|
|
6
|
+
px: '8',
|
|
7
|
+
py: '4',
|
|
8
|
+
cursor: 'pointer',
|
|
9
|
+
display: 'inline',
|
|
10
|
+
border: '1px solid',
|
|
11
|
+
whiteSpace: 'nowrap',
|
|
12
|
+
borderColor: 'border.strong',
|
|
13
|
+
borderRadius: '4',
|
|
14
|
+
backgroundColor: 'background.primary',
|
|
15
|
+
_hover: {
|
|
16
|
+
backgroundColor: 'background.hover',
|
|
17
|
+
_peerChecked: {
|
|
18
|
+
backgroundColor: 'background.selected-hover',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
_peerChecked: {
|
|
22
|
+
borderColor: 'border.selected',
|
|
23
|
+
backgroundColor: 'background.selected',
|
|
24
|
+
},
|
|
25
|
+
_peerFocusVisible: {
|
|
26
|
+
backgroundColor: 'background.hover',
|
|
27
|
+
_checked: {
|
|
28
|
+
backgroundColor: 'background.selected-hover',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
...tokensToTheme.textStyles['comp/tag/sm'],
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default SelectableTagTheme;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { UseCheckboxProps, chakra, forwardRef, useCheckbox, useStyleConfig } from '@chakra-ui/react';
|
|
3
|
+
import Text from '../Text/Text';
|
|
4
|
+
|
|
5
|
+
export interface SelectableTagProps extends PropsWithChildren<UseCheckboxProps> {}
|
|
6
|
+
|
|
7
|
+
const SelectableTag = forwardRef(({ children, ...props }: SelectableTagProps, ref) => {
|
|
8
|
+
const theme = useStyleConfig('SelectableTag');
|
|
9
|
+
const { htmlProps, getInputProps, getLabelProps } = useCheckbox(props);
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<chakra.label {...htmlProps}>
|
|
13
|
+
<input className="peer" {...getInputProps({}, ref)} />
|
|
14
|
+
<Text as="span" {...getLabelProps()} sx={theme}>
|
|
15
|
+
{children}
|
|
16
|
+
</Text>
|
|
17
|
+
</chakra.label>
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export default SelectableTag;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ReactElement, Children, cloneElement, isValidElement } from 'react';
|
|
2
|
+
import { useCheckboxGroup } from '@chakra-ui/react';
|
|
3
|
+
import CheckboxGroup, { CheckboxGroupProps } from '../Form/Checkbox/CheckboxGroup';
|
|
4
|
+
import { SelectableTagProps } from './SelectableTag';
|
|
5
|
+
|
|
6
|
+
export interface SelectableTagGroupProps extends CheckboxGroupProps {
|
|
7
|
+
children: ReactElement<SelectableTagProps> | ReactElement<SelectableTagProps>[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const SelectableTagGroup = ({ children, ...props }: SelectableTagGroupProps) => {
|
|
11
|
+
const { getCheckboxProps } = useCheckboxGroup(props);
|
|
12
|
+
|
|
13
|
+
const clonedChildren = Children.map(children, (child: ReactElement<SelectableTagProps>) => {
|
|
14
|
+
if (isValidElement(child)) {
|
|
15
|
+
return cloneElement(child, {
|
|
16
|
+
...child.props,
|
|
17
|
+
...getCheckboxProps({ value: child.props.value }),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return child;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return <CheckboxGroup {...props}>{clonedChildren}</CheckboxGroup>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default SelectableTagGroup;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { isValidElement, ReactElement, useEffect, useState } from 'react';
|
|
2
2
|
import { forwardRef, Tabs as ChakraTabs, TabsProps as ChakraTabsProps } from '@chakra-ui/react';
|
|
3
3
|
import { useHistory } from '../../hooks';
|
|
4
|
+
import { TabProps } from './Tab';
|
|
4
5
|
|
|
5
6
|
export interface TabsProps extends ChakraTabsProps {
|
|
6
7
|
defaultTab?: string;
|
|
@@ -14,7 +15,7 @@ const getTabIds = (props: TabsProps): string[] => {
|
|
|
14
15
|
const tabList = React.Children.toArray(props.children)[0] as ReactElement;
|
|
15
16
|
const tabs = React.Children.toArray(tabList.props.children) as ReactElement[];
|
|
16
17
|
|
|
17
|
-
return tabs.filter((item) => isValidElement(item)).map((item) => item.props.id);
|
|
18
|
+
return tabs.filter((item) => isValidElement(item)).map((item) => (item.props as TabProps).id || '');
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const getTabIndexFromSearchParams = (tabIds: string[], tabIndex?: number) => {
|
|
@@ -47,6 +47,7 @@ import Toggletip from './Toggletip/Toggletip.theme';
|
|
|
47
47
|
import FilterSwitch from './Filter/FilterSwitch/FilterSwitch.theme';
|
|
48
48
|
import TagsInput from './Form/TagsInput/TagsInput.theme';
|
|
49
49
|
import DraggableCard from './DraggableCard/DraggableCard.theme';
|
|
50
|
+
import SelectableTag from './SelectableTag/SelectableTag.theme';
|
|
50
51
|
|
|
51
52
|
const components = {
|
|
52
53
|
Accordion,
|
|
@@ -85,6 +86,7 @@ const components = {
|
|
|
85
86
|
Radio,
|
|
86
87
|
SegmentedControl,
|
|
87
88
|
Select,
|
|
89
|
+
SelectableTag,
|
|
88
90
|
Sidebar,
|
|
89
91
|
SidebarItem,
|
|
90
92
|
Skeleton,
|
package/src/index.ts
CHANGED
|
@@ -329,3 +329,9 @@ export { default as DraggableCard } from './Components/DraggableCard/DraggableCa
|
|
|
329
329
|
|
|
330
330
|
export type { ControlButtonProps } from './Components/ControlButton/ControlButton';
|
|
331
331
|
export { default as ControlButton } from './Components/ControlButton/ControlButton';
|
|
332
|
+
|
|
333
|
+
export type { SelectableTagProps } from './Components/SelectableTag/SelectableTag';
|
|
334
|
+
export { default as SelectableTag } from './Components/SelectableTag/SelectableTag';
|
|
335
|
+
|
|
336
|
+
export type { SelectableTagGroupProps } from './Components/SelectableTag/SelectableTagGroup';
|
|
337
|
+
export { default as SelectableTagGroup } from './Components/SelectableTag/SelectableTagGroup';
|