uicore-ts
Version:
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 tha
1,882 lines (1,403 loc) • 54.4 kB
Markdown
# UICore API Reference
All public classes, properties, and methods exported from the `UI`-prefixed source files. Internal/private members (prefixed with `_`) are omitted unless they are commonly accessed through public patterns.
---
## Table of Contents
- [Global utilities](#global-utilities)
- [Constants — YES / NO / nil](#constants--yes--no--nil)
- [Guard functions — IS, IS\_NOT, IS\_DEFINED, …](#guard-functions)
- [Functional helpers — IF, FIRST, FIRST\_OR\_NIL, LAZY\_VALUE, CALL, EXTEND](#functional-helpers)
- [Type utilities](#type-utilities)
- [UIObject](#uiobject)
- [UIColor](#uicolor)
- [UIPoint](#uipoint)
- [UIRectangle](#uirectangle)
- [UIView](#uiview)
- [UIBaseButton](#uibasebutton)
- [UIButton](#uibutton)
- [UILink](#uilink)
- [UILinkButton](#uilinkbutton)
- [UITextView](#uitextview)
- [UITextField](#uitextfield)
- [UITextArea](#uitextarea)
- [UIImageView](#uiimageview)
- [UIActionIndicator](#uiactionindicator)
- [UILoadingView](#uiloadingview)
- [UIScrollView](#uiscrollview)
- [UINativeScrollView](#uinativescrollview)
- [UITableView](#uitableview)
- [UISlideScrollerView](#uislidescrollerview)
- [UIDialogView](#uidialogview)
- [UIDateTimeInput](#uidatetimeinput)
- [UIAutocompleteTextField](#uiautocompletatextfield)
- [UIAutocompleteDropdownView](#uiautocompletedropdownview)
- [UIAutocompleteRowView](#uiautocompleterowview)
- [UITimer](#uitimer)
- [UIStringFilter](#uistringfilter)
- [UIKeyValueStringFilter](#uikeyvaluestringfilter)
- [UIKeyValueSorter](#uikeyvaluesorter)
- [UILayoutGrid](#uilayoutgrid)
- [UIViewController](#uiviewcontroller)
- [UIRootViewController](#uirootviewcontroller)
- [UIRoute](#uiroute)
- [UICore](#uicore)
- [Native prototype extensions](#native-prototype-extensions)
- [Decorator — @UIComponentView](#decorator--uicomponentview)
---
## Global utilities
### Constants — YES / NO / nil
```typescript
const YES: true // = true
const NO: false // = false
```
`nil` is a safe-null proxy. Any property access or method call on `nil` returns `nil` rather than throwing. It coerces to `0` (number), `""` (string), and `false` (boolean).
```typescript
nil.anyProperty // → nil
nil.anyMethod() // → nil
nil + 0 // → 0
nil + "" // → ""
```
---
### Guard functions
```typescript
IS(object): object is T
```
Returns `true` when `object` is defined, non-null, and not `nil`. The recommended truthiness check throughout UICore.
```typescript
IS_NOT(object): object is undefined | null | false
```
Inverse of `IS`.
```typescript
IS_DEFINED(object): object is T
```
Returns `true` when `object !== undefined` (allows `null`).
```typescript
IS_UNDEFINED(object): object is undefined
```
```typescript
IS_NIL(object): object is typeof nil
```
Strict check for the `nil` proxy.
```typescript
IS_NOT_NIL(object): boolean
```
```typescript
IS_LIKE_NULL(object): boolean
```
Returns `true` for `undefined`, `null`, and `nil`.
```typescript
IS_NOT_LIKE_NULL(object): boolean
```
```typescript
IS_AN_EMAIL_ADDRESS(email: string): boolean
```
Simple regex check (`\S+@\S+\.\S+`).
```typescript
MAKE_ID(randomPartLength = 15): string
```
Generates a unique string ID (random characters + timestamp).
---
### Functional helpers
```typescript
FIRST<T>(...objects: (T | undefined | null)[]): T
```
Returns the first value for which `IS()` is true, or the last element if none pass.
```typescript
FIRST_OR_NIL<T>(...objects: (T | undefined | null)[]): T
```
Same as `FIRST` but returns `nil` instead of the last element.
```typescript
RETURNER<T>(value?: T): (...args: any[]) => T
```
Returns a function that always returns `value`.
```typescript
IF(value: any): UIIFBlockReceiver<T>
```
Inline conditional expression that evaluates lazily.
```typescript
// Usage
const result = IF(condition)(() => valueWhenTrue)
.ELSE_IF(otherCondition)(() => valueWhenOtherTrue)
.ELSE(() => valueWhenFalse)
```
```typescript
LAZY_VALUE<T>(initFunction: () => T): UILazyPropertyValue<T>
```
Wraps a factory for use inside `configureWithObject`. The property is initialised on first access.
```typescript
CALL<T extends (...args: any) => any>(...args: Parameters<T>): UIFunctionCall<T>
```
Creates a call descriptor for use inside `configureWithObject` when you need to invoke a method rather than assign a value.
```typescript
EXTEND<T extends (...args: any) => any>(extendingFunction: T): UIFunctionExtender<T>
```
Creates an extender for use inside `configureWithObject`. When applied, the extender runs *after* the existing method rather than replacing it.
```typescript
// Extend a method in configureWithObject
this.configureWithObject({
layoutSubviews: EXTEND(function(this: MyView) {
this.childView.frame = this.bounds
})
})
```
---
### Type utilities
```typescript
type UIInitializerObject<T> // Deep partial used by configureWithObject
type UIInitializerValue<T> // Accepted values: primitives, nested objects, UIFunctionCall, UIFunctionExtender, UILazyPropertyValue
type RecursiveRequired<T>
type MethodsOnly<T>
type ValueOf<T>
```
---
## UIObject
Base class for all UICore objects. Implements `Configurable`.
### Constructor
```typescript
new UIObject()
```
### Instance properties
| Property | Type | Description |
|----------|------|-------------|
| `class` | `any` | Constructor of this instance. |
| `superclass` | `any` | Constructor of the parent class. |
### Instance methods
```typescript
isKindOfClass(classObject: any): boolean
```
Returns `true` if this instance is an instance of `classObject` or any subclass.
```typescript
isMemberOfClass(classObject: any): boolean
```
Returns `true` only for exact class membership (no subclass match).
```typescript
valueForKey(key: string): any
```
```typescript
valueForKeyPath<T>(keyPath: string, defaultValue?: T): T | undefined
```
Traverses dot-separated key paths. A path segment prefixed with `[]` maps over an array at that key.
```typescript
setValueForKeyPath(keyPath: string, value: any, createPath?: boolean): boolean
```
```typescript
configureWithObject<K extends keyof this>(
object: { [P in K]?: UIInitializerValue<this[P]> }
): void
```
The primary initialiser pattern. Deeply merges `object` onto `this`. Accepts plain property values, `UIFunctionCall` descriptors, `UIFunctionExtender` wrappers, and `UILazyPropertyValue` factories.
```typescript
configuredWithObject<K extends keyof this>(
object: { [P in K]?: UIInitializerValue<this[P]> }
): this
```
Same as `configureWithObject` but returns `this` for chaining.
```typescript
performFunctionWithDelay(delay: number, functionToCall: Function): void
```
Fires `functionToCall` after `delay` seconds (uses `UITimer` internally).
```typescript
performFunctionWithSelf<T>(functionToPerform: (self: this) => T): T
```
Passes `this` to the function and returns whatever it returns. Useful for inline transformations.
```typescript
performingFunctionWithSelf(functionToPerform: (self: this) => void): this
```
Same as above but returns `this` for chaining (the function's return value is ignored).
### Static methods
```typescript
static wrapObject<T>(object: T): UIObject & T
```
Promotes a plain object to a `UIObject` (no-op if already a `UIObject`).
```typescript
static valueForKeyPath<T>(keyPath: string, object: any, defaultValue?: T): T | undefined
static setValueForKeyPath(keyPath: string, value: any, target: any, createPath: boolean): boolean
static configureWithObject<T>(target: T, object: UIInitializerObject<T>): object
static configuredWithObject<T>(target: T, object: UIInitializerObject<T>): T
```
```typescript
static recordAnnotation(annotation: Function, target: Function): void
static classHasAnnotation(classObject: Function, annotation: Function): boolean
static annotationsOnClass(classObject: Function): Function[]
```
---
## UIColor
Wraps a CSS colour string. All factory methods return fresh instances (no shared mutable state).
### Constructor
```typescript
new UIColor(stringValue: string)
```
Accepts any valid CSS colour string (`"#ff0000"`, `"rgb(255,0,0)"`, `"red"`, etc.).
### Instance properties
| Property | Type |
|----------|------|
| `stringValue` | `string` |
| `colorDescriptor` | `UIColorDescriptor` |
### Instance methods
```typescript
colorWithAlpha(alpha: number): UIColor
colorWithRed(red: number): UIColor
colorWithGreen(green: number): UIColor
colorWithBlue(blue: number): UIColor
toString(): string // returns stringValue
```
### Static factories
```typescript
static get redColor(): UIColor
static get blueColor(): UIColor
static get greenColor(): UIColor
static get yellowColor(): UIColor
static get blackColor(): UIColor
static get brownColor(): UIColor
static get whiteColor(): UIColor
static get greyColor(): UIColor
static get lightGreyColor(): UIColor
static get transparentColor(): UIColor
static get clearColor(): UIColor // alias for transparent
static get nilColor(): UIColor // empty string — no colour applied
```
```typescript
static colorWithRGBA(r: number, g: number, b: number, a?: number): UIColor
```
### Static utilities
```typescript
static nameToHex(name: string): string | undefined
static hexToDescriptor(hex: string): UIColorDescriptor
static rgbToDescriptor(colorString: string): UIColorDescriptor
```
### UIColorDescriptor interface
```typescript
interface UIColorDescriptor {
red: number;
green: number;
blue: number;
alpha?: number;
}
```
---
## UIPoint
A 2-D point. Extends `UIObject`.
### Constructor
```typescript
new UIPoint(x: number, y: number)
```
### Properties
| Property | Type |
|----------|------|
| `x` | `number` |
| `y` | `number` |
| `length` | `number` (read-only) |
### Methods
```typescript
copy(): UIPoint
isEqualTo(point: UIPoint): boolean
scale(zoom: number): this // mutates in place, returns this
add(point: UIPoint): this
subtract(point: UIPoint): this
to(targetPoint: UIPoint): UIPoint // vector from this → targetPoint
pointWithX(x: number): UIPoint // copy with new x
pointWithY(y: number): UIPoint // copy with new y
pointByAddingX(x: number): UIPoint
pointByAddingY(y: number): UIPoint
```
---
## UIRectangle
Axis-aligned rectangle with copy-on-write (COW) data sharing. Extends `UIObject`.
### Constructor
```typescript
new UIRectangle(x: number = 0, y: number = 0, height: number = 0, width: number = 0)
```
### Core properties
| Property | Type | Description |
|----------|------|-------------|
| `min` | `UIPoint` | Top-left corner (origin). |
| `max` | `UIPoint` | Bottom-right corner. |
| `x` | `number` | Left edge (`min.x`). |
| `y` | `number` | Top edge (`min.y`). |
| `width` | `number` | `max.x − min.x`. |
| `height` | `number` | `max.y − min.y`. |
| `minWidth` | `number \| undefined` | Layout constraint — minimum allowed width. Used by `rectangleByEnforcingMinAndMaxSizes()` and the fluent `settingMinWidth()` API. Not applied to CSS. |
| `maxWidth` | `number \| undefined` | Layout constraint — maximum allowed width. |
| `minHeight` | `number \| undefined` | Layout constraint — minimum allowed height. |
| `maxHeight` | `number \| undefined` | Layout constraint — maximum allowed height. |
### Derived properties (read-only)
```typescript
get center(): UIPoint
get centerX(): number
get centerY(): number
get area(): number
get isValid(): boolean // width > 0 && height > 0
```
### SizeNumberOrFunctionOrView
Many UIRectangle methods accept flexible sizing values via this union type:
```typescript
type SizeNumberOrFunctionOrView =
| number
| ((constrainingOrthogonalSize: number) => number)
| UIView // uses intrinsic content size
```
When a `UIView` is passed, the rectangle method calls `intrinsicContentHeight(width)` or `intrinsicContentWidth(height)` on that view. When a function is passed, it receives the orthogonal dimension (e.g. width when computing height) and must return a number.
### Non-mutating constructors (return new UIRectangle)
```typescript
copy(): UIRectangle
lazyCopy(): UIRectangle // COW — shares data until mutation
rectangleWithX(x: number, centeredOnPosition?: number): UIRectangle
rectangleWithY(y: number, centeredOnPosition?: number): UIRectangle
rectangleWithWidth(width: SizeNumberOrFunctionOrView, centeredOnPosition?: number): UIRectangle
rectangleWithHeight(height: SizeNumberOrFunctionOrView, centeredOnPosition?: number): UIRectangle
rectangleByAddingX(delta: number): UIRectangle
rectangleByAddingY(delta: number): UIRectangle
rectangleByAddingWidth(delta: number, centeredOnPosition?: number): UIRectangle
rectangleByAddingHeight(delta: number, centeredOnPosition?: number): UIRectangle
rectangleWithInset(inset: number): UIRectangle
rectangleWithInsets(left: number, right: number, bottom: number, top: number): UIRectangle
// Size relative to the other dimension
rectangleWithHeightRelativeToWidth(heightRatio?: number, centeredOnPosition?: number): UIRectangle
rectangleWithWidthRelativeToHeight(widthRatio?: number, centeredOnPosition?: number): UIRectangle
// Clamp to min/max dimensions — returns this unchanged if already within bounds
rectangleWithMaxWidth(maxWidth: number, centeredOnPosition?: number): UIRectangle
rectangleWithMaxHeight(maxHeight: number, centeredOnPosition?: number): UIRectangle
rectangleWithMinWidth(minWidth: number, centeredOnPosition?: number): UIRectangle
rectangleWithMinHeight(minHeight: number, centeredOnPosition?: number): UIRectangle
// Position relative to a reference rectangle (default: centered)
rectangleByCenteringInRectangle(
referenceRectangle: UIRectangle,
xPosition?: number, // 0–1, default 0.5
yPosition?: number // 0–1, default 0.5
): UIRectangle
// Fractional sub-rectangle
rectangleWithRelativeValues(
relativeXPosition: number,
widthMultiplier: number,
relativeYPosition: number,
heightMultiplier: number
): UIRectangle
// Expand bounding box to include another rectangle (non-mutating)
rectangleByConcatenatingWithRectangle(rectangle: UIRectangle): UIRectangle
```
### Row / column navigation
Returns a rectangle positioned directly next to (or before) this one.
The first parameter is the gap (padding) between the two rectangles.
The second parameter sets the size on the stacking axis.
```typescript
rectangleForNextRow(padding?: number, height?: SizeNumberOrFunctionOrView): UIRectangle
rectangleForNextColumn(padding?: number, width?: SizeNumberOrFunctionOrView): UIRectangle
rectangleForPreviousRow(padding?: number, height?: SizeNumberOrFunctionOrView): UIRectangle
rectangleForPreviousColumn(padding?: number, width?: SizeNumberOrFunctionOrView): UIRectangle
```
Usage:
```typescript
// Stack three views vertically with 10px gaps
let frame = bounds.rectangleWithHeight(40)
headerView.frame = frame
frame = frame.rectangleForNextRow(10, 30)
subtitleView.frame = frame
frame = frame.rectangleForNextRow(10, contentView) // height from intrinsic size
contentView.frame = frame
```
### Splitting and distribution
```typescript
// Weighted column / row splitting
rectanglesBySplittingWidth(
weights: SizeNumberOrFunctionOrView[],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteWidths?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): UIRectangle[]
rectanglesBySplittingHeight(
weights: SizeNumberOrFunctionOrView[],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteHeights?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): UIRectangle[]
// Equal splitting
rectanglesByEquallySplittingWidth(numberOfFrames: number, padding?: number): UIRectangle[]
rectanglesByEquallySplittingHeight(numberOfFrames: number, padding?: number): UIRectangle[]
// Assign frames to views using weighted splits
distributeViewsAlongWidth(
views: UIView[],
weights?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteWidths?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): this
distributeViewsAlongHeight(
views: UIView[],
weights?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteHeights?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): this
// Assign frames to views using equal splits
distributeViewsEquallyAlongWidth(views: UIView[], padding: number): this
distributeViewsEquallyAlongHeight(views: UIView[], padding: number): this
// Distribute views sequentially, sizing each from its intrinsic content
framesByDistributingViewsAsColumn(
views: UIView[],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteHeights?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): UIRectangle[]
framesByDistributingViewsAsRow(
views: UIView[],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteWidths?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): UIRectangle[]
// 2D grid: views[row][column]
framesByDistributingViewsAsGrid(
views: UIView[][],
paddings?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[],
absoluteHeights?: SizeNumberOrFunctionOrView | SizeNumberOrFunctionOrView[]
): UIRectangle[][]
```
Usage:
```typescript
// Two-column layout: 1/3 sidebar, 2/3 main with 15px gap
const [sidebarFrame, mainFrame] = bounds.rectanglesBySplittingWidth([1, 2], 15)
// Distribute views in a column using intrinsic heights
bounds.framesByDistributingViewsAsColumn([titleView, bodyView, footerView], 10)
```
### Constraint helpers
```typescript
// Size from a view's intrinsic content
rectangleWithIntrinsicContentSizeForView(
view: UIView,
centeredOnXPosition?: number,
centeredOnYPosition?: number
): UIRectangle
// Fluent setters for min/max constraints (return this)
settingMinHeight(minHeight?: number): this
settingMinWidth(minWidth?: number): this
settingMaxHeight(maxHeight?: number): this
settingMaxWidth(maxWidth?: number): this
// Returns a new rectangle clamped to stored min/max constraints
rectangleByEnforcingMinAndMaxSizes(
centeredOnXPosition?: number,
centeredOnYPosition?: number
): UIRectangle
// Set this rectangle as the frame of a view (returns this)
assignedAsFrameOfView(view: UIView, isWeakFrame?: boolean): this
```
### Mutating methods
```typescript
materialize(): void // force COW detach before external mutation
// Translates the rectangle in place — returns this
offsetByPoint(offset: UIPoint): this
// Expands bounding box in place to include another rectangle — returns this
concatenateWithRectangle(rectangle: UIRectangle): this
```
### Utility
```typescript
isEqualTo(other: UIRectangle | undefined): boolean
// Inherited from UIObject — generic, not UIRectangle-specific
performFunctionWithSelf<T>(fn: (self: this) => T): T
performingFunctionWithSelf(fn: (self: this) => void): this // returns this for chaining
```
---
## UIView
The central layout and rendering node. Every visible element in UICore is a `UIView` or subclass. Extends `UIObject`.
### Constructor
```typescript
new UIView(
elementID?: string,
viewHTMLElement?: HTMLElement | null,
elementType?: string | null // defaults to "div"
)
```
### Static control events
```typescript
UIView.controlEvent = {
PointerDown, PointerUp, PointerUpInside, PointerMove,
PointerHover, PointerLeave, PointerEnter, PointerCancel,
PointerTap,
Focus, Blur,
EnterDown, EnterUp,
UpArrowDown, DownArrowDown,
EscDown,
MultipleTouches,
// … and more
}
```
### Static broadcast event names
```typescript
UIView.broadcastEventName = {
AddedToViewTree,
PageDidScroll,
WindowDidResize,
LanguageChanged,
// … and more
}
```
### Static layout methods
```typescript
static layoutViewsIfNeeded(): void
static runFunctionBeforeNextFrame(fn: () => void): void
static animateViewOrViewsWithDurationDelayAndFunction(
view: UIView | UIView[],
duration: number,
delay: number,
timingFunction: string | undefined,
animationsFunction: () => void,
completionFunction: (() => void) | null
): void
```
### Static page dimensions
```typescript
static get pageWidth(): number
static get pageHeight(): number
static get pageScale(): number
static invalidatePageDimensionsCache(): void
```
### Core instance properties
| Property | Type | Description |
|----------|------|-------------|
| `viewHTMLElement` | `HTMLElement` | The underlying DOM element. |
| `elementID` | `string` | `viewHTMLElement.id`. |
| `superview` | `UIView \| undefined` | Parent in the view tree. |
| `subviews` | `UIView[]` | Direct children. |
| `viewController` | `UIViewController \| undefined` | Owning view controller, if any. |
| `core` | `UICore` | UICore instance (defaults to `UICore.main`). |
| `style` | `CSSStyleDeclaration` | Inline style of the element. |
| `computedStyle` | `CSSStyleDeclaration` | `getComputedStyle` result. |
### Geometry
```typescript
get frame(): UIRectangle
set frame(rect: UIRectangle)
get bounds(): UIRectangle // origin always (0, 0)
get rootView(): UIView
setFrame(rect: UIRectangle, zIndex?: number, performUncheckedLayout?: boolean): void
setPosition(
left?: number | string,
right?: number | string,
bottom?: number | string,
top?: number | string,
height?: number | string,
width?: number | string
): void
setSizes(height?: number | string, width?: number | string): void
setMargins(left?: number | string, right?: number | string, bottom?: number | string, top?: number | string): void
setPaddings(left?: number | string, right?: number | string, bottom?: number | string, top?: number | string): void
```
`setPosition` sets CSS `left`/`right`/`bottom`/`top`/`height`/`width` as inline styles. All parameters accept `nil` to skip a property.
### Appearance
```typescript
get hidden(): boolean
set hidden(hidden: boolean)
get alpha(): number
set alpha(alpha: number)
get backgroundColor(): UIColor
set backgroundColor(color: UIColor)
get zIndex(): number
set zIndex(index: number)
setBorder(radius: number, width: number, color?: UIColor): void
setCornerRadius(radius: number): void
setShadow(x: number, y: number, blur: number, color: UIColor): void
```
### Layout
```typescript
setNeedsLayout(): void
setNeedsLayoutUpToRootView(): void
get needsLayout(): boolean
// Called by the layout engine — override in subclasses
layoutSubviews(): void
// Intrinsic sizing
intrinsicContentSize(): UIRectangle
intrinsicContentHeight(constrainingWidth?: number): number
intrinsicContentWidth(constrainingHeight?: number): number
clearIntrinsicSizeCache(): void
// Content bounds — the usable interior area after content insets
get contentBounds(): UIRectangle
contentBoundsWithInset(inset: number): UIRectangle // sets all insets uniformly
contentBoundsWithInsets(left: number, right: number, bottom: number, top: number): UIRectangle
// Convenience position helpers
centerInContainer(): void
centerXInContainer(): void
centerYInContainer(): void
```
### View hierarchy
```typescript
addSubview(view: UIView): void
removeFromSuperview(): void
hasSubview(view: UIView): boolean
forEachViewInSubtree(fn: (view: UIView) => void): void
get isMemberOfViewTree(): boolean
get rootView(): UIView
```
### Event handling
```typescript
addTargetForControlEvent(event: string, handler: Function): void
addTargetForControlEvents(events: string[], handler: Function): void
removeTargetForControlEvent(event: string, handler: Function): void
sendControlEventForKey(event: string, nativeEvent?: Event): void
// Fluent accumulator — assigns one handler per control event
get controlEventTargetAccumulator(): UIViewAddControlEventTargetObject<UIView>
```
Usage pattern:
```typescript
view.controlEventTargetAccumulator.PointerUpInside = () => this.doSomething()
// Chain multiple events in one expression:
view.controlEventTargetAccumulator.PointerUpInside.EnterDown = () => this.doSomething()
```
### Broadcast events
```typescript
broadcastEventInSubtree(event: UIViewBroadcastEvent): void
// Override in subclasses to receive events
didReceiveBroadcastEvent(event: UIViewBroadcastEvent): void
```
### Interaction flags
```typescript
userInteractionEnabled: boolean
pausesPointerEvents: boolean // YES = absorb pointer events but don't propagate
stopsPointerEventPropagation: boolean
ignoresTouches: boolean
ignoresMouse: boolean
nativeSelectionEnabled: boolean // text selection
tabIndex: number
get enabled(): boolean
set enabled(enabled: boolean)
updateContentForCurrentEnabledState(): void // override in subclasses
focus(): void
blur(): void
```
### Content
```typescript
get innerHTML(): string
set innerHTML(html: string)
hoverText: string | undefined | null // tooltip
setInnerHTML(key: string, defaultString: string, parameters?: Record<string, string>): void
get scrollSize(): UIRectangle
get localizedTextObject(): UILocalizedTextObject | undefined
set localizedTextObject(obj: UILocalizedTextObject | undefined)
```
### Loading overlay
```typescript
get loading(): boolean
set loading(isLoading: boolean)
```
Requires `UIView.LoadingViewClass` to be registered once at startup:
```typescript
UIView.LoadingViewClass = UILoadingView
```
### Style classes
```typescript
addStyleClass(className: string): void
removeStyleClass(className: string): void
get styleClasses(): string[]
set styleClasses(classes: string[])
get styleClassName(): string // per-class CSS selector token
// Override to register static CSS rules once per class
initViewStyleSelectors(): void
initStyleSelector(selector: string, style: string): void
```
### Lifecycle callbacks (override in subclasses)
```typescript
willMoveToSuperview(superview: UIView): void
didMoveToSuperview(superview: UIView): void
wasAddedToViewTree(): void
wasRemovedFromViewTree(): void
willAppear(animated?: boolean): void
didAppear(animated?: boolean): void
```
### Coordinate conversion
```typescript
rectangleInView(rectangle: UIRectangle, view: UIView, forceIfNotInViewTree?: boolean): UIRectangle
rectangleFromView(rectangle: UIRectangle, view: UIView): UIRectangle // inverse of rectangleInView
```
### Virtual layout
```typescript
startVirtualLayout(): void
finishVirtualLayout(): void
get isVirtualLayouting(): boolean
usesVirtualLayoutingForIntrinsicSizing: boolean // default YES
```
---
## UIBaseButton
Abstract interactive element with pointer-state tracking. Extends `UIView`.
### State properties
```typescript
get selected(): boolean
set selected(selected: boolean)
get highlighted(): boolean
set highlighted(highlighted: boolean)
get hovered(): boolean
set hovered(hovered: boolean)
get focused(): boolean
set focused(focused: boolean)
isToggleable: boolean // when YES, PointerUpInside toggles selected state
```
### State override methods (override in subclasses)
```typescript
updateContentForCurrentState(): void
updateContentForNormalState(): void
updateContentForHoveredState(): void // default: calls Normal
updateContentForFocusedState(): void // default: calls Hovered
updateContentForHighlightedState(): void
updateContentForSelectedState(): void
updateContentForSelectedAndHighlightedState(): void // default: calls Selected
updateContentForCurrentEnabledState(): void
```
State priority (highest first): SelectedAndHighlighted → Selected → Focused → Highlighted → Hovered → Normal.
---
## UIButton
Full-featured button with title label, image view, and per-state colour configuration. Extends `UIBaseButton`.
### UIButtonColorSpecifier interface
```typescript
interface UIButtonColorSpecifier {
background: {
normal: UIColor;
hovered?: UIColor;
focused?: UIColor;
highlighted: UIColor;
selected: UIColor;
selectedAndHighlighted?: UIColor;
};
titleLabel: {
normal: UIColor;
hovered?: UIColor;
focused?: UIColor;
highlighted: UIColor;
selected: UIColor;
selectedAndHighlighted?: UIColor;
};
}
```
### UIButtonElementColorSpecifier interface
```typescript
interface UIButtonElementColorSpecifier {
normal: UIColor;
hovered?: UIColor;
focused?: UIColor;
highlighted: UIColor;
selected: UIColor;
selectedAndHighlighted?: UIColor;
}
```
### Constructor
```typescript
new UIButton(elementID?: string, elementType?: string, titleType?: string)
```
### Properties
```typescript
get titleLabel(): UITextView
get imageView(): UIImageView
colors: UIButtonColorSpecifier // drives all state methods
contentPadding: number // horizontal padding for text/image
usesAutomaticTitleFontSize: boolean
minAutomaticFontSize: number
maxAutomaticFontSize: number
```
---
## UILink
A button backed by an `<a>` element for native browser navigation. Extends `UIBaseButton`.
### Properties
```typescript
text: string
target: string // the href attribute value
// Returns a UIRoute or URL string for the current app state
targetRouteForCurrentState: () => UIRoute | string
colors: UIButtonColorSpecifier | undefined
```
`target` is automatically kept in sync when the route changes (via `RouteDidChange` broadcast).
---
## UILinkButton
Wraps a `UIButton` inside a `UILink`, combining styled button visuals with native `<a>` semantics. Extends `UILink`.
```typescript
get titleLabel(): UITextView // forwarded from inner UIButton
get imageView(): UIImageView
colors: UIButtonColorSpecifier
target: string
```
---
## UITextView
Text display and measurement. Backed by a flex wrapper `<span>` containing an inner element (`<p>`, `<h1>`–`<h6>`, `<span>`, etc.). Extends `UIView`.
### Static properties
```typescript
static defaultTextColor: UIColor // = UIColor.blackColor
static notificationTextColor: UIColor // = UIColor.redColor
static type = {
paragraph: "p",
header1: "h1", header2: "h2", header3: "h3",
header4: "h4", header5: "h5", header6: "h6",
textArea: "textarea",
textField: "input",
span: "span",
label: "label"
} as const
static textAlignment = {
left: "left", center: "center",
right: "right", justify: "justify"
} as const
```
### Constructor
```typescript
new UITextView(elementID?: string, textViewType?: string)
```
`textViewType` defaults to `UITextView.type.paragraph`.
### Core text properties
```typescript
text: string // innerHTML of the inner element
textColor: UIColor
textAlignment: ValueOf<typeof UITextView.textAlignment>
fontSize: number // in points
isSingleLine: boolean // true = nowrap + ellipsis; false = multiline
notificationAmount: number // appends a red "(n)" badge to the text
```
### Inner element access
```typescript
get textElementView(): UIView // the inner element UIView
get containerStyle(): CSSStyleDeclaration // outer wrapper styles
```
### Localisation
```typescript
setText(key: string, defaultString: string, parameters?: Record<string, string>): void
```
### Measurement
```typescript
intrinsicContentSize(): UIRectangle
intrinsicContentHeight(constrainingWidth?: number): number
intrinsicContentWidth(constrainingHeight?: number): number
useAutomaticFontSize(minFontSize?: number, maxFontSize?: number): void
setUseFastMeasurement(useFast: boolean): void
invalidateMeasurementStrategy(): void
static automaticallyCalculatedFontSize(
bounds: UIRectangle,
intrinsicSize: UIRectangle,
currentFontSize: number,
minFontSize: number,
maxFontSize: number
): number
```
### Overrides
```typescript
notificationAmountDidChange(amount: number): void // hook — override in subclass
```
---
## UITextField
Editable single-line text input (`<input type="text">`). Extends `UITextView`.
### Additional control events
```typescript
UITextField.controlEvent.TextChange // fires on oninput and onchange
UITextField.controlEvent.ValidationChange // fires when autocomplete validation state changes
```
### Properties
```typescript
text: string // the current input value (read/write)
placeholderText: string
isSecure: boolean // toggles type="password"
// Native browser datalist autocomplete
nativeAutocompleteData: string[]
minCharactersForAutocomplete: number // default 0
hideNativeAutocompleteOnExactMatch: boolean // default YES
// Validation against the autocomplete list
validatesAgainstNativeAutocomplete: boolean
isValidAgainstNativeAutocomplete: boolean // read-only
validationInvalidBackgroundColor: UIColor
validationInvalidBorderColor: UIColor
```
### Methods
```typescript
setPlaceholderText(key: string, defaultString: string): void // localised placeholder
clearIfInvalid(): boolean // clears text if it fails autocomplete validation
getMatchingAutocompleteOptions(): string[]
```
---
## UITextArea
Multi-line `<textarea>`. Extends `UITextField`. The textarea fills its parent's `contentBounds`; set height on the parent view.
```typescript
new UITextArea(elementID?: string)
```
Inherits all `UITextField` properties. `isSingleLine` is effectively `NO`.
---
## UIImageView
Image element (`<img>`). Extends `UIView`.
### Static fill modes
```typescript
UIImageView.fillMode = {
stretchToFill: "fill",
aspectFit: "contain",
aspectFill: "cover",
center: "none",
aspectFitIfLarger: "scale-down"
}
```
### Properties
```typescript
imageSource: string // the img src attribute; setting empty hides the view
fillMode: string // one of UIImageView.fillMode values (sets object-fit)
hiddenWhenEmpty: boolean // auto-hide when imageSource is empty
```
### Methods
```typescript
getDataURL(height?: number, width?: number): string // renders to canvas and returns data URL
setImageSource(key: string, defaultString: string): void // localised image source
intrinsicContentSize(): UIRectangle // returns natural image dimensions
```
### Static utilities
```typescript
static dataURL(url: string | URL, callback: (result: string | ArrayBuffer | null) => void): void
static dataURLWithMaxSize(url: string, maxSize: number, completion: (url: string) => void): void
static dataURLWithSizes(url: string, height: number, width: number, completion: (url: string) => void): void
static objectURLFromDataURL(dataURL: string): string
```
---
## UIActionIndicator
Animated spinner view. Hidden by default. Extends `UIView`.
### Properties
```typescript
size: number // spinner size in pixels (default 50)
```
### Methods
```typescript
start(): void // show and animate
stop(): void // hide
```
---
## UILoadingView
Full-overlay loading screen with a spinner. Typically registered globally and shown via `view.loading = YES`. Extends `UIView`.
```typescript
new UILoadingView(elementID?: string)
```
```typescript
theme: "light" | "dark" // default "light"
```
Register once at startup:
```typescript
UIView.LoadingViewClass = UILoadingView
```
---
## UIScrollView
A custom-implemented scroll container backed by an absolutely positioned container view. Pointer-drag scrolling (touch and mouse) is built in. Extends `UIView`.
### Constructor
```typescript
new UIScrollView(elementID: string)
```
### Properties
```typescript
get containerView(): UIView // the scrollable content container
get contentOffset(): UIPoint
set contentOffset(offset: UIPoint) // triggers layout
_scrollEnabled: boolean // whether drag-scroll is active
```
### Methods
```typescript
// Override addSubview — adds to containerView
addSubview(view: UIView): void
invalidateIntrinsicContentFrame(): void
```
---
## UINativeScrollView
Uses the browser's native scroll (`overflow: auto`). Extends `UIView`. This is the base of `UITableView`.
### Key properties
```typescript
scrollsX: boolean
scrollsY: boolean
animationDuration: number
get contentOffset(): UIPoint
set contentOffset(offset: UIPoint)
get scrollSize(): UIRectangle // full scrollable content dimensions
```
### Methods
```typescript
scrollToTop(animated?: boolean): void
// Override to react to scroll position changes
didScrollToPosition(offsetPosition: UIPoint): void
```
---
## UITableView
Virtualised list with off-screen row recycling. Extends `UINativeScrollView`.
### Properties
```typescript
allRowsHaveEqualHeight: boolean // optimises position calculation when YES
sidePadding: number // horizontal padding applied to each row
animationDuration: number // used by animated row changes (default 0.25)
reloadsOnLanguageChange: boolean // default YES
cellWeights: number[] | undefined // column width ratios for grid layouts
```
### Data source methods (override to provide content)
```typescript
numberOfRows(): number // default 10000 — always override
heightForRowWithIndex(index: number): number // default 50
viewForRowWithIndex(index: number): UIView // return a configured row view
newReusableViewForIdentifier(identifier: string, rowIDIndex: number): UIView
// Persistence — save/restore transient row state across virtualisation cycles
defaultRowPersistenceDataItem(): any
persistenceDataItemForRowWithIndex(rowIndex: number, row: UIView): any
```
### Reload / update
```typescript
reloadData(): void // full reload, clears reuse pool
loadData(): void // recalculate positions, keep pool
invalidateSizeOfRowWithIndex(index: number, animateChange?: boolean): void
highlightChanges(previousData: any[], newData: any[]): void // animates new rows
```
### Reuse pool
```typescript
reusableViewForIdentifier(identifier: string, rowIndex: number): UIView
```
### Query
```typescript
visibleRowWithIndex(rowIndex: number | undefined): UIView | undefined
isRowWithIndexVisible(rowIndex: number): boolean
indexesForVisibleRows(paddingRatio?: number): number[]
intrinsicContentHeight(constrainingWidth?: number): number
```
---
## UISlideScrollerView
Horizontal carousel / slideshow. Extends `UIView`.
### Properties
```typescript
slideViews: UIView[] // set to replace all slides
currentPageIndex: number // read/write; triggers scroll
wrapAround: boolean // default YES
animationDuration: number // slide transition (default 0.35 s)
animationDelay: number // auto-play delay (default 2 s)
```
### Methods
```typescript
scrollToPageWithIndex(targetIndex: number, animated?: boolean): void
scrollToNextPage(animated: boolean): void
scrollToPreviousPage(animated: boolean): void
startAnimating(): void // begin auto-play
stopAnimating(): void
// Override hooks
willScrollToPageWithIndex(index: number): void
didScrollToPageWithIndex(index: number): void
buttonForPageIndicatorWithIndex(index: number): UIButton // customise indicators
```
---
## UIDialogView
Modal overlay. The `view` property holds the content; the `UIDialogView` itself is the dark backdrop. Generic parameter `ViewType` constrains the content view type. Extends `UIView`.
### Constructor
```typescript
new UIDialogView<ViewType extends UIView>(elementID?: string)
```
### Properties
```typescript
view: ViewType // the content view
isVisible: boolean
dismissesOnTapOutside: boolean // default YES
animationDuration: number // default 0.25 s
zIndex: number
```
### Methods
```typescript
showInView(containerView: UIView, animated: boolean): void
showInRootView(animated: boolean): void // shortcut — shows in UICore.main rootView
dismiss(animated?: boolean): void
// Override to customise enter/exit animations
animateAppearing(): void
animateDisappearing(): void
didDetectTapOutside(sender: UIView, event: Event): void
```
---
## UIDateTimeInput
Native `<input type="date|time|datetime">`. Extends `UIView`.
### Additional control events
```typescript
UIDateTimeInput.controlEvent.ValueChange
```
### Static types
```typescript
UIDateTimeInput.type = {
Date: "date",
Time: "time",
DateTime: "datetime"
}
UIDateTimeInput.format = {
European: "DD-MM-YYYY",
ISOComputer: "YYYY-MM-DD",
American: "MM/DD/YYYY"
}
```
### Constructor
```typescript
new UIDateTimeInput(elementID: string, type?: string)
```
### Properties
```typescript
get date(): Date // parsed from the current input value
```
---
## UIAutocompleteTextField
Text field with a filtered dropdown. Extends `UITextField`.
### Additional control events
```typescript
UIAutocompleteTextField.controlEvent.SelectionDidChange
```
### Properties
```typescript
autocompleteStrings: string[] // convenience setter — converts to items
autocompleteData: UIAutocompleteItem<T>[] // full item list (label + value)
selectedItem: T | undefined // the committed selection value
strictSelection: boolean // clears text if not in list on close
get isValid(): boolean
```
### Methods
```typescript
commitSelection(item: UIAutocompleteItem<T>): void
openDropdown(): void
closeDropdown(): void
updateFilteredItems(): void
updateValidationVisuals(): void // hook — override in subclass
// Override to return a custom dropdown
newDropdownView(): UIAutocompleteDropdownView<T>
```
---
## UIAutocompleteDropdownView
Dropdown list anchored beneath a field. Typically created and owned by `UIAutocompleteTextField`. Extends `UIView`.
### Properties
```typescript
filteredItems: UIAutocompleteItem<T>[]
highlightedRowIndex: number
get highlightedItem(): UIAutocompleteItem<T> | undefined
didSelectItem: ((item: UIAutocompleteItem<T>) => void) | undefined
anchorView: UIView | undefined
_rowHeight: number // default 36
_maxVisibleRows: number // default 8
```
### Methods
```typescript
showAnchoredToView(anchorView: UIView): void
dismiss(): void
newRowView(identifier: string, rowIndex: number): UIAutocompleteRowView<T> // override in subclass
```
---
## UIAutocompleteRowView
A single row in `UIAutocompleteDropdownView`. Extends `UIButton`.
```typescript
item: UIAutocompleteItem<T>
```
### UIAutocompleteItem interface
```typescript
interface UIAutocompleteItem<T> {
label: string;
value: T;
}
```
---
## UITimer
Thin wrapper around `setInterval` / `clearInterval`.
### Constructor
```typescript
new UITimer(interval: number, repeats: boolean, target: Function)
```
`interval` is in **seconds**. The timer starts immediately.
### Properties
```typescript
interval: number
repeats: boolean
isValid: boolean
```
### Methods
```typescript
schedule(): void
reschedule(): void // invalidates then re-schedules
fire(): void // execute target immediately, then handle repeat/invalidate
invalidate(): void // stops the timer
```
---
## UIStringFilter
Off-thread string filtering via a shared `Worker`. Case-insensitive, space-tokenised (all words must match). Results arrive in callback order.
### Constructor
```typescript
new UIStringFilter(useSeparateWebWorkerHolder?: boolean)
```
Pass `YES` to get a dedicated worker (for high-frequency independent searches).
### Methods
```typescript
// Callback-based
filterData(
filteringString: string,
data: string[],
excludedData: string[],
identifier: any,
completion: (filteredData: string[], filteredIndexes: number[], identifier: any) => void
): void
// Promise-based
filteredData(
filteringString: string,
data: string[],
excludedData?: string[],
identifier?: any
): Promise<{ filteredData: string[], filteredIndexes: number[], identifier: any }>
closeThread(): void // terminate a dedicated worker
```
---
## UIKeyValueStringFilter
Like `UIStringFilter` but filters objects by a dot-path string value.
### Constructor
```typescript
new UIKeyValueStringFilter(useSeparateWebWorkerHolder?: boolean)
```
### Methods
```typescript
filterData<T extends object>(
filteringString: string,
data: T[],
excludedData: string[],
dataKeyPath: string,
identifier: any,
completion: (filteredData: T[], filteredIndexes: number[], identifier: any) => void
): void
closeThread(): void
```
---
## UIKeyValueSorter
Off-thread multi-key sorting via a shared `Worker`.
### Static constants
```typescript
UIKeyValueSorter.dataType = { string: "string", number: "number" }
UIKeyValueSorter.direction = { ascending: "ascending", descending: "descending" }
```
### UIKeyValueSorterSortingInstruction interface
```typescript
interface UIKeyValueSorterSortingInstruction {
keyPath: string;
dataType: "string" | "number";
direction: "ascending" | "descending";
}
```
### Constructor
```typescript
new UIKeyValueSorter(useSeparateWebWorkerHolder?: boolean)
```
### Methods
```typescript
// Callback-based
sortData<T>(
data: T[],
sortingInstructions: UIKeyValueSorterSortingInstruction[],
identifier: any,
completion: (sortedData: T[], sortedIndexes: number[], identifier: any) => void
): void
// Promise-based
sortedData<T>(
data: T[],
sortingInstructions: UIKeyValueSorterSortingInstruction[],
identifier?: any
): Promise<{ sortedData: T[], sortedIndexes: number[], identifier: any }>
closeThread(): void
```
---
## UILayoutGrid
Helper for splitting a `UIRectangle` into a grid. Not fully implemented in the current codebase — `splitXInto` is stubbed. Extend or use directly when the implementation is complete.
```typescript
new UILayoutGrid(frame: UIRectangle)
```
---
## UIViewController
Base class for all view controllers. Manages a root `UIView` and participates in the route, lifecycle, and view-controller hierarchy. Extends `UIObject`.
### Static properties
```typescript
static readonly routeComponentName: string // declare in subclass
static readonly ParameterIdentifierName: any // declare in subclass for type-safe params
```
### Constructor
```typescript
new UIViewController(view: UIView)
```
### Properties
```typescript
view: UIView
parentViewController: UIViewController | undefined
childViewControllers: UIViewController[]
get core(): UICore
get routeComponent(): UIRouteComponent | undefined
```
### Lifecycle (override in subclasses)
```typescript
async viewWillAppear(): Promise<void>
async viewDidAppear(): Promise<void>
async viewWillDisappear(): Promise<void>
async viewDidDisappear(): Promise<void>
viewWillLayoutSubviews(): void // calls updateViewConstraints + updateViewStyles
viewDidLayoutSubviews(): void
updateViewConstraints(): void // hook
updateViewStyles(): void // hook
layoutViewSubviews(): void // hook
```
### Route handling
```typescript
async handleRoute(route: UIRoute): Promise<void> // override in subclass
handleRouteRecursively(route: UIRoute): void // called by UICore; recurses into children
viewDidReceiveBroadcastEvent(event: UIViewBroadcastEvent): void
```
### Child view controller management
```typescript
addChildViewController(viewController: UIViewController): void
removeChildViewController(controller: UIViewController): void
removeFromParentViewController(): void
hasChildViewController(viewController: UIViewController): boolean
// Add a child whose view goes into a specific container view
addChildViewControllerInContainer(
controller: UIViewController,
containerView: UIView
): void
// Add a child and connect it to a UIDialogView's content
addChildViewControllerInDialogView(
controller: UIViewController,
dialogView: UIDialogView
): void
willMoveToParentViewController(parent: UIViewController): void
didMoveToParentViewController(parent: UIViewController): void
```
---
## UIRootViewController
Application root. Owns the full-screen `UIView` and manages lazy-loaded child view controllers. Extends `UIViewController`.
### Interfaces
```typescript
interface UIRootViewControllerLazyViewControllerObject<T extends typeof UIViewController> {
viewControllerClass: T;
deleteOnUnload?: boolean; // destroy VC instance when not shown (saves memory)
shouldShow?: () => Promise<boolean> | boolean;
}
interface UIRootViewControllerLazyViewControllersObject {
[key: string]: UIRootViewControllerLazyViewControllerObject<any>;
}
```
### Properties
```typescript
topBarView: UIView // persistent top bar — excluded from content area
bottomBarView: UIView // persistent bottom bar
```
### Methods
```typescript
// Register lazy view controllers by key
lazyViewControllerObjectWithClass<T extends typeof UIViewController>(
viewControllerClass: T,
options?: { deleteOnUnload?: boolean; shouldShow?: () => Promise<boolean> | boolean }
): UIRootViewControllerLazyViewControllerObject<T>
// Scale the RootView for zoom/accessibility
updatePageScale(options: {
minWidth?: number;
maxWidth?: number;
minScale?: number;
maxScale?: number;
}): void
// Perform root-level layout
performDefaultLayout(): void
```
---
## UIRoute
Represents the URL hash as a structured array of named components with key-value parameters. Extends `Array<UIRouteComponent>`.
Hash format: `#component1[key:value,key2:value2]/component2[key:value]/`
### UIRouteComponent interface
```typescript
interface UIRouteComponent<T = any> {
name: string;
parameters: UIRouteParameters<T>;
}
type UIRouteParameters<T = any> = {
[K in keyof T]?: string;
}
```
### Static accessors
```typescript
static get currentRoute(): UIRoute // parsed from window.location.hash
```
### Instance methods
```typescript
// Navigation
apply(): void // pushes route to history
applyByReplacingCurrentRouteInHistory(): void // replaces history entry
get linkRepresentation(): string // the hash string for use in href
// Lookup
componentWithName(name: string): UIRouteComponent | undefined
componentWithViewController(vcClass: typeof UIViewController): UIRouteComponent | undefined
// Build a new route
routeBySettingComponent(component: UIRouteComponent): UIRoute
routeByRemovingComponen