@codacy/ui-components 0.67.69 → 0.67.71

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.
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ interface Props {
3
+ value: string;
4
+ className: string;
5
+ innerEditableRef: React.RefObject<HTMLDivElement>;
6
+ inputRef: React.RefObject<HTMLInputElement>;
7
+ change: (value: string) => void;
8
+ remove: () => void;
9
+ validator?: (value: string) => boolean;
10
+ removeOnBackspace?: boolean;
11
+ delimiters?: number[];
12
+ }
13
+ export declare class ContentEditable extends React.Component<Props> {
14
+ focused: boolean;
15
+ removed: boolean;
16
+ preFocusedValue: string;
17
+ componentDidMount(): void;
18
+ componentDidUpdate(prevProps: Props): void;
19
+ setContent: () => void;
20
+ onPaste: (e: React.ClipboardEvent<HTMLDivElement>) => void;
21
+ onClick: (e: React.MouseEvent<HTMLDivElement>) => void;
22
+ onFocus: () => void;
23
+ onBlur: () => void;
24
+ onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void;
25
+ getValue: () => string;
26
+ getRef: () => HTMLDivElement | null;
27
+ focusInputRef: () => void;
28
+ render(): React.JSX.Element;
29
+ }
30
+ export {};
@@ -0,0 +1,135 @@
1
+ import React from 'react';
2
+ import { removeLineBreaks } from './functions';
3
+ export class ContentEditable extends React.Component {
4
+ // Track focus state of editable tag
5
+ focused = false;
6
+
7
+ // Track if element has been removed from DOM
8
+ removed = false;
9
+
10
+ // Save value before input is focused / user starts typing
11
+ preFocusedValue = '';
12
+ componentDidMount() {
13
+ // The content of a contentEditable element is owned by the browser, not React, so it is
14
+ // written imperatively via the ref. `textContent` is used rather than `innerHTML` so the
15
+ // value is always treated as literal text and never parsed as markup.
16
+ this.setContent();
17
+ this.preFocusedValue = this.getValue();
18
+ }
19
+ componentDidUpdate(prevProps) {
20
+ if (prevProps.value !== this.props.value) {
21
+ this.setContent();
22
+ }
23
+ }
24
+ setContent = () => {
25
+ const ref = this.props.innerEditableRef.current;
26
+ const content = removeLineBreaks(this.props.value);
27
+ // Guard against clobbering the caret position when the DOM already holds this text
28
+ if (ref && ref.textContent !== content) {
29
+ ref.textContent = content;
30
+ }
31
+ };
32
+ onPaste = e => {
33
+ // Cancel paste event
34
+ e.preventDefault();
35
+
36
+ // Remove formatting from clipboard contents
37
+ const text = e.clipboardData.getData('text/plain');
38
+ const splitText = text.split(/,| /);
39
+ const firstString = splitText[0];
40
+
41
+ // Insert text manually from paste command. `insertText` inserts the string as literal
42
+ // text; `insertHTML` would parse it as markup.
43
+ document.execCommand('insertText', false, removeLineBreaks(firstString));
44
+ };
45
+ onClick = e => {
46
+ e.stopPropagation();
47
+ };
48
+ onFocus = () => {
49
+ this.preFocusedValue = this.getValue();
50
+ this.focused = true;
51
+ };
52
+ onBlur = () => {
53
+ this.focused = false;
54
+ const ref = this.props.innerEditableRef.current;
55
+ const {
56
+ validator,
57
+ change
58
+ } = this.props;
59
+ if (!this.removed && ref) {
60
+ // On blur, if no content in tag, remove it
61
+ if (ref.innerText === '') {
62
+ this.props.remove();
63
+ return;
64
+ }
65
+
66
+ // Validate input if needed
67
+ if (validator) {
68
+ const valid = validator(this.getValue());
69
+ // If invalidate, switch ref back to pre focused value
70
+ if (!valid) {
71
+ ref.innerText = this.preFocusedValue;
72
+ return;
73
+ }
74
+ }
75
+ change(ref.innerText);
76
+ }
77
+ };
78
+ onKeyDown = e => {
79
+ const {
80
+ delimiters
81
+ } = this.props;
82
+
83
+ // On enter, focus main tag input
84
+ if (e.keyCode === 13 || delimiters !== null && delimiters !== void 0 && delimiters.includes(e.keyCode)) {
85
+ e.preventDefault();
86
+ this.focusInputRef();
87
+ return;
88
+ }
89
+
90
+ // On backspace, if no content in ref, remove tag and focus main tag input
91
+ const {
92
+ removeOnBackspace
93
+ } = this.props;
94
+ const value = this.getValue();
95
+ if (removeOnBackspace && e.keyCode === 8 && value === '') {
96
+ this.removed = true;
97
+ this.props.remove();
98
+ this.focusInputRef();
99
+ return;
100
+ }
101
+ };
102
+ getValue = () => {
103
+ const ref = this.getRef();
104
+ return ref ? ref.innerText : '';
105
+ };
106
+ getRef = () => {
107
+ return this.props.innerEditableRef.current;
108
+ };
109
+ focusInputRef = () => {
110
+ const {
111
+ inputRef
112
+ } = this.props;
113
+ if (inputRef && inputRef.current) {
114
+ inputRef.current.focus();
115
+ }
116
+ };
117
+ render() {
118
+ const {
119
+ className,
120
+ innerEditableRef
121
+ } = this.props;
122
+ // No children are rendered here on purpose: the text is written as `textContent` in
123
+ // setContent(), so React never has to manage the children of a contentEditable node.
124
+ return /*#__PURE__*/React.createElement("div", {
125
+ ref: innerEditableRef,
126
+ className: className,
127
+ contentEditable: true,
128
+ onClick: this.onClick,
129
+ onPaste: this.onPaste,
130
+ onFocus: this.onFocus,
131
+ onBlur: this.onBlur,
132
+ onKeyDown: this.onKeyDown
133
+ });
134
+ }
135
+ }
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ type Tags = string[];
3
+ export interface ReactTagInputProps {
4
+ id?: string;
5
+ tags: Tags;
6
+ onChange: (tags: Tags) => void;
7
+ placeholder?: string;
8
+ maxTags?: number;
9
+ validator?: (val: string) => boolean;
10
+ editable?: boolean;
11
+ readOnly?: boolean;
12
+ removeOnBackspace?: boolean;
13
+ delimiters?: number[];
14
+ required?: boolean;
15
+ }
16
+ interface State {
17
+ input: string;
18
+ }
19
+ export declare class ReactTagInput extends React.Component<ReactTagInputProps, State> {
20
+ state: {
21
+ input: string;
22
+ };
23
+ inputRef: React.RefObject<HTMLInputElement>;
24
+ onWrapperClick: () => void;
25
+ onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
26
+ onInputKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
27
+ onBlur: () => void;
28
+ onPaste: (e: React.ClipboardEvent<HTMLInputElement>) => void;
29
+ addTag: (value: string) => void;
30
+ removeTag: (i: number) => void;
31
+ updateTag: (i: number, value: string) => void;
32
+ render(): React.JSX.Element;
33
+ }
34
+ export {};
@@ -0,0 +1,180 @@
1
+ import React from 'react';
2
+ import { Tag } from './Tag';
3
+ import { classSelectors } from './selectors';
4
+ export class ReactTagInput extends React.Component {
5
+ state = {
6
+ input: ''
7
+ };
8
+
9
+ // Ref for input element
10
+ inputRef = /*#__PURE__*/React.createRef();
11
+ onWrapperClick = () => {
12
+ var _this$inputRef$curren;
13
+ (_this$inputRef$curren = this.inputRef.current) === null || _this$inputRef$curren === void 0 || _this$inputRef$curren.focus();
14
+ };
15
+ onInputChange = e => {
16
+ var _this$inputRef$curren2;
17
+ const {
18
+ placeholder
19
+ } = this.props;
20
+ (_this$inputRef$curren2 = this.inputRef.current) === null || _this$inputRef$curren2 === void 0 || _this$inputRef$curren2.setAttribute('size', placeholder === null || placeholder === void 0 ? void 0 : placeholder.length.toString());
21
+ this.setState({
22
+ input: e.target.value
23
+ });
24
+ };
25
+ onInputKeyDown = e => {
26
+ const {
27
+ input
28
+ } = this.state;
29
+ const {
30
+ validator,
31
+ removeOnBackspace,
32
+ delimiters = [9, 13, 188, 32]
33
+ } = this.props;
34
+
35
+ //Check if alt + tab was hit to onfocus element
36
+ if (e.keyCode === 9 && e.altKey) {
37
+ var _this$inputRef$curren3;
38
+ (_this$inputRef$curren3 = this.inputRef.current) === null || _this$inputRef$curren3 === void 0 || _this$inputRef$curren3.blur();
39
+ }
40
+ // Check if default Enter or one of the delimiter keys was hit
41
+ else if (e.keyCode === 13 || delimiters !== null && delimiters !== void 0 && delimiters.includes(e.keyCode)) {
42
+ // Prevent form submission if tag input is nested in <form>
43
+ e.preventDefault();
44
+
45
+ // If input is blank, do nothing
46
+ if (input === '') {
47
+ return;
48
+ }
49
+
50
+ // Check if input is valid
51
+ const valid = validator !== undefined ? validator(input) : true;
52
+ if (!valid) {
53
+ return;
54
+ }
55
+
56
+ // Add input to tag list
57
+ this.addTag(input);
58
+ }
59
+ // On backspace or delete
60
+ else if (removeOnBackspace && (e.keyCode === 8 || e.keyCode === 46)) {
61
+ // If currently typing, do nothing
62
+ if (input !== '') {
63
+ return;
64
+ }
65
+
66
+ // If input is blank, remove previous tag
67
+ this.removeTag(this.props.tags.length - 1);
68
+ }
69
+ };
70
+ onBlur = () => {
71
+ const {
72
+ input
73
+ } = this.state;
74
+ const {
75
+ validator
76
+ } = this.props;
77
+ if (input === '') {
78
+ return;
79
+ }
80
+
81
+ // Check if input is valid
82
+ const valid = validator !== undefined ? validator(input) : true;
83
+ if (!valid) {
84
+ return;
85
+ }
86
+
87
+ // Add input to tag list
88
+ this.addTag(input);
89
+ };
90
+ onPaste = e => {
91
+ // Cancel paste event
92
+ e.preventDefault();
93
+
94
+ // Remove formatting from clipboard contents
95
+ const text = e.clipboardData.getData('text/plain');
96
+ const splitText = text.split(/[ ,\n\r\t\v\f\0]+/);
97
+
98
+ //If a list with spaces or commas is pasted, each item will be a tag
99
+ const tags = [...this.props.tags];
100
+ splitText.forEach(tag => {
101
+ if (!tags.includes(tag) && tag !== '') {
102
+ tags.push(tag);
103
+ }
104
+ });
105
+ this.props.onChange(tags);
106
+ };
107
+ addTag = value => {
108
+ const tags = [...this.props.tags];
109
+ if (!tags.includes(value)) {
110
+ tags.push(value);
111
+ this.props.onChange(tags);
112
+ }
113
+ this.setState({
114
+ input: ''
115
+ });
116
+ };
117
+ removeTag = i => {
118
+ const tags = [...this.props.tags];
119
+ tags.splice(i, 1);
120
+ this.props.onChange(tags);
121
+ };
122
+ updateTag = (i, value) => {
123
+ const tags = [...this.props.tags];
124
+ const numOccurrencesOfValue = tags.reduce((prev, currentValue, index) => prev + (currentValue === value && index !== i ? 1 : 0), 0);
125
+ if (numOccurrencesOfValue > 0) {
126
+ tags.splice(i, 1);
127
+ } else {
128
+ tags[i] = value;
129
+ }
130
+ this.props.onChange(tags);
131
+ };
132
+ render() {
133
+ const {
134
+ input
135
+ } = this.state;
136
+ const {
137
+ id,
138
+ tags,
139
+ placeholder = 'Type and press enter',
140
+ maxTags,
141
+ editable,
142
+ readOnly,
143
+ validator,
144
+ removeOnBackspace,
145
+ delimiters,
146
+ required = false
147
+ } = this.props;
148
+ const maxTagsReached = maxTags !== undefined ? tags.length >= maxTags : false;
149
+ const isEditable = readOnly ? false : editable || false;
150
+ const showInput = !readOnly && !maxTagsReached;
151
+ return /*#__PURE__*/React.createElement("div", {
152
+ id: id ? `${id}-wrapper` : '',
153
+ className: classSelectors.wrapper,
154
+ onClick: this.onWrapperClick
155
+ }, tags.map((tag, i) => /*#__PURE__*/React.createElement(Tag, {
156
+ key: i,
157
+ value: tag,
158
+ index: i,
159
+ editable: isEditable,
160
+ readOnly: readOnly || false,
161
+ inputRef: this.inputRef,
162
+ update: this.updateTag,
163
+ remove: this.removeTag,
164
+ validator: validator,
165
+ removeOnBackspace: removeOnBackspace,
166
+ delimiters: delimiters
167
+ })), showInput && /*#__PURE__*/React.createElement("input", {
168
+ id: id,
169
+ ref: this.inputRef,
170
+ value: input,
171
+ className: classSelectors.input,
172
+ placeholder: placeholder,
173
+ onChange: this.onInputChange,
174
+ onKeyDown: this.onInputKeyDown,
175
+ onPaste: this.onPaste,
176
+ onBlur: this.onBlur,
177
+ required: required
178
+ }));
179
+ }
180
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ interface Props {
3
+ value: string;
4
+ index: number;
5
+ editable: boolean;
6
+ readOnly: boolean;
7
+ inputRef: React.RefObject<HTMLInputElement>;
8
+ update: (i: number, value: string) => void;
9
+ remove: (i: number) => void;
10
+ validator?: (val: string) => boolean;
11
+ removeOnBackspace?: boolean;
12
+ delimiters?: number[];
13
+ }
14
+ export declare const CloseIcon: () => React.JSX.Element;
15
+ export declare class Tag extends React.Component<Props> {
16
+ innerEditableRef: React.RefObject<HTMLDivElement>;
17
+ remove: () => void;
18
+ render(): React.JSX.Element;
19
+ }
20
+ export {};
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { classSelectors } from './selectors';
3
+ import { ContentEditable } from './ContentEditable';
4
+ export const CloseIcon = () => /*#__PURE__*/React.createElement("svg", {
5
+ width: "8",
6
+ height: "8",
7
+ viewBox: "0 0 8 8",
8
+ fill: "none",
9
+ xmlns: "http://www.w3.org/2000/svg"
10
+ }, /*#__PURE__*/React.createElement("path", {
11
+ fillRule: "evenodd",
12
+ clipRule: "evenodd",
13
+ d: "M0.146447 0.146447C0.341709 -0.0488155 0.658291 -0.0488155 0.853553 0.146447L7.85355 7.14645C8.04882 7.34171 8.04882 7.65829 7.85355 7.85355C7.65829 8.04882 7.34171 8.04882 7.14645 7.85355L0.146447 0.853553C-0.0488155 0.658291 -0.0488155 0.341709 0.146447 0.146447Z",
14
+ fill: "#7E90B2"
15
+ }), /*#__PURE__*/React.createElement("path", {
16
+ fillRule: "evenodd",
17
+ clipRule: "evenodd",
18
+ d: "M7.85355 0.146447C8.04882 0.341709 8.04882 0.658291 7.85355 0.853553L0.853553 7.85355C0.658291 8.04882 0.341709 8.04882 0.146447 7.85355C-0.0488155 7.65829 -0.0488155 7.34171 0.146447 7.14645L7.14645 0.146447C7.34171 -0.0488155 7.65829 -0.0488155 7.85355 0.146447Z",
19
+ fill: "#7E90B2"
20
+ }));
21
+ export class Tag extends React.Component {
22
+ innerEditableRef = /*#__PURE__*/React.createRef();
23
+ remove = () => this.props.remove(this.props.index);
24
+ render() {
25
+ const {
26
+ value,
27
+ index,
28
+ editable,
29
+ inputRef,
30
+ validator,
31
+ update,
32
+ removeOnBackspace,
33
+ delimiters
34
+ } = this.props;
35
+ return /*#__PURE__*/React.createElement("div", {
36
+ className: classSelectors.tag
37
+ }, !editable && /*#__PURE__*/React.createElement("div", {
38
+ className: classSelectors.tagContent
39
+ }, value), editable && /*#__PURE__*/React.createElement(ContentEditable, {
40
+ value: value,
41
+ inputRef: inputRef,
42
+ innerEditableRef: this.innerEditableRef,
43
+ className: classSelectors.tagContent,
44
+ change: newValue => update(index, newValue),
45
+ remove: this.remove,
46
+ validator: validator,
47
+ removeOnBackspace: removeOnBackspace,
48
+ delimiters: delimiters
49
+ }), /*#__PURE__*/React.createElement("div", {
50
+ className: classSelectors.tagRemove,
51
+ onClick: this.remove
52
+ }, /*#__PURE__*/React.createElement(CloseIcon, null)));
53
+ }
54
+ }
@@ -0,0 +1 @@
1
+ export declare function removeLineBreaks(value: string): string;
@@ -0,0 +1,3 @@
1
+ export function removeLineBreaks(value) {
2
+ return value.replace(/(\r\n|\n|\r)/gm, '');
3
+ }
@@ -0,0 +1 @@
1
+ export * from './ReactTagInput';
@@ -0,0 +1 @@
1
+ export * from './ReactTagInput';
@@ -0,0 +1,8 @@
1
+ export declare const classSelectors: {
2
+ wrapper: string;
3
+ input: string;
4
+ tag: string;
5
+ tagContent: string;
6
+ tagRemove: string;
7
+ tagRemoveReadOnly: string;
8
+ };
@@ -0,0 +1,8 @@
1
+ export const classSelectors = {
2
+ wrapper: 'react-tag-input',
3
+ input: 'react-tag-input__input',
4
+ tag: 'react-tag-input__tag',
5
+ tagContent: 'react-tag-input__tag__content',
6
+ tagRemove: 'react-tag-input__tag__remove',
7
+ tagRemoveReadOnly: 'react-tag-input__tag__remove-readonly'
8
+ };
@@ -1,6 +1,6 @@
1
1
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
2
  import React from 'react';
3
- import ReactTagInput from '@pathofdev/react-tag-input';
3
+ import { ReactTagInput } from './ReactTagInput';
4
4
  import { StyledTagsInput, TagsInputWrapper } from './style';
5
5
  import { Labeled } from '../';
6
6
  export const TagsInput = ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/ui-components",
3
- "version": "0.67.69",
3
+ "version": "0.67.71",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -36,7 +36,6 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@babel/runtime": "^7.23.6",
39
- "@pathofdev/react-tag-input": "github:inesgomas/react-tag-input",
40
39
  "@styled-system/should-forward-prop": "^5.1.5",
41
40
  "@testing-library/user-event": "^14.6.1",
42
41
  "autosize": "^4.0.2",