firebase-os 1.1.5 → 1.1.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.
@@ -129,9 +129,11 @@ function qe({ children: t, scopeSelector: n }) {
129
129
  return r === "system" ? (o(t.matches ? "light" : "dark"), t.addEventListener("change", e)) : o(r), () => t.removeEventListener("change", e);
130
130
  }, [r]), m(() => {
131
131
  let e = (n ? document.querySelector(n) : document.documentElement) || document.documentElement, t = a === "dark" ? s.colors.dark : s.colors.light;
132
- e.style.setProperty("--bg-color", t.background), t.backgroundSecondary && e.style.setProperty("--bg-secondary-color", t.backgroundSecondary), e.style.setProperty("--fg-color", t.foreground), e.style.setProperty("--accent-color", t.accent), e.style.setProperty("--panel-bg", t.panelBg), e.style.setProperty("--panel-border", t.panelBorder);
133
- let i = (e) => !e || e.length === 0 ? "transparent" : e.length === 1 ? e[0] : `linear-gradient(135deg, ${e.map((t, n) => `${t} ${Math.round(n / (e.length - 1) * 100)}%`).join(", ")})`;
134
- e.style.setProperty("--button-bg", i(t.buttonGradient)), e.style.setProperty("--button-fg", t.buttonText || "#ffffff"), e.style.setProperty("--button-hover-bg", i(t.buttonHoverGradient || t.buttonGradient)), e.style.setProperty("--text-gradient", i(t.textGradient)), e.style.setProperty("--glow-color", t.glowColor || "rgba(124, 58, 237, 0.3)"), e.style.setProperty("--notification-icon-color", t.notificationIconColor || t.accent), e.style.setProperty("--btn-sec-bg", t.secondaryButton?.bg || "rgba(255, 255, 255, 0.05)"), e.style.setProperty("--btn-sec-border", t.secondaryButton?.border || "transparent"), e.style.setProperty("--btn-sec-text", t.secondaryButton?.text || t.foreground), e.style.setProperty("--selection-bg", t.selectionBg || "color-mix(in srgb, var(--accent-color) 40%, transparent)"), e.style.setProperty("--selection-text", t.selectionText || "#ffffff"), e.setAttribute("data-theme", a), localStorage.setItem("theme-mode", r), s.cornerRounding === "custom" && s.cornerRadii ? (e.style.setProperty("--btn-radius", `${parseFloat(String(s.cornerRadii.buttonRadius)) || 0}rem`), e.style.setProperty("--card-radius", `${parseFloat(String(s.cornerRadii.cardRadius)) || 0}rem`), e.style.setProperty("--input-radius", `${parseFloat(String(s.cornerRadii.inputRadius)) || 0}rem`), e.style.setProperty("--modal-radius", `${parseFloat(String(s.cornerRadii.modalRadius)) || 0}rem`)) : (e.style.setProperty("--btn-radius", "0.75rem"), e.style.setProperty("--card-radius", "1.5rem"), e.style.setProperty("--input-radius", "0.75rem"), e.style.setProperty("--modal-radius", "1.5rem")), ((t) => {
132
+ e.style.setProperty("--bg-color", t.background), e.style.setProperty("--bg-secondary-color", t.backgroundSecondary || t.background), e.style.setProperty("--fg-color", t.foreground), e.style.setProperty("--accent-color", t.accent), e.style.setProperty("--panel-bg", t.panelBg), e.style.setProperty("--panel-border", t.panelBorder);
133
+ let i = (e, t) => !e || e.length === 0 ? t || "transparent" : e.length === 1 ? e[0] : `linear-gradient(135deg, ${e.map((t, n) => `${t} ${Math.round(n / (e.length - 1) * 100)}%`).join(", ")})`, o = a === "dark" ? "linear-gradient(135deg, #6d28d9 0%, #a78bfa 100%)" : "linear-gradient(135deg, #5b21b6 0%, #a78bfa 100%)";
134
+ e.style.setProperty("--button-bg", i(t.buttonGradient, o)), e.style.setProperty("--button-fg", t.buttonText || "#ffffff"), e.style.setProperty("--button-hover-bg", i(t.buttonHoverGradient || t.buttonGradient, o)), e.style.setProperty("--text-gradient", i(t.textGradient, `linear-gradient(135deg, ${t.foreground} 0%, ${t.accent} 100%)`)), e.style.setProperty("--glow-color", t.glowColor || "rgba(124, 58, 237, 0.3)"), e.style.setProperty("--notification-icon-color", t.notificationIconColor || t.accent);
135
+ let c = t.secondaryButton?.bg || (a === "dark" ? "rgba(255, 255, 255, 0.05)" : "rgba(0, 0, 0, 0.03)"), l = t.secondaryButton?.border || (a === "dark" ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.06)"), u = t.secondaryButton?.text || t.foreground;
136
+ e.style.setProperty("--btn-sec-bg", c), e.style.setProperty("--btn-sec-border", l), e.style.setProperty("--btn-sec-text", u), e.style.setProperty("--selection-bg", t.selectionBg || "color-mix(in srgb, var(--accent-color) 40%, transparent)"), e.style.setProperty("--selection-text", t.selectionText || "#ffffff"), e.setAttribute("data-theme", a), localStorage.setItem("theme-mode", r), s.cornerRounding === "custom" && s.cornerRadii ? (e.style.setProperty("--btn-radius", `${parseFloat(String(s.cornerRadii.buttonRadius)) || 0}rem`), e.style.setProperty("--card-radius", `${parseFloat(String(s.cornerRadii.cardRadius)) || 0}rem`), e.style.setProperty("--input-radius", `${parseFloat(String(s.cornerRadii.inputRadius)) || 0}rem`), e.style.setProperty("--modal-radius", `${parseFloat(String(s.cornerRadii.modalRadius)) || 0}rem`)) : (e.style.setProperty("--btn-radius", "0.75rem"), e.style.setProperty("--card-radius", "1.5rem"), e.style.setProperty("--input-radius", "0.75rem"), e.style.setProperty("--modal-radius", "1.5rem")), ((t) => {
135
137
  let n = {
136
138
  Inter: "\"Inter\", sans-serif",
137
139
  Outfit: "\"Outfit\", sans-serif",
@@ -144,8 +146,8 @@ function qe({ children: t, scopeSelector: n }) {
144
146
  let r = document.getElementById("dynamic-google-font");
145
147
  t === "System UI" ? r && r.remove() : (r || (r = document.createElement("link"), r.id = "dynamic-google-font", r.rel = "stylesheet", document.head.appendChild(r)), r.href = `https://fonts.googleapis.com/css2?family=${t.replace(/ /g, "+")}:wght@400;500;600;700;800;900&display=swap`), e.style.fontSize = "16px", e.style.setProperty("--weight-h1", "800"), e.style.setProperty("--weight-h2", "700"), e.style.setProperty("--weight-h3", "700"), e.style.setProperty("--leading-normal", "1.5");
146
148
  })(s.fontFamily || "Inter");
147
- let o = document.querySelector("link[rel*='icon']");
148
- o || (o = document.createElement("link"), o.rel = "icon", document.head.appendChild(o)), s.faviconUrl && (o.href = s.faviconUrl);
149
+ let d = document.querySelector("link[rel*='icon']");
150
+ d || (d = document.createElement("link"), d.rel = "icon", document.head.appendChild(d)), s.faviconUrl && (d.href = s.faviconUrl);
149
151
  }, [
150
152
  a,
151
153
  r,
@@ -78857,9 +78859,14 @@ function OVn() {
78857
78859
  },
78858
78860
  transition: { delay: t * .05 },
78859
78861
  className: "glass-panel border border-[var(--panel-border)] rounded-2xl flex flex-col overflow-hidden hover:border-accent/40 transition-all duration-300",
78860
- children: [/* @__PURE__ */ V("button", {
78862
+ children: [/* @__PURE__ */ V("div", {
78863
+ role: "button",
78864
+ tabIndex: 0,
78865
+ onKeyDown: (t) => {
78866
+ (t.key === "Enter" || t.key === " ") && d(e.id);
78867
+ },
78861
78868
  onClick: () => d(e.id),
78862
- className: "w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left",
78869
+ className: "w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left cursor-pointer",
78863
78870
  children: [/* @__PURE__ */ V("div", {
78864
78871
  className: "flex items-center gap-4 flex-1 min-w-0",
78865
78872
  children: [/* @__PURE__ */ B("div", {
@@ -78999,9 +79006,14 @@ function OVn() {
78999
79006
  },
79000
79007
  transition: { delay: t * .05 },
79001
79008
  className: "glass-panel border border-[var(--panel-border)] rounded-2xl flex flex-col overflow-hidden opacity-50 grayscale hover:opacity-100 hover:grayscale-0 hover:border-accent/40 transition-all duration-300",
79002
- children: [/* @__PURE__ */ V("button", {
79009
+ children: [/* @__PURE__ */ V("div", {
79010
+ role: "button",
79011
+ tabIndex: 0,
79012
+ onKeyDown: (t) => {
79013
+ (t.key === "Enter" || t.key === " ") && d(e.id);
79014
+ },
79003
79015
  onClick: () => d(e.id),
79004
- className: "w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left",
79016
+ className: "w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left cursor-pointer",
79005
79017
  children: [/* @__PURE__ */ V("div", {
79006
79018
  className: "flex items-center gap-4 flex-1 min-w-0",
79007
79019
  children: [/* @__PURE__ */ B("div", {
@@ -89609,10 +89621,10 @@ function wUn() {
89609
89621
  let e = [];
89610
89622
  for (let { key: t, label: n } of SUn) {
89611
89623
  let r = CUn(t);
89612
- (!r || r.trim() === "") && e.push(n);
89624
+ !r || r.trim() === "" ? (console.log("Missing key:", t, r), e.push(n)) : console.log("Found key:", t, r);
89613
89625
  }
89614
89626
  let t = CUn("VITE_ADMIN_EMAILS"), n = !t || t.trim() === "";
89615
- return {
89627
+ return console.log("Setup complete?", e.length === 0, e), {
89616
89628
  allSet: e.length === 0,
89617
89629
  missing: e,
89618
89630
  missingAdminEmails: n
@@ -90365,7 +90377,10 @@ function FUn() {
90365
90377
  }),
90366
90378
  /* @__PURE__ */ B(U, {
90367
90379
  path: "/setup",
90368
- element: /* @__PURE__ */ B(jUn, {})
90380
+ element: /* @__PURE__ */ B(be, {
90381
+ to: "/",
90382
+ replace: !0
90383
+ })
90369
90384
  }),
90370
90385
  /* @__PURE__ */ B(U, {
90371
90386
  path: "*",
@@ -90402,13 +90417,14 @@ function RUn(e) {
90402
90417
  themeConfig: e.themeConfig,
90403
90418
  components: e.components
90404
90419
  },
90405
- children: /* @__PURE__ */ B(qe, {
90406
- scopeSelector: ".firebase-os",
90407
- children: /* @__PURE__ */ B("div", {
90408
- className: "firebase-os flex-1 flex flex-col min-h-screen",
90409
- children: /* @__PURE__ */ B(IUn, {})
90410
- })
90411
- })
90420
+ children: /* @__PURE__ */ B(qe, { children: /* @__PURE__ */ B("div", {
90421
+ className: "firebase-os flex-1 flex flex-col min-h-screen",
90422
+ style: {
90423
+ background: "var(--bg-gradient)",
90424
+ color: "var(--fg-color)"
90425
+ },
90426
+ children: /* @__PURE__ */ B(IUn, {})
90427
+ }) })
90412
90428
  });
90413
90429
  }
90414
90430
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-os",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "A complete Firebase-powered admin OS — one React component.",
5
5
  "type": "module",
6
6
  "main": "dist/firebase-os.cjs.js",
@@ -191,8 +191,8 @@ const viteConfigPath = path.join(consumerRoot, 'vite.config.ts');
191
191
  if (fs.existsSync(viteConfigPath)) {
192
192
  let viteConfig = fs.readFileSync(viteConfigPath, 'utf8');
193
193
  if (!viteConfig.includes('@tailwindcss/vite')) {
194
- viteConfig = "import tailwindcss from '@tailwindcss/vite';\\n" + viteConfig;
195
- viteConfig = viteConfig.replace('plugins: [', 'plugins: [\\n tailwindcss(),');
194
+ viteConfig = "import tailwindcss from '@tailwindcss/vite';\n" + viteConfig;
195
+ viteConfig = viteConfig.replace('plugins: [', 'plugins: [\n tailwindcss(),');
196
196
  fs.writeFileSync(viteConfigPath, viteConfig);
197
197
  console.log(' ✓ Patched vite.config.ts to enable Tailwind CSS v4');
198
198
  }
package/src/App.tsx CHANGED
@@ -160,8 +160,8 @@ function AuthenticatedApp() {
160
160
  <Route path="/profile" element={<PrivateRoute><Profile /></PrivateRoute>} />
161
161
  <Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} />
162
162
 
163
- {/* Setup (accessible even after completion for reference) */}
164
- <Route path="/setup" element={<Setup />} />
163
+ {/* Setup Redirect (if already done, don't show it via route) */}
164
+ <Route path="/setup" element={<Navigate to="/" replace />} />
165
165
 
166
166
  {/* Dynamic Content Routing */}
167
167
  <Route path="*" element={<DynamicPage />} />
@@ -68,9 +68,10 @@ export function FirebaseOS(props: FirebaseOSProps) {
68
68
 
69
69
  return (
70
70
  <ConfigProvider config={config}>
71
- <ThemeProvider scopeSelector=".firebase-os">
71
+ <ThemeProvider>
72
72
  <div
73
73
  className="firebase-os flex-1 flex flex-col min-h-screen"
74
+ style={{ background: 'var(--bg-gradient)', color: 'var(--fg-color)' }}
74
75
  >
75
76
  <App />
76
77
  </div>
@@ -102,9 +102,7 @@ export function ThemeProvider({ children, scopeSelector }: { children: React.Rea
102
102
 
103
103
  // Core Colors
104
104
  root.style.setProperty('--bg-color', colors.background);
105
- if (colors.backgroundSecondary) {
106
- root.style.setProperty('--bg-secondary-color', colors.backgroundSecondary);
107
- }
105
+ root.style.setProperty('--bg-secondary-color', colors.backgroundSecondary || colors.background);
108
106
  root.style.setProperty('--fg-color', colors.foreground);
109
107
  root.style.setProperty('--accent-color', colors.accent);
110
108
 
@@ -113,24 +111,32 @@ export function ThemeProvider({ children, scopeSelector }: { children: React.Rea
113
111
  root.style.setProperty('--panel-border', colors.panelBorder);
114
112
 
115
113
  // Gradients
116
- const buildGradient = (arr: string[] | undefined) => {
117
- if (!arr || arr.length === 0) return 'transparent';
114
+ const buildGradient = (arr: string[] | undefined, fallback?: string) => {
115
+ if (!arr || arr.length === 0) return fallback || 'transparent';
118
116
  if (arr.length === 1) return arr[0];
119
117
  const stops = arr.map((c, i) => `${c} ${Math.round((i / (arr.length - 1)) * 100)}%`).join(', ');
120
118
  return `linear-gradient(135deg, ${stops})`;
121
119
  };
122
120
 
123
- root.style.setProperty('--button-bg', buildGradient(colors.buttonGradient));
121
+ const defaultBtnGrad = currentTheme === 'dark'
122
+ ? 'linear-gradient(135deg, #6d28d9 0%, #a78bfa 100%)'
123
+ : 'linear-gradient(135deg, #5b21b6 0%, #a78bfa 100%)';
124
+
125
+ root.style.setProperty('--button-bg', buildGradient(colors.buttonGradient, defaultBtnGrad));
124
126
  root.style.setProperty('--button-fg', colors.buttonText || '#ffffff');
125
- root.style.setProperty('--button-hover-bg', buildGradient(colors.buttonHoverGradient || colors.buttonGradient));
126
- root.style.setProperty('--text-gradient', buildGradient(colors.textGradient));
127
+ root.style.setProperty('--button-hover-bg', buildGradient(colors.buttonHoverGradient || colors.buttonGradient, defaultBtnGrad));
128
+ root.style.setProperty('--text-gradient', buildGradient(colors.textGradient, `linear-gradient(135deg, ${colors.foreground} 0%, ${colors.accent} 100%)`));
127
129
  root.style.setProperty('--glow-color', colors.glowColor || 'rgba(124, 58, 237, 0.3)');
128
130
  root.style.setProperty('--notification-icon-color', colors.notificationIconColor || colors.accent);
129
131
 
130
132
  // Secondary Buttons
131
- root.style.setProperty('--btn-sec-bg', colors.secondaryButton?.bg || 'rgba(255, 255, 255, 0.05)');
132
- root.style.setProperty('--btn-sec-border', colors.secondaryButton?.border || 'transparent');
133
- root.style.setProperty('--btn-sec-text', colors.secondaryButton?.text || colors.foreground);
133
+ const secBg = colors.secondaryButton?.bg || (currentTheme === 'dark' ? 'rgba(255, 255, 255, 0.05)' : 'rgba(0, 0, 0, 0.03)');
134
+ const secBorder = colors.secondaryButton?.border || (currentTheme === 'dark' ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.06)');
135
+ const secText = colors.secondaryButton?.text || colors.foreground;
136
+
137
+ root.style.setProperty('--btn-sec-bg', secBg);
138
+ root.style.setProperty('--btn-sec-border', secBorder);
139
+ root.style.setProperty('--btn-sec-text', secText);
134
140
 
135
141
  // Text Selection
136
142
  root.style.setProperty('--selection-bg', colors.selectionBg || 'color-mix(in srgb, var(--accent-color) 40%, transparent)');
@@ -62,12 +62,18 @@ export function getEnvStatus() {
62
62
  const missing: string[] = [];
63
63
  for (const { key, label } of REQUIRED_KEYS) {
64
64
  const v = getEnvVal(key);
65
- if (!v || v.trim() === '') missing.push(label);
65
+ if (!v || v.trim() === '') {
66
+ console.log('Missing key:', key, v);
67
+ missing.push(label);
68
+ } else {
69
+ console.log('Found key:', key, v);
70
+ }
66
71
  }
67
72
 
68
73
  const adminEmails = getEnvVal('VITE_ADMIN_EMAILS');
69
74
  const missingAdminEmails = !adminEmails || adminEmails.trim() === '';
70
75
 
76
+ console.log('Setup complete?', missing.length === 0, missing);
71
77
  return { allSet: missing.length === 0, missing, missingAdminEmails };
72
78
  }
73
79
 
@@ -154,9 +154,12 @@ export function Submissions() {
154
154
  transition={{ delay: index * 0.05 }}
155
155
  className="glass-panel border border-[var(--panel-border)] rounded-2xl flex flex-col overflow-hidden hover:border-accent/40 transition-all duration-300"
156
156
  >
157
- <button
157
+ <div
158
+ role="button"
159
+ tabIndex={0}
160
+ onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') toggleExpand(submission.id); }}
158
161
  onClick={() => toggleExpand(submission.id)}
159
- className="w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left"
162
+ className="w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left cursor-pointer"
160
163
  >
161
164
  <div className="flex items-center gap-4 flex-1 min-w-0">
162
165
  <div className="relative shrink-0">
@@ -196,7 +199,7 @@ export function Submissions() {
196
199
  <ChevronDown className="w-4 h-4 text-foreground/50" />
197
200
  </div>
198
201
  </div>
199
- </button>
202
+ </div>
200
203
 
201
204
  <AnimatePresence>
202
205
  {isExpanded && (
@@ -269,9 +272,12 @@ export function Submissions() {
269
272
  transition={{ delay: index * 0.05 }}
270
273
  className="glass-panel border border-[var(--panel-border)] rounded-2xl flex flex-col overflow-hidden opacity-50 grayscale hover:opacity-100 hover:grayscale-0 hover:border-accent/40 transition-all duration-300"
271
274
  >
272
- <button
275
+ <div
276
+ role="button"
277
+ tabIndex={0}
278
+ onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') toggleExpand(submission.id); }}
273
279
  onClick={() => toggleExpand(submission.id)}
274
- className="w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left"
280
+ className="w-full flex items-center justify-between p-4 md:px-6 hover:bg-foreground/[0.02] transition-colors text-left cursor-pointer"
275
281
  >
276
282
  <div className="flex items-center gap-4 flex-1 min-w-0">
277
283
  <div className="relative shrink-0 grayscale">
@@ -303,7 +309,7 @@ export function Submissions() {
303
309
  <ChevronDown className="w-4 h-4 text-foreground/50" />
304
310
  </div>
305
311
  </div>
306
- </button>
312
+ </div>
307
313
 
308
314
  <AnimatePresence>
309
315
  {isExpanded && (