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.
- package/compiledScripts/UIActionIndicator.js.map +2 -2
- package/compiledScripts/UILoadingView.d.ts +21 -0
- package/compiledScripts/UILoadingView.js +144 -0
- package/compiledScripts/UILoadingView.js.map +7 -0
- package/compiledScripts/UIRectangle.d.ts +2 -1
- package/compiledScripts/UIRectangle.js +13 -0
- package/compiledScripts/UIRectangle.js.map +2 -2
- package/compiledScripts/UITextView.d.ts +3 -3
- package/compiledScripts/UITextView.js +16 -6
- package/compiledScripts/UITextView.js.map +2 -2
- package/compiledScripts/UIView.d.ts +7 -0
- package/compiledScripts/UIView.js +26 -0
- package/compiledScripts/UIView.js.map +2 -2
- package/compiledScripts/index.d.ts +1 -0
- package/compiledScripts/index.js +1 -0
- package/compiledScripts/index.js.map +2 -2
- package/package.json +1 -1
- package/scripts/UIActionIndicator.ts +8 -18
- package/scripts/UILoadingView.ts +201 -0
- package/scripts/UIRectangle.ts +16 -1
- package/scripts/UITextView.ts +23 -7
- package/scripts/UIView.ts +65 -14
- package/scripts/index.ts +2 -0
package/compiledScripts/index.js
CHANGED
|
@@ -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.
|
|
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
|
+
|
package/scripts/UIRectangle.ts
CHANGED
|
@@ -942,7 +942,7 @@ export class UIRectangle extends UIObject {
|
|
|
942
942
|
|
|
943
943
|
|
|
944
944
|
// Bounding box
|
|
945
|
-
static boundingBoxForPoints(points:
|
|
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
|
package/scripts/UITextView.ts
CHANGED
|
@@ -35,10 +35,10 @@ export class UITextView extends UIView {
|
|
|
35
35
|
} as const
|
|
36
36
|
|
|
37
37
|
static textAlignment = {
|
|
38
|
-
"left": "
|
|
38
|
+
"left": "flex-start",
|
|
39
39
|
"center": "center",
|
|
40
|
-
"right": "
|
|
41
|
-
"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.
|
|
208
|
+
return this.style.alignItems
|
|
192
209
|
}
|
|
193
210
|
|
|
194
211
|
set textAlignment(textAlignment: ValueOf<typeof UITextView.textAlignment>) {
|
|
195
|
-
this.
|
|
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(
|
|
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
|
-
}
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
350
394
|
// Wait for DOMContentLoaded if body isn't ready yet
|
|
351
|
-
document.addEventListener(
|
|
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: [
|
|
410
|
+
attributeFilter: ["style", "class"]
|
|
367
411
|
})
|
|
368
412
|
}
|
|
369
413
|
|
|
370
414
|
if (document.body) {
|
|
371
415
|
observeMutations()
|
|
372
|
-
}
|
|
373
|
-
|
|
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(
|
|
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
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
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
|
|