diff --git a/ghost/members-auth-pages/components/EmailInput.js b/ghost/members-auth-pages/components/EmailInput.js new file mode 100644 index 0000000000..54844adce6 --- /dev/null +++ b/ghost/members-auth-pages/components/EmailInput.js @@ -0,0 +1,18 @@ +import FormInput from './FormInput'; +import { IconEmail } from './icons'; + +export default ({value, error, children, onInput, className}) => ( + + {children} + +); diff --git a/ghost/members-auth-pages/components/Form.js b/ghost/members-auth-pages/components/Form.js new file mode 100644 index 0000000000..eb11edbf78 --- /dev/null +++ b/ghost/members-auth-pages/components/Form.js @@ -0,0 +1,82 @@ +import { Component } from 'preact'; + +const states = {}; + +export default class Form extends Component { + + constructor(props) { + super(props); + const includeData = props.includeData || {}; + + if (props.bindTo) { + if (states[props.bindTo]) { + this.state = states[props.bindTo] + this.state.data = { ...this.state.data, ...includeData }; + } else { + states[props.bindTo] = this.state = { + submitted: false, + data: {...includeData} + } + } + } else { + this.state = { + submitted: false, + data: {...includeData} + } + } + } + + wrapChildren(children, data, onInput = () => {}) { + return children.map(child => { + const { bindTo } = child.attributes; + if (bindTo) { + child.attributes.value = data[bindTo]; + child.attributes.onInput = (e) => { + // This is a hack + // Preact keeps copy of the child attributes to know whether to rerender + // The state change below will for a check, and the old attributes will be reused + child.attributes.error = false; + this.setState({ + submitted: false, + data: Object.assign({}, this.state.data, { + [bindTo]: e.target.value + }) + }); + } + + if (this.state.submitted && !data[bindTo]) { + child.attributes.error = true; + } + } + return child; + }) + } + + wrapSubmit(onSubmit = () => {}, children, data) { + return (e) => { + e.preventDefault(); + + const requiredFields = children.map(c => c.attributes.bindTo).filter(x => !!x) + if (!requiredFields.some(x => !data[x])) { + onSubmit(this.state.data) + } + this.setState({ + submitted: true + }); + } + } + + render({bindTo, children, onInput, onSubmit}, state) { + if (bindTo) { + states[bindTo] = state; + } + const data = state.data; + return ( +
+
+ { this.wrapChildren(children, data, onInput) } +
+
+ ); + } +} diff --git a/ghost/members-auth-pages/components/FormFooter.js b/ghost/members-auth-pages/components/FormFooter.js new file mode 100644 index 0000000000..e802e08a28 --- /dev/null +++ b/ghost/members-auth-pages/components/FormFooter.js @@ -0,0 +1,10 @@ +export default ({title, hash, label}) => ( +
+
+

{ title }

+ + { label } + +
+
+); diff --git a/ghost/members-auth-pages/components/FormHeader.js b/ghost/members-auth-pages/components/FormHeader.js new file mode 100644 index 0000000000..551d82b059 --- /dev/null +++ b/ghost/members-auth-pages/components/FormHeader.js @@ -0,0 +1,16 @@ +import { IconError } from './icons'; + +export default ({title, error, errorText, children}) => ( +
+
+
+

{ title }

+ { children } +
+ {(error ? +
{ IconError } + {errorText} +
: "") + } +
+); diff --git a/ghost/members-auth-pages/components/FormHeaderCTA.js b/ghost/members-auth-pages/components/FormHeaderCTA.js new file mode 100644 index 0000000000..b4ddb69ca1 --- /dev/null +++ b/ghost/members-auth-pages/components/FormHeaderCTA.js @@ -0,0 +1,8 @@ +export default ({title, label, hash}) => ( +
+

{ title }

+ + { label } + +
+); diff --git a/ghost/members-auth-pages/components/FormInput.js b/ghost/members-auth-pages/components/FormInput.js new file mode 100644 index 0000000000..9d4f4f155f --- /dev/null +++ b/ghost/members-auth-pages/components/FormInput.js @@ -0,0 +1,23 @@ +export default ({type, name, placeholder, value = '', error, onInput, required, className, children, icon}) => ( +
+
+ onInput(e, name) } + required={ required } + className={[ + (value ? "gm-input-filled" : ""), + (error ? "gm-error" : ""), + className + ].join(' ')} + /> + + { icon } + { children } +
+
+); diff --git a/ghost/members-auth-pages/components/FormSubmit.js b/ghost/members-auth-pages/components/FormSubmit.js new file mode 100644 index 0000000000..8b200be734 --- /dev/null +++ b/ghost/members-auth-pages/components/FormSubmit.js @@ -0,0 +1,7 @@ +export default ({onClick, label}) => ( +
+ +
+); diff --git a/ghost/members-auth-pages/components/MembersProvider.js b/ghost/members-auth-pages/components/MembersProvider.js new file mode 100644 index 0000000000..0331d3e900 --- /dev/null +++ b/ghost/members-auth-pages/components/MembersProvider.js @@ -0,0 +1,54 @@ +import { Component } from 'preact'; + +const layer0 = require('../layer0'); + +export default class MembersProvider extends Component { + constructor() { + super(); + this.setGatewayFrame = gatewayFrame => this.gatewayFrame = gatewayFrame; + this.gateway = null; + } + + getChildContext() { + return { + members: { + createSubscription: this.createMethod('createSubscription'), + signin: this.createMethod('signin'), + signup: this.createMethod('signup'), + requestPasswordReset: this.createMethod('requestPasswordReset'), + resetPassword: this.createMethod('resetPassword') + } + }; + } + + render({apiUrl, children}) { + const src = `${apiUrl}/members/gateway`; + return ( +
+ { children } +