Skip to content
Merged
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
12 changes: 6 additions & 6 deletions .changeset/add-interactive-resize.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
"@spatialkit/core": minor
"@spatialkit/svg": minor
"@spatialkit/react": minor
"@spatial-kit/core": minor
"@spatial-kit/svg": minor
"@spatial-kit/react": minor
---

Add interactive entity resizing via drag handles.

- `@spatialkit/core` exports a new `ResizeDirection` type (`'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw'`), `hitTestResizeHandles` to detect which handle is under the cursor in screen space, and `applyResizeDelta` to compute new bounds from a world-space drag delta (with optional snap-to-grid on the edge position)
- `@spatialkit/svg` adds `paintResizeHandles` painter that draws 8 handles around each selected entity at a consistent pixel size regardless of zoom, and wires resize drag into `attachHandlers` with a priority-over-entity-drag rule
- `@spatialkit/react` adds a `ResizeHandles` internal component that renders the same 8 handles declaratively, and wires resize drag into `attachHandlers` with the same state machine (`idle → pending → resize → idle`)
- `@spatial-kit/core` exports a new `ResizeDirection` type (`'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw'`), `hitTestResizeHandles` to detect which handle is under the cursor in screen space, and `applyResizeDelta` to compute new bounds from a world-space drag delta (with optional snap-to-grid on the edge position)
- `@spatial-kit/svg` adds `paintResizeHandles` painter that draws 8 handles around each selected entity at a consistent pixel size regardless of zoom, and wires resize drag into `attachHandlers` with a priority-over-entity-drag rule
- `@spatial-kit/react` adds a `ResizeHandles` internal component that renders the same 8 handles declaratively, and wires resize drag into `attachHandlers` with the same state machine (`idle → pending → resize → idle`)
12 changes: 6 additions & 6 deletions .changeset/add-snap-to-grid.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
"@spatialkit/core": minor
"@spatialkit/svg": minor
"@spatialkit/react": minor
"@spatial-kit/core": minor
"@spatial-kit/svg": minor
"@spatial-kit/react": minor
---

Add snap-to-grid support for entity drag.

- `@spatialkit/core` exports a new `snapToGrid(value, gridSize)` utility that rounds a world-space coordinate to the nearest grid multiple
- `@spatialkit/svg` accepts a `snapToGrid?: number` option on `mountSvgRenderer`; when set, entity positions are snapped on every drag frame
- `@spatialkit/react` accepts a `snapToGrid?: number` prop on `SpatialCanvas` with the same behavior
- `@spatial-kit/core` exports a new `snapToGrid(value, gridSize)` utility that rounds a world-space coordinate to the nearest grid multiple
- `@spatial-kit/svg` accepts a `snapToGrid?: number` option on `mountSvgRenderer`; when set, entity positions are snapped on every drag frame
- `@spatial-kit/react` accepts a `snapToGrid?: number` prop on `SpatialCanvas` with the same behavior
2 changes: 1 addition & 1 deletion .changeset/support-react-19.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
'@spatialkit/react': minor
'@spatial-kit/react': minor
---

Support React 19. The `react` peer dependency now accepts `^18.0.0 || ^19.0.0`.
6 changes: 3 additions & 3 deletions .claude/skills/issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ You are a GitHub issue creator and editor for the **spatialkit/spatial** reposit

**Repo:** `spatialkit/spatial`
**Owner:** `spatialkit`
**Packages:** `@spatialkit/core` · `@spatialkit/svg` · `@spatialkit/react` · cross-cutting
**Packages:** `@spatial-kit/core` · `@spatial-kit/svg` · `@spatial-kit/react` · cross-cutting
**Milestones:**
| # | Title | Scope |
|---|-------|-------|
Expand Down Expand Up @@ -53,7 +53,7 @@ Questions to ask in round 1:
2. "What type of issue is this?" (header: "Type")
Options: Feature | Bug | Chore
3. "Which package does this affect?" (header: "Package")
Options: @spatialkit/core | @spatialkit/svg | @spatialkit/react | cross-cutting
Options: @spatial-kit/core | @spatial-kit/svg | @spatial-kit/react | cross-cutting
4. "Which milestone does this belong to?" (header: "Milestone")
Options: M1 — Functional editor | M2 — Undo/Redo & Persistence | M3 — Extend & Optimize | M4 — Ecosystem | None
```
Expand Down Expand Up @@ -165,5 +165,5 @@ These fields can't be set via the API — open the issue in the project board to

- Never skip the question rounds — always ask before writing the body.
- Never invent code or file paths not derivable from the project context.
- Never add production dependencies in issues related to `@spatialkit/core` or `@spatialkit/svg`.
- Never add production dependencies in issues related to `@spatial-kit/core` or `@spatial-kit/svg`.
- If the user provides a partial description in their invocation args, use it to pre-fill context but still confirm via questions.
6 changes: 3 additions & 3 deletions .claude/skills/spatial-expert.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ You are an expert on the **Spatial** codebase. Apply this context whenever worki

## What Spatial is

A zero-dependency TypeScript toolkit for building interactive 2D editors (floor plans, seat maps, office layouts). It provides scene management, pan/zoom/selection/picking primitives, and pluggable renderers. It is a monorepo with two publishable packages: `@spatialkit/core` and `@spatialkit/svg`.
A zero-dependency TypeScript toolkit for building interactive 2D editors (floor plans, seat maps, office layouts). It provides scene management, pan/zoom/selection/picking primitives, and pluggable renderers. It is a monorepo with two publishable packages: `@spatial-kit/core` and `@spatial-kit/svg`.

---

Expand All @@ -33,7 +33,7 @@ A zero-dependency TypeScript toolkit for building interactive 2D editors (floor

## Architecture rules to enforce

1. **No production deps** — `@spatialkit/core` and `@spatialkit/svg` must stay dependency-free.
1. **No production deps** — `@spatial-kit/core` and `@spatial-kit/svg` must stay dependency-free.
2. **Core is framework-agnostic** — no DOM, no React, no browser APIs in `packages/core/src/`.
3. **Branded types everywhere** — `EntityId` and `LayerId` are branded strings; never substitute with `string`.
4. **Immutable selection** — `applySelection` returns a new `Set`, never mutates the input.
Expand Down Expand Up @@ -106,5 +106,5 @@ Test environment: **Node** for core, **jsdom** for svg. Tests live in `src/__tes
- Forgetting `selectable: true` on entities → `hitTestPoint` returns null
- Using `string` instead of `EntityId` / `LayerId` → type errors downstream
- Mutating the `Set` from `applySelection` → breaks immutability contract
- Adding DOM code to `@spatialkit/core` → breaks the agnostic renderer model
- Adding DOM code to `@spatial-kit/core` → breaks the agnostic renderer model
- Not updating `index.ts` after adding exports → new symbols invisible to consumers
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ body:
label: Package
multiple: true
options:
- '@spatialkit/core'
- '@spatialkit/svg'
- '@spatialkit/react'
- '@spatial-kit/core'
- '@spatial-kit/svg'
- '@spatial-kit/react'
- Not sure
validations:
required: true
Expand Down
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ body:
label: Package
multiple: true
options:
- '@spatialkit/core'
- '@spatialkit/svg'
- '@spatialkit/react'
- '@spatial-kit/core'
- '@spatial-kit/svg'
- '@spatial-kit/react'
- New package
- Not sure
validations:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deploy-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ jobs:
<p>Interactive 2D editor toolkit — live examples</p>
<a href="vanilla/">
Vanilla JS
<span>@spatialkit/core + @spatialkit/svg</span>
<span>@spatial-kit/core + @spatial-kit/svg</span>
</a>
<a href="react/">
React
<span>@spatialkit/core + @spatialkit/react</span>
<span>@spatial-kit/core + @spatial-kit/react</span>
</a>
</body>
</html>
Expand Down
14 changes: 7 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ Spatial is a zero-dependency TypeScript toolkit for building interactive 2D edit

```
packages/
core/ @spatialkit/core — scene engine, viewport, selection, events, picking
svg/ @spatialkit/svg — SVG renderer + DOM event handlers
core/ @spatial-kit/core — scene engine, viewport, selection, events, picking
svg/ @spatial-kit/svg — SVG renderer + DOM event handlers
adapters/
react/ @spatialkit/react — React adapter (hooks + SpatialCanvas component)
react/ @spatial-kit/react — React adapter (hooks + SpatialCanvas component)
examples/
js-vanilla/ vanilla JS example
react/ React example
Expand Down Expand Up @@ -47,7 +47,7 @@ Run from repo root. Per-package commands work inside each `packages/*` directory

## Architecture

### @spatialkit/core
### @spatial-kit/core

| Module | Responsibility |
|--------|---------------|
Expand All @@ -71,7 +71,7 @@ Run from repo root. Per-package commands work inside each `packages/*` directory
- `zoomAt` delta is multiplicative: `0.1` = +10%, `−0.1` = −10%
- `panBy` takes screen-space delta; positive `x` shifts content left (pan moves right in world)

### @spatialkit/svg
### @spatial-kit/svg

| Module | Responsibility |
|--------|---------------|
Expand Down Expand Up @@ -142,8 +142,8 @@ Run from repo root. Per-package commands work inside each `packages/*` directory

## What NOT to do

- Do not add production dependencies to `@spatialkit/core` or `@spatialkit/svg`.
- Do not add production dependencies to `@spatial-kit/core` or `@spatial-kit/svg`.
- Do not bypass branded types with plain strings.
- Do not mutate `Set` objects returned by `applySelection`.
- Do not add framework-specific code to `@spatialkit/core` (keep it agnostic).
- Do not add framework-specific code to `@spatial-kit/core` (keep it agnostic).
- Do not skip typecheck — the build uses project references.
10 changes: 5 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ pnpm test

```
packages/
core/ @spatialkit/core — scene engine, viewport, selection, events, picking
svg/ @spatialkit/svg — SVG renderer + DOM event handlers
core/ @spatial-kit/core — scene engine, viewport, selection, events, picking
svg/ @spatial-kit/svg — SVG renderer + DOM event handlers
adapters/
react/ @spatialkit/react — React adapter (hooks + SpatialCanvas)
react/ @spatial-kit/react — React adapter (hooks + SpatialCanvas)
examples/
js-vanilla/ vanilla JS example (not published)
react/ React example (not published)
Expand All @@ -51,8 +51,8 @@ Each package README documents its public API.

## Code conventions

- **No production dependencies** in `@spatialkit/core`, `@spatialkit/svg` or `@spatialkit/react`. Peer dependencies on other `@spatialkit/*` packages and on React are the only exceptions.
- **`@spatialkit/core` stays framework-agnostic**: no DOM, no browser APIs.
- **No production dependencies** in `@spatial-kit/core`, `@spatial-kit/svg` or `@spatial-kit/react`. Peer dependencies on other `@spatial-kit/*` packages and on React are the only exceptions.
- **`@spatial-kit/core` stays framework-agnostic**: no DOM, no browser APIs.
- **TypeScript strict**: no `any`, no unused variables (prefix intentionally unused arguments with `_`).
- **Branded ids**: use `EntityId` and `LayerId`, never plain `string`.
- **Immutable selection**: never mutate the `Set` returned by `applySelection`.
Expand Down
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

<p align="center">
<a href="https://github.com/spatialkit/spatial/actions/workflows/ci.yml"><img src="https://github.com/spatialkit/spatial/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
<a href="https://www.npmjs.com/package/@spatialkit/core"><img src="https://img.shields.io/npm/v/@spatialkit/core?label=%40spatialkit%2Fcore" alt="npm @spatialkit/core" /></a>
<a href="https://www.npmjs.com/package/@spatial-kit/core"><img src="https://img.shields.io/npm/v/@spatial-kit/core?label=%40spatialkit%2Fcore" alt="npm @spatial-kit/core" /></a>
<a href="./LICENSE"><img src="https://img.shields.io/github/license/spatialkit/spatial" alt="MIT license" /></a>
</p>

Expand All @@ -28,9 +28,9 @@ Spatial provides the low-level engine for pan/zoom, selection, hit testing, and

| Package | Version | Description |
|---------|---------|-------------|
| [`@spatialkit/core`](packages/core) | [![npm](https://img.shields.io/npm/v/@spatialkit/core)](https://www.npmjs.com/package/@spatialkit/core) | Scene engine, viewport, event bus, picking, selection |
| [`@spatialkit/svg`](packages/svg) | [![npm](https://img.shields.io/npm/v/@spatialkit/svg)](https://www.npmjs.com/package/@spatialkit/svg) | SVG renderer + DOM event handlers |
| [`@spatialkit/react`](packages/adapters/react) | [![npm](https://img.shields.io/npm/v/@spatialkit/react)](https://www.npmjs.com/package/@spatialkit/react) | React adapter — hooks and `SpatialCanvas` component |
| [`@spatial-kit/core`](packages/core) | [![npm](https://img.shields.io/npm/v/@spatial-kit/core)](https://www.npmjs.com/package/@spatial-kit/core) | Scene engine, viewport, event bus, picking, selection |
| [`@spatial-kit/svg`](packages/svg) | [![npm](https://img.shields.io/npm/v/@spatial-kit/svg)](https://www.npmjs.com/package/@spatial-kit/svg) | SVG renderer + DOM event handlers |
| [`@spatial-kit/react`](packages/adapters/react) | [![npm](https://img.shields.io/npm/v/@spatial-kit/react)](https://www.npmjs.com/package/@spatial-kit/react) | React adapter — hooks and `SpatialCanvas` component |

---

Expand All @@ -39,13 +39,13 @@ Spatial provides the low-level engine for pan/zoom, selection, hit testing, and
**Vanilla JS / framework-agnostic:**

```bash
npm install @spatialkit/core @spatialkit/svg
npm install @spatial-kit/core @spatial-kit/svg
```

**React:**

```bash
npm install @spatialkit/core @spatialkit/react
npm install @spatial-kit/core @spatial-kit/react
```

All packages ship dual **ESM + CJS** builds with full TypeScript declarations.
Expand All @@ -56,14 +56,14 @@ All packages ship dual **ESM + CJS** builds with full TypeScript declarations.

```tsx
import { useCallback, useEffect } from 'react';
import { createEmptyScene, addEntity } from '@spatialkit/core';
import type { Entity, EntityId, LayerId } from '@spatialkit/core';
import { createEmptyScene, addEntity } from '@spatial-kit/core';
import type { Entity, EntityId, LayerId } from '@spatial-kit/core';
import {
SpatialCanvas,
useSpatialCore,
useSelection,
useViewport,
} from '@spatialkit/react';
} from '@spatial-kit/react';

const LAYER = 'main' as LayerId;

Expand Down Expand Up @@ -222,9 +222,9 @@ useCoreEvent(core, 'entities:changed', ({ type, ids }) => {
## Quick start — Vanilla JS

```ts
import { createCore, createEmptyScene } from '@spatialkit/core';
import { mountSvgRenderer } from '@spatialkit/svg';
import type { EntityId, LayerId } from '@spatialkit/core';
import { createCore, createEmptyScene } from '@spatial-kit/core';
import { mountSvgRenderer } from '@spatial-kit/svg';
import type { EntityId, LayerId } from '@spatial-kit/core';

// 1. Define layers (bottom → top z-order)
const LAYERS = {
Expand Down Expand Up @@ -304,7 +304,7 @@ renderer.destroy();
- `fitToBounds`, `fitToScene`, `centerOn` for programmatic camera control
- Precise coordinate transforms: `worldToScreen` / `screenToWorld`

**Interaction** (via `@spatialkit/svg` or `@spatialkit/react`)
**Interaction** (via `@spatial-kit/svg` or `@spatial-kit/react`)
- Mouse wheel zoom (configurable sensitivity)
- Pointer drag-to-pan
- Pinch-to-zoom on touch and pen devices
Expand All @@ -314,13 +314,13 @@ renderer.destroy();
- Drag handles to resize the selected entity
- Optional snap-to-grid for drag and resize

**Rendering** (via `@spatialkit/svg` or `@spatialkit/react`)
**Rendering** (via `@spatial-kit/svg` or `@spatial-kit/react`)
- Bring-your-own-drawEntity callback — full SVG freedom
- World-aligned background grid that stays crisp at any zoom
- Built-in selection highlight overlay with customisable style
- Automatic repaints on viewport, entity, and selection changes

**React adapter** (`@spatialkit/react`)
**React adapter** (`@spatial-kit/react`)
- `SpatialCanvas` component — drop in an SVG canvas with zero boilerplate
- `useSpatialCore` — lazy engine initialisation, stable across re-renders
- `useSelection` / `useViewport` — fine-grained reactive subscriptions via `useSyncExternalStore`
Expand All @@ -343,14 +343,14 @@ renderer.destroy();
└────────────────┬────────────────────────┘
│ SpatialCore API
┌───────────▼────────────┐
│ @spatialkit/core │
│ @spatial-kit/core │
│ scene · viewport │
│ events · picking │
│ selection · store │
└─────────┬──────────────┘
│ subscribes to events
┌─────────┴──────────────┬──────────────────────┐
│ @spatialkit/svg │ @spatialkit/react │
│ @spatial-kit/svg │ @spatial-kit/react │
│ DOM setup · renderer │ SpatialCanvas │
│ handlers · grid │ useSpatialCore │
│ selection overlay │ useSelection │
Expand All @@ -359,7 +359,7 @@ renderer.destroy();
└──────────────────────┘
```

`@spatialkit/core` is fully framework-agnostic — no DOM, no browser APIs. `@spatialkit/svg` and `@spatialkit/react` are independent renderer/adapter layers that connect core to the browser. Use whichever fits your stack.
`@spatial-kit/core` is fully framework-agnostic — no DOM, no browser APIs. `@spatial-kit/svg` and `@spatial-kit/react` are independent renderer/adapter layers that connect core to the browser. Use whichever fits your stack.

---

Expand Down
6 changes: 3 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Spatial is in `0.x`. Security fixes are released for the latest published minor

| Package | Supported |
|---------|-----------|
| `@spatialkit/core` | latest `0.x` minor |
| `@spatialkit/svg` | latest `0.x` minor |
| `@spatialkit/react` | latest `0.x` minor |
| `@spatial-kit/core` | latest `0.x` minor |
| `@spatial-kit/svg` | latest `0.x` minor |
| `@spatial-kit/react` | latest `0.x` minor |

## Reporting a vulnerability

Expand Down
6 changes: 3 additions & 3 deletions packages/adapters/react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# @spatialkit/react
# @spatial-kit/react

## 0.1.0

### Minor Changes

- Initial release of @spatialkit/core, @spatialkit/svg, and @spatialkit/react.
- Initial release of @spatial-kit/core, @spatial-kit/svg, and @spatial-kit/react.

### Patch Changes

- Updated dependencies
- @spatialkit/core@0.1.0
- @spatial-kit/core@0.1.0
Loading
Loading