@yugnex/nexui 2.0.0
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/LICENSE +59 -0
- package/css/nexui-base.css +157 -0
- package/css/nexui-icons.css +86 -0
- package/css/nexui-tokens.css +113 -0
- package/css/nexui.css +16 -0
- package/dist/assets/geometry.d.ts +98 -0
- package/dist/assets/geometry.d.ts.map +1 -0
- package/dist/assets/geometry.js +114 -0
- package/dist/assets/geometry.js.map +1 -0
- package/dist/assets/typography.d.ts +3 -0
- package/dist/assets/typography.d.ts.map +1 -0
- package/dist/assets/typography.js +178 -0
- package/dist/assets/typography.js.map +1 -0
- package/dist/core/compiler.d.ts +30 -0
- package/dist/core/compiler.d.ts.map +1 -0
- package/dist/core/compiler.js +124 -0
- package/dist/core/compiler.js.map +1 -0
- package/dist/core/cx.d.ts +7 -0
- package/dist/core/cx.d.ts.map +1 -0
- package/dist/core/cx.js +34 -0
- package/dist/core/cx.js.map +1 -0
- package/dist/core/matrix.d.ts +118 -0
- package/dist/core/matrix.d.ts.map +1 -0
- package/dist/core/matrix.js +180 -0
- package/dist/core/matrix.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives/avatar.d.ts +8 -0
- package/dist/primitives/avatar.d.ts.map +1 -0
- package/dist/primitives/avatar.js +146 -0
- package/dist/primitives/avatar.js.map +1 -0
- package/dist/primitives/badge.d.ts +8 -0
- package/dist/primitives/badge.d.ts.map +1 -0
- package/dist/primitives/badge.js +88 -0
- package/dist/primitives/badge.js.map +1 -0
- package/dist/primitives/button.d.ts +10 -0
- package/dist/primitives/button.d.ts.map +1 -0
- package/dist/primitives/button.js +137 -0
- package/dist/primitives/button.js.map +1 -0
- package/dist/primitives/checkbox.d.ts +13 -0
- package/dist/primitives/checkbox.d.ts.map +1 -0
- package/dist/primitives/checkbox.js +107 -0
- package/dist/primitives/checkbox.js.map +1 -0
- package/dist/primitives/input.d.ts +14 -0
- package/dist/primitives/input.d.ts.map +1 -0
- package/dist/primitives/input.js +177 -0
- package/dist/primitives/input.js.map +1 -0
- package/dist/primitives/panel.d.ts +9 -0
- package/dist/primitives/panel.d.ts.map +1 -0
- package/dist/primitives/panel.js +101 -0
- package/dist/primitives/panel.js.map +1 -0
- package/dist/primitives/progress.d.ts +8 -0
- package/dist/primitives/progress.d.ts.map +1 -0
- package/dist/primitives/progress.js +105 -0
- package/dist/primitives/progress.js.map +1 -0
- package/dist/primitives/separator.d.ts +8 -0
- package/dist/primitives/separator.d.ts.map +1 -0
- package/dist/primitives/separator.js +69 -0
- package/dist/primitives/separator.js.map +1 -0
- package/dist/primitives/skeleton.d.ts +8 -0
- package/dist/primitives/skeleton.d.ts.map +1 -0
- package/dist/primitives/skeleton.js +61 -0
- package/dist/primitives/skeleton.js.map +1 -0
- package/dist/primitives/spinner.d.ts +8 -0
- package/dist/primitives/spinner.d.ts.map +1 -0
- package/dist/primitives/spinner.js +64 -0
- package/dist/primitives/spinner.js.map +1 -0
- package/dist/primitives/status-ring.d.ts +8 -0
- package/dist/primitives/status-ring.d.ts.map +1 -0
- package/dist/primitives/status-ring.js +101 -0
- package/dist/primitives/status-ring.js.map +1 -0
- package/dist/primitives/switch.d.ts +12 -0
- package/dist/primitives/switch.d.ts.map +1 -0
- package/dist/primitives/switch.js +124 -0
- package/dist/primitives/switch.js.map +1 -0
- package/dist/primitives/text-stream.d.ts +23 -0
- package/dist/primitives/text-stream.d.ts.map +1 -0
- package/dist/primitives/text-stream.js +167 -0
- package/dist/primitives/text-stream.js.map +1 -0
- package/dist/tokens/colors.d.ts +127 -0
- package/dist/tokens/colors.d.ts.map +1 -0
- package/dist/tokens/colors.js +135 -0
- package/dist/tokens/colors.js.map +1 -0
- package/dist/tokens/motion.d.ts +37 -0
- package/dist/tokens/motion.d.ts.map +1 -0
- package/dist/tokens/motion.js +93 -0
- package/dist/tokens/motion.js.map +1 -0
- package/dist/tokens/shadows.d.ts +34 -0
- package/dist/tokens/shadows.d.ts.map +1 -0
- package/dist/tokens/shadows.js +45 -0
- package/dist/tokens/shadows.js.map +1 -0
- package/dist/tokens/spacing.d.ts +69 -0
- package/dist/tokens/spacing.d.ts.map +1 -0
- package/dist/tokens/spacing.js +71 -0
- package/dist/tokens/spacing.js.map +1 -0
- package/dist/tokens/type.d.ts +166 -0
- package/dist/tokens/type.d.ts.map +1 -0
- package/dist/tokens/type.js +215 -0
- package/dist/tokens/type.js.map +1 -0
- package/fonts/NexuiIcons.woff2 +0 -0
- package/fonts/NexuiMono-Regular.otf +0 -0
- package/fonts/NexuiMono-Regular.woff2 +0 -0
- package/fonts/NexuiSans-Bold.otf +0 -0
- package/fonts/NexuiSans-Bold.woff2 +0 -0
- package/fonts/NexuiSans-Medium.otf +0 -0
- package/fonts/NexuiSans-Medium.woff2 +0 -0
- package/fonts/NexuiSans-Regular.otf +0 -0
- package/fonts/NexuiSans-Regular.woff2 +0 -0
- package/native/Cargo.toml +16 -0
- package/native/src/lib.rs +127 -0
- package/nexui-utils.css +485 -0
- package/package.json +58 -0
- package/src/assets/geometry.ts +144 -0
- package/src/assets/typography.ts +184 -0
- package/src/core/compiler.ts +139 -0
- package/src/core/cx.ts +50 -0
- package/src/core/matrix.ts +195 -0
- package/src/index.ts +78 -0
- package/src/primitives/avatar.ts +159 -0
- package/src/primitives/badge.ts +98 -0
- package/src/primitives/button.ts +149 -0
- package/src/primitives/checkbox.ts +113 -0
- package/src/primitives/input.ts +187 -0
- package/src/primitives/panel.ts +111 -0
- package/src/primitives/progress.ts +112 -0
- package/src/primitives/separator.ts +73 -0
- package/src/primitives/skeleton.ts +68 -0
- package/src/primitives/spinner.ts +71 -0
- package/src/primitives/status-ring.ts +109 -0
- package/src/primitives/switch.ts +134 -0
- package/src/primitives/text-stream.ts +187 -0
- package/src/tokens/colors.ts +149 -0
- package/src/tokens/motion.ts +97 -0
- package/src/tokens/shadows.ts +58 -0
- package/src/tokens/spacing.ts +79 -0
- package/src/tokens/type.ts +224 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// @yugnex/nexui — Motion Tokens
|
|
2
|
+
// Easing curves + durations. Matches native platform conventions.
|
|
3
|
+
|
|
4
|
+
export const NEXUI_EASING = {
|
|
5
|
+
// Standard — element moves between two screen states
|
|
6
|
+
standard: "cubic-bezier(0.2, 0, 0, 1)",
|
|
7
|
+
// Decelerate — element enters the screen (decelerates to rest)
|
|
8
|
+
decelerate: "cubic-bezier(0, 0, 0.2, 1)",
|
|
9
|
+
// Accelerate — element leaves the screen (accelerates to exit)
|
|
10
|
+
accelerate: "cubic-bezier(0.3, 0, 1, 1)",
|
|
11
|
+
// Linear — progress bars, loaders
|
|
12
|
+
linear: "linear",
|
|
13
|
+
// Spring — interactive, snap, bouncy (for emphasis)
|
|
14
|
+
spring: "cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
15
|
+
// Sharp — micro-interactions (toggles, chips)
|
|
16
|
+
sharp: "cubic-bezier(0.4, 0, 0.6, 1)",
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export const NEXUI_DURATION = {
|
|
20
|
+
// Micro — icon state change, badge pulse
|
|
21
|
+
50: "50ms",
|
|
22
|
+
// Fast — tooltip show/hide, focus ring
|
|
23
|
+
100: "100ms",
|
|
24
|
+
// Quick — button feedback, checkbox
|
|
25
|
+
150: "150ms",
|
|
26
|
+
// Standard — panel collapse, menu open
|
|
27
|
+
200: "200ms",
|
|
28
|
+
// Smooth — drawer, modal, tab transitions
|
|
29
|
+
300: "300ms",
|
|
30
|
+
// Deliberate — page-level transitions
|
|
31
|
+
400: "400ms",
|
|
32
|
+
// Slow — complex choreography
|
|
33
|
+
500: "500ms",
|
|
34
|
+
// Elaborate — data visualization entry
|
|
35
|
+
700: "700ms",
|
|
36
|
+
// Cinematic — splash, hero
|
|
37
|
+
1000: "1000ms",
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
// Semantic transition presets — use these in components
|
|
41
|
+
export const NEXUI_TRANSITION = {
|
|
42
|
+
"instant": `all ${NEXUI_DURATION[50]} ${NEXUI_EASING.sharp}`,
|
|
43
|
+
"fast": `all ${NEXUI_DURATION[100]} ${NEXUI_EASING.standard}`,
|
|
44
|
+
"base": `all ${NEXUI_DURATION[200]} ${NEXUI_EASING.standard}`,
|
|
45
|
+
"smooth": `all ${NEXUI_DURATION[300]} ${NEXUI_EASING.decelerate}`,
|
|
46
|
+
"slow": `all ${NEXUI_DURATION[500]} ${NEXUI_EASING.decelerate}`,
|
|
47
|
+
"none": "none",
|
|
48
|
+
|
|
49
|
+
// Specific property transitions (better performance than `all`)
|
|
50
|
+
"colors": `color ${NEXUI_DURATION[150]} ${NEXUI_EASING.standard}, background-color ${NEXUI_DURATION[150]} ${NEXUI_EASING.standard}, border-color ${NEXUI_DURATION[150]} ${NEXUI_EASING.standard}, fill ${NEXUI_DURATION[150]} ${NEXUI_EASING.standard}, stroke ${NEXUI_DURATION[150]} ${NEXUI_EASING.standard}`,
|
|
51
|
+
"opacity": `opacity ${NEXUI_DURATION[200]} ${NEXUI_EASING.standard}`,
|
|
52
|
+
"transform": `transform ${NEXUI_DURATION[200]} ${NEXUI_EASING.standard}`,
|
|
53
|
+
"ring": `box-shadow ${NEXUI_DURATION[150]} ${NEXUI_EASING.standard}`,
|
|
54
|
+
"slide-in": `transform ${NEXUI_DURATION[300]} ${NEXUI_EASING.decelerate}, opacity ${NEXUI_DURATION[300]} ${NEXUI_EASING.decelerate}`,
|
|
55
|
+
"slide-out": `transform ${NEXUI_DURATION[200]} ${NEXUI_EASING.accelerate}, opacity ${NEXUI_DURATION[200]} ${NEXUI_EASING.accelerate}`,
|
|
56
|
+
"scale": `transform ${NEXUI_DURATION[200]} ${NEXUI_EASING.spring}`,
|
|
57
|
+
"ring-score": `stroke-dashoffset ${NEXUI_DURATION[700]} ${NEXUI_EASING.decelerate}`,
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
// Keyframe definitions — inject once per page via NexuiTypographySheet or initializeNexuiEngine
|
|
61
|
+
export const NEXUI_KEYFRAMES = `
|
|
62
|
+
@keyframes nx-fade-in {
|
|
63
|
+
from { opacity: 0; }
|
|
64
|
+
to { opacity: 1; }
|
|
65
|
+
}
|
|
66
|
+
@keyframes nx-fade-out {
|
|
67
|
+
from { opacity: 1; }
|
|
68
|
+
to { opacity: 0; }
|
|
69
|
+
}
|
|
70
|
+
@keyframes nx-slide-up {
|
|
71
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
72
|
+
to { opacity: 1; transform: translateY(0); }
|
|
73
|
+
}
|
|
74
|
+
@keyframes nx-slide-down {
|
|
75
|
+
from { opacity: 0; transform: translateY(-8px); }
|
|
76
|
+
to { opacity: 1; transform: translateY(0); }
|
|
77
|
+
}
|
|
78
|
+
@keyframes nx-scale-in {
|
|
79
|
+
from { opacity: 0; transform: scale(0.95); }
|
|
80
|
+
to { opacity: 1; transform: scale(1); }
|
|
81
|
+
}
|
|
82
|
+
@keyframes nx-spin {
|
|
83
|
+
to { transform: rotate(360deg); }
|
|
84
|
+
}
|
|
85
|
+
@keyframes nx-pulse-ring {
|
|
86
|
+
0%, 100% { opacity: 1; }
|
|
87
|
+
50% { opacity: 0.4; }
|
|
88
|
+
}
|
|
89
|
+
@keyframes nx-shimmer {
|
|
90
|
+
0% { background-position: -200% 0; }
|
|
91
|
+
100% { background-position: 200% 0; }
|
|
92
|
+
}
|
|
93
|
+
@keyframes nx-blink {
|
|
94
|
+
0%, 100% { opacity: 1; }
|
|
95
|
+
50% { opacity: 0; }
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// @yugnex/nexui — Shadow / Elevation System
|
|
2
|
+
// Two rulesets: void (dark UI shadows use color + opacity) and terminal.
|
|
3
|
+
|
|
4
|
+
export const NEXUI_SHADOWS_VOID = {
|
|
5
|
+
// Flat — no elevation
|
|
6
|
+
"none": "none",
|
|
7
|
+
|
|
8
|
+
// Subtle — cards, inline elements on same surface
|
|
9
|
+
"xs": "0 1px 2px rgba(0,0,0,0.40)",
|
|
10
|
+
|
|
11
|
+
// Low — floating buttons, popover triggers
|
|
12
|
+
"sm": "0 1px 3px rgba(0,0,0,0.50), 0 1px 2px rgba(0,0,0,0.30)",
|
|
13
|
+
|
|
14
|
+
// Standard — cards, panels
|
|
15
|
+
"md": "0 4px 6px rgba(0,0,0,0.40), 0 2px 4px rgba(0,0,0,0.30)",
|
|
16
|
+
|
|
17
|
+
// Elevated — dropdowns, date pickers
|
|
18
|
+
"lg": "0 10px 15px rgba(0,0,0,0.50), 0 4px 6px rgba(0,0,0,0.30)",
|
|
19
|
+
|
|
20
|
+
// High — modals, dialogs
|
|
21
|
+
"xl": "0 20px 25px rgba(0,0,0,0.55), 0 8px 10px rgba(0,0,0,0.30)",
|
|
22
|
+
|
|
23
|
+
// Overlay — full-screen drawers, command palette
|
|
24
|
+
"2xl": "0 25px 50px rgba(0,0,0,0.65)",
|
|
25
|
+
|
|
26
|
+
// Accent glow — focused inputs, highlighted cards
|
|
27
|
+
"glow-accent": "0 0 0 3px rgba(232,144,16,0.30), 0 0 16px rgba(232,144,16,0.12)",
|
|
28
|
+
"glow-live": "0 0 0 3px rgba(15,212,198,0.25), 0 0 16px rgba(15,212,198,0.10)",
|
|
29
|
+
"glow-success": "0 0 0 3px rgba(34,197,94,0.25), 0 0 12px rgba(34,197,94,0.08)",
|
|
30
|
+
"glow-error": "0 0 0 3px rgba(239,68,68,0.30), 0 0 12px rgba(239,68,68,0.10)",
|
|
31
|
+
|
|
32
|
+
// Focus ring — keyboard nav, ARIA
|
|
33
|
+
"focus": "0 0 0 2px #0D1117, 0 0 0 4px rgba(232,144,16,0.60)",
|
|
34
|
+
|
|
35
|
+
// Inset — pressed states, sunken containers
|
|
36
|
+
"inner": "inset 0 2px 4px rgba(0,0,0,0.40)",
|
|
37
|
+
"inner-strong": "inset 0 2px 8px rgba(0,0,0,0.60)",
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
export const NEXUI_SHADOWS_TERMINAL = {
|
|
41
|
+
"none": "none",
|
|
42
|
+
"xs": "0 1px 2px rgba(0,0,0,0.70)",
|
|
43
|
+
"sm": "0 1px 3px rgba(0,0,0,0.80), 0 1px 2px rgba(0,0,0,0.50)",
|
|
44
|
+
"md": "0 4px 6px rgba(0,0,0,0.70), 0 2px 4px rgba(0,0,0,0.50)",
|
|
45
|
+
"lg": "0 10px 15px rgba(0,0,0,0.80), 0 4px 6px rgba(0,0,0,0.50)",
|
|
46
|
+
"xl": "0 20px 25px rgba(0,0,0,0.85), 0 8px 10px rgba(0,0,0,0.50)",
|
|
47
|
+
"2xl": "0 25px 50px rgba(0,0,0,0.90)",
|
|
48
|
+
|
|
49
|
+
"glow-accent": "0 0 0 3px rgba(232,144,16,0.30), 0 0 16px rgba(232,144,16,0.12)",
|
|
50
|
+
"glow-live": "0 0 0 3px rgba(16,185,129,0.30), 0 0 16px rgba(16,185,129,0.12)",
|
|
51
|
+
"glow-success": "0 0 0 3px rgba(16,185,129,0.30), 0 0 12px rgba(16,185,129,0.10)",
|
|
52
|
+
"glow-error": "0 0 0 3px rgba(239,68,68,0.35), 0 0 12px rgba(239,68,68,0.12)",
|
|
53
|
+
"focus": "0 0 0 2px #000000, 0 0 0 4px rgba(16,185,129,0.60)",
|
|
54
|
+
"inner": "inset 0 2px 4px rgba(0,0,0,0.70)",
|
|
55
|
+
"inner-strong": "inset 0 2px 8px rgba(0,0,0,0.90)",
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
export type ShadowKey = keyof typeof NEXUI_SHADOWS_VOID;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @yugnex/nexui — Spacing Scale
|
|
2
|
+
// 4px base unit. All values are multiples of 4px.
|
|
3
|
+
|
|
4
|
+
export const NEXUI_SPACE = {
|
|
5
|
+
0: "0px",
|
|
6
|
+
px: "1px",
|
|
7
|
+
0.5: "2px",
|
|
8
|
+
1: "4px",
|
|
9
|
+
1.5: "6px",
|
|
10
|
+
2: "8px",
|
|
11
|
+
2.5: "10px",
|
|
12
|
+
3: "12px",
|
|
13
|
+
3.5: "14px",
|
|
14
|
+
4: "16px",
|
|
15
|
+
5: "20px",
|
|
16
|
+
6: "24px",
|
|
17
|
+
7: "28px",
|
|
18
|
+
8: "32px",
|
|
19
|
+
9: "36px",
|
|
20
|
+
10: "40px",
|
|
21
|
+
11: "44px",
|
|
22
|
+
12: "48px",
|
|
23
|
+
14: "56px",
|
|
24
|
+
16: "64px",
|
|
25
|
+
20: "80px",
|
|
26
|
+
24: "96px",
|
|
27
|
+
28: "112px",
|
|
28
|
+
32: "128px",
|
|
29
|
+
36: "144px",
|
|
30
|
+
40: "160px",
|
|
31
|
+
44: "176px",
|
|
32
|
+
48: "192px",
|
|
33
|
+
52: "208px",
|
|
34
|
+
56: "224px",
|
|
35
|
+
60: "240px",
|
|
36
|
+
64: "256px",
|
|
37
|
+
72: "288px",
|
|
38
|
+
80: "320px",
|
|
39
|
+
96: "384px",
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
export type SpaceKey = keyof typeof NEXUI_SPACE;
|
|
43
|
+
|
|
44
|
+
// Semantic spacing aliases — what components reference
|
|
45
|
+
export const NEXUI_SPACE_SEMANTIC = {
|
|
46
|
+
"component-xs": NEXUI_SPACE[1], // 4px — tight internal padding
|
|
47
|
+
"component-sm": NEXUI_SPACE[2], // 8px — small component padding
|
|
48
|
+
"component-md": NEXUI_SPACE[3], // 12px — standard component padding
|
|
49
|
+
"component-lg": NEXUI_SPACE[4], // 16px — large component padding
|
|
50
|
+
"component-xl": NEXUI_SPACE[6], // 24px — extra-large component padding
|
|
51
|
+
|
|
52
|
+
"layout-xs": NEXUI_SPACE[4], // 16px — tight section gap
|
|
53
|
+
"layout-sm": NEXUI_SPACE[6], // 24px — small section gap
|
|
54
|
+
"layout-md": NEXUI_SPACE[8], // 32px — standard section gap
|
|
55
|
+
"layout-lg": NEXUI_SPACE[12], // 48px — large section gap
|
|
56
|
+
"layout-xl": NEXUI_SPACE[16], // 64px — page-level gap
|
|
57
|
+
|
|
58
|
+
"inline-xs": NEXUI_SPACE[1], // 4px — inline element gap
|
|
59
|
+
"inline-sm": NEXUI_SPACE[2], // 8px — small inline gap
|
|
60
|
+
"inline-md": NEXUI_SPACE[3], // 12px — standard inline gap
|
|
61
|
+
"inline-lg": NEXUI_SPACE[4], // 16px — large inline gap
|
|
62
|
+
|
|
63
|
+
"icon-sm": NEXUI_SPACE[4], // 16px — small icon size
|
|
64
|
+
"icon-md": NEXUI_SPACE[5], // 20px — standard icon size
|
|
65
|
+
"icon-lg": NEXUI_SPACE[6], // 24px — large icon size
|
|
66
|
+
|
|
67
|
+
"radius-none": "0px",
|
|
68
|
+
"radius-xs": "2px",
|
|
69
|
+
"radius-sm": "4px",
|
|
70
|
+
"radius-md": "6px",
|
|
71
|
+
"radius-lg": "8px",
|
|
72
|
+
"radius-xl": "12px",
|
|
73
|
+
"radius-2xl": "16px",
|
|
74
|
+
"radius-full": "9999px",
|
|
75
|
+
|
|
76
|
+
"border-thin": "1px",
|
|
77
|
+
"border-medium": "1.5px",
|
|
78
|
+
"border-thick": "2px",
|
|
79
|
+
} as const;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// @yugnex/nexui — Typography Tokens
|
|
2
|
+
// Fluid type scale: clamp(minPx, yIntersect + slope*100vw, maxPx)
|
|
3
|
+
// Min viewport: 320px. Max viewport: 1440px.
|
|
4
|
+
|
|
5
|
+
const MIN_VP = 320;
|
|
6
|
+
const MAX_VP = 1440;
|
|
7
|
+
|
|
8
|
+
function fluid(minPx: number, maxPx: number): string {
|
|
9
|
+
const slope = (maxPx - minPx) / (MAX_VP - MIN_VP);
|
|
10
|
+
const y = minPx - slope * MIN_VP;
|
|
11
|
+
const yFixed = parseFloat(y.toFixed(4));
|
|
12
|
+
const slopeFixed = parseFloat((slope * 100).toFixed(4));
|
|
13
|
+
const sign = yFixed >= 0 ? "+" : "-";
|
|
14
|
+
return `clamp(${minPx}px, ${Math.abs(yFixed)}px ${sign} ${slopeFixed}vw, ${maxPx}px)`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Type scale — based on a modular scale of 1.25 (Major Third)
|
|
18
|
+
export const NEXUI_FONT_SIZE = {
|
|
19
|
+
"2xs": fluid(10, 11), // micro labels, timestamps
|
|
20
|
+
"xs": fluid(11, 12), // captions, helper text
|
|
21
|
+
"sm": fluid(12, 13), // secondary body, badge text
|
|
22
|
+
"base": fluid(13, 14), // primary body
|
|
23
|
+
"md": fluid(14, 15), // large body, button labels
|
|
24
|
+
"lg": fluid(16, 18), // subheading
|
|
25
|
+
"xl": fluid(18, 20), // section heading
|
|
26
|
+
"2xl": fluid(20, 24), // page heading
|
|
27
|
+
"3xl": fluid(24, 30), // display sm
|
|
28
|
+
"4xl": fluid(30, 36), // display md
|
|
29
|
+
"5xl": fluid(36, 48), // display lg
|
|
30
|
+
"6xl": fluid(48, 60), // hero
|
|
31
|
+
"7xl": fluid(60, 72), // mega hero
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export const NEXUI_LINE_HEIGHT = {
|
|
35
|
+
"none": "1",
|
|
36
|
+
"tight": "1.15",
|
|
37
|
+
"snug": "1.3",
|
|
38
|
+
"normal": "1.5",
|
|
39
|
+
"relaxed": "1.65",
|
|
40
|
+
"loose": "1.8",
|
|
41
|
+
"code": "1.7",
|
|
42
|
+
} as const;
|
|
43
|
+
|
|
44
|
+
export const NEXUI_LETTER_SPACING = {
|
|
45
|
+
"tighter": "-0.04em",
|
|
46
|
+
"tight": "-0.02em",
|
|
47
|
+
"normal": "0em",
|
|
48
|
+
"wide": "0.04em",
|
|
49
|
+
"wider": "0.08em",
|
|
50
|
+
"widest": "0.16em",
|
|
51
|
+
"mono": "0.02em",
|
|
52
|
+
"caps": "0.06em",
|
|
53
|
+
} as const;
|
|
54
|
+
|
|
55
|
+
export const NEXUI_FONT_WEIGHT = {
|
|
56
|
+
"thin": "100",
|
|
57
|
+
"extralight": "200",
|
|
58
|
+
"light": "300",
|
|
59
|
+
"regular": "400",
|
|
60
|
+
"medium": "500",
|
|
61
|
+
"semibold": "600",
|
|
62
|
+
"bold": "700",
|
|
63
|
+
"extrabold": "800",
|
|
64
|
+
"black": "900",
|
|
65
|
+
} as const;
|
|
66
|
+
|
|
67
|
+
// Font family stacks — zero font file dependency (web-safe system stack)
|
|
68
|
+
// When NexuiSans/NexuiMono WOFF2 files are available, prepend them first.
|
|
69
|
+
export const NEXUI_FONT_FAMILY = {
|
|
70
|
+
"sans": [
|
|
71
|
+
"NexuiSans", // reserved — provide via @font-face
|
|
72
|
+
"Inter", // common on modern systems
|
|
73
|
+
"system-ui",
|
|
74
|
+
"-apple-system",
|
|
75
|
+
"BlinkMacSystemFont",
|
|
76
|
+
"Segoe UI",
|
|
77
|
+
"Roboto",
|
|
78
|
+
"Helvetica Neue",
|
|
79
|
+
"Arial",
|
|
80
|
+
"sans-serif",
|
|
81
|
+
].join(", "),
|
|
82
|
+
|
|
83
|
+
"mono": [
|
|
84
|
+
"NexuiMono", // reserved — provide via @font-face
|
|
85
|
+
"JetBrains Mono",
|
|
86
|
+
"Fira Code",
|
|
87
|
+
"Cascadia Code",
|
|
88
|
+
"SF Mono",
|
|
89
|
+
"ui-monospace",
|
|
90
|
+
"SFMono-Regular",
|
|
91
|
+
"Menlo",
|
|
92
|
+
"Monaco",
|
|
93
|
+
"Consolas",
|
|
94
|
+
"Liberation Mono",
|
|
95
|
+
"Courier New",
|
|
96
|
+
"monospace",
|
|
97
|
+
].join(", "),
|
|
98
|
+
|
|
99
|
+
"display": [
|
|
100
|
+
"NexuiDisplay", // reserved — provide via @font-face
|
|
101
|
+
"Cal Sans",
|
|
102
|
+
"DM Sans",
|
|
103
|
+
"Inter",
|
|
104
|
+
"system-ui",
|
|
105
|
+
"sans-serif",
|
|
106
|
+
].join(", "),
|
|
107
|
+
} as const;
|
|
108
|
+
|
|
109
|
+
// Semantic text role presets — map directly to component style objects
|
|
110
|
+
export const NEXUI_TEXT_ROLES = {
|
|
111
|
+
"display-lg": {
|
|
112
|
+
fontSize: NEXUI_FONT_SIZE["5xl"],
|
|
113
|
+
fontWeight: NEXUI_FONT_WEIGHT["bold"],
|
|
114
|
+
lineHeight: NEXUI_LINE_HEIGHT["tight"],
|
|
115
|
+
letterSpacing: NEXUI_LETTER_SPACING["tight"],
|
|
116
|
+
fontFamily: NEXUI_FONT_FAMILY["display"],
|
|
117
|
+
},
|
|
118
|
+
"display-md": {
|
|
119
|
+
fontSize: NEXUI_FONT_SIZE["4xl"],
|
|
120
|
+
fontWeight: NEXUI_FONT_WEIGHT["bold"],
|
|
121
|
+
lineHeight: NEXUI_LINE_HEIGHT["tight"],
|
|
122
|
+
letterSpacing: NEXUI_LETTER_SPACING["tight"],
|
|
123
|
+
fontFamily: NEXUI_FONT_FAMILY["display"],
|
|
124
|
+
},
|
|
125
|
+
"heading-xl": {
|
|
126
|
+
fontSize: NEXUI_FONT_SIZE["3xl"],
|
|
127
|
+
fontWeight: NEXUI_FONT_WEIGHT["semibold"],
|
|
128
|
+
lineHeight: NEXUI_LINE_HEIGHT["snug"],
|
|
129
|
+
letterSpacing: NEXUI_LETTER_SPACING["tight"],
|
|
130
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
131
|
+
},
|
|
132
|
+
"heading-lg": {
|
|
133
|
+
fontSize: NEXUI_FONT_SIZE["2xl"],
|
|
134
|
+
fontWeight: NEXUI_FONT_WEIGHT["semibold"],
|
|
135
|
+
lineHeight: NEXUI_LINE_HEIGHT["snug"],
|
|
136
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
137
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
138
|
+
},
|
|
139
|
+
"heading-md": {
|
|
140
|
+
fontSize: NEXUI_FONT_SIZE["xl"],
|
|
141
|
+
fontWeight: NEXUI_FONT_WEIGHT["semibold"],
|
|
142
|
+
lineHeight: NEXUI_LINE_HEIGHT["snug"],
|
|
143
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
144
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
145
|
+
},
|
|
146
|
+
"heading-sm": {
|
|
147
|
+
fontSize: NEXUI_FONT_SIZE["lg"],
|
|
148
|
+
fontWeight: NEXUI_FONT_WEIGHT["medium"],
|
|
149
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
150
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
151
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
152
|
+
},
|
|
153
|
+
"label-lg": {
|
|
154
|
+
fontSize: NEXUI_FONT_SIZE["md"],
|
|
155
|
+
fontWeight: NEXUI_FONT_WEIGHT["medium"],
|
|
156
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
157
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
158
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
159
|
+
},
|
|
160
|
+
"label-md": {
|
|
161
|
+
fontSize: NEXUI_FONT_SIZE["base"],
|
|
162
|
+
fontWeight: NEXUI_FONT_WEIGHT["medium"],
|
|
163
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
164
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
165
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
166
|
+
},
|
|
167
|
+
"label-sm": {
|
|
168
|
+
fontSize: NEXUI_FONT_SIZE["sm"],
|
|
169
|
+
fontWeight: NEXUI_FONT_WEIGHT["medium"],
|
|
170
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
171
|
+
letterSpacing: NEXUI_LETTER_SPACING["wide"],
|
|
172
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
173
|
+
},
|
|
174
|
+
"label-caps": {
|
|
175
|
+
fontSize: NEXUI_FONT_SIZE["xs"],
|
|
176
|
+
fontWeight: NEXUI_FONT_WEIGHT["semibold"],
|
|
177
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
178
|
+
letterSpacing: NEXUI_LETTER_SPACING["caps"],
|
|
179
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
180
|
+
textTransform: "uppercase" as const,
|
|
181
|
+
},
|
|
182
|
+
"body-lg": {
|
|
183
|
+
fontSize: NEXUI_FONT_SIZE["md"],
|
|
184
|
+
fontWeight: NEXUI_FONT_WEIGHT["regular"],
|
|
185
|
+
lineHeight: NEXUI_LINE_HEIGHT["relaxed"],
|
|
186
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
187
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
188
|
+
},
|
|
189
|
+
"body-md": {
|
|
190
|
+
fontSize: NEXUI_FONT_SIZE["base"],
|
|
191
|
+
fontWeight: NEXUI_FONT_WEIGHT["regular"],
|
|
192
|
+
lineHeight: NEXUI_LINE_HEIGHT["relaxed"],
|
|
193
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
194
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
195
|
+
},
|
|
196
|
+
"body-sm": {
|
|
197
|
+
fontSize: NEXUI_FONT_SIZE["sm"],
|
|
198
|
+
fontWeight: NEXUI_FONT_WEIGHT["regular"],
|
|
199
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
200
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
201
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
202
|
+
},
|
|
203
|
+
"caption": {
|
|
204
|
+
fontSize: NEXUI_FONT_SIZE["xs"],
|
|
205
|
+
fontWeight: NEXUI_FONT_WEIGHT["regular"],
|
|
206
|
+
lineHeight: NEXUI_LINE_HEIGHT["normal"],
|
|
207
|
+
letterSpacing: NEXUI_LETTER_SPACING["normal"],
|
|
208
|
+
fontFamily: NEXUI_FONT_FAMILY["sans"],
|
|
209
|
+
},
|
|
210
|
+
"code-base": {
|
|
211
|
+
fontSize: NEXUI_FONT_SIZE["sm"],
|
|
212
|
+
fontWeight: NEXUI_FONT_WEIGHT["regular"],
|
|
213
|
+
lineHeight: NEXUI_LINE_HEIGHT["code"],
|
|
214
|
+
letterSpacing: NEXUI_LETTER_SPACING["mono"],
|
|
215
|
+
fontFamily: NEXUI_FONT_FAMILY["mono"],
|
|
216
|
+
},
|
|
217
|
+
"code-sm": {
|
|
218
|
+
fontSize: NEXUI_FONT_SIZE["xs"],
|
|
219
|
+
fontWeight: NEXUI_FONT_WEIGHT["regular"],
|
|
220
|
+
lineHeight: NEXUI_LINE_HEIGHT["code"],
|
|
221
|
+
letterSpacing: NEXUI_LETTER_SPACING["mono"],
|
|
222
|
+
fontFamily: NEXUI_FONT_FAMILY["mono"],
|
|
223
|
+
},
|
|
224
|
+
} as const;
|