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/compiledScripts/UIRectangle.d.ts +4 -0
- package/compiledScripts/UIRectangle.js +19 -4
- package/compiledScripts/UIRectangle.js.map +2 -2
- package/compiledScripts/UITableView.d.ts +1 -0
- package/compiledScripts/UITableView.js +1 -0
- package/compiledScripts/UITableView.js.map +2 -2
- package/compiledScripts/UITextView.js +12 -0
- package/compiledScripts/UITextView.js.map +2 -2
- package/compiledScripts/UIView.d.ts +19 -1
- package/compiledScripts/UIView.js +176 -81
- package/compiledScripts/UIView.js.map +2 -2
- package/package.json +1 -1
- package/scripts/UIRectangle.ts +35 -5
- package/scripts/UITableView.ts +2 -0
- package/scripts/UITextView.ts +72 -47
- package/scripts/UIView.ts +230 -83
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uicore-ts",
|
|
3
|
-
"version": "1.1.
|
|
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",
|
package/scripts/UIRectangle.ts
CHANGED
|
@@ -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()
|
package/scripts/UITableView.ts
CHANGED
package/scripts/UITextView.ts
CHANGED
|
@@ -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 ===
|
|
485
|
-
return fontSize * 1.2
|
|
500
|
+
if (lineHeight === "normal") {
|
|
501
|
+
return fontSize * 1.2
|
|
486
502
|
}
|
|
487
|
-
if (lineHeight.endsWith(
|
|
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
|
-
}
|
|
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
|
|
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
|