@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.
- package/README.md +191 -0
- package/bin/create-trimble-app.js +9 -0
- package/package.json +67 -0
- package/src/cli.js +134 -0
- package/src/frameworks.js +28 -0
- package/src/scaffold.js +209 -0
- package/src/utils/file.js +47 -0
- package/src/utils/git.js +140 -0
- package/src/utils/install.js +25 -0
- package/src/utils/logger.js +124 -0
- package/templates/angular/.cursor/commands/remove-dev-content.md +394 -0
- package/templates/angular/.cursor/mcp.json +13 -0
- package/templates/angular/.cursor/rules/modus-angular-20.mdc +82 -0
- package/templates/angular/.cursor/rules/modus-angular-accordion-state-management-short.mdc +45 -0
- package/templates/angular/.cursor/rules/modus-angular-accordion-state-management.mdc +322 -0
- package/templates/angular/.cursor/rules/modus-angular-best-practices.mdc +472 -0
- package/templates/angular/.cursor/rules/modus-angular-border-usage-short.mdc +48 -0
- package/templates/angular/.cursor/rules/modus-angular-border-usage.mdc +286 -0
- package/templates/angular/.cursor/rules/modus-angular-button-group-usage-short.mdc +47 -0
- package/templates/angular/.cursor/rules/modus-angular-button-group-usage.mdc +263 -0
- package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion.mdc +92 -0
- package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing-short.mdc +34 -0
- package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing.mdc +185 -0
- package/templates/angular/.cursor/rules/modus-angular-color-usage-short.mdc +56 -0
- package/templates/angular/.cursor/rules/modus-angular-color-usage.mdc +208 -0
- package/templates/angular/.cursor/rules/modus-angular-components-reference.mdc +114 -0
- package/templates/angular/.cursor/rules/modus-angular-design-system.mdc +273 -0
- package/templates/angular/.cursor/rules/modus-angular-development-workflow-short.mdc +43 -0
- package/templates/angular/.cursor/rules/modus-angular-development-workflow.mdc +145 -0
- package/templates/angular/.cursor/rules/modus-angular-essentials.mdc +272 -0
- package/templates/angular/.cursor/rules/modus-angular-forms-validation-short.mdc +56 -0
- package/templates/angular/.cursor/rules/modus-angular-forms-validation.mdc +124 -0
- package/templates/angular/.cursor/rules/modus-angular-icon-names.mdc +70 -0
- package/templates/angular/.cursor/rules/modus-angular-icons-short.mdc +40 -0
- package/templates/angular/.cursor/rules/modus-angular-icons.mdc +137 -0
- package/templates/angular/.cursor/rules/modus-angular-implementation-guides-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-implementation-guides.mdc +301 -0
- package/templates/angular/.cursor/rules/modus-angular-integration-short.mdc +60 -0
- package/templates/angular/.cursor/rules/modus-angular-integration.mdc +1096 -0
- package/templates/angular/.cursor/rules/modus-angular-master.mdc +164 -0
- package/templates/angular/.cursor/rules/modus-angular-modal-usage-short.mdc +51 -0
- package/templates/angular/.cursor/rules/modus-angular-modal-usage.mdc +115 -0
- package/templates/angular/.cursor/rules/modus-angular-navbar-usage-short.mdc +49 -0
- package/templates/angular/.cursor/rules/modus-angular-navbar-usage.mdc +146 -0
- package/templates/angular/.cursor/rules/modus-angular-no-emojis.mdc +66 -0
- package/templates/angular/.cursor/rules/modus-angular-opacity-utilities-short.mdc +43 -0
- package/templates/angular/.cursor/rules/modus-angular-opacity-utilities.mdc +160 -0
- package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu-short.mdc +51 -0
- package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu.mdc +83 -0
- package/templates/angular/.cursor/rules/modus-angular-semantic-html-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-semantic-html.mdc +81 -0
- package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage-short.mdc +50 -0
- package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage.mdc +136 -0
- package/templates/angular/.cursor/rules/modus-angular-table-usage-short.mdc +52 -0
- package/templates/angular/.cursor/rules/modus-angular-table-usage.mdc +151 -0
- package/templates/angular/.cursor/rules/modus-angular-tailwind-usage-short.mdc +44 -0
- package/templates/angular/.cursor/rules/modus-angular-tailwind-usage.mdc +242 -0
- package/templates/angular/.cursor/rules/modus-angular-themes-short.mdc +54 -0
- package/templates/angular/.cursor/rules/modus-angular-themes.mdc +222 -0
- package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage-short.mdc +52 -0
- package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage.mdc +130 -0
- package/templates/angular/.cursor/rules/ux/gestalt-laws-detailed.mdc +514 -0
- package/templates/angular/.cursor/rules/ux/ux-ui-foundations.mdc +235 -0
- package/templates/angular/.cursor/skills/run-lint-checks/SKILL.md +169 -0
- package/templates/angular/.editorconfig +17 -0
- package/templates/angular/.github/dependabot.yml +19 -0
- package/templates/angular/.github/workflows/a11y-check.yml +135 -0
- package/templates/angular/.github/workflows/ci.yml +44 -0
- package/templates/angular/.husky/pre-commit +32 -0
- package/templates/angular/.postcssrc.json +5 -0
- package/templates/angular/.vscode/extensions.json +4 -0
- package/templates/angular/.vscode/launch.json +20 -0
- package/templates/angular/.vscode/tasks.json +42 -0
- package/templates/angular/CLAUDE.md +148 -0
- package/templates/angular/README.md +92 -0
- package/templates/angular/amplify.yml +25 -0
- package/templates/angular/angular.json +106 -0
- package/templates/angular/data/modusIcons.ts +861 -0
- package/templates/angular/package-lock.json +11030 -0
- package/templates/angular/package.json +66 -0
- package/templates/angular/public/angular-icon.svg +12 -0
- package/templates/angular/public/favicon.ico +0 -0
- package/templates/angular/public/modus-icons.css +49 -0
- package/templates/angular/public/vite.svg +1 -0
- package/templates/angular/scripts/README.md +410 -0
- package/templates/angular/scripts/check-border-violations.js +352 -0
- package/templates/angular/scripts/check-icon-names.js +402 -0
- package/templates/angular/scripts/check-inline-styles.js +292 -0
- package/templates/angular/scripts/check-modus-colors.js +282 -0
- package/templates/angular/scripts/check-modus-icons.js +263 -0
- package/templates/angular/scripts/check-opacity-utilities.js +426 -0
- package/templates/angular/scripts/check-semantic-html.js +452 -0
- package/templates/angular/scripts/check-typescript.js +109 -0
- package/templates/angular/src/app/app.config.ts +29 -0
- package/templates/angular/src/app/app.css +0 -0
- package/templates/angular/src/app/app.html +4 -0
- package/templates/angular/src/app/app.routes.ts +351 -0
- package/templates/angular/src/app/app.spec.ts +27 -0
- package/templates/angular/src/app/app.ts +47 -0
- package/templates/angular/src/app/components/README.md +77 -0
- package/templates/angular/src/app/components/index.ts +53 -0
- package/templates/angular/src/app/components/modus-accordion.component.ts +50 -0
- package/templates/angular/src/app/components/modus-alert.component.ts +133 -0
- package/templates/angular/src/app/components/modus-autocomplete.component.ts +262 -0
- package/templates/angular/src/app/components/modus-avatar.component.ts +75 -0
- package/templates/angular/src/app/components/modus-badge.component.ts +84 -0
- package/templates/angular/src/app/components/modus-breadcrumbs.component.ts +65 -0
- package/templates/angular/src/app/components/modus-button-group.component.ts +82 -0
- package/templates/angular/src/app/components/modus-button.component.ts +292 -0
- package/templates/angular/src/app/components/modus-card.component.ts +73 -0
- package/templates/angular/src/app/components/modus-checkbox.component.ts +117 -0
- package/templates/angular/src/app/components/modus-chip.component.ts +97 -0
- package/templates/angular/src/app/components/modus-collapse.component.ts +118 -0
- package/templates/angular/src/app/components/modus-date.component.ts +165 -0
- package/templates/angular/src/app/components/modus-dropdown-menu.component.ts +108 -0
- package/templates/angular/src/app/components/modus-file-dropzone.component.ts +121 -0
- package/templates/angular/src/app/components/modus-handle.component.ts +96 -0
- package/templates/angular/src/app/components/modus-icon.component.ts +81 -0
- package/templates/angular/src/app/components/modus-input-feedback.component.ts +54 -0
- package/templates/angular/src/app/components/modus-input-label.component.ts +62 -0
- package/templates/angular/src/app/components/modus-loader.component.ts +48 -0
- package/templates/angular/src/app/components/modus-logo.component.ts +115 -0
- package/templates/angular/src/app/components/modus-menu-item.component.ts +116 -0
- package/templates/angular/src/app/components/modus-menu.component.ts +58 -0
- package/templates/angular/src/app/components/modus-modal.component.ts +70 -0
- package/templates/angular/src/app/components/modus-navbar.component.ts +303 -0
- package/templates/angular/src/app/components/modus-number-input.component.ts +174 -0
- package/templates/angular/src/app/components/modus-pagination.component.ts +74 -0
- package/templates/angular/src/app/components/modus-panel.component.ts +61 -0
- package/templates/angular/src/app/components/modus-progress.component.ts +62 -0
- package/templates/angular/src/app/components/modus-radio.component.ts +102 -0
- package/templates/angular/src/app/components/modus-rating.component.ts +80 -0
- package/templates/angular/src/app/components/modus-select.component.ts +131 -0
- package/templates/angular/src/app/components/modus-side-navigation.component.ts +90 -0
- package/templates/angular/src/app/components/modus-skeleton.component.ts +54 -0
- package/templates/angular/src/app/components/modus-slider.component.ts +132 -0
- package/templates/angular/src/app/components/modus-stepper.component.ts +65 -0
- package/templates/angular/src/app/components/modus-switch.component.ts +118 -0
- package/templates/angular/src/app/components/modus-table.component.ts +204 -0
- package/templates/angular/src/app/components/modus-tabs.component.ts +82 -0
- package/templates/angular/src/app/components/modus-text-input.component.ts +221 -0
- package/templates/angular/src/app/components/modus-textarea.component.ts +168 -0
- package/templates/angular/src/app/components/modus-theme-switcher.component.ts +45 -0
- package/templates/angular/src/app/components/modus-time-input.component.ts +172 -0
- package/templates/angular/src/app/components/modus-toast.component.ts +63 -0
- package/templates/angular/src/app/components/modus-toolbar.component.ts +43 -0
- package/templates/angular/src/app/components/modus-tooltip.component.ts +83 -0
- package/templates/angular/src/app/components/modus-typography.component.ts +79 -0
- package/templates/angular/src/app/components/modus-utility-panel.component.ts +275 -0
- package/templates/angular/src/app/components/theme-demo.component.ts +1242 -0
- package/templates/angular/src/app/data/component-demos.ts +360 -0
- package/templates/angular/src/app/data/modus-icons.ts +806 -0
- package/templates/angular/src/app/demos/accordion/accordion-demo.component.ts +212 -0
- package/templates/angular/src/app/demos/alert/alert-demo.component.ts +108 -0
- package/templates/angular/src/app/demos/autocomplete/autocomplete-demo.component.ts +174 -0
- package/templates/angular/src/app/demos/avatar/avatar-demo.component.ts +149 -0
- package/templates/angular/src/app/demos/badge/badge-demo.component.ts +148 -0
- package/templates/angular/src/app/demos/breadcrumbs/breadcrumbs-demo.component.ts +96 -0
- package/templates/angular/src/app/demos/button/button-demo.component.ts +256 -0
- package/templates/angular/src/app/demos/button-group/button-group-demo.component.ts +215 -0
- package/templates/angular/src/app/demos/card/card-demo.component.ts +180 -0
- package/templates/angular/src/app/demos/checkbox/checkbox-demo.component.ts +71 -0
- package/templates/angular/src/app/demos/chip/chip-demo.component.ts +183 -0
- package/templates/angular/src/app/demos/date/date-demo.component.ts +193 -0
- package/templates/angular/src/app/demos/dropdown/dropdown-demo.component.ts +196 -0
- package/templates/angular/src/app/demos/file-dropzone/file-dropzone-demo.component.ts +176 -0
- package/templates/angular/src/app/demos/handle/handle-demo.component.ts +265 -0
- package/templates/angular/src/app/demos/icon/icon-demo.component.ts +65 -0
- package/templates/angular/src/app/demos/input-feedback/input-feedback-demo.component.ts +189 -0
- package/templates/angular/src/app/demos/input-label/input-label-demo.component.ts +330 -0
- package/templates/angular/src/app/demos/loader/loader-demo.component.ts +143 -0
- package/templates/angular/src/app/demos/logo/logo-demo.component.ts +191 -0
- package/templates/angular/src/app/demos/menu/menu-demo.component.ts +72 -0
- package/templates/angular/src/app/demos/modal/modal-demo.component.ts +278 -0
- package/templates/angular/src/app/demos/navbar/navbar-demo.component.ts +135 -0
- package/templates/angular/src/app/demos/number-input/number-input-demo.component.ts +175 -0
- package/templates/angular/src/app/demos/pagination/pagination-demo.component.ts +134 -0
- package/templates/angular/src/app/demos/panel/panel-demo.component.ts +235 -0
- package/templates/angular/src/app/demos/progress/progress-demo.component.ts +169 -0
- package/templates/angular/src/app/demos/radio/radio-demo.component.ts +161 -0
- package/templates/angular/src/app/demos/rating/rating-demo.component.ts +97 -0
- package/templates/angular/src/app/demos/select/select-demo.component.ts +107 -0
- package/templates/angular/src/app/demos/shared/demo-example-clean.component.ts +41 -0
- package/templates/angular/src/app/demos/shared/demo-example.component.ts +42 -0
- package/templates/angular/src/app/demos/shared/demo-page.component.ts +97 -0
- package/templates/angular/src/app/demos/shared/index.ts +3 -0
- package/templates/angular/src/app/demos/side-navigation/side-navigation-demo.component.ts +524 -0
- package/templates/angular/src/app/demos/skeleton/skeleton-demo.component.ts +112 -0
- package/templates/angular/src/app/demos/slider/slider-demo.component.ts +76 -0
- package/templates/angular/src/app/demos/stepper/stepper-demo.component.ts +79 -0
- package/templates/angular/src/app/demos/switch/switch-demo.component.ts +113 -0
- package/templates/angular/src/app/demos/table/table-demo.component.ts +405 -0
- package/templates/angular/src/app/demos/tabs/tabs-demo.component.ts +318 -0
- package/templates/angular/src/app/demos/text-input/text-input-demo.component.ts +160 -0
- package/templates/angular/src/app/demos/textarea/textarea-demo.component.ts +95 -0
- package/templates/angular/src/app/demos/theme-switcher/theme-switcher-demo.component.ts +38 -0
- package/templates/angular/src/app/demos/time-input/time-input-demo.component.ts +130 -0
- package/templates/angular/src/app/demos/toast/toast-demo.component.ts +258 -0
- package/templates/angular/src/app/demos/toolbar/toolbar-demo.component.ts +54 -0
- package/templates/angular/src/app/demos/tooltip/tooltip-demo.component.ts +163 -0
- package/templates/angular/src/app/demos/utility-panel/utility-panel-demo.component.ts +197 -0
- package/templates/angular/src/app/dev/dev-config.ts +119 -0
- package/templates/angular/src/app/dev/dev-panel/dev-panel.component.ts +215 -0
- package/templates/angular/src/app/dev/dev-panel.service.ts +63 -0
- package/templates/angular/src/app/dev/index.ts +8 -0
- package/templates/angular/src/app/dev/theme-switcher-dropdown/theme-switcher-dropdown.component.ts +134 -0
- package/templates/angular/src/app/dev-pages/color-palette/color-palette.component.ts +229 -0
- package/templates/angular/src/app/dev-pages/components-gallery/components-gallery.component.ts +486 -0
- package/templates/angular/src/app/dev-pages/icons/icons.component.ts +149 -0
- package/templates/angular/src/app/pages/home/home.component.ts +251 -0
- package/templates/angular/src/app/services/README.md +57 -0
- package/templates/angular/src/app/services/theme.service.ts +163 -0
- package/templates/angular/src/environments/environment.development.ts +8 -0
- package/templates/angular/src/environments/environment.ts +8 -0
- package/templates/angular/src/index.html +14 -0
- package/templates/angular/src/main.ts +6 -0
- package/templates/angular/src/styles.css +1328 -0
- package/templates/angular/tsconfig.app.json +15 -0
- package/templates/angular/tsconfig.json +35 -0
- package/templates/angular/tsconfig.spec.json +14 -0
- package/templates/config.json +23 -0
- package/templates/react/.cursor/commands/remove-dev-content.md +311 -0
- package/templates/react/.cursor/mcp.json +13 -0
- package/templates/react/.cursor/rules/README.md +240 -0
- package/templates/react/.cursor/rules/border-usage-guidelines-short.mdc +22 -0
- package/templates/react/.cursor/rules/border-usage-guidelines.mdc +380 -0
- package/templates/react/.cursor/rules/chrome-devtools-testing-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/development-workflow-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/development-workflow-react.mdc +292 -0
- package/templates/react/.cursor/rules/implementation-guides-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/implementation-guides-react.mdc +446 -0
- package/templates/react/.cursor/rules/modus-accordion-state-management-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-accordion-state-management-react.mdc +445 -0
- package/templates/react/.cursor/rules/modus-button-group-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-button-group-usage-react.mdc +117 -0
- package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react.mdc +492 -0
- package/templates/react/.cursor/rules/modus-color-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-color-usage-react.mdc +420 -0
- package/templates/react/.cursor/rules/modus-components-reference.mdc +366 -0
- package/templates/react/.cursor/rules/modus-icon-names.mdc +63 -0
- package/templates/react/.cursor/rules/modus-icons-react-short.mdc +24 -0
- package/templates/react/.cursor/rules/modus-icons-react.mdc +402 -0
- package/templates/react/.cursor/rules/modus-modal-implementation-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-modal-implementation-react.mdc +831 -0
- package/templates/react/.cursor/rules/modus-navbar-side-navigation-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-navbar-side-navigation-react.mdc +247 -0
- package/templates/react/.cursor/rules/modus-no-emojis-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-opacity-utilities-react-short.mdc +70 -0
- package/templates/react/.cursor/rules/modus-opacity-utilities-react.mdc +208 -0
- package/templates/react/.cursor/rules/modus-react-best-practices-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-best-practices.mdc +508 -0
- package/templates/react/.cursor/rules/modus-react-essentials.mdc +209 -0
- package/templates/react/.cursor/rules/modus-react-integration-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-integration.mdc +509 -0
- package/templates/react/.cursor/rules/modus-react-key-warnings-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-key-warnings.mdc +805 -0
- package/templates/react/.cursor/rules/modus-react-master.mdc +160 -0
- package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react.mdc +442 -0
- package/templates/react/.cursor/rules/modus-semantic-html-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-semantic-html-react.mdc +427 -0
- package/templates/react/.cursor/rules/modus-tailwind-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-tailwind-usage-react.mdc +642 -0
- package/templates/react/.cursor/rules/modus-themes-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-themes-react.mdc +506 -0
- package/templates/react/.cursor/rules/ux/gestalt-laws-detailed.mdc +456 -0
- package/templates/react/.cursor/rules/ux/ux-ui-foundations.mdc +211 -0
- package/templates/react/.cursor/skills/create-modus-form-component/SKILL.md +518 -0
- package/templates/react/.cursor/skills/create-modus-wrapper-component/SKILL.md +252 -0
- package/templates/react/.cursor/skills/fix-modus-component-event-issues/SKILL.md +345 -0
- package/templates/react/.cursor/skills/handle-modus-checkbox-value-bug/SKILL.md +202 -0
- package/templates/react/.cursor/skills/implement-modus-modal-with-refs/SKILL.md +386 -0
- package/templates/react/.cursor/skills/integrate-modus-icons/SKILL.md +300 -0
- package/templates/react/.cursor/skills/run-lint-checks/SKILL.md +235 -0
- package/templates/react/.cursor/skills/set-up-modus-event-listeners/SKILL.md +284 -0
- package/templates/react/.cursor/skills/style-modus-components-with-tailwind/SKILL.md +382 -0
- package/templates/react/.env.development +3 -0
- package/templates/react/.env.production +3 -0
- package/templates/react/.github/CODEOWNERS +28 -0
- package/templates/react/.github/ISSUE_TEMPLATE/bug_report.yml +176 -0
- package/templates/react/.github/ISSUE_TEMPLATE/config.yml +20 -0
- package/templates/react/.github/ISSUE_TEMPLATE/documentation.yml +115 -0
- package/templates/react/.github/ISSUE_TEMPLATE/feature_request.yml +171 -0
- package/templates/react/.github/ISSUE_TEMPLATE/question.yml +139 -0
- package/templates/react/.github/copilot-instructions.md +80 -0
- package/templates/react/.github/instructions/components.instructions.md +82 -0
- package/templates/react/.github/instructions/demos.instructions.md +82 -0
- package/templates/react/.github/instructions/pages.instructions.md +76 -0
- package/templates/react/.github/instructions/styles.instructions.md +77 -0
- package/templates/react/.github/instructions/typescript.instructions.md +101 -0
- package/templates/react/.github/pull_request_template.md +188 -0
- package/templates/react/.github/workflows/ci.yml +43 -0
- package/templates/react/.github/workflows/claude-code-review.yml +44 -0
- package/templates/react/.github/workflows/claude.yml +50 -0
- package/templates/react/.husky/pre-commit +28 -0
- package/templates/react/.vscode/extensions.json +8 -0
- package/templates/react/CLAUDE.md +119 -0
- package/templates/react/CODE_OF_CONDUCT.md +79 -0
- package/templates/react/CONTRIBUTING.md +65 -0
- package/templates/react/LICENSE +21 -0
- package/templates/react/README.md +728 -0
- package/templates/react/SECURITY.md +50 -0
- package/templates/react/eslint.config.js +23 -0
- package/templates/react/index.html +13 -0
- package/templates/react/package-lock.json +5209 -0
- package/templates/react/package.json +49 -0
- package/templates/react/postcss.config.js +6 -0
- package/templates/react/public/react.svg +1 -0
- package/templates/react/public/vite.svg +1 -0
- package/templates/react/readme_assets/getting_started_header.png +0 -0
- package/templates/react/readme_assets/hero.png +0 -0
- package/templates/react/readme_assets/modus_comp.png +0 -0
- package/templates/react/readme_assets/modus_figma_mcp.png +0 -0
- package/templates/react/readme_assets/teaser_comp.gif +0 -0
- package/templates/react/scripts/README.md +343 -0
- package/templates/react/scripts/check-border-violations.js +483 -0
- package/templates/react/scripts/check-icon-names.js +486 -0
- package/templates/react/scripts/check-inline-styles.js +364 -0
- package/templates/react/scripts/check-modus-colors.js +247 -0
- package/templates/react/scripts/check-modus-icons.js +256 -0
- package/templates/react/scripts/check-opacity-utilities.js +481 -0
- package/templates/react/scripts/check-semantic-html.js +476 -0
- package/templates/react/scripts/check-typescript.js +109 -0
- package/templates/react/src/App.css +42 -0
- package/templates/react/src/App.tsx +54 -0
- package/templates/react/src/assets/react.svg +1 -0
- package/templates/react/src/components/DemoExample.tsx +61 -0
- package/templates/react/src/components/DemoPage.tsx +81 -0
- package/templates/react/src/components/ModusAccordion.tsx +89 -0
- package/templates/react/src/components/ModusAlert.tsx +85 -0
- package/templates/react/src/components/ModusAutocomplete.tsx +207 -0
- package/templates/react/src/components/ModusAvatar.tsx +50 -0
- package/templates/react/src/components/ModusBadge.tsx +82 -0
- package/templates/react/src/components/ModusBreadcrumbs.tsx +75 -0
- package/templates/react/src/components/ModusButton.tsx +244 -0
- package/templates/react/src/components/ModusButtonGroup.tsx +91 -0
- package/templates/react/src/components/ModusCard.tsx +70 -0
- package/templates/react/src/components/ModusCheckbox.tsx +168 -0
- package/templates/react/src/components/ModusChip.tsx +93 -0
- package/templates/react/src/components/ModusDate.tsx +154 -0
- package/templates/react/src/components/ModusDropdownMenu.tsx +148 -0
- package/templates/react/src/components/ModusFileDropzone.tsx +140 -0
- package/templates/react/src/components/ModusHandle.tsx +101 -0
- package/templates/react/src/components/ModusIcon.tsx +49 -0
- package/templates/react/src/components/ModusInputFeedback.tsx +52 -0
- package/templates/react/src/components/ModusInputLabel.tsx +50 -0
- package/templates/react/src/components/ModusLoader.tsx +42 -0
- package/templates/react/src/components/ModusLogo.tsx +102 -0
- package/templates/react/src/components/ModusMenu.tsx +119 -0
- package/templates/react/src/components/ModusMenuItem.tsx +86 -0
- package/templates/react/src/components/ModusModal.tsx +145 -0
- package/templates/react/src/components/ModusNavbar.tsx +504 -0
- package/templates/react/src/components/ModusNumberInput.tsx +230 -0
- package/templates/react/src/components/ModusPagination.tsx +94 -0
- package/templates/react/src/components/ModusPanel.tsx +92 -0
- package/templates/react/src/components/ModusProgress.tsx +70 -0
- package/templates/react/src/components/ModusProvider.tsx +18 -0
- package/templates/react/src/components/ModusRadio.tsx +114 -0
- package/templates/react/src/components/ModusRating.tsx +108 -0
- package/templates/react/src/components/ModusSelect.tsx +171 -0
- package/templates/react/src/components/ModusSideNavigation.tsx +149 -0
- package/templates/react/src/components/ModusSkeleton.tsx +42 -0
- package/templates/react/src/components/ModusSlider.tsx +128 -0
- package/templates/react/src/components/ModusStepper.tsx +85 -0
- package/templates/react/src/components/ModusSwitch.tsx +130 -0
- package/templates/react/src/components/ModusTable.tsx +309 -0
- package/templates/react/src/components/ModusTabs.tsx +114 -0
- package/templates/react/src/components/ModusTextInput.tsx +179 -0
- package/templates/react/src/components/ModusTextarea.tsx +164 -0
- package/templates/react/src/components/ModusThemeSwitcher.tsx +58 -0
- package/templates/react/src/components/ModusTimeInput.tsx +176 -0
- package/templates/react/src/components/ModusToast.tsx +207 -0
- package/templates/react/src/components/ModusToolbar.tsx +70 -0
- package/templates/react/src/components/ModusTooltip.tsx +97 -0
- package/templates/react/src/components/ModusUtilityPanel.tsx +198 -0
- package/templates/react/src/components/ThemeSwitcherDropdown.tsx +117 -0
- package/templates/react/src/components/ThemeToggleSimple.tsx +157 -0
- package/templates/react/src/config/routes.ts +196 -0
- package/templates/react/src/contexts/ThemeContext.tsx +81 -0
- package/templates/react/src/contexts/ThemeContextData.tsx +89 -0
- package/templates/react/src/data/modusIcons.ts +865 -0
- package/templates/react/src/demos/accordion-demo/page.tsx +236 -0
- package/templates/react/src/demos/alert-demo/page.tsx +94 -0
- package/templates/react/src/demos/autocomplete-demo/page.tsx +166 -0
- package/templates/react/src/demos/avatar-demo/page.tsx +135 -0
- package/templates/react/src/demos/badge-demo/page.tsx +174 -0
- package/templates/react/src/demos/breadcrumbs-demo/page.tsx +88 -0
- package/templates/react/src/demos/button-demo/page.tsx +261 -0
- package/templates/react/src/demos/button-group-demo/page.tsx +231 -0
- package/templates/react/src/demos/card-demo/page.tsx +241 -0
- package/templates/react/src/demos/checkbox-demo/page.tsx +79 -0
- package/templates/react/src/demos/chip-demo/page.tsx +197 -0
- package/templates/react/src/demos/date-demo/page.tsx +179 -0
- package/templates/react/src/demos/dropdown-demo/page.tsx +150 -0
- package/templates/react/src/demos/file-dropzone-demo/page.tsx +186 -0
- package/templates/react/src/demos/handle-demo/page.tsx +313 -0
- package/templates/react/src/demos/icon-demo/page.tsx +72 -0
- package/templates/react/src/demos/input-feedback-demo/page.tsx +202 -0
- package/templates/react/src/demos/input-label-demo/page.tsx +392 -0
- package/templates/react/src/demos/loader-demo/page.tsx +138 -0
- package/templates/react/src/demos/logo-demo/page.tsx +292 -0
- package/templates/react/src/demos/menu-demo/page.tsx +70 -0
- package/templates/react/src/demos/modal-demo/page.tsx +332 -0
- package/templates/react/src/demos/navbar-demo/page.tsx +141 -0
- package/templates/react/src/demos/number-input-demo/page.tsx +180 -0
- package/templates/react/src/demos/pagination-demo/page.tsx +147 -0
- package/templates/react/src/demos/panel-demo/page.tsx +376 -0
- package/templates/react/src/demos/progress-demo/page.tsx +185 -0
- package/templates/react/src/demos/radio-demo/page.tsx +242 -0
- package/templates/react/src/demos/rating-demo/page.tsx +97 -0
- package/templates/react/src/demos/select-demo/page.tsx +111 -0
- package/templates/react/src/demos/side-navigation-demo/page.tsx +775 -0
- package/templates/react/src/demos/skeleton-demo/page.tsx +107 -0
- package/templates/react/src/demos/slider-demo/page.tsx +78 -0
- package/templates/react/src/demos/stepper-demo/page.tsx +86 -0
- package/templates/react/src/demos/switch-demo/page.tsx +146 -0
- package/templates/react/src/demos/table-demo/page.tsx +489 -0
- package/templates/react/src/demos/tabs-demo/page.tsx +187 -0
- package/templates/react/src/demos/text-input-demo/page.tsx +151 -0
- package/templates/react/src/demos/textarea-demo/page.tsx +73 -0
- package/templates/react/src/demos/theme-switcher-demo/page.tsx +26 -0
- package/templates/react/src/demos/time-input-demo/page.tsx +148 -0
- package/templates/react/src/demos/toast-demo/page.tsx +302 -0
- package/templates/react/src/demos/toolbar-demo/page.tsx +49 -0
- package/templates/react/src/demos/tooltip-demo/page.tsx +209 -0
- package/templates/react/src/demos/typography-test/page.tsx +28 -0
- package/templates/react/src/demos/utility-panel-demo/page.tsx +197 -0
- package/templates/react/src/dev/DevPanel.tsx +219 -0
- package/templates/react/src/dev/DevPanelContext.ts +14 -0
- package/templates/react/src/dev/DevPanelProvider.tsx +63 -0
- package/templates/react/src/dev/DevRoutes.tsx +98 -0
- package/templates/react/src/dev/config.ts +127 -0
- package/templates/react/src/dev/index.ts +8 -0
- package/templates/react/src/dev/useDevPanel.ts +17 -0
- package/templates/react/src/dev-pages/ColorPalettePage.tsx +347 -0
- package/templates/react/src/dev-pages/ComponentsGalleryPage.tsx +489 -0
- package/templates/react/src/dev-pages/IconsPage.tsx +137 -0
- package/templates/react/src/dev-pages/index.ts +3 -0
- package/templates/react/src/hooks/useTheme.ts +15 -0
- package/templates/react/src/index.css +635 -0
- package/templates/react/src/main.tsx +14 -0
- package/templates/react/src/pages/HomePage.tsx +283 -0
- package/templates/react/src/vite-env.d.ts +9 -0
- package/templates/react/tailwind.config.js +58 -0
- package/templates/react/tsconfig.app.json +27 -0
- package/templates/react/tsconfig.json +7 -0
- package/templates/react/tsconfig.node.json +25 -0
- package/templates/react/vite.config.ts +18 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-modus-wrapper-component
|
|
3
|
+
description: Scaffold a new Modus wrapper component following established patterns with proper TypeScript interfaces, event handling, and cleanup
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create Modus Wrapper Component
|
|
7
|
+
|
|
8
|
+
Scaffold a new Modus wrapper component following established patterns from the codebase.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Creating a new wrapper component for a Modus web component
|
|
14
|
+
- You need to integrate a Modus component that doesn't have a wrapper yet
|
|
15
|
+
- You want to ensure proper event handling and TypeScript types
|
|
16
|
+
|
|
17
|
+
## Pattern Overview
|
|
18
|
+
|
|
19
|
+
All Modus wrapper components follow this structure:
|
|
20
|
+
|
|
21
|
+
1. **Import the web component** from `@trimble-oss/moduswebcomponents-react`
|
|
22
|
+
2. **Define TypeScript props interface** with JSDoc comments
|
|
23
|
+
3. **Use `useRef`** for component reference
|
|
24
|
+
4. **Use `useEffect`** for event listeners with proper cleanup
|
|
25
|
+
5. **Forward props** to the web component with conditional spreading
|
|
26
|
+
6. **Handle events** via event listeners, not React props
|
|
27
|
+
|
|
28
|
+
## Reference Examples
|
|
29
|
+
|
|
30
|
+
- **Simple wrapper**: `src/components/ModusButton.tsx` - No event listeners needed
|
|
31
|
+
- **With event listeners**: `src/components/ModusCheckbox.tsx` - Shows event handling pattern
|
|
32
|
+
- **With dropdown**: `src/components/ModusDropdownMenu.tsx` - Shows menu event handling
|
|
33
|
+
|
|
34
|
+
## Implementation Template
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { useEffect, useRef } from "react";
|
|
38
|
+
import { ModusWc[ComponentName] } from "@trimble-oss/moduswebcomponents-react";
|
|
39
|
+
import type { ReactNode } from "react";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Props for the Modus[ComponentName] component.
|
|
43
|
+
*/
|
|
44
|
+
export interface Modus[ComponentName]Props {
|
|
45
|
+
/** Description of prop */
|
|
46
|
+
propName?: string;
|
|
47
|
+
|
|
48
|
+
/** A callback function to handle events. */
|
|
49
|
+
onEventName?: (event: CustomEvent<EventDetailType>) => void;
|
|
50
|
+
|
|
51
|
+
/** A custom CSS class to apply to the component. */
|
|
52
|
+
customClass?: string;
|
|
53
|
+
|
|
54
|
+
/** The ARIA label for accessibility. */
|
|
55
|
+
"aria-label"?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Renders a Modus [component name] component.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Basic usage
|
|
63
|
+
* <Modus[ComponentName] propName="value" />
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // With event handler
|
|
67
|
+
* <Modus[ComponentName]
|
|
68
|
+
* propName="value"
|
|
69
|
+
* onEventName={(event) => console.log(event.detail)}
|
|
70
|
+
* />
|
|
71
|
+
*
|
|
72
|
+
* @param {Modus[ComponentName]Props} props - The component props.
|
|
73
|
+
* @returns {JSX.Element} The rendered component.
|
|
74
|
+
* @see {@link https://modus.trimble.com/components/[component]} - Modus documentation
|
|
75
|
+
*/
|
|
76
|
+
export default function Modus[ComponentName]({
|
|
77
|
+
propName,
|
|
78
|
+
onEventName,
|
|
79
|
+
customClass,
|
|
80
|
+
"aria-label": ariaLabel,
|
|
81
|
+
}: Modus[ComponentName]Props) {
|
|
82
|
+
const componentRef = useRef<HTMLModusWc[ComponentName]Element>(null);
|
|
83
|
+
|
|
84
|
+
// Set up event listeners if needed
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const component = componentRef.current;
|
|
87
|
+
if (!component) return;
|
|
88
|
+
|
|
89
|
+
const handleEventName = (event: Event) => {
|
|
90
|
+
onEventName?.(event as CustomEvent<EventDetailType>);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (onEventName) {
|
|
94
|
+
component.addEventListener("eventName", handleEventName);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return () => {
|
|
98
|
+
if (onEventName) {
|
|
99
|
+
component.removeEventListener("eventName", handleEventName);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}, [onEventName]);
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<ModusWc[ComponentName]
|
|
106
|
+
ref={componentRef}
|
|
107
|
+
prop-name={propName}
|
|
108
|
+
custom-class={customClass}
|
|
109
|
+
aria-label={ariaLabel}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Key Patterns
|
|
116
|
+
|
|
117
|
+
### 1. Conditional Prop Spreading
|
|
118
|
+
|
|
119
|
+
For optional props that shouldn't be passed when undefined:
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
// ✅ CORRECT: Conditional spreading
|
|
123
|
+
<ModusWcComponent
|
|
124
|
+
{...(color && { color })}
|
|
125
|
+
{...(variant && { variant })}
|
|
126
|
+
size={size} // Required prop, always pass
|
|
127
|
+
/>
|
|
128
|
+
|
|
129
|
+
// ❌ WRONG: Passing undefined
|
|
130
|
+
<ModusWcComponent
|
|
131
|
+
color={color} // May be undefined
|
|
132
|
+
variant={variant} // May be undefined
|
|
133
|
+
/>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Reference: `src/components/ModusButton.tsx:229-230`
|
|
137
|
+
|
|
138
|
+
### 2. Event Listener Setup
|
|
139
|
+
|
|
140
|
+
Always use `useEffect` with cleanup:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
const component = componentRef.current;
|
|
145
|
+
if (!component) return;
|
|
146
|
+
|
|
147
|
+
const handleEvent = (event: Event) => {
|
|
148
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
if (onEvent) {
|
|
152
|
+
component.addEventListener("eventName", handleEvent);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return () => {
|
|
156
|
+
if (onEvent) {
|
|
157
|
+
component.removeEventListener("eventName", handleEvent);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}, [onEvent]);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Reference: `src/components/ModusCheckbox.tsx:91-150`
|
|
164
|
+
|
|
165
|
+
### 3. TypeScript Types
|
|
166
|
+
|
|
167
|
+
Use proper types for web component elements:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
// ✅ CORRECT: Proper element type
|
|
171
|
+
const componentRef = useRef<HTMLModusWcButtonElement>(null);
|
|
172
|
+
const componentRef = useRef<HTMLModusWcCheckboxElement>(null);
|
|
173
|
+
const componentRef = useRef<HTMLModusWcDropdownMenuElement>(null);
|
|
174
|
+
|
|
175
|
+
// Pattern: HTMLModusWc[ComponentName]Element
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 4. Prop Naming
|
|
179
|
+
|
|
180
|
+
Web components use kebab-case for props:
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
// React prop: customClass
|
|
184
|
+
// Web component prop: custom-class
|
|
185
|
+
<ModusWcComponent custom-class={customClass} />
|
|
186
|
+
|
|
187
|
+
// React prop: modalId
|
|
188
|
+
// Web component prop: modal-id
|
|
189
|
+
<ModusWcModal modal-id={modalId} />
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 5. Event Handler Types
|
|
193
|
+
|
|
194
|
+
Always type event handlers properly:
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
// ✅ CORRECT: Typed event handler
|
|
198
|
+
onEventName?: (event: CustomEvent<{ value: string }>) => void;
|
|
199
|
+
|
|
200
|
+
// In handler:
|
|
201
|
+
const handleEvent = (event: Event) => {
|
|
202
|
+
onEventName?.(event as CustomEvent<{ value: string }>);
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Common Event Names
|
|
207
|
+
|
|
208
|
+
Modus components use these common event names:
|
|
209
|
+
|
|
210
|
+
- `inputChange` - For input value changes
|
|
211
|
+
- `inputFocus` - For focus events
|
|
212
|
+
- `inputBlur` - For blur events
|
|
213
|
+
- `buttonClick` - For button clicks
|
|
214
|
+
- `itemSelect` - For menu/dropdown item selection
|
|
215
|
+
- `menuVisibilityChange` - For dropdown menu visibility
|
|
216
|
+
- `expandedChange` - For accordion/collapse state
|
|
217
|
+
|
|
218
|
+
Check the Modus documentation for component-specific events.
|
|
219
|
+
|
|
220
|
+
## Accessibility
|
|
221
|
+
|
|
222
|
+
Always include:
|
|
223
|
+
|
|
224
|
+
- `aria-label` prop for icon-only or non-text components
|
|
225
|
+
- Proper ARIA attributes passed to web component
|
|
226
|
+
- Keyboard navigation support (usually handled by web component)
|
|
227
|
+
|
|
228
|
+
## Testing Checklist
|
|
229
|
+
|
|
230
|
+
- [ ] Component renders without errors
|
|
231
|
+
- [ ] Props are forwarded correctly to web component
|
|
232
|
+
- [ ] Event listeners are set up and cleaned up properly
|
|
233
|
+
- [ ] TypeScript types are correct
|
|
234
|
+
- [ ] Accessibility attributes are included
|
|
235
|
+
- [ ] Conditional props don't pass undefined values
|
|
236
|
+
|
|
237
|
+
## Common Mistakes to Avoid
|
|
238
|
+
|
|
239
|
+
1. **Missing cleanup**: Always return cleanup function from `useEffect`
|
|
240
|
+
2. **Wrong event names**: Check Modus docs for exact event names
|
|
241
|
+
3. **Passing undefined**: Use conditional spreading for optional props
|
|
242
|
+
4. **Wrong prop names**: Web components use kebab-case, React uses camelCase
|
|
243
|
+
5. **Missing null checks**: Always check `componentRef.current` before use
|
|
244
|
+
|
|
245
|
+
## Next Steps
|
|
246
|
+
|
|
247
|
+
After creating the wrapper:
|
|
248
|
+
|
|
249
|
+
1. Export it from `src/components/index.ts` (if exists)
|
|
250
|
+
2. Create a demo page in `src/demos/[component]-demo/page.tsx`
|
|
251
|
+
3. Add to component reference documentation
|
|
252
|
+
4. Test all props and events
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fix-modus-component-event-issues
|
|
3
|
+
description: Debug and fix common event handling problems with Modus web components
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fix Modus Component Event Issues
|
|
7
|
+
|
|
8
|
+
Debug and fix common event handling problems with Modus web components.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Events aren't firing on Modus components
|
|
14
|
+
- Components aren't responding to user interactions
|
|
15
|
+
- Event handlers aren't being called
|
|
16
|
+
- You suspect event listener setup issues
|
|
17
|
+
|
|
18
|
+
## Common Issues and Solutions
|
|
19
|
+
|
|
20
|
+
### Issue 1: Events Not Firing
|
|
21
|
+
|
|
22
|
+
**Symptoms**: Click handlers, change handlers, or other events don't fire.
|
|
23
|
+
|
|
24
|
+
**Causes**:
|
|
25
|
+
1. Missing event listener setup
|
|
26
|
+
2. Wrong event name
|
|
27
|
+
3. Component ref not set up
|
|
28
|
+
4. Handler not passed as prop
|
|
29
|
+
|
|
30
|
+
**Solution**:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
// ✅ CORRECT: Proper event listener setup
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const component = componentRef.current;
|
|
36
|
+
if (!component) return;
|
|
37
|
+
|
|
38
|
+
const handleEvent = (event: Event) => {
|
|
39
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
if (onEvent) {
|
|
43
|
+
component.addEventListener("eventName", handleEvent);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
if (onEvent) {
|
|
48
|
+
component.removeEventListener("eventName", handleEvent);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}, [onEvent]); // ✅ Include handler in dependencies
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Checklist**:
|
|
55
|
+
- [ ] Component ref is created: `const componentRef = useRef<HTMLModusWcComponentElement>(null)`
|
|
56
|
+
- [ ] Ref is passed to web component: `<ModusWcComponent ref={componentRef} />`
|
|
57
|
+
- [ ] Event listener is added in `useEffect`
|
|
58
|
+
- [ ] Event name matches Modus documentation
|
|
59
|
+
- [ ] Handler is included in dependency array
|
|
60
|
+
- [ ] Cleanup function removes listener
|
|
61
|
+
|
|
62
|
+
### Issue 2: Missing Cleanup
|
|
63
|
+
|
|
64
|
+
**Symptoms**: Memory leaks, events firing multiple times, component errors after unmount.
|
|
65
|
+
|
|
66
|
+
**Solution**:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
const component = componentRef.current;
|
|
71
|
+
if (!component) return;
|
|
72
|
+
|
|
73
|
+
const handleEvent = (event: Event) => {
|
|
74
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
component.addEventListener("eventName", handleEvent);
|
|
78
|
+
|
|
79
|
+
// ✅ CRITICAL: Always return cleanup function
|
|
80
|
+
return () => {
|
|
81
|
+
component.removeEventListener("eventName", handleEvent);
|
|
82
|
+
};
|
|
83
|
+
}, [onEvent]);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Issue 3: Wrong Event Names
|
|
87
|
+
|
|
88
|
+
**Symptoms**: Events never fire, wrong event type received.
|
|
89
|
+
|
|
90
|
+
**Common Event Names**:
|
|
91
|
+
|
|
92
|
+
| Component | Event Name | Detail Type |
|
|
93
|
+
|-----------|------------|-------------|
|
|
94
|
+
| Checkbox | `inputChange` | `InputEvent` |
|
|
95
|
+
| TextInput | `inputChange` | `InputEvent` |
|
|
96
|
+
| DropdownMenu | `itemSelect` | `{ value: string }` |
|
|
97
|
+
| DropdownMenu | `menuVisibilityChange` | `{ isVisible: boolean }` |
|
|
98
|
+
| Navbar | `searchClick` | `MouseEvent \| KeyboardEvent` |
|
|
99
|
+
| Accordion | `expandedChange` | `{ expanded: boolean; index: number }` |
|
|
100
|
+
|
|
101
|
+
**Solution**: Check Modus documentation for exact event names. They're case-sensitive.
|
|
102
|
+
|
|
103
|
+
### Issue 4: Missing Ref
|
|
104
|
+
|
|
105
|
+
**Symptoms**: `Cannot read property 'addEventListener' of null`, events don't attach.
|
|
106
|
+
|
|
107
|
+
**Solution**:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
// ✅ CORRECT: Ref setup
|
|
111
|
+
const componentRef = useRef<HTMLModusWcComponentElement>(null);
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
const component = componentRef.current;
|
|
115
|
+
if (!component) return; // ✅ Check before use
|
|
116
|
+
|
|
117
|
+
// Set up listeners
|
|
118
|
+
}, []);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<ModusWcComponent ref={componentRef} /> // ✅ Pass ref
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Issue 5: Handler Not in Dependencies
|
|
126
|
+
|
|
127
|
+
**Symptoms**: Stale closures, handlers use old values.
|
|
128
|
+
|
|
129
|
+
**Solution**:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
const component = componentRef.current;
|
|
134
|
+
if (!component) return;
|
|
135
|
+
|
|
136
|
+
const handleEvent = (event: Event) => {
|
|
137
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
if (onEvent) {
|
|
141
|
+
component.addEventListener("eventName", handleEvent);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return () => {
|
|
145
|
+
if (onEvent) {
|
|
146
|
+
component.removeEventListener("eventName", handleEvent);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}, [onEvent]); // ✅ Include handler in dependencies
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Issue 6: Wrong Event Target
|
|
153
|
+
|
|
154
|
+
**Symptoms**: Can't access component properties, wrong value extracted.
|
|
155
|
+
|
|
156
|
+
**Solution**:
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
// ✅ CORRECT: Cast to proper element type
|
|
160
|
+
const handleInputChange = (event: Event) => {
|
|
161
|
+
const customEvent = event as CustomEvent<InputEvent>;
|
|
162
|
+
const value = (customEvent.target as HTMLModusWcTextInputElement).value;
|
|
163
|
+
onInputChange?.(value);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// ❌ WRONG: Don't use event.detail for input values
|
|
167
|
+
const handleInputChange = (event: Event) => {
|
|
168
|
+
const value = event.detail; // Wrong for input components!
|
|
169
|
+
};
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Issue 7: Multiple Event Listeners
|
|
173
|
+
|
|
174
|
+
**Symptoms**: Events fire multiple times, duplicate handlers.
|
|
175
|
+
|
|
176
|
+
**Solution**:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
// ✅ CORRECT: Conditional attachment
|
|
180
|
+
if (onEvent) {
|
|
181
|
+
component.addEventListener("eventName", handleEvent);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ✅ CORRECT: Remove in cleanup
|
|
185
|
+
return () => {
|
|
186
|
+
if (onEvent) {
|
|
187
|
+
component.removeEventListener("eventName", handleEvent);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Debugging Checklist
|
|
193
|
+
|
|
194
|
+
When events aren't working, check:
|
|
195
|
+
|
|
196
|
+
1. **Ref Setup**
|
|
197
|
+
- [ ] `useRef` is created with correct type
|
|
198
|
+
- [ ] Ref is passed to web component
|
|
199
|
+
- [ ] Ref is checked before use (`if (!component) return`)
|
|
200
|
+
|
|
201
|
+
2. **Event Listener Setup**
|
|
202
|
+
- [ ] Listener is added in `useEffect`
|
|
203
|
+
- [ ] Event name matches Modus documentation
|
|
204
|
+
- [ ] Handler function is defined
|
|
205
|
+
- [ ] Handler is conditionally attached (if prop exists)
|
|
206
|
+
|
|
207
|
+
3. **Cleanup**
|
|
208
|
+
- [ ] Cleanup function is returned from `useEffect`
|
|
209
|
+
- [ ] Listener is removed in cleanup
|
|
210
|
+
- [ ] Same handler reference is used for add/remove
|
|
211
|
+
|
|
212
|
+
4. **Dependencies**
|
|
213
|
+
- [ ] Handler props are in dependency array
|
|
214
|
+
- [ ] No missing dependencies causing stale closures
|
|
215
|
+
|
|
216
|
+
5. **Event Handling**
|
|
217
|
+
- [ ] Event is cast to correct `CustomEvent` type
|
|
218
|
+
- [ ] Value is extracted correctly (`target.value` vs `detail`)
|
|
219
|
+
- [ ] Handler is called with correct parameters
|
|
220
|
+
|
|
221
|
+
## Debugging Tools
|
|
222
|
+
|
|
223
|
+
### Console Logging
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
const component = componentRef.current;
|
|
228
|
+
if (!component) {
|
|
229
|
+
console.error("Component ref is null");
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.log("Setting up event listener for:", component);
|
|
234
|
+
|
|
235
|
+
const handleEvent = (event: Event) => {
|
|
236
|
+
console.log("Event fired:", event);
|
|
237
|
+
console.log("Event type:", event.type);
|
|
238
|
+
console.log("Event target:", event.target);
|
|
239
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
component.addEventListener("eventName", handleEvent);
|
|
243
|
+
console.log("Event listener attached");
|
|
244
|
+
|
|
245
|
+
return () => {
|
|
246
|
+
console.log("Cleaning up event listener");
|
|
247
|
+
component.removeEventListener("eventName", handleEvent);
|
|
248
|
+
};
|
|
249
|
+
}, [onEvent]);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### React DevTools
|
|
253
|
+
|
|
254
|
+
- Check if component ref is set
|
|
255
|
+
- Verify component is mounted
|
|
256
|
+
- Check if handlers are defined
|
|
257
|
+
|
|
258
|
+
### Browser DevTools
|
|
259
|
+
|
|
260
|
+
- Check Event Listeners panel for attached listeners
|
|
261
|
+
- Verify event names match
|
|
262
|
+
- Check for errors in console
|
|
263
|
+
|
|
264
|
+
## Common Patterns to Verify
|
|
265
|
+
|
|
266
|
+
### Pattern 1: Basic Event Setup
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
// ✅ Verify this pattern
|
|
270
|
+
const componentRef = useRef<HTMLModusWcComponentElement>(null);
|
|
271
|
+
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
const component = componentRef.current;
|
|
274
|
+
if (!component) return;
|
|
275
|
+
|
|
276
|
+
const handleEvent = (event: Event) => {
|
|
277
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
if (onEvent) {
|
|
281
|
+
component.addEventListener("eventName", handleEvent);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return () => {
|
|
285
|
+
if (onEvent) {
|
|
286
|
+
component.removeEventListener("eventName", handleEvent);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}, [onEvent]);
|
|
290
|
+
|
|
291
|
+
return <ModusWcComponent ref={componentRef} />;
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Pattern 2: Multiple Events
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
// ✅ Verify all events are set up
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
const component = componentRef.current;
|
|
300
|
+
if (!component) return;
|
|
301
|
+
|
|
302
|
+
const handleEvent1 = (event: Event) => {
|
|
303
|
+
onEvent1?.(event as CustomEvent<Type1>);
|
|
304
|
+
};
|
|
305
|
+
const handleEvent2 = (event: Event) => {
|
|
306
|
+
onEvent2?.(event as CustomEvent<Type2>);
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
if (onEvent1) component.addEventListener("event1", handleEvent1);
|
|
310
|
+
if (onEvent2) component.addEventListener("event2", handleEvent2);
|
|
311
|
+
|
|
312
|
+
return () => {
|
|
313
|
+
if (onEvent1) component.removeEventListener("event1", handleEvent1);
|
|
314
|
+
if (onEvent2) component.removeEventListener("event2", handleEvent2);
|
|
315
|
+
};
|
|
316
|
+
}, [onEvent1, onEvent2]); // ✅ All handlers in dependencies
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Quick Fixes
|
|
320
|
+
|
|
321
|
+
### Fix: Events Not Firing
|
|
322
|
+
|
|
323
|
+
1. Check if ref is set: `console.log(componentRef.current)`
|
|
324
|
+
2. Verify event name: Check Modus docs
|
|
325
|
+
3. Add console.log in handler to verify it's called
|
|
326
|
+
4. Check if handler prop is passed
|
|
327
|
+
|
|
328
|
+
### Fix: Events Firing Multiple Times
|
|
329
|
+
|
|
330
|
+
1. Check if cleanup is removing listeners
|
|
331
|
+
2. Verify handler isn't recreated on each render
|
|
332
|
+
3. Check dependency array includes handler
|
|
333
|
+
|
|
334
|
+
### Fix: Wrong Values
|
|
335
|
+
|
|
336
|
+
1. Verify event type casting
|
|
337
|
+
2. Check if using `target.value` vs `detail`
|
|
338
|
+
3. For checkboxes, verify value inversion is handled
|
|
339
|
+
|
|
340
|
+
## Related Files
|
|
341
|
+
|
|
342
|
+
- `src/components/ModusCheckbox.tsx` - Event handling example
|
|
343
|
+
- `src/components/ModusDropdownMenu.tsx` - Multiple events example
|
|
344
|
+
- `src/components/ModusNavbar.tsx` - Complex event handling
|
|
345
|
+
- `.cursor/rules/modus-react-integration.mdc` - Integration patterns
|