@ollaid/native-sso 1.0.4 → 1.0.6

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 CHANGED
@@ -105,9 +105,79 @@ La page `/auth/sso` gère automatiquement :
105
105
  | `logoUrl` | `string` | ❌ | URL du logo (remplace le slider) |
106
106
  | `hideFooter` | `boolean` | ❌ | Masquer "Propulsé par iam.ollaid.com" |
107
107
  | `onOnboardingComplete` | `(data: { image_url?: string; ccphone?: string; phone?: string }) => void` | ❌ | Callback après complétion de l'onboarding |
108
+ | `redirectAfterLogin` | `string` | ❌ | Route vers laquelle rediriger après connexion réussie (ex: `/client/dashboard`). Utilise `window.location.href`. Compatible avec ou sans react-router. |
109
+ | `redirectAfterLogout` | `string` | ❌ | Route vers laquelle rediriger après déconnexion (ex: `/auth/client`). Utilise `window.location.href`. |
108
110
 
109
111
  > **Note :** Le mode `debug` est contrôlé **uniquement** par le backend via la variable d'environnement `IAM_DEBUG` dans le `.env` du SaaS. Il n'y a plus de prop `debug` à passer au composant. Le `DebugPanel` est **réactif** : il apparaît automatiquement après le chargement des credentials si `debug: true` est retourné par le backend.
110
112
 
113
+ ### Redirections automatiques (optionnel)
114
+
115
+ > **Ces props sont entièrement optionnels.** Si vous ne les définissez pas,
116
+ > c'est votre backend SaaS qui gère la redirection après l'exchange — il connaît
117
+ > déjà le `accountType` et peut rediriger l'utilisateur vers la bonne page après
118
+ > avoir sauvegardé le token dans le localStorage.
119
+
120
+ Utilisez ces props uniquement si vous souhaitez que le **composant lui-même**
121
+ déclenche la redirection côté frontend :
122
+
123
+ ```tsx
124
+ <NativeSSOPage
125
+ saasApiUrl="https://votre-saas.com/api"
126
+ iamApiUrl="https://identityam.ollaid.com/api"
127
+ configPrefix="iam_client"
128
+ accountType="client"
129
+ redirectAfterLogin="/client/dashboard"
130
+ redirectAfterLogout="/auth/client"
131
+ />
132
+ ```
133
+
134
+ **Sans ces props** (usage minimal, le SaaS gère la redirection) :
135
+
136
+ ```tsx
137
+ <NativeSSOPage
138
+ saasApiUrl="https://votre-saas.com/api"
139
+ iamApiUrl="https://identityam.ollaid.com/api"
140
+ configPrefix="iam_client"
141
+ accountType="client"
142
+ onLoginSuccess={(token, user) => { /* votre logique */ }}
143
+ />
144
+ ```
145
+
146
+ **Comportement :**
147
+ - Si `redirectAfterLogin` est défini → redirection via `window.location.href` après connexion
148
+ - Si `onLoginSuccess` est aussi défini → le callback est appelé **avant** la redirection
149
+ - Si **aucun** prop de redirection n'est défini → aucune redirection automatique, comportement inchangé
150
+
151
+ ---
152
+
153
+ ## Déconnexion externe (sans le composant)
154
+
155
+ Quand l'utilisateur se déconnecte **depuis votre SaaS** (ex : bouton logout dans le backoffice), le composant `NativeSSOPage` n'est pas impliqué. Vous devez donc nettoyer manuellement la session SSO pour éviter que le package considère l'utilisateur comme encore connecté.
156
+
157
+ ### Utilisation
158
+
159
+ ```tsx
160
+ import { clearAuthToken } from '@ollaid/native-sso';
161
+
162
+ const handleLogout = async () => {
163
+ await revokeBackendToken(); // votre logique SaaS (révocation Sanctum, etc.)
164
+ clearAuthToken(); // nettoie les 5 clés localStorage du package
165
+ navigate('/auth/login');
166
+ };
167
+ ```
168
+
169
+ ### Clés localStorage nettoyées par `clearAuthToken()`
170
+
171
+ | Clé | Description |
172
+ |-----|-------------|
173
+ | `auth_token` | Token Sanctum actif |
174
+ | `token` | Token legacy |
175
+ | `user` | Objet utilisateur (avec `iam_reference`, `alias_reference`) |
176
+ | `account_type` | Type de compte (`user` ou `client`) |
177
+ | `alias_reference` | Référence de l'alias de connexion |
178
+
179
+ > **Important :** Si vous ne nettoyez pas ces clés, l'utilisateur verra l'écran "Déconnexion" au lieu du formulaire de connexion en revenant sur la page SSO.
180
+
111
181
  ---
112
182
 
113
183
  ## Multi-Tenant (plusieurs applications sur le même backend)
@@ -136,6 +206,8 @@ Backend SaaS:
136
206
  iamApiUrl="https://identityam.ollaid.com/api"
137
207
  configPrefix="iam"
138
208
  accountType="user"
209
+ redirectAfterLogin="/dashboard"
210
+ redirectAfterLogout="/auth/sso"
139
211
  />
140
212
 
141
213
  {/* Page login espace vendeur */}
@@ -144,6 +216,8 @@ Backend SaaS:
144
216
  iamApiUrl="https://identityam.ollaid.com/api"
145
217
  configPrefix="iam_vendor"
146
218
  accountType="client"
219
+ redirectAfterLogin="/vendor/dashboard"
220
+ redirectAfterLogout="/auth/vendor"
147
221
  />
148
222
 
149
223
  {/* Page login admin — même backend, app IAM différente */}
@@ -152,6 +226,8 @@ Backend SaaS:
152
226
  iamApiUrl="https://identityam.ollaid.com/api"
153
227
  configPrefix="iam_admin"
154
228
  accountType="user"
229
+ redirectAfterLogin="/admin/dashboard"
230
+ redirectAfterLogout="/auth/admin"
155
231
  />
156
232
  ```
157
233
 
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * Apps Logo Slider for @ollaid/native-sso
3
+ * Matches Web SSO badge style: horizontal marquee, small icons, no app names
3
4
  */
4
5
  interface AppsLogoSliderProps {
5
6
  speed?: 'slow' | 'normal' | 'fast';
6
7
  className?: string;
7
8
  iamApiUrl?: string;
8
9
  }
9
- export declare function AppsLogoSlider({ speed, className, iamApiUrl: iamApiUrlProp }: AppsLogoSliderProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export declare function AppsLogoSlider({ className, iamApiUrl: iamApiUrlProp }: AppsLogoSliderProps): import("react/jsx-runtime").JSX.Element | null;
10
11
  export default AppsLogoSlider;
@@ -2,42 +2,26 @@
2
2
  * NativeSSOPage — Page autonome complète pour @ollaid/native-sso
3
3
  * Design aligné sur /sso/auth (fond primary, card blanche, ShieldCheck branding)
4
4
  *
5
- * @version 1.0.0
5
+ * @version 2.0.0
6
6
  */
7
7
  import type { UserInfos } from '../types/native';
8
8
  export interface NativeSSOPageProps {
9
- /** URL du Backend SaaS */
10
9
  saasApiUrl: string;
11
- /** URL du Backend IAM */
12
10
  iamApiUrl: string;
13
- /** Callback après login/signup réussi — reçoit le token et l'utilisateur */
14
11
  onLoginSuccess?: (token: string, user: UserInfos) => void;
15
- /** Callback après logout */
16
12
  onLogout?: () => void;
17
- /** Callback quand l'utilisateur complète l'onboarding (photo/phone) */
18
13
  onOnboardingComplete?: (data: {
19
14
  image_url?: string;
20
15
  ccphone?: string;
21
16
  phone?: string;
22
17
  }) => void;
23
- /** Type de compte à persister dans localStorage (défaut: 'user') */
24
18
  accountType?: 'user' | 'client';
25
- /**
26
- * Préfixe de configuration IAM côté backend (défaut: 'iam').
27
- * Permet le multi-tenant : 'iam', 'iam_vendor', 'iam_client', 'iam_admin', etc.
28
- */
29
19
  configPrefix?: string;
30
- /** Titre personnalisé */
31
20
  title?: string;
32
- /** Description personnalisée */
33
21
  description?: string;
34
- /** Logo URL personnalisé */
35
22
  logoUrl?: string;
36
- /** Masquer le footer "Propulsé par" */
37
23
  hideFooter?: boolean;
38
- /** Route vers laquelle rediriger après un login réussi (via window.location.href) */
39
24
  redirectAfterLogin?: string;
40
- /** Route vers laquelle rediriger après un logout (via window.location.href) */
41
25
  redirectAfterLogout?: string;
42
26
  }
43
27
  export declare function NativeSSOPage({ saasApiUrl, iamApiUrl, onLoginSuccess, onLogout, onOnboardingComplete, accountType, configPrefix, title, description, logoUrl, hideFooter, redirectAfterLogin, redirectAfterLogout, }: NativeSSOPageProps): import("react/jsx-runtime").JSX.Element;
package/dist/index.cjs CHANGED
@@ -2954,12 +2954,9 @@ function PhoneInput({
2954
2954
  ] })
2955
2955
  ] });
2956
2956
  }
2957
- function AppsLogoSlider({ speed = "normal", className = "", iamApiUrl: iamApiUrlProp }) {
2958
- const scrollRef = react.useRef(null);
2959
- const [isPaused, setIsPaused] = react.useState(false);
2957
+ function AppsLogoSlider({ className = "", iamApiUrl: iamApiUrlProp }) {
2960
2958
  const [applications, setApplications] = react.useState([]);
2961
2959
  const [isLoading, setIsLoading] = react.useState(true);
2962
- const speedMap = { slow: 50, normal: 30, fast: 15 };
2963
2960
  react.useEffect(() => {
2964
2961
  const resolvedIamApiUrl = iamApiUrlProp || getNativeAuthConfig().iamApiUrl;
2965
2962
  if (!resolvedIamApiUrl) return;
@@ -2978,19 +2975,6 @@ function AppsLogoSlider({ speed = "normal", className = "", iamApiUrl: iamApiUrl
2978
2975
  };
2979
2976
  fetchApps();
2980
2977
  }, [iamApiUrlProp]);
2981
- react.useEffect(() => {
2982
- const container = scrollRef.current;
2983
- if (!container || applications.length === 0) return;
2984
- let pos = 0;
2985
- const id = setInterval(() => {
2986
- if (!isPaused && container) {
2987
- pos += 1;
2988
- if (pos >= container.scrollWidth / 2) pos = 0;
2989
- container.scrollLeft = pos;
2990
- }
2991
- }, speedMap[speed]);
2992
- return () => clearInterval(id);
2993
- }, [isPaused, speed, applications.length]);
2994
2978
  const getLogoUrl = (logo) => {
2995
2979
  if (!logo) return null;
2996
2980
  if (logo.startsWith("http")) return logo;
@@ -2998,27 +2982,85 @@ function AppsLogoSlider({ speed = "normal", className = "", iamApiUrl: iamApiUrl
2998
2982
  return `${resolvedUrl.replace("/api", "")}/storage/applications/${logo}`;
2999
2983
  };
3000
2984
  if (isLoading) {
3001
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: "1rem", padding: "0.5rem 0" }, children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flexShrink: 0, display: "flex", flexDirection: "column", alignItems: "center", gap: "0.5rem" }, children: [
3002
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "3rem", height: "3rem", borderRadius: "0.75rem", backgroundColor: "#e5e7eb" } }),
3003
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "2.5rem", height: "0.75rem", borderRadius: "0.25rem", backgroundColor: "#e5e7eb" } })
3004
- ] }, i)) }) });
2985
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: "0.75rem", padding: "0 0.75rem" }, children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "2rem", height: "2rem", borderRadius: "0.5rem", backgroundColor: "#e5e7eb", flexShrink: 0 } }, i)) }) });
3005
2986
  }
3006
2987
  if (applications.length === 0) return null;
3007
- const displayApps = [...applications, ...applications];
3008
- return /* @__PURE__ */ jsxRuntime.jsx(
2988
+ const displayApps = [...applications, ...applications, ...applications];
2989
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3009
2990
  "div",
3010
2991
  {
3011
2992
  className,
3012
- style: { position: "relative", overflow: "hidden" },
3013
- onMouseEnter: () => setIsPaused(true),
3014
- onMouseLeave: () => setIsPaused(false),
3015
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, style: { display: "flex", gap: "1rem", overflow: "hidden", padding: "0.5rem 0" }, children: displayApps.map((app, index) => {
3016
- const logoUrl = getLogoUrl(app.logo);
3017
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flexShrink: 0, display: "flex", flexDirection: "column", alignItems: "center", gap: "0.5rem" }, children: [
3018
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "3rem", height: "3rem", borderRadius: "0.75rem", display: "flex", alignItems: "center", justifyContent: "center", boxShadow: "0 1px 3px rgba(0,0,0,0.1)", backgroundColor: "white", border: "1px solid #f3f4f6" }, children: logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: app.name, style: { width: "2.5rem", height: "2.5rem", objectFit: "contain", borderRadius: "0.5rem" } }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 700, fontSize: "1.125rem", color: "hsl(var(--primary, 222 47% 11%))" }, children: app.name.charAt(0).toUpperCase() }) }),
3019
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", color: "#6b7280", fontWeight: 500 }, children: app.name })
3020
- ] }, `${app.id}-${index}`);
3021
- }) })
2993
+ style: { position: "relative", width: "100%", height: "100%", overflow: "hidden" },
2994
+ children: [
2995
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
2996
+ position: "absolute",
2997
+ left: 0,
2998
+ top: 0,
2999
+ bottom: 0,
3000
+ width: "1.5rem",
3001
+ background: "linear-gradient(to right, #ffffff, transparent)",
3002
+ zIndex: 10,
3003
+ pointerEvents: "none"
3004
+ } }),
3005
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3006
+ display: "flex",
3007
+ animation: "ollaid-marquee 20s linear infinite",
3008
+ height: "100%",
3009
+ alignItems: "center"
3010
+ }, children: displayApps.map((app, index) => {
3011
+ var _a, _b;
3012
+ const logoUrl = getLogoUrl(app.logo);
3013
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3014
+ "div",
3015
+ {
3016
+ style: { flexShrink: 0, padding: "0 0.75rem", display: "flex", alignItems: "center", height: "100%" },
3017
+ children: [
3018
+ logoUrl ? /* @__PURE__ */ jsxRuntime.jsx(
3019
+ "img",
3020
+ {
3021
+ src: logoUrl,
3022
+ alt: app.name,
3023
+ style: { width: "2rem", height: "2rem", objectFit: "contain" },
3024
+ onError: (e) => {
3025
+ const target = e.currentTarget;
3026
+ target.style.display = "none";
3027
+ if (target.nextElementSibling) {
3028
+ target.nextElementSibling.style.display = "flex";
3029
+ }
3030
+ }
3031
+ }
3032
+ ) : null,
3033
+ /* @__PURE__ */ jsxRuntime.jsx(
3034
+ "div",
3035
+ {
3036
+ style: {
3037
+ width: "2rem",
3038
+ height: "2rem",
3039
+ borderRadius: "0.5rem",
3040
+ backgroundColor: "#f3f4f6",
3041
+ alignItems: "center",
3042
+ justifyContent: "center",
3043
+ display: logoUrl ? "none" : "flex"
3044
+ },
3045
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", fontWeight: 700, color: "#6b7280" }, children: ((_b = (_a = app.name) == null ? void 0 : _a.charAt(0)) == null ? void 0 : _b.toUpperCase()) || "A" })
3046
+ }
3047
+ )
3048
+ ]
3049
+ },
3050
+ `${app.id}-${index}`
3051
+ );
3052
+ }) }),
3053
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3054
+ position: "absolute",
3055
+ right: 0,
3056
+ top: 0,
3057
+ bottom: 0,
3058
+ width: "1.5rem",
3059
+ background: "linear-gradient(to left, #ffffff, transparent)",
3060
+ zIndex: 10,
3061
+ pointerEvents: "none"
3062
+ } })
3063
+ ]
3022
3064
  }
3023
3065
  );
3024
3066
  }
@@ -4101,8 +4143,10 @@ function DebugPanel({ saasApiUrl, iamApiUrl }) {
4101
4143
  ] })
4102
4144
  ] });
4103
4145
  }
4146
+ const ollaidLogo = "data:image/png;base64,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";
4104
4147
  const COLORS = {
4105
4148
  primary: "#002147",
4149
+ primaryForeground: "#ffffff",
4106
4150
  accent: "#e8430a",
4107
4151
  card: "#ffffff",
4108
4152
  cardForeground: "#1a2332",
@@ -4131,13 +4175,49 @@ const LIGHT_VARS = {
4131
4175
  "--input": "40 15% 88%",
4132
4176
  "--ring": "209 100% 13%"
4133
4177
  };
4134
- const ShieldCheckIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: COLORS.accent, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4178
+ const ShieldCheckIcon = ({ size = 24, color = COLORS.accent }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4135
4179
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" }),
4136
4180
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 12 2 2 4-4" })
4137
4181
  ] });
4138
4182
  function needsOnboarding(user) {
4139
4183
  return !user.image_url || !user.phone;
4140
4184
  }
4185
+ const GRADIENT_STYLE_ID = "ollaid-sso-gradient-anim";
4186
+ function injectGradientAnimation() {
4187
+ if (document.getElementById(GRADIENT_STYLE_ID)) return;
4188
+ const style = document.createElement("style");
4189
+ style.id = GRADIENT_STYLE_ID;
4190
+ style.textContent = `
4191
+ @keyframes ollaid-border-gradient {
4192
+ 0% { background-position: 0% 50%; }
4193
+ 50% { background-position: 100% 50%; }
4194
+ 100% { background-position: 0% 50%; }
4195
+ }
4196
+ @keyframes ollaid-marquee {
4197
+ 0% { transform: translateX(0); }
4198
+ 100% { transform: translateX(-50%); }
4199
+ }
4200
+ `;
4201
+ document.head.appendChild(style);
4202
+ }
4203
+ const TopBranding = ({ subtitle }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", marginBottom: "1.5rem" }, children: [
4204
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0.5rem", marginBottom: "0.5rem" }, children: [
4205
+ /* @__PURE__ */ jsxRuntime.jsx(ShieldCheckIcon, { size: 28, color: COLORS.accent }),
4206
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "1.25rem", fontWeight: 700, color: COLORS.primaryForeground }, children: [
4207
+ "iam.",
4208
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: COLORS.accent }, children: "ollaid" }),
4209
+ ".com"
4210
+ ] })
4211
+ ] }),
4212
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "1rem", fontWeight: 600, color: "rgba(255,255,255,0.85)" }, children: subtitle })
4213
+ ] });
4214
+ const Footer = ({ hideFooter }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.5rem", textAlign: "center" }, children: [
4215
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: ollaidLogo, alt: "Ollaid", style: { height: "28px", margin: "0 auto 0.5rem" } }),
4216
+ !hideFooter && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.75rem", color: "rgba(255,255,255,0.5)" }, children: [
4217
+ "© 2026 iam.ollaid.com propulsé par ",
4218
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: "ollaid" })
4219
+ ] })
4220
+ ] });
4141
4221
  function NativeSSOPage({
4142
4222
  saasApiUrl,
4143
4223
  iamApiUrl,
@@ -4146,7 +4226,7 @@ function NativeSSOPage({
4146
4226
  onOnboardingComplete,
4147
4227
  accountType = "user",
4148
4228
  configPrefix = "iam",
4149
- title = "Un compte, plusieurs accès",
4229
+ title = "Un compte pour toutes vos applications",
4150
4230
  description = "Connectez-vous avec votre compte Ollaid pour accéder à toutes les applications partenaires.",
4151
4231
  logoUrl,
4152
4232
  hideFooter = false,
@@ -4167,6 +4247,7 @@ function NativeSSOPage({
4167
4247
  });
4168
4248
  const { isDebug: resolvedDebug } = useNativeAuth({ saasApiUrl, iamApiUrl, configPrefix, autoLoadCredentials: true });
4169
4249
  react.useEffect(() => {
4250
+ injectGradientAnimation();
4170
4251
  const root = document.documentElement;
4171
4252
  const originalValues = {};
4172
4253
  Object.keys(LIGHT_VARS).forEach((key) => {
@@ -4259,7 +4340,7 @@ function NativeSSOPage({
4259
4340
  flexDirection: "column",
4260
4341
  alignItems: "center",
4261
4342
  justifyContent: "center",
4262
- padding: "1rem"
4343
+ padding: "1.5rem 1rem"
4263
4344
  };
4264
4345
  const cardStyle = {
4265
4346
  width: "100%",
@@ -4270,25 +4351,40 @@ function NativeSSOPage({
4270
4351
  boxShadow: COLORS.shadow,
4271
4352
  overflow: "hidden"
4272
4353
  };
4273
- const footerStyle = {
4274
- marginTop: "1.5rem",
4275
- fontSize: "0.75rem",
4276
- color: "rgba(255,255,255,0.6)",
4277
- textAlign: "center"
4278
- };
4279
- const BrandingHeader = () => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", marginBottom: "1.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0.5rem", marginBottom: "0.5rem" }, children: [
4280
- /* @__PURE__ */ jsxRuntime.jsx(ShieldCheckIcon, {}),
4281
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "1.125rem", fontWeight: 700, color: COLORS.primary }, children: [
4282
- "iam.",
4283
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: COLORS.accent }, children: "ollaid" }),
4284
- ".com"
4285
- ] })
4354
+ const SliderBadge = () => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", maxWidth: "28rem", marginBottom: "1.5rem" }, children: logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: "Logo", style: { height: "3rem", margin: "0 auto" } }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "1rem" }, children: [
4355
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4356
+ width: "3rem",
4357
+ height: "3rem",
4358
+ borderRadius: "50%",
4359
+ backgroundColor: "#ffffff",
4360
+ display: "flex",
4361
+ alignItems: "center",
4362
+ justifyContent: "center",
4363
+ flexShrink: 0,
4364
+ boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
4365
+ border: `1px solid ${COLORS.border}`
4366
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ShieldCheckIcon, { size: 22, color: COLORS.accent }) }),
4367
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4368
+ flex: 1,
4369
+ minWidth: 0,
4370
+ position: "relative",
4371
+ borderRadius: "9999px",
4372
+ padding: "2px",
4373
+ background: `linear-gradient(90deg, ${COLORS.primary}, ${COLORS.accent}, ${COLORS.primary})`,
4374
+ backgroundSize: "200% 100%",
4375
+ animation: "ollaid-border-gradient 3s ease infinite"
4376
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4377
+ backgroundColor: "#ffffff",
4378
+ borderRadius: "9999px",
4379
+ height: "3rem",
4380
+ overflow: "hidden"
4381
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(AppsLogoSlider, { iamApiUrl, speed: "normal" }) }) })
4286
4382
  ] }) });
4287
4383
  if (session) {
4288
4384
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
4289
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", maxWidth: "28rem", marginBottom: "1.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(AppsLogoSlider, { iamApiUrl }) }),
4385
+ /* @__PURE__ */ jsxRuntime.jsx(TopBranding, { subtitle: title }),
4386
+ /* @__PURE__ */ jsxRuntime.jsx(SliderBadge, {}),
4290
4387
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "2rem 1.5rem 1.5rem" }, children: [
4291
- /* @__PURE__ */ jsxRuntime.jsx(BrandingHeader, {}),
4292
4388
  /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: { fontSize: "1.25rem", fontWeight: 600, textAlign: "center", color: COLORS.cardForeground }, children: [
4293
4389
  "Bienvenue, ",
4294
4390
  session.user.name
@@ -4296,20 +4392,13 @@ function NativeSSOPage({
4296
4392
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: COLORS.muted, textAlign: "center", marginTop: "0.25rem" }, children: "Vous êtes connecté à votre compte Ollaid SSO" }),
4297
4393
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "1.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: handleLogout, style: { width: "100%" }, children: "Déconnexion" }) })
4298
4394
  ] }) }),
4299
- !hideFooter && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: footerStyle, children: [
4300
- "Géré par",
4301
- " ",
4302
- /* @__PURE__ */ jsxRuntime.jsx("a", { href: "https://iam.ollaid.com", target: "_blank", rel: "noopener noreferrer", style: { color: COLORS.accent, textDecoration: "none" }, children: "iam.ollaid.com" }),
4303
- " ",
4304
- "— Identity Access Manager"
4305
- ] })
4395
+ /* @__PURE__ */ jsxRuntime.jsx(Footer, { hideFooter })
4306
4396
  ] });
4307
4397
  }
4308
4398
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
4309
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", maxWidth: "28rem", marginBottom: "1.5rem" }, children: logoUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: "Logo", style: { height: "3rem", margin: "0 auto" } }) : /* @__PURE__ */ jsxRuntime.jsx(AppsLogoSlider, { iamApiUrl }) }),
4399
+ /* @__PURE__ */ jsxRuntime.jsx(TopBranding, { subtitle: title }),
4400
+ /* @__PURE__ */ jsxRuntime.jsx(SliderBadge, {}),
4310
4401
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "2rem 1.5rem 1.5rem" }, children: [
4311
- /* @__PURE__ */ jsxRuntime.jsx(BrandingHeader, {}),
4312
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.25rem", fontWeight: 600, textAlign: "center", color: COLORS.cardForeground, marginBottom: "0.5rem" }, children: title }),
4313
4402
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: COLORS.muted, textAlign: "center", marginBottom: "1.5rem" }, children: description }),
4314
4403
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
4315
4404
  /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: openLogin, style: { width: "100%", height: "2.75rem" }, children: "Connexion" }),
@@ -4318,24 +4407,13 @@ function NativeSSOPage({
4318
4407
  {
4319
4408
  variant: "outline",
4320
4409
  onClick: openSignup,
4321
- style: {
4322
- width: "100%",
4323
- height: "2.75rem",
4324
- borderColor: COLORS.cardForeground,
4325
- color: COLORS.cardForeground
4326
- },
4410
+ style: { width: "100%", height: "2.75rem", borderColor: COLORS.cardForeground, color: COLORS.cardForeground },
4327
4411
  children: "Inscription"
4328
4412
  }
4329
4413
  )
4330
4414
  ] })
4331
4415
  ] }) }),
4332
- !hideFooter && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: footerStyle, children: [
4333
- "Géré par",
4334
- " ",
4335
- /* @__PURE__ */ jsxRuntime.jsx("a", { href: "https://iam.ollaid.com", target: "_blank", rel: "noopener noreferrer", style: { color: COLORS.accent, textDecoration: "none" }, children: "iam.ollaid.com" }),
4336
- " ",
4337
- "— Identity Access Manager"
4338
- ] }),
4416
+ /* @__PURE__ */ jsxRuntime.jsx(Footer, { hideFooter }),
4339
4417
  /* @__PURE__ */ jsxRuntime.jsx(
4340
4418
  LoginModal,
4341
4419
  {
@@ -4554,6 +4632,7 @@ exports.OnboardingModal = OnboardingModal;
4554
4632
  exports.PasswordRecoveryModal = PasswordRecoveryModal;
4555
4633
  exports.PhoneInput = PhoneInput;
4556
4634
  exports.SignupModal = SignupModal;
4635
+ exports.clearAuthToken = clearAuthToken;
4557
4636
  exports.getAccountType = getAccountType;
4558
4637
  exports.getAuthToken = getAuthToken;
4559
4638
  exports.getAuthUser = getAuthUser;