@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,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Angular 20 best practices and coding standards with signals, standalone components, and modern patterns
|
|
3
|
+
globs: ["**/*.ts", "**/*.html", "**/*.scss", "**/*.css"]
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Angular 20 Best Practices
|
|
8
|
+
|
|
9
|
+
This project adheres to modern Angular best practices, emphasizing maintainability, performance, accessibility, and scalability.
|
|
10
|
+
|
|
11
|
+
## TypeScript Best Practices
|
|
12
|
+
|
|
13
|
+
* **Strict Type Checking:** Always enable and adhere to strict type checking.
|
|
14
|
+
* **Prefer Type Inference:** Allow TypeScript to infer types when they are obvious from the context.
|
|
15
|
+
* **Avoid `any`:** Do not use the `any` type unless absolutely necessary. Prefer `unknown` when a type is uncertain.
|
|
16
|
+
|
|
17
|
+
## Angular Best Practices
|
|
18
|
+
|
|
19
|
+
* **Standalone Components:** Always use standalone components, directives, and pipes. Avoid using `NgModules` for new features.
|
|
20
|
+
* **Implicit Standalone:** Do not explicitly set `standalone: true` inside the `@Component`, `@Directive` and `@Pipe` decorators, as it is implied by default.
|
|
21
|
+
* **Signals for State Management:** Utilize Angular Signals for reactive state management within components and services.
|
|
22
|
+
* **Lazy Loading:** Implement lazy loading for feature routes to improve initial load times.
|
|
23
|
+
* **NgOptimizedImage:** Use `NgOptimizedImage` for all static images to automatically optimize image loading and performance.
|
|
24
|
+
* **Host bindings:** Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead.
|
|
25
|
+
|
|
26
|
+
## Components
|
|
27
|
+
|
|
28
|
+
* **Single Responsibility:** Keep components small, focused, and responsible for a single piece of functionality.
|
|
29
|
+
* **`input()` and `output()` Functions:** Prefer `input()` and `output()` functions over the `@Input()` and `@Output()` decorators:
|
|
30
|
+
```typescript
|
|
31
|
+
import { input, output } from '@angular/core';
|
|
32
|
+
|
|
33
|
+
userId = input<string>('');
|
|
34
|
+
userSelected = output<string>();
|
|
35
|
+
```
|
|
36
|
+
* **`computed()` for Derived State:** Use the `computed()` function from `@angular/core` for derived state based on signals.
|
|
37
|
+
* **`ChangeDetectionStrategy.OnPush`:** Always set `changeDetection: ChangeDetectionStrategy.OnPush` in the `@Component` decorator.
|
|
38
|
+
* **Inline Templates:** Prefer inline templates (template: `...`) for small components. For larger templates, use external HTML files.
|
|
39
|
+
* **Reactive Forms:** Prefer Reactive forms over Template-driven forms for complex forms.
|
|
40
|
+
* **No `ngClass` / `NgClass`:** Do not use the `ngClass` directive. Instead, use native `class` bindings:
|
|
41
|
+
```html
|
|
42
|
+
<section [class.active]="isActive"></section>
|
|
43
|
+
<section [class]="{'active': isActive}"></section>
|
|
44
|
+
```
|
|
45
|
+
* **No `ngStyle` / `NgStyle`:** Do not use the `ngStyle` directive. Instead, use native `style` bindings:
|
|
46
|
+
```html
|
|
47
|
+
<section [style.font-size.px]="fontSize"></section>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## State Management
|
|
51
|
+
|
|
52
|
+
* **Signals for Local State:** Use signals for managing local component state.
|
|
53
|
+
* **`computed()` for Derived State:** Leverage `computed()` for any state that can be derived from other signals.
|
|
54
|
+
* **Pure and Predictable Transformations:** Ensure state transformations are pure functions (no side effects) and predictable.
|
|
55
|
+
* **Signal value updates:** Do NOT use `mutate` on signals, use `update` or `set` instead.
|
|
56
|
+
|
|
57
|
+
## Templates
|
|
58
|
+
|
|
59
|
+
* **Simple Templates:** Keep templates as simple as possible, avoiding complex logic directly in the template.
|
|
60
|
+
* **Native Control Flow:** Use the new built-in control flow syntax (`@if`, `@for`, `@switch`) instead of the older structural directives (`*ngIf`, `*ngFor`, `*ngSwitch`):
|
|
61
|
+
```html
|
|
62
|
+
@if (isVisible) {
|
|
63
|
+
<section>Content</section>
|
|
64
|
+
}
|
|
65
|
+
@for (item of items; track item.id) {
|
|
66
|
+
<section>{{ item }}</section>
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
* **Async Pipe:** Use the `async` pipe to handle observables in templates.
|
|
70
|
+
|
|
71
|
+
## Services
|
|
72
|
+
|
|
73
|
+
* **Single Responsibility:** Design services around a single, well-defined responsibility.
|
|
74
|
+
* **`providedIn: 'root'`:** Use the `providedIn: 'root'` option when declaring injectable services to ensure they are singletons and tree-shakable.
|
|
75
|
+
* **`inject()` Function:** Prefer the `inject()` function over constructor injection:
|
|
76
|
+
```typescript
|
|
77
|
+
import { inject } from '@angular/core';
|
|
78
|
+
|
|
79
|
+
export class MyComponent {
|
|
80
|
+
private myService = inject(MyService);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: State management patterns for Modus accordion components in Angular
|
|
3
|
+
globs: ["**/*.ts", "**/*.html", "**/*.scss", "**/*.css"]
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Modus Accordion State Management - Short
|
|
8
|
+
|
|
9
|
+
Essential state management patterns for Modus Accordion components in Angular.
|
|
10
|
+
|
|
11
|
+
## Key Rules
|
|
12
|
+
|
|
13
|
+
- **Let Modus components manage their own state** - Don't try to control accordion state from Angular
|
|
14
|
+
- **Use `expanded` for initial state only** - Set initial state, then let component handle changes
|
|
15
|
+
- **Use `(expandedChange)` for tracking** - Monitor state changes without controlling them
|
|
16
|
+
- **Use ViewChild for programmatic control** - Access component methods when needed
|
|
17
|
+
- **Avoid real-time synchronization** - Don't sync Angular state with accordion state
|
|
18
|
+
- **Don't use signals to control accordion** - Creates state loops and conflicts
|
|
19
|
+
|
|
20
|
+
## Correct Patterns
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// CORRECT: Let Modus manage state
|
|
24
|
+
@Component({
|
|
25
|
+
template: `
|
|
26
|
+
<modus-accordion>
|
|
27
|
+
<modus-collapse collapse-id="item1" [expanded]="true">
|
|
28
|
+
<div slot="content">Content</div>
|
|
29
|
+
</modus-collapse>
|
|
30
|
+
</modus-accordion>
|
|
31
|
+
`,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// CORRECT: ViewChild for programmatic control
|
|
35
|
+
readonly collapseRef = viewChild<ElementRef>('collapseRef');
|
|
36
|
+
|
|
37
|
+
openAccordion(): void {
|
|
38
|
+
const collapse = this.collapseRef()?.nativeElement;
|
|
39
|
+
if (collapse) collapse.expanded = true;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Reference
|
|
44
|
+
|
|
45
|
+
For detailed state management patterns and advanced accordion usage, fetch the full rule: `modus-angular-accordion-state-management`
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: State management patterns for Modus accordion components in Angular
|
|
3
|
+
globs: ["**/*.ts", "**/*.html", "**/*.scss", "**/*.css"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Modus Accordion State Management in Angular
|
|
8
|
+
|
|
9
|
+
## IMPORTANT: Accordion State Management Guidelines
|
|
10
|
+
|
|
11
|
+
**Key Principle**: Modus Web Components (`modus-wc-accordion`, `modus-wc-collapse`) are designed to manage their own state, but they DO support controlled state when needed.
|
|
12
|
+
|
|
13
|
+
**Best Practice**: Use the `expanded` attribute on `modus-wc-collapse` components for initial state or programmatic control, but avoid trying to synchronize Angular state with Modus state in real-time.
|
|
14
|
+
|
|
15
|
+
## Common Anti-Patterns
|
|
16
|
+
|
|
17
|
+
### Real-time State Synchronization
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// WRONG: Trying to sync Angular state with Modus state in real-time
|
|
21
|
+
@Component({
|
|
22
|
+
template: `
|
|
23
|
+
<modus-accordion
|
|
24
|
+
(expandedChange)="onExpandedChange($event)"
|
|
25
|
+
>
|
|
26
|
+
<modus-collapse
|
|
27
|
+
[expanded]="isExpanded()" <!-- Creates state loop -->
|
|
28
|
+
>
|
|
29
|
+
<div slot="content">Content</div>
|
|
30
|
+
</modus-collapse>
|
|
31
|
+
</modus-accordion>
|
|
32
|
+
`,
|
|
33
|
+
})
|
|
34
|
+
export class AccordionComponent {
|
|
35
|
+
readonly isExpanded = signal(false);
|
|
36
|
+
|
|
37
|
+
onExpandedChange(event: CustomEvent): void {
|
|
38
|
+
this.isExpanded.set(event.detail.expanded); // Creates conflicts
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Complex State Synchronization
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// WRONG: Complex state synchronization that can cause loops
|
|
47
|
+
@Component({
|
|
48
|
+
template: `
|
|
49
|
+
@for (item of items(); track item.id) {
|
|
50
|
+
<modus-accordion
|
|
51
|
+
(expandedChange)="toggleAccordion(item.id)" <!-- Creates loops -->
|
|
52
|
+
>
|
|
53
|
+
<modus-collapse
|
|
54
|
+
[expanded]="accordionStates()[item.id]" <!-- Causes conflicts -->
|
|
55
|
+
>
|
|
56
|
+
<div slot="content">Content for {{ item.id }}</div>
|
|
57
|
+
</modus-collapse>
|
|
58
|
+
</modus-accordion>
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
})
|
|
62
|
+
export class MyComponent {
|
|
63
|
+
readonly items = signal([{ id: 'item1' }, { id: 'item2' }]);
|
|
64
|
+
readonly accordionStates = signal<Record<string, boolean>>({
|
|
65
|
+
item1: false,
|
|
66
|
+
item2: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
toggleAccordion(id: string): void {
|
|
70
|
+
this.accordionStates.update(states => ({
|
|
71
|
+
...states,
|
|
72
|
+
[id]: !states[id],
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Correct Patterns
|
|
79
|
+
|
|
80
|
+
### Let Modus Components Manage Their Own State
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// CORRECT: Let Modus accordion manage its own state
|
|
84
|
+
@Component({
|
|
85
|
+
template: `
|
|
86
|
+
<modus-accordion>
|
|
87
|
+
<modus-collapse
|
|
88
|
+
collapse-id="item1"
|
|
89
|
+
[options]="{
|
|
90
|
+
title: 'Item One',
|
|
91
|
+
description: 'First accordion item',
|
|
92
|
+
icon: 'star'
|
|
93
|
+
}"
|
|
94
|
+
>
|
|
95
|
+
<div slot="content">Content for item one.</div>
|
|
96
|
+
</modus-collapse>
|
|
97
|
+
</modus-accordion>
|
|
98
|
+
`,
|
|
99
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
100
|
+
})
|
|
101
|
+
export class AccordionComponent {}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Initial State Control (Recommended)
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// CORRECT: Set initial state without real-time synchronization
|
|
108
|
+
@Component({
|
|
109
|
+
template: `
|
|
110
|
+
<modus-accordion>
|
|
111
|
+
<modus-collapse
|
|
112
|
+
collapse-id="item1"
|
|
113
|
+
[expanded]="true" <!-- CORRECT: Initial state is fine -->
|
|
114
|
+
[options]="{
|
|
115
|
+
title: 'Initially Open',
|
|
116
|
+
description: 'This item starts expanded'
|
|
117
|
+
}"
|
|
118
|
+
>
|
|
119
|
+
<div slot="content">Content for item one.</div>
|
|
120
|
+
</modus-collapse>
|
|
121
|
+
</modus-accordion>
|
|
122
|
+
`,
|
|
123
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
124
|
+
})
|
|
125
|
+
export class AccordionComponent {}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Listen to Events for Tracking (Not Control)
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// CORRECT: Listen to events for tracking, don't control state
|
|
132
|
+
@Component({
|
|
133
|
+
template: `
|
|
134
|
+
<modus-accordion (expandedChange)="handleAccordionChange($event)">
|
|
135
|
+
<modus-collapse
|
|
136
|
+
collapse-id="item1"
|
|
137
|
+
[options]="{
|
|
138
|
+
title: 'Item One',
|
|
139
|
+
description: 'First accordion item'
|
|
140
|
+
}"
|
|
141
|
+
>
|
|
142
|
+
<div slot="content">Content for item one.</div>
|
|
143
|
+
</modus-collapse>
|
|
144
|
+
</modus-accordion>
|
|
145
|
+
`,
|
|
146
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
147
|
+
})
|
|
148
|
+
export class AccordionComponent {
|
|
149
|
+
readonly trackingData = signal({
|
|
150
|
+
accordionOpened: false,
|
|
151
|
+
openCount: 0,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
handleAccordionChange(event: CustomEvent<{ expanded: boolean; index: number }>): void {
|
|
155
|
+
const { expanded, index } = event.detail;
|
|
156
|
+
|
|
157
|
+
// CORRECT: Use for tracking/analytics, not state control
|
|
158
|
+
this.trackingData.update(data => ({
|
|
159
|
+
accordionOpened: expanded,
|
|
160
|
+
openCount: expanded ? data.openCount + 1 : data.openCount,
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
// CORRECT: Log for analytics
|
|
164
|
+
console.log(`Accordion item ${index} is now ${expanded ? 'open' : 'closed'}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Programmatic Control When Needed
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// CORRECT: Use ViewChild for programmatic control
|
|
173
|
+
@Component({
|
|
174
|
+
template: `
|
|
175
|
+
<div class="space-x-2">
|
|
176
|
+
<modus-button (buttonClick)="openAccordion()">Open Accordion</modus-button>
|
|
177
|
+
<modus-button (buttonClick)="closeAccordion()">Close Accordion</modus-button>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<modus-accordion>
|
|
181
|
+
<modus-collapse
|
|
182
|
+
#collapseRef
|
|
183
|
+
collapse-id="item1"
|
|
184
|
+
[options]="{
|
|
185
|
+
title: 'Controllable Item',
|
|
186
|
+
description: 'This can be controlled programmatically'
|
|
187
|
+
}"
|
|
188
|
+
>
|
|
189
|
+
<div slot="content">Content for controllable item.</div>
|
|
190
|
+
</modus-collapse>
|
|
191
|
+
</modus-accordion>
|
|
192
|
+
`,
|
|
193
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
194
|
+
})
|
|
195
|
+
export class AccordionComponent {
|
|
196
|
+
readonly collapseRef = viewChild<ElementRef>('collapseRef');
|
|
197
|
+
|
|
198
|
+
openAccordion(): void {
|
|
199
|
+
const collapse = this.collapseRef()?.nativeElement;
|
|
200
|
+
if (collapse) {
|
|
201
|
+
collapse.expanded = true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
closeAccordion(): void {
|
|
206
|
+
const collapse = this.collapseRef()?.nativeElement;
|
|
207
|
+
if (collapse) {
|
|
208
|
+
collapse.expanded = false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Best Practices
|
|
215
|
+
|
|
216
|
+
### State Management Strategy
|
|
217
|
+
|
|
218
|
+
1. **Let Modus Components Own Their State**
|
|
219
|
+
|
|
220
|
+
- Don't try to control `expanded` from Angular signals
|
|
221
|
+
- Use events to track state changes
|
|
222
|
+
- Use ViewChild for programmatic control when needed
|
|
223
|
+
|
|
224
|
+
2. **Event-Driven Architecture**
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// CORRECT: Event-driven approach
|
|
228
|
+
@Component({
|
|
229
|
+
template: `
|
|
230
|
+
<modus-accordion (expandedChange)="handleAccordionChange($event)">
|
|
231
|
+
<div slot="header">Header</div>
|
|
232
|
+
<div slot="body">Body</div>
|
|
233
|
+
</modus-accordion>
|
|
234
|
+
`,
|
|
235
|
+
})
|
|
236
|
+
export class MyComponent {
|
|
237
|
+
handleAccordionChange(event: CustomEvent): void {
|
|
238
|
+
// Handle the event for tracking, analytics, or side effects
|
|
239
|
+
// Don't try to control the accordion state
|
|
240
|
+
console.log('Accordion expanded:', event.detail);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
3. **Use ViewChild for Programmatic Control**
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// CORRECT: ViewChild-based control
|
|
249
|
+
readonly accordionRef = viewChild<ElementRef>('accordionRef');
|
|
250
|
+
|
|
251
|
+
toggleAccordion(): void {
|
|
252
|
+
const accordion = this.accordionRef()?.nativeElement;
|
|
253
|
+
if (accordion) {
|
|
254
|
+
accordion.expanded = !accordion.expanded;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Multiple Accordions Pattern
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
// CORRECT: Multiple accordions with independent state
|
|
263
|
+
@Component({
|
|
264
|
+
template: `
|
|
265
|
+
<div class="space-x-2">
|
|
266
|
+
<modus-button (buttonClick)="openAllAccordions()">Open All</modus-button>
|
|
267
|
+
<modus-button (buttonClick)="closeAllAccordions()">Close All</modus-button>
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
@for (item of accordionData(); track item.id; let i = $index) {
|
|
271
|
+
<modus-accordion>
|
|
272
|
+
<modus-collapse
|
|
273
|
+
#accordionRefs
|
|
274
|
+
[collapse-id]="item.id"
|
|
275
|
+
[options]="{ title: item.title }"
|
|
276
|
+
>
|
|
277
|
+
<div slot="content">{{ item.content }}</div>
|
|
278
|
+
</modus-collapse>
|
|
279
|
+
</modus-accordion>
|
|
280
|
+
}
|
|
281
|
+
`,
|
|
282
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
283
|
+
})
|
|
284
|
+
export class MultipleAccordionsComponent {
|
|
285
|
+
readonly accordionData = signal([
|
|
286
|
+
{ id: 'acc1', title: 'Accordion 1', content: 'Content 1' },
|
|
287
|
+
{ id: 'acc2', title: 'Accordion 2', content: 'Content 2' },
|
|
288
|
+
{ id: 'acc3', title: 'Accordion 3', content: 'Content 3' },
|
|
289
|
+
]);
|
|
290
|
+
|
|
291
|
+
readonly accordionRefs = viewChildren<ElementRef>('accordionRefs');
|
|
292
|
+
|
|
293
|
+
openAllAccordions(): void {
|
|
294
|
+
this.accordionRefs().forEach(ref => {
|
|
295
|
+
if (ref.nativeElement) {
|
|
296
|
+
ref.nativeElement.expanded = true;
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
closeAllAccordions(): void {
|
|
302
|
+
this.accordionRefs().forEach(ref => {
|
|
303
|
+
if (ref.nativeElement) {
|
|
304
|
+
ref.nativeElement.expanded = false;
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Key Takeaways
|
|
312
|
+
|
|
313
|
+
1. **Initial State is Fine**: Setting `[expanded]="true"` for initial state is perfectly acceptable
|
|
314
|
+
2. **Avoid Real-time Sync**: Don't try to synchronize Angular state with Modus state in real-time
|
|
315
|
+
3. **Use Events for Tracking**: Listen to `(expandedChange)` for analytics and side effects
|
|
316
|
+
4. **Use ViewChild for Control**: When you need programmatic control, use ViewChild on `modus-collapse`
|
|
317
|
+
5. **Trust the Component**: Modus Web Components handle their own state changes after initial render
|
|
318
|
+
6. **Proper Structure**: Use `modus-accordion` with `modus-collapse` components and `options` for headers
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
**Remember: Modus accordion components support controlled initial state but avoid real-time synchronization. Use `expanded` for initial state, `(expandedChange)` for tracking, and ViewChild for programmatic control. This approach prevents conflicts and ensures reliable behavior.**
|