Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"lint": "eslint",
"lint:fix": "eslint --fix",
"prerelease": "eslint && pnpm --filter './packages/*' typecheck && pnpm --filter './packages/*' build",
"release": "bumpp -r"
"release": "bumpp -r",
"build": "pnpm --filter './packages/*' build"
},
"devDependencies": {
"@schplitt/eslint-config": "catalog:",
Expand Down
3 changes: 3 additions & 0 deletions packages/angular/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Kept locally for experimental testing — not committed to the repo.
# Will be removed once ng-packagr is replaced with tsdown.
tsdown.config.ts
108 changes: 108 additions & 0 deletions packages/angular/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# @event-globe/angular

Angular component for the Event Globe 3D visualization library.

## Installation

```sh
npm install @event-globe/angular
```

## Usage

```ts
import { Component, viewChild } from '@angular/core'
import { EventGlobeComponent } from '@event-globe/angular'
import type { EventGlobeRendererConfig, ArcOptions } from '@event-globe/angular'

@Component({
selector: 'app-root',
standalone: true,
imports: [EventGlobeComponent],
template: `
<div class="globe-container">
<event-globe #globe [config]="config" (arcRemoved)="onArcRemoved($event)" />
<button (click)="addRandomArc()">Add Arc</button>
</div>
`,
styles: [`
.globe-container {
width: 100%;
height: 600px;
}
`],
})
export class AppComponent {
readonly globeRef = viewChild.required(EventGlobeComponent)

readonly config: EventGlobeRendererConfig = {
autoRotate: true,
autoRotateSpeed: 0.3,
globe: {
globeColor: '#3a228a',
showLandPolygons: true,
},
}

addRandomArc() {
this.globeRef().addArc({
startLat: (Math.random() * 180) - 90,
startLng: (Math.random() * 360) - 180,
endLat: (Math.random() * 180) - 90,
endLng: (Math.random() * 360) - 180,
color: '#DD63AF',
showEndRing: true,
})
}

onArcRemoved(event: { id: number, options: ArcOptions }) {
console.log('Arc removed:', event.id)
}
}
```

## API

### Inputs

- `config?: EventGlobeRendererConfig` - Configuration options for the globe

### Outputs

- `(arcRemoved)` - Emitted when an arc is removed. Payload: `{ id: number, options: ArcOptions }`

### Component Methods

Access these methods via a `viewChild` ref:

```ts
globeRef = viewChild.required(EventGlobeComponent)

// Access methods
this.globeRef().addArc({ /* ... */ })
this.globeRef().getActiveArcCount()
```

#### `addArc(options: ArcOptions): number`

Add an animated arc between two coordinates. Returns the arc ID.

#### `getActiveArcCount(): number`

Get the current number of active arcs.

#### `removeArcById(id: number): void`

Remove a specific arc by its ID.

#### `clearAllArcs(): void`

Remove all arcs from the globe.

## Full API Reference

For complete configurations and options, see the [@event-globe/core](../core/README.md) and [@event-globe/ts](../ts/README.md#configuration) packages.

## License

MIT
8 changes: 8 additions & 0 deletions packages/angular/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "./node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "src/index.ts"
},
"allowedNonPeerDependencies": ["@event-globe/ts"],
"dest": "dist"
}
58 changes: 58 additions & 0 deletions packages/angular/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@event-globe/angular",
"version": "1.0.1",
"type": "module",
"description": "Angular component for Three.js globe visualization with automatic resizing and controls",
"keywords": [
"globe",
"three",
"threejs",
"3d",
"visualization",
"angular"
],
"license": "MIT",
"author": "schplitt",
"homepage": "https://github.com/schplitt/event-globe/tree/main/packages/angular#readme",
"repository": {
"type": "git",
"url": "https://github.com/schplitt/event-globe.git",
"directory": "packages/angular"
},
"bugs": {
"url": "https://github.com/schplitt/event-globe/issues"
},
"sideEffects": false,
"exports": {
".": {
"types": "./dist/types/event-globe-angular.d.ts",
"default": "./dist/fesm2022/event-globe-angular.mjs"
}
},
"module": "./dist/fesm2022/event-globe-angular.mjs",
"typings": "./dist/types/event-globe-angular.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "ng-packagr -p ng-package.json",
"build:tsdown": "tsdown",
"dev": "ng-packagr -p ng-package.json --watch",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@event-globe/ts": "workspace:*"
},
"devDependencies": {
"@angular/compiler": "catalog:",
"@angular/compiler-cli": "catalog:",
"@angular/core": "catalog:",
"@types/three": "catalog:",
"ng-packagr": "catalog:",
"tslib": "catalog:",
"typescript": "catalog:"
},
"peerDependencies": {
"@angular/core": "^21.0.0"
}
}
69 changes: 69 additions & 0 deletions packages/angular/src/EventGlobe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type {
AfterViewInit,
ElementRef,
OnDestroy,
} from '@angular/core'
import {
ChangeDetectionStrategy,
Component,
effect,
input,
output,
viewChild,
} from '@angular/core'
import { EventGlobeRenderer } from '@event-globe/ts'
import type { ArcOptions, EventGlobeRendererConfig } from '@event-globe/ts'

@Component({
selector: 'event-globe',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<div #container style="width: 100%; height: 100%;"></div>`,
})
export class EventGlobeComponent implements AfterViewInit, OnDestroy {
readonly config = input<EventGlobeRendererConfig>()
readonly arcRemoved = output<{ id: number, options: ArcOptions }>()

private readonly containerRef = viewChild.required<ElementRef<HTMLDivElement>>('container')
private renderer: EventGlobeRenderer | null = null

constructor() {
effect(() => {
const cfg = this.config()
if (this.renderer && cfg) {
this.renderer.updateConfig(cfg)
}
})
}

ngAfterViewInit(): void {
this.renderer = new EventGlobeRenderer(
this.containerRef().nativeElement,
this.config(),
)
this.renderer.onArcRemoved((id, options) => {
this.arcRemoved.emit({ id, options })
})
}

ngOnDestroy(): void {
this.renderer?.destroy()
this.renderer = null
}

addArc(options: ArcOptions): number {
return this.renderer?.addArc(options) ?? -1
}

getActiveArcCount(): number {
return this.renderer?.getActiveArcCount() ?? 0
}

removeArcById(id: number): void {
this.renderer?.removeArcById(id)
}

clearAllArcs(): void {
this.renderer?.clearAllArcs()
}
}
2 changes: 2 additions & 0 deletions packages/angular/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { EventGlobeComponent } from './EventGlobe'
export type { ArcOptions, EventGlobeRendererConfig } from '@event-globe/ts'
30 changes: 30 additions & 0 deletions packages/angular/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"compilerOptions": {
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,

"strict": true,
"strictNullChecks": true,
"module": "esnext",
"moduleResolution": "bundler",

"resolveJsonModule": true,
"declaration": true,
"esModuleInterop": true,

"experimentalDecorators": true,
"lib": ["DOM", "ESNext"],
"target": "esnext",
"useDefineForClassFields": false,
"skipLibCheck": true
},
"angularCompilerOptions": {
"strictTemplates": true,
"strictInjectionParameters": true,
"strictStandalone": true,
"enableI18nLegacyMessageIdFormat": false,
"compilationMode": "partial"
}
}
19 changes: 19 additions & 0 deletions packages/angular/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// TODO: replace ng-packagr with tsdown once @oxc-angular/vite supports emitting
// Angular ivy declarations (ɵcmp) in .d.ts output for library builds.
// Tracked at: https://github.com/voidzero-dev/oxc-angular-compiler/issues/86
/* import { defineConfig } from 'tsdown'
import { angular } from '@oxc-angular/vite'

export default defineConfig({
entry: {
index: './src/index.ts',
},
target: ['es2024'],
format: 'esm',
clean: true,
dts: true,
platform: 'browser',
outDir: './dist',
plugins: [...angular({ tsconfig: './tsconfig.json' })],
})
*/
24 changes: 24 additions & 0 deletions playgrounds/angular/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>EventGlobe Angular Playground</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
width: 100vw;
height: 100vh;
overflow: hidden;
}
</style>
</head>
<body>
<app-root></app-root>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions playgrounds/angular/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "angular",
"version": "1.0.1",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"preview": "vite preview"
},
"dependencies": {
"@angular/common": "catalog:",
"@angular/core": "catalog:",
"@angular/platform-browser": "catalog:",
"@event-globe/angular": "workspace:*"
},
"devDependencies": {
"@oxc-angular/vite": "catalog:",
"@types/node": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
}
}
Loading
Loading