@proto-labs-inc/rig-core 0.2.1 → 0.2.2
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/index.d.ts +4 -0
- package/dist/index.js +28 -4
- package/dist/page-history.d.ts +4 -0
- package/dist/page-history.js +38 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -18,11 +18,15 @@ export declare class RigStore {
|
|
|
18
18
|
private values;
|
|
19
19
|
private listeners;
|
|
20
20
|
constructor(manifest: Manifest);
|
|
21
|
+
updateManifest(manifest: Manifest): void;
|
|
21
22
|
get(key: string): string | undefined;
|
|
22
23
|
set(key: string, value: string): void;
|
|
23
24
|
setMany(entries: Array<[string, string]>): void;
|
|
24
25
|
setState(id: string, variants: Record<string, string>): void;
|
|
25
26
|
subscribe: (l: () => void) => () => void;
|
|
27
|
+
/** Restore the exact URL, including removed selections, without writing a
|
|
28
|
+
* new history entry while Back or Forward is traversing an existing one. */
|
|
29
|
+
restoreUrl(): void;
|
|
26
30
|
private syncUrl;
|
|
27
31
|
}
|
|
28
32
|
export declare function postToFrame(msg: RigToFrame): void;
|
package/dist/index.js
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { PROTOCOL_VERSION, STATE_PARAM, variantParam, applyVariantSelection, isFrameToRig, } from "@proto-labs-inc/wire";
|
|
8
8
|
import { loadFrameTools } from "./frame-tools-loader.js";
|
|
9
|
+
import { observePageHistory } from "./page-history.js";
|
|
9
10
|
export { STATE_PARAM, variantParam } from "@proto-labs-inc/wire";
|
|
10
|
-
const RIG_VERSION = "0.2.
|
|
11
|
+
const RIG_VERSION = "0.2.2";
|
|
11
12
|
export const INTERNAL_PREVIEW_THEME_PARAM = "__protoTheme";
|
|
12
13
|
/** Mark the page light or dark (data-proto-theme and the "dark" class) for
|
|
13
14
|
* a prototype that styles both. The page's own CSS decides color-scheme:
|
|
@@ -60,9 +61,12 @@ export class RigStore {
|
|
|
60
61
|
hydrated = true;
|
|
61
62
|
}
|
|
62
63
|
if (hydrated) {
|
|
63
|
-
window.history.replaceState(null, "", `?${params.toString()}`);
|
|
64
|
+
window.history.replaceState(null, "", `?${params.toString()}${window.location.hash || ""}`);
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
updateManifest(manifest) {
|
|
68
|
+
this.manifest = manifest;
|
|
69
|
+
}
|
|
66
70
|
get(key) {
|
|
67
71
|
return this.values.get(key);
|
|
68
72
|
}
|
|
@@ -115,6 +119,21 @@ export class RigStore {
|
|
|
115
119
|
this.listeners.delete(l);
|
|
116
120
|
};
|
|
117
121
|
};
|
|
122
|
+
/** Restore the exact URL, including removed selections, without writing a
|
|
123
|
+
* new history entry while Back or Forward is traversing an existing one. */
|
|
124
|
+
restoreUrl() {
|
|
125
|
+
const next = new Map();
|
|
126
|
+
for (const [key, value] of new URLSearchParams(window.location.search)) {
|
|
127
|
+
if (key === STATE_PARAM || key.startsWith("v."))
|
|
128
|
+
next.set(key, value);
|
|
129
|
+
}
|
|
130
|
+
const changed = next.size !== this.values.size ||
|
|
131
|
+
[...next].some(([key, value]) => this.values.get(key) !== value);
|
|
132
|
+
if (!changed)
|
|
133
|
+
return;
|
|
134
|
+
this.values = next;
|
|
135
|
+
this.listeners.forEach((listener) => listener());
|
|
136
|
+
}
|
|
118
137
|
syncUrl() {
|
|
119
138
|
const params = new URLSearchParams(window.location.search);
|
|
120
139
|
for (const key of [...params.keys()]) {
|
|
@@ -123,9 +142,8 @@ export class RigStore {
|
|
|
123
142
|
}
|
|
124
143
|
for (const [k, v] of this.values)
|
|
125
144
|
params.set(k, v);
|
|
126
|
-
const search = `?${params.toString()}`;
|
|
145
|
+
const search = `?${params.toString()}${window.location.hash || ""}`;
|
|
127
146
|
window.history.replaceState(null, "", search);
|
|
128
|
-
postToFrame({ type: "state-changed", search: searchForFrame() });
|
|
129
147
|
}
|
|
130
148
|
}
|
|
131
149
|
export function postToFrame(msg) {
|
|
@@ -203,6 +221,11 @@ async function captureThumbnail() {
|
|
|
203
221
|
* Call client-side only.
|
|
204
222
|
*/
|
|
205
223
|
export function wireRig(store, manifest) {
|
|
224
|
+
store.updateManifest(manifest);
|
|
225
|
+
const disposeHistory = observePageHistory(() => {
|
|
226
|
+
store.restoreUrl();
|
|
227
|
+
postToFrame({ type: "state-changed", search: searchForFrame() });
|
|
228
|
+
});
|
|
206
229
|
const disposeTools = loadFrameTools(manifest.frameOrigin);
|
|
207
230
|
let controlledTheme = false;
|
|
208
231
|
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
@@ -246,6 +269,7 @@ export function wireRig(store, manifest) {
|
|
|
246
269
|
});
|
|
247
270
|
}
|
|
248
271
|
return () => {
|
|
272
|
+
disposeHistory();
|
|
249
273
|
media.removeEventListener("change", onSystemTheme);
|
|
250
274
|
window.removeEventListener("message", onMessage);
|
|
251
275
|
disposeTools();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Every URL change in a prototype is a step the browser bar can revisit.
|
|
2
|
+
* Keep state-only history writes intact: routers use those for bookkeeping.
|
|
3
|
+
* Install after boot-time URL hydration, which is not a navigation. */
|
|
4
|
+
export declare function observePageHistory(onNavigate: () => void): () => void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Every URL change in a prototype is a step the browser bar can revisit.
|
|
2
|
+
* Keep state-only history writes intact: routers use those for bookkeeping.
|
|
3
|
+
* Install after boot-time URL hydration, which is not a navigation. */
|
|
4
|
+
export function observePageHistory(onNavigate) {
|
|
5
|
+
const history = window.history;
|
|
6
|
+
const push = history.pushState;
|
|
7
|
+
const replace = history.replaceState;
|
|
8
|
+
let currentUrl = window.location.href;
|
|
9
|
+
const changed = () => {
|
|
10
|
+
const url = window.location.href;
|
|
11
|
+
if (url === currentUrl)
|
|
12
|
+
return;
|
|
13
|
+
currentUrl = url;
|
|
14
|
+
onNavigate();
|
|
15
|
+
};
|
|
16
|
+
const pushState = function (data, unused, url) {
|
|
17
|
+
push.call(this, data, unused, url);
|
|
18
|
+
changed();
|
|
19
|
+
};
|
|
20
|
+
const replaceState = function (data, unused, url) {
|
|
21
|
+
const next = url == null ? window.location.href : new URL(url, window.location.href).href;
|
|
22
|
+
const write = next === window.location.href ? replace : push;
|
|
23
|
+
write.call(this, data, unused, url);
|
|
24
|
+
changed();
|
|
25
|
+
};
|
|
26
|
+
history.pushState = pushState;
|
|
27
|
+
history.replaceState = replaceState;
|
|
28
|
+
window.addEventListener("popstate", changed);
|
|
29
|
+
window.addEventListener("hashchange", changed);
|
|
30
|
+
return () => {
|
|
31
|
+
if (history.pushState === pushState)
|
|
32
|
+
history.pushState = push;
|
|
33
|
+
if (history.replaceState === replaceState)
|
|
34
|
+
history.replaceState = replace;
|
|
35
|
+
window.removeEventListener("popstate", changed);
|
|
36
|
+
window.removeEventListener("hashchange", changed);
|
|
37
|
+
};
|
|
38
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proto-labs-inc/rig-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Proto's rig, framework-free: URL-state sync, the postMessage bridge to the Frame, and comment mode.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@proto-labs-inc/wire": "^0.2.
|
|
31
|
+
"@proto-labs-inc/wire": "^0.2.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"typescript": "~6.0.2",
|