@modernrelay/orbit-react 0.2.0 → 0.13.6
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.
- package/dist/components/Navigator.js +16 -1
- package/dist/components/Navigator.js.map +1 -1
- package/dist/components/SimControls.d.ts +3 -3
- package/dist/components/SimControls.js +3 -1
- package/dist/components/SimControls.js.map +1 -1
- package/dist/components/Table.js +1 -1
- package/dist/components/Table.js.map +1 -1
- package/dist/index.d.ts +23 -2
- package/dist/index.js +64 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/Table/model.ts","../../src/components/Table/csv.ts","../../src/components/Table/index.tsx"],"names":[],"mappings":"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","file":"Table.js","sourcesContent":["/**\n * Pure row/column/sort/filter helpers for `<GraphTable>` (§16.10).\n * Framework-free so the §8 sort-coercion contract and the bounded column\n * derivation stay unit-testable without a DOM.\n */\n\nimport { coerceNumeric } from '@modernrelay/orbit-core';\nimport type { GraphEdge, GraphNode } from '@modernrelay/orbit-core';\n\nexport type GraphTableMode = 'nodes' | 'edges';\n\nexport interface GraphTableColumn {\n /** Column key: 'id', 'source'/'target' (edge mode), or an attr key. */\n key: string;\n /** Header text; defaults to the key. Rendered as a TEXT NODE (§14). */\n label?: string;\n}\n\nexport interface GraphTableSort {\n key: string;\n direction: 'asc' | 'desc';\n}\n\n/**\n * One table row. Node rows: `key === id === NodeId`. Edge rows carry the\n * caller edge; `id` is null when the caller supplied no edge id (such rows\n * render and export but cannot write edge selection — the core-synthesized\n * id is not observable through the public surface).\n */\nexport interface GraphTableRowRef {\n /** Stable render identity (node id, edge id, or a positional edge key). */\n key: string;\n /** Public id usable for selection writes; null = unaddressable edge row. */\n id: string | null;\n edge?: GraphEdge<any>;\n}\n\n/** Attr value → display TEXT (never markup): strings verbatim, numbers via\n * String, null/undefined empty, structured values JSON (cycles degrade to\n * the String form) — the Inspector's §14 convention. */\nexport function cellText(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\nexport function nodeCellValue(\n node: GraphNode<any> | undefined,\n id: string,\n key: string,\n): unknown {\n if (key === 'id') return id;\n const attrs = node?.attrs as Record<string, unknown> | undefined;\n return attrs?.[key];\n}\n\nexport function edgeCellValue(edge: GraphEdge<any>, key: string): unknown {\n if (key === 'id') return edge.id ?? '';\n if (key === 'source') return edge.source;\n if (key === 'target') return edge.target;\n const attrs = edge.attrs as Record<string, unknown> | undefined;\n return attrs?.[key];\n}\n\nexport function normalizeColumns(\n pick: readonly (string | GraphTableColumn)[],\n): readonly GraphTableColumn[] {\n return pick.map((c) => (typeof c === 'string' ? { key: c } : c));\n}\n\n/**\n * Derived columns: the identity keys for the mode ('id', plus\n * 'source'/'target' for edges) followed by the union of attr keys over the\n * SAMPLED PREFIX the caller passes (bounded — attrs seen only past the\n * sample do not create columns; use the `columns` prop to pin them).\n * First-seen key order.\n */\nexport function deriveColumns(\n mode: GraphTableMode,\n attrsSample: readonly (Record<string, unknown> | undefined)[],\n): readonly GraphTableColumn[] {\n const keys: string[] = mode === 'edges' ? ['id', 'source', 'target'] : ['id'];\n const seen = new Set(keys);\n for (const attrs of attrsSample) {\n if (attrs === undefined) continue;\n for (const key of Object.keys(attrs)) {\n if (!seen.has(key)) {\n seen.add(key);\n keys.push(key);\n }\n }\n }\n return keys.map((key) => ({ key }));\n}\n\n// ---------------------------------------------------------------------------\n// §8 sort coercion. Three tiers:\n// 0 numeric — values `coerceNumeric` admits (numbers, numeric strings);\n// 1 string — everything else with content (plain strings, booleans,\n// structured values by display text);\n// 2 null — null/undefined, non-finite numbers, empty strings, and the\n// §8 sentinel strings 'NaN'/'Infinity'/'±Infinity'.\n// Tier order is fixed (numeric block, then string block); `direction` flips\n// ordering WITHIN each tier; the null tier is ALWAYS LAST regardless of\n// direction. Ties preserve base row order (stable sort).\n// ---------------------------------------------------------------------------\n\nexport interface SortKey {\n tier: 0 | 1 | 2;\n num: number;\n str: string;\n}\n\nconst NULL_KEY: SortKey = { tier: 2, num: 0, str: '' };\n\n/** Case-insensitive §8 hygiene sentinels (mirrors `coerceNumeric`'s list). */\nfunction isSentinelString(value: string): boolean {\n const lower = value.trim().toLowerCase();\n return (\n lower === '' ||\n lower === 'nan' ||\n lower === 'infinity' ||\n lower === '-infinity' ||\n lower === '+infinity'\n );\n}\n\nexport function sortKeyOf(value: unknown): SortKey {\n if (value === null || value === undefined) return NULL_KEY;\n const num = coerceNumeric(value);\n if (num !== null) return { tier: 0, num, str: '' };\n if (typeof value === 'number') return NULL_KEY; // non-finite\n if (typeof value === 'string') {\n return isSentinelString(value) ? NULL_KEY : { tier: 1, num: 0, str: value };\n }\n return { tier: 1, num: 0, str: cellText(value) };\n}\n\nexport function compareSortKeys(a: SortKey, b: SortKey, direction: 1 | -1): number {\n if (a.tier !== b.tier) {\n if (a.tier === 2) return 1; // nulls last regardless of direction\n if (b.tier === 2) return -1;\n return a.tier - b.tier; // numeric block before string block, fixed\n }\n if (a.tier === 2) return 0;\n if (a.tier === 0) return direction * (a.num < b.num ? -1 : a.num > b.num ? 1 : 0);\n return direction * (a.str < b.str ? -1 : a.str > b.str ? 1 : 0);\n}\n\n/** Case-insensitive substring match over a row's rendered cell texts. */\nexport function textMatches(texts: readonly string[], queryLower: string): boolean {\n for (const text of texts) {\n if (text.toLowerCase().includes(queryLower)) return true;\n }\n return false;\n}\n","/**\n * RFC-4180 CSV serialization with formula-injection neutralization\n * (§16.10 R-16.10-04, S12-T11).\n *\n * Contract:\n * - records join with CRLF (no trailing record terminator);\n * - a cell is quoted iff its text contains a double quote, comma, CR, or\n * LF; embedded double quotes double;\n * - NEUTRALIZATION (default on): a NON-NUMERIC cell whose text begins with\n * `=`, `+`, `-`, `@`, TAB, or CR gets a leading apostrophe — attr values\n * are untrusted (§14/§19) and must never export as live spreadsheet\n * formulas. Cells whose RAW value is a finite number are exempt and\n * serialize as plain numbers (`-5` stays `-5`). Neutralization runs\n * BEFORE quoting, so a prefixed cell still quotes correctly.\n * - header cells are strings and follow the same rules (attr KEYS are\n * untrusted too).\n *\n * The documented opt-out (`neutralizeFormulas: false`) is for callers\n * exporting legitimate formulas; the default stays safe.\n */\n\nimport { cellText } from './model';\n\nconst FORMULA_LEADS = '=+-@\\t\\r';\n\nexport function csvCell(value: unknown, neutralize: boolean): string {\n const numericExempt = typeof value === 'number' && Number.isFinite(value);\n let text = cellText(value);\n if (neutralize && !numericExempt && text.length > 0 && FORMULA_LEADS.includes(text[0]!)) {\n text = `'${text}`;\n }\n if (/[\",\\r\\n]/.test(text)) {\n text = `\"${text.replaceAll('\"', '\"\"')}\"`;\n }\n return text;\n}\n\nexport function toCsvString(\n header: readonly string[],\n rows: readonly (readonly unknown[])[],\n neutralize: boolean,\n): string {\n const records: string[] = [header.map((h) => csvCell(h, neutralize)).join(',')];\n for (const row of rows) {\n records.push(row.map((cell) => csvCell(cell, neutralize)).join(','));\n }\n return records.join('\\r\\n');\n}\n","/**\n * `@modernrelay/orbit-react/components/Table` — `<GraphTable>`, the §16.10\n * virtualized crossfiltered tabular view (S12-T10/T11).\n *\n * Rows are nodes (default) or edges; columns derive from the union of attr\n * keys over a BOUNDED sampled prefix (`columnSample`, default 200) plus the\n * identity keys, or are picked explicitly via `columns`. Every cell renders\n * as a TEXT NODE (§14 untrusted content); `renderCell` replaces cell content.\n *\n * ## Virtualization\n * Hand-rolled windowing (no external dependency): a fixed-height scroll\n * viewport over a full-height spacer with an absolutely positioned window of\n * `ceil(height/rowHeight) + 2*overscan` rows — the mounted row count is\n * BOUNDED regardless of row count (100K rows mount ~30 DOM rows). Row\n * geometry is prop-driven (`rowHeight`, `height`), never measured, so the\n * math is deterministic under jsdom; class hooks drop decorative styles but\n * MECHANICAL styles (viewport height, spacer, window offset, row height,\n * cell flex) always apply — geometry changes go through the props.\n *\n * ## Bidirectional sync\n * - graph → table: rows follow `instance.getVisibleNodeIds()` (scope ∧ §9.1\n * mask) via a store subscription; brushes, filters, legend toggles, and\n * hide/show narrow the rows. An edge row lists iff BOTH endpoints are\n * visible (the public surface exposes no per-edge visibility read —\n * documented approximation).\n * - table → graph: the text/predicate filter registers through the §16.6\n * crossfilter session as a brush on `filterDimension` (default 'table') —\n * the host opts in by configuring an ID-KEYED categorical dimension\n * `{ key: filterDimension, kind: 'categorical', get: (n) => n.id }`; the\n * filter then writes `{ excluded: nonMatchingIds }` over the scene roster\n * (null when the filter clears / matches everything), narrowing the graph\n * AND every other crossfilter view through the standard §9.1 mask fast\n * path, with standard brush history coalescing. DEGRADATION is graceful\n * and documented: no session (host never set `crossfilter`), an unknown\n * dimension key, or edge mode filter rows LOCALLY only — the graph is\n * untouched. A dimension keyed by anything other than row ids degrades the\n * same way (unknown excluded keys mask nothing). Unmounting clears any\n * brush this table wrote.\n * - selection: row click (or Enter/Space) writes the §16.2 SelectionState\n * through `selectNodes`/`selectEdges` (replace; meta/ctrl toggles\n * membership), so controlled selection degrades to intent per §6.4;\n * selected rows carry `aria-selected=\"true\"`.\n *\n * ## Sorting (§8 coercion)\n * Header click cycles none → asc → desc → none. Values sort in three tiers —\n * numeric (`coerceNumeric`-admitted), string (everything else with content),\n * null (null/undefined, non-finite, empty, and the 'NaN'/'Infinity' sentinel\n * strings). Tier order is fixed; direction flips order within a tier; the\n * null tier is ALWAYS LAST regardless of direction.\n *\n * ## CSV export (T11)\n * `exportCsv()` on the forwarded ref returns an RFC-4180 string over the\n * CURRENT filtered + sorted rows and visible columns: CRLF records, quote\n * doubling, and formula-injection neutralization (see ./csv.ts). The\n * documented opt-out is `neutralizeFormulas={false}`.\n *\n * Edge-mode row sourcing (documented v0.10 compromise): the public instance\n * surface exposes no edge roster, so `mode=\"edges\"` reads rows from the\n * `edges` prop — the same array the host passed in its snapshot. Edge rows\n * without a caller-supplied id render and export but cannot write selection.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport type {\n CSSProperties,\n ForwardedRef,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n ReactNode,\n UIEvent,\n} from 'react';\nimport type {\n BrushState,\n GraphEdge,\n GraphNode,\n GraphStoreState,\n SelectionState,\n} from '@modernrelay/orbit-core';\nimport type { AnyGraphInstance } from '../../GraphProvider';\nimport { useResolvedInstance } from '../shared';\nimport {\n cellText,\n compareSortKeys,\n deriveColumns,\n edgeCellValue,\n nodeCellValue,\n normalizeColumns,\n sortKeyOf,\n textMatches,\n} from './model';\nimport type { GraphTableColumn, GraphTableMode, GraphTableRowRef, GraphTableSort } from './model';\nimport { toCsvString } from './csv';\n\nexport type { GraphTableColumn, GraphTableMode, GraphTableRowRef, GraphTableSort } from './model';\n\n/** S0-T02 tree-shake probe: importing `<Graph>` alone must not pull this. */\nexport const __ORBIT_TABLE_SENTINEL__ = 'orbit-react/components/Table';\n\nconst COLUMN_SAMPLE_DEFAULT = 200;\nconst ROW_HEIGHT_DEFAULT = 28;\nconst HEIGHT_DEFAULT = 320;\nconst OVERSCAN_DEFAULT = 8;\n/** Default crossfilter dimension key the table filter registers on. */\nexport const TABLE_FILTER_DIMENSION_DEFAULT = 'table';\n\nexport interface GraphTableCellContext {\n row: GraphTableRowRef;\n /** Resolved node for node rows (undefined for edge rows / unknown ids). */\n node?: GraphNode<any>;\n column: GraphTableColumn;\n value: unknown;\n /** The default display text (always safe to render as a text node). */\n text: string;\n}\n\nexport interface GraphTableHandle {\n /** RFC-4180 CSV over the current filtered+sorted rows (see module doc). */\n exportCsv(): string;\n}\n\nexport interface GraphTableProps {\n /** Explicit instance (multi-instance pages); ambient context otherwise. */\n instance?: AnyGraphInstance;\n /** Row source. Default 'nodes'. */\n mode?: GraphTableMode;\n /** Edge-mode rows (documented compromise — see module doc). */\n edges?: readonly GraphEdge<any>[];\n /** Explicit column pick; replaces derivation entirely. */\n columns?: readonly (string | GraphTableColumn)[];\n /** Bounded derivation prefix (rows sampled for the attr-key union). Default 200. */\n columnSample?: number;\n /** Controlled filter text; uncontrolled via the built-in input otherwise. */\n filterText?: string;\n onFilterTextChange?: (text: string) => void;\n /** Composed AND with the text filter; receives the underlying item. */\n filterPredicate?: (item: GraphNode<any> | GraphEdge<any>) => boolean;\n /** Crossfilter dimension key the filter registers on. Default 'table'. */\n filterDimension?: string;\n /** CSV formula-injection neutralization opt-out. Default true (safe). */\n neutralizeFormulas?: boolean;\n /** Row height in CSS px (mechanical — drives the window math). Default 28. */\n rowHeight?: number;\n /** Scroll viewport height in CSS px (mechanical). Default 320. */\n height?: number;\n /** Extra rows mounted on each side of the viewport. Default 8. */\n overscan?: number;\n /** Replaces default cell content (rendered inside the cell element). */\n renderCell?: (ctx: GraphTableCellContext) => ReactNode;\n /** Accessible name of the table. Default 'Graph table'. */\n label?: string;\n /** Class hook for the root; providing it drops the decorative styles. */\n className?: string;\n style?: CSSProperties;\n /** Class hook for body rows; providing it drops their decorative styles. */\n rowClassName?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Store subscriptions\n// ---------------------------------------------------------------------------\n\n/**\n * Version string that changes whenever the row model could: revisions,\n * visible counts, accepted counts, status, and session availability. The\n * session listener re-attaches on every store publication (the\n * _shared/crossfilter convention — engine rebuilds swap subscribers).\n */\nfunction useTableVersion(instance: AnyGraphInstance): string {\n const subscribe = useCallback(\n (onChange: () => void) => {\n let sessionUnsub: (() => void) | null = null;\n const attach = (): void => {\n sessionUnsub?.();\n sessionUnsub = null;\n const session = instance.getCrossfilterSession();\n if (session !== null) sessionUnsub = session.subscribe(onChange);\n };\n attach();\n const storeUnsub = instance.store.subscribe(() => {\n attach();\n onChange();\n });\n return () => {\n storeUnsub();\n sessionUnsub?.();\n sessionUnsub = null;\n };\n },\n [instance],\n );\n const getSnapshot = useCallback((): string => {\n const s: GraphStoreState = instance.store.getState();\n const hasSession = instance.getCrossfilterSession() !== null ? 1 : 0;\n return `${s.status}:${s.revisions.model}:${s.revisions.scope}:${s.revisions.render}:${s.visible.nodes}:${s.visible.edges}:${s.nodeCount}:${s.edgeCount}:${hasSession}`;\n }, [instance]);\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/** The store keeps `selection` referentially stable across unrelated\n * publishes, so the raw field is a valid useSyncExternalStore snapshot. */\nfunction useSelection(instance: AnyGraphInstance): SelectionState {\n const subscribe = useCallback(\n (onChange: () => void) => instance.store.subscribe(onChange),\n [instance],\n );\n const getSnapshot = useCallback(\n (): SelectionState => instance.store.getState().selection,\n [instance],\n );\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ---------------------------------------------------------------------------\n// Styling defaults (decorative styles drop when the class hooks are given;\n// mechanical geometry always applies — see module doc).\n// ---------------------------------------------------------------------------\n\nconst ROOT_STYLE: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n padding: 8,\n borderRadius: 8,\n background: 'rgba(23, 25, 32, 0.96)',\n border: '1px solid rgba(255, 255, 255, 0.14)',\n color: '#e8eaf0',\n font: '12px/1.4 system-ui, sans-serif',\n};\nconst TOOLBAR_STYLE: CSSProperties = { display: 'flex', alignItems: 'center', gap: 8 };\nconst FILTER_STYLE: CSSProperties = {\n flex: 1,\n minWidth: 0,\n background: 'rgba(255, 255, 255, 0.06)',\n border: '1px solid rgba(255, 255, 255, 0.14)',\n borderRadius: 6,\n color: 'inherit',\n font: 'inherit',\n padding: '3px 8px',\n};\nconst COUNT_STYLE: CSSProperties = { opacity: 0.65, whiteSpace: 'nowrap' };\nconst HEADER_ROW_STYLE: CSSProperties = { borderBottom: '1px solid rgba(255, 255, 255, 0.2)' };\nconst HEADER_BUTTON_STYLE: CSSProperties = {\n appearance: 'none',\n background: 'transparent',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n font: 'inherit',\n fontWeight: 600,\n padding: '2px 4px',\n textAlign: 'left',\n width: '100%',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\nconst ROW_STYLE: CSSProperties = { cursor: 'pointer' };\nconst ROW_SELECTED_STYLE: CSSProperties = {\n ...ROW_STYLE,\n background: 'rgba(122, 162, 255, 0.22)',\n};\nconst CELL_STYLE: CSSProperties = {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n padding: '0 4px',\n};\nconst EMPTY_STYLE: CSSProperties = { fontStyle: 'italic', opacity: 0.8, padding: 4 };\n\n/** Mechanical (always applied) flex geometry for header/body cells. */\nconst CELL_MECHANICS: CSSProperties = { flex: 1, minWidth: 0 };\n\nfunction GraphTableInner(\n props: GraphTableProps,\n ref: ForwardedRef<GraphTableHandle>,\n): ReactElement {\n const instance = useResolvedInstance(props.instance, '<GraphTable>');\n const version = useTableVersion(instance);\n const selection = useSelection(instance);\n\n const mode: GraphTableMode = props.mode ?? 'nodes';\n const rowHeight = props.rowHeight ?? ROW_HEIGHT_DEFAULT;\n const height = props.height ?? HEIGHT_DEFAULT;\n const overscan = props.overscan ?? OVERSCAN_DEFAULT;\n const dimensionKey = props.filterDimension ?? TABLE_FILTER_DIMENSION_DEFAULT;\n const neutralize = props.neutralizeFormulas ?? true;\n const predicate = props.filterPredicate;\n\n const [internalFilter, setInternalFilter] = useState('');\n const filterText = props.filterText ?? internalFilter;\n const query = filterText.trim().toLowerCase();\n const [sort, setSort] = useState<GraphTableSort | null>(null);\n const [scrollTop, setScrollTop] = useState(0);\n\n // --- row model -------------------------------------------------------------\n\n const edgesProp = props.edges;\n const baseRows = useMemo<readonly GraphTableRowRef[]>(() => {\n void version; // rebuild on every relevant store publication\n if (mode === 'edges') {\n const visible = new Set(instance.getVisibleNodeIds());\n const out: GraphTableRowRef[] = [];\n (edgesProp ?? []).forEach((edge, i) => {\n if (!visible.has(edge.source) || !visible.has(edge.target)) return;\n if (edge.id !== undefined) out.push({ key: edge.id, id: edge.id, edge });\n else out.push({ key: `${i}:${edge.source}→${edge.target}`, id: null, edge });\n });\n return out;\n }\n return instance.getVisibleNodeIds().map((id) => ({ key: id, id }));\n }, [instance, version, mode, edgesProp]);\n\n const columnSample = props.columnSample ?? COLUMN_SAMPLE_DEFAULT;\n const columnsProp = props.columns;\n const columns = useMemo<readonly GraphTableColumn[]>(() => {\n if (columnsProp !== undefined) return normalizeColumns(columnsProp);\n const sample = baseRows.slice(0, columnSample).map((row) => {\n return row.edge !== undefined\n ? (row.edge.attrs as Record<string, unknown> | undefined)\n : ((instance.getNode(row.key) as GraphNode<any> | undefined)?.attrs as\n | Record<string, unknown>\n | undefined);\n });\n return deriveColumns(mode, sample);\n }, [instance, baseRows, mode, columnsProp, columnSample]);\n\n const valueOf = useCallback(\n (row: GraphTableRowRef, key: string): unknown =>\n row.edge !== undefined\n ? edgeCellValue(row.edge, key)\n : nodeCellValue(instance.getNode(row.key) as GraphNode<any> | undefined, row.key, key),\n [instance],\n );\n\n /** Text/predicate match for one row over the visible columns. */\n const matchesRow = useCallback(\n (row: GraphTableRowRef): boolean => {\n if (predicate !== undefined) {\n const item =\n row.edge !== undefined\n ? row.edge\n : (instance.getNode(row.key) as GraphNode<any> | undefined);\n if (item === undefined || !predicate(item)) return false;\n }\n if (query === '') return true;\n return textMatches(\n columns.map((col) => cellText(valueOf(row, col.key))),\n query,\n );\n },\n [instance, predicate, query, columns, valueOf],\n );\n\n const filterActive = query !== '' || predicate !== undefined;\n const filteredRows = useMemo<readonly GraphTableRowRef[]>(\n () => (filterActive ? baseRows.filter(matchesRow) : baseRows),\n [baseRows, filterActive, matchesRow],\n );\n\n const sortedRows = useMemo<readonly GraphTableRowRef[]>(() => {\n if (sort === null || !columns.some((c) => c.key === sort.key)) return filteredRows;\n const direction: 1 | -1 = sort.direction === 'asc' ? 1 : -1;\n const decorated = filteredRows.map((row) => ({\n row,\n key: sortKeyOf(valueOf(row, sort.key)),\n }));\n decorated.sort((a, b) => compareSortKeys(a.key, b.key, direction)); // stable → base-order ties\n return decorated.map((d) => d.row);\n }, [filteredRows, sort, columns, valueOf]);\n\n // --- table → graph: crossfilter registration (see module doc) ---------------\n\n /** Set once this table wrote a non-null brush; unmount clears it. */\n const wroteBrushRef = useRef<{ instance: AnyGraphInstance; key: string } | null>(null);\n\n useEffect(() => {\n if (mode !== 'nodes') return;\n const session = instance.getCrossfilterSession();\n if (session === null) return;\n try {\n session.getBrush(dimensionKey);\n } catch {\n return; // dimension not configured — degrade to local-only filtering\n }\n let brush: BrushState = null;\n if (filterActive) {\n const excluded: string[] = [];\n for (const id of instance.getSceneNodeIds()) {\n if (!matchesRow({ key: id, id })) excluded.push(id);\n }\n if (excluded.length > 0) brush = { excluded };\n }\n if (brush !== null) wroteBrushRef.current = { instance, key: dimensionKey };\n // Deep-equal brushes no-op inside the engine, so re-runs are cheap.\n void session.setBrush(dimensionKey, brush).catch(() => undefined);\n }, [instance, version, mode, dimensionKey, filterActive, matchesRow]);\n\n useEffect(\n () => () => {\n const wrote = wroteBrushRef.current;\n if (wrote === null) return;\n wroteBrushRef.current = null;\n const session = wrote.instance.getCrossfilterSession();\n if (session !== null) void session.setBrush(wrote.key, null).catch(() => undefined);\n },\n [],\n );\n\n // --- selection ---------------------------------------------------------------\n\n const selectedNodes = useMemo(() => new Set(selection.nodeIds), [selection]);\n const selectedEdges = useMemo(() => new Set(selection.edgeIds), [selection]);\n const isSelected = (row: GraphTableRowRef): boolean =>\n row.edge !== undefined\n ? row.id !== null && selectedEdges.has(row.id)\n : selectedNodes.has(row.key);\n\n const activateRow = (row: GraphTableRowRef, additive: boolean): void => {\n if (row.edge !== undefined) {\n if (row.id === null) return; // unaddressable (no caller edge id)\n const id = row.id;\n if (additive) {\n const current = selection.edgeIds;\n instance.selectEdges(\n current.includes(id) ? current.filter((e) => e !== id) : [...current, id],\n );\n } else {\n instance.selectEdges([id]);\n }\n return;\n }\n if (additive) {\n const current = selection.nodeIds;\n instance.selectNodes(\n current.includes(row.key) ? current.filter((n) => n !== row.key) : [...current, row.key],\n );\n } else {\n instance.selectNodes([row.key]);\n }\n };\n\n // --- CSV export (T11) ----------------------------------------------------------\n\n const exportStateRef = useRef({ columns, rows: sortedRows, valueOf, neutralize });\n exportStateRef.current = { columns, rows: sortedRows, valueOf, neutralize };\n useImperativeHandle(\n ref,\n (): GraphTableHandle => ({\n exportCsv: (): string => {\n const s = exportStateRef.current;\n return toCsvString(\n s.columns.map((col) => col.label ?? col.key),\n s.rows.map((row) => s.columns.map((col) => s.valueOf(row, col.key))),\n s.neutralize,\n );\n },\n }),\n [],\n );\n\n // --- windowing -----------------------------------------------------------------\n\n const total = sortedRows.length;\n const first = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);\n const windowSize = Math.ceil(height / rowHeight) + overscan * 2;\n const windowRows = sortedRows.slice(first, first + windowSize);\n\n const onScroll = (e: UIEvent<HTMLDivElement>): void => {\n setScrollTop(e.currentTarget.scrollTop);\n };\n\n const cycleSort = (key: string): void => {\n setSort((prev) => {\n if (prev === null || prev.key !== key) return { key, direction: 'asc' };\n if (prev.direction === 'asc') return { key, direction: 'desc' };\n return null;\n });\n };\n\n const onFilterChange = (text: string): void => {\n if (props.filterText === undefined) setInternalFilter(text);\n props.onFilterTextChange?.(text);\n };\n\n const styled = props.className === undefined;\n const rowStyled = props.rowClassName === undefined;\n const label = props.label ?? 'Graph table';\n\n const renderRow = (row: GraphTableRowRef, index: number): ReactElement => {\n const selected = isSelected(row);\n const node =\n row.edge === undefined\n ? (instance.getNode(row.key) as GraphNode<any> | undefined)\n : undefined;\n const mechanics: CSSProperties = {\n height: rowHeight,\n display: 'flex',\n alignItems: 'center',\n boxSizing: 'border-box',\n };\n return (\n <div\n key={row.key}\n role=\"row\"\n aria-rowindex={first + index + 2}\n aria-selected={selected}\n data-orbit-table-row={row.key}\n tabIndex={0}\n className={props.rowClassName}\n style={\n rowStyled ? { ...mechanics, ...(selected ? ROW_SELECTED_STYLE : ROW_STYLE) } : mechanics\n }\n onClick={(e: MouseEvent<HTMLDivElement>) => {\n activateRow(row, e.metaKey || e.ctrlKey);\n }}\n onKeyDown={(e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'Enter' && e.key !== ' ') return;\n e.preventDefault();\n activateRow(row, e.metaKey || e.ctrlKey);\n }}\n >\n {columns.map((col) => {\n const value = valueOf(row, col.key);\n const text = cellText(value);\n const ctx: GraphTableCellContext =\n node !== undefined\n ? { row, node, column: col, value, text }\n : { row, column: col, value, text };\n return (\n <div\n key={col.key}\n role=\"cell\"\n data-orbit-table-cell={col.key}\n style={styled ? { ...CELL_MECHANICS, ...CELL_STYLE } : CELL_MECHANICS}\n >\n {props.renderCell !== undefined ? props.renderCell(ctx) : text}\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div\n data-orbit-table={mode}\n role=\"group\"\n aria-label={label}\n className={props.className}\n style={styled ? { ...ROOT_STYLE, ...props.style } : props.style}\n >\n <div data-orbit-table-toolbar=\"\" style={styled ? TOOLBAR_STYLE : undefined}>\n <input\n type=\"text\"\n data-orbit-table-filter=\"\"\n aria-label=\"Filter rows\"\n value={filterText}\n style={styled ? FILTER_STYLE : undefined}\n onChange={(e) => {\n onFilterChange(e.currentTarget.value);\n }}\n />\n <span data-orbit-table-count=\"\" style={styled ? COUNT_STYLE : undefined}>\n {`${total} of ${baseRows.length} rows`}\n </span>\n </div>\n <div role=\"table\" aria-label={`${label} rows`} aria-rowcount={total + 1}>\n <div role=\"rowgroup\">\n <div\n role=\"row\"\n aria-rowindex={1}\n data-orbit-table-head=\"\"\n style={styled ? { display: 'flex', ...HEADER_ROW_STYLE } : { display: 'flex' }}\n >\n {columns.map((col) => {\n const active = sort !== null && sort.key === col.key;\n const ariaSort = active\n ? sort.direction === 'asc'\n ? 'ascending'\n : 'descending'\n : 'none';\n return (\n <div\n key={col.key}\n role=\"columnheader\"\n aria-sort={ariaSort}\n data-orbit-table-header={col.key}\n style={CELL_MECHANICS}\n >\n <button\n type=\"button\"\n data-orbit-table-sort={col.key}\n style={styled ? HEADER_BUTTON_STYLE : undefined}\n onClick={() => {\n cycleSort(col.key);\n }}\n >\n {col.label ?? col.key}\n </button>\n </div>\n );\n })}\n </div>\n </div>\n <div\n role=\"rowgroup\"\n data-orbit-table-viewport=\"\"\n onScroll={onScroll}\n style={{ height, overflowY: 'auto', position: 'relative' }}\n >\n {total === 0 ? (\n <div data-orbit-table-empty=\"\" style={styled ? EMPTY_STYLE : undefined}>\n No rows\n </div>\n ) : (\n <div\n data-orbit-table-spacer=\"\"\n style={{ height: total * rowHeight, position: 'relative' }}\n >\n <div\n data-orbit-table-window=\"\"\n style={{ position: 'absolute', top: first * rowHeight, left: 0, right: 0 }}\n >\n {windowRows.map((row, i) => renderRow(row, i))}\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const GraphTable = forwardRef<GraphTableHandle, GraphTableProps>(GraphTableInner);\nGraphTable.displayName = 'GraphTable';\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/Table/model.ts","../../src/components/Table/csv.ts","../../src/components/Table/index.tsx"],"names":[],"mappings":"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","file":"Table.js","sourcesContent":["/**\n * Pure row/column/sort/filter helpers for `<GraphTable>` (§16.10).\n * Framework-free so the §8 sort-coercion contract and the bounded column\n * derivation stay unit-testable without a DOM.\n */\n\nimport { coerceNumeric } from '@modernrelay/orbit-core';\nimport type { GraphEdge, GraphNode } from '@modernrelay/orbit-core';\n\nexport type GraphTableMode = 'nodes' | 'edges';\n\nexport interface GraphTableColumn {\n /** Column key: 'id', 'source'/'target' (edge mode), or an attr key. */\n key: string;\n /** Header text; defaults to the key. Rendered as a TEXT NODE (§14). */\n label?: string;\n}\n\nexport interface GraphTableSort {\n key: string;\n direction: 'asc' | 'desc';\n}\n\n/**\n * One table row. Node rows: `key === id === NodeId`. Edge rows carry the\n * caller edge; `id` is null when the caller supplied no edge id (such rows\n * render and export but cannot write edge selection — the core-synthesized\n * id is not observable through the public surface).\n */\nexport interface GraphTableRowRef {\n /** Stable render identity (node id, edge id, or a positional edge key). */\n key: string;\n /** Public id usable for selection writes; null = unaddressable edge row. */\n id: string | null;\n edge?: GraphEdge<any>;\n}\n\n/** Attr value → display TEXT (never markup): strings verbatim, numbers via\n * String, null/undefined empty, structured values JSON (cycles degrade to\n * the String form) — the Inspector's §14 convention. */\nexport function cellText(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\nexport function nodeCellValue(\n node: GraphNode<any> | undefined,\n id: string,\n key: string,\n): unknown {\n if (key === 'id') return id;\n const attrs = node?.attrs as Record<string, unknown> | undefined;\n return attrs?.[key];\n}\n\nexport function edgeCellValue(edge: GraphEdge<any>, key: string): unknown {\n if (key === 'id') return edge.id ?? '';\n if (key === 'source') return edge.source;\n if (key === 'target') return edge.target;\n const attrs = edge.attrs as Record<string, unknown> | undefined;\n return attrs?.[key];\n}\n\nexport function normalizeColumns(\n pick: readonly (string | GraphTableColumn)[],\n): readonly GraphTableColumn[] {\n return pick.map((c) => (typeof c === 'string' ? { key: c } : c));\n}\n\n/**\n * Derived columns: the identity keys for the mode ('id', plus\n * 'source'/'target' for edges) followed by the union of attr keys over the\n * SAMPLED PREFIX the caller passes (bounded — attrs seen only past the\n * sample do not create columns; use the `columns` prop to pin them).\n * First-seen key order.\n */\nexport function deriveColumns(\n mode: GraphTableMode,\n attrsSample: readonly (Record<string, unknown> | undefined)[],\n): readonly GraphTableColumn[] {\n const keys: string[] = mode === 'edges' ? ['id', 'source', 'target'] : ['id'];\n const seen = new Set(keys);\n for (const attrs of attrsSample) {\n if (attrs === undefined) continue;\n for (const key of Object.keys(attrs)) {\n if (!seen.has(key)) {\n seen.add(key);\n keys.push(key);\n }\n }\n }\n return keys.map((key) => ({ key }));\n}\n\n// ---------------------------------------------------------------------------\n// §8 sort coercion. Three tiers:\n// 0 numeric — values `coerceNumeric` admits (numbers, numeric strings);\n// 1 string — everything else with content (plain strings, booleans,\n// structured values by display text);\n// 2 null — null/undefined, non-finite numbers, empty strings, and the\n// §8 sentinel strings 'NaN'/'Infinity'/'±Infinity'.\n// Tier order is fixed (numeric block, then string block); `direction` flips\n// ordering WITHIN each tier; the null tier is ALWAYS LAST regardless of\n// direction. Ties preserve base row order (stable sort).\n// ---------------------------------------------------------------------------\n\nexport interface SortKey {\n tier: 0 | 1 | 2;\n num: number;\n str: string;\n}\n\nconst NULL_KEY: SortKey = { tier: 2, num: 0, str: '' };\n\n/** Case-insensitive §8 hygiene sentinels (mirrors `coerceNumeric`'s list). */\nfunction isSentinelString(value: string): boolean {\n const lower = value.trim().toLowerCase();\n return (\n lower === '' ||\n lower === 'nan' ||\n lower === 'infinity' ||\n lower === '-infinity' ||\n lower === '+infinity'\n );\n}\n\nexport function sortKeyOf(value: unknown): SortKey {\n if (value === null || value === undefined) return NULL_KEY;\n const num = coerceNumeric(value);\n if (num !== null) return { tier: 0, num, str: '' };\n if (typeof value === 'number') return NULL_KEY; // non-finite\n if (typeof value === 'string') {\n return isSentinelString(value) ? NULL_KEY : { tier: 1, num: 0, str: value };\n }\n return { tier: 1, num: 0, str: cellText(value) };\n}\n\nexport function compareSortKeys(a: SortKey, b: SortKey, direction: 1 | -1): number {\n if (a.tier !== b.tier) {\n if (a.tier === 2) return 1; // nulls last regardless of direction\n if (b.tier === 2) return -1;\n return a.tier - b.tier; // numeric block before string block, fixed\n }\n if (a.tier === 2) return 0;\n if (a.tier === 0) return direction * (a.num < b.num ? -1 : a.num > b.num ? 1 : 0);\n return direction * (a.str < b.str ? -1 : a.str > b.str ? 1 : 0);\n}\n\n/** Case-insensitive substring match over a row's rendered cell texts. */\nexport function textMatches(texts: readonly string[], queryLower: string): boolean {\n for (const text of texts) {\n if (text.toLowerCase().includes(queryLower)) return true;\n }\n return false;\n}\n","/**\n * RFC-4180 CSV serialization with formula-injection neutralization\n * (§16.10 R-16.10-04, S12-T11).\n *\n * Contract:\n * - records join with CRLF (no trailing record terminator);\n * - a cell is quoted iff its text contains a double quote, comma, CR, or\n * LF; embedded double quotes double;\n * - NEUTRALIZATION (default on): a NON-NUMERIC cell whose text begins with\n * `=`, `+`, `-`, `@`, TAB, or CR gets a leading apostrophe — attr values\n * are untrusted (§14/§19) and must never export as live spreadsheet\n * formulas. Cells whose RAW value is a finite number are exempt and\n * serialize as plain numbers (`-5` stays `-5`). Neutralization runs\n * BEFORE quoting, so a prefixed cell still quotes correctly.\n * - header cells are strings and follow the same rules (attr KEYS are\n * untrusted too).\n *\n * The documented opt-out (`neutralizeFormulas: false`) is for callers\n * exporting legitimate formulas; the default stays safe.\n */\n\nimport { cellText } from './model';\n\nconst FORMULA_LEADS = '=+-@\\t\\r';\n\nexport function csvCell(value: unknown, neutralize: boolean): string {\n const numericExempt = typeof value === 'number' && Number.isFinite(value);\n let text = cellText(value);\n if (neutralize && !numericExempt && text.length > 0 && FORMULA_LEADS.includes(text[0]!)) {\n text = `'${text}`;\n }\n if (/[\",\\r\\n]/.test(text)) {\n text = `\"${text.replaceAll('\"', '\"\"')}\"`;\n }\n return text;\n}\n\nexport function toCsvString(\n header: readonly string[],\n rows: readonly (readonly unknown[])[],\n neutralize: boolean,\n): string {\n const records: string[] = [header.map((h) => csvCell(h, neutralize)).join(',')];\n for (const row of rows) {\n records.push(row.map((cell) => csvCell(cell, neutralize)).join(','));\n }\n return records.join('\\r\\n');\n}\n","/**\n * `@modernrelay/orbit-react/components/Table` — `<GraphTable>`, the §16.10\n * virtualized crossfiltered tabular view (S12-T10/T11).\n *\n * Rows are nodes (default) or edges; columns derive from the union of attr\n * keys over a BOUNDED sampled prefix (`columnSample`, default 200) plus the\n * identity keys, or are picked explicitly via `columns`. Every cell renders\n * as a TEXT NODE (§14 untrusted content); `renderCell` replaces cell content.\n *\n * ## Virtualization\n * Hand-rolled windowing (no external dependency): a fixed-height scroll\n * viewport over a full-height spacer with an absolutely positioned window of\n * `ceil(height/rowHeight) + 2*overscan` rows — the mounted row count is\n * BOUNDED regardless of row count (100K rows mount ~30 DOM rows). Row\n * geometry is prop-driven (`rowHeight`, `height`), never measured, so the\n * math is deterministic under jsdom; class hooks drop decorative styles but\n * MECHANICAL styles (viewport height, spacer, window offset, row height,\n * cell flex) always apply — geometry changes go through the props.\n *\n * ## Bidirectional sync\n * - graph → table: rows follow `instance.getVisibleNodeIds()` (scope ∧ §9.1\n * mask) via a store subscription; brushes, filters, legend toggles, and\n * hide/show narrow the rows. An edge row lists iff BOTH endpoints are\n * visible (the public surface exposes no per-edge visibility read —\n * documented approximation).\n * - table → graph: the text/predicate filter registers through the §16.6\n * crossfilter session as a brush on `filterDimension` (default 'table') —\n * the host opts in by configuring an ID-KEYED categorical dimension\n * `{ key: filterDimension, kind: 'categorical', get: (n) => n.id }`; the\n * filter then writes `{ excluded: nonMatchingIds }` over the scene roster\n * (null when the filter clears / matches everything), narrowing the graph\n * AND every other crossfilter view through the standard §9.1 mask fast\n * path, with standard brush history coalescing. DEGRADATION is graceful\n * and documented: no session (host never set `crossfilter`), an unknown\n * dimension key, or edge mode filter rows LOCALLY only — the graph is\n * untouched. A dimension keyed by anything other than row ids degrades the\n * same way (unknown excluded keys mask nothing). Unmounting clears any\n * brush this table wrote.\n * - selection: row click (or Enter/Space) writes the §16.2 SelectionState\n * through `selectNodes`/`selectEdges` (replace; meta/ctrl toggles\n * membership), so controlled selection degrades to intent per §6.4;\n * selected rows carry `aria-selected=\"true\"`.\n *\n * ## Sorting (§8 coercion)\n * Header click cycles none → asc → desc → none. Values sort in three tiers —\n * numeric (`coerceNumeric`-admitted), string (everything else with content),\n * null (null/undefined, non-finite, empty, and the 'NaN'/'Infinity' sentinel\n * strings). Tier order is fixed; direction flips order within a tier; the\n * null tier is ALWAYS LAST regardless of direction.\n *\n * ## CSV export (T11)\n * `exportCsv()` on the forwarded ref returns an RFC-4180 string over the\n * CURRENT filtered + sorted rows and visible columns: CRLF records, quote\n * doubling, and formula-injection neutralization (see ./csv.ts). The\n * documented opt-out is `neutralizeFormulas={false}`.\n *\n * Edge-mode row sourcing (documented v0.10 compromise): the public instance\n * surface exposes no edge roster, so `mode=\"edges\"` reads rows from the\n * `edges` prop — the same array the host passed in its snapshot. Edge rows\n * without a caller-supplied id render and export but cannot write selection.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport type {\n CSSProperties,\n ForwardedRef,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n ReactNode,\n UIEvent,\n} from 'react';\nimport type {\n BrushState,\n GraphEdge,\n GraphNode,\n GraphStoreState,\n SelectionState,\n} from '@modernrelay/orbit-core';\nimport type { AnyGraphInstance } from '../../GraphProvider';\nimport { useResolvedInstance } from '../shared';\nimport {\n cellText,\n compareSortKeys,\n deriveColumns,\n edgeCellValue,\n nodeCellValue,\n normalizeColumns,\n sortKeyOf,\n textMatches,\n} from './model';\nimport type { GraphTableColumn, GraphTableMode, GraphTableRowRef, GraphTableSort } from './model';\nimport { toCsvString } from './csv';\n\nexport type { GraphTableColumn, GraphTableMode, GraphTableRowRef, GraphTableSort } from './model';\n\n/** S0-T02 tree-shake probe: importing `<Graph>` alone must not pull this. */\nexport const __ORBIT_TABLE_SENTINEL__ = 'orbit-react/components/Table';\n\nconst COLUMN_SAMPLE_DEFAULT = 200;\nconst ROW_HEIGHT_DEFAULT = 28;\nconst HEIGHT_DEFAULT = 320;\nconst OVERSCAN_DEFAULT = 8;\n/** Default crossfilter dimension key the table filter registers on. */\nexport const TABLE_FILTER_DIMENSION_DEFAULT = 'table';\n\nexport interface GraphTableCellContext {\n row: GraphTableRowRef;\n /** Resolved node for node rows (undefined for edge rows / unknown ids). */\n node?: GraphNode<any>;\n column: GraphTableColumn;\n value: unknown;\n /** The default display text (always safe to render as a text node). */\n text: string;\n}\n\nexport interface GraphTableHandle {\n /** RFC-4180 CSV over the current filtered+sorted rows (see module doc). */\n exportCsv(): string;\n}\n\nexport interface GraphTableProps {\n /** Explicit instance (multi-instance pages); ambient context otherwise. */\n instance?: AnyGraphInstance;\n /** Row source. Default 'nodes'. */\n mode?: GraphTableMode;\n /** Edge-mode rows (documented compromise — see module doc). */\n edges?: readonly GraphEdge<any>[];\n /** Explicit column pick; replaces derivation entirely. */\n columns?: readonly (string | GraphTableColumn)[];\n /** Bounded derivation prefix (rows sampled for the attr-key union). Default 200. */\n columnSample?: number;\n /** Controlled filter text; uncontrolled via the built-in input otherwise. */\n filterText?: string;\n onFilterTextChange?: (text: string) => void;\n /** Composed AND with the text filter; receives the underlying item. */\n filterPredicate?: (item: GraphNode<any> | GraphEdge<any>) => boolean;\n /** Crossfilter dimension key the filter registers on. Default 'table'. */\n filterDimension?: string;\n /** CSV formula-injection neutralization opt-out. Default true (safe). */\n neutralizeFormulas?: boolean;\n /** Row height in CSS px (mechanical — drives the window math). Default 28. */\n rowHeight?: number;\n /** Scroll viewport height in CSS px (mechanical). Default 320. */\n height?: number;\n /** Extra rows mounted on each side of the viewport. Default 8. */\n overscan?: number;\n /** Replaces default cell content (rendered inside the cell element). */\n renderCell?: (ctx: GraphTableCellContext) => ReactNode;\n /** Accessible name of the table. Default 'Graph table'. */\n label?: string;\n /** Class hook for the root; providing it drops the decorative styles. */\n className?: string;\n style?: CSSProperties;\n /** Class hook for body rows; providing it drops their decorative styles. */\n rowClassName?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Store subscriptions\n// ---------------------------------------------------------------------------\n\n/**\n * Version string that changes whenever the row model could: revisions,\n * visible counts, accepted counts, status, and session availability. The\n * session listener re-attaches on every store publication (the\n * _shared/crossfilter convention — engine rebuilds swap subscribers).\n */\nfunction useTableVersion(instance: AnyGraphInstance): string {\n const subscribe = useCallback(\n (onChange: () => void) => {\n let sessionUnsub: (() => void) | null = null;\n const attach = (): void => {\n sessionUnsub?.();\n sessionUnsub = null;\n const session = instance.getCrossfilterSession();\n if (session !== null) sessionUnsub = session.subscribe(onChange);\n };\n attach();\n const storeUnsub = instance.store.subscribe(() => {\n attach();\n onChange();\n });\n return () => {\n storeUnsub();\n sessionUnsub?.();\n sessionUnsub = null;\n };\n },\n [instance],\n );\n const getSnapshot = useCallback((): string => {\n const s: GraphStoreState = instance.store.getState();\n const hasSession = instance.getCrossfilterSession() !== null ? 1 : 0;\n return `${s.status}:${s.revisions.model}:${s.revisions.scope}:${s.revisions.render}:${s.visible.nodes}:${s.visible.edges}:${s.nodeCount}:${s.edgeCount}:${hasSession}`;\n }, [instance]);\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/** The store keeps `selection` referentially stable across unrelated\n * publishes, so the raw field is a valid useSyncExternalStore snapshot. */\nfunction useSelection(instance: AnyGraphInstance): SelectionState {\n const subscribe = useCallback(\n (onChange: () => void) => instance.store.subscribe(onChange),\n [instance],\n );\n const getSnapshot = useCallback(\n (): SelectionState => instance.store.getState().selection,\n [instance],\n );\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ---------------------------------------------------------------------------\n// Styling defaults (decorative styles drop when the class hooks are given;\n// mechanical geometry always applies — see module doc).\n// ---------------------------------------------------------------------------\n\nconst ROOT_STYLE: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n padding: 8,\n borderRadius: 8,\n background: 'rgba(23, 25, 32, 0.96)',\n border: '1px solid rgba(255, 255, 255, 0.14)',\n color: '#e8eaf0',\n font: '12px/1.4 system-ui, sans-serif',\n};\nconst TOOLBAR_STYLE: CSSProperties = { display: 'flex', alignItems: 'center', gap: 8 };\nconst FILTER_STYLE: CSSProperties = {\n flex: 1,\n minWidth: 0,\n background: 'rgba(255, 255, 255, 0.06)',\n border: '1px solid rgba(255, 255, 255, 0.14)',\n borderRadius: 6,\n color: 'inherit',\n font: 'inherit',\n padding: '3px 8px',\n};\nconst COUNT_STYLE: CSSProperties = { opacity: 0.65, whiteSpace: 'nowrap' };\nconst HEADER_ROW_STYLE: CSSProperties = { borderBottom: '1px solid rgba(255, 255, 255, 0.2)' };\nconst HEADER_BUTTON_STYLE: CSSProperties = {\n appearance: 'none',\n background: 'transparent',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n font: 'inherit',\n fontWeight: 600,\n padding: '2px 4px',\n textAlign: 'left',\n width: '100%',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\nconst ROW_STYLE: CSSProperties = { cursor: 'pointer' };\nconst ROW_SELECTED_STYLE: CSSProperties = {\n ...ROW_STYLE,\n background: 'rgba(122, 162, 255, 0.22)',\n};\nconst CELL_STYLE: CSSProperties = {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n padding: '0 4px',\n};\nconst EMPTY_STYLE: CSSProperties = { fontStyle: 'italic', opacity: 0.8, padding: 4 };\n\n/** Mechanical (always applied) flex geometry for header/body cells. */\nconst CELL_MECHANICS: CSSProperties = { flex: 1, minWidth: 0 };\n\nfunction GraphTableInner(\n props: GraphTableProps,\n ref: ForwardedRef<GraphTableHandle>,\n): ReactElement {\n const instance = useResolvedInstance(props.instance, '<GraphTable>');\n const version = useTableVersion(instance);\n const selection = useSelection(instance);\n\n const mode: GraphTableMode = props.mode ?? 'nodes';\n const rowHeight = props.rowHeight ?? ROW_HEIGHT_DEFAULT;\n const height = props.height ?? HEIGHT_DEFAULT;\n const overscan = props.overscan ?? OVERSCAN_DEFAULT;\n const dimensionKey = props.filterDimension ?? TABLE_FILTER_DIMENSION_DEFAULT;\n const neutralize = props.neutralizeFormulas ?? true;\n const predicate = props.filterPredicate;\n\n const [internalFilter, setInternalFilter] = useState('');\n const filterText = props.filterText ?? internalFilter;\n const query = filterText.trim().toLowerCase();\n const [sort, setSort] = useState<GraphTableSort | null>(null);\n const [scrollTop, setScrollTop] = useState(0);\n\n // --- row model -------------------------------------------------------------\n\n const edgesProp = props.edges;\n const baseRows = useMemo<readonly GraphTableRowRef[]>(() => {\n void version; // rebuild on every relevant store publication\n if (mode === 'edges') {\n const visible = new Set(instance.getVisibleNodeIds());\n const out: GraphTableRowRef[] = [];\n (edgesProp ?? []).forEach((edge, i) => {\n if (!visible.has(edge.source) || !visible.has(edge.target)) return;\n if (edge.id !== undefined) out.push({ key: edge.id, id: edge.id, edge });\n else out.push({ key: `${i}:${edge.source}→${edge.target}`, id: null, edge });\n });\n return out;\n }\n return instance.getVisibleNodeIds().map((id) => ({ key: id, id }));\n }, [instance, version, mode, edgesProp]);\n\n const columnSample = props.columnSample ?? COLUMN_SAMPLE_DEFAULT;\n const columnsProp = props.columns;\n const columns = useMemo<readonly GraphTableColumn[]>(() => {\n if (columnsProp !== undefined) return normalizeColumns(columnsProp);\n const sample = baseRows.slice(0, columnSample).map((row) => {\n return row.edge !== undefined\n ? (row.edge.attrs as Record<string, unknown> | undefined)\n : ((instance.getNode(row.key) as GraphNode<any> | undefined)?.attrs as\n | Record<string, unknown>\n | undefined);\n });\n return deriveColumns(mode, sample);\n }, [instance, baseRows, mode, columnsProp, columnSample]);\n\n const valueOf = useCallback(\n (row: GraphTableRowRef, key: string): unknown =>\n row.edge !== undefined\n ? edgeCellValue(row.edge, key)\n : nodeCellValue(instance.getNode(row.key) as GraphNode<any> | undefined, row.key, key),\n [instance],\n );\n\n /** Text/predicate match for one row over the visible columns. */\n const matchesRow = useCallback(\n (row: GraphTableRowRef): boolean => {\n if (predicate !== undefined) {\n const item =\n row.edge !== undefined\n ? row.edge\n : (instance.getNode(row.key) as GraphNode<any> | undefined);\n if (item === undefined || !predicate(item)) return false;\n }\n if (query === '') return true;\n return textMatches(\n columns.map((col) => cellText(valueOf(row, col.key))),\n query,\n );\n },\n [instance, predicate, query, columns, valueOf],\n );\n\n const filterActive = query !== '' || predicate !== undefined;\n const filteredRows = useMemo<readonly GraphTableRowRef[]>(\n () => (filterActive ? baseRows.filter(matchesRow) : baseRows),\n [baseRows, filterActive, matchesRow],\n );\n\n const sortedRows = useMemo<readonly GraphTableRowRef[]>(() => {\n if (sort === null || !columns.some((c) => c.key === sort.key)) return filteredRows;\n const direction: 1 | -1 = sort.direction === 'asc' ? 1 : -1;\n const decorated = filteredRows.map((row) => ({\n row,\n key: sortKeyOf(valueOf(row, sort.key)),\n }));\n decorated.sort((a, b) => compareSortKeys(a.key, b.key, direction)); // stable → base-order ties\n return decorated.map((d) => d.row);\n }, [filteredRows, sort, columns, valueOf]);\n\n // --- table → graph: crossfilter registration (see module doc) ---------------\n\n /** Set once this table wrote a non-null brush; unmount clears it. */\n const wroteBrushRef = useRef<{ instance: AnyGraphInstance; key: string } | null>(null);\n\n useEffect(() => {\n if (mode !== 'nodes') return;\n const session = instance.getCrossfilterSession();\n if (session === null) return;\n try {\n session.getBrush(dimensionKey);\n } catch {\n return; // dimension not configured — degrade to local-only filtering\n }\n let brush: BrushState = null;\n if (filterActive) {\n const excluded: string[] = [];\n for (const id of instance.getSceneNodeIds()) {\n if (!matchesRow({ key: id, id })) excluded.push(id);\n }\n if (excluded.length > 0) brush = { excluded };\n }\n if (brush !== null) wroteBrushRef.current = { instance, key: dimensionKey };\n // Deep-equal brushes no-op inside the engine, so re-runs are cheap.\n void session.setBrush(dimensionKey, brush).catch(() => undefined);\n }, [instance, version, mode, dimensionKey, filterActive, matchesRow]);\n\n // Review P2: clearing only on FINAL unmount left the previous dimension's\n // brush active across `dimensionKey`/`mode`/`instance` transitions,\n // silently intersecting later filters. The cleanup now runs on every\n // identity change (and still on unmount); the write effect above re-arms\n // the new identity immediately after.\n useEffect(\n () => () => {\n const wrote = wroteBrushRef.current;\n if (wrote === null) return;\n wroteBrushRef.current = null;\n const session = wrote.instance.getCrossfilterSession();\n if (session !== null) void session.setBrush(wrote.key, null).catch(() => undefined);\n },\n [instance, mode, dimensionKey],\n );\n\n // --- selection ---------------------------------------------------------------\n\n const selectedNodes = useMemo(() => new Set(selection.nodeIds), [selection]);\n const selectedEdges = useMemo(() => new Set(selection.edgeIds), [selection]);\n const isSelected = (row: GraphTableRowRef): boolean =>\n row.edge !== undefined\n ? row.id !== null && selectedEdges.has(row.id)\n : selectedNodes.has(row.key);\n\n const activateRow = (row: GraphTableRowRef, additive: boolean): void => {\n if (row.edge !== undefined) {\n if (row.id === null) return; // unaddressable (no caller edge id)\n const id = row.id;\n if (additive) {\n const current = selection.edgeIds;\n instance.selectEdges(\n current.includes(id) ? current.filter((e) => e !== id) : [...current, id],\n );\n } else {\n instance.selectEdges([id]);\n }\n return;\n }\n if (additive) {\n const current = selection.nodeIds;\n instance.selectNodes(\n current.includes(row.key) ? current.filter((n) => n !== row.key) : [...current, row.key],\n );\n } else {\n instance.selectNodes([row.key]);\n }\n };\n\n // --- CSV export (T11) ----------------------------------------------------------\n\n const exportStateRef = useRef({ columns, rows: sortedRows, valueOf, neutralize });\n exportStateRef.current = { columns, rows: sortedRows, valueOf, neutralize };\n useImperativeHandle(\n ref,\n (): GraphTableHandle => ({\n exportCsv: (): string => {\n const s = exportStateRef.current;\n return toCsvString(\n s.columns.map((col) => col.label ?? col.key),\n s.rows.map((row) => s.columns.map((col) => s.valueOf(row, col.key))),\n s.neutralize,\n );\n },\n }),\n [],\n );\n\n // --- windowing -----------------------------------------------------------------\n\n const total = sortedRows.length;\n const first = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);\n const windowSize = Math.ceil(height / rowHeight) + overscan * 2;\n const windowRows = sortedRows.slice(first, first + windowSize);\n\n const onScroll = (e: UIEvent<HTMLDivElement>): void => {\n setScrollTop(e.currentTarget.scrollTop);\n };\n\n const cycleSort = (key: string): void => {\n setSort((prev) => {\n if (prev === null || prev.key !== key) return { key, direction: 'asc' };\n if (prev.direction === 'asc') return { key, direction: 'desc' };\n return null;\n });\n };\n\n const onFilterChange = (text: string): void => {\n if (props.filterText === undefined) setInternalFilter(text);\n props.onFilterTextChange?.(text);\n };\n\n const styled = props.className === undefined;\n const rowStyled = props.rowClassName === undefined;\n const label = props.label ?? 'Graph table';\n\n const renderRow = (row: GraphTableRowRef, index: number): ReactElement => {\n const selected = isSelected(row);\n const node =\n row.edge === undefined\n ? (instance.getNode(row.key) as GraphNode<any> | undefined)\n : undefined;\n const mechanics: CSSProperties = {\n height: rowHeight,\n display: 'flex',\n alignItems: 'center',\n boxSizing: 'border-box',\n };\n return (\n <div\n key={row.key}\n role=\"row\"\n aria-rowindex={first + index + 2}\n aria-selected={selected}\n data-orbit-table-row={row.key}\n tabIndex={0}\n className={props.rowClassName}\n style={\n rowStyled ? { ...mechanics, ...(selected ? ROW_SELECTED_STYLE : ROW_STYLE) } : mechanics\n }\n onClick={(e: MouseEvent<HTMLDivElement>) => {\n activateRow(row, e.metaKey || e.ctrlKey);\n }}\n onKeyDown={(e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'Enter' && e.key !== ' ') return;\n e.preventDefault();\n activateRow(row, e.metaKey || e.ctrlKey);\n }}\n >\n {columns.map((col) => {\n const value = valueOf(row, col.key);\n const text = cellText(value);\n const ctx: GraphTableCellContext =\n node !== undefined\n ? { row, node, column: col, value, text }\n : { row, column: col, value, text };\n return (\n <div\n key={col.key}\n role=\"cell\"\n data-orbit-table-cell={col.key}\n style={styled ? { ...CELL_MECHANICS, ...CELL_STYLE } : CELL_MECHANICS}\n >\n {props.renderCell !== undefined ? props.renderCell(ctx) : text}\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div\n data-orbit-table={mode}\n role=\"group\"\n aria-label={label}\n className={props.className}\n style={styled ? { ...ROOT_STYLE, ...props.style } : props.style}\n >\n <div data-orbit-table-toolbar=\"\" style={styled ? TOOLBAR_STYLE : undefined}>\n <input\n type=\"text\"\n data-orbit-table-filter=\"\"\n aria-label=\"Filter rows\"\n value={filterText}\n style={styled ? FILTER_STYLE : undefined}\n onChange={(e) => {\n onFilterChange(e.currentTarget.value);\n }}\n />\n <span data-orbit-table-count=\"\" style={styled ? COUNT_STYLE : undefined}>\n {`${total} of ${baseRows.length} rows`}\n </span>\n </div>\n <div role=\"table\" aria-label={`${label} rows`} aria-rowcount={total + 1}>\n <div role=\"rowgroup\">\n <div\n role=\"row\"\n aria-rowindex={1}\n data-orbit-table-head=\"\"\n style={styled ? { display: 'flex', ...HEADER_ROW_STYLE } : { display: 'flex' }}\n >\n {columns.map((col) => {\n const active = sort !== null && sort.key === col.key;\n const ariaSort = active\n ? sort.direction === 'asc'\n ? 'ascending'\n : 'descending'\n : 'none';\n return (\n <div\n key={col.key}\n role=\"columnheader\"\n aria-sort={ariaSort}\n data-orbit-table-header={col.key}\n style={CELL_MECHANICS}\n >\n <button\n type=\"button\"\n data-orbit-table-sort={col.key}\n style={styled ? HEADER_BUTTON_STYLE : undefined}\n onClick={() => {\n cycleSort(col.key);\n }}\n >\n {col.label ?? col.key}\n </button>\n </div>\n );\n })}\n </div>\n </div>\n <div\n role=\"rowgroup\"\n data-orbit-table-viewport=\"\"\n onScroll={onScroll}\n style={{ height, overflowY: 'auto', position: 'relative' }}\n >\n {total === 0 ? (\n <div data-orbit-table-empty=\"\" style={styled ? EMPTY_STYLE : undefined}>\n No rows\n </div>\n ) : (\n <div\n data-orbit-table-spacer=\"\"\n style={{ height: total * rowHeight, position: 'relative' }}\n >\n <div\n data-orbit-table-window=\"\"\n style={{ position: 'absolute', top: first * rowHeight, left: 0, right: 0 }}\n >\n {windowRows.map((row, i) => renderRow(row, i))}\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const GraphTable = forwardRef<GraphTableHandle, GraphTableProps>(GraphTableInner);\nGraphTable.displayName = 'GraphTable';\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode, CSSProperties, RefAttributes, ReactElement } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { GraphSnapshotInput, Accessor, GraphNode, Scale, AcceptedEdge, LayoutKind, SimulationConfig, ThemeInput, MetricColumn, ScaleChannelInfo, GraphTheme, LabelConfig, AccessibilityConfig, NodeId, SubgraphSpec, FilterSpec, DimensionSpec, GroupSpec, GroupBySpec, ClusterSpec, ScaleLimits, WorkerFactoryOption, SearchResult, SearchUnavailableReason, CreateGraphInstanceOptions, SelectionState, DegradeEvent, GraphPerfSnapshot, ResolvedGroup, MetaEdge, JsonValue, ViewportState, GraphViewState, SetViewStateResult, PathOptions, PathResult, ExpandNodeResult, ResolvedCluster, BeginIngestOptions, IngestSession, TimelinePlayback, CrossfilterSession, MetricName, Revisions, GraphDiagnostic, GraphInstance, DimensionSummary, BrushState, EdgeId, InstanceStatus } from '@modernrelay/orbit-core';
|
|
3
3
|
import { EngineFactory, FitViewOptions } from '@modernrelay/orbit-core/engine';
|
|
4
4
|
export { G as GraphProvider, a as GraphProviderProps } from './GraphProvider-B8ITDXS0.js';
|
|
5
5
|
export { D as DEFAULT_CORNER_OFFSET, G as GraphCorner, a as GraphLabelsSurface, b as GraphOverlaySurface, u as useResolvedInstance } from './shared-Bj3Gk219.js';
|
|
@@ -24,7 +24,7 @@ interface GraphLegendRenderInfo<N = Record<string, unknown>> {
|
|
|
24
24
|
interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {
|
|
25
25
|
/** Engine factory; captured at first render — one factory per instance. */
|
|
26
26
|
engine: EngineFactory;
|
|
27
|
-
data?:
|
|
27
|
+
data?: GraphSnapshotInput<N, E>;
|
|
28
28
|
/** Constant, accessor, or §11 Scale descriptor. Scale-valued props compare
|
|
29
29
|
* by canonical structural value — equal inline literals never reproject. */
|
|
30
30
|
nodeColor?: Accessor<GraphNode<N>, string> | Scale<string, N>;
|
|
@@ -46,6 +46,9 @@ interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {
|
|
|
46
46
|
edgeArrows?: boolean;
|
|
47
47
|
/** §16.13 runtime link-render toggle — a config-only commit. */
|
|
48
48
|
showLinks?: boolean;
|
|
49
|
+
/** §13 emphasis-ring toggle (default true). False clears the ring once and
|
|
50
|
+
* suppresses every driver (hover, focusNode, emphasizeNode). */
|
|
51
|
+
emphasisRing?: boolean;
|
|
49
52
|
/** §11 legend escape hatch: rendered inside the provider in a positioned
|
|
50
53
|
* wrapper (bottom-left) whenever provided; re-invoked when scale info or
|
|
51
54
|
* theme changes. Return custom JSX, or compose <GraphLegend> from
|
|
@@ -126,6 +129,15 @@ interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {
|
|
|
126
129
|
* mount; changing it requires a keyed remount (a changed prop warns once
|
|
127
130
|
* and is ignored). */
|
|
128
131
|
searchIndex?: readonly string[];
|
|
132
|
+
/** §17/§6.1 degradation-ladder thresholds. CONSTRUCTION-ONLY (D7): read
|
|
133
|
+
* once at mount; a runtime change warns once and is ignored. */
|
|
134
|
+
limits?: Partial<ScaleLimits>;
|
|
135
|
+
/** §6.1/§17 execution mode (ADR-006). CONSTRUCTION-ONLY (D7): read once
|
|
136
|
+
* at mount; a runtime change warns once and is ignored. Current worker
|
|
137
|
+
* cargo: columnar acceptance off-thread. */
|
|
138
|
+
execution?: 'auto' | 'main' | 'worker';
|
|
139
|
+
/** ADR-006 D5 worker construction tri-option. CONSTRUCTION-ONLY (D7). */
|
|
140
|
+
workerFactory?: WorkerFactoryOption;
|
|
129
141
|
/** §16.5 result contract: the instance-wide DEFAULT for an activated
|
|
130
142
|
* search result that cannot be focused ('not-loaded' | 'out-of-scope' |
|
|
131
143
|
* 'filtered'). `<GraphSearch onResultUnavailable>` overrides it locally;
|
|
@@ -171,6 +183,10 @@ interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {
|
|
|
171
183
|
}) => void;
|
|
172
184
|
/** Fires with the full namespaced SelectionState (§16.2). */
|
|
173
185
|
onSelectionChange?: (payload: SelectionState) => void;
|
|
186
|
+
/** §17 ladder step engagement/disengagement (notification pattern). */
|
|
187
|
+
onDegrade?: (event: DegradeEvent) => void;
|
|
188
|
+
/** §17 throttled telemetry sample — never per frame. */
|
|
189
|
+
onPerfSample?: (snapshot: GraphPerfSnapshot) => void;
|
|
174
190
|
/** §16.3/§7.4: a super-node hit — the resolved GROUP payload, never a
|
|
175
191
|
* GraphNode (R-16.3-12). */
|
|
176
192
|
onGroupClick?: (payload: {
|
|
@@ -218,6 +234,11 @@ interface GraphHandle<N = Record<string, unknown>, E = Record<string, unknown>>
|
|
|
218
234
|
durationMs?: number;
|
|
219
235
|
}): void;
|
|
220
236
|
focusNode(id: NodeId): void;
|
|
237
|
+
/** §13 ring-only emphasis, no camera move (null clears; unknown ids
|
|
238
|
+
* no-op). The keyboard-navigation analog of hover. */
|
|
239
|
+
emphasizeNode(id: NodeId | null): void;
|
|
240
|
+
/** §17 telemetry snapshot (never raw attrs or ids). */
|
|
241
|
+
getPerfSnapshot(): GraphPerfSnapshot;
|
|
221
242
|
/** Open the typed context menu for a node from host chrome (a list row, a
|
|
222
243
|
* custom label) — the same 'contextMenu' event the canvas gesture emits.
|
|
223
244
|
* `screen` is container-relative CSS px. */
|
package/dist/index.js
CHANGED
|
@@ -386,10 +386,29 @@ function GraphInner(props, ref) {
|
|
|
386
386
|
options.fitViewOnFirstData = props.fitViewOnFirstData;
|
|
387
387
|
}
|
|
388
388
|
if (props.searchIndex !== void 0) options.searchIndex = props.searchIndex;
|
|
389
|
+
if (props.limits !== void 0) options.limits = props.limits;
|
|
390
|
+
if (props.execution !== void 0) options.execution = props.execution;
|
|
391
|
+
if (props.workerFactory !== void 0) options.workerFactory = props.workerFactory;
|
|
389
392
|
if (props.services !== void 0) options.services = props.services;
|
|
390
393
|
return createGraphInstance(options);
|
|
391
394
|
});
|
|
392
395
|
const searchIndexWarnedRef = useRef(false);
|
|
396
|
+
const limitsWarnedRef = useRef(false);
|
|
397
|
+
const initialLimitsRef = useRef(props.limits);
|
|
398
|
+
if (props.limits !== initialLimitsRef.current && !limitsWarnedRef.current) {
|
|
399
|
+
limitsWarnedRef.current = true;
|
|
400
|
+
console.warn(
|
|
401
|
+
"orbit: `limits` is a construction-only prop (D7/\xA717) \u2014 the runtime change is ignored; remount with a key to apply new thresholds."
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
const executionWarnedRef = useRef(false);
|
|
405
|
+
const initialExecutionRef = useRef(props.execution);
|
|
406
|
+
if (props.execution !== initialExecutionRef.current && !executionWarnedRef.current) {
|
|
407
|
+
executionWarnedRef.current = true;
|
|
408
|
+
console.warn(
|
|
409
|
+
"orbit: `execution` is a construction-only prop (D7/ADR-006) \u2014 the runtime change is ignored; remount with a key to switch lanes."
|
|
410
|
+
);
|
|
411
|
+
}
|
|
393
412
|
const containerRef = useRef(null);
|
|
394
413
|
const callbacksRef = useRef({
|
|
395
414
|
onNodeClick: void 0,
|
|
@@ -400,6 +419,8 @@ function GraphInner(props, ref) {
|
|
|
400
419
|
onNodeDragStart: void 0,
|
|
401
420
|
onNodeDragEnd: void 0,
|
|
402
421
|
onSelectionChange: void 0,
|
|
422
|
+
onDegrade: void 0,
|
|
423
|
+
onPerfSample: void 0,
|
|
403
424
|
onGroupClick: void 0,
|
|
404
425
|
onMetaEdgeClick: void 0,
|
|
405
426
|
onGroupsChange: void 0,
|
|
@@ -420,6 +441,8 @@ function GraphInner(props, ref) {
|
|
|
420
441
|
onNodeDragStart: props.onNodeDragStart,
|
|
421
442
|
onNodeDragEnd: props.onNodeDragEnd,
|
|
422
443
|
onSelectionChange: props.onSelectionChange,
|
|
444
|
+
onDegrade: props.onDegrade,
|
|
445
|
+
onPerfSample: props.onPerfSample,
|
|
423
446
|
onGroupClick: props.onGroupClick,
|
|
424
447
|
onMetaEdgeClick: props.onMetaEdgeClick,
|
|
425
448
|
onGroupsChange: props.onGroupsChange,
|
|
@@ -431,6 +454,35 @@ function GraphInner(props, ref) {
|
|
|
431
454
|
onError: props.onError
|
|
432
455
|
};
|
|
433
456
|
});
|
|
457
|
+
useLayoutEffect(() => {
|
|
458
|
+
const offs = [
|
|
459
|
+
instance.on("nodeClick", (p) => callbacksRef.current.onNodeClick?.(p)),
|
|
460
|
+
instance.on("backgroundClick", () => callbacksRef.current.onBackgroundClick?.()),
|
|
461
|
+
instance.on("nodeHover", (p) => callbacksRef.current.onNodeHover?.(p)),
|
|
462
|
+
instance.on("edgeClick", (p) => callbacksRef.current.onEdgeClick?.(p)),
|
|
463
|
+
instance.on("edgeHover", (p) => callbacksRef.current.onEdgeHover?.(p)),
|
|
464
|
+
instance.on("nodeDragStart", (p) => callbacksRef.current.onNodeDragStart?.(p)),
|
|
465
|
+
instance.on("nodeDragEnd", (p) => callbacksRef.current.onNodeDragEnd?.(p)),
|
|
466
|
+
instance.on("selectionChange", (p) => callbacksRef.current.onSelectionChange?.(p)),
|
|
467
|
+
instance.on("degrade", (p) => callbacksRef.current.onDegrade?.(p)),
|
|
468
|
+
instance.on("perfSample", (p) => callbacksRef.current.onPerfSample?.(p)),
|
|
469
|
+
instance.on("groupClick", (p) => callbacksRef.current.onGroupClick?.(p)),
|
|
470
|
+
instance.on("metaEdgeClick", (p) => callbacksRef.current.onMetaEdgeClick?.(p)),
|
|
471
|
+
instance.on("groupsChange", (p) => callbacksRef.current.onGroupsChange?.(p.groups)),
|
|
472
|
+
instance.on("viewStateRestore", (p) => callbacksRef.current.onViewStateRestore?.(p)),
|
|
473
|
+
instance.on(
|
|
474
|
+
"viewStateMismatch",
|
|
475
|
+
(p) => callbacksRef.current.onViewStateMismatch?.(p.stored, p.current)
|
|
476
|
+
),
|
|
477
|
+
instance.on("pinnedChange", (p) => callbacksRef.current.onPinnedChange?.(p.pinnedNodeIds)),
|
|
478
|
+
instance.on("viewportChange", (v) => callbacksRef.current.onViewportChange?.(v)),
|
|
479
|
+
instance.on("ready", () => callbacksRef.current.onReady?.()),
|
|
480
|
+
instance.on("error", (p) => callbacksRef.current.onError?.(p))
|
|
481
|
+
];
|
|
482
|
+
return () => {
|
|
483
|
+
for (const off of offs) off();
|
|
484
|
+
};
|
|
485
|
+
}, [instance]);
|
|
434
486
|
const prevRef = useRef(null);
|
|
435
487
|
useLayoutEffect(() => {
|
|
436
488
|
const prev = prevRef.current;
|
|
@@ -493,6 +545,13 @@ function GraphInner(props, ref) {
|
|
|
493
545
|
update.showLinks = props.showLinks;
|
|
494
546
|
dirty = true;
|
|
495
547
|
}
|
|
548
|
+
if (props.emphasisRing !== void 0 && (prev === null || prev.emphasisRing !== props.emphasisRing)) {
|
|
549
|
+
update.emphasisRing = props.emphasisRing;
|
|
550
|
+
dirty = true;
|
|
551
|
+
} else if (props.emphasisRing === void 0 && prev !== null && prev.emphasisRing !== void 0) {
|
|
552
|
+
update.emphasisRing = true;
|
|
553
|
+
dirty = true;
|
|
554
|
+
}
|
|
496
555
|
if (props.selection !== void 0 && (prev === null || prev.selection === void 0 || !sameIdArrays(prev.selection, props.selection))) {
|
|
497
556
|
update.selection = props.selection;
|
|
498
557
|
dirty = true;
|
|
@@ -576,6 +635,7 @@ function GraphInner(props, ref) {
|
|
|
576
635
|
nodeImage: props.nodeImage,
|
|
577
636
|
edgeArrows: props.edgeArrows,
|
|
578
637
|
showLinks: props.showLinks,
|
|
638
|
+
emphasisRing: props.emphasisRing,
|
|
579
639
|
selection: props.selection,
|
|
580
640
|
labels: props.labels,
|
|
581
641
|
accessibility: props.accessibility,
|
|
@@ -595,33 +655,6 @@ function GraphInner(props, ref) {
|
|
|
595
655
|
useLayoutEffect(() => {
|
|
596
656
|
setSearchResultUnavailableCallback(instance, props.onSearchResultUnavailable);
|
|
597
657
|
});
|
|
598
|
-
useEffect(() => {
|
|
599
|
-
const offs = [
|
|
600
|
-
instance.on("nodeClick", (p) => callbacksRef.current.onNodeClick?.(p)),
|
|
601
|
-
instance.on("backgroundClick", () => callbacksRef.current.onBackgroundClick?.()),
|
|
602
|
-
instance.on("nodeHover", (p) => callbacksRef.current.onNodeHover?.(p)),
|
|
603
|
-
instance.on("edgeClick", (p) => callbacksRef.current.onEdgeClick?.(p)),
|
|
604
|
-
instance.on("edgeHover", (p) => callbacksRef.current.onEdgeHover?.(p)),
|
|
605
|
-
instance.on("nodeDragStart", (p) => callbacksRef.current.onNodeDragStart?.(p)),
|
|
606
|
-
instance.on("nodeDragEnd", (p) => callbacksRef.current.onNodeDragEnd?.(p)),
|
|
607
|
-
instance.on("selectionChange", (p) => callbacksRef.current.onSelectionChange?.(p)),
|
|
608
|
-
instance.on("groupClick", (p) => callbacksRef.current.onGroupClick?.(p)),
|
|
609
|
-
instance.on("metaEdgeClick", (p) => callbacksRef.current.onMetaEdgeClick?.(p)),
|
|
610
|
-
instance.on("groupsChange", (p) => callbacksRef.current.onGroupsChange?.(p.groups)),
|
|
611
|
-
instance.on("viewStateRestore", (p) => callbacksRef.current.onViewStateRestore?.(p)),
|
|
612
|
-
instance.on(
|
|
613
|
-
"viewStateMismatch",
|
|
614
|
-
(p) => callbacksRef.current.onViewStateMismatch?.(p.stored, p.current)
|
|
615
|
-
),
|
|
616
|
-
instance.on("pinnedChange", (p) => callbacksRef.current.onPinnedChange?.(p.pinnedNodeIds)),
|
|
617
|
-
instance.on("viewportChange", (v) => callbacksRef.current.onViewportChange?.(v)),
|
|
618
|
-
instance.on("ready", () => callbacksRef.current.onReady?.()),
|
|
619
|
-
instance.on("error", (p) => callbacksRef.current.onError?.(p))
|
|
620
|
-
];
|
|
621
|
-
return () => {
|
|
622
|
-
for (const off of offs) off();
|
|
623
|
-
};
|
|
624
|
-
}, [instance]);
|
|
625
658
|
useEffect(() => {
|
|
626
659
|
const container = containerRef.current;
|
|
627
660
|
if (container === null) return void 0;
|
|
@@ -700,6 +733,10 @@ function GraphInner(props, ref) {
|
|
|
700
733
|
focusNode: (id) => {
|
|
701
734
|
instance.focusNode(id);
|
|
702
735
|
},
|
|
736
|
+
emphasizeNode: (id) => {
|
|
737
|
+
instance.emphasizeNode(id);
|
|
738
|
+
},
|
|
739
|
+
getPerfSnapshot: () => instance.getPerfSnapshot(),
|
|
703
740
|
setSelection: (ids) => {
|
|
704
741
|
instance.setSelection(ids);
|
|
705
742
|
},
|