├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── docs ├── build │ ├── 0.33333f40.js │ └── bundle.890bee4f.js ├── images │ └── sample.png └── index.html ├── example ├── .babelrc ├── index.html ├── index.js ├── package.json └── webpack.config.js ├── package.json ├── src ├── compare.js ├── index.js └── index.md ├── styleguide.config.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "react", 5 | "stage-0" 6 | ], 7 | "plugins": [ 8 | "transform-class-properties", 9 | "transform-decorators", 10 | "transform-react-constant-elements", 11 | "transform-react-inline-elements" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/node_modules -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "standard", 5 | "standard-react" 6 | ], 7 | "rules": { 8 | "key-spacing": 0, 9 | "jsx-quotes": [ 10 | 2, 11 | "prefer-single" 12 | ], 13 | "object-curly-spacing": [ 14 | 2, 15 | "always" 16 | ], 17 | "react/prefer-stateless-function": 0, 18 | "react/self-closing-comp": 0, 19 | "node/no-deprecated-api": 1, 20 | "node/no-missing-import": 2, 21 | "node/no-missing-require": 2 22 | }, 23 | "plugins": [ 24 | "babel", 25 | "react", 26 | "promise", 27 | "node" 28 | ], 29 | "env": { 30 | "browser": true 31 | } 32 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | package-lock.json 61 | lib -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | example 3 | src -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Gateway Apps 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-adaptivecards 2 | A react wrapper for [microsoft/adaptivecards](https://adaptivecards.io) 3 | 4 | ![](https://gatewayapps.github.io/react-adaptivecards/images/sample.png "Adaptive Cards") 5 | 6 | 7 | ### Installation 8 | ```js static 9 | npm install --save react-adaptivecards 10 | ``` 11 | 12 | ### Usage 13 | ```js static 14 | import AdaptiveCard from 'react-adaptivecards' 15 | ``` 16 | 17 | ### React-AdaptiveCard sample 18 | ```js 19 | 79 | ``` 80 | 81 | ### Sample Card Payload 82 | ```json 83 | { 84 | "type": "AdaptiveCard", 85 | "version": "1.0", 86 | "body": [ 87 | { 88 | "type": "TextBlock", 89 | "text": "Here is a ninja cat" 90 | }, 91 | { 92 | "type": "Image", 93 | "url": "http://adaptivecards.io/content/cats/1.png" 94 | } 95 | ] 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /docs/images/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gatewayapps/react-adaptivecards/b2303729c983f0a7e58bd00b4a6a045cf66ee301/docs/images/sample.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Adaptivecards Style Guide 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "react", 5 | "stage-0" 6 | ], 7 | "plugins": [ 8 | "transform-class-properties", 9 | "transform-decorators", 10 | "transform-react-constant-elements", 11 | "transform-react-inline-elements" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | React - Adaptive Cards Example 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from 'react-dom' 3 | import AdaptiveCard from '../src' 4 | 5 | // Author a card 6 | // In practice you'll probably get this from a service 7 | // see http://adaptivecards.io/samples/ for inspiration 8 | var card = { 9 | 'type': 'AdaptiveCard', 10 | 'version': '1.0', 11 | 'body': [ 12 | { 13 | 'type': 'TextBlock', 14 | 'text': 'Your registration is almost complete', 15 | 'size': 'medium', 16 | 'weight': 'bolder' 17 | }, 18 | { 19 | 'type': 'TextBlock', 20 | 'text': 'What type of food do you prefer?', 21 | 'wrap': true 22 | }, 23 | { 24 | 'type': 'ImageSet', 25 | 'imageSize': 'medium', 26 | 'images': [ 27 | { 28 | 'type': 'Image', 29 | 'url': 'http://contososcubabot.azurewebsites.net/assets/steak.jpg' 30 | }, 31 | { 32 | 'type': 'Image', 33 | 'url': 'http://contososcubabot.azurewebsites.net/assets/chicken.jpg' 34 | }, 35 | { 36 | 'type': 'Image', 37 | 'url': 'http://contososcubabot.azurewebsites.net/assets/tofu.jpg' 38 | } 39 | ] 40 | } 41 | ], 42 | 'actions': [ 43 | { 44 | 'type': 'Action.ShowCard', 45 | 'title': 'Steak', 46 | 'card': { 47 | 'type': 'AdaptiveCard', 48 | 'body': [ 49 | { 50 | 'type': 'TextBlock', 51 | 'text': 'How would you like your steak prepared?', 52 | 'size': 'medium', 53 | 'wrap': true 54 | }, 55 | { 56 | 'type': 'Input.ChoiceSet', 57 | 'id': 'SteakTemp', 58 | 'style': 'expanded', 59 | 'choices': [ 60 | { 61 | 'title': 'Rare', 62 | 'value': 'rare' 63 | }, 64 | { 65 | 'title': 'Medium-Rare', 66 | 'value': 'medium-rare' 67 | }, 68 | { 69 | 'title': 'Well-done', 70 | 'value': 'well-done' 71 | } 72 | ] 73 | }, 74 | { 75 | 'type': 'Input.Text', 76 | 'id': 'SteakOther', 77 | 'isMultiline': true, 78 | 'placeholder': 'Any other preparation requestes?' 79 | } 80 | ], 81 | 'actions': [ 82 | { 83 | 'type': 'Action.Submit', 84 | 'title': 'OK', 85 | 'data': { 86 | 'FoodChoice': 'Steak' 87 | } 88 | } 89 | ] 90 | } 91 | }, 92 | { 93 | 'type': 'Action.ShowCard', 94 | 'title': 'Chicken', 95 | 'card': { 96 | 'type': 'AdaptiveCard', 97 | 'body': [ 98 | { 99 | 'type': 'TextBlock', 100 | 'text': 'Do you have any allergies?', 101 | 'size': 'medium', 102 | 'wrap': true 103 | }, 104 | { 105 | 'type': 'Input.ChoiceSet', 106 | 'id': 'ChickenAllergy', 107 | 'style': 'expanded', 108 | 'isMultiSelect': true, 109 | 'choices': [ 110 | { 111 | 'title': "I'm allergic to peanuts", 112 | 'value': 'peanut' 113 | } 114 | ] 115 | }, 116 | { 117 | 'type': 'Input.Text', 118 | 'id': 'ChickenOther', 119 | 'isMultiline': true, 120 | 'placeholder': 'Any other preparation requestes?' 121 | } 122 | ], 123 | 'actions': [ 124 | { 125 | 'type': 'Action.Submit', 126 | 'title': 'OK', 127 | 'data': { 128 | 'FoodChoice': 'Chicken' 129 | } 130 | } 131 | ] 132 | } 133 | }, 134 | { 135 | 'type': 'Action.ShowCard', 136 | 'title': 'Tofu', 137 | 'card': { 138 | 'type': 'AdaptiveCard', 139 | 'body': [ 140 | { 141 | 'type': 'TextBlock', 142 | 'text': 'Would you like it prepared vegan?', 143 | 'size': 'medium', 144 | 'wrap': true 145 | }, 146 | { 147 | 'type': 'Input.Toggle', 148 | 'id': 'Vegetarian', 149 | 'title': 'Please prepare it vegan', 150 | 'valueOn': 'vegan', 151 | 'valueOff': 'notVegan' 152 | }, 153 | { 154 | 'type': 'Input.Text', 155 | 'id': 'VegOther', 156 | 'isMultiline': true, 157 | 'placeholder': 'Any other preparation requestes?' 158 | } 159 | ], 160 | 'actions': [ 161 | { 162 | 'type': 'Action.Submit', 163 | 'title': 'OK', 164 | 'data': { 165 | 'FoodChoice': 'Vegetarian' 166 | } 167 | } 168 | ] 169 | } 170 | } 171 | ] 172 | } 173 | 174 | const App = () => ( 175 |
176 |

React - Adaptive Cards Example

177 | 178 | 185 |
186 | ) 187 | 188 | render( 189 | , 190 | document.getElementById('root') 191 | ) 192 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-adaptivecards-example", 3 | "private": true, 4 | "version": "0.0.0", 5 | "description": "React-AdaptiveCards example", 6 | "scripts": { 7 | "start": "webpack-dev-server --hot --inline --progress --colors --port 8886" 8 | }, 9 | "babel": { 10 | "presets": [ 11 | "env", 12 | "react", 13 | "stage-0" 14 | ] 15 | }, 16 | "authors": [ 17 | "Daniel Gary " 18 | ], 19 | "license": "MIT", 20 | "devDependencies": { 21 | "babel-cli": "^6.10.1", 22 | "babel-core": "^6.10.4", 23 | "babel-env": "^2.4.1", 24 | "babel-loader": "^7.1.2", 25 | "babel-preset-react": "^6.5.0", 26 | "babel-preset-stage-0": "^6.5.0", 27 | "copy-webpack-plugin": "~4.2.3", 28 | "file-loader": "^1.1.5", 29 | "react-hot-loader": "^3.1.3", 30 | "rimraf": "^2.5.2", 31 | "webpack": "^3.8.1", 32 | "webpack-dev-server": "^2.9.4" 33 | }, 34 | "dependencies": { 35 | "adaptivecards": "^1.0.0", 36 | "react": "~16.0.0", 37 | "react-adaptivecards": "^0.1.1", 38 | "react-dom": "^16.0.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | 3 | const path = require('path') 4 | 5 | module.exports = { 6 | entry: './index.js', 7 | output: { 8 | path: path.join(__dirname, './lib/t'), 9 | filename: 'index.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.html$/, 15 | use: ['file?name=[name].[ext]'] 16 | }, 17 | { 18 | test: /\.(js|jsx)$/, 19 | exclude: /node_modules/, 20 | use: [{ loader: 'react-hot-loader/webpack' }, { loader: 'babel-loader' }] 21 | } 22 | ] 23 | }, 24 | resolve: { 25 | extensions: ['.js', '.json'], 26 | alias: { 'react-adaptivecards': '../src' } 27 | }, 28 | plugins: [ 29 | new webpack.HotModuleReplacementPlugin(), 30 | new webpack.LoaderOptionsPlugin({ debug: true }), 31 | new webpack.SourceMapDevToolPlugin({ exclude: /node_modules/ }), 32 | new webpack.DefinePlugin({ 33 | 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') } 34 | }) 35 | ], 36 | devServer: { contentBase: './' } 37 | } 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-adaptivecards", 3 | "version": "0.1.3", 4 | "description": "A react wrapper for microsoft/adaptive-cards", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "babel src --out-dir dist", 8 | "clean": "rimraf lib dist coverage", 9 | "lint": "eslint --fix src && eslint --fix example", 10 | "prepublish": "npm run styleguide:build", 11 | "styleguide": "styleguidist server", 12 | "styleguide:build": "styleguidist build" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/gatewayapps/react-adaptivecards.git" 17 | }, 18 | "babel": { 19 | "presets": [ 20 | "env", 21 | "react", 22 | "stage-0" 23 | ] 24 | }, 25 | "keywords": [ 26 | "react", 27 | "adaptivecards", 28 | "adaptive", 29 | "cards" 30 | ], 31 | "author": "Daniel Gary ", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/gatewayapps/react-adaptivecards/issues" 35 | }, 36 | "homepage": "https://github.com/gatewayapps/react-adaptivecards#readme", 37 | "devDependencies": { 38 | "babel-cli": "^6.26.0", 39 | "babel-core": "^6.26.0", 40 | "babel-env": "^2.4.1", 41 | "babel-eslint": "^8.2.2", 42 | "babel-loader": "^7.1.2", 43 | "babel-preset-react": "^6.24.1", 44 | "eslint": "^4.18.2", 45 | "eslint-config-standard": "^11.0.0", 46 | "eslint-config-standard-react": "^6.0.0", 47 | "eslint-plugin-babel": "^4.1.2", 48 | "eslint-plugin-import": "^2.9.0", 49 | "eslint-plugin-node": "^6.0.1", 50 | "eslint-plugin-promise": "^3.7.0", 51 | "eslint-plugin-react": "^7.7.0", 52 | "eslint-plugin-standard": "^3.0.1", 53 | "pre-commit": "^1.2.2", 54 | "react": "^16.2.0", 55 | "react-dom": "^16.2.0", 56 | "react-styleguidist": "^6.2.7", 57 | "rimraf": "^2.6.2", 58 | "webpack": "^3.11.0", 59 | "webpack-blocks": "^1.0.0-rc.2" 60 | }, 61 | "peerDependencies": { 62 | "react": "^15.x || ^16.x" 63 | }, 64 | "dependencies": { 65 | "adaptivecards": "^1.0.0", 66 | "prop-types": "^15.6.1" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/compare.js: -------------------------------------------------------------------------------- 1 | // Javascript Deep Compare function compliments of Jean Vincent 2 | // https://stackoverflow.com/a/6713782/4279849 3 | 4 | export default function compare (a, b) { 5 | if (a === b) return true 6 | // if both a and b are null or undefined and exactly the same 7 | 8 | if (!(a instanceof Object) || !(b instanceof Object)) return false 9 | // if they are not strictly equal, they both need to be Objects 10 | 11 | if (a.constructor !== b.constructor) return false 12 | // they must have the exact same prototype chain, the closest we can do is 13 | // test there constructor. 14 | 15 | for (var p in a) { 16 | if (!a.hasOwnProperty(p)) continue 17 | // other properties were tested using a.constructor === b.constructor 18 | 19 | if (!b.hasOwnProperty(p)) return false 20 | // allows to compare a[ p ] and b[ p ] when set to undefined 21 | 22 | if (a[ p ] === b[ p ]) continue 23 | // if they have the same strict value or identity then they are equal 24 | 25 | if (typeof (a[ p ]) !== 'object') return false 26 | // Numbers, Strings, Functions, Booleans must be strictly equal 27 | 28 | if (!compare(a[ p ], b[ p ])) return false 29 | // Objects and Arrays must be tested recursively 30 | } 31 | 32 | for (p in b) { 33 | if (b.hasOwnProperty(p) && !a.hasOwnProperty(p)) return false 34 | // allows a[ p ] to be set to undefined 35 | } 36 | return true 37 | } 38 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import * as AdaptiveCards from 'adaptivecards' 2 | import React from 'react' 3 | import PropTypes from 'prop-types' 4 | import compare from './compare' 5 | 6 | const ACTION_OPEN_URL = 'Action.OpenUrl' 7 | const ACTION_SHOW_CARD = 'Action.ShowCard' 8 | const ACTION_SUBMIT = 'Action.Submit' 9 | 10 | export default class AdaptiveCard extends React.Component { 11 | static propTypes = { 12 | /** The hostConfig object that is passed along to the native AdaptiveCards. [More Info](https://docs.microsoft.com/en-us/adaptive-cards/display/hostconfig) */ 13 | hostConfig: PropTypes.object, 14 | /** The card schema. It must comply with the card schema. [More Info](https://docs.microsoft.com/en-us/adaptive-cards/create/cardschema) */ 15 | payload: PropTypes.object.isRequired, 16 | /** Method that will be invoked anytime a card action is executed. [More Info](https://docs.microsoft.com/en-us/adaptive-cards/display/implementingrenderer#actions) */ 17 | onExecuteAction: PropTypes.func, 18 | /** Method that will be invoked when a Submit action is executed. [More Info](https://docs.microsoft.com/en-us/adaptive-cards/display/implementingrenderer#actionsubmit) */ 19 | onActionSubmit: PropTypes.func, 20 | /** Method that will be invoked when an Open Url action is executed. [More Info](https://docs.microsoft.com/en-us/adaptive-cards/display/implementingrenderer#actionopenurl) */ 21 | onActionOpenUrl: PropTypes.func, 22 | /** Method that will be invoked when a Show Card action is executed. [More Info](https://docs.microsoft.com/en-us/adaptive-cards/display/implementingrenderer#actionshowcard) */ 23 | onActionShowCard: PropTypes.func, 24 | /** Method that will be invoked if an error is thrown while trying to render a card. */ 25 | onError: PropTypes.func, 26 | /** JSX styles that will be applied to the card conatiner */ 27 | style: PropTypes.object 28 | } 29 | constructor (props) { 30 | super(props) 31 | // Create this in the constructor so we don't create it every render 32 | this.adaptiveCard = new AdaptiveCards.AdaptiveCard() 33 | } 34 | 35 | componentWillUnmount () { 36 | // Remove all references 37 | delete this.adaptiveCard 38 | } 39 | 40 | shouldComponentUpdate (nextProps) { 41 | if (compare(nextProps.hostConfig, this.props.hostConfig)) { 42 | return true 43 | } 44 | if (compare(nextProps.payload, this.props.payload)) { 45 | return true 46 | } 47 | if (compare(nextProps.onExecuteAction, this.props.onExecuteAction)) { 48 | return true 49 | } 50 | return false 51 | } 52 | 53 | executeAction (a) { 54 | const type = a.getJsonTypeName() 55 | switch (type) { 56 | case ACTION_OPEN_URL: { 57 | if (this.props.onActionOpenUrl) { 58 | this.props.onActionOpenUrl(a) 59 | } else { 60 | this.defaultOpenUrlHandler(a) 61 | } 62 | 63 | break 64 | } 65 | case ACTION_SHOW_CARD: { 66 | if (this.props.onActionShowCard) { 67 | this.props.onActionShowCard(a) 68 | } 69 | break 70 | } 71 | case ACTION_SUBMIT: { 72 | if (this.props.onActionSubmit) { 73 | this.props.onActionSubmit(a) 74 | } 75 | break 76 | } 77 | } 78 | if (this.props.onExecuteAction) { 79 | this.props.onExecuteAction(a) 80 | } 81 | } 82 | 83 | defaultOpenUrlHandler (action) { 84 | window.open(action.url, action.title || '_blank') 85 | } 86 | 87 | render () { 88 | if (this.props.hostConfig) { 89 | this.adaptiveCard.hostConfig = new AdaptiveCards.HostConfig(this.props.hostConfig) 90 | } 91 | this.adaptiveCard.onExecuteAction = this.executeAction.bind(this) 92 | 93 | try { 94 | this.adaptiveCard.parse(this.props.payload) 95 | const result = this.adaptiveCard.render() 96 | return
{ 97 | n && n.firstChild && n.removeChild(n.firstChild); 98 | n && n.appendChild(result); 99 | }} /> 100 | } catch (err) { 101 | console.error(err) 102 | if (this.props.onError) { 103 | return this.props.onError(err) 104 | } else { 105 | return
{err.message}
106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | ### About Adaptive Cards 2 | Adaptive Cards are a new way for developers to exchange card content in a common and consistent way. Find out more at https://adaptivecards.io 3 | 4 | ### Installation 5 | ```js static 6 | npm install --save react-adaptivecards 7 | ``` 8 | 9 | ### Usage 10 | ```js static 11 | import AdaptiveCard from 'react-adaptivecards' 12 | ``` 13 | 14 | ### React-AdaptiveCard sample 15 | ```js 16 | 76 | ``` 77 | 78 | ### Sample Card Payload 79 | ```json 80 | { 81 | "type": "AdaptiveCard", 82 | "version": "1.0", 83 | "body": [ 84 | { 85 | "type": "TextBlock", 86 | "text": "Here is a ninja cat" 87 | }, 88 | { 89 | "type": "Image", 90 | "url": "http://adaptivecards.io/content/cats/1.png" 91 | } 92 | ] 93 | } 94 | ``` -------------------------------------------------------------------------------- /styleguide.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | components: 'src/index.js', 5 | webpackConfig: require('./webpack.config.js'), 6 | styleguideComponents: { 7 | AdaptiveCard: './src' 8 | }, 9 | styleguideDir: './docs' 10 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | 3 | const path = require('path') 4 | 5 | module.exports = { 6 | entry: './index.js', 7 | output: { 8 | path: path.join(__dirname, './lib/t'), 9 | filename: 'index.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.html$/, 15 | use: ['file?name=[name].[ext]'] 16 | }, 17 | { 18 | test: /\.(js|jsx)$/, 19 | exclude: /node_modules/, 20 | use: [ { loader: 'babel-loader' }] 21 | } 22 | ] 23 | }, 24 | resolve: { 25 | extensions: ['.js', '.json'], 26 | alias: { 'react-adaptivecards': '../src' } 27 | }, 28 | plugins: [ 29 | 30 | new webpack.LoaderOptionsPlugin({ debug: true }), 31 | new webpack.SourceMapDevToolPlugin({ exclude: /node_modules/ }), 32 | new webpack.DefinePlugin({ 33 | 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') } 34 | }) 35 | ], 36 | devServer: { contentBase: './' } 37 | } 38 | --------------------------------------------------------------------------------