x4js 2.2.47 → 2.2.50

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 (56) hide show
  1. package/README.md +4 -3
  2. package/package.json +3 -2
  3. package/src/components/boxes/boxes.module.scss +1 -0
  4. package/src/components/breadcrumb/breadcrumb.ts +7 -0
  5. package/src/components/btngroup/btngroup.module.scss +1 -1
  6. package/src/components/button/button.ts +15 -5
  7. package/src/components/calendar/calendar.ts +19 -1
  8. package/src/components/checkbox/checkbox.ts +11 -0
  9. package/src/components/colorinput/colorinput.ts +6 -1
  10. package/src/components/colorpicker/colorpicker.ts +2 -2
  11. package/src/components/combobox/combobox.ts +14 -0
  12. package/src/components/dialog/dialog.ts +6 -2
  13. package/src/components/filedrop/filedrop.ts +10 -0
  14. package/src/components/form/form.ts +4 -1
  15. package/src/components/gauge/gauge.ts +9 -0
  16. package/src/components/gridview/gridview.ts +28 -1
  17. package/src/components/header/header.ts +6 -6
  18. package/src/components/image/image.ts +5 -0
  19. package/src/components/input/input.module.scss +5 -0
  20. package/src/components/input/input.ts +9 -0
  21. package/src/components/keyboard/keyboard.ts +8 -0
  22. package/src/components/label/label.ts +7 -1
  23. package/src/components/link/link.ts +4 -0
  24. package/src/components/listbox/listbox.ts +22 -9
  25. package/src/components/menu/menu.ts +10 -1
  26. package/src/components/messages/messages.ts +6 -0
  27. package/src/components/notification/notification.ts +13 -0
  28. package/src/components/panel/panel.ts +5 -1
  29. package/src/components/popup/popup.module.scss +1 -0
  30. package/src/components/popup/popup.ts +60 -34
  31. package/src/components/progress/progress.ts +8 -0
  32. package/src/components/propgrid/progrid.module.scss +11 -5
  33. package/src/components/propgrid/propgrid.ts +36 -16
  34. package/src/components/rating/rating.ts +6 -0
  35. package/src/components/select/select.ts +1 -0
  36. package/src/components/sizers/sizer.ts +23 -8
  37. package/src/components/slider/slider.ts +7 -0
  38. package/src/components/spreadsheet/spreadsheet.ts +28 -1
  39. package/src/components/switch/switch.ts +7 -0
  40. package/src/components/tabs/tabs.ts +6 -0
  41. package/src/components/tag/tag.ts +11 -0
  42. package/src/components/textarea/textarea.ts +6 -0
  43. package/src/components/textedit/textedit.ts +10 -0
  44. package/src/components/tickline/tickline.ts +9 -0
  45. package/src/components/tooltips/tooltips.ts +12 -2
  46. package/src/components/treeview/treeview.ts +14 -0
  47. package/src/components/viewport/viewport.ts +8 -0
  48. package/src/core/component.ts +44 -43
  49. package/src/core/core_application.ts +16 -4
  50. package/src/core/core_data.ts +1 -4
  51. package/src/core/core_dom.ts +49 -31
  52. package/src/core/core_element.ts +141 -39
  53. package/src/core/core_pdf.ts +1 -0
  54. package/src/core/core_svg.ts +2 -2
  55. package/src/core/core_tools.ts +1 -5
  56. package/src/x4doc.ts +23 -0
@@ -14,11 +14,11 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- import { isArray, UnsafeHtml, isNumber, Rect, Constructor, class_ns, x4_class_ns_sym, IRect } from './core_tools';
17
+ import { isArray, UnsafeHtml, isNumber, Rect, Constructor, class_ns, x4_class_ns_sym } from './core_tools';
18
18
  import { CoreElement } from './core_element';
19
19
  import { AriaAttributes, unitless } from './core_styles';
20
20
  import { CoreEvent, EventMap } from './core_events';
21
- import { addEvent, DOMEventHandler, GlobalDOMEvents } from './core_dom';
21
+ import { addEvent, DOMEventHandler, GlobalDOMEvents, COMPONENT } from './core_dom';
22
22
  import { Application, EvMessage } from './core_application';
23
23
  import { makeState } from './core_state.js';
24
24
 
@@ -30,7 +30,6 @@ type ComponentAttributes = Record<string,string|number|boolean>;
30
30
  type CreateComponentCallBack = ( attrs: Record<string,string> ) => ComponentContent;
31
31
 
32
32
  const FRAGMENT = Symbol( "fragment" );
33
- const COMPONENT = Symbol( "component" );
34
33
 
35
34
  const RE_NUMBER = /^-?\d+(\.\d*)?$/;
36
35
 
@@ -152,7 +151,7 @@ export interface ComponentEvents extends EventMap {
152
151
  * ```
153
152
  */
154
153
 
155
- @class_ns( "x4" )
154
+ @class_ns("x4")
156
155
  export class Component<P extends ComponentProps = ComponentProps, E extends ComponentEvents = ComponentEvents>
157
156
  extends CoreElement<E> {
158
157
 
@@ -166,16 +165,16 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
166
165
 
167
166
  #store: Map<string|symbol,any>;
168
167
  #pstate: any;
169
-
170
- constructor( props: P ) {
168
+
169
+ constructor(props: P) {
171
170
  super( );
172
171
 
173
172
  this.props = props; // copy ?
174
173
 
175
174
  if( props.existingDOM ) {
176
175
  this.dom = props.existingDOM;
177
- }
178
- else {
176
+ }
177
+ else {
179
178
  if( props.ns ) {
180
179
  this.dom = document.createElementNS( props.ns, props.tag ?? "div" );
181
180
  }
@@ -242,8 +241,8 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
242
241
  this.addDOMEvent( "created", ( ) => {
243
242
  this.enable( false );
244
243
  } );
244
+ }
245
245
  }
246
- }
247
246
 
248
247
  (this.dom as any)[COMPONENT] = this;
249
248
  }
@@ -281,10 +280,10 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
281
280
  * Multiple classes can be provided as a space-separated string.
282
281
  * @param cls - The CSS class(es) to add.
283
282
  */
284
-
283
+
285
284
  addClass( cls: string ) {
286
285
  if( !cls ) return;
287
-
286
+
288
287
  cls = cls.trim( );
289
288
 
290
289
  if( cls.includes(' ') ) {
@@ -309,13 +308,13 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
309
308
  if( cls=='*' ) {
310
309
  this.dom.classList.value = "";
311
310
  return;
312
- }
311
+ }
313
312
 
314
313
  if( cls.indexOf(' ')>=0 ) {
315
314
  const ccs = cls.split( " " );
316
315
  this.dom.classList.remove(...ccs);
317
- }
318
- else {
316
+ }
317
+ else {
319
318
  this.dom.classList.remove(cls);
320
319
  }
321
320
  }
@@ -351,11 +350,11 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
351
350
  if( cls.indexOf(' ')>=0 ) {
352
351
  const ccs = cls.split( " " );
353
352
  ccs.forEach( toggle );
354
- }
355
- else {
353
+ }
354
+ else {
356
355
  toggle( cls );
357
356
  }
358
- }
357
+ }
359
358
 
360
359
  /**
361
360
  * Sets or removes a CSS class based on a boolean condition.
@@ -368,7 +367,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
368
367
  if( set ) this.addClass(cls);
369
368
  else this.removeClass( cls );
370
369
  return this;
371
- }
370
+ }
372
371
 
373
372
  // :: ATTRIBUTES ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
374
373
 
@@ -383,7 +382,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
383
382
  this.setAttribute( name, attrs[name] );
384
383
  }
385
384
  return this;
386
- }
385
+ }
387
386
 
388
387
  /**
389
388
  * Sets a single HTML attribute on the component's DOM element.
@@ -399,7 +398,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
399
398
  else {
400
399
  this.dom.setAttribute( name, ""+value );
401
400
  }
402
- }
401
+ }
403
402
 
404
403
  /**
405
404
  * Retrieves the value of an HTML attribute from the component's DOM element.
@@ -416,10 +415,12 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
416
415
  * @param name - The suffix of the `data-` attribute (e.g., for `data-foo`, use `"foo"`).
417
416
  * @returns The string value of the `data-*` attribute, or `null` if not present.
418
417
  *
419
- * @cf Component.setIntData, Component.getIntData (number)
420
- * @cf Component.setInternalData, Component.getInternalData (typed data)
421
- */
422
-
418
+ * @see Component.setIntData
419
+ * @see Component.getIntData
420
+ * @see Component.setInternalData
421
+ * @see Component.getInternalData
422
+ */
423
+
423
424
  getData( name: string ) : string {
424
425
  return this.getAttribute( "data-"+name );
425
426
  }
@@ -536,7 +537,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
536
537
  * Appends content to the end of the component's DOM element.
537
538
  * Content can be a single Component, an array of Components, a string, an array of strings,
538
539
  * raw HTML, an array of raw HTML, a number, or a boolean.
539
- * @note
540
+ * @remarks
540
541
  * for simplicity, null is also allowed:
541
542
  * setContent( [
542
543
  * optional ? myControl : null,
@@ -629,7 +630,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
629
630
  /**
630
631
  * Removes a specific child component from this component's DOM element.
631
632
  * @param child - The child component instance to remove.
632
- * @cf clearContent
633
+ * @see clearContent
633
634
  */
634
635
 
635
636
  removeChild( child: Component ) {
@@ -792,8 +793,8 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
792
793
  /**
793
794
  * Sets pointer capture on the component's DOM element for a specific pointer.
794
795
  * @param pointerId - The unique ID of the pointer.
795
- *
796
- * @ex
796
+ *
797
+ * @example
797
798
  * control.on("pointerdown", (ev) => {
798
799
  * ev.preventDefault(); // Prevent default browser actions
799
800
  * control.setCapture(ev.pointerId);
@@ -856,7 +857,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
856
857
  /**
857
858
  * Checks if the component's DOM element is currently visible (i.e., not hidden by `display: none`).
858
859
  * @returns `true` if the component is visible, `false` otherwise.
859
- */
860
+ */
860
861
 
861
862
  isVisible( ) {
862
863
  return (this.dom as HTMLElement).offsetParent !== null;
@@ -942,7 +943,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
942
943
  /**
943
944
  * Returns the previous sibling element as a Component instance.
944
945
  * @returns The previous sibling component, or `null` if none exists.
945
- */
946
+ */
946
947
 
947
948
  prevElement<T extends Component = Component>( ): T {
948
949
  const nxt = this.dom.previousElementSibling;
@@ -960,7 +961,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
960
961
  }
961
962
 
962
963
  /**
963
- *
964
+ *
964
965
  */
965
966
 
966
967
  childCount( ) {
@@ -972,9 +973,9 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
972
973
  * @param dom - The starting DOM node from which to search upwards.
973
974
  * @param cls - Optional. The constructor of the Component type to match.
974
975
  * @returns The matching parent Component instance, or `null` if not found.
975
- */
976
-
977
-
976
+ */
977
+
978
+
978
979
  static parentElement<T extends Component>( dom: Node, cls?: Constructor<T> ): T {
979
980
 
980
981
  while( dom.parentElement ) {
@@ -989,14 +990,14 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
989
990
 
990
991
  dom = dom.parentElement;
991
992
  }
992
-
993
+
993
994
  return null;
994
995
  }
995
996
 
996
997
  /**
997
998
  * Returns the first child element as a Component instance.
998
999
  * @returns The first child component, or `null` if none exists.
999
- */
1000
+ */
1000
1001
 
1001
1002
  firstChild<T extends Component = Component>( ) : T {
1002
1003
  const nxt = this.dom.firstElementChild;
@@ -1006,7 +1007,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
1006
1007
  /**
1007
1008
  * Returns the last child element as a Component instance.
1008
1009
  * @returns The last child component, or `null` if none exists.
1009
- */
1010
+ */
1010
1011
 
1011
1012
  lastChild<T extends Component = Component>( ) : T {
1012
1013
  const nxt = this.dom.lastElementChild;
@@ -1017,19 +1018,19 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
1017
1018
  * Enumerates all child components of this component.
1018
1019
  * @param recursive - If `true`, searches all descendants; otherwise, only direct children.
1019
1020
  * @returns An array of child Component instances.
1020
- */
1021
+ */
1021
1022
 
1022
1023
  enumChildComponents( recursive: boolean ) {
1023
-
1024
+
1024
1025
  const children: Component[] = [];
1025
-
1026
+
1026
1027
  const nodes = this.enumChildNodes( recursive );
1027
1028
  nodes.forEach( ( c: Node ) => {
1028
1029
  const cc = componentFromDOM( c as HTMLElement );
1029
1030
  if( cc ) {
1030
1031
  children.push(cc);
1031
1032
  }
1032
- } );
1033
+ });
1033
1034
 
1034
1035
  return children;
1035
1036
  }
@@ -1186,7 +1187,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
1186
1187
  state.on( "change", ( ) => {
1187
1188
  this.setTimeout( key, 500, ( ) => {
1188
1189
  Application.instance().setStorage( key, JSON.stringify( raw ) );
1189
- });
1190
+ } );
1190
1191
  });
1191
1192
 
1192
1193
  this.#pstate[name] = state;
@@ -1212,7 +1213,7 @@ type ComponentConstructor = {
1212
1213
 
1213
1214
  export function componentFromDOM<T extends Component = Component>( node: Element ) {
1214
1215
  return node ? (node as any)[COMPONENT] as T : null;
1215
- }
1216
+ }
1216
1217
 
1217
1218
  /**
1218
1219
  * Wraps an existing HTMLElement with a new Component instance.
@@ -27,9 +27,15 @@ export interface EvMessage extends CoreEvent {
27
27
  params: any;
28
28
  }
29
29
 
30
+ interface EvWindowResize extends CoreEvent {
31
+ width: number;
32
+ height: number;
33
+ }
34
+
30
35
  export interface ApplicationEvents extends EventMap {
31
36
  global: EvMessage;
32
37
  message: EvMessage;
38
+ resize: EvWindowResize;
33
39
  }
34
40
 
35
41
  // singleton
@@ -104,6 +110,15 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
104
110
  else {
105
111
  window.addEventListener( "load", loaded, { once: true } );
106
112
  }
113
+
114
+ const resize = ( ) => {
115
+ this.fire( "resize", {
116
+ width: window.innerWidth,
117
+ height: window.innerHeight,
118
+ } );
119
+ }
120
+
121
+ window.addEventListener('resize', resize, { passive: true });
107
122
  }
108
123
 
109
124
  /**
@@ -171,10 +186,7 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
171
186
  }
172
187
 
173
188
  /**
174
- * Retrieves an environment variable from the application's environment map.
175
- * @param name - The name of the environment variable.
176
- * @param def_value - An optional default value to return if the variable is not found.
177
- * @returns The value of the environment variable, or `def_value` if not found.
189
+ *
178
190
  */
179
191
 
180
192
  static fireGlobal( msg: string, params?: any ) {
@@ -602,7 +602,6 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
602
602
 
603
603
  /**
604
604
  *
605
- * @param records
606
605
  */
607
606
 
608
607
  async load( url?: string ) {
@@ -666,7 +665,7 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
666
665
 
667
666
  /**
668
667
  *
669
- * @param data
668
+ * @param rec
670
669
  */
671
670
 
672
671
  public appendRaw( rec: T ) {
@@ -1206,8 +1205,6 @@ export class DataView extends CoreElement<DataViewEventMap>
1206
1205
 
1207
1206
  /**
1208
1207
  *
1209
- * @param columns
1210
- * @param ascending
1211
1208
  */
1212
1209
 
1213
1210
  public sort( props: SortProp[] ) {
@@ -14,6 +14,8 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
+ export const COMPONENT = Symbol( "component" );
18
+
17
19
  /** @ignore this events must be defined on domNode (do not bubble) */
18
20
  export const unbubbleEvents = {
19
21
  mouseleave: 1, mouseenter: 1, load: 1, unload: 1, scroll: 1, focus: 1, blur: 1, rowexit: 1, beforeunload: 1, stop: 1,
@@ -33,9 +35,33 @@ let mutObserver: MutationObserver = null;
33
35
 
34
36
  const observeMutation = (mutations: MutationRecord[], observer: MutationObserver): void => {
35
37
 
38
+ // moves are handled this way
39
+ const added = new Set<Node>( );
40
+ const removed = new Set<Node>( );
41
+
42
+ for( const mutation of mutations ) {
43
+ if( mutation.type == "childList" ) {
44
+ mutation.addedNodes.forEach( n => {
45
+ if( removed.has( n ) ) {
46
+ removed.delete( n );
47
+ }
48
+ else {
49
+ added.add( n );
50
+ }
51
+ } );
52
+
53
+ mutation.removedNodes.forEach( n => {
54
+ if( added.has( n ) ) {
55
+ added.delete( n );
56
+ }
57
+ else {
58
+ removed.add( n );
59
+ }
60
+ } );
61
+ }
62
+ }
63
+
36
64
  const sendEvent = ( node: Node, code: "created" | "removed" ) => {
37
- // console.log( "notify", node, code );
38
-
39
65
  const store = event_handlers.get( node );
40
66
  if ( store && store[code] ) {
41
67
  node.dispatchEvent( new Event( code, {} ) );
@@ -53,26 +79,17 @@ const observeMutation = (mutations: MutationRecord[], observer: MutationObserver
53
79
  }
54
80
 
55
81
  if( !create ) {
82
+ const core = (node as any)[COMPONENT];
83
+ if( core && core.cleanUp ) { //<yes: dirty hack
84
+ core.cleanUp();
85
+ }
86
+
56
87
  sendEvent( node, "removed" );
57
88
  }
58
89
  }
59
90
 
60
-
61
- for (const mutation of mutations) {
62
- if( mutation.type=="childList" ) {
63
- if( mutation.addedNodes ) {
64
- mutation.addedNodes.forEach( node => {
65
- notify( node, true );
66
- } );
67
- }
68
-
69
- if( mutation.removedNodes ) {
70
- mutation.removedNodes.forEach( node => {
71
- notify( node, false );
72
- } );
73
- }
74
- }
75
- }
91
+ added.forEach( n => { if( n.isConnected ) notify( n, true ); } );
92
+ removed.forEach( n => { if( !n.isConnected ) notify( n, false ); } );
76
93
  }
77
94
 
78
95
 
@@ -144,17 +161,27 @@ export function dispatchEvent(ev: Event) {
144
161
 
145
162
  export function addEvent( node: Node, name: string, handler: DOMEventHandler, prepend = false ) {
146
163
 
164
+ if( !mutObserver ) {
165
+ mutObserver = new MutationObserver( observeMutation )
166
+ mutObserver.observe( document.body, {childList: true,subtree: true} );
167
+ }
168
+
147
169
  if( name=="removed" || name=="created" ) {
148
- if( !mutObserver ) {
149
- mutObserver = new MutationObserver( observeMutation )
150
- mutObserver.observe( document.body, {childList: true,subtree: true} );
170
+ const core = (node as any)[COMPONENT];
171
+ if( core && core.addClass ) { //<yes: dirty hack
172
+ core.addClass( "x4:mut")
151
173
  }
152
174
  }
153
175
  else if( name=="resized" ) {
154
176
  if (!sizeObserver) {
155
177
  sizeObserver = new ResizeObserver( observeSize );
156
178
  }
157
-
179
+
180
+ const core = (node as any)[COMPONENT];
181
+ if( core && core.addClass ) { //<yes: dirty hack
182
+ core.addClass( "x4:sze")
183
+ }
184
+
158
185
  sizeObserver.observe( node as Element );
159
186
  }
160
187
 
@@ -470,12 +497,3 @@ export interface GlobalDOMEvents {
470
497
  created?: ( ev: Event ) => void; // occurs when inserted in the dom
471
498
  removed?: ( ev: Event ) => void; // occurs when removed from dom
472
499
  }
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-