@platformatic/ui-components 0.1.92 → 0.1.94

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.
Files changed (36) hide show
  1. package/dist/assets/index.194e494c.css +1 -0
  2. package/dist/assets/index.a0469c60.js +206 -0
  3. package/dist/index.html +2 -2
  4. package/index.js +2 -0
  5. package/package.json +1 -1
  6. package/src/components/Common.module.css +3 -0
  7. package/src/components/Logo.jsx +9 -5
  8. package/src/components/Logo.module.css +4 -1
  9. package/src/components/LogoDropDown.jsx +82 -0
  10. package/src/components/LogoDropDown.module.css +30 -0
  11. package/src/components/backgrounds/AppBackgroundIcon.jsx +12 -12
  12. package/src/components/backgrounds/LensBackgroundIcon.jsx +2 -2
  13. package/src/components/backgrounds/TimerBackgroundIcon.jsx +5 -5
  14. package/src/components/constants.js +1 -1
  15. package/src/components/forms/Input.jsx +15 -7
  16. package/src/components/forms/Input.module.css +5 -6
  17. package/src/components/forms/InputWithSeparator.jsx +134 -0
  18. package/src/components/forms/InputWithSeparator.module.css +24 -0
  19. package/src/components/forms/index.js +3 -2
  20. package/src/components/icons/CheckListIcon.jsx +98 -0
  21. package/src/components/icons/Icons.module.css +28 -16
  22. package/src/components/icons/SlotIcon.jsx +88 -0
  23. package/src/components/icons/SwitchIcon.jsx +81 -0
  24. package/src/components/icons/TeamsIcon.jsx +91 -0
  25. package/src/components/icons/WorkspaceEmptyIcon.jsx +1 -1
  26. package/src/components/icons/index.js +9 -0
  27. package/src/components/logos/AdvancedLogo.jsx +59 -0
  28. package/src/components/logos/BasicLogo.jsx +22 -20
  29. package/src/components/logos/FreeLogo.jsx +22 -20
  30. package/src/components/logos/ProLogo.jsx +60 -0
  31. package/src/components/logos/index.js +5 -1
  32. package/src/stories/LogoDropDown.stories.jsx +43 -0
  33. package/src/stories/forms/Input.stories.jsx +10 -1
  34. package/src/stories/forms/InputWithSeparator.stories.jsx +55 -0
  35. package/dist/assets/index.1ec7065b.css +0 -1
  36. package/dist/assets/index.e3fdc2c7.js +0 -206
package/dist/index.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Platformatic UI Components</title>
7
- <script type="module" crossorigin src="/assets/index.e3fdc2c7.js"></script>
8
- <link rel="stylesheet" href="/assets/index.1ec7065b.css">
7
+ <script type="module" crossorigin src="/assets/index.a0469c60.js"></script>
8
+ <link rel="stylesheet" href="/assets/index.194e494c.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/index.js CHANGED
@@ -23,6 +23,7 @@ import Loadable from './src/components/Loadable'
23
23
  import LoadingSpinner from './src/components/LoadingSpinner'
24
24
  import LoginButton from './src/components/LoginButton'
25
25
  import Logo from './src/components/Logo'
26
+ import LogoDropDown from './src/components/LogoDropDown'
26
27
  import Logos from './src/components/logos'
27
28
  import Modal from './src/components/Modal'
28
29
  import PlatformaticIcon from './src/components/PlatformaticIcon'
@@ -62,6 +63,7 @@ export {
62
63
  LoadingSpinner,
63
64
  LoginButton,
64
65
  Logo,
66
+ LogoDropDown,
65
67
  Modal,
66
68
  PlatformaticIcon,
67
69
  Playground,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@platformatic/ui-components",
3
3
  "description": "Platformatic UI Components",
4
- "version": "0.1.92",
4
+ "version": "0.1.94",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -183,4 +183,7 @@
183
183
  }
184
184
  .fontLight {
185
185
  @apply font-light;
186
+ }
187
+ .fullWidth {
188
+ @apply w-full;
186
189
  }
@@ -1,11 +1,13 @@
1
1
  import React from 'react'
2
2
  import styles from './Logo.module.css'
3
- export default function Logo ({ width = 107, heigth = 86, color = 'white' }) {
3
+ export default function Logo ({ width = 107, height = 86, color = 'white', fillColor = 'none' }) {
4
4
  const className = styles[`${color}`]
5
+ const filledClassName = styles[`filled--${fillColor}`]
6
+
5
7
  return (
6
8
  <svg
7
9
  width={width}
8
- height={heigth}
10
+ height={height}
9
11
  viewBox='0 0 107 86'
10
12
  fill='none'
11
13
  xmlns='http://www.w3.org/2000/svg'
@@ -18,6 +20,8 @@ export default function Logo ({ width = 107, heigth = 86, color = 'white' }) {
18
20
  strokeWidth={4.21053}
19
21
  strokeLinecap='round'
20
22
  strokeLinejoin='round'
23
+ fill='none'
24
+ className={filledClassName}
21
25
  />
22
26
  <path
23
27
  d='M41.4979 35.2219L33.6299 37.9838L37.0924 45.3197'
@@ -34,7 +38,7 @@ export default function Logo ({ width = 107, heigth = 86, color = 'white' }) {
34
38
  strokeLinejoin='round'
35
39
  />
36
40
  <path
37
- opacity='0.2'
41
+ opacity={0.2}
38
42
  d='M24.498 79.7146V83.0001'
39
43
  stroke='#21FA90'
40
44
  strokeWidth={4.21053}
@@ -42,7 +46,7 @@ export default function Logo ({ width = 107, heigth = 86, color = 'white' }) {
42
46
  strokeLinejoin='round'
43
47
  />
44
48
  <path
45
- opacity='0.4'
49
+ opacity={0.4}
46
50
  d='M24.5283 69.3757V74.5658'
47
51
  stroke='#21FA90'
48
52
  strokeWidth={4.21053}
@@ -50,7 +54,7 @@ export default function Logo ({ width = 107, heigth = 86, color = 'white' }) {
50
54
  strokeLinejoin='round'
51
55
  />
52
56
  <path
53
- opacity='0.7'
57
+ opacity={0.7}
54
58
  d='M24.498 55.3254V64.0028'
55
59
  stroke='#21FA90'
56
60
  strokeWidth={4.21053}
@@ -3,4 +3,7 @@
3
3
  }
4
4
  .main-dark-blue > path[id='platformatic-cloud']{
5
5
  @apply stroke-main-dark-blue
6
- }
6
+ }
7
+ .filled--main-dark-blue {
8
+ @apply fill-main-dark-blue;
9
+ }
@@ -0,0 +1,82 @@
1
+ 'use strict'
2
+ import React, { useState } from 'react'
3
+ import PropTypes from 'prop-types'
4
+ import styles from './LogoDropDown.module.css'
5
+ import PlatformaticIcon from './PlatformaticIcon'
6
+ import { MAIN_DARK_BLUE, SMALL, WHITE } from './constants'
7
+ import Logo from './Logo'
8
+ function LogoDropDown ({ itemSelected, items, width, height }) {
9
+ const [open, setOpen] = useState(false)
10
+
11
+ function handleOpen () {
12
+ setOpen(!open)
13
+ }
14
+
15
+ function getItemsSelected () {
16
+ return items.find(item => item.id === itemSelected)?.name
17
+ }
18
+
19
+ function onClick (callback) {
20
+ handleOpen()
21
+ callback()
22
+ }
23
+
24
+ return (
25
+ <div className={styles.container}>
26
+ <div className={styles.dropDown}>
27
+ <div className={styles.logoContainer}>
28
+ <Logo width={width} height={height} color={WHITE} fillColor={MAIN_DARK_BLUE} />
29
+ </div>
30
+ <div className={styles.selectorContainer} style={{ left: width / 2, paddingLeft: width / 3 }} onClick={() => handleOpen()}>
31
+ <p className={styles.header}>{getItemsSelected()}</p>
32
+ {!open && <PlatformaticIcon iconName='ArrowDownIcon' color={MAIN_DARK_BLUE} onClick={null} />}
33
+ {open && <PlatformaticIcon iconName='ArrowUpIcon' color={MAIN_DARK_BLUE} onClick={null} />}
34
+ </div>
35
+ </div>
36
+ {open && (
37
+ <div className={styles.menuContainer}>
38
+ <div className={styles.menu} style={{ width: `calc(100% - ${width}px)` }}>
39
+ {items.map((item, index) => {
40
+ return (
41
+ <div className={styles.item} key={index} onClick={() => onClick(item.handleClick)}>
42
+ <PlatformaticIcon iconName='OrganizationIcon' color={MAIN_DARK_BLUE} size={SMALL} onClick={null} /><span className={styles.itemName}>{item.name}</span>
43
+ </div>
44
+ )
45
+ })}
46
+ </div>
47
+ </div>
48
+ )}
49
+ </div>
50
+ )
51
+ }
52
+
53
+ LogoDropDown.propTypes = {
54
+ /**
55
+ * width
56
+ */
57
+ width: PropTypes.number,
58
+ /**
59
+ * height
60
+ */
61
+ height: PropTypes.number,
62
+ /**
63
+ * itemSelected
64
+ */
65
+ itemSelected: PropTypes.string,
66
+ /**
67
+ * items
68
+ */
69
+ items: PropTypes.arrayOf(PropTypes.shape({
70
+ id: PropTypes.string.isRequired,
71
+ name: PropTypes.string,
72
+ handleClick: PropTypes.func
73
+ }))
74
+ }
75
+
76
+ LogoDropDown.defaultProps = {
77
+ width: 71,
78
+ height: 56,
79
+ itemSelected: '',
80
+ items: []
81
+ }
82
+ export default LogoDropDown
@@ -0,0 +1,30 @@
1
+ .container {
2
+ @apply relative min-w-[263px] max-w-[263px];
3
+ }
4
+ .menuContainer {
5
+ @apply min-w-[263px] max-w-[263px] absolute top-[43px];
6
+ }
7
+ .dropDown {
8
+ @apply relative flex items-center;
9
+ }
10
+ .logoContainer {
11
+ @apply relative z-10;
12
+ }
13
+ .selectorContainer {
14
+ @apply absolute top-[50%] translate-y-[-50%] flex items-center gap-x-1 bg-white p-0.5 pr-3 rounded-full mt-[0.5px] cursor-pointer;
15
+ }
16
+ .header {
17
+ @apply flex items-center hover:cursor-pointer pr-2 font-light text-main-dark-blue ml-4 text-ellipsis overflow-hidden whitespace-nowrap min-w-[155px] max-w-[155px] w-full;
18
+ }
19
+ .picture {
20
+ @apply border border-transparent rounded-full mr-2;
21
+ }
22
+ .menu {
23
+ @apply absolute top-0 right-0 border border-main-dark-blue p-0 z-10 text-sm bg-white rounded-md w-fit z-20;
24
+ }
25
+ .item {
26
+ @apply inline-flex gap-x-2 py-2 px-5 first:border-t-0 tracking-wide text-sm font-normal leading-4 hover:font-semibold hover:cursor-pointer border-t text-main-dark-blue w-full;
27
+ }
28
+ .itemName {
29
+ @apply text-ellipsis overflow-hidden whitespace-nowrap;
30
+ }
@@ -4,18 +4,18 @@ const AppBackgroundIcon = () => {
4
4
  return (
5
5
  <svg width='669' height='669' viewBox='0 0 669 669' fill='none' xmlns='http://www.w3.org/2000/svg'>
6
6
  <g opacity='0.05'>
7
- <path d='M286.786 380.769H217.563C203.362 380.769 191.851 392.28 191.851 406.48V537.332C191.851 551.532 203.362 563.044 217.563 563.044H450.944C465.144 563.044 476.656 551.532 476.656 537.332V406.48C476.656 392.28 465.144 380.769 450.944 380.769H381.721' stroke='white' stroke-width='31' stroke-linecap='round' />
8
- <rect x='286.786' y='563.042' width='94.9349' height='45.5688' stroke='white' stroke-width='31' />
9
- <path d='M239.318 634.324C239.318 620.123 250.829 608.612 265.029 608.612H403.476C417.676 608.612 429.188 620.123 429.188 634.324V642.789H239.318V634.324Z' stroke='white' stroke-width='31' />
10
- <path d='M334.253 357.983L355.567 420.958H424.541L368.74 459.878L390.054 522.853L334.253 483.932L278.451 522.853L299.766 459.878L243.964 420.958H312.939L334.253 357.983Z' stroke='white' stroke-width='31' stroke-linejoin='round' />
11
- <path d='M156.246 476.653H73.1784V310.516' stroke='white' stroke-width='31' stroke-linecap='round' stroke-linejoin='round' />
12
- <path d='M239.315 334.25V120.647' stroke='white' stroke-width='31' stroke-linecap='round' stroke-linejoin='round' />
13
- <path d='M512.253 476.652H595.321V381.718' stroke='white' stroke-width='31' stroke-linecap='round' stroke-linejoin='round' />
14
- <path d='M405.451 346.117V274.916H488.519V144.38' stroke='white' stroke-width='31' stroke-linecap='round' stroke-linejoin='round' />
15
- <circle cx='73.179' cy='263.049' r='47.4675' stroke='white' stroke-width='31' />
16
- <circle cx='239.315' cy='73.1789' r='47.4675' stroke='white' stroke-width='31' />
17
- <circle cx='488.52' cy='96.9123' r='47.4675' stroke='white' stroke-width='31' />
18
- <circle cx='595.321' cy='334.25' r='47.4675' stroke='white' stroke-width='31' />
7
+ <path d='M286.786 380.769H217.563C203.362 380.769 191.851 392.28 191.851 406.48V537.332C191.851 551.532 203.362 563.044 217.563 563.044H450.944C465.144 563.044 476.656 551.532 476.656 537.332V406.48C476.656 392.28 465.144 380.769 450.944 380.769H381.721' stroke='white' stroke-width='31' strokeLinecap='round' />
8
+ <rect x='286.786' y='563.042' width='94.9349' height='45.5688' stroke='white' strokeWidth={31} />
9
+ <path d='M239.318 634.324C239.318 620.123 250.829 608.612 265.029 608.612H403.476C417.676 608.612 429.188 620.123 429.188 634.324V642.789H239.318V634.324Z' stroke='white' strokeWidth={31} />
10
+ <path d='M334.253 357.983L355.567 420.958H424.541L368.74 459.878L390.054 522.853L334.253 483.932L278.451 522.853L299.766 459.878L243.964 420.958H312.939L334.253 357.983Z' stroke='white' strokeWidth={31} strokeLinejoin='round' />
11
+ <path d='M156.246 476.653H73.1784V310.516' stroke='white' strokeWidth={31} strokeLinecap='round' strokeLinejoin='round' />
12
+ <path d='M239.315 334.25V120.647' stroke='white' strokeWidth={31} strokeLinecap='round' strokeLinejoin='round' />
13
+ <path d='M512.253 476.652H595.321V381.718' stroke='white' strokeWidth={31} strokeLinecap='round' strokeLinejoin='round' />
14
+ <path d='M405.451 346.117V274.916H488.519V144.38' stroke='white' strokeWidth={31} strokeLinecap='round' strokeLinejoin='round' />
15
+ <circle cx='73.179' cy='263.049' r='47.4675' stroke='white' strokeWidth={31} />
16
+ <circle cx='239.315' cy='73.1789' r='47.4675' stroke='white' strokeWidth={31} />
17
+ <circle cx='488.52' cy='96.9123' r='47.4675' stroke='white' strokeWidth={31} />
18
+ <circle cx='595.321' cy='334.25' r='47.4675' stroke='white' strokeWidth={31} />
19
19
  </g>
20
20
  </svg>
21
21
  )
@@ -4,8 +4,8 @@ const LensBackgroundIcon = () => {
4
4
  return (
5
5
  <svg width='828' height='828' viewBox='0 0 828 828' fill='none' xmlns='http://www.w3.org/2000/svg'>
6
6
  <g opacity='0.05'>
7
- <circle cx='258.75' cy='258.75' r='258.75' transform='matrix(-1 0 0 1 724.5 103.5)' stroke='white' stroke-width='41.4' />
8
- <path d='M103.5 724.5L258.75 569.25' stroke='white' stroke-width='41.4' stroke-linecap='round' stroke-linejoin='round' />
7
+ <circle cx='258.75' cy='258.75' r='258.75' transform='matrix(-1 0 0 1 724.5 103.5)' stroke='white' strokeWidth={41.4} />
8
+ <path d='M103.5 724.5L258.75 569.25' stroke='white' strokeWidth={41.4} strokeLinecap='round' strokeLinejoin='round' />
9
9
  </g>
10
10
  </svg>
11
11
  )
@@ -4,11 +4,11 @@ const TimerBackgroundIcon = () => {
4
4
  return (
5
5
  <svg width='828' height='828' viewBox='0 0 828 828' fill='none' xmlns='http://www.w3.org/2000/svg'>
6
6
  <g opacity='0.05'>
7
- <ellipse cx='409.996' cy='451.818' rx='254.746' ry='255.434' stroke='white' stroke-width='41.4' />
8
- <path d='M409.988 196.385V103.5M317.353 103.5H502.622' stroke='white' stroke-width='41.4' stroke-linecap='round' stroke-linejoin='round' />
9
- <path d='M607.247 255.825L640.369 223.361M607.992 190.15L672.746 256.572' stroke='white' stroke-width='41.4' stroke-linecap='round' stroke-linejoin='round' />
10
- <path d='M222.392 259.332L190.165 225.975M156.897 258.289L223.432 193.66' stroke='white' stroke-width='41.4' stroke-linecap='round' stroke-linejoin='round' />
11
- <path d='M491.054 335.708L409.994 475.036' stroke='white' stroke-width='41.4' stroke-linecap='round' stroke-linejoin='round' />
7
+ <ellipse cx='409.996' cy='451.818' rx='254.746' ry='255.434' stroke='white' strokeWidth={41.4} />
8
+ <path d='M409.988 196.385V103.5M317.353 103.5H502.622' stroke='white' strokeWidth={41.4} strokeLinecap='round' strokeLinejoin='round' />
9
+ <path d='M607.247 255.825L640.369 223.361M607.992 190.15L672.746 256.572' stroke='white' strokeWidth={41.4} strokeLinecap='round' strokeLinejoin='round' />
10
+ <path d='M222.392 259.332L190.165 225.975M156.897 258.289L223.432 193.66' stroke='white' strokeWidth={41.4} strokeLinecap='round' strokeLinejoin='round' />
11
+ <path d='M491.054 335.708L409.994 475.036' stroke='white' strokeWidth={41.4} strokeLinecap='round' strokeLinejoin='round' />
12
12
  </g>
13
13
  </svg>
14
14
 
@@ -25,7 +25,7 @@ export const FULL_WIDTH = 'full-width'
25
25
  export const HOVER_EFFECTS_BUTTONS = [BOX_SHADOW, BACKGROUND_COLOR_OPAQUE, UNDERLINE]
26
26
  export const MODAL_SIZES = [SMALL, MEDIUM, FULL_WIDTH]
27
27
 
28
- export const COLORS_ICON = [MAIN_GREEN, WHITE, MAIN_DARK_BLUE, ERROR_RED, WARNING_YELLOW]
28
+ export const COLORS_ICON = [MAIN_GREEN, WHITE, MAIN_DARK_BLUE, ERROR_RED, WARNING_YELLOW, TERTIARY_BLUE]
29
29
  export const COLORS_BUTTON = [MAIN_GREEN, DARK_GREEN, LIGHT_GREEN, MAIN_DARK_BLUE, DARK_BLUE, LIGHT_BLUE, WHITE, ERROR_RED, TERTIARY_BLUE, TRANSPARENT]
30
30
  export const COLORS_BORDERED_BOX = [MAIN_GREEN, ERROR_RED, WHITE, DARK_BLUE, MAIN_DARK_BLUE, WARNING_YELLOW, TRANSPARENT]
31
31
 
@@ -4,20 +4,23 @@ import PropTypes from 'prop-types'
4
4
  import styles from './Input.module.css'
5
5
  import commonStyles from '../Common.module.css'
6
6
  import PlatformaticIcon from '../PlatformaticIcon'
7
- import { MAIN_GREEN } from '../constants'
7
+ import { MAIN_DARK_BLUE, MAIN_GREEN } from '../constants'
8
8
  import BorderedBox from '../BorderedBox'
9
9
 
10
- function Input ({ placeholder, value, name, borderColor, errorMessage, onChange, disabled, beforeIcon, afterIcon, focused }) {
10
+ function Input ({ placeholder, value, name, borderColor, errorMessage, onChange, disabled, beforeIcon, afterIcon, focused, placeholderApart }) {
11
11
  let className = styles.inputContainer + ' ' + commonStyles[`bordered--${borderColor}`] + ' ' + commonStyles[`text--${borderColor}`] + ' ' + commonStyles.padded
12
12
  const showError = errorMessage.length > 0
13
13
  if (showError) className += ' ' + commonStyles['bordered--error-red']
14
14
  if (disabled) className += ' ' + commonStyles['apply-opacity-30']
15
+ const inputPlaceholder = placeholderApart ? '' : placeholder
16
+ const inputClassName = `${commonStyles.fullWidth} ${styles.input}`
15
17
 
16
18
  const cmp = (
17
19
  <div className={styles.container}>
18
20
  <div className={className}>
19
21
  {beforeIcon && <PlatformaticIcon iconName={beforeIcon.iconName} classes={styles.beforeInputIcon} size='small' data-testid='before-icon' color={beforeIcon.color} onClick={() => beforeIcon.onClick()} />}
20
- <input type='text' name={name} value={value} placeholder={placeholder} className={styles.fullWidth} onChange={onChange} disabled={disabled} />
22
+ <input type='text' name={name} value={value} className={inputClassName} onChange={onChange} disabled={disabled} placeholder={inputPlaceholder} />
23
+ {placeholderApart && <p className={styles.placeholderAPart}>{placeholder}</p>}
21
24
  {afterIcon && <PlatformaticIcon iconName={afterIcon.iconName} color={afterIcon.color} data-testid='after-icon' onClick={null} />}
22
25
  </div>
23
26
  {showError && <span className={commonStyles['error-message']}>{errorMessage}</span>}
@@ -43,7 +46,7 @@ Input.propTypes = {
43
46
  /**
44
47
  * color of border
45
48
  */
46
- borderColor: PropTypes.oneOf(['main-green', 'main-dark-blue']),
49
+ borderColor: PropTypes.oneOf([MAIN_GREEN, MAIN_DARK_BLUE]),
47
50
  /**
48
51
  * onChange
49
52
  */
@@ -71,20 +74,25 @@ Input.propTypes = {
71
74
  /**
72
75
  * addFocus
73
76
  */
74
- focused: PropTypes.bool
77
+ focused: PropTypes.bool,
78
+ /**
79
+ * placeholderApart
80
+ */
81
+ placeholderApart: PropTypes.bool
75
82
  }
76
83
 
77
84
  Input.defaultProps = {
78
85
  placeholder: '',
79
86
  value: '',
80
87
  name: '',
81
- borderColor: 'main-green',
88
+ borderColor: MAIN_GREEN,
82
89
  errorMessage: '',
83
90
  onChange: () => {},
84
91
  disabled: false,
85
92
  beforeIcon: null,
86
93
  afterIcon: null,
87
- focused: false
94
+ focused: false,
95
+ shadowPlaceholder: false
88
96
  }
89
97
 
90
98
  export default Input
@@ -2,13 +2,10 @@
2
2
  @apply flex flex-col w-full relative;
3
3
  }
4
4
  .inputContainer {
5
- @apply flex h-10 border border-solid box-border rounded-md;
6
- }
7
- .fullWidth {
8
- @apply w-full;
5
+ @apply flex h-10 border border-solid box-border rounded-md relative;
9
6
  }
10
7
  .input {
11
- @apply focus:outline-none focus-within:outline-none focus-visible:outline-none;
8
+ @apply z-10;
12
9
  }
13
10
  .beforeInputIcon {
14
11
  @apply ml-1 mr-3;
@@ -25,7 +22,9 @@
25
22
  .paddingFocused {
26
23
  @apply p-4;
27
24
  }
28
-
25
+ .placeholderAPart {
26
+ @apply absolute top-[50%] right-0 translate-y-[-50%] left-0 text-main-dark-blue text-opacity-20 ml-2 z-0;
27
+ }
29
28
  [type='text']:focus {
30
29
  outline: none;
31
30
  }
@@ -0,0 +1,134 @@
1
+ 'use strict'
2
+ import React, { useState, useEffect } from 'react'
3
+ import PropTypes from 'prop-types'
4
+ import inputStyles from './Input.module.css'
5
+ import styles from './InputWithSeparator.module.css'
6
+ import commonStyles from '../Common.module.css'
7
+ import PlatformaticIcon from '../PlatformaticIcon'
8
+ import { BACKGROUND_COLOR_OPAQUE, MAIN_DARK_BLUE, MAIN_GREEN, MEDIUM, TRANSPARENT } from '../constants'
9
+ import BorderedBox from '../BorderedBox'
10
+ import ButtonFullRounded from '../ButtonFullRounded'
11
+
12
+ function InputWithSeparator ({ placeholder, name, borderColor, errorMessage, onChange, disabled, afterIcon, value, separator }) {
13
+ const [chunks, setChunks] = useState([])
14
+ const [inputClassName, setInputClassName] = useState(`${styles.flexNone} ${styles.smallMargin} ${commonStyles.fullWidth}`)
15
+ const chunkClasses = `${styles.flexNone} ${styles.smallPadding} ${styles.smallMargin}`
16
+
17
+ let className = styles.inputContainer + ' ' + commonStyles[`bordered--${borderColor}`] + ' ' + commonStyles[`text--${borderColor}`] + ' ' + styles.smallPadding
18
+ const showError = errorMessage.length > 0
19
+ if (showError) className += ' ' + commonStyles['bordered--error-red']
20
+ if (disabled) className += ' ' + commonStyles['apply-opacity-30']
21
+
22
+ function handleRemove (chunk) {
23
+ const index = chunks.findIndex(c => c === chunk)
24
+ if (index > -1) {
25
+ chunks.splice(index, 1)
26
+ setChunks(chunks => [...chunks])
27
+ onChange({ value, chunks })
28
+ }
29
+ }
30
+
31
+ function handleChange (event) {
32
+ if (!showError && event.target.value.indexOf(separator) > -1) {
33
+ const elements = event.target.value.split(separator)
34
+ if (elements[0] !== '') {
35
+ const tmp = [elements[0]]
36
+ setChunks(prevChunks => [...prevChunks, ...tmp])
37
+ onChange({ value: elements[1], chunks })
38
+ return
39
+ }
40
+ }
41
+ onChange({ value: event.target.value, chunks })
42
+ }
43
+
44
+ useEffect(() => {
45
+ if (chunks.length > 0) {
46
+ setInputClassName(`${styles.flexNone} ${styles.smallMargin}`)
47
+ } else {
48
+ setInputClassName(`${styles.flexNone} ${styles.smallMargin} ${commonStyles.fullWidth}`)
49
+ }
50
+ }, [chunks.length])
51
+
52
+ function renderChunk (chunk, index) {
53
+ return (
54
+ <BorderedBox color={TRANSPARENT} backgroundColor={MAIN_DARK_BLUE} opaque={20} classes={chunkClasses} key={index}>
55
+ <div className={styles.chunkContent}>
56
+ <span className={styles.chunkText}>{chunk}</span>
57
+ <ButtonFullRounded
58
+ className=''
59
+ iconName='CircleCloseIcon'
60
+ iconSize={MEDIUM}
61
+ iconColor={MAIN_DARK_BLUE}
62
+ hoverEffect={BACKGROUND_COLOR_OPAQUE}
63
+ onClick={() => handleRemove(chunk)}
64
+ bordered={false}
65
+ alt='Close'
66
+ />
67
+ </div>
68
+ </BorderedBox>
69
+ )
70
+ }
71
+ return (
72
+ <div className={inputStyles.container}>
73
+ <div className={className}>
74
+ {chunks.map((value, index) => renderChunk(value, index))}
75
+ <input type='text' name={name} value={value} placeholder={placeholder} className={inputClassName} onChange={handleChange} disabled={disabled} />
76
+ </div>
77
+ {afterIcon && <div className={styles.iconContainer}><PlatformaticIcon iconName={afterIcon.iconName} color={afterIcon.color} data-testid='after-icon' onClick={afterIcon.handleClick} /></div>}
78
+ {showError && <span className={commonStyles['error-message']}>{errorMessage}</span>}
79
+ </div>
80
+ )
81
+ }
82
+
83
+ InputWithSeparator.propTypes = {
84
+ /**
85
+ * placeholder
86
+ */
87
+ placeholder: PropTypes.string,
88
+ /**
89
+ * name
90
+ */
91
+ name: PropTypes.string,
92
+ /**
93
+ * value
94
+ */
95
+ value: PropTypes.string,
96
+ /**
97
+ * separator
98
+ */
99
+ separator: PropTypes.string,
100
+ /**
101
+ * color of border
102
+ */
103
+ borderColor: PropTypes.oneOf([MAIN_GREEN, MAIN_DARK_BLUE]),
104
+ /**
105
+ * onChange
106
+ */
107
+ onChange: PropTypes.func,
108
+ /**
109
+ * Disabled
110
+ */
111
+ disabled: PropTypes.bool,
112
+ /**
113
+ * afterIcon: PlatformaticIcon props
114
+ */
115
+ afterIcon: PropTypes.shape({
116
+ iconName: PropTypes.string,
117
+ color: PropTypes.string,
118
+ handleClick: PropTypes.func
119
+ })
120
+ }
121
+
122
+ InputWithSeparator.defaultProps = {
123
+ placeholder: '',
124
+ value: '',
125
+ name: '',
126
+ borderColor: 'main-green',
127
+ errorMessage: '',
128
+ onChange: () => {},
129
+ disabled: false,
130
+ afterIcon: null,
131
+ separator: ''
132
+ }
133
+
134
+ export default InputWithSeparator
@@ -0,0 +1,24 @@
1
+ .chunkContent {
2
+ @apply flex gap-x-2 w-full items-center;
3
+ }
4
+ .chunkText {
5
+ @apply text-sm text-main-dark-blue;
6
+ }
7
+ .inputContainer {
8
+ @apply flex min-h-[46px] border border-solid box-border rounded-md items-center gap-[0.1rem] flex-wrap relative;
9
+ }
10
+ .smallPadding {
11
+ @apply p-1 !important
12
+ }
13
+ .flexNone {
14
+ @apply flex-none !important;
15
+ }
16
+ .noGrow {
17
+ @apply grow-0
18
+ }
19
+ .smallMargin {
20
+ @apply my-0;
21
+ }
22
+ .iconContainer {
23
+ @apply absolute top-[14px] right-[0.5rem]
24
+ }
@@ -1,8 +1,9 @@
1
- import Input from './Input'
2
1
  import Field from './Field'
2
+ import Input from './Input'
3
+ import InputWithSeparator from './InputWithSeparator'
3
4
  import Preview from './Preview'
4
5
  import ToggleSwitch from './ToggleSwitch'
5
6
 
6
7
  export default {
7
- Input, Field, Preview, ToggleSwitch
8
+ Field, Input, InputWithSeparator, Preview, ToggleSwitch
8
9
  }