x4js 2.3.22 → 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 +31 -1
- package/package.json +1 -1
- package/src/components/btngroup/btngroup.module.scss +1 -1
- package/src/components/btngroup/btngroup.ts +6 -1
- package/src/components/button/button.module.scss +4 -4
- package/src/components/button/button.ts +20 -0
- package/src/components/calendar/calendar.module.scss +2 -1
- package/src/components/calendar/calendar.ts +2 -1
- package/src/components/chart/chart.module.scss +4 -4
- package/src/components/checkbox/checkbox.module.scss +2 -1
- package/src/components/checkbox/checkbox.ts +1 -0
- package/src/components/colorpicker/colorpicker.module.scss +0 -1
- package/src/components/dialog/dialog.module.scss +4 -4
- package/src/components/dialog/dialog.ts +1 -0
- package/src/components/dockingview/dockingview.module.scss +9 -11
- package/src/components/dockingview/dockingview.ts +1 -0
- package/src/components/form/form.module.scss +2 -2
- package/src/components/form/form.ts +1 -1
- package/src/components/gauge/gauge.module.scss +2 -2
- package/src/components/gridview/gridview.module.scss +0 -1
- package/src/components/input/input.module.scss +2 -2
- package/src/components/input/input.ts +3 -0
- package/src/components/keyboard/keyboard.ts +11 -1
- package/src/components/label/label.module.scss +3 -3
- package/src/components/listbox/listbox.module.scss +6 -3
- package/src/components/listbox/listbox.ts +2 -0
- package/src/components/menu/menu.module.scss +1 -2
- package/src/components/messages/messages.module.scss +18 -17
- package/src/components/messages/messages.ts +70 -12
- package/src/components/messages/pen-field.svg +1 -1
- package/src/components/panel/panel.module.scss +4 -3
- package/src/components/panel/panel.ts +1 -0
- package/src/components/popup/popup.module.scss +2 -3
- package/src/components/popup/popup.ts +1 -0
- package/src/components/propgrid/progrid.module.scss +4 -4
- package/src/components/radio/radio.module.scss +9 -3
- package/src/components/radio/radio.ts +7 -1
- package/src/components/select/select.module.scss +17 -12
- package/src/components/select/select.ts +9 -0
- package/src/components/settingsview/settingsview.module.scss +1 -4
- package/src/components/spreadsheet/spreadsheet.module.scss +0 -1
- package/src/components/switch/switch.module.scss +3 -2
- package/src/components/switch/switch.ts +1 -0
- package/src/components/tabs/tabs.module.scss +6 -3
- package/src/components/tabs/tabs.ts +3 -0
- package/src/components/tag/tag.module.scss +1 -1
- package/src/components/textarea/textarea.module.scss +8 -1
- package/src/components/textarea/textarea.ts +3 -0
- package/src/components/themes.scss +79 -12
- package/src/components/tickline/tickline.module.scss +1 -1
- package/src/components/tooltips/tooltips.scss +4 -3
- package/src/components/tooltips/tooltips.ts +1 -0
- package/src/components/treeview/treeview.module.scss +6 -2
- package/src/components/treeview/treeview.ts +1 -0
- package/src/core/core_application.ts +47 -0
- package/src/core/core_colors.ts +112 -17
|
@@ -18,14 +18,15 @@
|
|
|
18
18
|
|
|
19
19
|
:root {
|
|
20
20
|
--tooltip-caption-background: var( --color-primary-a70 );
|
|
21
|
-
--tooltip-caption-color:
|
|
21
|
+
--tooltip-caption-color: var( --accent-color );
|
|
22
22
|
|
|
23
|
-
--tooltip-icon-background:
|
|
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;
|
|
27
27
|
--tooltip-color: var( --color-primary-a90 );
|
|
28
28
|
--tooltip-border: var( --color-primary-a20 );
|
|
29
|
+
--tooltip-image-background: var( --background-primary );
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
.x4tooltip {
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
img {
|
|
68
69
|
max-width: 100px;
|
|
69
70
|
max-height: 50px;
|
|
70
|
-
background-color:
|
|
71
|
+
background-color: var( --tooltip-image-background );
|
|
71
72
|
margin: 4px;
|
|
72
73
|
}
|
|
73
74
|
}
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
:root {
|
|
19
19
|
|
|
20
|
-
--treeview-background:
|
|
20
|
+
--treeview-background: var( --background-primary );
|
|
21
|
+
|
|
22
|
+
--treeitem-color: var( --text-primary );
|
|
21
23
|
|
|
22
24
|
--treeitem-backgound-hover: var( --background-secondary );
|
|
23
|
-
--treeitem-color-hover: var( );
|
|
25
|
+
--treeitem-color-hover: var( --text-primary );
|
|
24
26
|
|
|
25
27
|
--treeitem-background-sel: var( --accent-background );
|
|
26
28
|
--treeitem-color-sel: var( --accent-color );
|
|
@@ -97,6 +99,8 @@
|
|
|
97
99
|
|
|
98
100
|
&:hover {
|
|
99
101
|
background-color: var( --treeitem-backgound-hover );
|
|
102
|
+
--label-color: var( --treeitem-color-hover );
|
|
103
|
+
--label-icon-color: var( --treeitem-color-hover );
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
&.selected {
|
|
@@ -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
|
*/
|
package/src/core/core_colors.ts
CHANGED
|
@@ -26,6 +26,34 @@ function round(v: number) {
|
|
|
26
26
|
return Math.round(v);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
let ctx2d: CanvasRenderingContext2D = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* a colour of css as the browser paints it: [red, green, blue, alpha 0-1];
|
|
33
|
+
* null when the browser does not know it
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
function browserColor( value: string ) {
|
|
37
|
+
if( !ctx2d ) {
|
|
38
|
+
const canvas = document.createElement( "canvas" );
|
|
39
|
+
canvas.width = canvas.height = 1;
|
|
40
|
+
ctx2d = canvas.getContext( "2d", { willReadFrequently: true } );
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// a value the canvas refuses leaves fillStyle as it was
|
|
44
|
+
ctx2d.fillStyle = "#010203";
|
|
45
|
+
ctx2d.fillStyle = value;
|
|
46
|
+
if( ctx2d.fillStyle=="#010203" ) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// fillStyle keeps the colour as it was written (oklch, color(srgb ...)): the pixel is in rgb
|
|
51
|
+
ctx2d.clearRect( 0, 0, 1, 1 );
|
|
52
|
+
ctx2d.fillRect( 0, 0, 1, 1 );
|
|
53
|
+
const px = ctx2d.getImageData( 0, 0, 1, 1 ).data;
|
|
54
|
+
return [ px[0], px[1], px[2], px[3] / 255 ];
|
|
55
|
+
}
|
|
56
|
+
|
|
29
57
|
|
|
30
58
|
export interface Rgb {
|
|
31
59
|
red: number;
|
|
@@ -79,6 +107,7 @@ export class Color {
|
|
|
79
107
|
* var( --color-5 )
|
|
80
108
|
* cyan
|
|
81
109
|
* transparent
|
|
110
|
+
* any other colour of css the browser knows: hsl( ), oklch( ), color-mix( )...
|
|
82
111
|
*/
|
|
83
112
|
|
|
84
113
|
setValue(value: string): this {
|
|
@@ -137,6 +166,12 @@ export class Color {
|
|
|
137
166
|
}
|
|
138
167
|
}
|
|
139
168
|
|
|
169
|
+
// another colour the browser knows (color-mix, hsl, oklch...)
|
|
170
|
+
const known = browserColor( value );
|
|
171
|
+
if( known ) {
|
|
172
|
+
return this.setRgb( known[0], known[1], known[2], known[3] );
|
|
173
|
+
}
|
|
174
|
+
|
|
140
175
|
// red, to be seen, and marked as invalid
|
|
141
176
|
this.setRgb(255, 0, 0, 1);
|
|
142
177
|
this.invalid = true;
|
|
@@ -343,32 +378,92 @@ export class Color {
|
|
|
343
378
|
* @param percent - The percentage to lighten (0-100).
|
|
344
379
|
* @returns The current Color instance.
|
|
345
380
|
*/
|
|
346
|
-
lighten(percent: number)
|
|
381
|
+
lighten(percent: number): this {
|
|
382
|
+
const factor = clamp(percent, 0, 100) / 100;
|
|
347
383
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
else if (percent > 100) {
|
|
352
|
-
percent = 100;
|
|
353
|
-
}
|
|
384
|
+
const [r, g, b, a] = this.rgb;
|
|
385
|
+
this.rgb = [round(r + (255 - r) * factor), round(g + (255 - g) * factor), round(b + (255 - b) * factor), a];
|
|
354
386
|
|
|
355
|
-
|
|
387
|
+
return this;
|
|
388
|
+
}
|
|
356
389
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
390
|
+
/**
|
|
391
|
+
* Darkens the color by a given percentage.
|
|
392
|
+
*
|
|
393
|
+
* @param percent - The percentage to darken (0-100).
|
|
394
|
+
* @returns The current Color instance.
|
|
395
|
+
*/
|
|
396
|
+
darken(percent: number): this {
|
|
397
|
+
const factor = 1 - clamp(percent, 0, 100) / 100;
|
|
364
398
|
|
|
365
|
-
const
|
|
366
|
-
this.rgb = [
|
|
399
|
+
const [r, g, b, a] = this.rgb;
|
|
400
|
+
this.rgb = [round(r * factor), round(g * factor), round(b * factor), a];
|
|
367
401
|
|
|
368
402
|
return this;
|
|
369
403
|
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Mixes the color with another one, alpha included.
|
|
407
|
+
*
|
|
408
|
+
* @param other - The other color.
|
|
409
|
+
* @param amount - The part of the other color (0-1): 0 keeps this color, 1 gives the other one.
|
|
410
|
+
* @returns The current Color instance.
|
|
411
|
+
*/
|
|
412
|
+
mix(other: Color, amount: number): this {
|
|
413
|
+
const t = clamp(amount, 0, 1);
|
|
414
|
+
|
|
415
|
+
const [r, g, b, a] = this.rgb;
|
|
416
|
+
const [r2, g2, b2, a2] = other.rgb;
|
|
417
|
+
this.rgb = [round(r + (r2 - r) * t), round(g + (g2 - g) * t), round(b + (b2 - b) * t), a + (a2 - a) * t];
|
|
418
|
+
|
|
419
|
+
return this;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Gets the relative luminance of the color, as WCAG defines it. The alpha is not used.
|
|
424
|
+
*
|
|
425
|
+
* @returns The luminance (0 for black, 1 for white).
|
|
426
|
+
*/
|
|
427
|
+
luminance(): number {
|
|
428
|
+
// the components in linear light
|
|
429
|
+
const lin = (v: number) => {
|
|
430
|
+
v /= 255;
|
|
431
|
+
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
const [r, g, b] = this.rgb;
|
|
435
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Gets the contrast ratio between the color and another one, as WCAG defines it.
|
|
440
|
+
*
|
|
441
|
+
* @param other - The other color.
|
|
442
|
+
* @returns The ratio (1 for the same luminance, 21 for black and white).
|
|
443
|
+
*/
|
|
444
|
+
contrast(other: Color): number {
|
|
445
|
+
const l1 = this.luminance();
|
|
446
|
+
const l2 = other.luminance();
|
|
447
|
+
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Gets, of two colors of text, the one that contrasts most with the color.
|
|
452
|
+
*
|
|
453
|
+
* @param light - The light text color (white by default).
|
|
454
|
+
* @param dark - The dark text color (black by default).
|
|
455
|
+
* @returns A copy of light or dark.
|
|
456
|
+
*/
|
|
457
|
+
textColor(light = WHITE, dark = BLACK): Color {
|
|
458
|
+
const best = this.contrast(light) >= this.contrast(dark) ? light : dark;
|
|
459
|
+
|
|
460
|
+
const [r, g, b, a] = best.rgb;
|
|
461
|
+
return new Color(r, g, b, a);
|
|
462
|
+
}
|
|
370
463
|
}
|
|
371
464
|
|
|
465
|
+
const WHITE = new Color(255, 255, 255);
|
|
466
|
+
const BLACK = new Color(0, 0, 0);
|
|
372
467
|
|
|
373
468
|
|
|
374
469
|
|