uicore-ts 1.1.105 → 1.1.108

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.
@@ -32,3 +32,4 @@ export * from "./UIInterfaces";
32
32
  export * from "./ClientCheckers";
33
33
  export * from "./UICore";
34
34
  export * from "./UIRootViewController";
35
+ export * from "./UILoadingView";
@@ -49,4 +49,5 @@ __reExport(scripts_exports, require("./UIInterfaces"), module.exports);
49
49
  __reExport(scripts_exports, require("./ClientCheckers"), module.exports);
50
50
  __reExport(scripts_exports, require("./UICore"), module.exports);
51
51
  __reExport(scripts_exports, require("./UIRootViewController"), module.exports);
52
+ __reExport(scripts_exports, require("./UILoadingView"), module.exports);
52
53
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../scripts/index.ts"],
4
- "sourcesContent": ["export * from \"./UIObject\"\nexport * from \"./UIView\"\nexport * from \"./UIViewController\"\nexport * from \"./UITimer\"\nexport * from \"./UITextArea\"\nexport * from \"./UITextView\"\nexport * from \"./UITextField\"\nexport * from \"./UITableView\"\nexport * from \"./UIStringFilter\"\nexport * from \"./UISlideScrollerView\"\nexport * from \"./UIScrollView\"\nexport * from \"./UIRoute\"\nexport * from \"./UIRectangle\"\nexport * from \"./UIPoint\"\nexport * from \"./UINativeScrollView\"\nexport * from \"./UILink\"\nexport * from \"./UILinkButton\"\nexport * from \"./UILayoutGrid\"\nexport * from \"./UIKeyValueStringFilter\"\nexport * from \"./UIKeyValueSorter\"\nexport * from \"./UIImageView\"\nexport * from \"./UIDialogView\"\nexport * from \"./UIDateTimeInput\"\nexport * from \"./UICoreExtensions\"\nexport * from \"./UICore\"\nexport * from \"./UIColor\"\nexport * from \"./UIBaseButton\"\nexport * from \"./UIButton\"\nexport * from \"./UIActionIndicator\"\nexport * from \"./UICoreExtensionValueObject\"\nexport * from \"./UIInterfaces\"\nexport * from \"./ClientCheckers\"\nexport * from \"./UICore\"\nexport * from \"./UIRootViewController\"\n\n\n\n\n\n\n\n\n"],
5
- "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,4BAAc,uBAAd;AACA,4BAAc,qBADd;AAEA,4BAAc,+BAFd;AAGA,4BAAc,sBAHd;AAIA,4BAAc,yBAJd;AAKA,4BAAc,yBALd;AAMA,4BAAc,0BANd;AAOA,4BAAc,0BAPd;AAQA,4BAAc,6BARd;AASA,4BAAc,kCATd;AAUA,4BAAc,2BAVd;AAWA,4BAAc,sBAXd;AAYA,4BAAc,0BAZd;AAaA,4BAAc,sBAbd;AAcA,4BAAc,iCAdd;AAeA,4BAAc,qBAfd;AAgBA,4BAAc,2BAhBd;AAiBA,4BAAc,2BAjBd;AAkBA,4BAAc,qCAlBd;AAmBA,4BAAc,+BAnBd;AAoBA,4BAAc,0BApBd;AAqBA,4BAAc,2BArBd;AAsBA,4BAAc,8BAtBd;AAuBA,4BAAc,+BAvBd;AAwBA,4BAAc,qBAxBd;AAyBA,4BAAc,sBAzBd;AA0BA,4BAAc,2BA1Bd;AA2BA,4BAAc,uBA3Bd;AA4BA,4BAAc,gCA5Bd;AA6BA,4BAAc,yCA7Bd;AA8BA,4BAAc,2BA9Bd;AA+BA,4BAAc,6BA/Bd;AAgCA,4BAAc,qBAhCd;AAiCA,4BAAc,mCAjCd;",
4
+ "sourcesContent": ["export * from \"./UIObject\"\nexport * from \"./UIView\"\nexport * from \"./UIViewController\"\nexport * from \"./UITimer\"\nexport * from \"./UITextArea\"\nexport * from \"./UITextView\"\nexport * from \"./UITextField\"\nexport * from \"./UITableView\"\nexport * from \"./UIStringFilter\"\nexport * from \"./UISlideScrollerView\"\nexport * from \"./UIScrollView\"\nexport * from \"./UIRoute\"\nexport * from \"./UIRectangle\"\nexport * from \"./UIPoint\"\nexport * from \"./UINativeScrollView\"\nexport * from \"./UILink\"\nexport * from \"./UILinkButton\"\nexport * from \"./UILayoutGrid\"\nexport * from \"./UIKeyValueStringFilter\"\nexport * from \"./UIKeyValueSorter\"\nexport * from \"./UIImageView\"\nexport * from \"./UIDialogView\"\nexport * from \"./UIDateTimeInput\"\nexport * from \"./UICoreExtensions\"\nexport * from \"./UICore\"\nexport * from \"./UIColor\"\nexport * from \"./UIBaseButton\"\nexport * from \"./UIButton\"\nexport * from \"./UIActionIndicator\"\nexport * from \"./UICoreExtensionValueObject\"\nexport * from \"./UIInterfaces\"\nexport * from \"./ClientCheckers\"\nexport * from \"./UICore\"\nexport * from \"./UIRootViewController\"\nexport * from \"./UILoadingView\"\n\n\n\n\n\n\n\n\n\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,4BAAc,uBAAd;AACA,4BAAc,qBADd;AAEA,4BAAc,+BAFd;AAGA,4BAAc,sBAHd;AAIA,4BAAc,yBAJd;AAKA,4BAAc,yBALd;AAMA,4BAAc,0BANd;AAOA,4BAAc,0BAPd;AAQA,4BAAc,6BARd;AASA,4BAAc,kCATd;AAUA,4BAAc,2BAVd;AAWA,4BAAc,sBAXd;AAYA,4BAAc,0BAZd;AAaA,4BAAc,sBAbd;AAcA,4BAAc,iCAdd;AAeA,4BAAc,qBAfd;AAgBA,4BAAc,2BAhBd;AAiBA,4BAAc,2BAjBd;AAkBA,4BAAc,qCAlBd;AAmBA,4BAAc,+BAnBd;AAoBA,4BAAc,0BApBd;AAqBA,4BAAc,2BArBd;AAsBA,4BAAc,8BAtBd;AAuBA,4BAAc,+BAvBd;AAwBA,4BAAc,qBAxBd;AAyBA,4BAAc,sBAzBd;AA0BA,4BAAc,2BA1Bd;AA2BA,4BAAc,uBA3Bd;AA4BA,4BAAc,gCA5Bd;AA6BA,4BAAc,yCA7Bd;AA8BA,4BAAc,2BA9Bd;AA+BA,4BAAc,6BA/Bd;AAgCA,4BAAc,qBAhCd;AAiCA,4BAAc,mCAjCd;AAkCA,4BAAc,4BAlCd;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uicore-ts",
3
- "version": "1.1.105",
3
+ "version": "1.1.108",
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",
@@ -22,9 +22,6 @@ export class UIActionIndicator extends UIView {
22
22
  }
23
23
 
24
24
 
25
-
26
-
27
-
28
25
  set size(size: number) {
29
26
 
30
27
  this._size = size
@@ -40,15 +37,14 @@ export class UIActionIndicator extends UIView {
40
37
  }
41
38
 
42
39
 
43
-
44
40
  override set hidden(hidden: boolean) {
45
-
41
+
46
42
  super.hidden = hidden
47
-
48
- if (hidden) {
49
43
 
44
+ if (hidden) {
45
+
50
46
  this.indicatorView.removeFromSuperview()
51
-
47
+
52
48
  }
53
49
  else {
54
50
 
@@ -81,26 +77,20 @@ export class UIActionIndicator extends UIView {
81
77
 
82
78
  this.indicatorView.style.height = "" + this._size.integerValue + "px"
83
79
  this.indicatorView.style.width = "" + this._size.integerValue + "px"
84
-
80
+
85
81
  const minSize = Math.min(this.bounds.height, this.bounds.width)
86
-
82
+
87
83
  this.indicatorView.style.maxHeight = "" + minSize.integerValue + "px"
88
84
  this.indicatorView.style.maxWidth = "" + minSize.integerValue + "px"
89
-
85
+
90
86
  const size = Math.min(this._size, minSize)
91
-
87
+
92
88
  this.indicatorView.style.left = "" + ((bounds.width - size) * 0.5 - 11).integerValue + "px"
93
89
  this.indicatorView.style.top = "" + ((bounds.height - size) * 0.5 - 11).integerValue + "px"
94
90
 
95
-
96
-
97
-
98
91
  }
99
92
 
100
93
 
101
-
102
-
103
-
104
94
  }
105
95
 
106
96
 
@@ -0,0 +1,201 @@
1
+ import { UIColor } from "./UIColor"
2
+ import { IS_DEFINED, NO, YES } from "./UIObject"
3
+ import { UIRectangle } from "./UIRectangle"
4
+ import { IUILoadingView, UIView } from "./UIView"
5
+
6
+ export class UILoadingView extends UIView implements IUILoadingView {
7
+
8
+ private spinnerView: UIView
9
+ private isPulsing: boolean = NO
10
+ private _theme: "light" | "dark" = "light"
11
+
12
+ override set loading(loading: boolean) {
13
+ // cannot set loading on loading view
14
+ }
15
+
16
+ override get loading() {
17
+ return NO
18
+ }
19
+
20
+ /**
21
+ * Sets the visual theme of the loader.
22
+ * 'light' (default): Suitable for light backgrounds. Dark spinner, white-ish overlay.
23
+ * 'dark': Suitable for dark backgrounds. Light spinner, black-ish overlay.
24
+ */
25
+ set theme(theme: "light" | "dark") {
26
+ this._theme = theme
27
+ this.updateColors()
28
+ }
29
+
30
+ get theme() {
31
+ return this._theme
32
+ }
33
+
34
+ constructor(elementID?: string) {
35
+ super(elementID)
36
+
37
+ // 1. Initialize Spinner (Custom Bootstrap-like implementation)
38
+ this.spinnerView = new UIView(this.elementID + "_Spinner")
39
+ this.spinnerView.addStyleClass("UILoadingViewSpinnerContainer")
40
+ this.addSubview(this.spinnerView);
41
+
42
+ // 2. Configure defaults
43
+ (this as UILoadingView).configureWithObject({
44
+ backgroundColor: UIColor.transparentColor,
45
+ userInteractionEnabled: YES, // Blocks touches to underlying view
46
+ pausesPointerEvents: YES, // Prevents events from passing through
47
+ style: { height: "100%", width: "100%" }
48
+ })
49
+
50
+ // 3. Initialize CSS
51
+ this.initViewStyleSelectors()
52
+ this.updateColors()
53
+ }
54
+
55
+
56
+ override initViewStyleSelectors() {
57
+ super.initViewStyleSelectors()
58
+
59
+ // 1. Pulsing Animation
60
+ const pulseKeyframe = "UILoadingViewPulse"
61
+ UIView.injectCSS(`
62
+ @keyframes ${pulseKeyframe} {
63
+ 0% { background-color: rgba(0, 0, 0, 0.15); }
64
+ 50% { background-color: rgba(0, 0, 0, 0.35); }
65
+ 100% { background-color: rgba(0, 0, 0, 0.15); }
66
+ }
67
+ `, "UILoadingViewPulseCSS")
68
+ UIView.createStyleSelector(".UILoadingViewPulsing", `animation: ${pulseKeyframe} 1.2s infinite ease-in-out;`)
69
+
70
+ // 2. Spinner Rotation (Bootstrap style)
71
+ const spinKeyframe = "UILoadingViewSpin"
72
+ UIView.injectCSS(`
73
+ @keyframes ${spinKeyframe} {
74
+ from { transform: rotate(0deg); }
75
+ to { transform: rotate(-360deg); }
76
+ }
77
+ `, "UILoadingViewSpinCSS")
78
+
79
+ // We apply the animation to the ::after pseudo-element
80
+ // to avoid conflicts with the framework's positioning on the element itself.
81
+ UIView.createStyleSelector(".UILoadingViewSpinnerContainer::after", `
82
+ content: "";
83
+ display: block;
84
+ width: 100%;
85
+ height: 100%;
86
+ border-radius: 50%;
87
+ border-style: solid;
88
+ border-width: 5px;
89
+ border-color: inherit;
90
+ border-right-color: transparent !important;
91
+ animation: ${spinKeyframe} 1.5s linear infinite;
92
+ box-sizing: border-box;
93
+ `)
94
+ }
95
+
96
+ private updateColors() {
97
+ // --- Indicator Mode Styling ---
98
+ const isLightTheme = this._theme === "light"
99
+
100
+ // Background Overlay
101
+ // Light Theme -> UI is light -> Use White overlay with high alpha
102
+ // Dark Theme -> UI is dark -> Use Black overlay with medium alpha
103
+ const overlayColor = isLightTheme
104
+ ? new UIColor("rgba(255, 255, 255, 0.7)")
105
+ : new UIColor("rgba(0, 0, 0, 0.5)")
106
+
107
+ // Spinner Color
108
+ // Light Theme -> UI is light -> Spinner should be Dark (e.g. Bootstrap text-body-emphasis #212529 or primary)
109
+ // Dark Theme -> UI is dark -> Spinner should be Light (e.g. #f8f9fa)
110
+ const spinnerColor = isLightTheme
111
+ ? new UIColor("#343a40") // Dark Grey
112
+ : new UIColor("#f8f9fa") // Light/White
113
+
114
+ if (!this.isPulsing) {
115
+ this.backgroundColor = overlayColor
116
+ }
117
+
118
+ // Apply colors to spinner borders
119
+ // We set Top, Bottom, Left. Right is forced transparent by CSS class.
120
+ this.spinnerView.style.borderTopColor = spinnerColor.stringValue
121
+ this.spinnerView.style.borderBottomColor = spinnerColor.stringValue
122
+ this.spinnerView.style.borderLeftColor = spinnerColor.stringValue
123
+
124
+ // --- Pulsing Mode Styling ---
125
+ // We could switch animations here, but simply clearing the background
126
+ // allows the CSS animation to take over if the class is active.
127
+ if (this.isPulsing) {
128
+ this.style.backgroundColor = ""
129
+ }
130
+ }
131
+
132
+
133
+ override layoutSubviews() {
134
+
135
+ super.layoutSubviews();
136
+
137
+ // 1. Always fill the parent view
138
+ (this as UILoadingView).configureWithObject({
139
+ style: { height: "100%", width: "100%" }
140
+ })
141
+
142
+ const bounds = this.bounds
143
+ const minDimension = Math.min(bounds.width, bounds.height)
144
+
145
+ // 2. Adaptive Logic
146
+ // If smaller than 40px, use pulsing. Otherwise spinner.
147
+ if (minDimension < 40) {
148
+ this.enablePulsingMode()
149
+ }
150
+ else {
151
+ this.enableIndicatorMode()
152
+ }
153
+ }
154
+
155
+ private enablePulsingMode() {
156
+ if (this.isPulsing) {
157
+ return
158
+ }
159
+
160
+ this.spinnerView.hidden = YES
161
+ this.addStyleClass("UILoadingViewPulsing")
162
+
163
+ // Clear manual background so CSS animation visible
164
+ this.style.backgroundColor = ""
165
+
166
+ this.isPulsing = YES
167
+ }
168
+
169
+ private enableIndicatorMode() {
170
+ // Remove pulsing class
171
+ this.removeStyleClass("UILoadingViewPulsing")
172
+ this.isPulsing = NO
173
+
174
+ this.spinnerView.hidden = NO
175
+
176
+ // Apply Overlay Color immediately
177
+ this.updateColors()
178
+
179
+ // Layout Spinner
180
+ // Bootstrap standard is ~2rem (32px). We can scale it slightly based on available space if we wanted,
181
+ // but a fixed "neutral" size usually looks best unless very restricted.
182
+ const spinnerSize = 32
183
+ const borderWidth = 4 // 0.25em approx
184
+
185
+ const bounds = this.bounds
186
+
187
+ // Center the spinner
188
+ const x = (bounds.width - spinnerSize) / 2
189
+ const y = (bounds.height - spinnerSize) / 2
190
+
191
+ this.spinnerView.frame = new UIRectangle(x, y, spinnerSize, spinnerSize)
192
+ this.spinnerView.style.borderWidth = borderWidth + "px"
193
+ }
194
+
195
+ }
196
+
197
+ UIView.LoadingViewClass = UILoadingView
198
+
199
+
200
+
201
+
@@ -942,7 +942,7 @@ export class UIRectangle extends UIObject {
942
942
 
943
943
 
944
944
  // Bounding box
945
- static boundingBoxForPoints(points: string | any[]) {
945
+ static boundingBoxForPoints(points: UIPoint[]) {
946
946
  const result = new UIRectangle()
947
947
  for (let i = 0; i < points.length; i++) {
948
948
  result.updateByAddingPoint(points[i])
@@ -950,6 +950,21 @@ export class UIRectangle extends UIObject {
950
950
  return result
951
951
  }
952
952
 
953
+ static boundingBoxForRectanglesAndPoints(rectanglesAndPoints: (UIPoint | UIRectangle)[]) {
954
+ const result = new UIRectangle()
955
+ for (let i = 0; i < rectanglesAndPoints.length; i++) {
956
+ const rectangleOrPoint = rectanglesAndPoints[i]
957
+ if (rectangleOrPoint instanceof UIRectangle) {
958
+ result.updateByAddingPoint(rectangleOrPoint.min)
959
+ result.updateByAddingPoint(rectangleOrPoint.max)
960
+ }
961
+ else {
962
+ result.updateByAddingPoint(rectangleOrPoint)
963
+ }
964
+ }
965
+ return result
966
+ }
967
+
953
968
 
954
969
  beginUpdates() {
955
970
  this._isBeingUpdated = YES
@@ -35,10 +35,10 @@ export class UITextView extends UIView {
35
35
  } as const
36
36
 
37
37
  static textAlignment = {
38
- "left": "left",
38
+ "left": "flex-start",
39
39
  "center": "center",
40
- "right": "right",
41
- "justify": "justify"
40
+ "right": "flex-end",
41
+ "justify": "stretch"
42
42
  } as const
43
43
 
44
44
  //#endregion
@@ -61,7 +61,24 @@ export class UITextView extends UIView {
61
61
 
62
62
  this.textColor = this.textColor
63
63
 
64
- this.userInteractionEnabled = YES
64
+ this.userInteractionEnabled = YES;
65
+
66
+ (this as UITextView).configureWithObject({
67
+ style: {
68
+ display: "flex",
69
+ flexDirection: "column", // Ensures vertical stacking logic
70
+
71
+ // 'safe' ensures that if content overflows, it aligns to the start (top)
72
+ // instead of overflowing upwards or downwards equally.
73
+ justifyContent: "safe center",
74
+ alignItems: "flex-start", // Keeps text left-aligned (change to "center" for horizontal center)
75
+
76
+ // Optional: ensure text wraps if it gets too long
77
+ whiteSpace: "normal",
78
+ wordWrap: "break-word",
79
+ overflowWrap: "break-word"
80
+ }
81
+ })
65
82
 
66
83
  if (textViewType == UITextView.type.textArea) {
67
84
  this.pausesPointerEvents = YES
@@ -188,12 +205,11 @@ export class UITextView extends UIView {
188
205
 
189
206
  get textAlignment() {
190
207
  // @ts-ignore
191
- return this.style.textAlign
208
+ return this.style.alignItems
192
209
  }
193
210
 
194
211
  set textAlignment(textAlignment: ValueOf<typeof UITextView.textAlignment>) {
195
- this._textAlignment = textAlignment
196
- this.style.textAlign = textAlignment
212
+ this.style.alignItems = textAlignment
197
213
  }
198
214
 
199
215
  //#endregion
package/scripts/UIView.ts CHANGED
@@ -133,6 +133,12 @@ interface Constraint {
133
133
  }
134
134
 
135
135
 
136
+ export interface IUILoadingView extends UIView {
137
+ theme: "light" | "dark";
138
+ // Add any other specific methods you need to call from UIView
139
+ }
140
+
141
+
136
142
  export function UIComponentView(target: Function, context: ClassDecoratorContext) {
137
143
  console.log("Recording annotation UIComponentView on " + target.name)
138
144
  UIObject.recordAnnotation(UIComponentView, target)
@@ -149,7 +155,7 @@ export class UIView extends UIObject {
149
155
  _UIViewIntrinsicTemporaryWidth?: string
150
156
  _UIViewIntrinsicTemporaryHeight?: string
151
157
  _enabled: boolean = YES
152
- _frame?: UIRectangle & { zIndex?: number };
158
+ _frame?: UIRectangle & { zIndex?: number }
153
159
  _frameCache?: UIRectangle
154
160
  _backgroundColor: UIColor = UIColor.transparentColor
155
161
 
@@ -220,6 +226,43 @@ export class UIView extends UIObject {
220
226
  makeNotResizable?: () => void
221
227
  resizingHandles: UIView[] = []
222
228
 
229
+ public static LoadingViewClass: new () => IUILoadingView
230
+ private _loadingView?: IUILoadingView
231
+
232
+ public set loading(isLoading: boolean) {
233
+ this.userInteractionEnabled = !isLoading
234
+ if (isLoading) {
235
+ if (!IS(this._loadingView)) {
236
+ if (UIView.LoadingViewClass) {
237
+ this._loadingView = new UIView.LoadingViewClass()
238
+ }
239
+ else {
240
+ console.warn("UILoadingView class not registered yet.")
241
+ return
242
+ }
243
+ }
244
+
245
+ // Add to superview if not already added
246
+ if (this._loadingView.superview != this) {
247
+ this.addSubview(this._loadingView)
248
+ // Ensure it sits above other content
249
+ this._loadingView.style.zIndex = "1000"
250
+ }
251
+
252
+ // Force an immediate layout update to position the overlay
253
+ // this._loadingView.setFrame(this.bounds)
254
+
255
+ }
256
+ else {
257
+ this._loadingView?.removeFromSuperview()
258
+ }
259
+ }
260
+
261
+ public get loading(): boolean {
262
+ return IS(this._loadingView) && IS(this._loadingView.superview)
263
+ }
264
+
265
+
223
266
  private _isMoving: boolean = NO
224
267
  _isCBEditorTemporaryResizable = NO
225
268
  _isCBEditorTemporaryMovable = NO
@@ -334,7 +377,7 @@ export class UIView extends UIObject {
334
377
  this._resizeObserverInitialized = true
335
378
 
336
379
  // Invalidate cache on window resize
337
- window.addEventListener('resize', () => {
380
+ window.addEventListener("resize", () => {
338
381
  this._pageDimensionsCacheValid = false
339
382
  }, { passive: true })
340
383
 
@@ -346,9 +389,10 @@ export class UIView extends UIObject {
346
389
  // Start observing once body is available
347
390
  if (document.body) {
348
391
  bodyObserver.observe(document.body)
349
- } else {
392
+ }
393
+ else {
350
394
  // Wait for DOMContentLoaded if body isn't ready yet
351
- document.addEventListener('DOMContentLoaded', () => {
395
+ document.addEventListener("DOMContentLoaded", () => {
352
396
  bodyObserver.observe(document.body)
353
397
  }, { once: true })
354
398
  }
@@ -363,14 +407,15 @@ export class UIView extends UIObject {
363
407
  childList: true,
364
408
  subtree: true,
365
409
  attributes: true,
366
- attributeFilter: ['style', 'class']
410
+ attributeFilter: ["style", "class"]
367
411
  })
368
412
  }
369
413
 
370
414
  if (document.body) {
371
415
  observeMutations()
372
- } else {
373
- document.addEventListener('DOMContentLoaded', observeMutations, { once: true })
416
+ }
417
+ else {
418
+ document.addEventListener("DOMContentLoaded", observeMutations, { once: true })
374
419
  }
375
420
  }
376
421
 
@@ -431,7 +476,6 @@ export class UIView extends UIObject {
431
476
  //#endregion
432
477
 
433
478
 
434
-
435
479
  centerInContainer() {
436
480
  this.style.left = "50%"
437
481
  this.style.top = "50%"
@@ -1745,7 +1789,7 @@ export class UIView extends UIObject {
1745
1789
 
1746
1790
  // Skip if this view has been laid out too many times (cycle detection)
1747
1791
  if (layoutCount >= 5) {
1748
- console.warn('View layout cycle detected:', view)
1792
+ console.warn("View layout cycle detected:", view)
1749
1793
  continue
1750
1794
  }
1751
1795
 
@@ -1847,6 +1891,10 @@ export class UIView extends UIObject {
1847
1891
 
1848
1892
  }
1849
1893
 
1894
+ // if (this._loadingView && this._loadingView.superview == this) {
1895
+ // this._loadingView.setFrame(this.bounds)
1896
+ // }
1897
+
1850
1898
  this.didLayoutSubviews()
1851
1899
 
1852
1900
  }
@@ -3687,6 +3735,9 @@ export class UIView extends UIObject {
3687
3735
 
3688
3736
  const framePoints: UIPoint[] = []
3689
3737
  this.subviews.forEach(subview => {
3738
+ if (subview == this._loadingView) {
3739
+ return
3740
+ }
3690
3741
  subview.layoutIfNeeded()
3691
3742
  framePoints.push(subview.frame.min)
3692
3743
  framePoints.push(subview.frame.max)
@@ -3695,11 +3746,11 @@ export class UIView extends UIObject {
3695
3746
  // we will add padding based on the _contentInsets
3696
3747
  const resultFrame = UIRectangle.boundingBoxForPoints(framePoints)
3697
3748
  .rectangleWithInsets(
3698
- -this._contentInsets?.left ?? 0,
3699
- -this._contentInsets?.right ?? 0,
3700
- -this._contentInsets?.bottom ?? 0,
3701
- -this._contentInsets?.top ?? 0
3702
- )
3749
+ -this._contentInsets?.left ?? 0,
3750
+ -this._contentInsets?.right ?? 0,
3751
+ -this._contentInsets?.bottom ?? 0,
3752
+ -this._contentInsets?.top ?? 0
3753
+ )
3703
3754
  return resultFrame
3704
3755
  }
3705
3756
 
package/scripts/index.ts CHANGED
@@ -32,6 +32,8 @@ export * from "./UIInterfaces"
32
32
  export * from "./ClientCheckers"
33
33
  export * from "./UICore"
34
34
  export * from "./UIRootViewController"
35
+ export * from "./UILoadingView"
36
+
35
37
 
36
38
 
37
39