@salesforce/webapp-template-app-react-template-b2x-experimental 1.109.5 → 1.109.7

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.
Files changed (104) hide show
  1. package/dist/CHANGELOG.md +16 -0
  2. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/package.json +4 -3
  3. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/api/graphql-operations-types.ts +11260 -0
  4. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/sonner.tsx +20 -0
  5. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/authentication/sessionTimeout/SessionTimeoutValidator.tsx +8 -16
  6. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/authentication/sessionTimeout/sessionTimeService.ts +30 -42
  7. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/api/accountSearchService.ts +46 -0
  8. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/api/query/distinctAccountIndustries.graphql +19 -0
  9. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/api/query/distinctAccountTypes.graphql +19 -0
  10. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/api/query/getAccountDetail.graphql +121 -0
  11. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/api/query/searchAccounts.graphql +51 -0
  12. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/pages/AccountObjectDetailPage.tsx +357 -0
  13. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/pages/AccountSearch.tsx +275 -0
  14. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/__examples__/pages/Home.tsx +34 -0
  15. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/api/objectSearchService.ts +84 -0
  16. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/ActiveFilters.tsx +89 -0
  17. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/FilterPanel.tsx +127 -0
  18. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/ObjectBreadcrumb.tsx +66 -0
  19. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/PaginationControls.tsx +151 -0
  20. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/SearchBar.tsx +41 -0
  21. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/SortControl.tsx +143 -0
  22. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/BooleanFilter.tsx +94 -0
  23. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/DateFilter.tsx +138 -0
  24. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/DateRangeFilter.tsx +78 -0
  25. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/MultiSelectFilter.tsx +106 -0
  26. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/NumericRangeFilter.tsx +102 -0
  27. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/SearchFilter.tsx +40 -0
  28. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/SelectFilter.tsx +97 -0
  29. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/components/filters/TextFilter.tsx +77 -0
  30. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/hooks/useAsyncData.ts +53 -0
  31. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/hooks/useCachedAsyncData.ts +183 -0
  32. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/hooks/useObjectSearchParams.ts +225 -0
  33. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/utils/debounce.ts +22 -0
  34. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/utils/fieldUtils.ts +29 -0
  35. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/utils/filterUtils.ts +372 -0
  36. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/object-search/utils/sortUtils.ts +38 -0
  37. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Home.tsx +10 -11
  38. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/routes.tsx +8 -20
  39. package/dist/package-lock.json +2 -2
  40. package/dist/package.json +1 -1
  41. package/package.json +1 -1
  42. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectDetailService.ts +0 -102
  43. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectInfoGraphQLService.ts +0 -137
  44. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectInfoService.ts +0 -95
  45. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/recordListGraphQLService.ts +0 -364
  46. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailFields.tsx +0 -55
  47. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailForm.tsx +0 -146
  48. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailHeader.tsx +0 -34
  49. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/DetailLayoutSections.tsx +0 -80
  50. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/Section.tsx +0 -108
  51. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/SectionRow.tsx +0 -20
  52. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/UiApiDetailForm.tsx +0 -140
  53. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FieldValueDisplay.tsx +0 -73
  54. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedAddress.tsx +0 -29
  55. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedEmail.tsx +0 -17
  56. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedPhone.tsx +0 -24
  57. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedText.tsx +0 -11
  58. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/formatted/FormattedUrl.tsx +0 -29
  59. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FilterField.tsx +0 -54
  60. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FilterInput.tsx +0 -55
  61. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FilterSelect.tsx +0 -72
  62. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/filters/FiltersPanel.tsx +0 -380
  63. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/forms/filters-form.tsx +0 -114
  64. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/forms/submit-button.tsx +0 -47
  65. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/GlobalSearchInput.tsx +0 -114
  66. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/ResultCardFields.tsx +0 -71
  67. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchHeader.tsx +0 -31
  68. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchPagination.tsx +0 -144
  69. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchResultCard.tsx +0 -138
  70. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/search/SearchResultsPanel.tsx +0 -197
  71. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/shared/LoadingFallback.tsx +0 -61
  72. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/constants.ts +0 -39
  73. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/filters/FilterInput.tsx +0 -55
  74. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/filters/FilterSelect.tsx +0 -72
  75. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/form.tsx +0 -209
  76. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useObjectInfoBatch.ts +0 -72
  77. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useObjectSearchData.ts +0 -174
  78. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useRecordDetailLayout.ts +0 -137
  79. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useRecordListGraphQL.ts +0 -135
  80. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/pages/DetailPage.tsx +0 -109
  81. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/pages/GlobalSearch.tsx +0 -235
  82. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/filters/filters.ts +0 -121
  83. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/filters/picklist.ts +0 -6
  84. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/objectInfo/objectInfo.ts +0 -49
  85. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/recordDetail/recordDetail.ts +0 -61
  86. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/schema.d.ts +0 -200
  87. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/search/searchResults.ts +0 -229
  88. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/apiUtils.ts +0 -59
  89. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/cacheUtils.ts +0 -76
  90. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/debounce.ts +0 -90
  91. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/fieldUtils.ts +0 -354
  92. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/fieldValueExtractor.ts +0 -67
  93. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/filterUtils.ts +0 -32
  94. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/formDataTransformUtils.ts +0 -260
  95. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/formUtils.ts +0 -142
  96. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLNodeFieldUtils.ts +0 -186
  97. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +0 -77
  98. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLRecordAdapter.ts +0 -90
  99. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/layoutTransformUtils.ts +0 -236
  100. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/linkUtils.ts +0 -14
  101. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/paginationUtils.ts +0 -49
  102. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/recordUtils.ts +0 -159
  103. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/sanitizationUtils.ts +0 -50
  104. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/index.ts +0 -120
@@ -1,235 +0,0 @@
1
- /**
2
- * GlobalSearch Page Component
3
- *
4
- * Main page component for displaying global search results.
5
- * Uses GraphQL API (useRecordListGraphQL) for list data; results are adapted to the
6
- * same record shape as before so SearchResultCard and filters/sort/pagination work unchanged.
7
- *
8
- * @remarks
9
- * - Supports single object search (no tabs)
10
- * - Displays filters panel on the left and results on the right
11
- * - Pagination uses a cursor stack: we only query forward (first + after) and store endCursor per page;
12
- * Previous re-queries using the stored cursor for the previous page so both Next and Previous work.
13
- */
14
- import { useMemo, useState, useCallback, useEffect, useRef } from "react";
15
- import { useParams } from "react-router";
16
- import { OBJECT_API_NAMES, DEFAULT_PAGE_SIZE } from "../constants";
17
- import { useObjectListMetadata } from "../hooks/useObjectSearchData";
18
- import { useObjectInfoBatch } from "../hooks/useObjectInfoBatch";
19
- import { useRecordListGraphQL } from "../hooks/useRecordListGraphQL";
20
- import FiltersPanel from "../components/filters/FiltersPanel";
21
- import SearchHeader from "../components/search/SearchHeader";
22
- import SearchResultsPanel from "../components/search/SearchResultsPanel";
23
- import { Card, CardContent, CardHeader, CardTitle } from "../../../components/ui/card";
24
- import { Skeleton } from "../../../components/ui/skeleton";
25
- import type { FilterCriteria } from "../types/filters/filters";
26
- import type { SearchResultRecord } from "../types/search/searchResults";
27
- import { graphQLNodeToSearchResultRecordData } from "../utils/graphQLRecordAdapter";
28
-
29
- const EMPTY_HIGHLIGHT = { fields: {}, snippet: null };
30
- const EMPTY_SEARCH_INFO = { isPromoted: false, isSpellCorrected: false };
31
-
32
- export default function GlobalSearch() {
33
- const { query } = useParams<{ query: string }>();
34
-
35
- const objectApiName = OBJECT_API_NAMES[0];
36
-
37
- const [searchPageSize, setSearchPageSize] = useState(DEFAULT_PAGE_SIZE);
38
- const [afterCursor, setAfterCursor] = useState<string | null>(null);
39
- const [pageIndex, setPageIndex] = useState(0);
40
- /** Cursor stack: cursorStack[i] is the `after` value that returns page i. cursorStack[0] = null (first page). */
41
- const [cursorStack, setCursorStack] = useState<(string | null)[]>([null]);
42
- const [appliedFilters, setAppliedFilters] = useState<FilterCriteria[]>([]);
43
- const [sortBy, setSortBy] = useState("Name");
44
-
45
- const decodedQuery = useMemo(() => {
46
- if (!query) return "";
47
- try {
48
- return decodeURIComponent(query);
49
- } catch {
50
- return query;
51
- }
52
- }, [query]);
53
-
54
- const isBrowseAll = decodedQuery === "browse__all";
55
- const searchQuery = isBrowseAll ? "" : decodedQuery.trim();
56
-
57
- // Reset pagination when the URL search query changes so we don't use an old cursor with a new result set
58
- useEffect(() => {
59
- queueMicrotask(() => {
60
- setAfterCursor(null);
61
- setPageIndex(0);
62
- setCursorStack([null]);
63
- });
64
- }, [query]);
65
-
66
- const listMeta = useObjectListMetadata(objectApiName);
67
- const { objectInfos } = useObjectInfoBatch([...OBJECT_API_NAMES]);
68
- const labelPlural = (objectInfos[0]?.labelPlural as string | undefined) ?? "records";
69
- const {
70
- edges,
71
- pageInfo,
72
- loading: resultsLoading,
73
- error: resultsError,
74
- } = useRecordListGraphQL({
75
- objectApiName,
76
- first: searchPageSize,
77
- after: afterCursor,
78
- filters: appliedFilters,
79
- sortBy: sortBy === "relevance" ? "Name" : sortBy,
80
- searchQuery: searchQuery || undefined,
81
- columns: listMeta.columns,
82
- columnsLoading: listMeta.loading,
83
- columnsError: listMeta.error,
84
- });
85
-
86
- // Store endCursor for the next page so we can re-query when user clicks Next; also enables Previous via stack.
87
- // Only update when not loading so a stale response cannot write a cursor into the wrong stack index (e.g. after rapid Next clicks).
88
- useEffect(() => {
89
- if (resultsLoading) return;
90
- const cursor = pageInfo?.endCursor ?? null;
91
- if (cursor == null) return;
92
- queueMicrotask(() => {
93
- setCursorStack((prev) => {
94
- const next = [...prev];
95
- next[pageIndex + 1] = cursor;
96
- return next;
97
- });
98
- });
99
- }, [resultsLoading, pageInfo?.endCursor, pageIndex]);
100
-
101
- const results: SearchResultRecord[] = useMemo(
102
- () =>
103
- (edges ?? []).map((edge) => ({
104
- record: graphQLNodeToSearchResultRecordData(
105
- edge?.node as Record<string, unknown>,
106
- objectApiName,
107
- ),
108
- highlightInfo: EMPTY_HIGHLIGHT,
109
- searchInfo: EMPTY_SEARCH_INFO,
110
- })),
111
- [edges, objectApiName],
112
- );
113
-
114
- const nextPageToken = pageInfo?.endCursor ?? null;
115
- /** Entry cursor for the previous page; used when user clicks Previous to re-query with after=cursorStack[pageIndex-1]. */
116
- const previousPageToken = pageIndex > 0 ? (cursorStack[pageIndex - 1] ?? null) : null;
117
- const hasNextPage = pageInfo?.hasNextPage === true;
118
- const hasPreviousPage = pageIndex > 0;
119
- const currentPageToken = pageIndex.toString();
120
-
121
- const cursorStackRef = useRef(cursorStack);
122
- const pageIndexRef = useRef(pageIndex);
123
- useEffect(() => {
124
- cursorStackRef.current = cursorStack;
125
- pageIndexRef.current = pageIndex;
126
- }, [cursorStack, pageIndex]);
127
-
128
- const canRenderFilters =
129
- !listMeta.loading && listMeta.filters !== undefined && listMeta.picklistValues !== undefined;
130
-
131
- const handleApplyFilters = useCallback((filterCriteria: FilterCriteria[]) => {
132
- setAppliedFilters(filterCriteria);
133
- setAfterCursor(null);
134
- setPageIndex(0);
135
- setCursorStack([null]);
136
- }, []);
137
-
138
- const handlePageChange = useCallback(
139
- (newPageToken: string, direction?: "next" | "prev" | "first") => {
140
- if (direction === "first" || newPageToken === "0") {
141
- setAfterCursor(null);
142
- setPageIndex(0);
143
- } else if (direction === "prev") {
144
- const idx = pageIndexRef.current;
145
- const stack = cursorStackRef.current;
146
- const prevCursor = idx > 0 ? (stack[idx - 1] ?? null) : null;
147
- setAfterCursor(prevCursor);
148
- setPageIndex((prev) => Math.max(0, prev - 1));
149
- } else {
150
- setAfterCursor(newPageToken);
151
- setPageIndex((prev) => prev + 1);
152
- }
153
- window.scrollTo({ top: 0, behavior: "smooth" });
154
- },
155
- [],
156
- );
157
-
158
- const handlePageSizeChange = useCallback((newPageSize: number) => {
159
- setSearchPageSize(newPageSize);
160
- setAfterCursor(null);
161
- setPageIndex(0);
162
- setCursorStack([null]);
163
- window.scrollTo({ top: 0, behavior: "smooth" });
164
- }, []);
165
-
166
- const handleSortByChange = useCallback((newSortBy: string) => {
167
- setSortBy(newSortBy);
168
- setAfterCursor(null);
169
- setPageIndex(0);
170
- setCursorStack([null]);
171
- window.scrollTo({ top: 0, behavior: "smooth" });
172
- }, []);
173
-
174
- return (
175
- <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
176
- <SearchHeader query={decodedQuery} isBrowseAll={isBrowseAll} labelPlural={labelPlural} />
177
-
178
- <div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
179
- <aside className="lg:col-span-1" aria-label="Filters panel">
180
- {canRenderFilters ? (
181
- <FiltersPanel
182
- filters={listMeta.filters}
183
- picklistValues={listMeta.picklistValues}
184
- loading={listMeta.loading}
185
- objectApiName={objectApiName}
186
- onApplyFilters={handleApplyFilters}
187
- />
188
- ) : (
189
- <Card className="w-full" role="region" aria-label="Filters panel">
190
- <CardHeader>
191
- <CardTitle>Filters</CardTitle>
192
- </CardHeader>
193
- <CardContent
194
- className="space-y-4"
195
- role="status"
196
- aria-live="polite"
197
- aria-label="Loading filters"
198
- >
199
- <span className="sr-only">Loading filters</span>
200
- {[1, 2, 3].map((i) => (
201
- <div key={i} className="space-y-2" aria-hidden="true">
202
- <Skeleton className="h-4 w-24" />
203
- <Skeleton className="h-9 w-full" />
204
- </div>
205
- ))}
206
- </CardContent>
207
- </Card>
208
- )}
209
- </aside>
210
-
211
- <section className="lg:col-span-3" aria-label="Search results">
212
- <SearchResultsPanel
213
- objectApiName={objectApiName}
214
- columns={listMeta.columns}
215
- results={results}
216
- columnsLoading={listMeta.loading}
217
- resultsLoading={resultsLoading}
218
- columnsError={listMeta.error}
219
- resultsError={resultsError}
220
- currentPageToken={currentPageToken}
221
- nextPageToken={nextPageToken}
222
- previousPageToken={previousPageToken}
223
- hasNextPage={hasNextPage}
224
- hasPreviousPage={hasPreviousPage}
225
- pageSize={searchPageSize}
226
- sortBy={sortBy}
227
- onPageChange={handlePageChange}
228
- onPageSizeChange={handlePageSizeChange}
229
- onSortByChange={handleSortByChange}
230
- />
231
- </section>
232
- </div>
233
- </main>
234
- );
235
- }
@@ -1,121 +0,0 @@
1
- import { z } from "zod";
2
-
3
- /**
4
- * Type definitions for filter structures
5
- * All types are derived from Zod schemas using z.infer for type safety
6
- */
7
-
8
- /**
9
- * Allowed filter operators for Salesforce search queries
10
- */
11
- export const FILTER_OPERATORS = [
12
- "eq", // Equals
13
- "ne", // Not equals
14
- "like", // Pattern matching (contains)
15
- "in", // In list (multiple values)
16
- "gt", // Greater than
17
- "gte", // Greater than or equal
18
- "lt", // Less than
19
- "lte", // Less than or equal
20
- ] as const;
21
-
22
- /**
23
- * Filter operator type
24
- */
25
- export type FilterOperator = (typeof FILTER_OPERATORS)[number];
26
-
27
- /**
28
- * Salesforce field path validation regex
29
- * Validates field paths like:
30
- * - Simple fields: "Name", "FieldName__c"
31
- * - Relationship fields: "Account__r.Name", "Owner__r.FieldName__c"
32
- * - Nested relationships: "Account__r.Owner__r.Name"
33
- *
34
- * Pattern explanation:
35
- * - ^[A-Za-z][A-Za-z0-9_]* - Starts with letter, followed by letters/numbers/underscores
36
- * - (__[cr])? - Optional relationship suffix (__r or __c)
37
- * - (\.[A-Za-z][A-Za-z0-9_]*(__[cr])?)* - Optional relationship traversal (dot notation)
38
- */
39
- const SALESFORCE_FIELD_PATH_REGEX =
40
- /^[A-Za-z][A-Za-z0-9_]*(__[cr])?(\.[A-Za-z][A-Za-z0-9_]*(__[cr])?)*$/;
41
-
42
- /**
43
- * Validates Salesforce field path format
44
- * @param fieldPath - The field path to validate
45
- * @returns true if valid, false otherwise
46
- */
47
- function isValidSalesforceFieldPath(fieldPath: string): boolean {
48
- if (!fieldPath || fieldPath.trim().length === 0) {
49
- return false;
50
- }
51
- return SALESFORCE_FIELD_PATH_REGEX.test(fieldPath);
52
- }
53
-
54
- // Zod Schema for Filter Attributes
55
- const FilterAttributesSchema = z.object({
56
- affordance: z.string().optional(),
57
- placeholder: z.string().optional(),
58
- });
59
-
60
- /**
61
- * Filter attributes containing input-specific properties
62
- */
63
- export type FilterAttributes = z.infer<typeof FilterAttributesSchema>;
64
-
65
- // Zod Schema for Filter
66
- const FilterSchema = z.object({
67
- affordance: z.string(),
68
- attributes: FilterAttributesSchema.optional(),
69
- defaultValues: z.array(z.string()).optional(),
70
- helpMessage: z.string().nullable().optional(),
71
- label: z.string(),
72
- targetFieldPath: z.string().refine((value) => isValidSalesforceFieldPath(value), {
73
- message:
74
- "Invalid Salesforce field path format. Field paths must start with a letter and can contain letters, numbers, underscores, and relationship notation (__r or __c). Use dot notation for relationships (e.g., 'Account__r.Name').",
75
- }),
76
- type: z.string(),
77
- });
78
-
79
- /**
80
- * Single filter definition from getObjectListFilters API
81
- */
82
- export type Filter = z.infer<typeof FilterSchema>;
83
-
84
- // Export schema for validation
85
- export const FilterArraySchema = z.array(FilterSchema);
86
-
87
- // Zod Schema for Filter Criteria with operator and field path validation
88
- const FilterCriteriaSchema = z.object({
89
- objectApiName: z.string().min(1, "Object API name is required"),
90
- fieldPath: z
91
- .string()
92
- .min(1, "Field path is required")
93
- .refine((value) => isValidSalesforceFieldPath(value), {
94
- message:
95
- "Invalid Salesforce field path format. Field paths must start with a letter and can contain letters, numbers, underscores, and relationship notation (__r or __c). Use dot notation for relationships (e.g., 'Account__r.Name').",
96
- }),
97
- operator: z.enum(FILTER_OPERATORS, {
98
- message: `Operator must be one of: ${FILTER_OPERATORS.join(", ")}`,
99
- }),
100
- values: z.array(z.union([z.string(), z.number()])).min(1, "At least one value is required"),
101
- });
102
-
103
- /**
104
- * Filter criteria structure for filtering search results
105
- */
106
- export type FilterCriteria = z.infer<typeof FilterCriteriaSchema>;
107
-
108
- // Export schema for validation
109
- export const FilterCriteriaArraySchema = z.array(FilterCriteriaSchema);
110
-
111
- // Zod Schema for Filters Response (used for type inference via z.infer)
112
- export const FiltersResponseSchema = z.record(z.string(), z.unknown()).and(
113
- z.object({
114
- filters: FilterArraySchema.optional(),
115
- }),
116
- );
117
-
118
- /**
119
- * Filters response structure
120
- */
121
- export type FiltersResponse = z.infer<typeof FiltersResponseSchema>;
@@ -1,6 +0,0 @@
1
- import type { PicklistValue as GraphQLPicklistValue } from "../objectInfo/objectInfo";
2
-
3
- export type PicklistValue = GraphQLPicklistValue & {
4
- value: NonNullable<GraphQLPicklistValue["value"]>;
5
- label: NonNullable<GraphQLPicklistValue["label"]>;
6
- };
@@ -1,49 +0,0 @@
1
- import type { GetObjectInfosQuery, GetPicklistValuesQuery } from "../schema";
2
-
3
- // Generic utility types for extracting array item types
4
- type ArrayItem<T> = T extends (infer Item)[] ? Item : never;
5
- type NonNullableArrayItem<T> = NonNullable<ArrayItem<NonNullable<T>>>;
6
-
7
- // ObjectInfos extraction
8
- export type GetObjectInfosQueryObjectInfos = NonNullable<
9
- GetObjectInfosQuery["uiapi"]["objectInfos"]
10
- >;
11
- export type GetObjectInfosQueryObjectInfo = NonNullableArrayItem<GetObjectInfosQueryObjectInfos>;
12
- export type GetObjectInfosQueryField = NonNullableArrayItem<
13
- GetObjectInfosQueryObjectInfo["fields"]
14
- >;
15
-
16
- // ObjectInfoResult types
17
- export type ObjectInfoResult = Omit<GetObjectInfosQueryObjectInfo, "fields"> & {
18
- fields: Record<string, GetObjectInfosQueryField>;
19
- };
20
- export type ObjectInfoBatchResponse = {
21
- results: { result: ObjectInfoResult; statusCode: number }[];
22
- };
23
-
24
- // Picklist values extraction
25
- export type GetPicklistValuesQueryObjectInfos = GetPicklistValuesQuery["uiapi"]["objectInfos"];
26
- export type GetPicklistValuesQueryObjectInfo =
27
- NonNullableArrayItem<GetPicklistValuesQueryObjectInfos>;
28
- export type GetPicklistValuesQueryField = NonNullableArrayItem<
29
- GetPicklistValuesQueryObjectInfo["fields"]
30
- >;
31
-
32
- // Extract picklist-specific field type (the one with picklistValuesByRecordTypeIDs)
33
- type GetPicklistValuesQueryPicklistField = Extract<
34
- GetPicklistValuesQueryField,
35
- { picklistValuesByRecordTypeIDs?: unknown }
36
- >;
37
-
38
- // Extract types from picklistValuesByRecordTypeIDs
39
- type PicklistValuesByRecordTypeIDs =
40
- GetPicklistValuesQueryPicklistField["picklistValuesByRecordTypeIDs"];
41
- type PicklistValuesByRecordTypeID = NonNullable<
42
- NonNullable<PicklistValuesByRecordTypeIDs> extends (infer Item)[] ? Item : null
43
- >;
44
-
45
- // Extract individual picklist value type
46
- type PicklistValues = NonNullable<PicklistValuesByRecordTypeID>["picklistValues"];
47
- export type PicklistValue = NonNullable<
48
- NonNullable<PicklistValues> extends (infer Item)[] ? Item : null
49
- >;
@@ -1,61 +0,0 @@
1
- import { z } from "zod";
2
-
3
- /**
4
- * Type definitions and Zod schemas for Record Detail APIs:
5
- * - Layout API (layout/{objectApiName}?layoutType=Full&mode=View&recordTypeId=...)
6
- * - Record API (records/{recordId}?optionalFields=...)
7
- */
8
-
9
- const LayoutComponentSchema = z.object({
10
- apiName: z.string().nullable(),
11
- behavior: z.string().optional(),
12
- componentType: z.enum(["Field", "CustomLink", "EmptySpace"]),
13
- customLinkUrl: z.string().optional(),
14
- label: z.string().optional(),
15
- });
16
-
17
- export type LayoutComponent = z.infer<typeof LayoutComponentSchema>;
18
-
19
- const LayoutItemSchema = z.object({
20
- editableForNew: z.boolean(),
21
- editableForUpdate: z.boolean(),
22
- label: z.string(),
23
- layoutComponents: z.array(LayoutComponentSchema),
24
- lookupIdApiName: z.string().nullable(),
25
- required: z.boolean(),
26
- sortable: z.boolean(),
27
- uiBehavior: z.string().nullable(),
28
- });
29
-
30
- export type LayoutItem = z.infer<typeof LayoutItemSchema>;
31
-
32
- const LayoutRowSchema = z.object({
33
- layoutItems: z.array(LayoutItemSchema),
34
- });
35
-
36
- const LayoutSectionSchema = z.object({
37
- collapsible: z.boolean(),
38
- columns: z.number(),
39
- heading: z.string(),
40
- id: z.string(),
41
- layoutRows: z.array(LayoutRowSchema),
42
- rows: z.number(),
43
- tabOrder: z.string(),
44
- useHeading: z.boolean(),
45
- });
46
-
47
- export type LayoutSection = z.infer<typeof LayoutSectionSchema>;
48
-
49
- export const LayoutResponseSchema = z.object({
50
- eTag: z.string(),
51
- id: z.string(),
52
- layoutType: z.string(),
53
- mode: z.string(),
54
- objectApiName: z.string(),
55
- recordTypeId: z.string(),
56
- saveOptions: z.array(z.unknown()).optional(),
57
- sections: z.array(LayoutSectionSchema),
58
- });
59
-
60
- export type LayoutResponse = z.infer<typeof LayoutResponseSchema>;
61
- export type LayoutRow = z.infer<typeof LayoutRowSchema>;
@@ -1,200 +0,0 @@
1
- export type Maybe<T> = T | null;
2
- export type InputMaybe<T> = Maybe<T>;
3
- export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
4
- export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
5
- export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
6
- export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = {
7
- [_ in K]?: never;
8
- };
9
- export type Incremental<T> =
10
- | T
11
- | { [P in keyof T]?: P extends " $fragmentName" | "__typename" ? T[P] : never };
12
- /** All built-in and custom scalars, mapped to their actual values */
13
- export type Scalars = {
14
- ID: { input: string; output: string };
15
- String: { input: string; output: string };
16
- Boolean: { input: boolean; output: boolean };
17
- Int: { input: number; output: number };
18
- Float: { input: number; output: number };
19
- Base64: { input: string; output: string };
20
- /** An arbitrary precision signed decimal */
21
- BigDecimal: { input: number | string; output: number };
22
- /** An arbitrary precision signed integer */
23
- BigInteger: { input: number; output: number };
24
- /** An 8-bit signed integer */
25
- Byte: { input: number; output: number };
26
- /** A UTF-16 code unit; a character on Unicode's BMP */
27
- Char: { input: number; output: number };
28
- Currency: { input: number | string; output: number };
29
- Date: { input: string; output: string };
30
- DateTime: { input: string; output: string };
31
- Double: { input: number | string; output: number };
32
- Email: { input: string; output: string };
33
- EncryptedString: { input: string; output: string };
34
- /** Can be set to an ID or a Reference to the result of another mutation operation. */
35
- IdOrRef: { input: string; output: string };
36
- JSON: { input: string; output: string };
37
- Latitude: { input: number | string; output: number };
38
- /** A 64-bit signed integer */
39
- Long: { input: number; output: number };
40
- LongTextArea: { input: string; output: string };
41
- Longitude: { input: number | string; output: number };
42
- MultiPicklist: { input: string; output: string };
43
- Percent: { input: number | string; output: number };
44
- PhoneNumber: { input: string; output: string };
45
- Picklist: { input: string; output: string };
46
- RichTextArea: { input: string; output: string };
47
- /** A 16-bit signed integer */
48
- Short: { input: number; output: number };
49
- TextArea: { input: string; output: string };
50
- Time: { input: string; output: string };
51
- Url: { input: string; output: string };
52
- };
53
-
54
- export enum DataType {
55
- Address = "ADDRESS",
56
- Anytype = "ANYTYPE",
57
- Base64 = "BASE64",
58
- Boolean = "BOOLEAN",
59
- Combobox = "COMBOBOX",
60
- Complexvalue = "COMPLEXVALUE",
61
- Currency = "CURRENCY",
62
- Date = "DATE",
63
- Datetime = "DATETIME",
64
- Double = "DOUBLE",
65
- Email = "EMAIL",
66
- Encryptedstring = "ENCRYPTEDSTRING",
67
- Int = "INT",
68
- Json = "JSON",
69
- Junctionidlist = "JUNCTIONIDLIST",
70
- Location = "LOCATION",
71
- Long = "LONG",
72
- Multipicklist = "MULTIPICKLIST",
73
- Percent = "PERCENT",
74
- Phone = "PHONE",
75
- Picklist = "PICKLIST",
76
- Reference = "REFERENCE",
77
- String = "STRING",
78
- Textarea = "TEXTAREA",
79
- Time = "TIME",
80
- Url = "URL",
81
- }
82
-
83
- export enum FieldExtraTypeInfo {
84
- ExternalLookup = "EXTERNAL_LOOKUP",
85
- ImageUrl = "IMAGE_URL",
86
- IndirectLookup = "INDIRECT_LOOKUP",
87
- Personname = "PERSONNAME",
88
- Plaintextarea = "PLAINTEXTAREA",
89
- Richtextarea = "RICHTEXTAREA",
90
- SwitchablePersonname = "SWITCHABLE_PERSONNAME",
91
- }
92
-
93
- /** Input for ObjectInfo and PickValues */
94
- export type ObjectInfoInput = {
95
- apiName: Scalars["String"]["input"];
96
- fieldNames?: InputMaybe<Array<Scalars["String"]["input"]>>;
97
- recordTypeIDs?: InputMaybe<Array<Scalars["ID"]["input"]>>;
98
- };
99
-
100
- export enum ResultOrder {
101
- Asc = "ASC",
102
- Desc = "DESC",
103
- }
104
-
105
- export type GetObjectInfosQueryVariables = Exact<{
106
- apiNames: Array<Scalars["String"]["input"]> | Scalars["String"]["input"];
107
- }>;
108
-
109
- export type GetObjectInfosQuery = {
110
- uiapi: {
111
- objectInfos?: Array<{
112
- ApiName: string;
113
- label?: string | null;
114
- labelPlural?: string | null;
115
- nameFields: Array<string | null>;
116
- defaultRecordTypeId?: string | null;
117
- keyPrefix?: string | null;
118
- layoutable: boolean;
119
- queryable: boolean;
120
- searchable: boolean;
121
- updateable: boolean;
122
- deletable: boolean;
123
- createable: boolean;
124
- custom: boolean;
125
- mruEnabled: boolean;
126
- feedEnabled: boolean;
127
- fields: Array<
128
- | {
129
- ApiName: string;
130
- label?: string | null;
131
- dataType?: DataType | null;
132
- relationshipName?: string | null;
133
- reference: boolean;
134
- compound: boolean;
135
- compoundFieldName?: string | null;
136
- compoundComponentName?: string | null;
137
- controllingFields: Array<string | null>;
138
- controllerName?: string | null;
139
- referenceToInfos: Array<{ ApiName: string; nameFields: Array<string | null> } | null>;
140
- }
141
- | {
142
- ApiName: string;
143
- label?: string | null;
144
- dataType?: DataType | null;
145
- relationshipName?: string | null;
146
- reference: boolean;
147
- compound: boolean;
148
- compoundFieldName?: string | null;
149
- compoundComponentName?: string | null;
150
- controllingFields: Array<string | null>;
151
- controllerName?: string | null;
152
- referenceToInfos: Array<{ ApiName: string; nameFields: Array<string | null> } | null>;
153
- }
154
- | null
155
- >;
156
- recordTypeInfos: Array<{
157
- recordTypeId?: string | null;
158
- name?: string | null;
159
- master: boolean;
160
- available: boolean;
161
- defaultRecordTypeMapping: boolean;
162
- } | null>;
163
- themeInfo?: { color?: string | null; iconUrl?: string | null } | null;
164
- childRelationships: Array<{
165
- relationshipName?: string | null;
166
- fieldName?: string | null;
167
- childObjectApiName: string;
168
- } | null>;
169
- dependentFields: Array<{ controllingField: string } | null>;
170
- } | null> | null;
171
- };
172
- };
173
-
174
- export type GetPicklistValuesQueryVariables = Exact<{
175
- objectInfoInputs: Array<ObjectInfoInput> | ObjectInfoInput;
176
- }>;
177
-
178
- export type GetPicklistValuesQuery = {
179
- uiapi: {
180
- objectInfos?: Array<{
181
- ApiName: string;
182
- fields: Array<
183
- | {
184
- ApiName: string;
185
- picklistValuesByRecordTypeIDs?: Array<{
186
- recordTypeID: string;
187
- defaultValue?: { value?: string | null } | null;
188
- picklistValues?: Array<{
189
- label?: string | null;
190
- value?: string | null;
191
- validFor?: Array<number | null> | null;
192
- }> | null;
193
- } | null> | null;
194
- }
195
- | { ApiName: string }
196
- | null
197
- >;
198
- } | null> | null;
199
- };
200
- };