@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,476 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Semantic HTML Linting Script for Vite + React
|
|
5
|
+
*
|
|
6
|
+
* This script checks for usage of semantic HTML elements that should be replaced with div elements
|
|
7
|
+
* and Tailwind classes to ensure consistent styling and avoid browser default style conflicts.
|
|
8
|
+
*
|
|
9
|
+
* It flags semantic HTML elements and suggests div alternatives with appropriate Tailwind classes.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import fs from "fs";
|
|
13
|
+
import path from "path";
|
|
14
|
+
import { glob } from "glob";
|
|
15
|
+
|
|
16
|
+
// Semantic HTML elements to detect (should be replaced with div + Tailwind)
|
|
17
|
+
// Updated patterns to be more specific and avoid TypeScript/JavaScript syntax
|
|
18
|
+
const SEMANTIC_HTML_PATTERNS = [
|
|
19
|
+
// Headings - more specific to avoid matching TypeScript generics
|
|
20
|
+
/<h[1-6](?:\s+[^>]*)?>/g,
|
|
21
|
+
|
|
22
|
+
// Semantic sections
|
|
23
|
+
/<section(?:\s+[^>]*)?>/g,
|
|
24
|
+
/<header(?:\s+[^>]*)?>/g,
|
|
25
|
+
/<footer(?:\s+[^>]*)?>/g,
|
|
26
|
+
/<main(?:\s+[^>]*)?>/g,
|
|
27
|
+
/<article(?:\s+[^>]*)?>/g,
|
|
28
|
+
/<aside(?:\s+[^>]*)?>/g,
|
|
29
|
+
/<nav(?:\s+[^>]*)?>/g,
|
|
30
|
+
|
|
31
|
+
// Text elements - more specific patterns
|
|
32
|
+
/<p(?:\s+[^>]*)?>/g,
|
|
33
|
+
/<span(?:\s+[^>]*)?>/g,
|
|
34
|
+
|
|
35
|
+
// Lists
|
|
36
|
+
/<ul(?:\s+[^>]*)?>/g,
|
|
37
|
+
/<ol(?:\s+[^>]*)?>/g,
|
|
38
|
+
/<li(?:\s+[^>]*)?>/g,
|
|
39
|
+
|
|
40
|
+
// Other semantic elements - more specific patterns
|
|
41
|
+
/<button(?:\s+[^>]*)?>/g,
|
|
42
|
+
/<blockquote(?:\s+[^>]*)?>/g,
|
|
43
|
+
/<cite(?:\s+[^>]*)?>/g,
|
|
44
|
+
/<address(?:\s+[^>]*)?>/g,
|
|
45
|
+
/<time(?:\s+[^>]*)?>/g,
|
|
46
|
+
/<mark(?:\s+[^>]*)?>/g,
|
|
47
|
+
/<small(?:\s+[^>]*)?>/g,
|
|
48
|
+
/<strong(?:\s+[^>]*)?>/g,
|
|
49
|
+
/<em(?:\s+[^>]*)?>/g,
|
|
50
|
+
/<b(?:\s+[^>]*)?>/g,
|
|
51
|
+
/<i(?:\s+[^>]*)?>/g,
|
|
52
|
+
/<u(?:\s+[^>]*)?>/g,
|
|
53
|
+
// More specific patterns for potentially problematic elements
|
|
54
|
+
/<s(?:\s+[^>]*)?>/g, // Only match <s> with attributes or closing
|
|
55
|
+
/<del(?:\s+[^>]*)?>/g,
|
|
56
|
+
/<ins(?:\s+[^>]*)?>/g,
|
|
57
|
+
/<sub(?:\s+[^>]*)?>/g,
|
|
58
|
+
/<sup(?:\s+[^>]*)?>/g,
|
|
59
|
+
/<pre(?:\s+[^>]*)?>/g,
|
|
60
|
+
/<kbd(?:\s+[^>]*)?>/g,
|
|
61
|
+
/<samp(?:\s+[^>]*)?>/g,
|
|
62
|
+
/<var(?:\s+[^>]*)?>/g,
|
|
63
|
+
/<dfn(?:\s+[^>]*)?>/g,
|
|
64
|
+
/<abbr(?:\s+[^>]*)?>/g,
|
|
65
|
+
/<acronym(?:\s+[^>]*)?>/g,
|
|
66
|
+
/<q(?:\s+[^>]*)?>/g,
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// Files to check
|
|
70
|
+
const FILE_PATTERNS = [
|
|
71
|
+
"src/**/*.tsx",
|
|
72
|
+
"src/**/*.ts",
|
|
73
|
+
"src/**/*.jsx",
|
|
74
|
+
"src/**/*.js",
|
|
75
|
+
"src/**/*.css",
|
|
76
|
+
"src/**/*.scss",
|
|
77
|
+
"*.tsx",
|
|
78
|
+
"*.ts",
|
|
79
|
+
"*.js",
|
|
80
|
+
"test-*.tsx",
|
|
81
|
+
"test-*.ts",
|
|
82
|
+
"test-*.js",
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
// Files to exclude
|
|
86
|
+
const EXCLUDE_PATTERNS = [
|
|
87
|
+
"node_modules/**",
|
|
88
|
+
"dist/**",
|
|
89
|
+
"build/**",
|
|
90
|
+
"**/*.d.ts",
|
|
91
|
+
"scripts/**",
|
|
92
|
+
"**/*.md",
|
|
93
|
+
"**/*.mdx",
|
|
94
|
+
"**/*.txt",
|
|
95
|
+
"**/*.json",
|
|
96
|
+
"**/*.yml",
|
|
97
|
+
"**/*.yaml",
|
|
98
|
+
"**/*.xml",
|
|
99
|
+
"**/*.html",
|
|
100
|
+
"**/*.svg",
|
|
101
|
+
"**/*.png",
|
|
102
|
+
"**/*.jpg",
|
|
103
|
+
"**/*.jpeg",
|
|
104
|
+
"**/*.gif",
|
|
105
|
+
"**/*.ico",
|
|
106
|
+
"**/*.pdf",
|
|
107
|
+
"**/*.doc",
|
|
108
|
+
"**/*.docx",
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
// Tailwind alternatives for common semantic elements
|
|
112
|
+
const TAILWIND_ALTERNATIVES = {
|
|
113
|
+
// Headings
|
|
114
|
+
"<h1": '<div className="text-4xl font-bold',
|
|
115
|
+
"<h2": '<div className="text-3xl font-semibold',
|
|
116
|
+
"<h3": '<div className="text-2xl font-semibold',
|
|
117
|
+
"<h4": '<div className="text-xl font-semibold',
|
|
118
|
+
"<h5": '<div className="text-lg font-semibold',
|
|
119
|
+
"<h6": '<div className="text-base font-semibold',
|
|
120
|
+
|
|
121
|
+
// Sections
|
|
122
|
+
"<section": '<div className="',
|
|
123
|
+
"<header": '<div className="',
|
|
124
|
+
"<footer": '<div className="',
|
|
125
|
+
"<main": '<div className="',
|
|
126
|
+
"<article": '<div className="',
|
|
127
|
+
"<aside": '<div className="',
|
|
128
|
+
"<nav": '<div className="',
|
|
129
|
+
|
|
130
|
+
// Text elements
|
|
131
|
+
"<p": '<div className="text-base',
|
|
132
|
+
"<span": '<div className="',
|
|
133
|
+
|
|
134
|
+
// Lists
|
|
135
|
+
"<ul": '<div className="list-none',
|
|
136
|
+
"<ol": '<div className="list-none',
|
|
137
|
+
"<li": '<div className="',
|
|
138
|
+
|
|
139
|
+
// Other elements
|
|
140
|
+
"<button": '<ModusWcButton color="primary"',
|
|
141
|
+
"<blockquote": '<div className="border-l-4 pl-4 italic border-left-default',
|
|
142
|
+
"<cite": '<div className="text-sm text-muted-foreground italic',
|
|
143
|
+
"<address": '<div className="text-sm not-italic',
|
|
144
|
+
"<time": '<div className="text-sm',
|
|
145
|
+
"<mark": '<div className="bg-yellow-200 dark:bg-yellow-800',
|
|
146
|
+
"<small": '<div className="text-sm',
|
|
147
|
+
"<strong": '<div className="font-bold',
|
|
148
|
+
"<em": '<div className="italic',
|
|
149
|
+
"<b": '<div className="font-bold',
|
|
150
|
+
"<i": '<div className="italic',
|
|
151
|
+
"<u": '<div className="underline',
|
|
152
|
+
"<s": '<div className="line-through',
|
|
153
|
+
"<del": '<div className="line-through',
|
|
154
|
+
"<ins": '<div className="underline',
|
|
155
|
+
"<sub": '<div className="text-xs align-sub',
|
|
156
|
+
"<sup": '<div className="text-xs align-super',
|
|
157
|
+
"<pre":
|
|
158
|
+
'<div className="bg-muted p-4 rounded text-sm font-mono overflow-x-auto',
|
|
159
|
+
"<kbd": '<div className="bg-muted px-2 py-1 rounded text-sm font-mono border',
|
|
160
|
+
"<samp": '<div className="bg-muted px-1 py-0.5 rounded text-sm font-mono',
|
|
161
|
+
"<var": '<div className="italic',
|
|
162
|
+
"<dfn": '<div className="italic',
|
|
163
|
+
"<abbr": '<div className="underline decoration-dotted',
|
|
164
|
+
"<acronym": '<div className="underline decoration-dotted',
|
|
165
|
+
"<q": '<div className="italic',
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
function getTailwindSuggestion(element) {
|
|
169
|
+
// Try to find exact matches first
|
|
170
|
+
for (const [semanticElement, tailwindAlternative] of Object.entries(
|
|
171
|
+
TAILWIND_ALTERNATIVES
|
|
172
|
+
)) {
|
|
173
|
+
if (element.includes(semanticElement)) {
|
|
174
|
+
return tailwindAlternative;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Generic suggestions based on common patterns
|
|
179
|
+
if (element.includes("<h")) {
|
|
180
|
+
return '<div className="text-lg font-semibold';
|
|
181
|
+
}
|
|
182
|
+
if (
|
|
183
|
+
element.includes("<section") ||
|
|
184
|
+
element.includes("<header") ||
|
|
185
|
+
element.includes("<footer")
|
|
186
|
+
) {
|
|
187
|
+
return '<div className="';
|
|
188
|
+
}
|
|
189
|
+
if (element.includes("<p")) {
|
|
190
|
+
return '<div className="text-base';
|
|
191
|
+
}
|
|
192
|
+
if (element.includes("<ul") || element.includes("<ol")) {
|
|
193
|
+
return '<div className="list-none';
|
|
194
|
+
}
|
|
195
|
+
if (element.includes("<strong") || element.includes("<b")) {
|
|
196
|
+
return '<div className="font-bold';
|
|
197
|
+
}
|
|
198
|
+
if (element.includes("<em") || element.includes("<i")) {
|
|
199
|
+
return '<div className="italic';
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return '<div className="';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function isAllowedSemanticElement(element, content, matchIndex) {
|
|
206
|
+
// Allow certain semantic elements in specific contexts
|
|
207
|
+
const beforeMatch = content.substring(0, matchIndex);
|
|
208
|
+
const afterMatch = content.substring(matchIndex + element.length);
|
|
209
|
+
|
|
210
|
+
// Check if the element is in a JSX comment
|
|
211
|
+
const commentStart = beforeMatch.lastIndexOf("/*");
|
|
212
|
+
const commentEnd = beforeMatch.lastIndexOf("*/");
|
|
213
|
+
if (commentStart > commentEnd) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check if this is TypeScript/JavaScript syntax, not HTML
|
|
218
|
+
// Look for patterns that indicate TypeScript generics or JavaScript syntax
|
|
219
|
+
const typescriptPatterns = [
|
|
220
|
+
// TypeScript generics: <Map<string, number>>, <string>, <boolean>
|
|
221
|
+
/<[A-Z][a-zA-Z]*<[^>]*>>/,
|
|
222
|
+
/<[a-zA-Z]+(?:,\s*[a-zA-Z]+)*>/,
|
|
223
|
+
// Function calls: <string, number>
|
|
224
|
+
/<[a-zA-Z]+(?:,\s*[a-zA-Z]+)*>/,
|
|
225
|
+
// Array types: <string[]>
|
|
226
|
+
/<[a-zA-Z]+\[\]>/,
|
|
227
|
+
// Union types: <string | number>
|
|
228
|
+
/<[a-zA-Z]+\s*\|\s*[a-zA-Z]+>/,
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
for (const pattern of typescriptPatterns) {
|
|
232
|
+
if (pattern.test(element)) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Check if the element is part of TypeScript/JavaScript syntax
|
|
238
|
+
// Look for context clues like type annotations, generics, etc.
|
|
239
|
+
const contextBefore = beforeMatch.slice(-50); // Last 50 characters before match
|
|
240
|
+
const contextAfter = afterMatch.slice(0, 50); // First 50 characters after match
|
|
241
|
+
|
|
242
|
+
// TypeScript/JavaScript context patterns
|
|
243
|
+
const codeContextPatterns = [
|
|
244
|
+
// Type annotations: : <string>
|
|
245
|
+
/:\s*$/,
|
|
246
|
+
// Generic parameters: <T extends
|
|
247
|
+
/<[A-Z]\w*\s+extends/,
|
|
248
|
+
// Function parameters: (<string, number>
|
|
249
|
+
/\(\s*$/,
|
|
250
|
+
// Array declarations: Array<
|
|
251
|
+
/Array\s*$/,
|
|
252
|
+
// Map/Set declarations: Map<, Set<
|
|
253
|
+
/(Map|Set)\s*$/,
|
|
254
|
+
// React component props: <ComponentProps<
|
|
255
|
+
/<[A-Z]\w*Props\s*$/,
|
|
256
|
+
// useRef declarations: useRef<
|
|
257
|
+
/useRef\s*$/,
|
|
258
|
+
// useState declarations: useState<
|
|
259
|
+
/useState\s*$/,
|
|
260
|
+
// useCallback declarations: useCallback<
|
|
261
|
+
/useCallback\s*$/,
|
|
262
|
+
// useMemo declarations: useMemo<
|
|
263
|
+
/useMemo\s*$/,
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
for (const pattern of codeContextPatterns) {
|
|
267
|
+
if (pattern.test(contextBefore)) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Check if the element is in a string literal (but not JSX attributes)
|
|
273
|
+
// Look for quotes that are actually part of string literals, not JSX attributes
|
|
274
|
+
const singleQuoteStart = beforeMatch.lastIndexOf("'");
|
|
275
|
+
const doubleQuoteStart = beforeMatch.lastIndexOf('"');
|
|
276
|
+
const backtickStart = beforeMatch.lastIndexOf("`");
|
|
277
|
+
const lastQuote = Math.max(singleQuoteStart, doubleQuoteStart, backtickStart);
|
|
278
|
+
|
|
279
|
+
if (lastQuote > Math.max(commentStart, commentEnd)) {
|
|
280
|
+
// Check if this quote is part of a JSX attribute (className="...", style="...", etc.)
|
|
281
|
+
// or if it's actually a string literal
|
|
282
|
+
const beforeQuote = content.substring(0, lastQuote);
|
|
283
|
+
|
|
284
|
+
// Look for JSX attribute patterns before the quote
|
|
285
|
+
const jsxAttributePattern =
|
|
286
|
+
/(className|style|id|aria-\w+|data-\w+|on\w+)\s*=\s*$/;
|
|
287
|
+
if (jsxAttributePattern.test(beforeQuote)) {
|
|
288
|
+
// This is a JSX attribute, not a string literal - don't allow
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Check if the quote is actually part of a string literal
|
|
293
|
+
// Look for assignment patterns like const str = "..." or function calls like console.log("...")
|
|
294
|
+
const stringLiteralPattern = /(=\s*|\(\s*|,\s*|:\s*)\s*$/;
|
|
295
|
+
if (stringLiteralPattern.test(beforeQuote)) {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Check if it's styled-jsx syntax (should be allowed)
|
|
301
|
+
if (element.includes("<style jsx") || element.includes("<style jsx global")) {
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Allow <i> elements that are used for Modus icons
|
|
306
|
+
if (element.includes("<i") && element.includes("modus-icons")) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Allow <li> and <ul> elements when used inside ModusWcMenu components
|
|
311
|
+
// These are required for the web component's structure
|
|
312
|
+
if (element.includes("<li") || element.includes("<ul")) {
|
|
313
|
+
const beforeMatch = content.substring(0, matchIndex);
|
|
314
|
+
|
|
315
|
+
// Find the last opening tag for ModusWcMenu or modus-wc-menu before this element
|
|
316
|
+
const lastModusWcMenuOpen = beforeMatch.lastIndexOf("<ModusWcMenu");
|
|
317
|
+
const lastModusWcMenuOpen2 = beforeMatch.lastIndexOf("<modus-wc-menu");
|
|
318
|
+
const lastMenuOpen = Math.max(lastModusWcMenuOpen, lastModusWcMenuOpen2);
|
|
319
|
+
|
|
320
|
+
// If we found a menu opening tag, check if we're still inside it
|
|
321
|
+
if (lastMenuOpen !== -1) {
|
|
322
|
+
// Find the last closing tag for ModusWcMenu before this element
|
|
323
|
+
const lastModusWcMenuClose = beforeMatch.lastIndexOf("</ModusWcMenu>");
|
|
324
|
+
const lastModusWcMenuClose2 = beforeMatch.lastIndexOf("</modus-wc-menu>");
|
|
325
|
+
const lastMenuClose = Math.max(lastModusWcMenuClose, lastModusWcMenuClose2);
|
|
326
|
+
|
|
327
|
+
// If the last opening tag is after the last closing tag, we're inside a menu
|
|
328
|
+
if (lastMenuOpen > lastMenuClose) {
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Check if this looks like a real HTML element (has proper attributes or closing)
|
|
335
|
+
// Real HTML elements typically have spaces, attributes, or are self-closing
|
|
336
|
+
const hasAttributes = element.includes(" ") || element.includes("=");
|
|
337
|
+
const isSelfClosing = element.endsWith("/>");
|
|
338
|
+
const hasProperStructure = hasAttributes || isSelfClosing;
|
|
339
|
+
|
|
340
|
+
// If it doesn't have proper HTML structure and looks like code syntax, allow it
|
|
341
|
+
if (!hasProperStructure) {
|
|
342
|
+
// Check if it's followed by code syntax (>, =, etc.)
|
|
343
|
+
if (/^[>,=]/.test(contextAfter)) {
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function checkFile(filePath) {
|
|
352
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
353
|
+
const violations = [];
|
|
354
|
+
|
|
355
|
+
for (const pattern of SEMANTIC_HTML_PATTERNS) {
|
|
356
|
+
let match;
|
|
357
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
358
|
+
const line = content.substring(0, match.index).split("\n").length;
|
|
359
|
+
const column = match.index - content.lastIndexOf("\n", match.index - 1);
|
|
360
|
+
|
|
361
|
+
const element = match[0];
|
|
362
|
+
|
|
363
|
+
// Skip if it's an allowed semantic element
|
|
364
|
+
if (isAllowedSemanticElement(element, content, match.index)) {
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const suggestion = getTailwindSuggestion(element);
|
|
369
|
+
|
|
370
|
+
violations.push({
|
|
371
|
+
file: filePath,
|
|
372
|
+
line,
|
|
373
|
+
column,
|
|
374
|
+
match: match[0],
|
|
375
|
+
message: `Semantic HTML element detected: "${match[0]}". Use div with Tailwind classes instead.`,
|
|
376
|
+
suggestion: suggestion,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
pattern.lastIndex = 0;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return violations;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async function main() {
|
|
386
|
+
console.log(
|
|
387
|
+
"šØ Checking for semantic HTML elements that should use div + Tailwind classes in Vite + React app...\n"
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
let allViolations = [];
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
// Get all files to check
|
|
394
|
+
const files = await glob(FILE_PATTERNS, {
|
|
395
|
+
ignore: EXCLUDE_PATTERNS,
|
|
396
|
+
absolute: true,
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Check each file
|
|
400
|
+
for (const file of files) {
|
|
401
|
+
try {
|
|
402
|
+
const violations = await checkFile(file);
|
|
403
|
+
allViolations = allViolations.concat(violations);
|
|
404
|
+
} catch (error) {
|
|
405
|
+
console.warn(
|
|
406
|
+
`ā ļø Warning: Could not check file ${file}: ${error.message}`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Report results
|
|
412
|
+
if (allViolations.length === 0) {
|
|
413
|
+
console.log(
|
|
414
|
+
"ā
All files are using div elements with Tailwind classes correctly!"
|
|
415
|
+
);
|
|
416
|
+
console.log(
|
|
417
|
+
"š Note: Semantic HTML elements are avoided to prevent browser default style conflicts"
|
|
418
|
+
);
|
|
419
|
+
process.exit(0);
|
|
420
|
+
} else {
|
|
421
|
+
console.log(
|
|
422
|
+
`ā Found ${allViolations.length} semantic HTML violations:\n`
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// Group violations by file
|
|
426
|
+
const violationsByFile = allViolations.reduce((acc, violation) => {
|
|
427
|
+
if (!acc[violation.file]) {
|
|
428
|
+
acc[violation.file] = [];
|
|
429
|
+
}
|
|
430
|
+
acc[violation.file].push(violation);
|
|
431
|
+
return acc;
|
|
432
|
+
}, {});
|
|
433
|
+
|
|
434
|
+
// Print violations
|
|
435
|
+
for (const [file, violations] of Object.entries(violationsByFile)) {
|
|
436
|
+
const relativePath = path.relative(process.cwd(), file);
|
|
437
|
+
console.log(`š ${relativePath}:`);
|
|
438
|
+
|
|
439
|
+
for (const violation of violations) {
|
|
440
|
+
console.log(
|
|
441
|
+
` ${violation.line}:${violation.column} - ${violation.message}`
|
|
442
|
+
);
|
|
443
|
+
console.log(` š” Suggestion: ${violation.suggestion}`);
|
|
444
|
+
}
|
|
445
|
+
console.log();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
console.log("š” Tailwind Classes Reference:");
|
|
449
|
+
console.log(
|
|
450
|
+
" ā
Headings: text-4xl font-bold, text-3xl font-semibold, text-2xl font-semibold"
|
|
451
|
+
);
|
|
452
|
+
console.log(" ā
Sections: Use div with appropriate layout classes");
|
|
453
|
+
console.log(" ā
Text: text-base, text-sm, text-lg, text-xl");
|
|
454
|
+
console.log(
|
|
455
|
+
" ā
Typography: font-bold, font-semibold, italic, underline"
|
|
456
|
+
);
|
|
457
|
+
console.log(" ā
Layout: flex, grid, block, inline-block");
|
|
458
|
+
console.log(" ā
Spacing: p-4, m-2, px-4, py-2, gap-4");
|
|
459
|
+
console.log(
|
|
460
|
+
" ā
Colors: text-foreground, text-muted-foreground, bg-background"
|
|
461
|
+
);
|
|
462
|
+
console.log(
|
|
463
|
+
" š Note: Use div elements to avoid browser default styles and ensure consistent Tailwind behavior"
|
|
464
|
+
);
|
|
465
|
+
console.log(" š Documentation: https://tailwindcss.com/docs");
|
|
466
|
+
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
} catch (error) {
|
|
470
|
+
console.error("š„ Error running semantic HTML check:", error.message);
|
|
471
|
+
process.exit(1);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Run the script
|
|
476
|
+
main();
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TypeScript Type Checking Script for Vite + React
|
|
5
|
+
*
|
|
6
|
+
* This script runs TypeScript type checking with enhanced developer experience,
|
|
7
|
+
* providing clear success/failure messages and helpful error formatting.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { execSync } from "child_process";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
function formatTypeScriptError(errorOutput) {
|
|
14
|
+
const lines = errorOutput.split("\n");
|
|
15
|
+
const formattedErrors = [];
|
|
16
|
+
|
|
17
|
+
for (const line of lines) {
|
|
18
|
+
if (line.includes(".tsx") || line.includes(".ts")) {
|
|
19
|
+
// Extract file path and line info
|
|
20
|
+
const match = line.match(/([^(]+)\((\d+),(\d+)\): error TS(\d+): (.+)/);
|
|
21
|
+
if (match) {
|
|
22
|
+
const [, filePath, lineNum, colNum, errorCode, message] = match;
|
|
23
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
24
|
+
formattedErrors.push({
|
|
25
|
+
file: relativePath,
|
|
26
|
+
line: parseInt(lineNum),
|
|
27
|
+
column: parseInt(colNum),
|
|
28
|
+
code: errorCode,
|
|
29
|
+
message: message.trim(),
|
|
30
|
+
fullLine: line,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return formattedErrors;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function runTypeCheck() {
|
|
40
|
+
try {
|
|
41
|
+
console.log("š Running TypeScript type checking...\n");
|
|
42
|
+
|
|
43
|
+
// Run TypeScript compiler with noEmit
|
|
44
|
+
execSync("npx tsc --noEmit --pretty", {
|
|
45
|
+
encoding: "utf8",
|
|
46
|
+
stdio: "pipe",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// If we get here, no errors were found
|
|
50
|
+
console.log("ā
All TypeScript files are type-safe!");
|
|
51
|
+
console.log("šÆ No type errors found in the codebase.");
|
|
52
|
+
return { success: true, errors: [] };
|
|
53
|
+
} catch (error) {
|
|
54
|
+
// TypeScript found errors
|
|
55
|
+
const errorOutput = error.stdout || error.stderr || error.message;
|
|
56
|
+
const formattedErrors = formatTypeScriptError(errorOutput);
|
|
57
|
+
|
|
58
|
+
console.log(`ā Found ${formattedErrors.length} TypeScript errors:\n`);
|
|
59
|
+
|
|
60
|
+
// Group errors by file
|
|
61
|
+
const errorsByFile = formattedErrors.reduce((acc, error) => {
|
|
62
|
+
if (!acc[error.file]) {
|
|
63
|
+
acc[error.file] = [];
|
|
64
|
+
}
|
|
65
|
+
acc[error.file].push(error);
|
|
66
|
+
return acc;
|
|
67
|
+
}, {});
|
|
68
|
+
|
|
69
|
+
// Print errors grouped by file
|
|
70
|
+
for (const [file, errors] of Object.entries(errorsByFile)) {
|
|
71
|
+
console.log(`š ${file}:`);
|
|
72
|
+
|
|
73
|
+
for (const error of errors) {
|
|
74
|
+
console.log(
|
|
75
|
+
` ${error.line}:${error.column} - TS${error.code}: ${error.message}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
console.log();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Provide helpful suggestions
|
|
82
|
+
console.log("š” TypeScript Error Resolution Tips:");
|
|
83
|
+
console.log(" ⢠Check for missing type annotations");
|
|
84
|
+
console.log(" ⢠Verify import/export statements");
|
|
85
|
+
console.log(" ⢠Ensure proper interface definitions");
|
|
86
|
+
console.log(" ⢠Check for null/undefined handling");
|
|
87
|
+
console.log(" ⢠Verify component prop types");
|
|
88
|
+
console.log(" ⢠Run 'npm run type-check' to see full details");
|
|
89
|
+
|
|
90
|
+
return { success: false, errors: formattedErrors };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function main() {
|
|
95
|
+
console.log("š TypeScript Type Check for Vite + React App\n");
|
|
96
|
+
|
|
97
|
+
const result = runTypeCheck();
|
|
98
|
+
|
|
99
|
+
if (result.success) {
|
|
100
|
+
console.log("\nš Type checking completed successfully!");
|
|
101
|
+
process.exit(0);
|
|
102
|
+
} else {
|
|
103
|
+
console.log("\nš„ Type checking failed. Please fix the errors above.");
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Run the script
|
|
109
|
+
main();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#root {
|
|
2
|
+
max-width: 1280px;
|
|
3
|
+
margin: 0 auto;
|
|
4
|
+
padding: 2rem;
|
|
5
|
+
text-align: center;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.logo {
|
|
9
|
+
height: 6em;
|
|
10
|
+
padding: 1.5em;
|
|
11
|
+
will-change: filter;
|
|
12
|
+
transition: filter 300ms;
|
|
13
|
+
}
|
|
14
|
+
.logo:hover {
|
|
15
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
|
16
|
+
}
|
|
17
|
+
.logo.react:hover {
|
|
18
|
+
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@keyframes logo-spin {
|
|
22
|
+
from {
|
|
23
|
+
transform: rotate(0deg);
|
|
24
|
+
}
|
|
25
|
+
to {
|
|
26
|
+
transform: rotate(360deg);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
31
|
+
a:nth-of-type(2) .logo {
|
|
32
|
+
animation: logo-spin infinite 20s linear;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.card {
|
|
37
|
+
padding: 2em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.read-the-docs {
|
|
41
|
+
color: #888;
|
|
42
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
|
2
|
+
import ModusProvider from "./components/ModusProvider";
|
|
3
|
+
import { ThemeProvider } from "./contexts/ThemeContext";
|
|
4
|
+
import { DevPanelProvider, DevPanel, DevRoutes, isDevPanelEnabled } from "./dev";
|
|
5
|
+
|
|
6
|
+
// Your pages
|
|
7
|
+
import HomePage from "./pages/HomePage";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Main Application Component.
|
|
11
|
+
*
|
|
12
|
+
* Structure:
|
|
13
|
+
* - ThemeProvider: Manages Modus themes (6 themes available)
|
|
14
|
+
* - ModusProvider: Provides Modus Web Components CSS
|
|
15
|
+
* - DevPanelProvider: Manages Dev Panel state (development only)
|
|
16
|
+
* - Router: React Router for navigation
|
|
17
|
+
*
|
|
18
|
+
* Routes:
|
|
19
|
+
* - /dev/*: Development panel routes (demos, colors, icons) - dev only
|
|
20
|
+
* - /: Your application routes
|
|
21
|
+
*
|
|
22
|
+
* Getting Started:
|
|
23
|
+
* 1. Edit src/pages/HomePage.tsx for your landing page
|
|
24
|
+
* 2. Add new pages in src/pages/
|
|
25
|
+
* 3. Add routes below
|
|
26
|
+
* 4. Use Ctrl+Shift+D to open the Dev Panel for component reference
|
|
27
|
+
*/
|
|
28
|
+
function App() {
|
|
29
|
+
const showDevPanel = isDevPanelEnabled();
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<ThemeProvider>
|
|
33
|
+
<ModusProvider>
|
|
34
|
+
<DevPanelProvider>
|
|
35
|
+
<Router>
|
|
36
|
+
<Routes>
|
|
37
|
+
{/* Development routes - only available when VITE_DEV_PANEL=true */}
|
|
38
|
+
{showDevPanel && <Route path="/dev/*" element={<DevRoutes />} />}
|
|
39
|
+
|
|
40
|
+
{/* Your application routes - add more Route elements here */}
|
|
41
|
+
<Route path="/" element={<HomePage />} />
|
|
42
|
+
{/* Example: <Route path="/about" element={<AboutPage />} /> */}
|
|
43
|
+
</Routes>
|
|
44
|
+
|
|
45
|
+
{/* Dev Panel - floating panel for development reference */}
|
|
46
|
+
{showDevPanel && <DevPanel />}
|
|
47
|
+
</Router>
|
|
48
|
+
</DevPanelProvider>
|
|
49
|
+
</ModusProvider>
|
|
50
|
+
</ThemeProvider>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default App;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|