primus-react-ui 1.0.14 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -30
- package/dist/index.d.mts +229 -115
- package/dist/index.d.ts +229 -115
- package/dist/index.js +1294 -611
- package/dist/index.mjs +1194 -534
- package/package.json +1 -1
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,304 @@ 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: 600,
|
|
1124
|
+
marginBottom: "6px",
|
|
1125
|
+
textTransform: "uppercase",
|
|
1126
|
+
letterSpacing: "0.5px"
|
|
1127
|
+
},
|
|
1128
|
+
input: {
|
|
1129
|
+
width: "100%",
|
|
1130
|
+
border: "1px solid #cbd5e1",
|
|
1131
|
+
borderRadius: "8px",
|
|
1132
|
+
padding: "10px 12px",
|
|
1133
|
+
background: "#ffffff",
|
|
1134
|
+
color: "#0f172a",
|
|
1135
|
+
fontSize: "14px",
|
|
1136
|
+
outline: "none"
|
|
1137
|
+
},
|
|
1138
|
+
submitBtn: {
|
|
1139
|
+
marginTop: "8px",
|
|
1140
|
+
background: "#0f172a",
|
|
1141
|
+
// Slate-900
|
|
1142
|
+
color: "#ffffff",
|
|
1143
|
+
border: "none",
|
|
1144
|
+
borderRadius: "8px",
|
|
1145
|
+
padding: "12px",
|
|
1146
|
+
cursor: "pointer",
|
|
1147
|
+
fontWeight: 600,
|
|
1148
|
+
fontSize: "14px",
|
|
1149
|
+
width: "100%"
|
|
1150
|
+
},
|
|
1151
|
+
error: {
|
|
1152
|
+
marginTop: "12px",
|
|
1153
|
+
color: "#dc2626",
|
|
1154
|
+
fontSize: "12px",
|
|
1155
|
+
textAlign: "center"
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
var darkStyles = {
|
|
1159
|
+
container: { backgroundColor: "#0f172a", color: "#f8fafc" },
|
|
1160
|
+
card: { backgroundColor: "#1e293b", borderColor: "#334155", boxShadow: "none" },
|
|
1161
|
+
subtitle: { color: "#94a3b8" },
|
|
1162
|
+
socialBtn: { backgroundColor: "#1e293b", borderColor: "#334155", color: "#f8fafc" },
|
|
1163
|
+
label: { color: "#94a3b8" },
|
|
1164
|
+
input: { backgroundColor: "#0f172a", borderColor: "#334155", color: "#f8fafc" },
|
|
1165
|
+
submitBtn: { backgroundColor: "#8b5cf6" }
|
|
1166
|
+
// Violet for dark mode
|
|
1167
|
+
};
|
|
1168
|
+
var Icons = {
|
|
1169
|
+
google: /* @__PURE__ */ jsxs12("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
|
|
1170
|
+
/* @__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" }),
|
|
1171
|
+
/* @__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" }),
|
|
1172
|
+
/* @__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" }),
|
|
1173
|
+
/* @__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" })
|
|
1174
|
+
] }),
|
|
1175
|
+
microsoft: /* @__PURE__ */ jsxs12("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
|
|
1176
|
+
/* @__PURE__ */ jsx14("path", { d: "M0 0h8.571v8.571H0V0z", fill: "#F25022" }),
|
|
1177
|
+
/* @__PURE__ */ jsx14("path", { d: "M9.429 0H18v8.571H9.429V0z", fill: "#7FBA00" }),
|
|
1178
|
+
/* @__PURE__ */ jsx14("path", { d: "M0 9.429h8.571V18H0V9.429z", fill: "#00A4EF" }),
|
|
1179
|
+
/* @__PURE__ */ jsx14("path", { d: "M9.429 9.429H18V18H9.429V9.429z", fill: "#FFB900" })
|
|
1180
|
+
] }),
|
|
1181
|
+
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" }) }),
|
|
1182
|
+
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" }) }),
|
|
1183
|
+
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" }) }),
|
|
1184
|
+
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" }) })
|
|
1185
|
+
};
|
|
1186
|
+
function PrimusLogin({
|
|
1187
|
+
onLogin,
|
|
1188
|
+
socialProviders = [],
|
|
1189
|
+
onSocialLogin,
|
|
1190
|
+
authEndpoint = "/api/auth",
|
|
1191
|
+
showEmailLogin = true,
|
|
1192
|
+
title = "Welcome Back",
|
|
1193
|
+
subtitle = "Enter your credentials to continue",
|
|
1194
|
+
logo,
|
|
1195
|
+
theme: themeOverride,
|
|
1196
|
+
variant = "standalone",
|
|
1197
|
+
useAuth = false
|
|
1198
|
+
}) {
|
|
1199
|
+
const themeContext = usePrimusTheme();
|
|
1200
|
+
const auth = usePrimusAuth();
|
|
1201
|
+
const theme = themeOverride || themeContext.theme;
|
|
1202
|
+
const isLight = theme === "light";
|
|
1203
|
+
const isDark = !isLight;
|
|
1204
|
+
const [username, setUsername] = useState14("");
|
|
1205
|
+
const [password, setPassword] = useState14("");
|
|
1206
|
+
const [loading, setLoading] = useState14(false);
|
|
1207
|
+
const [errorMessage, setErrorMessage] = useState14("");
|
|
1208
|
+
const currentStyles = {
|
|
1209
|
+
container: { ...styles.container, ...isDark ? darkStyles.container : {} },
|
|
1210
|
+
card: { ...styles.card, ...isDark ? darkStyles.card : {} },
|
|
1211
|
+
title: { ...styles.title, color: isLight ? "#0f172a" : "#f8fafc" },
|
|
1212
|
+
subtitle: { ...styles.subtitle, ...isDark ? darkStyles.subtitle : {} },
|
|
1213
|
+
input: { ...styles.input, ...isDark ? darkStyles.input : {} },
|
|
1214
|
+
socialBtn: { ...styles.socialBtn, ...isDark ? darkStyles.socialBtn : {} },
|
|
1215
|
+
label: { ...styles.label, ...isDark ? darkStyles.label : {} },
|
|
1216
|
+
submitBtn: { ...styles.submitBtn, ...isDark ? darkStyles.submitBtn : {} }
|
|
1217
|
+
};
|
|
1218
|
+
const handleSubmit = async (e) => {
|
|
1219
|
+
e.preventDefault();
|
|
1220
|
+
if (!username || !password) return;
|
|
1221
|
+
setLoading(true);
|
|
1222
|
+
setErrorMessage("");
|
|
1223
|
+
try {
|
|
1224
|
+
if (useAuth) {
|
|
1225
|
+
const result = await auth.login({ email: username, password });
|
|
1226
|
+
if (!result.success) {
|
|
1227
|
+
setErrorMessage(result.error || "Login failed");
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
onLogin?.({ username, password });
|
|
1232
|
+
} catch (err) {
|
|
1233
|
+
setErrorMessage("Login failed. Please try again.");
|
|
1234
|
+
} finally {
|
|
1235
|
+
setLoading(false);
|
|
1236
|
+
}
|
|
1237
|
+
};
|
|
1238
|
+
const handleSocialClick = (provider) => {
|
|
1239
|
+
if (onSocialLogin) {
|
|
1240
|
+
onSocialLogin(provider);
|
|
1241
|
+
} else {
|
|
1242
|
+
const base = authEndpoint.replace(/\/+$/, "");
|
|
1243
|
+
window.location.href = `${base}/${provider}`;
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
const renderSocialIcon = (p) => {
|
|
1247
|
+
const key = p === "azure" ? "microsoft" : p;
|
|
1248
|
+
return Icons[key] || null;
|
|
1249
|
+
};
|
|
1250
|
+
const content = /* @__PURE__ */ jsxs12("div", { style: currentStyles.card, className: "primus-login-card", children: [
|
|
1251
|
+
/* @__PURE__ */ jsxs12("div", { style: styles.header, className: "primus-login-header", children: [
|
|
1252
|
+
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 })),
|
|
1253
|
+
/* @__PURE__ */ jsx14("h2", { style: currentStyles.title, children: title }),
|
|
1254
|
+
/* @__PURE__ */ jsx14("p", { style: currentStyles.subtitle, children: subtitle })
|
|
1255
|
+
] }),
|
|
1256
|
+
socialProviders.length > 0 && /* @__PURE__ */ jsx14("div", { style: styles.socialGrid, className: "primus-social", children: socialProviders.map((provider) => /* @__PURE__ */ jsxs12(
|
|
1257
|
+
"button",
|
|
1258
|
+
{
|
|
1259
|
+
type: "button",
|
|
1260
|
+
onClick: () => handleSocialClick(provider),
|
|
1261
|
+
style: currentStyles.socialBtn,
|
|
1262
|
+
onMouseOver: (e) => {
|
|
1263
|
+
if (isLight) e.currentTarget.style.backgroundColor = "#f1f5f9";
|
|
1264
|
+
else e.currentTarget.style.backgroundColor = "#334155";
|
|
1265
|
+
},
|
|
1266
|
+
onMouseOut: (e) => {
|
|
1267
|
+
if (isLight) e.currentTarget.style.backgroundColor = "#ffffff";
|
|
1268
|
+
else e.currentTarget.style.backgroundColor = "#1e293b";
|
|
1269
|
+
},
|
|
1270
|
+
children: [
|
|
1271
|
+
renderSocialIcon(provider),
|
|
1272
|
+
"Continue with ",
|
|
1273
|
+
provider === "azure" ? "Microsoft" : provider.charAt(0).toUpperCase() + provider.slice(1)
|
|
1274
|
+
]
|
|
1275
|
+
},
|
|
1276
|
+
provider
|
|
1277
|
+
)) }),
|
|
1278
|
+
socialProviders.length > 0 && showEmailLogin && /* @__PURE__ */ jsxs12("div", { style: styles.divider, className: "primus-divider", children: [
|
|
1279
|
+
/* @__PURE__ */ jsx14("span", { style: { backgroundColor: isLight ? "#fff" : "#1e293b", padding: "0 8px", position: "relative", zIndex: 1 }, children: "Or continue with email" }),
|
|
1280
|
+
/* @__PURE__ */ jsx14("div", { style: { position: "absolute", top: "50%", left: 0, right: 0, borderTop: isLight ? "1px solid #e2e8f0" : "1px solid #334155", zIndex: 0 } })
|
|
1281
|
+
] }),
|
|
1282
|
+
showEmailLogin && /* @__PURE__ */ jsxs12("form", { onSubmit: handleSubmit, style: styles.form, className: "primus-form", children: [
|
|
1283
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
1284
|
+
/* @__PURE__ */ jsx14("label", { style: currentStyles.label, children: "Email" }),
|
|
1285
|
+
/* @__PURE__ */ jsx14(
|
|
1286
|
+
"input",
|
|
1287
|
+
{
|
|
1288
|
+
type: "text",
|
|
1289
|
+
value: username,
|
|
1290
|
+
onChange: (e) => setUsername(e.target.value),
|
|
1291
|
+
style: currentStyles.input,
|
|
1292
|
+
placeholder: "you@example.com"
|
|
1293
|
+
}
|
|
1294
|
+
)
|
|
1295
|
+
] }),
|
|
1296
|
+
/* @__PURE__ */ jsxs12("div", { children: [
|
|
1297
|
+
/* @__PURE__ */ jsx14("label", { style: currentStyles.label, children: "Password" }),
|
|
1298
|
+
/* @__PURE__ */ jsx14(
|
|
1299
|
+
"input",
|
|
1300
|
+
{
|
|
1301
|
+
type: "password",
|
|
1302
|
+
value: password,
|
|
1303
|
+
onChange: (e) => setPassword(e.target.value),
|
|
1304
|
+
style: currentStyles.input,
|
|
1305
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
1306
|
+
}
|
|
1307
|
+
)
|
|
1308
|
+
] }),
|
|
1309
|
+
/* @__PURE__ */ jsx14(
|
|
1310
|
+
"button",
|
|
1311
|
+
{
|
|
1312
|
+
type: "submit",
|
|
1313
|
+
disabled: loading,
|
|
1314
|
+
style: { ...currentStyles.submitBtn, opacity: loading ? 0.7 : 1 },
|
|
1315
|
+
children: loading ? "Signing in..." : "Sign In"
|
|
1316
|
+
}
|
|
1317
|
+
)
|
|
1318
|
+
] }),
|
|
1319
|
+
errorMessage && /* @__PURE__ */ jsx14("p", { style: styles.error, children: errorMessage })
|
|
1320
|
+
] });
|
|
1321
|
+
if (variant === "embedded") {
|
|
1322
|
+
return content;
|
|
1323
|
+
}
|
|
1324
|
+
return /* @__PURE__ */ jsx14("div", { style: { ...currentStyles.container, background: isLight ? "#f8fafc" : "#0f172a" }, className: `primus-login ${isDark ? "dark" : ""}`, children: content });
|
|
1325
|
+
}
|
|
1326
|
+
var LoginPage = PrimusLogin;
|
|
1327
|
+
|
|
1115
1328
|
// src/components/shared/Button.tsx
|
|
1116
|
-
import
|
|
1329
|
+
import React14 from "react";
|
|
1117
1330
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1118
|
-
var Button =
|
|
1331
|
+
var Button = React14.forwardRef(
|
|
1119
1332
|
({ style, variant = "primary", size = "md", color = "sapphire", disabled, ...props }, ref) => {
|
|
1120
|
-
const [isHovered, setIsHovered] =
|
|
1333
|
+
const [isHovered, setIsHovered] = React14.useState(false);
|
|
1121
1334
|
const colorStyles = {
|
|
1122
1335
|
sapphire: {
|
|
1123
1336
|
solid: "#1341a7",
|
|
@@ -1256,6 +1469,51 @@ var UserProfile = ({
|
|
|
1256
1469
|
] });
|
|
1257
1470
|
};
|
|
1258
1471
|
|
|
1472
|
+
// src/hooks/usePrimusFetch.ts
|
|
1473
|
+
import { useCallback as useCallback3 } from "react";
|
|
1474
|
+
function usePrimusFetch() {
|
|
1475
|
+
const { logout, csrfCookieName = "XSRF-TOKEN", csrfHeaderName = "X-Primus-CSRF" } = usePrimusAuth();
|
|
1476
|
+
const getCookie = useCallback3((name) => {
|
|
1477
|
+
if (typeof document === "undefined") return null;
|
|
1478
|
+
try {
|
|
1479
|
+
const matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") + "=([^;]*)"));
|
|
1480
|
+
return matches ? decodeURIComponent(matches[1]) : null;
|
|
1481
|
+
} catch {
|
|
1482
|
+
return null;
|
|
1483
|
+
}
|
|
1484
|
+
}, []);
|
|
1485
|
+
const primusFetch = useCallback3(async (input, init) => {
|
|
1486
|
+
const { skipAuth, ...fetchInit } = init || {};
|
|
1487
|
+
const config = {
|
|
1488
|
+
...fetchInit,
|
|
1489
|
+
headers: new Headers(fetchInit.headers)
|
|
1490
|
+
};
|
|
1491
|
+
if (!skipAuth) {
|
|
1492
|
+
config.credentials = "include";
|
|
1493
|
+
}
|
|
1494
|
+
const method = (config.method || "GET").toUpperCase();
|
|
1495
|
+
if (!["GET", "HEAD", "OPTIONS"].includes(method)) {
|
|
1496
|
+
const csrfToken = getCookie(csrfCookieName);
|
|
1497
|
+
if (csrfToken) {
|
|
1498
|
+
config.headers.set(csrfHeaderName, csrfToken);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
try {
|
|
1502
|
+
const response = await window.fetch(input, config);
|
|
1503
|
+
if (response.status === 401 && !skipAuth) {
|
|
1504
|
+
console.debug("[PrimusFetch] 401 Unauthorized detected. triggering logout.");
|
|
1505
|
+
logout();
|
|
1506
|
+
}
|
|
1507
|
+
return response;
|
|
1508
|
+
} catch (error) {
|
|
1509
|
+
throw error;
|
|
1510
|
+
}
|
|
1511
|
+
}, [getCookie, logout, csrfCookieName, csrfHeaderName]);
|
|
1512
|
+
return {
|
|
1513
|
+
fetch: primusFetch
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1259
1517
|
// src/hooks/useNotifications.ts
|
|
1260
1518
|
import { useState as useState15, useEffect as useEffect9, useMemo } from "react";
|
|
1261
1519
|
var useNotifications = ({
|
|
@@ -1399,7 +1657,7 @@ var PrimusNotificationFeed = ({ useMock, mockData, apiUrl, className }) => {
|
|
|
1399
1657
|
};
|
|
1400
1658
|
|
|
1401
1659
|
// src/components/notifications/PrimusNotificationCenter.tsx
|
|
1402
|
-
import { useState as useState16, useEffect as useEffect10, useCallback as
|
|
1660
|
+
import { useState as useState16, useEffect as useEffect10, useCallback as useCallback4 } from "react";
|
|
1403
1661
|
import { Bell, Send, X, Check, AlertTriangle, Info, AlertCircle } from "lucide-react";
|
|
1404
1662
|
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1405
1663
|
var API_URL = "http://localhost:5222";
|
|
@@ -1421,7 +1679,7 @@ function PrimusNotificationCenter({
|
|
|
1421
1679
|
const [newMessage, setNewMessage] = useState16("");
|
|
1422
1680
|
const [newType, setNewType] = useState16("info");
|
|
1423
1681
|
const [sending, setSending] = useState16(false);
|
|
1424
|
-
const fetchNotifications =
|
|
1682
|
+
const fetchNotifications = useCallback4(async () => {
|
|
1425
1683
|
try {
|
|
1426
1684
|
const response = await fetch(`${apiUrl}/api/notifications`);
|
|
1427
1685
|
if (response.ok) {
|
|
@@ -1645,7 +1903,7 @@ var NotificationBell = PrimusNotificationCenter;
|
|
|
1645
1903
|
var PrimusNotifications = PrimusNotificationCenter;
|
|
1646
1904
|
|
|
1647
1905
|
// src/hooks/useRealtimeNotifications.ts
|
|
1648
|
-
import { useState as useState17, useEffect as useEffect11, useCallback as
|
|
1906
|
+
import { useState as useState17, useEffect as useEffect11, useCallback as useCallback5 } from "react";
|
|
1649
1907
|
var useRealtimeNotifications = (options) => {
|
|
1650
1908
|
const { apiUrl, pollInterval = 3e3, userId } = options;
|
|
1651
1909
|
const [notifications, setNotifications] = useState17([]);
|
|
@@ -1653,7 +1911,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1653
1911
|
const [loading, setLoading] = useState17(true);
|
|
1654
1912
|
const [error, setError] = useState17(null);
|
|
1655
1913
|
const baseUrl = `${apiUrl}/api/notifications`;
|
|
1656
|
-
const fetchNotifications =
|
|
1914
|
+
const fetchNotifications = useCallback5(async () => {
|
|
1657
1915
|
try {
|
|
1658
1916
|
const url = userId ? `${baseUrl}?userId=${userId}` : baseUrl;
|
|
1659
1917
|
const response = await fetch(url);
|
|
@@ -1669,7 +1927,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1669
1927
|
setLoading(false);
|
|
1670
1928
|
}
|
|
1671
1929
|
}, [baseUrl, userId]);
|
|
1672
|
-
const sendNotification =
|
|
1930
|
+
const sendNotification = useCallback5(async (title, message, type = "info") => {
|
|
1673
1931
|
try {
|
|
1674
1932
|
const response = await fetch(baseUrl, {
|
|
1675
1933
|
method: "POST",
|
|
@@ -1685,7 +1943,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1685
1943
|
return false;
|
|
1686
1944
|
}
|
|
1687
1945
|
}, [baseUrl, userId, fetchNotifications]);
|
|
1688
|
-
const markAsRead =
|
|
1946
|
+
const markAsRead = useCallback5(async (id) => {
|
|
1689
1947
|
try {
|
|
1690
1948
|
await fetch(`${baseUrl}/${id}/read`, { method: "PUT" });
|
|
1691
1949
|
setNotifications((prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n));
|
|
@@ -1693,13 +1951,13 @@ var useRealtimeNotifications = (options) => {
|
|
|
1693
1951
|
} catch {
|
|
1694
1952
|
}
|
|
1695
1953
|
}, [baseUrl]);
|
|
1696
|
-
const markAllAsRead =
|
|
1954
|
+
const markAllAsRead = useCallback5(async () => {
|
|
1697
1955
|
const unread = notifications.filter((n) => !n.read);
|
|
1698
1956
|
await Promise.all(unread.map((n) => fetch(`${baseUrl}/${n.id}/read`, { method: "PUT" })));
|
|
1699
1957
|
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
|
1700
1958
|
setUnreadCount(0);
|
|
1701
1959
|
}, [notifications, baseUrl]);
|
|
1702
|
-
const deleteNotification =
|
|
1960
|
+
const deleteNotification = useCallback5(async (id) => {
|
|
1703
1961
|
try {
|
|
1704
1962
|
await fetch(`${baseUrl}/${id}`, { method: "DELETE" });
|
|
1705
1963
|
setNotifications((prev) => prev.filter((n) => n.id !== id));
|
|
@@ -1728,7 +1986,7 @@ var useRealtimeNotifications = (options) => {
|
|
|
1728
1986
|
import { useState as useState18 } from "react";
|
|
1729
1987
|
|
|
1730
1988
|
// src/components/shared/Input.tsx
|
|
1731
|
-
import
|
|
1989
|
+
import React15 from "react";
|
|
1732
1990
|
import { clsx as clsx2 } from "clsx";
|
|
1733
1991
|
import { XMarkIcon } from "@heroicons/react/20/solid";
|
|
1734
1992
|
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -1742,20 +2000,48 @@ var iconSizeClasses = {
|
|
|
1742
2000
|
md: "w-5 h-5 [&>*]:w-full [&>*]:h-full",
|
|
1743
2001
|
lg: "w-6 h-6 [&>*]:w-full [&>*]:h-full"
|
|
1744
2002
|
};
|
|
1745
|
-
var Input =
|
|
1746
|
-
({
|
|
2003
|
+
var Input = React15.forwardRef(
|
|
2004
|
+
({
|
|
2005
|
+
className,
|
|
2006
|
+
style,
|
|
2007
|
+
label,
|
|
2008
|
+
error,
|
|
2009
|
+
disabled,
|
|
2010
|
+
startIcon,
|
|
2011
|
+
endIcon,
|
|
2012
|
+
onClear,
|
|
2013
|
+
value,
|
|
2014
|
+
onChange,
|
|
2015
|
+
onValueChange,
|
|
2016
|
+
size = "md",
|
|
2017
|
+
loading = false,
|
|
2018
|
+
autoSelect = false,
|
|
2019
|
+
onFocus,
|
|
2020
|
+
...props
|
|
2021
|
+
}, ref) => {
|
|
2022
|
+
const handleFocus = (e) => {
|
|
2023
|
+
if (autoSelect) {
|
|
2024
|
+
e.target.select();
|
|
2025
|
+
}
|
|
2026
|
+
onFocus?.(e);
|
|
2027
|
+
};
|
|
2028
|
+
const handleChange = (e) => {
|
|
2029
|
+
onChange?.(e);
|
|
2030
|
+
onValueChange?.(e.target.value);
|
|
2031
|
+
};
|
|
1747
2032
|
const hasValue = value !== void 0 && value !== "" && value !== null;
|
|
2033
|
+
const isDisabled = disabled || loading;
|
|
1748
2034
|
return /* @__PURE__ */ jsxs16("div", { className: clsx2("w-full", className), style, children: [
|
|
1749
2035
|
label && /* @__PURE__ */ jsx19("label", { className: clsx2(
|
|
1750
2036
|
"block font-medium mb-1.5",
|
|
1751
2037
|
size === "sm" ? "text-xs" : "text-sm",
|
|
1752
|
-
|
|
2038
|
+
isDisabled ? "text-gray-400 opacity-70" : "text-gray-700"
|
|
1753
2039
|
), children: label }),
|
|
1754
2040
|
/* @__PURE__ */ jsxs16("div", { className: clsx2(
|
|
1755
2041
|
"relative flex items-center w-full rounded-lg transition-all duration-200 ease-in-out bg-white overflow-hidden",
|
|
1756
2042
|
"border",
|
|
1757
2043
|
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
|
-
|
|
2044
|
+
isDisabled && "bg-gray-50 opacity-60 cursor-not-allowed"
|
|
1759
2045
|
), children: [
|
|
1760
2046
|
startIcon && /* @__PURE__ */ jsx19("div", { className: clsx2(
|
|
1761
2047
|
"flex-shrink-0 pl-3 pr-2 text-gray-400 select-none pointer-events-none flex items-center justify-center",
|
|
@@ -1765,9 +2051,10 @@ var Input = React14.forwardRef(
|
|
|
1765
2051
|
"input",
|
|
1766
2052
|
{
|
|
1767
2053
|
ref,
|
|
1768
|
-
disabled,
|
|
2054
|
+
disabled: isDisabled,
|
|
1769
2055
|
value,
|
|
1770
|
-
onChange,
|
|
2056
|
+
onChange: handleChange,
|
|
2057
|
+
onFocus: handleFocus,
|
|
1771
2058
|
className: clsx2(
|
|
1772
2059
|
"flex-1 w-full border-none bg-transparent p-0 placeholder:text-gray-400 focus:ring-0 outline-none",
|
|
1773
2060
|
sizeClasses[size],
|
|
@@ -1778,7 +2065,7 @@ var Input = React14.forwardRef(
|
|
|
1778
2065
|
...props
|
|
1779
2066
|
}
|
|
1780
2067
|
),
|
|
1781
|
-
onClear && hasValue && !
|
|
2068
|
+
onClear && hasValue && !isDisabled && /* @__PURE__ */ jsx19("div", { className: "flex-shrink-0 pr-2 flex items-center justify-center", children: /* @__PURE__ */ jsx19(
|
|
1782
2069
|
"button",
|
|
1783
2070
|
{
|
|
1784
2071
|
type: "button",
|
|
@@ -1786,7 +2073,8 @@ var Input = React14.forwardRef(
|
|
|
1786
2073
|
e.stopPropagation();
|
|
1787
2074
|
onClear();
|
|
1788
2075
|
},
|
|
1789
|
-
className: "p-1 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors",
|
|
2076
|
+
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",
|
|
2077
|
+
tabIndex: 0,
|
|
1790
2078
|
children: /* @__PURE__ */ jsx19(XMarkIcon, { className: "h-4 w-4" })
|
|
1791
2079
|
}
|
|
1792
2080
|
) }),
|
|
@@ -2394,7 +2682,7 @@ var PrimusSidebar = ({
|
|
|
2394
2682
|
};
|
|
2395
2683
|
|
|
2396
2684
|
// src/components/layout/PrimusHeader.tsx
|
|
2397
|
-
import
|
|
2685
|
+
import React19 from "react";
|
|
2398
2686
|
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2399
2687
|
var PrimusHeader = ({
|
|
2400
2688
|
title,
|
|
@@ -2405,7 +2693,7 @@ var PrimusHeader = ({
|
|
|
2405
2693
|
}) => {
|
|
2406
2694
|
return /* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between w-full", children: [
|
|
2407
2695
|
/* @__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(
|
|
2696
|
+
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
2697
|
index > 0 && /* @__PURE__ */ jsx30("span", { className: "text-gray-500", children: "/" }),
|
|
2410
2698
|
/* @__PURE__ */ jsx30("span", { className: index === breadcrumbs.length - 1 ? "text-white" : "text-gray-400 hover:text-white cursor-pointer", children: crumb.label })
|
|
2411
2699
|
] }, index)) }),
|
|
@@ -2431,9 +2719,30 @@ var PrimusHeader = ({
|
|
|
2431
2719
|
] });
|
|
2432
2720
|
};
|
|
2433
2721
|
|
|
2722
|
+
// src/components/layout/PrimusSection.tsx
|
|
2723
|
+
import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2724
|
+
var PrimusSection = ({
|
|
2725
|
+
title,
|
|
2726
|
+
subtitle,
|
|
2727
|
+
children,
|
|
2728
|
+
className = "",
|
|
2729
|
+
actions
|
|
2730
|
+
}) => {
|
|
2731
|
+
return /* @__PURE__ */ jsxs28("section", { className: `py-6 ${className}`, children: [
|
|
2732
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-end justify-between mb-6 border-b border-gray-200 dark:border-gray-800 pb-4", children: [
|
|
2733
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
2734
|
+
/* @__PURE__ */ jsx31("h2", { className: "text-2xl font-bold tracking-tight text-gray-900 dark:text-white", children: title }),
|
|
2735
|
+
subtitle && /* @__PURE__ */ jsx31("p", { className: "mt-1 text-base text-gray-500 dark:text-gray-400", children: subtitle })
|
|
2736
|
+
] }),
|
|
2737
|
+
actions && /* @__PURE__ */ jsx31("div", { className: "flex items-center gap-2", children: actions })
|
|
2738
|
+
] }),
|
|
2739
|
+
/* @__PURE__ */ jsx31("div", { children })
|
|
2740
|
+
] });
|
|
2741
|
+
};
|
|
2742
|
+
|
|
2434
2743
|
// src/components/crud/PrimusDataTable.tsx
|
|
2435
2744
|
import { useState as useState21, useMemo as useMemo2 } from "react";
|
|
2436
|
-
import { jsx as
|
|
2745
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2437
2746
|
function PrimusDataTable({
|
|
2438
2747
|
data,
|
|
2439
2748
|
columns,
|
|
@@ -2512,10 +2821,10 @@ function PrimusDataTable({
|
|
|
2512
2821
|
onSelectionChange?.(scopeKeys);
|
|
2513
2822
|
}
|
|
2514
2823
|
};
|
|
2515
|
-
return /* @__PURE__ */
|
|
2516
|
-
searchable && /* @__PURE__ */
|
|
2517
|
-
/* @__PURE__ */
|
|
2518
|
-
/* @__PURE__ */
|
|
2824
|
+
return /* @__PURE__ */ jsxs29("div", { className: "flex flex-col space-y-4", children: [
|
|
2825
|
+
searchable && /* @__PURE__ */ jsx32("div", { className: "flex items-center justify-between px-1", children: /* @__PURE__ */ jsxs29("div", { className: "relative group", children: [
|
|
2826
|
+
/* @__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" }) }) }),
|
|
2827
|
+
/* @__PURE__ */ jsx32(
|
|
2519
2828
|
"input",
|
|
2520
2829
|
{
|
|
2521
2830
|
type: "text",
|
|
@@ -2531,9 +2840,9 @@ function PrimusDataTable({
|
|
|
2531
2840
|
}
|
|
2532
2841
|
)
|
|
2533
2842
|
] }) }),
|
|
2534
|
-
/* @__PURE__ */
|
|
2535
|
-
/* @__PURE__ */
|
|
2536
|
-
selectable && /* @__PURE__ */
|
|
2843
|
+
/* @__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: [
|
|
2844
|
+
/* @__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: [
|
|
2845
|
+
selectable && /* @__PURE__ */ jsx32("th", { className: "w-12 px-6 py-4", children: /* @__PURE__ */ jsx32(
|
|
2537
2846
|
"input",
|
|
2538
2847
|
{
|
|
2539
2848
|
type: "checkbox",
|
|
@@ -2542,25 +2851,25 @@ function PrimusDataTable({
|
|
|
2542
2851
|
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
2852
|
}
|
|
2544
2853
|
) }),
|
|
2545
|
-
columns.map((col) => /* @__PURE__ */
|
|
2854
|
+
columns.map((col) => /* @__PURE__ */ jsx32(
|
|
2546
2855
|
"th",
|
|
2547
2856
|
{
|
|
2548
2857
|
className: `px-6 py-4 text-xs font-semibold text-gray-400 uppercase tracking-wider ${col.sortable ? "cursor-pointer hover:text-white group" : ""}`,
|
|
2549
2858
|
style: { width: col.width },
|
|
2550
2859
|
onClick: () => col.sortable && handleSort(String(col.key)),
|
|
2551
|
-
children: /* @__PURE__ */
|
|
2860
|
+
children: /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-2", children: [
|
|
2552
2861
|
col.header,
|
|
2553
|
-
col.sortable && /* @__PURE__ */
|
|
2862
|
+
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
2863
|
] })
|
|
2555
2864
|
},
|
|
2556
2865
|
String(col.key)
|
|
2557
2866
|
)),
|
|
2558
|
-
actions && /* @__PURE__ */
|
|
2867
|
+
actions && /* @__PURE__ */ jsx32("th", { className: "w-24 px-6 py-4 text-right text-xs font-semibold text-gray-400 uppercase tracking-wider" })
|
|
2559
2868
|
] }) }),
|
|
2560
|
-
/* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */
|
|
2563
|
-
] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */
|
|
2869
|
+
/* @__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: [
|
|
2870
|
+
/* @__PURE__ */ jsx32("div", { className: "w-6 h-6 border-2 border-purple-500/50 border-t-purple-500 rounded-full animate-spin" }),
|
|
2871
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm font-medium", children: "Loading data..." })
|
|
2872
|
+
] }) }) }) : 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
2873
|
"tr",
|
|
2565
2874
|
{
|
|
2566
2875
|
onClick: () => onRowClick?.(row),
|
|
@@ -2570,7 +2879,7 @@ function PrimusDataTable({
|
|
|
2570
2879
|
${selectedKeys.includes(row[rowKey]) ? "bg-purple-500/10 hover:bg-purple-500/20" : ""}
|
|
2571
2880
|
`,
|
|
2572
2881
|
children: [
|
|
2573
|
-
selectable && /* @__PURE__ */
|
|
2882
|
+
selectable && /* @__PURE__ */ jsx32("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx32(
|
|
2574
2883
|
"input",
|
|
2575
2884
|
{
|
|
2576
2885
|
type: "checkbox",
|
|
@@ -2579,15 +2888,15 @@ function PrimusDataTable({
|
|
|
2579
2888
|
className: "rounded border-gray-600 bg-gray-800 text-purple-600 focus:ring-offset-gray-900 focus:ring-purple-500 cursor-pointer"
|
|
2580
2889
|
}
|
|
2581
2890
|
) }),
|
|
2582
|
-
columns.map((col) => /* @__PURE__ */
|
|
2583
|
-
actions && /* @__PURE__ */
|
|
2891
|
+
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))),
|
|
2892
|
+
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
2893
|
]
|
|
2585
2894
|
},
|
|
2586
2895
|
String(row[rowKey])
|
|
2587
2896
|
)) })
|
|
2588
2897
|
] }) }) }),
|
|
2589
|
-
paginated && totalPages > 1 && /* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2898
|
+
paginated && totalPages > 1 && /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between text-sm text-gray-400 px-2", children: [
|
|
2899
|
+
/* @__PURE__ */ jsx32(
|
|
2591
2900
|
"button",
|
|
2592
2901
|
{
|
|
2593
2902
|
type: "button",
|
|
@@ -2597,13 +2906,13 @@ function PrimusDataTable({
|
|
|
2597
2906
|
children: "Previous"
|
|
2598
2907
|
}
|
|
2599
2908
|
),
|
|
2600
|
-
/* @__PURE__ */
|
|
2909
|
+
/* @__PURE__ */ jsxs29("span", { children: [
|
|
2601
2910
|
"Page ",
|
|
2602
2911
|
currentPageIndex + 1,
|
|
2603
2912
|
" of ",
|
|
2604
2913
|
totalPages
|
|
2605
2914
|
] }),
|
|
2606
|
-
/* @__PURE__ */
|
|
2915
|
+
/* @__PURE__ */ jsx32(
|
|
2607
2916
|
"button",
|
|
2608
2917
|
{
|
|
2609
2918
|
type: "button",
|
|
@@ -2618,7 +2927,7 @@ function PrimusDataTable({
|
|
|
2618
2927
|
}
|
|
2619
2928
|
|
|
2620
2929
|
// src/components/crud/PrimusModal.tsx
|
|
2621
|
-
import { jsx as
|
|
2930
|
+
import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2622
2931
|
var PrimusModal = ({
|
|
2623
2932
|
open,
|
|
2624
2933
|
onClose,
|
|
@@ -2634,34 +2943,34 @@ var PrimusModal = ({
|
|
|
2634
2943
|
lg: "max-w-lg",
|
|
2635
2944
|
xl: "max-w-xl"
|
|
2636
2945
|
};
|
|
2637
|
-
return /* @__PURE__ */
|
|
2638
|
-
/* @__PURE__ */
|
|
2946
|
+
return /* @__PURE__ */ jsxs30("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
2947
|
+
/* @__PURE__ */ jsx33(
|
|
2639
2948
|
"div",
|
|
2640
2949
|
{
|
|
2641
2950
|
className: "absolute inset-0 bg-black/60 backdrop-blur-sm",
|
|
2642
2951
|
onClick: onClose
|
|
2643
2952
|
}
|
|
2644
2953
|
),
|
|
2645
|
-
/* @__PURE__ */
|
|
2646
|
-
title && /* @__PURE__ */
|
|
2647
|
-
/* @__PURE__ */
|
|
2648
|
-
/* @__PURE__ */
|
|
2954
|
+
/* @__PURE__ */ jsxs30("div", { className: `relative w-full ${sizeClasses2[size]} mx-4 bg-gray-800 rounded-xl border border-gray-700 shadow-2xl`, children: [
|
|
2955
|
+
title && /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-700", children: [
|
|
2956
|
+
/* @__PURE__ */ jsx33("h2", { className: "text-lg font-semibold text-white", children: title }),
|
|
2957
|
+
/* @__PURE__ */ jsx33(
|
|
2649
2958
|
"button",
|
|
2650
2959
|
{
|
|
2651
2960
|
onClick: onClose,
|
|
2652
2961
|
className: "text-gray-400 hover:text-white transition-colors",
|
|
2653
|
-
children: /* @__PURE__ */
|
|
2962
|
+
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
2963
|
}
|
|
2655
2964
|
)
|
|
2656
2965
|
] }),
|
|
2657
|
-
/* @__PURE__ */
|
|
2658
|
-
footer && /* @__PURE__ */
|
|
2966
|
+
/* @__PURE__ */ jsx33("div", { className: "p-6", children }),
|
|
2967
|
+
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
2968
|
] })
|
|
2660
2969
|
] });
|
|
2661
2970
|
};
|
|
2662
2971
|
|
|
2663
2972
|
// src/components/dashboard/PrimusDashboard.tsx
|
|
2664
|
-
import { jsx as
|
|
2973
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2665
2974
|
var PrimusStatCard = ({
|
|
2666
2975
|
title,
|
|
2667
2976
|
value,
|
|
@@ -2697,35 +3006,35 @@ var PrimusStatCard = ({
|
|
|
2697
3006
|
const linePath = points.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x} ${point.y}`).join(" ");
|
|
2698
3007
|
const areaPath = `${linePath} L 100 100 L 0 100 Z`;
|
|
2699
3008
|
const gradientId = `gradient-${title.replace(/\s/g, "")}`;
|
|
2700
|
-
return /* @__PURE__ */
|
|
2701
|
-
/* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
3009
|
+
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: [
|
|
3010
|
+
/* @__PURE__ */ jsx34("defs", { children: /* @__PURE__ */ jsxs31("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
3011
|
+
/* @__PURE__ */ jsx34("stop", { offset: "0%", stopColor: "currentColor", stopOpacity: "0.25" }),
|
|
3012
|
+
/* @__PURE__ */ jsx34("stop", { offset: "100%", stopColor: "currentColor", stopOpacity: "0" })
|
|
2704
3013
|
] }) }),
|
|
2705
|
-
/* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
3014
|
+
/* @__PURE__ */ jsx34("path", { d: areaPath, fill: `url(#${gradientId})`, stroke: "none" }),
|
|
3015
|
+
/* @__PURE__ */ jsx34("path", { d: linePath, fill: "none", stroke: "currentColor", strokeWidth: "1.8", opacity: "0.6" })
|
|
2707
3016
|
] });
|
|
2708
3017
|
};
|
|
2709
|
-
return /* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
/* @__PURE__ */
|
|
2712
|
-
/* @__PURE__ */
|
|
2713
|
-
/* @__PURE__ */
|
|
2714
|
-
change && /* @__PURE__ */
|
|
3018
|
+
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: [
|
|
3019
|
+
/* @__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" }),
|
|
3020
|
+
/* @__PURE__ */ jsxs31("div", { className: "p-6 relative z-10", children: [
|
|
3021
|
+
/* @__PURE__ */ jsxs31("div", { className: "flex items-start justify-between mb-4", children: [
|
|
3022
|
+
/* @__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" }) }),
|
|
3023
|
+
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
3024
|
changeIcons[change.type],
|
|
2716
3025
|
" ",
|
|
2717
3026
|
Math.abs(change.value),
|
|
2718
3027
|
"%"
|
|
2719
3028
|
] })
|
|
2720
3029
|
] }),
|
|
2721
|
-
/* @__PURE__ */
|
|
2722
|
-
/* @__PURE__ */
|
|
2723
|
-
/* @__PURE__ */
|
|
2724
|
-
description && /* @__PURE__ */
|
|
3030
|
+
/* @__PURE__ */ jsxs31("div", { children: [
|
|
3031
|
+
/* @__PURE__ */ jsx34("h3", { className: "text-sm font-medium text-gray-400 tracking-wide", children: title }),
|
|
3032
|
+
/* @__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 }) }),
|
|
3033
|
+
description && /* @__PURE__ */ jsx34("p", { className: "text-xs text-gray-500 mt-2 font-medium", children: description })
|
|
2725
3034
|
] })
|
|
2726
3035
|
] }),
|
|
2727
3036
|
renderSparkline(),
|
|
2728
|
-
/* @__PURE__ */
|
|
3037
|
+
/* @__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
3038
|
] });
|
|
2730
3039
|
};
|
|
2731
3040
|
var PrimusDashboard = ({
|
|
@@ -2734,13 +3043,13 @@ var PrimusDashboard = ({
|
|
|
2734
3043
|
subtitle,
|
|
2735
3044
|
actions
|
|
2736
3045
|
}) => {
|
|
2737
|
-
return /* @__PURE__ */
|
|
2738
|
-
(title || actions) && /* @__PURE__ */
|
|
2739
|
-
/* @__PURE__ */
|
|
2740
|
-
title && /* @__PURE__ */
|
|
2741
|
-
subtitle && /* @__PURE__ */
|
|
3046
|
+
return /* @__PURE__ */ jsxs31("div", { className: "space-y-8 animate-enter", children: [
|
|
3047
|
+
(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: [
|
|
3048
|
+
/* @__PURE__ */ jsxs31("div", { children: [
|
|
3049
|
+
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 }),
|
|
3050
|
+
subtitle && /* @__PURE__ */ jsx34("p", { className: "text-gray-400 mt-2 text-lg font-light leading-relaxed", children: subtitle })
|
|
2742
3051
|
] }),
|
|
2743
|
-
actions && /* @__PURE__ */
|
|
3052
|
+
actions && /* @__PURE__ */ jsx34("div", { className: "flex items-center gap-3", children: actions })
|
|
2744
3053
|
] }),
|
|
2745
3054
|
children
|
|
2746
3055
|
] });
|
|
@@ -2755,25 +3064,119 @@ var DashboardGrid = ({
|
|
|
2755
3064
|
3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
|
|
2756
3065
|
4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4"
|
|
2757
3066
|
};
|
|
2758
|
-
return /* @__PURE__ */
|
|
3067
|
+
return /* @__PURE__ */ jsx34("div", { className: `grid gap-6 ${colClasses[columns]}`, children });
|
|
2759
3068
|
};
|
|
2760
3069
|
|
|
2761
|
-
// src/components/
|
|
2762
|
-
import
|
|
2763
|
-
import { jsx as
|
|
2764
|
-
var
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
3070
|
+
// src/components/shared/Card.tsx
|
|
3071
|
+
import React21 from "react";
|
|
3072
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
3073
|
+
var Card = React21.forwardRef(
|
|
3074
|
+
({ style, variant = "default", padding = "md", children, ...props }, ref) => {
|
|
3075
|
+
const [isHovered, setIsHovered] = React21.useState(false);
|
|
3076
|
+
const paddingStyles = {
|
|
3077
|
+
none: "0",
|
|
3078
|
+
sm: "0.75rem",
|
|
3079
|
+
md: "1.5rem",
|
|
3080
|
+
lg: "2rem"
|
|
3081
|
+
};
|
|
3082
|
+
const variantStyles = {
|
|
3083
|
+
default: {
|
|
3084
|
+
normal: {
|
|
3085
|
+
backgroundColor: "#ffffff",
|
|
3086
|
+
border: "1px solid #e5e7eb",
|
|
3087
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
3088
|
+
},
|
|
3089
|
+
hover: {
|
|
3090
|
+
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3091
|
+
}
|
|
3092
|
+
},
|
|
3093
|
+
outlined: {
|
|
3094
|
+
normal: {
|
|
3095
|
+
backgroundColor: "#ffffff",
|
|
3096
|
+
border: "2px solid #e5e7eb",
|
|
3097
|
+
boxShadow: "none"
|
|
3098
|
+
},
|
|
3099
|
+
hover: {
|
|
3100
|
+
borderColor: "#d1d5db"
|
|
3101
|
+
}
|
|
3102
|
+
},
|
|
3103
|
+
elevated: {
|
|
3104
|
+
normal: {
|
|
3105
|
+
backgroundColor: "#ffffff",
|
|
3106
|
+
border: "none",
|
|
3107
|
+
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3108
|
+
},
|
|
3109
|
+
hover: {
|
|
3110
|
+
boxShadow: "0 10px 15px rgba(0, 0, 0, 0.15)",
|
|
3111
|
+
transform: "translateY(-2px)"
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
};
|
|
3115
|
+
const baseStyles = {
|
|
3116
|
+
borderRadius: "0.5rem",
|
|
3117
|
+
padding: paddingStyles[padding],
|
|
3118
|
+
transition: "all 0.2s ease"
|
|
3119
|
+
};
|
|
3120
|
+
const currentVariant = variantStyles[variant];
|
|
3121
|
+
const combinedStyles = {
|
|
3122
|
+
...baseStyles,
|
|
3123
|
+
...currentVariant.normal,
|
|
3124
|
+
...isHovered ? currentVariant.hover : {},
|
|
3125
|
+
...style
|
|
3126
|
+
};
|
|
3127
|
+
return /* @__PURE__ */ jsx35(
|
|
3128
|
+
"div",
|
|
3129
|
+
{
|
|
3130
|
+
ref,
|
|
3131
|
+
style: combinedStyles,
|
|
3132
|
+
onMouseEnter: () => setIsHovered(true),
|
|
3133
|
+
onMouseLeave: () => setIsHovered(false),
|
|
3134
|
+
...props,
|
|
3135
|
+
children
|
|
3136
|
+
}
|
|
3137
|
+
);
|
|
3138
|
+
}
|
|
3139
|
+
);
|
|
3140
|
+
Card.displayName = "Card";
|
|
3141
|
+
|
|
3142
|
+
// src/components/dashboard/PrimusSummaryCard.tsx
|
|
3143
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3144
|
+
var PrimusSummaryCard = ({
|
|
3145
|
+
title,
|
|
3146
|
+
subtitle,
|
|
3147
|
+
actionLabel,
|
|
3148
|
+
onAction,
|
|
3149
|
+
children,
|
|
3150
|
+
className
|
|
3151
|
+
}) => {
|
|
3152
|
+
return /* @__PURE__ */ jsx36(Card, { className, children: /* @__PURE__ */ jsxs32("div", { className: "p-6", children: [
|
|
3153
|
+
/* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between mb-4", children: [
|
|
3154
|
+
/* @__PURE__ */ jsxs32("div", { children: [
|
|
3155
|
+
/* @__PURE__ */ jsx36("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: title }),
|
|
3156
|
+
subtitle && /* @__PURE__ */ jsx36("p", { className: "text-sm text-gray-500 dark:text-gray-400 mt-1", children: subtitle })
|
|
3157
|
+
] }),
|
|
3158
|
+
actionLabel && onAction && /* @__PURE__ */ jsx36(Button, { variant: "outline", size: "sm", onClick: onAction, children: actionLabel })
|
|
3159
|
+
] }),
|
|
3160
|
+
/* @__PURE__ */ jsx36("div", { className: "mt-4", children })
|
|
3161
|
+
] }) });
|
|
3162
|
+
};
|
|
3163
|
+
|
|
3164
|
+
// src/components/dashboard/PrimusActivityFeed.tsx
|
|
3165
|
+
import { useMemo as useMemo3 } from "react";
|
|
3166
|
+
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3167
|
+
var statusClasses = {
|
|
3168
|
+
success: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30",
|
|
3169
|
+
warning: "bg-amber-500/10 text-amber-300 border-amber-500/30",
|
|
3170
|
+
error: "bg-rose-500/10 text-rose-300 border-rose-500/30",
|
|
3171
|
+
info: "bg-blue-500/10 text-blue-300 border-blue-500/30"
|
|
3172
|
+
};
|
|
3173
|
+
var PrimusActivityFeed = ({
|
|
3174
|
+
items,
|
|
3175
|
+
maxItems = 10,
|
|
3176
|
+
showTimestamps = true,
|
|
3177
|
+
groupByDate = false,
|
|
3178
|
+
loading = false
|
|
3179
|
+
}) => {
|
|
2777
3180
|
const visibleItems = useMemo3(() => items.slice(0, maxItems), [items, maxItems]);
|
|
2778
3181
|
const groups = useMemo3(() => {
|
|
2779
3182
|
if (!groupByDate) {
|
|
@@ -2789,18 +3192,18 @@ var PrimusActivityFeed = ({
|
|
|
2789
3192
|
return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
2790
3193
|
}, [groupByDate, visibleItems]);
|
|
2791
3194
|
if (loading) {
|
|
2792
|
-
return /* @__PURE__ */
|
|
3195
|
+
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
3196
|
}
|
|
2794
|
-
return /* @__PURE__ */
|
|
2795
|
-
group.label && /* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
2797
|
-
/* @__PURE__ */
|
|
2798
|
-
/* @__PURE__ */
|
|
2799
|
-
/* @__PURE__ */
|
|
2800
|
-
/* @__PURE__ */
|
|
2801
|
-
showTimestamps && /* @__PURE__ */
|
|
3197
|
+
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: [
|
|
3198
|
+
group.label && /* @__PURE__ */ jsx37("div", { className: "text-xs uppercase tracking-wide text-gray-500 mb-3", children: group.label }),
|
|
3199
|
+
/* @__PURE__ */ jsx37("div", { className: "space-y-4", children: group.items.map((item, itemIndex) => /* @__PURE__ */ jsxs33("div", { className: "flex items-start gap-4", children: [
|
|
3200
|
+
/* @__PURE__ */ jsx37("div", { className: `mt-1 h-2.5 w-2.5 rounded-full border ${statusClasses[item.status ?? "info"]}` }),
|
|
3201
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
|
|
3202
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between gap-4", children: [
|
|
3203
|
+
/* @__PURE__ */ jsx37("div", { className: "text-sm font-medium text-gray-100", children: item.title }),
|
|
3204
|
+
showTimestamps && /* @__PURE__ */ jsx37("div", { className: "text-xs text-gray-500", children: formatTime(item.timestamp) })
|
|
2802
3205
|
] }),
|
|
2803
|
-
item.description && /* @__PURE__ */
|
|
3206
|
+
item.description && /* @__PURE__ */ jsx37("div", { className: "text-xs text-gray-400 mt-1", children: item.description })
|
|
2804
3207
|
] })
|
|
2805
3208
|
] }, item.id ?? `${itemIndex}-${item.title}`)) })
|
|
2806
3209
|
] }, `${group.label}-${index}`)) });
|
|
@@ -2827,12 +3230,12 @@ var formatTime = (value) => {
|
|
|
2827
3230
|
};
|
|
2828
3231
|
|
|
2829
3232
|
// src/components/charts/PrimusChartBase.tsx
|
|
2830
|
-
import { useEffect as useEffect14, useMemo as useMemo4, useRef } from "react";
|
|
3233
|
+
import { useEffect as useEffect14, useMemo as useMemo4, useRef as useRef2 } from "react";
|
|
2831
3234
|
import {
|
|
2832
3235
|
Chart,
|
|
2833
3236
|
registerables
|
|
2834
3237
|
} from "chart.js";
|
|
2835
|
-
import { jsx as
|
|
3238
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2836
3239
|
var registered = false;
|
|
2837
3240
|
var ensureRegistered = () => {
|
|
2838
3241
|
if (!registered) {
|
|
@@ -2855,8 +3258,8 @@ var PrimusChartBase = ({
|
|
|
2855
3258
|
className,
|
|
2856
3259
|
datasetTransform
|
|
2857
3260
|
}) => {
|
|
2858
|
-
const canvasRef =
|
|
2859
|
-
const chartRef =
|
|
3261
|
+
const canvasRef = useRef2(null);
|
|
3262
|
+
const chartRef = useRef2(null);
|
|
2860
3263
|
const builtData = useMemo4(() => {
|
|
2861
3264
|
if (data) {
|
|
2862
3265
|
return data;
|
|
@@ -2923,13 +3326,13 @@ var PrimusChartBase = ({
|
|
|
2923
3326
|
chartRef.current = null;
|
|
2924
3327
|
};
|
|
2925
3328
|
}, [type, builtData, builtOptions]);
|
|
2926
|
-
return /* @__PURE__ */
|
|
3329
|
+
return /* @__PURE__ */ jsx38("div", { className, style: { height, width }, children: /* @__PURE__ */ jsx38("canvas", { ref: canvasRef, "aria-label": ariaLabel, role: "img" }) });
|
|
2927
3330
|
};
|
|
2928
3331
|
|
|
2929
3332
|
// src/components/charts/PrimusLineChart.tsx
|
|
2930
|
-
import { jsx as
|
|
3333
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
2931
3334
|
var PrimusLineChart = (props) => {
|
|
2932
|
-
return /* @__PURE__ */
|
|
3335
|
+
return /* @__PURE__ */ jsx39(
|
|
2933
3336
|
PrimusChartBase,
|
|
2934
3337
|
{
|
|
2935
3338
|
...props,
|
|
@@ -2947,9 +3350,9 @@ var PrimusLineChart = (props) => {
|
|
|
2947
3350
|
};
|
|
2948
3351
|
|
|
2949
3352
|
// src/components/charts/PrimusAreaChart.tsx
|
|
2950
|
-
import { jsx as
|
|
3353
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
2951
3354
|
var PrimusAreaChart = (props) => {
|
|
2952
|
-
return /* @__PURE__ */
|
|
3355
|
+
return /* @__PURE__ */ jsx40(
|
|
2953
3356
|
PrimusChartBase,
|
|
2954
3357
|
{
|
|
2955
3358
|
...props,
|
|
@@ -2967,7 +3370,7 @@ var PrimusAreaChart = (props) => {
|
|
|
2967
3370
|
};
|
|
2968
3371
|
|
|
2969
3372
|
// src/components/charts/PrimusBarChart.tsx
|
|
2970
|
-
import { jsx as
|
|
3373
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2971
3374
|
var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
2972
3375
|
const mergedOptions = {
|
|
2973
3376
|
...options,
|
|
@@ -2977,7 +3380,7 @@ var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
|
2977
3380
|
...options?.scales ?? {}
|
|
2978
3381
|
}
|
|
2979
3382
|
};
|
|
2980
|
-
return /* @__PURE__ */
|
|
3383
|
+
return /* @__PURE__ */ jsx41(
|
|
2981
3384
|
PrimusChartBase,
|
|
2982
3385
|
{
|
|
2983
3386
|
...props,
|
|
@@ -2993,13 +3396,13 @@ var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
|
2993
3396
|
};
|
|
2994
3397
|
|
|
2995
3398
|
// src/components/charts/PrimusPieChart.tsx
|
|
2996
|
-
import { jsx as
|
|
3399
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2997
3400
|
var PrimusPieChart = ({ donut = false, cutout = "55%", options, ...props }) => {
|
|
2998
3401
|
const mergedOptions = {
|
|
2999
3402
|
...options,
|
|
3000
3403
|
cutout: donut ? cutout : void 0
|
|
3001
3404
|
};
|
|
3002
|
-
return /* @__PURE__ */
|
|
3405
|
+
return /* @__PURE__ */ jsx42(
|
|
3003
3406
|
PrimusChartBase,
|
|
3004
3407
|
{
|
|
3005
3408
|
...props,
|
|
@@ -3016,7 +3419,7 @@ var PrimusPieChart = ({ donut = false, cutout = "55%", options, ...props }) => {
|
|
|
3016
3419
|
|
|
3017
3420
|
// src/components/charts/PrimusSparkline.tsx
|
|
3018
3421
|
import { useMemo as useMemo5 } from "react";
|
|
3019
|
-
import { jsx as
|
|
3422
|
+
import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3020
3423
|
var PrimusSparkline = ({
|
|
3021
3424
|
series = [],
|
|
3022
3425
|
data,
|
|
@@ -3049,7 +3452,7 @@ var PrimusSparkline = ({
|
|
|
3049
3452
|
if (!values.length) {
|
|
3050
3453
|
return null;
|
|
3051
3454
|
}
|
|
3052
|
-
return /* @__PURE__ */
|
|
3455
|
+
return /* @__PURE__ */ jsxs34(
|
|
3053
3456
|
"svg",
|
|
3054
3457
|
{
|
|
3055
3458
|
className,
|
|
@@ -3060,17 +3463,17 @@ var PrimusSparkline = ({
|
|
|
3060
3463
|
"aria-label": ariaLabel,
|
|
3061
3464
|
role: "img",
|
|
3062
3465
|
children: [
|
|
3063
|
-
type === "area" && /* @__PURE__ */
|
|
3064
|
-
/* @__PURE__ */
|
|
3466
|
+
type === "area" && /* @__PURE__ */ jsx43("path", { d: areaPath, fill: color, opacity: 0.2, stroke: "none" }),
|
|
3467
|
+
/* @__PURE__ */ jsx43("path", { d: linePath, fill: "none", stroke: color, strokeWidth })
|
|
3065
3468
|
]
|
|
3066
3469
|
}
|
|
3067
3470
|
);
|
|
3068
3471
|
};
|
|
3069
3472
|
|
|
3070
3473
|
// src/components/shared/Checkbox.tsx
|
|
3071
|
-
import
|
|
3072
|
-
import { jsx as
|
|
3073
|
-
var Checkbox =
|
|
3474
|
+
import React24 from "react";
|
|
3475
|
+
import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3476
|
+
var Checkbox = React24.forwardRef(
|
|
3074
3477
|
({ style, label, error, disabled, className, ...props }, ref) => {
|
|
3075
3478
|
const containerStyles = {
|
|
3076
3479
|
display: "flex",
|
|
@@ -3107,9 +3510,9 @@ var Checkbox = React22.forwardRef(
|
|
|
3107
3510
|
marginTop: "0.25rem",
|
|
3108
3511
|
marginLeft: "1.75rem"
|
|
3109
3512
|
};
|
|
3110
|
-
return /* @__PURE__ */
|
|
3111
|
-
/* @__PURE__ */
|
|
3112
|
-
/* @__PURE__ */
|
|
3513
|
+
return /* @__PURE__ */ jsxs35("div", { children: [
|
|
3514
|
+
/* @__PURE__ */ jsxs35("div", { style: containerStyles, children: [
|
|
3515
|
+
/* @__PURE__ */ jsx44("div", { style: checkboxWrapperStyles, children: /* @__PURE__ */ jsx44(
|
|
3113
3516
|
"input",
|
|
3114
3517
|
{
|
|
3115
3518
|
ref,
|
|
@@ -3122,21 +3525,21 @@ var Checkbox = React22.forwardRef(
|
|
|
3122
3525
|
...props
|
|
3123
3526
|
}
|
|
3124
3527
|
) }),
|
|
3125
|
-
label && /* @__PURE__ */
|
|
3528
|
+
label && /* @__PURE__ */ jsx44("label", { style: labelStyles, onClick: (e) => {
|
|
3126
3529
|
if (!disabled) {
|
|
3127
3530
|
const input = e.currentTarget.previousElementSibling?.querySelector("input");
|
|
3128
3531
|
input?.click();
|
|
3129
3532
|
}
|
|
3130
3533
|
}, children: label })
|
|
3131
3534
|
] }),
|
|
3132
|
-
error && /* @__PURE__ */
|
|
3535
|
+
error && /* @__PURE__ */ jsx44("p", { style: errorTextStyles, children: error })
|
|
3133
3536
|
] });
|
|
3134
3537
|
}
|
|
3135
3538
|
);
|
|
3136
3539
|
Checkbox.displayName = "Checkbox";
|
|
3137
3540
|
|
|
3138
3541
|
// src/components/shared/RadioGroup.tsx
|
|
3139
|
-
import { jsx as
|
|
3542
|
+
import { jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3140
3543
|
var RadioGroup = ({
|
|
3141
3544
|
name,
|
|
3142
3545
|
options,
|
|
@@ -3176,9 +3579,9 @@ var RadioGroup = ({
|
|
|
3176
3579
|
color: "#ef4444",
|
|
3177
3580
|
marginTop: "0.5rem"
|
|
3178
3581
|
};
|
|
3179
|
-
return /* @__PURE__ */
|
|
3180
|
-
/* @__PURE__ */
|
|
3181
|
-
/* @__PURE__ */
|
|
3582
|
+
return /* @__PURE__ */ jsxs36("div", { children: [
|
|
3583
|
+
/* @__PURE__ */ jsx45("div", { style: containerStyles, children: options.map((option) => /* @__PURE__ */ jsxs36("div", { style: optionStyles, children: [
|
|
3584
|
+
/* @__PURE__ */ jsx45(
|
|
3182
3585
|
"input",
|
|
3183
3586
|
{
|
|
3184
3587
|
type: "radio",
|
|
@@ -3190,7 +3593,7 @@ var RadioGroup = ({
|
|
|
3190
3593
|
style: radioStyles
|
|
3191
3594
|
}
|
|
3192
3595
|
),
|
|
3193
|
-
/* @__PURE__ */
|
|
3596
|
+
/* @__PURE__ */ jsx45(
|
|
3194
3597
|
"label",
|
|
3195
3598
|
{
|
|
3196
3599
|
style: {
|
|
@@ -3206,17 +3609,17 @@ var RadioGroup = ({
|
|
|
3206
3609
|
}
|
|
3207
3610
|
)
|
|
3208
3611
|
] }, option.value)) }),
|
|
3209
|
-
error && /* @__PURE__ */
|
|
3612
|
+
error && /* @__PURE__ */ jsx45("p", { style: errorTextStyles, children: error })
|
|
3210
3613
|
] });
|
|
3211
3614
|
};
|
|
3212
3615
|
RadioGroup.displayName = "RadioGroup";
|
|
3213
3616
|
|
|
3214
3617
|
// src/components/shared/Select.tsx
|
|
3215
|
-
import
|
|
3618
|
+
import React25, { useState as useState22 } from "react";
|
|
3216
3619
|
import { Combobox, Transition as Transition2 } from "@headlessui/react";
|
|
3217
3620
|
import { CheckIcon as CheckIcon2, ChevronUpDownIcon, XMarkIcon as XMarkIcon3 } from "@heroicons/react/20/solid";
|
|
3218
3621
|
import { clsx as clsx7 } from "clsx";
|
|
3219
|
-
import { Fragment as Fragment5, jsx as
|
|
3622
|
+
import { Fragment as Fragment5, jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3220
3623
|
var Select = ({
|
|
3221
3624
|
label,
|
|
3222
3625
|
error,
|
|
@@ -3238,7 +3641,7 @@ var Select = ({
|
|
|
3238
3641
|
onChange?.(value.filter((v) => v !== valToRemove));
|
|
3239
3642
|
}
|
|
3240
3643
|
};
|
|
3241
|
-
return /* @__PURE__ */
|
|
3644
|
+
return /* @__PURE__ */ jsx46("div", { className: clsx7("w-full", className), children: /* @__PURE__ */ jsx46(
|
|
3242
3645
|
Combobox,
|
|
3243
3646
|
{
|
|
3244
3647
|
value,
|
|
@@ -3247,21 +3650,21 @@ var Select = ({
|
|
|
3247
3650
|
},
|
|
3248
3651
|
multiple,
|
|
3249
3652
|
disabled,
|
|
3250
|
-
children: ({}) => /* @__PURE__ */
|
|
3251
|
-
label && /* @__PURE__ */
|
|
3252
|
-
/* @__PURE__ */
|
|
3653
|
+
children: ({}) => /* @__PURE__ */ jsxs37("div", { className: "relative", children: [
|
|
3654
|
+
label && /* @__PURE__ */ jsx46(Combobox.Label, { className: "block text-sm font-medium text-gray-700 mb-1", children: label }),
|
|
3655
|
+
/* @__PURE__ */ jsxs37("div", { className: clsx7(
|
|
3253
3656
|
"relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left focus-within:ring-2 focus-within:ring-primus-500",
|
|
3254
3657
|
"border transition-all duration-200 ease-in-out",
|
|
3255
3658
|
error ? "border-red-500 focus-within:ring-red-500" : "border-gray-300",
|
|
3256
3659
|
disabled && "opacity-50 cursor-not-allowed bg-gray-50"
|
|
3257
3660
|
), children: [
|
|
3258
|
-
/* @__PURE__ */
|
|
3661
|
+
/* @__PURE__ */ jsxs37("div", { className: clsx7(
|
|
3259
3662
|
"flex flex-wrap items-center gap-1.5 w-full py-1.5 pl-3 pr-10 text-sm",
|
|
3260
3663
|
"min-h-[2.5rem]"
|
|
3261
3664
|
), children: [
|
|
3262
|
-
multiple && Array.isArray(value) && value.map((val) => /* @__PURE__ */
|
|
3263
|
-
/* @__PURE__ */
|
|
3264
|
-
/* @__PURE__ */
|
|
3665
|
+
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: [
|
|
3666
|
+
/* @__PURE__ */ jsx46("span", { className: "truncate", children: getLabel(val) }),
|
|
3667
|
+
/* @__PURE__ */ jsxs37(
|
|
3265
3668
|
"button",
|
|
3266
3669
|
{
|
|
3267
3670
|
type: "button",
|
|
@@ -3273,13 +3676,13 @@ var Select = ({
|
|
|
3273
3676
|
},
|
|
3274
3677
|
onMouseDown: (e) => e.preventDefault(),
|
|
3275
3678
|
children: [
|
|
3276
|
-
/* @__PURE__ */
|
|
3277
|
-
/* @__PURE__ */
|
|
3679
|
+
/* @__PURE__ */ jsx46("span", { className: "sr-only", children: "Remove" }),
|
|
3680
|
+
/* @__PURE__ */ jsx46(XMarkIcon3, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
3278
3681
|
]
|
|
3279
3682
|
}
|
|
3280
3683
|
)
|
|
3281
3684
|
] }, val)),
|
|
3282
|
-
/* @__PURE__ */
|
|
3685
|
+
/* @__PURE__ */ jsx46(
|
|
3283
3686
|
Combobox.Input,
|
|
3284
3687
|
{
|
|
3285
3688
|
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 +3692,7 @@ var Select = ({
|
|
|
3289
3692
|
}
|
|
3290
3693
|
)
|
|
3291
3694
|
] }),
|
|
3292
|
-
/* @__PURE__ */
|
|
3695
|
+
/* @__PURE__ */ jsx46(Combobox.Button, { className: "absolute inset-y-0 right-0 flex items-center pr-2", children: /* @__PURE__ */ jsx46(
|
|
3293
3696
|
ChevronUpDownIcon,
|
|
3294
3697
|
{
|
|
3295
3698
|
className: "h-5 w-5 text-gray-400",
|
|
@@ -3297,15 +3700,15 @@ var Select = ({
|
|
|
3297
3700
|
}
|
|
3298
3701
|
) })
|
|
3299
3702
|
] }),
|
|
3300
|
-
/* @__PURE__ */
|
|
3703
|
+
/* @__PURE__ */ jsx46(
|
|
3301
3704
|
Transition2,
|
|
3302
3705
|
{
|
|
3303
|
-
as:
|
|
3706
|
+
as: React25.Fragment,
|
|
3304
3707
|
leave: "transition ease-in duration-100",
|
|
3305
3708
|
leaveFrom: "opacity-100",
|
|
3306
3709
|
leaveTo: "opacity-0",
|
|
3307
3710
|
afterLeave: () => setQuery(""),
|
|
3308
|
-
children: /* @__PURE__ */
|
|
3711
|
+
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
3712
|
Combobox.Option,
|
|
3310
3713
|
{
|
|
3311
3714
|
className: ({ active }) => clsx7(
|
|
@@ -3314,16 +3717,16 @@ var Select = ({
|
|
|
3314
3717
|
),
|
|
3315
3718
|
value: option.value,
|
|
3316
3719
|
disabled: option.disabled,
|
|
3317
|
-
children: ({ selected, active }) => /* @__PURE__ */
|
|
3318
|
-
/* @__PURE__ */
|
|
3319
|
-
selected ? /* @__PURE__ */
|
|
3720
|
+
children: ({ selected, active }) => /* @__PURE__ */ jsxs37(Fragment5, { children: [
|
|
3721
|
+
/* @__PURE__ */ jsx46("span", { className: clsx7("block truncate", selected ? "font-medium" : "font-normal"), children: option.label }),
|
|
3722
|
+
selected ? /* @__PURE__ */ jsx46(
|
|
3320
3723
|
"span",
|
|
3321
3724
|
{
|
|
3322
3725
|
className: clsx7(
|
|
3323
3726
|
"absolute inset-y-0 left-0 flex items-center pl-3",
|
|
3324
3727
|
active ? "text-white" : "text-primus-600"
|
|
3325
3728
|
),
|
|
3326
|
-
children: /* @__PURE__ */
|
|
3729
|
+
children: /* @__PURE__ */ jsx46(CheckIcon2, { className: "h-5 w-5", "aria-hidden": "true" })
|
|
3327
3730
|
}
|
|
3328
3731
|
) : null
|
|
3329
3732
|
] })
|
|
@@ -3332,15 +3735,15 @@ var Select = ({
|
|
|
3332
3735
|
)) })
|
|
3333
3736
|
}
|
|
3334
3737
|
),
|
|
3335
|
-
error && /* @__PURE__ */
|
|
3738
|
+
error && /* @__PURE__ */ jsx46("p", { className: "mt-1 text-sm text-red-500", children: error })
|
|
3336
3739
|
] })
|
|
3337
3740
|
}
|
|
3338
3741
|
) });
|
|
3339
3742
|
};
|
|
3340
3743
|
|
|
3341
3744
|
// src/components/shared/Toggle.tsx
|
|
3342
|
-
import
|
|
3343
|
-
import { jsx as
|
|
3745
|
+
import React26 from "react";
|
|
3746
|
+
import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3344
3747
|
var Toggle = ({
|
|
3345
3748
|
checked = false,
|
|
3346
3749
|
onChange,
|
|
@@ -3348,7 +3751,7 @@ var Toggle = ({
|
|
|
3348
3751
|
label,
|
|
3349
3752
|
size = "md"
|
|
3350
3753
|
}) => {
|
|
3351
|
-
const [isHovered, setIsHovered] =
|
|
3754
|
+
const [isHovered, setIsHovered] = React26.useState(false);
|
|
3352
3755
|
const sizes = {
|
|
3353
3756
|
sm: { width: "2.25rem", height: "1.25rem", thumbSize: "0.875rem" },
|
|
3354
3757
|
md: { width: "2.75rem", height: "1.5rem", thumbSize: "1.125rem" },
|
|
@@ -3395,8 +3798,8 @@ var Toggle = ({
|
|
|
3395
3798
|
onChange?.(!checked);
|
|
3396
3799
|
}
|
|
3397
3800
|
};
|
|
3398
|
-
return /* @__PURE__ */
|
|
3399
|
-
/* @__PURE__ */
|
|
3801
|
+
return /* @__PURE__ */ jsxs38("div", { style: containerStyles, children: [
|
|
3802
|
+
/* @__PURE__ */ jsx47(
|
|
3400
3803
|
"div",
|
|
3401
3804
|
{
|
|
3402
3805
|
style: switchStyles,
|
|
@@ -3412,20 +3815,23 @@ var Toggle = ({
|
|
|
3412
3815
|
handleClick();
|
|
3413
3816
|
}
|
|
3414
3817
|
},
|
|
3415
|
-
children: /* @__PURE__ */
|
|
3818
|
+
children: /* @__PURE__ */ jsx47("div", { style: thumbStyles })
|
|
3416
3819
|
}
|
|
3417
3820
|
),
|
|
3418
|
-
label && /* @__PURE__ */
|
|
3821
|
+
label && /* @__PURE__ */ jsx47("label", { style: labelStyles, onClick: handleClick, children: label })
|
|
3419
3822
|
] });
|
|
3420
3823
|
};
|
|
3421
3824
|
Toggle.displayName = "Toggle";
|
|
3422
3825
|
|
|
3423
3826
|
// 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
|
|
3827
|
+
import React27 from "react";
|
|
3828
|
+
import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3829
|
+
var Textarea = React27.forwardRef(
|
|
3830
|
+
({ style, label, error, disabled, resize = "vertical", onChange, onValueChange, className, ...props }, ref) => {
|
|
3831
|
+
const handleChange = (e) => {
|
|
3832
|
+
onChange?.(e);
|
|
3833
|
+
onValueChange?.(e.target.value);
|
|
3834
|
+
};
|
|
3429
3835
|
const containerStyles = {
|
|
3430
3836
|
width: "100%"
|
|
3431
3837
|
};
|
|
@@ -3433,11 +3839,11 @@ var Textarea = React25.forwardRef(
|
|
|
3433
3839
|
fontSize: "0.875rem",
|
|
3434
3840
|
lineHeight: "1.25rem",
|
|
3435
3841
|
fontWeight: "500",
|
|
3436
|
-
marginBottom: "0.
|
|
3842
|
+
marginBottom: "0.375rem",
|
|
3437
3843
|
display: "block",
|
|
3438
3844
|
color: "#374151",
|
|
3439
|
-
|
|
3440
|
-
|
|
3845
|
+
opacity: disabled ? 0.7 : 1,
|
|
3846
|
+
cursor: disabled ? "not-allowed" : "default"
|
|
3441
3847
|
};
|
|
3442
3848
|
const textareaStyles = {
|
|
3443
3849
|
display: "flex",
|
|
@@ -3450,12 +3856,11 @@ var Textarea = React25.forwardRef(
|
|
|
3450
3856
|
fontSize: "0.875rem",
|
|
3451
3857
|
lineHeight: "1.5rem",
|
|
3452
3858
|
outline: "none",
|
|
3453
|
-
transition: "
|
|
3454
|
-
cursor: disabled ? "not-allowed" : "text",
|
|
3859
|
+
transition: "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out",
|
|
3455
3860
|
opacity: disabled ? 0.5 : 1,
|
|
3861
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
3456
3862
|
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"
|
|
3863
|
+
fontFamily: "inherit"
|
|
3459
3864
|
};
|
|
3460
3865
|
const errorTextStyles = {
|
|
3461
3866
|
fontSize: "0.875rem",
|
|
@@ -3463,9 +3868,9 @@ var Textarea = React25.forwardRef(
|
|
|
3463
3868
|
color: "#ef4444",
|
|
3464
3869
|
marginTop: "0.25rem"
|
|
3465
3870
|
};
|
|
3466
|
-
return /* @__PURE__ */
|
|
3467
|
-
label && /* @__PURE__ */
|
|
3468
|
-
/* @__PURE__ */
|
|
3871
|
+
return /* @__PURE__ */ jsxs39("div", { style: containerStyles, className, children: [
|
|
3872
|
+
label && /* @__PURE__ */ jsx48("label", { style: labelStyles, children: label }),
|
|
3873
|
+
/* @__PURE__ */ jsx48(
|
|
3469
3874
|
"textarea",
|
|
3470
3875
|
{
|
|
3471
3876
|
ref,
|
|
@@ -3473,94 +3878,28 @@ var Textarea = React25.forwardRef(
|
|
|
3473
3878
|
...textareaStyles,
|
|
3474
3879
|
...style
|
|
3475
3880
|
},
|
|
3476
|
-
onFocus: () => setIsFocused(true),
|
|
3477
|
-
onBlur: () => setIsFocused(false),
|
|
3478
3881
|
disabled,
|
|
3882
|
+
onChange: handleChange,
|
|
3883
|
+
className: `primus-textarea ${error ? "error" : ""}`,
|
|
3479
3884
|
...props
|
|
3480
3885
|
}
|
|
3481
3886
|
),
|
|
3482
|
-
|
|
3887
|
+
/* @__PURE__ */ jsx48("style", { children: `
|
|
3888
|
+
.primus-textarea:focus {
|
|
3889
|
+
border-color: ${error ? "#ef4444" : "#6366f1"};
|
|
3890
|
+
box-shadow: 0 0 0 1px ${error ? "#ef4444" : "#6366f1"};
|
|
3891
|
+
}
|
|
3892
|
+
` }),
|
|
3893
|
+
error && /* @__PURE__ */ jsx48("p", { style: errorTextStyles, children: error })
|
|
3483
3894
|
] });
|
|
3484
3895
|
}
|
|
3485
3896
|
);
|
|
3486
3897
|
Textarea.displayName = "Textarea";
|
|
3487
3898
|
|
|
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
3899
|
// src/components/shared/Badge.tsx
|
|
3561
|
-
import
|
|
3562
|
-
import { jsx as
|
|
3563
|
-
var Badge =
|
|
3900
|
+
import React28 from "react";
|
|
3901
|
+
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
3902
|
+
var Badge = React28.forwardRef(
|
|
3564
3903
|
({ style, variant = "default", size = "md", children, ...props }, ref) => {
|
|
3565
3904
|
const variantStyles = {
|
|
3566
3905
|
default: {
|
|
@@ -3614,14 +3953,14 @@ var Badge = React27.forwardRef(
|
|
|
3614
3953
|
...sizeStyles[size],
|
|
3615
3954
|
...style
|
|
3616
3955
|
};
|
|
3617
|
-
return /* @__PURE__ */
|
|
3956
|
+
return /* @__PURE__ */ jsx49("span", { ref, style: combinedStyles, ...props, children });
|
|
3618
3957
|
}
|
|
3619
3958
|
);
|
|
3620
3959
|
Badge.displayName = "Badge";
|
|
3621
3960
|
|
|
3622
3961
|
// src/components/shared/Table.tsx
|
|
3623
|
-
import
|
|
3624
|
-
import { jsx as
|
|
3962
|
+
import React29 from "react";
|
|
3963
|
+
import { jsx as jsx50, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3625
3964
|
function Table({
|
|
3626
3965
|
columns,
|
|
3627
3966
|
data,
|
|
@@ -3630,7 +3969,7 @@ function Table({
|
|
|
3630
3969
|
bordered = true,
|
|
3631
3970
|
style
|
|
3632
3971
|
}) {
|
|
3633
|
-
const [hoveredRow, setHoveredRow] =
|
|
3972
|
+
const [hoveredRow, setHoveredRow] = React29.useState(null);
|
|
3634
3973
|
const tableStyles = {
|
|
3635
3974
|
width: "100%",
|
|
3636
3975
|
borderCollapse: "collapse",
|
|
@@ -3655,8 +3994,8 @@ function Table({
|
|
|
3655
3994
|
backgroundColor: hoverable && hoveredRow === rowIndex ? "#f9fafb" : striped && rowIndex % 2 === 1 ? "#f9fafb" : "#ffffff",
|
|
3656
3995
|
transition: "background-color 0.15s ease"
|
|
3657
3996
|
});
|
|
3658
|
-
return /* @__PURE__ */
|
|
3659
|
-
/* @__PURE__ */
|
|
3997
|
+
return /* @__PURE__ */ jsx50("div", { style: { overflowX: "auto", borderRadius: "0.5rem", border: bordered ? "1px solid #e5e7eb" : "none" }, children: /* @__PURE__ */ jsxs40("table", { style: tableStyles, children: [
|
|
3998
|
+
/* @__PURE__ */ jsx50("thead", { style: theadStyles, children: /* @__PURE__ */ jsx50("tr", { children: columns.map((column) => /* @__PURE__ */ jsx50(
|
|
3660
3999
|
"th",
|
|
3661
4000
|
{
|
|
3662
4001
|
style: {
|
|
@@ -3667,12 +4006,12 @@ function Table({
|
|
|
3667
4006
|
},
|
|
3668
4007
|
column.key
|
|
3669
4008
|
)) }) }),
|
|
3670
|
-
/* @__PURE__ */
|
|
4009
|
+
/* @__PURE__ */ jsx50("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsx50(
|
|
3671
4010
|
"tr",
|
|
3672
4011
|
{
|
|
3673
4012
|
onMouseEnter: () => hoverable && setHoveredRow(rowIndex),
|
|
3674
4013
|
onMouseLeave: () => hoverable && setHoveredRow(null),
|
|
3675
|
-
children: columns.map((column) => /* @__PURE__ */
|
|
4014
|
+
children: columns.map((column) => /* @__PURE__ */ jsx50("td", { style: getTdStyles(rowIndex), children: column.render ? column.render(row) : row[column.key] }, column.key))
|
|
3676
4015
|
},
|
|
3677
4016
|
rowIndex
|
|
3678
4017
|
)) })
|
|
@@ -3681,9 +4020,9 @@ function Table({
|
|
|
3681
4020
|
Table.displayName = "Table";
|
|
3682
4021
|
|
|
3683
4022
|
// src/components/shared/Container.tsx
|
|
3684
|
-
import
|
|
3685
|
-
import { jsx as
|
|
3686
|
-
var Container =
|
|
4023
|
+
import React30 from "react";
|
|
4024
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
4025
|
+
var Container = React30.forwardRef(
|
|
3687
4026
|
({ style, maxWidth = "lg", padding = "md", children, ...props }, ref) => {
|
|
3688
4027
|
const maxWidthStyles = {
|
|
3689
4028
|
sm: "640px",
|
|
@@ -3708,15 +4047,15 @@ var Container = React29.forwardRef(
|
|
|
3708
4047
|
paddingRight: paddingStyles[padding],
|
|
3709
4048
|
...style
|
|
3710
4049
|
};
|
|
3711
|
-
return /* @__PURE__ */
|
|
4050
|
+
return /* @__PURE__ */ jsx51("div", { ref, style: containerStyles, ...props, children });
|
|
3712
4051
|
}
|
|
3713
4052
|
);
|
|
3714
4053
|
Container.displayName = "Container";
|
|
3715
4054
|
|
|
3716
4055
|
// src/components/shared/Grid.tsx
|
|
3717
|
-
import
|
|
3718
|
-
import { jsx as
|
|
3719
|
-
var Grid =
|
|
4056
|
+
import React31 from "react";
|
|
4057
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
4058
|
+
var Grid = React31.forwardRef(
|
|
3720
4059
|
({ style, columns = 3, rows, gap = "md", width = "100%", height = "auto", responsive = true, children, ...props }, ref) => {
|
|
3721
4060
|
const gapStyles = {
|
|
3722
4061
|
none: "0",
|
|
@@ -3734,15 +4073,15 @@ var Grid = React30.forwardRef(
|
|
|
3734
4073
|
height,
|
|
3735
4074
|
...style
|
|
3736
4075
|
};
|
|
3737
|
-
return /* @__PURE__ */
|
|
4076
|
+
return /* @__PURE__ */ jsx52("div", { ref, style: gridStyles, ...props, children });
|
|
3738
4077
|
}
|
|
3739
4078
|
);
|
|
3740
4079
|
Grid.displayName = "Grid";
|
|
3741
4080
|
|
|
3742
4081
|
// src/components/shared/Stack.tsx
|
|
3743
|
-
import
|
|
3744
|
-
import { jsx as
|
|
3745
|
-
var Stack =
|
|
4082
|
+
import React32 from "react";
|
|
4083
|
+
import { jsx as jsx53 } from "react/jsx-runtime";
|
|
4084
|
+
var Stack = React32.forwardRef(
|
|
3746
4085
|
({ style, direction = "vertical", gap = "md", align = "stretch", justify = "start", children, ...props }, ref) => {
|
|
3747
4086
|
const gapStyles = {
|
|
3748
4087
|
none: "0",
|
|
@@ -3772,14 +4111,14 @@ var Stack = React31.forwardRef(
|
|
|
3772
4111
|
justifyContent: justifyStyles[justify],
|
|
3773
4112
|
...style
|
|
3774
4113
|
};
|
|
3775
|
-
return /* @__PURE__ */
|
|
4114
|
+
return /* @__PURE__ */ jsx53("div", { ref, style: stackStyles, ...props, children });
|
|
3776
4115
|
}
|
|
3777
4116
|
);
|
|
3778
4117
|
Stack.displayName = "Stack";
|
|
3779
4118
|
|
|
3780
4119
|
// src/components/shared/Modal.tsx
|
|
3781
|
-
import
|
|
3782
|
-
import { jsx as
|
|
4120
|
+
import React33 from "react";
|
|
4121
|
+
import { jsx as jsx54, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3783
4122
|
var Modal = ({
|
|
3784
4123
|
isOpen,
|
|
3785
4124
|
onClose,
|
|
@@ -3788,7 +4127,7 @@ var Modal = ({
|
|
|
3788
4127
|
size = "md",
|
|
3789
4128
|
closeOnOverlayClick = true
|
|
3790
4129
|
}) => {
|
|
3791
|
-
|
|
4130
|
+
React33.useEffect(() => {
|
|
3792
4131
|
if (isOpen) {
|
|
3793
4132
|
document.body.style.overflow = "hidden";
|
|
3794
4133
|
} else {
|
|
@@ -3857,20 +4196,20 @@ var Modal = ({
|
|
|
3857
4196
|
overflowY: "auto",
|
|
3858
4197
|
flex: 1
|
|
3859
4198
|
};
|
|
3860
|
-
return /* @__PURE__ */
|
|
4199
|
+
return /* @__PURE__ */ jsx54(
|
|
3861
4200
|
"div",
|
|
3862
4201
|
{
|
|
3863
4202
|
style: overlayStyles,
|
|
3864
4203
|
onClick: closeOnOverlayClick ? onClose : void 0,
|
|
3865
|
-
children: /* @__PURE__ */
|
|
4204
|
+
children: /* @__PURE__ */ jsxs41(
|
|
3866
4205
|
"div",
|
|
3867
4206
|
{
|
|
3868
4207
|
style: modalStyles,
|
|
3869
4208
|
onClick: (e) => e.stopPropagation(),
|
|
3870
4209
|
children: [
|
|
3871
|
-
title && /* @__PURE__ */
|
|
3872
|
-
/* @__PURE__ */
|
|
3873
|
-
/* @__PURE__ */
|
|
4210
|
+
title && /* @__PURE__ */ jsxs41("div", { style: headerStyles, children: [
|
|
4211
|
+
/* @__PURE__ */ jsx54("h2", { style: titleStyles, children: title }),
|
|
4212
|
+
/* @__PURE__ */ jsx54(
|
|
3874
4213
|
"button",
|
|
3875
4214
|
{
|
|
3876
4215
|
style: closeButtonStyles,
|
|
@@ -3880,7 +4219,7 @@ var Modal = ({
|
|
|
3880
4219
|
}
|
|
3881
4220
|
)
|
|
3882
4221
|
] }),
|
|
3883
|
-
/* @__PURE__ */
|
|
4222
|
+
/* @__PURE__ */ jsx54("div", { style: contentStyles, children })
|
|
3884
4223
|
]
|
|
3885
4224
|
}
|
|
3886
4225
|
)
|
|
@@ -3891,7 +4230,7 @@ Modal.displayName = "Modal";
|
|
|
3891
4230
|
|
|
3892
4231
|
// src/components/shared/DateRangePicker.tsx
|
|
3893
4232
|
import { useEffect as useEffect15, useMemo as useMemo6, useState as useState23 } from "react";
|
|
3894
|
-
import { jsx as
|
|
4233
|
+
import { jsx as jsx55, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3895
4234
|
var PrimusDateRangePicker = ({
|
|
3896
4235
|
startDate = null,
|
|
3897
4236
|
endDate = null,
|
|
@@ -3927,8 +4266,8 @@ var PrimusDateRangePicker = ({
|
|
|
3927
4266
|
setEnd(nextEnd);
|
|
3928
4267
|
onRangeChange?.({ startDate: nextStart, endDate: nextEnd, label: range.label });
|
|
3929
4268
|
};
|
|
3930
|
-
return /* @__PURE__ */
|
|
3931
|
-
normalizedRanges.length > 0 && /* @__PURE__ */
|
|
4269
|
+
return /* @__PURE__ */ jsxs42("div", { className: "space-y-3", children: [
|
|
4270
|
+
normalizedRanges.length > 0 && /* @__PURE__ */ jsx55("div", { className: "flex flex-wrap gap-2", children: normalizedRanges.map((range) => /* @__PURE__ */ jsx55(
|
|
3932
4271
|
"button",
|
|
3933
4272
|
{
|
|
3934
4273
|
type: "button",
|
|
@@ -3939,8 +4278,8 @@ var PrimusDateRangePicker = ({
|
|
|
3939
4278
|
},
|
|
3940
4279
|
range.label
|
|
3941
4280
|
)) }),
|
|
3942
|
-
/* @__PURE__ */
|
|
3943
|
-
/* @__PURE__ */
|
|
4281
|
+
/* @__PURE__ */ jsxs42("div", { className: "flex flex-col md:flex-row gap-3", children: [
|
|
4282
|
+
/* @__PURE__ */ jsx55(
|
|
3944
4283
|
"input",
|
|
3945
4284
|
{
|
|
3946
4285
|
type: "date",
|
|
@@ -3952,7 +4291,7 @@ var PrimusDateRangePicker = ({
|
|
|
3952
4291
|
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
4292
|
}
|
|
3954
4293
|
),
|
|
3955
|
-
/* @__PURE__ */
|
|
4294
|
+
/* @__PURE__ */ jsx55(
|
|
3956
4295
|
"input",
|
|
3957
4296
|
{
|
|
3958
4297
|
type: "date",
|
|
@@ -4003,7 +4342,7 @@ var toDateInputValue = (value) => {
|
|
|
4003
4342
|
};
|
|
4004
4343
|
|
|
4005
4344
|
// src/components/shared/FilterBar.tsx
|
|
4006
|
-
import { jsx as
|
|
4345
|
+
import { jsx as jsx56, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
4007
4346
|
var PrimusFilterBar = ({
|
|
4008
4347
|
filters,
|
|
4009
4348
|
activeFilters,
|
|
@@ -4017,9 +4356,9 @@ var PrimusFilterBar = ({
|
|
|
4017
4356
|
};
|
|
4018
4357
|
onChange?.(next);
|
|
4019
4358
|
};
|
|
4020
|
-
return /* @__PURE__ */
|
|
4021
|
-
filters.map((filter) => /* @__PURE__ */
|
|
4022
|
-
filter.type === "select" && /* @__PURE__ */
|
|
4359
|
+
return /* @__PURE__ */ jsxs43("div", { className: "flex flex-wrap gap-4 items-end", children: [
|
|
4360
|
+
filters.map((filter) => /* @__PURE__ */ jsxs43("div", { className: "min-w-[220px]", children: [
|
|
4361
|
+
filter.type === "select" && /* @__PURE__ */ jsx56(
|
|
4023
4362
|
Select,
|
|
4024
4363
|
{
|
|
4025
4364
|
label: filter.label,
|
|
@@ -4029,7 +4368,7 @@ var PrimusFilterBar = ({
|
|
|
4029
4368
|
onChange: (value) => updateFilter(filter.key, value)
|
|
4030
4369
|
}
|
|
4031
4370
|
),
|
|
4032
|
-
filter.type === "toggle" && /* @__PURE__ */
|
|
4371
|
+
filter.type === "toggle" && /* @__PURE__ */ jsx56(
|
|
4033
4372
|
Toggle,
|
|
4034
4373
|
{
|
|
4035
4374
|
label: filter.label,
|
|
@@ -4037,7 +4376,7 @@ var PrimusFilterBar = ({
|
|
|
4037
4376
|
onChange: (checked) => updateFilter(filter.key, checked)
|
|
4038
4377
|
}
|
|
4039
4378
|
),
|
|
4040
|
-
filter.type === "search" && /* @__PURE__ */
|
|
4379
|
+
filter.type === "search" && /* @__PURE__ */ jsx56(
|
|
4041
4380
|
Input,
|
|
4042
4381
|
{
|
|
4043
4382
|
label: filter.label,
|
|
@@ -4053,7 +4392,7 @@ var PrimusFilterBar = ({
|
|
|
4053
4392
|
|
|
4054
4393
|
// src/components/shared/ExportMenu.tsx
|
|
4055
4394
|
import { useEffect as useEffect16, useState as useState24 } from "react";
|
|
4056
|
-
import { jsx as
|
|
4395
|
+
import { jsx as jsx57, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
4057
4396
|
var PrimusExportMenu = ({
|
|
4058
4397
|
formats = ["CSV", "PDF", "PNG", "JSON"],
|
|
4059
4398
|
includeCharts = true,
|
|
@@ -4078,29 +4417,29 @@ var PrimusExportMenu = ({
|
|
|
4078
4417
|
includeTables: tables
|
|
4079
4418
|
});
|
|
4080
4419
|
};
|
|
4081
|
-
return /* @__PURE__ */
|
|
4082
|
-
/* @__PURE__ */
|
|
4420
|
+
return /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
4421
|
+
/* @__PURE__ */ jsx57(
|
|
4083
4422
|
"select",
|
|
4084
4423
|
{
|
|
4085
4424
|
value: format,
|
|
4086
4425
|
onChange: (event) => setFormat(event.target.value),
|
|
4087
4426
|
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__ */
|
|
4427
|
+
children: formats.map((item) => /* @__PURE__ */ jsx57("option", { value: item, children: item }, item))
|
|
4089
4428
|
}
|
|
4090
4429
|
),
|
|
4091
|
-
/* @__PURE__ */
|
|
4092
|
-
/* @__PURE__ */
|
|
4430
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4431
|
+
/* @__PURE__ */ jsx57("input", { type: "checkbox", checked: charts, onChange: (e) => setCharts(e.target.checked) }),
|
|
4093
4432
|
"Charts"
|
|
4094
4433
|
] }),
|
|
4095
|
-
/* @__PURE__ */
|
|
4096
|
-
/* @__PURE__ */
|
|
4434
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4435
|
+
/* @__PURE__ */ jsx57("input", { type: "checkbox", checked: stats, onChange: (e) => setStats(e.target.checked) }),
|
|
4097
4436
|
"Stats"
|
|
4098
4437
|
] }),
|
|
4099
|
-
/* @__PURE__ */
|
|
4100
|
-
/* @__PURE__ */
|
|
4438
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4439
|
+
/* @__PURE__ */ jsx57("input", { type: "checkbox", checked: tables, onChange: (e) => setTables(e.target.checked) }),
|
|
4101
4440
|
"Tables"
|
|
4102
4441
|
] }),
|
|
4103
|
-
/* @__PURE__ */
|
|
4442
|
+
/* @__PURE__ */ jsx57(
|
|
4104
4443
|
"button",
|
|
4105
4444
|
{
|
|
4106
4445
|
type: "button",
|
|
@@ -4114,7 +4453,7 @@ var PrimusExportMenu = ({
|
|
|
4114
4453
|
|
|
4115
4454
|
// src/components/shared/Search.tsx
|
|
4116
4455
|
import { useEffect as useEffect17, useMemo as useMemo7, useState as useState25 } from "react";
|
|
4117
|
-
import { jsx as
|
|
4456
|
+
import { jsx as jsx58, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
4118
4457
|
var PrimusSearch = ({
|
|
4119
4458
|
placeholder = "Search...",
|
|
4120
4459
|
debounce = 300,
|
|
@@ -4142,8 +4481,8 @@ var PrimusSearch = ({
|
|
|
4142
4481
|
}
|
|
4143
4482
|
return suggestions.filter((item) => item.toLowerCase().includes(query.toLowerCase())).slice(0, 5);
|
|
4144
4483
|
}, [suggestions, query, showSuggestions]);
|
|
4145
|
-
return /* @__PURE__ */
|
|
4146
|
-
/* @__PURE__ */
|
|
4484
|
+
return /* @__PURE__ */ jsxs45("div", { className: "relative", children: [
|
|
4485
|
+
/* @__PURE__ */ jsx58(
|
|
4147
4486
|
"input",
|
|
4148
4487
|
{
|
|
4149
4488
|
type: "text",
|
|
@@ -4153,7 +4492,7 @@ var PrimusSearch = ({
|
|
|
4153
4492
|
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
4493
|
}
|
|
4155
4494
|
),
|
|
4156
|
-
visibleSuggestions.length > 0 && /* @__PURE__ */
|
|
4495
|
+
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
4496
|
"button",
|
|
4158
4497
|
{
|
|
4159
4498
|
type: "button",
|
|
@@ -4165,6 +4504,304 @@ var PrimusSearch = ({
|
|
|
4165
4504
|
)) })
|
|
4166
4505
|
] });
|
|
4167
4506
|
};
|
|
4507
|
+
|
|
4508
|
+
// src/components/shared/PrimusWizard.tsx
|
|
4509
|
+
import React37, { useState as useState26 } from "react";
|
|
4510
|
+
import { Fragment as Fragment6, jsx as jsx59, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
4511
|
+
var PrimusStep = ({ children }) => {
|
|
4512
|
+
return /* @__PURE__ */ jsx59(Fragment6, { children });
|
|
4513
|
+
};
|
|
4514
|
+
var PrimusStepper = ({ steps, currentStep }) => {
|
|
4515
|
+
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: [
|
|
4516
|
+
/* @__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" }) }) }),
|
|
4517
|
+
/* @__PURE__ */ jsx59("span", { className: "ml-4 text-sm font-medium", children: step.label })
|
|
4518
|
+
] }) }) : 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: [
|
|
4519
|
+
/* @__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 }) }),
|
|
4520
|
+
/* @__PURE__ */ jsx59("span", { className: "ml-4 text-sm font-medium text-gray-900 dark:text-white", children: step.label })
|
|
4521
|
+
] }) }) : /* @__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: [
|
|
4522
|
+
/* @__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 }) }),
|
|
4523
|
+
/* @__PURE__ */ jsx59("span", { className: "ml-4", children: step.label })
|
|
4524
|
+
] }) }) }, step.label)) }) });
|
|
4525
|
+
};
|
|
4526
|
+
var PrimusWizard = ({
|
|
4527
|
+
title,
|
|
4528
|
+
subtitle,
|
|
4529
|
+
children,
|
|
4530
|
+
onComplete,
|
|
4531
|
+
className,
|
|
4532
|
+
startStep = 0
|
|
4533
|
+
}) => {
|
|
4534
|
+
const [currentStep, setCurrentStep] = useState26(startStep);
|
|
4535
|
+
const steps = React37.Children.toArray(children).filter(
|
|
4536
|
+
(child) => React37.isValidElement(child) && (child.type === PrimusStep || child.type.name === "PrimusStep")
|
|
4537
|
+
);
|
|
4538
|
+
const totalSteps = steps.length;
|
|
4539
|
+
const isFirstStep = currentStep === 0;
|
|
4540
|
+
const isLastStep = currentStep === totalSteps - 1;
|
|
4541
|
+
const handleNext = () => {
|
|
4542
|
+
if (isLastStep) {
|
|
4543
|
+
onComplete?.();
|
|
4544
|
+
} else {
|
|
4545
|
+
setCurrentStep((prev) => prev + 1);
|
|
4546
|
+
}
|
|
4547
|
+
};
|
|
4548
|
+
const handleBack = () => {
|
|
4549
|
+
if (!isFirstStep) {
|
|
4550
|
+
setCurrentStep((prev) => prev - 1);
|
|
4551
|
+
}
|
|
4552
|
+
};
|
|
4553
|
+
if (totalSteps === 0) {
|
|
4554
|
+
return /* @__PURE__ */ jsx59("div", { className: "text-red-500", children: "Error: PrimusWizard requires PrimusStep children" });
|
|
4555
|
+
}
|
|
4556
|
+
const currentStepConfig = steps[currentStep].props;
|
|
4557
|
+
return /* @__PURE__ */ jsxs46("div", { className: `space-y-6 ${className}`, children: [
|
|
4558
|
+
/* @__PURE__ */ jsxs46("div", { children: [
|
|
4559
|
+
title && /* @__PURE__ */ jsx59("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: title }),
|
|
4560
|
+
subtitle && /* @__PURE__ */ jsx59("p", { className: "mt-1 text-gray-500 dark:text-gray-400", children: subtitle })
|
|
4561
|
+
] }),
|
|
4562
|
+
/* @__PURE__ */ jsx59(
|
|
4563
|
+
PrimusStepper,
|
|
4564
|
+
{
|
|
4565
|
+
steps: steps.map((s) => ({ label: s.props.label, description: s.props.description })),
|
|
4566
|
+
currentStep
|
|
4567
|
+
}
|
|
4568
|
+
),
|
|
4569
|
+
/* @__PURE__ */ jsxs46(Card, { className: "p-6 min-h-[300px]", children: [
|
|
4570
|
+
/* @__PURE__ */ jsx59("div", { className: "mb-8", children: steps[currentStep] }),
|
|
4571
|
+
/* @__PURE__ */ jsxs46("div", { className: "flex justify-between pt-6 border-t border-gray-100 dark:border-gray-800", children: [
|
|
4572
|
+
/* @__PURE__ */ jsx59(
|
|
4573
|
+
Button,
|
|
4574
|
+
{
|
|
4575
|
+
variant: "ghost",
|
|
4576
|
+
onClick: handleBack,
|
|
4577
|
+
disabled: isFirstStep,
|
|
4578
|
+
children: "Back"
|
|
4579
|
+
}
|
|
4580
|
+
),
|
|
4581
|
+
/* @__PURE__ */ jsx59(
|
|
4582
|
+
Button,
|
|
4583
|
+
{
|
|
4584
|
+
onClick: handleNext,
|
|
4585
|
+
disabled: currentStepConfig.isValid === false,
|
|
4586
|
+
children: isLastStep ? "Complete" : "Next"
|
|
4587
|
+
}
|
|
4588
|
+
)
|
|
4589
|
+
] })
|
|
4590
|
+
] })
|
|
4591
|
+
] });
|
|
4592
|
+
};
|
|
4593
|
+
|
|
4594
|
+
// src/components/shared/Field.tsx
|
|
4595
|
+
import React38 from "react";
|
|
4596
|
+
import { clsx as clsx8 } from "clsx";
|
|
4597
|
+
import { ExclamationCircleIcon } from "@heroicons/react/20/solid";
|
|
4598
|
+
import { jsx as jsx60, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
4599
|
+
var FieldContext = React38.createContext(void 0);
|
|
4600
|
+
var useFieldContext = () => React38.useContext(FieldContext);
|
|
4601
|
+
var Field = ({ children, error, disabled, dense, className, ...props }) => {
|
|
4602
|
+
const id = React38.useId();
|
|
4603
|
+
return /* @__PURE__ */ jsx60(FieldContext.Provider, { value: { id, error, disabled }, children: /* @__PURE__ */ jsx60(
|
|
4604
|
+
"div",
|
|
4605
|
+
{
|
|
4606
|
+
className: clsx8(
|
|
4607
|
+
"flex flex-col w-full",
|
|
4608
|
+
dense ? "gap-1" : "gap-1.5",
|
|
4609
|
+
className
|
|
4610
|
+
),
|
|
4611
|
+
...props,
|
|
4612
|
+
children
|
|
4613
|
+
}
|
|
4614
|
+
) });
|
|
4615
|
+
};
|
|
4616
|
+
var Label = ({ className, children, required, indicator, ...props }) => {
|
|
4617
|
+
const context = useFieldContext();
|
|
4618
|
+
return /* @__PURE__ */ jsxs47(
|
|
4619
|
+
"label",
|
|
4620
|
+
{
|
|
4621
|
+
htmlFor: context?.id,
|
|
4622
|
+
className: clsx8(
|
|
4623
|
+
"block text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
4624
|
+
context?.disabled ? "text-gray-400 opacity-70" : "text-gray-700",
|
|
4625
|
+
props.onClick ? "cursor-pointer" : "cursor-default",
|
|
4626
|
+
className
|
|
4627
|
+
),
|
|
4628
|
+
...props,
|
|
4629
|
+
children: [
|
|
4630
|
+
children,
|
|
4631
|
+
required && /* @__PURE__ */ jsx60("span", { className: "ml-0.5 text-red-500", children: "*" }),
|
|
4632
|
+
indicator
|
|
4633
|
+
]
|
|
4634
|
+
}
|
|
4635
|
+
);
|
|
4636
|
+
};
|
|
4637
|
+
var FieldDescription = ({ className, children, ...props }) => {
|
|
4638
|
+
const context = useFieldContext();
|
|
4639
|
+
return /* @__PURE__ */ jsx60(
|
|
4640
|
+
"p",
|
|
4641
|
+
{
|
|
4642
|
+
className: clsx8(
|
|
4643
|
+
"text-[0.8rem] text-muted-foreground text-gray-500",
|
|
4644
|
+
context?.disabled && "opacity-70",
|
|
4645
|
+
className
|
|
4646
|
+
),
|
|
4647
|
+
...props,
|
|
4648
|
+
children
|
|
4649
|
+
}
|
|
4650
|
+
);
|
|
4651
|
+
};
|
|
4652
|
+
var FieldError = ({ className, children, forceVisible, ...props }) => {
|
|
4653
|
+
const context = useFieldContext();
|
|
4654
|
+
const error = context?.error || children;
|
|
4655
|
+
if (!error && !forceVisible) return null;
|
|
4656
|
+
return /* @__PURE__ */ jsxs47(
|
|
4657
|
+
"p",
|
|
4658
|
+
{
|
|
4659
|
+
className: clsx8(
|
|
4660
|
+
"text-[0.8rem] font-medium text-red-500 flex items-center gap-1.5 animate-in slide-in-from-top-1 fade-in-50",
|
|
4661
|
+
className
|
|
4662
|
+
),
|
|
4663
|
+
...props,
|
|
4664
|
+
children: [
|
|
4665
|
+
/* @__PURE__ */ jsx60(ExclamationCircleIcon, { className: "h-4 w-4 shrink-0" }),
|
|
4666
|
+
error
|
|
4667
|
+
]
|
|
4668
|
+
}
|
|
4669
|
+
);
|
|
4670
|
+
};
|
|
4671
|
+
|
|
4672
|
+
// src/components/shared/InputGroup.tsx
|
|
4673
|
+
import React39 from "react";
|
|
4674
|
+
import { clsx as clsx9 } from "clsx";
|
|
4675
|
+
import { jsx as jsx61 } from "react/jsx-runtime";
|
|
4676
|
+
var InputGroup = ({ className, children, size = "md", ...props }) => {
|
|
4677
|
+
return /* @__PURE__ */ jsx61(
|
|
4678
|
+
"div",
|
|
4679
|
+
{
|
|
4680
|
+
className: clsx9(
|
|
4681
|
+
"flex items-stretch w-full rounded-lg shadow-sm",
|
|
4682
|
+
// Target direct children to remove borders and rounded corners where they touch
|
|
4683
|
+
"[&>*:first-child]:rounded-r-none",
|
|
4684
|
+
"[&>*:last-child]:rounded-l-none",
|
|
4685
|
+
"[&>*:not(:first-child):not(:last-child)]:rounded-none",
|
|
4686
|
+
// Handle borders to prevent double borders
|
|
4687
|
+
"[&>*:not(:first-child)]:-ml-px",
|
|
4688
|
+
// Ensure z-index handling for focus rings
|
|
4689
|
+
"[&>*:focus-within]:z-10",
|
|
4690
|
+
className
|
|
4691
|
+
),
|
|
4692
|
+
...props,
|
|
4693
|
+
children: React39.Children.map(children, (child) => {
|
|
4694
|
+
if (React39.isValidElement(child)) {
|
|
4695
|
+
return React39.cloneElement(child, { size });
|
|
4696
|
+
}
|
|
4697
|
+
return child;
|
|
4698
|
+
})
|
|
4699
|
+
}
|
|
4700
|
+
);
|
|
4701
|
+
};
|
|
4702
|
+
var InputAddon = ({ className, children, ...props }) => {
|
|
4703
|
+
return /* @__PURE__ */ jsx61(
|
|
4704
|
+
"div",
|
|
4705
|
+
{
|
|
4706
|
+
className: clsx9(
|
|
4707
|
+
"flex items-center px-3 border border-gray-200 bg-gray-50 text-gray-500 text-sm whitespace-nowrap",
|
|
4708
|
+
// These will be overridden by the group's first/last child selectors usually, but good defaults:
|
|
4709
|
+
"first:rounded-l-lg last:rounded-r-lg",
|
|
4710
|
+
className
|
|
4711
|
+
),
|
|
4712
|
+
...props,
|
|
4713
|
+
children
|
|
4714
|
+
}
|
|
4715
|
+
);
|
|
4716
|
+
};
|
|
4717
|
+
|
|
4718
|
+
// src/components/shared/PasswordInput.tsx
|
|
4719
|
+
import React40, { useState as useState27 } from "react";
|
|
4720
|
+
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/20/solid";
|
|
4721
|
+
import { jsx as jsx62, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4722
|
+
var PasswordInput = React40.forwardRef(
|
|
4723
|
+
(props, ref) => {
|
|
4724
|
+
const [showPassword, setShowPassword] = useState27(false);
|
|
4725
|
+
const toggleVisibility = () => {
|
|
4726
|
+
setShowPassword(!showPassword);
|
|
4727
|
+
};
|
|
4728
|
+
return /* @__PURE__ */ jsx62(
|
|
4729
|
+
Input,
|
|
4730
|
+
{
|
|
4731
|
+
ref,
|
|
4732
|
+
type: showPassword ? "text" : "password",
|
|
4733
|
+
endIcon: /* @__PURE__ */ jsxs48(
|
|
4734
|
+
"button",
|
|
4735
|
+
{
|
|
4736
|
+
type: "button",
|
|
4737
|
+
onClick: toggleVisibility,
|
|
4738
|
+
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",
|
|
4739
|
+
tabIndex: -1,
|
|
4740
|
+
children: [
|
|
4741
|
+
showPassword ? /* @__PURE__ */ jsx62(EyeSlashIcon, { className: "h-4 w-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx62(EyeIcon, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
4742
|
+
/* @__PURE__ */ jsx62("span", { className: "sr-only", children: showPassword ? "Hide password" : "Show password" })
|
|
4743
|
+
]
|
|
4744
|
+
}
|
|
4745
|
+
),
|
|
4746
|
+
...props
|
|
4747
|
+
}
|
|
4748
|
+
);
|
|
4749
|
+
}
|
|
4750
|
+
);
|
|
4751
|
+
PasswordInput.displayName = "PasswordInput";
|
|
4752
|
+
|
|
4753
|
+
// src/components/shared/SearchInput.tsx
|
|
4754
|
+
import React41, { useState as useState28, useEffect as useEffect18 } from "react";
|
|
4755
|
+
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
|
|
4756
|
+
import { jsx as jsx63 } from "react/jsx-runtime";
|
|
4757
|
+
var SearchInput = React41.forwardRef(
|
|
4758
|
+
({ value, onSearch, debounceMs = 300, className, ...props }, ref) => {
|
|
4759
|
+
const [localValue, setLocalValue] = useState28(value || "");
|
|
4760
|
+
const [isDebouncing, setIsDebouncing] = useState28(false);
|
|
4761
|
+
useEffect18(() => {
|
|
4762
|
+
if (value !== void 0) {
|
|
4763
|
+
setLocalValue(value);
|
|
4764
|
+
}
|
|
4765
|
+
}, [value]);
|
|
4766
|
+
useEffect18(() => {
|
|
4767
|
+
if (debounceMs === 0) {
|
|
4768
|
+
onSearch?.(localValue);
|
|
4769
|
+
return;
|
|
4770
|
+
}
|
|
4771
|
+
const handler = setTimeout(() => {
|
|
4772
|
+
onSearch?.(localValue);
|
|
4773
|
+
setIsDebouncing(false);
|
|
4774
|
+
}, debounceMs);
|
|
4775
|
+
return () => {
|
|
4776
|
+
clearTimeout(handler);
|
|
4777
|
+
};
|
|
4778
|
+
}, [localValue, debounceMs]);
|
|
4779
|
+
const handleChange = (e) => {
|
|
4780
|
+
const newVal = e.target.value;
|
|
4781
|
+
setLocalValue(newVal);
|
|
4782
|
+
if (debounceMs > 0) setIsDebouncing(true);
|
|
4783
|
+
};
|
|
4784
|
+
const handleClear = () => {
|
|
4785
|
+
setLocalValue("");
|
|
4786
|
+
props.onClear?.();
|
|
4787
|
+
};
|
|
4788
|
+
return /* @__PURE__ */ jsx63(
|
|
4789
|
+
Input,
|
|
4790
|
+
{
|
|
4791
|
+
ref,
|
|
4792
|
+
type: "text",
|
|
4793
|
+
startIcon: /* @__PURE__ */ jsx63(MagnifyingGlassIcon, { className: "h-4 w-4" }),
|
|
4794
|
+
value: localValue,
|
|
4795
|
+
onChange: handleChange,
|
|
4796
|
+
onClear: handleClear,
|
|
4797
|
+
loading: props.loading || props.loading === void 0 && isDebouncing,
|
|
4798
|
+
className,
|
|
4799
|
+
...props
|
|
4800
|
+
}
|
|
4801
|
+
);
|
|
4802
|
+
}
|
|
4803
|
+
);
|
|
4804
|
+
SearchInput.displayName = "SearchInput";
|
|
4168
4805
|
export {
|
|
4169
4806
|
AICopilot,
|
|
4170
4807
|
AccountDashboard,
|
|
@@ -4181,17 +4818,24 @@ export {
|
|
|
4181
4818
|
DashboardGrid,
|
|
4182
4819
|
DocumentViewer,
|
|
4183
4820
|
FeatureFlagToggle,
|
|
4821
|
+
Field,
|
|
4822
|
+
FieldDescription,
|
|
4823
|
+
FieldError,
|
|
4184
4824
|
FileUploader,
|
|
4185
4825
|
FraudDetectionDashboard,
|
|
4186
4826
|
Grid,
|
|
4187
4827
|
Input,
|
|
4828
|
+
InputAddon,
|
|
4829
|
+
InputGroup,
|
|
4188
4830
|
KYCVerification,
|
|
4831
|
+
Label,
|
|
4189
4832
|
LoanCalculator,
|
|
4190
4833
|
LogViewer,
|
|
4191
4834
|
LoginPage,
|
|
4192
4835
|
Modal,
|
|
4193
4836
|
NotificationBell,
|
|
4194
4837
|
PrimusNotificationFeed as NotificationFeed,
|
|
4838
|
+
PasswordInput,
|
|
4195
4839
|
PolicyCard,
|
|
4196
4840
|
PremiumCalculator,
|
|
4197
4841
|
PrimusActivityFeed,
|
|
@@ -4207,10 +4851,16 @@ export {
|
|
|
4207
4851
|
PrimusDataTable,
|
|
4208
4852
|
PrimusDateRangePicker,
|
|
4209
4853
|
PrimusExportMenu,
|
|
4854
|
+
Field as PrimusField,
|
|
4855
|
+
FieldDescription as PrimusFieldDescription,
|
|
4856
|
+
FieldError as PrimusFieldError,
|
|
4210
4857
|
PrimusFilterBar,
|
|
4211
4858
|
Grid as PrimusGrid,
|
|
4212
4859
|
PrimusHeader,
|
|
4213
4860
|
Input as PrimusInput,
|
|
4861
|
+
InputAddon as PrimusInputAddon,
|
|
4862
|
+
InputGroup as PrimusInputGroup,
|
|
4863
|
+
Label as PrimusLabel,
|
|
4214
4864
|
PrimusLayout,
|
|
4215
4865
|
PrimusLineChart,
|
|
4216
4866
|
PrimusLogin,
|
|
@@ -4219,22 +4869,31 @@ export {
|
|
|
4219
4869
|
PrimusNotificationCenter,
|
|
4220
4870
|
PrimusNotificationFeed,
|
|
4221
4871
|
PrimusNotifications,
|
|
4872
|
+
PasswordInput as PrimusPasswordInput,
|
|
4222
4873
|
PrimusPieChart,
|
|
4223
4874
|
PrimusProvider,
|
|
4224
4875
|
RadioGroup as PrimusRadioGroup,
|
|
4225
4876
|
PrimusSearch,
|
|
4877
|
+
SearchInput as PrimusSearchInput,
|
|
4878
|
+
PrimusSection,
|
|
4226
4879
|
Select as PrimusSelect,
|
|
4227
4880
|
PrimusSidebar,
|
|
4228
4881
|
PrimusSparkline,
|
|
4229
4882
|
Stack as PrimusStack,
|
|
4230
4883
|
PrimusStatCard,
|
|
4884
|
+
PrimusStatCard as PrimusStatsCard,
|
|
4885
|
+
PrimusStep,
|
|
4886
|
+
PrimusStepper,
|
|
4887
|
+
PrimusSummaryCard,
|
|
4231
4888
|
Table as PrimusTable,
|
|
4232
4889
|
Textarea as PrimusTextarea,
|
|
4233
4890
|
PrimusThemeProvider,
|
|
4234
4891
|
PrimusThemeToggle,
|
|
4235
4892
|
Toggle as PrimusToggle,
|
|
4893
|
+
PrimusWizard,
|
|
4236
4894
|
QuoteComparison,
|
|
4237
4895
|
RadioGroup,
|
|
4896
|
+
SearchInput,
|
|
4238
4897
|
SecurityDashboard,
|
|
4239
4898
|
Select,
|
|
4240
4899
|
Stack,
|
|
@@ -4246,6 +4905,7 @@ export {
|
|
|
4246
4905
|
themeColors,
|
|
4247
4906
|
useNotifications,
|
|
4248
4907
|
usePrimusAuth,
|
|
4908
|
+
usePrimusFetch,
|
|
4249
4909
|
usePrimusTheme,
|
|
4250
4910
|
useRealtimeNotifications
|
|
4251
4911
|
};
|