cx 24.6.3 → 24.6.4

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.
package/dist/widgets.js CHANGED
@@ -7096,6 +7096,7 @@ var Input$2 = /*#__PURE__*/ (function (_VDOM$Component) {
7096
7096
  this.onChange(e.target.value, "blur");
7097
7097
  };
7098
7098
  _proto2.onClearClick = function onClearClick(e) {
7099
+ this.input.value = ""; // prevent onChange call with old text value on blur or component unmount
7099
7100
  this.props.instance.set("value", this.props.instance.widget.emptyValue, {
7100
7101
  immediate: true,
7101
7102
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cx",
3
- "version": "24.6.3",
3
+ "version": "24.6.4",
4
4
  "description": "Advanced JavaScript UI framework for admin and dashboard applications with ready to use grid, form and chart components.",
5
5
  "main": "index.js",
6
6
  "jsnext:main": "src/index.js",
@@ -1,288 +1,289 @@
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.props.instance.set("value", this.props.instance.widget.emptyValue, { immediate: true });
207
- }
208
-
209
- onMouseMove(e) {
210
- tooltipMouseMove(e, ...getFieldTooltip(this.props.instance));
211
- }
212
-
213
- onMouseLeave(e) {
214
- tooltipMouseLeave(e, ...getFieldTooltip(this.props.instance));
215
- }
216
-
217
- componentDidMount() {
218
- tooltipParentDidMount(this.input, ...getFieldTooltip(this.props.instance));
219
- autoFocus(this.input, this);
220
- }
221
-
222
- componentDidUpdate() {
223
- autoFocus(this.input, this);
224
- }
225
-
226
- componentWillUnmount() {
227
- if (this.input == getActiveElement()) this.onChange(this.input.value, "blur");
228
- tooltipParentWillUnmount(this.props.instance);
229
- }
230
-
231
- onKeyDown(e) {
232
- let { instance } = this.props;
233
- if (instance.widget.handleKeyDown(e, instance) === false) return;
234
-
235
- switch (e.keyCode) {
236
- case KeyCode.enter:
237
- this.onChange(e.target.value, "enter");
238
- break;
239
-
240
- case KeyCode.left:
241
- case KeyCode.right:
242
- e.stopPropagation();
243
- break;
244
- }
245
- }
246
-
247
- UNSAFE_componentWillReceiveProps(props) {
248
- let { data } = props;
249
- // The second check is required for debouncing, sometimes the value in the store lags after the input
250
- // and update may be caused by some other property, i.e. visited
251
- if (data.value != this.input.value && data.value != this.props.data.value) this.input.value = data.value || "";
252
- tooltipParentWillReceiveProps(this.input, ...getFieldTooltip(props.instance));
253
- }
254
-
255
- onChange(textValue, change) {
256
- let { instance, data } = this.props;
257
-
258
- let immediate = change == "blur" || change == "enter";
259
-
260
- if (immediate) {
261
- instance.setState({ visited: true });
262
- }
263
-
264
- let { widget } = instance;
265
-
266
- if (widget.reactOn.indexOf(change) != -1) {
267
- let text = this.trimmed(textValue);
268
- if (data.maxLength != null && text.length > data.maxLength) {
269
- text = text.substring(0, data.maxLength);
270
- this.input.value = text;
271
- }
272
-
273
- let value = text || widget.emptyValue;
274
- if (!instance.set("value", value, { immediate })) {
275
- if (text != this.input.value && immediate) this.input.value = text;
276
- } else {
277
- if (value) instance.setState({ visited: true });
278
- }
279
- }
280
- }
281
-
282
- trimmed(value) {
283
- if (this.props.data.trim && isString(value)) return value.trim();
284
- return value;
285
- }
286
- }
287
-
288
- 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.onChange(this.input.value, "blur");
229
+ tooltipParentWillUnmount(this.props.instance);
230
+ }
231
+
232
+ onKeyDown(e) {
233
+ let { instance } = this.props;
234
+ if (instance.widget.handleKeyDown(e, instance) === false) return;
235
+
236
+ switch (e.keyCode) {
237
+ case KeyCode.enter:
238
+ this.onChange(e.target.value, "enter");
239
+ break;
240
+
241
+ case KeyCode.left:
242
+ case KeyCode.right:
243
+ e.stopPropagation();
244
+ break;
245
+ }
246
+ }
247
+
248
+ UNSAFE_componentWillReceiveProps(props) {
249
+ let { data } = props;
250
+ // The second check is required for debouncing, sometimes the value in the store lags after the input
251
+ // and update may be caused by some other property, i.e. visited
252
+ if (data.value != this.input.value && data.value != this.props.data.value) this.input.value = data.value || "";
253
+ tooltipParentWillReceiveProps(this.input, ...getFieldTooltip(props.instance));
254
+ }
255
+
256
+ onChange(textValue, change) {
257
+ let { instance, data } = this.props;
258
+
259
+ let immediate = change == "blur" || change == "enter";
260
+
261
+ if (immediate) {
262
+ instance.setState({ visited: true });
263
+ }
264
+
265
+ let { widget } = instance;
266
+
267
+ if (widget.reactOn.indexOf(change) != -1) {
268
+ let text = this.trimmed(textValue);
269
+ if (data.maxLength != null && text.length > data.maxLength) {
270
+ text = text.substring(0, data.maxLength);
271
+ this.input.value = text;
272
+ }
273
+
274
+ let value = text || widget.emptyValue;
275
+ if (!instance.set("value", value, { immediate })) {
276
+ if (text != this.input.value && immediate) this.input.value = text;
277
+ } else {
278
+ if (value) instance.setState({ visited: true });
279
+ }
280
+ }
281
+ }
282
+
283
+ trimmed(value) {
284
+ if (this.props.data.trim && isString(value)) return value.trim();
285
+ return value;
286
+ }
287
+ }
288
+
289
+ Widget.alias("textfield", TextField);