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

@oh-just-another/react-ui

v0.64.8

Published

React components and hooks over the diagram editor — DiagramCanvas, Toolbar, Palette, PropertyPanel.

Readme

@oh-just-another/react-ui

npm version

React 18+ wrappers around the editor — DiagramCanvas, Toolbar, Palette, PropertyPanel, plus a small set of hooks. Mount it with three lines of JSX, customize with hooks for everything else.

The React binding layer (L5) over @oh-just-another/state; needs React + DOM. For a single drop-in component, use @oh-just-another/editor.

Install

pnpm add @oh-just-another/react-ui react react-dom

react and react-dom are peer dependencies (any version ≥ 18 works).

Quick start

import { emptyScene } from "@oh-just-another/scene";
import { DiagramCanvas, Toolbar, Palette, PropertyPanel } from "@oh-just-another/react-ui";
import { installBuiltinTemplates, loadTemplateLibrary } from "@oh-just-another/templates";

installBuiltinTemplates();

export const App = () => (
  <DiagramCanvas initialScene={emptyScene()} initialTool="select">
    <Toolbar />
    <Palette />
    <PropertyPanel />
  </DiagramCanvas>
);

DiagramCanvas constructs the underlying Editor and supplies it to every descendant via context. Toolbar / Palette / PropertyPanel are independent — drop them anywhere in the subtree, layered with normal CSS.

Components

Every component reads the editor from context, so most take no required props.

Mounting & layout

| Name | Purpose | | -------------------------------- | ---------------------------------------------------------------- | | DiagramCanvas | Mounts a host element, instantiates Editor, provides context. | | DiagramRoot / DiagramSurface | Lower-level split of the canvas: provider root + render surface. | | DiagramProvider | Standalone provider for hosts that build their own editor. | | UILayer | Positioned overlay layer for placing chrome over the canvas. | | TopBar / BottomBar | Edge-anchored bars for toolbars and status chrome. | | Sidebar | Collapsible side container for panels. | | BottomSheet | Sliding bottom container (touch / mobile layouts). | | Minimap | Overview canvas with a viewport frame; click / drag to pan. |

Toolbar & zoom

| Name | Purpose | | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | Toolbar / DEFAULT_TOOLBAR / DEFAULT_VERTICAL_TOOLBAR | Declarative tool/action bar. Items: mode, action, divider, undo, redo. | | openImageFilePicker | Opens the OS file picker and inserts the chosen image. | | ZoomWidget / FloatingZoomControls | Composite zoom controls. | | ZoomInButton / ZoomOutButton / ResetZoomButton / ZoomToFitButton / ZoomDisplay | Individual zoom controls. | | ResetToContentButton | Recenters the viewport on scene content. |

Palettes & shape catalog

| Name | Purpose | | ------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | Palette | Drag-and-drop catalog of templates. | | LibraryPanel | Browsable template library panel. | | ColorSwatchPicker | Color swatch grid picker. | | ELEMENT_PALETTE_LIGHT / ELEMENT_PALETTE_DARK / CANVAS_PALETTE_LIGHT / CANVAS_PALETTE_DARK | Built-in color palettes. | | resolvePaletteTheme | Picks the light/dark palette for the active theme. |

Inspectors & property panels

| Name | Purpose | | ------------------------ | -------------------------------------------- | | PropertyPanel | Inspector for the current selection. | | LinkStylePanel | Edge/link styling controls. | | LayerPanel | Layer list with visibility / ordering. | | FramePanel | Frame list and controls. | | SelectionFloatingPanel | Floating controls anchored to the selection. |

Menus, dialogs & overlays

| Name | Purpose | | -------------------------------------- | -------------------------------------------------- | | MainMenu | Top-level application menu with submenus. | | ContextMenu / DEFAULT_CONTEXT_MENU | Right-click menu over the canvas. | | CommandPalette | Searchable command launcher. | | Modal / Popover | Generic modal dialog and anchored popover. | | Tooltip / TooltipProvider | Hover tooltips (wrap the subtree in the provider). | | HelpButton / HelpDialog | Keyboard-shortcut / help dialog and its trigger. | | ToastHost | Renders transient toasts; pair with useToast. |

Collaboration & versioning

| Name | Purpose | | ----------------------------------- | ----------------------------------------- | | CommentsPanel / CommentsPopover | Thread list and anchored comment popover. | | VersionPanel | Snapshot history browser. | | MergeDialog | Resolve conflicts when merging versions. | | DiffPanel | Visual diff between two scenes. |

Editing overlays

| Name | Purpose | | ------------------------------------------------------------ | -------------------------------------- | | TextEditorOverlay / FrameNameEditorOverlay | In-place text editors over the canvas. | | LinkHoverPopup / LinkDropShapeMenu / LinkCaptionEditor | Link interaction overlays. | | Markdown | Renders markdown (comments, captions). |

Primitives

| Name | Purpose | | ----------------------------- | ---------------------------------- | | IconButton / ButtonGroup | Buttons and grouped button rows. | | SegmentedControl / Slider | Segmented toggle and range slider. |

Hooks

| Name | Purpose | | ------------------------------------------------------------------------ | -------------------------------------------------------------- | | useDiagram() / useDiagramOptional() | Live Editor (imperative; no re-render on change). | | useDiagramContext() / useDiagramContextOptional() | Raw context value. | | useEditorSelector(select) | Custom selector — re-renders when the projected value changes. | | useScene() / useSelection() / useActiveTool() | Reactive slices of editor state. | | useHistory() | canUndo / canRedo + undo / redo. | | useLayers() / useActiveLayerId() | Layer list and active layer. | | useAnnotations() / useSelectedAnnotation() / useSelectedLink() | Annotation and link selection state. | | useMobileLayout() | Whether the compact / touch layout is active. | | useToast() / useToastOptional() / useEphemeralToast() | Toast API (pair with ToastHost). | | useSnapshotStore() | Snapshot store backing VersionPanel. | | useHelpDialogHotkey() | Wires the help-dialog hotkey. | | useContextMenuController() / ContextMenuControllerProvider | Imperative control of ContextMenu. | | usePaletteDropHandler() / usePalettePlacement() / usePaletteDrag() | Palette drop / placement / drag wiring. | | getActivePaletteDrag() / subscribePaletteDrag() | Read/observe the active palette drag outside React. |

Layout constants

Tunable sizes for the built-in panels and toolbar: PALETTE_WIDTH, PALETTE_ITEM_SIZE, PROPERTY_PANEL_WIDTH, PROPERTY_SWATCH_SIZE. Chrome sizes (side panels, sidebar, comment thread, toolbar separator) are CSS tokens — --du-side-panel-w, --du-sidebar-w, --du-thread-w, --du-panel-row-h, --du-icon-size.

Each component also exports its *Props type (e.g. ToolbarProps, PaletteProps); menu, toast, help, and context-menu modules additionally export their item/section types (ToolbarItem, ContextMenuItem, ToastKind, HelpRow, etc.).

Design notes

  • <DiagramCanvas> owns the editor's lifetime. Created in useLayoutEffect so children's effects see the provider value on first paint; disposed on unmount. initialScene and initialTool are read once — runtime updates go through the editor API (editor.loadScene, editor.setActiveTool).
  • Hooks subscribe via the editor's subscribe. Editor.setActiveTool calls notify() so useActiveTool (and similar bespoke selectors) re-render on tool changes.
  • No global state. Every editor instance is independent — composition via context lets multiple canvases live on the same page (useful for diff viewers, presentation modes).
  • Toolbar item kinds are a discriminated union. Hosts can mix builtin mode / undo / redo items with arbitrary action items in one declarative array.
  • Palette uses SVG icons through dangerouslySetInnerHTML. Template authors define the icon markup; the same SVG goes through the canvas renderer's SVG parser, so palette and canvas stay visually identical.
  • Tests run under jsdom. tests/setup.ts stubs HTMLCanvasElement.prototype.getContext, pointer-capture, and ResizeObserver — enough for the editor to mount without pulling the native canvas npm package.