@danxbot/ui 13.0.0 → 13.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,9 +22,9 @@ export interface GraphExplorerProps<Extra = unknown> {
22
22
  onNodeClick?: (node: CanvasNode<Extra>) => void;
23
23
  /** `variant="minimap"` only: the expand affordance's handler. Defaults to an in-place full-screen dialog. */
24
24
  onExpand?: () => void;
25
- /** Along-axis extent of a node that does not need more, in px. @default LAYOUT_DEFAULTS.nodeWidth */
25
+ /** Cross-axis extent of a node that does not need more, in px — the rank's OWN axis (ranks spread along y, DX-3401's vertical default) unless `orientation` is overridden. @default LAYOUT_DEFAULTS.nodeWidth */
26
26
  nodeWidth?: number;
27
- /** Cross-axis extent BEFORE a taller node's own content grows it. @default LAYOUT_DEFAULTS.nodeHeight */
27
+ /** Along-axis extent BEFORE a taller node's own content grows it — the axis ranks advance along. @default LAYOUT_DEFAULTS.nodeHeight */
28
28
  nodeHeight?: number;
29
29
  /** `variant="explorer"` only: height of the viewport. @default "32rem" */
30
30
  height?: string;
@@ -46,5 +46,12 @@ export interface FitOptions extends ScaleBounds {
46
46
  /** @default CAMERA_DEFAULTS.fitMaxScale — never zoom IN past this to fit a small box. */
47
47
  maxScale?: number;
48
48
  }
49
+ /**
50
+ * The smallest box containing every one of `boxes` — how a camera "frame"
51
+ * (e.g. a focused node plus its parent and children, DX-3401) is built from
52
+ * several already-placed boxes without re-deriving a bounding-box formula at
53
+ * every call site. `null` for an empty list — nothing to union.
54
+ */
55
+ export declare function unionBox(boxes: readonly Box[]): Box | null;
49
56
  /** A camera that fits the whole of `box` inside `viewport`, centred, padded. */
50
57
  export declare function fitBox(box: Box, viewport: Size, options?: FitOptions): CameraState;
@@ -1,5 +1,5 @@
1
1
  export { GraphExplorer, type GraphExplorerProps } from "./GraphExplorer";
2
- export { layoutExplorerTree, neighbourhoodTree, edgePath } from "./tree-layout";
3
- export { CAMERA_DEFAULTS, centerOn, clampScale, fitBox, toContentPoint, toScreenPoint, zoomAtPoint } from "./camera-math";
2
+ export { frameBoxFor, layoutExplorerTree, neighbourhoodTree, edgePath } from "./tree-layout";
3
+ export { CAMERA_DEFAULTS, centerOn, clampScale, fitBox, toContentPoint, toScreenPoint, unionBox, zoomAtPoint } from "./camera-math";
4
4
  export type { Box, CameraState, FitOptions, Point, ScaleBounds, Size } from "./camera-math";
5
5
  export type { CrossLink, ExplorerLayout, ExplorerNodeRenderContext, ExplorerNodeRenderer, ExplorerTree, GraphExplorerVariant, TreeNode, } from "./types";
@@ -1,10 +1,19 @@
1
1
  import { edgePath } from "../node-canvas/layout";
2
2
  import type { LayoutOptions } from "../node-canvas/types";
3
+ import { type Box } from "./camera-math";
3
4
  import type { CrossLink, ExplorerLayout, ExplorerTree } from "./types";
4
5
  /** Re-exported for a consumer drawing `edges`/`crossLinks` into an SVG. */
5
6
  export { edgePath };
6
7
  /**
7
- * Lay out a tree, left to right, from a parent backbone alone.
8
+ * Lay out a tree, top to bottom, from a parent backbone alone. Ranked
9
+ * vertically (dagre `rankdir: "TB"`) so SIBLINGS spread horizontally within a
10
+ * rank — the sprawl DX-3401's card asks for. A tree this shallow-but-wide (a
11
+ * handful of levels, many children per level) stacked its siblings into one
12
+ * tall column under the previous `"horizontal"` (`LR`) default, which is
13
+ * exactly backwards for that shape: `"horizontal"` ranks left to right, so
14
+ * within-rank siblings stack along the CROSS axis (vertically) instead.
15
+ * `options.orientation` still overrides this default for a caller with the
16
+ * opposite shape (deep and narrow).
8
17
  *
9
18
  * `crossLinks` are resolved against the ALREADY-FIXED node positions and
10
19
  * returned separately (`ExplorerLayout.crossLinks`) — they never reach
@@ -15,6 +24,18 @@ export { edgePath };
15
24
  * uses for a group boundary.
16
25
  */
17
26
  export declare function layoutExplorerTree<Extra>(tree: ExplorerTree<Extra>, crossLinks?: readonly CrossLink[], options?: LayoutOptions): ExplorerLayout<Extra>;
27
+ /**
28
+ * The box a camera should keep in frame around `focusId`: the focused node
29
+ * itself, its parent (one rank up) and every one of its direct children (one
30
+ * rank down) — "the minimap always frames the current node, its parent and
31
+ * its children" (DX-3401's fix for the minimap shrinking an entire tree to
32
+ * specks, and for the full-screen explorer's initial view not opening
33
+ * focused). Computed from an ALREADY-LAID-OUT tree, so it can never disagree
34
+ * with what is actually on screen the way fitting a separately-computed
35
+ * bounding box could. `null` when `focusId` isn't laid out at all — nothing
36
+ * to frame (a stale id, or data still loading).
37
+ */
38
+ export declare function frameBoxFor<Extra>(layout: ExplorerLayout<Extra>, focusId: string): Box | null;
18
39
  /**
19
40
  * The subtree a minimap draws: `focusId`'s ancestor chain up to its root,
20
41
  * `focusId`'s immediate siblings, and `focusId`'s immediate children — "the
@@ -6,6 +6,29 @@ export interface CameraClickEvent {
6
6
  export interface UseCameraOptions {
7
7
  /** Content-space bounding box of the whole drawing. Drives `fitAll`. */
8
8
  contentBox: Box;
9
+ /**
10
+ * The box the camera AUTOMATICALLY keeps in frame — on mount, and again
11
+ * whenever `frameKey` changes (DX-3401). Typically the focused node plus
12
+ * its parent and children, so the camera never zooms out further than the
13
+ * relevant neighbourhood just because the whole tree is big. `null`/
14
+ * `undefined` falls back to `contentBox` (fit the whole drawing) — the
15
+ * ordinary case when there is no focus yet.
16
+ */
17
+ frameBox?: Box | null;
18
+ /**
19
+ * A caller-chosen, STABLE value (e.g. the focused node's id) that changing
20
+ * re-runs the automatic frame fit even when `resetKey` hasn't changed —
21
+ * `frameBox` itself is deliberately NOT a dependency (see the frame-fit
22
+ * effect below for why), so this is the only reliable "the frame target
23
+ * moved" signal for a caller whose `resetKey` tracks something else (e.g.
24
+ * the explorer's own `resetKey` is the tree, not the focused node).
25
+ */
26
+ frameKey?: unknown;
27
+ /** Padding around the auto-fit target (`frameBox ?? contentBox`) — distinct
28
+ from `fitAll`'s always-`CAMERA_DEFAULTS.fitPadding`, since a compact
29
+ minimap strip wants much less breathing room than the full explorer.
30
+ @default CAMERA_DEFAULTS.fitPadding */
31
+ framePadding?: number;
9
32
  /** A node's content-space box, for `flyTo`. `null` for an id not laid out. */
10
33
  boxOf: (id: string) => Box | null;
11
34
  /** A press that released without travelling past `CLICK_DISTANCE`. */
@@ -129,7 +129,7 @@ export { ProvenanceDisclosure, ProvenanceDetail, ProvenanceBadge, ConfidenceRead
129
129
  export { confidenceLevel, CONFIDENCE_LEVEL_LABELS, type ConfidenceLevel } from "./lib/confidence";
130
130
  export { createSimStore, resetSimStores, useSimSettings, setSimSettings, getNetworkSpeed, getDataSource, simulateLatency, SimNetworkError, type SimStore, type SimStoreOptions, type SimSettings, type NetworkSpeed, type DataSource, type SimNamespace, } from "./lib/sim";
131
131
  export { NodeCanvas, LAYOUT_DEFAULTS, edgePath, layoutGraph, neighbourhood, type NodeCanvasProps, type CanvasCycleScope, type CanvasEdge, type CanvasGraph, type CanvasGroup, type CanvasLayout, type CanvasNode, type CanvasOrientation, type CanvasPlacedEdge, type CanvasScope, type LayoutOptions, type NodeRenderContext, type NodeRenderer, type PlacedNode, } from "./components/node-canvas";
132
- export { GraphExplorer, layoutExplorerTree, neighbourhoodTree, CAMERA_DEFAULTS, centerOn, clampScale, fitBox, toContentPoint, toScreenPoint, zoomAtPoint, type GraphExplorerProps, type Box, type CameraState, type FitOptions, type Point, type ScaleBounds, type Size, type CrossLink, type ExplorerLayout, type ExplorerNodeRenderContext, type ExplorerNodeRenderer, type ExplorerTree, type GraphExplorerVariant, type TreeNode as ExplorerTreeNode, } from "./components/graph-explorer";
132
+ export { GraphExplorer, frameBoxFor, layoutExplorerTree, neighbourhoodTree, CAMERA_DEFAULTS, centerOn, clampScale, fitBox, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, type GraphExplorerProps, type Box, type CameraState, type FitOptions, type Point, type ScaleBounds, type Size, type CrossLink, type ExplorerLayout, type ExplorerNodeRenderContext, type ExplorerNodeRenderer, type ExplorerTree, type GraphExplorerVariant, type TreeNode as ExplorerTreeNode, } from "./components/graph-explorer";
133
133
  export { defineRecordType, resetRecordTypes, useRecord, useRecords, useStaleness, write, writeAll, peekRecord, readState, readStaleness, subscribeToKey, subscribeToStaleness, retainKeys, sweepRecords, setRecordStoreTenant, getRecordStoreTenant, flushRecordNotifications, resetRecordStore, recordStoreStats, UNKNOWN_STATE, normalizeTypeName, normalizeTimestamp, recordKey, isRecordRef, type RecordRef, type ReadOptions, type RecordPayload, type RecordState, type RecordTypeOptions, type RecordTypeToken, type StalenessEntry, type WriteAllResult, type WriteOptions, type WriteResult, type WriteSource, type WriteVerdict, } from "./lib/records";
134
134
  export { RealtimeProvider, useRealtime, useRealtimeEpoch, useRealtimeHealth, useRealtimeRegistry, SubscriptionRegistry, normalizeScope, scopeKey, subscriptionKey, readRealtimeEpoch, subscribeToRealtimeEpoch, subscribeToRealtimeEvents, resetRealtimeSignals, type RealtimeChannel, type RealtimeConnectionState, type RealtimeDiagnostic, type RealtimeEvent, type RealtimeHealth, type RealtimeProviderProps, type RealtimeScope, type RealtimeScopeInput, type RealtimeStatus, type RealtimeTransport, type RegistryOptions, type SubscriptionHealth, type SubscriptionLease, type SubscriptionRequest, } from "./lib/realtime";
135
135
  export { useRecordRead, useRecordListRead, useRecordStoreSweep, applyMutationResult, optimisticWrite, beginOptimisticWrite, resetOptimisticWrites, type OptimisticHandle, type OptimisticWriteOptions, type OptimisticWriteSpec, type SlotDescriptor, acquireSlot, appendCreated, emptySlotSnapshot, readSlot, resetSlots, slotKeys, subscribeToSlot, writeSlot, RefetchRunner, registerActiveRead, resetActiveReads, type ActiveRead, type ListFetch, type ListFetchResult, type ListReadOptions, type ListReadResult, type ReadError, type RecordFetch, type RecordReadOptions, type RecordReadResult, type RunnerOptions, type SlotSnapshot, } from "./lib/reads";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danxbot/ui",
3
- "version": "13.0.0",
3
+ "version": "13.0.1",
4
4
  "type": "module",
5
5
  "description": "Danxbot — a domain-agnostic React design system with motion as a first-class primitive.",
6
6
  "license": "MIT",