Skip to content

feat: add GeoKitHooks — programmatic callbacks alongside every DOM CustomEvent - #46

Draft
shoesCodeFor with Copilot wants to merge 3 commits into
mainfrom
copilot/add-user-hooks-and-event-emitters
Draft

shoesCodeFor with Copilot wants to merge 3 commits into
mainfrom
copilot/add-user-hooks-and-event-emitters

Conversation

Copilot AI commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Good Vibes

  • I will be kind, constructive, and curious.

Summary

Users had no way to wire callbacks directly to geokit's internal events — the only option was DOM addEventListener. This adds a hooks property that accepts plain callback objects, called in lock-step with every CustomEvent dispatch.

Rationale

Framework consumers (React, Preact, Django widgets) often manage state through callback props rather than DOM listeners. The hooks object is read at call-time so it can be replaced at any point with no controller reinit, and it composes cleanly alongside the existing event system — both paths fire for every event.

The onIngest hook receives the same mutable detail object as the leaflet-draw:ingest DOM event, preserving the data-transformation contract.

Changes

  • src/types/events.ts — added DrawStartEventDetail, DrawStopEventDetail, EditStartEventDetail, EditStopEventDetail (previously named in DrawEvent constants but untyped)
  • src/types/public.ts — new GeoKitHooks interface; LeafletDrawMapElementAPI gains a hooks property
  • src/lib/MapController.tsMapControllerCallbacks extended with onDrawStart, onDrawStop, onEditStart, onEditStop; all four wired in bindDrawEvents() via L.Draw.Event.*
  • src/components/LeafletDrawMapElement.tshooks getter/setter (null/undefined normalised to {}); every callback and direct dispatch site now also calls the matching hook

Usage:

const map = document.querySelector('leaflet-geokit');

map.hooks = {
  onCreated: ({ id, geoJSON }) => store.add(id, geoJSON),
  onEdited:  ({ ids, geoJSON }) => store.sync(ids, geoJSON),
  onDeleted: ({ ids }) => store.remove(ids),
  // Transform data before it reaches the map (same as leaflet-draw:ingest listener)
  onIngest:  (detail) => { detail.fc = normalise(detail.fc); },
  onDrawStart: ({ layerType }) => ui.setActiveTool(layerType),
};

// Hooks can be swapped at any time — no reinit needed
map.hooks = { onReady: () => console.log('map ready') };

Screenshots / Recordings (if UI-visible)

No UI change — purely additive API surface.

Test Plan

  • Unit tests added/updated
  • Locally verified in the dev harness
  • Notes: tests/component-hooks.spec.ts — 21 tests covering getter/setter, all 11 hook callbacks, DOM event co-firing, mutable ingest, live hook replacement, and MapControllerCallbacks shape.

Coverage

  • Coverage is ≥ configured thresholds (see vitest.config.ts)

Breaking Changes

  • None

Docs

  • Public API typed and documented (README/ARCHITECTURE)
  • CONTRIBUTING unaffected or updated

Checklist

  • Lint passes (npm run lint)
  • Typecheck passes (npm run typecheck)
  • Unit tests pass (npm run test:unit)
  • No unrelated changes / drive‑by refactors

Related Issues / Links

  • Context: All 219 unit tests pass (4 pre-existing skips); 39 test files.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/leaflet-geokit/leaflet-geokit/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/leaflet-geokit/leaflet-geokit/node_modules/vitest/dist/workers/forks.js (dns block)
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/leaflet-geokit/leaflet-geokit/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/leaflet-geokit/leaflet-geokit/node_modules/vitest/dist/workers/forks.js Detail, EditStar--conditions node_modules/vitnode node_modules/vit--conditions node�� HEAD (dns block)
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/leaflet-geokit/leaflet-geokit/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/leaflet-geokit/leaflet-geokit/node_modules/vitest/dist/workers/forks.js --require node_modules/vit--verify node_modules/vitmain src/�� es/public.ts src/types/events.ts k/leaflet-geokit/node_modules/.bin/node tests/component-dirname l, DrawStopEvent.husky/_/post-checkout --ignore-REDACTED node (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title [WIP] Add support for user-defined hooks and event emitters in geokit feat: add GeoKitHooks — programmatic callbacks alongside every DOM CustomEvent Apr 4, 2026
Copilot AI requested a review from shoesCodeFor April 4, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants