diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 922f4c878..122e04306 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -24129,6 +24129,79 @@ + + landing + + + labels + + + features + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + managemyshop + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + pricing + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + menus diff --git a/client/package.json b/client/package.json index eeafdb4e5..f3843a26b 100644 --- a/client/package.json +++ b/client/package.json @@ -19,6 +19,7 @@ "craco-less": "^1.17.1", "dinero.js": "^1.8.1", "dotenv": "^9.0.2", + "enquire-js": "^0.2.1", "env-cmd": "^10.1.0", "exifr": "^7.0.0", "firebase": "^8.6.0", @@ -35,6 +36,8 @@ "preval.macro": "^5.0.0", "prop-types": "^15.7.2", "query-string": "^7.0.0", + "rc-queue-anim": "^1.8.5", + "rc-scroll-anim": "^2.7.6", "react": "^17.0.1", "react-big-calendar": "^0.33.2", "react-color": "^2.19.3", @@ -49,6 +52,7 @@ "react-resizable": "^3.0.1", "react-router-dom": "^5.2.0", "react-scripts": "^4.0.3", + "react-sublime-video": "^0.2.5", "react-virtualized": "^9.22.3", "recharts": "^2.0.7", "redux": "^4.1.0", diff --git a/client/src/assets/ImEX Online Logo - Dark.png b/client/src/assets/ImEX Online Logo - Dark.png new file mode 100644 index 000000000..f2a750669 Binary files /dev/null and b/client/src/assets/ImEX Online Logo - Dark.png differ diff --git a/client/src/assets/ImEX Online Logo.png b/client/src/assets/ImEX Online Logo.png new file mode 100644 index 000000000..0719589ec Binary files /dev/null and b/client/src/assets/ImEX Online Logo.png differ diff --git a/client/src/landing/home/Banner0.jsx b/client/src/landing/home/Banner0.jsx new file mode 100644 index 000000000..9b8ef68c8 --- /dev/null +++ b/client/src/landing/home/Banner0.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { Button } from 'antd'; +import { DownOutlined } from '@ant-design/icons'; +import QueueAnim from 'rc-queue-anim'; +import TweenOne from 'rc-tween-one'; +import { isImg } from './utils'; + +class Banner extends React.PureComponent { + render() { + const { ...currentProps } = this.props; + const { dataSource } = currentProps; + delete currentProps.dataSource; + delete currentProps.isMobile; + return ( +
+ +
+ {typeof dataSource.title.children === 'string' && + dataSource.title.children.match(isImg) ? ( + img + ) : ( + dataSource.title.children + )} +
+
+ {dataSource.content.children} +
+ +
+ + + +
+ ); + } +} +export default Banner; diff --git a/client/src/landing/home/Content0.jsx b/client/src/landing/home/Content0.jsx new file mode 100644 index 000000000..ab9e51526 --- /dev/null +++ b/client/src/landing/home/Content0.jsx @@ -0,0 +1,49 @@ +import React from 'react'; +import QueueAnim from 'rc-queue-anim'; +import { Row, Col } from 'antd'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import { getChildrenToRender } from './utils'; + +class Content extends React.PureComponent { + render() { + const { dataSource, isMobile, ...props } = this.props; + const { + wrapper, + titleWrapper, + page, + OverPack: overPackData, + childWrapper, + } = dataSource; + return ( +
+
+
+ {titleWrapper.children.map(getChildrenToRender)} +
+ + + {childWrapper.children.map((block, i) => { + const { children: item, ...blockProps } = block; + return ( + +
+ {item.children.map(getChildrenToRender)} +
+ + ); + })} +
+
+
+
+ ); + } +} + +export default Content; diff --git a/client/src/landing/home/Content1.jsx b/client/src/landing/home/Content1.jsx new file mode 100644 index 000000000..66e6425ee --- /dev/null +++ b/client/src/landing/home/Content1.jsx @@ -0,0 +1,70 @@ +import React from 'react'; +import QueueAnim from 'rc-queue-anim'; +import TweenOne from 'rc-tween-one'; +import { Row, Col } from 'antd'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; + +function Content1(props) { + const { ...tagProps } = props; + const { dataSource, isMobile } = tagProps; + delete tagProps.dataSource; + delete tagProps.isMobile; + const animType = { + queue: isMobile ? 'bottom' : 'right', + one: isMobile + ? { + scaleY: '+=0.3', + opacity: 0, + type: 'from', + ease: 'easeOutQuad', + } + : { + x: '-=30', + opacity: 0, + type: 'from', + ease: 'easeOutQuad', + }, + }; + return ( +
+ + + + img + + + +

+ {dataSource.title.children} +

+
+ {dataSource.content.children} +
+
+
+
+ ); +} + +export default Content1; diff --git a/client/src/landing/home/Content12.jsx b/client/src/landing/home/Content12.jsx new file mode 100644 index 000000000..b828b4c48 --- /dev/null +++ b/client/src/landing/home/Content12.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { Row, Col } from 'antd'; +import { TweenOneGroup } from 'rc-tween-one'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import { getChildrenToRender } from './utils'; + +class Content12 extends React.PureComponent { + getChildrenToRender = (data) => + data.map((item) => { + return ( + +
+ + img + +
+ + ); + }); + + render() { + const { ...props } = this.props; + const { dataSource } = props; + delete props.dataSource; + delete props.isMobile; + const childrenToRender = this.getChildrenToRender( + dataSource.block.children + ); + return ( +
+
+
+ {dataSource.titleWrapper.children.map(getChildrenToRender)} +
+ + + {childrenToRender} + + +
+
+ ); + } +} + +export default Content12; diff --git a/client/src/landing/home/Content3.jsx b/client/src/landing/home/Content3.jsx new file mode 100644 index 000000000..49fe071ce --- /dev/null +++ b/client/src/landing/home/Content3.jsx @@ -0,0 +1,94 @@ +import React from 'react'; +import QueueAnim from 'rc-queue-anim'; +import TweenOne from 'rc-tween-one'; +import { Row, Col } from 'antd'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import { getChildrenToRender } from './utils'; + +class Content3 extends React.PureComponent { + getDelay = (e, b) => (e % b) * 100 + Math.floor(e / b) * 100 + b * 100; + + render() { + const { ...props } = this.props; + const { dataSource, isMobile } = props; + delete props.dataSource; + delete props.isMobile; + let clearFloatNum = 0; + const children = dataSource.block.children.map((item, i) => { + const childObj = item.children; + const delay = isMobile ? i * 50 : this.getDelay(i, 24 / item.md); + const liAnim = { + opacity: 0, + type: 'from', + ease: 'easeOutQuad', + delay, + }; + const childrenAnim = { ...liAnim, x: '+=10', delay: delay + 100 }; + clearFloatNum += item.md; + clearFloatNum = clearFloatNum > 24 ? 0 : clearFloatNum; + return ( + + + img + +
+ + {childObj.title.children} + + + {childObj.content.children} + +
+
+ ); + }); + return ( +
+
+
+ {dataSource.titleWrapper.children.map(getChildrenToRender)} +
+ + + + {children} + + + +
+
+ ); + } +} + +export default Content3; diff --git a/client/src/landing/home/Content4.jsx b/client/src/landing/home/Content4.jsx new file mode 100644 index 000000000..836ca4d14 --- /dev/null +++ b/client/src/landing/home/Content4.jsx @@ -0,0 +1,59 @@ +import React from 'react'; +import TweenOne from 'rc-tween-one'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import VideoPlay from 'react-sublime-video'; +import { getChildrenToRender } from './utils'; + +function Content4(props) { + const { ...tagProps } = props; + const { dataSource, isMobile } = tagProps; + delete tagProps.dataSource; + delete tagProps.isMobile; + const animation = { + y: '+=30', + opacity: 0, + type: 'from', + ease: 'easeOutQuad', + }; + const videoChildren = dataSource.video.children.video; + const videoNameArray = videoChildren.split('.'); + const type = videoNameArray[videoNameArray.length - 1]; + return ( +
+
+
+ {dataSource.titleWrapper.children.map(getChildrenToRender)} +
+ + + {isMobile ? ( + + ) : ( + + + + )} + + +
+
+ ); +} + +export default Content4; diff --git a/client/src/landing/home/Footer1.jsx b/client/src/landing/home/Footer1.jsx new file mode 100644 index 000000000..fe64b1219 --- /dev/null +++ b/client/src/landing/home/Footer1.jsx @@ -0,0 +1,69 @@ +import React from 'react'; +import TweenOne from 'rc-tween-one'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import QueueAnim from 'rc-queue-anim'; +import { Row, Col } from 'antd'; +import { getChildrenToRender } from './utils'; +import { isImg } from './utils'; + +class Footer extends React.Component { + static defaultProps = { + className: 'footer1', + }; + + getLiChildren = (data) => + data.map((item, i) => { + const { title, childWrapper, ...itemProps } = item; + return ( + +

+ {typeof title.children === 'string' && + title.children.match(isImg) ? ( + img + ) : ( + title.children + )} +

+
+ {childWrapper.children.map(getChildrenToRender)} +
+ + ); + }); + + render() { + const { ...props } = this.props; + const { dataSource } = props; + delete props.dataSource; + delete props.isMobile; + const childrenToRender = this.getLiChildren(dataSource.block.children); + return ( +
+ + + {childrenToRender} + + +
+
+ {dataSource.copyright.children} +
+
+
+
+
+ ); + } +} + +export default Footer; diff --git a/client/src/landing/home/LandingNavigator.jsx b/client/src/landing/home/LandingNavigator.jsx new file mode 100644 index 000000000..2c0a840ae --- /dev/null +++ b/client/src/landing/home/LandingNavigator.jsx @@ -0,0 +1,182 @@ +import React, { useState } from "react"; +import TweenOne from "rc-tween-one"; +import { Anchor, Menu } from "antd"; +import { getChildrenToRender } from "./utils"; +import ImexOnlineLogoLight from "../../assets/ImEX Online Logo.png"; +import { Link } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +const { Item, SubMenu } = Menu; + +export default function LandingNavigator({ dataSource, isMobile, ...props }) { + const [state, setState] = useState({ phoneOpen: undefined }); + const { t } = useTranslation(); + const { phoneOpen } = state; + + const phoneClick = () => { + const phoneOpen = !state.phoneOpen; + setState({ + phoneOpen, + }); + }; + + const moment = phoneOpen === undefined ? 300 : null; + return ( + +
+ + img + + {isMobile && ( + //Unknown what this menu does. +
{ + phoneClick(); + }} + > + + + +
+ )} + { + if (state.phoneOpen) { + e.target.style.height = "auto"; + } + }, + ease: "easeInOutQuad", + } + : null + } + moment={moment} + reverse={!!phoneOpen} + > + + + + {t("landing.labels.features")} + + + + + {t("landing.labels.pricing")} + + + + + {t("landing.labels.managemyshop")} + + + + +
+
+ ); +} + +// +// {a.children.map(getChildrenToRender)} +// +// } +// popupClassName="header0-item-child" +// > +// {subItem.map(($item, ii) => { +// const { children: childItem } = $item; +// const child = childItem.href ? ( +// +// {childItem.children.map(getChildrenToRender)} +// +// ) : ( +//
+// {childItem.children.map(getChildrenToRender)} +//
+// ); +// return ( +// +// {child} +// +// ); +// })} +//
+// subItem: [ +// { +// name: "sub0", +// className: "item-sub", +// children: { +// className: "item-sub-item", +// children: [ +// { +// name: "image0", +// className: "item-image", +// children: +// "https://gw.alipayobjects.com/zos/rmsportal/ruHbkzzMKShUpDYMEmHM.svg", +// }, +// { +// name: "title", +// className: "item-title", +// children: "Ant Design", +// }, +// { +// name: "content", +// className: "item-content", +// children: "企业级 UI 设计体系", +// }, +// ], +// }, +// }, +// { +// name: "sub1", +// className: "item-sub", +// children: { +// className: "item-sub-item", +// children: [ +// { +// name: "image0", +// className: "item-image", +// children: +// "https://gw.alipayobjects.com/zos/rmsportal/ruHbkzzMKShUpDYMEmHM.svg", +// }, +// { +// name: "title", +// className: "item-title", +// children: "Ant Design", +// }, +// { +// name: "content", +// className: "item-content", +// children: "企业级 UI 设计体系", +// }, +// ], +// }, +// }, +// ], diff --git a/client/src/landing/home/Pricing1.jsx b/client/src/landing/home/Pricing1.jsx new file mode 100644 index 000000000..f74dcf901 --- /dev/null +++ b/client/src/landing/home/Pricing1.jsx @@ -0,0 +1,73 @@ +import React from 'react'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import QueueAnim from 'rc-queue-anim'; +import { Row, Col, Button } from 'antd'; +import { getChildrenToRender } from './utils'; + +class Pricing1 extends React.PureComponent { + getChildrenToRender = (item) => { + const { + wrapper, + topWrapper, + name, + buttonWrapper, + line, + content, + money, + } = item.children; + return ( + + +
+
+ {name.children} +
+

+ {money.children} +

+
+
+ {content.children} +
+ +
+ +
+
+ + ); + }; + + render() { + const { ...props } = this.props; + const { dataSource } = props; + delete props.dataSource; + delete props.isMobile; + const { block } = dataSource; + const childrenToRender = block.children.map(this.getChildrenToRender); + return ( +
+
+
+ {dataSource.titleWrapper.children.map(getChildrenToRender)} +
+ + + {childrenToRender} + + +
+
+ ); + } +} + +export default Pricing1; diff --git a/client/src/landing/home/Pricing2.jsx b/client/src/landing/home/Pricing2.jsx new file mode 100644 index 000000000..31eb70548 --- /dev/null +++ b/client/src/landing/home/Pricing2.jsx @@ -0,0 +1,114 @@ +import React from 'react'; +import OverPack from 'rc-scroll-anim/lib/ScrollOverPack'; +import QueueAnim from 'rc-queue-anim'; +import { Table } from 'antd'; +import { getChildrenToRender, isImg } from './utils'; + +class Pricing2 extends React.PureComponent { + getColumns = (columns) => { + return columns.map((item) => { + const { childWrapper, ...$item } = item; + return { + align: 'center', + ...$item, + title: ( +
+ {childWrapper.children.map(getChildrenToRender)} +
+ ), + }; + }); + }; + + getDataSource = (dataSource, columns) => + dataSource.map((item, i) => { + const obj = { key: i.toString() }; + item.children.forEach(($item, ii) => { + if (columns[ii]) { + obj[columns[ii].key] = ( +
+ {typeof $item.children === 'string' && + $item.children.match(isImg) ? ( + img + ) : ( + $item.children + )} +
+ ); + } + }); + return obj; + }); + + getMobileChild = (table) => { + const { columns, dataSource, ...tableProps } = table; + const names = columns.children.filter( + (item) => item.key.indexOf('name') >= 0 + ); + const newColumns = columns.children.filter( + (item) => item.key.indexOf('name') === -1 + ); + return newColumns.map((item, i) => { + const items = [].concat(names[0], item).filter((c) => c); + if (items.length > 1) { + items[0].colSpan = 0; + items[1].colSpan = 2; + } + const dataSources = dataSource.children.map(($item) => { + const child = $item.children.filter( + (c) => c.name.indexOf('name') === -1 + ); + const n = $item.children.filter((c) => c.name.indexOf('name') >= 0); + return { + ...$item, + children: [].concat(n[0], child[i]).filter((c) => c), + }; + }); + const props = { + ...tableProps, + columns: this.getColumns(items), + dataSource: this.getDataSource(dataSources, items), + }; + return ( + + ); + }); + }; + + render() { + const { dataSource, isMobile, ...props } = this.props; + const { Table: table, wrapper, page, titleWrapper } = dataSource; + const { columns, dataSource: tableData, ...$table } = table; + const tableProps = { + ...$table, + columns: this.getColumns(columns.children), + dataSource: this.getDataSource(tableData.children, columns.children), + }; + const childrenToRender = isMobile ? ( + this.getMobileChild(table) + ) : ( +
+ ); + return ( +
+
+
+ {titleWrapper.children.map(getChildrenToRender)} +
+ + + {childrenToRender} + + +
+
+ ); + } +} + +export default Pricing2; diff --git a/client/src/landing/home/data.source.js b/client/src/landing/home/data.source.js new file mode 100644 index 000000000..4033ddc07 --- /dev/null +++ b/client/src/landing/home/data.source.js @@ -0,0 +1,1013 @@ +import React from "react"; +export const Nav00DataSource = { + wrapper: { className: "header0 home-page-wrapper" }, + page: { className: "home-page" }, + logo: { + className: "header0-logo", + children: "https://os.alipayobjects.com/rmsportal/mlcYmsRilwraoAe.svg", + }, + Menu: { + className: "header0-menu", + children: [ + { + name: "item0", + className: "header0-item", + children: { + href: "#", + children: [{ children: "导航一", name: "text" }], + }, + subItem: [ + { + name: "sub0", + className: "item-sub", + children: { + className: "item-sub-item", + children: [ + { + name: "image0", + className: "item-image", + children: + "https://gw.alipayobjects.com/zos/rmsportal/ruHbkzzMKShUpDYMEmHM.svg", + }, + { + name: "title", + className: "item-title", + children: "Ant Design", + }, + { + name: "content", + className: "item-content", + children: "企业级 UI 设计体系", + }, + ], + }, + }, + { + name: "sub1", + className: "item-sub", + children: { + className: "item-sub-item", + children: [ + { + name: "image0", + className: "item-image", + children: + "https://gw.alipayobjects.com/zos/rmsportal/ruHbkzzMKShUpDYMEmHM.svg", + }, + { + name: "title", + className: "item-title", + children: "Ant Design", + }, + { + name: "content", + className: "item-content", + children: "企业级 UI 设计体系", + }, + ], + }, + }, + ], + }, + { + name: "item1", + className: "header0-item", + children: { + href: "#", + children: [{ children: "导航二", name: "text" }], + }, + }, + { + name: "item2", + className: "header0-item", + children: { + href: "#", + children: [{ children: "导航三", name: "text" }], + }, + }, + { + name: "item3", + className: "header0-item", + children: { + href: "#", + children: [{ children: "导航四", name: "text" }], + }, + }, + ], + }, + mobileMenu: { className: "header0-mobile-menu" }, +}; + +export const Banner00DataSource = { + wrapper: { className: "banner0" }, + textWrapper: { className: "banner0-text-wrapper" }, + title: { + className: "banner0-title", + children: "https://zos.alipayobjects.com/rmsportal/HqnZZjBjWRbjyMr.png", + }, + content: { + className: "banner0-content", + children: "一个高效的页面动画解决方案", + }, + button: { className: "banner0-button", children: "Learn More" }, +}; +export const Content40DataSource = { + wrapper: { className: "home-page-wrapper content4-wrapper" }, + page: { className: "home-page content4" }, + OverPack: { playScale: 0.3, className: "" }, + titleWrapper: { + className: "title-wrapper", + children: [ + { + name: "title", + children: "蚂蚁金融云提供专业的服务", + className: "title-h1", + }, + { + name: "content", + className: "title-content content4-title-content", + children: "科技想象力,金融创造力", + }, + ], + }, + video: { + className: "content4-video", + children: { + video: "https://os.alipayobjects.com/rmsportal/EejaUGsyExkXyXr.mp4", + image: "https://zos.alipayobjects.com/rmsportal/HZgzhugQZkqUwBVeNyfz.jpg", + }, + }, +}; +export const Content00DataSource = { + wrapper: { className: "home-page-wrapper content0-wrapper" }, + page: { className: "home-page content0" }, + OverPack: { playScale: 0.3, className: "" }, + titleWrapper: { + className: "title-wrapper", + children: [{ name: "title", children: "产品与服务" }], + }, + childWrapper: { + className: "content0-block-wrapper", + children: [ + { + name: "block0", + className: "content0-block", + md: 8, + xs: 24, + children: { + className: "content0-block-item", + children: [ + { + name: "image", + className: "content0-block-icon", + children: + "https://zos.alipayobjects.com/rmsportal/WBnVOjtIlGWbzyQivuyq.png", + }, + { + name: "title", + className: "content0-block-title", + children: "一站式业务接入", + }, + { name: "content", children: "支付、结算、核算接入产品效率翻四倍" }, + ], + }, + }, + { + name: "block1", + className: "content0-block", + md: 8, + xs: 24, + children: { + className: "content0-block-item", + children: [ + { + name: "image", + className: "content0-block-icon", + children: + "https://zos.alipayobjects.com/rmsportal/YPMsLQuCEXtuEkmXTTdk.png", + }, + { + name: "title", + className: "content0-block-title", + children: "一站式事中风险监控", + }, + { + name: "content", + children: "在所有需求配置环节事前风险控制和质量控制能力", + }, + ], + }, + }, + { + name: "block2", + className: "content0-block", + md: 8, + xs: 24, + children: { + className: "content0-block-item", + children: [ + { + name: "image", + className: "content0-block-icon", + children: + "https://zos.alipayobjects.com/rmsportal/EkXWVvAaFJKCzhMmQYiX.png", + }, + { + name: "title", + className: "content0-block-title", + children: "一站式数据运营", + }, + { + name: "content", + children: "沉淀产品接入效率和运营小二工作效率数据", + }, + ], + }, + }, + ], + }, +}; +export const Content10DataSource = { + wrapper: { className: "home-page-wrapper content1-wrapper" }, + OverPack: { className: "home-page content1", playScale: 0.3 }, + imgWrapper: { className: "content1-img", md: 10, xs: 24 }, + img: { + children: "https://zos.alipayobjects.com/rmsportal/nLzbeGQLPyBJoli.png", + }, + textWrapper: { className: "content1-text", md: 14, xs: 24 }, + title: { className: "content1-title", children: "企业资源管理" }, + content: { + className: "content1-content", + children: + "云资源集中编排、弹性伸缩、持续发布和部署,高可用及容灾。云资源集中编排、弹性伸缩、持续发布和部署,高可用及容灾。云资源集中编排、弹性伸缩、持续发布和部署,高可用及容灾。", + }, +}; +export const Pricing20DataSource = { + wrapper: { className: "home-page-wrapper pricing2-wrapper" }, + page: { className: "home-page pricing2" }, + OverPack: { playScale: 0.3, className: "pricing2-content-wrapper" }, + titleWrapper: { + className: "pricing2-title-wrapper", + children: [ + { name: "title", children: "价目表", className: "pricing2-title-h1" }, + ], + }, + Table: { + name: "tabsTitle", + size: "default", + className: "pricing2-table", + columns: { + children: [ + { + dataIndex: "name", + key: "name", + name: "empty", + childWrapper: { + children: [ + { name: "name", children: " " }, + { name: "content", children: " " }, + ], + }, + }, + { + dataIndex: "free", + key: "free", + name: "free", + childWrapper: { + className: "pricing2-table-name-block", + children: [ + { + name: "name", + className: "pricing2-table-name", + children: "Free", + }, + { + name: "content", + className: "pricing2-table-money", + children: "¥0", + }, + { name: "button", children: { href: "#", children: "免费试用" } }, + ], + }, + }, + { + dataIndex: "basic", + key: "basic", + name: "basic", + childWrapper: { + className: "pricing2-table-name-block", + children: [ + { + name: "name", + className: "pricing2-table-name", + children: "Basic", + }, + { + name: "content", + className: "pricing2-table-money", + children: "¥550", + }, + { name: "button", children: { href: "#", children: "立即购买" } }, + ], + }, + }, + { + dataIndex: "pro", + key: "pro", + name: "pro", + childWrapper: { + className: "pricing2-table-name-block", + children: [ + { + name: "name", + className: "pricing2-table-name", + children: "Pro", + }, + { + name: "content", + className: "pricing2-table-money", + children: "¥2,200", + }, + { + name: "button", + children: { href: "#", type: "primary", children: "立即购买" }, + }, + ], + }, + }, + { + dataIndex: "unlimited", + key: "unlimited", + name: "unlimited", + childWrapper: { + className: "pricing2-table-name-block", + children: [ + { + name: "name", + className: "pricing2-table-name", + children: "Unlimited", + }, + { + name: "content", + className: "pricing2-table-money", + children: "¥5,600", + }, + { name: "button", children: { href: "#", children: "立即购买" } }, + ], + }, + }, + ], + }, + dataSource: { + children: [ + { + name: "list0", + children: [ + { + className: "pricing2-table-content-name", + name: "name", + children: "实例系列1", + }, + { + children: "Limited", + name: "content0", + className: "pricing2-table-content", + }, + { + children: "Unlimited", + name: "content1", + className: "pricing2-table-content", + }, + { + children: "Unlimited", + name: "content2", + className: "pricing2-table-content", + }, + { + children: "Unlimited", + name: "content3", + className: "pricing2-table-content", + }, + ], + }, + { + name: "list1", + children: [ + { + className: "pricing2-table-content-name", + name: "name", + children: "实例系列2", + }, + { + children: "Limited", + name: "content0", + className: "pricing2-table-content", + }, + { + children: "Unlimited", + name: "content1", + className: "pricing2-table-content", + }, + { + children: "Unlimited", + name: "content2", + className: "pricing2-table-content", + }, + { + children: "Unlimited", + name: "content3", + className: "pricing2-table-content", + }, + ], + }, + { + name: "list2", + children: [ + { + className: "pricing2-table-content-name", + name: "name", + children: "固定宽带计费", + }, + { + name: "content0", + children: "50GB", + className: "pricing2-table-content", + }, + { + name: "content1", + children: "250GB", + className: "pricing2-table-content", + }, + { + name: "content2", + children: "600GB", + className: "pricing2-table-content", + }, + { + name: "content3", + children: "Unlimited", + className: "pricing2-table-content", + }, + ], + }, + { + name: "list3", + children: [ + { + className: "pricing2-table-content-name", + name: "name", + children: "闲置负载均衡", + }, + { + children: "-", + name: "content0", + className: "pricing2-table-content", + }, + { + name: "content1", + children: + "https://gw.alipayobjects.com/zos/basement_prod/14ce3060-34e6-4b30-9a45-1a6b95542310.svg", + className: "pricing2-table-content", + }, + { + name: "content2", + children: + "https://gw.alipayobjects.com/zos/basement_prod/14ce3060-34e6-4b30-9a45-1a6b95542310.svg", + className: "pricing2-table-content", + }, + { + name: "content3", + children: + "https://gw.alipayobjects.com/zos/basement_prod/14ce3060-34e6-4b30-9a45-1a6b95542310.svg", + className: "pricing2-table-content", + }, + ], + }, + { + name: "list4", + children: [ + { + className: "pricing2-table-content-name", + name: "name", + children: "4核", + }, + { + name: "content0", + children: "-", + className: "pricing2-table-content", + }, + { + name: "content1", + children: "-", + className: "pricing2-table-content", + }, + { + name: "content2", + children: + "https://gw.alipayobjects.com/zos/basement_prod/14ce3060-34e6-4b30-9a45-1a6b95542310.svg", + className: "pricing2-table-content", + }, + { + name: "content3", + children: + "https://gw.alipayobjects.com/zos/basement_prod/14ce3060-34e6-4b30-9a45-1a6b95542310.svg", + className: "pricing2-table-content", + }, + ], + }, + { + name: "list5", + children: [ + { + className: "pricing2-table-content-name", + name: "name", + children: "系统盘(线性计费)", + }, + { + name: "content0", + children: "-", + className: "pricing2-table-content", + }, + { + name: "content1", + children: "-", + className: "pricing2-table-content", + }, + { + name: "content2", + children: "-", + className: "pricing2-table-content", + }, + { + name: "content3", + children: + "https://gw.alipayobjects.com/zos/basement_prod/14ce3060-34e6-4b30-9a45-1a6b95542310.svg", + className: "pricing2-table-content", + }, + ], + }, + ], + }, + }, +}; +export const Pricing11DataSource = { + wrapper: { className: "home-page-wrapper pricing1-wrapper" }, + page: { className: "home-page pricing1" }, + OverPack: { playScale: 0.3, className: "pricing1-content-wrapper" }, + titleWrapper: { + className: "pricing1-title-wrapper", + children: [ + { name: "title", children: "价目表", className: "pricing1-title-h1" }, + ], + }, + block: { + className: "pricing1-block-wrapper", + children: [ + { + name: "block0", + className: "pricing1-block", + md: 8, + xs: 24, + children: { + wrapper: { className: "pricing1-block-box " }, + topWrapper: { className: "pricing1-top-wrapper" }, + name: { className: "pricing1-name", children: "Free" }, + money: { className: "pricing1-money", children: "¥0" }, + content: { + className: "pricing1-content", + children: ( + + 140-500Mbps +
140 GB-50TB(含) +
14500GB流量包 +
14国内按峰值宽带账单 +
14弹性计算 +
14云服务器 ECS{" "} +
+ ), + }, + line: { className: "pricing1-line" }, + buttonWrapper: { + className: "pricing1-button-wrapper", + children: { + a: { + className: "pricing1-button", + href: "#", + children: "免费试用", + }, + }, + }, + }, + }, + { + name: "block1", + className: "pricing1-block", + md: 8, + xs: 24, + children: { + wrapper: { className: "pricing1-block-box active" }, + topWrapper: { className: "pricing1-top-wrapper" }, + name: { className: "pricing1-name", children: "Starter" }, + money: { className: "pricing1-money", children: "¥199" }, + content: { + className: "pricing1-content", + children: ( + + 14500-5Gbps +
+ 1410 GB-50TB(含) +
+ 141TB流量包 +
+ 14国内按峰值宽带账单 +
+ 14弹性计算 +
+ 云服务器 ECS +
+ ), + }, + line: { className: "pricing1-line" }, + buttonWrapper: { + className: "pricing1-button-wrapper", + children: { + a: { + className: "pricing1-button", + href: "#", + children: "立即购买", + }, + }, + }, + }, + }, + { + name: "block2", + className: "pricing1-block", + md: 8, + xs: 24, + children: { + wrapper: { className: "pricing1-block-box " }, + topWrapper: { className: "pricing1-top-wrapper" }, + name: { className: "pricing1-name", children: "Pro" }, + money: { className: "pricing1-money", children: "¥999" }, + content: { + className: "pricing1-content", + children: ( + + 14大于5Gbps +
+ 1450 GB-100TB(含) +
+ 145TB流量包 +
+ 14国内按峰值宽带账单 +
+ 14弹性计算 +
+ 14云服务器 ECS +
+ ), + }, + line: { className: "pricing1-line" }, + buttonWrapper: { + className: "pricing1-button-wrapper", + children: { + a: { + className: "pricing1-button", + href: "#", + children: "立即购买", + }, + }, + }, + }, + }, + ], + }, +}; +export const Content30DataSource = { + wrapper: { className: "home-page-wrapper content3-wrapper" }, + page: { className: "home-page content3" }, + OverPack: { playScale: 0.3 }, + titleWrapper: { + className: "title-wrapper", + children: [ + { + name: "title", + children: "蚂蚁金融云提供专业的服务", + className: "title-h1", + }, + { + name: "content", + className: "title-content", + children: "基于阿里云强大的基础资源", + }, + ], + }, + block: { + className: "content3-block-wrapper", + children: [ + { + name: "block0", + className: "content3-block", + md: 8, + xs: 24, + children: { + icon: { + className: "content3-icon", + children: + "https://zos.alipayobjects.com/rmsportal/ScHBSdwpTkAHZkJ.png", + }, + textWrapper: { className: "content3-text" }, + title: { className: "content3-title", children: "企业资源管理" }, + content: { + className: "content3-content", + children: + "云资源集中编排、弹性伸缩、持续发布和部署,高可用及容灾。", + }, + }, + }, + { + name: "block1", + className: "content3-block", + md: 8, + xs: 24, + children: { + icon: { + className: "content3-icon", + children: + "https://zos.alipayobjects.com/rmsportal/NKBELAOuuKbofDD.png", + }, + textWrapper: { className: "content3-text" }, + title: { className: "content3-title", children: "云安全" }, + content: { + className: "content3-content", + children: + "按金融企业安全要求打造的完整云上安全体系,全方位保障金融应用及数据安全。", + }, + }, + }, + { + name: "block2", + className: "content3-block", + md: 8, + xs: 24, + children: { + icon: { + className: "content3-icon", + children: + "https://zos.alipayobjects.com/rmsportal/xMSBjgxBhKfyMWX.png", + }, + textWrapper: { className: "content3-text" }, + title: { className: "content3-title", children: "云监控" }, + content: { + className: "content3-content", + children: + "分布式云环境集中监控,统一资源及应用状态视图,智能分析及故障定位。", + }, + }, + }, + { + name: "block3", + className: "content3-block", + md: 8, + xs: 24, + children: { + icon: { + className: "content3-icon", + children: + "https://zos.alipayobjects.com/rmsportal/MNdlBNhmDBLuzqp.png", + }, + textWrapper: { className: "content3-text" }, + title: { className: "content3-title", children: "移动" }, + content: { + className: "content3-content", + children: + "一站式移动金融APP开发及全面监控;丰富可用组件,动态发布和故障热修复。", + }, + }, + }, + { + name: "block4", + className: "content3-block", + md: 8, + xs: 24, + children: { + icon: { + className: "content3-icon", + children: + "https://zos.alipayobjects.com/rmsportal/UsUmoBRyLvkIQeO.png", + }, + textWrapper: { className: "content3-text" }, + title: { className: "content3-title", children: "分布式中间件" }, + content: { + className: "content3-content", + children: + "金融级联机交易处理中间件,大规模分布式计算机,数万笔/秒级并发能力,严格保证交易数据统一性。", + }, + }, + }, + { + name: "block5", + className: "content3-block", + md: 8, + xs: 24, + children: { + icon: { + className: "content3-icon", + children: + "https://zos.alipayobjects.com/rmsportal/ipwaQLBLflRfUrg.png", + }, + textWrapper: { className: "content3-text" }, + title: { className: "content3-title", children: "大数据" }, + content: { + className: "content3-content", + children: + "一站式、全周期大数据协同工作平台,PB级数据处理、毫秒级数据分析工具。", + }, + }, + }, + ], + }, +}; +export const Content120DataSource = { + wrapper: { className: "home-page-wrapper content12-wrapper" }, + page: { className: "home-page content12" }, + OverPack: { playScale: 0.3, className: "" }, + titleWrapper: { + className: "title-wrapper", + children: [ + { + name: "image", + children: + "https://gw.alipayobjects.com/zos/rmsportal/PiqyziYmvbgAudYfhuBr.svg", + className: "title-image", + }, + { name: "title", children: "特别鸣谢", className: "title-h1" }, + ], + }, + block: { + className: "img-wrapper", + children: [ + { + name: "block0", + className: "block", + md: 8, + xs: 24, + children: { + wrapper: { className: "block-content" }, + img: { + children: + "https://gw.alipayobjects.com/zos/rmsportal/TFicUVisNHTOEeMYXuQF.svg", + }, + }, + }, + { + name: "block1", + className: "block", + md: 8, + xs: 24, + children: { + wrapper: { className: "block-content" }, + img: { + children: + "https://gw.alipayobjects.com/zos/rmsportal/hkLGkrlCEkGZeMQlnEkD.svg", + }, + }, + }, + { + name: "block2", + className: "block", + md: 8, + xs: 24, + children: { + wrapper: { className: "block-content" }, + img: { + children: + "https://gw.alipayobjects.com/zos/rmsportal/bqyPRSZmhvrsfJrBvASi.svg", + }, + }, + }, + { + name: "block3", + className: "block", + md: 8, + xs: 24, + children: { + wrapper: { className: "block-content" }, + img: { + children: + "https://gw.alipayobjects.com/zos/rmsportal/UcsyszzOabdCYDkoPPnM.svg", + }, + }, + }, + { + name: "block4", + className: "block", + md: 8, + xs: 24, + children: { + wrapper: { className: "block-content" }, + img: { + children: + "https://gw.alipayobjects.com/zos/rmsportal/kRBeaICGexAmVjqBEqgw.svg", + }, + }, + }, + { + name: "block5", + className: "block", + md: 8, + xs: 24, + children: { + wrapper: { className: "block-content" }, + img: { + children: + "https://gw.alipayobjects.com/zos/rmsportal/ftBIiyJcCHpHEioRvPsV.svg", + }, + }, + }, + ], + }, +}; +export const Footer10DataSource = { + wrapper: { className: "home-page-wrapper footer1-wrapper" }, + OverPack: { className: "footer1", playScale: 0.2 }, + block: { + className: "home-page", + gutter: 0, + children: [ + { + name: "block0", + xs: 24, + md: 6, + className: "block", + title: { + className: "logo", + children: + "https://zos.alipayobjects.com/rmsportal/qqaimmXZVSwAhpL.svg", + }, + childWrapper: { + className: "slogan", + children: [ + { + name: "content0", + children: "Animation specification and components of Ant Design.", + }, + ], + }, + }, + { + name: "block1", + xs: 24, + md: 6, + className: "block", + title: { children: "产品" }, + childWrapper: { + children: [ + { name: "link0", href: "#", children: "产品更新记录" }, + { name: "link1", href: "#", children: "API文档" }, + { name: "link2", href: "#", children: "快速入门" }, + { name: "link3", href: "#", children: "参考指南" }, + ], + }, + }, + { + name: "block2", + xs: 24, + md: 6, + className: "block", + title: { children: "关于" }, + childWrapper: { + children: [ + { href: "#", name: "link0", children: "FAQ" }, + { href: "#", name: "link1", children: "联系我们" }, + ], + }, + }, + { + name: "block3", + xs: 24, + md: 6, + className: "block", + title: { children: "资源" }, + childWrapper: { + children: [ + { href: "#", name: "link0", children: "Ant Design" }, + { href: "#", name: "link1", children: "Ant Motion" }, + ], + }, + }, + ], + }, + copyrightWrapper: { className: "copyright-wrapper" }, + copyrightPage: { className: "home-page" }, + copyright: { + className: "copyright", + children: ( + + ©2018 by Ant Motion All Rights + Reserved + + ), + }, +}; diff --git a/client/src/landing/home/documentation.md b/client/src/landing/home/documentation.md new file mode 100644 index 000000000..ad58ffcce --- /dev/null +++ b/client/src/landing/home/documentation.md @@ -0,0 +1,4 @@ +# 如何使用: + +- umi 里如何使用[请查看](https://landing.ant.design/docs/use/umi)。 +- 其它脚手架使用[请查看](https://landing.ant.design/docs/use/getting-started)。 diff --git a/client/src/landing/home/index.jsx b/client/src/landing/home/index.jsx new file mode 100644 index 000000000..2374e41c2 --- /dev/null +++ b/client/src/landing/home/index.jsx @@ -0,0 +1,142 @@ +/* eslint no-undef: 0 */ +/* eslint arrow-parens: 0 */ +import React from "react"; +import { enquireScreen } from "enquire-js"; +import { Anchor } from "antd"; +import LandingNavigator from "./LandingNavigator"; +import Banner0 from "./Banner0"; +import Content4 from "./Content4"; +import Content0 from "./Content0"; +import Content1 from "./Content1"; +import Pricing2 from "./Pricing2"; +import Pricing1 from "./Pricing1"; +import Content3 from "./Content3"; +import Content12 from "./Content12"; +import Footer1 from "./Footer1"; + +import { + Nav00DataSource, + Banner00DataSource, + Content40DataSource, + Content00DataSource, + Content10DataSource, + Pricing20DataSource, + Pricing11DataSource, + Content30DataSource, + Content120DataSource, + Footer10DataSource, +} from "./data.source"; +import "./less/antMotionStyle.less"; + +let isMobile; +enquireScreen((b) => { + isMobile = b; +}); + +const { location = {} } = typeof window !== "undefined" ? window : {}; + +export default class Home extends React.Component { + constructor(props) { + super(props); + this.state = { + isMobile, + show: !location.port, // 如果不是 dva 2.0 请删除 + }; + } + + componentDidMount() { + // 适配手机屏幕; + enquireScreen((b) => { + this.setState({ isMobile: !!b }); + }); + // dva 2.0 样式在组件渲染之后动态加载,导致滚动组件不生效;线上不影响; + /* 如果不是 dva 2.0 请删除 start */ + if (location.port) { + // 样式 build 时间在 200-300ms 之间; + setTimeout(() => { + this.setState({ + show: true, + }); + }, 500); + } + /* 如果不是 dva 2.0 请删除 end */ + } + + render() { + const children = [ + , + , + , + , + , + , + , + , + , + , + ]; + return ( +
{ + this.dom = d; + }} + > + + {this.state.show && children} + {/* 如果不是 dva 2.0 替换成 {children} end */} + +
+ ); + } +} diff --git a/client/src/landing/home/less/LandingNavigator.less b/client/src/landing/home/less/LandingNavigator.less new file mode 100644 index 000000000..3c662defc --- /dev/null +++ b/client/src/landing/home/less/LandingNavigator.less @@ -0,0 +1,187 @@ +@header0: header0; + +.@{header0} { + background: @template-nav-bg-color; + width: 100%; + z-index: 1; + box-shadow: 0 5px 8px fade(#000, 15); + position: relative; + top: 0; + + .home-page { + padding: 0 24px; + } + + &-logo { + display: inline-block; + position: relative; + width: 150px; + line-height: 64px; + + & img { + vertical-align: middle; + display: inline-block; + } + + & a { + display: block; + } + } + + &-menu { + float: right; + + .ant-menu { + line-height: 62px; + height: 64px; + + a { + display: block; + } + } + } + + &-item { + &-block { + padding: 0 8px; + + >* { + display: inline-block; + } + } + } + + &-item, + &-item-child, + &-menu { + + .ant-menu-sub .ant-menu-item, + .ant-menu-inline .ant-menu-item { + height: auto; + line-height: 1.5; + } + + .item { + &-sub-item { + display: block; + padding: 8px 24px; + } + + &-image { + float: left; + margin-right: 16px; + margin-top: 4px; + position: relative; + z-index: 1; + } + + &-title { + font-size: 14px; + color: #fff; + margin-left: 46px; + } + + &-content { + font-size: 12px; + color: fade(#fff, 75); + margin-left: 46px; + } + } + } +} + +@media screen and (max-width: 767px) { + .@{header0} { + &-logo { + z-index: 101; + } + + &.home-page-wrapper .home-page { + padding: 0 24px; + } + + &-menu { + height: auto; + float: inherit; + position: relative; + left: -24px; + width: ~"calc(100% + 48px)"; + opacity: 0; + transition: opacity .3s @ease-in-out; + + & li { + padding: 0 24px; + + &.ant-menu-submenu { + padding: 0; + } + } + .item { + &-sub-item { + padding: 8px 0; + } + } + } + + &-mobile-menu { + width: 16px; + height: 14px; + cursor: pointer; + position: absolute; + top: 24px; + right: 24px; + z-index: 100; + + em { + display: block; + width: 100%; + height: 2px; + background: #fff; + margin-top: 4px; + transition: transform .3s @ease-in-out, opacity .3s @ease-in-out; + } + + :first-child { + margin-top: 0; + } + } + + .ant-menu { + height: auto; + overflow: hidden; + + .ant-menu-item-selected { + border: none; + } + } + + & .open { + height: auto; + + .@{header0}-mobile-menu { + em { + &:nth-child(1) { + transform: translateY(6px) rotate(45deg); + } + + &:nth-child(2) { + opacity: 0; + } + + &:nth-child(3) { + transform: translateY(-6px) rotate(-45deg); + } + } + } + + >.@{header0}-menu { + opacity: 1; + pointer-events: auto; + } + } + &-item-block { + height: 40px; + line-height: 40px; + } + } +} diff --git a/client/src/landing/home/less/antMotionStyle.less b/client/src/landing/home/less/antMotionStyle.less new file mode 100644 index 000000000..f254f0346 --- /dev/null +++ b/client/src/landing/home/less/antMotionStyle.less @@ -0,0 +1,14 @@ +@import "./common.less"; +@import "./custom.less"; +@import "./content.less"; +@import "./LandingNavigator.less"; +@import "./banner0.less"; +@import "./content4.less"; +@import "./content0.less"; +@import "./content1.less"; +@import "./pricing2.less"; +@import "./pricing1.less"; +@import "./content3.less"; +@import "./content12.less"; +@import "./footer1.less"; +@import "./edit.less"; diff --git a/client/src/landing/home/less/banner0.less b/client/src/landing/home/less/banner0.less new file mode 100644 index 000000000..829bb9c4b --- /dev/null +++ b/client/src/landing/home/less/banner0.less @@ -0,0 +1,84 @@ +@banner0: banner0; +.@{banner0} { + // 如果在第一屏且导航位置为 relative, 一屏为 height: calc(~"100vh - 64px"); + width: 100%; + height: 100vh; + position: relative; + text-align: center; + border-color: #666; + background-image: url("https://zos.alipayobjects.com/rmsportal/gGlUMYGEIvjDOOw.jpg"); + background-size: cover; + background-attachment: fixed; + background-position: center; + & &-text-wrapper { + display: inline-block; + position: absolute; + top: 20%; + margin: auto; + left: 0; + right: 0; + font-size: 14px; + color: @template-text-color-light; + width: 550px; + >.queue-anim-leaving { + position: relative !important; + } + } + & &-title { + width: 350px; + left: 30px; + min-height: 60px; + margin: auto; + display: inline-block; + font-size: 40px; + position: relative; + } + & &-content { + margin-bottom: 20px; + word-wrap: break-word; + min-height: 24px; + } + & &-button { + border: 1px solid #fff; + color: #fff; + background: transparent; + box-shadow: 0 0 0 transparent; + font-size: 16px; + height: 40px; + transition: background .45s @ease-out, box-shadow .45s @ease-out; + &:hover { + color: #fff; + border-color: #fff; + background: rgba(255, 255, 255, 0.1); + box-shadow: 0 0 10px rgba(50, 250, 255, 0.75); + } + &:focus { + color: #fff; + border-color: #fff; + } + &.queue-anim-leaving { + width: auto; + } + } + & &-icon { + bottom: 20px; + font-size: 24px; + position: absolute; + left: 50%; + margin-left: -12px; + color: @template-text-color-light; + } +} + +@media screen and (max-width: 767px) { + .@{banner0} { + background-attachment: inherit; + & &-text-wrapper { + width: 90%; + } + & &-title { + width: 90%; + left: 0; + } + } +} diff --git a/client/src/landing/home/less/common.less b/client/src/landing/home/less/common.less new file mode 100644 index 000000000..a0ca2a04c --- /dev/null +++ b/client/src/landing/home/less/common.less @@ -0,0 +1,42 @@ + +// @import "~antd/lib/style/v2-compatible-reset.less"; + +body { + word-wrap: break-word; +} + +body, +div, +dl, +dt, +dd, +ul, +ol, +li, +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + padding: 0; +} + +/* .content-wrapper > .tween-one-leaving, +.queue-anim-leaving { + // position: absolute !important; + // width: 100%; +} */ + +.video { + max-width: 800px; +} + +#react-content { + min-height: 100%; +} +.home-page-wrapper p { + padding: 0; + margin: 0; +} diff --git a/client/src/landing/home/less/content.less b/client/src/landing/home/less/content.less new file mode 100644 index 000000000..c5ebf367c --- /dev/null +++ b/client/src/landing/home/less/content.less @@ -0,0 +1,44 @@ +@homepage: home-page; +.@{homepage}-wrapper { + width: 100%; + position: relative; + overflow: hidden; + .@{homepage} { + height: 100%; + max-width: 1200px; + position: relative; + margin: auto; + will-change: transform; + } + .title-wrapper > h1, > h1 { + font-size: 32px; + color: @text-color; + margin-bottom: 16px; + } + .title-wrapper { + margin: 0 auto 64px; + text-align: center; + } +} + +.@{homepage} { + padding: 128px 24px; +} + +@media screen and (max-width: 767px) { + .@{homepage}-wrapper { + .@{homepage} { + padding: 56px 24px; + >h1 { + font-size: 24px; + margin: 0 auto 32px; + &.title-h1 { + margin-bottom: 8px; + } + } + >p { + margin-bottom: 32px; + } + } + } +} diff --git a/client/src/landing/home/less/content0.less b/client/src/landing/home/less/content0.less new file mode 100644 index 000000000..0a97b2ef5 --- /dev/null +++ b/client/src/landing/home/less/content0.less @@ -0,0 +1,55 @@ +@content0: content0; + +.@{content0}-wrapper { + min-height: 446px; + overflow: hidden; + + .@{content0} { + height: 100%; + padding: 64px 24px; + + >.title-wrapper { + margin: 0 auto 48px; + } + + &-block { + padding: 0 4%; + display: inline-block; + text-align: center; + min-height: 200px; + margin-bottom: 24px; + img { + width: 100%; + } + + &-wrapper { + position: relative; + height: 100%; + top: 25%; + padding: 20px 0; + } + + &.queue-anim-leaving { + position: relative !important; + } + + &-icon { + width: 100px; + height: 100px; + margin: auto; + } + + &-title { + line-height: 32px; + margin: 10px auto; + font-size: 24px; + } + } + } +} + +@media screen and (max-width: 767px) { + .@{content0}-wrapper { + min-height: 880px; + } +} diff --git a/client/src/landing/home/less/content1.less b/client/src/landing/home/less/content1.less new file mode 100644 index 000000000..4d03ff366 --- /dev/null +++ b/client/src/landing/home/less/content1.less @@ -0,0 +1,76 @@ +@content1: content1; +.@{content1}-wrapper { + height: 360px; + .@{content1} { + height: 100%; + padding: 0 24px; + &-img { + height: 100%; + transform-origin: top; + padding: 0 32px; + display: flex; + align-items: center; + justify-content: center; + span { + display: block; + width: 250px; + img { + display: block; + } + } + } + &-text { + padding: 0 32px; + height: 100%; + .@{content1}-content, + .@{content1}-title { + position: relative !important; + } + .@{content1}-title { + font-size: 32px; + font-weight: normal; + color: #404040; + margin-top: 120px; + } + .content { + margin-top: 20px; + } + } + } +} + +@media screen and (max-width: 767px) { + .@{content1}-wrapper { + height: 600px; + .@{content1} { + &-img { + height: 200px; + padding: 0; + text-align: center; + margin-top: 64px; + span { + display: inline-block; + width: 180px; + height: 200px; + line-height: 200px; + margin: auto; + } + } + &-text { + height: auto; + margin-bottom: 20px; + text-align: center; + padding: 0; + .@{content1}-content, + .@{content1}-title { + width: 100%; + top: auto; + } + .@{content1}-title { + margin: 32px auto 16px; + font-size: 24px; + } + } + } + } +} diff --git a/client/src/landing/home/less/content12.less b/client/src/landing/home/less/content12.less new file mode 100644 index 000000000..4d4f05f53 --- /dev/null +++ b/client/src/landing/home/less/content12.less @@ -0,0 +1,52 @@ +@content12: content12; +.@{content12}-wrapper { + background-color: #fafafa; + min-height: 470px; + .@{content12} { + padding: 64px 24px; + >p { + text-align: center; + } + } + .img-wrapper { + margin: 0 auto; + left: 0; + right: 0; + .block { + margin-bottom: 40px; + .block-content { + display: flex; + border-radius: 4px; + text-align: center; + position: relative; + overflow: hidden; + border: none; + height: 64px; + align-items: center; + transition: box-shadow .3s @ease-out, transform .3s @ease-out; + & > span { + width: 100%; + display: block; + } + } + } + } +} + +@media screen and (max-width: 767px) { + .@{content12}-wrapper { + overflow: hidden; + .@{content12} { + ul { + li { + display: block; + width: 100%; + padding: 2%; + span { + height: 168px; + } + } + } + } + } +} diff --git a/client/src/landing/home/less/content3.less b/client/src/landing/home/less/content3.less new file mode 100644 index 000000000..24ee0e4f7 --- /dev/null +++ b/client/src/landing/home/less/content3.less @@ -0,0 +1,52 @@ +@content3: content3; +.@{content3}-wrapper { + min-height: 764px; + .@{content3} { + height: 100%; + overflow: hidden; + & .title-content { + text-align: center; + } + &-block-wrapper { + position: relative; + .@{content3}-block { + display: inline-block; + padding: 48px 24px; + vertical-align: top; + .@{content3}-icon { + display: inline-block; + width: 15%; + vertical-align: top; + } + .@{content3}-text { + width: 85%; + display: inline-block; + padding-left: 8%; + } + &.clear-both { + clear: both; + } + } + } + } +} + +@media screen and (max-width: 767px) { + .@{content3}-wrapper { + min-height: 1080px; + .@{content3} { + &-block-wrapper { + margin: 20px auto; + height: auto; + .@{content3}-block { + .@{content3}-title { + font-size: 20px; + } + &.queue-anim-leaving { + position: relative !important; + } + } + } + } + } +} diff --git a/client/src/landing/home/less/content4.less b/client/src/landing/home/less/content4.less new file mode 100644 index 000000000..c700bfb2a --- /dev/null +++ b/client/src/landing/home/less/content4.less @@ -0,0 +1,37 @@ +@content4: content4; +.@{content4}-wrapper { + min-height: 720px; + background: #fafafa; + .@{content4} { + height: 100%; + overflow: hidden; + &-video { + border-radius: 4px; + overflow: hidden; + max-width: 800px; + margin: auto; + background: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, .15); + video { + display: block; + margin: auto; + } + } + } +} + +@media screen and (max-width: 767px) { + .@{content4}-wrapper { + min-height: 350px; + .@{content4} { + overflow: hidden; + width: 90%; + margin: auto; + &-video { + top: 15%; + background: url("https://zos.alipayobjects.com/rmsportal/HZgzhugQZkqUwBVeNyfz.jpg") no-repeat center; + background-size: cover; + } + } + } +} diff --git a/client/src/landing/home/less/custom.less b/client/src/landing/home/less/custom.less new file mode 100644 index 000000000..710e47c9d --- /dev/null +++ b/client/src/landing/home/less/custom.less @@ -0,0 +1,35 @@ +@import "~antd/lib/style/themes/default.less"; + +@line-color: #e9e9e9; + +@shadow-color: rgba(0, 0, 0, 0.15); + +@bottom-bar-bg-color: #262626; +@bottom-bar-line-color: #000; + +@template-bg-color: #001529; +@template-bg-color-light: #ececec; +@template-nav-bg-color: #001529; +@template-text-color: #ccc; +@template-text-title-color: #bcbcbc; +@template-text-color-light: #fff; +@template-footer-text-color: #999; + +@animate-duration: .45s; + +/* 详细页图片或框框的样式; +*/ +.page-shadow() { + box-shadow: 0 5px 8px @shadow-color; +} + +.page-pro() { + border-radius: 6px; + border: 1px solid @line-color; + transform: translateY(0); + transition: transform .3s @ease-out, box-shadow .3s @ease-out; + &:hover { + .page-shadow(); + transform: translateY(-5px); + } +} diff --git a/client/src/landing/home/less/edit.less b/client/src/landing/home/less/edit.less new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/landing/home/less/footer1.less b/client/src/landing/home/less/footer1.less new file mode 100644 index 000000000..8d8579b8a --- /dev/null +++ b/client/src/landing/home/less/footer1.less @@ -0,0 +1,98 @@ +.footer1-wrapper { + background: @template-bg-color; + overflow: hidden; + position: relative; + min-height: 360px; + color: @template-footer-text-color; + .footer1 { + .home-page { + padding: 64px 24px 80px; + } + } + .block { + padding: 0 32px; + .logo { + max-width: 180px; + } + .slogan { + font-size: 12px; + margin-top: -20px; + } + >h2 { + margin-bottom: 24px; + color: @template-text-color; + } + a { + color: @template-footer-text-color; + margin-bottom: 12px; + float: left; + clear: both; + &:hover { + color: @primary-color; + } + } + } + .copyright-wrapper { + width: 100%; + border-top: 1px solid fade(@line-color, 10); + .home-page { + padding: 0 24px; + overflow: hidden; + } + .copyright { + height: 80px; + text-align: center; + line-height: 80px; + } + } +} + +@media screen and (max-width: 767px) { + .footer1 { + min-height: 550px; + &-wrapper { + .footer1 { + .home-page { + padding: 64px 24px 32px; + } + } + } + .logo { + margin: 0 auto 24px; + } + .block { + text-align: center; + margin-bottom: 32px; + padding: 0; + } + >ul { + width: 90%; + margin: 20px auto 0; + padding: 10px 0; + >li { + width: 100%; + h2 { + margin-bottom: 10px; + } + li { + display: inline-block; + margin-right: 10px; + } + } + } + .copyright { + &-wrapper { + .home-page { + padding: 0; + .copyright { + font-size: 12px; + } + } + } + + span { + width: 90%; + } + } + } +} diff --git a/client/src/landing/home/less/pricing1.less b/client/src/landing/home/less/pricing1.less new file mode 100644 index 000000000..ef736351f --- /dev/null +++ b/client/src/landing/home/less/pricing1.less @@ -0,0 +1,85 @@ +@pricing1: pricing1; +.@{pricing1}-wrapper { + min-height: 760px; + .@{pricing1} { + >p { + text-align: center; + } + &-content-wrapper { + min-height: 400px; + } + &-block-box { + width: 260px; + border-radius: 4px; + background: #eef0f3; + text-align: center; + color: #666; + min-height: 400px; + margin: auto; + border: 1px solid transparent; + .page-pro(); + &.active { + border-color: @primary-color; + background: #fff; + .@{pricing1} { + &-top-wrapper { + background: @primary-color; + } + &-name, + &-money, + &-button { + color: #fff; + } + &-button { + background: @primary-color; + } + } + } + } + &-block { + margin-bottom: 24px; + } + &-top-wrapper { + width: 100%; + padding: 16px 24px; + } + &-name { + font-size: 14px; + } + &-money { + font-family: 'Helvetica Neue', sans-serif; + font-size: 32px; + color: #666; + } + &-content { + font-size: 12px; + line-height: 2; + font-weight: 300; + margin: 32px 24px 48px; + } + &-line { + display: block; + height: 1px; + background: #d9d9d9; + margin: 0 24px; + } + &-button-wrapper { + margin: 18px 24px; + } + &-button { + padding: 0 24px; + } + } + &.home-page-wrapper { + .@{pricing1}-title-wrapper { + margin-bottom: 64px; + text-align: center; + } + } +} + +@media screen and (max-width: 767px) { + .@{pricing1}-wrapper { + padding-bottom: 0; + } +} diff --git a/client/src/landing/home/less/pricing2.less b/client/src/landing/home/less/pricing2.less new file mode 100644 index 000000000..69b193ef7 --- /dev/null +++ b/client/src/landing/home/less/pricing2.less @@ -0,0 +1,59 @@ +@pricing2: pricing2; + +.@{pricing2}-wrapper { + min-height: 760px; + + .@{pricing2} { + >p { + text-align: center; + } + + &-content-wrapper { + min-height: 400px; + } + + &-table-name-block { + text-align: center; + color: #666; + width: 100%; + } + + &-table-name { + font-size: 24px; + } + + &-table-money { + font-size: 16px; + margin: 8px 0 16px; + } + + &-table-content { + text-align: center; + color: #666; + + &-name { + color: #666; + text-align: center; + } + } + } + + &.home-page-wrapper { + .@{pricing2}-title-wrapper { + margin-bottom: 64px; + text-align: center; + } + } +} + +@media screen and (max-width: 767px) { + .@{pricing2} { + &-wrapper { + padding-bottom: 0; + } + + &-table { + margin-bottom: 24px; + } + } +} diff --git a/client/src/landing/home/utils.js b/client/src/landing/home/utils.js new file mode 100644 index 000000000..57cf9cb18 --- /dev/null +++ b/client/src/landing/home/utils.js @@ -0,0 +1,18 @@ + +import React from 'react'; +import { Button } from 'antd'; + +export const isImg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?/; +export const getChildrenToRender = (item, i) => { + let tag = item.name.indexOf('title') === 0 ? 'h1' : 'div'; + tag = item.href ? 'a' : tag; + let children = typeof item.children === 'string' && item.children.match(isImg) + ? React.createElement('img', { src: item.children, alt: 'img' }) + : item.children; + if (item.name.indexOf('button') === 0 && typeof item.children === 'object') { + children = React.createElement(Button, { + ...item.children + }); + } + return React.createElement(tag, { key: i.toString(), ...item }, children); +}; diff --git a/client/src/pages/landing/landing.page.jsx b/client/src/pages/landing/landing.page.jsx index 03085daf5..4f98800fd 100644 --- a/client/src/pages/landing/landing.page.jsx +++ b/client/src/pages/landing/landing.page.jsx @@ -3,6 +3,7 @@ import { connect } from "react-redux"; import { Redirect } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { selectCurrentUser } from "../../redux/user/user.selectors"; +import LandingPageStatic from "../../landing/home/index"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, @@ -13,5 +14,6 @@ export default connect(mapStateToProps, null)(LandingPage); export function LandingPage({ currentUser }) { if (currentUser.authorized) return ; - return ; + return ; + //return ; } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 3b6e66bf4..ce6095b2b 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1423,6 +1423,13 @@ "voided": "Job voided successfully." } }, + "landing": { + "labels": { + "features": "Features", + "managemyshop": "Manage my Shop", + "pricing": "Pricing" + } + }, "menus": { "currentuser": { "languageselector": "Language", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index c22819cda..3b3b79188 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1423,6 +1423,13 @@ "voided": "" } }, + "landing": { + "labels": { + "features": "", + "managemyshop": "", + "pricing": "" + } + }, "menus": { "currentuser": { "languageselector": "idioma", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 6021200d5..44b471439 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1423,6 +1423,13 @@ "voided": "" } }, + "landing": { + "labels": { + "features": "", + "managemyshop": "", + "pricing": "" + } + }, "menus": { "currentuser": { "languageselector": "La langue", diff --git a/client/yarn.lock b/client/yarn.lock index 86d239f03..544b8042a 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -3472,7 +3472,7 @@ babel-preset-react-app@^10.0.0: babel-plugin-macros "2.8.0" babel-plugin-transform-react-remove-prop-types "0.4.24" -babel-runtime@^6.26.0: +babel-runtime@6.x, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -4892,6 +4892,13 @@ deep-diff@^0.3.5: resolved "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz" integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ= +deep-eql@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" @@ -5313,6 +5320,18 @@ enhanced-resolve@^4.3.0: memory-fs "^0.5.0" tapable "^1.0.0" +enquire-js@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/enquire-js/-/enquire-js-0.2.1.tgz#f2478cf5808d42f54e8231f20fa133493e7f0fcb" + integrity sha512-4vbcWD0ncK6VQ5M5giOImQb2hFPrKDZH5U+uRX9S6e9vfC6Q5PX6A38PVS6RMnCdr/luDTtJjjLuJinH/+a+Lw== + dependencies: + enquire.js "^2.1.6" + +enquire.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/enquire.js/-/enquire.js-2.1.6.tgz#3e8780c9b8b835084c3f60e166dbc3c2a3c89814" + integrity sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ= + enquirer@^2.3.5: version "2.3.6" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" @@ -10179,7 +10198,7 @@ prompts@2.4.0, prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -10335,7 +10354,7 @@ raf-schd@^4.0.2: resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz" integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== -raf@^3.4.0, raf@^3.4.1: +raf@3.x, raf@^3.4.0, raf@^3.4.1, raf@~3.4.0: version "3.4.1" resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -10552,6 +10571,16 @@ rc-progress@~3.1.0: "@babel/runtime" "^7.10.1" classnames "^2.2.6" +rc-queue-anim@^1.8.5: + version "1.8.5" + resolved "https://registry.yarnpkg.com/rc-queue-anim/-/rc-queue-anim-1.8.5.tgz#01ef3872bdfa0b70bb915ef9a637fc404244a589" + integrity sha512-vTbZXBu7L3NcXUPjkFN7R80BE+1VYL1QBI10EioYYqZMk6A0iVbjoVAgfoK/Z4gIIxp399gJ8LqbMnQA1AhcXA== + dependencies: + babel-runtime "6.x" + prop-types "^15.6.0" + rc-tween-one "^2.5.0" + react-lifecycles-compat "^3.0.4" + rc-rate@~2.9.0: version "2.9.1" resolved "https://registry.npmjs.org/rc-rate/-/rc-rate-2.9.1.tgz" @@ -10571,6 +10600,18 @@ rc-resize-observer@^1.0.0: rc-util "^5.0.0" resize-observer-polyfill "^1.5.1" +rc-scroll-anim@^2.7.6: + version "2.7.6" + resolved "https://registry.yarnpkg.com/rc-scroll-anim/-/rc-scroll-anim-2.7.6.tgz#f7e6622f2930ca3e1e258f7275bc2e1c26ce791c" + integrity sha512-VwXJYXjZy9TtH1wcQIG7/yjt/Ay3VEjQl/TITaWzK9O7ujjOXRVOYY/tqKshmBMgaJ2oGeFQNmCN8zTwXguq0g== + dependencies: + babel-runtime "6.x" + prop-types "^15.6.0" + raf "3.x" + rc-tween-one "^2.4.0" + react-lifecycles-compat "^3.0.4" + tween-functions "1.x" + rc-select@^12.0.0, rc-select@~12.1.6: version "12.1.10" resolved "https://registry.npmjs.org/rc-select/-/rc-select-12.1.10.tgz" @@ -10687,6 +10728,30 @@ rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.1: rc-motion "^2.0.0" rc-util "^5.5.0" +rc-tween-one@^1.2.5: + version "1.8.1" + resolved "https://registry.yarnpkg.com/rc-tween-one/-/rc-tween-one-1.8.1.tgz#5b3b464b9bf2c369efc16c816cccf57bc16ae253" + integrity sha512-Avg8EXHdt6ABV9WnmTmh6zEaAzUvl4bFZKbP3y6BE8UGBGp1qUhlIgCB83gL+5eA0VECdM/b9PsEBRrcxzSpGw== + dependencies: + babel-runtime "6.x" + deep-eql "~3.0.1" + prop-types "^15.6.1" + raf "~3.4.0" + style-utils "~0.1.13" + tween-functions "~1.2.0" + +rc-tween-one@^2.4.0, rc-tween-one@^2.5.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/rc-tween-one/-/rc-tween-one-2.7.3.tgz#c9d3c44743e25c654d65c22ec3934afd79923fae" + integrity sha512-n4OPRLO6VMZHj61unq5KKxHMMfBz52bxob94fN3U5M9GqFg3H+T3TXnpHPnAK+cq/xBGo70ik2vB4Fpjo/txcA== + dependencies: + babel-runtime "6.x" + prop-types "^15.6.1" + raf "~3.4.0" + react-lifecycles-compat "^3.0.4" + style-utils "~0.2.0" + tween-functions "~1.2.0" + rc-upload@~4.3.0: version "4.3.1" resolved "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.1.tgz" @@ -11064,6 +11129,14 @@ react-smooth@^2.0.0: raf "^3.4.0" react-transition-group "2.9.0" +react-sublime-video@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/react-sublime-video/-/react-sublime-video-0.2.5.tgz#c967b8e9a374b36d6a5d1b63b93fa6ec02e54842" + integrity sha1-yWe46aN0s21qXRtjuT+m7ALlSEI= + dependencies: + prop-types "^15.5.10" + rc-tween-one "^1.2.5" + react-transition-group@2, react-transition-group@2.9.0: version "2.9.0" resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz" @@ -12441,6 +12514,16 @@ style-loader@1.3.0: loader-utils "^2.0.0" schema-utils "^2.7.0" +style-utils@~0.1.13: + version "0.1.24" + resolved "https://registry.yarnpkg.com/style-utils/-/style-utils-0.1.24.tgz#fc0675d79a0b201bf86fc5d5a1dd202f838de544" + integrity sha512-MVZSKubpU/vIfpmOsi8/0ckWxb0WmGBmyNoEDGWZM9cM8n8sCL6DJftl3lEf8Uy5zKQ9+O1XdJxscWTDosCQpQ== + +style-utils@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/style-utils/-/style-utils-0.2.1.tgz#c78fe6696214f4ab12701959f09553e9d81dd45b" + integrity sha512-eKRIfWnUSdBqe2ko+qisUwBSlfWpHru89geRqzmScpDhkPW1ksmE04d//nDcXeF+TVK5cnBG90mMmHgxyxXleQ== + styled-components@^5.3.0: version "5.3.0" resolved "https://registry.npmjs.org/styled-components/-/styled-components-5.3.0.tgz" @@ -12848,6 +12931,11 @@ tty-browserify@0.0.0: resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= +tween-functions@1.x, tween-functions@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff" + integrity sha1-GuOlDnxguz3vd06scHrLynO7w/8= + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" @@ -12862,7 +12950,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8: +type-detect@4.0.8, type-detect@^4.0.0: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==