react-apextree 1.1.0 → 2.0.0-beta.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 CHANGED
@@ -40,11 +40,13 @@ function App() {
40
40
  return (
41
41
  <ApexTreeChart
42
42
  data={data}
43
- width={800}
44
- height={600}
45
- direction="top"
46
- nodeWidth={120}
47
- nodeHeight={80}
43
+ options={{
44
+ width: 800,
45
+ height: 600,
46
+ direction: "top",
47
+ nodeWidth: 120,
48
+ nodeHeight: 80,
49
+ }}
48
50
  />
49
51
  );
50
52
  }
@@ -61,28 +63,18 @@ import { ApexTreeChart, ApexTreeRef } from "react-apextree";
61
63
  function App() {
62
64
  const treeRef = useRef<ApexTreeRef>(null);
63
65
 
64
- const handleChangeLayout = () => {
65
- treeRef.current?.changeLayout("left");
66
- };
67
-
68
- const handleCollapse = (nodeId: string) => {
69
- treeRef.current?.collapse(nodeId);
70
- };
71
-
72
- const handleExpand = (nodeId: string) => {
73
- treeRef.current?.expand(nodeId);
74
- };
75
-
76
- const handleFitScreen = () => {
77
- treeRef.current?.fitScreen();
78
- };
79
-
80
66
  return (
81
67
  <div>
82
- <button onClick={handleChangeLayout}>Change Layout</button>
83
- <button onClick={handleFitScreen}>Fit Screen</button>
84
-
85
- <ApexTreeChart ref={treeRef} data={data} width={800} height={600} />
68
+ <button onClick={() => treeRef.current?.changeLayout("left")}>Change Layout</button>
69
+ <button onClick={() => treeRef.current?.fitScreen()}>Fit Screen</button>
70
+ <button onClick={() => treeRef.current?.collapse("2")}>Collapse node 2</button>
71
+ <button onClick={() => treeRef.current?.expand("2")}>Expand node 2</button>
72
+
73
+ <ApexTreeChart
74
+ ref={treeRef}
75
+ data={data}
76
+ options={{ width: 800, height: 600 }}
77
+ />
86
78
  </div>
87
79
  );
88
80
  }
@@ -93,62 +85,83 @@ function App() {
93
85
  ```tsx
94
86
  <ApexTreeChart
95
87
  data={data}
96
- width={800}
97
- height={600}
98
- contentKey="data"
99
- nodeWidth={150}
100
- nodeHeight={100}
101
- nodeTemplate={(content) => `
102
- <div style="display: flex; flex-direction: column; align-items: center; height: 100%;">
103
- <img
104
- src="${content.imageURL}"
105
- style="width: 50px; height: 50px; border-radius: 50%;"
106
- />
107
- <div style="font-weight: bold;">${content.name}</div>
108
- </div>
109
- `}
88
+ options={{
89
+ width: 800,
90
+ height: 600,
91
+ contentKey: "data",
92
+ nodeWidth: 150,
93
+ nodeHeight: 100,
94
+ nodeTemplate: (content) => `
95
+ <div style="display: flex; flex-direction: column; align-items: center; height: 100%;">
96
+ <img
97
+ src="${content.imageURL}"
98
+ style="width: 50px; height: 50px; border-radius: 50%;"
99
+ />
100
+ <div style="font-weight: bold;">${content.name}</div>
101
+ </div>
102
+ `,
103
+ }}
110
104
  />
111
105
  ```
112
106
 
113
107
  ## Props
114
108
 
115
- | Prop | Type | Default | Description |
116
- | ---------------------- | ---------------------------------------- | ------------ | ----------------------------------- |
117
- | `data` | `NodeData` | **required** | Tree data structure |
118
- | `width` | `number \| string` | `400` | Width of the container |
119
- | `height` | `number \| string` | `400` | Height of the container |
120
- | `direction` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'top'` | Direction of tree growth |
121
- | `contentKey` | `string` | `'name'` | Key for node content |
122
- | `siblingSpacing` | `number` | `50` | Spacing between siblings |
123
- | `childrenSpacing` | `number` | `50` | Spacing between parent and children |
124
- | `nodeWidth` | `number` | `50` | Width of nodes |
125
- | `nodeHeight` | `number` | `30` | Height of nodes |
126
- | `nodeTemplate` | `(content: unknown) => string` | - | Custom HTML template for nodes |
127
- | `nodeStyle` | `string` | - | CSS styles for nodes |
128
- | `nodeBGColor` | `string` | `'#FFFFFF'` | Node background color |
129
- | `nodeBGColorHover` | `string` | `'#FFFFFF'` | Node background color on hover |
130
- | `borderWidth` | `number` | `1` | Node border width |
131
- | `borderStyle` | `string` | `'solid'` | Node border style |
132
- | `borderRadius` | `string` | `'5px'` | Node border radius |
133
- | `borderColor` | `string` | `'#BCBCBC'` | Node border color |
134
- | `borderColorHover` | `string` | `'#5C6BC0'` | Node border color on hover |
135
- | `edgeWidth` | `number` | `1` | Edge line width |
136
- | `edgeColor` | `string` | `'#BCBCBC'` | Edge line color |
137
- | `edgeColorHover` | `string` | `'#5C6BC0'` | Edge line color on hover |
138
- | `fontSize` | `string` | `'14px'` | Font size |
139
- | `fontFamily` | `string` | - | Font family |
140
- | `fontWeight` | `string` | `'400'` | Font weight |
141
- | `fontColor` | `string` | `'#000000'` | Font color |
142
- | `highlightOnHover` | `boolean` | `true` | Enable highlight on hover |
143
- | `enableToolbar` | `boolean` | `false` | Show toolbar |
144
- | `enableExpandCollapse` | `boolean` | `false` | Enable expand/collapse buttons |
145
- | `enableTooltip` | `boolean` | `false` | Enable tooltips |
146
- | `tooltipTemplate` | `(content: unknown) => string` | - | Custom tooltip template |
147
- | `groupLeafNodes` | `boolean` | `false` | Stack leaf nodes |
148
- | `onNodeClick` | `(node: NodeData) => void` | - | Node click handler |
149
- | `className` | `string` | - | CSS class for container |
150
- | `style` | `CSSProperties` | - | Inline styles for container |
151
- | `canvasStyle` | `string` | - | CSS styles for canvas |
109
+ | Prop | Type | Default | Description |
110
+ | ------------- | --------------------------------------- | ------------ | ------------------------------------- |
111
+ | `data` | `NestedNode` | **required** | Tree data structure |
112
+ | `options` | `Omit<Partial<TreeOptions>, 'onNodeClick'>` | - | Tree configuration (see below) |
113
+ | `onNodeClick` | `(node: unknown) => void` | - | Callback fired when a node is clicked |
114
+ | `className` | `string` | - | CSS class for the container |
115
+ | `style` | `CSSProperties` | - | Inline styles for the container |
116
+
117
+ ### TreeOptions
118
+
119
+ All tree configuration is passed through the `options` prop:
120
+
121
+ | Option | Type | Default | Description |
122
+ | -------------------------------- | ------------------------------ | ----------- | ----------------------------------- |
123
+ | `width` | `number \| string` | `400` | Width of the container |
124
+ | `height` | `number \| string` | `400` | Height of the container |
125
+ | `direction` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'top'` | Direction of tree growth |
126
+ | `contentKey` | `string` | `'name'` | Key for node content |
127
+ | `siblingSpacing` | `number` | `50` | Spacing between siblings |
128
+ | `childrenSpacing` | `number` | `50` | Spacing between parent and children |
129
+ | `nodeWidth` | `number` | `50` | Width of nodes |
130
+ | `nodeHeight` | `number` | `30` | Height of nodes |
131
+ | `nodeTemplate` | `(content: string) => string` | - | Custom HTML template for nodes |
132
+ | `nodeStyle` | `string` | - | CSS styles for nodes |
133
+ | `nodeBGColor` | `string` | `'#FFFFFF'` | Node background color |
134
+ | `nodeBGColorHover` | `string` | `'#FFFFFF'` | Node background color on hover |
135
+ | `borderWidth` | `number` | `1` | Node border width |
136
+ | `borderStyle` | `string` | `'solid'` | Node border style |
137
+ | `borderRadius` | `string` | `'5px'` | Node border radius |
138
+ | `borderColor` | `string` | `'#BCBCBC'` | Node border color |
139
+ | `borderColorHover` | `string` | `'#5C6BC0'` | Node border color on hover |
140
+ | `edgeWidth` | `number` | `1` | Edge line width |
141
+ | `edgeColor` | `string` | `'#BCBCBC'` | Edge line color |
142
+ | `edgeColorHover` | `string` | `'#5C6BC0'` | Edge line color on hover |
143
+ | `fontSize` | `string` | `'14px'` | Font size |
144
+ | `fontFamily` | `string` | - | Font family |
145
+ | `fontWeight` | `string` | `'400'` | Font weight |
146
+ | `fontColor` | `string` | `'#000000'` | Font color |
147
+ | `highlightOnHover` | `boolean` | `true` | Enable highlight on hover |
148
+ | `enableToolbar` | `boolean` | `false` | Show toolbar |
149
+ | `enableExpandCollapse` | `boolean` | `false` | Enable expand/collapse buttons |
150
+ | `expandCollapseButtonBGColor` | `string` | - | Expand/collapse button background |
151
+ | `expandCollapseButtonBorderColor`| `string` | - | Expand/collapse button border |
152
+ | `enableTooltip` | `boolean` | `false` | Enable tooltips |
153
+ | `tooltipTemplate` | `(content: string) => string` | - | Custom tooltip template |
154
+ | `tooltipMaxWidth` | `number` | - | Tooltip max width |
155
+ | `tooltipMinWidth` | `number` | - | Tooltip min width |
156
+ | `tooltipBorderColor` | `string` | - | Tooltip border color |
157
+ | `tooltipBGColor` | `string` | - | Tooltip background color |
158
+ | `tooltipFontColor` | `string` | - | Tooltip font color |
159
+ | `tooltipFontSize` | `string` | - | Tooltip font size |
160
+ | `tooltipPadding` | `number` | - | Tooltip padding |
161
+ | `tooltipOffset` | `number` | - | Tooltip offset |
162
+ | `groupLeafNodes` | `boolean` | `false` | Stack leaf nodes |
163
+ | `groupLeafNodesSpacing` | `number` | - | Spacing when leaf nodes are grouped |
164
+ | `canvasStyle` | `string` | - | CSS styles for the canvas |
152
165
 
153
166
  ## Ref Methods
154
167
 
@@ -163,23 +176,12 @@ function App() {
163
176
  ## Data Structure
164
177
 
165
178
  ```ts
166
- interface NodeData<T = unknown> {
167
- id: string; // unique identifier
168
- name?: string; // display name (or use contentKey)
169
- data?: T; // custom data for templates
170
- options?: NodeOptions; // per-node styling
171
- children?: NodeData<T>[];
172
- }
173
-
174
- interface NodeOptions {
175
- nodeBGColor?: string;
176
- nodeBGColorHover?: string;
177
- borderColor?: string;
178
- borderColorHover?: string;
179
- fontSize?: string;
180
- fontFamily?: string;
181
- fontWeight?: string | number;
182
- fontColor?: string;
179
+ interface NestedNode<T = undefined> {
180
+ id: string; // unique identifier
181
+ name: string; // display label (or use contentKey to point at a different field)
182
+ data: T; // custom data payload, available in nodeTemplate / onNodeClick
183
+ children: NestedNode<T>[]; // child nodes; pass [] for leaf nodes
184
+ options?: Partial<TreeOptions>; // per-node visual overrides (font, border, tooltip)
183
185
  }
184
186
  ```
185
187
 
@@ -191,13 +193,61 @@ Full TypeScript support with exported types:
191
193
  import type {
192
194
  ApexTreeProps,
193
195
  ApexTreeRef,
194
- NodeData,
195
- NodeOptions,
196
- TreeDirection,
196
+ NestedNode,
197
+ TreeOptions,
197
198
  GraphInstance,
198
199
  } from "react-apextree";
199
200
  ```
200
201
 
202
+ ## Migrating from v1
203
+
204
+ **v2 is a breaking change.** All tree configuration options that were previously individual props are now grouped under a single `options` prop.
205
+
206
+ ### Before (v1)
207
+
208
+ ```tsx
209
+ <ApexTreeChart
210
+ data={data}
211
+ width={800}
212
+ height={600}
213
+ direction="top"
214
+ nodeWidth={200}
215
+ nodeHeight={80}
216
+ edgeColor="#ccc"
217
+ fontSize="14px"
218
+ enableExpandCollapse
219
+ onNodeClick={(node) => console.log(node)}
220
+ />
221
+ ```
222
+
223
+ ### After (v2)
224
+
225
+ ```tsx
226
+ <ApexTreeChart
227
+ data={data}
228
+ onNodeClick={(node) => console.log(node)}
229
+ options={{
230
+ width: 800,
231
+ height: 600,
232
+ direction: "top",
233
+ nodeWidth: 200,
234
+ nodeHeight: 80,
235
+ edgeColor: "#ccc",
236
+ fontSize: "14px",
237
+ enableExpandCollapse: true,
238
+ }}
239
+ />
240
+ ```
241
+
242
+ The `className` and `style` props remain at the top level (they style the container element, not the tree).
243
+
244
+ ### Updated type imports
245
+
246
+ ```diff
247
+ - import type { NodeData, NodeOptions, TreeDirection } from "react-apextree";
248
+ + import type { NestedNode, TreeOptions } from "react-apextree";
249
+ ```
250
+
201
251
  ## License
202
252
 
203
253
  React-Apextree uses the same dual-license model as ApexCharts. See [LICENSE](./LICENSE) for details.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var react=require('react'),h=require('apextree'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var h__default=/*#__PURE__*/_interopDefault(h);function x(i){h__default.default.setLicense(i);}function u(i){let{className:e,style:d,data:a,...c}=i,l={};for(let[r,n]of Object.entries(c))n!==void 0&&(l[r]=n);return l}var A=react.forwardRef(function(e,d){let{data:a,className:c,style:l}=e,r=react.useRef(null),n=react.useRef(null),f=react.useMemo(()=>u(e),[e.width,e.height,e.direction,e.contentKey,e.siblingSpacing,e.childrenSpacing,e.containerClassName,e.canvasStyle,e.nodeWidth,e.nodeHeight,e.nodeTemplate,e.nodeStyle,e.nodeClassName,e.nodeBGColor,e.nodeBGColorHover,e.borderWidth,e.borderStyle,e.borderRadius,e.borderColor,e.borderColorHover,e.edgeWidth,e.edgeColor,e.edgeColorHover,e.fontSize,e.fontFamily,e.fontWeight,e.fontColor,e.enableTooltip,e.tooltipId,e.tooltipTemplate,e.tooltipMaxWidth,e.tooltipMinWidth,e.tooltipBorderColor,e.tooltipBGColor,e.tooltipFontColor,e.tooltipFontSize,e.tooltipPadding,e.tooltipOffset,e.highlightOnHover,e.enableToolbar,e.enableExpandCollapse,e.expandCollapseButtonBGColor,e.expandCollapseButtonBorderColor,e.groupLeafNodes,e.groupLeafNodesSpacing,e.onNodeClick]);return react.useImperativeHandle(d,()=>({changeLayout:t=>{var o;(o=n.current)==null||o.changeLayout(t);},collapse:t=>{var o;(o=n.current)==null||o.collapse(t);},expand:t=>{var o;(o=n.current)==null||o.expand(t);},fitScreen:()=>{var t;(t=n.current)==null||t.fitScreen();},getGraph:()=>n.current}),[]),react.useEffect(()=>{if(!r.current||!a)return;r.current.innerHTML="";let t=new h__default.default(r.current,f);n.current=t.render(a);},[a,f]),jsxRuntime.jsx("div",{ref:r,className:c,style:l})});exports.ApexTreeChart=A;exports.setApexTreeLicense=x;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var react=require('react'),R=require('apextree'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var R__default=/*#__PURE__*/_interopDefault(R);var g=react.forwardRef(function(x,d){let{data:c,options:f,onNodeClick:t,className:m,style:T}=x,s=react.useRef(null),u=react.useRef(null),n=react.useRef(null),o=react.useRef(t);react.useEffect(()=>{o.current=t;});let l=react.useMemo(()=>({...f,...t!==void 0&&{onNodeClick:r=>{var e;return (e=o.current)==null?void 0:e.call(o,r)}}}),[f,t!==void 0]);return react.useImperativeHandle(d,()=>({changeLayout:r=>{var e;(e=n.current)==null||e.changeLayout(r);},collapse:r=>{var e;(e=n.current)==null||e.collapse(r);},expand:r=>{var e;(e=n.current)==null||e.expand(r);},fitScreen:()=>{var r;(r=n.current)==null||r.fitScreen();},getGraph:()=>n.current}),[]),react.useEffect(()=>{if(!s.current||!c)return;let r=new R__default.default(s.current,l);return u.current=r,n.current=r.render(c),()=>{var e;(e=u.current)==null||e.destroy(),u.current=null,n.current=null;}},[c,l]),jsxRuntime.jsx("div",{ref:s,className:m,style:T})});function I(a){R__default.default.setLicense(a);}exports.ApexTreeChart=g;exports.setApexTreeLicense=I;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/ApexTreeChart.tsx"],"names":["setApexTreeLicense","licenseKey","ApexTree","buildOptions","props","_className","_style","_data","options","cleanOptions","key","value","ApexTreeChart","forwardRef","ref","data","className","style","containerRef","useRef","graphRef","useMemo","useImperativeHandle","direction","_a","nodeId","useEffect","tree","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["import ApexTree from \"apextree\";\nimport type { ApexTreeProps } from \"./types\";\n\n/**\n * sets the ApexTree license key globally\n * should be called once at app initialization, before rendering any charts\n *\n * @param licenseKey - the license key string provided by ApexCharts\n *\n * @example\n * ```tsx\n * import { setApexTreeLicense } from 'react-apextree';\n *\n * // call this at the top of your app, before rendering any charts\n * setApexTreeLicense('your-license-key-here');\n * ```\n */\nexport function setApexTreeLicense(licenseKey: string): void {\n ApexTree.setLicense(licenseKey);\n}\n\n/**\n * extracts ApexTree options from React props\n * filters out react-specific props (className, style, data)\n */\nexport function buildOptions<T>(\n props: ApexTreeProps<T>\n): Record<string, unknown> {\n const {\n // exclude react-specific props\n className: _className,\n style: _style,\n data: _data,\n // everything else becomes options\n ...options\n } = props;\n\n // remove undefined values to let ApexTree use its defaults\n const cleanOptions: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(options)) {\n if (value !== undefined) {\n cleanOptions[key] = value;\n }\n }\n\n return cleanOptions;\n}\n\n/**\n * shallow comparison of two objects\n * used to detect option changes\n */\nexport function shallowEqual(\n obj1: Record<string, unknown>,\n obj2: Record<string, unknown>\n): boolean {\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (obj1[key] !== obj2[key]) {\n return false;\n }\n }\n\n return true;\n}\n","import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react';\nimport ApexTree from 'apextree';\nimport type { ApexTreeProps, ApexTreeRef, GraphInstance } from './types';\nimport { buildOptions } from './utils';\n\n/**\n * react wrapper component for ApexTree\n */\nexport const ApexTreeChart = forwardRef<ApexTreeRef, ApexTreeProps>(\n function ApexTreeChart(props, ref) {\n const { data, className, style } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const graphRef = useRef<GraphInstance | null>(null);\n\n // memoize options to prevent unnecessary re-renders\n const options = useMemo(() => buildOptions(props), [\n props.width,\n props.height,\n props.direction,\n props.contentKey,\n props.siblingSpacing,\n props.childrenSpacing,\n props.containerClassName,\n props.canvasStyle,\n props.nodeWidth,\n props.nodeHeight,\n props.nodeTemplate,\n props.nodeStyle,\n props.nodeClassName,\n props.nodeBGColor,\n props.nodeBGColorHover,\n props.borderWidth,\n props.borderStyle,\n props.borderRadius,\n props.borderColor,\n props.borderColorHover,\n props.edgeWidth,\n props.edgeColor,\n props.edgeColorHover,\n props.fontSize,\n props.fontFamily,\n props.fontWeight,\n props.fontColor,\n props.enableTooltip,\n props.tooltipId,\n props.tooltipTemplate,\n props.tooltipMaxWidth,\n props.tooltipMinWidth,\n props.tooltipBorderColor,\n props.tooltipBGColor,\n props.tooltipFontColor,\n props.tooltipFontSize,\n props.tooltipPadding,\n props.tooltipOffset,\n props.highlightOnHover,\n props.enableToolbar,\n props.enableExpandCollapse,\n props.expandCollapseButtonBGColor,\n props.expandCollapseButtonBorderColor,\n props.groupLeafNodes,\n props.groupLeafNodesSpacing,\n props.onNodeClick,\n ]);\n\n // expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n changeLayout: (direction) => {\n graphRef.current?.changeLayout(direction);\n },\n collapse: (nodeId) => {\n graphRef.current?.collapse(nodeId);\n },\n expand: (nodeId) => {\n graphRef.current?.expand(nodeId);\n },\n fitScreen: () => {\n graphRef.current?.fitScreen();\n },\n getGraph: () => graphRef.current,\n }), []);\n\n // render tree when data or options change\n useEffect(() => {\n if (!containerRef.current || !data) {\n return;\n }\n\n // clear previous content\n containerRef.current.innerHTML = '';\n\n // create new tree instance and render\n const tree = new ApexTree(containerRef.current, options);\n graphRef.current = tree.render(data as any) as GraphInstance;\n }, [data, options]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={style}\n />\n );\n }\n);"]}
1
+ {"version":3,"sources":["../src/ApexTreeChart.tsx","../src/utils.ts"],"names":["ApexTreeChart","forwardRef","props","ref","data","options","onNodeClick","className","style","containerRef","useRef","treeRef","graphRef","onNodeClickRef","useEffect","mergedOptions","useMemo","node","_a","useImperativeHandle","direction","nodeId","tree","ApexTree","jsx","setApexTreeLicense","licenseKey"],"mappings":"sNAaO,IAAMA,CAAAA,CAAgBC,gBAAAA,CAC3B,SAAuBC,CAAAA,CAAOC,CAAAA,CAAK,CACjC,GAAM,CAAE,IAAA,CAAAC,EAAM,OAAA,CAAAC,CAAAA,CAAS,WAAA,CAAAC,CAAAA,CAAa,SAAA,CAAAC,CAAAA,CAAW,MAAAC,CAAM,CAAA,CAAIN,CAAAA,CAEnDO,CAAAA,CAAeC,YAAAA,CAAuB,IAAI,EAC1CC,CAAAA,CAAUD,YAAAA,CAAwB,IAAI,CAAA,CACtCE,CAAAA,CAAWF,YAAAA,CAA6B,IAAI,CAAA,CAG5CG,CAAAA,CAAiBH,YAAAA,CAAOJ,CAAW,CAAA,CACzCQ,eAAAA,CAAU,IAAM,CACdD,CAAAA,CAAe,OAAA,CAAUP,EAC3B,CAAC,CAAA,CAGD,IAAMS,EAAgBC,aAAAA,CAAQ,KAAO,CACnC,GAAGX,CAAAA,CACH,GAAIC,IAAgB,MAAA,EAAa,CAC/B,WAAA,CAAcW,CAAAA,EAAe,CA/BrC,IAAAC,CAAAA,CA+BwC,OAAA,CAAAA,CAAAA,CAAAL,CAAAA,CAAe,OAAA,GAAf,IAAA,CAAA,MAAA,CAAAK,CAAAA,CAAA,IAAA,CAAAL,EAAyBI,CAAAA,CAAAA,CAC3D,CACF,CAAA,CAAA,CAAI,CAACZ,CAAAA,CAASC,CAAAA,GAAgB,MAAS,CAAC,CAAA,CAGxC,OAAAa,yBAAAA,CAAoBhB,CAAAA,CAAK,KAAO,CAC9B,aAAeiB,CAAAA,EAAc,CArCnC,IAAAF,CAAAA,CAAAA,CAsCQA,CAAAA,CAAAN,CAAAA,CAAS,OAAA,GAAT,IAAA,EAAAM,CAAAA,CAAkB,YAAA,CAAaE,CAAAA,EACjC,CAAA,CACA,QAAA,CAAWC,CAAAA,EAAW,CAxC5B,IAAAH,CAAAA,CAAAA,CAyCQA,CAAAA,CAAAN,CAAAA,CAAS,OAAA,GAAT,IAAA,EAAAM,EAAkB,QAAA,CAASG,CAAAA,EAC7B,CAAA,CACA,MAAA,CAASA,CAAAA,EAAW,CA3C1B,IAAAH,CAAAA,CAAAA,CA4CQA,CAAAA,CAAAN,CAAAA,CAAS,OAAA,GAAT,IAAA,EAAAM,CAAAA,CAAkB,MAAA,CAAOG,CAAAA,EAC3B,CAAA,CACA,SAAA,CAAW,IAAM,CA9CvB,IAAAH,CAAAA,CAAAA,CA+CQA,EAAAN,CAAAA,CAAS,OAAA,GAAT,IAAA,EAAAM,CAAAA,CAAkB,SAAA,GACpB,CAAA,CACA,QAAA,CAAU,IAAMN,CAAAA,CAAS,OAC3B,CAAA,CAAA,CAAI,EAAE,CAAA,CAGNE,gBAAU,IAAM,CACd,GAAI,CAACL,CAAAA,CAAa,OAAA,EAAW,CAACL,CAAAA,CAC5B,OAGF,IAAMkB,CAAAA,CAAO,IAAIC,kBAAAA,CAASd,CAAAA,CAAa,QAASM,CAAa,CAAA,CAC7D,OAAAJ,CAAAA,CAAQ,OAAA,CAAUW,CAAAA,CAClBV,EAAS,OAAA,CAAUU,CAAAA,CAAK,MAAA,CAAOlB,CAAI,CAAA,CAE5B,IAAM,CA9DnB,IAAAc,CAAAA,CAAAA,CA+DQA,CAAAA,CAAAP,CAAAA,CAAQ,OAAA,GAAR,IAAA,EAAAO,CAAAA,CAAiB,OAAA,EAAA,CACjBP,CAAAA,CAAQ,OAAA,CAAU,IAAA,CAClBC,CAAAA,CAAS,OAAA,CAAU,KACrB,CACF,CAAA,CAAG,CAACR,CAAAA,CAAMW,CAAa,CAAC,CAAA,CAGtBS,cAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKf,CAAAA,CACL,SAAA,CAAWF,CAAAA,CACX,KAAA,CAAOC,CAAAA,CACT,CAEJ,CACF,EC7DO,SAASiB,CAAAA,CAAmBC,CAAAA,CAA0B,CAC3DH,kBAAAA,CAAS,UAAA,CAAWG,CAAU,EAChC","file":"index.cjs","sourcesContent":["import {\n forwardRef,\n useEffect,\n useMemo,\n useImperativeHandle,\n useRef,\n} from 'react';\nimport ApexTree from 'apextree';\nimport type { ApexTreeProps, ApexTreeRef, GraphInstance } from './types';\n\n/**\n * react wrapper component for ApexTree\n */\nexport const ApexTreeChart = forwardRef<ApexTreeRef, ApexTreeProps>(\n function ApexTreeChart(props, ref) {\n const { data, options, onNodeClick, className, style } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const treeRef = useRef<ApexTree | null>(null);\n const graphRef = useRef<GraphInstance | null>(null);\n\n // keep onNodeClick in a ref so the effect doesn't re-run when the callback changes identity\n const onNodeClickRef = useRef(onNodeClick);\n useEffect(() => {\n onNodeClickRef.current = onNodeClick;\n });\n\n // merge onNodeClick into options; stable object identity when neither changes\n const mergedOptions = useMemo(() => ({\n ...options,\n ...(onNodeClick !== undefined && {\n onNodeClick: (node: unknown) => onNodeClickRef.current?.(node),\n }),\n }), [options, onNodeClick !== undefined]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n changeLayout: (direction) => {\n graphRef.current?.changeLayout(direction);\n },\n collapse: (nodeId) => {\n graphRef.current?.collapse(nodeId);\n },\n expand: (nodeId) => {\n graphRef.current?.expand(nodeId);\n },\n fitScreen: () => {\n graphRef.current?.fitScreen();\n },\n getGraph: () => graphRef.current,\n }), []);\n\n // render tree when data or options change; destroy previous instance on cleanup\n useEffect(() => {\n if (!containerRef.current || !data) {\n return;\n }\n\n const tree = new ApexTree(containerRef.current, mergedOptions);\n treeRef.current = tree;\n graphRef.current = tree.render(data) as GraphInstance;\n\n return () => {\n treeRef.current?.destroy();\n treeRef.current = null;\n graphRef.current = null;\n };\n }, [data, mergedOptions]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={style}\n />\n );\n }\n);\n","import ApexTree from \"apextree\";\n\n/**\n * sets the ApexTree license key globally\n * should be called once at app initialization, before rendering any charts\n *\n * @param licenseKey - the license key string provided by ApexCharts\n *\n * @example\n * ```tsx\n * import { setApexTreeLicense } from 'react-apextree';\n *\n * // call this at the top of your app, before rendering any charts\n * setApexTreeLicense('your-license-key-here');\n * ```\n */\nexport function setApexTreeLicense(licenseKey: string): void {\n ApexTree.setLicense(licenseKey);\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,38 +1,24 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
+ import { NestedNode, TreeOptions, TreeDirection } from 'apextree';
4
+ export { NestedNode, TreeOptions } from 'apextree';
3
5
 
4
- type TreeDirection = 'top' | 'bottom' | 'left' | 'right';
5
6
  /**
6
- * node data structure expected by ApexTree
7
- */
8
- interface NodeData<T = unknown> {
9
- readonly id: string;
10
- readonly name?: string;
11
- readonly data?: T;
12
- readonly options?: NodeOptions;
13
- readonly children?: Array<NodeData<T>>;
14
- }
15
- /**
16
- * per-node styling options
17
- */
18
- interface NodeOptions {
19
- nodeBGColor?: string;
20
- nodeBGColorHover?: string;
21
- borderColor?: string;
22
- borderColorHover?: string;
23
- fontSize?: string;
24
- fontFamily?: string;
25
- fontWeight?: string | number;
26
- fontColor?: string;
27
- }
28
- /**
29
- * graph instance returned by ApexTree.render()
7
+ * public API surface of the graph instance returned by ApexTree.render().
8
+ * Defined as a structural interface to avoid exposing private class members
9
+ * from the core Graph class in wrapper public types (prevents TS4094).
30
10
  */
31
11
  interface GraphInstance {
32
- changeLayout: (direction?: TreeDirection) => void;
33
- collapse: (nodeId: string) => void;
34
- expand: (nodeId: string) => void;
35
- fitScreen: () => void;
12
+ options: TreeOptions;
13
+ changeLayout(direction?: TreeDirection): void;
14
+ collapse(nodeId: string): void;
15
+ construct(data: NestedNode): void;
16
+ expand(nodeId: string): void;
17
+ fitScreen(): void;
18
+ render(options?: {
19
+ keepOldPosition?: boolean;
20
+ mode?: 'initial' | 'expand' | 'collapse' | 'data-update';
21
+ }): void;
36
22
  }
37
23
  /**
38
24
  * imperative methods exposed via ref
@@ -47,62 +33,26 @@ interface ApexTreeRef {
47
33
  /**
48
34
  * props for the ApexTree React component
49
35
  */
50
- interface ApexTreeProps<T = unknown> {
51
- data: NodeData<T>;
36
+ interface ApexTreeProps<T = undefined> {
37
+ /** Tree data structure */
38
+ data: NestedNode<T>;
39
+ /**
40
+ * Configuration options — imported from core apextree, zero local re-definition.
41
+ * onNodeClick is omitted here; use the top-level onNodeClick prop instead.
42
+ */
43
+ options?: Omit<Partial<TreeOptions>, 'onNodeClick'>;
44
+ /** Callback fired when a node is clicked */
45
+ onNodeClick?: (node: unknown) => void;
46
+ /** CSS class name for the container element */
52
47
  className?: string;
48
+ /** Inline styles for the container element */
53
49
  style?: CSSProperties;
54
- width?: number | string;
55
- height?: number | string;
56
- direction?: TreeDirection;
57
- siblingSpacing?: number;
58
- childrenSpacing?: number;
59
- containerClassName?: string;
60
- canvasStyle?: string;
61
- contentKey?: string;
62
- nodeWidth?: number;
63
- nodeHeight?: number;
64
- nodeTemplate?: (content: unknown) => string;
65
- nodeStyle?: string;
66
- nodeClassName?: string;
67
- nodeBGColor?: string;
68
- nodeBGColorHover?: string;
69
- borderWidth?: number;
70
- borderStyle?: string;
71
- borderRadius?: string;
72
- borderColor?: string;
73
- borderColorHover?: string;
74
- edgeWidth?: number;
75
- edgeColor?: string;
76
- edgeColorHover?: string;
77
- fontSize?: string;
78
- fontFamily?: string;
79
- fontWeight?: string;
80
- fontColor?: string;
81
- enableTooltip?: boolean;
82
- tooltipId?: string;
83
- tooltipTemplate?: (content: unknown) => string;
84
- tooltipMaxWidth?: number;
85
- tooltipMinWidth?: number;
86
- tooltipBorderColor?: string;
87
- tooltipBGColor?: string;
88
- tooltipFontColor?: string;
89
- tooltipFontSize?: string;
90
- tooltipPadding?: number;
91
- tooltipOffset?: number;
92
- highlightOnHover?: boolean;
93
- enableToolbar?: boolean;
94
- enableExpandCollapse?: boolean;
95
- expandCollapseButtonBGColor?: string;
96
- expandCollapseButtonBorderColor?: string;
97
- groupLeafNodes?: boolean;
98
- groupLeafNodesSpacing?: number;
99
- onNodeClick?: (node: NodeData<T>) => void;
100
50
  }
101
51
 
102
52
  /**
103
53
  * react wrapper component for ApexTree
104
54
  */
105
- declare const ApexTreeChart: react.ForwardRefExoticComponent<ApexTreeProps<unknown> & react.RefAttributes<ApexTreeRef>>;
55
+ declare const ApexTreeChart: react.ForwardRefExoticComponent<ApexTreeProps<undefined> & react.RefAttributes<ApexTreeRef>>;
106
56
 
107
57
  /**
108
58
  * sets the ApexTree license key globally
@@ -120,4 +70,4 @@ declare const ApexTreeChart: react.ForwardRefExoticComponent<ApexTreeProps<unkno
120
70
  */
121
71
  declare function setApexTreeLicense(licenseKey: string): void;
122
72
 
123
- export { ApexTreeChart, type ApexTreeProps, type ApexTreeRef, type GraphInstance, type NodeData, type NodeOptions, type TreeDirection, setApexTreeLicense };
73
+ export { ApexTreeChart, type ApexTreeProps, type ApexTreeRef, type GraphInstance, setApexTreeLicense };
package/dist/index.d.ts CHANGED
@@ -1,38 +1,24 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
+ import { NestedNode, TreeOptions, TreeDirection } from 'apextree';
4
+ export { NestedNode, TreeOptions } from 'apextree';
3
5
 
4
- type TreeDirection = 'top' | 'bottom' | 'left' | 'right';
5
6
  /**
6
- * node data structure expected by ApexTree
7
- */
8
- interface NodeData<T = unknown> {
9
- readonly id: string;
10
- readonly name?: string;
11
- readonly data?: T;
12
- readonly options?: NodeOptions;
13
- readonly children?: Array<NodeData<T>>;
14
- }
15
- /**
16
- * per-node styling options
17
- */
18
- interface NodeOptions {
19
- nodeBGColor?: string;
20
- nodeBGColorHover?: string;
21
- borderColor?: string;
22
- borderColorHover?: string;
23
- fontSize?: string;
24
- fontFamily?: string;
25
- fontWeight?: string | number;
26
- fontColor?: string;
27
- }
28
- /**
29
- * graph instance returned by ApexTree.render()
7
+ * public API surface of the graph instance returned by ApexTree.render().
8
+ * Defined as a structural interface to avoid exposing private class members
9
+ * from the core Graph class in wrapper public types (prevents TS4094).
30
10
  */
31
11
  interface GraphInstance {
32
- changeLayout: (direction?: TreeDirection) => void;
33
- collapse: (nodeId: string) => void;
34
- expand: (nodeId: string) => void;
35
- fitScreen: () => void;
12
+ options: TreeOptions;
13
+ changeLayout(direction?: TreeDirection): void;
14
+ collapse(nodeId: string): void;
15
+ construct(data: NestedNode): void;
16
+ expand(nodeId: string): void;
17
+ fitScreen(): void;
18
+ render(options?: {
19
+ keepOldPosition?: boolean;
20
+ mode?: 'initial' | 'expand' | 'collapse' | 'data-update';
21
+ }): void;
36
22
  }
37
23
  /**
38
24
  * imperative methods exposed via ref
@@ -47,62 +33,26 @@ interface ApexTreeRef {
47
33
  /**
48
34
  * props for the ApexTree React component
49
35
  */
50
- interface ApexTreeProps<T = unknown> {
51
- data: NodeData<T>;
36
+ interface ApexTreeProps<T = undefined> {
37
+ /** Tree data structure */
38
+ data: NestedNode<T>;
39
+ /**
40
+ * Configuration options — imported from core apextree, zero local re-definition.
41
+ * onNodeClick is omitted here; use the top-level onNodeClick prop instead.
42
+ */
43
+ options?: Omit<Partial<TreeOptions>, 'onNodeClick'>;
44
+ /** Callback fired when a node is clicked */
45
+ onNodeClick?: (node: unknown) => void;
46
+ /** CSS class name for the container element */
52
47
  className?: string;
48
+ /** Inline styles for the container element */
53
49
  style?: CSSProperties;
54
- width?: number | string;
55
- height?: number | string;
56
- direction?: TreeDirection;
57
- siblingSpacing?: number;
58
- childrenSpacing?: number;
59
- containerClassName?: string;
60
- canvasStyle?: string;
61
- contentKey?: string;
62
- nodeWidth?: number;
63
- nodeHeight?: number;
64
- nodeTemplate?: (content: unknown) => string;
65
- nodeStyle?: string;
66
- nodeClassName?: string;
67
- nodeBGColor?: string;
68
- nodeBGColorHover?: string;
69
- borderWidth?: number;
70
- borderStyle?: string;
71
- borderRadius?: string;
72
- borderColor?: string;
73
- borderColorHover?: string;
74
- edgeWidth?: number;
75
- edgeColor?: string;
76
- edgeColorHover?: string;
77
- fontSize?: string;
78
- fontFamily?: string;
79
- fontWeight?: string;
80
- fontColor?: string;
81
- enableTooltip?: boolean;
82
- tooltipId?: string;
83
- tooltipTemplate?: (content: unknown) => string;
84
- tooltipMaxWidth?: number;
85
- tooltipMinWidth?: number;
86
- tooltipBorderColor?: string;
87
- tooltipBGColor?: string;
88
- tooltipFontColor?: string;
89
- tooltipFontSize?: string;
90
- tooltipPadding?: number;
91
- tooltipOffset?: number;
92
- highlightOnHover?: boolean;
93
- enableToolbar?: boolean;
94
- enableExpandCollapse?: boolean;
95
- expandCollapseButtonBGColor?: string;
96
- expandCollapseButtonBorderColor?: string;
97
- groupLeafNodes?: boolean;
98
- groupLeafNodesSpacing?: number;
99
- onNodeClick?: (node: NodeData<T>) => void;
100
50
  }
101
51
 
102
52
  /**
103
53
  * react wrapper component for ApexTree
104
54
  */
105
- declare const ApexTreeChart: react.ForwardRefExoticComponent<ApexTreeProps<unknown> & react.RefAttributes<ApexTreeRef>>;
55
+ declare const ApexTreeChart: react.ForwardRefExoticComponent<ApexTreeProps<undefined> & react.RefAttributes<ApexTreeRef>>;
106
56
 
107
57
  /**
108
58
  * sets the ApexTree license key globally
@@ -120,4 +70,4 @@ declare const ApexTreeChart: react.ForwardRefExoticComponent<ApexTreeProps<unkno
120
70
  */
121
71
  declare function setApexTreeLicense(licenseKey: string): void;
122
72
 
123
- export { ApexTreeChart, type ApexTreeProps, type ApexTreeRef, type GraphInstance, type NodeData, type NodeOptions, type TreeDirection, setApexTreeLicense };
73
+ export { ApexTreeChart, type ApexTreeProps, type ApexTreeRef, type GraphInstance, setApexTreeLicense };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import {forwardRef,useRef,useMemo,useImperativeHandle,useEffect}from'react';import h from'apextree';import {jsx}from'react/jsx-runtime';function x(i){h.setLicense(i);}function u(i){let{className:e,style:d,data:a,...c}=i,l={};for(let[r,n]of Object.entries(c))n!==void 0&&(l[r]=n);return l}var A=forwardRef(function(e,d){let{data:a,className:c,style:l}=e,r=useRef(null),n=useRef(null),f=useMemo(()=>u(e),[e.width,e.height,e.direction,e.contentKey,e.siblingSpacing,e.childrenSpacing,e.containerClassName,e.canvasStyle,e.nodeWidth,e.nodeHeight,e.nodeTemplate,e.nodeStyle,e.nodeClassName,e.nodeBGColor,e.nodeBGColorHover,e.borderWidth,e.borderStyle,e.borderRadius,e.borderColor,e.borderColorHover,e.edgeWidth,e.edgeColor,e.edgeColorHover,e.fontSize,e.fontFamily,e.fontWeight,e.fontColor,e.enableTooltip,e.tooltipId,e.tooltipTemplate,e.tooltipMaxWidth,e.tooltipMinWidth,e.tooltipBorderColor,e.tooltipBGColor,e.tooltipFontColor,e.tooltipFontSize,e.tooltipPadding,e.tooltipOffset,e.highlightOnHover,e.enableToolbar,e.enableExpandCollapse,e.expandCollapseButtonBGColor,e.expandCollapseButtonBorderColor,e.groupLeafNodes,e.groupLeafNodesSpacing,e.onNodeClick]);return useImperativeHandle(d,()=>({changeLayout:t=>{var o;(o=n.current)==null||o.changeLayout(t);},collapse:t=>{var o;(o=n.current)==null||o.collapse(t);},expand:t=>{var o;(o=n.current)==null||o.expand(t);},fitScreen:()=>{var t;(t=n.current)==null||t.fitScreen();},getGraph:()=>n.current}),[]),useEffect(()=>{if(!r.current||!a)return;r.current.innerHTML="";let t=new h(r.current,f);n.current=t.render(a);},[a,f]),jsx("div",{ref:r,className:c,style:l})});export{A as ApexTreeChart,x as setApexTreeLicense};//# sourceMappingURL=index.js.map
1
+ import {forwardRef,useRef,useEffect,useMemo,useImperativeHandle}from'react';import R from'apextree';import {jsx}from'react/jsx-runtime';var g=forwardRef(function(x,d){let{data:c,options:f,onNodeClick:t,className:m,style:T}=x,s=useRef(null),u=useRef(null),n=useRef(null),o=useRef(t);useEffect(()=>{o.current=t;});let l=useMemo(()=>({...f,...t!==void 0&&{onNodeClick:r=>{var e;return (e=o.current)==null?void 0:e.call(o,r)}}}),[f,t!==void 0]);return useImperativeHandle(d,()=>({changeLayout:r=>{var e;(e=n.current)==null||e.changeLayout(r);},collapse:r=>{var e;(e=n.current)==null||e.collapse(r);},expand:r=>{var e;(e=n.current)==null||e.expand(r);},fitScreen:()=>{var r;(r=n.current)==null||r.fitScreen();},getGraph:()=>n.current}),[]),useEffect(()=>{if(!s.current||!c)return;let r=new R(s.current,l);return u.current=r,n.current=r.render(c),()=>{var e;(e=u.current)==null||e.destroy(),u.current=null,n.current=null;}},[c,l]),jsx("div",{ref:s,className:m,style:T})});function I(a){R.setLicense(a);}export{g as ApexTreeChart,I as setApexTreeLicense};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/ApexTreeChart.tsx"],"names":["setApexTreeLicense","licenseKey","ApexTree","buildOptions","props","_className","_style","_data","options","cleanOptions","key","value","ApexTreeChart","forwardRef","ref","data","className","style","containerRef","useRef","graphRef","useMemo","useImperativeHandle","direction","_a","nodeId","useEffect","tree","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import ApexTree from \"apextree\";\nimport type { ApexTreeProps } from \"./types\";\n\n/**\n * sets the ApexTree license key globally\n * should be called once at app initialization, before rendering any charts\n *\n * @param licenseKey - the license key string provided by ApexCharts\n *\n * @example\n * ```tsx\n * import { setApexTreeLicense } from 'react-apextree';\n *\n * // call this at the top of your app, before rendering any charts\n * setApexTreeLicense('your-license-key-here');\n * ```\n */\nexport function setApexTreeLicense(licenseKey: string): void {\n ApexTree.setLicense(licenseKey);\n}\n\n/**\n * extracts ApexTree options from React props\n * filters out react-specific props (className, style, data)\n */\nexport function buildOptions<T>(\n props: ApexTreeProps<T>\n): Record<string, unknown> {\n const {\n // exclude react-specific props\n className: _className,\n style: _style,\n data: _data,\n // everything else becomes options\n ...options\n } = props;\n\n // remove undefined values to let ApexTree use its defaults\n const cleanOptions: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(options)) {\n if (value !== undefined) {\n cleanOptions[key] = value;\n }\n }\n\n return cleanOptions;\n}\n\n/**\n * shallow comparison of two objects\n * used to detect option changes\n */\nexport function shallowEqual(\n obj1: Record<string, unknown>,\n obj2: Record<string, unknown>\n): boolean {\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (obj1[key] !== obj2[key]) {\n return false;\n }\n }\n\n return true;\n}\n","import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react';\nimport ApexTree from 'apextree';\nimport type { ApexTreeProps, ApexTreeRef, GraphInstance } from './types';\nimport { buildOptions } from './utils';\n\n/**\n * react wrapper component for ApexTree\n */\nexport const ApexTreeChart = forwardRef<ApexTreeRef, ApexTreeProps>(\n function ApexTreeChart(props, ref) {\n const { data, className, style } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const graphRef = useRef<GraphInstance | null>(null);\n\n // memoize options to prevent unnecessary re-renders\n const options = useMemo(() => buildOptions(props), [\n props.width,\n props.height,\n props.direction,\n props.contentKey,\n props.siblingSpacing,\n props.childrenSpacing,\n props.containerClassName,\n props.canvasStyle,\n props.nodeWidth,\n props.nodeHeight,\n props.nodeTemplate,\n props.nodeStyle,\n props.nodeClassName,\n props.nodeBGColor,\n props.nodeBGColorHover,\n props.borderWidth,\n props.borderStyle,\n props.borderRadius,\n props.borderColor,\n props.borderColorHover,\n props.edgeWidth,\n props.edgeColor,\n props.edgeColorHover,\n props.fontSize,\n props.fontFamily,\n props.fontWeight,\n props.fontColor,\n props.enableTooltip,\n props.tooltipId,\n props.tooltipTemplate,\n props.tooltipMaxWidth,\n props.tooltipMinWidth,\n props.tooltipBorderColor,\n props.tooltipBGColor,\n props.tooltipFontColor,\n props.tooltipFontSize,\n props.tooltipPadding,\n props.tooltipOffset,\n props.highlightOnHover,\n props.enableToolbar,\n props.enableExpandCollapse,\n props.expandCollapseButtonBGColor,\n props.expandCollapseButtonBorderColor,\n props.groupLeafNodes,\n props.groupLeafNodesSpacing,\n props.onNodeClick,\n ]);\n\n // expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n changeLayout: (direction) => {\n graphRef.current?.changeLayout(direction);\n },\n collapse: (nodeId) => {\n graphRef.current?.collapse(nodeId);\n },\n expand: (nodeId) => {\n graphRef.current?.expand(nodeId);\n },\n fitScreen: () => {\n graphRef.current?.fitScreen();\n },\n getGraph: () => graphRef.current,\n }), []);\n\n // render tree when data or options change\n useEffect(() => {\n if (!containerRef.current || !data) {\n return;\n }\n\n // clear previous content\n containerRef.current.innerHTML = '';\n\n // create new tree instance and render\n const tree = new ApexTree(containerRef.current, options);\n graphRef.current = tree.render(data as any) as GraphInstance;\n }, [data, options]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={style}\n />\n );\n }\n);"]}
1
+ {"version":3,"sources":["../src/ApexTreeChart.tsx","../src/utils.ts"],"names":["ApexTreeChart","forwardRef","props","ref","data","options","onNodeClick","className","style","containerRef","useRef","treeRef","graphRef","onNodeClickRef","useEffect","mergedOptions","useMemo","node","_a","useImperativeHandle","direction","nodeId","tree","ApexTree","jsx","setApexTreeLicense","licenseKey"],"mappings":"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","file":"index.js","sourcesContent":["import {\n forwardRef,\n useEffect,\n useMemo,\n useImperativeHandle,\n useRef,\n} from 'react';\nimport ApexTree from 'apextree';\nimport type { ApexTreeProps, ApexTreeRef, GraphInstance } from './types';\n\n/**\n * react wrapper component for ApexTree\n */\nexport const ApexTreeChart = forwardRef<ApexTreeRef, ApexTreeProps>(\n function ApexTreeChart(props, ref) {\n const { data, options, onNodeClick, className, style } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const treeRef = useRef<ApexTree | null>(null);\n const graphRef = useRef<GraphInstance | null>(null);\n\n // keep onNodeClick in a ref so the effect doesn't re-run when the callback changes identity\n const onNodeClickRef = useRef(onNodeClick);\n useEffect(() => {\n onNodeClickRef.current = onNodeClick;\n });\n\n // merge onNodeClick into options; stable object identity when neither changes\n const mergedOptions = useMemo(() => ({\n ...options,\n ...(onNodeClick !== undefined && {\n onNodeClick: (node: unknown) => onNodeClickRef.current?.(node),\n }),\n }), [options, onNodeClick !== undefined]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n changeLayout: (direction) => {\n graphRef.current?.changeLayout(direction);\n },\n collapse: (nodeId) => {\n graphRef.current?.collapse(nodeId);\n },\n expand: (nodeId) => {\n graphRef.current?.expand(nodeId);\n },\n fitScreen: () => {\n graphRef.current?.fitScreen();\n },\n getGraph: () => graphRef.current,\n }), []);\n\n // render tree when data or options change; destroy previous instance on cleanup\n useEffect(() => {\n if (!containerRef.current || !data) {\n return;\n }\n\n const tree = new ApexTree(containerRef.current, mergedOptions);\n treeRef.current = tree;\n graphRef.current = tree.render(data) as GraphInstance;\n\n return () => {\n treeRef.current?.destroy();\n treeRef.current = null;\n graphRef.current = null;\n };\n }, [data, mergedOptions]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={style}\n />\n );\n }\n);\n","import ApexTree from \"apextree\";\n\n/**\n * sets the ApexTree license key globally\n * should be called once at app initialization, before rendering any charts\n *\n * @param licenseKey - the license key string provided by ApexCharts\n *\n * @example\n * ```tsx\n * import { setApexTreeLicense } from 'react-apextree';\n *\n * // call this at the top of your app, before rendering any charts\n * setApexTreeLicense('your-license-key-here');\n * ```\n */\nexport function setApexTreeLicense(licenseKey: string): void {\n ApexTree.setLicense(licenseKey);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-apextree",
3
- "version": "1.1.0",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "React wrapper for ApexTree - a JavaScript library for creating organizational and hierarchical charts",
5
5
  "author": "ApexCharts",
6
6
  "license": "See LICENSE in LICENSE",
@@ -54,14 +54,14 @@
54
54
  "demo:build": "npm run --prefix demo build"
55
55
  },
56
56
  "peerDependencies": {
57
- "apextree": ">=1.6.1",
57
+ "apextree": ">=1.9.0",
58
58
  "react": ">=17.0.0",
59
59
  "react-dom": ">=17.0.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/react": "^19.2.7",
63
63
  "@types/react-dom": "^19.2.3",
64
- "apextree": "^1.6.1",
64
+ "apextree": "^1.9.0",
65
65
  "react": "^19.2.3",
66
66
  "react-dom": "^19.2.3",
67
67
  "tsup": "^8.5.1",