# Typed event target
A geometric Canvas target routes pointer, mouse, touch, wheel, keyboard, input, clipboard, and drag events.

## APIs demonstrated

- [useCursor](/reference/hooks/use-cursor/) from `@pibbl/core`
- [useEventListener](/reference/hooks/use-event-listener/) from `@pibbl/core`
- [useEventTarget](/reference/hooks/use-event-target/) from `@pibbl/core`
- [PibblClipboardEvent](/reference/types/events/) from `@pibbl/core`
- [PibblCompositionEvent](/reference/types/events/) from `@pibbl/core`
- [PibblDragEvent](/reference/types/events/) from `@pibbl/core`
- [PibblEvent](/reference/types/events/) from `@pibbl/core`
- [PibblEventCapturePropName](/reference/types/events/) from `@pibbl/core`
- [PibblEventHandler](/reference/types/events/) from `@pibbl/core`
- [PibblEventHandlers](/reference/types/events/) from `@pibbl/core`
- [PibblEventMap](/reference/types/events/) from `@pibbl/core`
- [PibblEventParticipationOptions](/reference/types/events/) from `@pibbl/core`
- [PibblEventPhase](/reference/types/events/) from `@pibbl/core`
- [PibblEventPropName](/reference/types/events/) from `@pibbl/core`
- [PibblEventTarget](/reference/types/events/) from `@pibbl/core`
- [PibblEventTargetOptions](/reference/types/events/) from `@pibbl/core`
- [PibblEventTargetSnapshot](/reference/types/events/) from `@pibbl/core`
- [PibblEventType](/reference/types/events/) from `@pibbl/core`
- [PibblFocusEvent](/reference/types/events/) from `@pibbl/core`
- [PibblInputEvent](/reference/types/events/) from `@pibbl/core`
- [PibblKeyboardEvent](/reference/types/events/) from `@pibbl/core`
- [PibblLogicalMouseEvent](/reference/types/events/) from `@pibbl/core`
- [PibblPointerEvent](/reference/types/events/) from `@pibbl/core`
- [PibblPointerEvents](/reference/types/events/) from `@pibbl/core`
- [PibblTouchEvent](/reference/types/events/) from `@pibbl/core`
- [PibblWheelEvent](/reference/types/events/) from `@pibbl/core`

## Complete example

[Plain source](/minimal/events/target.tsx). Run as a browser module after the document body exists. TSX uses `jsx: "react-jsx"` and `jsxImportSource: "@pibbl/core"`.

```tsx
import {
  Rectangle,
  Text,
  pibbl,
  useCursor,
  useEventListener,
  useEventTarget,
  useRectPath,
  type PibblClipboardEvent,
  type PibblCompositionEvent,
  type PibblDragEvent,
  type PibblEvent,
  type PibblEventCapturePropName,
  type PibblEventHandler,
  type PibblEventHandlers,
  type PibblEventMap,
  type PibblEventParticipationOptions,
  type PibblEventPhase,
  type PibblEventPropName,
  type PibblEventTarget,
  type PibblEventTargetOptions,
  type PibblEventTargetSnapshot,
  type PibblEventType,
  type PibblFocusEvent,
  type PibblInputEvent,
  type PibblKeyboardEvent,
  type PibblLogicalMouseEvent,
  type PibblPointerEvent,
  type PibblPointerEvents,
  type PibblTouchEvent,
  type PibblWheelEvent,
  type PixelGridAlignment,
} from '@pibbl/core';

const canvas = document.createElement('canvas');
canvas.width = 320;
canvas.height = 150;
const status = document.createElement('p');
status.setAttribute('role', 'status');
document.body.append(canvas, status);

function report(event: PibblEvent, detail: string) {
  const phase: PibblEventPhase = event.eventPhase;
  status.textContent = `${event.type} phase ${phase}: ${detail}`;
}

function capturePointer(target: PibblEventTarget, event: PibblPointerEvent) {
  target.setPointerCapture(event.pointerId);
  report(event, `pointer ${event.pointerId} at ${event.x.toFixed(0)}, ${event.y.toFixed(0)}`);
}

const eventType: PibblEventType = 'click';
const eventProp: PibblEventPropName = 'onClick';
const captureProp: PibblEventCapturePropName = 'onClickCapture';
const click: PibblEventHandler<typeof eventType> = (event: PibblLogicalMouseEvent) => {
  report(event, `button ${event.button}`);
};
const pointerType: keyof PibblEventMap = 'pointerdown';
const pointerDown: PibblEventHandler<typeof pointerType> = (event) => {
  capturePointer(event.currentTarget, event);
};
const pointerEvents: PibblPointerEvents = 'none';
const decoration: PibblEventParticipationOptions = { pointerEvents };

function Target() {
  const alignment: PixelGridAlignment = 'round';
  const path = useRectPath(24, 24, 272, 96, { alignToPixelGrid: alignment });
  const options: PibblEventTargetOptions = {
    path,
    fill: true,
    keyboardFocusable: true,
    cursor: 'pointer',
  };
  const handlers: PibblEventHandlers = {
    [eventProp]: click,
    [captureProp]: (event: PibblLogicalMouseEvent) => report(event, 'capture'),
    onPointerDown: pointerDown,
    onPointerUp: (event: PibblPointerEvent) => {
      if (event.currentTarget.hasPointerCapture(event.pointerId)) {
        event.currentTarget.releasePointerCapture(event.pointerId);
      }
    },
    onTouchStart: (event: PibblTouchEvent) => report(event, `touch ${event.x.toFixed(0)}`),
    onWheel: (event: PibblWheelEvent) => report(event, `wheel ${event.deltaY}`),
    onKeyDown: (event: PibblKeyboardEvent) => report(event, `key ${event.key}`),
    onFocus: (event: PibblFocusEvent) => report(event, 'focused'),
    onBeforeInput: (event: PibblInputEvent) => report(event, `input ${event.inputType}`),
    onCompositionUpdate: (event: PibblCompositionEvent) => report(event, `composition ${event.data}`),
    onPaste: (event: PibblClipboardEvent) => report(event, `paste ${event.clipboardData?.types.length ?? 0} formats`),
    onDrop: (event: PibblDragEvent) => report(event, `drop ${event.dataTransfer?.files.length ?? 0} files`),
  };
  const focus: PibblEventTargetSnapshot = useEventTarget(handlers, options);
  useCursor({ path, fill: true, style: 'pointer' });
  return <>
    <Rectangle {...decoration} style={{ left: 24, top: 24, width: 272, height: 96, fill: focus.isFocusVisible ? '#0f766e' : '#2563eb' }} />
    <Text {...decoration} style={{ left: 42, top: 58, font: '18px sans-serif', fill: '#fff' }}>Click or touch this target</Text>
  </>;
}

function Scene() {
  useEventListener({ onClick: (event: PibblLogicalMouseEvent) => report(event, 'heard by ancestor') });
  return <Target />;
}

const controller = pibbl(canvas, <Scene />);
window.addEventListener('pagehide', () => controller.dispose(), { once: true });

```

## Usage notes

- Canvas events remain logical Pibbl events; this example does not create native semantic DOM for the target.
- Clipboard, input, composition, and drag fields are typed callbacks; their native browser events require an appropriate focused host or interaction.

## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
