@danxbot/ui 13.0.2 → 13.0.4

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.
@@ -26,10 +26,17 @@ export interface GraphExplorerProps<Extra = unknown> {
26
26
  nodeWidth?: number;
27
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
+ /** Floor on the automatic frame-fit's scale (mount / focus change, both
30
+ `variant`s) — below this, the camera holds the floor and centres on the
31
+ focused node instead of shrinking the whole frame to fit; `fitAll`
32
+ stays unaffected (DX-3404). See `MIN_READABLE_TITLE_SCALE`'s own
33
+ comment for the derivation; override when `renderNode` uses a
34
+ different title font size. @default MIN_READABLE_TITLE_SCALE */
35
+ minReadableScale?: number;
29
36
  /** `variant="explorer"` only: height of the viewport. @default "32rem" */
30
37
  height?: string;
31
38
  /** Nothing pans, zooms or clicks. Reading is unaffected. */
32
39
  disabled?: boolean;
33
40
  className?: string;
34
41
  }
35
- export declare function GraphExplorer<Extra = unknown>({ tree, crossLinks, label, renderNode, variant, focusId: controlledFocusId, defaultFocusId, onFocusIdChange, visitedIds, onNodeClick, onExpand, nodeWidth, nodeHeight, height, disabled, className, }: GraphExplorerProps<Extra>): import("react").JSX.Element;
42
+ export declare function GraphExplorer<Extra = unknown>({ tree, crossLinks, label, renderNode, variant, focusId: controlledFocusId, defaultFocusId, onFocusIdChange, visitedIds, onNodeClick, onExpand, nodeWidth, nodeHeight, height, minReadableScale, disabled, className, }: GraphExplorerProps<Extra>): import("react").JSX.Element;
@@ -55,3 +55,55 @@ export interface FitOptions extends ScaleBounds {
55
55
  export declare function unionBox(boxes: readonly Box[]): Box | null;
56
56
  /** A camera that fits the whole of `box` inside `viewport`, centred, padded. */
57
57
  export declare function fitBox(box: Box, viewport: Size, options?: FitOptions): CameraState;
58
+ /**
59
+ * Which viewport edges have `box`'s content extending past them at `camera`'s
60
+ * current position/scale — the input `fitBoxWithFloor` (below) needs to
61
+ * report an overflow cue, factored out because a caller re-deriving it from
62
+ * raw camera state would be a second, easily-drifting copy of this same
63
+ * arithmetic (DX-3404). A small epsilon absorbs floating-point noise at an
64
+ * edge that lands (by construction) exactly on the viewport boundary.
65
+ */
66
+ export interface FrameOverflow {
67
+ left: boolean;
68
+ right: boolean;
69
+ top: boolean;
70
+ bottom: boolean;
71
+ }
72
+ export interface FitWithFloorOptions extends FitOptions {
73
+ /**
74
+ * A SECOND, stricter lower bound on top of `minScale`/`fitBounds` (DX-3404)
75
+ * — readability-driven ("titles at least ~13px on screen"), not
76
+ * graph-legibility-driven the way `CAMERA_DEFAULTS.minScale` (0.15) is.
77
+ * `undefined` (the default) makes this behave exactly like `fitBox` — the
78
+ * floor is opt-in per call site, so `fitAll` (which never passes it) stays
79
+ * a manual control that may zoom out past readable text on purpose.
80
+ * When the ordinary fit-to-`box` scale would land BELOW this floor, the
81
+ * camera clamps to the floor and centres on `focusBox` instead of `box` —
82
+ * showing the focused target at a readable size and reaching the rest of
83
+ * `box` by panning, rather than shrinking everything to fit.
84
+ */
85
+ minReadableScale?: number;
86
+ /**
87
+ * What to centre on once `minReadableScale` clamps the scale — normally
88
+ * the focused node's own (small) box, not the whole (wide) `box` being
89
+ * framed. Defaults to `box` itself (so an omitted `focusBox` degrades to
90
+ * "clamp the scale but still centre the frame", never a crash).
91
+ */
92
+ focusBox?: Box;
93
+ }
94
+ export interface FitWithFloorResult {
95
+ camera: CameraState;
96
+ /** Which sides of `box` extend past the viewport at the returned camera's
97
+ scale/position — all `false` whenever the floor didn't clamp, since an
98
+ ordinary `fitBox` result always contains the whole of `box` by
99
+ construction. */
100
+ overflow: FrameOverflow;
101
+ }
102
+ /**
103
+ * `fitBox`, with an optional readable-text floor (DX-3404) — see
104
+ * `FitWithFloorOptions.minReadableScale`'s own doc for the behaviour. Used
105
+ * ONLY by `use-camera.ts`'s automatic frame-fit effect; `fitAll` keeps
106
+ * calling `fitBox` directly so the manual "fit everything" control is never
107
+ * affected by this floor (AC #2).
108
+ */
109
+ export declare function fitBoxWithFloor(box: Box, viewport: Size, options?: FitWithFloorOptions): FitWithFloorResult;
@@ -1,5 +1,5 @@
1
1
  export { GraphExplorer, type GraphExplorerProps } from "./GraphExplorer";
2
2
  export { frameBoxFor, layoutExplorerTree, neighbourhoodTree, edgePath } from "./tree-layout";
3
- export { CAMERA_DEFAULTS, centerOn, clampScale, fitBox, toContentPoint, toScreenPoint, unionBox, zoomAtPoint } from "./camera-math";
4
- export type { Box, CameraState, FitOptions, Point, ScaleBounds, Size } from "./camera-math";
3
+ export { CAMERA_DEFAULTS, centerOn, clampScale, fitBox, fitBoxWithFloor, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, } from "./camera-math";
4
+ export type { Box, CameraState, FitOptions, FitWithFloorOptions, FitWithFloorResult, FrameOverflow, Point, ScaleBounds, Size, } from "./camera-math";
5
5
  export type { CrossLink, ExplorerLayout, ExplorerNodeRenderContext, ExplorerNodeRenderer, ExplorerTree, GraphExplorerVariant, TreeNode, } from "./types";
@@ -1,4 +1,4 @@
1
- import { type Box, type CameraState } from "./camera-math";
1
+ import { type Box, type CameraState, type FrameOverflow } from "./camera-math";
2
2
  export interface CameraClickEvent {
3
3
  /** Client coordinates, for the caller to hit-test against its own elements. */
4
4
  target: HTMLElement;
@@ -29,6 +29,27 @@ export interface UseCameraOptions {
29
29
  minimap strip wants much less breathing room than the full explorer.
30
30
  @default CAMERA_DEFAULTS.fitPadding */
31
31
  framePadding?: number;
32
+ /**
33
+ * A THIRD, stricter lower bound layered on top of `fitBounds`'s own
34
+ * `minScale`, applied ONLY to the automatic frame-fit effect below — NEVER
35
+ * to `fitAll` (which keeps calling `fitBox` directly with `fitBounds`) and
36
+ * NEVER to `zoomBounds` (wheel/pinch/+/-, which stay `CAMERA_DEFAULTS
37
+ * .minScale`..`maxScale`) (DX-3404). See `camera-math.ts`'s
38
+ * `FitWithFloorOptions.minReadableScale` for the full behaviour: below
39
+ * this scale, the automatic fit clamps here and centres on `focusBox`
40
+ * instead of shrinking `frameBox ?? contentBox` to fit — the rest is
41
+ * reached by panning. `undefined` (the default) reproduces the pre-DX-3404
42
+ * behaviour exactly (plain `fitBox`, no floor).
43
+ */
44
+ minReadableScale?: number;
45
+ /**
46
+ * What the automatic fit centres on once `minReadableScale` clamps the
47
+ * scale — normally the focused node's own (small) box, distinct from the
48
+ * wider `frameBox` (focus + parent + children) being framed. Defaults to
49
+ * `frameBox ?? contentBox` when omitted, matching `fitBoxWithFloor`'s own
50
+ * default. Ignored when `minReadableScale` is unset.
51
+ */
52
+ focusBox?: Box | null;
32
53
  /** A node's content-space box, for `flyTo`. `null` for an id not laid out. */
33
54
  boxOf: (id: string) => Box | null;
34
55
  /** A press that released without travelling past `CLICK_DISTANCE`. */
@@ -44,6 +65,14 @@ export interface UseCameraResult {
44
65
  panning: boolean;
45
66
  /** True for the duration of a programmatic move — see the module doc. */
46
67
  animating: boolean;
68
+ /**
69
+ * Which sides of the automatic frame target (`frameBox ?? contentBox`)
70
+ * extend past the viewport at the CURRENT camera — all `false` unless
71
+ * `minReadableScale` actually clamped the last automatic fit (DX-3404).
72
+ * The one source of truth for an "edge cue" overlay, so a caller never
73
+ * re-derives this from raw `camera` state itself.
74
+ */
75
+ frameOverflow: FrameOverflow;
47
76
  bindViewport: (node: HTMLDivElement | null) => void;
48
77
  zoomIn: () => void;
49
78
  zoomOut: () => void;
@@ -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, 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";
132
+ export { GraphExplorer, frameBoxFor, layoutExplorerTree, neighbourhoodTree, CAMERA_DEFAULTS, centerOn, clampScale, fitBox, fitBoxWithFloor, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, type GraphExplorerProps, type Box, type CameraState, type FitOptions, type FitWithFloorOptions, type FitWithFloorResult, type FrameOverflow, 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.2",
3
+ "version": "13.0.4",
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",