@xqmsg/ui-core 0.25.0 → 0.26.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/dist/components/input/components/token/index.d.ts +1 -0
- package/dist/ui-core.cjs.development.js +119 -33
- package/dist/ui-core.cjs.development.js.map +1 -1
- package/dist/ui-core.cjs.production.min.js +1 -1
- package/dist/ui-core.cjs.production.min.js.map +1 -1
- package/dist/ui-core.esm.js +119 -33
- package/dist/ui-core.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/icons/close/index.tsx +1 -1
- package/src/components/input/Input.stories.tsx +18 -1
- package/src/components/input/StackedPilledInput/index.tsx +105 -21
- package/src/components/input/components/token/index.tsx +25 -6
package/package.json
CHANGED
|
@@ -14,9 +14,9 @@ export const Close: React.FC<CloseProps> = ({ boxSize, onClick }) => {
|
|
|
14
14
|
<CloseIcon
|
|
15
15
|
width={boxSize}
|
|
16
16
|
height={boxSize}
|
|
17
|
-
flexBasis={boxSize}
|
|
18
17
|
onClick={onClick}
|
|
19
18
|
cursor="pointer"
|
|
19
|
+
style={{ flexBasis: boxSize, cursor: 'pointer' }}
|
|
20
20
|
/>
|
|
21
21
|
);
|
|
22
22
|
};
|
|
@@ -113,7 +113,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
113
113
|
return (
|
|
114
114
|
<Form formHandler={formHandler}>
|
|
115
115
|
<Input
|
|
116
|
-
label="
|
|
116
|
+
label="Pilled Text Input - scroll mode"
|
|
117
117
|
name="recipients"
|
|
118
118
|
inputType="pilled-text"
|
|
119
119
|
placeholder="Enter email address..."
|
|
@@ -126,6 +126,23 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
126
126
|
ariaLabel="email input"
|
|
127
127
|
isRequired
|
|
128
128
|
truncatePillLength={1000}
|
|
129
|
+
overflowMode="scroll"
|
|
130
|
+
/>
|
|
131
|
+
<Input
|
|
132
|
+
label="Pilled Text - wrap mode"
|
|
133
|
+
name="recipients"
|
|
134
|
+
inputType="pilled-text"
|
|
135
|
+
placeholder="Enter email address..."
|
|
136
|
+
isInvalid={!!form.formState.errors['prop5']?.message}
|
|
137
|
+
errorText={form.formState.errors['prop5']?.message}
|
|
138
|
+
control={form.control}
|
|
139
|
+
setValue={form.setValue}
|
|
140
|
+
setError={form.setError}
|
|
141
|
+
clearErrors={form.clearErrors}
|
|
142
|
+
ariaLabel="email input"
|
|
143
|
+
isRequired
|
|
144
|
+
truncatePillLength={1000}
|
|
145
|
+
overflowMode="wrap"
|
|
129
146
|
/>
|
|
130
147
|
<Input
|
|
131
148
|
{...args}
|
|
@@ -150,19 +150,58 @@ const StackedPilledInput = React.forwardRef<
|
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
if (e.key === 'Backspace') {
|
|
154
|
+
// If input is empty and there are tokens
|
|
155
|
+
if (!localValue.length && lastestFormValueToArray.length) {
|
|
156
|
+
// If a token is selected, move it to input
|
|
157
|
+
if (tokenIndex !== null) {
|
|
158
|
+
setLocalValue(
|
|
159
|
+
lastestFormValueToArray[tokenIndex].substring(
|
|
160
|
+
0,
|
|
161
|
+
lastestFormValueToArray[tokenIndex].length
|
|
162
|
+
)
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const filteredUniqueValues = Array.from(
|
|
166
|
+
new Set(
|
|
167
|
+
[...lastestFormValueToArray].filter(
|
|
168
|
+
value => value !== lastestFormValueToArray[tokenIndex]
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
setValue(name as string, filteredUniqueValues.toString(), {
|
|
174
|
+
shouldValidate: true,
|
|
175
|
+
shouldDirty: true,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return setTokenIndex(null);
|
|
179
|
+
} else {
|
|
180
|
+
// No token selected, move last token to input
|
|
181
|
+
const lastToken =
|
|
182
|
+
lastestFormValueToArray[lastestFormValueToArray.length - 1];
|
|
183
|
+
setLocalValue(lastToken);
|
|
184
|
+
|
|
185
|
+
const filteredUniqueValues = lastestFormValueToArray.slice(0, -1);
|
|
161
186
|
|
|
187
|
+
setValue(name as string, filteredUniqueValues.toString(), {
|
|
188
|
+
shouldValidate: true,
|
|
189
|
+
shouldDirty: true,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
e.preventDefault();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (e.key === 'Delete') {
|
|
199
|
+
// If a token is selected, remove it completely
|
|
200
|
+
if (tokenIndex !== null && lastestFormValueToArray.length) {
|
|
162
201
|
const filteredUniqueValues = Array.from(
|
|
163
202
|
new Set(
|
|
164
203
|
[...lastestFormValueToArray].filter(
|
|
165
|
-
|
|
204
|
+
(_, index) => index !== tokenIndex
|
|
166
205
|
)
|
|
167
206
|
)
|
|
168
207
|
);
|
|
@@ -172,9 +211,13 @@ const StackedPilledInput = React.forwardRef<
|
|
|
172
211
|
shouldDirty: true,
|
|
173
212
|
});
|
|
174
213
|
|
|
175
|
-
|
|
214
|
+
setTokenIndex(null);
|
|
215
|
+
e.preventDefault();
|
|
216
|
+
return;
|
|
176
217
|
}
|
|
218
|
+
}
|
|
177
219
|
|
|
220
|
+
if (!localValue.trim().length && lastestFormValueToArray.length) {
|
|
178
221
|
if (e.key === 'ArrowLeft') {
|
|
179
222
|
if (tokenIndex === 0) return;
|
|
180
223
|
|
|
@@ -283,6 +326,8 @@ const StackedPilledInput = React.forwardRef<
|
|
|
283
326
|
onClick={() => {
|
|
284
327
|
if (isFocussed && tokenIndex !== null) {
|
|
285
328
|
setTokenIndex(null);
|
|
329
|
+
} else if (!scrollMode) {
|
|
330
|
+
setIsFocussed(true);
|
|
286
331
|
}
|
|
287
332
|
|
|
288
333
|
if (!disabled) {
|
|
@@ -301,7 +346,8 @@ const StackedPilledInput = React.forwardRef<
|
|
|
301
346
|
overflowX={scrollMode ? 'scroll' : 'hidden'}
|
|
302
347
|
flexWrap={scrollMode ? 'nowrap' : 'wrap'}
|
|
303
348
|
overflowY="hidden"
|
|
304
|
-
|
|
349
|
+
width={scrollMode ? 'auto' : '100%'}
|
|
350
|
+
maxWidth={isFocussed && scrollMode ? '80%' : '100%'}
|
|
305
351
|
style={{
|
|
306
352
|
scrollbarWidth: 'none' /* Firefox */,
|
|
307
353
|
msOverflowStyle: 'none',
|
|
@@ -312,29 +358,37 @@ const StackedPilledInput = React.forwardRef<
|
|
|
312
358
|
},
|
|
313
359
|
}}
|
|
314
360
|
ref={scrollRef}
|
|
315
|
-
zIndex={99}
|
|
316
361
|
onKeyDown={onHandleKeyDown}
|
|
317
362
|
>
|
|
318
363
|
{lastestFormValueToArray.length
|
|
319
364
|
? lastestFormValueToArray.map((label, index) => (
|
|
320
365
|
<Box
|
|
321
366
|
key={index}
|
|
322
|
-
mr="
|
|
367
|
+
mr="2px"
|
|
323
368
|
border={
|
|
324
369
|
tokenIndex === index
|
|
325
370
|
? `1px solid ${colors.border.focus}`
|
|
326
371
|
: 'none'
|
|
327
372
|
}
|
|
328
|
-
borderRadius="
|
|
329
|
-
onClick={
|
|
373
|
+
borderRadius="md"
|
|
374
|
+
onClick={e => {
|
|
375
|
+
e.stopPropagation();
|
|
376
|
+
// Don't change selection if clicking on already selected token
|
|
377
|
+
if (tokenIndex === index) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
setTokenIndex(index);
|
|
381
|
+
}}
|
|
330
382
|
width={scrollMode ? '100%' : 'auto'}
|
|
331
383
|
maxWidth={'100%'}
|
|
332
384
|
id={`${name}_token_${index}`}
|
|
385
|
+
cursor="default"
|
|
333
386
|
>
|
|
334
387
|
<Token
|
|
335
388
|
maxWidth={'100%'}
|
|
336
389
|
label={label}
|
|
337
|
-
showClose={
|
|
390
|
+
showClose={true}
|
|
391
|
+
isSelected={tokenIndex === index}
|
|
338
392
|
onDelete={(e: any) => {
|
|
339
393
|
e.stopPropagation();
|
|
340
394
|
e.preventDefault();
|
|
@@ -350,12 +404,46 @@ const StackedPilledInput = React.forwardRef<
|
|
|
350
404
|
<Text
|
|
351
405
|
color={colors.label.secondary.light}
|
|
352
406
|
fontSize={isMobile ? '17px' : '13px'}
|
|
407
|
+
pointerEvents="none"
|
|
353
408
|
>
|
|
354
409
|
{placeholder}
|
|
355
410
|
</Text>
|
|
356
411
|
) : null}
|
|
412
|
+
{!disabled && !scrollMode && (
|
|
413
|
+
<Flex
|
|
414
|
+
flex={1}
|
|
415
|
+
minWidth={isFocussed && !tokenIndex ? 'auto' : '100px'}
|
|
416
|
+
>
|
|
417
|
+
<Input
|
|
418
|
+
onKeyDown={onHandleKeyDown}
|
|
419
|
+
type="text"
|
|
420
|
+
padding={0}
|
|
421
|
+
alignContent="flex-start"
|
|
422
|
+
float="right"
|
|
423
|
+
border="none"
|
|
424
|
+
height="auto"
|
|
425
|
+
color={
|
|
426
|
+
tokenIndex !== null ? 'transparent' : colors.label.primary
|
|
427
|
+
}
|
|
428
|
+
_focus={{ boxShadow: 'none !important' }}
|
|
429
|
+
value={localValue}
|
|
430
|
+
onChange={handleOnChange}
|
|
431
|
+
ref={inputRef}
|
|
432
|
+
onFocus={() => setIsFocussed(true)}
|
|
433
|
+
fontSize={isMobile ? '17px' : '13px'}
|
|
434
|
+
lineHeight={1.5}
|
|
435
|
+
placeholder={
|
|
436
|
+
isMobile && label && lastestFormValueToArray.length === 0
|
|
437
|
+
? (label as string)
|
|
438
|
+
: ''
|
|
439
|
+
}
|
|
440
|
+
variant={variant}
|
|
441
|
+
style={isMobile ? { border: 'none' } : undefined}
|
|
442
|
+
/>
|
|
443
|
+
</Flex>
|
|
444
|
+
)}
|
|
357
445
|
</Flex>
|
|
358
|
-
{!disabled && (
|
|
446
|
+
{!disabled && scrollMode && (
|
|
359
447
|
<Flex flex={1} minWidth={isFocussed && !tokenIndex ? '20%' : 0}>
|
|
360
448
|
<Input
|
|
361
449
|
onKeyDown={onHandleKeyDown}
|
|
@@ -373,10 +461,6 @@ const StackedPilledInput = React.forwardRef<
|
|
|
373
461
|
onChange={handleOnChange}
|
|
374
462
|
ref={inputRef}
|
|
375
463
|
onFocus={() => setIsFocussed(true)}
|
|
376
|
-
onBlur={() => {
|
|
377
|
-
setIsFocussed(false);
|
|
378
|
-
return setTokenIndex(null);
|
|
379
|
-
}}
|
|
380
464
|
placeholder={
|
|
381
465
|
isMobile && label && lastestFormValueToArray.length === 0
|
|
382
466
|
? (label as string)
|
|
@@ -11,6 +11,7 @@ export interface TokenProps {
|
|
|
11
11
|
truncateLength?: number;
|
|
12
12
|
showClose?: boolean;
|
|
13
13
|
maxWidth?: string | number;
|
|
14
|
+
isSelected?: boolean;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
// For v1 we are truncating the label at 15 characters to avoid overflow
|
|
@@ -21,28 +22,35 @@ const Token: React.FC<TokenProps> = ({
|
|
|
21
22
|
truncateLength = 15,
|
|
22
23
|
showClose = true,
|
|
23
24
|
maxWidth = 'auto',
|
|
25
|
+
isSelected = false,
|
|
24
26
|
}) => {
|
|
27
|
+
// in pixels
|
|
28
|
+
const closeBoxSize = isMobile ? 20 : 15;
|
|
29
|
+
const closeBoxGap = isMobile ? 4 : 2;
|
|
30
|
+
const closeBoxPadding = closeBoxSize + closeBoxGap;
|
|
25
31
|
return (
|
|
26
32
|
<Flex
|
|
27
33
|
key={label}
|
|
28
|
-
borderRadius={'
|
|
34
|
+
borderRadius={'md'}
|
|
29
35
|
backgroundColor="#7676801F"
|
|
30
36
|
alignItems="center"
|
|
31
37
|
width="fit-content"
|
|
32
38
|
w="auto"
|
|
33
39
|
maxWidth={maxWidth}
|
|
34
|
-
h={
|
|
35
|
-
|
|
36
|
-
pr="2px"
|
|
40
|
+
h={'18px'}
|
|
41
|
+
px="4px"
|
|
37
42
|
py="2px"
|
|
43
|
+
pr={showClose ? closeBoxPadding : '4px'}
|
|
38
44
|
position="relative"
|
|
45
|
+
cursor="default"
|
|
39
46
|
>
|
|
40
47
|
<Text
|
|
41
48
|
whiteSpace="nowrap"
|
|
42
49
|
wordBreak="break-word"
|
|
43
50
|
color={colors.label.primary.light}
|
|
44
51
|
fontSize={isMobile ? '17px' : '13px'}
|
|
45
|
-
|
|
52
|
+
lineHeight="1.5"
|
|
53
|
+
pr="2px"
|
|
46
54
|
maxWidth={maxWidth}
|
|
47
55
|
overflow="hidden"
|
|
48
56
|
textOverflow="ellipsis"
|
|
@@ -53,7 +61,18 @@ const Token: React.FC<TokenProps> = ({
|
|
|
53
61
|
})}
|
|
54
62
|
</Text>
|
|
55
63
|
{showClose && (
|
|
56
|
-
<
|
|
64
|
+
<Flex
|
|
65
|
+
height="100%"
|
|
66
|
+
position="absolute"
|
|
67
|
+
top={0}
|
|
68
|
+
bottom={0}
|
|
69
|
+
right={0}
|
|
70
|
+
justifyContent="center"
|
|
71
|
+
alignItems="center"
|
|
72
|
+
cursor={isSelected ? 'default' : 'pointer'}
|
|
73
|
+
>
|
|
74
|
+
<Close boxSize={`${closeBoxSize}px`} onClick={onDelete} />
|
|
75
|
+
</Flex>
|
|
57
76
|
)}
|
|
58
77
|
</Flex>
|
|
59
78
|
);
|