uicore-ts 1.1.188 → 1.1.201
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/UIColor.d.ts +50 -1
- package/compiledScripts/UIColor.js +95 -32
- package/compiledScripts/UIColor.js.map +2 -2
- package/compiledScripts/UITextField.d.ts +7 -0
- package/compiledScripts/UITextField.js +16 -0
- package/compiledScripts/UITextField.js.map +2 -2
- package/compiledScripts/UIView.d.ts +5 -0
- package/compiledScripts/UIView.js +33 -2
- package/compiledScripts/UIView.js.map +2 -2
- package/package.json +1 -1
- package/scripts/UIColor.ts +156 -57
- package/scripts/UITextField.ts +28 -0
- package/scripts/UIView.ts +51 -2
- package/tsconfig.json +1 -1
|
@@ -5,10 +5,59 @@ export interface UIColorDescriptor {
|
|
|
5
5
|
blue: number;
|
|
6
6
|
alpha?: number;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Extend this interface via declaration merging in UIColor subclass files
|
|
10
|
+
* to register valid semantic key strings for autocomplete and type safety.
|
|
11
|
+
*
|
|
12
|
+
* Example (in BSColor.ts):
|
|
13
|
+
* declare module "./UIColor" {
|
|
14
|
+
* interface UIColorSemanticKeys {
|
|
15
|
+
* primary: never
|
|
16
|
+
* success: never
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
export interface UIColorSemanticKeys {
|
|
21
|
+
}
|
|
22
|
+
export type UIColorSemanticKey = keyof UIColorSemanticKeys;
|
|
8
23
|
export declare class UIColor extends UIObject {
|
|
24
|
+
static _liveColors: WeakRef<UIColor>[];
|
|
25
|
+
static _registrationMap: Map<string, UIColor>;
|
|
26
|
+
static _cssSubscriptions: Map<never, Set<() => void>>;
|
|
9
27
|
stringValue: string;
|
|
10
|
-
|
|
28
|
+
semanticKey?: UIColorSemanticKey;
|
|
29
|
+
_semanticClass?: typeof UIColor;
|
|
30
|
+
_elementRef?: HTMLElement;
|
|
31
|
+
_styleProperty?: string;
|
|
32
|
+
constructor(stringValue: string, semanticKey?: UIColorSemanticKey);
|
|
11
33
|
toString(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Re-resolves this instance's stringValue from its class's static getter
|
|
36
|
+
* matching the semanticKey, then writes the new value directly to the DOM
|
|
37
|
+
* via the stored element reference and style property.
|
|
38
|
+
* No-op if this instance has no semanticKey.
|
|
39
|
+
*/
|
|
40
|
+
apply(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Assigns a semantic key and the class that owns it to this color instance.
|
|
43
|
+
* Intended for derived colors that should participate in theme switching,
|
|
44
|
+
* e.g. `BSColor._primaryBase.colorWithAlpha(0.5).withSemanticKey("primaryShadow", BSColor)`.
|
|
45
|
+
* Returns `this` for fluent chaining.
|
|
46
|
+
*/
|
|
47
|
+
withSemanticKey(semanticKey: UIColorSemanticKey, semanticClass: typeof UIColor): this;
|
|
48
|
+
/**
|
|
49
|
+
* Iterates all live registered UIColor instances, calls apply() on each,
|
|
50
|
+
* compacts dead WeakRefs in the same pass, then fires any CSS subscriptions
|
|
51
|
+
* whose semantic key was affected.
|
|
52
|
+
*/
|
|
53
|
+
static applySemanticColors(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Registers a callback to be fired when applySemanticColors() affects
|
|
56
|
+
* the given semantic key. Intended for injected CSS blocks that cannot
|
|
57
|
+
* be tracked via the colorStyleProxy.
|
|
58
|
+
*/
|
|
59
|
+
static subscribe(semanticKey: UIColorSemanticKey, callback: () => void): void;
|
|
60
|
+
static unsubscribe(semanticKey: UIColorSemanticKey, callback: () => void): void;
|
|
12
61
|
static get redColor(): UIColor;
|
|
13
62
|
static get blueColor(): UIColor;
|
|
14
63
|
static get greenColor(): UIColor;
|
|
@@ -22,52 +22,108 @@ __export(UIColor_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(UIColor_exports);
|
|
24
24
|
var import_UIObject = require("./UIObject");
|
|
25
|
-
class
|
|
26
|
-
constructor(stringValue) {
|
|
25
|
+
const _UIColor = class extends import_UIObject.UIObject {
|
|
26
|
+
constructor(stringValue, semanticKey) {
|
|
27
27
|
super();
|
|
28
28
|
this.stringValue = stringValue;
|
|
29
|
+
this.semanticKey = semanticKey;
|
|
30
|
+
if (semanticKey) {
|
|
31
|
+
this._semanticClass = this.constructor;
|
|
32
|
+
}
|
|
29
33
|
}
|
|
30
34
|
toString() {
|
|
31
35
|
return this.stringValue;
|
|
32
36
|
}
|
|
37
|
+
apply() {
|
|
38
|
+
var _a;
|
|
39
|
+
if (!this.semanticKey) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const colorClass = (_a = this._semanticClass) != null ? _a : this.constructor;
|
|
43
|
+
const newColor = colorClass[this.semanticKey];
|
|
44
|
+
if (!newColor) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.stringValue = newColor.stringValue;
|
|
48
|
+
const element = this._elementRef;
|
|
49
|
+
if (!element || !this._styleProperty) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
element.style[this._styleProperty] = this.stringValue;
|
|
53
|
+
}
|
|
54
|
+
withSemanticKey(semanticKey, semanticClass) {
|
|
55
|
+
this.semanticKey = semanticKey;
|
|
56
|
+
this._semanticClass = semanticClass;
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
static applySemanticColors() {
|
|
60
|
+
var _a;
|
|
61
|
+
const affectedKeys = /* @__PURE__ */ new Set();
|
|
62
|
+
const live = [];
|
|
63
|
+
for (const ref of _UIColor._liveColors) {
|
|
64
|
+
const color = ref.deref();
|
|
65
|
+
if (!color) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
live.push(ref);
|
|
69
|
+
if (color.semanticKey) {
|
|
70
|
+
affectedKeys.add(color.semanticKey);
|
|
71
|
+
}
|
|
72
|
+
color.apply();
|
|
73
|
+
}
|
|
74
|
+
_UIColor._liveColors = live;
|
|
75
|
+
for (const key of affectedKeys) {
|
|
76
|
+
(_a = _UIColor._cssSubscriptions.get(key)) == null ? void 0 : _a.forEach((callback) => callback());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
static subscribe(semanticKey, callback) {
|
|
80
|
+
if (!_UIColor._cssSubscriptions.has(semanticKey)) {
|
|
81
|
+
_UIColor._cssSubscriptions.set(semanticKey, /* @__PURE__ */ new Set());
|
|
82
|
+
}
|
|
83
|
+
_UIColor._cssSubscriptions.get(semanticKey).add(callback);
|
|
84
|
+
}
|
|
85
|
+
static unsubscribe(semanticKey, callback) {
|
|
86
|
+
var _a;
|
|
87
|
+
(_a = _UIColor._cssSubscriptions.get(semanticKey)) == null ? void 0 : _a.delete(callback);
|
|
88
|
+
}
|
|
33
89
|
static get redColor() {
|
|
34
|
-
return new
|
|
90
|
+
return new _UIColor("red");
|
|
35
91
|
}
|
|
36
92
|
static get blueColor() {
|
|
37
|
-
return new
|
|
93
|
+
return new _UIColor("blue");
|
|
38
94
|
}
|
|
39
95
|
static get greenColor() {
|
|
40
|
-
return new
|
|
96
|
+
return new _UIColor("green");
|
|
41
97
|
}
|
|
42
98
|
static get yellowColor() {
|
|
43
|
-
return new
|
|
99
|
+
return new _UIColor("yellow");
|
|
44
100
|
}
|
|
45
101
|
static get blackColor() {
|
|
46
|
-
return new
|
|
102
|
+
return new _UIColor("black");
|
|
47
103
|
}
|
|
48
104
|
static get brownColor() {
|
|
49
|
-
return new
|
|
105
|
+
return new _UIColor("brown");
|
|
50
106
|
}
|
|
51
107
|
static get whiteColor() {
|
|
52
|
-
return new
|
|
108
|
+
return new _UIColor("white");
|
|
53
109
|
}
|
|
54
110
|
static get greyColor() {
|
|
55
|
-
return new
|
|
111
|
+
return new _UIColor("grey");
|
|
56
112
|
}
|
|
57
113
|
static get lightGreyColor() {
|
|
58
|
-
return new
|
|
114
|
+
return new _UIColor("lightgrey");
|
|
59
115
|
}
|
|
60
116
|
static get transparentColor() {
|
|
61
|
-
return new
|
|
117
|
+
return new _UIColor("transparent");
|
|
62
118
|
}
|
|
63
119
|
static get clearColor() {
|
|
64
|
-
return new
|
|
120
|
+
return new _UIColor("transparent");
|
|
65
121
|
}
|
|
66
122
|
static get undefinedColor() {
|
|
67
|
-
return new
|
|
123
|
+
return new _UIColor("");
|
|
68
124
|
}
|
|
69
125
|
static get nilColor() {
|
|
70
|
-
return new
|
|
126
|
+
return new _UIColor("");
|
|
71
127
|
}
|
|
72
128
|
static nameToHex(name) {
|
|
73
129
|
return {
|
|
@@ -242,42 +298,46 @@ class UIColor extends import_UIObject.UIObject {
|
|
|
242
298
|
}
|
|
243
299
|
get colorDescriptor() {
|
|
244
300
|
var descriptor;
|
|
245
|
-
const colorHEXFromName =
|
|
301
|
+
const colorHEXFromName = _UIColor.nameToHex(this.stringValue);
|
|
246
302
|
if (this.stringValue.startsWith("rgb")) {
|
|
247
|
-
descriptor =
|
|
303
|
+
descriptor = _UIColor.rgbToDescriptor(this.stringValue);
|
|
248
304
|
} else if (colorHEXFromName) {
|
|
249
|
-
descriptor =
|
|
305
|
+
descriptor = _UIColor.hexToDescriptor(colorHEXFromName);
|
|
250
306
|
} else {
|
|
251
|
-
descriptor =
|
|
307
|
+
descriptor = _UIColor.hexToDescriptor(this.stringValue);
|
|
252
308
|
}
|
|
253
309
|
return descriptor;
|
|
254
310
|
}
|
|
255
311
|
colorWithRed(red) {
|
|
256
312
|
const descriptor = this.colorDescriptor;
|
|
257
|
-
|
|
258
|
-
|
|
313
|
+
return new _UIColor(
|
|
314
|
+
"rgba(" + red + "," + descriptor.green + "," + descriptor.blue + "," + descriptor.alpha + ")"
|
|
315
|
+
);
|
|
259
316
|
}
|
|
260
317
|
colorWithGreen(green) {
|
|
261
318
|
const descriptor = this.colorDescriptor;
|
|
262
|
-
|
|
263
|
-
|
|
319
|
+
return new _UIColor(
|
|
320
|
+
"rgba(" + descriptor.red + "," + green + "," + descriptor.blue + "," + descriptor.alpha + ")"
|
|
321
|
+
);
|
|
264
322
|
}
|
|
265
323
|
colorWithBlue(blue) {
|
|
266
324
|
const descriptor = this.colorDescriptor;
|
|
267
|
-
|
|
268
|
-
|
|
325
|
+
return new _UIColor(
|
|
326
|
+
"rgba(" + descriptor.red + "," + descriptor.green + "," + blue + "," + descriptor.alpha + ")"
|
|
327
|
+
);
|
|
269
328
|
}
|
|
270
329
|
colorWithAlpha(alpha) {
|
|
271
330
|
const descriptor = this.colorDescriptor;
|
|
272
|
-
|
|
273
|
-
|
|
331
|
+
return new _UIColor(
|
|
332
|
+
"rgba(" + descriptor.red + "," + descriptor.green + "," + descriptor.blue + "," + alpha + ")"
|
|
333
|
+
);
|
|
274
334
|
}
|
|
275
335
|
static colorWithRGBA(red, green, blue, alpha = 1) {
|
|
276
|
-
const result = new
|
|
336
|
+
const result = new _UIColor("rgba(" + red + "," + green + "," + blue + "," + alpha + ")");
|
|
277
337
|
return result;
|
|
278
338
|
}
|
|
279
339
|
static colorWithDescriptor(descriptor) {
|
|
280
|
-
const result = new
|
|
340
|
+
const result = new _UIColor("rgba(" + descriptor.red.toFixed(0) + "," + descriptor.green.toFixed(0) + "," + descriptor.blue.toFixed(0) + "," + this.defaultAlphaToOne(descriptor.alpha) + ")");
|
|
281
341
|
return result;
|
|
282
342
|
}
|
|
283
343
|
static defaultAlphaToOne(value = 1) {
|
|
@@ -291,10 +351,13 @@ class UIColor extends import_UIObject.UIObject {
|
|
|
291
351
|
descriptor.red = descriptor.red * multiplier;
|
|
292
352
|
descriptor.green = descriptor.green * multiplier;
|
|
293
353
|
descriptor.blue = descriptor.blue * multiplier;
|
|
294
|
-
|
|
295
|
-
return result;
|
|
354
|
+
return _UIColor.colorWithDescriptor(descriptor);
|
|
296
355
|
}
|
|
297
|
-
}
|
|
356
|
+
};
|
|
357
|
+
let UIColor = _UIColor;
|
|
358
|
+
UIColor._liveColors = [];
|
|
359
|
+
UIColor._registrationMap = /* @__PURE__ */ new Map();
|
|
360
|
+
UIColor._cssSubscriptions = /* @__PURE__ */ new Map();
|
|
298
361
|
// Annotate the CommonJS export names for ESM import in node:
|
|
299
362
|
0 && (module.exports = {
|
|
300
363
|
UIColor
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../scripts/UIColor.ts"],
|
|
4
|
-
"sourcesContent": ["import { UIObject } from \"./UIObject\"\n\n\nexport interface UIColorDescriptor {\n \n red: number;\n green: number;\n blue: number;\n alpha?: number;\n \n}\n\n\nexport class UIColor extends UIObject {\n \n \n constructor(public stringValue: string) {\n \n super()\n \n }\n \n \n override toString() {\n return this.stringValue\n }\n \n static get redColor() {\n return new UIColor(\"red\")\n }\n \n static get blueColor() {\n return new UIColor(\"blue\")\n }\n \n static get greenColor() {\n return new UIColor(\"green\")\n }\n \n static get yellowColor() {\n return new UIColor(\"yellow\")\n }\n \n static get blackColor() {\n return new UIColor(\"black\")\n }\n \n static get brownColor() {\n return new UIColor(\"brown\")\n }\n \n static get whiteColor() {\n return new UIColor(\"white\")\n }\n \n static get greyColor() {\n return new UIColor(\"grey\")\n }\n \n static get lightGreyColor() {\n return new UIColor(\"lightgrey\")\n }\n \n static get transparentColor() {\n return new UIColor(\"transparent\")\n }\n \n static get clearColor() {\n return new UIColor(\"transparent\")\n }\n \n static get undefinedColor() {\n return new UIColor(\"\")\n }\n \n static get nilColor() {\n return new UIColor(\"\")\n }\n \n \n static nameToHex(name: string) {\n return {\n \"aliceblue\": \"#f0f8ff\",\n \"antiquewhite\": \"#faebd7\",\n \"aqua\": \"#00ffff\",\n \"aquamarine\": \"#7fffd4\",\n \"azure\": \"#f0ffff\",\n \"beige\": \"#f5f5dc\",\n \"bisque\": \"#ffe4c4\",\n \"black\": \"#000000\",\n \"blanchedalmond\": \"#ffebcd\",\n \"blue\": \"#0000ff\",\n \"blueviolet\": \"#8a2be2\",\n \"brown\": \"#a52a2a\",\n \"burlywood\": \"#deb887\",\n \"cadetblue\": \"#5f9ea0\",\n \"chartreuse\": \"#7fff00\",\n \"chocolate\": \"#d2691e\",\n \"coral\": \"#ff7f50\",\n \"cornflowerblue\": \"#6495ed\",\n \"cornsilk\": \"#fff8dc\",\n \"crimson\": \"#dc143c\",\n \"cyan\": \"#00ffff\",\n \"darkblue\": \"#00008b\",\n \"darkcyan\": \"#008b8b\",\n \"darkgoldenrod\": \"#b8860b\",\n \"darkgray\": \"#a9a9a9\",\n \"darkgreen\": \"#006400\",\n \"darkkhaki\": \"#bdb76b\",\n \"darkmagenta\": \"#8b008b\",\n \"darkolivegreen\": \"#556b2f\",\n \"darkorange\": \"#ff8c00\",\n \"darkorchid\": \"#9932cc\",\n \"darkred\": \"#8b0000\",\n \"darksalmon\": \"#e9967a\",\n \"darkseagreen\": \"#8fbc8f\",\n \"darkslateblue\": \"#483d8b\",\n \"darkslategray\": \"#2f4f4f\",\n \"darkturquoise\": \"#00ced1\",\n \"darkviolet\": \"#9400d3\",\n \"deeppink\": \"#ff1493\",\n \"deepskyblue\": \"#00bfff\",\n \"dimgray\": \"#696969\",\n \"dodgerblue\": \"#1e90ff\",\n \"firebrick\": \"#b22222\",\n \"floralwhite\": \"#fffaf0\",\n \"forestgreen\": \"#228b22\",\n \"fuchsia\": \"#ff00ff\",\n \"gainsboro\": \"#dcdcdc\",\n \"ghostwhite\": \"#f8f8ff\",\n \"gold\": \"#ffd700\",\n \"goldenrod\": \"#daa520\",\n \"gray\": \"#808080\",\n \"green\": \"#008000\",\n \"greenyellow\": \"#adff2f\",\n \"honeydew\": \"#f0fff0\",\n \"hotpink\": \"#ff69b4\",\n \"indianred \": \"#cd5c5c\",\n \"indigo\": \"#4b0082\",\n \"ivory\": \"#fffff0\",\n \"khaki\": \"#f0e68c\",\n \"lavender\": \"#e6e6fa\",\n \"lavenderblush\": \"#fff0f5\",\n \"lawngreen\": \"#7cfc00\",\n \"lemonchiffon\": \"#fffacd\",\n \"lightblue\": \"#add8e6\",\n \"lightcoral\": \"#f08080\",\n \"lightcyan\": \"#e0ffff\",\n \"lightgoldenrodyellow\": \"#fafad2\",\n \"lightgrey\": \"#d3d3d3\",\n \"lightgreen\": \"#90ee90\",\n \"lightpink\": \"#ffb6c1\",\n \"lightsalmon\": \"#ffa07a\",\n \"lightseagreen\": \"#20b2aa\",\n \"lightskyblue\": \"#87cefa\",\n \"lightslategray\": \"#778899\",\n \"lightsteelblue\": \"#b0c4de\",\n \"lightyellow\": \"#ffffe0\",\n \"lime\": \"#00ff00\",\n \"limegreen\": \"#32cd32\",\n \"linen\": \"#faf0e6\",\n \"magenta\": \"#ff00ff\",\n \"maroon\": \"#800000\",\n \"mediumaquamarine\": \"#66cdaa\",\n \"mediumblue\": \"#0000cd\",\n \"mediumorchid\": \"#ba55d3\",\n \"mediumpurple\": \"#9370d8\",\n \"mediumseagreen\": \"#3cb371\",\n \"mediumslateblue\": \"#7b68ee\",\n \"mediumspringgreen\": \"#00fa9a\",\n \"mediumturquoise\": \"#48d1cc\",\n \"mediumvioletred\": \"#c71585\",\n \"midnightblue\": \"#191970\",\n \"mintcream\": \"#f5fffa\",\n \"mistyrose\": \"#ffe4e1\",\n \"moccasin\": \"#ffe4b5\",\n \"navajowhite\": \"#ffdead\",\n \"navy\": \"#000080\",\n \"oldlace\": \"#fdf5e6\",\n \"olive\": \"#808000\",\n \"olivedrab\": \"#6b8e23\",\n \"orange\": \"#ffa500\",\n \"orangered\": \"#ff4500\",\n \"orchid\": \"#da70d6\",\n \"palegoldenrod\": \"#eee8aa\",\n \"palegreen\": \"#98fb98\",\n \"paleturquoise\": \"#afeeee\",\n \"palevioletred\": \"#d87093\",\n \"papayawhip\": \"#ffefd5\",\n \"peachpuff\": \"#ffdab9\",\n \"peru\": \"#cd853f\",\n \"pink\": \"#ffc0cb\",\n \"plum\": \"#dda0dd\",\n \"powderblue\": \"#b0e0e6\",\n \"purple\": \"#800080\",\n \"red\": \"#ff0000\",\n \"rosybrown\": \"#bc8f8f\",\n \"royalblue\": \"#4169e1\",\n \"saddlebrown\": \"#8b4513\",\n \"salmon\": \"#fa8072\",\n \"sandybrown\": \"#f4a460\",\n \"seagreen\": \"#2e8b57\",\n \"seashell\": \"#fff5ee\",\n \"sienna\": \"#a0522d\",\n \"silver\": \"#c0c0c0\",\n \"skyblue\": \"#87ceeb\",\n \"slateblue\": \"#6a5acd\",\n \"slategray\": \"#708090\",\n \"snow\": \"#fffafa\",\n \"springgreen\": \"#00ff7f\",\n \"steelblue\": \"#4682b4\",\n \"tan\": \"#d2b48c\",\n \"teal\": \"#008080\",\n \"thistle\": \"#d8bfd8\",\n \"tomato\": \"#ff6347\",\n \"turquoise\": \"#40e0d0\",\n \"violet\": \"#ee82ee\",\n \"wheat\": \"#f5deb3\",\n \"white\": \"#ffffff\",\n \"whitesmoke\": \"#f5f5f5\",\n \"yellow\": \"#ffff00\",\n \"yellowgreen\": \"#9acd32\"\n }[name.toLowerCase()]\n }\n \n \n static hexToDescriptor(c: string): UIColorDescriptor {\n if (c[0] === \"#\") {\n c = c.substr(1)\n }\n const r = parseInt(c.slice(0, 2), 16)\n const g = parseInt(c.slice(2, 4), 16)\n const b = parseInt(c.slice(4, 6), 16)\n const a = parseInt(c.slice(6, 8), 16)\n \n const result = { \"red\": r, \"green\": g, \"blue\": b, \"alpha\": a }\n \n return result\n \n //return 'rgb(' + r + ',' + g + ',' + b + ')';\n \n }\n \n static rgbToDescriptor(colorString: string) {\n \n \n if (colorString.startsWith(\"rgba(\")) {\n \n colorString = colorString.slice(5, colorString.length - 1)\n \n }\n \n if (colorString.startsWith(\"rgb(\")) {\n \n colorString = colorString.slice(4, colorString.length - 1) + \", 0\"\n \n }\n \n \n const components = colorString.split(\",\")\n \n \n const result = {\n \"red\": Number(components[0]),\n \"green\": Number(components[1]),\n \"blue\": Number(components[2]),\n \"alpha\": Number(components[3])\n }\n \n \n return result\n \n \n }\n \n \n get colorDescriptor(): UIColorDescriptor {\n \n var descriptor\n \n const colorHEXFromName = UIColor.nameToHex(this.stringValue)\n \n if (this.stringValue.startsWith(\"rgb\")) {\n \n descriptor = UIColor.rgbToDescriptor(this.stringValue)\n \n }\n else if (colorHEXFromName) {\n \n descriptor = UIColor.hexToDescriptor(colorHEXFromName)\n \n }\n else {\n \n descriptor = UIColor.hexToDescriptor(this.stringValue)\n \n }\n \n return descriptor\n \n }\n \n \n colorWithRed(red: number) {\n \n \n const descriptor = this.colorDescriptor\n \n const result = new UIColor(\"rgba(\" + red + \",\" + descriptor.green + \",\" + descriptor.blue + \",\" +\n descriptor.alpha + \")\")\n \n return result\n \n }\n \n colorWithGreen(green: number) {\n \n \n const descriptor = this.colorDescriptor\n \n const result = new UIColor(\"rgba(\" + descriptor.red + \",\" + green + \",\" + descriptor.blue + \",\" +\n descriptor.alpha + \")\")\n \n return result\n \n }\n \n colorWithBlue(blue: number) {\n \n \n const descriptor = this.colorDescriptor\n \n const result = new UIColor(\"rgba(\" + descriptor.red + \",\" + descriptor.green + \",\" + blue + \",\" +\n descriptor.alpha + \")\")\n \n return result\n \n }\n \n \n colorWithAlpha(alpha: number) {\n \n \n const descriptor = this.colorDescriptor\n \n const result = new UIColor(\"rgba(\" + descriptor.red + \",\" + descriptor.green + \",\" + descriptor.blue + \",\" +\n alpha + \")\")\n \n return result\n \n }\n \n \n static colorWithRGBA(red: number, green: number, blue: number, alpha: number = 1) {\n \n \n const result = new UIColor(\"rgba(\" + red + \",\" + green + \",\" + blue + \",\" + alpha + \")\")\n \n return result\n \n \n }\n \n static colorWithDescriptor(descriptor: UIColorDescriptor) {\n \n \n const result = new UIColor(\"rgba(\" + descriptor.red.toFixed(0) + \",\" + descriptor.green.toFixed(0) + \",\" +\n descriptor.blue.toFixed(0) + \",\" + this.defaultAlphaToOne(descriptor.alpha) + \")\")\n \n return result\n \n }\n \n \n private static defaultAlphaToOne(value = 1) {\n if (value != value) {\n value = 1\n }\n return value\n }\n \n \n colorByMultiplyingRGB(multiplier: number) {\n \n const descriptor = this.colorDescriptor\n \n descriptor.red = descriptor.red * multiplier\n descriptor.green = descriptor.green * multiplier\n descriptor.blue = descriptor.blue * multiplier\n \n const result = UIColor.colorWithDescriptor(descriptor)\n \n return result\n \n }\n \n \n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyB;
|
|
4
|
+
"sourcesContent": ["import { UIObject } from \"./UIObject\"\n\n\nexport interface UIColorDescriptor {\n \n red: number;\n green: number;\n blue: number;\n alpha?: number;\n \n}\n\n\n/**\n * Extend this interface via declaration merging in UIColor subclass files\n * to register valid semantic key strings for autocomplete and type safety.\n *\n * Example (in BSColor.ts):\n * declare module \"./UIColor\" {\n * interface UIColorSemanticKeys {\n * primary: never\n * success: never\n * }\n * }\n */\nexport interface UIColorSemanticKeys {}\n\nexport type UIColorSemanticKey = keyof UIColorSemanticKeys\n\n\nexport class UIColor extends UIObject {\n \n \n // --- Semantic color registry ---\n \n static _liveColors: WeakRef<UIColor>[] = []\n static _registrationMap = new Map<string, UIColor>()\n static _cssSubscriptions = new Map<UIColorSemanticKey, Set<() => void>>()\n \n \n // --- Instance fields ---\n \n stringValue: string\n semanticKey?: UIColorSemanticKey\n _semanticClass?: typeof UIColor\n _elementRef?: HTMLElement\n _styleProperty?: string\n \n \n constructor(stringValue: string, semanticKey?: UIColorSemanticKey) {\n \n super()\n \n this.stringValue = stringValue\n this.semanticKey = semanticKey\n if (semanticKey) {\n this._semanticClass = this.constructor as typeof UIColor\n }\n \n }\n \n \n override toString() {\n return this.stringValue\n }\n \n \n // --- Semantic apply ---\n \n /**\n * Re-resolves this instance's stringValue from its class's static getter\n * matching the semanticKey, then writes the new value directly to the DOM\n * via the stored element reference and style property.\n * No-op if this instance has no semanticKey.\n */\n apply() {\n \n if (!this.semanticKey) { return }\n \n const colorClass = this._semanticClass ?? this.constructor as typeof UIColor\n const newColor = (colorClass as any)[this.semanticKey] as UIColor | undefined\n \n if (!newColor) { return }\n \n this.stringValue = newColor.stringValue\n \n const element = this._elementRef\n \n if (!element || !this._styleProperty) { return }\n \n (element.style as any)[this._styleProperty] = this.stringValue\n \n }\n \n \n /**\n * Assigns a semantic key and the class that owns it to this color instance.\n * Intended for derived colors that should participate in theme switching,\n * e.g. `BSColor._primaryBase.colorWithAlpha(0.5).withSemanticKey(\"primaryShadow\", BSColor)`.\n * Returns `this` for fluent chaining.\n */\n withSemanticKey(semanticKey: UIColorSemanticKey, semanticClass: typeof UIColor): this {\n this.semanticKey = semanticKey\n this._semanticClass = semanticClass\n return this\n }\n \n \n /**\n * Iterates all live registered UIColor instances, calls apply() on each,\n * compacts dead WeakRefs in the same pass, then fires any CSS subscriptions\n * whose semantic key was affected.\n */\n static applySemanticColors() {\n \n const affectedKeys = new Set<UIColorSemanticKey>()\n \n const live: WeakRef<UIColor>[] = []\n \n for (const ref of UIColor._liveColors) {\n \n const color = ref.deref()\n \n if (!color) {\n continue\n }\n \n live.push(ref)\n \n if (color.semanticKey) {\n affectedKeys.add(color.semanticKey)\n }\n \n color.apply()\n \n }\n \n UIColor._liveColors = live\n \n for (const key of affectedKeys) {\n UIColor._cssSubscriptions.get(key)?.forEach(callback => callback())\n }\n \n }\n \n \n /**\n * Registers a callback to be fired when applySemanticColors() affects\n * the given semantic key. Intended for injected CSS blocks that cannot\n * be tracked via the colorStyleProxy.\n */\n static subscribe(semanticKey: UIColorSemanticKey, callback: () => void) {\n \n if (!UIColor._cssSubscriptions.has(semanticKey)) {\n UIColor._cssSubscriptions.set(semanticKey, new Set())\n }\n \n UIColor._cssSubscriptions.get(semanticKey)!.add(callback)\n \n }\n \n \n static unsubscribe(semanticKey: UIColorSemanticKey, callback: () => void) {\n UIColor._cssSubscriptions.get(semanticKey)?.delete(callback)\n }\n \n \n // --- Named colors ---\n \n static get redColor() {\n return new UIColor(\"red\")\n }\n \n static get blueColor() {\n return new UIColor(\"blue\")\n }\n \n static get greenColor() {\n return new UIColor(\"green\")\n }\n \n static get yellowColor() {\n return new UIColor(\"yellow\")\n }\n \n static get blackColor() {\n return new UIColor(\"black\")\n }\n \n static get brownColor() {\n return new UIColor(\"brown\")\n }\n \n static get whiteColor() {\n return new UIColor(\"white\")\n }\n \n static get greyColor() {\n return new UIColor(\"grey\")\n }\n \n static get lightGreyColor() {\n return new UIColor(\"lightgrey\")\n }\n \n static get transparentColor() {\n return new UIColor(\"transparent\")\n }\n \n static get clearColor() {\n return new UIColor(\"transparent\")\n }\n \n static get undefinedColor() {\n return new UIColor(\"\")\n }\n \n static get nilColor() {\n return new UIColor(\"\")\n }\n \n \n static nameToHex(name: string) {\n return {\n \"aliceblue\": \"#f0f8ff\",\n \"antiquewhite\": \"#faebd7\",\n \"aqua\": \"#00ffff\",\n \"aquamarine\": \"#7fffd4\",\n \"azure\": \"#f0ffff\",\n \"beige\": \"#f5f5dc\",\n \"bisque\": \"#ffe4c4\",\n \"black\": \"#000000\",\n \"blanchedalmond\": \"#ffebcd\",\n \"blue\": \"#0000ff\",\n \"blueviolet\": \"#8a2be2\",\n \"brown\": \"#a52a2a\",\n \"burlywood\": \"#deb887\",\n \"cadetblue\": \"#5f9ea0\",\n \"chartreuse\": \"#7fff00\",\n \"chocolate\": \"#d2691e\",\n \"coral\": \"#ff7f50\",\n \"cornflowerblue\": \"#6495ed\",\n \"cornsilk\": \"#fff8dc\",\n \"crimson\": \"#dc143c\",\n \"cyan\": \"#00ffff\",\n \"darkblue\": \"#00008b\",\n \"darkcyan\": \"#008b8b\",\n \"darkgoldenrod\": \"#b8860b\",\n \"darkgray\": \"#a9a9a9\",\n \"darkgreen\": \"#006400\",\n \"darkkhaki\": \"#bdb76b\",\n \"darkmagenta\": \"#8b008b\",\n \"darkolivegreen\": \"#556b2f\",\n \"darkorange\": \"#ff8c00\",\n \"darkorchid\": \"#9932cc\",\n \"darkred\": \"#8b0000\",\n \"darksalmon\": \"#e9967a\",\n \"darkseagreen\": \"#8fbc8f\",\n \"darkslateblue\": \"#483d8b\",\n \"darkslategray\": \"#2f4f4f\",\n \"darkturquoise\": \"#00ced1\",\n \"darkviolet\": \"#9400d3\",\n \"deeppink\": \"#ff1493\",\n \"deepskyblue\": \"#00bfff\",\n \"dimgray\": \"#696969\",\n \"dodgerblue\": \"#1e90ff\",\n \"firebrick\": \"#b22222\",\n \"floralwhite\": \"#fffaf0\",\n \"forestgreen\": \"#228b22\",\n \"fuchsia\": \"#ff00ff\",\n \"gainsboro\": \"#dcdcdc\",\n \"ghostwhite\": \"#f8f8ff\",\n \"gold\": \"#ffd700\",\n \"goldenrod\": \"#daa520\",\n \"gray\": \"#808080\",\n \"green\": \"#008000\",\n \"greenyellow\": \"#adff2f\",\n \"honeydew\": \"#f0fff0\",\n \"hotpink\": \"#ff69b4\",\n \"indianred \": \"#cd5c5c\",\n \"indigo\": \"#4b0082\",\n \"ivory\": \"#fffff0\",\n \"khaki\": \"#f0e68c\",\n \"lavender\": \"#e6e6fa\",\n \"lavenderblush\": \"#fff0f5\",\n \"lawngreen\": \"#7cfc00\",\n \"lemonchiffon\": \"#fffacd\",\n \"lightblue\": \"#add8e6\",\n \"lightcoral\": \"#f08080\",\n \"lightcyan\": \"#e0ffff\",\n \"lightgoldenrodyellow\": \"#fafad2\",\n \"lightgrey\": \"#d3d3d3\",\n \"lightgreen\": \"#90ee90\",\n \"lightpink\": \"#ffb6c1\",\n \"lightsalmon\": \"#ffa07a\",\n \"lightseagreen\": \"#20b2aa\",\n \"lightskyblue\": \"#87cefa\",\n \"lightslategray\": \"#778899\",\n \"lightsteelblue\": \"#b0c4de\",\n \"lightyellow\": \"#ffffe0\",\n \"lime\": \"#00ff00\",\n \"limegreen\": \"#32cd32\",\n \"linen\": \"#faf0e6\",\n \"magenta\": \"#ff00ff\",\n \"maroon\": \"#800000\",\n \"mediumaquamarine\": \"#66cdaa\",\n \"mediumblue\": \"#0000cd\",\n \"mediumorchid\": \"#ba55d3\",\n \"mediumpurple\": \"#9370d8\",\n \"mediumseagreen\": \"#3cb371\",\n \"mediumslateblue\": \"#7b68ee\",\n \"mediumspringgreen\": \"#00fa9a\",\n \"mediumturquoise\": \"#48d1cc\",\n \"mediumvioletred\": \"#c71585\",\n \"midnightblue\": \"#191970\",\n \"mintcream\": \"#f5fffa\",\n \"mistyrose\": \"#ffe4e1\",\n \"moccasin\": \"#ffe4b5\",\n \"navajowhite\": \"#ffdead\",\n \"navy\": \"#000080\",\n \"oldlace\": \"#fdf5e6\",\n \"olive\": \"#808000\",\n \"olivedrab\": \"#6b8e23\",\n \"orange\": \"#ffa500\",\n \"orangered\": \"#ff4500\",\n \"orchid\": \"#da70d6\",\n \"palegoldenrod\": \"#eee8aa\",\n \"palegreen\": \"#98fb98\",\n \"paleturquoise\": \"#afeeee\",\n \"palevioletred\": \"#d87093\",\n \"papayawhip\": \"#ffefd5\",\n \"peachpuff\": \"#ffdab9\",\n \"peru\": \"#cd853f\",\n \"pink\": \"#ffc0cb\",\n \"plum\": \"#dda0dd\",\n \"powderblue\": \"#b0e0e6\",\n \"purple\": \"#800080\",\n \"red\": \"#ff0000\",\n \"rosybrown\": \"#bc8f8f\",\n \"royalblue\": \"#4169e1\",\n \"saddlebrown\": \"#8b4513\",\n \"salmon\": \"#fa8072\",\n \"sandybrown\": \"#f4a460\",\n \"seagreen\": \"#2e8b57\",\n \"seashell\": \"#fff5ee\",\n \"sienna\": \"#a0522d\",\n \"silver\": \"#c0c0c0\",\n \"skyblue\": \"#87ceeb\",\n \"slateblue\": \"#6a5acd\",\n \"slategray\": \"#708090\",\n \"snow\": \"#fffafa\",\n \"springgreen\": \"#00ff7f\",\n \"steelblue\": \"#4682b4\",\n \"tan\": \"#d2b48c\",\n \"teal\": \"#008080\",\n \"thistle\": \"#d8bfd8\",\n \"tomato\": \"#ff6347\",\n \"turquoise\": \"#40e0d0\",\n \"violet\": \"#ee82ee\",\n \"wheat\": \"#f5deb3\",\n \"white\": \"#ffffff\",\n \"whitesmoke\": \"#f5f5f5\",\n \"yellow\": \"#ffff00\",\n \"yellowgreen\": \"#9acd32\"\n }[name.toLowerCase()]\n }\n \n \n static hexToDescriptor(c: string): UIColorDescriptor {\n if (c[0] === \"#\") {\n c = c.substr(1)\n }\n const r = parseInt(c.slice(0, 2), 16)\n const g = parseInt(c.slice(2, 4), 16)\n const b = parseInt(c.slice(4, 6), 16)\n const a = parseInt(c.slice(6, 8), 16)\n \n const result = { \"red\": r, \"green\": g, \"blue\": b, \"alpha\": a }\n \n return result\n \n //return 'rgb(' + r + ',' + g + ',' + b + ')';\n \n }\n \n static rgbToDescriptor(colorString: string) {\n \n if (colorString.startsWith(\"rgba(\")) {\n colorString = colorString.slice(5, colorString.length - 1)\n }\n \n if (colorString.startsWith(\"rgb(\")) {\n colorString = colorString.slice(4, colorString.length - 1) + \", 0\"\n }\n \n const components = colorString.split(\",\")\n \n const result = {\n \"red\": Number(components[0]),\n \"green\": Number(components[1]),\n \"blue\": Number(components[2]),\n \"alpha\": Number(components[3])\n }\n \n return result\n \n }\n \n \n get colorDescriptor(): UIColorDescriptor {\n \n var descriptor\n \n const colorHEXFromName = UIColor.nameToHex(this.stringValue)\n \n if (this.stringValue.startsWith(\"rgb\")) {\n descriptor = UIColor.rgbToDescriptor(this.stringValue)\n }\n else if (colorHEXFromName) {\n descriptor = UIColor.hexToDescriptor(colorHEXFromName)\n }\n else {\n descriptor = UIColor.hexToDescriptor(this.stringValue)\n }\n \n return descriptor\n \n }\n \n \n colorWithRed(red: number) {\n \n const descriptor = this.colorDescriptor\n \n return new UIColor(\n \"rgba(\" + red + \",\" + descriptor.green + \",\" + descriptor.blue + \",\" + descriptor.alpha + \")\"\n )\n \n }\n \n colorWithGreen(green: number) {\n \n const descriptor = this.colorDescriptor\n \n return new UIColor(\n \"rgba(\" + descriptor.red + \",\" + green + \",\" + descriptor.blue + \",\" + descriptor.alpha + \")\"\n )\n \n }\n \n colorWithBlue(blue: number) {\n \n const descriptor = this.colorDescriptor\n \n return new UIColor(\n \"rgba(\" + descriptor.red + \",\" + descriptor.green + \",\" + blue + \",\" + descriptor.alpha + \")\"\n )\n \n }\n \n colorWithAlpha(alpha: number) {\n \n const descriptor = this.colorDescriptor\n \n return new UIColor(\n \"rgba(\" + descriptor.red + \",\" + descriptor.green + \",\" + descriptor.blue + \",\" + alpha + \")\"\n )\n \n }\n \n static colorWithRGBA(red: number, green: number, blue: number, alpha: number = 1) {\n \n const result = new UIColor(\"rgba(\" + red + \",\" + green + \",\" + blue + \",\" + alpha + \")\")\n \n return result\n \n }\n \n static colorWithDescriptor(descriptor: UIColorDescriptor) {\n \n const result = new UIColor(\"rgba(\" + descriptor.red.toFixed(0) + \",\" + descriptor.green.toFixed(0) + \",\" +\n descriptor.blue.toFixed(0) + \",\" + this.defaultAlphaToOne(descriptor.alpha) + \")\")\n \n return result\n \n }\n \n \n private static defaultAlphaToOne(value = 1) {\n if (value != value) {\n value = 1\n }\n return value\n }\n \n \n colorByMultiplyingRGB(multiplier: number) {\n \n const descriptor = this.colorDescriptor\n \n descriptor.red = descriptor.red * multiplier\n descriptor.green = descriptor.green * multiplier\n descriptor.blue = descriptor.blue * multiplier\n \n return UIColor.colorWithDescriptor(descriptor)\n \n }\n \n \n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -55,6 +55,13 @@ export declare class UITextField extends UITextView {
|
|
|
55
55
|
set placeholderText(text: string);
|
|
56
56
|
get placeholderText(): string;
|
|
57
57
|
setPlaceholderText(key: string, defaultString: string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Controls whether the browser is allowed to autofill this field.
|
|
60
|
+
* Defaults to YES. Set to NO for sensitive fields such as passwords
|
|
61
|
+
* in registration or reset flows where autofill is undesirable.
|
|
62
|
+
*/
|
|
63
|
+
get autocompleteEnabled(): boolean;
|
|
64
|
+
set autocompleteEnabled(enabled: boolean);
|
|
58
65
|
didReceiveBroadcastEvent(event: UIViewBroadcastEvent): void;
|
|
59
66
|
willMoveToSuperview(superview: UIView): void;
|
|
60
67
|
_setPlaceholderFromKeyIfPossible(): void;
|
|
@@ -91,6 +91,22 @@ const _UITextField = class extends import_UITextView.UITextView {
|
|
|
91
91
|
const languageName = import_UICore.UICore.languageService.currentLanguageKey;
|
|
92
92
|
this.placeholderText = import_UICore.UICore.languageService.stringForKey(key, languageName, defaultString, import_UIObject.nil);
|
|
93
93
|
}
|
|
94
|
+
get autocompleteEnabled() {
|
|
95
|
+
const value = this.textElementView.viewHTMLElement.getAttribute("autocomplete");
|
|
96
|
+
return value === null || value === "" || value === "on";
|
|
97
|
+
}
|
|
98
|
+
set autocompleteEnabled(enabled) {
|
|
99
|
+
if (enabled) {
|
|
100
|
+
this.textElementView.viewHTMLElement.removeAttribute("autocomplete");
|
|
101
|
+
} else {
|
|
102
|
+
const type = this.textElementView.viewHTMLElement.type;
|
|
103
|
+
if (type === "password") {
|
|
104
|
+
this.textElementView.viewHTMLElement.setAttribute("autocomplete", "new-password one-time-code");
|
|
105
|
+
} else {
|
|
106
|
+
this.textElementView.viewHTMLElement.setAttribute("autocomplete", "off");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
94
110
|
didReceiveBroadcastEvent(event) {
|
|
95
111
|
super.didReceiveBroadcastEvent(event);
|
|
96
112
|
if (event.name == import_UIView.UIView.broadcastEventName.LanguageChanged || event.name == import_UIView.UIView.broadcastEventName.AddedToViewTree) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../scripts/UITextField.ts"],
|
|
4
|
-
"sourcesContent": ["import { UIColor } from \"./UIColor\"\nimport { UICore } from \"./UICore\"\nimport { nil, NO, ValueOf, YES } from \"./UIObject\"\nimport { UITextView } from \"./UITextView\"\nimport { UIView, UIViewAddControlEventTargetObject, UIViewBroadcastEvent } from \"./UIView\"\n\n\nexport class UITextField extends UITextView {\n \n _placeholderTextKey?: string\n _defaultPlaceholderText?: string\n \n override _viewHTMLElement!: HTMLInputElement\n \n // --- Native Autocomplete (HTML datalist) ---\n \n _datalistElement?: HTMLDataListElement\n _nativeAutocompleteData: string[] = []\n _hasCommittedSelection: boolean = NO\n \n /** Minimum characters required before showing autocomplete suggestions */\n minCharactersForAutocomplete: number = 0\n \n /**\n * When YES, hides the datalist if the current text exactly matches\n * a single autocomplete option (avoids showing redundant single suggestion).\n * Default is YES for better UX.\n */\n hideNativeAutocompleteOnExactMatch: boolean = YES\n \n // --- Validation against autocomplete list ---\n \n _validatesAgainstNativeAutocomplete: boolean = NO\n _isValidAgainstNativeAutocomplete: boolean = YES\n _validationInvalidBackgroundColor = UIColor.redColor.colorWithAlpha(0.5)\n _validationInvalidBorderColor = UIColor.colorWithRGBA(200, 0, 0, 0.5)\n \n \n static override controlEvent = Object.assign({}, UITextView.controlEvent, {\n \n \"TextChange\": \"TextChange\",\n \"ValidationChange\": \"ValidationChange\"\n \n })\n \n \n constructor(\n elementID?: string,\n viewHTMLElement = null,\n type: string | ValueOf<typeof UITextView.type> = UITextView.type.textField\n ) {\n \n super(elementID, type, viewHTMLElement)\n \n this.textElementView.viewHTMLElement.setAttribute(\"type\", \"text\")\n this.backgroundColor = UIColor.transparentColor\n this.addTargetForControlEvent(\n UIView.controlEvent.PointerUpInside,\n (sender, event) => sender.focus()\n )\n this.textElementView.viewHTMLElement.oninput = (event) => {\n this._hasCommittedSelection = NO\n this.sendControlEventForKey(UITextField.controlEvent.TextChange, event)\n this._validateAgainstNativeAutocompleteIfNeeded()\n this._updateDatalistVisibility()\n }\n this.textElementView.viewHTMLElement.onchange = (event) => {\n this.sendControlEventForKey(UITextField.controlEvent.TextChange, event)\n // Fires when the user commits a selection from the datalist (enter or click).\n // Regular typing does not trigger onchange, only committing a value does.\n if (this._datalistElement && this._nativeAutocompleteData.includes(this.text)) {\n this._hasCommittedSelection = YES\n this._updateDatalistVisibility()\n }\n // Validate on change (commit) when validation is enabled\n this._validateAgainstNativeAutocompleteIfNeeded()\n }\n this.textElementView.controlEventTargetAccumulator.Blur = (sender, event) => {\n // Final validation when leaving the field\n this._validateAgainstNativeAutocompleteIfNeeded()\n }\n this.textElementView.style.webkitUserSelect = \"text\"\n this.nativeSelectionEnabled = YES\n this.pausesPointerEvents = NO\n this.changesOften = YES\n \n }\n \n \n override get controlEventTargetAccumulator(): UIViewAddControlEventTargetObject<typeof UITextField> {\n return (super.controlEventTargetAccumulator as any)\n }\n \n public override get viewHTMLElement() {\n return this._viewHTMLElement\n }\n \n \n public override set text(text: string) {\n this.textElementView.viewHTMLElement.value = text\n // Re-validate when text is set programmatically\n this._validateAgainstNativeAutocompleteIfNeeded()\n this._updateDatalistVisibility()\n }\n \n public override get text(): string {\n return this.textElementView.viewHTMLElement.value\n }\n \n \n public set placeholderText(text: string) {\n this.textElementView.viewHTMLElement.placeholder = text\n }\n \n public get placeholderText(): string {\n return this.textElementView.viewHTMLElement.placeholder\n }\n \n \n setPlaceholderText(key: string, defaultString: string) {\n \n this._placeholderTextKey = key\n this._defaultPlaceholderText = defaultString\n \n const languageName = UICore.languageService.currentLanguageKey\n this.placeholderText = UICore.languageService.stringForKey(key, languageName, defaultString, nil)\n \n }\n \n \n override didReceiveBroadcastEvent(event: UIViewBroadcastEvent) {\n \n super.didReceiveBroadcastEvent(event)\n \n if (event.name == UIView.broadcastEventName.LanguageChanged || event.name ==\n UIView.broadcastEventName.AddedToViewTree) {\n \n this._setPlaceholderFromKeyIfPossible()\n \n }\n \n }\n \n \n override willMoveToSuperview(superview: UIView) {\n \n super.willMoveToSuperview(superview)\n \n this._setPlaceholderFromKeyIfPossible()\n \n }\n \n _setPlaceholderFromKeyIfPossible() {\n \n if (this._placeholderTextKey && this._defaultPlaceholderText) {\n \n this.setPlaceholderText(this._placeholderTextKey, this._defaultPlaceholderText)\n \n }\n \n }\n \n \n public get isSecure(): boolean {\n const result = (this.textElementView.viewHTMLElement.type == \"password\")\n return result\n }\n \n public set isSecure(secure: boolean) {\n let type = \"text\"\n if (secure) {\n type = \"password\"\n }\n this.textElementView.viewHTMLElement.type = type\n }\n \n \n // MARK: - Native Autocomplete Methods\n \n /**\n * Sets the data for native browser autocomplete using HTML datalist.\n * Setting an empty array will remove the autocomplete functionality.\n *\n * @param data Array of strings to show as autocomplete suggestions\n */\n public set nativeAutocompleteData(data: string[]) {\n this._nativeAutocompleteData = data\n this._hasCommittedSelection = NO\n this._updateDatalist()\n this._validateAgainstNativeAutocompleteIfNeeded()\n this._updateDatalistVisibility()\n }\n \n public get nativeAutocompleteData(): string[] {\n return this._nativeAutocompleteData\n }\n \n // MARK: - Validation Methods\n \n /**\n * When enabled, the text field will validate its content against the autocomplete list.\n * Invalid values will trigger a ValidationChange event and can be checked via isValidAgainstAutocomplete.\n *\n * Empty text is always considered valid (use required field validation separately if needed).\n */\n public set validatesAgainstNativeAutocomplete(validate: boolean) {\n if (this._validatesAgainstNativeAutocomplete !== validate) {\n this._validatesAgainstNativeAutocomplete = validate\n this._validateAgainstNativeAutocompleteIfNeeded()\n }\n }\n \n public get validatesAgainstNativeAutocomplete(): boolean {\n return this._validatesAgainstNativeAutocomplete\n }\n \n /**\n * Returns YES if the current text value is valid according to autocomplete validation.\n * Always returns YES if validatesAgainstAutocomplete is disabled.\n * Empty text is considered valid.\n */\n public get isValidAgainstNativeAutocomplete(): boolean {\n return this._isValidAgainstNativeAutocomplete\n }\n \n /**\n * Background color to apply when validation fails.\n * Set to nil to disable background color change on invalid state.\n */\n public set validationInvalidBackgroundColor(color: UIColor) {\n this._validationInvalidBackgroundColor = color\n this._updateValidationVisualState()\n }\n \n public get validationInvalidBackgroundColor(): UIColor {\n return this._validationInvalidBackgroundColor\n }\n \n /**\n * Border color to apply when validation fails.\n * Set to nil to disable border color change on invalid state.\n */\n public set validationInvalidBorderColor(color: UIColor) {\n this._validationInvalidBorderColor = color\n this._updateValidationVisualState()\n }\n \n public get validationInvalidBorderColor(): UIColor {\n return this._validationInvalidBorderColor\n }\n \n /**\n * Validates the current text against the autocomplete list if validation is enabled.\n * Updates the _isValidAgainstAutocomplete flag and fires ValidationChange event on state change.\n */\n _validateAgainstNativeAutocompleteIfNeeded() {\n if (!this._validatesAgainstNativeAutocomplete) {\n this._setValidationState(YES)\n return\n }\n \n const currentText = this.text\n \n // Empty text is considered valid (use separate required validation if needed)\n if (currentText.length === 0) {\n this._setValidationState(YES)\n return\n }\n \n const isValid = this._nativeAutocompleteData.includes(currentText)\n this._setValidationState(isValid)\n }\n \n _setValidationState(isValid: boolean) {\n const wasValid = this._isValidAgainstNativeAutocomplete\n this._isValidAgainstNativeAutocomplete = isValid\n \n // Update visual state\n this._updateValidationVisualState()\n \n // Fire event only on state change\n if (wasValid !== isValid) {\n this.sendControlEventForKey(UITextField.controlEvent.ValidationChange)\n }\n }\n \n /**\n * Updates the visual state of the text field based on validation status.\n * Override this method to customize validation styling.\n */\n _updateValidationVisualState() {\n const inputElement = this.textElementView.viewHTMLElement\n \n if (!this._validatesAgainstNativeAutocomplete || this._isValidAgainstNativeAutocomplete) {\n // Restore normal state - clear validation-specific styles\n inputElement.classList.remove(\"autocomplete-invalid\")\n \n // Reset to default colors if we had set validation colors\n if (this._validationInvalidBackgroundColor) {\n inputElement.style.removeProperty(\"background-color\")\n }\n if (this._validationInvalidBorderColor) {\n inputElement.style.removeProperty(\"border-color\")\n }\n } else {\n // Apply invalid state\n inputElement.classList.add(\"autocomplete-invalid\")\n \n // Apply validation colors if set\n if (this._validationInvalidBackgroundColor) {\n inputElement.style.backgroundColor = this._validationInvalidBackgroundColor.stringValue\n }\n if (this._validationInvalidBorderColor) {\n inputElement.style.borderColor = this._validationInvalidBorderColor.stringValue\n }\n }\n }\n \n /**\n * Clears the text field if the current value is not in the autocomplete list.\n * Useful for enforcing selection from the list only.\n * @returns YES if the text was cleared (was invalid), NO otherwise\n */\n public clearIfInvalid(): boolean {\n if (this._validatesAgainstNativeAutocomplete && !this._isValidAgainstNativeAutocomplete && this.text.length > 0) {\n this.text = \"\"\n return YES\n }\n return NO\n }\n \n /**\n * Returns a list of autocomplete options that match the current text (case-insensitive).\n * Useful for implementing custom filtering or showing filtered results elsewhere.\n */\n public getMatchingAutocompleteOptions(): string[] {\n const currentText = this.text\n if (currentText.length === 0) {\n return [...this._nativeAutocompleteData]\n }\n return this._getFilteredAutocompleteOptions(currentText)\n }\n \n // MARK: - Datalist Management\n \n _updateDatalist() {\n // If no data, remove the datalist\n if (this._nativeAutocompleteData.length === 0) {\n if (this._datalistElement) {\n this._datalistElement.remove()\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n this._datalistElement = undefined\n }\n return\n }\n \n // Create datalist if it doesn't exist\n if (!this._datalistElement) {\n const datalistId = this.elementID + \"_datalist\"\n this._datalistElement = document.createElement(\"datalist\")\n this._datalistElement.id = datalistId\n // Add datalist as a sibling to the text element within this view's container\n this.viewHTMLElement.appendChild(this._datalistElement)\n this.textElementView.viewHTMLElement.setAttribute(\"list\", datalistId)\n }\n \n // Update the options\n this._datalistElement.innerHTML = \"\"\n this._nativeAutocompleteData.forEach(item => {\n const option = document.createElement(\"option\")\n option.value = item\n this._datalistElement!.appendChild(option)\n })\n }\n \n _updateDatalistVisibility() {\n if (!this._datalistElement) {\n return\n }\n \n // After the user has picked a value from the list, hide suggestions until\n // they start typing again. oninput clears _hasCommittedSelection, so this\n // gate only holds for exactly as long as the selection stands untouched.\n if (this._hasCommittedSelection) {\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n return\n }\n \n const currentText = this.text\n \n // Check minimum character requirement\n if (this.minCharactersForAutocomplete > 0 &&\n currentText.length < this.minCharactersForAutocomplete) {\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n return\n }\n \n // Hide datalist when it would show only a single redundant option\n if (this.hideNativeAutocompleteOnExactMatch && currentText.length > 0) {\n // Count how many options would be offered (browser uses starts-with logic)\n const matchingOptions = this._nativeAutocompleteData.filter(item =>\n item.toLowerCase().startsWith(currentText.toLowerCase()) ||\n currentText.toLowerCase().startsWith(item.toLowerCase())\n )\n \n // If only one option matches, it's redundant - hide the datalist\n if (matchingOptions.length === 1) {\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n return\n }\n }\n \n // Show the datalist\n this.textElementView.viewHTMLElement.setAttribute(\"list\", this._datalistElement.id)\n }\n \n /**\n * Returns autocomplete options that match the given search text.\n * Uses case-insensitive substring matching (consistent with browser behavior).\n */\n _getFilteredAutocompleteOptions(searchText: string): string[] {\n const searchLower = searchText.toLowerCase()\n return this._nativeAutocompleteData.filter(item =>\n item.toLowerCase().includes(searchLower)\n )\n }\n \n override wasRemovedFromViewTree() {\n \n super.wasRemovedFromViewTree()\n \n // Clean up datalist element when text field is removed\n if (this._datalistElement) {\n this._datalistElement.remove()\n this._datalistElement = undefined\n }\n \n }\n \n \n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAwB;AACxB,oBAAuB;AACvB,sBAAsC;AACtC,wBAA2B;AAC3B,oBAAgF;AAGzE,MAAM,eAAN,cAA0B,6BAAW;AAAA,EAuCxC,YACI,WACA,kBAAkB,MAClB,OAAiD,6BAAW,KAAK,WACnE;AAEE,UAAM,WAAW,MAAM,eAAe;AAnC1C,mCAAoC,CAAC;AACrC,kCAAkC;AAGlC,wCAAuC;AAOvC,8CAA8C;AAI9C,+CAA+C;AAC/C,6CAA6C;AAC7C,6CAAoC,uBAAQ,SAAS,eAAe,GAAG;AACvE,yCAAgC,uBAAQ,cAAc,KAAK,GAAG,GAAG,GAAG;AAmBhE,SAAK,gBAAgB,gBAAgB,aAAa,QAAQ,MAAM;AAChE,SAAK,kBAAkB,uBAAQ;AAC/B,SAAK;AAAA,MACD,qBAAO,aAAa;AAAA,MACpB,CAAC,QAAQ,UAAU,OAAO,MAAM;AAAA,IACpC;AACA,SAAK,gBAAgB,gBAAgB,UAAU,CAAC,UAAU;AACtD,WAAK,yBAAyB;AAC9B,WAAK,uBAAuB,aAAY,aAAa,YAAY,KAAK;AACtE,WAAK,2CAA2C;AAChD,WAAK,0BAA0B;AAAA,IACnC;AACA,SAAK,gBAAgB,gBAAgB,WAAW,CAAC,UAAU;AACvD,WAAK,uBAAuB,aAAY,aAAa,YAAY,KAAK;AAGtE,UAAI,KAAK,oBAAoB,KAAK,wBAAwB,SAAS,KAAK,IAAI,GAAG;AAC3E,aAAK,yBAAyB;AAC9B,aAAK,0BAA0B;AAAA,MACnC;AAEA,WAAK,2CAA2C;AAAA,IACpD;AACA,SAAK,gBAAgB,8BAA8B,OAAO,CAAC,QAAQ,UAAU;AAEzE,WAAK,2CAA2C;AAAA,IACpD;AACA,SAAK,gBAAgB,MAAM,mBAAmB;AAC9C,SAAK,yBAAyB;AAC9B,SAAK,sBAAsB;AAC3B,SAAK,eAAe;AAAA,EAExB;AAAA,EAGA,IAAa,gCAAuF;AAChG,WAAQ,MAAM;AAAA,EAClB;AAAA,EAEA,IAAoB,kBAAkB;AAClC,WAAO,KAAK;AAAA,EAChB;AAAA,EAGA,IAAoB,KAAK,MAAc;AACnC,SAAK,gBAAgB,gBAAgB,QAAQ;AAE7C,SAAK,2CAA2C;AAChD,SAAK,0BAA0B;AAAA,EACnC;AAAA,EAEA,IAAoB,OAAe;AAC/B,WAAO,KAAK,gBAAgB,gBAAgB;AAAA,EAChD;AAAA,EAGA,IAAW,gBAAgB,MAAc;AACrC,SAAK,gBAAgB,gBAAgB,cAAc;AAAA,EACvD;AAAA,EAEA,IAAW,kBAA0B;AACjC,WAAO,KAAK,gBAAgB,gBAAgB;AAAA,EAChD;AAAA,EAGA,mBAAmB,KAAa,eAAuB;AAEnD,SAAK,sBAAsB;AAC3B,SAAK,0BAA0B;AAE/B,UAAM,eAAe,qBAAO,gBAAgB;AAC5C,SAAK,kBAAkB,qBAAO,gBAAgB,aAAa,KAAK,cAAc,eAAe,mBAAG;AAAA,EAEpG;AAAA,EAGS,yBAAyB,OAA6B;AAE3D,UAAM,yBAAyB,KAAK;AAEpC,QAAI,MAAM,QAAQ,qBAAO,mBAAmB,mBAAmB,MAAM,QACjE,qBAAO,mBAAmB,iBAAiB;AAE3C,WAAK,iCAAiC;AAAA,IAE1C;AAAA,EAEJ;AAAA,EAGS,oBAAoB,WAAmB;AAE5C,UAAM,oBAAoB,SAAS;AAEnC,SAAK,iCAAiC;AAAA,EAE1C;AAAA,EAEA,mCAAmC;AAE/B,QAAI,KAAK,uBAAuB,KAAK,yBAAyB;AAE1D,WAAK,mBAAmB,KAAK,qBAAqB,KAAK,uBAAuB;AAAA,IAElF;AAAA,EAEJ;AAAA,EAGA,IAAW,WAAoB;AAC3B,UAAM,SAAU,KAAK,gBAAgB,gBAAgB,QAAQ;AAC7D,WAAO;AAAA,EACX;AAAA,EAEA,IAAW,SAAS,QAAiB;AACjC,QAAI,OAAO;AACX,QAAI,QAAQ;AACR,aAAO;AAAA,IACX;AACA,SAAK,gBAAgB,gBAAgB,OAAO;AAAA,EAChD;AAAA,EAWA,IAAW,uBAAuB,MAAgB;AAC9C,SAAK,0BAA0B;AAC/B,SAAK,yBAAyB;AAC9B,SAAK,gBAAgB;AACrB,SAAK,2CAA2C;AAChD,SAAK,0BAA0B;AAAA,EACnC;AAAA,EAEA,IAAW,yBAAmC;AAC1C,WAAO,KAAK;AAAA,EAChB;AAAA,EAUA,IAAW,mCAAmC,UAAmB;AAC7D,QAAI,KAAK,wCAAwC,UAAU;AACvD,WAAK,sCAAsC;AAC3C,WAAK,2CAA2C;AAAA,IACpD;AAAA,EACJ;AAAA,EAEA,IAAW,qCAA8C;AACrD,WAAO,KAAK;AAAA,EAChB;AAAA,EAOA,IAAW,mCAA4C;AACnD,WAAO,KAAK;AAAA,EAChB;AAAA,EAMA,IAAW,iCAAiC,OAAgB;AACxD,SAAK,oCAAoC;AACzC,SAAK,6BAA6B;AAAA,EACtC;AAAA,EAEA,IAAW,mCAA4C;AACnD,WAAO,KAAK;AAAA,EAChB;AAAA,EAMA,IAAW,6BAA6B,OAAgB;AACpD,SAAK,gCAAgC;AACrC,SAAK,6BAA6B;AAAA,EACtC;AAAA,EAEA,IAAW,+BAAwC;AAC/C,WAAO,KAAK;AAAA,EAChB;AAAA,EAMA,6CAA6C;AACzC,QAAI,CAAC,KAAK,qCAAqC;AAC3C,WAAK,oBAAoB,mBAAG;AAC5B;AAAA,IACJ;AAEA,UAAM,cAAc,KAAK;AAGzB,QAAI,YAAY,WAAW,GAAG;AAC1B,WAAK,oBAAoB,mBAAG;AAC5B;AAAA,IACJ;AAEA,UAAM,UAAU,KAAK,wBAAwB,SAAS,WAAW;AACjE,SAAK,oBAAoB,OAAO;AAAA,EACpC;AAAA,EAEA,oBAAoB,SAAkB;AAClC,UAAM,WAAW,KAAK;AACtB,SAAK,oCAAoC;AAGzC,SAAK,6BAA6B;AAGlC,QAAI,aAAa,SAAS;AACtB,WAAK,uBAAuB,aAAY,aAAa,gBAAgB;AAAA,IACzE;AAAA,EACJ;AAAA,EAMA,+BAA+B;AAC3B,UAAM,eAAe,KAAK,gBAAgB;AAE1C,QAAI,CAAC,KAAK,uCAAuC,KAAK,mCAAmC;AAErF,mBAAa,UAAU,OAAO,sBAAsB;AAGpD,UAAI,KAAK,mCAAmC;AACxC,qBAAa,MAAM,eAAe,kBAAkB;AAAA,MACxD;AACA,UAAI,KAAK,+BAA+B;AACpC,qBAAa,MAAM,eAAe,cAAc;AAAA,MACpD;AAAA,IACJ,OAAO;AAEH,mBAAa,UAAU,IAAI,sBAAsB;AAGjD,UAAI,KAAK,mCAAmC;AACxC,qBAAa,MAAM,kBAAkB,KAAK,kCAAkC;AAAA,MAChF;AACA,UAAI,KAAK,+BAA+B;AACpC,qBAAa,MAAM,cAAc,KAAK,8BAA8B;AAAA,MACxE;AAAA,IACJ;AAAA,EACJ;AAAA,EAOO,iBAA0B;AAC7B,QAAI,KAAK,uCAAuC,CAAC,KAAK,qCAAqC,KAAK,KAAK,SAAS,GAAG;AAC7G,WAAK,OAAO;AACZ,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA,EAMO,iCAA2C;AAC9C,UAAM,cAAc,KAAK;AACzB,QAAI,YAAY,WAAW,GAAG;AAC1B,aAAO,CAAC,GAAG,KAAK,uBAAuB;AAAA,IAC3C;AACA,WAAO,KAAK,gCAAgC,WAAW;AAAA,EAC3D;AAAA,EAIA,kBAAkB;AAEd,QAAI,KAAK,wBAAwB,WAAW,GAAG;AAC3C,UAAI,KAAK,kBAAkB;AACvB,aAAK,iBAAiB,OAAO;AAC7B,aAAK,gBAAgB,gBAAgB,gBAAgB,MAAM;AAC3D,aAAK,mBAAmB;AAAA,MAC5B;AACA;AAAA,IACJ;AAGA,QAAI,CAAC,KAAK,kBAAkB;AACxB,YAAM,aAAa,KAAK,YAAY;AACpC,WAAK,mBAAmB,SAAS,cAAc,UAAU;AACzD,WAAK,iBAAiB,KAAK;AAE3B,WAAK,gBAAgB,YAAY,KAAK,gBAAgB;AACtD,WAAK,gBAAgB,gBAAgB,aAAa,QAAQ,UAAU;AAAA,IACxE;AAGA,SAAK,iBAAiB,YAAY;AAClC,SAAK,wBAAwB,QAAQ,UAAQ;AACzC,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,QAAQ;AACf,WAAK,iBAAkB,YAAY,MAAM;AAAA,IAC7C,CAAC;AAAA,EACL;AAAA,EAEA,4BAA4B;AACxB,QAAI,CAAC,KAAK,kBAAkB;AACxB;AAAA,IACJ;AAKA,QAAI,KAAK,wBAAwB;AAC7B,WAAK,gBAAgB,gBAAgB,gBAAgB,MAAM;AAC3D;AAAA,IACJ;AAEA,UAAM,cAAc,KAAK;AAGzB,QAAI,KAAK,+BAA+B,KACpC,YAAY,SAAS,KAAK,8BAA8B;AACxD,WAAK,gBAAgB,gBAAgB,gBAAgB,MAAM;AAC3D;AAAA,IACJ;AAGA,QAAI,KAAK,sCAAsC,YAAY,SAAS,GAAG;AAEnE,YAAM,kBAAkB,KAAK,wBAAwB;AAAA,QAAO,UACxD,KAAK,YAAY,EAAE,WAAW,YAAY,YAAY,CAAC,KACvD,YAAY,YAAY,EAAE,WAAW,KAAK,YAAY,CAAC;AAAA,MAC3D;AAGA,UAAI,gBAAgB,WAAW,GAAG;AAC9B,aAAK,gBAAgB,gBAAgB,gBAAgB,MAAM;AAC3D;AAAA,MACJ;AAAA,IACJ;AAGA,SAAK,gBAAgB,gBAAgB,aAAa,QAAQ,KAAK,iBAAiB,EAAE;AAAA,EACtF;AAAA,EAMA,gCAAgC,YAA8B;AAC1D,UAAM,cAAc,WAAW,YAAY;AAC3C,WAAO,KAAK,wBAAwB;AAAA,MAAO,UACvC,KAAK,YAAY,EAAE,SAAS,WAAW;AAAA,IAC3C;AAAA,EACJ;AAAA,EAES,yBAAyB;AAE9B,UAAM,uBAAuB;AAG7B,QAAI,KAAK,kBAAkB;AACvB,WAAK,iBAAiB,OAAO;AAC7B,WAAK,mBAAmB;AAAA,IAC5B;AAAA,EAEJ;AAGJ;
|
|
4
|
+
"sourcesContent": ["import { UIColor } from \"./UIColor\"\nimport { UICore } from \"./UICore\"\nimport { nil, NO, ValueOf, YES } from \"./UIObject\"\nimport { UITextView } from \"./UITextView\"\nimport { UIView, UIViewAddControlEventTargetObject, UIViewBroadcastEvent } from \"./UIView\"\n\n\nexport class UITextField extends UITextView {\n \n _placeholderTextKey?: string\n _defaultPlaceholderText?: string\n \n override _viewHTMLElement!: HTMLInputElement\n \n // --- Native Autocomplete (HTML datalist) ---\n \n _datalistElement?: HTMLDataListElement\n _nativeAutocompleteData: string[] = []\n _hasCommittedSelection: boolean = NO\n \n /** Minimum characters required before showing autocomplete suggestions */\n minCharactersForAutocomplete: number = 0\n \n /**\n * When YES, hides the datalist if the current text exactly matches\n * a single autocomplete option (avoids showing redundant single suggestion).\n * Default is YES for better UX.\n */\n hideNativeAutocompleteOnExactMatch: boolean = YES\n \n // --- Validation against autocomplete list ---\n \n _validatesAgainstNativeAutocomplete: boolean = NO\n _isValidAgainstNativeAutocomplete: boolean = YES\n _validationInvalidBackgroundColor = UIColor.redColor.colorWithAlpha(0.5)\n _validationInvalidBorderColor = UIColor.colorWithRGBA(200, 0, 0, 0.5)\n \n \n static override controlEvent = Object.assign({}, UITextView.controlEvent, {\n \n \"TextChange\": \"TextChange\",\n \"ValidationChange\": \"ValidationChange\"\n \n })\n \n \n constructor(\n elementID?: string,\n viewHTMLElement = null,\n type: string | ValueOf<typeof UITextView.type> = UITextView.type.textField\n ) {\n \n super(elementID, type, viewHTMLElement)\n \n this.textElementView.viewHTMLElement.setAttribute(\"type\", \"text\")\n this.backgroundColor = UIColor.transparentColor\n this.addTargetForControlEvent(\n UIView.controlEvent.PointerUpInside,\n (sender, event) => sender.focus()\n )\n this.textElementView.viewHTMLElement.oninput = (event) => {\n this._hasCommittedSelection = NO\n this.sendControlEventForKey(UITextField.controlEvent.TextChange, event)\n this._validateAgainstNativeAutocompleteIfNeeded()\n this._updateDatalistVisibility()\n }\n this.textElementView.viewHTMLElement.onchange = (event) => {\n this.sendControlEventForKey(UITextField.controlEvent.TextChange, event)\n // Fires when the user commits a selection from the datalist (enter or click).\n // Regular typing does not trigger onchange, only committing a value does.\n if (this._datalistElement && this._nativeAutocompleteData.includes(this.text)) {\n this._hasCommittedSelection = YES\n this._updateDatalistVisibility()\n }\n // Validate on change (commit) when validation is enabled\n this._validateAgainstNativeAutocompleteIfNeeded()\n }\n this.textElementView.controlEventTargetAccumulator.Blur = (sender, event) => {\n // Final validation when leaving the field\n this._validateAgainstNativeAutocompleteIfNeeded()\n }\n this.textElementView.style.webkitUserSelect = \"text\"\n this.nativeSelectionEnabled = YES\n this.pausesPointerEvents = NO\n this.changesOften = YES\n \n }\n \n \n override get controlEventTargetAccumulator(): UIViewAddControlEventTargetObject<typeof UITextField> {\n return (super.controlEventTargetAccumulator as any)\n }\n \n public override get viewHTMLElement() {\n return this._viewHTMLElement\n }\n \n \n public override set text(text: string) {\n this.textElementView.viewHTMLElement.value = text\n // Re-validate when text is set programmatically\n this._validateAgainstNativeAutocompleteIfNeeded()\n this._updateDatalistVisibility()\n }\n \n public override get text(): string {\n return this.textElementView.viewHTMLElement.value\n }\n \n \n public set placeholderText(text: string) {\n this.textElementView.viewHTMLElement.placeholder = text\n }\n \n public get placeholderText(): string {\n return this.textElementView.viewHTMLElement.placeholder\n }\n \n \n setPlaceholderText(key: string, defaultString: string) {\n \n this._placeholderTextKey = key\n this._defaultPlaceholderText = defaultString\n \n const languageName = UICore.languageService.currentLanguageKey\n this.placeholderText = UICore.languageService.stringForKey(key, languageName, defaultString, nil)\n \n }\n \n \n /**\n * Controls whether the browser is allowed to autofill this field.\n * Defaults to YES. Set to NO for sensitive fields such as passwords\n * in registration or reset flows where autofill is undesirable.\n */\n public get autocompleteEnabled(): boolean {\n const value = this.textElementView.viewHTMLElement.getAttribute(\"autocomplete\")\n return value === null || value === \"\" || value === \"on\"\n }\n \n public set autocompleteEnabled(enabled: boolean) {\n if (enabled) {\n this.textElementView.viewHTMLElement.removeAttribute(\"autocomplete\")\n }\n else {\n const type = this.textElementView.viewHTMLElement.type\n if (type === \"password\") {\n // \"new-password\" prevents autofill; appending \"one-time-code\" suppresses\n // Chrome's offer to save the password after submission\n this.textElementView.viewHTMLElement.setAttribute(\"autocomplete\", \"new-password one-time-code\")\n }\n else {\n this.textElementView.viewHTMLElement.setAttribute(\"autocomplete\", \"off\")\n }\n }\n }\n \n \n override didReceiveBroadcastEvent(event: UIViewBroadcastEvent) {\n \n super.didReceiveBroadcastEvent(event)\n \n if (event.name == UIView.broadcastEventName.LanguageChanged || event.name ==\n UIView.broadcastEventName.AddedToViewTree) {\n \n this._setPlaceholderFromKeyIfPossible()\n \n }\n \n }\n \n \n override willMoveToSuperview(superview: UIView) {\n \n super.willMoveToSuperview(superview)\n \n this._setPlaceholderFromKeyIfPossible()\n \n }\n \n _setPlaceholderFromKeyIfPossible() {\n \n if (this._placeholderTextKey && this._defaultPlaceholderText) {\n \n this.setPlaceholderText(this._placeholderTextKey, this._defaultPlaceholderText)\n \n }\n \n }\n \n \n public get isSecure(): boolean {\n const result = (this.textElementView.viewHTMLElement.type == \"password\")\n return result\n }\n \n public set isSecure(secure: boolean) {\n let type = \"text\"\n if (secure) {\n type = \"password\"\n }\n this.textElementView.viewHTMLElement.type = type\n }\n \n \n // MARK: - Native Autocomplete Methods\n \n /**\n * Sets the data for native browser autocomplete using HTML datalist.\n * Setting an empty array will remove the autocomplete functionality.\n *\n * @param data Array of strings to show as autocomplete suggestions\n */\n public set nativeAutocompleteData(data: string[]) {\n this._nativeAutocompleteData = data\n this._hasCommittedSelection = NO\n this._updateDatalist()\n this._validateAgainstNativeAutocompleteIfNeeded()\n this._updateDatalistVisibility()\n }\n \n public get nativeAutocompleteData(): string[] {\n return this._nativeAutocompleteData\n }\n \n // MARK: - Validation Methods\n \n /**\n * When enabled, the text field will validate its content against the autocomplete list.\n * Invalid values will trigger a ValidationChange event and can be checked via isValidAgainstAutocomplete.\n *\n * Empty text is always considered valid (use required field validation separately if needed).\n */\n public set validatesAgainstNativeAutocomplete(validate: boolean) {\n if (this._validatesAgainstNativeAutocomplete !== validate) {\n this._validatesAgainstNativeAutocomplete = validate\n this._validateAgainstNativeAutocompleteIfNeeded()\n }\n }\n \n public get validatesAgainstNativeAutocomplete(): boolean {\n return this._validatesAgainstNativeAutocomplete\n }\n \n /**\n * Returns YES if the current text value is valid according to autocomplete validation.\n * Always returns YES if validatesAgainstAutocomplete is disabled.\n * Empty text is considered valid.\n */\n public get isValidAgainstNativeAutocomplete(): boolean {\n return this._isValidAgainstNativeAutocomplete\n }\n \n /**\n * Background color to apply when validation fails.\n * Set to nil to disable background color change on invalid state.\n */\n public set validationInvalidBackgroundColor(color: UIColor) {\n this._validationInvalidBackgroundColor = color\n this._updateValidationVisualState()\n }\n \n public get validationInvalidBackgroundColor(): UIColor {\n return this._validationInvalidBackgroundColor\n }\n \n /**\n * Border color to apply when validation fails.\n * Set to nil to disable border color change on invalid state.\n */\n public set validationInvalidBorderColor(color: UIColor) {\n this._validationInvalidBorderColor = color\n this._updateValidationVisualState()\n }\n \n public get validationInvalidBorderColor(): UIColor {\n return this._validationInvalidBorderColor\n }\n \n /**\n * Validates the current text against the autocomplete list if validation is enabled.\n * Updates the _isValidAgainstAutocomplete flag and fires ValidationChange event on state change.\n */\n _validateAgainstNativeAutocompleteIfNeeded() {\n if (!this._validatesAgainstNativeAutocomplete) {\n this._setValidationState(YES)\n return\n }\n \n const currentText = this.text\n \n // Empty text is considered valid (use separate required validation if needed)\n if (currentText.length === 0) {\n this._setValidationState(YES)\n return\n }\n \n const isValid = this._nativeAutocompleteData.includes(currentText)\n this._setValidationState(isValid)\n }\n \n _setValidationState(isValid: boolean) {\n const wasValid = this._isValidAgainstNativeAutocomplete\n this._isValidAgainstNativeAutocomplete = isValid\n \n // Update visual state\n this._updateValidationVisualState()\n \n // Fire event only on state change\n if (wasValid !== isValid) {\n this.sendControlEventForKey(UITextField.controlEvent.ValidationChange)\n }\n }\n \n /**\n * Updates the visual state of the text field based on validation status.\n * Override this method to customize validation styling.\n */\n _updateValidationVisualState() {\n const inputElement = this.textElementView.viewHTMLElement\n \n if (!this._validatesAgainstNativeAutocomplete || this._isValidAgainstNativeAutocomplete) {\n // Restore normal state - clear validation-specific styles\n inputElement.classList.remove(\"autocomplete-invalid\")\n \n // Reset to default colors if we had set validation colors\n if (this._validationInvalidBackgroundColor) {\n inputElement.style.removeProperty(\"background-color\")\n }\n if (this._validationInvalidBorderColor) {\n inputElement.style.removeProperty(\"border-color\")\n }\n } else {\n // Apply invalid state\n inputElement.classList.add(\"autocomplete-invalid\")\n \n // Apply validation colors if set\n if (this._validationInvalidBackgroundColor) {\n inputElement.style.backgroundColor = this._validationInvalidBackgroundColor.stringValue\n }\n if (this._validationInvalidBorderColor) {\n inputElement.style.borderColor = this._validationInvalidBorderColor.stringValue\n }\n }\n }\n \n /**\n * Clears the text field if the current value is not in the autocomplete list.\n * Useful for enforcing selection from the list only.\n * @returns YES if the text was cleared (was invalid), NO otherwise\n */\n public clearIfInvalid(): boolean {\n if (this._validatesAgainstNativeAutocomplete && !this._isValidAgainstNativeAutocomplete && this.text.length > 0) {\n this.text = \"\"\n return YES\n }\n return NO\n }\n \n /**\n * Returns a list of autocomplete options that match the current text (case-insensitive).\n * Useful for implementing custom filtering or showing filtered results elsewhere.\n */\n public getMatchingAutocompleteOptions(): string[] {\n const currentText = this.text\n if (currentText.length === 0) {\n return [...this._nativeAutocompleteData]\n }\n return this._getFilteredAutocompleteOptions(currentText)\n }\n \n // MARK: - Datalist Management\n \n _updateDatalist() {\n // If no data, remove the datalist\n if (this._nativeAutocompleteData.length === 0) {\n if (this._datalistElement) {\n this._datalistElement.remove()\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n this._datalistElement = undefined\n }\n return\n }\n \n // Create datalist if it doesn't exist\n if (!this._datalistElement) {\n const datalistId = this.elementID + \"_datalist\"\n this._datalistElement = document.createElement(\"datalist\")\n this._datalistElement.id = datalistId\n // Add datalist as a sibling to the text element within this view's container\n this.viewHTMLElement.appendChild(this._datalistElement)\n this.textElementView.viewHTMLElement.setAttribute(\"list\", datalistId)\n }\n \n // Update the options\n this._datalistElement.innerHTML = \"\"\n this._nativeAutocompleteData.forEach(item => {\n const option = document.createElement(\"option\")\n option.value = item\n this._datalistElement!.appendChild(option)\n })\n }\n \n _updateDatalistVisibility() {\n if (!this._datalistElement) {\n return\n }\n \n // After the user has picked a value from the list, hide suggestions until\n // they start typing again. oninput clears _hasCommittedSelection, so this\n // gate only holds for exactly as long as the selection stands untouched.\n if (this._hasCommittedSelection) {\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n return\n }\n \n const currentText = this.text\n \n // Check minimum character requirement\n if (this.minCharactersForAutocomplete > 0 &&\n currentText.length < this.minCharactersForAutocomplete) {\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n return\n }\n \n // Hide datalist when it would show only a single redundant option\n if (this.hideNativeAutocompleteOnExactMatch && currentText.length > 0) {\n // Count how many options would be offered (browser uses starts-with logic)\n const matchingOptions = this._nativeAutocompleteData.filter(item =>\n item.toLowerCase().startsWith(currentText.toLowerCase()) ||\n currentText.toLowerCase().startsWith(item.toLowerCase())\n )\n \n // If only one option matches, it's redundant - hide the datalist\n if (matchingOptions.length === 1) {\n this.textElementView.viewHTMLElement.removeAttribute(\"list\")\n return\n }\n }\n \n // Show the datalist\n this.textElementView.viewHTMLElement.setAttribute(\"list\", this._datalistElement.id)\n }\n \n /**\n * Returns autocomplete options that match the given search text.\n * Uses case-insensitive substring matching (consistent with browser behavior).\n */\n _getFilteredAutocompleteOptions(searchText: string): string[] {\n const searchLower = searchText.toLowerCase()\n return this._nativeAutocompleteData.filter(item =>\n item.toLowerCase().includes(searchLower)\n )\n }\n \n override wasRemovedFromViewTree() {\n \n super.wasRemovedFromViewTree()\n \n // Clean up datalist element when text field is removed\n if (this._datalistElement) {\n this._datalistElement.remove()\n this._datalistElement = undefined\n }\n \n }\n \n \n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -57,6 +57,9 @@ export interface UIViewBroadcastEvent {
|
|
|
57
57
|
type Mutable<T> = {
|
|
58
58
|
-readonly [P in keyof T]: T[P];
|
|
59
59
|
};
|
|
60
|
+
type ColorStyleProxy = {
|
|
61
|
+
[K in keyof CSSStyleDeclaration as K extends string ? (Lowercase<K> extends `${string}color${string}` ? K : never) : never]?: UIColor;
|
|
62
|
+
};
|
|
60
63
|
export type UIViewAddControlEventTargetObject<T extends {
|
|
61
64
|
controlEvent: Record<string, any>;
|
|
62
65
|
}> = Mutable<{
|
|
@@ -94,6 +97,7 @@ export declare class UIView extends UIObject {
|
|
|
94
97
|
};
|
|
95
98
|
_frameCache?: UIRectangle;
|
|
96
99
|
_backgroundColor: UIColor;
|
|
100
|
+
_colorStyleProxy?: ColorStyleProxy;
|
|
97
101
|
_viewHTMLElement: HTMLElement & LooseObject;
|
|
98
102
|
_innerHTMLKey?: string;
|
|
99
103
|
_defaultInnerHTML?: string;
|
|
@@ -289,6 +293,7 @@ export declare class UIView extends UIObject {
|
|
|
289
293
|
set userInteractionEnabled(userInteractionEnabled: boolean);
|
|
290
294
|
get backgroundColor(): UIColor;
|
|
291
295
|
set backgroundColor(backgroundColor: UIColor);
|
|
296
|
+
get colorStyleProxy(): ColorStyleProxy;
|
|
292
297
|
get alpha(): number;
|
|
293
298
|
set alpha(alpha: number);
|
|
294
299
|
static animateViewOrViewsWithDurationDelayAndFunction(viewOrViews: UIView | HTMLElement | UIView[] | HTMLElement[], duration: number, delay: number, timingStyle: string | undefined, transformFunction: Function, transitioncompletionFunction: Function): {
|
|
@@ -798,7 +798,7 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
798
798
|
setBorder(radius = import_UIObject.nil, width = 1, color = import_UIColor.UIColor.blackColor, style = "solid") {
|
|
799
799
|
this.setStyleProperty("borderStyle", style);
|
|
800
800
|
this.setStyleProperty("borderRadius", radius);
|
|
801
|
-
this.
|
|
801
|
+
this.colorStyleProxy.borderColor = color;
|
|
802
802
|
this.setStyleProperty("borderWidth", width);
|
|
803
803
|
}
|
|
804
804
|
setStyleProperty(propertyName, value) {
|
|
@@ -829,7 +829,31 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
829
829
|
}
|
|
830
830
|
set backgroundColor(backgroundColor) {
|
|
831
831
|
this._backgroundColor = backgroundColor;
|
|
832
|
-
this.
|
|
832
|
+
this.colorStyleProxy.backgroundColor = backgroundColor;
|
|
833
|
+
}
|
|
834
|
+
get colorStyleProxy() {
|
|
835
|
+
if (!this._colorStyleProxy) {
|
|
836
|
+
const element = this._viewHTMLElement;
|
|
837
|
+
this._colorStyleProxy = new Proxy(element.style, {
|
|
838
|
+
set: (target, property, value) => {
|
|
839
|
+
const registrationKey = `${this._UIViewIndex}_${property}`;
|
|
840
|
+
const previousColor = import_UIColor.UIColor._registrationMap.get(registrationKey);
|
|
841
|
+
if (previousColor) {
|
|
842
|
+
previousColor._elementRef = void 0;
|
|
843
|
+
previousColor._styleProperty = void 0;
|
|
844
|
+
}
|
|
845
|
+
value._elementRef = element;
|
|
846
|
+
value._styleProperty = property;
|
|
847
|
+
if (value.semanticKey) {
|
|
848
|
+
import_UIColor.UIColor._liveColors.push(new WeakRef(value));
|
|
849
|
+
}
|
|
850
|
+
import_UIColor.UIColor._registrationMap.set(registrationKey, value);
|
|
851
|
+
Reflect.set(target, property, value.stringValue);
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
return this._colorStyleProxy;
|
|
833
857
|
}
|
|
834
858
|
get alpha() {
|
|
835
859
|
return 1 * this.style.opacity;
|
|
@@ -1326,6 +1350,13 @@ const _UIView = class extends import_UIObject.UIObject {
|
|
|
1326
1350
|
}
|
|
1327
1351
|
wasRemovedFromViewTree() {
|
|
1328
1352
|
_UIView.resizeObserver.unobserve(this.viewHTMLElement);
|
|
1353
|
+
for (const [key, color] of import_UIColor.UIColor._registrationMap) {
|
|
1354
|
+
if (key.startsWith(`${this._UIViewIndex}_`)) {
|
|
1355
|
+
color._elementRef = void 0;
|
|
1356
|
+
color._styleProperty = void 0;
|
|
1357
|
+
import_UIColor.UIColor._registrationMap.delete(key);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1329
1360
|
}
|
|
1330
1361
|
get isMemberOfViewTree() {
|
|
1331
1362
|
let element = this.viewHTMLElement;
|