firebase-os 1.1.3 → 1.1.5
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 +2 -17
- package/dist/firebase-os.es.js +63 -72
- package/dist/index.d.ts +3 -0
- package/dist/lib/ConfigContext.d.ts +12 -0
- package/package.json +3 -2
- package/scripts/postinstall.js +89 -10
- package/src/App.css +184 -0
- package/src/App.tsx +214 -0
- package/src/FirebaseOS.tsx +80 -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 +227 -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 +401 -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 +372 -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
|
@@ -89363,62 +89363,62 @@ function vUn({ config: e }) {
|
|
|
89363
89363
|
//#endregion
|
|
89364
89364
|
//#region src/pages/DynamicPage.tsx
|
|
89365
89365
|
function yUn() {
|
|
89366
|
-
let e = Se(), { user: t } = $e(),
|
|
89366
|
+
let e = Se(), { user: t } = $e(), n = Ze(), [r, i] = x(null), [a, o] = x(!0);
|
|
89367
89367
|
m(() => {
|
|
89368
89368
|
(async () => {
|
|
89369
|
-
|
|
89369
|
+
o(!0);
|
|
89370
89370
|
try {
|
|
89371
|
-
let [t, n] = await Promise.all([ee(C(W, "sys_pages")), ee(C(W, "sys_tabs"))]),
|
|
89371
|
+
let [t, n] = await Promise.all([ee(C(W, "sys_pages")), ee(C(W, "sys_tabs"))]), r = null, a = null, o = (t, n) => {
|
|
89372
89372
|
t.forEach((t) => {
|
|
89373
|
-
let
|
|
89373
|
+
let i = t.data(), o = i.route;
|
|
89374
89374
|
o && !o.startsWith("/") && (o = "/" + o);
|
|
89375
89375
|
let s = "/" + t.id === e.pathname;
|
|
89376
|
-
(o === e.pathname || s) && (
|
|
89377
|
-
...
|
|
89376
|
+
(o === e.pathname || s) && (r = {
|
|
89377
|
+
...i,
|
|
89378
89378
|
isPrivate: n,
|
|
89379
|
-
isAdmin:
|
|
89380
|
-
isShared:
|
|
89379
|
+
isAdmin: i.pageType === "admin",
|
|
89380
|
+
isShared: i.pageType === "shared"
|
|
89381
89381
|
}, a = t.id);
|
|
89382
89382
|
});
|
|
89383
89383
|
};
|
|
89384
|
-
if (o(t, !1),
|
|
89384
|
+
if (o(t, !1), r || o(n, !0), r || (e.pathname === "/contact" ? (r = {
|
|
89385
89385
|
route: "/contact",
|
|
89386
89386
|
template: "popup_form",
|
|
89387
89387
|
form: "contact"
|
|
89388
|
-
}, a = "contact") : e.pathname === "/support" && (
|
|
89388
|
+
}, a = "contact") : e.pathname === "/support" && (r = {
|
|
89389
89389
|
route: "/support",
|
|
89390
89390
|
template: "popup_form",
|
|
89391
89391
|
form: "support"
|
|
89392
|
-
}, a = "support")),
|
|
89393
|
-
if ((a === "contact" || a === "support") && !
|
|
89394
|
-
let e = await E(T(W, "sys_forms",
|
|
89395
|
-
if (e.exists())
|
|
89392
|
+
}, a = "support")), r) {
|
|
89393
|
+
if ((a === "contact" || a === "support") && !r.form && (r.form = a), r.pageId = a, r.form) {
|
|
89394
|
+
let e = await E(T(W, "sys_forms", r.form));
|
|
89395
|
+
if (e.exists()) r.formConfigOverride = {
|
|
89396
89396
|
...e.data(),
|
|
89397
89397
|
id: e.id
|
|
89398
89398
|
};
|
|
89399
|
-
else if (
|
|
89399
|
+
else if (r.form === "contact") {
|
|
89400
89400
|
let { contactFormConfig: e } = await import("./contactForm.config-DLeI_ZEj.js");
|
|
89401
|
-
|
|
89402
|
-
} else if (
|
|
89401
|
+
r.formConfigOverride = e;
|
|
89402
|
+
} else if (r.form === "support") {
|
|
89403
89403
|
let { supportFormConfig: e } = await import("./supportForm.config-74T-eSSH.js");
|
|
89404
|
-
|
|
89404
|
+
r.formConfigOverride = e;
|
|
89405
89405
|
}
|
|
89406
89406
|
}
|
|
89407
|
-
let e =
|
|
89408
|
-
e && (document.title = e), r
|
|
89409
|
-
} else
|
|
89407
|
+
let e = r.pageName || r.tabName || r.title;
|
|
89408
|
+
e && (document.title = e), i(r);
|
|
89409
|
+
} else i("not-found");
|
|
89410
89410
|
} catch {
|
|
89411
|
-
|
|
89411
|
+
i("not-found");
|
|
89412
89412
|
} finally {
|
|
89413
|
-
|
|
89413
|
+
o(!1);
|
|
89414
89414
|
}
|
|
89415
89415
|
})();
|
|
89416
89416
|
}, [e.pathname]);
|
|
89417
|
-
let [
|
|
89417
|
+
let [s, c] = x(!1);
|
|
89418
89418
|
if (m(() => {
|
|
89419
89419
|
let e;
|
|
89420
|
-
return
|
|
89421
|
-
}, [
|
|
89420
|
+
return a ? e = setTimeout(() => c(!0), 150) : c(!1), () => clearTimeout(e);
|
|
89421
|
+
}, [a]), a) return s ? t ? /* @__PURE__ */ V("main", {
|
|
89422
89422
|
className: "flex-1 w-full max-w-7xl mx-auto p-4 md:p-8 z-10 flex flex-col",
|
|
89423
89423
|
children: [/* @__PURE__ */ V("div", {
|
|
89424
89424
|
className: "mb-6",
|
|
@@ -89434,7 +89434,7 @@ function yUn() {
|
|
|
89434
89434
|
className: "flex-1 flex items-center justify-center min-h-[60vh] z-10",
|
|
89435
89435
|
children: /* @__PURE__ */ B(K, { className: "w-6 h-6 animate-spin text-accent" })
|
|
89436
89436
|
}) : null;
|
|
89437
|
-
if (
|
|
89437
|
+
if (r === "not-found") return /* @__PURE__ */ B("main", {
|
|
89438
89438
|
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
89439
|
children: /* @__PURE__ */ V("div", {
|
|
89440
89440
|
className: "flex flex-col items-center justify-center flex-1 text-center",
|
|
@@ -89481,53 +89481,53 @@ function yUn() {
|
|
|
89481
89481
|
]
|
|
89482
89482
|
})
|
|
89483
89483
|
});
|
|
89484
|
-
if ((
|
|
89484
|
+
if ((r.pageId === "support" || r.isPrivate) && !t) return /* @__PURE__ */ B(be, {
|
|
89485
89485
|
to: "/login",
|
|
89486
89486
|
state: { from: e }
|
|
89487
89487
|
});
|
|
89488
|
-
let
|
|
89489
|
-
if (
|
|
89490
|
-
if (
|
|
89491
|
-
let e =
|
|
89492
|
-
return /* @__PURE__ */ B(JVn, {
|
|
89493
|
-
title:
|
|
89494
|
-
subtitle:
|
|
89488
|
+
let l = r.pageName?.toLowerCase().replace(/\s+/g, "_") || r.pageId || "custom_page", u = `pub_${l}`;
|
|
89489
|
+
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 });
|
|
89490
|
+
if (r.template === "board") {
|
|
89491
|
+
let e = r.isAdmin ? `admin_${r.pageId || l}` : r.isShared ? `mem_${r.pageId || l}` : r.isPrivate ? `user_${r.pageId || l}` : u;
|
|
89492
|
+
return /* @__PURE__ */ B(n.components?.TemplateBoard || JVn, {
|
|
89493
|
+
title: r.tabTitle || r.tabName || r.title || r.pageName || "Board",
|
|
89494
|
+
subtitle: r.route,
|
|
89495
89495
|
tasksCollection: `${e}_tasks`,
|
|
89496
89496
|
categoriesCollection: `${e}_categories`,
|
|
89497
|
-
config:
|
|
89497
|
+
config: r
|
|
89498
89498
|
});
|
|
89499
89499
|
}
|
|
89500
|
-
if (
|
|
89501
|
-
let e =
|
|
89502
|
-
return /* @__PURE__ */ B($Hn, {
|
|
89503
|
-
title:
|
|
89504
|
-
subtitle:
|
|
89500
|
+
if (r.template === "table") {
|
|
89501
|
+
let e = r.isAdmin ? `admin_${r.pageId || l}` : r.isShared ? `mem_${r.pageId || l}` : r.isPrivate ? `user_${r.pageId || l}` : u;
|
|
89502
|
+
return /* @__PURE__ */ B(n.components?.TemplateTable || $Hn, {
|
|
89503
|
+
title: r.tabTitle || r.tabName || r.title || r.pageName || "Table",
|
|
89504
|
+
subtitle: r.route,
|
|
89505
89505
|
tableCollection: `${e}_table`,
|
|
89506
|
-
config:
|
|
89506
|
+
config: r
|
|
89507
89507
|
});
|
|
89508
89508
|
}
|
|
89509
|
-
if (
|
|
89510
|
-
let e =
|
|
89511
|
-
return /* @__PURE__ */ B(tUn, {
|
|
89512
|
-
title:
|
|
89513
|
-
subtitle:
|
|
89509
|
+
if (r.template === "calendar") {
|
|
89510
|
+
let e = r.isAdmin ? `admin_${r.pageId || l}` : r.isShared ? `mem_${r.pageId || l}` : r.isPrivate ? `user_${r.pageId || l}` : u;
|
|
89511
|
+
return /* @__PURE__ */ B(n.components?.TemplateCalendar || tUn, {
|
|
89512
|
+
title: r.tabTitle || r.tabName || r.title || r.pageName || "Calendar",
|
|
89513
|
+
subtitle: r.route,
|
|
89514
89514
|
eventsCollection: `${e}_events`,
|
|
89515
|
-
defaultTimeFormat:
|
|
89516
|
-
config:
|
|
89515
|
+
defaultTimeFormat: r.defaultTimeFormat || r.defaulttimeformat || "12h",
|
|
89516
|
+
config: r
|
|
89517
89517
|
});
|
|
89518
89518
|
}
|
|
89519
|
-
return
|
|
89519
|
+
return r.template === "inline_form" ? /* @__PURE__ */ B("div", {
|
|
89520
89520
|
className: "flex-1 flex flex-col items-center justify-start mt-8 relative z-10 w-full min-h-[60vh]",
|
|
89521
89521
|
children: /* @__PURE__ */ B(Es, {
|
|
89522
89522
|
isInline: !0,
|
|
89523
|
-
formId:
|
|
89524
|
-
formConfig:
|
|
89523
|
+
formId: r.form,
|
|
89524
|
+
formConfig: r.formConfigOverride
|
|
89525
89525
|
})
|
|
89526
89526
|
}) : /* @__PURE__ */ B("div", {
|
|
89527
89527
|
className: "flex-1 flex flex-col items-center justify-center relative z-10 w-full min-h-[60vh]",
|
|
89528
89528
|
children: /* @__PURE__ */ B(Es, {
|
|
89529
|
-
formId:
|
|
89530
|
-
formConfig:
|
|
89529
|
+
formId: r.form,
|
|
89530
|
+
formConfig: r.formConfigOverride,
|
|
89531
89531
|
onClose: () => window.history.back()
|
|
89532
89532
|
})
|
|
89533
89533
|
});
|
|
@@ -90265,6 +90265,7 @@ function PUn() {
|
|
|
90265
90265
|
});
|
|
90266
90266
|
}
|
|
90267
90267
|
function FUn() {
|
|
90268
|
+
let e = Ze().components?.Home || fce;
|
|
90268
90269
|
return /* @__PURE__ */ B(eee, { children: /* @__PURE__ */ V("div", {
|
|
90269
90270
|
className: "min-h-screen relative flex flex-col overflow-x-hidden",
|
|
90270
90271
|
children: [
|
|
@@ -90272,7 +90273,7 @@ function FUn() {
|
|
|
90272
90273
|
/* @__PURE__ */ V(xe, { children: [
|
|
90273
90274
|
/* @__PURE__ */ B(U, {
|
|
90274
90275
|
path: "/",
|
|
90275
|
-
element: /* @__PURE__ */ B(Q9, { children: /* @__PURE__ */ B(
|
|
90276
|
+
element: /* @__PURE__ */ B(Q9, { children: /* @__PURE__ */ B(e, {}) })
|
|
90276
90277
|
}),
|
|
90277
90278
|
/* @__PURE__ */ B(U, {
|
|
90278
90279
|
path: "/register",
|
|
@@ -90397,28 +90398,18 @@ function RUn(e) {
|
|
|
90397
90398
|
firebaseConfig: e.firebaseConfig,
|
|
90398
90399
|
adminEmails: e.adminEmails,
|
|
90399
90400
|
basename: e.basename,
|
|
90400
|
-
onAuthChange: e.onAuthChange
|
|
90401
|
+
onAuthChange: e.onAuthChange,
|
|
90402
|
+
themeConfig: e.themeConfig,
|
|
90403
|
+
components: e.components
|
|
90401
90404
|
},
|
|
90402
90405
|
children: /* @__PURE__ */ B(qe, {
|
|
90403
90406
|
scopeSelector: ".firebase-os",
|
|
90404
|
-
children: /* @__PURE__ */
|
|
90405
|
-
className: "firebase-os",
|
|
90406
|
-
|
|
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, {})]
|
|
90407
|
+
children: /* @__PURE__ */ B("div", {
|
|
90408
|
+
className: "firebase-os flex-1 flex flex-col min-h-screen",
|
|
90409
|
+
children: /* @__PURE__ */ B(IUn, {})
|
|
90419
90410
|
})
|
|
90420
90411
|
})
|
|
90421
90412
|
});
|
|
90422
90413
|
}
|
|
90423
90414
|
//#endregion
|
|
90424
|
-
export { RUn as FirebaseOS, $e as useAuth, Ze as useConfig, Je as useTheme };
|
|
90415
|
+
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.5",
|
|
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,14 +81,54 @@ createRoot(document.getElementById('root')!).render(
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
// ── 3.
|
|
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');
|
|
90
|
+
if (fs.existsSync(sourceCssPath)) {
|
|
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');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ── 4. Write App.tsx with Hybrid Overrides Wired Up ───────────────────────
|
|
85
123
|
const appPath = path.join(srcDir, 'App.tsx');
|
|
86
124
|
const appContent = `import { FirebaseOS } from 'firebase-os';
|
|
87
|
-
import 'firebase-os/
|
|
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';
|
|
88
130
|
|
|
89
131
|
// 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
132
|
const firebaseConfig = {
|
|
93
133
|
apiKey: import.meta.env.VITE_FIREBASE_API_KEY || '',
|
|
94
134
|
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || '',
|
|
@@ -108,21 +148,57 @@ export default function App() {
|
|
|
108
148
|
<FirebaseOS
|
|
109
149
|
firebaseConfig={firebaseConfig}
|
|
110
150
|
adminEmails={adminEmails}
|
|
151
|
+
themeConfig={themeConfig}
|
|
152
|
+
components={{
|
|
153
|
+
Home: Home
|
|
154
|
+
}}
|
|
111
155
|
/>
|
|
112
156
|
);
|
|
113
157
|
}
|
|
114
158
|
`;
|
|
115
159
|
|
|
116
|
-
// Only write if the file doesn't already import FirebaseOS
|
|
117
160
|
const existingApp = fs.existsSync(appPath) ? fs.readFileSync(appPath, 'utf8') : '';
|
|
118
161
|
if (!existingApp.includes('firebase-os')) {
|
|
119
162
|
fs.writeFileSync(appPath, appContent);
|
|
120
|
-
console.log(' ✓ Wrote App.tsx with <FirebaseOS /> ready to go');
|
|
163
|
+
console.log(' ✓ Wrote App.tsx with <FirebaseOS /> hybrid architecture ready to go');
|
|
121
164
|
} else {
|
|
122
165
|
console.log(' ℹ App.tsx already uses firebase-os — skipped');
|
|
123
166
|
}
|
|
124
167
|
|
|
125
|
-
// ──
|
|
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 ──────────────────────────────────
|
|
126
202
|
const envPath = path.join(consumerRoot, '.env');
|
|
127
203
|
if (!fs.existsSync(envPath)) {
|
|
128
204
|
const envContent = `# 🔥 Firebase OS Configuration
|
|
@@ -137,10 +213,13 @@ VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
|
|
|
137
213
|
VITE_FIREBASE_APP_ID=your_app_id
|
|
138
214
|
|
|
139
215
|
# Comma-separated list of admin emails
|
|
140
|
-
VITE_ADMIN_EMAILS=
|
|
216
|
+
VITE_ADMIN_EMAILS=admin@example.com
|
|
141
217
|
`;
|
|
142
218
|
fs.writeFileSync(envPath, envContent);
|
|
143
|
-
console.log(' ✓ Created .env
|
|
219
|
+
console.log(' ✓ Created .env template');
|
|
144
220
|
}
|
|
145
221
|
|
|
146
|
-
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');
|
package/src/App.css
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
.counter {
|
|
2
|
+
font-size: 16px;
|
|
3
|
+
padding: 5px 10px;
|
|
4
|
+
border-radius: 5px;
|
|
5
|
+
color: var(--accent);
|
|
6
|
+
background: var(--accent-bg);
|
|
7
|
+
border: 2px solid transparent;
|
|
8
|
+
transition: border-color 0.3s;
|
|
9
|
+
margin-bottom: 24px;
|
|
10
|
+
|
|
11
|
+
&:hover {
|
|
12
|
+
border-color: var(--accent-border);
|
|
13
|
+
}
|
|
14
|
+
&:focus-visible {
|
|
15
|
+
outline: 2px solid var(--accent);
|
|
16
|
+
outline-offset: 2px;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.hero {
|
|
21
|
+
position: relative;
|
|
22
|
+
|
|
23
|
+
.base,
|
|
24
|
+
.framework,
|
|
25
|
+
.vite {
|
|
26
|
+
inset-inline: 0;
|
|
27
|
+
margin: 0 auto;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.base {
|
|
31
|
+
width: 170px;
|
|
32
|
+
position: relative;
|
|
33
|
+
z-index: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.framework,
|
|
37
|
+
.vite {
|
|
38
|
+
position: absolute;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.framework {
|
|
42
|
+
z-index: 1;
|
|
43
|
+
top: 34px;
|
|
44
|
+
height: 28px;
|
|
45
|
+
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
|
|
46
|
+
scale(1.4);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.vite {
|
|
50
|
+
z-index: 0;
|
|
51
|
+
top: 107px;
|
|
52
|
+
height: 26px;
|
|
53
|
+
width: auto;
|
|
54
|
+
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
|
|
55
|
+
scale(0.8);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#center {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
gap: 25px;
|
|
63
|
+
place-content: center;
|
|
64
|
+
place-items: center;
|
|
65
|
+
flex-grow: 1;
|
|
66
|
+
|
|
67
|
+
@media (max-width: 1024px) {
|
|
68
|
+
padding: 32px 20px 24px;
|
|
69
|
+
gap: 18px;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#next-steps {
|
|
74
|
+
display: flex;
|
|
75
|
+
border-top: 1px solid var(--border);
|
|
76
|
+
text-align: left;
|
|
77
|
+
|
|
78
|
+
& > div {
|
|
79
|
+
flex: 1 1 0;
|
|
80
|
+
padding: 32px;
|
|
81
|
+
@media (max-width: 1024px) {
|
|
82
|
+
padding: 24px 20px;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.icon {
|
|
87
|
+
margin-bottom: 16px;
|
|
88
|
+
width: 22px;
|
|
89
|
+
height: 22px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@media (max-width: 1024px) {
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
text-align: center;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#docs {
|
|
99
|
+
border-right: 1px solid var(--border);
|
|
100
|
+
|
|
101
|
+
@media (max-width: 1024px) {
|
|
102
|
+
border-right: none;
|
|
103
|
+
border-bottom: 1px solid var(--border);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#next-steps ul {
|
|
108
|
+
list-style: none;
|
|
109
|
+
padding: 0;
|
|
110
|
+
display: flex;
|
|
111
|
+
gap: 8px;
|
|
112
|
+
margin: 32px 0 0;
|
|
113
|
+
|
|
114
|
+
.logo {
|
|
115
|
+
height: 18px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
a {
|
|
119
|
+
color: var(--text-h);
|
|
120
|
+
font-size: 16px;
|
|
121
|
+
border-radius: 6px;
|
|
122
|
+
background: var(--social-bg);
|
|
123
|
+
display: flex;
|
|
124
|
+
padding: 6px 12px;
|
|
125
|
+
align-items: center;
|
|
126
|
+
gap: 8px;
|
|
127
|
+
text-decoration: none;
|
|
128
|
+
transition: box-shadow 0.3s;
|
|
129
|
+
|
|
130
|
+
&:hover {
|
|
131
|
+
box-shadow: var(--shadow);
|
|
132
|
+
}
|
|
133
|
+
.button-icon {
|
|
134
|
+
height: 18px;
|
|
135
|
+
width: 18px;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@media (max-width: 1024px) {
|
|
140
|
+
margin-top: 20px;
|
|
141
|
+
flex-wrap: wrap;
|
|
142
|
+
justify-content: center;
|
|
143
|
+
|
|
144
|
+
li {
|
|
145
|
+
flex: 1 1 calc(50% - 8px);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
a {
|
|
149
|
+
width: 100%;
|
|
150
|
+
justify-content: center;
|
|
151
|
+
box-sizing: border-box;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#spacer {
|
|
157
|
+
height: 88px;
|
|
158
|
+
border-top: 1px solid var(--border);
|
|
159
|
+
@media (max-width: 1024px) {
|
|
160
|
+
height: 48px;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.ticks {
|
|
165
|
+
position: relative;
|
|
166
|
+
width: 100%;
|
|
167
|
+
|
|
168
|
+
&::before,
|
|
169
|
+
&::after {
|
|
170
|
+
content: '';
|
|
171
|
+
position: absolute;
|
|
172
|
+
top: -4.5px;
|
|
173
|
+
border: 5px solid transparent;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
&::before {
|
|
177
|
+
left: 0;
|
|
178
|
+
border-left-color: var(--border);
|
|
179
|
+
}
|
|
180
|
+
&::after {
|
|
181
|
+
right: 0;
|
|
182
|
+
border-right-color: var(--border);
|
|
183
|
+
}
|
|
184
|
+
}
|