UNPKG

react-saasify-chrisvxd

Version:

React components for Saasify web clients.

1,554 lines (1,350 loc) 101 kB
import React, { Component, Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; import { inject, observer } from 'mobx-react'; import { Redirect, Route, withRouter, Link as Link$2 } from 'react-router-dom'; import { observable, autorun, trace, toJS, decorate, computed, reaction } from 'mobx'; import cs from 'classnames'; import cv from 'css-var'; import codeTheme from 'react-syntax-highlighter/dist/esm/styles/hljs/vs2015'; import 'antd/es/avatar/style/css'; import 'antd/es/button/style/css'; import 'antd/es/checkbox/style/css'; import 'antd/es/divider/style/css'; import 'antd/es/form/style/css'; import 'antd/es/icon/style/css'; import 'antd/es/input/style/css'; import 'antd/es/modal/style/css'; import 'antd/es/popconfirm/style/css'; import 'antd/es/result/style/css'; import 'antd/es/steps/style/css'; import 'antd/es/tag/style/css'; import 'antd/es/tooltip/style/css'; import 'antd/es/table/style/css'; import 'antd/es/message/style/css'; import 'antd/es/notification/style/css'; import Avatar from 'antd/es/avatar'; export { default as Avatar } from 'antd/es/avatar'; import Button from 'antd/es/button'; export { default as Button } from 'antd/es/button'; import Checkbox from 'antd/es/checkbox'; export { default as Checkbox } from 'antd/es/checkbox'; import Divider from 'antd/es/divider'; export { default as Divider } from 'antd/es/divider'; import Form from 'antd/es/form'; export { default as Form } from 'antd/es/form'; import Icon from 'antd/es/icon'; export { default as Icon } from 'antd/es/icon'; import Input from 'antd/es/input'; export { default as Input } from 'antd/es/input'; import Modal from 'antd/es/modal'; export { default as Modal } from 'antd/es/modal'; import Popconfirm from 'antd/es/popconfirm'; export { default as Popconfirm } from 'antd/es/popconfirm'; export { default as Result } from 'antd/es/result'; export { default as Steps } from 'antd/es/steps'; import Tag from 'antd/es/tag'; export { default as Tag } from 'antd/es/tag'; import Tooltip from 'antd/es/tooltip'; export { default as Tooltip } from 'antd/es/tooltip'; import Table from 'antd/es/table'; export { default as Table } from 'antd/es/table'; import message from 'antd/es/message'; export { default as message } from 'antd/es/message'; import notification from 'antd/es/notification'; export { default as notification } from 'antd/es/notification'; import qs from 'qs'; import _debug from 'debug'; import { StripeProvider, Elements, injectStripe, CardElement } from 'react-stripe-elements'; import raf from 'raf'; import Hoverable from 'react-event-as-prop/lib/Hoverable'; import slugify from '@sindresorhus/slugify'; import copyTextToClipboard from 'copy-text-to-clipboard'; import { format } from 'date-fns'; import SaasifyClient from 'saasify-client'; import titleize from 'titleize'; import Colr from 'colr'; import random from 'random'; import sizeMe from 'react-sizeme'; import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/light'; import defaultCodeTheme from 'react-syntax-highlighter/dist/esm/styles/hljs/tomorrow'; import js from 'react-syntax-highlighter/dist/esm/languages/hljs/javascript'; import python from 'react-syntax-highlighter/dist/esm/languages/hljs/python'; import ruby from 'react-syntax-highlighter/dist/esm/languages/hljs/ruby'; import bash from 'react-syntax-highlighter/dist/esm/languages/hljs/bash'; import mem from 'mem'; import getServiceExamples from 'saasify-codegen'; import ReactMarkdown from 'react-markdown'; import ReactBackgroundSlideshow from 'react-background-slideshow'; import localforage from 'localforage'; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); } function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; } var _dec, _class, _class2, _temp; var AuthenticatedRoute = (_dec = inject('auth'), _dec(_class = observer(_class = (_temp = _class2 = /*#__PURE__*/ function (_Component) { _inheritsLoose(AuthenticatedRoute, _Component); function AuthenticatedRoute() { return _Component.apply(this, arguments) || this; } var _proto = AuthenticatedRoute.prototype; _proto.render = function render() { var _this$props = this.props, Component = _this$props.component, redirect = _this$props.redirect, auth = _this$props.auth, rest = _objectWithoutPropertiesLoose(_this$props, ["component", "redirect", "auth"]); if (!auth.isAuthenticated) { return h(Redirect, { to: { pathname: redirect } }); } return h(Route, _extends({}, rest, { render: function render(props) { return auth.isAuthenticated ? h(Component, props) : h(Redirect, { to: { pathname: redirect, state: { from: props.location } } }); } })); }; return AuthenticatedRoute; }(Component), _class2.propTypes = { component: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).isRequired, auth: PropTypes.object.isRequired, redirect: PropTypes.string }, _class2.defaultProps = { redirect: '/login' }, _temp)) || _class) || _class); var styles = {"section":"okta-module_section__3C6V-","title":"okta-module_title__7O1oG","subtitle":"okta-module_subtitle__2pQn3","content":"okta-module_content__LUjyp","theme-okta":"okta-module_theme-okta__iN0o9","light":"okta-module_light__2w-1n","header":"okta-module_header__1WlW3","link":"okta-module_link___U-L6","detail":"okta-module_detail__2hQvP","cta-button":"okta-module_cta-button__qGo57"}; var okta = function okta(opts) { if (opts === void 0) { opts = {}; } return _extends({}, styles, { '@name': 'okta', '@section-fg-color': '#23303a', '@section-bg-color': '#1e3a54', '@primary-color': '#d23d67' }, opts); }; var styles$1 = {"theme-sadie":"sadie-module_theme-sadie__3l09s","logo":"sadie-module_logo__2UDtj"}; var sadie = function sadie(opts) { if (opts === void 0) { opts = {}; } return _extends({}, styles$1, { '@name': 'sadie', '@section-fg-color': '#ffe2e2', '@section-bg-color': '#f6f6f6' }, opts, { fonts: ['Manjari'] }); }; var styles$2 = {"theme-waves":"waves-module_theme-waves__1n8ID","paper":"waves-module_paper__2gGTy","section":"waves-module_section__1rcZB","title":"waves-module_title__187d7","subtitle":"waves-module_subtitle__TrWkk","content":"waves-module_content__1Ajv_","section-divider":"waves-module_section-divider__JORu2","home-page":"waves-module_home-page__HehpF","hero-section":"waves-module_hero-section__1oUVj","demo-section":"waves-module_demo-section__110gv","desc":"waves-module_desc__2-xxF","features-section":"waves-module_features-section__Wh5oo","features":"waves-module_features__1tipn","feature":"waves-module_feature__IEwpV","illustration":"waves-module_illustration__3Fh40","pricing-page":"waves-module_pricing-page__2vWtL","pricing-section":"waves-module_pricing-section__5n2kB","checkout-page":"waves-module_checkout-page__2QBVi","form":"waves-module_form__1QVzc","plan":"waves-module_plan__2TiGz","login-page":"waves-module_login-page__1pI2a","signup-page":"waves-module_signup-page__h7p2D","submit":"waves-module_submit__1SnXA","dashboard-page":"waves-module_dashboard-page__tKTN_","dashboard-section":"waves-module_dashboard-section__8-Qin","onboarding-section":"waves-module_onboarding-section__YtEao","container":"waves-module_container__2oeV_","links":"waves-module_links__28bbL","link":"waves-module_link__2JCo9","actions":"waves-module_actions__3tNt_","attached":"waves-module_attached__3LC-8","logo":"waves-module_logo__1Gh94","logo-text":"waves-module_logo-text__vkHFQ","expanded":"waves-module_expanded__2X-st","cta-button":"waves-module_cta-button__20BxY","detail":"waves-module_detail__2I0uM","header":"waves-module_header__1_jJS","inline":"waves-module_inline__3_KjR","live-service-demo":"waves-module_live-service-demo__31IVr","tabs":"waves-module_tabs__3Eu3q","tab":"waves-module_tab__1-Vh0","selected-tab":"waves-module_selected-tab__1plbx","tab-content":"waves-module_tab-content__3K5QX","code-block":"waves-module_code-block__3mKWM","info":"waves-module_info__1fGpA","copy":"waves-module_copy__3GXTv","plans":"waves-module_plans__x7Y9T","emphasis":"waves-module_emphasis__LuiDm","column":"waves-module_column__1FHbK","price":"waves-module_price__1todn","dollas":"waves-module_dollas__ujRrQ","enterprise-section":"waves-module_enterprise-section__20D09"}; var waveSvg = require("./wave~460294b2beb2f420816c1baacd0936cede842f36.svg"); var waveShadowedSvg = require("./wave-shadowed~26aa255c879811bd7995c0a46cc18b4958eb1a5e.svg"); var waves = function waves(_temp) { var _ref = _temp === void 0 ? {} : _temp, backgroundImage = _ref.backgroundImage, _ref$buttonStyle = _ref.buttonStyle, buttonStyle = _ref$buttonStyle === void 0 ? 'normal' : _ref$buttonStyle, _ref$color = _ref.color, color = _ref$color === void 0 ? '#5061CB' : _ref$color, _ref$gradient = _ref.gradient, gradient = _ref$gradient === void 0 ? true : _ref$gradient, _ref$gradientDark = _ref.gradientDark, gradientDark = _ref$gradientDark === void 0 ? false : _ref$gradientDark, _ref$wave = _ref.wave, wave = _ref$wave === void 0 ? true : _ref$wave, _ref$codeBlockDark = _ref.codeBlockDark, codeBlockDark = _ref$codeBlockDark === void 0 ? false : _ref$codeBlockDark, opts = _objectWithoutPropertiesLoose(_ref, ["backgroundImage", "buttonStyle", "color", "gradient", "gradientDark", "wave", "codeBlockDark"]); var gradientTop = gradientDark ? 'rgba(0,0,0,0.35)' : 'rgba(158,143,143,0.50)'; cv({ 'border-radius': buttonStyle === 'rounded' ? '100px' : '4px', 'color-primary': color, 'background-image': backgroundImage ? (gradient ? "linear-gradient(180deg, " + gradientTop + " 0%, rgba(0,0,0,0.50) 100%), " : '') + "url(" + backgroundImage + ")" : 'linear-gradient(104deg, #fcfcfc 13%, #f5f7fb 91%)', 'background-image-wave': wave ? backgroundImage ? "url(" + waveSvg + ")" : "url(" + waveShadowedSvg + ")" : '', 'color-nav-secondary-cta': backgroundImage ? 'white' : color, 'code-block-background': codeBlockDark ? '#1E1E1E' : 'linear-gradient(174deg, #6e60e1 0%, #1b3b87 93%)', 'code-block-shadow-color': codeBlockDark ? '#1E1E1E95' : '#392ab195', 'hero-color': backgroundImage ? 'white' : '#3a3a3a', 'nav-border-width': backgroundImage ? '0px' : '1px' }); return _extends({}, styles$2, { '@name': 'waves', '@section-fg-color': '#FFFFFF', '@section-bg-color': '#FFFFFF', '@primary-color': color, codeTheme: codeTheme }, opts); }; var themes = ({ __proto__: null, okta: okta, sadie: sadie, waves: waves }); var _class$1, _descriptor, _temp$1; var ThemeManagerClass = (_class$1 = (_temp$1 = function ThemeManagerClass() { var _this = this; _initializerDefineProperty(this, "theme", _descriptor, this); this._themes = {}; this.registerTheme = function (name, themeFactory) { if (process.env.NODE_ENV === 'development') { console.log('register theme', name); } _this._themes[name] = themeFactory; }; this.setTheme = function (opts) { var name; if (typeof opts === 'object') { name = opts.name; } else { name = opts; opts = {}; } var themeFactory = name && _this._themes[name]; if (themeFactory) { _this.theme = themeFactory(opts); } else { console.error(); console.error("ThemeManager.setTheme(" + name + ") theme not found"); console.error('Must call ThemeManager.registerTheme first'); console.error(); } }; }, _temp$1), (_descriptor = _applyDecoratedDescriptor(_class$1.prototype, "theme", [observable], { configurable: true, enumerable: true, writable: true, initializer: function initializer() { return {}; } })), _class$1); var ThemeManager = observable(new ThemeManagerClass()); window.ThemeManager = ThemeManager; for (var _i = 0, _Object$entries = Object.entries(themes); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _Object$entries[_i], k = _Object$entries$_i[0], v = _Object$entries$_i[1]; ThemeManager.registerTheme(k, v); } if (process.env.NODE_ENV === 'development') { autorun(function () { trace(); console.log('theme', toJS(ThemeManager.theme)); }, { name: 'Theme change (development)' }); } var themeUtil = function themeUtil(styles, id) { var theme = ThemeManager.theme; for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } return cs.apply(void 0, [styles && styles[id], theme[id]].concat(args)); }; var variables = ['@name', '@section-fg-color', '@section-bg-color', 'light', 'codeTheme', '@primary-color', '@link-color', '@success-color', '@warning-color', '@error-color', '@font-size-base', '@heading-color', '@text-color', '@text-color-secondary ', '@disabled-color ', '@border-radius-base', '@border-color-base', '@box-shadow-base']; var _loop = function _loop() { var v = _variables[_i$1]; Object.defineProperty(themeUtil, v, { get: function get() { return ThemeManager.theme[v]; } }); }; for (var _i$1 = 0, _variables = variables; _i$1 < _variables.length; _i$1++) { _loop(); } decorate(themeUtil, variables.reduce(function (acc, k) { acc[k] = computed; return acc; }, {})); var theme = themeUtil; var isProd = process.env.NODE_ENV === 'production'; var suffix = isProd ? 'PRD' : 'DEV'; var githubRedirectUri = window.location.origin + "/auth/github"; var githubRedirectQuery = qs.stringify({ uri: githubRedirectUri }); var env = { providerGitHubClientId: process.env["REACT_APP_PROVIDER_GITHUB_CLIENT_ID_" + suffix], stripePublicKey: isProd ? process.env.REACT_APP_STRIPE_PUBLIC_KEY_LIVE : process.env.REACT_APP_STRIPE_PUBLIC_KEY_TEST, githubRedirectUri: "https://auth.saasify.sh?" + githubRedirectQuery }; var config = { client_id: env.providerGitHubClientId, redirect_uri: env.githubRedirectUri }; var authGitHub = (function (_ref) { var location = _ref.location; var scope = 'read:user user:email'; var opts = qs.stringify(_extends({}, config, { scope: scope, state: location.pathname })); window.location = "https://github.com/login/oauth/authorize?" + opts; }); var debug = _debug('app'); var styles$3 = {"form":"styles-module_form__yUzwU","title":"styles-module_title__muMf6","forgot":"styles-module_forgot__7hJYu","submit":"styles-module_submit__1k3Id"}; var _dec$1, _dec2, _class$2, _class2$1, _temp$2; var FormItem = Form.Item; var LoginForm = (_dec$1 = inject('auth'), _dec2 = Form.create(), _dec$1(_class$2 = withRouter(_class$2 = _dec2(_class$2 = (_temp$2 = _class2$1 = /*#__PURE__*/ function (_Component) { _inheritsLoose(LoginForm, _Component); function LoginForm() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { loading: false }; _this._onSubmit = function (e) { e.preventDefault(); _this.props.form.validateFields(function (err, data) { if (!err) { _this.setState({ loading: true }); _this.props.auth.signin(data).then(_this.props.onAuth)["catch"](function (err) { _this.setState({ loading: false }); debug(err); message.error("Error logging in: " + err.response.data.error); }); } }); }; _this._onClickGitHub = function (e) { e.preventDefault(); authGitHub({ location: _this.props.location }); }; return _this; } var _proto = LoginForm.prototype; _proto.render = function render() { var className = this.props.className; var getFieldDecorator = this.props.form.getFieldDecorator; var loading = this.state.loading; var iconUser = h(Icon, { type: "user", style: { color: 'rgba(0,0,0,.25)' } }); var iconLock = h(Icon, { type: "lock", style: { color: 'rgba(0,0,0,.25)' } }); return h(Form, { className: themeUtil(styles$3, 'form', themeUtil.light, className), onSubmit: this._onSubmit }, h("h2", { className: themeUtil(styles$3, 'title') }, "Login"), h(FormItem, null, h(Button, { className: themeUtil(styles$3, 'submit'), icon: "github", onClick: this._onClickGitHub }, "Login with GitHub")), h(Divider, null, "Or"), h(FormItem, null, getFieldDecorator('username', { rules: [{ required: true, message: 'Please enter your username or email.' }] })(h(Input, { prefix: iconUser, placeholder: "Username" }))), h(FormItem, null, getFieldDecorator('password', { rules: [{ required: true, message: 'Please enter your password.' }] })(h(Input, { prefix: iconLock, type: "password", placeholder: "Password" }))), h(FormItem, null, getFieldDecorator('remember', { valuePropName: 'checked', initialValue: true })(h(Checkbox, null, "Remember me"))), h(Button, { type: "primary", htmlType: "submit", className: themeUtil(styles$3, 'submit'), loading: loading }, "Log in"), "Or ", h(Link$2, { to: "/signup" }, "sign up!")); }; return LoginForm; }(Component), _class2$1.propTypes = { auth: PropTypes.object.isRequired, form: PropTypes.object.isRequired, location: PropTypes.object.isRequired, className: PropTypes.string, onAuth: PropTypes.func }, _class2$1.defaultProps = { onAuth: function onAuth() { return undefined; } }, _temp$2)) || _class$2) || _class$2) || _class$2); var styles$4 = {"form":"styles-module_form__QEYKq","title":"styles-module_title__2b9xU","submit":"styles-module_submit__2hmyi"}; var _dec$2, _dec2$1, _class$3, _class2$2, _temp$3; var FormItem$1 = Form.Item; var SignupForm = (_dec$2 = inject('auth'), _dec2$1 = Form.create(), _dec$2(_class$3 = withRouter(_class$3 = _dec2$1(_class$3 = (_temp$3 = _class2$2 = /*#__PURE__*/ function (_Component) { _inheritsLoose(SignupForm, _Component); function SignupForm() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { loading: false }; _this._onSubmit = function (e) { e.preventDefault(); _this.props.form.validateFields(function (err, data) { if (!err) { _this.setState({ loading: true }); _this.props.auth.signup(data).then(_this.props.onAuth)["catch"](function (err) { _this.setState({ loading: false }); debug(err); message.error("Error signing up: " + err.response.data.error); }); } }); }; _this._onClickGitHub = function (e) { e.preventDefault(); authGitHub({ location: _this.props.location }); }; return _this; } var _proto = SignupForm.prototype; _proto.render = function render() { var className = this.props.className; var getFieldDecorator = this.props.form.getFieldDecorator; var loading = this.state.loading; var iconUser = h(Icon, { type: "user", style: { color: 'rgba(0,0,0,.25)' } }); var iconLock = h(Icon, { type: "lock", style: { color: 'rgba(0,0,0,.25)' } }); return h(Form, { className: themeUtil(styles$4, 'form', themeUtil.light, className), onSubmit: this._onSubmit }, h("h2", { className: themeUtil(styles$4, 'title') }, "Sign up"), h(FormItem$1, null, h(Button, { className: themeUtil(styles$4, 'submit'), icon: "github", onClick: this._onClickGitHub }, "Sign up with GitHub")), h(Divider, null, "Or"), h(FormItem$1, null, getFieldDecorator('email', { rules: [{ required: true, message: 'Please enter your email.' }] })(h(Input, { prefix: iconUser, placeholder: "Email" }))), h(FormItem$1, null, getFieldDecorator('username', { rules: [{ required: true, message: 'Please enter a username.' }] })(h(Input, { prefix: iconUser, placeholder: "Username" }))), h(FormItem$1, null, getFieldDecorator('password', { rules: [{ required: true, message: 'Please enter a password.' }] })(h(Input, { prefix: iconLock, type: "password", placeholder: "Password" }))), h(FormItem$1, null, getFieldDecorator('remember', { valuePropName: 'checked', initialValue: true })(h(Checkbox, null, "Remember me"))), h(Button, { type: "primary", htmlType: "submit", className: themeUtil(styles$4, 'submit'), loading: loading }, "Sign up")); }; return SignupForm; }(Component), _class2$2.propTypes = { auth: PropTypes.object.isRequired, form: PropTypes.object.isRequired, location: PropTypes.object.isRequired, className: PropTypes.string, onAuth: PropTypes.func }, _class2$2.defaultProps = { onAuth: function onAuth() { return undefined; } }, _temp$3)) || _class$3) || _class$3) || _class$3); var SaasifyContext = React.createContext(undefined); var styles$5 = {"form":"styles-module_form__IMIw5","title":"styles-module_title__202A0","submit":"styles-module_submit__3cAJZ","label":"styles-module_label__1mKjb","input":"styles-module_input__2PQy2","detail":"styles-module_detail__1-Z3w"}; var _class$4, _class2$3, _temp$4; var createOptions = function createOptions(fontSize) { if (fontSize === void 0) { fontSize = 16; } return { style: { base: { fontSize: fontSize, color: '#424770', letterSpacing: '0.025em', '::placeholder': { color: '#aab7c4' } }, invalid: { color: '#9e2146' } } }; }; var CheckoutForm = /*#__PURE__*/ function (_Component) { _inheritsLoose(CheckoutForm, _Component); function CheckoutForm() { return _Component.apply(this, arguments) || this; } var _proto = CheckoutForm.prototype; _proto.render = function render() { var _this = this; return h(SaasifyContext.Consumer, null, function (config) { return h(StripeProvider, { apiKey: env.stripePublicKey }, h(Elements, null, h(CheckoutFormImpl, _extends({}, _this.props, { config: config })))); }); }; return CheckoutForm; }(Component); CheckoutForm.propTypes = { onSubmit: PropTypes.func.isRequired, loading: PropTypes.bool, title: PropTypes.string, action: PropTypes.node, className: PropTypes.string }; var CheckoutFormImpl = injectStripe(_class$4 = (_temp$4 = _class2$3 = /*#__PURE__*/ function (_Component2) { _inheritsLoose(CheckoutFormImpl, _Component2); function CheckoutFormImpl() { var _this2; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this2 = _Component2.call.apply(_Component2, [this].concat(args)) || this; _this2._onSubmit = function (e) { try { e.preventDefault(); var name = e.target.name.value; var coupon = e.target.coupon && e.target.coupon.value; _this2.props.onSubmit({ name: name, coupon: coupon, stripe: _this2.props.stripe }); return Promise.resolve(); } catch (e) { return Promise.reject(e); } }; return _this2; } var _proto2 = CheckoutFormImpl.prototype; _proto2.render = function render() { var _this$props = this.props, config = _this$props.config, loading = _this$props.loading, title = _this$props.title, action = _this$props.action, className = _this$props.className; return h("form", { className: themeUtil(styles$5, 'form', className, themeUtil(styles$5, 'light')), onSubmit: this._onSubmit }, title && h("h2", { className: themeUtil(styles$5, 'title') }, title), h("label", { className: themeUtil(styles$5, 'label') }, "Name", h("input", { className: themeUtil(styles$5, 'input'), name: "name", type: "text", placeholder: "John Doe", required: true })), h("label", { className: themeUtil(styles$5, 'label') }, "Card Details", h(Tooltip, { placement: "right", title: "All payment info is securely handled by Stripe." }, h(Icon, { className: themeUtil(styles$5, 'detail'), type: "question-circle" })), h(CardElement, createOptions())), config.coupons && config.coupons.length > 0 && h("label", { className: themeUtil(styles$5, 'label') }, "Promo Code", h("input", { className: themeUtil(styles$5, 'input'), name: "coupon", type: "text", placeholder: "" })), action && h(Button, { type: "primary", htmlType: "submit", className: themeUtil(styles$5, 'submit'), loading: loading }, action)); }; return CheckoutFormImpl; }(Component), _class2$3.propTypes = { config: PropTypes.object.isRequired, stripe: PropTypes.object.isRequired, onSubmit: PropTypes.func.isRequired, loading: PropTypes.bool, title: PropTypes.string, action: PropTypes.node, className: PropTypes.string }, _class2$3.defaultProps = { loading: false }, _temp$4)) || _class$4; var styles$6 = {"cta-button":"styles-module_cta-button__3AKzj","inline":"styles-module_inline__1QeA5"}; var _class$5; var CTAButton = Hoverable(_class$5 = observer(_class$5 = /*#__PURE__*/ function (_Component) { _inheritsLoose(CTAButton, _Component); function CTAButton() { return _Component.apply(this, arguments) || this; } var _proto = CTAButton.prototype; _proto.render = function render() { var _this$props = this.props, hovered = _this$props.hovered, _this$props$type = _this$props.type, type = _this$props$type === void 0 ? 'primary' : _this$props$type, inline = _this$props.inline, className = _this$props.className, children = _this$props.children, _this$props$style = _this$props.style, style = _this$props$style === void 0 ? {} : _this$props$style, rest = _objectWithoutPropertiesLoose(_this$props, ["hovered", "type", "inline", "className", "children", "style"]); var primaryColor = themeUtil['@primary-color']; var borderColor = type === 'secondary' || !hovered ? primaryColor : 'transparent'; var ownStyle = { border: "2px solid " + borderColor }; if (type === 'secondary') { ownStyle.background = hovered ? primaryColor : 'transparent'; } return h(Button, _extends({ type: type, className: themeUtil(styles$6, 'cta-button', className, type, styles$6[type], inline && themeUtil(styles$6, 'inline')), style: _extends({}, ownStyle, {}, style) }, rest), children); }; return CTAButton; }(Component)) || _class$5) || _class$5; var styles$7 = {"logo":"styles-module_logo__CDiMd"}; var Logo = /*#__PURE__*/ function (_Component) { _inheritsLoose(Logo, _Component); function Logo() { return _Component.apply(this, arguments) || this; } var _proto = Logo.prototype; _proto.render = function render() { var _this$props = this.props, className = _this$props.className, _this$props$style = _this$props.style, style = _this$props$style === void 0 ? {} : _this$props$style, rest = _objectWithoutPropertiesLoose(_this$props, ["className", "style"]); return h(SaasifyContext.Consumer, null, function (config) { return config.logo ? h("img", _extends({ className: themeUtil(styles$7, 'logo', className), src: config.logo, alt: config.name + " Logo", style: style }, rest)) : h("div", _extends({ className: themeUtil(styles$7, 'logo', className), style: style }, rest), config.name); }); }; return Logo; }(Component); var styles$8 = {"container":"styles-module_container__2vHAE","content":"styles-module_content__1AUWq","content-body":"styles-module_content-body__1Omfb","attached":"styles-module_attached__2xShN","primary":"styles-module_primary__1cin0","logo":"styles-module_logo__3yU03","logo-text":"styles-module_logo-text__KGXVL","links":"styles-module_links__3DD6V","link":"styles-module_link__oAvSn","menuWrapper":"styles-module_menuWrapper__2252q","actions":"styles-module_actions__RSgiO","burger":"styles-module_burger__1fkY1","expanded":"styles-module_expanded__39KUP"}; var Link = (function (_ref) { var children = _ref.children, label = _ref.label, to = _ref.to, href = _ref.href, className = _ref.className, rest = _objectWithoutPropertiesLoose(_ref, ["children", "label", "to", "href", "className"]); return to ? h(Link$2, _extends({ to: to, className: themeUtil(styles$8, 'link', className) }, rest), label || children) : h("a", _extends({ href: href, className: themeUtil(styles$8, 'link', className) }, rest), label || children); }); var _dec$3, _class$6, _class2$4, _temp$5; var isServer = typeof window === 'undefined'; var NavHeader = (_dec$3 = inject('auth'), _dec$3(_class$6 = observer(_class$6 = (_temp$5 = _class2$4 = /*#__PURE__*/ function (_Component) { _inheritsLoose(NavHeader, _Component); function NavHeader() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { attached: isServer || window.scrollY > 0, expanded: false }; _this.handleToggleExpanded = function () { _this.setState({ expanded: !_this.state.expanded }); }; _this._onScroll = function () { if (!_this._scrollRaf) { _this._scrollRaf = raf(_this._onScrollAF); } }; _this._onScrollAF = function () { _this._scrollRaf = null; _this.setState({ attached: isServer || window.scrollY > 0 }); }; return _this; } var _proto = NavHeader.prototype; _proto.componentDidMount = function componentDidMount() { if (!isServer) { window.addEventListener('scroll', this._onScroll); this._onScrollAF(); } }; _proto.componentWillUnmount = function componentWillUnmount() { if (!isServer) { window.removeEventListener('scroll', this._onScroll); } if (this._scrollRaf) { raf.cancel(this._scrollRaf); this._scrollRaf = null; } }; _proto.render = function render() { var _this2 = this; var _this$props = this.props, auth = _this$props.auth, fixed = _this$props.fixed; var _this$state = this.state, attached = _this$state.attached, expanded = _this$state.expanded; return h(SaasifyContext.Consumer, null, function (config) { return h("header", { className: themeUtil(styles$8, 'container', attached || fixed ? themeUtil(styles$8, 'attached') : null, expanded ? themeUtil(styles$8, 'expanded') : null), style: { background: attached || fixed || expanded ? themeUtil['@section-fg-color'] : 'transparent' } }, h("div", { className: themeUtil(styles$8, 'content') }, h("div", { className: themeUtil(styles$8, 'primary') }, h(Link, { to: "/" }, h(Logo, { className: themeUtil(styles$8, 'logo') }), h("span", { className: themeUtil(styles$8, 'logo-text') }, config.name)), h("div", { className: themeUtil(styles$8, 'burger') }, h(CTAButton, { type: "secondary", inline: true, onClick: _this2.handleToggleExpanded }, "Menu"))), h("div", { className: themeUtil(styles$8, 'content-body') }, h("div", { className: themeUtil(styles$8, 'links') }, config.header.links.map(function (link) { if (typeof link === 'function') { link = link({ config: config, auth: auth, fixed: fixed, attached: attached }); if (!link) return null; } return h(Link, _extends({ key: link.to || link.href }, link)); })), auth.isAuthenticated ? h("div", { className: themeUtil(styles$8, 'actions') }, h(Link, { to: "/logout", className: themeUtil(styles$8, 'login') }, h(CTAButton, { type: "secondary", inline: true }, "Log Out")), h(Link, { to: "/dashboard" }, h(CTAButton, { type: "primary", inline: true }, "Dashboard"))) : h("div", { className: themeUtil(styles$8, 'actions') }, h(Link, { to: "/login", className: themeUtil(styles$8, 'login') }, h(CTAButton, { type: "secondary", inline: true }, "Log In")), h(Link, { to: "/signup" }, h(CTAButton, { type: "primary", inline: true }, "Get Started")))))); }); }; return NavHeader; }(Component), _class2$4.propTypes = { auth: PropTypes.object.isRequired, fixed: PropTypes.bool }, _class2$4.defaultProps = { fixed: false }, _temp$5)) || _class$6) || _class$6); var styles$9 = {"container":"styles-module_container__2VcGn","content":"styles-module_content__3N4wM","header":"styles-module_header__1as3z","listItem":"styles-module_listItem__GSzET","link":"styles-module_link__37mj5","logo":"styles-module_logo__3-Ksc","detail":"styles-module_detail__2O5Bo"}; var Link$1 = (function (_ref) { var children = _ref.children, label = _ref.label, to = _ref.to, href = _ref.href, className = _ref.className, rest = _objectWithoutPropertiesLoose(_ref, ["children", "label", "to", "href", "className"]); return to ? h(Link$2, _extends({ to: to, className: themeUtil(styles$9, 'link', className) }, rest), label || children) : h("a", _extends({ href: href, className: themeUtil(styles$9, 'link', className) }, rest), label || children); }); var _dec$4, _class$7, _class2$5, _temp$6; var NavFooter = (_dec$4 = inject('auth'), _dec$4(_class$7 = observer(_class$7 = (_temp$6 = _class2$5 = /*#__PURE__*/ function (_Component) { _inheritsLoose(NavFooter, _Component); function NavFooter() { return _Component.apply(this, arguments) || this; } var _proto = NavFooter.prototype; _proto.render = function render() { var auth = this.props.auth; return h(SaasifyContext.Consumer, null, function (config) { return h("footer", { className: themeUtil(styles$9, 'container'), style: { background: themeUtil['@section-fg-color'] } }, h("div", { className: themeUtil(styles$9, 'content') }, h("div", { className: themeUtil(styles$9, 'detailColumn') }, h(Link$1, { to: "/" }, h(Logo, { className: themeUtil(styles$9, 'logo') })), h("div", { className: themeUtil(styles$9, 'detail') }, "Brooklyn, NY")), config.footer.columns.map(function (column) { return h("div", { key: column.label }, h("h3", { className: themeUtil(styles$9, 'header') }, column.label), h("ul", null, column.links.map(function (link) { if (typeof link === 'function') { link = link({ config: config, auth: auth }); if (!link) return null; } return h("li", { key: link.to || link.href, className: themeUtil(styles$9, 'listItem') }, h(Link$1, link)); }))); }))); }); }; return NavFooter; }(Component), _class2$5.propTypes = { auth: PropTypes.object.isRequired }, _temp$6)) || _class$7) || _class$7); var styles$a = {"section":"styles-module_section__3it4s","content":"styles-module_content__3VDXY","stretch":"styles-module_stretch__3Qte5","title":"styles-module_title__Z9skz","subtitle":"styles-module_subtitle__3U5mR","desc":"styles-module_desc__2eFJn"}; var _class$8, _class2$6, _temp$7; var Section = observer(_class$8 = (_temp$7 = _class2$6 = /*#__PURE__*/ function (_Component) { _inheritsLoose(Section, _Component); function Section() { return _Component.apply(this, arguments) || this; } var _proto = Section.prototype; _proto.render = function render() { var _this$props = this.props, inverted = _this$props.inverted, stretch = _this$props.stretch, title = _this$props.title, subtitle = _this$props.subtitle, desc = _this$props.desc, id = _this$props.id, className = _this$props.className, _this$props$style = _this$props.style, style = _this$props$style === void 0 ? {} : _this$props$style, children = _this$props.children; var sectionProps = {}; if (id || title) { sectionProps.id = id || slugify(title.toLowerCase()); } var themeArgs = [styles$a, 'section', themeUtil(styles$a, sectionProps.id + "-section"), inverted && themeUtil(styles$a, 'inverted'), className]; return h("section", _extends({ className: themeUtil.apply(void 0, themeArgs), style: _extends({ background: inverted ? themeUtil['@section-fg-color'] : themeUtil['@section-bg-color'] }, style) }, sectionProps), h("div", { className: themeUtil(styles$a, 'content', stretch && themeUtil(styles$a, 'stretch')) }, title && h("h1", { className: themeUtil(styles$a, 'title') }, title), subtitle && h("h5", { className: themeUtil(styles$a, 'subtitle') }, subtitle), desc && h("p", { className: themeUtil(styles$a, 'desc') }, desc), children)); }; return Section; }(Component), _class2$6.propTypes = { inverted: PropTypes.bool, stretch: PropTypes.bool, title: PropTypes.node, subtitle: PropTypes.node, desc: PropTypes.node, id: PropTypes.string, className: PropTypes.string, style: PropTypes.object, children: PropTypes.node }, _class2$6.defaultProps = { inverted: false, stretch: false }, _temp$7)) || _class$8; var styles$b = {"dashboard":"styles-module_dashboard__1hS0Q"}; var DashboardSection = /*#__PURE__*/ function (_Component) { _inheritsLoose(DashboardSection, _Component); function DashboardSection() { return _Component.apply(this, arguments) || this; } var _proto = DashboardSection.prototype; _proto.render = function render() { var _this$props = this.props, className = _this$props.className, rest = _objectWithoutPropertiesLoose(_this$props, ["className"]); return h(Section, _extends({ id: "dashboard", title: "Dashboard", className: themeUtil(styles$b, 'dashboard', className) }, rest)); }; return DashboardSection; }(Component); var API = new SaasifyClient({ baseUrl: process.env.REACT_APP_SAASIFY_API_BASE_URL }); var styles$c = {"body":"styles-module_body__284OX"}; var _dec$5, _class$9, _class2$7, _temp$8; var ProfileSection = (_dec$5 = inject('auth'), _dec$5(_class$9 = observer(_class$9 = (_temp$8 = _class2$7 = /*#__PURE__*/ function (_Component) { _inheritsLoose(ProfileSection, _Component); function ProfileSection() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { copiedTextToClipboard: false, isLoadingUnsubscribe: false, isLoadingRefreshAuthToken: false }; _this._onClickCopyToken = function () { var token = _this.props.auth.consumer.token; copyTextToClipboard(token); _this.setState({ copiedTextToClipboard: true }); _this._clearCopyTimeout(); _this._copyTimeout = setTimeout(_this._onCopyTimeout, 3000); }; _this._onCopyTimeout = function () { _this._clearCopyTimeout(); _this.setState({ copiedTextToClipboard: false }); }; _this._clearCopyTimeout = function () { if (_this._copyTimeout) { clearTimeout(_this._copyTimeout); _this._copyTimeout = null; } }; _this._onConfirmUnsubscribe = function () { _this.setState({ isLoadingUnsubscribe: true }); API.removeConsumer(_this.props.auth.consumer).then(function () { _this.props.auth.consumer = null; notification.success({ message: 'Subscription canceled', description: 'Your subscription has been canceled. Any outstanding charges will be charged at the end of the current billing cycle.' }); _this.setState({ isLoadingUnsubscribe: false }); }, function (err) { console.warn(err); notification.error({ message: 'Error canceling subscription', description: err.error && err.error.message, duration: 0 }); _this.setState({ isLoadingUnsubscribe: false }); }); }; _this._onClickRefreshAuthToken = function () { _this.setState({ isLoadingRefreshAuthToken: true }); API.updateConsumer(_this.props.auth.consumer).then(function (consumer) { _this.props.auth.consumer = consumer; notification.success({ message: 'Auth token refreshed', description: 'Your auth token has been refreshed. Your old token is now invalid.' }); _this.setState({ isLoadingRefreshAuthToken: false }); }, function (err) { console.warn(err); notification.error({ message: 'Error refreshing auth token', description: err.error && err.error.message, duration: 0 }); _this.setState({ isLoadingRefreshAuthToken: false }); }); }; return _this; } var _proto = ProfileSection.prototype; _proto.componentWillUnmount = function componentWillUnmount() { if (this._copyTimeout) { clearTimeout(this._copyTimeout); this._copyTimeout = null; } }; _proto.render = function render() { var _this2 = this; var _this$props = this.props, auth = _this$props.auth, rest = _objectWithoutPropertiesLoose(_this$props, ["auth"]); var _this$state = this.state, copiedTextToClipboard = _this$state.copiedTextToClipboard, isLoadingUnsubscribe = _this$state.isLoadingUnsubscribe, isLoadingRefreshAuthToken = _this$state.isLoadingRefreshAuthToken; var hasSubscription = auth.consumer && auth.consumer.enabled; var columns = [{ title: 'Avatar', dataIndex: 'image', render: function render(image) { return image ? h(Avatar, { src: image, className: themeUtil(styles$c, 'avatar') }) : h(Avatar, { icon: "user", className: themeUtil(styles$c, 'avatar') }); } }, { title: 'Username', dataIndex: 'username' }, { title: 'Email', dataIndex: 'email' }, { title: 'Joined', dataIndex: 'joined', render: function render(date) { return format(new Date(date), 'MM/dd/yyyy'); } }, { title: 'Subscription', dataIndex: 'subscription', render: function render(subscription) { return h(Link$2, { to: "/pricing" }, subscription); } }, hasSubscription && { title: 'Auth Token', dataIndex: 'token', render: function render(token) { return h(Tooltip, { placement: "top", title: copiedTextToClipboard ? 'Copied!' : 'Copy to clipboard' }, h(Button, { type: "primary", ghost: true, onClick: _this2._onClickCopyToken }, auth.consumer.token.substr(0, 8) + " ...")); } }, { title: 'Actions', key: 'actions', render: function render(token) { return hasSubscription ? h(Fragment, null, h(Button, { type: "ghost", icon: "reload", loading: isLoadingRefreshAuthToken, onClick: _this2._onClickRefreshAuthToken }, "Refresh Token"), h(Divider, { type: "vertical" }), h(Popconfirm, { placement: "top", title: "Are you sure you want to cancel your subscription?", okText: "Yes", cancelText: "No", onConfirm: _this2._onConfirmUnsubscribe }, h(Button, { type: "default", loading: isLoadingUnsubscribe }, "Downgrade"))) : h(Button, { type: "primary", href: "/checkout?plan=unlimited" }, "Upgrade"); } }].filter(Boolean); var dataSource = [{ id: auth.user.id, username: auth.user.username, email: auth.user.email, image: auth.user.image, joined: auth.user.createdAt, subscription: hasSubscription ? 'Unlimited' : 'Free', subscribed: auth.consumer && auth.consumer.createdAt }]; return h(Section, _extends({ id: "profile", title: "Profile" }, rest), h("div", { className: themeUtil(styles$c, 'body') }, h(Table, { columns: columns, rowKey: function rowKey(record) { return record.id; }, dataSource: dataSource, pagination: false }))); }; return ProfileSection; }(Component), _class2$7.propTypes = { auth: PropTypes.object.isRequired }, _temp$8)) || _class$9) || _class$9); var styles$d = {"body":"styles-module_body__2yNe4"}; var _dec$6, _class$a, _class2$8, _temp$9; var statusColors = { draft: 'geekblue', open: 'red', paid: 'green', uncollectable: 'volcano', "void": 'purple' }; var columns = [{ title: 'ID', dataIndex: 'number' }, { title: 'Date', dataIndex: 'created', render: function render(timestamp) { return format(new Date(timestamp * 1000), 'MM/dd/yyyy'); } }, { title: 'Amount', dataIndex: 'amount_due', render: function render(amount) { return "$" + (amount / 100).toFixed(2); } }, { title: 'Status', dataIndex: 'status', render: function render(status) { var color = statusColors[status]; return h(Tag, { color: color }, titleize(status)); } }, { title: 'PDF', dataIndex: 'invoice_pdf', render: function render(link) { return h("a", { href: link, title: "Invoice PDF", target: "_blank", rel: "noopener noreferrer" }, "Download"); } }]; var InvoicingSection = (_dec$6 = inject('auth'), _dec$6(_class$a = observer(_class$a = (_temp$9 = _class2$8 = /*#__PURE__*/ function (_Component) { _inheritsLoose(InvoicingSection, _Component); function InvoicingSection() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { data: [],