uicore-ts 1.1.118 → 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.
@@ -98,19 +98,32 @@ const _UITextView = class extends import_UIView.UIView {
98
98
  if (this._cachedMeasurementStyles) {
99
99
  return this._cachedMeasurementStyles;
100
100
  }
101
+ if (!this.viewHTMLElement.isConnected) {
102
+ return null;
103
+ }
104
+ this.viewHTMLElement.offsetHeight;
101
105
  const computed = window.getComputedStyle(this.viewHTMLElement);
102
- const fontSize = parseFloat(computed.fontSize);
106
+ const fontSizeStr = computed.fontSize;
107
+ const fontSize = parseFloat(fontSizeStr);
108
+ if (!fontSize || isNaN(fontSize)) {
109
+ return null;
110
+ }
111
+ const lineHeight = this._parseLineHeight(computed.lineHeight, fontSize);
112
+ if (isNaN(lineHeight)) {
113
+ return null;
114
+ }
115
+ const font = [
116
+ computed.fontStyle || "normal",
117
+ computed.fontVariant || "normal",
118
+ computed.fontWeight || "normal",
119
+ fontSize + "px",
120
+ computed.fontFamily || "sans-serif"
121
+ ].join(" ");
103
122
  this._cachedMeasurementStyles = {
104
- font: [
105
- computed.fontStyle,
106
- computed.fontVariant,
107
- computed.fontWeight,
108
- computed.fontSize,
109
- computed.fontFamily
110
- ].join(" "),
123
+ font,
111
124
  fontSize,
112
- lineHeight: this._parseLineHeight(computed.lineHeight, fontSize),
113
- whiteSpace: computed.whiteSpace,
125
+ lineHeight,
126
+ whiteSpace: computed.whiteSpace || "normal",
114
127
  paddingLeft: parseFloat(computed.paddingLeft) || 0,
115
128
  paddingRight: parseFloat(computed.paddingRight) || 0,
116
129
  paddingTop: parseFloat(computed.paddingTop) || 0,
@@ -301,6 +314,7 @@ const _UITextView = class extends import_UIView.UIView {
301
314
  return maxFittingFontSize;
302
315
  }
303
316
  intrinsicContentHeight(constrainingWidth = 0) {
317
+ var _a;
304
318
  const keyPath = this.viewHTMLElement.innerHTML + "_csf_" + this._getFontCacheKey() + "." + ("" + constrainingWidth).replace(new RegExp("\\.", "g"), "_");
305
319
  let cacheObject = _UITextView._intrinsicHeightCache;
306
320
  if (this.changesOften) {
@@ -308,7 +322,24 @@ const _UITextView = class extends import_UIView.UIView {
308
322
  }
309
323
  var result = cacheObject.valueForKeyPath(keyPath);
310
324
  if ((0, import_UIObject.IS_LIKE_NULL)(result)) {
311
- result = super.intrinsicContentHeight(constrainingWidth);
325
+ const shouldUseFastPath = (_a = this._useFastMeasurement) != null ? _a : this._shouldUseFastMeasurement();
326
+ if (shouldUseFastPath) {
327
+ const styles = this._getMeasurementStyles();
328
+ if (styles) {
329
+ const size = import_UITextMeasurement.UITextMeasurement.calculateTextSize(
330
+ this.viewHTMLElement,
331
+ this.text || this.innerHTML,
332
+ constrainingWidth || void 0,
333
+ void 0,
334
+ styles
335
+ );
336
+ result = size.height;
337
+ } else {
338
+ result = super.intrinsicContentHeight(constrainingWidth);
339
+ }
340
+ } else {
341
+ result = super.intrinsicContentHeight(constrainingWidth);
342
+ }
312
343
  cacheObject.setValueForKeyPath(keyPath, result);
313
344
  }
314
345
  if (isNaN(result) || !result && !this.text) {
@@ -318,6 +349,7 @@ const _UITextView = class extends import_UIView.UIView {
318
349
  return result;
319
350
  }
320
351
  intrinsicContentWidth(constrainingHeight = 0) {
352
+ var _a;
321
353
  const keyPath = this.viewHTMLElement.innerHTML + "_csf_" + this._getFontCacheKey() + "." + ("" + constrainingHeight).replace(new RegExp("\\.", "g"), "_");
322
354
  let cacheObject = _UITextView._intrinsicWidthCache;
323
355
  if (this.changesOften) {
@@ -325,7 +357,24 @@ const _UITextView = class extends import_UIView.UIView {
325
357
  }
326
358
  var result = cacheObject.valueForKeyPath(keyPath);
327
359
  if ((0, import_UIObject.IS_LIKE_NULL)(result)) {
328
- result = super.intrinsicContentWidth(constrainingHeight);
360
+ const shouldUseFastPath = (_a = this._useFastMeasurement) != null ? _a : this._shouldUseFastMeasurement();
361
+ if (shouldUseFastPath) {
362
+ const styles = this._getMeasurementStyles();
363
+ if (styles) {
364
+ const size = import_UITextMeasurement.UITextMeasurement.calculateTextSize(
365
+ this.viewHTMLElement,
366
+ this.text || this.innerHTML,
367
+ void 0,
368
+ constrainingHeight || void 0,
369
+ styles
370
+ );
371
+ result = size.width;
372
+ } else {
373
+ result = super.intrinsicContentWidth(constrainingHeight);
374
+ }
375
+ } else {
376
+ result = super.intrinsicContentWidth(constrainingHeight);
377
+ }
329
378
  cacheObject.setValueForKeyPath(keyPath, result);
330
379
  }
331
380
  return result;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../scripts/UITextView.ts"],
4
- "sourcesContent": ["import { UIColor } from \"./UIColor\"\nimport { UILocalizedTextObject } from \"./UIInterfaces\"\nimport { FIRST, IS_LIKE_NULL, nil, NO, UIObject, ValueOf, YES } from \"./UIObject\"\nimport { UIRectangle } from \"./UIRectangle\"\nimport { TextMeasurementStyle, UITextMeasurement } from \"./UITextMeasurement\"\nimport { UIView, UIViewBroadcastEvent } from \"./UIView\"\n\n\nexport class UITextView extends UIView {\n \n //#region Static Properties\n \n static defaultTextColor = UIColor.blackColor\n static notificationTextColor = UIColor.redColor\n \n // Global caches for all UILabels\n static _intrinsicHeightCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n static _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n \n static _ptToPx: number\n static _pxToPt: number\n \n static type = {\n \"paragraph\": \"p\",\n \"header1\": \"h1\",\n \"header2\": \"h2\",\n \"header3\": \"h3\",\n \"header4\": \"h4\",\n \"header5\": \"h5\",\n \"header6\": \"h6\",\n \"textArea\": \"textarea\",\n \"textField\": \"input\",\n \"span\": \"span\",\n \"label\": \"label\"\n } as const\n \n static textAlignment = {\n \"left\": \"flex-start\",\n \"center\": \"center\",\n \"right\": \"flex-end\",\n \"justify\": \"stretch\"\n } as const\n \n //#endregion\n \n //#region Constructor\n \n constructor(\n elementID?: string,\n textViewType: string | ValueOf<typeof UITextView.type> = UITextView.type.paragraph,\n viewHTMLElement = null\n ) {\n \n super(elementID, viewHTMLElement, textViewType)\n \n this.text = \"\"\n \n this.style.overflow = \"hidden\"\n this.style.textOverflow = \"ellipsis\"\n this.isSingleLine = YES\n \n this.textColor = this.textColor\n \n this.userInteractionEnabled = YES;\n \n (this as UITextView).configureWithObject({\n style: {\n display: \"flex\",\n flexDirection: \"column\", // Ensures vertical stacking logic\n \n // 'safe' ensures that if content overflows, it aligns to the start (top)\n // instead of overflowing upwards or downwards equally.\n justifyContent: \"safe center\",\n alignItems: \"flex-start\", // Keeps text left-aligned (change to \"center\" for horizontal center)\n \n // Optional: ensure text wraps if it gets too long\n whiteSpace: \"normal\",\n wordWrap: \"break-word\",\n overflowWrap: \"break-word\"\n }\n })\n \n if (textViewType == UITextView.type.textArea) {\n this.pausesPointerEvents = YES\n this.addTargetForControlEvent(\n UIView.controlEvent.PointerUpInside,\n (sender, event) => sender.focus()\n )\n }\n }\n \n //#endregion\n \n //#region Lifecycle Methods\n \n override didReceiveBroadcastEvent(event: UIViewBroadcastEvent) {\n super.didReceiveBroadcastEvent(event)\n }\n \n override willMoveToSuperview(superview: UIView) {\n super.willMoveToSuperview(superview)\n }\n \n override layoutSubviews() {\n super.layoutSubviews()\n \n if (this._automaticFontSizeSelection) {\n this.fontSize = UITextView.automaticallyCalculatedFontSize(\n new UIRectangle(0, 0, 1 *\n this.viewHTMLElement.offsetHeight, 1 *\n this.viewHTMLElement.offsetWidth),\n this.intrinsicContentSize(),\n this.fontSize,\n this._minFontSize,\n this._maxFontSize\n )\n }\n }\n \n //#endregion\n \n //#region Measurement & Sizing - Private Methods\n \n private _invalidateMeasurementStyles(): void {\n this._cachedMeasurementStyles = undefined\n UITextMeasurement.invalidateElement(this.viewHTMLElement)\n this._intrinsicSizesCache = {}\n }\n \n private _getMeasurementStyles(): TextMeasurementStyle {\n if (this._cachedMeasurementStyles) {\n return this._cachedMeasurementStyles\n }\n \n const computed = window.getComputedStyle(this.viewHTMLElement)\n const fontSize = parseFloat(computed.fontSize)\n \n this._cachedMeasurementStyles = {\n font: [\n computed.fontStyle,\n computed.fontVariant,\n computed.fontWeight,\n computed.fontSize,\n computed.fontFamily\n ].join(\" \"),\n fontSize: fontSize,\n lineHeight: this._parseLineHeight(computed.lineHeight, fontSize),\n whiteSpace: computed.whiteSpace,\n paddingLeft: parseFloat(computed.paddingLeft) || 0,\n paddingRight: parseFloat(computed.paddingRight) || 0,\n paddingTop: parseFloat(computed.paddingTop) || 0,\n paddingBottom: parseFloat(computed.paddingBottom) || 0\n }\n \n return this._cachedMeasurementStyles\n }\n \n private _parseLineHeight(lineHeight: string, fontSize: number): number {\n if (lineHeight === \"normal\") {\n return fontSize * 1.2\n }\n if (lineHeight.endsWith(\"px\")) {\n return parseFloat(lineHeight)\n }\n const numericLineHeight = parseFloat(lineHeight)\n if (!isNaN(numericLineHeight)) {\n return fontSize * numericLineHeight\n }\n return fontSize * 1.2\n }\n \n private _shouldUseFastMeasurement(): boolean {\n const content = this.text || this.innerHTML\n \n if (this._innerHTMLKey || this._localizedTextObject) {\n return false\n }\n \n if (this.notificationAmount > 0) {\n return false\n }\n \n const hasComplexHTML = /<(?!\\/?(b|i|em|strong|span|br)\\b)[^>]+>/i.test(content)\n \n return !hasComplexHTML\n }\n \n //#endregion\n \n //#region Measurement & Sizing - Public Methods\n \n setUseFastMeasurement(useFast: boolean): void {\n this._useFastMeasurement = useFast\n this._intrinsicSizesCache = {}\n }\n \n invalidateMeasurementStrategy(): void {\n this._useFastMeasurement = undefined\n this._invalidateMeasurementStyles()\n }\n \n //#endregion\n \n //#region Getters & Setters - Text Alignment\n \n get textAlignment() {\n // @ts-ignore\n return this.style.alignItems\n }\n \n set textAlignment(textAlignment: ValueOf<typeof UITextView.textAlignment>) {\n this.style.alignItems = textAlignment\n }\n \n //#endregion\n \n //#region Getters & Setters - Text Color\n \n get textColor() {\n return this._textColor\n }\n \n set textColor(color: UIColor) {\n this._textColor = color || UITextView.defaultTextColor\n this.style.color = this._textColor.stringValue\n }\n \n //#endregion\n \n //#region Getters & Setters - Single Line\n \n get isSingleLine() {\n return this._isSingleLine\n }\n \n set isSingleLine(isSingleLine: boolean) {\n this._isSingleLine = isSingleLine\n \n this._intrinsicHeightCache = new UIObject() as any\n this._intrinsicWidthCache = new UIObject() as any\n \n if (isSingleLine) {\n this.style.whiteSpace = \"pre\"\n return\n }\n \n this.style.whiteSpace = \"pre-wrap\"\n this.invalidateMeasurementStrategy()\n }\n \n //#endregion\n \n //#region Getters & Setters - Notification Amount\n \n get notificationAmount() {\n return this._notificationAmount\n }\n \n set notificationAmount(notificationAmount: number) {\n if (this._notificationAmount == notificationAmount) {\n return\n }\n \n this._notificationAmount = notificationAmount\n this.text = this.text\n this.setNeedsLayoutUpToRootView()\n this.notificationAmountDidChange(notificationAmount)\n }\n \n notificationAmountDidChange(notificationAmount: number) {\n }\n \n //#endregion\n \n //#region Getters & Setters - Text Content\n \n get text() {\n return (this._text || this.viewHTMLElement.innerHTML)\n }\n \n set text(text) {\n this._text = text\n var notificationText = \"\"\n if (this.notificationAmount) {\n notificationText = \"<span style=\\\"color: \" + UITextView.notificationTextColor.stringValue + \";\\\">\" +\n (\" (\" + this.notificationAmount + \")\").bold() + \"</span>\"\n }\n \n if (this.viewHTMLElement.innerHTML != this.textPrefix + text + this.textSuffix + notificationText) {\n this.viewHTMLElement.innerHTML = this.textPrefix + FIRST(text, \"\") + this.textSuffix + notificationText\n }\n \n if (this.changesOften) {\n this._intrinsicHeightCache = new UIObject() as any\n this._intrinsicWidthCache = new UIObject() as any\n }\n \n this._useFastMeasurement = undefined\n this._intrinsicSizesCache = {}\n this.invalidateMeasurementStrategy()\n this._invalidateMeasurementStyles()\n this.clearIntrinsicSizeCache()\n \n this.setNeedsLayout()\n }\n \n override set innerHTML(innerHTML: string) {\n this.text = innerHTML\n this.invalidateMeasurementStrategy()\n }\n \n override get innerHTML() {\n return this.viewHTMLElement.innerHTML\n }\n \n setText(key: string, defaultString: string, parameters?: { [x: string]: string | UILocalizedTextObject }) {\n this.setInnerHTML(key, defaultString, parameters)\n this.invalidateMeasurementStrategy()\n }\n \n //#endregion\n \n //#region Getters & Setters - Font Size\n \n get fontSize() {\n const style = this.style.fontSize || window.getComputedStyle(this.viewHTMLElement, null).fontSize\n const result = (parseFloat(style) * UITextView._pxToPt)\n return result\n }\n \n set fontSize(fontSize: number) {\n if (fontSize != this.fontSize) {\n this.style.fontSize = \"\" + fontSize + \"pt\"\n \n this._intrinsicHeightCache = new UIObject() as any\n this._intrinsicWidthCache = new UIObject() as any\n \n this._invalidateFontCache()\n this._invalidateMeasurementStyles()\n this.clearIntrinsicSizeCache()\n }\n }\n \n useAutomaticFontSize(minFontSize: number = nil, maxFontSize: number = nil) {\n this._automaticFontSizeSelection = YES\n this._minFontSize = minFontSize\n this._maxFontSize = maxFontSize\n this.setNeedsLayout()\n }\n \n //#endregion\n \n //#region Font Caching - Private Methods\n \n /**\n * Get a stable cache key for the font without triggering reflow.\n * Only computes font on first access or when font properties change.\n */\n private _getFontCacheKey(): string {\n // Check if font-related properties have changed\n const currentTriggers = {\n fontSize: this.style.fontSize || \"\",\n fontFamily: this.style.fontFamily || \"\",\n fontWeight: this.style.fontWeight || \"\",\n fontStyle: this.style.fontStyle || \"\",\n styleClasses: this.styleClasses.join(\",\")\n }\n \n const hasChanged =\n currentTriggers.fontSize !== this._fontInvalidationTriggers.fontSize ||\n currentTriggers.fontFamily !== this._fontInvalidationTriggers.fontFamily ||\n currentTriggers.fontWeight !== this._fontInvalidationTriggers.fontWeight ||\n currentTriggers.fontStyle !== this._fontInvalidationTriggers.fontStyle ||\n currentTriggers.styleClasses !== this._fontInvalidationTriggers.styleClasses\n \n if (!this._cachedFontKey || hasChanged) {\n // Only access computedStyle when we know something changed\n const computed = this.computedStyle\n this._cachedFontKey = [\n computed.fontStyle,\n computed.fontVariant,\n computed.fontWeight,\n computed.fontSize,\n computed.fontFamily\n ].join(\"_\").replace(/[.\\s]/g, \"_\")\n \n this._fontInvalidationTriggers = currentTriggers\n }\n \n return this._cachedFontKey\n }\n \n /**\n * Invalidate font cache when font properties change\n */\n private _invalidateFontCache(): void {\n this._cachedFontKey = undefined\n }\n \n //#endregion\n \n //#region Static Methods\n \n static _determinePXAndPTRatios() {\n if (UITextView._ptToPx) {\n return\n }\n \n const o = document.createElement(\"div\")\n o.style.width = \"1000pt\"\n document.body.appendChild(o)\n UITextView._ptToPx = o.clientWidth / 1000\n document.body.removeChild(o)\n UITextView._pxToPt = 1 / UITextView._ptToPx\n }\n \n static automaticallyCalculatedFontSize(\n bounds: UIRectangle,\n currentSize: UIRectangle,\n currentFontSize: number,\n minFontSize?: number,\n maxFontSize?: number\n ) {\n minFontSize = FIRST(minFontSize, 1)\n maxFontSize = FIRST(maxFontSize, 100000000000)\n \n const heightMultiplier = bounds.height / (currentSize.height + 1)\n const widthMultiplier = bounds.width / (currentSize.width + 1)\n \n var multiplier = heightMultiplier\n if (heightMultiplier > widthMultiplier) {\n multiplier = widthMultiplier\n }\n \n const maxFittingFontSize = currentFontSize * multiplier\n \n if (maxFittingFontSize > maxFontSize) {\n return maxFontSize\n }\n \n if (minFontSize > maxFittingFontSize) {\n return minFontSize\n }\n \n return maxFittingFontSize\n }\n \n //#endregion\n \n //#region Instance Properties - Text Content\n \n _text?: string\n textPrefix = \"\"\n textSuffix = \"\"\n _notificationAmount = 0\n \n //#endregion\n \n //#region Instance Properties - Styling\n \n _textColor: UIColor = UITextView.defaultTextColor\n _textAlignment?: ValueOf<typeof UITextView.textAlignment>\n _isSingleLine = YES\n \n //#endregion\n \n //#region Instance Properties - Font & Sizing\n \n _minFontSize?: number\n _maxFontSize?: number\n _automaticFontSizeSelection = NO\n \n // Cache for the computed font string\n private _cachedFontKey?: string\n private _fontInvalidationTriggers = {\n fontSize: this.style.fontSize || \"\",\n fontFamily: this.style.fontFamily || \"\",\n fontWeight: this.style.fontWeight || \"\",\n fontStyle: this.style.fontStyle || \"\",\n styleClasses: this.styleClasses.join(\",\")\n }\n \n //#endregion\n \n //#region Instance Properties - Caching & Performance\n \n changesOften = NO\n \n // Local cache for this instance if the label changes often\n _intrinsicHeightCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n \n private _useFastMeasurement: boolean | undefined\n private _cachedMeasurementStyles: TextMeasurementStyle | undefined\n \n override usesVirtualLayoutingForIntrinsicSizing = NO\n \n //#endregion\n \n \n \n override intrinsicContentHeight(constrainingWidth = 0) {\n \n const keyPath = (this.viewHTMLElement.innerHTML + \"_csf_\" + this._getFontCacheKey()) + \".\" +\n (\"\" + constrainingWidth).replace(new RegExp(\"\\\\.\", \"g\"), \"_\")\n \n let cacheObject = UITextView._intrinsicHeightCache\n \n if (this.changesOften) {\n cacheObject = this._intrinsicHeightCache\n }\n \n var result = cacheObject.valueForKeyPath(keyPath)\n \n if (IS_LIKE_NULL(result)) {\n result = super.intrinsicContentHeight(constrainingWidth)\n cacheObject.setValueForKeyPath(keyPath, result)\n }\n \n if (isNaN(result) || (!result && !this.text)) {\n result = super.intrinsicContentHeight(constrainingWidth)\n cacheObject.setValueForKeyPath(keyPath, result)\n }\n \n return result\n }\n \n override intrinsicContentWidth(constrainingHeight = 0) {\n \n const keyPath = (this.viewHTMLElement.innerHTML + \"_csf_\" + this._getFontCacheKey()) + \".\" +\n (\"\" + constrainingHeight).replace(new RegExp(\"\\\\.\", \"g\"), \"_\")\n \n let cacheObject = UITextView._intrinsicWidthCache\n \n if (this.changesOften) {\n cacheObject = this._intrinsicWidthCache\n }\n \n var result = cacheObject.valueForKeyPath(keyPath)\n \n if (IS_LIKE_NULL(result)) {\n result = super.intrinsicContentWidth(constrainingHeight)\n cacheObject.setValueForKeyPath(keyPath, result)\n }\n \n return result\n }\n \n \n // Override addStyleClass to invalidate font cache\n override addStyleClass(styleClass: string) {\n super.addStyleClass(styleClass)\n this._invalidateFontCache()\n }\n \n // Override removeStyleClass to invalidate font cache\n override removeStyleClass(styleClass: string) {\n super.removeStyleClass(styleClass)\n this._invalidateFontCache()\n }\n \n \n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { UIColor } from \"./UIColor\"\nimport { UILocalizedTextObject } from \"./UIInterfaces\"\nimport { FIRST, IS_LIKE_NULL, nil, NO, UIObject, ValueOf, YES } from \"./UIObject\"\nimport { UIRectangle } from \"./UIRectangle\"\nimport { TextMeasurementStyle, UITextMeasurement } from \"./UITextMeasurement\"\nimport { UIView, UIViewBroadcastEvent } from \"./UIView\"\n\n\nexport class UITextView extends UIView {\n \n //#region Static Properties\n \n static defaultTextColor = UIColor.blackColor\n static notificationTextColor = UIColor.redColor\n \n // Global caches for all UILabels\n static _intrinsicHeightCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n static _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n \n static _ptToPx: number\n static _pxToPt: number\n \n static type = {\n \"paragraph\": \"p\",\n \"header1\": \"h1\",\n \"header2\": \"h2\",\n \"header3\": \"h3\",\n \"header4\": \"h4\",\n \"header5\": \"h5\",\n \"header6\": \"h6\",\n \"textArea\": \"textarea\",\n \"textField\": \"input\",\n \"span\": \"span\",\n \"label\": \"label\"\n } as const\n \n static textAlignment = {\n \"left\": \"flex-start\",\n \"center\": \"center\",\n \"right\": \"flex-end\",\n \"justify\": \"stretch\"\n } as const\n \n //#endregion\n \n //#region Constructor\n \n constructor(\n elementID?: string,\n textViewType: string | ValueOf<typeof UITextView.type> = UITextView.type.paragraph,\n viewHTMLElement = null\n ) {\n \n super(elementID, viewHTMLElement, textViewType)\n \n this.text = \"\"\n \n this.style.overflow = \"hidden\"\n this.style.textOverflow = \"ellipsis\"\n this.isSingleLine = YES\n \n this.textColor = this.textColor\n \n this.userInteractionEnabled = YES;\n \n (this as UITextView).configureWithObject({\n style: {\n display: \"flex\",\n flexDirection: \"column\", // Ensures vertical stacking logic\n \n // 'safe' ensures that if content overflows, it aligns to the start (top)\n // instead of overflowing upwards or downwards equally.\n justifyContent: \"safe center\",\n alignItems: \"flex-start\", // Keeps text left-aligned (change to \"center\" for horizontal center)\n \n // Optional: ensure text wraps if it gets too long\n whiteSpace: \"normal\",\n wordWrap: \"break-word\",\n overflowWrap: \"break-word\"\n }\n })\n \n if (textViewType == UITextView.type.textArea) {\n this.pausesPointerEvents = YES\n this.addTargetForControlEvent(\n UIView.controlEvent.PointerUpInside,\n (sender, event) => sender.focus()\n )\n }\n }\n \n //#endregion\n \n //#region Lifecycle Methods\n \n override didReceiveBroadcastEvent(event: UIViewBroadcastEvent) {\n super.didReceiveBroadcastEvent(event)\n }\n \n override willMoveToSuperview(superview: UIView) {\n super.willMoveToSuperview(superview)\n }\n \n override layoutSubviews() {\n super.layoutSubviews()\n \n if (this._automaticFontSizeSelection) {\n this.fontSize = UITextView.automaticallyCalculatedFontSize(\n new UIRectangle(0, 0, 1 *\n this.viewHTMLElement.offsetHeight, 1 *\n this.viewHTMLElement.offsetWidth),\n this.intrinsicContentSize(),\n this.fontSize,\n this._minFontSize,\n this._maxFontSize\n )\n }\n }\n \n //#endregion\n \n //#region Measurement & Sizing - Private Methods\n \n private _invalidateMeasurementStyles(): void {\n this._cachedMeasurementStyles = undefined\n UITextMeasurement.invalidateElement(this.viewHTMLElement)\n this._intrinsicSizesCache = {}\n }\n \n private _getMeasurementStyles(): TextMeasurementStyle | null {\n if (this._cachedMeasurementStyles) {\n return this._cachedMeasurementStyles\n }\n \n // Ensure element is in document\n if (!this.viewHTMLElement.isConnected) {\n return null\n }\n \n // Force a layout flush ONCE to ensure computed styles are available\n // This is only paid once per style change, then we use cached values\n this.viewHTMLElement.offsetHeight\n \n const computed = window.getComputedStyle(this.viewHTMLElement)\n const fontSizeStr = computed.fontSize\n const fontSize = parseFloat(fontSizeStr)\n \n if (!fontSize || isNaN(fontSize)) {\n return null\n }\n \n const lineHeight = this._parseLineHeight(computed.lineHeight, fontSize)\n \n if (isNaN(lineHeight)) {\n return null\n }\n \n const font = [\n computed.fontStyle || 'normal',\n computed.fontVariant || 'normal',\n computed.fontWeight || 'normal',\n fontSize + 'px',\n computed.fontFamily || 'sans-serif'\n ].join(\" \")\n \n this._cachedMeasurementStyles = {\n font: font,\n fontSize: fontSize,\n lineHeight: lineHeight,\n whiteSpace: computed.whiteSpace || 'normal',\n paddingLeft: parseFloat(computed.paddingLeft) || 0,\n paddingRight: parseFloat(computed.paddingRight) || 0,\n paddingTop: parseFloat(computed.paddingTop) || 0,\n paddingBottom: parseFloat(computed.paddingBottom) || 0\n }\n \n return this._cachedMeasurementStyles\n }\n \n private _parseLineHeight(lineHeight: string, fontSize: number): number {\n if (lineHeight === \"normal\") {\n return fontSize * 1.2\n }\n if (lineHeight.endsWith(\"px\")) {\n return parseFloat(lineHeight)\n }\n const numericLineHeight = parseFloat(lineHeight)\n if (!isNaN(numericLineHeight)) {\n return fontSize * numericLineHeight\n }\n return fontSize * 1.2\n }\n \n private _shouldUseFastMeasurement(): boolean {\n const content = this.text || this.innerHTML\n \n if (this._innerHTMLKey || this._localizedTextObject) {\n return false\n }\n \n if (this.notificationAmount > 0) {\n return false\n }\n \n const hasComplexHTML = /<(?!\\/?(b|i|em|strong|span|br)\\b)[^>]+>/i.test(content)\n \n return !hasComplexHTML\n }\n \n //#endregion\n \n //#region Measurement & Sizing - Public Methods\n \n setUseFastMeasurement(useFast: boolean): void {\n this._useFastMeasurement = useFast\n this._intrinsicSizesCache = {}\n }\n \n invalidateMeasurementStrategy(): void {\n this._useFastMeasurement = undefined\n this._invalidateMeasurementStyles()\n }\n \n //#endregion\n \n //#region Getters & Setters - Text Alignment\n \n get textAlignment() {\n // @ts-ignore\n return this.style.alignItems\n }\n \n set textAlignment(textAlignment: ValueOf<typeof UITextView.textAlignment>) {\n this.style.alignItems = textAlignment\n }\n \n //#endregion\n \n //#region Getters & Setters - Text Color\n \n get textColor() {\n return this._textColor\n }\n \n set textColor(color: UIColor) {\n this._textColor = color || UITextView.defaultTextColor\n this.style.color = this._textColor.stringValue\n }\n \n //#endregion\n \n //#region Getters & Setters - Single Line\n \n get isSingleLine() {\n return this._isSingleLine\n }\n \n set isSingleLine(isSingleLine: boolean) {\n this._isSingleLine = isSingleLine\n \n this._intrinsicHeightCache = new UIObject() as any\n this._intrinsicWidthCache = new UIObject() as any\n \n if (isSingleLine) {\n this.style.whiteSpace = \"pre\"\n return\n }\n \n this.style.whiteSpace = \"pre-wrap\"\n this.invalidateMeasurementStrategy()\n }\n \n //#endregion\n \n //#region Getters & Setters - Notification Amount\n \n get notificationAmount() {\n return this._notificationAmount\n }\n \n set notificationAmount(notificationAmount: number) {\n if (this._notificationAmount == notificationAmount) {\n return\n }\n \n this._notificationAmount = notificationAmount\n this.text = this.text\n this.setNeedsLayoutUpToRootView()\n this.notificationAmountDidChange(notificationAmount)\n }\n \n notificationAmountDidChange(notificationAmount: number) {\n }\n \n //#endregion\n \n //#region Getters & Setters - Text Content\n \n get text() {\n return (this._text || this.viewHTMLElement.innerHTML)\n }\n \n set text(text) {\n this._text = text\n var notificationText = \"\"\n if (this.notificationAmount) {\n notificationText = \"<span style=\\\"color: \" + UITextView.notificationTextColor.stringValue + \";\\\">\" +\n (\" (\" + this.notificationAmount + \")\").bold() + \"</span>\"\n }\n \n if (this.viewHTMLElement.innerHTML != this.textPrefix + text + this.textSuffix + notificationText) {\n this.viewHTMLElement.innerHTML = this.textPrefix + FIRST(text, \"\") + this.textSuffix + notificationText\n }\n \n if (this.changesOften) {\n this._intrinsicHeightCache = new UIObject() as any\n this._intrinsicWidthCache = new UIObject() as any\n }\n \n this._useFastMeasurement = undefined\n this._intrinsicSizesCache = {}\n this.invalidateMeasurementStrategy()\n this._invalidateMeasurementStyles()\n this.clearIntrinsicSizeCache()\n \n this.setNeedsLayout()\n }\n \n override set innerHTML(innerHTML: string) {\n this.text = innerHTML\n this.invalidateMeasurementStrategy()\n }\n \n override get innerHTML() {\n return this.viewHTMLElement.innerHTML\n }\n \n setText(key: string, defaultString: string, parameters?: { [x: string]: string | UILocalizedTextObject }) {\n this.setInnerHTML(key, defaultString, parameters)\n this.invalidateMeasurementStrategy()\n }\n \n //#endregion\n \n //#region Getters & Setters - Font Size\n \n get fontSize() {\n const style = this.style.fontSize || window.getComputedStyle(this.viewHTMLElement, null).fontSize\n const result = (parseFloat(style) * UITextView._pxToPt)\n return result\n }\n \n set fontSize(fontSize: number) {\n if (fontSize != this.fontSize) {\n this.style.fontSize = \"\" + fontSize + \"pt\"\n \n this._intrinsicHeightCache = new UIObject() as any\n this._intrinsicWidthCache = new UIObject() as any\n \n this._invalidateFontCache()\n this._invalidateMeasurementStyles()\n this.clearIntrinsicSizeCache()\n }\n }\n \n useAutomaticFontSize(minFontSize: number = nil, maxFontSize: number = nil) {\n this._automaticFontSizeSelection = YES\n this._minFontSize = minFontSize\n this._maxFontSize = maxFontSize\n this.setNeedsLayout()\n }\n \n //#endregion\n \n //#region Font Caching - Private Methods\n \n /**\n * Get a stable cache key for the font without triggering reflow.\n * Only computes font on first access or when font properties change.\n */\n private _getFontCacheKey(): string {\n // Check if font-related properties have changed\n const currentTriggers = {\n fontSize: this.style.fontSize || \"\",\n fontFamily: this.style.fontFamily || \"\",\n fontWeight: this.style.fontWeight || \"\",\n fontStyle: this.style.fontStyle || \"\",\n styleClasses: this.styleClasses.join(\",\")\n }\n \n const hasChanged =\n currentTriggers.fontSize !== this._fontInvalidationTriggers.fontSize ||\n currentTriggers.fontFamily !== this._fontInvalidationTriggers.fontFamily ||\n currentTriggers.fontWeight !== this._fontInvalidationTriggers.fontWeight ||\n currentTriggers.fontStyle !== this._fontInvalidationTriggers.fontStyle ||\n currentTriggers.styleClasses !== this._fontInvalidationTriggers.styleClasses\n \n if (!this._cachedFontKey || hasChanged) {\n // Only access computedStyle when we know something changed\n const computed = this.computedStyle\n this._cachedFontKey = [\n computed.fontStyle,\n computed.fontVariant,\n computed.fontWeight,\n computed.fontSize,\n computed.fontFamily\n ].join(\"_\").replace(/[.\\s]/g, \"_\")\n \n this._fontInvalidationTriggers = currentTriggers\n }\n \n return this._cachedFontKey\n }\n \n /**\n * Invalidate font cache when font properties change\n */\n private _invalidateFontCache(): void {\n this._cachedFontKey = undefined\n }\n \n //#endregion\n \n //#region Static Methods\n \n static _determinePXAndPTRatios() {\n if (UITextView._ptToPx) {\n return\n }\n \n const o = document.createElement(\"div\")\n o.style.width = \"1000pt\"\n document.body.appendChild(o)\n UITextView._ptToPx = o.clientWidth / 1000\n document.body.removeChild(o)\n UITextView._pxToPt = 1 / UITextView._ptToPx\n }\n \n static automaticallyCalculatedFontSize(\n bounds: UIRectangle,\n currentSize: UIRectangle,\n currentFontSize: number,\n minFontSize?: number,\n maxFontSize?: number\n ) {\n minFontSize = FIRST(minFontSize, 1)\n maxFontSize = FIRST(maxFontSize, 100000000000)\n \n const heightMultiplier = bounds.height / (currentSize.height + 1)\n const widthMultiplier = bounds.width / (currentSize.width + 1)\n \n var multiplier = heightMultiplier\n if (heightMultiplier > widthMultiplier) {\n multiplier = widthMultiplier\n }\n \n const maxFittingFontSize = currentFontSize * multiplier\n \n if (maxFittingFontSize > maxFontSize) {\n return maxFontSize\n }\n \n if (minFontSize > maxFittingFontSize) {\n return minFontSize\n }\n \n return maxFittingFontSize\n }\n \n //#endregion\n \n //#region Instance Properties - Text Content\n \n _text?: string\n textPrefix = \"\"\n textSuffix = \"\"\n _notificationAmount = 0\n \n //#endregion\n \n //#region Instance Properties - Styling\n \n _textColor: UIColor = UITextView.defaultTextColor\n _textAlignment?: ValueOf<typeof UITextView.textAlignment>\n _isSingleLine = YES\n \n //#endregion\n \n //#region Instance Properties - Font & Sizing\n \n _minFontSize?: number\n _maxFontSize?: number\n _automaticFontSizeSelection = NO\n \n // Cache for the computed font string\n private _cachedFontKey?: string\n private _fontInvalidationTriggers = {\n fontSize: this.style.fontSize || \"\",\n fontFamily: this.style.fontFamily || \"\",\n fontWeight: this.style.fontWeight || \"\",\n fontStyle: this.style.fontStyle || \"\",\n styleClasses: this.styleClasses.join(\",\")\n }\n \n //#endregion\n \n //#region Instance Properties - Caching & Performance\n \n changesOften = NO\n \n // Local cache for this instance if the label changes often\n _intrinsicHeightCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n _intrinsicWidthCache: { [x: string]: { [x: string]: number; }; } & UIObject = new UIObject() as any\n \n private _useFastMeasurement: boolean | undefined\n private _cachedMeasurementStyles: TextMeasurementStyle | undefined | null\n \n override usesVirtualLayoutingForIntrinsicSizing = NO\n \n //#endregion\n \n \n \n override intrinsicContentHeight(constrainingWidth = 0) {\n \n const keyPath = (this.viewHTMLElement.innerHTML + \"_csf_\" + this._getFontCacheKey()) + \".\" +\n (\"\" + constrainingWidth).replace(new RegExp(\"\\\\.\", \"g\"), \"_\")\n \n let cacheObject = UITextView._intrinsicHeightCache\n \n if (this.changesOften) {\n cacheObject = this._intrinsicHeightCache\n }\n \n var result = cacheObject.valueForKeyPath(keyPath)\n \n if (IS_LIKE_NULL(result)) {\n // Determine if we should use fast measurement\n const shouldUseFastPath = this._useFastMeasurement ?? this._shouldUseFastMeasurement()\n \n if (shouldUseFastPath) {\n // Fast path: use UITextMeasurement with pre-extracted styles\n const styles = this._getMeasurementStyles()\n \n // If styles are invalid (element not properly initialized), fall back to DOM\n if (styles) {\n const size = UITextMeasurement.calculateTextSize(\n this.viewHTMLElement,\n this.text || this.innerHTML,\n constrainingWidth || undefined,\n undefined,\n styles\n )\n result = size.height\n } else {\n // Styles not ready, use DOM measurement\n result = super.intrinsicContentHeight(constrainingWidth)\n }\n } else {\n // Fallback: DOM-based measurement for complex content\n result = super.intrinsicContentHeight(constrainingWidth)\n }\n \n cacheObject.setValueForKeyPath(keyPath, result)\n }\n \n if (isNaN(result) || (!result && !this.text)) {\n result = super.intrinsicContentHeight(constrainingWidth)\n cacheObject.setValueForKeyPath(keyPath, result)\n }\n \n return result\n }\n \n override intrinsicContentWidth(constrainingHeight = 0) {\n \n const keyPath = (this.viewHTMLElement.innerHTML + \"_csf_\" + this._getFontCacheKey()) + \".\" +\n (\"\" + constrainingHeight).replace(new RegExp(\"\\\\.\", \"g\"), \"_\")\n \n let cacheObject = UITextView._intrinsicWidthCache\n \n if (this.changesOften) {\n cacheObject = this._intrinsicWidthCache\n }\n \n var result = cacheObject.valueForKeyPath(keyPath)\n \n if (IS_LIKE_NULL(result)) {\n // Determine if we should use fast measurement\n const shouldUseFastPath = this._useFastMeasurement ?? this._shouldUseFastMeasurement()\n \n if (shouldUseFastPath) {\n // Fast path: use UITextMeasurement with pre-extracted styles\n const styles = this._getMeasurementStyles()\n \n // If styles are invalid (element not properly initialized), fall back to DOM\n if (styles) {\n const size = UITextMeasurement.calculateTextSize(\n this.viewHTMLElement,\n this.text || this.innerHTML,\n undefined,\n constrainingHeight || undefined,\n styles\n )\n result = size.width\n } else {\n // Styles not ready, use DOM measurement\n result = super.intrinsicContentWidth(constrainingHeight)\n }\n } else {\n // Fallback: DOM-based measurement for complex content\n result = super.intrinsicContentWidth(constrainingHeight)\n }\n \n cacheObject.setValueForKeyPath(keyPath, result)\n }\n \n return result\n }\n \n \n // Override addStyleClass to invalidate font cache\n override addStyleClass(styleClass: string) {\n super.addStyleClass(styleClass)\n this._invalidateFontCache()\n }\n \n // Override removeStyleClass to invalidate font cache\n override removeStyleClass(styleClass: string) {\n super.removeStyleClass(styleClass)\n this._invalidateFontCache()\n }\n \n \n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uicore-ts",
3
- "version": "1.1.118",
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",
@@ -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