initial
This commit is contained in:
parent
c32b784f8b
commit
d516397d3e
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"editor.detectIndentation": false,
|
||||||
|
"editor.insertSpaces": false,
|
||||||
|
"eslint.format.enable": true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export default {
|
||||||
|
base: '/',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="root">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="module" src="./src/index.tsx"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "materialnext",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/styled": "^11.13.5",
|
||||||
|
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||||
|
"@lit/react": "^1.0.7",
|
||||||
|
"@material/material-color-utilities": "^0.3.0",
|
||||||
|
"@material/web": "^2.2.0",
|
||||||
|
"@mui/material": "^6.1.6",
|
||||||
|
"@vitejs/plugin-react": "^4.3.3",
|
||||||
|
"beercss": "^3.7.12",
|
||||||
|
"classnames": "^2.5.1",
|
||||||
|
"material-dynamic-colors": "^1.1.2",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
|
"uuid": "^11.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-inject": "^5.0.5",
|
||||||
|
"@types/react": "^18.3.12",
|
||||||
|
"@types/react-dom": "^18.3.1",
|
||||||
|
"typescript": "^5.6.3",
|
||||||
|
"vite": "^5.4.11",
|
||||||
|
"vite-plugin-top-level-await": "^1.4.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import React, { CSSProperties, ReactNode } from 'react';
|
||||||
|
|
||||||
|
type BoxProps = {
|
||||||
|
style?: CSSProperties;
|
||||||
|
children: ReactNode;
|
||||||
|
display?: 'flex' | 'block' | 'inline-block' | 'inline' | 'grid' | 'inline-grid' | 'contents' | 'list-item' | 'hidden' | 'initial' | 'inherit';
|
||||||
|
flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
|
||||||
|
flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
|
||||||
|
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
|
||||||
|
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';
|
||||||
|
alignContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch' | 'baseline' | 'first baseline' | 'last baseline' | 'safe center' | 'unsafe center' | 'left' | 'right' | 'safe left' | 'safe right' | 'unsafe left' | 'unsafe right';
|
||||||
|
gap?: number;
|
||||||
|
rowGap?: number;
|
||||||
|
columnGap?: number;
|
||||||
|
flex?: number;
|
||||||
|
flexGrow?: number;
|
||||||
|
flexShrink?: number;
|
||||||
|
flexBasis?: 'auto' | 'content' | 'fit-content' | 'max-content' | 'min-content' | 'fill' | 'fit-content' | 'max-content' | 'min-content' | 'fill' | 'fit-content' | 'max-content' | 'min-content' | 'fill';
|
||||||
|
flexFlow?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
|
||||||
|
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';
|
||||||
|
order?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Box = ({ style, children, alignContent, alignSelf, justifyContent, alignItems, display, flex, flexBasis, flexDirection, flexFlow, flexGrow, flexShrink, flexWrap, gap, rowGap, columnGap, order }: BoxProps) => {
|
||||||
|
return (
|
||||||
|
<div style={{
|
||||||
|
...style,
|
||||||
|
display,
|
||||||
|
flexDirection,
|
||||||
|
flexWrap,
|
||||||
|
justifyContent,
|
||||||
|
alignItems,
|
||||||
|
alignContent,
|
||||||
|
gap,
|
||||||
|
rowGap,
|
||||||
|
columnGap,
|
||||||
|
flex,
|
||||||
|
flexGrow,
|
||||||
|
flexShrink,
|
||||||
|
flexBasis,
|
||||||
|
flexFlow,
|
||||||
|
alignSelf,
|
||||||
|
order,
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { createComponent } from '@lit/react';
|
||||||
|
import { MdFilledButton as MdFilledButtonWebComponent } from '@material/web/button/filled-button';
|
||||||
|
import { MdFilledTonalButton as MdFilledTonalButtonWebComponent } from '@material/web/button/filled-tonal-button';
|
||||||
|
import { MdElevatedButton as MdElevatedButtonWebComponent } from '@material/web/button/elevated-button';
|
||||||
|
import { MdOutlinedButton as MdOutlinedButtonWebComponent } from '@material/web/button/outlined-button';
|
||||||
|
import { MdTextButton as MdTextButtonWebComponent } from '@material/web/button/text-button';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const MdFilledButton = createComponent({
|
||||||
|
tagName: 'md-filled-button',
|
||||||
|
elementClass: MdFilledButtonWebComponent,
|
||||||
|
react: React,
|
||||||
|
});
|
||||||
|
|
||||||
|
const MdFilledTonalButton = createComponent({
|
||||||
|
tagName: 'md-filled-tonal-button',
|
||||||
|
elementClass: MdFilledTonalButtonWebComponent,
|
||||||
|
react: React,
|
||||||
|
});
|
||||||
|
|
||||||
|
const MdElevatedButton = createComponent({
|
||||||
|
tagName: 'md-elevated-button',
|
||||||
|
elementClass: MdElevatedButtonWebComponent,
|
||||||
|
react: React,
|
||||||
|
});
|
||||||
|
|
||||||
|
const MdOutlinedButton = createComponent({
|
||||||
|
tagName: 'md-outlined-button',
|
||||||
|
elementClass: MdOutlinedButtonWebComponent,
|
||||||
|
react: React,
|
||||||
|
});
|
||||||
|
|
||||||
|
const MdTextButton = createComponent({
|
||||||
|
tagName: 'md-text-button',
|
||||||
|
elementClass: MdTextButtonWebComponent,
|
||||||
|
react: React,
|
||||||
|
});
|
||||||
|
|
||||||
|
type ButtonProps = {
|
||||||
|
variant?: 'filled' | 'filled-tonal' | 'elevated' | 'outlined' | 'text';
|
||||||
|
children: React.ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
|
softDisabled?: boolean;
|
||||||
|
href?: string;
|
||||||
|
target?: '_blank' | '_parent' | '_self' | '_top';
|
||||||
|
type?: 'button' | 'submit' | 'reset';
|
||||||
|
value?: string;
|
||||||
|
onClick?: (e: React.MouseEvent) => void;
|
||||||
|
onMouseDown?: (e: React.MouseEvent) => void;
|
||||||
|
onMouseUp?: (e: React.MouseEvent) => void;
|
||||||
|
onMouseEnter?: (e: React.MouseEvent) => void;
|
||||||
|
onMouseLeave?: (e: React.MouseEvent) => void;
|
||||||
|
onFocus?: (e: React.FocusEvent) => void;
|
||||||
|
onBlur?: (e: React.FocusEvent) => void;
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
id?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Button = ({ variant, children, disabled, softDisabled, href, target, type, value, ...props }: ButtonProps) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'filled':
|
||||||
|
return <MdFilledButton {...props} disabled={disabled} softDisabled={softDisabled} href={href} target={target} type={type} value={value}>{children}</MdFilledButton>;
|
||||||
|
case 'filled-tonal':
|
||||||
|
return <MdFilledTonalButton {...props} disabled={disabled} softDisabled={softDisabled} href={href} target={target} type={type} value={value}>{children}</MdFilledTonalButton>;
|
||||||
|
case 'elevated':
|
||||||
|
return <MdElevatedButton {...props} disabled={disabled} softDisabled={softDisabled} href={href} target={target} type={type} value={value}>{children}</MdElevatedButton>;
|
||||||
|
case 'outlined':
|
||||||
|
return <MdOutlinedButton {...props} disabled={disabled} softDisabled={softDisabled} href={href} target={target} type={type} value={value}>{children}</MdOutlinedButton>;
|
||||||
|
case 'text':
|
||||||
|
return <MdTextButton {...props} disabled={disabled} softDisabled={softDisabled} href={href} target={target} type={type} value={value}>{children}</MdTextButton>;
|
||||||
|
default:
|
||||||
|
return <MdFilledButton {...props} disabled={disabled} softDisabled={softDisabled} href={href} target={target} type={type} value={value}>{children}</MdFilledButton>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
import React, { FormEvent, MouseEvent, FocusEvent } from "react";
|
||||||
|
import { createComponent } from "@lit/react";
|
||||||
|
import { MdCheckbox as MdCheckboxWebComponent } from "@material/web/checkbox/checkbox";
|
||||||
|
|
||||||
|
const MdCheckbox = createComponent({
|
||||||
|
tagName: "md-checkbox",
|
||||||
|
react: React,
|
||||||
|
elementClass: MdCheckboxWebComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
type CheckboxProps = {
|
||||||
|
checked?: boolean;
|
||||||
|
indeterminate?: boolean;
|
||||||
|
id?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
|
ariaLabel?: string;
|
||||||
|
ariaLabelledBy?: string;
|
||||||
|
ariaDescribedBy?: string;
|
||||||
|
ariaControls?: string;
|
||||||
|
required?: boolean;
|
||||||
|
onInput?: (e: FormEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onChange?: (e: FormEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onClick?: (e: MouseEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onMouseDown?: (e: MouseEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onMouseUp?: (e: MouseEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onMouseEnter?: (e: MouseEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onFocus?: (e: FocusEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
onBlur?: (e: FocusEvent<MdCheckboxWebComponent>) => void;
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
tabIndex?: number;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Checkbox = ({ checked, indeterminate, id, disabled, hidden, ariaLabel, ariaLabelledBy, ariaDescribedBy, ariaControls, required, onInput, onChange, onClick, onMouseDown, onMouseUp, onMouseEnter, onFocus, onBlur, className, style, tabIndex, name, ...props }: CheckboxProps) => {
|
||||||
|
return <MdCheckbox
|
||||||
|
{...props}
|
||||||
|
id={id}
|
||||||
|
value={checked ? 'on' : 'off'}
|
||||||
|
indeterminate={indeterminate}
|
||||||
|
disabled={disabled || false}
|
||||||
|
required={required}
|
||||||
|
checked={checked}
|
||||||
|
hidden={hidden}
|
||||||
|
touch-target='wrapper'
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
aria-labelledby={ariaLabelledBy}
|
||||||
|
aria-describedby={ariaDescribedBy}
|
||||||
|
aria-controls={ariaControls}
|
||||||
|
aria-required={required}
|
||||||
|
onInput={onInput}
|
||||||
|
onChange={onChange}
|
||||||
|
onClick={onClick}
|
||||||
|
onMouseDown={onMouseDown}
|
||||||
|
onMouseUp={onMouseUp}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onFocus={onFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
|
className={className}
|
||||||
|
style={style}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
name={name || undefined}
|
||||||
|
/>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { createComponent } from '@lit/react';
|
||||||
|
|
||||||
|
export const FormLabel = createComponent({
|
||||||
|
tagName: 'label',
|
||||||
|
react: React,
|
||||||
|
elementClass: HTMLLabelElement,
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React, { FormEvent, MouseEvent, FocusEvent } from "react";
|
||||||
|
import { createComponent } from "@lit/react";
|
||||||
|
import { MdSwitch as MdSwitchWebComponent } from "@material/web/switch/switch";
|
||||||
|
|
||||||
|
const MdSwitch = createComponent({
|
||||||
|
tagName: "md-switch",
|
||||||
|
react: React,
|
||||||
|
elementClass: MdSwitchWebComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
type SwitchProps = {
|
||||||
|
checked?: boolean;
|
||||||
|
id?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
|
ariaLabel?: string;
|
||||||
|
ariaLabelledBy?: string;
|
||||||
|
ariaDescribedBy?: string;
|
||||||
|
ariaControls?: string;
|
||||||
|
required?: boolean;
|
||||||
|
onInput?: (e: FormEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onChange?: (e: FormEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onClick?: (e: MouseEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onMouseDown?: (e: MouseEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onMouseUp?: (e: MouseEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onMouseEnter?: (e: MouseEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onFocus?: (e: FocusEvent<MdSwitchWebComponent>) => void;
|
||||||
|
onBlur?: (e: FocusEvent<MdSwitchWebComponent>) => void;
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
tabIndex?: number;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Switch = ({ checked, id, disabled, hidden, ariaLabel, ariaLabelledBy, ariaDescribedBy, ariaControls, required, onInput, onChange, onClick, onMouseDown, onMouseUp, onMouseEnter, onFocus, onBlur, className, style, tabIndex, name, ...props }: SwitchProps) => {
|
||||||
|
return <MdSwitch
|
||||||
|
{...props}
|
||||||
|
id={id}
|
||||||
|
disabled={disabled || false}
|
||||||
|
required={required}
|
||||||
|
selected={checked}
|
||||||
|
hidden={hidden}
|
||||||
|
touch-target='wrapper'
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
aria-labelledby={ariaLabelledBy}
|
||||||
|
aria-describedby={ariaDescribedBy}
|
||||||
|
aria-controls={ariaControls}
|
||||||
|
aria-required={required}
|
||||||
|
onInput={onInput}
|
||||||
|
onChange={onChange}
|
||||||
|
onClick={onClick}
|
||||||
|
onMouseDown={onMouseDown}
|
||||||
|
onMouseUp={onMouseUp}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onFocus={onFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
|
className={className}
|
||||||
|
style={style}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
name={name || undefined}
|
||||||
|
/>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React, { createContext, useContext } from "react";
|
||||||
|
|
||||||
|
const SchemeContext = createContext<'light' | 'dark'>('light');
|
||||||
|
|
||||||
|
export function SchemeProvider({ children, scheme }: { children: React.ReactNode, scheme: 'light' | 'dark' }) {
|
||||||
|
return (
|
||||||
|
<SchemeContext.Provider value={scheme}>{children}</SchemeContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useScheme() {
|
||||||
|
const scheme = useContext(SchemeContext);
|
||||||
|
return scheme;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { hexFromArgb, Theme } from "@material/material-color-utilities";
|
||||||
|
import React from "react";
|
||||||
|
import { createContext, useContext } from "react";
|
||||||
|
import { useScheme } from "./useScheme";
|
||||||
|
|
||||||
|
const ThemeContext = createContext<Theme | undefined>(undefined);
|
||||||
|
|
||||||
|
export function ThemeProvider({ children, theme, scheme }: { children: React.ReactNode, theme: Theme, scheme: 'dark' | 'light' }) {
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={theme}>
|
||||||
|
<style>
|
||||||
|
{`
|
||||||
|
body {
|
||||||
|
|
||||||
|
--md-ref-typeface-brand: 'Open Sans';
|
||||||
|
--md-ref-typeface-plain: system-ui;
|
||||||
|
|
||||||
|
--md-sys-color-primary: ${hexFromArgb(theme.schemes[scheme].primary)};
|
||||||
|
--md-sys-color-primary-container: ${hexFromArgb(theme.schemes[scheme].primaryContainer)};
|
||||||
|
--md-sys-color-secondary: ${hexFromArgb(theme.schemes[scheme].secondary)};
|
||||||
|
--md-sys-color-secondary-container: ${hexFromArgb(theme.schemes[scheme].secondaryContainer)};
|
||||||
|
--md-sys-color-tertiary: ${hexFromArgb(theme.schemes[scheme].tertiary)};
|
||||||
|
--md-sys-color-tertiary-container: ${hexFromArgb(theme.schemes[scheme].tertiaryContainer)};
|
||||||
|
--md-sys-color-error: ${hexFromArgb(theme.schemes[scheme].error)};
|
||||||
|
--md-sys-color-error-container: ${hexFromArgb(theme.schemes[scheme].errorContainer)};
|
||||||
|
--md-sys-color-background: ${hexFromArgb(theme.schemes[scheme].background)};
|
||||||
|
--md-sys-color-surface: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-bright: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-dim: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-container: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-container-lowest: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-container-low: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-container-high: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-surface-container-highest: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
--md-sys-color-outline: ${hexFromArgb(theme.schemes[scheme].outline)};
|
||||||
|
--md-sys-color-outline-variant: ${hexFromArgb(theme.schemes[scheme].outlineVariant)};
|
||||||
|
--md-sys-color-scrim: ${hexFromArgb(theme.schemes[scheme].scrim)};
|
||||||
|
--md-sys-color-shadow: ${hexFromArgb(theme.schemes[scheme].shadow)};
|
||||||
|
--md-sys-color-on-surface: ${hexFromArgb(theme.schemes[scheme].onSurface)};
|
||||||
|
--md-sys-color-on-surface-variant: ${hexFromArgb(theme.schemes[scheme].onSurfaceVariant)};
|
||||||
|
--md-sys-color-on-surface-bright: ${hexFromArgb(theme.schemes[scheme].onSurface)};
|
||||||
|
--md-sys-color-on-surface-dim: ${hexFromArgb(theme.schemes[scheme].onSurface)};
|
||||||
|
--md-sys-color-background: ${hexFromArgb(theme.schemes[scheme].background)};
|
||||||
|
--md-sys-color-background-variant: ${hexFromArgb(theme.schemes[scheme].surface)};
|
||||||
|
|
||||||
|
--md-sys-color-on-primary: ${hexFromArgb(theme.schemes[scheme].onPrimary)};
|
||||||
|
--md-sys-color-on-primary-container: ${hexFromArgb(theme.schemes[scheme].onPrimaryContainer)};
|
||||||
|
--md-sys-color-on-secondary: ${hexFromArgb(theme.schemes[scheme].onSecondary)};
|
||||||
|
--md-sys-color-on-secondary-container: ${hexFromArgb(theme.schemes[scheme].onSecondaryContainer)};
|
||||||
|
--md-sys-color-on-tertiary: ${hexFromArgb(theme.schemes[scheme].onTertiary)};
|
||||||
|
--md-sys-color-on-tertiary-container: ${hexFromArgb(theme.schemes[scheme].onTertiaryContainer)};
|
||||||
|
--md-sys-color-on-error: ${hexFromArgb(theme.schemes[scheme].onError)};
|
||||||
|
--md-sys-color-on-error-container: ${hexFromArgb(theme.schemes[scheme].onErrorContainer)};
|
||||||
|
|
||||||
|
background-color: var(--md-sys-color-background);
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
</style>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useTheme() {
|
||||||
|
const context = useContext(ThemeContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error("useTheme must be used within a ThemeProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usePalette() {
|
||||||
|
const theme = useTheme();
|
||||||
|
const scheme = useScheme();
|
||||||
|
return theme.schemes[scheme];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import { createTheme } from './utils/theme';
|
||||||
|
import { ThemeProvider } from './hooks/useTheme';
|
||||||
|
import { Button } from './components/Button';
|
||||||
|
import { Box } from "./components/Box";
|
||||||
|
import { Checkbox } from "./components/Checkbox";
|
||||||
|
import { Switch } from "./components/Switch";
|
||||||
|
const mountApp = async () => {
|
||||||
|
const rootContainer = document.getElementById('root');
|
||||||
|
|
||||||
|
if (rootContainer === null) {
|
||||||
|
console.error('Root container element not found!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const theme = createTheme('#e22216');
|
||||||
|
|
||||||
|
const root = createRoot(rootContainer);
|
||||||
|
root.render(
|
||||||
|
<ThemeProvider theme={theme} scheme='dark'>
|
||||||
|
<Box style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100vh',
|
||||||
|
backgroundColor: 'var(--md-sys-color-background)',
|
||||||
|
}}>
|
||||||
|
<Button onClick={() => alert('Hello')} variant='filled'>Hello</Button>
|
||||||
|
<Checkbox />
|
||||||
|
<Switch />
|
||||||
|
</Box>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
mountApp();
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
declare module 'material-dynamic-colors' {
|
||||||
|
interface IMaterialDynamicColorsTheme {
|
||||||
|
primary: string;
|
||||||
|
onPrimary: string;
|
||||||
|
primaryContainer: string;
|
||||||
|
onPrimaryContainer: string;
|
||||||
|
secondary: string;
|
||||||
|
onSecondary: string;
|
||||||
|
secondaryContainer: string;
|
||||||
|
onSecondaryContainer: string;
|
||||||
|
tertiary: string;
|
||||||
|
onTertiary: string;
|
||||||
|
tertiaryContainer: string;
|
||||||
|
onTertiaryContainer: string;
|
||||||
|
error: string;
|
||||||
|
onError: string;
|
||||||
|
errorContainer: string;
|
||||||
|
onErrorContainer: string;
|
||||||
|
background: string;
|
||||||
|
onBackground: string;
|
||||||
|
surface: string;
|
||||||
|
onSurface: string;
|
||||||
|
surfaceVariant: string;
|
||||||
|
onSurfaceVariant: string;
|
||||||
|
outline: string;
|
||||||
|
shadow: string;
|
||||||
|
scrim: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMaterialDynamicColors {
|
||||||
|
light: IMaterialDynamicColorsTheme;
|
||||||
|
dark: IMaterialDynamicColorsTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MaterialDynamicColors(accent: string): Promise<IMaterialDynamicColors>;
|
||||||
|
export default MaterialDynamicColors;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { argbFromHex, themeFromSourceColor, applyTheme } from '@material/material-color-utilities';
|
||||||
|
|
||||||
|
export function createTheme(accent: string) {
|
||||||
|
const sourceColor = argbFromHex(accent);
|
||||||
|
const theme = themeFromSourceColor(sourceColor);
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"sourceMap": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"target": "ES2016",
|
||||||
|
"module": "ES2020",
|
||||||
|
"lib": [
|
||||||
|
"ES2021",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
|
||||||
|
import inject from '@rollup/plugin-inject';
|
||||||
|
import buildConfig from './build.config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
appType: 'spa',
|
||||||
|
publicDir: false,
|
||||||
|
base: buildConfig.base,
|
||||||
|
server: {
|
||||||
|
port: 8080,
|
||||||
|
host: '127.0.0.1',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
react()
|
||||||
|
],
|
||||||
|
optimizeDeps: {
|
||||||
|
esbuildOptions: {
|
||||||
|
define: {
|
||||||
|
global: 'globalThis',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
// Enable esbuild polyfill plugins
|
||||||
|
NodeGlobalsPolyfillPlugin({
|
||||||
|
process: false,
|
||||||
|
buffer: true
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'dist',
|
||||||
|
sourcemap: true,
|
||||||
|
copyPublicDir: false,
|
||||||
|
rollupOptions: {
|
||||||
|
plugins: [inject({ Buffer: ['buffer', 'Buffer'] })],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue