@sixb/desktop 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +81 -2
- package/dist/generate.d.ts +30 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/identity.d.ts +22 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +383 -0
- package/dist/index.js.map +15 -0
- package/dist/mac-icon.d.ts +7 -0
- package/dist/mac-icon.d.ts.map +1 -0
- package/dist/run.d.ts +3 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/shell/main.d.ts +2 -0
- package/dist/shell/main.d.ts.map +1 -0
- package/dist/shell/navigation.d.ts +39 -0
- package/dist/shell/navigation.d.ts.map +1 -0
- package/dist/shell/window.d.ts +44 -0
- package/dist/shell/window.d.ts.map +1 -0
- package/dist/tsconfig.json +5 -0
- package/package.json +57 -4
- package/src/generate.ts +134 -0
- package/src/identity.ts +83 -0
- package/src/index.ts +177 -0
- package/src/mac-icon.ts +81 -0
- package/src/packager.mjs +5 -0
- package/src/run.ts +11 -0
- package/src/shell/index.html +204 -0
- package/src/shell/main.ts +107 -0
- package/src/shell/navigation.ts +84 -0
- package/src/shell/window.ts +111 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { ShellConfig } from "./navigation"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether the window itself may show `url`: only the app and the API that serves its sign-in
|
|
5
|
+
* pages. Anything else a page links to opens in the user's browser instead.
|
|
6
|
+
*/
|
|
7
|
+
export function mayNavigate(config: ShellConfig, url: string): boolean {
|
|
8
|
+
try {
|
|
9
|
+
const { origin } = new URL(url)
|
|
10
|
+
return origin === new URL(config.appUrl).origin || origin === new URL(config.apiOrigin).origin
|
|
11
|
+
} catch {
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Whether `url` is on the app's own origin. Camera, location and the like are the app's to ask for,
|
|
18
|
+
* and not a frame it embeds from elsewhere.
|
|
19
|
+
*/
|
|
20
|
+
export function isAppUrl(config: ShellConfig, url: string): boolean {
|
|
21
|
+
try {
|
|
22
|
+
return new URL(url).origin === new URL(config.appUrl).origin
|
|
23
|
+
} catch {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* What the window paints before a page has: the loading page's own background, so the window
|
|
30
|
+
* opens, and passes from that page to the app, without a flash of white.
|
|
31
|
+
*/
|
|
32
|
+
export const WINDOW_BACKGROUND = { light: "#fafafa", dark: "#0a0a0a" } as const
|
|
33
|
+
|
|
34
|
+
/** The band at the top of a window without a title bar where macOS draws the window controls. */
|
|
35
|
+
export const CONTROLS_HEIGHT_PX = 36
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Styles for a window without a title bar, inserted into every page it shows.
|
|
39
|
+
*
|
|
40
|
+
* The page reaches the top edge, under the window controls, so two things a title bar did have
|
|
41
|
+
* to come from the page: somewhere to grab the window, and room for the controls.
|
|
42
|
+
* - `#sixb-desktop-drag` (added by the preload) is the drag handle: a strip across the top, above
|
|
43
|
+
* the page. It ignores the pointer, and every control is cut out of the draggable area, so
|
|
44
|
+
* buttons and links under the strip still take their clicks and the space between them moves
|
|
45
|
+
* the window. Something clickable that is none of the things listed here needs
|
|
46
|
+
* `-webkit-app-region: no-drag` of its own.
|
|
47
|
+
* - The shared sidebar is moved down so most apps need nothing. Other layouts can use
|
|
48
|
+
* `html[data-sixb-desktop]` and `--sixb-desktop-controls-height`, which the preload sets.
|
|
49
|
+
*/
|
|
50
|
+
export const HIDDEN_TITLE_BAR_CSS = [
|
|
51
|
+
`#sixb-desktop-drag{position:fixed;top:0;left:0;right:0;height:${CONTROLS_HEIGHT_PX}px;`,
|
|
52
|
+
"z-index:2147483647;pointer-events:none;-webkit-app-region:drag}",
|
|
53
|
+
`${[
|
|
54
|
+
"a",
|
|
55
|
+
"button",
|
|
56
|
+
"input",
|
|
57
|
+
"select",
|
|
58
|
+
"textarea",
|
|
59
|
+
"summary",
|
|
60
|
+
"label",
|
|
61
|
+
"[role=button]",
|
|
62
|
+
"[role=link]",
|
|
63
|
+
"[role=tab]",
|
|
64
|
+
"[role=menuitem]",
|
|
65
|
+
"[role=switch]",
|
|
66
|
+
"[role=checkbox]",
|
|
67
|
+
"[role=combobox]",
|
|
68
|
+
"[contenteditable]",
|
|
69
|
+
"[tabindex]:not([tabindex='-1'])",
|
|
70
|
+
].join(",")}{-webkit-app-region:no-drag}`,
|
|
71
|
+
`[data-slot="sidebar-inner"]{padding-top:calc(${CONTROLS_HEIGHT_PX}px - 0.5rem)}`,
|
|
72
|
+
].join("")
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The preload of a window without a title bar: runs in every page before the page's own scripts.
|
|
76
|
+
*
|
|
77
|
+
* It marks `<html>` the moment the element exists, so an app can read the mark on its first
|
|
78
|
+
* render, and adds the drag handle once there is a body to hold it. Written to a file by
|
|
79
|
+
* `writeDesktopApp`, which is why it is source text and not a function.
|
|
80
|
+
*/
|
|
81
|
+
export const HIDDEN_TITLE_BAR_PRELOAD = `(() => {
|
|
82
|
+
const mark = () => {
|
|
83
|
+
const root = document.documentElement
|
|
84
|
+
if (!root) return false
|
|
85
|
+
root.dataset.sixbDesktop = "inset"
|
|
86
|
+
root.style.setProperty("--sixb-desktop-controls-height", "${CONTROLS_HEIGHT_PX}px")
|
|
87
|
+
return true
|
|
88
|
+
}
|
|
89
|
+
if (!mark()) {
|
|
90
|
+
const observer = new MutationObserver(() => {
|
|
91
|
+
if (mark()) observer.disconnect()
|
|
92
|
+
})
|
|
93
|
+
observer.observe(document, { childList: true })
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const addHandle = () => {
|
|
97
|
+
if (!document.body || document.getElementById("sixb-desktop-drag")) return
|
|
98
|
+
const handle = document.createElement("div")
|
|
99
|
+
handle.id = "sixb-desktop-drag"
|
|
100
|
+
handle.setAttribute("aria-hidden", "true")
|
|
101
|
+
// First in the body, not last: the draggable area is built in document order, so a control
|
|
102
|
+
// is only cut out of it if it comes after the handle.
|
|
103
|
+
document.body.prepend(handle)
|
|
104
|
+
}
|
|
105
|
+
if (document.readyState === "loading") {
|
|
106
|
+
document.addEventListener("DOMContentLoaded", addHandle, { once: true })
|
|
107
|
+
} else {
|
|
108
|
+
addHandle()
|
|
109
|
+
}
|
|
110
|
+
})()
|
|
111
|
+
`
|