@thesage/ui 0.0.12 → 0.0.13
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/README.md +5 -5
- package/dist/index.d.mts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +89 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +89 -51
- package/dist/index.mjs.map +1 -1
- package/dist/providers.js +44 -0
- package/dist/providers.js.map +1 -1
- package/dist/providers.mjs +44 -0
- package/dist/providers.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Sage
|
|
1
|
+
# Sage Design Engine (@thesage/ui)
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
**Sage
|
|
17
|
+
**Sage Design Engine** is not just a component library—it's a systematic design engine built for speed, consistency, and beauty. Built on top of **Radix UI** for headless accessibility and **Tailwind CSS** for styling, it provides a comprehensive suite of 45+ polished components that work together seamlessly.
|
|
18
18
|
|
|
19
19
|
## ✨ Features
|
|
20
20
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
## 🚀 Installation
|
|
28
28
|
|
|
29
29
|
### 1. Install Dependencies
|
|
30
|
-
Sage
|
|
30
|
+
Sage Design Engine is built on Tailwind CSS. You need to install the package and its peer dependencies.
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
pnpm add @thesage/ui @thesage/tokens @thesage/hooks lucide-react clsx tailwind-merge
|
|
@@ -61,7 +61,7 @@ import '@thesage/ui/globals.css';
|
|
|
61
61
|
|
|
62
62
|
## 💻 Usage
|
|
63
63
|
|
|
64
|
-
Sage
|
|
64
|
+
Sage Design Engine components are designed to be dropped into any React application.
|
|
65
65
|
|
|
66
66
|
```tsx
|
|
67
67
|
import { Button, Card, Text, Heading } from '@thesage/ui';
|
|
@@ -84,7 +84,7 @@ export default function WelcomeCard() {
|
|
|
84
84
|
|
|
85
85
|
## 🖌️ Theming
|
|
86
86
|
|
|
87
|
-
Sage
|
|
87
|
+
Sage Design Engine uses a 4-layer token system. Changing a single primary color automatically updates buttons, focus rings, and chart colors across your entire application.
|
|
88
88
|
|
|
89
89
|
```tsx
|
|
90
90
|
// Example: Customizing the theme
|
package/dist/index.d.mts
CHANGED
|
@@ -2207,9 +2207,28 @@ interface OrbBackgroundProps {
|
|
|
2207
2207
|
hoverIntensity?: number;
|
|
2208
2208
|
rotateOnHover?: boolean;
|
|
2209
2209
|
forceHoverState?: boolean;
|
|
2210
|
+
/**
|
|
2211
|
+
* Background color (hex). If not provided, uses CSS variable --color-background.
|
|
2212
|
+
* @default undefined (reads from theme)
|
|
2213
|
+
*/
|
|
2210
2214
|
backgroundColor?: string;
|
|
2215
|
+
/**
|
|
2216
|
+
* Primary orb color (hex). Creates the main vibrant tone.
|
|
2217
|
+
* @default '#9c43fe' (purple)
|
|
2218
|
+
*/
|
|
2219
|
+
orbColor1?: string;
|
|
2220
|
+
/**
|
|
2221
|
+
* Secondary orb color (hex). Adds cool cyan tones.
|
|
2222
|
+
* @default '#4cc2e9' (cyan)
|
|
2223
|
+
*/
|
|
2224
|
+
orbColor2?: string;
|
|
2225
|
+
/**
|
|
2226
|
+
* Tertiary orb color (hex). Provides deep blue accent tones.
|
|
2227
|
+
* @default '#101499' (deep blue)
|
|
2228
|
+
*/
|
|
2229
|
+
orbColor3?: string;
|
|
2211
2230
|
}
|
|
2212
|
-
declare function OrbBackground({ className, hue, hoverIntensity, rotateOnHover, forceHoverState, backgroundColor }: OrbBackgroundProps): react_jsx_runtime.JSX.Element;
|
|
2231
|
+
declare function OrbBackground({ className, hue, hoverIntensity, rotateOnHover, forceHoverState, backgroundColor, orbColor1, orbColor2, orbColor3, }: OrbBackgroundProps): react_jsx_runtime.JSX.Element;
|
|
2213
2232
|
|
|
2214
2233
|
interface HeroBlockProps {
|
|
2215
2234
|
className?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -2207,9 +2207,28 @@ interface OrbBackgroundProps {
|
|
|
2207
2207
|
hoverIntensity?: number;
|
|
2208
2208
|
rotateOnHover?: boolean;
|
|
2209
2209
|
forceHoverState?: boolean;
|
|
2210
|
+
/**
|
|
2211
|
+
* Background color (hex). If not provided, uses CSS variable --color-background.
|
|
2212
|
+
* @default undefined (reads from theme)
|
|
2213
|
+
*/
|
|
2210
2214
|
backgroundColor?: string;
|
|
2215
|
+
/**
|
|
2216
|
+
* Primary orb color (hex). Creates the main vibrant tone.
|
|
2217
|
+
* @default '#9c43fe' (purple)
|
|
2218
|
+
*/
|
|
2219
|
+
orbColor1?: string;
|
|
2220
|
+
/**
|
|
2221
|
+
* Secondary orb color (hex). Adds cool cyan tones.
|
|
2222
|
+
* @default '#4cc2e9' (cyan)
|
|
2223
|
+
*/
|
|
2224
|
+
orbColor2?: string;
|
|
2225
|
+
/**
|
|
2226
|
+
* Tertiary orb color (hex). Provides deep blue accent tones.
|
|
2227
|
+
* @default '#101499' (deep blue)
|
|
2228
|
+
*/
|
|
2229
|
+
orbColor3?: string;
|
|
2211
2230
|
}
|
|
2212
|
-
declare function OrbBackground({ className, hue, hoverIntensity, rotateOnHover, forceHoverState, backgroundColor }: OrbBackgroundProps): react_jsx_runtime.JSX.Element;
|
|
2231
|
+
declare function OrbBackground({ className, hue, hoverIntensity, rotateOnHover, forceHoverState, backgroundColor, orbColor1, orbColor2, orbColor3, }: OrbBackgroundProps): react_jsx_runtime.JSX.Element;
|
|
2213
2232
|
|
|
2214
2233
|
interface HeroBlockProps {
|
|
2215
2234
|
className?: string;
|
package/dist/index.js
CHANGED
|
@@ -9880,13 +9880,30 @@ var AnimatedBeam = ({
|
|
|
9880
9880
|
var import_ogl3 = require("ogl");
|
|
9881
9881
|
var import_react36 = require("react");
|
|
9882
9882
|
var import_jsx_runtime85 = require("react/jsx-runtime");
|
|
9883
|
+
function hexToRgb4(hex) {
|
|
9884
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
9885
|
+
if (!result) return [0, 0, 0];
|
|
9886
|
+
return [
|
|
9887
|
+
parseInt(result[1], 16) / 255,
|
|
9888
|
+
parseInt(result[2], 16) / 255,
|
|
9889
|
+
parseInt(result[3], 16) / 255
|
|
9890
|
+
];
|
|
9891
|
+
}
|
|
9892
|
+
function getCSSVariable2(name, fallback) {
|
|
9893
|
+
if (typeof window === "undefined") return fallback;
|
|
9894
|
+
const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
9895
|
+
return value || fallback;
|
|
9896
|
+
}
|
|
9883
9897
|
function OrbBackground({
|
|
9884
9898
|
className,
|
|
9885
9899
|
hue = 0,
|
|
9886
9900
|
hoverIntensity = 0.2,
|
|
9887
9901
|
rotateOnHover = true,
|
|
9888
9902
|
forceHoverState = false,
|
|
9889
|
-
backgroundColor
|
|
9903
|
+
backgroundColor,
|
|
9904
|
+
orbColor1,
|
|
9905
|
+
orbColor2,
|
|
9906
|
+
orbColor3
|
|
9890
9907
|
}) {
|
|
9891
9908
|
const ctnDom = (0, import_react36.useRef)(null);
|
|
9892
9909
|
const vert = (
|
|
@@ -9914,6 +9931,10 @@ function OrbBackground({
|
|
|
9914
9931
|
uniform float rot;
|
|
9915
9932
|
uniform float hoverIntensity;
|
|
9916
9933
|
uniform vec3 backgroundColor;
|
|
9934
|
+
// THEME-AWARE: Orb colors from theme (to revert: change back to const)
|
|
9935
|
+
uniform vec3 orbColor1;
|
|
9936
|
+
uniform vec3 orbColor2;
|
|
9937
|
+
uniform vec3 orbColor3;
|
|
9917
9938
|
varying vec2 vUv;
|
|
9918
9939
|
|
|
9919
9940
|
vec3 rgb2yiq(vec3 c) {
|
|
@@ -9982,10 +10003,12 @@ function OrbBackground({
|
|
|
9982
10003
|
float a = max(max(colorIn.r, colorIn.g), colorIn.b);
|
|
9983
10004
|
return vec4(colorIn.rgb / (a + 1e-5), a);
|
|
9984
10005
|
}
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
const vec3
|
|
10006
|
+
|
|
10007
|
+
// THEME-AWARE: Colors now come from uniforms (orbColor1, orbColor2, orbColor3)
|
|
10008
|
+
// To revert to hardcoded: uncomment these and remove uniforms above
|
|
10009
|
+
// const vec3 baseColor1 = vec3(0.611765, 0.262745, 0.996078);
|
|
10010
|
+
// const vec3 baseColor2 = vec3(0.298039, 0.760784, 0.913725);
|
|
10011
|
+
// const vec3 baseColor3 = vec3(0.062745, 0.078431, 0.600000);
|
|
9989
10012
|
const float innerRadius = 0.6;
|
|
9990
10013
|
const float noiseScale = 0.65;
|
|
9991
10014
|
|
|
@@ -9998,9 +10021,10 @@ function OrbBackground({
|
|
|
9998
10021
|
}
|
|
9999
10022
|
|
|
10000
10023
|
vec4 draw(vec2 uv) {
|
|
10001
|
-
|
|
10002
|
-
vec3
|
|
10003
|
-
vec3
|
|
10024
|
+
// THEME-AWARE: Use uniform colors instead of hardcoded consts
|
|
10025
|
+
vec3 color1 = adjustHue(orbColor1, hue);
|
|
10026
|
+
vec3 color2 = adjustHue(orbColor2, hue);
|
|
10027
|
+
vec3 color3 = adjustHue(orbColor3, hue);
|
|
10004
10028
|
|
|
10005
10029
|
float ang = atan(uv.y, uv.x);
|
|
10006
10030
|
float len = length(uv);
|
|
@@ -10069,6 +10093,14 @@ function OrbBackground({
|
|
|
10069
10093
|
(0, import_react36.useEffect)(() => {
|
|
10070
10094
|
const container = ctnDom.current;
|
|
10071
10095
|
if (!container) return;
|
|
10096
|
+
const bgColor = backgroundColor || getCSSVariable2("--color-background", "#000000");
|
|
10097
|
+
const color1 = orbColor1 || "#9c43fe";
|
|
10098
|
+
const color2 = orbColor2 || "#4cc2e9";
|
|
10099
|
+
const color3 = orbColor3 || "#101499";
|
|
10100
|
+
const bgRgb = hexToRgb4(bgColor);
|
|
10101
|
+
const color1Rgb = hexToRgb4(color1);
|
|
10102
|
+
const color2Rgb = hexToRgb4(color2);
|
|
10103
|
+
const color3Rgb = hexToRgb4(color3);
|
|
10072
10104
|
const renderer = new import_ogl3.Renderer({ alpha: true, premultipliedAlpha: false });
|
|
10073
10105
|
const gl = renderer.gl;
|
|
10074
10106
|
gl.clearColor(0, 0, 0, 0);
|
|
@@ -10086,7 +10118,11 @@ function OrbBackground({
|
|
|
10086
10118
|
hover: { value: 0 },
|
|
10087
10119
|
rot: { value: 0 },
|
|
10088
10120
|
hoverIntensity: { value: hoverIntensity },
|
|
10089
|
-
|
|
10121
|
+
// THEME-AWARE: Pass theme colors to shader
|
|
10122
|
+
backgroundColor: { value: new import_ogl3.Vec3(...bgRgb) },
|
|
10123
|
+
orbColor1: { value: new import_ogl3.Vec3(...color1Rgb) },
|
|
10124
|
+
orbColor2: { value: new import_ogl3.Vec3(...color2Rgb) },
|
|
10125
|
+
orbColor3: { value: new import_ogl3.Vec3(...color3Rgb) }
|
|
10090
10126
|
}
|
|
10091
10127
|
});
|
|
10092
10128
|
const mesh = new import_ogl3.Mesh(gl, { geometry, program });
|
|
@@ -10143,7 +10179,6 @@ function OrbBackground({
|
|
|
10143
10179
|
currentRot += dt * rotationSpeed;
|
|
10144
10180
|
}
|
|
10145
10181
|
program.uniforms.rot.value = currentRot;
|
|
10146
|
-
program.uniforms.backgroundColor.value = hexToVec3(backgroundColor);
|
|
10147
10182
|
renderer.render({ scene: mesh });
|
|
10148
10183
|
};
|
|
10149
10184
|
rafId = requestAnimationFrame(update);
|
|
@@ -10160,47 +10195,6 @@ function OrbBackground({
|
|
|
10160
10195
|
}, [hue, hoverIntensity, rotateOnHover, forceHoverState, backgroundColor]);
|
|
10161
10196
|
return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { ref: ctnDom, className: cn("w-full h-full pointer-events-auto", className) });
|
|
10162
10197
|
}
|
|
10163
|
-
function hslToRgb(h, s, l) {
|
|
10164
|
-
let r, g, b;
|
|
10165
|
-
if (s === 0) {
|
|
10166
|
-
r = g = b = l;
|
|
10167
|
-
} else {
|
|
10168
|
-
const hue2rgb = (p2, q2, t) => {
|
|
10169
|
-
if (t < 0) t += 1;
|
|
10170
|
-
if (t > 1) t -= 1;
|
|
10171
|
-
if (t < 1 / 6) return p2 + (q2 - p2) * 6 * t;
|
|
10172
|
-
if (t < 1 / 2) return q2;
|
|
10173
|
-
if (t < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t) * 6;
|
|
10174
|
-
return p2;
|
|
10175
|
-
};
|
|
10176
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
10177
|
-
const p = 2 * l - q;
|
|
10178
|
-
r = hue2rgb(p, q, h + 1 / 3);
|
|
10179
|
-
g = hue2rgb(p, q, h);
|
|
10180
|
-
b = hue2rgb(p, q, h - 1 / 3);
|
|
10181
|
-
}
|
|
10182
|
-
return new import_ogl3.Vec3(r, g, b);
|
|
10183
|
-
}
|
|
10184
|
-
function hexToVec3(color) {
|
|
10185
|
-
if (color.startsWith("#")) {
|
|
10186
|
-
const r = parseInt(color.slice(1, 3), 16) / 255;
|
|
10187
|
-
const g = parseInt(color.slice(3, 5), 16) / 255;
|
|
10188
|
-
const b = parseInt(color.slice(5, 7), 16) / 255;
|
|
10189
|
-
return new import_ogl3.Vec3(r, g, b);
|
|
10190
|
-
}
|
|
10191
|
-
const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
10192
|
-
if (rgbMatch) {
|
|
10193
|
-
return new import_ogl3.Vec3(parseInt(rgbMatch[1]) / 255, parseInt(rgbMatch[2]) / 255, parseInt(rgbMatch[3]) / 255);
|
|
10194
|
-
}
|
|
10195
|
-
const hslMatch = color.match(/hsla?\((\d+),\s*(\d+)%,\s*(\d+)%/);
|
|
10196
|
-
if (hslMatch) {
|
|
10197
|
-
const h = parseInt(hslMatch[1]) / 360;
|
|
10198
|
-
const s = parseInt(hslMatch[2]) / 100;
|
|
10199
|
-
const l = parseInt(hslMatch[3]) / 100;
|
|
10200
|
-
return hslToRgb(h, s, l);
|
|
10201
|
-
}
|
|
10202
|
-
return new import_ogl3.Vec3(0, 0, 0);
|
|
10203
|
-
}
|
|
10204
10198
|
|
|
10205
10199
|
// src/components/blocks/Hero.tsx
|
|
10206
10200
|
var import_lucide_react22 = require("lucide-react");
|
|
@@ -11679,6 +11673,49 @@ function mergeCustomColorTokens(baseTokens2, customPalette) {
|
|
|
11679
11673
|
...customPalette.derivedTokens
|
|
11680
11674
|
};
|
|
11681
11675
|
}
|
|
11676
|
+
function validateThemeTokens(theme, mode) {
|
|
11677
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
|
|
11678
|
+
const root = document.documentElement;
|
|
11679
|
+
const style = getComputedStyle(root);
|
|
11680
|
+
const requiredTokens = [
|
|
11681
|
+
"--color-background",
|
|
11682
|
+
"--color-foreground",
|
|
11683
|
+
"--color-primary",
|
|
11684
|
+
"--color-primary-foreground",
|
|
11685
|
+
"--color-border",
|
|
11686
|
+
"--color-ring",
|
|
11687
|
+
"--font-heading",
|
|
11688
|
+
"--font-body",
|
|
11689
|
+
"--font-mono"
|
|
11690
|
+
];
|
|
11691
|
+
const missingTokens = [];
|
|
11692
|
+
const invalidTokens = [];
|
|
11693
|
+
requiredTokens.forEach((token) => {
|
|
11694
|
+
const value = style.getPropertyValue(token).trim();
|
|
11695
|
+
if (!value) {
|
|
11696
|
+
missingTokens.push(token);
|
|
11697
|
+
} else if (token.startsWith("--color-") && !value.match(/^(#|rgb|hsl|var\()/)) {
|
|
11698
|
+
invalidTokens.push(`${token} = "${value}"`);
|
|
11699
|
+
} else if (token.startsWith("--font-") && value === "") {
|
|
11700
|
+
invalidTokens.push(`${token} = empty`);
|
|
11701
|
+
}
|
|
11702
|
+
});
|
|
11703
|
+
if (missingTokens.length > 0) {
|
|
11704
|
+
console.warn(
|
|
11705
|
+
`[ThemeProvider] Missing CSS variables for theme "${theme}" (${mode} mode):`,
|
|
11706
|
+
missingTokens
|
|
11707
|
+
);
|
|
11708
|
+
}
|
|
11709
|
+
if (invalidTokens.length > 0) {
|
|
11710
|
+
console.warn(
|
|
11711
|
+
`[ThemeProvider] Invalid CSS variable values for theme "${theme}" (${mode} mode):`,
|
|
11712
|
+
invalidTokens
|
|
11713
|
+
);
|
|
11714
|
+
}
|
|
11715
|
+
if (missingTokens.length === 0 && invalidTokens.length === 0) {
|
|
11716
|
+
console.log(`[ThemeProvider] \u2713 Theme validation passed for "${theme}" (${mode} mode)`);
|
|
11717
|
+
}
|
|
11718
|
+
}
|
|
11682
11719
|
function ThemeProvider({ children }) {
|
|
11683
11720
|
const { theme, mode } = useThemeStore();
|
|
11684
11721
|
const customPalette = useCustomizer((state) => state.customColors?.[theme]?.[mode]);
|
|
@@ -11712,6 +11749,7 @@ function ThemeProvider({ children }) {
|
|
|
11712
11749
|
} else {
|
|
11713
11750
|
root.classList.remove("dark");
|
|
11714
11751
|
}
|
|
11752
|
+
validateThemeTokens(theme, mode);
|
|
11715
11753
|
const timeout = setTimeout(() => {
|
|
11716
11754
|
root.classList.remove("theme-transitioning");
|
|
11717
11755
|
setIsTransitioning(false);
|