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 +19 -1
- package/demo/main.js +1 -1
- package/demo/page2.html +1 -1
- package/docs/api.md +24 -1
- package/package.json +2 -2
- package/src/loader.js +6 -6
- package/src/router.js +17 -3
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
|
-
|
|
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
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:
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
84
|
-
if (!response.ok) throw new Error(`Failed to fetch ${
|
|
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(
|
|
104
|
+
module = await import(loadPath);
|
|
105
105
|
}
|
|
106
106
|
} else {
|
|
107
107
|
// Auto-wrapping disabled, load natively
|
|
108
|
-
module = await import(
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
}
|