mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-26 11:17:04 +08:00
feat(core): support for simultaneous pseudo states (#10656)
This commit is contained in:

committed by
GitHub

parent
a883a79e3b
commit
f970455007
@ -274,7 +274,7 @@ export var test_StateHighlighted_also_fires_pressedState = function () {
|
||||
|
||||
helper.waitUntilLayoutReady(view);
|
||||
|
||||
view._goToVisualState('highlighted');
|
||||
view._addVisualState('highlighted');
|
||||
|
||||
var actualResult = buttonTestsNative.getNativeBackgroundColor(view);
|
||||
TKUnit.assert(actualResult.hex === expectedNormalizedColor, 'Actual: ' + actualResult.hex + '; Expected: ' + expectedNormalizedColor);
|
||||
@ -291,7 +291,7 @@ export var test_StateHighlighted_also_fires_activeState = function () {
|
||||
|
||||
helper.waitUntilLayoutReady(view);
|
||||
|
||||
view._goToVisualState('highlighted');
|
||||
view._addVisualState('highlighted');
|
||||
|
||||
var actualResult = buttonTestsNative.getNativeBackgroundColor(view);
|
||||
TKUnit.assert(actualResult.hex === expectedNormalizedColor, 'Actual: ' + actualResult.hex + '; Expected: ' + expectedNormalizedColor);
|
||||
|
@ -602,9 +602,9 @@ export function test_restore_original_values_when_state_is_changed() {
|
||||
page.css = 'button { color: blue; } ' + 'button:pressed { color: red; } ';
|
||||
|
||||
helper.assertViewColor(btn, '#0000FF');
|
||||
btn._goToVisualState('pressed');
|
||||
btn._addVisualState('pressed');
|
||||
helper.assertViewColor(btn, '#FF0000');
|
||||
btn._goToVisualState('normal');
|
||||
btn._removeVisualState('pressed');
|
||||
helper.assertViewColor(btn, '#0000FF');
|
||||
}
|
||||
|
||||
@ -655,9 +655,9 @@ export const test_composite_selector_type_class_state = function () {
|
||||
|
||||
// The button with no class should not react to state changes.
|
||||
TKUnit.assertNull(btnWithNoClass.style.color, 'Color should not have a value.');
|
||||
btnWithNoClass._goToVisualState('pressed');
|
||||
btnWithNoClass._addVisualState('pressed');
|
||||
TKUnit.assertNull(btnWithNoClass.style.color, 'Color should not have a value.');
|
||||
btnWithNoClass._goToVisualState('normal');
|
||||
btnWithNoClass._removeVisualState('pressed');
|
||||
TKUnit.assertNull(btnWithNoClass.style.color, 'Color should not have a value.');
|
||||
|
||||
TKUnit.assertNull(lblWithClass.style.color, 'Color should not have a value');
|
||||
@ -864,11 +864,11 @@ function testSelectorsPrioritiesTemplate(css: string) {
|
||||
function testButtonPressedStateIsRed(btn: Button) {
|
||||
TKUnit.assert(btn.style.color === undefined, 'Color should not have a value.');
|
||||
|
||||
btn._goToVisualState('pressed');
|
||||
btn._addVisualState('pressed');
|
||||
|
||||
helper.assertViewColor(btn, '#FF0000');
|
||||
|
||||
btn._goToVisualState('normal');
|
||||
btn._removeVisualState('pressed');
|
||||
|
||||
TKUnit.assert(btn.style.color === undefined, 'Color should not have a value after returned to normal state.');
|
||||
}
|
||||
|
@ -94,3 +94,54 @@ export var test_goToVisualState_NoState_ShouldGoToNormal = function () {
|
||||
|
||||
helper.do_PageTest_WithButton(test);
|
||||
};
|
||||
|
||||
export var test_addVisualState = function () {
|
||||
var test = function (views: Array<view.View>) {
|
||||
(<page.Page>views[0]).css = 'button:hovered { color: red; background-color: orange } button:pressed { color: white }';
|
||||
|
||||
var btn = views[1];
|
||||
|
||||
assertInState(btn, btn.defaultVisualState, ['hovered', 'pressed', btn.defaultVisualState]);
|
||||
|
||||
btn._addVisualState('hovered');
|
||||
|
||||
assertInState(btn, 'hovered', ['hovered', 'pressed', btn.defaultVisualState]);
|
||||
|
||||
TKUnit.assert(types.isDefined(btn.style.color) && btn.style.color.name === 'red');
|
||||
TKUnit.assert(types.isDefined(btn.style.backgroundColor) && btn.style.backgroundColor.name === 'orange');
|
||||
|
||||
btn._addVisualState('pressed');
|
||||
|
||||
assertInState(btn, 'hovered', ['hovered', btn.defaultVisualState]);
|
||||
assertInState(btn, 'pressed', ['pressed', btn.defaultVisualState]);
|
||||
|
||||
TKUnit.assert(types.isDefined(btn.style.color) && btn.style.color.name === 'white');
|
||||
TKUnit.assert(types.isDefined(btn.style.backgroundColor) && btn.style.backgroundColor.name === 'orange');
|
||||
};
|
||||
|
||||
helper.do_PageTest_WithButton(test);
|
||||
};
|
||||
|
||||
export var test_removeVisualState = function () {
|
||||
var test = function (views: Array<view.View>) {
|
||||
(<page.Page>views[0]).css = 'button { background-color: yellow; color: green } button:pressed { background-color: red; color: white }';
|
||||
|
||||
var btn = views[1];
|
||||
|
||||
btn._addVisualState('pressed');
|
||||
|
||||
assertInState(btn, 'pressed', ['pressed', 'hovered', btn.defaultVisualState]);
|
||||
|
||||
TKUnit.assert(types.isDefined(btn.style.color) && btn.style.color.name === 'white');
|
||||
TKUnit.assert(types.isDefined(btn.style.backgroundColor) && btn.style.backgroundColor.name === 'red');
|
||||
|
||||
btn._removeVisualState('pressed');
|
||||
|
||||
assertInState(btn, btn.defaultVisualState, ['hovered', 'pressed', btn.defaultVisualState]);
|
||||
|
||||
TKUnit.assert(types.isDefined(btn.style.color) && btn.style.color.name === 'green');
|
||||
TKUnit.assert(types.isDefined(btn.style.backgroundColor) && btn.style.backgroundColor.name === 'yellow');
|
||||
};
|
||||
|
||||
helper.do_PageTest_WithButton(test);
|
||||
};
|
||||
|
@ -44,11 +44,24 @@ function initializeClickListener(): void {
|
||||
ClickListener = ClickListenerImpl;
|
||||
}
|
||||
|
||||
function onButtonStateChange(args: TouchGestureEventData) {
|
||||
const button = args.object as Button;
|
||||
|
||||
switch (args.action) {
|
||||
case TouchAction.up:
|
||||
case TouchAction.cancel:
|
||||
button._removeVisualState('highlighted');
|
||||
break;
|
||||
case TouchAction.down:
|
||||
button._addVisualState('highlighted');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export class Button extends ButtonBase {
|
||||
nativeViewProtected: android.widget.Button;
|
||||
|
||||
private _stateListAnimator: any;
|
||||
private _highlightedHandler: (args: TouchGestureEventData) => void;
|
||||
|
||||
@profile
|
||||
public createNativeView() {
|
||||
@ -87,22 +100,9 @@ export class Button extends ButtonBase {
|
||||
@PseudoClassHandler('normal', 'highlighted', 'pressed', 'active')
|
||||
_updateButtonStateChangeHandler(subscribe: boolean) {
|
||||
if (subscribe) {
|
||||
this._highlightedHandler =
|
||||
this._highlightedHandler ||
|
||||
((args: TouchGestureEventData) => {
|
||||
switch (args.action) {
|
||||
case TouchAction.up:
|
||||
case TouchAction.cancel:
|
||||
this._goToVisualState(this.defaultVisualState);
|
||||
break;
|
||||
case TouchAction.down:
|
||||
this._goToVisualState('highlighted');
|
||||
break;
|
||||
}
|
||||
});
|
||||
this.on(GestureTypes[GestureTypes.touch], this._highlightedHandler);
|
||||
this.on(GestureTypes[GestureTypes.touch], onButtonStateChange);
|
||||
} else {
|
||||
this.off(GestureTypes[GestureTypes.touch], this._highlightedHandler);
|
||||
this.off(GestureTypes[GestureTypes.touch], onButtonStateChange);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@ import { Color } from '../../color';
|
||||
|
||||
export * from './button-common';
|
||||
|
||||
const observableVisualStates = ['highlighted']; // States like :disabled are handled elsewhere
|
||||
|
||||
export class Button extends ButtonBase {
|
||||
public nativeViewProtected: UIButton;
|
||||
|
||||
@ -46,8 +48,12 @@ export class Button extends ButtonBase {
|
||||
_updateButtonStateChangeHandler(subscribe: boolean) {
|
||||
if (subscribe) {
|
||||
if (!this._stateChangedHandler) {
|
||||
this._stateChangedHandler = new ControlStateChangeListener(this.nativeViewProtected, (s: string) => {
|
||||
this._goToVisualState(s);
|
||||
this._stateChangedHandler = new ControlStateChangeListener(this.nativeViewProtected, observableVisualStates, (state: string, add: boolean) => {
|
||||
if (add) {
|
||||
this._addVisualState(state);
|
||||
} else {
|
||||
this._removeVisualState(state);
|
||||
}
|
||||
});
|
||||
}
|
||||
this._stateChangedHandler.start();
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* tslint:disable:no-unused-variable */
|
||||
/* tslint:disable:no-empty */
|
||||
import { ControlStateChangeListener as ControlStateChangeListenerDefinition } from '.';
|
||||
import { ControlStateChangeListenerCallback, ControlStateChangeListener as ControlStateChangeListenerDefinition } from '.';
|
||||
|
||||
export class ControlStateChangeListener implements ControlStateChangeListenerDefinition {
|
||||
constructor(control: any /* UIControl */, callback: (state: string) => void) {
|
||||
constructor(control: any /* UIControl */, states: string[], callback: ControlStateChangeListenerCallback) {
|
||||
console.log('ControlStateChangeListener is intended for IOS usage only.');
|
||||
}
|
||||
public start() {}
|
||||
|
@ -1,4 +1,6 @@
|
||||
/**
|
||||
export type ControlStateChangeListenerCallback = (state: string, add: boolean) => void;
|
||||
|
||||
/**
|
||||
* An utility class used for supporting styling infrastructure.
|
||||
* WARNING: This class is intended for IOS only.
|
||||
*/
|
||||
@ -8,7 +10,7 @@ export class ControlStateChangeListener {
|
||||
* @param control An instance of the UIControl which state will be watched.
|
||||
* @param callback A callback called when a visual state of the UIControl is changed.
|
||||
*/
|
||||
constructor(control: any /* UIControl */, callback: (state: string) => void);
|
||||
constructor(control: any /* UIControl */, states: string[], callback: ControlStateChangeListenerCallback);
|
||||
|
||||
start();
|
||||
stop();
|
||||
|
@ -1,16 +1,21 @@
|
||||
/* tslint:disable:no-unused-variable */
|
||||
import { ControlStateChangeListener as ControlStateChangeListenerDefinition } from '.';
|
||||
import { ControlStateChangeListenerCallback, ControlStateChangeListener as ControlStateChangeListenerDefinition } from '.';
|
||||
|
||||
@NativeClass
|
||||
class ObserverClass extends NSObject {
|
||||
// NOTE: Refactor this - use Typescript property instead of strings....
|
||||
observeValueForKeyPathOfObjectChangeContext(path: string) {
|
||||
if (path === 'selected') {
|
||||
this['_owner']._onSelectedChanged();
|
||||
} else if (path === 'enabled') {
|
||||
this['_owner']._onEnabledChanged();
|
||||
} else if (path === 'highlighted') {
|
||||
this['_owner']._onHighlightedChanged();
|
||||
public callback: WeakRef<ControlStateChangeListenerCallback>;
|
||||
|
||||
public static initWithCallback(callback: WeakRef<ControlStateChangeListenerCallback>): ObserverClass {
|
||||
const observer = <ObserverClass>ObserverClass.alloc().init();
|
||||
observer.callback = callback;
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
public observeValueForKeyPathOfObjectChangeContext(path: string, object: UIControl) {
|
||||
const callback = this.callback?.deref();
|
||||
|
||||
if (callback) {
|
||||
callback(path, object[path]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,52 +23,33 @@ class ObserverClass extends NSObject {
|
||||
export class ControlStateChangeListener implements ControlStateChangeListenerDefinition {
|
||||
private _observer: NSObject;
|
||||
private _control: UIControl;
|
||||
private _observing = false;
|
||||
private _observing: boolean = false;
|
||||
|
||||
private _callback: (state: string) => void;
|
||||
private readonly _states: string[];
|
||||
|
||||
constructor(control: UIControl, callback: (state: string) => void) {
|
||||
this._observer = ObserverClass.alloc().init();
|
||||
this._observer['_owner'] = this;
|
||||
constructor(control: UIControl, states: string[], callback: ControlStateChangeListenerCallback) {
|
||||
this._control = control;
|
||||
this._callback = callback;
|
||||
this._states = states;
|
||||
this._observer = ObserverClass.initWithCallback(new WeakRef(callback));
|
||||
}
|
||||
|
||||
public start() {
|
||||
if (!this._observing) {
|
||||
this._control.addObserverForKeyPathOptionsContext(this._observer, 'highlighted', NSKeyValueObservingOptions.New, null);
|
||||
this._observing = true;
|
||||
this._updateState();
|
||||
|
||||
for (const state of this._states) {
|
||||
this._control.addObserverForKeyPathOptionsContext(this._observer, state, NSKeyValueObservingOptions.New, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public stop() {
|
||||
if (this._observing) {
|
||||
for (const state of this._states) {
|
||||
this._control.removeObserverForKeyPath(this._observer, state);
|
||||
}
|
||||
|
||||
this._observing = false;
|
||||
this._control.removeObserverForKeyPath(this._observer, 'highlighted');
|
||||
}
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
private _onEnabledChanged() {
|
||||
this._updateState();
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
private _onSelectedChanged() {
|
||||
this._updateState();
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
private _onHighlightedChanged() {
|
||||
this._updateState();
|
||||
}
|
||||
|
||||
private _updateState() {
|
||||
let state = 'normal';
|
||||
if (this._control.highlighted) {
|
||||
state = 'highlighted';
|
||||
}
|
||||
this._callback(state);
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +345,12 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
private _androidView: Object;
|
||||
private _style: Style;
|
||||
private _isLoaded: boolean;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
private _visualState: string;
|
||||
|
||||
private _templateParent: ViewBase;
|
||||
private __nativeView: any;
|
||||
// private _disableNativeViewRecycling: boolean;
|
||||
@ -557,10 +562,18 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
*/
|
||||
public reusable: boolean;
|
||||
|
||||
public readonly cssClasses: Set<string>;
|
||||
public readonly cssPseudoClasses: Set<string>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._domId = viewIdCounter++;
|
||||
this._style = new Style(new WeakRef(this));
|
||||
this.cssClasses = new Set();
|
||||
this.cssPseudoClasses = new Set();
|
||||
|
||||
this.cssPseudoClasses.add(this.defaultVisualState);
|
||||
|
||||
this.notify({ eventName: ViewBase.createdEvent, type: this.constructor.name, object: this });
|
||||
}
|
||||
|
||||
@ -800,14 +813,11 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
highlighted: ['active', 'pressed'],
|
||||
};
|
||||
|
||||
public cssClasses: Set<string> = new Set();
|
||||
public cssPseudoClasses: Set<string> = new Set();
|
||||
private getAllAliasedStates(name: string): string[] {
|
||||
const allStates: string[] = [name];
|
||||
|
||||
private getAllAliasedStates(name: string): Array<string> {
|
||||
const allStates = [];
|
||||
allStates.push(name);
|
||||
if (name in this.pseudoClassAliases) {
|
||||
for (let i = 0; i < this.pseudoClassAliases[name].length; i++) {
|
||||
for (let i = 0, length = this.pseudoClassAliases[name].length; i < length; i++) {
|
||||
allStates.push(this.pseudoClassAliases[name][i]);
|
||||
}
|
||||
}
|
||||
@ -823,7 +833,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
@profile
|
||||
public addPseudoClass(name: string): void {
|
||||
const allStates = this.getAllAliasedStates(name);
|
||||
for (let i = 0; i < allStates.length; i++) {
|
||||
for (let i = 0, length = allStates.length; i < length; i++) {
|
||||
if (!this.cssPseudoClasses.has(allStates[i])) {
|
||||
this.cssPseudoClasses.add(allStates[i]);
|
||||
this.notifyPseudoClassChanged(allStates[i]);
|
||||
@ -839,7 +849,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
@profile
|
||||
public deletePseudoClass(name: string): void {
|
||||
const allStates = this.getAllAliasedStates(name);
|
||||
for (let i = 0; i < allStates.length; i++) {
|
||||
for (let i = 0, length = allStates.length; i < length; i++) {
|
||||
if (this.cssPseudoClasses.has(allStates[i])) {
|
||||
this.cssPseudoClasses.delete(allStates[i]);
|
||||
this.notifyPseudoClassChanged(allStates[i]);
|
||||
@ -1334,11 +1344,32 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
view._isAddedToNativeVisualTree = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public get visualState() {
|
||||
return this._visualState;
|
||||
}
|
||||
|
||||
public _addVisualState(state: string): void {
|
||||
this.deletePseudoClass(this.defaultVisualState);
|
||||
this.addPseudoClass(state);
|
||||
}
|
||||
|
||||
public _removeVisualState(state: string): void {
|
||||
this.deletePseudoClass(state);
|
||||
|
||||
if (!this.cssPseudoClasses.size) {
|
||||
this.addPseudoClass(this.defaultVisualState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use View._addVisualState() and View._removeVisualState() instead.
|
||||
*/
|
||||
public _goToVisualState(state: string) {
|
||||
console.log('_goToVisualState() is deprecated. Use View._addVisualState() and View._removeVisualState() instead.');
|
||||
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(this + ' going to state: ' + state, Trace.categories.Style);
|
||||
}
|
||||
@ -1584,6 +1615,21 @@ export const idProperty = new Property<ViewBase, string>({
|
||||
});
|
||||
idProperty.register(ViewBase);
|
||||
|
||||
export const defaultVisualStateProperty = new Property<ViewBase, string>({
|
||||
name: 'defaultVisualState',
|
||||
defaultValue: 'normal',
|
||||
valueChanged(this: void, target, oldValue, newValue): void {
|
||||
const value = newValue || 'normal';
|
||||
|
||||
// Append new default if old one is currently applied
|
||||
if (target.cssPseudoClasses && target.cssPseudoClasses.has(oldValue)) {
|
||||
target.deletePseudoClass(oldValue);
|
||||
target.addPseudoClass(newValue);
|
||||
}
|
||||
},
|
||||
});
|
||||
defaultVisualStateProperty.register(ViewBase);
|
||||
|
||||
export function booleanConverter(v: string | boolean): boolean {
|
||||
const lowercase = (v + '').toLowerCase();
|
||||
if (lowercase === 'true') {
|
||||
|
9
packages/core/ui/core/view/index.d.ts
vendored
9
packages/core/ui/core/view/index.d.ts
vendored
@ -1022,6 +1022,15 @@ export abstract class View extends ViewCommon {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_addVisualState(state: string): void;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_removeVisualState(state: string): void;
|
||||
/**
|
||||
* @deprecated Use View.addPseudoClass() and View.deletePseudoClass() instead.
|
||||
* @private
|
||||
*/
|
||||
_goToVisualState(state: string);
|
||||
/**
|
||||
* @private
|
||||
|
@ -24,7 +24,7 @@ import { StyleScope } from '../../styling/style-scope';
|
||||
import { LinearGradient } from '../../styling/linear-gradient';
|
||||
|
||||
import * as am from '../../animation';
|
||||
import { AccessibilityEventOptions, AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait } from '../../../accessibility/accessibility-types';
|
||||
import { AccessibilityEventOptions, AccessibilityLiveRegion, AccessibilityRole, AccessibilityState } from '../../../accessibility/accessibility-types';
|
||||
import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
|
||||
import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, accessibilityPerformEscapeEvent, getCurrentFontScale } from '../../../accessibility';
|
||||
import { ShadowCSSValues } from '../../styling/css-shadow';
|
||||
@ -1266,24 +1266,18 @@ export const originYProperty = new Property<ViewCommon, number>({
|
||||
});
|
||||
originYProperty.register(ViewCommon);
|
||||
|
||||
export const defaultVisualStateProperty = new Property<ViewCommon, string>({
|
||||
name: 'defaultVisualState',
|
||||
defaultValue: 'normal',
|
||||
valueChanged(this: void, target, oldValue, newValue): void {
|
||||
target.defaultVisualState = newValue || 'normal';
|
||||
if (!target.visualState || target.visualState === oldValue) {
|
||||
target._goToVisualState(target.defaultVisualState);
|
||||
}
|
||||
},
|
||||
});
|
||||
defaultVisualStateProperty.register(ViewCommon);
|
||||
|
||||
export const isEnabledProperty = new Property<ViewCommon, boolean>({
|
||||
name: 'isEnabled',
|
||||
defaultValue: true,
|
||||
valueConverter: booleanConverter,
|
||||
valueChanged(this: void, target, oldValue, newValue): void {
|
||||
target._goToVisualState(newValue ? target.defaultVisualState : 'disabled');
|
||||
const state = 'disabled';
|
||||
|
||||
if (newValue) {
|
||||
target._removeVisualState(state);
|
||||
} else {
|
||||
target._addVisualState(state);
|
||||
}
|
||||
},
|
||||
});
|
||||
isEnabledProperty.register(ViewCommon);
|
||||
|
@ -6,6 +6,19 @@ import { booleanConverter } from '../core/view-base';
|
||||
import { Style } from '../styling/style';
|
||||
import { Color } from '../../color';
|
||||
import { CoreTypes } from '../../core-types';
|
||||
import { EventData } from '../../data/observable';
|
||||
|
||||
function focusChangeHandler(args: EventData): void {
|
||||
const view = args.object as EditableTextBase;
|
||||
|
||||
if (args.eventName === 'focus') {
|
||||
view._addVisualState('focus');
|
||||
view._removeVisualState('blur');
|
||||
} else {
|
||||
view._addVisualState('blur');
|
||||
view._removeVisualState('focus');
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class EditableTextBase extends TextBase implements EditableTextBaseDefinition {
|
||||
public static blurEvent = 'blur';
|
||||
@ -28,15 +41,12 @@ export abstract class EditableTextBase extends TextBase implements EditableTextB
|
||||
public abstract setSelection(start: number, stop?: number);
|
||||
placeholderColor: Color;
|
||||
|
||||
private _focusHandler = () => this._goToVisualState('focus');
|
||||
private _blurHandler = () => this._goToVisualState('blur');
|
||||
|
||||
@PseudoClassHandler('focus', 'blur')
|
||||
_updateTextBaseFocusStateHandler(subscribe) {
|
||||
const method = subscribe ? 'on' : 'off';
|
||||
|
||||
this[method]('focus', this._focusHandler);
|
||||
this[method]('blur', this._blurHandler);
|
||||
this[method]('focus', focusChangeHandler);
|
||||
this[method]('blur', focusChangeHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import { Color } from '../../color';
|
||||
export abstract class SearchBarBase extends View implements SearchBarDefinition {
|
||||
public static submitEvent = 'submit';
|
||||
public static clearEvent = 'clear';
|
||||
|
||||
public text: string;
|
||||
public hint: string;
|
||||
public textFieldBackgroundColor: Color;
|
||||
|
@ -13,17 +13,17 @@ export class SwitchBase extends View implements SwitchDefinition {
|
||||
|
||||
_onCheckedPropertyChanged(newValue: boolean) {
|
||||
if (newValue) {
|
||||
this.addPseudoClass('checked');
|
||||
this._addVisualState('checked');
|
||||
} else {
|
||||
this.deletePseudoClass('checked');
|
||||
this._removeVisualState('checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwitchBase.prototype.recycleNativeView = 'auto';
|
||||
|
||||
function onCheckedPropertyChanged(switchBase: SwitchBase, oldValue: boolean, newValue: boolean) {
|
||||
switchBase._onCheckedPropertyChanged(newValue);
|
||||
function onCheckedPropertyChanged(target: SwitchBase, oldValue: boolean, newValue: boolean) {
|
||||
target._onCheckedPropertyChanged(newValue);
|
||||
}
|
||||
|
||||
export const checkedProperty = new Property<SwitchBase, boolean>({
|
||||
|
@ -7,6 +7,7 @@ import { booleanConverter } from '../core/view-base';
|
||||
@CSSType('TextField')
|
||||
export class TextFieldBase extends EditableTextBase implements TextFieldDefinition {
|
||||
public static returnPressEvent = 'returnPress';
|
||||
|
||||
public secure: boolean;
|
||||
public closeOnReturn: boolean;
|
||||
// iOS only (to avoid 12+ suggested strong password handling)
|
||||
|
@ -3,5 +3,6 @@ import { EditableTextBase } from '../editable-text-base';
|
||||
|
||||
export class TextViewBase extends EditableTextBase implements TextViewDefinition {
|
||||
public static returnPressEvent = 'returnPress';
|
||||
|
||||
public maxLines: number;
|
||||
}
|
||||
|
Reference in New Issue
Block a user