@immediately-run/omnibox 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/README.md +26 -0
- package/dist/Omnibox.cjs +280 -0
- package/dist/Omnibox.cjs.map +1 -0
- package/dist/Omnibox.d.cts +44 -0
- package/dist/Omnibox.d.ts +44 -0
- package/dist/Omnibox.js +260 -0
- package/dist/Omnibox.js.map +1 -0
- package/dist/index.cjs +53 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/launch.cjs +113 -0
- package/dist/launch.cjs.map +1 -0
- package/dist/launch.d.cts +27 -0
- package/dist/launch.d.ts +27 -0
- package/dist/launch.js +88 -0
- package/dist/launch.js.map +1 -0
- package/dist/omnibox.css +274 -0
- package/dist/omniboxFocus.cjs +61 -0
- package/dist/omniboxFocus.cjs.map +1 -0
- package/dist/omniboxFocus.d.cts +19 -0
- package/dist/omniboxFocus.d.ts +19 -0
- package/dist/omniboxFocus.js +34 -0
- package/dist/omniboxFocus.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @immediately-run/omnibox
|
|
2
|
+
|
|
3
|
+
The front door's omnibox (R3-512; FRONT_DOOR_IA §5): one WAI-ARIA
|
|
4
|
+
list-autocomplete combobox that runs a repository by URL or
|
|
5
|
+
`provider:namespace/repository@ref` tuple and searches a consumer's app
|
|
6
|
+
directory and docs. Shared by landing-page and the Home app so there is one
|
|
7
|
+
component and one grammar (R3-530) — the brief's rejection of a second paste
|
|
8
|
+
box.
|
|
9
|
+
|
|
10
|
+
## What it owns, and what it does not
|
|
11
|
+
|
|
12
|
+
- **Owned:** `Omnibox` (the component), `parseLaunch` + the `Launch` grammar
|
|
13
|
+
(pure, no React, no SDK, no network), the cross-instance focus registry, and
|
|
14
|
+
the stylesheet (`./omnibox.css`, `.kbd` included).
|
|
15
|
+
- **Injected:** the data. `hits.apps` and `hits.docs` are the consumer's
|
|
16
|
+
sources; the package ranks and orders the app candidates (name > repo >
|
|
17
|
+
blurb > category) but imports no consumer records. An app-row chip comes
|
|
18
|
+
back through `renderChip` — chips are site components with site data types.
|
|
19
|
+
An `<Omnibox>` with no `hits` is the launch grammar only — the Home app's
|
|
20
|
+
shape.
|
|
21
|
+
|
|
22
|
+
## Peer dependencies
|
|
23
|
+
|
|
24
|
+
`react` and `@immediately-run/sdk` (the `PlatformLink` subpath, which builds
|
|
25
|
+
host-space hrefs and escapes the sandboxed frame). Both are peer deps, never
|
|
26
|
+
bundled.
|
package/dist/Omnibox.cjs
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var Omnibox_exports = {};
|
|
20
|
+
__export(Omnibox_exports, {
|
|
21
|
+
default: () => Omnibox_default
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(Omnibox_exports);
|
|
24
|
+
var import_jsx_runtime = (
|
|
25
|
+
// One provider: a static label with no caret — NOT a dropdown of
|
|
26
|
+
// providers that do not exist.
|
|
27
|
+
require("react/jsx-runtime")
|
|
28
|
+
);
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
var import_omnibox = require("./omnibox.css");
|
|
31
|
+
var import_launch = require("./launch");
|
|
32
|
+
var import_platformLink = require("@immediately-run/sdk/platformLink");
|
|
33
|
+
var import_omniboxFocus = require("./omniboxFocus");
|
|
34
|
+
function useMediaQuery(query) {
|
|
35
|
+
const [matches, setMatches] = (0, import_react.useState)(
|
|
36
|
+
() => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
|
|
37
|
+
);
|
|
38
|
+
(0, import_react.useEffect)(() => {
|
|
39
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
40
|
+
const mq = window.matchMedia(query);
|
|
41
|
+
const onChange = () => setMatches(mq.matches);
|
|
42
|
+
onChange();
|
|
43
|
+
mq.addEventListener("change", onChange);
|
|
44
|
+
return () => mq.removeEventListener("change", onChange);
|
|
45
|
+
}, [query]);
|
|
46
|
+
return matches;
|
|
47
|
+
}
|
|
48
|
+
function appScore(hit, q) {
|
|
49
|
+
if (hit.name.toLowerCase().startsWith(q)) return 4;
|
|
50
|
+
if (hit.name.toLowerCase().includes(q)) return 3;
|
|
51
|
+
if (hit.repo.toLowerCase().includes(q)) return 2;
|
|
52
|
+
if (hit.blurb.toLowerCase().includes(q)) return 1;
|
|
53
|
+
if (hit.category.toLowerCase().includes(q)) return 0;
|
|
54
|
+
return -1;
|
|
55
|
+
}
|
|
56
|
+
const appRoute = (repo) => `/present/github/immediately-run/${repo}/main/files/src/App.tsx`;
|
|
57
|
+
function Omnibox({ variant, heroShortcut = false, hits, renderChip }) {
|
|
58
|
+
const isMobile = useMediaQuery("(max-width: 720px)");
|
|
59
|
+
const [query, setQuery] = (0, import_react.useState)("");
|
|
60
|
+
const [highlight, setHighlight] = (0, import_react.useState)(-1);
|
|
61
|
+
const inputRef = (0, import_react.useRef)(null);
|
|
62
|
+
const outerRef = (0, import_react.useRef)(null);
|
|
63
|
+
const listId = (0, import_react.useId)();
|
|
64
|
+
const inputId = `${listId}-input`;
|
|
65
|
+
const helperId = (0, import_react.useId)();
|
|
66
|
+
const noticeId = (0, import_react.useId)();
|
|
67
|
+
const warnedSources = (0, import_react.useRef)(/* @__PURE__ */ new Set());
|
|
68
|
+
const callSource = (0, import_react.useCallback)(
|
|
69
|
+
function callSource2(kind, source, q) {
|
|
70
|
+
try {
|
|
71
|
+
return source(q);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (!warnedSources.current.has(kind)) {
|
|
74
|
+
warnedSources.current.add(kind);
|
|
75
|
+
console.warn(`omnibox: the "${String(kind)}" hit source threw and is disabled for this mount`, error);
|
|
76
|
+
}
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
[]
|
|
81
|
+
);
|
|
82
|
+
const parsed = (0, import_react.useMemo)(() => (0, import_launch.parseLaunch)(query), [query]);
|
|
83
|
+
const runnable = parsed.kind === "location" || parsed.kind === "platform-url";
|
|
84
|
+
const runPath = parsed.kind === "location" ? parsed.presentPath : parsed.kind === "platform-url" ? parsed.path : void 0;
|
|
85
|
+
const panelOpen = query.trim() !== "";
|
|
86
|
+
const [prevQuery, setPrevQuery] = (0, import_react.useState)(query);
|
|
87
|
+
if (prevQuery !== query) {
|
|
88
|
+
setPrevQuery(query);
|
|
89
|
+
setHighlight(-1);
|
|
90
|
+
}
|
|
91
|
+
const notice = parsed.kind === "unknown-provider" ? `${parsed.provider.charAt(0).toUpperCase()}${parsed.provider.slice(1)} is not supported yet. GitHub works today.` : "";
|
|
92
|
+
const helper = variant === "new" ? "the repo you just created" : "Accepts provider:namespace/repository@ref \xB7 GitHub is the first provider";
|
|
93
|
+
const appHits = (0, import_react.useMemo)(() => {
|
|
94
|
+
if (!panelOpen || !hits?.apps) return [];
|
|
95
|
+
const q = query.trim().toLowerCase();
|
|
96
|
+
return callSource("apps", hits.apps, q).map((hit) => ({ hit, score: appScore(hit, q) })).filter(({ score }) => score >= 0).sort((a, b) => b.score - a.score).map(({ hit }) => hit);
|
|
97
|
+
}, [panelOpen, query, hits, callSource]);
|
|
98
|
+
const docHits = (0, import_react.useMemo)(() => {
|
|
99
|
+
if (!panelOpen || !hits?.docs) return [];
|
|
100
|
+
return callSource("docs", hits.docs, query.trim().toLowerCase());
|
|
101
|
+
}, [panelOpen, query, hits, callSource]);
|
|
102
|
+
const locationRow = parsed.kind === "location" ? parsed : void 0;
|
|
103
|
+
const hasResults = Boolean(locationRow) || appHits.length > 0 || docHits.length > 0;
|
|
104
|
+
const options = (0, import_react.useMemo)(() => {
|
|
105
|
+
const list = [];
|
|
106
|
+
if (locationRow) list.push({ id: `${listId}-opt-location`, label: locationRow.display });
|
|
107
|
+
for (const hit of appHits) list.push({ id: `${listId}-opt-${hit.key}`, label: hit.name });
|
|
108
|
+
for (const hit of docHits) list.push({ id: `${listId}-opt-doc-${hit.key}`, label: hit.title });
|
|
109
|
+
return list;
|
|
110
|
+
}, [locationRow, appHits, docHits, listId]);
|
|
111
|
+
(0, import_react.useEffect)(
|
|
112
|
+
() => (0, import_omniboxFocus.registerOmniboxFocus)(variant, {
|
|
113
|
+
focus: () => inputRef.current?.focus(),
|
|
114
|
+
reveal: () => outerRef.current?.scrollIntoView({ behavior: "smooth", block: "center" })
|
|
115
|
+
}),
|
|
116
|
+
[variant]
|
|
117
|
+
);
|
|
118
|
+
const onKeyDown = (0, import_react.useCallback)(
|
|
119
|
+
(e) => {
|
|
120
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
121
|
+
if (!panelOpen || options.length === 0) return;
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
setHighlight((h) => {
|
|
124
|
+
if (h === -1) return e.key === "ArrowDown" ? 0 : options.length - 1;
|
|
125
|
+
return (h + (e.key === "ArrowDown" ? 1 : -1) + options.length) % options.length;
|
|
126
|
+
});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (e.key === "Enter") {
|
|
130
|
+
if (highlight >= 0 && highlight < options.length) {
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
document.getElementById(options[highlight].id)?.click();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (runnable) {
|
|
136
|
+
e.preventDefault();
|
|
137
|
+
document.getElementById(`${listId}-run`)?.click();
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (e.key === "Escape") {
|
|
142
|
+
setQuery("");
|
|
143
|
+
setHighlight(-1);
|
|
144
|
+
inputRef.current?.blur();
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
[panelOpen, options, highlight, runnable, listId]
|
|
148
|
+
);
|
|
149
|
+
const chip = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-chip", "aria-hidden": Object.keys(import_launch.PROVIDERS).length === 1 || void 0, children: Object.keys(import_launch.PROVIDERS).length === 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-chip-label", children: "github" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { className: "omnibox-chip-select", "aria-label": "Provider", children: Object.keys(import_launch.PROVIDERS).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p, children: p }, p)) }) });
|
|
150
|
+
const run = runPath !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
151
|
+
import_platformLink.PlatformLink,
|
|
152
|
+
{
|
|
153
|
+
id: `${listId}-run`,
|
|
154
|
+
className: "omnibox-run",
|
|
155
|
+
path: runPath,
|
|
156
|
+
"aria-label": "Run",
|
|
157
|
+
children: [
|
|
158
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-run-label", children: "Run" }),
|
|
159
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-run-arrow", "aria-hidden": "true", children: "\u2192" })
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
163
|
+
"button",
|
|
164
|
+
{
|
|
165
|
+
id: `${listId}-run`,
|
|
166
|
+
type: "button",
|
|
167
|
+
className: "omnibox-run",
|
|
168
|
+
"aria-disabled": "true",
|
|
169
|
+
"aria-describedby": `${helperId} ${noticeId}`,
|
|
170
|
+
onClick: (e) => e.preventDefault(),
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-run-label", children: "Run" }),
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-run-arrow", "aria-hidden": "true", children: "\u2192" })
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
const field = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `omnibox omnibox--${variant}`, children: [
|
|
178
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "omnibox-row", children: [
|
|
179
|
+
chip,
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
181
|
+
"input",
|
|
182
|
+
{
|
|
183
|
+
ref: inputRef,
|
|
184
|
+
id: inputId,
|
|
185
|
+
className: "omnibox-input",
|
|
186
|
+
type: "text",
|
|
187
|
+
role: "combobox",
|
|
188
|
+
"aria-autocomplete": "list",
|
|
189
|
+
"aria-expanded": panelOpen,
|
|
190
|
+
"aria-controls": panelOpen ? listId : void 0,
|
|
191
|
+
"aria-activedescendant": highlight >= 0 ? options[highlight]?.id : void 0,
|
|
192
|
+
"aria-describedby": `${helperId} ${noticeId}`,
|
|
193
|
+
"aria-invalid": notice ? true : void 0,
|
|
194
|
+
placeholder: isMobile ? "Paste a repo or an app name" : "owner/repo@branch, a GitHub URL, or an app name",
|
|
195
|
+
value: query,
|
|
196
|
+
onChange: (e) => setQuery(e.target.value),
|
|
197
|
+
onKeyDown
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
run
|
|
201
|
+
] }),
|
|
202
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "omnibox-helper", id: helperId, children: notice || helper }),
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "omnibox-visually-hidden", id: noticeId, "aria-live": "polite", children: notice }),
|
|
204
|
+
panelOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "omnibox-panel", id: listId, role: "listbox", "aria-label": "Results", children: hasResults ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
205
|
+
locationRow && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "omnibox-group", role: "group", "aria-label": "Run from source", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
206
|
+
import_platformLink.PlatformLink,
|
|
207
|
+
{
|
|
208
|
+
id: `${listId}-opt-location`,
|
|
209
|
+
className: "omnibox-option",
|
|
210
|
+
role: "option",
|
|
211
|
+
"aria-selected": highlight === 0,
|
|
212
|
+
path: locationRow.presentPath,
|
|
213
|
+
children: [
|
|
214
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-name", children: locationRow.display }),
|
|
215
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-action", children: "Run" })
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
) }),
|
|
219
|
+
appHits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "omnibox-group", role: "group", "aria-label": "Apps in the directory", children: appHits.map((hit) => {
|
|
220
|
+
const idx = options.findIndex((o) => o.id === `${listId}-opt-${hit.key}`);
|
|
221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
222
|
+
import_platformLink.PlatformLink,
|
|
223
|
+
{
|
|
224
|
+
id: `${listId}-opt-${hit.key}`,
|
|
225
|
+
className: "omnibox-option",
|
|
226
|
+
role: "option",
|
|
227
|
+
"aria-selected": highlight === idx,
|
|
228
|
+
path: appRoute(hit.repo),
|
|
229
|
+
children: [
|
|
230
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-name", children: hit.name }),
|
|
231
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-cat", children: hit.category }),
|
|
232
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-blurb", children: hit.blurb }),
|
|
233
|
+
renderChip?.(hit)
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
hit.key
|
|
237
|
+
);
|
|
238
|
+
}) }),
|
|
239
|
+
docHits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "omnibox-group", role: "group", "aria-label": "Docs and tutorials", children: docHits.map((hit) => {
|
|
240
|
+
const idx = options.findIndex((o) => o.id === `${listId}-opt-doc-${hit.key}`);
|
|
241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
242
|
+
"a",
|
|
243
|
+
{
|
|
244
|
+
id: `${listId}-opt-doc-${hit.key}`,
|
|
245
|
+
className: "omnibox-option",
|
|
246
|
+
role: "option",
|
|
247
|
+
"aria-selected": highlight === idx,
|
|
248
|
+
href: hit.href,
|
|
249
|
+
children: [
|
|
250
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-name", children: hit.title }),
|
|
251
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-option-blurb", children: hit.lead })
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
hit.key
|
|
255
|
+
);
|
|
256
|
+
}) })
|
|
257
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "omnibox-empty", children: "Nothing matched. Try an app name, or paste a repo." }) })
|
|
258
|
+
] });
|
|
259
|
+
if (variant === "nav" && heroShortcut) {
|
|
260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
261
|
+
"button",
|
|
262
|
+
{
|
|
263
|
+
type: "button",
|
|
264
|
+
className: "omnibox-nav-button",
|
|
265
|
+
onClick: () => (0, import_omniboxFocus.focusHeroOmnibox)(),
|
|
266
|
+
"aria-label": "Search apps and docs, or paste a repo",
|
|
267
|
+
children: [
|
|
268
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "omnibox-nav-button-label", children: "Search" }),
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "kbd", children: "\u2318K" })
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `omnibox-outer omnibox-outer--${variant}`, ref: outerRef, children: [
|
|
275
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "omnibox-visually-hidden", htmlFor: inputId, children: "Paste a repo, or search apps and docs" }),
|
|
276
|
+
field
|
|
277
|
+
] });
|
|
278
|
+
}
|
|
279
|
+
var Omnibox_default = Omnibox;
|
|
280
|
+
//# sourceMappingURL=Omnibox.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Omnibox.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent, ReactNode } from 'react';\nimport './omnibox.css';\nimport { parseLaunch, PROVIDERS, type Launch } from './launch';\nimport { PlatformLink } from '@immediately-run/sdk/platformLink';\nimport { focusHeroOmnibox, registerOmniboxFocus } from './omniboxFocus';\nimport type { OmniboxVariant } from './omniboxFocus';\n\n// The omnibox (R3-512; FRONT_DOOR_IA §5) — the front door's primary control. It\n// does W1 (run a repo by URL or tuple) and W2 (find an app) in one place, as a\n// WAI-ARIA list-autocomplete combobox with three result groups of ONE action per\n// row. Run and Open rows render through `PlatformLink`, which resolves the\n// host-space href and escapes the frame: a platform route navigates the HOST\n// document, and a root-relative href inside the sandboxed frame would resolve\n// against the sandbox origin and land nowhere.\n//\n// The package owns the component and the launch grammar; it owns NO data. The\n// app-directory and docs hit sources are injected per app (`hits`), because the\n// package cannot depend on a consumer's records (R3-530).\n\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() =>\n typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n ? window.matchMedia(query).matches\n : false,\n );\n useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return;\n const mq = window.matchMedia(query);\n const onChange = () => setMatches(mq.matches);\n onChange();\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n }, [query]);\n return matches;\n}\n\n/* ── the hit vocabulary a consumer's sources speak ──────────────────────── */\n\nexport interface AppHit {\n key: string;\n name: string;\n category: string;\n blurb: string;\n /** The repository the row opens — an org repo under immediately-run. */\n repo: string;\n /** Opaque to the package: a consumer's `renderChip` reads it back. */\n provenance?: unknown;\n}\n\nexport interface DocHit {\n key: string;\n title: string;\n lead: string;\n /** A real href — copy-link, middle-click and open-in-new-tab all resolve it. */\n href: string;\n}\n\n/** The data seams. Absent sources simply yield no rows of their kind; an omnibox\n * with no `hits` at all is the launch grammar only (what the Home app renders). */\nexport interface OmniboxHitSources {\n /** Candidate app hits for a query; the package ranks, filters and orders them. */\n apps?: (query: string) => AppHit[];\n /** Matched doc hits for a query, best-first, capped by the source. */\n docs?: (query: string) => DocHit[];\n}\n\n/* ── ranking ────────────────────────────────────────────────────────────── */\n\n/** name-prefix > name-substring > repo > blurb > category (FRONT_DOOR_IA §5.3).\n * Internal: the ranking is the package's policy, not part of the surface. */\nfunction appScore(hit: AppHit, q: string): number {\n if (hit.name.toLowerCase().startsWith(q)) return 4;\n if (hit.name.toLowerCase().includes(q)) return 3;\n if (hit.repo.toLowerCase().includes(q)) return 2;\n if (hit.blurb.toLowerCase().includes(q)) return 1;\n if (hit.category.toLowerCase().includes(q)) return 0;\n return -1;\n}\n\n/** The platform path an app row opens. The directory's apps are org repos that\n * open at their entry — the one shape an injected `apps` source feeds. */\nconst appRoute = (repo: string) => `/present/github/immediately-run/${repo}/main/files/src/App.tsx`;\n\n/* ── the component ──────────────────────────────────────────────────────── */\n\nexport interface OmniboxProps {\n variant: OmniboxVariant;\n /** Nav variant only: true while the hero omnibox is mounted (`/`), so the\n * nav field renders as the shortcut that focuses it. Derived by the caller\n * from the route — render-time data, not an effect. */\n heroShortcut?: boolean;\n /** App-directory and docs hit sources. Absent → the launch grammar only. */\n hits?: OmniboxHitSources;\n /** Renders the app row's trailing chip (e.g. a provenance chip). The chip is a\n * site component with site data types, so the package renders what it is given. */\n renderChip?: (hit: AppHit) => ReactNode;\n}\n\nfunction Omnibox({ variant, heroShortcut = false, hits, renderChip }: OmniboxProps) {\n const isMobile = useMediaQuery('(max-width: 720px)');\n const [query, setQuery] = useState('');\n const [highlight, setHighlight] = useState(-1);\n const inputRef = useRef<HTMLInputElement>(null);\n const outerRef = useRef<HTMLDivElement>(null);\n const listId = useId();\n const inputId = `${listId}-input`;\n const helperId = useId();\n const noticeId = useId();\n // A source that throws is degraded, not fatal: logged ONCE per source, then\n // that group stays empty — the location row still renders.\n const warnedSources = useRef<Set<keyof OmniboxHitSources>>(new Set());\n const callSource = useCallback(\n function callSource<K extends keyof OmniboxHitSources>(\n kind: K,\n source: OmniboxHitSources[K],\n q: string,\n ): ReturnType<NonNullable<OmniboxHitSources[K]>> | [] {\n try {\n return source!(q) as ReturnType<NonNullable<OmniboxHitSources[K]>>;\n } catch (error) {\n if (!warnedSources.current.has(kind)) {\n warnedSources.current.add(kind);\n console.warn(`omnibox: the \"${String(kind)}\" hit source threw and is disabled for this mount`, error);\n }\n return [];\n }\n },\n [],\n );\n\n const parsed: Launch = useMemo(() => parseLaunch(query), [query]);\n const runnable = parsed.kind === 'location' || parsed.kind === 'platform-url';\n const runPath =\n parsed.kind === 'location'\n ? parsed.presentPath\n : parsed.kind === 'platform-url'\n ? parsed.path\n : undefined;\n\n const panelOpen = query.trim() !== '';\n\n // Adjusting state during render (the sanctioned pattern): the highlight must\n // not survive the option set changing under it, and an effect would cascade.\n const [prevQuery, setPrevQuery] = useState(query);\n if (prevQuery !== query) {\n setPrevQuery(query);\n setHighlight(-1);\n }\n\n // Unknown provider → the notice replaces the helper line's text and is\n // announced through the live region.\n const notice =\n parsed.kind === 'unknown-provider'\n ? `${parsed.provider.charAt(0).toUpperCase()}${parsed.provider.slice(1)} is not supported yet. GitHub works today.`\n : '';\n\n const helper =\n variant === 'new' ? 'the repo you just created' : 'Accepts provider:namespace/repository@ref · GitHub is the first provider';\n\n const appHits = useMemo(() => {\n if (!panelOpen || !hits?.apps) return [];\n const q = query.trim().toLowerCase();\n return callSource('apps', hits.apps, q)\n .map((hit) => ({ hit, score: appScore(hit, q) }))\n .filter(({ score }) => score >= 0)\n .sort((a, b) => b.score - a.score)\n .map(({ hit }) => hit);\n }, [panelOpen, query, hits, callSource]);\n\n const docHits = useMemo(() => {\n if (!panelOpen || !hits?.docs) return [];\n return callSource('docs', hits.docs, query.trim().toLowerCase());\n }, [panelOpen, query, hits, callSource]);\n\n const locationRow = parsed.kind === 'location' ? parsed : undefined;\n const hasResults = Boolean(locationRow) || appHits.length > 0 || docHits.length > 0;\n\n // Flattened options, in group order — the arrow-key walk and the highlight id\n // both read this list.\n const options = useMemo(() => {\n const list: { id: string; label: string }[] = [];\n if (locationRow) list.push({ id: `${listId}-opt-location`, label: locationRow.display });\n for (const hit of appHits) list.push({ id: `${listId}-opt-${hit.key}`, label: hit.name });\n for (const hit of docHits) list.push({ id: `${listId}-opt-doc-${hit.key}`, label: hit.title });\n return list;\n }, [locationRow, appHits, docHits, listId]);\n\n // Register with the focus registry (⌘K, the nav shortcut and the \"paste a repo\"\n // CTAs all land here). `reveal` is what lets those CTAs scroll this field into\n // view without any component querying for its CSS class.\n useEffect(\n () =>\n registerOmniboxFocus(variant, {\n focus: () => inputRef.current?.focus(),\n reveal: () => outerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' }),\n }),\n [variant],\n );\n\n const onKeyDown = useCallback(\n (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n if (!panelOpen || options.length === 0) return;\n e.preventDefault();\n setHighlight((h) => {\n if (h === -1) return e.key === 'ArrowDown' ? 0 : options.length - 1;\n return (h + (e.key === 'ArrowDown' ? 1 : -1) + options.length) % options.length;\n });\n return;\n }\n if (e.key === 'Enter') {\n if (highlight >= 0 && highlight < options.length) {\n e.preventDefault();\n document.getElementById(options[highlight].id)?.click();\n return;\n }\n if (runnable) {\n e.preventDefault();\n document.getElementById(`${listId}-run`)?.click();\n }\n return;\n }\n if (e.key === 'Escape') {\n // Close the panel, then clear the highlight, then blur — in that order.\n setQuery('');\n setHighlight(-1);\n inputRef.current?.blur();\n }\n },\n [panelOpen, options, highlight, runnable, listId],\n );\n\n const chip = (\n <span className=\"omnibox-chip\" aria-hidden={Object.keys(PROVIDERS).length === 1 || undefined}>\n {Object.keys(PROVIDERS).length === 1 ? (\n // One provider: a static label with no caret — NOT a dropdown of\n // providers that do not exist.\n <span className=\"omnibox-chip-label\">github</span>\n ) : (\n <select className=\"omnibox-chip-select\" aria-label=\"Provider\">\n {Object.keys(PROVIDERS).map((p) => (\n <option key={p} value={p}>\n {p}\n </option>\n ))}\n </select>\n )}\n </span>\n );\n\n const run = runPath !== undefined ? (\n <PlatformLink\n id={`${listId}-run`}\n className=\"omnibox-run\"\n path={runPath}\n aria-label=\"Run\"\n >\n <span className=\"omnibox-run-label\">Run</span>\n <span className=\"omnibox-run-arrow\" aria-hidden=\"true\">\n →\n </span>\n </PlatformLink>\n ) : (\n <button\n id={`${listId}-run`}\n type=\"button\"\n className=\"omnibox-run\"\n aria-disabled=\"true\"\n aria-describedby={`${helperId} ${noticeId}`}\n onClick={(e) => e.preventDefault()}\n >\n <span className=\"omnibox-run-label\">Run</span>\n <span className=\"omnibox-run-arrow\" aria-hidden=\"true\">\n →\n </span>\n </button>\n );\n\n const field = (\n <div className={`omnibox omnibox--${variant}`}>\n <div className=\"omnibox-row\">\n {chip}\n <input\n ref={inputRef}\n id={inputId}\n className=\"omnibox-input\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={panelOpen}\n aria-controls={panelOpen ? listId : undefined}\n aria-activedescendant={highlight >= 0 ? options[highlight]?.id : undefined}\n aria-describedby={`${helperId} ${noticeId}`}\n aria-invalid={notice ? true : undefined}\n placeholder={isMobile ? 'Paste a repo or an app name' : 'owner/repo@branch, a GitHub URL, or an app name'}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={onKeyDown}\n />\n {run}\n </div>\n <p className=\"omnibox-helper\" id={helperId}>\n {notice || helper}\n </p>\n {/* The live region announces the notice; empty in the common case. */}\n <p className=\"omnibox-visually-hidden\" id={noticeId} aria-live=\"polite\">\n {notice}\n </p>\n {panelOpen && (\n <div className=\"omnibox-panel\" id={listId} role=\"listbox\" aria-label=\"Results\">\n {hasResults ? (\n <>\n {locationRow && (\n <div className=\"omnibox-group\" role=\"group\" aria-label=\"Run from source\">\n <PlatformLink\n id={`${listId}-opt-location`}\n className=\"omnibox-option\"\n role=\"option\"\n aria-selected={highlight === 0}\n path={locationRow.presentPath}\n >\n <span className=\"omnibox-option-name\">{locationRow.display}</span>\n <span className=\"omnibox-option-action\">Run</span>\n </PlatformLink>\n </div>\n )}\n {appHits.length > 0 && (\n <div className=\"omnibox-group\" role=\"group\" aria-label=\"Apps in the directory\">\n {appHits.map((hit) => {\n const idx = options.findIndex((o) => o.id === `${listId}-opt-${hit.key}`);\n return (\n <PlatformLink\n key={hit.key}\n id={`${listId}-opt-${hit.key}`}\n className=\"omnibox-option\"\n role=\"option\"\n aria-selected={highlight === idx}\n path={appRoute(hit.repo)}\n >\n <span className=\"omnibox-option-name\">{hit.name}</span>\n <span className=\"omnibox-option-cat\">{hit.category}</span>\n <span className=\"omnibox-option-blurb\">{hit.blurb}</span>\n {renderChip?.(hit)}\n </PlatformLink>\n );\n })}\n </div>\n )}\n {docHits.length > 0 && (\n <div className=\"omnibox-group\" role=\"group\" aria-label=\"Docs and tutorials\">\n {docHits.map((hit) => {\n const idx = options.findIndex((o) => o.id === `${listId}-opt-doc-${hit.key}`);\n return (\n <a\n key={hit.key}\n id={`${listId}-opt-doc-${hit.key}`}\n className=\"omnibox-option\"\n role=\"option\"\n aria-selected={highlight === idx}\n href={hit.href}\n >\n <span className=\"omnibox-option-name\">{hit.title}</span>\n <span className=\"omnibox-option-blurb\">{hit.lead}</span>\n </a>\n );\n })}\n </div>\n )}\n </>\n ) : (\n <div className=\"omnibox-empty\">Nothing matched. Try an app name, or paste a repo.</div>\n )}\n </div>\n )}\n </div>\n );\n\n // The nav variant collapses to a shortcut button while the hero omnibox is\n // mounted (on `/`): activating it focuses the hero field. On every other\n // route the field expands in place.\n if (variant === 'nav' && heroShortcut) {\n return (\n <button\n type=\"button\"\n className=\"omnibox-nav-button\"\n onClick={() => focusHeroOmnibox()}\n aria-label=\"Search apps and docs, or paste a repo\"\n >\n <span className=\"omnibox-nav-button-label\">Search</span>\n <span className=\"kbd\">⌘K</span>\n </button>\n );\n }\n\n return (\n <div className={`omnibox-outer omnibox-outer--${variant}`} ref={outerRef}>\n <label className=\"omnibox-visually-hidden\" htmlFor={inputId}>\n Paste a repo, or search apps and docs\n </label>\n {field}\n </div>\n );\n}\n\nexport default Omnibox;\n"],"mappings":"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","names":["callSource"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { OmniboxVariant } from './omniboxFocus.cjs';
|
|
4
|
+
|
|
5
|
+
interface AppHit {
|
|
6
|
+
key: string;
|
|
7
|
+
name: string;
|
|
8
|
+
category: string;
|
|
9
|
+
blurb: string;
|
|
10
|
+
/** The repository the row opens — an org repo under immediately-run. */
|
|
11
|
+
repo: string;
|
|
12
|
+
/** Opaque to the package: a consumer's `renderChip` reads it back. */
|
|
13
|
+
provenance?: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface DocHit {
|
|
16
|
+
key: string;
|
|
17
|
+
title: string;
|
|
18
|
+
lead: string;
|
|
19
|
+
/** A real href — copy-link, middle-click and open-in-new-tab all resolve it. */
|
|
20
|
+
href: string;
|
|
21
|
+
}
|
|
22
|
+
/** The data seams. Absent sources simply yield no rows of their kind; an omnibox
|
|
23
|
+
* with no `hits` at all is the launch grammar only (what the Home app renders). */
|
|
24
|
+
interface OmniboxHitSources {
|
|
25
|
+
/** Candidate app hits for a query; the package ranks, filters and orders them. */
|
|
26
|
+
apps?: (query: string) => AppHit[];
|
|
27
|
+
/** Matched doc hits for a query, best-first, capped by the source. */
|
|
28
|
+
docs?: (query: string) => DocHit[];
|
|
29
|
+
}
|
|
30
|
+
interface OmniboxProps {
|
|
31
|
+
variant: OmniboxVariant;
|
|
32
|
+
/** Nav variant only: true while the hero omnibox is mounted (`/`), so the
|
|
33
|
+
* nav field renders as the shortcut that focuses it. Derived by the caller
|
|
34
|
+
* from the route — render-time data, not an effect. */
|
|
35
|
+
heroShortcut?: boolean;
|
|
36
|
+
/** App-directory and docs hit sources. Absent → the launch grammar only. */
|
|
37
|
+
hits?: OmniboxHitSources;
|
|
38
|
+
/** Renders the app row's trailing chip (e.g. a provenance chip). The chip is a
|
|
39
|
+
* site component with site data types, so the package renders what it is given. */
|
|
40
|
+
renderChip?: (hit: AppHit) => ReactNode;
|
|
41
|
+
}
|
|
42
|
+
declare function Omnibox({ variant, heroShortcut, hits, renderChip }: OmniboxProps): react.JSX.Element;
|
|
43
|
+
|
|
44
|
+
export { type AppHit, type DocHit, type OmniboxHitSources, type OmniboxProps, Omnibox as default };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { OmniboxVariant } from './omniboxFocus.js';
|
|
4
|
+
|
|
5
|
+
interface AppHit {
|
|
6
|
+
key: string;
|
|
7
|
+
name: string;
|
|
8
|
+
category: string;
|
|
9
|
+
blurb: string;
|
|
10
|
+
/** The repository the row opens — an org repo under immediately-run. */
|
|
11
|
+
repo: string;
|
|
12
|
+
/** Opaque to the package: a consumer's `renderChip` reads it back. */
|
|
13
|
+
provenance?: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface DocHit {
|
|
16
|
+
key: string;
|
|
17
|
+
title: string;
|
|
18
|
+
lead: string;
|
|
19
|
+
/** A real href — copy-link, middle-click and open-in-new-tab all resolve it. */
|
|
20
|
+
href: string;
|
|
21
|
+
}
|
|
22
|
+
/** The data seams. Absent sources simply yield no rows of their kind; an omnibox
|
|
23
|
+
* with no `hits` at all is the launch grammar only (what the Home app renders). */
|
|
24
|
+
interface OmniboxHitSources {
|
|
25
|
+
/** Candidate app hits for a query; the package ranks, filters and orders them. */
|
|
26
|
+
apps?: (query: string) => AppHit[];
|
|
27
|
+
/** Matched doc hits for a query, best-first, capped by the source. */
|
|
28
|
+
docs?: (query: string) => DocHit[];
|
|
29
|
+
}
|
|
30
|
+
interface OmniboxProps {
|
|
31
|
+
variant: OmniboxVariant;
|
|
32
|
+
/** Nav variant only: true while the hero omnibox is mounted (`/`), so the
|
|
33
|
+
* nav field renders as the shortcut that focuses it. Derived by the caller
|
|
34
|
+
* from the route — render-time data, not an effect. */
|
|
35
|
+
heroShortcut?: boolean;
|
|
36
|
+
/** App-directory and docs hit sources. Absent → the launch grammar only. */
|
|
37
|
+
hits?: OmniboxHitSources;
|
|
38
|
+
/** Renders the app row's trailing chip (e.g. a provenance chip). The chip is a
|
|
39
|
+
* site component with site data types, so the package renders what it is given. */
|
|
40
|
+
renderChip?: (hit: AppHit) => ReactNode;
|
|
41
|
+
}
|
|
42
|
+
declare function Omnibox({ variant, heroShortcut, hits, renderChip }: OmniboxProps): react.JSX.Element;
|
|
43
|
+
|
|
44
|
+
export { type AppHit, type DocHit, type OmniboxHitSources, type OmniboxProps, Omnibox as default };
|