|
18 | 18 | * |
19 | 19 | * @default 0 |
20 | 20 | */ |
21 | | - padding?: number; |
| 21 | + padding?: number | ((node: HierarchyRectangularNode<T>) => number); |
22 | 22 |
|
23 | 23 | /** |
24 | 24 | * The inner padding between nodes. |
25 | 25 | * |
26 | 26 | * @default 0 |
27 | 27 | */ |
28 | | - paddingInner?: number; |
| 28 | + paddingInner?: number | ((node: HierarchyRectangularNode<T>) => number); |
29 | 29 |
|
30 | 30 | /** |
31 | 31 | * The outer padding between nodes. |
32 | 32 | * |
33 | 33 | * @default 0 |
34 | 34 | */ |
35 | | - paddingOuter?: number; |
| 35 | + paddingOuter?: number | ((node: HierarchyRectangularNode<T>) => number); |
36 | 36 |
|
37 | 37 | /** |
38 | 38 | * The top padding between nodes. |
39 | 39 | * |
40 | 40 | * @default 0 |
41 | 41 | */ |
42 | | - paddingTop?: number; |
| 42 | + paddingTop?: number | ((node: HierarchyRectangularNode<T>) => number); |
43 | 43 |
|
44 | 44 | /** |
45 | 45 | * The bottom padding between nodes. |
46 | 46 | * |
47 | 47 | * @default 0 |
48 | 48 | */ |
49 | | - paddingBottom?: number; |
| 49 | + paddingBottom?: number | ((node: HierarchyRectangularNode<T>) => number); |
50 | 50 | /** |
51 | 51 | * The left padding between nodes. |
52 | 52 | * |
53 | 53 | */ |
54 | | - paddingLeft?: number; |
| 54 | + paddingLeft?: number | ((node: HierarchyRectangularNode<T>) => number); |
55 | 55 |
|
56 | 56 | /** |
57 | 57 | * The right padding between nodes. |
58 | 58 | * |
59 | 59 | */ |
60 | | - paddingRight?: number; |
| 60 | + paddingRight?: number | ((node: HierarchyRectangularNode<T>) => number); |
61 | 61 |
|
62 | 62 | /** |
63 | | - * The selected node. |
| 63 | + * Modify tiling function for approapriate aspect ratio when treemap is zoomed in |
64 | 64 | * |
65 | | - * @default null |
| 65 | + * @default false |
66 | 66 | */ |
67 | | - selected?: HierarchyRectangularNode<T> | null; |
| 67 | + maintainAspectRatio?: boolean; |
68 | 68 |
|
69 | 69 | hierarchy?: HierarchyNode<T>; |
70 | 70 |
|
|
99 | 99 | paddingBottom = 0, |
100 | 100 | paddingLeft, |
101 | 101 | paddingRight, |
102 | | - selected = $bindable(null), |
| 102 | + maintainAspectRatio = false, |
103 | 103 | children, |
104 | 104 | }: TreemapProps<T> = $props(); |
105 | 105 |
|
|
121 | 121 | : tile |
122 | 122 | ); |
123 | 123 |
|
124 | | - const treemap = $derived.by(() => { |
| 124 | + const treemapData = $derived.by(() => { |
125 | 125 | const _treemap = d3treemap<T>() |
126 | 126 | .size([ctx.width, ctx.height]) |
127 | | - .tile(aspectTile(tileFunc, ctx.width, ctx.height)); |
| 127 | + .tile(maintainAspectRatio ? aspectTile(tileFunc, ctx.width, ctx.height) : tileFunc); |
128 | 128 |
|
129 | 129 | if (padding) { |
130 | | - _treemap.padding(padding); |
| 130 | + // Make Typescript happy to pick the correct overload |
| 131 | + // TODO: Better way to do this? |
| 132 | + if (typeof padding === 'number') { |
| 133 | + _treemap.padding(padding); |
| 134 | + } else { |
| 135 | + _treemap.padding(padding); |
| 136 | + } |
131 | 137 | } |
132 | 138 |
|
133 | 139 | if (paddingInner) { |
134 | | - _treemap.paddingInner(paddingInner); |
| 140 | + if (typeof paddingInner === 'number') { |
| 141 | + _treemap.paddingInner(typeof paddingInner === 'number' ? paddingInner : paddingInner); |
| 142 | + } else { |
| 143 | + _treemap.paddingInner(paddingInner); |
| 144 | + } |
135 | 145 | } |
136 | 146 |
|
137 | 147 | if (paddingOuter) { |
138 | | - _treemap.paddingOuter(paddingOuter); |
| 148 | + if (typeof paddingOuter === 'number') { |
| 149 | + _treemap.paddingOuter(paddingOuter); |
| 150 | + } else { |
| 151 | + _treemap.paddingOuter(paddingOuter); |
| 152 | + } |
139 | 153 | } |
140 | 154 |
|
141 | 155 | if (paddingTop) { |
142 | | - _treemap.paddingTop(paddingTop); |
| 156 | + if (typeof paddingTop === 'number') { |
| 157 | + _treemap.paddingTop(paddingTop); |
| 158 | + } else { |
| 159 | + _treemap.paddingTop(paddingTop); |
| 160 | + } |
143 | 161 | } |
144 | 162 |
|
145 | 163 | if (paddingBottom) { |
146 | | - _treemap.paddingBottom(paddingBottom); |
| 164 | + if (typeof paddingBottom === 'number') { |
| 165 | + _treemap.paddingBottom(paddingBottom); |
| 166 | + } else { |
| 167 | + _treemap.paddingBottom(paddingBottom); |
| 168 | + } |
147 | 169 | } |
148 | 170 |
|
149 | 171 | if (paddingLeft) { |
150 | | - _treemap.paddingLeft(paddingLeft); |
| 172 | + if (typeof paddingLeft === 'number') { |
| 173 | + _treemap.paddingLeft(paddingLeft); |
| 174 | + } else { |
| 175 | + _treemap.paddingLeft(paddingLeft); |
| 176 | + } |
151 | 177 | } |
152 | 178 | if (paddingRight) { |
153 | | - _treemap.paddingRight(paddingRight); |
| 179 | + if (typeof paddingRight === 'number') { |
| 180 | + _treemap.paddingRight(paddingRight); |
| 181 | + } else { |
| 182 | + _treemap.paddingRight(paddingRight); |
| 183 | + } |
154 | 184 | } |
155 | | - return _treemap; |
156 | | - }); |
157 | 185 |
|
158 | | - const treemapData = $derived(hierarchy ? treemap(hierarchy) : null); |
| 186 | + if (hierarchy) { |
| 187 | + const h = hierarchy.copy(); |
| 188 | + const treemapData = _treemap(h); |
| 189 | + return { |
| 190 | + links: treemapData.links(), |
| 191 | + nodes: treemapData.descendants(), |
| 192 | + }; |
| 193 | + } |
159 | 194 |
|
160 | | - $effect.pre(() => { |
161 | | - selected = treemapData; |
| 195 | + return { |
| 196 | + links: [], |
| 197 | + nodes: [], |
| 198 | + }; |
162 | 199 | }); |
163 | 200 | </script> |
164 | 201 |
|
165 | | -{@render children?.({ nodes: treemapData ? treemapData.descendants() : [] })} |
| 202 | +{@render children?.({ nodes: treemapData.nodes })} |
0 commit comments