react-saasify-chrisvxd
Version:
React components for Saasify web clients.
1,554 lines (1,350 loc) • 101 kB
JavaScript
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: [],