mirror of
https://github.com/dzeiocom/markblog.git
synced 2025-04-22 10:52:12 +00:00
WIP
Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
parent
f19f4f43a6
commit
70f05363e2
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
32
components/Button.tsx
Normal file
32
components/Button.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Component } from "react";
|
||||||
|
import { type } from "os";
|
||||||
|
|
||||||
|
import '../styl/styl.styl'
|
||||||
|
|
||||||
|
|
||||||
|
export enum ButtonType {
|
||||||
|
NORMAL = "",
|
||||||
|
OUTLINE = "outline",
|
||||||
|
GHOST = "ghost"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text: string
|
||||||
|
type?: ButtonType
|
||||||
|
// src: string
|
||||||
|
// alt?: string
|
||||||
|
// layout?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DWButton extends Component<Props, {}> {
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<button className={this.props.type}>{this.props.text}</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
89
components/Element.tsx
Normal file
89
components/Element.tsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { ChevronRight } from 'react-feather'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string
|
||||||
|
date: Date
|
||||||
|
image?: string
|
||||||
|
link: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const months = [
|
||||||
|
"le 13eme mois",
|
||||||
|
'Janvier',
|
||||||
|
'Février',
|
||||||
|
'Mars',
|
||||||
|
'Avril',
|
||||||
|
'Mai',
|
||||||
|
'Juin',
|
||||||
|
'Juillet',
|
||||||
|
'Août',
|
||||||
|
'Septembre',
|
||||||
|
'Octobre',
|
||||||
|
'Novembre',
|
||||||
|
'Décembre'
|
||||||
|
]
|
||||||
|
|
||||||
|
export default class Element extends React.Component<Props, {}> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Link href={this.props.link}>
|
||||||
|
{this.props.image ? (
|
||||||
|
<a><img src={this.props.image}/></a>
|
||||||
|
) : (
|
||||||
|
<div></div>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<i>Le {this.props.date.getDate()} {months[this.props.date.getMonth()]} {this.props.date.getFullYear()}</i>
|
||||||
|
<span>
|
||||||
|
<Link href={this.props.link}>
|
||||||
|
<a>{this.props.title}</a>
|
||||||
|
</Link>
|
||||||
|
<Link href={this.props.link}>
|
||||||
|
<a><ChevronRight size={48}/></a>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
<style jsx>{`
|
||||||
|
div {
|
||||||
|
padding: 5% 5%;
|
||||||
|
max-width: 40%;
|
||||||
|
min-width: 400px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
|
height: 250px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
a, i {
|
||||||
|
margin: 10px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24px;
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
158
components/Filters.tsx
Normal file
158
components/Filters.tsx
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import Category from './interfaces/Category'
|
||||||
|
import '../styl/styl.styl'
|
||||||
|
import { ChevronRight } from 'react-feather'
|
||||||
|
import Router from 'next/router'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
categories?: Category[]
|
||||||
|
onQuery?: (query: string) => void
|
||||||
|
onHeight?: (height: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
interface States {
|
||||||
|
follow?: boolean
|
||||||
|
height?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Filters extends React.Component<Props, States> {
|
||||||
|
|
||||||
|
private aside = undefined
|
||||||
|
private input = undefined
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
setRef = element => {
|
||||||
|
this.aside = element
|
||||||
|
}
|
||||||
|
|
||||||
|
setInput = element => {
|
||||||
|
this.input = element
|
||||||
|
}
|
||||||
|
|
||||||
|
onScroll = () => {
|
||||||
|
this.setState({
|
||||||
|
follow: window.pageYOffset > 217
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.submit()
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick = () => {
|
||||||
|
if (this.input.value !== "") {
|
||||||
|
this.submit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.input.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
submit = () => {
|
||||||
|
if (this.props.onQuery) this.props.onQuery(this.input.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.onScroll()
|
||||||
|
this.setState({
|
||||||
|
height: this.aside.clientHeight
|
||||||
|
})
|
||||||
|
if (this.props.onHeight) this.props.onHeight(this.aside.clientHeight)
|
||||||
|
window.addEventListener('scroll', this.onScroll)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('scroll', this.onScroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<aside ref={this.setRef} className={this.state && this.state.follow ? "follow" : ""}>
|
||||||
|
<div>Trier</div>
|
||||||
|
<div className="input icon-right">
|
||||||
|
<select>
|
||||||
|
<option value="plus récant au moins récent"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>Filtrer</div>
|
||||||
|
<div className="input icon-right">
|
||||||
|
<input placeholder="ex: dzeio.com" type="text" ref={this.setInput} onKeyDownCapture={this.onKeyDown} />
|
||||||
|
<i>
|
||||||
|
<ChevronRight onClick={this.onClick} />
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
<p>Languages :</p>
|
||||||
|
{this.props.categories.map(cat => (
|
||||||
|
<Link key={cat.slug} href={cat.slug}>
|
||||||
|
<a>{cat.name}</a>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<style jsx>{`
|
||||||
|
|
||||||
|
aside {
|
||||||
|
padding: 5% 3% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 820px) and (min-height: ${this.state && this.state.height ? this.state.height+100 : 600}px) {
|
||||||
|
aside {
|
||||||
|
position: absolute;
|
||||||
|
min-width: calc(400px - 6%);
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aside.follow {
|
||||||
|
position: fixed;
|
||||||
|
top: 70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.input {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:not(.input) {
|
||||||
|
display: block;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||||
|
color: white;
|
||||||
|
font-size: 24px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
padding: 7px 12px;
|
||||||
|
background: #4285F4;
|
||||||
|
color: white;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
transition: background 200ms
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background: #45CAFC;
|
||||||
|
}
|
||||||
|
|
||||||
|
`}</style>
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
32
components/Header.tsx
Normal file
32
components/Header.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Header extends React.Component<Props, {}> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<img src="/clouds.svg" alt=""/>
|
||||||
|
|
||||||
|
|
||||||
|
<style jsx>{`
|
||||||
|
div {
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||||
|
height: 207px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
height: 50px
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
46
components/Menu.tsx
Normal file
46
components/Menu.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Menu extends React.Component<Props, {}> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<Link href="/">
|
||||||
|
<a>Home</a>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<style jsx>{`
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
background: white;
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: black;
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
transition: background 200ms
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background: #45CAFC20
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
125
components/Navbar.tsx
Normal file
125
components/Navbar.tsx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Menu } from 'react-feather'
|
||||||
|
import { timingSafeEqual } from 'crypto'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
height?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface States {
|
||||||
|
scrolled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Navbar extends React.Component<Props, States> {
|
||||||
|
|
||||||
|
private height = 80
|
||||||
|
|
||||||
|
private menuRef = undefined
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
if (this.props.height) {
|
||||||
|
this.height = this.props.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setRef = element => {
|
||||||
|
this.menuRef = element
|
||||||
|
}
|
||||||
|
|
||||||
|
onScroll = () => {
|
||||||
|
this.setState({
|
||||||
|
scrolled: window.pageYOffset > 207
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
window.addEventListener('scroll', this.onScroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('scroll', this.onScroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick = () => {
|
||||||
|
this.menuRef.classList.toggle("shown")
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const height = this.props.height || 80
|
||||||
|
|
||||||
|
// if (!this.state.scrolled)
|
||||||
|
|
||||||
|
// console.log(this.state.scrolled)
|
||||||
|
return (
|
||||||
|
<nav className={this.state && this.state.scrolled ? "scrolled" : ""}>
|
||||||
|
<style jsx global>{`
|
||||||
|
body {
|
||||||
|
margin-top: ${height}px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<div className="head">
|
||||||
|
<img src="/logo.svg" alt=""/>
|
||||||
|
<span onClick={this.onClick} data-menu={this.refs.menu}>
|
||||||
|
<Menu size={30} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ref={this.setRef} className="menu">
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style jsx>{`
|
||||||
|
nav {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
transition: box-shadow 200ms
|
||||||
|
}
|
||||||
|
nav.scrolled {
|
||||||
|
box-shadow: 0 0 10px 5px #00000040
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
height: 10px;
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||||
|
}
|
||||||
|
.menu {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
.menu.shown {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
.head {
|
||||||
|
display: flex;
|
||||||
|
height: ${height-10}px;
|
||||||
|
background: white;
|
||||||
|
padding-left: ${height-10}px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
width: ${height-10}px;
|
||||||
|
height: ${height-10}px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
56
components/Post.ts
Normal file
56
components/Post.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import matter from 'gray-matter'
|
||||||
|
|
||||||
|
|
||||||
|
interface PostInterface {
|
||||||
|
slug: string
|
||||||
|
title: string
|
||||||
|
content: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PostHeader {
|
||||||
|
title: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Post implements PostInterface {
|
||||||
|
|
||||||
|
public slug: string
|
||||||
|
public title: string
|
||||||
|
public content: string
|
||||||
|
public isStarted = false
|
||||||
|
|
||||||
|
constructor(slug: string) {
|
||||||
|
this.slug = slug
|
||||||
|
}
|
||||||
|
|
||||||
|
public async fetch() {
|
||||||
|
console.log(this.slug)
|
||||||
|
const content = await import(`../posts/${this.slug}.md`)
|
||||||
|
const md = matter(content.default)
|
||||||
|
this.title = md.data.title
|
||||||
|
this.content = md.content
|
||||||
|
}
|
||||||
|
|
||||||
|
public fetchSync() {
|
||||||
|
console.log(this.slug)
|
||||||
|
const content = require(`../posts/${this.slug}.md`)
|
||||||
|
const md = matter(content.default)
|
||||||
|
this.title = md.data.title
|
||||||
|
this.content = md.content
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async fetchAll(): Promise<Post[]> {
|
||||||
|
const files: string[] = ((require as any).context('../posts', true, /\.md$/)).keys()
|
||||||
|
const posts: Post[] = []
|
||||||
|
for (const file of files) {
|
||||||
|
posts.push(
|
||||||
|
new Post(
|
||||||
|
file.replace(/^.*[\\\/]/, '')
|
||||||
|
.split('.')
|
||||||
|
.slice(0, -1)
|
||||||
|
.join('.')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return posts
|
||||||
|
}
|
||||||
|
}
|
15
components/default.tsx
Normal file
15
components/default.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Name extends React.Component<Props, {}> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<span></span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
4
components/interfaces/Category.ts
Normal file
4
components/interfaces/Category.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export default interface Category {
|
||||||
|
name: string
|
||||||
|
slug: string
|
||||||
|
}
|
49
export.js
Executable file
49
export.js
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
const replace = require('replace-in-file')
|
||||||
|
const options = {
|
||||||
|
files: [
|
||||||
|
'out/**/*.html',
|
||||||
|
'out/**/*.js',
|
||||||
|
'out/*.html',
|
||||||
|
],
|
||||||
|
from: /_next/g,
|
||||||
|
to: 'assets',
|
||||||
|
countMatches: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const options2 = {
|
||||||
|
files: [
|
||||||
|
'out/**/*.html',
|
||||||
|
'out/**/*.js',
|
||||||
|
'out/*.html',
|
||||||
|
],
|
||||||
|
from: /__next/g,
|
||||||
|
to: 'root',
|
||||||
|
countMatches: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const options3 = {
|
||||||
|
files: [
|
||||||
|
'out/**/*.html',
|
||||||
|
'out/**/*.js',
|
||||||
|
'out/*.html',
|
||||||
|
],
|
||||||
|
from: /__NEXT_DATA__/g,
|
||||||
|
to: '__DZEIO_DATA__',
|
||||||
|
countMatches: true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const res3 = await replace(options3)
|
||||||
|
console.log(res3)
|
||||||
|
const res2 = await replace(options2)
|
||||||
|
console.log(res2)
|
||||||
|
const results = await replace(options)
|
||||||
|
console.log(results)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
2
next-env.d.ts
vendored
Normal file
2
next-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/types/global" />
|
40
next.config.js
Normal file
40
next.config.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const withCSS = require('@zeit/next-stylus')
|
||||||
|
const glob = require('glob')
|
||||||
|
const withOffline = require('next-offline')
|
||||||
|
// import posts from './posts/pages.json.ts'
|
||||||
|
// const posts = require('./posts/pages.json.ts')
|
||||||
|
// const t = require('./pages/portfolio/')
|
||||||
|
module.exports = withOffline(withCSS({
|
||||||
|
/* config options here */
|
||||||
|
exportTrailingSlash: true,
|
||||||
|
// cssModules: true,
|
||||||
|
// target: 'serverless',
|
||||||
|
webpack: function(config) {
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /\.md$/,
|
||||||
|
use: 'raw-loader'
|
||||||
|
})
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
["styled-jsx/babel", { "optimizeForSpeed": true }]
|
||||||
|
],
|
||||||
|
exportPathMap: async function() {
|
||||||
|
const paths = {
|
||||||
|
'/': { page: '/'},
|
||||||
|
'/portfolio': { page: '/portfolio'},
|
||||||
|
}
|
||||||
|
|
||||||
|
const posts = glob.sync('./posts/**/*.md')
|
||||||
|
|
||||||
|
posts.forEach(element => {
|
||||||
|
element = element.replace(/^.*[\\\/]/, '')
|
||||||
|
.split('.')
|
||||||
|
.slice(0, -1)
|
||||||
|
.join('.')
|
||||||
|
paths[`/portfolio/${element}`] = { page: '/portfolio/[slug]', query: { slug: element}}
|
||||||
|
});
|
||||||
|
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
}))
|
34
package.json
Normal file
34
package.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "website",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"export": "next export && node export.js && yarn move_next",
|
||||||
|
"start": "next start",
|
||||||
|
"move_next": "mv out/_next out/assets",
|
||||||
|
"serve": "serve out"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@zeit/next-css": "^1.0.1",
|
||||||
|
"@zeit/next-stylus": "^1.0.1",
|
||||||
|
"glob": "^7.1.6",
|
||||||
|
"gray-matter": "^4.0.2",
|
||||||
|
"next": "9.1.5",
|
||||||
|
"next-offline": "^4.0.6",
|
||||||
|
"raw-loader": "^4.0.0",
|
||||||
|
"react": "16.12.0",
|
||||||
|
"react-dom": "16.12.0",
|
||||||
|
"react-feather": "^2.0.3",
|
||||||
|
"react-markdown": "^4.2.2",
|
||||||
|
"replace-in-file": "^4.2.0",
|
||||||
|
"serve": "^11.2.0",
|
||||||
|
"stylus": "^0.54.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^12.12.17",
|
||||||
|
"@types/react": "^16.9.16",
|
||||||
|
"typescript": "^3.7.3"
|
||||||
|
}
|
||||||
|
}
|
23
pages/_app.tsx
Normal file
23
pages/_app.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import App from 'next/app'
|
||||||
|
|
||||||
|
class MyApp extends App {
|
||||||
|
// Only uncomment this method if you have blocking data requirements for
|
||||||
|
// every single page in your application. This disables the ability to
|
||||||
|
// perform automatic static optimization, causing every page in your app to
|
||||||
|
// be server-side rendered.
|
||||||
|
//
|
||||||
|
// static async getInitialProps(appContext) {
|
||||||
|
// // calls page's `getInitialProps` and fills `appProps.pageProps`
|
||||||
|
// const appProps = await App.getInitialProps(appContext);
|
||||||
|
//
|
||||||
|
// return { ...appProps }
|
||||||
|
// }
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { Component, pageProps } = this.props
|
||||||
|
return <Component {...pageProps} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyApp
|
26
pages/_document.tsx
Normal file
26
pages/_document.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// _document is only rendered on the server side and not on the client side
|
||||||
|
// Event handlers like onClick can't be added to this file
|
||||||
|
|
||||||
|
// ./pages/_document.js
|
||||||
|
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
class MyDocument extends Document {
|
||||||
|
static async getInitialProps(ctx) {
|
||||||
|
const initialProps = await Document.getInitialProps(ctx)
|
||||||
|
return { ...initialProps }
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Html>
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyDocument
|
124
pages/index.tsx
Normal file
124
pages/index.tsx
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import { NextPage } from 'next'
|
||||||
|
import Head from 'next/head'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import '../styl/styl.styl'
|
||||||
|
import Element from '../components/Element'
|
||||||
|
import Navbar from '../components/Navbar'
|
||||||
|
import Header from '../components/Header'
|
||||||
|
import Menu from '../components/Menu'
|
||||||
|
import Filters from '../components/Filters'
|
||||||
|
import Category from '../components/interfaces/Category'
|
||||||
|
import { Component } from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
userAgent?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface el {
|
||||||
|
link: string,
|
||||||
|
title: string,
|
||||||
|
img: string,
|
||||||
|
date: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
interface States {
|
||||||
|
elements: el[]
|
||||||
|
asideHeight: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// export const config = {amp: 'hybrid'}
|
||||||
|
|
||||||
|
const categories: Category[] = [
|
||||||
|
{
|
||||||
|
name: "test",
|
||||||
|
slug: "pouet"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const elements: el[] = [
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Dzeio.io, Services en ligne pour vous simplifier la vie !", img:"/sea.jpg", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Loram ipsum dolor sit amet", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"j'aime les licornes et leurs jolie corne", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Pokémon ! attrapez les tous !", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"abcde", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"def", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"abc", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||||
|
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()}
|
||||||
|
]
|
||||||
|
|
||||||
|
export default class Page extends Component<Props, States> {
|
||||||
|
|
||||||
|
onQuery = (query: string) => {
|
||||||
|
console.log(`query: ${query}`)
|
||||||
|
const t= elements.filter(el => {
|
||||||
|
return el.title.toLowerCase().includes(query.toLowerCase())
|
||||||
|
})
|
||||||
|
this.setState({
|
||||||
|
elements: t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onHeight = (height: number) => {
|
||||||
|
this.setState({
|
||||||
|
asideHeight: height
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setState({
|
||||||
|
elements
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Head>
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
</Head>
|
||||||
|
<Navbar>
|
||||||
|
<Menu />
|
||||||
|
</Navbar>
|
||||||
|
<Header />
|
||||||
|
<main>
|
||||||
|
<span>
|
||||||
|
{this.state && this.state.elements.map((el, index) => (
|
||||||
|
<Element key={index} link={el.link} title={el.title} image={el.img} date={el.date} />
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
<Filters categories={categories} onQuery={this.onQuery} onHeight={this.onHeight}/>
|
||||||
|
</main>
|
||||||
|
<style jsx>{`
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
main span {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 820px) and (min-height: ${this.state && this.state.asideHeight ? this.state.asideHeight+100 : 600}px) {
|
||||||
|
main span {
|
||||||
|
max-width: calc(100% - 400px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
28
pages/portfolio/[slug].tsx
Normal file
28
pages/portfolio/[slug].tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { NextPage, NextPageContext } from "next"
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import Post from "../../components/Post"
|
||||||
|
import ReactMarkdown from 'react-markdown'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
post: Post
|
||||||
|
}
|
||||||
|
|
||||||
|
const PostPage: NextPage<Props> = (props: Props) => {
|
||||||
|
// React.
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<ReactMarkdown source={props.post.content}/>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PostPage.getInitialProps = async (context: NextPageContext) => {
|
||||||
|
const { slug } = context.query
|
||||||
|
if (typeof slug === "object") throw new Error("Slug is not correct")
|
||||||
|
const post = new Post(slug)
|
||||||
|
await post.fetch()
|
||||||
|
return {post}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostPage
|
58
pages/portfolio/index.tsx
Normal file
58
pages/portfolio/index.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { NextPage, NextPageContext } from "next"
|
||||||
|
import Link from 'next/link'
|
||||||
|
import Post from "../../components/Post"
|
||||||
|
// import posts from '../../posts/pages.json'
|
||||||
|
// import firstline from 'firstline'
|
||||||
|
// import 'fs'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
files: fileInformations[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface fileInformations {
|
||||||
|
title: string
|
||||||
|
slug: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const PortfolioIndex: NextPage<Props> = (props: Props) => {
|
||||||
|
|
||||||
|
const el: JSX.Element[] = []
|
||||||
|
for (const post of props.files) {
|
||||||
|
el.push(
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{props.files.map(post => (
|
||||||
|
<li key={post.slug}>
|
||||||
|
<Link href="/portfolio/[slug]" as={`/portfolio/${post.slug}`}>
|
||||||
|
<a>{post.title}</a>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
|
||||||
|
const arr: fileInformations[] = []
|
||||||
|
for (const post of await Post.fetchAll()) {
|
||||||
|
if (!post.isStarted) await post.fetch()
|
||||||
|
arr.push({
|
||||||
|
slug: post.slug,
|
||||||
|
title: post.title
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {files: arr}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PortfolioIndex
|
||||||
|
|
||||||
|
function l(args: any) {
|
||||||
|
console.log(arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
}
|
5
posts/test.md
Normal file
5
posts/test.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: pouet :D
|
||||||
|
---
|
||||||
|
|
||||||
|
# Pouet :D
|
3
public/clouds.svg
Normal file
3
public/clouds.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="1440" height="55" viewBox="0 0 1440 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M-72.0044 55C-24.0044 1.66667 23.9956 1.66667 71.9956 55H-72.0044ZM-0.00439644 55C47.9956 -11.6667 95.9956 -11.6667 143.996 55H-0.00439644ZM71.9956 55C119.996 8.33333 167.996 8.33333 215.996 55H71.9956ZM143.996 55C191.996 -5 239.996 -5 287.996 55H143.996ZM215.996 55C263.996 8.33333 311.996 8.33333 359.996 55H215.996ZM287.996 55C335.996 -18.3333 383.996 -18.3333 431.996 55H287.996ZM359.996 55C407.996 -5 455.996 -5 503.996 55H359.996ZM431.996 55C479.996 8.33333 527.996 8.33333 575.996 55H431.996ZM503.996 55C551.996 -5 599.996 -5 647.996 55H503.996ZM575.996 55C623.996 21.6667 671.996 21.6667 719.996 55H575.996ZM647.996 55C695.996 1.66667 743.996 1.66667 791.996 55H647.996ZM719.996 55C767.996 15 815.996 15 863.996 55H719.996ZM791.996 55C839.996 28.3333 887.996 28.3333 935.996 55H791.996ZM863.996 55C911.996 21.6667 959.996 21.6667 1008 55H863.996ZM935.996 55C983.996 1.66667 1032 1.66667 1080 55H935.996ZM1008 55C1056 18.3333 1104 18.3333 1152 55H1008ZM1080 55C1128 8.33333 1176 8.33333 1224 55H1080ZM1152 55C1200 1.66667 1248 1.66667 1296 55H1152ZM1224 55C1272 21.6667 1320 21.6667 1368 55H1224ZM1296 55C1344 5 1392 5 1440 55H1296ZM1368 55C1416 -1.66667 1464 -1.66667 1512 55H1368Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
3
public/logo.svg
Normal file
3
public/logo.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M72.8109 101.066L25 128.807L44.2174 84.4441L72.8109 101.066ZM79.7067 24.0024L125 128.807L45.0697 82.3519L70.2925 24.0024C71.8679 22.4526 73.4308 21.8064 74.9806 22.0652C76.556 21.7808 78.1321 22.427 79.7067 24.0024Z" fill="#4285F4"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 390 B |
34
public/manifest.json
Normal file
34
public/manifest.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"short_name": "Gitea",
|
||||||
|
"name": "Gitea - Git with a cup of tea",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/img/gitea-lg.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "880x880"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/gitea-sm.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "120x120"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/gitea-512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/gitea-192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"serviceworker": {
|
||||||
|
"src": "/service-worker.js"
|
||||||
|
},
|
||||||
|
"start_url": "/",
|
||||||
|
"scope": "/",
|
||||||
|
"background_color": "#FAFAFA",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#6cc644"
|
||||||
|
}
|
BIN
public/sea.jpg
Normal file
BIN
public/sea.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
BIN
public/uploads/stm.png
Normal file
BIN
public/uploads/stm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
102
styl/include/_button.styl
Normal file
102
styl/include/_button.styl
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
$color = #4285F4
|
||||||
|
$hover = #70A8F8
|
||||||
|
$active = #3066D1
|
||||||
|
|
||||||
|
$outline-shadow = inset 0 0 0 2px $color
|
||||||
|
$outline-hover = rgba(179, 216, 253, 0.3)
|
||||||
|
$outline-active = rgba(66, 133, 244, 0.3)
|
||||||
|
|
||||||
|
$active-shadow = 0 0 0 3px rgba(204,204,204,.75)
|
||||||
|
|
||||||
|
button, a.button
|
||||||
|
cursor: pointer
|
||||||
|
color: #FFF
|
||||||
|
background-color: $color
|
||||||
|
border-radius: 5px
|
||||||
|
border: none
|
||||||
|
padding: 7px 14px
|
||||||
|
transition-property: box-shadow, background-color
|
||||||
|
transition-duration: 200ms
|
||||||
|
transition-timing-function: cubic-bezier(.2,0,.6,1)
|
||||||
|
margin: 3px
|
||||||
|
display: inline-flex
|
||||||
|
user-select: none
|
||||||
|
outline: none
|
||||||
|
/* Set Chrome on Firefox base */
|
||||||
|
line-height: 22px
|
||||||
|
text-decoration: none
|
||||||
|
box-sizing: border-box
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background-color: $hover
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background-color: $active
|
||||||
|
|
||||||
|
&:focus:not(.disabled)
|
||||||
|
background-color: $active
|
||||||
|
box-shadow: $active-shadow
|
||||||
|
|
||||||
|
&::-moz-focus-inner
|
||||||
|
border: none
|
||||||
|
|
||||||
|
|
||||||
|
&.outline, &.ghost
|
||||||
|
color: $color
|
||||||
|
background-color: transparent
|
||||||
|
|
||||||
|
&:hover:not(:disabled):not(.disabled)
|
||||||
|
background-color: $outline-hover
|
||||||
|
|
||||||
|
&:active:not(:disabled):not(.disabled)
|
||||||
|
background-color: $outline-active
|
||||||
|
|
||||||
|
&.loading::after
|
||||||
|
border-color: transparent transparent $color $color
|
||||||
|
|
||||||
|
&.outline
|
||||||
|
box-shadow: $outline-shadow
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
box-shadow: $outline-shadow, $active-shadow
|
||||||
|
|
||||||
|
&:disabled, &.disabled
|
||||||
|
background-color: #EEE
|
||||||
|
color: #BDBDBD
|
||||||
|
cursor: default
|
||||||
|
pointer-events: none
|
||||||
|
|
||||||
|
&.outline
|
||||||
|
box-shadow: 0 0 0 2px #BDBDBD
|
||||||
|
|
||||||
|
&.loading
|
||||||
|
color: transparent
|
||||||
|
position: relative
|
||||||
|
pointer-events: none
|
||||||
|
// cursor: default
|
||||||
|
&::after
|
||||||
|
content: ""
|
||||||
|
display: block
|
||||||
|
border: white 2px solid
|
||||||
|
border-color: transparent transparent white white
|
||||||
|
width: 1em
|
||||||
|
position: absolute
|
||||||
|
top: calc(50% - (1em / 2))
|
||||||
|
left: calc(50% - (1em / 2))
|
||||||
|
border-radius: 1000000000px
|
||||||
|
height: 1em
|
||||||
|
box-sizing: inherit
|
||||||
|
animation: ButtonLoading .5s infinite linear
|
||||||
|
|
||||||
|
|
||||||
|
a.button.outline:focus:not(.disabled),
|
||||||
|
a.button.ghost:focus:not(.disabled),
|
||||||
|
button.outline:focus, button.ghost:focus
|
||||||
|
background-color: $outline-active
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes ButtonLoading
|
||||||
|
0%
|
||||||
|
transform: rotate(0)
|
||||||
|
100%
|
||||||
|
transform: rotate(365deg)
|
90
styl/include/_input.styl
Normal file
90
styl/include/_input.styl
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
$color = #4285F4
|
||||||
|
|
||||||
|
.input
|
||||||
|
position relative
|
||||||
|
|
||||||
|
*:not(input)
|
||||||
|
display inline
|
||||||
|
|
||||||
|
&.inline
|
||||||
|
display inline-block
|
||||||
|
|
||||||
|
&:not(:last-of-type)
|
||||||
|
margin-right 10px
|
||||||
|
|
||||||
|
input
|
||||||
|
display block
|
||||||
|
border-radius 10px
|
||||||
|
background-color #EEE
|
||||||
|
border none
|
||||||
|
padding 15px 20px
|
||||||
|
margin 3px
|
||||||
|
box-shadow inset 0 0 0 2px #BDBDBD
|
||||||
|
transition-property background-color, box-shadow, border
|
||||||
|
transition-duration 200ms
|
||||||
|
transition-timing-function cubic-bezier(.2, 0, .6, 1)
|
||||||
|
|
||||||
|
// Make input follow .input size
|
||||||
|
width: inherit
|
||||||
|
max-width calc(100% - 46px) // padding * 2 + margin * 2
|
||||||
|
|
||||||
|
&::placeholder
|
||||||
|
text-transform: lowercase
|
||||||
|
color #666
|
||||||
|
|
||||||
|
:disabled
|
||||||
|
background-color #EFEFEF
|
||||||
|
box-shadow none
|
||||||
|
|
||||||
|
&:not([readonly]):not([disabled])
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background-color #DDD
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
background-color #FFF
|
||||||
|
box-shadow inset 0 0 0 2px $color, 0 0 0 3px rgba(204,204,204, .75)
|
||||||
|
|
||||||
|
label
|
||||||
|
text-transform uppercase
|
||||||
|
margin auto
|
||||||
|
font-weight 700
|
||||||
|
|
||||||
|
.helper
|
||||||
|
text-transform lowercase
|
||||||
|
font-weight 300
|
||||||
|
|
||||||
|
.status
|
||||||
|
float right
|
||||||
|
text-transform lowercase
|
||||||
|
font-weight 300
|
||||||
|
font-style italic
|
||||||
|
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
|
||||||
|
i
|
||||||
|
width 25px
|
||||||
|
position absolute
|
||||||
|
left 28px
|
||||||
|
top 18px
|
||||||
|
// pointer-events none
|
||||||
|
color #666
|
||||||
|
transition color 200ms cubic-bezier(.2,0,.6,1)
|
||||||
|
|
||||||
|
&.icon-right i
|
||||||
|
left initial
|
||||||
|
right 28px
|
||||||
|
|
||||||
|
&.icon-left input
|
||||||
|
padding-left 50px
|
||||||
|
|
||||||
|
&.icon-right input
|
||||||
|
padding-right 50px
|
||||||
|
|
||||||
|
|
||||||
|
&.icon-right input, &.icon-left input
|
||||||
|
max-width calc(100% - 76px)
|
||||||
|
|
||||||
|
input:focus:not([readonly]) + i
|
||||||
|
color $color
|
6
styl/styl.styl
Normal file
6
styl/styl.styl
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@import "include/_button"
|
||||||
|
@import "include/_input"
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin 0
|
||||||
|
}
|
7
style.css
Normal file
7
style.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.card {
|
||||||
|
box-shadow: 0 0 5px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.backWhite {
|
||||||
|
background: white;
|
||||||
|
}
|
29
tsconfig.json
Normal file
29
tsconfig.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": false,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx"
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user