x4js 2.3.23 → 2.3.24
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/aicontext.md +21 -0
- package/package.json +1 -1
- package/src/components/dialog/dialog.module.scss +2 -2
- package/src/components/dockingview/dockingview.module.scss +0 -3
- package/src/components/keyboard/keyboard.ts +11 -1
- package/src/components/label/label.module.scss +2 -2
- package/src/components/messages/messages.module.scss +7 -6
- package/src/components/messages/messages.ts +63 -11
- package/src/components/settingsview/settingsview.module.scss +0 -3
- package/src/components/themes.scss +54 -0
- package/src/components/tooltips/tooltips.scss +2 -2
- package/src/core/core_application.ts +47 -0
package/aicontext.md
CHANGED
|
@@ -285,6 +285,9 @@ static instance<P extends Application>(): P
|
|
|
285
285
|
setEnv(name: string, value: any): void
|
|
286
286
|
getEnv(name: string, def_value?: any): any
|
|
287
287
|
static fireGlobal(msg: string, params?: any): void
|
|
288
|
+
static setTheme(name: string): void // the class x4theme-<name> on <html>: "" the light theme (default, no class),
|
|
289
|
+
// "dark" the dark theme of x4, another name a theme of the application
|
|
290
|
+
static getTheme(): string // "" for the light theme, "dark", or the name given to setTheme
|
|
288
291
|
focusNext(next: boolean): boolean
|
|
289
292
|
addShortcut(keys: string | string[], callback: (ev: KeyboardEvent) => void, options?: ShortcutOptions): void // see Shortcuts
|
|
290
293
|
setupSocketMessaging(path?: string, looseCallback?: () => void): void
|
|
@@ -1510,6 +1513,24 @@ isLanguage(name: string): boolean
|
|
|
1510
1513
|
|
|
1511
1514
|
---
|
|
1512
1515
|
|
|
1516
|
+
## Theme (`themes.scss`)
|
|
1517
|
+
|
|
1518
|
+
```css
|
|
1519
|
+
--color-primary-a0 … --color-primary-a100 /* the scale: a0 the background, a100 the text, the accent between */
|
|
1520
|
+
/* the globals the components use: --background-primary / -secondary / -ternary / -hover / -active / -input,
|
|
1521
|
+
--text-primary / -secondary / -ternary, --border / -light / -hover / -focus, --accent-background / -hover /
|
|
1522
|
+
-focus / -active / -light, --accent-color (the text on the accent), --disabled-*, --icon-color / -active,
|
|
1523
|
+
--alert-*, --warning-*, --success-* */
|
|
1524
|
+
```
|
|
1525
|
+
// The greys are mixes of a0 and a100: a theme that reverses the scale gets them light on dark.
|
|
1526
|
+
// Each component reads its own variables (the @cssvar of its class), which point to these globals:
|
|
1527
|
+
// a theme redefines the globals, or one variable of a component.
|
|
1528
|
+
// Themes: Application.setTheme(name) puts the class x4theme-<name> on <html>. "" is the light theme (by default),
|
|
1529
|
+
// "dark" the dark theme of x4 (the colours of VS Code Dark Modern). An application adds its own theme in its css,
|
|
1530
|
+
// html.x4theme-pink { --color-primary-a0: ...; ... }, then Application.setTheme("pink").
|
|
1531
|
+
|
|
1532
|
+
---
|
|
1533
|
+
|
|
1513
1534
|
## Utilities (`core_tools`)
|
|
1514
1535
|
|
|
1515
1536
|
```ts
|
package/package.json
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
@use "../shared";
|
|
18
18
|
|
|
19
19
|
:root {
|
|
20
|
-
--color-dialog-caption: var( --
|
|
21
|
-
--color-dialog-caption-text: var( --color
|
|
20
|
+
--color-dialog-caption: var( --accent-background-active );
|
|
21
|
+
--color-dialog-caption-text: var( --accent-color );
|
|
22
22
|
--color-dialog-background: var( --background-primary );
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -221,7 +221,6 @@
|
|
|
221
221
|
width: 16px;
|
|
222
222
|
height: 16px;
|
|
223
223
|
line-height: 16px;
|
|
224
|
-
border-radius: 3px;
|
|
225
224
|
text-align: center;
|
|
226
225
|
font-weight: 400;
|
|
227
226
|
cursor: pointer;
|
|
@@ -269,7 +268,6 @@
|
|
|
269
268
|
|
|
270
269
|
background: var( --dock-float-background );
|
|
271
270
|
border: 1px solid var( --dock-line );
|
|
272
|
-
border-radius: 4px;
|
|
273
271
|
box-shadow: var( --dock-float-shadow );
|
|
274
272
|
}
|
|
275
273
|
|
|
@@ -282,7 +280,6 @@
|
|
|
282
280
|
|
|
283
281
|
background: var( --dock-preview-background );
|
|
284
282
|
border: 1px solid var( --dock-accent );
|
|
285
|
-
border-radius: 3px;
|
|
286
283
|
}
|
|
287
284
|
|
|
288
285
|
// It holds the pointer during a drag: its cursor is the one that shows.
|
|
@@ -284,7 +284,10 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
284
284
|
keyboard: Box;
|
|
285
285
|
visible: boolean;
|
|
286
286
|
input: HTMLInputElement;
|
|
287
|
-
|
|
287
|
+
|
|
288
|
+
// the pointerdown handled last (see handleKeyEvent)
|
|
289
|
+
private handled: UIEvent = null;
|
|
290
|
+
|
|
288
291
|
constructor( props: KeyboardProps ) {
|
|
289
292
|
super( { ...props, id: 'v-keyboard' } );
|
|
290
293
|
|
|
@@ -355,6 +358,13 @@ export class Keyboard extends HBox<KeyboardProps>
|
|
|
355
358
|
*/
|
|
356
359
|
|
|
357
360
|
private handleKeyEvent( e: UIEvent ) {
|
|
361
|
+
// the key backspace listens to pointerdown too (its autorepeat): this handler is
|
|
362
|
+
// called for its node and for the keyboard, the same event twice; one key only
|
|
363
|
+
if( e===this.handled ) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
this.handled = e;
|
|
367
|
+
|
|
358
368
|
let target = e.target as HTMLElement;
|
|
359
369
|
let key;
|
|
360
370
|
|
|
@@ -126,21 +126,22 @@
|
|
|
126
126
|
line-height: 1.8em;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
// on the right, the bar and the lines end where the button OK does: the bar of
|
|
130
|
+
// buttons has a padding of 20px and the button a margin of 2px, the form 16px
|
|
129
131
|
.x4progress {
|
|
130
|
-
margin: 0 16px;
|
|
132
|
+
margin: 0 6px 0 16px;
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
// the lines: a textarea read only, 10 lines high at least, a line is not wrapped
|
|
133
136
|
#sub-text {
|
|
134
137
|
flex-grow: 1;
|
|
138
|
+
min-height: calc( 10lh + 10px ); // its padding and its border too
|
|
135
139
|
max-height: 400px;
|
|
136
140
|
overflow: auto;
|
|
141
|
+
white-space: pre;
|
|
137
142
|
background-color: var( --msgbox-log-background );
|
|
138
143
|
padding: 4px 8px;
|
|
139
|
-
margin: 0 16px;
|
|
140
|
-
|
|
141
|
-
.x4simpletext {
|
|
142
|
-
white-space: nowrap;
|
|
143
|
-
}
|
|
144
|
+
margin: 0 6px 0 16px;
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
}
|
|
@@ -11,6 +11,8 @@ import { Dialog, DialogProps } from "../dialog/dialog"
|
|
|
11
11
|
import { Form } from '../form/form';
|
|
12
12
|
import { BtnGroupItem } from '../btngroup/btngroup';
|
|
13
13
|
import { Input } from '../input/input';
|
|
14
|
+
import { SimpleTextArea } from '../textarea/textarea';
|
|
15
|
+
import { Button } from '../button/button';
|
|
14
16
|
import { Component } from '../../core/component';
|
|
15
17
|
import { Progress } from '../components.js';
|
|
16
18
|
|
|
@@ -275,6 +277,13 @@ export class PromptBox extends Dialog<DialogProps>
|
|
|
275
277
|
|
|
276
278
|
// :: PROGRESS ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
277
279
|
|
|
280
|
+
/**
|
|
281
|
+
* a modal box that follows a long task: a title, a bar, and the lines of what is done
|
|
282
|
+
* in a textarea read only (they are text: a markup is shown as it is written).
|
|
283
|
+
* done( ) shows its button OK: after an error it waits for it, else it closes the box
|
|
284
|
+
* after 5s, the seconds left in the button.
|
|
285
|
+
*/
|
|
286
|
+
|
|
278
287
|
@class_ns( "x4" )
|
|
279
288
|
export class ProgressionBox extends Dialog {
|
|
280
289
|
|
|
@@ -294,7 +303,7 @@ export class ProgressionBox extends Dialog {
|
|
|
294
303
|
new VBox( { flex: 1, cls: "right", content: [
|
|
295
304
|
new SimpleText( { id: "title", text: title } ),
|
|
296
305
|
new Progress( { id:"prog", min: 0, max: 100, value: 0 } ),
|
|
297
|
-
new
|
|
306
|
+
new SimpleTextArea( { id: "sub-text", readonly: true, trim: false } ),
|
|
298
307
|
]})
|
|
299
308
|
]
|
|
300
309
|
}),
|
|
@@ -305,37 +314,80 @@ export class ProgressionBox extends Dialog {
|
|
|
305
314
|
|
|
306
315
|
this.query("#btnbar").show( false );
|
|
307
316
|
|
|
308
|
-
|
|
317
|
+
// OK: closed at once, the countdown stopped
|
|
318
|
+
this.on("btnclick", ( ) => {
|
|
319
|
+
this.clearInterval( "close" );
|
|
320
|
+
this.show( false );
|
|
321
|
+
} );
|
|
309
322
|
}
|
|
310
323
|
|
|
324
|
+
/** a line at the end */
|
|
325
|
+
|
|
311
326
|
addText( text: string | UnsafeHtml, perc: number ) {
|
|
312
|
-
this.
|
|
327
|
+
this._addLine( text );
|
|
313
328
|
this.query<Progress>( "#prog").setValue( perc );
|
|
314
329
|
}
|
|
315
330
|
|
|
331
|
+
/** a line at the end: done( ) then waits for the button OK */
|
|
332
|
+
|
|
316
333
|
addError( text: string | UnsafeHtml, perc: number ) {
|
|
317
|
-
this.
|
|
334
|
+
this._addLine( text );
|
|
318
335
|
this.query<Progress>( "#prog").setValue( perc );
|
|
319
336
|
|
|
320
337
|
this.#has_errors = true;
|
|
321
338
|
}
|
|
322
339
|
|
|
340
|
+
/** the text in place of all the lines */
|
|
341
|
+
|
|
323
342
|
setText( text: string | UnsafeHtml, perc: number ) {
|
|
324
|
-
this.query<
|
|
343
|
+
this.query<SimpleTextArea>( "#sub-text" ).setText( text.toString( ) );
|
|
325
344
|
this.query<Progress>( "#prog").setValue( perc );
|
|
326
345
|
}
|
|
327
346
|
|
|
347
|
+
/** as at the start: no line, no error, no button OK */
|
|
348
|
+
|
|
328
349
|
clear( ) {
|
|
329
|
-
this.#has_errors =
|
|
330
|
-
this.
|
|
350
|
+
this.#has_errors = false;
|
|
351
|
+
this.clearInterval( "close" );
|
|
352
|
+
this.query( "#btnbar" ).show( false );
|
|
353
|
+
this.query<SimpleTextArea>( "#sub-text" ).setText( "" );
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// the line after the others, the last one shown
|
|
357
|
+
private _addLine( text: string | UnsafeHtml ) {
|
|
358
|
+
const log = this.query<SimpleTextArea>( "#sub-text" );
|
|
359
|
+
const lines = log.getText( );
|
|
360
|
+
|
|
361
|
+
log.setText( lines ? lines + "\n" + text : text.toString( ) );
|
|
362
|
+
log.scrollToBottom( );
|
|
331
363
|
}
|
|
332
364
|
|
|
365
|
+
/**
|
|
366
|
+
* the task is over: the button OK is shown. After an error it waits for a click;
|
|
367
|
+
* without one it counts the seconds left, "OK (5s)", and closes the box at 0
|
|
368
|
+
*/
|
|
369
|
+
|
|
333
370
|
done( ) {
|
|
371
|
+
const ok = this.query<Button>( "#ok" );
|
|
372
|
+
this.query( "#btnbar" ).show( true );
|
|
373
|
+
|
|
334
374
|
if( this.#has_errors ) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
else {
|
|
338
|
-
this.setTimeout( "close", 5000, ( ) => { this.show(false);} );
|
|
375
|
+
ok.setText( _tr.global.ok );
|
|
376
|
+
return;
|
|
339
377
|
}
|
|
378
|
+
|
|
379
|
+
let left = 5;
|
|
380
|
+
ok.setText( `${_tr.global.ok} (${left}s)` );
|
|
381
|
+
|
|
382
|
+
this.setInterval( "close", 1000, ( ) => {
|
|
383
|
+
left--;
|
|
384
|
+
if( left>0 ) {
|
|
385
|
+
ok.setText( `${_tr.global.ok} (${left}s)` );
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
this.clearInterval( "close" );
|
|
389
|
+
this.show( false );
|
|
390
|
+
}
|
|
391
|
+
} );
|
|
340
392
|
}
|
|
341
393
|
}
|
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
margin: 0;
|
|
37
37
|
padding: 6px 10px;
|
|
38
38
|
border: 1px solid var( --border );
|
|
39
|
-
border-radius: 4px;
|
|
40
39
|
|
|
41
40
|
&:focus {
|
|
42
41
|
border-color: var( --settingsview-marker );
|
|
@@ -100,7 +99,6 @@
|
|
|
100
99
|
max-width: 900px;
|
|
101
100
|
padding: 0 8px 10px;
|
|
102
101
|
border: 1px solid var( --border );
|
|
103
|
-
border-radius: 8px;
|
|
104
102
|
background: var( --settingsview-section-background );
|
|
105
103
|
overflow: hidden;
|
|
106
104
|
scroll-margin-top: 20px; // brought to the top: below the padding of the view
|
|
@@ -144,7 +142,6 @@
|
|
|
144
142
|
gap: 4px;
|
|
145
143
|
padding: 10px 8px 12px;
|
|
146
144
|
border-left: 2px solid transparent;
|
|
147
|
-
border-radius: 4px;
|
|
148
145
|
|
|
149
146
|
&:hover {
|
|
150
147
|
background: var( --settingsview-hover-background );
|
|
@@ -100,4 +100,58 @@ $color--interval: 8.4%;
|
|
|
100
100
|
--success-background: var(--color-success-a50);
|
|
101
101
|
--success-background-active: var(--color-success-a60);
|
|
102
102
|
--success-color: #ffffff;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// :: dark theme :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
106
|
+
// Application.setTheme( "dark" ): the class x4theme-dark on <html>, like the theme Dark
|
|
107
|
+
// Modern of VS Code. Its colours are taken in the sources of VS Code:
|
|
108
|
+
// extensions/theme-defaults/themes/dark_modern.json, and for the lists the defaults of
|
|
109
|
+
// src/vs/platform/theme/common/colors/listColors.ts; the values marked "chosen" are not
|
|
110
|
+
// in VS Code. A theme of an application is written the same way, under html.x4theme-<name>.
|
|
111
|
+
|
|
112
|
+
html.x4theme-dark {
|
|
113
|
+
// the scale: a0 the background, a100 the text, the surfaces between them, then the blues
|
|
114
|
+
--color-primary-a0: #1f1f1f; // editor.background
|
|
115
|
+
--color-primary-a5: #252526; // chosen
|
|
116
|
+
--color-primary-a10: #2a2d2e; // list.hoverBackground
|
|
117
|
+
--color-primary-a20: #37373d; // list.inactiveSelectionBackground
|
|
118
|
+
--color-primary-a30: #3c3c3c; // input.border
|
|
119
|
+
--color-primary-a40: #04395e; // list.activeSelectionBackground
|
|
120
|
+
--color-primary-a50: #0078d4; // button.background, focusBorder
|
|
121
|
+
--color-primary-a55: #026ec1; // button.hoverBackground
|
|
122
|
+
--color-primary-a60: #0078d4;
|
|
123
|
+
--color-primary-a70: #026ec1;
|
|
124
|
+
--color-primary-a80: #04395e;
|
|
125
|
+
--color-primary-a90: #cccccc;
|
|
126
|
+
--color-primary-a100: #cccccc; // foreground
|
|
127
|
+
|
|
128
|
+
// what the scale does not give
|
|
129
|
+
--background-ternary: #181818; // sideBar.background
|
|
130
|
+
--background-hover: #2b2b2b; // button.secondaryHoverBackground
|
|
131
|
+
--background-active: #37373d; // list.inactiveSelectionBackground
|
|
132
|
+
--background-input: #313131; // input.background
|
|
133
|
+
|
|
134
|
+
--text-secondary: #9d9d9d; // descriptionForeground
|
|
135
|
+
--text-ternary: #bbbbbb; // chosen: between the description and the text
|
|
136
|
+
|
|
137
|
+
--border: #3c3c3c; // input.border
|
|
138
|
+
--border-light: #2b2b2b; // panel.border
|
|
139
|
+
--border-hover: #616161; // chosen (badge.background)
|
|
140
|
+
|
|
141
|
+
--disabled-background: #313131; // chosen
|
|
142
|
+
--disabled-color: #6e6e6e; // chosen
|
|
143
|
+
--disabled-color-dark: #6e6e6e; // chosen
|
|
144
|
+
--disabled-color-light: #4f4f4f; // chosen
|
|
145
|
+
|
|
146
|
+
--accent-color: #ffffff; // button.foreground: the text on the accent
|
|
147
|
+
--accent-color-hover: #ffffff;
|
|
148
|
+
--accent-color-focus: #ffffff;
|
|
149
|
+
--accent-color-active: #ffffff;
|
|
150
|
+
|
|
151
|
+
// the title bar of a Dialog: the one of the window of VS Code
|
|
152
|
+
--color-dialog-caption: #181818; // titleBar.activeBackground
|
|
153
|
+
--color-dialog-caption-text: #cccccc; // titleBar.activeForeground
|
|
154
|
+
--color-dialog-background: #202020; // editorWidget.background
|
|
155
|
+
|
|
156
|
+
color-scheme: dark; // the native parts: select, scroll bars, number spinners
|
|
103
157
|
}
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
:root {
|
|
20
20
|
--tooltip-caption-background: var( --color-primary-a70 );
|
|
21
|
-
--tooltip-caption-color: var( --color
|
|
21
|
+
--tooltip-caption-color: var( --accent-color );
|
|
22
22
|
|
|
23
|
-
--tooltip-icon-background: var( --color
|
|
23
|
+
--tooltip-icon-background: var( --accent-color );
|
|
24
24
|
--tooltip-icon-color: var( --color-primary-a70 );
|
|
25
25
|
|
|
26
26
|
--tooltip-background: var( --color-primary-a10 ); //white;
|
|
@@ -42,6 +42,9 @@ export interface ApplicationEvents extends EventMap {
|
|
|
42
42
|
// singleton
|
|
43
43
|
let main_app: Application = null;
|
|
44
44
|
|
|
45
|
+
// the class of a theme on <html>: x4theme-<name> (see Application.setTheme)
|
|
46
|
+
const THEME_PREFIX = "x4theme-";
|
|
47
|
+
|
|
45
48
|
/**
|
|
46
49
|
* Provides information about the user's device and browser capabilities.
|
|
47
50
|
*/
|
|
@@ -201,6 +204,50 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
|
|
|
201
204
|
Application.instance().fire( "global", { msg, params } );
|
|
202
205
|
}
|
|
203
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Selects the theme of the page: the class `x4theme-<name>` on `<html>`, in place
|
|
209
|
+
* of the one of the theme before.
|
|
210
|
+
* - `""`: the light theme of x4, the one by default: no class.
|
|
211
|
+
* - `"dark"`: the dark theme of x4, like the theme Dark Modern of VS Code
|
|
212
|
+
* (`html.x4theme-dark` in themes.scss).
|
|
213
|
+
* - any other name: a theme of the application, defined in its own css under
|
|
214
|
+
* `html.x4theme-<name>`, with the variables of themes.scss it changes.
|
|
215
|
+
* @param name - the name of the theme; "" for the light theme.
|
|
216
|
+
* @example
|
|
217
|
+
* Application.setTheme( "dark" ); // the dark theme of x4
|
|
218
|
+
* Application.setTheme( "pink" ); // html.x4theme-pink { --color-primary-a0: ...; } in the css of the application
|
|
219
|
+
* Application.setTheme( "" ); // back to the light theme
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
static setTheme( name: string ) {
|
|
223
|
+
const classes = document.documentElement.classList;
|
|
224
|
+
|
|
225
|
+
const current = Application.getTheme( );
|
|
226
|
+
if( current ) {
|
|
227
|
+
classes.remove( THEME_PREFIX + current );
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if( name ) {
|
|
231
|
+
classes.add( THEME_PREFIX + name );
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* The name of the theme of the page, as setTheme got it: `""` for the light theme
|
|
237
|
+
* of x4, `"dark"` for its dark theme, or the name of a theme of the application.
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
static getTheme( ): string {
|
|
241
|
+
const classes = document.documentElement.classList;
|
|
242
|
+
for( let i = 0; i < classes.length; i++ ) {
|
|
243
|
+
if( classes[i].startsWith( THEME_PREFIX ) ) {
|
|
244
|
+
return classes[i].replace( THEME_PREFIX, "" );
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return "";
|
|
249
|
+
}
|
|
250
|
+
|
|
204
251
|
/**
|
|
205
252
|
*
|
|
206
253
|
*/
|