cx 25.4.1 → 25.5.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 (140) hide show
  1. package/dist/charts.js +2 -2
  2. package/dist/data.js +17 -3
  3. package/dist/manifest.js +732 -732
  4. package/dist/ui.js +94 -61
  5. package/dist/widgets.js +25 -13
  6. package/package.json +1 -1
  7. package/src/charts/Legend.d.ts +45 -45
  8. package/src/charts/LegendEntry.js +128 -128
  9. package/src/charts/LegendEntry.scss +27 -27
  10. package/src/charts/PieChart.d.ts +92 -92
  11. package/src/charts/RangeMarker.js +6 -2
  12. package/src/charts/axis/Axis.d.ts +113 -113
  13. package/src/charts/axis/Axis.js +280 -280
  14. package/src/charts/axis/CategoryAxis.d.ts +30 -30
  15. package/src/charts/axis/CategoryAxis.js +241 -241
  16. package/src/charts/axis/NumericAxis.d.ts +46 -46
  17. package/src/charts/axis/NumericAxis.js +351 -351
  18. package/src/charts/axis/Stack.js +55 -55
  19. package/src/charts/axis/TimeAxis.d.ts +31 -28
  20. package/src/charts/axis/TimeAxis.js +611 -611
  21. package/src/charts/helpers/PointReducer.js +47 -47
  22. package/src/charts/helpers/SnapPointFinder.js +69 -69
  23. package/src/data/AugmentedViewBase.js +77 -75
  24. package/src/data/Binding.spec.js +69 -69
  25. package/src/data/ExposedRecordView.js +75 -70
  26. package/src/data/ExposedValueView.js +73 -72
  27. package/src/data/Expression.js +229 -229
  28. package/src/data/Expression.spec.js +229 -229
  29. package/src/data/Ref.d.ts +24 -24
  30. package/src/data/Ref.spec.js +79 -79
  31. package/src/data/StoreRef.spec.js +24 -24
  32. package/src/data/StringTemplate.js +92 -92
  33. package/src/data/StringTemplate.spec.js +132 -132
  34. package/src/data/StructuredDataAccessor.d.ts +7 -7
  35. package/src/data/StructuredSelector.js +132 -132
  36. package/src/data/SubscribableView.js +54 -54
  37. package/src/data/getAccessor.spec.js +11 -11
  38. package/src/data/getSelector.js +49 -49
  39. package/src/hooks/createLocalStorageRef.d.ts +3 -3
  40. package/src/hooks/createLocalStorageRef.js +20 -20
  41. package/src/index.scss +6 -6
  42. package/src/ui/Container.js +154 -183
  43. package/src/ui/Culture.d.ts +57 -57
  44. package/src/ui/Culture.js +139 -139
  45. package/src/ui/Cx.js +3 -3
  46. package/src/ui/DataProxy.js +45 -44
  47. package/src/ui/DetachedScope.js +98 -94
  48. package/src/ui/FocusManager.js +171 -171
  49. package/src/ui/Format.js +108 -108
  50. package/src/ui/HoverSync.js +147 -147
  51. package/src/ui/Instance.d.ts +1 -1
  52. package/src/ui/Instance.js +25 -16
  53. package/src/ui/IsolatedScope.js +30 -30
  54. package/src/ui/Repeater.d.ts +61 -61
  55. package/src/ui/Repeater.js +109 -102
  56. package/src/ui/Rescope.js +35 -31
  57. package/src/ui/Restate.js +167 -163
  58. package/src/ui/Widget.js +184 -200
  59. package/src/ui/adapter/ArrayAdapter.js +152 -142
  60. package/src/ui/adapter/TreeAdapter.js +101 -100
  61. package/src/ui/createFunctionalComponent.d.ts +1 -1
  62. package/src/ui/createFunctionalComponent.js +31 -36
  63. package/src/ui/layout/ContentPlaceholder.d.ts +19 -19
  64. package/src/ui/layout/ContentPlaceholder.js +105 -105
  65. package/src/ui/layout/ContentPlaceholder.spec.js +579 -579
  66. package/src/ui/layout/LabelsTopLayout.js +134 -134
  67. package/src/ui/layout/exploreChildren.d.ts +12 -15
  68. package/src/ui/layout/exploreChildren.js +27 -40
  69. package/src/util/Format.js +270 -270
  70. package/src/util/date/encodeDate.d.ts +1 -1
  71. package/src/util/date/encodeDate.js +8 -8
  72. package/src/util/date/encodeDateWithTimezoneOffset.d.ts +1 -1
  73. package/src/util/date/index.d.ts +11 -11
  74. package/src/util/date/index.js +11 -11
  75. package/src/util/date/parseDateInvariant.d.ts +3 -3
  76. package/src/util/date/parseDateInvariant.js +20 -20
  77. package/src/util/debounce.js +18 -18
  78. package/src/util/getSearchQueryPredicate.js +59 -59
  79. package/src/util/index.d.ts +51 -51
  80. package/src/util/index.js +54 -54
  81. package/src/util/isValidIdentifierName.d.ts +1 -1
  82. package/src/util/isValidIdentifierName.js +5 -5
  83. package/src/util/isValidIdentifierName.spec.js +33 -33
  84. package/src/util/scss/add-rules.scss +38 -38
  85. package/src/util/validatedDebounce.js +19 -19
  86. package/src/widgets/Button.js +118 -118
  87. package/src/widgets/CxCredit.scss +37 -37
  88. package/src/widgets/HighlightedSearchText.js +36 -36
  89. package/src/widgets/HighlightedSearchText.scss +18 -18
  90. package/src/widgets/List.js +594 -587
  91. package/src/widgets/List.scss +91 -91
  92. package/src/widgets/Sandbox.js +9 -8
  93. package/src/widgets/drag-drop/DropZone.js +214 -214
  94. package/src/widgets/form/Calendar.d.ts +86 -86
  95. package/src/widgets/form/Calendar.js +618 -618
  96. package/src/widgets/form/Calendar.scss +196 -196
  97. package/src/widgets/form/Checkbox.scss +127 -127
  98. package/src/widgets/form/ColorField.js +397 -397
  99. package/src/widgets/form/ColorField.scss +96 -96
  100. package/src/widgets/form/ColorPicker.scss +283 -283
  101. package/src/widgets/form/DateTimeField.js +576 -576
  102. package/src/widgets/form/DateTimePicker.js +392 -392
  103. package/src/widgets/form/LookupField.d.ts +179 -179
  104. package/src/widgets/form/LookupField.scss +219 -219
  105. package/src/widgets/form/MonthField.d.ts +99 -99
  106. package/src/widgets/form/MonthField.js +523 -523
  107. package/src/widgets/form/MonthPicker.d.ts +76 -76
  108. package/src/widgets/form/MonthPicker.js +641 -641
  109. package/src/widgets/form/MonthPicker.scss +118 -118
  110. package/src/widgets/form/NumberField.js +459 -459
  111. package/src/widgets/form/NumberField.scss +61 -61
  112. package/src/widgets/form/Radio.scss +121 -121
  113. package/src/widgets/form/Select.scss +99 -99
  114. package/src/widgets/form/Slider.scss +118 -118
  115. package/src/widgets/form/Switch.scss +140 -140
  116. package/src/widgets/form/TextArea.scss +43 -43
  117. package/src/widgets/form/TextField.js +290 -290
  118. package/src/widgets/form/TextField.scss +55 -55
  119. package/src/widgets/form/UploadButton.d.ts +34 -34
  120. package/src/widgets/form/variables.scss +353 -353
  121. package/src/widgets/grid/Grid.d.ts +442 -442
  122. package/src/widgets/grid/Grid.js +7 -0
  123. package/src/widgets/grid/GridRow.js +228 -228
  124. package/src/widgets/grid/TreeNode.d.ts +23 -23
  125. package/src/widgets/grid/TreeNode.scss +88 -88
  126. package/src/widgets/grid/variables.scss +133 -133
  127. package/src/widgets/nav/LinkButton.js +128 -128
  128. package/src/widgets/nav/Menu.scss +74 -74
  129. package/src/widgets/nav/Route.js +102 -106
  130. package/src/widgets/overlay/Dropdown.js +612 -612
  131. package/src/widgets/overlay/FlyweightTooltipTracker.js +39 -39
  132. package/src/widgets/overlay/Overlay.d.ts +73 -73
  133. package/src/widgets/overlay/Tooltip.js +1 -1
  134. package/src/widgets/overlay/Window.js +202 -202
  135. package/src/widgets/overlay/captureMouse.js +124 -124
  136. package/src/widgets/overlay/createHotPromiseWindowFactory.d.ts +18 -18
  137. package/src/widgets/overlay/createHotPromiseWindowFactory.js +56 -56
  138. package/src/widgets/overlay/index.d.ts +11 -11
  139. package/src/widgets/overlay/index.js +11 -11
  140. package/src/widgets/variables.scss +144 -144
@@ -1,290 +1,290 @@
1
- import { Widget, VDOM, getContent } from "../../ui/Widget";
2
- import { Field, getFieldTooltip } from "./Field";
3
- import {
4
- tooltipParentWillReceiveProps,
5
- tooltipParentWillUnmount,
6
- tooltipMouseMove,
7
- tooltipMouseLeave,
8
- tooltipParentDidMount,
9
- } from "../overlay/tooltip-ops";
10
- import { stopPropagation, preventDefault } from "../../util/eventCallbacks";
11
- import { StringTemplate } from "../../data/StringTemplate";
12
- import { Icon } from "../Icon";
13
- import { KeyCode } from "../../util/KeyCode";
14
- import { Localization } from "../../ui/Localization";
15
- import ClearIcon from "../icons/clear";
16
- import { autoFocus } from "../autoFocus";
17
- import { isString } from "../../util/isString";
18
- import { getActiveElement } from "../../util/getActiveElement";
19
-
20
- export class TextField extends Field {
21
- init() {
22
- if (typeof this.hideClear !== "undefined") this.showClear = !this.hideClear;
23
-
24
- if (this.alwaysShowClear) this.showClear = true;
25
-
26
- super.init();
27
- }
28
-
29
- declareData() {
30
- super.declareData(
31
- {
32
- value: this.emptyValue,
33
- disabled: undefined,
34
- readOnly: undefined,
35
- enabled: undefined,
36
- placeholder: undefined,
37
- required: undefined,
38
- minLength: undefined,
39
- maxLength: undefined,
40
- icon: undefined,
41
- trim: undefined,
42
- },
43
- ...arguments,
44
- );
45
- }
46
-
47
- renderInput(context, instance, key) {
48
- return (
49
- <Input
50
- key={key}
51
- instance={instance}
52
- data={instance.data}
53
- label={this.labelPlacement && getContent(this.renderLabel(context, instance, "label"))}
54
- help={this.helpPlacement && getContent(this.renderHelp(context, instance, "help"))}
55
- icon={this.renderIcon(context, instance, "icon")}
56
- />
57
- );
58
- }
59
-
60
- validate(context, instance) {
61
- super.validate(context, instance);
62
-
63
- let { data } = instance;
64
-
65
- if (!data.error && data.value) {
66
- if (this.validationRegExp) this.validationRegExp.lastIndex = 0;
67
- if (this.validationRegExp && !this.validationRegExp.test(data.value)) data.error = this.validationErrorText;
68
- else if (typeof data.value === "string" && data.minLength != null && data.value.length < data.minLength)
69
- data.error = StringTemplate.format(this.minLengthValidationErrorText, data.minLength, data.value.length);
70
- else if (typeof data.value === "string" && data.maxLength != null && data.value.length > data.maxLength)
71
- data.error = StringTemplate.format(this.maxLengthValidationErrorText, data.maxLength, data.value.length);
72
- }
73
- }
74
- }
75
-
76
- TextField.prototype.baseClass = "textfield";
77
- TextField.prototype.reactOn = "change input blur enter";
78
- TextField.prototype.inputType = "text";
79
- TextField.prototype.validationErrorText = "The entered value is not valid.";
80
- TextField.prototype.minLengthValidationErrorText = "Enter {[{0}-{1}]} more character(s).";
81
- TextField.prototype.maxLengthValidationErrorText = "Use {0} characters or fewer.";
82
- TextField.prototype.suppressErrorsUntilVisited = true;
83
- TextField.prototype.icon = null;
84
- TextField.prototype.showClear = false;
85
- TextField.prototype.alwaysShowClear = false;
86
- TextField.prototype.keyboardShortcut = false;
87
- TextField.prototype.trim = false;
88
-
89
- Localization.registerPrototype("cx/widgets/TextField", TextField);
90
-
91
- class Input extends VDOM.Component {
92
- constructor(props) {
93
- super(props);
94
- this.state = {
95
- focus: false,
96
- };
97
- }
98
-
99
- render() {
100
- let { instance, data, label, help, icon: iconVDOM } = this.props;
101
- let { widget, state } = instance;
102
- let { CSS, baseClass, suppressErrorsUntilVisited } = widget;
103
-
104
- let icon = iconVDOM && (
105
- <div
106
- className={CSS.element(baseClass, "left-icon")}
107
- onMouseDown={preventDefault}
108
- onClick={(e) => this.onChange(e.target.value, "enter")}
109
- >
110
- {iconVDOM}
111
- </div>
112
- );
113
-
114
- let insideButton;
115
- if (
116
- widget.showClear &&
117
- !data.empty &&
118
- !data.readOnly &&
119
- !data.disabled &&
120
- (widget.alwaysShowClear || !data.required)
121
- ) {
122
- insideButton = (
123
- <div
124
- className={CSS.element(baseClass, "clear")}
125
- onMouseDown={(e) => e.preventDefault()}
126
- onClick={(e) => this.onClearClick(e)}
127
- >
128
- <ClearIcon className={CSS.element(baseClass, "icon")} />
129
- </div>
130
- );
131
- }
132
-
133
- let empty = this.input ? !this.trimmed(this.input.value) : data.empty;
134
-
135
- return (
136
- <div
137
- className={CSS.expand(
138
- data.classNames,
139
- CSS.state({
140
- visited: state.visited,
141
- focus: this.state.focus,
142
- icon: !!icon,
143
- clear: insideButton != null,
144
- empty: empty && !data.placeholder,
145
- error: data.error && (state.visited || !suppressErrorsUntilVisited || !empty),
146
- }),
147
- )}
148
- style={data.style}
149
- onMouseDown={stopPropagation}
150
- onTouchStart={stopPropagation}
151
- >
152
- <input
153
- ref={(el) => {
154
- this.input = el;
155
- }}
156
- className={CSS.expand(CSS.element(baseClass, "input"), data.inputClass)}
157
- defaultValue={data.value}
158
- id={data.id}
159
- style={data.inputStyle}
160
- type={widget.inputType}
161
- disabled={data.disabled}
162
- readOnly={data.readOnly}
163
- tabIndex={data.tabIndex}
164
- placeholder={data.placeholder}
165
- {...data.inputAttrs}
166
- onMouseMove={this.onMouseMove.bind(this)}
167
- onMouseLeave={this.onMouseLeave.bind(this)}
168
- onInput={(e) => this.onChange(e.target.value, "input")}
169
- onChange={(e) => this.onChange(e.target.value, "change")}
170
- onKeyDown={this.onKeyDown.bind(this)}
171
- onFocus={this.onFocus.bind(this)}
172
- onBlur={this.onBlur.bind(this)}
173
- onClick={stopPropagation}
174
- />
175
- {insideButton}
176
- {icon}
177
- {label}
178
- {help}
179
- </div>
180
- );
181
- }
182
-
183
- onFocus() {
184
- let { instance, data } = this.props;
185
- let { widget } = instance;
186
- if (widget.trackFocus) {
187
- this.setState({
188
- focus: true,
189
- });
190
- instance.set("focused", true);
191
- }
192
- if (data.error && data.value) instance.setState({ visited: true });
193
- }
194
-
195
- onBlur(e) {
196
- if (this.state.focus) {
197
- this.setState({
198
- focus: false,
199
- });
200
- this.props.instance.set("focused", false);
201
- }
202
- this.onChange(e.target.value, "blur");
203
- }
204
-
205
- onClearClick(e) {
206
- this.input.value = ""; // prevent onChange call with old text value on blur or component unmount
207
- this.props.instance.set("value", this.props.instance.widget.emptyValue, { immediate: true });
208
- }
209
-
210
- onMouseMove(e) {
211
- tooltipMouseMove(e, ...getFieldTooltip(this.props.instance));
212
- }
213
-
214
- onMouseLeave(e) {
215
- tooltipMouseLeave(e, ...getFieldTooltip(this.props.instance));
216
- }
217
-
218
- componentDidMount() {
219
- tooltipParentDidMount(this.input, ...getFieldTooltip(this.props.instance));
220
- autoFocus(this.input, this);
221
- }
222
-
223
- componentDidUpdate() {
224
- autoFocus(this.input, this);
225
- }
226
-
227
- componentWillUnmount() {
228
- if (this.input == getActiveElement() && this.input.value != this.props.data.value)
229
- this.onChange(this.input.value, "blur");
230
- tooltipParentWillUnmount(this.props.instance);
231
- }
232
-
233
- onKeyDown(e) {
234
- let { instance } = this.props;
235
- if (instance.widget.handleKeyDown(e, instance) === false) return;
236
-
237
- switch (e.keyCode) {
238
- case KeyCode.enter:
239
- this.onChange(e.target.value, "enter");
240
- break;
241
-
242
- case KeyCode.left:
243
- case KeyCode.right:
244
- e.stopPropagation();
245
- break;
246
- }
247
- }
248
-
249
- UNSAFE_componentWillReceiveProps(props) {
250
- let { data } = props;
251
- // The second check is required for debouncing, sometimes the value in the store lags after the input
252
- // and update may be caused by some other property, i.e. visited
253
- if (data.value != this.input.value && data.value != this.props.data.value) this.input.value = data.value || "";
254
- tooltipParentWillReceiveProps(this.input, ...getFieldTooltip(props.instance));
255
- }
256
-
257
- onChange(textValue, change) {
258
- let { instance, data } = this.props;
259
-
260
- let immediate = change == "blur" || change == "enter";
261
-
262
- if (immediate) {
263
- instance.setState({ visited: true });
264
- }
265
-
266
- let { widget } = instance;
267
-
268
- if (widget.reactOn.indexOf(change) != -1) {
269
- let text = this.trimmed(textValue);
270
- if (data.maxLength != null && text.length > data.maxLength) {
271
- text = text.substring(0, data.maxLength);
272
- this.input.value = text;
273
- }
274
-
275
- let value = text || widget.emptyValue;
276
- if (!instance.set("value", value, { immediate })) {
277
- if (text != this.input.value && immediate) this.input.value = text;
278
- } else {
279
- if (value) instance.setState({ visited: true });
280
- }
281
- }
282
- }
283
-
284
- trimmed(value) {
285
- if (this.props.data.trim && isString(value)) return value.trim();
286
- return value;
287
- }
288
- }
289
-
290
- Widget.alias("textfield", TextField);
1
+ import { Widget, VDOM, getContent } from "../../ui/Widget";
2
+ import { Field, getFieldTooltip } from "./Field";
3
+ import {
4
+ tooltipParentWillReceiveProps,
5
+ tooltipParentWillUnmount,
6
+ tooltipMouseMove,
7
+ tooltipMouseLeave,
8
+ tooltipParentDidMount,
9
+ } from "../overlay/tooltip-ops";
10
+ import { stopPropagation, preventDefault } from "../../util/eventCallbacks";
11
+ import { StringTemplate } from "../../data/StringTemplate";
12
+ import { Icon } from "../Icon";
13
+ import { KeyCode } from "../../util/KeyCode";
14
+ import { Localization } from "../../ui/Localization";
15
+ import ClearIcon from "../icons/clear";
16
+ import { autoFocus } from "../autoFocus";
17
+ import { isString } from "../../util/isString";
18
+ import { getActiveElement } from "../../util/getActiveElement";
19
+
20
+ export class TextField extends Field {
21
+ init() {
22
+ if (typeof this.hideClear !== "undefined") this.showClear = !this.hideClear;
23
+
24
+ if (this.alwaysShowClear) this.showClear = true;
25
+
26
+ super.init();
27
+ }
28
+
29
+ declareData() {
30
+ super.declareData(
31
+ {
32
+ value: this.emptyValue,
33
+ disabled: undefined,
34
+ readOnly: undefined,
35
+ enabled: undefined,
36
+ placeholder: undefined,
37
+ required: undefined,
38
+ minLength: undefined,
39
+ maxLength: undefined,
40
+ icon: undefined,
41
+ trim: undefined,
42
+ },
43
+ ...arguments,
44
+ );
45
+ }
46
+
47
+ renderInput(context, instance, key) {
48
+ return (
49
+ <Input
50
+ key={key}
51
+ instance={instance}
52
+ data={instance.data}
53
+ label={this.labelPlacement && getContent(this.renderLabel(context, instance, "label"))}
54
+ help={this.helpPlacement && getContent(this.renderHelp(context, instance, "help"))}
55
+ icon={this.renderIcon(context, instance, "icon")}
56
+ />
57
+ );
58
+ }
59
+
60
+ validate(context, instance) {
61
+ super.validate(context, instance);
62
+
63
+ let { data } = instance;
64
+
65
+ if (!data.error && data.value) {
66
+ if (this.validationRegExp) this.validationRegExp.lastIndex = 0;
67
+ if (this.validationRegExp && !this.validationRegExp.test(data.value)) data.error = this.validationErrorText;
68
+ else if (typeof data.value === "string" && data.minLength != null && data.value.length < data.minLength)
69
+ data.error = StringTemplate.format(this.minLengthValidationErrorText, data.minLength, data.value.length);
70
+ else if (typeof data.value === "string" && data.maxLength != null && data.value.length > data.maxLength)
71
+ data.error = StringTemplate.format(this.maxLengthValidationErrorText, data.maxLength, data.value.length);
72
+ }
73
+ }
74
+ }
75
+
76
+ TextField.prototype.baseClass = "textfield";
77
+ TextField.prototype.reactOn = "change input blur enter";
78
+ TextField.prototype.inputType = "text";
79
+ TextField.prototype.validationErrorText = "The entered value is not valid.";
80
+ TextField.prototype.minLengthValidationErrorText = "Enter {[{0}-{1}]} more character(s).";
81
+ TextField.prototype.maxLengthValidationErrorText = "Use {0} characters or fewer.";
82
+ TextField.prototype.suppressErrorsUntilVisited = true;
83
+ TextField.prototype.icon = null;
84
+ TextField.prototype.showClear = false;
85
+ TextField.prototype.alwaysShowClear = false;
86
+ TextField.prototype.keyboardShortcut = false;
87
+ TextField.prototype.trim = false;
88
+
89
+ Localization.registerPrototype("cx/widgets/TextField", TextField);
90
+
91
+ class Input extends VDOM.Component {
92
+ constructor(props) {
93
+ super(props);
94
+ this.state = {
95
+ focus: false,
96
+ };
97
+ }
98
+
99
+ render() {
100
+ let { instance, data, label, help, icon: iconVDOM } = this.props;
101
+ let { widget, state } = instance;
102
+ let { CSS, baseClass, suppressErrorsUntilVisited } = widget;
103
+
104
+ let icon = iconVDOM && (
105
+ <div
106
+ className={CSS.element(baseClass, "left-icon")}
107
+ onMouseDown={preventDefault}
108
+ onClick={(e) => this.onChange(e.target.value, "enter")}
109
+ >
110
+ {iconVDOM}
111
+ </div>
112
+ );
113
+
114
+ let insideButton;
115
+ if (
116
+ widget.showClear &&
117
+ !data.empty &&
118
+ !data.readOnly &&
119
+ !data.disabled &&
120
+ (widget.alwaysShowClear || !data.required)
121
+ ) {
122
+ insideButton = (
123
+ <div
124
+ className={CSS.element(baseClass, "clear")}
125
+ onMouseDown={(e) => e.preventDefault()}
126
+ onClick={(e) => this.onClearClick(e)}
127
+ >
128
+ <ClearIcon className={CSS.element(baseClass, "icon")} />
129
+ </div>
130
+ );
131
+ }
132
+
133
+ let empty = this.input ? !this.trimmed(this.input.value) : data.empty;
134
+
135
+ return (
136
+ <div
137
+ className={CSS.expand(
138
+ data.classNames,
139
+ CSS.state({
140
+ visited: state.visited,
141
+ focus: this.state.focus,
142
+ icon: !!icon,
143
+ clear: insideButton != null,
144
+ empty: empty && !data.placeholder,
145
+ error: data.error && (state.visited || !suppressErrorsUntilVisited || !empty),
146
+ }),
147
+ )}
148
+ style={data.style}
149
+ onMouseDown={stopPropagation}
150
+ onTouchStart={stopPropagation}
151
+ >
152
+ <input
153
+ ref={(el) => {
154
+ this.input = el;
155
+ }}
156
+ className={CSS.expand(CSS.element(baseClass, "input"), data.inputClass)}
157
+ defaultValue={data.value}
158
+ id={data.id}
159
+ style={data.inputStyle}
160
+ type={widget.inputType}
161
+ disabled={data.disabled}
162
+ readOnly={data.readOnly}
163
+ tabIndex={data.tabIndex}
164
+ placeholder={data.placeholder}
165
+ {...data.inputAttrs}
166
+ onMouseMove={this.onMouseMove.bind(this)}
167
+ onMouseLeave={this.onMouseLeave.bind(this)}
168
+ onInput={(e) => this.onChange(e.target.value, "input")}
169
+ onChange={(e) => this.onChange(e.target.value, "change")}
170
+ onKeyDown={this.onKeyDown.bind(this)}
171
+ onFocus={this.onFocus.bind(this)}
172
+ onBlur={this.onBlur.bind(this)}
173
+ onClick={stopPropagation}
174
+ />
175
+ {insideButton}
176
+ {icon}
177
+ {label}
178
+ {help}
179
+ </div>
180
+ );
181
+ }
182
+
183
+ onFocus() {
184
+ let { instance, data } = this.props;
185
+ let { widget } = instance;
186
+ if (widget.trackFocus) {
187
+ this.setState({
188
+ focus: true,
189
+ });
190
+ instance.set("focused", true);
191
+ }
192
+ if (data.error && data.value) instance.setState({ visited: true });
193
+ }
194
+
195
+ onBlur(e) {
196
+ if (this.state.focus) {
197
+ this.setState({
198
+ focus: false,
199
+ });
200
+ this.props.instance.set("focused", false);
201
+ }
202
+ this.onChange(e.target.value, "blur");
203
+ }
204
+
205
+ onClearClick(e) {
206
+ this.input.value = ""; // prevent onChange call with old text value on blur or component unmount
207
+ this.props.instance.set("value", this.props.instance.widget.emptyValue, { immediate: true });
208
+ }
209
+
210
+ onMouseMove(e) {
211
+ tooltipMouseMove(e, ...getFieldTooltip(this.props.instance));
212
+ }
213
+
214
+ onMouseLeave(e) {
215
+ tooltipMouseLeave(e, ...getFieldTooltip(this.props.instance));
216
+ }
217
+
218
+ componentDidMount() {
219
+ tooltipParentDidMount(this.input, ...getFieldTooltip(this.props.instance));
220
+ autoFocus(this.input, this);
221
+ }
222
+
223
+ componentDidUpdate() {
224
+ autoFocus(this.input, this);
225
+ }
226
+
227
+ componentWillUnmount() {
228
+ if (this.input == getActiveElement() && this.input.value != this.props.data.value)
229
+ this.onChange(this.input.value, "blur");
230
+ tooltipParentWillUnmount(this.props.instance);
231
+ }
232
+
233
+ onKeyDown(e) {
234
+ let { instance } = this.props;
235
+ if (instance.widget.handleKeyDown(e, instance) === false) return;
236
+
237
+ switch (e.keyCode) {
238
+ case KeyCode.enter:
239
+ this.onChange(e.target.value, "enter");
240
+ break;
241
+
242
+ case KeyCode.left:
243
+ case KeyCode.right:
244
+ e.stopPropagation();
245
+ break;
246
+ }
247
+ }
248
+
249
+ UNSAFE_componentWillReceiveProps(props) {
250
+ let { data } = props;
251
+ // The second check is required for debouncing, sometimes the value in the store lags after the input
252
+ // and update may be caused by some other property, i.e. visited
253
+ if (data.value != this.input.value && data.value != this.props.data.value) this.input.value = data.value || "";
254
+ tooltipParentWillReceiveProps(this.input, ...getFieldTooltip(props.instance));
255
+ }
256
+
257
+ onChange(textValue, change) {
258
+ let { instance, data } = this.props;
259
+
260
+ let immediate = change == "blur" || change == "enter";
261
+
262
+ if (immediate) {
263
+ instance.setState({ visited: true });
264
+ }
265
+
266
+ let { widget } = instance;
267
+
268
+ if (widget.reactOn.indexOf(change) != -1) {
269
+ let text = this.trimmed(textValue);
270
+ if (data.maxLength != null && text.length > data.maxLength) {
271
+ text = text.substring(0, data.maxLength);
272
+ this.input.value = text;
273
+ }
274
+
275
+ let value = text || widget.emptyValue;
276
+ if (!instance.set("value", value, { immediate })) {
277
+ if (text != this.input.value && immediate) this.input.value = text;
278
+ } else {
279
+ if (value) instance.setState({ visited: true });
280
+ }
281
+ }
282
+ }
283
+
284
+ trimmed(value) {
285
+ if (this.props.data.trim && isString(value)) return value.trim();
286
+ return value;
287
+ }
288
+ }
289
+
290
+ Widget.alias("textfield", TextField);