@zvk/graphs 0.1.1 → 0.1.3

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/svg.js CHANGED
@@ -1,50 +1,265 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useId } from "react";
3
3
  import { getEdgeAccessibleLabel } from "./diagnostics.js";
4
- import { nodeCenter } from "./layout/index.js";
4
+ import { deriveGraphEdgeLabelAnchor, deriveGraphGroupBounds, getGraphBounds, nodeCenter } from "./layout/index.js";
5
5
  function pathForPoints(points) {
6
6
  if (points.length === 0 || !points[0]) {
7
7
  return "";
8
8
  }
9
9
  return points.slice(1).reduce((path, point) => `${path} L ${point.x} ${point.y}`, `M ${points[0].x} ${points[0].y}`);
10
10
  }
11
- function graphBounds(graph) {
12
- const padding = 24;
13
- const maxX = graph.nodes.reduce((value, node) => Math.max(value, node.position.x + node.size.width), 0);
14
- const maxY = graph.nodes.reduce((value, node) => Math.max(value, node.position.y + node.size.height), 0);
15
- const width = Math.max(1, maxX + padding * 2);
16
- const height = Math.max(1, maxY + padding * 2);
17
- return {
18
- width,
19
- height,
20
- viewBox: `${-padding} ${-padding} ${width} ${height}`
21
- };
22
- }
23
11
  function nodeSelected(selectedNodeIds, nodeId) {
24
12
  return selectedNodeIds?.includes(nodeId) ?? false;
25
13
  }
26
14
  function edgeSelected(selectedEdgeIds, edgeId) {
27
15
  return selectedEdgeIds?.includes(edgeId) ?? false;
28
16
  }
17
+ function summaryValue(value) {
18
+ if (typeof value === "string") {
19
+ return value.trim().length > 0 ? value : undefined;
20
+ }
21
+ if (typeof value === "number" || typeof value === "boolean") {
22
+ return String(value);
23
+ }
24
+ return undefined;
25
+ }
26
+ function metadataValue(value) {
27
+ if (value === null) {
28
+ return "None";
29
+ }
30
+ return summaryValue(value);
31
+ }
32
+ function metadataRows(metadata, visibility) {
33
+ return (metadata ?? []).filter((item) => {
34
+ if (metadataValue(item.value) === undefined) {
35
+ return false;
36
+ }
37
+ return visibility === undefined ? true : item.visibility === visibility;
38
+ });
39
+ }
40
+ function nodeAccessibleLabel(node) {
41
+ const label = node.accessibility?.label;
42
+ return label && label.trim().length > 0 ? label : node.label;
43
+ }
44
+ function nodeAccessibleDescription(node) {
45
+ return node.accessibility?.description ?? node.ariaDescription ?? node.summary;
46
+ }
47
+ function edgeAccessibleDescription(edge, graph) {
48
+ return edge.accessibility?.description ?? edgeDescription(edge, graph);
49
+ }
50
+ function groupAccessibleLabel(group) {
51
+ const label = group.accessibility?.label;
52
+ return label && label.trim().length > 0 ? label : group.label;
53
+ }
54
+ function groupAccessibleDescription(group) {
55
+ return group.accessibility?.description ?? group.summary;
56
+ }
57
+ function normalizeNodeShape(node) {
58
+ return node.presentation?.shape ?? "rounded";
59
+ }
60
+ function nodeLabelLines(node) {
61
+ const lines = node.labelLines?.filter((line) => line.trim().length > 0);
62
+ return lines && lines.length > 0 ? lines : [node.label];
63
+ }
64
+ function defaultStatusGlyph(status) {
65
+ if (!status) {
66
+ return undefined;
67
+ }
68
+ if (status === "success") {
69
+ return "OK";
70
+ }
71
+ if (status === "warning" || status === "danger" || status === "destructive") {
72
+ return "!";
73
+ }
74
+ if (status === "info") {
75
+ return "i";
76
+ }
77
+ if (status === "active") {
78
+ return "*";
79
+ }
80
+ if (status === "disabled") {
81
+ return "-";
82
+ }
83
+ return status.slice(0, 1).toUpperCase();
84
+ }
85
+ function nodeGlyph(node) {
86
+ return node.presentation?.glyph ?? node.presentation?.statusGlyph ?? defaultStatusGlyph(node.status);
87
+ }
88
+ function nodeBadge(node) {
89
+ return node.presentation?.badge ?? node.presentation?.statusLabel;
90
+ }
91
+ function NodeShape({ node, shape }) {
92
+ if (shape === "circle") {
93
+ return (_jsx("ellipse", { className: "zvk-graphs__node-shape", cx: node.size.width / 2, cy: node.size.height / 2, rx: node.size.width / 2, ry: node.size.height / 2 }));
94
+ }
95
+ if (shape === "diamond") {
96
+ const points = [
97
+ `${node.size.width / 2},0`,
98
+ `${node.size.width},${node.size.height / 2}`,
99
+ `${node.size.width / 2},${node.size.height}`,
100
+ `0,${node.size.height / 2}`
101
+ ].join(" ");
102
+ return _jsx("polygon", { className: "zvk-graphs__node-shape", points: points });
103
+ }
104
+ const rx = shape === "rect" ? 0 : shape === "pill" ? node.size.height / 2 : 8;
105
+ return _jsx("rect", { className: "zvk-graphs__node-shape", width: node.size.width, height: node.size.height, rx: rx });
106
+ }
107
+ function NodeLabel({ node }) {
108
+ const lines = nodeLabelLines(node);
109
+ const lineHeight = 14;
110
+ const firstY = node.size.height / 2 - ((lines.length - 1) * lineHeight) / 2;
111
+ return (_jsx("text", { className: "zvk-graphs__node-label", x: node.size.width / 2, children: lines.map((line, index) => (_jsx("tspan", { x: node.size.width / 2, y: firstY + index * lineHeight, children: line }, `${node.id}-label-${index}`))) }));
112
+ }
113
+ function NodeSummaryMetadata({ node }) {
114
+ const rows = metadataRows(node.metadata, "summary");
115
+ if (rows.length === 0) {
116
+ return null;
117
+ }
118
+ const lineHeight = 11;
119
+ const startY = node.size.height - 8 - (rows.length - 1) * lineHeight;
120
+ return (_jsx("g", { className: "zvk-graphs__node-metadata", "aria-hidden": "true", children: rows.map((item, index) => (_jsxs("text", { className: "zvk-graphs__node-metadata-item", "data-tone": item.tone, x: node.size.width / 2, y: startY + index * lineHeight, children: [item.label, ": ", metadataValue(item.value)] }, item.key))) }));
121
+ }
122
+ function edgeDescription(edge, graph) {
123
+ const source = graph.nodes.find((node) => node.id === edge.source)?.label ?? edge.source;
124
+ const target = graph.nodes.find((node) => node.id === edge.target)?.label ?? edge.target;
125
+ const details = [
126
+ `Source: ${source}`,
127
+ `Target: ${target}`,
128
+ edge.status ? `Status: ${edge.status}` : undefined,
129
+ edge.summary ?? summaryValue(edge.data)
130
+ ].filter(Boolean);
131
+ return details.join(". ");
132
+ }
133
+ function DetailRow({ label, value }) {
134
+ if (!value) {
135
+ return null;
136
+ }
137
+ return (_jsxs(_Fragment, { children: [_jsx("dt", { children: label }), _jsx("dd", { children: value })] }));
138
+ }
139
+ function MetadataFallbackRows({ metadata }) {
140
+ const rows = metadataRows(metadata);
141
+ if (rows.length === 0) {
142
+ return null;
143
+ }
144
+ return (_jsx(_Fragment, { children: rows.map((item) => (_jsx(DetailRow, { label: item.label, value: metadataValue(item.value) }, item.key))) }));
145
+ }
146
+ function GroupFallbackDetails({ group, memberLabels }) {
147
+ const description = groupAccessibleDescription(group);
148
+ const hasMetadata = metadataRows(group.metadata).length > 0;
149
+ const hasDetails = group.summary ||
150
+ group.accessibility?.label ||
151
+ description ||
152
+ group.tone ||
153
+ group.status ||
154
+ hasMetadata ||
155
+ memberLabels.length > 0;
156
+ if (!hasDetails) {
157
+ return null;
158
+ }
159
+ return (_jsxs("dl", { className: "zvk-graphs__fallback-details", children: [_jsx(DetailRow, { label: "Summary", value: group.summary }), _jsx(DetailRow, { label: "Accessible label", value: group.accessibility?.label }), _jsx(DetailRow, { label: "Description", value: description }), _jsx(DetailRow, { label: "Tone", value: group.tone }), _jsx(DetailRow, { label: "Status", value: group.status }), _jsx(MetadataFallbackRows, { metadata: group.metadata }), _jsx(DetailRow, { label: "Members", value: memberLabels.length > 0 ? memberLabels.join(", ") : undefined })] }));
160
+ }
161
+ function NodeFallbackDetails({ node, groupLabel }) {
162
+ const dataSummary = summaryValue(node.data);
163
+ const accessibilityDescription = nodeAccessibleDescription(node);
164
+ const badge = nodeBadge(node);
165
+ const glyph = nodeGlyph(node);
166
+ const hasMetadata = metadataRows(node.metadata).length > 0;
167
+ const hasDetails = node.summary ||
168
+ node.accessibility?.label ||
169
+ accessibilityDescription ||
170
+ node.kind ||
171
+ node.groupId ||
172
+ node.status ||
173
+ node.presentation?.statusLabel ||
174
+ badge ||
175
+ glyph ||
176
+ hasMetadata ||
177
+ dataSummary;
178
+ if (!hasDetails) {
179
+ return null;
180
+ }
181
+ return (_jsxs("dl", { className: "zvk-graphs__fallback-details", children: [_jsx(DetailRow, { label: "Summary", value: node.summary }), _jsx(DetailRow, { label: "Accessible label", value: node.accessibility?.label }), _jsx(DetailRow, { label: "Description", value: accessibilityDescription }), _jsx(DetailRow, { label: "Kind", value: node.kind }), _jsx(DetailRow, { label: "Group", value: groupLabel ?? node.groupId }), _jsx(DetailRow, { label: "Status", value: node.status }), _jsx(DetailRow, { label: "Status label", value: node.presentation?.statusLabel }), _jsx(DetailRow, { label: "Badge", value: badge }), _jsx(DetailRow, { label: "Glyph", value: glyph }), _jsx(MetadataFallbackRows, { metadata: node.metadata }), _jsx(DetailRow, { label: "Data", value: dataSummary })] }));
182
+ }
183
+ function EdgeFallbackDetails({ edge, graph }) {
184
+ const dataSummary = summaryValue(edge.data);
185
+ const source = graph.nodes.find((node) => node.id === edge.source)?.label ?? edge.source;
186
+ const target = graph.nodes.find((node) => node.id === edge.target)?.label ?? edge.target;
187
+ return (_jsxs("dl", { className: "zvk-graphs__fallback-details", children: [_jsx(DetailRow, { label: "Source", value: source }), _jsx(DetailRow, { label: "Target", value: target }), _jsx(DetailRow, { label: "Kind", value: edge.kind }), _jsx(DetailRow, { label: "Route", value: edge.routeKind }), _jsx(DetailRow, { label: "Accessible label", value: edge.accessibility?.label }), _jsx(DetailRow, { label: "Description", value: edge.accessibility?.description }), _jsx(DetailRow, { label: "Status", value: edge.status }), _jsx(DetailRow, { label: "Summary", value: edge.summary }), _jsx(MetadataFallbackRows, { metadata: edge.metadata }), _jsx(DetailRow, { label: "Data", value: dataSummary })] }));
188
+ }
29
189
  export function GraphSvg({ graph, titleId, descriptionId, selectedNodeIds, selectedEdgeIds, renderNode, svgProps }) {
30
- const bounds = graphBounds(graph);
190
+ const bounds = getGraphBounds(graph);
31
191
  const markerId = `${titleId}-arrow`;
32
192
  const hasDirectedEdges = graph.edges.some((edge) => edge.directed !== false);
33
- return (_jsxs("svg", { ...svgProps, className: ["zvk-graphs__svg", svgProps?.className].filter(Boolean).join(" "), role: "img", "aria-labelledby": titleId, "aria-describedby": descriptionId, viewBox: bounds.viewBox, width: svgProps?.width ?? bounds.width, height: svgProps?.height ?? bounds.height, children: [_jsx("title", { id: titleId, children: graph.title }), _jsx("desc", { id: descriptionId, children: graph.description ?? `${graph.nodes.length} nodes and ${graph.edges.length} edges.` }), hasDirectedEdges ? (_jsx("defs", { children: _jsx("marker", { id: markerId, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "7", markerHeight: "7", orient: "auto", children: _jsx("path", { className: "zvk-graphs__marker", d: "M 0 0 L 10 5 L 0 10 z" }) }) })) : null, _jsx("g", { className: "zvk-graphs__edges", children: graph.edges.map((edge) => {
193
+ const groupBounds = deriveGraphGroupBounds(graph);
194
+ const groupById = new Map((graph.groups ?? []).map((group) => [group.id, group]));
195
+ return (_jsxs("svg", { ...svgProps, className: ["zvk-graphs__svg", svgProps?.className].filter(Boolean).join(" "), role: "img", "aria-labelledby": titleId, "aria-describedby": descriptionId, viewBox: bounds.viewBox, width: svgProps?.width ?? bounds.width, height: svgProps?.height ?? bounds.height, children: [_jsx("title", { id: titleId, children: graph.title }), _jsx("desc", { id: descriptionId, children: graph.description ?? `${graph.nodes.length} nodes and ${graph.edges.length} edges.` }), hasDirectedEdges ? (_jsx("defs", { children: _jsx("marker", { id: markerId, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "7", markerHeight: "7", orient: "auto", children: _jsx("path", { className: "zvk-graphs__marker", d: "M 0 0 L 10 5 L 0 10 z" }) }) })) : null, _jsx("g", { className: "zvk-graphs__groups", children: groupBounds.map((boundsEntry) => {
196
+ const group = groupById.get(boundsEntry.groupId);
197
+ if (!group) {
198
+ return null;
199
+ }
200
+ const description = groupAccessibleDescription(group);
201
+ return (_jsxs("g", { className: "zvk-graphs__group", "data-group-id": group.id, "data-tone": group.tone, "data-status": group.status, children: [_jsx("title", { children: groupAccessibleLabel(group) }), description ? _jsx("desc", { children: description }) : null, _jsx("rect", { className: "zvk-graphs__group-shape", x: boundsEntry.position.x, y: boundsEntry.position.y, width: boundsEntry.size.width, height: boundsEntry.size.height, rx: "12" }), _jsx("text", { className: "zvk-graphs__group-label", x: boundsEntry.position.x + 12, y: boundsEntry.position.y + 18, children: group.label })] }, group.id));
202
+ }) }), _jsx("g", { className: "zvk-graphs__edges", children: graph.edges.map((edge) => {
34
203
  const selected = edgeSelected(selectedEdgeIds, edge.id);
35
204
  const d = pathForPoints(edge.points);
36
- return (_jsxs("g", { className: "zvk-graphs__edge-group", "data-edge-id": edge.id, "data-status": edge.status, "data-selected": selected ? "true" : undefined, children: [_jsx("path", { className: "zvk-graphs__edge", d: d, markerEnd: edge.directed === false ? undefined : `url(#${markerId})` }), edge.label && edge.labelPosition ? (_jsx("text", { className: "zvk-graphs__edge-label", x: edge.labelPosition.x, y: edge.labelPosition.y - 6, children: edge.label })) : null] }, edge.id));
205
+ const labelAnchor = deriveGraphEdgeLabelAnchor(edge);
206
+ return (_jsxs("g", { className: "zvk-graphs__edge-group", "data-edge-id": edge.id, "data-edge-kind": edge.kind, "data-edge-label-anchor": labelAnchor?.anchor, "data-edge-label-side": labelAnchor?.side, "data-edge-route-kind": edge.routeKind, "data-status": edge.status, "data-selected": selected ? "true" : undefined, children: [_jsx("title", { children: getEdgeAccessibleLabel(edge, graph) }), _jsx("desc", { children: edgeAccessibleDescription(edge, graph) }), _jsx("path", { className: "zvk-graphs__edge", d: d, markerEnd: edge.directed === false ? undefined : `url(#${markerId})` }), edge.label && labelAnchor ? (_jsxs(_Fragment, { children: [_jsx("rect", { className: "zvk-graphs__edge-label-bg", x: labelAnchor.bounds.x, y: labelAnchor.bounds.y, width: labelAnchor.bounds.width, height: labelAnchor.bounds.height, rx: "4", "aria-hidden": "true" }), _jsx("text", { className: "zvk-graphs__edge-label", textAnchor: labelAnchor.anchor, x: labelAnchor.textPosition.x, y: labelAnchor.textPosition.y, children: edge.label })] })) : null] }, edge.id));
37
207
  }) }), _jsx("g", { className: "zvk-graphs__nodes", children: graph.nodes.map((node) => {
38
208
  const selected = nodeSelected(selectedNodeIds, node.id);
39
209
  const center = nodeCenter(node);
40
- return (_jsxs("g", { className: "zvk-graphs__node", "data-node-id": node.id, "data-kind": node.kind, "data-status": node.status, "data-selected": selected ? "true" : undefined, transform: `translate(${node.position.x} ${node.position.y})`, children: [renderNode ? (renderNode({ node, selected, focused: false })) : (_jsxs(_Fragment, { children: [_jsx("rect", { className: "zvk-graphs__node-shape", width: node.size.width, height: node.size.height, rx: "8" }), _jsx("text", { className: "zvk-graphs__node-label", x: node.size.width / 2, y: node.size.height / 2, children: node.label }), _jsx("title", { children: node.ariaDescription ?? node.label })] })), selected ? (_jsx("rect", { className: "zvk-graphs__node-selection", x: "-4", y: "-4", width: node.size.width + 8, height: node.size.height + 8, rx: "10", "aria-hidden": "true" })) : null, _jsx("circle", { className: "zvk-graphs__node-anchor", cx: center.x - node.position.x, cy: center.y - node.position.y, r: "0" })] }, node.id));
210
+ const shape = normalizeNodeShape(node);
211
+ const badge = nodeBadge(node);
212
+ const glyph = nodeGlyph(node);
213
+ const description = nodeAccessibleDescription(node);
214
+ return (_jsxs("g", { className: "zvk-graphs__node", "data-node-id": node.id, "data-kind": node.kind, "data-node-shape": shape, "data-density": node.presentation?.density, "data-tone": node.presentation?.tone, "data-status": node.status, "data-selected": selected ? "true" : undefined, transform: `translate(${node.position.x} ${node.position.y})`, children: [_jsx("title", { children: nodeAccessibleLabel(node) }), description ? _jsx("desc", { children: description }) : null, selected ? (_jsx("rect", { className: "zvk-graphs__node-selection", x: "-4", y: "-4", width: node.size.width + 8, height: node.size.height + 8, rx: "10", "aria-hidden": "true" })) : null, renderNode ? (renderNode({ node, selected, focused: false })) : (_jsxs(_Fragment, { children: [_jsx(NodeShape, { node: node, shape: shape }), glyph ? (_jsx("text", { className: "zvk-graphs__node-glyph", x: "8", y: "14", "aria-hidden": "true", children: glyph })) : null, badge ? (_jsx("text", { className: "zvk-graphs__node-badge", x: node.size.width - 8, y: "14", "aria-hidden": "true", children: badge })) : null, _jsx(NodeLabel, { node: node }), _jsx(NodeSummaryMetadata, { node: node })] })), _jsx("circle", { className: "zvk-graphs__node-anchor", cx: center.x - node.position.x, cy: center.y - node.position.y, r: "0" })] }, node.id));
41
215
  }) })] }));
42
216
  }
43
217
  export function GraphFallbackList({ graph }) {
44
- return (_jsxs("div", { className: "zvk-graphs__fallback", children: [_jsx("h3", { children: "Nodes" }), _jsx("ul", { children: graph.nodes.map((node) => (_jsxs("li", { children: [node.label, node.status ? ` (${node.status})` : ""] }, node.id))) }), _jsx("h3", { children: "Edges" }), _jsx("ul", { children: graph.edges.map((edge) => (_jsx("li", { children: getEdgeAccessibleLabel(edge, graph) }, edge.id))) })] }));
218
+ const groups = graph.groups ?? [];
219
+ const groupLabelById = new Map(groups.map((group) => [group.id, group.label]));
220
+ return (_jsxs("div", { className: "zvk-graphs__fallback", children: [groups.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("h3", { children: "Groups" }), _jsx("ul", { children: groups.map((group) => {
221
+ const memberLabels = graph.nodes.filter((node) => node.groupId === group.id).map((node) => node.label);
222
+ return (_jsxs("li", { children: [group.label, group.status ? ` (${group.status})` : "", _jsx(GroupFallbackDetails, { group: group, memberLabels: memberLabels })] }, group.id));
223
+ }) })] })) : null, _jsx("h3", { children: "Nodes" }), _jsx("ul", { children: graph.nodes.map((node) => {
224
+ const groupLabel = node.groupId ? groupLabelById.get(node.groupId) : undefined;
225
+ return (_jsxs("li", { children: [node.label, node.status ? ` (${node.status})` : "", _jsx(NodeFallbackDetails, { node: node, ...(groupLabel !== undefined ? { groupLabel } : {}) })] }, node.id));
226
+ }) }), _jsx("h3", { children: "Edges" }), _jsx("ul", { children: graph.edges.map((edge) => (_jsxs("li", { children: [getEdgeAccessibleLabel(edge, graph), _jsx(EdgeFallbackDetails, { edge: edge, graph: graph })] }, edge.id))) })] }));
45
227
  }
46
228
  export function GraphFallbackTree({ graph }) {
47
- return _jsx(GraphFallbackList, { graph: graph });
229
+ const childIdsByNodeId = new Map();
230
+ const parentCountByNodeId = new Map();
231
+ const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
232
+ const groupLabelById = new Map((graph.groups ?? []).map((group) => [group.id, group.label]));
233
+ for (const node of graph.nodes) {
234
+ childIdsByNodeId.set(node.id, []);
235
+ parentCountByNodeId.set(node.id, 0);
236
+ }
237
+ for (const edge of graph.edges) {
238
+ if (!nodeById.has(edge.source) || !nodeById.has(edge.target)) {
239
+ continue;
240
+ }
241
+ childIdsByNodeId.get(edge.source)?.push(edge.target);
242
+ parentCountByNodeId.set(edge.target, (parentCountByNodeId.get(edge.target) ?? 0) + 1);
243
+ }
244
+ const roots = graph.nodes.filter((node) => parentCountByNodeId.get(node.id) === 0);
245
+ if (roots.length !== 1) {
246
+ return _jsx(GraphFallbackList, { graph: graph });
247
+ }
248
+ const root = roots[0];
249
+ if (!root) {
250
+ return _jsx(GraphFallbackList, { graph: graph });
251
+ }
252
+ function renderNode(node, visited) {
253
+ const nextVisited = new Set(visited);
254
+ nextVisited.add(node.id);
255
+ const groupLabel = node.groupId ? groupLabelById.get(node.groupId) : undefined;
256
+ const children = (childIdsByNodeId.get(node.id) ?? [])
257
+ .filter((childId) => !nextVisited.has(childId))
258
+ .map((childId) => nodeById.get(childId))
259
+ .filter((child) => child !== undefined);
260
+ return (_jsxs("li", { children: [node.label, node.status ? ` (${node.status})` : "", _jsx(NodeFallbackDetails, { node: node, ...(groupLabel !== undefined ? { groupLabel } : {}) }), children.length > 0 ? _jsx("ul", { children: children.map((child) => renderNode(child, nextVisited)) }) : null] }, node.id));
261
+ }
262
+ return (_jsxs("div", { className: "zvk-graphs__fallback zvk-graphs__fallback-tree", children: [_jsx("h3", { children: "Tree" }), _jsx("ul", { children: renderNode(root, new Set()) })] }));
48
263
  }
49
264
  export function GraphFigure({ graph, selectedNodeIds, selectedEdgeIds, renderNode, fallbackMode = "list" }) {
50
265
  const id = useId();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zvk/graphs",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Accessible SVG-first node and edge graph utilities, deterministic layouts, and static React renderers for ZVK applications.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -25,27 +25,38 @@
25
25
  "exports": {
26
26
  ".": {
27
27
  "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js"
28
+ "import": "./dist/index.js",
29
+ "default": "./dist/index.js"
29
30
  },
30
31
  "./model": {
31
32
  "types": "./dist/model.d.ts",
32
- "import": "./dist/model.js"
33
+ "import": "./dist/model.js",
34
+ "default": "./dist/model.js"
33
35
  },
34
36
  "./diagnostics": {
35
37
  "types": "./dist/diagnostics.d.ts",
36
- "import": "./dist/diagnostics.js"
38
+ "import": "./dist/diagnostics.js",
39
+ "default": "./dist/diagnostics.js"
37
40
  },
38
41
  "./algorithms": {
39
42
  "types": "./dist/algorithms.d.ts",
40
- "import": "./dist/algorithms.js"
43
+ "import": "./dist/algorithms.js",
44
+ "default": "./dist/algorithms.js"
45
+ },
46
+ "./serialization": {
47
+ "types": "./dist/serialization.d.ts",
48
+ "import": "./dist/serialization.js",
49
+ "default": "./dist/serialization.js"
41
50
  },
42
51
  "./layout": {
43
52
  "types": "./dist/layout/index.d.ts",
44
- "import": "./dist/layout/index.js"
53
+ "import": "./dist/layout/index.js",
54
+ "default": "./dist/layout/index.js"
45
55
  },
46
56
  "./svg": {
47
57
  "types": "./dist/svg.d.ts",
48
- "import": "./dist/svg.js"
58
+ "import": "./dist/svg.js",
59
+ "default": "./dist/svg.js"
49
60
  },
50
61
  "./styles.css": "./dist/styles.css",
51
62
  "./package.json": "./package.json"
@@ -59,11 +70,15 @@
59
70
  "test": "vitest run",
60
71
  "test:ssr": "vitest run tests/ssr --environment node",
61
72
  "test:exports": "vitest run tests/exports --environment node",
73
+ "test:docs-examples": "bun run build && vitest run tests/docs-examples --environment node",
62
74
  "test:types": "tsd",
63
75
  "validate:exports": "bun run scripts/validate-exports.mjs",
76
+ "validate:source-policy": "bun run scripts/validate-source-policy.mjs",
77
+ "verify:style-contract": "bun run scripts/verify-style-contract.mjs",
64
78
  "tarball:inspect": "bun run scripts/check-tarball.mjs",
65
79
  "pack:dry": "bun pm pack --dry-run",
66
- "preflight": "bun run build && bun run typecheck && bun run test && bun run test:ssr && bun run test:types && bun run test:exports && bun run validate:exports && bun run tarball:inspect && bun run pack:dry"
80
+ "preflight": "bun run build && bun run typecheck && bun run test && bun run test:ssr && bun run test:types && bun run test:exports && bun run validate:exports && bun run validate:source-policy && bun run verify:style-contract && bun run tarball:inspect && bun run pack:dry",
81
+ "preflight:ci": "bun run build && bun run typecheck && bun run test && bun run test:ssr && bun run test:types && bun run test:exports && bun run validate:exports && bun run validate:source-policy && bun run verify:style-contract && bun run tarball:inspect && bun run pack:dry"
67
82
  },
68
83
  "dependencies": {},
69
84
  "peerDependencies": {