@salesforce/ui-bundle-template-feature-react-global-search
v1.119.6
Published
Global search feature for Salesforce objects with filtering and pagination
Downloads
1,412
Maintainers
Keywords
Readme
Feature: React Global Search (Single Object)
This package is a reference implementation for adding global search (keyword search, filters, results list, and record detail) to a Salesforce UI Bundle. It provides API services, hooks, types/schemas, and utilities so you can build your own UI and import the data layer from the package—or optionally copy the reference UI from the package and adapt it.
Intended use (vibing model):
- Do not copy the feature source (api, hooks, types, utils).
- Build your own UI (recommended), or copy the reference pages/components from the package and adapt.
- Import data-layer pieces from the package: services, hooks, types, utilities.
UI components and feature constants are deliberately not exported from the public API.
What you get (public API)
Import from the package root:
import {
objectInfoService,
objectDetailService,
useObjectListMetadata,
useRecordListGraphQL,
useRecordDetailLayout,
useObjectColumns,
useObjectFilters,
useObjectInfoBatch,
type FilterCriteria,
parseFilterValue,
sanitizeFilterValue,
} from "@salesforce/ui-bundle-template-feature-react-global-search";API services
objectInfoServicegetObjectInfoBatch(objectApiNames)(GraphQL uiapi.objectInfos)getPicklistValues(objectApiName, fieldName, recordTypeId?)(GraphQL uiapi.objectInfos)getObjectListFilters(objectApiName)(REST search-info filters)
objectDetailServicegetLayout(objectApiName, recordTypeId?)(REST layout)getRecordDetail(objectApiName, recordId, recordTypeId?)(layout + object info + record)
- GraphQL record helpers
getRecordsGraphQL(...)(list query,first + after)getRecordByIdGraphQL(...)(single record by Id)buildWhereFromCriteria(...),buildOrderByFromSort(...),buildGetRecordsQuery(...)
Hooks
- List metadata:
useObjectListMetadata(objectApiName)— filters, columns (derived from filters), picklistValues. - List columns (legacy):
useObjectColumns(objectApiName)— columns, columnsLoading, columnsError. - List filters:
useObjectFilters(objectApiName)— filtersData (filters + picklist values per object). - List records:
useRecordListGraphQL({ objectApiName, first, after, filters, sortBy, searchQuery, columns? })— GraphQL list with cursor pagination. - Detail:
useRecordDetailLayout({ objectApiName, recordId, recordTypeId?, initialData? })— layout (REST) + object metadata + record (GraphQL). - Batch object info:
useObjectInfoBatch(objectApiNames)— objectInfos, loading, error.
Types, schemas, utils
- Types:
Filter,FilterCriteria,Column,SearchResultRecord,LayoutResponse,ObjectInfoResult, … - Zod schemas:
LayoutResponseSchema,ObjectInfoResultSchema,SearchResultsResponseSchema, … - Utilities:
parseFilterValue,sanitizeFilterValue,createFiltersKey,getGraphQLNodeValue,graphQLNodeToSearchResultRecordData,fetchAndValidate,safeEncodePath,getNestedFieldValue,getRecordDisplayName, layout transform and form helpers, etc.
The definitive type surface is in index.d.ts in this package.
Features
- Single object browse & search: keyword search and “browse all” mode (
browse__all). - Filterable list: filter definitions + picklist values, criteria → GraphQL where clause.
- Sortable list: build orderBy from sort selection.
- Cursor pagination (forward-only) with previous-page simulation via cursor stack.
- Record detail: layout-driven field selection (layout REST + record GraphQL).
- Type safety: Zod validation + exported TypeScript types.
Architecture
Data layer (GraphQL vs REST)
- GraphQL (uiapi)
Object metadata viagetObjectInfoBatchandgetPicklistValues. Records viagetRecordsGraphQLandgetRecordByIdGraphQL. - REST (uiApiClient)
Layout fromGET /layout/{object}. Search filters fromGET /search-info/{object}/filters. List/search results are GraphQL-only viauseRecordListGraphQL(no REST keyword search in the public API).
In the reference implementation:
- Detail page:
useRecordDetailLayout→objectDetailService.getRecordDetail(layout REST + record GraphQL). - List page:
useObjectListMetadata(filters + columns + picklists) +useRecordListGraphQL(records).
API flow (conceptual)
- Initialization:
getObjectInfoBatchfor object metadata; per object:getObjectListFilters(columns derived from filters), thengetPicklistValuesfor picklist filters. - List/search:
useRecordListGraphQL(GraphQL UI API with cursor pagination; use a cursor stack for “Previous”). - Detail:
useRecordDetailLayout/objectDetailService.getRecordDetail.
All API calls use fetchAndValidate and validate with Zod.
Install
npm install @salesforce/ui-bundle-template-feature-react-global-searchRequired peer environment
@salesforce/ui-bundle(API proxy, auth, etc.)- React and React Router
If you are not using that stack, you can still reuse pure utilities and types; the API services and hooks need an equivalent UI API transport.
Configuration (constants)
Constants are not exported. When you build your app (or copy reference UI), define them in the app:
- OBJECT_API_NAMES – Array of object API names to search. First element is the primary object (e.g.
OBJECT_API_NAMES[0]). Default to["Account"]if no object is specified. - DEFAULT_PAGE_SIZE – e.g.
20. - DEFAULT_DETAIL_PAGE_TITLE – e.g.
"Untitled".
Determining the search object: Decide from the user’s request or app context. If the user does not specify an object, use Account. If your repo provides a script (e.g. scripts/parse-feature-install-context.cjs), you can use it to parse the user prompt and get an object API name or label hint; otherwise set OBJECT_API_NAMES in the app’s constants accordingly.
Vibing integration (recommended: build your own UI)
Routes
Search results: e.g./global-search/:query(usebrowse__allfor “show all”). Record detail: e.g./object/:objectApiName/:recordId.Search entry
On submit, navigate to/global-search/${encodeURIComponent(query)}or/global-search/browse__all.Results page (list)
UseuseObjectListMetadata(objectApiName)for filters/columns/picklists anduseRecordListGraphQL({ objectApiName, first, after, filters, sortBy, searchQuery, columns })for records. Implement a cursor stack for “Previous” (see referenceGlobalSearchpage).Detail page
UseuseRecordDetailLayout({ objectApiName, recordId })forlayout,record,objectMetadata; render withlayoutTransformUtilsandgraphQLNodeFieldUtils(or equivalent).Search input placement
Put the search entry on the Home page (e.g. as a card) or in the app Header—not in a root layout that wraps every page.
Optional: copy reference UI from the package
The package does not export UI components. If you prefer to copy the reference UI instead of building your own:
- What to import (do not copy): API (
objectInfoService,objectDetailService, …), hooks (useObjectListMetadata,useRecordListGraphQL,useRecordDetailLayout, …), types, Zod schemas, utilities. - What to copy into the app: A single constants file (set
OBJECT_API_NAMESto your chosen object(s)) and the pages and components from the package’s reference implementation.
Path convention (reference implementation in this repo):
All paths below are relative to the package root of this feature. The reference implementation lives under:
src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/
Example paths:
- Constants:
src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/constants.ts - Search page:
src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/pages/GlobalSearch.tsx - Components:
src/force-app/main/default/uiBundles/feature-react-global-search/src/features/global-search/components/
After copying pages/ and components/ into your app:
- In the copied files only, replace imports from
@/api,@/hooks,@/types,@/utils,@/lib,@/featureswith imports from@salesforce/ui-bundle-template-feature-react-global-search. - Keep constants and component-to-component imports pointing at your app’s copied constants and components.
- Adapt markup and styles to your app’s UI library (the reference uses shadcn and Tailwind).
Example: build filters → FilterCriteria[]
import {
parseFilterValue,
sanitizeFilterValue,
type FilterCriteria,
} from "@salesforce/ui-bundle-template-feature-react-global-search";
function toCriteria(
objectApiName: string,
fieldPath: string,
operator: "eq" | "like",
rawValues: string[],
): FilterCriteria {
return {
objectApiName,
fieldPath,
operator,
values: rawValues
.map((v) => sanitizeFilterValue(v))
.filter(Boolean)
.map((v) => parseFilterValue(v)),
};
}Implementation steps (for an agent)
Install
From the consumer app root:npm install @salesforce/ui-bundle-template-feature-react-global-search.Determine search object(s)
From user prompt or app context. Default to Account if none specified. SetOBJECT_API_NAMESin the app’s constants to this value.Constants
In the app, create a constants file (or copy from the package reference path above) and setOBJECT_API_NAMES,DEFAULT_PAGE_SIZE,DEFAULT_DETAIL_PAGE_TITLE.API / types / utils / hooks
Import only from the package. Do not create or copyapi/,hooks/,types/, orutils/in the app.UI
Either (a) build your own UI using the package’s hooks and types, or (b) copy the full pages/ and components/ from the package reference path into the app, then batch-replace imports in the copied files to use the package (see “Optional: copy reference UI” above).Routes and search input
Add routes for search (e.g./global-search/:query) and record detail (e.g./object/:objectApiName/:recordId). Place the search input on the Home page or in the Header only—not in a root layout.
Checklist
- [ ] Package installed.
- [ ] Search object(s) determined;
OBJECT_API_NAMESset in app constants. - [ ] API, types, utils, hooks imported from package only (no api/hooks/types/utils folders in app).
- [ ] UI: own implementation or full copy of reference pages/components with imports updated to the package.
- [ ] Routes and search entry placement done; GlobalSearchInput not in root layout.
Notes / constraints
- Single-object scope: The package’s APIs and hooks are designed for one CRM object at a time (one
objectApiNameper call). There is no built-in multi-object search or tabbed results. You can still implement multi-object CRM search by calling the same services and hooks once per object (e.g. in parallel or per tab), then combining the results and building your own UI (tabs, merged lists, or separate sections). - Layout is REST: record layout from UI API REST; record and object metadata are GraphQL-backed.
- No UI exports: build or copy UI in the app; import only the data layer from the package.
Local development (this repo)
When developing this feature inside the ui-bundle repo:
nx run @salesforce/ui-bundle-template-feature-react-global-search:build:dist-app
nx run @salesforce/ui-bundle-template-feature-react-global-search:dev