Merged PR 686347: Align the render rule with other platforms and enhance extensibility
Related work items: #1292147, #1300851, #1300852, #1300853, #1300854, #1300855, #1300856, #1307932
This commit is contained in:
Родитель
fe552d5317
Коммит
8b9dc5a947
|
@ -57,3 +57,5 @@ typings/
|
||||||
# dotenv environment variables file
|
# dotenv environment variables file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode
|
|
@ -0,0 +1,127 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { TouchableOpacity, View } from 'react-native';
|
||||||
|
export class FlexBox extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderChildren = () => {
|
||||||
|
if (this.props.children) {
|
||||||
|
return React.Children.map(this.props.children, (child, index) => {
|
||||||
|
if (child) {
|
||||||
|
if (typeof child !== 'string' && typeof child !== 'number') {
|
||||||
|
if (this.props.width === 'auto') {
|
||||||
|
return React.cloneElement(child, {
|
||||||
|
containerWidth: this.props.containerWidth,
|
||||||
|
containerHeight: this.props.containerHeight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return React.cloneElement(child, {
|
||||||
|
containerWidth: this.state.width,
|
||||||
|
containerHeight: this.state.height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onLayoutChange = (event) => {
|
||||||
|
let width = event.nativeEvent.layout.width;
|
||||||
|
let height = event.nativeEvent.layout.height;
|
||||||
|
this.setState({
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
}, () => {
|
||||||
|
console.log(`FlexBox: width: ${width} height: ${height}`);
|
||||||
|
if (this.props.onLayoutChange) {
|
||||||
|
this.props.onLayoutChange(width, height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.getFlexStyle = () => {
|
||||||
|
if (this.props.flex) {
|
||||||
|
return {
|
||||||
|
flex: this.props.flex
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.getChildrenFlexStyle = () => {
|
||||||
|
let result = {
|
||||||
|
flexDirection: this.props.flexDirection,
|
||||||
|
alignItems: this.props.wrap === 'wrap' ? 'flex-start' : this.props.alignItems,
|
||||||
|
justifyContent: this.props.justifyContent,
|
||||||
|
height: this.props.height,
|
||||||
|
flexWrap: this.props.wrap,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
this.getSizeStyle = () => {
|
||||||
|
if (this.props.width === 'auto') {
|
||||||
|
return {
|
||||||
|
flex: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.props.width === 'stretch') {
|
||||||
|
return {
|
||||||
|
flex: 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.props.relativeWidth && typeof this.props.width === 'number') {
|
||||||
|
return {
|
||||||
|
flex: this.props.width
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
width: this.props.width
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.getVerticalMarginStyle = () => {
|
||||||
|
if (this.props.vIndex > 0) {
|
||||||
|
return {
|
||||||
|
marginTop: this.props.vSpace,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.getHorizontalMarginStyle = () => {
|
||||||
|
if (this.props.hIndex > 0) {
|
||||||
|
return {
|
||||||
|
marginLeft: this.props.hSpace,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.state = {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
if (this.props.onPress) {
|
||||||
|
return this.renderTouchableBox();
|
||||||
|
}
|
||||||
|
return this.renderBox();
|
||||||
|
}
|
||||||
|
renderBox() {
|
||||||
|
return (React.createElement(View, { style: [
|
||||||
|
this.getChildrenFlexStyle(),
|
||||||
|
this.getFlexStyle(),
|
||||||
|
this.getSizeStyle(),
|
||||||
|
this.getVerticalMarginStyle(),
|
||||||
|
this.getHorizontalMarginStyle(),
|
||||||
|
this.props.style,
|
||||||
|
], onLayout: this.onLayoutChange }, this.renderChildren()));
|
||||||
|
}
|
||||||
|
renderTouchableBox() {
|
||||||
|
return (React.createElement(TouchableOpacity, { style: [
|
||||||
|
this.getChildrenFlexStyle(),
|
||||||
|
this.getFlexStyle(),
|
||||||
|
this.getSizeStyle(),
|
||||||
|
this.getVerticalMarginStyle(),
|
||||||
|
this.getHorizontalMarginStyle(),
|
||||||
|
this.props.style,
|
||||||
|
], onLayout: this.onLayoutChange, onPress: this.props.onPress }, this.renderChildren()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Image, Text, View } from 'react-native';
|
||||||
|
import { FlexBox } from './FlexBox';
|
||||||
|
export class ImageBlock extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderPlaceholder = () => {
|
||||||
|
if (!this.state.loaded) {
|
||||||
|
return (React.createElement(View, { style: [
|
||||||
|
{
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}
|
||||||
|
] },
|
||||||
|
React.createElement(Text, { style: {
|
||||||
|
fontSize: 32,
|
||||||
|
color: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
textAlign: 'center'
|
||||||
|
} }, '\uE601')));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onLayoutChange = (width, height) => {
|
||||||
|
Image.getSize(this.props.url, this.onImageSize, this.onImageSizeError);
|
||||||
|
};
|
||||||
|
this.onImageSizeUpdate = (event) => {
|
||||||
|
let width = event.nativeEvent.layout.width;
|
||||||
|
let height = event.nativeEvent.layout.height;
|
||||||
|
console.log(`Image at url:${this.props.url} size updated. Width: ${width}, height: ${height}`);
|
||||||
|
if (this.props.onImageSize) {
|
||||||
|
this.props.onImageSize(width, height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onImageSize = (width, height) => {
|
||||||
|
console.log(`Image at url:${this.props.url} get size succeed. Width: ${width}, height: ${height}`);
|
||||||
|
let ratio = width > 0 ? height / width : height;
|
||||||
|
if (this.props.width === 'auto') {
|
||||||
|
this.applyAutoSize(width, ratio);
|
||||||
|
}
|
||||||
|
else if (this.props.width === 'stretch') {
|
||||||
|
this.applyStretchSize(width, height, ratio);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.applyFixSize(ratio);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onImageSizeError = () => {
|
||||||
|
console.log(`Image at url:${this.props.url} get size failed.`);
|
||||||
|
this.setState({
|
||||||
|
loaded: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.onImageLoad = () => {
|
||||||
|
console.log(`Image at url:${this.props.url} load succeed.`);
|
||||||
|
this.setState({
|
||||||
|
loaded: true
|
||||||
|
});
|
||||||
|
Image.getSize(this.props.url, this.onImageSize, this.onImageSizeError);
|
||||||
|
};
|
||||||
|
this.onImageError = () => {
|
||||||
|
console.log(`Image at url:${this.props.url} load failed.`);
|
||||||
|
this.setState({
|
||||||
|
loaded: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.state = {
|
||||||
|
loaded: true,
|
||||||
|
width: undefined,
|
||||||
|
height: undefined,
|
||||||
|
ratio: 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, Object.assign({}, this.props, { style: [
|
||||||
|
this.props.boxStyle,
|
||||||
|
{
|
||||||
|
alignSelf: this.props.alignSelf,
|
||||||
|
}
|
||||||
|
], onLayoutChange: this.onLayoutChange, onPress: this.props.onPress, width: 'auto' }),
|
||||||
|
this.renderPlaceholder(),
|
||||||
|
React.createElement(Image, { accessible: !!this.props.alt, accessibilityLabel: this.props.alt, source: { uri: this.props.url }, style: [
|
||||||
|
this.getSize(),
|
||||||
|
this.props.imgStyle
|
||||||
|
], onLoad: this.onImageLoad, onError: this.onImageError, onLayout: this.onImageSizeUpdate })));
|
||||||
|
}
|
||||||
|
applyFixSize(ratio) {
|
||||||
|
if (typeof this.props.width === 'number') {
|
||||||
|
this.setState({
|
||||||
|
width: this.props.width,
|
||||||
|
height: this.props.width * ratio,
|
||||||
|
ratio: ratio,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyStretchSize(width, height, ratio) {
|
||||||
|
if (this.props.containerWidth) {
|
||||||
|
let finalWidth = this.props.containerWidth;
|
||||||
|
let finalHeight = finalWidth * ratio;
|
||||||
|
console.log(`Image at url:${this.props.url} get size succeed. Final width: ${finalWidth}, final height: ${finalHeight}`);
|
||||||
|
this.setState({
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
ratio: ratio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
ratio: ratio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyAutoSize(width, ratio) {
|
||||||
|
let finalWidth = width;
|
||||||
|
if (finalWidth > this.props.containerWidth) {
|
||||||
|
finalWidth = this.props.containerWidth;
|
||||||
|
}
|
||||||
|
let finalHeight = finalWidth * ratio;
|
||||||
|
console.log(`Image at url:${this.props.url} get size succeed. Final width: ${finalWidth}, final height: ${finalHeight}`);
|
||||||
|
this.setState({
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
ratio: ratio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getSize() {
|
||||||
|
let finalWidth = this.state.width;
|
||||||
|
let finalHeight = this.state.height;
|
||||||
|
if (this.state.width && this.state.height) {
|
||||||
|
if (this.state.ratio <= 1) {
|
||||||
|
if (this.props.maxWidth && finalWidth > this.props.maxWidth) {
|
||||||
|
finalWidth = this.props.maxWidth;
|
||||||
|
}
|
||||||
|
finalHeight = finalWidth * this.state.ratio;
|
||||||
|
if (this.props.maxHeight && finalHeight > this.props.maxHeight) {
|
||||||
|
finalHeight = this.props.maxHeight;
|
||||||
|
finalWidth = this.state.ratio > 0 ? finalHeight / this.state.ratio : finalWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.props.maxHeight && finalHeight > this.props.maxHeight) {
|
||||||
|
finalHeight = this.props.maxHeight;
|
||||||
|
}
|
||||||
|
finalWidth = this.state.ratio > 0 ? finalHeight / this.state.ratio : finalWidth;
|
||||||
|
if (this.props.maxWidth && finalWidth > this.props.maxWidth) {
|
||||||
|
finalWidth = this.props.maxWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { PixelRatio, Platform, View, } from 'react-native';
|
||||||
|
export class SeparateLine extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { color, margin } = this.props;
|
||||||
|
const thickness = (Platform.OS === 'ios') ?
|
||||||
|
parseFloat((1 / PixelRatio.get()).toFixed(2)) :
|
||||||
|
1;
|
||||||
|
const style = {
|
||||||
|
height: thickness,
|
||||||
|
marginHorizontal: 0,
|
||||||
|
marginVertical: margin
|
||||||
|
};
|
||||||
|
return (React.createElement(View, Object.assign({}, this.props, { style: [
|
||||||
|
{
|
||||||
|
flex: 0,
|
||||||
|
backgroundColor: color,
|
||||||
|
},
|
||||||
|
style
|
||||||
|
] })));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, } from 'react-native';
|
||||||
|
import { FlexBox } from './FlexBox';
|
||||||
|
export class TextBlock extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, flexDirection: 'row', relativeWidth: false, width: this.props.width, vSpace: this.props.spacing, alignSelf: 'stretch', alignItems: 'stretch', alignContent: 'stretch', justifyContent: this.props.horizontalAlign, style: this.props.boxStyle },
|
||||||
|
React.createElement(Text, { style: [
|
||||||
|
this.props.textStyle,
|
||||||
|
], numberOfLines: this.props.numberOfLines }, this.props.children)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class Column extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { flexDirection: 'column', relativeWidth: true, alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: this.props.width, vIndex: this.props.vIndex, hIndex: this.props.hIndex, style: this.props.style, vSpace: this.props.spacing, onPress: this.props.onPress }, this.props.children));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class Row extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { flexDirection: 'row', relativeWidth: false, alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', wrap: this.props.wrap, justifyContent: 'space-between', width: this.props.width ? this.props.width : 'stretch', vIndex: this.props.vIndex, hIndex: this.props.hIndex, style: this.props.style, vSpace: this.props.spacing, onPress: this.props.onPress }, this.props.children));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
import { TextBlock } from '../Basic/TextBlock';
|
||||||
|
export class Button extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, flexDirection: 'row', relativeWidth: false, flex: 1, alignSelf: 'stretch', alignItems: 'center', alignContent: 'center', justifyContent: 'center', width: 'stretch', hSpace: 10, style: [
|
||||||
|
{
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: '#277BDF',
|
||||||
|
},
|
||||||
|
this.props.boxStyle
|
||||||
|
], onPress: this.props.onPress },
|
||||||
|
React.createElement(TextBlock, { vIndex: 0, hIndex: 0, width: 'stretch', horizontalAlign: 'center', textStyle: [
|
||||||
|
{
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
this.props.textStyle,
|
||||||
|
], numberOfLines: 1 }, this.props.title)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
import * as React from 'react';
|
||||||
|
import { DatePickerAndroid, DatePickerIOS, Platform, Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class DateInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderBtn = () => {
|
||||||
|
if (!this.state.showDatePicker) {
|
||||||
|
return (React.createElement(TouchableOpacity, { style: { flex: 1 }, onPress: this.showDatePicker },
|
||||||
|
React.createElement(View, { style: {
|
||||||
|
flex: 1,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 6,
|
||||||
|
marginVertical: 6,
|
||||||
|
height: 38,
|
||||||
|
} },
|
||||||
|
React.createElement(Text, null, this.props.value))));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.renderInlineDatePicker = () => {
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
if (this.state.showDatePicker) {
|
||||||
|
let date = Utils.extractDate(this.props.value);
|
||||||
|
console.log(date);
|
||||||
|
return (React.createElement(DatePickerIOS, { date: date, mode: 'date', onDateChange: this.onDateChange, style: { flex: 1 } }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onPickerClose = () => {
|
||||||
|
if (this.props.validateInput) {
|
||||||
|
if (this.props.validateInput(this.props.value)) {
|
||||||
|
console.log('DateInput: valid');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('DateInput: invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onDateChange = (date) => {
|
||||||
|
if (this.props.onValueChange) {
|
||||||
|
let timeString = Utils.getDateString(date);
|
||||||
|
console.log(timeString);
|
||||||
|
this.setState({
|
||||||
|
showDatePicker: false,
|
||||||
|
}, () => this.props.onValueChange(timeString));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.showDatePickerAndroid = this.showDatePickerAndroid.bind(this);
|
||||||
|
this.showDatePicker = this.showDatePicker.bind(this);
|
||||||
|
this.state = {
|
||||||
|
showDatePicker: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, flexDirection: 'row', alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: 'stretch' },
|
||||||
|
this.renderBtn(),
|
||||||
|
this.renderInlineDatePicker()));
|
||||||
|
}
|
||||||
|
showDatePickerAndroid() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
const today = new Date();
|
||||||
|
try {
|
||||||
|
const { action, year, month, day } = yield DatePickerAndroid.open({
|
||||||
|
date: today,
|
||||||
|
});
|
||||||
|
if (action === DatePickerAndroid.dateSetAction) {
|
||||||
|
let newDate = new Date(year, month, day);
|
||||||
|
this.onDateChange(newDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ({ code, message }) {
|
||||||
|
console.warn('Cannot open date picker', message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
showDatePicker() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.state.showDatePicker) {
|
||||||
|
this.setState({
|
||||||
|
showDatePicker: false
|
||||||
|
}, this.onPickerClose);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
showDatePicker: true
|
||||||
|
});
|
||||||
|
yield this.showDatePickerAndroid();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { TextInput } from 'react-native';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class InputBox extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, flexDirection: 'row', alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: 'stretch' },
|
||||||
|
React.createElement(TextInput, { style: [
|
||||||
|
{
|
||||||
|
flex: 1,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 6,
|
||||||
|
marginVertical: 6,
|
||||||
|
height: 38,
|
||||||
|
},
|
||||||
|
this.props.style
|
||||||
|
], multiline: this.props.multiline, keyboardType: this.props.keyboardType, blurOnSubmit: true, placeholder: this.props.placeholder, value: this.props.value, returnKeyType: this.props.returnKeyType, underlineColorAndroid: 'transparent', importantForAccessibility: 'no-hide-descendants', onChangeText: this.props.onValueChange, onBlur: this.props.onBlur })));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Platform } from 'react-native';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { InputBox } from './InputBox';
|
||||||
|
export class NumberInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onChangeText = (input) => {
|
||||||
|
if (this.props.onValueChange) {
|
||||||
|
if (Utils.isSymbol(input) || Utils.isNumber(input)) {
|
||||||
|
console.log('change text');
|
||||||
|
this.props.onValueChange(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onBlur = () => {
|
||||||
|
if (this.props.validateInput) {
|
||||||
|
if (this.props.validateInput(this.props.value)) {
|
||||||
|
console.log('NumberInput: valid');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('NumberInput: invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.props.onBlur) {
|
||||||
|
this.props.onBlur();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(InputBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, multiline: false, keyboardType: Platform.OS === 'ios' ? 'numbers-and-punctuation' : 'numeric', placeholder: this.props.placeholder, value: this.props.value, returnKeyType: 'done', onValueChange: this.onChangeText, onBlur: this.onBlur }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
import * as React from 'react';
|
||||||
|
import { DatePickerIOS, Platform, Text, TimePickerAndroid, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class TimeInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderBtn = () => {
|
||||||
|
if (!this.state.showTimePicker) {
|
||||||
|
return (React.createElement(TouchableOpacity, { style: { flex: 1 }, onPress: this.showDatePicker },
|
||||||
|
React.createElement(View, { style: [
|
||||||
|
{
|
||||||
|
flex: 1,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 6,
|
||||||
|
marginVertical: 6,
|
||||||
|
height: 38,
|
||||||
|
}
|
||||||
|
] },
|
||||||
|
React.createElement(Text, null, this.props.value))));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.showTimePickerIOS = () => {
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
if (this.state.showTimePicker) {
|
||||||
|
let time = Utils.extractTime(this.props.value);
|
||||||
|
console.log(time);
|
||||||
|
return (React.createElement(DatePickerIOS, { date: time, mode: 'time', onDateChange: this.onTimeChangeIOS, style: { flex: 1 } }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onPickerClose = () => {
|
||||||
|
if (this.props.validateInput) {
|
||||||
|
if (this.props.validateInput(this.props.value)) {
|
||||||
|
console.log('TimeInput: valid');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('TimeInput: invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onTimeChangeIOS = (date) => {
|
||||||
|
this.onTimeChange(date.getHours(), date.getMinutes());
|
||||||
|
};
|
||||||
|
this.onTimeChange = (hour, minute) => {
|
||||||
|
if (this.props.onValueChange) {
|
||||||
|
let timeString = Utils.composeTimeString(hour, minute);
|
||||||
|
console.log(timeString);
|
||||||
|
this.setState({
|
||||||
|
showTimePicker: false,
|
||||||
|
}, () => this.props.onValueChange(timeString));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.showTimePickerAndroid = this.showTimePickerAndroid.bind(this);
|
||||||
|
this.showDatePicker = this.showDatePicker.bind(this);
|
||||||
|
this.state = {
|
||||||
|
showTimePicker: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, flexDirection: 'row', alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: 'stretch' },
|
||||||
|
this.renderBtn(),
|
||||||
|
this.showTimePickerIOS()));
|
||||||
|
}
|
||||||
|
showTimePickerAndroid() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
const now = new Date();
|
||||||
|
try {
|
||||||
|
const { action, hour, minute } = yield TimePickerAndroid.open({
|
||||||
|
hour: now.getHours(),
|
||||||
|
minute: now.getMinutes(),
|
||||||
|
is24Hour: true
|
||||||
|
});
|
||||||
|
if (action === TimePickerAndroid.timeSetAction) {
|
||||||
|
this.onTimeChange(hour, minute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ({ code, message }) {
|
||||||
|
console.warn('Cannot open date picker', message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
showDatePicker() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.state.showTimePicker) {
|
||||||
|
this.setState({
|
||||||
|
showTimePicker: false
|
||||||
|
}, this.onPickerClose);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
showTimePicker: true
|
||||||
|
}, this.showTimePickerAndroid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ export class ActionContext {
|
||||||
formValidate: false,
|
formValidate: false,
|
||||||
target: target,
|
target: target,
|
||||||
};
|
};
|
||||||
let hookFuncs = this.getExcuteFuncs(action.type, externalHooks);
|
let hookFuncs = this.getExecuteFuncs(action.type, externalHooks);
|
||||||
args = hookFuncs.reduce((prev, current) => {
|
args = hookFuncs.reduce((prev, current) => {
|
||||||
return current(prev);
|
return current(prev);
|
||||||
}, args);
|
}, args);
|
||||||
|
@ -75,7 +75,7 @@ export class ActionContext {
|
||||||
}
|
}
|
||||||
return callback;
|
return callback;
|
||||||
}
|
}
|
||||||
getExcuteFuncs(actionType, externalHooks) {
|
getExecuteFuncs(actionType, externalHooks) {
|
||||||
let hookFuncs = [];
|
let hookFuncs = [];
|
||||||
if (this.hooks) {
|
if (this.hooks) {
|
||||||
let hookArrays = this.hooks[actionType];
|
let hookArrays = this.hooks[actionType];
|
|
@ -1,4 +1,4 @@
|
||||||
import { AbstractElement } from '../Base/AbstractElement';
|
import { AbstractElement } from './AbstractElement';
|
||||||
export var ActionType;
|
export var ActionType;
|
||||||
(function (ActionType) {
|
(function (ActionType) {
|
||||||
ActionType["OpenUrl"] = "Action.OpenUrl";
|
ActionType["OpenUrl"] = "Action.OpenUrl";
|
||||||
|
@ -27,6 +27,9 @@ export class ActionElement extends AbstractElement {
|
||||||
getData() {
|
getData() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
isAction() {
|
isAction() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Spacing } from '../../Shared/Enums';
|
import { Spacing } from '../../Shared/Enums';
|
||||||
import { Utils } from '../../Shared/Utils';
|
import { Utils } from '../../Shared/Utils';
|
||||||
import { AbstractElement } from '../Base/AbstractElement';
|
import { AbstractElement } from './AbstractElement';
|
||||||
export var ContentElementType;
|
export var ContentElementType;
|
||||||
(function (ContentElementType) {
|
(function (ContentElementType) {
|
||||||
ContentElementType["Column"] = "Column";
|
ContentElementType["Column"] = "Column";
|
||||||
|
@ -31,6 +31,11 @@ export class ContentElement extends AbstractElement {
|
||||||
getId() {
|
getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing
|
||||||
|
};
|
||||||
|
}
|
||||||
isContent() {
|
isContent() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { FormContext } from '../../Context/FormContext';
|
import { FormContext } from '../../Contexts/FormContext';
|
||||||
import { ContentElement } from '../Base/ContentElement';
|
|
||||||
import { ActionFactory } from '../Factories/ActionFactory';
|
import { ActionFactory } from '../Factories/ActionFactory';
|
||||||
|
import { ContentElement } from './ContentElement';
|
||||||
export var FormElementType;
|
export var FormElementType;
|
||||||
(function (FormElementType) {
|
(function (FormElementType) {
|
||||||
FormElementType["Column"] = "Column";
|
FormElementType["Column"] = "Column";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ContentElement } from '../Base/ContentElement';
|
import { ContentElement } from './ContentElement';
|
||||||
export var InputElementType;
|
export var InputElementType;
|
||||||
(function (InputElementType) {
|
(function (InputElementType) {
|
||||||
InputElementType["TextInput"] = "Input.Text";
|
InputElementType["TextInput"] = "Input.Text";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AbstractElement } from '../Base/AbstractElement';
|
import { AbstractElement } from './AbstractElement';
|
||||||
export var ValueElementType;
|
export var ValueElementType;
|
||||||
(function (ValueElementType) {
|
(function (ValueElementType) {
|
||||||
ValueElementType["Fact"] = "Fact";
|
ValueElementType["Fact"] = "Fact";
|
||||||
|
@ -18,4 +18,7 @@ export class ValueElement extends AbstractElement {
|
||||||
isValue() {
|
isValue() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,14 @@ export class ImageElement extends FormElement {
|
||||||
getChildren() {
|
getChildren() {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
horizontalAlignment: this.horizontalAlignment,
|
||||||
|
imgSize: this.size,
|
||||||
|
style: this.style,
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
setSize(size) {
|
setSize(size) {
|
||||||
this.size = Utils.getStringEnumValueOrDefault(ImageSize, size, ImageSize.Auto);
|
this.size = Utils.getStringEnumValueOrDefault(ImageSize, size, ImageSize.Auto);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,17 @@ export class TextBlockElement extends ContentElement {
|
||||||
this.wrap = json.wrap || false;
|
this.wrap = json.wrap || false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
color: this.color,
|
||||||
|
horizontalAlignment: this.horizontalAlignment,
|
||||||
|
isSubtle: this.isSubtle,
|
||||||
|
fontSize: this.size,
|
||||||
|
fontWeight: this.weight,
|
||||||
|
wrap: this.wrap,
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
getTypeName() {
|
getTypeName() {
|
||||||
return ContentElementType.TextBlock;
|
return ContentElementType.TextBlock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,12 @@ export class ColumnElement extends FormElement {
|
||||||
getChildren() {
|
getChildren() {
|
||||||
return this.items;
|
return this.items;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing,
|
||||||
|
columnWidth: this.width,
|
||||||
|
};
|
||||||
|
}
|
||||||
hasItems() {
|
hasItems() {
|
||||||
return this.items && this.items.length > 0;
|
return this.items && this.items.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@ export class ColumnSetElement extends FormElement {
|
||||||
getChildren() {
|
getChildren() {
|
||||||
return this.columns;
|
return this.columns;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
hasColumns() {
|
hasColumns() {
|
||||||
return this.columns && this.columns.length > 0;
|
return this.columns && this.columns.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,11 @@ export class ContainerElement extends FormElement {
|
||||||
getChildren() {
|
getChildren() {
|
||||||
return this.items;
|
return this.items;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
hasItems() {
|
hasItems() {
|
||||||
return this.items && this.items.length > 0;
|
return this.items && this.items.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,11 @@ export class FactSetElement extends ContentElement {
|
||||||
getRequiredProperties() {
|
getRequiredProperties() {
|
||||||
return ['facts'];
|
return ['facts'];
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
hasFacts() {
|
hasFacts() {
|
||||||
return this.facts && this.facts.length > 0;
|
return this.facts && this.facts.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,11 @@ export class ImageSetElement extends ContentElement {
|
||||||
getRequiredProperties() {
|
getRequiredProperties() {
|
||||||
return ['images'];
|
return ['images'];
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
hasImages() {
|
hasImages() {
|
||||||
return this.images && this.images.length > 0;
|
return this.images && this.images.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
import { ColumnWidth, FontSize, FontWeight, HorizontalAlignment, ImageSize, Spacing, TextColor } from '../Shared/Enums';
|
||||||
|
export var SizeModeCode;
|
||||||
|
(function (SizeModeCode) {
|
||||||
|
SizeModeCode[SizeModeCode["Auto"] = -1] = "Auto";
|
||||||
|
SizeModeCode[SizeModeCode["Stretch"] = -2] = "Stretch";
|
||||||
|
})(SizeModeCode || (SizeModeCode = {}));
|
||||||
|
export class HostConfigManager {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
static getInstance() {
|
||||||
|
if (HostConfigManager.sharedInstance === undefined) {
|
||||||
|
HostConfigManager.sharedInstance = new HostConfigManager();
|
||||||
|
}
|
||||||
|
return HostConfigManager.sharedInstance;
|
||||||
|
}
|
||||||
|
getDefaultStyle() {
|
||||||
|
return {
|
||||||
|
textAlign: this.getTextAlignment(HorizontalAlignment.Center),
|
||||||
|
alignSelf: this.getSelfAlignment(HorizontalAlignment.Center),
|
||||||
|
color: this.getColor(TextColor.Default),
|
||||||
|
flex: 1,
|
||||||
|
fontSize: this.getFontSize(FontSize.Default),
|
||||||
|
imgSize: this.getImgSize(ImageSize.Auto),
|
||||||
|
fontWeight: this.getFontWeight(FontWeight.Default),
|
||||||
|
marginTop: this.getSpacing(Spacing.Default),
|
||||||
|
columnWidth: this.getColumnWidth(ColumnWidth.Auto),
|
||||||
|
wrap: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
getColor(color) {
|
||||||
|
switch (color) {
|
||||||
|
case TextColor.Accent:
|
||||||
|
return '#2E89FC';
|
||||||
|
case TextColor.Attention:
|
||||||
|
return '#FF0000';
|
||||||
|
case TextColor.Dark:
|
||||||
|
return '#000000';
|
||||||
|
case TextColor.Default:
|
||||||
|
return '#333333';
|
||||||
|
case TextColor.Good:
|
||||||
|
return '#54a254';
|
||||||
|
case TextColor.Light:
|
||||||
|
return '#FFFFFF';
|
||||||
|
case TextColor.Warning:
|
||||||
|
return '#c3ab23';
|
||||||
|
default:
|
||||||
|
return this.getColor(TextColor.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getSubtleColor(color) {
|
||||||
|
switch (color) {
|
||||||
|
case TextColor.Accent:
|
||||||
|
return '#2E89FC88';
|
||||||
|
case TextColor.Attention:
|
||||||
|
return '#FF0000DD';
|
||||||
|
case TextColor.Dark:
|
||||||
|
return '#00000066';
|
||||||
|
case TextColor.Default:
|
||||||
|
return '#333333EE';
|
||||||
|
case TextColor.Good:
|
||||||
|
return '#54a254DD';
|
||||||
|
case TextColor.Light:
|
||||||
|
return '#00000033';
|
||||||
|
case TextColor.Warning:
|
||||||
|
return '#c3ab23dd';
|
||||||
|
default:
|
||||||
|
return this.getSubtleColor(TextColor.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getFontSize(size) {
|
||||||
|
switch (size) {
|
||||||
|
case FontSize.Default:
|
||||||
|
return 14;
|
||||||
|
case FontSize.ExtraLarge:
|
||||||
|
return 26;
|
||||||
|
case FontSize.Large:
|
||||||
|
return 21;
|
||||||
|
case FontSize.Medium:
|
||||||
|
return 17;
|
||||||
|
case FontSize.Small:
|
||||||
|
return 12;
|
||||||
|
default:
|
||||||
|
return this.getFontSize(FontSize.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getFontWeight(weight) {
|
||||||
|
switch (weight) {
|
||||||
|
case FontWeight.Bolder:
|
||||||
|
return '600';
|
||||||
|
case FontWeight.Default:
|
||||||
|
return '400';
|
||||||
|
case FontWeight.Lighter:
|
||||||
|
return '200';
|
||||||
|
default:
|
||||||
|
return this.getFontWeight(FontWeight.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getImgSize(size) {
|
||||||
|
switch (size) {
|
||||||
|
case ImageSize.Auto:
|
||||||
|
return 'auto';
|
||||||
|
case ImageSize.Large:
|
||||||
|
return 160;
|
||||||
|
case ImageSize.Medium:
|
||||||
|
return 80;
|
||||||
|
case ImageSize.Small:
|
||||||
|
return 40;
|
||||||
|
case ImageSize.Stretch:
|
||||||
|
return 'stretch';
|
||||||
|
default:
|
||||||
|
return this.getImgSize(ImageSize.Auto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getSpacing(spacing) {
|
||||||
|
switch (spacing) {
|
||||||
|
case Spacing.Default:
|
||||||
|
return 8;
|
||||||
|
case Spacing.ExtraLarge:
|
||||||
|
return 40;
|
||||||
|
case Spacing.Large:
|
||||||
|
return 30;
|
||||||
|
case Spacing.Medium:
|
||||||
|
return 20;
|
||||||
|
case Spacing.None:
|
||||||
|
return 0;
|
||||||
|
case Spacing.Padding:
|
||||||
|
return 10;
|
||||||
|
case Spacing.Small:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return this.getSpacing(Spacing.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getTextAlignment(align) {
|
||||||
|
switch (align) {
|
||||||
|
case HorizontalAlignment.Center:
|
||||||
|
return 'center';
|
||||||
|
case HorizontalAlignment.Left:
|
||||||
|
return 'left';
|
||||||
|
case HorizontalAlignment.Right:
|
||||||
|
return 'right';
|
||||||
|
default:
|
||||||
|
return this.getTextAlignment(HorizontalAlignment.Center);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getInboxTextAlignment(align) {
|
||||||
|
switch (align) {
|
||||||
|
case HorizontalAlignment.Center:
|
||||||
|
return 'center';
|
||||||
|
case HorizontalAlignment.Left:
|
||||||
|
return 'flex-start';
|
||||||
|
case HorizontalAlignment.Right:
|
||||||
|
return 'flex-end';
|
||||||
|
case ImageSize.Stretch:
|
||||||
|
return 'space-between';
|
||||||
|
default:
|
||||||
|
return this.getInboxTextAlignment(HorizontalAlignment.Left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getSelfAlignment(align) {
|
||||||
|
switch (align) {
|
||||||
|
case HorizontalAlignment.Center:
|
||||||
|
return 'center';
|
||||||
|
case HorizontalAlignment.Left:
|
||||||
|
return 'flex-start';
|
||||||
|
case HorizontalAlignment.Right:
|
||||||
|
return 'flex-end';
|
||||||
|
case ImageSize.Stretch:
|
||||||
|
return 'stretch';
|
||||||
|
default:
|
||||||
|
return this.getSelfAlignment(HorizontalAlignment.Center);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getColumnWidth(width) {
|
||||||
|
if (typeof width === 'number') {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
switch (width) {
|
||||||
|
case ColumnWidth.Auto:
|
||||||
|
return 'auto';
|
||||||
|
case ColumnWidth.Stretch:
|
||||||
|
return 'stretch';
|
||||||
|
default:
|
||||||
|
return this.getColumnWidth(ColumnWidth.Auto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getWrap(wrap) {
|
||||||
|
return wrap ? 'wrap' : 'nowrap';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { ImageSize } from '../Shared/Enums';
|
||||||
|
import { HostConfigManager } from './HostConfig';
|
||||||
|
export class StyleManager {
|
||||||
|
constructor() { }
|
||||||
|
static getInstance() {
|
||||||
|
if (StyleManager.sharedInstance === undefined) {
|
||||||
|
StyleManager.sharedInstance = new StyleManager();
|
||||||
|
}
|
||||||
|
return StyleManager.sharedInstance;
|
||||||
|
}
|
||||||
|
getStyle(element) {
|
||||||
|
let elementConfig = element.getStyleConfig();
|
||||||
|
let style = {
|
||||||
|
textAlign: HostConfigManager.getInstance().getTextAlignment(elementConfig.horizontalAlignment),
|
||||||
|
inboxTextAlign: HostConfigManager.getInstance().getInboxTextAlignment(elementConfig.horizontalAlignment),
|
||||||
|
alignSelf: HostConfigManager.getInstance().getSelfAlignment(elementConfig.horizontalAlignment),
|
||||||
|
color: this.getColor(elementConfig.color, elementConfig.isSubtle),
|
||||||
|
flex: 1,
|
||||||
|
fontSize: HostConfigManager.getInstance().getFontSize(elementConfig.fontSize),
|
||||||
|
imgSize: HostConfigManager.getInstance().getImgSize(elementConfig.imgSize),
|
||||||
|
fontWeight: HostConfigManager.getInstance().getFontWeight(elementConfig.fontWeight),
|
||||||
|
spacing: HostConfigManager.getInstance().getSpacing(elementConfig.spacing),
|
||||||
|
columnWidth: HostConfigManager.getInstance().getColumnWidth(elementConfig.columnWidth),
|
||||||
|
wrap: HostConfigManager.getInstance().getWrap(elementConfig.wrap),
|
||||||
|
};
|
||||||
|
if (elementConfig.imgSize === ImageSize.Stretch) {
|
||||||
|
style.alignSelf = HostConfigManager.getInstance().getSelfAlignment(ImageSize.Stretch);
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
getColor(color, isSubtle) {
|
||||||
|
if (isSubtle) {
|
||||||
|
return HostConfigManager.getInstance().getSubtleColor(color);
|
||||||
|
}
|
||||||
|
return HostConfigManager.getInstance().getColor(color);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,45 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { TouchableOpacity, } from 'react-native';
|
|
||||||
import { ActionContext } from '../../Context/ActionContext';
|
|
||||||
import { CardText } from '../Basic/CardText';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class OpenUrlActionView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onPress = () => {
|
|
||||||
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element);
|
|
||||||
if (callback) {
|
|
||||||
if (this.props.actionHooks) {
|
|
||||||
callback(...this.props.actionHooks);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (React.createElement(TouchableOpacity, { style: [
|
|
||||||
{
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingVertical: this.styleConfig.action.button.paddingVertical,
|
|
||||||
paddingHorizontal: this.styleConfig.action.button.paddingHorizontal,
|
|
||||||
borderRadius: this.styleConfig.action.button.borderRadius,
|
|
||||||
backgroundColor: this.styleConfig.action.button.backgroundColor,
|
|
||||||
},
|
|
||||||
StyleManager.getInstance().getActionButtonSpacingStyle(index)
|
|
||||||
], onPress: this.onPress },
|
|
||||||
React.createElement(CardText, { style: {
|
|
||||||
fontSize: this.styleConfig.action.button.fontSize,
|
|
||||||
color: this.styleConfig.action.button.textColor,
|
|
||||||
}, numberOfLines: 1 }, element.title)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { TouchableOpacity, } from 'react-native';
|
|
||||||
import { ActionContext } from '../../Context/ActionContext';
|
|
||||||
import { CardText } from '../Basic/CardText';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class ShowCardActionView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onPress = () => {
|
|
||||||
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element);
|
|
||||||
if (callback) {
|
|
||||||
if (this.props.actionHooks) {
|
|
||||||
callback(...this.props.actionHooks);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (React.createElement(TouchableOpacity, { style: [
|
|
||||||
{
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingVertical: this.styleConfig.action.button.paddingVertical,
|
|
||||||
paddingHorizontal: this.styleConfig.action.button.paddingHorizontal,
|
|
||||||
borderRadius: this.styleConfig.action.button.borderRadius,
|
|
||||||
backgroundColor: this.styleConfig.action.button.backgroundColor,
|
|
||||||
},
|
|
||||||
StyleManager.getInstance().getActionButtonSpacingStyle(index)
|
|
||||||
], onPress: this.onPress },
|
|
||||||
React.createElement(CardText, { style: {
|
|
||||||
fontSize: this.styleConfig.action.button.fontSize,
|
|
||||||
color: this.styleConfig.action.button.textColor,
|
|
||||||
}, numberOfLines: 1 }, element.title)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { TouchableOpacity, } from 'react-native';
|
|
||||||
import { ActionContext } from '../../Context/ActionContext';
|
|
||||||
import { CardText } from '../Basic/CardText';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class SubmitActionView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onPress = () => {
|
|
||||||
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element);
|
|
||||||
if (callback) {
|
|
||||||
if (this.props.actionHooks) {
|
|
||||||
callback(...this.props.actionHooks);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (React.createElement(TouchableOpacity, { style: [
|
|
||||||
{
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingVertical: this.styleConfig.action.button.paddingVertical,
|
|
||||||
paddingHorizontal: this.styleConfig.action.button.paddingHorizontal,
|
|
||||||
borderRadius: this.styleConfig.action.button.borderRadius,
|
|
||||||
backgroundColor: this.styleConfig.action.button.backgroundColor,
|
|
||||||
},
|
|
||||||
StyleManager.getInstance().getActionButtonSpacingStyle(index)
|
|
||||||
], onPress: this.onPress },
|
|
||||||
React.createElement(CardText, { style: {
|
|
||||||
fontSize: this.styleConfig.action.button.fontSize,
|
|
||||||
color: this.styleConfig.action.button.textColor,
|
|
||||||
}, numberOfLines: 1 }, element.title)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Text, } from 'react-native';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class CardText extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.fontFamily = StyleManager.getInstance().getFontFamily();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { style, children } = this.props;
|
|
||||||
return (React.createElement(Text, Object.assign({}, this.props, { style: [
|
|
||||||
{
|
|
||||||
fontFamily: this.fontFamily || undefined,
|
|
||||||
},
|
|
||||||
style
|
|
||||||
] }), children));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { ContentElementType } from '../../Schema/Base/ContentElement';
|
|
||||||
import { ImageView } from '../CardElements/ImageView';
|
|
||||||
import { TextBlockView } from '../CardElements/TextBlockView';
|
|
||||||
import { ColumnSetView } from '../Containers/ColumnSetView';
|
|
||||||
import { ColumnView } from '../Containers/ColumnView';
|
|
||||||
import { ContainerView } from '../Containers/ContainerView';
|
|
||||||
import { FactSetView } from '../Containers/FactSetView';
|
|
||||||
import { ImageSetView } from '../Containers/ImageSetView';
|
|
||||||
import { DateInputView } from '../Inputs/DateInputView';
|
|
||||||
import { NumberInputView } from '../Inputs/NumberInputView';
|
|
||||||
import { TextInputView } from '../Inputs/TextInputView';
|
|
||||||
import { TimeInputView } from '../Inputs/TimeInputView';
|
|
||||||
export class DecCardElementView extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
const { element, index, containerWidth } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch (element.type) {
|
|
||||||
case ContentElementType.TextBlock:
|
|
||||||
return (React.createElement(TextBlockView, { element: element, index: index }));
|
|
||||||
case ContentElementType.Image:
|
|
||||||
return (React.createElement(ImageView, { element: element, index: index }));
|
|
||||||
case ContentElementType.ImageSet:
|
|
||||||
return (React.createElement(ImageSetView, { element: element, index: index }));
|
|
||||||
case ContentElementType.Container:
|
|
||||||
return (React.createElement(ContainerView, { element: element, index: index }));
|
|
||||||
case ContentElementType.Column:
|
|
||||||
return (React.createElement(ColumnView, { element: element, containerWidth: containerWidth, index: index }));
|
|
||||||
case ContentElementType.ColumnSet:
|
|
||||||
return (React.createElement(ColumnSetView, { element: element, index: index }));
|
|
||||||
case ContentElementType.FactSet:
|
|
||||||
return (React.createElement(FactSetView, { element: element, index: index }));
|
|
||||||
case ContentElementType.TextInput:
|
|
||||||
return (React.createElement(TextInputView, { element: element, index: index }));
|
|
||||||
case ContentElementType.DateInput:
|
|
||||||
return (React.createElement(DateInputView, { element: element, index: index }));
|
|
||||||
case ContentElementType.TimeInput:
|
|
||||||
return (React.createElement(TimeInputView, { element: element, index: index }));
|
|
||||||
case ContentElementType.NumberInput:
|
|
||||||
return (React.createElement(NumberInputView, { element: element, index: index }));
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { TouchableOpacity, View, } from 'react-native';
|
|
||||||
import { ActionContext } from '../../Context/ActionContext';
|
|
||||||
import { SeparateLine } from '../Basic/SeparateLine';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class DecCardElementWrapper extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
this.onClick = this.onClick.bind(this);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
if (!this.props.element || !this.props.element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (this.props.element.isForm() && this.props.element.getAction() !== undefined) {
|
|
||||||
return this.renderActionView();
|
|
||||||
}
|
|
||||||
return this.renderNonActionView();
|
|
||||||
}
|
|
||||||
renderActionView() {
|
|
||||||
const isHorizontalLayout = StyleManager.getInstance().isHorizontalCardElement(this.props.element.type);
|
|
||||||
if (this.props.element.separator) {
|
|
||||||
return (React.createElement(TouchableOpacity, { style: this.props.style, onPress: this.onClick },
|
|
||||||
this.renderSeparator(this.props.element.spacing, isHorizontalLayout),
|
|
||||||
this.renderWrapper(this.props.element.spacing, 0, isHorizontalLayout, { flex: 1 })));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return this.renderTouchableWrapper(this.props.element.spacing, this.props.index, isHorizontalLayout, this.props.style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderNonActionView() {
|
|
||||||
const isHorizontalLayout = StyleManager.getInstance().isHorizontalCardElement(this.props.element.type);
|
|
||||||
if (this.props.element.separator) {
|
|
||||||
return (React.createElement(View, { style: this.props.style },
|
|
||||||
this.renderSeparator(this.props.element.spacing, isHorizontalLayout),
|
|
||||||
this.renderWrapper(this.props.element.spacing, 0, isHorizontalLayout, { flex: 1 })));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return this.renderWrapper(this.props.element.spacing, this.props.index, isHorizontalLayout, this.props.style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderTouchableWrapper(spacing, index, isHorizontalLayout, wrapperStyle) {
|
|
||||||
return (React.createElement(TouchableOpacity, { style: [
|
|
||||||
wrapperStyle,
|
|
||||||
StyleManager.getInstance().getCardElementSpacingStyle(spacing, index, isHorizontalLayout)
|
|
||||||
], onPress: this.onClick }, this.props.children));
|
|
||||||
}
|
|
||||||
renderWrapper(spacing, index, isHorizontalLayout, wrapperStyle) {
|
|
||||||
return (React.createElement(View, { style: [
|
|
||||||
wrapperStyle,
|
|
||||||
StyleManager.getInstance().getCardElementSpacingStyle(spacing, index, isHorizontalLayout)
|
|
||||||
] }, this.props.children));
|
|
||||||
}
|
|
||||||
renderSeparator(spacing, isHorizontalLayout) {
|
|
||||||
return (React.createElement(SeparateLine, { isHorizontal: isHorizontalLayout, margin: StyleManager.getInstance().getCardElementMargin(spacing), color: this.styleConfig.element.separateLineColor }));
|
|
||||||
}
|
|
||||||
onClick() {
|
|
||||||
let actionContext = ActionContext.getGlobalInstance();
|
|
||||||
let callback = actionContext.getActionEventHandler(this.props.element.getAction());
|
|
||||||
if (callback) {
|
|
||||||
const element = this.props.element;
|
|
||||||
if (element.isForm()) {
|
|
||||||
let action = element.getAction();
|
|
||||||
if (action) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { PixelRatio, Platform, View, } from 'react-native';
|
|
||||||
export class SeparateLine extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
const { color, isHorizontal, margin } = this.props;
|
|
||||||
const thickness = (Platform.OS === 'ios') ?
|
|
||||||
parseFloat((1 / PixelRatio.get()).toFixed(2)) :
|
|
||||||
1;
|
|
||||||
const style = isHorizontal ?
|
|
||||||
{
|
|
||||||
width: thickness,
|
|
||||||
marginLeft: margin,
|
|
||||||
marginRight: margin,
|
|
||||||
marginTop: 0,
|
|
||||||
marginBottom: 0,
|
|
||||||
} :
|
|
||||||
{
|
|
||||||
height: thickness,
|
|
||||||
marginLeft: 0,
|
|
||||||
marginRight: 0,
|
|
||||||
marginTop: margin,
|
|
||||||
marginBottom: margin,
|
|
||||||
};
|
|
||||||
return (React.createElement(View, Object.assign({}, this.props, { style: [
|
|
||||||
{
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: color,
|
|
||||||
},
|
|
||||||
style
|
|
||||||
] })));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Image, StyleSheet, Text, View, } from 'react-native';
|
|
||||||
import { FlexImageAlignment, HorizontalAlignment, ImageSize, ImageStyle, } from '../../Shared/Enums';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
const IMAGEMINSIZE = 18;
|
|
||||||
var ImageFit;
|
|
||||||
(function (ImageFit) {
|
|
||||||
ImageFit[ImageFit["FlexibleWidth"] = 0] = "FlexibleWidth";
|
|
||||||
ImageFit[ImageFit["FlexibleHeight"] = 1] = "FlexibleHeight";
|
|
||||||
})(ImageFit || (ImageFit = {}));
|
|
||||||
export class ImageView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onLayout = (event) => {
|
|
||||||
const { element } = this.props;
|
|
||||||
if (element.isFixedSize()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let width = event.nativeEvent.layout.width;
|
|
||||||
let height = event.nativeEvent.layout.height;
|
|
||||||
console.log('AdaptiveCard Image onLayout', width, height);
|
|
||||||
if (!this.fitStyle) {
|
|
||||||
this.fitStyle = width !== 0 && height === 0 ? 1 : 0;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
viewWidth: width,
|
|
||||||
viewHeight: height
|
|
||||||
});
|
|
||||||
};
|
|
||||||
this.onLoad = () => {
|
|
||||||
const { element } = this.props;
|
|
||||||
Image.getSize(element.url, (width, height) => {
|
|
||||||
console.log('AdaptiveCard Image getSize', width, height);
|
|
||||||
if (!this.isComponentUnmounted && width) {
|
|
||||||
this.setState({
|
|
||||||
imageAspectRatio: height / width
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, (error) => {
|
|
||||||
console.error('failed to get image size of commute url, error');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
this.onError = () => {
|
|
||||||
if (!this.isComponentUnmounted) {
|
|
||||||
this.setState({
|
|
||||||
imageLoadSuccess: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.getDimensionsForBestFit = () => {
|
|
||||||
if (this.state.imageAspectRatio) {
|
|
||||||
switch (this.fitStyle) {
|
|
||||||
case 1:
|
|
||||||
if (this.state.viewWidth) {
|
|
||||||
return {
|
|
||||||
height: Math.floor(this.state.viewWidth * this.state.imageAspectRatio),
|
|
||||||
width: this.state.viewWidth
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
if (this.state.viewHeight) {
|
|
||||||
let dimensions = {
|
|
||||||
width: Math.floor(this.state.viewHeight / this.state.imageAspectRatio),
|
|
||||||
height: this.state.viewHeight
|
|
||||||
};
|
|
||||||
if (this.state.viewWidth && dimensions.width > this.state.viewWidth) {
|
|
||||||
dimensions.width = this.state.viewWidth;
|
|
||||||
}
|
|
||||||
return dimensions;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (this.fitStyle !== undefined) {
|
|
||||||
return {
|
|
||||||
width: this.state.viewWidth || IMAGEMINSIZE,
|
|
||||||
height: this.state.viewHeight || IMAGEMINSIZE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
this.state = {
|
|
||||||
viewWidth: 0,
|
|
||||||
viewHeight: 0,
|
|
||||||
imageAspectRatio: 1,
|
|
||||||
imageLoadSuccess: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.isComponentUnmounted = true;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const dimensions = element.isFixedSize() ?
|
|
||||||
{
|
|
||||||
width: StyleManager.getInstance().getImageSize(element.size),
|
|
||||||
height: StyleManager.getInstance().getImageSize(element.size),
|
|
||||||
} :
|
|
||||||
this.getDimensionsForBestFit();
|
|
||||||
const borderRadius = element.style === ImageStyle.Person && dimensions ?
|
|
||||||
dimensions.width / 2 :
|
|
||||||
undefined;
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: StyleManager.getInstance().isHorizontalImageSet() ? undefined : { flex: 1 } },
|
|
||||||
React.createElement(View, { style: { flex: 1 }, onLayout: this.onLayout },
|
|
||||||
this.state.imageLoadSuccess ?
|
|
||||||
undefined :
|
|
||||||
this.renderPlaceholder(),
|
|
||||||
React.createElement(Image, { accessible: !!element.altText, accessibilityLabel: element.altText || undefined, style: {
|
|
||||||
overflow: 'hidden',
|
|
||||||
width: dimensions ? dimensions.width : undefined,
|
|
||||||
height: dimensions ? dimensions.height : undefined,
|
|
||||||
alignSelf: this.getImageAlignment(element.horizontalAlignment, element.size),
|
|
||||||
borderRadius: borderRadius
|
|
||||||
}, source: { uri: element.url }, onLoad: this.onLoad, onError: this.onError, resizeMode: 'cover', resizeMethod: 'auto' }))));
|
|
||||||
}
|
|
||||||
renderPlaceholder() {
|
|
||||||
return (React.createElement(View, { style: [
|
|
||||||
StyleSheet.absoluteFill,
|
|
||||||
{
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}
|
|
||||||
] },
|
|
||||||
React.createElement(Text, { style: {
|
|
||||||
fontSize: 32,
|
|
||||||
color: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
textAlign: 'center'
|
|
||||||
} }, '\uE601')));
|
|
||||||
}
|
|
||||||
getImageAlignment(alignment, imageSize) {
|
|
||||||
let imageAlignment;
|
|
||||||
if (imageSize === ImageSize.Stretch) {
|
|
||||||
imageAlignment = FlexImageAlignment.Stretch;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch (alignment) {
|
|
||||||
case HorizontalAlignment.Left:
|
|
||||||
imageAlignment = FlexImageAlignment.FlexStart;
|
|
||||||
break;
|
|
||||||
case HorizontalAlignment.Right:
|
|
||||||
imageAlignment = FlexImageAlignment.FlexEnd;
|
|
||||||
break;
|
|
||||||
case HorizontalAlignment.Center:
|
|
||||||
default:
|
|
||||||
imageAlignment = FlexImageAlignment.Center;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return imageAlignment;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View, } from 'react-native';
|
|
||||||
import { CardText } from '../Basic/CardText';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class TextBlockView extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: {
|
|
||||||
flex: 1,
|
|
||||||
} },
|
|
||||||
React.createElement(View, { style: {
|
|
||||||
flex: 1,
|
|
||||||
} },
|
|
||||||
React.createElement(CardText, { style: {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
fontSize: StyleManager.getInstance().getFontSize(element.size),
|
|
||||||
fontWeight: StyleManager.getInstance().getFontWeight(element.weight),
|
|
||||||
color: element.isSubtle ?
|
|
||||||
StyleManager.getInstance().getSubtleColor(element.color) :
|
|
||||||
StyleManager.getInstance().getColor(element.color),
|
|
||||||
textAlign: element.horizontalAlignment,
|
|
||||||
flexWrap: StyleManager.getInstance().getWrapStyle(element.wrap),
|
|
||||||
}, numberOfLines: element.maxLines || undefined }, element.text))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View, } from 'react-native';
|
|
||||||
import { DecCardElementView } from '../Basic/DecCardElementView';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
export class ColumnSetView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.renderColumn = (column, index) => {
|
|
||||||
return (React.createElement(DecCardElementView, { key: 'column' + index, index: index, containerWidth: this.state.viewWidth, element: column }));
|
|
||||||
};
|
|
||||||
this.onLayout = (event) => {
|
|
||||||
if (!this.isComponentUnmounted && !this.state.viewWidth && this.hasFixedWidthColumns) {
|
|
||||||
this.setState({
|
|
||||||
viewWidth: event.nativeEvent.layout.width,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.state = {
|
|
||||||
viewWidth: 0,
|
|
||||||
};
|
|
||||||
const { element } = props;
|
|
||||||
this.hasFixedWidthColumns = element.columns.some(item => item.isFixedWidth());
|
|
||||||
this.isEqualDistribution = element.columns.every(item => item.isFixedWidth());
|
|
||||||
}
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.isComponentUnmounted = true;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid() || !element.hasColumns()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: {
|
|
||||||
flex: 1,
|
|
||||||
} },
|
|
||||||
React.createElement(View, { style: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: this.isEqualDistribution ? 'space-between' : 'flex-start',
|
|
||||||
}, onLayout: this.onLayout }, element.columns.map(this.renderColumn))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View, } from 'react-native';
|
|
||||||
import { ColumnWidth } from '../../Shared/Enums';
|
|
||||||
import { DecCardElementView } from '../Basic/DecCardElementView';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
export class ColumnView extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid() || !element.hasItems()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: this.getViewStyle() },
|
|
||||||
React.createElement(View, { style: { flex: 1 } }, element.items.map((cardElement, index) => React.createElement(DecCardElementView, { key: 'containerItems' + index, index: index, element: cardElement })))));
|
|
||||||
}
|
|
||||||
getViewStyle() {
|
|
||||||
const { element, containerWidth } = this.props;
|
|
||||||
if (element.isFixedWidth()) {
|
|
||||||
if (element.width < 10) {
|
|
||||||
return {
|
|
||||||
flex: element.width,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (containerWidth) {
|
|
||||||
return {
|
|
||||||
width: containerWidth * (element.width / 100),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
flex: element.width === ColumnWidth.Auto ? 0 : 1,
|
|
||||||
alignSelf: element.width,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View, } from 'react-native';
|
|
||||||
import { ContainerStyle } from '../../Shared/Enums';
|
|
||||||
import { DecCardElementView } from '../Basic/DecCardElementView';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class ContainerView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid() || !element.hasItems()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: {
|
|
||||||
flex: 1,
|
|
||||||
} },
|
|
||||||
React.createElement(View, { style: [{
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
this.getContainerStyle(element.style)
|
|
||||||
] }, element.items.map((cardElement, index) => React.createElement(DecCardElementView, { key: 'containerItems' + index, index: index, element: cardElement })))));
|
|
||||||
}
|
|
||||||
getContainerStyle(style) {
|
|
||||||
let containerStyle;
|
|
||||||
switch (style) {
|
|
||||||
case ContainerStyle.Emphasis:
|
|
||||||
containerStyle = {
|
|
||||||
backgroundColor: this.styleConfig.container.backgroundColor,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case ContainerStyle.Default:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return containerStyle;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View } from 'react-native';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
import { FactView } from './FactView';
|
|
||||||
export class FactSetView extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid() || !element.hasFacts()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: {
|
|
||||||
flex: 1,
|
|
||||||
} },
|
|
||||||
React.createElement(View, { style: {
|
|
||||||
flex: 1,
|
|
||||||
} }, element.facts.map((fact, index) => React.createElement(FactView, { key: 'fact' + index, element: fact })))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { View } from 'react-native';
|
|
||||||
import { CardText } from '../Basic/CardText';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class FactView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(View, { style: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'flex-start'
|
|
||||||
} },
|
|
||||||
React.createElement(CardText, { style: {
|
|
||||||
color: this.styleConfig.fact.titleColor,
|
|
||||||
marginRight: this.styleConfig.fact.spacing,
|
|
||||||
} }, element.title),
|
|
||||||
React.createElement(CardText, { style: {
|
|
||||||
color: this.styleConfig.fact.valueColor,
|
|
||||||
marginLeft: this.styleConfig.fact.spacing,
|
|
||||||
} }, element.value)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { FlatList, View, } from 'react-native';
|
|
||||||
import { DecCardElementView } from '../Basic/DecCardElementView';
|
|
||||||
import { DecCardElementWrapper } from '../Basic/DecCardElementWrapper';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class ImageSetView extends React.PureComponent {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.renderImage = (image, index) => {
|
|
||||||
const { element } = this.props;
|
|
||||||
image.setSize(element.imageSize);
|
|
||||||
return (React.createElement(DecCardElementView, { key: 'image' + index, index: index, element: image }));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element, index } = this.props;
|
|
||||||
if (!element || !element.isValid() || !element.hasImages()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(DecCardElementWrapper, { element: element, index: index, style: {
|
|
||||||
flex: 1,
|
|
||||||
} }, StyleManager.getInstance().isHorizontalImageSet() ?
|
|
||||||
React.createElement(FlatList, { style: { flex: 1 }, horizontal: true, data: element.images, renderItem: ({ item, index }) => this.renderImage(item, index), keyExtractor: (item, index) => 'image' + index, showsHorizontalScrollIndicator: false })
|
|
||||||
:
|
|
||||||
React.createElement(View, { style: {
|
|
||||||
flex: 1,
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
} }, element.images.map(this.renderImage))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { ActionType } from '../../Schema/Base/ActionElement';
|
|
||||||
import { OpenUrlActionView } from '../Actions/OpenUrlAction';
|
|
||||||
import { ShowCardActionView } from '../Actions/ShowCardAction';
|
|
||||||
import { SubmitActionView } from '../Actions/SubmitAction';
|
|
||||||
export class ActionElementView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.getHooks = this.getHooks.bind(this);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
console.log('Render Action: ' + this.props.element.getActionType());
|
|
||||||
switch (this.props.element.getActionType()) {
|
|
||||||
case ActionType.OpenUrl:
|
|
||||||
return (React.createElement(OpenUrlActionView, { element: this.props.element, index: this.props.index, actionHooks: this.getHooks(ActionType.OpenUrl) }));
|
|
||||||
case ActionType.ShowCard:
|
|
||||||
return (React.createElement(ShowCardActionView, { element: this.props.element, index: this.props.index, actionHooks: this.getHooks(ActionType.ShowCard) }));
|
|
||||||
case ActionType.Submit:
|
|
||||||
return (React.createElement(SubmitActionView, { element: this.props.element, index: this.props.index, actionHooks: this.getHooks(ActionType.Submit) }));
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getHooks(actionType) {
|
|
||||||
if (this.props.actionContext) {
|
|
||||||
let result = this.props.actionContext.getHooks(actionType);
|
|
||||||
console.log('Attach hook:' + result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { ContentElementType } from '../../Schema/Base/ContentElement';
|
|
||||||
import { SeparateLine } from '../Basic/SeparateLine';
|
|
||||||
import { TextBlockView } from '../CardElements/TextBlockView';
|
|
||||||
import { FactSetView } from '../Containers/FactSetView';
|
|
||||||
import { ImageSetView } from '../Containers/ImageSetView';
|
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
import { FormElementView } from './FormElementView';
|
|
||||||
import { InputElementView } from './InputElementView';
|
|
||||||
export class ContentElementView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return [
|
|
||||||
this.renderSeperator(),
|
|
||||||
this.renderELement()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
renderELement() {
|
|
||||||
if (this.props.element) {
|
|
||||||
if (this.props.element.isForm()) {
|
|
||||||
return (React.createElement(FormElementView, { index: this.props.index, element: this.props.element }));
|
|
||||||
}
|
|
||||||
else if (this.props.element.isInput()) {
|
|
||||||
return (React.createElement(InputElementView, { index: this.props.index, element: this.props.element }));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch (this.props.element.type) {
|
|
||||||
case ContentElementType.TextBlock:
|
|
||||||
return (React.createElement(TextBlockView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case ContentElementType.ImageSet:
|
|
||||||
return (React.createElement(ImageSetView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case ContentElementType.FactSet:
|
|
||||||
return (React.createElement(FactSetView, { element: this.props.element, index: this.props.index }));
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
renderSeperator() {
|
|
||||||
if (this.props.element.separator) {
|
|
||||||
return (React.createElement(SeparateLine, { isHorizontal: StyleManager.getInstance().isHorizontalCardElement(this.props.element.type), margin: StyleManager.getInstance().getCardElementMargin(this.props.element.spacing), color: StyleManager.getInstance().getStyle().element.separateLineColor }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { ContentElementView } from './ContentElementView';
|
|
||||||
import { ValueElementView } from './ValueElementView';
|
|
||||||
export class ElementView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
if (this.props.element) {
|
|
||||||
if (this.props.element.isContent()) {
|
|
||||||
return (React.createElement(ContentElementView, { index: this.props.index, element: this.props.element }));
|
|
||||||
}
|
|
||||||
else if (this.props.element.isContent()) {
|
|
||||||
return (React.createElement(ValueElementView, { index: this.props.index, element: this.props.element }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { FormElementType } from 'Schema/Base/FormElement';
|
|
||||||
import { ImageView } from '../CardElements/ImageView';
|
|
||||||
import { CardView } from '../Cards/CardView';
|
|
||||||
import { ColumnSetView } from '../Containers/ColumnSetView';
|
|
||||||
import { ColumnView } from '../Containers/ColumnView';
|
|
||||||
import { ContainerView } from '../Containers/ContainerView';
|
|
||||||
export class FormElementView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
if (this.props.element) {
|
|
||||||
switch (this.props.element.type) {
|
|
||||||
case FormElementType.Image:
|
|
||||||
return (React.createElement(ImageView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case FormElementType.Container:
|
|
||||||
return (React.createElement(ContainerView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case FormElementType.Column:
|
|
||||||
return (React.createElement(ColumnView, { element: this.props.element, containerWidth: this.props.containerWidth, index: this.props.index }));
|
|
||||||
case FormElementType.ColumnSet:
|
|
||||||
return (React.createElement(ColumnSetView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case FormElementType.AdaptiveCard:
|
|
||||||
return (React.createElement(CardView, { element: this.props.element, index: this.props.index }));
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { InputElementType } from '../../Schema/Base/InputElement';
|
|
||||||
import { DateInputView } from '../Inputs/DateInputView';
|
|
||||||
import { NumberInputView } from '../Inputs/NumberInputView';
|
|
||||||
import { TextInputView } from '../Inputs/TextInputView';
|
|
||||||
export class InputElementView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
if (this.props.element) {
|
|
||||||
switch (this.props.element.type) {
|
|
||||||
case InputElementType.TextInput:
|
|
||||||
return (React.createElement(TextInputView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case InputElementType.NumberInput:
|
|
||||||
return (React.createElement(NumberInputView, { element: this.props.element, index: this.props.index }));
|
|
||||||
case InputElementType.DateInput:
|
|
||||||
return (React.createElement(DateInputView, { element: this.props.element, index: this.props.index }));
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { ValueElementType } from '../../Schema/Base/ValueElement';
|
|
||||||
import { FactView } from '../Containers/FactView';
|
|
||||||
export class ValueElementView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
if (this.props.element) {
|
|
||||||
switch (this.props.element.type) {
|
|
||||||
case ValueElementType.Fact:
|
|
||||||
return (React.createElement(FactView, { element: this.props.element, index: this.props.index }));
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import React from 'react';
|
|
||||||
import { DatePickerAndroid, DatePickerIOS, Platform, Text, TouchableOpacity, View } from 'react-native';
|
|
||||||
import { FormContext } from '../../Context/FormContext';
|
|
||||||
import { Utils } from '../../Shared/Utils';
|
|
||||||
export class DateInputView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.showDatePicker = this.showDatePicker.bind(this);
|
|
||||||
this.onDateChange = this.onDateChange.bind(this);
|
|
||||||
this.onPickerClose = this.onPickerClose.bind(this);
|
|
||||||
this.state = {
|
|
||||||
dateString: this.props.element.value,
|
|
||||||
showDatePicker: false,
|
|
||||||
};
|
|
||||||
this.updateStore();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(View, null,
|
|
||||||
React.createElement(TouchableOpacity, { onPress: this.showDatePicker },
|
|
||||||
React.createElement(View, { style: {
|
|
||||||
borderColor: 'gray',
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 4,
|
|
||||||
paddingHorizontal: 10,
|
|
||||||
paddingVertical: 6,
|
|
||||||
marginVertical: 6,
|
|
||||||
height: 38
|
|
||||||
} },
|
|
||||||
React.createElement(Text, null, this.state.dateString))),
|
|
||||||
this.renderInlineTimePicker()));
|
|
||||||
}
|
|
||||||
renderInlineTimePicker() {
|
|
||||||
if (Platform.OS === 'ios') {
|
|
||||||
if (this.state.showDatePicker) {
|
|
||||||
let date = Utils.extractDate(this.state.dateString);
|
|
||||||
console.log(date);
|
|
||||||
return (React.createElement(DatePickerIOS, { date: date, mode: 'date', onDateChange: this.onDateChange }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
showDatePickerAndroid() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (Platform.OS === 'android') {
|
|
||||||
const today = new Date();
|
|
||||||
try {
|
|
||||||
const { action, year, month, day } = yield DatePickerAndroid.open({
|
|
||||||
date: today,
|
|
||||||
});
|
|
||||||
if (action === DatePickerAndroid.dateSetAction) {
|
|
||||||
let newDate = new Date(year, month, day);
|
|
||||||
this.onDateChange(newDate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ({ code, message }) {
|
|
||||||
console.warn('Cannot open date picker', message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
showDatePicker() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (this.state.showDatePicker) {
|
|
||||||
this.setState({
|
|
||||||
showDatePicker: false
|
|
||||||
}, this.onPickerClose);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.setState({
|
|
||||||
showDatePicker: true
|
|
||||||
});
|
|
||||||
yield this.showDatePickerAndroid();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
onPickerClose() {
|
|
||||||
if (this.props.element.validateForm(this.state.dateString)) {
|
|
||||||
console.log('DateInput: valide');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('DateInput: invalide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onDateChange(date) {
|
|
||||||
let timeString = Utils.getDateString(date);
|
|
||||||
console.log(timeString);
|
|
||||||
this.setState({
|
|
||||||
dateString: timeString,
|
|
||||||
}, this.updateStore);
|
|
||||||
}
|
|
||||||
updateStore() {
|
|
||||||
FormContext.getInstance().updateField(this.props.element.id, this.state.dateString, this.props.element.validateForm(this.state.dateString));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Platform, TextInput, } from 'react-native';
|
|
||||||
import { FormContext } from '../../Context/FormContext';
|
|
||||||
import { Utils } from '../../Shared/Utils';
|
|
||||||
export class NumberInputView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onChangeText = this.onChangeText.bind(this);
|
|
||||||
this.onBlur = this.onBlur.bind(this);
|
|
||||||
let defaultValue = this.props.element.value;
|
|
||||||
if (defaultValue === undefined) {
|
|
||||||
defaultValue = '';
|
|
||||||
}
|
|
||||||
if (Utils.isNumber(this.props.element.value.toString())) {
|
|
||||||
this.state = {
|
|
||||||
value: this.props.element.value.toString(),
|
|
||||||
};
|
|
||||||
this.updateStore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(TextInput, { style: {
|
|
||||||
borderColor: 'gray',
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 4,
|
|
||||||
paddingHorizontal: 10,
|
|
||||||
paddingVertical: 6,
|
|
||||||
marginVertical: 6,
|
|
||||||
height: 38
|
|
||||||
}, multiline: false, keyboardType: Platform.OS === 'ios' ? 'numbers-and-punctuation' : 'numeric', blurOnSubmit: true, placeholder: element.placeholder, value: this.state.value, returnKeyType: 'done', underlineColorAndroid: 'transparent', importantForAccessibility: 'no-hide-descendants', onChangeText: this.onChangeText, onBlur: this.onBlur }));
|
|
||||||
}
|
|
||||||
onChangeText(input) {
|
|
||||||
if (Utils.isSymbol(input) || Utils.isNumber(input)) {
|
|
||||||
console.log('change text');
|
|
||||||
this.setState({
|
|
||||||
value: input
|
|
||||||
}, this.updateStore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onBlur() {
|
|
||||||
if (this.props.element.validateForm(this.state.value)) {
|
|
||||||
console.log('NumberInput: valide');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('NumberInput: invalide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateStore() {
|
|
||||||
FormContext.getInstance().updateField(this.props.element.id, this.state.value, this.props.element.validateForm(this.state.value));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { TextInput, } from 'react-native';
|
|
||||||
import { FormContext } from '../../Context/FormContext';
|
|
||||||
export class TextInputView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onChangeText = this.onChangeText.bind(this);
|
|
||||||
let defaultValue = this.props.element.value;
|
|
||||||
if (defaultValue === undefined) {
|
|
||||||
defaultValue = '';
|
|
||||||
}
|
|
||||||
this.state = {
|
|
||||||
value: defaultValue,
|
|
||||||
};
|
|
||||||
this.updateStore();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(TextInput, { style: {
|
|
||||||
borderColor: 'gray',
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 4,
|
|
||||||
fontSize: 16,
|
|
||||||
paddingHorizontal: 10,
|
|
||||||
paddingVertical: 6,
|
|
||||||
marginVertical: 6,
|
|
||||||
height: element.isMultiline ? 116 : 38
|
|
||||||
}, multiline: element.isMultiline, blurOnSubmit: true, placeholder: element.placeholder, value: this.state.value, returnKeyType: 'done', underlineColorAndroid: 'transparent', importantForAccessibility: 'no-hide-descendants', onChangeText: this.onChangeText }));
|
|
||||||
}
|
|
||||||
onChangeText(input) {
|
|
||||||
this.setState({
|
|
||||||
value: input
|
|
||||||
}, this.updateStore);
|
|
||||||
}
|
|
||||||
updateStore() {
|
|
||||||
FormContext.getInstance().updateField(this.props.element.id, this.state.value, this.props.element.validateForm(this.state.value));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import React from 'react';
|
|
||||||
import { DatePickerIOS, Platform, Text, TimePickerAndroid, TouchableOpacity, View } from 'react-native';
|
|
||||||
import { FormContext } from '../../Context/FormContext';
|
|
||||||
import { Utils } from '../../Shared/Utils';
|
|
||||||
export class TimeInputView extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.showDatePicker = this.showDatePicker.bind(this);
|
|
||||||
this.onTimeChangeIOS = this.onTimeChangeIOS.bind(this);
|
|
||||||
this.onTimeChange = this.onTimeChange.bind(this);
|
|
||||||
this.onPickerClose = this.onPickerClose.bind(this);
|
|
||||||
this.state = {
|
|
||||||
timeString: this.props.element.value,
|
|
||||||
showTimePicker: false,
|
|
||||||
};
|
|
||||||
this.updateStore();
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { element } = this.props;
|
|
||||||
if (!element || !element.isValid()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (React.createElement(View, null,
|
|
||||||
React.createElement(TouchableOpacity, { onPress: this.showDatePicker },
|
|
||||||
React.createElement(View, { style: {
|
|
||||||
borderColor: 'gray',
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 4,
|
|
||||||
paddingHorizontal: 10,
|
|
||||||
paddingVertical: 6,
|
|
||||||
marginVertical: 6,
|
|
||||||
height: 38
|
|
||||||
} },
|
|
||||||
React.createElement(Text, null, this.state.timeString))),
|
|
||||||
this.showTimePickerIOS()));
|
|
||||||
}
|
|
||||||
showTimePickerIOS() {
|
|
||||||
if (Platform.OS === 'ios') {
|
|
||||||
if (this.state.showTimePicker) {
|
|
||||||
let time = Utils.extractTime(this.state.timeString);
|
|
||||||
console.log(time);
|
|
||||||
return (React.createElement(DatePickerIOS, { date: time, mode: 'time', onDateChange: this.onTimeChangeIOS }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
showTimePickerAndroid() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (Platform.OS === 'android') {
|
|
||||||
const now = new Date();
|
|
||||||
try {
|
|
||||||
const { action, hour, minute } = yield TimePickerAndroid.open({
|
|
||||||
hour: now.getHours(),
|
|
||||||
minute: now.getMinutes(),
|
|
||||||
is24Hour: true
|
|
||||||
});
|
|
||||||
if (action === TimePickerAndroid.timeSetAction) {
|
|
||||||
this.onTimeChange(hour, minute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ({ code, message }) {
|
|
||||||
console.warn('Cannot open date picker', message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
showDatePicker() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (this.state.showTimePicker) {
|
|
||||||
this.setState({
|
|
||||||
showTimePicker: false
|
|
||||||
}, this.onPickerClose);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.setState({
|
|
||||||
showTimePicker: true
|
|
||||||
}, this.showTimePickerAndroid);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
onPickerClose() {
|
|
||||||
if (this.props.element.validateForm(this.state.timeString)) {
|
|
||||||
console.log('TimeInput: valide');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('TimeInput: invalide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onTimeChangeIOS(date) {
|
|
||||||
this.onTimeChange(date.getHours(), date.getMinutes());
|
|
||||||
}
|
|
||||||
onTimeChange(hour, minute) {
|
|
||||||
let timeString = Utils.composeTimeString(hour, minute);
|
|
||||||
console.log(timeString);
|
|
||||||
this.setState({
|
|
||||||
timeString: timeString,
|
|
||||||
showTimePicker: false,
|
|
||||||
}, this.updateStore);
|
|
||||||
}
|
|
||||||
updateStore() {
|
|
||||||
FormContext.getInstance().updateField(this.props.element.id, this.state.timeString, this.props.element.validateForm(this.state.timeString));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
{
|
|
||||||
"card": {
|
|
||||||
"backgroundColor": "#FFF",
|
|
||||||
"borderWidth": 1,
|
|
||||||
"borderColor": "#EEE",
|
|
||||||
"borderRadius": 4,
|
|
||||||
"padding": 20,
|
|
||||||
"spacing": 10
|
|
||||||
},
|
|
||||||
"element": {
|
|
||||||
"separateLineColor": "#EEE",
|
|
||||||
"spacing": {
|
|
||||||
"none": 0,
|
|
||||||
"small": 2,
|
|
||||||
"default": 6,
|
|
||||||
"medium": 16,
|
|
||||||
"large": 24,
|
|
||||||
"extraLarge": 34,
|
|
||||||
"padding": 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"textBlock": {
|
|
||||||
"fontFamily": {
|
|
||||||
"ios": "",
|
|
||||||
"android": ""
|
|
||||||
},
|
|
||||||
"fontSize": {
|
|
||||||
"small": 12,
|
|
||||||
"default": 13,
|
|
||||||
"medium": 16,
|
|
||||||
"large": 18,
|
|
||||||
"extraLarge": 20
|
|
||||||
},
|
|
||||||
"fontWeight": {
|
|
||||||
"lighter": "100",
|
|
||||||
"default": "normal",
|
|
||||||
"bolder": "bold"
|
|
||||||
},
|
|
||||||
"textColor": {
|
|
||||||
"default": "#2B2C33",
|
|
||||||
"dark": "#000",
|
|
||||||
"light": "#FFF",
|
|
||||||
"accent": "#1686D9",
|
|
||||||
"good": "#4CAF50",
|
|
||||||
"warning": "#F0C01E",
|
|
||||||
"attention": "#F44336"
|
|
||||||
},
|
|
||||||
"subtleTextColor": {
|
|
||||||
"default": "#8A8D91",
|
|
||||||
"dark": "#000",
|
|
||||||
"light": "#FFF",
|
|
||||||
"accent": "rgba(22, 134, 217, 0.5)",
|
|
||||||
"good": "rgba(76, 175, 80, 0.8)",
|
|
||||||
"warning": "rgba(240, 192, 30, 0.8)",
|
|
||||||
"attention": "rgba(244, 67, 54, 0.8)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"imageSet": {
|
|
||||||
"direction": "row"
|
|
||||||
},
|
|
||||||
"imageSize": {
|
|
||||||
"small": 25,
|
|
||||||
"medium": 50,
|
|
||||||
"large": 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"container": {
|
|
||||||
"backgroundColor": "#F5F5F5"
|
|
||||||
},
|
|
||||||
"fact": {
|
|
||||||
"titleColor": "#8A8D91",
|
|
||||||
"valueColor": "#000",
|
|
||||||
"spacing": 5
|
|
||||||
},
|
|
||||||
"action": {
|
|
||||||
"actionSet": {
|
|
||||||
"direction": "row",
|
|
||||||
"spacing": 10
|
|
||||||
},
|
|
||||||
"button": {
|
|
||||||
"borderRadius": 4,
|
|
||||||
"backgroundColor": "#277BDF",
|
|
||||||
"spacing": 10,
|
|
||||||
"paddingVertical": 10,
|
|
||||||
"paddingHorizontal": 10,
|
|
||||||
"textColor": "#FFF",
|
|
||||||
"fontSize": 13
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
import merge from 'lodash/merge';
|
|
||||||
import { Platform, } from 'react-native';
|
|
||||||
import { ContentElementType } from '../../Schema/Base/ContentElement';
|
|
||||||
import { FlexDirection, FlexWrap, FontSize, FontWeight, Spacing, TextColor, } from '../../Shared/Enums';
|
|
||||||
import { Utils } from '../../Shared/Utils';
|
|
||||||
const defaultStyle = require('./DefaultStyle.json');
|
|
||||||
export class StyleManager {
|
|
||||||
constructor(style = {}) {
|
|
||||||
this.style = style;
|
|
||||||
}
|
|
||||||
static getInstance() {
|
|
||||||
if (StyleManager.sharedInstance === undefined) {
|
|
||||||
StyleManager.sharedInstance = new StyleManager(defaultStyle);
|
|
||||||
}
|
|
||||||
return StyleManager.sharedInstance;
|
|
||||||
}
|
|
||||||
addStyle(overrideStyle) {
|
|
||||||
return merge(this.style, overrideStyle);
|
|
||||||
}
|
|
||||||
getStyle() {
|
|
||||||
return this.style;
|
|
||||||
}
|
|
||||||
getFontFamily() {
|
|
||||||
return Platform.OS === 'ios' ?
|
|
||||||
this.style.textBlock.fontFamily.ios :
|
|
||||||
this.style.textBlock.fontFamily.android;
|
|
||||||
}
|
|
||||||
getImageSetFlexDirectionValue() {
|
|
||||||
return this.getFlexDirectionValue(this.style.image.imageSet.direction);
|
|
||||||
}
|
|
||||||
getActionSetFlexDirectionValue() {
|
|
||||||
return this.getFlexDirectionValue(this.style.action.actionSet.direction);
|
|
||||||
}
|
|
||||||
isHorizontalImageSet() {
|
|
||||||
return this.isHorizontalSet(this.style.image.imageSet.direction);
|
|
||||||
}
|
|
||||||
isHorizontalActionSet() {
|
|
||||||
return this.isHorizontalSet(this.style.action.actionSet.direction);
|
|
||||||
}
|
|
||||||
getImageSize(size) {
|
|
||||||
return this.style.image.imageSize[size] || this.style.image.imageSize.medium;
|
|
||||||
}
|
|
||||||
getFontSize(size) {
|
|
||||||
return this.style.textBlock.fontSize[size] || this.style.textBlock.fontSize[FontSize.Default];
|
|
||||||
}
|
|
||||||
getFontWeight(weight) {
|
|
||||||
return (this.style.textBlock.fontWeight[weight] || this.style.textBlock.fontWeight[FontWeight.Default]);
|
|
||||||
}
|
|
||||||
getColor(colorName) {
|
|
||||||
return this.style.textBlock.textColor[colorName] || this.style.textBlock.textColor[TextColor.Default];
|
|
||||||
}
|
|
||||||
getSubtleColor(colorName) {
|
|
||||||
return this.style.textBlock.subtleTextColor[colorName] || this.style.textBlock.subtleTextColor[TextColor.Default];
|
|
||||||
}
|
|
||||||
getWrapStyle(wrap) {
|
|
||||||
return (wrap ? FlexWrap.Wrap : FlexWrap.NoWrap);
|
|
||||||
}
|
|
||||||
isHorizontalCardElement(type) {
|
|
||||||
return type === ContentElementType.Column ||
|
|
||||||
(type === ContentElementType.Image && this.isHorizontalImageSet());
|
|
||||||
}
|
|
||||||
getCardElementMargin(spacing) {
|
|
||||||
let margin = 0;
|
|
||||||
if (spacing.toLowerCase() !== Spacing.Padding.toLowerCase()) {
|
|
||||||
margin = Utils.isValidValue(this.style.element.spacing[spacing]) ?
|
|
||||||
this.style.element.spacing[spacing] :
|
|
||||||
this.style.element.spacing[Spacing.Default];
|
|
||||||
}
|
|
||||||
return margin;
|
|
||||||
}
|
|
||||||
getCardElementSpacingStyle(spacing, index, isHorizontalLayout) {
|
|
||||||
if (spacing === Spacing.Padding) {
|
|
||||||
return {
|
|
||||||
padding: this.style.element.spacing.padding
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let margin = 0;
|
|
||||||
if (index > 0) {
|
|
||||||
margin = this.getCardElementMargin(spacing);
|
|
||||||
}
|
|
||||||
if (isHorizontalLayout) {
|
|
||||||
return {
|
|
||||||
marginLeft: margin
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
marginTop: margin
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getActionButtonSpacingStyle(index) {
|
|
||||||
if (index > 0) {
|
|
||||||
if (this.isHorizontalActionSet()) {
|
|
||||||
return {
|
|
||||||
marginLeft: this.style.action.button.spacing,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
marginTop: this.style.action.button.spacing,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getFlexDirectionValue(direction) {
|
|
||||||
let directionStyle;
|
|
||||||
switch (direction.toLowerCase()) {
|
|
||||||
case FlexDirection.Row:
|
|
||||||
default:
|
|
||||||
directionStyle = FlexDirection.Row;
|
|
||||||
break;
|
|
||||||
case FlexDirection.Column:
|
|
||||||
directionStyle = FlexDirection.Column;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return directionStyle;
|
|
||||||
}
|
|
||||||
isHorizontalSet(direction) {
|
|
||||||
if (direction.toLowerCase() === FlexDirection.Column.toLowerCase()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Button } from '../../Components/Inputs/Button';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
|
export class OpenUrlActionView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onPress = () => {
|
||||||
|
console.log('OpenUrlAction pressed');
|
||||||
|
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element);
|
||||||
|
if (callback) {
|
||||||
|
if (this.props.actionHooks) {
|
||||||
|
callback(...this.props.actionHooks);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Button, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, title: this.props.element.title, onPress: this.onPress }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Button } from '../../Components/Inputs/Button';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
|
export class ShowCardActionView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onPress = () => {
|
||||||
|
console.log('ShowCardAction pressed');
|
||||||
|
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element);
|
||||||
|
if (callback) {
|
||||||
|
if (this.props.actionHooks) {
|
||||||
|
callback(...this.props.actionHooks);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Button, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, title: this.props.element.title, onPress: this.onPress }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Button } from '../../Components/Inputs/Button';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
|
export class SubmitActionView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onPress = () => {
|
||||||
|
console.log('SubmitAction pressed');
|
||||||
|
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element);
|
||||||
|
if (callback) {
|
||||||
|
if (this.props.actionHooks) {
|
||||||
|
callback(...this.props.actionHooks);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Button, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, title: this.props.element.title, onPress: this.onPress }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ImageBlock } from '../../Components/Basic/ImageBlock';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
|
import { HostConfigManager } from '../../Styles/HostConfig';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
export class ImageView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.getBorderRadius = () => {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid() && element.style === 'person') {
|
||||||
|
return {
|
||||||
|
borderRadius: this.state.width / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.onImageSize = (width, height) => {
|
||||||
|
this.setState({
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
}, () => {
|
||||||
|
console.log(`ImageView onImageSize width: ${width} height: ${height}`);
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
if (this.props.onImageSize) {
|
||||||
|
this.props.onImageSize(width, height, element.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.onPress = () => {
|
||||||
|
console.log('ImageView pressed');
|
||||||
|
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element.selectAction);
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
if (this.props.size) {
|
||||||
|
this.styleConfig.imgSize = HostConfigManager.getInstance().getImgSize(this.props.size);
|
||||||
|
}
|
||||||
|
this.state = {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(ImageBlock, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, url: element.url, alt: element.altText, flexDirection: 'row', alignSelf: this.styleConfig.alignSelf, alignItems: this.styleConfig.alignSelf, alignContent: 'center', justifyContent: 'center', width: this.styleConfig.imgSize, vSpace: this.styleConfig.spacing || this.props.vSpace, hSpace: this.props.hSpace, containerWidth: this.props.containerWidth, containerHeight: this.props.containerHeight, maxWidth: this.props.maxWidth, maxHeight: this.props.maxHeight, imgStyle: this.getBorderRadius(), onPress: element.selectAction ? this.onPress : undefined, onImageSize: this.onImageSize }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { TextBlock } from '../../Components/Basic/TextBlock';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
export class TextBlockView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(TextBlock, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, width: 'stretch', boxStyle: [
|
||||||
|
{
|
||||||
|
backgroundColor: 'transparent'
|
||||||
|
}
|
||||||
|
], textStyle: [
|
||||||
|
{
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
fontSize: this.styleConfig.fontSize,
|
||||||
|
fontWeight: this.styleConfig.fontWeight,
|
||||||
|
color: this.styleConfig.color,
|
||||||
|
textAlign: this.styleConfig.textAlign,
|
||||||
|
flexWrap: this.styleConfig.wrap,
|
||||||
|
}
|
||||||
|
], horizontalAlign: this.styleConfig.inboxTextAlign, spacing: this.styleConfig.spacing, numberOfLines: element.maxLines }, element.text));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, } from 'react-native';
|
import { View, } from 'react-native';
|
||||||
import { ActionContext } from '../../Context/ActionContext';
|
import { ImageBackground } from '../../Components/Basic/ImageBackground';
|
||||||
|
import { Column } from '../../Components/Containers/Column';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
import { ActionType } from '../../Schema/Base/ActionElement';
|
import { ActionType } from '../../Schema/Base/ActionElement';
|
||||||
import { DecCardElementView } from '../Basic/DecCardElementView';
|
import { ActionFactory } from '../Factories/ActionFactory';
|
||||||
import { ImageBackground } from '../Basic/ImageBackground';
|
import { ContentFactory } from '../Factories/ContentFactory';
|
||||||
import { ActionElementView } from '../Factories/ActionElementView';
|
export class AdaptiveCardView extends React.Component {
|
||||||
import { StyleManager } from '../Styles/StyleManager';
|
|
||||||
export class CardView extends React.Component {
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.showSubCard = (args) => {
|
this.showSubCard = (args) => {
|
||||||
|
@ -32,7 +33,6 @@ export class CardView extends React.Component {
|
||||||
name: 'showSubCard',
|
name: 'showSubCard',
|
||||||
actionType: ActionType.ShowCard
|
actionType: ActionType.ShowCard
|
||||||
});
|
});
|
||||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
if (!this.props.element.isValid()) {
|
if (!this.props.element.isValid()) {
|
||||||
|
@ -40,24 +40,27 @@ export class CardView extends React.Component {
|
||||||
}
|
}
|
||||||
const cardStyle = Object.assign({
|
const cardStyle = Object.assign({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: this.styleConfig.card.backgroundColor,
|
backgroundColor: 'white',
|
||||||
borderWidth: this.styleConfig.card.borderWidth,
|
borderWidth: 1,
|
||||||
borderColor: this.styleConfig.card.borderColor,
|
borderColor: '#777777',
|
||||||
borderRadius: this.styleConfig.card.borderRadius,
|
borderRadius: 4,
|
||||||
}, this.props.style);
|
}, this.props.style);
|
||||||
if (this.props.element.backgroundImage) {
|
if (this.props.element.backgroundImage) {
|
||||||
return (React.createElement(ImageBackground, { containerStyle: cardStyle, imageStyle: {
|
return (React.createElement(ImageBackground, { containerStyle: cardStyle, imageStyle: {
|
||||||
borderRadius: this.styleConfig.card.borderRadius,
|
borderRadius: 4,
|
||||||
}, source: { uri: this.props.element.backgroundImage } },
|
}, source: { uri: this.props.element.backgroundImage } },
|
||||||
React.createElement(View, { style: { flex: 1, padding: this.styleConfig.card.padding } },
|
React.createElement(View, { style: { flex: 1, padding: 10 } },
|
||||||
this.renderBody(),
|
this.renderBody(),
|
||||||
this.renderActions(),
|
this.renderActions(),
|
||||||
this.renderSubCard())));
|
this.renderSubCard())));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (React.createElement(View, { style: [cardStyle, {
|
return (React.createElement(View, { style: [
|
||||||
padding: this.styleConfig.card.padding,
|
cardStyle,
|
||||||
}] },
|
{
|
||||||
|
padding: 20,
|
||||||
|
}
|
||||||
|
] },
|
||||||
this.renderBody(),
|
this.renderBody(),
|
||||||
this.renderActions(),
|
this.renderActions(),
|
||||||
this.renderSubCard()));
|
this.renderSubCard()));
|
||||||
|
@ -67,23 +70,18 @@ export class CardView extends React.Component {
|
||||||
if (!this.props.element.hasBody()) {
|
if (!this.props.element.hasBody()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (React.createElement(View, { style: { flex: 1 } }, this.props.element.body.map((cardElement, index) => React.createElement(DecCardElementView, { key: 'body' + index, index: index, element: cardElement }))));
|
return (React.createElement(Column, { vIndex: 0, hIndex: 0, width: 'stretch' }, this.props.element.body.map((contentElement, index) => ContentFactory.createView(contentElement, index))));
|
||||||
}
|
}
|
||||||
renderActions() {
|
renderActions() {
|
||||||
if (!this.props.element.hasActions()) {
|
if (!this.props.element.hasActions()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (React.createElement(View, { style: {
|
return (React.createElement(Row, { vIndex: 1, hIndex: 0, spacing: 10 }, this.props.element.actions.map((action, index) => ActionFactory.createAction(action, index, this.actionContext))));
|
||||||
flex: 1,
|
|
||||||
flexDirection: StyleManager.getInstance().getActionSetFlexDirectionValue(),
|
|
||||||
alignItems: 'stretch',
|
|
||||||
marginTop: this.styleConfig.action.actionSet.spacing,
|
|
||||||
} }, this.props.element.actions.map((action, index) => React.createElement(ActionElementView, { key: index, element: action, index: index, actionContext: this.actionContext }))));
|
|
||||||
}
|
}
|
||||||
renderSubCard() {
|
renderSubCard() {
|
||||||
if (this.state.subCard) {
|
if (this.state.subCard) {
|
||||||
return (React.createElement(CardView, { element: this.state.subCard, style: {
|
return (React.createElement(AdaptiveCardView, { vIndex: 2, hIndex: 0, element: this.state.subCard, style: {
|
||||||
marginTop: this.styleConfig.card.spacing,
|
marginTop: 10,
|
||||||
} }));
|
} }));
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
|
@ -0,0 +1,38 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Column } from '../../Components/Containers/Column';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
import { ContentFactory } from '../Factories/ContentFactory';
|
||||||
|
export class ColumnView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderContents = () => {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (element.hasItems()) {
|
||||||
|
return element.items.map((content, index) => ContentFactory.createView(content, index));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onPress = () => {
|
||||||
|
console.log('ColumnView onPress');
|
||||||
|
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element.selectAction);
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Column, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, width: this.styleConfig.columnWidth, onPress: element.selectAction ? this.onPress : undefined, spacing: this.styleConfig.spacing }, this.renderContents()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
import { ColumnView } from './Column';
|
||||||
|
export class ColumnSetView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderColumns = () => {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (element.hasColumns()) {
|
||||||
|
return element.columns.map((column, index) => (React.createElement(ColumnView, { key: index, vIndex: 0, hIndex: index, element: column })));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Row, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, spacing: this.styleConfig.spacing }, this.renderColumns()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Column } from '../../Components/Containers/Column';
|
||||||
|
import { ActionContext } from '../../Contexts/ActionContext';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
import { ContentFactory } from '../Factories/ContentFactory';
|
||||||
|
export class ContainerView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderContents = () => {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (element.hasItems()) {
|
||||||
|
return element.items.map((content, index) => ContentFactory.createView(content, index));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onPress = () => {
|
||||||
|
console.log('ContainerView onPress');
|
||||||
|
let callback = ActionContext.getGlobalInstance().getActionEventHandler(this.props.element.selectAction);
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Column, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, width: 'stretch', onPress: element.selectAction ? this.onPress : undefined, spacing: this.styleConfig.spacing }, this.renderContents()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { TextBlock } from '../../Components/Basic/TextBlock';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
export class FactView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Row, { vIndex: this.props.vIndex, hIndex: this.props.hIndex },
|
||||||
|
React.createElement(TextBlock, { vIndex: 0, hIndex: 0, width: 'auto', textStyle: {
|
||||||
|
color: '#333333',
|
||||||
|
} }, element.title),
|
||||||
|
React.createElement(TextBlock, { vIndex: 0, hIndex: 1, width: 'auto', textStyle: {
|
||||||
|
color: '#777777',
|
||||||
|
} }, element.value)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Column } from '../../Components/Containers/Column';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
import { FactView } from './Fact';
|
||||||
|
export class FactSetView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderFacts = () => {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValue()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (element.facts) {
|
||||||
|
return element.facts.map((fact, index) => (React.createElement(FactView, { key: index, vIndex: 0, hIndex: index, element: fact })));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Column, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, width: 'stretch', spacing: this.styleConfig.spacing }, this.renderFacts()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ScrollView } from 'react-native';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
import { ImageView } from '../CardElements/Image';
|
||||||
|
export class ImageSetView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderImages = () => {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return element.images.map((img, index) => (React.createElement(ImageView, { key: index, vIndex: 1, hIndex: index, element: img, size: element.imageSize, maxWidth: this.state.maxWidth, maxHeight: this.state.maxHeight, onImageSize: this.onImageSize, hSpace: 10 })));
|
||||||
|
};
|
||||||
|
this.onImageSize = (width, height, url) => {
|
||||||
|
console.log(`ImageSet adjust height: ${height}`);
|
||||||
|
let maxWidth = width;
|
||||||
|
let maxHeight = height;
|
||||||
|
let ratio = width > 0 ? height / width : height;
|
||||||
|
if (maxWidth > this.props.containerWidth) {
|
||||||
|
maxWidth = this.props.containerWidth;
|
||||||
|
}
|
||||||
|
maxHeight = maxWidth * ratio;
|
||||||
|
if (this.state.maxHeight !== undefined && this.state.maxHeight !== 0 && maxHeight > this.state.maxHeight) {
|
||||||
|
maxHeight = this.state.maxHeight;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
maxHeight: maxHeight
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
this.state = {
|
||||||
|
maxWidth: undefined,
|
||||||
|
maxHeight: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(ScrollView, { flex: 1, horizontal: true, minHeight: this.state.maxHeight },
|
||||||
|
React.createElement(Row, { vIndex: 0, hIndex: 0, spacing: this.styleConfig.spacing, wrap: 'nowrap' }, this.renderImages())));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { ActionType } from '../../Schema/Base/ActionElement';
|
||||||
|
import { OpenUrlActionView } from '../Actions/OpenUrlAction';
|
||||||
|
import { ShowCardActionView } from '../Actions/ShowCardAction';
|
||||||
|
import { SubmitActionView } from '../Actions/SubmitAction';
|
||||||
|
export class ActionFactory {
|
||||||
|
static createAction(element, index, context) {
|
||||||
|
if (element) {
|
||||||
|
switch (element.type) {
|
||||||
|
case ActionType.OpenUrl:
|
||||||
|
return (React.createElement(OpenUrlActionView, { key: 'OpenUrlActionView' + index, vIndex: 0, hIndex: index, element: element, actionHooks: this.getHooks(context, element.getActionType()) }));
|
||||||
|
case ActionType.ShowCard:
|
||||||
|
return (React.createElement(ShowCardActionView, { key: 'ShowCardActionView' + index, vIndex: 0, hIndex: index, element: element, actionHooks: this.getHooks(context, element.getActionType()) }));
|
||||||
|
case ActionType.Submit:
|
||||||
|
return (React.createElement(SubmitActionView, { key: 'SubmitActionView' + index, vIndex: 0, hIndex: index, element: element, actionHooks: this.getHooks(context, element.getActionType()) }));
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static getHooks(context, actionType) {
|
||||||
|
if (context) {
|
||||||
|
return context.getHooks(actionType);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { SeparateLine } from '../../Components/Basic/SeparateLine';
|
||||||
|
import { ContentElementType } from '../../Schema/Base/ContentElement';
|
||||||
|
import { HostConfigManager } from '../../Styles/HostConfig';
|
||||||
|
import { ImageView } from '../CardElements/Image';
|
||||||
|
import { TextBlockView } from '../CardElements/TextBlock';
|
||||||
|
import { ColumnSetView } from '../Containers/ColumnSet';
|
||||||
|
import { ContainerView } from '../Containers/Container';
|
||||||
|
import { FactSetView } from '../Containers/FactSet';
|
||||||
|
import { ImageSetView } from '../Containers/ImageSet';
|
||||||
|
import { DateInputView } from '../Inputs/DateInput';
|
||||||
|
import { NumberInputView } from '../Inputs/NumberInput';
|
||||||
|
import { TextInputView } from '../Inputs/TextInput';
|
||||||
|
import { TimeInputView } from '../Inputs/TimeInput';
|
||||||
|
export class ContentFactory {
|
||||||
|
static createView(element, index) {
|
||||||
|
if (element) {
|
||||||
|
let elementView = ContentFactory.createElement(element, index);
|
||||||
|
if (index > 0 && element.separator) {
|
||||||
|
return [
|
||||||
|
React.createElement(SeparateLine, { key: 'SeparateLine' + index, color: '#777777', margin: HostConfigManager.getInstance().getSpacing(element.spacing) }),
|
||||||
|
elementView
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [elementView];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static createElement(element, index) {
|
||||||
|
if (element) {
|
||||||
|
switch (element.type) {
|
||||||
|
case ContentElementType.TextInput:
|
||||||
|
return (React.createElement(TextInputView, { key: 'TextInputView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.NumberInput:
|
||||||
|
return (React.createElement(NumberInputView, { key: 'NumberInputView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.DateInput:
|
||||||
|
return (React.createElement(DateInputView, { key: 'DateInputView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.TimeInput:
|
||||||
|
return (React.createElement(TimeInputView, { key: 'TimeInputView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.Container:
|
||||||
|
return (React.createElement(ContainerView, { key: 'ContainerView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.ColumnSet:
|
||||||
|
return (React.createElement(ColumnSetView, { key: 'ColumnSetView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.TextBlock:
|
||||||
|
return (React.createElement(TextBlockView, { key: 'TextBlockView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.Image:
|
||||||
|
return (React.createElement(ImageView, { key: 'ImageView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.ImageSet:
|
||||||
|
return (React.createElement(ImageSetView, { key: 'ImageSetView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
case ContentElementType.FactSet:
|
||||||
|
return (React.createElement(FactSetView, { key: 'FactSetView' + index, element: element, vIndex: index, hIndex: 0 }));
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { DateInput } from '../../Components/Inputs/DateInput';
|
||||||
|
import { FormContext } from '../../Contexts/FormContext';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
export class DateInputView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onValueChange = (value) => {
|
||||||
|
this.setState({
|
||||||
|
value: value
|
||||||
|
}, this.updateStore);
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.state = {
|
||||||
|
value: this.props.element.value,
|
||||||
|
};
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Row, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, spacing: this.styleConfig.spacing },
|
||||||
|
React.createElement(DateInput, { vIndex: 0, hIndex: 0, value: this.state.value, onValueChange: this.onValueChange, validateInput: element.validateForm })));
|
||||||
|
}
|
||||||
|
updateStore() {
|
||||||
|
FormContext.getInstance().updateField(this.props.element.id, this.state.value, this.props.element.validateForm(this.state.value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { NumberInput } from '../../Components/Inputs/NumberInput';
|
||||||
|
import { FormContext } from '../../Contexts/FormContext';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
export class NumberInputView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onBlur = () => {
|
||||||
|
console.log('NumberInputView onBlur');
|
||||||
|
};
|
||||||
|
this.onValueChange = (value) => {
|
||||||
|
this.setState({
|
||||||
|
value: value
|
||||||
|
}, this.updateStore);
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
let defaultValue = this.props.element.value;
|
||||||
|
if (defaultValue === undefined) {
|
||||||
|
defaultValue = '';
|
||||||
|
}
|
||||||
|
if (Utils.isNumber(this.props.element.value.toString())) {
|
||||||
|
this.state = {
|
||||||
|
value: this.props.element.value.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Row, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, spacing: this.styleConfig.spacing },
|
||||||
|
React.createElement(NumberInput, { vIndex: 0, hIndex: 0, placeholder: element.placeholder, value: this.state.value, onValueChange: this.onValueChange, onBlur: this.onBlur, validateInput: element.validateForm })));
|
||||||
|
}
|
||||||
|
updateStore() {
|
||||||
|
FormContext.getInstance().updateField(this.props.element.id, this.state.value, this.props.element.validateForm(this.state.value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { InputBox } from '../../Components/Inputs/InputBox';
|
||||||
|
import { FormContext } from '../../Contexts/FormContext';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
export class TextInputView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onBlur = () => {
|
||||||
|
console.log('TextInputView onBlur');
|
||||||
|
};
|
||||||
|
this.onValueChange = (value) => {
|
||||||
|
this.setState({
|
||||||
|
value: value
|
||||||
|
}, this.updateStore);
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.state = {
|
||||||
|
value: this.props.element.value,
|
||||||
|
};
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Row, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, spacing: this.styleConfig.spacing },
|
||||||
|
React.createElement(InputBox, { vIndex: 0, hIndex: 0, placeholder: element.placeholder, value: this.state.value, onValueChange: this.onValueChange, onBlur: this.onBlur })));
|
||||||
|
}
|
||||||
|
updateStore() {
|
||||||
|
FormContext.getInstance().updateField(this.props.element.id, this.state.value, this.props.element.validateForm(this.state.value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Row } from '../../Components/Containers/Row';
|
||||||
|
import { TimeInput } from '../../Components/Inputs/TimeInput';
|
||||||
|
import { FormContext } from '../../Contexts/FormContext';
|
||||||
|
import { StyleManager } from '../../Styles/StyleManager';
|
||||||
|
export class TimeInputView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onValueChange = (value) => {
|
||||||
|
this.setState({
|
||||||
|
value: value
|
||||||
|
}, this.updateStore);
|
||||||
|
};
|
||||||
|
const { element } = this.props;
|
||||||
|
if (element && element.isValid()) {
|
||||||
|
this.state = {
|
||||||
|
value: this.props.element.value,
|
||||||
|
};
|
||||||
|
this.styleConfig = StyleManager.getInstance().getStyle(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { element } = this.props;
|
||||||
|
if (!element || !element.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (React.createElement(Row, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, spacing: this.styleConfig.spacing },
|
||||||
|
React.createElement(TimeInput, { vIndex: 0, hIndex: 0, value: this.state.value, onValueChange: this.onValueChange, validateInput: element.validateForm })));
|
||||||
|
}
|
||||||
|
updateStore() {
|
||||||
|
FormContext.getInstance().updateField(this.props.element.id, this.state.value, this.props.element.validateForm(this.state.value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Linking, View, } from 'react-native';
|
import { Linking, View, } from 'react-native';
|
||||||
import { ActionContext } from '../Context/ActionContext';
|
import { ActionContext } from '../Contexts/ActionContext';
|
||||||
import { FormContext } from '../Context/FormContext';
|
import { FormContext } from '../Contexts/FormContext';
|
||||||
import { ActionType } from '../Schema/Base/ActionElement';
|
import { ActionType } from '../Schema/Base/ActionElement';
|
||||||
import { CardElement } from '../Schema/Cards/Card';
|
import { CardElement } from '../Schema/Cards/Card';
|
||||||
import { CardView } from './Cards/CardView';
|
import { AdaptiveCardView } from './Cards/AdaptiveCard';
|
||||||
export class CardRootView extends React.PureComponent {
|
export class CardRootView extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -65,6 +65,6 @@ export class CardRootView extends React.PureComponent {
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (React.createElement(View, { style: { flex: 1 } },
|
return (React.createElement(View, { style: { flex: 1 } },
|
||||||
React.createElement(CardView, { element: this.state.rootCard })));
|
React.createElement(AdaptiveCardView, { vIndex: 0, hIndex: 0, element: this.state.rootCard })));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,2 +1,2 @@
|
||||||
import { CardRootView } from './View/CardRootView';
|
import { CardRootView } from './Views/Root';
|
||||||
export default CardRootView;
|
export default CardRootView;
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { TouchableOpacity, View } from 'react-native';
|
||||||
|
export class FlexBox extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderChildren = () => {
|
||||||
|
if (this.props.children) {
|
||||||
|
return React.Children.map(this.props.children, (child, index) => {
|
||||||
|
if (child) {
|
||||||
|
if (typeof child !== 'string' && typeof child !== 'number') {
|
||||||
|
if (this.props.width === 'auto') {
|
||||||
|
return React.cloneElement(child, {
|
||||||
|
containerWidth: this.props.containerWidth,
|
||||||
|
containerHeight: this.props.containerHeight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return React.cloneElement(child, {
|
||||||
|
containerWidth: this.state.width,
|
||||||
|
containerHeight: this.state.height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onLayoutChange = (event) => {
|
||||||
|
let width = event.nativeEvent.layout.width;
|
||||||
|
let height = event.nativeEvent.layout.height;
|
||||||
|
this.setState({
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
}, () => {
|
||||||
|
console.log(`FlexBox: width: ${width} height: ${height}`);
|
||||||
|
if (this.props.onLayoutChange) {
|
||||||
|
this.props.onLayoutChange(width, height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.getFlexStyle = () => {
|
||||||
|
if (this.props.flex) {
|
||||||
|
return {
|
||||||
|
flex: this.props.flex
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.getChildrenFlexStyle = () => {
|
||||||
|
let result = {
|
||||||
|
flexDirection: this.props.flexDirection,
|
||||||
|
alignItems: this.props.wrap === 'wrap' ? 'flex-start' : this.props.alignItems,
|
||||||
|
justifyContent: this.props.justifyContent,
|
||||||
|
height: this.props.height,
|
||||||
|
flexWrap: this.props.wrap,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
this.getSizeStyle = () => {
|
||||||
|
if (this.props.width === 'auto') {
|
||||||
|
return {
|
||||||
|
flex: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.props.width === 'stretch') {
|
||||||
|
return {
|
||||||
|
flex: 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.props.relativeWidth && typeof this.props.width === 'number') {
|
||||||
|
return {
|
||||||
|
flex: this.props.width
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
width: this.props.width
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.getVerticalMarginStyle = () => {
|
||||||
|
if (this.props.vIndex > 0) {
|
||||||
|
return {
|
||||||
|
marginTop: this.props.vSpace,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.getHorizontalMarginStyle = () => {
|
||||||
|
if (this.props.hIndex > 0) {
|
||||||
|
return {
|
||||||
|
marginLeft: this.props.hSpace,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
this.state = {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
if (this.props.onPress) {
|
||||||
|
return this.renderTouchableBox();
|
||||||
|
}
|
||||||
|
return this.renderBox();
|
||||||
|
}
|
||||||
|
renderBox() {
|
||||||
|
return (React.createElement(View, { style: [
|
||||||
|
this.getChildrenFlexStyle(),
|
||||||
|
this.getFlexStyle(),
|
||||||
|
this.getSizeStyle(),
|
||||||
|
this.getVerticalMarginStyle(),
|
||||||
|
this.getHorizontalMarginStyle(),
|
||||||
|
this.props.style,
|
||||||
|
], onLayout: this.onLayoutChange }, this.renderChildren()));
|
||||||
|
}
|
||||||
|
renderTouchableBox() {
|
||||||
|
return (React.createElement(TouchableOpacity, { style: [
|
||||||
|
this.getChildrenFlexStyle(),
|
||||||
|
this.getFlexStyle(),
|
||||||
|
this.getSizeStyle(),
|
||||||
|
this.getVerticalMarginStyle(),
|
||||||
|
this.getHorizontalMarginStyle(),
|
||||||
|
this.props.style,
|
||||||
|
], onLayout: this.onLayoutChange, onPress: this.props.onPress }, this.renderChildren()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Image, Text, View } from 'react-native';
|
||||||
|
import { FlexBox } from './FlexBox';
|
||||||
|
export class ImageBlock extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderPlaceholder = () => {
|
||||||
|
if (!this.state.loaded) {
|
||||||
|
return (React.createElement(View, { style: [
|
||||||
|
{
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}
|
||||||
|
] },
|
||||||
|
React.createElement(Text, { style: {
|
||||||
|
fontSize: 32,
|
||||||
|
color: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
textAlign: 'center'
|
||||||
|
} }, '\uE601')));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onLayoutChange = (width, height) => {
|
||||||
|
Image.getSize(this.props.url, this.onImageSize, this.onImageSizeError);
|
||||||
|
};
|
||||||
|
this.onImageSizeUpdate = (event) => {
|
||||||
|
let width = event.nativeEvent.layout.width;
|
||||||
|
let height = event.nativeEvent.layout.height;
|
||||||
|
console.log(`Image at url:${this.props.url} size updated. Width: ${width}, height: ${height}`);
|
||||||
|
if (this.props.onImageSize) {
|
||||||
|
this.props.onImageSize(width, height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onImageSize = (width, height) => {
|
||||||
|
console.log(`Image at url:${this.props.url} get size succeed. Width: ${width}, height: ${height}`);
|
||||||
|
let ratio = width > 0 ? height / width : height;
|
||||||
|
if (this.props.width === 'auto') {
|
||||||
|
this.applyAutoSize(width, ratio);
|
||||||
|
}
|
||||||
|
else if (this.props.width === 'stretch') {
|
||||||
|
this.applyStretchSize(width, height, ratio);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.applyFixSize(ratio);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onImageSizeError = () => {
|
||||||
|
console.log(`Image at url:${this.props.url} get size failed.`);
|
||||||
|
this.setState({
|
||||||
|
loaded: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.onImageLoad = () => {
|
||||||
|
console.log(`Image at url:${this.props.url} load succeed.`);
|
||||||
|
this.setState({
|
||||||
|
loaded: true
|
||||||
|
});
|
||||||
|
Image.getSize(this.props.url, this.onImageSize, this.onImageSizeError);
|
||||||
|
};
|
||||||
|
this.onImageError = () => {
|
||||||
|
console.log(`Image at url:${this.props.url} load failed.`);
|
||||||
|
this.setState({
|
||||||
|
loaded: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.state = {
|
||||||
|
loaded: true,
|
||||||
|
width: undefined,
|
||||||
|
height: undefined,
|
||||||
|
ratio: 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, Object.assign({}, this.props, { style: [
|
||||||
|
this.props.boxStyle,
|
||||||
|
{
|
||||||
|
alignSelf: this.props.alignSelf,
|
||||||
|
}
|
||||||
|
], onLayoutChange: this.onLayoutChange, onPress: this.props.onPress, width: 'auto' }),
|
||||||
|
this.renderPlaceholder(),
|
||||||
|
React.createElement(Image, { accessible: !!this.props.alt, accessibilityLabel: this.props.alt, source: { uri: this.props.url }, style: [
|
||||||
|
this.getSize(),
|
||||||
|
this.props.imgStyle
|
||||||
|
], onLoad: this.onImageLoad, onError: this.onImageError, onLayout: this.onImageSizeUpdate })));
|
||||||
|
}
|
||||||
|
applyFixSize(ratio) {
|
||||||
|
if (typeof this.props.width === 'number') {
|
||||||
|
this.setState({
|
||||||
|
width: this.props.width,
|
||||||
|
height: this.props.width * ratio,
|
||||||
|
ratio: ratio,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyStretchSize(width, height, ratio) {
|
||||||
|
if (this.props.containerWidth) {
|
||||||
|
let finalWidth = this.props.containerWidth;
|
||||||
|
let finalHeight = finalWidth * ratio;
|
||||||
|
console.log(`Image at url:${this.props.url} get size succeed. Final width: ${finalWidth}, final height: ${finalHeight}`);
|
||||||
|
this.setState({
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
ratio: ratio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
ratio: ratio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyAutoSize(width, ratio) {
|
||||||
|
let finalWidth = width;
|
||||||
|
if (finalWidth > this.props.containerWidth) {
|
||||||
|
finalWidth = this.props.containerWidth;
|
||||||
|
}
|
||||||
|
let finalHeight = finalWidth * ratio;
|
||||||
|
console.log(`Image at url:${this.props.url} get size succeed. Final width: ${finalWidth}, final height: ${finalHeight}`);
|
||||||
|
this.setState({
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
ratio: ratio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getSize() {
|
||||||
|
let finalWidth = this.state.width;
|
||||||
|
let finalHeight = this.state.height;
|
||||||
|
if (this.state.width && this.state.height) {
|
||||||
|
if (this.state.ratio <= 1) {
|
||||||
|
if (this.props.maxWidth && finalWidth > this.props.maxWidth) {
|
||||||
|
finalWidth = this.props.maxWidth;
|
||||||
|
}
|
||||||
|
finalHeight = finalWidth * this.state.ratio;
|
||||||
|
if (this.props.maxHeight && finalHeight > this.props.maxHeight) {
|
||||||
|
finalHeight = this.props.maxHeight;
|
||||||
|
finalWidth = this.state.ratio > 0 ? finalHeight / this.state.ratio : finalWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.props.maxHeight && finalHeight > this.props.maxHeight) {
|
||||||
|
finalHeight = this.props.maxHeight;
|
||||||
|
}
|
||||||
|
finalWidth = this.state.ratio > 0 ? finalHeight / this.state.ratio : finalWidth;
|
||||||
|
if (this.props.maxWidth && finalWidth > this.props.maxWidth) {
|
||||||
|
finalWidth = this.props.maxWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { PixelRatio, Platform, View, } from 'react-native';
|
||||||
|
export class SeparateLine extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { color, margin } = this.props;
|
||||||
|
const thickness = (Platform.OS === 'ios') ?
|
||||||
|
parseFloat((1 / PixelRatio.get()).toFixed(2)) :
|
||||||
|
1;
|
||||||
|
const style = {
|
||||||
|
height: thickness,
|
||||||
|
marginHorizontal: 0,
|
||||||
|
marginVertical: margin
|
||||||
|
};
|
||||||
|
return (React.createElement(View, Object.assign({}, this.props, { style: [
|
||||||
|
{
|
||||||
|
flex: 0,
|
||||||
|
backgroundColor: color,
|
||||||
|
},
|
||||||
|
style
|
||||||
|
] })));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, } from 'react-native';
|
||||||
|
import { FlexBox } from './FlexBox';
|
||||||
|
export class TextBlock extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, flexDirection: 'row', relativeWidth: false, width: this.props.width, vSpace: this.props.spacing, alignSelf: 'stretch', alignItems: 'stretch', alignContent: 'stretch', justifyContent: this.props.horizontalAlign, style: this.props.boxStyle },
|
||||||
|
React.createElement(Text, { style: [
|
||||||
|
this.props.textStyle,
|
||||||
|
], numberOfLines: this.props.numberOfLines }, this.props.children)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class Column extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { flexDirection: 'column', relativeWidth: true, alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: this.props.width, vIndex: this.props.vIndex, hIndex: this.props.hIndex, style: this.props.style, vSpace: this.props.spacing, onPress: this.props.onPress }, this.props.children));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class Row extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { flexDirection: 'row', relativeWidth: false, alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', wrap: this.props.wrap, justifyContent: 'space-between', width: this.props.width ? this.props.width : 'stretch', vIndex: this.props.vIndex, hIndex: this.props.hIndex, style: this.props.style, vSpace: this.props.spacing, onPress: this.props.onPress }, this.props.children));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
import { TextBlock } from '../Basic/TextBlock';
|
||||||
|
export class Button extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, flexDirection: 'row', relativeWidth: false, flex: 1, alignSelf: 'stretch', alignItems: 'center', alignContent: 'center', justifyContent: 'center', width: 'stretch', hSpace: 10, style: [
|
||||||
|
{
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: '#277BDF',
|
||||||
|
},
|
||||||
|
this.props.boxStyle
|
||||||
|
], onPress: this.props.onPress },
|
||||||
|
React.createElement(TextBlock, { vIndex: 0, hIndex: 0, width: 'stretch', horizontalAlign: 'center', textStyle: [
|
||||||
|
{
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
this.props.textStyle,
|
||||||
|
], numberOfLines: 1 }, this.props.title)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
import * as React from 'react';
|
||||||
|
import { DatePickerAndroid, DatePickerIOS, Platform, Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class DateInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderBtn = () => {
|
||||||
|
if (!this.state.showDatePicker) {
|
||||||
|
return (React.createElement(TouchableOpacity, { style: { flex: 1 }, onPress: this.showDatePicker },
|
||||||
|
React.createElement(View, { style: {
|
||||||
|
flex: 1,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 6,
|
||||||
|
marginVertical: 6,
|
||||||
|
height: 38,
|
||||||
|
} },
|
||||||
|
React.createElement(Text, null, this.props.value))));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.renderInlineDatePicker = () => {
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
if (this.state.showDatePicker) {
|
||||||
|
let date = Utils.extractDate(this.props.value);
|
||||||
|
console.log(date);
|
||||||
|
return (React.createElement(DatePickerIOS, { date: date, mode: 'date', onDateChange: this.onDateChange, style: { flex: 1 } }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onPickerClose = () => {
|
||||||
|
if (this.props.validateInput) {
|
||||||
|
if (this.props.validateInput(this.props.value)) {
|
||||||
|
console.log('DateInput: valid');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('DateInput: invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onDateChange = (date) => {
|
||||||
|
if (this.props.onValueChange) {
|
||||||
|
let timeString = Utils.getDateString(date);
|
||||||
|
console.log(timeString);
|
||||||
|
this.setState({
|
||||||
|
showDatePicker: false,
|
||||||
|
}, () => this.props.onValueChange(timeString));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.showDatePickerAndroid = this.showDatePickerAndroid.bind(this);
|
||||||
|
this.showDatePicker = this.showDatePicker.bind(this);
|
||||||
|
this.state = {
|
||||||
|
showDatePicker: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, flexDirection: 'row', alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: 'stretch' },
|
||||||
|
this.renderBtn(),
|
||||||
|
this.renderInlineDatePicker()));
|
||||||
|
}
|
||||||
|
showDatePickerAndroid() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
const today = new Date();
|
||||||
|
try {
|
||||||
|
const { action, year, month, day } = yield DatePickerAndroid.open({
|
||||||
|
date: today,
|
||||||
|
});
|
||||||
|
if (action === DatePickerAndroid.dateSetAction) {
|
||||||
|
let newDate = new Date(year, month, day);
|
||||||
|
this.onDateChange(newDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ({ code, message }) {
|
||||||
|
console.warn('Cannot open date picker', message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
showDatePicker() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.state.showDatePicker) {
|
||||||
|
this.setState({
|
||||||
|
showDatePicker: false
|
||||||
|
}, this.onPickerClose);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
showDatePicker: true
|
||||||
|
});
|
||||||
|
yield this.showDatePickerAndroid();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { TextInput } from 'react-native';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class InputBox extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, flexDirection: 'row', alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: 'stretch' },
|
||||||
|
React.createElement(TextInput, { style: [
|
||||||
|
{
|
||||||
|
flex: 1,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 6,
|
||||||
|
marginVertical: 6,
|
||||||
|
height: 38,
|
||||||
|
},
|
||||||
|
this.props.style
|
||||||
|
], multiline: this.props.multiline, keyboardType: this.props.keyboardType, blurOnSubmit: true, placeholder: this.props.placeholder, value: this.props.value, returnKeyType: this.props.returnKeyType, underlineColorAndroid: 'transparent', importantForAccessibility: 'no-hide-descendants', onChangeText: this.props.onValueChange, onBlur: this.props.onBlur })));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Platform } from 'react-native';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { InputBox } from './InputBox';
|
||||||
|
export class NumberInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.onChangeText = (input) => {
|
||||||
|
if (this.props.onValueChange) {
|
||||||
|
if (Utils.isSymbol(input) || Utils.isNumber(input)) {
|
||||||
|
console.log('change text');
|
||||||
|
this.props.onValueChange(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onBlur = () => {
|
||||||
|
if (this.props.validateInput) {
|
||||||
|
if (this.props.validateInput(this.props.value)) {
|
||||||
|
console.log('NumberInput: valid');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('NumberInput: invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.props.onBlur) {
|
||||||
|
this.props.onBlur();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(InputBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, multiline: false, keyboardType: Platform.OS === 'ios' ? 'numbers-and-punctuation' : 'numeric', placeholder: this.props.placeholder, value: this.props.value, returnKeyType: 'done', onValueChange: this.onChangeText, onBlur: this.onBlur }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
import * as React from 'react';
|
||||||
|
import { DatePickerIOS, Platform, Text, TimePickerAndroid, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { Utils } from '../../Shared/Utils';
|
||||||
|
import { FlexBox } from '../Basic/FlexBox';
|
||||||
|
export class TimeInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.renderBtn = () => {
|
||||||
|
if (!this.state.showTimePicker) {
|
||||||
|
return (React.createElement(TouchableOpacity, { style: { flex: 1 }, onPress: this.showDatePicker },
|
||||||
|
React.createElement(View, { style: [
|
||||||
|
{
|
||||||
|
flex: 1,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 6,
|
||||||
|
marginVertical: 6,
|
||||||
|
height: 38,
|
||||||
|
}
|
||||||
|
] },
|
||||||
|
React.createElement(Text, null, this.props.value))));
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.showTimePickerIOS = () => {
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
if (this.state.showTimePicker) {
|
||||||
|
let time = Utils.extractTime(this.props.value);
|
||||||
|
console.log(time);
|
||||||
|
return (React.createElement(DatePickerIOS, { date: time, mode: 'time', onDateChange: this.onTimeChangeIOS, style: { flex: 1 } }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
this.onPickerClose = () => {
|
||||||
|
if (this.props.validateInput) {
|
||||||
|
if (this.props.validateInput(this.props.value)) {
|
||||||
|
console.log('TimeInput: valid');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('TimeInput: invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.onTimeChangeIOS = (date) => {
|
||||||
|
this.onTimeChange(date.getHours(), date.getMinutes());
|
||||||
|
};
|
||||||
|
this.onTimeChange = (hour, minute) => {
|
||||||
|
if (this.props.onValueChange) {
|
||||||
|
let timeString = Utils.composeTimeString(hour, minute);
|
||||||
|
console.log(timeString);
|
||||||
|
this.setState({
|
||||||
|
showTimePicker: false,
|
||||||
|
}, () => this.props.onValueChange(timeString));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.showTimePickerAndroid = this.showTimePickerAndroid.bind(this);
|
||||||
|
this.showDatePicker = this.showDatePicker.bind(this);
|
||||||
|
this.state = {
|
||||||
|
showTimePicker: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (React.createElement(FlexBox, { vIndex: this.props.vIndex, hIndex: this.props.hIndex, relativeWidth: false, flexDirection: 'row', alignSelf: 'stretch', alignContent: 'flex-start', alignItems: 'stretch', justifyContent: 'space-between', width: 'stretch' },
|
||||||
|
this.renderBtn(),
|
||||||
|
this.showTimePickerIOS()));
|
||||||
|
}
|
||||||
|
showTimePickerAndroid() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
const now = new Date();
|
||||||
|
try {
|
||||||
|
const { action, hour, minute } = yield TimePickerAndroid.open({
|
||||||
|
hour: now.getHours(),
|
||||||
|
minute: now.getMinutes(),
|
||||||
|
is24Hour: true
|
||||||
|
});
|
||||||
|
if (action === TimePickerAndroid.timeSetAction) {
|
||||||
|
this.onTimeChange(hour, minute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ({ code, message }) {
|
||||||
|
console.warn('Cannot open date picker', message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
showDatePicker() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.state.showTimePicker) {
|
||||||
|
this.setState({
|
||||||
|
showTimePicker: false
|
||||||
|
}, this.onPickerClose);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setState({
|
||||||
|
showTimePicker: true
|
||||||
|
}, this.showTimePickerAndroid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ export class ActionContext {
|
||||||
formValidate: false,
|
formValidate: false,
|
||||||
target: target,
|
target: target,
|
||||||
};
|
};
|
||||||
let hookFuncs = this.getExcuteFuncs(action.type, externalHooks);
|
let hookFuncs = this.getExecuteFuncs(action.type, externalHooks);
|
||||||
args = hookFuncs.reduce((prev, current) => {
|
args = hookFuncs.reduce((prev, current) => {
|
||||||
return current(prev);
|
return current(prev);
|
||||||
}, args);
|
}, args);
|
||||||
|
@ -75,7 +75,7 @@ export class ActionContext {
|
||||||
}
|
}
|
||||||
return callback;
|
return callback;
|
||||||
}
|
}
|
||||||
getExcuteFuncs(actionType, externalHooks) {
|
getExecuteFuncs(actionType, externalHooks) {
|
||||||
let hookFuncs = [];
|
let hookFuncs = [];
|
||||||
if (this.hooks) {
|
if (this.hooks) {
|
||||||
let hookArrays = this.hooks[actionType];
|
let hookArrays = this.hooks[actionType];
|
|
@ -1,4 +1,4 @@
|
||||||
import { AbstractElement } from '../Base/AbstractElement';
|
import { AbstractElement } from './AbstractElement';
|
||||||
export var ActionType;
|
export var ActionType;
|
||||||
(function (ActionType) {
|
(function (ActionType) {
|
||||||
ActionType["OpenUrl"] = "Action.OpenUrl";
|
ActionType["OpenUrl"] = "Action.OpenUrl";
|
||||||
|
@ -27,6 +27,9 @@ export class ActionElement extends AbstractElement {
|
||||||
getData() {
|
getData() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
isAction() {
|
isAction() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Spacing } from '../../Shared/Enums';
|
import { Spacing } from '../../Shared/Enums';
|
||||||
import { Utils } from '../../Shared/Utils';
|
import { Utils } from '../../Shared/Utils';
|
||||||
import { AbstractElement } from '../Base/AbstractElement';
|
import { AbstractElement } from './AbstractElement';
|
||||||
export var ContentElementType;
|
export var ContentElementType;
|
||||||
(function (ContentElementType) {
|
(function (ContentElementType) {
|
||||||
ContentElementType["Column"] = "Column";
|
ContentElementType["Column"] = "Column";
|
||||||
|
@ -31,6 +31,11 @@ export class ContentElement extends AbstractElement {
|
||||||
getId() {
|
getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
spacing: this.spacing
|
||||||
|
};
|
||||||
|
}
|
||||||
isContent() {
|
isContent() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { FormContext } from '../../Context/FormContext';
|
import { FormContext } from '../../Contexts/FormContext';
|
||||||
import { ContentElement } from '../Base/ContentElement';
|
|
||||||
import { ActionFactory } from '../Factories/ActionFactory';
|
import { ActionFactory } from '../Factories/ActionFactory';
|
||||||
|
import { ContentElement } from './ContentElement';
|
||||||
export var FormElementType;
|
export var FormElementType;
|
||||||
(function (FormElementType) {
|
(function (FormElementType) {
|
||||||
FormElementType["Column"] = "Column";
|
FormElementType["Column"] = "Column";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ContentElement } from '../Base/ContentElement';
|
import { ContentElement } from './ContentElement';
|
||||||
export var InputElementType;
|
export var InputElementType;
|
||||||
(function (InputElementType) {
|
(function (InputElementType) {
|
||||||
InputElementType["TextInput"] = "Input.Text";
|
InputElementType["TextInput"] = "Input.Text";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AbstractElement } from '../Base/AbstractElement';
|
import { AbstractElement } from './AbstractElement';
|
||||||
export var ValueElementType;
|
export var ValueElementType;
|
||||||
(function (ValueElementType) {
|
(function (ValueElementType) {
|
||||||
ValueElementType["Fact"] = "Fact";
|
ValueElementType["Fact"] = "Fact";
|
||||||
|
@ -18,4 +18,7 @@ export class ValueElement extends AbstractElement {
|
||||||
isValue() {
|
isValue() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,14 @@ export class ImageElement extends FormElement {
|
||||||
getChildren() {
|
getChildren() {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
horizontalAlignment: this.horizontalAlignment,
|
||||||
|
imgSize: this.size,
|
||||||
|
style: this.style,
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
setSize(size) {
|
setSize(size) {
|
||||||
this.size = Utils.getStringEnumValueOrDefault(ImageSize, size, ImageSize.Auto);
|
this.size = Utils.getStringEnumValueOrDefault(ImageSize, size, ImageSize.Auto);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,17 @@ export class TextBlockElement extends ContentElement {
|
||||||
this.wrap = json.wrap || false;
|
this.wrap = json.wrap || false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getStyleConfig() {
|
||||||
|
return {
|
||||||
|
color: this.color,
|
||||||
|
horizontalAlignment: this.horizontalAlignment,
|
||||||
|
isSubtle: this.isSubtle,
|
||||||
|
fontSize: this.size,
|
||||||
|
fontWeight: this.weight,
|
||||||
|
wrap: this.wrap,
|
||||||
|
spacing: this.spacing,
|
||||||
|
};
|
||||||
|
}
|
||||||
getTypeName() {
|
getTypeName() {
|
||||||
return ContentElementType.TextBlock;
|
return ContentElementType.TextBlock;
|
||||||
}
|
}
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче