@bencamus/vue3-tree-chart 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "name": "@bencamus/vue3-tree-chart",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "main": "src/index.ts",
5
5
  "module": "src/index.ts",
6
6
  "types": "src/index.ts",
7
7
  "style": "src/styles/vue3-tree-chart.css",
8
- "files": ["src"],
8
+ "files": [
9
+ "src"
10
+ ],
9
11
  "scripts": {
10
12
  "build": "vite build",
11
13
  "prepublishOnly": "echo 'No build required for source-only package'",
12
- "test": "echo \"Error: no test specified\" && exit 1"
14
+ "test": "echo \"Error: no test specified\" && exit 1",
15
+ "release": "semantic-release"
13
16
  },
14
17
  "devDependencies": {
15
18
  "@vitejs/plugin-vue": "^5.2.1",
16
19
  "@vue/tsconfig": "^0.7.0",
17
20
  "typescript": "~5.7.2",
18
21
  "vite": "^6.2.0",
19
- "less": "^4.2.2",
20
- "@types/node": "^20.0.0",
21
- "vite-plugin-less": "^2.0.0"
22
+ "@types/node": "^20.0.0"
22
23
  },
23
24
  "peerDependencies": {
24
25
  "vue": "^3.0.0",
@@ -26,4 +27,4 @@
26
27
  },
27
28
  "license": "MIT",
28
29
  "description": "Vue 3 component for tree chart visualization (source code)."
29
- }
30
+ }
@@ -1,247 +1,247 @@
1
- <template>
2
- <div class="tree-container" ref="container">
3
- <svg class="svg vue-tree" ref="svg" :style="initialTransformStyle"></svg>
4
- <div class="dom-container" ref="domContainer" :style="initialTransformStyle">
5
- <transition-group name="tree-node-item" tag="div">
6
- <div class="node-slot" v-for="(node, index) of nodeDataList" @click="onClickNode(index)" :key="node.data._key"
7
- :style="{
8
- left: formatDimension(
9
- direction === Direction.VERTICAL ? node.x : node.y
10
- ),
11
- top: formatDimension(
12
- direction === Direction.VERTICAL ? node.y : node.x
13
- ),
14
- width: formatDimension(config.nodeWidth),
15
- height: formatDimension(config.nodeHeight),
16
- }">
17
- <slot name="node" v-bind:node="node.data" v-bind:collapsed="node.data._collapsed">
18
- <span>{{ node.data.value }}</span>
19
- </slot>
20
- </div>
21
- </transition-group>
22
- </div>
23
- </div>
24
- </template>
25
-
26
- <script lang="ts">
27
- import { defineComponent, ref, onMounted, onBeforeUnmount, watch } from 'vue';
28
- import TreeChartCore, {
29
- DEFAULT_NODE_WIDTH,
30
- DEFAULT_NODE_HEIGHT,
31
- DEFAULT_LEVEL_HEIGHT,
32
- TreeLinkStyle,
33
- Direction,
34
- } from "@bencamus/tree-chart-core";
35
-
36
- interface TreeConfig {
37
- nodeWidth?: number;
38
- nodeHeight?: number;
39
- levelHeight?: number;
40
- focusToNode?: boolean;
41
- initiallyCollapsed?: boolean;
42
- useMobileZoom?: boolean;
43
- useMouseZoom?: boolean;
44
- collapseDepth?: number;
45
- }
46
-
47
- interface NodeData {
48
- x: number;
49
- y: number;
50
- data: {
51
- _key: string;
52
- _collapsed: boolean;
53
- value: string;
54
- [key: string]: any;
55
- };
56
- }
57
-
58
- const formatDimension = (dimension: number | string): string => {
59
- if (typeof dimension === "number") return `${dimension}px`;
60
- if (typeof dimension === "string" && dimension.indexOf("px") !== -1) {
61
- return dimension;
62
- }
63
- return `${dimension}px`;
64
- };
65
-
66
- export default defineComponent({
67
- name: "VueTree",
68
- props: {
69
- config: {
70
- type: Object as () => TreeConfig,
71
- default: () => ({
72
- nodeWidth: DEFAULT_NODE_WIDTH,
73
- nodeHeight: DEFAULT_NODE_HEIGHT,
74
- levelHeight: DEFAULT_LEVEL_HEIGHT,
75
- focusToNode: false,
76
- initiallyCollapsed: false,
77
- useMobileZoom: false,
78
- useMouseZoom: false,
79
- collapseDepth: 0,
80
- }),
81
- },
82
- linkStyle: {
83
- type: String as () => TreeLinkStyle,
84
- default: TreeLinkStyle.CURVE,
85
- },
86
- direction: {
87
- type: String as () => Direction,
88
- default: Direction.VERTICAL,
89
- },
90
- collapseEnabled: {
91
- type: Boolean,
92
- default: true,
93
- },
94
- dataset: {
95
- type: [Object, Array] as () => any,
96
- required: true,
97
- },
98
- },
99
- setup(props) {
100
- const container = ref<HTMLElement | null>(null);
101
- const svg = ref<SVGSVGElement | null>(null);
102
- const domContainer = ref<HTMLElement | null>(null);
103
- const treeChartCore = ref<TreeChartCore | null>(null);
104
- const nodeDataList = ref<NodeData[]>([]);
105
- const initialTransformStyle = ref<Record<string, string>>({});
106
-
107
- const init = () => {
108
- if (!svg.value || !domContainer.value || !container.value) return;
109
-
110
- treeChartCore.value = new TreeChartCore({
111
- svgElement: svg.value,
112
- domElement: domContainer.value,
113
- treeContainer: container.value,
114
- dataset: props.dataset,
115
- direction: props.direction,
116
- treeConfig: props.config,
117
- collapseEnabled: props.collapseEnabled,
118
- linkStyle: props.linkStyle,
119
- });
120
-
121
- treeChartCore.value.init();
122
- nodeDataList.value = treeChartCore.value.getNodeDataList();
123
- initialTransformStyle.value = treeChartCore.value.getInitialTransformStyle();
124
- };
125
-
126
- const zoomIn = () => treeChartCore.value?.zoomIn();
127
- const zoomOut = () => treeChartCore.value?.zoomOut();
128
- const restoreScale = () => treeChartCore.value?.setScale(1);
129
- const expandNodeByLevelAndPosition = (level: number, position: number) => {
130
- treeChartCore.value?.expandNodeByLevelAndPosition(level, position);
131
- nodeDataList.value = treeChartCore.value?.getNodeDataList() || [];
132
- };
133
- const restorePosition = () => treeChartCore.value?.restorePosition();
134
- const onClickNode = (index: number) => {
135
- treeChartCore.value?.onClickNode(index);
136
- nodeDataList.value = treeChartCore.value?.getNodeDataList() || [];
137
- if (props.config.focusToNode) {
138
- focusToNode(index);
139
- }
140
- };
141
- const focusToNode = (index: number) => treeChartCore.value?.focusToNode(index);
142
-
143
- onMounted(() => {
144
- init();
145
- });
146
-
147
- onBeforeUnmount(() => {
148
- treeChartCore.value?.destroy();
149
- });
150
-
151
- watch(
152
- () => props.dataset,
153
- (newDataset) => {
154
- treeChartCore.value?.updateDataset(newDataset);
155
- nodeDataList.value = treeChartCore.value?.getNodeDataList() || [];
156
- },
157
- { deep: true }
158
- );
159
-
160
- return {
161
- container,
162
- svg,
163
- domContainer,
164
- nodeDataList,
165
- initialTransformStyle,
166
- formatDimension,
167
- Direction,
168
- zoomIn,
169
- zoomOut,
170
- restoreScale,
171
- expandNodeByLevelAndPosition,
172
- restorePosition,
173
- onClickNode,
174
- focusToNode,
175
- };
176
- },
177
- });
178
- </script>
179
-
180
- <style>
181
- .tree-container .node {
182
- fill: grey !important;
183
- }
184
-
185
- .tree-container .link {
186
- stroke-width: 2px !important;
187
- fill: transparent !important;
188
- stroke: #cecece !important;
189
- }
190
-
191
- .tree-container .link-hidden {
192
- display: none;
193
- stroke-width: 2px !important;
194
- fill: transparent !important;
195
- stroke: #FC2020FF !important;
196
- }
197
-
198
- .tree-node-item-enter,
199
- .tree-node-item-leave-to {
200
- opacity: 0;
201
- }
202
-
203
- .tree-node-item-enter-active,
204
- .tree-node-item-leave-active {
205
-
206
- }
207
-
208
- .tree-container {
209
- touch-action: none;
210
- position: relative;
211
- overflow: hidden;
212
- }
213
-
214
- .tree-container .vue-tree {
215
- position: relative;
216
- }
217
-
218
- .tree-container > svg,
219
- .tree-container .dom-container {
220
- width: 100%;
221
- height: 100%;
222
- position: absolute;
223
- left: 0;
224
- top: 0;
225
- overflow: visible;
226
- transform-origin: 0 50%;
227
- }
228
-
229
- .tree-container .dom-container {
230
- z-index: 1;
231
- pointer-events: none;
232
- }
233
-
234
- .node-slot {
235
- cursor: pointer;
236
- pointer-events: all;
237
- position: absolute;
238
- background-color: transparent;
239
- box-sizing: border-box;
240
- transform: translate(-50%, -50%);
241
- display: flex;
242
- align-items: center;
243
- justify-content: center;
244
- box-sizing: content-box;
245
- transition-timing-function: ease-in-out;
246
- }
1
+ <template>
2
+ <div class="tree-container" ref="container">
3
+ <svg class="svg vue-tree" ref="svg" :style="initialTransformStyle"></svg>
4
+ <div class="dom-container" ref="domContainer" :style="initialTransformStyle">
5
+ <transition-group name="tree-node-item" tag="div">
6
+ <div class="node-slot" v-for="(node, index) of nodeDataList" @click="onClickNode(index)" :key="node.data._key"
7
+ :style="{
8
+ left: formatDimension(
9
+ direction === Direction.VERTICAL ? node.x : node.y
10
+ ),
11
+ top: formatDimension(
12
+ direction === Direction.VERTICAL ? node.y : node.x
13
+ ),
14
+ width: formatDimension(config.nodeWidth),
15
+ height: formatDimension(config.nodeHeight),
16
+ }">
17
+ <slot name="node" v-bind:node="node.data" v-bind:collapsed="node.data._collapsed">
18
+ <span>{{ node.data.value }}</span>
19
+ </slot>
20
+ </div>
21
+ </transition-group>
22
+ </div>
23
+ </div>
24
+ </template>
25
+
26
+ <script lang="ts">
27
+ import { defineComponent, ref, onMounted, onBeforeUnmount, watch } from 'vue';
28
+ import TreeChartCore, {
29
+ DEFAULT_NODE_WIDTH,
30
+ DEFAULT_NODE_HEIGHT,
31
+ DEFAULT_LEVEL_HEIGHT,
32
+ TreeLinkStyle,
33
+ Direction,
34
+ } from "../../../tree-chart-core/index.ts";
35
+
36
+ interface TreeConfig {
37
+ nodeWidth?: number;
38
+ nodeHeight?: number;
39
+ levelHeight?: number;
40
+ focusToNode?: boolean;
41
+ initiallyCollapsed?: boolean;
42
+ useMobileZoom?: boolean;
43
+ useMouseZoom?: boolean;
44
+ collapseDepth?: number;
45
+ }
46
+
47
+ interface NodeData {
48
+ x: number;
49
+ y: number;
50
+ data: {
51
+ _key: string;
52
+ _collapsed: boolean;
53
+ value: string;
54
+ [key: string]: any;
55
+ };
56
+ }
57
+
58
+ const formatDimension = (dimension: number | string): string => {
59
+ if (typeof dimension === "number") return `${dimension}px`;
60
+ if (typeof dimension === "string" && dimension.indexOf("px") !== -1) {
61
+ return dimension;
62
+ }
63
+ return `${dimension}px`;
64
+ };
65
+
66
+ export default defineComponent({
67
+ name: "VueTree",
68
+ props: {
69
+ config: {
70
+ type: Object as () => TreeConfig,
71
+ default: () => ({
72
+ nodeWidth: DEFAULT_NODE_WIDTH,
73
+ nodeHeight: DEFAULT_NODE_HEIGHT,
74
+ levelHeight: DEFAULT_LEVEL_HEIGHT,
75
+ focusToNode: false,
76
+ initiallyCollapsed: false,
77
+ useMobileZoom: false,
78
+ useMouseZoom: false,
79
+ collapseDepth: 0,
80
+ }),
81
+ },
82
+ linkStyle: {
83
+ type: String as () => TreeLinkStyle,
84
+ default: TreeLinkStyle.CURVE,
85
+ },
86
+ direction: {
87
+ type: String as () => Direction,
88
+ default: Direction.VERTICAL,
89
+ },
90
+ collapseEnabled: {
91
+ type: Boolean,
92
+ default: true,
93
+ },
94
+ dataset: {
95
+ type: [Object, Array] as () => any,
96
+ required: true,
97
+ },
98
+ },
99
+ setup(props) {
100
+ const container = ref<HTMLElement | null>(null);
101
+ const svg = ref<SVGSVGElement | null>(null);
102
+ const domContainer = ref<HTMLElement | null>(null);
103
+ const treeChartCore = ref<TreeChartCore | null>(null);
104
+ const nodeDataList = ref<NodeData[]>([]);
105
+ const initialTransformStyle = ref<Record<string, string>>({});
106
+
107
+ const init = () => {
108
+ if (!svg.value || !domContainer.value || !container.value) return;
109
+
110
+ treeChartCore.value = new TreeChartCore({
111
+ svgElement: svg.value,
112
+ domElement: domContainer.value,
113
+ treeContainer: container.value,
114
+ dataset: props.dataset,
115
+ direction: props.direction,
116
+ treeConfig: props.config,
117
+ collapseEnabled: props.collapseEnabled,
118
+ linkStyle: props.linkStyle,
119
+ });
120
+
121
+ treeChartCore.value.init();
122
+ nodeDataList.value = treeChartCore.value.getNodeDataList();
123
+ initialTransformStyle.value = treeChartCore.value.getInitialTransformStyle();
124
+ };
125
+
126
+ const zoomIn = () => treeChartCore.value?.zoomIn();
127
+ const zoomOut = () => treeChartCore.value?.zoomOut();
128
+ const restoreScale = () => treeChartCore.value?.setScale(1);
129
+ const expandNodeByLevelAndPosition = (level: number, position: number) => {
130
+ treeChartCore.value?.expandNodeByLevelAndPosition(level, position);
131
+ nodeDataList.value = treeChartCore.value?.getNodeDataList() || [];
132
+ };
133
+ const restorePosition = () => treeChartCore.value?.restorePosition();
134
+ const onClickNode = (index: number) => {
135
+ treeChartCore.value?.onClickNode(index);
136
+ nodeDataList.value = treeChartCore.value?.getNodeDataList() || [];
137
+ if (props.config.focusToNode) {
138
+ focusToNode(index);
139
+ }
140
+ };
141
+ const focusToNode = (index: number) => treeChartCore.value?.focusToNode(index);
142
+
143
+ onMounted(() => {
144
+ init();
145
+ });
146
+
147
+ onBeforeUnmount(() => {
148
+ treeChartCore.value?.destroy();
149
+ });
150
+
151
+ watch(
152
+ () => props.dataset,
153
+ (newDataset) => {
154
+ treeChartCore.value?.updateDataset(newDataset);
155
+ nodeDataList.value = treeChartCore.value?.getNodeDataList() || [];
156
+ },
157
+ { deep: true }
158
+ );
159
+
160
+ return {
161
+ container,
162
+ svg,
163
+ domContainer,
164
+ nodeDataList,
165
+ initialTransformStyle,
166
+ formatDimension,
167
+ Direction,
168
+ zoomIn,
169
+ zoomOut,
170
+ restoreScale,
171
+ expandNodeByLevelAndPosition,
172
+ restorePosition,
173
+ onClickNode,
174
+ focusToNode,
175
+ };
176
+ },
177
+ });
178
+ </script>
179
+
180
+ <style>
181
+ .tree-container .node {
182
+ fill: grey !important;
183
+ }
184
+
185
+ .tree-container .link {
186
+ stroke-width: 2px !important;
187
+ fill: transparent !important;
188
+ stroke: #cecece !important;
189
+ }
190
+
191
+ .tree-container .link-hidden {
192
+ display: none;
193
+ stroke-width: 2px !important;
194
+ fill: transparent !important;
195
+ stroke: #FC2020FF !important;
196
+ }
197
+
198
+ .tree-node-item-enter,
199
+ .tree-node-item-leave-to {
200
+ opacity: 0;
201
+ }
202
+
203
+ .tree-node-item-enter-active,
204
+ .tree-node-item-leave-active {
205
+
206
+ }
207
+
208
+ .tree-container {
209
+ touch-action: none;
210
+ position: relative;
211
+ overflow: hidden;
212
+ }
213
+
214
+ .tree-container .vue-tree {
215
+ position: relative;
216
+ }
217
+
218
+ .tree-container > svg,
219
+ .tree-container .dom-container {
220
+ width: 100%;
221
+ height: 100%;
222
+ position: absolute;
223
+ left: 0;
224
+ top: 0;
225
+ overflow: visible;
226
+ transform-origin: 0 50%;
227
+ }
228
+
229
+ .tree-container .dom-container {
230
+ z-index: 1;
231
+ pointer-events: none;
232
+ }
233
+
234
+ .node-slot {
235
+ cursor: pointer;
236
+ pointer-events: all;
237
+ position: absolute;
238
+ background-color: transparent;
239
+ box-sizing: border-box;
240
+ transform: translate(-50%, -50%);
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ box-sizing: content-box;
245
+ transition-timing-function: ease-in-out;
246
+ }
247
247
  </style>
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- import VueTree from './components/VueTree.vue';
2
-
1
+ import VueTree from './components/VueTree.vue';
2
+
3
3
  export default VueTree;