@bitrise/bitkit 13.9.0 → 13.10.1-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.9.0",
4
+ "version": "13.10.1-alpha.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.18",
40
40
  "@fontsource/source-code-pro": "^5.0.16",
41
- "framer-motion": "^11.0.6",
41
+ "framer-motion": "^11.0.8",
42
42
  "luxon": "^3.4.4",
43
43
  "react": "^18.2.0",
44
44
  "react-dom": "^18.2.0",
@@ -51,8 +51,8 @@
51
51
  "react-dom": "^18.2.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@babel/core": "^7.23.9",
55
- "@babel/preset-env": "^7.23.9",
54
+ "@babel/core": "^7.24.0",
55
+ "@babel/preset-env": "^7.24.0",
56
56
  "@babel/preset-react": "^7.23.3",
57
57
  "@babel/preset-typescript": "^7.23.3",
58
58
  "@bitrise/eslint-plugin": "^2.7.0",
@@ -73,7 +73,7 @@
73
73
  "@testing-library/user-event": "^14.5.2",
74
74
  "@types/jest": "^29.5.12",
75
75
  "@types/luxon": "^3.4.2",
76
- "@types/react": "^18.2.60",
76
+ "@types/react": "^18.2.61",
77
77
  "@types/react-dom": "^18.2.19",
78
78
  "@typescript-eslint/eslint-plugin": "^7.1.0",
79
79
  "@typescript-eslint/parser": "^7.1.0",
@@ -0,0 +1,37 @@
1
+ import type { ComponentStyleConfig } from '@chakra-ui/theme';
2
+
3
+ const AccordionTheme: ComponentStyleConfig = {
4
+ baseStyle: {
5
+ button: {
6
+ _hover: {
7
+ background: 'background/hover',
8
+ },
9
+ _active: {
10
+ background: 'background/active',
11
+ },
12
+ alignItems: 'center',
13
+ display: 'flex',
14
+ justifyContent: 'space-between',
15
+ padding: '16',
16
+ width: '100%',
17
+ },
18
+ icon: {
19
+ height: '24',
20
+ marginLeft: '16',
21
+ width: '24',
22
+ },
23
+ item: {
24
+ borderTop: '1px solid',
25
+ borderTopColor: 'border/regular',
26
+ },
27
+ panel: {
28
+ padding: '16',
29
+ },
30
+ root: {
31
+ borderBottom: '1px solid',
32
+ borderBottomColor: 'border/regular',
33
+ },
34
+ },
35
+ };
36
+
37
+ export default AccordionTheme;
@@ -92,7 +92,7 @@ export const FILTER_STORY_DATA: FilterData = {
92
92
  export const FILTER_STORY_INIT_STATE: FilterState = {
93
93
  app: ['46b6b9a78a418ee8'],
94
94
  cache_type: ['gradle'],
95
- pipeline: ['ipsum', 'dolor'],
95
+ pipeline: ['ipsum'],
96
96
  };
97
97
 
98
98
  export const FILTER_STORY_CONTEXT: FilterContextType = {
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { Modal, ModalOverlay, useMultiStyleConfig } from '@chakra-ui/react';
3
+ import { isEqual } from '../../utils/utils';
3
4
  import Box, { BoxProps } from '../Box/Box';
4
5
  import Button from '../Button/Button';
5
6
  import Divider from '../Divider/Divider';
@@ -45,7 +46,7 @@ const Filter = (props: FilterProps) => {
45
46
  ...rest
46
47
  } = props;
47
48
 
48
- const isInited = useRef<boolean>(false);
49
+ const initialState = useRef<FilterState>();
49
50
 
50
51
  const filterStyle = useMultiStyleConfig('Filter') as FilterStyle;
51
52
 
@@ -76,9 +77,6 @@ const Filter = (props: FilterProps) => {
76
77
  };
77
78
 
78
79
  const onFilterChange = (category: string, value: FilterValue) => {
79
- if (isInited.current === false) {
80
- return;
81
- }
82
80
  let newState = { ...cleanState };
83
81
  if (value && value.length > 0) {
84
82
  newState[category] = value;
@@ -99,7 +97,7 @@ const Filter = (props: FilterProps) => {
99
97
  };
100
98
 
101
99
  const onClearFilters = () => {
102
- onChange({});
100
+ onChange(initialState.current || {});
103
101
  };
104
102
 
105
103
  const filters = {
@@ -114,9 +112,7 @@ const Filter = (props: FilterProps) => {
114
112
  filters[value.type || 'tag'][category] = value;
115
113
  });
116
114
 
117
- const stateCategories = Object.keys(cleanState).filter((c) => !['date_range', 'search'].includes(c));
118
-
119
- const showClearFilters = stateCategories.length > 0 || (cleanState.search && cleanState.search.length > 0);
115
+ const showClearFilters = initialState.current && !isEqual(initialState.current, state);
120
116
 
121
117
  const contextValue: FilterContextType = useMemo(
122
118
  () => ({
@@ -132,10 +128,10 @@ const Filter = (props: FilterProps) => {
132
128
  );
133
129
 
134
130
  useEffect(() => {
135
- if (isInited.current === false) {
136
- isInited.current = true;
131
+ if (!initialState.current) {
132
+ initialState.current = cleanState;
137
133
  }
138
- }, [isInited.current]);
134
+ }, []);
139
135
 
140
136
  return (
141
137
  <FilterContext value={contextValue}>
@@ -183,7 +179,7 @@ const Filter = (props: FilterProps) => {
183
179
  {showSearch && (
184
180
  <>
185
181
  <Divider flexShrink="0" orientation="vertical" size="1" variant="solid" />
186
- <FilterSearch onChange={onFilterChange} value={(cleanState.search && cleanState.search[0]) || ''} />
182
+ <FilterSearch onChange={onFilterChange} value={cleanState.search?.length ? cleanState.search[0] : ''} />
187
183
  </>
188
184
  )}
189
185
  </Box>
@@ -7,7 +7,6 @@ import {
7
7
  InputRightElement,
8
8
  useMultiStyleConfig,
9
9
  } from '@chakra-ui/react';
10
- import { useDebounce } from '../../../utils/utils';
11
10
  import Icon from '../../Icon/Icon';
12
11
  import IconButton from '../../IconButton/IconButton';
13
12
  import { FilterStyle } from '../Filter.theme';
@@ -23,7 +22,6 @@ const FilterSearch = (props: FilterSearchProps) => {
23
22
  const filterStyle = useMultiStyleConfig('Filter') as FilterStyle;
24
23
 
25
24
  const [searchValue, setSearchValue] = useState(value);
26
- const debouncedSearchValue = useDebounce<string>(searchValue, 500);
27
25
 
28
26
  const onInputChange = (event: ChangeEvent<HTMLInputElement>) => {
29
27
  setSearchValue(event.currentTarget.value);
@@ -34,8 +32,11 @@ const FilterSearch = (props: FilterSearchProps) => {
34
32
  };
35
33
 
36
34
  useEffect(() => {
37
- onChange('search', debouncedSearchValue.length ? [debouncedSearchValue] : []);
38
- }, [debouncedSearchValue]);
35
+ const delayInputTimeoutId = setTimeout(() => {
36
+ onChange('search', searchValue.length ? [searchValue] : []);
37
+ }, 500);
38
+ return () => clearTimeout(delayInputTimeoutId);
39
+ }, [searchValue, 500]);
39
40
 
40
41
  useEffect(() => {
41
42
  setSearchValue(value);
@@ -1,4 +1,5 @@
1
1
  import Alert from './Alert/Alert.theme';
2
+ import Accordion from './Accordion/Accordion.theme';
2
3
  import Avatar from './Avatar/Avatar.theme';
3
4
  import Badge from './Badge/Badge.theme';
4
5
  import Breadcrumb from './Breadcrumb/Breadcrumb.theme';
@@ -48,6 +49,7 @@ import FilterSwitch from './Filter/FilterSwitch/FilterSwitch.theme';
48
49
  import TagsInput from './Form/TagsInput/TagsInput.theme';
49
50
 
50
51
  const components = {
52
+ Accordion,
51
53
  Avatar,
52
54
  Badge,
53
55
  Breadcrumb,
@@ -15,10 +15,24 @@ export function useObjectMemo<T extends object>(obj: T): T {
15
15
  }, Object.values(obj));
16
16
  }
17
17
 
18
- export function isEqual(a: number | string | number[] | string[], b: number | string | number[] | string[]) {
18
+ export function isEqual(a: any, b: any) {
19
19
  if (Array.isArray(a) && Array.isArray(b)) {
20
20
  return a.length === b.length && [...a].every((val) => [...b].includes(val));
21
21
  }
22
+ if (typeof a === 'object' && typeof b === 'object') {
23
+ let isEqualObjects = true;
24
+ Object.keys(a).forEach((key: any) => {
25
+ if (!isEqual(a[key], b[key])) {
26
+ isEqualObjects = false;
27
+ }
28
+ });
29
+ Object.keys(b).forEach((key: any) => {
30
+ if (!isEqual(b[key], a[key])) {
31
+ isEqualObjects = false;
32
+ }
33
+ });
34
+ return isEqualObjects;
35
+ }
22
36
  return a === b;
23
37
  }
24
38