firebase-os 1.1.4 → 1.1.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/dist/FirebaseOS.d.ts +15 -0
- package/dist/firebase-os.cjs.js +5 -20
- package/dist/firebase-os.es.js +95 -90
- package/dist/index.d.ts +3 -0
- package/dist/lib/ConfigContext.d.ts +12 -0
- package/package.json +3 -2
- package/scripts/postinstall.js +86 -15
- package/src/App.css +184 -0
- package/src/App.tsx +214 -0
- package/src/FirebaseOS.tsx +81 -0
- package/src/assets/hero.png +0 -0
- package/src/assets/react.svg +1 -0
- package/src/assets/vite.svg +1 -0
- package/src/components/AdminNotifications.test.tsx +98 -0
- package/src/components/AdminNotifications.tsx +194 -0
- package/src/components/Button.test.tsx +22 -0
- package/src/components/Button.tsx +53 -0
- package/src/components/ConfirmModal.test.tsx +98 -0
- package/src/components/ConfirmModal.tsx +73 -0
- package/src/components/ContactPopup.test.tsx +98 -0
- package/src/components/ContactPopup.tsx +437 -0
- package/src/components/CustomSelect.test.tsx +47 -0
- package/src/components/CustomSelect.tsx +89 -0
- package/src/components/DashboardNav.test.tsx +98 -0
- package/src/components/DashboardNav.tsx +281 -0
- package/src/components/Input.test.tsx +33 -0
- package/src/components/Input.tsx +61 -0
- package/src/components/JsonEditor.tsx +579 -0
- package/src/components/Navbar.test.tsx +98 -0
- package/src/components/Navbar.tsx +563 -0
- package/src/configs/forms/contactForm.config.ts +15 -0
- package/src/configs/forms/index.ts +29 -0
- package/src/configs/forms/pubForm.config.ts +11 -0
- package/src/configs/forms/supportForm.config.ts +14 -0
- package/src/configs/forms/userForm.config.ts +11 -0
- package/src/configs/pages/admin.config.ts +29 -0
- package/src/configs/pages/contact.config.ts +6 -0
- package/src/configs/pages/home.config.ts +18 -0
- package/src/configs/pages/mem.config.ts +2 -0
- package/src/configs/pages/menuOrders.config.ts +11 -0
- package/src/configs/pages/pub.config.ts +11 -0
- package/src/configs/pages/shared.config.ts +29 -0
- package/src/configs/pages/support.config.ts +7 -0
- package/src/configs/pages/tabOrders.config.ts +33 -0
- package/src/configs/pages/user.config.ts +29 -0
- package/src/configs/theme.config.ts +93 -0
- package/src/index.css +403 -0
- package/src/index.ts +22 -0
- package/src/lib/AuthContext.test.tsx +88 -0
- package/src/lib/AuthContext.tsx +191 -0
- package/src/lib/ConfigContext.tsx +45 -0
- package/src/lib/ThemeContext.tsx +233 -0
- package/src/lib/firebase.ts +91 -0
- package/src/main.tsx +22 -0
- package/src/microcomponents/AdminExampleContent.tsx +44 -0
- package/src/microcomponents/PrivateExampleContent.tsx +39 -0
- package/src/microcomponents/Public.tsx +126 -0
- package/src/microcomponents/SharedExampleContent.tsx +53 -0
- package/src/pages/Dashboard.test.tsx +98 -0
- package/src/pages/Dashboard.tsx +60 -0
- package/src/pages/DynamicPage.tsx +237 -0
- package/src/pages/FormsAdmin.test.tsx +98 -0
- package/src/pages/FormsAdmin.tsx +459 -0
- package/src/pages/Home.test.tsx +98 -0
- package/src/pages/Home.tsx +144 -0
- package/src/pages/Login.test.tsx +98 -0
- package/src/pages/Login.tsx +108 -0
- package/src/pages/PagesAdmin.test.tsx +98 -0
- package/src/pages/PagesAdmin.tsx +1022 -0
- package/src/pages/Profile.test.tsx +98 -0
- package/src/pages/Profile.tsx +319 -0
- package/src/pages/Register.test.tsx +98 -0
- package/src/pages/Register.tsx +116 -0
- package/src/pages/Requests.test.tsx +95 -0
- package/src/pages/Requests.tsx +422 -0
- package/src/pages/ResetPassword.test.tsx +98 -0
- package/src/pages/ResetPassword.tsx +92 -0
- package/src/pages/Settings.test.tsx +98 -0
- package/src/pages/Settings.tsx +393 -0
- package/src/pages/Setup.tsx +407 -0
- package/src/pages/StorageAdmin.test.tsx +150 -0
- package/src/pages/StorageAdmin.tsx +769 -0
- package/src/pages/Submissions.test.tsx +95 -0
- package/src/pages/Submissions.tsx +378 -0
- package/src/pages/Templates.test.tsx +98 -0
- package/src/pages/Templates.tsx +103 -0
- package/src/pages/ThemeAdmin.test.tsx +144 -0
- package/src/pages/ThemeAdmin.tsx +1000 -0
- package/src/pages/Users.test.tsx +95 -0
- package/src/pages/Users.tsx +334 -0
- package/src/pages/Verify.test.tsx +98 -0
- package/src/pages/Verify.tsx +95 -0
- package/src/prompts/index.ts +13 -0
- package/src/prompts/pages/publicPage.ts +44 -0
- package/src/prompts/sharedConstants.ts +12 -0
- package/src/prompts/tabs/board/adminboard.ts +32 -0
- package/src/prompts/tabs/board/privateboard.ts +36 -0
- package/src/prompts/tabs/board/publicboard.ts +36 -0
- package/src/prompts/tabs/calendar/admincalendar.ts +32 -0
- package/src/prompts/tabs/calendar/privatecalendar.ts +36 -0
- package/src/prompts/tabs/calendar/publiccalendar.ts +36 -0
- package/src/prompts/tabs/crud/admin.ts +54 -0
- package/src/prompts/tabs/crud/private.ts +55 -0
- package/src/prompts/tabs/crud/shared.ts +53 -0
- package/src/prompts/tabs/table/admintable.ts +32 -0
- package/src/prompts/tabs/table/privatetable.ts +36 -0
- package/src/prompts/tabs/table/publictable.ts +36 -0
- package/src/setupTests.ts +1 -0
- package/src/templates/AdminPageTemplate.tsx +678 -0
- package/src/templates/PrivatePageTemplate.tsx +594 -0
- package/src/templates/PublicPageTemplate.tsx +92 -0
- package/src/templates/SharedPageTemplate.tsx +551 -0
- package/src/templates/TemplateBoard.test.tsx +106 -0
- package/src/templates/TemplateBoard.tsx +642 -0
- package/src/templates/TemplateCalendar.test.tsx +106 -0
- package/src/templates/TemplateCalendar.tsx +848 -0
- package/src/templates/TemplateConfirmation.test.tsx +106 -0
- package/src/templates/TemplateConfirmation.tsx +145 -0
- package/src/templates/TemplateInlineForm.test.tsx +106 -0
- package/src/templates/TemplateInlineForm.tsx +129 -0
- package/src/templates/TemplatePopupForm.test.tsx +106 -0
- package/src/templates/TemplatePopupForm.tsx +174 -0
- package/src/templates/TemplateTable.test.tsx +106 -0
- package/src/templates/TemplateTable.tsx +675 -0
package/dist/firebase-os.es.js
CHANGED
|
@@ -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),
|
|
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
|
|
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
|
|
148
|
-
|
|
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("
|
|
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("
|
|
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", {
|
|
@@ -89363,62 +89375,62 @@ function vUn({ config: e }) {
|
|
|
89363
89375
|
//#endregion
|
|
89364
89376
|
//#region src/pages/DynamicPage.tsx
|
|
89365
89377
|
function yUn() {
|
|
89366
|
-
let e = Se(), { user: t } = $e(),
|
|
89378
|
+
let e = Se(), { user: t } = $e(), n = Ze(), [r, i] = x(null), [a, o] = x(!0);
|
|
89367
89379
|
m(() => {
|
|
89368
89380
|
(async () => {
|
|
89369
|
-
|
|
89381
|
+
o(!0);
|
|
89370
89382
|
try {
|
|
89371
|
-
let [t, n] = await Promise.all([ee(C(W, "sys_pages")), ee(C(W, "sys_tabs"))]),
|
|
89383
|
+
let [t, n] = await Promise.all([ee(C(W, "sys_pages")), ee(C(W, "sys_tabs"))]), r = null, a = null, o = (t, n) => {
|
|
89372
89384
|
t.forEach((t) => {
|
|
89373
|
-
let
|
|
89385
|
+
let i = t.data(), o = i.route;
|
|
89374
89386
|
o && !o.startsWith("/") && (o = "/" + o);
|
|
89375
89387
|
let s = "/" + t.id === e.pathname;
|
|
89376
|
-
(o === e.pathname || s) && (
|
|
89377
|
-
...
|
|
89388
|
+
(o === e.pathname || s) && (r = {
|
|
89389
|
+
...i,
|
|
89378
89390
|
isPrivate: n,
|
|
89379
|
-
isAdmin:
|
|
89380
|
-
isShared:
|
|
89391
|
+
isAdmin: i.pageType === "admin",
|
|
89392
|
+
isShared: i.pageType === "shared"
|
|
89381
89393
|
}, a = t.id);
|
|
89382
89394
|
});
|
|
89383
89395
|
};
|
|
89384
|
-
if (o(t, !1),
|
|
89396
|
+
if (o(t, !1), r || o(n, !0), r || (e.pathname === "/contact" ? (r = {
|
|
89385
89397
|
route: "/contact",
|
|
89386
89398
|
template: "popup_form",
|
|
89387
89399
|
form: "contact"
|
|
89388
|
-
}, a = "contact") : e.pathname === "/support" && (
|
|
89400
|
+
}, a = "contact") : e.pathname === "/support" && (r = {
|
|
89389
89401
|
route: "/support",
|
|
89390
89402
|
template: "popup_form",
|
|
89391
89403
|
form: "support"
|
|
89392
|
-
}, a = "support")),
|
|
89393
|
-
if ((a === "contact" || a === "support") && !
|
|
89394
|
-
let e = await E(T(W, "sys_forms",
|
|
89395
|
-
if (e.exists())
|
|
89404
|
+
}, a = "support")), r) {
|
|
89405
|
+
if ((a === "contact" || a === "support") && !r.form && (r.form = a), r.pageId = a, r.form) {
|
|
89406
|
+
let e = await E(T(W, "sys_forms", r.form));
|
|
89407
|
+
if (e.exists()) r.formConfigOverride = {
|
|
89396
89408
|
...e.data(),
|
|
89397
89409
|
id: e.id
|
|
89398
89410
|
};
|
|
89399
|
-
else if (
|
|
89411
|
+
else if (r.form === "contact") {
|
|
89400
89412
|
let { contactFormConfig: e } = await import("./contactForm.config-DLeI_ZEj.js");
|
|
89401
|
-
|
|
89402
|
-
} else if (
|
|
89413
|
+
r.formConfigOverride = e;
|
|
89414
|
+
} else if (r.form === "support") {
|
|
89403
89415
|
let { supportFormConfig: e } = await import("./supportForm.config-74T-eSSH.js");
|
|
89404
|
-
|
|
89416
|
+
r.formConfigOverride = e;
|
|
89405
89417
|
}
|
|
89406
89418
|
}
|
|
89407
|
-
let e =
|
|
89408
|
-
e && (document.title = e), r
|
|
89409
|
-
} else
|
|
89419
|
+
let e = r.pageName || r.tabName || r.title;
|
|
89420
|
+
e && (document.title = e), i(r);
|
|
89421
|
+
} else i("not-found");
|
|
89410
89422
|
} catch {
|
|
89411
|
-
|
|
89423
|
+
i("not-found");
|
|
89412
89424
|
} finally {
|
|
89413
|
-
|
|
89425
|
+
o(!1);
|
|
89414
89426
|
}
|
|
89415
89427
|
})();
|
|
89416
89428
|
}, [e.pathname]);
|
|
89417
|
-
let [
|
|
89429
|
+
let [s, c] = x(!1);
|
|
89418
89430
|
if (m(() => {
|
|
89419
89431
|
let e;
|
|
89420
|
-
return
|
|
89421
|
-
}, [
|
|
89432
|
+
return a ? e = setTimeout(() => c(!0), 150) : c(!1), () => clearTimeout(e);
|
|
89433
|
+
}, [a]), a) return s ? t ? /* @__PURE__ */ V("main", {
|
|
89422
89434
|
className: "flex-1 w-full max-w-7xl mx-auto p-4 md:p-8 z-10 flex flex-col",
|
|
89423
89435
|
children: [/* @__PURE__ */ V("div", {
|
|
89424
89436
|
className: "mb-6",
|
|
@@ -89434,7 +89446,7 @@ function yUn() {
|
|
|
89434
89446
|
className: "flex-1 flex items-center justify-center min-h-[60vh] z-10",
|
|
89435
89447
|
children: /* @__PURE__ */ B(K, { className: "w-6 h-6 animate-spin text-accent" })
|
|
89436
89448
|
}) : null;
|
|
89437
|
-
if (
|
|
89449
|
+
if (r === "not-found") return /* @__PURE__ */ B("main", {
|
|
89438
89450
|
className: "flex-1 w-full max-w-7xl mx-auto p-4 md:p-8 z-10 flex flex-col pt-12 min-h-screen",
|
|
89439
89451
|
children: /* @__PURE__ */ V("div", {
|
|
89440
89452
|
className: "flex flex-col items-center justify-center flex-1 text-center",
|
|
@@ -89481,53 +89493,53 @@ function yUn() {
|
|
|
89481
89493
|
]
|
|
89482
89494
|
})
|
|
89483
89495
|
});
|
|
89484
|
-
if ((
|
|
89496
|
+
if ((r.pageId === "support" || r.isPrivate) && !t) return /* @__PURE__ */ B(be, {
|
|
89485
89497
|
to: "/login",
|
|
89486
89498
|
state: { from: e }
|
|
89487
89499
|
});
|
|
89488
|
-
let
|
|
89489
|
-
if (
|
|
89490
|
-
if (
|
|
89491
|
-
let e =
|
|
89492
|
-
return /* @__PURE__ */ B(JVn, {
|
|
89493
|
-
title:
|
|
89494
|
-
subtitle:
|
|
89500
|
+
let l = r.pageName?.toLowerCase().replace(/\s+/g, "_") || r.pageId || "custom_page", u = `pub_${l}`;
|
|
89501
|
+
if (r.template === "none") return r.isAdmin ? /* @__PURE__ */ B(_Un, { config: r }) : r.isShared ? /* @__PURE__ */ B(vUn, { config: r }) : r.isPrivate ? /* @__PURE__ */ B(gUn, { config: r }) : /* @__PURE__ */ B(hUn, { config: r });
|
|
89502
|
+
if (r.template === "board") {
|
|
89503
|
+
let e = r.isAdmin ? `admin_${r.pageId || l}` : r.isShared ? `mem_${r.pageId || l}` : r.isPrivate ? `user_${r.pageId || l}` : u;
|
|
89504
|
+
return /* @__PURE__ */ B(n.components?.TemplateBoard || JVn, {
|
|
89505
|
+
title: r.tabTitle || r.tabName || r.title || r.pageName || "Board",
|
|
89506
|
+
subtitle: r.route,
|
|
89495
89507
|
tasksCollection: `${e}_tasks`,
|
|
89496
89508
|
categoriesCollection: `${e}_categories`,
|
|
89497
|
-
config:
|
|
89509
|
+
config: r
|
|
89498
89510
|
});
|
|
89499
89511
|
}
|
|
89500
|
-
if (
|
|
89501
|
-
let e =
|
|
89502
|
-
return /* @__PURE__ */ B($Hn, {
|
|
89503
|
-
title:
|
|
89504
|
-
subtitle:
|
|
89512
|
+
if (r.template === "table") {
|
|
89513
|
+
let e = r.isAdmin ? `admin_${r.pageId || l}` : r.isShared ? `mem_${r.pageId || l}` : r.isPrivate ? `user_${r.pageId || l}` : u;
|
|
89514
|
+
return /* @__PURE__ */ B(n.components?.TemplateTable || $Hn, {
|
|
89515
|
+
title: r.tabTitle || r.tabName || r.title || r.pageName || "Table",
|
|
89516
|
+
subtitle: r.route,
|
|
89505
89517
|
tableCollection: `${e}_table`,
|
|
89506
|
-
config:
|
|
89518
|
+
config: r
|
|
89507
89519
|
});
|
|
89508
89520
|
}
|
|
89509
|
-
if (
|
|
89510
|
-
let e =
|
|
89511
|
-
return /* @__PURE__ */ B(tUn, {
|
|
89512
|
-
title:
|
|
89513
|
-
subtitle:
|
|
89521
|
+
if (r.template === "calendar") {
|
|
89522
|
+
let e = r.isAdmin ? `admin_${r.pageId || l}` : r.isShared ? `mem_${r.pageId || l}` : r.isPrivate ? `user_${r.pageId || l}` : u;
|
|
89523
|
+
return /* @__PURE__ */ B(n.components?.TemplateCalendar || tUn, {
|
|
89524
|
+
title: r.tabTitle || r.tabName || r.title || r.pageName || "Calendar",
|
|
89525
|
+
subtitle: r.route,
|
|
89514
89526
|
eventsCollection: `${e}_events`,
|
|
89515
|
-
defaultTimeFormat:
|
|
89516
|
-
config:
|
|
89527
|
+
defaultTimeFormat: r.defaultTimeFormat || r.defaulttimeformat || "12h",
|
|
89528
|
+
config: r
|
|
89517
89529
|
});
|
|
89518
89530
|
}
|
|
89519
|
-
return
|
|
89531
|
+
return r.template === "inline_form" ? /* @__PURE__ */ B("div", {
|
|
89520
89532
|
className: "flex-1 flex flex-col items-center justify-start mt-8 relative z-10 w-full min-h-[60vh]",
|
|
89521
89533
|
children: /* @__PURE__ */ B(Es, {
|
|
89522
89534
|
isInline: !0,
|
|
89523
|
-
formId:
|
|
89524
|
-
formConfig:
|
|
89535
|
+
formId: r.form,
|
|
89536
|
+
formConfig: r.formConfigOverride
|
|
89525
89537
|
})
|
|
89526
89538
|
}) : /* @__PURE__ */ B("div", {
|
|
89527
89539
|
className: "flex-1 flex flex-col items-center justify-center relative z-10 w-full min-h-[60vh]",
|
|
89528
89540
|
children: /* @__PURE__ */ B(Es, {
|
|
89529
|
-
formId:
|
|
89530
|
-
formConfig:
|
|
89541
|
+
formId: r.form,
|
|
89542
|
+
formConfig: r.formConfigOverride,
|
|
89531
89543
|
onClose: () => window.history.back()
|
|
89532
89544
|
})
|
|
89533
89545
|
});
|
|
@@ -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
|
-
|
|
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
|
|
@@ -90265,6 +90277,7 @@ function PUn() {
|
|
|
90265
90277
|
});
|
|
90266
90278
|
}
|
|
90267
90279
|
function FUn() {
|
|
90280
|
+
let e = Ze().components?.Home || fce;
|
|
90268
90281
|
return /* @__PURE__ */ B(eee, { children: /* @__PURE__ */ V("div", {
|
|
90269
90282
|
className: "min-h-screen relative flex flex-col overflow-x-hidden",
|
|
90270
90283
|
children: [
|
|
@@ -90272,7 +90285,7 @@ function FUn() {
|
|
|
90272
90285
|
/* @__PURE__ */ V(xe, { children: [
|
|
90273
90286
|
/* @__PURE__ */ B(U, {
|
|
90274
90287
|
path: "/",
|
|
90275
|
-
element: /* @__PURE__ */ B(Q9, { children: /* @__PURE__ */ B(
|
|
90288
|
+
element: /* @__PURE__ */ B(Q9, { children: /* @__PURE__ */ B(e, {}) })
|
|
90276
90289
|
}),
|
|
90277
90290
|
/* @__PURE__ */ B(U, {
|
|
90278
90291
|
path: "/register",
|
|
@@ -90364,7 +90377,10 @@ function FUn() {
|
|
|
90364
90377
|
}),
|
|
90365
90378
|
/* @__PURE__ */ B(U, {
|
|
90366
90379
|
path: "/setup",
|
|
90367
|
-
element: /* @__PURE__ */ B(
|
|
90380
|
+
element: /* @__PURE__ */ B(be, {
|
|
90381
|
+
to: "/",
|
|
90382
|
+
replace: !0
|
|
90383
|
+
})
|
|
90368
90384
|
}),
|
|
90369
90385
|
/* @__PURE__ */ B(U, {
|
|
90370
90386
|
path: "*",
|
|
@@ -90397,30 +90413,19 @@ function RUn(e) {
|
|
|
90397
90413
|
firebaseConfig: e.firebaseConfig,
|
|
90398
90414
|
adminEmails: e.adminEmails,
|
|
90399
90415
|
basename: e.basename,
|
|
90400
|
-
onAuthChange: e.onAuthChange
|
|
90416
|
+
onAuthChange: e.onAuthChange,
|
|
90417
|
+
themeConfig: e.themeConfig,
|
|
90418
|
+
components: e.components
|
|
90401
90419
|
},
|
|
90402
|
-
children: /* @__PURE__ */ B(qe, {
|
|
90403
|
-
|
|
90404
|
-
|
|
90405
|
-
|
|
90406
|
-
|
|
90407
|
-
|
|
90408
|
-
|
|
90409
|
-
|
|
90410
|
-
height: "100vh",
|
|
90411
|
-
zIndex: 9999,
|
|
90412
|
-
overflowY: "auto",
|
|
90413
|
-
overflowX: "hidden",
|
|
90414
|
-
textAlign: "left",
|
|
90415
|
-
margin: 0,
|
|
90416
|
-
padding: 0,
|
|
90417
|
-
background: "var(--bg-gradient)",
|
|
90418
|
-
color: "var(--fg-color)"
|
|
90419
|
-
},
|
|
90420
|
-
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, {})]
|
|
90421
|
-
})
|
|
90422
|
-
})
|
|
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
|
+
}) })
|
|
90423
90428
|
});
|
|
90424
90429
|
}
|
|
90425
90430
|
//#endregion
|
|
90426
|
-
export { RUn as FirebaseOS, $e as useAuth, Ze as useConfig, Je as useTheme };
|
|
90431
|
+
export { Es as ContactPopup, RUn as FirebaseOS, Ie as auth, W as db, Ns as defaultHomeConfig, Le as storage, $e as useAuth, Ze as useConfig, Je as useTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,3 +4,6 @@ export { useAuth } from './lib/AuthContext';
|
|
|
4
4
|
export { useTheme } from './lib/ThemeContext';
|
|
5
5
|
export { useConfig } from './lib/ConfigContext';
|
|
6
6
|
export type { FirebaseOSConfig } from './lib/ConfigContext';
|
|
7
|
+
export { db, auth, storage } from './lib/firebase';
|
|
8
|
+
export { ContactPopup } from './components/ContactPopup';
|
|
9
|
+
export { defaultHomeConfig } from './configs/pages/home.config';
|
|
@@ -11,6 +11,18 @@ export interface FirebaseOSConfig {
|
|
|
11
11
|
adminEmails?: string[];
|
|
12
12
|
basename?: string;
|
|
13
13
|
onAuthChange?: (user: any) => void;
|
|
14
|
+
themeConfig?: any;
|
|
15
|
+
components?: {
|
|
16
|
+
Home?: React.ComponentType<any>;
|
|
17
|
+
TemplateBoard?: React.ComponentType<any>;
|
|
18
|
+
TemplateTable?: React.ComponentType<any>;
|
|
19
|
+
TemplateCalendar?: React.ComponentType<any>;
|
|
20
|
+
TemplatePopupForm?: React.ComponentType<any>;
|
|
21
|
+
TemplateInlineForm?: React.ComponentType<any>;
|
|
22
|
+
TemplatePages?: React.ComponentType<any>;
|
|
23
|
+
TemplateStorage?: React.ComponentType<any>;
|
|
24
|
+
TemplateNone?: React.ComponentType<any>;
|
|
25
|
+
};
|
|
14
26
|
}
|
|
15
27
|
export declare function ConfigProvider({ config, children }: {
|
|
16
28
|
config: FirebaseOSConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-os",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "A complete Firebase-powered admin OS — one React component.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/firebase-os.cjs.js",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
24
|
-
"scripts"
|
|
24
|
+
"scripts",
|
|
25
|
+
"src"
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
28
|
"dev": "vite",
|
package/scripts/postinstall.js
CHANGED
|
@@ -81,22 +81,54 @@ createRoot(document.getElementById('root')!).render(
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
// ── 3.
|
|
85
|
-
const
|
|
86
|
-
|
|
84
|
+
// ── 3. Hybrid Architecture: Create local overrides directory ─────────────
|
|
85
|
+
const fbosDir = path.join(srcDir, 'firebase-os');
|
|
86
|
+
if (!fs.existsSync(fbosDir)) fs.mkdirSync(fbosDir, { recursive: true });
|
|
87
|
+
|
|
88
|
+
// Copy raw index.css to give user full control over Tailwind and variables
|
|
89
|
+
const sourceCssPath = path.join(__dirname, '..', 'src', 'index.css');
|
|
87
90
|
if (fs.existsSync(sourceCssPath)) {
|
|
88
|
-
fs.copyFileSync(sourceCssPath,
|
|
89
|
-
console.log(' ✓ Copied
|
|
91
|
+
fs.copyFileSync(sourceCssPath, path.join(fbosDir, 'theme.css'));
|
|
92
|
+
console.log(' ✓ Copied theme.css to your src/firebase-os directory');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Copy configurations
|
|
96
|
+
const configsDir = path.join(fbosDir, 'configs');
|
|
97
|
+
if (!fs.existsSync(configsDir)) fs.mkdirSync(configsDir, { recursive: true });
|
|
98
|
+
|
|
99
|
+
const copyConfig = (srcPath, destName) => {
|
|
100
|
+
const fullSrc = path.join(__dirname, '..', 'src', 'configs', srcPath);
|
|
101
|
+
if (fs.existsSync(fullSrc)) {
|
|
102
|
+
fs.copyFileSync(fullSrc, path.join(configsDir, destName));
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
copyConfig('theme.config.ts', 'theme.config.ts');
|
|
106
|
+
copyConfig('pages/home.config.ts', 'home.config.ts');
|
|
107
|
+
copyConfig('forms/contactForm.config.ts', 'contactForm.config.ts');
|
|
108
|
+
copyConfig('forms/supportForm.config.ts', 'supportForm.config.ts');
|
|
109
|
+
console.log(' ✓ Copied configuration files to your src/firebase-os/configs directory');
|
|
110
|
+
|
|
111
|
+
// Read and rewrite Home.tsx
|
|
112
|
+
const sourceHomePath = path.join(__dirname, '..', 'src', 'pages', 'Home.tsx');
|
|
113
|
+
if (fs.existsSync(sourceHomePath)) {
|
|
114
|
+
let homeContent = fs.readFileSync(sourceHomePath, 'utf8');
|
|
115
|
+
homeContent = homeContent.replace(/from '\.\.\/components\/ContactPopup'/g, "from 'firebase-os'");
|
|
116
|
+
homeContent = homeContent.replace(/from '\.\.\/lib\/firebase'/g, "from 'firebase-os'");
|
|
117
|
+
homeContent = homeContent.replace(/from '\.\.\/configs\/pages\/home\.config'/g, "from './configs/home.config'");
|
|
118
|
+
fs.writeFileSync(path.join(fbosDir, 'Home.tsx'), homeContent);
|
|
119
|
+
console.log(' ✓ Created local Home.tsx template override');
|
|
90
120
|
}
|
|
91
121
|
|
|
92
|
-
// ── 4. Write App.tsx with
|
|
122
|
+
// ── 4. Write App.tsx with Hybrid Overrides Wired Up ───────────────────────
|
|
93
123
|
const appPath = path.join(srcDir, 'App.tsx');
|
|
94
124
|
const appContent = `import { FirebaseOS } from 'firebase-os';
|
|
95
|
-
import './firebase-os.css';
|
|
125
|
+
import './firebase-os/theme.css';
|
|
126
|
+
|
|
127
|
+
// Local Hybrid Overrides
|
|
128
|
+
import { Home } from './firebase-os/Home';
|
|
129
|
+
import { themeConfig } from './firebase-os/configs/theme.config';
|
|
96
130
|
|
|
97
131
|
// Vite injects these from your .env file at dev/build time.
|
|
98
|
-
// The library can't read them directly since it's pre-built,
|
|
99
|
-
// so we pass them as props.
|
|
100
132
|
const firebaseConfig = {
|
|
101
133
|
apiKey: import.meta.env.VITE_FIREBASE_API_KEY || '',
|
|
102
134
|
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || '',
|
|
@@ -116,21 +148,57 @@ export default function App() {
|
|
|
116
148
|
<FirebaseOS
|
|
117
149
|
firebaseConfig={firebaseConfig}
|
|
118
150
|
adminEmails={adminEmails}
|
|
151
|
+
themeConfig={themeConfig}
|
|
152
|
+
components={{
|
|
153
|
+
Home: Home
|
|
154
|
+
}}
|
|
119
155
|
/>
|
|
120
156
|
);
|
|
121
157
|
}
|
|
122
158
|
`;
|
|
123
159
|
|
|
124
|
-
// Only write if the file doesn't already import FirebaseOS
|
|
125
160
|
const existingApp = fs.existsSync(appPath) ? fs.readFileSync(appPath, 'utf8') : '';
|
|
126
161
|
if (!existingApp.includes('firebase-os')) {
|
|
127
162
|
fs.writeFileSync(appPath, appContent);
|
|
128
|
-
console.log(' ✓ Wrote App.tsx with <FirebaseOS /> ready to go');
|
|
163
|
+
console.log(' ✓ Wrote App.tsx with <FirebaseOS /> hybrid architecture ready to go');
|
|
129
164
|
} else {
|
|
130
165
|
console.log(' ℹ App.tsx already uses firebase-os — skipped');
|
|
131
166
|
}
|
|
132
167
|
|
|
133
|
-
// ──
|
|
168
|
+
// ── 5. Setup Tailwind V4 in host app ───────────────────────────────────────
|
|
169
|
+
// We'll update the user's package.json to include tailwindcss dependencies
|
|
170
|
+
const pkgPath = path.join(consumerRoot, 'package.json');
|
|
171
|
+
if (fs.existsSync(pkgPath)) {
|
|
172
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
173
|
+
let pkgModified = false;
|
|
174
|
+
pkg.devDependencies = pkg.devDependencies || {};
|
|
175
|
+
|
|
176
|
+
if (!pkg.devDependencies['tailwindcss']) {
|
|
177
|
+
pkg.devDependencies['tailwindcss'] = '^4.0.0';
|
|
178
|
+
pkgModified = true;
|
|
179
|
+
}
|
|
180
|
+
if (!pkg.devDependencies['@tailwindcss/vite']) {
|
|
181
|
+
pkg.devDependencies['@tailwindcss/vite'] = '^4.0.0';
|
|
182
|
+
pkgModified = true;
|
|
183
|
+
}
|
|
184
|
+
if (pkgModified) {
|
|
185
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
186
|
+
console.log(' ✓ Added tailwindcss and @tailwindcss/vite to your package.json');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const viteConfigPath = path.join(consumerRoot, 'vite.config.ts');
|
|
191
|
+
if (fs.existsSync(viteConfigPath)) {
|
|
192
|
+
let viteConfig = fs.readFileSync(viteConfigPath, 'utf8');
|
|
193
|
+
if (!viteConfig.includes('@tailwindcss/vite')) {
|
|
194
|
+
viteConfig = "import tailwindcss from '@tailwindcss/vite';\\n" + viteConfig;
|
|
195
|
+
viteConfig = viteConfig.replace('plugins: [', 'plugins: [\\n tailwindcss(),');
|
|
196
|
+
fs.writeFileSync(viteConfigPath, viteConfig);
|
|
197
|
+
console.log(' ✓ Patched vite.config.ts to enable Tailwind CSS v4');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ── 6. Create .env file with placeholders ──────────────────────────────────
|
|
134
202
|
const envPath = path.join(consumerRoot, '.env');
|
|
135
203
|
if (!fs.existsSync(envPath)) {
|
|
136
204
|
const envContent = `# 🔥 Firebase OS Configuration
|
|
@@ -145,10 +213,13 @@ VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
|
|
|
145
213
|
VITE_FIREBASE_APP_ID=your_app_id
|
|
146
214
|
|
|
147
215
|
# Comma-separated list of admin emails
|
|
148
|
-
VITE_ADMIN_EMAILS=
|
|
216
|
+
VITE_ADMIN_EMAILS=admin@example.com
|
|
149
217
|
`;
|
|
150
218
|
fs.writeFileSync(envPath, envContent);
|
|
151
|
-
console.log(' ✓ Created .env
|
|
219
|
+
console.log(' ✓ Created .env template');
|
|
152
220
|
}
|
|
153
221
|
|
|
154
|
-
console.log('\n[firebase-os] Setup complete!
|
|
222
|
+
console.log('\n[firebase-os] 🎉 Hybrid Setup complete! You now have full control over styling and configs.\n');
|
|
223
|
+
console.log('🚨 IMPORTANT NEXT STEPS:');
|
|
224
|
+
console.log('1. Run `npm install` again to install the required Tailwind CSS dependencies.');
|
|
225
|
+
console.log('2. Run `npm run dev` to start your app.\n');
|