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 @@
---
"@floormap-tools/core": minor
"@floormap-tools/svg": minor
"@floormap-tools/react": minor
"@spatialkit/core": minor
"@spatialkit/svg": minor
"@spatialkit/react": minor
---

Add interactive entity resizing via drag handles.

- `@floormap-tools/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)
- `@floormap-tools/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
- `@floormap-tools/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`)
- `@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`)
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 @@
---
"@floormap-tools/core": minor
"@floormap-tools/svg": minor
"@floormap-tools/react": minor
"@spatialkit/core": minor
"@spatialkit/svg": minor
"@spatialkit/react": minor
---

Add snap-to-grid support for entity drag.

- `@floormap-tools/core` exports a new `snapToGrid(value, gridSize)` utility that rounds a world-space coordinate to the nearest grid multiple
- `@floormap-tools/svg` accepts a `snapToGrid?: number` option on `mountSvgRenderer`; when set, entity positions are snapped on every drag frame
- `@floormap-tools/react` accepts a `snapToGrid?: number` prop on `FloormapCanvas` with the same behavior
- `@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
22 changes: 11 additions & 11 deletions .claude/skills/issue.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
name: issue
description: Interactive creator and editor of GitHub issues for the floormap-tools/floormap project. Asks structured questions to build a complete, consistent issue body matching the project's template.
description: Interactive creator and editor of GitHub issues for the spatialkit/spatial project. Asks structured questions to build a complete, consistent issue body matching the project's template.
---

You are a GitHub issue creator and editor for the **floormap-tools/floormap** repository. Your job is to collect structured information and produce a well-formatted issue that matches the project's template.
You are a GitHub issue creator and editor for the **spatialkit/spatial** repository. Your job is to collect structured information and produce a well-formatted issue that matches the project's template.

---

## Project reference

**Repo:** `floormap-tools/floormap`
**Owner:** `floormap-tools`
**Packages:** `@floormap-tools/core` · `@floormap-tools/svg` · `@floormap-tools/react` · cross-cutting
**Repo:** `spatialkit/spatial`
**Owner:** `spatialkit`
**Packages:** `@spatialkit/core` · `@spatialkit/svg` · `@spatialkit/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: @floormap-tools/core | @floormap-tools/svg | @floormap-tools/react | cross-cutting
Options: @spatialkit/core | @spatialkit/svg | @spatialkit/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 @@ -124,8 +124,8 @@ Use the answers to generate a complete body in this template:
**Create:**
```
mcp__github__create_issue(
owner: "floormap-tools",
repo: "floormap",
owner: "spatialkit",
repo: "spatial",
title: <title from answers>,
body: <generated body>,
labels: [<label matching type>],
Expand All @@ -136,8 +136,8 @@ mcp__github__create_issue(
**Edit:**
```
mcp__github__update_issue(
owner: "floormap-tools",
repo: "floormap",
owner: "spatialkit",
repo: "spatial",
issue_number: <number>,
title: <updated title if changed>,
body: <new body>
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 `@floormap-tools/core` or `@floormap-tools/svg`.
- Never add production dependencies in issues related to `@spatialkit/core` or `@spatialkit/svg`.
- If the user provides a partial description in their invocation args, use it to pre-fill context but still confirm via questions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
name: floormap-expert
description: Expert skill for the Floormap project. Activates deep context about architecture, conventions, module responsibilities, and development workflow. Use when working on any code in this repository.
name: spatial-expert
description: Expert skill for the Spatial project. Activates deep context about architecture, conventions, module responsibilities, and development workflow. Use when working on any code in this repository.
---

You are an expert on the **Floormap** codebase. Apply this context whenever working on any code in this repository.
You are an expert on the **Spatial** codebase. Apply this context whenever working on any code in this repository.

---

## What Floormap is
## 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: `@floormap-tools/core` and `@floormap-tools/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: `@spatialkit/core` and `@spatialkit/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** — `@floormap-tools/core` and `@floormap-tools/svg` must stay dependency-free.
1. **No production deps** — `@spatialkit/core` and `@spatialkit/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 All @@ -55,7 +55,7 @@ Both are in `viewport.ts`. Use them — don't reimplement.
```
matrix(zoom 0 0 zoom -pan.x*zoom -pan.y*zoom)
```
Applied on `<g data-fm="viewport">`. Changing this breaks all rendering.
Applied on `<g data-spatial="viewport">`. Changing this breaks all rendering.

### Core events
```
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 `@floormap-tools/core` → breaks the agnostic renderer model
- Adding DOM code to `@spatialkit/core` → breaks the agnostic renderer model
- Not updating `index.ts` after adding exports → new symbols invisible to consumers
8 changes: 4 additions & 4 deletions .github/workflows/deploy-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Floormap — Examples</title>
<title>Spatial — Examples</title>
<style>
body { font-family: sans-serif; max-width: 480px; margin: 80px auto; padding: 0 24px; }
h1 { font-size: 1.5rem; margin-bottom: 8px; }
Expand All @@ -51,15 +51,15 @@ jobs:
</style>
</head>
<body>
<h1>Floormap</h1>
<h1>Spatial</h1>
<p>Interactive 2D editor toolkit — live examples</p>
<a href="vanilla/">
Vanilla JS
<span>@floormap-tools/core + @floormap-tools/svg</span>
<span>@spatialkit/core + @spatialkit/svg</span>
</a>
<a href="react/">
React
<span>@floormap-tools/core + @floormap-tools/react</span>
<span>@spatialkit/core + @spatialkit/react</span>
</a>
</body>
</html>
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
node-version: 22
cache: pnpm
registry-url: https://npm.pkg.github.com
scope: '@floormap-tools'
scope: '@spatialkit'

- run: pnpm install --frozen-lockfile

Expand Down
2 changes: 1 addition & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
@floormap-tools:registry=https://npm.pkg.github.com
@spatialkit:registry=https://npm.pkg.github.com
34 changes: 17 additions & 17 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Floormap — Claude Code Guide
# Spatial — Claude Code Guide

## Project overview

Floormap is a zero-dependency TypeScript toolkit for building interactive 2D editors (floor plans, seat maps, office layouts, warehouse maps). It exposes low-level primitives for pan/zoom/selection/picking and ships pluggable renderers.
Spatial is a zero-dependency TypeScript toolkit for building interactive 2D editors (floor plans, seat maps, office layouts, warehouse maps). It exposes low-level primitives for pan/zoom/selection/picking and ships pluggable renderers.

**Repo:** `github.com/floormap-tools/floormap`
**Repo:** `github.com/spatialkit/spatial`
**Status:** v0.0.0 — core stable, SVG renderer complete, React adapter in progress

> Detailed per-package guides: [`packages/core/CLAUDE.md`](packages/core/CLAUDE.md) · [`packages/svg/CLAUDE.md`](packages/svg/CLAUDE.md)
Expand All @@ -15,10 +15,10 @@ Floormap is a zero-dependency TypeScript toolkit for building interactive 2D edi

```
packages/
core/ @floormap-tools/core — scene engine, viewport, selection, events, picking
svg/ @floormap-tools/svg — SVG renderer + DOM event handlers
core/ @spatialkit/core — scene engine, viewport, selection, events, picking
svg/ @spatialkit/svg — SVG renderer + DOM event handlers
adapters/
react/ @floormap-tools/react — React adapter (hooks + FloormapCanvas component)
react/ @spatialkit/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

### @floormap-tools/core
### @spatialkit/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)

### @floormap-tools/svg
### @spatialkit/svg

| Module | Responsibility |
|--------|---------------|
Expand All @@ -84,13 +84,13 @@ Run from repo root. Per-package commands work inside each `packages/*` directory
**SVG group hierarchy:**
```
<svg>
<g data-fm="viewport"> ← transform matrix applied here
<g data-fm="grid">
<g data-fm="objects">
<g data-fm-layer="..."> ← one per layer, in scene.layers order
<g data-fm="selection">
<g data-fm="overlays">
<defs data-fm="defs"> ← only if defs callback is provided
<g data-spatial="viewport"> ← transform matrix applied here
<g data-spatial="grid">
<g data-spatial="objects">
<g data-spatial-layer="..."> ← one per layer, in scene.layers order
<g data-spatial="selection">
<g data-spatial="overlays">
<defs data-spatial="defs"> ← only if defs callback is provided
```

**Transform matrix:** `matrix(zoom 0 0 zoom -pan.x*zoom -pan.y*zoom)`
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 `@floormap-tools/core` or `@floormap-tools/svg`.
- Do not add production dependencies to `@spatialkit/core` or `@spatialkit/svg`.
- Do not bypass branded types with plain strings.
- Do not mutate `Set` objects returned by `applySelection`.
- Do not add framework-specific code to `@floormap-tools/core` (keep it agnostic).
- Do not add framework-specific code to `@spatialkit/core` (keep it agnostic).
- Do not skip typecheck — the build uses project references.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 Floor Map
Copyright (c) 2025 spatialkit

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading
Loading