Skip to content

Releases: Pivotick/Pivotick

v2.0.1

Choose a tag to compare

@github-actions github-actions released this 17 Sep 08:01
v2.0.1
936f03c
v2.0.1

Pivotick v2.0.0

Choose a tag to compare

@github-actions github-actions released this 14 Sep 12:30
v2.0.0
3fd3413

Pivotick now does the thing it is named for: Pivots

Pull more graph out of wherever your data lives, and you choose what lands. History is the way back out of anything that does.

Pivots

pivot-review

Run an enrichment against the nodes you picked and the results arrive as candidates: not in the graph, not in the table, not in a count, until you commit them.

  • Review them in the dock, one tab per source, searchable and sortable, with the rows already on canvas marked as such.
  • Reject what you do not want. It stays rejected for the session, and Reject all remaining turns 1,800 rows into 12.
  • Too many results means a refusal that says the number and the limit, never a silent sample. Narrow, and it lifts by itself.
  • Everything that lands remembers which source vouched for it, so one source's contribution can be dropped again in one call.

One click, when the question is simple

pivot-one-click

Right-click a node and Pivot ▸ lists every enrichment that applies, each with what it is advertising. Picking a row is the run. Small results land straight on the canvas; large ones open the review tab.

Undo, over everything the canvas holds

history-timeline

The top bar's Undo and Redo buttons are wired up at last, with Ctrl+Z / Ctrl+Shift+Z behind them and a timeline dropdown behind each. Pivot results, deletions, hides and hand-drawn work all go in the same list.

Saving results back

A pivot can write its own results back into the system they came from, and Pivotick keeps the books on what has crossed and what has not, so re-running does not duplicate what was saved.

Also in this release

  • Put your own mode on the left rail, beside Select, Create, View and Physics.
  • Every UI feature has an on/off switch that takes its button, panel, menu entry and shortcut with it.
  • The legend sits above the minimap in full mode, and the minimap draws notes.
  • Notifications can carry an action and outlive the usual few seconds.
  • Fixed: updating a node no longer replaces it, so its edges, position and physics survive.
  • Security: an external review closed several routes out of a note and into the page around it. Note Markdown now renders against an allow-list, which costs a task list its checkbox. Thanks to @Wachizungu for the relentless effort!

Upgrading

Most breaking changes touch APIs that never shipped. The one to read is the retirement of UI.modeRail, whose disabled slots are exactly what custom rail modes now fill. The migration table is in CHANGELOG.md.

Docs: Pivots & enrichment · Saving results · Undo & history in the gallery.

v1.6.0

Choose a tag to compare

@github-actions github-actions released this 28 Aug 14:24
v1.6.0
a31c262

Data dock, edge layers, a minimap, and a layout that tunes itself

Pivotick in full mode: mode rail, filtering legend, minimap, data dock and node panel

  • A data dock under the canvas: the graph as a sortable, filterable, selectable table sharing
    one selection with the canvas. It lists the whole graph — hidden nodes and collapsed clusters'
    contents included — and hosts panes of your own via addDockTab().
  • Edges come in kinds. Key them with edgeTypeAccessor, style them with edgeStyleMap, and
    switch a whole layer off from the filter panel or the legend — without moving the graph a pixel.
    UI.filter.hideDisconnected clears the nodes that leaves stranded.
  • A legend that filters, now keying several dimensions at once, through the same query engine
    the filter panel drives. A minimap in full mode, built on the new public
    getContentBounds() / setViewport().
  • Auto is the default physics preset: forces derived from what is on screen, and re-derived
    as the graph changes. Layout and physics also moved into a Physics rail mode.
  • Tree layouts no longer need a perfect hierarchy. Cycles, disconnected components and edgeless
    nodes all lay out, spacing works itself out from the node sizes, and parentKey / depthKey let
    the data declare parents outright.
  • On the canvas: rim badges as a channel of their own, an HTML card as the whole node
    (shape: 'none'), and edges meeting a node on its real border rather than a circle around it.
  • Every user-initiated write now goes through a before-hook you can veto, and content
    renderers may return a promise
    .
The data dock
The data dock — every node and edge, Visibility leading each row.
A custom dock pane
Panes of your own — addDockTab(), with its own views and toolbar.
Edge kinds and a stacked legend
Edge kinds, keyed and switchable — styled per kind, stacked in the legend.
The minimap
A minimap, on the public viewport API — click to recentre, drag to pan.
Badges on a node's rim
Rim badges — counts and states, on the shape's real rim.

The Physics rail mode, with a tree layout active

Physics is its own rail mode: a tile per layout, and — while a tree is active — a Root picker and
the two spacing sliders in place of the force knobs a tree ignores.

Breaking

Almost all of it is in the physics presets: PHYSICS_PRESETS.default is gone (Auto replaces the
concept), PhysicsKnobs widened from four fields to six, tight is re-tuned, and linkDistance's
range tops out higher. flipEdgeDirection is gone too: the tree layout now wor
when the arrows are not a hierarchy. In CSS, the legend's state classes moved t
.pvt-legend-section.

Full notes, with the exact preset values, in CHANGELOG.md

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 29 Jul 10:15
7de3de3

Chrome UI - mode-driven UI redesign, Improvements & Security fixes

Replaces the classic control bar + toolbar with a mode-driven UI built around a left mode rail (Select / Create / View), a contextual tool panel, and a View flyout for layout / physics / grid. The top bar becomes a transparent overlay floating over the graph, and every panel — sidebar, slide panels, modal, context menu, tooltip — now sits on one shared floating-chrome surface, themed for both light and dark.

It also ships a security-hardening pass over everything reachable from untrusted graph data, which carries its own breaking change: a string returned from a render hook now renders as text, never as markup.

Pivotick full UI

Mode-driven controls

  • Mode rail — Select / Create / View as exclusive modes. The Select/Create slots double as split-buttons that reflect the armed tool (e.g. Select → Lasso). The coming-soon Explore / Enrich modes are opt-in via UI.modeRail (both hidden by default; rendered as disabled SOON slots when enabled).
  • Tool panel — contextual tools per mode (Create → Add node / Add edge / Add note / Edit node), collapsible, with the rail reflecting the active tool.
  • View flyout — layout picker, physics presets + live sliders, and grid / snap / freeze toggles.
Mode rail Tool panel (Create) View flyout
Mode rail Tool panel View flyout

Floating chrome

  • Transparent top bar — Search / Filter / Notes float as pills over the graph grid.
  • Sidebar, slide panels, modal, context menu and tooltip share one rounded, bordered surface; the Filters and Notes slide panels are mutually exclusive and restyled to match.
  • Active-filter indicator restyled as a quiet accent chip; notes snap to the grid on drag when grid-snapping is on, and the decorative grid pitch now matches the snap gridSize.
  • Accessibility: rail / chrome controls are focusable and expose their toggle state.

Sidebar: selection & bulk actions

  • Clear-selection control, plus a bulk-action row for multi-selection: Pin / Unpin / Hide / Delete are functional; Group / Ungroup / Isolate / Bulk-edit are shown disabled with a SOON badge.
  • Empty panels and their separators collapse instead of leaving gaps.

New APIs

  • Simulation physics setters, each mapping a 0–100 knob to the real force domain and reheating the simulation: setRepulsion, setLinkDistance, setCollisionRadius, setFriction, plus applyPhysicsPreset('tight' | 'loose' | 'default').
  • New UIManager accessors: modeRail, toolPanel, viewFlyout.
  • New UI.modeRail option — { explore?: boolean, enrich?: boolean }, both `f

Breaking changes

Before After
graph.UIManager.graphControls Layout/physics moved to the View flyout — graph.UIManager.viewFlyout
graph.UIManager.graphToolbar Select/Create tools — graph.UIManager.toolPRail
graph.UIManager.graphNaviation graph.UIManager.graphNavigation (long-st
UI.selectionMenu (per-node) UI.contextMenu
UI.selectionMenu (multi-select) Sidebar bulk-action row
render: () => '<b>hi</b>' on any string | HTMLElement option Renders ant` for markup
  • GraphControls and GraphToolbar are retired; the mode chrome is the defaul
  • The e "Edit Graph" toggle is gone, superseded by the Create mode.

See the CHANGELOG.

Also in this release

  • Reusable Typeahead wired to [[node]] note references
  • Themed body-portaled scrollbars (typeahead / dropdown / context menu)
  • Ego-graph capped to 50 neighbours; grayscale dropped from dimmed nodes; neigh
  • Fixes: shadowlink-container SVG leak on tooltip rebuild; View-flyout run/pausatchdog; lasso outline + screen→graph mapping restored; edit-tool canvas cursors
    restored; Edit-node tool disabled without a selection; picker input styling; fo square
  • Docs: new security guide, README hero regenerated for the new chrome (`npm ruails refreshed

Security hardening

Reported by @Wachizungu see the new security guide.

  • Strings never render as markup. Every string | HTMLElement option — extes, main-header / properties-panel / tooltip render — now resolves to text;return an HTMLElement for markup. Breaking.
  • style.svgIcon is sanitized before insertion; style.imagePath and property links are limited to http:, https:, data: and blob:.
  • Node name and description render as text in the node modals, and the Markdown node-reference renderer escapes nodeName.
  • Recursive walks over caller data (hasCycle, findMaxReachabilityRoot, JsonViewer) are iterative and bounded, and node-id lookups are Map-keyed so __proto__ / constructor ids
    no longer break the layout.

Assigned CVE/GCVE

Testing

  • npm run build, tsc, and ESLint: clean.
  • Playwright visual suite: 175 / 175 passing on the chrome work; the security pass adds security.spec.ts, covering the reported XSS surfaces with hostile graph data.
  • Gallery thumbnails refreshed for the new chrome.

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:13
v1.4.0
8972247

Pivotick v1.4.0

Since v1.2.0 — bundles the 1.3.0 feature wave and the 1.4.0 hardening pass.

Highlights

  • 🔌 Plugin API — register custom UI through a composite lifecycle and a declarative registry (PivotickPlugin, UIComponent).
  • ✏️ Interactive edge creation — onBeforeEdgeCreate / isValidConnection gate edges, and ctx.promptLabel / ctx.promptData enrich them as you draw.
  • 🔎 Faceted multi-select sidebar — inspect a selection as distribution facets and click bars/pills to filter it.
  • 🗂️ Type-aware node inspector — properties rendered by type (links, JSON, copy), with an auto-fitting header title and a neighbour graph/stats/list.
  • 🗒️ Notes redesigned as jewel cards — colour-driven cards with a jewel/terminal surface toggle and Markdown content.
  • 🎨 Theme-aware polish — themed scrollbars, a richer tooltip, and opt-in auto-fit on cluster expand/collapse.
  • 🔒 Hardening pass (1.4.0) — javascript: URL XSS blocked, cyclic-data stack-overflow guard, keybinding stacking, and more.

🔌 Plugin API & composite UI lifecycle

UI elements are now driven by a composite lifecycle and a declarative registry,
and third-party code can hook into it. A plugin receives a PluginContext
(with a live ctx.layout getter) and can mount its own UIComponents that
participate in the same phased setup/teardown as the built-in UI.

New public exports: UIComponent, PivotickPlugin, PluginContext, UIPhase
(also attached as Pivotick.UIComponent on the UMD/IIFE global).

Custom "Graph stats" badge added through the plugin API

Gallery: Extend with a plugin


✏️ Interactive edge creation — validate, enrich, and label

Edge creation (drag-and-drop or click-click) now has a full set of hooks:

  • onBeforeEdgeCreate + live isValidConnection — veto or approve an edge
    before it commits; invalid targets are rejected as you drag.
  • ctx.promptLabel({ mode }) — prompt for an edge label at creation time
    (inline free-text on drag, a predefined-label dropdown on click).
  • ctx.promptData — open a rich edge-create modal, either from a
    declarative form spec or fully custom HTML.
  • edgeEditor.labelPrompt — the static/config equivalent for label prompts.

The async lifecycle behind these was hardened in 1.4.0 (zombie-mode guards,
promise rejections, static-mode dedup, and the modal prompt path).

▶ Try it live — edge creation is a motion, so these are best seen in the interactive gallery:


🔎 Faceted multi-select sidebar

Selecting multiple nodes now shows a faceted breakdown of the selection —
distribution bars for low-cardinality fields, value pills for high-cardinality
ones, plus a filterable connection-stat facet. Click a bar or pill (or the
hover Select / Exclude cluster) to filter the selection down; filtering to a
single node drops straight into the single-node view.

1.4.0 hardening: facet matching uses strict equality (so 80 and '80' stay
distinct), matches the displayed value rather than raw getData(), and caps
distribution rows/segments with a collapsed tail summary.

Faceted multi-select breakdown of a node selection


🗂️ Type-aware node inspector

The single-node sidebar renders each property according to its type — links
become clickable, objects render as collapsible JSON, and every value gets a
copy button. Long node titles auto-fit in the header (with a type-aware
fallback), and the neighbour section offers a graph / stats / list view.

1.4.0 hardening: property links are restricted to an allowlist of URL schemes
to block javascript: XSS, jsonToHtml guards against cyclic/deeply-nested
data (no more stack overflow), and middle-truncation slices by code point so
emoji/surrogate pairs aren't garbled.

Type-aware property list with a clickable URL and collapsible style JSON

Node inspector with the neighbour graph view


🗒️ Notes redesigned as jewel cards

Notes are now colour-driven "jewel" cards. Each note can toggle between a solid
jewel surface and a neutral terminal panel, its first line is promoted to
the title, and content supports Markdown (bold / italic / code). Edit-mode
chrome was reworked (header drag, save button, thicker accent) and notes now
render above the graph nodes.

The five jewel note colours

Jewel vs. terminal note surfaces

A Markdown jewel note on the dark theme


🎨 Tooltip & theming polish

  • Tooltips reuse the sidebar's type-aware PropertyList, with compact
    properties, scrollable JSON, and a shared title-fit controller (each pinned
    tooltip refits its own title on resize).
  • Theme-aware scrollbars throughout, including the tooltip and its resize grip.
  • Opt-in auto-fit on cluster expand/collapse (fitViewOnExpandCollapse, default off).
  • Copy buttons in pinned tooltips are re-wired after cloning so they keep working.

🔒 Hardening & fixes (1.4.0)

  • Security: allowlist URL schemes in property links to block javascript: XSS.
  • Robustness: guard jsonToHtml against cyclic / deeply-nested node data to prevent stack overflow.
  • Keybindings: stack bindings per key so a plugin's binding shadows the built-in instead of clobbering it.
  • Notes: keep the dirty flag mid-edit and rebuild on edit-end so programmatic setContent isn't lost.
  • Lifecycle: fire lifecycle phases once so setData() doesn't stack graphReady handlers; auto-remove subscriptions on destroy.
  • Build: attach UIComponent to the Graph global so it's usable from the UMD/IIFE bundles.
  • Perf: update only the note connector on drag/resize instead of running a full renderer tick.
  • Emoji-safe middle-truncation, strict-equality facet filtering, and assorted dead-code cleanup.

⚠️ Breaking changes

  • PropertyEntry value semantics — string values now render as text;
    pass an HTMLElement to render HTML. Previously-HTML string values must be
    converted to elements (1.4.0).

🧪 Tests & docs

  • The Playwright visual regression suite (tests/visual/) is now documented
    in CLAUDE.md and gained specs for edge-create veto, facet filtering, the
    node panel, notes, the plugin API, and UI-lifecycle reentrancy.
  • New gallery examples ship with screenshots: Extend with a plugin,
    Validate & enrich new edges, Label an edge as you draw it.
  • TypeDoc entry points and internal-type annotations were tidied.

Upgrading

npm install pivotick@1.4.0

v1.2.0 → v1.4.0 — see the Breaking changes note above
before upgrading if you build property lists with HTML strings.

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 08 Jul 13:51
v1.2.0
397e89a

Documentation gallery rebuild + library hardening (v1.2.0)

Rebuilds the examples gallery from scratch — 34 interactive cards across 8 phases
(styling, layouts, events, editing/notes, filtering, theming, and scale up to
~1,500 nodes) — and fixes/extends the library features those cards exercised.

image image

New

  • Gallery — 34 live, copy-pasteable cards demonstrating every major feature in the doc.
  • Image nodes — imageFit modes (icon / cover / contain / frame), click-to-reveal
    full picture, and a graceful fallback glyph for broken images.
  • Font-agnostic icons — resolve node icons across Font Awesome + misp-iconify.
  • Seedable & pinnable layouts — preserve initial node x/y and honour caller fx/fy.
  • Gravity tiers — configurable d3GravityStrengthConnected floor.

Changes

  • Version bumped to 1.2.0.
  • Replaced tom-select with the in-house PivotickPicker.
  • Simulation worker hardened: serialization-safe DTOs, compute-time slow-tick
    detection, and main-thread fallback when the worker is blocked.
  • Sass modernized (@use over @import); lint + dataset cleanups.

Fixes

  • Simulation / clustering — positions written back by node id; external edges
    re-anchored to expanded clusters; cross-cluster edges re-targeted through collapse
    states; charge damping clamped (no more NaN); fit-and-center after the layout settles.
  • Rendering — measured renderNode size feeds the collision radius; visibility
    observer guarded against an unset selection.
  • Filtering / query — null/undefined facet values dropped (crash); programmatic
    setFilter reflected in the panel; excludeNode/includeNode act on the live node;
    integer attributes added to the numbers set.
  • Edges / tooltip — per-edge style preserved across updateStyle; themed label
    colours; tooltip honours its own header/properties maps.

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 26 Jun 09:43
v1.1.0
3c4d8e8

This release turns Pivotick from a graph viewer into a graph editor. It adds
two major new subsystems — free-floating Notes and an interactive editing
layer
— plus a new editing toolbar, fullscreen, lasso selection, and Markdown-rich annotations.

All changes are backward compatible: existing options, events, and callbacks keep working. New capabilities are opt-in.

✨ Notes — free-floating annotations (new)

image
  • Add free-floating notes anywhere on the canvas, passed via the constructor
    (new Graph(el, { notes: [...] })) or created interactively from the toolbar.
  • Markdown content rendered with marked + dompurify, including a custom
    node-reference extension: link note text to graph nodes, styled with the
    referenced node's color.
  • Inline edit mode (open with the edit shortcut), drag to reposition, resize,
    and icon support. Notes are rendered as full HTML.
  • New Notes sidebar with header actions.
  • New data events on the graph bus: noteAdd, noteRemove, noteChange
    (and note:add / note:remove / note:change in batch changes).

✏️ Interactive editing layer (new) — graph.editing

image
  • In-place node editing through an Edit Node modal, configured via
    ui.editors.nodeEditor (enabled, fields, or a custom render(session)).
  • Hybrid edge creation: connect nodes by either drag-and-drop or
    click-click, with a live "shadow edge" preview while you draw.
  • "Connect to…" action added to the node context menu.

🧰 Editing toolbar & selection (new)

image
  • New graph toolbar for edit operations, with icons and node-vs-edge selection
    awareness.
  • Lasso selection and inverse selection.
  • Add note directly from the toolbar.

🧭 Navigation & canvas

  • Fullscreen mode (close with Esc).
  • Canvas tools moved into graph navigation; canvas grid highlighting.
  • "Freeze nodes on drag" toggle in the options dropdown.

🔌 API & interaction layer

  • Interaction callbacks reworked with more abstraction and a way to cancel
    default behavior
    .
  • Quick-action menu items now accept Notes, support a shortcut hint, and
    new outline-soft variant.
  • Note dragging events; "closest node to pointer" helper for interactions.
  • Improved keybinding handler + a UI helper to render keybinding badges.

🧩 Components & UI

image
  • New JSON viewer component and node picker widgets.
  • Inspect node modal.
  • createNodePreview helper for node vignettes.
  • Dropdown styling/animation polish; modal lifecycle fix (removed from DOM once).
  • Neighbors sidebar: hover a list item to highlight the node on the graph.

🐛 Fixes

  • Non-directed graphs: correct edge rendering and neighbor resolution.
  • Drag & text-selection behavior; pointerdown/click no longer call
    preventDefault.
  • Note drawer: min-width, correct foreignObject sizing, action-button
    positioning on resize, live shadow-link update while resizing.
  • Inspect modal no longer opens multiple times.
  • Node-reference color applied in the Notes sidebar.
  • Resolved 16 pre-existing TypeScript errors; getters now resolve object/boolea
    types.

🛠️ Developer / internal

  • New Playwright visual-regression test suite (10 areas: styling, dark theme,
    layout, clustering, filtering, selection, hover/tooltip/context-menu, UI chro
    notes, edge-creation).
  • Note rendering reworked from mixed SVG/HTML to full HTML — see upgrade notes.
  • Pluggable note-content renderer pipeline (NoteContentRenderer).

⚠️ Upgrade notes

  • No breaking API changes — all new options/events/callbacks are additive.
  • If you custom-styled notes via SVG selectors, note rendering is now full
    HTML; update your selectors accordingly.

Full changelog: v1.0.0...v1.1.

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 11 May 12:22
v1.0.0
65eb2ad
v1.0.0