@hansenexus/hud 0.2.0 → 0.4.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/README.md +253 -9
- package/dist/access-CNvJOwKM.d.ts +54 -0
- package/dist/capabilities-CjulXFQX.js +189 -0
- package/dist/define-hud-BBzsSl8b.d.ts +36 -0
- package/dist/env-DfxpPfs9.js +28 -0
- package/dist/env-vEjyJfPW.d.ts +17 -0
- package/dist/force-state-BaqWsmrf.js +153 -0
- package/dist/force-state-CCqoTfVB.d.ts +23 -0
- package/dist/handler-WmE4Lu7l.d.ts +39 -0
- package/dist/index-BYsdS-7d.d.ts +55 -0
- package/dist/index.d.ts +6 -39
- package/dist/index.js +980 -264
- package/dist/marker-C66LxOhJ.d.ts +9 -0
- package/dist/marker-CMrvxPmS.d.ts +12 -0
- package/dist/marker-DjeGvL-F.js +9 -0
- package/dist/marker-uZYPOJ4M.js +12 -0
- package/dist/markers.d.ts +3 -0
- package/dist/markers.js +3 -0
- package/dist/next.d.ts +33 -0
- package/dist/next.js +52 -0
- package/dist/payload-CLKDVZWl.d.ts +68 -0
- package/dist/plugins/access/server.d.ts +122 -0
- package/dist/plugins/access/server.js +339 -0
- package/dist/plugins/access.d.ts +41 -0
- package/dist/plugins/access.js +250 -0
- package/dist/plugins/agent/server.d.ts +129 -0
- package/dist/plugins/agent/server.js +429 -0
- package/dist/plugins/agent.d.ts +37 -0
- package/dist/plugins/agent.js +411 -0
- package/dist/plugins/design.d.ts +125 -0
- package/dist/plugins/design.js +619 -0
- package/dist/plugins/observe.d.ts +64 -0
- package/dist/plugins/observe.js +617 -0
- package/dist/plugins/ops/server.d.ts +82 -0
- package/dist/plugins/ops/server.js +380 -0
- package/dist/plugins/ops.d.ts +26 -0
- package/dist/plugins/ops.js +362 -0
- package/dist/plugins/vitals.d.ts +25 -0
- package/dist/plugins/vitals.js +26 -0
- package/dist/plugins-CQ_0w1ot.d.ts +114 -0
- package/dist/plugins-DVy_vaYr.js +70 -0
- package/dist/review.d.ts +181 -0
- package/dist/review.js +1017 -0
- package/dist/selector-NSYSe7AZ.js +28 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +106 -0
- package/dist/shortcut-U6ftVY06.js +222 -0
- package/dist/state-boundary.d.ts +26 -0
- package/dist/state-boundary.js +61 -0
- package/dist/styles--slk86ZQ.js +332 -0
- package/dist/types-DADBRiGk.d.ts +50 -0
- package/dist/types-QJUajwWq.js +35 -0
- package/dist/types-f3jlNxzw.d.ts +92 -0
- package/dist/vitals-panel-Dvc5dnR-.js +87 -0
- package/package.json +36 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
//#region src/plugins/design/force-state.ts
|
|
2
|
+
/**
|
|
3
|
+
* Force-state store: lets a reviewer (the States panel) or an agent
|
|
4
|
+
* (`?__state=`) render any registered state boundary as loading, empty or
|
|
5
|
+
* error without faking data.
|
|
6
|
+
*
|
|
7
|
+
* Development only. `StateBoundary` reaches this module behind a
|
|
8
|
+
* `NODE_ENV === "development"` constant, so production builds drop it; a
|
|
9
|
+
* consumer's bundle gate greps client chunks for FORCE_STATE_MARKER to prove it.
|
|
10
|
+
*/
|
|
11
|
+
const FORCED_STATES = [
|
|
12
|
+
"loading",
|
|
13
|
+
"empty",
|
|
14
|
+
"error"
|
|
15
|
+
];
|
|
16
|
+
/** `?__state=loading` forces top-level boundaries; `?__state=<id>:error` one boundary. */
|
|
17
|
+
const FORCE_STATE_PARAM = "__state";
|
|
18
|
+
/**
|
|
19
|
+
* globalThis key of the store singleton, and the bundle-gate marker. Holding
|
|
20
|
+
* the store on globalThis keeps one instance even if the module is evaluated
|
|
21
|
+
* twice: HMR, or the app's `StateBoundary` chunk and the HUD's States panel
|
|
22
|
+
* chunk each carrying a copy.
|
|
23
|
+
*/
|
|
24
|
+
const FORCE_STATE_MARKER = "__HANSENEXUS_HUD_FORCE_STATE__";
|
|
25
|
+
function isForcedState(value) {
|
|
26
|
+
return FORCED_STATES.includes(value);
|
|
27
|
+
}
|
|
28
|
+
/** Parses the value of `?__state=`; anything unrecognised is ignored (null). */
|
|
29
|
+
function parseForceStateParam(value) {
|
|
30
|
+
if (!value) return null;
|
|
31
|
+
const separator = value.lastIndexOf(":");
|
|
32
|
+
if (separator === -1) return isForcedState(value) ? {
|
|
33
|
+
state: value,
|
|
34
|
+
target: null
|
|
35
|
+
} : null;
|
|
36
|
+
const target = value.slice(0, separator);
|
|
37
|
+
const state = value.slice(separator + 1);
|
|
38
|
+
if (!target || !isForcedState(state)) return null;
|
|
39
|
+
return {
|
|
40
|
+
state,
|
|
41
|
+
target
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Reads the param out of a `location.search` string. */
|
|
45
|
+
function forceStateParamFromSearch(search) {
|
|
46
|
+
return parseForceStateParam(new URLSearchParams(search).get(FORCE_STATE_PARAM));
|
|
47
|
+
}
|
|
48
|
+
/** The param's value as it appears in the URL, `<id>:<state>` or `<state>`. */
|
|
49
|
+
function formatForceStateParam(param) {
|
|
50
|
+
return param.target === null ? param.state : `${param.target}:${param.state}`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The state a boundary renders. A panel override for the boundary wins; else
|
|
54
|
+
* the URL param applies to its target, or, untargeted, to the nearest
|
|
55
|
+
* boundaries: the top-level ones. Forcing an outer boundary unmounts the
|
|
56
|
+
* inner ones anyway, so the page-level state is what a screenshot wants.
|
|
57
|
+
*/
|
|
58
|
+
function resolveForcedState(snapshot, boundary) {
|
|
59
|
+
const override = snapshot.overrides[boundary.id];
|
|
60
|
+
if (override) return override;
|
|
61
|
+
const { param } = snapshot;
|
|
62
|
+
if (!param) return null;
|
|
63
|
+
if (param.target !== null) return param.target === boundary.id ? param.state : null;
|
|
64
|
+
return boundary.parentId === null ? param.state : null;
|
|
65
|
+
}
|
|
66
|
+
var ForceStateStore = class {
|
|
67
|
+
registrations = /* @__PURE__ */ new Map();
|
|
68
|
+
overrides = {};
|
|
69
|
+
search = "";
|
|
70
|
+
snapshot = {
|
|
71
|
+
boundaries: [],
|
|
72
|
+
overrides: {},
|
|
73
|
+
param: null
|
|
74
|
+
};
|
|
75
|
+
listeners = /* @__PURE__ */ new Set();
|
|
76
|
+
getSnapshot = () => this.snapshot;
|
|
77
|
+
subscribe = (listener) => {
|
|
78
|
+
this.listeners.add(listener);
|
|
79
|
+
return () => {
|
|
80
|
+
this.listeners.delete(listener);
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
/** Registers a mounted boundary; the returned function unregisters it. Mounts are counted. */
|
|
84
|
+
register(id, parentId) {
|
|
85
|
+
const existing = this.registrations.get(id);
|
|
86
|
+
this.registrations.set(id, {
|
|
87
|
+
parentId,
|
|
88
|
+
count: (existing?.count ?? 0) + 1
|
|
89
|
+
});
|
|
90
|
+
this.emit();
|
|
91
|
+
return () => {
|
|
92
|
+
const current = this.registrations.get(id);
|
|
93
|
+
if (!current) return;
|
|
94
|
+
if (current.count > 1) this.registrations.set(id, {
|
|
95
|
+
...current,
|
|
96
|
+
count: current.count - 1
|
|
97
|
+
});
|
|
98
|
+
else this.registrations.delete(id);
|
|
99
|
+
this.emit();
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Forces one boundary (panel toggle); null returns it to auto. */
|
|
103
|
+
force(id, state) {
|
|
104
|
+
const next = { ...this.overrides };
|
|
105
|
+
if (state) next[id] = state;
|
|
106
|
+
else delete next[id];
|
|
107
|
+
this.overrides = next;
|
|
108
|
+
this.emit();
|
|
109
|
+
}
|
|
110
|
+
clearOverrides() {
|
|
111
|
+
this.overrides = {};
|
|
112
|
+
this.emit();
|
|
113
|
+
}
|
|
114
|
+
/** Feeds the current `location.search`; a no-op when it did not change. */
|
|
115
|
+
syncSearch(search) {
|
|
116
|
+
if (search === this.search) return;
|
|
117
|
+
this.search = search;
|
|
118
|
+
this.emit();
|
|
119
|
+
}
|
|
120
|
+
emit() {
|
|
121
|
+
this.snapshot = {
|
|
122
|
+
boundaries: [...this.registrations].map(([id, { parentId }]) => ({
|
|
123
|
+
id,
|
|
124
|
+
parentId
|
|
125
|
+
})),
|
|
126
|
+
overrides: this.overrides,
|
|
127
|
+
param: forceStateParamFromSearch(this.search)
|
|
128
|
+
};
|
|
129
|
+
for (const listener of this.listeners) listener();
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
/** The page's store, created on first use. */
|
|
133
|
+
function getForceStateStore() {
|
|
134
|
+
const holder = globalThis;
|
|
135
|
+
holder[FORCE_STATE_MARKER] ??= new ForceStateStore();
|
|
136
|
+
return holder[FORCE_STATE_MARKER];
|
|
137
|
+
}
|
|
138
|
+
/** Subscribes to the page's store and keeps it in step with back/forward navigation. */
|
|
139
|
+
function subscribeForceState(listener) {
|
|
140
|
+
const store = getForceStateStore();
|
|
141
|
+
const onPopState = () => store.syncSearch(window.location.search);
|
|
142
|
+
window.addEventListener("popstate", onPopState);
|
|
143
|
+
const unsubscribe = store.subscribe(listener);
|
|
144
|
+
return () => {
|
|
145
|
+
window.removeEventListener("popstate", onPopState);
|
|
146
|
+
unsubscribe();
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function getForceStateSnapshot() {
|
|
150
|
+
return getForceStateStore().getSnapshot();
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { getForceStateSnapshot as a, subscribeForceState as c, formatForceStateParam as i, FORCE_STATE_MARKER as n, getForceStateStore as o, FORCE_STATE_PARAM as r, resolveForcedState as s, FORCED_STATES as t };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/plugins/design/force-state.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Force-state store: lets a reviewer (the States panel) or an agent
|
|
4
|
+
* (`?__state=`) render any registered state boundary as loading, empty or
|
|
5
|
+
* error without faking data.
|
|
6
|
+
*
|
|
7
|
+
* Development only. `StateBoundary` reaches this module behind a
|
|
8
|
+
* `NODE_ENV === "development"` constant, so production builds drop it; a
|
|
9
|
+
* consumer's bundle gate greps client chunks for FORCE_STATE_MARKER to prove it.
|
|
10
|
+
*/
|
|
11
|
+
declare const FORCED_STATES: readonly ["loading", "empty", "error"];
|
|
12
|
+
type ForcedState = (typeof FORCED_STATES)[number];
|
|
13
|
+
/** `?__state=loading` forces top-level boundaries; `?__state=<id>:error` one boundary. */
|
|
14
|
+
declare const FORCE_STATE_PARAM = "__state";
|
|
15
|
+
/**
|
|
16
|
+
* globalThis key of the store singleton, and the bundle-gate marker. Holding
|
|
17
|
+
* the store on globalThis keeps one instance even if the module is evaluated
|
|
18
|
+
* twice: HMR, or the app's `StateBoundary` chunk and the HUD's States panel
|
|
19
|
+
* chunk each carrying a copy.
|
|
20
|
+
*/
|
|
21
|
+
declare const FORCE_STATE_MARKER = "__HANSENEXUS_HUD_FORCE_STATE__";
|
|
22
|
+
//#endregion
|
|
23
|
+
export { ForcedState as i, FORCE_STATE_MARKER as n, FORCE_STATE_PARAM as r, FORCED_STATES as t };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { a as HudHttpMethod, o as HudPlugin, r as HudCapability } from "./plugins-CQ_0w1ot.js";
|
|
2
|
+
//#region src/server/handler.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Decides whether a request may reach a plugin route. Return a `Response` to
|
|
5
|
+
* refuse it (404, 401, 403 ...) or `null` to let it through. The `access`
|
|
6
|
+
* plugin supplies one for deployed tiers.
|
|
7
|
+
*/
|
|
8
|
+
type HudGuard = (request: Request, capability: HudCapability | undefined) => Response | null | Promise<Response | null>;
|
|
9
|
+
interface HudHandlerOptions {
|
|
10
|
+
/** Path the catch-all route is mounted at. Default `/api/hud`. */
|
|
11
|
+
basePath?: string;
|
|
12
|
+
/** Default: `developmentOnly`, which answers 404 unless `NODE_ENV` is `development`. */
|
|
13
|
+
guard?: HudGuard;
|
|
14
|
+
/** Drops plugins server side, like `defineHud({ can })` does client side. Default: grant all. */
|
|
15
|
+
can?: (capability: HudCapability) => boolean;
|
|
16
|
+
}
|
|
17
|
+
type HudRequestHandler = (request: Request) => Promise<Response>;
|
|
18
|
+
/** One function per method, so a Next route can `export const { GET, POST } = createHudHandler(...)`. */
|
|
19
|
+
type HudHandler = {
|
|
20
|
+
handle: HudRequestHandler;
|
|
21
|
+
} & Record<HudHttpMethod, HudRequestHandler>;
|
|
22
|
+
/**
|
|
23
|
+
* The default guard. Core assumes development, so a deployed build that
|
|
24
|
+
* mounts the route without an `access` guard serves nothing and reveals
|
|
25
|
+
* nothing about which plugins exist.
|
|
26
|
+
*/
|
|
27
|
+
declare const developmentOnly: HudGuard;
|
|
28
|
+
/**
|
|
29
|
+
* Serves every plugin's routes from one catch-all route
|
|
30
|
+
* (`app/api/hud/[...hud]/route.ts` in Next). A request to
|
|
31
|
+
* `<basePath>/<plugin id>/<path>` reaches that plugin's `routes[path][method]`;
|
|
32
|
+
* unknown plugin or path answers 404, a known path with another method 405.
|
|
33
|
+
*
|
|
34
|
+
* Pass the server halves (`@hansenexus/hud/plugins/<id>/server`): they carry
|
|
35
|
+
* `routes` and no React.
|
|
36
|
+
*/
|
|
37
|
+
declare function createHudHandler(plugins: readonly HudPlugin[], options?: HudHandlerOptions): HudHandler;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { createHudHandler as a, HudRequestHandler as i, HudHandler as n, developmentOnly as o, HudHandlerOptions as r, HudGuard as t };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { o as HudPlugin, r as HudCapability } from "./plugins-CQ_0w1ot.js";
|
|
2
|
+
import "./define-hud-BBzsSl8b.js";
|
|
3
|
+
//#region src/core/grabber/picker.d.ts
|
|
4
|
+
interface PickPoint {
|
|
5
|
+
clientX: number;
|
|
6
|
+
clientY: number;
|
|
7
|
+
}
|
|
8
|
+
interface ElementPickerProps {
|
|
9
|
+
active: boolean;
|
|
10
|
+
onPick: (element: Element, point: PickPoint) => void;
|
|
11
|
+
onCancel: () => void;
|
|
12
|
+
/** Banner text while active. */
|
|
13
|
+
hint?: string;
|
|
14
|
+
/** Label next to the hover outline. Default: the tag name. */
|
|
15
|
+
describe?: (element: Element) => string;
|
|
16
|
+
/** Extra elements to leave alone, on top of the picker's own shadow host. */
|
|
17
|
+
ignore?: (element: Element) => boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Styles for the picker overlay. The picker renders where it is mounted, so
|
|
21
|
+
* the caller puts these into the same (shadow) root. Colours fall back when
|
|
22
|
+
* the `--hud-*` tokens are absent.
|
|
23
|
+
*/
|
|
24
|
+
declare const PICKER_CSS = "\n.grab-layer { position: fixed; inset: 0; pointer-events: none; }\n.grab-hint {\n position: fixed;\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n padding: 3px 12px;\n border-radius: 0 0 6px 6px;\n white-space: nowrap;\n background: var(--hud-accent, #0369a1);\n color: var(--hud-accent-fg, #ffffff);\n font: 600 11px/1.5 var(--hud-mono, ui-monospace, monospace);\n}\n.grab-outline {\n position: fixed;\n border: 1.5px solid var(--hud-accent, #0369a1);\n background: color-mix(in srgb, var(--hud-accent, #0369a1) 8%, transparent);\n border-radius: 3px;\n}\n.grab-label {\n position: fixed;\n max-width: min(480px, calc(100vw - 8px));\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 1px 6px;\n border-radius: 3px;\n background: var(--hud-accent, #0369a1);\n color: var(--hud-accent-fg, #ffffff);\n font: 600 10px/1.6 var(--hud-mono, ui-monospace, monospace);\n}\n";
|
|
25
|
+
/**
|
|
26
|
+
* Click-to-pick controller: crosshair, hover outline with a label, the next
|
|
27
|
+
* click picks, Escape cancels. Events inside the picker's own shadow host
|
|
28
|
+
* (the HUD's pill and panels) pass through untouched, so panels stay usable
|
|
29
|
+
* and mounted during a grab.
|
|
30
|
+
*/
|
|
31
|
+
declare function ElementPicker({ active, onPick, onCancel, hint, describe, ignore }: ElementPickerProps): import("react").JSX.Element;
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/shell/hud.d.ts
|
|
34
|
+
interface HudProps {
|
|
35
|
+
/** App slug: labels the pill and keys the persisted layout. */
|
|
36
|
+
appSlug: string;
|
|
37
|
+
/** Badge shown at the start of the pill. Default "DEV". */
|
|
38
|
+
envLabel?: string;
|
|
39
|
+
/** Client halves of the plugins, in pill order. Keep the array stable across renders. */
|
|
40
|
+
plugins?: readonly HudPlugin[];
|
|
41
|
+
/** Base path of the plugin routes. Default "/api/hud". */
|
|
42
|
+
apiBase?: string;
|
|
43
|
+
/** Capability check. Default: grant all (core assumes development). Keep it stable. */
|
|
44
|
+
can?: (capability: HudCapability) => boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The HUD shell: a shadow-rooted status pill and floating panels.
|
|
48
|
+
*
|
|
49
|
+
* It renders unconditionally. Keeping it out of production builds is the
|
|
50
|
+
* loader's job, at the import site, so a bundler can drop the whole module
|
|
51
|
+
* (see `@hansenexus/hud/next`).
|
|
52
|
+
*/
|
|
53
|
+
declare function Hud({ appSlug, envLabel, plugins, apiBase, can }: HudProps): import("react").JSX.Element;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { PICKER_CSS as a, ElementPickerProps as i, HudProps as n, PickPoint as o, ElementPicker as r, Hud as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* incidental string a refactor could rename away.
|
|
8
|
-
*/
|
|
9
|
-
export declare const HUD_DEV_MARKER = "__HANSENEXUS_HUD_DEV__";
|
|
10
|
-
/** Tag name of the element that hosts the HUD's shadow root. */
|
|
11
|
-
export declare const HUD_HOST_TAG = "hn-hud";
|
|
12
|
-
//#endregion
|
|
13
|
-
//#region src/shell/hud.d.ts
|
|
14
|
-
interface HudProps {
|
|
15
|
-
/** App slug, used for labels now and for the layout storage key later. */
|
|
16
|
-
appSlug: string;
|
|
17
|
-
/** Badge shown at the start of the pill. Default "DEV". */
|
|
18
|
-
envLabel?: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* The HUD shell: a shadow-rooted status pill and floating panels.
|
|
22
|
-
*
|
|
23
|
-
* It renders unconditionally. Keeping it out of production builds is the
|
|
24
|
-
* loader's job, at the import site, so a bundler can drop the whole module
|
|
25
|
-
* (see the Next adapter, hud#4).
|
|
26
|
-
*/
|
|
27
|
-
export declare function Hud({ appSlug, envLabel }: HudProps): import("react").JSX.Element;
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/vitals/store.d.ts
|
|
30
|
-
type VitalName = Metric["name"];
|
|
31
|
-
type VitalRating = Metric["rating"];
|
|
32
|
-
interface Vital {
|
|
33
|
-
name: VitalName;
|
|
34
|
-
value: number;
|
|
35
|
-
rating: VitalRating;
|
|
36
|
-
}
|
|
37
|
-
type VitalsSnapshot = Partial<Record<VitalName, Vital>>;
|
|
38
|
-
//#endregion
|
|
39
|
-
export type { HudProps, Vital, VitalName, VitalRating, VitalsSnapshot };
|
|
1
|
+
import { a as GrabComponent, i as matchComponentHints, n as GrabAnchor, r as GrabPayload, t as ComponentHint } from "./payload-CLKDVZWl.js";
|
|
2
|
+
import { c as HudPluginProps, f as PinEdge, g as useGrab, h as HudGrabState, i as HudCommand, m as HudGrab, n as HudApiError, o as HudPlugin, p as definePlugin, r as HudCapability, s as HudPluginContext, t as HudAccessControl } from "./plugins-CQ_0w1ot.js";
|
|
3
|
+
import { n as HudMountProps, r as defineHud, t as DefineHudOptions } from "./define-hud-BBzsSl8b.js";
|
|
4
|
+
import { a as PICKER_CSS, i as ElementPickerProps, n as HudProps, o as PickPoint, r as ElementPicker, t as Hud } from "./index-BYsdS-7d.js";
|
|
5
|
+
import { n as HUD_HOST_TAG, t as HUD_DEV_MARKER } from "./marker-CMrvxPmS.js";
|
|
6
|
+
export { type ComponentHint, type DefineHudOptions, ElementPicker, type ElementPickerProps, type GrabAnchor, type GrabComponent, type GrabPayload, HUD_DEV_MARKER, HUD_HOST_TAG, Hud, type HudAccessControl, HudApiError, type HudCapability, type HudCommand, type HudGrab, type HudGrabState, type HudMountProps, type HudPlugin, type HudPluginContext, type HudPluginProps, type HudProps, PICKER_CSS, type PickPoint, type PinEdge, defineHud, definePlugin, matchComponentHints, useGrab };
|