ui-material-components icon indicating copy to clipboard operation
ui-material-components copied to clipboard

React support

Open shirakaba opened this issue 4 years ago • 5 comments

This is mainly an issue just to provide documentation until a contribution can be made that incorporates this into the repo.

Here are JSX typings (from Mayer Lench) for the UI Material Components, enabling React support:

// app.ts
import { Button } from '@nativescript-community/ui-material-button'
import { Progress } from '@nativescript-community/ui-material-progress'
import { TextField } from '@nativescript-community/ui-material-textfield'
import { Ripple } from '@nativescript-community/ui-material-ripple'
import { Slider } from '@nativescript-community/ui-material-slider'
import { TextView } from '@nativescript-community/ui-material-textview'
import { ImageSource, View, TextField as NTextField } from '@nativescript/core'
import { ActivityIndicatorAttributes, ButtonAttributes, ContentViewAttributes, NativeScriptProps, ProgressAttributes, SliderAttributes, StackLayoutAttributes, TextFieldAttributes } from 'react-nativescript'
import { ActivityIndicatorBase } from '@nativescript-community/ui-material-activityindicator/index-common'
import { CardView } from '@nativescript-community/ui-material-cardview'
import { EditableTextBaseAttributes } from 'react-nativescript/dist/lib/react-nativescript-jsx'

/**
 * NativeScript Gradient extends StackLayout, so it inherits all the
 * same attributes. Thus, we extend StackLayoutAttributes here.
 */

interface MDButtonAttributes extends ButtonAttributes {
	variant?: string
	elevation?: number
	dynamicElevationOffset?: number;
	rippleColor?: string
	verticalTextAlignment?: string
	shape?: string
	imageSource?: ImageSource
	src?: string | ImageSource
	isLoading?: boolean
}

interface MDProgressAttributes extends ProgressAttributes {
	progressColor?: string;
	progressBackgroundColor?: string;
	indeterminate?: boolean;
	busy?: boolean;
	startAnimating?(): void;
	stopAnimating?(): void;
}

interface MDActivityIndicatorAttributes extends ActivityIndicatorAttributes {
	indeterminate?: boolean;
	startAnimating?(): void;
	stopAnimating?(): void;
	onMeasure?(widthMeasureSpec: number, heightMeasureSpec: number): void;
}

interface MDTextFieldAttributes extends TextFieldAttributes {
	nativeViewProtected?: any;
	helper?: string;
	helperColor?: string;
	counterMaxLength?: number;
	errorColor?: string;
	floating?: boolean;
	placeholderColor?: string;
	variant?: string;
	error?: string;
	digits?: string;

	focus?();
	blur?();
	requestFocus?();
	clearFocus?();
	setSelection?(start: number, stop?: number);
}

interface MDRippleAttributes extends StackLayoutAttributes {
	rippleColor?: string;
}

interface MDSliderAttributes extends SliderAttributes {
	rippleColor?: string;
	trackBackgroundColor?: string;
	trackFillColor?: string;
	thumbColor?: string;
	elevation?: number;
}

interface MDCardViewAttributes extends ContentViewAttributes {
	elevation?: number;
	dynamicElevationOffset?: number;
	rippleColor?: string;
	shape?: string;
}

interface MDTextViewAttributes extends EditableTextBaseAttributes {
	helper?: string;
	helperColor?: string;
	counterMaxLength?: number;
	errorColor?: string;
	floating?: boolean;
	placeholderColor?: string;
	variant?: string;
	error?: string;

	focus?();
	blur?();
	requestFocus?();
	clearFocus?();
	setSelection?(start: number, stop?: number);
}

declare global {
	module JSX {
		interface IntrinsicElements {
			mdProgress: NativeScriptProps<MDProgressAttributes, Progress>
			mdButton: NativeScriptProps<MDButtonAttributes, Button>
			mdActivityIndicator: NativeScriptProps<MDActivityIndicatorAttributes, ActivityIndicatorBase>
			mdCardView: NativeScriptProps<MDCardViewAttributes, CardView>
			mdSlider: NativeScriptProps<MDSliderAttributes, Slider>
			mdRipple: NativeScriptProps<MDRippleAttributes, Ripple>
			mdTextField: NativeScriptProps<MDTextFieldAttributes, TextField>
			mdTextView: NativeScriptProps<MDTextViewAttributes, TextView>
		}
	}
}

The elements would then be registered as:

registerElement('mdButton', () => require('@nativescript-community/ui-material-button').Button)
registerElement('mdProgress', () => require('@nativescript-community/ui-material-progress').Progress)
registerElement('mdActivityIndicator', () => require('@nativescript-community/ui-material-activityindicator').ActivityIndicator)
registerElement('mdBottomNavigationBar', () => require('@nativescript-community/ui-material-bottomnavigationbar').BottomNavigationBar)
registerElement('mdCardView', () => require('@nativescript-community/ui-material-cardview').CardView)
registerElement('mdFloatingActionButton', () => require('@nativescript-community/ui-material-floatingactionbutton').FloatingActionButton)
registerElement('mdRipple', () => require('@nativescript-community/ui-material-ripple').Ripple)
registerElement('mdSlider', () => require('@nativescript-community/ui-material-slider').Slider)
registerElement('mdTextField', () => require('@nativescript-community/ui-material-textfield').TextField)
registerElement('mdTextView', () => require('@nativescript-community/ui-material-textview').TextView)

shirakaba avatar Dec 11 '20 15:12 shirakaba

Awesome! This has been on my list to implement. I'll try to get around to it soon.

keerl avatar Dec 11 '20 15:12 keerl

Thanks @shirakaba, I'll start using

t1amat9409 avatar Dec 27 '20 08:12 t1amat9409

I need to use setSelection, as I'm developing a custom mask, can you guide me on how to achieve it?

NavruzbekNoraliev avatar Feb 09 '21 13:02 NavruzbekNoraliev

@NavruzbekNoraliev I think the provided setSelection typing is wrong – setSelection shouldn't be a prop for the React component; rather, it's an imperative API that you'd call on the native view.

For example:

import * as React from "react";
import { EventData } from "@nativescript/core";
import { TextField as MDTextField } from '@nativescript-community/ui-material-textfield';

function MDTextFieldExample(){
    // This event handler is called as soon as the native view has been populated.
    function onMDTextFieldLoaded(args: EventData): void {
        const mdTextField: MDTextField = args.object as MDTextField;
        mdTextField.setSelection(0); // Sets selection to start at 0.
    }

    return <mdTextField onLoaded={onMDTextFieldLoaded}/>;
}

Happy to help if you have further problems. There are other ways to get a reference to the native view, but what you'd write as code depends greatly on what exactly you're trying to do.

shirakaba avatar Feb 09 '21 15:02 shirakaba

@shirakaba thank you very much, this information really helped me to solve my problem)

NavruzbekNoraliev avatar Feb 10 '21 04:02 NavruzbekNoraliev