@livechat/design-system-react-components 1.0.0-alpha.4 → 1.0.0-alpha.5

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 (233) hide show
  1. package/dist/dsrc.cjs.js +1 -0
  2. package/dist/dsrc.es.js +2213 -0
  3. package/dist/dsrc.umd.js +1 -0
  4. package/dist/src/components/Alert/Alert.d.ts +19 -0
  5. package/{src/components/Alert/index.ts → dist/src/components/Alert/index.d.ts} +0 -0
  6. package/dist/src/components/Badge/Badge.d.ts +5 -0
  7. package/{src/components/Badge/index.ts → dist/src/components/Badge/index.d.ts} +0 -0
  8. package/dist/src/components/Button/Button.d.ts +13 -0
  9. package/{src/components/Button/index.ts → dist/src/components/Button/index.d.ts} +0 -0
  10. package/dist/src/components/ButtonGroup/ButtonGroup.d.ts +11 -0
  11. package/{src/components/ButtonGroup/index.ts → dist/src/components/ButtonGroup/index.d.ts} +0 -0
  12. package/dist/src/components/Card/Card.d.ts +6 -0
  13. package/{src/components/Card/index.ts → dist/src/components/Card/index.d.ts} +0 -0
  14. package/dist/src/components/Checkbox/Checkbox.d.ts +7 -0
  15. package/dist/src/components/Checkbox/CheckboxField.d.ts +7 -0
  16. package/{src/components/Checkbox/index.ts → dist/src/components/Checkbox/index.d.ts} +0 -0
  17. package/dist/src/components/FieldDescription/FieldDescription.d.ts +3 -0
  18. package/{src/components/FieldDescription/index.ts → dist/src/components/FieldDescription/index.d.ts} +0 -0
  19. package/dist/src/components/FieldError/FieldError.d.ts +3 -0
  20. package/{src/components/FieldError/index.ts → dist/src/components/FieldError/index.d.ts} +0 -0
  21. package/dist/src/components/FieldGroup/FieldGroup.d.ts +8 -0
  22. package/{src/components/FieldGroup/index.ts → dist/src/components/FieldGroup/index.d.ts} +0 -0
  23. package/dist/src/components/Form/Form.d.ts +7 -0
  24. package/{src/components/Form/index.ts → dist/src/components/Form/index.d.ts} +0 -0
  25. package/dist/src/components/FormGroup/FormGroup.d.ts +7 -0
  26. package/{src/components/FormGroup/index.ts → dist/src/components/FormGroup/index.d.ts} +0 -0
  27. package/dist/src/components/Icon/Icon.d.ts +70 -0
  28. package/{src/components/Icon/index.ts → dist/src/components/Icon/index.d.ts} +0 -0
  29. package/dist/src/components/InputField/InputField.d.ts +15 -0
  30. package/{src/components/InputField/index.ts → dist/src/components/InputField/index.d.ts} +0 -0
  31. package/{src/components/Link/Link.tsx → dist/src/components/Link/Link.d.ts} +3 -26
  32. package/{src/components/Link/index.ts → dist/src/components/Link/index.d.ts} +0 -0
  33. package/dist/src/components/Loader/Loader.d.ts +10 -0
  34. package/{src/components/Loader/index.ts → dist/src/components/Loader/index.d.ts} +0 -0
  35. package/dist/src/components/Modal/ActionModal.d.ts +8 -0
  36. package/dist/src/components/Modal/Modal.d.ts +7 -0
  37. package/dist/src/components/Modal/ModalBase.d.ts +6 -0
  38. package/dist/src/components/Modal/ModalCloseButton.d.ts +3 -0
  39. package/dist/src/components/Modal/ModalPortal.d.ts +7 -0
  40. package/{src/components/Modal/index.ts → dist/src/components/Modal/index.d.ts} +0 -1
  41. package/dist/src/components/NumericInput/NumericInput.d.ts +14 -0
  42. package/dist/src/components/NumericInput/NumericInputField.d.ts +19 -0
  43. package/{src/components/NumericInput/index.ts → dist/src/components/NumericInput/index.d.ts} +0 -0
  44. package/dist/src/components/Popover/Popover.d.ts +15 -0
  45. package/{src/components/Popover/index.ts → dist/src/components/Popover/index.d.ts} +0 -0
  46. package/dist/src/components/Progress/ProgressCircle.d.ts +9 -0
  47. package/dist/src/components/Progress/constants.d.ts +12 -0
  48. package/dist/src/components/Progress/helpers.d.ts +3 -0
  49. package/{src/components/Progress/index.ts → dist/src/components/Progress/index.d.ts} +0 -0
  50. package/dist/src/components/PromoBanner/PromoBanner.d.ts +19 -0
  51. package/{src/components/PromoBanner/index.ts → dist/src/components/PromoBanner/index.d.ts} +0 -0
  52. package/dist/src/components/RadioButton/RadioButton.d.ts +7 -0
  53. package/{src/components/RadioButton/index.ts → dist/src/components/RadioButton/index.d.ts} +0 -0
  54. package/dist/src/components/Switch/Switch.d.ts +20 -0
  55. package/{src/components/Switch/index.ts → dist/src/components/Switch/index.d.ts} +0 -0
  56. package/dist/src/components/Tab/Tab.d.ts +12 -0
  57. package/dist/src/components/Tab/TabsWrapper.d.ts +3 -0
  58. package/{src/components/Tab/index.ts → dist/src/components/Tab/index.d.ts} +0 -0
  59. package/dist/src/components/Tag/Tag.d.ts +12 -0
  60. package/{src/components/Tag/index.ts → dist/src/components/Tag/index.d.ts} +0 -0
  61. package/dist/src/components/TagInput/EditableTag.d.ts +11 -0
  62. package/dist/src/components/TagInput/EditableTagContent.d.ts +11 -0
  63. package/dist/src/components/TagInput/EmailTagInput.d.ts +5 -0
  64. package/dist/src/components/TagInput/TagInput.d.ts +12 -0
  65. package/{src/components/TagInput/index.ts → dist/src/components/TagInput/index.d.ts} +0 -0
  66. package/dist/src/components/TextField/TextField.d.ts +13 -0
  67. package/{src/components/TextField/index.ts → dist/src/components/TextField/index.d.ts} +0 -0
  68. package/dist/src/components/Toast/Toast.d.ts +22 -0
  69. package/dist/src/components/Toast/ToastWrapper.d.ts +27 -0
  70. package/{src/components/Toast/index.ts → dist/src/components/Toast/index.d.ts} +0 -0
  71. package/dist/src/components/Typography/Heading.d.ts +11 -0
  72. package/dist/src/components/Typography/Text.d.ts +15 -0
  73. package/{src/components/Typography/index.ts → dist/src/components/Typography/index.d.ts} +0 -0
  74. package/{src/index.ts → dist/src/index.d.ts} +0 -3
  75. package/dist/src/themes/designTokens.d.ts +126 -0
  76. package/dist/src/utils/keyCodes.d.ts +12 -0
  77. package/dist/src/utils/noop.d.ts +1 -0
  78. package/{src → dist/src}/vite-env.d.ts +0 -0
  79. package/dist/style.css +1 -0
  80. package/{src/themes/dark.scss → dist/themes/dark.css} +2 -0
  81. package/dist/themes/dark.css.map +1 -0
  82. package/{src/themes/legacy.scss → dist/themes/legacy.css} +2 -0
  83. package/dist/themes/legacy.css.map +1 -0
  84. package/{src/themes/light.scss → dist/themes/light.css} +2 -0
  85. package/dist/themes/light.css.map +1 -0
  86. package/package.json +5 -2
  87. package/.eslintrc +0 -9
  88. package/.storybook/main.js +0 -20
  89. package/.storybook/preview-head.html +0 -31
  90. package/.storybook/preview.js +0 -21
  91. package/src/components/Alert/Alert.module.scss +0 -88
  92. package/src/components/Alert/Alert.spec.tsx +0 -78
  93. package/src/components/Alert/Alert.stories.tsx +0 -73
  94. package/src/components/Alert/Alert.tsx +0 -94
  95. package/src/components/Badge/Badge.module.scss +0 -23
  96. package/src/components/Badge/Badge.spec.tsx +0 -12
  97. package/src/components/Badge/Badge.stories.tsx +0 -24
  98. package/src/components/Badge/Badge.tsx +0 -24
  99. package/src/components/Button/Button.module.scss +0 -257
  100. package/src/components/Button/Button.spec.tsx +0 -110
  101. package/src/components/Button/Button.stories.tsx +0 -152
  102. package/src/components/Button/Button.tsx +0 -88
  103. package/src/components/ButtonGroup/ButtonGroup.module.scss +0 -31
  104. package/src/components/ButtonGroup/ButtonGroup.spec.tsx +0 -61
  105. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -53
  106. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -75
  107. package/src/components/Card/Card.module.scss +0 -31
  108. package/src/components/Card/Card.spec.tsx +0 -38
  109. package/src/components/Card/Card.stories.tsx +0 -30
  110. package/src/components/Card/Card.tsx +0 -34
  111. package/src/components/Checkbox/Checkbox.module.scss +0 -99
  112. package/src/components/Checkbox/Checkbox.tsx +0 -39
  113. package/src/components/Checkbox/CheckboxField.spec.tsx +0 -58
  114. package/src/components/Checkbox/CheckboxField.stories.tsx +0 -30
  115. package/src/components/Checkbox/CheckboxField.tsx +0 -46
  116. package/src/components/FieldDescription/FieldDescription.module.scss +0 -5
  117. package/src/components/FieldDescription/FieldDescription.tsx +0 -23
  118. package/src/components/FieldError/FieldError.module.scss +0 -5
  119. package/src/components/FieldError/FieldError.tsx +0 -23
  120. package/src/components/FieldGroup/FieldGroup.module.scss +0 -25
  121. package/src/components/FieldGroup/FieldGroup.spec.tsx +0 -42
  122. package/src/components/FieldGroup/FieldGroup.stories.tsx +0 -34
  123. package/src/components/FieldGroup/FieldGroup.tsx +0 -38
  124. package/src/components/Form/Form.module.scss +0 -22
  125. package/src/components/Form/Form.spec.tsx +0 -38
  126. package/src/components/Form/Form.stories.tsx +0 -42
  127. package/src/components/Form/Form.tsx +0 -46
  128. package/src/components/FormGroup/FormGroup.module.scss +0 -20
  129. package/src/components/FormGroup/FormGroup.spec.tsx +0 -34
  130. package/src/components/FormGroup/FormGroup.stories.tsx +0 -30
  131. package/src/components/FormGroup/FormGroup.tsx +0 -44
  132. package/src/components/Icon/Icon.module.scss +0 -70
  133. package/src/components/Icon/Icon.stories.tsx +0 -53
  134. package/src/components/Icon/Icon.tsx +0 -118
  135. package/src/components/InputField/InputField.module.scss +0 -37
  136. package/src/components/InputField/InputField.spec.tsx +0 -53
  137. package/src/components/InputField/InputField.stories.tsx +0 -73
  138. package/src/components/InputField/InputField.tsx +0 -72
  139. package/src/components/Link/Link.module.scss +0 -18
  140. package/src/components/Link/Link.stories.tsx +0 -17
  141. package/src/components/Loader/Loader.module.scss +0 -66
  142. package/src/components/Loader/Loader.spec.tsx +0 -64
  143. package/src/components/Loader/Loader.stories.tsx +0 -25
  144. package/src/components/Loader/Loader.tsx +0 -48
  145. package/src/components/Modal/ActionModal.tsx +0 -37
  146. package/src/components/Modal/Modal.module.scss +0 -131
  147. package/src/components/Modal/Modal.stories.tsx +0 -85
  148. package/src/components/Modal/Modal.tsx +0 -41
  149. package/src/components/Modal/ModalBase.spec.tsx +0 -58
  150. package/src/components/Modal/ModalBase.tsx +0 -66
  151. package/src/components/Modal/ModalCloseButton.tsx +0 -20
  152. package/src/components/Modal/ModalPortal.tsx +0 -35
  153. package/src/components/NumericInput/NumericInput.module.scss +0 -110
  154. package/src/components/NumericInput/NumericInput.spec.tsx +0 -129
  155. package/src/components/NumericInput/NumericInput.stories.tsx +0 -56
  156. package/src/components/NumericInput/NumericInput.tsx +0 -161
  157. package/src/components/NumericInput/NumericInputField.stories.tsx +0 -58
  158. package/src/components/NumericInput/NumericInputField.tsx +0 -57
  159. package/src/components/Popover/Popover.module.scss +0 -16
  160. package/src/components/Popover/Popover.spec.tsx +0 -39
  161. package/src/components/Popover/Popover.stories.css +0 -23
  162. package/src/components/Popover/Popover.stories.tsx +0 -164
  163. package/src/components/Popover/Popover.tsx +0 -124
  164. package/src/components/Progress/ProgressBar.module.scss +0 -48
  165. package/src/components/Progress/ProgressBar.spec.tsx +0 -33
  166. package/src/components/Progress/ProgressBar.stories.tsx +0 -23
  167. package/src/components/Progress/ProgressBar.tsx +0 -62
  168. package/src/components/Progress/ProgressCircle.module.scss +0 -64
  169. package/src/components/Progress/ProgressCircle.spec.tsx +0 -34
  170. package/src/components/Progress/ProgressCircle.stories.tsx +0 -28
  171. package/src/components/Progress/ProgressCircle.tsx +0 -104
  172. package/src/components/Progress/constants.ts +0 -23
  173. package/src/components/Progress/helpers.ts +0 -23
  174. package/src/components/PromoBanner/PromoBanner.module.scss +0 -121
  175. package/src/components/PromoBanner/PromoBanner.spec.tsx +0 -119
  176. package/src/components/PromoBanner/PromoBanner.stories.tsx +0 -125
  177. package/src/components/PromoBanner/PromoBanner.tsx +0 -99
  178. package/src/components/RadioButton/RadioButton.module.scss +0 -100
  179. package/src/components/RadioButton/RadioButton.spec.tsx +0 -70
  180. package/src/components/RadioButton/RadioButton.stories.tsx +0 -34
  181. package/src/components/RadioButton/RadioButton.tsx +0 -54
  182. package/src/components/Switch/Switch.module.scss +0 -126
  183. package/src/components/Switch/Switch.spec.tsx +0 -40
  184. package/src/components/Switch/Switch.stories.tsx +0 -23
  185. package/src/components/Switch/Switch.tsx +0 -100
  186. package/src/components/Tab/Tab.module.scss +0 -56
  187. package/src/components/Tab/Tab.spec.tsx +0 -34
  188. package/src/components/Tab/Tab.stories.tsx +0 -20
  189. package/src/components/Tab/Tab.tsx +0 -49
  190. package/src/components/Tab/TabsWrapper.module.scss +0 -11
  191. package/src/components/Tab/TabsWrapper.spec.tsx +0 -19
  192. package/src/components/Tab/TabsWrapper.stories.tsx +0 -46
  193. package/src/components/Tab/TabsWrapper.tsx +0 -24
  194. package/src/components/Tag/Tag.module.scss +0 -131
  195. package/src/components/Tag/Tag.spec.tsx +0 -93
  196. package/src/components/Tag/Tag.stories.tsx +0 -151
  197. package/src/components/Tag/Tag.tsx +0 -129
  198. package/src/components/TagInput/EditableTag.tsx +0 -54
  199. package/src/components/TagInput/EditableTagContent.tsx +0 -81
  200. package/src/components/TagInput/EmailTagInput.tsx +0 -31
  201. package/src/components/TagInput/TagInput.module.scss +0 -81
  202. package/src/components/TagInput/TagInput.spec.tsx +0 -58
  203. package/src/components/TagInput/TagInput.stories.tsx +0 -49
  204. package/src/components/TagInput/TagInput.tsx +0 -133
  205. package/src/components/TextField/TextField.module.scss +0 -90
  206. package/src/components/TextField/TextField.spec.tsx +0 -40
  207. package/src/components/TextField/TextField.stories.tsx +0 -60
  208. package/src/components/TextField/TextField.tsx +0 -100
  209. package/src/components/Toast/Toast.module.scss +0 -218
  210. package/src/components/Toast/Toast.spec.tsx +0 -96
  211. package/src/components/Toast/Toast.stories.tsx +0 -64
  212. package/src/components/Toast/Toast.tsx +0 -121
  213. package/src/components/Toast/ToastWrapper.spec.tsx +0 -13
  214. package/src/components/Toast/ToastWrapper.stories.tsx +0 -55
  215. package/src/components/Toast/ToastWrapper.tsx +0 -87
  216. package/src/components/Typography/Heading.tsx +0 -36
  217. package/src/components/Typography/Text.tsx +0 -49
  218. package/src/components/Typography/Typography.module.scss +0 -132
  219. package/src/index.scss +0 -9
  220. package/src/stories/ColorTokens.stories.mdx +0 -10
  221. package/src/stories/Icons.stories.mdx +0 -12
  222. package/src/stories/Typography.stories.mdx +0 -65
  223. package/src/stories/components/ColorTokens.tsx +0 -99
  224. package/src/stories/components/IconsShowcase.tsx +0 -25
  225. package/src/stories/components/iconsShowcase.css +0 -13
  226. package/src/test/setup.ts +0 -1
  227. package/src/test/utils.ts +0 -3
  228. package/src/themes/designTokens.ts +0 -126
  229. package/src/utils/keyCodes.ts +0 -12
  230. package/src/utils/noop.ts +0 -2
  231. package/tsconfig.json +0 -25
  232. package/tsconfig.node.json +0 -8
  233. package/vite.config.ts +0 -44
@@ -1,81 +0,0 @@
1
- .tag-input {
2
- align-items: center;
3
- background-clip: padding-box;
4
- border: 1px solid var(--border-default);
5
- border-radius: 4px;
6
- box-sizing: border-box;
7
- color: var(--content-default);
8
- display: flex;
9
- flex-wrap: wrap;
10
- font-size: 15px;
11
- overflow-y: auto;
12
- padding: 4px;
13
- transition: border 0.25s ease-in-out;
14
- width: 100%;
15
- will-change: border-color;
16
-
17
- &::placeholder {
18
- color: var(--content-disabled);
19
- }
20
-
21
- &:hover {
22
- border-color: var(--border-hover);
23
- outline: 0;
24
- }
25
-
26
- &:focus-within {
27
- border-color: var(--color-action-default);
28
- outline: 0;
29
- }
30
-
31
- &--error,
32
- &--error:focus-within {
33
- border-color: var(--color-negative-default);
34
- }
35
-
36
- &:disabled {
37
- color: var(--content-disabled);
38
- cursor: not-allowed;
39
- }
40
-
41
- * {
42
- box-sizing: border-box;
43
- }
44
-
45
- > * {
46
- margin: 2px;
47
- }
48
-
49
- @at-root #{&}__input {
50
- appearance: none;
51
- background: transparent;
52
- border-style: none;
53
- box-shadow: none;
54
- color: var(--content-default);
55
- flex-grow: 1;
56
- font-size: 15px;
57
- margin: 0 4px;
58
- outline: 0;
59
- padding: 0 0 0 4px;
60
- width: auto;
61
-
62
- &--medium {
63
- line-height: 28px;
64
- }
65
-
66
- &--large {
67
- line-height: 36px;
68
- }
69
-
70
- &:focus {
71
- border-style: none;
72
- }
73
- }
74
-
75
- @at-root #{&}__tag__content {
76
- border-style: none;
77
- outline: 0;
78
- padding: 0;
79
- white-space: nowrap;
80
- }
81
- }
@@ -1,58 +0,0 @@
1
- import * as React from 'react';
2
- import { render, fireEvent, userEvent, vi } from 'test-utils';
3
- import noop from '../../utils/noop';
4
-
5
- import { TagInput } from './TagInput';
6
- import styles from './TagInput.module.scss';
7
-
8
- const baseClass = 'tag-input';
9
-
10
- describe('<TagInput> component', () => {
11
- it('should have error class when error occurs', () => {
12
- const { container } = render(
13
- <TagInput onChange={noop} error={'test error'} />
14
- );
15
- expect(container.firstChild).toHaveClass(styles[`${baseClass}--error`]);
16
- });
17
-
18
- it('should call onChange method on enter press', () => {
19
- const onChange = vi.fn();
20
- const { getByRole } = render(<TagInput onChange={onChange} />);
21
- const tagText = 'tagText';
22
- const input = getByRole('textbox');
23
- userEvent.type(input, `${tagText}{enter}`);
24
- expect(onChange).toBeCalledWith([tagText]);
25
- });
26
-
27
- it('should call onChange method on separator provided', () => {
28
- const onChange = vi.fn();
29
- const { getByRole } = render(<TagInput onChange={onChange} />);
30
- const tagText = 'tagText';
31
- const tagSeparator = ';';
32
- const input = getByRole('textbox');
33
- userEvent.type(input, `${tagText}${tagSeparator}`);
34
- expect(onChange).toBeCalledWith([tagText]);
35
- });
36
-
37
- it('should not call onChange method on enter press when tag separator is not provided', () => {
38
- const onChange = vi.fn();
39
- const { getByRole } = render(<TagInput onChange={onChange} />);
40
- const tagText = 'tagText';
41
- const input = getByRole('textbox');
42
- userEvent.type(input, tagText);
43
- expect(onChange).not.toBeCalled();
44
- });
45
-
46
- it('should call onChange method on text paste', () => {
47
- const onChange = vi.fn();
48
- const { getByRole } = render(<TagInput onChange={onChange} />);
49
- const pastedText = 'tag1;tag2,tag3 tag4';
50
- const input = getByRole('textbox');
51
- fireEvent.paste(input, {
52
- clipboardData: {
53
- getData: () => pastedText,
54
- },
55
- });
56
- expect(onChange).toBeCalledWith(['tag1', 'tag2', 'tag3', 'tag4']);
57
- });
58
- });
@@ -1,49 +0,0 @@
1
- import * as React from 'react';
2
- import { ComponentMeta } from '@storybook/react';
3
-
4
- import {
5
- TagInput as TagInputComponent,
6
- TagInputProps,
7
- EmailTagInput as EmailTagInputComponent,
8
- EmailTagInputProps,
9
- } from './index';
10
-
11
- export default {
12
- title: 'Forms (WIP)/Tag Input',
13
- component: TagInputComponent,
14
- argTypes: {
15
- tags: {
16
- control: {
17
- disable: true,
18
- },
19
- },
20
- },
21
- } as ComponentMeta<typeof TagInputComponent>;
22
-
23
- export const TagInput = ({ ...args }: TagInputProps): React.ReactElement => {
24
- const [tags, setTags] = React.useState(['tag1', 'tag2']);
25
- return (
26
- <div>
27
- <TagInputComponent {...args} tags={tags} onChange={setTags} />
28
- </div>
29
- );
30
- };
31
-
32
- TagInput.args = {
33
- placeholder: 'Tag input placeholder',
34
- } as TagInputProps;
35
-
36
- export const EmailTagInput = ({
37
- ...args
38
- }: EmailTagInputProps): React.ReactElement => {
39
- const [tags, setTags] = React.useState(['one@test.com', 'two@test.com']);
40
- return (
41
- <div>
42
- <EmailTagInputComponent {...args} tags={tags} onChange={setTags} />
43
- </div>
44
- );
45
- };
46
-
47
- EmailTagInput.args = {
48
- placeholder: 'name@company.com',
49
- } as TagInputProps;
@@ -1,133 +0,0 @@
1
- import * as React from 'react';
2
- import cx from 'clsx';
3
- import { EditableTag } from './EditableTag';
4
- import { KeyCodes } from '../../utils/keyCodes';
5
- import { FieldError } from '../FieldError';
6
-
7
- import styles from './TagInput.module.scss';
8
-
9
- const baseClass = 'tag-input';
10
-
11
- const tagSeparatorKeys = [
12
- KeyCodes.enter,
13
- KeyCodes.spacebar,
14
- KeyCodes.tab,
15
- KeyCodes.semicolon,
16
- KeyCodes.comma,
17
- ];
18
- const tagRemoveKeys = [KeyCodes.backspace, KeyCodes.delete];
19
-
20
- type Tags = string[];
21
-
22
- export interface TagInputProps {
23
- error?: string;
24
- tags?: Tags;
25
- onChange: (tags: Tags) => void;
26
- placeholder?: string;
27
- validator?: (val: string) => boolean;
28
- size?: 'medium' | 'large';
29
- }
30
-
31
- export const TagInput: React.FC<TagInputProps> = ({
32
- tags,
33
- onChange,
34
- validator,
35
- error,
36
- placeholder,
37
- size = 'medium',
38
- }) => {
39
- const mergedClassNames = cx(styles[baseClass], {
40
- [styles[`${baseClass}--error`]]: error,
41
- });
42
- const inputClassNames = cx(
43
- styles[`${baseClass}__input`],
44
- styles[`${baseClass}__input--${size}`]
45
- );
46
-
47
- const [inputValue, setInputValue] = React.useState('');
48
- const inputRef = React.useRef<HTMLInputElement>(null);
49
-
50
- const addTag = (value: string) => {
51
- onChange([...(tags || []), value]);
52
- setInputValue('');
53
- };
54
-
55
- const removeTag = (idx: number) => {
56
- const newTags = [...(tags || [])];
57
- newTags.splice(idx, 1);
58
- onChange(newTags);
59
- };
60
-
61
- const onInputChange = (e: React.ChangeEvent<HTMLInputElement>) =>
62
- setInputValue(e.target.value);
63
-
64
- const onInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
65
- if (tagSeparatorKeys.includes(e.key)) {
66
- e.preventDefault();
67
-
68
- if (inputValue === '') {
69
- return;
70
- }
71
-
72
- addTag(inputValue);
73
- } else if (tagRemoveKeys.includes(e.key)) {
74
- if (inputValue !== '' || !tags?.length) {
75
- return;
76
- }
77
-
78
- removeTag(tags.length - 1);
79
- }
80
- };
81
-
82
- const updateTag = (i: number, value: string) => {
83
- const newTags = [...(tags || [])];
84
- const numOccurrencesOfValue = newTags.reduce(
85
- (prev, currentValue, index) =>
86
- prev + (currentValue === value && index !== i ? 1 : 0),
87
- 0
88
- );
89
- if (numOccurrencesOfValue > 0) {
90
- newTags.splice(i, 1);
91
- } else {
92
- newTags[i] = value;
93
- }
94
- onChange(newTags);
95
- };
96
-
97
- const onPaste = (e: React.ClipboardEvent<HTMLInputElement>) => {
98
- e.preventDefault();
99
- const text = e.clipboardData.getData('text/plain');
100
- const newTags = text.split(/[\s,;\n]+/);
101
- onChange([...(tags || []), ...newTags]);
102
- };
103
-
104
- return (
105
- <>
106
- <div className={mergedClassNames}>
107
- {tags?.map((tag, index) => (
108
- <EditableTag
109
- index={index}
110
- key={`${index}${tag}`}
111
- update={updateTag}
112
- remove={removeTag}
113
- inputRef={inputRef}
114
- validator={validator}
115
- size={size}
116
- >
117
- {tag}
118
- </EditableTag>
119
- ))}
120
- <input
121
- ref={inputRef}
122
- className={inputClassNames}
123
- placeholder={placeholder}
124
- value={inputValue}
125
- onChange={onInputChange}
126
- onKeyDown={onInputKeyDown}
127
- onPaste={onPaste}
128
- />
129
- </div>
130
- {error && <FieldError>{error}</FieldError>}
131
- </>
132
- );
133
- };
@@ -1,90 +0,0 @@
1
- .text-field {
2
- margin-bottom: 20px;
3
-
4
- &--inline {
5
- display: flex;
6
- flex-direction: column;
7
- }
8
-
9
- &__wrapper--inline {
10
- display: flex;
11
- flex-direction: row;
12
- flex-wrap: nowrap;
13
- }
14
-
15
- &__label {
16
- align-items: center;
17
- display: flex;
18
- flex-direction: row;
19
- justify-content: flex-start;
20
- margin-bottom: 4px;
21
-
22
- label {
23
- margin-bottom: 0;
24
- }
25
-
26
- &--inline {
27
- align-items: center;
28
- height: 32px;
29
- justify-content: center;
30
- margin-bottom: 0;
31
- margin-right: 10px;
32
- }
33
-
34
- &--no-text {
35
- justify-content: flex-end;
36
- margin-right: 0;
37
- }
38
- }
39
-
40
- &__label-wrapper {
41
- display: flex;
42
- flex-grow: 1;
43
- }
44
-
45
- &__label-adornment {
46
- align-items: center;
47
- align-self: flex-end;
48
- display: flex;
49
- flex-shrink: 0;
50
- height: 20px;
51
- justify-content: flex-end;
52
- line-height: 20px;
53
- margin-left: 4px;
54
- overflow: hidden;
55
- width: 20px;
56
- }
57
-
58
- &__label-right-node {
59
- align-self: flex-end;
60
- color: var(--content-default);
61
- display: flex;
62
- flex-shrink: 0;
63
- font-size: 14px;
64
- justify-content: flex-end;
65
- line-height: 20px;
66
- margin-left: 5px;
67
-
68
- &--inline {
69
- flex-grow: 1;
70
- margin-bottom: 4px;
71
- }
72
- }
73
-
74
- &__row-break {
75
- flex-basis: 100%;
76
- height: 0;
77
- }
78
-
79
- &__content {
80
- flex-grow: 1;
81
- }
82
- }
83
-
84
- .field-label {
85
- color: var(--content-default);
86
- display: block;
87
- font-size: 14px;
88
- line-height: 20px;
89
- margin-bottom: 4px;
90
- }
@@ -1,40 +0,0 @@
1
- import * as React from 'react';
2
- import { render } from 'test-utils';
3
- import { TextFieldProps, TextField } from './TextField';
4
-
5
- const renderComponent = (props: TextFieldProps) => {
6
- return render(
7
- <TextField {...props} className="my-css-class">
8
- <input id="input-field-example" />
9
- </TextField>
10
- );
11
- };
12
-
13
- describe('<TextField> component', () => {
14
- it('should allow for custom class', () => {
15
- const { container } = renderComponent({});
16
-
17
- expect(container.firstChild).toHaveClass('my-css-class');
18
- });
19
-
20
- it('should render field elements', () => {
21
- const label = 'Example label text';
22
- const error = 'Error text';
23
- const description = <div>Description text</div>;
24
- const adornment = <div>Decoration element</div>;
25
- const labelRight = <div>Label right</div>;
26
- const { getByText } = renderComponent({
27
- labelText: label,
28
- error: error,
29
- description: description,
30
- labelAdornment: adornment,
31
- labelRightNode: labelRight,
32
- });
33
-
34
- expect(getByText(label)).toBeVisible();
35
- expect(getByText(error)).toBeVisible();
36
- expect(getByText('Description text')).toBeVisible();
37
- expect(getByText('Decoration element')).toBeVisible();
38
- expect(getByText('Label right')).toBeVisible();
39
- });
40
- });
@@ -1,60 +0,0 @@
1
- import * as React from 'react';
2
- import { ComponentMeta, Story } from '@storybook/react';
3
-
4
- import { TextFieldProps, TextField as TextFieldComponent } from './TextField';
5
-
6
- export default {
7
- title: 'Forms (WIP)/TextField',
8
- component: TextFieldComponent,
9
- parameters: {
10
- componentSubtitle: `
11
- TextField is useful if you need to develop custom input field,
12
- but want to reuse the logic behind labels, descriptions and errors
13
- present in other form components like InputField, TextAreaField etc.
14
- `,
15
- },
16
- } as ComponentMeta<typeof TextFieldComponent>;
17
-
18
- const StoryTemplate: Story<TextFieldProps> = (args: TextFieldProps) => (
19
- <div>
20
- <TextFieldComponent {...args}>
21
- <input style={{ height: 26 }} id="text-field-example" />
22
- </TextFieldComponent>
23
- </div>
24
- );
25
-
26
- export const TextField = StoryTemplate.bind({});
27
- TextField.args = {};
28
-
29
- export const TextFieldWithLabel = StoryTemplate.bind({});
30
- TextFieldWithLabel.args = {
31
- labelText: 'Example label text',
32
- };
33
-
34
- export const TextFieldWithLabelInline = StoryTemplate.bind({});
35
- TextFieldWithLabelInline.args = {
36
- labelText: 'Example label text',
37
- inline: true,
38
- };
39
-
40
- export const TextFieldWithLabelAndLabelRightNode = StoryTemplate.bind({});
41
- TextFieldWithLabelAndLabelRightNode.args = {
42
- labelText: 'Example label text',
43
- labelRightNode: <img src="https://via.placeholder.com/100" />,
44
- };
45
-
46
- export const TextFieldWithLabelAdornment = StoryTemplate.bind({});
47
- TextFieldWithLabelAdornment.args = {
48
- labelText: 'Example label text',
49
- labelAdornment: <img src="https://via.placeholder.com/100" />,
50
- };
51
-
52
- export const TextFieldWithError = StoryTemplate.bind({});
53
- TextFieldWithError.args = {
54
- error: 'Error text',
55
- };
56
-
57
- export const TextFieldWithDescription = StoryTemplate.bind({});
58
- TextFieldWithDescription.args = {
59
- description: <div>Description text</div>,
60
- };
@@ -1,100 +0,0 @@
1
- import * as React from 'react';
2
- import cx from 'clsx';
3
- import { Text } from '../Typography';
4
- import { FieldError } from '../FieldError';
5
- import { FieldDescription } from '../FieldDescription';
6
-
7
- import styles from './TextField.module.scss';
8
-
9
- const baseClass = 'text-field';
10
-
11
- export interface TextFieldProps {
12
- labelText?: string;
13
- labelAdornment?: React.ReactNode;
14
- labelFor?: string;
15
- className?: string;
16
- inline?: boolean;
17
- error?: string;
18
- description?: React.ReactNode;
19
- children?: React.ReactNode;
20
- labelRightNode?: React.ReactNode;
21
- }
22
-
23
- export const TextField: React.FC<TextFieldProps> = ({
24
- inline,
25
- error,
26
- description,
27
- labelText,
28
- labelAdornment,
29
- className,
30
- labelFor,
31
- children,
32
- labelRightNode,
33
- }) => {
34
- const mergedClassNames = cx(
35
- styles[baseClass],
36
- {
37
- [styles[`${baseClass}--inline`]]: inline,
38
- },
39
- className
40
- );
41
-
42
- return (
43
- <div className={mergedClassNames}>
44
- {labelRightNode && inline && (
45
- <React.Fragment>
46
- <div
47
- className={cx(
48
- styles[`${baseClass}__label-right-node`],
49
- styles[`${baseClass}__label-right-node--inline`]
50
- )}
51
- >
52
- {labelRightNode}
53
- </div>
54
- <div className={styles[`${baseClass}__row-break`]} />
55
- </React.Fragment>
56
- )}
57
- <div
58
- className={cx(
59
- styles[`${baseClass}__wrapper`],
60
- inline && styles[`${baseClass}__wrapper--inline`]
61
- )}
62
- >
63
- {(labelText || labelRightNode) && (
64
- <div
65
- className={cx(
66
- styles[`${baseClass}__label`],
67
- inline && styles[`${baseClass}__label--inline`],
68
- !labelText && styles[`${baseClass}__label--no-text`]
69
- )}
70
- >
71
- {labelText && (
72
- <div className={cx(styles[`${baseClass}__label-wrapper`])}>
73
- <label className="lc-field-label" htmlFor={labelFor}>
74
- <Text as="span" size="sm">
75
- {labelText}
76
- </Text>
77
- </label>
78
- {labelAdornment && (
79
- <div className={cx(styles[`${baseClass}__label-adornment`])}>
80
- {labelAdornment}
81
- </div>
82
- )}
83
- </div>
84
- )}
85
- {labelRightNode && !inline && (
86
- <div className={cx(styles[`${baseClass}__label-right-node`])}>
87
- {labelRightNode}
88
- </div>
89
- )}
90
- </div>
91
- )}
92
- <div className={cx(styles[`${baseClass}__content`])}>
93
- {children}
94
- {error && <FieldError>{error}</FieldError>}
95
- {description && <FieldDescription>{description}</FieldDescription>}
96
- </div>
97
- </div>
98
- </div>
99
- );
100
- };