diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..47a861b1 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,55 @@ +You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices. + +## TypeScript Best Practices + +- Use strict type checking +- Prefer type inference when the type is obvious +- Avoid the `any` type; use `unknown` when type is uncertain + +## Angular Best Practices + +- Always use standalone components over NgModules +- Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+. +- Use signals for state management +- Implement lazy loading for feature routes +- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead +- Use `NgOptimizedImage` for all static images. + - `NgOptimizedImage` does not work for inline base64 images. + +## Accessibility Requirements + +- It MUST pass all AXE checks. +- It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes. + +### Components + +- Keep components small and focused on a single responsibility +- Use `input()` and `output()` functions instead of decorators +- Use `computed()` for derived state +- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator +- Prefer inline templates for small components +- Prefer Reactive forms instead of Template-driven ones +- Do NOT use `ngClass`, use `class` bindings instead +- Do NOT use `ngStyle`, use `style` bindings instead +- When using external templates/styles, use paths relative to the component TS file. + +## State Management + +- Use signals for local component state +- Use `computed()` for derived state +- Keep state transformations pure and predictable +- Do NOT use `mutate` on signals, use `update` or `set` instead + +## Templates + +- Keep templates simple and avoid complex logic +- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` +- Use the async pipe to handle observables +- Do not assume globals like (`new Date()`) are available. +- Do not write arrow functions in templates (they are not supported). + +## Services + +- Design services around a single responsibility +- Use the `providedIn: 'root'` option for singleton services +- Use the `inject()` function instead of constructor injection diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e828f373..e2096a1d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,6 +10,7 @@ jobs: fetch-depth: 0 # Need all tags to get a version number in-between tags - uses: actions/setup-node@v4 with: + node-version: '24' cache: 'yarn' - run: yarn --frozen-lockfile - run: yarn build-demo @@ -25,6 +26,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: + node-version: '24' cache: 'yarn' - run: yarn --frozen-lockfile - run: ./node_modules/.bin/ng test natural --progress false --watch=false --browsers ChromeHeadlessCustom @@ -38,6 +40,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: + node-version: '24' cache: 'yarn' - run: yarn --frozen-lockfile - run: yarn lint @@ -48,6 +51,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: + node-version: '24' cache: 'yarn' - run: yarn --frozen-lockfile - run: ./node_modules/.bin/prettier --experimental-cli --check . @@ -75,9 +79,7 @@ jobs: id-token: write packages: write if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - needs: - - build - - test + needs: [build, test, lint, prettier] steps: - uses: actions/checkout@v4 with: @@ -91,24 +93,11 @@ jobs: # Publish to npm - uses: actions/setup-node@v4 with: + node-version: '24' registry-url: 'https://registry.npmjs.org' - - run: npm publish --provenance --access public dist/natural/ - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - run: npm publish --provenance --access public dist/natural-editor/ - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - # Publish to GitHub Packages - - uses: actions/setup-node@v4 - with: - registry-url: 'https://npm.pkg.github.com' - - run: npm publish --provenance --access public dist/natural/ - env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: npm publish --provenance --access public dist/natural-editor/ - env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - run: npm publish dist/natural/ + - run: npm publish dist/natural-editor/ # Create release - name: Get release info diff --git a/README.md b/README.md index 6a90ba09..5ed1bcac 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [](https://www.npmjs.com/package/@ecodev/natural) [](https://www.npmjs.com/package/@ecodev/natural) [](https://www.npmjs.com/package/@ecodev/natural) -[](https://gitter.im/Ecodev/natural) This project is a collection of Angular Material components and various utilities classes for Angular projects. diff --git a/angular.json b/angular.json index c6bc953b..542e5963 100644 --- a/angular.json +++ b/angular.json @@ -26,7 +26,21 @@ "polyfills": ["zone.js", "@angular/localize/init"], "tsConfig": "tsconfig.app.json", "assets": ["src/favicon.ico", "src/assets"], - "styles": ["src/styles.scss", "node_modules/@ecodev/natural-layout/natural-layout.css"], + "styles": [ + "src/styles.scss", + "src/styles/natural.scss", + "src/styles/epicerio.scss", + "src/styles/chez-emmy.scss", + "src/styles/epicentre.scss", + "src/styles/epicoop.scss", + "src/styles/jardinvivant.scss", + "src/styles/lacanopee.scss", + "src/styles/lavracrie.scss", + "src/styles/lelocalhauterive.scss", + "src/styles/levorace.scss", + "src/styles/rucher.scss", + "node_modules/@ecodev/natural-layout/natural-layout.css" + ], "scripts": [], "allowedCommonJsDependencies": ["graphql-tag", "zen-observable"], "extractLicenses": false, diff --git a/eslint.config.mjs b/eslint.config.mjs index abf00ca2..0e102a6b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -20,6 +20,7 @@ const basicAllowedAttributes = [ 'id', 'lang', 'list', + 'matButton', 'name', 'ngClass', 'ngProjectAs', @@ -30,6 +31,7 @@ const basicAllowedAttributes = [ 'stroke', 'stroke-width', 'style', + 'subscriptSizing', 'svgIcon', 'tabindex', 'target', diff --git a/package.json b/package.json index fc577eb6..b10b4209 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "demo", - "version": "0.0.0", + "version": "66.0.13", "license": "MIT", "scripts": { "ng": "ng", @@ -53,7 +53,7 @@ "prosemirror-view": "^1.41.0", "rxjs": "^7.8.2", "tslib": "^2.8.1", - "type-fest": "^4.41.0", + "type-fest": "^5.3.1", "zone.js": "~0.15.1" }, "devDependencies": { diff --git a/projects/natural-editor/package.json b/projects/natural-editor/package.json index 32ca5fff..4d5118ac 100644 --- a/projects/natural-editor/package.json +++ b/projects/natural-editor/package.json @@ -2,7 +2,10 @@ "name": "@ecodev/natural-editor", "version": "0.0.1", "license": "MIT", - "repository": "github:Ecodev/natural", + "repository": { + "type": "git", + "url": "git+https://github.com/Ecodev/natural.git" + }, "sideEffects": false, "exports": { ".": { diff --git a/projects/natural-editor/src/lib/editor/_editor.theme.scss b/projects/natural-editor/src/lib/editor/_editor.theme.scss deleted file mode 100644 index d60a38f8..00000000 --- a/projects/natural-editor/src/lib/editor/_editor.theme.scss +++ /dev/null @@ -1,59 +0,0 @@ -@use 'sass:map'; -@use '@angular/material' as mat; - -@mixin natural-editor($theme) { - $primary: map.get($theme, primary); - $accent: map.get($theme, accent); - $warn: map.get($theme, warn); - - $config: mat.m2-get-color-config($theme); - $background: map.get($config, background); - $foreground: map.get($config, foreground); - $is-dark-theme: map.get($config, is-dark); - - // Copied from Material Form Field - $fill-background: mat.m2-get-color-from-palette($foreground, base, if($is-dark-theme, 0.1, 0.04)); - $underline-color: mat.m2-get-color-from-palette($foreground, divider, if($is-dark-theme, 0.5, 0.42)); - $drawer-container-background-color: mat.m2-get-color-from-palette($background, background); - - natural-editor { - // Since MDC, icon buttons have round borders. We need square-ish border in the toolbar to not look too weird - .mat-mdc-icon-button, - .mat-mdc-icon-button .mat-mdc-button-persistent-ripple { - border-radius: 4px; - } - - // Since MDC, all buttons have fixed height. We need taller buttons to look similar to mat-button-toggle-group - button.mat-mdc-button.mat-mdc-button-base.mat-mdc-menu-trigger { - height: 50px; - } - - button.natural-file-over { - background: mat.m2-get-color-from-palette($primary); - } - - .menu-container { - background-color: $drawer-container-background-color; - } - - .menu, - .ProseMirror { - background-color: $fill-background; - } - - .menu { - border-color: $underline-color; - } - - placeholder { - background: linear-gradient( - 90deg, - mat.m2-get-color-from-palette($primary), - mat.m2-get-color-from-palette($primary), - mat.m2-get-color-from-palette($accent), - mat.m2-get-color-from-palette($primary), - mat.m2-get-color-from-palette($primary) - ); - } - } -} diff --git a/projects/natural-editor/src/lib/editor/editor.component.html b/projects/natural-editor/src/lib/editor/editor.component.html index 33188f22..da09d80f 100644 --- a/projects/natural-editor/src/lib/editor/editor.component.html +++ b/projects/natural-editor/src/lib/editor/editor.component.html @@ -3,7 +3,7 @@