소스 검색

Initial commit

master
Modal Software 3 년 전
커밋
2f5f30362b
95개의 변경된 파일5669개의 추가작업 그리고 0개의 파일을 삭제
  1. +11
    -0
      .editorconfig
  2. +35
    -0
      .eslintrc.json
  3. +36
    -0
      .gitignore
  4. +8
    -0
      .prettierrc
  5. +2
    -0
      next-env.d.ts
  6. +3
    -0
      next.config.js
  7. +37
    -0
      package.json
  8. BIN
      public/contents/japanese-calligraphy/20101122_Calligraphy_Hirano_Demo.jpg
  9. BIN
      public/contents/japanese-calligraphy/freddie-marriage-gL-7_NtZpYI-unsplash.jpg
  10. BIN
      public/contents/japanese-calligraphy/japanese_calligraphy_at_meiji_shrine_tokyo.jpg
  11. BIN
      public/contents/japanese-calligraphy/marco-zuppone-zHwWnUDMizo-unsplash.jpg
  12. BIN
      public/contents/japanese-calligraphy/niketh-vellanki-vJqSAasmCEY-unsplash.jpg
  13. BIN
      public/contents/japanese-calligraphy/what-is-japanese-calligraphy-used-for-1-1.jpg
  14. BIN
      public/contents/piano/bechstein-moor-grand-00.jpg
  15. BIN
      public/contents/piano/bechstein-moor-grand-01.jpg
  16. BIN
      public/contents/piano/boesendorfer-moor-grand-00.jpg
  17. BIN
      public/contents/piano/boesendorfer-moor-grand-01.jpg
  18. BIN
      public/contents/piano/boesendorfer-moor-grand-02.jpg
  19. BIN
      public/contents/piano/chris-maene-cm228-parlor-grand-00.jpg
  20. BIN
      public/contents/piano/chris-maene-cm250-chamber-concert-grand-00.jpg
  21. BIN
      public/contents/piano/chris-maene-cm284-concert-grand-00.jpg
  22. BIN
      public/contents/piano/grotrian-duo-double-grand.jpg
  23. BIN
      public/contents/piano/grotrian-steinweg-double-grand-00.jpg
  24. BIN
      public/contents/piano/korg-kronos-88-00.jpg
  25. BIN
      public/contents/piano/korg-kronos-88-01.jpg
  26. BIN
      public/contents/piano/kurzweil-forte-00.webp
  27. BIN
      public/contents/piano/nehlsen-omega-double-grand-00.jpg
  28. BIN
      public/contents/piano/pleyel-double-grand-00.jpg
  29. BIN
      public/contents/piano/pleyel-double-grand-01.jpg
  30. BIN
      public/contents/piano/pleyel-double-grand-02.jpg
  31. BIN
      public/contents/piano/pleyel-moor-grand-00.jpg
  32. BIN
      public/contents/piano/pleyel-moor-grand-01.jpg
  33. BIN
      public/contents/piano/pleyel-moor-grand-02.jpg
  34. BIN
      public/contents/piano/pleyel-moor-upright-00.jpg
  35. BIN
      public/contents/piano/roland-fantom-8-00.jpg
  36. BIN
      public/contents/piano/roland-fantom-8-01.jpg
  37. BIN
      public/contents/piano/roland-fantom-8-02.jpg
  38. BIN
      public/contents/piano/steinway-moor-grand-00.jpg
  39. BIN
      public/contents/piano/stuart-and-sons-beleura-concert-grand-00.jpg
  40. BIN
      public/contents/piano/stuart-and-sons-beleura-concert-grand-01.jpg
  41. BIN
      public/contents/piano/stuart-and-sons-beleura-studio-grand-00.jpg
  42. BIN
      public/contents/piano/yamaha-cp88-00.jpg
  43. BIN
      public/contents/piano/yamaha-cp88-01.jpg
  44. BIN
      public/contents/piano/yamaha-cp88-02.jpg
  45. BIN
      public/contents/piano/yamaha-montage-8-00.webp
  46. BIN
      public/contents/ramen/Butter_Corn_Ramen.jpg
  47. BIN
      public/contents/ramen/Tokyoramen.jpg
  48. BIN
      public/contents/ramen/karei.png
  49. BIN
      public/contents/ramen/miso.png
  50. BIN
      public/contents/ramen/sapporo.jpg
  51. BIN
      public/contents/ramen/shio.png
  52. BIN
      public/contents/ramen/shoyu.jpg
  53. BIN
      public/favicon.ico
  54. BIN
      public/fonts/mononoki/mononoki-Bold.eot
  55. BIN
      public/fonts/mononoki/mononoki-Bold.ttf
  56. BIN
      public/fonts/mononoki/mononoki-Bold.woff
  57. BIN
      public/fonts/mononoki/mononoki-Bold.woff2
  58. BIN
      public/fonts/mononoki/mononoki-BoldItalic.eot
  59. BIN
      public/fonts/mononoki/mononoki-BoldItalic.ttf
  60. BIN
      public/fonts/mononoki/mononoki-BoldItalic.woff
  61. BIN
      public/fonts/mononoki/mononoki-BoldItalic.woff2
  62. BIN
      public/fonts/mononoki/mononoki-Italic.eot
  63. BIN
      public/fonts/mononoki/mononoki-Italic.ttf
  64. BIN
      public/fonts/mononoki/mononoki-Italic.woff
  65. BIN
      public/fonts/mononoki/mononoki-Italic.woff2
  66. BIN
      public/fonts/mononoki/mononoki-Regular.eot
  67. BIN
      public/fonts/mononoki/mononoki-Regular.ttf
  68. BIN
      public/fonts/mononoki/mononoki-Regular.woff
  69. BIN
      public/fonts/mononoki/mononoki-Regular.woff2
  70. +77
    -0
      public/global.css
  71. +166
    -0
      public/theme.css
  72. +19
    -0
      public/theme/dark.css
  73. +19
    -0
      public/theme/light.css
  74. +4
    -0
      public/vercel.svg
  75. +39
    -0
      src/components/molecules/Brand/index.tsx
  76. +212
    -0
      src/components/molecules/DummyContent/index.tsx
  77. +22
    -0
      src/components/molecules/Link/index.tsx
  78. +87
    -0
      src/components/templates/BasicLayout/index.tsx
  79. +185
    -0
      src/components/templates/Index/index.tsx
  80. +129
    -0
      src/components/templates/LeftSidebarLayout/index.tsx
  81. +178
    -0
      src/components/templates/LeftSidebarWithMenuLayout/index.tsx
  82. +98
    -0
      src/components/templates/RightSidebarLayout/index.tsx
  83. +12
    -0
      src/pages/_app.tsx
  84. +58
    -0
      src/pages/_document.tsx
  85. +33
    -0
      src/pages/index.tsx
  86. +33
    -0
      src/pages/layouts/basic/index.tsx
  87. +40
    -0
      src/pages/layouts/left-sidebar/index.tsx
  88. +104
    -0
      src/pages/layouts/left-sidebar/with-menu/index.tsx
  89. +33
    -0
      src/pages/layouts/right-sidebar-static/index.tsx
  90. +1
    -0
      src/utilities/popups.ts
  91. +5
    -0
      src/utilities/queryKeys.ts
  92. +21
    -0
      src/utilities/styles/mixins.ts
  93. +3
    -0
      src/utilities/subpages.ts
  94. +30
    -0
      tsconfig.json
  95. +3929
    -0
      yarn.lock

+ 11
- 0
.editorconfig 파일 보기

@@ -0,0 +1,11 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = tab
tab_width = 2
indent_style = tab
insert_final_newline = true
max_line_length = 120
trim_trailing_whitespace = true

+ 35
- 0
.eslintrc.json 파일 보기

@@ -0,0 +1,35 @@
{
"settings": {
"react": {
"version": "detect",
"pragma": "React",
"fragment": "Fragment"
}
},
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"react",
"@typescript-eslint"
],
"rules": {
"react/react-in-jsx-scope": "off",
"react/prop-types": "off"
}
}

+ 36
- 0
.gitignore 파일 보기

@@ -0,0 +1,36 @@
# 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
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel

.idea/

+ 8
- 0
.prettierrc 파일 보기

@@ -0,0 +1,8 @@
{
"jsxSingleQuote": false,
"semi": false,
"jsxBracketSameLine": false,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": false
}

+ 2
- 0
next-env.d.ts 파일 보기

@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />

+ 3
- 0
next.config.js 파일 보기

@@ -0,0 +1,3 @@
module.exports = {
basePath: '',
}

+ 37
- 0
package.json 파일 보기

@@ -0,0 +1,37 @@
{
"name": "starter-next",
"version": "0.1.0",
"private": true,
"homepage": "https://code.modal.sh",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@tesseract-design/react-common": "^0.3.0",
"@theoryofnekomata/viewfinder": "0.2.4",
"next": "10.1.3",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-markdown": "^6.0.1",
"styled-components": "^5.2.3"
},
"devDependencies": {
"@types/node": "^14.14.41",
"@types/react": "^17.0.3",
"@types/styled-components": "^5.1.9",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"eslint": "^7.27.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-app": "^6.2.2",
"prettier": "2.3.0",
"typescript": "^4.2.4"
},
"optionalDependencies": {
"react-markdown": "^6.0.1"
}
}

BIN
public/contents/japanese-calligraphy/20101122_Calligraphy_Hirano_Demo.jpg 파일 보기

Before After
Width: 440  |  Height: 362  |  Size: 156 KiB

BIN
public/contents/japanese-calligraphy/freddie-marriage-gL-7_NtZpYI-unsplash.jpg 파일 보기

Before After
Width: 4896  |  Height: 3264  |  Size: 2.3 MiB

BIN
public/contents/japanese-calligraphy/japanese_calligraphy_at_meiji_shrine_tokyo.jpg 파일 보기

Before After
Width: 600  |  Height: 315  |  Size: 55 KiB

BIN
public/contents/japanese-calligraphy/marco-zuppone-zHwWnUDMizo-unsplash.jpg 파일 보기

Before After
Width: 3888  |  Height: 2592  |  Size: 937 KiB

BIN
public/contents/japanese-calligraphy/niketh-vellanki-vJqSAasmCEY-unsplash.jpg 파일 보기

Before After
Width: 5184  |  Height: 3456  |  Size: 4.5 MiB

BIN
public/contents/japanese-calligraphy/what-is-japanese-calligraphy-used-for-1-1.jpg 파일 보기

Before After
Width: 700  |  Height: 450  |  Size: 51 KiB

BIN
public/contents/piano/bechstein-moor-grand-00.jpg 파일 보기

Before After
Width: 1600  |  Height: 1200  |  Size: 385 KiB

BIN
public/contents/piano/bechstein-moor-grand-01.jpg 파일 보기

Before After
Width: 336  |  Height: 381  |  Size: 66 KiB

BIN
public/contents/piano/boesendorfer-moor-grand-00.jpg 파일 보기

Before After
Width: 1536  |  Height: 1024  |  Size: 353 KiB

BIN
public/contents/piano/boesendorfer-moor-grand-01.jpg 파일 보기

Before After
Width: 300  |  Height: 400  |  Size: 27 KiB

BIN
public/contents/piano/boesendorfer-moor-grand-02.jpg 파일 보기

Before After
Width: 1500  |  Height: 1500  |  Size: 421 KiB

BIN
public/contents/piano/chris-maene-cm228-parlor-grand-00.jpg 파일 보기

Before After
Width: 650  |  Height: 886  |  Size: 78 KiB

BIN
public/contents/piano/chris-maene-cm250-chamber-concert-grand-00.jpg 파일 보기

Before After
Width: 650  |  Height: 975  |  Size: 73 KiB

BIN
public/contents/piano/chris-maene-cm284-concert-grand-00.jpg 파일 보기

Before After
Width: 650  |  Height: 1026  |  Size: 80 KiB

BIN
public/contents/piano/grotrian-duo-double-grand.jpg 파일 보기

Before After
Width: 582  |  Height: 540  |  Size: 91 KiB

BIN
public/contents/piano/grotrian-steinweg-double-grand-00.jpg 파일 보기

Before After
Width: 1200  |  Height: 1600  |  Size: 1.1 MiB

BIN
public/contents/piano/korg-kronos-88-00.jpg 파일 보기

Before After
Width: 1200  |  Height: 300  |  Size: 56 KiB

BIN
public/contents/piano/korg-kronos-88-01.jpg 파일 보기

Before After
Width: 1200  |  Height: 300  |  Size: 93 KiB

BIN
public/contents/piano/kurzweil-forte-00.webp 파일 보기

Before After

BIN
public/contents/piano/nehlsen-omega-double-grand-00.jpg 파일 보기

Before After
Width: 1320  |  Height: 990  |  Size: 157 KiB

BIN
public/contents/piano/pleyel-double-grand-00.jpg 파일 보기

Before After
Width: 604  |  Height: 402  |  Size: 43 KiB

BIN
public/contents/piano/pleyel-double-grand-01.jpg 파일 보기

Before After
Width: 1600  |  Height: 1362  |  Size: 192 KiB

BIN
public/contents/piano/pleyel-double-grand-02.jpg 파일 보기

Before After
Width: 2592  |  Height: 1944  |  Size: 452 KiB

BIN
public/contents/piano/pleyel-moor-grand-00.jpg 파일 보기

Before After
Width: 1000  |  Height: 750  |  Size: 100 KiB

BIN
public/contents/piano/pleyel-moor-grand-01.jpg 파일 보기

Before After
Width: 4752  |  Height: 3168  |  Size: 4.8 MiB

BIN
public/contents/piano/pleyel-moor-grand-02.jpg 파일 보기

Before After
Width: 2178  |  Height: 2631  |  Size: 3.0 MiB

BIN
public/contents/piano/pleyel-moor-upright-00.jpg 파일 보기

Before After
Width: 680  |  Height: 634  |  Size: 196 KiB

BIN
public/contents/piano/roland-fantom-8-00.jpg 파일 보기

Before After
Width: 2397  |  Height: 807  |  Size: 317 KiB

BIN
public/contents/piano/roland-fantom-8-01.jpg 파일 보기

Before After
Width: 1680  |  Height: 519  |  Size: 147 KiB

BIN
public/contents/piano/roland-fantom-8-02.jpg 파일 보기

Before After
Width: 1680  |  Height: 178  |  Size: 62 KiB

BIN
public/contents/piano/steinway-moor-grand-00.jpg 파일 보기

Before After
Width: 5312  |  Height: 2988  |  Size: 1.4 MiB

BIN
public/contents/piano/stuart-and-sons-beleura-concert-grand-00.jpg 파일 보기

Before After
Width: 533  |  Height: 800  |  Size: 80 KiB

BIN
public/contents/piano/stuart-and-sons-beleura-concert-grand-01.jpg 파일 보기

Before After
Width: 1250  |  Height: 834  |  Size: 219 KiB

BIN
public/contents/piano/stuart-and-sons-beleura-studio-grand-00.jpg 파일 보기

Before After
Width: 1250  |  Height: 911  |  Size: 332 KiB

BIN
public/contents/piano/yamaha-cp88-00.jpg 파일 보기

Before After
Width: 7745  |  Height: 1313  |  Size: 911 KiB

BIN
public/contents/piano/yamaha-cp88-01.jpg 파일 보기

Before After
Width: 7383  |  Height: 1849  |  Size: 1.3 MiB

BIN
public/contents/piano/yamaha-cp88-02.jpg 파일 보기

Before After
Width: 7778  |  Height: 2582  |  Size: 1.9 MiB

BIN
public/contents/piano/yamaha-montage-8-00.webp 파일 보기

Before After

BIN
public/contents/ramen/Butter_Corn_Ramen.jpg 파일 보기

Before After
Width: 3072  |  Height: 2304  |  Size: 1.6 MiB

BIN
public/contents/ramen/Tokyoramen.jpg 파일 보기

Before After
Width: 1218  |  Height: 1236  |  Size: 139 KiB

BIN
public/contents/ramen/karei.png 파일 보기

Before After
Width: 2400  |  Height: 1800  |  Size: 9.0 MiB

BIN
public/contents/ramen/miso.png 파일 보기

Before After
Width: 1224  |  Height: 1632  |  Size: 3.7 MiB

BIN
public/contents/ramen/sapporo.jpg 파일 보기

Before After
Width: 4875  |  Height: 3250  |  Size: 9.2 MiB

BIN
public/contents/ramen/shio.png 파일 보기

Before After
Width: 980  |  Height: 726  |  Size: 1.3 MiB

BIN
public/contents/ramen/shoyu.jpg 파일 보기

Before After
Width: 5472  |  Height: 3648  |  Size: 5.6 MiB

BIN
public/favicon.ico 파일 보기

Before After

BIN
public/fonts/mononoki/mononoki-Bold.eot 파일 보기


BIN
public/fonts/mononoki/mononoki-Bold.ttf 파일 보기


BIN
public/fonts/mononoki/mononoki-Bold.woff 파일 보기


BIN
public/fonts/mononoki/mononoki-Bold.woff2 파일 보기


BIN
public/fonts/mononoki/mononoki-BoldItalic.eot 파일 보기


BIN
public/fonts/mononoki/mononoki-BoldItalic.ttf 파일 보기


BIN
public/fonts/mononoki/mononoki-BoldItalic.woff 파일 보기


BIN
public/fonts/mononoki/mononoki-BoldItalic.woff2 파일 보기


BIN
public/fonts/mononoki/mononoki-Italic.eot 파일 보기


BIN
public/fonts/mononoki/mononoki-Italic.ttf 파일 보기


BIN
public/fonts/mononoki/mononoki-Italic.woff 파일 보기


BIN
public/fonts/mononoki/mononoki-Italic.woff2 파일 보기


BIN
public/fonts/mononoki/mononoki-Regular.eot 파일 보기


BIN
public/fonts/mononoki/mononoki-Regular.ttf 파일 보기


BIN
public/fonts/mononoki/mononoki-Regular.woff 파일 보기


BIN
public/fonts/mononoki/mononoki-Regular.woff2 파일 보기


+ 77
- 0
public/global.css 파일 보기

@@ -0,0 +1,77 @@
body {
margin: 0;
/* overflow: overlay; */
}

h1 {
font-size: 3em;
text-transform: lowercase;
}

h2 {
font-size: 2em;
text-transform: lowercase;
}

h3 {
font-size: 1.75em;
text-transform: lowercase;
}

h4 {
font-size: 1.5em;
text-transform: lowercase;
}

h5 {
font-size: 1.25em;
text-transform: lowercase;
}

h6 {
font-size: 1.125em;
text-transform: lowercase;
}

p {
margin: 2em 0;
}

li {
margin: 2em 0;
}

small {
font-size: 0.75em;
}

a:focus {
outline: 0;
}

pre {
overflow: auto;
margin: 0 -1rem;
padding: 0 1rem;
line-height: 1.2;
box-sizing: border-box;
}

@media only print {
pre, pre * {
color: inherit !important;
}

code, code * {
color: inherit !important;
}

img {
filter: grayscale(100%);
}

:root {
--color-accent: black !important;
--color-active: black !important;
}
}

+ 166
- 0
public/theme.css 파일 보기

@@ -0,0 +1,166 @@
@font-face {
font-family: 'mononoki';
font-weight: 400;
font-style: normal;
font-display: swap;
src:
local('mononoki'),
url(fonts/mononoki/mononoki-Regular.woff2) format('woff2');
}

@font-face {
font-family: 'mononoki';
font-weight: 700;
font-style: normal;
font-display: swap;
src:
local('mononoki Bold'),
local('mononoki'),
url(fonts/mononoki/mononoki-Bold.woff2) format('woff2');
}

@font-face {
font-family: 'mononoki';
font-weight: 400;
font-style: italic;
font-display: swap;
src:
local('mononoki Italic'),
local('mononoki'),
url(fonts/mononoki/mononoki-Italic.woff2) format('woff2');
}

@font-face {
font-family: 'mononoki';
font-weight: 700;
font-style: italic;
font-display: swap;
src:
local('mononoki Bold Italic'),
local('mononoki BoldItalic'),
local('mononoki'),
url(fonts/mononoki/mononoki-BoldItalic.woff2) format('woff2');
}

:root {
--font-family-base: 'Encode Sans', system-ui;
--font-stretch-base: semi-expanded;
--font-weight-base: 400;
--line-height-base: 1.75em;
--font-family-headings: 'Encode Sans', system-ui;
--font-stretch-headings: condensed;
--font-weight-headings: 100;
--line-height-headings: 1.125em;
--font-family-monospace: 'mononoki';
--font-size-root: 16px;
--opacity-light: 0.25;
--opacity-lighter: 0.5;
--opacity-lightest: 0.75;
}

:root {
--color-bg: var(--color-negative, white);
--color-fg: var(--color-positive, black);
--color-accent: var(--color-primary, blue);
--color-active: var(--color-secondary, red);
}

@media (prefers-color-scheme: dark) {
:root {
--color-bg: var(--color-negative, black);
--color-fg: var(--color-positive, white);
}
}

:root {
font-size: var(--font-size-root);
font-family: var(--font-family-base), sans-serif;
font-stretch: var(--font-stretch-base, normal);
font-weight: var(--font-weight-base, 400);
line-height: var(--line-height-base, 1.75em);
transition-property: color, background-color;
transition-timing-function: ease;
transition-duration: 350ms;
}

@media only screen {
:root {
background-color: var(--color-bg);
color: var(--color-fg);
}
}

h1 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h2 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: calc(var(--font-weight-headings, 400) / 100 * 150);
line-height: var(--line-height-headings, 1.5);
}

h3 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: calc(var(--font-weight-headings, 400) / 100 * 250);
line-height: var(--line-height-headings, 1.5);
}

h4 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h5 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

h6 {
font-family: var(--font-family-headings), sans-serif;
font-stretch: var(--font-stretch-headings, normal);
font-weight: var(--font-weight-headings, 400);
line-height: var(--line-height-headings, 1.5);
}

code {
font-family: var(--font-family-monospace), monospace;
}

pre {
font-family: var(--font-family-monospace), monospace;
}

a {
color: inherit;
text-decoration: none;
}

@media only screen {
a {
color: var(--color-accent);
text-decoration: underline;
}

a:focus {
color: var(--color-active);
}
}

::selection {
background-color: var(--color-active);
color: var(--color-fg);
}

:root {
caret-color: var(--color-active);
}

+ 19
- 0
public/theme/dark.css 파일 보기

@@ -0,0 +1,19 @@
:root {
--color-shade: #000;
--color-negative: #222;
--color-positive: #eee;
--color-primary: #C78AB3;
--color-secondary: #f90;
--color-code-number: #74f95e;
--color-code-keyword: #ff4389;
--color-code-type: #5097D2;
--color-code-instance-attribute: #76a7d2;
--color-code-function: #67c252;
--color-code-parameter: #915ec2;
--color-code-property: #ffa1c9;
--color-code-string: #eed371;
--color-code-variable: #8bc275;
--color-code-regexp: #74A72B;
--color-code-url: #0099CC;
--color-code-global: #C28050;
}

+ 19
- 0
public/theme/light.css 파일 보기

@@ -0,0 +1,19 @@
:root {
--color-shade: #fff;
--color-negative: #f8f8f8;
--color-positive: #333;
--color-primary: #ba6a9c;
--color-secondary: #f90;
--color-code-number: #72b507;
--color-code-keyword: #ee5189;
--color-code-type: #427fb1;
--color-code-instance-attribute: #76a7d2;
--color-code-function: #5a984a;
--color-code-parameter: #915ec2;
--color-code-property: #b76e8d;
--color-code-string: #b59e36;
--color-code-variable: #61864e;
--color-code-regexp: #4f7e03;
--color-code-url: #0099CC;
--color-code-global: #C28050;
}

+ 4
- 0
public/vercel.svg 파일 보기

@@ -0,0 +1,4 @@
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
</svg>

+ 39
- 0
src/components/molecules/Brand/index.tsx 파일 보기

@@ -0,0 +1,39 @@
import * as React from 'react'
import styled from 'styled-components'
import Link from '../Link'

const BrandBase = styled(Link)({
display: 'block',
textDecoration: 'none',
fontSize: '1.5rem',
fontWeight: 'bold',
fontStretch: '75%',
textTransform: 'uppercase',
width: '2rem',
textAlign: 'center',
'@media (min-width: 720px)': {
width: '8rem',
textAlign: 'left',
},
})

const Hide = styled('span')({
display: 'none',
'@media (min-width: 720px)': {
display: 'inline',
},
})

const Brand: React.FC = () => {
return (
<BrandBase
href={{
pathname: '/',
}}
>
B<Hide>rand</Hide>
</BrandBase>
)
}

export default Brand

+ 212
- 0
src/components/molecules/DummyContent/index.tsx 파일 보기

@@ -0,0 +1,212 @@
/* eslint-disable */
import ReactMarkdown from 'react-markdown'

const DEFAULT_CONTENTS = [
{
name: 'ramen',
images: [
'Butter_Corn_Ramen.jpg',
'karei.png',
'miso.png',
'sapporo.jpg',
'shio.png',
'shoyu.jpg',
'Tokyoramen.jpg',
],
text: `# Ramen

Ramen is a Japanese noodle soup. It consists of Chinese wheat noodles served in a meat or (occasionally) fish-based broth, often flavored with soy sauce or miso, and uses toppings such as sliced pork (叉焼, chāshū), nori (dried seaweed), menma, and scallions. Nearly every region in Japan has its own variation of ramen, such as the tonkotsu (pork bone broth) ramen of Kyushu and the miso ramen of Hokkaido. Mazemen is a ramen dish that is not served in a soup, but rather with a sauce (such as tare), like noodles that are served with a sweet and sour sauce.

## Types

A wide variety of ramen exists in Japan, with geographical and vendor-specific differences even in varieties that share the same name. Ramen can be broadly categorized by its two main ingredients: noodles and broth.

### Noodles

Most noodles are made from four basic ingredients: wheat flour, salt, water, and kansui (かん水) (from kansui (鹼水, alkaline water)) a type of alkaline mineral water, containing sodium carbonate and usually potassium carbonate, as well as sometimes a small amount of phosphoric acid. Although ramen noodles and Udon noodles are both made with wheat, they are different kinds of noodle.

The kansui is the distinguishing ingredient in ramen noodles, and originated in Inner Mongolia, where some lakes contain large amounts of these minerals and whose water is said to be perfect for making these noodles. Making noodles with kansui lends them a yellowish hue as well as a firm texture.[citation needed] Eggs may also be substituted for kansui. Some noodles are made with neither eggs nor kansui and should only be used for yakisoba, as they have a weaker structure and are more prone to soaking up moisture and becoming extremely soft when served in soup.[citation needed]

Ramen comes in various shapes and lengths. It may be thick, thin, or even ribbon-like, as well as straight or wrinkled.

Traditionally, ramen noodles were made by hand, but with growing popularity many ramen restaurants prefer to have in-house capacity to produce fresh noodles to meet the increased demand and improve quality. Automatic ramen-making machines imitating manual production methods have been available since the mid. 20th century produced by such Japanese manufacturers as Yamato MFG. and others.

### Soup

Ramen soup is generally made from stock based on chicken or pork, combined with a variety of ingredients such as kombu (kelp), katsuobushi (skipjack tuna flakes), niboshi (dried baby sardines), beef bones, pork bones, shiitake, and onions. Some modern ramen broths can also be vegetable-based. Tare is often added to broth to make the soup.

Tonkotsu (豚骨, "pork bone"; not to be confused with tonkatsu) soup is broth with a typically translucent white colored appearance. It is similar to the Chinese baitang (白湯) and has a thick broth made from boiling pork bones, fat, and collagen over high heat for many hours, which suffuses the broth with a hearty pork flavor and a creamy consistency that rivals milk, melted butter or gravy (depending on the shop). Although Tonkotsu is merely a kind of broth, some people consider tonkotsu ramen (specialty of Kyushu, its birthplace) a distinct flavor category.

### Flavors

The resulting combination is generally divided into several categories. (although new and original variations often make this categorization less clear-cut) A description of said old variations are as follows:

- Shōyu (醤油, "soy sauce") ramen has a clear brown broth, based on a chicken and vegetable (or sometimes fish or beef) stock with plenty of soy sauce added resulting in a soup that is tangy, salty, and savory yet still fairly light on the palate. Shōyu ramen usually has curly noodles rather than straight ones, but this is not always the case. It is often adorned with marinated bamboo shoots or menma, green onions, ninjin (carrot), kamaboko (fish cakes), nori (seaweed), boiled eggs, bean sprouts or black pepper; occasionally the soup will also contain chili oil or Chinese spices, and some shops serve sliced beef instead of the usual chāshū.
- Shio (塩,"salt") ramen is the oldest of the four types. It has a pale, clear, yellowish broth made with plenty of salt and any combination of chicken, vegetables, fish, and seaweed. Occasionally pork bones are also used, but they are not boiled as long as they are for tonkotsu ramen, so the soup remains light and clear. Chāshū is sometimes swapped for lean chicken meatballs, and pickled plums and kamaboko (a slice of processed fish roll sometimes served as a frilly white circle with a pink or red spiral called narutomaki) are popular toppings as well. Noodle texture and thickness varies among shio ramen, but they are usually straight rather than curly. "Hakodate Ramen" is the representative of shio❨salt❩ ramen in Japan.
- Miso (味噌) ramen is a relative newcomer, having reached national prominence around 1965. This uniquely Japanese ramen, which was developed in Sapporo Hokkaido, features a broth that combines copious miso and is blended with oily chicken or fish broth – and sometimes with tonkotsu or lard – to create a thick, nutty, slightly sweet and very hearty soup. Miso ramen broth tends to have a robust, tangy flavor, so it stands up to a variety of flavorful toppings: spicy bean paste or tōbanjan (豆瓣醤), butter and corn, leeks, onions, bean sprouts, ground pork, cabbage, sesame seeds, white pepper, and chopped garlic are common. The noodles are typically thick, curly, and slightly chewy.
- Karē (カレー,"curry") ramen, ramen cooked with curry soup, is thought that was born spontaneously relatively recently in Japan. In Japan, several cities claim to be its place of origin. The city of Muroran claims it originated there in 1965 (see also Muroran curry ramen), while the city of Sanjō city claims to have had kare ramen for over 80 years, and the city of Katori also claims to have been the site of its origin. Curry soup is mainly made with pork bones and vegetables and is seasoned with curry. The noodles are thick and curly. Toppings include chāshū, wakame, and bean sprouts.

### Toppings

After basic preparation, ramen can be seasoned and flavored with any number of toppings, including but not limited to:

- Chāshū (sliced barbecued or braised pork)
- Negi (green onion)
- Takana-zuke (Pickled and seasoned mustard leaves)
- Seasoned (usually salted) boiled egg (Soy egg ("Ajitsuke Tamago"))
- Bean or other sprouts
- Menma (lactate-fermented bamboo shoots)
- Kakuni (braised pork cubes or squares)
- Kikurage (wood ear mushroom)
- Nori (dried seaweed)
- Kamaboko (formed fish paste, often in a pink and white spiral called narutomaki)
- Squid
- Umeboshi (pickled plum)
- Corn
- Butter
- Wakame (a type of seaweed)
- Olive oil
- Sesame oil
- Soy sauce
- Other types of vegetables

### Preference

Seasonings commonly added to ramen are white pepper, black pepper, butter, chili pepper, sesame seeds, and crushed garlic. Soup recipes and methods of preparation tend to be closely guarded secrets.

Most tonkotsu ramen restaurants offer a system known as kae-dama (替え玉), where customers who have finished their noodles can request a "refill" (for a few hundred yen more) to be put into their remaining soup.
`,
},
{
name: 'japanese-calligraphy',
images: [
'20101122_Calligraphy_Hirano_Demo.jpg',
'freddie-marriage-gL-7_NtZpYI-unsplash.jpg',
'japanese_calligraphy_at_meiji_shrine_tokyo.jpg',
'marco-zuppone-zHwWnUDMizo-unsplash.jpg',
'niketh-vellanki-vJqSAasmCEY-unsplash.jpg',
'what-is-japanese-calligraphy-used-for-1-1.jpg',
],
text: `# Japanese calligraphy

Japanese calligraphy (書道, shodō) also called shūji (習字) is a form of calligraphy, or artistic writing, of the Japanese language. For a long time, the most esteemed calligrapher in Japan had been Wang Xizhi, a Chinese calligrapher from the 4th century, but after the invention of Hiragana and Katakana, the Japanese unique syllabaries, the distinctive Japanese writing system developed and calligraphers produced styles intrinsic to Japan. The term shodō (書道, "way of writing") is of Chinese origin as it is widely used to describe the art of Chinese calligraphy during the medieval Tang dynasty.

## Styles

Early Japanese calligraphy was originated from Chinese calligraphy. Many of its principles and techniques are very similar, and it recognizes the same basic writing styles:

- seal script (篆書 tensho) (pinyin: zhuànshū). The Seal Script (tensho) was commonly used throughout the Zhou Dynasty (1046-256 BC) and the following Qin Dynasty (221- 206 BC) of China. After this time period, tens style fell out of popularity in favor of reishi. However, tensho was still used for titles of published works or inscriptions. The clear and bold style of tensho made it work well for titles and this tradition of using tensho only for titles is still around today. By the time Chinese characters and calligraphy migrated over to Japan, tensho was already only used for titles and as a result, was never commonly used in Japan. In 57 AD, the Chinese emperor, Guang Wu presented a golden seal to a king of a small region near what is now known as Fukuoka Prefecture. While this seal was not made in Japan, it is believed to be the first instance of tensho in Japan. The first work in Japan that actually utilized tensho was during the Nara period (646-794) was a six-paneled screen called the Torige Tensho Byobu. Each panel is divided into two columns and each column has eight characters. The screen speaks to a ruler and recommends that he use the counsel of wise ministers in order to rule justly.
- clerical script (隷書 reisho) (pinyin: lìshū) The Clerical Script or Scribe's Script (reisho) is a very bold and commanding style of Chinese calligraphy, each of the strokes are greatly exaggerated at the beginning and end. It was most commonly used during the Han Dynasty (206 BC- 220 AD) and the term reisho had many significant meanings but is now only known as one of the five styles of Chinese and Japanese calligraphy. Because of its bold style, the reisho technique is now reserved for large text applications such as plaques, signboards, titles of works, etc. This was its main purpose in Japan as well until the Edo Period (1603-1868) when it was regarded as a calligraphic art form.
- regular script (楷書 kaisho) (pinyin: kǎishū) The Regular Script or Block Script (kaisho) is fairly similar in function to that of Roman block capitals. While Japanese kaisho varies slightly from Chinese kaisho, it is primarily based on Chinese kaisho script in both form and function. The Japanese kaisho style was heavily influenced by the Sui Dynasty (581-618) and the following Tang Dynasty (618-907). Early examples of this style in Japan are mostly various statue and temple inscriptions. This was during the early Heian Period (794-1185) and as time progressed there was a movement in Japan to become more culturally independent and a version of kaisho developed that became uniquely Japanese and included a little bit of the gyosho style. As its influence spread, the primary use of the kaisho technique was to copy the Lotus Sutra. There was a second wave of influence during the Kamakura (1192-1333) and Muromachi (1338-1573) periods, but this was mostly by Zen monks who used a technique based on Zen insight and is different from the classic kaisho technique.
- semi-cursive (行書 gyōsho) (pinyin: xíngshū) The Semi-cursive Script (gyosho) means exactly what it says; this script style is a slightly more cursive version of kaisho script. This script was practiced at the same time as the reisho script. There are three different levels of "cursiveness" called seigyo, gyo, and gyoso. The style of gyosho utilizes a softer and more rounded technique, staying away from sharp corners and angles. In Japan many works were made using the gyosho technique during the early Heian Period. Later in the Heian Period, once Japan began to separate itself from China a Japanese version called wayo began to emerge. The Japanese version of gyosho became widely popular and became the basis of many schools of calligraphy. This was a result of gyosho meshing very well with both kanji and hiragana and writing with this technique was both natural and fluid.
- cursive (草書 sōsho) (pinyin: cǎoshū). The Cursive Script (sosho) has its origins in the Han Dynasty. It was used by scribes as a cursive version of reisho for taking notes. Early examples of sosho include inscriptions on bamboo and other wooden strips. This technique can be easily recognized by many strokes ending with a sweep to the upper right in a breaking-wave type form. As the Han Dynasty came to an end, another version of sosho was developed, but this version was written slowly as opposed to the faster sosho that was popular until then. The exact date when sosho was introduced is unclear. Several texts from Japan shared many sosho-like techniques with Chinese texts during this time but it was not until Kukai, a famous Japanese buddhist monk and scholar traveled to China during the early Heian Period and brought back copies of texts that he made written in the sosho style.

## Tools

A number of tools are used to create a work of modern calligraphy.

The four most basic tools were collectively called the Four Treasures of the Study (文房四宝, bunbō shihō).

- A brush (筆, fude)
- An inkstick (墨, sumi).The hardened mixture of vegetable or pine soot and glue in the shape of a stick. The best inksticks are between 50 and 100 years old.
- Mulberry paper (和紙, washi)
- An inkstone (硯, suzuri) to grind the inkstick against, mixed with water.

Other tools include:

- A paper weight (文鎮, bunchin) to hold the paper in place
- A cloth (下敷き, shitajiki) to place under the paper (often newsprint is used as well) to prevent ink from bleeding through.
- A seal (印, in). The art of engraving a seal is called "tenkoku" 篆刻. The student is encouraged to engrave his own seal. The position of the seal or seals is based on aesthetic preferences. One is not allowed to put a seal on calligraphy of a sutra.

During preparation, water is poured into the inkstone and the inkstick is ground against it, mixing the water with the dried ink to liquefy it. As this is a time-consuming process, modern-day beginners frequently use bottled liquid ink called Bokuju (墨汁, bokujū) . More advanced students are encouraged to grind their own ink. Paper is usually placed on a desk, while a large piece of paper may be placed on the floor or even on the ground (for a performance).

The brushes come in various shapes and sizes, and are usually made using animal hair bristles. Typical animal hair may come from goats, sheep, or horses. The handle may be made from wood, bamboo, plastic or other materials.
`,
},
{
name: 'piano',
text: `# Piano

The piano is an acoustic, stringed musical instrument invented in Italy by Bartolomeo Cristofori around the year 1700 (the exact year is uncertain), in which the strings are struck by wooden hammers that are coated with a softer material (modern hammers are covered with dense wool felt; some early pianos used leather). It is played using a keyboard, which is a row of keys (small levers) that the performer presses down or strikes with the fingers and thumbs of both hands to cause the hammers to strike the strings.

The word piano is a shortened form of pianoforte, the Italian term for the early 1700s versions of the instrument, which in turn derives from gravicembalo col piano e forte (key cymbal with quieter and louder) and fortepiano. The Italian musical terms piano and forte indicate "soft" and "loud" respectively, in this context referring to the variations in volume (i.e., loudness) produced in response to a pianist's touch or pressure on the keys: the greater the velocity of a key press, the greater the force of the hammer hitting the strings, and the louder the sound of the note produced and the stronger the attack. The name was created as a contrast to harpsichord, a musical instrument that does not allow variation in volume; compared to the harpsichord, the first fortepianos in the 1700s had a quieter sound and smaller dynamic range.

A piano usually has a protective wooden case surrounding the soundboard and metal strings, which are strung under great tension on a heavy metal frame. Pressing one or more keys on the piano's keyboard causes a wooden or plastic hammer (typically padded with firm felt) to strike the strings. The hammer rebounds from the strings, and the strings continue to vibrate at their resonant frequency. These vibrations are transmitted through a bridge to a soundboard that amplifies by more efficiently coupling the acoustic energy to the air. When the key is released, a damper stops the strings' vibration, ending the sound. Notes can be sustained, even when the keys are released by the fingers and thumbs, by the use of pedals at the base of the instrument. The sustain pedal enables pianists to play musical passages that would otherwise be impossible, such as sounding a 10-note chord in the lower register and then, while this chord is being continued with the sustain pedal, shifting both hands to the treble range to play a melody and arpeggios over the top of this sustained chord. Unlike the pipe organ and harpsichord, two major keyboard instruments widely used before the piano, the piano allows gradations of volume and tone according to how forcefully or softly a performer presses or strikes the keys.

Most modern pianos have a row of 88 black and white keys, 52 white keys for the notes of the C major scale (C, D, E, F, G, A and B) and 36 shorter black keys, which are raised above the white keys, and set further back on the keyboard. This means that the piano can play 88 different pitches (or "notes"), going from the deepest bass range to the highest treble. The black keys are for the "accidentals" (F♯/G♭, G♯/A♭, A♯/B♭, C♯/D♭, and D♯/E♭), which are needed to play in all twelve keys. More rarely, some pianos have additional keys (which require additional strings), an example of which is the Bösendorfer Concert Grand 290 Imperial, which has 97 keys. Most notes have three strings, except for the bass, which graduates from one to two. The strings are sounded when keys are pressed or struck, and silenced by dampers when the hands are lifted from the keyboard. Although an acoustic piano has strings, it is usually classified as a percussion instrument rather than as a stringed instrument, because the strings are struck rather than plucked (as with a harpsichord or spinet); in the Hornbostel–Sachs system of instrument classification, pianos are considered chordophones. There are two main types of piano: the grand piano and the upright piano. The grand piano has a better sound and gives the player a more precise control of the keys, and is therefore the preferred choice for every situation in which the available floor-space and the budget will allow, as well as often being considered a requirement in venues where skilled pianists will frequently give public performances. The upright piano, which necessarily involves some compromise in both tone and key action compared to a grand piano of equivalent quality, is nevertheless much more widely used, because it occupies less space (allowing it to fit comfortably in a room where a grand piano would be too large) and is significantly less expensive.

During the 1800s, influenced by the musical trends of the Romantic music era, innovations such as the cast iron frame (which allowed much greater string tensions) and aliquot stringing gave grand pianos a more powerful sound, with a longer sustain and richer tone. In the nineteenth century, a family's piano played the same role that a radio or phonograph played in the twentieth century; when a nineteenth-century family wanted to hear a newly published musical piece or symphony, they could hear it by having a family member play a simplified version on the piano. During the nineteenth century, music publishers produced many types of musical works (symphonies, opera overtures, waltzes, etc.) in arrangements for piano, so that music lovers could play and hear the popular pieces of the day in their home. The piano is widely employed in classical, jazz, traditional and popular music for solo and ensemble performances, accompaniment, and for composing, songwriting and rehearsals. Although the piano is very heavy and thus not portable and is expensive (in comparison with other widely used accompaniment instruments, such as the acoustic guitar), its musical versatility (i.e., its wide pitch range, ability to play chords, louder or softer notes and two or more independent musical lines at the same time), the large number of musicians - both amateurs and professionals - trained in playing it, and its wide availability in performance venues, schools and rehearsal spaces have made it one of the Western world's most familiar musical instruments.`,
images: [
'bechstein-moor-grand-00.jpg',
'bechstein-moor-grand-01.jpg',
'boesendorfer-moor-grand-00.jpg',
'boesendorfer-moor-grand-01.jpg',
'boesendorfer-moor-grand-02.jpg',
'chris-maene-cm228-parlor-grand-00.jpg',
'chris-maene-cm250-chamber-concert-grand-00.jpg',
'chris-maene-cm284-concert-grand-00.jpg',
'grotrian-duo-double-grand.jpg',
'grotrian-steinweg-double-grand-00.jpg',
'korg-kronos-88-00.jpg',
'korg-kronos-88-01.jpg',
'kurzweil-forte-00.webp',
'nehlsen-omega-double-grand-00.jpg',
'pleyel-double-grand-00.jpg',
'pleyel-double-grand-01.jpg',
'pleyel-double-grand-02.jpg',
'pleyel-moor-grand-00.jpg',
'pleyel-moor-grand-01.jpg',
'pleyel-moor-grand-02.jpg',
'pleyel-moor-upright-00.jpg',
'roland-fantom-8-00.jpg',
'roland-fantom-8-01.jpg',
'roland-fantom-8-02.jpg',
'steinway-moor-grand-00.jpg',
'stuart-and-sons-beleura-concert-grand-00.jpg',
'stuart-and-sons-beleura-concert-grand-01.jpg',
'stuart-and-sons-beleura-studio-grand-00.jpg',
'yamaha-cp88-00.jpg',
'yamaha-cp88-01.jpg',
'yamaha-cp88-02.jpg',
'yamaha-montage-8-00.webp',
],
},
]

const DummyContent = ({contents = DEFAULT_CONTENTS}) => {
const content = contents[Math.floor(Math.random() * contents.length)]

return (
<ReactMarkdown
components={{
p: ({node, ...etcProps}) => {
if (!(Array.isArray(content.images) && content.images.length > 0)) {
return <p {...etcProps} />
}
const shouldHaveImage = Math.floor(Math.random() * 2) === 1
if (shouldHaveImage) {
const randomImage = Math.floor(Math.random() * content.images.length)
return (
<>
<img
src={`/contents/${content.name}/${content.images[randomImage]}`}
alt={content.name}
style={{
width: '100%',
display: 'block',
}}
/>
<p {...etcProps} />
</>
)
}
return <p {...etcProps} />
},
}}
>
{content.text}
</ReactMarkdown>
)
}

export default DummyContent

+ 22
- 0
src/components/molecules/Link/index.tsx 파일 보기

@@ -0,0 +1,22 @@
import * as React from 'react'
import NextLink from 'next/link'
import {UrlObject} from 'url'

type Props = {
href: UrlObject
as?: UrlObject
prefetch?: boolean
replace?: boolean
shallow?: boolean
component?: React.ElementType
}

const Link: React.FC<Props> = ({href, as, prefetch, replace, shallow, component: Component = 'a', ...etcProps}) => {
return (
<NextLink href={href} as={as} passHref replace={replace} shallow={shallow} prefetch={prefetch}>
<Component {...etcProps} />
</NextLink>
)
}

export default Link

+ 87
- 0
src/components/templates/BasicLayout/index.tsx 파일 보기

@@ -0,0 +1,87 @@
import * as React from 'react'
import styled from 'styled-components'
import * as T from '@tesseract-design/react-common'
import {Basic} from '@theoryofnekomata/viewfinder'
import Link from '../../molecules/Link'
import DummyContent from '../../molecules/DummyContent'
import Brand from '../../molecules/Brand'

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::before': {
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
'::after': {
backgroundColor: 'black',
opacity: 0.5,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

type Props = {
query: string
userLinkLabel: string
searchQueryKey: string
searchLabel: string
searchHint: string
popupQueryKey: string
userPopupQueryValue: string
}

const BasicLayoutTemplate: React.FC<Props> = ({
query,
userLinkLabel,
searchQueryKey,
searchLabel,
searchHint,
popupQueryKey,
userPopupQueryValue,
}) => {
return (
<Basic.Layout
topBarComponent={TopBarComponent}
brand={<Brand />}
topBarCenter={
<form>
<T.TextInput
name={searchQueryKey}
label={searchLabel}
hint={searchHint}
defaultValue={query}
border
alternate
/>
</form>
}
userLink={
<Link
href={{
query: {
[popupQueryKey]: userPopupQueryValue,
},
}}
>
<T.Icon name="user" label={userLinkLabel} />
</Link>
}
>
<Basic.ContentContainer>
<DummyContent />
</Basic.ContentContainer>
</Basic.Layout>
)
}

export default BasicLayoutTemplate

+ 185
- 0
src/components/templates/Index/index.tsx 파일 보기

@@ -0,0 +1,185 @@
import * as React from 'react'
import styled from 'styled-components'
import * as T from '@tesseract-design/react-common'
import {Basic} from '@theoryofnekomata/viewfinder'
import Link from '../../molecules/Link'
import Brand from '../../molecules/Brand'

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::before': {
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
'::after': {
backgroundColor: 'black',
opacity: 0.5,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

const LinkContainer = styled('nav')({
margin: '1rem 0',
display: 'grid',
gap: '1rem',
'@media (min-width: 720px)': {
gridTemplateColumns: 'repeat(2, 1fr)',
},
})

const PreviewWrapper = styled('div')({
overflow: 'hidden',
width: '100%',
paddingBottom: '150%',
position: 'relative',
marginTop: '0.25rem',
'::after': {
content: "''",
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
border: '0.125rem solid',
boxSizing: 'border-box',
},
'@media (min-width: 720px)': {
paddingBottom: '75%',
},
})

const Preview = styled('iframe')({
position: 'absolute',
top: 0,
left: 0,
border: 0,
display: 'block',
transformOrigin: 'top left',
width: '200%',
height: '200%',
transform: 'scale(0.5)',
'@media (min-width: 720px)': {
width: '400%',
height: '400%',
transform: 'scale(0.25)',
},
})

const StyledLink = styled(Link)({
display: 'block',
textDecoration: 'none',
// borderRadius: '0.25rem',
// padding: '1rem',
boxSizing: 'border-box',
// border: '0.125rem solid',
})

type Props = {
query: string
userLinkLabel: string
searchQueryKey: string
searchLabel: string
searchHint: string
popupQueryKey: string
userPopupQueryValue: string
}

const IndexTemplate: React.FC<Props> = ({
query,
userLinkLabel,
searchQueryKey,
searchLabel,
searchHint,
popupQueryKey,
userPopupQueryValue,
}) => {
return (
<Basic.Layout
brand={<Brand />}
topBarComponent={TopBarComponent}
topBarCenter={
<form>
<T.TextInput
name={searchQueryKey}
label={searchLabel}
hint={searchHint}
defaultValue={query}
border
alternate
/>
</form>
}
userLink={
<Link
href={{
query: {
[popupQueryKey]: userPopupQueryValue,
},
}}
>
<T.Icon name="user" label={userLinkLabel} />
</Link>
}
>
<Basic.ContentContainer>
<h1>Welcome</h1>
<p>Select a template to preview:</p>
<LinkContainer>
<StyledLink
href={{
pathname: '/layouts/basic',
}}
>
Basic Layout
<PreviewWrapper>
<Preview src="/layouts/basic" scrolling="no" />
</PreviewWrapper>
</StyledLink>
<StyledLink
href={{
pathname: '/layouts/right-sidebar-static',
}}
>
Right Sidebar (static)
<PreviewWrapper>
<Preview src="/layouts/right-sidebar-static" scrolling="no" />
</PreviewWrapper>
</StyledLink>
<StyledLink
href={{
pathname: '/layouts/left-sidebar',
}}
>
Left Sidebar
<PreviewWrapper>
<Preview src="/layouts/left-sidebar" scrolling="no" />
</PreviewWrapper>
</StyledLink>
<StyledLink
href={{
pathname: '/layouts/left-sidebar/with-menu',
}}
>
Left Sidebar (with menu)
<PreviewWrapper>
<Preview src="/layouts/left-sidebar/with-menu" scrolling="no" />
</PreviewWrapper>
</StyledLink>
</LinkContainer>
</Basic.ContentContainer>
</Basic.Layout>
)
}

export default IndexTemplate

+ 129
- 0
src/components/templates/LeftSidebarLayout/index.tsx 파일 보기

@@ -0,0 +1,129 @@
import * as React from 'react'
import styled from 'styled-components'
import * as T from '@tesseract-design/react-common'
import {LeftSidebar} from '@theoryofnekomata/viewfinder'
import DummyContent from '../../molecules/DummyContent'
import Link from '../../molecules/Link'
import Brand from '../../molecules/Brand'

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::before': {
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
'::after': {
backgroundColor: 'black',
opacity: 0.5,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

const SidebarMainComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
zIndex: 2,
'::after': {
backgroundColor: 'black',
opacity: 0.25,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

type Props = {
query: string
menuLinkLabel: string
userLinkLabel: string
searchQueryKey: string
searchLabel: string
searchHint: string
popupQueryKey: string
userPopupQueryValue: string
sidebarSubpageQueryValue: string
subpageQueryKey: string
subpage: string
}

const LeftSidebarLayoutTemplate: React.FC<Props> = ({
query,
menuLinkLabel,
userLinkLabel,
searchQueryKey,
searchLabel,
searchHint,
popupQueryKey,
userPopupQueryValue,
sidebarSubpageQueryValue,
subpageQueryKey,
subpage,
}) => {
return (
<LeftSidebar.Layout
brand={<Brand />}
topBarComponent={TopBarComponent}
sidebarMainComponent={SidebarMainComponent}
sidebarMainOpen={subpage === sidebarSubpageQueryValue}
topBarCenter={
<form>
<T.TextInput
name={searchQueryKey}
label={searchLabel}
hint={searchHint}
defaultValue={query}
border
alternate
/>
</form>
}
menuLink={
<Link
href={{
query: {
[subpageQueryKey]: sidebarSubpageQueryValue,
},
}}
>
<T.Icon name="menu" label={menuLinkLabel} />
</Link>
}
userLink={
<Link
href={{
query: {
[popupQueryKey]: userPopupQueryValue,
},
}}
>
<T.Icon name="user" label={userLinkLabel} />
</Link>
}
sidebarMain={
<LeftSidebar.SidebarMainContainer>
<DummyContent />
</LeftSidebar.SidebarMainContainer>
}
>
<LeftSidebar.ContentContainer>
<DummyContent />
</LeftSidebar.ContentContainer>
</LeftSidebar.Layout>
)
}

export default LeftSidebarLayoutTemplate

+ 178
- 0
src/components/templates/LeftSidebarWithMenuLayout/index.tsx 파일 보기

@@ -0,0 +1,178 @@
import * as React from 'react'
import styled from 'styled-components'
import * as T from '@tesseract-design/react-common'
import {LeftSidebarWithMenu} from '@theoryofnekomata/viewfinder'
import DummyContent from '../../molecules/DummyContent'
import Link from '../../molecules/Link'
import Brand from '../../molecules/Brand'

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::before': {
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
'::after': {
backgroundColor: 'black',
opacity: 0.5,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

const SidebarMainComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
zIndex: 2,
'::after': {
backgroundColor: 'black',
opacity: 0.25,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

const SidebarMenuComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::after': {
backgroundColor: 'black',
opacity: 0.4,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

type Props = {
query: string
menuLinkLabel: string
userLinkLabel: string
searchQueryKey: string
searchLabel: string
searchHint: string
popupQueryKey: string
moreSubpageQueryValue: string
sidebarSubpageQueryValue: string
moreLinkLabel: string
sidebarMenuItems: LeftSidebarWithMenu.MenuItem[]
userPopupQueryValue: string
subpageQueryKey: string
subpage: string
}

const LeftSidebarLayoutTemplate: React.FC<Props> = ({
query,
menuLinkLabel,
userLinkLabel,
searchQueryKey,
searchLabel,
searchHint,
popupQueryKey,
moreSubpageQueryValue,
sidebarSubpageQueryValue,
moreLinkLabel,
sidebarMenuItems,
userPopupQueryValue,
subpageQueryKey,
subpage,
}) => {
return (
<LeftSidebarWithMenu.Layout
brand={<Brand />}
sidebarMainComponent={SidebarMainComponent}
sidebarMenuComponent={SidebarMenuComponent}
topBarComponent={TopBarComponent}
topBarCenter={
<form>
<T.TextInput
name={searchQueryKey}
label={searchLabel}
hint={searchHint}
defaultValue={query}
border
alternate
/>
</form>
}
menuLink={
<Link
href={{
query: {
[subpageQueryKey]: sidebarSubpageQueryValue,
},
}}
>
<T.Icon name="menu" label={menuLinkLabel} />
</Link>
}
userLink={
<Link
href={{
query: {
[popupQueryKey]: userPopupQueryValue,
},
}}
>
<T.Icon name="user" label={userLinkLabel} />
</Link>
}
moreLinkMenuItem={{
label: moreLinkLabel,
url: {
query: {
[subpageQueryKey]: moreSubpageQueryValue,
},
},
icon: <T.Icon name="more-horizontal" label="" />,
}}
moreItemsOpen={subpage === moreSubpageQueryValue}
moreLinkComponent={({url, icon, label}) => (
<Link href={url}>
<LeftSidebarWithMenu.MoreSidebarMenuContainer>
<LeftSidebarWithMenu.MoreSidebarMenuItemIcon>{icon}</LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.MoreSidebarMenuContainer>
</Link>
)}
linkComponent={({url, icon, label}) => (
<Link href={url}>
<LeftSidebarWithMenu.SidebarMenuContainer>
<LeftSidebarWithMenu.SidebarMenuItemIcon>{icon}</LeftSidebarWithMenu.SidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.SidebarMenuContainer>
</Link>
)}
sidebarMainOpen={subpage === sidebarSubpageQueryValue}
sidebarMain={
<LeftSidebarWithMenu.SidebarMainContainer>
<DummyContent />
</LeftSidebarWithMenu.SidebarMainContainer>
}
sidebarMenuItems={sidebarMenuItems}
>
<LeftSidebarWithMenu.ContentContainer>
<DummyContent />
</LeftSidebarWithMenu.ContentContainer>
</LeftSidebarWithMenu.Layout>
)
}

export default LeftSidebarLayoutTemplate

+ 98
- 0
src/components/templates/RightSidebarLayout/index.tsx 파일 보기

@@ -0,0 +1,98 @@
import * as React from 'react'
import styled from 'styled-components'
import * as T from '@tesseract-design/react-common'
import {RightSidebarStatic} from '@theoryofnekomata/viewfinder'
import DummyContent from '../../molecules/DummyContent'
import Link from '../../molecules/Link'
import Brand from '../../molecules/Brand'

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::before': {
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
'::after': {
backgroundColor: 'black',
opacity: 0.5,
content: "''",
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
},
})

const SidebarMainComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
zIndex: 2,
})

type Props = {
query: string
userLinkLabel: string
searchQueryKey: string
searchLabel: string
searchHint: string
popupQueryKey: string
userPopupQueryValue: string
}

const RightSidebarLayoutTemplate: React.FC<Props> = ({
query,
userLinkLabel,
searchQueryKey,
searchLabel,
searchHint,
popupQueryKey,
userPopupQueryValue,
}) => {
return (
<RightSidebarStatic.Layout
brand={<Brand />}
topBarComponent={TopBarComponent}
sidebarMainComponent={SidebarMainComponent}
topBarCenter={
<form>
<T.TextInput
name={searchQueryKey}
label={searchLabel}
hint={searchHint}
defaultValue={query}
border
alternate
/>
</form>
}
userLink={
<Link
href={{
query: {
[popupQueryKey]: userPopupQueryValue,
},
}}
>
<T.Icon name="user" label={userLinkLabel} />
</Link>
}
sidebarMain={
<RightSidebarStatic.SidebarMainContainer>
<DummyContent />
</RightSidebarStatic.SidebarMainContainer>
}
>
<RightSidebarStatic.ContentContainer>
<DummyContent />
</RightSidebarStatic.ContentContainer>
</RightSidebarStatic.Layout>
)
}

export default RightSidebarLayoutTemplate

+ 12
- 0
src/pages/_app.tsx 파일 보기

@@ -0,0 +1,12 @@
import * as React from 'react'

type Props = {
Component: React.ElementType
pageProps: Record<string, unknown>
}

const MyApp: React.FC<Props> = ({Component, pageProps}) => {
return <Component {...pageProps} />
}

export default MyApp

+ 58
- 0
src/pages/_document.tsx 파일 보기

@@ -0,0 +1,58 @@
import * as React from 'react'
import Document, {Html, Head, Main, NextScript, DocumentInitialProps, DocumentContext} from 'next/document'
import {ServerStyleSheet} from 'styled-components'
import pkg from '../../package.json'
import config from '../../next.config'

const publicUrl = process.env.NODE_ENV === 'production' ? pkg.homepage : config.basePath

export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage

try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
})

const initialProps = await Document.getInitialProps(ctx)

return {
...initialProps,
styles: (
<>
{initialProps.styles}
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Encode+Sans:wdth,wght@75..112.5,100..900&display=swap"
/>
<link rel="stylesheet" href={`${publicUrl}/global.css`} />
<link rel="stylesheet" href={`${publicUrl}/theme.css`} />
<link rel="stylesheet" title="Dark" href={`${publicUrl}/theme/dark.css`} />
<link rel="alternate stylesheet" title="Light" href={`${publicUrl}/theme/light.css`} />
{sheet.getStyleElement()}
</>
),
}
} catch (err) {
console.error(err)
} finally {
sheet.seal()
}
}

render(): React.ReactElement {
return (
<Html lang="en-PH">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}

+ 33
- 0
src/pages/index.tsx 파일 보기

@@ -0,0 +1,33 @@
import {GetServerSideProps, NextPage} from 'next'
import {USER} from '../utilities/popups'
import {QUERY, POPUP} from '../utilities/queryKeys'
import Template from '../components/templates/Index'

type Props = {
query: string
}

const Page: NextPage<Props> = ({query}) => {
return (
<Template
query={query}
userLinkLabel="User"
searchQueryKey={QUERY}
searchLabel="Search"
searchHint="e.g. keywords, names&hellip;"
popupQueryKey={POPUP}
userPopupQueryValue={USER}
/>
)
}

export default Page

export const getServerSideProps: GetServerSideProps = async (ctx) => {
const {[QUERY]: query = ''} = ctx.query
return {
props: {
query,
},
}
}

+ 33
- 0
src/pages/layouts/basic/index.tsx 파일 보기

@@ -0,0 +1,33 @@
import {GetServerSideProps, NextPage} from 'next'
import Template from '../../../components/templates/BasicLayout'
import {USER} from '../../../utilities/popups'
import {POPUP, QUERY} from '../../../utilities/queryKeys'

type Props = {
query: string
}

const Page: NextPage<Props> = ({query}) => {
return (
<Template
query={query}
userLinkLabel="User"
searchQueryKey={QUERY}
searchLabel="Search"
searchHint="e.g. keywords, names&hellip;"
popupQueryKey={POPUP}
userPopupQueryValue={USER}
/>
)
}

export default Page

export const getServerSideProps: GetServerSideProps = async (ctx) => {
const {[QUERY]: query = ''} = ctx.query
return {
props: {
query,
},
}
}

+ 40
- 0
src/pages/layouts/left-sidebar/index.tsx 파일 보기

@@ -0,0 +1,40 @@
import {GetServerSideProps, NextPage} from 'next'
import Template from '../../../components/templates/LeftSidebarLayout'
import {POPUP, QUERY, SUBPAGE} from '../../../utilities/queryKeys'
import {USER} from '../../../utilities/popups'
import {SIDEBAR} from '../../../utilities/subpages'

type Props = {
query: string
subpage: string
}

const Page: NextPage<Props> = ({query, subpage}) => {
return (
<Template
subpage={subpage}
query={query}
userLinkLabel="User"
searchQueryKey={QUERY}
searchLabel="Search"
searchHint="e.g. keywords, names&hellip;"
popupQueryKey={POPUP}
userPopupQueryValue={USER}
menuLinkLabel="Menu"
subpageQueryKey={SUBPAGE}
sidebarSubpageQueryValue={SIDEBAR}
/>
)
}

export default Page

export const getServerSideProps: GetServerSideProps = async (ctx) => {
const {[QUERY]: query = '', [SUBPAGE]: subpage = null} = ctx.query
return {
props: {
query,
subpage,
},
}
}

+ 104
- 0
src/pages/layouts/left-sidebar/with-menu/index.tsx 파일 보기

@@ -0,0 +1,104 @@
import * as React from 'react'
import * as T from '@tesseract-design/react-common'
import {GetServerSideProps, NextPage} from 'next'
import Template from '../../../../components/templates/LeftSidebarWithMenuLayout'
import {POPUP, QUERY, SUBPAGE} from '../../../../utilities/queryKeys'
import {USER} from '../../../../utilities/popups'
import {MORE, SIDEBAR} from '../../../../utilities/subpages'

type Props = {
query: string
subpage: string
}

const Page: NextPage<Props> = ({query, subpage}) => {
return (
<Template
query={query}
subpage={subpage}
userLinkLabel="User"
searchQueryKey={QUERY}
searchLabel="Search"
searchHint="e.g. keywords, names&hellip;"
popupQueryKey={POPUP}
userPopupQueryValue={USER}
menuLinkLabel="Menu"
moreLinkLabel="More"
subpageQueryKey={SUBPAGE}
sidebarSubpageQueryValue={SIDEBAR}
moreSubpageQueryValue={MORE}
sidebarMenuItems={[
{
id: '1',
label: 'P1',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
},
{
id: '2',
label: 'P2',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
},
{
id: '3',
label: 'P3',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
},
{
id: '100',
label: 'P4',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
},
{
id: '101',
label: 'P5',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
},
{
id: '4',
label: 'S1',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
secondary: true,
},
{
id: '5',
label: 'S2',
url: {
pathname: '/hello',
},
icon: <T.Icon name="square" label="" />,
secondary: true,
},
]}
/>
)
}

export default Page

export const getServerSideProps: GetServerSideProps = async (ctx) => {
const {[QUERY]: query = '', [SUBPAGE]: subpage = null} = ctx.query
return {
props: {
query,
subpage,
},
}
}

+ 33
- 0
src/pages/layouts/right-sidebar-static/index.tsx 파일 보기

@@ -0,0 +1,33 @@
import {GetServerSideProps, NextPage} from 'next'
import Template from '../../../components/templates/RightSidebarLayout'
import {POPUP, QUERY} from '../../../utilities/queryKeys'
import {USER} from '../../../utilities/popups'

type Props = {
query: string
}

const Page: NextPage<Props> = ({query}) => {
return (
<Template
query={query}
userLinkLabel="User"
searchQueryKey={QUERY}
searchLabel="Search"
searchHint="e.g. keywords, names&hellip;"
popupQueryKey={POPUP}
userPopupQueryValue={USER}
/>
)
}

export default Page

export const getServerSideProps: GetServerSideProps = async (ctx) => {
const {[QUERY]: query = ''} = ctx.query
return {
props: {
query,
},
}
}

+ 1
- 0
src/utilities/popups.ts 파일 보기

@@ -0,0 +1 @@
export const USER = 'user'

+ 5
- 0
src/utilities/queryKeys.ts 파일 보기

@@ -0,0 +1,5 @@
export const QUERY = 'q'

export const POPUP = 'popup'

export const SUBPAGE = 'subpage'

+ 21
- 0
src/utilities/styles/mixins.ts 파일 보기

@@ -0,0 +1,21 @@
export const container = {
padding: '0 1rem',
boxSizing: 'border-box',
margin: '0 auto',
maxWidth: 'calc(var(--width-base, 360px) * 2)',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
}

export const wideContainer = {
padding: '0 1rem',
boxSizing: 'border-box',
margin: '0 auto',
maxWidth: 'calc(var(--width-base, 360px) * 3)',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
}

+ 3
- 0
src/utilities/subpages.ts 파일 보기

@@ -0,0 +1,3 @@
export const SIDEBAR = 'sidebar'

export const MORE = 'more'

+ 30
- 0
tsconfig.json 파일 보기

@@ -0,0 +1,30 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}

+ 3929
- 0
yarn.lock
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


불러오는 중...
취소
저장