ultimate-jekyll-manager 1.0.8 → 1.0.10

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 (59) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/assets/js/pages/admin/dashboard/index.js +2 -3
  3. package/dist/build.js +5 -4
  4. package/dist/defaults/dist/pages/test/libraries/firestore.html +201 -0
  5. package/dist/defaults/src/_config.yml +1 -1
  6. package/dist/defaults/src/assets/css/main.scss +6 -6
  7. package/dist/gulp/tasks/webpack.js +1 -1
  8. package/package.json +2 -2
  9. package/dist/assets/css/bundles/umbra.scss +0 -5
  10. package/dist/assets/themes/umbra/README.md +0 -75
  11. package/dist/assets/themes/umbra/_config.scss +0 -187
  12. package/dist/assets/themes/umbra/_theme.js +0 -36
  13. package/dist/assets/themes/umbra/_theme.scss +0 -34
  14. package/dist/assets/themes/umbra/css/base/_animations.scss +0 -27
  15. package/dist/assets/themes/umbra/css/base/_backgrounds.scss +0 -191
  16. package/dist/assets/themes/umbra/css/base/_borders.scss +0 -65
  17. package/dist/assets/themes/umbra/css/base/_root.scss +0 -68
  18. package/dist/assets/themes/umbra/css/base/_typography.scss +0 -148
  19. package/dist/assets/themes/umbra/css/base/_utilities.scss +0 -15
  20. package/dist/assets/themes/umbra/css/components/_accordion.scss +0 -44
  21. package/dist/assets/themes/umbra/css/components/_badges.scss +0 -25
  22. package/dist/assets/themes/umbra/css/components/_buttons.scss +0 -264
  23. package/dist/assets/themes/umbra/css/components/_cards.scss +0 -47
  24. package/dist/assets/themes/umbra/css/components/_carousel.scss +0 -41
  25. package/dist/assets/themes/umbra/css/components/_forms.scss +0 -150
  26. package/dist/assets/themes/umbra/css/components/_infinite-scroll.scss +0 -140
  27. package/dist/assets/themes/umbra/css/components/_text.scss +0 -53
  28. package/dist/assets/themes/umbra/css/layout/_backend.scss +0 -59
  29. package/dist/assets/themes/umbra/css/layout/_blog.scss +0 -42
  30. package/dist/assets/themes/umbra/css/layout/_general.scss +0 -142
  31. package/dist/assets/themes/umbra/css/layout/_navigation.scss +0 -602
  32. package/dist/assets/themes/umbra/css/layout/_team.scss +0 -18
  33. package/dist/assets/themes/umbra/js/hero-demo-form.js +0 -42
  34. package/dist/assets/themes/umbra/js/infinite-scroll.js +0 -139
  35. package/dist/assets/themes/umbra/js/initialize-tooltips.js +0 -20
  36. package/dist/assets/themes/umbra/js/navbar-scroll.js +0 -65
  37. package/dist/defaults/dist/_includes/themes/umbra/admin/sections/sidebar.html +0 -3
  38. package/dist/defaults/dist/_includes/themes/umbra/admin/sections/topbar.html +0 -3
  39. package/dist/defaults/dist/_includes/themes/umbra/backend/sections/sidebar.html +0 -347
  40. package/dist/defaults/dist/_includes/themes/umbra/backend/sections/topbar.html +0 -184
  41. package/dist/defaults/dist/_includes/themes/umbra/frontend/components/testimonial-scroll.html +0 -84
  42. package/dist/defaults/dist/_includes/themes/umbra/frontend/sections/footer.html +0 -158
  43. package/dist/defaults/dist/_includes/themes/umbra/frontend/sections/nav.html +0 -276
  44. package/dist/defaults/dist/_includes/themes/umbra/global/sections/account.html +0 -72
  45. package/dist/defaults/dist/_layouts/themes/umbra/admin/core/minimal-viewport-locked.html +0 -31
  46. package/dist/defaults/dist/_layouts/themes/umbra/admin/core/minimal.html +0 -32
  47. package/dist/defaults/dist/_layouts/themes/umbra/backend/core/base.html +0 -55
  48. package/dist/defaults/dist/_layouts/themes/umbra/backend/core/minimal-viewport-locked.html +0 -149
  49. package/dist/defaults/dist/_layouts/themes/umbra/backend/core/minimal.html +0 -149
  50. package/dist/defaults/dist/_layouts/themes/umbra/backend/pages/dashboard/index.html +0 -247
  51. package/dist/defaults/dist/_layouts/themes/umbra/frontend/core/base.html +0 -32
  52. package/dist/defaults/dist/_layouts/themes/umbra/frontend/core/cover.html +0 -41
  53. package/dist/defaults/dist/_layouts/themes/umbra/frontend/core/minimal.html +0 -42
  54. package/dist/defaults/dist/_layouts/themes/umbra/frontend/pages/account/index.html +0 -152
  55. package/dist/defaults/dist/_layouts/themes/umbra/frontend/pages/auth/signin.html +0 -85
  56. package/dist/defaults/dist/_layouts/themes/umbra/frontend/pages/auth/signup.html +0 -97
  57. package/dist/defaults/dist/_layouts/themes/umbra/frontend/pages/index.html +0 -188
  58. package/dist/defaults/dist/_layouts/themes/umbra/frontend/pages/pricing.html +0 -129
  59. package/test.css +0 -18
package/CHANGELOG.md CHANGED
@@ -15,6 +15,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
15
15
  - `Security` in case of vulnerabilities.
16
16
 
17
17
  ---
18
+ ## [1.0.10] - 2026-03-24
19
+ ### Fixed
20
+ - `getUJMConfig()` now throws descriptive errors when config file is missing, empty, or malformed instead of crashing silently
21
+ - Admin dashboard subscription queries now filter by `subscription.status == 'active'` instead of expiry timestamp
22
+
23
+ ### Changed
24
+ - Webpack watch path for web-manager changed from `src/` to `dist/`
25
+
26
+ ## [1.0.9] - 2026-03-20
27
+ ### Changed
28
+ - `authorizedFetch` no longer throws when no user is logged in; logs a warning and proceeds without the Authorization header
29
+
18
30
  ## [1.0.7] - 2026-03-20
19
31
  ### Changed
20
32
  - Upgrade `web-manager` from ^4.1.29 to ^4.1.30
@@ -77,7 +77,7 @@ async function loadStatCards() {
77
77
  const [totalUsers, newUsers, activeSubscriptions, pushSubscribers] = await Promise.allSettled([
78
78
  getCountFromServer(collection(db, 'users')),
79
79
  getCountFromServer(query(collection(db, 'users'), where('metadata.created.timestampUNIX', '>=', thirtyDaysAgo))),
80
- getCountFromServer(query(collection(db, 'users'), where('subscription.expires.timestampUNIX', '>=', now))),
80
+ getCountFromServer(query(collection(db, 'users'), where('subscription.status', '==', 'active'), where('subscription.product.id', '!=', 'basic'))),
81
81
  getCountFromServer(collection(db, 'notifications')),
82
82
  ]);
83
83
 
@@ -92,10 +92,9 @@ async function loadStatCards() {
92
92
  // ============================================
93
93
  async function loadSubscriberData() {
94
94
  const firestore = webManager.firestore();
95
- const now = Math.floor(Date.now() / 1000);
96
95
 
97
96
  const snapshot = await firestore.collection('users')
98
- .where('subscription.expires.timestampUNIX', '>=', now)
97
+ .where('subscription.status', '==', 'active')
99
98
  .get();
100
99
 
101
100
  // Group by plan
package/dist/build.js CHANGED
@@ -143,15 +143,16 @@ Manager.prototype.getPackage = Manager.getPackage;
143
143
  Manager.getUJMConfig = function () {
144
144
  const configPath = path.join(process.cwd(), 'config', 'ultimate-jekyll-manager.json');
145
145
  if (!jetpack.exists(configPath)) {
146
- return {};
146
+ throw new Error(`Config file not found: ${configPath}`);
147
147
  }
148
148
  const content = jetpack.read(configPath);
149
- if (!content) return {};
149
+ if (!content) {
150
+ throw new Error(`Config file is empty: ${configPath}`);
151
+ }
150
152
  try {
151
153
  return JSON5.parse(content);
152
154
  } catch (e) {
153
- console.error('Failed to parse ' + configPath, e);
154
- return {};
155
+ throw new Error(`Failed to parse ${configPath}: ${e.message}`);
155
156
  }
156
157
  }
157
158
  Manager.prototype.getUJMConfig = Manager.getUJMConfig;
@@ -0,0 +1,201 @@
1
+ ---
2
+ layout: none
3
+ permalink: /test/libraries/firestore
4
+ sitemap:
5
+ include: false
6
+ ---
7
+ <!DOCTYPE html>
8
+ <html>
9
+ <head>
10
+ <meta charset="utf-8">
11
+ <meta name="viewport" content="width=device-width, initial-scale=1">
12
+ <title>Firestore Version Test</title>
13
+ <style>
14
+ * { margin: 0; padding: 0; box-sizing: border-box; }
15
+ body { font-family: monospace; padding: 16px; font-size: 13px; background: #111; color: #eee; }
16
+ h1 { font-size: 18px; margin-bottom: 8px; }
17
+ h2 { font-size: 14px; margin-bottom: 4px; color: #aaa; }
18
+ .test { margin-bottom: 12px; border: 1px solid #333; padding: 8px; border-radius: 4px; }
19
+ .test.success { border-color: #0a0; }
20
+ .test.fail { border-color: #a00; }
21
+ pre { white-space: pre-wrap; font-size: 11px; line-height: 1.3; max-height: 150px; overflow-y: auto; }
22
+ #ua { font-size: 11px; color: #666; margin-bottom: 12px; word-break: break-all; }
23
+ #status { font-size: 14px; margin-bottom: 12px; color: #ff0; }
24
+ .summary { margin-bottom: 16px; padding: 12px; border: 2px solid #555; border-radius: 4px; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <h1>Firestore Version + Transport Test</h1>
29
+ <div id="ua"></div>
30
+ <div id="status">Loading...</div>
31
+ <div id="sw-status" style="color: #f80; margin-bottom: 12px;"></div>
32
+ <div class="summary" id="summary" style="display:none"></div>
33
+
34
+ <div class="test" id="rest"><h2>Baseline: REST API (v12.11.0 auth only)</h2><pre id="rest-log"></pre></div>
35
+ <div class="test" id="v11"><h2>Firebase 11.0.0 - getFirestore</h2><pre id="v11-log"></pre></div>
36
+ <div class="test" id="v11lp"><h2>Firebase 11.0.0 - initializeFirestore + forceLongPolling</h2><pre id="v11lp-log"></pre></div>
37
+ <div class="test" id="v12_0"><h2>Firebase 12.0.0 - getFirestore</h2><pre id="v12_0-log"></pre></div>
38
+ <div class="test" id="v12_0lp"><h2>Firebase 12.0.0 - initializeFirestore + forceLongPolling</h2><pre id="v12_0lp-log"></pre></div>
39
+ <div class="test" id="v12_11"><h2>Firebase 12.11.0 (current) - getFirestore</h2><pre id="v12_11-log"></pre></div>
40
+ <div class="test" id="v12_11lp"><h2>Firebase 12.11.0 (current) - initializeFirestore + forceLongPolling</h2><pre id="v12_11lp-log"></pre></div>
41
+ <div class="test" id="v10"><h2>Firebase 10.14.0 - getFirestore</h2><pre id="v10-log"></pre></div>
42
+ <div class="test" id="v10lp"><h2>Firebase 10.14.0 - initializeFirestore + forceLongPolling</h2><pre id="v10lp-log"></pre></div>
43
+
44
+ <script type="module">
45
+ // Use 12.11.0 for auth only (default app)
46
+ import { initializeApp } from 'https://www.gstatic.com/firebasejs/12.11.0/firebase-app.js';
47
+ import { getAuth, onAuthStateChanged } from 'https://www.gstatic.com/firebasejs/12.11.0/firebase-auth.js';
48
+
49
+ const config = {{ page.resolved.web_manager.firebase.app.config | jsonify }};
50
+
51
+ document.getElementById('ua').textContent = navigator.userAgent;
52
+
53
+ // Unregister all service workers first
54
+ if ('serviceWorker' in navigator) {
55
+ const regs = await navigator.serviceWorker.getRegistrations();
56
+ console.log(`[Setup] Found ${regs.length} service worker(s)`);
57
+ for (const reg of regs) {
58
+ const result = await reg.unregister();
59
+ console.log(`[Setup] Unregistered service worker: ${reg.scope} (success: ${result})`);
60
+ }
61
+ const swMsg = regs.length > 0
62
+ ? `Unregistered ${regs.length} service worker(s)`
63
+ : 'No service workers found';
64
+ document.getElementById('sw-status').textContent = swMsg;
65
+ document.getElementById('status').textContent = swMsg + '. Running tests...';
66
+ } else {
67
+ console.log('[Setup] Service workers not supported');
68
+ document.getElementById('sw-status').textContent = 'Service workers not supported';
69
+ }
70
+
71
+ function makeLogger(id) {
72
+ const $log = document.getElementById(id + '-log');
73
+ const $box = document.getElementById(id);
74
+ return {
75
+ log: (msg) => {
76
+ console.log(`[${id}]`, msg);
77
+ $log.textContent += msg + '\n';
78
+ $log.scrollTop = $log.scrollHeight;
79
+ },
80
+ pass: () => { $box.classList.add('success'); return 'PASS'; },
81
+ fail: () => { $box.classList.add('fail'); return 'FAIL'; },
82
+ };
83
+ }
84
+
85
+ const results = {};
86
+
87
+ // REST baseline
88
+ async function testRest(uid, token) {
89
+ const t = makeLogger('rest');
90
+ try {
91
+ const url = `https://firestore.googleapis.com/v1/projects/${config.projectId}/databases/(default)/documents/users/${uid}`;
92
+ t.log('Fetching via REST...');
93
+ const res = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
94
+ t.log(`Status: ${res.status}`);
95
+ if (res.ok) {
96
+ const data = await res.json();
97
+ t.log('SUCCESS');
98
+ results['REST'] = t.pass();
99
+ } else {
100
+ const text = await res.text();
101
+ t.log('ERROR: ' + text.substring(0, 150));
102
+ results['REST'] = t.fail();
103
+ }
104
+ } catch (e) { t.log('ERROR: ' + e.message); results['REST'] = t.fail(); }
105
+ }
106
+
107
+ // Generic version test using dynamic import
108
+ async function testVersion(id, version, uid, useLP) {
109
+ const t = makeLogger(id);
110
+ try {
111
+ const label = useLP ? 'initializeFirestore+forceLongPolling' : 'getFirestore';
112
+ t.log(`Loading Firebase ${version}...`);
113
+
114
+ const appMod = await import(`https://www.gstatic.com/firebasejs/${version}/firebase-app.js`);
115
+ const fsMod = await import(`https://www.gstatic.com/firebasejs/${version}/firebase-firestore.js`);
116
+
117
+ const appName = id;
118
+ let app;
119
+ try {
120
+ app = appMod.initializeApp(config, appName);
121
+ } catch (e) {
122
+ app = appMod.getApp(appName);
123
+ }
124
+
125
+ let db;
126
+ if (useLP) {
127
+ t.log(`initializeFirestore + experimentalForceLongPolling...`);
128
+ db = fsMod.initializeFirestore(app, { experimentalForceLongPolling: true });
129
+ } else {
130
+ t.log(`getFirestore...`);
131
+ db = fsMod.getFirestore(app);
132
+ }
133
+
134
+ t.log(`Fetching users/${uid} (10s timeout)...`);
135
+
136
+ // Race against a timeout
137
+ const fetchPromise = fsMod.getDoc(fsMod.doc(db, 'users', uid));
138
+ const timeoutPromise = new Promise((_, reject) =>
139
+ setTimeout(() => reject(new Error('TIMEOUT after 10s')), 10000)
140
+ );
141
+
142
+ const snap = await Promise.race([fetchPromise, timeoutPromise]);
143
+
144
+ if (snap.exists()) {
145
+ t.log('SUCCESS: ' + JSON.stringify(snap.data()).substring(0, 100));
146
+ results[id] = t.pass();
147
+ } else {
148
+ t.log('Doc not found');
149
+ results[id] = t.fail();
150
+ }
151
+ } catch (e) {
152
+ const code = e.code || '';
153
+ if (code === 'permission-denied') {
154
+ t.log('TRANSPORT OK (permission-denied = network works, just no auth)');
155
+ results[id] = t.pass();
156
+ } else {
157
+ t.log(`ERROR: ${code} ${e.message}`);
158
+ results[id] = t.fail();
159
+ }
160
+ }
161
+ }
162
+
163
+ // Main
164
+ const defaultApp = initializeApp(config);
165
+ const auth = getAuth(defaultApp);
166
+
167
+ onAuthStateChanged(auth, async (user) => {
168
+ if (!user) {
169
+ document.getElementById('status').textContent = 'Not signed in. Sign in at /dashboard first.';
170
+ return;
171
+ }
172
+
173
+ const uid = user.uid;
174
+ const token = await user.getIdToken();
175
+ document.getElementById('status').textContent = `Signed in: ${uid}. Running tests...`;
176
+
177
+ // Run REST first
178
+ await testRest(uid, token);
179
+
180
+ // Run version tests (sequential to avoid interference)
181
+ await testVersion('v10', '10.14.0', uid, false);
182
+ await testVersion('v10lp', '10.14.0', uid, true);
183
+ await testVersion('v11', '11.0.0', uid, false);
184
+ await testVersion('v11lp', '11.0.0', uid, true);
185
+ await testVersion('v12_0', '12.0.0', uid, false);
186
+ await testVersion('v12_0lp', '12.0.0', uid, true);
187
+ await testVersion('v12_11', '12.11.0', uid, false);
188
+ await testVersion('v12_11lp', '12.11.0', uid, true);
189
+
190
+ // Show summary
191
+ document.getElementById('status').textContent = 'All tests complete.';
192
+ const $summary = document.getElementById('summary');
193
+ $summary.style.display = 'block';
194
+ $summary.innerHTML = '<h2 style="margin-bottom:8px">Results Summary</h2>' +
195
+ Object.entries(results).map(([k, v]) =>
196
+ `<div style="color:${v === 'PASS' ? '#0f0' : '#f00'}">${v}: ${k}</div>`
197
+ ).join('');
198
+ });
199
+ </script>
200
+ </body>
201
+ </html>
@@ -7,7 +7,7 @@ baseurl: ""
7
7
 
8
8
  # Theme
9
9
  theme:
10
- id: "umbra"
10
+ id: "classy"
11
11
  target: "frontend"
12
12
  appearance: "dark"
13
13
  version: "latest"
@@ -1,21 +1,21 @@
1
1
  // ============================================
2
2
  // Theme Configuration
3
3
  // ============================================
4
- // Customize theme variables here
5
- // See: ultimate-jekyll-manager/src/assets/themes/umbra/_config.scss for all available variables
4
+ // Customize Classy theme variables here
5
+ // See: ultimate-jekyll-manager/src/assets/themes/classy/_config.scss for all available variables
6
6
 
7
7
  @use 'ultimate-jekyll-manager' as * with (
8
8
  // ============================================
9
9
  // Brand Colors
10
10
  // ============================================
11
- // $primary: #E2725B,
12
- // $secondary: #8B7A75,
11
+ $primary: #5B47FB,
12
+ // $secondary: #6C757D,
13
13
 
14
14
  // ============================================
15
15
  // Backgrounds
16
16
  // ============================================
17
- // $umbra-bg-light: #FFFFFF,
18
- // $umbra-bg-dark: #1E1B1A,
17
+ // $classy-bg-light: #FFFFFF,
18
+ // $classy-bg-dark: #212529,
19
19
 
20
20
  // ============================================
21
21
  // Typography (uncomment to customize)
@@ -62,7 +62,7 @@ const watchInput = [
62
62
  `${rootPathPackage}/dist/service-worker.js`,
63
63
 
64
64
  // So we can watch for changes while we're developing web-manager
65
- `${rootPathPackage}/../web-manager/src`,
65
+ `${rootPathPackage}/../web-manager/dist`,
66
66
  ];
67
67
 
68
68
  // Files to copy directly without webpack processing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultimate-jekyll-manager",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Ultimate Jekyll dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -104,7 +104,7 @@
104
104
  "sass": "^1.98.0",
105
105
  "spellchecker": "^3.7.1",
106
106
  "through2": "^4.0.2",
107
- "web-manager": "^4.1.30",
107
+ "web-manager": "^4.1.31",
108
108
  "webpack": "^5.105.4",
109
109
  "wonderful-fetch": "^2.0.4",
110
110
  "wonderful-version": "^1.3.2",
@@ -1,5 +0,0 @@
1
- // Import Ultimate Jekyll Manager
2
- @use 'ultimate-jekyll-manager' as *;
3
-
4
- // Custom styles
5
- // ...
@@ -1,75 +0,0 @@
1
- # Umbra Theme Customization Guide
2
-
3
- ## How to Customize in Your Consuming Project
4
-
5
- The Umbra theme is designed to be fully customizable. All theme variables use `!default` which means you can override them BEFORE importing the theme.
6
-
7
- ### Example: Customizing Colors in Your Project
8
-
9
- In your consuming project's `src/assets/css/main.scss`:
10
-
11
- ```scss
12
- // 1. Override Umbra theme variables BEFORE importing the theme
13
- $primary: #FF0000; // Change primary color to red
14
- $umbra-bg-light: #F5F5F5; // Change light mode background
15
- $umbra-bg-dark: #1A1A1A; // Change dark mode background
16
- $font-family-sans-serif: 'Inter', sans-serif; // Change font
17
-
18
- // 2. Now import the Umbra theme - it will use YOUR values
19
- @import '~ultimate-jekyll-manager/src/assets/themes/umbra/theme';
20
-
21
- // 3. Add your custom styles below
22
- .my-custom-class {
23
- // Your custom CSS
24
- }
25
- ```
26
-
27
- ## Available Customizable Variables
28
-
29
- See `_config.scss` for the full list of variables you can override:
30
-
31
- ### Bootstrap Colors
32
- - `$primary` - Primary brand color
33
- - `$secondary` - Secondary color
34
- - `$success`, `$info`, `$warning`, `$danger` - Utility colors
35
- - `$light`, `$dark` - Light and dark variants
36
-
37
- ### Background Colors
38
- - `$umbra-bg-light` - Light mode background
39
- - `$umbra-bg-dark` - Dark mode background
40
-
41
- ### Typography
42
- - `$font-family-sans-serif` - Main font family
43
- - `$headings-font-weight` - Heading font weight
44
-
45
- ### Border Radius
46
- - `$border-radius` - Default border radius
47
- - `$border-radius-sm`, `$border-radius-lg` - Size variants
48
-
49
- ### Gradients
50
- - `$umbra-gradient-primary`, `$umbra-gradient-aurora`, etc.
51
-
52
- ## File Structure
53
-
54
- ```
55
- umbra/
56
- ├── _config.scss ← All customizable variables with !default
57
- ├── _theme.scss ← Main entry point, imports config then Bootstrap
58
- ├── css/base/
59
- │ ├── _variables.scss ← Internal non-customizable values
60
- │ └── _root.scss ← CSS custom property overrides
61
- └── ...
62
- ```
63
-
64
- ## How It Works
65
-
66
- 1. **`_config.scss`**: Defines all variables with `!default` (can be overridden)
67
- 2. **Your `main.scss`**: Sets custom values BEFORE importing theme
68
- 3. **`_theme.scss`**: Imports config (uses your values or defaults), then Bootstrap
69
- 4. **`_root.scss`**: Converts SCSS variables to CSS custom properties for runtime
70
-
71
- This ensures:
72
- - ✅ You can customize anything
73
- - ✅ Bootstrap gets configured with your colors
74
- - ✅ CSS custom properties update for light/dark mode
75
- - ✅ No need to modify theme files
@@ -1,187 +0,0 @@
1
- // Umbra Theme Configuration
2
- // ALL customizable variables are defined here with !default
3
- // Consuming projects can override any of these using @use ... with ()
4
-
5
- // ============================================
6
- // Bootstrap Color Overrides
7
- // ============================================
8
- $primary: #E2725B !default; // Terracotta
9
- $secondary: #8B7A75 !default; // Warm Gray
10
- $success: #2A9D8F !default;
11
- $info: #E9C46A !default; // Soft Gold
12
- $warning: #F4A261 !default;
13
- $danger: #E76F51 !default;
14
- $light: #FDFBF7 !default; // Warm Cream
15
- $dark: #1E1A18 !default; // Warm Charcoal
16
-
17
- // ============================================
18
- // Typography
19
- // ============================================
20
- $font-family-sans-serif: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !default;
21
- $headings-font-weight: 600 !default;
22
- $umbra-font-mono: monospace !default;
23
- $umbra-font-accent: 'Figtree', sans-serif !default;
24
-
25
- // ============================================
26
- // Border Radius
27
- // ============================================
28
- $border-radius: 0.5rem !default;
29
- $border-radius-sm: 0.375rem !default;
30
- $border-radius-lg: 0.75rem !default;
31
- $border-radius-xl: 1rem !default;
32
- $border-radius-2xl: 1.5rem !default;
33
- $border-radius-pill: 50rem !default;
34
-
35
- // Umbra-specific border radius aliases
36
- $umbra-radius-sm: $border-radius-sm !default;
37
- $umbra-radius-md: $border-radius !default;
38
- $umbra-radius-lg: $border-radius-lg !default;
39
- $umbra-radius-xl: $border-radius-xl !default;
40
- $umbra-radius-2xl: $border-radius-2xl !default;
41
- $umbra-radius-full: 9999px !default;
42
-
43
- // ============================================
44
- // Background Colors (Light Mode)
45
- // ============================================
46
- $umbra-bg-light: #FDFBF7 !default; // Main body background (warm cream)
47
- $umbra-bg-light-secondary: #F5F2EC !default; // Secondary backgrounds
48
- $umbra-bg-light-tertiary: #EBE5DB !default; // Tertiary backgrounds
49
-
50
- // ============================================
51
- // Background Colors (Dark Mode)
52
- // ============================================
53
- $umbra-bg-dark: #1E1A18 !default; // Main body background (warm charcoal)
54
- $umbra-bg-dark-secondary: #2A2421 !default; // Secondary backgrounds
55
- $umbra-bg-dark-tertiary: #372F2B !default; // Tertiary backgrounds
56
-
57
- // ============================================
58
- // Umbra-Specific Colors
59
- // ============================================
60
- $umbra-primary: $primary !default;
61
- $umbra-primary-dark: darken($primary, 10%) !default;
62
- $umbra-primary-light: lighten($primary, 10%) !default;
63
- $umbra-primary-soft: mix($primary, white, 10%) !default;
64
-
65
- $umbra-secondary: $secondary !default;
66
- $umbra-secondary-dark: darken($secondary, 5%) !default;
67
- $umbra-secondary-light: lighten($secondary, 5%) !default;
68
-
69
- $umbra-accent: $info !default;
70
- $umbra-accent-dark: darken($info, 10%) !default;
71
- $umbra-accent-light: lighten($info, 10%) !default;
72
-
73
- $umbra-dark: $dark !default;
74
- $umbra-dark-900: lighten($dark, 5%) !default;
75
- $umbra-dark-800: lighten($dark, 10%) !default;
76
- $umbra-dark-700: lighten($dark, 15%) !default;
77
- $umbra-dark-600: lighten($dark, 20%) !default;
78
-
79
- $umbra-gray: #6B7280 !default;
80
- $umbra-gray-light: #9CA3AF !default;
81
- $umbra-gray-lighter: #D1D5DB !default;
82
- $umbra-gray-lightest: #F3F4F6 !default;
83
-
84
- $umbra-white: #FFFFFF !default;
85
- $umbra-off-white: #FAFBFC !default;
86
- $umbra-cream: #FFF9F5 !default;
87
-
88
- // ============================================
89
- // Gradient Definitions
90
- // ============================================
91
- $umbra-gradient-primary: linear-gradient(135deg, $umbra-primary 0%, #D58C40 100%) !default;
92
- $umbra-gradient-dark: linear-gradient(135deg, $umbra-dark 0%, $umbra-dark-800 100%) !default;
93
- $umbra-gradient-light: linear-gradient(135deg, $umbra-white 0%, $umbra-off-white 100%) !default;
94
- $umbra-gradient-sunset: linear-gradient(135deg, #E2725B 0%, #F4A261 100%) !default;
95
- $umbra-gradient-aurora: linear-gradient(135deg, #E2725B 0%, #D58C40 50%, #2A9D8F 100%) !default;
96
- $umbra-gradient-rainbow: linear-gradient(60deg, #E2725B, #D58C40, #F4A261, #E9C46A, #2A9D8F, #8B7A75) !default;
97
-
98
- // ============================================
99
- // Typography Scale
100
- // ============================================
101
- $umbra-font-size-xs: 0.75rem !default;
102
- $umbra-font-size-sm: 0.875rem !default;
103
- $umbra-font-size-base: 1rem !default;
104
- $umbra-font-size-lg: 1.125rem !default;
105
- $umbra-font-size-xl: 1.25rem !default;
106
- $umbra-font-size-2xl: 1.5rem !default;
107
- $umbra-font-size-3xl: 1.875rem !default;
108
- $umbra-font-size-4xl: 2.25rem !default;
109
- $umbra-font-size-5xl: 3rem !default;
110
- $umbra-font-size-6xl: 3.75rem !default;
111
-
112
- // ============================================
113
- // Spacing Scale
114
- // ============================================
115
- $umbra-spacing-xs: 0.25rem !default;
116
- $umbra-spacing-sm: 0.5rem !default;
117
- $umbra-spacing-md: 1rem !default;
118
- $umbra-spacing-lg: 1.5rem !default;
119
- $umbra-spacing-xl: 2rem !default;
120
- $umbra-spacing-2xl: 3rem !default;
121
- $umbra-spacing-3xl: 4rem !default;
122
- $umbra-spacing-4xl: 6rem !default;
123
-
124
- // ============================================
125
- // Shadow System
126
- // ============================================
127
- $umbra-shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05) !default;
128
- $umbra-shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06) !default;
129
- $umbra-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !default;
130
- $umbra-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05) !default;
131
- $umbra-shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04) !default;
132
- $umbra-shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !default;
133
- $umbra-shadow-glow: 0 0 40px rgba(91, 71, 251, 0.15) !default;
134
-
135
- // ============================================
136
- // Transition Timing
137
- // ============================================
138
- $umbra-transition-fast: all 0.15s cubic-bezier(.2,.3,0,1) !default;
139
- $umbra-transition-base: all 0.3s cubic-bezier(.2,.3,0,1) !default;
140
- $umbra-transition-slow: all 0.5s cubic-bezier(.2,.3,0,1) !default;
141
- $umbra-transition-bounce: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55) !default;
142
-
143
- // ============================================
144
- // Responsive Breakpoints
145
- // ============================================
146
- // Bootstrap-compatible breakpoint values
147
- $umbra-breakpoint-sm: 576px !default;
148
- $umbra-breakpoint-md: 768px !default;
149
- $umbra-breakpoint-lg: 992px !default;
150
- $umbra-breakpoint-xl: 1200px !default;
151
- $umbra-breakpoint-xxl: 1400px !default;
152
-
153
- // ============================================
154
- // Component Sizing
155
- // ============================================
156
- // Avatar sizes map
157
- $avatar-sizes: (
158
- null: 3rem, // default
159
- 2xs: 0.5rem,
160
- xs: 1.5rem,
161
- sm: 2rem,
162
- md: 2.5rem,
163
- lg: 3.5rem,
164
- xl: 5rem,
165
- 2xl: 7.5rem,
166
- 3xl: 10rem,
167
- 4xl: 12.5rem,
168
- 5xl: 15rem
169
- ) !default;
170
-
171
- // Forward Bootstrap with our configuration
172
- @forward '../bootstrap/scss/bootstrap.scss' with (
173
- $primary: $primary,
174
- $secondary: $secondary,
175
- $success: $success,
176
- $info: $info,
177
- $warning: $warning,
178
- $danger: $danger,
179
- $light: $light,
180
- $dark: $dark,
181
- $font-family-sans-serif: $font-family-sans-serif,
182
- $headings-font-weight: $headings-font-weight,
183
- $border-radius: $border-radius,
184
- $border-radius-sm: $border-radius-sm,
185
- $border-radius-lg: $border-radius-lg,
186
- $enable-negative-margins: true
187
- );
@@ -1,36 +0,0 @@
1
- // Import the theme entry point
2
- // __main_assets__ is a webpack alias that resolves to UJM's dist/assets
3
- import bootstrap from '__main_assets__/themes/bootstrap/js/index.umd.js';
4
- import { ready as domReady } from 'web-manager/modules/dom.js';
5
-
6
- // Make Bootstrap available globally
7
- window.bootstrap = bootstrap;
8
-
9
- // Log that we've MADE IT
10
- /* @dev-only:start */
11
- {
12
- console.log('Umbra theme loaded successfully (assets/themes/umbra/_theme.js)');
13
- }
14
- /* @dev-only:end */
15
-
16
- // Import navbar scroll functionality
17
- import setupNavbarScroll from './js/navbar-scroll.js';
18
- // Import infinite scroll functionality (used by logo scroll, testimonials, etc.)
19
- import { setupInfiniteScroll } from './js/infinite-scroll.js';
20
- // Import tooltip initialization
21
- import initializeTooltips from './js/initialize-tooltips.js';
22
- // Import hero demo form initialization
23
- import initHeroDemoForm from './js/hero-demo-form.js';
24
-
25
- // Initialize theme components when DOM is ready
26
- domReady().then(() => {
27
- // Umbra Theme Initializations
28
- setupNavbarScroll();
29
- setupInfiniteScroll();
30
-
31
- // Generic Bootstrap initializations
32
- initializeTooltips();
33
-
34
- // Initialize hero demo form if present
35
- initHeroDemoForm();
36
- });
@@ -1,34 +0,0 @@
1
- // Forward theme configuration (allows consuming project to override)
2
- @forward 'config';
3
- @use 'config' as *;
4
-
5
- // Import root overrides (CSS custom properties)
6
- @import 'css/base/root';
7
-
8
- // Import base styles
9
- @import 'css/base/animations';
10
- @import 'css/base/backgrounds';
11
- @import 'css/base/borders';
12
- @import 'css/base/typography';
13
- @import 'css/base/utilities';
14
-
15
- // Import layout styles
16
- @import 'css/layout/backend';
17
- @import 'css/layout/blog';
18
- @import 'css/layout/general';
19
- @import 'css/layout/navigation';
20
- @import 'css/layout/team';
21
-
22
- // Import component styles
23
- @import 'css/components/accordion';
24
- @import 'css/components/badges';
25
- @import 'css/components/buttons';
26
- @import 'css/components/cards';
27
- @import 'css/components/carousel';
28
- @import 'css/components/forms';
29
- @import 'css/components/infinite-scroll';
30
- @import 'css/components/text';
31
-
32
- // Import universal Bootstrap overrides (shared across all UJ themes)
33
- // Must come AFTER Bootstrap is loaded via config to use @extend
34
- @import '../bootstrap/overrides';