Use css-utils, which is powered by Goober, for separating HTML semantics and styling, as compared from styled-components where semantics and styling are defined together.refactor/nx-goober
@@ -0,0 +1,108 @@ | |||||
# Logs | |||||
logs | |||||
*.log | |||||
npm-debug.log* | |||||
yarn-debug.log* | |||||
yarn-error.log* | |||||
lerna-debug.log* | |||||
# Diagnostic reports (https://nodejs.org/api/report.html) | |||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | |||||
# Runtime data | |||||
pids | |||||
*.pid | |||||
*.seed | |||||
*.pid.lock | |||||
# Directory for instrumented libs generated by jscoverage/JSCover | |||||
lib-cov | |||||
# Coverage directory used by tools like istanbul | |||||
coverage | |||||
*.lcov | |||||
# nyc test coverage | |||||
.nyc_output | |||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | |||||
.grunt | |||||
# Bower dependency directory (https://bower.io/) | |||||
bower_components | |||||
# node-waf configuration | |||||
.lock-wscript | |||||
# Compiled binary addons (https://nodejs.org/api/addons.html) | |||||
build/Release | |||||
# Dependency directories | |||||
node_modules/ | |||||
jspm_packages/ | |||||
# TypeScript v1 declaration files | |||||
typings/ | |||||
# TypeScript cache | |||||
*.tsbuildinfo | |||||
# Optional npm cache directory | |||||
.npm | |||||
# Optional eslint cache | |||||
.eslintcache | |||||
# Microbundle cache | |||||
.rpt2_cache/ | |||||
.rts2_cache_cjs/ | |||||
.rts2_cache_es/ | |||||
.rts2_cache_umd/ | |||||
# Optional REPL history | |||||
.node_repl_history | |||||
# Output of 'npm pack' | |||||
*.tgz | |||||
# Yarn Integrity file | |||||
.yarn-integrity | |||||
# dotenv environment variables file | |||||
.env | |||||
.env.production | |||||
.env.development | |||||
# parcel-bundler cache (https://parceljs.org/) | |||||
.cache | |||||
# Next.js build output | |||||
.next | |||||
# Nuxt.js build / generate output | |||||
.nuxt | |||||
dist | |||||
# Gatsby files | |||||
.cache/ | |||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js | |||||
# https://nextjs.org/blog/next-9-1#public-directory-support | |||||
# public | |||||
# vuepress build output | |||||
.vuepress/dist | |||||
# Serverless directories | |||||
.serverless/ | |||||
# FuseBox cache | |||||
.fusebox/ | |||||
# DynamoDB Local files | |||||
.dynamodb/ | |||||
# TernJS port file | |||||
.tern-port | |||||
.npmrc | |||||
.idea/ |
@@ -0,0 +1,7 @@ | |||||
MIT License Copyright (c) 2022 TheoryOfNekomata <allan.crisostomo@outlook.com> | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@@ -0,0 +1,6 @@ | |||||
{ | |||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json", | |||||
"useNx": true, | |||||
"useWorkspaces": true, | |||||
"version": "0.0.0" | |||||
} |
@@ -0,0 +1,30 @@ | |||||
{ | |||||
"extends": "nx/presets/npm.json", | |||||
"tasksRunnerOptions": { | |||||
"default": { | |||||
"runner": "nx/tasks-runners/default", | |||||
"options": { | |||||
"cacheableOperations": [ | |||||
"prepublishOnly", | |||||
"build", | |||||
"type-check", | |||||
"lint", | |||||
"clean", | |||||
"watch", | |||||
"dev", | |||||
"test" | |||||
] | |||||
} | |||||
} | |||||
}, | |||||
"targetDefaults": { | |||||
"build": { | |||||
"dependsOn": [ | |||||
"^build" | |||||
] | |||||
} | |||||
}, | |||||
"affected": { | |||||
"defaultBase": "master" | |||||
} | |||||
} |
@@ -0,0 +1,11 @@ | |||||
{ | |||||
"name": "root", | |||||
"private": true, | |||||
"workspaces": [ | |||||
"packages/**/*" | |||||
], | |||||
"devDependencies": { | |||||
"lerna": "^5.3.0", | |||||
"nx": "14.5.4" | |||||
} | |||||
} |
@@ -0,0 +1,64 @@ | |||||
{ | |||||
"name": "@tesseract-design/viewfinder-base", | |||||
"version": "0.0.0", | |||||
"files": [ | |||||
"dist", | |||||
"src" | |||||
], | |||||
"engines": { | |||||
"node": ">=10" | |||||
}, | |||||
"license": "MIT", | |||||
"keywords": [ | |||||
"pridepack" | |||||
], | |||||
"devDependencies": { | |||||
"@types/node": "^18.0.0", | |||||
"eslint": "^8.20.0", | |||||
"eslint-config-lxsmnsyc": "^0.4.7", | |||||
"pridepack": "2.2.1", | |||||
"tslib": "^2.4.0", | |||||
"typescript": "^4.7.4", | |||||
"vitest": "^0.19.1" | |||||
}, | |||||
"scripts": { | |||||
"prepublishOnly": "pridepack clean && pridepack build", | |||||
"build": "pridepack build", | |||||
"type-check": "pridepack check", | |||||
"lint": "pridepack lint", | |||||
"clean": "pridepack clean", | |||||
"watch": "pridepack watch", | |||||
"start": "pridepack start", | |||||
"dev": "pridepack dev", | |||||
"test": "vitest" | |||||
}, | |||||
"private": false, | |||||
"description": "Base styles for Viewfinder.", | |||||
"repository": { | |||||
"url": "", | |||||
"type": "git" | |||||
}, | |||||
"homepage": "", | |||||
"bugs": { | |||||
"url": "" | |||||
}, | |||||
"author": "TheoryOfNekomata <allan.crisostomo@outlook.com>", | |||||
"publishConfig": { | |||||
"access": "public" | |||||
}, | |||||
"types": "./dist/types/index.d.ts", | |||||
"exports": { | |||||
".": { | |||||
"development": { | |||||
"require": "./dist/cjs/development/index.js", | |||||
"import": "./dist/esm/development/index.js" | |||||
}, | |||||
"require": "./dist/cjs/production/index.js", | |||||
"import": "./dist/esm/production/index.js", | |||||
"types": "./dist/types/index.d.ts" | |||||
} | |||||
}, | |||||
"typesVersions": { | |||||
"*": {} | |||||
} | |||||
} |
@@ -0,0 +1,3 @@ | |||||
{ | |||||
"target": "es2017" | |||||
} |
@@ -0,0 +1,10 @@ | |||||
export enum Span { | |||||
NARROW = 'narrow', | |||||
NORMAL = 'normal', | |||||
WIDE = 'wide', | |||||
} | |||||
export type LayoutArgs = { | |||||
span: Span; | |||||
mainSidebarOpen: boolean; | |||||
} |
@@ -0,0 +1,3 @@ | |||||
export * as layouts from './layouts'; | |||||
export * as widgets from './widgets'; | |||||
export * from './common'; |
@@ -0,0 +1,34 @@ | |||||
import { css } from '@tesseract-design/css-utils'; | |||||
import {LayoutArgs, Span} from '../common'; | |||||
export const ContentBase = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
` | |||||
); | |||||
export const ContentContainer = ({ | |||||
span, | |||||
}: LayoutArgs) => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
margin: 0 auto; | |||||
width: 100%; | |||||
`, | |||||
css.if(span === Span.NARROW)( | |||||
css` | |||||
max-width: var(--base-width); | |||||
` | |||||
), | |||||
css.if(span === Span.NORMAL)( | |||||
css` | |||||
max-width: calc(var(--base-width) * 2); | |||||
` | |||||
), | |||||
css.if(span === Span.WIDE)( | |||||
css` | |||||
max-width: calc(var(--base-width) * 3); | |||||
` | |||||
), | |||||
); |
@@ -0,0 +1,90 @@ | |||||
import { css } from '@tesseract-design/css-utils'; | |||||
import {LayoutArgs} from '../common'; | |||||
export const ContentBase = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
padding-left: calc(50% - (var(--base-width) * 0.5)); | |||||
` | |||||
), | |||||
); | |||||
export const SidebarOverflow = () => css.cx( | |||||
css` | |||||
width: 100%; | |||||
height: 100%; | |||||
overflow: auto; | |||||
// overflow: overlay; | |||||
position: relative; | |||||
z-index: 1; | |||||
scrollbar-width: none; | |||||
&::-webkit-scrollbar { | |||||
display: none; | |||||
} | |||||
` | |||||
) | |||||
export const SidebarBase = ({ | |||||
mainSidebarOpen, | |||||
}: LayoutArgs) => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
position: fixed; | |||||
top: 0; | |||||
left: -100%; | |||||
width: 100%; | |||||
height: 100%; | |||||
background-color: white; | |||||
& > * { | |||||
display: block; | |||||
width: 100%; | |||||
height: 100%; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: calc(50% - (var(--base-width) * 0.5)); | |||||
left: 0; | |||||
` | |||||
), | |||||
css.if(mainSidebarOpen)( | |||||
css` | |||||
left: 0; | |||||
` | |||||
), | |||||
); | |||||
export const SidebarMainContainer = () => css.cx( | |||||
css` | |||||
width: 100%; | |||||
margin: 0 auto; | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
max-width: calc(var(--base-width) * 2); | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: var(--base-width); | |||||
margin-right: 0; | |||||
` | |||||
), | |||||
); | |||||
export const ContentContainer = () => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
width: 100%; | |||||
max-width: calc(var(--base-width) * 2); | |||||
margin-right: auto; | |||||
margin-left: auto; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
margin-left: 0; | |||||
` | |||||
), | |||||
); |
@@ -0,0 +1,368 @@ | |||||
import { css } from '@tesseract-design/css-utils'; | |||||
import {LayoutArgs} from '../common'; | |||||
export const ContentBase = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
padding-bottom: var(--size-menu, 4rem); | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
padding-left: calc(50% - var(--base-width) * 0.5); | |||||
padding-bottom: 0; | |||||
`, | |||||
), | |||||
) | |||||
export const SidebarBase = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
overflow: hidden; | |||||
display: contents; | |||||
left: calc(var(--base-width) * -1); | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
width: calc(50% - var(--base-width) * 0.5); | |||||
height: 100%; | |||||
display: block; | |||||
`, | |||||
), | |||||
) | |||||
export const SidebarMain = ({ | |||||
mainSidebarOpen, | |||||
}: LayoutArgs) => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
position: fixed; | |||||
top: 0; | |||||
width: 100%; | |||||
height: 100%; | |||||
padding-top: inherit; | |||||
padding-bottom: var(--size-menu, 4rem); | |||||
z-index: 2; | |||||
> * { | |||||
display: block; | |||||
width: 100%; | |||||
height: 100%; | |||||
background-color: white; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
position: absolute; | |||||
right: 0; | |||||
width: calc(var(--base-width) - var(--size-menu, 4rem)); | |||||
margin-left: 0; | |||||
padding-bottom: 0; | |||||
`, | |||||
), | |||||
css.dynamic({ | |||||
right: mainSidebarOpen ? 0 : '100%', | |||||
}), | |||||
) | |||||
export const SidebarMainOverflow = () => css.cx( | |||||
css` | |||||
width: 100%; | |||||
height: 100%; | |||||
overflow: auto; /* overflow: overlay */ | |||||
scrollbar-width: none; | |||||
position: relative; | |||||
z-index: 1; | |||||
::-webkit-scrollbar { | |||||
display: none; | |||||
} | |||||
` | |||||
) | |||||
export const SidebarMenu = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
overflow: auto; /* overflow: overlay */ | |||||
scrollbar-width: none; | |||||
::-webkit-scrollbar { | |||||
display: none; | |||||
} | |||||
position: fixed; | |||||
bottom: 0; | |||||
left: 0; | |||||
width: 100%; | |||||
height: var(--size-menu, 4rem); | |||||
z-index: 1; | |||||
> * { | |||||
display: block; | |||||
width: 100%; | |||||
height: 100%; | |||||
background-color: white; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
top: 0; | |||||
margin-left: auto; | |||||
position: absolute; | |||||
height: 100%; | |||||
padding-top: inherit; | |||||
overflow: auto; | |||||
z-index: auto; | |||||
`, | |||||
), | |||||
); | |||||
export const SidebarMenuSize = () => css.cx( | |||||
css` | |||||
display: flex; | |||||
width: 100%; | |||||
height: 100%; | |||||
max-width: calc(var(--base-width) * 2); | |||||
margin: 0 auto; | |||||
position: relative; | |||||
z-index: 1; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
max-width: none; | |||||
margin-right: 0; | |||||
flex-direction: column; | |||||
justify-content: space-between; | |||||
align-items: flex-end; | |||||
`, | |||||
), | |||||
); | |||||
export const SidebarMenuGroup = () => css.cx( | |||||
css` | |||||
display: contents; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: 100%; | |||||
display: block; | |||||
`, | |||||
), | |||||
); | |||||
export const MoreItems = ({ | |||||
mainSidebarOpen, | |||||
}: LayoutArgs) => css.cx( | |||||
css` | |||||
position: fixed; | |||||
top: 0; | |||||
width: 100%; | |||||
height: 100%; | |||||
padding-top: var(--height-topbar, 4rem); | |||||
padding-bottom: var(--size-menu, 4rem); | |||||
z-index: -1; | |||||
box-sizing: border-box; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
display: contents; | |||||
`, | |||||
), | |||||
css.dynamic({ | |||||
left: mainSidebarOpen ? 0 : '-100%', | |||||
}), | |||||
); | |||||
export const MoreItemsScroll = () => css.cx( | |||||
css` | |||||
width: 100%; | |||||
height: 100%; | |||||
overflow: auto; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
display: contents; | |||||
`, | |||||
), | |||||
); | |||||
export const MorePrimarySidebarMenuGroup = () => css.cx( | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
flex: auto; | |||||
`, | |||||
), | |||||
); | |||||
export const MoreSecondarySidebarMenuGroup = () => css.cx( | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
order: 4; | |||||
`, | |||||
), | |||||
); | |||||
export const SidebarMenuItem = () => css.cx( | |||||
css` | |||||
width: 0; | |||||
flex: auto; | |||||
height: var(--size-menu, 4rem); | |||||
> * { | |||||
height: 100%; | |||||
display: flex; | |||||
align-items: center; | |||||
text-decoration: none; | |||||
width: 100%; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: auto !important; | |||||
flex: 0 1 auto; | |||||
> * { | |||||
height: auto; | |||||
} | |||||
` | |||||
), | |||||
); | |||||
export const MoreSidebarMenuItem = () => css.cx( | |||||
css` | |||||
width: 0; | |||||
flex: auto; | |||||
height: var(--size-menu, 4rem); | |||||
> * { | |||||
height: 100%; | |||||
display: flex; | |||||
align-items: center; | |||||
text-decoration: none; | |||||
width: 100%; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: auto !important; | |||||
flex: 0 1 auto; | |||||
`, | |||||
), | |||||
); | |||||
export const MoreToggleSidebarMenuItem = () => css.cx( | |||||
css` | |||||
width: 0; | |||||
flex: auto; | |||||
height: var(--size-menu, 4rem); | |||||
> * { | |||||
height: 100%; | |||||
display: flex; | |||||
align-items: center; | |||||
text-decoration: none; | |||||
width: 100%; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
display: none; | |||||
`, | |||||
), | |||||
); | |||||
export const SidebarMenuItemIcon = () => css.cx( | |||||
css` | |||||
display: block; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: var(--size-menu, 4rem); | |||||
height: var(--size-menu, 4rem); | |||||
display: grid; | |||||
place-content: center; | |||||
`, | |||||
), | |||||
); | |||||
export const MoreSidebarMenuItemItem = () => css.cx( | |||||
css` | |||||
margin-right: 1rem; | |||||
display: block; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
width: var(--size-menu, 4rem); | |||||
height: var(--size-menu, 4rem); | |||||
display: grid; | |||||
place-content: center; | |||||
margin-right: 0; | |||||
`, | |||||
), | |||||
); | |||||
export const SidebarMenuContainer = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
display: grid; | |||||
place-content: center; | |||||
width: 100%; | |||||
text-align: center; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
display: flex; | |||||
justify-content: flex-start; | |||||
align-items: center; | |||||
margin-left: auto; | |||||
padding-right: 1rem; | |||||
text-align: left; | |||||
box-sizing: border-box; | |||||
width: var(--base-width); | |||||
`, | |||||
), | |||||
) | |||||
export const MoreSidebarMenuContainer = () => css.cx( | |||||
css` | |||||
display: flex; | |||||
justify-content: flex-start; | |||||
align-items: center; | |||||
width: calc(var(--base-width) * 2); | |||||
margin: 0 auto; | |||||
padding: 0 1rem; | |||||
text-align: left; | |||||
box-sizing: border-box; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
margin-right: 0; | |||||
width: var(--base-width); | |||||
padding-left: 0; | |||||
`, | |||||
), | |||||
); | |||||
export const ContentContainer = () => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
width: 100%; | |||||
max-width: calc(var(--base-width) * 2); | |||||
margin-right: auto; | |||||
margin-left: auto; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
margin-left: 0; | |||||
`, | |||||
), | |||||
); | |||||
export const SidebarMainContainer = () => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
width: 100%; | |||||
max-width: calc(var(--base-width) * 2); | |||||
margin: 0 auto; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
max-width: none; | |||||
`, | |||||
), | |||||
); |
@@ -0,0 +1,83 @@ | |||||
import { css } from '@tesseract-design/css-utils'; | |||||
export const ContentBase = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
padding-right: calc(50% - (var(--base-width) * 0.5)); | |||||
` | |||||
), | |||||
); | |||||
export const SidebarBase = () => css.cx( | |||||
css` | |||||
box-sizing: border-box; | |||||
background-color: white; | |||||
`, | |||||
// prevent collapse of margin | |||||
css` | |||||
&::after { | |||||
content: "''"; | |||||
display: block; | |||||
padding-bottom: 1px; | |||||
margin-top: -1px; | |||||
box-sizing: border-box; | |||||
} | |||||
& > * { | |||||
display: block; | |||||
width: 100%; | |||||
height: 100%; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
position: absolute; | |||||
top: 0; | |||||
right: 0; | |||||
width: calc(50% - var(--base-width) * 0.5); | |||||
height: 100%; | |||||
`, | |||||
), | |||||
) | |||||
export const SidebarMainContent = () => css.cx( | |||||
css` | |||||
position: relative; | |||||
z-index: 1; | |||||
` | |||||
) | |||||
export const SidebarMainContainer = () => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
width: 100%; | |||||
max-width: calc(var(--base-width) * 2); | |||||
margin: 0 auto; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
margin-left: 0; | |||||
width: var(--base-width); | |||||
`, | |||||
), | |||||
) | |||||
export const ContentContainer = () => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
width: 100%; | |||||
max-width: calc(var(--base-width) * 2); | |||||
margin: 0 auto; | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
margin-right: 0; | |||||
`, | |||||
), | |||||
) | |||||
// TODO port from original viewfinder package |
@@ -0,0 +1,4 @@ | |||||
export * as Basic from './Basic'; | |||||
export * as LeftSidebar from './LeftSidebar'; | |||||
export * as LeftSidebarWithMenu from './LeftSidebarWithMenu'; | |||||
export * as RightSidebarStatic from './RightSidebarStatic'; |
@@ -0,0 +1,125 @@ | |||||
import { css } from '@tesseract-design/css-utils'; | |||||
import {LayoutArgs, Span} from '../common'; | |||||
export const Base = () => css.cx( | |||||
css` | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
width: 100%; | |||||
height: var(--height-topbar, 4rem); | |||||
z-index: 2; | |||||
& > * { | |||||
display: block; | |||||
width: 100%; | |||||
height: 100%; | |||||
background-color: white; | |||||
} | |||||
& ~ * { | |||||
padding-top: var(--height-topbar, 4rem);; | |||||
} | |||||
~ main ~ * { | |||||
padding-top: 0; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
~ main ~ * { | |||||
padding-top: var(--height-topbar, 4rem); | |||||
} | |||||
` | |||||
) | |||||
); | |||||
export const Container = ({ | |||||
span, | |||||
}: LayoutArgs) => css.cx( | |||||
css` | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
margin: 0 auto; | |||||
width: 100%; | |||||
height: 100%; | |||||
display: flex; | |||||
align-items: center; | |||||
position: relative; | |||||
z-index: 1; | |||||
`, | |||||
css.if(span === Span.NARROW)( | |||||
css` | |||||
max-width: var(--base-width); | |||||
` | |||||
), | |||||
css.if(span === Span.NORMAL)( | |||||
css` | |||||
max-width: calc(var(--base-width) * 3); | |||||
` | |||||
), | |||||
css.if(span === Span.WIDE)( | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
max-width: calc(var(--base-width) * 3); | |||||
` | |||||
) | |||||
), | |||||
); | |||||
export const CenterContainer = () => css.cx( | |||||
css` | |||||
flex: auto; | |||||
padding: 0 1rem; | |||||
box-sizing: border-box; | |||||
`, | |||||
css.nest(':first-child')( | |||||
css` | |||||
padding-left: 0; | |||||
` | |||||
) | |||||
) | |||||
export const ActionContainer = () => css.cx( | |||||
css` | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: flex-end; | |||||
height: 100%; | |||||
white-space: nowrap; | |||||
`, | |||||
css.media('(min-width: 720px)')( | |||||
css` | |||||
min-width: 8rem; | |||||
` | |||||
) | |||||
); | |||||
export const LinkContainer = () => css.cx( | |||||
css` | |||||
width: var(--height-topbar, 4rem); | |||||
height: 100%; | |||||
& > * { | |||||
width: 100%; | |||||
height: 100%; | |||||
display: inline-grid; | |||||
place-content: center; | |||||
} | |||||
` | |||||
); | |||||
export const MenuLinkContainer = () => css.cx( | |||||
css` | |||||
width: var(--height-topbar, 4rem); | |||||
height: 100%; | |||||
& > * { | |||||
width: 100%; | |||||
height: 100%; | |||||
display: inline-grid; | |||||
place-content: center; | |||||
} | |||||
`, | |||||
css.media('(min-width: 1080px)')( | |||||
css` | |||||
position: absolute; | |||||
left: -999999px; | |||||
` | |||||
) | |||||
); |
@@ -0,0 +1 @@ | |||||
export * as TopBar from './TopBar'; |
@@ -0,0 +1,8 @@ | |||||
import { describe, it, expect } from 'vitest'; | |||||
import add from '../src'; | |||||
describe('blah', () => { | |||||
it('works', () => { | |||||
expect(add(1, 1)).toEqual(2); | |||||
}); | |||||
}); |
@@ -0,0 +1,21 @@ | |||||
{ | |||||
"exclude": ["node_modules"], | |||||
"include": ["src", "types"], | |||||
"compilerOptions": { | |||||
"module": "ESNext", | |||||
"lib": ["ESNext"], | |||||
"importHelpers": true, | |||||
"declaration": true, | |||||
"sourceMap": true, | |||||
"rootDir": "./src", | |||||
"strict": true, | |||||
"noUnusedLocals": true, | |||||
"noUnusedParameters": true, | |||||
"noImplicitReturns": true, | |||||
"noFallthroughCasesInSwitch": true, | |||||
"moduleResolution": "node", | |||||
"jsx": "react", | |||||
"esModuleInterop": true, | |||||
"target": "ES2017" | |||||
} | |||||
} |
@@ -0,0 +1,3 @@ | |||||
{ | |||||
"extends": "next/core-web-vitals" | |||||
} |
@@ -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* | |||||
.pnpm-debug.log* | |||||
# local env files | |||||
.env*.local | |||||
# vercel | |||||
.vercel | |||||
# typescript | |||||
*.tsbuildinfo | |||||
next-env.d.ts |
@@ -0,0 +1,34 @@ | |||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). | |||||
## Getting Started | |||||
First, run the development server: | |||||
```bash | |||||
npm run dev | |||||
# or | |||||
yarn dev | |||||
``` | |||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | |||||
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. | |||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. | |||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. | |||||
## Learn More | |||||
To learn more about Next.js, take a look at the following resources: | |||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. | |||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. | |||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! | |||||
## Deploy on Vercel | |||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. | |||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. |
@@ -0,0 +1,7 @@ | |||||
/** @type {import('next').NextConfig} */ | |||||
const nextConfig = { | |||||
reactStrictMode: true, | |||||
swcMinify: true, | |||||
} | |||||
module.exports = nextConfig |
@@ -0,0 +1,25 @@ | |||||
{ | |||||
"name": "@tesseract-design/viewfinder-kitchen-sink-react", | |||||
"version": "0.1.0", | |||||
"private": true, | |||||
"scripts": { | |||||
"dev": "next dev", | |||||
"build": "next build", | |||||
"start": "next start", | |||||
"lint": "next lint" | |||||
}, | |||||
"dependencies": { | |||||
"next": "12.2.4", | |||||
"react": "18.2.0", | |||||
"react-dom": "18.2.0", | |||||
"@tesseract-design/viewfinder-react": "*" | |||||
}, | |||||
"devDependencies": { | |||||
"@types/node": "18.6.4", | |||||
"@types/react": "18.0.15", | |||||
"@types/react-dom": "18.0.6", | |||||
"eslint": "8.21.0", | |||||
"eslint-config-next": "12.2.4", | |||||
"typescript": "4.7.4" | |||||
} | |||||
} |
@@ -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> |
@@ -0,0 +1,20 @@ | |||||
import Link from 'next/link' | |||||
export const Brand = () => ( | |||||
<Link | |||||
href="/" | |||||
passHref | |||||
> | |||||
<a> | |||||
<div | |||||
style={{ | |||||
textTransform: 'uppercase', | |||||
fontWeight: 'bold', | |||||
fontSize: '2em', | |||||
}} | |||||
> | |||||
Brand | |||||
</div> | |||||
</a> | |||||
</Link> | |||||
) |
@@ -0,0 +1,37 @@ | |||||
import Link from 'next/link' | |||||
export const DummyLinks = () => ( | |||||
<div | |||||
style={{ | |||||
display: 'flex', | |||||
gap: '1rem', | |||||
alignItems: 'center', | |||||
marginLeft: '1rem', | |||||
}} | |||||
> | |||||
<Link | |||||
href="/" | |||||
passHref | |||||
> | |||||
<a> | |||||
About | |||||
</a> | |||||
</Link> | |||||
<Link | |||||
href="/" | |||||
passHref | |||||
> | |||||
<a> | |||||
Learn More | |||||
</a> | |||||
</Link> | |||||
<Link | |||||
href="/" | |||||
passHref | |||||
> | |||||
<a> | |||||
Contact | |||||
</a> | |||||
</Link> | |||||
</div> | |||||
) |
@@ -0,0 +1,8 @@ | |||||
import '../styles/globals.css' | |||||
import type { AppProps } from 'next/app' | |||||
function MyApp({ Component, pageProps }: AppProps) { | |||||
return <Component {...pageProps} /> | |||||
} | |||||
export default MyApp |
@@ -0,0 +1,13 @@ | |||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction | |||||
import type { NextApiRequest, NextApiResponse } from 'next' | |||||
type Data = { | |||||
name: string | |||||
} | |||||
export default function handler( | |||||
req: NextApiRequest, | |||||
res: NextApiResponse<Data> | |||||
) { | |||||
res.status(200).json({ name: 'John Doe' }) | |||||
} |
@@ -0,0 +1,29 @@ | |||||
import type { NextPage } from 'next' | |||||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||||
import {Span} from '@tesseract-design/viewfinder-base'; | |||||
const Home: NextPage = () => { | |||||
return ( | |||||
<Layouts.Basic.Root | |||||
topBarWidget={ | |||||
<Widgets.TopBar | |||||
brand="Brand" | |||||
style={{ | |||||
backgroundColor: 'inherit', | |||||
}} | |||||
span={Span.NARROW} | |||||
> | |||||
TopBar | |||||
</Widgets.TopBar> | |||||
} | |||||
> | |||||
<Layouts.Basic.ContentContainer | |||||
span={Span.NARROW} | |||||
> | |||||
Hello | |||||
</Layouts.Basic.ContentContainer> | |||||
</Layouts.Basic.Root> | |||||
) | |||||
} | |||||
export default Home |
@@ -0,0 +1,33 @@ | |||||
import type { NextPage } from 'next' | |||||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||||
import {Span} from '@tesseract-design/viewfinder-base'; | |||||
import {Brand} from '../../components/Brand'; | |||||
import {DummyLinks} from '../../components/DummyLinks'; | |||||
const BasicLayoutPage: NextPage = () => { | |||||
return ( | |||||
<Layouts.Basic.Root | |||||
topBarWidget={ | |||||
<Widgets.TopBar | |||||
brand={ | |||||
<Brand /> | |||||
} | |||||
style={{ | |||||
backgroundColor: 'inherit', | |||||
}} | |||||
span={Span.NARROW} | |||||
> | |||||
<DummyLinks /> | |||||
</Widgets.TopBar> | |||||
} | |||||
> | |||||
<Layouts.Basic.ContentContainer | |||||
span={Span.NARROW} | |||||
> | |||||
Hello | |||||
</Layouts.Basic.ContentContainer> | |||||
</Layouts.Basic.Root> | |||||
) | |||||
} | |||||
export default BasicLayoutPage |
@@ -0,0 +1,61 @@ | |||||
import type { NextPage } from 'next' | |||||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||||
import {Span} from '@tesseract-design/viewfinder-base'; | |||||
import {useRouter} from 'next/router'; | |||||
import {useMemo} from 'react'; | |||||
import Link from 'next/link'; | |||||
import {Brand} from '../../components/Brand'; | |||||
import {DummyLinks} from '../../components/DummyLinks'; | |||||
const LeftSidebarLayoutPage: NextPage = () => { | |||||
const router = useRouter(); | |||||
const sidebarOpen = useMemo(() => router.query.open === 'sidebar', [router]); | |||||
return ( | |||||
<Layouts.LeftSidebar.Root | |||||
sidebarBaseWidget={ | |||||
<Widgets.LeftSidebarBase | |||||
span={Span.WIDE} | |||||
open={sidebarOpen} | |||||
style={{ | |||||
backgroundColor: 'inherit', | |||||
}} | |||||
> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
Sidebar | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</Widgets.LeftSidebarBase> | |||||
} | |||||
topBarWidget={ | |||||
<Widgets.TopBar | |||||
brand={ | |||||
<Brand /> | |||||
} | |||||
style={{ | |||||
backgroundColor: 'inherit', | |||||
}} | |||||
menuLink={ | |||||
<Link | |||||
href={{ | |||||
query: { | |||||
open: 'sidebar', | |||||
}, | |||||
}} | |||||
> | |||||
Open | |||||
</Link> | |||||
} | |||||
span={Span.WIDE} | |||||
> | |||||
<DummyLinks /> | |||||
</Widgets.TopBar> | |||||
} | |||||
> | |||||
<Layouts.LeftSidebar.MainContentContainer> | |||||
Hello | |||||
</Layouts.LeftSidebar.MainContentContainer> | |||||
</Layouts.LeftSidebar.Root> | |||||
) | |||||
} | |||||
export default LeftSidebarLayoutPage |
@@ -0,0 +1,44 @@ | |||||
import type { NextPage } from 'next' | |||||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||||
import {Span} from '@tesseract-design/viewfinder-base'; | |||||
import Link from 'next/link'; | |||||
import {Brand} from '../../components/Brand'; | |||||
import {DummyLinks} from '../../components/DummyLinks'; | |||||
const RightSidebarStaticLayoutPage: NextPage = () => { | |||||
return ( | |||||
<Layouts.RightSidebarStatic.Root | |||||
sidebarBaseWidget={ | |||||
<Widgets.RightSidebarStaticBase | |||||
span={Span.WIDE} | |||||
style={{ | |||||
backgroundColor: 'inherit', | |||||
}} | |||||
> | |||||
<Layouts.RightSidebarStatic.SidebarContentContainer> | |||||
Sidebar | |||||
</Layouts.RightSidebarStatic.SidebarContentContainer> | |||||
</Widgets.RightSidebarStaticBase> | |||||
} | |||||
topBarWidget={ | |||||
<Widgets.TopBar | |||||
brand={ | |||||
<Brand /> | |||||
} | |||||
style={{ | |||||
backgroundColor: 'inherit', | |||||
}} | |||||
span={Span.WIDE} | |||||
> | |||||
<DummyLinks /> | |||||
</Widgets.TopBar> | |||||
} | |||||
> | |||||
<Layouts.RightSidebarStatic.MainContentContainer> | |||||
Hello | |||||
</Layouts.RightSidebarStatic.MainContentContainer> | |||||
</Layouts.RightSidebarStatic.Root> | |||||
) | |||||
} | |||||
export default RightSidebarStaticLayoutPage |
@@ -0,0 +1,129 @@ | |||||
.container { | |||||
padding: 0 2rem; | |||||
} | |||||
.main { | |||||
min-height: 100vh; | |||||
padding: 4rem 0; | |||||
flex: 1; | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: center; | |||||
align-items: center; | |||||
} | |||||
.footer { | |||||
display: flex; | |||||
flex: 1; | |||||
padding: 2rem 0; | |||||
border-top: 1px solid #eaeaea; | |||||
justify-content: center; | |||||
align-items: center; | |||||
} | |||||
.footer a { | |||||
display: flex; | |||||
justify-content: center; | |||||
align-items: center; | |||||
flex-grow: 1; | |||||
} | |||||
.title a { | |||||
color: #0070f3; | |||||
text-decoration: none; | |||||
} | |||||
.title a:hover, | |||||
.title a:focus, | |||||
.title a:active { | |||||
text-decoration: underline; | |||||
} | |||||
.title { | |||||
margin: 0; | |||||
line-height: 1.15; | |||||
font-size: 4rem; | |||||
} | |||||
.title, | |||||
.description { | |||||
text-align: center; | |||||
} | |||||
.description { | |||||
margin: 4rem 0; | |||||
line-height: 1.5; | |||||
font-size: 1.5rem; | |||||
} | |||||
.code { | |||||
background: #fafafa; | |||||
border-radius: 5px; | |||||
padding: 0.75rem; | |||||
font-size: 1.1rem; | |||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, | |||||
Bitstream Vera Sans Mono, Courier New, monospace; | |||||
} | |||||
.grid { | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: center; | |||||
flex-wrap: wrap; | |||||
max-width: 800px; | |||||
} | |||||
.card { | |||||
margin: 1rem; | |||||
padding: 1.5rem; | |||||
text-align: left; | |||||
color: inherit; | |||||
text-decoration: none; | |||||
border: 1px solid #eaeaea; | |||||
border-radius: 10px; | |||||
transition: color 0.15s ease, border-color 0.15s ease; | |||||
max-width: 300px; | |||||
} | |||||
.card:hover, | |||||
.card:focus, | |||||
.card:active { | |||||
color: #0070f3; | |||||
border-color: #0070f3; | |||||
} | |||||
.card h2 { | |||||
margin: 0 0 1rem 0; | |||||
font-size: 1.5rem; | |||||
} | |||||
.card p { | |||||
margin: 0; | |||||
font-size: 1.25rem; | |||||
line-height: 1.5; | |||||
} | |||||
.logo { | |||||
height: 1em; | |||||
margin-left: 0.5rem; | |||||
} | |||||
@media (max-width: 600px) { | |||||
.grid { | |||||
width: 100%; | |||||
flex-direction: column; | |||||
} | |||||
} | |||||
@media (prefers-color-scheme: dark) { | |||||
.card, | |||||
.footer { | |||||
border-color: #222; | |||||
} | |||||
.code { | |||||
background: #111; | |||||
} | |||||
.logo img { | |||||
filter: invert(1); | |||||
} | |||||
} |
@@ -0,0 +1,30 @@ | |||||
:root { | |||||
--base-width: 360px; | |||||
} | |||||
html, | |||||
body { | |||||
padding: 0; | |||||
margin: 0; | |||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, | |||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; | |||||
} | |||||
a { | |||||
color: inherit; | |||||
text-decoration: none; | |||||
} | |||||
* { | |||||
box-sizing: border-box; | |||||
} | |||||
@media (prefers-color-scheme: dark) { | |||||
html { | |||||
color-scheme: dark; | |||||
} | |||||
body { | |||||
color: white; | |||||
background: black; | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
{ | |||||
"compilerOptions": { | |||||
"target": "es5", | |||||
"lib": ["dom", "dom.iterable", "esnext"], | |||||
"allowJs": true, | |||||
"skipLibCheck": true, | |||||
"strict": true, | |||||
"forceConsistentCasingInFileNames": true, | |||||
"noEmit": true, | |||||
"esModuleInterop": true, | |||||
"module": "esnext", | |||||
"moduleResolution": "node", | |||||
"resolveJsonModule": true, | |||||
"isolatedModules": true, | |||||
"jsx": "preserve", | |||||
"incremental": true | |||||
}, | |||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], | |||||
"exclude": ["node_modules"] | |||||
} |
@@ -0,0 +1,79 @@ | |||||
{ | |||||
"name": "@tesseract-design/viewfinder-react", | |||||
"version": "0.0.0", | |||||
"files": [ | |||||
"dist", | |||||
"src" | |||||
], | |||||
"engines": { | |||||
"node": ">=10" | |||||
}, | |||||
"license": "MIT", | |||||
"keywords": [ | |||||
"pridepack" | |||||
], | |||||
"dependencies": { | |||||
"@tesseract-design/viewfinder-base": "*" | |||||
}, | |||||
"devDependencies": { | |||||
"@testing-library/jest-dom": "^5.16.4", | |||||
"@testing-library/react": "^13.3.0", | |||||
"@testing-library/react-hooks": "^8.0.1", | |||||
"@types/node": "^18.0.0", | |||||
"@types/react": "^18.0.14", | |||||
"eslint": "^8.20.0", | |||||
"eslint-config-lxsmnsyc": "^0.4.7", | |||||
"jsdom": "^20.0.0", | |||||
"pridepack": "2.2.1", | |||||
"react": "^18.2.0", | |||||
"react-dom": "^18.2.0", | |||||
"react-test-renderer": "^18.2.0", | |||||
"tslib": "^2.4.0", | |||||
"typescript": "^4.7.4", | |||||
"vitest": "^0.19.1" | |||||
}, | |||||
"peerDependencies": { | |||||
"react": "^16.8 || ^17.0 || ^18.0", | |||||
"react-dom": "^16.8 || ^17.0 || ^18.0" | |||||
}, | |||||
"scripts": { | |||||
"prepublishOnly": "pridepack clean && pridepack build", | |||||
"build": "pridepack build", | |||||
"type-check": "pridepack check", | |||||
"lint": "pridepack lint", | |||||
"clean": "pridepack clean", | |||||
"watch": "pridepack watch", | |||||
"start": "pridepack start", | |||||
"dev": "pridepack dev", | |||||
"test": "vitest" | |||||
}, | |||||
"private": false, | |||||
"description": "View scaffolding for React", | |||||
"repository": { | |||||
"url": "", | |||||
"type": "git" | |||||
}, | |||||
"homepage": "", | |||||
"bugs": { | |||||
"url": "" | |||||
}, | |||||
"author": "TheoryOfNekomata <allan.crisostomo@outlook.com>", | |||||
"publishConfig": { | |||||
"access": "public" | |||||
}, | |||||
"types": "./dist/types/index.d.ts", | |||||
"exports": { | |||||
".": { | |||||
"development": { | |||||
"require": "./dist/cjs/development/index.js", | |||||
"import": "./dist/esm/development/index.js" | |||||
}, | |||||
"require": "./dist/cjs/production/index.js", | |||||
"import": "./dist/esm/production/index.js", | |||||
"types": "./dist/types/index.d.ts" | |||||
} | |||||
}, | |||||
"typesVersions": { | |||||
"*": {} | |||||
} | |||||
} |
@@ -0,0 +1,3 @@ | |||||
{ | |||||
"target": "es2017" | |||||
} |
@@ -0,0 +1,3 @@ | |||||
export * as Layouts from './layouts'; | |||||
export * as Widgets from './widgets'; | |||||
@@ -0,0 +1,52 @@ | |||||
import * as React from 'react'; | |||||
import {LayoutArgs, layouts, Span} from '@tesseract-design/viewfinder-base'; | |||||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||||
topBarWidget?: React.ReactNode; | |||||
} | |||||
export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||||
children, | |||||
topBarWidget, | |||||
...etcProps | |||||
}, ref) => ( | |||||
<> | |||||
{topBarWidget} | |||||
<main | |||||
{...etcProps} | |||||
className={layouts.Basic.ContentBase()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</main> | |||||
</> | |||||
)); | |||||
Root.displayName = 'Root'; | |||||
export type ContentContainerProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||||
span?: Span, | |||||
} | |||||
export const ContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||||
children, | |||||
span = Span.NORMAL, | |||||
}, ref) => { | |||||
const args = React.useMemo<LayoutArgs>(() => ({ | |||||
span, | |||||
mainSidebarOpen: false, | |||||
}), [ | |||||
span | |||||
]); | |||||
return ( | |||||
<div | |||||
className={layouts.Basic.ContentContainer(args)} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
) | |||||
}); | |||||
ContentContainer.displayName = 'ContentContainer' |
@@ -0,0 +1,60 @@ | |||||
import * as React from 'react'; | |||||
import {layouts} from '@tesseract-design/viewfinder-base'; | |||||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||||
sidebarBaseWidget?: React.ReactNode; | |||||
topBarWidget?: React.ReactNode; | |||||
}; | |||||
export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||||
children, | |||||
topBarWidget, | |||||
sidebarBaseWidget, | |||||
...etcProps | |||||
}, ref) => { | |||||
return ( | |||||
<> | |||||
{topBarWidget} | |||||
{sidebarBaseWidget} | |||||
<main | |||||
{...etcProps} | |||||
ref={ref} | |||||
className={layouts.LeftSidebar.ContentBase()} | |||||
> | |||||
{children} | |||||
</main> | |||||
</> | |||||
) | |||||
}); | |||||
export type ContentContainerProps = React.HTMLProps<HTMLDivElement> & {} | |||||
export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||||
children, | |||||
}, ref) => ( | |||||
<div | |||||
className={layouts.LeftSidebar.ContentContainer()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
)); | |||||
MainContentContainer.displayName = 'MainContentContainer' | |||||
export type SidebarMainContainerProps = React.HTMLProps<HTMLDivElement> & {} | |||||
export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarMainContainerProps>(({ | |||||
children, | |||||
...etcProps | |||||
}, ref) => ( | |||||
<div | |||||
{...etcProps} | |||||
className={layouts.LeftSidebar.SidebarMainContainer()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
)); | |||||
SidebarContentContainer.displayName = 'SidebarMainContainer'; |
@@ -0,0 +1,60 @@ | |||||
import * as React from 'react'; | |||||
import {layouts} from '@tesseract-design/viewfinder-base'; | |||||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||||
sidebarBaseWidget?: React.ReactNode; | |||||
topBarWidget?: React.ReactNode; | |||||
}; | |||||
export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||||
children, | |||||
topBarWidget, | |||||
sidebarBaseWidget, | |||||
...etcProps | |||||
}, ref) => { | |||||
return ( | |||||
<> | |||||
{topBarWidget} | |||||
{sidebarBaseWidget} | |||||
<main | |||||
{...etcProps} | |||||
ref={ref} | |||||
className={layouts.LeftSidebarWithMenu.ContentBase()} | |||||
> | |||||
{children} | |||||
</main> | |||||
</> | |||||
) | |||||
}); | |||||
export type ContentContainerProps = React.HTMLProps<HTMLDivElement> & {} | |||||
export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||||
children, | |||||
}, ref) => ( | |||||
<div | |||||
className={layouts.LeftSidebarWithMenu.ContentContainer()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
)); | |||||
MainContentContainer.displayName = 'MainContentContainer' | |||||
export type SidebarMainContainerProps = React.HTMLProps<HTMLDivElement> & {} | |||||
export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarMainContainerProps>(({ | |||||
children, | |||||
...etcProps | |||||
}, ref) => ( | |||||
<div | |||||
{...etcProps} | |||||
className={layouts.LeftSidebarWithMenu.SidebarMainContainer()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
)); | |||||
SidebarContentContainer.displayName = 'SidebarMainContainer'; |
@@ -0,0 +1,61 @@ | |||||
import * as React from 'react'; | |||||
import {layouts} from '@tesseract-design/viewfinder-base'; | |||||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||||
sidebarBaseWidget?: React.ReactNode; | |||||
topBarWidget?: React.ReactNode; | |||||
}; | |||||
export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||||
children, | |||||
topBarWidget, | |||||
sidebarBaseWidget, | |||||
...etcProps | |||||
}, ref) => { | |||||
return ( | |||||
<> | |||||
{topBarWidget} | |||||
<main | |||||
{...etcProps} | |||||
ref={ref} | |||||
className={layouts.RightSidebarStatic.ContentBase()} | |||||
> | |||||
{children} | |||||
</main> | |||||
{sidebarBaseWidget} | |||||
</> | |||||
) | |||||
}) | |||||
export type ContentContainerProps = React.HTMLProps<HTMLDivElement> & {} | |||||
export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||||
children, | |||||
}, ref) => ( | |||||
<div | |||||
className={layouts.RightSidebarStatic.ContentContainer()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
)); | |||||
MainContentContainer.displayName = 'MainContentContainer' | |||||
export type SidebarMainContainerProps = React.HTMLProps<HTMLDivElement> & {} | |||||
export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarMainContainerProps>(({ | |||||
children, | |||||
...etcProps | |||||
}, ref) => ( | |||||
<div | |||||
{...etcProps} | |||||
className={layouts.RightSidebarStatic.SidebarMainContainer()} | |||||
ref={ref} | |||||
> | |||||
{children} | |||||
</div> | |||||
)); | |||||
SidebarContentContainer.displayName = 'SidebarMainContainer'; |
@@ -0,0 +1,4 @@ | |||||
export * as Basic from './Basic'; | |||||
export * as LeftSidebar from './LeftSidebar'; | |||||
export * as LeftSidebarWithMenu from './LeftSidebarWithMenu'; | |||||
export * as RightSidebarStatic from './RightSidebarStatic'; |
@@ -0,0 +1,37 @@ | |||||
import * as React from 'react'; | |||||
import {LayoutArgs, layouts, Span} from '@tesseract-design/viewfinder-base'; | |||||
export type LeftSidebarBaseProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||||
span?: Span, | |||||
} | |||||
export const LeftSidebarBase = React.forwardRef<HTMLDivElement, LeftSidebarBaseProps>(({ | |||||
children, | |||||
span = Span.WIDE, | |||||
open = false, | |||||
...etcProps | |||||
}, ref) => { | |||||
const args = React.useMemo<LayoutArgs>(() => ({ | |||||
span, | |||||
mainSidebarOpen: open, | |||||
}), [ | |||||
span, | |||||
open, | |||||
]); | |||||
return ( | |||||
<div | |||||
className={layouts.LeftSidebar.SidebarBase(args)} | |||||
{...etcProps} | |||||
ref={ref} | |||||
> | |||||
<div | |||||
className={layouts.LeftSidebar.SidebarOverflow()} | |||||
> | |||||
{children} | |||||
</div> | |||||
</div> | |||||
) | |||||
}); | |||||
LeftSidebarBase.displayName = 'LeftSidebarBase' |
@@ -0,0 +1,50 @@ | |||||
// TODO figure out how to refactor left sidebar with menu widget | |||||
import * as React from 'react'; | |||||
import {LayoutArgs, layouts, Span} from '@tesseract-design/viewfinder-base'; | |||||
export type LeftSidebarWithMenuBaseProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||||
span?: Span, | |||||
} | |||||
export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSidebarWithMenuBaseProps>(({ | |||||
children, | |||||
span = Span.WIDE, | |||||
open = false, | |||||
...etcProps | |||||
}, ref) => { | |||||
const args = React.useMemo<LayoutArgs>(() => ({ | |||||
span, | |||||
mainSidebarOpen: open, | |||||
}), [ | |||||
span, | |||||
open, | |||||
]); | |||||
return ( | |||||
<div | |||||
className={layouts.LeftSidebarWithMenu.SidebarBase()} | |||||
{...etcProps} | |||||
ref={ref} | |||||
> | |||||
<div | |||||
className={layouts.LeftSidebarWithMenu.SidebarMenu()} | |||||
> | |||||
<div | |||||
className={layouts.LeftSidebarWithMenu.SidebarMenuSize()} | |||||
> | |||||
// TODO | |||||
</div> | |||||
</div> | |||||
<div | |||||
className={layouts.LeftSidebarWithMenu.SidebarMain(args)} | |||||
> | |||||
<div | |||||
className={layouts.LeftSidebarWithMenu.SidebarMainOverflow()} | |||||
> | |||||
{children} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
) | |||||
}); |
@@ -0,0 +1,28 @@ | |||||
import * as React from 'react'; | |||||
import {layouts, Span} from '@tesseract-design/viewfinder-base'; | |||||
export type RightSidebarStaticBaseProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||||
span?: Span, | |||||
} | |||||
export const RightSidebarStaticBase = React.forwardRef<HTMLDivElement, RightSidebarStaticBaseProps>(({ | |||||
children, | |||||
span = Span.WIDE, | |||||
...etcProps | |||||
}, ref) => { | |||||
return ( | |||||
<div | |||||
className={layouts.RightSidebarStatic.SidebarBase()} | |||||
{...etcProps} | |||||
ref={ref} | |||||
> | |||||
<div | |||||
className={layouts.RightSidebarStatic.SidebarMainContent()} | |||||
> | |||||
{children} | |||||
</div> | |||||
</div> | |||||
) | |||||
}); | |||||
RightSidebarStaticBase.displayName = 'RightSidebarStaticBase' |
@@ -0,0 +1,66 @@ | |||||
import * as React from 'react'; | |||||
import {LayoutArgs, Span, widgets} from '@tesseract-design/viewfinder-base'; | |||||
export type TopBarProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||||
span?: Span, | |||||
brand?: React.ReactNode, | |||||
menuLink?: React.ReactNode, | |||||
userLink?: React.ReactNode, | |||||
} | |||||
export const TopBar = React.forwardRef<HTMLDivElement, TopBarProps>(({ | |||||
span = Span.NORMAL, | |||||
brand, | |||||
menuLink, | |||||
userLink, | |||||
children, | |||||
...etcProps | |||||
}, ref) => { | |||||
const args = React.useMemo<LayoutArgs>(() => ({ | |||||
span, | |||||
mainSidebarOpen: false, | |||||
}), [span]); | |||||
return ( | |||||
<div className={widgets.TopBar.Base()}> | |||||
<div | |||||
{...etcProps} | |||||
ref={ref} | |||||
> | |||||
<div className={widgets.TopBar.Container(args)}> | |||||
{ | |||||
Boolean(brand as unknown) | |||||
&& ( | |||||
<div> | |||||
{brand} | |||||
</div> | |||||
) | |||||
} | |||||
<div className={widgets.TopBar.CenterContainer()}> | |||||
{children} | |||||
</div> | |||||
<div className={widgets.TopBar.ActionContainer()}> | |||||
{ | |||||
Boolean(menuLink as unknown) | |||||
&& ( | |||||
<div className={widgets.TopBar.MenuLinkContainer()}> | |||||
{menuLink} | |||||
</div> | |||||
) | |||||
} | |||||
{ | |||||
Boolean(userLink as unknown) | |||||
&& ( | |||||
<div className={widgets.TopBar.LinkContainer()}> | |||||
{userLink} | |||||
</div> | |||||
) | |||||
} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
) | |||||
}) | |||||
TopBar.displayName = 'TopBar'; |
@@ -0,0 +1,3 @@ | |||||
export * from './LeftSidebarBase'; | |||||
export * from './RightSidebarBase'; | |||||
export * from './TopBar'; |
@@ -0,0 +1,21 @@ | |||||
{ | |||||
"exclude": ["node_modules"], | |||||
"include": ["src", "types"], | |||||
"compilerOptions": { | |||||
"module": "ESNext", | |||||
"lib": ["DOM", "ESNext"], | |||||
"importHelpers": true, | |||||
"declaration": true, | |||||
"sourceMap": true, | |||||
"rootDir": "./src", | |||||
"strict": true, | |||||
"noUnusedLocals": true, | |||||
"noUnusedParameters": true, | |||||
"noImplicitReturns": true, | |||||
"noFallthroughCasesInSwitch": true, | |||||
"moduleResolution": "node", | |||||
"jsx": "react", | |||||
"esModuleInterop": true, | |||||
"target": "ES2017" | |||||
} | |||||
} |
@@ -0,0 +1,8 @@ | |||||
/// <reference types="vitest" /> | |||||
export default ({ | |||||
test: { | |||||
global: true, | |||||
environment: 'jsdom', | |||||
}, | |||||
}); |