diff --git a/demo-vue/app/main.ts b/demo-vue/app/main.ts index a43f1210f..0856ad482 100644 --- a/demo-vue/app/main.ts +++ b/demo-vue/app/main.ts @@ -17,7 +17,7 @@ import { install as installBottomSheet } from '@nativescript-community/ui-materi import BottomSheetPlugin from '@nativescript-community/ui-material-bottomsheet/vue'; import BottomNavigationBarPlugin from '@nativescript-community/ui-material-bottomnavigationbar/vue'; import TabsPlugin from '@nativescript-community/ui-material-tabs/vue'; -import BottomNavigationPlugin from '@nativescript-community/ui-material-bottomnavigation/vue'; +import BottomNavigationPlugin from '@nativescript-community/ui-material-bottom-navigation/vue'; import SpeedDialPlugin from '@nativescript-community/ui-material-speeddial/vue'; installBottomSheet(); diff --git a/demo-vue/package.json b/demo-vue/package.json index f4d5fc604..3c7e69b4a 100644 --- a/demo-vue/package.json +++ b/demo-vue/package.json @@ -8,7 +8,7 @@ "@nativescript/core": "7.0.13", "@nativescript-community/text": "1.3.6", "@nativescript-community/ui-material-activityindicator": "file:../packages/activityindicator", - "@nativescript-community/ui-material-bottomnavigation": "file:../packages/bottomnavigation", + "@nativescript-community/ui-material-bottom-navigation": "file:../packages/bottom-navigation", "@nativescript-community/ui-material-bottomnavigationbar": "file:../packages/bottomnavigationbar", "@nativescript-community/ui-material-bottomsheet": "file:../packages/bottomsheet", "@nativescript-community/ui-material-button": "file:../packages/button", diff --git a/packages/bottomnavigation/.npmignore b/packages/bottom-navigation/.npmignore similarity index 100% rename from packages/bottomnavigation/.npmignore rename to packages/bottom-navigation/.npmignore diff --git a/packages/bottom-navigation/README.md b/packages/bottom-navigation/README.md new file mode 100644 index 000000000..27ff5242a --- /dev/null +++ b/packages/bottom-navigation/README.md @@ -0,0 +1,216 @@ +[![npm](https://img.shields.io/npm/v/nativescript-material-bottom-navigation.svg)](https://www.npmjs.com/package/nativescript-material-bottom-navigation) +[![npm](https://img.shields.io/npm/dt/nativescript-material-bottom-navigation.svg?label=npm%20downloads)](https://www.npmjs.com/package/nativescript-material-bottom-navigation) +[![GitHub forks](https://img.shields.io/github/forks/Akylas/nativescript-material-components.svg)](https://github.com/Akylas/nativescript-material-components/network) +[![GitHub stars](https://img.shields.io/github/stars/Akylas/nativescript-material-components.svg)](https://github.com/Akylas/nativescript-material-components/stargazers) + +## Installation + +### Warning :warning: :warning: +From 5.x using material component will break N tab component on iOS (which is bound to be removed). This is needed to allow using the latest native iOS features. If needed you can use either [bottomnavigationbar](https://www.npmjs.com/package/nativescript-material-bottomnavigationbar) (this one is the best choice, closest to material design) or [tabs](https://www.npmjs.com/package/nativescript-material-bottom-navigation) (clone of N one, but with a little less features) + +* `tns plugin add @nativescript-community/ui-material-bottom-navigation` + +Be sure to run a new build after adding plugins to avoid any issues. + +--- + +##### [Material Design Spec](https://material.io/design/components/bottom-navigation.html) + +### Usage + + +## Plain NativeScript + +IMPORTANT: _Make sure you include `xmlns:mds="@nativescript-community/ui-material-bottom-navigation"` on the Page element_ + +### XML + +```XML + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### CSS + +```CSS +MDBottomNavigation.bottom-nav { + background-color: orangered; + color: gold; + font-size: 18; +} + +TabStripItem.tabstripitem-active { + background-color: teal; +} + +TabStripItem.tabstripitem-active:active { + background-color: yellowgreen; +} + +TabContentItem.first-tabcontent { + background-color: seashell; + color: olive; +} +TabContentItem.second-tabcontent { + background-color: slategray; + color: aquamarine; +} +TabContentItem.third-tabcontent { + background-color: blueviolet; + color: antiquewhite; +} +MDBottomNavigation TabStrip { + highlight-color: red; +} +``` + +## NativeScript + Angular + +```typescript +import { NativeScriptMaterialTabsModule } from "@nativescript-community/ui-material-slider/angular"; + +@NgModule({ + imports: [ + NativeScriptMaterialTabsModule, + ... + ], + ... +}) +``` + +```html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## NativeScript + Vue + +```javascript +import BottomNavigation from '@nativescript-community/ui-material-bottom-navigation/vue'; + +Vue.use(BottomNavigation); +``` + +```html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## Attributes + +| Name |Type| Description| +| ------------- |:-------------:| -----:| +| items | Array | Gets or sets the items of the BottomNavigation.| +|selectedIndex | number | Gets or sets the selectedIndex of the BottomNavigation.| +|swipeEnabled | boolean | Gets or sets the swipe enabled state of the Tabs.| +|offscreenTabLimit | number | Gets or sets the number of offscreen preloaded tabs of the Tabs.| +|tabStrip |TabStrip | Gets or sets the tab strip of the BottomNavigation.| +|tabsPosition | "top", "bottom" | Gets or sets the position state of the Tabs. Default value: top| +|iOSTabBarItemsAlignment | "leading", "justified", "center", "centerSelected" |iOS Only: Gets or set the MDCTabBarAlignment of the tab bar icons in iOS. Default value: justified| + +## Events + +|Name | Description| +| ------------- |:-------------:| -----:| +|selectedIndexChanged | Emitted when the selectedIndex property is changed. +|loaded | Emitted when the view is loaded. +|unloaded | Emitted when the view is unloaded. +|layoutChanged | Emitted when the layout bounds of a view changes due to layout processing. diff --git a/packages/bottomnavigation/package-lock.json b/packages/bottom-navigation/package-lock.json similarity index 100% rename from packages/bottomnavigation/package-lock.json rename to packages/bottom-navigation/package-lock.json diff --git a/packages/bottomnavigation/package.json b/packages/bottom-navigation/package.json similarity index 89% rename from packages/bottomnavigation/package.json rename to packages/bottom-navigation/package.json index 8e111e833..b3486d446 100644 --- a/packages/bottomnavigation/package.json +++ b/packages/bottom-navigation/package.json @@ -1,5 +1,5 @@ { - "name": "@nativescript-community/ui-material-bottomnavigation", + "name": "@nativescript-community/ui-material-bottom-navigation", "version": "5.1.16", "description": "Material Design Bottom Navigation bars allow movement between primary destinations in an app. Tapping on a bottom navigation icon takes you directly to the associated view or refreshes the currently active view.", "main": "bottomnavigation", @@ -16,7 +16,7 @@ "tsc-win": "../../node_modules/.bin/cpy ..\\..\\src\\bottom-navigation\\index.d.ts .\\ && ..\\..\\node_modules\\.bin\\tsc --skipLibCheck -d", "build": "npm run tsc", "build.all": "npm run build && npm run build.angular", - "build.angular": "../../node_modules/.bin/ng-packagr -p ../../src/bottomnavigation/angular/package.json -c ../../src/bottom-navigation/angular/tsconfig.json", + "build.angular": "../../node_modules/.bin/ng-packagr -p ../../src/bottom-navigation/angular/package.json -c ../../src/bottom-navigation/angular/tsconfig.json", "clean": "../../node_modules/.bin/rimraf ./*.d.ts ./*.js ./*.js.map" }, "keywords": [ @@ -43,7 +43,7 @@ "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/nativescript-community/ui-material-components/tree/master/packages/bottomnavigation" + "url": "https://github.com/nativescript-community/ui-material-components/tree/master/packages/bottom-navigation" }, "readmeFilename": "README.md", "dependencies": { diff --git a/packages/bottomnavigation/platforms/ios/Podfile b/packages/bottom-navigation/platforms/ios/Podfile similarity index 100% rename from packages/bottomnavigation/platforms/ios/Podfile rename to packages/bottom-navigation/platforms/ios/Podfile diff --git a/packages/bottomnavigation/tsconfig.json b/packages/bottom-navigation/tsconfig.json similarity index 100% rename from packages/bottomnavigation/tsconfig.json rename to packages/bottom-navigation/tsconfig.json diff --git a/packages/bottomnavigation/README.md b/packages/bottomnavigation/README.md deleted file mode 100644 index 48c69b37b..000000000 --- a/packages/bottomnavigation/README.md +++ /dev/null @@ -1,274 +0,0 @@ -# Nativescript Material Bottom Navigation - -Nativescript plugin for Android & iOS to have the Bottom Navigation Bar following the Material Design Guidelines. - -[![npm](https://img.shields.io/npm/v/nativescript-material-bottomnavigation.svg)](https://www.npmjs.com/package/nativescript-material-bottomnavigation) [![npm](https://img.shields.io/npm/dt/nativescript-material-bottomnavigation.svg?label=npm%20downloads)](https://www.npmjs.com/package/nativescript-material-bottomnavigation) - -iOS - -## Contents - -1. [Installation](#installation) -2. [Usage with Javascript](#usage) -3. [Usage with Angular](#angular) -4. [Usage with Vue](#vue) -5. [Css Styling](#css-styling) -6. [API](#api) - -### Prerequisites / Requirements - -You need the version of NS6 or later to use this plugin. - -### Installation -For N 7.0 -* `tns plugin add @nativescript-community/ui-material-bottomnavigation` - -For N 6.x -* `tns plugin add nativescript-material-bottomnavigation` - -### NEW FEATURES - -- `Badge` now are supported using the method: `showBadge(index, value)` - - NOTE: if you want to show a badge as a red dot no value should be passed to the function. - -### Usage - -Before start using the plugin you need to add the icons for Android & iOS in your `App_Resources` directory. - -#### XML - -You can set the tabs using the `tabs` property - -```xml - - - - - - - - -``` - -```typescript -import { EventData } from '@nativescript/core/data/observable'; -import { Page } from '@nativescript/core/ui/page'; -import { BottomNavigationTab, TabSelectedEventData } from '@nativescript-community/ui-material-bottomnavigation'; - -// Event handler for Page 'loaded' event attached in main-page.xml -export function pageLoaded(args: EventData) { - // Get the event sender - let page = args.object; - page.bindingContext = { - tabs: [ - new BottomNavigationTab({ title: 'First', icon: 'res://ic_home' }), - new BottomNavigationTab({ - title: 'Second', - icon: 'res://ic_view_list', - isSelectable: false - }), - new BottomNavigationTab({ title: 'Third', icon: 'res://ic_menu' }) - ] - }; -} - -export function tabSelected(args: TabSelectedEventData) { - console.log('tab selected ' + args.newIndex); -} -``` - -or you can add the tabs directly in your xml view - -```xml - - - - - - - - - -         - - -``` - -#### Angular - -First you need to include the `NativeScriptMaterialbottomnavigationModule` in your `app.module.ts`` - -```typescript -import { NativeScriptMaterialbottomnavigationModule} from "@nativescript-community/ui-material-bottomnavigation/angular"; - -@NgModule({ - imports: [ - NativeScriptMaterialbottomnavigationModule - ], - ... -}) -``` - -```html - - - - - - -``` - -or you can declare the `BottomNavigationTab` in your html directly - -```html - - - - - - - - - - -``` - -#### Vue - -If you want to use this plugin with Vue, do this in your `app.js` or `main.js`: - -```javascript -import bottomnavigation from '@nativescript-community/ui-material-bottomnavigation/vue'; - -Vue.use(bottomnavigation); -``` - -This will install and register `bottomnavigation` and `BottomNavigationTab` components to your `Vue` instance and now you can use the plugin as follows: - -```html - - - - - - - - - - -``` - -You can find more information of how to use nativescript plugins with Vue [Here!](https://nativescript-vue.org/en/docs/getting-started/nativescript-plugins/) - -#### CSS Styling - -You can also use your css file to set or change the `activeColor`, `inactiveColor` & `backgroundColor` of the Bottom Navigation Bar. - -```css -.botom-nav { - active-color: green; - inactive-color: black; - background-color: blue; -} -``` - -## API - -1. [bottomnavigation](#bottom-navigation-bar) -2. [BottomNavigationTab](#bottom-navigation-tab) - -- **Properties (bindable):** Properties settable through XML/HTML -- **Properties (internal):** Properties accessible through JS/TS instance -- **Events:** Event properties settable thew XML/HTML - -# Bottom Navigation Bar - -#### Properties (bindable) - -Properties settable through XML/HTML - -| Property | Required | Default | Type | Description | -| --------------- | -------- | --------------------------- | ---------------------------- | ------------------------------------------------------- | -| tabs | true | [] | `Array` | Array containing the tabs for the bottomnavigation | -| titleVisibility | false | `TitleVisibility.Selected` | `TitleVisibility` | Title Visibility for each BottomNavigationTab | -| activeColor | false | "black" | `String` | Color of the BottomNavigationTab when it's selected | -| inactiveColor | false | "gray" | `String` | Color of the BottomNavigationTab when it's not selected | -| backgroundColor | false | "white" | `String` | Color of the BottomNavigation background | - -#### Properties (internal) - -Properties accessible through JS/TS instance - -| Property | Default | Type | Description | -| ---------------- | --------------------------- | ---------------------------- | ------------------------------------------------------- | -| items | `[]` | `Array` | Array containing the tabs for the bottomnavigation | -| selectedTabIndex | 0 | `Number` | Index of the selected tab | -| titleVisibility | `TitleVisibility.Selected` | `TitleVisibility` | Title Visibility for each BottomNavigationTab | -| activeColor | `new Color('black')` | `Color` | Color of the BottomNavigationTab when it's selected | -| inactiveColor | `new Color('gray')` | `Color` | Color of the BottomNavigationTab when it's not selected | -| backgroundColor | `new Color('white')` | `Color` | Color of the BottomNavigation background | - -#### Events - -Event properties settable thew XML/HTML - -| Name | Type | Description | -| ------------- | -------------------------------------- | ------------------------------------------------------------------------ | -| tabPressed | `(args: TabPressedEventData): void` | Function fired every time the user tap a tab with `isSelectable: false` | -| tabSelected | `(args: TabSelectedEventData): void` | Function fired every time the user select a new tab | -| tabReselected | `(args: TabReselectedEventData): void` | Function fired every time the user select a tab that is already selected | - -#### Methods - -Methods accessible through JS/TS instance - -| Property | Type | Description | -| ------------------------------------------ | ------ | -------------------------------- | -| `selectTab(index: number)` | `void` | Select a tab programmatically | -| `showBadge(index: number, value?: number)` | `void` | Show a badge for an specific tab | - -# Bottom Navigation Tab - -#### Properties (bindable) - -Properties settable through XML/HTML - -| Property | Required | Default | Type | Description | -| ------------ | -------- | ------- | --------- | ------------------------------------------- | -| title | true | null | `string` | Title of the tab | -| icon | true | null | `string` | Icon of the tab | -| isSelectable | false | true | `boolean` | Determine if the tab can be selected or not | diff --git a/packages/tabs/README.md b/packages/tabs/README.md index 1f3078c63..9ba888800 100644 --- a/packages/tabs/README.md +++ b/packages/tabs/README.md @@ -101,7 +101,7 @@ MDTabs TabStrip { ## NativeScript + Angular ```typescript -import { NativeScriptMaterialTabsModule } from "@nativescript-community/ui-material-slider/angular"; +import { NativeScriptMaterialTabsModule } from "@nativescript-community/ui-material-tabs/angular"; @NgModule({ imports: [ @@ -196,10 +196,6 @@ Vue.use(TabsPlugin); ## Attributes -Inherite from Nativescript [Tabs](https://docs.nativescript.org/ui/ns-ui-widgets/slider) so it already has all the same attributes - -## Attributes - | Name |Type| Description| | ------------- |:-------------:| -----:| | items | Array | Gets or sets the items of the BottomNavigation.| diff --git a/src/bottom-navigation/angular/index.ts b/src/bottom-navigation/angular/index.ts index 438abb5a4..fc0d36251 100644 --- a/src/bottom-navigation/angular/index.ts +++ b/src/bottom-navigation/angular/index.ts @@ -1,6 +1,6 @@ import { Directive, NgModule } from '@angular/core'; import { registerElement } from '@nativescript/angular'; -import { BottomNavigation } from '@nativescript-community/ui-material-bottomnavigation'; +import { BottomNavigation } from '@nativescript-community/ui-material-bottom-navigation'; @Directive({ selector: 'MDBottomNavigation' }) export class MaterialBottomNavigationDirective {} diff --git a/src/bottom-navigation/angular/package.json b/src/bottom-navigation/angular/package.json index dafd159ea..12ff215d0 100644 --- a/src/bottom-navigation/angular/package.json +++ b/src/bottom-navigation/angular/package.json @@ -1,14 +1,14 @@ { - "name": "@nativescript-community/ui-material-bottomnavigation-angular", + "name": "@nativescript-community/ui-material-bottom-navigation-angular", "main": "index.js", "ngPackage": { - "dest":"../../../packages/bottomnavigation/angular", + "dest": "../../../packages/bottom-navigation/angular", "lib": { "entryFile": "index.ts", "umdModuleIds": { "@nativescript/core": "ns-core", "@nativescript/angular": "ns-angular", - "@nativescript-community/ui-material-bottomnavigation": "ns-material-bottomnavigation" + "@nativescript-community/ui-material-bottom-navigation": "ns-material-bottom-navigation" } }, "whitelistedNonPeerDependencies": [ diff --git a/src/bottom-navigation/angular/tsconfig.json b/src/bottom-navigation/angular/tsconfig.json index c47c0b31a..4eae05416 100644 --- a/src/bottom-navigation/angular/tsconfig.json +++ b/src/bottom-navigation/angular/tsconfig.json @@ -7,8 +7,8 @@ "tns-core-modules/*": ["./node_modules/@nativescript/core/*"], "@nativescript-community/ui-material-core": ["packages/core/index"], "@nativescript-community/ui-material-core/*": ["packages/core/*"], - "@nativescript-community/ui-material-bottomnavigation": ["packages/bottomnavigation/index"], - "@nativescript-community/ui-material-bottomnavigation/*": ["packages/bottomnavigation/*"] + "@nativescript-community/ui-material-bottom-navigation": ["packages/bottom-navigation/index"], + "@nativescript-community/ui-material-bottom-navigation/*": ["packages/bottom-navigation/*"] } }, "include": ["./**/*.ts", "../../../references.d.ts", "../../references.d.ts"], diff --git a/src/textfield/textfield.new.ios.t b/src/textfield/textfield.new.ios.t new file mode 100644 index 000000000..fbfd2b158 --- /dev/null +++ b/src/textfield/textfield.new.ios.t @@ -0,0 +1,377 @@ +import { VerticalTextAlignment, verticalTextAlignmentProperty } from '@nativescript-community/text'; +import { themer } from '@nativescript-community/ui-material-core'; +import { + buttonColorProperty, + counterMaxLengthProperty, + digitsProperty, + errorColorProperty, + errorProperty, + floatingColorProperty, + floatingInactiveColorProperty, + floatingProperty, + helperColorProperty, + helperProperty, + strokeColorProperty, + strokeDisabledColorProperty, + strokeInactiveColorProperty +} from '@nativescript-community/ui-material-core/textbase/cssproperties'; +import { + Background, + Color, + Font, + Style, + Utils, + _updateCharactersInRangeReplacementString, + backgroundInternalProperty, + editableProperty, + fontInternalProperty, + hintProperty, + paddingBottomProperty, + paddingLeftProperty, + paddingRightProperty, + paddingTopProperty, + placeholderColorProperty +} from '@nativescript/core'; +import { textProperty } from '@nativescript/core/ui/text-base'; +import { TextFieldBase } from './textfield.common'; + +@NativeClass +class MDCFilledTextFieldImpl extends MDCFilledTextField { + _owner: WeakRef; + public static initWithOwner(owner: TextField) { + const delegate = MDCFilledTextFieldImpl.new() as MDCFilledTextFieldImpl; + delegate._owner = new WeakRef(owner); + + return delegate; + } + textRectForBounds(bounds: CGRect) { + const owner = this._owner ? this._owner.get() : null; + if (owner) { + return owner._getTextRectForBounds(bounds); + } + return super.textRectForBounds(bounds); + } + public editingRectForBounds(bounds: CGRect): CGRect { + const owner = this._owner ? this._owner.get() : null; + if (owner) { + return owner._getTextRectForBounds(bounds); + } + return super.editingRectForBounds(bounds); + } +} + +@NativeClass +class MDCOutlinedTextFieldImpl extends MDCOutlinedTextField { + _owner: WeakRef; + public static initWithOwner(owner: TextField) { + const delegate = MDCOutlinedTextFieldImpl.new() as MDCOutlinedTextFieldImpl; + delegate._owner = new WeakRef(owner); + + return delegate; + } + textRectForBounds(bounds: CGRect) { + const owner = this._owner ? this._owner.get() : null; + if (owner) { + return owner._getTextRectForBounds(bounds); + } + return super.textRectForBounds(bounds); + } + public editingRectForBounds(bounds: CGRect): CGRect { + const owner = this._owner ? this._owner.get() : null; + if (owner) { + return owner._getTextRectForBounds(bounds); + } + return super.editingRectForBounds(bounds); + } +} + +@NativeClass +class MDCUnderlinedTextFieldImpl extends MDCUnderlinedTextField { + _owner: WeakRef; + public static initWithOwner(owner: TextField) { + const delegate = MDCUnderlinedTextFieldImpl.new() as MDCUnderlinedTextFieldImpl; + delegate._owner = new WeakRef(owner); + + return delegate; + } + textRectForBounds(bounds: CGRect) { + const owner = this._owner ? this._owner.get() : null; + if (owner) { + return owner._getTextRectForBounds(bounds); + } + return super.textRectForBounds(bounds); + } + public editingRectForBounds(bounds: CGRect): CGRect { + const owner = this._owner ? this._owner.get() : null; + if (owner) { + return owner._getTextRectForBounds(bounds); + } + return super.editingRectForBounds(bounds); + } +} + +declare module '@nativescript/core/ui/text-field' { + interface TextField { + textFieldShouldChangeCharactersInRangeReplacementString(textField: UITextField, range: NSRange, replacementString: string): boolean; + } +} + +export class TextField extends TextFieldBase { + nativeViewProtected: MDCBaseTextField; + nativeTextViewProtected: MDCBaseTextField; + public readonly style: Style & { variant: 'outline' | 'underline' | 'filled' }; + public nsdigits?: NSCharacterSet; + firstEdit: boolean; + public clearFocus() { + this.dismissSoftInput(); + } + + public requestFocus() { + this.focus(); + } + + textFieldShouldChangeCharactersInRangeReplacementString(textField: UITextField, range: NSRange, replacementString: string): boolean { + // ignore if not in our alllowed digits + if (this.nsdigits && replacementString.length > 0 && NSString.stringWithString(replacementString).rangeOfCharacterFromSet(this.nsdigits).location === NSNotFound) { + return false; + } + if (this.secureWithoutAutofill && !textField.secureTextEntry) { + /** + * Helps avoid iOS 12+ autofill strong password suggestion prompt + * Discussed in several circles but for example: + * https://github.com/expo/expo/issues/2571#issuecomment-473347380 + */ + textField.secureTextEntry = true; + } + + // we need to override this from N as in MDC case the range is 0 + // if (range.length > 0) { + const delta = replacementString.length - range.length; + if (delta > 0) { + if (textField.text.length + delta > this.maxLength) { + return false; + } + } + // } + + if (this.updateTextTrigger === 'textChanged') { + if (textField.secureTextEntry && this.firstEdit) { + textProperty.nativeValueChange(this, replacementString); + } else { + if (range.location <= textField.text.length) { + const newText = NSString.stringWithString(textField.text).stringByReplacingCharactersInRangeWithString(range, replacementString); + textProperty.nativeValueChange(this, newText); + } + } + } + + if (this.formattedText) { + _updateCharactersInRangeReplacementString(this.formattedText, range.location, range.length, replacementString); + } + + this.firstEdit = false; + + return true; + // return super.textFieldShouldChangeCharactersInRangeReplacementString(textField, range, replacementString); + } + + _getTextRectForBounds(bounds: CGRect): CGRect { + const size = bounds.size; + + const x = Utils.layout.toDeviceIndependentPixels(this.effectiveBorderLeftWidth + this.effectivePaddingLeft); + const y = Utils.layout.toDeviceIndependentPixels(this.effectiveBorderTopWidth + this.effectivePaddingTop); + const width = Utils.layout.toDeviceIndependentPixels( + Utils.layout.toDevicePixels(size.width) - (this.effectiveBorderLeftWidth + this.effectivePaddingLeft + this.effectivePaddingRight + this.effectiveBorderRightWidth) + ); + const height = Utils.layout.toDeviceIndependentPixels( + Utils.layout.toDevicePixels(size.height) - (this.effectiveBorderTopWidth + this.effectivePaddingTop + this.effectivePaddingBottom + this.effectiveBorderBottomWidth) + ); + + return CGRectMake(x, y, width, height); + } + + // variant = 'underline'; + public createNativeView() { + // const view = MDCTextFieldImpl.initWithOwner(new WeakRef(this)); + let view: MDCFilledTextFieldImpl | MDCOutlinedTextFieldImpl | MDCUnderlinedTextFieldImpl; + + // disable it for now + if (this.style.variant === 'filled') { + view = MDCFilledTextFieldImpl.initWithOwner(this); + } else if (this.style.variant === 'outline') { + view = MDCOutlinedTextFieldImpl.initWithOwner(this); + } else if (this.style.variant === 'underline') { + view = MDCUnderlinedTextFieldImpl.initWithOwner(this); + } else { + view = MDCUnderlinedTextFieldImpl.initWithOwner(this); + (view as MDCUnderlinedTextField).normalUnderlineThickness = 0; + (view as MDCUnderlinedTextField).editingUnderlineThickness = 0; + } + view.clearButtonMode = UITextFieldViewMode.Never; + //theme needs to be applied after setting the textInput + const scheme = MDCContainerScheme.new(); + scheme.colorScheme = themer.getAppColorScheme(); + view.applyThemeWithScheme(scheme); // Default theming method + view.applyErrorThemeWithScheme(scheme); // Default theming method + return view; + } + + // TODO: check why i was checking for isFirstResponder + // with it the blur event is not fired anymore + + // public dismissSoftInput() { + // if (this.nativeViewProtected.isFirstResponder) { + // super.dismissSoftInput(); + // } + // } + + blur() { + this.dismissSoftInput(); + } + + public setSelection(start: number, stop?: number) { + const view = this.nativeTextViewProtected; + if (stop !== undefined) { + const begin = view.beginningOfDocument; + view.selectedTextRange = view.textRangeFromPositionToPosition(view.positionFromPositionOffset(begin, start), view.positionFromPositionOffset(begin, stop)); + } else { + const begin = view.beginningOfDocument; + const pos = view.positionFromPositionOffset(begin, start); + view.selectedTextRange = view.textRangeFromPositionToPosition(pos, pos); + } + } + [editableProperty.setNative](value: boolean) { + this.clearFocus(); + // this.nativeTextViewProtected.enabled = value; + } + [floatingColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + this.nativeViewProtected.setFloatingLabelColorForState(color, MDCTextControlState.Editing); + this._updateAttributedPlaceholder(); + } + [floatingInactiveColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + // this._controller.inlinePlaceholderColor = color; + this.nativeViewProtected.setFloatingLabelColorForState(color, MDCTextControlState.Normal); + this._updateAttributedPlaceholder(); + } + [placeholderColorProperty.setNative](value: UIColor | Color) { + this._updateAttributedPlaceholder(); + } + [hintProperty.setNative](value: string) { + this._updateAttributedPlaceholder(); + if (this.floating && this.variant !== 'none') { + this.nativeViewProtected.label.text = value; + } + } + [errorColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + this.nativeViewProtected.trailingAssistiveLabel.textColor = color; + } + [strokeColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + const view = this.nativeViewProtected; + if (view instanceof MDCOutlinedTextFieldImpl) { + view.setOutlineColorForState(color, MDCTextControlState.Editing); + } else { + (view as MDCFilledTextFieldImpl).setUnderlineColorForState(color, MDCTextControlState.Editing); + } + } + [strokeInactiveColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + const view = this.nativeViewProtected; + if (view instanceof MDCOutlinedTextFieldImpl) { + view.setOutlineColorForState(color, MDCTextControlState.Normal); + } else { + (view as MDCFilledTextFieldImpl).setUnderlineColorForState(color, MDCTextControlState.Normal); + } + } + [strokeDisabledColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + const view = this.nativeViewProtected; + if (view instanceof MDCOutlinedTextFieldImpl) { + view.setOutlineColorForState(color, MDCTextControlState.Disabled); + } else { + (view as MDCFilledTextFieldImpl).setUnderlineColorForState(color, MDCTextControlState.Disabled); + } + } + [buttonColorProperty.setNative](value: Color) { + const color = value instanceof Color ? value.ios : value; + // this._controller.textInputClearButtonTintColor = color; + } + [helperProperty.setNative](value: string) { + this.nativeViewProtected.leadingAssistiveLabel.text = value; + } + [helperColorProperty.setNative](value: string | Color) { + const temp = typeof value === 'string' ? new Color(value) : value; + const color: UIColor = temp.ios; + this.nativeViewProtected.leadingAssistiveLabel.textColor = color; + } + [counterMaxLengthProperty.setNative](value: number) { + // this._controller.characterCountMax = value; + } + [floatingProperty.setNative](value: boolean) { + // this.nativeViewProtected.labelBehavior = MDCTextControlLabelBehavior.Floats; + } + [errorProperty.setNative](value: string) { + this.nativeViewProtected.trailingAssistiveLabel.text = value; + } + [digitsProperty.setNative](value: string) { + if (value && value.length > 0) { + this.nsdigits = NSCharacterSet.characterSetWithCharactersInString(value); + } else { + this.nsdigits = null; + } + } + [backgroundInternalProperty.setNative](value: Background) { + const view = this.nativeViewProtected; + switch (this.variant) { + case 'none': + super[backgroundInternalProperty.setNative](value); + break; + case 'outline': + case 'filled': + case 'underline': { + if (value.color) { + if (view instanceof MDCFilledTextFieldImpl) { + view.setFilledBackgroundColorForState(value.color ? value.color.ios : null, MDCTextControlState.Normal); + view.setFilledBackgroundColorForState(value.color ? value.color.ios : null, MDCTextControlState.Editing); + } else { + view.backgroundColor = value.color ? value.color.ios : null; + } + } + // if (value.borderTopColor) { + // this._controller.activeColor = value.borderTopColor.ios; + // } + break; + } + } + } + [fontInternalProperty.setNative](value: Font | UIFont) { + super[fontInternalProperty.setNative](value); + const view = this.nativeViewProtected; + const font = value instanceof Font ? value.getUIFont(view.font) : value; + view.leadingAssistiveLabel.font = font; + view.trailingAssistiveLabel.font = font; + } + + [verticalTextAlignmentProperty.setNative](value: VerticalTextAlignment) { + // TODO: not working for now + const view = this.nativeTextViewProtected; + view.backgroundColor = UIColor.redColor; + switch (value) { + case 'initial': + case 'top': + view.contentVerticalAlignment = UIControlContentVerticalAlignment.Top; + break; + case 'middle': + view.contentVerticalAlignment = UIControlContentVerticalAlignment.Center; + + break; + + case 'bottom': + view.contentVerticalAlignment = UIControlContentVerticalAlignment.Bottom; + break; + } + } +}