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
|
||||
.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,
|
||||
target: target,
|
||||
};
|
||||
let hookFuncs = this.getExcuteFuncs(action.type, externalHooks);
|
||||
let hookFuncs = this.getExecuteFuncs(action.type, externalHooks);
|
||||
args = hookFuncs.reduce((prev, current) => {
|
||||
return current(prev);
|
||||
}, args);
|
||||
|
@ -75,7 +75,7 @@ export class ActionContext {
|
|||
}
|
||||
return callback;
|
||||
}
|
||||
getExcuteFuncs(actionType, externalHooks) {
|
||||
getExecuteFuncs(actionType, externalHooks) {
|
||||
let hookFuncs = [];
|
||||
if (this.hooks) {
|
||||
let hookArrays = this.hooks[actionType];
|
|
@ -1,4 +1,4 @@
|
|||
import { AbstractElement } from '../Base/AbstractElement';
|
||||
import { AbstractElement } from './AbstractElement';
|
||||
export var ActionType;
|
||||
(function (ActionType) {
|
||||
ActionType["OpenUrl"] = "Action.OpenUrl";
|
||||
|
@ -27,6 +27,9 @@ export class ActionElement extends AbstractElement {
|
|||
getData() {
|
||||
return {};
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {};
|
||||
}
|
||||
isAction() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Spacing } from '../../Shared/Enums';
|
||||
import { Utils } from '../../Shared/Utils';
|
||||
import { AbstractElement } from '../Base/AbstractElement';
|
||||
import { AbstractElement } from './AbstractElement';
|
||||
export var ContentElementType;
|
||||
(function (ContentElementType) {
|
||||
ContentElementType["Column"] = "Column";
|
||||
|
@ -31,6 +31,11 @@ export class ContentElement extends AbstractElement {
|
|||
getId() {
|
||||
return this.id;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing
|
||||
};
|
||||
}
|
||||
isContent() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FormContext } from '../../Context/FormContext';
|
||||
import { ContentElement } from '../Base/ContentElement';
|
||||
import { FormContext } from '../../Contexts/FormContext';
|
||||
import { ActionFactory } from '../Factories/ActionFactory';
|
||||
import { ContentElement } from './ContentElement';
|
||||
export var FormElementType;
|
||||
(function (FormElementType) {
|
||||
FormElementType["Column"] = "Column";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ContentElement } from '../Base/ContentElement';
|
||||
import { ContentElement } from './ContentElement';
|
||||
export var InputElementType;
|
||||
(function (InputElementType) {
|
||||
InputElementType["TextInput"] = "Input.Text";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AbstractElement } from '../Base/AbstractElement';
|
||||
import { AbstractElement } from './AbstractElement';
|
||||
export var ValueElementType;
|
||||
(function (ValueElementType) {
|
||||
ValueElementType["Fact"] = "Fact";
|
||||
|
@ -18,4 +18,7 @@ export class ValueElement extends AbstractElement {
|
|||
isValue() {
|
||||
return true;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,14 @@ export class ImageElement extends FormElement {
|
|||
getChildren() {
|
||||
return [];
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
horizontalAlignment: this.horizontalAlignment,
|
||||
imgSize: this.size,
|
||||
style: this.style,
|
||||
spacing: this.spacing,
|
||||
};
|
||||
}
|
||||
setSize(size) {
|
||||
this.size = Utils.getStringEnumValueOrDefault(ImageSize, size, ImageSize.Auto);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,17 @@ export class TextBlockElement extends ContentElement {
|
|||
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() {
|
||||
return ContentElementType.TextBlock;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,12 @@ export class ColumnElement extends FormElement {
|
|||
getChildren() {
|
||||
return this.items;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing,
|
||||
columnWidth: this.width,
|
||||
};
|
||||
}
|
||||
hasItems() {
|
||||
return this.items && this.items.length > 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@ export class ColumnSetElement extends FormElement {
|
|||
getChildren() {
|
||||
return this.columns;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing,
|
||||
};
|
||||
}
|
||||
hasColumns() {
|
||||
return this.columns && this.columns.length > 0;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ export class ContainerElement extends FormElement {
|
|||
getChildren() {
|
||||
return this.items;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing,
|
||||
};
|
||||
}
|
||||
hasItems() {
|
||||
return this.items && this.items.length > 0;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,11 @@ export class FactSetElement extends ContentElement {
|
|||
getRequiredProperties() {
|
||||
return ['facts'];
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing,
|
||||
};
|
||||
}
|
||||
hasFacts() {
|
||||
return this.facts && this.facts.length > 0;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@ export class ImageSetElement extends ContentElement {
|
|||
getRequiredProperties() {
|
||||
return ['images'];
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing,
|
||||
};
|
||||
}
|
||||
hasImages() {
|
||||
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 { 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 { DecCardElementView } from '../Basic/DecCardElementView';
|
||||
import { ImageBackground } from '../Basic/ImageBackground';
|
||||
import { ActionElementView } from '../Factories/ActionElementView';
|
||||
import { StyleManager } from '../Styles/StyleManager';
|
||||
export class CardView extends React.Component {
|
||||
import { ActionFactory } from '../Factories/ActionFactory';
|
||||
import { ContentFactory } from '../Factories/ContentFactory';
|
||||
export class AdaptiveCardView extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.showSubCard = (args) => {
|
||||
|
@ -32,7 +33,6 @@ export class CardView extends React.Component {
|
|||
name: 'showSubCard',
|
||||
actionType: ActionType.ShowCard
|
||||
});
|
||||
this.styleConfig = StyleManager.getInstance().getStyle();
|
||||
}
|
||||
render() {
|
||||
if (!this.props.element.isValid()) {
|
||||
|
@ -40,24 +40,27 @@ export class CardView extends React.Component {
|
|||
}
|
||||
const cardStyle = Object.assign({
|
||||
flex: 1,
|
||||
backgroundColor: this.styleConfig.card.backgroundColor,
|
||||
borderWidth: this.styleConfig.card.borderWidth,
|
||||
borderColor: this.styleConfig.card.borderColor,
|
||||
borderRadius: this.styleConfig.card.borderRadius,
|
||||
backgroundColor: 'white',
|
||||
borderWidth: 1,
|
||||
borderColor: '#777777',
|
||||
borderRadius: 4,
|
||||
}, this.props.style);
|
||||
if (this.props.element.backgroundImage) {
|
||||
return (React.createElement(ImageBackground, { containerStyle: cardStyle, imageStyle: {
|
||||
borderRadius: this.styleConfig.card.borderRadius,
|
||||
borderRadius: 4,
|
||||
}, 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.renderActions(),
|
||||
this.renderSubCard())));
|
||||
}
|
||||
else {
|
||||
return (React.createElement(View, { style: [cardStyle, {
|
||||
padding: this.styleConfig.card.padding,
|
||||
}] },
|
||||
return (React.createElement(View, { style: [
|
||||
cardStyle,
|
||||
{
|
||||
padding: 20,
|
||||
}
|
||||
] },
|
||||
this.renderBody(),
|
||||
this.renderActions(),
|
||||
this.renderSubCard()));
|
||||
|
@ -67,23 +70,18 @@ export class CardView extends React.Component {
|
|||
if (!this.props.element.hasBody()) {
|
||||
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() {
|
||||
if (!this.props.element.hasActions()) {
|
||||
return null;
|
||||
}
|
||||
return (React.createElement(View, { style: {
|
||||
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 }))));
|
||||
return (React.createElement(Row, { vIndex: 1, hIndex: 0, spacing: 10 }, this.props.element.actions.map((action, index) => ActionFactory.createAction(action, index, this.actionContext))));
|
||||
}
|
||||
renderSubCard() {
|
||||
if (this.state.subCard) {
|
||||
return (React.createElement(CardView, { element: this.state.subCard, style: {
|
||||
marginTop: this.styleConfig.card.spacing,
|
||||
return (React.createElement(AdaptiveCardView, { vIndex: 2, hIndex: 0, element: this.state.subCard, style: {
|
||||
marginTop: 10,
|
||||
} }));
|
||||
}
|
||||
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 { Linking, View, } from 'react-native';
|
||||
import { ActionContext } from '../Context/ActionContext';
|
||||
import { FormContext } from '../Context/FormContext';
|
||||
import { ActionContext } from '../Contexts/ActionContext';
|
||||
import { FormContext } from '../Contexts/FormContext';
|
||||
import { ActionType } from '../Schema/Base/ActionElement';
|
||||
import { CardElement } from '../Schema/Cards/Card';
|
||||
import { CardView } from './Cards/CardView';
|
||||
import { AdaptiveCardView } from './Cards/AdaptiveCard';
|
||||
export class CardRootView extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -65,6 +65,6 @@ export class CardRootView extends React.PureComponent {
|
|||
}
|
||||
render() {
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
target: target,
|
||||
};
|
||||
let hookFuncs = this.getExcuteFuncs(action.type, externalHooks);
|
||||
let hookFuncs = this.getExecuteFuncs(action.type, externalHooks);
|
||||
args = hookFuncs.reduce((prev, current) => {
|
||||
return current(prev);
|
||||
}, args);
|
||||
|
@ -75,7 +75,7 @@ export class ActionContext {
|
|||
}
|
||||
return callback;
|
||||
}
|
||||
getExcuteFuncs(actionType, externalHooks) {
|
||||
getExecuteFuncs(actionType, externalHooks) {
|
||||
let hookFuncs = [];
|
||||
if (this.hooks) {
|
||||
let hookArrays = this.hooks[actionType];
|
|
@ -1,4 +1,4 @@
|
|||
import { AbstractElement } from '../Base/AbstractElement';
|
||||
import { AbstractElement } from './AbstractElement';
|
||||
export var ActionType;
|
||||
(function (ActionType) {
|
||||
ActionType["OpenUrl"] = "Action.OpenUrl";
|
||||
|
@ -27,6 +27,9 @@ export class ActionElement extends AbstractElement {
|
|||
getData() {
|
||||
return {};
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {};
|
||||
}
|
||||
isAction() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Spacing } from '../../Shared/Enums';
|
||||
import { Utils } from '../../Shared/Utils';
|
||||
import { AbstractElement } from '../Base/AbstractElement';
|
||||
import { AbstractElement } from './AbstractElement';
|
||||
export var ContentElementType;
|
||||
(function (ContentElementType) {
|
||||
ContentElementType["Column"] = "Column";
|
||||
|
@ -31,6 +31,11 @@ export class ContentElement extends AbstractElement {
|
|||
getId() {
|
||||
return this.id;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
spacing: this.spacing
|
||||
};
|
||||
}
|
||||
isContent() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FormContext } from '../../Context/FormContext';
|
||||
import { ContentElement } from '../Base/ContentElement';
|
||||
import { FormContext } from '../../Contexts/FormContext';
|
||||
import { ActionFactory } from '../Factories/ActionFactory';
|
||||
import { ContentElement } from './ContentElement';
|
||||
export var FormElementType;
|
||||
(function (FormElementType) {
|
||||
FormElementType["Column"] = "Column";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ContentElement } from '../Base/ContentElement';
|
||||
import { ContentElement } from './ContentElement';
|
||||
export var InputElementType;
|
||||
(function (InputElementType) {
|
||||
InputElementType["TextInput"] = "Input.Text";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AbstractElement } from '../Base/AbstractElement';
|
||||
import { AbstractElement } from './AbstractElement';
|
||||
export var ValueElementType;
|
||||
(function (ValueElementType) {
|
||||
ValueElementType["Fact"] = "Fact";
|
||||
|
@ -18,4 +18,7 @@ export class ValueElement extends AbstractElement {
|
|||
isValue() {
|
||||
return true;
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,14 @@ export class ImageElement extends FormElement {
|
|||
getChildren() {
|
||||
return [];
|
||||
}
|
||||
getStyleConfig() {
|
||||
return {
|
||||
horizontalAlignment: this.horizontalAlignment,
|
||||
imgSize: this.size,
|
||||
style: this.style,
|
||||
spacing: this.spacing,
|
||||
};
|
||||
}
|
||||
setSize(size) {
|
||||
this.size = Utils.getStringEnumValueOrDefault(ImageSize, size, ImageSize.Auto);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,17 @@ export class TextBlockElement extends ContentElement {
|
|||
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() {
|
||||
return ContentElementType.TextBlock;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче