@lingxia/page-runtime 0.11.1 → 0.12.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/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { ensurePageBridgeSubscription, getPageActions, getPageSnapshot, getPageStateInfo, subscribePageData, subscribePageSnapshot, type ActionMap, type Snapshot, } from "./shared/runtime.js";
2
+ export { getPageChromeLayout, installPageChromeRuntime, subscribePageChromeLayout, type LxPageChrome, type PageChromeLayoutListener, type PageChromeLayoutSnapshot, type PageChromeRect, } from "./page-chrome.js";
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { ensurePageBridgeSubscription, getPageActions, getPageSnapshot, getPageStateInfo, subscribePageData, subscribePageSnapshot, } from "./shared/runtime.js";
2
+ export { getPageChromeLayout, installPageChromeRuntime, subscribePageChromeLayout, } from "./page-chrome.js";
@@ -0,0 +1,45 @@
1
+ export interface PageChromeRect {
2
+ readonly width: number;
3
+ readonly height: number;
4
+ readonly top: number;
5
+ readonly right: number;
6
+ readonly bottom: number;
7
+ readonly left: number;
8
+ }
9
+ export interface PageChromeLayoutSnapshot {
10
+ readonly revision: number;
11
+ /**
12
+ * Height of the runtime-owned drag strip across the top of a
13
+ * `chrome: 'full'` window. Zero everywhere else. Lay content out beneath it
14
+ * the same way you already do for the capsule — the strip stays draggable
15
+ * whether or not the page cooperates.
16
+ */
17
+ readonly topInset: number;
18
+ readonly bottomInset: number;
19
+ readonly capsuleRect: PageChromeRect | null;
20
+ readonly capsuleInlineEndInset: number;
21
+ }
22
+ export interface LxPageChrome {
23
+ readonly layout: PageChromeLayoutSnapshot;
24
+ }
25
+ export type PageChromeLayoutListener = (layout: PageChromeLayoutSnapshot) => void;
26
+ declare global {
27
+ interface Window {
28
+ readonly lxPageChrome: LxPageChrome;
29
+ }
30
+ interface WindowEventMap {
31
+ lxpagechromechange: CustomEvent<PageChromeLayoutSnapshot>;
32
+ }
33
+ }
34
+ export declare function shouldApplyPageChromeRevision(currentRevision: number, nextRevision: number): boolean;
35
+ /** Read the latest realized page-chrome layout synchronously. */
36
+ export declare function getPageChromeLayout(): PageChromeLayoutSnapshot;
37
+ /** Subscribe to realized page-chrome layout changes. */
38
+ export declare function subscribePageChromeLayout(listener: PageChromeLayoutListener): () => void;
39
+ /** Ensure browser previews have the same synchronous contract as native pages. */
40
+ export declare function installPageChromeRuntime(): LxPageChrome | undefined;
41
+ declare global {
42
+ interface Window {
43
+ readonly __lingxiaApplyPageChrome?: (layout: PageChromeLayoutSnapshot, scheme: "light" | "dark") => void;
44
+ }
45
+ }
@@ -0,0 +1,76 @@
1
+ const initialLayout = Object.freeze({
2
+ revision: 0,
3
+ topInset: 0,
4
+ bottomInset: 0,
5
+ capsuleRect: null,
6
+ capsuleInlineEndInset: 0,
7
+ });
8
+ export function shouldApplyPageChromeRevision(currentRevision, nextRevision) {
9
+ return nextRevision >= currentRevision;
10
+ }
11
+ function projectPageChromeLayout(layout) {
12
+ const root = document.documentElement;
13
+ root?.style.setProperty("--lx-page-chrome-top-inset", `${layout.topInset}px`);
14
+ root?.style.setProperty("--lx-page-chrome-bottom-inset", `${layout.bottomInset}px`);
15
+ root?.style.setProperty("--lx-page-chrome-capsule-inline-end-inset", `${layout.capsuleInlineEndInset}px`);
16
+ }
17
+ /** Read the latest realized page-chrome layout synchronously. */
18
+ export function getPageChromeLayout() {
19
+ if (typeof window === "undefined")
20
+ return initialLayout;
21
+ return installPageChromeRuntime()?.layout ?? initialLayout;
22
+ }
23
+ /** Subscribe to realized page-chrome layout changes. */
24
+ export function subscribePageChromeLayout(listener) {
25
+ if (typeof window === "undefined")
26
+ return () => { };
27
+ installPageChromeRuntime();
28
+ const handleChange = (event) => {
29
+ listener(event.detail);
30
+ };
31
+ window.addEventListener("lxpagechromechange", handleChange);
32
+ return () => window.removeEventListener("lxpagechromechange", handleChange);
33
+ }
34
+ /** Ensure browser previews have the same synchronous contract as native pages. */
35
+ export function installPageChromeRuntime() {
36
+ if (typeof window === "undefined")
37
+ return undefined;
38
+ if (window.lxPageChrome)
39
+ return window.lxPageChrome;
40
+ let layout = initialLayout;
41
+ const api = Object.freeze({
42
+ get layout() {
43
+ return layout;
44
+ },
45
+ });
46
+ Object.defineProperty(window, "lxPageChrome", {
47
+ configurable: false,
48
+ enumerable: true,
49
+ value: api,
50
+ });
51
+ Object.defineProperty(window, "__lingxiaApplyPageChrome", {
52
+ configurable: false,
53
+ enumerable: false,
54
+ value(next, scheme) {
55
+ if (!shouldApplyPageChromeRevision(layout.revision, next.revision))
56
+ return;
57
+ const capsuleRect = next.capsuleRect
58
+ ? Object.freeze({ ...next.capsuleRect })
59
+ : null;
60
+ layout = Object.freeze({ ...next, capsuleRect });
61
+ projectPageChromeLayout(layout);
62
+ const root = document.documentElement;
63
+ if (root) {
64
+ root.style.colorScheme = scheme;
65
+ // Authoritative theme signal: platform media queries can lag an
66
+ // in-place appearance switch (Android locks them at webview
67
+ // creation); [data-theme] CSS keys off this instead.
68
+ root.setAttribute('data-theme', scheme);
69
+ }
70
+ window.dispatchEvent(new CustomEvent("lxpagechromechange", { detail: layout }));
71
+ },
72
+ });
73
+ projectPageChromeLayout(initialLayout);
74
+ return api;
75
+ }
76
+ installPageChromeRuntime();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingxia/page-runtime",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "private": false,
5
5
  "description": "Shared page runtime core for LingXia lxapp frameworks",
6
6
  "type": "module",
@@ -16,10 +16,11 @@
16
16
  "scripts": {
17
17
  "build": "npm run clean && npm --prefix ../lingxia-bridge run build:types && tsc -p tsconfig.json",
18
18
  "clean": "rm -rf dist",
19
+ "test:runtime": "npm run build && node tests/page-chrome-revision.mjs",
19
20
  "prepublishOnly": "npm run build"
20
21
  },
21
22
  "dependencies": {
22
- "@lingxia/bridge": "^0.11.1"
23
+ "@lingxia/bridge": "~0.12.0"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@lingxia/bridge": "file:../lingxia-bridge",