uicore-ts 1.1.102 → 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.102",
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