primus-react-ui 1.0.14 → 1.1.1
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 +40 -30
- package/dist/index.d.mts +229 -115
- package/dist/index.d.ts +229 -115
- package/dist/index.js +1290 -611
- package/dist/index.mjs +1190 -534
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -760,7 +760,7 @@ var SecurityDashboard = ({
|
|
|
760
760
|
};
|
|
761
761
|
|
|
762
762
|
// src/components/auth/PrimusLogin.tsx
|
|
763
|
-
import { useState as
|
|
763
|
+
import { useState as useState14 } from "react";
|
|
764
764
|
|
|
765
765
|
// src/context/PrimusThemeProvider.tsx
|
|
766
766
|
import { createContext, useContext, useState as useState12, useCallback } from "react";
|
|
@@ -844,240 +844,144 @@ function PrimusThemeToggle() {
|
|
|
844
844
|
);
|
|
845
845
|
}
|
|
846
846
|
|
|
847
|
-
// src/components/auth/PrimusLogin.tsx
|
|
848
|
-
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
849
|
-
var providerConfigs = {
|
|
850
|
-
google: {
|
|
851
|
-
name: "Google",
|
|
852
|
-
icon: /* @__PURE__ */ jsxs12("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", children: [
|
|
853
|
-
/* @__PURE__ */ jsx13("path", { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }),
|
|
854
|
-
/* @__PURE__ */ jsx13("path", { fill: "#34A853", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }),
|
|
855
|
-
/* @__PURE__ */ jsx13("path", { fill: "#FBBC05", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" }),
|
|
856
|
-
/* @__PURE__ */ jsx13("path", { fill: "#EA4335", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })
|
|
857
|
-
] }),
|
|
858
|
-
colors: { light: "bg-white hover:bg-gray-50 text-gray-700 border-gray-300", dark: "bg-white hover:bg-gray-100 text-gray-700 border-gray-300" }
|
|
859
|
-
},
|
|
860
|
-
azure: {
|
|
861
|
-
name: "Microsoft",
|
|
862
|
-
icon: /* @__PURE__ */ jsxs12("svg", { className: "h-5 w-5", viewBox: "0 0 23 23", children: [
|
|
863
|
-
/* @__PURE__ */ jsx13("path", { fill: "#f35325", d: "M1 1h10v10H1z" }),
|
|
864
|
-
/* @__PURE__ */ jsx13("path", { fill: "#81bc06", d: "M12 1h10v10H12z" }),
|
|
865
|
-
/* @__PURE__ */ jsx13("path", { fill: "#05a6f0", d: "M1 12h10v10H1z" }),
|
|
866
|
-
/* @__PURE__ */ jsx13("path", { fill: "#ffba08", d: "M12 12h10v10H12z" })
|
|
867
|
-
] }),
|
|
868
|
-
colors: { light: "bg-white hover:bg-gray-50 text-gray-700 border-gray-300", dark: "bg-white hover:bg-gray-100 text-gray-700 border-gray-300" }
|
|
869
|
-
},
|
|
870
|
-
github: {
|
|
871
|
-
name: "GitHub",
|
|
872
|
-
icon: /* @__PURE__ */ jsx13("svg", { className: "h-5 w-5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { fillRule: "evenodd", d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z", clipRule: "evenodd" }) }),
|
|
873
|
-
colors: { light: "bg-gray-900 hover:bg-gray-800 text-white border-gray-900", dark: "bg-white hover:bg-gray-100 text-gray-900 border-gray-300" }
|
|
874
|
-
},
|
|
875
|
-
microsoft: {
|
|
876
|
-
name: "Microsoft",
|
|
877
|
-
icon: /* @__PURE__ */ jsxs12("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", children: [
|
|
878
|
-
/* @__PURE__ */ jsx13("path", { fill: "#F25022", d: "M1 1h10v10H1z" }),
|
|
879
|
-
/* @__PURE__ */ jsx13("path", { fill: "#00A4EF", d: "M1 13h10v10H1z" }),
|
|
880
|
-
/* @__PURE__ */ jsx13("path", { fill: "#7FBA00", d: "M13 1h10v10H13z" }),
|
|
881
|
-
/* @__PURE__ */ jsx13("path", { fill: "#FFB900", d: "M13 13h10v10H13z" })
|
|
882
|
-
] }),
|
|
883
|
-
colors: { light: "bg-white hover:bg-gray-50 text-gray-700 border-gray-300", dark: "bg-white hover:bg-gray-100 text-gray-700 border-gray-300" }
|
|
884
|
-
},
|
|
885
|
-
apple: {
|
|
886
|
-
name: "Apple",
|
|
887
|
-
icon: /* @__PURE__ */ jsx13("svg", { className: "h-5 w-5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { d: "M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" }) }),
|
|
888
|
-
colors: { light: "bg-black hover:bg-gray-900 text-white border-black", dark: "bg-white hover:bg-gray-100 text-black border-gray-300" }
|
|
889
|
-
},
|
|
890
|
-
facebook: {
|
|
891
|
-
name: "Facebook",
|
|
892
|
-
icon: /* @__PURE__ */ jsx13("svg", { className: "h-5 w-5", fill: "white", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13("path", { d: "M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" }) }),
|
|
893
|
-
colors: { light: "bg-[#1877F2] hover:bg-[#166FE5] text-white border-[#1877F2]", dark: "bg-[#1877F2] hover:bg-[#166FE5] text-white border-[#1877F2]" }
|
|
894
|
-
}
|
|
895
|
-
};
|
|
896
|
-
function PrimusLogin({
|
|
897
|
-
onLogin,
|
|
898
|
-
socialProviders = [],
|
|
899
|
-
onSocialLogin,
|
|
900
|
-
authEndpoint = "/api/auth",
|
|
901
|
-
showEmailLogin = true,
|
|
902
|
-
title = "Welcome Back",
|
|
903
|
-
subtitle = "Enter your credentials to continue",
|
|
904
|
-
logo,
|
|
905
|
-
theme: themeOverride
|
|
906
|
-
}) {
|
|
907
|
-
const themeContext = usePrimusTheme();
|
|
908
|
-
const theme = themeOverride || themeContext.theme;
|
|
909
|
-
const isLight = theme === "light";
|
|
910
|
-
const [username, setUsername] = useState13("");
|
|
911
|
-
const [password, setPassword] = useState13("");
|
|
912
|
-
const [loading, setLoading] = useState13(false);
|
|
913
|
-
const handleSubmit = async (e) => {
|
|
914
|
-
e.preventDefault();
|
|
915
|
-
if (!username || !password) return;
|
|
916
|
-
setLoading(true);
|
|
917
|
-
try {
|
|
918
|
-
onLogin?.({ username, password });
|
|
919
|
-
} finally {
|
|
920
|
-
setLoading(false);
|
|
921
|
-
}
|
|
922
|
-
};
|
|
923
|
-
const handleSocialClick = (provider) => {
|
|
924
|
-
if (onSocialLogin) {
|
|
925
|
-
onSocialLogin(provider);
|
|
926
|
-
} else {
|
|
927
|
-
window.location.href = `${authEndpoint}/${provider}`;
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
|
-
const bgGradient = isLight ? "bg-gradient-to-br from-gray-50 via-white to-violet-50" : "bg-gray-950";
|
|
931
|
-
const cardBg = isLight ? "bg-white border-gray-200 shadow-xl" : "bg-gray-900/50 border-white/10";
|
|
932
|
-
const headingColor = isLight ? "text-gray-900" : "text-white";
|
|
933
|
-
const subtextColor = isLight ? "text-gray-500" : "text-slate-400";
|
|
934
|
-
const labelColor = isLight ? "text-gray-600" : "text-slate-300";
|
|
935
|
-
const inputClasses = isLight ? "bg-gray-50 border-gray-300 text-gray-900 placeholder:text-gray-400 focus:border-violet-500 focus:ring-violet-500" : "bg-gray-950/50 border-slate-700 text-white placeholder:text-slate-600 focus:border-blue-500 focus:ring-blue-500";
|
|
936
|
-
const buttonGradient = isLight ? "bg-gradient-to-r from-violet-600 to-purple-600" : "bg-gradient-to-r from-blue-600 to-indigo-600";
|
|
937
|
-
const logoBg = isLight ? "bg-violet-600 shadow-violet-500/20" : "bg-blue-600 shadow-blue-500/20";
|
|
938
|
-
const dividerColor = isLight ? "border-gray-200" : "border-slate-700";
|
|
939
|
-
const hasSocial = socialProviders.length > 0;
|
|
940
|
-
return /* @__PURE__ */ jsxs12("div", { className: `min-h-screen ${bgGradient} flex items-center justify-center p-4`, children: [
|
|
941
|
-
!isLight && /* @__PURE__ */ jsxs12("div", { className: "absolute inset-0 overflow-hidden", children: [
|
|
942
|
-
/* @__PURE__ */ jsx13("div", { className: "absolute -top-[20%] -left-[10%] w-[50%] h-[50%] bg-blue-600/20 rounded-full blur-[120px]" }),
|
|
943
|
-
/* @__PURE__ */ jsx13("div", { className: "absolute -bottom-[20%] -right-[10%] w-[50%] h-[50%] bg-purple-600/20 rounded-full blur-[120px]" })
|
|
944
|
-
] }),
|
|
945
|
-
/* @__PURE__ */ jsxs12("div", { className: `w-full max-w-md ${cardBg} p-8 rounded-2xl border backdrop-blur-xl relative z-10`, children: [
|
|
946
|
-
/* @__PURE__ */ jsxs12("div", { className: "text-center mb-8", children: [
|
|
947
|
-
logo ? typeof logo === "string" ? /* @__PURE__ */ jsx13("img", { src: logo, alt: "Logo", className: "h-12 w-12 mx-auto mb-4 rounded-xl" }) : /* @__PURE__ */ jsx13("div", { className: "mb-4", children: logo }) : /* @__PURE__ */ jsx13("div", { className: `h-12 w-12 ${logoBg} rounded-xl mx-auto flex items-center justify-center mb-4 shadow-lg`, children: /* @__PURE__ */ jsx13("span", { className: "font-bold text-xl text-white", children: "P" }) }),
|
|
948
|
-
/* @__PURE__ */ jsx13("h1", { className: `text-2xl font-bold ${headingColor} tracking-tight`, children: title }),
|
|
949
|
-
/* @__PURE__ */ jsx13("p", { className: `${subtextColor} text-sm mt-2`, children: subtitle })
|
|
950
|
-
] }),
|
|
951
|
-
hasSocial && /* @__PURE__ */ jsx13("div", { className: "space-y-3 mb-6", children: socialProviders.map((provider) => {
|
|
952
|
-
const config = providerConfigs[provider];
|
|
953
|
-
if (!config) return null;
|
|
954
|
-
return /* @__PURE__ */ jsxs12(
|
|
955
|
-
"button",
|
|
956
|
-
{
|
|
957
|
-
onClick: () => handleSocialClick(provider),
|
|
958
|
-
className: `w-full flex items-center justify-center gap-3 px-4 py-2.5 border rounded-lg font-medium text-sm transition-all duration-200 ${isLight ? config.colors.light : config.colors.dark}`,
|
|
959
|
-
children: [
|
|
960
|
-
config.icon,
|
|
961
|
-
/* @__PURE__ */ jsxs12("span", { children: [
|
|
962
|
-
"Continue with ",
|
|
963
|
-
config.name
|
|
964
|
-
] })
|
|
965
|
-
]
|
|
966
|
-
},
|
|
967
|
-
provider
|
|
968
|
-
);
|
|
969
|
-
}) }),
|
|
970
|
-
hasSocial && showEmailLogin && /* @__PURE__ */ jsxs12("div", { className: "relative my-6", children: [
|
|
971
|
-
/* @__PURE__ */ jsx13("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx13("div", { className: `w-full border-t ${dividerColor}` }) }),
|
|
972
|
-
/* @__PURE__ */ jsx13("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx13("span", { className: `${isLight ? "bg-white" : "bg-gray-900/50"} px-2 ${subtextColor}`, children: "Or continue with email" }) })
|
|
973
|
-
] }),
|
|
974
|
-
showEmailLogin && /* @__PURE__ */ jsxs12("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
975
|
-
/* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
|
|
976
|
-
/* @__PURE__ */ jsx13("label", { className: `text-xs font-medium ${labelColor} ml-1`, children: "EMAIL" }),
|
|
977
|
-
/* @__PURE__ */ jsx13(
|
|
978
|
-
"input",
|
|
979
|
-
{
|
|
980
|
-
type: "text",
|
|
981
|
-
value: username,
|
|
982
|
-
onChange: (e) => setUsername(e.target.value),
|
|
983
|
-
className: `w-full px-4 py-2.5 ${inputClasses} border rounded-lg focus:outline-none focus:ring-1 transition-all text-sm`,
|
|
984
|
-
placeholder: "you@example.com"
|
|
985
|
-
}
|
|
986
|
-
)
|
|
987
|
-
] }),
|
|
988
|
-
/* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
|
|
989
|
-
/* @__PURE__ */ jsx13("label", { className: `text-xs font-medium ${labelColor} ml-1`, children: "PASSWORD" }),
|
|
990
|
-
/* @__PURE__ */ jsx13(
|
|
991
|
-
"input",
|
|
992
|
-
{
|
|
993
|
-
type: "password",
|
|
994
|
-
value: password,
|
|
995
|
-
onChange: (e) => setPassword(e.target.value),
|
|
996
|
-
className: `w-full px-4 py-2.5 ${inputClasses} border rounded-lg focus:outline-none focus:ring-1 transition-all text-sm`,
|
|
997
|
-
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
998
|
-
}
|
|
999
|
-
)
|
|
1000
|
-
] }),
|
|
1001
|
-
/* @__PURE__ */ jsx13(
|
|
1002
|
-
"button",
|
|
1003
|
-
{
|
|
1004
|
-
type: "submit",
|
|
1005
|
-
disabled: loading,
|
|
1006
|
-
className: `w-full mt-4 py-2.5 ${buttonGradient} text-white font-medium rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50`,
|
|
1007
|
-
children: loading ? "Signing in..." : "Sign In"
|
|
1008
|
-
}
|
|
1009
|
-
)
|
|
1010
|
-
] })
|
|
1011
|
-
] })
|
|
1012
|
-
] });
|
|
1013
|
-
}
|
|
1014
|
-
var LoginPage = PrimusLogin;
|
|
1015
|
-
|
|
1016
847
|
// src/context/PrimusProvider.tsx
|
|
1017
|
-
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect8, useState as
|
|
1018
|
-
import { jsx as
|
|
848
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect8, useState as useState13, useCallback as useCallback2, useRef } from "react";
|
|
849
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1019
850
|
var PrimusAuthContext = createContext2(void 0);
|
|
1020
851
|
var PrimusProvider = ({
|
|
1021
852
|
children,
|
|
1022
853
|
authority,
|
|
854
|
+
authBasePath = "/api/auth",
|
|
855
|
+
csrfCookieName = "XSRF-TOKEN",
|
|
856
|
+
csrfHeaderName = "X-Primus-CSRF",
|
|
857
|
+
seedCsrfOnLoad = true,
|
|
1023
858
|
clientId,
|
|
1024
859
|
onLoginSuccess,
|
|
1025
|
-
onLoginError
|
|
860
|
+
onLoginError,
|
|
861
|
+
heartbeatInterval = 3e5
|
|
862
|
+
// 5 minutes
|
|
1026
863
|
}) => {
|
|
1027
864
|
void clientId;
|
|
1028
|
-
const [isAuthenticated, setIsAuthenticated] =
|
|
1029
|
-
const [user, setUser] =
|
|
1030
|
-
const [token, setToken] =
|
|
1031
|
-
const [isLoading, setIsLoading] =
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
865
|
+
const [isAuthenticated, setIsAuthenticated] = useState13(false);
|
|
866
|
+
const [user, setUser] = useState13(null);
|
|
867
|
+
const [token, setToken] = useState13(null);
|
|
868
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
869
|
+
const heartbeatRef = useRef(null);
|
|
870
|
+
const trimTrailingSlash = (value) => value.replace(/\/+$/, "");
|
|
871
|
+
const ensureLeadingSlash = (value) => value.startsWith("/") ? value : `/${value}`;
|
|
872
|
+
const joinUrl = (base, path) => `${trimTrailingSlash(base)}${ensureLeadingSlash(path)}`;
|
|
873
|
+
const authBaseUrl = trimTrailingSlash(joinUrl(authority, authBasePath));
|
|
874
|
+
const getCookie = (name) => {
|
|
875
|
+
if (typeof document === "undefined") return null;
|
|
876
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
877
|
+
const matches = document.cookie.match(new RegExp(`(?:^|; )${escaped}=([^;]*)`));
|
|
878
|
+
return matches ? decodeURIComponent(matches[1]) : null;
|
|
879
|
+
};
|
|
880
|
+
const fetchSessionUser = useCallback2(async () => {
|
|
881
|
+
const response = await fetch(`${authBaseUrl}/me`, {
|
|
882
|
+
credentials: "include",
|
|
883
|
+
headers: {
|
|
884
|
+
"Accept": "application/json"
|
|
1043
885
|
}
|
|
886
|
+
});
|
|
887
|
+
if (!response.ok) return null;
|
|
888
|
+
const data = await response.json().catch(() => null);
|
|
889
|
+
if (!data) return null;
|
|
890
|
+
const resolvedUser = data.user ?? data;
|
|
891
|
+
return resolvedUser ?? null;
|
|
892
|
+
}, [authBaseUrl]);
|
|
893
|
+
const startHeartbeat = useCallback2(() => {
|
|
894
|
+
if (typeof window === "undefined") return;
|
|
895
|
+
if (heartbeatRef.current) clearInterval(heartbeatRef.current);
|
|
896
|
+
heartbeatRef.current = setInterval(() => {
|
|
897
|
+
fetchSessionUser().catch(() => {
|
|
898
|
+
});
|
|
899
|
+
}, heartbeatInterval);
|
|
900
|
+
}, [heartbeatInterval, fetchSessionUser]);
|
|
901
|
+
const stopHeartbeat = useCallback2(() => {
|
|
902
|
+
if (heartbeatRef.current) {
|
|
903
|
+
clearInterval(heartbeatRef.current);
|
|
904
|
+
heartbeatRef.current = null;
|
|
1044
905
|
}
|
|
1045
906
|
}, []);
|
|
907
|
+
useEffect8(() => {
|
|
908
|
+
return () => stopHeartbeat();
|
|
909
|
+
}, [stopHeartbeat]);
|
|
910
|
+
const seedCsrf = useCallback2(async () => {
|
|
911
|
+
try {
|
|
912
|
+
await fetch(`${authBaseUrl}/providers`, {
|
|
913
|
+
credentials: "include",
|
|
914
|
+
headers: { "Accept": "application/json" }
|
|
915
|
+
});
|
|
916
|
+
} catch {
|
|
917
|
+
}
|
|
918
|
+
}, [authBaseUrl]);
|
|
919
|
+
useEffect8(() => {
|
|
920
|
+
const checkSession = async () => {
|
|
921
|
+
setIsLoading(true);
|
|
922
|
+
try {
|
|
923
|
+
if (seedCsrfOnLoad) {
|
|
924
|
+
await seedCsrf();
|
|
925
|
+
}
|
|
926
|
+
const userData = await fetchSessionUser();
|
|
927
|
+
if (userData) {
|
|
928
|
+
setUser(userData);
|
|
929
|
+
setIsAuthenticated(true);
|
|
930
|
+
setToken("session-active");
|
|
931
|
+
startHeartbeat();
|
|
932
|
+
} else {
|
|
933
|
+
stopHeartbeat();
|
|
934
|
+
}
|
|
935
|
+
} catch (err) {
|
|
936
|
+
console.debug("No active session found", err);
|
|
937
|
+
setIsAuthenticated(false);
|
|
938
|
+
setUser(null);
|
|
939
|
+
stopHeartbeat();
|
|
940
|
+
} finally {
|
|
941
|
+
setIsLoading(false);
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
checkSession();
|
|
945
|
+
}, [fetchSessionUser, seedCsrf, seedCsrfOnLoad, startHeartbeat, stopHeartbeat]);
|
|
1046
946
|
const login = useCallback2(async (credentials) => {
|
|
1047
947
|
setIsLoading(true);
|
|
1048
948
|
try {
|
|
1049
|
-
let endpoint;
|
|
1050
|
-
let body;
|
|
1051
949
|
if ("provider" in credentials) {
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
|
|
950
|
+
window.location.href = `${authBaseUrl}/${credentials.provider}`;
|
|
951
|
+
return { success: true };
|
|
952
|
+
}
|
|
953
|
+
const csrfToken = getCookie(csrfCookieName);
|
|
954
|
+
const headers = {
|
|
955
|
+
"Content-Type": "application/json"
|
|
956
|
+
};
|
|
957
|
+
if (csrfToken) {
|
|
958
|
+
headers[csrfHeaderName] = csrfToken;
|
|
1057
959
|
}
|
|
1058
|
-
const response = await fetch(
|
|
960
|
+
const response = await fetch(`${authBaseUrl}/login`, {
|
|
1059
961
|
method: "POST",
|
|
1060
|
-
headers
|
|
1061
|
-
|
|
962
|
+
headers,
|
|
963
|
+
credentials: "include",
|
|
964
|
+
// CRITICAL: Persist HttpOnly Cookie
|
|
965
|
+
body: JSON.stringify({ email: credentials.email, password: credentials.password })
|
|
1062
966
|
});
|
|
1063
967
|
if (!response.ok) {
|
|
1064
968
|
const errorData = await response.json().catch(() => ({}));
|
|
1065
|
-
const errorMsg = errorData.message || `Login failed (${response.status})`;
|
|
969
|
+
const errorMsg = errorData.message || errorData.title || `Login failed (${response.status})`;
|
|
1066
970
|
onLoginError?.(errorMsg);
|
|
1067
971
|
return { success: false, error: errorMsg };
|
|
1068
972
|
}
|
|
1069
|
-
const data = await response.json();
|
|
1070
|
-
const
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
setToken(accessToken);
|
|
1078
|
-
setUser(userData);
|
|
973
|
+
const data = await response.json().catch(() => null);
|
|
974
|
+
const userData = data ? data.user || data : null;
|
|
975
|
+
const refreshedUser = userData ?? await fetchSessionUser();
|
|
976
|
+
setToken("session-active");
|
|
977
|
+
if (refreshedUser) {
|
|
978
|
+
setUser(refreshedUser);
|
|
979
|
+
startHeartbeat();
|
|
980
|
+
}
|
|
1079
981
|
setIsAuthenticated(true);
|
|
1080
|
-
|
|
982
|
+
if (refreshedUser) {
|
|
983
|
+
onLoginSuccess?.(refreshedUser, "session-active");
|
|
984
|
+
}
|
|
1081
985
|
return { success: true };
|
|
1082
986
|
} catch (err) {
|
|
1083
987
|
const errorMsg = err instanceof Error ? err.message : "Network error";
|
|
@@ -1086,15 +990,38 @@ var PrimusProvider = ({
|
|
|
1086
990
|
} finally {
|
|
1087
991
|
setIsLoading(false);
|
|
1088
992
|
}
|
|
1089
|
-
}, [
|
|
993
|
+
}, [authBaseUrl, csrfCookieName, csrfHeaderName, fetchSessionUser, onLoginError, onLoginSuccess, startHeartbeat]);
|
|
1090
994
|
const logout = useCallback2(async () => {
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
995
|
+
try {
|
|
996
|
+
stopHeartbeat();
|
|
997
|
+
const csrfToken = getCookie(csrfCookieName);
|
|
998
|
+
const headers = {};
|
|
999
|
+
if (csrfToken) {
|
|
1000
|
+
headers[csrfHeaderName] = csrfToken;
|
|
1001
|
+
}
|
|
1002
|
+
await fetch(`${authBaseUrl}/logout`, {
|
|
1003
|
+
method: "POST",
|
|
1004
|
+
credentials: "include",
|
|
1005
|
+
headers
|
|
1006
|
+
});
|
|
1007
|
+
} catch (e) {
|
|
1008
|
+
console.error("Logout failed", e);
|
|
1009
|
+
} finally {
|
|
1010
|
+
setToken(null);
|
|
1011
|
+
setIsAuthenticated(false);
|
|
1012
|
+
setUser(null);
|
|
1013
|
+
}
|
|
1014
|
+
}, [authBaseUrl, csrfCookieName, csrfHeaderName, stopHeartbeat]);
|
|
1015
|
+
return /* @__PURE__ */ jsx13(PrimusAuthContext.Provider, { value: {
|
|
1016
|
+
isAuthenticated,
|
|
1017
|
+
user,
|
|
1018
|
+
login,
|
|
1019
|
+
logout,
|
|
1020
|
+
token,
|
|
1021
|
+
isLoading,
|
|
1022
|
+
csrfCookieName,
|
|
1023
|
+
csrfHeaderName
|
|
1024
|
+
}, children });
|
|
1098
1025
|
};
|
|
1099
1026
|
var usePrimusAuth = () => {
|
|
1100
1027
|
const context = useContext2(PrimusAuthContext);
|
|
@@ -1106,18 +1033,300 @@ var usePrimusAuth = () => {
|
|
|
1106
1033
|
logout: async () => {
|
|
1107
1034
|
},
|
|
1108
1035
|
token: null,
|
|
1109
|
-
isLoading: false
|
|
1036
|
+
isLoading: false,
|
|
1037
|
+
csrfCookieName: "XSRF-TOKEN",
|
|
1038
|
+
csrfHeaderName: "X-Primus-CSRF"
|
|
1110
1039
|
};
|
|
1111
1040
|
}
|
|
1112
1041
|
return context;
|
|
1113
1042
|
};
|
|
1114
1043
|
|
|
1044
|
+
// src/components/auth/PrimusLogin.tsx
|
|
1045
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1046
|
+
var styles = {
|
|
1047
|
+
container: {
|
|
1048
|
+
minHeight: "100vh",
|
|
1049
|
+
display: "flex",
|
|
1050
|
+
alignItems: "center",
|
|
1051
|
+
justifyContent: "center",
|
|
1052
|
+
padding: "24px",
|
|
1053
|
+
fontFamily: '"Segoe UI", Arial, sans-serif',
|
|
1054
|
+
transition: "background-color 0.3s, color 0.3s"
|
|
1055
|
+
},
|
|
1056
|
+
card: {
|
|
1057
|
+
width: "100%",
|
|
1058
|
+
maxWidth: "420px",
|
|
1059
|
+
borderRadius: "16px",
|
|
1060
|
+
padding: "24px",
|
|
1061
|
+
boxShadow: "0 20px 40px rgba(15, 23, 42, 0.08)",
|
|
1062
|
+
border: "1px solid #e2e8f0",
|
|
1063
|
+
backgroundColor: "#ffffff"
|
|
1064
|
+
},
|
|
1065
|
+
header: {
|
|
1066
|
+
marginBottom: "24px",
|
|
1067
|
+
textAlign: "center"
|
|
1068
|
+
},
|
|
1069
|
+
logoStr: {
|
|
1070
|
+
width: "48px",
|
|
1071
|
+
height: "48px",
|
|
1072
|
+
borderRadius: "12px",
|
|
1073
|
+
marginBottom: "16px",
|
|
1074
|
+
objectFit: "cover"
|
|
1075
|
+
},
|
|
1076
|
+
title: {
|
|
1077
|
+
margin: "12px 0 4px",
|
|
1078
|
+
fontSize: "22px",
|
|
1079
|
+
fontWeight: "600"
|
|
1080
|
+
},
|
|
1081
|
+
subtitle: {
|
|
1082
|
+
margin: 0,
|
|
1083
|
+
fontSize: "13px",
|
|
1084
|
+
color: "#64748b"
|
|
1085
|
+
},
|
|
1086
|
+
socialGrid: {
|
|
1087
|
+
display: "grid",
|
|
1088
|
+
gap: "10px",
|
|
1089
|
+
marginTop: "16px"
|
|
1090
|
+
},
|
|
1091
|
+
socialBtn: {
|
|
1092
|
+
border: "1px solid #cbd5e1",
|
|
1093
|
+
background: "#ffffff",
|
|
1094
|
+
padding: "10px",
|
|
1095
|
+
borderRadius: "10px",
|
|
1096
|
+
fontSize: "13px",
|
|
1097
|
+
cursor: "pointer",
|
|
1098
|
+
color: "#0f172a",
|
|
1099
|
+
display: "flex",
|
|
1100
|
+
alignItems: "center",
|
|
1101
|
+
justifyContent: "center",
|
|
1102
|
+
gap: "8px",
|
|
1103
|
+
width: "100%",
|
|
1104
|
+
fontWeight: 500,
|
|
1105
|
+
transition: "background-color 0.2s"
|
|
1106
|
+
},
|
|
1107
|
+
divider: {
|
|
1108
|
+
margin: "24px 0",
|
|
1109
|
+
textAlign: "center",
|
|
1110
|
+
fontSize: "12px",
|
|
1111
|
+
color: "#94a3b8",
|
|
1112
|
+
position: "relative"
|
|
1113
|
+
},
|
|
1114
|
+
// Form
|
|
1115
|
+
form: {
|
|
1116
|
+
display: "grid",
|
|
1117
|
+
gap: "16px"
|
|
1118
|
+
},
|
|
1119
|
+
label: {
|
|
1120
|
+
display: "block",
|
|
1121
|
+
fontSize: "12px",
|
|
1122
|
+
color: "#64748b",
|
|
1123
|
+
fontWeight: 400,
|
|
1124
|
+
marginBottom: "6px"
|
|
1125
|
+
},
|
|
1126
|
+
input: {
|
|
1127
|
+
width: "100%",
|
|
1128
|
+
border: "1px solid #cbd5e1",
|
|
1129
|
+
borderRadius: "8px",
|
|
1130
|
+
padding: "10px 12px",
|
|
1131
|
+
background: "#ffffff",
|
|
1132
|
+
color: "#0f172a",
|
|
1133
|
+
fontSize: "14px",
|
|
1134
|
+
outline: "none"
|
|
1135
|
+
},
|
|
1136
|
+
submitBtn: {
|
|
1137
|
+
marginTop: "8px",
|
|
1138
|
+
background: "#8b5cf6",
|
|
1139
|
+
// Purple to match Angular
|
|
1140
|
+
color: "#ffffff",
|
|
1141
|
+
border: "none",
|
|
1142
|
+
borderRadius: "8px",
|
|
1143
|
+
padding: "10px",
|
|
1144
|
+
cursor: "pointer",
|
|
1145
|
+
fontWeight: 500,
|
|
1146
|
+
fontSize: "13px",
|
|
1147
|
+
width: "100%"
|
|
1148
|
+
},
|
|
1149
|
+
error: {
|
|
1150
|
+
marginTop: "12px",
|
|
1151
|
+
color: "#dc2626",
|
|
1152
|
+
fontSize: "12px",
|
|
1153
|
+
textAlign: "center"
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
var darkStyles = {
|
|
1157
|
+
container: { backgroundColor: "#0f172a", color: "#f8fafc" },
|
|
1158
|
+
card: { backgroundColor: "#1e293b", borderColor: "#334155", boxShadow: "none" },
|
|
1159
|
+
subtitle: { color: "#94a3b8" },
|
|
1160
|
+
socialBtn: { backgroundColor: "#1e293b", borderColor: "#334155", color: "#f8fafc" },
|
|
1161
|
+
label: { color: "#94a3b8" },
|
|
1162
|
+
input: { backgroundColor: "#0f172a", borderColor: "#334155", color: "#f8fafc" },
|
|
1163
|
+
submitBtn: { backgroundColor: "#8b5cf6" }
|
|
1164
|
+
// Purple to match Angular
|
|
1165
|
+
};
|
|
1166
|
+
var Icons = {
|
|
1167
|
+
google: /* @__PURE__ */ jsxs12("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
|
|
1168
|
+
/* @__PURE__ */ jsx14("path", { d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z", fill: "#4285F4" }),
|
|
1169
|
+
/* @__PURE__ */ jsx14("path", { d: "M9 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332C2.438 15.983 5.482 18 9 18z", fill: "#34A853" }),
|
|
1170
|
+
/* @__PURE__ */ jsx14("path", { d: "M3.964 10.707c-.18-.54-.282-1.117-.282-1.707 0-.593.102-1.17.282-1.709V4.958H.957C.347 6.173 0 7.548 0 9c0 1.452.348 2.827.957 4.042l3.007-2.335z", fill: "#FBBC05" }),
|
|
1171
|
+
/* @__PURE__ */ jsx14("path", { d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0 5.482 0 2.438 2.017.957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z", fill: "#EA4335" })
|
|
1172
|
+
] }),
|
|
1173
|
+
microsoft: /* @__PURE__ */ jsxs12("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
|
|
1174
|
+
/* @__PURE__ */ jsx14("path", { d: "M0 0h8.571v8.571H0V0z", fill: "#F25022" }),
|
|
1175
|
+
/* @__PURE__ */ jsx14("path", { d: "M9.429 0H18v8.571H9.429V0z", fill: "#7FBA00" }),
|
|
1176
|
+
/* @__PURE__ */ jsx14("path", { d: "M0 9.429h8.571V18H0V9.429z", fill: "#00A4EF" }),
|
|
1177
|
+
/* @__PURE__ */ jsx14("path", { d: "M9.429 9.429H18V18H9.429V9.429z", fill: "#FFB900" })
|
|
1178
|
+
] }),
|
|
1179
|
+
github: /* @__PURE__ */ jsx14("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "currentColor", children: /* @__PURE__ */ jsx14("path", { d: "M9 0C4.029 0 0 4.029 0 9c0 3.977 2.578 7.348 6.155 8.537.45.082.615-.195.615-.433 0-.213-.008-.923-.012-1.674-2.505.544-3.034-1.073-3.034-1.073-.41-1.04-1-1.316-1-1.316-.817-.558.062-.547.062-.547.903.064 1.378.927 1.378.927.803 1.376 2.107.978 2.62.748.082-.582.314-.978.572-1.203-2-.227-4.1-1-4.1-4.448 0-.983.35-1.786.927-2.416-.093-.228-.402-1.144.088-2.383 0 0 .756-.242 2.475.923A8.63 8.63 0 019 4.347c.765.004 1.535.103 2.254.303 1.718-1.165 2.473-.923 2.473-.923.491 1.239.182 2.155.089 2.383.578.63.926 1.433.926 2.416 0 3.457-2.104 4.218-4.109 4.44.323.278.611.827.611 1.667 0 1.203-.011 2.173-.011 2.469 0 .24.163.52.619.432C15.424 16.345 18 12.976 18 9c0-4.971-4.029-9-9-9z" }) }),
|
|
1180
|
+
apple: /* @__PURE__ */ jsx14("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "currentColor", children: /* @__PURE__ */ jsx14("path", { d: "M14.94 13.52c-.36.77-.54 1.12-1.01 1.8-.66.95-1.59 2.13-2.74 2.14-1.02.01-1.29-.66-2.68-.65-1.39.01-1.69.66-2.71.65-1.15-.01-2.01-1.07-2.67-2.02-1.85-2.66-2.04-5.78-.9-7.44.81-1.18 2.09-1.87 3.29-1.87 1.22 0 1.99.67 3 .67.98 0 1.58-.67 2.99-.67 1.07 0 2.2.58 3.01 1.58-2.64 1.45-2.21 5.23.42 6.81zM11.53 3.96c.52-.67.92-1.61.77-2.56-.84.04-1.84.59-2.43 1.29-.52.62-.96 1.58-.79 2.5.94.02 1.91-.53 2.45-1.23z" }) }),
|
|
1181
|
+
auth0: /* @__PURE__ */ jsx14("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "#EB5424", children: /* @__PURE__ */ jsx14("path", { d: "M13.98 0L9 7.83 4.02 0H0l9 15.59L18 0h-4.02zM9 10.41L4.02 18h9.96L9 10.41z" }) }),
|
|
1182
|
+
facebook: /* @__PURE__ */ jsx14("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "#1877F2", children: /* @__PURE__ */ jsx14("path", { d: "M18 9.05C18 4.05 13.97 0 9 0S0 4.05 0 9.05C0 13.58 3.29 17.34 7.59 18v-6.28H5.31V9.05h2.28V7.05c0-2.25 1.34-3.49 3.39-3.49.98 0 2.01.18 2.01.18v2.21h-1.13c-1.11 0-1.46.69-1.46 1.4v1.68h2.49l-.4 2.67h-2.09V18C14.71 17.34 18 13.58 18 9.05z" }) })
|
|
1183
|
+
};
|
|
1184
|
+
function PrimusLogin({
|
|
1185
|
+
onLogin,
|
|
1186
|
+
socialProviders = [],
|
|
1187
|
+
onSocialLogin,
|
|
1188
|
+
authEndpoint = "/api/auth",
|
|
1189
|
+
showEmailLogin = true,
|
|
1190
|
+
title = "Welcome Back",
|
|
1191
|
+
subtitle = "Enter your credentials to continue",
|
|
1192
|
+
logo,
|
|
1193
|
+
theme: themeOverride,
|
|
1194
|
+
variant = "standalone",
|
|
1195
|
+
useAuth = false
|
|
1196
|
+
}) {
|
|
1197
|
+
const themeContext = usePrimusTheme();
|
|
1198
|
+
const auth = usePrimusAuth();
|
|
1199
|
+
const theme = themeOverride || themeContext.theme;
|
|
1200
|
+
const isLight = theme === "light";
|
|
1201
|
+
const isDark = !isLight;
|
|
1202
|
+
const [username, setUsername] = useState14("");
|
|
1203
|
+
const [password, setPassword] = useState14("");
|
|
1204
|
+
const [loading, setLoading] = useState14(false);
|
|
1205
|
+
const [errorMessage, setErrorMessage] = useState14("");
|
|
1206
|
+
const currentStyles = {
|
|
1207
|
+
container: { ...styles.container, ...isDark ? darkStyles.container : {} },
|
|
1208
|
+
card: { ...styles.card, ...isDark ? darkStyles.card : {} },
|
|
1209
|
+
title: { ...styles.title, color: isLight ? "#0f172a" : "#f8fafc" },
|
|
1210
|
+
subtitle: { ...styles.subtitle, ...isDark ? darkStyles.subtitle : {} },
|
|
1211
|
+
input: { ...styles.input, ...isDark ? darkStyles.input : {} },
|
|
1212
|
+
socialBtn: { ...styles.socialBtn, ...isDark ? darkStyles.socialBtn : {} },
|
|
1213
|
+
label: { ...styles.label, ...isDark ? darkStyles.label : {} },
|
|
1214
|
+
submitBtn: { ...styles.submitBtn, ...isDark ? darkStyles.submitBtn : {} }
|
|
1215
|
+
};
|
|
1216
|
+
const handleSubmit = async (e) => {
|
|
1217
|
+
e.preventDefault();
|
|
1218
|
+
if (!username || !password) return;
|
|
1219
|
+
setLoading(true);
|
|
1220
|
+
setErrorMessage("");
|
|
1221
|
+
try {
|
|
1222
|
+
if (useAuth) {
|
|
1223
|
+
const result = await auth.login({ email: username, password });
|
|
1224
|
+
if (!result.success) {
|
|
1225
|
+
setErrorMessage(result.error || "Login failed");
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
onLogin?.({ username, password });
|
|
1230
|
+
} catch (err) {
|
|
1231
|
+
setErrorMessage("Login failed. Please try again.");
|
|
1232
|
+
} finally {
|
|
1233
|
+
setLoading(false);
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
const handleSocialClick = (provider) => {
|
|
1237
|
+
if (onSocialLogin) {
|
|
1238
|
+
onSocialLogin(provider);
|
|
1239
|
+
} else {
|
|
1240
|
+
const base = authEndpoint.replace(/\/+$/, "");
|
|
1241
|
+
window.location.href = `${base}/${provider}`;
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
const renderSocialIcon = (p) => {
|
|
1245
|
+
const key = p === "azure" ? "microsoft" : p;
|
|
1246
|
+
return Icons[key] || null;
|
|
1247
|
+
};
|
|
1248
|
+
const content = /* @__PURE__ */ jsxs12("div", { style: currentStyles.card, className: "primus-login-card", children: [
|
|
1249
|
+
/* @__PURE__ */ jsxs12("div", { style: styles.header, className: "primus-login-header", children: [
|
|
1250
|
+
logo && (typeof logo === "string" ? /* @__PURE__ */ jsx14("img", { src: logo, alt: "Logo", style: styles.logoStr }) : /* @__PURE__ */ jsx14("div", { style: { marginBottom: "16px", display: "flex", justifyContent: "center" }, children: logo })),
|
|
1251
|
+
/* @__PURE__ */ jsx14("h2", { style: currentStyles.title, children: title }),
|
|
1252
|
+
/* @__PURE__ */ jsx14("p", { style: currentStyles.subtitle, children: subtitle })
|
|
1253
|
+
] }),
|
|
1254
|
+
socialProviders.length > 0 && /* @__PURE__ */ jsx14("div", { style: styles.socialGrid, className: "primus-social", children: socialProviders.map((provider) => /* @__PURE__ */ jsxs12(
|
|
1255
|
+
"button",
|
|
1256
|
+
{
|
|
1257
|
+
type: "button",
|
|
1258
|
+
onClick: () => handleSocialClick(provider),
|
|
1259
|
+
style: currentStyles.socialBtn,
|
|
1260
|
+
onMouseOver: (e) => {
|
|
1261
|
+
if (isLight) e.currentTarget.style.backgroundColor = "#f1f5f9";
|
|
1262
|
+
else e.currentTarget.style.backgroundColor = "#334155";
|
|
1263
|
+
},
|
|
1264
|
+
onMouseOut: (e) => {
|
|
1265
|
+
if (isLight) e.currentTarget.style.backgroundColor = "#ffffff";
|
|
1266
|
+
else e.currentTarget.style.backgroundColor = "#1e293b";
|
|
1267
|
+
},
|
|
1268
|
+
children: [
|
|
1269
|
+
renderSocialIcon(provider),
|
|
1270
|
+
"Continue with ",
|
|
1271
|
+
provider === "azure" ? "Microsoft" : provider.charAt(0).toUpperCase() + provider.slice(1)
|
|
1272
|
+
]
|
|
1273
|
+
},
|
|
1274
|
+
provider
|
|
1275
|
+
)) }),
|
|
1276
|
+
socialProviders.length > 0 && showEmailLogin && /* @__PURE__ */ jsxs12("div", { style: styles.divider, className: "primus-divider", children: [
|
|
1277
|
+
/* @__PURE__ */ jsx14("span", { style: { backgroundColor: isLight ? "#fff" : "#1e293b", padding: "0 8px", position: "relative", zIndex: 1 }, children: "Or continue with email" }),
|
|
1278
|
+
/* @__PURE__ */ jsx14("div", { style: { position: "absolute", top: "50%", left: 0, right: 0, borderTop: isLight ? "1px solid #e2e8f0" : "1px solid #334155", zIndex: 0 } })
|
|
1279
|
+
] }),
|
|
1280
|
+
showEmailLogin && /* @__PURE__ */ jsxs12("form", { onSubmit: handleSubmit, style: styles.form, className: "primus-form", children: [
|
|
1281
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
1282
|
+
/* @__PURE__ */ jsx14("label", { style: currentStyles.label, children: "Email" }),
|
|
1283
|
+
/* @__PURE__ */ jsx14(
|
|
1284
|
+
"input",
|
|
1285
|
+
{
|
|
1286
|
+
type: "email",
|
|
1287
|
+
value: username,
|
|
1288
|
+
onChange: (e) => setUsername(e.target.value),
|
|
1289
|
+
style: currentStyles.input
|
|
1290
|
+
}
|
|
1291
|
+
)
|
|
1292
|
+
] }),
|
|
1293
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
1294
|
+
/* @__PURE__ */ jsx14("label", { style: currentStyles.label, children: "Password" }),
|
|
1295
|
+
/* @__PURE__ */ jsx14(
|
|
1296
|
+
"input",
|
|
1297
|
+
{
|
|
1298
|
+
type: "password",
|
|
1299
|
+
value: password,
|
|
1300
|
+
onChange: (e) => setPassword(e.target.value),
|
|
1301
|
+
style: currentStyles.input
|
|
1302
|
+
}
|
|
1303
|
+
)
|
|
1304
|
+
] }),
|
|
1305
|
+
/* @__PURE__ */ jsx14(
|
|
1306
|
+
"button",
|
|
1307
|
+
{
|
|
1308
|
+
type: "submit",
|
|
1309
|
+
disabled: loading,
|
|
1310
|
+
style: { ...currentStyles.submitBtn, opacity: loading ? 0.7 : 1 },
|
|
1311
|
+
children: loading ? "Signing in..." : "Sign In"
|
|
1312
|
+
}
|
|
1313
|
+
)
|
|
1314
|
+
] }),
|
|
1315
|
+
errorMessage && /* @__PURE__ */ jsx14("p", { style: styles.error, children: errorMessage })
|
|
1316
|
+
] });
|
|
1317
|
+
if (variant === "embedded") {
|
|
1318
|
+
return content;
|
|
1319
|
+
}
|
|
1320
|
+
return /* @__PURE__ */ jsx14("div", { style: { ...currentStyles.container, background: isLight ? "#f8fafc" : "#0f172a" }, className: `primus-login ${isDark ? "dark" : ""}`, children: content });
|
|
1321
|
+
}
|
|
1322
|
+
var LoginPage = PrimusLogin;
|
|
1323
|
+
|
|
1115
1324
|
// src/components/shared/Button.tsx
|
|
1116
|
-
import
|
|
1325
|
+
import React14 from "react";
|
|
1117
1326
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1118
|
-
var Button =
|
|
1327
|
+
var Button = React14.forwardRef(
|
|
1119
1328
|
({ style, variant = "primary", size = "md", color = "sapphire", disabled, ...props }, ref) => {
|
|
1120
|
-
const [isHovered, setIsHovered] =
|
|
1329
|
+
const [isHovered, setIsHovered] = React14.useState(false);
|
|
1121
1330
|
const colorStyles = {
|
|
1122
1331
|
sapphire: {
|
|
1123
1332
|
solid: "#1341a7",
|
|
@@ -1256,6 +1465,51 @@ var UserProfile = ({
|
|
|
1256
1465
|
] });
|
|
1257
1466
|
};
|
|
1258
1467
|
|
|
1468
|
+
// src/hooks/usePrimusFetch.ts
|
|
1469
|
+
import { useCallback as useCallback3 } from "react";
|
|
1470
|
+
function usePrimusFetch() {
|
|
1471
|
+
const { logout, csrfCookieName = "XSRF-TOKEN", csrfHeaderName = "X-Primus-CSRF" } = usePrimusAuth();
|
|
1472
|
+
const getCookie = useCallback3((name) => {
|
|
1473
|
+
if (typeof document === "undefined") return null;
|
|
1474
|
+
try {
|
|
1475
|
+
const matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") + "=([^;]*)"));
|
|
1476
|
+
return matches ? decodeURIComponent(matches[1]) : null;
|
|
1477
|
+
} catch {
|
|
1478
|
+
return null;
|
|
1479
|
+
}
|
|
1480
|
+
}, []);
|
|
1481
|
+
const primusFetch = useCallback3(async (input, init) => {
|
|
1482
|
+
const { skipAuth, ...fetchInit } = init || {};
|
|
1483
|
+
const config = {
|
|
1484
|
+
...fetchInit,
|
|
1485
|
+
headers: new Headers(fetchInit.headers)
|
|
1486
|
+
};
|
|
1487
|
+
if (!skipAuth) {
|
|
1488
|
+
config.credentials = "include";
|
|
1489
|
+
}
|
|
1490
|
+
const method = (config.method || "GET").toUpperCase();
|
|
1491
|
+
if (!["GET", "HEAD", "OPTIONS"].includes(method)) {
|
|
1492
|
+
const csrfToken = getCookie(csrfCookieName);
|
|
1493
|
+
if (csrfToken) {
|
|
1494
|
+
config.headers.set(csrfHeaderName, csrfToken);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
try {
|
|
1498
|
+
const response = await window.fetch(input, config);
|
|
1499
|
+
if (response.status === 401 && !skipAuth) {
|
|
1500
|
+
console.debug("[PrimusFetch] 401 Unauthorized detected. triggering logout.");
|
|
1501
|
+
logout();
|
|
1502
|
+
}
|
|
1503
|
+
return response;
|
|
1504
|
+
} catch (error) {
|
|
1505
|
+
throw error;
|
|
1506
|
+
}
|
|
1507
|
+
}, [getCookie, logout, csrfCookieName, csrfHeaderName]);
|
|
1508
|
+
return {
|
|
1509
|
+
fetch: primusFetch
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1259
1513
|
// src/hooks/useNotifications.ts
|
|
1260
1514
|
import { useState as useState15, useEffect as useEffect9, useMemo } from "react";
|
|
1261
1515
|
var useNotifications = ({
|
|
@@ -1399,7 +1653,7 @@ var PrimusNotificationFeed = ({ useMock, mockData, apiUrl, className }) => {
|
|
|
1399
1653
|
};
|
|
1400
1654
|
|
|
1401
1655
|
// src/components/notifications/PrimusNotificationCenter.tsx
|
|
1402
|
-
import { useState as useState16, useEffect as useEffect10, useCallback as
|
|
1656
|
+
import { useState as useState16, useEffect as useEffect10, useCallback as useCallback4 } from "react";
|
|
1403
1657
|
import { Bell, Send, X, Check, AlertTriangle, Info, AlertCircle } from "lucide-react";
|
|
1404
1658
|
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1405
1659
|
var API_URL = "http://localhost:5222";
|
|
@@ -1421,7 +1675,7 @@ function PrimusNotificationCenter({
|
|
|
1421
1675
|
const [newMessage, setNewMessage] = useState16("");
|
|
1422
1676
|
const [newType, setNewType] = useState16("info");
|
|
1423
1677
|
const [sending, setSending] = useState16(false);
|
|
1424
|
-
const fetchNotifications =
|
|
1678
|
+
const fetchNotifications = useCallback4(async () => {
|
|
1425
1679
|
try {
|
|
1426
1680
|
const response = await fetch(`${apiUrl}/api/notifications`);
|
|
1427
1681
|
if (response.ok) {
|
|
@@ -1645,7 +1899,7 @@ var NotificationBell = PrimusNotificationCenter;
|
|
|
1645
1899
|
var PrimusNotifications = PrimusNotificationCenter;
|
|
1646
1900
|
|
|
1647
1901
|
// src/hooks/useRealtimeNotifications.ts
|
|
1648
|
-
import { useState as useState17, useEffect as useEffect11, useCallback as
|
|
1902
|
+
import { useState as useState17, useEffect as useEffect11, useCallback as useCallback5 } from "react";
|
|
1649
1903
|
var useRealtimeNotifications = (options) => {
|
|
1650
1904
|
const { apiUrl, pollInterval = 3e3, userId } = options;
|
|
1651
1905
|
const [notifications, setNotifications] = useState17([]);
|
|
@@ -1653,7 +1907,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1653
1907
|
const [loading, setLoading] = useState17(true);
|
|
1654
1908
|
const [error, setError] = useState17(null);
|
|
1655
1909
|
const baseUrl = `${apiUrl}/api/notifications`;
|
|
1656
|
-
const fetchNotifications =
|
|
1910
|
+
const fetchNotifications = useCallback5(async () => {
|
|
1657
1911
|
try {
|
|
1658
1912
|
const url = userId ? `${baseUrl}?userId=${userId}` : baseUrl;
|
|
1659
1913
|
const response = await fetch(url);
|
|
@@ -1669,7 +1923,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1669
1923
|
setLoading(false);
|
|
1670
1924
|
}
|
|
1671
1925
|
}, [baseUrl, userId]);
|
|
1672
|
-
const sendNotification =
|
|
1926
|
+
const sendNotification = useCallback5(async (title, message, type = "info") => {
|
|
1673
1927
|
try {
|
|
1674
1928
|
const response = await fetch(baseUrl, {
|
|
1675
1929
|
method: "POST",
|
|
@@ -1685,7 +1939,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1685
1939
|
return false;
|
|
1686
1940
|
}
|
|
1687
1941
|
}, [baseUrl, userId, fetchNotifications]);
|
|
1688
|
-
const markAsRead =
|
|
1942
|
+
const markAsRead = useCallback5(async (id) => {
|
|
1689
1943
|
try {
|
|
1690
1944
|
await fetch(`${baseUrl}/${id}/read`, { method: "PUT" });
|
|
1691
1945
|
setNotifications((prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n));
|
|
@@ -1693,13 +1947,13 @@ var useRealtimeNotifications = (options) => {
|
|
|
1693
1947
|
} catch {
|
|
1694
1948
|
}
|
|
1695
1949
|
}, [baseUrl]);
|
|
1696
|
-
const markAllAsRead =
|
|
1950
|
+
const markAllAsRead = useCallback5(async () => {
|
|
1697
1951
|
const unread = notifications.filter((n) => !n.read);
|
|
1698
1952
|
await Promise.all(unread.map((n) => fetch(`${baseUrl}/${n.id}/read`, { method: "PUT" })));
|
|
1699
1953
|
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
|
1700
1954
|
setUnreadCount(0);
|
|
1701
1955
|
}, [notifications, baseUrl]);
|
|
1702
|
-
const deleteNotification =
|
|
1956
|
+
const deleteNotification = useCallback5(async (id) => {
|
|
1703
1957
|
try {
|
|
1704
1958
|
await fetch(`${baseUrl}/${id}`, { method: "DELETE" });
|
|
1705
1959
|
setNotifications((prev) => prev.filter((n) => n.id !== id));
|
|
@@ -1728,7 +1982,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1728
1982
|
import { useState as useState18 } from "react";
|
|
1729
1983
|
|
|
1730
1984
|
// src/components/shared/Input.tsx
|
|
1731
|
-
import
|
|
1985
|
+
import React15 from "react";
|
|
1732
1986
|
import { clsx as clsx2 } from "clsx";
|
|
1733
1987
|
import { XMarkIcon } from "@heroicons/react/20/solid";
|
|
1734
1988
|
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -1742,20 +1996,48 @@ var iconSizeClasses = {
|
|
|
1742
1996
|
md: "w-5 h-5 [&>*]:w-full [&>*]:h-full",
|
|
1743
1997
|
lg: "w-6 h-6 [&>*]:w-full [&>*]:h-full"
|
|
1744
1998
|
};
|
|
1745
|
-
var Input =
|
|
1746
|
-
({
|
|
1999
|
+
var Input = React15.forwardRef(
|
|
2000
|
+
({
|
|
2001
|
+
className,
|
|
2002
|
+
style,
|
|
2003
|
+
label,
|
|
2004
|
+
error,
|
|
2005
|
+
disabled,
|
|
2006
|
+
startIcon,
|
|
2007
|
+
endIcon,
|
|
2008
|
+
onClear,
|
|
2009
|
+
value,
|
|
2010
|
+
onChange,
|
|
2011
|
+
onValueChange,
|
|
2012
|
+
size = "md",
|
|
2013
|
+
loading = false,
|
|
2014
|
+
autoSelect = false,
|
|
2015
|
+
onFocus,
|
|
2016
|
+
...props
|
|
2017
|
+
}, ref) => {
|
|
2018
|
+
const handleFocus = (e) => {
|
|
2019
|
+
if (autoSelect) {
|
|
2020
|
+
e.target.select();
|
|
2021
|
+
}
|
|
2022
|
+
onFocus?.(e);
|
|
2023
|
+
};
|
|
2024
|
+
const handleChange = (e) => {
|
|
2025
|
+
onChange?.(e);
|
|
2026
|
+
onValueChange?.(e.target.value);
|
|
2027
|
+
};
|
|
1747
2028
|
const hasValue = value !== void 0 && value !== "" && value !== null;
|
|
2029
|
+
const isDisabled = disabled || loading;
|
|
1748
2030
|
return /* @__PURE__ */ jsxs16("div", { className: clsx2("w-full", className), style, children: [
|
|
1749
2031
|
label && /* @__PURE__ */ jsx19("label", { className: clsx2(
|
|
1750
2032
|
"block font-medium mb-1.5",
|
|
1751
2033
|
size === "sm" ? "text-xs" : "text-sm",
|
|
1752
|
-
|
|
2034
|
+
isDisabled ? "text-gray-400 opacity-70" : "text-gray-700"
|
|
1753
2035
|
), children: label }),
|
|
1754
2036
|
/* @__PURE__ */ jsxs16("div", { className: clsx2(
|
|
1755
2037
|
"relative flex items-center w-full rounded-lg transition-all duration-200 ease-in-out bg-white overflow-hidden",
|
|
1756
2038
|
"border",
|
|
1757
2039
|
error ? "border-red-500 hover:border-red-600 focus-within:ring-2 focus-within:ring-red-500/20 focus-within:border-red-500" : "border-gray-200 hover:border-gray-300 focus-within:ring-2 focus-within:ring-primus-500/20 focus-within:border-primus-500",
|
|
1758
|
-
|
|
2040
|
+
isDisabled && "bg-gray-50 opacity-60 cursor-not-allowed"
|
|
1759
2041
|
), children: [
|
|
1760
2042
|
startIcon && /* @__PURE__ */ jsx19("div", { className: clsx2(
|
|
1761
2043
|
"flex-shrink-0 pl-3 pr-2 text-gray-400 select-none pointer-events-none flex items-center justify-center",
|
|
@@ -1765,9 +2047,10 @@ var Input = React14.forwardRef(
|
|
|
1765
2047
|
"input",
|
|
1766
2048
|
{
|
|
1767
2049
|
ref,
|
|
1768
|
-
disabled,
|
|
2050
|
+
disabled: isDisabled,
|
|
1769
2051
|
value,
|
|
1770
|
-
onChange,
|
|
2052
|
+
onChange: handleChange,
|
|
2053
|
+
onFocus: handleFocus,
|
|
1771
2054
|
className: clsx2(
|
|
1772
2055
|
"flex-1 w-full border-none bg-transparent p-0 placeholder:text-gray-400 focus:ring-0 outline-none",
|
|
1773
2056
|
sizeClasses[size],
|
|
@@ -1778,7 +2061,7 @@ var Input = React14.forwardRef(
|
|
|
1778
2061
|
...props
|
|
1779
2062
|
}
|
|
1780
2063
|
),
|
|
1781
|
-
onClear && hasValue && !
|
|
2064
|
+
onClear && hasValue && !isDisabled && /* @__PURE__ */ jsx19("div", { className: "flex-shrink-0 pr-2 flex items-center justify-center", children: /* @__PURE__ */ jsx19(
|
|
1782
2065
|
"button",
|
|
1783
2066
|
{
|
|
1784
2067
|
type: "button",
|
|
@@ -1786,7 +2069,8 @@ var Input = React14.forwardRef(
|
|
|
1786
2069
|
e.stopPropagation();
|
|
1787
2070
|
onClear();
|
|
1788
2071
|
},
|
|
1789
|
-
className: "p-1 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors",
|
|
2072
|
+
className: "p-1 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-primus-500",
|
|
2073
|
+
tabIndex: 0,
|
|
1790
2074
|
children: /* @__PURE__ */ jsx19(XMarkIcon, { className: "h-4 w-4" })
|
|
1791
2075
|
}
|
|
1792
2076
|
) }),
|
|
@@ -2394,7 +2678,7 @@ var PrimusSidebar = ({
|
|
|
2394
2678
|
};
|
|
2395
2679
|
|
|
2396
2680
|
// src/components/layout/PrimusHeader.tsx
|
|
2397
|
-
import
|
|
2681
|
+
import React19 from "react";
|
|
2398
2682
|
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2399
2683
|
var PrimusHeader = ({
|
|
2400
2684
|
title,
|
|
@@ -2405,7 +2689,7 @@ var PrimusHeader = ({
|
|
|
2405
2689
|
}) => {
|
|
2406
2690
|
return /* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between w-full", children: [
|
|
2407
2691
|
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-4", children: [
|
|
2408
|
-
breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx30("nav", { className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsxs27(
|
|
2692
|
+
breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx30("nav", { className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsxs27(React19.Fragment, { children: [
|
|
2409
2693
|
index > 0 && /* @__PURE__ */ jsx30("span", { className: "text-gray-500", children: "/" }),
|
|
2410
2694
|
/* @__PURE__ */ jsx30("span", { className: index === breadcrumbs.length - 1 ? "text-white" : "text-gray-400 hover:text-white cursor-pointer", children: crumb.label })
|
|
2411
2695
|
] }, index)) }),
|
|
@@ -2431,9 +2715,30 @@ var PrimusHeader = ({
|
|
|
2431
2715
|
] });
|
|
2432
2716
|
};
|
|
2433
2717
|
|
|
2718
|
+
// src/components/layout/PrimusSection.tsx
|
|
2719
|
+
import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2720
|
+
var PrimusSection = ({
|
|
2721
|
+
title,
|
|
2722
|
+
subtitle,
|
|
2723
|
+
children,
|
|
2724
|
+
className = "",
|
|
2725
|
+
actions
|
|
2726
|
+
}) => {
|
|
2727
|
+
return /* @__PURE__ */ jsxs28("section", { className: `py-6 ${className}`, children: [
|
|
2728
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-end justify-between mb-6 border-b border-gray-200 dark:border-gray-800 pb-4", children: [
|
|
2729
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
2730
|
+
/* @__PURE__ */ jsx31("h2", { className: "text-2xl font-bold tracking-tight text-gray-900 dark:text-white", children: title }),
|
|
2731
|
+
subtitle && /* @__PURE__ */ jsx31("p", { className: "mt-1 text-base text-gray-500 dark:text-gray-400", children: subtitle })
|
|
2732
|
+
] }),
|
|
2733
|
+
actions && /* @__PURE__ */ jsx31("div", { className: "flex items-center gap-2", children: actions })
|
|
2734
|
+
] }),
|
|
2735
|
+
/* @__PURE__ */ jsx31("div", { children })
|
|
2736
|
+
] });
|
|
2737
|
+
};
|
|
2738
|
+
|
|
2434
2739
|
// src/components/crud/PrimusDataTable.tsx
|
|
2435
2740
|
import { useState as useState21, useMemo as useMemo2 } from "react";
|
|
2436
|
-
import { jsx as
|
|
2741
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2437
2742
|
function PrimusDataTable({
|
|
2438
2743
|
data,
|
|
2439
2744
|
columns,
|
|
@@ -2512,10 +2817,10 @@ function PrimusDataTable({
|
|
|
2512
2817
|
onSelectionChange?.(scopeKeys);
|
|
2513
2818
|
}
|
|
2514
2819
|
};
|
|
2515
|
-
return /* @__PURE__ */
|
|
2516
|
-
searchable && /* @__PURE__ */
|
|
2517
|
-
/* @__PURE__ */
|
|
2518
|
-
/* @__PURE__ */
|
|
2820
|
+
return /* @__PURE__ */ jsxs29("div", { className: "flex flex-col space-y-4", children: [
|
|
2821
|
+
searchable && /* @__PURE__ */ jsx32("div", { className: "flex items-center justify-between px-1", children: /* @__PURE__ */ jsxs29("div", { className: "relative group", children: [
|
|
2822
|
+
/* @__PURE__ */ jsx32("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx32("svg", { className: "h-4 w-4 text-gray-500 group-focus-within:text-purple-400 transition-colors", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx32("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }) }),
|
|
2823
|
+
/* @__PURE__ */ jsx32(
|
|
2519
2824
|
"input",
|
|
2520
2825
|
{
|
|
2521
2826
|
type: "text",
|
|
@@ -2531,9 +2836,9 @@ function PrimusDataTable({
|
|
|
2531
2836
|
}
|
|
2532
2837
|
)
|
|
2533
2838
|
] }) }),
|
|
2534
|
-
/* @__PURE__ */
|
|
2535
|
-
/* @__PURE__ */
|
|
2536
|
-
selectable && /* @__PURE__ */
|
|
2839
|
+
/* @__PURE__ */ jsx32("div", { className: `overflow-hidden rounded-xl border border-white/5 bg-slate-900/40 backdrop-blur-md shadow-xl ring-1 ring-white/5 ${loading ? "opacity-80" : ""}`, children: /* @__PURE__ */ jsx32("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs29("table", { className: "w-full text-left border-collapse", children: [
|
|
2840
|
+
/* @__PURE__ */ jsx32("thead", { className: "bg-white/5 border-b border-white/5 backdrop-blur-md sticky top-0 z-20", children: /* @__PURE__ */ jsxs29("tr", { children: [
|
|
2841
|
+
selectable && /* @__PURE__ */ jsx32("th", { className: "w-12 px-6 py-4", children: /* @__PURE__ */ jsx32(
|
|
2537
2842
|
"input",
|
|
2538
2843
|
{
|
|
2539
2844
|
type: "checkbox",
|
|
@@ -2542,25 +2847,25 @@ function PrimusDataTable({
|
|
|
2542
2847
|
className: "rounded border-gray-600 bg-gray-800 text-purple-600 focus:ring-offset-gray-900 focus:ring-purple-500 transition-colors cursor-pointer"
|
|
2543
2848
|
}
|
|
2544
2849
|
) }),
|
|
2545
|
-
columns.map((col) => /* @__PURE__ */
|
|
2850
|
+
columns.map((col) => /* @__PURE__ */ jsx32(
|
|
2546
2851
|
"th",
|
|
2547
2852
|
{
|
|
2548
2853
|
className: `px-6 py-4 text-xs font-semibold text-gray-400 uppercase tracking-wider ${col.sortable ? "cursor-pointer hover:text-white group" : ""}`,
|
|
2549
2854
|
style: { width: col.width },
|
|
2550
2855
|
onClick: () => col.sortable && handleSort(String(col.key)),
|
|
2551
|
-
children: /* @__PURE__ */
|
|
2856
|
+
children: /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-2", children: [
|
|
2552
2857
|
col.header,
|
|
2553
|
-
col.sortable && /* @__PURE__ */
|
|
2858
|
+
col.sortable && /* @__PURE__ */ jsx32("span", { className: `transition-opacity duration-200 ${sortKey === col.key ? "opacity-100 text-purple-400" : "opacity-0 group-hover:opacity-50"}`, children: sortDir === "asc" ? "\u2191" : "\u2193" })
|
|
2554
2859
|
] })
|
|
2555
2860
|
},
|
|
2556
2861
|
String(col.key)
|
|
2557
2862
|
)),
|
|
2558
|
-
actions && /* @__PURE__ */
|
|
2863
|
+
actions && /* @__PURE__ */ jsx32("th", { className: "w-24 px-6 py-4 text-right text-xs font-semibold text-gray-400 uppercase tracking-wider" })
|
|
2559
2864
|
] }) }),
|
|
2560
|
-
/* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */
|
|
2563
|
-
] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */
|
|
2865
|
+
/* @__PURE__ */ jsx32("tbody", { className: "divide-y divide-white/5", children: loading ? /* @__PURE__ */ jsx32("tr", { children: /* @__PURE__ */ jsx32("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ jsxs29("div", { className: "flex flex-col items-center justify-center gap-3", children: [
|
|
2866
|
+
/* @__PURE__ */ jsx32("div", { className: "w-6 h-6 border-2 border-purple-500/50 border-t-purple-500 rounded-full animate-spin" }),
|
|
2867
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm font-medium", children: "Loading data..." })
|
|
2868
|
+
] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */ jsx32("tr", { children: /* @__PURE__ */ jsx32("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ jsx32("p", { className: "text-sm", children: emptyMessage }) }) }) : pageData.map((row) => /* @__PURE__ */ jsxs29(
|
|
2564
2869
|
"tr",
|
|
2565
2870
|
{
|
|
2566
2871
|
onClick: () => onRowClick?.(row),
|
|
@@ -2570,7 +2875,7 @@ function PrimusDataTable({
|
|
|
2570
2875
|
${selectedKeys.includes(row[rowKey]) ? "bg-purple-500/10 hover:bg-purple-500/20" : ""}
|
|
2571
2876
|
`,
|
|
2572
2877
|
children: [
|
|
2573
|
-
selectable && /* @__PURE__ */
|
|
2878
|
+
selectable && /* @__PURE__ */ jsx32("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx32(
|
|
2574
2879
|
"input",
|
|
2575
2880
|
{
|
|
2576
2881
|
type: "checkbox",
|
|
@@ -2579,15 +2884,15 @@ function PrimusDataTable({
|
|
|
2579
2884
|
className: "rounded border-gray-600 bg-gray-800 text-purple-600 focus:ring-offset-gray-900 focus:ring-purple-500 cursor-pointer"
|
|
2580
2885
|
}
|
|
2581
2886
|
) }),
|
|
2582
|
-
columns.map((col) => /* @__PURE__ */
|
|
2583
|
-
actions && /* @__PURE__ */
|
|
2887
|
+
columns.map((col) => /* @__PURE__ */ jsx32("td", { className: "px-6 py-4 text-sm text-gray-300 group-hover:text-white transition-colors", children: col.render ? col.render(row[col.key], row) : String(row[col.key] ?? "") }, String(col.key))),
|
|
2888
|
+
actions && /* @__PURE__ */ jsx32("td", { className: "px-6 py-4 text-right", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx32("div", { className: "opacity-0 group-hover:opacity-100 transition-opacity transform translate-x-2 group-hover:translate-x-0", children: actions(row) }) })
|
|
2584
2889
|
]
|
|
2585
2890
|
},
|
|
2586
2891
|
String(row[rowKey])
|
|
2587
2892
|
)) })
|
|
2588
2893
|
] }) }) }),
|
|
2589
|
-
paginated && totalPages > 1 && /* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2894
|
+
paginated && totalPages > 1 && /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between text-sm text-gray-400 px-2", children: [
|
|
2895
|
+
/* @__PURE__ */ jsx32(
|
|
2591
2896
|
"button",
|
|
2592
2897
|
{
|
|
2593
2898
|
type: "button",
|
|
@@ -2597,13 +2902,13 @@ function PrimusDataTable({
|
|
|
2597
2902
|
children: "Previous"
|
|
2598
2903
|
}
|
|
2599
2904
|
),
|
|
2600
|
-
/* @__PURE__ */
|
|
2905
|
+
/* @__PURE__ */ jsxs29("span", { children: [
|
|
2601
2906
|
"Page ",
|
|
2602
2907
|
currentPageIndex + 1,
|
|
2603
2908
|
" of ",
|
|
2604
2909
|
totalPages
|
|
2605
2910
|
] }),
|
|
2606
|
-
/* @__PURE__ */
|
|
2911
|
+
/* @__PURE__ */ jsx32(
|
|
2607
2912
|
"button",
|
|
2608
2913
|
{
|
|
2609
2914
|
type: "button",
|
|
@@ -2618,7 +2923,7 @@ function PrimusDataTable({
|
|
|
2618
2923
|
}
|
|
2619
2924
|
|
|
2620
2925
|
// src/components/crud/PrimusModal.tsx
|
|
2621
|
-
import { jsx as
|
|
2926
|
+
import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2622
2927
|
var PrimusModal = ({
|
|
2623
2928
|
open,
|
|
2624
2929
|
onClose,
|
|
@@ -2634,34 +2939,34 @@ var PrimusModal = ({
|
|
|
2634
2939
|
lg: "max-w-lg",
|
|
2635
2940
|
xl: "max-w-xl"
|
|
2636
2941
|
};
|
|
2637
|
-
return /* @__PURE__ */
|
|
2638
|
-
/* @__PURE__ */
|
|
2942
|
+
return /* @__PURE__ */ jsxs30("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
2943
|
+
/* @__PURE__ */ jsx33(
|
|
2639
2944
|
"div",
|
|
2640
2945
|
{
|
|
2641
2946
|
className: "absolute inset-0 bg-black/60 backdrop-blur-sm",
|
|
2642
2947
|
onClick: onClose
|
|
2643
2948
|
}
|
|
2644
2949
|
),
|
|
2645
|
-
/* @__PURE__ */
|
|
2646
|
-
title && /* @__PURE__ */
|
|
2647
|
-
/* @__PURE__ */
|
|
2648
|
-
/* @__PURE__ */
|
|
2950
|
+
/* @__PURE__ */ jsxs30("div", { className: `relative w-full ${sizeClasses2[size]} mx-4 bg-gray-800 rounded-xl border border-gray-700 shadow-2xl`, children: [
|
|
2951
|
+
title && /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-700", children: [
|
|
2952
|
+
/* @__PURE__ */ jsx33("h2", { className: "text-lg font-semibold text-white", children: title }),
|
|
2953
|
+
/* @__PURE__ */ jsx33(
|
|
2649
2954
|
"button",
|
|
2650
2955
|
{
|
|
2651
2956
|
onClick: onClose,
|
|
2652
2957
|
className: "text-gray-400 hover:text-white transition-colors",
|
|
2653
|
-
children: /* @__PURE__ */
|
|
2958
|
+
children: /* @__PURE__ */ jsx33("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx33("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
2654
2959
|
}
|
|
2655
2960
|
)
|
|
2656
2961
|
] }),
|
|
2657
|
-
/* @__PURE__ */
|
|
2658
|
-
footer && /* @__PURE__ */
|
|
2962
|
+
/* @__PURE__ */ jsx33("div", { className: "p-6", children }),
|
|
2963
|
+
footer && /* @__PURE__ */ jsx33("div", { className: "flex justify-end gap-3 px-6 py-4 border-t border-gray-700 bg-gray-800/50", children: footer })
|
|
2659
2964
|
] })
|
|
2660
2965
|
] });
|
|
2661
2966
|
};
|
|
2662
2967
|
|
|
2663
2968
|
// src/components/dashboard/PrimusDashboard.tsx
|
|
2664
|
-
import { jsx as
|
|
2969
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2665
2970
|
var PrimusStatCard = ({
|
|
2666
2971
|
title,
|
|
2667
2972
|
value,
|
|
@@ -2697,35 +3002,35 @@ var PrimusStatCard = ({
|
|
|
2697
3002
|
const linePath = points.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x} ${point.y}`).join(" ");
|
|
2698
3003
|
const areaPath = `${linePath} L 100 100 L 0 100 Z`;
|
|
2699
3004
|
const gradientId = `gradient-${title.replace(/\s/g, "")}`;
|
|
2700
|
-
return /* @__PURE__ */
|
|
2701
|
-
/* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
3005
|
+
return /* @__PURE__ */ jsxs31("svg", { className: "w-full h-12 opacity-60 absolute bottom-0 left-0", viewBox: "0 0 100 100", preserveAspectRatio: "none", "data-trend": trend.join(","), children: [
|
|
3006
|
+
/* @__PURE__ */ jsx34("defs", { children: /* @__PURE__ */ jsxs31("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
3007
|
+
/* @__PURE__ */ jsx34("stop", { offset: "0%", stopColor: "currentColor", stopOpacity: "0.25" }),
|
|
3008
|
+
/* @__PURE__ */ jsx34("stop", { offset: "100%", stopColor: "currentColor", stopOpacity: "0" })
|
|
2704
3009
|
] }) }),
|
|
2705
|
-
/* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
3010
|
+
/* @__PURE__ */ jsx34("path", { d: areaPath, fill: `url(#${gradientId})`, stroke: "none" }),
|
|
3011
|
+
/* @__PURE__ */ jsx34("path", { d: linePath, fill: "none", stroke: "currentColor", strokeWidth: "1.8", opacity: "0.6" })
|
|
2707
3012
|
] });
|
|
2708
3013
|
};
|
|
2709
|
-
return /* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
/* @__PURE__ */
|
|
2712
|
-
/* @__PURE__ */
|
|
2713
|
-
/* @__PURE__ */
|
|
2714
|
-
change && /* @__PURE__ */
|
|
3014
|
+
return /* @__PURE__ */ jsxs31("div", { className: "relative overflow-hidden bg-slate-900/40 backdrop-blur-md rounded-2xl border border-white/5 hover:border-white/10 transition-all duration-300 group", children: [
|
|
3015
|
+
/* @__PURE__ */ jsx34("div", { className: "absolute inset-0 bg-gradient-to-br from-white/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" }),
|
|
3016
|
+
/* @__PURE__ */ jsxs31("div", { className: "p-6 relative z-10", children: [
|
|
3017
|
+
/* @__PURE__ */ jsxs31("div", { className: "flex items-start justify-between mb-4", children: [
|
|
3018
|
+
/* @__PURE__ */ jsx34("div", { className: "p-2.5 rounded-lg bg-white/5 text-gray-300 ring-1 ring-white/10 group-hover:bg-purple-500/20 group-hover:text-purple-300 transition-colors", children: icon || /* @__PURE__ */ jsx34("div", { className: "w-5 h-5 bg-current opacity-20" }) }),
|
|
3019
|
+
change && /* @__PURE__ */ jsxs31("span", { className: `px-2 py-0.5 text-xs font-medium rounded-full flex items-center gap-1 ${changeColors[change.type]}`, children: [
|
|
2715
3020
|
changeIcons[change.type],
|
|
2716
3021
|
" ",
|
|
2717
3022
|
Math.abs(change.value),
|
|
2718
3023
|
"%"
|
|
2719
3024
|
] })
|
|
2720
3025
|
] }),
|
|
2721
|
-
/* @__PURE__ */
|
|
2722
|
-
/* @__PURE__ */
|
|
2723
|
-
/* @__PURE__ */
|
|
2724
|
-
description && /* @__PURE__ */
|
|
3026
|
+
/* @__PURE__ */ jsxs31("div", { children: [
|
|
3027
|
+
/* @__PURE__ */ jsx34("h3", { className: "text-sm font-medium text-gray-400 tracking-wide", children: title }),
|
|
3028
|
+
/* @__PURE__ */ jsx34("div", { className: "mt-1 flex items-baseline gap-2", children: /* @__PURE__ */ jsx34("span", { className: "text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-white to-gray-400", children: value }) }),
|
|
3029
|
+
description && /* @__PURE__ */ jsx34("p", { className: "text-xs text-gray-500 mt-2 font-medium", children: description })
|
|
2725
3030
|
] })
|
|
2726
3031
|
] }),
|
|
2727
3032
|
renderSparkline(),
|
|
2728
|
-
/* @__PURE__ */
|
|
3033
|
+
/* @__PURE__ */ jsx34("div", { className: `absolute -bottom-2 -right-4 w-32 h-32 blur-2xl opacity-20 rounded-full transition-colors duration-500 ${change?.type === "increase" ? "bg-emerald-500" : change?.type === "decrease" ? "bg-rose-500" : "bg-blue-500"}` })
|
|
2729
3034
|
] });
|
|
2730
3035
|
};
|
|
2731
3036
|
var PrimusDashboard = ({
|
|
@@ -2734,13 +3039,13 @@ var PrimusDashboard = ({
|
|
|
2734
3039
|
subtitle,
|
|
2735
3040
|
actions
|
|
2736
3041
|
}) => {
|
|
2737
|
-
return /* @__PURE__ */
|
|
2738
|
-
(title || actions) && /* @__PURE__ */
|
|
2739
|
-
/* @__PURE__ */
|
|
2740
|
-
title && /* @__PURE__ */
|
|
2741
|
-
subtitle && /* @__PURE__ */
|
|
3042
|
+
return /* @__PURE__ */ jsxs31("div", { className: "space-y-8 animate-enter", children: [
|
|
3043
|
+
(title || actions) && /* @__PURE__ */ jsxs31("div", { className: "flex flex-col md:flex-row md:items-end justify-between gap-4 border-b border-white/5 pb-6", children: [
|
|
3044
|
+
/* @__PURE__ */ jsxs31("div", { children: [
|
|
3045
|
+
title && /* @__PURE__ */ jsx34("h1", { className: "text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-white via-gray-200 to-gray-400 tracking-tight", children: title }),
|
|
3046
|
+
subtitle && /* @__PURE__ */ jsx34("p", { className: "text-gray-400 mt-2 text-lg font-light leading-relaxed", children: subtitle })
|
|
2742
3047
|
] }),
|
|
2743
|
-
actions && /* @__PURE__ */
|
|
3048
|
+
actions && /* @__PURE__ */ jsx34("div", { className: "flex items-center gap-3", children: actions })
|
|
2744
3049
|
] }),
|
|
2745
3050
|
children
|
|
2746
3051
|
] });
|
|
@@ -2755,25 +3060,119 @@ var DashboardGrid = ({
|
|
|
2755
3060
|
3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
|
|
2756
3061
|
4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4"
|
|
2757
3062
|
};
|
|
2758
|
-
return /* @__PURE__ */
|
|
3063
|
+
return /* @__PURE__ */ jsx34("div", { className: `grid gap-6 ${colClasses[columns]}`, children });
|
|
2759
3064
|
};
|
|
2760
3065
|
|
|
2761
|
-
// src/components/
|
|
2762
|
-
import
|
|
2763
|
-
import { jsx as
|
|
2764
|
-
var
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
3066
|
+
// src/components/shared/Card.tsx
|
|
3067
|
+
import React21 from "react";
|
|
3068
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
3069
|
+
var Card = React21.forwardRef(
|
|
3070
|
+
({ style, variant = "default", padding = "md", children, ...props }, ref) => {
|
|
3071
|
+
const [isHovered, setIsHovered] = React21.useState(false);
|
|
3072
|
+
const paddingStyles = {
|
|
3073
|
+
none: "0",
|
|
3074
|
+
sm: "0.75rem",
|
|
3075
|
+
md: "1.5rem",
|
|
3076
|
+
lg: "2rem"
|
|
3077
|
+
};
|
|
3078
|
+
const variantStyles = {
|
|
3079
|
+
default: {
|
|
3080
|
+
normal: {
|
|
3081
|
+
backgroundColor: "#ffffff",
|
|
3082
|
+
border: "1px solid #e5e7eb",
|
|
3083
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
3084
|
+
},
|
|
3085
|
+
hover: {
|
|
3086
|
+
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3087
|
+
}
|
|
3088
|
+
},
|
|
3089
|
+
outlined: {
|
|
3090
|
+
normal: {
|
|
3091
|
+
backgroundColor: "#ffffff",
|
|
3092
|
+
border: "2px solid #e5e7eb",
|
|
3093
|
+
boxShadow: "none"
|
|
3094
|
+
},
|
|
3095
|
+
hover: {
|
|
3096
|
+
borderColor: "#d1d5db"
|
|
3097
|
+
}
|
|
3098
|
+
},
|
|
3099
|
+
elevated: {
|
|
3100
|
+
normal: {
|
|
3101
|
+
backgroundColor: "#ffffff",
|
|
3102
|
+
border: "none",
|
|
3103
|
+
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3104
|
+
},
|
|
3105
|
+
hover: {
|
|
3106
|
+
boxShadow: "0 10px 15px rgba(0, 0, 0, 0.15)",
|
|
3107
|
+
transform: "translateY(-2px)"
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
};
|
|
3111
|
+
const baseStyles = {
|
|
3112
|
+
borderRadius: "0.5rem",
|
|
3113
|
+
padding: paddingStyles[padding],
|
|
3114
|
+
transition: "all 0.2s ease"
|
|
3115
|
+
};
|
|
3116
|
+
const currentVariant = variantStyles[variant];
|
|
3117
|
+
const combinedStyles = {
|
|
3118
|
+
...baseStyles,
|
|
3119
|
+
...currentVariant.normal,
|
|
3120
|
+
...isHovered ? currentVariant.hover : {},
|
|
3121
|
+
...style
|
|
3122
|
+
};
|
|
3123
|
+
return /* @__PURE__ */ jsx35(
|
|
3124
|
+
"div",
|
|
3125
|
+
{
|
|
3126
|
+
ref,
|
|
3127
|
+
style: combinedStyles,
|
|
3128
|
+
onMouseEnter: () => setIsHovered(true),
|
|
3129
|
+
onMouseLeave: () => setIsHovered(false),
|
|
3130
|
+
...props,
|
|
3131
|
+
children
|
|
3132
|
+
}
|
|
3133
|
+
);
|
|
3134
|
+
}
|
|
3135
|
+
);
|
|
3136
|
+
Card.displayName = "Card";
|
|
3137
|
+
|
|
3138
|
+
// src/components/dashboard/PrimusSummaryCard.tsx
|
|
3139
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3140
|
+
var PrimusSummaryCard = ({
|
|
3141
|
+
title,
|
|
3142
|
+
subtitle,
|
|
3143
|
+
actionLabel,
|
|
3144
|
+
onAction,
|
|
3145
|
+
children,
|
|
3146
|
+
className
|
|
3147
|
+
}) => {
|
|
3148
|
+
return /* @__PURE__ */ jsx36(Card, { className, children: /* @__PURE__ */ jsxs32("div", { className: "p-6", children: [
|
|
3149
|
+
/* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between mb-4", children: [
|
|
3150
|
+
/* @__PURE__ */ jsxs32("div", { children: [
|
|
3151
|
+
/* @__PURE__ */ jsx36("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: title }),
|
|
3152
|
+
subtitle && /* @__PURE__ */ jsx36("p", { className: "text-sm text-gray-500 dark:text-gray-400 mt-1", children: subtitle })
|
|
3153
|
+
] }),
|
|
3154
|
+
actionLabel && onAction && /* @__PURE__ */ jsx36(Button, { variant: "outline", size: "sm", onClick: onAction, children: actionLabel })
|
|
3155
|
+
] }),
|
|
3156
|
+
/* @__PURE__ */ jsx36("div", { className: "mt-4", children })
|
|
3157
|
+
] }) });
|
|
3158
|
+
};
|
|
3159
|
+
|
|
3160
|
+
// src/components/dashboard/PrimusActivityFeed.tsx
|
|
3161
|
+
import { useMemo as useMemo3 } from "react";
|
|
3162
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3163
|
+
var statusClasses = {
|
|
3164
|
+
success: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30",
|
|
3165
|
+
warning: "bg-amber-500/10 text-amber-300 border-amber-500/30",
|
|
3166
|
+
error: "bg-rose-500/10 text-rose-300 border-rose-500/30",
|
|
3167
|
+
info: "bg-blue-500/10 text-blue-300 border-blue-500/30"
|
|
3168
|
+
};
|
|
3169
|
+
var PrimusActivityFeed = ({
|
|
3170
|
+
items,
|
|
3171
|
+
maxItems = 10,
|
|
3172
|
+
showTimestamps = true,
|
|
3173
|
+
groupByDate = false,
|
|
3174
|
+
loading = false
|
|
3175
|
+
}) => {
|
|
2777
3176
|
const visibleItems = useMemo3(() => items.slice(0, maxItems), [items, maxItems]);
|
|
2778
3177
|
const groups = useMemo3(() => {
|
|
2779
3178
|
if (!groupByDate) {
|
|
@@ -2789,18 +3188,18 @@ var PrimusActivityFeed = ({
|
|
|
2789
3188
|
return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
2790
3189
|
}, [groupByDate, visibleItems]);
|
|
2791
3190
|
if (loading) {
|
|
2792
|
-
return /* @__PURE__ */
|
|
3191
|
+
return /* @__PURE__ */ jsx37("div", { className: "rounded-xl border border-white/10 bg-slate-900/40 p-6 text-sm text-gray-400", children: "Loading activity..." });
|
|
2793
3192
|
}
|
|
2794
|
-
return /* @__PURE__ */
|
|
2795
|
-
group.label && /* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
2797
|
-
/* @__PURE__ */
|
|
2798
|
-
/* @__PURE__ */
|
|
2799
|
-
/* @__PURE__ */
|
|
2800
|
-
/* @__PURE__ */
|
|
2801
|
-
showTimestamps && /* @__PURE__ */
|
|
3193
|
+
return /* @__PURE__ */ jsx37("div", { className: "rounded-xl border border-white/10 bg-slate-900/40 p-6 space-y-6", children: groups.map((group, index) => /* @__PURE__ */ jsxs33("div", { children: [
|
|
3194
|
+
group.label && /* @__PURE__ */ jsx37("div", { className: "text-xs uppercase tracking-wide text-gray-500 mb-3", children: group.label }),
|
|
3195
|
+
/* @__PURE__ */ jsx37("div", { className: "space-y-4", children: group.items.map((item, itemIndex) => /* @__PURE__ */ jsxs33("div", { className: "flex items-start gap-4", children: [
|
|
3196
|
+
/* @__PURE__ */ jsx37("div", { className: `mt-1 h-2.5 w-2.5 rounded-full border ${statusClasses[item.status ?? "info"]}` }),
|
|
3197
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
|
|
3198
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between gap-4", children: [
|
|
3199
|
+
/* @__PURE__ */ jsx37("div", { className: "text-sm font-medium text-gray-100", children: item.title }),
|
|
3200
|
+
showTimestamps && /* @__PURE__ */ jsx37("div", { className: "text-xs text-gray-500", children: formatTime(item.timestamp) })
|
|
2802
3201
|
] }),
|
|
2803
|
-
item.description && /* @__PURE__ */
|
|
3202
|
+
item.description && /* @__PURE__ */ jsx37("div", { className: "text-xs text-gray-400 mt-1", children: item.description })
|
|
2804
3203
|
] })
|
|
2805
3204
|
] }, item.id ?? `${itemIndex}-${item.title}`)) })
|
|
2806
3205
|
] }, `${group.label}-${index}`)) });
|
|
@@ -2827,12 +3226,12 @@ var formatTime = (value) => {
|
|
|
2827
3226
|
};
|
|
2828
3227
|
|
|
2829
3228
|
// src/components/charts/PrimusChartBase.tsx
|
|
2830
|
-
import { useEffect as useEffect14, useMemo as useMemo4, useRef } from "react";
|
|
3229
|
+
import { useEffect as useEffect14, useMemo as useMemo4, useRef as useRef2 } from "react";
|
|
2831
3230
|
import {
|
|
2832
3231
|
Chart,
|
|
2833
3232
|
registerables
|
|
2834
3233
|
} from "chart.js";
|
|
2835
|
-
import { jsx as
|
|
3234
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2836
3235
|
var registered = false;
|
|
2837
3236
|
var ensureRegistered = () => {
|
|
2838
3237
|
if (!registered) {
|
|
@@ -2855,8 +3254,8 @@ var PrimusChartBase = ({
|
|
|
2855
3254
|
className,
|
|
2856
3255
|
datasetTransform
|
|
2857
3256
|
}) => {
|
|
2858
|
-
const canvasRef =
|
|
2859
|
-
const chartRef =
|
|
3257
|
+
const canvasRef = useRef2(null);
|
|
3258
|
+
const chartRef = useRef2(null);
|
|
2860
3259
|
const builtData = useMemo4(() => {
|
|
2861
3260
|
if (data) {
|
|
2862
3261
|
return data;
|
|
@@ -2923,13 +3322,13 @@ var PrimusChartBase = ({
|
|
|
2923
3322
|
chartRef.current = null;
|
|
2924
3323
|
};
|
|
2925
3324
|
}, [type, builtData, builtOptions]);
|
|
2926
|
-
return /* @__PURE__ */
|
|
3325
|
+
return /* @__PURE__ */ jsx38("div", { className, style: { height, width }, children: /* @__PURE__ */ jsx38("canvas", { ref: canvasRef, "aria-label": ariaLabel, role: "img" }) });
|
|
2927
3326
|
};
|
|
2928
3327
|
|
|
2929
3328
|
// src/components/charts/PrimusLineChart.tsx
|
|
2930
|
-
import { jsx as
|
|
3329
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
2931
3330
|
var PrimusLineChart = (props) => {
|
|
2932
|
-
return /* @__PURE__ */
|
|
3331
|
+
return /* @__PURE__ */ jsx39(
|
|
2933
3332
|
PrimusChartBase,
|
|
2934
3333
|
{
|
|
2935
3334
|
...props,
|
|
@@ -2947,9 +3346,9 @@ var PrimusLineChart = (props) => {
|
|
|
2947
3346
|
};
|
|
2948
3347
|
|
|
2949
3348
|
// src/components/charts/PrimusAreaChart.tsx
|
|
2950
|
-
import { jsx as
|
|
3349
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
2951
3350
|
var PrimusAreaChart = (props) => {
|
|
2952
|
-
return /* @__PURE__ */
|
|
3351
|
+
return /* @__PURE__ */ jsx40(
|
|
2953
3352
|
PrimusChartBase,
|
|
2954
3353
|
{
|
|
2955
3354
|
...props,
|
|
@@ -2967,7 +3366,7 @@ var PrimusAreaChart = (props) => {
|
|
|
2967
3366
|
};
|
|
2968
3367
|
|
|
2969
3368
|
// src/components/charts/PrimusBarChart.tsx
|
|
2970
|
-
import { jsx as
|
|
3369
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2971
3370
|
var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
2972
3371
|
const mergedOptions = {
|
|
2973
3372
|
...options,
|
|
@@ -2977,7 +3376,7 @@ var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
|
2977
3376
|
...options?.scales ?? {}
|
|
2978
3377
|
}
|
|
2979
3378
|
};
|
|
2980
|
-
return /* @__PURE__ */
|
|
3379
|
+
return /* @__PURE__ */ jsx41(
|
|
2981
3380
|
PrimusChartBase,
|
|
2982
3381
|
{
|
|
2983
3382
|
...props,
|
|
@@ -2993,13 +3392,13 @@ var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
|
2993
3392
|
};
|
|
2994
3393
|
|
|
2995
3394
|
// src/components/charts/PrimusPieChart.tsx
|
|
2996
|
-
import { jsx as
|
|
3395
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2997
3396
|
var PrimusPieChart = ({ donut = false, cutout = "55%", options, ...props }) => {
|
|
2998
3397
|
const mergedOptions = {
|
|
2999
3398
|
...options,
|
|
3000
3399
|
cutout: donut ? cutout : void 0
|
|
3001
3400
|
};
|
|
3002
|
-
return /* @__PURE__ */
|
|
3401
|
+
return /* @__PURE__ */ jsx42(
|
|
3003
3402
|
PrimusChartBase,
|
|
3004
3403
|
{
|
|
3005
3404
|
...props,
|
|
@@ -3016,7 +3415,7 @@ var PrimusPieChart = ({ donut = false, cutout = "55%", options, ...props }) => {
|
|
|
3016
3415
|
|
|
3017
3416
|
// src/components/charts/PrimusSparkline.tsx
|
|
3018
3417
|
import { useMemo as useMemo5 } from "react";
|
|
3019
|
-
import { jsx as
|
|
3418
|
+
import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3020
3419
|
var PrimusSparkline = ({
|
|
3021
3420
|
series = [],
|
|
3022
3421
|
data,
|
|
@@ -3049,7 +3448,7 @@ var PrimusSparkline = ({
|
|
|
3049
3448
|
if (!values.length) {
|
|
3050
3449
|
return null;
|
|
3051
3450
|
}
|
|
3052
|
-
return /* @__PURE__ */
|
|
3451
|
+
return /* @__PURE__ */ jsxs34(
|
|
3053
3452
|
"svg",
|
|
3054
3453
|
{
|
|
3055
3454
|
className,
|
|
@@ -3060,17 +3459,17 @@ var PrimusSparkline = ({
|
|
|
3060
3459
|
"aria-label": ariaLabel,
|
|
3061
3460
|
role: "img",
|
|
3062
3461
|
children: [
|
|
3063
|
-
type === "area" && /* @__PURE__ */
|
|
3064
|
-
/* @__PURE__ */
|
|
3462
|
+
type === "area" && /* @__PURE__ */ jsx43("path", { d: areaPath, fill: color, opacity: 0.2, stroke: "none" }),
|
|
3463
|
+
/* @__PURE__ */ jsx43("path", { d: linePath, fill: "none", stroke: color, strokeWidth })
|
|
3065
3464
|
]
|
|
3066
3465
|
}
|
|
3067
3466
|
);
|
|
3068
3467
|
};
|
|
3069
3468
|
|
|
3070
3469
|
// src/components/shared/Checkbox.tsx
|
|
3071
|
-
import
|
|
3072
|
-
import { jsx as
|
|
3073
|
-
var Checkbox =
|
|
3470
|
+
import React24 from "react";
|
|
3471
|
+
import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3472
|
+
var Checkbox = React24.forwardRef(
|
|
3074
3473
|
({ style, label, error, disabled, className, ...props }, ref) => {
|
|
3075
3474
|
const containerStyles = {
|
|
3076
3475
|
display: "flex",
|
|
@@ -3107,9 +3506,9 @@ var Checkbox = React22.forwardRef(
|
|
|
3107
3506
|
marginTop: "0.25rem",
|
|
3108
3507
|
marginLeft: "1.75rem"
|
|
3109
3508
|
};
|
|
3110
|
-
return /* @__PURE__ */
|
|
3111
|
-
/* @__PURE__ */
|
|
3112
|
-
/* @__PURE__ */
|
|
3509
|
+
return /* @__PURE__ */ jsxs35("div", { children: [
|
|
3510
|
+
/* @__PURE__ */ jsxs35("div", { style: containerStyles, children: [
|
|
3511
|
+
/* @__PURE__ */ jsx44("div", { style: checkboxWrapperStyles, children: /* @__PURE__ */ jsx44(
|
|
3113
3512
|
"input",
|
|
3114
3513
|
{
|
|
3115
3514
|
ref,
|
|
@@ -3122,21 +3521,21 @@ var Checkbox = React22.forwardRef(
|
|
|
3122
3521
|
...props
|
|
3123
3522
|
}
|
|
3124
3523
|
) }),
|
|
3125
|
-
label && /* @__PURE__ */
|
|
3524
|
+
label && /* @__PURE__ */ jsx44("label", { style: labelStyles, onClick: (e) => {
|
|
3126
3525
|
if (!disabled) {
|
|
3127
3526
|
const input = e.currentTarget.previousElementSibling?.querySelector("input");
|
|
3128
3527
|
input?.click();
|
|
3129
3528
|
}
|
|
3130
3529
|
}, children: label })
|
|
3131
3530
|
] }),
|
|
3132
|
-
error && /* @__PURE__ */
|
|
3531
|
+
error && /* @__PURE__ */ jsx44("p", { style: errorTextStyles, children: error })
|
|
3133
3532
|
] });
|
|
3134
3533
|
}
|
|
3135
3534
|
);
|
|
3136
3535
|
Checkbox.displayName = "Checkbox";
|
|
3137
3536
|
|
|
3138
3537
|
// src/components/shared/RadioGroup.tsx
|
|
3139
|
-
import { jsx as
|
|
3538
|
+
import { jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3140
3539
|
var RadioGroup = ({
|
|
3141
3540
|
name,
|
|
3142
3541
|
options,
|
|
@@ -3176,9 +3575,9 @@ var RadioGroup = ({
|
|
|
3176
3575
|
color: "#ef4444",
|
|
3177
3576
|
marginTop: "0.5rem"
|
|
3178
3577
|
};
|
|
3179
|
-
return /* @__PURE__ */
|
|
3180
|
-
/* @__PURE__ */
|
|
3181
|
-
/* @__PURE__ */
|
|
3578
|
+
return /* @__PURE__ */ jsxs36("div", { children: [
|
|
3579
|
+
/* @__PURE__ */ jsx45("div", { style: containerStyles, children: options.map((option) => /* @__PURE__ */ jsxs36("div", { style: optionStyles, children: [
|
|
3580
|
+
/* @__PURE__ */ jsx45(
|
|
3182
3581
|
"input",
|
|
3183
3582
|
{
|
|
3184
3583
|
type: "radio",
|
|
@@ -3190,7 +3589,7 @@ var RadioGroup = ({
|
|
|
3190
3589
|
style: radioStyles
|
|
3191
3590
|
}
|
|
3192
3591
|
),
|
|
3193
|
-
/* @__PURE__ */
|
|
3592
|
+
/* @__PURE__ */ jsx45(
|
|
3194
3593
|
"label",
|
|
3195
3594
|
{
|
|
3196
3595
|
style: {
|
|
@@ -3206,17 +3605,17 @@ var RadioGroup = ({
|
|
|
3206
3605
|
}
|
|
3207
3606
|
)
|
|
3208
3607
|
] }, option.value)) }),
|
|
3209
|
-
error && /* @__PURE__ */
|
|
3608
|
+
error && /* @__PURE__ */ jsx45("p", { style: errorTextStyles, children: error })
|
|
3210
3609
|
] });
|
|
3211
3610
|
};
|
|
3212
3611
|
RadioGroup.displayName = "RadioGroup";
|
|
3213
3612
|
|
|
3214
3613
|
// src/components/shared/Select.tsx
|
|
3215
|
-
import
|
|
3614
|
+
import React25, { useState as useState22 } from "react";
|
|
3216
3615
|
import { Combobox, Transition as Transition2 } from "@headlessui/react";
|
|
3217
3616
|
import { CheckIcon as CheckIcon2, ChevronUpDownIcon, XMarkIcon as XMarkIcon3 } from "@heroicons/react/20/solid";
|
|
3218
3617
|
import { clsx as clsx7 } from "clsx";
|
|
3219
|
-
import { Fragment as Fragment5, jsx as
|
|
3618
|
+
import { Fragment as Fragment5, jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3220
3619
|
var Select = ({
|
|
3221
3620
|
label,
|
|
3222
3621
|
error,
|
|
@@ -3238,7 +3637,7 @@ var Select = ({
|
|
|
3238
3637
|
onChange?.(value.filter((v) => v !== valToRemove));
|
|
3239
3638
|
}
|
|
3240
3639
|
};
|
|
3241
|
-
return /* @__PURE__ */
|
|
3640
|
+
return /* @__PURE__ */ jsx46("div", { className: clsx7("w-full", className), children: /* @__PURE__ */ jsx46(
|
|
3242
3641
|
Combobox,
|
|
3243
3642
|
{
|
|
3244
3643
|
value,
|
|
@@ -3247,21 +3646,21 @@ var Select = ({
|
|
|
3247
3646
|
},
|
|
3248
3647
|
multiple,
|
|
3249
3648
|
disabled,
|
|
3250
|
-
children: ({}) => /* @__PURE__ */
|
|
3251
|
-
label && /* @__PURE__ */
|
|
3252
|
-
/* @__PURE__ */
|
|
3649
|
+
children: ({}) => /* @__PURE__ */ jsxs37("div", { className: "relative", children: [
|
|
3650
|
+
label && /* @__PURE__ */ jsx46(Combobox.Label, { className: "block text-sm font-medium text-gray-700 mb-1", children: label }),
|
|
3651
|
+
/* @__PURE__ */ jsxs37("div", { className: clsx7(
|
|
3253
3652
|
"relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left focus-within:ring-2 focus-within:ring-primus-500",
|
|
3254
3653
|
"border transition-all duration-200 ease-in-out",
|
|
3255
3654
|
error ? "border-red-500 focus-within:ring-red-500" : "border-gray-300",
|
|
3256
3655
|
disabled && "opacity-50 cursor-not-allowed bg-gray-50"
|
|
3257
3656
|
), children: [
|
|
3258
|
-
/* @__PURE__ */
|
|
3657
|
+
/* @__PURE__ */ jsxs37("div", { className: clsx7(
|
|
3259
3658
|
"flex flex-wrap items-center gap-1.5 w-full py-1.5 pl-3 pr-10 text-sm",
|
|
3260
3659
|
"min-h-[2.5rem]"
|
|
3261
3660
|
), children: [
|
|
3262
|
-
multiple && Array.isArray(value) && value.map((val) => /* @__PURE__ */
|
|
3263
|
-
/* @__PURE__ */
|
|
3264
|
-
/* @__PURE__ */
|
|
3661
|
+
multiple && Array.isArray(value) && value.map((val) => /* @__PURE__ */ jsxs37("span", { className: "inline-flex items-center gap-1 rounded bg-primus-50 px-2 py-0.5 text-xs font-medium text-primus-700 ring-1 ring-inset ring-primus-700/10 max-w-[150px]", children: [
|
|
3662
|
+
/* @__PURE__ */ jsx46("span", { className: "truncate", children: getLabel(val) }),
|
|
3663
|
+
/* @__PURE__ */ jsxs37(
|
|
3265
3664
|
"button",
|
|
3266
3665
|
{
|
|
3267
3666
|
type: "button",
|
|
@@ -3273,13 +3672,13 @@ var Select = ({
|
|
|
3273
3672
|
},
|
|
3274
3673
|
onMouseDown: (e) => e.preventDefault(),
|
|
3275
3674
|
children: [
|
|
3276
|
-
/* @__PURE__ */
|
|
3277
|
-
/* @__PURE__ */
|
|
3675
|
+
/* @__PURE__ */ jsx46("span", { className: "sr-only", children: "Remove" }),
|
|
3676
|
+
/* @__PURE__ */ jsx46(XMarkIcon3, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
3278
3677
|
]
|
|
3279
3678
|
}
|
|
3280
3679
|
)
|
|
3281
3680
|
] }, val)),
|
|
3282
|
-
/* @__PURE__ */
|
|
3681
|
+
/* @__PURE__ */ jsx46(
|
|
3283
3682
|
Combobox.Input,
|
|
3284
3683
|
{
|
|
3285
3684
|
className: "border-none p-0 text-gray-900 focus:ring-0 outline-none placeholder:text-gray-400 bg-transparent min-w-[50px] flex-1 text-sm leading-5 py-0.5",
|
|
@@ -3289,7 +3688,7 @@ var Select = ({
|
|
|
3289
3688
|
}
|
|
3290
3689
|
)
|
|
3291
3690
|
] }),
|
|
3292
|
-
/* @__PURE__ */
|
|
3691
|
+
/* @__PURE__ */ jsx46(Combobox.Button, { className: "absolute inset-y-0 right-0 flex items-center pr-2", children: /* @__PURE__ */ jsx46(
|
|
3293
3692
|
ChevronUpDownIcon,
|
|
3294
3693
|
{
|
|
3295
3694
|
className: "h-5 w-5 text-gray-400",
|
|
@@ -3297,15 +3696,15 @@ var Select = ({
|
|
|
3297
3696
|
}
|
|
3298
3697
|
) })
|
|
3299
3698
|
] }),
|
|
3300
|
-
/* @__PURE__ */
|
|
3699
|
+
/* @__PURE__ */ jsx46(
|
|
3301
3700
|
Transition2,
|
|
3302
3701
|
{
|
|
3303
|
-
as:
|
|
3702
|
+
as: React25.Fragment,
|
|
3304
3703
|
leave: "transition ease-in duration-100",
|
|
3305
3704
|
leaveFrom: "opacity-100",
|
|
3306
3705
|
leaveTo: "opacity-0",
|
|
3307
3706
|
afterLeave: () => setQuery(""),
|
|
3308
|
-
children: /* @__PURE__ */
|
|
3707
|
+
children: /* @__PURE__ */ jsx46(Combobox.Options, { className: "absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm", children: filteredOptions.length === 0 && query !== "" ? /* @__PURE__ */ jsx46("div", { className: "relative cursor-default select-none py-2 px-4 text-gray-700", children: "Nothing found." }) : filteredOptions.map((option) => /* @__PURE__ */ jsx46(
|
|
3309
3708
|
Combobox.Option,
|
|
3310
3709
|
{
|
|
3311
3710
|
className: ({ active }) => clsx7(
|
|
@@ -3314,16 +3713,16 @@ var Select = ({
|
|
|
3314
3713
|
),
|
|
3315
3714
|
value: option.value,
|
|
3316
3715
|
disabled: option.disabled,
|
|
3317
|
-
children: ({ selected, active }) => /* @__PURE__ */
|
|
3318
|
-
/* @__PURE__ */
|
|
3319
|
-
selected ? /* @__PURE__ */
|
|
3716
|
+
children: ({ selected, active }) => /* @__PURE__ */ jsxs37(Fragment5, { children: [
|
|
3717
|
+
/* @__PURE__ */ jsx46("span", { className: clsx7("block truncate", selected ? "font-medium" : "font-normal"), children: option.label }),
|
|
3718
|
+
selected ? /* @__PURE__ */ jsx46(
|
|
3320
3719
|
"span",
|
|
3321
3720
|
{
|
|
3322
3721
|
className: clsx7(
|
|
3323
3722
|
"absolute inset-y-0 left-0 flex items-center pl-3",
|
|
3324
3723
|
active ? "text-white" : "text-primus-600"
|
|
3325
3724
|
),
|
|
3326
|
-
children: /* @__PURE__ */
|
|
3725
|
+
children: /* @__PURE__ */ jsx46(CheckIcon2, { className: "h-5 w-5", "aria-hidden": "true" })
|
|
3327
3726
|
}
|
|
3328
3727
|
) : null
|
|
3329
3728
|
] })
|
|
@@ -3332,15 +3731,15 @@ var Select = ({
|
|
|
3332
3731
|
)) })
|
|
3333
3732
|
}
|
|
3334
3733
|
),
|
|
3335
|
-
error && /* @__PURE__ */
|
|
3734
|
+
error && /* @__PURE__ */ jsx46("p", { className: "mt-1 text-sm text-red-500", children: error })
|
|
3336
3735
|
] })
|
|
3337
3736
|
}
|
|
3338
3737
|
) });
|
|
3339
3738
|
};
|
|
3340
3739
|
|
|
3341
3740
|
// src/components/shared/Toggle.tsx
|
|
3342
|
-
import
|
|
3343
|
-
import { jsx as
|
|
3741
|
+
import React26 from "react";
|
|
3742
|
+
import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3344
3743
|
var Toggle = ({
|
|
3345
3744
|
checked = false,
|
|
3346
3745
|
onChange,
|
|
@@ -3348,7 +3747,7 @@ var Toggle = ({
|
|
|
3348
3747
|
label,
|
|
3349
3748
|
size = "md"
|
|
3350
3749
|
}) => {
|
|
3351
|
-
const [isHovered, setIsHovered] =
|
|
3750
|
+
const [isHovered, setIsHovered] = React26.useState(false);
|
|
3352
3751
|
const sizes = {
|
|
3353
3752
|
sm: { width: "2.25rem", height: "1.25rem", thumbSize: "0.875rem" },
|
|
3354
3753
|
md: { width: "2.75rem", height: "1.5rem", thumbSize: "1.125rem" },
|
|
@@ -3395,8 +3794,8 @@ var Toggle = ({
|
|
|
3395
3794
|
onChange?.(!checked);
|
|
3396
3795
|
}
|
|
3397
3796
|
};
|
|
3398
|
-
return /* @__PURE__ */
|
|
3399
|
-
/* @__PURE__ */
|
|
3797
|
+
return /* @__PURE__ */ jsxs38("div", { style: containerStyles, children: [
|
|
3798
|
+
/* @__PURE__ */ jsx47(
|
|
3400
3799
|
"div",
|
|
3401
3800
|
{
|
|
3402
3801
|
style: switchStyles,
|
|
@@ -3412,20 +3811,23 @@ var Toggle = ({
|
|
|
3412
3811
|
handleClick();
|
|
3413
3812
|
}
|
|
3414
3813
|
},
|
|
3415
|
-
children: /* @__PURE__ */
|
|
3814
|
+
children: /* @__PURE__ */ jsx47("div", { style: thumbStyles })
|
|
3416
3815
|
}
|
|
3417
3816
|
),
|
|
3418
|
-
label && /* @__PURE__ */
|
|
3817
|
+
label && /* @__PURE__ */ jsx47("label", { style: labelStyles, onClick: handleClick, children: label })
|
|
3419
3818
|
] });
|
|
3420
3819
|
};
|
|
3421
3820
|
Toggle.displayName = "Toggle";
|
|
3422
3821
|
|
|
3423
3822
|
// src/components/shared/Textarea.tsx
|
|
3424
|
-
import
|
|
3425
|
-
import { jsx as
|
|
3426
|
-
var Textarea =
|
|
3427
|
-
({ style, label, error, disabled, resize = "vertical", ...props }, ref) => {
|
|
3428
|
-
const
|
|
3823
|
+
import React27 from "react";
|
|
3824
|
+
import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3825
|
+
var Textarea = React27.forwardRef(
|
|
3826
|
+
({ style, label, error, disabled, resize = "vertical", onChange, onValueChange, className, ...props }, ref) => {
|
|
3827
|
+
const handleChange = (e) => {
|
|
3828
|
+
onChange?.(e);
|
|
3829
|
+
onValueChange?.(e.target.value);
|
|
3830
|
+
};
|
|
3429
3831
|
const containerStyles = {
|
|
3430
3832
|
width: "100%"
|
|
3431
3833
|
};
|
|
@@ -3433,11 +3835,11 @@ var Textarea = React25.forwardRef(
|
|
|
3433
3835
|
fontSize: "0.875rem",
|
|
3434
3836
|
lineHeight: "1.25rem",
|
|
3435
3837
|
fontWeight: "500",
|
|
3436
|
-
marginBottom: "0.
|
|
3838
|
+
marginBottom: "0.375rem",
|
|
3437
3839
|
display: "block",
|
|
3438
3840
|
color: "#374151",
|
|
3439
|
-
|
|
3440
|
-
|
|
3841
|
+
opacity: disabled ? 0.7 : 1,
|
|
3842
|
+
cursor: disabled ? "not-allowed" : "default"
|
|
3441
3843
|
};
|
|
3442
3844
|
const textareaStyles = {
|
|
3443
3845
|
display: "flex",
|
|
@@ -3450,12 +3852,11 @@ var Textarea = React25.forwardRef(
|
|
|
3450
3852
|
fontSize: "0.875rem",
|
|
3451
3853
|
lineHeight: "1.5rem",
|
|
3452
3854
|
outline: "none",
|
|
3453
|
-
transition: "
|
|
3454
|
-
cursor: disabled ? "not-allowed" : "text",
|
|
3855
|
+
transition: "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out",
|
|
3455
3856
|
opacity: disabled ? 0.5 : 1,
|
|
3857
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
3456
3858
|
resize,
|
|
3457
|
-
fontFamily: "inherit"
|
|
3458
|
-
boxShadow: isFocused ? error ? "0 0 0 2px rgba(239, 68, 68, 0.2)" : "0 0 0 2px rgba(3, 7, 18, 0.1)" : "none"
|
|
3859
|
+
fontFamily: "inherit"
|
|
3459
3860
|
};
|
|
3460
3861
|
const errorTextStyles = {
|
|
3461
3862
|
fontSize: "0.875rem",
|
|
@@ -3463,9 +3864,9 @@ var Textarea = React25.forwardRef(
|
|
|
3463
3864
|
color: "#ef4444",
|
|
3464
3865
|
marginTop: "0.25rem"
|
|
3465
3866
|
};
|
|
3466
|
-
return /* @__PURE__ */
|
|
3467
|
-
label && /* @__PURE__ */
|
|
3468
|
-
/* @__PURE__ */
|
|
3867
|
+
return /* @__PURE__ */ jsxs39("div", { style: containerStyles, className, children: [
|
|
3868
|
+
label && /* @__PURE__ */ jsx48("label", { style: labelStyles, children: label }),
|
|
3869
|
+
/* @__PURE__ */ jsx48(
|
|
3469
3870
|
"textarea",
|
|
3470
3871
|
{
|
|
3471
3872
|
ref,
|
|
@@ -3473,94 +3874,28 @@ var Textarea = React25.forwardRef(
|
|
|
3473
3874
|
...textareaStyles,
|
|
3474
3875
|
...style
|
|
3475
3876
|
},
|
|
3476
|
-
onFocus: () => setIsFocused(true),
|
|
3477
|
-
onBlur: () => setIsFocused(false),
|
|
3478
3877
|
disabled,
|
|
3878
|
+
onChange: handleChange,
|
|
3879
|
+
className: `primus-textarea ${error ? "error" : ""}`,
|
|
3479
3880
|
...props
|
|
3480
3881
|
}
|
|
3481
3882
|
),
|
|
3482
|
-
|
|
3883
|
+
/* @__PURE__ */ jsx48("style", { children: `
|
|
3884
|
+
.primus-textarea:focus {
|
|
3885
|
+
border-color: ${error ? "#ef4444" : "#6366f1"};
|
|
3886
|
+
box-shadow: 0 0 0 1px ${error ? "#ef4444" : "#6366f1"};
|
|
3887
|
+
}
|
|
3888
|
+
` }),
|
|
3889
|
+
error && /* @__PURE__ */ jsx48("p", { style: errorTextStyles, children: error })
|
|
3483
3890
|
] });
|
|
3484
3891
|
}
|
|
3485
3892
|
);
|
|
3486
3893
|
Textarea.displayName = "Textarea";
|
|
3487
3894
|
|
|
3488
|
-
// src/components/shared/Card.tsx
|
|
3489
|
-
import React26 from "react";
|
|
3490
|
-
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
3491
|
-
var Card = React26.forwardRef(
|
|
3492
|
-
({ style, variant = "default", padding = "md", children, ...props }, ref) => {
|
|
3493
|
-
const [isHovered, setIsHovered] = React26.useState(false);
|
|
3494
|
-
const paddingStyles = {
|
|
3495
|
-
none: "0",
|
|
3496
|
-
sm: "0.75rem",
|
|
3497
|
-
md: "1.5rem",
|
|
3498
|
-
lg: "2rem"
|
|
3499
|
-
};
|
|
3500
|
-
const variantStyles = {
|
|
3501
|
-
default: {
|
|
3502
|
-
normal: {
|
|
3503
|
-
backgroundColor: "#ffffff",
|
|
3504
|
-
border: "1px solid #e5e7eb",
|
|
3505
|
-
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
3506
|
-
},
|
|
3507
|
-
hover: {
|
|
3508
|
-
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3509
|
-
}
|
|
3510
|
-
},
|
|
3511
|
-
outlined: {
|
|
3512
|
-
normal: {
|
|
3513
|
-
backgroundColor: "#ffffff",
|
|
3514
|
-
border: "2px solid #e5e7eb",
|
|
3515
|
-
boxShadow: "none"
|
|
3516
|
-
},
|
|
3517
|
-
hover: {
|
|
3518
|
-
borderColor: "#d1d5db"
|
|
3519
|
-
}
|
|
3520
|
-
},
|
|
3521
|
-
elevated: {
|
|
3522
|
-
normal: {
|
|
3523
|
-
backgroundColor: "#ffffff",
|
|
3524
|
-
border: "none",
|
|
3525
|
-
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3526
|
-
},
|
|
3527
|
-
hover: {
|
|
3528
|
-
boxShadow: "0 10px 15px rgba(0, 0, 0, 0.15)",
|
|
3529
|
-
transform: "translateY(-2px)"
|
|
3530
|
-
}
|
|
3531
|
-
}
|
|
3532
|
-
};
|
|
3533
|
-
const baseStyles = {
|
|
3534
|
-
borderRadius: "0.5rem",
|
|
3535
|
-
padding: paddingStyles[padding],
|
|
3536
|
-
transition: "all 0.2s ease"
|
|
3537
|
-
};
|
|
3538
|
-
const currentVariant = variantStyles[variant];
|
|
3539
|
-
const combinedStyles = {
|
|
3540
|
-
...baseStyles,
|
|
3541
|
-
...currentVariant.normal,
|
|
3542
|
-
...isHovered ? currentVariant.hover : {},
|
|
3543
|
-
...style
|
|
3544
|
-
};
|
|
3545
|
-
return /* @__PURE__ */ jsx46(
|
|
3546
|
-
"div",
|
|
3547
|
-
{
|
|
3548
|
-
ref,
|
|
3549
|
-
style: combinedStyles,
|
|
3550
|
-
onMouseEnter: () => setIsHovered(true),
|
|
3551
|
-
onMouseLeave: () => setIsHovered(false),
|
|
3552
|
-
...props,
|
|
3553
|
-
children
|
|
3554
|
-
}
|
|
3555
|
-
);
|
|
3556
|
-
}
|
|
3557
|
-
);
|
|
3558
|
-
Card.displayName = "Card";
|
|
3559
|
-
|
|
3560
3895
|
// src/components/shared/Badge.tsx
|
|
3561
|
-
import
|
|
3562
|
-
import { jsx as
|
|
3563
|
-
var Badge =
|
|
3896
|
+
import React28 from "react";
|
|
3897
|
+
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
3898
|
+
var Badge = React28.forwardRef(
|
|
3564
3899
|
({ style, variant = "default", size = "md", children, ...props }, ref) => {
|
|
3565
3900
|
const variantStyles = {
|
|
3566
3901
|
default: {
|
|
@@ -3614,14 +3949,14 @@ var Badge = React27.forwardRef(
|
|
|
3614
3949
|
...sizeStyles[size],
|
|
3615
3950
|
...style
|
|
3616
3951
|
};
|
|
3617
|
-
return /* @__PURE__ */
|
|
3952
|
+
return /* @__PURE__ */ jsx49("span", { ref, style: combinedStyles, ...props, children });
|
|
3618
3953
|
}
|
|
3619
3954
|
);
|
|
3620
3955
|
Badge.displayName = "Badge";
|
|
3621
3956
|
|
|
3622
3957
|
// src/components/shared/Table.tsx
|
|
3623
|
-
import
|
|
3624
|
-
import { jsx as
|
|
3958
|
+
import React29 from "react";
|
|
3959
|
+
import { jsx as jsx50, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3625
3960
|
function Table({
|
|
3626
3961
|
columns,
|
|
3627
3962
|
data,
|
|
@@ -3630,7 +3965,7 @@ function Table({
|
|
|
3630
3965
|
bordered = true,
|
|
3631
3966
|
style
|
|
3632
3967
|
}) {
|
|
3633
|
-
const [hoveredRow, setHoveredRow] =
|
|
3968
|
+
const [hoveredRow, setHoveredRow] = React29.useState(null);
|
|
3634
3969
|
const tableStyles = {
|
|
3635
3970
|
width: "100%",
|
|
3636
3971
|
borderCollapse: "collapse",
|
|
@@ -3655,8 +3990,8 @@ function Table({
|
|
|
3655
3990
|
backgroundColor: hoverable && hoveredRow === rowIndex ? "#f9fafb" : striped && rowIndex % 2 === 1 ? "#f9fafb" : "#ffffff",
|
|
3656
3991
|
transition: "background-color 0.15s ease"
|
|
3657
3992
|
});
|
|
3658
|
-
return /* @__PURE__ */
|
|
3659
|
-
/* @__PURE__ */
|
|
3993
|
+
return /* @__PURE__ */ jsx50("div", { style: { overflowX: "auto", borderRadius: "0.5rem", border: bordered ? "1px solid #e5e7eb" : "none" }, children: /* @__PURE__ */ jsxs40("table", { style: tableStyles, children: [
|
|
3994
|
+
/* @__PURE__ */ jsx50("thead", { style: theadStyles, children: /* @__PURE__ */ jsx50("tr", { children: columns.map((column) => /* @__PURE__ */ jsx50(
|
|
3660
3995
|
"th",
|
|
3661
3996
|
{
|
|
3662
3997
|
style: {
|
|
@@ -3667,12 +4002,12 @@ function Table({
|
|
|
3667
4002
|
},
|
|
3668
4003
|
column.key
|
|
3669
4004
|
)) }) }),
|
|
3670
|
-
/* @__PURE__ */
|
|
4005
|
+
/* @__PURE__ */ jsx50("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsx50(
|
|
3671
4006
|
"tr",
|
|
3672
4007
|
{
|
|
3673
4008
|
onMouseEnter: () => hoverable && setHoveredRow(rowIndex),
|
|
3674
4009
|
onMouseLeave: () => hoverable && setHoveredRow(null),
|
|
3675
|
-
children: columns.map((column) => /* @__PURE__ */
|
|
4010
|
+
children: columns.map((column) => /* @__PURE__ */ jsx50("td", { style: getTdStyles(rowIndex), children: column.render ? column.render(row) : row[column.key] }, column.key))
|
|
3676
4011
|
},
|
|
3677
4012
|
rowIndex
|
|
3678
4013
|
)) })
|
|
@@ -3681,9 +4016,9 @@ function Table({
|
|
|
3681
4016
|
Table.displayName = "Table";
|
|
3682
4017
|
|
|
3683
4018
|
// src/components/shared/Container.tsx
|
|
3684
|
-
import
|
|
3685
|
-
import { jsx as
|
|
3686
|
-
var Container =
|
|
4019
|
+
import React30 from "react";
|
|
4020
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
4021
|
+
var Container = React30.forwardRef(
|
|
3687
4022
|
({ style, maxWidth = "lg", padding = "md", children, ...props }, ref) => {
|
|
3688
4023
|
const maxWidthStyles = {
|
|
3689
4024
|
sm: "640px",
|
|
@@ -3708,15 +4043,15 @@ var Container = React29.forwardRef(
|
|
|
3708
4043
|
paddingRight: paddingStyles[padding],
|
|
3709
4044
|
...style
|
|
3710
4045
|
};
|
|
3711
|
-
return /* @__PURE__ */
|
|
4046
|
+
return /* @__PURE__ */ jsx51("div", { ref, style: containerStyles, ...props, children });
|
|
3712
4047
|
}
|
|
3713
4048
|
);
|
|
3714
4049
|
Container.displayName = "Container";
|
|
3715
4050
|
|
|
3716
4051
|
// src/components/shared/Grid.tsx
|
|
3717
|
-
import
|
|
3718
|
-
import { jsx as
|
|
3719
|
-
var Grid =
|
|
4052
|
+
import React31 from "react";
|
|
4053
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
4054
|
+
var Grid = React31.forwardRef(
|
|
3720
4055
|
({ style, columns = 3, rows, gap = "md", width = "100%", height = "auto", responsive = true, children, ...props }, ref) => {
|
|
3721
4056
|
const gapStyles = {
|
|
3722
4057
|
none: "0",
|
|
@@ -3734,15 +4069,15 @@ var Grid = React30.forwardRef(
|
|
|
3734
4069
|
height,
|
|
3735
4070
|
...style
|
|
3736
4071
|
};
|
|
3737
|
-
return /* @__PURE__ */
|
|
4072
|
+
return /* @__PURE__ */ jsx52("div", { ref, style: gridStyles, ...props, children });
|
|
3738
4073
|
}
|
|
3739
4074
|
);
|
|
3740
4075
|
Grid.displayName = "Grid";
|
|
3741
4076
|
|
|
3742
4077
|
// src/components/shared/Stack.tsx
|
|
3743
|
-
import
|
|
3744
|
-
import { jsx as
|
|
3745
|
-
var Stack =
|
|
4078
|
+
import React32 from "react";
|
|
4079
|
+
import { jsx as jsx53 } from "react/jsx-runtime";
|
|
4080
|
+
var Stack = React32.forwardRef(
|
|
3746
4081
|
({ style, direction = "vertical", gap = "md", align = "stretch", justify = "start", children, ...props }, ref) => {
|
|
3747
4082
|
const gapStyles = {
|
|
3748
4083
|
none: "0",
|
|
@@ -3772,14 +4107,14 @@ var Stack = React31.forwardRef(
|
|
|
3772
4107
|
justifyContent: justifyStyles[justify],
|
|
3773
4108
|
...style
|
|
3774
4109
|
};
|
|
3775
|
-
return /* @__PURE__ */
|
|
4110
|
+
return /* @__PURE__ */ jsx53("div", { ref, style: stackStyles, ...props, children });
|
|
3776
4111
|
}
|
|
3777
4112
|
);
|
|
3778
4113
|
Stack.displayName = "Stack";
|
|
3779
4114
|
|
|
3780
4115
|
// src/components/shared/Modal.tsx
|
|
3781
|
-
import
|
|
3782
|
-
import { jsx as
|
|
4116
|
+
import React33 from "react";
|
|
4117
|
+
import { jsx as jsx54, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3783
4118
|
var Modal = ({
|
|
3784
4119
|
isOpen,
|
|
3785
4120
|
onClose,
|
|
@@ -3788,7 +4123,7 @@ var Modal = ({
|
|
|
3788
4123
|
size = "md",
|
|
3789
4124
|
closeOnOverlayClick = true
|
|
3790
4125
|
}) => {
|
|
3791
|
-
|
|
4126
|
+
React33.useEffect(() => {
|
|
3792
4127
|
if (isOpen) {
|
|
3793
4128
|
document.body.style.overflow = "hidden";
|
|
3794
4129
|
} else {
|
|
@@ -3857,20 +4192,20 @@ var Modal = ({
|
|
|
3857
4192
|
overflowY: "auto",
|
|
3858
4193
|
flex: 1
|
|
3859
4194
|
};
|
|
3860
|
-
return /* @__PURE__ */
|
|
4195
|
+
return /* @__PURE__ */ jsx54(
|
|
3861
4196
|
"div",
|
|
3862
4197
|
{
|
|
3863
4198
|
style: overlayStyles,
|
|
3864
4199
|
onClick: closeOnOverlayClick ? onClose : void 0,
|
|
3865
|
-
children: /* @__PURE__ */
|
|
4200
|
+
children: /* @__PURE__ */ jsxs41(
|
|
3866
4201
|
"div",
|
|
3867
4202
|
{
|
|
3868
4203
|
style: modalStyles,
|
|
3869
4204
|
onClick: (e) => e.stopPropagation(),
|
|
3870
4205
|
children: [
|
|
3871
|
-
title && /* @__PURE__ */
|
|
3872
|
-
/* @__PURE__ */
|
|
3873
|
-
/* @__PURE__ */
|
|
4206
|
+
title && /* @__PURE__ */ jsxs41("div", { style: headerStyles, children: [
|
|
4207
|
+
/* @__PURE__ */ jsx54("h2", { style: titleStyles, children: title }),
|
|
4208
|
+
/* @__PURE__ */ jsx54(
|
|
3874
4209
|
"button",
|
|
3875
4210
|
{
|
|
3876
4211
|
style: closeButtonStyles,
|
|
@@ -3880,7 +4215,7 @@ var Modal = ({
|
|
|
3880
4215
|
}
|
|
3881
4216
|
)
|
|
3882
4217
|
] }),
|
|
3883
|
-
/* @__PURE__ */
|
|
4218
|
+
/* @__PURE__ */ jsx54("div", { style: contentStyles, children })
|
|
3884
4219
|
]
|
|
3885
4220
|
}
|
|
3886
4221
|
)
|
|
@@ -3891,7 +4226,7 @@ Modal.displayName = "Modal";
|
|
|
3891
4226
|
|
|
3892
4227
|
// src/components/shared/DateRangePicker.tsx
|
|
3893
4228
|
import { useEffect as useEffect15, useMemo as useMemo6, useState as useState23 } from "react";
|
|
3894
|
-
import { jsx as
|
|
4229
|
+
import { jsx as jsx55, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3895
4230
|
var PrimusDateRangePicker = ({
|
|
3896
4231
|
startDate = null,
|
|
3897
4232
|
endDate = null,
|
|
@@ -3927,8 +4262,8 @@ var PrimusDateRangePicker = ({
|
|
|
3927
4262
|
setEnd(nextEnd);
|
|
3928
4263
|
onRangeChange?.({ startDate: nextStart, endDate: nextEnd, label: range.label });
|
|
3929
4264
|
};
|
|
3930
|
-
return /* @__PURE__ */
|
|
3931
|
-
normalizedRanges.length > 0 && /* @__PURE__ */
|
|
4265
|
+
return /* @__PURE__ */ jsxs42("div", { className: "space-y-3", children: [
|
|
4266
|
+
normalizedRanges.length > 0 && /* @__PURE__ */ jsx55("div", { className: "flex flex-wrap gap-2", children: normalizedRanges.map((range) => /* @__PURE__ */ jsx55(
|
|
3932
4267
|
"button",
|
|
3933
4268
|
{
|
|
3934
4269
|
type: "button",
|
|
@@ -3939,8 +4274,8 @@ var PrimusDateRangePicker = ({
|
|
|
3939
4274
|
},
|
|
3940
4275
|
range.label
|
|
3941
4276
|
)) }),
|
|
3942
|
-
/* @__PURE__ */
|
|
3943
|
-
/* @__PURE__ */
|
|
4277
|
+
/* @__PURE__ */ jsxs42("div", { className: "flex flex-col md:flex-row gap-3", children: [
|
|
4278
|
+
/* @__PURE__ */ jsx55(
|
|
3944
4279
|
"input",
|
|
3945
4280
|
{
|
|
3946
4281
|
type: "date",
|
|
@@ -3952,7 +4287,7 @@ var PrimusDateRangePicker = ({
|
|
|
3952
4287
|
className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
|
|
3953
4288
|
}
|
|
3954
4289
|
),
|
|
3955
|
-
/* @__PURE__ */
|
|
4290
|
+
/* @__PURE__ */ jsx55(
|
|
3956
4291
|
"input",
|
|
3957
4292
|
{
|
|
3958
4293
|
type: "date",
|
|
@@ -4003,7 +4338,7 @@ var toDateInputValue = (value) => {
|
|
|
4003
4338
|
};
|
|
4004
4339
|
|
|
4005
4340
|
// src/components/shared/FilterBar.tsx
|
|
4006
|
-
import { jsx as
|
|
4341
|
+
import { jsx as jsx56, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
4007
4342
|
var PrimusFilterBar = ({
|
|
4008
4343
|
filters,
|
|
4009
4344
|
activeFilters,
|
|
@@ -4017,9 +4352,9 @@ var PrimusFilterBar = ({
|
|
|
4017
4352
|
};
|
|
4018
4353
|
onChange?.(next);
|
|
4019
4354
|
};
|
|
4020
|
-
return /* @__PURE__ */
|
|
4021
|
-
filters.map((filter) => /* @__PURE__ */
|
|
4022
|
-
filter.type === "select" && /* @__PURE__ */
|
|
4355
|
+
return /* @__PURE__ */ jsxs43("div", { className: "flex flex-wrap gap-4 items-end", children: [
|
|
4356
|
+
filters.map((filter) => /* @__PURE__ */ jsxs43("div", { className: "min-w-[220px]", children: [
|
|
4357
|
+
filter.type === "select" && /* @__PURE__ */ jsx56(
|
|
4023
4358
|
Select,
|
|
4024
4359
|
{
|
|
4025
4360
|
label: filter.label,
|
|
@@ -4029,7 +4364,7 @@ var PrimusFilterBar = ({
|
|
|
4029
4364
|
onChange: (value) => updateFilter(filter.key, value)
|
|
4030
4365
|
}
|
|
4031
4366
|
),
|
|
4032
|
-
filter.type === "toggle" && /* @__PURE__ */
|
|
4367
|
+
filter.type === "toggle" && /* @__PURE__ */ jsx56(
|
|
4033
4368
|
Toggle,
|
|
4034
4369
|
{
|
|
4035
4370
|
label: filter.label,
|
|
@@ -4037,7 +4372,7 @@ var PrimusFilterBar = ({
|
|
|
4037
4372
|
onChange: (checked) => updateFilter(filter.key, checked)
|
|
4038
4373
|
}
|
|
4039
4374
|
),
|
|
4040
|
-
filter.type === "search" && /* @__PURE__ */
|
|
4375
|
+
filter.type === "search" && /* @__PURE__ */ jsx56(
|
|
4041
4376
|
Input,
|
|
4042
4377
|
{
|
|
4043
4378
|
label: filter.label,
|
|
@@ -4053,7 +4388,7 @@ var PrimusFilterBar = ({
|
|
|
4053
4388
|
|
|
4054
4389
|
// src/components/shared/ExportMenu.tsx
|
|
4055
4390
|
import { useEffect as useEffect16, useState as useState24 } from "react";
|
|
4056
|
-
import { jsx as
|
|
4391
|
+
import { jsx as jsx57, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
4057
4392
|
var PrimusExportMenu = ({
|
|
4058
4393
|
formats = ["CSV", "PDF", "PNG", "JSON"],
|
|
4059
4394
|
includeCharts = true,
|
|
@@ -4078,29 +4413,29 @@ var PrimusExportMenu = ({
|
|
|
4078
4413
|
includeTables: tables
|
|
4079
4414
|
});
|
|
4080
4415
|
};
|
|
4081
|
-
return /* @__PURE__ */
|
|
4082
|
-
/* @__PURE__ */
|
|
4416
|
+
return /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
4417
|
+
/* @__PURE__ */ jsx57(
|
|
4083
4418
|
"select",
|
|
4084
4419
|
{
|
|
4085
4420
|
value: format,
|
|
4086
4421
|
onChange: (event) => setFormat(event.target.value),
|
|
4087
4422
|
className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm",
|
|
4088
|
-
children: formats.map((item) => /* @__PURE__ */
|
|
4423
|
+
children: formats.map((item) => /* @__PURE__ */ jsx57("option", { value: item, children: item }, item))
|
|
4089
4424
|
}
|
|
4090
4425
|
),
|
|
4091
|
-
/* @__PURE__ */
|
|
4092
|
-
/* @__PURE__ */
|
|
4426
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4427
|
+
/* @__PURE__ */ jsx57("input", { type: "checkbox", checked: charts, onChange: (e) => setCharts(e.target.checked) }),
|
|
4093
4428
|
"Charts"
|
|
4094
4429
|
] }),
|
|
4095
|
-
/* @__PURE__ */
|
|
4096
|
-
/* @__PURE__ */
|
|
4430
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4431
|
+
/* @__PURE__ */ jsx57("input", { type: "checkbox", checked: stats, onChange: (e) => setStats(e.target.checked) }),
|
|
4097
4432
|
"Stats"
|
|
4098
4433
|
] }),
|
|
4099
|
-
/* @__PURE__ */
|
|
4100
|
-
/* @__PURE__ */
|
|
4434
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4435
|
+
/* @__PURE__ */ jsx57("input", { type: "checkbox", checked: tables, onChange: (e) => setTables(e.target.checked) }),
|
|
4101
4436
|
"Tables"
|
|
4102
4437
|
] }),
|
|
4103
|
-
/* @__PURE__ */
|
|
4438
|
+
/* @__PURE__ */ jsx57(
|
|
4104
4439
|
"button",
|
|
4105
4440
|
{
|
|
4106
4441
|
type: "button",
|
|
@@ -4114,7 +4449,7 @@ var PrimusExportMenu = ({
|
|
|
4114
4449
|
|
|
4115
4450
|
// src/components/shared/Search.tsx
|
|
4116
4451
|
import { useEffect as useEffect17, useMemo as useMemo7, useState as useState25 } from "react";
|
|
4117
|
-
import { jsx as
|
|
4452
|
+
import { jsx as jsx58, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
4118
4453
|
var PrimusSearch = ({
|
|
4119
4454
|
placeholder = "Search...",
|
|
4120
4455
|
debounce = 300,
|
|
@@ -4142,8 +4477,8 @@ var PrimusSearch = ({
|
|
|
4142
4477
|
}
|
|
4143
4478
|
return suggestions.filter((item) => item.toLowerCase().includes(query.toLowerCase())).slice(0, 5);
|
|
4144
4479
|
}, [suggestions, query, showSuggestions]);
|
|
4145
|
-
return /* @__PURE__ */
|
|
4146
|
-
/* @__PURE__ */
|
|
4480
|
+
return /* @__PURE__ */ jsxs45("div", { className: "relative", children: [
|
|
4481
|
+
/* @__PURE__ */ jsx58(
|
|
4147
4482
|
"input",
|
|
4148
4483
|
{
|
|
4149
4484
|
type: "text",
|
|
@@ -4153,7 +4488,7 @@ var PrimusSearch = ({
|
|
|
4153
4488
|
className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
|
|
4154
4489
|
}
|
|
4155
4490
|
),
|
|
4156
|
-
visibleSuggestions.length > 0 && /* @__PURE__ */
|
|
4491
|
+
visibleSuggestions.length > 0 && /* @__PURE__ */ jsx58("div", { className: "absolute mt-2 w-full rounded-lg border border-white/10 bg-slate-900/90 backdrop-blur-sm shadow-lg z-10", children: visibleSuggestions.map((item) => /* @__PURE__ */ jsx58(
|
|
4157
4492
|
"button",
|
|
4158
4493
|
{
|
|
4159
4494
|
type: "button",
|
|
@@ -4165,6 +4500,304 @@ var PrimusSearch = ({
|
|
|
4165
4500
|
)) })
|
|
4166
4501
|
] });
|
|
4167
4502
|
};
|
|
4503
|
+
|
|
4504
|
+
// src/components/shared/PrimusWizard.tsx
|
|
4505
|
+
import React37, { useState as useState26 } from "react";
|
|
4506
|
+
import { Fragment as Fragment6, jsx as jsx59, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
4507
|
+
var PrimusStep = ({ children }) => {
|
|
4508
|
+
return /* @__PURE__ */ jsx59(Fragment6, { children });
|
|
4509
|
+
};
|
|
4510
|
+
var PrimusStepper = ({ steps, currentStep }) => {
|
|
4511
|
+
return /* @__PURE__ */ jsx59("nav", { "aria-label": "Progress", className: "mb-8", children: /* @__PURE__ */ jsx59("ol", { role: "list", className: "overflow-hidden rounded-md items-center flex md:border md:border-gray-200 dark:md:border-gray-800", children: steps.map((step, stepIdx) => /* @__PURE__ */ jsx59("li", { className: "relative md:flex-1 md:flex", children: stepIdx < currentStep ? /* @__PURE__ */ jsx59("div", { className: "group flex flex-1 items-center md:border-b-0 md:border-r border-gray-200 dark:border-gray-800 py-2 pl-4 md:py-3 md:pl-6 bg-white dark:bg-gray-900", children: /* @__PURE__ */ jsxs46("span", { className: "flex items-center text-sm font-medium text-purple-600 dark:text-purple-400", children: [
|
|
4512
|
+
/* @__PURE__ */ jsx59("span", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-purple-600 hover:bg-purple-800 text-white dark:bg-purple-500 dark:text-white", children: /* @__PURE__ */ jsx59("svg", { className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx59("path", { fillRule: "evenodd", d: "M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z", clipRule: "evenodd" }) }) }),
|
|
4513
|
+
/* @__PURE__ */ jsx59("span", { className: "ml-4 text-sm font-medium", children: step.label })
|
|
4514
|
+
] }) }) : stepIdx === currentStep ? /* @__PURE__ */ jsx59("div", { className: "flex flex-1 items-center md:border-b-0 md:border-r border-gray-200 dark:border-gray-800 py-2 pl-4 md:py-3 md:pl-6 bg-white dark:bg-gray-900", "aria-current": "step", children: /* @__PURE__ */ jsxs46("span", { className: "flex items-center text-sm font-medium text-purple-600 dark:text-purple-400", children: [
|
|
4515
|
+
/* @__PURE__ */ jsx59("span", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full border-2 border-purple-600 dark:border-purple-500", children: /* @__PURE__ */ jsx59("span", { className: "text-purple-600 dark:text-purple-500 font-bold", children: stepIdx + 1 }) }),
|
|
4516
|
+
/* @__PURE__ */ jsx59("span", { className: "ml-4 text-sm font-medium text-gray-900 dark:text-white", children: step.label })
|
|
4517
|
+
] }) }) : /* @__PURE__ */ jsx59("div", { className: "group flex flex-1 items-center md:border-b-0 md:border-r border-gray-200 dark:border-gray-800 py-2 pl-4 md:py-3 md:pl-6 bg-gray-50 dark:bg-gray-800/50", children: /* @__PURE__ */ jsxs46("span", { className: "flex items-center text-sm font-medium text-gray-500 dark:text-gray-400", children: [
|
|
4518
|
+
/* @__PURE__ */ jsx59("span", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full border-2 border-gray-300 dark:border-gray-700", children: /* @__PURE__ */ jsx59("span", { className: "text-gray-500 dark:text-gray-400 font-medium", children: stepIdx + 1 }) }),
|
|
4519
|
+
/* @__PURE__ */ jsx59("span", { className: "ml-4", children: step.label })
|
|
4520
|
+
] }) }) }, step.label)) }) });
|
|
4521
|
+
};
|
|
4522
|
+
var PrimusWizard = ({
|
|
4523
|
+
title,
|
|
4524
|
+
subtitle,
|
|
4525
|
+
children,
|
|
4526
|
+
onComplete,
|
|
4527
|
+
className,
|
|
4528
|
+
startStep = 0
|
|
4529
|
+
}) => {
|
|
4530
|
+
const [currentStep, setCurrentStep] = useState26(startStep);
|
|
4531
|
+
const steps = React37.Children.toArray(children).filter(
|
|
4532
|
+
(child) => React37.isValidElement(child) && (child.type === PrimusStep || child.type.name === "PrimusStep")
|
|
4533
|
+
);
|
|
4534
|
+
const totalSteps = steps.length;
|
|
4535
|
+
const isFirstStep = currentStep === 0;
|
|
4536
|
+
const isLastStep = currentStep === totalSteps - 1;
|
|
4537
|
+
const handleNext = () => {
|
|
4538
|
+
if (isLastStep) {
|
|
4539
|
+
onComplete?.();
|
|
4540
|
+
} else {
|
|
4541
|
+
setCurrentStep((prev) => prev + 1);
|
|
4542
|
+
}
|
|
4543
|
+
};
|
|
4544
|
+
const handleBack = () => {
|
|
4545
|
+
if (!isFirstStep) {
|
|
4546
|
+
setCurrentStep((prev) => prev - 1);
|
|
4547
|
+
}
|
|
4548
|
+
};
|
|
4549
|
+
if (totalSteps === 0) {
|
|
4550
|
+
return /* @__PURE__ */ jsx59("div", { className: "text-red-500", children: "Error: PrimusWizard requires PrimusStep children" });
|
|
4551
|
+
}
|
|
4552
|
+
const currentStepConfig = steps[currentStep].props;
|
|
4553
|
+
return /* @__PURE__ */ jsxs46("div", { className: `space-y-6 ${className}`, children: [
|
|
4554
|
+
/* @__PURE__ */ jsxs46("div", { children: [
|
|
4555
|
+
title && /* @__PURE__ */ jsx59("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: title }),
|
|
4556
|
+
subtitle && /* @__PURE__ */ jsx59("p", { className: "mt-1 text-gray-500 dark:text-gray-400", children: subtitle })
|
|
4557
|
+
] }),
|
|
4558
|
+
/* @__PURE__ */ jsx59(
|
|
4559
|
+
PrimusStepper,
|
|
4560
|
+
{
|
|
4561
|
+
steps: steps.map((s) => ({ label: s.props.label, description: s.props.description })),
|
|
4562
|
+
currentStep
|
|
4563
|
+
}
|
|
4564
|
+
),
|
|
4565
|
+
/* @__PURE__ */ jsxs46(Card, { className: "p-6 min-h-[300px]", children: [
|
|
4566
|
+
/* @__PURE__ */ jsx59("div", { className: "mb-8", children: steps[currentStep] }),
|
|
4567
|
+
/* @__PURE__ */ jsxs46("div", { className: "flex justify-between pt-6 border-t border-gray-100 dark:border-gray-800", children: [
|
|
4568
|
+
/* @__PURE__ */ jsx59(
|
|
4569
|
+
Button,
|
|
4570
|
+
{
|
|
4571
|
+
variant: "ghost",
|
|
4572
|
+
onClick: handleBack,
|
|
4573
|
+
disabled: isFirstStep,
|
|
4574
|
+
children: "Back"
|
|
4575
|
+
}
|
|
4576
|
+
),
|
|
4577
|
+
/* @__PURE__ */ jsx59(
|
|
4578
|
+
Button,
|
|
4579
|
+
{
|
|
4580
|
+
onClick: handleNext,
|
|
4581
|
+
disabled: currentStepConfig.isValid === false,
|
|
4582
|
+
children: isLastStep ? "Complete" : "Next"
|
|
4583
|
+
}
|
|
4584
|
+
)
|
|
4585
|
+
] })
|
|
4586
|
+
] })
|
|
4587
|
+
] });
|
|
4588
|
+
};
|
|
4589
|
+
|
|
4590
|
+
// src/components/shared/Field.tsx
|
|
4591
|
+
import React38 from "react";
|
|
4592
|
+
import { clsx as clsx8 } from "clsx";
|
|
4593
|
+
import { ExclamationCircleIcon } from "@heroicons/react/20/solid";
|
|
4594
|
+
import { jsx as jsx60, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
4595
|
+
var FieldContext = React38.createContext(void 0);
|
|
4596
|
+
var useFieldContext = () => React38.useContext(FieldContext);
|
|
4597
|
+
var Field = ({ children, error, disabled, dense, className, ...props }) => {
|
|
4598
|
+
const id = React38.useId();
|
|
4599
|
+
return /* @__PURE__ */ jsx60(FieldContext.Provider, { value: { id, error, disabled }, children: /* @__PURE__ */ jsx60(
|
|
4600
|
+
"div",
|
|
4601
|
+
{
|
|
4602
|
+
className: clsx8(
|
|
4603
|
+
"flex flex-col w-full",
|
|
4604
|
+
dense ? "gap-1" : "gap-1.5",
|
|
4605
|
+
className
|
|
4606
|
+
),
|
|
4607
|
+
...props,
|
|
4608
|
+
children
|
|
4609
|
+
}
|
|
4610
|
+
) });
|
|
4611
|
+
};
|
|
4612
|
+
var Label = ({ className, children, required, indicator, ...props }) => {
|
|
4613
|
+
const context = useFieldContext();
|
|
4614
|
+
return /* @__PURE__ */ jsxs47(
|
|
4615
|
+
"label",
|
|
4616
|
+
{
|
|
4617
|
+
htmlFor: context?.id,
|
|
4618
|
+
className: clsx8(
|
|
4619
|
+
"block text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
4620
|
+
context?.disabled ? "text-gray-400 opacity-70" : "text-gray-700",
|
|
4621
|
+
props.onClick ? "cursor-pointer" : "cursor-default",
|
|
4622
|
+
className
|
|
4623
|
+
),
|
|
4624
|
+
...props,
|
|
4625
|
+
children: [
|
|
4626
|
+
children,
|
|
4627
|
+
required && /* @__PURE__ */ jsx60("span", { className: "ml-0.5 text-red-500", children: "*" }),
|
|
4628
|
+
indicator
|
|
4629
|
+
]
|
|
4630
|
+
}
|
|
4631
|
+
);
|
|
4632
|
+
};
|
|
4633
|
+
var FieldDescription = ({ className, children, ...props }) => {
|
|
4634
|
+
const context = useFieldContext();
|
|
4635
|
+
return /* @__PURE__ */ jsx60(
|
|
4636
|
+
"p",
|
|
4637
|
+
{
|
|
4638
|
+
className: clsx8(
|
|
4639
|
+
"text-[0.8rem] text-muted-foreground text-gray-500",
|
|
4640
|
+
context?.disabled && "opacity-70",
|
|
4641
|
+
className
|
|
4642
|
+
),
|
|
4643
|
+
...props,
|
|
4644
|
+
children
|
|
4645
|
+
}
|
|
4646
|
+
);
|
|
4647
|
+
};
|
|
4648
|
+
var FieldError = ({ className, children, forceVisible, ...props }) => {
|
|
4649
|
+
const context = useFieldContext();
|
|
4650
|
+
const error = context?.error || children;
|
|
4651
|
+
if (!error && !forceVisible) return null;
|
|
4652
|
+
return /* @__PURE__ */ jsxs47(
|
|
4653
|
+
"p",
|
|
4654
|
+
{
|
|
4655
|
+
className: clsx8(
|
|
4656
|
+
"text-[0.8rem] font-medium text-red-500 flex items-center gap-1.5 animate-in slide-in-from-top-1 fade-in-50",
|
|
4657
|
+
className
|
|
4658
|
+
),
|
|
4659
|
+
...props,
|
|
4660
|
+
children: [
|
|
4661
|
+
/* @__PURE__ */ jsx60(ExclamationCircleIcon, { className: "h-4 w-4 shrink-0" }),
|
|
4662
|
+
error
|
|
4663
|
+
]
|
|
4664
|
+
}
|
|
4665
|
+
);
|
|
4666
|
+
};
|
|
4667
|
+
|
|
4668
|
+
// src/components/shared/InputGroup.tsx
|
|
4669
|
+
import React39 from "react";
|
|
4670
|
+
import { clsx as clsx9 } from "clsx";
|
|
4671
|
+
import { jsx as jsx61 } from "react/jsx-runtime";
|
|
4672
|
+
var InputGroup = ({ className, children, size = "md", ...props }) => {
|
|
4673
|
+
return /* @__PURE__ */ jsx61(
|
|
4674
|
+
"div",
|
|
4675
|
+
{
|
|
4676
|
+
className: clsx9(
|
|
4677
|
+
"flex items-stretch w-full rounded-lg shadow-sm",
|
|
4678
|
+
// Target direct children to remove borders and rounded corners where they touch
|
|
4679
|
+
"[&>*:first-child]:rounded-r-none",
|
|
4680
|
+
"[&>*:last-child]:rounded-l-none",
|
|
4681
|
+
"[&>*:not(:first-child):not(:last-child)]:rounded-none",
|
|
4682
|
+
// Handle borders to prevent double borders
|
|
4683
|
+
"[&>*:not(:first-child)]:-ml-px",
|
|
4684
|
+
// Ensure z-index handling for focus rings
|
|
4685
|
+
"[&>*:focus-within]:z-10",
|
|
4686
|
+
className
|
|
4687
|
+
),
|
|
4688
|
+
...props,
|
|
4689
|
+
children: React39.Children.map(children, (child) => {
|
|
4690
|
+
if (React39.isValidElement(child)) {
|
|
4691
|
+
return React39.cloneElement(child, { size });
|
|
4692
|
+
}
|
|
4693
|
+
return child;
|
|
4694
|
+
})
|
|
4695
|
+
}
|
|
4696
|
+
);
|
|
4697
|
+
};
|
|
4698
|
+
var InputAddon = ({ className, children, ...props }) => {
|
|
4699
|
+
return /* @__PURE__ */ jsx61(
|
|
4700
|
+
"div",
|
|
4701
|
+
{
|
|
4702
|
+
className: clsx9(
|
|
4703
|
+
"flex items-center px-3 border border-gray-200 bg-gray-50 text-gray-500 text-sm whitespace-nowrap",
|
|
4704
|
+
// These will be overridden by the group's first/last child selectors usually, but good defaults:
|
|
4705
|
+
"first:rounded-l-lg last:rounded-r-lg",
|
|
4706
|
+
className
|
|
4707
|
+
),
|
|
4708
|
+
...props,
|
|
4709
|
+
children
|
|
4710
|
+
}
|
|
4711
|
+
);
|
|
4712
|
+
};
|
|
4713
|
+
|
|
4714
|
+
// src/components/shared/PasswordInput.tsx
|
|
4715
|
+
import React40, { useState as useState27 } from "react";
|
|
4716
|
+
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/20/solid";
|
|
4717
|
+
import { jsx as jsx62, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4718
|
+
var PasswordInput = React40.forwardRef(
|
|
4719
|
+
(props, ref) => {
|
|
4720
|
+
const [showPassword, setShowPassword] = useState27(false);
|
|
4721
|
+
const toggleVisibility = () => {
|
|
4722
|
+
setShowPassword(!showPassword);
|
|
4723
|
+
};
|
|
4724
|
+
return /* @__PURE__ */ jsx62(
|
|
4725
|
+
Input,
|
|
4726
|
+
{
|
|
4727
|
+
ref,
|
|
4728
|
+
type: showPassword ? "text" : "password",
|
|
4729
|
+
endIcon: /* @__PURE__ */ jsxs48(
|
|
4730
|
+
"button",
|
|
4731
|
+
{
|
|
4732
|
+
type: "button",
|
|
4733
|
+
onClick: toggleVisibility,
|
|
4734
|
+
className: "text-gray-400 hover:text-gray-600 focus:outline-none focus:text-primus-600 transition-colors pointer-events-auto cursor-pointer p-0.5 rounded",
|
|
4735
|
+
tabIndex: -1,
|
|
4736
|
+
children: [
|
|
4737
|
+
showPassword ? /* @__PURE__ */ jsx62(EyeSlashIcon, { className: "h-4 w-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx62(EyeIcon, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
4738
|
+
/* @__PURE__ */ jsx62("span", { className: "sr-only", children: showPassword ? "Hide password" : "Show password" })
|
|
4739
|
+
]
|
|
4740
|
+
}
|
|
4741
|
+
),
|
|
4742
|
+
...props
|
|
4743
|
+
}
|
|
4744
|
+
);
|
|
4745
|
+
}
|
|
4746
|
+
);
|
|
4747
|
+
PasswordInput.displayName = "PasswordInput";
|
|
4748
|
+
|
|
4749
|
+
// src/components/shared/SearchInput.tsx
|
|
4750
|
+
import React41, { useState as useState28, useEffect as useEffect18 } from "react";
|
|
4751
|
+
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
|
|
4752
|
+
import { jsx as jsx63 } from "react/jsx-runtime";
|
|
4753
|
+
var SearchInput = React41.forwardRef(
|
|
4754
|
+
({ value, onSearch, debounceMs = 300, className, ...props }, ref) => {
|
|
4755
|
+
const [localValue, setLocalValue] = useState28(value || "");
|
|
4756
|
+
const [isDebouncing, setIsDebouncing] = useState28(false);
|
|
4757
|
+
useEffect18(() => {
|
|
4758
|
+
if (value !== void 0) {
|
|
4759
|
+
setLocalValue(value);
|
|
4760
|
+
}
|
|
4761
|
+
}, [value]);
|
|
4762
|
+
useEffect18(() => {
|
|
4763
|
+
if (debounceMs === 0) {
|
|
4764
|
+
onSearch?.(localValue);
|
|
4765
|
+
return;
|
|
4766
|
+
}
|
|
4767
|
+
const handler = setTimeout(() => {
|
|
4768
|
+
onSearch?.(localValue);
|
|
4769
|
+
setIsDebouncing(false);
|
|
4770
|
+
}, debounceMs);
|
|
4771
|
+
return () => {
|
|
4772
|
+
clearTimeout(handler);
|
|
4773
|
+
};
|
|
4774
|
+
}, [localValue, debounceMs]);
|
|
4775
|
+
const handleChange = (e) => {
|
|
4776
|
+
const newVal = e.target.value;
|
|
4777
|
+
setLocalValue(newVal);
|
|
4778
|
+
if (debounceMs > 0) setIsDebouncing(true);
|
|
4779
|
+
};
|
|
4780
|
+
const handleClear = () => {
|
|
4781
|
+
setLocalValue("");
|
|
4782
|
+
props.onClear?.();
|
|
4783
|
+
};
|
|
4784
|
+
return /* @__PURE__ */ jsx63(
|
|
4785
|
+
Input,
|
|
4786
|
+
{
|
|
4787
|
+
ref,
|
|
4788
|
+
type: "text",
|
|
4789
|
+
startIcon: /* @__PURE__ */ jsx63(MagnifyingGlassIcon, { className: "h-4 w-4" }),
|
|
4790
|
+
value: localValue,
|
|
4791
|
+
onChange: handleChange,
|
|
4792
|
+
onClear: handleClear,
|
|
4793
|
+
loading: props.loading || props.loading === void 0 && isDebouncing,
|
|
4794
|
+
className,
|
|
4795
|
+
...props
|
|
4796
|
+
}
|
|
4797
|
+
);
|
|
4798
|
+
}
|
|
4799
|
+
);
|
|
4800
|
+
SearchInput.displayName = "SearchInput";
|
|
4168
4801
|
export {
|
|
4169
4802
|
AICopilot,
|
|
4170
4803
|
AccountDashboard,
|
|
@@ -4181,17 +4814,24 @@ export {
|
|
|
4181
4814
|
DashboardGrid,
|
|
4182
4815
|
DocumentViewer,
|
|
4183
4816
|
FeatureFlagToggle,
|
|
4817
|
+
Field,
|
|
4818
|
+
FieldDescription,
|
|
4819
|
+
FieldError,
|
|
4184
4820
|
FileUploader,
|
|
4185
4821
|
FraudDetectionDashboard,
|
|
4186
4822
|
Grid,
|
|
4187
4823
|
Input,
|
|
4824
|
+
InputAddon,
|
|
4825
|
+
InputGroup,
|
|
4188
4826
|
KYCVerification,
|
|
4827
|
+
Label,
|
|
4189
4828
|
LoanCalculator,
|
|
4190
4829
|
LogViewer,
|
|
4191
4830
|
LoginPage,
|
|
4192
4831
|
Modal,
|
|
4193
4832
|
NotificationBell,
|
|
4194
4833
|
PrimusNotificationFeed as NotificationFeed,
|
|
4834
|
+
PasswordInput,
|
|
4195
4835
|
PolicyCard,
|
|
4196
4836
|
PremiumCalculator,
|
|
4197
4837
|
PrimusActivityFeed,
|
|
@@ -4207,10 +4847,16 @@ export {
|
|
|
4207
4847
|
PrimusDataTable,
|
|
4208
4848
|
PrimusDateRangePicker,
|
|
4209
4849
|
PrimusExportMenu,
|
|
4850
|
+
Field as PrimusField,
|
|
4851
|
+
FieldDescription as PrimusFieldDescription,
|
|
4852
|
+
FieldError as PrimusFieldError,
|
|
4210
4853
|
PrimusFilterBar,
|
|
4211
4854
|
Grid as PrimusGrid,
|
|
4212
4855
|
PrimusHeader,
|
|
4213
4856
|
Input as PrimusInput,
|
|
4857
|
+
InputAddon as PrimusInputAddon,
|
|
4858
|
+
InputGroup as PrimusInputGroup,
|
|
4859
|
+
Label as PrimusLabel,
|
|
4214
4860
|
PrimusLayout,
|
|
4215
4861
|
PrimusLineChart,
|
|
4216
4862
|
PrimusLogin,
|
|
@@ -4219,22 +4865,31 @@ export {
|
|
|
4219
4865
|
PrimusNotificationCenter,
|
|
4220
4866
|
PrimusNotificationFeed,
|
|
4221
4867
|
PrimusNotifications,
|
|
4868
|
+
PasswordInput as PrimusPasswordInput,
|
|
4222
4869
|
PrimusPieChart,
|
|
4223
4870
|
PrimusProvider,
|
|
4224
4871
|
RadioGroup as PrimusRadioGroup,
|
|
4225
4872
|
PrimusSearch,
|
|
4873
|
+
SearchInput as PrimusSearchInput,
|
|
4874
|
+
PrimusSection,
|
|
4226
4875
|
Select as PrimusSelect,
|
|
4227
4876
|
PrimusSidebar,
|
|
4228
4877
|
PrimusSparkline,
|
|
4229
4878
|
Stack as PrimusStack,
|
|
4230
4879
|
PrimusStatCard,
|
|
4880
|
+
PrimusStatCard as PrimusStatsCard,
|
|
4881
|
+
PrimusStep,
|
|
4882
|
+
PrimusStepper,
|
|
4883
|
+
PrimusSummaryCard,
|
|
4231
4884
|
Table as PrimusTable,
|
|
4232
4885
|
Textarea as PrimusTextarea,
|
|
4233
4886
|
PrimusThemeProvider,
|
|
4234
4887
|
PrimusThemeToggle,
|
|
4235
4888
|
Toggle as PrimusToggle,
|
|
4889
|
+
PrimusWizard,
|
|
4236
4890
|
QuoteComparison,
|
|
4237
4891
|
RadioGroup,
|
|
4892
|
+
SearchInput,
|
|
4238
4893
|
SecurityDashboard,
|
|
4239
4894
|
Select,
|
|
4240
4895
|
Stack,
|
|
@@ -4246,6 +4901,7 @@ export {
|
|
|
4246
4901
|
themeColors,
|
|
4247
4902
|
useNotifications,
|
|
4248
4903
|
usePrimusAuth,
|
|
4904
|
+
usePrimusFetch,
|
|
4249
4905
|
usePrimusTheme,
|
|
4250
4906
|
useRealtimeNotifications
|
|
4251
4907
|
};
|