@prasadj28/react-neu 1.0.27 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +28 -19
- package/src/App.tsx +626 -0
- package/src/components/Button/Button.css.ts +28 -0
- package/src/components/Button/Button.tsx +85 -0
- package/src/components/Card/Card.css.ts +11 -0
- package/src/components/Card/Card.tsx +106 -0
- package/src/components/Checkbox/Checkbox.css.ts +49 -0
- package/src/components/Checkbox/Checkbox.tsx +134 -0
- package/src/components/Icon/Icon.css.ts +39 -0
- package/src/components/Icon/Icon.tsx +163 -0
- package/src/components/Icon/IconPaths.tsx +80 -0
- package/src/components/Radio/Radio.css.ts +57 -0
- package/src/components/Radio/Radio.tsx +130 -0
- package/src/components/Ridge/Ridge.css.ts +11 -0
- package/src/components/Ridge/Ridge.tsx +66 -0
- package/src/components/Slider/Slider.css.ts +36 -0
- package/src/components/Slider/Slider.tsx +175 -0
- package/src/components/TextInput/TextInput.tsx +71 -0
- package/src/components/Toggle/Toggle.css.ts +55 -0
- package/src/components/Toggle/Toggle.tsx +167 -0
- package/src/index.ts +44 -0
- package/{react-neu/src → src}/main.tsx +0 -1
- package/src/styles/neumorphicEngine.ts +159 -0
- package/src/styles/theme.css.ts +38 -0
- package/src/styles/types.ts +45 -0
- package/tsconfig.json +26 -0
- package/LICENSE +0 -21
- package/react-neu/package-lock.json +0 -3753
- package/react-neu/package.json +0 -33
- package/react-neu/src/App.tsx +0 -30
- package/react-neu/src/components/Button/Button.css.ts +0 -12
- package/react-neu/src/components/Button/Button.tsx +0 -92
- package/react-neu/src/components/TextInput/TextInput.tsx +0 -72
- package/react-neu/src/index.ts +0 -3
- package/react-neu/src/styles/defaults.css.ts +0 -16
- package/react-neu/src/styles/filterDomProps.ts +0 -28
- package/react-neu/src/styles/global.css.ts +0 -12
- package/react-neu/src/styles/neumorphicEngine.ts +0 -110
- package/react-neu/src/styles/shadowUtils.ts +0 -68
- package/react-neu/src/styles/theme.css.ts +0 -26
- package/react-neu/tsconfig.json +0 -7
- /package/{react-neu/README.md → README.md} +0 -0
- /package/{react-neu/eslint.config.js → eslint.config.js} +0 -0
- /package/{react-neu/index.html → index.html} +0 -0
- /package/{react-neu/public → public}/vite.svg +0 -0
- /package/{react-neu/src → src}/assets/react.svg +0 -0
- /package/{react-neu/src → src}/components/TextInput/TextInput.css.ts +0 -0
- /package/{react-neu/src → src}/components/index.ts +0 -0
- /package/{react-neu/src → src}/styles/colorUtils.ts +0 -0
- /package/{react-neu/src → src}/utils/colorUtils.ts +0 -0
- /package/{react-neu/src → src}/utils/neuEngine.ts +0 -0
- /package/{react-neu/tsconfig.app.json → tsconfig.app.json} +0 -0
- /package/{react-neu/tsconfig.node.json → tsconfig.node.json} +0 -0
- /package/{react-neu/vite.config.ts → vite.config.ts} +0 -0
package/react-neu/package.json
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "react-neu",
|
|
3
|
-
"private": true,
|
|
4
|
-
"version": "0.0.0",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite --open",
|
|
8
|
-
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
9
|
-
"build:vite": "LIB=true vite build",
|
|
10
|
-
"lint": "eslint .",
|
|
11
|
-
"preview": "vite preview"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"react": "^19.1.1",
|
|
15
|
-
"react-dom": "^19.1.1"
|
|
16
|
-
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"@eslint/js": "^9.36.0",
|
|
19
|
-
"@types/node": "^24.6.0",
|
|
20
|
-
"@types/react": "^19.1.16",
|
|
21
|
-
"@types/react-dom": "^19.1.9",
|
|
22
|
-
"@vanilla-extract/css": "^1.17.4",
|
|
23
|
-
"@vanilla-extract/vite-plugin": "^5.1.1",
|
|
24
|
-
"@vitejs/plugin-react": "^5.0.4",
|
|
25
|
-
"eslint": "^9.36.0",
|
|
26
|
-
"eslint-plugin-react-hooks": "^5.2.0",
|
|
27
|
-
"eslint-plugin-react-refresh": "^0.4.22",
|
|
28
|
-
"globals": "^16.4.0",
|
|
29
|
-
"typescript": "~5.9.3",
|
|
30
|
-
"typescript-eslint": "^8.45.0",
|
|
31
|
-
"vite": "^7.1.7"
|
|
32
|
-
}
|
|
33
|
-
}
|
package/react-neu/src/App.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { NeuButton } from './components/Button/Button'
|
|
2
|
-
import { NeuTextInput } from './components/TextInput/TextInput'
|
|
3
|
-
function App() {
|
|
4
|
-
|
|
5
|
-
return (
|
|
6
|
-
<>
|
|
7
|
-
<NeuTextInput
|
|
8
|
-
placeholder="Enter your name"
|
|
9
|
-
variant="pressed"
|
|
10
|
-
color="#f6f5f4"
|
|
11
|
-
intensity={10}
|
|
12
|
-
elevation={2}
|
|
13
|
-
/>
|
|
14
|
-
<br/>
|
|
15
|
-
Hello
|
|
16
|
-
<NeuButton variant="flat">Flat</NeuButton>
|
|
17
|
-
<NeuButton variant="convex" >Convex</NeuButton>
|
|
18
|
-
<NeuButton variant="concave" >Concave</NeuButton>
|
|
19
|
-
<NeuButton
|
|
20
|
-
variant="pressed"
|
|
21
|
-
intensity={10}
|
|
22
|
-
shadowintensity={10}
|
|
23
|
-
>
|
|
24
|
-
Pressed
|
|
25
|
-
</NeuButton>
|
|
26
|
-
</>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default App
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { style } from "@vanilla-extract/css";
|
|
2
|
-
import { neuVars } from "../../styles/theme.css";
|
|
3
|
-
|
|
4
|
-
export const baseButton = style({
|
|
5
|
-
background: neuVars.color.background,
|
|
6
|
-
color: neuVars.color.text,
|
|
7
|
-
border: "none",
|
|
8
|
-
borderRadius: "0px",
|
|
9
|
-
padding: "14px 28px",
|
|
10
|
-
cursor: "pointer",
|
|
11
|
-
transition: "all 0.2s ease",
|
|
12
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import * as styles from "./Button.css";
|
|
3
|
-
import { filterDOMProps } from "../../styles/filterDomProps";
|
|
4
|
-
import { getNeumorphicStyle } from "../../styles/neumorphicEngine";
|
|
5
|
-
|
|
6
|
-
export const NeuButton: React.FC<NeuButtonProps> = ({
|
|
7
|
-
// internal props
|
|
8
|
-
variant = "flat",
|
|
9
|
-
color = "#e0e0e0",
|
|
10
|
-
angleDeg = 135,
|
|
11
|
-
distance = 4,
|
|
12
|
-
blur = 6,
|
|
13
|
-
intensity = 5,
|
|
14
|
-
elevation = 2,
|
|
15
|
-
border = false,
|
|
16
|
-
radius = "0px",
|
|
17
|
-
padding = "14px 28px",
|
|
18
|
-
textColor = "#333",
|
|
19
|
-
fontSize = "1rem",
|
|
20
|
-
fontFamily = "inherit",
|
|
21
|
-
fontWeight = 500,
|
|
22
|
-
transition,
|
|
23
|
-
hoverStyle,
|
|
24
|
-
activeStyle,
|
|
25
|
-
disabledStyle,
|
|
26
|
-
style,
|
|
27
|
-
disabled,
|
|
28
|
-
onClick,
|
|
29
|
-
children,
|
|
30
|
-
...props
|
|
31
|
-
}) => {
|
|
32
|
-
const defaultProps = filterDOMProps(props);
|
|
33
|
-
|
|
34
|
-
const [state, setState] = React.useState<"default" | "hover" | "active" | "disabled">(
|
|
35
|
-
disabled ? "disabled" : "default"
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const visualVariant =
|
|
39
|
-
state === "active"
|
|
40
|
-
? "pressed"
|
|
41
|
-
: state === "hover"
|
|
42
|
-
? variant === "concave"
|
|
43
|
-
? "pressed"
|
|
44
|
-
: "convex"
|
|
45
|
-
: variant;
|
|
46
|
-
|
|
47
|
-
const { background, boxShadow, border: borderStyle } = getNeumorphicStyle({
|
|
48
|
-
variant: visualVariant,
|
|
49
|
-
color,
|
|
50
|
-
angleDeg,
|
|
51
|
-
distance,
|
|
52
|
-
blur,
|
|
53
|
-
intensity,
|
|
54
|
-
elevation,
|
|
55
|
-
border,
|
|
56
|
-
state,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const mergedStyle: React.CSSProperties = {
|
|
60
|
-
background,
|
|
61
|
-
boxShadow,
|
|
62
|
-
border: borderStyle,
|
|
63
|
-
borderRadius: radius,
|
|
64
|
-
padding,
|
|
65
|
-
color: textColor,
|
|
66
|
-
fontSize,
|
|
67
|
-
fontFamily,
|
|
68
|
-
fontWeight,
|
|
69
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
70
|
-
transition: transition || "all 0.25s ease",
|
|
71
|
-
...(state === "hover" && hoverStyle),
|
|
72
|
-
...(state === "active" && activeStyle),
|
|
73
|
-
...(state === "disabled" && disabledStyle),
|
|
74
|
-
...style,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<button
|
|
79
|
-
className={styles.baseButton}
|
|
80
|
-
style={mergedStyle}
|
|
81
|
-
disabled={disabled}
|
|
82
|
-
onClick={onClick}
|
|
83
|
-
onMouseEnter={() => !disabled && setState("hover")}
|
|
84
|
-
onMouseLeave={() => !disabled && setState("default")}
|
|
85
|
-
onMouseDown={() => !disabled && setState("active")}
|
|
86
|
-
onMouseUp={() => !disabled && setState("hover")}
|
|
87
|
-
{...defaultProps}
|
|
88
|
-
>
|
|
89
|
-
{children}
|
|
90
|
-
</button>
|
|
91
|
-
);
|
|
92
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import * as styles from "./TextInput.css";
|
|
3
|
-
import { getNeumorphicStyle } from "../../styles/neumorphicEngine";
|
|
4
|
-
import { filterDOMProps } from "../../styles/filterDomProps";
|
|
5
|
-
|
|
6
|
-
export const NeuTextInput: React.FC<React.InputHTMLAttributes<HTMLInputElement>> = ({
|
|
7
|
-
variant = "pressed",
|
|
8
|
-
color = "#cccccc",
|
|
9
|
-
distance = 5,
|
|
10
|
-
blur = 10,
|
|
11
|
-
intensity = 6,
|
|
12
|
-
elevation = 2,
|
|
13
|
-
border = false,
|
|
14
|
-
radius = "15px",
|
|
15
|
-
padding = "1em",
|
|
16
|
-
fontSize = "1rem",
|
|
17
|
-
textColor = "#333",
|
|
18
|
-
transition = "all 0.3s ease-in-out",
|
|
19
|
-
style,
|
|
20
|
-
disabled,
|
|
21
|
-
...props
|
|
22
|
-
}) => {
|
|
23
|
-
const domProps = filterDOMProps(props);
|
|
24
|
-
const [focused, setFocused] = React.useState(false);
|
|
25
|
-
|
|
26
|
-
// Base neumorphic shadow (pressed = inset)
|
|
27
|
-
const { background, boxShadow } = getNeumorphicStyle({
|
|
28
|
-
variant: "pressed",
|
|
29
|
-
color,
|
|
30
|
-
distance,
|
|
31
|
-
blur,
|
|
32
|
-
intensity,
|
|
33
|
-
elevation,
|
|
34
|
-
border,
|
|
35
|
-
state: focused ? "active" : "default",
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const mergedStyle: React.CSSProperties = {
|
|
39
|
-
WebkitAppearance: "none",
|
|
40
|
-
MozAppearance: "none",
|
|
41
|
-
appearance: "none",
|
|
42
|
-
background: background || color,
|
|
43
|
-
border: "none",
|
|
44
|
-
outline: "none",
|
|
45
|
-
borderRadius: radius,
|
|
46
|
-
padding,
|
|
47
|
-
color: textColor,
|
|
48
|
-
fontSize,
|
|
49
|
-
width: "100%",
|
|
50
|
-
boxSizing: "border-box",
|
|
51
|
-
transition,
|
|
52
|
-
boxShadow: focused
|
|
53
|
-
? "13px 13px 100px #969696, -13px -13px 100px #ffffff" // your custom glow
|
|
54
|
-
: boxShadow || "inset 2px 5px 10px rgba(0,0,0,0.3)",
|
|
55
|
-
transform: focused ? "scale(1.05)" : "scale(1)",
|
|
56
|
-
backgroundColor: focused ? "white" : color,
|
|
57
|
-
cursor: disabled ? "not-allowed" : "text",
|
|
58
|
-
...style,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<input
|
|
63
|
-
className={styles.baseInput}
|
|
64
|
-
style={mergedStyle}
|
|
65
|
-
disabled={disabled}
|
|
66
|
-
onFocus={() => setFocused(true)}
|
|
67
|
-
onBlur={() => setFocused(false)}
|
|
68
|
-
{...domProps}
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
package/react-neu/src/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { createGlobalTheme } from "@vanilla-extract/css";
|
|
2
|
-
import { neuVars } from "./theme.css";
|
|
3
|
-
|
|
4
|
-
createGlobalTheme(":root", neuVars, {
|
|
5
|
-
color: {
|
|
6
|
-
background: "#e0e0e0",
|
|
7
|
-
primary: "#ffffff",
|
|
8
|
-
secondary: "#c8c8c8",
|
|
9
|
-
text: "#111111",
|
|
10
|
-
},
|
|
11
|
-
neumorphic: {
|
|
12
|
-
angle: "135deg",
|
|
13
|
-
depth: "0.3",
|
|
14
|
-
distance: "10px",
|
|
15
|
-
},
|
|
16
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const internalProps = new Set([
|
|
2
|
-
"variant",
|
|
3
|
-
"color",
|
|
4
|
-
"angleDeg",
|
|
5
|
-
"distance",
|
|
6
|
-
"blur",
|
|
7
|
-
"intensity",
|
|
8
|
-
"elevation",
|
|
9
|
-
"border",
|
|
10
|
-
"radius",
|
|
11
|
-
"padding",
|
|
12
|
-
"textColor",
|
|
13
|
-
"fontSize",
|
|
14
|
-
"fontFamily",
|
|
15
|
-
"fontWeight",
|
|
16
|
-
"transition",
|
|
17
|
-
"hoverStyle",
|
|
18
|
-
"activeStyle",
|
|
19
|
-
"disabledStyle",
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
export function filterDOMProps<T extends Record<string, any>>(props: T):Partial<T> {
|
|
23
|
-
const result: Partial<T> = {};
|
|
24
|
-
for(const key in props) {
|
|
25
|
-
if(!internalProps.has(key)) result[key] = props[key];
|
|
26
|
-
}
|
|
27
|
-
return result;
|
|
28
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { globalStyle } from "@vanilla-extract/css";
|
|
2
|
-
import { neuVars } from "./theme.css";
|
|
3
|
-
|
|
4
|
-
globalStyle("body", {
|
|
5
|
-
margin: 0,
|
|
6
|
-
backgroundColor: neuVars.color.background,
|
|
7
|
-
fontFamily: "Inter, sans-serif",
|
|
8
|
-
display: "flex",
|
|
9
|
-
justifyContent: "center",
|
|
10
|
-
alignItems: "center",
|
|
11
|
-
height: "100vh",
|
|
12
|
-
});
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// src/styles/neumorphicEngine.ts
|
|
2
|
-
import { lighten, darken } from "./colorUtils";
|
|
3
|
-
|
|
4
|
-
export type NeumorphicVariant = "flat" | "convex" | "concave" | "pressed";
|
|
5
|
-
export type NeumorphicState = "default" | "hover" | "active" | "disabled" | "focus";
|
|
6
|
-
|
|
7
|
-
export interface NeumorphicOptions {
|
|
8
|
-
variant?: NeumorphicVariant;
|
|
9
|
-
color?: string;
|
|
10
|
-
angleDeg?: number;
|
|
11
|
-
distance?: number; // 1–10 (or px if you want)
|
|
12
|
-
blur?: number; // 1–10
|
|
13
|
-
intensity?: number; // 1–10
|
|
14
|
-
elevation?: number; // 1–10
|
|
15
|
-
border?: boolean;
|
|
16
|
-
state?: NeumorphicState;
|
|
17
|
-
|
|
18
|
-
// New: control composite behavior without hardcoding in components
|
|
19
|
-
focusGlow?: boolean; // add an outer glow on focus
|
|
20
|
-
glowScale?: number; // multiplier for distance/blur on glow
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function pairShadows({
|
|
24
|
-
color, intensity, distance, blur, angleDeg, inset = false,
|
|
25
|
-
}: {
|
|
26
|
-
color: string;
|
|
27
|
-
intensity: number;
|
|
28
|
-
distance: number;
|
|
29
|
-
blur: number;
|
|
30
|
-
angleDeg: number;
|
|
31
|
-
inset?: boolean;
|
|
32
|
-
}) {
|
|
33
|
-
const darkShadow = darken(color, intensity * 2);
|
|
34
|
-
const lightShadow = lighten(color, intensity * 2);
|
|
35
|
-
const ang = (angleDeg * Math.PI) / 180;
|
|
36
|
-
const ox = Math.cos(ang) * distance;
|
|
37
|
-
const oy = Math.sin(ang) * distance;
|
|
38
|
-
const pre = inset ? "inset " : "";
|
|
39
|
-
return `${pre}${ox}px ${oy}px ${blur}px ${darkShadow}, ${pre}${-ox}px ${-oy}px ${blur}px ${lightShadow}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function getNeumorphicStyle({
|
|
43
|
-
variant = "convex",
|
|
44
|
-
color = "#f6f5f4",
|
|
45
|
-
angleDeg = 135,
|
|
46
|
-
distance = 6,
|
|
47
|
-
blur = 12,
|
|
48
|
-
intensity = 6,
|
|
49
|
-
elevation = 2,
|
|
50
|
-
border = false,
|
|
51
|
-
state = "default",
|
|
52
|
-
focusGlow = false,
|
|
53
|
-
glowScale = 3,
|
|
54
|
-
}: NeumorphicOptions) {
|
|
55
|
-
// Elevation scaling (kept mild so component props remain the main control)
|
|
56
|
-
const level = Math.max(1, Math.min(10, elevation));
|
|
57
|
-
const effDistance = distance * level ** 1.2;
|
|
58
|
-
const effBlur = blur * level ** 1.2;
|
|
59
|
-
|
|
60
|
-
// Base background by variant
|
|
61
|
-
let background = color;
|
|
62
|
-
if (variant === "convex") {
|
|
63
|
-
background = `linear-gradient(225deg, ${lighten(color, 4)}, ${darken(color, 4)})`;
|
|
64
|
-
} else if (variant === "concave") {
|
|
65
|
-
background = `linear-gradient(225deg, ${darken(color, 4)}, ${lighten(color, 4)})`;
|
|
66
|
-
} else if (variant === "pressed") {
|
|
67
|
-
background = lighten(color, 3);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Base shadows by variant
|
|
71
|
-
let base = "";
|
|
72
|
-
if (variant === "flat") {
|
|
73
|
-
base = pairShadows({ color, intensity, distance: effDistance, blur: effBlur, angleDeg });
|
|
74
|
-
} else if (variant === "convex") {
|
|
75
|
-
base = pairShadows({ color, intensity, distance: effDistance, blur: effBlur, angleDeg });
|
|
76
|
-
} else if (variant === "concave") {
|
|
77
|
-
base = pairShadows({ color, intensity, distance: effDistance, blur: effBlur, angleDeg, inset: true });
|
|
78
|
-
} else if (variant === "pressed") {
|
|
79
|
-
// deeper inset for pressed
|
|
80
|
-
base = pairShadows({
|
|
81
|
-
color,
|
|
82
|
-
intensity: intensity + 2,
|
|
83
|
-
distance: effDistance * 1.6,
|
|
84
|
-
blur: effBlur * 1.8,
|
|
85
|
-
angleDeg,
|
|
86
|
-
inset: true,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Optional focus glow layer (outer) – engine-driven, not hardcoded
|
|
91
|
-
let composite = base;
|
|
92
|
-
if (state === "focus" && focusGlow) {
|
|
93
|
-
const glow = pairShadows({
|
|
94
|
-
color,
|
|
95
|
-
intensity: Math.max(1, intensity - 1),
|
|
96
|
-
distance: effDistance * glowScale,
|
|
97
|
-
blur: effBlur * glowScale,
|
|
98
|
-
angleDeg,
|
|
99
|
-
inset: false,
|
|
100
|
-
});
|
|
101
|
-
// outer glow first, then base inset so it feels “halo + pressed”
|
|
102
|
-
composite = `${glow}, ${base}`;
|
|
103
|
-
// Slight brighten on focus to mimic your white-on-focus without hardcoding white
|
|
104
|
-
background = lighten(color, 6);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const borderStyle = border ? `2px solid ${darken(color, 10)}` : "none";
|
|
108
|
-
return { background, boxShadow: composite, border: borderStyle };
|
|
109
|
-
}
|
|
110
|
-
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// src/styles/shadowUtils.ts
|
|
2
|
-
import { lighten, darken } from "./colorUtils";
|
|
3
|
-
|
|
4
|
-
export type NeumorphicMode = "pop" | "drop";
|
|
5
|
-
export type NeumorphicState = "default" | "hover" | "active";
|
|
6
|
-
|
|
7
|
-
interface ShadowOptions {
|
|
8
|
-
mode?: NeumorphicMode;
|
|
9
|
-
color?: string;
|
|
10
|
-
intensity?: number; // base brightness delta
|
|
11
|
-
elevation?: number; // 1–10 scale
|
|
12
|
-
state?: NeumorphicState;
|
|
13
|
-
angleDeg?: number; // 0–360
|
|
14
|
-
customDistance?: number; // optional user override for offset
|
|
15
|
-
customDepth?: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function getNeumorphicShadow({
|
|
19
|
-
mode,
|
|
20
|
-
color: buttonColor,
|
|
21
|
-
intensity = 12,
|
|
22
|
-
elevation = 1,
|
|
23
|
-
state = "default",
|
|
24
|
-
angleDeg = 135,
|
|
25
|
-
customDistance,
|
|
26
|
-
customDepth,
|
|
27
|
-
}: ShadowOptions) {
|
|
28
|
-
if (!mode) return "none";
|
|
29
|
-
|
|
30
|
-
// Clamp elevation to 1–10
|
|
31
|
-
const level = Math.max(1, Math.min(10, elevation));
|
|
32
|
-
|
|
33
|
-
// Adjust for hover/active but maintain same strength feel
|
|
34
|
-
const elevationMap = {
|
|
35
|
-
default: level,
|
|
36
|
-
hover: level + 1.2,
|
|
37
|
-
active: level - 0.8,
|
|
38
|
-
} as const;
|
|
39
|
-
const effectiveElevation = elevationMap[state];
|
|
40
|
-
const color = buttonColor || "#e0e0e0";
|
|
41
|
-
// Make big changes to spatial distance and blur
|
|
42
|
-
// Elevation now multiplies both — this gives real visual separation
|
|
43
|
-
const distance = customDistance ?? 2 * effectiveElevation ** 1.4;
|
|
44
|
-
const blur = customDepth ?? 5 * effectiveElevation ** 1.4;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Make contrast increase sharply with elevation
|
|
48
|
-
// 1 → soft, 10 → extremely strong
|
|
49
|
-
const effectiveIntensity = intensity + level * 15;
|
|
50
|
-
|
|
51
|
-
const darkBoost = 1 + Math.pow(level / 8, 2); // nonlinear dark boost
|
|
52
|
-
const lightBoost = 1 + Math.pow(level / 10, 1.5); // gentle brightening
|
|
53
|
-
|
|
54
|
-
const darkShadow = darken(color, intensity * 1.5 * darkBoost);
|
|
55
|
-
const lightShadow = lighten(color, intensity * lightBoost);
|
|
56
|
-
|
|
57
|
-
const inset = mode === "drop" ? "inset " : "";
|
|
58
|
-
|
|
59
|
-
const angleRad = (angleDeg * Math.PI) / 180;
|
|
60
|
-
const offsetX = Math.cos(angleRad) * distance;
|
|
61
|
-
const offsetY = Math.sin(angleRad) * distance;
|
|
62
|
-
|
|
63
|
-
return `
|
|
64
|
-
${inset}${offsetX.toFixed(1)}px ${offsetY.toFixed(1)}px ${blur.toFixed(1)}px ${darkShadow},
|
|
65
|
-
${inset}${-offsetX.toFixed(1)}px ${-offsetY.toFixed(1)}px ${blur.toFixed(1)}px ${lightShadow}
|
|
66
|
-
`;
|
|
67
|
-
}
|
|
68
|
-
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { createVar, style, globalStyle } from "@vanilla-extract/css";
|
|
2
|
-
|
|
3
|
-
export const neuVars = {
|
|
4
|
-
color: {
|
|
5
|
-
background: createVar(),
|
|
6
|
-
text: createVar(),
|
|
7
|
-
shadowLight: createVar(),
|
|
8
|
-
shadowDark: createVar(),
|
|
9
|
-
},
|
|
10
|
-
shadow: {
|
|
11
|
-
depth: createVar(),
|
|
12
|
-
distance: createVar(),
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
globalStyle(":root", {
|
|
17
|
-
vars: {
|
|
18
|
-
[neuVars.color.background]: "var(--background-color, #e0e0e0)",
|
|
19
|
-
[neuVars.color.text]: "var(--text-color, #2c2c2c)",
|
|
20
|
-
[neuVars.color.shadowLight]: "rgba(255,255,255,0.7)",
|
|
21
|
-
[neuVars.color.shadowDark]: "rgba(0,0,0,0.25)",
|
|
22
|
-
[neuVars.shadow.depth]: "0.3",
|
|
23
|
-
[neuVars.shadow.distance]: "8px",
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
package/react-neu/tsconfig.json
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|