uicore-ts 1.1.88 → 1.1.101

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uicore-ts",
3
- "version": "1.1.88",
3
+ "version": "1.1.101",
4
4
  "description": "UICore is a library to build native-like user interfaces using pure Typescript. No HTML is needed at all. Components are described as TS classes and all user interactions are handled explicitly. This library is strongly inspired by the UIKit framework that is used in IOS. In addition, UICore has tools to handle URL based routing, array sorting and filtering and adds a number of other utilities for convenience.",
5
5
  "main": "compiledScripts/index.js",
6
6
  "types": "compiledScripts/index.d.ts",
@@ -1,4 +1,4 @@
1
- import { FIRST_OR_NIL, IS, IS_DEFINED, IS_NIL, IS_NOT_NIL, nil, NO, UIObject, YES } from "./UIObject"
1
+ import { FIRST_OR_NIL, IS, IS_DEFINED, IS_NIL, IS_NOT_LIKE_NULL, IS_NOT_NIL, nil, NO, UIObject, YES } from "./UIObject"
2
2
  import { UIPoint } from "./UIPoint"
3
3
  import { UIView } from "./UIView"
4
4
 
@@ -380,6 +380,22 @@ export class UIRectangle extends UIObject {
380
380
 
381
381
  }
382
382
 
383
+ rectangleByAddingWidth(widthToAdd: number, centeredOnPosition = 0) {
384
+
385
+ const result = this.rectangleWithWidth(this.width + widthToAdd, centeredOnPosition)
386
+
387
+ return result
388
+
389
+ }
390
+
391
+ rectangleByAddingHeight(heightToAdd: number, centeredOnPosition = 0) {
392
+
393
+ const result = this.rectangleWithHeight(this.height + heightToAdd, centeredOnPosition)
394
+
395
+ return result
396
+
397
+ }
398
+
383
399
 
384
400
  rectangleWithRelativeValues(
385
401
  relativeXPosition: number,
@@ -891,15 +907,15 @@ export class UIRectangle extends UIObject {
891
907
  rectangleByEnforcingMinAndMaxSizes(centeredOnXPosition = 0, centeredOnYPosition = 0) {
892
908
  return this.rectangleWithHeight(
893
909
  [
894
- [this.height, this.maxHeight].min(),
910
+ [this.height, this.maxHeight].filter(value => IS_NOT_LIKE_NULL(value)).min(),
895
911
  this.minHeight
896
- ].max(),
912
+ ].filter(value => IS_NOT_LIKE_NULL(value)).max(),
897
913
  centeredOnYPosition
898
914
  ).rectangleWithWidth(
899
915
  [
900
- [this.width, this.maxWidth].min(),
916
+ [this.width, this.maxWidth].filter(value => IS_NOT_LIKE_NULL(value)).min(),
901
917
  this.minWidth
902
- ].max(),
918
+ ].filter(value => IS_NOT_LIKE_NULL(value)).max(),
903
919
  centeredOnXPosition
904
920
  )
905
921
  }
@@ -911,6 +927,20 @@ export class UIRectangle extends UIObject {
911
927
  }
912
928
 
913
929
 
930
+ override toString() {
931
+
932
+ const result = "[" + this.class.name + "] { x: " + this.x + ", y: " + this.y + ", " +
933
+ "height: " + this.height.toFixed(2) + ", width: " + this.height.toFixed(2) + " }"
934
+
935
+ return result
936
+
937
+ }
938
+
939
+ get [Symbol.toStringTag]() {
940
+ return this.toString()
941
+ }
942
+
943
+
914
944
  // Bounding box
915
945
  static boundingBoxForPoints(points: string | any[]) {
916
946
  const result = new UIRectangle()
@@ -56,6 +56,8 @@ export class UITableView extends UINativeScrollView {
56
56
  _isDrawVisibleRowsScheduled = NO
57
57
  _shouldAnimateNextLayout?: boolean
58
58
 
59
+ override usesVirtualLayoutingForIntrinsicSizing = NO
60
+
59
61
  override animationDuration = 0.25
60
62
 
61
63
 
@@ -30,9 +30,11 @@ export class UITextView extends UIView {
30
30
  static defaultTextColor = UIColor.blackColor
31
31
  static notificationTextColor = UIColor.redColor
32
32
 
33
+ // Global caches for all UILabels
33
34
  static _intrinsicHeightCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any
34
35
  static _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any
35
36
 
37
+ // Local cache for this instance if the label changes often
36
38
  _intrinsicHeightCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any
37
39
  _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any
38
40
 
@@ -41,12 +43,11 @@ export class UITextView extends UIView {
41
43
  static _pxToPt: number
42
44
  _text?: string
43
45
 
44
- private _useFastMeasurement: boolean | undefined;
45
- private _cachedMeasurementStyles: TextMeasurementStyle | undefined;
46
+ private _useFastMeasurement: boolean | undefined
47
+ private _cachedMeasurementStyles: TextMeasurementStyle | undefined
46
48
 
47
49
  override usesVirtualLayoutingForIntrinsicSizing = NO
48
50
 
49
-
50
51
  constructor(
51
52
  elementID?: string,
52
53
  textViewType: string | ValueOf<typeof UITextView.type> = UITextView.type.paragraph,
@@ -228,10 +229,11 @@ export class UITextView extends UIView {
228
229
  this._intrinsicWidthCache = new UIObject() as any
229
230
  }
230
231
  // Invalidate measurement strategy when text changes significantly
231
- this._useFastMeasurement = undefined;
232
- this._intrinsicSizesCache = {};
232
+ this._useFastMeasurement = undefined
233
+ this._intrinsicSizesCache = {}
233
234
  this.invalidateMeasurementStrategy()
234
235
  this._invalidateMeasurementStyles()
236
+ this.clearIntrinsicSizeCache()
235
237
 
236
238
  this.setNeedsLayout()
237
239
 
@@ -279,13 +281,13 @@ export class UITextView extends UIView {
279
281
  this._intrinsicWidthCache = new UIObject() as any // MEETOD LUUA!!!!
280
282
 
281
283
  this._invalidateMeasurementStyles() // Invalidate when font changes
282
-
284
+ this.clearIntrinsicSizeCache()
285
+
283
286
  }
284
287
 
285
288
  }
286
289
 
287
290
 
288
-
289
291
  useAutomaticFontSize(minFontSize: number = nil, maxFontSize: number = nil) {
290
292
 
291
293
  this._automaticFontSizeSelection = YES
@@ -402,6 +404,20 @@ export class UITextView extends UIView {
402
404
  }
403
405
 
404
406
 
407
+ if (isNaN(result) || (!result && !this.text) ) {
408
+
409
+ // console.error("Failed to calculate intrinsic height (" + this.elementID + ")", this, this.viewHTMLElement)
410
+ var asd = 1
411
+
412
+ result = super.intrinsicContentHeight(constrainingWidth)
413
+
414
+ cacheObject.setValueForKeyPath(keyPath, result)
415
+
416
+ var asdasd = 1
417
+
418
+
419
+ }
420
+
405
421
  return result
406
422
 
407
423
  }
@@ -445,20 +461,20 @@ export class UITextView extends UIView {
445
461
 
446
462
  // Call this when styles change (fontSize, padding, etc.)
447
463
  private _invalidateMeasurementStyles(): void {
448
- this._cachedMeasurementStyles = undefined;
449
- UITextMeasurement.invalidateElement(this.viewHTMLElement);
450
- this._intrinsicSizesCache = {};
464
+ this._cachedMeasurementStyles = undefined
465
+ UITextMeasurement.invalidateElement(this.viewHTMLElement)
466
+ this._intrinsicSizesCache = {}
451
467
  }
452
468
 
453
469
  // Extract styles ONCE and cache them (avoids getComputedStyle)
454
470
  private _getMeasurementStyles(): TextMeasurementStyle {
455
471
  if (this._cachedMeasurementStyles) {
456
- return this._cachedMeasurementStyles;
472
+ return this._cachedMeasurementStyles
457
473
  }
458
474
 
459
475
  // Only call getComputedStyle once and cache the result
460
- const computed = window.getComputedStyle(this.viewHTMLElement);
461
- const fontSize = parseFloat(computed.fontSize);
476
+ const computed = window.getComputedStyle(this.viewHTMLElement)
477
+ const fontSize = parseFloat(computed.fontSize)
462
478
 
463
479
  this._cachedMeasurementStyles = {
464
480
  font: [
@@ -467,7 +483,7 @@ export class UITextView extends UIView {
467
483
  computed.fontWeight,
468
484
  computed.fontSize,
469
485
  computed.fontFamily
470
- ].join(' '),
486
+ ].join(" "),
471
487
  fontSize: fontSize,
472
488
  lineHeight: this._parseLineHeight(computed.lineHeight, fontSize),
473
489
  whiteSpace: computed.whiteSpace,
@@ -475,23 +491,23 @@ export class UITextView extends UIView {
475
491
  paddingRight: parseFloat(computed.paddingRight) || 0,
476
492
  paddingTop: parseFloat(computed.paddingTop) || 0,
477
493
  paddingBottom: parseFloat(computed.paddingBottom) || 0
478
- };
494
+ }
479
495
 
480
- return this._cachedMeasurementStyles;
496
+ return this._cachedMeasurementStyles
481
497
  }
482
498
 
483
499
  private _parseLineHeight(lineHeight: string, fontSize: number): number {
484
- if (lineHeight === 'normal') {
485
- return fontSize * 1.2;
500
+ if (lineHeight === "normal") {
501
+ return fontSize * 1.2
486
502
  }
487
- if (lineHeight.endsWith('px')) {
488
- return parseFloat(lineHeight);
503
+ if (lineHeight.endsWith("px")) {
504
+ return parseFloat(lineHeight)
489
505
  }
490
- const numericLineHeight = parseFloat(lineHeight);
506
+ const numericLineHeight = parseFloat(lineHeight)
491
507
  if (!isNaN(numericLineHeight)) {
492
- return fontSize * numericLineHeight;
508
+ return fontSize * numericLineHeight
493
509
  }
494
- return fontSize * 1.2;
510
+ return fontSize * 1.2
495
511
  }
496
512
 
497
513
  // Override the intrinsic size method
@@ -499,73 +515,82 @@ export class UITextView extends UIView {
499
515
  constrainingHeight: number = 0,
500
516
  constrainingWidth: number = 0
501
517
  ): UIRectangle {
502
- const cacheKey = "h_" + constrainingHeight + "__w_" + constrainingWidth;
503
- const cachedResult = this._intrinsicSizesCache[cacheKey];
518
+ const cacheKey = "h_" + constrainingHeight + "__w_" + constrainingWidth
519
+ const cachedResult = this._intrinsicSizesCache[cacheKey]
504
520
  if (cachedResult) {
505
- return cachedResult;
521
+ return cachedResult
506
522
  }
507
523
 
508
524
  // Determine measurement strategy
509
- const shouldUseFastPath = this._useFastMeasurement ?? this._shouldUseFastMeasurement();
525
+ const shouldUseFastPath = this._useFastMeasurement ?? this._shouldUseFastMeasurement()
510
526
 
511
- let result: UIRectangle;
527
+ let result: UIRectangle
512
528
 
513
529
  if (shouldUseFastPath) {
514
530
  // Fast path: canvas-based measurement with pre-extracted styles
515
- const styles = this._getMeasurementStyles();
531
+ const styles = this._getMeasurementStyles()
516
532
  const size = UITextMeasurement.calculateTextSize(
517
533
  this.viewHTMLElement,
518
534
  this.text || this.innerHTML,
519
535
  constrainingWidth || undefined,
520
536
  constrainingHeight || undefined,
521
537
  styles // Pass pre-computed styles to avoid getComputedStyle!
522
- );
523
- result = new UIRectangle(0, 0, size.height, size.width);
524
- } else {
538
+ )
539
+ result = new UIRectangle(0, 0, size.height, size.width)
540
+ }
541
+ else {
525
542
  // Fallback: original DOM-based measurement for complex content
526
- result = super.intrinsicContentSizeWithConstraints(constrainingHeight, constrainingWidth);
543
+ result = super.intrinsicContentSizeWithConstraints(constrainingHeight, constrainingWidth)
544
+ }
545
+
546
+ if (isNaN(result.height) || isNaN(result.width)) {
547
+
548
+ // console.error("Failed to calculate intrinsic height (" + this.elementID + ")", this)
549
+ var asd = 1
550
+
551
+ // Fallback: original DOM-based measurement
552
+ result = super.intrinsicContentSizeWithConstraints(constrainingHeight, constrainingWidth)
553
+
554
+
527
555
  }
528
556
 
529
- this._intrinsicSizesCache[cacheKey] = result.copy();
530
- return result;
557
+ this._intrinsicSizesCache[cacheKey] = result.copy()
558
+ return result
531
559
  }
532
560
 
533
561
  // Helper to determine if we can use fast measurement
534
562
  private _shouldUseFastMeasurement(): boolean {
535
- const content = this.text || this.innerHTML;
563
+ const content = this.text || this.innerHTML
536
564
 
537
565
  // If using dynamic innerHTML with parameters, use DOM measurement
538
566
  if (this._innerHTMLKey || this._localizedTextObject) {
539
- return false;
567
+ return false
540
568
  }
541
569
 
542
570
  // Check for notification badges
543
571
  if (this.notificationAmount > 0) {
544
- return false; // Has span with colored text
572
+ return false // Has span with colored text
545
573
  }
546
574
 
547
575
  // Check content complexity
548
- const hasComplexHTML = /<(?!\/?(b|i|em|strong|span|br)\b)[^>]+>/i.test(content);
576
+ const hasComplexHTML = /<(?!\/?(b|i|em|strong|span|br)\b)[^>]+>/i.test(content)
549
577
 
550
- return !hasComplexHTML;
578
+ return !hasComplexHTML
551
579
  }
552
580
 
553
581
  // Optional: Allow manual override for specific instances
554
582
  setUseFastMeasurement(useFast: boolean): void {
555
- this._useFastMeasurement = useFast;
556
- this._intrinsicSizesCache = {};
583
+ this._useFastMeasurement = useFast
584
+ this._intrinsicSizesCache = {}
557
585
  }
558
586
 
559
587
  // Optional: Force re-evaluation of measurement strategy
560
588
  invalidateMeasurementStrategy(): void {
561
- this._useFastMeasurement = undefined;
562
- this._invalidateMeasurementStyles();
589
+ this._useFastMeasurement = undefined
590
+ this._invalidateMeasurementStyles()
563
591
  }
564
592
 
565
593
 
566
-
567
-
568
-
569
594
  override intrinsicContentSize() {
570
595
 
571
596
  // This works but is slow