intelicoreact 0.0.31 → 0.0.41

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 (37) hide show
  1. package/dist/Atomic/FormElements/Calendar/Calendar.js +134 -0
  2. package/dist/Atomic/FormElements/Calendar/Calendar.scss +543 -0
  3. package/dist/Atomic/FormElements/Calendar/Calendar.stories.js +75 -0
  4. package/dist/Atomic/FormElements/CheckboxInput/CheckboxInput.stories.js +1 -1
  5. package/dist/Atomic/FormElements/Input/Input.js +91 -99
  6. package/dist/Atomic/FormElements/Input/Input.scss +16 -5
  7. package/dist/Atomic/FormElements/Input/Input.stories.js +32 -25
  8. package/dist/Atomic/UI/Accordion/Accordion.stories.js +1 -1
  9. package/dist/Atomic/UI/AdvancedTag/AdvancedTags.stories.js +1 -1
  10. package/dist/Atomic/UI/Alert/Alert.stories.js +1 -1
  11. package/dist/Atomic/UI/Button/Button.js +1 -12
  12. package/dist/Atomic/UI/Button/Button.stories.js +5 -19
  13. package/dist/Atomic/UI/Hint/Hint.stories.js +1 -1
  14. package/dist/Atomic/UI/Price/Price.js +32 -0
  15. package/dist/Atomic/UI/Price/Price.stories.js +42 -0
  16. package/dist/Atomic/UI/Status/Status.stories.js +1 -1
  17. package/dist/Functions/useClickOutside.js +25 -0
  18. package/dist/scss/main.scss +2 -2
  19. package/package.json +7 -5
  20. package/src/Atomic/FormElements/Calendar/Calendar.js +106 -0
  21. package/src/Atomic/FormElements/Calendar/Calendar.scss +543 -0
  22. package/src/Atomic/FormElements/Calendar/Calendar.stories.js +38 -0
  23. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.stories.js +1 -1
  24. package/src/Atomic/FormElements/Input/Input.js +73 -72
  25. package/src/Atomic/FormElements/Input/Input.scss +16 -5
  26. package/src/Atomic/FormElements/Input/Input.stories.js +23 -27
  27. package/src/Atomic/UI/Accordion/Accordion.stories.js +1 -1
  28. package/src/Atomic/UI/AdvancedTag/AdvancedTags.stories.js +1 -1
  29. package/src/Atomic/UI/Alert/Alert.stories.js +1 -1
  30. package/src/Atomic/UI/Button/Button.js +1 -3
  31. package/src/Atomic/UI/Button/Button.stories.js +4 -19
  32. package/src/Atomic/UI/Hint/Hint.stories.js +1 -1
  33. package/src/Atomic/UI/Price/Price.js +19 -0
  34. package/src/Atomic/UI/Price/Price.stories.js +30 -0
  35. package/src/Atomic/UI/Status/Status.stories.js +1 -1
  36. package/src/Functions/useClickOutside.js +15 -0
  37. package/src/scss/main.scss +2 -2
@@ -1,110 +1,111 @@
1
1
  import React, { useState, useEffect, useRef } from 'react';
2
2
  import cn from 'classnames';
3
3
  import { Minus, Plus } from 'react-feather';
4
-
5
- import Label from '../Label/Label';
4
+ import InputMask from 'react-input-mask';
6
5
 
7
6
  import './Input.scss';
8
7
 
9
8
  const Input = ({
10
- error,
11
9
  onChange,
12
10
  disabled,
13
11
  withDelete,
14
12
  isNumeric,
15
- min,
13
+ numStep = 1,
14
+ min = 0,
16
15
  max,
17
- value = min,
16
+ value,
18
17
  placeholder,
19
- hint,
20
- label,
21
- hintSide,
22
18
  className,
23
- isLabelBold,
24
19
  type = 'text',
25
- onBlur = () => {},
26
- icon,
27
- isRequired,
28
- ...props
20
+ onBlur,
21
+ onFocus,
22
+ onKeyUp,
23
+ mask,
24
+ error
29
25
  }) => {
26
+ // STATES
30
27
  const [isFocused, setIsFocused] = useState(false);
31
- const [onInputHover, setOnInputHover] = useState(false);
32
28
  const [isEditing, setEditing] = useState(false);
33
29
  const inputRef = useRef(null);
34
-
35
- const changeHandler = inputValue => {
36
- if (isNumeric || (type === 'number' && inputValue !== '')) {
37
- const totalValue = Number(+inputValue);
38
- if (totalValue >= (min ?? -Infinity) && totalValue <= (max ?? Infinity)) onChange(totalValue);
39
- return;
40
- }
41
- onChange(inputValue);
42
- };
43
-
44
- const toggleEditing = () => {
45
- setEditing(!isEditing);
30
+ // HANDLES
31
+ const handle = {
32
+ change: event => {
33
+ let inputValue = event.target.value;
34
+ if (isNumeric || (type === 'number' && inputValue !== '')) {
35
+ inputValue = parseFloat(inputValue) || '';
36
+ if (min && +min > inputValue) {
37
+ inputValue = min;
38
+ } else if (max && +max < inputValue) inputValue = max;
39
+ }
40
+ onChange(inputValue.toString());
41
+ },
42
+ toggleEdit: () => {
43
+ setEditing(!isEditing);
44
+ onChange('');
45
+ },
46
+ focus: () => {
47
+ setIsFocused(true);
48
+ if (onFocus) onFocus();
49
+ },
50
+ blur: () => {
51
+ setIsFocused(false);
52
+ setEditing(false);
53
+ if (onBlur) onBlur();
54
+ },
55
+ keyUp: e => (onKeyUp ? onKeyUp(e.keyCode) : null)
46
56
  };
47
57
 
48
58
  useEffect(() => {
49
- if (isEditing) {
50
- inputRef.current.focus();
51
- }
59
+ if (isEditing) inputRef.current.focus();
52
60
  }, [isEditing, isFocused]);
53
61
 
54
- return (
55
- <div className={cn('input-classic', className)}>
56
- {label && <Label className="input-classic-label" isBold={isLabelBold} label={label} hint={hint} hintSide={hintSide} isRequired={isRequired} />}
62
+ const uniProps = {
63
+ className: `input-classic ${className}`,
64
+ placeholder,
65
+ value: value || '',
66
+ disabled,
67
+ onChange: handle.change,
68
+ onFocus: handle.focus,
69
+ onBlur: handle.blur,
70
+ onKeyUp: handle.keyUp,
71
+ min,
72
+ max
73
+ };
57
74
 
58
- <div
59
- onMouseEnter={() => setOnInputHover(true)}
60
- onMouseLeave={() => setOnInputHover(false)}
61
- className={cn(
62
- `input-classic__wrap`,
63
- { [`input-classic__wrap_focus`]: isFocused },
64
- { [`input-classic__wrap_error`]: error },
65
- { [`input-classic__wrap_disabled`]: disabled }
66
- )}
67
- >
68
- <input
69
- ref={inputRef}
70
- className="input-classic__input"
71
- type={isNumeric ? 'number' : type}
72
- onChange={e => changeHandler(e.target.value)}
73
- value={value || ''}
74
- disabled={disabled}
75
- onBlur={() => {
76
- setIsFocused(false);
77
- setEditing(false);
78
- onBlur();
79
- }}
80
- onFocus={() => setIsFocused(true)}
81
- placeholder={placeholder}
82
- {...props}
83
- />
75
+ function renderInput() {
76
+ if (mask) {
77
+ return <InputMask {...uniProps} ref={inputRef} mask={mask} />;
78
+ }
79
+
80
+ return (
81
+ <>
82
+ <input {...uniProps} ref={inputRef} type={isNumeric ? 'number' : type} />
84
83
  {isNumeric && (
85
84
  <div className="input-classic__nums">
86
- <button onClick={() => changeHandler(value - 1)} className={cn(`input-classic__num-btn`, { disabled: value === min })}>
85
+ <button onClick={() => handle.change(value - numStep)} className={cn(`input-classic__num-btn`, { disabled: value <= min })}>
87
86
  <Minus />
88
87
  </button>
89
- <button onClick={() => changeHandler(value + 1)} className={cn(`input-classic__num-btn`, { disabled: value === max })}>
88
+ <button onClick={() => handle.change(+value + +numStep)} className={cn(`input-classic__num-btn`, { disabled: value >= max })}>
90
89
  <Plus />
91
90
  </button>
92
91
  </div>
93
92
  )}
93
+ </>
94
+ );
95
+ }
94
96
 
95
- {withDelete && onInputHover && !isNumeric && (
96
- <button
97
- className={cn(`input-classic__close`, { hidden: !value })}
98
- onClick={() => {
99
- toggleEditing();
100
- onChange('');
101
- }}
102
- />
103
- )}
104
- {icon ?? null}
105
- </div>
97
+ return (
98
+ <div
99
+ className={cn(
100
+ `input-classic__wrap`,
101
+ { [`input-classic__wrap_focus`]: isFocused },
102
+ { [`input-classic__wrap_error`]: error },
103
+ { [`input-classic__wrap_disabled`]: disabled }
104
+ )}
105
+ >
106
+ {renderInput()}
106
107
 
107
- {error && <span className="input-classic__error">{error}</span>}
108
+ {withDelete && !isNumeric && <span className={cn(`input-classic__close`, { hidden: !value })} onClick={handle.toggleEdit} />}
108
109
  </div>
109
110
  );
110
111
  };
@@ -1,9 +1,12 @@
1
1
  .input-classic {
2
2
  position: relative;
3
3
  word-break: break-all;
4
-
5
- input::-webkit-outer-spin-button,
6
- input::-webkit-inner-spin-button {
4
+ border: none;
5
+ background: none;
6
+ padding: 0 10px;
7
+ width: 100%;
8
+ &::-webkit-outer-spin-button,
9
+ &::-webkit-inner-spin-button {
7
10
  -webkit-appearance: none;
8
11
  }
9
12
 
@@ -77,7 +80,8 @@
77
80
  background: none;
78
81
  cursor: pointer;
79
82
  margin-right: 4px;
80
-
83
+ visibility: hidden;
84
+ pointer-events: none;
81
85
  &:hover {
82
86
  opacity: 1;
83
87
  }
@@ -121,7 +125,9 @@
121
125
  background: none;
122
126
  font-size: 20px;
123
127
  user-select: none;
124
-
128
+ &.disabled {
129
+ opacity: 0.3;
130
+ }
125
131
  svg {
126
132
  margin-right: 0;
127
133
  }
@@ -131,3 +137,8 @@
131
137
  margin-bottom: 5px;
132
138
  }
133
139
  }
140
+
141
+ .input-classic__wrap:hover .input-classic__close {
142
+ visibility: visible;
143
+ pointer-events: all;
144
+ }
@@ -4,50 +4,47 @@ import Input from './Input';
4
4
  global.lng = 'en';
5
5
 
6
6
  export default {
7
- title: 'Input',
7
+ title: 'Form Elements/Input',
8
8
  component: Input,
9
9
  argTypes: {
10
- hintSide: {
11
- description: 'string: ["right", "bottom", "top", "left"]',
12
- control: {
13
- type: 'select',
14
- options: ['right', 'bottom', 'top', 'left']
15
- }
16
- },
17
- hint: {
18
- description: 'string'
19
- },
20
10
  disabled: {
21
- description: 'boolean'
11
+ description: 'boolean',
22
12
  },
23
13
  error: {
24
- description: 'text'
14
+ description: 'text - coloring input if is errored'
25
15
  },
26
16
  withDelete: {
27
- description: 'boolean'
17
+ description: 'boolean - add clear-cross by hover'
28
18
  },
29
19
  isNumeric: {
30
- description: 'boolean'
20
+ description: 'boolean - add plus/minus buttons, force input to numeric type'
21
+ },
22
+ numStep: {
23
+ description: 'number/text - plus/minus buttons factor (default: 1)'
31
24
  },
32
25
  min: {
33
- description: 'number'
26
+ description: 'number/text - minimal number for numeric input'
34
27
  },
35
28
  max: {
36
- description: 'number'
29
+ description: 'number/text - maximal number for numeric input'
37
30
  },
38
31
  placeholder: {
39
32
  description: 'text'
40
33
  },
41
- label: {
42
- description: 'text'
43
- },
44
34
  type: {
45
- description: 'string: any input type',
35
+
36
+ description: "'text', 'number', 'password', 'color', 'date', 'datetime-local', 'month', 'time', 'email', 'range'",
46
37
  control: {
47
38
  type: 'select',
48
- options: ['text', 'number']
39
+ options: ['text', 'number', 'password', 'color', 'date', 'datetime-local', 'month', 'time', 'email', 'range']
49
40
  }
50
- }
41
+ },
42
+ value: { description: '(* - required prop)' },
43
+ className: { description: 'string' },
44
+ mask: { description: 'string: force input to masked https://www.npmjs.com/package/react-input-mask' },
45
+ onBlur: { description: 'custom callback on blur' },
46
+ onFocus: { description: 'custom callback on focus' },
47
+ onKeyUp: { description: 'custom callback on keyup, returns event keyCode' }
51
48
  }
52
49
  };
53
50
 
@@ -64,10 +61,9 @@ InputTemplate.args = {
64
61
  error: '',
65
62
  withDelete: true,
66
63
  isNumeric: false,
64
+ numStep: 1,
67
65
  min: '0',
68
- max: 5,
66
+ max: '5',
69
67
  placeholder: 'Placeholder',
70
- label: 'label',
71
- hint: 'hint',
72
- hintSide: 'bottom'
68
+ mask: ''
73
69
  };
@@ -5,7 +5,7 @@ import Accordion from './Accordion';
5
5
  global.lng = 'en';
6
6
 
7
7
  export default {
8
- title: 'Accordion',
8
+ title: 'UI/Accordion',
9
9
  component: Accordion
10
10
  };
11
11
 
@@ -4,7 +4,7 @@ import AdvancedTags from './AdvancedTags';
4
4
  global.lng = 'en';
5
5
 
6
6
  export default {
7
- title: 'AdvancedTags',
7
+ title: 'UI/AdvancedTags',
8
8
  component: AdvancedTags
9
9
  };
10
10
 
@@ -4,7 +4,7 @@ import Alert from './Alert';
4
4
  global.lng = 'en';
5
5
 
6
6
  export default {
7
- title: 'Alert',
7
+ title: 'UI/Alert',
8
8
  component: Alert,
9
9
  argTypes: {
10
10
  variant: {
@@ -1,15 +1,13 @@
1
1
  import React from 'react';
2
2
  import cn from 'classnames';
3
- import * as Icons from 'react-feather';
4
3
 
5
4
  import './Button.scss';
6
5
 
7
6
  const Button = ({ label, variant = 'primary', onClick, disabled, icon, className, children, style }) => {
8
- const Icon = Icons[icon];
9
7
 
10
8
  return (
11
9
  <button style={style} className={cn(className, 'button', { [`button_${variant}`]: variant })} onClick={onClick} disabled={disabled}>
12
- {icon && <Icon className="button__icon" />}
10
+ {icon}
13
11
  {label && <div className="button__text">{label}</div>}
14
12
  {!label && children ? children : null}
15
13
  </button>
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
+ import {Check} from 'react-feather';
2
3
  import Button from './Button';
3
4
 
4
5
  global.lng = 'en';
5
6
 
6
7
  export default {
7
- title: 'Button',
8
+ title: 'UI/Button',
8
9
  component: Button,
9
10
  argTypes: {
10
11
  variant: {
@@ -30,22 +31,6 @@ export default {
30
31
  options: ['Check', 'Edit3', 'Plus', 'Tool', 'UploadCloud', 'X', 'ArrowLeft']
31
32
  }
32
33
  }
33
- },
34
- label: {
35
- description: 'string'
36
- },
37
- disabled: {
38
- description: 'boolean'
39
- },
40
- onClick: {
41
- description: 'function'
42
- },
43
- icon: {
44
- description: 'svg icon code',
45
- control: {
46
- type: 'select',
47
- options: ['Check', 'Edit3', 'Plus', 'Tool', 'UploadCloud', 'X']
48
- }
49
34
  }
50
35
  };
51
36
 
@@ -58,6 +43,6 @@ export const ButtonTemplate = Template.bind({});
58
43
  ButtonTemplate.args = {
59
44
  disabled: false,
60
45
  onClick: () => null,
61
- text: 'Button',
62
- icon: 'Check'
46
+ label: 'Button',
47
+ icon: <Check/>
63
48
  };
@@ -4,7 +4,7 @@ import Hint from './Hint';
4
4
  global.lng = 'en';
5
5
 
6
6
  export default {
7
- title: 'Hint',
7
+ title: 'UI/Hint',
8
8
  component: Hint,
9
9
  argTypes: {
10
10
  side: {
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ const Price = ({ value, unit = '$', unitAfter, className }) => {
3
+ let formatted;
4
+ if (value.length <= 3) {
5
+ formatted = parseFloat(value).toFixed(2);
6
+ } else {
7
+ formatted = Number(value.toString().replace(/[+*?$^(,)]/g, '')).toLocaleString('en-US');
8
+ }
9
+
10
+ return (
11
+ <div className={`price ${className}`}>
12
+ {!unitAfter && unit}
13
+ {formatted}
14
+ {unitAfter && unit}
15
+ </div>
16
+ );
17
+ };
18
+
19
+ export default Price;
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import Price from './Price';
3
+
4
+ global.lng = 'en';
5
+
6
+ export default {
7
+ title: 'UI/Price',
8
+ component: Price,
9
+ argTypes: {
10
+ value: {
11
+ description: 'string',
12
+ },
13
+ unit: {
14
+ description: 'string'
15
+ },
16
+ unitAfter: {
17
+ description: 'boolean'
18
+ }
19
+ }
20
+ };
21
+
22
+ const Template = args => <Price {...args} />;
23
+
24
+ export const PriceTemplate = Template.bind({});
25
+
26
+ PriceTemplate.args = {
27
+ value: '15000',
28
+ unit: '$',
29
+ unitAfter: false
30
+ };
@@ -4,7 +4,7 @@ import Status from './Status';
4
4
  global.lng = 'en';
5
5
 
6
6
  export default {
7
- title: 'Status',
7
+ title: 'UI/Status',
8
8
  component: Status,
9
9
  argTypes: {
10
10
  status: {
@@ -0,0 +1,15 @@
1
+ import { useEffect } from 'react';
2
+
3
+ export const useClickOutside = (ref, setOut, open) => {
4
+ function handleClickOutside(event) {
5
+ if (ref.current && !ref.current.contains(event.target)) {
6
+ setOut(open);
7
+ }
8
+ }
9
+ useEffect(() => {
10
+ document.addEventListener('mousedown', handleClickOutside);
11
+ return () => {
12
+ document.removeEventListener('mousedown', handleClickOutside);
13
+ };
14
+ }, [ref]);
15
+ };
@@ -35,6 +35,6 @@ button {
35
35
 
36
36
  .main {
37
37
  &__wrap {
38
- display: flex;
38
+ display: flex;
39
39
  }
40
- }
40
+ }