@salesforce/webapp-template-app-react-template-b2x-experimental 1.71.0 → 1.71.2

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 (103) hide show
  1. package/dist/CHANGELOG.md +16 -0
  2. package/dist/README.md +58 -4
  3. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/package.json +3 -3
  4. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/alerts/status-alert.tsx +36 -32
  5. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layouts/card-layout.tsx +29 -0
  6. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/footers/footer-link.tsx +1 -1
  7. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/forms/auth-form.tsx +3 -3
  8. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/forms/submit-button.tsx +3 -3
  9. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/hooks/form.tsx +3 -3
  10. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/layout/card-skeleton.tsx +2 -2
  11. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/layout/centered-page-layout.tsx +1 -1
  12. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/layouts/AuthAppLayout.tsx +1 -1
  13. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/pages/ResetPassword.tsx +2 -2
  14. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/sessionTimeout/SessionTimeoutValidator.tsx +3 -3
  15. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{api → features/global-search/api}/objectDetailService.ts +2 -2
  16. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/DetailHeader.tsx +1 -1
  17. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/filters/FilterInput.tsx +2 -2
  18. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/filters/FilterSelect.tsx +2 -2
  19. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components/filters}/FiltersPanel.tsx +15 -10
  20. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/forms/filters-form.tsx +4 -4
  21. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/forms/submit-button.tsx +3 -3
  22. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components/shared → features/global-search/components/search}/GlobalSearchInput.tsx +4 -4
  23. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/search/SearchPagination.tsx +3 -3
  24. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components/search}/SearchResultCard.tsx +10 -5
  25. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/search/SearchResultsPanel.tsx +5 -5
  26. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components/shared}/LoadingFallback.tsx +1 -1
  27. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/filters/FilterInput.tsx +55 -0
  28. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/filters/FilterSelect.tsx +72 -0
  29. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/global-search/hooks}/form.tsx +9 -4
  30. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/global-search/pages}/DetailPage.tsx +4 -4
  31. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{pages → features/global-search/pages}/GlobalSearch.tsx +4 -4
  32. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Home.tsx +1 -1
  33. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/routes.tsx +13 -13
  34. package/dist/package.json +1 -1
  35. package/package.json +1 -1
  36. package/dist/force-app/main/default/README.md +0 -72
  37. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/auth/alerts/status-alert.tsx +0 -45
  38. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/auth/layout/card-layout.tsx +0 -29
  39. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layout/card-layout.tsx +0 -19
  40. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/index.ts +0 -33
  41. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/authHelpers.ts +0 -0
  42. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/authenticationConfig.ts +0 -0
  43. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/context/AuthContext.tsx +0 -0
  44. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/hooks/useCountdownTimer.ts +0 -0
  45. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/hooks/useRetryWithBackoff.ts +0 -0
  46. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/layouts/authenticationRouteLayout.tsx +0 -0
  47. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/layouts/privateRouteLayout.tsx +0 -0
  48. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/pages/ChangePassword.tsx +0 -0
  49. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/pages/ForgotPassword.tsx +0 -0
  50. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/pages/Login.tsx +0 -0
  51. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/pages/Profile.tsx +0 -0
  52. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/pages/Register.tsx +0 -0
  53. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/sessionTimeout/sessionTimeService.ts +0 -0
  54. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/sessionTimeout/sessionTimeoutConfig.ts +0 -0
  55. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{auth → features/authentication}/utils/helpers.ts +0 -0
  56. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{api → features/global-search/api}/index.ts +0 -0
  57. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{api → features/global-search/api}/objectInfoGraphQLService.ts +0 -0
  58. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{api → features/global-search/api}/objectInfoService.ts +0 -0
  59. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{api → features/global-search/api}/recordListGraphQLService.ts +0 -0
  60. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/DetailFields.tsx +0 -0
  61. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/DetailForm.tsx +0 -0
  62. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/DetailLayoutSections.tsx +0 -0
  63. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/Section.tsx +0 -0
  64. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/SectionRow.tsx +0 -0
  65. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/UiApiDetailForm.tsx +0 -0
  66. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/FieldValueDisplay.tsx +0 -0
  67. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/FormattedAddress.tsx +0 -0
  68. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/FormattedEmail.tsx +0 -0
  69. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/FormattedPhone.tsx +0 -0
  70. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/FormattedText.tsx +0 -0
  71. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/FormattedUrl.tsx +0 -0
  72. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/detail/formatted/index.ts +0 -0
  73. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/filters/FilterField.tsx +0 -0
  74. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/search/ResultCardFields.tsx +0 -0
  75. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{components → features/global-search/components}/search/SearchHeader.tsx +0 -0
  76. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/global-search/hooks}/index.ts +0 -0
  77. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/global-search/hooks}/useObjectInfoBatch.ts +0 -0
  78. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/global-search/hooks}/useObjectSearchData.ts +0 -0
  79. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/global-search/hooks}/useRecordDetailLayout.ts +0 -0
  80. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{hooks → features/global-search/hooks}/useRecordListGraphQL.ts +0 -0
  81. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{types → features/global-search/types}/filters/filters.ts +0 -0
  82. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{types → features/global-search/types}/filters/picklist.ts +0 -0
  83. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{types → features/global-search/types}/index.ts +0 -0
  84. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{types → features/global-search/types}/objectInfo/objectInfo.ts +0 -0
  85. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{types → features/global-search/types}/recordDetail/recordDetail.ts +0 -0
  86. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{types → features/global-search/types}/search/searchResults.ts +0 -0
  87. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/apiUtils.ts +0 -0
  88. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/cacheUtils.ts +0 -0
  89. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/debounce.ts +0 -0
  90. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/fieldUtils.ts +0 -0
  91. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/fieldValueExtractor.ts +0 -0
  92. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/filterUtils.ts +0 -0
  93. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/formDataTransformUtils.ts +0 -0
  94. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/formUtils.ts +0 -0
  95. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/graphQLNodeFieldUtils.ts +0 -0
  96. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/graphQLObjectInfoAdapter.ts +0 -0
  97. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/graphQLRecordAdapter.ts +0 -0
  98. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/index.ts +0 -0
  99. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/layoutTransformUtils.ts +0 -0
  100. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/linkUtils.ts +0 -0
  101. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/paginationUtils.ts +0 -0
  102. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/recordUtils.ts +0 -0
  103. /package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → features/global-search/utils}/sanitizationUtils.ts +0 -0
package/dist/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.71.2](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.71.1...v1.71.2) (2026-03-05)
7
+
8
+ **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
9
+
10
+
11
+
12
+
13
+
14
+ ## [1.71.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.71.0...v1.71.1) (2026-03-05)
15
+
16
+ **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
17
+
18
+
19
+
20
+
21
+
6
22
  # [1.71.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.70.0...v1.71.0) (2026-03-05)
7
23
 
8
24
  **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
package/dist/README.md CHANGED
@@ -1,10 +1,64 @@
1
- # Salesforce DX Project: Next Steps
1
+ # App React Template B2X
2
2
 
3
- Now that you’ve created a Salesforce DX project, what’s next? Here are some documentation resources to get you started.
3
+ A B2X (Business-to-Consumer) React starter template for customer-facing apps on the Salesforce platform. Includes authentication, global search, and an Experience Cloud site container. Built with React, Vite, TypeScript, and Tailwind/shadcn.
4
4
 
5
- ## How Do You Plan to Deploy Your Changes?
5
+ ## What's included
6
6
 
7
- Do you want to deploy a set of changes, or create a self-contained application? Choose a [development model](https://developer.salesforce.com/tools/vscode/en/user-guide/development-models).
7
+ | Path | Description |
8
+ | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
9
+ | `force-app/main/default/webapplications/appreacttemplateb2x/` | React web app (source, config, tests) |
10
+ | `force-app/main/default/classes/` | Apex classes for authentication — `WebAppAuthUtils`, `WebAppChangePassword`, `WebAppForgotPassword`, `WebAppLogin`, `WebAppRegistration` |
11
+ | `force-app/main/default/digitalExperienceConfigs/` | Experience Cloud site configuration |
12
+ | `force-app/main/default/digitalExperiences/` | Experience Cloud site definition |
13
+ | `force-app/main/default/networks/` | Experience Cloud network |
14
+ | `force-app/main/default/sites/` | Salesforce site |
15
+
16
+ ## Getting started
17
+
18
+ Navigate to the web app and install dependencies:
19
+
20
+ ```bash
21
+ cd force-app/main/default/webapplications/appreacttemplateb2x
22
+ npm install
23
+ npm run dev
24
+ ```
25
+
26
+ Opens at http://localhost:5173 by default. For build and test instructions, see the [web app README](force-app/main/default/webapplications/appreacttemplateb2x/README.md).
27
+
28
+ ## Deploy
29
+
30
+ ### Deploy everything (metadata + Experience Cloud site + web app)
31
+
32
+ ```bash
33
+ cd force-app/main/default/webapplications/appreacttemplateb2x && npm install && npm run build && cd -
34
+ sf project deploy start --source-dir force-app --target-org <alias>
35
+ ```
36
+
37
+ ### Deploy the web app only
38
+
39
+ ```bash
40
+ cd force-app/main/default/webapplications/appreacttemplateb2x && npm install && npm run build && cd -
41
+ sf project deploy start --source-dir force-app/main/default/webapplications --target-org <alias>
42
+ ```
43
+
44
+ ### Deploy Experience Cloud site only
45
+
46
+ ```bash
47
+ sf project deploy start \
48
+ --source-dir force-app/main/default/digitalExperienceConfigs \
49
+ --source-dir force-app/main/default/digitalExperiences \
50
+ --source-dir force-app/main/default/networks \
51
+ --source-dir force-app/main/default/sites \
52
+ --target-org <alias>
53
+ ```
54
+
55
+ ### Deploy authentication classes only
56
+
57
+ ```bash
58
+ sf project deploy start --source-dir force-app/main/default/classes --target-org <alias>
59
+ ```
60
+
61
+ Replace `<alias>` with your target org alias.
8
62
 
9
63
  ## Configure Your Salesforce DX Project
10
64
 
@@ -15,8 +15,8 @@
15
15
  "graphql:schema": "node scripts/get-graphql-schema.mjs"
16
16
  },
17
17
  "dependencies": {
18
- "@salesforce/sdk-data": "^1.71.0",
19
- "@salesforce/webapp-experimental": "^1.71.0",
18
+ "@salesforce/sdk-data": "^1.71.2",
19
+ "@salesforce/webapp-experimental": "^1.71.2",
20
20
  "@tailwindcss/vite": "^4.1.17",
21
21
  "@tanstack/react-form": "^1.28.4",
22
22
  "class-variance-authority": "^0.7.1",
@@ -40,7 +40,7 @@
40
40
  "@graphql-eslint/eslint-plugin": "^4.1.0",
41
41
  "@graphql-tools/utils": "^11.0.0",
42
42
  "@playwright/test": "^1.49.0",
43
- "@salesforce/vite-plugin-webapp-experimental": "^1.71.0",
43
+ "@salesforce/vite-plugin-webapp-experimental": "^1.71.2",
44
44
  "@testing-library/jest-dom": "^6.6.3",
45
45
  "@testing-library/react": "^16.1.0",
46
46
  "@testing-library/user-event": "^14.5.2",
@@ -1,45 +1,49 @@
1
- import { cva, type VariantProps } from "class-variance-authority";
2
- import { Alert, AlertDescription } from "../ui/alert";
3
- import { useId } from "react";
4
- import { AlertCircle, CheckCircle } from "lucide-react";
1
+ import { cva, type VariantProps } from 'class-variance-authority';
2
+ import { AlertCircleIcon, CheckCircle2Icon } from 'lucide-react';
3
+ import { Alert, AlertDescription } from '../../components/ui/alert';
4
+ import { useId } from 'react';
5
5
 
6
- const statusAlertVariants = cva("", {
7
- variants: {
8
- variant: {
9
- error: "",
10
- success: "",
11
- },
12
- },
13
- defaultVariants: {
14
- variant: "error",
15
- },
6
+ const statusAlertVariants = cva('', {
7
+ variants: {
8
+ variant: {
9
+ error: '',
10
+ success: '',
11
+ },
12
+ },
13
+ defaultVariants: {
14
+ variant: 'error',
15
+ },
16
16
  });
17
17
 
18
18
  interface StatusAlertProps extends VariantProps<typeof statusAlertVariants> {
19
- children?: React.ReactNode;
20
- /** Alert variant type. @default "error" */
21
- variant?: "error" | "success";
19
+ children?: React.ReactNode;
20
+ /** Alert variant type. @default "error" */
21
+ variant?: 'error' | 'success';
22
22
  }
23
23
 
24
24
  /**
25
25
  * Status alert component for displaying error or success messages.
26
26
  * Returns null if no children are provided.
27
27
  */
28
- export function StatusAlert({ children, variant = "error" }: StatusAlertProps) {
29
- if (!children) return null;
28
+ export function StatusAlert({ children, variant = 'error' }: StatusAlertProps) {
29
+ if (!children) return null;
30
30
 
31
- const isError = variant === "error";
32
- const descriptionId = useId();
31
+ const isError = variant === 'error';
32
+ const descriptionId = useId();
33
33
 
34
- return (
35
- <Alert
36
- variant={isError ? "destructive" : "default"}
37
- className={statusAlertVariants({ variant })}
38
- aria-describedby={descriptionId}
39
- role={isError ? "alert" : "status"}
40
- >
41
- {isError ? <AlertCircle aria-hidden="true" /> : <CheckCircle aria-hidden="true" />}
42
- <AlertDescription id={descriptionId}>{children}</AlertDescription>
43
- </Alert>
44
- );
34
+ return (
35
+ <Alert
36
+ variant={isError ? 'destructive' : 'default'}
37
+ className={statusAlertVariants({ variant })}
38
+ aria-describedby={descriptionId}
39
+ role={isError ? 'alert' : 'status'}
40
+ >
41
+ {isError ? (
42
+ <AlertCircleIcon aria-hidden="true" />
43
+ ) : (
44
+ <CheckCircle2Icon aria-hidden="true" />
45
+ )}
46
+ <AlertDescription id={descriptionId}>{children}</AlertDescription>
47
+ </Alert>
48
+ );
45
49
  }
@@ -0,0 +1,29 @@
1
+ import {
2
+ Card,
3
+ CardContent,
4
+ CardDescription,
5
+ CardHeader,
6
+ CardTitle,
7
+ } from '../../components/ui/card';
8
+
9
+ interface CardLayoutProps {
10
+ title: string;
11
+ description?: string;
12
+ children: React.ReactNode;
13
+ }
14
+
15
+ /**
16
+ * Card layout component for authentication pages.
17
+ * Provides CardHeader with title and optional description, and CardContent.
18
+ */
19
+ export function CardLayout({ title, description, children }: CardLayoutProps) {
20
+ return (
21
+ <Card>
22
+ <CardHeader>
23
+ <CardTitle className="text-2xl">{title}</CardTitle>
24
+ {description && <CardDescription>{description}</CardDescription>}
25
+ </CardHeader>
26
+ <CardContent>{children}</CardContent>
27
+ </Card>
28
+ );
29
+ }
@@ -1,5 +1,5 @@
1
1
  import { Link } from "react-router";
2
- import { cn } from "../../lib/utils";
2
+ import { cn } from "../../../lib/utils";
3
3
 
4
4
  interface FooterLinkProps extends Omit<React.ComponentProps<typeof Link>, "children"> {
5
5
  /** Link text prefix (e.g., "Don't have an account?") */
@@ -1,8 +1,8 @@
1
- import { FieldGroup } from "../../components/ui/field";
2
- import { StatusAlert } from "../alerts/status-alert";
1
+ import { FieldGroup } from "../../../components/ui/field";
2
+ import { StatusAlert } from "../../../components/alerts/status-alert";
3
3
  import { FooterLink } from "../footers/footer-link";
4
4
  import { SubmitButton } from "./submit-button";
5
- import { CardLayout } from "../layout/card-layout";
5
+ import { CardLayout } from "../../../components/layouts/card-layout";
6
6
  import { useFormContext } from "../hooks/form";
7
7
  import { useId } from "react";
8
8
 
@@ -1,6 +1,6 @@
1
- import { Button } from "../../components/ui/button";
2
- import { Spinner } from "../../components/ui/spinner";
3
- import { cn } from "../../lib/utils";
1
+ import { Button } from "../../../components/ui/button";
2
+ import { Spinner } from "../../../components/ui/spinner";
3
+ import { cn } from "../../../lib/utils";
4
4
  import { useFormContext } from "../hooks/form";
5
5
 
6
6
  interface SubmitButtonProps extends Omit<React.ComponentProps<typeof Button>, "type"> {
@@ -5,9 +5,9 @@ import {
5
5
  FieldDescription,
6
6
  FieldError,
7
7
  FieldLabel,
8
- } from "../../components/ui/field";
9
- import { Input } from "../../components/ui/input";
10
- import { cn } from "../../lib/utils";
8
+ } from "../../../components/ui/field";
9
+ import { Input } from "../../../components/ui/input";
10
+ import { cn } from "../../../lib/utils";
11
11
  import { AUTH_PLACEHOLDERS } from "../authenticationConfig";
12
12
 
13
13
  // Create form hook contexts
@@ -1,6 +1,6 @@
1
1
  import { CenteredPageLayout } from "./centered-page-layout";
2
- import { Card, CardContent, CardHeader } from "../../components/ui/card";
3
- import { Skeleton } from "../../components/ui/skeleton";
2
+ import { Card, CardContent, CardHeader } from "../../../components/ui/card";
3
+ import { Skeleton } from "../../../components/ui/skeleton";
4
4
 
5
5
  interface CardSkeletonProps {
6
6
  /**
@@ -1,5 +1,5 @@
1
1
  import { cva, type VariantProps } from "class-variance-authority";
2
- import { cn } from "../../lib/utils";
2
+ import { cn } from "../../../lib/utils";
3
3
 
4
4
  /**
5
5
  * Variant styles for the content container's maximum width.
@@ -1,6 +1,6 @@
1
1
  import SessionTimeoutValidator from "../sessionTimeout/SessionTimeoutValidator";
2
2
  import { AuthProvider } from "../context/AuthContext";
3
- import AppLayout from "../../appLayout";
3
+ import AppLayout from "../../../appLayout";
4
4
 
5
5
  export default function AuthAppLayout() {
6
6
  return (
@@ -1,9 +1,9 @@
1
1
  import { useState } from "react";
2
2
  import { Link, useSearchParams } from "react-router";
3
- import { CardLayout } from "../layout/card-layout";
3
+ import { CardLayout } from "../../../components/layouts/card-layout";
4
4
  import { CenteredPageLayout } from "../layout/centered-page-layout";
5
5
  import { AuthForm } from "../forms/auth-form";
6
- import { StatusAlert } from "../alerts/status-alert";
6
+ import { StatusAlert } from "../../../components/alerts/status-alert";
7
7
  import { useAppForm } from "../hooks/form";
8
8
  import { getDataSDK } from "@salesforce/sdk-data";
9
9
  import { ROUTES, AUTH_PLACEHOLDERS } from "../authenticationConfig";
@@ -10,8 +10,8 @@ import { useAuth } from "../context/AuthContext";
10
10
  import { pollSessionTimeServlet, extendSessionTime } from "./sessionTimeService";
11
11
  import { useCountdownTimer } from "../hooks/useCountdownTimer";
12
12
  import { useRetryWithBackoff } from "../hooks/useRetryWithBackoff";
13
- import { Alert, AlertTitle, AlertDescription } from "../../components/ui/alert";
14
- import { Button } from "../../components/ui/button";
13
+ import { Alert, AlertTitle, AlertDescription } from "../../../components/ui/alert";
14
+ import { Button } from "../../../components/ui/button";
15
15
  import {
16
16
  Dialog,
17
17
  DialogContent,
@@ -19,7 +19,7 @@ import {
19
19
  DialogTitle,
20
20
  DialogDescription,
21
21
  DialogFooter,
22
- } from "../../components/ui/dialog";
22
+ } from "../../../components/ui/dialog";
23
23
  import {
24
24
  STORAGE_KEYS,
25
25
  LABELS,
@@ -11,9 +11,9 @@ import { uiApiClient } from "@salesforce/webapp-experimental/api";
11
11
  import type { LayoutResponse } from "../types/recordDetail/recordDetail";
12
12
  import { LayoutResponseSchema } from "../types/recordDetail/recordDetail";
13
13
  import { fetchAndValidate, safeEncodePath } from "../utils/apiUtils";
14
- import { objectInfoService } from "../api/objectInfoService";
14
+ import { objectInfoService } from "./objectInfoService";
15
15
  import type { ObjectInfoResult } from "../types/objectInfo/objectInfo";
16
- import { getRecordByIdGraphQL, type GraphQLRecordNode } from "../api/recordListGraphQLService";
16
+ import { getRecordByIdGraphQL, type GraphQLRecordNode } from "./recordListGraphQLService";
17
17
  import type { Column } from "../types/search/searchResults";
18
18
  import { calculateFieldsToFetch } from "../utils/recordUtils";
19
19
 
@@ -4,7 +4,7 @@
4
4
  * @param title - Record title (e.g. record name) shown next to the back control.
5
5
  * @param onBack - Called when the user activates the back control.
6
6
  */
7
- import { Button } from "../ui/button";
7
+ import { Button } from "../../../../components/ui/button";
8
8
  import { ArrowLeft } from "lucide-react";
9
9
 
10
10
  interface DetailHeaderProps {
@@ -22,8 +22,8 @@
22
22
  * />
23
23
  * ```
24
24
  */
25
- import { Input } from "../ui/input";
26
- import { Field, FieldLabel, FieldDescription } from "../ui/field";
25
+ import { Input } from "../../../../components/ui/input";
26
+ import { Field, FieldLabel, FieldDescription } from "../../../../components/ui/field";
27
27
  import type { Filter } from "../../types/filters/filters";
28
28
 
29
29
  interface FilterInputProps {
@@ -30,8 +30,8 @@ import {
30
30
  SelectItem,
31
31
  SelectTrigger,
32
32
  SelectValue,
33
- } from "../ui/select";
34
- import { Field, FieldLabel, FieldDescription } from "../ui/field";
33
+ } from "../../../../components/ui/select";
34
+ import { Field, FieldLabel, FieldDescription } from "../../../../components/ui/field";
35
35
  import type { Filter } from "../../types/filters/filters";
36
36
  import type { PicklistValue } from "../../types/filters/picklist";
37
37
 
@@ -27,16 +27,21 @@
27
27
  * ```
28
28
  */
29
29
  import { useState, useMemo, useCallback, useEffect, useRef } from "react";
30
- import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
31
- import { Skeleton } from "./ui/skeleton";
32
- import { FiltersForm } from "./forms/filters-form";
33
- import { Field, FieldLabel, FieldDescription } from "./ui/field";
34
- import { useAppForm, validateRangeValues } from "../hooks/form";
35
- import type { Filter, FilterCriteria } from "../types/filters/filters";
36
- import type { PicklistValue } from "../types/filters/picklist";
37
- import { parseFilterValue } from "../utils/filterUtils";
38
- import { sanitizeFilterValue } from "../utils/sanitizationUtils";
39
- import { getFormValueByPath } from "../utils/formUtils";
30
+ import {
31
+ Card,
32
+ CardContent,
33
+ CardHeader,
34
+ CardTitle,
35
+ } from "../../../../components/ui/card";
36
+ import { Skeleton } from "../../../../components/ui/skeleton";
37
+ import { FiltersForm } from "../forms/filters-form";
38
+ import { Field, FieldLabel, FieldDescription } from "../../../../components/ui/field";
39
+ import { useAppForm, validateRangeValues } from "../../hooks/form";
40
+ import type { Filter, FilterCriteria } from "../../types/filters/filters";
41
+ import type { PicklistValue } from "../../types/filters/picklist";
42
+ import { parseFilterValue } from "../../utils/filterUtils";
43
+ import { sanitizeFilterValue } from "../../utils/sanitizationUtils";
44
+ import { getFormValueByPath } from "../../utils/formUtils";
40
45
 
41
46
  interface FiltersPanelProps {
42
47
  filters: Filter[];
@@ -1,8 +1,8 @@
1
- import { FieldGroup } from "../ui/field";
2
- import { StatusAlert } from "../alerts/status-alert";
3
- import { CardLayout } from "../layout/card-layout";
1
+ import { FieldGroup } from "../../../../components/ui/field";
2
+ import { StatusAlert } from "../../../../components/alerts/status-alert";
3
+ import { CardLayout } from "../../../../components/layouts/card-layout";
4
4
  import { SubmitButton } from "./submit-button";
5
- import { Button } from "../ui/button";
5
+ import { Button } from "../../../../components/ui/button";
6
6
  import { useFormContext } from "../../hooks/form";
7
7
  import { useId, useEffect, useRef } from "react";
8
8
 
@@ -1,6 +1,6 @@
1
- import { Button } from "../ui/button";
2
- import { Spinner } from "../ui/spinner";
3
- import { cn } from "../../lib/utils";
1
+ import { Button } from "../../../../components/ui/button";
2
+ import { Spinner } from "../../../../components/ui/spinner";
3
+ import { cn } from "../../../../lib/utils";
4
4
  import { useFormContext } from "../../hooks/form";
5
5
 
6
6
  interface SubmitButtonProps extends Omit<React.ComponentProps<typeof Button>, "type" | "disabled"> {
@@ -7,11 +7,11 @@
7
7
  import { useState, useCallback, useMemo, useId } from "react";
8
8
  import type { KeyboardEvent, ChangeEvent } from "react";
9
9
  import { useNavigate } from "react-router";
10
- import { Card, CardContent } from "../ui/card";
11
- import { Input } from "../ui/input";
12
- import { Button } from "../ui/button";
10
+ import { Card, CardContent } from "../../../../components/ui/card";
11
+ import { Input } from "../../../../components/ui/input";
12
+ import { Button } from "../../../../components/ui/button";
13
13
  import { Search } from "lucide-react";
14
- import { OBJECT_API_NAMES } from "../../constants";
14
+ import { OBJECT_API_NAMES } from "../../../../constants";
15
15
  import { useObjectInfoBatch } from "../../hooks/useObjectInfoBatch";
16
16
 
17
17
  const BROWSE_SEGMENT = "browse__all";
@@ -9,15 +9,15 @@
9
9
  * - Previous disabled when !hasPreviousPage (cursor stack enables prev when pageIndex > 0).
10
10
  * - Next disabled when !hasNextPage or nextPageToken is null.
11
11
  */
12
- import { Button } from "../ui/button";
12
+ import { Button } from "../../../../components/ui/button";
13
13
  import {
14
14
  Select,
15
15
  SelectContent,
16
16
  SelectItem,
17
17
  SelectTrigger,
18
18
  SelectValue,
19
- } from "../ui/select";
20
- import { Label } from "../ui/label";
19
+ } from "../../../../components/ui/select";
20
+ import { Label } from "../../../../components/ui/label";
21
21
  import { PAGE_SIZE_OPTIONS, getValidPageSize, isValidPageSize } from "../../utils/paginationUtils";
22
22
  import { ChevronLeft, ChevronRight } from "lucide-react";
23
23
 
@@ -25,11 +25,16 @@
25
25
  */
26
26
  import { useNavigate } from "react-router";
27
27
  import { useMemo, useCallback } from "react";
28
- import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
29
- import type { Column, SearchResultRecordData } from "../types/search/searchResults";
30
- import { getNestedFieldValue } from "../utils/fieldUtils";
31
- import ResultCardFields from "./search/ResultCardFields";
32
- import { OBJECT_API_NAMES } from "../constants";
28
+ import {
29
+ Card,
30
+ CardContent,
31
+ CardHeader,
32
+ CardTitle,
33
+ } from "../../../../components/ui/card";
34
+ import type { Column, SearchResultRecordData } from "../../types/search/searchResults";
35
+ import { getNestedFieldValue } from "../../utils/fieldUtils";
36
+ import ResultCardFields from "./ResultCardFields";
37
+ import { OBJECT_API_NAMES } from "../../../../constants";
33
38
 
34
39
  interface SearchResultCardProps {
35
40
  record: SearchResultRecordData;
@@ -32,8 +32,8 @@
32
32
  * ```
33
33
  */
34
34
  import { useMemo } from "react";
35
- import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
36
- import { Skeleton } from "../ui/skeleton";
35
+ import { Alert, AlertDescription, AlertTitle } from "../../../../components/ui/alert";
36
+ import { Skeleton } from "../../../../components/ui/skeleton";
37
37
  import { AlertCircle } from "lucide-react";
38
38
  import {
39
39
  Select,
@@ -41,9 +41,9 @@ import {
41
41
  SelectItem,
42
42
  SelectTrigger,
43
43
  SelectValue,
44
- } from "../ui/select";
45
- import { Label } from "../ui/label";
46
- import SearchResultCard from "../SearchResultCard";
44
+ } from "../../../../components/ui/select";
45
+ import { Label } from "../../../../components/ui/label";
46
+ import SearchResultCard from "./SearchResultCard";
47
47
  import SearchPagination from "./SearchPagination";
48
48
  import type { Column, SearchResultRecord } from "../../types/search/searchResults";
49
49
  import { getSafeKey } from "../../utils/recordUtils";
@@ -17,7 +17,7 @@
17
17
  * ```
18
18
  */
19
19
  import { cva, type VariantProps } from "class-variance-authority";
20
- import { Spinner } from "./ui/spinner";
20
+ import { Spinner } from "../../../../components/ui/spinner";
21
21
 
22
22
  /**
23
23
  * Spinner size variants based on content width.
@@ -0,0 +1,55 @@
1
+ /**
2
+ * FilterInput Component
3
+ *
4
+ * Renders a text input field for filter values.
5
+ * Used for filters that don't have a picklist (affordance !== 'select').
6
+ *
7
+ * @param filter - Filter definition containing field path, label, and attributes
8
+ * @param value - Current filter input value
9
+ * @param onChange - Callback when input value changes
10
+ *
11
+ * @remarks
12
+ * - Displays filter label or field path as the label
13
+ * - Shows placeholder text from filter attributes or generates default
14
+ * - Displays help message if available
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * <FilterInput
19
+ * filter={textFilter}
20
+ * value={filterValue}
21
+ * onChange={(value) => setFilterValue(value)}
22
+ * />
23
+ * ```
24
+ */
25
+ import { Input } from "../../../components/ui/input";
26
+ import { Field, FieldLabel, FieldDescription } from "../../../components/ui/field";
27
+ import type { Filter } from "../types/filters/filters";
28
+
29
+ interface FilterInputProps {
30
+ filter: Filter;
31
+ value: string;
32
+ onChange: (value: string) => void;
33
+ }
34
+
35
+ export default function FilterInput({ filter, value, onChange }: FilterInputProps) {
36
+ return (
37
+ <Field>
38
+ <FieldLabel htmlFor={filter.targetFieldPath}>
39
+ {filter.label || filter.targetFieldPath}
40
+ </FieldLabel>
41
+ <Input
42
+ id={filter.targetFieldPath}
43
+ type="text"
44
+ value={value}
45
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.value)}
46
+ placeholder={
47
+ filter.attributes?.placeholder ||
48
+ `Enter ${(filter.label || filter.targetFieldPath).toLowerCase()}`
49
+ }
50
+ aria-label={filter.label || filter.targetFieldPath}
51
+ />
52
+ {filter.helpMessage && <FieldDescription>{filter.helpMessage}</FieldDescription>}
53
+ </Field>
54
+ );
55
+ }