@widergy/mobile-ui 1.13.5 → 1.14.1

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 (50) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/lib/components/Surface/propTypes.js +3 -2
  3. package/lib/components/UTBaseInputField/README.md +179 -0
  4. package/lib/components/UTBaseInputField/components/ActionAdornment/index.js +41 -0
  5. package/lib/components/UTBaseInputField/components/IconAdornment/constants.js +1 -0
  6. package/lib/components/UTBaseInputField/components/IconAdornment/index.js +32 -0
  7. package/lib/components/UTBaseInputField/components/IconAdornment/utils.js +2 -0
  8. package/lib/components/UTBaseInputField/components/PrefixAdornment/index.js +16 -0
  9. package/lib/components/UTBaseInputField/components/SuffixAdornment/index.js +12 -0
  10. package/lib/components/UTBaseInputField/components/TooltipAdornment/index.js +19 -0
  11. package/lib/components/UTBaseInputField/constants.js +34 -0
  12. package/lib/components/UTBaseInputField/index.js +191 -0
  13. package/lib/components/{UTTextInput/versions/V1/components/TextInputField → UTBaseInputField}/theme.js +3 -2
  14. package/lib/components/UTButton/README.md +1 -1
  15. package/lib/components/UTButton/index.js +8 -2
  16. package/lib/components/UTCheckBox/README.md +15 -17
  17. package/lib/components/UTCheckBox/constants.js +2 -0
  18. package/lib/components/UTCheckBox/index.js +50 -24
  19. package/lib/components/UTCheckBox/proptypes.js +7 -10
  20. package/lib/components/UTCheckBox/theme.js +26 -15
  21. package/lib/components/UTCheckList/constants.js +1 -0
  22. package/lib/components/UTCheckList/index.js +43 -46
  23. package/lib/components/UTCheckList/styles.js +8 -11
  24. package/lib/components/UTCheckList/utils.js +5 -0
  25. package/lib/components/{UTRequiredLabel → UTFieldLabel}/index.js +3 -3
  26. package/lib/components/UTIcon/README.md +10 -10
  27. package/lib/components/UTIcon/index.js +6 -8
  28. package/lib/components/UTIcon/theme.js +1 -5
  29. package/lib/components/UTRoundView/index.js +22 -9
  30. package/lib/components/UTRoundView/propTypes.js +4 -2
  31. package/lib/components/UTRoundView/styles.js +8 -0
  32. package/lib/components/UTRoundView/utils.js +14 -0
  33. package/lib/components/UTSelect/index.js +5 -4
  34. package/lib/components/UTTextArea/constants.js +3 -1
  35. package/lib/components/UTTextArea/index.js +4 -4
  36. package/lib/components/UTTextInput/versions/V0/components/BaseInput/index.js +1 -1
  37. package/lib/components/UTTextInput/versions/V1/README.md +6 -15
  38. package/lib/components/UTTextInput/versions/V1/components/TextInputField/index.js +67 -201
  39. package/lib/components/UTTextInput/versions/V1/constants.js +1 -1
  40. package/lib/components/UTTextInput/versions/V1/index.js +5 -5
  41. package/lib/components/UTValidation/README.md +9 -6
  42. package/lib/components/UTValidation/index.js +8 -6
  43. package/lib/components/UTValidation/utils.js +4 -0
  44. package/package.json +4 -3
  45. package/lib/components/UTTextInput/versions/V1/components/TextInputField/constants.js +0 -12
  46. package/lib/components/UTTextInput/versions/V1/components/TextInputField/utils.js +0 -13
  47. package/lib/components/UTTextInput/versions/V1/utils.js +0 -1
  48. /package/lib/components/{UTRequiredLabel → UTFieldLabel}/constants.js +0 -0
  49. /package/lib/components/{UTRequiredLabel → UTFieldLabel}/styles.js +0 -0
  50. /package/lib/components/{UTButton → UTIcon}/utils.js +0 -0
@@ -3,11 +3,11 @@ import React from 'react';
3
3
  import UTTextInput from '../UTTextInput';
4
4
  import propTypes from '../UTTextInput/versions/V1/proptypes';
5
5
 
6
- import { DEFAULT_MAX_ROWS } from './constants';
6
+ import { DEFAULT_PROPS } from './constants';
7
7
 
8
- const UTTextArea = ({ maxRows = DEFAULT_MAX_ROWS, ...props }) => (
9
- <UTTextInput maxRows={maxRows} version="V1" {...props} />
10
- );
8
+ const UTTextArea = ({ maxRows, ...props }) => <UTTextInput maxRows={maxRows} version="V1" {...props} />;
9
+
10
+ UTTextArea.defaultProps = DEFAULT_PROPS;
11
11
 
12
12
  UTTextArea.propTypes = propTypes;
13
13
 
@@ -97,7 +97,7 @@ const BaseInput = forwardRef(
97
97
  ]}
98
98
  id={props?.id ? `${props.id}` : undefined}
99
99
  />
100
- {(RightIcon || hiddenInput) && (
100
+ {RightIcon && (
101
101
  <Touchable
102
102
  borderless
103
103
  onPress={hiddenInput ? toggleShowInput : onRightIconPress}
@@ -50,15 +50,15 @@ Configuration object for the action button.
50
50
 
51
51
  It must be one of these:
52
52
 
53
- - "s": small
54
- - "l": large
53
+ - "small": small
54
+ - "large": large
55
55
 
56
56
  ### inputSize
57
57
 
58
58
  It must be one of these:
59
59
 
60
- - "s": small
61
- - "l": large
60
+ - "small": small
61
+ - "large": large
62
62
 
63
63
  ### type
64
64
 
@@ -147,11 +147,7 @@ If both `error` and `validations` are provided, `validations` will take preceden
147
147
  #### Example usage with `error`:
148
148
 
149
149
  ```jsx
150
- <UTTextInput
151
- label="Username"
152
- placeholder="Enter your username"
153
- error="This username is already taken"
154
- />
150
+ <UTTextInput label="Username" placeholder="Enter your username" error="This username is already taken" />
155
151
  ```
156
152
 
157
153
  #### Example usage with validations:
@@ -192,12 +188,7 @@ const validations = [
192
188
  }
193
189
  ];
194
190
 
195
- <UTTextInput
196
- label="Email"
197
- placeholder="Enter your email"
198
- validations={validations}
199
- />
200
-
191
+ <UTTextInput label="Email" placeholder="Enter your email" validations={validations} />;
201
192
  ```
202
193
 
203
194
  ## Usage
@@ -1,205 +1,71 @@
1
- import React, {
2
- useState,
3
- useRef,
4
- useEffect,
5
- useCallback,
6
- useLayoutEffect,
7
- useImperativeHandle,
8
- forwardRef
9
- } from 'react';
10
- import { bool, elementType, func, number, string, shape } from 'prop-types';
11
- import { View, TextInput } from 'react-native';
1
+ import React from 'react';
2
+ import { bool, elementType, func, number, shape, string } from 'prop-types';
12
3
  import { ViewPropTypes } from 'deprecated-react-native-prop-types';
13
4
 
14
- import { useTheme } from '../../../../../../theming';
15
- import UTButton from '../../../../../UTButton';
16
- import UTIcon from '../../../../../UTIcon';
17
- import UTLabel from '../../../../../UTLabel';
18
- import UTTooltip from '../../../../../UTTooltip';
19
-
20
- import { ERROR_ICON, KEYBOARD_BY_TYPE, TYPES } from './constants';
21
- import { renderLeftIcon, renderRightIcon } from './utils';
22
- import { retrieveStyle } from './theme';
23
-
24
- const TextInputField = forwardRef(
25
- (
26
- {
27
- action,
28
- alwaysShowPlaceholder,
29
- disabled,
30
- error,
31
- id,
32
- inputSize,
33
- LeftIcon,
34
- maxCount,
35
- maxRows,
36
- onBlur,
37
- onChange,
38
- onFocus,
39
- onSubmitEditing,
40
- placeholder,
41
- prefix,
42
- readOnly,
43
- returnKeyType,
44
- RightIcon,
45
- style,
46
- suffix,
47
- tooltip,
48
- type,
49
- value
50
- },
51
- ref
52
- ) => {
53
- const [displayValue, setDisplayValue] = useState(value);
54
- const [focused, setFocused] = useState(false);
55
- const [inputWidth, setInputWidth] = useState(null);
56
- const [internalValue, setInternalValue] = useState(value);
57
- const textInputRef = useRef(null);
58
-
59
- const theme = useTheme();
60
- const multiline = maxRows > 1;
61
-
62
- useImperativeHandle(
63
- ref,
64
- () => ({
65
- focus: () => textInputRef.current?.focus(),
66
- blur: () => textInputRef.current?.blur(),
67
- setValue: text => textInputRef.current?.setNativeProps({ text }),
68
- clear: () => textInputRef.current?.setNativeProps({ text: '' })
69
- }),
70
- []
71
- );
72
-
73
- const handleTextChange = useCallback(
74
- text => {
75
- setInternalValue(text);
76
- onChange?.(text);
77
- },
78
- [onChange]
79
- );
80
-
81
- const handleFocus = useCallback(
82
- event => {
83
- setFocused(true);
84
- if (!multiline) setDisplayValue(internalValue);
85
- onFocus?.(event);
86
- },
87
- [onFocus, internalValue, multiline]
88
- );
89
-
90
- const handleBlur = useCallback(
91
- event => {
92
- const truncateText = text => {
93
- if (!inputWidth || !text) return text;
94
-
95
- const charWidth = 8;
96
- const maxCharsPerLine = Math.floor(inputWidth / charWidth);
97
- const maxLength = maxCharsPerLine;
98
-
99
- return text.length > maxLength ? `${text.substring(0, maxLength - 3)}...` : text;
100
- };
101
-
102
- setFocused(false);
103
- if (!multiline) setDisplayValue(truncateText(internalValue));
104
- onBlur?.(event);
105
- },
106
- [inputWidth, internalValue, multiline, onBlur]
107
- );
108
-
109
- const { actionStyle, containerStyle, inputRowStyle, inputStyle, textLengthRowStyle } = retrieveStyle({
110
- disabled,
111
- error,
112
- focused,
113
- inputSize,
114
- maxRows,
115
- multiline,
116
- readOnly,
117
- style,
118
- theme
119
- });
120
-
121
- useEffect(() => {
122
- setInternalValue(value);
123
- setDisplayValue(value);
124
- }, [value]);
125
-
126
- useLayoutEffect(() => {
127
- if (textInputRef.current) {
128
- textInputRef.current.measure((_x, _y, width) => {
129
- setInputWidth(width);
130
- });
131
- }
132
- }, [focused]);
133
-
134
- const secureTextEntry = type === TYPES.PASSWORD;
135
- const autoCapitalize = type === TYPES.EMAIL ? 'none' : 'sentences';
136
- const keyboardType = KEYBOARD_BY_TYPE[type] || 'default';
137
-
138
- const rightIcon = error ? ERROR_ICON : RightIcon;
139
-
140
- return (
141
- <View style={containerStyle}>
142
- <View style={inputRowStyle}>
143
- {LeftIcon && renderLeftIcon(inputStyle.root.color, LeftIcon)}
144
- {prefix && <UTLabel colorTheme="gray">{prefix}</UTLabel>}
145
- <TextInput
146
- autoCapitalize={autoCapitalize}
147
- autoCorrect={false}
148
- editable={!disabled && !readOnly}
149
- id={id ? `${id}` : undefined}
150
- keyboardType={keyboardType}
151
- maxLength={maxCount}
152
- multiline={multiline}
153
- numberOfLines={maxRows}
154
- onChangeText={handleTextChange}
155
- onEndEditing={handleBlur}
156
- onFocus={handleFocus}
157
- onSubmitEditing={onSubmitEditing}
158
- placeholder={!focused && !alwaysShowPlaceholder ? '' : placeholder}
159
- placeholderTextColor={inputStyle.placeholderTextColor}
160
- ref={textInputRef}
161
- returnKeyType={returnKeyType}
162
- secureTextEntry={secureTextEntry}
163
- selectionColor={inputStyle.selectionColor}
164
- style={inputStyle.root}
165
- type={type}
166
- value={focused || multiline ? internalValue : displayValue}
167
- />
168
- {suffix && (
169
- <UTLabel colorTheme="gray" weight="medium" variant="small">
170
- {suffix}
171
- </UTLabel>
172
- )}
173
- {action && (
174
- <UTButton
175
- disabled={disabled}
176
- style={actionStyle}
177
- variant="text"
178
- colorTheme={action.colorTheme}
179
- Icon={action.icon}
180
- onPress={action.onPress}
181
- >
182
- {action.text}
183
- </UTButton>
184
- )}
185
- {rightIcon && renderRightIcon(error, inputStyle.root.color, rightIcon)}
186
- {!!tooltip && (
187
- <UTTooltip content={<UTLabel>{tooltip}</UTLabel>}>
188
- <UTIcon name="IconInfoCircle" color="gray" />
189
- </UTTooltip>
190
- )}
191
- </View>
192
- {maxCount && (
193
- <View style={textLengthRowStyle}>
194
- <UTLabel colorTheme="gray" variant="small">
195
- {internalValue?.length || 0}/{maxCount}
196
- </UTLabel>
197
- </View>
198
- )}
199
- </View>
200
- );
201
- }
202
- );
5
+ import UTBaseInputField from '../../../../../UTBaseInputField';
6
+ import { COMPONENT_KEYS } from '../../../../../UTBaseInputField/constants';
7
+
8
+ const TextInputField = ({
9
+ action,
10
+ alwaysShowPlaceholder,
11
+ disabled,
12
+ error,
13
+ InputRef,
14
+ inputSize,
15
+ LeftIcon,
16
+ maxCount,
17
+ maxRows,
18
+ onBlur,
19
+ onChange,
20
+ onFocus,
21
+ onSubmitEditing,
22
+ placeholder,
23
+ prefix,
24
+ readOnly,
25
+ returnKeyType,
26
+ RightIcon,
27
+ style,
28
+ suffix,
29
+ tooltip,
30
+ type,
31
+ value
32
+ }) => {
33
+ const leftAdornments = [
34
+ { name: COMPONENT_KEYS.ICON, props: { Icon: LeftIcon } },
35
+ { name: COMPONENT_KEYS.PREFIX, props: { text: prefix } }
36
+ ];
37
+
38
+ const rightAdornments = [
39
+ { name: COMPONENT_KEYS.SUFFIX, props: { text: suffix } },
40
+ { name: COMPONENT_KEYS.ICON, props: { Icon: RightIcon, changeOnError: true } },
41
+ { name: COMPONENT_KEYS.ACTION, props: { action } },
42
+ { name: COMPONENT_KEYS.TOOLTIP, props: { tooltip } }
43
+ ];
44
+
45
+ return (
46
+ <UTBaseInputField
47
+ alwaysShowPlaceholder={alwaysShowPlaceholder}
48
+ disabled={disabled}
49
+ error={error}
50
+ inputSize={inputSize}
51
+ leftAdornments={leftAdornments}
52
+ maxCount={maxCount}
53
+ maxRows={maxRows}
54
+ onBlur={onBlur}
55
+ onChange={onChange}
56
+ onFocus={onFocus}
57
+ onSubmitEditing={onSubmitEditing}
58
+ placeholder={placeholder}
59
+ readOnly={readOnly}
60
+ ref={InputRef}
61
+ returnKeyType={returnKeyType}
62
+ rightAdornments={rightAdornments}
63
+ style={style}
64
+ type={type}
65
+ value={value}
66
+ />
67
+ );
68
+ };
203
69
 
204
70
  TextInputField.displayName = 'TextInputField';
205
71
 
@@ -208,7 +74,7 @@ TextInputField.propTypes = {
208
74
  alwaysShowPlaceholder: bool,
209
75
  disabled: bool,
210
76
  error: string,
211
- id: string,
77
+ InputRef: func,
212
78
  inputSize: string,
213
79
  LeftIcon: elementType,
214
80
  maxCount: number,
@@ -3,4 +3,4 @@ export const DEFAULT_PROPS = {
3
3
  style: {}
4
4
  };
5
5
 
6
- export const SMALL = 's';
6
+ export const SMALL = 'small';
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
2
  import { View } from 'react-native';
3
3
 
4
+ import { formatErrorToValidation } from '../../../UTValidation/utils';
4
5
  import UTLabel from '../../../UTLabel';
5
- import UTRequiredLabel from '../../../UTRequiredLabel';
6
+ import UTFieldLabel from '../../../UTFieldLabel';
6
7
  import UTValidation from '../../../UTValidation';
7
8
 
8
9
  import { DEFAULT_PROPS, SMALL } from './constants';
9
- import { formatErrorToValidation } from './utils';
10
10
  import propTypes from './proptypes';
11
11
  import styles from './styles';
12
12
  import TextInputField from './components/TextInputField';
@@ -48,15 +48,16 @@ const UTTextInput = ({
48
48
  return (
49
49
  <View style={[styles.container, style.root]}>
50
50
  {label && (
51
- <UTRequiredLabel colorTheme={labelColorTheme} required={required} variant={labelComponentVariant}>
51
+ <UTFieldLabel colorTheme={labelColorTheme} required={required} variant={labelComponentVariant}>
52
52
  {label}
53
- </UTRequiredLabel>
53
+ </UTFieldLabel>
54
54
  )}
55
55
  <TextInputField
56
56
  action={action}
57
57
  alwaysShowPlaceholder={alwaysShowPlaceholder}
58
58
  disabled={disabled}
59
59
  error={error}
60
+ InputRef={InputRef}
60
61
  inputSize={inputSize}
61
62
  LeftIcon={LeftIcon}
62
63
  maxCount={maxCount}
@@ -68,7 +69,6 @@ const UTTextInput = ({
68
69
  placeholder={placeholder}
69
70
  prefix={prefix}
70
71
  readOnly={readOnly}
71
- ref={InputRef}
72
72
  returnKeyType={returnKeyType}
73
73
  RightIcon={RightIcon}
74
74
  style={style}
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Description
4
4
 
5
- `UTValidation` is a component designed to display input validation messages. The statuses of the messages can be information, error, or success, helping users understand the current state of their input.
5
+ `UTValidation` is a component designed to display input validation messages. The statuses of the messages can be information, error, or success, helping users understand the current state of their input. The component also supports optional icons for each validation item.
6
6
 
7
7
  ## Props
8
8
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## Validation Data
15
15
 
16
- The `validationData` prop is an array of objects, each representing a validation message or group of messages. Each object can optionally have a `title` and must have a `status` and an `items` array. The `items` array contains objects, each with `text` and `status` properties.
16
+ The `validationData` prop is an array of objects, each representing a validation message or group of messages. Each object can optionally have a `title` and must have a `status` and an `items` array. The `items` array contains objects, each with `text`, `status`, and an optional `withIcon` property.
17
17
 
18
18
  ### Structure of validationData
19
19
 
@@ -22,6 +22,7 @@ The `validationData` prop is an array of objects, each representing a validation
22
22
  - **items** (required): An array of objects, each representing an individual validation item.
23
23
  - **text** (required): A string containing the validation message.
24
24
  - **status** (required): A string indicating the status of the validation item. Possible values are `success`, `error`, and `default`.
25
+ - **withIcon** (optional): A boolean indicating whether to display an icon next to the validation message. Defaults to `true`.
25
26
 
26
27
  ### Example
27
28
 
@@ -31,7 +32,8 @@ const validationData = [
31
32
  items: [
32
33
  {
33
34
  status: 'success',
34
- text: 'Debe tener como mínimo 8 caracteres.'
35
+ text: 'Debe tener como mínimo 8 caracteres.',
36
+ withIcon: true // Optional, defaults to true
35
37
  }
36
38
  ]
37
39
  },
@@ -40,14 +42,15 @@ const validationData = [
40
42
  status: 'error',
41
43
  items: [
42
44
  {
43
- text: 'Al menos 1 letra minúscula.' // Defaults to "default"
45
+ text: 'Al menos 1 letra minúscula.' // Defaults to "default" and "withIcon" to true
44
46
  },
45
47
  {
46
- text: 'Al menos 1 letra mayúscula.' // Defaults to "default"
48
+ text: 'Al menos 1 letra mayúscula.' // Defaults to "default" and "withIcon" to true
47
49
  },
48
50
  {
49
51
  status: 'success',
50
- text: 'Al menos 1 número.'
52
+ text: 'Al menos 1 número.',
53
+ withIcon: false // Will not display an icon
51
54
  }
52
55
  ]
53
56
  }
@@ -39,16 +39,18 @@ const UTValidation = ({ style, validationData }) => {
39
39
  </UTLabel>
40
40
  )}
41
41
  <View style={styles.itemsContainer}>
42
- {items.map(({ text, status: itemStatus = STATUSES.default }, itemIndex) => (
42
+ {items.map(({ text, status: itemStatus = STATUSES.default, withIcon = true }, itemIndex) => (
43
43
  <View
44
44
  key={generateItemKey({ text, status: itemStatus }, itemIndex)}
45
45
  style={styles.itemContainer}
46
46
  >
47
- <View style={[styles.iconContainer, themeStyles.icon[itemStatus]]}>
48
- {showIcon(itemStatus) && (
49
- <UTIcon color={itemStatus} name={ICON_MAPPER[itemStatus]} size={ICON_SIZE} />
50
- )}
51
- </View>
47
+ {withIcon && (
48
+ <View style={[styles.iconContainer, themeStyles.icon[itemStatus]]}>
49
+ {showIcon(itemStatus) && (
50
+ <UTIcon colorTheme={itemStatus} name={ICON_MAPPER[itemStatus]} size={ICON_SIZE} />
51
+ )}
52
+ </View>
53
+ )}
52
54
  <UTLabel colorTheme={STATUS_COLOR_MAPPER[itemStatus]} variant="small">
53
55
  {text}
54
56
  </UTLabel>
@@ -6,3 +6,7 @@ export const generateKey = (data, index) => {
6
6
  };
7
7
 
8
8
  export const generateItemKey = (item, index) => `${index}-${item.status}-${item.text}`;
9
+
10
+ export const formatErrorToValidation = (error, options) => [
11
+ { items: [{ text: error, status: 'error', withIcon: options?.withIcon }] }
12
+ ];
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@widergy/mobile-ui",
3
3
  "description": "Widergy Mobile Components",
4
4
  "author": "widergy",
5
- "version": "1.13.5",
5
+ "version": "1.14.1",
6
6
  "repository": "https://github.com/widergy/mobile-ui.git",
7
7
  "main": "lib/index.js",
8
8
  "files": [
@@ -45,8 +45,9 @@
45
45
  "react-native-collapsible": "^1.6.1",
46
46
  "react-native-markdown-display": "^7.0.0-alpha.2",
47
47
  "react-native-modal": "^13.0.1",
48
- "react-native-safe-area-context": "^4.5.0",
49
- "react-native-pager-view": "^6.2.1"
48
+ "react-native-pager-view": "^6.2.1",
49
+ "react-native-svg": "^13.13.0",
50
+ "react-native-safe-area-context": "^4.5.0"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@babel/cli": "^7.22.10",
@@ -1,12 +0,0 @@
1
- export const TYPES = {
2
- EMAIL: 'email',
3
- NUMERIC: 'numeric',
4
- PASSWORD: 'password'
5
- };
6
-
7
- export const KEYBOARD_BY_TYPE = {
8
- [TYPES.EMAIL]: 'email-address',
9
- [TYPES.NUMERIC]: 'numeric'
10
- };
11
-
12
- export const ERROR_ICON = 'IconInfoCircle';
@@ -1,13 +0,0 @@
1
- import React from 'react';
2
-
3
- import UTIcon from '../../../../../UTIcon';
4
-
5
- const isUTIcon = icon => typeof icon === 'string';
6
-
7
- const getIconColorProps = error => (error ? { color: 'error', shade: '04' } : { color: 'gray' });
8
-
9
- export const renderLeftIcon = (themeColor, Icon) =>
10
- isUTIcon(Icon) ? <UTIcon name={Icon} color="gray" /> : <Icon fill={themeColor} />;
11
-
12
- export const renderRightIcon = (error, themeColor, Icon) =>
13
- isUTIcon(Icon) ? <UTIcon name={Icon} {...getIconColorProps(error)} /> : <Icon fill={themeColor} />;
@@ -1 +0,0 @@
1
- export const formatErrorToValidation = error => [{ items: [{ text: error, status: 'error' }] }];
File without changes