baremetal.js 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -22,7 +22,23 @@ BareMetal.js is designed to bring Single Page Application (SPA) functionality to
22
22
 
23
23
  ### Installation
24
24
 
25
- No installation required! Just clone the repository or copy the `src` folder into your project.
25
+ **Option 1: Using npm**
26
+ If you are using a bundler (like Vite, Webpack) or modern Node.js environments:
27
+ ```bash
28
+ npm install baremetal.js
29
+ ```
30
+ ```javascript
31
+ import { BareMetal, loader } from 'baremetal.js';
32
+ ```
33
+
34
+ **Option 2: Using jsDelivr CDN**
35
+ To use the latest version directly in the browser without any build tools, import it via CDN:
36
+ ```javascript
37
+ import { BareMetal, loader } from 'https://cdn.jsdelivr.net/npm/baremetal.js@latest/src/index.js';
38
+ ```
39
+
40
+ **Option 3: Manual Download**
41
+ Just clone the repository or copy the `src` folder directly into your project.
26
42
 
27
43
  ### Running the Demo
28
44
 
@@ -122,6 +138,8 @@ The `BareMetal.init(config)` method accepts the following configuration object:
122
138
  | `transition.enabled` | boolean | `false` | Enable the protected transition module. |
123
139
  | `transition.module` | string | `null` | Path to a custom transition module. |
124
140
  | `transition.simulatedDelay` | number | `0` | Artificial delay (ms) for testing transitions. |
141
+ | `offline` | object | `{}` | Configure offline service worker support. See API docs for details. |
142
+ | `transition.useViewTransitions` | boolean | `false` | Enables the native View Transitions API for smooth cross-fades during navigation. |
125
143
 
126
144
  ## API Reference
127
145
 
package/demo/main.js CHANGED
@@ -2,7 +2,7 @@ import { BareMetal } from '../src/index.js';
2
2
 
3
3
  // Initialize the BareMetal engine with our desired config
4
4
  BareMetal.init({
5
- debug: false,
5
+ debug: true,
6
6
  keepAliveSameModules: true,
7
7
  autoWrap: false,
8
8
  hoverPrefetch: false,
package/demo/page2.html CHANGED
@@ -93,7 +93,7 @@
93
93
  Your browser does not support HTML video.
94
94
  </video>
95
95
  <br/>
96
- <audio id="demo-audio" data-baremetal-preserve controls style="width: 100%; margin-top: 10px;">
96
+ <audio id="demo-audio" data-baremetal-preserve controls style="width: 300px; margin-top: 10px;">
97
97
  <source src="./assets/audio/darren_hirst-20-474737.mp3" type="audio/mpeg">
98
98
  Your browser does not support the audio element.
99
99
  </audio>
package/docs/api.md CHANGED
@@ -15,10 +15,33 @@ Initializes the engine, sets up the Router, and binds global configurations.
15
15
  - `config.transition.enabled` *(boolean)*: Enables the protected transition module.
16
16
  - `config.transition.module` *(string)*: Optional path to a custom transition module (defaults to `/src/transition.js`).
17
17
  - `config.transition.simulatedDelay` *(number)*: Optional artificial delay in milliseconds (useful for testing animations locally).
18
+ - `config.transition.useViewTransitions` *(boolean)*: Enables the native View Transitions API for smooth cross-fades during navigation (default: `false`).
19
+ - `config.offline` *(object)*: Configuration for offline Progressive Web App (PWA) support.
20
+ - `config.offline.enabled` *(boolean)*: Enables Service Worker registration (default: `false`).
21
+ - `config.offline.version` *(string)*: Version identifier for the offline cache (e.g., `'1.0.0'`). Bump this to push updates to users.
22
+ - `config.offline.installType` *(string)*: `'auto'` (installs silently), `'consent'` (shows a popup), or `'custom'` (triggered manually via `BareMetal.offline.install()`).
23
+ - `config.offline.delay` *(number)*: Milliseconds to wait before auto-install or showing the consent popup.
24
+ - `config.offline.showInfo` *(boolean)*: If true, displays themed toast notifications at the bottom left during installation/updates.
25
+ - `config.offline.assets` *(string[])*: An array of URLs to strictly pre-cache upon installation.
18
26
 
19
27
  ---
20
28
 
21
- ## 2. Router Navigation
29
+ ## 2. Offline Manager
30
+
31
+ Accessible via `BareMetal.offline` when enabled.
32
+
33
+ ### `offline.install()`
34
+ Manually triggers the background download of all resources specified in `config.offline.assets`.
35
+
36
+ ### `offline.update()`
37
+ Triggers a background fetch to update the cached assets based on the current `config.offline.version`.
38
+
39
+ ### `offline.remove()`
40
+ Unregisters the Service Worker and deletes all offline caches.
41
+
42
+ ---
43
+
44
+ ## 3. Router Navigation
22
45
 
23
46
  ### `BareMetal.router.reload()`
24
47
  Executes a hard reload of the current SPA page by calling `window.location.reload()`. This is useful when you want to force the browser to wipe the entire SPA state and fetch fresh assets.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baremetal.js",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A lightweight, dependency-free Vanilla JavaScript SPA engine prioritizing extreme performance, native browser features, and explicit lifecycle management.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -26,4 +26,4 @@
26
26
  "url": "https://github.com/dkydivyansh/BareMetal.js/issues"
27
27
  },
28
28
  "homepage": "https://BareMetal.dkydivyansh.com"
29
- }
29
+ }
package/src/loader.js CHANGED
@@ -2,7 +2,7 @@ import { stateManager } from './state.js';
2
2
 
3
3
  export const Loader = {
4
4
  activeModules: {}, // { key: { path: "./dash.js", module: exportedModule } }
5
- config: { keepAliveSameModules: true, debug: false, autoWrap: true, hoverPrefetch: false, showErrorNotification: false, transition: { enabled: false, simulatedDelay: 0, module: null } },
5
+ config: { keepAliveSameModules: true, debug: false, autoWrap: true, hoverPrefetch: false, showErrorNotification: false, transition: { enabled: false, simulatedDelay: 0, module: null, useViewTransitions: false } },
6
6
 
7
7
  setConfig(globalConfig) {
8
8
  this.config = { ...this.config, ...globalConfig };
@@ -74,14 +74,14 @@ export const Loader = {
74
74
  this.log(`Importing module: ${path}`);
75
75
  try {
76
76
  const resolvedPath = new URL(path, document.baseURI).href;
77
- const noCachePath = `${resolvedPath}?t=${Date.now()}`;
77
+ const loadPath = this.config.debug ? `${resolvedPath}?t=${Date.now()}` : resolvedPath;
78
78
 
79
79
  let module;
80
80
 
81
81
  if (this.config.autoWrap) {
82
82
  // Fetch source to check if it needs auto-wrapping
83
- const response = await fetch(noCachePath);
84
- if (!response.ok) throw new Error(`Failed to fetch ${noCachePath}`);
83
+ const response = await fetch(loadPath);
84
+ if (!response.ok) throw new Error(`Failed to fetch ${loadPath}`);
85
85
  const sourceText = await response.text();
86
86
 
87
87
  const hasMount = /export\s+(function|const|let|var)\s+mount\b/.test(sourceText) || /export\s+\{.*?\bmount\b.*?\}/.test(sourceText);
@@ -101,11 +101,11 @@ export const Loader = {
101
101
  module = await import(blobUrl);
102
102
  URL.revokeObjectURL(blobUrl);
103
103
  } else {
104
- module = await import(noCachePath);
104
+ module = await import(loadPath);
105
105
  }
106
106
  } else {
107
107
  // Auto-wrapping disabled, load natively
108
- module = await import(noCachePath);
108
+ module = await import(loadPath);
109
109
  }
110
110
 
111
111
  if (typeof module.mount === 'function') {
package/src/router.js CHANGED
@@ -192,9 +192,18 @@ export const Router = {
192
192
  stateManager.publish('DOM_SWAPPED', null);
193
193
  };
194
194
 
195
- // Execute DOM swap and restore scroll synchronously
196
- executeDOMSwap();
197
- window.scrollTo(0, this.scrollMemory[url] || 0);
195
+ const doSwap = () => {
196
+ executeDOMSwap();
197
+ window.scrollTo(0, this.scrollMemory[url] || 0);
198
+ };
199
+
200
+ if (Loader.config.transition && Loader.config.transition.useViewTransitions && document.startViewTransition) {
201
+ document.startViewTransition(() => {
202
+ doSwap();
203
+ });
204
+ } else {
205
+ doSwap();
206
+ }
198
207
 
199
208
  // 4. Mount new modules (this emits ROUTE_END)
200
209
  await Loader.loadPrepared(modulesToLoad);
@@ -233,6 +242,11 @@ export const Router = {
233
242
  }, 4000);
234
243
  } else {
235
244
  // Formal redirect to let server handle the error
245
+ // FIRST: Undo the pushState so we don't leave a phantom history entry that breaks the Back button!
246
+ if (this.historyStack.length > 0) {
247
+ const prev = this.historyStack.pop();
248
+ history.replaceState(null, '', prev);
249
+ }
236
250
  window.location.assign(url);
237
251
  }
238
252
  }