@julianoczkowski/create-trimble-app 2.0.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 (450) hide show
  1. package/README.md +191 -0
  2. package/bin/create-trimble-app.js +9 -0
  3. package/package.json +67 -0
  4. package/src/cli.js +134 -0
  5. package/src/frameworks.js +28 -0
  6. package/src/scaffold.js +209 -0
  7. package/src/utils/file.js +47 -0
  8. package/src/utils/git.js +140 -0
  9. package/src/utils/install.js +25 -0
  10. package/src/utils/logger.js +124 -0
  11. package/templates/angular/.cursor/commands/remove-dev-content.md +394 -0
  12. package/templates/angular/.cursor/mcp.json +13 -0
  13. package/templates/angular/.cursor/rules/modus-angular-20.mdc +82 -0
  14. package/templates/angular/.cursor/rules/modus-angular-accordion-state-management-short.mdc +45 -0
  15. package/templates/angular/.cursor/rules/modus-angular-accordion-state-management.mdc +322 -0
  16. package/templates/angular/.cursor/rules/modus-angular-best-practices.mdc +472 -0
  17. package/templates/angular/.cursor/rules/modus-angular-border-usage-short.mdc +48 -0
  18. package/templates/angular/.cursor/rules/modus-angular-border-usage.mdc +286 -0
  19. package/templates/angular/.cursor/rules/modus-angular-button-group-usage-short.mdc +47 -0
  20. package/templates/angular/.cursor/rules/modus-angular-button-group-usage.mdc +263 -0
  21. package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion-short.mdc +36 -0
  22. package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion.mdc +92 -0
  23. package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing-short.mdc +34 -0
  24. package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing.mdc +185 -0
  25. package/templates/angular/.cursor/rules/modus-angular-color-usage-short.mdc +56 -0
  26. package/templates/angular/.cursor/rules/modus-angular-color-usage.mdc +208 -0
  27. package/templates/angular/.cursor/rules/modus-angular-components-reference.mdc +114 -0
  28. package/templates/angular/.cursor/rules/modus-angular-design-system.mdc +273 -0
  29. package/templates/angular/.cursor/rules/modus-angular-development-workflow-short.mdc +43 -0
  30. package/templates/angular/.cursor/rules/modus-angular-development-workflow.mdc +145 -0
  31. package/templates/angular/.cursor/rules/modus-angular-essentials.mdc +272 -0
  32. package/templates/angular/.cursor/rules/modus-angular-forms-validation-short.mdc +56 -0
  33. package/templates/angular/.cursor/rules/modus-angular-forms-validation.mdc +124 -0
  34. package/templates/angular/.cursor/rules/modus-angular-icon-names.mdc +70 -0
  35. package/templates/angular/.cursor/rules/modus-angular-icons-short.mdc +40 -0
  36. package/templates/angular/.cursor/rules/modus-angular-icons.mdc +137 -0
  37. package/templates/angular/.cursor/rules/modus-angular-implementation-guides-short.mdc +36 -0
  38. package/templates/angular/.cursor/rules/modus-angular-implementation-guides.mdc +301 -0
  39. package/templates/angular/.cursor/rules/modus-angular-integration-short.mdc +60 -0
  40. package/templates/angular/.cursor/rules/modus-angular-integration.mdc +1096 -0
  41. package/templates/angular/.cursor/rules/modus-angular-master.mdc +164 -0
  42. package/templates/angular/.cursor/rules/modus-angular-modal-usage-short.mdc +51 -0
  43. package/templates/angular/.cursor/rules/modus-angular-modal-usage.mdc +115 -0
  44. package/templates/angular/.cursor/rules/modus-angular-navbar-usage-short.mdc +49 -0
  45. package/templates/angular/.cursor/rules/modus-angular-navbar-usage.mdc +146 -0
  46. package/templates/angular/.cursor/rules/modus-angular-no-emojis.mdc +66 -0
  47. package/templates/angular/.cursor/rules/modus-angular-opacity-utilities-short.mdc +43 -0
  48. package/templates/angular/.cursor/rules/modus-angular-opacity-utilities.mdc +160 -0
  49. package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu-short.mdc +51 -0
  50. package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu.mdc +83 -0
  51. package/templates/angular/.cursor/rules/modus-angular-semantic-html-short.mdc +36 -0
  52. package/templates/angular/.cursor/rules/modus-angular-semantic-html.mdc +81 -0
  53. package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage-short.mdc +50 -0
  54. package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage.mdc +136 -0
  55. package/templates/angular/.cursor/rules/modus-angular-table-usage-short.mdc +52 -0
  56. package/templates/angular/.cursor/rules/modus-angular-table-usage.mdc +151 -0
  57. package/templates/angular/.cursor/rules/modus-angular-tailwind-usage-short.mdc +44 -0
  58. package/templates/angular/.cursor/rules/modus-angular-tailwind-usage.mdc +242 -0
  59. package/templates/angular/.cursor/rules/modus-angular-themes-short.mdc +54 -0
  60. package/templates/angular/.cursor/rules/modus-angular-themes.mdc +222 -0
  61. package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage-short.mdc +52 -0
  62. package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage.mdc +130 -0
  63. package/templates/angular/.cursor/rules/ux/gestalt-laws-detailed.mdc +514 -0
  64. package/templates/angular/.cursor/rules/ux/ux-ui-foundations.mdc +235 -0
  65. package/templates/angular/.cursor/skills/run-lint-checks/SKILL.md +169 -0
  66. package/templates/angular/.editorconfig +17 -0
  67. package/templates/angular/.github/dependabot.yml +19 -0
  68. package/templates/angular/.github/workflows/a11y-check.yml +135 -0
  69. package/templates/angular/.github/workflows/ci.yml +44 -0
  70. package/templates/angular/.husky/pre-commit +32 -0
  71. package/templates/angular/.postcssrc.json +5 -0
  72. package/templates/angular/.vscode/extensions.json +4 -0
  73. package/templates/angular/.vscode/launch.json +20 -0
  74. package/templates/angular/.vscode/tasks.json +42 -0
  75. package/templates/angular/CLAUDE.md +148 -0
  76. package/templates/angular/README.md +92 -0
  77. package/templates/angular/amplify.yml +25 -0
  78. package/templates/angular/angular.json +106 -0
  79. package/templates/angular/data/modusIcons.ts +861 -0
  80. package/templates/angular/package-lock.json +11030 -0
  81. package/templates/angular/package.json +66 -0
  82. package/templates/angular/public/angular-icon.svg +12 -0
  83. package/templates/angular/public/favicon.ico +0 -0
  84. package/templates/angular/public/modus-icons.css +49 -0
  85. package/templates/angular/public/vite.svg +1 -0
  86. package/templates/angular/scripts/README.md +410 -0
  87. package/templates/angular/scripts/check-border-violations.js +352 -0
  88. package/templates/angular/scripts/check-icon-names.js +402 -0
  89. package/templates/angular/scripts/check-inline-styles.js +292 -0
  90. package/templates/angular/scripts/check-modus-colors.js +282 -0
  91. package/templates/angular/scripts/check-modus-icons.js +263 -0
  92. package/templates/angular/scripts/check-opacity-utilities.js +426 -0
  93. package/templates/angular/scripts/check-semantic-html.js +452 -0
  94. package/templates/angular/scripts/check-typescript.js +109 -0
  95. package/templates/angular/src/app/app.config.ts +29 -0
  96. package/templates/angular/src/app/app.css +0 -0
  97. package/templates/angular/src/app/app.html +4 -0
  98. package/templates/angular/src/app/app.routes.ts +351 -0
  99. package/templates/angular/src/app/app.spec.ts +27 -0
  100. package/templates/angular/src/app/app.ts +47 -0
  101. package/templates/angular/src/app/components/README.md +77 -0
  102. package/templates/angular/src/app/components/index.ts +53 -0
  103. package/templates/angular/src/app/components/modus-accordion.component.ts +50 -0
  104. package/templates/angular/src/app/components/modus-alert.component.ts +133 -0
  105. package/templates/angular/src/app/components/modus-autocomplete.component.ts +262 -0
  106. package/templates/angular/src/app/components/modus-avatar.component.ts +75 -0
  107. package/templates/angular/src/app/components/modus-badge.component.ts +84 -0
  108. package/templates/angular/src/app/components/modus-breadcrumbs.component.ts +65 -0
  109. package/templates/angular/src/app/components/modus-button-group.component.ts +82 -0
  110. package/templates/angular/src/app/components/modus-button.component.ts +292 -0
  111. package/templates/angular/src/app/components/modus-card.component.ts +73 -0
  112. package/templates/angular/src/app/components/modus-checkbox.component.ts +117 -0
  113. package/templates/angular/src/app/components/modus-chip.component.ts +97 -0
  114. package/templates/angular/src/app/components/modus-collapse.component.ts +118 -0
  115. package/templates/angular/src/app/components/modus-date.component.ts +165 -0
  116. package/templates/angular/src/app/components/modus-dropdown-menu.component.ts +108 -0
  117. package/templates/angular/src/app/components/modus-file-dropzone.component.ts +121 -0
  118. package/templates/angular/src/app/components/modus-handle.component.ts +96 -0
  119. package/templates/angular/src/app/components/modus-icon.component.ts +81 -0
  120. package/templates/angular/src/app/components/modus-input-feedback.component.ts +54 -0
  121. package/templates/angular/src/app/components/modus-input-label.component.ts +62 -0
  122. package/templates/angular/src/app/components/modus-loader.component.ts +48 -0
  123. package/templates/angular/src/app/components/modus-logo.component.ts +115 -0
  124. package/templates/angular/src/app/components/modus-menu-item.component.ts +116 -0
  125. package/templates/angular/src/app/components/modus-menu.component.ts +58 -0
  126. package/templates/angular/src/app/components/modus-modal.component.ts +70 -0
  127. package/templates/angular/src/app/components/modus-navbar.component.ts +303 -0
  128. package/templates/angular/src/app/components/modus-number-input.component.ts +174 -0
  129. package/templates/angular/src/app/components/modus-pagination.component.ts +74 -0
  130. package/templates/angular/src/app/components/modus-panel.component.ts +61 -0
  131. package/templates/angular/src/app/components/modus-progress.component.ts +62 -0
  132. package/templates/angular/src/app/components/modus-radio.component.ts +102 -0
  133. package/templates/angular/src/app/components/modus-rating.component.ts +80 -0
  134. package/templates/angular/src/app/components/modus-select.component.ts +131 -0
  135. package/templates/angular/src/app/components/modus-side-navigation.component.ts +90 -0
  136. package/templates/angular/src/app/components/modus-skeleton.component.ts +54 -0
  137. package/templates/angular/src/app/components/modus-slider.component.ts +132 -0
  138. package/templates/angular/src/app/components/modus-stepper.component.ts +65 -0
  139. package/templates/angular/src/app/components/modus-switch.component.ts +118 -0
  140. package/templates/angular/src/app/components/modus-table.component.ts +204 -0
  141. package/templates/angular/src/app/components/modus-tabs.component.ts +82 -0
  142. package/templates/angular/src/app/components/modus-text-input.component.ts +221 -0
  143. package/templates/angular/src/app/components/modus-textarea.component.ts +168 -0
  144. package/templates/angular/src/app/components/modus-theme-switcher.component.ts +45 -0
  145. package/templates/angular/src/app/components/modus-time-input.component.ts +172 -0
  146. package/templates/angular/src/app/components/modus-toast.component.ts +63 -0
  147. package/templates/angular/src/app/components/modus-toolbar.component.ts +43 -0
  148. package/templates/angular/src/app/components/modus-tooltip.component.ts +83 -0
  149. package/templates/angular/src/app/components/modus-typography.component.ts +79 -0
  150. package/templates/angular/src/app/components/modus-utility-panel.component.ts +275 -0
  151. package/templates/angular/src/app/components/theme-demo.component.ts +1242 -0
  152. package/templates/angular/src/app/data/component-demos.ts +360 -0
  153. package/templates/angular/src/app/data/modus-icons.ts +806 -0
  154. package/templates/angular/src/app/demos/accordion/accordion-demo.component.ts +212 -0
  155. package/templates/angular/src/app/demos/alert/alert-demo.component.ts +108 -0
  156. package/templates/angular/src/app/demos/autocomplete/autocomplete-demo.component.ts +174 -0
  157. package/templates/angular/src/app/demos/avatar/avatar-demo.component.ts +149 -0
  158. package/templates/angular/src/app/demos/badge/badge-demo.component.ts +148 -0
  159. package/templates/angular/src/app/demos/breadcrumbs/breadcrumbs-demo.component.ts +96 -0
  160. package/templates/angular/src/app/demos/button/button-demo.component.ts +256 -0
  161. package/templates/angular/src/app/demos/button-group/button-group-demo.component.ts +215 -0
  162. package/templates/angular/src/app/demos/card/card-demo.component.ts +180 -0
  163. package/templates/angular/src/app/demos/checkbox/checkbox-demo.component.ts +71 -0
  164. package/templates/angular/src/app/demos/chip/chip-demo.component.ts +183 -0
  165. package/templates/angular/src/app/demos/date/date-demo.component.ts +193 -0
  166. package/templates/angular/src/app/demos/dropdown/dropdown-demo.component.ts +196 -0
  167. package/templates/angular/src/app/demos/file-dropzone/file-dropzone-demo.component.ts +176 -0
  168. package/templates/angular/src/app/demos/handle/handle-demo.component.ts +265 -0
  169. package/templates/angular/src/app/demos/icon/icon-demo.component.ts +65 -0
  170. package/templates/angular/src/app/demos/input-feedback/input-feedback-demo.component.ts +189 -0
  171. package/templates/angular/src/app/demos/input-label/input-label-demo.component.ts +330 -0
  172. package/templates/angular/src/app/demos/loader/loader-demo.component.ts +143 -0
  173. package/templates/angular/src/app/demos/logo/logo-demo.component.ts +191 -0
  174. package/templates/angular/src/app/demos/menu/menu-demo.component.ts +72 -0
  175. package/templates/angular/src/app/demos/modal/modal-demo.component.ts +278 -0
  176. package/templates/angular/src/app/demos/navbar/navbar-demo.component.ts +135 -0
  177. package/templates/angular/src/app/demos/number-input/number-input-demo.component.ts +175 -0
  178. package/templates/angular/src/app/demos/pagination/pagination-demo.component.ts +134 -0
  179. package/templates/angular/src/app/demos/panel/panel-demo.component.ts +235 -0
  180. package/templates/angular/src/app/demos/progress/progress-demo.component.ts +169 -0
  181. package/templates/angular/src/app/demos/radio/radio-demo.component.ts +161 -0
  182. package/templates/angular/src/app/demos/rating/rating-demo.component.ts +97 -0
  183. package/templates/angular/src/app/demos/select/select-demo.component.ts +107 -0
  184. package/templates/angular/src/app/demos/shared/demo-example-clean.component.ts +41 -0
  185. package/templates/angular/src/app/demos/shared/demo-example.component.ts +42 -0
  186. package/templates/angular/src/app/demos/shared/demo-page.component.ts +97 -0
  187. package/templates/angular/src/app/demos/shared/index.ts +3 -0
  188. package/templates/angular/src/app/demos/side-navigation/side-navigation-demo.component.ts +524 -0
  189. package/templates/angular/src/app/demos/skeleton/skeleton-demo.component.ts +112 -0
  190. package/templates/angular/src/app/demos/slider/slider-demo.component.ts +76 -0
  191. package/templates/angular/src/app/demos/stepper/stepper-demo.component.ts +79 -0
  192. package/templates/angular/src/app/demos/switch/switch-demo.component.ts +113 -0
  193. package/templates/angular/src/app/demos/table/table-demo.component.ts +405 -0
  194. package/templates/angular/src/app/demos/tabs/tabs-demo.component.ts +318 -0
  195. package/templates/angular/src/app/demos/text-input/text-input-demo.component.ts +160 -0
  196. package/templates/angular/src/app/demos/textarea/textarea-demo.component.ts +95 -0
  197. package/templates/angular/src/app/demos/theme-switcher/theme-switcher-demo.component.ts +38 -0
  198. package/templates/angular/src/app/demos/time-input/time-input-demo.component.ts +130 -0
  199. package/templates/angular/src/app/demos/toast/toast-demo.component.ts +258 -0
  200. package/templates/angular/src/app/demos/toolbar/toolbar-demo.component.ts +54 -0
  201. package/templates/angular/src/app/demos/tooltip/tooltip-demo.component.ts +163 -0
  202. package/templates/angular/src/app/demos/utility-panel/utility-panel-demo.component.ts +197 -0
  203. package/templates/angular/src/app/dev/dev-config.ts +119 -0
  204. package/templates/angular/src/app/dev/dev-panel/dev-panel.component.ts +215 -0
  205. package/templates/angular/src/app/dev/dev-panel.service.ts +63 -0
  206. package/templates/angular/src/app/dev/index.ts +8 -0
  207. package/templates/angular/src/app/dev/theme-switcher-dropdown/theme-switcher-dropdown.component.ts +134 -0
  208. package/templates/angular/src/app/dev-pages/color-palette/color-palette.component.ts +229 -0
  209. package/templates/angular/src/app/dev-pages/components-gallery/components-gallery.component.ts +486 -0
  210. package/templates/angular/src/app/dev-pages/icons/icons.component.ts +149 -0
  211. package/templates/angular/src/app/pages/home/home.component.ts +251 -0
  212. package/templates/angular/src/app/services/README.md +57 -0
  213. package/templates/angular/src/app/services/theme.service.ts +163 -0
  214. package/templates/angular/src/environments/environment.development.ts +8 -0
  215. package/templates/angular/src/environments/environment.ts +8 -0
  216. package/templates/angular/src/index.html +14 -0
  217. package/templates/angular/src/main.ts +6 -0
  218. package/templates/angular/src/styles.css +1328 -0
  219. package/templates/angular/tsconfig.app.json +15 -0
  220. package/templates/angular/tsconfig.json +35 -0
  221. package/templates/angular/tsconfig.spec.json +14 -0
  222. package/templates/config.json +23 -0
  223. package/templates/react/.cursor/commands/remove-dev-content.md +311 -0
  224. package/templates/react/.cursor/mcp.json +13 -0
  225. package/templates/react/.cursor/rules/README.md +240 -0
  226. package/templates/react/.cursor/rules/border-usage-guidelines-short.mdc +22 -0
  227. package/templates/react/.cursor/rules/border-usage-guidelines.mdc +380 -0
  228. package/templates/react/.cursor/rules/chrome-devtools-testing-react-short.mdc +23 -0
  229. package/templates/react/.cursor/rules/development-workflow-react-short.mdc +23 -0
  230. package/templates/react/.cursor/rules/development-workflow-react.mdc +292 -0
  231. package/templates/react/.cursor/rules/implementation-guides-react-short.mdc +23 -0
  232. package/templates/react/.cursor/rules/implementation-guides-react.mdc +446 -0
  233. package/templates/react/.cursor/rules/modus-accordion-state-management-react-short.mdc +23 -0
  234. package/templates/react/.cursor/rules/modus-accordion-state-management-react.mdc +445 -0
  235. package/templates/react/.cursor/rules/modus-button-group-usage-react-short.mdc +23 -0
  236. package/templates/react/.cursor/rules/modus-button-group-usage-react.mdc +117 -0
  237. package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react-short.mdc +23 -0
  238. package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react.mdc +492 -0
  239. package/templates/react/.cursor/rules/modus-color-usage-react-short.mdc +23 -0
  240. package/templates/react/.cursor/rules/modus-color-usage-react.mdc +420 -0
  241. package/templates/react/.cursor/rules/modus-components-reference.mdc +366 -0
  242. package/templates/react/.cursor/rules/modus-icon-names.mdc +63 -0
  243. package/templates/react/.cursor/rules/modus-icons-react-short.mdc +24 -0
  244. package/templates/react/.cursor/rules/modus-icons-react.mdc +402 -0
  245. package/templates/react/.cursor/rules/modus-modal-implementation-react-short.mdc +23 -0
  246. package/templates/react/.cursor/rules/modus-modal-implementation-react.mdc +831 -0
  247. package/templates/react/.cursor/rules/modus-navbar-side-navigation-react-short.mdc +23 -0
  248. package/templates/react/.cursor/rules/modus-navbar-side-navigation-react.mdc +247 -0
  249. package/templates/react/.cursor/rules/modus-no-emojis-react-short.mdc +23 -0
  250. package/templates/react/.cursor/rules/modus-opacity-utilities-react-short.mdc +70 -0
  251. package/templates/react/.cursor/rules/modus-opacity-utilities-react.mdc +208 -0
  252. package/templates/react/.cursor/rules/modus-react-best-practices-short.mdc +23 -0
  253. package/templates/react/.cursor/rules/modus-react-best-practices.mdc +508 -0
  254. package/templates/react/.cursor/rules/modus-react-essentials.mdc +209 -0
  255. package/templates/react/.cursor/rules/modus-react-integration-short.mdc +23 -0
  256. package/templates/react/.cursor/rules/modus-react-integration.mdc +509 -0
  257. package/templates/react/.cursor/rules/modus-react-key-warnings-short.mdc +23 -0
  258. package/templates/react/.cursor/rules/modus-react-key-warnings.mdc +805 -0
  259. package/templates/react/.cursor/rules/modus-react-master.mdc +160 -0
  260. package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react-short.mdc +23 -0
  261. package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react.mdc +442 -0
  262. package/templates/react/.cursor/rules/modus-semantic-html-react-short.mdc +23 -0
  263. package/templates/react/.cursor/rules/modus-semantic-html-react.mdc +427 -0
  264. package/templates/react/.cursor/rules/modus-tailwind-usage-react-short.mdc +23 -0
  265. package/templates/react/.cursor/rules/modus-tailwind-usage-react.mdc +642 -0
  266. package/templates/react/.cursor/rules/modus-themes-react-short.mdc +23 -0
  267. package/templates/react/.cursor/rules/modus-themes-react.mdc +506 -0
  268. package/templates/react/.cursor/rules/ux/gestalt-laws-detailed.mdc +456 -0
  269. package/templates/react/.cursor/rules/ux/ux-ui-foundations.mdc +211 -0
  270. package/templates/react/.cursor/skills/create-modus-form-component/SKILL.md +518 -0
  271. package/templates/react/.cursor/skills/create-modus-wrapper-component/SKILL.md +252 -0
  272. package/templates/react/.cursor/skills/fix-modus-component-event-issues/SKILL.md +345 -0
  273. package/templates/react/.cursor/skills/handle-modus-checkbox-value-bug/SKILL.md +202 -0
  274. package/templates/react/.cursor/skills/implement-modus-modal-with-refs/SKILL.md +386 -0
  275. package/templates/react/.cursor/skills/integrate-modus-icons/SKILL.md +300 -0
  276. package/templates/react/.cursor/skills/run-lint-checks/SKILL.md +235 -0
  277. package/templates/react/.cursor/skills/set-up-modus-event-listeners/SKILL.md +284 -0
  278. package/templates/react/.cursor/skills/style-modus-components-with-tailwind/SKILL.md +382 -0
  279. package/templates/react/.env.development +3 -0
  280. package/templates/react/.env.production +3 -0
  281. package/templates/react/.github/CODEOWNERS +28 -0
  282. package/templates/react/.github/ISSUE_TEMPLATE/bug_report.yml +176 -0
  283. package/templates/react/.github/ISSUE_TEMPLATE/config.yml +20 -0
  284. package/templates/react/.github/ISSUE_TEMPLATE/documentation.yml +115 -0
  285. package/templates/react/.github/ISSUE_TEMPLATE/feature_request.yml +171 -0
  286. package/templates/react/.github/ISSUE_TEMPLATE/question.yml +139 -0
  287. package/templates/react/.github/copilot-instructions.md +80 -0
  288. package/templates/react/.github/instructions/components.instructions.md +82 -0
  289. package/templates/react/.github/instructions/demos.instructions.md +82 -0
  290. package/templates/react/.github/instructions/pages.instructions.md +76 -0
  291. package/templates/react/.github/instructions/styles.instructions.md +77 -0
  292. package/templates/react/.github/instructions/typescript.instructions.md +101 -0
  293. package/templates/react/.github/pull_request_template.md +188 -0
  294. package/templates/react/.github/workflows/ci.yml +43 -0
  295. package/templates/react/.github/workflows/claude-code-review.yml +44 -0
  296. package/templates/react/.github/workflows/claude.yml +50 -0
  297. package/templates/react/.husky/pre-commit +28 -0
  298. package/templates/react/.vscode/extensions.json +8 -0
  299. package/templates/react/CLAUDE.md +119 -0
  300. package/templates/react/CODE_OF_CONDUCT.md +79 -0
  301. package/templates/react/CONTRIBUTING.md +65 -0
  302. package/templates/react/LICENSE +21 -0
  303. package/templates/react/README.md +728 -0
  304. package/templates/react/SECURITY.md +50 -0
  305. package/templates/react/eslint.config.js +23 -0
  306. package/templates/react/index.html +13 -0
  307. package/templates/react/package-lock.json +5209 -0
  308. package/templates/react/package.json +49 -0
  309. package/templates/react/postcss.config.js +6 -0
  310. package/templates/react/public/react.svg +1 -0
  311. package/templates/react/public/vite.svg +1 -0
  312. package/templates/react/readme_assets/getting_started_header.png +0 -0
  313. package/templates/react/readme_assets/hero.png +0 -0
  314. package/templates/react/readme_assets/modus_comp.png +0 -0
  315. package/templates/react/readme_assets/modus_figma_mcp.png +0 -0
  316. package/templates/react/readme_assets/teaser_comp.gif +0 -0
  317. package/templates/react/scripts/README.md +343 -0
  318. package/templates/react/scripts/check-border-violations.js +483 -0
  319. package/templates/react/scripts/check-icon-names.js +486 -0
  320. package/templates/react/scripts/check-inline-styles.js +364 -0
  321. package/templates/react/scripts/check-modus-colors.js +247 -0
  322. package/templates/react/scripts/check-modus-icons.js +256 -0
  323. package/templates/react/scripts/check-opacity-utilities.js +481 -0
  324. package/templates/react/scripts/check-semantic-html.js +476 -0
  325. package/templates/react/scripts/check-typescript.js +109 -0
  326. package/templates/react/src/App.css +42 -0
  327. package/templates/react/src/App.tsx +54 -0
  328. package/templates/react/src/assets/react.svg +1 -0
  329. package/templates/react/src/components/DemoExample.tsx +61 -0
  330. package/templates/react/src/components/DemoPage.tsx +81 -0
  331. package/templates/react/src/components/ModusAccordion.tsx +89 -0
  332. package/templates/react/src/components/ModusAlert.tsx +85 -0
  333. package/templates/react/src/components/ModusAutocomplete.tsx +207 -0
  334. package/templates/react/src/components/ModusAvatar.tsx +50 -0
  335. package/templates/react/src/components/ModusBadge.tsx +82 -0
  336. package/templates/react/src/components/ModusBreadcrumbs.tsx +75 -0
  337. package/templates/react/src/components/ModusButton.tsx +244 -0
  338. package/templates/react/src/components/ModusButtonGroup.tsx +91 -0
  339. package/templates/react/src/components/ModusCard.tsx +70 -0
  340. package/templates/react/src/components/ModusCheckbox.tsx +168 -0
  341. package/templates/react/src/components/ModusChip.tsx +93 -0
  342. package/templates/react/src/components/ModusDate.tsx +154 -0
  343. package/templates/react/src/components/ModusDropdownMenu.tsx +148 -0
  344. package/templates/react/src/components/ModusFileDropzone.tsx +140 -0
  345. package/templates/react/src/components/ModusHandle.tsx +101 -0
  346. package/templates/react/src/components/ModusIcon.tsx +49 -0
  347. package/templates/react/src/components/ModusInputFeedback.tsx +52 -0
  348. package/templates/react/src/components/ModusInputLabel.tsx +50 -0
  349. package/templates/react/src/components/ModusLoader.tsx +42 -0
  350. package/templates/react/src/components/ModusLogo.tsx +102 -0
  351. package/templates/react/src/components/ModusMenu.tsx +119 -0
  352. package/templates/react/src/components/ModusMenuItem.tsx +86 -0
  353. package/templates/react/src/components/ModusModal.tsx +145 -0
  354. package/templates/react/src/components/ModusNavbar.tsx +504 -0
  355. package/templates/react/src/components/ModusNumberInput.tsx +230 -0
  356. package/templates/react/src/components/ModusPagination.tsx +94 -0
  357. package/templates/react/src/components/ModusPanel.tsx +92 -0
  358. package/templates/react/src/components/ModusProgress.tsx +70 -0
  359. package/templates/react/src/components/ModusProvider.tsx +18 -0
  360. package/templates/react/src/components/ModusRadio.tsx +114 -0
  361. package/templates/react/src/components/ModusRating.tsx +108 -0
  362. package/templates/react/src/components/ModusSelect.tsx +171 -0
  363. package/templates/react/src/components/ModusSideNavigation.tsx +149 -0
  364. package/templates/react/src/components/ModusSkeleton.tsx +42 -0
  365. package/templates/react/src/components/ModusSlider.tsx +128 -0
  366. package/templates/react/src/components/ModusStepper.tsx +85 -0
  367. package/templates/react/src/components/ModusSwitch.tsx +130 -0
  368. package/templates/react/src/components/ModusTable.tsx +309 -0
  369. package/templates/react/src/components/ModusTabs.tsx +114 -0
  370. package/templates/react/src/components/ModusTextInput.tsx +179 -0
  371. package/templates/react/src/components/ModusTextarea.tsx +164 -0
  372. package/templates/react/src/components/ModusThemeSwitcher.tsx +58 -0
  373. package/templates/react/src/components/ModusTimeInput.tsx +176 -0
  374. package/templates/react/src/components/ModusToast.tsx +207 -0
  375. package/templates/react/src/components/ModusToolbar.tsx +70 -0
  376. package/templates/react/src/components/ModusTooltip.tsx +97 -0
  377. package/templates/react/src/components/ModusUtilityPanel.tsx +198 -0
  378. package/templates/react/src/components/ThemeSwitcherDropdown.tsx +117 -0
  379. package/templates/react/src/components/ThemeToggleSimple.tsx +157 -0
  380. package/templates/react/src/config/routes.ts +196 -0
  381. package/templates/react/src/contexts/ThemeContext.tsx +81 -0
  382. package/templates/react/src/contexts/ThemeContextData.tsx +89 -0
  383. package/templates/react/src/data/modusIcons.ts +865 -0
  384. package/templates/react/src/demos/accordion-demo/page.tsx +236 -0
  385. package/templates/react/src/demos/alert-demo/page.tsx +94 -0
  386. package/templates/react/src/demos/autocomplete-demo/page.tsx +166 -0
  387. package/templates/react/src/demos/avatar-demo/page.tsx +135 -0
  388. package/templates/react/src/demos/badge-demo/page.tsx +174 -0
  389. package/templates/react/src/demos/breadcrumbs-demo/page.tsx +88 -0
  390. package/templates/react/src/demos/button-demo/page.tsx +261 -0
  391. package/templates/react/src/demos/button-group-demo/page.tsx +231 -0
  392. package/templates/react/src/demos/card-demo/page.tsx +241 -0
  393. package/templates/react/src/demos/checkbox-demo/page.tsx +79 -0
  394. package/templates/react/src/demos/chip-demo/page.tsx +197 -0
  395. package/templates/react/src/demos/date-demo/page.tsx +179 -0
  396. package/templates/react/src/demos/dropdown-demo/page.tsx +150 -0
  397. package/templates/react/src/demos/file-dropzone-demo/page.tsx +186 -0
  398. package/templates/react/src/demos/handle-demo/page.tsx +313 -0
  399. package/templates/react/src/demos/icon-demo/page.tsx +72 -0
  400. package/templates/react/src/demos/input-feedback-demo/page.tsx +202 -0
  401. package/templates/react/src/demos/input-label-demo/page.tsx +392 -0
  402. package/templates/react/src/demos/loader-demo/page.tsx +138 -0
  403. package/templates/react/src/demos/logo-demo/page.tsx +292 -0
  404. package/templates/react/src/demos/menu-demo/page.tsx +70 -0
  405. package/templates/react/src/demos/modal-demo/page.tsx +332 -0
  406. package/templates/react/src/demos/navbar-demo/page.tsx +141 -0
  407. package/templates/react/src/demos/number-input-demo/page.tsx +180 -0
  408. package/templates/react/src/demos/pagination-demo/page.tsx +147 -0
  409. package/templates/react/src/demos/panel-demo/page.tsx +376 -0
  410. package/templates/react/src/demos/progress-demo/page.tsx +185 -0
  411. package/templates/react/src/demos/radio-demo/page.tsx +242 -0
  412. package/templates/react/src/demos/rating-demo/page.tsx +97 -0
  413. package/templates/react/src/demos/select-demo/page.tsx +111 -0
  414. package/templates/react/src/demos/side-navigation-demo/page.tsx +775 -0
  415. package/templates/react/src/demos/skeleton-demo/page.tsx +107 -0
  416. package/templates/react/src/demos/slider-demo/page.tsx +78 -0
  417. package/templates/react/src/demos/stepper-demo/page.tsx +86 -0
  418. package/templates/react/src/demos/switch-demo/page.tsx +146 -0
  419. package/templates/react/src/demos/table-demo/page.tsx +489 -0
  420. package/templates/react/src/demos/tabs-demo/page.tsx +187 -0
  421. package/templates/react/src/demos/text-input-demo/page.tsx +151 -0
  422. package/templates/react/src/demos/textarea-demo/page.tsx +73 -0
  423. package/templates/react/src/demos/theme-switcher-demo/page.tsx +26 -0
  424. package/templates/react/src/demos/time-input-demo/page.tsx +148 -0
  425. package/templates/react/src/demos/toast-demo/page.tsx +302 -0
  426. package/templates/react/src/demos/toolbar-demo/page.tsx +49 -0
  427. package/templates/react/src/demos/tooltip-demo/page.tsx +209 -0
  428. package/templates/react/src/demos/typography-test/page.tsx +28 -0
  429. package/templates/react/src/demos/utility-panel-demo/page.tsx +197 -0
  430. package/templates/react/src/dev/DevPanel.tsx +219 -0
  431. package/templates/react/src/dev/DevPanelContext.ts +14 -0
  432. package/templates/react/src/dev/DevPanelProvider.tsx +63 -0
  433. package/templates/react/src/dev/DevRoutes.tsx +98 -0
  434. package/templates/react/src/dev/config.ts +127 -0
  435. package/templates/react/src/dev/index.ts +8 -0
  436. package/templates/react/src/dev/useDevPanel.ts +17 -0
  437. package/templates/react/src/dev-pages/ColorPalettePage.tsx +347 -0
  438. package/templates/react/src/dev-pages/ComponentsGalleryPage.tsx +489 -0
  439. package/templates/react/src/dev-pages/IconsPage.tsx +137 -0
  440. package/templates/react/src/dev-pages/index.ts +3 -0
  441. package/templates/react/src/hooks/useTheme.ts +15 -0
  442. package/templates/react/src/index.css +635 -0
  443. package/templates/react/src/main.tsx +14 -0
  444. package/templates/react/src/pages/HomePage.tsx +283 -0
  445. package/templates/react/src/vite-env.d.ts +9 -0
  446. package/templates/react/tailwind.config.js +58 -0
  447. package/templates/react/tsconfig.app.json +27 -0
  448. package/templates/react/tsconfig.json +7 -0
  449. package/templates/react/tsconfig.node.json +25 -0
  450. package/templates/react/vite.config.ts +18 -0
@@ -0,0 +1,805 @@
1
+ ---
2
+ description: Critical React key prop patterns for Modus Web Components
3
+ globs: ["**/*.tsx"]
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Modus React Key Warnings - Essential Rules
8
+
9
+ ## 🚨 CRITICAL: React Key Props with Modus Web Components
10
+
11
+ When using Modus Web Components in React, proper key handling is essential to prevent React warnings and ensure optimal performance.
12
+
13
+ ## ❌ NEVER Do These
14
+
15
+ ### 1. Missing Key Props on Mapped Components
16
+
17
+ ```tsx
18
+ // ❌ WRONG - No key prop
19
+ {
20
+ items.map((item) => (
21
+ <ModusWcMenuItem label={item.label} value={item.value} />
22
+ ));
23
+ }
24
+
25
+ // ❌ WRONG - Using index only as key
26
+ {
27
+ items.map((item, index) => (
28
+ <ModusWcMenuItem key={index} label={item.label} value={item.value} />
29
+ ));
30
+ }
31
+ ```
32
+
33
+ ### 2. Using Slots Instead of Props for Icons
34
+
35
+ ```tsx
36
+ // ❌ WRONG - Using slot content causes key issues
37
+ <ModusWcMenuItem label={item.label} value={item.value}>
38
+ {item.startIcon && (
39
+ <i className="modus-icons" slot="start-icon">
40
+ {item.startIcon}
41
+ </i>
42
+ )}
43
+ </ModusWcMenuItem>
44
+ ```
45
+
46
+ ### 3. Wrapping Web Components in Divs
47
+
48
+ ```tsx
49
+ // ❌ WRONG - Div wrapper interferes with web component
50
+ {
51
+ items.map((item) => (
52
+ <div key={item.value}>
53
+ <ModusWcMenuItem label={item.label} value={item.value} />
54
+ </div>
55
+ ));
56
+ }
57
+ ```
58
+
59
+ ## ✅ ALWAYS Do These
60
+
61
+ ### 1. Use Composite Keys for Web Components
62
+
63
+ ```tsx
64
+ // ✅ CORRECT - Composite key ensures uniqueness
65
+ {
66
+ items.map((item, index) => (
67
+ <ModusWcMenuItem
68
+ key={`${item.value}-${index}`}
69
+ label={item.label}
70
+ value={item.value}
71
+ start-icon={item.startIcon}
72
+ />
73
+ ));
74
+ }
75
+ ```
76
+
77
+ ### 2. Use Props Instead of Slots for Modus Components
78
+
79
+ ```tsx
80
+ // ✅ CORRECT - Use start-icon prop
81
+ <ModusWcMenuItem
82
+ key={`${item.value}-${index}`}
83
+ label={item.label}
84
+ value={item.value}
85
+ start-icon={item.startIcon}
86
+ sub-label={item.subLabel}
87
+ selected={item.selected}
88
+ disabled={item.disabled}
89
+ bordered={item.bordered}
90
+ />
91
+ ```
92
+
93
+ ### 3. Handle Dynamic Content Properly
94
+
95
+ ```tsx
96
+ // ✅ CORRECT - Safe key generation
97
+ const generateKey = (item: MenuItem, index: number) => {
98
+ return item.value ? `${item.value}-${index}` : `item-${index}`;
99
+ };
100
+
101
+ {
102
+ items.map((item, index) => (
103
+ <ModusWcMenuItem
104
+ key={generateKey(item, index)}
105
+ label={item.label}
106
+ value={item.value}
107
+ />
108
+ ));
109
+ }
110
+ ```
111
+
112
+ ## 🎯 Key Patterns for Different Modus Components
113
+
114
+ ### ModusWcMenuItem
115
+
116
+ ```tsx
117
+ // ✅ CORRECT
118
+ {
119
+ menuItems.map((item, index) => (
120
+ <ModusWcMenuItem
121
+ key={`${item.value}-${index}`}
122
+ label={item.label}
123
+ value={item.value}
124
+ start-icon={item.startIcon}
125
+ sub-label={item.subLabel}
126
+ />
127
+ ));
128
+ }
129
+ ```
130
+
131
+ ### ModusWcTabs
132
+
133
+ ```tsx
134
+ // ✅ CORRECT
135
+ {
136
+ panels.map((panel, index) => (
137
+ <div key={index} slot={`tab-${index}`}>
138
+ {panel}
139
+ </div>
140
+ ));
141
+ }
142
+ ```
143
+
144
+ ### ModusWcDropdownMenu
145
+
146
+ ```tsx
147
+ // ✅ CORRECT
148
+ {
149
+ menuItems.map((item, index) => (
150
+ <ModusWcMenuItem
151
+ key={`${item.value}-${index}`}
152
+ label={item.label}
153
+ value={item.value}
154
+ start-icon={item.startIcon}
155
+ />
156
+ ));
157
+ }
158
+ ```
159
+
160
+ ## 🚨 Common Warning Messages
161
+
162
+ ### React Key Warning
163
+
164
+ ```text
165
+ Each child in a list should have a unique "key" prop.
166
+ Check the render method of `ModusWcMenu2`. It was passed a child from ModusMenu.
167
+ ```
168
+
169
+ **Solution**: Use composite keys and props instead of slots.
170
+
171
+ ### Web Component Slot Issues
172
+
173
+ ```text
174
+ Warning: React does not recognize the `slot` prop on a DOM element.
175
+ ```
176
+
177
+ **Solution**: Use component props instead of slot attributes.
178
+
179
+ ### Common Pitfalls and Solutions
180
+
181
+ #### ❌ Pitfall: Using Array Index as Key
182
+
183
+ ```tsx
184
+ // ❌ PROBLEMATIC - Can cause issues with reordering
185
+ {
186
+ items.map((item, index) => <ModusWcMenuItem key={index} {...item} />);
187
+ }
188
+ ```
189
+
190
+ #### ✅ Solution: Use Stable Identifiers
191
+
192
+ ```tsx
193
+ // ✅ CORRECT - Use unique, stable identifier
194
+ {
195
+ items.map((item) => <ModusWcMenuItem key={item.id} {...item} />);
196
+ }
197
+ ```
198
+
199
+ #### ❌ Pitfall: Missing Event Cleanup
200
+
201
+ ```tsx
202
+ // ❌ PROBLEMATIC - Memory leaks
203
+ useEffect(() => {
204
+ const element = ref.current;
205
+ element?.addEventListener("itemSelect", handler);
206
+ // Missing cleanup!
207
+ }, []);
208
+ ```
209
+
210
+ #### ✅ Solution: Proper Cleanup
211
+
212
+ ```tsx
213
+ // ✅ CORRECT - Clean up event listeners
214
+ useEffect(() => {
215
+ const element = ref.current;
216
+ if (!element) return;
217
+
218
+ element.addEventListener("itemSelect", handler);
219
+
220
+ return () => {
221
+ element.removeEventListener("itemSelect", handler);
222
+ };
223
+ }, [handler]);
224
+ ```
225
+
226
+ #### ❌ Pitfall: Inconsistent Key Generation
227
+
228
+ ```tsx
229
+ // ❌ PROBLEMATIC - Keys can collide
230
+ {
231
+ items.map((item) => <ModusWcMenuItem key={item.value} {...item} />);
232
+ }
233
+ ```
234
+
235
+ #### ✅ Solution: Composite Keys
236
+
237
+ ```tsx
238
+ // ✅ CORRECT - Composite keys prevent collisions
239
+ {
240
+ items.map((item, index) => (
241
+ <ModusWcMenuItem key={`${item.value}-${index}`} {...item} />
242
+ ));
243
+ }
244
+ ```
245
+
246
+ ## 🔧 Debugging Steps
247
+
248
+ 1. **Check Console**: Look for React key warnings
249
+ 2. **Use Chrome DevTools**: Inspect component structure
250
+ 3. **Verify Keys**: Ensure each mapped item has a unique key
251
+ 4. **Test Props**: Use component props instead of slots when possible
252
+
253
+ ## 📚 Reference Components
254
+
255
+ **Working Examples:**
256
+
257
+ - `ModusDropdownMenu.tsx` - Uses `start-icon={item.startIcon}` prop
258
+ - `ThemeSwitcherDropdown.tsx` - Proper key handling
259
+ - `ModusTabs.tsx` - Correct slot usage for tab panels
260
+
261
+ **Problematic Patterns:**
262
+
263
+ - Slot-based icon rendering
264
+ - Missing or duplicate keys
265
+ - Wrapping web components unnecessarily
266
+
267
+ ## 🔗 Modus Web Components React Integration
268
+
269
+ ### Official Documentation Patterns
270
+
271
+ Based on the [Modus Web Components React Documentation](https://trimble-oss.github.io/modus-wc-2.0/main/?path=/docs/documentation-frameworks-react--docs), follow these patterns:
272
+
273
+ #### ✅ Proper List Rendering
274
+
275
+ ```tsx
276
+ // ✅ CORRECT - Use unique identifiers as keys
277
+ {
278
+ items.map((item) => (
279
+ <ModusWcMenuItem
280
+ key={item.id}
281
+ label={item.label}
282
+ value={item.value}
283
+ start-icon={item.startIcon}
284
+ />
285
+ ));
286
+ }
287
+ ```
288
+
289
+ #### ✅ Required Props Configuration
290
+
291
+ ```tsx
292
+ // ✅ CORRECT - Provide all required props
293
+ <ModusWcMenuItem
294
+ label="Menu Item"
295
+ value="menu-item"
296
+ start-icon="icon-name"
297
+ disabled={false}
298
+ selected={false}
299
+ />
300
+ ```
301
+
302
+ #### ❌ Avoid Index-Based Keys for Dynamic Lists
303
+
304
+ ```tsx
305
+ // ❌ WRONG - Index can cause issues with reordering
306
+ {
307
+ items.map((item, index) => <ModusWcMenuItem key={index} {...item} />);
308
+ }
309
+
310
+ // ✅ CORRECT - Use stable identifier
311
+ {
312
+ items.map((item) => <ModusWcMenuItem key={item.id} {...item} />);
313
+ }
314
+ ```
315
+
316
+ ### Key Integration Principles
317
+
318
+ 1. **Stable Keys**: Use data-based identifiers, not array indices
319
+ 2. **Complete Props**: Provide all required web component props
320
+ 3. **Event Handling**: Use proper React event handlers for web component events
321
+ 4. **Type Safety**: Leverage TypeScript interfaces for web component props
322
+ 5. **Performance**: Avoid unnecessary re-renders with proper key usage
323
+
324
+ ### TypeScript Integration Patterns
325
+
326
+ ```tsx
327
+ // ✅ CORRECT - Type-safe interface
328
+ interface MenuItem {
329
+ id: string;
330
+ label: string;
331
+ value: string;
332
+ startIcon?: string;
333
+ disabled?: boolean;
334
+ selected?: boolean;
335
+ }
336
+
337
+ // ✅ CORRECT - Proper event handling
338
+ const handleItemSelect = (event: CustomEvent<{ value: string }>) => {
339
+ const selectedValue = event.detail.value;
340
+ // Handle selection
341
+ };
342
+
343
+ // ✅ CORRECT - Type-safe component usage
344
+ {
345
+ menuItems.map((item: MenuItem) => (
346
+ <ModusWcMenuItem
347
+ key={item.id}
348
+ label={item.label}
349
+ value={item.value}
350
+ start-icon={item.startIcon}
351
+ disabled={item.disabled}
352
+ selected={item.selected}
353
+ onItemSelect={handleItemSelect}
354
+ />
355
+ ));
356
+ }
357
+ ```
358
+
359
+ ### Event Handling Best Practices
360
+
361
+ ```tsx
362
+ // ✅ CORRECT - Proper event listener setup
363
+ useEffect(() => {
364
+ const menuElement = menuRef.current;
365
+ if (!menuElement) return;
366
+
367
+ const handleItemSelect = (event: CustomEvent<{ value: string }>) => {
368
+ onItemSelect?.(event.detail);
369
+ };
370
+
371
+ menuElement.addEventListener("itemSelect", handleItemSelect);
372
+
373
+ return () => {
374
+ menuElement.removeEventListener("itemSelect", handleItemSelect);
375
+ };
376
+ }, [onItemSelect]);
377
+ ```
378
+
379
+ ## 🎯 Key Rules Summary
380
+
381
+ 1. **Always use composite keys**: `${value}-${index}`
382
+ 2. **Use props over slots**: `start-icon={icon}` not `<i slot="start-icon">`
383
+ 3. **Avoid div wrappers**: Let web components render directly
384
+ 4. **Test in Chrome DevTools**: Verify no React warnings
385
+ 5. **Follow Modus patterns**: Use established component patterns
386
+ 6. **Use unique identifiers**: Never use array index as key when items can reorder
387
+ 7. **Provide all required props**: Ensure web components have proper configuration
388
+ 8. **Handle dynamic content safely**: Use stable identifiers for keys
389
+
390
+ ## 🚀 Performance Benefits
391
+
392
+ - **Faster re-renders**: React can efficiently track component changes
393
+ - **No console warnings**: Clean development experience
394
+ - **Better debugging**: Clear component hierarchy
395
+ - **Optimal performance**: Proper React reconciliation
396
+
397
+ ## 📝 Quick Checklist
398
+
399
+ - [ ] ✅ All mapped components have unique keys
400
+ - [ ] ✅ Using composite keys (`${value}-${index}`)
401
+ - [ ] ✅ Using props instead of slots for icons
402
+ - [ ] ✅ No unnecessary div wrappers
403
+ - [ ] ✅ No React warnings in console
404
+ - [ ] ✅ Components render correctly
405
+ - [ ] ✅ Following Modus Web Components patterns
406
+
407
+ # Modus React Key Warnings - Essential Rules
408
+
409
+ ## 🚨 CRITICAL: React Key Props with Modus Web Components
410
+
411
+ When using Modus Web Components in React, proper key handling is essential to prevent React warnings and ensure optimal performance.
412
+
413
+ ## ❌ NEVER Do These
414
+
415
+ ### 1. Missing Key Props on Mapped Components
416
+
417
+ ```tsx
418
+ // ❌ WRONG - No key prop
419
+ {
420
+ items.map((item) => (
421
+ <ModusWcMenuItem label={item.label} value={item.value} />
422
+ ));
423
+ }
424
+
425
+ // ❌ WRONG - Using index only as key
426
+ {
427
+ items.map((item, index) => (
428
+ <ModusWcMenuItem key={index} label={item.label} value={item.value} />
429
+ ));
430
+ }
431
+ ```
432
+
433
+ ### 2. Using Slots Instead of Props for Icons
434
+
435
+ ```tsx
436
+ // ❌ WRONG - Using slot content causes key issues
437
+ <ModusWcMenuItem label={item.label} value={item.value}>
438
+ {item.startIcon && (
439
+ <i className="modus-icons" slot="start-icon">
440
+ {item.startIcon}
441
+ </i>
442
+ )}
443
+ </ModusWcMenuItem>
444
+ ```
445
+
446
+ ### 3. Wrapping Web Components in Divs
447
+
448
+ ```tsx
449
+ // ❌ WRONG - Div wrapper interferes with web component
450
+ {
451
+ items.map((item) => (
452
+ <div key={item.value}>
453
+ <ModusWcMenuItem label={item.label} value={item.value} />
454
+ </div>
455
+ ));
456
+ }
457
+ ```
458
+
459
+ ## ✅ ALWAYS Do These
460
+
461
+ ### 1. Use Composite Keys for Web Components
462
+
463
+ ```tsx
464
+ // ✅ CORRECT - Composite key ensures uniqueness
465
+ {
466
+ items.map((item, index) => (
467
+ <ModusWcMenuItem
468
+ key={`${item.value}-${index}`}
469
+ label={item.label}
470
+ value={item.value}
471
+ start-icon={item.startIcon}
472
+ />
473
+ ));
474
+ }
475
+ ```
476
+
477
+ ### 2. Use Props Instead of Slots for Modus Components
478
+
479
+ ```tsx
480
+ // ✅ CORRECT - Use start-icon prop
481
+ <ModusWcMenuItem
482
+ key={`${item.value}-${index}`}
483
+ label={item.label}
484
+ value={item.value}
485
+ start-icon={item.startIcon}
486
+ sub-label={item.subLabel}
487
+ selected={item.selected}
488
+ disabled={item.disabled}
489
+ bordered={item.bordered}
490
+ />
491
+ ```
492
+
493
+ ### 3. Handle Dynamic Content Properly
494
+
495
+ ```tsx
496
+ // ✅ CORRECT - Safe key generation
497
+ const generateKey = (item: MenuItem, index: number) => {
498
+ return item.value ? `${item.value}-${index}` : `item-${index}`;
499
+ };
500
+
501
+ {
502
+ items.map((item, index) => (
503
+ <ModusWcMenuItem
504
+ key={generateKey(item, index)}
505
+ label={item.label}
506
+ value={item.value}
507
+ />
508
+ ));
509
+ }
510
+ ```
511
+
512
+ ## 🎯 Key Patterns for Different Modus Components
513
+
514
+ ### ModusWcMenuItem
515
+
516
+ ```tsx
517
+ // ✅ CORRECT
518
+ {
519
+ menuItems.map((item, index) => (
520
+ <ModusWcMenuItem
521
+ key={`${item.value}-${index}`}
522
+ label={item.label}
523
+ value={item.value}
524
+ start-icon={item.startIcon}
525
+ sub-label={item.subLabel}
526
+ />
527
+ ));
528
+ }
529
+ ```
530
+
531
+ ### ModusWcTabs
532
+
533
+ ```tsx
534
+ // ✅ CORRECT
535
+ {
536
+ panels.map((panel, index) => (
537
+ <div key={index} slot={`tab-${index}`}>
538
+ {panel}
539
+ </div>
540
+ ));
541
+ }
542
+ ```
543
+
544
+ ### ModusWcDropdownMenu
545
+
546
+ ```tsx
547
+ // ✅ CORRECT
548
+ {
549
+ menuItems.map((item, index) => (
550
+ <ModusWcMenuItem
551
+ key={`${item.value}-${index}`}
552
+ label={item.label}
553
+ value={item.value}
554
+ start-icon={item.startIcon}
555
+ />
556
+ ));
557
+ }
558
+ ```
559
+
560
+ ## 🚨 Common Warning Messages
561
+
562
+ ### React Key Warning
563
+
564
+ ```text
565
+ Each child in a list should have a unique "key" prop.
566
+ Check the render method of `ModusWcMenu2`. It was passed a child from ModusMenu.
567
+ ```
568
+
569
+ **Solution**: Use composite keys and props instead of slots.
570
+
571
+ ### Web Component Slot Issues
572
+
573
+ ```text
574
+ Warning: React does not recognize the `slot` prop on a DOM element.
575
+ ```
576
+
577
+ **Solution**: Use component props instead of slot attributes.
578
+
579
+ ### Common Pitfalls and Solutions
580
+
581
+ #### ❌ Pitfall: Using Array Index as Key
582
+
583
+ ```tsx
584
+ // ❌ PROBLEMATIC - Can cause issues with reordering
585
+ {
586
+ items.map((item, index) => <ModusWcMenuItem key={index} {...item} />);
587
+ }
588
+ ```
589
+
590
+ #### ✅ Solution: Use Stable Identifiers
591
+
592
+ ```tsx
593
+ // ✅ CORRECT - Use unique, stable identifier
594
+ {
595
+ items.map((item) => <ModusWcMenuItem key={item.id} {...item} />);
596
+ }
597
+ ```
598
+
599
+ #### ❌ Pitfall: Missing Event Cleanup
600
+
601
+ ```tsx
602
+ // ❌ PROBLEMATIC - Memory leaks
603
+ useEffect(() => {
604
+ const element = ref.current;
605
+ element?.addEventListener("itemSelect", handler);
606
+ // Missing cleanup!
607
+ }, []);
608
+ ```
609
+
610
+ #### ✅ Solution: Proper Cleanup
611
+
612
+ ```tsx
613
+ // ✅ CORRECT - Clean up event listeners
614
+ useEffect(() => {
615
+ const element = ref.current;
616
+ if (!element) return;
617
+
618
+ element.addEventListener("itemSelect", handler);
619
+
620
+ return () => {
621
+ element.removeEventListener("itemSelect", handler);
622
+ };
623
+ }, [handler]);
624
+ ```
625
+
626
+ #### ❌ Pitfall: Inconsistent Key Generation
627
+
628
+ ```tsx
629
+ // ❌ PROBLEMATIC - Keys can collide
630
+ {
631
+ items.map((item) => <ModusWcMenuItem key={item.value} {...item} />);
632
+ }
633
+ ```
634
+
635
+ #### ✅ Solution: Composite Keys
636
+
637
+ ```tsx
638
+ // ✅ CORRECT - Composite keys prevent collisions
639
+ {
640
+ items.map((item, index) => (
641
+ <ModusWcMenuItem key={`${item.value}-${index}`} {...item} />
642
+ ));
643
+ }
644
+ ```
645
+
646
+ ## 🔧 Debugging Steps
647
+
648
+ 1. **Check Console**: Look for React key warnings
649
+ 2. **Use Chrome DevTools**: Inspect component structure
650
+ 3. **Verify Keys**: Ensure each mapped item has a unique key
651
+ 4. **Test Props**: Use component props instead of slots when possible
652
+
653
+ ## 📚 Reference Components
654
+
655
+ **Working Examples:**
656
+
657
+ - `ModusDropdownMenu.tsx` - Uses `start-icon={item.startIcon}` prop
658
+ - `ThemeSwitcherDropdown.tsx` - Proper key handling
659
+ - `ModusTabs.tsx` - Correct slot usage for tab panels
660
+
661
+ **Problematic Patterns:**
662
+
663
+ - Slot-based icon rendering
664
+ - Missing or duplicate keys
665
+ - Wrapping web components unnecessarily
666
+
667
+ ## 🔗 Modus Web Components React Integration
668
+
669
+ ### Official Documentation Patterns
670
+
671
+ Based on the [Modus Web Components React Documentation](https://trimble-oss.github.io/modus-wc-2.0/main/?path=/docs/documentation-frameworks-react--docs), follow these patterns:
672
+
673
+ #### ✅ Proper List Rendering
674
+
675
+ ```tsx
676
+ // ✅ CORRECT - Use unique identifiers as keys
677
+ {
678
+ items.map((item) => (
679
+ <ModusWcMenuItem
680
+ key={item.id}
681
+ label={item.label}
682
+ value={item.value}
683
+ start-icon={item.startIcon}
684
+ />
685
+ ));
686
+ }
687
+ ```
688
+
689
+ #### ✅ Required Props Configuration
690
+
691
+ ```tsx
692
+ // ✅ CORRECT - Provide all required props
693
+ <ModusWcMenuItem
694
+ label="Menu Item"
695
+ value="menu-item"
696
+ start-icon="icon-name"
697
+ disabled={false}
698
+ selected={false}
699
+ />
700
+ ```
701
+
702
+ #### ❌ Avoid Index-Based Keys for Dynamic Lists
703
+
704
+ ```tsx
705
+ // ❌ WRONG - Index can cause issues with reordering
706
+ {
707
+ items.map((item, index) => <ModusWcMenuItem key={index} {...item} />);
708
+ }
709
+
710
+ // ✅ CORRECT - Use stable identifier
711
+ {
712
+ items.map((item) => <ModusWcMenuItem key={item.id} {...item} />);
713
+ }
714
+ ```
715
+
716
+ ### Key Integration Principles
717
+
718
+ 1. **Stable Keys**: Use data-based identifiers, not array indices
719
+ 2. **Complete Props**: Provide all required web component props
720
+ 3. **Event Handling**: Use proper React event handlers for web component events
721
+ 4. **Type Safety**: Leverage TypeScript interfaces for web component props
722
+ 5. **Performance**: Avoid unnecessary re-renders with proper key usage
723
+
724
+ ### TypeScript Integration Patterns
725
+
726
+ ```tsx
727
+ // ✅ CORRECT - Type-safe interface
728
+ interface MenuItem {
729
+ id: string;
730
+ label: string;
731
+ value: string;
732
+ startIcon?: string;
733
+ disabled?: boolean;
734
+ selected?: boolean;
735
+ }
736
+
737
+ // ✅ CORRECT - Proper event handling
738
+ const handleItemSelect = (event: CustomEvent<{ value: string }>) => {
739
+ const selectedValue = event.detail.value;
740
+ // Handle selection
741
+ };
742
+
743
+ // ✅ CORRECT - Type-safe component usage
744
+ {
745
+ menuItems.map((item: MenuItem) => (
746
+ <ModusWcMenuItem
747
+ key={item.id}
748
+ label={item.label}
749
+ value={item.value}
750
+ start-icon={item.startIcon}
751
+ disabled={item.disabled}
752
+ selected={item.selected}
753
+ onItemSelect={handleItemSelect}
754
+ />
755
+ ));
756
+ }
757
+ ```
758
+
759
+ ### Event Handling Best Practices
760
+
761
+ ```tsx
762
+ // ✅ CORRECT - Proper event listener setup
763
+ useEffect(() => {
764
+ const menuElement = menuRef.current;
765
+ if (!menuElement) return;
766
+
767
+ const handleItemSelect = (event: CustomEvent<{ value: string }>) => {
768
+ onItemSelect?.(event.detail);
769
+ };
770
+
771
+ menuElement.addEventListener("itemSelect", handleItemSelect);
772
+
773
+ return () => {
774
+ menuElement.removeEventListener("itemSelect", handleItemSelect);
775
+ };
776
+ }, [onItemSelect]);
777
+ ```
778
+
779
+ ## 🎯 Key Rules Summary
780
+
781
+ 1. **Always use composite keys**: `${value}-${index}`
782
+ 2. **Use props over slots**: `start-icon={icon}` not `<i slot="start-icon">`
783
+ 3. **Avoid div wrappers**: Let web components render directly
784
+ 4. **Test in Chrome DevTools**: Verify no React warnings
785
+ 5. **Follow Modus patterns**: Use established component patterns
786
+ 6. **Use unique identifiers**: Never use array index as key when items can reorder
787
+ 7. **Provide all required props**: Ensure web components have proper configuration
788
+ 8. **Handle dynamic content safely**: Use stable identifiers for keys
789
+
790
+ ## 🚀 Performance Benefits
791
+
792
+ - **Faster re-renders**: React can efficiently track component changes
793
+ - **No console warnings**: Clean development experience
794
+ - **Better debugging**: Clear component hierarchy
795
+ - **Optimal performance**: Proper React reconciliation
796
+
797
+ ## 📝 Quick Checklist
798
+
799
+ - [ ] ✅ All mapped components have unique keys
800
+ - [ ] ✅ Using composite keys (`${value}-${index}`)
801
+ - [ ] ✅ Using props instead of slots for icons
802
+ - [ ] ✅ No unnecessary div wrappers
803
+ - [ ] ✅ No React warnings in console
804
+ - [ ] ✅ Components render correctly
805
+ - [ ] ✅ Following Modus Web Components patterns