firebase-os 1.0.0 → 1.1.3

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.
@@ -97,41 +97,41 @@ function Ge(e, t) {
97
97
  return n;
98
98
  }
99
99
  var Ke = c(void 0);
100
- function qe({ children: t }) {
101
- let [n, r] = x(() => localStorage.getItem("theme-mode") || e.defaultTheme), [i, a] = x("dark"), [o, s] = x(() => {
100
+ function qe({ children: t, scopeSelector: n }) {
101
+ let [r, i] = x(() => localStorage.getItem("theme-mode") || e.defaultTheme), [a, o] = x("dark"), [s, c] = x(() => {
102
102
  try {
103
103
  let e = localStorage.getItem("theme_config_cache");
104
104
  if (e) return JSON.parse(e);
105
105
  } catch {}
106
106
  return e;
107
- }), [c, l] = x(() => !!localStorage.getItem("theme_config_cache"));
107
+ }), [l, u] = x(() => !!localStorage.getItem("theme_config_cache"));
108
108
  return m(() => {
109
109
  if (!W) {
110
- s(e), l(!0);
110
+ c(e), u(!0);
111
111
  return;
112
112
  }
113
113
  let t = O(T(W, "sys_configs", "theme"), (t) => {
114
114
  if (t.exists()) {
115
115
  let n = t.data();
116
116
  delete n.fontStyles, delete n.fontCustomization;
117
- let i = Ge(e, n);
118
- s(i), localStorage.setItem("theme_config_cache", JSON.stringify(i));
117
+ let r = Ge(e, n);
118
+ c(r), localStorage.setItem("theme_config_cache", JSON.stringify(r));
119
119
  let a = localStorage.getItem("last-seen-default-theme");
120
- i.defaultTheme && i.defaultTheme !== a && (localStorage.setItem("last-seen-default-theme", i.defaultTheme), r(i.defaultTheme));
121
- } else s(e), localStorage.setItem("theme_config_cache", JSON.stringify(e));
122
- l(!0);
120
+ r.defaultTheme && r.defaultTheme !== a && (localStorage.setItem("last-seen-default-theme", r.defaultTheme), i(r.defaultTheme));
121
+ } else c(e), localStorage.setItem("theme_config_cache", JSON.stringify(e));
122
+ u(!0);
123
123
  });
124
124
  return () => t();
125
125
  }, []), m(() => {
126
126
  let e = (e) => {
127
- n === "system" && a(e.matches ? "light" : "dark");
127
+ r === "system" && o(e.matches ? "light" : "dark");
128
128
  }, t = window.matchMedia("(prefers-color-scheme: light)");
129
- return n === "system" ? (a(t.matches ? "light" : "dark"), t.addEventListener("change", e)) : a(n), () => t.removeEventListener("change", e);
130
- }, [n]), m(() => {
131
- let e = document.querySelector(".firebase-os") || document.documentElement, t = i === "dark" ? o.colors.dark : o.colors.light;
129
+ return r === "system" ? (o(t.matches ? "light" : "dark"), t.addEventListener("change", e)) : o(r), () => t.removeEventListener("change", e);
130
+ }, [r]), m(() => {
131
+ let e = (n ? document.querySelector(n) : document.documentElement) || document.documentElement, t = a === "dark" ? s.colors.dark : s.colors.light;
132
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 r = (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", r(t.buttonGradient)), e.style.setProperty("--button-fg", t.buttonText || "#ffffff"), e.style.setProperty("--button-hover-bg", r(t.buttonHoverGradient || t.buttonGradient)), e.style.setProperty("--text-gradient", r(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", i), localStorage.setItem("theme-mode", n), o.cornerRounding === "custom" && o.cornerRadii ? (e.style.setProperty("--btn-radius", `${parseFloat(String(o.cornerRadii.buttonRadius)) || 0}rem`), e.style.setProperty("--card-radius", `${parseFloat(String(o.cornerRadii.cardRadius)) || 0}rem`), e.style.setProperty("--input-radius", `${parseFloat(String(o.cornerRadii.inputRadius)) || 0}rem`), e.style.setProperty("--modal-radius", `${parseFloat(String(o.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) => {
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) => {
135
135
  let n = {
136
136
  Inter: "\"Inter\", sans-serif",
137
137
  Outfit: "\"Outfit\", sans-serif",
@@ -143,26 +143,26 @@ function qe({ children: t }) {
143
143
  e.style.setProperty("--font-family", n[t] || n.Inter);
144
144
  let r = document.getElementById("dynamic-google-font");
145
145
  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
- })(o.fontFamily || "Inter");
147
- let a = document.querySelector("link[rel*='icon']");
148
- a || (a = document.createElement("link"), a.rel = "icon", document.head.appendChild(a)), o.faviconUrl && (a.href = o.faviconUrl);
146
+ })(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
149
  }, [
150
- i,
151
- n,
152
- o
150
+ a,
151
+ r,
152
+ s
153
153
  ]), /* @__PURE__ */ B(Ke.Provider, {
154
154
  value: {
155
- theme: i,
156
- setTheme: (e) => r(e),
155
+ theme: a,
156
+ setTheme: (e) => i(e),
157
157
  toggleTheme: () => {
158
- r((e) => e === "light" ? "dark" : "light");
158
+ i((e) => e === "light" ? "dark" : "light");
159
159
  },
160
- isSystem: n === "system",
161
- setIsSystem: (e) => r(e ? "system" : i),
162
- config: o,
163
- activeConfig: o
160
+ isSystem: r === "system",
161
+ setIsSystem: (e) => i(e ? "system" : a),
162
+ config: s,
163
+ activeConfig: s
164
164
  },
165
- children: c ? t : null
165
+ children: l ? t : null
166
166
  });
167
167
  }
168
168
  var Je = () => {
@@ -89561,21 +89561,31 @@ var bUn = "rules_version = '2';\nservice cloud.firestore {\n match /databases/{
89561
89561
  }
89562
89562
  ];
89563
89563
  function CUn(e) {
89564
+ let t;
89564
89565
  try {
89565
- let t = {
89566
- BASE_URL: "/",
89567
- DEV: !1,
89568
- MODE: "production",
89569
- PROD: !0,
89570
- SSR: !1,
89571
- VITE_ADMIN_EMAILS: void 0,
89572
- VITE_FIREBASE_API_KEY: void 0,
89573
- VITE_FIREBASE_APP_ID: void 0,
89574
- VITE_FIREBASE_AUTH_DOMAIN: void 0,
89575
- VITE_FIREBASE_MESSAGING_SENDER_ID: void 0,
89576
- VITE_FIREBASE_PROJECT_ID: void 0,
89577
- VITE_FIREBASE_STORAGE_BUCKET: void 0
89578
- }?.[e];
89566
+ switch (e) {
89567
+ case "VITE_FIREBASE_API_KEY":
89568
+ t = void 0;
89569
+ break;
89570
+ case "VITE_FIREBASE_AUTH_DOMAIN":
89571
+ t = void 0;
89572
+ break;
89573
+ case "VITE_FIREBASE_PROJECT_ID":
89574
+ t = void 0;
89575
+ break;
89576
+ case "VITE_FIREBASE_STORAGE_BUCKET":
89577
+ t = void 0;
89578
+ break;
89579
+ case "VITE_FIREBASE_MESSAGING_SENDER_ID":
89580
+ t = void 0;
89581
+ break;
89582
+ case "VITE_FIREBASE_APP_ID":
89583
+ t = void 0;
89584
+ break;
89585
+ case "VITE_ADMIN_EMAILS":
89586
+ t = void 0;
89587
+ break;
89588
+ }
89579
89589
  if (t && typeof t == "string" && t.trim() !== "") return t;
89580
89590
  } catch {}
89581
89591
  try {
@@ -90369,7 +90379,8 @@ function IUn() {
90369
90379
  return /* @__PURE__ */ B(ye, { children: /* @__PURE__ */ B(LUn, {}) });
90370
90380
  }
90371
90381
  function LUn() {
90372
- return TUn() ? /* @__PURE__ */ B(FUn, {}) : /* @__PURE__ */ V("div", {
90382
+ let e = Ze();
90383
+ return e.firebaseConfig && e.firebaseConfig.apiKey && e.firebaseConfig.apiKey.trim() !== "" && e.firebaseConfig.projectId && e.firebaseConfig.projectId.trim() !== "" || TUn() ? /* @__PURE__ */ B(FUn, {}) : /* @__PURE__ */ V("div", {
90373
90384
  className: "min-h-screen relative flex flex-col overflow-x-hidden",
90374
90385
  children: [
90375
90386
  /* @__PURE__ */ B(Ms, { standalone: !0 }),
@@ -90388,22 +90399,25 @@ function RUn(e) {
90388
90399
  basename: e.basename,
90389
90400
  onAuthChange: e.onAuthChange
90390
90401
  },
90391
- children: /* @__PURE__ */ B(qe, { children: /* @__PURE__ */ V("div", {
90392
- className: "firebase-os",
90393
- style: {
90394
- position: "fixed",
90395
- inset: 0,
90396
- width: "100vw",
90397
- height: "100vh",
90398
- zIndex: 9999,
90399
- overflowY: "auto",
90400
- overflowX: "hidden",
90401
- textAlign: "left",
90402
- margin: 0,
90403
- padding: 0
90404
- },
90405
- children: [/* @__PURE__ */ B("style", { children: "\n .firebase-os h1, .firebase-os h2, .firebase-os h3, .firebase-os h4, .firebase-os h5, .firebase-os h6 {\n font-family: var(--font-family, 'Inter', system-ui, sans-serif) !important;\n }\n .firebase-os code, .firebase-os pre {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !important;\n background: transparent;\n border: none;\n }\n " }), /* @__PURE__ */ B(IUn, {})]
90406
- }) })
90402
+ children: /* @__PURE__ */ B(qe, {
90403
+ scopeSelector: ".firebase-os",
90404
+ children: /* @__PURE__ */ V("div", {
90405
+ className: "firebase-os",
90406
+ style: {
90407
+ position: "fixed",
90408
+ inset: 0,
90409
+ width: "100vw",
90410
+ height: "100vh",
90411
+ zIndex: 9999,
90412
+ overflowY: "auto",
90413
+ overflowX: "hidden",
90414
+ textAlign: "left",
90415
+ margin: 0,
90416
+ padding: 0
90417
+ },
90418
+ children: [/* @__PURE__ */ B("style", { children: "\n /* Defensive Typography Reset: Specificity 0,0,0 */\n /* This ensures we provide base styles without overriding ANY utility classes */\n :where(.firebase-os) :where(h1, h2, h3, h4, h5, h6, p, span, li, label, a, td, th) {\n color: var(--fg-color);\n font-family: var(--font-family, 'Inter', system-ui, sans-serif);\n }\n :where(.firebase-os) :where(h1, h2, h3, h4, h5, h6, p) {\n margin: 0;\n }\n :where(.firebase-os) :where(code, pre) {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !important;\n background: transparent;\n border: none;\n }\n " }), /* @__PURE__ */ B(IUn, {})]
90419
+ })
90420
+ })
90407
90421
  });
90408
90422
  }
90409
90423
  //#endregion
@@ -10,8 +10,9 @@ interface ThemeContextType {
10
10
  config: typeof themeConfig;
11
11
  activeConfig: any;
12
12
  }
13
- export declare function ThemeProvider({ children }: {
13
+ export declare function ThemeProvider({ children, scopeSelector }: {
14
14
  children: React.ReactNode;
15
+ scopeSelector?: string;
15
16
  }): import("react/jsx-runtime").JSX.Element;
16
17
  export declare const useTheme: () => ThemeContextType;
17
18
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-os",
3
- "version": "1.0.0",
3
+ "version": "1.1.3",
4
4
  "description": "A complete Firebase-powered admin OS — one React component.",
5
5
  "type": "module",
6
6
  "main": "dist/firebase-os.cjs.js",
@@ -41,10 +41,15 @@ if (pkgJson.name === 'firebase-os') {
41
41
  process.exit(0);
42
42
  }
43
43
 
44
- console.log('\n[firebase-os] Setting up project for zero-config usage...\n');
45
-
46
44
  const srcDir = path.join(consumerRoot, 'src');
47
45
 
46
+ // No src/ directory means this isn't a Vite/React project — skip silently
47
+ if (!fs.existsSync(srcDir)) {
48
+ process.exit(0);
49
+ }
50
+
51
+ console.log('\n[firebase-os] Setting up project for zero-config usage...\n');
52
+
48
53
  // ── 1. Clear Vite's default conflicting CSS files ───────────────────────────
49
54
  const cssFiles = ['index.css', 'App.css'];
50
55
  for (const file of cssFiles) {
@@ -81,8 +86,30 @@ const appPath = path.join(srcDir, 'App.tsx');
81
86
  const appContent = `import { FirebaseOS } from 'firebase-os';
82
87
  import 'firebase-os/styles.css';
83
88
 
89
+ // Vite injects these from your .env file at dev/build time.
90
+ // The library can't read them directly since it's pre-built,
91
+ // so we pass them as props.
92
+ const firebaseConfig = {
93
+ apiKey: import.meta.env.VITE_FIREBASE_API_KEY || '',
94
+ authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || '',
95
+ projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || '',
96
+ storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || '',
97
+ messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || '',
98
+ appId: import.meta.env.VITE_FIREBASE_APP_ID || '',
99
+ };
100
+
101
+ const adminEmails = (import.meta.env.VITE_ADMIN_EMAILS || '')
102
+ .split(',')
103
+ .map((e: string) => e.trim())
104
+ .filter(Boolean);
105
+
84
106
  export default function App() {
85
- return <FirebaseOS />;
107
+ return (
108
+ <FirebaseOS
109
+ firebaseConfig={firebaseConfig}
110
+ adminEmails={adminEmails}
111
+ />
112
+ );
86
113
  }
87
114
  `;
88
115
 
@@ -95,4 +122,25 @@ if (!existingApp.includes('firebase-os')) {
95
122
  console.log(' ℹ App.tsx already uses firebase-os — skipped');
96
123
  }
97
124
 
125
+ // ── 4. Create .env file with placeholders ──────────────────────────────────
126
+ const envPath = path.join(consumerRoot, '.env');
127
+ if (!fs.existsSync(envPath)) {
128
+ const envContent = `# 🔥 Firebase OS Configuration
129
+ # Paste your Firebase Web App configuration here.
130
+ # You can find these in your Firebase Console -> Project Settings -> General -> Your Apps
131
+
132
+ VITE_FIREBASE_API_KEY=your_api_key_here
133
+ VITE_FIREBASE_AUTH_DOMAIN=your_project_id.firebaseapp.com
134
+ VITE_FIREBASE_PROJECT_ID=your_project_id
135
+ VITE_FIREBASE_STORAGE_BUCKET=your_project_id.firebasestorage.app
136
+ VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
137
+ VITE_FIREBASE_APP_ID=your_app_id
138
+
139
+ # Comma-separated list of admin emails
140
+ VITE_ADMIN_EMAILS=your_email@example.com
141
+ `;
142
+ fs.writeFileSync(envPath, envContent);
143
+ console.log(' ✓ Created .env file with configuration placeholders');
144
+ }
145
+
98
146
  console.log('\n[firebase-os] Setup complete! Run `npm run dev` to start.\n');