@immediately-run/omnibox 0.2.1 → 0.3.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/Omnibox.cjs CHANGED
@@ -27,10 +27,11 @@ var import_jsx_runtime = (
27
27
  require("react/jsx-runtime")
28
28
  );
29
29
  var import_react = require("react");
30
- var import_omnibox = require("./omnibox.css");
30
+ var import_omniboxStyles = require("./omniboxStyles");
31
31
  var import_launch = require("./launch");
32
32
  var import_platformLink = require("@immediately-run/sdk/platformLink");
33
33
  var import_omniboxFocus = require("./omniboxFocus");
34
+ (0, import_omniboxStyles.ensureOmniboxStyles)();
34
35
  function useMediaQuery(query) {
35
36
  const [matches, setMatches] = (0, import_react.useState)(
36
37
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Omnibox.tsx"],"sourcesContent":["import { Fragment, 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 /** The PLATFORM path the row opens, e.g. `/present/github/immediately-run/todo/main/files/src/App.tsx`.\n * Supplied by the consumer's `apps` source beside its own route builder, so the\n * package carries no second spelling of any route family. Rendered through\n * `PlatformLink` (host-space href, frame-escaping). */\n path: 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 /** The app-space route behind `href`, when the consumer renders the row through\n * its own in-app link (`renderDoc`). Opaque to the package. */\n to?: 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 component ──────────────────────────────────────────────────────── */\n\n/** What a `renderDoc` anchor must spread: the combobox's option identity and state. */\nexport interface DocAnchorProps {\n id: string;\n className: string;\n role: 'option';\n 'aria-selected': boolean;\n}\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 /** Renders a doc ROW. `anchorProps` carries the combobox contract (the option's\n * id, class, role and aria-selected) — spread them onto the anchor you render so\n * the arrow-key highlight and the Enter walk keep working. The fallback is a\n * plain `<a href>` — its href is real and resolvable, but on-host a plain click\n * navigates the sandboxed FRAME to the target instead of routing the app, so a\n * consumer with an in-app link (the landing page's SiteLink) should supply this. */\n renderDoc?: (hit: DocHit, anchorProps: DocAnchorProps) => ReactNode;\n}\n\nfunction Omnibox({ variant, heroShortcut = false, hits, renderChip, renderDoc }: 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: that query's group stays empty\n // and the location row still renders. The source is called again on the next\n // keystroke — a transient throw recovers silently; only the LOG is once.\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; its rows are empty for this query`, 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={hit.path}\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 const anchorProps: DocAnchorProps = {\n id: `${listId}-opt-doc-${hit.key}`,\n className: 'omnibox-option',\n role: 'option',\n 'aria-selected': highlight === idx,\n };\n if (renderDoc) {\n return <Fragment key={hit.key}>{renderDoc(hit, anchorProps)}</Fragment>;\n }\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"]}
1
+ {"version":3,"sources":["../src/Omnibox.tsx"],"sourcesContent":["import { Fragment, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent, ReactNode } from 'react';\nimport { ensureOmniboxStyles } from './omniboxStyles';\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// Module scope, so the rules are present before the first render — the same moment the\n// old `import './omnibox.css'` took effect.\n//\n// It is EAGER for anyone who loads the package entry, and that is worth saying plainly:\n// `index.ts` re-exports `Omnibox`, and the CJS build has no tree-shaking, so\n// `dist/index.cjs` carries an unconditional `require(\"./Omnibox\")` — a consumer importing\n// only `parseLaunch` or `focusOmnibox` still injects the stylesheet. Exactly what the CSS\n// import did, so nothing regressed; it just is not the free lunch an earlier draft of\n// this comment claimed.\nensureOmniboxStyles();\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 /** The PLATFORM path the row opens, e.g. `/present/github/immediately-run/todo/main/files/src/App.tsx`.\n * Supplied by the consumer's `apps` source beside its own route builder, so the\n * package carries no second spelling of any route family. Rendered through\n * `PlatformLink` (host-space href, frame-escaping). */\n path: 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 /** The app-space route behind `href`, when the consumer renders the row through\n * its own in-app link (`renderDoc`). Opaque to the package. */\n to?: 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 component ──────────────────────────────────────────────────────── */\n\n/** What a `renderDoc` anchor must spread: the combobox's option identity and state. */\nexport interface DocAnchorProps {\n id: string;\n className: string;\n role: 'option';\n 'aria-selected': boolean;\n}\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 /** Renders a doc ROW. `anchorProps` carries the combobox contract (the option's\n * id, class, role and aria-selected) — spread them onto the anchor you render so\n * the arrow-key highlight and the Enter walk keep working. The fallback is a\n * plain `<a href>` — its href is real and resolvable, but on-host a plain click\n * navigates the sandboxed FRAME to the target instead of routing the app, so a\n * consumer with an in-app link (the landing page's SiteLink) should supply this. */\n renderDoc?: (hit: DocHit, anchorProps: DocAnchorProps) => ReactNode;\n}\n\nfunction Omnibox({ variant, heroShortcut = false, hits, renderChip, renderDoc }: 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: that query's group stays empty\n // and the location row still renders. The source is called again on the next\n // keystroke — a transient throw recovers silently; only the LOG is once.\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; its rows are empty for this query`, 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={hit.path}\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 const anchorProps: DocAnchorProps = {\n id: `${listId}-opt-doc-${hit.key}`,\n className: 'omnibox-option',\n role: 'option',\n 'aria-selected': highlight === idx,\n };\n if (renderDoc) {\n return <Fragment key={hit.key}>{renderDoc(hit, anchorProps)}</Fragment>;\n }\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"]}
package/dist/Omnibox.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Fragment as Fragment2, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
3
- import "./omnibox.css";
3
+ import { ensureOmniboxStyles } from "./omniboxStyles";
4
4
  import { parseLaunch, PROVIDERS } from "./launch";
5
5
  import { PlatformLink } from "@immediately-run/sdk/platformLink";
6
6
  import { focusHeroOmnibox, registerOmniboxFocus } from "./omniboxFocus";
7
+ ensureOmniboxStyles();
7
8
  function useMediaQuery(query) {
8
9
  const [matches, setMatches] = useState(
9
10
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Omnibox.tsx"],"sourcesContent":["import { Fragment, 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 /** The PLATFORM path the row opens, e.g. `/present/github/immediately-run/todo/main/files/src/App.tsx`.\n * Supplied by the consumer's `apps` source beside its own route builder, so the\n * package carries no second spelling of any route family. Rendered through\n * `PlatformLink` (host-space href, frame-escaping). */\n path: 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 /** The app-space route behind `href`, when the consumer renders the row through\n * its own in-app link (`renderDoc`). Opaque to the package. */\n to?: 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 component ──────────────────────────────────────────────────────── */\n\n/** What a `renderDoc` anchor must spread: the combobox's option identity and state. */\nexport interface DocAnchorProps {\n id: string;\n className: string;\n role: 'option';\n 'aria-selected': boolean;\n}\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 /** Renders a doc ROW. `anchorProps` carries the combobox contract (the option's\n * id, class, role and aria-selected) — spread them onto the anchor you render so\n * the arrow-key highlight and the Enter walk keep working. The fallback is a\n * plain `<a href>` — its href is real and resolvable, but on-host a plain click\n * navigates the sandboxed FRAME to the target instead of routing the app, so a\n * consumer with an in-app link (the landing page's SiteLink) should supply this. */\n renderDoc?: (hit: DocHit, anchorProps: DocAnchorProps) => ReactNode;\n}\n\nfunction Omnibox({ variant, heroShortcut = false, hits, renderChip, renderDoc }: 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: that query's group stays empty\n // and the location row still renders. The source is called again on the next\n // keystroke — a transient throw recovers silently; only the LOG is once.\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; its rows are empty for this query`, 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={hit.path}\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 const anchorProps: DocAnchorProps = {\n id: `${listId}-opt-doc-${hit.key}`,\n className: 'omnibox-option',\n role: 'option',\n 'aria-selected': highlight === idx,\n };\n if (renderDoc) {\n return <Fragment key={hit.key}>{renderDoc(hit, anchorProps)}</Fragment>;\n }\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":"AAkQQ,SA0EI,UA1EJ,KAcJ,YAdI;AAlQR,SAAS,YAAAA,WAAU,aAAa,WAAW,OAAO,SAAS,QAAQ,gBAAgB;AAEnF,OAAO;AACP,SAAS,aAAa,iBAA8B;AACpD,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB,4BAA4B;AAevD,SAAS,cAAc,OAAwB;AAC7C,QAAM,CAAC,SAAS,UAAU,IAAI;AAAA,IAAS,MACrC,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,aAC1D,OAAO,WAAW,KAAK,EAAE,UACzB;AAAA,EACN;AACA,YAAU,MAAM;AACd,QAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY;AAC9E,UAAM,KAAK,OAAO,WAAW,KAAK;AAClC,UAAM,WAAW,MAAM,WAAW,GAAG,OAAO;AAC5C,aAAS;AACT,OAAG,iBAAiB,UAAU,QAAQ;AACtC,WAAO,MAAM,GAAG,oBAAoB,UAAU,QAAQ;AAAA,EACxD,GAAG,CAAC,KAAK,CAAC;AACV,SAAO;AACT;AA4CA,SAAS,SAAS,KAAa,GAAmB;AAChD,MAAI,IAAI,KAAK,YAAY,EAAE,WAAW,CAAC,EAAG,QAAO;AACjD,MAAI,IAAI,KAAK,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AAC/C,MAAI,IAAI,KAAK,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AAC/C,MAAI,IAAI,MAAM,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AAChD,MAAI,IAAI,SAAS,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AACnD,SAAO;AACT;AAgCA,SAAS,QAAQ,EAAE,SAAS,eAAe,OAAO,MAAM,YAAY,UAAU,GAAiB;AAC7F,QAAM,WAAW,cAAc,oBAAoB;AACnD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,EAAE;AAC7C,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,WAAW,OAAuB,IAAI;AAC5C,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,GAAG,MAAM;AACzB,QAAM,WAAW,MAAM;AACvB,QAAM,WAAW,MAAM;AAIvB,QAAM,gBAAgB,OAAqC,oBAAI,IAAI,CAAC;AACpE,QAAM,aAAa;AAAA,IACjB,SAASC,YACP,MACA,QACA,GACoD;AACpD,UAAI;AACF,eAAO,OAAQ,CAAC;AAAA,MAClB,SAAS,OAAO;AACd,YAAI,CAAC,cAAc,QAAQ,IAAI,IAAI,GAAG;AACpC,wBAAc,QAAQ,IAAI,IAAI;AAC9B,kBAAQ,KAAK,iBAAiB,OAAO,IAAI,CAAC,yDAAyD,KAAK;AAAA,QAC1G;AACA,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,SAAiB,QAAQ,MAAM,YAAY,KAAK,GAAG,CAAC,KAAK,CAAC;AAChE,QAAM,WAAW,OAAO,SAAS,cAAc,OAAO,SAAS;AAC/D,QAAM,UACJ,OAAO,SAAS,aACZ,OAAO,cACP,OAAO,SAAS,iBACd,OAAO,OACP;AAER,QAAM,YAAY,MAAM,KAAK,MAAM;AAInC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,MAAI,cAAc,OAAO;AACvB,iBAAa,KAAK;AAClB,iBAAa,EAAE;AAAA,EACjB;AAIA,QAAM,SACJ,OAAO,SAAS,qBACZ,GAAG,OAAO,SAAS,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,OAAO,SAAS,MAAM,CAAC,CAAC,+CACrE;AAEN,QAAM,SACJ,YAAY,QAAQ,8BAA8B;AAEpD,QAAM,UAAU,QAAQ,MAAM;AAC5B,QAAI,CAAC,aAAa,CAAC,MAAM,KAAM,QAAO,CAAC;AACvC,UAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,WAAO,WAAW,QAAQ,KAAK,MAAM,CAAC,EACnC,IAAI,CAAC,SAAS,EAAE,KAAK,OAAO,SAAS,KAAK,CAAC,EAAE,EAAE,EAC/C,OAAO,CAAC,EAAE,MAAM,MAAM,SAAS,CAAC,EAChC,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,IAAI,CAAC,EAAE,IAAI,MAAM,GAAG;AAAA,EACzB,GAAG,CAAC,WAAW,OAAO,MAAM,UAAU,CAAC;AAEvC,QAAM,UAAU,QAAQ,MAAM;AAC5B,QAAI,CAAC,aAAa,CAAC,MAAM,KAAM,QAAO,CAAC;AACvC,WAAO,WAAW,QAAQ,KAAK,MAAM,MAAM,KAAK,EAAE,YAAY,CAAC;AAAA,EACjE,GAAG,CAAC,WAAW,OAAO,MAAM,UAAU,CAAC;AAEvC,QAAM,cAAc,OAAO,SAAS,aAAa,SAAS;AAC1D,QAAM,aAAa,QAAQ,WAAW,KAAK,QAAQ,SAAS,KAAK,QAAQ,SAAS;AAIlF,QAAM,UAAU,QAAQ,MAAM;AAC5B,UAAM,OAAwC,CAAC;AAC/C,QAAI,YAAa,MAAK,KAAK,EAAE,IAAI,GAAG,MAAM,iBAAiB,OAAO,YAAY,QAAQ,CAAC;AACvF,eAAW,OAAO,QAAS,MAAK,KAAK,EAAE,IAAI,GAAG,MAAM,QAAQ,IAAI,GAAG,IAAI,OAAO,IAAI,KAAK,CAAC;AACxF,eAAW,OAAO,QAAS,MAAK,KAAK,EAAE,IAAI,GAAG,MAAM,YAAY,IAAI,GAAG,IAAI,OAAO,IAAI,MAAM,CAAC;AAC7F,WAAO;AAAA,EACT,GAAG,CAAC,aAAa,SAAS,SAAS,MAAM,CAAC;AAK1C;AAAA,IACE,MACE,qBAAqB,SAAS;AAAA,MAC5B,OAAO,MAAM,SAAS,SAAS,MAAM;AAAA,MACrC,QAAQ,MAAM,SAAS,SAAS,eAAe,EAAE,UAAU,UAAU,OAAO,SAAS,CAAC;AAAA,IACxF,CAAC;AAAA,IACH,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,MAA4C;AAC3C,UAAI,EAAE,QAAQ,eAAe,EAAE,QAAQ,WAAW;AAChD,YAAI,CAAC,aAAa,QAAQ,WAAW,EAAG;AACxC,UAAE,eAAe;AACjB,qBAAa,CAAC,MAAM;AAClB,cAAI,MAAM,GAAI,QAAO,EAAE,QAAQ,cAAc,IAAI,QAAQ,SAAS;AAClE,kBAAQ,KAAK,EAAE,QAAQ,cAAc,IAAI,MAAM,QAAQ,UAAU,QAAQ;AAAA,QAC3E,CAAC;AACD;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,SAAS;AACrB,YAAI,aAAa,KAAK,YAAY,QAAQ,QAAQ;AAChD,YAAE,eAAe;AACjB,mBAAS,eAAe,QAAQ,SAAS,EAAE,EAAE,GAAG,MAAM;AACtD;AAAA,QACF;AACA,YAAI,UAAU;AACZ,YAAE,eAAe;AACjB,mBAAS,eAAe,GAAG,MAAM,MAAM,GAAG,MAAM;AAAA,QAClD;AACA;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,UAAU;AAEtB,iBAAS,EAAE;AACX,qBAAa,EAAE;AACf,iBAAS,SAAS,KAAK;AAAA,MACzB;AAAA,IACF;AAAA,IACA,CAAC,WAAW,SAAS,WAAW,UAAU,MAAM;AAAA,EAClD;AAEA,QAAM,OACJ,oBAAC,UAAK,WAAU,gBAAe,eAAa,OAAO,KAAK,SAAS,EAAE,WAAW,KAAK,QAChF,iBAAO,KAAK,SAAS,EAAE,WAAW;AAAA;AAAA;AAAA,IAGjC,oBAAC,UAAK,WAAU,sBAAqB,oBAAM;AAAA,MAE3C,oBAAC,YAAO,WAAU,uBAAsB,cAAW,YAChD,iBAAO,KAAK,SAAS,EAAE,IAAI,CAAC,MAC3B,oBAAC,YAAe,OAAO,GACpB,eADU,CAEb,CACD,GACH,GAEJ;AAGF,QAAM,MAAM,YAAY,SACtB;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,GAAG,MAAM;AAAA,MACb,WAAU;AAAA,MACV,MAAM;AAAA,MACN,cAAW;AAAA,MAEX;AAAA,4BAAC,UAAK,WAAU,qBAAoB,iBAAG;AAAA,QACvC,oBAAC,UAAK,WAAU,qBAAoB,eAAY,QAAO,oBAEvD;AAAA;AAAA;AAAA,EACF,IAEA;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,GAAG,MAAM;AAAA,MACb,MAAK;AAAA,MACL,WAAU;AAAA,MACV,iBAAc;AAAA,MACd,oBAAkB,GAAG,QAAQ,IAAI,QAAQ;AAAA,MACzC,SAAS,CAAC,MAAM,EAAE,eAAe;AAAA,MAEjC;AAAA,4BAAC,UAAK,WAAU,qBAAoB,iBAAG;AAAA,QACvC,oBAAC,UAAK,WAAU,qBAAoB,eAAY,QAAO,oBAEvD;AAAA;AAAA;AAAA,EACF;AAGF,QAAM,QACJ,qBAAC,SAAI,WAAW,oBAAoB,OAAO,IACzC;AAAA,yBAAC,SAAI,WAAU,eACZ;AAAA;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,IAAI;AAAA,UACJ,WAAU;AAAA,UACV,MAAK;AAAA,UACL,MAAK;AAAA,UACL,qBAAkB;AAAA,UAClB,iBAAe;AAAA,UACf,iBAAe,YAAY,SAAS;AAAA,UACpC,yBAAuB,aAAa,IAAI,QAAQ,SAAS,GAAG,KAAK;AAAA,UACjE,oBAAkB,GAAG,QAAQ,IAAI,QAAQ;AAAA,UACzC,gBAAc,SAAS,OAAO;AAAA,UAC9B,aAAa,WAAW,gCAAgC;AAAA,UACxD,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,UACxC;AAAA;AAAA,MACF;AAAA,MACC;AAAA,OACH;AAAA,IACA,oBAAC,OAAE,WAAU,kBAAiB,IAAI,UAC/B,oBAAU,QACb;AAAA,IAEA,oBAAC,OAAE,WAAU,2BAA0B,IAAI,UAAU,aAAU,UAC5D,kBACH;AAAA,IACC,aACC,oBAAC,SAAI,WAAU,iBAAgB,IAAI,QAAQ,MAAK,WAAU,cAAW,WAClE,uBACC,iCACG;AAAA,qBACC,oBAAC,SAAI,WAAU,iBAAgB,MAAK,SAAQ,cAAW,mBACrD;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,GAAG,MAAM;AAAA,UACb,WAAU;AAAA,UACV,MAAK;AAAA,UACL,iBAAe,cAAc;AAAA,UAC7B,MAAM,YAAY;AAAA,UAElB;AAAA,gCAAC,UAAK,WAAU,uBAAuB,sBAAY,SAAQ;AAAA,YAC3D,oBAAC,UAAK,WAAU,yBAAwB,iBAAG;AAAA;AAAA;AAAA,MAC7C,GACF;AAAA,MAED,QAAQ,SAAS,KAChB,oBAAC,SAAI,WAAU,iBAAgB,MAAK,SAAQ,cAAW,yBACpD,kBAAQ,IAAI,CAAC,QAAQ;AACpB,cAAM,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,QAAQ,IAAI,GAAG,EAAE;AACxE,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,IAAI,GAAG,MAAM,QAAQ,IAAI,GAAG;AAAA,YAC5B,WAAU;AAAA,YACV,MAAK;AAAA,YACL,iBAAe,cAAc;AAAA,YAC7B,MAAM,IAAI;AAAA,YAEV;AAAA,kCAAC,UAAK,WAAU,uBAAuB,cAAI,MAAK;AAAA,cAChD,oBAAC,UAAK,WAAU,sBAAsB,cAAI,UAAS;AAAA,cACnD,oBAAC,UAAK,WAAU,wBAAwB,cAAI,OAAM;AAAA,cACjD,aAAa,GAAG;AAAA;AAAA;AAAA,UAVZ,IAAI;AAAA,QAWX;AAAA,MAEJ,CAAC,GACH;AAAA,MAED,QAAQ,SAAS,KAChB,oBAAC,SAAI,WAAU,iBAAgB,MAAK,SAAQ,cAAW,sBACpD,kBAAQ,IAAI,CAAC,QAAQ;AACpB,cAAM,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,YAAY,IAAI,GAAG,EAAE;AAC5E,cAAM,cAA8B;AAAA,UAClC,IAAI,GAAG,MAAM,YAAY,IAAI,GAAG;AAAA,UAChC,WAAW;AAAA,UACX,MAAM;AAAA,UACN,iBAAiB,cAAc;AAAA,QACjC;AACA,YAAI,WAAW;AACb,iBAAO,oBAACD,WAAA,EAAwB,oBAAU,KAAK,WAAW,KAApC,IAAI,GAAkC;AAAA,QAC9D;AACA,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,IAAI,GAAG,MAAM,YAAY,IAAI,GAAG;AAAA,YAChC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,iBAAe,cAAc;AAAA,YAC7B,MAAM,IAAI;AAAA,YAEV;AAAA,kCAAC,UAAK,WAAU,uBAAuB,cAAI,OAAM;AAAA,cACjD,oBAAC,UAAK,WAAU,wBAAwB,cAAI,MAAK;AAAA;AAAA;AAAA,UAR5C,IAAI;AAAA,QASX;AAAA,MAEJ,CAAC,GACH;AAAA,OAEJ,IAEA,oBAAC,SAAI,WAAU,iBAAgB,gEAAkD,GAErF;AAAA,KAEJ;AAMF,MAAI,YAAY,SAAS,cAAc;AACrC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS,MAAM,iBAAiB;AAAA,QAChC,cAAW;AAAA,QAEX;AAAA,8BAAC,UAAK,WAAU,4BAA2B,oBAAM;AAAA,UACjD,oBAAC,UAAK,WAAU,OAAM,qBAAE;AAAA;AAAA;AAAA,IAC1B;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAW,gCAAgC,OAAO,IAAI,KAAK,UAC9D;AAAA,wBAAC,WAAM,WAAU,2BAA0B,SAAS,SAAS,mDAE7D;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,IAAO,kBAAQ;","names":["Fragment","callSource"]}
1
+ {"version":3,"sources":["../src/Omnibox.tsx"],"sourcesContent":["import { Fragment, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent, ReactNode } from 'react';\nimport { ensureOmniboxStyles } from './omniboxStyles';\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// Module scope, so the rules are present before the first render — the same moment the\n// old `import './omnibox.css'` took effect.\n//\n// It is EAGER for anyone who loads the package entry, and that is worth saying plainly:\n// `index.ts` re-exports `Omnibox`, and the CJS build has no tree-shaking, so\n// `dist/index.cjs` carries an unconditional `require(\"./Omnibox\")` — a consumer importing\n// only `parseLaunch` or `focusOmnibox` still injects the stylesheet. Exactly what the CSS\n// import did, so nothing regressed; it just is not the free lunch an earlier draft of\n// this comment claimed.\nensureOmniboxStyles();\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 /** The PLATFORM path the row opens, e.g. `/present/github/immediately-run/todo/main/files/src/App.tsx`.\n * Supplied by the consumer's `apps` source beside its own route builder, so the\n * package carries no second spelling of any route family. Rendered through\n * `PlatformLink` (host-space href, frame-escaping). */\n path: 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 /** The app-space route behind `href`, when the consumer renders the row through\n * its own in-app link (`renderDoc`). Opaque to the package. */\n to?: 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 component ──────────────────────────────────────────────────────── */\n\n/** What a `renderDoc` anchor must spread: the combobox's option identity and state. */\nexport interface DocAnchorProps {\n id: string;\n className: string;\n role: 'option';\n 'aria-selected': boolean;\n}\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 /** Renders a doc ROW. `anchorProps` carries the combobox contract (the option's\n * id, class, role and aria-selected) — spread them onto the anchor you render so\n * the arrow-key highlight and the Enter walk keep working. The fallback is a\n * plain `<a href>` — its href is real and resolvable, but on-host a plain click\n * navigates the sandboxed FRAME to the target instead of routing the app, so a\n * consumer with an in-app link (the landing page's SiteLink) should supply this. */\n renderDoc?: (hit: DocHit, anchorProps: DocAnchorProps) => ReactNode;\n}\n\nfunction Omnibox({ variant, heroShortcut = false, hits, renderChip, renderDoc }: 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: that query's group stays empty\n // and the location row still renders. The source is called again on the next\n // keystroke — a transient throw recovers silently; only the LOG is once.\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; its rows are empty for this query`, 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={hit.path}\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 const anchorProps: DocAnchorProps = {\n id: `${listId}-opt-doc-${hit.key}`,\n className: 'omnibox-option',\n role: 'option',\n 'aria-selected': highlight === idx,\n };\n if (renderDoc) {\n return <Fragment key={hit.key}>{renderDoc(hit, anchorProps)}</Fragment>;\n }\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":["Fragment","callSource"]}
@@ -0,0 +1,45 @@
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 omniboxStyles_exports = {};
20
+ __export(omniboxStyles_exports, {
21
+ ensureOmniboxStyles: () => ensureOmniboxStyles
22
+ });
23
+ module.exports = __toCommonJS(omniboxStyles_exports);
24
+ var import_omniboxStyles = require("./omniboxStyles.generated");
25
+ const STYLE_ID = "immediately-run-omnibox-css";
26
+ function ensureOmniboxStyles() {
27
+ try {
28
+ if (typeof document === "undefined") return;
29
+ if (document.getElementById(STYLE_ID)) return;
30
+ const style = document.createElement("style");
31
+ style.id = STYLE_ID;
32
+ style.textContent = import_omniboxStyles.OMNIBOX_CSS;
33
+ (document.head ?? document.documentElement).appendChild(style);
34
+ } catch (err) {
35
+ try {
36
+ console.warn("[omnibox] could not inject the stylesheet; rendering unstyled.", err);
37
+ } catch {
38
+ }
39
+ }
40
+ }
41
+ // Annotate the CommonJS export names for ESM import in node:
42
+ 0 && (module.exports = {
43
+ ensureOmniboxStyles
44
+ });
45
+ //# sourceMappingURL=omniboxStyles.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/omniboxStyles.ts"],"sourcesContent":["// Injecting the omnibox's stylesheet from JS, once per document.\n//\n// WHY NOT `import './omnibox.css'`. That is what the package shipped until 2026-09-08,\n// and on immediately.run it took down the front door. The sandbox bundler followed the\n// specifier out of the resolved package, fetched the stylesheet, and evaluated it as\n// JAVASCRIPT: `SyntaxError: Unexpected token '.'` on the first selector, the whole app\n// dead behind it, prod and local alike. An app's OWN `.css` import works there; a\n// dependency's did not, and this package cannot make a consumer's bundler grow a CSS\n// loader. JS is the one thing every consumer can execute, so the styles ship as JS.\n//\n// `dist/omnibox.css` is still published and still exported at `./omnibox.css`, for a\n// consumer that would rather own the cascade — importing it as well is harmless (the\n// rules are identical and idempotent), it just is not required any more.\nimport { OMNIBOX_CSS } from './omniboxStyles.generated';\n\n/** Marks the injected element, and makes a second injection a no-op. */\nconst STYLE_ID = 'immediately-run-omnibox-css';\n\n/**\n * Ensure the omnibox stylesheet is in `document`. Idempotent, and safe to call from\n * render: it writes nothing when the element is already there.\n *\n * Deliberately defensive rather than clever:\n * - **no `document` is not an error.** SSR and any non-DOM renderer simply get no\n * styles rather than a crash on import, and this module is imported at module scope.\n * - **a throwing DOM is not an error either.** Some embeddings forbid injecting a\n * style element; an unstyled combobox is a bad outcome, a dead app is a worse one,\n * and the caller has no way to recover from either.\n * - the element carries an `id`, so a second copy of this package on the page (a\n * version skew in one consumer's tree) styles the DOM once, not twice.\n */\nexport function ensureOmniboxStyles(): void {\n try {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = OMNIBOX_CSS;\n (document.head ?? document.documentElement).appendChild(style);\n } catch (err) {\n // Unstyled beats dead — but silent beats neither. Three different failures land here\n // (no `head` or `documentElement`, an embedding that refuses `createElement('style')`,\n // a refused `textContent` assignment) and without this they are indistinguishable\n // from \"the styles are fine\", which is how an unstyled combobox goes unreported.\n // `console.warn` and not `throw`: the caller can recover from neither outcome.\n try {\n console.warn('[omnibox] could not inject the stylesheet; rendering unstyled.', err);\n } catch {\n /* a console that throws must not be the thing that breaks the render. */\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAaA,2BAA4B;AAG5B,MAAM,WAAW;AAeV,SAAS,sBAA4B;AAC1C,MAAI;AACF,QAAI,OAAO,aAAa,YAAa;AACrC,QAAI,SAAS,eAAe,QAAQ,EAAG;AACvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AACpB,KAAC,SAAS,QAAQ,SAAS,iBAAiB,YAAY,KAAK;AAAA,EAC/D,SAAS,KAAK;AAMZ,QAAI;AACF,cAAQ,KAAK,kEAAkE,GAAG;AAAA,IACpF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Ensure the omnibox stylesheet is in `document`. Idempotent, and safe to call from
3
+ * render: it writes nothing when the element is already there.
4
+ *
5
+ * Deliberately defensive rather than clever:
6
+ * - **no `document` is not an error.** SSR and any non-DOM renderer simply get no
7
+ * styles rather than a crash on import, and this module is imported at module scope.
8
+ * - **a throwing DOM is not an error either.** Some embeddings forbid injecting a
9
+ * style element; an unstyled combobox is a bad outcome, a dead app is a worse one,
10
+ * and the caller has no way to recover from either.
11
+ * - the element carries an `id`, so a second copy of this package on the page (a
12
+ * version skew in one consumer's tree) styles the DOM once, not twice.
13
+ */
14
+ declare function ensureOmniboxStyles(): void;
15
+
16
+ export { ensureOmniboxStyles };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Ensure the omnibox stylesheet is in `document`. Idempotent, and safe to call from
3
+ * render: it writes nothing when the element is already there.
4
+ *
5
+ * Deliberately defensive rather than clever:
6
+ * - **no `document` is not an error.** SSR and any non-DOM renderer simply get no
7
+ * styles rather than a crash on import, and this module is imported at module scope.
8
+ * - **a throwing DOM is not an error either.** Some embeddings forbid injecting a
9
+ * style element; an unstyled combobox is a bad outcome, a dead app is a worse one,
10
+ * and the caller has no way to recover from either.
11
+ * - the element carries an `id`, so a second copy of this package on the page (a
12
+ * version skew in one consumer's tree) styles the DOM once, not twice.
13
+ */
14
+ declare function ensureOmniboxStyles(): void;
15
+
16
+ export { ensureOmniboxStyles };
@@ -0,0 +1,29 @@
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 omniboxStyles_generated_exports = {};
20
+ __export(omniboxStyles_generated_exports, {
21
+ OMNIBOX_CSS: () => OMNIBOX_CSS
22
+ });
23
+ module.exports = __toCommonJS(omniboxStyles_generated_exports);
24
+ const OMNIBOX_CSS = "/* The omnibox (R3-512; FRONT_DOOR_IA \xA75). Tokens come from index.css only; the\n floating results panel (desktop nav variant) is the only shadowed form \u2014\n hero, new, and every mobile form are in-flow and carry no shadow. */\n\n.omnibox-outer {\n width: 100%;\n}\n\n.omnibox-outer--hero,\n.omnibox-outer--new {\n max-width: 620px;\n}\n\n.omnibox-row {\n display: flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--line);\n border-color: var(--accent);\n border-radius: var(--r-md);\n background: var(--panel);\n overflow: hidden;\n}\n\n.omnibox-input {\n flex: 1 1 auto;\n min-width: 0;\n border: 0;\n background: transparent;\n color: var(--ink);\n font: 400 16px/1.2 var(--sans);\n padding: 14px 14px;\n outline: none;\n}\n\n.omnibox-input:focus-visible {\n outline: none;\n}\n\n.omnibox-outer:focus-within .omnibox-row {\n box-shadow: var(--glow);\n}\n\n.omnibox-chip {\n display: flex;\n align-items: center;\n padding: 0 0 0 16px;\n flex: 0 0 auto;\n}\n\n.omnibox-chip-label,\n.omnibox-chip-select {\n font: 400 12px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n background: transparent;\n border: 0;\n}\n\n.omnibox-run {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin: 6px;\n padding: 8px 18px;\n border-radius: var(--r-sm);\n border: 1px solid var(--line);\n background: var(--bg);\n color: var(--ink);\n font: 700 14px/1 var(--sans);\n text-decoration: none;\n cursor: pointer;\n align-self: center;\n}\n\n.omnibox-run-arrow {\n font-family: var(--mono);\n}\n\n.omnibox--hero .omnibox-run:not([aria-disabled='true']),\n.omnibox--new .omnibox-run:not([aria-disabled='true']) {\n border: 0;\n color: #16101a;\n background-image: var(--grad-btn);\n}\n\n.omnibox-run[aria-disabled='true'] {\n opacity: 0.55;\n cursor: default;\n}\n\n.omnibox-helper {\n margin: 8px 2px 0;\n font: 400 12px/1.4 var(--mono);\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 results panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-panel {\n border: 1px solid var(--line);\n border-radius: var(--r-md);\n background: var(--bg);\n margin-top: 8px;\n padding: 6px;\n /* in-flow by default: it pushes content down (mobile + hero + new) */\n}\n\n.omnibox-group {\n padding: 4px 0;\n}\n\n.omnibox-group + .omnibox-group {\n border-top: 1px solid var(--line);\n}\n\n.omnibox-option {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 4px 10px;\n padding: 10px 12px;\n border-radius: var(--r-xs);\n color: var(--ink);\n text-decoration: none;\n cursor: pointer;\n}\n\n.omnibox-option[aria-selected='true'],\n.omnibox-option:hover {\n background: var(--line);\n}\n\n.omnibox-option-name {\n font-weight: 600;\n font-size: 15px;\n}\n\n.omnibox-option-cat {\n font: 400 11px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n}\n\n.omnibox-option-blurb {\n flex-basis: 100%;\n font-size: 13px;\n color: var(--ink-2);\n}\n\n.omnibox-option-action {\n margin-left: auto;\n font: 400 12px/1 var(--mono);\n color: var(--ink-2);\n}\n\n.omnibox-empty {\n padding: 14px 12px;\n color: var(--ink-2);\n font-size: 14px;\n}\n\n/* \u2500\u2500 nav variant (desktop): floating field + shadowed panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-outer--nav {\n position: relative;\n width: 230px;\n}\n\n.omnibox-outer--nav .omnibox-row {\n border-color: var(--line);\n border-radius: var(--r-sm);\n}\n\n.omnibox-outer--nav .omnibox-input {\n padding: 9px 12px;\n font-size: 14px;\n}\n\n.omnibox-outer--nav .omnibox-helper {\n display: none;\n}\n\n.omnibox-outer--nav .omnibox-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n right: 0;\n box-shadow: var(--shadow-pop);\n z-index: 30;\n}\n\n.omnibox-nav-button {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: 1px solid var(--line);\n border-radius: var(--r-sm);\n background: transparent;\n color: var(--ink);\n font: 400 14px/1 var(--sans);\n padding: 9px 12px;\n cursor: pointer;\n}\n\n.omnibox-nav-button .omnibox-nav-button-label {\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 mobile (FRONT_DOOR_IA \xA75.5): full width, chip collapses into the field's\n left padding, Run is an in-field 44px arrow, panel in-flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@media (max-width: 720px) {\n .omnibox-outer--nav {\n width: 100%;\n }\n\n .omnibox-chip {\n display: none;\n }\n\n .omnibox-input {\n padding-left: 16px;\n }\n\n .omnibox-run {\n margin: 5px;\n padding: 0;\n width: 44px;\n height: 44px;\n justify-content: center;\n gap: 0;\n }\n\n .omnibox-run-label {\n display: none;\n }\n\n .omnibox-run-arrow {\n font-size: 20px;\n }\n\n .omnibox-outer--nav .omnibox-helper {\n display: block;\n }\n\n .omnibox-outer--nav .omnibox-panel {\n position: static;\n box-shadow: none;\n }\n}\n\n/* The visually hidden label / live region: present to assistive tech, absent\n to the eye. Scoped here so the omnibox owns its own a11y plumbing. */\n.omnibox-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* The keyboard-hint chip the omnibox and the nav shortcut render (R3-512). Moved\n * verbatim from landing-page App.css with the component that renders it \u2014 one home,\n * so the Home app renders the same chip. */\n.kbd{font:400 11px var(--mono);background:var(--bg);border:1px solid var(--line);\n border-radius:var(--r-xs);padding:2px 6px;color:var(--ink-3)}\n";
25
+ // Annotate the CommonJS export names for ESM import in node:
26
+ 0 && (module.exports = {
27
+ OMNIBOX_CSS
28
+ });
29
+ //# sourceMappingURL=omniboxStyles.generated.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/omniboxStyles.generated.ts"],"sourcesContent":["// GENERATED by scripts/build-css.mjs from src/omnibox.css — do not edit by hand.\n// Committed so tests and `tsc` see it without a build step; `npm run check:css-parity`\n// fails when it drifts. See that script for why the styles ship as a string.\n\nexport const OMNIBOX_CSS = \"/* The omnibox (R3-512; FRONT_DOOR_IA §5). Tokens come from index.css only; the\\n floating results panel (desktop nav variant) is the only shadowed form —\\n hero, new, and every mobile form are in-flow and carry no shadow. */\\n\\n.omnibox-outer {\\n width: 100%;\\n}\\n\\n.omnibox-outer--hero,\\n.omnibox-outer--new {\\n max-width: 620px;\\n}\\n\\n.omnibox-row {\\n display: flex;\\n align-items: stretch;\\n gap: 0;\\n border: 1px solid var(--line);\\n border-color: var(--accent);\\n border-radius: var(--r-md);\\n background: var(--panel);\\n overflow: hidden;\\n}\\n\\n.omnibox-input {\\n flex: 1 1 auto;\\n min-width: 0;\\n border: 0;\\n background: transparent;\\n color: var(--ink);\\n font: 400 16px/1.2 var(--sans);\\n padding: 14px 14px;\\n outline: none;\\n}\\n\\n.omnibox-input:focus-visible {\\n outline: none;\\n}\\n\\n.omnibox-outer:focus-within .omnibox-row {\\n box-shadow: var(--glow);\\n}\\n\\n.omnibox-chip {\\n display: flex;\\n align-items: center;\\n padding: 0 0 0 16px;\\n flex: 0 0 auto;\\n}\\n\\n.omnibox-chip-label,\\n.omnibox-chip-select {\\n font: 400 12px/1 var(--mono);\\n letter-spacing: 0.08em;\\n text-transform: uppercase;\\n color: var(--ink-2);\\n background: transparent;\\n border: 0;\\n}\\n\\n.omnibox-run {\\n flex: 0 0 auto;\\n display: inline-flex;\\n align-items: center;\\n gap: 8px;\\n margin: 6px;\\n padding: 8px 18px;\\n border-radius: var(--r-sm);\\n border: 1px solid var(--line);\\n background: var(--bg);\\n color: var(--ink);\\n font: 700 14px/1 var(--sans);\\n text-decoration: none;\\n cursor: pointer;\\n align-self: center;\\n}\\n\\n.omnibox-run-arrow {\\n font-family: var(--mono);\\n}\\n\\n.omnibox--hero .omnibox-run:not([aria-disabled='true']),\\n.omnibox--new .omnibox-run:not([aria-disabled='true']) {\\n border: 0;\\n color: #16101a;\\n background-image: var(--grad-btn);\\n}\\n\\n.omnibox-run[aria-disabled='true'] {\\n opacity: 0.55;\\n cursor: default;\\n}\\n\\n.omnibox-helper {\\n margin: 8px 2px 0;\\n font: 400 12px/1.4 var(--mono);\\n color: var(--ink-2);\\n}\\n\\n/* ── results panel ─────────────────────────────────────────────────────── */\\n\\n.omnibox-panel {\\n border: 1px solid var(--line);\\n border-radius: var(--r-md);\\n background: var(--bg);\\n margin-top: 8px;\\n padding: 6px;\\n /* in-flow by default: it pushes content down (mobile + hero + new) */\\n}\\n\\n.omnibox-group {\\n padding: 4px 0;\\n}\\n\\n.omnibox-group + .omnibox-group {\\n border-top: 1px solid var(--line);\\n}\\n\\n.omnibox-option {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: baseline;\\n gap: 4px 10px;\\n padding: 10px 12px;\\n border-radius: var(--r-xs);\\n color: var(--ink);\\n text-decoration: none;\\n cursor: pointer;\\n}\\n\\n.omnibox-option[aria-selected='true'],\\n.omnibox-option:hover {\\n background: var(--line);\\n}\\n\\n.omnibox-option-name {\\n font-weight: 600;\\n font-size: 15px;\\n}\\n\\n.omnibox-option-cat {\\n font: 400 11px/1 var(--mono);\\n letter-spacing: 0.08em;\\n text-transform: uppercase;\\n color: var(--ink-2);\\n}\\n\\n.omnibox-option-blurb {\\n flex-basis: 100%;\\n font-size: 13px;\\n color: var(--ink-2);\\n}\\n\\n.omnibox-option-action {\\n margin-left: auto;\\n font: 400 12px/1 var(--mono);\\n color: var(--ink-2);\\n}\\n\\n.omnibox-empty {\\n padding: 14px 12px;\\n color: var(--ink-2);\\n font-size: 14px;\\n}\\n\\n/* ── nav variant (desktop): floating field + shadowed panel ────────────── */\\n\\n.omnibox-outer--nav {\\n position: relative;\\n width: 230px;\\n}\\n\\n.omnibox-outer--nav .omnibox-row {\\n border-color: var(--line);\\n border-radius: var(--r-sm);\\n}\\n\\n.omnibox-outer--nav .omnibox-input {\\n padding: 9px 12px;\\n font-size: 14px;\\n}\\n\\n.omnibox-outer--nav .omnibox-helper {\\n display: none;\\n}\\n\\n.omnibox-outer--nav .omnibox-panel {\\n position: absolute;\\n top: calc(100% + 8px);\\n left: 0;\\n right: 0;\\n box-shadow: var(--shadow-pop);\\n z-index: 30;\\n}\\n\\n.omnibox-nav-button {\\n display: inline-flex;\\n align-items: center;\\n gap: 8px;\\n border: 1px solid var(--line);\\n border-radius: var(--r-sm);\\n background: transparent;\\n color: var(--ink);\\n font: 400 14px/1 var(--sans);\\n padding: 9px 12px;\\n cursor: pointer;\\n}\\n\\n.omnibox-nav-button .omnibox-nav-button-label {\\n color: var(--ink-2);\\n}\\n\\n/* ── mobile (FRONT_DOOR_IA §5.5): full width, chip collapses into the field's\\n left padding, Run is an in-field 44px arrow, panel in-flow ───────────── */\\n\\n@media (max-width: 720px) {\\n .omnibox-outer--nav {\\n width: 100%;\\n }\\n\\n .omnibox-chip {\\n display: none;\\n }\\n\\n .omnibox-input {\\n padding-left: 16px;\\n }\\n\\n .omnibox-run {\\n margin: 5px;\\n padding: 0;\\n width: 44px;\\n height: 44px;\\n justify-content: center;\\n gap: 0;\\n }\\n\\n .omnibox-run-label {\\n display: none;\\n }\\n\\n .omnibox-run-arrow {\\n font-size: 20px;\\n }\\n\\n .omnibox-outer--nav .omnibox-helper {\\n display: block;\\n }\\n\\n .omnibox-outer--nav .omnibox-panel {\\n position: static;\\n box-shadow: none;\\n }\\n}\\n\\n/* The visually hidden label / live region: present to assistive tech, absent\\n to the eye. Scoped here so the omnibox owns its own a11y plumbing. */\\n.omnibox-visually-hidden {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n margin: -1px;\\n padding: 0;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n border: 0;\\n}\\n\\n/* The keyboard-hint chip the omnibox and the nav shortcut render (R3-512). Moved\\n * verbatim from landing-page App.css with the component that renders it — one home,\\n * so the Home app renders the same chip. */\\n.kbd{font:400 11px var(--mono);background:var(--bg);border:1px solid var(--line);\\n border-radius:var(--r-xs);padding:2px 6px;color:var(--ink-3)}\\n\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,cAAc;","names":[]}
@@ -0,0 +1,3 @@
1
+ declare const OMNIBOX_CSS = "/* The omnibox (R3-512; FRONT_DOOR_IA \u00A75). Tokens come from index.css only; the\n floating results panel (desktop nav variant) is the only shadowed form \u2014\n hero, new, and every mobile form are in-flow and carry no shadow. */\n\n.omnibox-outer {\n width: 100%;\n}\n\n.omnibox-outer--hero,\n.omnibox-outer--new {\n max-width: 620px;\n}\n\n.omnibox-row {\n display: flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--line);\n border-color: var(--accent);\n border-radius: var(--r-md);\n background: var(--panel);\n overflow: hidden;\n}\n\n.omnibox-input {\n flex: 1 1 auto;\n min-width: 0;\n border: 0;\n background: transparent;\n color: var(--ink);\n font: 400 16px/1.2 var(--sans);\n padding: 14px 14px;\n outline: none;\n}\n\n.omnibox-input:focus-visible {\n outline: none;\n}\n\n.omnibox-outer:focus-within .omnibox-row {\n box-shadow: var(--glow);\n}\n\n.omnibox-chip {\n display: flex;\n align-items: center;\n padding: 0 0 0 16px;\n flex: 0 0 auto;\n}\n\n.omnibox-chip-label,\n.omnibox-chip-select {\n font: 400 12px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n background: transparent;\n border: 0;\n}\n\n.omnibox-run {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin: 6px;\n padding: 8px 18px;\n border-radius: var(--r-sm);\n border: 1px solid var(--line);\n background: var(--bg);\n color: var(--ink);\n font: 700 14px/1 var(--sans);\n text-decoration: none;\n cursor: pointer;\n align-self: center;\n}\n\n.omnibox-run-arrow {\n font-family: var(--mono);\n}\n\n.omnibox--hero .omnibox-run:not([aria-disabled='true']),\n.omnibox--new .omnibox-run:not([aria-disabled='true']) {\n border: 0;\n color: #16101a;\n background-image: var(--grad-btn);\n}\n\n.omnibox-run[aria-disabled='true'] {\n opacity: 0.55;\n cursor: default;\n}\n\n.omnibox-helper {\n margin: 8px 2px 0;\n font: 400 12px/1.4 var(--mono);\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 results panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-panel {\n border: 1px solid var(--line);\n border-radius: var(--r-md);\n background: var(--bg);\n margin-top: 8px;\n padding: 6px;\n /* in-flow by default: it pushes content down (mobile + hero + new) */\n}\n\n.omnibox-group {\n padding: 4px 0;\n}\n\n.omnibox-group + .omnibox-group {\n border-top: 1px solid var(--line);\n}\n\n.omnibox-option {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 4px 10px;\n padding: 10px 12px;\n border-radius: var(--r-xs);\n color: var(--ink);\n text-decoration: none;\n cursor: pointer;\n}\n\n.omnibox-option[aria-selected='true'],\n.omnibox-option:hover {\n background: var(--line);\n}\n\n.omnibox-option-name {\n font-weight: 600;\n font-size: 15px;\n}\n\n.omnibox-option-cat {\n font: 400 11px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n}\n\n.omnibox-option-blurb {\n flex-basis: 100%;\n font-size: 13px;\n color: var(--ink-2);\n}\n\n.omnibox-option-action {\n margin-left: auto;\n font: 400 12px/1 var(--mono);\n color: var(--ink-2);\n}\n\n.omnibox-empty {\n padding: 14px 12px;\n color: var(--ink-2);\n font-size: 14px;\n}\n\n/* \u2500\u2500 nav variant (desktop): floating field + shadowed panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-outer--nav {\n position: relative;\n width: 230px;\n}\n\n.omnibox-outer--nav .omnibox-row {\n border-color: var(--line);\n border-radius: var(--r-sm);\n}\n\n.omnibox-outer--nav .omnibox-input {\n padding: 9px 12px;\n font-size: 14px;\n}\n\n.omnibox-outer--nav .omnibox-helper {\n display: none;\n}\n\n.omnibox-outer--nav .omnibox-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n right: 0;\n box-shadow: var(--shadow-pop);\n z-index: 30;\n}\n\n.omnibox-nav-button {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: 1px solid var(--line);\n border-radius: var(--r-sm);\n background: transparent;\n color: var(--ink);\n font: 400 14px/1 var(--sans);\n padding: 9px 12px;\n cursor: pointer;\n}\n\n.omnibox-nav-button .omnibox-nav-button-label {\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 mobile (FRONT_DOOR_IA \u00A75.5): full width, chip collapses into the field's\n left padding, Run is an in-field 44px arrow, panel in-flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@media (max-width: 720px) {\n .omnibox-outer--nav {\n width: 100%;\n }\n\n .omnibox-chip {\n display: none;\n }\n\n .omnibox-input {\n padding-left: 16px;\n }\n\n .omnibox-run {\n margin: 5px;\n padding: 0;\n width: 44px;\n height: 44px;\n justify-content: center;\n gap: 0;\n }\n\n .omnibox-run-label {\n display: none;\n }\n\n .omnibox-run-arrow {\n font-size: 20px;\n }\n\n .omnibox-outer--nav .omnibox-helper {\n display: block;\n }\n\n .omnibox-outer--nav .omnibox-panel {\n position: static;\n box-shadow: none;\n }\n}\n\n/* The visually hidden label / live region: present to assistive tech, absent\n to the eye. Scoped here so the omnibox owns its own a11y plumbing. */\n.omnibox-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* The keyboard-hint chip the omnibox and the nav shortcut render (R3-512). Moved\n * verbatim from landing-page App.css with the component that renders it \u2014 one home,\n * so the Home app renders the same chip. */\n.kbd{font:400 11px var(--mono);background:var(--bg);border:1px solid var(--line);\n border-radius:var(--r-xs);padding:2px 6px;color:var(--ink-3)}\n";
2
+
3
+ export { OMNIBOX_CSS };
@@ -0,0 +1,3 @@
1
+ declare const OMNIBOX_CSS = "/* The omnibox (R3-512; FRONT_DOOR_IA \u00A75). Tokens come from index.css only; the\n floating results panel (desktop nav variant) is the only shadowed form \u2014\n hero, new, and every mobile form are in-flow and carry no shadow. */\n\n.omnibox-outer {\n width: 100%;\n}\n\n.omnibox-outer--hero,\n.omnibox-outer--new {\n max-width: 620px;\n}\n\n.omnibox-row {\n display: flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--line);\n border-color: var(--accent);\n border-radius: var(--r-md);\n background: var(--panel);\n overflow: hidden;\n}\n\n.omnibox-input {\n flex: 1 1 auto;\n min-width: 0;\n border: 0;\n background: transparent;\n color: var(--ink);\n font: 400 16px/1.2 var(--sans);\n padding: 14px 14px;\n outline: none;\n}\n\n.omnibox-input:focus-visible {\n outline: none;\n}\n\n.omnibox-outer:focus-within .omnibox-row {\n box-shadow: var(--glow);\n}\n\n.omnibox-chip {\n display: flex;\n align-items: center;\n padding: 0 0 0 16px;\n flex: 0 0 auto;\n}\n\n.omnibox-chip-label,\n.omnibox-chip-select {\n font: 400 12px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n background: transparent;\n border: 0;\n}\n\n.omnibox-run {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin: 6px;\n padding: 8px 18px;\n border-radius: var(--r-sm);\n border: 1px solid var(--line);\n background: var(--bg);\n color: var(--ink);\n font: 700 14px/1 var(--sans);\n text-decoration: none;\n cursor: pointer;\n align-self: center;\n}\n\n.omnibox-run-arrow {\n font-family: var(--mono);\n}\n\n.omnibox--hero .omnibox-run:not([aria-disabled='true']),\n.omnibox--new .omnibox-run:not([aria-disabled='true']) {\n border: 0;\n color: #16101a;\n background-image: var(--grad-btn);\n}\n\n.omnibox-run[aria-disabled='true'] {\n opacity: 0.55;\n cursor: default;\n}\n\n.omnibox-helper {\n margin: 8px 2px 0;\n font: 400 12px/1.4 var(--mono);\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 results panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-panel {\n border: 1px solid var(--line);\n border-radius: var(--r-md);\n background: var(--bg);\n margin-top: 8px;\n padding: 6px;\n /* in-flow by default: it pushes content down (mobile + hero + new) */\n}\n\n.omnibox-group {\n padding: 4px 0;\n}\n\n.omnibox-group + .omnibox-group {\n border-top: 1px solid var(--line);\n}\n\n.omnibox-option {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 4px 10px;\n padding: 10px 12px;\n border-radius: var(--r-xs);\n color: var(--ink);\n text-decoration: none;\n cursor: pointer;\n}\n\n.omnibox-option[aria-selected='true'],\n.omnibox-option:hover {\n background: var(--line);\n}\n\n.omnibox-option-name {\n font-weight: 600;\n font-size: 15px;\n}\n\n.omnibox-option-cat {\n font: 400 11px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n}\n\n.omnibox-option-blurb {\n flex-basis: 100%;\n font-size: 13px;\n color: var(--ink-2);\n}\n\n.omnibox-option-action {\n margin-left: auto;\n font: 400 12px/1 var(--mono);\n color: var(--ink-2);\n}\n\n.omnibox-empty {\n padding: 14px 12px;\n color: var(--ink-2);\n font-size: 14px;\n}\n\n/* \u2500\u2500 nav variant (desktop): floating field + shadowed panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-outer--nav {\n position: relative;\n width: 230px;\n}\n\n.omnibox-outer--nav .omnibox-row {\n border-color: var(--line);\n border-radius: var(--r-sm);\n}\n\n.omnibox-outer--nav .omnibox-input {\n padding: 9px 12px;\n font-size: 14px;\n}\n\n.omnibox-outer--nav .omnibox-helper {\n display: none;\n}\n\n.omnibox-outer--nav .omnibox-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n right: 0;\n box-shadow: var(--shadow-pop);\n z-index: 30;\n}\n\n.omnibox-nav-button {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: 1px solid var(--line);\n border-radius: var(--r-sm);\n background: transparent;\n color: var(--ink);\n font: 400 14px/1 var(--sans);\n padding: 9px 12px;\n cursor: pointer;\n}\n\n.omnibox-nav-button .omnibox-nav-button-label {\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 mobile (FRONT_DOOR_IA \u00A75.5): full width, chip collapses into the field's\n left padding, Run is an in-field 44px arrow, panel in-flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@media (max-width: 720px) {\n .omnibox-outer--nav {\n width: 100%;\n }\n\n .omnibox-chip {\n display: none;\n }\n\n .omnibox-input {\n padding-left: 16px;\n }\n\n .omnibox-run {\n margin: 5px;\n padding: 0;\n width: 44px;\n height: 44px;\n justify-content: center;\n gap: 0;\n }\n\n .omnibox-run-label {\n display: none;\n }\n\n .omnibox-run-arrow {\n font-size: 20px;\n }\n\n .omnibox-outer--nav .omnibox-helper {\n display: block;\n }\n\n .omnibox-outer--nav .omnibox-panel {\n position: static;\n box-shadow: none;\n }\n}\n\n/* The visually hidden label / live region: present to assistive tech, absent\n to the eye. Scoped here so the omnibox owns its own a11y plumbing. */\n.omnibox-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* The keyboard-hint chip the omnibox and the nav shortcut render (R3-512). Moved\n * verbatim from landing-page App.css with the component that renders it \u2014 one home,\n * so the Home app renders the same chip. */\n.kbd{font:400 11px var(--mono);background:var(--bg);border:1px solid var(--line);\n border-radius:var(--r-xs);padding:2px 6px;color:var(--ink-3)}\n";
2
+
3
+ export { OMNIBOX_CSS };
@@ -0,0 +1,5 @@
1
+ const OMNIBOX_CSS = "/* The omnibox (R3-512; FRONT_DOOR_IA \xA75). Tokens come from index.css only; the\n floating results panel (desktop nav variant) is the only shadowed form \u2014\n hero, new, and every mobile form are in-flow and carry no shadow. */\n\n.omnibox-outer {\n width: 100%;\n}\n\n.omnibox-outer--hero,\n.omnibox-outer--new {\n max-width: 620px;\n}\n\n.omnibox-row {\n display: flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--line);\n border-color: var(--accent);\n border-radius: var(--r-md);\n background: var(--panel);\n overflow: hidden;\n}\n\n.omnibox-input {\n flex: 1 1 auto;\n min-width: 0;\n border: 0;\n background: transparent;\n color: var(--ink);\n font: 400 16px/1.2 var(--sans);\n padding: 14px 14px;\n outline: none;\n}\n\n.omnibox-input:focus-visible {\n outline: none;\n}\n\n.omnibox-outer:focus-within .omnibox-row {\n box-shadow: var(--glow);\n}\n\n.omnibox-chip {\n display: flex;\n align-items: center;\n padding: 0 0 0 16px;\n flex: 0 0 auto;\n}\n\n.omnibox-chip-label,\n.omnibox-chip-select {\n font: 400 12px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n background: transparent;\n border: 0;\n}\n\n.omnibox-run {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin: 6px;\n padding: 8px 18px;\n border-radius: var(--r-sm);\n border: 1px solid var(--line);\n background: var(--bg);\n color: var(--ink);\n font: 700 14px/1 var(--sans);\n text-decoration: none;\n cursor: pointer;\n align-self: center;\n}\n\n.omnibox-run-arrow {\n font-family: var(--mono);\n}\n\n.omnibox--hero .omnibox-run:not([aria-disabled='true']),\n.omnibox--new .omnibox-run:not([aria-disabled='true']) {\n border: 0;\n color: #16101a;\n background-image: var(--grad-btn);\n}\n\n.omnibox-run[aria-disabled='true'] {\n opacity: 0.55;\n cursor: default;\n}\n\n.omnibox-helper {\n margin: 8px 2px 0;\n font: 400 12px/1.4 var(--mono);\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 results panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-panel {\n border: 1px solid var(--line);\n border-radius: var(--r-md);\n background: var(--bg);\n margin-top: 8px;\n padding: 6px;\n /* in-flow by default: it pushes content down (mobile + hero + new) */\n}\n\n.omnibox-group {\n padding: 4px 0;\n}\n\n.omnibox-group + .omnibox-group {\n border-top: 1px solid var(--line);\n}\n\n.omnibox-option {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 4px 10px;\n padding: 10px 12px;\n border-radius: var(--r-xs);\n color: var(--ink);\n text-decoration: none;\n cursor: pointer;\n}\n\n.omnibox-option[aria-selected='true'],\n.omnibox-option:hover {\n background: var(--line);\n}\n\n.omnibox-option-name {\n font-weight: 600;\n font-size: 15px;\n}\n\n.omnibox-option-cat {\n font: 400 11px/1 var(--mono);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ink-2);\n}\n\n.omnibox-option-blurb {\n flex-basis: 100%;\n font-size: 13px;\n color: var(--ink-2);\n}\n\n.omnibox-option-action {\n margin-left: auto;\n font: 400 12px/1 var(--mono);\n color: var(--ink-2);\n}\n\n.omnibox-empty {\n padding: 14px 12px;\n color: var(--ink-2);\n font-size: 14px;\n}\n\n/* \u2500\u2500 nav variant (desktop): floating field + shadowed panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.omnibox-outer--nav {\n position: relative;\n width: 230px;\n}\n\n.omnibox-outer--nav .omnibox-row {\n border-color: var(--line);\n border-radius: var(--r-sm);\n}\n\n.omnibox-outer--nav .omnibox-input {\n padding: 9px 12px;\n font-size: 14px;\n}\n\n.omnibox-outer--nav .omnibox-helper {\n display: none;\n}\n\n.omnibox-outer--nav .omnibox-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n right: 0;\n box-shadow: var(--shadow-pop);\n z-index: 30;\n}\n\n.omnibox-nav-button {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: 1px solid var(--line);\n border-radius: var(--r-sm);\n background: transparent;\n color: var(--ink);\n font: 400 14px/1 var(--sans);\n padding: 9px 12px;\n cursor: pointer;\n}\n\n.omnibox-nav-button .omnibox-nav-button-label {\n color: var(--ink-2);\n}\n\n/* \u2500\u2500 mobile (FRONT_DOOR_IA \xA75.5): full width, chip collapses into the field's\n left padding, Run is an in-field 44px arrow, panel in-flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@media (max-width: 720px) {\n .omnibox-outer--nav {\n width: 100%;\n }\n\n .omnibox-chip {\n display: none;\n }\n\n .omnibox-input {\n padding-left: 16px;\n }\n\n .omnibox-run {\n margin: 5px;\n padding: 0;\n width: 44px;\n height: 44px;\n justify-content: center;\n gap: 0;\n }\n\n .omnibox-run-label {\n display: none;\n }\n\n .omnibox-run-arrow {\n font-size: 20px;\n }\n\n .omnibox-outer--nav .omnibox-helper {\n display: block;\n }\n\n .omnibox-outer--nav .omnibox-panel {\n position: static;\n box-shadow: none;\n }\n}\n\n/* The visually hidden label / live region: present to assistive tech, absent\n to the eye. Scoped here so the omnibox owns its own a11y plumbing. */\n.omnibox-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* The keyboard-hint chip the omnibox and the nav shortcut render (R3-512). Moved\n * verbatim from landing-page App.css with the component that renders it \u2014 one home,\n * so the Home app renders the same chip. */\n.kbd{font:400 11px var(--mono);background:var(--bg);border:1px solid var(--line);\n border-radius:var(--r-xs);padding:2px 6px;color:var(--ink-3)}\n";
2
+ export {
3
+ OMNIBOX_CSS
4
+ };
5
+ //# sourceMappingURL=omniboxStyles.generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/omniboxStyles.generated.ts"],"sourcesContent":["// GENERATED by scripts/build-css.mjs from src/omnibox.css — do not edit by hand.\n// Committed so tests and `tsc` see it without a build step; `npm run check:css-parity`\n// fails when it drifts. See that script for why the styles ship as a string.\n\nexport const OMNIBOX_CSS = \"/* The omnibox (R3-512; FRONT_DOOR_IA §5). Tokens come from index.css only; the\\n floating results panel (desktop nav variant) is the only shadowed form —\\n hero, new, and every mobile form are in-flow and carry no shadow. */\\n\\n.omnibox-outer {\\n width: 100%;\\n}\\n\\n.omnibox-outer--hero,\\n.omnibox-outer--new {\\n max-width: 620px;\\n}\\n\\n.omnibox-row {\\n display: flex;\\n align-items: stretch;\\n gap: 0;\\n border: 1px solid var(--line);\\n border-color: var(--accent);\\n border-radius: var(--r-md);\\n background: var(--panel);\\n overflow: hidden;\\n}\\n\\n.omnibox-input {\\n flex: 1 1 auto;\\n min-width: 0;\\n border: 0;\\n background: transparent;\\n color: var(--ink);\\n font: 400 16px/1.2 var(--sans);\\n padding: 14px 14px;\\n outline: none;\\n}\\n\\n.omnibox-input:focus-visible {\\n outline: none;\\n}\\n\\n.omnibox-outer:focus-within .omnibox-row {\\n box-shadow: var(--glow);\\n}\\n\\n.omnibox-chip {\\n display: flex;\\n align-items: center;\\n padding: 0 0 0 16px;\\n flex: 0 0 auto;\\n}\\n\\n.omnibox-chip-label,\\n.omnibox-chip-select {\\n font: 400 12px/1 var(--mono);\\n letter-spacing: 0.08em;\\n text-transform: uppercase;\\n color: var(--ink-2);\\n background: transparent;\\n border: 0;\\n}\\n\\n.omnibox-run {\\n flex: 0 0 auto;\\n display: inline-flex;\\n align-items: center;\\n gap: 8px;\\n margin: 6px;\\n padding: 8px 18px;\\n border-radius: var(--r-sm);\\n border: 1px solid var(--line);\\n background: var(--bg);\\n color: var(--ink);\\n font: 700 14px/1 var(--sans);\\n text-decoration: none;\\n cursor: pointer;\\n align-self: center;\\n}\\n\\n.omnibox-run-arrow {\\n font-family: var(--mono);\\n}\\n\\n.omnibox--hero .omnibox-run:not([aria-disabled='true']),\\n.omnibox--new .omnibox-run:not([aria-disabled='true']) {\\n border: 0;\\n color: #16101a;\\n background-image: var(--grad-btn);\\n}\\n\\n.omnibox-run[aria-disabled='true'] {\\n opacity: 0.55;\\n cursor: default;\\n}\\n\\n.omnibox-helper {\\n margin: 8px 2px 0;\\n font: 400 12px/1.4 var(--mono);\\n color: var(--ink-2);\\n}\\n\\n/* ── results panel ─────────────────────────────────────────────────────── */\\n\\n.omnibox-panel {\\n border: 1px solid var(--line);\\n border-radius: var(--r-md);\\n background: var(--bg);\\n margin-top: 8px;\\n padding: 6px;\\n /* in-flow by default: it pushes content down (mobile + hero + new) */\\n}\\n\\n.omnibox-group {\\n padding: 4px 0;\\n}\\n\\n.omnibox-group + .omnibox-group {\\n border-top: 1px solid var(--line);\\n}\\n\\n.omnibox-option {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: baseline;\\n gap: 4px 10px;\\n padding: 10px 12px;\\n border-radius: var(--r-xs);\\n color: var(--ink);\\n text-decoration: none;\\n cursor: pointer;\\n}\\n\\n.omnibox-option[aria-selected='true'],\\n.omnibox-option:hover {\\n background: var(--line);\\n}\\n\\n.omnibox-option-name {\\n font-weight: 600;\\n font-size: 15px;\\n}\\n\\n.omnibox-option-cat {\\n font: 400 11px/1 var(--mono);\\n letter-spacing: 0.08em;\\n text-transform: uppercase;\\n color: var(--ink-2);\\n}\\n\\n.omnibox-option-blurb {\\n flex-basis: 100%;\\n font-size: 13px;\\n color: var(--ink-2);\\n}\\n\\n.omnibox-option-action {\\n margin-left: auto;\\n font: 400 12px/1 var(--mono);\\n color: var(--ink-2);\\n}\\n\\n.omnibox-empty {\\n padding: 14px 12px;\\n color: var(--ink-2);\\n font-size: 14px;\\n}\\n\\n/* ── nav variant (desktop): floating field + shadowed panel ────────────── */\\n\\n.omnibox-outer--nav {\\n position: relative;\\n width: 230px;\\n}\\n\\n.omnibox-outer--nav .omnibox-row {\\n border-color: var(--line);\\n border-radius: var(--r-sm);\\n}\\n\\n.omnibox-outer--nav .omnibox-input {\\n padding: 9px 12px;\\n font-size: 14px;\\n}\\n\\n.omnibox-outer--nav .omnibox-helper {\\n display: none;\\n}\\n\\n.omnibox-outer--nav .omnibox-panel {\\n position: absolute;\\n top: calc(100% + 8px);\\n left: 0;\\n right: 0;\\n box-shadow: var(--shadow-pop);\\n z-index: 30;\\n}\\n\\n.omnibox-nav-button {\\n display: inline-flex;\\n align-items: center;\\n gap: 8px;\\n border: 1px solid var(--line);\\n border-radius: var(--r-sm);\\n background: transparent;\\n color: var(--ink);\\n font: 400 14px/1 var(--sans);\\n padding: 9px 12px;\\n cursor: pointer;\\n}\\n\\n.omnibox-nav-button .omnibox-nav-button-label {\\n color: var(--ink-2);\\n}\\n\\n/* ── mobile (FRONT_DOOR_IA §5.5): full width, chip collapses into the field's\\n left padding, Run is an in-field 44px arrow, panel in-flow ───────────── */\\n\\n@media (max-width: 720px) {\\n .omnibox-outer--nav {\\n width: 100%;\\n }\\n\\n .omnibox-chip {\\n display: none;\\n }\\n\\n .omnibox-input {\\n padding-left: 16px;\\n }\\n\\n .omnibox-run {\\n margin: 5px;\\n padding: 0;\\n width: 44px;\\n height: 44px;\\n justify-content: center;\\n gap: 0;\\n }\\n\\n .omnibox-run-label {\\n display: none;\\n }\\n\\n .omnibox-run-arrow {\\n font-size: 20px;\\n }\\n\\n .omnibox-outer--nav .omnibox-helper {\\n display: block;\\n }\\n\\n .omnibox-outer--nav .omnibox-panel {\\n position: static;\\n box-shadow: none;\\n }\\n}\\n\\n/* The visually hidden label / live region: present to assistive tech, absent\\n to the eye. Scoped here so the omnibox owns its own a11y plumbing. */\\n.omnibox-visually-hidden {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n margin: -1px;\\n padding: 0;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n border: 0;\\n}\\n\\n/* The keyboard-hint chip the omnibox and the nav shortcut render (R3-512). Moved\\n * verbatim from landing-page App.css with the component that renders it — one home,\\n * so the Home app renders the same chip. */\\n.kbd{font:400 11px var(--mono);background:var(--bg);border:1px solid var(--line);\\n border-radius:var(--r-xs);padding:2px 6px;color:var(--ink-3)}\\n\";\n"],"mappings":"AAIO,MAAM,cAAc;","names":[]}
@@ -0,0 +1,21 @@
1
+ import { OMNIBOX_CSS } from "./omniboxStyles.generated";
2
+ const STYLE_ID = "immediately-run-omnibox-css";
3
+ function ensureOmniboxStyles() {
4
+ try {
5
+ if (typeof document === "undefined") return;
6
+ if (document.getElementById(STYLE_ID)) return;
7
+ const style = document.createElement("style");
8
+ style.id = STYLE_ID;
9
+ style.textContent = OMNIBOX_CSS;
10
+ (document.head ?? document.documentElement).appendChild(style);
11
+ } catch (err) {
12
+ try {
13
+ console.warn("[omnibox] could not inject the stylesheet; rendering unstyled.", err);
14
+ } catch {
15
+ }
16
+ }
17
+ }
18
+ export {
19
+ ensureOmniboxStyles
20
+ };
21
+ //# sourceMappingURL=omniboxStyles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/omniboxStyles.ts"],"sourcesContent":["// Injecting the omnibox's stylesheet from JS, once per document.\n//\n// WHY NOT `import './omnibox.css'`. That is what the package shipped until 2026-09-08,\n// and on immediately.run it took down the front door. The sandbox bundler followed the\n// specifier out of the resolved package, fetched the stylesheet, and evaluated it as\n// JAVASCRIPT: `SyntaxError: Unexpected token '.'` on the first selector, the whole app\n// dead behind it, prod and local alike. An app's OWN `.css` import works there; a\n// dependency's did not, and this package cannot make a consumer's bundler grow a CSS\n// loader. JS is the one thing every consumer can execute, so the styles ship as JS.\n//\n// `dist/omnibox.css` is still published and still exported at `./omnibox.css`, for a\n// consumer that would rather own the cascade — importing it as well is harmless (the\n// rules are identical and idempotent), it just is not required any more.\nimport { OMNIBOX_CSS } from './omniboxStyles.generated';\n\n/** Marks the injected element, and makes a second injection a no-op. */\nconst STYLE_ID = 'immediately-run-omnibox-css';\n\n/**\n * Ensure the omnibox stylesheet is in `document`. Idempotent, and safe to call from\n * render: it writes nothing when the element is already there.\n *\n * Deliberately defensive rather than clever:\n * - **no `document` is not an error.** SSR and any non-DOM renderer simply get no\n * styles rather than a crash on import, and this module is imported at module scope.\n * - **a throwing DOM is not an error either.** Some embeddings forbid injecting a\n * style element; an unstyled combobox is a bad outcome, a dead app is a worse one,\n * and the caller has no way to recover from either.\n * - the element carries an `id`, so a second copy of this package on the page (a\n * version skew in one consumer's tree) styles the DOM once, not twice.\n */\nexport function ensureOmniboxStyles(): void {\n try {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = OMNIBOX_CSS;\n (document.head ?? document.documentElement).appendChild(style);\n } catch (err) {\n // Unstyled beats dead — but silent beats neither. Three different failures land here\n // (no `head` or `documentElement`, an embedding that refuses `createElement('style')`,\n // a refused `textContent` assignment) and without this they are indistinguishable\n // from \"the styles are fine\", which is how an unstyled combobox goes unreported.\n // `console.warn` and not `throw`: the caller can recover from neither outcome.\n try {\n console.warn('[omnibox] could not inject the stylesheet; rendering unstyled.', err);\n } catch {\n /* a console that throws must not be the thing that breaks the render. */\n }\n }\n}\n"],"mappings":"AAaA,SAAS,mBAAmB;AAG5B,MAAM,WAAW;AAeV,SAAS,sBAA4B;AAC1C,MAAI;AACF,QAAI,OAAO,aAAa,YAAa;AACrC,QAAI,SAAS,eAAe,QAAQ,EAAG;AACvC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AACpB,KAAC,SAAS,QAAQ,SAAS,iBAAiB,YAAY,KAAK;AAAA,EAC/D,SAAS,KAAK;AAMZ,QAAI;AACF,cAAQ,KAAK,kEAAkE,GAAG;AAAA,IACpF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immediately-run/omnibox",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "The front door's omnibox: one list-autocomplete combobox that runs a repo by URL or tuple and searches a consumer's app directory and docs (the launch grammar always; the hit sources injected). Shared by landing-page and the Home app so there is one component and one grammar (R3-512, R3-530).",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -23,15 +23,21 @@
23
23
  "dist"
24
24
  ],
25
25
  "sideEffects": [
26
- "*.css"
26
+ "*.css",
27
+ "dist/Omnibox.js",
28
+ "dist/Omnibox.cjs",
29
+ "src/Omnibox.tsx"
27
30
  ],
28
31
  "scripts": {
29
- "build": "tsup && node scripts/build-css.mjs",
32
+ "build": "node scripts/build-css.mjs && tsup && node scripts/build-css.mjs --dist",
30
33
  "test": "vitest run",
31
34
  "lint": "eslint src",
32
35
  "prepare": "npm run build",
33
36
  "check:pins": "node scripts/check-dependency-pins.mjs --self-test && node scripts/check-dependency-pins.mjs",
34
- "check:publish-version": "node scripts/check-publish-version.mjs --self-test && node scripts/check-publish-version.mjs"
37
+ "check:publish-version": "node scripts/check-publish-version.mjs --self-test && node scripts/check-publish-version.mjs",
38
+ "build:css": "node scripts/build-css.mjs",
39
+ "check:css-parity": "node scripts/check-css-parity.mjs --self-test && node scripts/check-css-parity.mjs",
40
+ "check:no-css-import": "node scripts/check-no-css-import.mjs --self-test && node scripts/check-no-css-import.mjs"
35
41
  },
36
42
  "peerDependencies": {
37
43
  "@immediately-run/sdk": "0.60.0",