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
@@ -17,6 +17,13 @@
17
17
  import { EventMap, EventSource } from './core_events';
18
18
 
19
19
 
20
+ interface TimerEntry {
21
+ cb: Function;
22
+ id: number;
23
+ clear: Function;
24
+ }
25
+
26
+
20
27
  /**
21
28
  * CoreElement
22
29
  *
@@ -77,10 +84,14 @@ import { EventMap, EventSource } from './core_events';
77
84
  * el.clearInterval("poll");
78
85
  * ```
79
86
  */
87
+
80
88
  export class CoreElement<E extends EventMap = EventMap> {
81
89
 
82
90
  #events: EventSource<E>;
83
- #timers: Map<string, Function>;
91
+ #timers: Map<string, TimerEntry>;
92
+ #cleanup: Function[];
93
+
94
+ /** changed to stop timers when object is down
84
95
 
85
96
  private __startTimer( name: string, ms: number, repeat: boolean, callback: ( ) => void ) {
86
97
  if (!this.#timers) {
@@ -102,6 +113,69 @@ export class CoreElement<E extends EventMap = EventMap> {
102
113
  const clear = this.#timers?.get(name);
103
114
  if (clear) { clear(); }
104
115
  }
116
+ */
117
+
118
+ private __startTimer(name: string, ms: number, repeat: boolean, callback: () => void) {
119
+ if (!this.#timers) {
120
+ this.#timers = new Map();
121
+ }
122
+ else {
123
+ this.__stopTimer(name);
124
+ }
125
+
126
+ // Weak reference only: the native timer must not keep the element alive.
127
+ // The callback itself is stored in #timers, held by the element,
128
+ // so the element remains collectable while a timer is active.
129
+ const ref = new WeakRef(this); // avoid keeping a ref on this.
130
+
131
+ let tick: () => void;
132
+
133
+ if (repeat) {
134
+ tick = () => {
135
+ const self = ref.deref();
136
+ if (!self) {
137
+ clearInterval(id);
138
+ return;
139
+ }
140
+
141
+ self.#timers.get(name)!.cb();
142
+ };
143
+
144
+ const id = setInterval( tick, ms );
145
+
146
+ this.#timers.set(name, {
147
+ cb: callback,
148
+ id,
149
+ clear( ) { clearInterval(id); }
150
+ });
151
+ }
152
+ else {
153
+ tick = () => {
154
+ const self = ref.deref();
155
+ if (!self) {
156
+ return;
157
+ }
158
+
159
+ // One-shot: remove the entry before firing so the map stays clean.
160
+ self.#timers.delete(name);
161
+ callback();
162
+ };
163
+
164
+ this.#timers.set(name, {
165
+ cb: callback,
166
+ id: setTimeout(tick, ms),
167
+ clear() { clearTimeout(this.id); }
168
+ });
169
+ }
170
+ }
171
+
172
+ private __stopTimer(name: string) {
173
+ const entry = this.#timers?.get(name);
174
+ if (entry) {
175
+ entry.clear();
176
+ this.#timers.delete(name);
177
+ }
178
+ }
105
179
 
106
180
  /**
107
181
  * Sets a timeout that executes a callback function after a specified delay.
@@ -110,19 +184,19 @@ export class CoreElement<E extends EventMap = EventMap> {
110
184
  * @param ms - The delay in milliseconds before the callback is executed.
111
185
  * @param callback - The function to execute after the delay.
112
186
  */
113
-
114
- setTimeout( name: string, ms: number, callback: () => void ) {
115
- this.__startTimer( name, ms, false, callback );
187
+
188
+ setTimeout(name: string, ms: number, callback: () => void) {
189
+ this.__startTimer(name, ms, false, callback);
116
190
  }
117
-
191
+
118
192
  /**
119
193
  * Clears a previously set timeout.
120
194
  * @param name - The name of the timeout to clear.
121
- * @link setTimeout
195
+ * @see setTimeout
122
196
  */
123
197
 
124
- clearTimeout( name: string ) {
125
- this.__stopTimer( name );
198
+ clearTimeout(name: string) {
199
+ this.__stopTimer(name);
126
200
  }
127
201
 
128
202
  /**
@@ -133,31 +207,59 @@ export class CoreElement<E extends EventMap = EventMap> {
133
207
  * @param callback - The function to execute after the delay.
134
208
  */
135
209
 
136
- setInterval( name: string, ms: number, callback: ( ) => void ) {
137
- this.__startTimer( name, ms, true, callback );
210
+ setInterval(name: string, ms: number, callback: () => void) {
211
+ this.__startTimer(name, ms, true, callback);
138
212
  }
139
213
 
140
214
  /**
141
215
  * Clears a previously set interval.
142
216
  * @param name - The name of the interval to clear.
143
- * @link setInterval
217
+ * @see setInterval
144
218
  */
145
219
 
146
- clearInterval( name: string ) {
147
- this.__stopTimer( name );
220
+ clearInterval(name: string) {
221
+ this.__stopTimer(name);
148
222
  }
149
223
 
150
224
  /**
151
225
  * Clears all timeouts and intervals currently managed by this instance.
152
226
  * This stops all scheduled callbacks and removes their references.
153
- * @link setTimeout
227
+ * @see setTimeout
154
228
  */
155
- clearTimeouts( ) {
156
- for( const [id,val] of this.#timers ) {
157
- val( );
229
+
230
+ clearTimeouts() {
231
+ if (!this.#timers) {
232
+ return;
233
+ }
234
+
235
+ // Entries no longer mutate the map in clear(), so plain iteration is safe.
236
+ for (const entry of this.#timers.values()) {
237
+ entry.clear();
158
238
  }
159
-
160
- this.#timers.clear( );
239
+
240
+ this.#timers.clear();
241
+ }
242
+
243
+ /**
244
+ * add a cleanup function to the cleanup list
245
+ * @see cleanUp
246
+ */
247
+
248
+ addCleanup( fn : Function ) {
249
+ if( !this.#cleanup ) {
250
+ this.#cleanup = [];
251
+ }
252
+
253
+ this.#cleanup.push( fn );
254
+ }
255
+
256
+ /**
257
+ * called when element is removed from dom
258
+ */
259
+
260
+ cleanUp( ) {
261
+ this.clearTimeouts( );
262
+ this.#cleanup?.forEach( x => x() );
161
263
  }
162
264
 
163
265
  // :: EVENTS ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@@ -169,21 +271,21 @@ export class CoreElement<E extends EventMap = EventMap> {
169
271
  * @param name - The name of the event to listen for.
170
272
  * @param listener - The callback function to execute when the event is fired.
171
273
  * @returns An object containing an `off()` method to unsubscribe the listener.
172
- * @link fire
274
+ * @see fire
173
275
  * attach to an event
174
276
  */
175
277
 
176
- on<K extends keyof E>( name: K, listener: ( ev: E[K] ) => void ) {
177
- console.assert( listener!==undefined && listener!==null );
278
+ on<K extends keyof E>(name: K, listener: (ev: E[K]) => void) {
279
+ console.assert(listener !== undefined && listener !== null);
178
280
 
179
- if( !this.#events ) {
180
- this.#events = new EventSource( this );
281
+ if (!this.#events) {
282
+ this.#events = new EventSource(this);
181
283
  }
182
-
183
- this.#events.addListener( name, listener );
284
+
285
+ this.#events.addListener(name, listener);
184
286
  return {
185
- off: ( ) => {
186
- this.#events.removeListener( name, listener );
287
+ off: () => {
288
+ this.#events.removeListener(name, listener);
187
289
  }
188
290
  }
189
291
  }
@@ -193,15 +295,15 @@ export class CoreElement<E extends EventMap = EventMap> {
193
295
  * If the listener was not found or no events were registered, this method does nothing.
194
296
  * @param name - The name of the event from which to remove the listener.
195
297
  * @param listener - The specific listener function to remove.
196
- * @link on
197
- * @link fire
298
+ * @see on
299
+ * @see fire
198
300
  */
199
301
 
200
- off<K extends keyof E>( name: K, listener: ( ev: E[K] ) => void ) {
201
- console.assert( listener!==undefined && listener!==null );
302
+ off<K extends keyof E>(name: K, listener: (ev: E[K]) => void) {
303
+ console.assert(listener !== undefined && listener !== null);
202
304
 
203
- if( this.#events ) {
204
- this.#events.removeListener( name, listener );
305
+ if (this.#events) {
306
+ this.#events.removeListener(name, listener);
205
307
  }
206
308
  }
207
309
 
@@ -210,13 +312,13 @@ export class CoreElement<E extends EventMap = EventMap> {
210
312
  * If no listeners are registered for the event name, or if no EventSource has been initialized, this method does nothing.
211
313
  * @param name - The name of the event to fire.
212
314
  * @param ev - The payload (event object) to pass to the listeners.
213
- * @link on
214
- * @link off
315
+ * @see on
316
+ * @see off
215
317
  */
216
318
 
217
- fire<K extends keyof E>( name: K, ev: E[K] ) {
218
- if( this.#events ) {
219
- this.#events.fire( name, ev );
319
+ fire<K extends keyof E>(name: K, ev: E[K]) {
320
+ if (this.#events) {
321
+ this.#events.fire(name, ev);
220
322
  }
221
323
  }
222
324
  }
@@ -124,6 +124,7 @@ function serialize(val: PDFValue): string {
124
124
  return String(val)
125
125
  }
126
126
 
127
+ // @internal
127
128
  class Ref {
128
129
  id: number
129
130
  constructor(id: number) { this.id = id }
@@ -267,7 +267,7 @@ class SvgItem {
267
267
 
268
268
  /**
269
269
  * add a class
270
- * @param name class name to add
270
+ * @param cls class name to add
271
271
  */
272
272
 
273
273
  addClass( cls: string ): this {
@@ -287,7 +287,7 @@ class SvgItem {
287
287
 
288
288
  /**
289
289
  * remove a class
290
- * @param name class name to remove
290
+ * @param cls class name to remove
291
291
  */
292
292
 
293
293
  removeClass( cls: string ): this {
@@ -424,8 +424,6 @@ export function oneshot(callback: () => void, ms = 0) {
424
424
 
425
425
  /**
426
426
  * prepend 0 to a value to a given length
427
- * @param value
428
- * @param length
429
427
  */
430
428
 
431
429
  export function pad(what: any, size: number, ch: string = '0') {
@@ -466,7 +464,7 @@ export function sprintf(format: string, ...args: any[]) {
466
464
  /**
467
465
  * inverse of camel case
468
466
  * theThingToCase -> the-thing-to-case
469
- * @param {String} str
467
+ * @param string
470
468
  */
471
469
 
472
470
  export function pascalCase(string: string): string {
@@ -524,8 +522,6 @@ export function date_format(date: Date, options?: any): string {
524
522
 
525
523
  /**
526
524
  * difference between 2 dates
527
- * @param date
528
- * @param options
529
525
  * @return text
530
526
  */
531
527
 
package/src/x4doc.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file x4-doc.ts
9
+ * @author Etienne Cochard
10
+ *
11
+ * @copyright (c) 2026 R-libre ingenierie
12
+ *
13
+ * Use of this source code is governed by an MIT-style license
14
+ * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
+ **/
16
+
17
+
18
+ /**
19
+ * do not use, only to generate full x4documentation
20
+ */
21
+
22
+ export * from "./x4.js"
23
+ export * from "./components/monaco/monaco.js"