@bitrise/bitkit 13.187.0 → 13.188.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 +1 -1
- package/src/Components/Dropdown/Dropdown.context.tsx +2 -0
- package/src/Components/Dropdown/Dropdown.theme.ts +17 -11
- package/src/Components/Dropdown/Dropdown.tsx +17 -3
- package/src/Components/Dropdown/DropdownButton.tsx +4 -0
- package/src/Components/Dropdown/DropdownOption.tsx +13 -2
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ComponentProps, ReactNode } from 'react';
|
|
2
2
|
import { createStylesContext } from '@chakra-ui/react';
|
|
3
3
|
import { createContext } from '@chakra-ui/react-utils';
|
|
4
|
+
import { DropdownProps } from './DropdownProps';
|
|
4
5
|
|
|
5
6
|
const [DropdownStylesProvider, useDropdownStyles] = createStylesContext('Dropdown');
|
|
6
7
|
|
|
@@ -17,6 +18,7 @@ type DropdownContext<T> = {
|
|
|
17
18
|
filter?: string;
|
|
18
19
|
activeIndex?: number | null;
|
|
19
20
|
getItemProps: (userProps?: React.HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
|
|
21
|
+
size: DropdownProps<unknown>['size'];
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const [DropdownContextProvider, useDropdownContext] = createContext<DropdownContext<unknown>>();
|
|
@@ -4,6 +4,7 @@ import { DropdownProps } from './DropdownProps';
|
|
|
4
4
|
type DropdownStateProps = Pick<DropdownProps<string | null>, 'disabled' | 'readOnly' | 'isWarning' | 'isError'> & {
|
|
5
5
|
placeholder: boolean;
|
|
6
6
|
isOpen: boolean;
|
|
7
|
+
hasAvatar: boolean;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
const getCursor = ({ readOnly, disabled }: DropdownStateProps) => {
|
|
@@ -68,7 +69,7 @@ const getButtonContentColor = ({ disabled, placeholder }: DropdownStateProps) =>
|
|
|
68
69
|
|
|
69
70
|
const DropdownTheme = {
|
|
70
71
|
baseStyle: (props: DropdownStateProps) => {
|
|
71
|
-
const { disabled, readOnly, isError } = props;
|
|
72
|
+
const { disabled, readOnly, hasAvatar, isError } = props;
|
|
72
73
|
return {
|
|
73
74
|
field: {
|
|
74
75
|
_hover:
|
|
@@ -128,7 +129,8 @@ const DropdownTheme = {
|
|
|
128
129
|
},
|
|
129
130
|
color: 'purple.10',
|
|
130
131
|
cursor: 'pointer',
|
|
131
|
-
|
|
132
|
+
paddingLeft: hasAvatar ? '12' : '16',
|
|
133
|
+
paddingRight: '24',
|
|
132
134
|
paddingY: '8',
|
|
133
135
|
textAlign: 'start',
|
|
134
136
|
userSelect: 'none',
|
|
@@ -151,7 +153,7 @@ const DropdownTheme = {
|
|
|
151
153
|
options: {
|
|
152
154
|
flexShrink: 1,
|
|
153
155
|
overflowY: 'auto',
|
|
154
|
-
paddingY: '
|
|
156
|
+
paddingY: '8',
|
|
155
157
|
position: 'relative',
|
|
156
158
|
},
|
|
157
159
|
search: {
|
|
@@ -162,22 +164,26 @@ const DropdownTheme = {
|
|
|
162
164
|
};
|
|
163
165
|
},
|
|
164
166
|
sizes: {
|
|
165
|
-
lg: {
|
|
167
|
+
lg: ({ hasAvatar }: DropdownStateProps) => ({
|
|
166
168
|
field: {
|
|
167
169
|
fontSize: '3',
|
|
168
|
-
gap: '
|
|
170
|
+
gap: rem('8'),
|
|
169
171
|
height: '48',
|
|
170
|
-
paddingLeft: rem('
|
|
171
|
-
paddingRight: rem('
|
|
172
|
+
paddingLeft: hasAvatar ? rem('12') : rem('16'),
|
|
173
|
+
paddingRight: rem('16'),
|
|
172
174
|
},
|
|
173
|
-
},
|
|
175
|
+
}),
|
|
174
176
|
md: {
|
|
175
177
|
field: {
|
|
176
178
|
fontSize: '2',
|
|
177
|
-
gap: '
|
|
179
|
+
gap: rem('8'),
|
|
178
180
|
height: '40',
|
|
179
|
-
paddingLeft: rem('
|
|
180
|
-
paddingRight: rem('
|
|
181
|
+
paddingLeft: rem('12'),
|
|
182
|
+
paddingRight: rem('12'),
|
|
183
|
+
},
|
|
184
|
+
item: {
|
|
185
|
+
fontSize: '2',
|
|
186
|
+
paddingLeft: rem('12'),
|
|
181
187
|
},
|
|
182
188
|
},
|
|
183
189
|
},
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
import { FloatingFocusManager } from '@floating-ui/react-dom-interactions';
|
|
21
21
|
import SearchInput from '../SearchInput/SearchInput';
|
|
22
22
|
import FormLabel from '../Form/FormLabel';
|
|
23
|
+
import { AvatarProps } from '../Avatar/Avatar';
|
|
23
24
|
import { DropdownEventArgs, DropdownProvider, useDropdownContext, useDropdownStyles } from './Dropdown.context';
|
|
24
25
|
import { DropdownDetailedOption, DropdownGroup, DropdownOption, DropdownOptionProps } from './DropdownOption';
|
|
25
26
|
import DropdownButton from './DropdownButton';
|
|
@@ -112,14 +113,17 @@ type UseDropdownProps = {
|
|
|
112
113
|
optionsRef: React.RefObject<HTMLDivElement>;
|
|
113
114
|
};
|
|
114
115
|
|
|
115
|
-
function findOption<T>(
|
|
116
|
+
function findOption<T>(
|
|
117
|
+
children: ReactNode,
|
|
118
|
+
value: T,
|
|
119
|
+
): { label: ReactNode; index: number; avatar?: AvatarProps } | null {
|
|
116
120
|
const list = React.Children.toArray(children);
|
|
117
121
|
for (let i = 0; i < list.length; i++) {
|
|
118
122
|
const elem = list[i];
|
|
119
123
|
if (React.isValidElement(elem) && !elem.props.isDisabled) {
|
|
120
124
|
const optValue = typeof elem.props.value === 'undefined' ? null : elem.props.value;
|
|
121
125
|
if (elem.type === DropdownOption && optValue === value) {
|
|
122
|
-
return { index: elem.props.index, label: elem.props.children };
|
|
126
|
+
return { index: elem.props.index, label: elem.props.children, avatar: elem.props.avatar };
|
|
123
127
|
}
|
|
124
128
|
const ch =
|
|
125
129
|
findOption(elem.props.children, value) || (isSearchable(elem.type) && findOption(elem.type(elem.props), value));
|
|
@@ -141,6 +145,7 @@ function useDropdown<T>({
|
|
|
141
145
|
placement = 'bottom-start',
|
|
142
146
|
readOnly,
|
|
143
147
|
ref,
|
|
148
|
+
size,
|
|
144
149
|
value,
|
|
145
150
|
...rest
|
|
146
151
|
}: DropdownProps<T> & UseDropdownProps) {
|
|
@@ -162,8 +167,8 @@ function useDropdown<T>({
|
|
|
162
167
|
onChange: (newValue) => onChange?.({ target: { name, value: newValue } }),
|
|
163
168
|
value,
|
|
164
169
|
});
|
|
165
|
-
|
|
166
170
|
const [formLabel, setFormLabel] = useState<ReactNode>();
|
|
171
|
+
const [selectedAvatar, setSelectedAvatar] = useState<AvatarProps | undefined>();
|
|
167
172
|
const refdChildren = useOptionListWithIndexes({ children });
|
|
168
173
|
|
|
169
174
|
const searchOnSubmit = useCallback(() => {
|
|
@@ -203,6 +208,7 @@ function useDropdown<T>({
|
|
|
203
208
|
searchOnSubmit,
|
|
204
209
|
searchRef,
|
|
205
210
|
searchValue,
|
|
211
|
+
size,
|
|
206
212
|
}),
|
|
207
213
|
[
|
|
208
214
|
listRef,
|
|
@@ -214,6 +220,7 @@ function useDropdown<T>({
|
|
|
214
220
|
searchValue,
|
|
215
221
|
searchRef,
|
|
216
222
|
searchOnSubmit,
|
|
223
|
+
size,
|
|
217
224
|
],
|
|
218
225
|
);
|
|
219
226
|
|
|
@@ -222,12 +229,15 @@ function useDropdown<T>({
|
|
|
222
229
|
if (currentOption) {
|
|
223
230
|
setFormLabel(currentOption.label);
|
|
224
231
|
setSelectedIndex(currentOption.index);
|
|
232
|
+
setSelectedAvatar(currentOption.avatar);
|
|
225
233
|
} else {
|
|
226
234
|
setFormLabel(null);
|
|
227
235
|
setSelectedIndex(null);
|
|
236
|
+
setSelectedAvatar(undefined);
|
|
228
237
|
}
|
|
229
238
|
}, [refdChildren, formValue]);
|
|
230
239
|
return {
|
|
240
|
+
avatar: selectedAvatar,
|
|
231
241
|
context,
|
|
232
242
|
floatingContext,
|
|
233
243
|
floatingProps,
|
|
@@ -283,6 +293,7 @@ const Dropdown = forwardRef<Element, DropdownProps<string | null>>(
|
|
|
283
293
|
) => {
|
|
284
294
|
const optionsRef = useRef(null);
|
|
285
295
|
const {
|
|
296
|
+
avatar,
|
|
286
297
|
children,
|
|
287
298
|
context: dropdownCtx,
|
|
288
299
|
floatingContext,
|
|
@@ -303,10 +314,12 @@ const Dropdown = forwardRef<Element, DropdownProps<string | null>>(
|
|
|
303
314
|
placement,
|
|
304
315
|
readOnly,
|
|
305
316
|
ref,
|
|
317
|
+
size,
|
|
306
318
|
value,
|
|
307
319
|
...props,
|
|
308
320
|
});
|
|
309
321
|
const dropdownStyles = useMultiStyleConfig('Dropdown', {
|
|
322
|
+
hasAvatar: Boolean(avatar),
|
|
310
323
|
disabled,
|
|
311
324
|
isError,
|
|
312
325
|
isOpen,
|
|
@@ -352,6 +365,7 @@ const Dropdown = forwardRef<Element, DropdownProps<string | null>>(
|
|
|
352
365
|
{...referenceProps}
|
|
353
366
|
{...buttonProps}
|
|
354
367
|
aria-label={ariaLabel}
|
|
368
|
+
avatar={avatar}
|
|
355
369
|
data-testid={dataTestid}
|
|
356
370
|
id={buttonId}
|
|
357
371
|
iconName={iconName}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { forwardRef, ReactNode } from 'react';
|
|
2
2
|
import { chakra, ChakraProps } from '@chakra-ui/react';
|
|
3
3
|
import Icon, { TypeIconName } from '../Icon/Icon';
|
|
4
|
+
import Avatar, { AvatarProps } from '../Avatar/Avatar';
|
|
4
5
|
import { useDropdownStyles } from './Dropdown.context';
|
|
5
6
|
import { DropdownProps } from './DropdownProps';
|
|
6
7
|
|
|
7
8
|
interface DropdownButtonProps extends ChakraProps {
|
|
9
|
+
avatar?: AvatarProps | undefined;
|
|
8
10
|
'aria-label'?: string;
|
|
9
11
|
blurHandler: () => void;
|
|
10
12
|
id?: string;
|
|
@@ -22,6 +24,7 @@ interface DropdownButtonProps extends ChakraProps {
|
|
|
22
24
|
const DropdownButton = forwardRef<HTMLButtonElement, DropdownButtonProps>(
|
|
23
25
|
(
|
|
24
26
|
{
|
|
27
|
+
avatar,
|
|
25
28
|
blurHandler,
|
|
26
29
|
children,
|
|
27
30
|
disabled,
|
|
@@ -57,6 +60,7 @@ const DropdownButton = forwardRef<HTMLButtonElement, DropdownButtonProps>(
|
|
|
57
60
|
type="button"
|
|
58
61
|
{...rest}
|
|
59
62
|
>
|
|
63
|
+
{avatar && <Avatar size={size === 'lg' ? '32' : '24'} {...avatar} />}
|
|
60
64
|
{iconName && <Icon __css={icon} aria-hidden="true" name={iconName} size={iconSize} />}
|
|
61
65
|
<chakra.span
|
|
62
66
|
__css={buttonContent}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { MouseEventHandler, ReactNode, useId } from 'react';
|
|
2
|
-
import { chakra } from '@chakra-ui/react';
|
|
2
|
+
import { Avatar, AvatarProps, chakra } from '@chakra-ui/react';
|
|
3
3
|
import { cx } from '@chakra-ui/utils';
|
|
4
4
|
import Text, { TextProps } from '../Text/Text';
|
|
5
5
|
import Divider from '../Divider/Divider';
|
|
6
|
+
import Box from '../Box/Box';
|
|
6
7
|
import { useDropdownContext, useDropdownStyles } from './Dropdown.context';
|
|
7
8
|
|
|
8
9
|
export type DropdownOptionProps<T> = {
|
|
10
|
+
avatar?: AvatarProps;
|
|
9
11
|
value?: T | null;
|
|
10
12
|
children?: ReactNode;
|
|
11
13
|
'aria-label'?: string;
|
|
@@ -13,6 +15,7 @@ export type DropdownOptionProps<T> = {
|
|
|
13
15
|
isDisabled?: boolean;
|
|
14
16
|
};
|
|
15
17
|
const DropdownOption = <T = string,>({
|
|
18
|
+
avatar,
|
|
16
19
|
children,
|
|
17
20
|
isDisabled,
|
|
18
21
|
onClick,
|
|
@@ -22,6 +25,7 @@ const DropdownOption = <T = string,>({
|
|
|
22
25
|
const { item } = useDropdownStyles();
|
|
23
26
|
const ctx = useDropdownContext<T | null>();
|
|
24
27
|
const { index } = rest as { index?: number };
|
|
28
|
+
|
|
25
29
|
return (
|
|
26
30
|
<chakra.div
|
|
27
31
|
ref={(node) => {
|
|
@@ -52,7 +56,14 @@ const DropdownOption = <T = string,>({
|
|
|
52
56
|
},
|
|
53
57
|
)}
|
|
54
58
|
>
|
|
55
|
-
{
|
|
59
|
+
{avatar ? (
|
|
60
|
+
<Box display="flex" alignItems="center" gap="8">
|
|
61
|
+
<Avatar size={ctx.size === 'lg' ? '32' : '24'} {...avatar} />
|
|
62
|
+
{children}
|
|
63
|
+
</Box>
|
|
64
|
+
) : (
|
|
65
|
+
children
|
|
66
|
+
)}
|
|
56
67
|
</chakra.div>
|
|
57
68
|
);
|
|
58
69
|
};
|