From c743a391ae9055db16447b7917949fa1057629cf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 22 Aug 2025 08:36:58 +0000
Subject: [PATCH 1/7] Initial plan
From 246a04ac304a0239d610150782112cdd669065d9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 22 Aug 2025 09:01:14 +0000
Subject: [PATCH 2/7] Add comprehensive GitHub Copilot instructions for
ng-in-viewport development
- Created .github/copilot-instructions.md with detailed guidance for coding agents
- Added exception to .gitignore to track the copilot-instructions.md file
- Instructions include repository setup, build processes, testing workflows, and troubleshooting
- All commands validated and tested with proper timeout recommendations
- Includes network workarounds for Cypress and Google Fonts in restricted environments
Co-authored-by: k3nsei <190422+k3nsei@users.noreply.github.com>
---
.github/copilot-instructions.md | 276 ++++++++++++++++++++++++++++++++
.gitignore | 1 +
2 files changed, 277 insertions(+)
create mode 100644 .github/copilot-instructions.md
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 00000000..0799232a
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,276 @@
+# GitHub Copilot Instructions for ng-in-viewport
+
+This file provides comprehensive guidance for GitHub Copilot coding agents working in the ng-in-viewport repository.
+
+## Repository Overview
+
+This is an Angular library that allows checking if an element is within the browser's visual viewport. The repository contains:
+
+- **Main library**: `projects/ng-in-viewport` - The core viewport detection library
+- **Demo application**: `projects/demo` - Documentation and examples site
+- **Example application**: `projects/example` - Interactive examples and playground
+- **E2E tests**: `projects/demo-e2e` and `projects/example-e2e` - End-to-end testing suites
+
+## Repository Setup
+
+### Node.js Requirements
+
+- **Required**: Node.js 18.x or >=20.10.0
+- **Required**: npm >=10.0.0
+- **Recommended**: Use Volta configuration (Node 20.11.1, npm 10.4.0)
+
+### Dependency Installation
+
+**ALWAYS** use the network workaround for Cypress in restricted environments:
+
+```bash
+CYPRESS_INSTALL_BINARY=0 npm ci
+```
+
+**Execution time**: ~15 seconds
+**Timeout recommendation**: Use 60+ seconds minimum, NEVER CANCEL
+
+This command installs all dependencies while skipping Cypress binary download that may be blocked by network restrictions.
+
+## Build Processes
+
+### Core Build Pipeline
+
+Run the complete build and validation pipeline:
+
+```bash
+npm run format && npm run lint && npm run build:lib && npm run test:lib
+```
+
+**Execution time**: ~45 seconds total
+**Timeout recommendation**: Use 120+ seconds minimum, NEVER CANCEL
+
+### Individual Build Commands
+
+#### Formatting and Linting
+
+```bash
+npm run format # Check code formatting (5 seconds)
+npm run format:write # Fix code formatting (5 seconds)
+npm run lint # Lint all projects (15 seconds)
+npm run lint:lib # Lint library only (8 seconds)
+npm run lint:demo # Lint demo app only (8 seconds)
+npm run lint:example # Lint example app only (8 seconds)
+```
+
+#### Library Build
+
+```bash
+npm run build:lib # Build ng-in-viewport library (20 seconds)
+```
+
+#### Application Builds
+
+```bash
+npm run build:demo # Build demo app for production (25 seconds)
+npm run build:example # Build example app for production (30 seconds)
+```
+
+**WARNING**: `npm run build:example` may fail with Google Fonts download issues in restricted environments. This is expected and does not indicate a problem with your code changes.
+
+#### Watch Mode Builds
+
+```bash
+npm run watch:lib # Watch and rebuild library
+npm run watch:demo # Watch and rebuild demo app
+npm run watch:example # Watch and rebuild example app
+```
+
+## Testing Workflows
+
+### Unit Testing
+
+```bash
+npm run test # Run all unit tests with coverage (25 seconds)
+npm run test:lib # Test library only (15 seconds)
+npm run test:demo # Test demo app only (10 seconds)
+npm run test:example # Test example app only (10 seconds)
+```
+
+**Timeout recommendation**: Use 90+ seconds minimum, NEVER CANCEL
+
+### E2E Testing
+
+```bash
+npm run e2e:run:demo # Run demo E2E tests headlessly (60+ seconds)
+npm run e2e:run:example # Run example E2E tests headlessly (60+ seconds)
+npm run e2e:open:demo # Open demo E2E tests interactively
+npm run e2e:open:example # Open example E2E tests interactively
+```
+
+**Timeout recommendation**: Use 180+ seconds minimum, NEVER CANCEL
+**Note**: E2E tests may fail in headless environments. Use manual validation instead.
+
+## Development Workflows
+
+### Serving Applications
+
+```bash
+npm run serve:demo # Serve demo app at http://localhost:4200
+npm run serve:example # Serve example app at http://localhost:4300
+```
+
+**Execution time**: ~10 seconds to start
+**Usage**: Keep running for development and manual testing
+
+### Library Development Workflow
+
+1. Make changes to library code in `projects/ng-in-viewport/src/`
+2. Build library: `npm run build:lib`
+3. Test changes: `npm run test:lib`
+4. Validate in demo app: `npm run serve:demo`
+5. Validate in example app: `npm run serve:example`
+
+### Code Quality Workflow
+
+1. Format code: `npm run format:write`
+2. Lint code: `npm run lint`
+3. Build library: `npm run build:lib`
+4. Run tests: `npm run test:lib`
+
+## Manual Validation Requirements
+
+After making changes to viewport detection functionality, ALWAYS perform manual validation:
+
+### Demo App Validation (http://localhost:4200)
+
+1. Run `npm run serve:demo`
+2. Navigate through the documentation sections
+3. Verify viewport detection examples work correctly
+4. Test responsive behavior at different screen sizes
+
+### Example App Validation (http://localhost:4300)
+
+1. Run `npm run serve:example`
+2. Scroll through the numbered elements (1-20)
+3. Verify that elements change appearance when entering/leaving viewport
+4. Test with different viewport threshold settings
+5. Verify callback functions are triggered correctly
+
+### Expected Behavior
+
+- Elements should visually indicate when they enter the viewport
+- Elements should update their state when leaving the viewport
+- Threshold settings should affect when detection triggers
+- Performance should remain smooth during scrolling
+
+## CI Pipeline Compatibility
+
+The repository uses GitHub Actions for CI/CD. Ensure your changes are compatible with:
+
+- **Formatting check**: `npm run format`
+- **Linting**: `npm run lint`
+- **Library build**: `npm run build:lib`
+- **Unit tests**: `npm run test:lib`
+- **E2E tests**: May be skipped in CI due to environment restrictions
+
+## Troubleshooting
+
+### Common Issues and Solutions
+
+#### Cypress Installation Fails
+
+**Error**: `download.cypress.io` blocked or timeout
+**Solution**: Use `CYPRESS_INSTALL_BINARY=0 npm ci` instead of `npm install`
+
+#### Google Fonts Download Fails
+
+**Error**: `fonts.googleapis.com` blocked during `npm run build:example`
+**Solution**: This is expected in restricted environments. The build failure does not indicate a problem with your code.
+
+#### Tests Time Out
+
+**Error**: Jest or npm commands time out
+**Solution**: Increase timeout to 120+ seconds minimum. NEVER CANCEL running tests.
+
+#### Port Already in Use
+
+**Error**: Port 4200 or 4300 already in use
+**Solution**: Kill existing processes or use different ports with `ng serve --port=XXXX`
+
+#### Build Artifacts Conflict
+
+**Error**: Unexpected build errors after changes
+**Solution**: Clear build cache and rebuild:
+
+```bash
+rm -rf dist/
+npm run build:lib
+```
+
+### Network Restrictions
+
+This repository is designed to work in restricted network environments:
+
+- Cypress binary installation is skipped
+- Google Fonts download failures are expected
+- All core functionality works without external network access
+
+### Memory Issues
+
+If you encounter memory issues during builds or tests:
+
+- Increase Node.js memory limit: `export NODE_OPTIONS="--max-old-space-size=4096"`
+- Run operations individually instead of chained commands
+
+## File Structure Guidelines
+
+### Library Code (`projects/ng-in-viewport/src/`)
+
+- **Core logic**: `lib/` directory
+- **Public API**: `public-api.ts`
+- **Tests**: `.spec.ts` files alongside source files
+
+### Demo App (`projects/demo/src/`)
+
+- **Components**: Demonstrate library usage
+- **Routing**: Navigate between examples
+- **Styles**: Visual presentation of examples
+
+### Example App (`projects/example/src/`)
+
+- **Interactive examples**: Real-world usage scenarios
+- **Configuration options**: Demonstrate different settings
+- **Performance testing**: Stress test viewport detection
+
+## Code Standards
+
+### TypeScript
+
+- Use strict TypeScript configuration
+- Provide explicit type annotations for public APIs
+- Follow Angular coding style guide
+
+### Testing
+
+- Write unit tests for all public API methods
+- Test edge cases and error conditions
+- Maintain high code coverage (>90%)
+
+### Documentation
+
+- Update README.md for API changes
+- Add JSDoc comments for public methods
+- Include usage examples for new features
+
+## Performance Considerations
+
+### Viewport Detection
+
+- Minimize DOM queries and measurements
+- Use efficient event listeners
+- Implement proper cleanup in component destruction
+- Consider using Intersection Observer API when available
+
+### Memory Management
+
+- Unsubscribe from observables in ngOnDestroy
+- Remove event listeners when components are destroyed
+- Avoid memory leaks in long-running applications
+
+This documentation ensures that any GitHub Copilot agent can work effectively in this codebase with clear, actionable guidance and no ambiguity about build processes or validation requirements.
diff --git a/.gitignore b/.gitignore
index 8144bb66..32e7ec47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,6 +47,7 @@ Thumbs.db
/.github/workflows/*
!/.github/dependabot.yml
!/.github/funding.yml
+!/.github/copilot-instructions.md
!/.github/actions/install-npm-deps/action.yml
!/.github/workflows/main.yml
!/.github/workflows/pr.yml
From 1773d5bb0c86dcdaa957fda96c1e02fbdb64bdf8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 22 Aug 2025 09:10:32 +0000
Subject: [PATCH 3/7] Enhance copilot instructions with Angular best practices
from official docs
Co-authored-by: k3nsei <190422+k3nsei@users.noreply.github.com>
---
.github/copilot-instructions.md | 107 ++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 0799232a..32dd2f83 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -273,4 +273,111 @@ If you encounter memory issues during builds or tests:
- Remove event listeners when components are destroyed
- Avoid memory leaks in long-running applications
+## Angular Development Guidelines
+
+### Persona and Context
+
+You are an Angular developer working on this viewport detection library. This project uses **Angular 17** with modern practices including standalone components, the inject() function, and Intersection Observer API for performance.
+
+### Angular Best Practices for This Project
+
+#### TypeScript Standards
+
+- Use strict type checking (already configured)
+- Prefer type inference when the type is obvious
+- Avoid the `any` type; use `unknown` when type is uncertain
+- Provide explicit type annotations for public APIs
+
+#### Component Guidelines
+
+- **Always use standalone components** - this library already follows this pattern
+- **DO NOT set `standalone: true`** in decorators (it's the default in modern Angular)
+- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
+- Keep components small and focused on single responsibility
+- Use `input()` and `output()` functions instead of `@Input()` and `@Output()` decorators when adding new features
+- Use `computed()` for derived state when working with signals
+- Use the `inject()` function instead of constructor injection (already implemented)
+
+#### Template Best Practices
+
+- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` for new code
+- DO NOT use `ngClass`, use `class` bindings instead
+- DO NOT use `ngStyle`, use `style` bindings instead
+- Keep templates simple and avoid complex logic
+- Use the async pipe to handle observables
+
+#### State Management
+
+- Use signals for local component state when adding new features
+- Use `computed()` for derived state
+- Keep state transformations pure and predictable
+- DO NOT use `mutate` on signals, use `update` or `set` instead
+
+#### Service and Directive Guidelines
+
+- Design services around single responsibility (InViewportService follows this)
+- Use `providedIn: 'root'` for singleton services
+- Put host bindings inside the `host` object of decorators instead of `@HostBinding`/`@HostListener`
+
+#### Library-Specific Considerations
+
+- **Intersection Observer API**: This library uses Intersection Observer for performance-critical viewport detection
+- **Platform checks**: Always use `isPlatformBrowser()` before DOM operations for SSR compatibility
+- **Memory management**: Implement proper cleanup in `ngOnDestroy` - unsubscribe from observables and remove event listeners
+- **Performance**: Minimize DOM queries and use efficient event handling patterns
+
+#### Code Examples for This Project
+
+Modern Angular component structure:
+
+```typescript
+import {
+ ChangeDetectionStrategy,
+ Component,
+ inject,
+ input,
+ output,
+} from '@angular/core';
+
+@Component({
+ selector: 'custom-element',
+ standalone: true,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ template: `
+ @if (isVisible()) {
+ Element is in viewport
+ } @else {
+ Element is not visible
+ }
+ `,
+})
+export class CustomComponent {
+ // Use signal inputs for new features
+ readonly threshold = input(0.5);
+
+ // Use output functions for new features
+ readonly visibilityChange = output();
+
+ // Use inject() function
+ private readonly elementRef = inject(ElementRef);
+}
+```
+
+#### Modernization Guidelines
+
+When updating existing code in this library:
+
+- **Gradual migration**: Don't break existing decorator-based inputs/outputs without good reason
+- **New features**: Use modern signal-based APIs for new components and directives
+- **Maintain compatibility**: Ensure changes don't break public API for library consumers
+- **Test thoroughly**: Viewport detection is performance-critical, validate with manual testing
+
+#### Angular Style Guide References
+
+- [Official Angular Style Guide](https://angular.dev/style-guide)
+- [Angular Essentials - Components](https://angular.dev/essentials/components)
+- [Angular Essentials - Signals](https://angular.dev/essentials/signals)
+- [Angular Essentials - Templates](https://angular.dev/essentials/templates)
+- [Angular Essentials - Dependency Injection](https://angular.dev/essentials/dependency-injection)
+
This documentation ensures that any GitHub Copilot agent can work effectively in this codebase with clear, actionable guidance and no ambiguity about build processes or validation requirements.
From 651f5e01379aa2900a6b30e935858fe9b6a65928 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 22 Aug 2025 09:19:03 +0000
Subject: [PATCH 4/7] Replace copilot instructions with Angular v20.2.1
standards and latest best practices
Co-authored-by: k3nsei <190422+k3nsei@users.noreply.github.com>
---
.github/copilot-instructions.md | 769 ++++++++++++++++++++------------
1 file changed, 485 insertions(+), 284 deletions(-)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 32dd2f83..f0163d80 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -1,383 +1,584 @@
# GitHub Copilot Instructions for ng-in-viewport
-This file provides comprehensive guidance for GitHub Copilot coding agents working in the ng-in-viewport repository.
+**Angular v20.2.1 Development Guidelines**
+*Ignore current project patterns - use only latest Angular v20+ standards and best practices*
-## Repository Overview
+## Project Overview
-This is an Angular library that allows checking if an element is within the browser's visual viewport. The repository contains:
+This is an Angular library for viewport detection using modern Angular v20.2.1 patterns. The repository contains:
-- **Main library**: `projects/ng-in-viewport` - The core viewport detection library
-- **Demo application**: `projects/demo` - Documentation and examples site
-- **Example application**: `projects/example` - Interactive examples and playground
-- **E2E tests**: `projects/demo-e2e` and `projects/example-e2e` - End-to-end testing suites
+- **Core library**: `projects/ng-in-viewport` - Signal-based viewport detection with Intersection Observer
+- **Demo application**: `projects/demo` - Documentation and interactive examples
+- **Example application**: `projects/example` - Real-world usage scenarios and performance testing
+- **Test suites**: Comprehensive unit and E2E testing with modern Angular testing patterns
-## Repository Setup
+## Environment Setup
### Node.js Requirements
-- **Required**: Node.js 18.x or >=20.10.0
+- **Required**: Node.js >=22.0.0 (LTS)
- **Required**: npm >=10.0.0
-- **Recommended**: Use Volta configuration (Node 20.11.1, npm 10.4.0)
+- **Package Manager**: Prefer `npm` with exact versions for consistency
### Dependency Installation
-**ALWAYS** use the network workaround for Cypress in restricted environments:
+For restricted environments, use network workarounds:
```bash
CYPRESS_INSTALL_BINARY=0 npm ci
```
**Execution time**: ~15 seconds
-**Timeout recommendation**: Use 60+ seconds minimum, NEVER CANCEL
+**Timeout**: Use 60+ seconds minimum, NEVER CANCEL
-This command installs all dependencies while skipping Cypress binary download that may be blocked by network restrictions.
+## Build Pipeline
-## Build Processes
-
-### Core Build Pipeline
-
-Run the complete build and validation pipeline:
+### Complete Build Validation
```bash
npm run format && npm run lint && npm run build:lib && npm run test:lib
```
-**Execution time**: ~45 seconds total
-**Timeout recommendation**: Use 120+ seconds minimum, NEVER CANCEL
+**Execution time**: ~45 seconds
+**Timeout**: Use 120+ seconds minimum, NEVER CANCEL
-### Individual Build Commands
-
-#### Formatting and Linting
+### Individual Commands
```bash
-npm run format # Check code formatting (5 seconds)
-npm run format:write # Fix code formatting (5 seconds)
-npm run lint # Lint all projects (15 seconds)
-npm run lint:lib # Lint library only (8 seconds)
-npm run lint:demo # Lint demo app only (8 seconds)
-npm run lint:example # Lint example app only (8 seconds)
+# Code Quality
+npm run format # Check formatting (5s)
+npm run format:write # Fix formatting (5s)
+npm run lint # Lint all projects (15s)
+
+# Library Build
+npm run build:lib # Production build (20s)
+npm run watch:lib # Development watch mode
+
+# Testing
+npm run test:lib # Unit tests with coverage (15s)
+npm run e2e:run # E2E tests headless (60s+)
+
+# Development Servers
+npm run serve:demo # Demo app - localhost:4200
+npm run serve:example # Example app - localhost:4300
```
-#### Library Build
+## Angular v20.2.1 Development Standards
-```bash
-npm run build:lib # Build ng-in-viewport library (20 seconds)
-```
+### Core Principles
-#### Application Builds
+**Signal-First Architecture**: Use signals as the primary state management pattern. Observables are reserved for streams and HTTP operations only.
-```bash
-npm run build:demo # Build demo app for production (25 seconds)
-npm run build:example # Build example app for production (30 seconds)
-```
+**Component Design**: All components MUST be standalone with OnPush change detection and signal-based APIs.
-**WARNING**: `npm run build:example` may fail with Google Fonts download issues in restricted environments. This is expected and does not indicate a problem with your code changes.
+**Template Syntax**: Exclusive use of modern control flow (`@if`, `@for`, `@switch`) and direct binding patterns.
-#### Watch Mode Builds
+### TypeScript Configuration
-```bash
-npm run watch:lib # Watch and rebuild library
-npm run watch:demo # Watch and rebuild demo app
-npm run watch:example # Watch and rebuild example app
+```typescript
+// Use strict TypeScript with latest features
+{
+ "compilerOptions": {
+ "strict": true,
+ "exactOptionalPropertyTypes": true,
+ "noUncheckedIndexedAccess": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true
+ }
+}
```
-## Testing Workflows
+**Type Standards**:
+- NEVER use `any` - use `unknown` for uncertain types
+- Use `satisfies` operator for type checking with inference
+- Prefer `readonly` for all data that shouldn't be mutated
+- Use template literal types for string constants
-### Unit Testing
+### Component Architecture
-```bash
-npm run test # Run all unit tests with coverage (25 seconds)
-npm run test:lib # Test library only (15 seconds)
-npm run test:demo # Test demo app only (10 seconds)
-npm run test:example # Test example app only (10 seconds)
-```
+```typescript
+import {
+ ChangeDetectionStrategy,
+ Component,
+ computed,
+ effect,
+ inject,
+ input,
+ output,
+ signal,
+} from '@angular/core';
-**Timeout recommendation**: Use 90+ seconds minimum, NEVER CANCEL
+@Component({
+ selector: 'viewport-element',
+ standalone: true,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ template: `
+ @if (isInViewport()) {
+
+ Content is visible ({{ visibilityRatio() }}%)
+
+ } @else {
+
Content is hidden
+ }
+ `,
+ host: {
+ '[attr.data-viewport-state]': 'viewportState()',
+ '[class.in-viewport]': 'isInViewport()',
+ },
+})
+export class ViewportElementComponent {
+ // Signal inputs - primary pattern for v20+
+ readonly threshold = input(0.5);
+ readonly rootMargin = input('0px');
+ readonly trackVisibility = input(true);
-### E2E Testing
+ // Signal outputs - modern event handling
+ readonly visibilityChange = output<{
+ isVisible: boolean;
+ entry: IntersectionObserverEntry;
+ }>();
-```bash
-npm run e2e:run:demo # Run demo E2E tests headlessly (60+ seconds)
-npm run e2e:run:example # Run example E2E tests headlessly (60+ seconds)
-npm run e2e:open:demo # Open demo E2E tests interactively
-npm run e2e:open:example # Open example E2E tests interactively
+ // Dependency injection with inject()
+ private readonly elementRef = inject(ElementRef);
+ private readonly viewportService = inject(ViewportService);
+
+ // Internal signals
+ protected readonly isInViewport = signal(false);
+ protected readonly visibilityRatio = signal(0);
+
+ // Computed values - derived state
+ protected readonly opacity = computed(() =>
+ this.visibilityRatio() * 0.8 + 0.2
+ );
+
+ protected readonly viewportState = computed(() =>
+ this.isInViewport() ? 'visible' : 'hidden'
+ );
+
+ constructor() {
+ // Effects for side effects and reactions
+ effect(() => {
+ if (this.trackVisibility()) {
+ this.setupViewportObserver();
+ }
+ });
+
+ effect(() => {
+ // Emit events when visibility changes
+ this.visibilityChange.emit({
+ isVisible: this.isInViewport(),
+ entry: this.lastEntry(), // Reference to latest entry
+ });
+ });
+ }
+
+ private setupViewportObserver() {
+ // Implementation with Intersection Observer
+ }
+}
```
-**Timeout recommendation**: Use 180+ seconds minimum, NEVER CANCEL
-**Note**: E2E tests may fail in headless environments. Use manual validation instead.
+### Service Design Patterns
-## Development Workflows
+```typescript
+import { Injectable, inject, signal, computed } from '@angular/core';
+import { DOCUMENT } from '@angular/common';
+
+@Injectable({ providedIn: 'root' })
+export class ViewportService {
+ private readonly document = inject(DOCUMENT);
+
+ // Signal-based state management
+ private readonly _elements = signal