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)
-
-
-
-## 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;
+ }
+ }
+}