@qoretechnologies/reqore 0.31.1 → 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 +5 -2
- package/dist/components/Collection/index.d.ts.map +1 -1
- package/dist/components/Collection/index.js +10 -5
- package/dist/components/Collection/index.js.map +1 -1
- package/dist/components/Collection/item.d.ts.map +1 -1
- package/dist/components/Collection/item.js +1 -1
- package/dist/components/Collection/item.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 +4 -2
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +18 -14
- 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/dist/types/global.d.ts +11 -0
- package/dist/types/global.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/components/Button/index.tsx +1 -0
- package/src/components/Collection/index.tsx +34 -7
- package/src/components/Collection/item.tsx +1 -0
- 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 +34 -26
- package/src/components/Textarea/index.tsx +15 -8
- package/src/hooks/useAutoFocus.ts +104 -0
- package/src/mock/collectionData.tsx +1 -0
- package/src/stories/Collection/Collection.stories.tsx +84 -10
- package/src/stories/Input/Input.stories.tsx +29 -6
- package/src/stories/Panel/Panel.stories.tsx +20 -2
- package/src/stories/TextArea/TextArea.stories.tsx +1 -0
- package/src/styles.ts +0 -1
- package/src/types/global.ts +12 -0
- package/tests.json +1 -1
|
@@ -2,11 +2,13 @@ import { size } from 'lodash';
|
|
|
2
2
|
import { useMemo, useState } from 'react';
|
|
3
3
|
import { useUpdateEffect } from 'react-use';
|
|
4
4
|
import styled, { css } from 'styled-components';
|
|
5
|
+
import { PADDING_FROM_SIZE } from '../../constants/sizes';
|
|
5
6
|
import { IReqoreIconName } from '../../types/icons';
|
|
6
7
|
import { IReqoreColumnsProps, StyledColumns } from '../Columns';
|
|
7
8
|
import ReqoreInput, { IReqoreInputProps } from '../Input';
|
|
8
9
|
import ReqoreMessage from '../Message';
|
|
9
10
|
import { IReqorePanelAction, IReqorePanelProps, ReqorePanel, TReqorePanelActions } from '../Panel';
|
|
11
|
+
import { ReqoreVerticalSpacer } from '../Spacer';
|
|
10
12
|
import { sortTableData } from '../Table/helpers';
|
|
11
13
|
import { IReqoreCollectionItemProps, ReqoreCollectionItem } from './item';
|
|
12
14
|
|
|
@@ -26,6 +28,8 @@ export interface IReqoreCollectionProps
|
|
|
26
28
|
| 'minimal'
|
|
27
29
|
| 'transparent'
|
|
28
30
|
| 'fluid'
|
|
31
|
+
| 'responsiveActions'
|
|
32
|
+
| 'padded'
|
|
29
33
|
>,
|
|
30
34
|
IReqoreColumnsProps {
|
|
31
35
|
items?: IReqoreCollectionItemProps[];
|
|
@@ -43,6 +47,11 @@ export interface IReqoreCollectionProps
|
|
|
43
47
|
showSelectedFirst?: boolean;
|
|
44
48
|
selectedIcon?: IReqoreIconName;
|
|
45
49
|
|
|
50
|
+
childrenBefore?: React.ReactNode;
|
|
51
|
+
childrenAfter?: React.ReactNode;
|
|
52
|
+
|
|
53
|
+
onQueryChange?: (query: string) => void;
|
|
54
|
+
|
|
46
55
|
emptyMessage?: string;
|
|
47
56
|
sortButtonTooltip?: (sort?: 'asc' | 'desc') => string;
|
|
48
57
|
displayButtonTooltip?: (display?: 'list' | 'grid') => string;
|
|
@@ -50,7 +59,7 @@ export interface IReqoreCollectionProps
|
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
export const StyledCollectionWrapper = styled(StyledColumns)`
|
|
53
|
-
height: ${({ height }) => (height ? `${height}
|
|
62
|
+
height: ${({ height }) => (height ? `${height}` : 'auto')};
|
|
54
63
|
|
|
55
64
|
${({ rounded, stacked }: IReqoreCollectionProps) =>
|
|
56
65
|
(!rounded || stacked) &&
|
|
@@ -58,7 +67,7 @@ export const StyledCollectionWrapper = styled(StyledColumns)`
|
|
|
58
67
|
border-radius: ${stacked && rounded ? '10px' : undefined};
|
|
59
68
|
`}
|
|
60
69
|
|
|
61
|
-
overflow:
|
|
70
|
+
overflow: auto;
|
|
62
71
|
position: relative;
|
|
63
72
|
`;
|
|
64
73
|
|
|
@@ -68,7 +77,6 @@ export const ReqoreCollection = ({
|
|
|
68
77
|
stacked,
|
|
69
78
|
rounded = true,
|
|
70
79
|
fill,
|
|
71
|
-
height,
|
|
72
80
|
maxItemHeight,
|
|
73
81
|
filterable,
|
|
74
82
|
sortable,
|
|
@@ -82,11 +90,13 @@ export const ReqoreCollection = ({
|
|
|
82
90
|
flat = true,
|
|
83
91
|
minimal,
|
|
84
92
|
transparent = true,
|
|
85
|
-
|
|
93
|
+
onQueryChange,
|
|
94
|
+
childrenBefore,
|
|
95
|
+
childrenAfter,
|
|
86
96
|
emptyMessage = 'No data in this collection, try changing your search query or filters',
|
|
87
97
|
sortButtonTooltip = (sort) => (sort === 'desc' ? 'Sort ascending' : 'Sort descending'),
|
|
88
98
|
displayButtonTooltip = (display) => (display === 'grid' ? 'Show as list' : 'Show as grid'),
|
|
89
|
-
inputPlaceholder = (items) => `
|
|
99
|
+
inputPlaceholder = (items) => `Search in ${size(items)} items`,
|
|
90
100
|
...rest
|
|
91
101
|
}: IReqoreCollectionProps) => {
|
|
92
102
|
const [_showAs, setShowAs] = useState<'list' | 'grid'>(showAs);
|
|
@@ -97,6 +107,10 @@ export const ReqoreCollection = ({
|
|
|
97
107
|
setShowAs(showAs);
|
|
98
108
|
}, [showAs]);
|
|
99
109
|
|
|
110
|
+
useUpdateEffect(() => {
|
|
111
|
+
onQueryChange?.(query);
|
|
112
|
+
}, [query]);
|
|
113
|
+
|
|
100
114
|
const sortedItems: IReqoreCollectionItemProps[] = useMemo(() => {
|
|
101
115
|
if (!sortable) {
|
|
102
116
|
return items;
|
|
@@ -182,6 +196,8 @@ export const ReqoreCollection = ({
|
|
|
182
196
|
{
|
|
183
197
|
as: ReqoreInput,
|
|
184
198
|
props: {
|
|
199
|
+
key: 'search',
|
|
200
|
+
fixed: false,
|
|
185
201
|
placeholder: inputPlaceholder(finalItems),
|
|
186
202
|
onClearClick: () => setQuery(''),
|
|
187
203
|
onChange: handleQueryChange,
|
|
@@ -203,16 +219,20 @@ export const ReqoreCollection = ({
|
|
|
203
219
|
headerSize={headerSize}
|
|
204
220
|
style={{
|
|
205
221
|
...rest.style,
|
|
206
|
-
height: height ?? undefined,
|
|
207
222
|
}}
|
|
208
223
|
fill={fill}
|
|
209
|
-
padded
|
|
210
224
|
transparent={transparent}
|
|
211
225
|
minimal={minimal}
|
|
212
226
|
flat={flat}
|
|
213
227
|
actions={finalActions}
|
|
214
228
|
className={`reqore-collection ${rest.className || ''}`}
|
|
215
229
|
>
|
|
230
|
+
{childrenBefore ? (
|
|
231
|
+
<>
|
|
232
|
+
{childrenBefore}
|
|
233
|
+
<ReqoreVerticalSpacer height={PADDING_FROM_SIZE[rest.size || 'normal']} />
|
|
234
|
+
</>
|
|
235
|
+
) : null}
|
|
216
236
|
{!size(finalItems) ? (
|
|
217
237
|
<ReqoreMessage flat icon='Search2Line'>
|
|
218
238
|
{emptyMessage}
|
|
@@ -227,6 +247,7 @@ export const ReqoreCollection = ({
|
|
|
227
247
|
>
|
|
228
248
|
{finalItems?.map((item, index) => (
|
|
229
249
|
<ReqoreCollectionItem
|
|
250
|
+
size={rest.size}
|
|
230
251
|
{...item}
|
|
231
252
|
icon={item.icon || (item.selected ? selectedIcon : undefined)}
|
|
232
253
|
key={index}
|
|
@@ -236,6 +257,12 @@ export const ReqoreCollection = ({
|
|
|
236
257
|
))}
|
|
237
258
|
</StyledCollectionWrapper>
|
|
238
259
|
)}
|
|
260
|
+
{childrenAfter ? (
|
|
261
|
+
<>
|
|
262
|
+
<ReqoreVerticalSpacer height={PADDING_FROM_SIZE[rest.size || 'normal']} />
|
|
263
|
+
{childrenAfter}
|
|
264
|
+
</>
|
|
265
|
+
) : null}
|
|
239
266
|
</ReqorePanel>
|
|
240
267
|
);
|
|
241
268
|
};
|
|
@@ -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;
|