@qoretechnologies/reqore 0.31.2 → 0.32.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/__tests__/collection.test.tsx +5 -1
- package/__tests__/input.test.tsx +417 -24
- package/__tests__/multiselect.test.tsx +8 -10
- package/__tests__/textarea.test.tsx +405 -24
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +1 -1
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Collection/index.d.ts +3 -2
- package/dist/components/Collection/index.d.ts.map +1 -1
- package/dist/components/Collection/index.js +6 -3
- package/dist/components/Collection/index.js.map +1 -1
- package/dist/components/ControlGroup/index.d.ts.map +1 -1
- package/dist/components/ControlGroup/index.js +17 -56
- package/dist/components/ControlGroup/index.js.map +1 -1
- package/dist/components/Icon/index.d.ts +2 -0
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.js +10 -5
- package/dist/components/Icon/index.js.map +1 -1
- package/dist/components/Input/index.d.ts +4 -0
- package/dist/components/Input/index.d.ts.map +1 -1
- package/dist/components/Input/index.js +18 -6
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/InputClearButton/index.d.ts +1 -0
- package/dist/components/InputClearButton/index.d.ts.map +1 -1
- package/dist/components/InputClearButton/index.js +18 -8
- package/dist/components/InputClearButton/index.js.map +1 -1
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +11 -6
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/Textarea/index.d.ts.map +1 -1
- package/dist/components/Textarea/index.js +4 -2
- package/dist/components/Textarea/index.js.map +1 -1
- package/dist/hooks/useAutoFocus.d.ts +11 -0
- package/dist/hooks/useAutoFocus.d.ts.map +1 -0
- package/dist/hooks/useAutoFocus.js +80 -0
- package/dist/hooks/useAutoFocus.js.map +1 -0
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +1 -1
- package/dist/styles.js.map +1 -1
- package/package.json +3 -1
- package/src/components/Button/index.tsx +1 -0
- package/src/components/Collection/index.tsx +12 -2
- package/src/components/ControlGroup/index.tsx +25 -86
- package/src/components/Icon/index.tsx +18 -4
- package/src/components/Input/index.tsx +38 -3
- package/src/components/InputClearButton/index.tsx +41 -17
- package/src/components/Panel/index.tsx +18 -8
- package/src/components/Textarea/index.tsx +15 -8
- package/src/hooks/useAutoFocus.ts +104 -0
- package/src/stories/Collection/Collection.stories.tsx +54 -10
- package/src/stories/Input/Input.stories.tsx +29 -6
- package/src/stories/Panel/Panel.stories.tsx +3 -2
- package/src/stories/TextArea/TextArea.stories.tsx +1 -0
- package/src/styles.ts +0 -1
- package/tests.json +1 -1
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { debounce } from 'lodash';
|
|
2
|
-
import React, {
|
|
3
|
-
memo,
|
|
4
|
-
useCallback,
|
|
5
|
-
useEffect,
|
|
6
|
-
useMemo,
|
|
7
|
-
useRef,
|
|
8
|
-
useState,
|
|
9
|
-
} from 'react';
|
|
2
|
+
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
10
3
|
import { useMount, useUnmount } from 'react-use';
|
|
11
4
|
import styled, { css } from 'styled-components';
|
|
12
5
|
import { ReqoreButton, ReqoreDrawer } from '../..';
|
|
@@ -63,16 +56,13 @@ export interface IReqoreControlGroupStyle extends IReqoreControlGroupProps {
|
|
|
63
56
|
|
|
64
57
|
export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
|
|
65
58
|
display: flex;
|
|
66
|
-
flex: ${({ fluid, fixed }) =>
|
|
67
|
-
fixed ? '0 0 auto' : fluid ? undefined : '0 0 auto'};
|
|
59
|
+
flex: ${({ fluid, fixed }) => (fixed ? '0 0 auto' : fluid ? undefined : '0 0 auto')};
|
|
68
60
|
width: ${({ fluid, fixed }) => (fluid && !fixed ? '100%' : undefined)};
|
|
69
|
-
justify-content: ${({ fluid, vertical }) =>
|
|
70
|
-
vertical && fluid ? 'stretch' : undefined};
|
|
61
|
+
justify-content: ${({ fluid, vertical }) => (vertical && fluid ? 'stretch' : undefined)};
|
|
71
62
|
align-items: ${({ vertical, fluid, horizontalAlign }) =>
|
|
72
63
|
vertical ? (fluid ? 'stretch' : horizontalAlign) : undefined};
|
|
73
64
|
flex-flow: ${({ vertical }) => (vertical ? 'column' : 'row')};
|
|
74
|
-
gap: ${({ gapSize, stack }) =>
|
|
75
|
-
!stack ? `${GAP_FROM_SIZE[gapSize]}px` : undefined};
|
|
65
|
+
gap: ${({ gapSize, stack }) => (!stack ? `${GAP_FROM_SIZE[gapSize]}px` : undefined)};
|
|
76
66
|
flex-wrap: ${({ wrap }) => (wrap ? 'wrap' : 'nowrap')};
|
|
77
67
|
|
|
78
68
|
// If the group has the fill prop,
|
|
@@ -95,23 +85,16 @@ export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
|
|
|
95
85
|
|
|
96
86
|
> * {
|
|
97
87
|
margin-top: ${({ fill, verticalAlign }) =>
|
|
98
|
-
!fill && (verticalAlign === 'flex-end' || verticalAlign === 'center')
|
|
99
|
-
? 'auto'
|
|
100
|
-
: undefined};
|
|
88
|
+
!fill && (verticalAlign === 'flex-end' || verticalAlign === 'center') ? 'auto' : undefined};
|
|
101
89
|
margin-bottom: ${({ fill, verticalAlign }) =>
|
|
102
|
-
!fill && (verticalAlign === 'flex-start' || verticalAlign === 'center')
|
|
103
|
-
|
|
104
|
-
: undefined};
|
|
105
|
-
margin-right: ${({ horizontalAlign }) =>
|
|
106
|
-
horizontalAlign === 'center' ? 'auto' : undefined};
|
|
90
|
+
!fill && (verticalAlign === 'flex-start' || verticalAlign === 'center') ? 'auto' : undefined};
|
|
91
|
+
margin-right: ${({ horizontalAlign }) => (horizontalAlign === 'center' ? 'auto' : undefined)};
|
|
107
92
|
|
|
108
93
|
${({ vertical }) =>
|
|
109
94
|
vertical &&
|
|
110
95
|
css`
|
|
111
96
|
margin-left: ${({ horizontalAlign }) =>
|
|
112
|
-
horizontalAlign === 'flex-end' || horizontalAlign === 'center'
|
|
113
|
-
? 'auto'
|
|
114
|
-
: undefined};
|
|
97
|
+
horizontalAlign === 'flex-end' || horizontalAlign === 'center' ? 'auto' : undefined};
|
|
115
98
|
`}
|
|
116
99
|
}
|
|
117
100
|
|
|
@@ -120,9 +103,7 @@ export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
|
|
|
120
103
|
css`
|
|
121
104
|
> *:first-child {
|
|
122
105
|
margin-left: ${({ horizontalAlign }) =>
|
|
123
|
-
horizontalAlign === 'flex-end' || horizontalAlign === 'center'
|
|
124
|
-
? 'auto'
|
|
125
|
-
: undefined};
|
|
106
|
+
horizontalAlign === 'flex-end' || horizontalAlign === 'center' ? 'auto' : undefined};
|
|
126
107
|
}
|
|
127
108
|
`}
|
|
128
109
|
|
|
@@ -168,12 +149,9 @@ const ReqoreControlGroup = memo(
|
|
|
168
149
|
const isStack = stack || isInsideStackGroup;
|
|
169
150
|
const isVertical = vertical || isInsideVerticalGroup;
|
|
170
151
|
|
|
171
|
-
const [overflowingChildren, setOverflowingChildren] = useState<
|
|
172
|
-
number | undefined
|
|
173
|
-
>(0);
|
|
152
|
+
const [overflowingChildren, setOverflowingChildren] = useState<number | undefined>(0);
|
|
174
153
|
const [lastReSize, setLastReSize] = useState<number>(0);
|
|
175
|
-
const [isOverflownDialogOpen, setIsOverflownDialogOpen] =
|
|
176
|
-
useState<boolean>(false);
|
|
154
|
+
const [isOverflownDialogOpen, setIsOverflownDialogOpen] = useState<boolean>(false);
|
|
177
155
|
const observer = useRef<ResizeObserver | null>(null);
|
|
178
156
|
const ref = useRef<HTMLDivElement>(null);
|
|
179
157
|
|
|
@@ -232,10 +210,7 @@ const ReqoreControlGroup = memo(
|
|
|
232
210
|
|
|
233
211
|
useEffect(() => {
|
|
234
212
|
// Is the control group still overflowing?
|
|
235
|
-
if (
|
|
236
|
-
(overflowingChildren || overflowingChildren === 0) &&
|
|
237
|
-
checkIfOverflowing()
|
|
238
|
-
) {
|
|
213
|
+
if ((overflowingChildren || overflowingChildren === 0) && checkIfOverflowing()) {
|
|
239
214
|
setOverflowingChildren(overflowingChildren + 1);
|
|
240
215
|
}
|
|
241
216
|
|
|
@@ -258,33 +233,22 @@ const ReqoreControlGroup = memo(
|
|
|
258
233
|
const getIsLastInFirstGroup = (index: number): boolean => {
|
|
259
234
|
return !isInsideStackGroup
|
|
260
235
|
? index === 0
|
|
261
|
-
: isFirstGroup &&
|
|
262
|
-
(isLast || isLast !== false) &&
|
|
263
|
-
index === realChildCount - 1;
|
|
236
|
+
: isFirstGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
264
237
|
};
|
|
265
238
|
const getIsFirstInLastGroup = (index: number): boolean => {
|
|
266
239
|
return !isInsideStackGroup
|
|
267
240
|
? index === realChildCount - 1
|
|
268
|
-
: isLastGroup &&
|
|
269
|
-
(isFirst || isFirst !== false) &&
|
|
270
|
-
childId === 1 &&
|
|
271
|
-
index === 0;
|
|
241
|
+
: isLastGroup && (isFirst || isFirst !== false) && childId === 1 && index === 0;
|
|
272
242
|
};
|
|
273
243
|
const getIsLastInLastGroup = (index: number): boolean => {
|
|
274
244
|
return !isInsideStackGroup
|
|
275
245
|
? index === realChildCount - 1
|
|
276
|
-
: isLastGroup &&
|
|
277
|
-
(isLast || isLast !== false) &&
|
|
278
|
-
index === realChildCount - 1;
|
|
246
|
+
: isLastGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
279
247
|
};
|
|
280
248
|
|
|
281
249
|
const getBorderTopLeftRadius = (index: number): number | undefined => {
|
|
282
250
|
const _isFirstGroup =
|
|
283
|
-
!isInsideStackGroup || childrenCount === 1
|
|
284
|
-
? true
|
|
285
|
-
: isChild
|
|
286
|
-
? isFirstGroup
|
|
287
|
-
: index === 0;
|
|
251
|
+
!isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
|
|
288
252
|
|
|
289
253
|
// If this is the first item
|
|
290
254
|
if (_isFirstGroup && getIsFirst(index)) {
|
|
@@ -324,11 +288,7 @@ const ReqoreControlGroup = memo(
|
|
|
324
288
|
// If this group is not vertical we need to style the very first item
|
|
325
289
|
if (!isVertical || !isStack) {
|
|
326
290
|
const _isFirstGroup =
|
|
327
|
-
!isInsideStackGroup || childrenCount === 1
|
|
328
|
-
? true
|
|
329
|
-
: isChild
|
|
330
|
-
? isFirstGroup
|
|
331
|
-
: index === 0;
|
|
291
|
+
!isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
|
|
332
292
|
|
|
333
293
|
if (_isFirstGroup && getIsFirst(index)) {
|
|
334
294
|
return RADIUS_FROM_SIZE[size];
|
|
@@ -369,7 +329,6 @@ const ReqoreControlGroup = memo(
|
|
|
369
329
|
return React.Children.map(children, (child) => {
|
|
370
330
|
if (child && React.isValidElement(child)) {
|
|
371
331
|
if (child.type === React.Fragment) {
|
|
372
|
-
// just compare to `React.Fragment`
|
|
373
332
|
return cloneThroughFragments(child.props.children);
|
|
374
333
|
}
|
|
375
334
|
|
|
@@ -381,26 +340,12 @@ const ReqoreControlGroup = memo(
|
|
|
381
340
|
? child.props.minimal
|
|
382
341
|
: minimal,
|
|
383
342
|
size: child.props?.size || size,
|
|
384
|
-
flat:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
fluid:
|
|
389
|
-
child.props?.fluid || child.props?.fluid === false
|
|
390
|
-
? child.props.fluid
|
|
391
|
-
: fluid,
|
|
392
|
-
fixed:
|
|
393
|
-
child.props?.fixed || child.props?.fixed === false
|
|
394
|
-
? child.props.fixed
|
|
395
|
-
: fixed,
|
|
396
|
-
fill:
|
|
397
|
-
child.props?.fill || child.props?.fill === false
|
|
398
|
-
? child.props.fill
|
|
399
|
-
: fill,
|
|
343
|
+
flat: child.props?.flat || child.props?.flat === false ? child.props.flat : flat,
|
|
344
|
+
fluid: child.props?.fluid || child.props?.fluid === false ? child.props.fluid : fluid,
|
|
345
|
+
fixed: child.props?.fixed || child.props?.fixed === false ? child.props.fixed : fixed,
|
|
346
|
+
fill: child.props?.fill || child.props?.fill === false ? child.props.fill : fill,
|
|
400
347
|
stack:
|
|
401
|
-
child.props?.stack || child.props?.stack === false
|
|
402
|
-
? child.props.stack
|
|
403
|
-
: isStack,
|
|
348
|
+
child.props?.stack || child.props?.stack === false ? child.props.stack : isStack,
|
|
404
349
|
intent: child.props?.intent || intent,
|
|
405
350
|
customTheme: child.props?.customTheme || customTheme,
|
|
406
351
|
};
|
|
@@ -428,9 +373,7 @@ const ReqoreControlGroup = memo(
|
|
|
428
373
|
childId: index + 1,
|
|
429
374
|
|
|
430
375
|
isFirstGroup: isChild ? isFirstGroup : index === 0,
|
|
431
|
-
isLastGroup: isChild
|
|
432
|
-
? isLastGroup
|
|
433
|
-
: index === realChildCount - 1,
|
|
376
|
+
isLastGroup: isChild ? isLastGroup : index === realChildCount - 1,
|
|
434
377
|
};
|
|
435
378
|
}
|
|
436
379
|
|
|
@@ -469,9 +412,7 @@ const ReqoreControlGroup = memo(
|
|
|
469
412
|
// Get the overflown children
|
|
470
413
|
const overflownChildren = useMemo(
|
|
471
414
|
() =>
|
|
472
|
-
overflowingChildren
|
|
473
|
-
? React.Children.toArray(children).slice(0, overflowingChildren)
|
|
474
|
-
: [],
|
|
415
|
+
overflowingChildren ? React.Children.toArray(children).slice(0, overflowingChildren) : [],
|
|
475
416
|
[children, overflowingChildren]
|
|
476
417
|
);
|
|
477
418
|
|
|
@@ -485,9 +426,7 @@ const ReqoreControlGroup = memo(
|
|
|
485
426
|
icon='MenuLine'
|
|
486
427
|
customTheme={customTheme}
|
|
487
428
|
tooltip={{
|
|
488
|
-
content: `Show ${React.Children.count(
|
|
489
|
-
overflownChildren
|
|
490
|
-
)} hidden items`,
|
|
429
|
+
content: `Show ${React.Children.count(overflownChildren)} hidden items`,
|
|
491
430
|
}}
|
|
492
431
|
fixed
|
|
493
432
|
active={isOverflownDialogOpen}
|
|
@@ -21,6 +21,8 @@ export interface IReqoreIconProps
|
|
|
21
21
|
icon?: IReqoreIconName;
|
|
22
22
|
color?: TReqoreEffectColor;
|
|
23
23
|
size?: TSizes | string;
|
|
24
|
+
wrapperSize?: TSizes | string;
|
|
25
|
+
wrapperElement?: any;
|
|
24
26
|
iconProps?: IconBaseProps;
|
|
25
27
|
margin?: 'right' | 'left' | 'both';
|
|
26
28
|
image?: string;
|
|
@@ -38,8 +40,10 @@ const SpinKeyframes = keyframes`
|
|
|
38
40
|
`;
|
|
39
41
|
|
|
40
42
|
export const StyledIconWrapper = styled(StyledEffect)<{ margin: 'right' | 'left' | 'both' }>`
|
|
41
|
-
display: inline-
|
|
43
|
+
display: inline-flex;
|
|
42
44
|
flex: 0 0 auto;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
align-items: center;
|
|
43
47
|
vertical-align: text-bottom;
|
|
44
48
|
transition: all 0.2s ease-out;
|
|
45
49
|
overflow: hidden;
|
|
@@ -78,6 +82,8 @@ const ReqoreIcon = memo(
|
|
|
78
82
|
{
|
|
79
83
|
icon,
|
|
80
84
|
size = 'normal',
|
|
85
|
+
wrapperSize,
|
|
86
|
+
wrapperElement,
|
|
81
87
|
className,
|
|
82
88
|
color,
|
|
83
89
|
margin,
|
|
@@ -97,6 +103,11 @@ const ReqoreIcon = memo(
|
|
|
97
103
|
? theme.intents[intent]
|
|
98
104
|
: getColorFromMaybeString(theme, color);
|
|
99
105
|
const finalSize: string = isStringSize(size) ? ICON_FROM_SIZE[size] : size;
|
|
106
|
+
const finalWrapperSize: string = wrapperSize
|
|
107
|
+
? isStringSize(wrapperSize)
|
|
108
|
+
? ICON_FROM_SIZE[wrapperSize]
|
|
109
|
+
: wrapperSize
|
|
110
|
+
: finalSize;
|
|
100
111
|
|
|
101
112
|
useTooltip(targetRef.current, tooltip);
|
|
102
113
|
|
|
@@ -104,11 +115,12 @@ const ReqoreIcon = memo(
|
|
|
104
115
|
return (
|
|
105
116
|
<StyledIconWrapper
|
|
106
117
|
{...rest}
|
|
118
|
+
as={wrapperElement}
|
|
107
119
|
ref={targetRef}
|
|
108
120
|
size={size}
|
|
109
121
|
margin={margin}
|
|
110
122
|
className={`${className || ''} reqore-icon`}
|
|
111
|
-
style={{
|
|
123
|
+
style={{ width: finalWrapperSize, height: finalWrapperSize, ...style }}
|
|
112
124
|
>
|
|
113
125
|
<img src={image} alt='' />
|
|
114
126
|
</StyledIconWrapper>
|
|
@@ -119,11 +131,12 @@ const ReqoreIcon = memo(
|
|
|
119
131
|
return (
|
|
120
132
|
<StyledIconWrapper
|
|
121
133
|
{...rest}
|
|
134
|
+
as={wrapperElement}
|
|
122
135
|
ref={targetRef}
|
|
123
136
|
size={size}
|
|
124
137
|
margin={margin}
|
|
125
138
|
className={`${className || ''} reqore-icon`}
|
|
126
|
-
style={{
|
|
139
|
+
style={{ width: finalWrapperSize, height: finalWrapperSize, ...style }}
|
|
127
140
|
/>
|
|
128
141
|
);
|
|
129
142
|
}
|
|
@@ -131,10 +144,11 @@ const ReqoreIcon = memo(
|
|
|
131
144
|
return (
|
|
132
145
|
<StyledIconWrapper
|
|
133
146
|
{...rest}
|
|
147
|
+
as={wrapperElement}
|
|
134
148
|
ref={targetRef}
|
|
135
149
|
margin={margin}
|
|
136
150
|
size={size}
|
|
137
|
-
style={{
|
|
151
|
+
style={{ width: finalWrapperSize, height: finalWrapperSize, ...style }}
|
|
138
152
|
className={`${className || ''} reqore-icon`}
|
|
139
153
|
>
|
|
140
154
|
<IconContext.Provider
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { rgba } from 'polished';
|
|
2
|
-
import React, { forwardRef } from 'react';
|
|
2
|
+
import React, { forwardRef, useRef } from 'react';
|
|
3
3
|
import styled, { css } from 'styled-components';
|
|
4
4
|
import {
|
|
5
5
|
PADDING_FROM_SIZE,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '../../constants/sizes';
|
|
11
11
|
import { IReqoreTheme } from '../../constants/theme';
|
|
12
12
|
import { changeLightness, getReadableColor } from '../../helpers/colors';
|
|
13
|
+
import { IReqoreAutoFocusRules, useAutoFocus } from '../../hooks/useAutoFocus';
|
|
13
14
|
import { useCombinedRefs } from '../../hooks/useCombinedRefs';
|
|
14
15
|
import { useReqoreTheme } from '../../hooks/useTheme';
|
|
15
16
|
import { useTooltip } from '../../hooks/useTooltip';
|
|
@@ -44,11 +45,14 @@ export interface IReqoreInputProps
|
|
|
44
45
|
onClearClick?: () => void;
|
|
45
46
|
maxLength?: number;
|
|
46
47
|
icon?: IReqoreIconName;
|
|
48
|
+
rightIcon?: IReqoreIconName;
|
|
47
49
|
flat?: boolean;
|
|
48
50
|
rounded?: boolean;
|
|
49
51
|
type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url';
|
|
50
52
|
wrapperStyle?: React.CSSProperties;
|
|
51
53
|
iconColor?: TReqoreEffectColor;
|
|
54
|
+
rightIconColor?: TReqoreEffectColor;
|
|
55
|
+
focusRules?: IReqoreAutoFocusRules;
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
export interface IReqoreInputStyle extends IReqoreInputProps {
|
|
@@ -76,6 +80,8 @@ const StyledIconWrapper = styled.div<IReqoreInputStyle>`
|
|
|
76
80
|
position: absolute;
|
|
77
81
|
height: ${({ _size }) => SIZE_TO_PX[_size]}px;
|
|
78
82
|
width: ${({ _size }) => SIZE_TO_PX[_size]}px;
|
|
83
|
+
right: ${({ position }) => (position === 'right' ? 0 : undefined)};
|
|
84
|
+
top: 0;
|
|
79
85
|
display: flex;
|
|
80
86
|
justify-content: center;
|
|
81
87
|
align-items: center;
|
|
@@ -87,7 +93,18 @@ export const StyledInput = styled(StyledEffect)<IReqoreInputStyle>`
|
|
|
87
93
|
flex: 1;
|
|
88
94
|
margin: 0;
|
|
89
95
|
padding: ${({ _size }) => PADDING_FROM_SIZE[_size] / 2}px 7px;
|
|
90
|
-
padding-right: ${({ clearable, _size }) =>
|
|
96
|
+
padding-right: ${({ clearable, hasRightIcon, _size }) => {
|
|
97
|
+
let padding = 7;
|
|
98
|
+
|
|
99
|
+
if (clearable || hasRightIcon) {
|
|
100
|
+
padding = 0;
|
|
101
|
+
padding += clearable ? SIZE_TO_PX[_size] : 0;
|
|
102
|
+
padding += hasRightIcon ? SIZE_TO_PX[_size] : 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return padding;
|
|
106
|
+
}}px;
|
|
107
|
+
|
|
91
108
|
padding-left: ${({ hasIcon, _size }) => (hasIcon ? SIZE_TO_PX[_size] : 7)}px;
|
|
92
109
|
font-size: ${({ _size }) => TEXT_FROM_SIZE[_size]}px;
|
|
93
110
|
transition: all 0.2s ease-out;
|
|
@@ -154,7 +171,9 @@ const ReqoreInput = forwardRef<HTMLDivElement, IReqoreInputProps>(
|
|
|
154
171
|
className,
|
|
155
172
|
onClearClick,
|
|
156
173
|
icon,
|
|
174
|
+
rightIcon,
|
|
157
175
|
iconColor,
|
|
176
|
+
rightIconColor,
|
|
158
177
|
flat,
|
|
159
178
|
rounded = true,
|
|
160
179
|
minimal,
|
|
@@ -163,14 +182,21 @@ const ReqoreInput = forwardRef<HTMLDivElement, IReqoreInputProps>(
|
|
|
163
182
|
customTheme,
|
|
164
183
|
intent,
|
|
165
184
|
wrapperStyle,
|
|
185
|
+
focusRules,
|
|
166
186
|
...rest
|
|
167
187
|
}: IReqoreInputProps,
|
|
168
188
|
ref
|
|
169
189
|
) => {
|
|
170
190
|
const { targetRef } = useCombinedRefs(ref);
|
|
191
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
171
192
|
const theme = useReqoreTheme('main', customTheme, intent);
|
|
172
193
|
|
|
173
194
|
useTooltip(targetRef.current, tooltip);
|
|
195
|
+
useAutoFocus(
|
|
196
|
+
inputRef.current,
|
|
197
|
+
readOnly || rest.disabled ? undefined : focusRules,
|
|
198
|
+
rest.onChange
|
|
199
|
+
);
|
|
174
200
|
|
|
175
201
|
return (
|
|
176
202
|
<StyledInputWrapper
|
|
@@ -199,23 +225,32 @@ const ReqoreInput = forwardRef<HTMLDivElement, IReqoreInputProps>(
|
|
|
199
225
|
interactive: !rest?.disabled && !readOnly,
|
|
200
226
|
...rest?.effect,
|
|
201
227
|
}}
|
|
228
|
+
onChange={!readOnly && !rest?.disabled ? rest?.onChange : undefined}
|
|
202
229
|
as='input'
|
|
230
|
+
ref={inputRef}
|
|
203
231
|
theme={theme}
|
|
204
232
|
_size={size}
|
|
205
233
|
minimal={minimal}
|
|
206
234
|
flat={flat}
|
|
207
235
|
rounded={rounded}
|
|
208
236
|
hasIcon={!!icon}
|
|
209
|
-
|
|
237
|
+
hasRightIcon={!!rightIcon}
|
|
238
|
+
clearable={!rest?.disabled && !readOnly && !!(onClearClick && rest?.onChange)}
|
|
210
239
|
className={`${className || ''} reqore-control reqore-input`}
|
|
211
240
|
readOnly={readOnly}
|
|
212
241
|
/>
|
|
213
242
|
<ReqoreInputClearButton
|
|
214
243
|
enabled={!readOnly && !rest?.disabled && !!(onClearClick && rest?.onChange)}
|
|
215
244
|
onClick={onClearClick}
|
|
245
|
+
hasRightIcon={!!rightIcon}
|
|
216
246
|
size={size}
|
|
217
247
|
show={rest?.value && rest.value !== '' ? true : false}
|
|
218
248
|
/>
|
|
249
|
+
{rightIcon && (
|
|
250
|
+
<StyledIconWrapper _size={size} position='right'>
|
|
251
|
+
<ReqoreIcon size={size} icon={rightIcon} color={rightIconColor} />
|
|
252
|
+
</StyledIconWrapper>
|
|
253
|
+
)}
|
|
219
254
|
</StyledInputWrapper>
|
|
220
255
|
);
|
|
221
256
|
}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
+
import { animated, useTransition } from '@react-spring/web';
|
|
1
2
|
import styled from 'styled-components';
|
|
2
|
-
import
|
|
3
|
+
import { SPRING_CONFIG } from '../../constants/animations';
|
|
4
|
+
import { SIZE_TO_PX } from '../../constants/sizes';
|
|
5
|
+
import { IReqoreButtonProps } from '../Button';
|
|
6
|
+
import ReqoreIcon from '../Icon';
|
|
3
7
|
|
|
4
8
|
export interface IReqoreInputClearButtonProps extends IReqoreButtonProps {
|
|
5
9
|
show: boolean;
|
|
6
10
|
enabled: boolean;
|
|
11
|
+
hasRightIcon?: boolean;
|
|
7
12
|
}
|
|
8
13
|
|
|
9
|
-
export const StyledInputClearButton = styled(
|
|
14
|
+
export const StyledInputClearButton = styled(ReqoreIcon)<{ show?: boolean }>`
|
|
10
15
|
position: absolute;
|
|
11
|
-
right: ${({
|
|
16
|
+
right: ${({ size, hasRightIcon }) => (hasRightIcon ? SIZE_TO_PX[size] : 0)}px;
|
|
12
17
|
top: 0;
|
|
13
|
-
|
|
18
|
+
justify-content: center;
|
|
19
|
+
align-items: center;
|
|
20
|
+
transition: all 0.1s ease-out;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
|
|
23
|
+
&:hover {
|
|
24
|
+
opacity: 1 !important;
|
|
25
|
+
}
|
|
14
26
|
`;
|
|
15
27
|
|
|
16
28
|
const ReqoreInputClearButton = ({
|
|
@@ -18,18 +30,30 @@ const ReqoreInputClearButton = ({
|
|
|
18
30
|
enabled,
|
|
19
31
|
size = 'normal',
|
|
20
32
|
...rest
|
|
21
|
-
}: IReqoreInputClearButtonProps) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
}: IReqoreInputClearButtonProps) => {
|
|
34
|
+
const transitions = useTransition(show && enabled, {
|
|
35
|
+
from: { opacity: 0, filter: 'blur(10px)' },
|
|
36
|
+
enter: { opacity: 0.5, filter: 'blur(0px)' },
|
|
37
|
+
leave: { opacity: 0, filter: 'blur(10px)' },
|
|
38
|
+
config: SPRING_CONFIG,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return transitions((styles, item) =>
|
|
42
|
+
item ? (
|
|
43
|
+
<StyledInputClearButton
|
|
44
|
+
{...rest}
|
|
45
|
+
className='reqore-clear-input-button'
|
|
46
|
+
icon='CloseLine'
|
|
47
|
+
wrapperElement={animated.span}
|
|
48
|
+
size={size}
|
|
49
|
+
wrapperSize={SIZE_TO_PX[size]}
|
|
50
|
+
show={show}
|
|
51
|
+
style={{
|
|
52
|
+
opacity: styles.opacity,
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
) : null
|
|
56
|
+
);
|
|
57
|
+
};
|
|
34
58
|
|
|
35
59
|
export default ReqoreInputClearButton;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { size } from 'lodash';
|
|
2
2
|
import { darken, rgba } from 'polished';
|
|
3
|
-
import {
|
|
3
|
+
import { forwardRef, ReactElement, useCallback, useMemo, useState } from 'react';
|
|
4
4
|
import { useUpdateEffect } from 'react-use';
|
|
5
5
|
import styled, { css } from 'styled-components';
|
|
6
6
|
import {
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from '../../helpers/colors';
|
|
22
22
|
import { getOneHigherSize, isActionShown } from '../../helpers/utils';
|
|
23
23
|
import { useCombinedRefs } from '../../hooks/useCombinedRefs';
|
|
24
|
+
import { useReqore } from '../../hooks/useReqore';
|
|
24
25
|
import { useReqoreTheme } from '../../hooks/useTheme';
|
|
25
26
|
import { useTooltip } from '../../hooks/useTooltip';
|
|
26
27
|
import { ACTIVE_ICON_SCALE, INACTIVE_ICON_SCALE } from '../../styles';
|
|
@@ -186,6 +187,7 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
|
|
|
186
187
|
|
|
187
188
|
export const StyledPanelTitle = styled.div<IStyledPanel>`
|
|
188
189
|
display: flex;
|
|
190
|
+
flex-flow: ${({ isMobile }) => (isMobile ? 'column' : 'row')};
|
|
189
191
|
background-color: ${({ theme, opacity = 1 }: IStyledPanel) =>
|
|
190
192
|
rgba(changeLightness(getMainBackgroundColor(theme), 0.03), opacity)};
|
|
191
193
|
justify-content: space-between;
|
|
@@ -306,6 +308,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
306
308
|
? { main: Object.values(contentEffect.gradient.colors)[0] as TReqoreEffectColor }
|
|
307
309
|
: undefined)
|
|
308
310
|
);
|
|
311
|
+
const { isMobile } = useReqore();
|
|
309
312
|
const { targetRef } = useCombinedRefs(ref);
|
|
310
313
|
|
|
311
314
|
useTooltip(targetRef.current, tooltip);
|
|
@@ -418,8 +421,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
418
421
|
stack
|
|
419
422
|
customTheme={rest.customTheme || theme}
|
|
420
423
|
size={rest.size}
|
|
421
|
-
fixed
|
|
422
|
-
fluid={rest.fluid}
|
|
424
|
+
fixed={rest.fixed ? true : false}
|
|
425
|
+
fluid={rest.fluid ? true : false}
|
|
423
426
|
key={index}
|
|
424
427
|
>
|
|
425
428
|
{group.map((action, index) => renderActions(action, index, true))}
|
|
@@ -430,9 +433,9 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
430
433
|
if (size(actions)) {
|
|
431
434
|
return (
|
|
432
435
|
<ReqoreDropdown<IReqoreButtonProps>
|
|
436
|
+
fixed
|
|
433
437
|
{...rest}
|
|
434
438
|
key={index}
|
|
435
|
-
fixed
|
|
436
439
|
label={label}
|
|
437
440
|
items={actions}
|
|
438
441
|
intent={intent}
|
|
@@ -449,7 +452,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
449
452
|
<CustomElement
|
|
450
453
|
fixed
|
|
451
454
|
{...props}
|
|
452
|
-
key={index}
|
|
455
|
+
key={props.key || index}
|
|
456
|
+
reactKey={props.key || index}
|
|
453
457
|
customTheme={props.customTheme || theme}
|
|
454
458
|
onClick={(e: React.MouseEvent<any>) => {
|
|
455
459
|
e.stopPropagation();
|
|
@@ -461,9 +465,9 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
461
465
|
|
|
462
466
|
return (
|
|
463
467
|
<ReqoreButton
|
|
468
|
+
fixed
|
|
464
469
|
{...rest}
|
|
465
470
|
id={id}
|
|
466
|
-
fixed
|
|
467
471
|
key={index}
|
|
468
472
|
className={className}
|
|
469
473
|
customTheme={rest.customTheme || theme}
|
|
@@ -536,6 +540,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
536
540
|
size={contentSize || panelSize}
|
|
537
541
|
opacity={opacity ?? (minimal ? 0 : 1)}
|
|
538
542
|
noHorizontalPadding={noHorizontalPadding}
|
|
543
|
+
isMobile={isMobile}
|
|
539
544
|
>
|
|
540
545
|
{hasTitleHeader && (
|
|
541
546
|
<StyledPanelTitleHeader>
|
|
@@ -579,7 +584,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
579
584
|
{hasResponsiveActions(actions) && (
|
|
580
585
|
<ReqoreControlGroup
|
|
581
586
|
responsive={responsiveActions}
|
|
582
|
-
fluid={responsiveActions}
|
|
587
|
+
fluid={responsiveActions || isMobile}
|
|
583
588
|
horizontalAlign='flex-end'
|
|
584
589
|
customTheme={theme}
|
|
585
590
|
size={panelSize}
|
|
@@ -589,7 +594,12 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
589
594
|
)}
|
|
590
595
|
{collapsible || onClose || hasNonResponsiveActions(actions) ? (
|
|
591
596
|
<>
|
|
592
|
-
<ReqoreControlGroup
|
|
597
|
+
<ReqoreControlGroup
|
|
598
|
+
fixed={!isMobile}
|
|
599
|
+
fluid={isMobile}
|
|
600
|
+
horizontalAlign='flex-end'
|
|
601
|
+
size={panelSize}
|
|
602
|
+
>
|
|
593
603
|
{actions.map(renderNonResponsiveActions)}
|
|
594
604
|
{collapsible && (
|
|
595
605
|
<ReqoreButton
|
|
@@ -4,6 +4,7 @@ import styled, { css } from 'styled-components';
|
|
|
4
4
|
import { RADIUS_FROM_SIZE, SIZE_TO_PX, TEXT_FROM_SIZE, TSizes } from '../../constants/sizes';
|
|
5
5
|
import { IReqoreTheme } from '../../constants/theme';
|
|
6
6
|
import { changeLightness, getReadableColor } from '../../helpers/colors';
|
|
7
|
+
import { IReqoreAutoFocusRules, useAutoFocus } from '../../hooks/useAutoFocus';
|
|
7
8
|
import { useCombinedRefs } from '../../hooks/useCombinedRefs';
|
|
8
9
|
import useAutosizeTextArea from '../../hooks/useTextareaAutoSize';
|
|
9
10
|
import { useReqoreTheme } from '../../hooks/useTheme';
|
|
@@ -44,6 +45,7 @@ export interface IReqoreTextareaProps
|
|
|
44
45
|
fixed?: boolean;
|
|
45
46
|
onClearClick?: () => any;
|
|
46
47
|
wrapperStyle?: React.CSSProperties;
|
|
48
|
+
focusRules?: IReqoreAutoFocusRules;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export interface IReqoreTextareaStyle extends IReqoreTextareaProps {
|
|
@@ -138,6 +140,7 @@ const ReqoreInput = forwardRef<HTMLTextAreaElement, IReqoreTextareaProps>(
|
|
|
138
140
|
value,
|
|
139
141
|
onChange,
|
|
140
142
|
fixed,
|
|
143
|
+
focusRules,
|
|
141
144
|
...rest
|
|
142
145
|
}: IReqoreTextareaProps,
|
|
143
146
|
ref
|
|
@@ -152,6 +155,11 @@ const ReqoreInput = forwardRef<HTMLTextAreaElement, IReqoreTextareaProps>(
|
|
|
152
155
|
|
|
153
156
|
useTooltip(targetRef?.current, tooltip);
|
|
154
157
|
useAutosizeTextArea(targetRef?.current, _value, scaleWithContent);
|
|
158
|
+
useAutoFocus(
|
|
159
|
+
targetRef.current,
|
|
160
|
+
rest.readOnly || rest.disabled ? undefined : focusRules,
|
|
161
|
+
onChange
|
|
162
|
+
);
|
|
155
163
|
|
|
156
164
|
return (
|
|
157
165
|
<StyledTextareaWrapper
|
|
@@ -182,15 +190,14 @@ const ReqoreInput = forwardRef<HTMLTextAreaElement, IReqoreTextareaProps>(
|
|
|
182
190
|
rounded={rounded}
|
|
183
191
|
rows={1}
|
|
184
192
|
value={_value}
|
|
193
|
+
readonly={rest?.readOnly}
|
|
194
|
+
/>
|
|
195
|
+
<ReqoreInputClearButton
|
|
196
|
+
enabled={!rest?.readOnly && !rest?.disabled && !!(onClearClick && onChange)}
|
|
197
|
+
show={_value && _value !== ''}
|
|
198
|
+
onClick={onClearClick}
|
|
199
|
+
size={size}
|
|
185
200
|
/>
|
|
186
|
-
{!rest.readOnly && (
|
|
187
|
-
<ReqoreInputClearButton
|
|
188
|
-
enabled={!rest?.disabled && !!(onClearClick && onChange)}
|
|
189
|
-
show={_value && _value !== ''}
|
|
190
|
-
onClick={onClearClick}
|
|
191
|
-
size={size}
|
|
192
|
-
/>
|
|
193
|
-
)}
|
|
194
201
|
</StyledTextareaWrapper>
|
|
195
202
|
);
|
|
196
203
|
}
|