cx 26.1.8 → 26.1.9
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/build/ui/app/History.js +1 -1
- package/build/util/Component.js +8 -8
- package/build/widgets/HtmlElement.d.ts +1 -1
- package/build/widgets/HtmlElement.js +6 -5
- package/build/widgets/form/TextField.d.ts +4 -3
- package/build/widgets/form/TextField.js +33 -19
- package/build/widgets/grid/Grid.d.ts +3 -1
- package/build/widgets/overlay/FlyweightTooltipTracker.js +10 -6
- package/dist/manifest.js +883 -883
- package/dist/ui.js +1 -1
- package/dist/util.js +8 -7
- package/dist/widgets.css +7 -2
- package/dist/widgets.js +8 -7
- package/package.json +1 -1
- package/src/ui/app/History.ts +19 -5
- package/src/ui/createFunctionalComponent.spec.tsx +86 -0
- package/src/util/Component.ts +81 -35
- package/src/widgets/HtmlElement.tsx +374 -319
- package/src/widgets/ProgressBar.scss +16 -12
- package/src/widgets/form/TextField.tsx +399 -341
- package/src/widgets/grid/Grid.tsx +4 -1
- package/src/widgets/overlay/FlyweightTooltipTracker.ts +33 -10
- package/src/widgets/variables.scss +1 -0
package/build/ui/app/History.js
CHANGED
|
@@ -90,7 +90,7 @@ export class History {
|
|
|
90
90
|
return changed;
|
|
91
91
|
}
|
|
92
92
|
static updateStore(href) {
|
|
93
|
-
let url = Url.unresolve(href
|
|
93
|
+
let url = Url.unresolve(href ?? document?.location.href ?? "");
|
|
94
94
|
let hash = null;
|
|
95
95
|
let hashIndex = url.indexOf("#");
|
|
96
96
|
if (hashIndex !== -1) {
|
package/build/util/Component.js
CHANGED
|
@@ -53,8 +53,10 @@ export class Component {
|
|
|
53
53
|
return typeAlias.map((c) => this.create(c, config, more));
|
|
54
54
|
if (typeAlias.$type)
|
|
55
55
|
return this.create(typeAlias.$type, typeAlias, config);
|
|
56
|
-
if (typeAlias.type)
|
|
57
|
-
|
|
56
|
+
if (typeAlias.type) {
|
|
57
|
+
let { type, ...rest } = typeAlias;
|
|
58
|
+
return this.create(type, rest, config);
|
|
59
|
+
}
|
|
58
60
|
let cmpType, alias;
|
|
59
61
|
if (typeAlias.isComponentType)
|
|
60
62
|
cmpType = typeAlias;
|
|
@@ -73,12 +75,10 @@ export class Component {
|
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
else if (typeof typeAlias == "object") {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
config = typeAlias;
|
|
81
|
-
}
|
|
78
|
+
// typeAlias.type and typeAlias.$type are handled above, so this is a plain config object
|
|
79
|
+
cmpType = this;
|
|
80
|
+
more = more ? Object.assign({}, config, more) : config;
|
|
81
|
+
config = typeAlias;
|
|
82
82
|
}
|
|
83
83
|
if (isArray(config))
|
|
84
84
|
return config.map((cfg) => this.create(cmpType, cfg, more));
|
|
@@ -10,7 +10,7 @@ import type { TooltipConfig, TooltipProp } from "./overlay/tooltip-ops";
|
|
|
10
10
|
import { TooltipParentInstance } from "./overlay/tooltip-ops";
|
|
11
11
|
export declare let urlAttributes: Record<string, boolean>;
|
|
12
12
|
type ReactIntrinsicElements = ReactJSX.IntrinsicElements;
|
|
13
|
-
type IsEventHandler<K, T> = K extends `on${string}` ?
|
|
13
|
+
type IsEventHandler<K, T> = K extends `on${string}` ? NonNullable<T> extends Function ? true : false : false;
|
|
14
14
|
type CxEventHandler<T> = T extends (event: infer E) => any ? string | ((event: E, instance: Instance) => void) : T extends undefined ? undefined : string | T;
|
|
15
15
|
type TransformHtmlElementProps<T> = {
|
|
16
16
|
[K in keyof T]: K extends "children" ? ChildNode | ChildNode[] : K extends "className" | "class" ? ClassProp : IsEventHandler<K, T[K]> extends true ? CxEventHandler<T[K]> : string extends T[K] ? Prop<T[K]> : NonNullable<T[K]> extends string ? Prop<T[K]> | string : Prop<T[K]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Url } from "../ui/app/Url";
|
|
3
|
-
import { StyledContainerBase } from "../ui/Container";
|
|
3
|
+
import { StyledContainerBase, } from "../ui/Container";
|
|
4
4
|
import { Instance } from "../ui/Instance";
|
|
5
5
|
import { VDOM, Widget } from "../ui/Widget";
|
|
6
6
|
import { debug } from "../util/Debug";
|
|
@@ -10,7 +10,7 @@ import { isString } from "../util/isString";
|
|
|
10
10
|
import { isUndefined } from "../util/isUndefined";
|
|
11
11
|
import { autoFocus } from "./autoFocus";
|
|
12
12
|
import { tooltipMouseLeave, tooltipMouseMove, tooltipParentDidMount, tooltipParentDidUpdate, tooltipParentWillReceiveProps, tooltipParentWillUnmount, } from "./overlay/tooltip-ops";
|
|
13
|
-
const isDataAttribute = (attr) =>
|
|
13
|
+
const isDataAttribute = (attr) => attr.indexOf("data-") === 0 ? attr.substring(5) : false;
|
|
14
14
|
export let urlAttributes = {
|
|
15
15
|
"a.href": true,
|
|
16
16
|
"img.src": true,
|
|
@@ -48,7 +48,8 @@ export class HtmlElement extends StyledContainerBase {
|
|
|
48
48
|
this.data = {};
|
|
49
49
|
this.data[name] = this[attr];
|
|
50
50
|
}
|
|
51
|
-
else if ((name = this.isValidHtmlAttribute(attr)) &&
|
|
51
|
+
else if ((name = this.isValidHtmlAttribute(attr)) &&
|
|
52
|
+
!data.hasOwnProperty(name)) {
|
|
52
53
|
if (name.indexOf("on") === 0) {
|
|
53
54
|
if (this[attr]) {
|
|
54
55
|
if (!this.events)
|
|
@@ -72,7 +73,6 @@ export class HtmlElement extends StyledContainerBase {
|
|
|
72
73
|
isValidHtmlAttribute(attrName) {
|
|
73
74
|
switch (attrName) {
|
|
74
75
|
case "tag":
|
|
75
|
-
case "type":
|
|
76
76
|
case "$type":
|
|
77
77
|
case "$props":
|
|
78
78
|
case "text":
|
|
@@ -133,7 +133,8 @@ export class HtmlElement extends StyledContainerBase {
|
|
|
133
133
|
this.urlAttributes.forEach((attr) => {
|
|
134
134
|
const attrValue = data.attrs[attr];
|
|
135
135
|
if (isString(attrValue)) {
|
|
136
|
-
data.attrs[attr] =
|
|
136
|
+
data.attrs[attr] =
|
|
137
|
+
Url.resolve(attrValue);
|
|
137
138
|
}
|
|
138
139
|
});
|
|
139
140
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
|
-
import { Field, FieldConfig } from "./Field";
|
|
3
|
-
import { BooleanProp, NumberProp, Prop, StringProp } from "../../ui/Prop";
|
|
4
2
|
import { Instance } from "../../ui/Instance";
|
|
3
|
+
import { BooleanProp, NumberProp, Prop, StringProp } from "../../ui/Prop";
|
|
4
|
+
import { Field, FieldConfig } from "./Field";
|
|
5
5
|
export interface TextFieldConfig extends FieldConfig {
|
|
6
6
|
/** Textual value of the input field. */
|
|
7
7
|
value?: Prop<any>;
|
|
@@ -44,7 +44,7 @@ export interface TextFieldConfig extends FieldConfig {
|
|
|
44
44
|
/** Set to `true` to display the clear button even if `required` is set. Default is `false`. */
|
|
45
45
|
alwaysShowClear?: BooleanProp;
|
|
46
46
|
/** Name or configuration of the icon to be put on the left side of the input. */
|
|
47
|
-
icon?:
|
|
47
|
+
icon?: string | FieldIconConfig;
|
|
48
48
|
/** Additional attributes to be passed to the input element. */
|
|
49
49
|
inputAttrs?: Prop<any>;
|
|
50
50
|
/** If `trackFocus` is set, this value will be set when the field receives or loses focus. */
|
|
@@ -64,6 +64,7 @@ export interface TextFieldConfig extends FieldConfig {
|
|
|
64
64
|
}
|
|
65
65
|
export interface TextFieldProps extends TextFieldConfig {
|
|
66
66
|
}
|
|
67
|
+
import { FieldIconConfig } from "./FieldIcon";
|
|
67
68
|
export declare class TextField<Config extends TextFieldConfig = TextFieldConfig> extends Field<Config> {
|
|
68
69
|
hideClear?: boolean;
|
|
69
70
|
showClear?: boolean;
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/** @jsxImportSource react */
|
|
3
2
|
import { Widget, getContent } from "../../ui/Widget";
|
|
4
3
|
import { Field, getFieldTooltip } from "./Field";
|
|
5
|
-
import { tooltipParentWillReceiveProps, tooltipParentWillUnmount, tooltipMouseMove, tooltipMouseLeave, tooltipParentDidMount, } from "../overlay/tooltip-ops";
|
|
6
|
-
import { stopPropagation, preventDefault } from "../../util/eventCallbacks";
|
|
7
4
|
import { StringTemplate } from "../../data/StringTemplate";
|
|
8
|
-
import { KeyCode } from "../../util/KeyCode";
|
|
9
5
|
import { Localization } from "../../ui/Localization";
|
|
10
|
-
import ClearIcon from "../icons/clear";
|
|
11
|
-
import { autoFocus } from "../autoFocus";
|
|
12
|
-
import { isString } from "../../util/isString";
|
|
13
|
-
import { getActiveElement } from "../../util/getActiveElement";
|
|
14
6
|
import { VDOM } from "../../ui/VDOM";
|
|
7
|
+
import { preventDefault, stopPropagation } from "../../util/eventCallbacks";
|
|
8
|
+
import { getActiveElement } from "../../util/getActiveElement";
|
|
9
|
+
import { isString } from "../../util/isString";
|
|
10
|
+
import { KeyCode } from "../../util/KeyCode";
|
|
11
|
+
import { autoFocus } from "../autoFocus";
|
|
12
|
+
import ClearIcon from "../icons/clear";
|
|
13
|
+
import { tooltipMouseLeave, tooltipMouseMove, tooltipParentDidMount, tooltipParentWillReceiveProps, tooltipParentWillUnmount, } from "../overlay/tooltip-ops";
|
|
15
14
|
export class TextField extends Field {
|
|
16
15
|
init() {
|
|
17
16
|
if (typeof this.hideClear !== "undefined")
|
|
@@ -30,12 +29,14 @@ export class TextField extends Field {
|
|
|
30
29
|
required: undefined,
|
|
31
30
|
minLength: undefined,
|
|
32
31
|
maxLength: undefined,
|
|
33
|
-
icon: undefined,
|
|
34
32
|
trim: undefined,
|
|
33
|
+
inputType: undefined,
|
|
35
34
|
}, ...args);
|
|
36
35
|
}
|
|
37
36
|
renderInput(context, instance, key) {
|
|
38
|
-
return (_jsx(Input, { instance: instance, data: instance.data, label: this.labelPlacement &&
|
|
37
|
+
return (_jsx(Input, { instance: instance, data: instance.data, label: this.labelPlacement &&
|
|
38
|
+
getContent(this.renderLabel(context, instance, "label")), help: this.helpPlacement &&
|
|
39
|
+
getContent(this.renderHelp(context, instance, "help")), icon: this.renderIcon(context, instance, "icon") }, key));
|
|
39
40
|
}
|
|
40
41
|
validate(context, instance) {
|
|
41
42
|
super.validate(context, instance);
|
|
@@ -45,9 +46,13 @@ export class TextField extends Field {
|
|
|
45
46
|
this.validationRegExp.lastIndex = 0;
|
|
46
47
|
if (this.validationRegExp && !this.validationRegExp.test(data.value))
|
|
47
48
|
data.error = this.validationErrorText;
|
|
48
|
-
else if (typeof data.value === "string" &&
|
|
49
|
+
else if (typeof data.value === "string" &&
|
|
50
|
+
data.minLength != null &&
|
|
51
|
+
data.value.length < data.minLength)
|
|
49
52
|
data.error = StringTemplate.format(this.minLengthValidationErrorText, data.minLength, data.value.length);
|
|
50
|
-
else if (typeof data.value === "string" &&
|
|
53
|
+
else if (typeof data.value === "string" &&
|
|
54
|
+
data.maxLength != null &&
|
|
55
|
+
data.value.length > data.maxLength)
|
|
51
56
|
data.error = StringTemplate.format(this.maxLengthValidationErrorText, data.maxLength, data.value.length);
|
|
52
57
|
}
|
|
53
58
|
}
|
|
@@ -56,8 +61,10 @@ TextField.prototype.baseClass = "textfield";
|
|
|
56
61
|
TextField.prototype.reactOn = "change input blur enter";
|
|
57
62
|
TextField.prototype.inputType = "text";
|
|
58
63
|
TextField.prototype.validationErrorText = "The entered value is not valid.";
|
|
59
|
-
TextField.prototype.minLengthValidationErrorText =
|
|
60
|
-
|
|
64
|
+
TextField.prototype.minLengthValidationErrorText =
|
|
65
|
+
"Enter {[{0}-{1}]} more character(s).";
|
|
66
|
+
TextField.prototype.maxLengthValidationErrorText =
|
|
67
|
+
"Use {0} characters or fewer.";
|
|
61
68
|
TextField.prototype.suppressErrorsUntilVisited = true;
|
|
62
69
|
TextField.prototype.icon = null;
|
|
63
70
|
TextField.prototype.showClear = false;
|
|
@@ -93,10 +100,11 @@ class Input extends VDOM.Component {
|
|
|
93
100
|
icon: !!icon,
|
|
94
101
|
clear: insideButton != null,
|
|
95
102
|
empty: empty && !data.placeholder,
|
|
96
|
-
error: data.error &&
|
|
103
|
+
error: data.error &&
|
|
104
|
+
(state.visited || !suppressErrorsUntilVisited || !empty),
|
|
97
105
|
})), style: data.style, onMouseDown: stopPropagation, onTouchStart: stopPropagation, children: [_jsx("input", { ref: (el) => {
|
|
98
106
|
this.input = el || undefined;
|
|
99
|
-
}, className: CSS.expand(CSS.element(baseClass, "input"), data.inputClass), defaultValue: data.value, id: data.id, style: data.inputStyle, type:
|
|
107
|
+
}, className: CSS.expand(CSS.element(baseClass, "input"), data.inputClass), defaultValue: data.value, id: data.id, style: data.inputStyle, type: data.inputType, disabled: data.disabled, readOnly: data.readOnly, tabIndex: data.tabIndex, placeholder: data.placeholder, ...data.inputAttrs, onMouseMove: this.onMouseMove.bind(this), onMouseLeave: this.onMouseLeave.bind(this), onInput: (e) => this.onChange(e.target.value, "input"), onChange: (e) => this.onChange(e.target.value, "change"), onKeyDown: this.onKeyDown.bind(this), onFocus: this.onFocus.bind(this), onBlur: this.onBlur.bind(this), onClick: stopPropagation }), insideButton, icon, label, help] }));
|
|
100
108
|
}
|
|
101
109
|
onFocus() {
|
|
102
110
|
let { instance, data } = this.props;
|
|
@@ -122,7 +130,9 @@ class Input extends VDOM.Component {
|
|
|
122
130
|
onClearClick(_e) {
|
|
123
131
|
if (this.input)
|
|
124
132
|
this.input.value = ""; // prevent onChange call with old text value on blur or component unmount
|
|
125
|
-
this.props.instance.set("value", this.props.instance.widget.emptyValue, {
|
|
133
|
+
this.props.instance.set("value", this.props.instance.widget.emptyValue, {
|
|
134
|
+
immediate: true,
|
|
135
|
+
});
|
|
126
136
|
}
|
|
127
137
|
onMouseMove(e) {
|
|
128
138
|
const tooltip = getFieldTooltip(this.props.instance);
|
|
@@ -141,7 +151,9 @@ class Input extends VDOM.Component {
|
|
|
141
151
|
autoFocus(this.input, this);
|
|
142
152
|
}
|
|
143
153
|
componentWillUnmount() {
|
|
144
|
-
if (this.input == getActiveElement() &&
|
|
154
|
+
if (this.input == getActiveElement() &&
|
|
155
|
+
this.input &&
|
|
156
|
+
this.input.value != this.props.data.value)
|
|
145
157
|
this.onChange(this.input.value, "blur");
|
|
146
158
|
tooltipParentWillUnmount(this.props.instance);
|
|
147
159
|
}
|
|
@@ -163,7 +175,9 @@ class Input extends VDOM.Component {
|
|
|
163
175
|
let { data } = props;
|
|
164
176
|
// The second check is required for debouncing, sometimes the value in the store lags after the input
|
|
165
177
|
// and update may be caused by some other property, i.e. visited
|
|
166
|
-
if (this.input &&
|
|
178
|
+
if (this.input &&
|
|
179
|
+
data.value != this.input.value &&
|
|
180
|
+
data.value != this.props.data.value)
|
|
167
181
|
this.input.value = data.value || "";
|
|
168
182
|
const tooltip = getFieldTooltip(props.instance);
|
|
169
183
|
tooltipParentWillReceiveProps(this.input, tooltip[0], tooltip[1], tooltip[2]);
|
|
@@ -251,7 +251,9 @@ export interface GridConfig<T = any> extends StyledContainerConfig {
|
|
|
251
251
|
/** Parameters that affect filtering. */
|
|
252
252
|
filterParams?: StructuredProp;
|
|
253
253
|
/** Callback function to be executed when a row is right-clicked. */
|
|
254
|
-
onRowContextMenu?: string | ((e: React.
|
|
254
|
+
onRowContextMenu?: string | ((e: React.MouseEvent<any>, instance: Instance) => void);
|
|
255
|
+
/** Callback function to be executed when a column header is right-clicked. */
|
|
256
|
+
onColumnContextMenu?: string | ((e: React.MouseEvent<any>, columnInstance: Instance) => void);
|
|
255
257
|
/** Callback to create a filter function for given filter params. */
|
|
256
258
|
onCreateFilter?: (filterParams: any, instance?: Instance) => (record: T) => boolean;
|
|
257
259
|
/** Enable infinite scrolling */
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { Instance } from "../../ui/Instance";
|
|
2
2
|
import { Widget } from "../../ui/Widget";
|
|
3
3
|
import { closest } from "../../util";
|
|
4
|
-
import { tooltipMouseLeave, tooltipMouseMove } from "./tooltip-ops";
|
|
4
|
+
import { tooltipMouseLeave, tooltipMouseMove, } from "./tooltip-ops";
|
|
5
5
|
export class FlyweightTooltipTrackerInstance extends Instance {
|
|
6
6
|
}
|
|
7
7
|
export class FlyweightTooltipTracker extends Widget {
|
|
8
8
|
initInstance(context, instance) {
|
|
9
9
|
let handler = (e) => this.handleMouseMove(e, instance);
|
|
10
|
-
document
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
if (typeof document !== "undefined") {
|
|
11
|
+
document.addEventListener("mousemove", handler);
|
|
12
|
+
instance.subscribeOnDestroy(() => {
|
|
13
|
+
document.removeEventListener("mousemove", handler);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
14
16
|
}
|
|
15
17
|
render(context, instance, key) {
|
|
16
18
|
return null;
|
|
@@ -27,7 +29,9 @@ export class FlyweightTooltipTracker extends Widget {
|
|
|
27
29
|
return !!tooltip;
|
|
28
30
|
});
|
|
29
31
|
if (!parentEl)
|
|
30
|
-
tooltipMouseLeave(e, instance, instance.tooltip, {
|
|
32
|
+
tooltipMouseLeave(e, instance, instance.tooltip, {
|
|
33
|
+
target: instance.parentEl,
|
|
34
|
+
});
|
|
31
35
|
else {
|
|
32
36
|
instance.tooltip = tooltip;
|
|
33
37
|
instance.parentEl = parentEl;
|