@salesforce/templates 66.1.0 → 66.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/lib/generators/projectGenerator.d.ts +6 -0
  2. package/lib/generators/projectGenerator.js +43 -4
  3. package/lib/generators/projectGenerator.js.map +1 -1
  4. package/lib/templates/project/react-b2e/.a4drules/README.md +35 -0
  5. package/lib/templates/project/react-b2e/.a4drules/a4d-webapp-generate.md +27 -0
  6. package/lib/templates/project/react-b2e/.a4drules/build-validation.md +78 -0
  7. package/lib/templates/project/react-b2e/.a4drules/code-quality.md +137 -0
  8. package/lib/templates/project/react-b2e/.a4drules/graphql/tools/knowledge/lds-explore-graphql-schema.md +227 -0
  9. package/lib/templates/project/react-b2e/.a4drules/graphql/tools/knowledge/lds-generate-graphql-mutationquery.md +212 -0
  10. package/lib/templates/project/react-b2e/.a4drules/graphql/tools/knowledge/lds-generate-graphql-readquery.md +185 -0
  11. package/lib/templates/project/react-b2e/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +205 -0
  12. package/lib/templates/project/react-b2e/.a4drules/graphql/tools/schemas/shared.graphqls +1150 -0
  13. package/lib/templates/project/react-b2e/.a4drules/graphql.md +409 -0
  14. package/lib/templates/project/react-b2e/.a4drules/images.md +13 -0
  15. package/lib/templates/project/react-b2e/.a4drules/react.md +387 -0
  16. package/lib/templates/project/react-b2e/.a4drules/react_image_processing.md +45 -0
  17. package/lib/templates/project/react-b2e/.a4drules/typescript.md +224 -0
  18. package/lib/templates/project/react-b2e/.a4drules/ui-layout.md +23 -0
  19. package/lib/templates/project/react-b2e/.a4drules/webapp-nav-and-placeholders.md +33 -0
  20. package/lib/templates/project/react-b2e/.a4drules/webapp-no-node-e.md +25 -0
  21. package/lib/templates/project/react-b2e/.a4drules/webapp-ui-first.md +32 -0
  22. package/lib/templates/project/react-b2e/.a4drules/webapp.md +75 -0
  23. package/lib/templates/project/react-b2e/.forceignore +15 -0
  24. package/lib/templates/project/react-b2e/.husky/pre-commit +4 -0
  25. package/lib/templates/project/react-b2e/.prettierignore +11 -0
  26. package/lib/templates/project/react-b2e/.prettierrc +17 -0
  27. package/lib/templates/project/react-b2e/AGENT.md +75 -0
  28. package/lib/templates/project/react-b2e/CHANGELOG.md +696 -0
  29. package/lib/templates/project/react-b2e/README.md +18 -0
  30. package/lib/templates/project/react-b2e/config/project-scratch-def.json +13 -0
  31. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/.graphqlrc.yml +2 -0
  32. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/.prettierignore +9 -0
  33. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/.prettierrc +11 -0
  34. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/appreacttemplateb2e.webapplication-meta.xml +7 -0
  35. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/build/vite.config.d.ts +2 -0
  36. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/build/vite.config.js +93 -0
  37. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/codegen.yml +94 -0
  38. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/e2e/app.spec.ts +17 -0
  39. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/eslint.config.js +141 -0
  40. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/index.html +13 -0
  41. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/package-lock.json +14392 -0
  42. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/package.json +58 -0
  43. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/playwright.config.ts +24 -0
  44. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/scripts/get-graphql-schema.mjs +68 -0
  45. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/scripts/rewrite-e2e-assets.mjs +23 -0
  46. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/api/graphql-operations-types.ts +116 -0
  47. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/api/utils/accounts.ts +33 -0
  48. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/api/utils/query/highRevenueAccountsQuery.graphql +29 -0
  49. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/app.tsx +22 -0
  50. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/appLayout.tsx +19 -0
  51. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/icons/book.svg +3 -0
  52. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/icons/copy.svg +4 -0
  53. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/icons/rocket.svg +3 -0
  54. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/icons/star.svg +3 -0
  55. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/images/codey-1.png +0 -0
  56. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/images/codey-2.png +0 -0
  57. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/images/codey-3.png +0 -0
  58. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/assets/images/vibe-codey.svg +194 -0
  59. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/components/AgentforceConversationClient.tsx +127 -0
  60. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/index.ts +6 -0
  61. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/navigationMenu.tsx +80 -0
  62. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/pages/Home.tsx +12 -0
  63. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/pages/NotFound.tsx +18 -0
  64. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/router-utils.tsx +35 -0
  65. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/routes.tsx +22 -0
  66. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/styles/global.css +13 -0
  67. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/src/types/conversation.ts +21 -0
  68. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/tsconfig.json +36 -0
  69. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/tsconfig.node.json +13 -0
  70. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/vite-env.d.ts +1 -0
  71. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/vite.config.ts +102 -0
  72. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/vitest-env.d.ts +2 -0
  73. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/vitest.config.ts +11 -0
  74. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/vitest.setup.ts +1 -0
  75. package/lib/templates/project/react-b2e/force-app/main/default/webapplications/appreacttemplateb2e/webapplication.json +7 -0
  76. package/lib/templates/project/react-b2e/jest.config.js +6 -0
  77. package/lib/templates/project/react-b2e/package.json +38 -0
  78. package/lib/templates/project/react-b2e/scripts/apex/hello.apex +10 -0
  79. package/lib/templates/project/react-b2e/scripts/soql/account.soql +6 -0
  80. package/lib/templates/project/react-b2e/sfdx-project.json +12 -0
  81. package/lib/templates/project/react-b2x/.a4drules/README.md +35 -0
  82. package/lib/templates/project/react-b2x/.a4drules/a4d-webapp-generate.md +27 -0
  83. package/lib/templates/project/react-b2x/.a4drules/build-validation.md +78 -0
  84. package/lib/templates/project/react-b2x/.a4drules/code-quality.md +137 -0
  85. package/lib/templates/project/react-b2x/.a4drules/graphql/tools/knowledge/lds-explore-graphql-schema.md +227 -0
  86. package/lib/templates/project/react-b2x/.a4drules/graphql/tools/knowledge/lds-generate-graphql-mutationquery.md +212 -0
  87. package/lib/templates/project/react-b2x/.a4drules/graphql/tools/knowledge/lds-generate-graphql-readquery.md +185 -0
  88. package/lib/templates/project/react-b2x/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +205 -0
  89. package/lib/templates/project/react-b2x/.a4drules/graphql/tools/schemas/shared.graphqls +1150 -0
  90. package/lib/templates/project/react-b2x/.a4drules/graphql.md +409 -0
  91. package/lib/templates/project/react-b2x/.a4drules/images.md +13 -0
  92. package/lib/templates/project/react-b2x/.a4drules/react.md +387 -0
  93. package/lib/templates/project/react-b2x/.a4drules/react_image_processing.md +45 -0
  94. package/lib/templates/project/react-b2x/.a4drules/typescript.md +224 -0
  95. package/lib/templates/project/react-b2x/.a4drules/ui-layout.md +23 -0
  96. package/lib/templates/project/react-b2x/.a4drules/webapp-nav-and-placeholders.md +33 -0
  97. package/lib/templates/project/react-b2x/.a4drules/webapp-no-node-e.md +25 -0
  98. package/lib/templates/project/react-b2x/.a4drules/webapp-ui-first.md +32 -0
  99. package/lib/templates/project/react-b2x/.a4drules/webapp.md +75 -0
  100. package/lib/templates/project/react-b2x/.forceignore +15 -0
  101. package/lib/templates/project/react-b2x/.husky/pre-commit +4 -0
  102. package/lib/templates/project/react-b2x/.prettierignore +11 -0
  103. package/lib/templates/project/react-b2x/.prettierrc +17 -0
  104. package/lib/templates/project/react-b2x/AGENT.md +75 -0
  105. package/lib/templates/project/react-b2x/CHANGELOG.md +696 -0
  106. package/lib/templates/project/react-b2x/README.md +18 -0
  107. package/lib/templates/project/react-b2x/config/project-scratch-def.json +13 -0
  108. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppAuthUtils.cls +68 -0
  109. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppAuthUtils.cls-meta.xml +5 -0
  110. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppChangePassword.cls +77 -0
  111. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppChangePassword.cls-meta.xml +5 -0
  112. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppForgotPassword.cls +71 -0
  113. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppForgotPassword.cls-meta.xml +5 -0
  114. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppLogin.cls +105 -0
  115. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppLogin.cls-meta.xml +5 -0
  116. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppRegistration.cls +162 -0
  117. package/lib/templates/project/react-b2x/force-app/main/default/classes/WebAppRegistration.cls-meta.xml +5 -0
  118. package/lib/templates/project/react-b2x/force-app/main/default/digitalExperienceConfigs/appreacttemplateb2x1.digitalExperienceConfig +8 -0
  119. package/lib/templates/project/react-b2x/force-app/main/default/digitalExperiences/site/appreacttemplateb2x1/appreacttemplateb2x1.digitalExperience-meta.xml +11 -0
  120. package/lib/templates/project/react-b2x/force-app/main/default/digitalExperiences/site/appreacttemplateb2x1/sfdc_cms__site/appreacttemplateb2x1/_meta.json +5 -0
  121. package/lib/templates/project/react-b2x/force-app/main/default/digitalExperiences/site/appreacttemplateb2x1/sfdc_cms__site/appreacttemplateb2x1/content.json +10 -0
  122. package/lib/templates/project/react-b2x/force-app/main/default/networks/appreacttemplateb2x.network +60 -0
  123. package/lib/templates/project/react-b2x/force-app/main/default/package.xml +20 -0
  124. package/lib/templates/project/react-b2x/force-app/main/default/sites/appreacttemplateb2x.site +31 -0
  125. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/.graphqlrc.yml +2 -0
  126. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/.prettierignore +9 -0
  127. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/.prettierrc +11 -0
  128. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/appreacttemplateb2x.webapplication-meta.xml +7 -0
  129. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/build/vite.config.d.ts +2 -0
  130. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/build/vite.config.js +93 -0
  131. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/codegen.yml +94 -0
  132. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/e2e/app.spec.ts +17 -0
  133. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/eslint.config.js +141 -0
  134. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/index.html +13 -0
  135. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/package-lock.json +18408 -0
  136. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/package.json +66 -0
  137. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/playwright.config.ts +24 -0
  138. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/scripts/get-graphql-schema.mjs +68 -0
  139. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/scripts/rewrite-e2e-assets.mjs +23 -0
  140. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/api/graphql-operations-types.ts +116 -0
  141. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/api/utils/accounts.ts +33 -0
  142. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/api/utils/query/highRevenueAccountsQuery.graphql +29 -0
  143. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/app.tsx +13 -0
  144. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/appLayout.tsx +11 -0
  145. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/icons/book.svg +3 -0
  146. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/icons/copy.svg +4 -0
  147. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/icons/rocket.svg +3 -0
  148. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/icons/star.svg +3 -0
  149. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/images/codey-1.png +0 -0
  150. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/images/codey-2.png +0 -0
  151. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/images/codey-3.png +0 -0
  152. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/assets/images/vibe-codey.svg +194 -0
  153. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/alerts/status-alert.tsx +45 -0
  154. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/authHelpers.ts +73 -0
  155. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/authenticationConfig.ts +61 -0
  156. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/authenticationRouteLayout.tsx +21 -0
  157. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/privateRouteLayout.tsx +36 -0
  158. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/sessionTimeout/SessionTimeoutValidator.tsx +616 -0
  159. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/sessionTimeout/sessionTimeService.ts +161 -0
  160. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/sessionTimeout/sessionTimeoutConfig.ts +77 -0
  161. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/footers/footer-link.tsx +36 -0
  162. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/forms/auth-form.tsx +81 -0
  163. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/forms/submit-button.tsx +49 -0
  164. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layout/card-layout.tsx +23 -0
  165. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layout/card-skeleton.tsx +38 -0
  166. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/layout/centered-page-layout.tsx +73 -0
  167. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/alert.tsx +69 -0
  168. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/button.tsx +67 -0
  169. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/card.tsx +92 -0
  170. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/dialog.tsx +143 -0
  171. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/field.tsx +222 -0
  172. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/index.ts +72 -0
  173. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/input.tsx +19 -0
  174. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/label.tsx +19 -0
  175. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/pagination.tsx +112 -0
  176. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/select.tsx +183 -0
  177. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/separator.tsx +26 -0
  178. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/skeleton.tsx +14 -0
  179. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/spinner.tsx +15 -0
  180. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/table.tsx +87 -0
  181. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/tabs.tsx +78 -0
  182. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/components.json +18 -0
  183. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/context/AuthContext.tsx +95 -0
  184. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/hooks/form.tsx +116 -0
  185. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/hooks/useCountdownTimer.ts +266 -0
  186. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/hooks/useRetryWithBackoff.ts +109 -0
  187. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/layouts/AuthAppLayout.tsx +12 -0
  188. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/lib/data-sdk.ts +21 -0
  189. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/lib/utils.ts +6 -0
  190. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/navigationMenu.tsx +80 -0
  191. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/ChangePassword.tsx +107 -0
  192. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/ForgotPassword.tsx +73 -0
  193. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Home.tsx +12 -0
  194. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Login.tsx +97 -0
  195. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/NotFound.tsx +18 -0
  196. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Profile.tsx +178 -0
  197. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Register.tsx +138 -0
  198. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/ResetPassword.tsx +107 -0
  199. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/router-utils.tsx +35 -0
  200. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/routes.tsx +71 -0
  201. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/styles/global.css +135 -0
  202. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/src/utils/helpers.ts +121 -0
  203. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/tsconfig.json +36 -0
  204. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/tsconfig.node.json +13 -0
  205. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/vite-env.d.ts +1 -0
  206. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/vite.config.ts +102 -0
  207. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/vitest-env.d.ts +2 -0
  208. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/vitest.config.ts +11 -0
  209. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/vitest.setup.ts +1 -0
  210. package/lib/templates/project/react-b2x/force-app/main/default/webapplications/appreacttemplateb2x/webapplication.json +7 -0
  211. package/lib/templates/project/react-b2x/jest.config.js +6 -0
  212. package/lib/templates/project/react-b2x/package.json +38 -0
  213. package/lib/templates/project/react-b2x/scripts/apex/hello.apex +10 -0
  214. package/lib/templates/project/react-b2x/scripts/soql/account.soql +6 -0
  215. package/lib/templates/project/react-b2x/sfdx-project.json +12 -0
  216. package/lib/templates/webapplication/reactbasic/.graphqlrc.yml +2 -0
  217. package/lib/templates/webapplication/reactbasic/build/vite.config.js +20 -1
  218. package/lib/templates/webapplication/reactbasic/codegen.yml +94 -0
  219. package/lib/templates/webapplication/reactbasic/e2e/app.spec.ts +0 -7
  220. package/lib/templates/webapplication/reactbasic/eslint.config.js +28 -0
  221. package/lib/templates/webapplication/reactbasic/package-lock.json +10090 -2874
  222. package/lib/templates/webapplication/reactbasic/package.json +16 -4
  223. package/lib/templates/webapplication/reactbasic/scripts/get-graphql-schema.mjs +68 -0
  224. package/lib/templates/webapplication/reactbasic/src/api/graphql-operations-types.ts +23 -34
  225. package/lib/templates/webapplication/reactbasic/src/api/utils/accounts.ts +33 -0
  226. package/lib/templates/webapplication/reactbasic/src/app.tsx +10 -1
  227. package/lib/templates/webapplication/reactbasic/src/appLayout.tsx +2 -0
  228. package/lib/templates/webapplication/reactbasic/src/navigationMenu.tsx +80 -0
  229. package/lib/templates/webapplication/reactbasic/src/router-utils.tsx +35 -0
  230. package/lib/templates/webapplication/reactbasic/src/routes.tsx +1 -7
  231. package/lib/templates/webapplication/reactbasic/vite.config.ts +20 -1
  232. package/lib/tsconfig.tsbuildinfo +1 -1
  233. package/lib/utils/types.d.ts +1 -1
  234. package/lib/utils/webappTemplateUtils.d.ts +49 -0
  235. package/lib/utils/webappTemplateUtils.js +210 -0
  236. package/lib/utils/webappTemplateUtils.js.map +1 -0
  237. package/package.json +8 -6
  238. package/lib/templates/webapplication/reactbasic/src/pages/About.tsx +0 -12
@@ -0,0 +1,161 @@
1
+ /**
2
+ * SessionTimeServlet API service
3
+ * Handles communication with the session validation endpoint
4
+ */
5
+
6
+ import { SESSION_CONFIG } from "./sessionTimeoutConfig";
7
+
8
+ /**
9
+ * Response from SessionTimeServlet API
10
+ */
11
+ export interface SessionResponse {
12
+ /** Session phase */
13
+ sp: number;
14
+ /** Seconds remaining in session */
15
+ sr: number;
16
+ }
17
+
18
+ /**
19
+ * Parse the servlet response text into SessionResponse object
20
+ * Handles CSRF protection prefix
21
+ *
22
+ * @param text - Raw response text from servlet
23
+ * @returns Parsed session response
24
+ * @throws Error if response cannot be parsed
25
+ */
26
+ function parseResponseResult(text: string): SessionResponse {
27
+ let cleanedText = text;
28
+
29
+ // Strip CSRF protection prefix if present
30
+ if (cleanedText.startsWith(SESSION_CONFIG.CSRF_TOKEN)) {
31
+ cleanedText = cleanedText.substring(SESSION_CONFIG.CSRF_TOKEN.length);
32
+ }
33
+
34
+ // Trim whitespace
35
+ cleanedText = cleanedText.trim();
36
+
37
+ try {
38
+ const parsed = JSON.parse(cleanedText) as SessionResponse;
39
+
40
+ // Validate response structure
41
+ if (typeof parsed.sp !== "number" || typeof parsed.sr !== "number") {
42
+ throw new Error("Invalid response structure: missing sp or sr properties");
43
+ }
44
+
45
+ return parsed;
46
+ } catch (error) {
47
+ console.error("[sessionTimeService] Failed to parse response:", error, "Text:", cleanedText);
48
+ throw new Error(
49
+ `Failed to parse session response: ${error instanceof Error ? error.message : "Unknown error"}`,
50
+ );
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Call SessionTimeServlet API
56
+ * Internal function used by both poll and extend functions
57
+ *
58
+ * @param basePath - Community base path (e.g., "/sfsites/c/")
59
+ * @param extend - Whether to extend the session (updateTimedOutSession param)
60
+ * @returns Session response with remaining time
61
+ * @throws Error if API call fails or security checks fail
62
+ */
63
+ async function callSessionTimeServlet(
64
+ basePath: string,
65
+ extend: boolean = false,
66
+ ): Promise<SessionResponse> {
67
+ // Build URL with cache-busting timestamp
68
+ const timestamp = Date.now();
69
+ let url = `${basePath}${SESSION_CONFIG.SERVLET_URL}?buster=${timestamp}`;
70
+
71
+ if (extend) {
72
+ url += "&updateTimedOutSession=true";
73
+ }
74
+
75
+ try {
76
+ const response = await fetch(url, {
77
+ method: "GET",
78
+ credentials: "same-origin", // Include cookies for session
79
+ cache: "no-cache",
80
+ // Security headers
81
+ headers: {
82
+ "X-Requested-With": "XMLHttpRequest", // Helps identify XHR requests
83
+ },
84
+ });
85
+
86
+ if (!response.ok) {
87
+ // Provide more context for common error codes
88
+ if (response.status === 401) {
89
+ throw new Error("Session expired or unauthorized");
90
+ } else if (response.status === 403) {
91
+ throw new Error("Access forbidden");
92
+ } else if (response.status === 404) {
93
+ throw new Error("Session endpoint not found");
94
+ } else {
95
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
96
+ }
97
+ }
98
+
99
+ // Security: Validate content type (should be text or JSON)
100
+ const contentType = response.headers.get("content-type");
101
+ if (contentType && !contentType.includes("text") && !contentType.includes("json")) {
102
+ throw new Error(`Unexpected content type: ${contentType}`);
103
+ }
104
+
105
+ const text = await response.text();
106
+ const parsed = parseResponseResult(text);
107
+
108
+ // Apply latency buffer to account for network delay
109
+ const adjustedSecondsRemaining = Math.max(0, parsed.sr - SESSION_CONFIG.LATENCY_BUFFER_SECONDS);
110
+
111
+ return {
112
+ sp: parsed.sp,
113
+ sr: adjustedSecondsRemaining,
114
+ };
115
+ } catch (error) {
116
+ // Don't log the full URL in production to avoid leaking sensitive info
117
+ console.error("[sessionTimeService] API call failed:", error);
118
+ throw error;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Poll SessionTimeServlet to check remaining session time
124
+ * Called periodically to monitor session status
125
+ *
126
+ * @param basePath - Community base path (e.g., "/sfsites/c/")
127
+ * @returns Session response with remaining time (after latency buffer adjustment)
128
+ * @throws Error if API call fails
129
+ *
130
+ * @example
131
+ * const { sr, sp } = await pollSessionTimeServlet('/sfsites/c/');
132
+ * if (sr <= 300) {
133
+ * // Less than 5 minutes remaining
134
+ * showWarning();
135
+ * }
136
+ */
137
+ export async function pollSessionTimeServlet(basePath: string): Promise<SessionResponse> {
138
+ return callSessionTimeServlet(basePath, false);
139
+ }
140
+
141
+ /**
142
+ * Extend the current session time
143
+ * Called when user clicks "Continue Working" in warning modal
144
+ *
145
+ * @param basePath - Community base path (e.g., "/sfsites/c/")
146
+ * @returns Session response with new remaining time
147
+ * @throws Error if API call fails
148
+ *
149
+ * @example
150
+ * const { sr } = await extendSessionTime('/sfsites/c/');
151
+ * console.log(`Session extended. ${sr} seconds remaining.`);
152
+ */
153
+ export async function extendSessionTime(basePath: string): Promise<SessionResponse> {
154
+ return callSessionTimeServlet(basePath, true);
155
+ }
156
+
157
+ /**
158
+ * Export parseResponseResult for testing purposes
159
+ * @internal
160
+ */
161
+ export { parseResponseResult };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Configuration constants for session timeout monitoring
3
+ */
4
+
5
+ // ============================================================================
6
+ // Retry Configuration
7
+ // ============================================================================
8
+
9
+ /** Initial delay for first retry attempt (2 seconds) */
10
+ export const INITIAL_RETRY_DELAY = 2000;
11
+
12
+ /** Maximum number of retry attempts before giving up */
13
+ export const MAX_RETRY_ATTEMPTS = 10;
14
+
15
+ /** Maximum retry delay (30 minutes) */
16
+ export const MAX_RETRY_DELAY = 30 * 60 * 1000;
17
+
18
+ // ============================================================================
19
+ // Session Storage Keys
20
+ // ============================================================================
21
+
22
+ /** sessionStorage keys used by session validator */
23
+ export const STORAGE_KEYS = {
24
+ /** Flag to show session expired message on login page */
25
+ SHOW_SESSION_MESSAGE: "lwrSessionValidator.showSessionMessage",
26
+ } as const;
27
+
28
+ // ============================================================================
29
+ // Servlet Configuration
30
+ // ============================================================================
31
+
32
+ /** SessionTimeServlet configuration */
33
+ export const SESSION_CONFIG = {
34
+ /** Relative URL to SessionTimeServlet */
35
+ SERVLET_URL: "/sfsites/c/_nc_external/system/security/session/SessionTimeServlet",
36
+
37
+ /** Latency buffer to subtract from server response (seconds) */
38
+ LATENCY_BUFFER_SECONDS: 3,
39
+
40
+ /** CSRF protection prefix in servlet responses */
41
+ CSRF_TOKEN: "while(1);\n",
42
+ } as const;
43
+
44
+ // ============================================================================
45
+ // UI Labels
46
+ // ============================================================================
47
+
48
+ /**
49
+ * UI labels for session timeout components
50
+ */
51
+ export const LABELS = {
52
+ /** Title for session warning modal */
53
+ sessionWarningTitle: "Session Timeout Warning",
54
+
55
+ /** Message text in session warning modal */
56
+ sessionWarningMessage:
57
+ "For security, we log you out if you’re inactive for too long. To continue working, click Continue before the time expires.",
58
+
59
+ /** Text for "Continue" button */
60
+ continueButton: "Continue",
61
+
62
+ /** Text for "Log Out" button */
63
+ logoutButton: "Log Out",
64
+
65
+ /** Message shown on login page after session expires */
66
+ invalidSessionMessage: "Your session has expired. Please log in again.",
67
+
68
+ /** Accessibility label for close button */
69
+ closeLabel: "Close",
70
+ } as const;
71
+
72
+ // ============================================================================
73
+ // Session Timeout Configuration
74
+ // ============================================================================
75
+
76
+ /** Session warning time in seconds (30 seconds) */
77
+ export const SESSION_WARNING_TIME = 30;
@@ -0,0 +1,36 @@
1
+ import { Link } from "react-router";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ interface FooterLinkProps extends Omit<React.ComponentProps<typeof Link>, "children"> {
5
+ /** Link text prefix (e.g., "Don't have an account?") */
6
+ text?: string;
7
+ /** Link label (e.g., "Sign up") */
8
+ linkText: string;
9
+ }
10
+
11
+ /**
12
+ * Footer link component.
13
+ */
14
+ export function FooterLink({ text, to, linkText, className, ...props }: FooterLinkProps) {
15
+ return (
16
+ <p className={cn("w-full text-center text-sm text-muted-foreground", className)}>
17
+ {text && (
18
+ <>
19
+ {text}
20
+ {/* Robustness: Explicit space ensures formatting tools don't strip it */}
21
+ {"\u00A0"}
22
+ </>
23
+ )}
24
+ <Link
25
+ to={to}
26
+ className={cn(
27
+ "font-medium underline hover:text-primary transition-colors",
28
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
29
+ )}
30
+ {...props}
31
+ >
32
+ {linkText}
33
+ </Link>
34
+ </p>
35
+ );
36
+ }
@@ -0,0 +1,81 @@
1
+ import { FieldGroup } from "../ui/field";
2
+ import { StatusAlert } from "../alerts/status-alert";
3
+ import { FooterLink } from "../footers/footer-link";
4
+ import { SubmitButton } from "./submit-button";
5
+ import { CardLayout } from "../layout/card-layout";
6
+ import { useFormContext } from "../../hooks/form";
7
+ import { useId } from "react";
8
+
9
+ /**
10
+ * [Dev Note] A wrapper component that enforces consistent layout (Card) and error/success alert positioning
11
+ * for all authentication forms.
12
+ */
13
+ interface AuthFormProps extends Omit<React.ComponentProps<"form">, "onSubmit"> {
14
+ title: string;
15
+ description: string;
16
+ error?: React.ReactNode;
17
+ success?: React.ReactNode;
18
+ submit: {
19
+ text: string;
20
+ loadingText?: string;
21
+ disabled?: boolean;
22
+ };
23
+ footer?: {
24
+ text?: string;
25
+ link: string;
26
+ linkText: string;
27
+ };
28
+ }
29
+
30
+ /**
31
+ * [Dev Note] Standardized Authentication Layout:
32
+ * Wraps the specific logic of Login/Register forms with a consistent visual frame (Card),
33
+ * title, and error alert placement. Extends form element props for flexibility.
34
+ * This ensures all auth-related pages look and behave similarly.
35
+ */
36
+ export function AuthForm({
37
+ id: providedId,
38
+ title,
39
+ description,
40
+ error,
41
+ success,
42
+ children,
43
+ submit,
44
+ footer,
45
+ ...props
46
+ }: AuthFormProps) {
47
+ const form = useFormContext();
48
+ const generatedId = useId();
49
+ const id = providedId ?? generatedId;
50
+
51
+ return (
52
+ <CardLayout title={title} description={description}>
53
+ <div className="space-y-6">
54
+ {/* [Dev Note] Global form error alert (e.g. "Invalid Credentials") */}
55
+ {error && <StatusAlert variant="error">{error}</StatusAlert>}
56
+ {success && <StatusAlert variant="success">{success}</StatusAlert>}
57
+
58
+ <form
59
+ id={id}
60
+ onSubmit={(e) => {
61
+ e.preventDefault();
62
+ e.stopPropagation();
63
+ form.handleSubmit();
64
+ }}
65
+ {...props}
66
+ >
67
+ <FieldGroup>{children}</FieldGroup>
68
+ <SubmitButton
69
+ form={id}
70
+ label={submit.text}
71
+ loadingLabel={submit.loadingText}
72
+ disabled={submit.disabled}
73
+ className="mt-6"
74
+ />
75
+ </form>
76
+ {/* [Dev Note] Navigation links (e.g. "Forgot Password?") */}
77
+ {footer && <FooterLink text={footer.text} to={footer.link} linkText={footer.linkText} />}
78
+ </div>
79
+ </CardLayout>
80
+ );
81
+ }
@@ -0,0 +1,49 @@
1
+ import { Button } from "../ui/button";
2
+ import { Spinner } from "../ui/spinner";
3
+ import { cn } from "../../lib/utils";
4
+ import { useFormContext } from "../../hooks/form";
5
+
6
+ interface SubmitButtonProps extends Omit<React.ComponentProps<typeof Button>, "type"> {
7
+ /** Button text when not submitting */
8
+ label: string;
9
+ /** Button text while submitting */
10
+ loadingLabel?: string;
11
+ /** Form id to associate with (for buttons outside form element) */
12
+ form?: string;
13
+ }
14
+
15
+ const isSubmittingSelector = (state: { isSubmitting: boolean }) => state.isSubmitting;
16
+
17
+ /**
18
+ * Submit button that subscribes to form submission state.
19
+ * UX Best Practice:
20
+ * 1. Disables interaction immediately upon click (via isLoading) to prevent
21
+ * accidental double-submissions.
22
+ * 2. Provides immediate visual feedback (Spinner).
23
+ */
24
+ export function SubmitButton({
25
+ label,
26
+ loadingLabel = "Submitting…",
27
+ className,
28
+ form: formId,
29
+ disabled,
30
+ ...props
31
+ }: SubmitButtonProps) {
32
+ const form = useFormContext();
33
+ return (
34
+ <form.Subscribe selector={isSubmittingSelector}>
35
+ {(isSubmitting: boolean) => (
36
+ <Button
37
+ type="submit"
38
+ form={formId}
39
+ className={cn("w-full", className)}
40
+ disabled={isSubmitting || disabled}
41
+ {...props}
42
+ >
43
+ {isSubmitting && <Spinner className="mr-2" aria-hidden="true" />}
44
+ {isSubmitting ? loadingLabel : label}
45
+ </Button>
46
+ )}
47
+ </form.Subscribe>
48
+ );
49
+ }
@@ -0,0 +1,23 @@
1
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card";
2
+
3
+ interface CardLayoutProps {
4
+ title: string;
5
+ description?: string;
6
+ children: React.ReactNode;
7
+ }
8
+
9
+ /**
10
+ * Card layout component for authentication pages.
11
+ * Provides CardHeader with title and optional description, and CardContent.
12
+ */
13
+ export function CardLayout({ title, description, children }: CardLayoutProps) {
14
+ return (
15
+ <Card>
16
+ <CardHeader>
17
+ <CardTitle className="text-2xl">{title}</CardTitle>
18
+ {description && <CardDescription>{description}</CardDescription>}
19
+ </CardHeader>
20
+ <CardContent>{children}</CardContent>
21
+ </Card>
22
+ );
23
+ }
@@ -0,0 +1,38 @@
1
+ import { CenteredPageLayout } from "./centered-page-layout";
2
+ import { Card, CardContent, CardHeader } from "../ui/card";
3
+ import { Skeleton } from "../ui/skeleton";
4
+
5
+ interface CardSkeletonProps {
6
+ /**
7
+ * Maximum width of the content container.
8
+ * @default "sm"
9
+ */
10
+ contentMaxWidth?: "sm" | "md" | "lg";
11
+ /**
12
+ * Accessible label for screen readers.
13
+ * @default "Loading…"
14
+ */
15
+ loadingText?: string;
16
+ }
17
+
18
+ /**
19
+ * Full-page loading indicator with skeleton card placeholder.
20
+ */
21
+ export function CardSkeleton({ contentMaxWidth, loadingText = "Loading…" }: CardSkeletonProps) {
22
+ return (
23
+ <CenteredPageLayout contentMaxWidth={contentMaxWidth}>
24
+ <div role="status" aria-live="polite">
25
+ <Card className="w-full">
26
+ <CardHeader>
27
+ <Skeleton className="h-4 w-2/3" />
28
+ <Skeleton className="h-4 w-1/2" />
29
+ </CardHeader>
30
+ <CardContent>
31
+ <Skeleton className="aspect-video w-full" />
32
+ </CardContent>
33
+ </Card>
34
+ <span className="sr-only">{loadingText}</span>
35
+ </div>
36
+ </CenteredPageLayout>
37
+ );
38
+ }
@@ -0,0 +1,73 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ /**
5
+ * Variant styles for the content container's maximum width.
6
+ * Controls the maximum width of the inner content area within the page layout.
7
+ */
8
+ const contentContainerVariants = cva("w-full", {
9
+ variants: {
10
+ contentMaxWidth: {
11
+ sm: "max-w-sm",
12
+ md: "max-w-md",
13
+ lg: "max-w-lg",
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ contentMaxWidth: "sm",
18
+ },
19
+ });
20
+
21
+ /**
22
+ * Props for the CenteredPageLayout component.
23
+ */
24
+ interface CenteredPageLayoutProps
25
+ extends React.ComponentProps<"div">,
26
+ VariantProps<typeof contentContainerVariants> {
27
+ /** The content to be displayed within the page layout */
28
+ children: React.ReactNode;
29
+ /**
30
+ * Maximum width of the content container.
31
+ * @default "sm"
32
+ */
33
+ contentMaxWidth?: "sm" | "md" | "lg";
34
+ /**
35
+ * Optional page title. If provided, will render a <title> component that React will place in the document head.
36
+ */
37
+ title?: string;
38
+ }
39
+
40
+ /**
41
+ * CenteredPageLayout component that provides consistent page structure and spacing.
42
+ *
43
+ * This component creates a full-viewport-height container that centers its content
44
+ * both horizontally and vertically. The inner content area has a configurable maximum width
45
+ * to prevent content from becoming too wide on large screens.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * <CenteredPageLayout contentMaxWidth="md">
50
+ * <YourPageContent />
51
+ * </CenteredPageLayout>
52
+ * ```
53
+ */
54
+ export function CenteredPageLayout({
55
+ contentMaxWidth,
56
+ className,
57
+ children,
58
+ title,
59
+ ...props
60
+ }: CenteredPageLayoutProps) {
61
+ return (
62
+ <>
63
+ {title && <title>{title}</title>}
64
+ <main
65
+ className={cn("flex min-h-svh w-full items-center justify-center p-6 md:p-10", className)}
66
+ data-slot="page-layout"
67
+ {...props}
68
+ >
69
+ <div className={contentContainerVariants({ contentMaxWidth })}>{children}</div>
70
+ </main>
71
+ </>
72
+ );
73
+ }
@@ -0,0 +1,69 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "../../lib/utils";
5
+
6
+ const alertVariants = cva(
7
+ "grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-card text-card-foreground",
12
+ destructive:
13
+ "text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ variant: "default",
18
+ },
19
+ },
20
+ );
21
+
22
+ function Alert({
23
+ className,
24
+ variant,
25
+ ...props
26
+ }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
27
+ return (
28
+ <div
29
+ data-slot="alert"
30
+ role="alert"
31
+ className={cn(alertVariants({ variant }), className)}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38
+ return (
39
+ <div
40
+ data-slot="alert-title"
41
+ className={cn(
42
+ "font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
43
+ className,
44
+ )}
45
+ {...props}
46
+ />
47
+ );
48
+ }
49
+
50
+ function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
51
+ return (
52
+ <div
53
+ data-slot="alert-description"
54
+ className={cn(
55
+ "text-muted-foreground text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
56
+ className,
57
+ )}
58
+ {...props}
59
+ />
60
+ );
61
+ }
62
+
63
+ function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
64
+ return (
65
+ <div data-slot="alert-action" className={cn("absolute top-2 right-2", className)} {...props} />
66
+ );
67
+ }
68
+
69
+ export { Alert, AlertTitle, AlertDescription, AlertAction };
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import { Slot } from "radix-ui";
4
+
5
+ import { cn } from "../../lib/utils";
6
+
7
+ const buttonVariants = cva(
8
+ "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
+ outline:
14
+ "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
15
+ secondary:
16
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
17
+ ghost:
18
+ "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
19
+ destructive:
20
+ "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ size: {
24
+ default:
25
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
26
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
27
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
28
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
29
+ icon: "size-8",
30
+ "icon-xs":
31
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
32
+ "icon-sm":
33
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
34
+ "icon-lg": "size-9",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ size: "default",
40
+ },
41
+ },
42
+ );
43
+
44
+ function Button({
45
+ className,
46
+ variant = "default",
47
+ size = "default",
48
+ asChild = false,
49
+ ...props
50
+ }: React.ComponentProps<"button"> &
51
+ VariantProps<typeof buttonVariants> & {
52
+ asChild?: boolean;
53
+ }) {
54
+ const Comp = asChild ? Slot.Root : "button";
55
+
56
+ return (
57
+ <Comp
58
+ data-slot="button"
59
+ data-variant={variant}
60
+ data-size={size}
61
+ className={cn(buttonVariants({ variant, size, className }))}
62
+ {...props}
63
+ />
64
+ );
65
+ }
66
+
67
+ export { Button, buttonVariants };