Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/base/card-api.gts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
type getCardCollection,
type Store,
type PrerenderedCardComponentSignature,
type SearchResultsComponentSignature,
type ErrorEntry,
type Query,
type QueryWithInterpolations,
Expand Down Expand Up @@ -344,7 +345,18 @@ export interface CardContext<T extends CardDef = CardDef> {
};
};
}>;
/**
* @deprecated Use {@link CardContext.searchResultsComponent} — the v2
* `<SearchResults>` surface. Retained (and still provided) during the
* migration window; first-party card source moves to the v2 surface via the
* `@context` search codemod, after which this is removed.
*/
prerenderedCardSearchComponent: typeof GlimmerComponent<PrerenderedCardComponentSignature>;
// The v2 search rendering surface: renders the heterogeneous `search-entry`
// stream for a `search-entry`-rooted query — prerendered HTML inert (hydrated
// lazily) or a live card — so a card author renders results without ever
// branching on prerendered-vs-live. Supersedes `prerenderedCardSearchComponent`.
searchResultsComponent: typeof GlimmerComponent<SearchResultsComponentSignature>;
getCard: getCard<T>;
getCards: getCards;
getCardCollection: getCardCollection;
Expand Down
10 changes: 5 additions & 5 deletions packages/host/app/components/card-search/hydratable-card.gts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
GetCardContextName,
type ErrorEntry,
type Format,
type HydrationMode,
type ResolvedCodeRef,
type StoreReadType,
type getCard,
Expand All @@ -24,11 +25,10 @@ import CardRenderer from '../card-renderer';

import SearchResultError from './search-result-error';

// How an HTML-backed search result becomes a live, running card. `none` stays
// inert; `hover` / `click` / `touch` fetch the card on the matching gesture and
// swap the inert HTML for a live `<CardRenderer>`. The mode is a host-side UX
// choice and never travels on the wire.
export type HydrationMode = 'none' | 'hover' | 'click' | 'touch';
// `HydrationMode` is the card-facing contract (it rides the v2 `@context`
// search surface), so it lives in runtime-common; re-exported here because this
// is where it's consumed and where call sites have long imported it.
export type { HydrationMode };

type CardComponentModifier = NonNullable<CardContext['cardComponentModifier']>;

Expand Down
33 changes: 3 additions & 30 deletions packages/host/app/components/card-search/search-results.gts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
type PrerenderedHtmlFormat,
type ResolvedCodeRef,
type Saved,
type SearchEntryCollectionDocument,
type SearchEntryWireQuery,
type SearchResultsComponentSignature,
type SearchResultsYield,
type StoreReadType,
} from '@cardstack/runtime-common';

Expand Down Expand Up @@ -188,33 +188,6 @@ class RenderableSearchEntry {
}
}

// The block argument: the heterogeneous result stream plus its loading/meta/
// error state. Mirrors the documented public API (`results.entries` /
// `.isLoading` / `.meta` / `.errors`).
export interface SearchResultsYield {
entries: RenderableSearchEntry[];
isLoading: boolean;
meta: SearchEntryCollectionDocument['meta'];
errors: ErrorEntry[] | undefined;
}

interface Signature {
Element: HTMLElement;
Args: {
// The `search-entry`-rooted v2 query. Re-issued live on invalidation;
// changing it re-runs the search. Undefined → idle (no results).
query: SearchEntryWireQuery | undefined;
// The hydration gesture for HTML-backed rows — a host-UX choice, never on
// the wire. A full live row ignores it. Defaults to `hover` (the fitted
// fast path); pass `none` to keep rows inert, `click`/`touch` to gate on
// those gestures.
mode?: HydrationMode;
};
Blocks: {
default: [SearchResultsYield];
};
}

// The one v2 search component family. Consumes the heterogeneous `search-entry`
// stream from `getSearchEntriesResource` and renders it transparently —
// prerendered HTML inert (the fast path, hydrated lazily on interaction) or the
Expand All @@ -223,7 +196,7 @@ interface Signature {
// the default stream of `entry.component`s itself. Additive: it supersedes the
// `prerendered-card-search` component and the live `SearchContent` tree as call
// sites migrate.
export default class SearchResults extends Component<Signature> {
export default class SearchResults extends Component<SearchResultsComponentSignature> {
@service declare private store: StoreService;

// Created once per component (the resource owns its own realm subscriptions
Expand Down
2 changes: 2 additions & 0 deletions packages/host/app/components/operator-mode/container.gts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import type MessageService from '@cardstack/host/services/message-service';
import type { CardContext } from 'https://cardstack.com/base/card-api';

import CardChooserModal from '../card-chooser/modal';
import SearchResults from '../card-search/search-results';
import PrerenderedCardSearch from '../prerendered-card-search';
import { Submodes } from '../submode-switcher';

Expand Down Expand Up @@ -108,6 +109,7 @@ export default class OperatorModeContainer extends Component<Signature> {
store: this.store,
commandContext: this.commandContext,
prerenderedCardSearchComponent: PrerenderedCardSearch,
searchResultsComponent: SearchResults,
mode: 'operator',
submode: this.operatorModeStateService.state?.submode,
};
Expand Down
26 changes: 5 additions & 21 deletions packages/host/app/resources/search-entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ import {
type ErrorEntry,
type FileMetaResource,
type HtmlResource,
type PrerenderedHtmlFormat,
type ResolvedCodeRef,
type Saved,
type SearchEntryCollectionDocument,
type SearchEntryRendering,
type SearchEntryWireQuery,
} from '@cardstack/runtime-common';

Expand All @@ -42,25 +41,10 @@ import type StoreService from '../services/store';

const waiter = buildWaiter('search-entries-resource:search-waiter');

// One rendering of an entry: the wire's `html` resource flattened, with its
// `styles` references resolved to the stylesheets' hrefs (the stylesheets
// themselves are already imported through the loader by the time entries are
// exposed). `id` is the (card URL, format, renderType) composite — an opaque
// cache key; the readable rendering dimensions are the `format`/`renderType`
// fields.
export interface SearchEntryRendering {
id: string;
// Absent only on an error rendering with no last-known-good HTML.
html?: string;
cardType: string;
iconHtml?: string;
isError: boolean;
format: PrerenderedHtmlFormat;
// The type this rendering was rendered as. A file rendering carries none
// (files render natively).
renderType?: ResolvedCodeRef;
cssUrls: string[];
}
// `SearchEntryRendering` is the card-facing rendering view-model (it rides the
// v2 `@context` search surface), so it lives in runtime-common; re-exported
// here because this resource builds it and call sites import it from here.
export type { SearchEntryRendering };

// One v2 search result, joined from the wire document: the `search-entry`
// resource plus the `html` renderings and/or `item` serialization it
Expand Down
2 changes: 2 additions & 0 deletions packages/host/app/templates/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
type getCard as GetCardType,
} from '@cardstack/runtime-common';

import SearchResults from '@cardstack/host/components/card-search/search-results';
import HostModeContent from '@cardstack/host/components/host-mode/content';
import OperatorModeContainer from '@cardstack/host/components/operator-mode/container';

Expand Down Expand Up @@ -148,6 +149,7 @@ export class IndexComponent extends Component<IndexComponentComponentSignature>
store: this.store,
commandContext: this.commandContext,
prerenderedCardSearchComponent: PrerenderedCardSearch,
searchResultsComponent: SearchResults,
mode: this.hostModeService.isActive ? 'host' : 'operator',
submode: this.hostModeService.isActive
? 'host'
Expand Down
2 changes: 2 additions & 0 deletions packages/host/app/templates/render/html.gts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
CardContextName,
} from '@cardstack/runtime-common';

import SearchResults from '@cardstack/host/components/card-search/search-results';
import PrerenderedCardSearch from '@cardstack/host/components/prerendered-card-search';
import { getCardCollection } from '@cardstack/host/resources/card-collection';
import { getCard } from '@cardstack/host/resources/card-resource';
Expand Down Expand Up @@ -56,6 +57,7 @@ class RenderHtmlTemplate extends Component<Signature> {
getCardCollection: this.getCardCollection,
store: this.store,
prerenderedCardSearchComponent: PrerenderedCardSearch,
searchResultsComponent: SearchResults,
Comment thread
habdelra marked this conversation as resolved.
mode: 'host',
submode: 'host',
};
Expand Down
Loading
Loading