lispgram 0.10.0 → 0.10.2
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/README.md +11 -5
- package/dist/index.js +250 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -118,10 +118,11 @@ npm install lispgram
|
|
|
118
118
|
<script type="module">
|
|
119
119
|
import lispgram from "lispgram";
|
|
120
120
|
lispgram.initialize({
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
startOnLoad: true,
|
|
122
|
+
showArrowGlyphs: true,
|
|
123
|
+
clickToFocus: true,
|
|
124
|
+
zoom: "both"
|
|
125
|
+
});
|
|
125
126
|
</script>
|
|
126
127
|
```
|
|
127
128
|
|
|
@@ -226,6 +227,8 @@ import { render, renderElement, initialize, createDiagramSvg } from "lispgram/la
|
|
|
226
227
|
|
|
227
228
|
`render(target, source, options?)` renders Lispgram or NCF into a DOM target. `renderElement(sourceElement, options?)` renders one source element. `initialize(options?)` auto-renders matching elements such as `<pre class="lispgram">`. `createDiagramSvg(doc, options?)` renders an already-normalized NCF document into an SVG element.
|
|
228
229
|
|
|
230
|
+
`options.zoom` controls built-in shift zoom behavior. The default with no option is `"both"`, which enables Shift-click zoom-to-fit and cursor-centered Shift + wheel zoom. Shift-click fits containers to about 80% of the viewport; Shift-click on ordinary nodes or arrows zooms to that target so its height is about 5% of the view. Use `"shift-wheel"` for cursor-centered Shift + wheel only, `"shift-click-container"` for Shift-click only, or `"none"` to disable zoom. Auto-rendered `<pre>` blocks can set `data-lispgram-zoom="both"`, `data-lispgram-zoom="shift-wheel"`, `data-lispgram-zoom="shift-click-container"`, or `data-lispgram-zoom="none"`.
|
|
231
|
+
|
|
229
232
|
### Interaction entry point
|
|
230
233
|
|
|
231
234
|
```js
|
|
@@ -286,6 +289,8 @@ When `clickToFocus` is enabled, clicking a node, compound/container, or arrow fo
|
|
|
286
289
|
|
|
287
290
|
Click hit-testing uses a transparent interaction layer above the rendered diagram. Ordinary nodes are given priority over arrows, arrows over container interiors, and deeper containers over their ancestors. This keeps large ancestor containers clickable without letting them steal clicks from nested containers such as `BuildSystem`, `ExternalDependencies`, or `GuileBinding`.
|
|
288
291
|
|
|
292
|
+
The examples use `zoom: "both"`, which is also the default. It enables Shift-click zoom-to-fit plus Shift-wheel cursor zoom. Containers fit to roughly 80% of the viewport. Ordinary nodes and arrows fit so the clicked target is about 5% of the view height. Pass `zoom: "shift-wheel"` for Shift + wheel only, `zoom: "shift-click-container"` for Shift-click only, or `zoom: "none"` to disable built-in zoom.
|
|
293
|
+
|
|
289
294
|
## Demo
|
|
290
295
|
|
|
291
296
|
go to repo root directory
|
|
@@ -308,10 +313,11 @@ navigate to examples/basic.html in browser
|
|
|
308
313
|
</pre>
|
|
309
314
|
<script type="module">
|
|
310
315
|
import lispgram from "https://unpkg.com/lispgram@latest/dist/index.js";
|
|
311
|
-
|
|
316
|
+
lispgram.initialize({
|
|
312
317
|
startOnLoad: true,
|
|
313
318
|
showArrowGlyphs: true,
|
|
314
319
|
clickToFocus: true,
|
|
320
|
+
zoom: "both",
|
|
315
321
|
arrowGlyphRadius: 5.75
|
|
316
322
|
});
|
|
317
323
|
</script>
|
package/dist/index.js
CHANGED
|
@@ -4772,7 +4772,7 @@ function renderLispgramRoute(svg, route, options) {
|
|
|
4772
4772
|
}
|
|
4773
4773
|
|
|
4774
4774
|
function renderLispgramHitLayer(svg, result, options = {}) {
|
|
4775
|
-
if (options.clickToFocus === false) return;
|
|
4775
|
+
if (options.clickToFocus === false && normalizeZoomMode(options) === 'none') return;
|
|
4776
4776
|
const layer = svgEl('g', { class: 'lispgram-hit-layer', 'aria-hidden': 'true' });
|
|
4777
4777
|
|
|
4778
4778
|
// Container hit regions are separate from the visible paint order. They are
|
|
@@ -4888,6 +4888,248 @@ function routeTouchesFocus(route, focus) {
|
|
|
4888
4888
|
return endpointTouches(route.fromEndpoint, focus.id, focus.type) || endpointTouches(route.toEndpoint, focus.id, focus.type);
|
|
4889
4889
|
}
|
|
4890
4890
|
|
|
4891
|
+
function normalizeZoomMode(options = {}) {
|
|
4892
|
+
const raw = options.zoom ?? options.zoomMode ?? options.interactionZoom;
|
|
4893
|
+
if (raw === false || raw == null && options.noZoom === true) return 'none';
|
|
4894
|
+
if (raw == null || raw === true || raw === '') return 'both';
|
|
4895
|
+
const value = String(raw).trim().toLowerCase().replace(/_/g, '-');
|
|
4896
|
+
if (['none', 'off', 'false', '0', 'no', 'disabled', 'disable'].includes(value)) return 'none';
|
|
4897
|
+
if (['wheel', 'scroll', 'cursor', 'cursor-wheel', 'shift-wheel', 'shift-scroll', 'wheel-at-cursor', 'scroll-at-cursor'].includes(value)) return 'shift-wheel';
|
|
4898
|
+
if (['container', 'click-container', 'shift-click', 'shift-click-container', 'container-fit', 'fit-container', 'zoom-container', 'container-zoom'].includes(value)) return 'shift-click-container';
|
|
4899
|
+
if (['both', 'all', 'shift-both'].includes(value)) return 'both';
|
|
4900
|
+
return 'both';
|
|
4901
|
+
}
|
|
4902
|
+
|
|
4903
|
+
function shiftClickZoomEnabled(options = {}) {
|
|
4904
|
+
const mode = normalizeZoomMode(options);
|
|
4905
|
+
return mode === 'shift-click-container' || mode === 'both';
|
|
4906
|
+
}
|
|
4907
|
+
|
|
4908
|
+
function shiftWheelZoomEnabled(options = {}) {
|
|
4909
|
+
const mode = normalizeZoomMode(options);
|
|
4910
|
+
return mode === 'shift-wheel' || mode === 'both';
|
|
4911
|
+
}
|
|
4912
|
+
|
|
4913
|
+
function parseViewBox(svg) {
|
|
4914
|
+
const raw = svg?.getAttribute?.('viewBox') || '';
|
|
4915
|
+
const nums = raw.trim().split(/[\s,]+/).map(Number).filter(Number.isFinite);
|
|
4916
|
+
if (nums.length >= 4) return { x: nums[0], y: nums[1], w: nums[2], h: nums[3] };
|
|
4917
|
+
return null;
|
|
4918
|
+
}
|
|
4919
|
+
|
|
4920
|
+
function writeViewBox(svg, vb) {
|
|
4921
|
+
if (!svg || !vb) return;
|
|
4922
|
+
svg.setAttribute('viewBox', `${vb.x} ${vb.y} ${vb.w} ${vb.h}`);
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
function svgDisplayAspect(svg, fallbackViewBox) {
|
|
4926
|
+
const attrW = Number(svg?.getAttribute?.('width'));
|
|
4927
|
+
const attrH = Number(svg?.getAttribute?.('height'));
|
|
4928
|
+
if (Number.isFinite(attrW) && attrW > 0 && Number.isFinite(attrH) && attrH > 0) return attrW / attrH;
|
|
4929
|
+
const rect = typeof svg?.getBoundingClientRect === 'function' ? svg.getBoundingClientRect() : null;
|
|
4930
|
+
if (rect?.width > 0 && rect?.height > 0) return rect.width / rect.height;
|
|
4931
|
+
return fallbackViewBox?.w && fallbackViewBox?.h ? fallbackViewBox.w / fallbackViewBox.h : 1;
|
|
4932
|
+
}
|
|
4933
|
+
|
|
4934
|
+
function svgPointFromEvent(svg, event, fallbackViewBox) {
|
|
4935
|
+
const vb = parseViewBox(svg) || fallbackViewBox;
|
|
4936
|
+
if (!vb) return null;
|
|
4937
|
+
const rect = typeof svg?.getBoundingClientRect === 'function' ? svg.getBoundingClientRect() : null;
|
|
4938
|
+
if (rect?.width > 0 && rect?.height > 0 && Number.isFinite(event?.clientX) && Number.isFinite(event?.clientY)) {
|
|
4939
|
+
return {
|
|
4940
|
+
x: vb.x + ((event.clientX - rect.left) / rect.width) * vb.w,
|
|
4941
|
+
y: vb.y + ((event.clientY - rect.top) / rect.height) * vb.h
|
|
4942
|
+
};
|
|
4943
|
+
}
|
|
4944
|
+
return { x: vb.x + vb.w / 2, y: vb.y + vb.h / 2 };
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4947
|
+
function zoomViewBoxAt(svg, pivot, factor, originalViewBox, options = {}) {
|
|
4948
|
+
const vb = parseViewBox(svg) || originalViewBox;
|
|
4949
|
+
if (!vb || !pivot || !Number.isFinite(factor) || factor <= 0) return null;
|
|
4950
|
+
const minScale = Number.isFinite(Number(options.zoomMinScale)) ? Number(options.zoomMinScale) : 0.08;
|
|
4951
|
+
const maxScale = Number.isFinite(Number(options.zoomMaxScale)) ? Number(options.zoomMaxScale) : 6;
|
|
4952
|
+
const base = originalViewBox || vb;
|
|
4953
|
+
let nextW = vb.w * factor;
|
|
4954
|
+
let nextH = vb.h * factor;
|
|
4955
|
+
nextW = Math.max(base.w * minScale, Math.min(base.w * maxScale, nextW));
|
|
4956
|
+
nextH = Math.max(base.h * minScale, Math.min(base.h * maxScale, nextH));
|
|
4957
|
+
const actualX = nextW / vb.w;
|
|
4958
|
+
const actualY = nextH / vb.h;
|
|
4959
|
+
const next = {
|
|
4960
|
+
x: pivot.x - (pivot.x - vb.x) * actualX,
|
|
4961
|
+
y: pivot.y - (pivot.y - vb.y) * actualY,
|
|
4962
|
+
w: nextW,
|
|
4963
|
+
h: nextH
|
|
4964
|
+
};
|
|
4965
|
+
writeViewBox(svg, next);
|
|
4966
|
+
return next;
|
|
4967
|
+
}
|
|
4968
|
+
|
|
4969
|
+
function viewBoxForBox(svg, box, originalViewBox, options = {}) {
|
|
4970
|
+
if (!box || !originalViewBox) return null;
|
|
4971
|
+
const ratioRaw = Number(options.zoomFitRatio ?? options.containerZoomFitRatio ?? 0.8);
|
|
4972
|
+
const fitRatio = Number.isFinite(ratioRaw) && ratioRaw > 0 && ratioRaw < 1 ? ratioRaw : 0.8;
|
|
4973
|
+
const aspect = svgDisplayAspect(svg, originalViewBox) || 1;
|
|
4974
|
+
const minW = Number(options.containerZoomMinWidth ?? 160);
|
|
4975
|
+
const minH = Number(options.containerZoomMinHeight ?? 120);
|
|
4976
|
+
let w = Math.max(box.w / fitRatio, (box.h / fitRatio) * aspect, minW);
|
|
4977
|
+
let h = w / aspect;
|
|
4978
|
+
if (h < Math.max(box.h / fitRatio, minH)) {
|
|
4979
|
+
h = Math.max(box.h / fitRatio, minH);
|
|
4980
|
+
w = h * aspect;
|
|
4981
|
+
}
|
|
4982
|
+
const maxW = originalViewBox.w * (Number(options.containerZoomMaxScale ?? 1.05) || 1.05);
|
|
4983
|
+
const maxH = originalViewBox.h * (Number(options.containerZoomMaxScale ?? 1.05) || 1.05);
|
|
4984
|
+
if (w > maxW || h > maxH) {
|
|
4985
|
+
const scale = Math.max(w / maxW, h / maxH);
|
|
4986
|
+
w /= scale;
|
|
4987
|
+
h /= scale;
|
|
4988
|
+
}
|
|
4989
|
+
return { x: box.cx - w / 2, y: box.cy - h / 2, w, h };
|
|
4990
|
+
}
|
|
4991
|
+
|
|
4992
|
+
function finiteBounds(points) {
|
|
4993
|
+
const pts = (points || []).filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y));
|
|
4994
|
+
if (!pts.length) return null;
|
|
4995
|
+
let left = Infinity;
|
|
4996
|
+
let right = -Infinity;
|
|
4997
|
+
let top = Infinity;
|
|
4998
|
+
let bottom = -Infinity;
|
|
4999
|
+
for (const p of pts) {
|
|
5000
|
+
left = Math.min(left, p.x);
|
|
5001
|
+
right = Math.max(right, p.x);
|
|
5002
|
+
top = Math.min(top, p.y);
|
|
5003
|
+
bottom = Math.max(bottom, p.y);
|
|
5004
|
+
}
|
|
5005
|
+
return { left, right, top, bottom, w: right - left, h: bottom - top, cx: (left + right) / 2, cy: (top + bottom) / 2 };
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
function routeZoomBounds(route, options = {}) {
|
|
5009
|
+
const mid = route?.anchors?.label || route?.anchors?.mid || pointAlongPolyline(route?.points || [], 0.5);
|
|
5010
|
+
const glyphRadius = Number.isFinite(Number(options.arrowGlyphRadius)) ? Number(options.arrowGlyphRadius) : 5;
|
|
5011
|
+
const glyphDiameter = Math.max(10, glyphRadius * 2);
|
|
5012
|
+
const routeBounds = finiteBounds(route?.points || []);
|
|
5013
|
+
if (!mid) return routeBounds;
|
|
5014
|
+
const desired = Math.max(glyphDiameter, Number(options.arrowZoomTargetSize || 0) || 0);
|
|
5015
|
+
const half = desired / 2;
|
|
5016
|
+
return {
|
|
5017
|
+
left: mid.x - half,
|
|
5018
|
+
right: mid.x + half,
|
|
5019
|
+
top: mid.y - half,
|
|
5020
|
+
bottom: mid.y + half,
|
|
5021
|
+
w: desired,
|
|
5022
|
+
h: desired,
|
|
5023
|
+
cx: mid.x,
|
|
5024
|
+
cy: mid.y,
|
|
5025
|
+
routeBounds
|
|
5026
|
+
};
|
|
5027
|
+
}
|
|
5028
|
+
|
|
5029
|
+
function viewBoxForSmallBounds(svg, bounds, originalViewBox, options = {}) {
|
|
5030
|
+
if (!bounds || !originalViewBox) return null;
|
|
5031
|
+
const aspect = svgDisplayAspect(svg, originalViewBox) || 1;
|
|
5032
|
+
const fractionRaw = Number(options.zoomTargetHeightFraction ?? options.smallZoomHeightFraction ?? 0.05);
|
|
5033
|
+
const fraction = Number.isFinite(fractionRaw) && fractionRaw > 0 && fractionRaw < 1 ? fractionRaw : 0.05;
|
|
5034
|
+
const minTargetH = Number.isFinite(Number(options.smallZoomMinTargetHeight)) ? Number(options.smallZoomMinTargetHeight) : 10;
|
|
5035
|
+
const targetH = Math.max(bounds.h || 0, minTargetH);
|
|
5036
|
+
let h = targetH / fraction;
|
|
5037
|
+
let w = h * aspect;
|
|
5038
|
+
const minW = Number(options.smallZoomMinWidth ?? 120);
|
|
5039
|
+
const minH = Number(options.smallZoomMinHeight ?? 90);
|
|
5040
|
+
if (w < minW) { w = minW; h = w / aspect; }
|
|
5041
|
+
if (h < minH) { h = minH; w = h * aspect; }
|
|
5042
|
+
return { x: bounds.cx - w / 2, y: bounds.cy - h / 2, w, h };
|
|
5043
|
+
}
|
|
5044
|
+
|
|
5045
|
+
function viewBoxForZoomTarget(svg, target, result, originalViewBox, options = {}) {
|
|
5046
|
+
if (!target || !originalViewBox) return null;
|
|
5047
|
+
if (target.type === 'node') {
|
|
5048
|
+
const box = result.boxes?.get?.(target.id);
|
|
5049
|
+
if (!box) return null;
|
|
5050
|
+
if (box.kind === 'container') return viewBoxForBox(svg, box, originalViewBox, options);
|
|
5051
|
+
return viewBoxForSmallBounds(svg, box, originalViewBox, options);
|
|
5052
|
+
}
|
|
5053
|
+
if (target.type === 'edge') {
|
|
5054
|
+
const route = result.routes?.get?.(target.id);
|
|
5055
|
+
return viewBoxForSmallBounds(svg, routeZoomBounds(route, options), originalViewBox, options);
|
|
5056
|
+
}
|
|
5057
|
+
return null;
|
|
5058
|
+
}
|
|
5059
|
+
|
|
5060
|
+
function enableLispgramZoom(svg, result, options = {}) {
|
|
5061
|
+
if (!svg || !result) return;
|
|
5062
|
+
const mode = normalizeZoomMode(options);
|
|
5063
|
+
if (mode === 'none') return;
|
|
5064
|
+
const originalViewBox = parseViewBox(svg) || result.viewBox || null;
|
|
5065
|
+
if (!originalViewBox) return;
|
|
5066
|
+
let currentViewBox = { ...originalViewBox };
|
|
5067
|
+
const animationMs = Number.isFinite(Number(options.zoomAnimationMs)) ? Number(options.zoomAnimationMs) : 160;
|
|
5068
|
+
|
|
5069
|
+
function setViewBox(vb) {
|
|
5070
|
+
if (!vb) return null;
|
|
5071
|
+
currentViewBox = { ...vb };
|
|
5072
|
+
if (svg.style && animationMs > 0) svg.style.transition = `viewBox ${animationMs}ms ease`;
|
|
5073
|
+
writeViewBox(svg, currentViewBox);
|
|
5074
|
+
return currentViewBox;
|
|
5075
|
+
}
|
|
5076
|
+
|
|
5077
|
+
function zoomToTarget(target) {
|
|
5078
|
+
return setViewBox(viewBoxForZoomTarget(svg, target, result, originalViewBox, options));
|
|
5079
|
+
}
|
|
5080
|
+
|
|
5081
|
+
function zoomToBox(id) {
|
|
5082
|
+
return zoomToTarget({ type: 'node', id });
|
|
5083
|
+
}
|
|
5084
|
+
|
|
5085
|
+
function zoomToEdge(id) {
|
|
5086
|
+
return zoomToTarget({ type: 'edge', id });
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
function reset() {
|
|
5090
|
+
return setViewBox(originalViewBox);
|
|
5091
|
+
}
|
|
5092
|
+
|
|
5093
|
+
if (shiftWheelZoomEnabled(options) && typeof svg.addEventListener === 'function') {
|
|
5094
|
+
svg.addEventListener('wheel', (event) => {
|
|
5095
|
+
if (!event?.shiftKey) return;
|
|
5096
|
+
if (typeof event.preventDefault === 'function') event.preventDefault();
|
|
5097
|
+
const scale = Number.isFinite(Number(options.zoomWheelScale)) ? Number(options.zoomWheelScale) : 1.08;
|
|
5098
|
+
const delta = Number(event.deltaY || 0);
|
|
5099
|
+
const factor = delta < 0 ? 1 / scale : scale;
|
|
5100
|
+
const pivot = svgPointFromEvent(svg, event, currentViewBox);
|
|
5101
|
+
currentViewBox = zoomViewBoxAt(svg, pivot, factor, originalViewBox, options) || currentViewBox;
|
|
5102
|
+
}, { passive: false });
|
|
5103
|
+
}
|
|
5104
|
+
|
|
5105
|
+
if (shiftClickZoomEnabled(options)) {
|
|
5106
|
+
const hitboxes = [];
|
|
5107
|
+
walkSvgElements(svg, (node) => {
|
|
5108
|
+
if (typeof node.getAttribute !== 'function') return;
|
|
5109
|
+
const cls = node.getAttribute('class');
|
|
5110
|
+
if (cls === 'lispgram-compound-hitbox' || cls === 'lispgram-node-hitbox') {
|
|
5111
|
+
const id = node.getAttribute('data-node-id');
|
|
5112
|
+
if (result.boxes?.has?.(id)) hitboxes.push([node, { type: 'node', id }]);
|
|
5113
|
+
} else if (cls === 'lispgram-edge-hitbox') {
|
|
5114
|
+
const id = node.getAttribute('data-edge-id');
|
|
5115
|
+
if (result.routes?.has?.(id)) hitboxes.push([node, { type: 'edge', id }]);
|
|
5116
|
+
}
|
|
5117
|
+
});
|
|
5118
|
+
for (const [el, target] of hitboxes) {
|
|
5119
|
+
if (typeof el.addEventListener !== 'function') continue;
|
|
5120
|
+
el.addEventListener('click', (event) => {
|
|
5121
|
+
if (!event?.shiftKey) return;
|
|
5122
|
+
if (typeof event.preventDefault === 'function') event.preventDefault();
|
|
5123
|
+
if (typeof event.stopPropagation === 'function') event.stopPropagation();
|
|
5124
|
+
if (typeof event.stopImmediatePropagation === 'function') event.stopImmediatePropagation();
|
|
5125
|
+
zoomToTarget(target);
|
|
5126
|
+
});
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
|
|
5130
|
+
svg.__lispgramZoom = { mode, originalViewBox, get viewBox() { return currentViewBox; }, reset, zoomToBox, zoomToEdge, zoomToTarget };
|
|
5131
|
+
}
|
|
5132
|
+
|
|
4891
5133
|
function enableLispgramClickFocus(svg, result, options = {}) {
|
|
4892
5134
|
if (!svg || !result || options.clickToFocus === false) return;
|
|
4893
5135
|
const dimOpacity = Number.isFinite(Number(options.focusDimOpacity)) ? Number(options.focusDimOpacity) : 0.12;
|
|
@@ -4960,6 +5202,7 @@ function enableLispgramClickFocus(svg, result, options = {}) {
|
|
|
4960
5202
|
if (typeof el.addEventListener !== 'function') continue;
|
|
4961
5203
|
if (el.style) el.style.cursor = 'pointer';
|
|
4962
5204
|
el.addEventListener('click', (event) => {
|
|
5205
|
+
if (event?.shiftKey && shiftClickZoomEnabled(options) && result.boxes?.has?.(id)) return;
|
|
4963
5206
|
stop(event);
|
|
4964
5207
|
const next = { type: 'node', id };
|
|
4965
5208
|
applyFocus(sameFocus(currentFocus, next) ? null : next);
|
|
@@ -4999,6 +5242,7 @@ function createLispgramConstraintSvg(result, options = {}) {
|
|
|
4999
5242
|
for (const route of result.routes.values()) renderLispgramRoute(svg, route, options);
|
|
5000
5243
|
renderLispgramHitLayer(svg, result, options);
|
|
5001
5244
|
enableLispgramClickFocus(svg, result, options);
|
|
5245
|
+
enableLispgramZoom(svg, result, options);
|
|
5002
5246
|
return svg;
|
|
5003
5247
|
}
|
|
5004
5248
|
|
|
@@ -5207,6 +5451,8 @@ function elementRenderOptions(sourceElement, options = {}) {
|
|
|
5207
5451
|
...options,
|
|
5208
5452
|
showArrowGlyphs: parseBooleanOption(data.lispgramArrowGlyphs, options.showArrowGlyphs ?? false),
|
|
5209
5453
|
clickToFocus: parseBooleanOption(data.lispgramClickFocus, options.clickToFocus ?? true),
|
|
5454
|
+
zoom: data.lispgramZoom || data.lispgramZoomMode || options.zoom || options.zoomMode,
|
|
5455
|
+
zoomMode: data.lispgramZoomMode || data.lispgramZoom || options.zoomMode || options.zoom,
|
|
5210
5456
|
arrowGlyphRadius: parseNumericOption(data.lispgramArrowGlyphRadius, options.arrowGlyphRadius),
|
|
5211
5457
|
diagramId: data.lispgramDiagram || data.diagramId || options.diagramId || options.name || options.id || sourceElement?.id || undefined
|
|
5212
5458
|
};
|
|
@@ -5277,6 +5523,8 @@ function initialize(options = {}) {
|
|
|
5277
5523
|
showNCF = false,
|
|
5278
5524
|
showArrowGlyphs = false,
|
|
5279
5525
|
clickToFocus = true,
|
|
5526
|
+
zoom,
|
|
5527
|
+
zoomMode,
|
|
5280
5528
|
arrowGlyphRadius = 5.75,
|
|
5281
5529
|
height,
|
|
5282
5530
|
width,
|
|
@@ -5288,7 +5536,7 @@ function initialize(options = {}) {
|
|
|
5288
5536
|
for (const element of elements) {
|
|
5289
5537
|
if (element.dataset.lispgramMounted === 'true') continue;
|
|
5290
5538
|
try {
|
|
5291
|
-
renderElement(element, { showNCF, showArrowGlyphs, clickToFocus, arrowGlyphRadius, height, width, diagramId });
|
|
5539
|
+
renderElement(element, { showNCF, showArrowGlyphs, clickToFocus, zoom: zoomMode ?? zoom, zoomMode: zoomMode ?? zoom, arrowGlyphRadius, height, width, diagramId });
|
|
5292
5540
|
element.dataset.lispgramMounted = 'true';
|
|
5293
5541
|
} catch {
|
|
5294
5542
|
element.dataset.lispgramMounted = 'error';
|