import React from 'react'; import ReactDOM from 'react-dom'; import '../src/genfun_formatter'; import { Receipt } from './render'; import * as m from './Model'; import * as gf from '../src/genfuns'; const Editable = gf.defgeneric("Editable", "props") .around([Object], function (_) { return <div style={{ display: 'inline-block' }}>{this.call_next_method()} </div> }) .primary([gf.Shape("label", "htmlFor")], ({ label, htmlFor }) => <label {...{htmlFor}}>{label}</label>) .primary([gf.Shape("label", "htmlFor", "value")], function ({ value, onChange }) { return <> {this.call_next_method()} {onChange ? null : <span> {value}</span>} </> }) .primary([gf.Shape("label", "htmlFor", "value", "onChange")], function ({ value, htmlFor, onChange }) { return <> {this.call_next_method()} <input type="text" value={value} id={htmlFor} name={htmlFor} onChange={onChange}></input> </> }) .fn; class Field extends React.Component { constructor(props) { super(); this.state = { editing: false, val: props.value }; } click() { this.setState(() => ({ editing: !this.state.editing, val: this.state.val })); } onChange(e) { const val = e.target.value; this.setState(() => ({ editing: true, val })) } render() { const editingProps = {}; if (this.state.editing) { editingProps.onChange = this.onChange.bind(this); } return <div> <Editable {...this.props} {...editingProps} value={this.state.val} /> <button onClick={this.click.bind(this)}>Toggle</button> </div> } } ReactDOM.render( <div> <Field label="the field" htmlFor="the-field" value="foo" /> <Editable label="bazquuxes" htmlFor="bazquux" value="foo" display /> <Editable label="bazquuxes" htmlFor="bazquux" value="foo" editable /> <Receipt items={[ new m.AlcoholicBeverage(11), new m.AlcoholicBeverage(12), new m.AlcoholicBeverage(13), new m.NormalFood(11), new m.NonFood(11), new m.AlcoholicBeverage(10) ]} /> </div>, document.querySelector('main'), () => { console.log('rendered'); } );