x4js 2.3.26 → 2.3.28

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/aicontext.md +73 -6
  4. package/package.json +2 -1
  5. package/src/components/autocomplete/autocomplete.ts +6 -2
  6. package/src/components/boxes/boxes.ts +2 -2
  7. package/src/components/button/button.module.scss +4 -3
  8. package/src/components/calendar/calendar.ts +1 -1
  9. package/src/components/chart/chart.ts +1 -1
  10. package/src/components/checkbox/checkbox.module.scss +67 -1
  11. package/src/components/checkbox/checkbox.ts +22 -6
  12. package/src/components/colorinput/colorinput.module.scss +1 -0
  13. package/src/components/combobox/combobox.module.scss +4 -1
  14. package/src/components/components.ts +1 -0
  15. package/src/components/dockingview/dockingview.ts +1 -1
  16. package/src/components/gridview/gridview.module.scss +6 -0
  17. package/src/components/input/input.module.scss +1 -1
  18. package/src/components/listbox/listbox.ts +31 -45
  19. package/src/components/messages/messages.module.scss +9 -4
  20. package/src/components/monaco/monaco.ts +1 -2
  21. package/src/components/popup/popup.ts +2 -2
  22. package/src/components/propgrid/progrid.module.scss +13 -5
  23. package/src/components/radio/radio.module.scss +54 -31
  24. package/src/components/radio/radio.ts +12 -1
  25. package/src/components/rating/rating.ts +1 -1
  26. package/src/components/sizers/sizer.ts +17 -5
  27. package/src/components/spreadsheet/spreadsheet.module.scss +6 -0
  28. package/src/components/tabs/tabs.module.scss +2 -0
  29. package/src/components/tabs/tabs.ts +1 -0
  30. package/src/components/textarea/textarea.module.scss +9 -0
  31. package/src/components/textarea/textarea.ts +1 -0
  32. package/src/components/themes.scss +1 -0
  33. package/src/components/timeline/timeline.module.scss +147 -0
  34. package/src/components/timeline/timeline.ts +146 -0
  35. package/src/components/treeview/treeview.module.scss +6 -1
  36. package/src/components/treeview/treeview.ts +17 -22
  37. package/src/components/video/video.module.scss +5 -2
  38. package/src/components/video/video.ts +14 -1
  39. package/src/core/component.ts +31 -2
  40. package/src/core/core_pdf.ts +17 -0
  41. package/src/core/core_react.ts +12 -18
  42. package/src/core/core_shortcuts.ts +2 -1
  43. package/src/core/core_svg.ts +9 -6
@@ -20,6 +20,7 @@
20
20
  --treeview-background: var( --background-primary );
21
21
 
22
22
  --treeitem-color: var( --text-primary );
23
+ --treeitem-icon-color: var( --icon-color );
23
24
 
24
25
  --treeitem-backgound-hover: var( --background-secondary );
25
26
  --treeitem-color-hover: var( --text-primary );
@@ -79,7 +80,7 @@
79
80
 
80
81
  &>.label {
81
82
  --label-color: var( --treeitem-color );
82
- --label-icon-color: var( --treeitem-color );
83
+ --label-icon-color: var( --treeitem-icon-color );
83
84
 
84
85
  gap: 4px;
85
86
 
@@ -210,6 +211,10 @@
210
211
  border-color: var( --border );
211
212
  color: var( --treeview-item-color-disabled );
212
213
 
214
+ // the texts and the icons of the items
215
+ --treeitem-color: var( --treeview-item-color-disabled );
216
+ --treeitem-icon-color: var( --treeview-item-color-disabled );
217
+
213
218
  &>.body {
214
219
  .x4viewport {
215
220
  pointer-events: none;
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { asap } from '../../core/core_tools';
18
18
  import { EventCallback } from '../../core/core_events';
19
- import { Component, ComponentEvent, ComponentEvents, ComponentProps, EvClick, EvDblClick, EvSelectionChange, componentFromDOM } from '../../core/component';
19
+ import { Component, ComponentEvent, ComponentEvents, ComponentProps, EvClick, EvDblClick, EvSelectionChange } from '../../core/component';
20
20
 
21
21
  import { ScrollView, Viewport } from '../viewport/viewport';
22
22
  import { Label, SimpleText } from '../label/label';
@@ -73,6 +73,7 @@ export interface TreeviewEvents extends ComponentEvents {
73
73
  * ```
74
74
  * --treeview-background
75
75
  * --treeitem-color
76
+ * --treeitem-icon-color
76
77
  * --treeitem-backgound-hover
77
78
  * --treeitem-color-hover
78
79
  * --treeitem-background-sel
@@ -244,30 +245,24 @@ export class Treeview extends Component<TreeviewProps,TreeviewEvents> {
244
245
  }
245
246
 
246
247
  private _on_click( ev: UIEvent ) {
247
- let target = ev.target as HTMLElement;
248
-
249
- while( target && target!=this.dom ) {
250
- const c = componentFromDOM( target );
251
-
252
- if( c && c.hasClass("item") ) {
253
- const id = c.getInternalData( "id" );
254
-
255
- const fev: ComponentEvent = { context:id };
256
- if (ev.type == 'click') {
257
- this.fire('click', fev );
258
- }
259
- else {
260
- this.fire('dblClick', fev );
261
- }
262
-
263
- if (!fev.defaultPrevented) {
264
- this._selectItem( id, c );
265
- }
248
+ // an item of this tree, not of a component around it
249
+ const c = Component.closest( ev.target as Element, ".item" );
250
+ if( c && this.contains( c ) ) {
251
+ const id = c.getInternalData( "id" );
252
+
253
+ const fev: ComponentEvent = { context:id };
254
+ if (ev.type == 'click') {
255
+ this.fire('click', fev );
256
+ }
257
+ else {
258
+ this.fire('dblClick', fev );
259
+ }
266
260
 
267
- return;
261
+ if (!fev.defaultPrevented) {
262
+ this._selectItem( id, c );
268
263
  }
269
264
 
270
- target = target.parentElement;
265
+ return;
271
266
  }
272
267
 
273
268
  this.clearSelection( );
@@ -20,11 +20,14 @@
20
20
  background-color: black;
21
21
  position: relative;
22
22
 
23
+ // the size of the box, whatever the size of the stream (a <video> keeps its own size
24
+ // with only left / right): the image fitted in it, black bands around
23
25
  .vplayer {
24
26
  position: absolute;
25
27
  left: 0;
26
28
  top: 0;
27
- right: 0;
28
- bottom: 0;
29
+ width: 100%;
30
+ height: 100%;
31
+ object-fit: contain;
29
32
  }
30
33
  }
@@ -23,7 +23,8 @@ interface VideoProps extends ComponentProps {
23
23
  autoplay?: boolean;
24
24
  muted?: boolean;
25
25
  playsInline?: boolean;
26
- stream: MediaStream;
26
+ src?: string; // a file to play (url); a stream, when there is one, is shown instead
27
+ stream?: MediaStream; // a camera, a screen, a canvas (captureStream)
27
28
  }
28
29
 
29
30
  /**
@@ -55,6 +56,10 @@ export class Video extends Box {
55
56
  this.playsInline = props.playsInline;
56
57
  }
57
58
 
59
+ if( props.src ) {
60
+ this.src = props.src;
61
+ }
62
+
58
63
  this.stream = props.stream;
59
64
  }
60
65
 
@@ -86,6 +91,14 @@ export class Video extends Box {
86
91
  this.player.playsInline = set;
87
92
  }
88
93
 
94
+ get src( ) {
95
+ return this.player.src;
96
+ }
97
+
98
+ set src( url: string ) {
99
+ this.player.src = url;
100
+ }
101
+
89
102
  set stream( stream: MediaStream ) {
90
103
  this.player.srcObject = stream;
91
104
  }
@@ -959,7 +959,24 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
959
959
  */
960
960
 
961
961
  parentElement<T extends Component>( cls?: Constructor<T> ): T {
962
- return Component.parentElement<T>( this.dom, cls );
962
+ return Component.parentElement<T>( this.dom, cls );
963
+ }
964
+
965
+ /**
966
+ * The nearest component whose element matches a css selector: this one, or one of its ancestors.
967
+ * @returns null when there is none
968
+ */
969
+
970
+ closest<T extends Component = Component>( selector: string ): T {
971
+ return Component.closest<T>( this.dom, selector );
972
+ }
973
+
974
+ /**
975
+ * true when a node, or the element of a component, is the element of this one or inside it
976
+ */
977
+
978
+ contains( other: Component | Node ): boolean {
979
+ return this.dom.contains( other instanceof Component ? other.dom : other );
963
980
  }
964
981
 
965
982
  /**
@@ -992,10 +1009,22 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
992
1009
 
993
1010
  dom = dom.parentElement;
994
1011
  }
995
-
1012
+
996
1013
  return null;
997
1014
  }
998
1015
 
1016
+ /**
1017
+ * The nearest component whose element matches a css selector: the one of dom, or one of its ancestors.
1018
+ * @returns null when there is none
1019
+ * @example
1020
+ * // in a click handler: the item hit, wherever the click is in it
1021
+ * const item = Component.closest( ev.target as Element, ".x4timeline > .item" );
1022
+ */
1023
+
1024
+ static closest<T extends Component = Component>( dom: Element, selector: string ): T {
1025
+ return componentFromDOM<T>( dom.closest( selector ) );
1026
+ }
1027
+
999
1028
  /**
1000
1029
  * Returns the first child element as a Component instance.
1001
1030
  * @returns The first child component, or `null` if none exists.
@@ -1543,6 +1543,23 @@ export class X4PDFBuilder {
1543
1543
 
1544
1544
  return result
1545
1545
  }
1546
+
1547
+ /**
1548
+ * the document as a file, of type application/pdf (build, its streams not compressed)
1549
+ */
1550
+
1551
+ buildBlob(): Blob {
1552
+ return new Blob([this.build() as BlobPart], { type: 'application/pdf' })
1553
+ }
1554
+
1555
+ /**
1556
+ * an object url of the document: the src of an iframe, the href of a link, window.open.
1557
+ * URL.revokeObjectURL( url ) frees it when it is no longer shown
1558
+ */
1559
+
1560
+ buildURL(): string {
1561
+ return URL.createObjectURL(this.buildBlob())
1562
+ }
1546
1563
  }
1547
1564
 
1548
1565
  /*
@@ -13,25 +13,19 @@
13
13
  * Use of this source code is governed by an MIT-style license
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  *
16
- * to use you must:
17
- *
18
- * 1. add this to your tsconfig.json
16
+ * JSX in .tsx files:
17
+ *
18
+ * 1. in tsconfig.json (esbuild reads it too):
19
19
  * "compilerOptions": {
20
- * ...
21
- * "jsx": "preserve",
22
- * ...
23
- * }
24
- *
25
- * 2. be sure that esbuild has this:
26
- * jsxFactory: "x4create_element",
27
- * loader: { ".ts": "tsx" }
28
- *
29
- *
30
- * after that, all things like that will be ok
31
- *
32
- * import { x4_create_element } from "x4react"
33
- * const xx = <h1>This is a title</h1>
34
- *
20
+ * "jsx": "react",
21
+ * "jsxFactory": "x4_react.create_element"
22
+ * },
23
+ * "files": [ "node_modules/x4js/src/x4tsx.d.ts" ] // the JSX types of x4 (ref)
24
+ *
25
+ * 2. in each .tsx file, the factory imported:
26
+ * import { Label, VBox, x4_react } from "x4js";
27
+ * const box = <VBox><Label text="Hello" /></VBox>;
28
+ *
35
29
  */
36
30
 
37
31
  import { Component } from './component';
@@ -51,7 +51,8 @@ interface Keys {
51
51
  key: string;
52
52
  }
53
53
 
54
- const isMac = /mac|iphone|ipad/i.test( navigator.platform ?? "" );
54
+ /** true on a Mac, an iPhone or an iPad: Mod is Cmd there */
55
+ export const isMac = /mac|iphone|ipad/i.test( navigator.platform ?? "" );
55
56
 
56
57
  /**
57
58
  * "Shift+Mod+K" -> shift, ctrl (cmd on a Mac), k
@@ -557,7 +557,8 @@ export class SvgText extends SvgItem {
557
557
  * @returns The current `SvgText` instance for chaining.
558
558
  */
559
559
  fontWeight( weight: 'light' | 'normal' | 'bold' ): this {
560
- return this.setAttr( 'font-weight', weight );
560
+ // "light" is no value of font-weight: its number
561
+ return this.setAttr( 'font-weight', weight=='light' ? '300' : weight );
561
562
  }
562
563
 
563
564
  /**
@@ -583,23 +584,25 @@ export class SvgText extends SvgItem {
583
584
  }
584
585
 
585
586
  /**
586
- * change the vertical alignment
587
+ * change the vertical alignment: y is the top, the middle, the bottom or the baseline
588
+ * of the text. dominant-baseline, read by all the browsers (alignment-baseline is not
589
+ * by Firefox before 149)
587
590
  */
588
591
  verticalAlign( align: 'top' | 'center' | 'bottom' | 'baseline' ): this {
589
592
 
590
593
  let al;
591
594
  switch( align ) {
592
595
  case 'top': al = 'hanging'; break;
593
- case 'center': al = 'middle'; break;
594
- case 'bottom': al = 'baseline'; break;
595
- case 'baseline': al = 'mathematical'; break;
596
+ case 'center': al = 'central'; break;
597
+ case 'bottom': al = 'ideographic'; break;
598
+ case 'baseline': al = 'alphabetic'; break;
596
599
  default:
597
600
  // If an invalid alignment is provided, do nothing and return this for chaining.
598
601
  console.warn(`Invalid verticalAlign value: ${align}. Must be 'top', 'center', 'bottom', or 'baseline'.`);
599
602
  return this;
600
603
  }
601
604
 
602
- return this.setAttr( 'alignment-baseline', al );
605
+ return this.setAttr( 'dominant-baseline', al );
603
606
  }
604
607
  }
605
608