@dou-ui/chart 0.0.0-stage → 0.1.0-alpha.0

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.
Files changed (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/chart.js +6 -0
  4. package/dist/chart.js.map +1 -0
  5. package/dist/chart.vue_vue_type_script_setup_true_lang.js +4245 -0
  6. package/dist/chart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  7. package/dist/components/area.js +6 -0
  8. package/dist/components/area.js.map +1 -0
  9. package/dist/components/area.vue_vue_type_script_setup_true_lang.js +55 -0
  10. package/dist/components/area.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/components/axis.js +6 -0
  12. package/dist/components/axis.js.map +1 -0
  13. package/dist/components/axis.vue_vue_type_script_setup_true_lang.js +46 -0
  14. package/dist/components/axis.vue_vue_type_script_setup_true_lang.js.map +1 -0
  15. package/dist/components/bar.js +6 -0
  16. package/dist/components/bar.js.map +1 -0
  17. package/dist/components/bar.vue_vue_type_script_setup_true_lang.js +46 -0
  18. package/dist/components/bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  19. package/dist/components/boxplot.js +6 -0
  20. package/dist/components/boxplot.js.map +1 -0
  21. package/dist/components/boxplot.vue_vue_type_script_setup_true_lang.js +42 -0
  22. package/dist/components/boxplot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  23. package/dist/components/brush.js +6 -0
  24. package/dist/components/brush.js.map +1 -0
  25. package/dist/components/brush.vue_vue_type_script_setup_true_lang.js +42 -0
  26. package/dist/components/brush.vue_vue_type_script_setup_true_lang.js.map +1 -0
  27. package/dist/components/funnel.js +6 -0
  28. package/dist/components/funnel.js.map +1 -0
  29. package/dist/components/funnel.vue_vue_type_script_setup_true_lang.js +41 -0
  30. package/dist/components/funnel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  31. package/dist/components/gauge.js +6 -0
  32. package/dist/components/gauge.js.map +1 -0
  33. package/dist/components/gauge.vue_vue_type_script_setup_true_lang.js +91 -0
  34. package/dist/components/gauge.vue_vue_type_script_setup_true_lang.js.map +1 -0
  35. package/dist/components/heatmap.js +6 -0
  36. package/dist/components/heatmap.js.map +1 -0
  37. package/dist/components/heatmap.vue_vue_type_script_setup_true_lang.js +45 -0
  38. package/dist/components/heatmap.vue_vue_type_script_setup_true_lang.js.map +1 -0
  39. package/dist/components/histogram.js +6 -0
  40. package/dist/components/histogram.js.map +1 -0
  41. package/dist/components/histogram.vue_vue_type_script_setup_true_lang.js +61 -0
  42. package/dist/components/histogram.vue_vue_type_script_setup_true_lang.js.map +1 -0
  43. package/dist/components/line.js +6 -0
  44. package/dist/components/line.js.map +1 -0
  45. package/dist/components/line.vue_vue_type_script_setup_true_lang.js +52 -0
  46. package/dist/components/line.vue_vue_type_script_setup_true_lang.js.map +1 -0
  47. package/dist/components/marker.js +6 -0
  48. package/dist/components/marker.js.map +1 -0
  49. package/dist/components/marker.vue_vue_type_script_setup_true_lang.js +31 -0
  50. package/dist/components/marker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/components/pie.js +6 -0
  52. package/dist/components/pie.js.map +1 -0
  53. package/dist/components/pie.vue_vue_type_script_setup_true_lang.js +42 -0
  54. package/dist/components/pie.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/radar.js +6 -0
  56. package/dist/components/radar.js.map +1 -0
  57. package/dist/components/radar.vue_vue_type_script_setup_true_lang.js +45 -0
  58. package/dist/components/radar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/components/range.js +6 -0
  60. package/dist/components/range.js.map +1 -0
  61. package/dist/components/range.vue_vue_type_script_setup_true_lang.js +27 -0
  62. package/dist/components/range.vue_vue_type_script_setup_true_lang.js.map +1 -0
  63. package/dist/components/scatter.js +6 -0
  64. package/dist/components/scatter.js.map +1 -0
  65. package/dist/components/scatter.vue_vue_type_script_setup_true_lang.js +45 -0
  66. package/dist/components/scatter.vue_vue_type_script_setup_true_lang.js.map +1 -0
  67. package/dist/components/sunburst.js +6 -0
  68. package/dist/components/sunburst.js.map +1 -0
  69. package/dist/components/sunburst.vue_vue_type_script_setup_true_lang.js +36 -0
  70. package/dist/components/sunburst.vue_vue_type_script_setup_true_lang.js.map +1 -0
  71. package/dist/components/tooltip.js +6 -0
  72. package/dist/components/tooltip.js.map +1 -0
  73. package/dist/components/tooltip.vue_vue_type_script_setup_true_lang.js +31 -0
  74. package/dist/components/tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
  75. package/dist/components/treemap.js +6 -0
  76. package/dist/components/treemap.js.map +1 -0
  77. package/dist/components/treemap.vue_vue_type_script_setup_true_lang.js +33 -0
  78. package/dist/components/treemap.vue_vue_type_script_setup_true_lang.js.map +1 -0
  79. package/dist/components/waterfall.js +6 -0
  80. package/dist/components/waterfall.js.map +1 -0
  81. package/dist/components/waterfall.vue_vue_type_script_setup_true_lang.js +49 -0
  82. package/dist/components/waterfall.vue_vue_type_script_setup_true_lang.js.map +1 -0
  83. package/dist/components/zoom.js +6 -0
  84. package/dist/components/zoom.js.map +1 -0
  85. package/dist/components/zoom.vue_vue_type_script_setup_true_lang.js +37 -0
  86. package/dist/components/zoom.vue_vue_type_script_setup_true_lang.js.map +1 -0
  87. package/dist/context.js +30 -0
  88. package/dist/context.js.map +1 -0
  89. package/dist/core/bar.js +223 -0
  90. package/dist/core/bar.js.map +1 -0
  91. package/dist/core/box.js +150 -0
  92. package/dist/core/box.js.map +1 -0
  93. package/dist/core/colors.js +58 -0
  94. package/dist/core/colors.js.map +1 -0
  95. package/dist/core/data.js +257 -0
  96. package/dist/core/data.js.map +1 -0
  97. package/dist/core/decimate.js +211 -0
  98. package/dist/core/decimate.js.map +1 -0
  99. package/dist/core/format.js +151 -0
  100. package/dist/core/format.js.map +1 -0
  101. package/dist/core/funnel.js +68 -0
  102. package/dist/core/funnel.js.map +1 -0
  103. package/dist/core/grid.js +87 -0
  104. package/dist/core/grid.js.map +1 -0
  105. package/dist/core/heatmap.js +187 -0
  106. package/dist/core/heatmap.js.map +1 -0
  107. package/dist/core/histogram.js +81 -0
  108. package/dist/core/histogram.js.map +1 -0
  109. package/dist/core/hit.js +115 -0
  110. package/dist/core/hit.js.map +1 -0
  111. package/dist/core/labels.js +141 -0
  112. package/dist/core/labels.js.map +1 -0
  113. package/dist/core/layout.js +1002 -0
  114. package/dist/core/layout.js.map +1 -0
  115. package/dist/core/line.js +230 -0
  116. package/dist/core/line.js.map +1 -0
  117. package/dist/core/marker.js +205 -0
  118. package/dist/core/marker.js.map +1 -0
  119. package/dist/core/model.js +391 -0
  120. package/dist/core/model.js.map +1 -0
  121. package/dist/core/painter.js +79 -0
  122. package/dist/core/painter.js.map +1 -0
  123. package/dist/core/pattern.js +102 -0
  124. package/dist/core/pattern.js.map +1 -0
  125. package/dist/core/pie.js +119 -0
  126. package/dist/core/pie.js.map +1 -0
  127. package/dist/core/radar.js +83 -0
  128. package/dist/core/radar.js.map +1 -0
  129. package/dist/core/scale.js +149 -0
  130. package/dist/core/scale.js.map +1 -0
  131. package/dist/core/scatter.js +263 -0
  132. package/dist/core/scatter.js.map +1 -0
  133. package/dist/core/svg.js +209 -0
  134. package/dist/core/svg.js.map +1 -0
  135. package/dist/core/sync.js +21 -0
  136. package/dist/core/sync.js.map +1 -0
  137. package/dist/core/time.js +217 -0
  138. package/dist/core/time.js.map +1 -0
  139. package/dist/core/tree.js +348 -0
  140. package/dist/core/tree.js.map +1 -0
  141. package/dist/core/warn.js +11 -0
  142. package/dist/core/warn.js.map +1 -0
  143. package/dist/core/waterfall.js +134 -0
  144. package/dist/core/waterfall.js.map +1 -0
  145. package/dist/core/window.js +94 -0
  146. package/dist/core/window.js.map +1 -0
  147. package/dist/define.js +62 -0
  148. package/dist/define.js.map +1 -0
  149. package/dist/index.js +49 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/locale.js +170 -0
  152. package/dist/locale.js.map +1 -0
  153. package/dist/overlay.js +6 -0
  154. package/dist/overlay.js.map +1 -0
  155. package/dist/overlay.vue_vue_type_script_setup_true_lang.js +207 -0
  156. package/dist/overlay.vue_vue_type_script_setup_true_lang.js.map +1 -0
  157. package/dist/pointer.js +6 -0
  158. package/dist/pointer.js.map +1 -0
  159. package/dist/pointer.vue_vue_type_script_setup_true_lang.js +136 -0
  160. package/dist/pointer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  161. package/dist/static.js +6 -0
  162. package/dist/static.js.map +1 -0
  163. package/dist/static.vue_vue_type_script_setup_true_lang.js +34 -0
  164. package/dist/static.vue_vue_type_script_setup_true_lang.js.map +1 -0
  165. package/dist/style.css +1 -0
  166. package/dist/style.d.ts +1 -0
  167. package/dist/style.js +3 -0
  168. package/dist/table.js +6 -0
  169. package/dist/table.js.map +1 -0
  170. package/dist/table.vue_vue_type_script_setup_true_lang.js +52 -0
  171. package/dist/table.vue_vue_type_script_setup_true_lang.js.map +1 -0
  172. package/dist/types/chart.vue.d.ts +24 -0
  173. package/dist/types/components/area.vue.d.ts +16 -0
  174. package/dist/types/components/axis.vue.d.ts +8 -0
  175. package/dist/types/components/bar.vue.d.ts +14 -0
  176. package/dist/types/components/boxplot.vue.d.ts +14 -0
  177. package/dist/types/components/brush.vue.d.ts +22 -0
  178. package/dist/types/components/funnel.vue.d.ts +14 -0
  179. package/dist/types/components/gauge.vue.d.ts +17 -0
  180. package/dist/types/components/heatmap.vue.d.ts +14 -0
  181. package/dist/types/components/histogram.vue.d.ts +14 -0
  182. package/dist/types/components/line.vue.d.ts +16 -0
  183. package/dist/types/components/marker.vue.d.ts +6 -0
  184. package/dist/types/components/pie.vue.d.ts +23 -0
  185. package/dist/types/components/radar.vue.d.ts +16 -0
  186. package/dist/types/components/range.vue.d.ts +12 -0
  187. package/dist/types/components/scatter.vue.d.ts +14 -0
  188. package/dist/types/components/sunburst.vue.d.ts +17 -0
  189. package/dist/types/components/tooltip.vue.d.ts +13 -0
  190. package/dist/types/components/treemap.vue.d.ts +8 -0
  191. package/dist/types/components/waterfall.vue.d.ts +16 -0
  192. package/dist/types/components/zoom.vue.d.ts +18 -0
  193. package/dist/types/context.d.ts +87 -0
  194. package/dist/types/core/bar.d.ts +38 -0
  195. package/dist/types/core/box.d.ts +25 -0
  196. package/dist/types/core/colors.d.ts +16 -0
  197. package/dist/types/core/data.d.ts +72 -0
  198. package/dist/types/core/decimate.d.ts +39 -0
  199. package/dist/types/core/format.d.ts +33 -0
  200. package/dist/types/core/funnel.d.ts +15 -0
  201. package/dist/types/core/grid.d.ts +18 -0
  202. package/dist/types/core/heatmap.d.ts +17 -0
  203. package/dist/types/core/histogram.d.ts +23 -0
  204. package/dist/types/core/hit.d.ts +31 -0
  205. package/dist/types/core/labels.d.ts +45 -0
  206. package/dist/types/core/layout.d.ts +259 -0
  207. package/dist/types/core/line.d.ts +36 -0
  208. package/dist/types/core/marker.d.ts +67 -0
  209. package/dist/types/core/model.d.ts +86 -0
  210. package/dist/types/core/painter.d.ts +34 -0
  211. package/dist/types/core/pattern.d.ts +14 -0
  212. package/dist/types/core/pie.d.ts +66 -0
  213. package/dist/types/core/radar.d.ts +12 -0
  214. package/dist/types/core/scale.d.ts +60 -0
  215. package/dist/types/core/scatter.d.ts +16 -0
  216. package/dist/types/core/series.d.ts +228 -0
  217. package/dist/types/core/svg.d.ts +63 -0
  218. package/dist/types/core/sync.d.ts +8 -0
  219. package/dist/types/core/time.d.ts +20 -0
  220. package/dist/types/core/tree.d.ts +84 -0
  221. package/dist/types/core/warn.d.ts +4 -0
  222. package/dist/types/core/waterfall.d.ts +24 -0
  223. package/dist/types/core/window.d.ts +36 -0
  224. package/dist/types/define.d.ts +115 -0
  225. package/dist/types/index.d.ts +363 -0
  226. package/dist/types/locale.d.ts +100 -0
  227. package/dist/types/overlay.vue.d.ts +95 -0
  228. package/dist/types/pointer.vue.d.ts +53 -0
  229. package/dist/types/static.vue.d.ts +24 -0
  230. package/dist/types/table.vue.d.ts +19 -0
  231. package/dist/types/types.d.ts +555 -0
  232. package/dist/types/zoom-layer.vue.d.ts +41 -0
  233. package/dist/zoom-layer.js +6 -0
  234. package/dist/zoom-layer.js.map +1 -0
  235. package/dist/zoom-layer.vue_vue_type_script_setup_true_lang.js +210 -0
  236. package/dist/zoom-layer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  237. package/package.json +53 -4
@@ -0,0 +1,217 @@
1
+ // src/core/time.ts
2
+ var SECOND = 1e3;
3
+ var MINUTE = 60 * SECOND;
4
+ var HOUR = 60 * MINUTE;
5
+ var DAY = 24 * HOUR;
6
+ var INTERVALS = [
7
+ [
8
+ "second",
9
+ 1,
10
+ SECOND
11
+ ],
12
+ [
13
+ "second",
14
+ 5,
15
+ 5 * SECOND
16
+ ],
17
+ [
18
+ "second",
19
+ 15,
20
+ 15 * SECOND
21
+ ],
22
+ [
23
+ "second",
24
+ 30,
25
+ 30 * SECOND
26
+ ],
27
+ [
28
+ "minute",
29
+ 1,
30
+ MINUTE
31
+ ],
32
+ [
33
+ "minute",
34
+ 2,
35
+ 2 * MINUTE
36
+ ],
37
+ [
38
+ "minute",
39
+ 5,
40
+ 5 * MINUTE
41
+ ],
42
+ [
43
+ "minute",
44
+ 10,
45
+ 10 * MINUTE
46
+ ],
47
+ [
48
+ "minute",
49
+ 15,
50
+ 15 * MINUTE
51
+ ],
52
+ [
53
+ "minute",
54
+ 30,
55
+ 30 * MINUTE
56
+ ],
57
+ [
58
+ "hour",
59
+ 1,
60
+ HOUR
61
+ ],
62
+ [
63
+ "hour",
64
+ 2,
65
+ 2 * HOUR
66
+ ],
67
+ [
68
+ "hour",
69
+ 3,
70
+ 3 * HOUR
71
+ ],
72
+ [
73
+ "hour",
74
+ 6,
75
+ 6 * HOUR
76
+ ],
77
+ [
78
+ "hour",
79
+ 12,
80
+ 12 * HOUR
81
+ ],
82
+ [
83
+ "day",
84
+ 1,
85
+ DAY
86
+ ],
87
+ [
88
+ "day",
89
+ 2,
90
+ 2 * DAY
91
+ ],
92
+ [
93
+ "week",
94
+ 1,
95
+ 7 * DAY
96
+ ],
97
+ [
98
+ "week",
99
+ 2,
100
+ 14 * DAY
101
+ ],
102
+ [
103
+ "month",
104
+ 1,
105
+ 30 * DAY
106
+ ],
107
+ [
108
+ "month",
109
+ 3,
110
+ 91 * DAY
111
+ ],
112
+ [
113
+ "month",
114
+ 6,
115
+ 182 * DAY
116
+ ],
117
+ [
118
+ "year",
119
+ 1,
120
+ 365 * DAY
121
+ ]
122
+ ];
123
+ /** The smallest interval that gives at most `count` ticks across `span` ms. */
124
+ function timeInterval(span, count) {
125
+ for (const [unit, every, length] of INTERVALS) if (span / length <= Math.max(1, count)) return {
126
+ unit,
127
+ every
128
+ };
129
+ const years = span / (365 * DAY) / Math.max(1, count);
130
+ const power = 10 ** Math.floor(Math.log10(years));
131
+ const fraction = years / power;
132
+ return {
133
+ unit: "year",
134
+ every: (fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10) * power
135
+ };
136
+ }
137
+ /** The start of the `unit` that `time` falls in (weeks start on Monday). */
138
+ function floorTime(time, unit) {
139
+ const d = new Date(time);
140
+ switch (unit) {
141
+ case "year": return new Date(d.getFullYear(), 0, 1);
142
+ case "month": return new Date(d.getFullYear(), d.getMonth(), 1);
143
+ case "week": {
144
+ const back = (d.getDay() + 6) % 7;
145
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate() - back);
146
+ }
147
+ case "day": return new Date(d.getFullYear(), d.getMonth(), d.getDate());
148
+ case "hour": return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours());
149
+ case "minute": return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());
150
+ default: return /* @__PURE__ */ new Date(Math.floor(time / SECOND) * SECOND);
151
+ }
152
+ }
153
+ /** Whether `date` is on a multiple of `every` within the next unit up, so steps line up. */
154
+ function aligned(date, { unit, every }) {
155
+ if (every === 1) return true;
156
+ switch (unit) {
157
+ case "year": return date.getFullYear() % every === 0;
158
+ case "month": return date.getMonth() % every === 0;
159
+ case "day": return (date.getDate() - 1) % every === 0 && date.getDate() + every - 1 <= 31;
160
+ case "hour": return date.getHours() % every === 0;
161
+ case "minute": return date.getMinutes() % every === 0;
162
+ case "second": return date.getSeconds() % every === 0;
163
+ case "week": return Math.round((date.getTime() - new Date(1970, 0, 5).getTime()) / (7 * DAY)) % every === 0;
164
+ default: return true;
165
+ }
166
+ }
167
+ function next(date, unit) {
168
+ const d = new Date(date);
169
+ switch (unit) {
170
+ case "year":
171
+ d.setFullYear(d.getFullYear() + 1);
172
+ break;
173
+ case "month":
174
+ d.setMonth(d.getMonth() + 1);
175
+ break;
176
+ case "week":
177
+ d.setDate(d.getDate() + 7);
178
+ break;
179
+ case "day":
180
+ d.setDate(d.getDate() + 1);
181
+ break;
182
+ case "hour": return new Date(d.getTime() + HOUR);
183
+ case "minute": return new Date(d.getTime() + MINUTE);
184
+ default: return new Date(d.getTime() + SECOND);
185
+ }
186
+ return d;
187
+ }
188
+ /** The ticks of `interval` from `lo` to `hi` (ms), both ends included when they fall on one. */
189
+ function timeTicks(lo, hi, interval) {
190
+ const ticks = [];
191
+ if (!(hi >= lo)) return ticks;
192
+ let date = floorTime(lo, interval.unit);
193
+ for (let guard = 0; guard < 1e4 && date.getTime() <= hi; guard++) {
194
+ if (date.getTime() >= lo && aligned(date, interval)) ticks.push(date.getTime());
195
+ date = next(date, interval.unit);
196
+ }
197
+ return ticks;
198
+ }
199
+ /** The next unit up, whose boundaries a tick label marks with more context. */
200
+ function parentUnit(unit) {
201
+ switch (unit) {
202
+ case "second": return "minute";
203
+ case "minute":
204
+ case "hour": return "day";
205
+ case "day":
206
+ case "week": return "month";
207
+ case "month": return "year";
208
+ default: return null;
209
+ }
210
+ }
211
+ /** Whether `time` is the very start of a `unit`. */
212
+ function startsUnit(time, unit) {
213
+ return floorTime(time, unit).getTime() === time;
214
+ }
215
+ export { floorTime, parentUnit, startsUnit, timeInterval, timeTicks };
216
+
217
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","names":[],"sources":["../../src/core/time.ts"],"sourcesContent":["/**\n * Ticks on a time axis, at round points of local time: whole minutes,\n * midnights, the first of a month. The step is the smallest one that\n * gives no more than the wanted number of ticks.\n */\n\nexport type TimeUnit = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'\n\nexport interface TimeInterval {\n unit: TimeUnit\n every: number\n}\n\nconst SECOND = 1000\nconst MINUTE = 60 * SECOND\nconst HOUR = 60 * MINUTE\nconst DAY = 24 * HOUR\n\nconst INTERVALS: Array<[TimeUnit, number, number]> = [\n ['second', 1, SECOND],\n ['second', 5, 5 * SECOND],\n ['second', 15, 15 * SECOND],\n ['second', 30, 30 * SECOND],\n ['minute', 1, MINUTE],\n ['minute', 2, 2 * MINUTE],\n ['minute', 5, 5 * MINUTE],\n ['minute', 10, 10 * MINUTE],\n ['minute', 15, 15 * MINUTE],\n ['minute', 30, 30 * MINUTE],\n ['hour', 1, HOUR],\n ['hour', 2, 2 * HOUR],\n ['hour', 3, 3 * HOUR],\n ['hour', 6, 6 * HOUR],\n ['hour', 12, 12 * HOUR],\n ['day', 1, DAY],\n ['day', 2, 2 * DAY],\n ['week', 1, 7 * DAY],\n ['week', 2, 14 * DAY],\n ['month', 1, 30 * DAY],\n ['month', 3, 91 * DAY],\n ['month', 6, 182 * DAY],\n ['year', 1, 365 * DAY],\n]\n\n/** The smallest interval that gives at most `count` ticks across `span` ms. */\nexport function timeInterval(span: number, count: number): TimeInterval {\n for (const [unit, every, length] of INTERVALS) {\n if (span / length <= Math.max(1, count)) return { unit, every }\n }\n // whole years, a nice number of them\n const years = span / (365 * DAY) / Math.max(1, count)\n const power = 10 ** Math.floor(Math.log10(years))\n const fraction = years / power\n return {\n unit: 'year',\n every: (fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10) * power,\n }\n}\n\n/** The start of the `unit` that `time` falls in (weeks start on Monday). */\nexport function floorTime(time: number, unit: TimeUnit): Date {\n const d = new Date(time)\n switch (unit) {\n case 'year':\n return new Date(d.getFullYear(), 0, 1)\n case 'month':\n return new Date(d.getFullYear(), d.getMonth(), 1)\n case 'week': {\n const back = (d.getDay() + 6) % 7\n return new Date(d.getFullYear(), d.getMonth(), d.getDate() - back)\n }\n case 'day':\n return new Date(d.getFullYear(), d.getMonth(), d.getDate())\n case 'hour':\n return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours())\n case 'minute':\n return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes())\n default:\n return new Date(Math.floor(time / SECOND) * SECOND)\n }\n}\n\n/** Whether `date` is on a multiple of `every` within the next unit up, so steps line up. */\nfunction aligned(date: Date, { unit, every }: TimeInterval): boolean {\n if (every === 1) return true\n switch (unit) {\n case 'year':\n return date.getFullYear() % every === 0\n case 'month':\n return date.getMonth() % every === 0\n case 'day':\n return (date.getDate() - 1) % every === 0 && date.getDate() + every - 1 <= 31\n case 'hour':\n return date.getHours() % every === 0\n case 'minute':\n return date.getMinutes() % every === 0\n case 'second':\n return date.getSeconds() % every === 0\n case 'week':\n // counted from a Monday long ago, so the same weeks are picked whatever is shown\n return Math.round((date.getTime() - new Date(1970, 0, 5).getTime()) / (7 * DAY)) % every === 0\n default:\n return true\n }\n}\n\nfunction next(date: Date, unit: TimeUnit): Date {\n const d = new Date(date)\n switch (unit) {\n case 'year':\n d.setFullYear(d.getFullYear() + 1)\n break\n case 'month':\n d.setMonth(d.getMonth() + 1)\n break\n case 'week':\n d.setDate(d.getDate() + 7)\n break\n case 'day':\n d.setDate(d.getDate() + 1)\n break\n case 'hour':\n // by the clock, so a daylight saving change doesn't shift every tick after it\n return new Date(d.getTime() + HOUR)\n case 'minute':\n return new Date(d.getTime() + MINUTE)\n default:\n return new Date(d.getTime() + SECOND)\n }\n return d\n}\n\n/** The ticks of `interval` from `lo` to `hi` (ms), both ends included when they fall on one. */\nexport function timeTicks(lo: number, hi: number, interval: TimeInterval): number[] {\n const ticks: number[] = []\n if (!(hi >= lo)) return ticks\n let date = floorTime(lo, interval.unit)\n // a guard against runaway loops on absurd spans\n for (let guard = 0; guard < 10000 && date.getTime() <= hi; guard++) {\n if (date.getTime() >= lo && aligned(date, interval)) ticks.push(date.getTime())\n date = next(date, interval.unit)\n }\n return ticks\n}\n\n/** The next unit up, whose boundaries a tick label marks with more context. */\nexport function parentUnit(unit: TimeUnit): TimeUnit | null {\n switch (unit) {\n case 'second':\n return 'minute'\n case 'minute':\n case 'hour':\n return 'day'\n case 'day':\n case 'week':\n return 'month'\n case 'month':\n return 'year'\n default:\n return null\n }\n}\n\n/** Whether `time` is the very start of a `unit`. */\nexport function startsUnit(time: number, unit: TimeUnit): boolean {\n return floorTime(time, unit).getTime() === time\n}\n"],"mappings":"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"}
@@ -0,0 +1,348 @@
1
+ import { read } from "./data.js";
2
+ // src/core/tree.ts
3
+ /** The tree read from nested rows, and its nodes walked parents first; nodes without value are left out. */
4
+ function buildTree(data, { label, value, children }) {
5
+ const make = (row, place, depth, parent) => ({
6
+ index: -1,
7
+ name: row ? String(read(row, label, place) ?? "") : "",
8
+ value: 0,
9
+ depth,
10
+ parent,
11
+ children: [],
12
+ row,
13
+ place,
14
+ group: -1,
15
+ x0: 0,
16
+ y0: 0,
17
+ x1: 0,
18
+ y1: 0
19
+ });
20
+ const root = make(null, -1, 0, null);
21
+ const grow = (node, rows) => {
22
+ if (!Array.isArray(rows)) return;
23
+ rows.forEach((row, i) => {
24
+ const child = make(row, i, node.depth + 1, node);
25
+ const kids = read(row, children, i);
26
+ if (Array.isArray(kids) && kids.length) grow(child, kids);
27
+ if (child.children.length) child.value = child.children.reduce((sum, c) => sum + c.value, 0);
28
+ else {
29
+ const own = Number(read(row, value, i));
30
+ child.value = Number.isFinite(own) && own > 0 ? own : 0;
31
+ }
32
+ if (child.value > 0) node.children.push(child);
33
+ });
34
+ };
35
+ grow(root, data);
36
+ root.value = root.children.reduce((sum, c) => sum + c.value, 0);
37
+ const nodes = [];
38
+ const walk = (node) => {
39
+ node.index = nodes.length;
40
+ nodes.push(node);
41
+ for (const child of node.children) walk(child);
42
+ };
43
+ root.children.forEach((top, k) => {
44
+ const mark = (node) => {
45
+ node.group = k;
46
+ node.children.forEach(mark);
47
+ };
48
+ mark(top);
49
+ });
50
+ walk(root);
51
+ return {
52
+ root,
53
+ nodes
54
+ };
55
+ }
56
+ /** The names from the top level down to `node`. */
57
+ function treePath(node) {
58
+ const out = [];
59
+ for (let at = node; at && at.depth > 0; at = at.parent) out.unshift(at.name);
60
+ return out;
61
+ }
62
+ /** Room around a group's children, in px. */
63
+ var TREE_PAD = 2;
64
+ /** The smallest group that gets a header of its own, in px. */
65
+ var HEADED = {
66
+ width: 56,
67
+ height: 52
68
+ };
69
+ /**
70
+ * Lays the treemap out in `rect`: each node's rectangle as near a square
71
+ * as can be (the squarified layout), largest first, children inside their
72
+ * group below its header.
73
+ */
74
+ function layoutTreemap(root, rect) {
75
+ root.x0 = rect.x;
76
+ root.y0 = rect.y;
77
+ root.x1 = rect.x + rect.width;
78
+ root.y1 = rect.y + rect.height;
79
+ const place = (node) => {
80
+ if (!node.children.length) return;
81
+ let { x0, y0, x1, y1 } = node;
82
+ if (node.depth > 0) {
83
+ const headed = x1 - x0 >= HEADED.width && y1 - y0 >= HEADED.height;
84
+ x0 += TREE_PAD;
85
+ x1 -= TREE_PAD;
86
+ y0 += headed ? 20 : TREE_PAD;
87
+ y1 -= TREE_PAD;
88
+ }
89
+ squarify(node.children, x0, y0, Math.max(0, x1 - x0), Math.max(0, y1 - y0));
90
+ node.children.forEach(place);
91
+ };
92
+ place(root);
93
+ }
94
+ /** Whether a treemap group has room for its header (see `layoutTreemap`). */
95
+ function hasHeader(node) {
96
+ return node.depth > 0 && node.children.length > 0 && node.x1 - node.x0 >= HEADED.width && node.y1 - node.y0 >= HEADED.height;
97
+ }
98
+ function squarify(nodes, x, y, width, height) {
99
+ const list = [...nodes];
100
+ list.sort((a, b) => b.value - a.value);
101
+ const total = list.reduce((sum, n) => sum + n.value, 0);
102
+ if (!(total > 0) || !(width > 0) || !(height > 0)) {
103
+ for (const n of list) [n.x0, n.y0, n.x1, n.y1] = [
104
+ x,
105
+ y,
106
+ x,
107
+ y
108
+ ];
109
+ return;
110
+ }
111
+ const scale = width * height / total;
112
+ let i = 0;
113
+ while (i < list.length) {
114
+ const short = Math.min(width, height);
115
+ let row = [list[i]];
116
+ let sum = list[i].value * scale;
117
+ let worst = ratio(row, sum, short, scale);
118
+ let j = i + 1;
119
+ while (j < list.length) {
120
+ const next = [...row, list[j]];
121
+ const nextSum = sum + list[j].value * scale;
122
+ const w = ratio(next, nextSum, short, scale);
123
+ if (w > worst) break;
124
+ row = next;
125
+ sum = nextSum;
126
+ worst = w;
127
+ j++;
128
+ }
129
+ const thick = sum / short;
130
+ let at = 0;
131
+ for (const n of row) {
132
+ const length = n.value * scale / thick;
133
+ if (width >= height) [n.x0, n.y0, n.x1, n.y1] = [
134
+ x,
135
+ y + at,
136
+ x + thick,
137
+ y + at + length
138
+ ];
139
+ else [n.x0, n.y0, n.x1, n.y1] = [
140
+ x + at,
141
+ y,
142
+ x + at + length,
143
+ y + thick
144
+ ];
145
+ at += length;
146
+ }
147
+ if (width >= height) {
148
+ x += thick;
149
+ width -= thick;
150
+ } else {
151
+ y += thick;
152
+ height -= thick;
153
+ }
154
+ i = j;
155
+ }
156
+ }
157
+ /** The worst (largest) side ratio of the rectangles of a row laid along a side `short` long. */
158
+ function ratio(row, sum, short, scale) {
159
+ let lo = Infinity;
160
+ let hi = 0;
161
+ for (const n of row) {
162
+ const area = n.value * scale;
163
+ if (area < lo) lo = area;
164
+ if (area > hi) hi = area;
165
+ }
166
+ const s2 = sum * sum;
167
+ const w2 = short * short;
168
+ return Math.max(w2 * hi / s2, s2 / (w2 * lo));
169
+ }
170
+ /** The deepest node of a treemap under `(px, py)`. */
171
+ function treemapAt(root, px, py) {
172
+ let found = null;
173
+ let at = root;
174
+ while (at) {
175
+ const inside = at.children.find((c) => px >= c.x0 && px < c.x1 && py >= c.y0 && py < c.y1);
176
+ if (!inside) break;
177
+ found = inside;
178
+ at = inside;
179
+ }
180
+ return found;
181
+ }
182
+ /**
183
+ * Draws a treemap: a leaf filled with its color, a group a light wash of
184
+ * it under its children. `focus` (a node's index) is ringed.
185
+ */
186
+ function drawTreemap(painter, nodes, colors, { surface, ring, focus = -1, t = 1 }) {
187
+ painter.save();
188
+ painter.globalAlpha *= t;
189
+ for (const node of nodes) {
190
+ if (node.depth === 0) continue;
191
+ const w = node.x1 - node.x0;
192
+ const h = node.y1 - node.y0;
193
+ if (w < 1 || h < 1) continue;
194
+ painter.beginPath();
195
+ roundRect(painter, node.x0, node.y0, w, h, w > 8 && h > 8 ? 4 : 0);
196
+ if (node.children.length) {
197
+ painter.save();
198
+ painter.fillStyle = colors[node.index];
199
+ painter.globalAlpha *= .14;
200
+ painter.fill();
201
+ painter.restore();
202
+ } else {
203
+ painter.fillStyle = colors[node.index];
204
+ painter.fill();
205
+ }
206
+ }
207
+ painter.strokeStyle = surface;
208
+ painter.lineWidth = 1;
209
+ painter.beginPath();
210
+ for (const node of nodes) {
211
+ if (node.depth === 0) continue;
212
+ const w = node.x1 - node.x0;
213
+ const h = node.y1 - node.y0;
214
+ if (w > 2 && h > 2) roundRect(painter, node.x0 + .5, node.y0 + .5, w - 1, h - 1, w > 8 && h > 8 ? 3.5 : 0);
215
+ }
216
+ painter.stroke();
217
+ painter.restore();
218
+ if (focus >= 0) ringTreemap(painter, nodes[focus], ring);
219
+ }
220
+ /** Rings a treemap's node: the one under the pointer or picked with the keys. */
221
+ function ringTreemap(painter, node, ring) {
222
+ if (!node || node.depth === 0) return;
223
+ painter.save();
224
+ painter.strokeStyle = ring;
225
+ painter.lineWidth = 2;
226
+ painter.beginPath();
227
+ roundRect(painter, node.x0 + 1, node.y0 + 1, node.x1 - node.x0 - 2, node.y1 - node.y0 - 2, 3);
228
+ painter.stroke();
229
+ painter.restore();
230
+ }
231
+ function roundRect(painter, x, y, w, h, r) {
232
+ if (w <= 0 || h <= 0) return;
233
+ r = Math.max(0, Math.min(r, w / 2, h / 2));
234
+ if (r < .5) {
235
+ painter.rect(x, y, w, h);
236
+ return;
237
+ }
238
+ painter.moveTo(x + r, y);
239
+ painter.arcTo(x + w, y, x + w, y + h, r);
240
+ painter.arcTo(x + w, y + h, x, y + h, r);
241
+ painter.arcTo(x, y + h, x, y, r);
242
+ painter.arcTo(x, y, x + w, y, r);
243
+ painter.closePath();
244
+ }
245
+ /**
246
+ * Lays a sunburst out round `(cx, cy)`: the top level in the ring just out
247
+ * of the hole (`inner`), each level a ring further out to `radius`; each
248
+ * node's arc a share of its parent's as its value is of the parent's.
249
+ * Angles run clockwise from 12 o'clock.
250
+ */
251
+ function layoutSunburst(root, inner, radius) {
252
+ let depth = 0;
253
+ const deepest = (node) => {
254
+ if (node.depth > depth) depth = node.depth;
255
+ node.children.forEach(deepest);
256
+ };
257
+ deepest(root);
258
+ const ring = depth ? (radius - inner) / depth : 0;
259
+ root.x0 = 0;
260
+ root.x1 = Math.PI * 2;
261
+ root.y0 = 0;
262
+ root.y1 = inner;
263
+ const place = (node) => {
264
+ let angle = node.x0;
265
+ const span = node.x1 - node.x0;
266
+ for (const child of node.children) {
267
+ child.x0 = angle;
268
+ angle += node.value > 0 ? child.value / node.value * span : 0;
269
+ child.x1 = angle;
270
+ child.y0 = inner + (child.depth - 1) * ring;
271
+ child.y1 = child.y0 + ring;
272
+ place(child);
273
+ }
274
+ };
275
+ place(root);
276
+ }
277
+ /** The node of a sunburst under the angle `angle` (clockwise from 12 o'clock) and radius `r`. */
278
+ function sunburstAt(root, angle, r) {
279
+ let at = root;
280
+ while (at) {
281
+ const inside = at.children.find((c) => angle >= c.x0 && angle < c.x1);
282
+ if (!inside) return null;
283
+ if (r >= inside.y0 && r < inside.y1) return inside;
284
+ at = inside;
285
+ }
286
+ return null;
287
+ }
288
+ /** The gap between a sunburst's arcs, in px. */
289
+ var ARC_GAP = 1.5;
290
+ /**
291
+ * Draws a sunburst round `(cx, cy)`, sweeping in with `sweep` (0 to 1).
292
+ * Nodes other than `focus`, its ancestors and its descendants are faded.
293
+ */
294
+ /** How much of a sunburst shows off the branch pointed at. */
295
+ var SUNBURST_FADE = .4;
296
+ /** A node with its ancestors and all its descendants: what stays lit when it is pointed at. */
297
+ function sunburstBranch(node) {
298
+ const out = [];
299
+ for (let a = node.parent; a; a = a.parent) out.push(a);
300
+ const stack = [node];
301
+ while (stack.length) {
302
+ const n = stack.pop();
303
+ out.push(n);
304
+ for (const c of n.children) stack.push(c);
305
+ }
306
+ return out;
307
+ }
308
+ function drawSunburst(painter, nodes, colors, { cx, cy, surface, focus = -1, sweep = 1 }) {
309
+ const at = (angle) => angle * sweep - Math.PI / 2;
310
+ const focused = nodes[focus];
311
+ const lit = (node) => {
312
+ if (!focused) return true;
313
+ for (let a = node; a; a = a.parent) if (a === focused) return true;
314
+ for (let a = focused; a; a = a.parent) if (a === node) return true;
315
+ return false;
316
+ };
317
+ painter.save();
318
+ for (const node of nodes) {
319
+ if (node.depth === 0 || !(node.x1 > node.x0)) continue;
320
+ painter.save();
321
+ if (!lit(node)) painter.globalAlpha *= SUNBURST_FADE;
322
+ painter.fillStyle = colors[node.index];
323
+ painter.beginPath();
324
+ painter.arc(cx, cy, node.y1, at(node.x0), at(node.x1));
325
+ painter.arc(cx, cy, node.y0, at(node.x1), at(node.x0), true);
326
+ painter.closePath();
327
+ painter.fill();
328
+ painter.restore();
329
+ }
330
+ painter.strokeStyle = surface;
331
+ painter.lineWidth = ARC_GAP;
332
+ painter.beginPath();
333
+ for (const node of nodes) {
334
+ if (node.depth === 0 || !(node.x1 > node.x0)) continue;
335
+ const a = at(node.x0);
336
+ if ((node.x1 - node.x0) * sweep * node.y1 >= ARC_GAP * 3 || !node.parent || node.parent.depth === 0 || node.x0 === node.parent.x0) {
337
+ painter.moveTo(cx + Math.cos(a) * node.y0, cy + Math.sin(a) * node.y0);
338
+ painter.lineTo(cx + Math.cos(a) * node.y1, cy + Math.sin(a) * node.y1);
339
+ }
340
+ painter.moveTo(cx + Math.cos(at(node.x0)) * node.y0, cy + Math.sin(at(node.x0)) * node.y0);
341
+ painter.arc(cx, cy, node.y0, at(node.x0), at(node.x1));
342
+ }
343
+ painter.stroke();
344
+ painter.restore();
345
+ }
346
+ export { SUNBURST_FADE, buildTree, drawSunburst, drawTreemap, hasHeader, layoutSunburst, layoutTreemap, ringTreemap, sunburstAt, sunburstBranch, treePath, treemapAt };
347
+
348
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","names":[],"sources":["../../src/core/tree.ts"],"sourcesContent":["import { read, type ChartAccessor, type ChartRow } from './data'\nimport type { Painter, Rect } from './painter'\n\n/*\n * Charts of a tree: what a whole is made of, level by level. A treemap\n * fills a rectangle, each node a rectangle as large as its value, its\n * children inside it; a sunburst draws rings out from a center, each node\n * an arc of its parent's, one ring per level.\n */\n\nexport interface TreeNode {\n /** Its place in `nodes`, in the order the tree is walked (parents first). */\n index: number\n name: string\n /** Its own value (a leaf's), or the sum of its children's. */\n value: number\n /** 1 for the top level: the root, which holds the whole, is 0. */\n depth: number\n parent: TreeNode | null\n children: TreeNode[]\n /** The row it was read from; the root has none. */\n row: ChartRow | null\n /** Its row's place among its siblings' rows, as accessors are given it. */\n place: number\n /** The place of its top-level node among the top level, which picks its color. */\n group: number\n /** A treemap's rectangle, or a sunburst's arc (angles and radii). */\n x0: number\n y0: number\n x1: number\n y1: number\n}\n\nexport interface TreeAccessors {\n label: ChartAccessor\n value: ChartAccessor\n children: ChartAccessor\n}\n\n/** The tree read from nested rows, and its nodes walked parents first; nodes without value are left out. */\nexport function buildTree(\n data: readonly ChartRow[] | undefined,\n { label, value, children }: TreeAccessors,\n): { root: TreeNode; nodes: TreeNode[] } {\n const make = (\n row: ChartRow | null,\n place: number,\n depth: number,\n parent: TreeNode | null,\n ): TreeNode => ({\n index: -1,\n name: row ? String(read(row, label, place) ?? '') : '',\n value: 0,\n depth,\n parent,\n children: [],\n row,\n place,\n group: -1,\n x0: 0,\n y0: 0,\n x1: 0,\n y1: 0,\n })\n const root = make(null, -1, 0, null)\n const grow = (node: TreeNode, rows: unknown) => {\n if (!Array.isArray(rows)) return\n rows.forEach((row: ChartRow, i) => {\n const child = make(row, i, node.depth + 1, node)\n const kids = read(row, children, i)\n if (Array.isArray(kids) && kids.length) grow(child, kids)\n if (child.children.length) child.value = child.children.reduce((sum, c) => sum + c.value, 0)\n else {\n const own = Number(read(row, value, i))\n child.value = Number.isFinite(own) && own > 0 ? own : 0\n }\n if (child.value > 0) node.children.push(child)\n })\n }\n grow(root, data)\n root.value = root.children.reduce((sum, c) => sum + c.value, 0)\n const nodes: TreeNode[] = []\n const walk = (node: TreeNode) => {\n node.index = nodes.length\n nodes.push(node)\n for (const child of node.children) walk(child)\n }\n root.children.forEach((top, k) => {\n const mark = (node: TreeNode) => {\n node.group = k\n node.children.forEach(mark)\n }\n mark(top)\n })\n walk(root)\n return { root, nodes }\n}\n\n/** The names from the top level down to `node`. */\nexport function treePath(node: TreeNode): string[] {\n const out: string[] = []\n for (let at: TreeNode | null = node; at && at.depth > 0; at = at.parent) out.unshift(at.name)\n return out\n}\n\n/* the treemap */\n\n/** Room above a group's children for its name, in px. */\nexport const TREE_HEADER = 20\n/** Room around a group's children, in px. */\nconst TREE_PAD = 2\n/** The smallest group that gets a header of its own, in px. */\nconst HEADED = { width: 56, height: 52 }\n\n/**\n * Lays the treemap out in `rect`: each node's rectangle as near a square\n * as can be (the squarified layout), largest first, children inside their\n * group below its header.\n */\nexport function layoutTreemap(root: TreeNode, rect: Rect) {\n root.x0 = rect.x\n root.y0 = rect.y\n root.x1 = rect.x + rect.width\n root.y1 = rect.y + rect.height\n const place = (node: TreeNode) => {\n if (!node.children.length) return\n let { x0, y0, x1, y1 } = node\n if (node.depth > 0) {\n const headed = x1 - x0 >= HEADED.width && y1 - y0 >= HEADED.height\n x0 += TREE_PAD\n x1 -= TREE_PAD\n y0 += headed ? TREE_HEADER : TREE_PAD\n y1 -= TREE_PAD\n }\n squarify(node.children, x0, y0, Math.max(0, x1 - x0), Math.max(0, y1 - y0))\n node.children.forEach(place)\n }\n place(root)\n}\n\n/** Whether a treemap group has room for its header (see `layoutTreemap`). */\nexport function hasHeader(node: TreeNode) {\n return (\n node.depth > 0 &&\n node.children.length > 0 &&\n node.x1 - node.x0 >= HEADED.width &&\n node.y1 - node.y0 >= HEADED.height\n )\n}\n\nfunction squarify(nodes: TreeNode[], x: number, y: number, width: number, height: number) {\n const list = [...nodes]\n list.sort((a, b) => b.value - a.value)\n const total = list.reduce((sum, n) => sum + n.value, 0)\n if (!(total > 0) || !(width > 0) || !(height > 0)) {\n for (const n of list) [n.x0, n.y0, n.x1, n.y1] = [x, y, x, y]\n return\n }\n // area per unit of value\n const scale = (width * height) / total\n let i = 0\n while (i < list.length) {\n const short = Math.min(width, height)\n // add to the row while it makes its worst rectangle squarer\n let row = [list[i]!]\n let sum = list[i]!.value * scale\n let worst = ratio(row, sum, short, scale)\n let j = i + 1\n while (j < list.length) {\n const next = [...row, list[j]!]\n const nextSum = sum + list[j]!.value * scale\n const w = ratio(next, nextSum, short, scale)\n if (w > worst) break\n row = next\n sum = nextSum\n worst = w\n j++\n }\n // the row along the short side, as thick as it needs\n const thick = sum / short\n let at = 0\n for (const n of row) {\n const length = (n.value * scale) / thick\n if (width >= height) [n.x0, n.y0, n.x1, n.y1] = [x, y + at, x + thick, y + at + length]\n else [n.x0, n.y0, n.x1, n.y1] = [x + at, y, x + at + length, y + thick]\n at += length\n }\n if (width >= height) {\n x += thick\n width -= thick\n } else {\n y += thick\n height -= thick\n }\n i = j\n }\n}\n\n/** The worst (largest) side ratio of the rectangles of a row laid along a side `short` long. */\nfunction ratio(row: TreeNode[], sum: number, short: number, scale: number) {\n let lo = Infinity\n let hi = 0\n for (const n of row) {\n const area = n.value * scale\n if (area < lo) lo = area\n if (area > hi) hi = area\n }\n const s2 = sum * sum\n const w2 = short * short\n return Math.max((w2 * hi) / s2, s2 / (w2 * lo))\n}\n\n/** The deepest node of a treemap under `(px, py)`. */\nexport function treemapAt(root: TreeNode, px: number, py: number): TreeNode | null {\n let found: TreeNode | null = null\n let at: TreeNode | undefined = root\n while (at) {\n const inside: TreeNode | undefined = at.children.find(\n (c) => px >= c.x0 && px < c.x1 && py >= c.y0 && py < c.y1,\n )\n if (!inside) break\n found = inside\n at = inside\n }\n return found\n}\n\n/**\n * Draws a treemap: a leaf filled with its color, a group a light wash of\n * it under its children. `focus` (a node's index) is ringed.\n */\nexport function drawTreemap(\n painter: Painter,\n nodes: TreeNode[],\n colors: string[],\n {\n surface,\n ring,\n focus = -1,\n t = 1,\n }: { surface: string; ring: string; focus?: number; t?: number },\n) {\n painter.save()\n painter.globalAlpha *= t\n for (const node of nodes) {\n if (node.depth === 0) continue\n const w = node.x1 - node.x0\n const h = node.y1 - node.y0\n // under a pixel: nothing to see, and very many of them are slow to draw\n if (w < 1 || h < 1) continue\n painter.beginPath()\n roundRect(painter, node.x0, node.y0, w, h, w > 8 && h > 8 ? 4 : 0)\n if (node.children.length) {\n painter.save()\n painter.fillStyle = colors[node.index]!\n painter.globalAlpha *= 0.14\n painter.fill()\n painter.restore()\n } else {\n painter.fillStyle = colors[node.index]!\n painter.fill()\n }\n }\n // a hairline of the surface between neighbors, groups and leaves alike\n painter.strokeStyle = surface\n painter.lineWidth = 1\n painter.beginPath()\n for (const node of nodes) {\n if (node.depth === 0) continue\n const w = node.x1 - node.x0\n const h = node.y1 - node.y0\n // square corners on small ones: rounding thousands of them is slow, and unseen\n if (w > 2 && h > 2)\n roundRect(painter, node.x0 + 0.5, node.y0 + 0.5, w - 1, h - 1, w > 8 && h > 8 ? 3.5 : 0)\n }\n painter.stroke()\n painter.restore()\n if (focus >= 0) ringTreemap(painter, nodes[focus], ring)\n}\n\n/** Rings a treemap's node: the one under the pointer or picked with the keys. */\nexport function ringTreemap(painter: Painter, node: TreeNode | undefined, ring: string) {\n if (!node || node.depth === 0) return\n painter.save()\n painter.strokeStyle = ring\n painter.lineWidth = 2\n painter.beginPath()\n roundRect(painter, node.x0 + 1, node.y0 + 1, node.x1 - node.x0 - 2, node.y1 - node.y0 - 2, 3)\n painter.stroke()\n painter.restore()\n}\n\nfunction roundRect(painter: Painter, x: number, y: number, w: number, h: number, r: number) {\n if (w <= 0 || h <= 0) return\n r = Math.max(0, Math.min(r, w / 2, h / 2))\n if (r < 0.5) {\n painter.rect(x, y, w, h)\n return\n }\n painter.moveTo(x + r, y)\n painter.arcTo(x + w, y, x + w, y + h, r)\n painter.arcTo(x + w, y + h, x, y + h, r)\n painter.arcTo(x, y + h, x, y, r)\n painter.arcTo(x, y, x + w, y, r)\n painter.closePath()\n}\n\n/* the sunburst */\n\n/**\n * Lays a sunburst out round `(cx, cy)`: the top level in the ring just out\n * of the hole (`inner`), each level a ring further out to `radius`; each\n * node's arc a share of its parent's as its value is of the parent's.\n * Angles run clockwise from 12 o'clock.\n */\nexport function layoutSunburst(root: TreeNode, inner: number, radius: number) {\n let depth = 0\n const deepest = (node: TreeNode) => {\n if (node.depth > depth) depth = node.depth\n node.children.forEach(deepest)\n }\n deepest(root)\n const ring = depth ? (radius - inner) / depth : 0\n root.x0 = 0\n root.x1 = Math.PI * 2\n root.y0 = 0\n root.y1 = inner\n const place = (node: TreeNode) => {\n let angle = node.x0\n const span = node.x1 - node.x0\n for (const child of node.children) {\n child.x0 = angle\n angle += node.value > 0 ? (child.value / node.value) * span : 0\n child.x1 = angle\n child.y0 = inner + (child.depth - 1) * ring\n child.y1 = child.y0 + ring\n place(child)\n }\n }\n place(root)\n}\n\n/** The node of a sunburst under the angle `angle` (clockwise from 12 o'clock) and radius `r`. */\nexport function sunburstAt(root: TreeNode, angle: number, r: number): TreeNode | null {\n let at: TreeNode | undefined = root\n while (at) {\n const inside: TreeNode | undefined = at.children.find((c) => angle >= c.x0 && angle < c.x1)\n if (!inside) return null\n if (r >= inside.y0 && r < inside.y1) return inside\n at = inside\n }\n return null\n}\n\n/** The gap between a sunburst's arcs, in px. */\nconst ARC_GAP = 1.5\n\n/**\n * Draws a sunburst round `(cx, cy)`, sweeping in with `sweep` (0 to 1).\n * Nodes other than `focus`, its ancestors and its descendants are faded.\n */\n/** How much of a sunburst shows off the branch pointed at. */\nexport const SUNBURST_FADE = 0.4\n\n/** A node with its ancestors and all its descendants: what stays lit when it is pointed at. */\nexport function sunburstBranch(node: TreeNode): TreeNode[] {\n const out: TreeNode[] = []\n for (let a = node.parent; a; a = a.parent) out.push(a)\n const stack = [node]\n while (stack.length) {\n const n = stack.pop()!\n out.push(n)\n for (const c of n.children) stack.push(c)\n }\n return out\n}\n\nexport function drawSunburst(\n painter: Painter,\n nodes: TreeNode[],\n colors: string[],\n {\n cx,\n cy,\n surface,\n focus = -1,\n sweep = 1,\n }: { cx: number; cy: number; surface: string; focus?: number; sweep?: number },\n) {\n const at = (angle: number) => angle * sweep - Math.PI / 2\n const focused = nodes[focus]\n const lit = (node: TreeNode) => {\n if (!focused) return true\n for (let a: TreeNode | null = node; a; a = a.parent) if (a === focused) return true\n for (let a: TreeNode | null = focused; a; a = a.parent) if (a === node) return true\n return false\n }\n painter.save()\n for (const node of nodes) {\n if (node.depth === 0 || !(node.x1 > node.x0)) continue\n painter.save()\n if (!lit(node)) painter.globalAlpha *= SUNBURST_FADE\n painter.fillStyle = colors[node.index]!\n painter.beginPath()\n painter.arc(cx, cy, node.y1, at(node.x0), at(node.x1))\n painter.arc(cx, cy, node.y0, at(node.x1), at(node.x0), true)\n painter.closePath()\n painter.fill()\n painter.restore()\n }\n // the gaps: rings and spokes of the surface's color\n painter.strokeStyle = surface\n painter.lineWidth = ARC_GAP\n painter.beginPath()\n for (const node of nodes) {\n if (node.depth === 0 || !(node.x1 > node.x0)) continue\n const a = at(node.x0)\n // arcs too thin to show beside a gap run together, but a group's edge stays\n const wide = (node.x1 - node.x0) * sweep * node.y1 >= ARC_GAP * 3\n if (wide || !node.parent || node.parent.depth === 0 || node.x0 === node.parent.x0) {\n painter.moveTo(cx + Math.cos(a) * node.y0, cy + Math.sin(a) * node.y0)\n painter.lineTo(cx + Math.cos(a) * node.y1, cy + Math.sin(a) * node.y1)\n }\n painter.moveTo(cx + Math.cos(at(node.x0)) * node.y0, cy + Math.sin(at(node.x0)) * node.y0)\n painter.arc(cx, cy, node.y0, at(node.x0), at(node.x1))\n }\n painter.stroke()\n painter.restore()\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ // src/core/warn.ts
2
+ var warned = /* @__PURE__ */ new Set();
3
+ /** A warning in development, once per kind of mistake. */
4
+ function warnOnce(key, text) {
5
+ if (process.env.NODE_ENV === "production" || warned.has(key)) return;
6
+ warned.add(key);
7
+ console.warn(`[@dou-ui/chart] ${text}`);
8
+ }
9
+ export { warnOnce };
10
+
11
+ //# sourceMappingURL=warn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warn.js","names":[],"sources":["../../src/core/warn.ts"],"sourcesContent":["const warned = new Set<string>()\n/** A warning in development, once per kind of mistake. */\nexport function warnOnce(key: string, text: string) {\n // the app's bundler replaces this, as for Vue's own warnings\n if (process.env.NODE_ENV === 'production' || warned.has(key)) return\n warned.add(key)\n console.warn(`[@dou-ui/chart] ${text}`)\n}\n\n/** Forgets what was warned about, so a test sees each warning afresh. */\nexport function forgetWarnings() {\n warned.clear()\n}\n"],"mappings":";AAAA,IAAM,yBAAS,IAAI,IAAY;;AAE/B,SAAgB,SAAS,KAAa,MAAc;CAElD,IAAA,QAAA,IAAA,aAA6B,gBAAgB,OAAO,IAAI,GAAG,GAAG;CAC9D,OAAO,IAAI,GAAG;CACd,QAAQ,KAAK,mBAAmB,MAAM;AACxC"}