x4js 2.3.22 → 2.3.23

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.
Files changed (54) hide show
  1. package/aicontext.md +10 -1
  2. package/package.json +1 -1
  3. package/src/components/btngroup/btngroup.module.scss +1 -1
  4. package/src/components/btngroup/btngroup.ts +6 -1
  5. package/src/components/button/button.module.scss +4 -4
  6. package/src/components/button/button.ts +20 -0
  7. package/src/components/calendar/calendar.module.scss +2 -1
  8. package/src/components/calendar/calendar.ts +2 -1
  9. package/src/components/chart/chart.module.scss +4 -4
  10. package/src/components/checkbox/checkbox.module.scss +2 -1
  11. package/src/components/checkbox/checkbox.ts +1 -0
  12. package/src/components/colorpicker/colorpicker.module.scss +0 -1
  13. package/src/components/dialog/dialog.module.scss +2 -2
  14. package/src/components/dialog/dialog.ts +1 -0
  15. package/src/components/dockingview/dockingview.module.scss +9 -8
  16. package/src/components/dockingview/dockingview.ts +1 -0
  17. package/src/components/form/form.module.scss +2 -2
  18. package/src/components/form/form.ts +1 -1
  19. package/src/components/gauge/gauge.module.scss +2 -2
  20. package/src/components/gridview/gridview.module.scss +0 -1
  21. package/src/components/input/input.module.scss +2 -2
  22. package/src/components/input/input.ts +3 -0
  23. package/src/components/label/label.module.scss +1 -1
  24. package/src/components/listbox/listbox.module.scss +6 -3
  25. package/src/components/listbox/listbox.ts +2 -0
  26. package/src/components/menu/menu.module.scss +1 -2
  27. package/src/components/messages/messages.module.scss +11 -11
  28. package/src/components/messages/messages.ts +7 -1
  29. package/src/components/messages/pen-field.svg +1 -1
  30. package/src/components/panel/panel.module.scss +4 -3
  31. package/src/components/panel/panel.ts +1 -0
  32. package/src/components/popup/popup.module.scss +2 -3
  33. package/src/components/popup/popup.ts +1 -0
  34. package/src/components/propgrid/progrid.module.scss +4 -4
  35. package/src/components/radio/radio.module.scss +9 -3
  36. package/src/components/radio/radio.ts +7 -1
  37. package/src/components/select/select.module.scss +17 -12
  38. package/src/components/select/select.ts +9 -0
  39. package/src/components/settingsview/settingsview.module.scss +1 -1
  40. package/src/components/spreadsheet/spreadsheet.module.scss +0 -1
  41. package/src/components/switch/switch.module.scss +3 -2
  42. package/src/components/switch/switch.ts +1 -0
  43. package/src/components/tabs/tabs.module.scss +6 -3
  44. package/src/components/tabs/tabs.ts +3 -0
  45. package/src/components/tag/tag.module.scss +1 -1
  46. package/src/components/textarea/textarea.module.scss +8 -1
  47. package/src/components/textarea/textarea.ts +3 -0
  48. package/src/components/themes.scss +25 -12
  49. package/src/components/tickline/tickline.module.scss +1 -1
  50. package/src/components/tooltips/tooltips.scss +4 -3
  51. package/src/components/tooltips/tooltips.ts +1 -0
  52. package/src/components/treeview/treeview.module.scss +6 -2
  53. package/src/components/treeview/treeview.ts +1 -0
  54. package/src/core/core_colors.ts +112 -17
package/aicontext.md CHANGED
@@ -1030,6 +1030,8 @@ interface ButtonProps extends ComponentProps {
1030
1030
  tabindex?: number | boolean
1031
1031
  autorepeat?: number | boolean // true=200ms; number=interval (first fire after 500ms)
1032
1032
  click?: EventCallback<EvClick>
1033
+ menu?: MenuElement[] | (() => MenuElement[]) // a click opens this Menu under the button, in place of the click event;
1034
+ // a function is called at each click; the button gets the class "with-menu"
1033
1035
  }
1034
1036
  class Button extends Component {
1035
1037
  click(): void // simulate a click
@@ -1531,8 +1533,15 @@ class Timer { setTimeout; clearTimeout; setInterval; clearInterval; clearAllTime
1531
1533
 
1532
1534
  class Color {
1533
1535
  // new Color(value) | new Color(r,g,b,a?) a: 0..1, default 1
1536
+ // value: "#rgb", "#rrggbb", "#rrggbbaa", "rgb()", "rgba()", a name ("cyan", "transparent"), "var(--name)",
1537
+ // and any other colour the browser knows (hsl(), oklch(), color-mix()), read from the pixel it paints
1534
1538
  setValue(value): this; setRgb(r,g,b,a?): this; setHsv(h,s,v,a?): this; setAlpha(a): this
1535
- getAlpha(): number; lighten(percent): this
1539
+ getAlpha(): number
1540
+ lighten(percent): this; darken(percent): this // toward white / black, 0-100, each component rounded
1541
+ mix(other: Color, amount): this // amount 0-1: 0 keeps this color, 1 gives the other one; alpha too
1542
+ luminance(): number // WCAG relative luminance, 0 (black) to 1 (white); alpha not used
1543
+ contrast(other: Color): number // WCAG ratio, 1 to 21
1544
+ textColor(light?: Color, dark?: Color): Color // a copy of the one of the two that contrasts most with this color; white and black by default
1536
1545
  isInvalid(): boolean // the last setValue could not be read (the color is red); setRgb/setHsv make it valid
1537
1546
  toHexString(): string; toNumber(): number
1538
1547
  toRgbString(withAlpha = false): string // "rgb(r,g,b)"; true: "rgba(r,g,b,0.500)" when not opaque, "rgb(...)" when opaque
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x4js",
3
- "version": "2.3.22",
3
+ "version": "2.3.23",
4
4
  "type": "module",
5
5
  "main": "src/x4.ts",
6
6
  "module": "src/x4.ts",
@@ -15,7 +15,7 @@
15
15
  **/
16
16
 
17
17
  :root {
18
- --btngroup-background: white;
18
+ --btngroup-background: var( --background-primary );
19
19
  }
20
20
 
21
21
  .x4btngroup {
@@ -56,7 +56,12 @@ interface BtnGroupProps extends Omit<ComponentProps,"content"> {
56
56
  }
57
57
 
58
58
  /**
59
- *
59
+ *
60
+ * @cssvar
61
+ * ```
62
+ * --btngroup-background
63
+ * ```
64
+ * a packed group draws its buttons with the --ol-button-* variables of Button
60
65
  */
61
66
 
62
67
  @class_ns( "x4" )
@@ -32,15 +32,15 @@
32
32
  --button-background-disabled: var( --disabled-background );
33
33
  --button-color-disabled: var( --disabled-color );
34
34
 
35
- --button-icon-color: rgb(255 255 255 / 64%);
35
+ --button-icon-color: var( --icon-color-active );
36
36
 
37
37
  // outline
38
38
  --ol-button-background: var( --background-primary );
39
- --ol-button-background-active: #ccc;
39
+ --ol-button-background-active: var( --background-active );
40
40
  --ol-button-color-active: var( --text-primary );
41
- --ol-button-background-hover: #eee;
41
+ --ol-button-background-hover: var( --background-hover );
42
42
  --ol-button-color-hover: var( --text-primary );
43
- --ol-button-color-disabled: #ccc;
43
+ --ol-button-color-disabled: var( --disabled-color-light );
44
44
 
45
45
  --ol-button-color: var( --text-primary );
46
46
  --ol-button-border: var( --border );
@@ -71,6 +71,14 @@ export interface ButtonProps extends ComponentProps {
71
71
  */
72
72
  click?: EventCallback<EvClick>;
73
73
 
74
+ /**
75
+ * A menu that a click opens under the button, in place of the click event.
76
+ * A function is called at each click: it gives the items of that time.
77
+ * The button gets the class "with-menu".
78
+ *
79
+ * @example
80
+ * new Button( { label: "File", menu: [ { text: "Open", click: open }, "-", { text: "Quit", click: quit } ] } );
81
+ */
74
82
  menu?: MenuElement[] | (( ) => MenuElement[]);
75
83
  }
76
84
 
@@ -90,7 +98,19 @@ export interface ButtonProps extends ComponentProps {
90
98
  * --button-background-disabled
91
99
  * --button-color-disabled
92
100
  * --button-icon-color
101
+ * --ol-button-background
102
+ * --ol-button-color
103
+ * --ol-button-border
104
+ * --ol-button-icon-color
105
+ * --ol-button-background-hover
106
+ * --ol-button-color-hover
107
+ * --ol-button-background-active
108
+ * --ol-button-color-active
109
+ * --ol-button-color-disabled
110
+ * --ol-button-border-focus
111
+ * --ol-button-color-focus
93
112
  * ```
113
+ * the --ol-button-* variables are the ones of the outline buttons
94
114
  */
95
115
 
96
116
  @class_ns( "x4" )
@@ -36,6 +36,7 @@
36
36
 
37
37
  --calendar-header-color: var( --text-primary );
38
38
  --calendar-out-color: var( --disabled-color-dark );
39
+ --calendar-day-color: var( --text-primary );
39
40
  }
40
41
 
41
42
  .x4calendar {
@@ -93,7 +94,7 @@
93
94
  min-width: 28px;
94
95
  min-height: 28px;
95
96
 
96
- color: var( --gray-900 );
97
+ color: var( --calendar-day-color );
97
98
  text-align: center;
98
99
 
99
100
  .text {
@@ -54,7 +54,7 @@ interface CalendarProps extends ComponentProps {
54
54
  * ```
55
55
  * --calendar-btn-background
56
56
  * --calendar-btn-color
57
- * --calendar-btn-color
57
+ * --calendar-btn-color-hover
58
58
  * --calendar-week-color
59
59
  * --calendar-week-color-hover
60
60
  * --calendard-day-background-hover
@@ -66,6 +66,7 @@ interface CalendarProps extends ComponentProps {
66
66
  * --calendar-today-border
67
67
  * --calendar-header-color
68
68
  * --calendar-out-color
69
+ * --calendar-day-color
69
70
  * ```
70
71
  */
71
72
 
@@ -15,10 +15,10 @@
15
15
  **/
16
16
 
17
17
  :root {
18
- --chart-background: white;
19
- --chart-text: #52514e;
20
- --chart-grid: #e6e5e0;
21
- --chart-axis: #b5b4ae;
18
+ --chart-background: var( --background-primary );
19
+ --chart-text: var( --text-ternary );
20
+ --chart-grid: var( --border );
21
+ --chart-axis: var( --border-hover );
22
22
 
23
23
  // series colors, used in this order
24
24
  --chart-color-1: #2a78d6;
@@ -24,6 +24,7 @@
24
24
  --checkbox-color-disabled: var( --disabled-background );
25
25
  --checkbox-check-border: var( --border );
26
26
  --checkbox-check-border-hover: var( --border-hover );
27
+ --checkbox-check-color: var( --accent-color );
27
28
  }
28
29
 
29
30
  .x4checkbox {
@@ -41,7 +42,7 @@
41
42
  .inner {
42
43
  height: 1rem;
43
44
  width: 1rem;
44
- color: white;
45
+ color: var( --checkbox-check-color );
45
46
  position: relative;
46
47
  order: 1;
47
48
 
@@ -41,6 +41,7 @@ interface CheckboxProps extends ComponentProps {
41
41
  * --checkbox-color-disabled
42
42
  * --checkbox-check-border
43
43
  * --checkbox-check-border-hover
44
+ * --checkbox-check-color
44
45
  * ```
45
46
  */
46
47
 
@@ -74,7 +74,6 @@
74
74
  overflow: hidden;
75
75
 
76
76
  background-image: linear-gradient(to right, rgb(255, 0, 0), rgb(255, 255, 0), rgb(0, 255, 0), rgb(0, 255, 212), rgb(0, 0, 255), rgb(255, 0, 255), rgb(255, 0, 0));
77
- border: 1px solid var( --color-gray-3 );
78
77
 
79
78
  .thumb {
80
79
  @include overlay-shadow;
@@ -19,6 +19,7 @@
19
19
  :root {
20
20
  --color-dialog-caption: var( --color-primary-a80 );
21
21
  --color-dialog-caption-text: var( --color-primary-a0 );
22
+ --color-dialog-background: var( --background-primary );
22
23
  }
23
24
 
24
25
  .x4dialog {
@@ -26,8 +27,7 @@
26
27
  @extend %vbox;
27
28
 
28
29
  position: absolute !important;
29
- background-color: white;
30
- border: 1px solid var( --border-dark );
30
+ background-color: var( --color-dialog-background );
31
31
  max-width: 99vw;
32
32
  outline: none;
33
33
 
@@ -54,6 +54,7 @@ interface DialogEvents extends PopupEvents {
54
54
  * ```
55
55
  * --color-dialog-caption
56
56
  * --color-dialog-caption-text
57
+ * --color-dialog-background
57
58
  * ```
58
59
  */
59
60
 
@@ -15,13 +15,14 @@
15
15
  **/
16
16
 
17
17
  .x4dockingview {
18
- --dock-line: var( --border, #cfdae0 ); // between two panels, under a title
19
- --dock-title-background: var( --background-secondary, #f3f7f9 );
20
- --dock-title-background-hover: color-mix( in srgb, var( --dock-accent ) 25%, transparent );
21
- --dock-title-color: var( --text-ternary, #607784 );
22
- --dock-title-color-active: var( --text-primary, #002a40 );
23
- --dock-accent: var( --accent-background, #126e9e ); // the tab in front, the sizer under the pointer, the preview
24
- --dock-float-background: var( --background-primary, white );
18
+ --dock-line: var( --border ); // between two panels, under a title
19
+ --dock-title-background: var( --background-secondary );
20
+ --dock-title-background-hover: var( --accent-background-light );
21
+ --dock-title-color: var( --text-ternary );
22
+ --dock-title-color-active: var( --text-primary );
23
+ --dock-accent: var( --accent-background ); // the tab in front, the sizer under the pointer, the border of the preview
24
+ --dock-preview-background: var( --accent-background-light ); // where the panel that is dragged will go
25
+ --dock-float-background: var( --background-primary );
25
26
  --dock-float-shadow: 0 6px 24px rgba( 0, 0, 0, 0.35 );
26
27
 
27
28
  position: relative;
@@ -279,7 +280,7 @@
279
280
  box-sizing: border-box;
280
281
  pointer-events: none;
281
282
 
282
- background: color-mix( in srgb, var( --dock-accent ) 30%, transparent );
283
+ background: var( --dock-preview-background );
283
284
  border: 1px solid var( --dock-accent );
284
285
  border-radius: 3px;
285
286
  }
@@ -179,6 +179,7 @@ interface Drag {
179
179
  * --dock-title-background-hover
180
180
  * --dock-title-color
181
181
  * --dock-title-color-active
182
+ * --dock-preview-background
182
183
  * --dock-float-background
183
184
  * --dock-float-shadow
184
185
  * ```
@@ -17,7 +17,7 @@
17
17
  @use "../shared.scss";
18
18
 
19
19
  :root {
20
- --form--background: var( --background-primary );
20
+ --form-background: transparent;
21
21
  }
22
22
 
23
23
  .x4form {
@@ -25,7 +25,7 @@
25
25
  @extend %flex;
26
26
 
27
27
  padding: 16px;
28
- background-color: var( --color-form );
28
+ background-color: var( --form-background );
29
29
 
30
30
  &.horizontal {
31
31
  flex-direction: row;
@@ -31,7 +31,7 @@ type ValidationFn = ( values: FormValues, is_valid: boolean ) => boolean;
31
31
  /**
32
32
  * @cssvar
33
33
  * ```
34
- * --form--background
34
+ * --form-background
35
35
  * ```
36
36
  */
37
37
 
@@ -16,8 +16,8 @@
16
16
 
17
17
  :root {
18
18
  --gauge-base-color: var( --color-primary-a70 );
19
- --gauge-needle-back: black;
20
- --gauge-needle-dot: rgb(58, 58, 58);
19
+ --gauge-needle-back: var( --text-primary );
20
+ --gauge-needle-dot: var( --text-ternary );
21
21
  }
22
22
 
23
23
  .x4gauge {
@@ -346,7 +346,6 @@
346
346
 
347
347
  .cell-out {
348
348
  position: absolute;
349
- background-color: var( --color-gray-0 );
350
349
  width: 100%;
351
350
  height: var( --row-height );
352
351
  }
@@ -15,8 +15,8 @@
15
15
  **/
16
16
 
17
17
  :root {
18
- --input-background: rgba(255, 255, 255, 0.6);
19
- --input-color: black;
18
+ --input-background: var( --background-input );
19
+ --input-color: var( --text-primary );
20
20
 
21
21
  --input-sel-background: var( --accent-background );
22
22
  --input-sel-color: var( --accent-color );
@@ -203,6 +203,9 @@ interface InputEvents extends ComponentEvent {
203
203
  *
204
204
  * @cssvar
205
205
  * ```
206
+ * --input-background
207
+ * --input-color
208
+ * --input-color-disabled
206
209
  * --input-sel-background
207
210
  * --input-sel-color
208
211
  * --input-placeholder
@@ -19,7 +19,7 @@
19
19
  :root {
20
20
  --label-background: transparent;
21
21
  --label-color: var( --text-ternary );
22
- --label-icon-color: rgb(0 0 0 / 44%);
22
+ --label-icon-color: var( --icon-color );
23
23
  --label-color-disa: var( --disabled-color-dark );
24
24
  }
25
25
 
@@ -28,9 +28,12 @@
28
28
  --listbox-item-color-hover: var( --text-primary );;
29
29
  --listbox-item-background-hover: var( --background-secondary );
30
30
 
31
- --listbox-background: white;
31
+ --listbox-background: var( --background-primary );
32
32
  --listbox-border: var( --border );
33
33
  --listbox-border-focus: var( --accent-background-focus );
34
+
35
+ --listbox-title-background: var( --background-primary );
36
+ --listbox-title-color: var( --text-primary );
34
37
  }
35
38
 
36
39
  .x4listbox {
@@ -48,10 +51,10 @@
48
51
  }
49
52
 
50
53
  &>.title {
51
- background: white;
54
+ background: var( --listbox-title-background );
52
55
  padding: 4px;
53
56
  font-weight: bold;
54
- color: black;
57
+ color: var( --listbox-title-color );
55
58
  border-bottom: 1px solid var(--border);
56
59
  }
57
60
 
@@ -88,6 +88,8 @@ export interface ListboxProps extends Omit<ComponentProps,'content'> {
88
88
  * --listbox-background
89
89
  * --listbox-border
90
90
  * --listbox-border-focus
91
+ * --listbox-title-background
92
+ * --listbox-title-color
91
93
  * ```
92
94
  */
93
95
 
@@ -17,7 +17,7 @@
17
17
  @use "../shared.scss";
18
18
 
19
19
  :root {
20
- --menu-background: white;
20
+ --menu-background: var( --background-primary );
21
21
  --menu-border: var( --border-hover );
22
22
 
23
23
  --menuitem-color: var( --text-ternary );;
@@ -33,7 +33,6 @@
33
33
  position: absolute;
34
34
  overflow-y: auto;
35
35
 
36
- border-radius: var(--bradius);
37
36
  padding: 8px 0;
38
37
  min-width: 150px;
39
38
 
@@ -20,12 +20,16 @@
20
20
  --msgbox-caption-color: var( --alert-color );
21
21
 
22
22
  --msgbox-icon-color: var( --alert-background );
23
+ --msgbox-question-icon-color: var( --accent-background ); // a question, an InputBox, a PromptBox
24
+
25
+ --msgbox-log-background: var( --background-ternary ); // the lines of a ProgressionBox
23
26
  }
24
27
 
25
28
  .x4messagebox {
26
29
  max-width: 60vw;
27
30
 
28
- & > .caption {
31
+ // an error has its own title bar; a question has the one of a Dialog
32
+ &.error > .caption {
29
33
  background-color: var( --msgbox-caption-background );
30
34
 
31
35
  & > #title {
@@ -45,24 +49,20 @@
45
49
  line-height: 1.8em;
46
50
  }
47
51
  }
52
+
53
+ &.question .x4form .x4icon {
54
+ color: var( --msgbox-question-icon-color );
55
+ }
48
56
  }
49
57
 
50
58
  .x4inputbox,
51
59
  .x4promptbox {
52
60
  max-width: 60vw;
53
61
 
54
- & > .caption {
55
- background-color: var( --msgbox-caption-background );
56
-
57
- & > #title {
58
- color: var( --msgbox-caption-color );
59
- }
60
- }
61
-
62
62
  & .x4form {
63
63
  min-width: 400px;
64
64
  .x4icon {
65
- color: var( --msgbox-icon-color );
65
+ color: var( --msgbox-question-icon-color );
66
66
  height: 64px;
67
67
  }
68
68
 
@@ -134,7 +134,7 @@
134
134
  flex-grow: 1;
135
135
  max-height: 400px;
136
136
  overflow: auto;
137
- background-color: #f5f5f5;
137
+ background-color: var( --msgbox-log-background );
138
138
  padding: 4px 8px;
139
139
  margin: 0 16px;
140
140
 
@@ -34,7 +34,11 @@ export interface MessageBoxProps extends DialogProps {
34
34
  * --msgbox-caption-background
35
35
  * --msgbox-caption-color
36
36
  * --msgbox-icon-color
37
+ * --msgbox-question-icon-color
38
+ * --msgbox-log-background
37
39
  * ```
40
+ * --msgbox-caption-* and --msgbox-icon-color are the ones of an error; a question, an InputBox
41
+ * and a PromptBox have the title bar of a Dialog and their icon in --msgbox-question-icon-color
38
42
  */
39
43
 
40
44
  @class_ns( "x4" )
@@ -58,7 +62,9 @@ export class MessageBox extends Dialog<DialogProps>
58
62
  }
59
63
  }
60
64
 
61
- const box = new MessageBox({
65
+ // the kind as a class: an error has its own title bar
66
+ const box = new MessageBox({
67
+ cls: icon_type ?? "error",
62
68
  modal: true,
63
69
  title: title ?? _tr.global.error,
64
70
  movable: true,
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--!Font Awesome Pro 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.--><path class="fa-secondary" opacity=".4" d="M0 128l32 0 224 0 32 0 0 64-32 0L64 192l0 256 448 0 0-128 0-32 64 0 0 32 0 160 0 32-32 0L32 512 0 512l0-32L0 160l0-32z"/><path class="fa-primary" d="M288 352l16-112L468.7 75.3l96 96L400 336 288 352zM587.3 148.7l-96-96L544 0l96 96-52.7 52.7zM96 288l64 0 0 64-64 0 0-64zm160 0l0 64-64 0 0-64 64 0z"/></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" fill="currentColor"><!--!Font Awesome Pro 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.--><path class="fa-secondary" opacity=".4" d="M0 128l32 0 224 0 32 0 0 64-32 0L64 192l0 256 448 0 0-128 0-32 64 0 0 32 0 160 0 32-32 0L32 512 0 512l0-32L0 160l0-32z"/><path class="fa-primary" d="M288 352l16-112L468.7 75.3l96 96L400 336 288 352zM587.3 148.7l-96-96L544 0l96 96-52.7 52.7zM96 288l64 0 0 64-64 0 0-64zm160 0l0 64-64 0 0-64 64 0z"/></svg>
@@ -18,7 +18,8 @@
18
18
 
19
19
  :root {
20
20
  --panel-border: var( --border );
21
- --panel-title-color: var( --border );
21
+ --panel-title-color: var( --text-primary );
22
+ --panel-title-background: var( --background-primary );
22
23
  }
23
24
 
24
25
 
@@ -34,9 +35,9 @@
34
35
  position: absolute;
35
36
  left: 4px;
36
37
  top: -0.7em;
37
- background-color: white;
38
+ background-color: var( --panel-title-background );
38
39
  font-weight: bold;
39
- color: var(--color-gray-9);
40
+ color: var( --panel-title-color );
40
41
  }
41
42
 
42
43
  & > .body {
@@ -33,6 +33,7 @@ interface PanelProps extends ComponentProps {
33
33
  * ```
34
34
  * --panel-border
35
35
  * --panel-title-color
36
+ * --panel-title-background
36
37
  * ```
37
38
  */
38
39
 
@@ -16,15 +16,14 @@
16
16
 
17
17
  :root {
18
18
  --modal-mask-background: rgb(0 0 0 / 60% );
19
+ --popup-background: transparent;
19
20
  }
20
21
 
21
22
  .x4popup {
22
23
  position: absolute !important;
23
- background-color: var(--fill-color);
24
- border: 1px solid var(--border-color);
24
+ background-color: var( --popup-background );
25
25
  overflow: hidden;
26
26
  z-index: 1000;
27
- border-radius: var(--bradius);
28
27
 
29
28
  &.popup-caption,
30
29
  .popup-caption {
@@ -66,6 +66,7 @@ function dismissLast( e: UIEvent ) {
66
66
  * @cssvar
67
67
  * ```
68
68
  * --modal-mask-background
69
+ * --popup-background
69
70
  * ```
70
71
  */
71
72
 
@@ -5,16 +5,16 @@
5
5
  **/
6
6
 
7
7
  :root {
8
- --propertygrid-background: white;
9
- --propertygrid-gadget-background: white;
10
- --propertygrid-gadget-color: black;
8
+ --propertygrid-background: var( --background-primary );
9
+ --propertygrid-gadget-background: var( --background-primary );
10
+ --propertygrid-gadget-color: var( --text-primary );
11
11
 
12
12
  --propertygrid-odd-background: var(--color-primary-a5);
13
13
  --propertygrid-even-background: transparent;
14
14
  --propertygrid-disabled-background: rgb(170 170 170 / 14%);
15
15
  --propertygrid-hover-background: var(--color-primary-a10);
16
16
  --propertygrid-focus-background: var(--color-primary-a20);
17
- --propertygrid-input-background: rgba(255,255,255,0.6);
17
+ --propertygrid-input-background: var( --background-input );
18
18
 
19
19
  --propertygrid-group-background: var( --color-primary-a5 );
20
20
  --propertygrid-group-color: var( --color-primary-a50 );
@@ -14,6 +14,12 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
+ :root {
18
+ --radio-background: var( --background-primary );
19
+ --radio-check-color: var( --accent-color );
20
+ --radio-square-border-checked: var( --accent-color );
21
+ }
22
+
17
23
  .x4radio {
18
24
  display: flex;
19
25
  flex-direction: row;
@@ -36,7 +42,7 @@
36
42
  input {
37
43
  appearance: none;
38
44
  border-radius: 50%;
39
- background-color: white;
45
+ background-color: var( --radio-background );
40
46
  cursor: pointer;
41
47
  display: block;
42
48
 
@@ -67,7 +73,7 @@
67
73
  }
68
74
 
69
75
  .fa-secondary {
70
- fill: white;
76
+ fill: var( --radio-check-color );
71
77
  }
72
78
  }
73
79
 
@@ -157,7 +163,7 @@
157
163
 
158
164
  &:has(input:checked) {
159
165
  background-color: var( --accent-background-active );
160
- border-color: white;
166
+ border-color: var( --radio-square-border-checked );
161
167
  font-weight: 700;
162
168
  }
163
169
  }
@@ -48,7 +48,13 @@ interface RadioProps extends ComponentProps {
48
48
  }
49
49
 
50
50
  /**
51
- *
51
+ *
52
+ * @cssvar
53
+ * ```
54
+ * --radio-background
55
+ * --radio-check-color
56
+ * --radio-square-border-checked
57
+ * ```
52
58
  */
53
59
 
54
60
  @class_ns( "x4" )
@@ -1,10 +1,11 @@
1
1
 
2
- /**
3
- * @cssvar
4
- * --select-border
5
- * --select-border-focus
6
- * --select-background
7
- */
2
+ :root {
3
+ --select-border: var( --border );
4
+ --select-border-focus: var( --accent-background );
5
+ --select-background: var( --background-primary );
6
+ --select-color: var( --text-primary );
7
+ --select-arrow-color: var( --text-ternary );
8
+ }
8
9
 
9
10
  .x4select,
10
11
  ::picker(select) {
@@ -14,22 +15,26 @@
14
15
  outline: none;
15
16
 
16
17
  border-radius: 0;
17
- border: 1px solid var( --select-border, var( --border ) );
18
- background-color: var( --select-background, white );
18
+ border: 1px solid var( --select-border );
19
+ background-color: var( --select-background );
20
+ color: var( --select-color );
19
21
  }
20
22
 
21
23
  .x4select {
22
24
  appearance: none;
23
25
  -webkit-appearance: none;
24
26
  -moz-appearance: none;
25
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%23333' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
27
+ // the arrow: two halves of a square side by side, in the colour of the variable
28
+ background-image:
29
+ linear-gradient( 45deg, transparent 50%, var( --select-arrow-color ) 50% ),
30
+ linear-gradient( 135deg, var( --select-arrow-color ) 50%, transparent 50% );
26
31
  background-repeat: no-repeat;
27
- background-position: right 6px center;
28
- background-size: 12px 8px;
32
+ background-position: right 13px center, right 8px center;
33
+ background-size: 5px 5px, 5px 5px;
29
34
  padding-right: 23px;
30
35
 
31
36
  &:focus-visible {
32
- border-color: var( --select-border-focus, var( --accent-background ) );
37
+ border-color: var( --select-border-focus );
33
38
  }
34
39
 
35
40
  .select-option {
@@ -46,6 +46,15 @@ interface SelectEvents extends ComponentEvents {
46
46
  /**
47
47
  * simple select
48
48
  * cf. Combobox
49
+ *
50
+ * @cssvar
51
+ * ```
52
+ * --select-border
53
+ * --select-border-focus
54
+ * --select-background
55
+ * --select-color
56
+ * --select-arrow-color
57
+ * ```
49
58
  */
50
59
 
51
60
  @class_ns( "x4" )
@@ -18,7 +18,7 @@
18
18
  --settingsview-toc-width: 210px;
19
19
  --settingsview-section-background: var( --color-primary-a10 );
20
20
  --settingsview-section-title-background: var( --color-primary-a20 );
21
- --settingsview-hover-background: color-mix( in srgb, var( --color-primary-a20 ) 60%, transparent );
21
+ --settingsview-hover-background: var( --color-primary-a20 );
22
22
  --settingsview-marker: var( --accent-background );
23
23
  }
24
24
 
@@ -333,7 +333,6 @@
333
333
 
334
334
  .cell-out {
335
335
  position: absolute;
336
- background-color: var( --color-gray-0 );
337
336
  width: 100%;
338
337
  height: var( --row-height );
339
338
  }
@@ -18,9 +18,10 @@
18
18
 
19
19
  :root {
20
20
  --switch-border: var( --border );
21
- --switch-background: #eee;
21
+ --switch-background: var( --background-hover );
22
22
  --switch-background-disabled: var( --disabled-background );
23
23
  --switch-checked: var( --accent-background );
24
+ --switch-thumb: var( --background-primary );
24
25
  }
25
26
 
26
27
  .x4switch {
@@ -88,7 +89,7 @@
88
89
  height: 1rem;
89
90
 
90
91
  border-radius: 8px;
91
- background-color: white;
92
+ background-color: var( --switch-thumb );
92
93
  box-shadow: 0 0 2px rgba(0,0,0,0.5);
93
94
 
94
95
  transition: left ease 0.2s;
@@ -39,6 +39,7 @@ interface SwitchProps extends ComponentProps {
39
39
  * --switch-background
40
40
  * --switch-background-disabled
41
41
  * --switch-checked
42
+ * --switch-thumb
42
43
  * ```
43
44
  */
44
45
 
@@ -3,6 +3,9 @@
3
3
  :root {
4
4
  --tab-border-selected: var( --accent-background );
5
5
  --tab-border-hover: var( --accent-background-hover );
6
+ --tab-color-hover: var( --text-primary );
7
+ --tab-color: var( --text-primary );
8
+ --tab-color-selected: var( --text-primary );
6
9
  }
7
10
 
8
11
  .x4tabs {
@@ -20,7 +23,7 @@
20
23
  .x4button {
21
24
  border: none;
22
25
  border-bottom: 2px solid transparent;
23
- color: var( --color-gray-7 );
26
+ color: var( --tab-color );
24
27
  margin: 0;
25
28
  outline: none;
26
29
  transition: border-color 0.2s ease;
@@ -28,12 +31,12 @@
28
31
  &.selected {
29
32
  border-bottom-color: var( --tab-border-selected );
30
33
  font-weight: bold;
31
- color: var( --color-gray-9 );
34
+ color: var( --tab-color-selected );
32
35
  }
33
36
 
34
37
  &:hover {
35
38
  background-color: unset;;
36
- color: black;
39
+ color: var( --tab-color-hover );
37
40
  border-bottom-color: var( --tab-border-hover );
38
41
  }
39
42
 
@@ -146,6 +146,9 @@ interface TabsProps extends Omit<ComponentProps,"content"> {
146
146
  * ```
147
147
  * --tab-border-selected
148
148
  * --tab-border-hover
149
+ * --tab-color-hover
150
+ * --tab-color
151
+ * --tab-color-selected
149
152
  * ```
150
153
  */
151
154
 
@@ -19,7 +19,7 @@
19
19
  --tag-border: var( --border );
20
20
  --tag-border-focus: var( --border-focus );
21
21
  --tag-background: var( --accent-background );
22
- --tag-color: black;
22
+ --tag-color: var( --text-primary );
23
23
  --tag-icon-color: var( --tag-color );
24
24
  }
25
25
 
@@ -20,6 +20,9 @@
20
20
  --textarea-border: var( --border );
21
21
  --textarea-border-focus: var( --border-focus );
22
22
  --textarea-selection: var( --accent-background );
23
+ --textarea-selection-color: var( --accent-color );
24
+ --textarea-background: var( --background-input );
25
+ --textarea-color: var( --text-primary );
23
26
  }
24
27
 
25
28
  .x4simpletextarea {
@@ -36,6 +39,10 @@
36
39
  outline: none;
37
40
  font: inherit;
38
41
 
42
+ // as the ones of an input
43
+ background-color: var( --textarea-background );
44
+ color: var( --textarea-color );
45
+
39
46
  border: 1px solid var( --textarea-border );
40
47
 
41
48
  &:focus {
@@ -44,7 +51,7 @@
44
51
 
45
52
  &::selection {
46
53
  background-color: var( --textarea-selection );
47
- color: white;
54
+ color: var( --textarea-selection-color );
48
55
  }
49
56
 
50
57
  // as the one of an input
@@ -136,6 +136,9 @@ export class SimpleTextArea extends Component<SimpleTextAreaProps,TextAreaEvents
136
136
  * --textarea-border
137
137
  * --textarea-border-focus
138
138
  * --textarea-selection
139
+ * --textarea-selection-color
140
+ * --textarea-background
141
+ * --textarea-color
139
142
  * ```
140
143
  */
141
144
 
@@ -44,27 +44,39 @@ $color--interval: 8.4%;
44
44
  --color-success-a60: #{color.adjust(#10c01f, $lightness: -10%)};
45
45
  }
46
46
 
47
+ // the greys are mixes of the two ends of the scale: #999 with a0 white and a100 black,
48
+ // light on dark when a theme reverses the scale
49
+
47
50
  :root {
48
51
  // Backgrounds
49
52
  --background-primary: var(--color-primary-a0);
50
53
  --background-secondary: var(--color-primary-a10);
51
- --background-ternary: #f4f4f4;
54
+ --background-ternary: color-mix(in srgb, var(--color-primary-a100) 4.3%, var(--color-primary-a0)); // #f4f4f4
55
+ --background-hover: color-mix(in srgb, var(--color-primary-a100) 6.7%, var(--color-primary-a0)); // #eee
56
+ --background-active: color-mix(in srgb, var(--color-primary-a100) 20%, var(--color-primary-a0)); // #ccc
57
+ --background-input: color-mix(in srgb, var(--color-primary-a0) 60%, transparent); // white at 60%
52
58
 
53
59
  // Texts
54
60
  --text-primary: var(--color-primary-a100);
55
- --text-secondary: #999;
56
- --text-ternary: #666;
61
+ --text-secondary: color-mix(in srgb, var(--color-primary-a100) 40%, var(--color-primary-a0)); // #999
62
+ --text-ternary: color-mix(in srgb, var(--color-primary-a100) 60%, var(--color-primary-a0)); // #666
57
63
 
58
64
  // Disabled
59
- --disabled-background: #ccc;
60
- --disabled-color: white;
61
- --disabled-color-dark: #aaa;
65
+ --disabled-background: color-mix(in srgb, var(--color-primary-a100) 20%, var(--color-primary-a0)); // #ccc
66
+ --disabled-color: var(--color-primary-a0);
67
+ --disabled-color-dark: color-mix(in srgb, var(--color-primary-a100) 33.3%, var(--color-primary-a0)); // #aaa
68
+ --disabled-color-light: color-mix(in srgb, var(--color-primary-a100) 20%, var(--color-primary-a0)); // #ccc
69
+
70
+ // Icons
71
+ --icon-color: color-mix(in srgb, var(--color-primary-a100) 44%, transparent); // black at 44%
72
+ --icon-color-active: color-mix(in srgb, var(--accent-color) 64%, transparent); // white at 64%
62
73
 
63
74
  // Accents
64
75
  --accent-background: var(--color-primary-a60);
65
76
  --accent-background-hover: var(--color-primary-a55);
66
77
  --accent-background-focus: var(--color-primary-a70);
67
78
  --accent-background-active: var(--color-primary-a80);
79
+ --accent-background-light: color-mix(in srgb, var(--accent-background) 25%, transparent); // the accent at 25%
68
80
 
69
81
  --accent-color: var(--color-primary-a0);
70
82
  --accent-color-hover: var(--color-primary-a0);
@@ -72,19 +84,20 @@ $color--interval: 8.4%;
72
84
  --accent-color-active: var(--color-primary-a0);
73
85
 
74
86
  // Borders
75
- --border: #e1e1e1;
76
- --border-light: #eaeaea;
77
- --border-hover: #c2c2c2;
87
+ --border: color-mix(in srgb, var(--color-primary-a100) 11.8%, var(--color-primary-a0)); // #e1e1e1
88
+ --border-light: color-mix(in srgb, var(--color-primary-a100) 8.2%, var(--color-primary-a0)); // #eaeaea
89
+ --border-hover: color-mix(in srgb, var(--color-primary-a100) 23.9%, var(--color-primary-a0)); // #c2c2c2
78
90
  --border-focus: var(--accent-background);
79
91
 
92
+ // the red, orange and green do not follow the scale: their text stays white
80
93
  --alert-background: var(--color-danger-a50);
81
94
  --alert-background-active: var(--color-danger-a60);
82
- --alert-color: var(--color-primary-a0);
95
+ --alert-color: #ffffff;
83
96
 
84
97
  --warning-background: var(--color-warning-a50);
85
- --warning-color: var(--color-primary-a0);
98
+ --warning-color: #ffffff;
86
99
 
87
100
  --success-background: var(--color-success-a50);
88
101
  --success-background-active: var(--color-success-a60);
89
- --success-color: var(--color-primary-a0);
102
+ --success-color: #ffffff;
90
103
  }
@@ -18,7 +18,7 @@
18
18
  --tickline-axis-color: var( --border );
19
19
  --tickline-color: var( --accent-color );
20
20
  --tickline-width: 1px;
21
- --tickline-background: white;
21
+ --tickline-background: var( --background-primary );
22
22
  }
23
23
 
24
24
  .x4tickline {
@@ -18,14 +18,15 @@
18
18
 
19
19
  :root {
20
20
  --tooltip-caption-background: var( --color-primary-a70 );
21
- --tooltip-caption-color: white;
21
+ --tooltip-caption-color: var( --color-primary-a0 );
22
22
 
23
- --tooltip-icon-background: white;
23
+ --tooltip-icon-background: var( --color-primary-a0 );
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: white;
71
+ background-color: var( --tooltip-image-background );
71
72
  margin: 4px;
72
73
  }
73
74
  }
@@ -104,6 +104,7 @@ function closeTT( ) {
104
104
  * --tooltip-background
105
105
  * --tooltip-color
106
106
  * --tooltip-border
107
+ * --tooltip-image-background
107
108
  * ```
108
109
  */
109
110
 
@@ -17,10 +17,12 @@
17
17
 
18
18
  :root {
19
19
 
20
- --treeview-background: white;
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 {
@@ -72,6 +72,7 @@ export interface TreeviewEvents extends ComponentEvents {
72
72
  * @cssvar
73
73
  * ```
74
74
  * --treeview-background
75
+ * --treeitem-color
75
76
  * --treeitem-backgound-hover
76
77
  * --treeitem-color-hover
77
78
  * --treeitem-background-sel
@@ -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) : this {
381
+ lighten(percent: number): this {
382
+ const factor = clamp(percent, 0, 100) / 100;
347
383
 
348
- if (percent < 0) {
349
- percent = 0;
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
- const factor = percent / 100;
387
+ return this;
388
+ }
356
389
 
357
- const adj = (value: number): number => {
358
- value = (value + (255 - value) * factor) | 0;
359
- if (value > 255) {
360
- value = 255;
361
- }
362
- return value;
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 _ = this.rgb;
366
- this.rgb = [adj(_[0]), adj(_[1]), adj(_[2]), _[3]];
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