Merge pull request #2 from woodchen-ink:rutikwankhade-master

Rutikwankhade-master
This commit is contained in:
wood chen 2024-10-21 12:57:12 +08:00 committed by GitHub
commit 90c57dd33c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 20839 additions and 459 deletions

View File

@ -14,7 +14,8 @@ Creating cover images for your blogs is now super easy.
<img src="https://user-images.githubusercontent.com/47467468/175771056-bf7fa9a0-801b-4887-80b5-169735923d64.png" height="auto" width="800px" margin="20px">
<img src="https://gist.github.com/user-attachments/assets/1d1c1833-29bc-45d6-97dd-e26c2d1019cb
" height="auto" width="800px" margin="20px">
@ -23,9 +24,9 @@ Creating cover images for your blogs is now super easy.
## ⚡ Features
- 🚀 super fast and easy to use
- 🌈 4 different themes, multiple fonts
- ✨ unsplash integration to search images
- 🌈 7 different themes, multiple fonts
- 🌠 100+ dev icons with option to upload custom icon
- ✨ 15+ different background patterns
- 💾 Cover size based on blogging platform (i.e hashnode and dev)
## 👩‍💻 Developing
@ -52,10 +53,10 @@ Pull requests are welcome. For major changes, please open an issue first to disc
## 🙏 Acknowledgments
- [react-component-export-image](https://www.npmjs.com/package/react-component-export-image)
- [dom-to-image](https://github.com/tsayen/dom-to-image)
- [Hero Patterns](https://www.heropatterns.com/)
- [Devicons](https://github.com/devicons/devicon)
Don't forget to leave a ⭐ if you found this useful.
Don't forget to leave a ⭐ if you found this useful. Also checkout more products i built at [rutik.dev](https://rutik.dev)

20429
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -41,13 +41,11 @@ const CoverImage = (props) => {
return (
<div className="md:w-full md:scale-100 scale-50">
{selectTheme(theme)} </div>
<div className={`border-2 border-gray-50 md:scale-100 scale-50 ${props.platform}`}>
{selectTheme(theme)}
</div>
);
}
export default CoverImage;

View File

@ -5,18 +5,9 @@ import Select from 'react-select';
import RandomTheme from './RandomTheme';
import { ImgProvider } from '../utils/ImgContext'
import Header from "./Header";
import { Tab } from '@headlessui/react'
import theme1 from '../assets/images/theme1.webp'
import theme2 from '../assets/images/theme2.webp'
import theme3 from '../assets/images/theme3.webp'
import theme4 from '../assets/images/theme4.webp'
import theme5 from '../assets/images/theme5.webp'
import theme6 from '../assets/images/theme6.webp'
import theme7 from '../assets/images/theme7.webp'
import { THEMES } from "../utils/constants";
const defaultIcon = { 'label': 'react', 'value': 'react' }
@ -31,30 +22,27 @@ const defaultSettings = {
font: 'font-Anek',
theme: '背景',
customIcon: '',
platform: 'Hashnode'
platform: 'hashnode'
};
const devIconsUrl = "https://mirror.czl.net/https://raw.githubusercontent.com/devicons/devicon/master/devicon.json"
// const devIconOptions = [
// { value: 'None', label: 'None' },
// { value: 'javascript', label: 'Javascript' },
// { value: 'python', label: 'Python' },
// ]
class Editor extends React.Component {
state = defaultSettings;
componentDidMount() {
console.log("Mount")
// console.log("Mount")
fetch(devIconsUrl).then(r => r.json()).then(data => {
data.push({ name: 'custom' })
data.unshift({ name: 'upload your own' })
this.setState({ devIconOptions: data.map(item => ({ 'value': item.name, 'label': item.name })) })
})
}
handleReset = () => {
this.setState(defaultSettings);
this.setState({
...defaultSettings,
devIconOptions: this.state.devIconOptions,
});
};
getRandomTheme = (theme, Pattern) => {
@ -74,83 +62,77 @@ class Editor extends React.Component {
render() {
return (
<div>
<div className="max-w-[1400px] mx-auto">
<Header />
<ImgProvider>
<div className="flex md:flex-row flex-col bg-gray-50 ">
<div className="flex md:flex-row flex-col ">
<div className="bg-white flex flex-col h-100 md:w-4/12">
<div className="bg-white flex flex-col h-100 md:w-3/12">
<Tab.Group>
<div>
<div className="flex md:flex-row flex-col">
<Tab.List className=" bg-white md:p-0 p-2 flex flex-row md:flex-col">
<Tab className="flex items-center font-semibold ">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" className="text-gray- bg-white rounded-xl w-12 m-2 h-12 p-2 rounded border" width="24" height="24" viewBox="0 0 24 24" ><path d="M19.045 7.401c.378-.378.586-.88.586-1.414s-.208-1.036-.586-1.414l-1.586-1.586c-.378-.378-.88-.586-1.414-.586s-1.036.208-1.413.585L4 13.585V18h4.413L19.045 7.401zm-3-3 1.587 1.585-1.59 1.584-1.586-1.585 1.589-1.584zM6 16v-1.585l7.04-7.018 1.586 1.586L7.587 16H6zm-2 4h16v2H4z"></path></svg>
</Tab>
<Tab className="flex items-center font-semibold text-lg">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" className=" text-gray-800 bg-white rounded-xl w-12 h-12 p-2 m-2 rounded border" width="24" height="24" viewBox="0 0 24 24" ><path d="M11.024 11.536 10 10l-2 3h9l-3.5-5z"></path><circle cx="9.503" cy="7.497" r="1.503"></circle><path d="M19 2H6c-1.206 0-3 .799-3 3v14c0 2.201 1.794 3 3 3h15v-2H6.012C5.55 19.988 5 19.806 5 19s.55-.988 1.012-1H21V4c0-1.103-.897-2-2-2zm0 14H5V5c0-.806.55-.988 1-1h13v12z"></path></svg>
</Tab>
</Tab.List>
<Tab.Panels className="bg-white border-l w-full p-4 ">
<Tab.Panel>
<div className="bg-white font-Inter border-dashed border-r-2 border-gray-100 w-full p-4 ">
<div>
<div className="m-2 flex flex-col">
<span className="font-medium pb-1">Blog Title</span>
<span className="font-medium text-sm pb-1">Blog Title</span>
<textarea
type="text"
value={this.state.title}
placeholder="Enter title here"
className="focus:outline-none border text-gray-700 text-xl rounded p-2 h-24"
className="focus:outline-none border text-gray-700 text-lg rounded p-2 h-24"
onChange={(e) => this.setState({ title: e.target.value })}
/>
</div>
<div className="flex flex-col m-2 ">
<span className="font-medium pb-1">Author</span>
<span className="font-medium text-sm pb-1">Author</span>
<input
type="text"
value={this.state.author}
placeholder="Author"
className="focus:outline-none border text-gray-700 text-xl rounded bg-white p-2"
className="focus:outline-none border text-gray-700 text-lg rounded bg-white p-2"
onChange={(e) => this.setState({ author: e.target.value })}
></input>
</div>
<div className="flex flex-col m-2 ">
<span className="font-medium pb-1">Icon</span>
<span className="font-medium text-sm pb-1">Icon</span>
<Select value={this.state.icon}
onChange={(selectedOption) => this.setState({ icon: selectedOption })}
options={this.state.devIconOptions}
formatOptionLabel={this.formatOptionLabel}
className="outline-none focus:outline-none text-xl text-gray-700"
className="outline-none focus:outline-none items-center text-lg text-gray-700"
/>
</div>
<div className="w-full">
{this.state.icon.label === 'custom' ?
<div className="flex items-center justify-center m-2">
<input type="file"
className="focus:outline-none text-lg cursor-pointer bg-white rounded border"
onChange={(e) => this.setState({ 'customIcon': URL.createObjectURL(e.target.files[0]) })}
/>
</div>
:
<div></div>
}
{this.state.icon.label === 'upload your own' ?
<div className="flex items-center justify-center w-64 mx-auto">
<input type="file"
className="focus:outline-none w-full text-sm cursor-pointer bg-white rounded border"
onChange={(e) => this.setState({ 'customIcon': URL.createObjectURL(e.target.files[0]) })}
/>
</div>
:
<div></div>
}
</div>
<div className="flex items-center">
<div className="flex flex-col m-2 w-1/2">
<span className="font-medium pb-1">Font</span>
<span className="font-medium text-sm pb-1">Font</span>
<select
value={this.state.font}
onChange={(e) => this.setState({ font: e.target.value })}
className="focus:outline-none text-gray-700 text-xl p-2 rounded border">
className="focus:outline-none text-gray-700 text-lg p-2 rounded border">
<option>衬线体</option>
<option>无衬线体</option>
<option>等宽字体</option>
@ -160,13 +142,13 @@ class Editor extends React.Component {
</select>
</div>
<div className="flex flex-col m-2 w-1/2">
<span className="font-medium pb-1">Color</span>
<div className="border rounded flex items-center p-2">
<span className="font-medium text-sm pb-1">Color</span>
<div className="border rounded flex items-center p-1">
<span className="text-xl text-gray-700 mx-2">{this.state.bgColor}</span>
{/* <span className="text-base text-gray-700 mx-2">{this.state.bgColor}</span> */}
<input type="color" value={this.state.bgColor}
onChange={(e) => this.setState({ bgColor: e.target.value })}
className="h-8 w-8 ml-auto mr-1 rounded"
className="h-8 w-full rounded"
/>
</div>
</div>
@ -176,10 +158,10 @@ class Editor extends React.Component {
<div className="flex items-center">
{/* <div className="flex flex-col m-2 w-1/2">
<span className="font-medium pb-1">图案</span>
<span className="font-medium text-sm pb-1">Pattern</span>
<select
onChange={(e) => this.setState({ pattern: e.target.value })}
className="focus:outline-none border text-xl p-2 rounded"
className="focus:outline-none border text-lg p-2 rounded"
value={this.state.pattern}>
<option></option>
@ -205,12 +187,12 @@ class Editor extends React.Component {
</div> */}
<div className="flex flex-col m-2 w-full">
<span className="font-medium pb-1">平台</span>
<span className="font-medium text-sm pb-1">平台</span>
<select
onChange={(e) => this.setState({ platform: e.target.value })}
value={this.state.platform}
className="focus:outline-none text-gray-700 text-xl p-2 rounded border">
className="focus:outline-none text-gray-700 text-lg p-2 rounded border">
<option>hashnode</option>
<option>dev</option>
</select>
@ -219,64 +201,20 @@ class Editor extends React.Component {
</div>
<button
className="flex items-center bg-gray-700 text-white rounded-lg mt-6 text-lg font-semibold p-1 px-4 mx-auto border"
className="flex items-center bg-gray-700 hover:bg-gray-800 text-white rounded-lg mt-6 text-base p-1 px-4 mx-auto border"
onClick={this.handleReset}>
<span>全部重置</span>
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5 text-white mr-2 " fill="currentColor" viewBox="0 0 24 24" ><path d="M12 16c1.671 0 3-1.331 3-3s-1.329-3-3-3-3 1.331-3 3 1.329 3 3 3z"></path><path d="M20.817 11.186a8.94 8.94 0 0 0-1.355-3.219 9.053 9.053 0 0 0-2.43-2.43 8.95 8.95 0 0 0-3.219-1.355 9.028 9.028 0 0 0-1.838-.18V2L8 5l3.975 3V6.002c.484-.002.968.044 1.435.14a6.961 6.961 0 0 1 2.502 1.053 7.005 7.005 0 0 1 1.892 1.892A6.967 6.967 0 0 1 19 13a7.032 7.032 0 0 1-.55 2.725 7.11 7.11 0 0 1-.644 1.188 7.2 7.2 0 0 1-.858 1.039 7.028 7.028 0 0 1-3.536 1.907 7.13 7.13 0 0 1-2.822 0 6.961 6.961 0 0 1-2.503-1.054 7.002 7.002 0 0 1-1.89-1.89A6.996 6.996 0 0 1 5 13H3a9.02 9.02 0 0 0 1.539 5.034 9.096 9.096 0 0 0 2.428 2.428A8.95 8.95 0 0 0 12 22a9.09 9.09 0 0 0 1.814-.183 9.014 9.014 0 0 0 3.218-1.355 8.886 8.886 0 0 0 1.331-1.099 9.228 9.228 0 0 0 1.1-1.332A8.952 8.952 0 0 0 21 13a9.09 9.09 0 0 0-.183-1.814z"></path></svg>
<span className="font-Inter">全部重置</span>
</button>
</Tab.Panel>
</div>
<Tab.Panel className="h-99 w-full flex flex-col justify-center">
<div className="flex items-center border rounded-xl border-gray-50 px-4">
<h2 className="text-lg pl-2 font-inter font-semibold">Themes</h2>
<div className="ml-auto mr-1 p-2">
<RandomTheme onThemeChange={this.getRandomTheme} />
</div>
</div>
<div className="p-4 flex flex-wrap overflow-y-scroll ">
<img src={theme7} alt="basic theme"
onClick={(e) => this.setState({ theme: "background" })}
className=" cursor-pointer border border-gray-100 hover:border-gray-200 hover:scale-105 duration-300 m-2"
/>
<img src={theme1} alt="basic theme"
onClick={(e) => this.setState({ theme: "basic" })}
className=" cursor-pointer border-gray-100 hover:scale-105 duration-300 hover:border-gray-200 border m-2 "
/>
<img src={theme2} alt="basic theme"
onClick={(e) => this.setState({ theme: "modern" })}
className="cursor-pointer border-gray-100 hover:scale-105 hover:border-gray-200 duration-300 border m-2 "
/>
<img src={theme3} alt="basic theme"
onClick={(e) => this.setState({ theme: "stylish" })}
className=" cursor-pointer border border-gray-100 hover:border-gray-200 hover:scale-105 duration-300 m-2"
/>
<img src={theme5} alt="basic theme"
onClick={(e) => this.setState({ theme: "outline" })}
className=" cursor-pointer border border-gray-100 hover:border-gray-200 hover:scale-105 duration-300 m-2"
/>
<img src={theme4} alt="basic theme"
onClick={(e) => this.setState({ theme: "preview" })}
className=" cursor-pointer border border-gray-100 hover:border-gray-200 hover:scale-105 duration-300 m-2"
/>
<img src={theme6} alt="basic theme"
onClick={(e) => this.setState({ theme: "mobile" })}
className=" cursor-pointer border border-gray-100 hover:border-gray-200 hover:scale-105 duration-300 m-2"
/>
</div>
</Tab.Panel>
</Tab.Panels>
</div>
</div>
</Tab.Group>
</div>
{/* <div className="mx-4 my-1">
@ -289,17 +227,51 @@ class Editor extends React.Component {
</select>
</div> */}
</div>
<div className=" flex m-6 flex-col items-center justify-center ">
{/* cover image preview */}
<div className=" flex m-2 flex-col items-center justify-center ">
<ComponentToImg downloadAs={this.state.download}>
<CoverImage {...this.state} />
</ComponentToImg>
</div>
{/* themes section */}
<div className="md:w-60 px-4 border-dashed border-l-2 border-gray-100 bg-white">
<div className="h-99 w-full flex flex-col justify-center">
<div className="flex items-center">
<h2 className="text-lg pl-2 font-inter font-semibold">Themes</h2>
<div className="ml-auto mr-1 p-2">
<RandomTheme onThemeChange={this.getRandomTheme} />
</div>
</div>
<div className=" flex gap-2 flex-wrap justify-center overflow-y-scroll ">
{
THEMES.map(themePlaceholder => (
<div className={`${themePlaceholder.label === this.state.theme ? 'border-blue-400 border-2' : ''}`} key={themePlaceholder.label}>
<img src={themePlaceholder.preview} alt={themePlaceholder.label}
onClick={(e) => this.setState({ theme: themePlaceholder.label })}
className=" cursor-pointer border border-gray-100 hover:border-gray-200 hover:scale-105 duration-300 "
/>
</div>
))
}
</div>
</div>
</div>
</div>
</ImgProvider>
</div>

View File

@ -3,18 +3,18 @@ import { Link } from 'react-router-dom'
import logo from '../assets/icons/logo.png'
const Header = () => {
return (
<div className="text-xl md:px-2 flex border-b border-gray-100 p-2">
<Link to="/" className="flex items-center">
<img src={logo} alt="logo" className="w-8 h-8 mx-4" />
<h1 className="font-semibold">Coverview</h1>
return (
</Link>
<div className="bg-white text-xl md:px-2 flex border-dashed border-b-2 border-gray-100 p-2">
<Link to="/" className="flex items-center">
<img src={logo} alt="logo" className="w-8 h-8 mx-4" />
<h1 className="font-semibold">Coverview</h1>
</Link>
</div>
);
}
export default Header;

View File

@ -17,82 +17,88 @@ const Home = () => {
return (
<div className="bg-gray-50">
<div className="">
<div className="text-xl flex border-b border-gray-100 p-2 md:w-10/12 mx-auto">
<div className="flex items-center">
<img src={logo} alt="logo" className="w-8 h-8 mx-2" />
<h1 className="font-semibold md:text-xl text-lg font-Inter">封面视图</h1>
<div className="">
<div className="text-xl flex p-2 md:w-10/12 mx-auto">
<div className="flex items-center">
<img src={logo} alt="logo" className="w-8 h-8 mx-2" />
<h1 className="font-semibold md:text-xl text-lg font-Inter">封面视图</h1>
</div>
{/* <a href="https://github.com/rutikwankhade/CoverView" target="_blank" rel="noreferrer" className="hover:translate-x-2 flex items-center justify-center duration-300 bg-gray-700 group rounded-xl text-white ml-auto mr-4 font-Inter font-semibold ">
<span className="md:text-sm text-xs px-2 md:px-4 py-1 md:py-2"> Star on Github</span>
</a> */}
</div>
{/* <a href="https://github.com/rutikwankhade/CoverView" target="_blank" rel="noreferrer" className="hover:translate-x-2 duration-300 bg-gray-700 group rounded-xl md:px-4 text-white md:text-sm text-xs ml-auto mr-4 font-Inter font-semibold p-2">
<span className="text-sm"> Star on Github</span>
</a> */}
</div>
<div className=" mx-auto md:px-20 py-6 flex flex-col items-center">
<h1 className="md:w-7/12 m-10 text-center md:text-5xl text-3xl font-extrabold text-gray-700 font-Anek">
<div className=" mx-auto md:px-20 py-6 flex flex-col items-center">
<h1 className="md:w-7/12 md:mx-10 mx-6 my-10 text-center md:text-5xl text-4xl font-extrabold text-gray-700 font-Anek">
为博客创建封面图片现在变得超级简单
</h1>
<Link to="/editor" className="hover:translate-x-2 duration-300 bg-gray-700 hover:bg-gray-800 group rounded-full px-4 md:px-8 text-white md:text-2xl text-lg mx-auto font-Inter font-semibold md:p-4 p-2">
<span className="md:text-2xl text-lg">打开编辑器 &rarr;</span>
</Link>
</div>
<div className=" temple flex flex-row items-center justify-center mx-auto md:w-10/12">
<div className="m-4 transform -translate-y-20 border animate hover:scale-105 hover:-rotate-3 rotate-6 duration-100 bg-white p-2 shadow-sm w-1/5 rounded-lg flex flex-col ">
<img src={cover2} className="border border-gray-100 rounded mb-2" alt="cover1" />
<p className="animate animate-pulse bg-gray-50 md:h-5 h-2 rounded mb-2"></p>
<p className="animate animate-pulse w-8/12 bg-gray-50 md:h-5 h-2 rounded mb-2"></p>
</h1>
<Link to="/editor" className="hover:translate-x-2 duration-300 bg-gray-700 hover:bg-gray-800 group rounded-full border-4 border-gray-100 px-6 md:px-8 text-white md:text-2xl text-base mx-auto font-Poppins font-semibold md:p-4 p-2">
<span className="md:text-2xl font-semibold text-lg">立即创建</span>
</Link>
</div>
<div className="m-4 transform hover:scale-105 hover:rotate-3 -rotate-2 duration-300 bg-white p-4 shadow-sm w-1/3 rounded-lg flex flex-col ">
<img src={cover1} className="rounded border border-gray-100 mb-2" alt="cover-2" />
<p className="animate animate-pulse bg-gray-50 md:h-6 h-3 rounded mb-2"></p>
<p className="animate animate-pulse w-8/12 bg-gray-50 md:h-6 h-3 rounded mb-2"></p>
</div>
<div className="m-4 transform -translate-y-20 border animate hover:scale-105 hover:rotate-3 -rotate-6 duration-100 bg-white p-2 shadow-sm w-1/5 rounded-lg flex flex-col ">
<img src={cover3} className="rounded border border-gray-100 mb-2" alt="cover3" />
<p className="animate animate-pulse bg-gray-50 md:h-5 h-2 rounded mb-2"></p>
<p className="animate animate-pulse w-8/12 bg-gray-50 md:odd:h-5 h-2 rounded mb-2"></p>
</div>
</div>
<div className=" flex flex-row items-center justify-center mx-auto md:w-10/12">
<div className="md:my-32 my-10 mx-auto">
<div className="md:w-10/12 mx-auto flex flex-col ">
<div className="md:w-9/12 text-center mx-auto ">
<h2 className="text-5xl py-4 font-bold font-Anek text-gray-700">为什么封面图像比你想象的更重要</h2>
<div className="m-4 transform -translate-y-20 border animate hover:scale-105 hover:-rotate-3 rotate-6 duration-100 bg-white p-2 shadow-lg shadow-gray-50 w-1/5 rounded-lg flex flex-col ">
<img src={cover2} className="border border-gray-100 rounded mb-2" alt="cover1" />
<p className="animate animate-pulse bg-gray-50 md:h-5 h-2 rounded mb-2"></p>
<p className="animate animate-pulse w-8/12 bg-gray-50 md:h-5 h-2 rounded mb-2"></p>
</div>
<div className="flex md:flex-row flex-col mx-auto justify-center my-10 mx-auto">
<div className="m-4 transform hover:scale-105 hover:rotate-3 -rotate-2 duration-300 bg-white p-4 shadow-lg shadow-gray-50 w-1/3 rounded-lg flex flex-col ">
<img src={cover1} className="rounded border border-gray-100 mb-2" alt="cover-2" />
<p className="animate animate-pulse bg-gray-50 md:h-6 h-3 rounded mb-2"></p>
<p className="animate animate-pulse w-8/12 bg-gray-50 md:h-6 h-3 rounded mb-2"></p>
<div className="m-10 p-10 bg-white rounded-xl shadow-xl shadow-gray-100 flex flex-col md:w-4/12 ">
<div className=" my-2 bg-purple-300 h-24 w-24 p-4 flex justify-center items-center rounded-full">
</div>
<div className="m-4 transform -translate-y-20 border animate hover:scale-105 hover:rotate-3 -rotate-6 duration-100 bg-white p-2 sshadow-lg shadow-gray-50 w-1/5 rounded-lg flex flex-col ">
<img src={cover3} className="rounded border border-gray-100 mb-2" alt="cover3" />
<p className="animate animate-pulse bg-gray-50 md:h-5 h-2 rounded mb-2"></p>
<p className="animate animate-pulse w-8/12 bg-gray-50 md:odd:h-5 h-2 rounded mb-2"></p>
</div>
</div>
</div>
<div className="md:mt-32 my-t0 mx-auto">
<div className=" mx-auto flex flex-col md:w-10/12">
<div className="w-full text-center mx-auto p-10 md:p-4 ">
<h2 className="md:text-5xl md:w-9/12 mx-auto text-3xl px-4 font-bold font-Anek text-gray-700">为什么封面图像比你想象的更重要</h2>
</div>
<div className="flex md:flex-row flex-col justify-center md:gap-6 gap-2 mx-auto">
<div className=" p-10 rounded-xl shadow-gray-100 flex flex-col gap-4 md:w-4/12 ">
<div className=" my-2 md:mx-0 mx-auto bg-purple-300 h-24 w-24 p-4 flex justify-center items-center rounded-full">
<svg className="text-white w-20 h-20" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"></path></svg>
</div>
<p className="text-2xl md:text-left text-center text-gray-700">每天都有大概 <span className="font-bold">700 </span> </p>
<p className="md:text-2xl text-xl md:text-left text-center font-Nunito ">每天都有大概 <span className="font-bold">700 </span> </p>
</div>
<div className="m-10 p-10 bg-white rounded-xl shadow-xl shadow-gray-100 flex flex-col md:w-4/12 ">
<div className=" my-2 bg-green-300 h-24 w-24 p-4 flex justify-center items-center rounded-full">
<div className="p-10 rounded-xl shadow-gray-100 flex flex-col gap-4 md:w-4/12 ">
<div className="md:mx-0 mx-auto my-2 bg-green-300 h-24 w-24 p-4 flex justify-center items-center rounded-full">
<svg className="text-white w-20 h-20" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path></svg>
</div>
<p className="text-2xl md:text-left text-center text-gray-700">一张好的封面图片可以带来 <span className="font-bold">更高的转换率</span> </p>
<p className="md:text-2xl text-xl md:text-left text-center font-Nunito ">一张好的封面图片可以带来 <span className="font-bold">更高的转换率</span> </p>
</div>
</div>
@ -102,46 +108,48 @@ const Home = () => {
</div>
<h2 className="md:text-5xl text-3xl md:w-1/2 mx-auto mt-32 font-bold font-Anek text-center text-gray-700">使用 coverview您可以在以下时间内创建封面图像: <span className="text-indigo-400">几秒内</span>.</h2>
<div className="md:w-8/12 my-20 flex md:flex-row flex-col mx-auto">
<h2 className="md:text-5xl text-3xl md:w-7/12 md:mx-auto mt-12 md:mt-32 mx-10 font-bold font-Anek text-center text-gray-700">使用 coverview您可以在以下时间内创建封面图像: <span className="text-indigo-400">几秒内</span></h2>
<div className="md:w-1/3 flex flex-col mx-10">
<div className="md:w-8/12 md:my-16 p-4 flex md:flex-row flex-col gap-4 mx-auto">
<div className="md:w-1/2 md:border border-gray-50 md:shadow-sm md:shadow-gray-50 rounded-xl px-4 pt-6 flex flex-col md:mx-10">
<div className="text-center">
<div className="text-xl mx-auto w-10 h-10 p-2 font-bold text-white bg-gray-700 rounded-full flex items-center justify-center">1</div>
<div className="text-xl w-max mx-auto text-white py-1 px-4 font-Anek font-semibold bg-indigo-400 rounded-full ">Step 1</div>
<p className="text-2xl my-2 font-semibold font-Inter text-gray-600">添加博文标题和作者</p>
<p className="md:text-3xl text-2xl p-4 text-center mx-auto my-2 font-semibold font-Inter text-gray-700">添加博客标题和作者姓名</p>
</div>
<img src={step1} alt="preview" className="mt-2 rounded-lg shadow-sm" />
<img src={step1} alt="preview" className="mt-2 w-10/12 mx-auto rounded-t-xl shadow-sm" />
</div>
<div className="flex items-center font-bold text-3xl text-center mx-auto">--------&rarr;</div>
<div className="flex flex-col md:w-1/3 mx-10">
<div className="md:w-1/2 md:border md:border-gray-50 md:shadow-sm md:shadow-gray-50 rounded-xl px-4 pt-6 flex flex-col md:mx-10">
<div className="text-center">
<div className="text-xl mx-auto w-10 h-10 p-2 font-bold text-white bg-gray-700 rounded-full flex items-center justify-center">2</div>
<div className="text-xl w-max mx-auto text-white py-1 px-4 font-Anek font-semibold bg-indigo-400 rounded-full ">Step 2</div>
<p className="text-2xl my-2 font-semibold font-Inter text-gray-600">自定义颜色字体图标和图案</p>
<p className="md:text-3xl text-2xl p-4 text-center mx-auto my-2 font-semibold font-Inter text-gray-700">自定义颜色字体和图标</p>
</div>
<img src={step2} alt="preview" className="mt-2 rounded-lg shadow-sm" />
<img src={step2} alt="preview" className="mt-auto mb-0 w-10/12 mx-auto rounded-t-xl shadow-sm" />
</div>
</div>
<div className="md:w-8/12 flex md:flex-row flex-col justify-center items-center mx-auto">
<div className="md:w-7/12 p-6 mx-auto rounded-xl md:border md:border-gray-50 md:shadow-sm md:shadow-gray-50 flex md:flex-row flex-col justify-center items-center ">
<div className="text-center md:w-1/3 m-4">
<div className="text-xl mx-auto w-10 h-10 p-2 font-bold text-white bg-gray-700 rounded-full flex items-center justify-center">3</div>
<div className="text-center md:w-1/2 m-4">
<div className="text-xl w-max mx-auto text-white py-1 px-4 font-Anek font-semibold bg-indigo-400 rounded-full ">Step 3</div>
<p className="md:text-3xl mt-4 text-2xl pb-2 text-center mx-auto my-2 font-semibold font-Inter text-gray-700">Choose your style from different themes</p>
<p className="text-2xl my-2 font-semibold font-Inter text-gray-600">选择不同的主题</p>
<p className="text-xl">Unsplash 集成个人品牌定制图标等</p>
<p className="md:text-xl text-gray-500 text-lg">Unsplash 集成个人品牌定制图标等</p>
</div>
<div className="flex md:w-8/12 hideout p-6">
<div className="flex md:w-1/2 hideout p-6">
<div className="flex flex-col w-1/2 ">
<img src={cover1} alt="preview" className=" hover:scale-105 duration-300 m-2 rounded-lg shadow-sm" />
<img src={cover2} alt="preview" className="hover:scale-105 duration-300 m-2 rounded-lg shadow-sm" />
@ -160,46 +168,45 @@ const Home = () => {
</div>
<div className="md:w-6/12 my-20 mx-auto">
<div className="md:w-6/12 md:my-20 mb-6 mx-auto">
<div className="text-center m-4">
<div className="text-center m-6 px-6">
<p className="text-2xl my-2 font-semibold font-Inter text-gray-600">支持 Hashnode Dev.to 等平台</p>
<p className="md:text-2xl text-xl my-2 font-semibold font-Inter text-gray-700">支持 Hashnode Dev.to 等平台</p>
</div>
<div className="flex mx-auto justify-center">
<img src={hashnodeLogo} className="w-20 m-2" alt="hashnode" />
<img src={devLogo} className="w-20 m-2" alt="dev" />
<div className="flex mx-auto justify-center gap-4">
<img src={hashnodeLogo} className="md:w-20 w-10" alt="hashnode" />
<img src={devLogo} className="md:w-20 w-10" alt="dev" />
</div>
</div>
{/* <WallOfLove /> */}
<div className="md:w-8/12 mx-auto pt-24 p-4">
<h2 className="text-6xl text-center font-Anek font-bold text-gray-700 mx-auto">简单快捷易于使用</h2>
<p className="text-2xl text-center py-4 md:w-8/12 mx-auto">这样你就可以专注于撰写博客再也不用担心封面图片的问题了</p>
<Link to="/editor" >
<button className="flex mx-auto my-4 hover:translate-x-2 duration-300 bg-gray-700 rounded-full px-6 text-white text-xl font-Inter font-semibold p-4">免费试用立即试用 &rarr;</button>
</Link>
<div className="bg-gray-800 text-white p-2">
<div className="md:w-8/12 mx-auto pt-32 p-6">
<h2 className="md:text-6xl text-4xl text-center font-Anek font-bold mx-auto">简单快捷易于使用</h2>
<p className="md:text-2xl text-lg font-Inter text-gray-300 text-center py-4 md:w-8/12 mx-auto">这样你就可以专注于撰写博客再也不用担心封面图片的问题了</p>
<Link to="/editor" >
<button className="flex mx-auto my-4 hover:translate-x-2 duration-300 bg-indigo-500 hover:bg-indigo-600 rounded-full text-white md:text-xl text-base font-Nunito font-semibold p-4 px-8">这是免费的立即试用 &rarr;</button>
</Link>
</div>
<footer className=" p-10 gap-2 flex md:flex-row flex-col-reverse font-Inter md:px-20 md:justify-between justify-center mx-auto md:w-10/12 w-full items-center">
</footer>
</div>
</div>
<footer className="bg-white p-10 flex md:flex-row flex-col font-Inter md:px-20 justify-center items-center">
<div className="md:w-1/2 flex flex-col">
<span className="text-lg">Made with 💛 by <a href="https://twitter.com/WankhadeRutik" className="font-semibold" target="_blank" rel="noreferrer">Rutik Wankhade </a>and <a href="https://woodchen.ink" className="font-semibold" target="_blank" rel="noreferrer">wood chen</a></span>
{/* <span className="text-lg font-Nunito">checkout <a href="https://rutikwankhade.dev" target="_blank" rel="noreferrer" className="text-purple-400 hover:text-pink-400">more cool stuff</a> I built</span> */}
</div>
<div className="md:text-lg text-sm flex flex-wrap ">
<Link to="/faq" className="m-2 hover:font-semibold">📌 如何使用</Link>
{/* <a href="https://github.com/rutikwankhade/CoverView" target="_blank" rel="noreferrer" className="m-2 hover:font-semibold"> Star on Github</a>
<a href="https://www.buymeacoffee.com/rutikwankhade" target="_blank" rel="noreferrer" className="m-2 hover:font-semibold">🥤 Buy me a coffee</a> */}
</div>
</footer>
</div>
);

View File

@ -1,12 +1,12 @@
.shuffle-btn:active{
transform: rotate(360deg);
transition: all 0.2s ease-out;
transform: rotate(720deg);
transition: all 0.6s ease-out;
}
.bi-shuffle{
height: 30px;
width: 30px;
height: 20px;
width: 20px;
opacity: 0.6;
}

View File

@ -108,8 +108,8 @@ class RandomTheme extends React.Component {
render() {
return (
<div className="flex flex-col justify-center">
<div className="shuffle-btn w-10 flex justify-center items-center shadow-xl shadow-gray-100 h-10 p-2 bg-indigo-400 rounded-xl cursor-pointer" onClick={this.changeTheme}>
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" className="text-white w-10 h-10" width="24" height="24" viewBox="0 0 24 24" ><path d="M17 17h-1.559l-9.7-10.673A1 1 0 0 0 5.001 6H2v2h2.559l4.09 4.5-4.09 4.501H2v2h3.001a1 1 0 0 0 .74-.327L10 13.987l4.259 4.686a1 1 0 0 0 .74.327H17v3l5-4-5-4v3z"></path><path d="M15.441 8H17v3l5-3.938L17 3v3h-2.001a1 1 0 0 0-.74.327l-3.368 3.707 1.48 1.346L15.441 8z"></path></svg>
<div className="shuffle-btn flex justify-center items-center p-2 cursor-pointer" onClick={this.changeTheme}>
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" className="text-gray-600 hover:text-gray-700 " width="20" height="20" viewBox="0 0 24 24" ><path d="M17 17h-1.559l-9.7-10.673A1 1 0 0 0 5.001 6H2v2h2.559l4.09 4.5-4.09 4.501H2v2h3.001a1 1 0 0 0 .74-.327L10 13.987l4.259 4.686a1 1 0 0 0 .74.327H17v3l5-4-5-4v3z"></path><path d="M15.441 8H17v3l5-3.938L17 3v3h-2.001a1 1 0 0 0-.74.327l-3.368 3.707 1.48 1.346L15.441 8z"></path></svg>
</div>
</div>

View File

@ -1,83 +1,24 @@
import React, { useState, useEffect, useContext } from 'react';
import unsplash from "../../utils/unsplashConfig";
import React, { useContext } from 'react';
import { ImgContext } from '../../utils/ImgContext';
import UnsplashSearch from '../UnsplashSearch';
const BackgroundTheme = ({ config }) => {
const { title, author, font, icon, customIcon, platform, bgColor } = config;
// const [image, setImage] = useState({})
const [imageList, setImageList] = useState([]);
const [searchText, setSearchText] = useState('dev');
const { title, author, font, icon, customIcon, bgColor } = config;
const { unsplashImage, setUnsplashImage } = useContext(ImgContext);
const searchImages = () => {
unsplash.search
.getPhotos({
query: searchText,
page: 1,
per_page: 30,
// orientation:'portrait'
})
.then(response => {
console.log(response.response.results);
setImageList(response.response.results)
});
}
useEffect(() => {
unsplash.search
.getPhotos({
query: 'setup',
page: 1,
per_page: 30
})
.then(response => {
console.log(response.response.results);
setImageList(response.response.results)
});
}, [])
const selectImage = (image) => {
setUnsplashImage({
url: image.urls.regular,
name: image.user.name,
avatar: image.user.profile_image.small,
profile: `${image.user.links.html}?utm_source=https://coverview.czl.net&utm_medium=referral`,
downloadLink: image.links.download_location
})
}
const handleSearchSubmit = (e) => {
e.preventDefault();
searchImages(searchText);
}
return (
<div className=" bg-white rounded">
<div className=" bg-white ">
<div className={` overflow-y-hidden flex flex-col rounded ${platform}`}
<div className={` overflow-y-hidden flex flex-col`}
style={{ backgroundColor: bgColor }}
>
<div className="flex flex-row items-center bg-white justify-center ">
<div className="flex flex-row items-center bg-white justify-center ">
<div className="w-full">
{unsplashImage ?
<div className='relative flex group'>
@ -86,7 +27,7 @@ const BackgroundTheme = ({ config }) => {
</div>
<div className=" backdrop-blur-sm h-full bg-gray-800/60 absolute top-0 right-0 left-0 ">
<div className="h-full bg-gray-800/60 absolute top-0 right-0 left-0 ">
<button
onClick={() => setUnsplashImage('')}
className="absolute top-2 right-2 cursor-pointer">
@ -131,37 +72,8 @@ const BackgroundTheme = ({ config }) => {
:
<div className="flex flex-col p-2 bg-white items-center justify-center">
<div className="flex items-center w-full px-6 ">
<div className="text-lg font-semibold text-gray-700">Click on any image to select</div>
<form onSubmit={(e) => handleSearchSubmit(e)} className=" ml-auto mr-2 w-1/2 flex bg-gray-50 rounded-full border mb-2">
<input type="text"
value={searchText}
placeholder="Search image"
className="focus:outline-none w-full text-lg bg-gray-50 p-1 px-4 rounded-full border border-gray-50"
onChange={(e) => setSearchText(e.target.value)}
/>
<UnsplashSearch largeImgPreview />
<button type="submit" onClick={() => searchImages(searchText)}>
<svg className="w-9 h-9 ml-auto mr-1 p-2 bg-gray-700 hover:bg-gray-800 text-white rounded-full" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
</button>
</form>
</div>
<div className="overflow-y-scroll overflow-x-hidden h-96 justify-center flex flex-wrap">
{
imageList.map(image => {
return <img src={image.urls.regular}
key={image.id}
alt={image.alt_description}
className="rounded m-2 cursor-pointer w-5/12 object-cover h-40"
onClick={() => selectImage(image)
}
/>
})
}
</div>
</div>
}

View File

@ -2,11 +2,11 @@ import React from 'react';
const BasicTheme = ({ config }) => {
const { title, bgColor, pattern, author, icon, font, customIcon,platform } = config;
const { title, bgColor, pattern, author, icon, font, customIcon } = config;
return (
<div className="p-4 bg-white ">
<div className={`overflow-y-hidden flex text-gray-800 items-center h-full ${platform} ${pattern} `}
<div className=" bg-white w-full h-full ">
<div className={`overflow-y-hidden flex text-gray-800 items-center h-full ${pattern} `}
style={{ backgroundColor: bgColor }}
>
@ -33,8 +33,8 @@ const BasicTheme = ({ config }) => {
<h2 className="text-xl ml-auto mr-2 font-semibold">{author}</h2>
</div>
</div>
</div>
</div>

View File

@ -1,22 +1,22 @@
import React, { useState } from 'react';
const MobileMockupTheme = ({ config }) => {
const { bgColor, platform, title,font } = config;
const { bgColor, title, font } = config;
const [image, setImage] = useState()
return (
<div className="p-4 bg-white">
<div className={`bg-white w-full h-full`}>
<div className={`overflow-y-hidden flex flex-row px-10 items-center justify-center rounded px-8 pt-4 ${platform}`}
<div className={`overflow-y-hidden flex flex-row px-10 items-center w-full h-full justify-center pt-4`}
style={{ backgroundColor: bgColor }}
>
<h1 className={`${font} text-2xl w-1/2 md:text-4xl px-4 text-white font-bold text-left`}>{title}</h1>
<div className="w-5/12 mx-auto m-4 mt-10 group mx-auto h-full shadow-lg flex flex-col bg-white border-t-8 border-x-8 border-gray-800 rounded-t-3xl border-white">
<div className="w-5/12 mx-auto m-4 mt-10 group h-full shadow-lg flex flex-col bg-white border-t-8 border-x-8 border-gray-800 rounded-t-3xl border-white">
<div className="bg-gray-800 h-8 w-full p-2 pb-3 flex items-center rounded-t">
<div className="flex mx-auto items-center">

View File

@ -3,12 +3,12 @@ import React from 'react';
const ModernTheme = ({ config }) => {
const { title, bgColor, pattern, author, icon, font, customIcon, platform } = config;
const { title, bgColor, pattern, author, icon, font, customIcon } = config;
return (
<div className="w-full p-4 bg-white ">
<div className=" overflow-y-hidden w-full flex items-center">
<div className={` h-full w-full rounded-xl p-4 text-gray-800 flex items-center ${pattern} ${platform}`}
<div className="w-full h-full bg-white ">
<div className=" overflow-y-hidden w-full h-full flex items-center">
<div className={` h-full w-full p-4 text-gray-800 flex items-center ${pattern} `}
style={{ backgroundColor: bgColor }}
>

View File

@ -1,12 +1,12 @@
import React from 'react';
const OutlineTheme = ({ config }) => {
const { title, bgColor, author, icon, font, customIcon, platform } = config;
const { title, bgColor, author, icon, font, customIcon } = config;
return (
<div className="p-4 bg-white ">
<div className="w-full h-full bg-white ">
<div className={`overflow-y-hidden rounded flex flex-col text-gray-800 px-10 ${platform} `}
<div className={`overflow-y-hidden flex flex-col text-gray-800 px-10 h-full`}
style={{ backgroundColor: bgColor }}
>

View File

@ -1,19 +1,18 @@
import React, { useState } from 'react';
const PreviewTheme = ({ config }) => {
const { bgColor, platform, title, font } = config;
const { bgColor, title, font } = config;
const [image, setImage] = useState()
return (
<div className="p-4 bg-white">
<div className="w-full h-full bg-white">
<div className={`overflow-y-hidden flex flex-col rounded px-4 pt-4 ${platform}`}
<div className={`overflow-y-hidden flex flex-col px-4 pt-4 w-full h-full`}
style={{ backgroundColor: bgColor }}
>
<h1 className={`${font} text-2xl md:text-3xl p-10 text-white font-bold text-center`}>{title}</h1>
<div className="w-10/12 group mx-auto mt-auto mb-0 shadow-lg flex flex-col bg-white rounded-t-xl border-white">
@ -30,7 +29,6 @@ const PreviewTheme = ({ config }) => {
</div>
{image ?
<div className="">
<img src={image && image} className="object-cover " alt="preview" />
@ -48,13 +46,8 @@ const PreviewTheme = ({ config }) => {
}
</div>
</div>
</div>
);
}

View File

@ -1,78 +1,21 @@
import React, { useState, useEffect, useContext } from 'react';
import unsplash from "../../utils/unsplashConfig";
import React, { useContext } from 'react';
import { ImgContext } from '../../utils/ImgContext';
import UnsplashSearch from '../UnsplashSearch';
const StylishTheme = ({ config }) => {
const { title, author, font, icon, customIcon, platform,bgColor } = config;
// const [image, setImage] = useState({})
const [imageList, setImageList] = useState([]);
const [searchText, setSearchText] = useState('dev');
const { title, author, font, icon, customIcon, bgColor } = config;
const { unsplashImage, setUnsplashImage } = useContext(ImgContext);
const searchImages = () => {
unsplash.search
.getPhotos({
query: searchText,
page: 1,
per_page: 30,
// orientation:'portrait'
})
.then(response => {
// console.log(response.response.results);
setImageList(response.response.results)
});
}
useEffect(() => {
unsplash.search
.getPhotos({
query: 'setup',
page: 1,
per_page: 25
})
.then(response => {
// console.log(response.response.results);
setImageList(response.response.results)
});
}, [])
const selectImage = (image) => {
setUnsplashImage({
url: image.urls.regular,
name: image.user.name,
avatar: image.user.profile_image.small,
profile: `${image.user.links.html}?utm_source=https://coverview.czl.net&utm_medium=referral`,
downloadLink: image.links.download_location
})
}
const handleSearchSubmit = (e) => {
e.preventDefault();
searchImages(searchText);
}
return (
<div className=" bg-white rounded">
<div className=" bg-white w-full h-full">
<div className={` overflow-y-hidden flex flex-col rounded ${platform}`}
style={{ backgroundColor: bgColor }}
<div className={` overflow-y-hidden flex flex-col`}
style={{ backgroundColor: bgColor }}
>
<div className="flex flex-row items-center bg-white justify-center m-4 ">
<div className="flex flex-row items-center bg-white justify-center">
<div className="h-full w-1/2 bg-white rounded-l-xl">
<div className={`${font} px-12 justify-center text-left rounded-xl h-full p-4 flex flex-col`}>
@ -94,18 +37,15 @@ const StylishTheme = ({ config }) => {
</div>
</div>
</div>
<div className="w-1/2">
<div className="w-1/2 h-full">
{unsplashImage ?
<div className='relative flex group'>
<div className='relative w-full h-max flex group'>
<img src={unsplashImage.url && unsplashImage.url} className=" object-cover w-full h-full " alt="preview" />
<div className="h-96 w-96 ">
<img src={unsplashImage.url && unsplashImage.url} className=" object-cover h-96 w-96 " alt="preview" />
</div>
<button
onClick={() => setUnsplashImage('')}
className="absolute top-4 right-2 cursor-pointer">
@ -128,35 +68,9 @@ const StylishTheme = ({ config }) => {
</div>
</div>
:
<div className="flex flex-col p-2 bg-white items-center justify-center">
<div className="flex h-max w-full flex-col bg-white items-center justify-center">
<form onSubmit={(e) => handleSearchSubmit(e)} className="flex bg-gray-50 rounded-full border mb-2">
<input type="text"
value={searchText}
placeholder="Search image"
className="focus:outline-none w-max text-lg bg-gray-50 p-1 px-4 rounded-full border border-gray-50"
onChange={(e) => setSearchText(e.target.value)}
/>
<button type="submit" onClick={() => searchImages(searchText)}>
<svg className="w-9 h-9 p-2 bg-gray-700 hover:bg-gray-800 text-white rounded-full" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
</button>
</form>
<div className="overflow-y-scroll overflow-x-hidden h-80">
{
imageList.map(image => {
return <img src={image.urls.regular}
key={image.id}
alt={image.alt_description}
className="rounded m-2 cursor-pointer"
onClick={() => selectImage(image)
}
/>
})
}
</div>
<UnsplashSearch />
</div>
}

View File

@ -0,0 +1,108 @@
import React, { useState, useEffect, useContext } from 'react';
import unsplash from '../utils/unsplashConfig';
import { ImgContext } from '../utils/ImgContext';
const UnsplashSearch = ({ largeImgPreview }) => {
const [imageList, setImageList] = useState([]);
const [searchText, setSearchText] = useState('setup');
const { unsplashImage, setUnsplashImage } = useContext(ImgContext);
const searchImages = () => {
unsplash.search
.getPhotos({
query: searchText,
page: 1,
per_page: 30,
// orientation:'portrait'
})
.then(response => {
// console.log(response.response.results);
setImageList(response.response.results)
});
}
const selectImage = (image) => {
setUnsplashImage({
url: image.urls.regular,
name: image.user.name,
avatar: image.user.profile_image.small,
profile: `${image.user.links.html}?utm_source=https://coverview.czl.net&utm_medium=referral`,
downloadLink: image.links.download_location
})
}
const handleSearchSubmit = (e) => {
e.preventDefault();
searchImages(searchText);
}
useEffect(() => {
unsplash.search
.getPhotos({
query: 'setup',
page: 1,
per_page: 30
})
.then(response => {
// console.log(response.response.results);
setImageList(response.response.results)
});
}, [])
return (
<div className='w-full h-full'>
<div className="flex flex-col p-2 bg-white items-center justify-center">
<div className="flex items-center w-full px-6 ">
<form onSubmit={(e) => handleSearchSubmit(e)} className=" mx-auto w-full flex bg-gray-50 rounded-full border border-gray-50 mb-2">
<input type="text"
value={searchText}
placeholder="Search photos"
className="focus:outline-none w-full text-lg bg-gray-50 p-1 px-4 rounded-full "
onChange={(e) => setSearchText(e.target.value)}
/>
<button type="submit" onClick={() => searchImages(searchText)}>
<svg className="w-9 h-9 ml-auto p-2 bg-gray-700 hover:bg-gray-800 text-white rounded-full" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
</button>
</form>
</div>
<div className="overflow-y-scroll w-full pb-12 overflow-x-hidden h-max justify-center flex flex-wrap">
{
imageList.map(image => {
return <div key={image.id}
className={`rounded-lg relative cursor-pointer m-1 ${largeImgPreview ? ' h-44 w-60' : 'h-24 w-40'
}`}
>
<span className="font-Inter top-2 left-2 absolute text-sm font-semibold text-white opacity-50 ">Click to Select</span>
<img src={image.urls.regular}
alt={image.alt_description}
onClick={() => selectImage(image)
}
className="rounded-lg object-cover h-full w-full"
/>
</div>
})
}
</div>
</div>
</div>
);
}
export default UnsplashSearch;

View File

@ -20,7 +20,7 @@ const WallOfLove = () => {
return (
<div>
<div className='md:h-[800px] h-screen w-full'>
<iframe id="senja-frame-902012ea"
title="wall of love"
src=""
@ -29,7 +29,7 @@ const WallOfLove = () => {
scrolling="no"
width="100%"
height="100%"
className="w-9/12 h-screen mx-auto"
className="md:w-9/12 h-full py-4 px-6 mx-auto"
>
</iframe>

View File

@ -13,6 +13,11 @@
height:36rem;
}
/* Solve the problem of poor display effect caused by the height of the cover image exceeding the range under the first theme */
.h-max.w-full {
height: 420px;
}
.h-99{
height:35rem;
}
@ -35,4 +40,4 @@ Track
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #b3b3ff;
}
}

41
src/utils/constants.js Normal file
View File

@ -0,0 +1,41 @@
import backgroundThemePlaceholder from '../assets/images/background-theme-placeholder.webp'
import basicThemePlaceholder from '../assets/images/basic-theme-placeholder.webp'
import modernThemePlaceholder from '../assets/images/modern-theme-placeholder.webp'
import stylishThemePlaceholder from '../assets/images/stylish-theme-placeholder.webp'
import outlineThemePlaceholder from '../assets/images/outline-theme-placeholder.webp'
import previewThemePlaceholder from '../assets/images/preview-theme-placeholder.webp'
import mobileThemePlaceholder from '../assets/images/mobile-theme-placeholder.webp'
export const THEMES = [
{
label: 'background',
preview: backgroundThemePlaceholder
},
{
label: 'stylish',
preview: stylishThemePlaceholder
},
{
label: 'basic',
preview: basicThemePlaceholder
},
{
label: 'modern',
preview: modernThemePlaceholder
},
{
label: 'outline',
preview: outlineThemePlaceholder
},
{
label: 'preview',
preview: previewThemePlaceholder
},
{
label: 'mobile',
preview: mobileThemePlaceholder
},
]