@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,402 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Modus Icon Names Validation Script for Angular + Tailwind v4
5
+ *
6
+ * This script validates that all Modus icon names used in the codebase
7
+ * are correct and exist in the official Modus Icons list.
8
+ *
9
+ * It checks for typos, invalid names, and suggests corrections.
10
+ */
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { createRequire } from 'module';
15
+ const require = createRequire(import.meta.url);
16
+ const { glob } = require('glob');
17
+
18
+ // Read and parse the Modus icons data from TypeScript file
19
+ const iconsContent = fs.readFileSync(path.join(process.cwd(), 'data/modusIcons.ts'), 'utf8');
20
+
21
+ // Extract the modusIcons object using regex
22
+ const modusIconsMatch = iconsContent.match(/export const modusIcons = ({[\s\S]*?});/);
23
+ if (!modusIconsMatch) {
24
+ console.error('Could not extract modusIcons object from TypeScript file');
25
+ process.exit(1);
26
+ }
27
+
28
+ // Evaluate the modusIcons object (safe since we control the content)
29
+ const modusIcons = eval(`(${modusIconsMatch[1]})`);
30
+
31
+ // Flatten all icons for easy access
32
+ const allModusIcons = Object.values(modusIcons).flat();
33
+
34
+ // File patterns to check
35
+ const FILE_PATTERNS = ['src/**/*.{ts,html}', 'src/**/*.css', 'src/**/*.scss'];
36
+
37
+ // Colors for console output
38
+ const colors = {
39
+ red: '\x1b[31m',
40
+ green: '\x1b[32m',
41
+ yellow: '\x1b[33m',
42
+ blue: '\x1b[34m',
43
+ magenta: '\x1b[35m',
44
+ cyan: '\x1b[36m',
45
+ white: '\x1b[37m',
46
+ reset: '\x1b[0m',
47
+ bold: '\x1b[1m',
48
+ dim: '\x1b[2m',
49
+ };
50
+
51
+ // Icon usage patterns to detect (Angular template syntax)
52
+ const ICON_USAGE_PATTERNS = [
53
+ // Angular modus-icon component usage
54
+ /<modus-icon[^>]*name=["']([^"']+)["'][^>]*>/g,
55
+
56
+ // Direct icon class usage - match content between <i> tags with modus-icons class
57
+ /<i[^>]*class=["'][^"']*modus-icons[^"']*["'][^>]*>([^<]+)<\/i>/g,
58
+
59
+ // Icon in string literals - only for specific icon-related attributes
60
+ /icon=["']([a-zA-Z0-9_-]+)["']/g,
61
+ /iconName=["']([a-zA-Z0-9_-]+)["']/g,
62
+ /startIcon=["']([a-zA-Z0-9_-]+)["']/g,
63
+ /endIcon=["']([a-zA-Z0-9_-]+)["']/g,
64
+
65
+ // Angular component icon attributes
66
+ /<modus-button[^>]*icon=["']([^"']+)["'][^>]*>/g,
67
+ /<modus-card[^>]*icon=["']([^"']+)["'][^>]*>/g,
68
+ /<modus-chip[^>]*icon=["']([^"']+)["'][^>]*>/g,
69
+ /<modus-alert[^>]*icon=["']([^"']+)["'][^>]*>/g,
70
+ /<modus-tooltip[^>]*icon=["']([^"']+)["'][^>]*>/g,
71
+
72
+ // Icon in template literals - only if they're likely icon names
73
+ /`([a-zA-Z0-9_-]+)`(?=.*modus-icons)/g,
74
+ ];
75
+
76
+ /**
77
+ * Find similar icon names using Levenshtein distance
78
+ */
79
+ function findSimilarIcons(iconName, maxDistance = 2) {
80
+ const similar = [];
81
+
82
+ for (const validIcon of allModusIcons) {
83
+ const distance = levenshteinDistance(iconName.toLowerCase(), validIcon.toLowerCase());
84
+
85
+ // Only include if distance is reasonable and the icon name is meaningful
86
+ if (distance <= maxDistance && distance > 0) {
87
+ // Filter out very short matches that are likely meaningless
88
+ if (validIcon.length >= 3 && iconName.length >= 3) {
89
+ similar.push({
90
+ name: validIcon,
91
+ distance: distance,
92
+ });
93
+ }
94
+ }
95
+ }
96
+
97
+ return similar.sort((a, b) => a.distance - b.distance).slice(0, 5);
98
+ }
99
+
100
+ /**
101
+ * Calculate Levenshtein distance between two strings
102
+ */
103
+ function levenshteinDistance(str1, str2) {
104
+ const matrix = [];
105
+
106
+ for (let i = 0; i <= str2.length; i++) {
107
+ matrix[i] = [i];
108
+ }
109
+
110
+ for (let j = 0; j <= str1.length; j++) {
111
+ matrix[0][j] = j;
112
+ }
113
+
114
+ for (let i = 1; i <= str2.length; i++) {
115
+ for (let j = 1; j <= str1.length; j++) {
116
+ if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
117
+ matrix[i][j] = matrix[i - 1][j - 1];
118
+ } else {
119
+ matrix[i][j] = Math.min(
120
+ matrix[i - 1][j - 1] + 1,
121
+ matrix[i][j - 1] + 1,
122
+ matrix[i - 1][j] + 1
123
+ );
124
+ }
125
+ }
126
+ }
127
+
128
+ return matrix[str2.length][str1.length];
129
+ }
130
+
131
+ /**
132
+ * Find icon by partial name match
133
+ */
134
+ function findIconByPartial(iconName) {
135
+ // Only search for partial matches if the input is meaningful
136
+ if (iconName.length < 3) {
137
+ return [];
138
+ }
139
+
140
+ const partialMatches = allModusIcons.filter((icon) => {
141
+ // Only include icons that are at least 3 characters long
142
+ if (icon.length < 3) return false;
143
+
144
+ // Check if the icon name contains the search term or vice versa
145
+ const iconLower = icon.toLowerCase();
146
+ const searchLower = iconName.toLowerCase();
147
+
148
+ return iconLower.includes(searchLower) || searchLower.includes(iconLower);
149
+ });
150
+
151
+ // Sort by relevance (exact substring matches first, then by length)
152
+ return partialMatches
153
+ .sort((a, b) => {
154
+ const aExact = a.toLowerCase().includes(iconName.toLowerCase());
155
+ const bExact = b.toLowerCase().includes(iconName.toLowerCase());
156
+
157
+ if (aExact && !bExact) return -1;
158
+ if (!aExact && bExact) return 1;
159
+
160
+ return a.length - b.length;
161
+ })
162
+ .slice(0, 5);
163
+ }
164
+
165
+ /**
166
+ * Get icon category
167
+ */
168
+ function getIconCategory(iconName) {
169
+ for (const [category, icons] of Object.entries(modusIcons)) {
170
+ if (icons.includes(iconName)) {
171
+ return category;
172
+ }
173
+ }
174
+ return null;
175
+ }
176
+
177
+ /**
178
+ * Check a single file for icon name violations
179
+ */
180
+ function checkFile(filePath) {
181
+ const content = fs.readFileSync(filePath, 'utf8');
182
+ const violations = [];
183
+
184
+ for (const pattern of ICON_USAGE_PATTERNS) {
185
+ let match;
186
+ while ((match = pattern.exec(content)) !== null) {
187
+ const iconName = match[1];
188
+
189
+ // Skip if it's not a potential icon name (too short, contains spaces, etc.)
190
+ if (
191
+ iconName.length < 2 ||
192
+ iconName.includes(' ') ||
193
+ iconName.includes('\n') ||
194
+ iconName.includes('\t')
195
+ ) {
196
+ continue;
197
+ }
198
+
199
+ // Skip common non-icon words that might be caught by the regex
200
+ const commonWords = [
201
+ 'description',
202
+ 'title',
203
+ 'content',
204
+ 'text',
205
+ 'label',
206
+ 'value',
207
+ 'name',
208
+ 'id',
209
+ 'class',
210
+ 'type',
211
+ 'src',
212
+ 'alt',
213
+ 'href',
214
+ 'target',
215
+ 'rel',
216
+ 'style',
217
+ 'width',
218
+ 'height',
219
+ 'size',
220
+ 'onClick',
221
+ 'onChange',
222
+ 'onSubmit',
223
+ 'onFocus',
224
+ 'onBlur',
225
+ 'onMouseOver',
226
+ 'onMouseOut',
227
+ 'className',
228
+ 'htmlFor',
229
+ 'ariaLabel',
230
+ 'ariaDescribedBy',
231
+ 'role',
232
+ 'tabIndex',
233
+ 'true',
234
+ 'false',
235
+ 'null',
236
+ 'undefined',
237
+ 'this',
238
+ 'that',
239
+ 'here',
240
+ 'there',
241
+ 'where',
242
+ ];
243
+
244
+ if (commonWords.includes(iconName.toLowerCase())) {
245
+ continue;
246
+ }
247
+
248
+ // Check if the icon name exists in the official list
249
+ if (!allModusIcons.includes(iconName)) {
250
+ const lines = content.substring(0, match.index).split('\n');
251
+ const lineNumber = lines.length;
252
+ const columnNumber = lines[lines.length - 1].length + 1;
253
+
254
+ // Find similar icons
255
+ const similarIcons = findSimilarIcons(iconName);
256
+ const partialMatches = findIconByPartial(iconName);
257
+
258
+ violations.push({
259
+ file: filePath,
260
+ line: lineNumber,
261
+ column: columnNumber,
262
+ iconName: iconName,
263
+ match: match[0],
264
+ similarIcons: similarIcons,
265
+ partialMatches: partialMatches,
266
+ });
267
+ }
268
+ }
269
+ pattern.lastIndex = 0;
270
+ }
271
+
272
+ return violations;
273
+ }
274
+
275
+ /**
276
+ * Format violation for display
277
+ */
278
+ function formatViolation(violation) {
279
+ const { file, line, column, iconName, similarIcons, partialMatches } = violation;
280
+ const relativePath = path.relative(process.cwd(), file);
281
+
282
+ let suggestions = [];
283
+
284
+ if (similarIcons.length > 0) {
285
+ suggestions.push(
286
+ `Did you mean: ${colors.green}${similarIcons.map((s) => s.name).join(', ')}${colors.reset}`
287
+ );
288
+ }
289
+
290
+ if (partialMatches.length > 0) {
291
+ suggestions.push(`Similar icons: ${colors.cyan}${partialMatches.join(', ')}${colors.reset}`);
292
+ }
293
+
294
+ return {
295
+ location: `${relativePath}:${line}:${column}`,
296
+ message: `Invalid Modus icon name: ${colors.red}${iconName}${colors.reset}`,
297
+ suggestions: suggestions,
298
+ explanation: `The icon "${iconName}" is not found in the official Modus Icons list.`,
299
+ };
300
+ }
301
+
302
+ /**
303
+ * Main function
304
+ */
305
+ async function main() {
306
+ console.log(`${colors.bold}${colors.blue}🔍 Validating Modus icon names...${colors.reset}\n`);
307
+
308
+ const allFiles = [];
309
+ for (const pattern of FILE_PATTERNS) {
310
+ const files = glob.sync(pattern, { cwd: process.cwd() });
311
+ allFiles.push(...files);
312
+ }
313
+ const uniqueFiles = [...new Set(allFiles)];
314
+ let totalViolations = 0;
315
+ const violationsByFile = {};
316
+
317
+ // Check each file
318
+ for (const file of uniqueFiles) {
319
+ const violations = checkFile(file);
320
+ if (violations.length > 0) {
321
+ violationsByFile[file] = violations;
322
+ totalViolations += violations.length;
323
+ }
324
+ }
325
+
326
+ // Display results
327
+ if (totalViolations === 0) {
328
+ console.log(`${colors.green}✅ All Modus icon names are valid!${colors.reset}`);
329
+ console.log(
330
+ `${colors.dim}Found ${allModusIcons.length} valid Modus icons across ${
331
+ Object.keys(modusIcons).length
332
+ } categories.${colors.reset}\n`
333
+ );
334
+ process.exit(0);
335
+ }
336
+
337
+ console.log(
338
+ `${colors.red}❌ Found ${totalViolations} invalid Modus icon name${
339
+ totalViolations === 1 ? '' : 's'
340
+ }:${colors.reset}\n`
341
+ );
342
+
343
+ // Group violations by file
344
+ for (const [file, violations] of Object.entries(violationsByFile)) {
345
+ const relativePath = path.relative(process.cwd(), file);
346
+ console.log(`${colors.bold}${colors.cyan}📁 ${relativePath}${colors.reset}`);
347
+
348
+ for (const violation of violations) {
349
+ const formatted = formatViolation(violation);
350
+ console.log(` ${colors.dim}${formatted.location}${colors.reset}`);
351
+ console.log(` ${formatted.message}`);
352
+ if (formatted.suggestions.length > 0) {
353
+ formatted.suggestions.forEach((suggestion) => {
354
+ console.log(` ${suggestion}`);
355
+ });
356
+ }
357
+ console.log(` ${colors.dim}${formatted.explanation}${colors.reset}\n`);
358
+ }
359
+ }
360
+
361
+ // Summary and help
362
+ console.log(`${colors.bold}${colors.yellow}📋 Summary:${colors.reset}`);
363
+ console.log(`• Total violations: ${colors.red}${totalViolations}${colors.reset}`);
364
+ console.log(
365
+ `• Files affected: ${colors.red}${Object.keys(violationsByFile).length}${colors.reset}`
366
+ );
367
+ console.log(`• Valid icons available: ${colors.green}${allModusIcons.length}${colors.reset}\n`);
368
+
369
+ console.log(`${colors.bold}${colors.blue}💡 How to fix:${colors.reset}`);
370
+ console.log(`• Check the icon name spelling and case`);
371
+ console.log(`• Use the suggestions provided above`);
372
+ console.log(`• Browse available icons at: ${colors.cyan}data/modusIcons.ts${colors.reset}`);
373
+ console.log(`• See docs/angular-design-system.mdc for usage patterns\n`);
374
+
375
+ console.log(`${colors.bold}${colors.magenta}🔧 Available commands:${colors.reset}`);
376
+ console.log(`• ${colors.cyan}npm run lint:icon-names${colors.reset} - Run this check`);
377
+ console.log(`• ${colors.cyan}npm run lint:all${colors.reset} - Run all linting checks\n`);
378
+
379
+ // Show some popular icon categories
380
+ console.log(`${colors.bold}${colors.blue}📚 Popular Icon Categories:${colors.reset}`);
381
+ const popularCategories = [
382
+ 'Navigation & UI',
383
+ 'Actions & Operations',
384
+ 'Status & Feedback',
385
+ 'Files & Documents',
386
+ ];
387
+
388
+ popularCategories.forEach((category) => {
389
+ const count = modusIcons[category]?.length || 0;
390
+ console.log(`• ${colors.cyan}${category}${colors.reset}: ${count} icons`);
391
+ });
392
+ console.log();
393
+
394
+ process.exit(1);
395
+ }
396
+
397
+ // Run the script
398
+ main().catch((error) => {
399
+ console.error(`${colors.red}❌ Error running icon names validation:${colors.reset}`);
400
+ console.error(error);
401
+ process.exit(1);
402
+ });
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Inline Styles Linting Script for Angular + Tailwind v4
5
+ *
6
+ * This script checks for usage of inline styles that should be replaced with Tailwind classes
7
+ * to ensure design system consistency and proper styling patterns.
8
+ *
9
+ * It flags common inline style patterns and suggests Tailwind alternatives.
10
+ *
11
+ * EXCEPTIONS: Border-related styles are allowed due to Tailwind v4 + Modus conflicts.
12
+ * However, inline border styles should be replaced with our border utility classes.
13
+ */
14
+
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+ import { createRequire } from 'module';
18
+ const require = createRequire(import.meta.url);
19
+ const { glob } = require('glob');
20
+
21
+ // Inline style patterns to detect (Angular template syntax: [style.*] and style="")
22
+ const INLINE_STYLE_PATTERNS = [
23
+ // Angular style attribute binding
24
+ /\[style\.[^\]]+=\s*["'][^"']+["']\]/g,
25
+ /\[style\.[^\]]+\.px\]/g,
26
+ /\[style\.[^\]]+\.rem\]/g,
27
+ /\[style\.[^\]]+\.em\]/g,
28
+ /\[style\.[^\]]+\.%\]/g,
29
+
30
+ // Regular style attribute
31
+ /style\s*=\s*["'][^"']*background[^"']*["']/gi,
32
+ /style\s*=\s*["'][^"']*color[^"']*["']/gi,
33
+ /style\s*=\s*["'][^"']*margin[^"']*["']/gi,
34
+ /style\s*=\s*["'][^"']*padding[^"']*["']/gi,
35
+ /style\s*=\s*["'][^"']*font-size[^"']*["']/gi,
36
+ /style\s*=\s*["'][^"']*font-weight[^"']*["']/gi,
37
+ /style\s*=\s*["'][^"']*width[^"']*["']/gi,
38
+ /style\s*=\s*["'][^"']*height[^"']*["']/gi,
39
+ /style\s*=\s*["'][^"']*display[^"']*["']/gi,
40
+ /style\s*=\s*["'][^"']*var\(--[^"']*["']/gi,
41
+ ];
42
+
43
+ // Tailwind alternatives for common inline styles
44
+ const TAILWIND_ALTERNATIVES = {
45
+ // Spacing (most common in Angular templates)
46
+ '[style.margin-right.px]="8"': 'mr-2',
47
+ '[style.margin-left.px]="8"': 'ml-2',
48
+ '[style.margin-top.px]="8"': 'mt-2',
49
+ '[style.margin-bottom.px]="8"': 'mb-2',
50
+ '[style.padding.px]="16"': 'p-4',
51
+ '[style.padding.px]="8"': 'p-2',
52
+ '[style.padding.px]="32"': 'p-8',
53
+
54
+ // Background colors - Design System Colors
55
+ 'style="background: var(--background)"': 'bg-background',
56
+ 'style="background: var(--card)"': 'bg-card',
57
+ 'style="background: var(--muted)"': 'bg-muted',
58
+ 'style="background: var(--secondary)"': 'bg-secondary',
59
+ 'style="background: var(--primary)"': 'bg-primary',
60
+ 'style="background: var(--success)"': 'bg-success',
61
+ 'style="background: var(--error)"': 'bg-error',
62
+ 'style="background: var(--warning)"': 'bg-warning',
63
+
64
+ // Text colors - Design System Colors
65
+ 'style="color: var(--foreground)"': 'text-foreground',
66
+ 'style="color: var(--primary)"': 'text-primary',
67
+ 'style="color: var(--success)"': 'text-success',
68
+ 'style="color: var(--error)"': 'text-error',
69
+ 'style="color: var(--warning)"': 'text-warning',
70
+ 'style="color: var(--muted-foreground)"': 'text-muted-foreground',
71
+
72
+ // Typography
73
+ 'style="font-size: 1.5rem"': 'text-xl',
74
+ 'style="font-size: 1.25rem"': 'text-lg',
75
+ 'style="font-size: 1rem"': 'text-base',
76
+ 'style="font-size: 0.875rem"': 'text-sm',
77
+ 'style="font-size: 0.75rem"': 'text-xs',
78
+ 'style="font-weight: 600"': 'font-semibold',
79
+ 'style="font-weight: 700"': 'font-bold',
80
+ 'style="text-align: center"': 'text-center',
81
+ 'style="text-align: left"': 'text-left',
82
+ 'style="text-align: right"': 'text-right',
83
+
84
+ // Layout
85
+ 'style="display: flex"': 'flex',
86
+ 'style="display: grid"': 'grid',
87
+ 'style="display: block"': 'block',
88
+ 'style="display: inline-block"': 'inline-block',
89
+
90
+ // Sizing
91
+ 'style="width: 100%"': 'w-full',
92
+ 'style="height: 100%"': 'h-full',
93
+ };
94
+
95
+ // Files to check
96
+ const FILE_PATTERNS = ['src/**/*.ts', 'src/**/*.html', 'src/**/*.css', 'src/**/*.scss'];
97
+
98
+ // Files to exclude
99
+ const EXCLUDE_PATTERNS = [
100
+ 'node_modules/**',
101
+ 'dist/**',
102
+ 'build/**',
103
+ '**/*.d.ts',
104
+ 'scripts/**',
105
+ 'src/styles.css', // Exclude styles.css as it contains the design system definitions
106
+ ];
107
+
108
+ function isBorderRelatedStyle(styleContent) {
109
+ // Check for border-related patterns
110
+ const borderPatterns = [
111
+ /border-width/gi,
112
+ /border-top/gi,
113
+ /border-right/gi,
114
+ /border-bottom/gi,
115
+ /border-left/gi,
116
+ /border:\s*["']?\d+px/gi,
117
+ /border:\s*["']?\d+px\s+solid/gi,
118
+ /border:\s*["']?\d+px\s+solid\s+var\(--border\)/gi,
119
+ /border:\s*["']?\d+px\s+solid\s+var\(--modus-wc-color/gi,
120
+ ];
121
+
122
+ return borderPatterns.some((pattern) => pattern.test(styleContent));
123
+ }
124
+
125
+ function isDynamicValue(styleContent) {
126
+ // Check for Angular template expressions
127
+ return (
128
+ styleContent.includes('{{') ||
129
+ styleContent.includes('}}') ||
130
+ (styleContent.includes('[') && styleContent.includes(']') && styleContent.includes('=')) ||
131
+ styleContent.includes('*ngIf') ||
132
+ styleContent.includes('*ngFor') ||
133
+ styleContent.includes('@') ||
134
+ styleContent.includes('?') || // Ternary operators
135
+ styleContent.includes('&&') || // Logical operators
136
+ styleContent.includes('||')
137
+ ); // Logical operators
138
+ }
139
+
140
+ function getTailwindSuggestion(styleContent) {
141
+ // Try to find exact matches first
142
+ for (const [inlineStyle, tailwindClass] of Object.entries(TAILWIND_ALTERNATIVES)) {
143
+ if (styleContent.includes(inlineStyle)) {
144
+ return tailwindClass;
145
+ }
146
+ }
147
+
148
+ // Generic suggestions based on common patterns
149
+ if (styleContent.includes('background') || styleContent.includes('background-color')) {
150
+ return 'Use bg-* classes (bg-background, bg-card, bg-primary, etc.)';
151
+ }
152
+ if (styleContent.includes('color')) {
153
+ return 'Use text-* classes (text-foreground, text-primary, etc.)';
154
+ }
155
+ if (styleContent.includes('margin')) {
156
+ return 'Use m-* classes (m-2, mr-4, mt-8, etc.)';
157
+ }
158
+ if (styleContent.includes('padding')) {
159
+ return 'Use p-* classes (p-2, px-4, py-8, etc.)';
160
+ }
161
+ if (styleContent.includes('font-size')) {
162
+ return 'Use text-* classes (text-sm, text-lg, text-xl, etc.)';
163
+ }
164
+ if (styleContent.includes('display')) {
165
+ return 'Use display classes (flex, grid, block, etc.)';
166
+ }
167
+
168
+ return 'Use appropriate Tailwind utility classes';
169
+ }
170
+
171
+ async function checkFile(filePath) {
172
+ const content = fs.readFileSync(filePath, 'utf8');
173
+ const violations = [];
174
+
175
+ for (const pattern of INLINE_STYLE_PATTERNS) {
176
+ let match;
177
+ while ((match = pattern.exec(content)) !== null) {
178
+ const line = content.substring(0, match.index).split('\n').length;
179
+ const column = match.index - content.lastIndexOf('\n', match.index - 1);
180
+
181
+ const styleContent = match[0];
182
+
183
+ // Skip if it's a border-related style (allowed, but should use utilities)
184
+ if (isBorderRelatedStyle(styleContent)) {
185
+ continue;
186
+ }
187
+
188
+ // Skip if it's a dynamic value (contains template expressions)
189
+ if (isDynamicValue(styleContent)) {
190
+ continue;
191
+ }
192
+
193
+ const suggestion = getTailwindSuggestion(styleContent);
194
+
195
+ violations.push({
196
+ file: filePath,
197
+ line,
198
+ column,
199
+ match: match[0],
200
+ message: `Inline style detected: "${match[0]}". Use Tailwind classes instead.`,
201
+ suggestion: suggestion,
202
+ });
203
+ }
204
+ pattern.lastIndex = 0;
205
+ }
206
+
207
+ return violations;
208
+ }
209
+
210
+ async function main() {
211
+ console.log('🎨 Checking for inline styles that should use Tailwind classes in Angular app...\n');
212
+
213
+ let allViolations = [];
214
+
215
+ try {
216
+ // Get all files to check
217
+ const allFiles = [];
218
+ for (const pattern of FILE_PATTERNS) {
219
+ const files = glob.sync(pattern, {
220
+ ignore: EXCLUDE_PATTERNS,
221
+ });
222
+ allFiles.push(...files.map(f => path.resolve(f)));
223
+ }
224
+ const files = [...new Set(allFiles)];
225
+
226
+ // Check each file
227
+ for (const file of files) {
228
+ try {
229
+ const violations = await checkFile(file);
230
+ allViolations = allViolations.concat(violations);
231
+ } catch (error) {
232
+ console.warn(`⚠️ Warning: Could not check file ${file}: ${error.message}`);
233
+ }
234
+ }
235
+
236
+ // Report results
237
+ if (allViolations.length === 0) {
238
+ console.log('✅ All files are using Tailwind classes correctly!');
239
+ console.log(
240
+ '📝 Note: Border-related styles are allowed due to Tailwind v4 + Modus conflicts'
241
+ );
242
+ process.exit(0);
243
+ } else {
244
+ console.log(`❌ Found ${allViolations.length} inline style violations:\n`);
245
+
246
+ // Group violations by file
247
+ const violationsByFile = allViolations.reduce((acc, violation) => {
248
+ if (!acc[violation.file]) {
249
+ acc[violation.file] = [];
250
+ }
251
+ acc[violation.file].push(violation);
252
+ return acc;
253
+ }, {});
254
+
255
+ // Print violations
256
+ for (const [file, violations] of Object.entries(violationsByFile)) {
257
+ const relativePath = path.relative(process.cwd(), file);
258
+ console.log(`📄 ${relativePath}:`);
259
+
260
+ for (const violation of violations) {
261
+ console.log(` ${violation.line}:${violation.column} - ${violation.message}`);
262
+ console.log(` 💡 Suggestion: ${violation.suggestion}`);
263
+ }
264
+ console.log();
265
+ }
266
+
267
+ console.log('💡 Tailwind Classes Reference:');
268
+ console.log(' ✅ Background: bg-background, bg-card, bg-primary, bg-muted');
269
+ console.log(' ✅ Text: text-foreground, text-primary, text-error');
270
+ console.log(' ✅ Spacing: p-4, m-2, px-4, py-2, gap-4, mr-2, ml-2');
271
+ console.log(' ✅ Typography: text-lg, font-semibold, text-center');
272
+ console.log(' ✅ Layout: flex, grid, items-center, justify-between');
273
+ console.log(' ✅ Sizing: w-full, h-full, max-w-5xl, min-h-screen');
274
+ console.log(' ✅ Effects: opacity-50, rounded-lg, shadow-lg');
275
+ console.log(
276
+ ' 📝 Note: Border styles (borderWidth, border) are allowed due to Tailwind v4 conflicts'
277
+ );
278
+ console.log(
279
+ ' 🎯 Use border utility classes: border-default, border-thick, border-dashed, etc.'
280
+ );
281
+ console.log(' 📖 Documentation: https://tailwindcss.com/docs');
282
+
283
+ process.exit(1);
284
+ }
285
+ } catch (error) {
286
+ console.error('💥 Error running inline styles check:', error.message);
287
+ process.exit(1);
288
+ }
289
+ }
290
+
291
+ // Run the script
292
+ main();