overmux 0.0.9 → 0.0.10

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.
@@ -0,0 +1,166 @@
1
+ ---
2
+ title: Native web views
3
+ ---
4
+
5
+ `NativeWebView` embeds a website in Overmux Desktop using a chrome native webview.
6
+
7
+ ```tsx
8
+ import { NativeWebView } from "overmux/client";
9
+
10
+ export const Website = () => (
11
+ <NativeWebView
12
+ url="https://example.com"
13
+ style={{ width: "100%", height: 600 }}
14
+ fallback={
15
+ <a href="https://example.com" target="_blank" rel="noopener noreferrer">
16
+ Open website in browser
17
+ </a>
18
+ }
19
+ />
20
+ );
21
+ ```
22
+
23
+ ## Props
24
+
25
+ `NativeWebViewProps` and `NativeWebViewLoadError` are exported from `overmux/client`.
26
+
27
+ ### `url`
28
+
29
+ **Required.** Type: `string`. The initial website URL.
30
+
31
+ ```tsx
32
+ import { NativeWebView } from "overmux/client";
33
+
34
+ <NativeWebView url="https://example.com" style={{ height: 600 }} />;
35
+ ```
36
+
37
+ Changing this string navigates; rerendering the same URL preserves in-page navigation. A remount starts again at `url`, retaining cookies and site storage.
38
+
39
+ A blocked `url` prop clears the native page, including when an HTTP allowance is revoked. Blocked in-page links leave the current page in place. See [`allowedHttpOrigins`](#allowedhttporigins) for permitted destinations.
40
+
41
+ New-window links open in the system browser, not another embedded surface. The system browser has its own login state. Popup-based authentication flows may therefore not complete inside the embedded view; use in-page sign-in where supported.
42
+
43
+ ### `className`
44
+
45
+ **Optional.** Type: `string`. No default. Applies a CSS class to the desktop placeholder `div`, not the embedded website.
46
+
47
+ ```tsx
48
+ import { NativeWebView } from "overmux/client";
49
+
50
+ <NativeWebView
51
+ url="https://example.com"
52
+ className="website-pane"
53
+ style={{ height: 600 }}
54
+ />;
55
+ ```
56
+
57
+ Define the class in your application's stylesheet. See [Theming and CSS](./theming) for loading styles.
58
+
59
+ ### `style`
60
+
61
+ **Optional.** Type: `React.CSSProperties`. No default. Applies inline styles to the desktop placeholder `div`.
62
+
63
+ ```tsx
64
+ import { NativeWebView } from "overmux/client";
65
+
66
+ <NativeWebView
67
+ url="https://example.com"
68
+ style={{ width: "100%", height: 600 }}
69
+ />;
70
+ ```
71
+
72
+ Give the placeholder a **nonzero width and height**. The component has no default height. Desktop follows its rectangular position and size as the layout moves, scrolls or resizes. Hidden and zero-size placeholders hide the native surface without clearing its site data. See [Layout limitations](#layout-limitations) before using overlapping panes or CSS effects.
73
+
74
+ ### `fallback`
75
+
76
+ **Optional.** Type: `React.ReactNode`. Content shown in browsers, PWAs and desktop versions without native web view support.
77
+
78
+ ```tsx
79
+ import { NativeWebView } from "overmux/client";
80
+
81
+ <NativeWebView
82
+ url="https://example.com"
83
+ style={{ height: 600 }}
84
+ fallback={
85
+ <a href="https://example.com" target="_blank" rel="noopener noreferrer">
86
+ Open website in browser
87
+ </a>
88
+ }
89
+ />;
90
+ ```
91
+
92
+
93
+ ### `onLoadError`
94
+
95
+ **Optional.** Type: `(error: NativeWebViewLoadError) => void`. No default handler. Receives `{ url, code, message }` for main-page load failures, blocked destinations, invalid configuration or bridge errors.
96
+
97
+ ```tsx
98
+ import { NativeWebView, type NativeWebViewLoadError } from "overmux/client";
99
+
100
+ const reportLoadError = (error: NativeWebViewLoadError) => console.error(error);
101
+
102
+ <NativeWebView
103
+ url="https://example.com"
104
+ style={{ height: 600 }}
105
+ onLoadError={reportLoadError}
106
+ />;
107
+ ```
108
+
109
+ Main-page failures exclude subresource failures and aborted navigation superseded by a newer request.
110
+
111
+ | Code | Meaning |
112
+ | --- | --- |
113
+ | Numeric string, such as `"-105"` | Chromium load error |
114
+ | `ERR_URL_BLOCKED` | Destination rejected by navigation policy |
115
+ | `ERR_DESKTOP_BRIDGE` | Bridge or configuration failure |
116
+ | `ERR_OPEN_EXTERNAL` | Failed to open the system browser |
117
+ | `ERR_RENDER_PROCESS_GONE` | Native renderer crashed; the surface is destroyed |
118
+
119
+ Remount to retry after a native renderer crash.
120
+
121
+ ### `allowedHttpOrigins`
122
+
123
+ **Optional.** Type: `string[]`. Defaults to `[]`. Additional plain-HTTP origins to permit. An origin is the scheme, hostname and port, without a path.
124
+
125
+ ```tsx
126
+ import { NativeWebView } from "overmux/client";
127
+
128
+ <NativeWebView
129
+ url="http://devbox.local:3000"
130
+ style={{ height: 600 }}
131
+ allowedHttpOrigins={["http://devbox.local:3000"]}
132
+ />;
133
+ ```
134
+
135
+ HTTPS is allowed. HTTP is allowed for `localhost`, `127.0.0.1` and `[::1]`, plus exact origins in this list. Entries must be HTTP origins, optionally with a trailing slash. Wildcards, credentials, paths, queries and fragments are rejected. Matching includes the port. Other schemes are denied. Policy is enforced in Electron main for requested URLs, page navigation, redirects and new-window links.
136
+
137
+ ### `passthroughBindings`
138
+
139
+ **Optional.** Type: `readonly ShortcutBinding[]`. Defaults to `[]`. Keyboard bindings to forward to the owning Overmux UI while the embedded page has focus. `ShortcutBinding` is exported from `overmux/client`.
140
+
141
+ ```tsx
142
+ import { NativeWebView } from "overmux/client";
143
+
144
+ <NativeWebView
145
+ url="https://example.com"
146
+ style={{ height: 600 }}
147
+ passthroughBindings={["Escape", "Control+Shift+X", ["F12", "P", "R"]]}
148
+ />;
149
+ ```
150
+
151
+ Uses the same binding and chord syntax as [command shortcuts](./shortcuts), but does not require a matching command registration. A chord is a sequence of key presses, such as F12, then P, then R.
152
+
153
+ Overmux desktop intercepts a completed configured binding before the embedded page receives it and forwards its keyboard input, including modifiers and releases, to the owning Overmux UI. That UI then handles it through its ordinary DOM listeners - for example, a dialog's Escape handler, a local `onKeyDown`, or the normal shortcut host. The embedded page remains sandboxed and receives no Overmux bridge or command capability.
154
+
155
+
156
+ ## Security and shared sessions
157
+
158
+ Embedded pages have no Overmux bridge, preload script or Node access. Sandbox, context isolation and web security stay enabled. Permissions and downloads are denied.
159
+
160
+ All native views across connected Overmux instances share **one persistent desktop browser session**, `persist:overmux-native-web`. Cookies and login state survive unmounting, switching instances and restarting Desktop. This session is separate from Overmux authentication and from the system browser. Unmounting destroys the surface, not site data. Clearing an Overmux instance does not clear native website logins. There is no per-view profile or partition option.
161
+
162
+ ## Layout limitations
163
+
164
+ Native surfaces paint **above the DOM**, including React modals, menus and dropdowns. Use ordinary, non-overlapping rectangular panes. DOM stacking order, rounded corners, CSS transforms, ancestor clipping and arbitrary CSS effects are not faithfully reproduced. Bounds are clipped to the host window, not arbitrary DOM containers. Avoid layouts that depend on those effects; unmount the view when its native surface must not cover other content.
165
+
166
+ There is no `visible` prop, toolbar, zoom or history API, overlap coordination, or pane/session restoration. Host document reloads, crashes, instance changes and window destruction also destroy its native surfaces.
@@ -8,5 +8,6 @@ We recommend:
8
8
  - [TanStack Router](https://tanstack.com/router) for routing.
9
9
  - [shadcn/ui](https://ui.shadcn.com/) for UI components.
10
10
  - [Zod](https://zod.dev/) for schemas and runtime validation.
11
+ - [@pierre/diffs](https://diffs.com/) for building custom Git diff views.
11
12
 
12
13
  If your app already uses a different stack, follow its existing conventions.
@@ -122,7 +122,7 @@ Inspect these files so guidance matches the versions used by the application.
122
122
  #### `tech-stack-recommendations`
123
123
 
124
124
  ```text
125
- Prefer pnpm as the package manager, TanStack Router for routing, shadcn/ui for UI components, and Zod for schemas and runtime validation. Follow the application's established stack when it already differs.
125
+ Prefer pnpm as the package manager, TanStack Router for routing, shadcn/ui for UI components, and Zod for schemas and runtime validation. For custom Git diff views, prefer @pierre/diffs (https://diffs.com/). Follow the application's established stack when it already differs.
126
126
  ```
127
127
 
128
128
  [//]: # (END GENERATED AI CONTEXT)
@@ -2,12 +2,51 @@ import { B as InstanceIdentity, w as ContractInputArguments } from "./index-Dk11
2
2
  import { z } from "zod";
3
3
  import { UseMutationResult } from "@tanstack/react-query";
4
4
  import { CSSProperties, ComponentType, ReactNode, RefObject } from "react";
5
- import { KeyBinding, KeyBinding as KeyBinding$1 } from "@overmux/keybindings";
5
+ import { KeyBinding, KeyBinding as KeyBinding$1, KeySequence, ShortcutBinding, ShortcutBinding as ShortcutBinding$1, formatShortcutBinding } from "@overmux/keybindings";
6
6
  declare const enableBackgroundNotifications: () => Promise<boolean>;
7
7
  declare const disableBackgroundNotifications: () => Promise<void>;
8
+ type NativeWebViewLoadError = {
9
+ url: string;
10
+ code: string;
11
+ message: string;
12
+ };
13
+ type NativeWebViewProps = {
14
+ url: string;
15
+ className?: string;
16
+ style?: CSSProperties;
17
+ fallback?: ReactNode;
18
+ onLoadError?: (error: NativeWebViewLoadError) => void;
19
+ allowedHttpOrigins?: string[];
20
+ passthroughBindings?: readonly ShortcutBinding$1[];
21
+ };
22
+ declare const NativeWebView: ({ url, className, style, fallback, onLoadError, allowedHttpOrigins, passthroughBindings }: NativeWebViewProps) => import("react").JSX.Element;
23
+ type NativeWebViewBridge = {
24
+ version: 1;
25
+ command: (input: {
26
+ type: "create" | "destroy";
27
+ id: string;
28
+ } | {
29
+ type: "configure";
30
+ id: string;
31
+ url: string;
32
+ allowedHttpOrigins: string[];
33
+ passthroughBindings: readonly ShortcutBinding$1[];
34
+ }) => Promise<void>;
35
+ setBounds: (id: string, bounds: {
36
+ x: number;
37
+ y: number;
38
+ width: number;
39
+ height: number;
40
+ }) => void;
41
+ onLoadError: (callback: (input: {
42
+ id: string;
43
+ error: NativeWebViewLoadError;
44
+ }) => void) => () => void;
45
+ };
8
46
  type DesktopHost = {
9
47
  version: 1;
10
48
  platform: string;
49
+ nativeWebView?: NativeWebViewBridge;
11
50
  instance?: {
12
51
  report: (identity: {
13
52
  instanceId: string;
@@ -72,20 +111,17 @@ type OvermuxThemeScopeProps = {
72
111
  };
73
112
  declare const OvermuxPortal: ({ children, external }: OvermuxPortalProps) => import("react").ReactPortal | null;
74
113
  declare const OvermuxThemeScope: ({ children, className, contrast, scheme, style }: OvermuxThemeScopeProps) => import("react").JSX.Element;
75
- type KeySequence = readonly [KeyBinding$1, KeyBinding$1, ...KeyBinding$1[]];
76
- type ShortcutBinding = KeyBinding$1 | KeySequence;
77
114
  type ConditionalShortcutBinding = {
78
- binding: ShortcutBinding;
115
+ binding: ShortcutBinding$1;
79
116
  when: {
80
117
  media: string;
81
118
  };
82
119
  };
83
- type CommandBinding = ShortcutBinding | ConditionalShortcutBinding;
120
+ type CommandBinding = ShortcutBinding$1 | ConditionalShortcutBinding;
84
121
  type ChordPrefix = {
85
122
  binding: KeyBinding$1;
86
123
  unmatched: "replay-to-focused-input";
87
124
  };
88
- declare const formatShortcutBinding: (binding: ShortcutBinding) => string;
89
125
  type CommandRunResult$1 = Promise<unknown> | unknown;
90
126
  type CommandRun<TServerConfig, TParams> = (input: {
91
127
  overmuxServerApi: OvermuxServerApi<TServerConfig>;
@@ -254,5 +290,5 @@ type ShortcutInputTarget = {
254
290
  input: RefObject<HTMLElement | null>;
255
291
  };
256
292
  declare const useShortcutInputTarget: (target: ShortcutInputTarget) => void;
257
- export { type ChordPrefix, type CommandBinding, type CommandEntry, type CommandHandle, type ConditionalShortcutBinding, type InstanceIdentity, type KeyBinding, type KeySequence, type OvermuxClientAppearance, type OvermuxContrast, type OvermuxExternalPortalContainer, OvermuxHost, OvermuxPortal, type OvermuxPortalProps, type OvermuxScheme, type OvermuxServerApi, type OvermuxStyle, OvermuxThemeScope, type OvermuxThemeScopeProps, type OvermuxThemeToken, type ResourceResult, type ShortcutBinding, type ShortcutInputTarget, type SkipToken, type StreamResult, createOvermuxHooks, defineCommandRegistry, defineOvermuxClient, disableBackgroundNotifications, enableBackgroundNotifications, formatShortcutBinding, readClipboardText, skipToken, useCommand, useCommands, useShortcutInputTarget, writeClipboardText };
293
+ export { type ChordPrefix, type CommandBinding, type CommandEntry, type CommandHandle, type ConditionalShortcutBinding, type InstanceIdentity, type KeyBinding, type KeySequence, NativeWebView, type NativeWebViewLoadError, type NativeWebViewProps, type OvermuxClientAppearance, type OvermuxContrast, type OvermuxExternalPortalContainer, OvermuxHost, OvermuxPortal, type OvermuxPortalProps, type OvermuxScheme, type OvermuxServerApi, type OvermuxStyle, OvermuxThemeScope, type OvermuxThemeScopeProps, type OvermuxThemeToken, type ResourceResult, type ShortcutBinding, type ShortcutInputTarget, type SkipToken, type StreamResult, createOvermuxHooks, defineCommandRegistry, defineOvermuxClient, disableBackgroundNotifications, enableBackgroundNotifications, formatShortcutBinding, readClipboardText, skipToken, useCommand, useCommands, useShortcutInputTarget, writeClipboardText };
258
294
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/internal/client/background-notifications.ts","../../src/internal/client/host/desktop-host.ts","../../src/internal/client/clipboard.ts","../../src/internal/client/browser-api.ts","../../src/internal/client/theme-scope.tsx","../../src/internal/client/client-definition.ts","../../src/internal/client/commands.tsx","../../src/internal/client/overmux-react.ts","../../src/internal/client/host/overmux-host.tsx","../../src/internal/client/shortcuts.tsx"],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/internal/client/background-notifications.ts","../../src/internal/client/native-web-view.tsx","../../src/internal/client/host/desktop-host.ts","../../src/internal/client/clipboard.ts","../../src/internal/client/browser-api.ts","../../src/internal/client/theme-scope.tsx","../../src/internal/client/client-definition.ts","../../src/internal/client/commands.tsx","../../src/internal/client/overmux-react.ts","../../src/internal/client/host/overmux-host.tsx","../../src/internal/client/shortcuts.tsx"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { a as notificationSchema, c as parseDeepLink, l as resolveOvermuxReturnT
3
3
  import { z } from "zod";
4
4
  import { QueryClient, QueryClientProvider, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
5
  import { Component, createContext, createElement, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
6
- import { formatKeyBinding, keyBindingSchema, matchesKeyBinding, platformBinding } from "@overmux/keybindings";
6
+ import { formatShortcutBinding, keyBindingSchema, keyBindingSequence, matchesKeyBinding, matchesShortcutBindingPrefix, normalizedShortcutBinding, shortcutBindingSchema } from "@overmux/keybindings";
7
7
  import { createPortal } from "react-dom";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/internal/shared/background-notifications.ts
@@ -320,7 +320,6 @@ const writeClipboardText = async (text) => {
320
320
  };
321
321
  //#endregion
322
322
  //#region src/internal/client/client-definition.ts
323
- const shortcutBindingSchema = z.union([keyBindingSchema, z.array(keyBindingSchema).min(2)]);
324
323
  const commandBindingSchema = z.union([shortcutBindingSchema, z.object({
325
324
  binding: shortcutBindingSchema,
326
325
  when: z.object({ media: z.string().trim().min(1) })
@@ -329,7 +328,6 @@ const chordPrefixSchema = z.object({
329
328
  binding: keyBindingSchema,
330
329
  unmatched: z.literal("replay-to-focused-input")
331
330
  });
332
- const formatShortcutBinding = (binding) => typeof binding === "string" ? formatKeyBinding(binding) : binding.map(formatKeyBinding).join(" ");
333
331
  const validateBindings = (bindings) => bindings?.forEach((binding) => commandBindingSchema.parse(binding));
334
332
  const defineCommandRegistry = () => (commands) => Object.fromEntries(Object.entries(commands).map(([id, command]) => {
335
333
  validateBindings(command.defaultBindings);
@@ -919,12 +917,6 @@ const installDeepLinkNavigation = ({ getInstance, navigate = defaultNavigate })
919
917
  };
920
918
  //#endregion
921
919
  //#region src/internal/client/shortcuts.tsx
922
- const bindingSequence = (binding) => typeof binding === "string" ? [binding] : [...binding];
923
- const normalizedBinding = (binding) => bindingSequence(binding).map((key) => platformBinding(key));
924
- const sequenceMatches = (binding, pending, event) => {
925
- const sequence = normalizedBinding(binding);
926
- return sequence.length > pending.length && pending.every((key, index) => sequence[index] === key) && matchesKeyBinding(sequence[pending.length], event);
927
- };
928
920
  const isTextInput = (element) => element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement || element instanceof HTMLElement && (element.isContentEditable || element.getAttribute("role") === "textbox");
929
921
  const acceptsTextInput = (bindings) => {
930
922
  if (!(document.activeElement instanceof Element)) return false;
@@ -932,7 +924,7 @@ const acceptsTextInput = (bindings) => {
932
924
  if (!terminal) return false;
933
925
  if (terminal.closest("[data-copy-mode]")) return true;
934
926
  return bindings.some((binding) => {
935
- const sequence = bindingSequence(binding);
927
+ const sequence = keyBindingSequence(binding);
936
928
  return sequence.length > 1 || sequence[0]?.startsWith("F") || sequence[0]?.includes("+");
937
929
  });
938
930
  };
@@ -1030,8 +1022,8 @@ const ShortcutHost = ({ children, definition, registrations, registrationRevisio
1030
1022
  window.addEventListener("focusin", refreshFocus);
1031
1023
  return () => window.removeEventListener("focusin", refreshFocus);
1032
1024
  }, []);
1025
+ const shortcuts = flattenShortcuts(definition, (media) => window.matchMedia(media).matches);
1033
1026
  useEffect(() => {
1034
- const shortcuts = flattenShortcuts(definition, (media) => window.matchMedia(media).matches);
1035
1027
  let pending = [];
1036
1028
  let pendingEvents = [];
1037
1029
  let pendingTarget;
@@ -1061,7 +1053,11 @@ const ShortcutHost = ({ children, definition, registrations, registrationRevisio
1061
1053
  clearPending();
1062
1054
  return;
1063
1055
  }
1064
- const matches = shortcuts.flatMap((shortcut) => shortcut.bindings.filter((binding) => sequenceMatches(binding, pending, event) && canRunShortcut(shortcut, event, registrations)).map((binding) => ({
1056
+ const matches = shortcuts.flatMap((shortcut) => shortcut.bindings.filter((binding) => matchesShortcutBindingPrefix({
1057
+ binding,
1058
+ input: event,
1059
+ pending
1060
+ }) && canRunShortcut(shortcut, event, registrations)).map((binding) => ({
1065
1061
  binding,
1066
1062
  shortcut
1067
1063
  })));
@@ -1073,14 +1069,14 @@ const ShortcutHost = ({ children, definition, registrations, registrationRevisio
1073
1069
  }
1074
1070
  return;
1075
1071
  }
1076
- const complete = matches.find(({ binding }) => normalizedBinding(binding).length === pending.length + 1);
1072
+ const complete = matches.find(({ binding }) => normalizedShortcutBinding(binding).length === pending.length + 1);
1077
1073
  if (complete) {
1078
1074
  clearPending();
1079
1075
  if (runShortcut(complete.shortcut, event, registrations)) event.stopPropagation();
1080
1076
  return;
1081
1077
  }
1082
1078
  if (!pending.length) pendingTarget = definition.chordPrefixes?.some((prefix) => matchesKeyBinding(prefix.binding, event)) ? selectShortcutInputTarget(inputTargets, document.activeElement) : void 0;
1083
- pending = [...pending, normalizedBinding(matches[0].binding)[pending.length]];
1079
+ pending = [...pending, normalizedShortcutBinding(matches[0].binding)[pending.length]];
1084
1080
  pendingEvents = [...pendingEvents, event];
1085
1081
  event.preventDefault();
1086
1082
  event.stopPropagation();
@@ -1906,6 +1902,118 @@ const OvermuxHost = ({ definition }) => /* @__PURE__ */ jsx(OvermuxThemeScope, {
1906
1902
  children: location.pathname === "/_overmux/settings" ? /* @__PURE__ */ jsx(HostedSettingsPage, {}) : location.pathname === "/_overmux/logout" ? /* @__PURE__ */ jsx(HostedLogoutPage, {}) : /* @__PURE__ */ jsx(OvermuxRuntime, { definition })
1907
1903
  });
1908
1904
  //#endregion
1909
- export { OvermuxHost, OvermuxPortal, OvermuxThemeScope, createOvermuxHooks, defineCommandRegistry, defineOvermuxClient, disableBackgroundNotifications, enableBackgroundNotifications, formatShortcutBinding, readClipboardText, skipToken, useCommand, useCommands, useShortcutInputTarget, writeClipboardText };
1905
+ //#region src/internal/client/native-web-view.tsx
1906
+ const command = async (view, input, url) => {
1907
+ try {
1908
+ await view.bridge.command(input);
1909
+ } catch (error) {
1910
+ view.report({
1911
+ url,
1912
+ code: "ERR_DESKTOP_BRIDGE",
1913
+ message: String(error)
1914
+ });
1915
+ }
1916
+ };
1917
+ const trackBounds = (element, view) => {
1918
+ let previous = "";
1919
+ let frame = 0;
1920
+ const measure = () => {
1921
+ const rect = element.getBoundingClientRect();
1922
+ const visible = !document.hidden && element.checkVisibility({
1923
+ opacityProperty: true,
1924
+ visibilityProperty: true
1925
+ });
1926
+ const bounds = {
1927
+ x: Math.round(rect.x),
1928
+ y: Math.round(rect.y),
1929
+ width: visible ? Math.max(0, Math.round(rect.width)) : 0,
1930
+ height: visible ? Math.max(0, Math.round(rect.height)) : 0
1931
+ };
1932
+ const key = JSON.stringify(bounds);
1933
+ if (key !== previous) {
1934
+ previous = key;
1935
+ view.bridge.setBounds(view.id, bounds);
1936
+ }
1937
+ };
1938
+ const tick = () => {
1939
+ measure();
1940
+ frame = requestAnimationFrame(tick);
1941
+ };
1942
+ tick();
1943
+ document.addEventListener("visibilitychange", measure);
1944
+ return () => {
1945
+ cancelAnimationFrame(frame);
1946
+ document.removeEventListener("visibilitychange", measure);
1947
+ };
1948
+ };
1949
+ const NativeWebView = ({ url, className, style, fallback, onLoadError, allowedHttpOrigins = [], passthroughBindings = [] }) => {
1950
+ const bridge = typeof window === "undefined" || window.overmuxHost?.version !== 1 || window.overmuxHost.nativeWebView?.version !== 1 ? void 0 : window.overmuxHost.nativeWebView;
1951
+ const element = useRef(null);
1952
+ const mounted = useRef(void 0);
1953
+ const latest = useRef({
1954
+ url,
1955
+ onLoadError
1956
+ });
1957
+ latest.current = {
1958
+ url,
1959
+ onLoadError
1960
+ };
1961
+ const origins = JSON.stringify(allowedHttpOrigins);
1962
+ const bindings = JSON.stringify(passthroughBindings);
1963
+ useEffect(() => {
1964
+ if (!bridge || !element.current) return;
1965
+ const view = {
1966
+ id: crypto.randomUUID(),
1967
+ active: true,
1968
+ bridge,
1969
+ report: (error) => {
1970
+ queueMicrotask(() => {
1971
+ if (view.active) latest.current.onLoadError?.(error);
1972
+ });
1973
+ }
1974
+ };
1975
+ mounted.current = view;
1976
+ const unsubscribe = bridge.onLoadError(({ id, error }) => {
1977
+ if (id === view.id) view.report(error);
1978
+ });
1979
+ command(view, {
1980
+ type: "create",
1981
+ id: view.id
1982
+ }, latest.current.url);
1983
+ const stopTracking = trackBounds(element.current, view);
1984
+ return () => {
1985
+ view.active = false;
1986
+ mounted.current = void 0;
1987
+ stopTracking();
1988
+ unsubscribe();
1989
+ command(view, {
1990
+ type: "destroy",
1991
+ id: view.id
1992
+ }, latest.current.url);
1993
+ };
1994
+ }, [bridge]);
1995
+ useEffect(() => {
1996
+ const view = mounted.current;
1997
+ if (view) command(view, {
1998
+ type: "configure",
1999
+ id: view.id,
2000
+ url,
2001
+ allowedHttpOrigins: JSON.parse(origins),
2002
+ passthroughBindings: JSON.parse(bindings)
2003
+ }, url);
2004
+ }, [
2005
+ bindings,
2006
+ bridge,
2007
+ url,
2008
+ origins
2009
+ ]);
2010
+ return bridge ? /* @__PURE__ */ jsx("div", {
2011
+ ref: element,
2012
+ className,
2013
+ style
2014
+ }) : /* @__PURE__ */ jsx(Fragment, { children: fallback });
2015
+ };
2016
+ //#endregion
2017
+ export { NativeWebView, OvermuxHost, OvermuxPortal, OvermuxThemeScope, createOvermuxHooks, defineCommandRegistry, defineOvermuxClient, disableBackgroundNotifications, enableBackgroundNotifications, formatShortcutBinding, readClipboardText, skipToken, useCommand, useCommands, useShortcutInputTarget, writeClipboardText };
1910
2018
 
1911
2019
  //# sourceMappingURL=client.js.map