@bruno00o/graph 0.2.0 → 0.3.0

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.
@@ -1,4 +1,4 @@
1
- import { O as Point, _ as Key, f as FreeState, m as GraphDefinition, z as View } from "./types-D6b86Rt1.js";
1
+ import { B as View, _ as Key, f as FreeState, k as Point, m as GraphDefinition } from "./types-BaflHDaf.js";
2
2
  import { ReadonlyStore } from "@tanstack/store";
3
3
  interface Endpoints {
4
4
  readonly source: Key;
@@ -40,6 +40,9 @@ interface GraphDragEvent {
40
40
  readonly world: Point;
41
41
  readonly originalEvent: PointerEvent;
42
42
  }
43
+ interface GraphFocusEvent {
44
+ readonly target: GraphTarget | null;
45
+ }
43
46
  type PositionOrigin = "drag" | "api";
44
47
  interface GraphPositionEvent {
45
48
  readonly origin: PositionOrigin;
@@ -56,6 +59,7 @@ interface GraphEvents {
56
59
  readonly dragend: GraphDragEvent;
57
60
  readonly positionchange: GraphPositionEvent;
58
61
  readonly selectionchange: ElementKeys;
62
+ readonly focuschange: GraphFocusEvent;
59
63
  readonly viewchange: {
60
64
  readonly view: View;
61
65
  };
@@ -67,6 +71,7 @@ interface GraphState<S extends string = string> {
67
71
  readonly width: number;
68
72
  readonly height: number;
69
73
  readonly hovered: GraphTarget | null;
74
+ readonly focused: GraphTarget | null;
70
75
  readonly selection: ElementKeys;
71
76
  readonly states: { readonly [K in FreeState<S>]: ElementKeys; };
72
77
  readonly positionsVersion: number;
@@ -95,6 +100,10 @@ interface GraphSelection {
95
100
  set(keys: ElementKeysInput): void;
96
101
  clear(): void;
97
102
  }
103
+ interface GraphFocus {
104
+ get(): GraphTarget | null;
105
+ set(element: GraphElement | null): void;
106
+ }
98
107
  interface GraphStates<N extends string = string> {
99
108
  set(name: N, keys: ElementKeysInput): void;
100
109
  add(name: N, keys: ElementKeysInput): void;
@@ -117,6 +126,7 @@ interface GraphInstance<S extends string = string> {
117
126
  readonly store: GraphStore<S>;
118
127
  readonly view: GraphView;
119
128
  readonly selection: GraphSelection;
129
+ readonly focus: GraphFocus;
120
130
  readonly states: GraphStates<FreeState<S>>;
121
131
  readonly positions: GraphPositions;
122
132
  readonly element: HTMLElement;
@@ -129,5 +139,5 @@ interface GraphInstance<S extends string = string> {
129
139
  destroy(): void;
130
140
  }
131
141
  declare function mountGraph<S extends string = string>(container: HTMLElement, options: MountGraphOptions<S>): GraphInstance<S>;
132
- export { PositionOrigin as C, GraphTargetEvent as S, GraphEventName as _, GraphSelection as a, GraphPositionEvent as b, GraphStore as c, ViewOptions as d, mountGraph as f, GraphEventHandler as g, GraphDragEvent as h, GraphPositions as i, GraphView as l, ElementKeysInput as m, GraphElement as n, GraphState as o, ElementKeys as p, GraphInstance as r, GraphStates as s, FitOptions as t, MountGraphOptions as u, GraphEvents as v, GraphTarget as x, GraphPointerEvent as y };
133
- //# sourceMappingURL=mount-graph-B88WGOQu.d.ts.map
142
+ export { GraphTarget as C, GraphPositionEvent as S, PositionOrigin as T, GraphEventHandler as _, GraphPositions as a, GraphFocusEvent as b, GraphStates as c, MountGraphOptions as d, ViewOptions as f, GraphDragEvent as g, ElementKeysInput as h, GraphInstance as i, GraphStore as l, ElementKeys as m, GraphElement as n, GraphSelection as o, mountGraph as p, GraphFocus as r, GraphState as s, FitOptions as t, GraphView as u, GraphEventName as v, GraphTargetEvent as w, GraphPointerEvent as x, GraphEvents as y };
143
+ //# sourceMappingURL=mount-graph-DQLST9-_.d.ts.map
package/dist/query.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as Key, x as LiveSource } from "./types-D6b86Rt1.js";
1
+ import { _ as Key, x as LiveSource } from "./types-BaflHDaf.js";
2
2
  import { ReadonlyStore } from "@tanstack/store";
3
3
  import { DefaultError, QueryClient, QueryKey, QueryObserverOptions } from "@tanstack/query-core";
4
4
  export interface ExplorationData<TNode, TEdge> {
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { _ as GraphEventName, c as GraphStore, g as GraphEventHandler, m as ElementKeysInput, o as GraphState, r as GraphInstance } from "./mount-graph-B88WGOQu.js";
2
- import { m as GraphDefinition, z as View } from "./types-D6b86Rt1.js";
1
+ import { _ as GraphEventHandler, h as ElementKeysInput, i as GraphInstance, l as GraphStore, s as GraphState, v as GraphEventName } from "./mount-graph-DQLST9-_.js";
2
+ import { B as View, m as GraphDefinition } from "./types-BaflHDaf.js";
3
3
  import { CSSProperties, JSX, ReactNode, Ref } from "react";
4
4
  export interface GraphEventProps {
5
5
  readonly onClick?: GraphEventHandler<"click">;
@@ -12,6 +12,7 @@ export interface GraphEventProps {
12
12
  readonly onDragEnd?: GraphEventHandler<"dragend">;
13
13
  readonly onPositionChange?: GraphEventHandler<"positionchange">;
14
14
  readonly onSelectionChange?: GraphEventHandler<"selectionchange">;
15
+ readonly onFocusChange?: GraphEventHandler<"focuschange">;
15
16
  readonly onViewChange?: GraphEventHandler<"viewchange">;
16
17
  }
17
18
  export interface GraphProps<S extends string = string> extends GraphEventProps {
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as mountGraph } from "./mount-graph-DYOgD_ql.js";
1
+ import { t as mountGraph } from "./mount-graph-CzVfiIte.js";
2
2
  import { createContext, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  // src/react/index.tsx
@@ -13,6 +13,7 @@ const eventProps = {
13
13
  dragend: "onDragEnd",
14
14
  positionchange: "onPositionChange",
15
15
  selectionchange: "onSelectionChange",
16
+ focuschange: "onFocusChange",
16
17
  viewchange: "onViewChange"
17
18
  };
18
19
  const GraphContext = createContext(null);
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../src/react/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n createContext,\n type JSX,\n type ReactNode,\n type Ref,\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react'\nimport type {\n ElementKeysInput,\n GraphEventHandler,\n GraphEventName,\n GraphEvents,\n} from '../host/events'\nimport {\n type GraphInstance,\n type GraphState,\n type GraphStore,\n mountGraph,\n} from '../host/mount-graph'\nimport type { GraphDefinition, View } from '../types'\n\nexport interface GraphEventProps {\n readonly onClick?: GraphEventHandler<'click'>\n readonly onDoubleClick?: GraphEventHandler<'doubleclick'>\n readonly onContextMenu?: GraphEventHandler<'contextmenu'>\n readonly onPointerEnter?: GraphEventHandler<'pointerenter'>\n readonly onPointerLeave?: GraphEventHandler<'pointerleave'>\n readonly onDragStart?: GraphEventHandler<'dragstart'>\n readonly onDrag?: GraphEventHandler<'drag'>\n readonly onDragEnd?: GraphEventHandler<'dragend'>\n readonly onPositionChange?: GraphEventHandler<'positionchange'>\n readonly onSelectionChange?: GraphEventHandler<'selectionchange'>\n readonly onViewChange?: GraphEventHandler<'viewchange'>\n}\n\nconst eventProps: Readonly<Record<GraphEventName, keyof GraphEventProps>> = {\n click: 'onClick',\n doubleclick: 'onDoubleClick',\n contextmenu: 'onContextMenu',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n dragstart: 'onDragStart',\n drag: 'onDrag',\n dragend: 'onDragEnd',\n positionchange: 'onPositionChange',\n selectionchange: 'onSelectionChange',\n viewchange: 'onViewChange',\n}\n\nexport interface GraphProps<S extends string = string> extends GraphEventProps {\n readonly definition: GraphDefinition<S>\n readonly ariaLabel: string\n readonly initialView?: View\n readonly selection?: ElementKeysInput\n readonly className?: string\n readonly style?: CSSProperties\n readonly ref?: Ref<GraphInstance<S> | null>\n readonly children?: ReactNode\n}\n\nconst GraphContext = createContext<GraphInstance | null>(null)\n\nconst fill: CSSProperties = { position: 'absolute', inset: 0 }\n\nfunction useLatest<T>(value: T): { readonly current: T } {\n const latest = useRef(value)\n useLayoutEffect(() => {\n latest.current = value\n })\n return latest\n}\n\nexport function Graph<S extends string = string>(props: GraphProps<S>): JSX.Element {\n const { definition, ariaLabel, selection, className, style, ref, children } = props\n const host = useRef<HTMLDivElement>(null)\n const [graph, setGraph] = useState<GraphInstance<S> | null>(null)\n const latest = useLatest(props)\n\n useLayoutEffect(() => {\n const element = host.current\n if (!element) return\n const initial = latest.current\n const instance = mountGraph(element, {\n definition: initial.definition,\n ariaLabel: initial.ariaLabel,\n ...(initial.initialView ? { initialView: initial.initialView } : {}),\n ...(initial.selection !== undefined\n ? {\n selection: initial.selection,\n onSelectionChange: (next) => latest.current.onSelectionChange?.(next),\n }\n : {}),\n })\n setGraph(instance)\n return () => {\n instance.destroy()\n setGraph(null)\n }\n }, [latest])\n\n useLayoutEffect(() => {\n graph?.update({ definition, ariaLabel, ...(selection !== undefined ? { selection } : {}) })\n }, [graph, definition, ariaLabel, selection])\n\n useEffect(() => {\n if (!graph) return\n const stops = (Object.keys(eventProps) as GraphEventName[]).map((name) =>\n graph.on(name, (event) => {\n if (name === 'selectionchange' && latest.current.selection !== undefined) return\n const handler = latest.current[eventProps[name]] as ((event: unknown) => void) | undefined\n handler?.(event)\n }),\n )\n return () => {\n for (const stop of stops) stop()\n }\n }, [graph, latest])\n\n useImperativeHandle<GraphInstance<S> | null, GraphInstance<S> | null>(ref, () => graph, [graph])\n\n return (\n <div className={className} style={{ position: 'relative', ...style }}>\n <div ref={host} style={fill} />\n {graph ? <GraphContext value={graph}>{children}</GraphContext> : null}\n </div>\n )\n}\n\nexport function useGraph(): GraphInstance {\n const graph = useContext(GraphContext)\n if (!graph) throw new Error('useGraph: call it inside <Graph>')\n return graph\n}\n\ninterface Selected<T> {\n readonly state: GraphState\n readonly selector: (state: GraphState) => T\n readonly value: T\n}\n\nexport interface UseGraphStateOptions<T> {\n readonly compare?: (a: T, b: T) => boolean\n}\n\nexport function useGraphState<T>(\n selector: (state: GraphState) => T,\n options: UseGraphStateOptions<T> = {},\n): T {\n const compare = options.compare ?? Object.is\n const graph = useGraph()\n const cache = useRef<Selected<T> | null>(null)\n const subscribe = useCallback(\n (notify: () => void) => {\n const subscription = graph.store.subscribe(() => notify())\n return () => subscription.unsubscribe()\n },\n [graph],\n )\n const snapshot = (): T => {\n const state = graph.store.get()\n const cached = cache.current\n if (cached && cached.state === state && cached.selector === selector) return cached.value\n const value = selector(state)\n const kept = cached && compare(cached.value, value) ? cached.value : value\n cache.current = { state, selector, value: kept }\n return kept\n }\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n\nexport function useGraphEvent<K extends GraphEventName>(\n name: K,\n handler: GraphEventHandler<K>,\n): void {\n const graph = useGraph()\n const latest = useLatest(handler)\n useEffect(\n () => graph.on(name, (event: GraphEvents[K]) => latest.current(event)),\n [graph, name, latest],\n )\n}\n\nexport type { GraphInstance, GraphState, GraphStore }\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/react/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n createContext,\n type JSX,\n type ReactNode,\n type Ref,\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react'\nimport type {\n ElementKeysInput,\n GraphEventHandler,\n GraphEventName,\n GraphEvents,\n} from '../host/events'\nimport {\n type GraphInstance,\n type GraphState,\n type GraphStore,\n mountGraph,\n} from '../host/mount-graph'\nimport type { GraphDefinition, View } from '../types'\n\nexport interface GraphEventProps {\n readonly onClick?: GraphEventHandler<'click'>\n readonly onDoubleClick?: GraphEventHandler<'doubleclick'>\n readonly onContextMenu?: GraphEventHandler<'contextmenu'>\n readonly onPointerEnter?: GraphEventHandler<'pointerenter'>\n readonly onPointerLeave?: GraphEventHandler<'pointerleave'>\n readonly onDragStart?: GraphEventHandler<'dragstart'>\n readonly onDrag?: GraphEventHandler<'drag'>\n readonly onDragEnd?: GraphEventHandler<'dragend'>\n readonly onPositionChange?: GraphEventHandler<'positionchange'>\n readonly onSelectionChange?: GraphEventHandler<'selectionchange'>\n readonly onFocusChange?: GraphEventHandler<'focuschange'>\n readonly onViewChange?: GraphEventHandler<'viewchange'>\n}\n\nconst eventProps: Readonly<Record<GraphEventName, keyof GraphEventProps>> = {\n click: 'onClick',\n doubleclick: 'onDoubleClick',\n contextmenu: 'onContextMenu',\n pointerenter: 'onPointerEnter',\n pointerleave: 'onPointerLeave',\n dragstart: 'onDragStart',\n drag: 'onDrag',\n dragend: 'onDragEnd',\n positionchange: 'onPositionChange',\n selectionchange: 'onSelectionChange',\n focuschange: 'onFocusChange',\n viewchange: 'onViewChange',\n}\n\nexport interface GraphProps<S extends string = string> extends GraphEventProps {\n readonly definition: GraphDefinition<S>\n readonly ariaLabel: string\n readonly initialView?: View\n readonly selection?: ElementKeysInput\n readonly className?: string\n readonly style?: CSSProperties\n readonly ref?: Ref<GraphInstance<S> | null>\n readonly children?: ReactNode\n}\n\nconst GraphContext = createContext<GraphInstance | null>(null)\n\nconst fill: CSSProperties = { position: 'absolute', inset: 0 }\n\nfunction useLatest<T>(value: T): { readonly current: T } {\n const latest = useRef(value)\n useLayoutEffect(() => {\n latest.current = value\n })\n return latest\n}\n\nexport function Graph<S extends string = string>(props: GraphProps<S>): JSX.Element {\n const { definition, ariaLabel, selection, className, style, ref, children } = props\n const host = useRef<HTMLDivElement>(null)\n const [graph, setGraph] = useState<GraphInstance<S> | null>(null)\n const latest = useLatest(props)\n\n useLayoutEffect(() => {\n const element = host.current\n if (!element) return\n const initial = latest.current\n const instance = mountGraph(element, {\n definition: initial.definition,\n ariaLabel: initial.ariaLabel,\n ...(initial.initialView ? { initialView: initial.initialView } : {}),\n ...(initial.selection !== undefined\n ? {\n selection: initial.selection,\n onSelectionChange: (next) => latest.current.onSelectionChange?.(next),\n }\n : {}),\n })\n setGraph(instance)\n return () => {\n instance.destroy()\n setGraph(null)\n }\n }, [latest])\n\n useLayoutEffect(() => {\n graph?.update({ definition, ariaLabel, ...(selection !== undefined ? { selection } : {}) })\n }, [graph, definition, ariaLabel, selection])\n\n useEffect(() => {\n if (!graph) return\n const stops = (Object.keys(eventProps) as GraphEventName[]).map((name) =>\n graph.on(name, (event) => {\n if (name === 'selectionchange' && latest.current.selection !== undefined) return\n const handler = latest.current[eventProps[name]] as ((event: unknown) => void) | undefined\n handler?.(event)\n }),\n )\n return () => {\n for (const stop of stops) stop()\n }\n }, [graph, latest])\n\n useImperativeHandle<GraphInstance<S> | null, GraphInstance<S> | null>(ref, () => graph, [graph])\n\n return (\n <div className={className} style={{ position: 'relative', ...style }}>\n <div ref={host} style={fill} />\n {graph ? <GraphContext value={graph}>{children}</GraphContext> : null}\n </div>\n )\n}\n\nexport function useGraph(): GraphInstance {\n const graph = useContext(GraphContext)\n if (!graph) throw new Error('useGraph: call it inside <Graph>')\n return graph\n}\n\ninterface Selected<T> {\n readonly state: GraphState\n readonly selector: (state: GraphState) => T\n readonly value: T\n}\n\nexport interface UseGraphStateOptions<T> {\n readonly compare?: (a: T, b: T) => boolean\n}\n\nexport function useGraphState<T>(\n selector: (state: GraphState) => T,\n options: UseGraphStateOptions<T> = {},\n): T {\n const compare = options.compare ?? Object.is\n const graph = useGraph()\n const cache = useRef<Selected<T> | null>(null)\n const subscribe = useCallback(\n (notify: () => void) => {\n const subscription = graph.store.subscribe(() => notify())\n return () => subscription.unsubscribe()\n },\n [graph],\n )\n const snapshot = (): T => {\n const state = graph.store.get()\n const cached = cache.current\n if (cached && cached.state === state && cached.selector === selector) return cached.value\n const value = selector(state)\n const kept = cached && compare(cached.value, value) ? cached.value : value\n cache.current = { state, selector, value: kept }\n return kept\n }\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n\nexport function useGraphEvent<K extends GraphEventName>(\n name: K,\n handler: GraphEventHandler<K>,\n): void {\n const graph = useGraph()\n const latest = useLatest(handler)\n useEffect(\n () => graph.on(name, (event: GraphEvents[K]) => latest.current(event)),\n [graph, name, latest],\n )\n}\n\nexport type { GraphInstance, GraphState, GraphStore }\n"],"mappings":"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"}
@@ -33,7 +33,14 @@ type EdgeDash = "solid" | "dashed" | "dotted";
33
33
  type EdgeArrow = "none" | "source" | "target" | "both";
34
34
  type BadgeCorner = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
35
35
  interface Badge {
36
- readonly text?: string;
36
+ readonly text?: string | number;
37
+ readonly fill?: string;
38
+ readonly color?: string;
39
+ }
40
+ interface NodeImage {
41
+ readonly src: string;
42
+ readonly scale?: number;
43
+ readonly color?: string;
37
44
  }
38
45
  interface LabelOptions<T> {
39
46
  readonly text: Channel<T, string>;
@@ -51,7 +58,7 @@ interface NodeOptions<T> {
51
58
  readonly stroke?: Style<T, string>;
52
59
  readonly strokeWidth?: Style<T, number>;
53
60
  readonly opacity?: Style<T, number>;
54
- readonly image?: Style<T, string | null>;
61
+ readonly image?: Style<T, string | NodeImage | null>;
55
62
  readonly badges?: Readonly<Partial<Record<BadgeCorner, Accessor<T, Badge | null | undefined>>>>;
56
63
  readonly units?: "world" | "screen";
57
64
  }
@@ -152,5 +159,5 @@ interface GraphDefinition<S extends string = string> {
152
159
  readonly interaction: ResolvedInteraction;
153
160
  readonly transitions: ResolvedTransitions;
154
161
  }
155
- export { ResolvedTransitions as A, NodeMark as C, NumberScaleType as D, NumberScale as E, StateStyle as F, StateStyles as I, Style as L, SelectMode as M, SourceChange as N, Point as O, SourceSubscription as P, TransitionOptions as R, Mark as S, NodeShape as T, Key as _, Channel as a, LabelOptions as b, EdgeDash as c, FieldOf as d, FreeState as f, InteractionOptions as g, GraphDefinitionOptions as h, BuiltInState as i, ScalesOptions as j, ResolvedInteraction as k, EdgeMark as l, GraphDefinition as m, Badge as n, ColorScale as o, GraphData as p, BadgeCorner as r, EdgeArrow as s, Accessor as t, EdgeOptions as u, KeyChannel as v, NodeOptions as w, LiveSource as x, KeyFieldOf as y, View as z };
156
- //# sourceMappingURL=types-D6b86Rt1.d.ts.map
162
+ export { ResolvedInteraction as A, View as B, NodeImage as C, NumberScale as D, NodeShape as E, SourceSubscription as F, StateStyle as I, StateStyles as L, ScalesOptions as M, SelectMode as N, NumberScaleType as O, SourceChange as P, Style as R, Mark as S, NodeOptions as T, Key as _, Channel as a, LabelOptions as b, EdgeDash as c, FieldOf as d, FreeState as f, InteractionOptions as g, GraphDefinitionOptions as h, BuiltInState as i, ResolvedTransitions as j, Point as k, EdgeMark as l, GraphDefinition as m, Badge as n, ColorScale as o, GraphData as p, BadgeCorner as r, EdgeArrow as s, Accessor as t, EdgeOptions as u, KeyChannel as v, NodeMark as w, LiveSource as x, KeyFieldOf as y, TransitionOptions as z };
163
+ //# sourceMappingURL=types-BaflHDaf.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bruno00o/graph",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Framework-agnostic, typed graph visualization rendered with WebGL2.",
5
5
  "keywords": [
6
6
  "graph",