firebase-os 1.1.4 → 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.
Files changed (124) hide show
  1. package/dist/FirebaseOS.d.ts +15 -0
  2. package/dist/firebase-os.cjs.js +2 -17
  3. package/dist/firebase-os.es.js +63 -74
  4. package/dist/index.d.ts +3 -0
  5. package/dist/lib/ConfigContext.d.ts +12 -0
  6. package/package.json +3 -2
  7. package/scripts/postinstall.js +86 -15
  8. package/src/App.css +184 -0
  9. package/src/App.tsx +214 -0
  10. package/src/FirebaseOS.tsx +80 -0
  11. package/src/assets/hero.png +0 -0
  12. package/src/assets/react.svg +1 -0
  13. package/src/assets/vite.svg +1 -0
  14. package/src/components/AdminNotifications.test.tsx +98 -0
  15. package/src/components/AdminNotifications.tsx +194 -0
  16. package/src/components/Button.test.tsx +22 -0
  17. package/src/components/Button.tsx +53 -0
  18. package/src/components/ConfirmModal.test.tsx +98 -0
  19. package/src/components/ConfirmModal.tsx +73 -0
  20. package/src/components/ContactPopup.test.tsx +98 -0
  21. package/src/components/ContactPopup.tsx +437 -0
  22. package/src/components/CustomSelect.test.tsx +47 -0
  23. package/src/components/CustomSelect.tsx +89 -0
  24. package/src/components/DashboardNav.test.tsx +98 -0
  25. package/src/components/DashboardNav.tsx +281 -0
  26. package/src/components/Input.test.tsx +33 -0
  27. package/src/components/Input.tsx +61 -0
  28. package/src/components/JsonEditor.tsx +579 -0
  29. package/src/components/Navbar.test.tsx +98 -0
  30. package/src/components/Navbar.tsx +563 -0
  31. package/src/configs/forms/contactForm.config.ts +15 -0
  32. package/src/configs/forms/index.ts +29 -0
  33. package/src/configs/forms/pubForm.config.ts +11 -0
  34. package/src/configs/forms/supportForm.config.ts +14 -0
  35. package/src/configs/forms/userForm.config.ts +11 -0
  36. package/src/configs/pages/admin.config.ts +29 -0
  37. package/src/configs/pages/contact.config.ts +6 -0
  38. package/src/configs/pages/home.config.ts +18 -0
  39. package/src/configs/pages/mem.config.ts +2 -0
  40. package/src/configs/pages/menuOrders.config.ts +11 -0
  41. package/src/configs/pages/pub.config.ts +11 -0
  42. package/src/configs/pages/shared.config.ts +29 -0
  43. package/src/configs/pages/support.config.ts +7 -0
  44. package/src/configs/pages/tabOrders.config.ts +33 -0
  45. package/src/configs/pages/user.config.ts +29 -0
  46. package/src/configs/theme.config.ts +93 -0
  47. package/src/index.css +403 -0
  48. package/src/index.ts +22 -0
  49. package/src/lib/AuthContext.test.tsx +88 -0
  50. package/src/lib/AuthContext.tsx +191 -0
  51. package/src/lib/ConfigContext.tsx +45 -0
  52. package/src/lib/ThemeContext.tsx +227 -0
  53. package/src/lib/firebase.ts +91 -0
  54. package/src/main.tsx +22 -0
  55. package/src/microcomponents/AdminExampleContent.tsx +44 -0
  56. package/src/microcomponents/PrivateExampleContent.tsx +39 -0
  57. package/src/microcomponents/Public.tsx +126 -0
  58. package/src/microcomponents/SharedExampleContent.tsx +53 -0
  59. package/src/pages/Dashboard.test.tsx +98 -0
  60. package/src/pages/Dashboard.tsx +60 -0
  61. package/src/pages/DynamicPage.tsx +237 -0
  62. package/src/pages/FormsAdmin.test.tsx +98 -0
  63. package/src/pages/FormsAdmin.tsx +459 -0
  64. package/src/pages/Home.test.tsx +98 -0
  65. package/src/pages/Home.tsx +144 -0
  66. package/src/pages/Login.test.tsx +98 -0
  67. package/src/pages/Login.tsx +108 -0
  68. package/src/pages/PagesAdmin.test.tsx +98 -0
  69. package/src/pages/PagesAdmin.tsx +1022 -0
  70. package/src/pages/Profile.test.tsx +98 -0
  71. package/src/pages/Profile.tsx +319 -0
  72. package/src/pages/Register.test.tsx +98 -0
  73. package/src/pages/Register.tsx +116 -0
  74. package/src/pages/Requests.test.tsx +95 -0
  75. package/src/pages/Requests.tsx +422 -0
  76. package/src/pages/ResetPassword.test.tsx +98 -0
  77. package/src/pages/ResetPassword.tsx +92 -0
  78. package/src/pages/Settings.test.tsx +98 -0
  79. package/src/pages/Settings.tsx +393 -0
  80. package/src/pages/Setup.tsx +401 -0
  81. package/src/pages/StorageAdmin.test.tsx +150 -0
  82. package/src/pages/StorageAdmin.tsx +769 -0
  83. package/src/pages/Submissions.test.tsx +95 -0
  84. package/src/pages/Submissions.tsx +372 -0
  85. package/src/pages/Templates.test.tsx +98 -0
  86. package/src/pages/Templates.tsx +103 -0
  87. package/src/pages/ThemeAdmin.test.tsx +144 -0
  88. package/src/pages/ThemeAdmin.tsx +1000 -0
  89. package/src/pages/Users.test.tsx +95 -0
  90. package/src/pages/Users.tsx +334 -0
  91. package/src/pages/Verify.test.tsx +98 -0
  92. package/src/pages/Verify.tsx +95 -0
  93. package/src/prompts/index.ts +13 -0
  94. package/src/prompts/pages/publicPage.ts +44 -0
  95. package/src/prompts/sharedConstants.ts +12 -0
  96. package/src/prompts/tabs/board/adminboard.ts +32 -0
  97. package/src/prompts/tabs/board/privateboard.ts +36 -0
  98. package/src/prompts/tabs/board/publicboard.ts +36 -0
  99. package/src/prompts/tabs/calendar/admincalendar.ts +32 -0
  100. package/src/prompts/tabs/calendar/privatecalendar.ts +36 -0
  101. package/src/prompts/tabs/calendar/publiccalendar.ts +36 -0
  102. package/src/prompts/tabs/crud/admin.ts +54 -0
  103. package/src/prompts/tabs/crud/private.ts +55 -0
  104. package/src/prompts/tabs/crud/shared.ts +53 -0
  105. package/src/prompts/tabs/table/admintable.ts +32 -0
  106. package/src/prompts/tabs/table/privatetable.ts +36 -0
  107. package/src/prompts/tabs/table/publictable.ts +36 -0
  108. package/src/setupTests.ts +1 -0
  109. package/src/templates/AdminPageTemplate.tsx +678 -0
  110. package/src/templates/PrivatePageTemplate.tsx +594 -0
  111. package/src/templates/PublicPageTemplate.tsx +92 -0
  112. package/src/templates/SharedPageTemplate.tsx +551 -0
  113. package/src/templates/TemplateBoard.test.tsx +106 -0
  114. package/src/templates/TemplateBoard.tsx +642 -0
  115. package/src/templates/TemplateCalendar.test.tsx +106 -0
  116. package/src/templates/TemplateCalendar.tsx +848 -0
  117. package/src/templates/TemplateConfirmation.test.tsx +106 -0
  118. package/src/templates/TemplateConfirmation.tsx +145 -0
  119. package/src/templates/TemplateInlineForm.test.tsx +106 -0
  120. package/src/templates/TemplateInlineForm.tsx +129 -0
  121. package/src/templates/TemplatePopupForm.test.tsx +106 -0
  122. package/src/templates/TemplatePopupForm.tsx +174 -0
  123. package/src/templates/TemplateTable.test.tsx +106 -0
  124. package/src/templates/TemplateTable.tsx +675 -0
@@ -0,0 +1,174 @@
1
+ import { motion, AnimatePresence } from 'framer-motion';
2
+ import { ArrowLeft, CheckCircle2, AlertCircle, X, Plus } from 'lucide-react';
3
+ import { Link } from 'react-router-dom';
4
+ import { Button } from '../components/Button';
5
+ import { Input } from '../components/Input';
6
+ import { useState } from 'react';
7
+ import { auth, db } from '../lib/firebase';
8
+ import { collection, addDoc, serverTimestamp } from 'firebase/firestore';
9
+
10
+ export function TemplatePopupForm() {
11
+ const [popupOpen, setPopupOpen] = useState(false);
12
+
13
+ const [formData, setFormData] = useState({ concept: '', featureRequest: '', notes: '' });
14
+ const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
15
+
16
+ const handleSubmit = async (e: React.FormEvent) => {
17
+ e.preventDefault();
18
+ setStatus('loading');
19
+
20
+ try {
21
+ const currentUserId = auth.currentUser?.uid || 'guest';
22
+ await addDoc(collection(db, 'user_submissions'), {
23
+ uid: currentUserId,
24
+ ...formData,
25
+ type: 'template_simulation',
26
+ submittedAt: serverTimestamp(),
27
+ });
28
+
29
+ setStatus('success');
30
+ setTimeout(() => {
31
+ setStatus('idle');
32
+ setFormData({ concept: '', featureRequest: '', notes: '' });
33
+ setPopupOpen(false);
34
+ }, 3000);
35
+ } catch (err: any) {
36
+ setStatus('error');
37
+ }
38
+ };
39
+
40
+ return (
41
+ <main 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">
42
+ <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="mb-4">
43
+ <h1 className="w-fit inline-block text-3xl md:text-4xl lg:text-5xl font-extrabold tracking-tight mb-3 text-gradient mt-1">
44
+ Popup Form
45
+ </h1>
46
+ <div className="flex items-center gap-2 text-foreground/40 font-bold uppercase tracking-[0.2em] text-[11px]">
47
+ <span className="w-8 h-[1px] bg-foreground/10" />
48
+ /popup_form
49
+ </div>
50
+ </motion.div>
51
+
52
+ <div className="flex justify-between items-center mb-6 border-b border-[var(--panel-border)] pb-6 relative z-20">
53
+ <Link to="/templates" className="px-5 py-2 border border-[var(--panel-border)] rounded-xl text-[13px] font-bold hover:bg-foreground/5 transition-all flex items-center gap-2 text-foreground/70">
54
+ <ArrowLeft className="w-4 h-4" /> Go Back
55
+ </Link>
56
+ </div>
57
+
58
+ <motion.div
59
+ initial={{ opacity: 0, y: 20 }}
60
+ animate={{ opacity: 1, y: 0 }}
61
+ className="glass-panel border border-[var(--panel-border)] rounded-3xl overflow-hidden shadow-2xl relative flex flex-col w-full min-h-[150px] p-6 lg:p-10"
62
+ >
63
+ <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] bg-accent/5 blur-[120px] rounded-full pointer-events-none -z-10" />
64
+
65
+ <div className="flex h-full w-full justify-end items-start relative z-10">
66
+ <Button onClick={() => setPopupOpen(true)} className="px-6 py-2.5 text-[14px] font-bold rounded-xl shadow-lg flex items-center justify-center gap-2 btn-primary transition-all hover:-translate-y-1">
67
+ <Plus className="w-4 h-4" /> Open Form
68
+ </Button>
69
+ </div>
70
+ </motion.div>
71
+
72
+ <AnimatePresence>
73
+ {popupOpen && (
74
+ <div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
75
+ <motion.div
76
+ initial={{ opacity: 0 }}
77
+ animate={{ opacity: 1 }}
78
+ exit={{ opacity: 0 }}
79
+ className="absolute inset-0 bg-background/60 backdrop-blur-xl cursor-pointer"
80
+ onClick={() => setPopupOpen(false)}
81
+ />
82
+
83
+ <motion.div
84
+ initial={{ opacity: 0, scale: 0.95, y: 10 }}
85
+ animate={{ opacity: 1, scale: 1, y: 0 }}
86
+ exit={{ opacity: 0, scale: 0.95, y: 10 }}
87
+ className="w-full max-w-[500px] p-6 sm:p-8 lg:p-10 rounded-3xl md:rounded-3xl glass-panel relative glow-hover shadow-[0_8px_32px_rgba(0,0,0,0.08)] z-10 mx-4 max-h-[95vh] overflow-y-auto no-scrollbar"
88
+ >
89
+ <div className="absolute -inset-[1px] bg-gradient-to-br from-[var(--primary-glow)] to-transparent opacity-30 blur-[20px] rounded-3xl md:rounded-3xl -z-10" />
90
+
91
+ <div className="relative z-10 w-full">
92
+ <button
93
+ onClick={() => setPopupOpen(false)}
94
+ className="absolute -top-2 -right-2 w-8 h-8 flex items-center justify-center rounded-full hover:bg-foreground/5 text-foreground/60 hover:text-foreground transition-colors z-20"
95
+ >
96
+ <X className="w-5 h-5" />
97
+ </button>
98
+
99
+ {status === 'success' ? (
100
+ <motion.div
101
+ initial={{ opacity: 0, y: 10 }}
102
+ animate={{ opacity: 1, y: 0 }}
103
+ className="flex flex-col items-center justify-center py-12 text-center"
104
+ >
105
+ <div className="w-16 h-16 rounded-full bg-green-500/10 border border-green-500/20 flex items-center justify-center text-green-500 mb-4">
106
+ <CheckCircle2 className="w-8 h-8" />
107
+ </div>
108
+ <h4 className="text-xl font-bold text-foreground mb-2">Simulation Complete!</h4>
109
+ <p className="text-[14px] text-foreground/60 leading-relaxed max-w-[280px]">Your test data was sent successfully. Log in as an admin and check the Submissions tab!</p>
110
+ </motion.div>
111
+ ) : status === 'loading' ? (
112
+ <motion.div
113
+ initial={{ opacity: 0, scale: 0.95 }}
114
+ animate={{ opacity: 1, scale: 1 }}
115
+ className="flex flex-col items-center justify-center py-16 text-center"
116
+ >
117
+ <div className="w-10 h-10 border-4 border-accent border-r-transparent rounded-full animate-spin mb-4" />
118
+ <h4 className="text-lg font-bold text-foreground tracking-tight">Processing</h4>
119
+ <p className="text-[13px] text-foreground/50 mt-1">Simulating submission...</p>
120
+ </motion.div>
121
+ ) : (
122
+ <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
123
+ <div className="mb-6 text-center">
124
+ <h3 className="text-2xl sm:text-3xl font-extrabold mb-2 text-foreground tracking-tight break-words">Popup Template</h3>
125
+ <p className="text-[14px] md:text-[15px] font-medium text-foreground/60 tracking-wide leading-relaxed">Fill out the simulated fields below to test the interaction.</p>
126
+ </div>
127
+
128
+ <form onSubmit={handleSubmit} className="space-y-4 w-full">
129
+ <Input
130
+ label="Concept Name"
131
+ placeholder="e.g. Project Apollo"
132
+ value={formData.concept}
133
+ onChange={e => setFormData({ ...formData, concept: e.target.value })}
134
+ />
135
+ <Input
136
+ label="Feature Request"
137
+ placeholder="e.g. Real-time sync"
138
+ value={formData.featureRequest}
139
+ onChange={e => setFormData({ ...formData, featureRequest: e.target.value })}
140
+ />
141
+
142
+ <div className="flex flex-col w-full relative">
143
+ <label className="text-[13px] font-medium text-foreground/50 select-none mb-1.5 ml-1">
144
+ Simulated Notes
145
+ </label>
146
+ <textarea
147
+ rows={3}
148
+ placeholder="Type something here..."
149
+ value={formData.notes}
150
+ onChange={e => setFormData({ ...formData, notes: e.target.value })}
151
+ className="flex w-full rounded-xl text-[15px] text-foreground px-4 py-3 transition-all duration-300 placeholder:text-foreground/40 focus:outline-none focus:border-accent glow-focus disabled:cursor-not-allowed disabled:opacity-50 glass-panel min-h-[100px] resize-none"
152
+ />
153
+ </div>
154
+
155
+ <div className="pt-2">
156
+ <Button
157
+ type="submit"
158
+ className="w-full px-6 md:px-8 py-3 md:py-3.5 rounded-xl font-semibold tracking-wide btn-primary text-[15px] shadow-xl transition-all duration-300 hover:-translate-y-1 active:scale-95 flex items-center justify-center"
159
+ isLoading={false}
160
+ >
161
+ Trigger Simulation
162
+ </Button>
163
+ </div>
164
+ </form>
165
+ </motion.div>
166
+ )}
167
+ </div>
168
+ </motion.div>
169
+ </div>
170
+ )}
171
+ </AnimatePresence>
172
+ </main>
173
+ );
174
+ }
@@ -0,0 +1,106 @@
1
+ // @generated-test
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { render, screen, act } from '@testing-library/react';
4
+ import { BrowserRouter } from 'react-router-dom';
5
+ import { AuthProvider } from '../lib/AuthContext';
6
+ import { ThemeProvider } from '../lib/ThemeContext';
7
+ import { TemplateTable } from './TemplateTable';
8
+
9
+ // Global mocks
10
+ Object.defineProperty(window, 'matchMedia', {
11
+ writable: true,
12
+ value: vi.fn().mockImplementation(query => ({
13
+ matches: false,
14
+ media: query,
15
+ onchange: null,
16
+ addListener: vi.fn(),
17
+ removeListener: vi.fn(),
18
+ addEventListener: vi.fn(),
19
+ removeEventListener: vi.fn(),
20
+ dispatchEvent: vi.fn(),
21
+ })),
22
+ });
23
+
24
+ const mockAuthContext = {
25
+ user: { uid: 'mock-user-123', email: 'test@example.com' },
26
+ userWorkspaces: [],
27
+ activeWorkspace: null,
28
+ activeOrg: null,
29
+ loading: false
30
+ };
31
+
32
+ const mockThemeContext = {
33
+ themeMode: 'light',
34
+ setThemeMode: vi.fn(),
35
+ activeConfig: {}
36
+ };
37
+
38
+ vi.mock('../lib/AuthContext', () => ({
39
+ AuthProvider: ({ children }: any) => <>{children}</>,
40
+ useAuth: () => mockAuthContext
41
+ }));
42
+
43
+ vi.mock('../lib/ThemeContext', () => ({
44
+ ThemeProvider: ({ children }: any) => <>{children}</>,
45
+ useTheme: () => mockThemeContext
46
+ }));
47
+
48
+ vi.mock('firebase/auth', () => ({
49
+ getAuth: vi.fn(() => ({})),
50
+ onAuthStateChanged: vi.fn((auth, cb) => { cb({ uid: 'mock-user-123', email: 'test@example.com', getIdToken: vi.fn(() => Promise.resolve('mock-token')) }); return () => {}; })
51
+ }));
52
+ vi.mock('firebase/firestore', () => ({
53
+ getFirestore: vi.fn(() => ({})),
54
+ collection: vi.fn(),
55
+ doc: vi.fn(),
56
+ setDoc: vi.fn(() => Promise.resolve()),
57
+ addDoc: vi.fn(() => Promise.resolve()),
58
+ updateDoc: vi.fn(() => Promise.resolve()),
59
+ deleteDoc: vi.fn(() => Promise.resolve()),
60
+ query: vi.fn(),
61
+ where: vi.fn(),
62
+ orderBy: vi.fn(),
63
+ limit: vi.fn(),
64
+ getDoc: vi.fn(() => Promise.resolve({ exists: () => true, data: () => ({ role: 'super_admin' }) })),
65
+ getDocs: vi.fn(() => Promise.resolve({ docs: [], forEach: vi.fn() })),
66
+ onSnapshot: vi.fn((...args: any[]) => {
67
+ let cb = args[1];
68
+ if (typeof args[2] === 'function') {
69
+ cb = args[2];
70
+ }
71
+ if (typeof cb === 'function') {
72
+ cb({docs: [], forEach: vi.fn(), data: () => ({}), exists: () => true});
73
+ }
74
+ return () => {};
75
+ })
76
+ }));
77
+ vi.mock('firebase/storage', () => ({
78
+ getStorage: vi.fn(() => ({})),
79
+ ref: vi.fn(),
80
+ listAll: vi.fn(() => Promise.resolve({ items: [], prefixes: [] })),
81
+ getDownloadURL: vi.fn(() => Promise.resolve('mock-url')),
82
+ getMetadata: vi.fn(() => Promise.resolve({ size: 1024, timeCreated: new Date().toISOString() }))
83
+ }));
84
+
85
+ describe('TemplateTable Component', () => {
86
+ it('renders without crashing', async () => {
87
+ // Wrap in standard application providers inside act to process async side effects and prevent warnings
88
+ await act(async () => {
89
+ render(
90
+ <BrowserRouter>
91
+ <AuthProvider>
92
+ <ThemeProvider>
93
+ {/* @ts-ignore */}
94
+ <TemplateTable />
95
+ </ThemeProvider>
96
+ </AuthProvider>
97
+ </BrowserRouter>
98
+ );
99
+ // Wait a tick to flush background state updates
100
+ await new Promise(resolve => setTimeout(resolve, 0));
101
+ });
102
+
103
+ // Check if the document has anything rendered without throwing
104
+ expect(document.body).toBeDefined();
105
+ });
106
+ });