1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import { create } from "zustand";
interface PreviewPopoutState {
pipWindow: Window | null;
container: HTMLElement | null;
openPopout: () => Promise<void>;
dockPopout: () => void;
}
function copyStylesInto({ pipWindow }: { pipWindow: Window }) {
const styleNodes = document.head.querySelectorAll(
"style, link[rel='stylesheet']",
);
for (const node of styleNodes) {
if (node instanceof HTMLStyleElement) {
pipWindow.document.head.appendChild(node.cloneNode(true));
} else if (node instanceof HTMLLinkElement) {
const link = pipWindow.document.createElement("link");
link.rel = "stylesheet";
link.href = node.href;
pipWindow.document.head.appendChild(link);
}
}
}
function preparePipDocument({ pipWindow }: { pipWindow: Window }) {
pipWindow.document.documentElement.className =
document.documentElement.className;
pipWindow.document.documentElement.style.height = "100%";
pipWindow.document.body.className = document.body.className;
pipWindow.document.body.style.margin = "0";
pipWindow.document.body.style.height = "100%";
pipWindow.document.body.style.overflow = "hidden";
pipWindow.document.title = "Preview";
copyStylesInto({ pipWindow });
}
export const usePreviewPopoutStore = create<PreviewPopoutState>()(
(set, get) => ({
pipWindow: null,
container: null,
openPopout: async () => {
if (get().container !== null) {
return;
}
if (!("documentPictureInPicture" in window)) {
return;
}
const pip = window.documentPictureInPicture;
if (!pip) {
return;
}
const pipWindow = await pip.requestWindow();
preparePipDocument({ pipWindow });
const container = pipWindow.document.createElement("div");
container.style.width = "100%";
container.style.height = "100%";
pipWindow.document.body.appendChild(container);
pipWindow.addEventListener(
"pagehide",
() => {
set({ pipWindow: null, container: null });
},
{ once: true },
);
set({ pipWindow, container });
},
dockPopout: () => {
const { pipWindow } = get();
if (pipWindow && !pipWindow.closed) {
pipWindow.close();
}
set({ pipWindow: null, container: null });
},
}),
);
|