x4js 2.3.17 → 2.3.19
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/aicli.md +3 -3
- package/aicontext.md +211 -47
- package/cli/config.mjs +14 -7
- package/cli/copy-plugin.mjs +8 -0
- package/cli/create.mjs +8 -2
- package/cli/dev.mjs +4 -1
- package/cli/less-plugin.mjs +5 -1
- package/cli/main.mjs +15 -5
- package/cli/rawfile-plugin.mjs +23 -3
- package/cli/templates.mjs +5 -1
- package/package.json +1 -1
- package/src/components/calendar/calendar.module.scss +16 -1
- package/src/components/calendar/calendar.ts +52 -9
- package/src/components/checkbox/checkbox.ts +1 -0
- package/src/components/combobox/combobox.ts +51 -23
- package/src/components/dialog/dialog.ts +4 -1
- package/src/components/form/form.ts +9 -5
- package/src/components/gridview/gridview.ts +352 -176
- package/src/components/input/input.ts +63 -38
- package/src/components/keyboard/keyboard.module.scss +35 -4
- package/src/components/keyboard/keyboard.ts +295 -80
- package/src/components/listbox/listbox.ts +6 -1
- package/src/components/messages/messages.ts +12 -3
- package/src/components/popup/popup.ts +19 -20
- package/src/components/radio/radio.ts +8 -4
- package/src/components/rating/rating.ts +38 -48
- package/src/components/slider/slider.ts +38 -8
- package/src/components/spreadsheet/spreadsheet.ts +167 -132
- package/src/components/switch/switch.ts +2 -1
- package/src/components/tag/tag.ts +1 -2
- package/src/components/textarea/textarea.module.scss +6 -2
- package/src/components/textarea/textarea.ts +50 -11
- package/src/components/textedit/textedit.ts +12 -2
- package/src/core/component.ts +16 -9
- package/src/core/core_application.ts +8 -4
- package/src/core/core_clipboard.ts +239 -0
- package/src/core/core_data.ts +118 -49
- package/src/core/core_dom.ts +36 -6
- package/src/core/core_dragdrop.ts +11 -5
- package/src/core/core_element.ts +1 -1
- package/src/core/core_pdf.ts +696 -46
- package/src/core/core_router.ts +42 -44
- package/src/core/core_shortcuts.ts +1 -1
- package/src/core/core_state.ts +22 -5
- package/src/x4.d.ts +1 -0
- package/src/x4.ts +1 -0
|
@@ -28,75 +28,226 @@ import icon_hide from "./eye-slash.svg";
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
31
|
+
/**
|
|
32
|
+
* A layout is the place of the 26 letters (its base) and the letters that
|
|
33
|
+
* a language adds to them (its extra), shown on a page of their own,
|
|
34
|
+
* called by a key. The upper case is computed, the digits and the signs
|
|
35
|
+
* are the same for all.
|
|
36
|
+
*
|
|
37
|
+
* base: the countries where it is not QWERTY are those that
|
|
38
|
+
* https://en.wikipedia.org/wiki/QWERTZ and /AZERTY list.
|
|
39
|
+
* extra: the main letters of the language in the CLDR of Unicode
|
|
40
|
+
* (cldr-json, cldr-misc-full/main/<lang>/characters.json), without a..z.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
type KbBase = "azerty" | "qwerty" | "qwertz";
|
|
44
|
+
type KbMode = "alpha" | "accents" | "symbols" | "number" | "date";
|
|
45
|
+
|
|
46
|
+
interface KbLayout {
|
|
47
|
+
base: KbBase;
|
|
48
|
+
extra: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const kb_bases: Record<KbBase,string[]> = {
|
|
52
|
+
azerty: [ "a z e r t y u i o p", "q s d f g h j k l m", "w x c v b n" ],
|
|
53
|
+
qwerty: [ "q w e r t y u i o p", "a s d f g h j k l", "z x c v b n m" ],
|
|
54
|
+
qwertz: [ "q w e r t z u i o p", "a s d f g h j k l", "y x c v b n m" ],
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// by language
|
|
58
|
+
const kb_langs: Record<string,KbLayout> = {
|
|
59
|
+
cs: { base: "qwertz", extra: "á č ď é ě í ň ó ř š ť ú ů ý ž" },
|
|
60
|
+
da: { base: "qwerty", extra: "æ ø å" },
|
|
61
|
+
de: { base: "qwertz", extra: "ä ö ü ß" },
|
|
62
|
+
en: { base: "qwerty", extra: "" },
|
|
63
|
+
es: { base: "qwerty", extra: "á é í ñ ó ú ü" },
|
|
64
|
+
et: { base: "qwerty", extra: "õ ä ö ü š ž" },
|
|
65
|
+
fi: { base: "qwerty", extra: "å ä ö š ž" },
|
|
66
|
+
fr: { base: "azerty", extra: "é è ê ë à â æ ç î ï ô œ ù û ü ÿ" },
|
|
67
|
+
ga: { base: "qwerty", extra: "á é í ó ú" },
|
|
68
|
+
hr: { base: "qwertz", extra: "č ć đ š ž" },
|
|
69
|
+
hu: { base: "qwertz", extra: "á é í ó ö ő ú ü ű" },
|
|
70
|
+
it: { base: "qwerty", extra: "à è é ì ò ù" },
|
|
71
|
+
lt: { base: "qwerty", extra: "ą č ę ė į š ų ū ž" },
|
|
72
|
+
lv: { base: "qwerty", extra: "ā č ē ģ ī ķ ļ ņ š ū ž" },
|
|
73
|
+
mt: { base: "qwerty", extra: "à ċ è ġ ħ ì ò ù ż" },
|
|
74
|
+
nl: { base: "qwerty", extra: "á ä é ë í ï ó ö ú ü" },
|
|
75
|
+
pl: { base: "qwerty", extra: "ą ć ę ł ń ó ś ź ż" },
|
|
76
|
+
pt: { base: "qwerty", extra: "á à â ã ç é ê í ó ò ô õ ú" },
|
|
77
|
+
ro: { base: "qwerty", extra: "ă â î ș ț" },
|
|
78
|
+
sk: { base: "qwertz", extra: "á ä č ď é í ĺ ľ ň ó ô ŕ š ť ú ý ž" },
|
|
79
|
+
sl: { base: "qwertz", extra: "č š ž" },
|
|
80
|
+
sv: { base: "qwerty", extra: "å ä ö é à" },
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// the countries that do not have the keyboard of their language
|
|
84
|
+
const kb_countries: Record<string,Partial<KbLayout>> = {
|
|
85
|
+
"de-CH": { extra: "ä ö ü" }, // no ß in Switzerland
|
|
86
|
+
"fr-CH": { base: "qwertz" },
|
|
87
|
+
"it-CH": { base: "qwertz" },
|
|
88
|
+
"fr-LU": { base: "qwertz" }, // the Swiss French keyboard
|
|
89
|
+
"nl-BE": { base: "azerty" },
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const kb_digits = "1 2 3 4 5 6 7 8 9 0";
|
|
93
|
+
const kb_signs = "! @ # $ % ^ & * ( ) _ +";
|
|
94
|
+
|
|
95
|
+
// the page of the signs, that the letters do not have
|
|
96
|
+
const kb_symbols = [
|
|
97
|
+
"- / : ; ( ) € & @ \"",
|
|
98
|
+
"\\ | ~ _ ` § £ $ ^ %",
|
|
99
|
+
"[ ] { } < > = + * #",
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const kb_pads = {
|
|
103
|
+
number: [
|
|
104
|
+
"1 2 3 {2}",
|
|
105
|
+
"4 5 6 {8}",
|
|
106
|
+
"7 8 9 {9}",
|
|
107
|
+
"0 . {3} {9}"
|
|
108
|
+
],
|
|
109
|
+
date: [
|
|
110
|
+
"1 2 3 {2}",
|
|
111
|
+
"4 5 6 {8}",
|
|
112
|
+
"7 8 9 {9}",
|
|
113
|
+
"0 / {3} {9}"
|
|
114
|
+
]
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const KB_MAX_EXTRA = 12; // keys on a row of extra letters, as many as there are signs
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* "de-CH", "de_ch", "de": the layout of the country, or else the one of
|
|
121
|
+
* its language. A language that is not known gets a QWERTY.
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
function findLayout( locale: string ): KbLayout {
|
|
125
|
+
const [lang, country] = locale.replace( "_", "-" ).split( "-" );
|
|
126
|
+
|
|
127
|
+
let layout = kb_langs[lang.toLowerCase( )];
|
|
128
|
+
if( !layout ) {
|
|
129
|
+
layout = kb_langs.en;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if( country ) {
|
|
133
|
+
const own = kb_countries[lang.toLowerCase( ) + "-" + country.toUpperCase( )];
|
|
134
|
+
if( own ) {
|
|
135
|
+
layout = { ...layout, ...own };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return layout;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function upperKeys( line: string ): string {
|
|
143
|
+
return line.split( " " ).map( key => {
|
|
144
|
+
const up = key.toUpperCase( );
|
|
145
|
+
return up.length===1 ? up : key; // ß has no upper case of one letter
|
|
146
|
+
} ).join( " " );
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* the extra letters, on rows of the same length
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
function extraLines( extra: string ): string[] {
|
|
154
|
+
if( !extra ) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const keys = extra.split( " " );
|
|
159
|
+
const count = Math.ceil( keys.length / KB_MAX_EXTRA );
|
|
160
|
+
const size = Math.ceil( keys.length / count );
|
|
161
|
+
|
|
162
|
+
const lines: string[] = [];
|
|
163
|
+
for( let i=0; i<keys.length; i+=size ) {
|
|
164
|
+
lines.push( keys.slice( i, i+size ).join( " " ) );
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return lines;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function letterLines( layout: KbLayout, upper: boolean ): string[] {
|
|
171
|
+
let [l1, l2, l3] = kb_bases[layout.base];
|
|
172
|
+
|
|
173
|
+
if( upper ) {
|
|
174
|
+
l1 = upperKeys( l1 );
|
|
175
|
+
l2 = upperKeys( l2 );
|
|
176
|
+
l3 = upperKeys( l3 );
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return [
|
|
180
|
+
upper ? kb_signs : kb_digits,
|
|
181
|
+
l1 + " {2}",
|
|
182
|
+
l2 + " {3}",
|
|
183
|
+
"{4} " + l3 + ( upper ? " ? : {4}" : " , . {4}" ),
|
|
184
|
+
bottomLine( layout, "alpha" ),
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* the page called by {10}: the extra letters
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
function accentLines( layout: KbLayout, upper: boolean ): string[] {
|
|
193
|
+
let extra = extraLines( layout.extra );
|
|
194
|
+
if( upper ) {
|
|
195
|
+
extra = extra.map( upperKeys );
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return [
|
|
199
|
+
...extra,
|
|
200
|
+
"{4} {2} {3}",
|
|
201
|
+
bottomLine( layout, "accents" ),
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* the page called by {11}: the signs
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
function symbolLines( layout: KbLayout ): string[] {
|
|
210
|
+
const [s1, s2, s3] = kb_symbols;
|
|
211
|
+
|
|
212
|
+
return [
|
|
213
|
+
s1 + " {2}",
|
|
214
|
+
s2 + " {3}",
|
|
215
|
+
s3,
|
|
216
|
+
bottomLine( layout, "symbols" ),
|
|
217
|
+
];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* the last row of the pages of letters: the key of the page that is shown
|
|
222
|
+
* is replaced by {8} at its place, to come back to the letters.
|
|
223
|
+
* no key of the extra letters when the language has none
|
|
224
|
+
*/
|
|
225
|
+
|
|
226
|
+
function bottomLine( layout: KbLayout, page: "alpha" | "accents" | "symbols" ): string {
|
|
227
|
+
const accents = !layout.extra ? "" : page=="accents" ? "{8} " : "{10} ";
|
|
228
|
+
const symbols = page=="symbols" ? "{8} " : "{11} ";
|
|
229
|
+
|
|
230
|
+
return "{5} " + accents + symbols + "{6} ' {7}";
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* the text of the key that calls the extra letters: the first two of them
|
|
235
|
+
*/
|
|
236
|
+
|
|
237
|
+
function accentLabel( layout: KbLayout, upper: boolean ): string {
|
|
238
|
+
const label = layout.extra.split( " " ).slice( 0, 2 ).join( " " );
|
|
239
|
+
return ( upper ? upperKeys( label ) : label ).replace( " ", "" );
|
|
93
240
|
}
|
|
94
241
|
|
|
95
242
|
|
|
96
243
|
const RE_sel = /text|password|search|tel|url/i;
|
|
97
244
|
|
|
98
245
|
interface KeyboardProps extends BoxProps {
|
|
99
|
-
|
|
246
|
+
/**
|
|
247
|
+
* the language of the keys, with or without its country: "fr-FR",
|
|
248
|
+
* "de-CH", "pl"... "fr-FR" when it is not given
|
|
249
|
+
*/
|
|
250
|
+
locale?: string;
|
|
100
251
|
}
|
|
101
252
|
|
|
102
253
|
/**
|
|
@@ -104,13 +255,17 @@ interface KeyboardProps extends BoxProps {
|
|
|
104
255
|
* ```
|
|
105
256
|
* --keyboard-key-background
|
|
106
257
|
* --keyboard-hilite-color
|
|
258
|
+
* --keyboard-key-color
|
|
259
|
+
* --keyboard-accents-color
|
|
260
|
+
* --keyboard-symbols-color
|
|
107
261
|
* --keyboard-zoom
|
|
108
262
|
* ```
|
|
109
263
|
*/
|
|
110
264
|
@class_ns( "x4" )
|
|
111
265
|
export class Keyboard extends HBox<KeyboardProps>
|
|
112
266
|
{
|
|
113
|
-
mode:
|
|
267
|
+
mode: KbMode;
|
|
268
|
+
upper: boolean;
|
|
114
269
|
locale: string;
|
|
115
270
|
keyboard: Box;
|
|
116
271
|
visible: boolean;
|
|
@@ -119,8 +274,9 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
119
274
|
constructor( props: KeyboardProps ) {
|
|
120
275
|
super( { ...props, id: 'v-keyboard' } );
|
|
121
276
|
|
|
122
|
-
this.mode = '
|
|
123
|
-
this.
|
|
277
|
+
this.mode = 'alpha';
|
|
278
|
+
this.upper = false;
|
|
279
|
+
this.locale = props.locale ?? 'fr-FR';
|
|
124
280
|
this.visible = false;
|
|
125
281
|
|
|
126
282
|
document.addEventListener( 'focusin', (e) => this.handleFocus(e.target as Element,true), false );
|
|
@@ -152,6 +308,29 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
152
308
|
this.setStyleVariable( '--keyboard-zoom', perc+'%' );
|
|
153
309
|
}
|
|
154
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Change the language of the keys.
|
|
313
|
+
* @param locale - "fr-FR", "de-CH", "pl"... A country that has no keyboard
|
|
314
|
+
* of its own gets the one of its language, a language that is not known a QWERTY.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* keyboard.setLocale( "de-CH" );
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
setLocale( locale: string ) {
|
|
321
|
+
this.locale = locale;
|
|
322
|
+
|
|
323
|
+
// a language without extra letters has no page for them
|
|
324
|
+
if( this.mode=="accents" && !findLayout( locale ).extra ) {
|
|
325
|
+
this.mode = "alpha";
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// drawn at least once
|
|
329
|
+
if( this.keyboard ) {
|
|
330
|
+
this._redraw( );
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
155
334
|
/**
|
|
156
335
|
*
|
|
157
336
|
*/
|
|
@@ -192,15 +371,9 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
192
371
|
|
|
193
372
|
// shift
|
|
194
373
|
case 4: {
|
|
195
|
-
|
|
196
|
-
this.mode = 'upper';
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
this.mode = 'lower';
|
|
200
|
-
}
|
|
201
|
-
|
|
374
|
+
this.upper = !this.upper;
|
|
202
375
|
this._redraw( );
|
|
203
|
-
break;
|
|
376
|
+
break;
|
|
204
377
|
}
|
|
205
378
|
|
|
206
379
|
// num + sym
|
|
@@ -222,7 +395,19 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
222
395
|
}
|
|
223
396
|
|
|
224
397
|
case 8: {
|
|
225
|
-
this._switchMode( "
|
|
398
|
+
this._switchMode( "alpha" );
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// extra letters
|
|
403
|
+
case 10: {
|
|
404
|
+
this._switchMode( "accents" );
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// signs
|
|
409
|
+
case 11: {
|
|
410
|
+
this._switchMode( "symbols" );
|
|
226
411
|
break;
|
|
227
412
|
}
|
|
228
413
|
|
|
@@ -245,7 +430,7 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
245
430
|
*
|
|
246
431
|
*/
|
|
247
432
|
|
|
248
|
-
private _switchMode( m:
|
|
433
|
+
private _switchMode( m: KbMode ) {
|
|
249
434
|
this.mode = m;
|
|
250
435
|
this._redraw( );
|
|
251
436
|
}
|
|
@@ -312,7 +497,8 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
312
497
|
this._switchMode( "date");
|
|
313
498
|
}
|
|
314
499
|
else {
|
|
315
|
-
this.
|
|
500
|
+
this.upper = false;
|
|
501
|
+
this._switchMode( "alpha" );
|
|
316
502
|
}
|
|
317
503
|
}
|
|
318
504
|
}
|
|
@@ -436,7 +622,22 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
436
622
|
*/
|
|
437
623
|
|
|
438
624
|
private _createContent( ) {
|
|
439
|
-
let lines
|
|
625
|
+
let lines: string[];
|
|
626
|
+
const layout = findLayout( this.locale );
|
|
627
|
+
|
|
628
|
+
if( this.mode=="number" || this.mode=="date" ) {
|
|
629
|
+
lines = kb_pads[this.mode];
|
|
630
|
+
}
|
|
631
|
+
else if( this.mode=="accents" ) {
|
|
632
|
+
lines = accentLines( layout, this.upper );
|
|
633
|
+
}
|
|
634
|
+
else if( this.mode=="symbols" ) {
|
|
635
|
+
lines = symbolLines( layout );
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
lines = letterLines( layout, this.upper );
|
|
639
|
+
}
|
|
640
|
+
|
|
440
641
|
let result: Box[] = [];
|
|
441
642
|
|
|
442
643
|
for( let j=0; j<lines.length; j++ ) {
|
|
@@ -527,8 +728,22 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
527
728
|
|
|
528
729
|
case 9:
|
|
529
730
|
{
|
|
530
|
-
content = '';
|
|
531
|
-
cls += ' cplace';
|
|
731
|
+
content = '';
|
|
732
|
+
cls += ' cplace';
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
case 10:
|
|
737
|
+
{
|
|
738
|
+
content = accentLabel( layout, this.upper );
|
|
739
|
+
cls += ' caccents';
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
case 11:
|
|
744
|
+
{
|
|
745
|
+
content = '#+=';
|
|
746
|
+
cls += ' csymbols';
|
|
532
747
|
break;
|
|
533
748
|
}
|
|
534
749
|
}
|
|
@@ -181,7 +181,8 @@ private _view: Viewport;
|
|
|
181
181
|
|
|
182
182
|
navigate( sens: kbNav ) {
|
|
183
183
|
|
|
184
|
-
|
|
184
|
+
// an item of id 0 is one
|
|
185
|
+
if( this._lastsel===undefined ) {
|
|
185
186
|
if( sens==kbNav.next ) sens = kbNav.first;
|
|
186
187
|
else sens = kbNav.last;
|
|
187
188
|
}
|
|
@@ -395,6 +396,7 @@ private _view: Viewport;
|
|
|
395
396
|
if( itm ) {
|
|
396
397
|
this._multisel.add( id );
|
|
397
398
|
itm.addClass( "selected" );
|
|
399
|
+
this._lastsel = id; // the arrows go on from it
|
|
398
400
|
}
|
|
399
401
|
});
|
|
400
402
|
|
|
@@ -434,6 +436,9 @@ private _view: Viewport;
|
|
|
434
436
|
}
|
|
435
437
|
|
|
436
438
|
clearSelection( fireEvent = true ) {
|
|
439
|
+
// nothing selected: the arrows start from the first item
|
|
440
|
+
this._lastsel = undefined;
|
|
441
|
+
|
|
437
442
|
if( this._multisel.size ) {
|
|
438
443
|
this._clearSelection( );
|
|
439
444
|
if( fireEvent ) {
|
|
@@ -106,10 +106,13 @@ export class MessageBox extends Dialog<DialogProps>
|
|
|
106
106
|
box.on( "btnclick", ( ev ) => {
|
|
107
107
|
asap( ( ) => {
|
|
108
108
|
resolve( ev.button );
|
|
109
|
-
box.close()
|
|
109
|
+
box.close()
|
|
110
110
|
});
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
+
// closed without a button (Escape, the close box): nothing was chosen
|
|
114
|
+
box.on( "closed", ( ) => resolve( null ) );
|
|
115
|
+
|
|
113
116
|
box.show();
|
|
114
117
|
} );
|
|
115
118
|
|
|
@@ -175,10 +178,13 @@ export class InputBox extends Dialog<DialogProps>
|
|
|
175
178
|
box.on( "btnclick", ( ev ) => {
|
|
176
179
|
asap( ( ) => {
|
|
177
180
|
resolve( ev.button=="ok" ? box.getValue( ) : null );
|
|
178
|
-
box.close()
|
|
181
|
+
box.close()
|
|
179
182
|
});
|
|
180
183
|
});
|
|
181
184
|
|
|
185
|
+
// closed without a button (Escape, the close box): nothing was chosen
|
|
186
|
+
box.on( "closed", ( ) => resolve( null ) );
|
|
187
|
+
|
|
182
188
|
box.show();
|
|
183
189
|
} );
|
|
184
190
|
|
|
@@ -233,10 +239,13 @@ export class PromptBox extends Dialog<DialogProps>
|
|
|
233
239
|
box.on( "btnclick", ( ev ) => {
|
|
234
240
|
asap( ( ) => {
|
|
235
241
|
resolve( ev.button );
|
|
236
|
-
box.close()
|
|
242
|
+
box.close()
|
|
237
243
|
});
|
|
238
244
|
});
|
|
239
245
|
|
|
246
|
+
// closed without a button (Escape, the close box): nothing was chosen
|
|
247
|
+
box.on( "closed", ( ) => resolve( null ) );
|
|
248
|
+
|
|
240
249
|
box.show();
|
|
241
250
|
} );
|
|
242
251
|
}
|
|
@@ -46,6 +46,22 @@ function getRoot( ) {
|
|
|
46
46
|
return document.body;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* on the document while the event goes down (capture): a press outside
|
|
51
|
+
* every popup closes the group opened last, the others at the next presses.
|
|
52
|
+
* The event is left as it is, what is pressed handles it as usual.
|
|
53
|
+
* One function for all the popups: it is removed by the one that empties the list.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
function dismissLast( e: UIEvent ) {
|
|
57
|
+
if( autoclose_list.some( x => x.dom.contains( e.target as Node ) ) ) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// the newest popup: dismiss( ) closes its whole group (a menu and its sub-menus)
|
|
62
|
+
autoclose_list[autoclose_list.length-1].dismiss( );
|
|
63
|
+
}
|
|
64
|
+
|
|
49
65
|
/**
|
|
50
66
|
* @cssvar
|
|
51
67
|
* ```
|
|
@@ -233,7 +249,7 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
233
249
|
if( idx>=0 ) {
|
|
234
250
|
autoclose_list.splice( idx, 1 );
|
|
235
251
|
if( autoclose_list.length==0 ) {
|
|
236
|
-
document.removeEventListener( "pointerdown",
|
|
252
|
+
document.removeEventListener( "pointerdown", dismissLast, true );
|
|
237
253
|
}
|
|
238
254
|
}
|
|
239
255
|
}
|
|
@@ -263,7 +279,7 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
263
279
|
|
|
264
280
|
if( this.props.autoClose ) {
|
|
265
281
|
if( autoclose_list.length==0 ) {
|
|
266
|
-
document.addEventListener( "pointerdown",
|
|
282
|
+
document.addEventListener( "pointerdown", dismissLast, true );
|
|
267
283
|
}
|
|
268
284
|
|
|
269
285
|
autoclose_list.push( this );
|
|
@@ -320,23 +336,6 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
320
336
|
this._do_hide( );
|
|
321
337
|
}
|
|
322
338
|
|
|
323
|
-
/**
|
|
324
|
-
* binded
|
|
325
|
-
*
|
|
326
|
-
* listened on the document while the event goes down (capture): a press
|
|
327
|
-
* closes the popups even when what is pressed stops its propagation.
|
|
328
|
-
* the event is left as it is, what is pressed handles it as usual.
|
|
329
|
-
*/
|
|
330
|
-
|
|
331
|
-
private _dismiss = ( e: UIEvent ) => {
|
|
332
|
-
const onac = autoclose_list.some( x=> x.dom.contains(e.target as Node) )
|
|
333
|
-
if( onac ) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
this.dismiss( );
|
|
338
|
-
}
|
|
339
|
-
|
|
340
339
|
/**
|
|
341
340
|
* dismiss all popup belonging to the same group as 'this'
|
|
342
341
|
*/
|
|
@@ -369,7 +368,7 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
369
368
|
const list = inc_group.reverse( );
|
|
370
369
|
autoclose_list = excl_group;
|
|
371
370
|
if( autoclose_list.length==0 ) {
|
|
372
|
-
document.removeEventListener( "pointerdown",
|
|
371
|
+
document.removeEventListener( "pointerdown", dismissLast, true );
|
|
373
372
|
}
|
|
374
373
|
|
|
375
374
|
list.forEach( x => x.close() );
|
|
@@ -19,7 +19,7 @@ import { class_ns } from '../../core/core_tools';
|
|
|
19
19
|
import { EventCallback } from '../../core/core_events';
|
|
20
20
|
|
|
21
21
|
import { Label } from '../label/label';
|
|
22
|
-
import { Input } from '../input/input'
|
|
22
|
+
import { Input, getRadioOwner } from '../input/input'
|
|
23
23
|
import { HBox } from '../boxes/boxes';
|
|
24
24
|
|
|
25
25
|
import icons from "../assets/icons"
|
|
@@ -152,10 +152,14 @@ export class Radio extends Component<RadioProps,RadioEvents> {
|
|
|
152
152
|
*/
|
|
153
153
|
|
|
154
154
|
checkValue( vname: string ) {
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
// the radios of the group: in the form that holds this one, else in
|
|
156
|
+
// its dialog, else in the document (as a Form reads them)
|
|
157
|
+
const owner = getRadioOwner( this.dom );
|
|
158
|
+
const selector = `input[name="${this.props.name}"][value="${vname}"]`;
|
|
159
|
+
|
|
160
|
+
const el = owner.querySelector( selector ) as HTMLInputElement;
|
|
157
161
|
if( el ) {
|
|
158
|
-
el.
|
|
162
|
+
el.checked = true;
|
|
159
163
|
}
|
|
160
164
|
}
|
|
161
165
|
}
|