@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
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # Create Modus App
2
+
3
+ Interactive CLI to scaffold Modus 2.0 web component applications for React and Angular.
4
+
5
+ **Templates are bundled directly** - no external downloads, works fully offline.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ npx @julianoczkowski/create-trimble-app
11
+ ```
12
+
13
+ ## Features
14
+
15
+ - šŸ“¦ **Bundled Templates** - Templates included in package, no network required
16
+ - šŸ”’ **Secure** - No runtime external dependencies
17
+ - āš›ļø **React** - React + Vite + Modus 2.0 Components + Cursor Rules
18
+ - šŸ…°ļø **Angular** - Angular + Modus 2.0 Web Components + Cursor Rules
19
+ - šŸŽÆ **Interactive** - Beautiful CLI with framework selection
20
+ - ⚔ **Fast** - Local file copy, instant setup
21
+
22
+ ## Usage
23
+
24
+ ### Interactive Mode (Recommended)
25
+
26
+ ```bash
27
+ npx @julianoczkowski/create-trimble-app
28
+ ```
29
+
30
+ This will guide you through:
31
+
32
+ 1. Framework selection (React or Angular)
33
+ 2. Installation location choice
34
+ 3. Project name input
35
+ 4. Optional dependency installation
36
+
37
+ ### Command Line Options
38
+
39
+ ```bash
40
+ # Create with project name
41
+ npx @julianoczkowski/create-trimble-app my-app
42
+
43
+ # Specify framework
44
+ npx @julianoczkowski/create-trimble-app my-app --framework react
45
+
46
+ # Install in current folder
47
+ npx @julianoczkowski/create-trimble-app --current-folder
48
+
49
+ # Preview without creating files
50
+ npx @julianoczkowski/create-trimble-app my-app --dry-run
51
+
52
+ # Enable verbose output
53
+ npx @julianoczkowski/create-trimble-app my-app --verbose
54
+
55
+ # Show CLI information
56
+ npx @julianoczkowski/create-trimble-app --info
57
+
58
+ # Skip dependency installation
59
+ npx @julianoczkowski/create-trimble-app my-app --no-install
60
+
61
+ # Show help
62
+ npx @julianoczkowski/create-trimble-app --help
63
+ ```
64
+
65
+ ## CLI Options
66
+
67
+ | Option | Description |
68
+ | ------------------------ | -------------------------------------- |
69
+ | `[project-name]` | Name of the project to create |
70
+ | `-f, --framework <name>` | Framework to use (react, angular) |
71
+ | `--current-folder` | Install in current folder |
72
+ | `--dry-run` | Preview what would be created |
73
+ | `--verbose` | Enable verbose output for debugging |
74
+ | `--info` | Show information about this CLI |
75
+ | `--no-install` | Skip automatic dependency installation |
76
+ | `-v, --version` | Display version number |
77
+ | `-h, --help` | Display help |
78
+
79
+ ## Supported Frameworks
80
+
81
+ | Framework | Description | What's Included |
82
+ | -------------- | ------------ | -------------------------------------------------------------------------------------------------------- |
83
+ | āš›ļø **React** | React + Vite | Modus 2.0 Components, TypeScript, Tailwind CSS, 40+ Cursor Rules, GitHub Templates, Code Quality Scripts |
84
+ | šŸ…°ļø **Angular** | Angular 20+ | Modus 2.0 Web Components, TypeScript, Tailwind CSS, 11 Cursor Rules, GitHub Workflows, Demo Components |
85
+
86
+ ## What's Included in Each Template
87
+
88
+ Both templates come fully configured with:
89
+
90
+ ```
91
+ your-project/
92
+ ā”œā”€ā”€ .cursor/ # Cursor IDE rules for Modus development
93
+ ā”œā”€ā”€ .github/ # Issue templates, PR template, CI workflows
94
+ ā”œā”€ā”€ .husky/ # Git hooks (pre-commit)
95
+ ā”œā”€ā”€ .vscode/ # VS Code extensions & settings
96
+ ā”œā”€ā”€ docs/ # Documentation
97
+ ā”œā”€ā”€ scripts/ # Code quality check scripts
98
+ ā”œā”€ā”€ src/ # Source code with demo components
99
+ ā”œā”€ā”€ package.json # All dependencies configured
100
+ └── README.md # Getting started guide
101
+ ```
102
+
103
+ ## Architecture
104
+
105
+ ```
106
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
107
+ │ npx create-trimble-app │
108
+ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
109
+ │ 1. Parse CLI arguments (Commander.js) │
110
+ │ 2. Interactive prompts (if needed) │
111
+ │ 3. Copy bundled template (local file copy) │
112
+ │ 4. Update package.json with project name │
113
+ │ 5. Install dependencies (optional) │
114
+ │ 6. Show success message │
115
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
116
+ ```
117
+
118
+ For detailed architecture documentation, see [docs/architecture.md](docs/architecture.md).
119
+
120
+ ## Security
121
+
122
+ This CLI is designed with security as a priority:
123
+
124
+ - **No External Downloads** - Templates are bundled in the npm package
125
+ - **Works Offline** - No network required to create projects
126
+ - **npm Provenance** - Published with provenance attestation
127
+ - **Minimal Dependencies** - Only essential runtime dependencies
128
+
129
+ Unlike other scaffolding tools that download templates from GitHub at runtime, this CLI bundles templates directly. This eliminates:
130
+
131
+ - Supply chain attacks from compromised repositories
132
+ - Network failures during project creation
133
+ - Version drift between CLI and templates
134
+
135
+ ## Requirements
136
+
137
+ - Node.js 18 or higher
138
+ - npm, yarn, or pnpm
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ # Clone this repository
144
+ git clone https://github.com/julianoczkowski/create-trimble-app.git
145
+ cd create-trimble-app
146
+
147
+ # Install dependencies
148
+ npm install
149
+
150
+ # Run locally
151
+ npm run dev
152
+
153
+ # Run tests
154
+ npm test
155
+
156
+ # Test specific commands
157
+ node bin/create-trimble-app.js --help
158
+ node bin/create-trimble-app.js my-app --framework react --dry-run
159
+ ```
160
+
161
+ For detailed testing instructions, see [docs/local-testing.md](docs/local-testing.md).
162
+
163
+ ## Documentation
164
+
165
+ | Document | Description |
166
+ | -------------------------------------- | ------------------------------ |
167
+ | [Architecture](docs/architecture.md) | How the CLI works internally |
168
+ | [Local Testing](docs/local-testing.md) | How to test during development |
169
+
170
+ ## Contributing
171
+
172
+ 1. Fork the repository
173
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
174
+ 3. Run tests (`npm test`)
175
+ 4. Commit your changes (`git commit -m 'Add some amazing feature'`)
176
+ 5. Push to the branch (`git push origin feature/amazing-feature`)
177
+ 6. Open a Pull Request
178
+
179
+ ## License
180
+
181
+ MIT Ā© Julian Oczkowski
182
+
183
+ ## Related
184
+
185
+ - [Modus Web Components Documentation](https://trimble-oss.github.io/modus-wc-2.0/main/?path=/docs/documentation-getting-started--docs)
186
+ - [Modus Icons](https://modus-icons.trimble.com/)
187
+ - [Trimble Modus Design System](https://modus.trimble.com)
188
+
189
+ ---
190
+
191
+ **Made with ā¤ļø for the Modus community**
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { cli } from "../src/cli.js";
4
+
5
+ // Run the CLI
6
+ cli().catch((error) => {
7
+ console.error("Error:", error.message);
8
+ process.exit(1);
9
+ });
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@julianoczkowski/create-trimble-app",
3
+ "version": "2.0.0",
4
+ "description": "Interactive CLI to scaffold Modus 2.0 web component applications for React and Angular - templates bundled, works offline",
5
+ "type": "module",
6
+ "main": "src/cli.js",
7
+ "bin": {
8
+ "create-trimble-app": "bin/create-trimble-app.js"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "src/",
13
+ "templates/"
14
+ ],
15
+ "scripts": {
16
+ "dev": "node bin/create-trimble-app.js",
17
+ "test": "vitest run",
18
+ "test:watch": "vitest",
19
+ "test:coverage": "vitest run --coverage",
20
+ "lint": "eslint src/",
21
+ "prepublishOnly": "npm run test && npm audit"
22
+ },
23
+ "keywords": [
24
+ "modus",
25
+ "web-components",
26
+ "cli",
27
+ "scaffold",
28
+ "react",
29
+ "angular",
30
+ "trimble",
31
+ "create-app",
32
+ "boilerplate",
33
+ "starter",
34
+ "template",
35
+ "offline"
36
+ ],
37
+ "author": "Julian Oczkowski",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/julianoczkowski/create-trimble-app.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/julianoczkowski/create-trimble-app/issues"
45
+ },
46
+ "homepage": "https://github.com/julianoczkowski/create-trimble-app#readme",
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public",
52
+ "registry": "https://registry.npmjs.org"
53
+ },
54
+ "dependencies": {
55
+ "chalk": "^5.3.0",
56
+ "commander": "^12.1.0",
57
+ "execa": "^8.0.1",
58
+ "ora": "^8.0.1",
59
+ "prompts": "^2.4.2",
60
+ "update-notifier": "^7.0.0"
61
+ },
62
+ "devDependencies": {
63
+ "@vitest/coverage-v8": "^4.0.18",
64
+ "eslint": "^9.0.0",
65
+ "vitest": "^4.0.18"
66
+ }
67
+ }
package/src/cli.js ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import chalk from "chalk";
5
+ import { readFileSync } from "fs";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname, join } from "path";
8
+ import { scaffold } from "./scaffold.js";
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ // Load package.json for version info
14
+ const packageJsonPath = join(__dirname, "..", "package.json");
15
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
16
+
17
+ // Check for updates (non-blocking)
18
+ async function checkForUpdates() {
19
+ try {
20
+ const { default: updateNotifier } = await import("update-notifier");
21
+ const notifier = updateNotifier({
22
+ pkg: packageJson,
23
+ updateCheckInterval: 1000 * 60 * 60 * 24, // 1 day
24
+ });
25
+ notifier.notify({ isGlobal: true });
26
+ } catch {
27
+ // Silently ignore update check failures
28
+ }
29
+ }
30
+
31
+ const program = new Command();
32
+
33
+ program
34
+ .name("create-trimble-app")
35
+ .description(
36
+ "Interactive CLI to scaffold Modus 2.0 web component applications",
37
+ )
38
+ .version(packageJson.version, "-v, --version", "Display version number")
39
+ .argument("[project-name]", "Name of the project to create")
40
+ .option(
41
+ "-f, --framework <name>",
42
+ "Framework to use (react, angular)",
43
+ validateFramework,
44
+ )
45
+ .option(
46
+ "--current-folder",
47
+ "Install in current folder and use folder name as project name",
48
+ )
49
+ .option("--no-install", "Skip automatic dependency installation")
50
+ .option("--dry-run", "Preview what would be created without making changes")
51
+ .option("--verbose", "Enable verbose output for debugging")
52
+ .option("--info", "Show information about this CLI")
53
+ .addHelpText(
54
+ "after",
55
+ `
56
+ ${chalk.cyan("Examples:")}
57
+ ${chalk.gray("# Interactive mode - choose framework and name")}
58
+ $ npx @julianoczkowski/create-trimble-app
59
+
60
+ ${chalk.gray("# Create a React project")}
61
+ $ npx @julianoczkowski/create-trimble-app my-app --framework react
62
+
63
+ ${chalk.gray("# Create an Angular project")}
64
+ $ npx @julianoczkowski/create-trimble-app my-app --framework angular
65
+
66
+ ${chalk.gray("# Install in current folder")}
67
+ $ npx @julianoczkowski/create-trimble-app --current-folder
68
+
69
+ ${chalk.gray("# Preview without creating files")}
70
+ $ npx @julianoczkowski/create-trimble-app my-app --dry-run
71
+
72
+ ${chalk.cyan("Frameworks:")}
73
+ ${chalk.white("react")} - React with Vite and Modus 2.0 Components
74
+ ${chalk.white("angular")} - Angular with Modus 2.0 Web Components
75
+
76
+ ${chalk.cyan("Security:")}
77
+ Templates are bundled directly in this CLI package.
78
+ No external downloads - works offline, always consistent.
79
+ Use ${chalk.yellow("--info")} for more details.
80
+
81
+ ${chalk.cyan("More information:")}
82
+ ${chalk.blue("https://github.com/julianoczkowski/create-trimble-app")}
83
+ `,
84
+ )
85
+ .action(async (projectName, options) => {
86
+ // Check for updates in background
87
+ checkForUpdates();
88
+
89
+ try {
90
+ await scaffold({
91
+ projectName,
92
+ framework: options.framework,
93
+ currentFolder: options.currentFolder,
94
+ install: options.install,
95
+ dryRun: options.dryRun,
96
+ verbose: options.verbose,
97
+ showInfo: options.info,
98
+ });
99
+ } catch (error) {
100
+ console.error(chalk.red("Error:"), error.message);
101
+ if (options.verbose) {
102
+ console.error(chalk.gray(error.stack));
103
+ }
104
+ process.exit(1);
105
+ }
106
+ });
107
+
108
+ /**
109
+ * Validate framework option
110
+ * @param {string} value - Framework name
111
+ * @returns {string} - Validated framework name
112
+ */
113
+ function validateFramework(value) {
114
+ const validFrameworks = ["react", "angular"];
115
+ const lowercaseValue = value.toLowerCase();
116
+
117
+ if (!validFrameworks.includes(lowercaseValue)) {
118
+ throw new Error(
119
+ `Invalid framework "${value}". Valid options: ${validFrameworks.join(", ")}`,
120
+ );
121
+ }
122
+
123
+ return lowercaseValue;
124
+ }
125
+
126
+ // Export for testing
127
+ export async function cli(args = process.argv) {
128
+ await program.parseAsync(args);
129
+ }
130
+
131
+ // Run CLI if this is the main module
132
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
133
+ cli();
134
+ }
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ export function loadFrameworks() {
9
+ try {
10
+ const configPath = join(__dirname, "../templates/config.json");
11
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
12
+
13
+ return Object.entries(config.frameworks)
14
+ .filter(([_id, framework]) => !framework.disabled)
15
+ .map(([id, framework]) => ({
16
+ id,
17
+ ...framework,
18
+ }));
19
+ } catch (error) {
20
+ throw new Error(
21
+ `Failed to load framework configurations: ${error.message}`,
22
+ );
23
+ }
24
+ }
25
+
26
+ export function getFrameworkById(frameworks, id) {
27
+ return frameworks.find((framework) => framework.id === id);
28
+ }
@@ -0,0 +1,209 @@
1
+ import prompts from "prompts";
2
+ import ora from "ora";
3
+ import chalk from "chalk";
4
+ import { loadFrameworks, getFrameworkById } from "./frameworks.js";
5
+ import {
6
+ updatePackageJson,
7
+ validateProjectName,
8
+ getCurrentFolderName,
9
+ } from "./utils/file.js";
10
+ import { installDependencies } from "./utils/install.js";
11
+ import { copyTemplate, getDetailedErrorMessage } from "./utils/git.js";
12
+ import { logger } from "./utils/logger.js";
13
+
14
+ export async function scaffold(options = {}) {
15
+ const { verbose = false, dryRun = false } = options;
16
+
17
+ // Set verbose mode
18
+ if (verbose) {
19
+ process.env.VERBOSE = "true";
20
+ }
21
+
22
+ // Show welcome screen
23
+ logger.welcome();
24
+
25
+ // Show security notice if requested
26
+ if (options.showInfo) {
27
+ logger.securityNotice();
28
+ process.exit(0);
29
+ }
30
+
31
+ const frameworks = loadFrameworks();
32
+
33
+ // 1. Framework Selection
34
+ let framework = options.framework;
35
+
36
+ if (!framework) {
37
+ const result = await prompts({
38
+ type: "select",
39
+ name: "framework",
40
+ message: "Select your framework:",
41
+ choices: frameworks.map((f) => ({
42
+ title: `${f.badge} ${f.name}`,
43
+ description: f.description + (f.note ? ` (${f.note})` : ""),
44
+ value: f.id,
45
+ })),
46
+ });
47
+ framework = result.framework;
48
+ }
49
+
50
+ if (!framework) {
51
+ console.log(chalk.yellow("X Cancelled"));
52
+ process.exit(0);
53
+ }
54
+
55
+ const config = getFrameworkById(frameworks, framework);
56
+
57
+ if (!config) {
58
+ console.error(chalk.red(`Error: Unknown framework "${framework}"`));
59
+ console.log(
60
+ chalk.yellow(
61
+ `Available frameworks: ${frameworks.map((f) => f.id).join(", ")}`,
62
+ ),
63
+ );
64
+ process.exit(1);
65
+ }
66
+
67
+ // 2. Installation Location Choice
68
+ let installInCurrentFolder = options.currentFolder;
69
+ let projectName = options.projectName;
70
+
71
+ if (!installInCurrentFolder && !projectName) {
72
+ const currentFolderName = getCurrentFolderName();
73
+
74
+ const result = await prompts({
75
+ type: "select",
76
+ name: "installLocation",
77
+ message: "Where would you like to install your app?",
78
+ choices: [
79
+ {
80
+ title: `šŸ“ Install in current directory (${currentFolderName})`,
81
+ description: "Use the current folder as your project directory",
82
+ value: "current",
83
+ },
84
+ {
85
+ title: "šŸ“‚ Create new directory",
86
+ description: "Create a new folder for your project",
87
+ value: "new",
88
+ },
89
+ ],
90
+ });
91
+
92
+ if (!result.installLocation) {
93
+ console.log(chalk.yellow("X Cancelled"));
94
+ process.exit(0);
95
+ }
96
+
97
+ installInCurrentFolder = result.installLocation === "current";
98
+ }
99
+
100
+ // 3. Project Name
101
+ if (installInCurrentFolder) {
102
+ projectName = getCurrentFolderName();
103
+ console.log(chalk.blue(`šŸ“ Using current folder name: ${projectName}`));
104
+ } else if (!projectName) {
105
+ const result = await prompts({
106
+ type: "text",
107
+ name: "projectName",
108
+ message: "Project name:",
109
+ initial: "my-modus-app",
110
+ validate: (name) => validateProjectName(name, false),
111
+ });
112
+ projectName = result.projectName;
113
+ } else {
114
+ const validation = validateProjectName(projectName, false);
115
+ if (validation !== true) {
116
+ console.error(chalk.red(`Error: ${validation}`));
117
+ process.exit(1);
118
+ }
119
+ }
120
+
121
+ if (!projectName) {
122
+ console.log(chalk.yellow("X Cancelled"));
123
+ process.exit(0);
124
+ }
125
+
126
+ const projectPath = installInCurrentFolder ? "." : projectName;
127
+
128
+ // Dry-run mode: show what would be created without executing
129
+ if (dryRun) {
130
+ console.log(chalk.cyan("\nšŸ” Dry-run mode - no changes will be made\n"));
131
+ console.log(chalk.white("Would create project with:"));
132
+ console.log(chalk.gray(` Framework: ${config.name}`));
133
+ console.log(chalk.gray(` Project name: ${projectName}`));
134
+ console.log(
135
+ chalk.gray(
136
+ ` Location: ${installInCurrentFolder ? "Current directory" : `New directory: ${projectName}`}`,
137
+ ),
138
+ );
139
+ console.log(chalk.gray(` Template: Bundled (included in CLI package)`));
140
+ console.log();
141
+ process.exit(0);
142
+ }
143
+
144
+ // 4. Copy Template
145
+ const spinner = ora(`šŸ“¦ Creating ${config.name} project...`).start();
146
+
147
+ try {
148
+ await copyTemplate(framework, projectPath);
149
+ spinner.succeed(chalk.green(`Project created successfully!`));
150
+
151
+ // 5. Update package.json with project name
152
+ try {
153
+ await updatePackageJson(projectPath, {
154
+ name: projectName,
155
+ });
156
+ logger.success("Updated project configuration");
157
+ } catch (error) {
158
+ logger.warning("Could not update package.json name");
159
+ if (verbose) {
160
+ console.log(chalk.gray(` Error: ${error.message}`));
161
+ }
162
+ }
163
+ } catch (error) {
164
+ spinner.fail(chalk.red(`Failed to create project`));
165
+ const detailedMessage = getDetailedErrorMessage(error);
166
+ console.error(chalk.red(`\n${detailedMessage}`));
167
+ process.exit(1);
168
+ }
169
+
170
+ // Visual separator before dependency installation
171
+ console.log(chalk.gray("═".repeat(60)));
172
+
173
+ // 6. Install Dependencies (optional)
174
+ let install = options.install;
175
+
176
+ if (install === undefined) {
177
+ const result = await prompts({
178
+ type: "confirm",
179
+ name: "install",
180
+ message: "šŸ“¦ Install dependencies now (default: yes)?",
181
+ initial: true,
182
+ });
183
+ install = result.install;
184
+ }
185
+
186
+ if (install) {
187
+ const installSpinner = ora("Installing dependencies...").start();
188
+ try {
189
+ await installDependencies(projectPath);
190
+ installSpinner.succeed(chalk.green("Dependencies installed"));
191
+ } catch (error) {
192
+ installSpinner.fail(chalk.red("Failed to install dependencies"));
193
+ console.error(chalk.red(error.message));
194
+ console.log(
195
+ chalk.yellow(`\nšŸ’” You can install dependencies manually by running:`),
196
+ );
197
+ const installCommand = installInCurrentFolder
198
+ ? "npm install"
199
+ : `cd ${projectName} && npm install`;
200
+ console.log(chalk.cyan(` ${installCommand}`));
201
+ }
202
+ }
203
+
204
+ // Visual separator before final success message
205
+ console.log(chalk.gray("═".repeat(60)));
206
+
207
+ // 7. Success Message
208
+ logger.nextSteps(projectName, config.name, install, installInCurrentFolder);
209
+ }
@@ -0,0 +1,47 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "fs";
2
+ import { join, basename } from "path";
3
+ import { cwd } from "process";
4
+
5
+ export async function updatePackageJson(projectPath, updates) {
6
+ const packageJsonPath = join(projectPath, "package.json");
7
+
8
+ try {
9
+ if (!existsSync(packageJsonPath)) {
10
+ throw new Error("package.json not found in template");
11
+ }
12
+
13
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
14
+
15
+ // Update only specified fields
16
+ Object.assign(packageJson, updates);
17
+
18
+ writeFileSync(
19
+ packageJsonPath,
20
+ JSON.stringify(packageJson, null, 2) + "\n",
21
+ "utf-8"
22
+ );
23
+ } catch (error) {
24
+ throw new Error(
25
+ `Failed to update package.json: ${error.message}. Contact julian_oczkowski@trimble.com`
26
+ );
27
+ }
28
+ }
29
+
30
+ export function getCurrentFolderName() {
31
+ return basename(cwd());
32
+ }
33
+
34
+ export function validateProjectName(name, isCurrentFolder = false) {
35
+ if (!name) return "Project name is required";
36
+
37
+ if (!/^[a-z0-9-_]+$/i.test(name)) {
38
+ return "Project name can't contain spaces. It can only contain letters, numbers, dashes.";
39
+ }
40
+
41
+ // Skip directory existence check if installing in current folder
42
+ if (!isCurrentFolder && existsSync(name)) {
43
+ return `Directory "${name}" already exists`;
44
+ }
45
+
46
+ return true;
47
+ }