{"_id":"@brandingbrand/tcomb-form-native","_rev":"199-76a34cf25c9670aed4f2030a7a233b08","name":"@brandingbrand/tcomb-form-native","dist-tags":{"latest":"0.6.20"},"versions":{"0.6.20":{"name":"@brandingbrand/tcomb-form-native","version":"0.6.20","keywords":["tcomb","form","forms","react","react-native","react-component"],"author":{"name":"Giulio Canti","email":"giulio.canti@gmail.com"},"license":"MIT","_id":"@brandingbrand/tcomb-form-native@0.6.20","maintainers":[{"name":"danish.khalid","email":"danish.khalid@brandingbrand.com"},{"name":"jbancroft","email":"joshabancroft@gmail.com"},{"name":"alvaroloss","email":"alvaro.lossada.1992@gmail.com"},{"name":"bhushankini","email":"bhushan.kini@gmail.com"},{"name":"jhuerkamp","email":"jhuerkamp@gmail.com"},{"name":"andretodman","email":"oinsighto@mac.com"},{"name":"david.normington","email":"david.normington@arcadiagroup.co.uk"},{"name":"omarkoueifi","email":"omarokmail@gmail.com"},{"name":"zrispo","email":"zach.rispoli@gmail.com"},{"name":"cawhite","email":"corey.white.a@gmail.com"},{"name":"saurabh7693","email":"saurabhjaiswal93@gmail.com"},{"name":"sjotterman","email":"sjotterman@gmail.com"},{"name":"bb-najito","email":"nobu.ajito@brandingbrand.com"},{"name":"metprox","email":"olegvakarchuk94@gmail.com"},{"name":"erichfeinstein","email":"erichfeinstein@gmail.com"},{"name":"bb-evar","email":"evar.smith@brandingbrand.com"},{"name":"tboetto","email":"anthonyboetto@gmail.com"},{"name":"romaniukua","email":"romaniuk1511@gmail.com"},{"name":"winterss","email":"winter.nes@gmail.com"},{"name":"jeromefitz","email":"j@jeromefitzgerald.com"},{"name":"abhishek_npm","email":"abhishek.jain@brandingbrand.com"},{"name":"lhenze33","email":"lhenze3@gmail.com"},{"name":"celuchnb","email":"noah.celuch@gmail.com"},{"name":"danrudolf2","email":"dan.rudolf@brandingbrand.com"},{"name":"rosahbruno","email":"bruno.rosa@brandingbrand.com"},{"name":"huizhuz","email":"huizhuz@outlook.com"},{"name":"cboetto","email":"cmitchellboetto@gmail.com"},{"name":"branding_alex","email":"alex.risch@brandingbrand.com"},{"name":"bodrus","email":"maxshop2010@gmail.com"},{"name":"olexandor","email":"olexandor.s@gmail.com"},{"name":"anna.larionova","email":"anna.larionova@metroglobal.net"},{"name":"crherman7","email":"crherman7@gmail.com"},{"name":"sapter","email":"sam@sapter.com"},{"name":"bb_jenkins","email":"ops@brandingbrand.com"},{"name":"varzamanbb","email":"stefan.neamtu@brandingbrand.com"},{"name":"avard","email":"alexandrkorsia@gmail.com"},{"name":"olksns","email":"olksns@gmail.com"},{"name":"tim.matyas","email":"tim.matyas@brandingbrand.com"},{"name":"caleb.griffith","email":"caleb.griffith@brandingbrand.com"},{"name":"mike.lux","email":"mike.lux@brandingbrand.com"},{"name":"hearsh","email":"Hearsh.Mahidharia@brandingbrand.com"},{"name":"xero","email":"andrew.harrison@brandingbrand.com"},{"name":"bbkohsinchu","email":"kohsin.chu@brandingbrand.com"},{"name":"miraestilbb","email":"mira.estil@brandingbrand.com"},{"name":"maksymdeminbbc","email":"maksym.demin@brandingbrand.com"},{"name":"jon.ploucha","email":"jon.ploucha@brandingbrand.com"},{"name":"nathan-sankbeil","email":"nathan.sankbeil@brandingbrand.com"},{"name":"doubs","email":"david.dwornick@brandingbrand.com"},{"name":"branderbrett","email":"brett@brandingbrand.com"},{"name":"skyeckstrom","email":"npm@skyeckstrom.com"},{"name":"nickburkhartbb","email":"nick.burkhart@brandingbrand.com"},{"name":"bbtravis","email":"travis+bbtravis@brandingbrand.com"},{"name":"deemaabdallah","email":"deema.abdallah@brandingbrand.com"},{"name":"msiauko","email":"mikhail@brandingbrand.com"},{"name":"tuckerbrander","email":"tucker@brandingbrand.com"},{"name":"jasonmosleybb","email":"jason.mosley@brandingbrand.com"},{"name":"dshadrick","email":"dan.shadrick@brandingbrand.com"},{"name":"nickbb","email":"nick@brandingbrand.com"},{"name":"notajvento","email":"aj@brandingbrand.com"},{"name":"cauldrath","email":"ben@brandingbrand.com"},{"name":"andyschwob","email":"andy.schwob@brandingbrand.com"},{"name":"brad.habenicht","email":"brad.habenicht@brandingbrand.com"}],"homepage":"https://github.com/gcanti/tcomb-form-native","bugs":{"url":"https://github.com/gcanti/tcomb-form-native/issues"},"dist":{"shasum":"57c93717b5eb00f041154493503eafcf1b5022d5","tarball":"https://registry.npmjs.org/@brandingbrand/tcomb-form-native/-/tcomb-form-native-0.6.20.tgz","fileCount":21,"integrity":"sha512-yYaZbIMQMVUwqU7Sehc9uzaB4+Qpf+neHuEnR0zKdt1aveEy1kTWhEakF25SjOawvuvPBVyH7vPqv/AstGdkXw==","signatures":[{"sig":"MEYCIQC4xgJ3UeNuNO+BOyZKZMPIuvCVKe83R+oNJ/tlHneExgIhAPf5Tw0TWWYVXu5QbyQ+W21akTipVEw8moH2vBV4Zibf","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":108724,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfc5K6CRA9TVsSAnZWagAA108QAJN24Mm3xlBEw6GXHwzQ\n3tIrIfEc6NqVlvBSW6DJ/tsoZw4waEq0SCanBlNzbB4F0Hjl1ErJu5aB9+FF\nngpElz+D2XZkN3/0v4MzYGNZNqbum4bu1ACYrkqmr30MIAEo49326wY9pRpL\nQjuH2TRshfaTZxEcJq5ZSOUCrSNMyUmZPPIe2l5BzcgINTlG4qD1YxJK3HX4\ns2zLsUWmccBbFPholDJrOsPW3Tu2Q0QJNIT5WzQFgk8rIzw+9skmayJI68nN\ns+U5kNsZoHVsSbDOHWN1QICjQ+jdyEPm7EpQxElodjuN5LRqlI8o2RTWXrt1\n39+n59kpbEjk9lfUYwOMdDHVwAHOzV0TBAGUZJQGMHTjR/iiWZT/gZcknk0M\n+g0SpNdn5i3atINte4xIQT08QfJV4VcNozfpbveRv+f0oDbfANRscSYtX5DM\nKSlT9JNMDaYI5F/oZui+gcLLZyCIyMrpRiOH609TbFvi8zeMvEHyZIuSL1Sv\nTfZD/dsdGfKjSRx70vDiirpnUhjcKCQP3OTJX1UbY32rJC9rqcmAvHp+T5cK\nLpKh4pQZlOJ2FnDFl8bN87S9nda6eEF54IaJ9r80vIWHfueWfAkT2cKkMmac\nvXqduGixWq/q4rTEwt09mKw5WF2DpdQHYaF/2BRPihqVlveZgtiYrPYwUmSf\ndFz+\r\n=GGG4\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","tags":["tcomb","form","forms","react","react-native","react-component"],"gitHead":"3d5f9403a42564eb3cd05ba98d8dbd0a35acf3fc","scripts":{"lint":"eslint lib","test":"npm run lint && babel-node test"},"_npmUser":{"name":"branderbrett","email":"brett@brandingbrand.com"},"repository":{"url":"git+https://github.com/gcanti/tcomb-form-native.git","type":"git"},"_npmVersion":"6.14.4","description":"Fork of tcomb-form-native to support RN core thinning","directories":{},"_nodeVersion":"12.17.0","dependencies":{"tcomb-validation":"^3.0.0","@react-native-community/picker":"^1.8.0","@react-native-community/datetimepicker":"^3.0.2"},"_hasShrinkwrap":false,"devDependencies":{"tape":"3.5.0","babel":"5.8.34","react":"^15.6.1","eslint":"^4.19.1","prettier":"^1.7.4","babel-core":"5.8.34","prop-types":"^15.5.10","@types/prettier":"^1.7.0","eslint-plugin-react":"2.5.2","eslint-config-prettier":"^2.9.0","eslint-plugin-prettier":"^2.6.0","@types/eslint-plugin-prettier":"^2.2.0"},"peerDependencies":{"react-native":"^0.63.0"},"_npmOperationalInternal":{"tmp":"tmp/tcomb-form-native_0.6.20_1601409722334_0.10411936644674036","host":"s3://npm-registry-packages"}}},"time":{"created":"2020-09-29T20:02:02.333Z","modified":"2026-03-13T16:21:04.361Z","0.6.20":"2020-09-29T20:02:02.488Z"},"bugs":{"url":"https://github.com/gcanti/tcomb-form-native/issues"},"author":{"name":"Giulio Canti","email":"giulio.canti@gmail.com"},"license":"MIT","homepage":"https://github.com/gcanti/tcomb-form-native","keywords":["tcomb","form","forms","react","react-native","react-component"],"repository":{"url":"git+https://github.com/gcanti/tcomb-form-native.git","type":"git"},"description":"Fork of tcomb-form-native to support RN core thinning","maintainers":[{"email":"nathan.sankbeil@brandingbrand.com","name":"nathan-sankbeil"},{"email":"nick.burkhart@brandingbrand.com","name":"nickburkhartbb"},{"email":"travis+bbtravis@brandingbrand.com","name":"bbtravis"},{"email":"deema.abdallah@brandingbrand.com","name":"deemaabdallah"},{"email":"mikhail@brandingbrand.com","name":"msiauko"},{"email":"jason.mosley@brandingbrand.com","name":"jasonmosleybb"},{"email":"nick@brandingbrand.com","name":"nickbb"},{"email":"aj@brandingbrand.com","name":"notajvento"},{"email":"andrew.harrison@brandingbrand.com","name":"xero"},{"email":"stefan.neamtu@brandingbrand.com","name":"varzamanbb"},{"email":"ops@brandingbrand.com","name":"bb_jenkins"},{"email":"crherman7@gmail.com","name":"crherman7"},{"email":"johnmichael.w.riley@gmail.com","name":"jmwr"},{"email":"travis@brandingbrand.com","name":"bbtravisreadonly"}],"readme":"[![build status](https://img.shields.io/travis/gcanti/tcomb-form-native/master.svg?style=flat-square)](https://travis-ci.org/gcanti/tcomb-form-native)\n[![dependency status](https://img.shields.io/david/gcanti/tcomb-form-native.svg?style=flat-square)](https://david-dm.org/gcanti/tcomb-form-native)\n![npm downloads](https://img.shields.io/npm/dm/tcomb-form-native.svg)\n\n# Notice\n\n`tcomb-form-native` is looking for maintainers. If you're interested in helping, a great way to get started would just be to start weighing-in on [GitHub issues](https://github.com/gcanti/tcomb-form-native/issues), reviewing and testing some [PRs](https://github.com/gcanti/tcomb-form-native/pulls).\n\n# Contents\n\n- [Setup](#setup)\n- [Supported react-native versions](#supported-react-native-versions)\n- [Example](#example)\n- [API](#api)\n- [Types](#types)\n- [Rendering options](#rendering-options)\n- [Unions](#unions)\n- [Lists](#lists)\n- [Customizations](#customizations)\n- [Tests](#tests)\n- [License](#license)\n\n# Setup\n\n```\nnpm install tcomb-form-native\n```\n\n# Supported react-native versions\n\n| Version | React Native Support | Android Support | iOS Support |\n|---|---|---|---|\n| 0.5 - 0.6.1 | 0.25.0 - 0.35.0 | 7.1 | 10.0.2 |\n| 0.4 | 0.20.0 - 0.24.0 | 7.1 | 10.0.2 |\n| 0.3 | 0.1.0 - 0.13.0  | 7.1 | 10.0.2 |\n*Complies with [react-native-version-support-table](https://github.com/dangnelson/react-native-version-support-table)*\n\n### Domain Driven Forms\n\nThe [tcomb library](https://github.com/gcanti/tcomb) provides a concise but expressive way to define domain models in JavaScript.\n\nThe [tcomb-validation library](https://github.com/gcanti/tcomb-validation) builds on tcomb, providing validation functions for tcomb domain models.\n\nThis library builds on those two and the awesome react-native.\n\n### Benefits\n\nWith **tcomb-form-native** you simply call `<Form type={Model} />` to generate a form based on that domain model. What does this get you?\n\n1. Write a lot less code\n2. Usability and accessibility for free (automatic labels, inline validation, etc)\n3. No need to update forms when domain model changes\n\n### JSON Schema support\n\nJSON Schemas are also supported via the (tiny) [tcomb-json-schema library](https://github.com/gcanti/tcomb-json-schema).\n\n**Note**. Please use tcomb-json-schema ^0.2.5.\n\n### Pluggable look and feel\n\nThe look and feel is customizable via react-native stylesheets and *templates* (see documentation).\n\n### Screencast\n\nhttp://react.rocks/example/tcomb-form-native\n\n### Example App\n\n[https://github.com/bartonhammond/snowflake](https://github.com/bartonhammond/snowflake) React-Native, Tcomb, Redux, Parse.com, Jest - 88% coverage\n\n# Example\n\n```js\n// index.ios.js\n\n'use strict';\n\nvar React = require('react-native');\nvar t = require('tcomb-form-native');\nvar { AppRegistry, StyleSheet, Text, View, TouchableHighlight } = React;\n\nvar Form = t.form.Form;\n\n// here we are: define your domain model\nvar Person = t.struct({\n  name: t.String,              // a required string\n  surname: t.maybe(t.String),  // an optional string\n  age: t.Number,               // a required number\n  rememberMe: t.Boolean        // a boolean\n});\n\nvar options = {}; // optional rendering options (see documentation)\n\nvar AwesomeProject = React.createClass({\n\n  onPress: function () {\n    // call getValue() to get the values of the form\n    var value = this.refs.form.getValue();\n    if (value) { // if validation fails, value will be null\n      console.log(value); // value here is an instance of Person\n    }\n  },\n\n  render: function() {\n    return (\n      <View style={styles.container}>\n        {/* display */}\n        <Form\n          ref=\"form\"\n          type={Person}\n          options={options}\n        />\n        <TouchableHighlight style={styles.button} onPress={this.onPress} underlayColor='#99d9f4'>\n          <Text style={styles.buttonText}>Save</Text>\n        </TouchableHighlight>\n      </View>\n    );\n  }\n});\n\nvar styles = StyleSheet.create({\n  container: {\n    justifyContent: 'center',\n    marginTop: 50,\n    padding: 20,\n    backgroundColor: '#ffffff',\n  },\n  buttonText: {\n    fontSize: 18,\n    color: 'white',\n    alignSelf: 'center'\n  },\n  button: {\n    height: 36,\n    backgroundColor: '#48BBEC',\n    borderColor: '#48BBEC',\n    borderWidth: 1,\n    borderRadius: 8,\n    marginBottom: 10,\n    alignSelf: 'stretch',\n    justifyContent: 'center'\n  }\n});\n\nAppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);\n```\n\n**Output:**\n\n(Labels are automatically generated)\n\n![Result](docs/images/result.png)\n\n**Ouput after a validation error:**\n\n![Result after a validation error](docs/images/validation.png)\n\n# API\n\n## `getValue()`\n\nReturns `null` if the validation failed, an instance of your model otherwise.\n\n> **Note**. Calling `getValue` will cause the validation of all the fields of the form, including some side effects like highlighting the errors.\n\n## `validate()`\n\nReturns a `ValidationResult` (see [tcomb-validation](https://github.com/gcanti/tcomb-validation) for a reference documentation).\n\n## Adding a default value and listen to changes\n\nThe `Form` component behaves like a [controlled component](https://facebook.github.io/react/docs/forms.html):\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.maybe(t.String)\n});\n\nvar AwesomeProject = React.createClass({\n\n  getInitialState() {\n    return {\n      value: {\n        name: 'Giulio',\n        surname: 'Canti'\n      }\n    };\n  },\n\n  onChange(value) {\n    this.setState({value});\n  },\n\n  onPress: function () {\n    var value = this.refs.form.getValue();\n    if (value) {\n      console.log(value);\n    }\n  },\n\n  render: function() {\n    return (\n      <View style={styles.container}>\n        <Form\n          ref=\"form\"\n          type={Person}\n          value={this.state.value}\n          onChange={this.onChange}\n        />\n        <TouchableHighlight style={styles.button} onPress={this.onPress} underlayColor='#99d9f4'>\n          <Text style={styles.buttonText}>Save</Text>\n        </TouchableHighlight>\n      </View>\n    );\n  }\n});\n```\n\nThe `onChange` handler has the following signature:\n\n```\n(raw: any, path: Array<string | number>) => void\n```\n\nwhere\n\n- `raw` contains the current raw value of the form (can be an invalid value for your model)\n- `path` is the path to the field triggering the change\n\n> **Warning**. tcomb-form-native uses `shouldComponentUpdate` aggressively. In order to ensure that tcomb-form-native detect any change to `type`, `options` or `value` props you have to change references:\n\n## Disable a field based on another field's value\n\n```js\nvar Type = t.struct({\n  disable: t.Boolean, // if true, name field will be disabled\n  name: t.String\n});\n\n// see the \"Rendering options\" section in this guide\nvar options = {\n  fields: {\n    name: {}\n  }\n};\n\nvar AwesomeProject = React.createClass({\n\n  getInitialState() {\n    return {\n      options: options,\n      value: null\n    };\n  },\n\n  onChange(value) {\n    // tcomb immutability helpers\n    // https://github.com/gcanti/tcomb/blob/master/docs/API.md#updating-immutable-instances\n    var options = t.update(this.state.options, {\n      fields: {\n        name: {\n          editable: {'$set': !value.disable}\n        }\n      }\n    });\n    this.setState({options: options, value: value});\n  },\n\n  onPress: function () {\n    var value = this.refs.form.getValue();\n    if (value) {\n      console.log(value);\n    }\n  },\n\n  render: function() {\n    return (\n      <View style={styles.container}>\n        <Form\n          ref=\"form\"\n          type={Type}\n          options={this.state.options}\n          value={this.state.value}\n          onChange={this.onChange}\n        />\n        <TouchableHighlight style={styles.button} onPress={this.onPress} underlayColor='#99d9f4'>\n          <Text style={styles.buttonText}>Save</Text>\n        </TouchableHighlight>\n      </View>\n    );\n  }\n\n});\n```\n\n## How to get access to a field\n\nYou can get access to a field with the `getComponent(path)` API:\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.maybe(t.String),\n  age: t.Number,\n  rememberMe: t.Boolean\n});\n\nvar AwesomeProject = React.createClass({\n\n  componentDidMount() {\n    // give focus to the name textbox\n    this.refs.form.getComponent('name').refs.input.focus();\n  },\n\n  onPress: function () {\n    var value = this.refs.form.getValue();\n    if (value) {\n      console.log(value);\n    }\n  },\n\n  render: function() {\n    return (\n      <View style={styles.container}>\n        <Form\n          ref=\"form\"\n          type={Person}\n        />\n        <TouchableHighlight style={styles.button} onPress={this.onPress} underlayColor='#99d9f4'>\n          <Text style={styles.buttonText}>Save</Text>\n        </TouchableHighlight>\n      </View>\n    );\n  }\n});\n```\n\n## How to clear form after submit\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.maybe(t.String),\n  age: t.Number,\n  rememberMe: t.Boolean\n});\n\nvar AwesomeProject = React.createClass({\n\n  getInitialState() {\n    return { value: null };\n  },\n\n  onChange(value) {\n    this.setState({ value });\n  },\n\n  clearForm() {\n    // clear content from all textbox\n    this.setState({ value: null });\n  },\n\n  onPress: function () {\n    var value = this.refs.form.getValue();\n    if (value) {\n      console.log(value);\n      // clear all fields after submit\n      this.clearForm();\n    }\n  },\n\n  render: function() {\n    return (\n      <View style={styles.container}>\n        <Form\n          ref=\"form\"\n          type={Person}\n          value={this.state.value}\n          onChange={this.onChange.bind(this)}\n        />\n        <TouchableHighlight style={styles.button} onPress={this.onPress} underlayColor='#99d9f4'>\n          <Text style={styles.buttonText}>Save</Text>\n        </TouchableHighlight>\n      </View>\n    );\n  }\n});\n```\n\n## Dynamic forms example: how to change a form based on selection\n\nSay I have an iOS Picker, depending on which option is selected in this picker I want the next component to either be a checkbox or a textbox:\n\n```js\nconst Country = t.enums({\n  'IT': 'Italy',\n  'US': 'United States'\n}, 'Country');\n\nvar AwesomeProject = React.createClass({\n\n  // returns the suitable type based on the form value\n  getType(value) {\n    if (value.country === 'IT') {\n      return t.struct({\n        country: Country,\n        rememberMe: t.Boolean\n      });\n    } else if (value.country === 'US') {\n      return t.struct({\n        country: Country,\n        name: t.String\n      });\n    } else {\n      return t.struct({\n        country: Country\n      });\n    }\n  },\n\n  getInitialState() {\n    const value = {};\n    return { value, type: this.getType(value) };\n  },\n\n  onChange(value) {\n    // recalculate the type only if strictly necessary\n    const type = value.country !== this.state.value.country ?\n      this.getType(value) :\n      this.state.type;\n    this.setState({ value, type });\n  },\n\n  onPress() {\n    var value = this.refs.form.getValue();\n    if (value) {\n      console.log(value);\n    }\n  },\n\n  render() {\n\n    return (\n      <View style={styles.container}>\n        <t.form.Form\n          ref=\"form\"\n          type={this.state.type}\n          value={this.state.value}\n          onChange={this.onChange}\n        />\n        <TouchableHighlight style={styles.button} onPress={this.onPress} underlayColor='#99d9f4'>\n          <Text style={styles.buttonText}>Save</Text>\n        </TouchableHighlight>\n      </View>\n    );\n  }\n});\n```\n\n# Types\n\n### Required field\n\nBy default fields are required:\n\n```js\nvar Person = t.struct({\n  name: t.String,    // a required string\n  surname: t.String  // a required string\n});\n```\n\n### Optional field\n\nIn order to create an optional field, wrap the field type with the `t.maybe` combinator:\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.String,\n  email: t.maybe(t.String) // an optional string\n});\n```\n\nThe postfix `\" (optional)\"` is automatically added to optional fields.\n\nYou can customise the postfix value or setting a postfix for required fields:\n\n```js\nt.form.Form.i18n = {\n  optional: '',\n  required: ' (required)' // inverting the behaviour: adding a postfix to the required fields\n};\n```\n\n### Numbers\n\nIn order to create a numeric field, use the `t.Number` type:\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.String,\n  email: t.maybe(t.String),\n  age: t.Number // a numeric field\n});\n```\n\ntcomb-form-native will convert automatically numbers to / from strings.\n\n### Booleans\n\nIn order to create a boolean field, use the `t.Boolean` type:\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.String,\n  email: t.maybe(t.String),\n  age: t.Number,\n  rememberMe: t.Boolean // a boolean field\n});\n```\n\nBooleans are displayed as `SwitchIOS`s.\n\n### Dates\n\nIn order to create a date field, use the `t.Date` type:\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  surname: t.String,\n  email: t.maybe(t.String),\n  age: t.Number,\n  birthDate: t.Date // a date field\n});\n```\n\nDates are displayed as `DatePickerIOS`s under iOS and `DatePickerAndroid` or `TimePickerAndroid` under Android, depending on the `mode` selected (`date` or `time`).\n\nUnder Android, use the `fields` option to configure which `mode` to display the Picker:\n\n```js\n// see the \"Rendering options\" section in this guide\nvar options = {\n  fields: {\n    birthDate: {\n      mode: 'date' // display the Date field as a DatePickerAndroid\n    }\n  }\n};\n```\n\n#### iOS date `config` option\n\nThe bundled template will render an iOS `UIDatePicker` component, but collapsed into a touchable component in order to improve usability. A `config` object can be passed to customize it with the following parameters:\n\n| Key | Value |\n|-----|-------|\n| `animation` | The animation to collapse the date picker. Defaults to `Animated.timing`. |\n| `animationConfig` | The animation configuration object. Defaults to `{duration: 200}` for the default animation. |\n| `format` | A `(date) => String(date)` kind of function to provide a custom date format parsing to display the value. Optional, defaults to `(date) => String(date)`.\n| `defaultValueText` | An `string` to customize the default value of the `null` date value text. |\n\nFor the collapsible customization, look at the `dateTouchable` and `dateValue` keys in the stylesheet file.\n\n#### Android date `config` option\n\nWhen using a `t.Date` type in Android, it can be configured through a `config` option that take the following parameters:\n\n| Key | Value |\n|-----|-------|\n| ``background`` | Determines the type of background drawable that's going to be used to display feedback. Optional, defaults to ``TouchableNativeFeedback.SelectableBackground``. |\n| ``format`` | A ``(date) => String(date)`` kind of function to provide a custom date format parsing to display the value. Optional, defaults to ``(date) => String(date)``.\n| ``dialogMode`` | Determines the type of datepicker mode for Android (`default`, `spinner` or `calendar`). |\n| `defaultValueText` | An `string` to customize the default value of the `null` date value text. |\n\n### Enums\n\nIn order to create an enum field, use the `t.enums` combinator:\n\n```js\nvar Gender = t.enums({\n  M: 'Male',\n  F: 'Female'\n});\n\nvar Person = t.struct({\n  name: t.String,\n  surname: t.String,\n  email: t.maybe(t.String),\n  age: t.Number,\n  rememberMe: t.Boolean,\n  gender: Gender // enum\n});\n```\n\nEnums are displayed as `Picker`s.\n\n#### iOS select `config` option\n\nThe bundled template will render an iOS `UIPickerView` component, but collapsed into a touchable component in order to improve usability. A `config` object can be passed to customize it with the following parameters:\n\n| Key | Value |\n|-----|-------|\n| `animation` | The animation to collapse the date picker. Defaults to `Animated.timing`. |\n| `animationConfig` | The animation configuration object. Defaults to `{duration: 200}` for the default animation. |\n\nFor the collapsible customization, look at the `pickerContainer`, `pickerTouchable` and `pickerValue` keys in the stylesheet file.\n\n### Refinements\n\nA *predicate* is a function with the following signature:\n\n```\n(x: any) => boolean\n```\n\nYou can refine a type with the `t.refinement(type, predicate)` combinator:\n\n```js\n// a type representing positive numbers\nvar Positive = t.refinement(t.Number, function (n) {\n  return n >= 0;\n});\n\nvar Person = t.struct({\n  name: t.String,\n  surname: t.String,\n  email: t.maybe(t.String),\n  age: Positive, // refinement\n  rememberMe: t.Boolean,\n  gender: Gender\n});\n```\n\nSubtypes allow you to express any custom validation with a simple predicate.\n\n# Rendering options\n\nIn order to customize the look and feel, use an `options` prop:\n\n```js\n<Form type={Model} options={options} />\n```\n\n## Form component\n\n### Labels and placeholders\n\nBy default labels are automatically generated. You can turn off this behaviour or override the default labels\non field basis.\n\n```js\nvar options = {\n  label: 'My struct label' // <= form legend, displayed before the fields\n};\n\nvar options = {\n  fields: {\n    name: {\n      label: 'My name label' // <= label for the name field\n    }\n  }\n};\n```\n\nIn order to automatically generate default placeholders, use the option `auto: 'placeholders'`:\n\n```js\nvar options = {\n  auto: 'placeholders'\n};\n\n<Form type={Person} options={options} />\n```\n\n![Placeholders](docs/images/placeholders.png)\n\nSet `auto: 'none'` if you don't want neither labels nor placeholders.\n\n```js\nvar options = {\n  auto: 'none'\n};\n```\n\n### Fields order\n\nYou can sort the fields with the `order` option:\n\n```js\nvar options = {\n  order: ['name', 'surname', 'rememberMe', 'gender', 'age', 'email']\n};\n```\n\n### Default values\n\nYou can set the default values passing a `value` prop to the `Form` component:\n\n```js\nvar value = {\n  name: 'Giulio',\n  surname: 'Canti',\n  age: 41,\n  gender: 'M'\n};\n\n<Form type={Model} value={value} />\n```\n\n### Fields configuration\n\nYou can configure each field with the `fields` option:\n\n```js\nvar options = {\n  fields: {\n    name: {\n      // name field configuration here..\n    },\n    surname: {\n      // surname field configuration here..\n    }\n  }\n};\n```\n\n## Textbox component\n\nImplementation: `TextInput`\n\n**Tech note.** Values containing only white spaces are converted to `null`.\n\n### Placeholder\n\nYou can set the placeholder with the `placeholder` option:\n\n```js\nvar options = {\n  fields: {\n    name: {\n      placeholder: 'Your placeholder here'\n    }\n  }\n};\n```\n\n### Label\n\nYou can set the label with the `label` option:\n\n```js\nvar options = {\n  fields: {\n    name: {\n      label: 'Insert your name'\n    }\n  }\n};\n```\n\n### Help message\n\nYou can set a help message with the `help` option:\n\n```js\nvar options = {\n  fields: {\n    name: {\n      help: 'Your help message here'\n    }\n  }\n};\n```\n\n![Help](docs/images/help.png)\n\n### Error messages\n\nYou can add a custom error message with the `error` option:\n\n```js\nvar options = {\n  fields: {\n    email: {\n      // you can use strings or JSX\n      error: 'Insert a valid email'\n    }\n  }\n};\n```\n\n![Help](docs/images/error.png)\n\ntcomb-form-native will display the error message when the field validation fails.\n\n`error` can also be a function with the following signature:\n\n```\n(value, path, context) => ?(string | ReactElement)\n```\n\nwhere\n\n- `value` is an object containing the current form value.\n- `path` is the path of the value being validated\n- `context` is the value of the `context` prop. Also it contains a reference to the component options.\n\nThe value returned by the function will be used as error message.\n\nIf you want to show the error message onload, add the `hasError` option:\n\n```js\nvar options = {\n  hasError: true,\n  error: <i>A custom error message</i>\n};\n```\n\nAnother way is to add a:\n\n```\ngetValidationErrorMessage(value, path, context)\n```\n\nstatic function to a type, where:\n\n- `value` is the (parsed) current value of the component.\n- `path` is the path of the value being validated\n- `context` is the value of the `context` prop. Also it contains a reference to the component options.\n\n\n```js\nvar Age = t.refinement(t.Number, function (n) { return n >= 18; });\n\n// if you define a getValidationErrorMessage function, it will be called on validation errors\nAge.getValidationErrorMessage = function (value, path, context) {\n  return 'bad age, locale: ' + context.locale;\n};\n\nvar Schema = t.struct({\n  age: Age\n});\n\n...\n\n<t.form.Form\n  ref=\"form\"\n  type={Schema}\n  context={{locale: 'it-IT'}}\n/>\n```\n\nYou can even define `getValidationErrorMessage` on the supertype in order to be DRY:\n\n```js\nt.Number.getValidationErrorMessage = function (value, path, context) {\n  return 'bad number';\n};\n\nAge.getValidationErrorMessage = function (value, path, context) {\n  return 'bad age, locale: ' + context.locale;\n};\n```\n\n### Other standard options\n\nThe following standard options are available (see http://facebook.github.io/react-native/docs/textinput.html):\n\n- `allowFontScaling`\n- `autoCapitalize`\n- `autoCorrect`\n- `autoFocus`\n- `bufferDelay`\n- `clearButtonMode`\n- `editable`\n- `enablesReturnKeyAutomatically`\n- `keyboardType`\n- `maxLength`\n- `multiline`\n- `numberOfLines`\n- `onBlur`\n- `onEndEditing`\n- `onFocus`\n- `onSubmitEditing`\n- `onContentSizeChange`\n- `password`\n- `placeholderTextColor`\n- `returnKeyType`\n- `selectTextOnFocus`\n- `secureTextEntry`\n- `selectionState`\n- `textAlign`\n- `textAlignVertical`\n- `textContentType`\n- ~~`underlineColorAndroid`~~\n\n`underlineColorAndroid` is not supported now on `tcomb-form-native` due to random crashes on Android, especially on ScrollView. See more on:\nhttps://github.com/facebook/react-native/issues/17530#issuecomment-416367184\n\n## Checkbox component\n\nImplementation: `SwitchIOS`\n\nThe following options are similar to the `Textbox` component's ones:\n\n- `label`\n- `help`\n- `error`\n\n### Other standard options\n\nThe following standard options are available (see http://facebook.github.io/react-native/docs/switchios.html):\n\n- `disabled`\n- `onTintColor`\n- `thumbTintColor`\n- `tintColor`\n\n## Select component\n\nImplementation: `PickerIOS`\n\nThe following options are similar to the `Textbox` component's ones:\n\n- `label`\n- `help`\n- `error`\n\n### `nullOption` option\n\nYou can customize the null option with the `nullOption` option:\n\n```js\nvar options = {\n  fields: {\n    gender: {\n      nullOption: {value: '', text: 'Choose your gender'}\n    }\n  }\n};\n```\n\nYou can remove the null option setting the `nullOption` option to `false`.\n\n**Warning**: when you set `nullOption = false` you must also set the Form's `value` prop for the select field.\n\n**Tech note.** A value equal to `nullOption.value` (default `''`) is converted to `null`.\n\n### Options order\n\nYou can sort the options with the `order` option:\n\n```js\nvar options = {\n  fields: {\n    gender: {\n      order: 'asc' // or 'desc'\n    }\n  }\n};\n```\n\n### Options isCollapsed\n\nYou can determinate if Select is collapsed:\n\n```js\nvar options = {\n  fields: {\n    gender: {\n      isCollapsed: false // default: true\n    }\n  }\n};\n```\n\nIf option not set, default is `true`\n\n### Options onCollapseChange\n\nYou can set a callback, triggered, when collapse change:\n\n```js\nvar options = {\n  fields: {\n    gender: {\n      onCollapseChange: () => { console.log('collapse changed'); }\n    }\n  }\n};\n```\n\n## DatePicker component\n\nImplementation: `DatePickerIOS`\n\n### Example\n\n```js\nvar Person = t.struct({\n  name: t.String,\n  birthDate: t.Date\n});\n```\n\nThe following options are similar to the `Textbox` component's ones:\n\n- `label`\n- `help`\n- `error`\n\n### Other standard options\n\nThe following standard options are available (see http://facebook.github.io/react-native/docs/datepickerios.html):\n\n- `maximumDate`,\n- `minimumDate`,\n- `minuteInterval`,\n- `mode`,\n- `timeZoneOffsetInMinutes`\n\n## Hidden Component\n\nFor any component, you can set the field with the `hidden` option:\n\n```js\nvar options = {\n  fields: {\n    name: {\n      hidden: true\n    }\n  }\n};\n```\n\nThis will completely skip the rendering of the component, while the default value will be available for validation purposes.\n\n# Unions\n\n**Code Example**\n\n```js\nconst AccountType = t.enums.of([\n  'type 1',\n  'type 2',\n  'other'\n], 'AccountType')\n\nconst KnownAccount = t.struct({\n  type: AccountType\n}, 'KnownAccount')\n\n// UnknownAccount extends KnownAccount so it owns also the type field\nconst UnknownAccount = KnownAccount.extend({\n  label: t.String,\n}, 'UnknownAccount')\n\n// the union\nconst Account = t.union([KnownAccount, UnknownAccount], 'Account')\n\n// the final form type\nconst Type = t.list(Account)\n\nconst options = {\n  item: [ // one options object for each concrete type of the union\n    {\n      label: 'KnownAccount'\n    },\n    {\n      label: 'UnknownAccount'\n    }\n  ]\n}\n```\n\nGenerally `tcomb`'s unions require a `dispatch` implementation in order to select the suitable type constructor for a given value and this would be the key in this use case:\n\n```js\n// if account type is 'other' return the UnknownAccount type\nAccount.dispatch = value => value && value.type === 'other' ? UnknownAccount : KnownAccount\n```\n\n# Lists\n\nYou can handle a list with the `t.list` combinator:\n\n```js\nconst Person = t.struct({\n  name: t.String,\n  tags: t.list(t.String) // a list of strings\n});\n```\n\n## Items configuration\n\nTo configure all the items in a list, set the `item` option:\n\n```js\nconst Person = t.struct({\n  name: t.String,\n  tags: t.list(t.String) // a list of strings\n});\n\nconst options = {\n  fields: { // <= Person options\n    tags: {\n      item: { // <= options applied to each item in the list\n        label: 'My tag'\n      }\n    }\n  }\n});\n```\n\n## Nested structures\n\nYou can nest lists and structs at an arbitrary level:\n\n```js\nconst Person = t.struct({\n  name: t.String,\n  surname: t.String\n});\n\nconst Persons = t.list(Person);\n```\n\nIf you want to provide options for your nested structures they must be nested\nfollowing the type structure. Here is an example:\n\n```js\nconst Person = t.struct({\n  name: t.Struct,\n  position: t.Struct({\n    latitude: t.Number,\n    longitude: t.Number\n  });\n});\n\nconst options = {\n  fields: { // <= Person options\n    name: {\n        label: 'name label'\n    }\n    position: {\n        fields: {\n            // Note that latitude is not directly nested in position,\n            // but in the fields property\n            latitude: {\n                label: 'My position label'\n            }\n        }\n    }\n  }\n});\n```\n\nWhen dealing with `t.list`, make sure to declare the `fields` property inside the `item` property, as such:\n\n```js\nconst Documents = t.struct({\n  type: t.Number,\n  value: t.String\n})\n\nconst Person = t.struct({\n  name: t.Struct,\n  documents: t.list(Documents)\n});\n\nconst options = {\n  fields: {\n    name: { /*...*/ },\n    documents: {\n      item: {\n        fields: {\n          type: {\n            // Documents t.struct 'type' options\n          },\n          value: {\n            // Documents t.struct 'value' options\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n## Internationalization\n\nYou can override the default language (english) with the `i18n` option:\n\n```js\nconst options = {\n  i18n: {\n    optional: ' (optional)',\n    required: '',\n    add: 'Add',   // add button\n    remove: '✘',  // remove button\n    up: '↑',      // move up button\n    down: '↓'     // move down button\n  }\n};\n```\n\n## Buttons configuration\n\nYou can prevent operations on lists with the following options:\n\n- `disableAdd`: (default `false`) prevents adding new items\n- `disableRemove`: (default `false`) prevents removing existing items\n- `disableOrder`: (default `false`) prevents sorting existing items\n\n```js\nconst options = {\n  disableOrder: true\n};\n```\n\n## List with Dynamic Items (Different structs based on selected value)\n\nLists of different types are not supported. This is because a `tcomb`'s list, by definition, contains only values of the same type. You can define a union though:\n\n```js\nconst AccountType = t.enums.of([\n  'type 1',\n  'type 2',\n  'other'\n], 'AccountType')\n\nconst KnownAccount = t.struct({\n  type: AccountType\n}, 'KnownAccount')\n\n// UnknownAccount extends KnownAccount so it owns also the type field\nconst UnknownAccount = KnownAccount.extend({\n  label: t.String,\n}, 'UnknownAccount')\n\n// the union\nconst Account = t.union([KnownAccount, UnknownAccount], 'Account')\n\n// the final form type\nconst Type = t.list(Account)\n```\n\nGenerally `tcomb`'s unions require a `dispatch` implementation in order to select the suitable type constructor for a given value and this would be the key in this use case:\n\n```js\n// if account type is 'other' return the UnknownAccount type\nAccount.dispatch = value => value && value.type === 'other' ? UnknownAccount : KnownAccount\n```\n\n# Customizations\n\n## Stylesheets\n\nSee also [Stylesheet guide](docs/STYLESHEETS.md).\n\ntcomb-form-native comes with a default style. You can customize the look and feel by setting another stylesheet:\n\n```js\nvar t = require('tcomb-form-native/lib');\nvar i18n = require('tcomb-form-native/lib/i18n/en');\nvar templates = require('tcomb-form-native/lib/templates/bootstrap');\n\n// define a stylesheet (see lib/stylesheets/bootstrap for an example)\nvar stylesheet = {...};\n\n// override globally the default stylesheet\nt.form.Form.stylesheet = stylesheet;\n// set defaults\nt.form.Form.templates = templates;\nt.form.Form.i18n = i18n;\n```\n\nYou can also override the stylesheet locally for selected fields:\n\n```js\nvar Person = t.struct({\n  name: t.String\n});\n\nvar options = {\n  fields: {\n    name: {\n      stylesheet: myCustomStylesheet\n    }\n  }\n};\n```\n\nOr per form:\n\n```js\nvar Person = t.struct({\n  name: t.String\n});\n\nvar options = {\n  stylesheet: myCustomStylesheet\n};\n```\n\nFor a complete example see the default stylesheet https://github.com/gcanti/tcomb-form-native/blob/master/lib/stylesheets/bootstrap.js.\n\n## Templates\n\ntcomb-form-native comes with a default layout, i.e. a bunch of templates, one for each component.\nWhen changing the stylesheet is not enough, you can customize the layout by setting custom templates:\n\n```js\nvar t = require('tcomb-form-native/lib');\nvar i18n = require('tcomb-form-native/lib/i18n/en');\nvar stylesheet = require('tcomb-form-native/lib/stylesheets/bootstrap');\n\n// define the templates (see lib/templates/bootstrap for an example)\nvar templates = {...};\n\n// override globally the default layout\nt.form.Form.templates = templates;\n// set defaults\nt.form.Form.stylesheet = stylesheet;\nt.form.Form.i18n = i18n;\n```\n\nYou can also override the template locally:\n\n```js\nvar Person = t.struct({\n  name: t.String\n});\n\nfunction myCustomTemplate(locals) {\n\n  var containerStyle = {...};\n  var labelStyle = {...};\n  var textboxStyle = {...};\n\n  return (\n    <View style={containerStyle}>\n      <Text style={labelStyle}>{locals.label}</Text>\n      <TextInput style={textboxStyle} />\n    </View>\n  );\n}\n\nvar options = {\n  fields: {\n    name: {\n      template: myCustomTemplate\n    }\n  }\n};\n```\n\nA template is a function with the following signature:\n\n```\n(locals: Object) => ReactElement\n```\n\nwhere `locals` is an object contaning the \"recipe\" for rendering the input and it's built for you by tcomb-form-native.\nLet's see an example: the `locals` object passed in the `checkbox` template:\n\n```js\ntype Message = string | ReactElement\n\n{\n  stylesheet: Object, // the styles to be applied\n  hasError: boolean,  // true if there is a validation error\n  error: ?Message,    // the optional error message to be displayed\n  label: Message,     // the label to be displayed\n  help: ?Message,     // the optional help message to be displayed\n  value: boolean,     // the current value of the checkbox\n  onChange: Function, // the event handler to be called when the value changes\n  config: Object,     // an optional object to pass configuration options to the new template\n\n  ...other input options here...\n\n}\n```\n\nFor a complete example see the default template https://github.com/gcanti/tcomb-form-native/blob/master/lib/templates/bootstrap.\n\n## i18n\n\ntcomb-form-native comes with a default internationalization (English). You can change it by setting another i18n object:\n\n```js\nvar t = require('tcomb-form-native/lib');\nvar templates = require('tcomb-form-native/lib/templates/bootstrap');\n\n// define an object containing your translations (see tcomb-form-native/lib/i18n/en for an example)\nvar i18n = {...};\n\n// override globally the default i18n\nt.form.Form.i18n = i18n;\n// set defaults\nt.form.Form.templates = templates;\nt.form.Form.stylesheet = stylesheet;\n```\n\n## Transformers\n\nSay you want a search textbox which accepts a list of keywords separated by spaces:\n\n```js\nvar Search = t.struct({\n  search: t.list(t.String)\n});\n```\n\ntcomb-form by default will render the `search` field as a list. In order to render a textbox you have to override the default behaviour with the factory option:\n\n```js\nvar options = {\n  fields: {\n    search: {\n      factory: t.form.Textbox\n    }\n  }\n};\n```\n\nThere is a problem though: a textbox handle only strings so we need a way to transform a list in a string and a string in a list: a `Transformer` deals with serialization / deserialization of data and has the following interface:\n\n```js\nvar Transformer = t.struct({\n  format: t.Function, // from value to string, it must be idempotent\n  parse: t.Function   // from string to value\n});\n```\n\nA basic transformer implementation for the search textbox:\n\n```js\nvar listTransformer = {\n  format: function (value) {\n    return Array.isArray(value) ? value.join(' ') : value;\n  },\n  parse: function (str) {\n    return str ? str.split(' ') : [];\n  }\n};\n```\n\nNow you can handle lists using the transformer option:\n\n```js\n// example of initial value\nvar value = {\n  search: ['climbing', 'yosemite']\n};\n\nvar options = {\n  fields: {\n    search: {\n      factory: t.form.Textbox, // tell tcomb-react-native to use the same component for textboxes\n      transformer: listTransformer,\n      help: 'Keywords are separated by spaces'\n    }\n  }\n};\n```\n\n## Custom factories\n\nYou can pack together style, template (and transformers) in a custom component and then you can use it with the `factory` option:\n\n```js\nvar Component = t.form.Component;\n\n// extend the base Component\nclass MyComponent extends Component {\n\n  // this is the only required method to implement\n  getTemplate() {\n    // define here your custom template\n    return function (locals) {\n\n      //return ... jsx ...\n\n    };\n  }\n\n  // you can optionally override the default getLocals method\n  // it will provide the locals param to your template\n  getLocals() {\n\n    // in locals you'll find the default locals:\n    // - path\n    // - error\n    // - hasError\n    // - label\n    // - onChange\n    // - stylesheet\n    var locals = super.getLocals();\n\n    // add here your custom locals\n\n    return locals;\n  }\n\n\n}\n\n// as example of transformer: this is the default transformer for textboxes\nMyComponent.transformer = {\n  format: value => Nil.is(value) ? null : value,\n  parse: value => (t.String.is(value) && value.trim() === '') || Nil.is(value) ? null : value\n};\n\nvar Person = t.struct({\n  name: t.String\n});\n\nvar options = {\n  fields: {\n    name: {\n      factory: MyComponent\n    }\n  }\n};\n```\n\n# Tests\n\n```\nnpm test\n```\n**Note:** If you are using Jest, you will encounter an error which can\nbe fixed w/ a small change to the ```package.json```.\n\nThe error will look similiar to the following:\n```\nError: Cannot find module './datepicker' from 'index.js' at\nResolver.resolveModule\n```\n\nA completely working example ```jest``` setup is shown below w/ the\n[http://facebook.github.io/jest/docs/api.html#modulefileextensions-array-string](http://facebook.github.io/jest/docs/api.html#modulefileextensions-array-string)\nfix added:\n\n```\n  \"jest\": {\n    \"setupEnvScriptFile\": \"./node_modules/react-native/jestSupport/env.js\",\n    \"haste\": {\n      \"defaultPlatform\": \"ios\",\n      \"platforms\": [\n        \"ios\",\n        \"android\"\n      ],\n      \"providesModuleNodeModules\": [\n        \"react-native\"\n      ]\n    },\n    \"testPathIgnorePatterns\": [\n      \"/node_modules/\"\n    ],\n    \"testFileExtensions\": [\n      \"es6\",\n      \"js\"\n    ],\n    \"moduleFileExtensions\": [\n      \"js\",\n      \"json\",\n      \"es6\",\n      \"ios.js\"    <<<<<<<<<<<< this needs to be defined!\n    ],\n    \"unmockedModulePathPatterns\": [\n      \"react\",\n      \"react-addons-test-utils\",\n      \"react-native-router-flux\",\n      \"promise\",\n      \"source-map\",\n      \"key-mirror\",\n      \"immutable\",\n      \"fetch\",\n      \"redux\",\n      \"redux-thunk\",\n      \"fbjs\"\n    ],\n    \"collectCoverage\": false,\n    \"verbose\": true\n    },\n```\n\n# License\n\n[MIT](LICENSE)\n","readmeFilename":"README.md"}