npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@magnaboy/layout-core

v0.0.1

Published

Shared canvas geometry, gestures, snapping and React interaction controls.

Downloads

131

Readme

@magnaboy/layout-core

Shared canvas mechanics extracted from the cx-toolkit and cx-live layout editors.

The root export is pure TypeScript. The optional /react export supplies pointer handlers, keyboard shortcuts, fit measurement, selection controls, snap guides and an error boundary.

Install

pnpm add @magnaboy/layout-core

Install React 19+ to use /react. Its components import CSS modules; use a bundler that supports *.module.css (such as Vite). The root export does not import React or CSS.

Geometry

import { resizeRotatedSourceGesture, snapMoveDelta } from '@magnaboy/layout-core';

const resized = resizeRotatedSourceGesture(transform, 'bottom-right', dx, dy, true);
const snapped = snapMoveDelta(rect, { width: 1920, height: 1080 }, 8 / screenScale, otherRects);

| Exports | Purpose | | --- | --- | | outerScale, screenToCanvasScale, screenDeltaToCanvas, screenPointToCanvas | Convert screen coordinates using fit scale, zoom and pan | | resizeGesture, resizeSourceGesture, resizeRotatedSourceGesture | Resize with minimum dimensions, crop scaling and rotation anchors | | cropGesture, rotateGesture, rotateDeltaToLocal, visibleRect | Crop, rotation and visible bounds | | isCornerHandle, isAxisAligned, MIN_SOURCE_SIZE, NUDGE_DELTAS | Shared gesture rules | | snapTargetRects, snapMoveDelta, snapResizeDelta | Edge/center snapping and guide positions |

Coordinates and dimensions are canvas pixels; rotations are degrees. A viewport must have positive dimensions and zoom. Pass the rendered viewport rectangle, not the surrounding editor rectangle. Snapping thresholds are canvas pixels; divide a screen-pixel threshold by screenToCanvasScale. Rotated sources are excluded by snapTargetRects; callers also skip move/resize snapping for a rotated source. Corner resizing preserves aspect ratio when requested. The minimum source size is 10 canvas pixels.

React adapter

The host owns its source renderers, document, reducer and history. It supplies a structural CanvasController:

import type { CanvasController } from '@magnaboy/layout-core/react';

const canvas: CanvasController = {
	dispatch,
	containerRef,
	stateRef
};

stateRef.current supplies sources, selectedSourceIds and container. Each source needs only id, transform, locked and visible. The viewport needs width, height, zoom, panX and panY. Product fields can remain on these objects. Keep the ref current after each host state change. containerRef points to the rendered viewport.

The dispatch function handles CanvasAction: selectSource, removeSources, multiTransform, rotate, crop, setZoom, setPan, beginInteraction, endInteraction, undo and redo. Group updates between beginInteraction and endInteraction into one history entry.

import { SourceControls, useSourceDrag } from '@magnaboy/layout-core/react';

const drag = useSourceDrag({ source, isSelected, manager: canvas, onSnapGuides });

<div {...drag} style={hostSourcePlacement}>
	{hostSourceRenderer}
	{isSelected && !source.locked && <SourceControls source={source} manager={canvas} onSnapGuides={onSnapGuides} />}
</div>;

The host source element provides positioning and rotation. The shared controls use its local coordinate space. useSourceDrag handles locked sources; render resize controls only for unlocked sources. Route useCanvasShortcuts to the focused canvas, excluding text inputs. Attach usePanZoom handlers only to empty canvas areas or middle-button panning. Consume its suppressed click after a pan so dragging does not deselect sources.

useFitScale observes the supplied root and returns a contain scale. Use scale 1 when fit is disabled. useSnapGuides avoids redundant guide updates; SnapGuides draws them at constant screen thickness. SourceBoundary renders nothing after a child fails and retries when resetKey changes.

Boundary

The package contains no Kick integration, network calls, source renderer registry, panels, fonts, background presets, source properties, document serializer, renderer composition format or reducer. The applications retain those parts and their existing file formats. It uses @magnaboy/ts-core for numeric clamping and has no randomness.

Consumer migration after publication

Both existing editors can pass their LayoutManagerApi directly as CanvasController. Keep local import paths as re-exports while migrating:

| Existing canvas module | Shared export | | --- | --- | | coords.ts, gestures.ts, snapping.ts | Named exports from @magnaboy/layout-core | | SourceControls.tsx, SourceBoundary.tsx, SnapGuides.tsx | Named exports from @magnaboy/layout-core/react | | useSourceDrag.ts, usePanZoom.ts, useCanvasShortcuts.ts, useFitScale.ts | Named exports from @magnaboy/layout-core/react |

The shared components carry their own handle and guide CSS. Other canvas styling stays local. The copied geometry tests and React interaction tests protect the existing behavior.

Development

From the repository root:

pnpm --filter @magnaboy/layout-core build
pnpm --filter @magnaboy/layout-core test:types
pnpm --filter @magnaboy/layout-core test:unit
pnpm --filter @magnaboy/layout-core check:publish