<file_sep>import React from 'react';
import styled from 'styled-components';
import { Section } from '../components';
import { THEME } from '../config';
import GeneralLayout from '../layouts/general';
import '../styles/index.css';

/**
  尺寸定义全部使用 EM
  相对于 BlogContentArea 设置的 FontSize
 */
// https://github.com/markdowncss/retro/blob/master/css/retro.css
const BlogContentArea = styled.div`
  max-width: ${THEME.size.sectionContainerWidthMax};
  margin: 0 auto;
  padding: 1em;

  font-family: "Courier New";
  font-size: 16px;
  line-height: 1.45em;

  display: flex;
  justify-content: center;

  @media screen and (max-width: 1300px) {
    flex-direction: column-reverse;
    font-size: 10px;
    line-height: 2.6em;
  }

`;

const MarkdownContent = styled.div`

  flex-grow: 1;
  max-width: 100%;

  padding: 0 1em;
  min-height: 100%;

  & code {
    color: #111;
    background: #ddd;
  }
  & pre {
    margin: .5em 0;
    padding: .5em;
    
    overflow-x: scroll;
    background-color: #333;
  }
  & pre code {
    max-width: 100%;
    font-family: Menlo, Monaco, "Courier New", monospace;
    color: #fff;
    background: transparent;
    font-size: .6em;
  }

  & a, a:visited {
    color: #0000ff;
  }
  & a:hover, a:focus, a:active {
    color: #007cff;
  }

  & ul ul {
    padding: 0 1.6em;
    /* list-style-type: disc; */
    /* list-style-type: circle; */
  }
  & ul ul ul {
    list-style-type: square;
  }

  &.retro-no-decoration {
    text-decoration: none;
  }

  & p, .retro-p {
    margin-bottom: .6em;
  }

  & h1, .retro-h1, h2, .retro-h2, h3, .retro-h3, h4, .retro-h4 {
    margin: 1.414em 0 .5em;
  }
  & h1, .retro-h1 {
    width: 100%;
    text-align: center;

    margin-top: 0;    
    font-size: 1.8em;
    letter-spacing: .16em;
  }
  & h2, .retro-h2 {
    font-size: 1.6em;
  }
  & h3, .retro-h3 {
    font-size: 1.2em;
  }
  & h4, .retro-h4 {
    font-size: 1em;
  }
  & h5, .retro-h5 {
    font-size: .8em;
  }
  & h6, .retro-h6 {
    font-size: .7em;
  }
  & small, .retro-small {
    font-size: .6em;
  }
  & blockquote {
    margin: 1em 0;
    padding-left: 1em;
    border-left: .6em solid ${THEME.color.primary.border};
  }

  & img, canvas, iframe, video, svg, select, textarea {
    max-width: 100%;
  }


  & table {
    border-collapse: collapse;
    border-spacing: 0;
    empty-cells: show;
    border: 1px solid #cbcbcb;
  }
  & thead {
    background-color: #666666;
    color: #fff;
    /* text-align: left; */
    vertical-align: bottom;
    letter-spacing: .2em;
  }
  & td,th {
    margin: 0;
    padding: .5em 1em;
    border-left: 1px solid #cbcbcb;
    border-width: 0 0 0 1px;
    font-size: inherit;
    overflow: visible;
  }
  & tr:nth-child(2n+1) {
    background-color: transparent;
  }
  & tr:nth-child(2n+0) {
    background-color: #f9f9f9;
  }
 
  & caption {
    color: #000;
    font: italic 85%/1 arial,sans-serif;
    padding: 1em 0;
    text-align: center;
  }

`;

const SideColumn = styled.div`
  padding: 0 1em;

  @media screen and (max-width: 1024px) {
    padding: 2em 1em;
  }
`;

const Tag = styled.span`
  margin-left: 1em;
  color: #999;
  text-decoration: underline;
  
`;
const TagsList = styled.p`
  width: 100%;
  margin-top: .2em;
  display: flex;
  flex-wrap: wrap;
  & span {
    /* color: #999; */
    font-weight: bold;
    letter-spacing: .16em;
  }
`;

const Details = styled.div`
  width: 100%;
  /* border: solid 1px red; */
  & h5, h6, p {
    display: inline-block;
    line-height: 2em;
    font-size: .8em;
  }
  & h5 {
    color: ${THEME.color.primary.ft};
  }
  & h6 {
    font-weight: normal;
  }
    
`;

export default function Blog({pageContext}) {
  // console.log(98989898, pageContext)

  const at = (pageContext?.frontmatter?.tags?.length > 0) ? pageContext?.frontmatter?.tags?.split(';') : null;
  const ak = (pageContext?.frontmatter?.keywords?.length > 0) ? pageContext?.frontmatter?.keywords?.split(';') : null;
  const ss = [];
  if (!!at && (at.length > 0)) ss.push(...at);
  if (!!ak && (ak.length > 0)) ss.push(...ak);
  const tags = Array.from(new Set(ss));

  const context = pageContext?.frontmatter || {};
  return (
    <GeneralLayout context={{
      ...context,
      head: pageContext?.frontmatter?.title,
    }} >

      <Section style={{background: '#fff', padding: '1em'}}>
        <BlogContentArea>
          <MarkdownContent dangerouslySetInnerHTML={{__html: pageContext?.html}} />
          <SideColumn >
            <Details>
              <table style={{width: '100%', marginBottom: '1.2em'}}>
                <tr>
                  <td><h5>主题：</h5><h6>{`${pageContext?.frontmatter?.subject}`}</h6></td>
                  <td><h5>类别：</h5><h6>{`${pageContext?.frontmatter?.category}`}</h6></td>
                </tr>
                <tr>
                  <td><h5>更新：</h5><h6>{`${pageContext?.frontmatter?.updated_when}`}</h6></td>
                  <td><h5>创建：</h5><h6>{`${pageContext?.frontmatter?.created_when}`}</h6></td>
                </tr>
                <tr>
                  <td><h5>作者：</h5><h6>{`${pageContext?.frontmatter?.author}`}</h6></td>
                </tr>
              </table>

              { !tags ? null : 
                <TagsList>
                  <span>{'标签&关键字：'}</span>
                  { tags.map((t) => (
                    <Tag>{t}</Tag>
                  )) }
                </TagsList>
                
              }
            </Details>
          </SideColumn >
        </BlogContentArea>
      </Section>

    </GeneralLayout>
  )
}
<file_sep>import React from 'react';
import styled from 'styled-components';
import { Link } from 'gatsby';
import { MENU_SETTING } from './menu.setting';
import { SVGTriangle } from './SVG';

/**
  Styled Components
 */
const MenuContainer = styled.nav`
  width: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;

  white-space: nowrap;
  font-size: 10px;
  
  height: ${ (props) => (props.height || MENU_SETTING.NAV_MENU_HEIGHT) };

  & a {
    text-decoration: none;
  }
  & ul {
    list-style: none;
  }

  @media screen and (max-width: ${MENU_SETTING.SCREEN_WIDTH_THRESHOLD}) {
    display: none;
  }

`;
const Menu = styled.ul`
  width: 100%;
  display: flex;
  justify-content: space-between;
`;
const SubMenu = styled.ul`
  display: block;
  position: absolute;
  z-index: 999999;
  top : ${ (props) => (props.ext ? '.3rem' : '100%')};
  left: ${ (props) => (props.ext ? '100%' : '0')};

  background: ${ (props) => (` ${props.color?.subBg || 'rgba(255, 255, 255, 0.6)' }`) };

  border-top  : ${ (props) => (props.ext ? 'none' : `solid 3px ${props.color?.arrow}`)};
  border-left : ${ (props) => (props.ext ? `solid 3px ${props.color?.arrow}` : 'none')};

  visibility: hidden;
  opacity: 0;
  transition: all .6s ease;

  &:before {
    content: '';
    position: absolute;
    top: ${ (props) => (props.ext ? '.2rem' : '-1.3rem') };
    left: ${ (props) => (props.ext ? '-1.3rem' : '1rem') };
    border: solid .6rem transparent;
    border-bottom-color : ${ (props) => (props.ext ? 'transparent' : (props.color?.arrow)) };
    border-right-color  : ${ (props) => (props.ext ? (props.color?.arrow) : 'transparent') };
  }
`;
const MenuItem = styled.li`
  position: relative;
  line-height: ${MENU_SETTING.NAV_MENU_HEIGHT};

  & a {
    display: block;
    padding: 0 .5rem;
    font-size: 1.1rem;
    color: ${(props) => props.color?.ft || '#eee'};
    transition: color 0.6s;
  }
  & a:hover {
    color: ${(props) => props.color?.ftHover || '#fff'};
  }
  &:hover > ${SubMenu} {
    visibility: visible;
    opacity: 1;
  }
`;
const SubMenuItem = styled(MenuItem)`
  line-height: 2rem;
`;


/**
  Function Components
 */
const NavSub = (props) => {
  const {items, ext} = props;
  return(
    !items ? null :
    <SubMenu {...props} ext={ext}>
    { items?.map((item, index) => (
      <SubMenuItem key={index} active={index === -1}>
        <Link to={item.url} style={{width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
          <span>{item.text}</span>
          { !item.sub ? null : 
            <div style={{ height: '100%', marginLeft: '.3em', display: 'inline-flex', justifyContent: 'center', alignItems: 'center'}}>
              <SVGTriangle width=".8em" height=".8em" color={props.color.ft} direction="right" />
            </div> 
          }
        </Link>
        { !item.sub ? null : <NavSub {...props} ext={true} items={item.sub} /> }
      </SubMenuItem>
    )) }
    </SubMenu>
  )
}

export const NavMenu = (props) => {
  const { items } = props;
  return (
    !items ? null :
    <MenuContainer {...props}>
      <Menu>
      { items?.map((item, index) => (
        <MenuItem {...props} key={index} active={index === -1} >
          <Link to={item.url} style={{width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
            <span>
              {item.text}
            </span>
            { !item.sub ? null : 
              <div style={{ height: '100%', marginLeft: '.3em', display: 'inline-flex', justifyContent: 'center', alignItems: 'center'}}>
                <SVGTriangle width=".8em" height=".8em" color={props.color.ft} />
              </div> 
            }
          </Link>
          { !item.sub ? null : <NavSub {...props} items={item.sub} /> }
        </MenuItem>
      )) }
      </Menu>
    </MenuContainer>
  )
}
<file_sep>// import React from 'react';
import styled from 'styled-components';
import { THEME } from '../config';

export const Button = styled.button`
  border-radius: 0;
  padding: .5rem 1rem;
  outline: none;
  white-space: nowrap;
  cursor: pointer;
  color: ${({ primary }) => (primary ? '#fff' : THEME.color.primary.bg)};;
  border: ${({ primary }) => (primary ? 'solid 1px #fff' : `solid 1px ${THEME.color.primary.bg}`)};;
  background: ${({ primary }) => (primary ? THEME.color.primary.bg : 'none')};

  & svg {
    width: 1rem;
    height: 1rem;
    margin-left: .5rem;
    border-radius: 50%;
    border: solid 1px;
    transform: translateY(.2rem);
  }

  &:hover {
    transition: all .3s ease-out;
    background: ${THEME.color.primary.bg};
    color: #fff;
  }

  @media screen and (max-width: 991px) {
    width: 100%;
  }
`;
<file_sep>import React, { useState } from 'react';
import styled from 'styled-components';
import { Link } from 'gatsby';
import { Bars } from './bars';
import { MENU_SETTING } from './menu.setting';
import { SVGTriangle } from './SVG';
/**
  Styled Components
 */
const Menu = styled.ul`
  position: relative;
  width: 100vw;
  height: 100vh;
  padding: 6em 2em;
  line-height: 3em;
  display: block;
  z-index: 9999;

  font-size: 24px;

  background: ${ (props) => ( props.color?.bg) };

  transform: ${(props) => !props.open ? `translateX(110vw)` : `translateX(0)` } ;

  transition: all .6s ease;
`;
const SubMenu = styled.ul`
  margin: 0 0 0 1.2em;
  display: none;
  visibility: visible;
  opacity: 1;
`;
const MenuItem = styled.li`
  border-top: solid 1px #999;
  & a {
    display: block;
    padding: 0 .5em;
    font-size: 1.1em;
    color: ${(props) => props.color?.ft || '#ddd'};
    transition: color 0.6s;
  }
  & a:hover {
    color: ${(props) => props.color?.ftHover || '#fff'};
  }
  &:hover > ${SubMenu} {
    display: block;
    visibility: visible;
    opacity: 1;
  }
`;

/**
  Function Components
 */
const RecurMenu = (props) => {
  const {items, open, ext} = props;
  return (
    !items ? null :
    <SubMenu  className='menu' {...props} ext={ext} open={open} >
    { items?.map((item, index) => (
      <MenuItem {...props} key={index} active={index === -1}>
        <Link to={item.url} style={{width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
          <span>{item.text}</span>
          { !item.sub ? null : 
            <div style={{ height: '100%', marginLeft: '.3em', display: 'inline-flex', justifyContent: 'center', alignItems: 'center'}}>
              <SVGTriangle width=".8em" height=".8em" color={props.color.ft} />
            </div> 
          }
        </Link>
        { !item.sub ? null : <RecurMenu {...props} ext={true} items={item.sub} /> }
      </MenuItem>
    )) }
    </SubMenu>
  )
}
const MainMenu = (props) => {
  const {items, open, ext} = props;
  return (
    !items ? null :
    <Menu className='menu' {...props} ext={ext} open={open} >
    { items?.map((item, index) => (
      <MenuItem {...props} key={index} active={index === -1}>
        <Link to={item.url} style={{width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
          <span>{item.text}</span>
          { !item.sub ? null : 
            <div style={{ height: '100%', marginLeft: '.3em', display: 'inline-flex', justifyContent: 'center', alignItems: 'center'}}>
              <SVGTriangle width=".8em" height=".8em" color={props.color.ft} />
            </div> 
          }
        </Link>
        { !item.sub ? null : <RecurMenu {...props} ext={true} items={item.sub} /> }
      </MenuItem>
    )) }
    </Menu>
  )
}

const MenuContainer = styled.div`
  position: fixed;
  height: 1px;     // 防止这一层会遮盖住 blog list

  font-size: 10px;

  & a {
    text-decoration: none;
  }
  & ul {
    list-style-type: none;
  }

  @media screen and (min-width: ${MENU_SETTING.SCREEN_WIDTH_THRESHOLD}) {
    display: none;
  }
`;
const PopButton = styled.div`
  cursor: pointer;
  position: absolute;
  top: 1em;
  right: 2em;

  z-index: 999999;
`;

export const PopMenu = (props) => {
  const {items, color} = props;
  const [open, setOpen] = useState(false);

  return (
    <MenuContainer className='container' {...props} >
      
      <PopButton className='button' onClick={() => setOpen(!open)} >
        <Bars open={open} color={color.ft} ></Bars>
      </PopButton>

      <MainMenu {...props} open={open} items={items} />

    </MenuContainer>
  )

}
<file_sep>import React from "react";
import { graphql, useStaticQuery } from 'gatsby';
import styled from 'styled-components';
import { THEME } from '../config';
import { Section, CenterColumn, NavMenu, PopMenu } from '../components';

const JumbotronArea = styled.div`
  width: 100%;
  padding: 2em 0;

  font-size: 16px;
  line-height: 2em;

  display: flex;
  justify-content: center;
  align-items: center;

  & img {
    width: 30%;
  }

  @media screen and (max-width: 800px) {
    font-size: 12px;

    flex-direction: column-reverse;
    
    & img {
      width: 50%;
    }
  }
  @media screen and (max-width: 450px) {
    font-size: 10px;
  }
`;
const Slogan = styled.div`
  width: 50%;
  height: 100%;
  margin: 0 2em;

  display: flex;
  flex-direction: column;

  color: #e0e0e0;

  & h1 {
    line-height: 2.3em;
    font-size: 2.8em;
  }
  & p {
    font-size: 1.2em;
    line-height: 1.6em;
    letter-spacing: .1em;
  }
  @media screen and (max-width: 800px) {
    width: 80%;
  }
`;

export default function JumbotronSection() {
  const data = useStaticQuery(graphql`
query {
  site {
    siteMetadata {
      title
      author
      description
      jumbotron
      navItems {
        key
        url
        text
        sub {
          key
          url
          text
          sub {
            key
            url
            text
          }
        }
      }
    }
  }
}
  `);

  return (
    <Section style={{background: `linear-gradient(90deg,${THEME.color.primary.border},${THEME.color.primary.ft})` }}>
      <CenterColumn>
        <PopMenu color={{ ft: '#eee', bg: THEME.color.primary.border }} items={data.site.siteMetadata.navItems} />

        <div style={{width: '100%', display: 'flex', justifyContent: 'center'}}>
          <div style={{width: '20rem', color: '#fff'}} >
            <NavMenu items={data.site.siteMetadata.navItems} color={{ 
              subBg: THEME.color.primary.border,
              arrow: '#fff',
              ft: '#fff',
            }}/>
          </div>
        </div>
        <JumbotronArea>
          <Slogan>
            <h1>{data.site.siteMetadata.title}</h1>
            <p>{data.site.siteMetadata.description}</p>
          </Slogan>
          <img src={data.site.siteMetadata.jumbotron} alt='coding' />
        </JumbotronArea>
      </CenterColumn>
    </Section>
  )
}
<file_sep>import styled from 'styled-components';

export const Bars = styled.span`
  width: 2em;
  height: .2em;
  background: ${(props) => (!!props.open ? 'transparent' : (props.color || '#999'))} ;
  display: inline-block;
  position: relative;

  transition: all .2s ease;

  &:before,&:after {
    content: '';
    width: 2em;
    height: .2em;
    background: ${(props) => (props.color || '#999')} ;
    display: inline-block;

    position: absolute;
  }
  &:before {
    top       : ${(props) => (!props.open ? '.5em' : '0')};
    transform : ${(props) => (!props.open ? 'none' : 'rotate(45deg)')};
  }
  &:after {
    top       : ${(props) => (!props.open ? '-.5em' : '0')};
    transform : ${(props) => (!props.open ? 'none' : 'rotate(135deg)')};
  }
`;
<file_sep>export const MENU_SETTING = {
  SCREEN_WIDTH_THRESHOLD: '576px',
  NAV_MENU_HEIGHT: '4em',
}
<file_sep>export * from './elements';
export * from './bars';
export * from './search';

export * from './Head';
export * from './Button';
export * from './Menu';
export * from './Menu.Pop';
export * from './ShortCutToTop';

export * from './Slider';
<file_sep>import React from 'react';

export const SVGTriangle = ({width, height, direction, color}) => (
  <svg xmlns="http://www.w3.org/2000/svg" width={width} height={height} viewBox="0 0 16 16">
    <polygon points={ direction === 'right' ? "4,3 13,9 4,14" : "2,4 14,4 9,13"} style={{
      fill: color,
    }} />
  </svg>
)
<file_sep>import React from "react";
import HomeLayout from '../layouts/home';
import '../styles/index.css';

export default function HomePage() {
  return (
    <HomeLayout context={{ head: '首页' }} />
  )
}
<file_sep># blog
This is a fundamental web site source code repo.
This project is mainly based on React & Gatsby.<file_sep>import React from "react"
import { Link } from 'gatsby';
import '../styles/index.css';

export default function NotFound() {
  return (
    <>
      <h1>Page not found!</h1>
      <Link to="/">Back to Home</Link>
    </>
  )
}
<file_sep>import React from 'react';
import { Head, PageTopAnchor, ShortCutToTop } from '../components';
import JumbotronSection from './section.jumbotron';
import BlogListSection from './section.bloglist';
import FooterSection from './section.footer'; 

export default function HomeLayout ({context}) {
  return (
  <>
    <Head context={context} />

    <PageTopAnchor />
    <ShortCutToTop>👍</ShortCutToTop>

    <JumbotronSection />
    <BlogListSection />
    <FooterSection />
  </>
  )
}
<file_sep>import React, { useState, useRef, useMemo, useEffect } from 'react';
import styled, { keyframes, css } from 'styled-components';
// import { THEME } from '../config';

const ANIMATION_TOTAL = 100; // 动画整体进度为 100%

const move2Left = (width, timings) => keyframes`
  0%   { margin-left: 0; }
  ${timings.map((times, index) => (
    `${times[0]}%, ${times[1]}% { margin-left: -${width * index}px; }`
  ))}
  /* 100% { margin-left: 0; } */
`;

const SliderContainer = styled.div`
  position: relative;
  width : ${ (props) => `${props?.size?.width}px` };
  height: ${ (props) => `${props?.size?.height}px` };
  /* border: solid 5px #f00; */
`;
const SliderWindow = styled.div`
  /* border: solid 5px #0f0; */
  position: absolute;
  top: 0;
  left: 0;
  width : ${ (props) => `${props?.size?.width}px` };
  height: ${ (props) => `${props?.size?.height}px` };
  overflow: hidden;
`;
// props.focusId 只有在 animation 没有的情况下，才有效果
const SliderGallery = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  margin-left: ${(props) => `-${ (props.focusId || 0) * props?.width }px`};

  display: flex;

  animation: ${ (props) => (props.focusId !== null) ? '' : css`${move2Left(props?.width, props?.timings)} ${props.duration}s linear infinite` };
`;
export const SliderItem = styled.div`
  /* border: solid 1px #ff0000; */
  position: relative;
  width : ${ (props) => `${props?.size?.width}px` };
  height: ${ (props) => `${props?.size?.height}px` };

  & img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%; 
  }
  & p {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    text-align: center;
    overflow: hidden;
  }
`;
const SliderItemIndicator = styled.div`
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;

  display: flex;
  justify-content: center;
`;
const SliderIndicatorDot = styled.button`
  width: 16px;
  height: 16px;
  border: solid 3px #333;
  border-radius: 50%;
  margin: 2rem .2rem;
  background: ${ (props) => ( props.active ? 'yellow' : 'grey' ) };
`;

export const Slider = ({size, duration, children}) => {
  const [focusId, setFocusId] = useState(null);
  const [, setTrigger] = useState(0);
  const timerRef = useRef(null);
  const galleryRef = useRef();

  useEffect(() => {
    console.log('effect')
    timerRef.current = setInterval(() => {
      // console.log('interval', trigger); // !!! 这里的 trigger 始终都不会改变，似乎被 “冻住” 了 （无法访问外部的变量，而外部的变量其实是变化了的） !!!
      setTrigger(Math.random());        // 所以，这里设置随机数，来触发界面刷新
    }, 1000);
    return () => {
      console.log('Bye', timerRef.current);
      clearInterval(timerRef.current);
    }
  }, []);

  const timings = useMemo(() => {
    const length  = children?.length || 1;
    const trans   = ANIMATION_TOTAL / length / 10;    // 图片与图片间的过场动画时间
    const result  = children.map((x, index) => ([trans, ANIMATION_TOTAL * (index + 1) / length]));
    result.forEach((timing, index) => {
      if (index > 0) timing[0] = result[index - 1][1] + trans;
    });
    return result;
  }, [children]);

  const styleMarginLeft = !galleryRef?.current ? 0 : window.getComputedStyle(galleryRef.current).getPropertyValue("margin-left");
  const currentImgId = (focusId !== null) ? focusId : (-parseInt(parseInt(styleMarginLeft)/size.width));
  
  // console.log(galleryRef, styleMarginLeft);
  // console.log(trigger, currentImgId);
  return (
    !children?.length ? null :

    // <>
    //   <h1>{trigger}</h1>
    //   <button onClick={() => setTrigger(trigger +1)}>+</button>
    // </>

    <SliderContainer size={size}>
      <SliderWindow size={size}>
        
        <SliderGallery ref={galleryRef} width={size.width} timings={timings} duration={duration * (children?.length || 0)} focusId={focusId}>
        { children.map((child, index) => {
            const newChild = React.cloneElement(child, { 
              ...child?.props,
              size: size,
            });
            return newChild;
        })  }
        </SliderGallery>

        <SliderItemIndicator>
        { children.map((child, index) => ( <SliderIndicatorDot active={index === currentImgId} onClick={ () => setFocusId( (focusId !== index) ? index : null) }></SliderIndicatorDot> ))}
        </SliderItemIndicator>

      </SliderWindow>
    </SliderContainer>
  )
}
<file_sep>import React from "react";
import styled from 'styled-components';
import { graphql, useStaticQuery } from 'gatsby';
import { THEME } from '../config';
import { Section } from '../components';

const FooterArea = styled.div`
  max-width: ${THEME.size.sectionContainerWidthMax};
  min-height: 6em;
  margin: 0 auto;
  padding: 1em;

  font-size: 16px;

  display: flex;
  justify-content: space-between;
  
  
  @media screen and (max-width: 800px) {
    line-height: 2em;
    font-size: 10px;

    flex-direction: column-reverse;
    align-items: center;
  }
`;

export default function FooterSection() {
  const data = useStaticQuery(graphql`
query {
  site {
    siteMetadata {
      copyright
      contact {
        phone
        email
      }
      
    }
  }
}
  `);

  return (
    <Section style={{ background: THEME.color.dark.bg, color: '#fff' }}>
      <FooterArea>
        <span>{data?.site?.siteMetadata?.copyright}</span>
        <div>
          <span role="img" aria-label="Phone" >☎️</span>
          <span>{data?.site?.siteMetadata?.contact?.phone}</span>
          <span style={{margin: '0 .7em'}}></span>
          <span role="img" aria-label="Email" >📧</span>
          <span>{data?.site?.siteMetadata?.contact?.email}</span>
        </div>
        <span role="img" aria-label="Goodness" >✨ 🍺 🏠 ☕ 🌈 🇨🇳  </span>
      </FooterArea>
    </Section>
  )
}
<file_sep>import React from 'react';

export const PageTopAnchor = () => (<div id='__page_top__' />)
export const ShortCutToTop = ({children}) => (
  <div style={{ 
    position: 'fixed', 
    bottom: '2rem',
    right: '2rem', 
    zIndex: '99999',
    fontSize: '2rem',
  }} >
    <a href='#__page_top__'><span role="img" aria-label="Up">{children}</span></a>
  </div>
)
<file_sep>export const THEME = {

  size: {
    sectionContainerWidthMax: '1300px',
  },

  // https://colorbrewer2.org/#type=sequential&scheme=PuBuGn&n=3

  color: {
    primary   : { bg: '#00A6CB', border: '#00818e', ft: '#00b8cb' },
    secondary : { bg: '#e4fd63', border: '#e4fd63', ft: '#e4fd63' },

    normal    : { bg: '#e6e6e6', border: '#adadad', ft: '#333', },
    // primary   : { bg: '#286090', border: '#204d74', },
    success   : { bg: '#cb008b', border: '#8e0061', },
    info      : { bg: '#bff9ff', border: '#80f3ff', },
    warning   : { bg: '#cba600', border: '#8e7400', },
    danger    : { bg: '#cb5500', border: '#8e3c00', },
    
    link      : { ft: '#23527c'},

    dark      : { bg: '#262626'},
  },

}

/**
  https://www.shutterstock.com/zh/color/cyan-blue

Single  : #00A6CB, #00b8cb, #00818e, #bff9ff, #80f3ff
Similar :                            #052fcb, #04218e
Contrast:                            #cb5500, #8e3c00
Triangle:          #cb008b, #8e0061, #cba600, #8e7400

 */ 

/**
  https://www.shutterstock.com/zh/color/teal-blue

Single  : #00807E, #008080, #005a5a, #bfffff, #80ffff
Similar :                            #002080, #00165a
Contrast:                            #803300, #5a2400
Triangle:          #800060, #5a0043, #806600, #5a4800

 */

/**
  https://www.shutterstock.com/zh/color/bottle-green

Single  : #006a4e, #006a5a, #004a3f, #bffff5, #80ffeb
Similar :                            #00256a, #001a4a
Contrast:                            #6a2300, #4a1900
Triangle:          #6a0057, #4a003d, #6a5100, #4a3900

 */
<file_sep>---
title: markdown
subtitle: markdown
subject: subject
category: category
tags: tag
keywords: kw
level: 100
cover: http://qiniuargus.weready.online/blog/coder.jpg
author: <NAME>
created_when: 2021-12-31
updated_when: 2021-12-31
---

# debugging

- step 1
- step 2
    + step 2.1
    + step 2.2
      * step 2.2.1
      <file_sep>import React, { useState } from "react";
import styled from 'styled-components';
import { Head, NavMenu, PopMenu } from '../components';
import '../styles/index.css';

const OPTIONS = [
  { bg: '#0062be', img: "http://qiniuargus.weready.online/storybooks/pepsi/pepsi001.png"},
  { bg: '#e60c2c', img: "http://qiniuargus.weready.online/storybooks/pepsi/pepsi002.png"},
  { bg: '#1e1e1e', img: "http://qiniuargus.weready.online/storybooks/pepsi/pepsi003.png"},
];
const SETTING = {
  distanceSide: '6em',
}
const Section = styled.section`
  position: relative;
  min-height: 100vh;

  font-size: 16px;

  display: flex;
  flex-direction: column;
  justify-content: space-between;

  @media screen and (max-width: 500px) {
    font-size: 10px;
  }

`;
const HeaderBar = styled.div`
  padding: 1em ${SETTING.distanceSide};
  display: flex;
  justify-content: space-between;
  align-items: center;
`;
const Jumbotron = styled.div`
  position: relative;
  margin: 0 ${SETTING.distanceSide};

  display: flex;
  justify-content: space-between;
  align-items: center;

  @media screen and (max-width: 500px) {
    width: 100%;
    flex-direction: column-reverse;
    margin: .6em 0;
  }

`;
const Selector = styled.ul`
  list-style-type: none;

  display: flex;
  justify-content: center;

  & li {
    margin: 1em;
    transition: .5s;
  }
  & li:hover {
    transform: translateY(-20%);
  }
  & img {
    height: 6em;
  }
`;

const Logo = styled.div`
  & img {
    width: 5em;
    height: 5em;
  }
`;
const Menu = styled.ul`
`;

const TextArea = styled.div`
  width: 50%;
  color: #fff;

  & h1, h2 {
    text-transform: uppercase;
  }
  & h2 {
    font-size: 3.6em;
    line-height: 1em;
  }
  & h1 {
    font-size: 7.2em;
    line-height: 1em;
  }
  & p {
    margin: 0;
    letter-spacing: .06em;
    line-height: 1.4em;
    text-align: justify;
    text-justify: inter-ideograph;/*IE*/
  }
  @media screen and (max-width: 500px) {
    width: 100%;
    padding: 0 3.6em;
  }
`;
const Image = styled.div`
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  @media screen and (max-width: 500px) {
    width: 100%;
    margin: 3.2em;
  }
`;
const Contact = styled.ul`
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%); */

  list-style: none;

  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  & li {
    padding: 1em 0;
    list-style: none;
    cursor: pointer;
    transition: .5s;
  }
  & li:hover {
    transform: scale(1.1);
  }
  & img {
    filter: invert(1);
  }

  @media screen and (max-width: 500px) {
    display: none;
  }
`;

const navItems = [
  { key: 'home',      url: '/', text: 'Home' },
  { key: 'products',  url: '/#', text: 'Products' },
  { key: 'whatisnew', url: '/#', text: "What's New" },
  { key: 'newsletter',url: '/#', text: 'Newsletter' },
  { key: 'contact',   url: '/#', text: 'Contact' },
];

export default function LandingPage() {
  const [index, setIndex] = useState(0);

  return (
    <>
      <Head context={{ head: '百事可乐' }} />
      <Section style={{ background: OPTIONS[index].bg }}>
        
        <HeaderBar>
          
          <Logo>
            <img src="http://qiniuargus.weready.online/storybooks/pepsi/logo.png" />
          </Logo>

          <Menu>
            <NavMenu items={navItems} color={{ 
              subBg: OPTIONS[index].bg,
              arrow: '#fff',
            }}/>
          </Menu>

        </HeaderBar>
        
        <Jumbotron className="jumbotron">
          
          <TextArea>
            <h2>That's what</h2>
            <h1>I like</h1>
            <p>It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood; who strives valiantly; who errs, who comes short again and again, because there is no effort without error and shortcoming; but who does actually strive to do the deeds; who knows great enthusiasms, the great devotions; who spends himself in a worthy cause; who at the best knows in the end the triumph of high achievement, and who at the worst, if he fails, at least fails while daring greatly, so that his place shall never be with those cold and timid souls who neither know victory nor defeat.</p>
          </TextArea>

          <Image>
            <img src={OPTIONS[index].img} />
          </Image>

        </Jumbotron>
        
        <Selector>
        { OPTIONS.map((op, id) => (
          <li onClick={() => setIndex(id)}><img src={op.img} /></li>
        ))}
        </Selector>

        <Contact>
          <li><img src='http://qiniuargus.weready.online/icons/facebook.png' /></li>
          <li><img src='http://qiniuargus.weready.online/icons/instagram.png'/></li>
          <li><img src='http://qiniuargus.weready.online/icons/twitter.png' /></li>
        </Contact>

        <PopMenu color={{ ft: '#999', bg: OPTIONS[index].bg }}  items={navItems} />

      </Section>

    </>
  )
}
<file_sep>import React from 'react';
import { Helmet } from 'react-helmet';
import { useStaticQuery, graphql } from 'gatsby';

export const Head = ({context}) => {

  const data = useStaticQuery(graphql`
    query {
      site {
        siteMetadata {
          title
        }
      }
    }
  `);
// console.log(999999, data)
// console.log(999999, data.site.siteMetadata.title)

  return(
    <Helmet >
      <title>
      {
        (!context || !context.head) ? data.site.siteMetadata.title :
        `${data.site.siteMetadata.title} | ${context.head}`
      }
      </title>

      { !context?.keywords ? null : <meta name='keywords'            content={context.keywords} /> }
      { !context?.category ? null : <meta property='wr:type'         content={context.category} /> }
      { !context?.title    ? null : <meta property='wr:title'        content={context.title} /> }
      { !context?.subtitle ? null : <meta property='wr:description'  content={context.subtitle} /> }

      {/* { !context?.? null : <meta property='wr:image'       content={context.} /> }
      { !context?.? null : <meta property='wr:locale'      content={context.} /> }
      { !context?.? null : <meta property='wr:url'         content={context.} /> } */}
      {/* <link rel='canonical'           content='' /> */}
    }
    </Helmet>
  )

}
<file_sep>import styled from 'styled-components';
import { THEME } from '../config';

export const Section = styled.div`
  width: 100%;
`;
export const Column = styled.div`
  height: 100%;
`;
export const CenterColumn = styled(Column)`
  margin: 0 auto;
  max-width: ${THEME.size.sectionContainerWidthMax};
`;
<file_sep>import React from "react";
import { graphql, useStaticQuery } from 'gatsby';
import { THEME } from '../config';
import { Section, CenterColumn, NavMenu, PopMenu } from '../components';

export default function HeaderSection() {
  const data = useStaticQuery(graphql`
query {
  site {
    siteMetadata {
      navItems {
        key
        url
        text
        sub {
          key
          url
          text
          sub {
            key
            url
            text
          }
        }
      }
    }
  }
}
  `);

  return (
    <Section style={{background: `linear-gradient(90deg,${THEME.color.primary.border},${THEME.color.primary.ft})` }}>
      <CenterColumn>
        <PopMenu color={{ ft: '#999', bg: THEME.color.primary.border }}  items={data.site.siteMetadata.navItems} />
        <div style={{width: '100%', display: 'flex', justifyContent: 'center'}}>
          <div style={{width: '20rem', color: '#fff'}} >
            <NavMenu items={data.site.siteMetadata.navItems} color={{ 
              subBg: THEME.color.primary.border,
              arrow: '#fff',
            }}/>
          </div>
        </div>
      </CenterColumn>
    </Section>
  )
}
