x4js 1.4.45 → 1.4.48
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/lib/autocomplete.d.ts +58 -0
- package/lib/autocomplete.js +158 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/listview.d.ts +2 -1
- package/lib/listview.js +7 -3
- package/lib/treeview.js +2 -2
- package/lib/x4.css +3 -3
- package/package.json +1 -1
- package/src/autocomplete.ts +196 -0
- package/src/index.ts +1 -0
- package/src/listview.ts +9 -3
- package/src/treeview.ts +2 -2
- package/src/version.ts +29 -0
- package/src/x4.less +5 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ___ ___ __
|
|
3
|
+
* \ \/ / / _
|
|
4
|
+
* \ / /_| |_
|
|
5
|
+
* / \____ _|
|
|
6
|
+
* /__/\__\ |_|
|
|
7
|
+
*
|
|
8
|
+
* @file autocomplete.ts
|
|
9
|
+
* @author Etienne Cochard
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
12
|
+
*
|
|
13
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
* in the Software without restriction, including without limitation the rights
|
|
16
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
18
|
+
* subject to the following conditions:
|
|
19
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
20
|
+
* or substantial portions of the Software.
|
|
21
|
+
*
|
|
22
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
25
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
26
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
+
**/
|
|
29
|
+
import { TextEdit, TextEditProps } from './textedit';
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
interface AutoCompleteProps extends TextEditProps {
|
|
34
|
+
enumValues: (filter: string) => string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
export declare class AutoComplete extends TextEdit<AutoCompleteProps> {
|
|
40
|
+
private m_popup;
|
|
41
|
+
private m_popvis;
|
|
42
|
+
private m_needval;
|
|
43
|
+
private m_lockpop;
|
|
44
|
+
constructor(props: AutoCompleteProps);
|
|
45
|
+
_onKey(e: KeyboardEvent): void;
|
|
46
|
+
private _onChange;
|
|
47
|
+
componentDisposed(): void;
|
|
48
|
+
/**
|
|
49
|
+
* display the popup
|
|
50
|
+
*/
|
|
51
|
+
showPopup(items: string[]): void;
|
|
52
|
+
protected _validate(value: string): boolean;
|
|
53
|
+
validate(): boolean;
|
|
54
|
+
private _checkFocus;
|
|
55
|
+
private _hidePopup;
|
|
56
|
+
private _onFocus;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ___ ___ __
|
|
4
|
+
* \ \/ / / _
|
|
5
|
+
* \ / /_| |_
|
|
6
|
+
* / \____ _|
|
|
7
|
+
* /__/\__\ |_|
|
|
8
|
+
*
|
|
9
|
+
* @file autocomplete.ts
|
|
10
|
+
* @author Etienne Cochard
|
|
11
|
+
*
|
|
12
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
13
|
+
*
|
|
14
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
* in the Software without restriction, including without limitation the rights
|
|
17
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
18
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
19
|
+
* subject to the following conditions:
|
|
20
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
21
|
+
* or substantial portions of the Software.
|
|
22
|
+
*
|
|
23
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
24
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
25
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
26
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
27
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
28
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
29
|
+
**/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.AutoComplete = void 0;
|
|
32
|
+
const listview_1 = require("./listview");
|
|
33
|
+
const textedit_1 = require("./textedit");
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
*/
|
|
37
|
+
class AutoComplete extends textedit_1.TextEdit {
|
|
38
|
+
m_popup;
|
|
39
|
+
m_popvis;
|
|
40
|
+
m_needval;
|
|
41
|
+
m_lockpop;
|
|
42
|
+
constructor(props) {
|
|
43
|
+
super(props);
|
|
44
|
+
this.setDomEvent("input", () => this._onChange());
|
|
45
|
+
this.setDomEvent("focusin", () => this._onFocus());
|
|
46
|
+
this.startTimer("focus-check", 100, true, () => this._checkFocus());
|
|
47
|
+
this.m_popvis = false;
|
|
48
|
+
this.m_needval = false;
|
|
49
|
+
this.m_lockpop = false;
|
|
50
|
+
this.setDomEvent("keydown", e => this._onKey(e));
|
|
51
|
+
}
|
|
52
|
+
_onKey(e) {
|
|
53
|
+
if (this.m_popvis) {
|
|
54
|
+
if (e.key == "ArrowUp" || e.key == "ArrowDown") {
|
|
55
|
+
this.m_lockpop = true;
|
|
56
|
+
this.m_popup.handleKey(e);
|
|
57
|
+
this.m_lockpop = false;
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
e.stopPropagation();
|
|
60
|
+
}
|
|
61
|
+
else if (e.key == "Escape") {
|
|
62
|
+
this._hidePopup();
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
e.stopPropagation();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (e.key == "ArrowDown") {
|
|
68
|
+
this._onChange();
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
_onChange() {
|
|
74
|
+
const items = this.m_props.enumValues(this.value);
|
|
75
|
+
this.showPopup(items);
|
|
76
|
+
}
|
|
77
|
+
componentDisposed() {
|
|
78
|
+
if (this.m_popup) {
|
|
79
|
+
this._hidePopup();
|
|
80
|
+
}
|
|
81
|
+
super.componentDisposed();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* display the popup
|
|
85
|
+
*/
|
|
86
|
+
showPopup(items) {
|
|
87
|
+
let props = this.m_props;
|
|
88
|
+
if (props.readOnly || this.hasClass("@disable")) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// need creation ?
|
|
92
|
+
if (!this.m_popup) {
|
|
93
|
+
let cstyle = this.getComputedStyle();
|
|
94
|
+
let fontFamily = cstyle.value('fontFamily');
|
|
95
|
+
let fontSize = cstyle.value('fontSize');
|
|
96
|
+
// prepare the combo listview
|
|
97
|
+
this.m_popup = new listview_1.PopupListView({
|
|
98
|
+
cls: '@combo-popup',
|
|
99
|
+
attrs: {
|
|
100
|
+
tabindex: 0
|
|
101
|
+
},
|
|
102
|
+
selectionChange: (e) => {
|
|
103
|
+
this.value = e.selection.id;
|
|
104
|
+
if (!this.m_lockpop) {
|
|
105
|
+
this._hidePopup();
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
style: {
|
|
109
|
+
fontFamily,
|
|
110
|
+
fontSize
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
this.m_popup.items = items.map(c => ({ id: c, text: c }));
|
|
115
|
+
let r1 = this.m_ui_input.getBoundingRect();
|
|
116
|
+
this.m_popup.setStyle({
|
|
117
|
+
minWidth: r1.width,
|
|
118
|
+
});
|
|
119
|
+
this.m_popup.displayAt(r1.left, r1.bottom);
|
|
120
|
+
this.m_popvis = true;
|
|
121
|
+
//if( this.value!==undefined ) {
|
|
122
|
+
// this.m_popup.selection = this.value;
|
|
123
|
+
//}
|
|
124
|
+
}
|
|
125
|
+
_validate(value) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
validate() {
|
|
129
|
+
return super._validate(this.value);
|
|
130
|
+
}
|
|
131
|
+
_checkFocus() {
|
|
132
|
+
const focus = document.activeElement;
|
|
133
|
+
if (this.dom.contains(focus)) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (this.m_popup && this.m_popup.dom && this.m_popup.dom.contains(focus)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this._hidePopup();
|
|
140
|
+
}
|
|
141
|
+
_hidePopup() {
|
|
142
|
+
if (this.m_popvis) {
|
|
143
|
+
this.m_popup.close();
|
|
144
|
+
this.m_popvis = false;
|
|
145
|
+
}
|
|
146
|
+
if (this.m_needval) {
|
|
147
|
+
this.validate();
|
|
148
|
+
this.m_needval = false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
_onFocus() {
|
|
152
|
+
if (this.value.length == 0) {
|
|
153
|
+
this._onChange();
|
|
154
|
+
}
|
|
155
|
+
this.m_needval = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.AutoComplete = AutoComplete;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -43,6 +43,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
__exportStar(require("./application"), exports);
|
|
46
|
+
__exportStar(require("./autocomplete"), exports);
|
|
46
47
|
__exportStar(require("./base_component"), exports);
|
|
47
48
|
//export * from "./base64"
|
|
48
49
|
__exportStar(require("./button"), exports);
|
package/lib/listview.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ export declare class ListView extends VLayout<ListViewProps, ListViewEventMap> {
|
|
|
109
109
|
* @param items - new array of items
|
|
110
110
|
*/
|
|
111
111
|
setItems(items: ListViewItem[], keepSel?: boolean): void;
|
|
112
|
-
|
|
112
|
+
handleKey(ev: KeyboardEvent): void;
|
|
113
113
|
/** @ignore */
|
|
114
114
|
private _buildContent;
|
|
115
115
|
/**
|
|
@@ -167,6 +167,7 @@ export declare class PopupListView extends Popup<PopupListViewProps, PopupListVi
|
|
|
167
167
|
m_list: ListView;
|
|
168
168
|
constructor(props: ListViewProps);
|
|
169
169
|
set items(items: ListViewItem[]);
|
|
170
|
+
handleKey(ev: KeyboardEvent): void;
|
|
170
171
|
private _handleClick;
|
|
171
172
|
show(modal?: boolean): void;
|
|
172
173
|
hide(): void;
|
package/lib/listview.js
CHANGED
|
@@ -50,7 +50,7 @@ class ListView extends layout_1.VLayout {
|
|
|
50
50
|
m_cache; // recycling elements
|
|
51
51
|
constructor(props) {
|
|
52
52
|
super(props);
|
|
53
|
-
this.setDomEvent('keydown', (e) => this.
|
|
53
|
+
this.setDomEvent('keydown', (e) => this.handleKey(e));
|
|
54
54
|
this.setDomEvent('click', (e) => this._handleClick(e));
|
|
55
55
|
this.setDomEvent('dblclick', (e) => this._handleClick(e));
|
|
56
56
|
this.setDomEvent('contextmenu', (e) => this._handleCtxMenu(e));
|
|
@@ -110,7 +110,7 @@ class ListView extends layout_1.VLayout {
|
|
|
110
110
|
this._buildItems();
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
|
|
113
|
+
handleKey(ev) {
|
|
114
114
|
let moveSel = (sens) => {
|
|
115
115
|
let items;
|
|
116
116
|
if ((0, tools_1.isFunction)(this.m_props.items)) {
|
|
@@ -144,11 +144,13 @@ class ListView extends layout_1.VLayout {
|
|
|
144
144
|
switch (ev.key) {
|
|
145
145
|
case 'ArrowDown': {
|
|
146
146
|
moveSel(1);
|
|
147
|
+
ev.preventDefault();
|
|
147
148
|
ev.stopPropagation();
|
|
148
149
|
break;
|
|
149
150
|
}
|
|
150
151
|
case 'ArrowUp': {
|
|
151
152
|
moveSel(-1);
|
|
153
|
+
ev.preventDefault();
|
|
152
154
|
ev.stopPropagation();
|
|
153
155
|
break;
|
|
154
156
|
}
|
|
@@ -491,7 +493,9 @@ class PopupListView extends popup_1.Popup {
|
|
|
491
493
|
set items(items) {
|
|
492
494
|
this.m_list.items = items;
|
|
493
495
|
}
|
|
494
|
-
|
|
496
|
+
handleKey(ev) {
|
|
497
|
+
this.m_list.handleKey(ev);
|
|
498
|
+
}
|
|
495
499
|
// todo: move into popup
|
|
496
500
|
_handleClick = (e) => {
|
|
497
501
|
if (!this.dom) {
|
package/lib/treeview.js
CHANGED
|
@@ -197,10 +197,10 @@ class TreeView extends layout_1.VLayout {
|
|
|
197
197
|
if (icon === undefined) {
|
|
198
198
|
if (node.children) {
|
|
199
199
|
if (node.open === true) {
|
|
200
|
-
icon = 'var(--x4-icon-
|
|
200
|
+
icon = 'var(--x4-icon-chevron-down)';
|
|
201
201
|
}
|
|
202
202
|
else {
|
|
203
|
-
icon = 'var(--x4-icon-
|
|
203
|
+
icon = 'var(--x4-icon-chevron-right)';
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
}
|
package/lib/x4.css
CHANGED
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
--x4-icon-check: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M440.1 103C450.3 112.4 450.3 127.6 440.1 136.1L176.1 400.1C167.6 410.3 152.4 410.3 143 400.1L7.029 264.1C-2.343 255.6-2.343 240.4 7.029 231C16.4 221.7 31.6 221.7 40.97 231L160 350.1L407 103C416.4 93.66 431.6 93.66 440.1 103V103z"/></svg>';
|
|
64
64
|
--x4-icon-folder-closed: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M448 96h-172.1L226.7 50.75C214.7 38.74 198.5 32 181.5 32H64C28.65 32 0 60.66 0 96v320c0 35.34 28.65 64 64 64h384c35.35 0 64-28.66 64-64V160C512 124.7 483.3 96 448 96zM64 80h117.5c4.273 0 8.293 1.664 11.31 4.688L256 144h192c8.822 0 16 7.176 16 16v32h-416V96C48 87.18 55.18 80 64 80zM448 432H64c-8.822 0-16-7.176-16-16V240h416V416C464 424.8 456.8 432 448 432z"/></svg>';
|
|
65
65
|
--x4-icon-folder-opened: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" fill="currentColor"><!--! Font Awesome Pro 6.1.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M572.6 270.3l-96 192C471.2 473.2 460.1 480 447.1 480H64c-35.35 0-64-28.66-64-64V96c0-35.34 28.65-64 64-64h117.5c16.97 0 33.25 6.742 45.26 18.75L275.9 96H416c35.35 0 64 28.66 64 64v32h-48V160c0-8.824-7.178-16-16-16H256L192.8 84.69C189.8 81.66 185.8 80 181.5 80H64C55.18 80 48 87.18 48 96v288l71.16-142.3C124.6 230.8 135.7 224 147.8 224h396.2C567.7 224 583.2 249 572.6 270.3z"/></svg>';
|
|
66
|
-
--x4-icon-chevron-down: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"
|
|
66
|
+
--x4-icon-chevron-down: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M432.6 209.3l-191.1 183.1C235.1 397.8 229.1 400 224 400s-11.97-2.219-16.59-6.688L15.41 209.3C5.814 200.2 5.502 184.1 14.69 175.4c9.125-9.625 24.38-9.938 33.91-.7187L224 342.8l175.4-168c9.5-9.219 24.78-8.906 33.91 .7187C442.5 184.1 442.2 200.2 432.6 209.3z"/></svg>';
|
|
67
67
|
--x4-icon-chevron-right: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor"><path d="M96 480c-8.188 0-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L242.8 256L73.38 86.63c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l192 192c12.5 12.5 12.5 32.75 0 45.25l-192 192C112.4 476.9 104.2 480 96 480z"/></svg>';
|
|
68
|
-
--x4-icon-chevron-left: 'data:image/svg+xml
|
|
69
|
-
--x4-icon-chevron-up: 'data:image/svg+xml
|
|
68
|
+
--x4-icon-chevron-left: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor"><path d="M206.7 464.6l-183.1-191.1C18.22 267.1 16 261.1 16 256s2.219-11.97 6.688-16.59l183.1-191.1c9.152-9.594 24.34-9.906 33.9-.7187c9.625 9.125 9.938 24.37 .7187 33.91L73.24 256l168 175.4c9.219 9.5 8.906 24.78-.7187 33.91C231 474.5 215.8 474.2 206.7 464.6z"/></svg>';
|
|
69
|
+
--x4-icon-chevron-up: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M15.41 302.7l191.1-183.1C212 114.2 218 111.1 224 111.1s11.97 2.219 16.59 6.688l191.1 183.1c9.594 9.152 9.906 24.34 .7187 33.9c-9.125 9.625-24.38 9.938-33.91 .7187L224 169.2l-175.4 168c-9.5 9.219-24.78 8.906-33.91-.7187C5.502 327 5.814 311.8 15.41 302.7z"/></svg>';
|
|
70
70
|
}
|
|
71
71
|
/* source: https://tailwindcss.com/docs/customizing-colors/#default-color-palette */
|
|
72
72
|
:root {
|
package/package.json
CHANGED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ___ ___ __
|
|
3
|
+
* \ \/ / / _
|
|
4
|
+
* \ / /_| |_
|
|
5
|
+
* / \____ _|
|
|
6
|
+
* /__/\__\ |_|
|
|
7
|
+
*
|
|
8
|
+
* @file autocomplete.ts
|
|
9
|
+
* @author Etienne Cochard
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
12
|
+
*
|
|
13
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
* in the Software without restriction, including without limitation the rights
|
|
16
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
18
|
+
* subject to the following conditions:
|
|
19
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
20
|
+
* or substantial portions of the Software.
|
|
21
|
+
*
|
|
22
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
25
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
26
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
+
**/
|
|
29
|
+
|
|
30
|
+
import { ListViewItem, PopupListView } from "./listview";
|
|
31
|
+
import { TextEdit, TextEditProps } from './textedit';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
interface AutoCompleteProps extends TextEditProps {
|
|
38
|
+
enumValues: ( filter: string ) => string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
export class AutoComplete extends TextEdit<AutoCompleteProps> {
|
|
46
|
+
|
|
47
|
+
private m_popup: PopupListView;
|
|
48
|
+
private m_popvis: boolean;
|
|
49
|
+
private m_needval: boolean;
|
|
50
|
+
private m_lockpop: boolean;
|
|
51
|
+
|
|
52
|
+
constructor( props: AutoCompleteProps ) {
|
|
53
|
+
super( props );
|
|
54
|
+
|
|
55
|
+
this.setDomEvent( "input", ( ) => this._onChange( ) );
|
|
56
|
+
this.setDomEvent( "focusin", ( ) => this._onFocus( ) );
|
|
57
|
+
this.startTimer( "focus-check", 100, true, () => this._checkFocus() );
|
|
58
|
+
|
|
59
|
+
this.m_popvis = false;
|
|
60
|
+
this.m_needval = false;
|
|
61
|
+
this.m_lockpop = false;
|
|
62
|
+
|
|
63
|
+
this.setDomEvent( "keydown", e => this._onKey(e) );
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_onKey( e: KeyboardEvent ) {
|
|
67
|
+
if( this.m_popvis ) {
|
|
68
|
+
if( e.key=="ArrowUp" || e.key=="ArrowDown" ) {
|
|
69
|
+
this.m_lockpop = true;
|
|
70
|
+
this.m_popup.handleKey( e );
|
|
71
|
+
this.m_lockpop = false;
|
|
72
|
+
|
|
73
|
+
e.preventDefault( );
|
|
74
|
+
e.stopPropagation( );
|
|
75
|
+
}
|
|
76
|
+
else if( e.key=="Escape" ) {
|
|
77
|
+
this._hidePopup( );
|
|
78
|
+
|
|
79
|
+
e.preventDefault( );
|
|
80
|
+
e.stopPropagation( );
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if( e.key=="ArrowDown" ) {
|
|
84
|
+
this._onChange( );
|
|
85
|
+
e.preventDefault( );
|
|
86
|
+
e.stopPropagation( );
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private _onChange( ) {
|
|
91
|
+
const items = this.m_props.enumValues( this.value );
|
|
92
|
+
this.showPopup( items );
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
componentDisposed( ) {
|
|
96
|
+
if( this.m_popup ) {
|
|
97
|
+
this._hidePopup( );
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
super.componentDisposed( );
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* display the popup
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
showPopup( items: string[] ) {
|
|
108
|
+
|
|
109
|
+
let props = this.m_props;
|
|
110
|
+
if (props.readOnly || this.hasClass("@disable") ) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// need creation ?
|
|
115
|
+
|
|
116
|
+
if( !this.m_popup ) {
|
|
117
|
+
let cstyle = this.getComputedStyle( );
|
|
118
|
+
let fontFamily = cstyle.value( 'fontFamily' );
|
|
119
|
+
let fontSize = cstyle.value( 'fontSize' );
|
|
120
|
+
|
|
121
|
+
// prepare the combo listview
|
|
122
|
+
this.m_popup = new PopupListView({
|
|
123
|
+
cls: '@combo-popup',
|
|
124
|
+
attrs: {
|
|
125
|
+
tabindex: 0
|
|
126
|
+
},
|
|
127
|
+
selectionChange: (e) => {
|
|
128
|
+
this.value = (e.selection as ListViewItem).id
|
|
129
|
+
if( !this.m_lockpop ) {
|
|
130
|
+
this._hidePopup( );
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
style: {
|
|
134
|
+
fontFamily,
|
|
135
|
+
fontSize
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this.m_popup.items = items.map( c => ({ id: c, text: c }) );
|
|
141
|
+
|
|
142
|
+
let r1 = this.m_ui_input.getBoundingRect();
|
|
143
|
+
this.m_popup.setStyle({
|
|
144
|
+
minWidth: r1.width,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
this.m_popup.displayAt(r1.left, r1.bottom);
|
|
148
|
+
this.m_popvis = true;
|
|
149
|
+
|
|
150
|
+
//if( this.value!==undefined ) {
|
|
151
|
+
// this.m_popup.selection = this.value;
|
|
152
|
+
//}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
protected override _validate(value: string): boolean {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
override validate( ): boolean {
|
|
160
|
+
return super._validate( this.value );
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private _checkFocus( ) {
|
|
164
|
+
const focus = document.activeElement;
|
|
165
|
+
if( this.dom.contains(focus) ) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if( this.m_popup && this.m_popup.dom && this.m_popup.dom.contains(focus) ) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
this._hidePopup( );
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private _hidePopup( ) {
|
|
177
|
+
|
|
178
|
+
if( this.m_popvis ) {
|
|
179
|
+
this.m_popup.close();
|
|
180
|
+
this.m_popvis = false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if( this.m_needval ) {
|
|
184
|
+
this.validate( );
|
|
185
|
+
this.m_needval = false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private _onFocus( ) {
|
|
190
|
+
if( this.value.length==0 ) {
|
|
191
|
+
this._onChange( );
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this.m_needval = true;
|
|
195
|
+
}
|
|
196
|
+
}
|
package/src/index.ts
CHANGED
package/src/listview.ts
CHANGED
|
@@ -122,7 +122,7 @@ export class ListView extends VLayout<ListViewProps,ListViewEventMap> {
|
|
|
122
122
|
constructor(props: ListViewProps) {
|
|
123
123
|
super(props);
|
|
124
124
|
|
|
125
|
-
this.setDomEvent('keydown', (e) => this.
|
|
125
|
+
this.setDomEvent('keydown', (e) => this.handleKey(e));
|
|
126
126
|
this.setDomEvent('click', (e) => this._handleClick(e));
|
|
127
127
|
this.setDomEvent('dblclick', (e) => this._handleClick(e));
|
|
128
128
|
this.setDomEvent('contextmenu', (e) => this._handleCtxMenu(e));
|
|
@@ -198,7 +198,7 @@ export class ListView extends VLayout<ListViewProps,ListViewEventMap> {
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
public handleKey(ev: KeyboardEvent) {
|
|
202
202
|
|
|
203
203
|
let moveSel = (sens) => {
|
|
204
204
|
|
|
@@ -237,12 +237,14 @@ export class ListView extends VLayout<ListViewProps,ListViewEventMap> {
|
|
|
237
237
|
switch (ev.key) {
|
|
238
238
|
case 'ArrowDown': {
|
|
239
239
|
moveSel(1);
|
|
240
|
+
ev.preventDefault( );
|
|
240
241
|
ev.stopPropagation();
|
|
241
242
|
break;
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
case 'ArrowUp': {
|
|
245
246
|
moveSel(-1);
|
|
247
|
+
ev.preventDefault( );
|
|
246
248
|
ev.stopPropagation();
|
|
247
249
|
break;
|
|
248
250
|
}
|
|
@@ -705,7 +707,11 @@ export class PopupListView extends Popup<PopupListViewProps,PopupListViewEventMa
|
|
|
705
707
|
this.m_list.items = items;
|
|
706
708
|
}
|
|
707
709
|
|
|
708
|
-
|
|
710
|
+
public handleKey( ev: KeyboardEvent ) {
|
|
711
|
+
this.m_list.handleKey( ev );
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
|
|
709
715
|
// todo: move into popup
|
|
710
716
|
private _handleClick = (e: MouseEvent) => {
|
|
711
717
|
if (!this.dom) {
|
package/src/treeview.ts
CHANGED
|
@@ -292,10 +292,10 @@ export class TreeView extends VLayout<TreeViewProps, TreeViewEventMap> {
|
|
|
292
292
|
if (icon === undefined ) {
|
|
293
293
|
if (node.children) {
|
|
294
294
|
if( node.open===true ) {
|
|
295
|
-
icon = 'var(--x4-icon-
|
|
295
|
+
icon = 'var(--x4-icon-chevron-down)';
|
|
296
296
|
}
|
|
297
297
|
else {
|
|
298
|
-
icon = 'var(--x4-icon-
|
|
298
|
+
icon = 'var(--x4-icon-chevron-right)';
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ___ ___ __
|
|
3
|
+
* \ \_/ / / _
|
|
4
|
+
* \ / /_| |_
|
|
5
|
+
* / _ \____ _|
|
|
6
|
+
* /__/ \__\ |_|
|
|
7
|
+
*
|
|
8
|
+
* @file version.ts
|
|
9
|
+
* @author Etienne Cochard
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) 2019-2022 R-libre ingenierie
|
|
12
|
+
*
|
|
13
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
* in the Software without restriction, including without limitation the rights
|
|
16
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
17
|
+
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
18
|
+
* subject to the following conditions:
|
|
19
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
20
|
+
* or substantial portions of the Software.
|
|
21
|
+
*
|
|
22
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
25
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
26
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
+
**/
|
|
29
|
+
|
|
1
30
|
export const x4js_version = "1.4";
|
package/src/x4.less
CHANGED
|
@@ -78,10 +78,11 @@
|
|
|
78
78
|
--x4-icon-check: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M440.1 103C450.3 112.4 450.3 127.6 440.1 136.1L176.1 400.1C167.6 410.3 152.4 410.3 143 400.1L7.029 264.1C-2.343 255.6-2.343 240.4 7.029 231C16.4 221.7 31.6 221.7 40.97 231L160 350.1L407 103C416.4 93.66 431.6 93.66 440.1 103V103z"/></svg>';
|
|
79
79
|
--x4-icon-folder-closed: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M448 96h-172.1L226.7 50.75C214.7 38.74 198.5 32 181.5 32H64C28.65 32 0 60.66 0 96v320c0 35.34 28.65 64 64 64h384c35.35 0 64-28.66 64-64V160C512 124.7 483.3 96 448 96zM64 80h117.5c4.273 0 8.293 1.664 11.31 4.688L256 144h192c8.822 0 16 7.176 16 16v32h-416V96C48 87.18 55.18 80 64 80zM448 432H64c-8.822 0-16-7.176-16-16V240h416V416C464 424.8 456.8 432 448 432z"/></svg>';
|
|
80
80
|
--x4-icon-folder-opened: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" fill="currentColor"><!--! Font Awesome Pro 6.1.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M572.6 270.3l-96 192C471.2 473.2 460.1 480 447.1 480H64c-35.35 0-64-28.66-64-64V96c0-35.34 28.65-64 64-64h117.5c16.97 0 33.25 6.742 45.26 18.75L275.9 96H416c35.35 0 64 28.66 64 64v32h-48V160c0-8.824-7.178-16-16-16H256L192.8 84.69C189.8 81.66 185.8 80 181.5 80H64C55.18 80 48 87.18 48 96v288l71.16-142.3C124.6 230.8 135.7 224 147.8 224h396.2C567.7 224 583.2 249 572.6 270.3z"/></svg>';
|
|
81
|
-
|
|
82
|
-
--x4-icon-chevron-
|
|
83
|
-
--x4-icon-chevron-
|
|
84
|
-
--x4-icon-chevron-
|
|
81
|
+
|
|
82
|
+
--x4-icon-chevron-down: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M432.6 209.3l-191.1 183.1C235.1 397.8 229.1 400 224 400s-11.97-2.219-16.59-6.688L15.41 209.3C5.814 200.2 5.502 184.1 14.69 175.4c9.125-9.625 24.38-9.938 33.91-.7187L224 342.8l175.4-168c9.5-9.219 24.78-8.906 33.91 .7187C442.5 184.1 442.2 200.2 432.6 209.3z"/></svg>';
|
|
83
|
+
--x4-icon-chevron-right: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor"><path d="M96 480c-8.188 0-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L242.8 256L73.38 86.63c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l192 192c12.5 12.5 12.5 32.75 0 45.25l-192 192C112.4 476.9 104.2 480 96 480z"/></svg>';
|
|
84
|
+
--x4-icon-chevron-left: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor"><path d="M206.7 464.6l-183.1-191.1C18.22 267.1 16 261.1 16 256s2.219-11.97 6.688-16.59l183.1-191.1c9.152-9.594 24.34-9.906 33.9-.7187c9.625 9.125 9.938 24.37 .7187 33.91L73.24 256l168 175.4c9.219 9.5 8.906 24.78-.7187 33.91C231 474.5 215.8 474.2 206.7 464.6z"/></svg>';
|
|
85
|
+
--x4-icon-chevron-up: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M15.41 302.7l191.1-183.1C212 114.2 218 111.1 224 111.1s11.97 2.219 16.59 6.688l191.1 183.1c9.594 9.152 9.906 24.34 .7187 33.9c-9.125 9.625-24.38 9.938-33.91 .7187L224 169.2l-175.4 168c-9.5 9.219-24.78 8.906-33.91-.7187C5.502 327 5.814 311.8 15.41 302.7z"/></svg>';
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
@BLACK10: rgba(0,0,0,0.1);
|