react-beauti-graph 1.3.0 → 1.3.1
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 +45 -17
- package/dist/graphFactory.d.cts +2 -0
- package/dist/graphFactory.d.ts +2 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +229 -210
- package/dist/index.js.map +1 -1
- package/dist/style.css +380 -356
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
A React component for drawing report dependency graphs with [Cytoscape](https://js.cytoscape.org/).
|
|
6
6
|
Give it your reports, the groups they belong to and the connections between them; it draws the graph
|
|
7
|
-
on a grid and adds search, tracing of parents and children, a details panel and
|
|
7
|
+
on a grid and adds search, tracing of parents and children, a details panel, clipboard export and SVG export.
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|
|
|
11
11
|
_The [quick start](#quick-start) example, with the_ Node to Display _list open._
|
|
12
12
|
|
|
13
13
|
## Contents
|
|
14
14
|
|
|
15
15
|
- [Features](#features)
|
|
16
|
+
- [Release notes](#release-notes)
|
|
16
17
|
- [Install](#install)
|
|
17
18
|
- [Quick start](#quick-start)
|
|
18
19
|
- [Frameworks](#frameworks)
|
|
@@ -39,15 +40,37 @@ _The [quick start](#quick-start) example, with the_ Node to Display _list open._
|
|
|
39
40
|
- **Show Dependency 1 and 2**: highlight the whole chain of parents or children of a report in two colors, and dim the rest
|
|
40
41
|
- **Details panel** (double click): the report, its group, its parents and children, one level or all levels; click a name to jump to it
|
|
41
42
|
- **Save to clipboard** (right click): copies the same information as the details panel
|
|
43
|
+
- **Export SVG** button: downloads the whole graph as a vector `graph.svg` file (a static image, not interactive)
|
|
42
44
|
- **Text size buttons** (− / +) for the top row, the details panel and the graph
|
|
43
45
|
- **Configurable** colors, text sizes and grid spacing
|
|
44
46
|
|
|
47
|
+
## Release notes
|
|
48
|
+
|
|
49
|
+
### 1.3.1
|
|
50
|
+
|
|
51
|
+
- **Export SVG**: a blue button at the right end of the top row saves the whole graph (not only the visible part) as `graph.svg`, using [`cytoscape-svg`](https://github.com/kinimesi/cytoscape-svg), which is now a dependency. The graph is still drawn on canvas; the SVG is an export only.
|
|
52
|
+
- **Top row layout**: the text size dropdown with − / + and _Export SVG_ sit together at the right end of the row, after the _?_ help
|
|
53
|
+
- **`downloadSvg(cy)`**: the same export, available in code (takes a Cytoscape core instance)
|
|
54
|
+
- Typecheck, lint, format check and all 85 tests pass (`npm run check`)
|
|
55
|
+
|
|
56
|
+
### 1.3.0
|
|
57
|
+
|
|
58
|
+
- **Report boxes fit their text**: each box is as big as its label plus a little padding (it was a fixed 200 × 60); the _Font Graph Panel_ − / + buttons resize the boxes with the text
|
|
59
|
+
- Built and type-checked with TypeScript 7; dependencies updated
|
|
60
|
+
- **Show Dependency 1 and 2**: two independent chains of parents or children, each with its own colors; reports and arrows on both use `commonColor`
|
|
61
|
+
- **Details panel**: _One level / All levels_ switch, also used by _Save to clipboard_
|
|
62
|
+
- **Text size**: dropdown with − / + buttons for the top row, the details panel and the graph
|
|
63
|
+
- **Renamed controls**: _Node to Display_, _Show Dependency_, _Show Nothing_
|
|
64
|
+
- **`node_groups`** is the name of the first `create_graph` argument (it was `folders`; the argument is positional, so existing calls keep working)
|
|
65
|
+
- **TypeScript**: written in strict TypeScript, with generated type definitions for ESM and CommonJS
|
|
66
|
+
- **Example app**: now a separate project in `examples/` (Vite); Next.js is no longer used
|
|
67
|
+
|
|
45
68
|
## Install
|
|
46
69
|
|
|
47
70
|
From the [GitHub release](https://github.com/ramasco/react-beauti-graph/releases/latest):
|
|
48
71
|
|
|
49
72
|
```bash
|
|
50
|
-
npm install https://github.com/ramasco/react-beauti-graph/releases/download/v1.3.
|
|
73
|
+
npm install https://github.com/ramasco/react-beauti-graph/releases/download/v1.3.1/react-beauti-graph-1.3.1.tgz
|
|
51
74
|
```
|
|
52
75
|
|
|
53
76
|
Requires React 18 or newer. Cytoscape is installed automatically.
|
|
@@ -214,7 +237,7 @@ disappears too. Hidden reports stay in the list, greyed out.
|
|
|
214
237
|
Clicking a checkbox does not select the report and keeps the list open, so you can hide several in a row.
|
|
215
238
|
Picking a hidden report by name shows it again, and _ALL_ zooms to fit the reports that are shown.
|
|
216
239
|
|
|
217
|
-

|
|
218
241
|
|
|
219
242
|
_`r001` unchecked, with_ Show Groups _and_ Add Group to Node Name _turned off: only `r002 → r003` is left._
|
|
220
243
|
|
|
@@ -267,6 +290,7 @@ at the graph. Pick what to resize in the dropdown, then click **−** or **+**:
|
|
|
267
290
|
| _Parents / Children_ | Which chain the _Show Dependency_ next to it follows. Disabled while nothing is tracked. |
|
|
268
291
|
| _Font Top Panel / Font Right Panel / Font Graph Panel_ | Dropdown that picks which text the next two buttons resize: the top row, the details panel, or the labels and boxes of the graph. |
|
|
269
292
|
| _−_ and _+_ | Make the chosen text 2px smaller or larger (from 8px smaller to 16px larger than the configured size). Each area keeps its own size; they reset when the page is reloaded. |
|
|
293
|
+
| _Export SVG_ | Downloads the whole graph as `graph.svg` (all reports and groups, whatever the zoom). The file is a static image: no search, details or highlighting. |
|
|
270
294
|
| _?_ | Short help. |
|
|
271
295
|
|
|
272
296
|
In all search boxes, use the arrow keys and Enter to pick, Escape to close the list, and × to clear.
|
|
@@ -308,6 +332,7 @@ Building blocks used by the component, for building your own UI:
|
|
|
308
332
|
| `NodeSearch` | The search box: `<NodeSearch options={[{ id, label }]} selectedId={id} onSelect={(id) => …} noneLabel="ALL" />`. `''` means no node. Add `onToggleVisible={(id) => …}` and `hiddenIds={new Set([...])}` to show a checkbox next to each node. |
|
|
309
333
|
| `getNodeInfo(node, allLevels?)` | For a Cytoscape node: `{ id, name, group, parents, children }` (parents and children sorted by name). With `allLevels` set to `true`, the lists hold every ancestor and descendant instead of the direct ones. |
|
|
310
334
|
| `formatNodeInfo(info)` | The clipboard text for the result of `getNodeInfo`. |
|
|
335
|
+
| `downloadSvg(cy)` | Downloads the whole graph of a Cytoscape core instance as `graph.svg`. |
|
|
311
336
|
|
|
312
337
|
## Development
|
|
313
338
|
|
|
@@ -331,6 +356,7 @@ npm run lint # ESLint, strict rules (eslint.config.mjs)
|
|
|
331
356
|
npm run format # Prettier: formats the code (npm run format:check only checks)
|
|
332
357
|
npm run check # typecheck + lint + format check + tests: run it before a commit
|
|
333
358
|
npm run build:lib # build the npm package (code and .d.ts types) into dist/
|
|
359
|
+
npm run smoke # draws the example app in Chrome or Edge and checks the arrows are painted
|
|
334
360
|
```
|
|
335
361
|
|
|
336
362
|
**Example app** (`examples/`):
|
|
@@ -346,19 +372,21 @@ On Windows, `examples/run.cmd` installs the example's dependencies the first tim
|
|
|
346
372
|
`npm run dev` does the same as `cd examples && npm run dev`. While developing, the name `react-beauti-graph`
|
|
347
373
|
points at the library source in `src/` (see `examples/vite.config.mjs`), so library changes show up at once.
|
|
348
374
|
|
|
349
|
-
| Path | Contents
|
|
350
|
-
| ---------------------------------------------------------------- |
|
|
351
|
-
| `src/graphFactory.tsx` | The library: `create_graph`, layout, styles, search box
|
|
352
|
-
| `src/default_setting.ts` | Default colors, text sizes and layout (the `DEFAULT_*` values)
|
|
353
|
-
| `src/react-beauti-graph.css` | The library styles (published as `style.css`)
|
|
354
|
-
| `src/index.ts` | Public entry point of the package (the `.d.ts` types are generated into `dist/`)
|
|
355
|
-
| `tests/` | `graphFactory.test.ts`, `NodeSearch.test.tsx`
|
|
356
|
-
| `tsconfig.json`, `tsconfig.build.json` | TypeScript settings (strict), and the settings that generate the types
|
|
357
|
-
| `
|
|
358
|
-
|
|
|
359
|
-
| `
|
|
360
|
-
| `examples/
|
|
361
|
-
| `examples/
|
|
375
|
+
| Path | Contents |
|
|
376
|
+
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
377
|
+
| `src/graphFactory.tsx` | The library: `create_graph`, layout, styles, search box |
|
|
378
|
+
| `src/default_setting.ts` | Default colors, text sizes and layout (the `DEFAULT_*` values) |
|
|
379
|
+
| `src/react-beauti-graph.css` | The library styles (published as `style.css`) |
|
|
380
|
+
| `src/index.ts` | Public entry point of the package (the `.d.ts` types are generated into `dist/`) |
|
|
381
|
+
| `tests/` | `graphFactory.test.ts`, `NodeSearch.test.tsx` |
|
|
382
|
+
| `tsconfig.json`, `tsconfig.build.json` | TypeScript settings (strict), and the settings that generate the types |
|
|
383
|
+
| `scripts/` | `smoke.mjs` (browser smoke test) and `make-cts.mjs` (finishes the type files) |
|
|
384
|
+
| `.github/workflows/ci.yml` | GitHub Actions: runs the check, the package build and the smoke test on every push |
|
|
385
|
+
| `vite.lib.config.mjs`, `vitest.config.mjs` | Build of the npm package, and the test setup |
|
|
386
|
+
| `examples/DemoApp.tsx` | The example page, with the _Demo data_ dropdown |
|
|
387
|
+
| `examples/main.tsx`, `examples/index.html`, `examples/index.css` | The Vite entry that mounts the example page, and its page styles |
|
|
388
|
+
| `examples/samples/` | Example data: a small example and 100 reports in 5 groups |
|
|
389
|
+
| `examples/package.json`, `examples/vite.config.mjs` | The example app's own dependencies and Vite setup |
|
|
362
390
|
|
|
363
391
|
In the example app, switch between the two samples with the _Demo data_ dropdown at the top of the page.
|
|
364
392
|
|
package/dist/graphFactory.d.cts
CHANGED
|
@@ -2,6 +2,8 @@ import type { FC } from 'react';
|
|
|
2
2
|
import cytoscape from 'cytoscape';
|
|
3
3
|
import type { StylesheetJson } from 'cytoscape';
|
|
4
4
|
export * from './default_setting.cjs';
|
|
5
|
+
/** Downloads the whole graph as a static SVG file named graph.svg. */
|
|
6
|
+
export declare function downloadSvg(cy: cytoscape.Core): void;
|
|
5
7
|
export declare const REPORT_NODE = "node[class = \"macromolecule\"]";
|
|
6
8
|
/** Group (folder box) names mapped to the names of the reports inside them */
|
|
7
9
|
export type NodeGroups = Record<string, string[]>;
|
package/dist/graphFactory.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { FC } from 'react';
|
|
|
2
2
|
import cytoscape from 'cytoscape';
|
|
3
3
|
import type { StylesheetJson } from 'cytoscape';
|
|
4
4
|
export * from './default_setting.js';
|
|
5
|
+
/** Downloads the whole graph as a static SVG file named graph.svg. */
|
|
6
|
+
export declare function downloadSvg(cy: cytoscape.Core): void;
|
|
5
7
|
export declare const REPORT_NODE = "node[class = \"macromolecule\"]";
|
|
6
8
|
/** Group (folder box) names mapped to the names of the reports inside them */
|
|
7
9
|
export type NodeGroups = Record<string, string[]>;
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("react"),l=require("cytoscape");l=s(l,1);let u=require("react/jsx-runtime");var
|
|
2
|
-
`)}function W(e){let t=/^#([0-9a-f]{6})$/i.exec(e)?.[1];if(t!==void 0)return parseInt(t,16);let n=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(e);if(n===null)return null;let[r=0,i=0,a=0]=n.slice(1).map(e=>Math.min(Number(e),255));return r<<16|i<<8|a}function G(e,t=.88){let n=W(e);return n===null?`#ffffff`:`#${[16,8,0].map(e=>{let r=n>>e&255;return Math.round(r+(255-r)*t).toString(16).padStart(2,`0`)}).join(``)}`}function ae(e,t,n=g){let r=[`track`,`track2`],i=r.flatMap(e=>[`${e}-parents`,`${e}-children`,`${e}-root`]).concat(`faded`,`track-mixed`).join(` `);e.batch(()=>{e.elements().removeClass(i).removeData(`trackMixColor trackMixFill`);let a=t.map(({id:t,direction:n},i)=>{if(!t)return null;let a=e.getElementById(t);if(a.empty())return null;let o=V(a,n),s=r[i]??`track`;return o.addClass(`${s}-${n}`),a.addClass(`${s}-root`),o}),o=a.filter(e=>e!==null);if(o.length===0)return;let[s,c]=a;s&&c&&s.intersection(c).forEach(e=>{e.data({trackMixColor:n,trackMixFill:G(n)}),e.addClass(`track-mixed`)});let l=o.reduce((e,t)=>e.union(t));e.elements().not(l).not(`node:parent`).addClass(`faded`)})}function K({selectedColor:e=d,parentsColor:t=f,childrenColor:n=p,track2ParentsColor:r=m,track2ChildrenColor:i=h}={}){return[{selector:`node`,style:{"background-color":b,label:`data(graphLabel)`,shape:`rectangle`,"font-family":O,"font-size":T,color:y,"border-width":2,"border-color":y,"text-valign":`center`,"text-halign":`center`}},{selector:`node:parent`,style:{"background-color":x,"background-opacity":.5,"border-style":`dashed`,label:`data(label)`,"text-valign":`top`,"font-size":E,"font-weight":`bold`,padding:`18px`}},{selector:`.selected`,style:{"overlay-color":e,"overlay-opacity":.35,"overlay-padding":8}},{selector:`edge`,style:{"line-color":y,width:2,"curve-style":`bezier`,"target-arrow-shape":`vee`,"target-arrow-color":y,"target-arrow-fill":`filled`,"arrow-scale":2}},{selector:`edge:loop`,style:{"loop-direction":`0deg`,"loop-sweep":`-50deg`,"control-point-step-size":70}},{selector:`edge.bidirectional`,style:{"source-arrow-shape":`vee`,"source-arrow-color":y,"source-arrow-fill":`filled`}},{selector:`.faded`,style:{opacity:.15}},...[[`track-parents`,`track-root`,t],[`track-children`,`track-root`,n],[`track2-parents`,`track2-root`,r],[`track2-children`,`track2-root`,i]].flatMap(([e,t,n])=>[{selector:`edge.${e}`,style:{"line-color":n,"target-arrow-color":n,"source-arrow-color":n,width:4}},{selector:`node.${e}`,style:{"border-color":n,"border-width":3}},{selector:`node.${e}.${t}`,style:{"border-width":5,"background-color":G(n)}}]),{selector:`edge.track-mixed`,style:{"line-color":`data(trackMixColor)`,"target-arrow-color":`data(trackMixColor)`,"source-arrow-color":`data(trackMixColor)`,width:5}},{selector:`node.track-mixed`,style:{"border-color":`data(trackMixColor)`,"border-width":4}},{selector:`node.track-mixed.track-root, node.track-mixed.track2-root`,style:{"border-width":6,"background-color":`data(trackMixFill)`}},{selector:`.hidden`,style:{display:`none`}}]}var q=`ALL`;function J({id:e,options:t,selectedId:n,onSelect:r,noneLabel:i=q,hiddenIds:a,onToggleVisible:o}){let[s,l]=(0,c.useState)(``),[d,f]=(0,c.useState)(``),[p,m]=(0,c.useState)(!1),[h,g]=(0,c.useState)(0),_=(0,c.useRef)(null),v=(0,c.useRef)(null),y=t.find(e=>e.id===n)?.label??``,[b,x]=(0,c.useState)(null);b!==y&&(x(y),l(y));let S=d.trim().toLowerCase(),C=S?t.filter(e=>e.label.toLowerCase().includes(S)):t,w={id:``,label:i},T=!S||i.toLowerCase().includes(S)?[w,...C]:C,E=()=>{f(``),g(0),m(!0)},D=()=>{m(!1),f(``),l(y)},O=e=>{r(e.id),l(e.id?e.label:``),f(``),m(!1)};return(0,c.useEffect)(()=>{if(!p)return;let e=e=>{_.current?.contains(e.target)||D()};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)}),(0,c.useEffect)(()=>{v.current?.children[h]?.scrollIntoView({block:`nearest`})},[h,p]),(0,u.jsxs)(`div`,{className:`node-search`,ref:_,children:[(0,u.jsx)(`input`,{id:e,type:`text`,value:s,placeholder:`-- type to search --`,autoComplete:`off`,onChange:e=>{l(e.target.value),f(e.target.value),g(0),m(!0)},onFocus:e=>{e.target.select(),E()},onClick:()=>{p||E()},onKeyDown:e=>{if(e.key===`ArrowDown`)e.preventDefault(),p||m(!0),g(e=>Math.min(e+1,T.length-1));else if(e.key===`ArrowUp`)e.preventDefault(),g(e=>Math.max(e-1,0));else if(e.key===`Enter`&&p){let t=T[h];t&&(e.preventDefault(),O(t))}else e.key===`Escape`&&D()}}),s&&(0,u.jsx)(`button`,{type:`button`,className:`node-search-clear`,"aria-label":`Clear`,onClick:()=>{r(``),l(``),f(``)},children:`×`}),p&&(0,u.jsx)(`ul`,{className:`node-search-list`,ref:v,role:`listbox`,children:T.length===0?(0,u.jsx)(`li`,{className:`node-search-empty`,role:`option`,"aria-selected":`false`,"aria-disabled":`true`,children:`no match`}):T.map((e,t)=>(0,u.jsxs)(`li`,{role:`option`,"aria-selected":t===h,className:[t===h&&`active`,a?.has(e.id)&&`off`].filter(Boolean).join(` `)||void 0,onMouseDown:t=>{t.preventDefault(),O(e)},onMouseEnter:()=>g(t),children:[o&&e.id&&(0,u.jsx)(`input`,{type:`checkbox`,checked:!a?.has(e.id),"aria-label":`Show ${e.label}`,onMouseDown:e=>{e.preventDefault(),e.stopPropagation()},onClick:e=>e.stopPropagation(),onChange:()=>o(e.id)}),e.label]},e.id||`__none__`))})]})}function Y(e={},t=[],n=null,r={}){let i=Array.isArray(n)?n:null,a=n!==null&&!Array.isArray(n)?n:r,o=i!==null&&i.length>0,{selectedColor:s=d,parentsColor:y=f,childrenColor:b=p,track2ParentsColor:x=m,track2ChildrenColor:O=h,commonColor:k=g,topControlsFontSize:A=_,rightDisplayFontSize:j=v,layoutColumns:M=10}=a,P=K({selectedColor:s,parentsColor:y,childrenColor:b,track2ParentsColor:x,track2ChildrenColor:O}),F={"--rbg-parents-color":y,"--rbg-children-color":b},L={"--rbg-parents-color":x,"--rbg-children-color":O},V=z(e,t,i!==null&&o?i.flat():[]),W=i!==null&&o?te(i):R(V,M);function G(){let e=(0,c.useRef)(null),t=(0,c.useRef)(null),n=(0,c.useId)(),[r,i]=(0,c.useState)([]),[o,s]=(0,c.useState)(``),[d,f]=(0,c.useState)(0),[p,m]=(0,c.useState)(``),[h,g]=(0,c.useState)(`parents`),[_,v]=(0,c.useState)(``),[y,b]=(0,c.useState)(`parents`),[x,O]=(0,c.useState)(!0),[M,te]=(0,c.useState)(!0),[R,z]=(0,c.useState)(null),[G,K]=(0,c.useState)(null),[q,Y]=(0,c.useState)(`top`),[X,oe]=(0,c.useState)({top:0,right:0,graph:0}),[Z,se]=(0,c.useState)(!1),Q=(0,c.useRef)(!1);(0,c.useEffect)(()=>{Q.current=Z},[Z]);let[$,ce]=(0,c.useState)(()=>new Set);(0,c.useEffect)(()=>{let n=e.current;if(!n)return;let r=(0,l.default)({container:n,elements:re(V,x,M),style:P,layout:{name:`preset`,fit:!1}});r.on(`cxttap`,N,e=>{let t=U(B(e.target,Q.current)),{clientX:n,clientY:r}=e.originalEvent;z({x:n,y:r,copyText:t})}),r.on(`dbltap`,N,e=>{K(B(e.target,Q.current))}),r.on(`tap cxttap`,e=>{e.target===r&&z(null)}),r.on(`tap`,`node`,()=>z(null)),r.on(`viewport`,()=>z(null));let o=e=>e.preventDefault();return n.addEventListener(`contextmenu`,o),ne(r,W,a),requestAnimationFrame(()=>r.resize()),i(r.nodes(N).map(e=>({id:e.id(),label:e.data(`displayLabel`)})).sort((e,t)=>I(e.label,t.label))),t.current=r,()=>{n.removeEventListener(`contextmenu`,o),z(null),r.destroy(),t.current=null}},[x,M]),(0,c.useEffect)(()=>{let e=t.current;if(!e)return;let n=X.graph;e.batch(()=>{e.nodes(N).forEach(e=>{let t=T+n,{width:r,height:i}=ee(e.data(`graphLabel`),t);e.style({"font-size":t,width:r,height:i})}),e.nodes(`:parent`).style(`font-size`,E+n)})},[X.graph,x,M]),(0,c.useEffect)(()=>{if(!R)return;let e=e=>{e.target.closest(`.node-context-menu`)||z(null)},t=e=>{e.key===`Escape`&&z(null)};return document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t)}},[R]);let le=()=>{if(R===null)return;let{copyText:e}=R;z(null),navigator.clipboard.writeText(e).catch(e=>{console.error(`Failed to copy:`,e)})},ue=e=>{ce(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},de=e=>{let n=t.current?.getElementById(e);n&&!n.empty()&&($.has(e)&&ue(e),s(e),K(B(n,Z)))},fe=()=>{s(``),K(null),f(e=>e+1)};(0,c.useEffect)(()=>{let e=t.current;e&&e.batch(()=>{e.elements().removeClass(`hidden`),ie(e,$).addClass(`hidden`)})},[$,x,M]),(0,c.useEffect)(()=>{let e=t.current;d&&e&&(e.stop(),e.resize(),e.animate({fit:{eles:e.elements().not(`.hidden`),padding:30}},{duration:400}))},[d]),(0,c.useEffect)(()=>{let e=t.current;if(!e||(e.nodes().removeClass(`selected`),!o))return;let n=e.getElementById(o);n.nonempty()&&(n.addClass(`selected`),e.animate({center:{eles:n},zoom:1.8},{duration:400}))},[o,x,M]),(0,c.useEffect)(()=>{let e=t.current;e&&ae(e,[{id:p,direction:h},{id:_,direction:y}],k)},[p,h,_,y,x,M]),(0,c.useEffect)(()=>{t.current?.resize()},[G!==null]),(0,c.useEffect)(()=>{let e=()=>t.current?.resize();return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]);let pe=[{n:1,id:p,setId:m,direction:h,setDirection:g,style:void 0},{n:2,id:_,setId:v,direction:y,setDirection:b,style:L}],me=[{label:`Smaller text`,symbol:`−`,step:-2,atLimit:X[q]<=C},{label:`Larger text`,symbol:`+`,step:S,atLimit:X[q]>=w}];return(0,u.jsxs)(`div`,{className:`rbg-graph`,style:{...F,"--rbg-top-controls-font-size":`calc(${A} + ${X.top}px)`,"--rbg-right-display-font-size":`calc(${j} + ${X.right}px)`},children:[(0,u.jsxs)(`div`,{className:`controls`,children:[(0,u.jsxs)(`span`,{className:`control-group`,children:[(0,u.jsx)(`label`,{htmlFor:`${n}-search`,children:`Node to Display:`}),(0,u.jsx)(J,{id:`${n}-search`,options:r,selectedId:o,onSelect:e=>e?de(e):fe(),hiddenIds:$,onToggleVisible:ue})]}),(0,u.jsxs)(`label`,{children:[(0,u.jsx)(`input`,{type:`checkbox`,checked:x,onChange:e=>O(e.target.checked)}),`Show Groups`]}),(0,u.jsxs)(`label`,{children:[(0,u.jsx)(`input`,{type:`checkbox`,checked:M,onChange:e=>te(e.target.checked)}),`Add Group to Node Name`]}),pe.map(({n:e,id:t,setId:i,direction:a,setDirection:o,style:s})=>(0,u.jsxs)(`span`,{className:`control-group`,style:s,children:[(0,u.jsxs)(`label`,{htmlFor:`${n}-track${e}`,children:[`Show Dependency `,e,`:`]}),(0,u.jsx)(J,{id:`${n}-track${e}`,options:r,selectedId:t,onSelect:i,noneLabel:`Show Nothing`}),(0,u.jsxs)(`span`,{className:t?`track-switch`:`track-switch disabled`,children:[(0,u.jsx)(`span`,{className:a===`parents`?`parents on`:`parents`,children:`Parents`}),(0,u.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":a===`children`,"aria-label":`Show Dependency ${e}: track children instead of parents`,className:`switch`,disabled:!t,onClick:()=>o(e=>e===`parents`?`children`:`parents`),children:(0,u.jsx)(`span`,{className:`switch-knob`})}),(0,u.jsx)(`span`,{className:a===`children`?`children on`:`children`,children:`Children`})]})]},e)),(0,u.jsxs)(`span`,{className:`help`,children:[(0,u.jsx)(`button`,{type:`button`,className:`help-icon`,"aria-label":`Help`,"aria-describedby":`${n}-help`,children:`?`}),(0,u.jsxs)(`span`,{id:`${n}-help`,role:`tooltip`,className:`help-tooltip`,children:[(0,u.jsx)(`strong`,{children:`Double click`}),` on a node to see its information, parents and children.`,(0,u.jsx)(`br`,{}),(0,u.jsx)(`strong`,{children:`Right click`}),` on a node to save the same information to the clipboard.`]})]}),(0,u.jsxs)(`span`,{className:`font-size-buttons`,children:[(0,u.jsx)(`select`,{"aria-label":`Area whose text size the + and - buttons change`,value:q,onChange:e=>Y(e.target.value),children:D.map(([e,t])=>(0,u.jsx)(`option`,{value:e,children:t},e))}),me.map(({label:e,symbol:t,step:n,atLimit:r})=>(0,u.jsx)(`button`,{type:`button`,className:`help-icon`,"aria-label":e,disabled:r,onClick:()=>oe(e=>({...e,[q]:e[q]+n})),children:t},e))]})]}),(0,u.jsxs)(`div`,{className:`graph-area`,children:[(0,u.jsx)(`div`,{ref:e,className:`cy-container`}),G&&(0,u.jsxs)(`aside`,{className:`node-info-panel`,children:[(0,u.jsxs)(`div`,{className:`node-info-header`,children:[(0,u.jsxs)(`h2`,{children:[(0,u.jsx)(`strong`,{children:`Node:`}),` `,G.name]}),(0,u.jsx)(`button`,{type:`button`,onClick:()=>K(null),"aria-label":`Close`,children:`×`})]}),G.group&&(0,u.jsxs)(`p`,{children:[(0,u.jsx)(`strong`,{children:`Group:`}),` `,G.group]}),(0,u.jsxs)(`div`,{className:`track-switch level-switch`,children:[(0,u.jsx)(`span`,{className:Z?``:`parents on`,children:`One level`}),(0,u.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":Z,"aria-label":`Show all levels of parents and children`,className:`switch`,onClick:()=>{let e=!Z;se(e);let n=t.current?.getElementById(G.id);n&&!n.empty()&&K(B(n,e))},children:(0,u.jsx)(`span`,{className:`switch-knob`})}),(0,u.jsx)(`span`,{className:Z?`children on`:``,children:`All levels`})]}),H(G).map(([e,t])=>(0,u.jsxs)(`section`,{children:[(0,u.jsxs)(`h3`,{children:[e,` (`,t.length,`):`]}),(0,u.jsx)(`ul`,{children:t.map(e=>(0,u.jsx)(`li`,{children:(0,u.jsxs)(`button`,{type:`button`,onClick:()=>de(e.id),children:[e.name,e.group&&(0,u.jsxs)(`span`,{children:[` (`,e.group,`)`]})]})},e.id))})]},e))]})]}),R&&(0,u.jsx)(`div`,{className:`node-context-menu`,style:{left:R.x,top:R.y},onContextMenu:e=>e.preventDefault(),children:(0,u.jsx)(`button`,{type:`button`,onClick:le,children:`Save to clipboard`})})]})}return G.displayName=`CytoscapeGraph`,G}exports.NodeSearch=J,exports.create_graph=Y,exports.formatNodeInfo=U,exports.getNodeInfo=B;
|
|
1
|
+
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("react"),l=require("cytoscape");l=s(l,1);let u=require("cytoscape-svg");u=s(u,1);let d=require("react/jsx-runtime");var f=`#e91e63`,p=`#2e7d32`,m=`#7b1fa2`,h=`#efeb00`,g=`#8b4513`,_=`rgb(239, 108, 0)`,v=`22px`,y=`18px`,b=`#0066cc`,x=`#fff`,S=`#f0f8ff`;l.default.use(u.default);function C(e){let t=e.svg({full:!0,scale:1}),n=URL.createObjectURL(new Blob([t],{type:`image/svg+xml`})),r=document.createElement(`a`);r.href=n,r.download=`graph.svg`,r.click(),URL.revokeObjectURL(n)}var w=2,T=-8,E=16,D=16,O=14,ee=[[`top`,`Font Top Panel`],[`right`,`Font Right Panel`],[`graph`,`Font Graph Panel`]],k=`Helvetica Neue, Helvetica, Arial, sans-serif`,A=1.2,j=.6,M=`macromolecule`,N=`compartment`,P=`node[class = "${M}"]`,F;function te(e,t){if(F===void 0)try{F=document.createElement(`canvas`).getContext(`2d`)}catch{F=null}return F?(F.font=`${t}px ${k}`,F.measureText(e).width):e.length*t*j}function ne(e,t=D){return{width:Math.ceil(te(e??``,t))+8,height:Math.ceil(t*A)+8}}function I(e,t){return e.localeCompare(t,void 0,{numeric:!0,sensitivity:`base`})}function L(e=[]){let t=new Map;return e.map(e=>e.map(e=>{let n=t.get(e)??0;if(t.set(e,n+1),n===0)return e;let r=`${e}(${n})`;return console.warn(`layout: duplicate id "${e}" — renamed to "${r}"`),r}))}function re(e,t,n={}){let{startX:r=0,startY:i=0,offsetX:a=200,offsetY:o=200,base:s=1}=n,c=new Set;t.forEach((t,n)=>{t.forEach((t,l)=>{let u=t,d=e.getElementById(u);if(d.empty()){let n=/^(.+)\((\d+)\)$/.exec(t)?.[1];n!==void 0&&e.getElementById(n).nonempty()&&(u=n,d=e.getElementById(u),console.warn(`applyLayout: "${t}" not found — using "${u}" instead`))}d.empty()?console.warn(`applyLayout: node "${t}" not found`):c.has(u)?console.warn(`applyLayout: duplicate layout entry for node "${u}" (from "${t}") — keeping the first position`):(c.add(u),d.position({x:r+(l+s)*a,y:i+(n+s)*o}))})})}function R(e,t){let n=e,r=2;for(;t.has(n);)n=`${e}_${r++}`;return t.add(n),n}function z(e,t=10){let n=Math.max(1,Math.floor(t)||1),r=e.filter(e=>e.data.class===M),i=e.filter(e=>e.data.class===N).map(e=>r.filter(t=>t.data.parent===e.data.id));i.push(r.filter(e=>!e.data.parent));let a=[];for(let e of i)for(let t=0;t<e.length;t+=n)a.push(e.slice(t,t+n).map(e=>e.data.id));return a}function B(e={},t=[],n=[]){let r=[],i=new Set,a=new Set([...t.flat(),...n]);for(let t of Object.values(e))for(let e of t)i.add(e);for(let e of a)i.add(e);let o=e=>{let t=e.replace(/\s+/g,``);return t?t.charAt(0).toLowerCase()+t.slice(1):`folder`},s=new Map,c=new Map;for(let[t,n]of Object.entries(e)){let e=R(o(t),i);c.set(t,e),r.push({data:{id:e,class:N,label:t}});for(let e of n){let n=s.get(e)??[],r=e;if(n.length>0){let t=n.length;for(r=`${e}(${t})`;i.has(r);)r=`${e}(${++t})`;i.add(r)}n.push({actualId:r,folderLabel:t}),s.set(e,n)}}let l=[];for(let[e,t]of s)for(let{actualId:n,folderLabel:r}of t)l.push({actualId:n,originalId:e,folderLabel:r});for(let e of a)s.has(e)||l.push({actualId:e,originalId:e,folderLabel:null});for(let{actualId:e,originalId:t,folderLabel:n}of l){let i={id:e,class:M,rawLabel:t,displayLabel:n?`${t} (${n})`:t,group:n};n&&(i.parent=c.get(n)),r.push({data:i})}let u=e=>s.get(e)?.[0]?.actualId??e,d=(e,t)=>`${e}->${t}`,f=new Map;return t.forEach(([e,t],n)=>{let a=u(e),o=u(t);if(f.has(d(a,o)))return;let s=f.get(d(o,a));if(s){s.classes=`bidirectional`;return}let c={data:{id:R(`e${n+1}`,i),source:a,target:o}};f.set(d(a,o),c),r.push(c)}),r}function ie(e,t,n){return e.filter(e=>t||e.data.class!==N).map(e=>{if(e.data.class!==M)return{...e,data:{...e.data}};let t=n?e.data.displayLabel:e.data.rawLabel;return{...e,data:{...e.data,graphLabel:t}}})}function V(e,t=!1){let n=e=>({id:e.id(),name:e.data(`rawLabel`)??e.id(),group:e.data(`group`)??null}),r=new Map,i=new Map;if(e.connectedEdges().forEach(t=>{let a=t.hasClass(`bidirectional`);t.target().same(e)&&(r.set(t.source().id(),n(t.source())),a&&i.set(t.source().id(),n(t.source()))),t.source().same(e)&&(i.set(t.target().id(),n(t.target())),a&&r.set(t.target().id(),n(t.target())))}),t){let t=[[r,`parents`],[i,`children`]];for(let[r,i]of t)r.clear(),H(e,i).nodes().forEach(t=>{t.same(e)||r.set(t.id(),n(t))})}let a=(e,t)=>I(e.name,t.name);return{...n(e),parents:[...r.values()].sort(a),children:[...i.values()].sort(a)}}function H(e,t){let n=t===`parents`,r=e.cy().collection(),i=new Set([e.id()]),a=[e];for(let e=a.shift();e!==void 0;e=a.shift()){let t=e;t.connectedEdges().forEach(e=>{let o=e.hasClass(`bidirectional`),s=null;e.target().same(t)&&(n||o)&&(s=e.source()),e.source().same(t)&&(!n||o)&&(s=e.target()),s&&(r=r.union(e),i.has(s.id())||(i.add(s.id()),a.push(s)))})}return r.union(e.cy().nodes().filter(e=>i.has(e.id())))}function U(e){return[[`Parent Nodes`,e.parents],[`Child Nodes`,e.children]].filter(([,e])=>e.length>0)}function ae(e,t){let n=e.nodes(P).filter(e=>t.has(e.id())),r=e.nodes(`:parent`).filter(e=>e.children().every(e=>n.has(e)));return n.union(r)}function W(e){let t=e=>e.group?`${e.name} (${e.group})`:e.name,n=[`Node: ${e.name}`];e.group&&n.push(`Group: ${e.group}`);for(let[r,i]of U(e))n.push(``,`${r} (${i.length}):`,...i.map(t));return n.join(`
|
|
2
|
+
`)}function G(e){let t=/^#([0-9a-f]{6})$/i.exec(e)?.[1];if(t!==void 0)return parseInt(t,16);let n=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(e);if(n===null)return null;let[r=0,i=0,a=0]=n.slice(1).map(e=>Math.min(Number(e),255));return r<<16|i<<8|a}function K(e,t=.88){let n=G(e);return n===null?`#ffffff`:`#${[16,8,0].map(e=>{let r=n>>e&255;return Math.round(r+(255-r)*t).toString(16).padStart(2,`0`)}).join(``)}`}function oe(e,t,n=_){let r=[`track`,`track2`],i=r.flatMap(e=>[`${e}-parents`,`${e}-children`,`${e}-root`]).concat(`faded`,`track-mixed`).join(` `);e.batch(()=>{e.elements().removeClass(i).removeData(`trackMixColor trackMixFill`);let a=t.map(({id:t,direction:n},i)=>{if(!t)return null;let a=e.getElementById(t);if(a.empty())return null;let o=H(a,n),s=r[i]??`track`;return o.addClass(`${s}-${n}`),a.addClass(`${s}-root`),o}),o=a.filter(e=>e!==null);if(o.length===0)return;let[s,c]=a;s&&c&&s.intersection(c).forEach(e=>{e.data({trackMixColor:n,trackMixFill:K(n)}),e.addClass(`track-mixed`)});let l=o.reduce((e,t)=>e.union(t));e.elements().not(l).not(`node:parent`).addClass(`faded`)})}function q({selectedColor:e=f,parentsColor:t=p,childrenColor:n=m,track2ParentsColor:r=h,track2ChildrenColor:i=g}={}){return[{selector:`node`,style:{"background-color":x,label:`data(graphLabel)`,shape:`rectangle`,"font-family":k,"font-size":D,color:b,"border-width":2,"border-color":b,"text-valign":`center`,"text-halign":`center`}},{selector:`node:parent`,style:{"background-color":S,"background-opacity":.5,"border-style":`dashed`,label:`data(label)`,"text-valign":`top`,"font-size":O,"font-weight":`bold`,padding:`18px`}},{selector:`.selected`,style:{"overlay-color":e,"overlay-opacity":.35,"overlay-padding":8}},{selector:`edge`,style:{"line-color":b,width:2,"curve-style":`bezier`,"target-arrow-shape":`vee`,"target-arrow-color":b,"target-arrow-fill":`filled`,"arrow-scale":2}},{selector:`edge:loop`,style:{"loop-direction":`0deg`,"loop-sweep":`-50deg`,"control-point-step-size":70}},{selector:`edge.bidirectional`,style:{"source-arrow-shape":`vee`,"source-arrow-color":b,"source-arrow-fill":`filled`}},{selector:`.faded`,style:{opacity:.15}},...[[`track-parents`,`track-root`,t],[`track-children`,`track-root`,n],[`track2-parents`,`track2-root`,r],[`track2-children`,`track2-root`,i]].flatMap(([e,t,n])=>[{selector:`edge.${e}`,style:{"line-color":n,"target-arrow-color":n,"source-arrow-color":n,width:4}},{selector:`node.${e}`,style:{"border-color":n,"border-width":3}},{selector:`node.${e}.${t}`,style:{"border-width":5,"background-color":K(n)}}]),{selector:`edge.track-mixed`,style:{"line-color":`data(trackMixColor)`,"target-arrow-color":`data(trackMixColor)`,"source-arrow-color":`data(trackMixColor)`,width:5}},{selector:`node.track-mixed`,style:{"border-color":`data(trackMixColor)`,"border-width":4}},{selector:`node.track-mixed.track-root, node.track-mixed.track2-root`,style:{"border-width":6,"background-color":`data(trackMixFill)`}},{selector:`.hidden`,style:{display:`none`}}]}var J=`ALL`;function Y({id:e,options:t,selectedId:n,onSelect:r,noneLabel:i=J,hiddenIds:a,onToggleVisible:o}){let[s,l]=(0,c.useState)(``),[u,f]=(0,c.useState)(``),[p,m]=(0,c.useState)(!1),[h,g]=(0,c.useState)(0),_=(0,c.useRef)(null),v=(0,c.useRef)(null),y=t.find(e=>e.id===n)?.label??``,[b,x]=(0,c.useState)(null);b!==y&&(x(y),l(y));let S=u.trim().toLowerCase(),C=S?t.filter(e=>e.label.toLowerCase().includes(S)):t,w={id:``,label:i},T=!S||i.toLowerCase().includes(S)?[w,...C]:C,E=()=>{f(``),g(0),m(!0)},D=()=>{m(!1),f(``),l(y)},O=e=>{r(e.id),l(e.id?e.label:``),f(``),m(!1)};return(0,c.useEffect)(()=>{if(!p)return;let e=e=>{_.current?.contains(e.target)||D()};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)}),(0,c.useEffect)(()=>{v.current?.children[h]?.scrollIntoView({block:`nearest`})},[h,p]),(0,d.jsxs)(`div`,{className:`node-search`,ref:_,children:[(0,d.jsx)(`input`,{id:e,type:`text`,value:s,placeholder:`-- type to search --`,autoComplete:`off`,onChange:e=>{l(e.target.value),f(e.target.value),g(0),m(!0)},onFocus:e=>{e.target.select(),E()},onClick:()=>{p||E()},onKeyDown:e=>{if(e.key===`ArrowDown`)e.preventDefault(),p||m(!0),g(e=>Math.min(e+1,T.length-1));else if(e.key===`ArrowUp`)e.preventDefault(),g(e=>Math.max(e-1,0));else if(e.key===`Enter`&&p){let t=T[h];t&&(e.preventDefault(),O(t))}else e.key===`Escape`&&D()}}),s&&(0,d.jsx)(`button`,{type:`button`,className:`node-search-clear`,"aria-label":`Clear`,onClick:()=>{r(``),l(``),f(``)},children:`×`}),p&&(0,d.jsx)(`ul`,{className:`node-search-list`,ref:v,role:`listbox`,children:T.length===0?(0,d.jsx)(`li`,{className:`node-search-empty`,role:`option`,"aria-selected":`false`,"aria-disabled":`true`,children:`no match`}):T.map((e,t)=>(0,d.jsxs)(`li`,{role:`option`,"aria-selected":t===h,className:[t===h&&`active`,a?.has(e.id)&&`off`].filter(Boolean).join(` `)||void 0,onMouseDown:t=>{t.preventDefault(),O(e)},onMouseEnter:()=>g(t),children:[o&&e.id&&(0,d.jsx)(`input`,{type:`checkbox`,checked:!a?.has(e.id),"aria-label":`Show ${e.label}`,onMouseDown:e=>{e.preventDefault(),e.stopPropagation()},onClick:e=>e.stopPropagation(),onChange:()=>o(e.id)}),e.label]},e.id||`__none__`))})]})}function X(e={},t=[],n=null,r={}){let i=Array.isArray(n)?n:null,a=n!==null&&!Array.isArray(n)?n:r,o=i!==null&&i.length>0,{selectedColor:s=f,parentsColor:u=p,childrenColor:b=m,track2ParentsColor:x=h,track2ChildrenColor:S=g,commonColor:k=_,topControlsFontSize:A=v,rightDisplayFontSize:j=y,layoutColumns:M=10}=a,N=q({selectedColor:s,parentsColor:u,childrenColor:b,track2ParentsColor:x,track2ChildrenColor:S}),F={"--rbg-parents-color":u,"--rbg-children-color":b},te={"--rbg-parents-color":x,"--rbg-children-color":S},R=B(e,t,i!==null&&o?i.flat():[]),H=i!==null&&o?L(i):z(R,M);function G(){let e=(0,c.useRef)(null),t=(0,c.useRef)(null),n=(0,c.useId)(),[r,i]=(0,c.useState)([]),[o,s]=(0,c.useState)(``),[u,f]=(0,c.useState)(0),[p,m]=(0,c.useState)(``),[h,g]=(0,c.useState)(`parents`),[_,v]=(0,c.useState)(``),[y,b]=(0,c.useState)(`parents`),[x,S]=(0,c.useState)(!0),[M,L]=(0,c.useState)(!0),[z,B]=(0,c.useState)(null),[G,K]=(0,c.useState)(null),[q,J]=(0,c.useState)(`top`),[X,se]=(0,c.useState)({top:0,right:0,graph:0}),[Z,ce]=(0,c.useState)(!1),Q=(0,c.useRef)(!1);(0,c.useEffect)(()=>{Q.current=Z},[Z]);let[$,le]=(0,c.useState)(()=>new Set);(0,c.useEffect)(()=>{let n=e.current;if(!n)return;let r=(0,l.default)({container:n,elements:ie(R,x,M),style:N,layout:{name:`preset`,fit:!1}});r.on(`cxttap`,P,e=>{let t=W(V(e.target,Q.current)),{clientX:n,clientY:r}=e.originalEvent;B({x:n,y:r,copyText:t})}),r.on(`dbltap`,P,e=>{K(V(e.target,Q.current))}),r.on(`tap cxttap`,e=>{e.target===r&&B(null)}),r.on(`tap`,`node`,()=>B(null)),r.on(`viewport`,()=>B(null));let o=e=>e.preventDefault();return n.addEventListener(`contextmenu`,o),re(r,H,a),requestAnimationFrame(()=>r.resize()),i(r.nodes(P).map(e=>({id:e.id(),label:e.data(`displayLabel`)})).sort((e,t)=>I(e.label,t.label))),t.current=r,()=>{n.removeEventListener(`contextmenu`,o),B(null),r.destroy(),t.current=null}},[x,M]),(0,c.useEffect)(()=>{let e=t.current;if(!e)return;let n=X.graph;e.batch(()=>{e.nodes(P).forEach(e=>{let t=D+n,{width:r,height:i}=ne(e.data(`graphLabel`),t);e.style({"font-size":t,width:r,height:i})}),e.nodes(`:parent`).style(`font-size`,O+n)})},[X.graph,x,M]),(0,c.useEffect)(()=>{if(!z)return;let e=e=>{e.target.closest(`.node-context-menu`)||B(null)},t=e=>{e.key===`Escape`&&B(null)};return document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t)}},[z]);let ue=()=>{if(z===null)return;let{copyText:e}=z;B(null),navigator.clipboard.writeText(e).catch(e=>{console.error(`Failed to copy:`,e)})},de=()=>{t.current&&C(t.current)},fe=e=>{le(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},pe=e=>{let n=t.current?.getElementById(e);n&&!n.empty()&&($.has(e)&&fe(e),s(e),K(V(n,Z)))},me=()=>{s(``),K(null),f(e=>e+1)};(0,c.useEffect)(()=>{let e=t.current;e&&e.batch(()=>{e.elements().removeClass(`hidden`),ae(e,$).addClass(`hidden`)})},[$,x,M]),(0,c.useEffect)(()=>{let e=t.current;u&&e&&(e.stop(),e.resize(),e.animate({fit:{eles:e.elements().not(`.hidden`),padding:30}},{duration:400}))},[u]),(0,c.useEffect)(()=>{let e=t.current;if(!e||(e.nodes().removeClass(`selected`),!o))return;let n=e.getElementById(o);n.nonempty()&&(n.addClass(`selected`),e.animate({center:{eles:n},zoom:1.8},{duration:400}))},[o,x,M]),(0,c.useEffect)(()=>{let e=t.current;e&&oe(e,[{id:p,direction:h},{id:_,direction:y}],k)},[p,h,_,y,x,M]),(0,c.useEffect)(()=>{t.current?.resize()},[G!==null]),(0,c.useEffect)(()=>{let e=()=>t.current?.resize();return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]);let he=[{n:1,id:p,setId:m,direction:h,setDirection:g,style:void 0},{n:2,id:_,setId:v,direction:y,setDirection:b,style:te}],ge=[{label:`Smaller text`,symbol:`−`,step:-2,atLimit:X[q]<=T},{label:`Larger text`,symbol:`+`,step:w,atLimit:X[q]>=E}];return(0,d.jsxs)(`div`,{className:`rbg-graph`,style:{...F,"--rbg-top-controls-font-size":`calc(${A} + ${X.top}px)`,"--rbg-right-display-font-size":`calc(${j} + ${X.right}px)`},children:[(0,d.jsxs)(`div`,{className:`controls`,children:[(0,d.jsxs)(`span`,{className:`control-group`,children:[(0,d.jsx)(`label`,{htmlFor:`${n}-search`,children:`Node to Display:`}),(0,d.jsx)(Y,{id:`${n}-search`,options:r,selectedId:o,onSelect:e=>e?pe(e):me(),hiddenIds:$,onToggleVisible:fe})]}),(0,d.jsxs)(`label`,{children:[(0,d.jsx)(`input`,{type:`checkbox`,checked:x,onChange:e=>S(e.target.checked)}),`Show Groups`]}),(0,d.jsxs)(`label`,{children:[(0,d.jsx)(`input`,{type:`checkbox`,checked:M,onChange:e=>L(e.target.checked)}),`Add Group to Node Name`]}),he.map(({n:e,id:t,setId:i,direction:a,setDirection:o,style:s})=>(0,d.jsxs)(`span`,{className:`control-group`,style:s,children:[(0,d.jsxs)(`label`,{htmlFor:`${n}-track${e}`,children:[`Show Dependency `,e,`:`]}),(0,d.jsx)(Y,{id:`${n}-track${e}`,options:r,selectedId:t,onSelect:i,noneLabel:`Show Nothing`}),(0,d.jsxs)(`span`,{className:t?`track-switch`:`track-switch disabled`,children:[(0,d.jsx)(`span`,{className:a===`parents`?`parents on`:`parents`,children:`Parents`}),(0,d.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":a===`children`,"aria-label":`Show Dependency ${e}: track children instead of parents`,className:`switch`,disabled:!t,onClick:()=>o(e=>e===`parents`?`children`:`parents`),children:(0,d.jsx)(`span`,{className:`switch-knob`})}),(0,d.jsx)(`span`,{className:a===`children`?`children on`:`children`,children:`Children`})]})]},e)),(0,d.jsxs)(`span`,{className:`help`,children:[(0,d.jsx)(`button`,{type:`button`,className:`help-icon`,"aria-label":`Help`,"aria-describedby":`${n}-help`,children:`?`}),(0,d.jsxs)(`span`,{id:`${n}-help`,role:`tooltip`,className:`help-tooltip`,children:[(0,d.jsx)(`strong`,{children:`Double click`}),` on a node to see its information, parents and children.`,(0,d.jsx)(`br`,{}),(0,d.jsx)(`strong`,{children:`Right click`}),` on a node to save the same information to the clipboard.`]})]}),(0,d.jsxs)(`span`,{className:`font-size-buttons`,children:[(0,d.jsx)(`select`,{"aria-label":`Area whose text size the + and - buttons change`,value:q,onChange:e=>J(e.target.value),children:ee.map(([e,t])=>(0,d.jsx)(`option`,{value:e,children:t},e))}),ge.map(({label:e,symbol:t,step:n,atLimit:r})=>(0,d.jsx)(`button`,{type:`button`,className:`help-icon`,"aria-label":e,disabled:r,onClick:()=>se(e=>({...e,[q]:e[q]+n})),children:t},e))]}),(0,d.jsx)(`button`,{type:`button`,className:`export-svg`,onClick:de,children:`Export SVG`})]}),(0,d.jsxs)(`div`,{className:`graph-area`,children:[(0,d.jsx)(`div`,{ref:e,className:`cy-container`}),G&&(0,d.jsxs)(`aside`,{className:`node-info-panel`,children:[(0,d.jsxs)(`div`,{className:`node-info-header`,children:[(0,d.jsxs)(`h2`,{children:[(0,d.jsx)(`strong`,{children:`Node:`}),` `,G.name]}),(0,d.jsx)(`button`,{type:`button`,onClick:()=>K(null),"aria-label":`Close`,children:`×`})]}),G.group&&(0,d.jsxs)(`p`,{children:[(0,d.jsx)(`strong`,{children:`Group:`}),` `,G.group]}),(0,d.jsxs)(`div`,{className:`track-switch level-switch`,children:[(0,d.jsx)(`span`,{className:Z?``:`parents on`,children:`One level`}),(0,d.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":Z,"aria-label":`Show all levels of parents and children`,className:`switch`,onClick:()=>{let e=!Z;ce(e);let n=t.current?.getElementById(G.id);n&&!n.empty()&&K(V(n,e))},children:(0,d.jsx)(`span`,{className:`switch-knob`})}),(0,d.jsx)(`span`,{className:Z?`children on`:``,children:`All levels`})]}),U(G).map(([e,t])=>(0,d.jsxs)(`section`,{children:[(0,d.jsxs)(`h3`,{children:[e,` (`,t.length,`):`]}),(0,d.jsx)(`ul`,{children:t.map(e=>(0,d.jsx)(`li`,{children:(0,d.jsxs)(`button`,{type:`button`,onClick:()=>pe(e.id),children:[e.name,e.group&&(0,d.jsxs)(`span`,{children:[` (`,e.group,`)`]})]})},e.id))})]},e))]})]}),z&&(0,d.jsx)(`div`,{className:`node-context-menu`,style:{left:z.x,top:z.y},onContextMenu:e=>e.preventDefault(),children:(0,d.jsx)(`button`,{type:`button`,onClick:ue,children:`Save to clipboard`})})]})}return G.displayName=`CytoscapeGraph`,G}exports.NodeSearch=Y,exports.create_graph=X,exports.downloadSvg=C,exports.formatNodeInfo=W,exports.getNodeInfo=V;
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|