@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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.25.0",
2
+ "version": "0.26.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -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="To"
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 (!localValue.trim().length && lastestFormValueToArray.length) {
154
- if (e.key === 'Backspace' && tokenIndex !== null) {
155
- setLocalValue(
156
- lastestFormValueToArray[tokenIndex].substring(
157
- 0,
158
- lastestFormValueToArray[tokenIndex].length
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
- value => value !== lastestFormValueToArray[tokenIndex]
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
- return setTokenIndex(null);
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
- maxWidth={isFocussed ? '80%' : '100%'}
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="4px"
367
+ mr="2px"
323
368
  border={
324
369
  tokenIndex === index
325
370
  ? `1px solid ${colors.border.focus}`
326
371
  : 'none'
327
372
  }
328
- borderRadius="full"
329
- onClick={() => setTokenIndex(index)}
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={!isFocussed || tokenIndex === index}
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={'full'}
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={isMobile ? '18px' : '16px'}
35
- pl="6px"
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
- pr="4px"
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
- <Close boxSize={isMobile ? '17px' : '11px'} onClick={onDelete} />
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
  );