initial commit

This commit is contained in:
jrgarciadev 2021-04-22 10:07:22 -03:00
commit 26583faa40
29 changed files with 8239 additions and 0 deletions

17
.babelrc Normal file
View File

@ -0,0 +1,17 @@
{
"presets": ["next/babel"],
"plugins": [
[
"module-resolver",
{
"root": ["./"],
"alias": {
"@components": "./src/components",
"@hooks": "./src/hooks",
"@utils": "./src/utils",
"@theme": "./src/theme"
}
}
]
]
}

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

9
.eslintignore Normal file
View File

@ -0,0 +1,9 @@
.now/*
.next/*
examples/*
dist/*
esm/*
public/*
scripts/*
tests/*
*.config.js

79
.eslintrc Normal file
View File

@ -0,0 +1,79 @@
{
"plugins": ["prettier", "@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"ecmaFeatures": {
"jsx": true
}
},
"settings": {
"react": {
"pragma": "React",
"version": "detect"
},
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
}
}
},
"rules": {
"object-curly-spacing": ["warn", "always"],
"no-unused-vars": [
"warn",
{
"vars": "all",
"args": "none"
}
],
"@typescript-eslint/no-unused-vars": [
"warn",
{
"vars": "all",
"args": "none"
}
],
"@typescript-eslint/no-explicit-any": [
"error",
{
"ignoreRestArgs": true
}
],
"max-len": [
"warn",
{
"code": 80,
"ignoreStrings": true,
"ignoreTemplateLiterals": true,
"ignoreComments": true
}
],
"no-plusplus": [
"error",
{
"allowForLoopAfterthoughts": true
}
],
"react/jsx-key": "error",
"react/jsx-props-no-spreading": "off",
"import/prefer-default-export": "off",
"react/jsx-boolean-value": "off",
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
"react/jsx-one-expression-per-line": "off",
"react/jsx-wrap-multilines": "off",
"react/destructuring-assignment": "off",
"@typescript-eslint/comma-dangle": [
"error",
{
"arrays": "only-multiline",
"objects": "only-multiline",
"imports": "only-multiline",
"exports": "only-multiline",
"functions": "never"
}
]
}
}

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.now
dist
esm
examples/**/yarn.lock
examples/**/out
examples/**/.next

12
.prettierignore Normal file
View File

@ -0,0 +1,12 @@
.github
.next
.now
.circleci
dist
coverage
public
esm
*.json
*.d.ts
*.yml
*.snap

6
.prettierrc Normal file
View File

@ -0,0 +1,6 @@
{
"printWidth": 80,
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 2
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Next UI
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 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.

2
next-env.d.ts vendored Normal file
View File

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

5
next.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
future: {
webpack5: true,
},
};

95
package.json Normal file
View File

@ -0,0 +1,95 @@
{
"name": "nextui",
"version": "0.1.1",
"main": "dist/index.js",
"module": "esm/index.js",
"types": "dist/index.d.ts",
"unpkg": "dist/index.min.js",
"license": "MIT",
"description": "🚀 Beautiful and modern React UI library.",
"homepage": "https://nextui.org",
"bugs": {
"url": "https://github.com/jrgarciadev/next-ui/issues/new/choose"
},
"repository": {
"type": "git",
"url": "https://github.com/jrgarciadev/next-ui"
},
"keywords": [
"next",
"next ui",
"components",
"modern components",
"react components",
"react ui"
],
"scripts": {
"dev": "next dev",
"start": "next start",
"contributor-collect": "node scripts/collect-contributors.js",
"build:esm": "babel --config-file ./scripts/babel.config.js --extensions \".js,.ts,.tsx\" ./components --out-dir ./esm --ignore \"**/__tests__/**/*,**/*.d.ts\"",
"build:webpack": "webpack --config scripts/webpack.config.js",
"build:types": "tsc -p ./scripts",
"build": "yarn clear && yarn build:esm && yarn build:webpack && yarn build:types",
"clear": "rm -rf ./dist ./esm",
"lint": "eslint --ext .js,.jsx,.ts,.tsx src --color",
"format": "prettier --write 'src/**/*.{ts,tsx,scss,css,json}'",
"prettier": "prettier --write .",
"test": "jest --config .jest.config.js --no-cache",
"test-update": "jest --config .jest.config.js --no-cache --update-snapshot",
"coverage": "yarn test --coverage",
"release": "yarn build && yarn publish --access public --non-interactive"
},
"files": [
"/dist",
"/esm"
],
"dependencies": {
"styled-jsx": "^3.4.4"
},
"devDependencies": {
"@babel/cli": "^7.13.16",
"@babel/plugin-transform-runtime": "^7.13.15",
"@babel/preset-typescript": "^7.13.0",
"@babel/runtime": "^7.13.17",
"@mapbox/rehype-prism": "^0.6.0",
"@mdx-js/loader": "^1.6.22",
"@next/mdx": "^10.1.3",
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"@types/styled-jsx": "^2.2.8",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-plugin-module-resolver": "^4.1.0",
"eslint": "^7.24.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-prettier": "^8.2.0",
"eslint-config-react-app": "^6.0.0",
"eslint-config-ts-lambdas": "^1.2.3",
"eslint-import-resolver-typescript": "^2.4.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "^5.7.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"next": "^10.1.3",
"prettier": "^2.2.1",
"prettier-eslint": "^12.0.0",
"prettier-eslint-cli": "^5.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-local-resolve": "^1.0.7",
"typescript": "^4.2.4",
"webpack": "^5.35.0",
"webpack-cli": "^4.6.0"
}
}

15
pages/index.tsx Normal file
View File

@ -0,0 +1,15 @@
import React from 'react';
import Checkbox from '@components/checkbox';
const IndexPage = () => {
return (
<div>
<h1>Checkbox</h1>
<Checkbox checked={true} size="medium">
medium
</Checkbox>
</div>
);
};
export default IndexPage;

82
rollup.config.js Normal file
View File

@ -0,0 +1,82 @@
import commonjs from '@rollup/plugin-commonjs'
import nodeResolve from '@rollup/plugin-node-resolve'
import localResolve from 'rollup-plugin-local-resolve'
import babel from 'rollup-plugin-babel'
import fs from 'fs-extra'
import path from 'path'
const componentsPath = path.join(__dirname, 'components')
const distPath = path.join(__dirname, 'dist')
const extensions = ['.js', '.jsx', '.ts', '.tsx']
const plugins = [
babel({
exclude: 'node_modules/**',
extensions,
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],
plugins: ['styled-jsx/babel'],
}),
localResolve(),
nodeResolve({
browser: true,
extensions,
}),
commonjs(),
]
const globals = {
react: 'React',
'react-dom': 'ReactDOM',
}
const external = id => /^react|react-dom|styled-jsx|next\/link/.test(id)
const cjsOutput = {
format: 'cjs',
exports: 'named',
entryFileNames: '[name]/index.js',
dir: 'dist',
globals,
}
export default (async () => {
await fs.remove(distPath)
const files = await fs.readdir(componentsPath)
const components = await Promise.all(
files.map(async name => {
const comPath = path.join(componentsPath, name)
const entry = path.join(comPath, 'index.ts')
const stat = await fs.stat(comPath)
if (!stat.isDirectory()) return null
const hasFile = await fs.pathExists(entry)
if (!hasFile) return null
return { name, url: entry }
}),
)
return [
...components
.filter(r => r)
.map(({ name, url }) => ({
input: { [name]: url },
output: [cjsOutput],
external,
plugins,
})),
{
input: { index: path.join(componentsPath, 'index.ts') },
output: [
{
...cjsOutput,
entryFileNames: 'index.js',
},
],
external,
plugins,
},
]
})()

View File

@ -0,0 +1,21 @@
import React from 'react';
export interface CheckboxConfig {
updateState?: (value: string, checked: boolean) => void;
disabledAll: boolean;
values: string[];
inGroup: boolean;
}
const defaultContext = {
disabledAll: false,
inGroup: false,
values: [],
};
export const CheckboxContext = React.createContext<CheckboxConfig>(
defaultContext
);
export const useCheckbox = (): CheckboxConfig =>
React.useContext<CheckboxConfig>(CheckboxContext);

View File

@ -0,0 +1,85 @@
import React, { useEffect, useMemo, useState } from 'react';
import { CheckboxContext } from './checkbox-context';
import useWarning from '@hooks/use-warning';
import { NormalSizes } from '@utils/prop-types';
import withDefaults from '@utils/with-defaults';
interface Props {
value: string[];
disabled?: boolean;
size?: NormalSizes;
onChange?: (values: string[]) => void;
className?: string;
}
const defaultProps = {
disabled: false,
size: 'small' as NormalSizes,
className: '',
};
type NativeAttrs = Omit<React.HTMLAttributes<unknown>, keyof Props>;
export type CheckboxGroupProps = Props & typeof defaultProps & NativeAttrs;
export const getCheckboxSize = (size: NormalSizes): string => {
const sizes: { [key in NormalSizes]: string } = {
mini: '.75rem',
small: '.875rem',
medium: '1rem',
large: '1.125rem',
};
return sizes[size];
};
const CheckboxGroup: React.FC<React.PropsWithChildren<CheckboxGroupProps>> = ({
disabled,
onChange,
value,
size,
children,
className,
...props
}) => {
const [selfVal, setSelfVal] = useState<string[]>([]);
if (!value) {
value = [];
useWarning('Props "value" is required.', 'Checkbox Group');
}
const updateState = (val: string, checked: boolean) => {
const removed = selfVal.filter((v) => v !== val);
const next = checked ? [...removed, val] : removed;
setSelfVal(next);
onChange && onChange(next);
};
const providerValue = useMemo(() => {
return {
updateState,
disabledAll: disabled,
inGroup: true,
values: selfVal,
};
}, [disabled, selfVal]);
const fontSize = useMemo(() => getCheckboxSize(size), [size]);
useEffect(() => {
setSelfVal(value);
}, [value.join(',')]);
return (
<CheckboxContext.Provider value={providerValue}>
<div className={`group ${className}`} {...props}>
{children}
<style jsx>{`
.group :global(label) {
margin-right: calc(${fontSize} * 2);
--checkbox-size: ${fontSize};
}
`}</style>
</div>
</CheckboxContext.Provider>
);
};
export default withDefaults(CheckboxGroup, defaultProps);

View File

@ -0,0 +1,54 @@
import React, { useMemo } from 'react';
import useTheme from '@hooks/use-theme';
interface Props {
disabled?: boolean;
checked?: boolean;
}
const CheckboxIcon: React.FC<Props> = ({ disabled, checked }) => {
const theme = useTheme();
const { fill, bg, stroke } = useMemo(() => {
return {
fill: theme.palette.foreground,
bg: theme.palette.background,
stroke: theme.palette.accents_5,
};
}, [theme.palette]);
return (
<>
{checked ? (
<svg viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.1429 0H3.85714C1.7269 0 0 1.79086 0 4V12C0 14.2091 1.7269 16 3.85714 16H12.1429C14.2731 16 16 14.2091 16 12V4C16 1.79086 14.2731 0 12.1429 0Z"
fill={fill}
/>
<path d="M16 3L7.72491 11L5 8" stroke={bg} strokeWidth="1.5" />
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" fill="none">
<path
d="M8.5 0.5H3.5C1.84315 0.5 0.5 1.84315 0.5 3.5V8.5C0.5 10.1569 1.84315 11.5 3.5 11.5H8.5C10.1569 11.5 11.5 10.1569 11.5 8.5V3.5C11.5 1.84315 10.1569 0.5 8.5 0.5Z"
stroke={stroke}
/>
</svg>
)}
<style jsx>{`
svg {
display: inline-flex;
width: calc(0.86 * var(--checkbox-size));
height: calc(0.86 * var(--checkbox-size));
user-select: none;
opacity: ${disabled ? 0.4 : 1};
cursor: ${disabled ? 'not-allowed' : 'pointer'};
}
`}</style>
</>
);
};
const MemoCheckboxIcon = React.memo(CheckboxIcon);
export default MemoCheckboxIcon;

View File

@ -0,0 +1,155 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useCheckbox } from './checkbox-context';
import CheckboxGroup, { getCheckboxSize } from './checkbox-group';
import CheckboxIcon from './checkbox-icon';
import useWarning from '@hooks/use-warning';
import { NormalSizes } from '@utils/prop-types';
interface CheckboxEventTarget {
checked: boolean;
}
export interface CheckboxEvent {
target: CheckboxEventTarget;
stopPropagation: () => void;
preventDefault: () => void;
nativeEvent: React.ChangeEvent;
}
interface Props {
checked?: boolean;
disabled?: boolean;
initialChecked?: boolean;
onChange?: (e: CheckboxEvent) => void;
size?: NormalSizes;
className?: string;
value?: string;
}
const defaultProps = {
disabled: false,
initialChecked: false,
size: 'small' as NormalSizes,
className: '',
value: '',
};
type NativeAttrs = Omit<React.InputHTMLAttributes<unknown>, keyof Props>;
export type CheckboxProps = Props & typeof defaultProps & NativeAttrs;
const Checkbox: React.FC<CheckboxProps> = ({
checked,
initialChecked,
disabled,
onChange,
className,
children,
size,
value,
...props
}) => {
const [selfChecked, setSelfChecked] = useState<boolean>(initialChecked);
const { updateState, inGroup, disabledAll, values } = useCheckbox();
const isDisabled = inGroup ? disabledAll || disabled : disabled;
if (inGroup && checked) {
useWarning(
'Remove props "checked" when [Checkbox] component is in the group.',
'Checkbox'
);
}
if (inGroup) {
useEffect(() => {
const next = values.includes(value);
if (next === selfChecked) return;
setSelfChecked(next);
}, [values.join(',')]);
}
const fontSize = useMemo(() => getCheckboxSize(size), [size]);
const changeHandle = useCallback(
(ev: React.ChangeEvent) => {
if (isDisabled) return;
const selfEvent: CheckboxEvent = {
target: {
checked: !selfChecked,
},
stopPropagation: ev.stopPropagation,
preventDefault: ev.preventDefault,
nativeEvent: ev,
};
if (inGroup && updateState) {
updateState && updateState(value, !selfChecked);
}
setSelfChecked(!selfChecked);
onChange && onChange(selfEvent);
},
[updateState, onChange, isDisabled, selfChecked]
);
useEffect(() => {
if (checked === undefined) return;
setSelfChecked(checked);
}, [checked]);
return (
<label className={`${className}`}>
<CheckboxIcon disabled={isDisabled} checked={selfChecked} />
<input
type="checkbox"
disabled={isDisabled}
checked={selfChecked}
onChange={changeHandle}
{...props}
/>
<span className="text">{children}</span>
<style jsx>{`
label {
--checkbox-size: ${fontSize};
display: inline-flex;
justify-content: center;
align-items: center;
width: auto;
cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
opacity: ${isDisabled ? 0.75 : 1};
height: var(--checkbox-size);
line-height: var(--checkbox-size);
}
.text {
font-size: var(--checkbox-size);
line-height: var(--checkbox-size);
padding-left: calc(var(--checkbox-size) * 0.57);
user-select: none;
cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
}
input {
opacity: 0;
outline: none;
position: absolute;
width: 0;
height: 0;
margin: 0;
padding: 0;
z-index: -1;
background-color: transparent;
}
`}</style>
</label>
);
};
Checkbox.defaultProps = defaultProps;
type CheckboxComponent<P = {}> = React.FC<P> & {
Group: typeof CheckboxGroup;
};
type ComponentProps = Partial<typeof defaultProps> &
Omit<Props, keyof typeof defaultProps> &
NativeAttrs;
export default Checkbox as CheckboxComponent<ComponentProps>;

View File

@ -0,0 +1,10 @@
import Checkbox from './checkbox'
import CheckboxGroup from './checkbox-group'
import { CheckboxProps, CheckboxEvent } from './checkbox'
export type Props = CheckboxProps
export type Event = CheckboxEvent
Checkbox.Group = CheckboxGroup
export default Checkbox

1
src/components/index.ts Normal file
View File

@ -0,0 +1 @@
export { default as Checkbox } from './checkbox';

7
src/hooks/use-theme.ts Normal file
View File

@ -0,0 +1,7 @@
import React from 'react'
import ThemeContext from '@theme/theme-context'
import { NextUIThemes } from '@theme/index'
const useTheme = (): NextUIThemes => React.useContext<NextUIThemes>(ThemeContext)
export default useTheme

16
src/hooks/use-warning.ts Normal file
View File

@ -0,0 +1,16 @@
const warningStack: { [key: string]: boolean } = {}
const useWarning = (message: string, component?: string) => {
const tag = component ? ` [${component}]` : ' '
const log = `[Next UI]${tag}: ${message}`
if (typeof console === 'undefined') return
if (warningStack[log]) return
warningStack[log] = true
if (process.env.NODE_ENV !== 'production') {
return console.error(log)
}
console.warn(log)
}
export default useWarning

72
src/theme/default.ts Normal file
View File

@ -0,0 +1,72 @@
import { NextUIThemes, NextUIThemesPalette, NextUIThemesExpressiveness } from './index'
import { defaultFont, defaultBreakpoints, defaultLayout } from './shared'
export const palette: NextUIThemesPalette = {
accents_1: '#fafafa',
accents_2: '#eaeaea',
accents_3: '#999',
accents_4: '#888',
accents_5: '#666',
accents_6: '#444',
accents_7: '#333',
accents_8: '#111',
background: '#fff',
foreground: '#000',
selection: '#79ffe1',
secondary: '#666',
code: '#f81ce5',
border: '#eaeaea',
error: '#e00',
errorLight: '#ff1a1a',
errorLighter: '#f7d4d6',
errorDark: '#c50000',
success: '#0070f3',
successLight: '#3291ff',
successLighter: '#d3e5ff',
successDark: '#0761d1',
warning: '#f5a623',
warningLight: '#f7b955',
warningLighter: '#ffefcf',
warningDark: '#ab570a',
cyan: '#50e3c2',
cyanLighter: '#aaffec',
cyanLight: '#79ffe1',
cyanDark: '#29bc9b',
violet: '#7928ca',
violetLighter: '#e3d7fc',
violetLight: '#8a63d2',
violetDark: '#4c2889',
purple: '#f81ce5',
alert: '#ff0080',
magenta: '#eb367f',
link: '#0070f3',
}
export const expressiveness: NextUIThemesExpressiveness = {
linkStyle: 'none',
linkHoverStyle: 'none',
dropdownBoxShadow: '0 4px 4px 0 rgba(0, 0, 0, 0.02)',
scrollerStart: 'rgba(255, 255, 255, 1)',
scrollerEnd: 'rgba(255, 255, 255, 0)',
shadowSmall: '0 5px 10px rgba(0, 0, 0, 0.12)',
shadowMedium: '0 8px 30px rgba(0, 0, 0, 0.12)',
shadowLarge: '0 30px 60px rgba(0, 0, 0, 0.12)',
portalOpacity: 0.25,
}
export const font = defaultFont
export const breakpoints = defaultBreakpoints
export const layout = defaultLayout
export const themes: NextUIThemes = {
type: 'light',
font,
layout,
palette,
breakpoints,
expressiveness,
}
export default themes

96
src/theme/index.ts Normal file
View File

@ -0,0 +1,96 @@
import { ThemeTypes } from '@utils/prop-types'
export interface NextUIThemesPalette {
accents_1: string
accents_2: string
accents_3: string
accents_4: string
accents_5: string
accents_6: string
accents_7: string
accents_8: string
background: string
foreground: string
selection: string
secondary: string
code: string
border: string
success: string
successLighter: string
successLight: string
successDark: string
error: string
errorLighter: string
errorLight: string
errorDark: string
warning: string
warningLighter: string
warningLight: string
warningDark: string
cyan: string
cyanLighter: string
cyanLight: string
cyanDark: string
violet: string
violetLighter: string
violetLight: string
violetDark: string
link: string
purple: string
magenta: string
alert: string
}
export interface NextUIThemesExpressiveness {
linkStyle: string
linkHoverStyle: string
dropdownBoxShadow: string
scrollerStart: string
scrollerEnd: string
shadowSmall: string
shadowMedium: string
shadowLarge: string
portalOpacity: number
}
export interface NextUIThemesLayout {
gap: string
gapNegative: string
gapHalf: string
gapHalfNegative: string
gapQuarter: string
gapQuarterNegative: string
pageMargin: string
pageWidth: string
pageWidthWithMargin: string
breakpointMobile: string
breakpointTablet: string
radius: string
}
export interface NextUIThemesFont {
sans: string
mono: string
}
export interface BreakpointsItem {
min: string
max: string
}
export interface NextUIThemesBreakpoints {
xs: BreakpointsItem
sm: BreakpointsItem
md: BreakpointsItem
lg: BreakpointsItem
xl: BreakpointsItem
}
export interface NextUIThemes {
type: ThemeTypes
font: NextUIThemesFont
layout: NextUIThemesLayout
palette: NextUIThemesPalette
breakpoints: NextUIThemesBreakpoints
expressiveness: NextUIThemesExpressiveness
}

51
src/theme/shared.ts Normal file
View File

@ -0,0 +1,51 @@
import {
NextUIThemesBreakpoints,
NextUIThemesFont,
NextUIThemesLayout,
} from './index'
export const defaultFont: NextUIThemesFont = {
sans:
'-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',
mono:
'Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace',
}
export const defaultBreakpoints: NextUIThemesBreakpoints = {
xs: {
min: '0',
max: '650px',
},
sm: {
min: '650px',
max: '900px',
},
md: {
min: '900px',
max: '1280px',
},
lg: {
min: '1280px',
max: '1920px',
},
xl: {
min: '1920px',
max: '10000px',
},
}
export const defaultLayout: NextUIThemesLayout = {
gap: '16pt',
gapNegative: '-16pt',
gapHalf: '8pt',
gapHalfNegative: '-8pt',
gapQuarter: '4pt',
gapQuarterNegative: '-4pt',
pageMargin: '16pt',
pageWidth: '750pt',
pageWidthWithMargin: '782pt',
breakpointMobile: defaultBreakpoints.xs.max,
breakpointTablet: defaultBreakpoints.sm.max,
radius: '5px',
}

View File

@ -0,0 +1,7 @@
import React from 'react'
import { NextUIThemes } from './index'
import defaultTheme from './default'
const ThemeContext: React.Context<NextUIThemes> = React.createContext<NextUIThemes>(defaultTheme)
export default ThemeContext

77
src/utils/prop-types.ts Normal file
View File

@ -0,0 +1,77 @@
export const tuple = <T extends string[]>(...args: T) => args
const buttonTypes = tuple(
'default',
'secondary',
'success',
'warning',
'error',
'abort',
'secondary-light',
'success-light',
'warning-light',
'error-light',
)
const normalSizes = tuple('mini', 'small', 'medium', 'large')
const normalTypes = tuple('default', 'secondary', 'success', 'warning', 'error')
const themeTypes = tuple('dark', 'light')
const snippetTypes = tuple('default', 'secondary', 'success', 'warning', 'error', 'dark', 'lite')
const cardTypes = tuple(
'default',
'secondary',
'success',
'warning',
'error',
'dark',
'lite',
'alert',
'purple',
'violet',
'cyan',
)
const copyTypes = tuple('default', 'slient', 'prevent')
const triggerTypes = tuple('hover', 'click')
const placement = tuple(
'top',
'topStart',
'topEnd',
'left',
'leftStart',
'leftEnd',
'bottom',
'bottomStart',
'bottomEnd',
'right',
'rightStart',
'rightEnd',
)
const dividerAlign = tuple('start', 'center', 'end', 'left', 'right')
export type ButtonTypes = typeof buttonTypes[number]
export type NormalSizes = typeof normalSizes[number]
export type NormalTypes = typeof normalTypes[number]
export type ThemeTypes = typeof themeTypes[number]
export type SnippetTypes = typeof snippetTypes[number]
export type CardTypes = typeof cardTypes[number]
export type CopyTypes = typeof copyTypes[number]
export type TriggerTypes = typeof triggerTypes[number]
export type Placement = typeof placement[number]
export type DividerAlign = typeof dividerAlign[number]

View File

@ -0,0 +1,9 @@
import React from 'react'
const withDefaults = <P, DP>(component: React.ComponentType<P>, defaultProps: DP) => {
type Props = Partial<DP> & Omit<P, keyof DP>
component.defaultProps = defaultProps
return component as React.ComponentType<Props>
}
export default withDefaults

47
tsconfig.json Normal file
View File

@ -0,0 +1,47 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["./src/components/*"],
"@hooks/*": ["./src/hooks/*"],
"@utils/*": ["./src/utils/*"],
"@theme/*": ["./src/theme/*"]
},
"strictNullChecks": true,
"moduleResolution": "node",
"esModuleInterop": true,
"experimentalDecorators": true,
"jsx": "preserve",
"noUnusedParameters": true,
"noUnusedLocals": true,
"noImplicitAny": true,
"target": "es6",
"lib": [
"dom",
"es2017"
],
"skipLibCheck": true,
"allowJs": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"module": "esnext",
"resolveJsonModule": true,
"isolatedModules": true,
"typeRoots": [
"node_modules/@types",
"./typings"
]
},
"exclude": ["node_modules"],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx",
"src/**/*.tsx"
],
}

7142
yarn.lock Normal file

File diff suppressed because it is too large Load Diff