# D2JS Animation Library

A versatile animation library for modern web applications with support for React, Vue, and Angular.

## Features

- **Simple Animations**: Rotate, bounce, and drag effects
- **Framework Support**: Works with React, Vue, and Angular
- **Typescript Ready**: Full TypeScript support with type definitions
- **Customizable**: Extensive options for each animation type
- **Lightweight**: No dependencies, minimal footprint

## Installation

```bash
npm install d2js
```

## Usage

### Core API (Framework-Agnostic)

```js
import { createAnimationController } from 'd2js';

// Get an element
const element = document.getElementById('my-element');

// Create animation controller
const controller = createAnimationController(element);

// Apply rotation animation
controller.rotate({
  degrees: 360,
  duration: 1000,
  easing: 'ease-in-out'
});

// Apply bounce animation
controller.bounce({
  intensity: 20,
  direction: 'up'
});

// Enable drag functionality
controller.enableDrag({
  axis: 'both',
  returnToOrigin: true
});
```

### React

```jsx
import React from 'react';
import { AnimatedDiv, useRotate, useBounce, useDrag } from 'd2js';

// Using the AnimatedDiv component
function MyComponent() {
  return (
    <AnimatedDiv
      rotateOptions={{ degrees: 360, trigger: 'click' }}
      bounceOptions={{ intensity: 20, trigger: 'hover' }}
      dragOptions={{ returnToOrigin: true }}
      style={{ width: 100, height: 100, background: 'blue' }}
    >
      Click me or hover over me!
    </AnimatedDiv>
  );
}

// Using hooks
function MyHookComponent() {
  const ref = React.useRef(null);
  const rotate = useRotate(ref);
  const bounce = useBounce(ref);
  const { enable: enableDrag, disable: disableDrag } = useDrag(ref);
  
  return (
    <div>
      <div
        ref={ref}
        style={{ width: 100, height: 100, background: 'red' }}
      >
        Animated element
      </div>
      <button onClick={() => rotate({ degrees: 360 })}>Rotate</button>
      <button onClick={() => bounce({ intensity: 20 })}>Bounce</button>
      <button onClick={() => enableDrag()}>Enable Drag</button>
      <button onClick={() => disableDrag()}>Disable Drag</button>
    </div>
  );
}
```

### Vue

```vue
<template>
  <!-- Using directive -->
  <div v-animate="{ 
    rotate: { degrees: 360, trigger: 'click' },
    bounce: { intensity: 20, trigger: 'hover' },
    drag: { returnToOrigin: true } 
  }">
    Click me or hover over me!
  </div>
  
  <!-- Using composable -->
  <div ref="elementRef">Animated with composable</div>
  <button @click="rotateElement">Rotate</button>
  <button @click="bounceElement">Bounce</button>
  <button @click="enableElementDrag">Enable Drag</button>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { useAnimations, D2jsPlugin } from 'd2js';

// Register plugin in your main.js: app.use(D2jsPlugin)

const elementRef = ref(null);
const { rotate, bounce, enableDrag } = useAnimations();
let disableDrag = null;

function rotateElement() {
  if (elementRef.value) {
    rotate(elementRef.value, { degrees: 360 });
  }
}

function bounceElement() {
  if (elementRef.value) {
    bounce(elementRef.value, { intensity: 20 });
  }
}

function enableElementDrag() {
  if (elementRef.value && !disableDrag) {
    disableDrag = enableDrag(elementRef.value, { returnToOrigin: true });
  }
}

// Clean up when component unmounts
onUnmounted(() => {
  if (disableDrag) {
    disableDrag();
  }
});
</script>
```

### Angular

```typescript
// In your module
import { NgModule } from '@angular/core';
import { D2jsModule } from 'd2js';

@NgModule({
  imports: [D2jsModule],
  // ...
})
export class AppModule {}

// In your component
import { Component, ElementRef, ViewChild } from '@angular/core';
import { D2jsService } from 'd2js';

@Component({
  selector: 'app-my-component',
  template: `
    <!-- Using directives -->
    <div 
      [d2jsRotate]="{degrees: 360}" 
      trigger="click">
      Click me to rotate
    </div>
    
    <div 
      [d2jsBounce]="{intensity: 20}" 
      trigger="hover">
      Hover me to bounce
    </div>
    
    <div 
      [d2jsDrag]="{returnToOrigin: true}">
      Drag me
    </div>
    
    <!-- Using service -->
    <div #animatedElement>Animated with service</div>
    <button (click)="rotateElement()">Rotate</button>
    <button (click)="bounceElement()">Bounce</button>
    <button (click)="enableElementDrag()">Enable Drag</button>
  `
})
export class MyComponent {
  @ViewChild('animatedElement') elementRef: ElementRef;
  private disableDrag: Function;
  
  constructor(private d2jsService: D2jsService) {}
  
  rotateElement() {
    this.d2jsService.rotate(
      this.elementRef.nativeElement, 
      { degrees: 360 }
    );
  }
  
  bounceElement() {
    this.d2jsService.bounce(
      this.elementRef.nativeElement, 
      { intensity: 20 }
    );
  }
  
  enableElementDrag() {
    if (!this.disableDrag) {
      this.disableDrag = this.d2jsService.enableDrag(
        this.elementRef.nativeElement,
        { returnToOrigin: true }
      );
    }
  }
  
  ngOnDestroy() {
    if (this.disableDrag) {
      this.disableDrag();
    }
  }
}
```

## Animation Options

### Rotate Options

```typescript
interface RotateOptions {
  degrees?: number;       // Rotation degrees (default: 360)
  duration?: number;      // Animation duration in ms (default: 1000)
  easing?: string;        // CSS easing function (default: 'ease-in-out')
  delay?: number;         // Delay before animation in ms (default: 0)
  iterations?: number;    // Number of iterations (default: 1)
  direction?: 'clockwise' | 'counterclockwise'; // Rotation direction (default: 'clockwise')
}
```

### Bounce Options

```typescript
interface BounceOptions {
  intensity?: number;     // Bounce intensity in pixels (default: 20)
  duration?: number;      // Animation duration in ms (default: 500)
  easing?: string;        // CSS easing function (default: cubic-bezier curve)
  delay?: number;         // Delay before animation in ms (default: 0)
  iterations?: number;    // Number of iterations (default: 1)
  direction?: 'up' | 'down' | 'left' | 'right'; // Bounce direction (default: 'up')
}
```

### Drag Options

```typescript
interface DragOptions {
  bounds?: {              // Constrains drag within these bounds
    top?: number;
    right?: number;
    bottom?: number;
    left?: number;
  };
  axis?: 'x' | 'y' | 'both'; // Drag axis constraint (default: 'both')
  returnToOrigin?: boolean;  // Return to original position on release (default: true)
}
```

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. 