@bitrise/bitkit 12.10.1 → 12.11.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": "12.10.1",
4
+ "version": "12.11.0",
5
5
  "repository": "git@github.com:bitrise-io/bitkit.git",
6
6
  "main": "src/index.ts",
7
7
  "license": "UNLICENSED",
@@ -1,4 +1,4 @@
1
- import { Fragment, ReactNode, Ref } from 'react';
1
+ import { ChangeEvent, Fragment, ReactNode, Ref, useState } from 'react';
2
2
  import {
3
3
  FormControl,
4
4
  FormControlProps,
@@ -17,6 +17,7 @@ import {
17
17
  import { TypeColors } from '../../../Foundations/Colors/Colors';
18
18
  import Icon, { TypeIconName } from '../../Icon/Icon';
19
19
  import Text from '../../Text/Text';
20
+ import Box from '../../Box/Box';
20
21
 
21
22
  type UsedFormControlProps = Omit<FormControlProps, 'label' | 'onBlur' | 'onChange'>;
22
23
  type UsedChakraInputProps = Pick<
@@ -49,6 +50,7 @@ export interface InputProps extends UsedFormControlProps, UsedChakraInputProps {
49
50
  rightAddon?: ReactNode;
50
51
  rightAddonPlacement?: 'inside' | 'outside';
51
52
  rightIconName?: TypeIconName;
53
+ withCounter?: boolean;
52
54
  }
53
55
 
54
56
  /**
@@ -85,6 +87,7 @@ const Input = forwardRef<InputProps, 'div'>((props, ref) => {
85
87
  role,
86
88
  type,
87
89
  value,
90
+ withCounter,
88
91
  ...rest
89
92
  } = props;
90
93
 
@@ -99,7 +102,6 @@ const Input = forwardRef<InputProps, 'div'>((props, ref) => {
99
102
  autoFocus,
100
103
  'data-testid': dataTestid,
101
104
  onBlur,
102
- onChange,
103
105
  name,
104
106
  max,
105
107
  maxLength,
@@ -124,27 +126,50 @@ const Input = forwardRef<InputProps, 'div'>((props, ref) => {
124
126
  const RightContentWrapper = rightAddonPlacement === 'inside' ? InputRightElement : InputRightAddon;
125
127
  const inputRightPadding = rightIconName || (rightAddon && rightAddonPlacement === 'inside') ? '43px' : '11px';
126
128
 
129
+ const [valueLength, setValueLength] = useState(0);
130
+
131
+ const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
132
+ setValueLength(e.currentTarget.value.length);
133
+
134
+ if (onChange) {
135
+ onChange(e);
136
+ }
137
+ };
138
+
127
139
  return (
128
140
  <FormControl {...formControlProps}>
129
- {label && (
130
- <FormLabel
131
- requiredIndicator={null as any}
132
- optionalIndicator={
133
- <Text as="span" fontSize="2" color="neutral.40" fontWeight="normal" marginLeft="4px">
134
- (Optional)
135
- </Text>
136
- }
137
- >
138
- {label}
139
- </FormLabel>
140
- )}
141
+ <Box display="flex" justifyContent="space-between">
142
+ {label && (
143
+ <FormLabel
144
+ requiredIndicator={null as any}
145
+ optionalIndicator={
146
+ <Text as="span" fontSize="2" color="neutral.40" fontWeight="normal" marginLeft="4px">
147
+ (Optional)
148
+ </Text>
149
+ }
150
+ >
151
+ {label}
152
+ </FormLabel>
153
+ )}
154
+ {withCounter && maxLength && (
155
+ <Text as="span" size="2" color="neutral.40" sx={{ fontVariantNumeric: 'tabular-nums' }}>
156
+ {valueLength}/{maxLength}
157
+ </Text>
158
+ )}
159
+ </Box>
160
+
141
161
  <InputWrapper {...inputWrapperProps}>
142
162
  {leftIconName && (
143
163
  <InputLeftElement margin="12px" pointerEvents="none">
144
164
  <Icon color={leftIconColor} name={leftIconName} />
145
165
  </InputLeftElement>
146
166
  )}
147
- <ChakraInput paddingLeft={leftIconName ? '43px' : '11px'} paddingRight={inputRightPadding} {...inputProps} />
167
+ <ChakraInput
168
+ paddingLeft={leftIconName ? '43px' : '11px'}
169
+ paddingRight={inputRightPadding}
170
+ {...inputProps}
171
+ onChange={onInputChange}
172
+ />
148
173
  {rightAddon && <RightContentWrapper>{rightAddon}</RightContentWrapper>}
149
174
  {!rightAddon && rightIconName && (
150
175
  <InputRightElement margin="12px" pointerEvents="none">
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import { ChangeEvent, ReactNode, useState } from 'react';
2
2
  import {
3
3
  FormControl,
4
4
  FormControlProps,
@@ -10,6 +10,7 @@ import {
10
10
  forwardRef,
11
11
  } from '@chakra-ui/react';
12
12
  import Text from '../../Text/Text';
13
+ import Box from '../../Box/Box';
13
14
 
14
15
  type UsedFormControlProps = Omit<FormControlProps, 'label' | 'onBlur' | 'onChange'>;
15
16
  type UsedChakraTextProps = Pick<
@@ -27,6 +28,7 @@ export interface TextareaProps extends UsedFormControlProps, UsedChakraTextProps
27
28
  onBlur?: ChakraTextareaProps['onBlur'];
28
29
  onChange?: ChakraTextareaProps['onChange'];
29
30
  value?: ChakraTextareaProps['value'];
31
+ withCounter?: boolean;
30
32
  }
31
33
 
32
34
  /**
@@ -52,6 +54,7 @@ const Textarea = forwardRef<TextareaProps, 'div'>((props, ref) => {
52
54
  name,
53
55
  role,
54
56
  value,
57
+ withCounter,
55
58
  ...rest
56
59
  } = props;
57
60
  const formControlProps = {
@@ -65,7 +68,6 @@ const Textarea = forwardRef<TextareaProps, 'div'>((props, ref) => {
65
68
  autoFocus,
66
69
  'data-testid': dataTestid,
67
70
  onBlur,
68
- onChange,
69
71
  maxLength,
70
72
  minLength,
71
73
  name,
@@ -74,22 +76,40 @@ const Textarea = forwardRef<TextareaProps, 'div'>((props, ref) => {
74
76
  role,
75
77
  value,
76
78
  };
79
+
80
+ const [valueLength, setValueLength] = useState(0);
81
+
82
+ const onTextareaChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
83
+ setValueLength(e.currentTarget.value.length);
84
+
85
+ if (onChange) {
86
+ onChange(e);
87
+ }
88
+ };
89
+
77
90
  return (
78
91
  <FormControl {...formControlProps}>
79
92
  {label && (
80
- <FormLabel
81
- requiredIndicator={null as any}
82
- optionalIndicator={
83
- <Text as="span" fontSize="2" color="neutral.40" fontWeight="normal" marginLeft="4px">
84
- (Optional)
93
+ <Box display="flex" justifyContent="space-between">
94
+ <FormLabel
95
+ requiredIndicator={null as any}
96
+ optionalIndicator={
97
+ <Text as="span" fontSize="2" color="neutral.40" fontWeight="normal" marginLeft="4px">
98
+ (Optional)
99
+ </Text>
100
+ }
101
+ >
102
+ {label}
103
+ </FormLabel>
104
+ {withCounter && maxLength && (
105
+ <Text as="span" size="2" color="neutral.40" sx={{ fontVariantNumeric: 'tabular-nums' }}>
106
+ {valueLength}/{maxLength}
85
107
  </Text>
86
- }
87
- >
88
- {label}
89
- </FormLabel>
108
+ )}
109
+ </Box>
90
110
  )}
91
111
 
92
- <ChakraTextarea {...textareaProps} />
112
+ <ChakraTextarea {...textareaProps} onChange={onTextareaChange} />
93
113
  {errorText && <FormErrorMessage as="p">{errorText}</FormErrorMessage>}
94
114
  {helperText && <FormHelperText as="p">{helperText}</FormHelperText>}
95
115
  </FormControl>