@vaultix.ai/react 0.3.5 → 0.3.7

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/dist/index.d.mts CHANGED
@@ -87,6 +87,13 @@ interface VaultixContextValue {
87
87
  * Controls which login methods and OAuth providers are rendered by <SignIn /> and <SignUp />.
88
88
  */
89
89
  appConfig: AppConfig | null;
90
+ /**
91
+ * True once the /api/v1/app/config fetch has settled (success OR failure).
92
+ * <SignIn /> and <SignUp /> render a skeleton until this is true so the
93
+ * default full set of methods/providers never flashes before narrowing
94
+ * to the app's configured set.
95
+ */
96
+ appConfigLoaded: boolean;
90
97
  signOut: (redirectUrl?: string) => Promise<void>;
91
98
  /** Update the current user's profile. Resolves with the updated user. */
92
99
  updateUser: (params: UpdateUserParams) => Promise<VaultixUser>;
package/dist/index.d.ts CHANGED
@@ -87,6 +87,13 @@ interface VaultixContextValue {
87
87
  * Controls which login methods and OAuth providers are rendered by <SignIn /> and <SignUp />.
88
88
  */
89
89
  appConfig: AppConfig | null;
90
+ /**
91
+ * True once the /api/v1/app/config fetch has settled (success OR failure).
92
+ * <SignIn /> and <SignUp /> render a skeleton until this is true so the
93
+ * default full set of methods/providers never flashes before narrowing
94
+ * to the app's configured set.
95
+ */
96
+ appConfigLoaded: boolean;
90
97
  signOut: (redirectUrl?: string) => Promise<void>;
91
98
  /** Update the current user's profile. Resolves with the updated user. */
92
99
  updateUser: (params: UpdateUserParams) => Promise<VaultixUser>;
package/dist/index.js CHANGED
@@ -113,6 +113,7 @@ function VaultixProvider({
113
113
  const [session, setSession] = (0, import_react.useState)(null);
114
114
  const [organization, setOrganization] = (0, import_react.useState)(null);
115
115
  const [appConfig, setAppConfig] = (0, import_react.useState)(null);
116
+ const [appConfigLoaded, setAppConfigLoaded] = (0, import_react.useState)(false);
116
117
  const jwtRef = (0, import_react.useRef)(null);
117
118
  const refreshTimerRef = (0, import_react.useRef)(null);
118
119
  const clearAuth = (0, import_react.useCallback)(() => {
@@ -224,6 +225,8 @@ function VaultixProvider({
224
225
  setAppConfig(cfg);
225
226
  }
226
227
  } catch {
228
+ } finally {
229
+ if (!cancelled) setAppConfigLoaded(true);
227
230
  }
228
231
  }
229
232
  hydrate();
@@ -287,6 +290,7 @@ function VaultixProvider({
287
290
  isSignedIn: !!session,
288
291
  apiOrigin,
289
292
  appConfig,
293
+ appConfigLoaded,
290
294
  signOut,
291
295
  updateUser,
292
296
  connectPlatform
@@ -332,7 +336,11 @@ function usePlatformConnect(provider, defaultOptions) {
332
336
  );
333
337
  (0, import_react2.useEffect)(() => {
334
338
  if (typeof window === "undefined") return;
335
- const params = new URLSearchParams(window.location.search);
339
+ const hashStr = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : "";
340
+ const hashParams = new URLSearchParams(hashStr);
341
+ const queryParams = new URLSearchParams(window.location.search);
342
+ const usingHash = hashParams.has("__vaultix_connect");
343
+ const params = usingHash ? hashParams : queryParams;
336
344
  const connectToken = params.get("__vaultix_connect");
337
345
  const returnedProvider = params.get("provider");
338
346
  if (!connectToken || returnedProvider !== provider) return;
@@ -351,9 +359,13 @@ function usePlatformConnect(provider, defaultOptions) {
351
359
  };
352
360
  setConnectedAccount(result);
353
361
  const clean = new URL(window.location.href);
354
- clean.searchParams.delete("__vaultix_connect");
355
- clean.searchParams.delete("provider");
356
- window.history.replaceState({}, "", clean.toString());
362
+ if (usingHash) {
363
+ clean.hash = "";
364
+ } else {
365
+ clean.searchParams.delete("__vaultix_connect");
366
+ clean.searchParams.delete("provider");
367
+ }
368
+ window.history.replaceState({}, "", clean.href.replace(/#$/, ""));
357
369
  } catch {
358
370
  }
359
371
  }, [provider]);
@@ -430,8 +442,11 @@ function SignIn({
430
442
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
431
443
  const mutedColor = vars.colorTextMuted ?? "#475569";
432
444
  let appConfig = null;
445
+ let appConfigLoaded = true;
433
446
  try {
434
- appConfig = useVaultixContext().appConfig;
447
+ const ctx = useVaultixContext();
448
+ appConfig = ctx.appConfig;
449
+ appConfigLoaded = ctx.appConfigLoaded;
435
450
  } catch {
436
451
  }
437
452
  const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
@@ -703,6 +718,39 @@ function SignIn({
703
718
  "forgot-verify": `Code sent to ${email}`,
704
719
  "forgot-reset": "Choose a new password"
705
720
  };
721
+ if (!appConfigLoaded) {
722
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
723
+ "div",
724
+ {
725
+ className: (0, import_clsx.clsx)(
726
+ "w-full max-w-sm mx-auto rounded-2xl border border-white/8 shadow-2xl",
727
+ "backdrop-blur-[16px]",
728
+ className
729
+ ),
730
+ style: { background: cardBg },
731
+ "aria-busy": "true",
732
+ children: [
733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-8 pt-8 pb-6 text-center", children: [
734
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
735
+ "div",
736
+ {
737
+ className: "inline-flex items-center justify-center w-10 h-10 rounded-xl shadow-lg mb-4 animate-pulse",
738
+ style: { background: primaryColor ?? "linear-gradient(to bottom right, #7c3aed, #2563eb)" },
739
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LockIcon, {})
740
+ }
741
+ ),
742
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-5 w-32 mx-auto rounded bg-white/10 animate-pulse" }),
743
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-3 w-44 mx-auto mt-2 rounded bg-white/5 animate-pulse" })
744
+ ] }),
745
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-8 pb-8 space-y-3", children: [
746
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-11 w-full rounded-lg bg-white/10 animate-pulse" }),
747
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" }),
748
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" })
749
+ ] })
750
+ ]
751
+ }
752
+ );
753
+ }
706
754
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
707
755
  "div",
708
756
  {
@@ -1107,8 +1155,11 @@ function SignUp({
1107
1155
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
1108
1156
  const mutedColor = vars.colorTextMuted ?? "#475569";
1109
1157
  let appConfig = null;
1158
+ let appConfigLoaded = true;
1110
1159
  try {
1111
- appConfig = useVaultixContext().appConfig;
1160
+ const ctx = useVaultixContext();
1161
+ appConfig = ctx.appConfig;
1162
+ appConfigLoaded = ctx.appConfigLoaded;
1112
1163
  } catch {
1113
1164
  }
1114
1165
  const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
@@ -1201,6 +1252,37 @@ function SignUp({
1201
1252
  } catch {
1202
1253
  }
1203
1254
  }
1255
+ if (!appConfigLoaded) {
1256
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1257
+ "div",
1258
+ {
1259
+ className: (0, import_clsx2.clsx)(
1260
+ "w-full max-w-sm mx-auto rounded-2xl border border-white/8 shadow-2xl backdrop-blur-[16px]",
1261
+ className
1262
+ ),
1263
+ style: { background: cardBg },
1264
+ "aria-busy": "true",
1265
+ children: [
1266
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "px-8 pt-8 pb-6 text-center", children: [
1267
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1268
+ "div",
1269
+ {
1270
+ className: "inline-flex items-center justify-center w-10 h-10 rounded-xl shadow-lg mb-4 animate-pulse",
1271
+ style: { background: primaryColor ?? "linear-gradient(to bottom right, #7c3aed, #2563eb)" }
1272
+ }
1273
+ ),
1274
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "h-5 w-32 mx-auto rounded bg-white/10 animate-pulse" }),
1275
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "h-3 w-44 mx-auto mt-2 rounded bg-white/5 animate-pulse" })
1276
+ ] }),
1277
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "px-8 pb-8 space-y-3", children: [
1278
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "h-11 w-full rounded-lg bg-white/10 animate-pulse" }),
1279
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" }),
1280
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" })
1281
+ ] })
1282
+ ]
1283
+ }
1284
+ );
1285
+ }
1204
1286
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1205
1287
  "div",
1206
1288
  {
package/dist/index.mjs CHANGED
@@ -78,6 +78,7 @@ function VaultixProvider({
78
78
  const [session, setSession] = useState(null);
79
79
  const [organization, setOrganization] = useState(null);
80
80
  const [appConfig, setAppConfig] = useState(null);
81
+ const [appConfigLoaded, setAppConfigLoaded] = useState(false);
81
82
  const jwtRef = useRef(null);
82
83
  const refreshTimerRef = useRef(null);
83
84
  const clearAuth = useCallback(() => {
@@ -189,6 +190,8 @@ function VaultixProvider({
189
190
  setAppConfig(cfg);
190
191
  }
191
192
  } catch {
193
+ } finally {
194
+ if (!cancelled) setAppConfigLoaded(true);
192
195
  }
193
196
  }
194
197
  hydrate();
@@ -252,6 +255,7 @@ function VaultixProvider({
252
255
  isSignedIn: !!session,
253
256
  apiOrigin,
254
257
  appConfig,
258
+ appConfigLoaded,
255
259
  signOut,
256
260
  updateUser,
257
261
  connectPlatform
@@ -297,7 +301,11 @@ function usePlatformConnect(provider, defaultOptions) {
297
301
  );
298
302
  useEffect2(() => {
299
303
  if (typeof window === "undefined") return;
300
- const params = new URLSearchParams(window.location.search);
304
+ const hashStr = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : "";
305
+ const hashParams = new URLSearchParams(hashStr);
306
+ const queryParams = new URLSearchParams(window.location.search);
307
+ const usingHash = hashParams.has("__vaultix_connect");
308
+ const params = usingHash ? hashParams : queryParams;
301
309
  const connectToken = params.get("__vaultix_connect");
302
310
  const returnedProvider = params.get("provider");
303
311
  if (!connectToken || returnedProvider !== provider) return;
@@ -316,9 +324,13 @@ function usePlatformConnect(provider, defaultOptions) {
316
324
  };
317
325
  setConnectedAccount(result);
318
326
  const clean = new URL(window.location.href);
319
- clean.searchParams.delete("__vaultix_connect");
320
- clean.searchParams.delete("provider");
321
- window.history.replaceState({}, "", clean.toString());
327
+ if (usingHash) {
328
+ clean.hash = "";
329
+ } else {
330
+ clean.searchParams.delete("__vaultix_connect");
331
+ clean.searchParams.delete("provider");
332
+ }
333
+ window.history.replaceState({}, "", clean.href.replace(/#$/, ""));
322
334
  } catch {
323
335
  }
324
336
  }, [provider]);
@@ -395,8 +407,11 @@ function SignIn({
395
407
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
396
408
  const mutedColor = vars.colorTextMuted ?? "#475569";
397
409
  let appConfig = null;
410
+ let appConfigLoaded = true;
398
411
  try {
399
- appConfig = useVaultixContext().appConfig;
412
+ const ctx = useVaultixContext();
413
+ appConfig = ctx.appConfig;
414
+ appConfigLoaded = ctx.appConfigLoaded;
400
415
  } catch {
401
416
  }
402
417
  const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
@@ -668,6 +683,39 @@ function SignIn({
668
683
  "forgot-verify": `Code sent to ${email}`,
669
684
  "forgot-reset": "Choose a new password"
670
685
  };
686
+ if (!appConfigLoaded) {
687
+ return /* @__PURE__ */ jsxs(
688
+ "div",
689
+ {
690
+ className: clsx(
691
+ "w-full max-w-sm mx-auto rounded-2xl border border-white/8 shadow-2xl",
692
+ "backdrop-blur-[16px]",
693
+ className
694
+ ),
695
+ style: { background: cardBg },
696
+ "aria-busy": "true",
697
+ children: [
698
+ /* @__PURE__ */ jsxs("div", { className: "px-8 pt-8 pb-6 text-center", children: [
699
+ /* @__PURE__ */ jsx2(
700
+ "div",
701
+ {
702
+ className: "inline-flex items-center justify-center w-10 h-10 rounded-xl shadow-lg mb-4 animate-pulse",
703
+ style: { background: primaryColor ?? "linear-gradient(to bottom right, #7c3aed, #2563eb)" },
704
+ children: /* @__PURE__ */ jsx2(LockIcon, {})
705
+ }
706
+ ),
707
+ /* @__PURE__ */ jsx2("div", { className: "h-5 w-32 mx-auto rounded bg-white/10 animate-pulse" }),
708
+ /* @__PURE__ */ jsx2("div", { className: "h-3 w-44 mx-auto mt-2 rounded bg-white/5 animate-pulse" })
709
+ ] }),
710
+ /* @__PURE__ */ jsxs("div", { className: "px-8 pb-8 space-y-3", children: [
711
+ /* @__PURE__ */ jsx2("div", { className: "h-11 w-full rounded-lg bg-white/10 animate-pulse" }),
712
+ /* @__PURE__ */ jsx2("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" }),
713
+ /* @__PURE__ */ jsx2("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" })
714
+ ] })
715
+ ]
716
+ }
717
+ );
718
+ }
671
719
  return /* @__PURE__ */ jsxs(
672
720
  "div",
673
721
  {
@@ -1072,8 +1120,11 @@ function SignUp({
1072
1120
  const textColor = vars.colorText ?? "rgba(255,255,255,0.9)";
1073
1121
  const mutedColor = vars.colorTextMuted ?? "#475569";
1074
1122
  let appConfig = null;
1123
+ let appConfigLoaded = true;
1075
1124
  try {
1076
- appConfig = useVaultixContext().appConfig;
1125
+ const ctx = useVaultixContext();
1126
+ appConfig = ctx.appConfig;
1127
+ appConfigLoaded = ctx.appConfigLoaded;
1077
1128
  } catch {
1078
1129
  }
1079
1130
  const enabledProviders = appConfig?.providers ?? ["google", "github", "meta", "linkedin", "x", "threads"];
@@ -1166,6 +1217,37 @@ function SignUp({
1166
1217
  } catch {
1167
1218
  }
1168
1219
  }
1220
+ if (!appConfigLoaded) {
1221
+ return /* @__PURE__ */ jsxs2(
1222
+ "div",
1223
+ {
1224
+ className: clsx2(
1225
+ "w-full max-w-sm mx-auto rounded-2xl border border-white/8 shadow-2xl backdrop-blur-[16px]",
1226
+ className
1227
+ ),
1228
+ style: { background: cardBg },
1229
+ "aria-busy": "true",
1230
+ children: [
1231
+ /* @__PURE__ */ jsxs2("div", { className: "px-8 pt-8 pb-6 text-center", children: [
1232
+ /* @__PURE__ */ jsx3(
1233
+ "div",
1234
+ {
1235
+ className: "inline-flex items-center justify-center w-10 h-10 rounded-xl shadow-lg mb-4 animate-pulse",
1236
+ style: { background: primaryColor ?? "linear-gradient(to bottom right, #7c3aed, #2563eb)" }
1237
+ }
1238
+ ),
1239
+ /* @__PURE__ */ jsx3("div", { className: "h-5 w-32 mx-auto rounded bg-white/10 animate-pulse" }),
1240
+ /* @__PURE__ */ jsx3("div", { className: "h-3 w-44 mx-auto mt-2 rounded bg-white/5 animate-pulse" })
1241
+ ] }),
1242
+ /* @__PURE__ */ jsxs2("div", { className: "px-8 pb-8 space-y-3", children: [
1243
+ /* @__PURE__ */ jsx3("div", { className: "h-11 w-full rounded-lg bg-white/10 animate-pulse" }),
1244
+ /* @__PURE__ */ jsx3("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" }),
1245
+ /* @__PURE__ */ jsx3("div", { className: "h-11 w-full rounded-lg bg-white/5 animate-pulse" })
1246
+ ] })
1247
+ ]
1248
+ }
1249
+ );
1250
+ }
1169
1251
  return /* @__PURE__ */ jsxs2(
1170
1252
  "div",
1171
1253
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultix.ai/react",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Vaultix-ID React SDK — drop-in auth components for any React app",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",