uicore-ts 1.1.116 → 1.1.121

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.116",
3
+ "version": "1.1.121",
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",
@@ -311,7 +311,7 @@ export class UIButton extends UIBaseButton {
311
311
 
312
312
  let bounds = this.bounds
313
313
 
314
- this.hoverText = this.titleLabel?.text ?? ""
314
+ this.hoverText = this.hoverText ?? this.titleLabel?.text ?? ""
315
315
 
316
316
  // Image only if text is not present
317
317
  if (IS_NOT(this.imageView.hidden) && !IS(this.titleLabel?.text)) {
package/scripts/UICore.ts CHANGED
@@ -10,7 +10,7 @@ export class UICore extends UIObject {
10
10
 
11
11
  rootViewController: UIViewController
12
12
 
13
- paddingLength = 20
13
+
14
14
 
15
15
  static RootViewControllerClass: typeof UIViewController
16
16
  static main: UICore
@@ -24,7 +24,7 @@ export class UICore extends UIObject {
24
24
 
25
25
  }
26
26
 
27
- constructor(rootDivElementID: string, rootViewControllerClass: typeof UIViewController) {
27
+ constructor(rootDivElementID: string, rootViewControllerClass: typeof UIViewController, public paddingLength = 20) {
28
28
 
29
29
  super()
30
30
 
@@ -118,9 +118,11 @@ export class UIDialogView<ViewType extends UIView = UIView> extends UIView {
118
118
 
119
119
 
120
120
  containerView.addSubview(this)
121
+ this.view.setNeedsLayoutUpToRootView()
121
122
 
122
123
  if (animated) {
123
124
 
125
+ UIView.layoutViewsIfNeeded()
124
126
  this.layoutSubviews()
125
127
 
126
128
  UIView.animateViewOrViewsWithDurationDelayAndFunction(
@@ -250,6 +252,8 @@ export class UIDialogView<ViewType extends UIView = UIView> extends UIView {
250
252
 
251
253
  this.view.style.zIndex = "" + this.zIndex
252
254
 
255
+ this.view.setNeedsLayout()
256
+
253
257
  // this.view.style.maxHeight = "" + (bounds.height - margin * 2).integerValue + "px";
254
258
  // this.view.style.maxWidth = "" + (bounds.width - margin * 2).integerValue + "px";
255
259
 
@@ -127,25 +127,47 @@ export class UITextView extends UIView {
127
127
  this._intrinsicSizesCache = {}
128
128
  }
129
129
 
130
- private _getMeasurementStyles(): TextMeasurementStyle {
130
+ private _getMeasurementStyles(): TextMeasurementStyle | null {
131
131
  if (this._cachedMeasurementStyles) {
132
132
  return this._cachedMeasurementStyles
133
133
  }
134
134
 
135
+ // Ensure element is in document
136
+ if (!this.viewHTMLElement.isConnected) {
137
+ return null
138
+ }
139
+
140
+ // Force a layout flush ONCE to ensure computed styles are available
141
+ // This is only paid once per style change, then we use cached values
142
+ this.viewHTMLElement.offsetHeight
143
+
135
144
  const computed = window.getComputedStyle(this.viewHTMLElement)
136
- const fontSize = parseFloat(computed.fontSize)
145
+ const fontSizeStr = computed.fontSize
146
+ const fontSize = parseFloat(fontSizeStr)
147
+
148
+ if (!fontSize || isNaN(fontSize)) {
149
+ return null
150
+ }
151
+
152
+ const lineHeight = this._parseLineHeight(computed.lineHeight, fontSize)
153
+
154
+ if (isNaN(lineHeight)) {
155
+ return null
156
+ }
157
+
158
+ const font = [
159
+ computed.fontStyle || 'normal',
160
+ computed.fontVariant || 'normal',
161
+ computed.fontWeight || 'normal',
162
+ fontSize + 'px',
163
+ computed.fontFamily || 'sans-serif'
164
+ ].join(" ")
137
165
 
138
166
  this._cachedMeasurementStyles = {
139
- font: [
140
- computed.fontStyle,
141
- computed.fontVariant,
142
- computed.fontWeight,
143
- computed.fontSize,
144
- computed.fontFamily
145
- ].join(" "),
167
+ font: font,
146
168
  fontSize: fontSize,
147
- lineHeight: this._parseLineHeight(computed.lineHeight, fontSize),
148
- whiteSpace: computed.whiteSpace,
169
+ lineHeight: lineHeight,
170
+ whiteSpace: computed.whiteSpace || 'normal',
149
171
  paddingLeft: parseFloat(computed.paddingLeft) || 0,
150
172
  paddingRight: parseFloat(computed.paddingRight) || 0,
151
173
  paddingTop: parseFloat(computed.paddingTop) || 0,
@@ -491,7 +513,7 @@ export class UITextView extends UIView {
491
513
  _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any
492
514
 
493
515
  private _useFastMeasurement: boolean | undefined
494
- private _cachedMeasurementStyles: TextMeasurementStyle | undefined
516
+ private _cachedMeasurementStyles: TextMeasurementStyle | undefined | null
495
517
 
496
518
  override usesVirtualLayoutingForIntrinsicSizing = NO
497
519
 
@@ -513,7 +535,32 @@ export class UITextView extends UIView {
513
535
  var result = cacheObject.valueForKeyPath(keyPath)
514
536
 
515
537
  if (IS_LIKE_NULL(result)) {
516
- result = super.intrinsicContentHeight(constrainingWidth)
538
+ // Determine if we should use fast measurement
539
+ const shouldUseFastPath = this._useFastMeasurement ?? this._shouldUseFastMeasurement()
540
+
541
+ if (shouldUseFastPath) {
542
+ // Fast path: use UITextMeasurement with pre-extracted styles
543
+ const styles = this._getMeasurementStyles()
544
+
545
+ // If styles are invalid (element not properly initialized), fall back to DOM
546
+ if (styles) {
547
+ const size = UITextMeasurement.calculateTextSize(
548
+ this.viewHTMLElement,
549
+ this.text || this.innerHTML,
550
+ constrainingWidth || undefined,
551
+ undefined,
552
+ styles
553
+ )
554
+ result = size.height
555
+ } else {
556
+ // Styles not ready, use DOM measurement
557
+ result = super.intrinsicContentHeight(constrainingWidth)
558
+ }
559
+ } else {
560
+ // Fallback: DOM-based measurement for complex content
561
+ result = super.intrinsicContentHeight(constrainingWidth)
562
+ }
563
+
517
564
  cacheObject.setValueForKeyPath(keyPath, result)
518
565
  }
519
566
 
@@ -539,7 +586,32 @@ export class UITextView extends UIView {
539
586
  var result = cacheObject.valueForKeyPath(keyPath)
540
587
 
541
588
  if (IS_LIKE_NULL(result)) {
542
- result = super.intrinsicContentWidth(constrainingHeight)
589
+ // Determine if we should use fast measurement
590
+ const shouldUseFastPath = this._useFastMeasurement ?? this._shouldUseFastMeasurement()
591
+
592
+ if (shouldUseFastPath) {
593
+ // Fast path: use UITextMeasurement with pre-extracted styles
594
+ const styles = this._getMeasurementStyles()
595
+
596
+ // If styles are invalid (element not properly initialized), fall back to DOM
597
+ if (styles) {
598
+ const size = UITextMeasurement.calculateTextSize(
599
+ this.viewHTMLElement,
600
+ this.text || this.innerHTML,
601
+ undefined,
602
+ constrainingHeight || undefined,
603
+ styles
604
+ )
605
+ result = size.width
606
+ } else {
607
+ // Styles not ready, use DOM measurement
608
+ result = super.intrinsicContentWidth(constrainingHeight)
609
+ }
610
+ } else {
611
+ // Fallback: DOM-based measurement for complex content
612
+ result = super.intrinsicContentWidth(constrainingHeight)
613
+ }
614
+
543
615
  cacheObject.setValueForKeyPath(keyPath, result)
544
616
  }
545
617
 
package/scripts/UIView.ts CHANGED
@@ -5,7 +5,21 @@ import { UICore } from "./UICore"
5
5
  import "./UICoreExtensions"
6
6
  import type { UIDialogView } from "./UIDialogView"
7
7
  import { UILocalizedTextObject } from "./UIInterfaces"
8
- import { FIRST, FIRST_OR_NIL, IF, IS, IS_DEFINED, IS_NIL, IS_NOT, nil, NO, RETURNER, UIObject, YES } from "./UIObject"
8
+ import {
9
+ FIRST,
10
+ FIRST_OR_NIL,
11
+ IF,
12
+ IS,
13
+ IS_DEFINED,
14
+ IS_NIL,
15
+ IS_NOT,
16
+ IS_NOT_LIKE_NULL,
17
+ nil,
18
+ NO,
19
+ RETURNER,
20
+ UIObject,
21
+ YES
22
+ } from "./UIObject"
9
23
  import { UIPoint } from "./UIPoint"
10
24
  import { UIRectangle } from "./UIRectangle"
11
25
  import { UIViewController } from "./UIViewController"
@@ -642,13 +656,17 @@ export class UIView extends UIObject {
642
656
  }
643
657
 
644
658
 
645
- set hoverText(hoverText: string) {
646
- this.viewHTMLElement.setAttribute("title", hoverText)
659
+ set hoverText(hoverText: string | undefined | null) {
660
+ if (IS_NOT_LIKE_NULL(hoverText)) {
661
+ this.viewHTMLElement.setAttribute("title", hoverText)
662
+ }
663
+ else {
664
+ this.viewHTMLElement.removeAttribute("title")
665
+ }
647
666
  }
648
667
 
649
-
650
668
  get hoverText() {
651
- return this.viewHTMLElement.getAttribute("title") ?? ""
669
+ return this.viewHTMLElement.getAttribute("title")
652
670
  }
653
671
 
654
672