refactor: circular deps part 11

This commit is contained in:
Nathan Walker
2025-07-09 11:23:53 -07:00
parent 1db6259763
commit 33d967b5b2
15 changed files with 113 additions and 92 deletions

View File

@ -2,14 +2,8 @@ import { assert, assertEqual } from '../tk-unit';
import { DOMNode } from '@nativescript/core/debugger/dom-types';
import { attachDOMInspectorCommandCallbacks, attachCSSInspectorCommandCallbacks, attachDOMInspectorEventCallbacks } from '@nativescript/core/debugger/devtools-elements';
import { InspectorCommands, InspectorEvents } from '@nativescript/core/debugger/devtools-elements';
import { unsetValue } from '@nativescript/core/ui/core/properties';
import { Button } from '@nativescript/core/ui/button';
import { Slider } from '@nativescript/core/ui/slider';
import { Label } from '@nativescript/core/ui/label';
import { unsetValue, Button, Slider, Label, TextView, StackLayout, isAndroid } from '@nativescript/core';
import { textProperty } from '@nativescript/core/ui/text-base';
import { TextView } from '@nativescript/core/ui/text-view';
import { StackLayout } from '@nativescript/core/ui/layouts/stack-layout';
import { isAndroid } from '@nativescript/core/platform';
let originalInspectorGlobal: InspectorCommands & InspectorEvents;

View File

@ -5,7 +5,8 @@ import { CoreTypes } from '../../core-types';
import { View, CSSType } from '../core/view';
import { ViewBase, booleanConverter } from '../core/view-base';
import { Trace } from '../../trace';
import { ShorthandProperty, CssProperty, Property, unsetValue } from '../core/properties';
import { ShorthandProperty, CssProperty, Property } from '../core/properties';
import { unsetValue } from '../core/properties/property-shared';
import { horizontalAlignmentProperty, verticalAlignmentProperty } from '../styling/style-properties';
import { Length } from '../styling/length-shared';
import { Style } from '../styling/style';

View File

@ -6,7 +6,7 @@ import { CoreTypes } from '../../core-types';
import { Trace } from '../../trace';
// Types.
import { unsetValue } from '../core/properties';
import { unsetValue } from '../core/properties/property-shared';
import { Animation } from './index';
import { backgroundColorProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, rotateProperty, opacityProperty, rotateXProperty, rotateYProperty, widthProperty, heightProperty } from '../styling/style-properties';

View File

@ -1,6 +1,6 @@
import type { ViewBase } from '../view-base';
import type { BindingOptions } from './bindable-types';
import { unsetValue } from '../properties';
import { unsetValue } from '../properties/property-shared';
import { Observable, PropertyChangeData } from '../../../data/observable';
import { addWeakEventListener, removeWeakEventListener } from '../weak-event-listener';
import { bindingConstants, parentsRegex } from '../../builder/binding-builder';

View File

@ -7,44 +7,7 @@ import { Style } from '../../styling/style';
import { profile } from '../../../profiling';
import { CoreTypes } from '../../enums';
import { makeValidator, makeParser } from '../../../core-types/validators';
/**
* Value specifying that Property should be set to its initial value.
*/
export const unsetValue: any = new Object();
export interface PropertyOptions<T, U> {
readonly name: string;
readonly defaultValue?: U;
readonly affectsLayout?: boolean;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
export interface CoerciblePropertyOptions<T, U> extends PropertyOptions<T, U> {
readonly coerceValue: (t: T, u: U) => U;
}
export interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> {
readonly cssName: string;
}
export interface ShorthandPropertyOptions<P> {
readonly name: string;
readonly cssName: string;
readonly converter: (value: string | P) => [CssProperty<any, any> | CssAnimationProperty<any, any>, any][];
readonly getter: (this: Style) => string | P;
}
export interface CssAnimationPropertyOptions<T, U> {
readonly name: string;
readonly cssName?: string;
readonly defaultValue?: U;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
import { unsetValue, PropertyOptions, CoerciblePropertyOptions, CssPropertyOptions, ShorthandPropertyOptions, CssAnimationPropertyOptions, isCssWideKeyword, isCssUnsetValue, isResetValue } from './property-shared';
const cssPropertyNames: string[] = [];
const symbolPropertyMap = {};
@ -71,14 +34,6 @@ function print(map) {
}
}
function isCssUnsetValue(value: any): boolean {
return value === 'unset' || value === 'revert';
}
function isResetValue(value: any): boolean {
return value === unsetValue || value === 'initial' || value === 'inherit' || isCssUnsetValue(value);
}
export function _printUnregisteredProperties(): void {
print(symbolPropertyMap);
print(cssSymbolPropertyMap);
@ -104,10 +59,6 @@ export function isCssVariableExpression(value: string) {
return value.includes('var(--');
}
export function isCssWideKeyword(value: any): value is CoreTypes.CSSWideKeywords {
return value === 'initial' || value === 'inherit' || isCssUnsetValue(value);
}
export function _evaluateCssVariableExpression(view: ViewBase, cssName: string, value: string): string {
if (typeof value !== 'string') {
return value;

View File

@ -0,0 +1,63 @@
// Shared property types, interfaces, and value helpers for properties and view-base modules.
// Only put platform-agnostic logic here.
/**
* Value specifying that Property should be set to its initial value.
*/
export const unsetValue: any = new Object();
export interface PropertyOptions<T, U> {
readonly name: string;
readonly defaultValue?: U;
readonly affectsLayout?: boolean;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
export interface CoerciblePropertyOptions<T, U> extends PropertyOptions<T, U> {
readonly coerceValue: (t: T, u: U) => U;
}
export interface CssPropertyOptions<T, U> extends PropertyOptions<T, U> {
readonly cssName: string;
}
// TODO: revisit this after circular dependency issues are resolved to see if types can be retained.
// export interface CssPropertyOptions<T extends Style, U> extends PropertyOptions<T, U> {
// readonly cssName: string;
// }
export interface ShorthandPropertyOptions<P> {
readonly name: string;
readonly cssName: string;
readonly converter: (value: string | P) => [any, any][];
readonly getter: (this: any) => string | P;
}
// TODO: revisit this after circular dependency issues are resolved to see if types can be retained.
// export interface ShorthandPropertyOptions<P> {
// readonly name: string;
// readonly cssName: string;
// readonly converter: (value: string | P) => [CssProperty<any, any> | CssAnimationProperty<any, any>, any][];
// readonly getter: (this: Style) => string | P;
// }
export interface CssAnimationPropertyOptions<T, U> {
readonly name: string;
readonly cssName?: string;
readonly defaultValue?: U;
readonly equalityComparer?: (x: U, y: U) => boolean;
readonly valueChanged?: (target: T, oldValue: U, newValue: U) => void;
readonly valueConverter?: (value: string) => U;
}
export function isCssUnsetValue(value: any): boolean {
return value === 'unset' || value === 'revert';
}
export function isResetValue(value: any): boolean {
return value === unsetValue || value === 'initial' || value === 'inherit' || isCssUnsetValue(value);
}
export function isCssWideKeyword(value: any): boolean {
return value === 'initial' || value === 'inherit' || isCssUnsetValue(value);
}

View File

@ -13,6 +13,7 @@ import type { ModalTransition } from '../../transition/modal-transition';
// TODO: Remove this import!
import { getClass } from '../../../utils/types';
import { unsetValue } from '../properties/property-shared';
import { profile } from '../../../profiling';

View File

@ -7,7 +7,7 @@ import { Length } from '../../styling/length-shared';
import { layout } from '../../../utils';
import { Trace } from '../../../trace';
import { ShowModalOptions, hiddenProperty } from '../view-base';
import { isCssWideKeyword } from '../properties';
import { isCssWideKeyword } from '../properties/property-shared';
import { EventData } from '../../../data/observable';
import { perspectiveProperty, visibilityProperty, opacityProperty, horizontalAlignmentProperty, verticalAlignmentProperty, minWidthProperty, minHeightProperty, widthProperty, heightProperty, marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, androidElevationProperty, androidDynamicElevationOffsetProperty } from '../../styling/style-properties';
@ -1375,15 +1375,15 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO
setPixels(this.nativeViewProtected, auto);
} else if (typeof length === 'number') {
setPixels(this.nativeViewProtected, layout.round(layout.toDevicePixels(length)));
} else if (length.unit == 'dip') {
} else if ((length as CoreTypes.LengthDipUnit).unit == 'dip') {
// tslint:disable-line
setPixels(this.nativeViewProtected, layout.round(layout.toDevicePixels(length.value)));
} else if (length.unit == 'px') {
setPixels(this.nativeViewProtected, layout.round(layout.toDevicePixels((length as CoreTypes.LengthDipUnit).value)));
} else if ((length as CoreTypes.LengthPxUnit).unit == 'px') {
// tslint:disable-line
setPixels(this.nativeViewProtected, layout.round(length.value));
} else if (length.unit == '%') {
setPixels(this.nativeViewProtected, layout.round((length as CoreTypes.LengthPxUnit).value));
} else if ((length as CoreTypes.LengthPercentUnit).unit == '%') {
// tslint:disable-line
setPercent(this.nativeViewProtected, length.value);
setPercent(this.nativeViewProtected, (length as CoreTypes.LengthPercentUnit).value);
} else {
throw new Error(`Unsupported PercentLength ${length}`);
}

View File

@ -3,6 +3,7 @@ export { ActivityIndicator } from './activity-indicator';
export { Animation, _resolveAnimationCurve } from './animation';
export { KeyframeAnimation, KeyframeAnimationInfo, KeyframeDeclaration, KeyframeInfo } from './animation/keyframe-animation';
export type { AnimationDefinition, Pair, Transformation, TransformationType, TransformationValue, TransformFunctionsInfo, Point3D, AnimationPromise, Cancelable } from './animation/animation-types';
export * from './animation/animation-shared';
export { Builder } from './builder';
export type { LoadOptions } from './builder';
export type { ComponentModule } from './builder/component-builder';
@ -17,7 +18,8 @@ export type { ShowModalOptions } from './core/view-base';
export { View, CSSType, ContainerView, ViewHelper, AndroidHelper, IOSHelper, isUserInteractionEnabledProperty, PseudoClassHandler, CustomLayoutView } from './core/view';
export type { Template, KeyedTemplate, AddArrayFromBuilder, AddChildFromBuilder } from './core/view';
export type { ShownModallyData, Size } from './core/view/view-interfaces';
export { Property, CoercibleProperty, InheritedProperty, CssProperty, InheritedCssProperty, ShorthandProperty, CssAnimationProperty, unsetValue, makeParser, makeValidator } from './core/properties';
export { Property, CoercibleProperty, InheritedProperty, CssProperty, InheritedCssProperty, ShorthandProperty, CssAnimationProperty, makeParser, makeValidator } from './core/properties';
export { unsetValue } from './core/properties/property-shared';
export { addWeakEventListener, removeWeakEventListener } from './core/weak-event-listener';
export { DatePicker } from './date-picker';

View File

@ -1,6 +1,7 @@
import { LayoutBase } from '../layout-base';
import { View, CSSType } from '../../core/view';
import { CssProperty, ShorthandProperty, makeParser, makeValidator, unsetValue } from '../../core/properties';
import { CssProperty, ShorthandProperty, makeParser, makeValidator } from '../../core/properties';
import { unsetValue } from '../../core/properties/property-shared';
import { Style } from '../../styling/style';
export type Basis = 'auto' | number;

View File

@ -1,7 +1,7 @@
import { ItemEventData, ItemsSource } from '.';
import { ListViewBase, separatorColorProperty, itemTemplatesProperty } from './list-view-common';
import { View, KeyedTemplate } from '../core/view';
import { unsetValue } from '../core/properties';
import { unsetValue } from '../core/properties/property-shared';
import { CoreTypes } from '../../core-types';
import { Color } from '../../color';
import { Observable } from '../../data/observable';
@ -269,7 +269,7 @@ export class ListView extends ListViewBase {
| {
dividerHeight: number;
divider: android.graphics.drawable.Drawable;
}
},
) {
const nativeView = this.nativeViewProtected;
if (value instanceof Color) {

View File

@ -3,7 +3,7 @@
import { CoreTypes } from '../../core-types';
import { layout } from '../../utils';
import { isCssWideKeyword } from '../core/properties';
import { isCssWideKeyword } from '../core/properties/property-shared';
function equalsCommon(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean;
@ -23,16 +23,16 @@ function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLength
if (!b) {
return false;
}
return b.unit == 'dip' && a == b.value;
return (b as CoreTypes.LengthDipUnit).unit == 'dip' && a == (b as CoreTypes.LengthDipUnit).value;
}
if (typeof b === 'number') {
return a ? a.unit == 'dip' && a.value == b : false;
return a ? (a as CoreTypes.LengthDipUnit).unit == 'dip' && (a as CoreTypes.LengthDipUnit).value == b : false;
}
if (!a || !b) {
return false;
}
return a.value == b.value && a.unit == b.unit;
return (a as CoreTypes.LengthDipUnit).value == (b as CoreTypes.LengthDipUnit).value && (a as CoreTypes.LengthDipUnit).unit == (b as CoreTypes.LengthDipUnit).unit;
}
function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentLengthType): string {
@ -44,12 +44,12 @@ function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentL
return length.toString();
}
let val = length.value;
if (length.unit === '%') {
let val = (length as CoreTypes.LengthPercentUnit).value;
if ((length as CoreTypes.LengthPercentUnit).unit === '%') {
val *= 100;
}
return val + length.unit;
return val + (length as CoreTypes.LengthPercentUnit).unit;
}
function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number = Number.NaN, parentAvailableWidth: number = Number.NaN): number {
@ -62,13 +62,17 @@ function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number
if (!length) {
return auto;
}
// @ts-ignore
switch (length.unit) {
case 'px':
// @ts-ignore
return layout.round(length.value);
case '%':
// @ts-ignore
return layout.round(parentAvailableWidth * length.value);
case 'dip':
default:
// @ts-ignore
return layout.round(layout.toDevicePixels(length.value));
}
}

View File

@ -1,4 +1,5 @@
import { unsetValue, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty, isCssWideKeyword } from '../core/properties';
import { CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from '../core/properties';
import { unsetValue, isCssWideKeyword } from '../core/properties/property-shared';
import { Style } from './style';
import { Color } from '../../color';
@ -25,7 +26,7 @@ interface ShorthandPositioning {
function equalsCommon(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean;
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean {
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType | CoreTypes.LengthDipUnit): boolean {
if (a == 'auto' || isCssWideKeyword(a)) {
return b == 'auto' || isCssWideKeyword(b);
}
@ -41,16 +42,16 @@ function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLength
if (!b) {
return false;
}
return b.unit == 'dip' && a == b.value;
return (b as CoreTypes.LengthDipUnit).unit == 'dip' && a == (b as CoreTypes.LengthDipUnit).value;
}
if (typeof b === 'number') {
return a ? a.unit == 'dip' && a.value == b : false;
return a ? (a as CoreTypes.LengthDipUnit).unit == 'dip' && (a as CoreTypes.LengthDipUnit).value == b : false;
}
if (!a || !b) {
return false;
}
return a.value == b.value && a.unit == b.unit;
return (a as CoreTypes.LengthDipUnit).value == (b as CoreTypes.LengthDipUnit).value && (a as CoreTypes.LengthDipUnit).unit == (b as CoreTypes.LengthDipUnit).unit;
}
function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentLengthType): string {
@ -62,12 +63,12 @@ function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentL
return length.toString();
}
let val = length.value;
if (length.unit === '%') {
let val = (length as CoreTypes.LengthPercentUnit).value;
if ((length as CoreTypes.LengthPercentUnit).unit === '%') {
val *= 100;
}
return val + length.unit;
return val + (length as CoreTypes.LengthPercentUnit).unit;
}
function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number = Number.NaN, parentAvailableWidth: number = Number.NaN): number {
@ -80,13 +81,17 @@ function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number
if (!length) {
return auto;
}
// @ts-ignore
switch (length.unit) {
case 'px':
// @ts-ignore
return layout.round(length.value);
case '%':
// @ts-ignore
return layout.round(parentAvailableWidth * length.value);
case 'dip':
default:
// @ts-ignore
return layout.round(layout.toDevicePixels(length.value));
}
}

View File

@ -1,6 +1,7 @@
import { ViewBase } from '../core/view-base';
import { View } from '../core/view';
import { unsetValue, _evaluateCssVariableExpression, _evaluateCssCalcExpression, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties';
import { _evaluateCssVariableExpression, _evaluateCssCalcExpression, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties';
import { unsetValue } from '../core/properties/property-shared';
import * as ReworkCSS from '../../css';
import { RuleSet, StyleSheetSelectorScope, SelectorCore, SelectorsMatch, ChangeMap, fromAstNode, Node, MEDIA_QUERY_SEPARATOR, matchMediaQueryString } from './css-selector';

View File

@ -1,8 +1,5 @@
// Types
import { getClosestPropertyValue, maxLinesProperty, textOverflowProperty } from './text-base-common';
import { ShadowCSSValues } from '../styling/css-shadow';
// Requires
import { Font } from '../styling/font';
import { TextBaseCommon, formattedTextProperty, textAlignmentProperty, textDecorationProperty, textProperty, textTransformProperty, textShadowProperty, textStrokeProperty, letterSpacingProperty, whiteSpaceProperty, lineHeightProperty, resetSymbol } from './text-base-common';
import { Color } from '../../color';
@ -16,7 +13,8 @@ import { layout } from '../../utils';
import { SDK_VERSION } from '../../utils/constants';
import { isString, isNullOrUndefined } from '../../utils/types';
import { accessibilityIdentifierProperty } from '../../accessibility/accessibility-properties';
import { isCssWideKeyword, testIDProperty } from '../../ui/core/view';
import { testIDProperty } from '../core/view';
import { isCssWideKeyword } from '../core/properties/property-shared';
export * from './text-base-common';
@ -423,7 +421,7 @@ export class TextBase extends TextBaseCommon {
if (value === 'none' || isCssWideKeyword(value)) {
this.nativeTextViewProtected.setPaintFlags(0);
} else {
this.nativeTextViewProtected.setPaintFlags(value);
this.nativeTextViewProtected.setPaintFlags(value as number);
}
break;
}