Files
Alexander Vakrilov cc97a16800 feat: Scoped Packages (#7911)
* chore: move tns-core-modules to nativescript-core

* chore: preparing compat generate script

* chore: add missing definitions

* chore: no need for http-request to be private

* chore: packages chore

* test: generate tests for tns-core-modules

* chore: add anroid module for consistency

* chore: add .npmignore

* chore: added privateModulesWhitelist

* chore(webpack): added bundle-entry-points

* chore: scripts

* chore: tests changed to use @ns/core

* test: add scoped-packages test project

* test: fix types

* test: update test project

* chore: build scripts

* chore: update build script

* chore: npm scripts cleanup

* chore: make the compat pgk work with old wp config

* test: generate diff friendly tests

* chore: create barrel exports

* chore: move files after rebase

* chore: typedoc config

* chore: compat mode

* chore: review of barrels

* chore: remove tns-core-modules import after rebase

* chore: dev workflow setup

* chore: update developer-workflow

* docs: experiment with API extractor

* chore: api-extractor and barrel exports

* chore: api-extractor configs

* chore: generate d.ts rollup with api-extractor

* refactor: move methods inside Frame

* chore: fic tests to use Frame static methods

* refactor: create Builder class

* refactor: use Builder class in tests

* refactor: include Style in ui barrel

* chore: separate compat build script

* chore: fix tslint errors

* chore: update NATIVESCRIPT_CORE_ARGS

* chore: fix compat pack

* chore: fix ui-test-app build with linked modules

* chore: Application, ApplicationSettings, Connectivity and Http

* chore: export Trace, Profiling and Utils

* refactor: Static create methods for ImageSource

* chore: fix deprecated usages of ImageSource

* chore: move Span and FormattedString to ui

* chore: add events-args and ImageSource to index files

* chore: check for CLI >= 6.2 when building for IOS

* chore: update travis build

* chore: copy Pod file to compat package

* chore: update error msg ui-tests-app

* refactor: Apply suggestions from code review

Co-Authored-By: Martin Yankov <m.i.yankov@gmail.com>

* chore: typings and refs

* chore: add missing d.ts files for public API

* chore: adress code review FB

* chore: update api-report

* chore: dev-workflow for other apps

* chore: api update

* chore: update api-report
2019-10-17 00:45:33 +03:00

458 lines
14 KiB
TypeScript

import {
ActionBar as ActionBarDefinition,
ActionItems as ActionItemsDefinition,
ActionItem as ActionItemDefinition,
NavigationButton, IOSActionItemSettings, AndroidActionItemSettings, AndroidActionBarSettings,
} from ".";
import { profile } from "../../profiling";
export * from "../core/view";
import {
View,
ViewBase,
Property,
unsetValue,
booleanConverter,
horizontalAlignmentProperty,
verticalAlignmentProperty,
CSSType,
traceWrite,
traceCategories,
traceMessageType
} from "../core/view";
import { ShorthandProperty, CssProperty, Style } from "../core/properties/properties";
import { Length } from "../core/view";
export module knownCollections {
export const actionItems = "actionItems";
}
@CSSType("ActionBar")
export class ActionBarBase extends View implements ActionBarDefinition {
private _actionItems: ActionItems;
private _navigationButton: NavigationButton;
private _titleView: View;
public title: string;
public flat: boolean;
public iosIconRenderingMode: "automatic" | "alwaysOriginal" | "alwaysTemplate";
public effectiveContentInsetLeft: number;
public effectiveContentInsetRight: number;
get navigationButton(): NavigationButton {
return this._navigationButton;
}
set navigationButton(value: NavigationButton) {
if (this._navigationButton !== value) {
if (this._navigationButton) {
this._removeView(this._navigationButton);
this._navigationButton.actionBar = undefined;
}
this._navigationButton = value;
if (this._navigationButton) {
this._navigationButton.actionBar = this;
this._addView(this._navigationButton);
}
this.update();
}
}
get actionItems(): ActionItems {
return this._actionItems;
}
set actionItems(value: ActionItems) {
throw new Error("actionItems property is read-only");
}
get titleView(): View {
return this._titleView;
}
set titleView(value: View) {
if (this._titleView !== value) {
if (this._titleView) {
this._removeView(this._titleView);
this._titleView.style[horizontalAlignmentProperty.cssName] = unsetValue;
this._titleView.style[verticalAlignmentProperty.cssName] = unsetValue;
}
this._titleView = value;
if (value) {
// Addview will reset CSS properties so we first add it then set aligments with lowest priority.
this._addView(value);
const style = value.style;
if (!horizontalAlignmentProperty.isSet(style)) {
style[horizontalAlignmentProperty.cssName] = "center";
}
if (!verticalAlignmentProperty.isSet(style)) {
style[verticalAlignmentProperty.cssName] = "middle";
}
}
this.update();
}
}
public get androidContentInset(): string | Length {
return this.style.androidContentInset;
}
public set androidContentInset(value: string | Length) {
this.style.androidContentInset = value;
}
public get androidContentInsetLeft(): Length {
return this.style.androidContentInsetLeft;
}
public set androidContentInsetLeft(value: Length) {
this.style.androidContentInsetLeft = value;
}
public get androidContentInsetRight(): Length {
return this.style.androidContentInsetRight;
}
public set androidContentInsetRight(value: Length) {
this.style.androidContentInsetRight = value;
}
get ios(): any {
return undefined;
}
get android(): AndroidActionBarSettings {
return undefined;
}
get _childrenCount(): number {
let actionViewsCount = 0;
this._actionItems.getItems().forEach((actionItem) => {
if (actionItem.actionView) {
actionViewsCount++;
}
});
return actionViewsCount + (this.titleView ? 1 : 0);
}
constructor() {
super();
this._actionItems = new ActionItems(this);
}
public static onTitleChanged;
public update() {
//
}
public _onTitlePropertyChanged() {
//
}
public _addArrayFromBuilder(name: string, value: Array<any>) {
if (name === "actionItems") {
this.actionItems.setItems(value);
}
}
public eachChildView(callback: (child: View) => boolean) {
const titleView = this.titleView;
if (titleView) {
callback(titleView);
}
}
public eachChild(callback: (child: ViewBase) => boolean) {
const titleView = this.titleView;
if (titleView) {
callback(titleView);
}
const navigationButton = this._navigationButton;
if (navigationButton) {
callback(navigationButton);
}
this.actionItems.getItems().forEach((actionItem) => {
callback(actionItem);
});
}
public _isEmpty(): boolean {
if (this.title ||
this.titleView ||
(this.android && this.android.icon) ||
this.navigationButton ||
this.actionItems.getItems().length > 0) {
return false;
}
return true;
}
}
export class ActionItems implements ActionItemsDefinition {
private _items = new Array<ActionItemDefinition>();
private _actionBar: ActionBarDefinition;
constructor(actionBar: ActionBarDefinition) {
this._actionBar = actionBar;
}
public addItem(item: ActionItemDefinition): void {
if (!item) {
throw new Error("Cannot add empty item");
}
this._items.push(item);
item.actionBar = this._actionBar;
this._actionBar._addView(item);
this.invalidate();
}
public removeItem(item: ActionItemDefinition): void {
if (!item) {
throw new Error("Cannot remove empty item");
}
const itemIndex = this._items.indexOf(item);
if (itemIndex < 0) {
throw new Error("Cannot find item to remove");
}
this._items.splice(itemIndex, 1);
this._actionBar._removeView(item);
item.actionBar = undefined;
this.invalidate();
}
public getItems(): Array<ActionItemDefinition> {
return this._items.slice();
}
public getVisibleItems(): Array<ActionItemDefinition> {
const visibleItems = [];
this._items.forEach((item) => {
if (isVisible(item)) {
visibleItems.push(item);
}
});
return visibleItems;
}
public getItemAt(index: number): ActionItemDefinition {
if (index < 0 || index >= this._items.length) {
return undefined;
}
return this._items[index];
}
public setItems(items: Array<ActionItemDefinition>) {
// Remove all existing items
while (this._items.length > 0) {
this.removeItem(this._items[this._items.length - 1]);
}
// Add new items
for (let i = 0; i < items.length; i++) {
this.addItem(items[i]);
}
this.invalidate();
}
private invalidate() {
if (this._actionBar) {
this._actionBar.update();
}
}
}
export class ActionItemBase extends ViewBase implements ActionItemDefinition {
public static tapEvent = "tap";
private _actionBar: ActionBarDefinition;
private _actionView: View;
public ios: IOSActionItemSettings;
public android: AndroidActionItemSettings;
public text: string;
public icon: string;
public visibility: string;
get actionView(): View {
return this._actionView;
}
set actionView(value: View) {
if (this._actionView !== value) {
if (this._actionView) {
this._actionView.style[horizontalAlignmentProperty.cssName] = unsetValue;
this._actionView.style[verticalAlignmentProperty.cssName] = unsetValue;
this._removeView(this._actionView);
}
this._actionView = value;
if (this._actionView) {
this._addView(this._actionView);
}
if (this._actionBar) {
this._actionBar.update();
}
}
}
get actionBar(): ActionBarDefinition {
return this._actionBar;
}
set actionBar(value: ActionBarDefinition) {
if (value !== this._actionBar) {
this._actionBar = value;
}
}
@profile
public onLoaded() {
if (this._actionView) {
this._actionView.style[horizontalAlignmentProperty.cssName] = "center";
this._actionView.style[verticalAlignmentProperty.cssName] = "middle";
}
super.onLoaded();
}
public _raiseTap() {
this._emit(ActionItemBase.tapEvent);
}
public _addChildFromBuilder(name: string, value: any) {
this.actionView = value;
}
public _onVisibilityChanged(visibility: string) {
if (this.actionBar) {
this.actionBar.update();
}
}
public eachChild(callback: (child: ViewBase) => boolean) {
if (this._actionView) {
callback(this._actionView);
}
}
}
export function isVisible(item: ActionItemDefinition) {
return item.visibility === "visible";
}
function onTitlePropertyChanged(actionBar: ActionBarBase, oldValue: string, newValue: string) {
actionBar._onTitlePropertyChanged();
}
export const titleProperty = new Property<ActionBarBase, string>({ name: "title", valueChanged: onTitlePropertyChanged });
titleProperty.register(ActionBarBase);
function onItemChanged(item: ActionItemBase, oldValue: string, newValue: string) {
if (item.actionBar) {
item.actionBar.update();
}
}
function onVisibilityChanged(item: ActionItemBase, oldValue: string, newValue: string) {
item._onVisibilityChanged(newValue);
}
export function traceMissingIcon(icon: string) {
traceWrite("Could not load action bar icon: " + icon,
traceCategories.Error,
traceMessageType.error);
}
function convertToContentInset(this: void, value: string | Length): [CssProperty<any, any>, any][] {
if (typeof value === "string" && value !== "auto") {
let insets = value.split(/[ ,]+/);
return [
[androidContentInsetLeftProperty, Length.parse(insets[0])],
[androidContentInsetRightProperty, Length.parse(insets[1] || insets[0])]
];
}
else {
return [
[androidContentInsetLeftProperty, value],
[androidContentInsetRightProperty, value]
];
}
}
export const iosIconRenderingModeProperty = new Property<ActionBarBase, "automatic" | "alwaysOriginal" | "alwaysTemplate">({ name: "iosIconRenderingMode", defaultValue: "alwaysOriginal" });
iosIconRenderingModeProperty.register(ActionBarBase);
export const textProperty = new Property<ActionItemBase, string>({ name: "text", defaultValue: "", valueChanged: onItemChanged });
textProperty.register(ActionItemBase);
export const iconProperty = new Property<ActionItemBase, string>({ name: "icon", valueChanged: onItemChanged });
iconProperty.register(ActionItemBase);
export const visibilityProperty = new Property({ name: "visibility", defaultValue: "visible", valueChanged: onVisibilityChanged });
visibilityProperty.register(ActionItemBase);
export const flatProperty = new Property<ActionBarBase, boolean>({ name: "flat", defaultValue: false, valueConverter: booleanConverter });
flatProperty.register(ActionBarBase);
const androidContentInsetProperty = new ShorthandProperty<Style, string | Length>({
name: "androidContentInset", cssName: "android-content-inset",
getter: function (this: Style) {
if (Length.equals(this.androidContentInsetLeft, this.androidContentInsetRight)) {
return this.androidContentInsetLeft;
}
return `${Length.convertToString(this.androidContentInsetLeft)} ${Length.convertToString(this.androidContentInsetRight)}`;
},
converter: convertToContentInset
});
androidContentInsetProperty.register(Style);
export const androidContentInsetLeftProperty = new CssProperty<Style, Length>({
name: "androidContentInsetLeft", cssName: "android-content-inset-left",
defaultValue: "auto", equalityComparer: Length.equals,
valueChanged: (target, oldValue, newValue) => {
const view = <ActionBarBase>target.viewRef.get();
if (view) {
view.effectiveContentInsetLeft = Length.toDevicePixels(newValue);
} else {
traceWrite(`${newValue} not set to view's property because ".viewRef" is cleared`, traceCategories.Style, traceMessageType.warn);
}
}, valueConverter: Length.parse
});
androidContentInsetLeftProperty.register(Style);
export const androidContentInsetRightProperty = new CssProperty<Style, Length>({
name: "androidContentInsetRight", cssName: "android-content-inset-right",
defaultValue: "auto", equalityComparer: Length.equals,
valueChanged: (target, oldValue, newValue) => {
const view = <ActionBarBase>target.viewRef.get();
if (view) {
view.effectiveContentInsetRight = Length.toDevicePixels(newValue);
} else {
traceWrite(`${newValue} not set to view's property because ".viewRef" is cleared`, traceCategories.Style, traceMessageType.warn);
}
}, valueConverter: Length.parse
});
androidContentInsetRightProperty.register(Style);