@ixfx/components 0.3.1 → 0.4.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 (256) hide show
  1. package/bundle/index.d.ts +1086 -603
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +16527 -14258
  4. package/bundle/index.js.map +1 -1
  5. package/bundle/style.css +14 -4
  6. package/dist/ac-text.d.ts.map +1 -1
  7. package/dist/ac-text.js +11 -6
  8. package/dist/ac-text.js.map +1 -1
  9. package/dist/{button-DMt5XWUK.js → button-C3fLMKUv.js} +4 -4
  10. package/dist/{button-DMt5XWUK.js.map → button-C3fLMKUv.js.map} +1 -1
  11. package/dist/button.d.ts.map +1 -1
  12. package/dist/button.js +1 -1
  13. package/dist/checkbox.d.ts +2 -2
  14. package/dist/checkbox.d.ts.map +1 -1
  15. package/dist/checkbox.js +14 -8
  16. package/dist/checkbox.js.map +1 -1
  17. package/dist/{colour-C3MQIjFJ-BLXg8W3U.js → colour-C3MQIjFJ-vRCdr8W-.js} +146 -552
  18. package/dist/colour-C3MQIjFJ-vRCdr8W-.js.map +1 -0
  19. package/dist/{colour-picker-K6zu82lm.js → colour-picker-0sgAha1T.js} +14 -9
  20. package/dist/colour-picker-0sgAha1T.js.map +1 -0
  21. package/dist/colour-picker.d.ts +1 -1
  22. package/dist/colour-picker.js +1 -1
  23. package/dist/crumbs.d.ts +1 -1
  24. package/dist/crumbs.d.ts.map +1 -1
  25. package/dist/crumbs.js +11 -6
  26. package/dist/crumbs.js.map +1 -1
  27. package/dist/data-display.d.ts +9 -4
  28. package/dist/data-display.d.ts.map +1 -1
  29. package/dist/data-display.js +270 -43
  30. package/dist/data-display.js.map +1 -1
  31. package/dist/data-provider-DgI909FP.js +23 -0
  32. package/dist/data-provider-DgI909FP.js.map +1 -0
  33. package/dist/{decorate-D7rC1gLP.js → decorate-DdjvVHS-.js} +2 -2
  34. package/dist/{decorate-D7rC1gLP.js.map → decorate-DdjvVHS-.js.map} +1 -1
  35. package/dist/{defaults-C7elhuyJ.js → defaults-C3b9OWJD.js} +2 -2
  36. package/dist/{defaults-C7elhuyJ.js.map → defaults-C3b9OWJD.js.map} +1 -1
  37. package/dist/{dist-TAGYwaju.js → dist-CA13FvMn.js} +7 -66
  38. package/dist/dist-CA13FvMn.js.map +1 -0
  39. package/dist/editable-label.d.ts.map +1 -1
  40. package/dist/editable-label.js +3 -2
  41. package/dist/editable-label.js.map +1 -1
  42. package/dist/fallbacks-pNMOMx38.js +168 -0
  43. package/dist/fallbacks-pNMOMx38.js.map +1 -0
  44. package/dist/{hex-editor-DlfoA65y.d.ts → hex-editor-CMIxtNgT.d.ts} +1 -1
  45. package/dist/hex-editor-CMIxtNgT.d.ts.map +1 -0
  46. package/dist/{hex-editor-CsN_ySkH.js → hex-editor-WZrjRtvL.js} +3 -3
  47. package/dist/{hex-editor-CsN_ySkH.js.map → hex-editor-WZrjRtvL.js.map} +1 -1
  48. package/dist/hex.d.ts +1 -1
  49. package/dist/hex.js +1 -1
  50. package/dist/{highlight-TPbSHruI.js → highlight-B-eQrhhb.js} +1 -1
  51. package/dist/{highlight-TPbSHruI.js.map → highlight-B-eQrhhb.js.map} +1 -1
  52. package/dist/{icon-CeTDJhC7.d.ts → icon-Bd5BiU4b.d.ts} +2 -2
  53. package/dist/icon-Bd5BiU4b.d.ts.map +1 -0
  54. package/dist/{icon-9NWTXtE1.js → icon-Ndo40kNO.js} +6 -5
  55. package/dist/icon-Ndo40kNO.js.map +1 -0
  56. package/dist/icons.d.ts +2 -2
  57. package/dist/icons.js +3 -3
  58. package/dist/{incr-search-DSKKsk6w.js → incr-search-CeERfijK.js} +2 -2
  59. package/dist/{incr-search-DSKKsk6w.js.map → incr-search-CeERfijK.js.map} +1 -1
  60. package/dist/incr-search.d.ts +1 -1
  61. package/dist/incr-search.js +2 -2
  62. package/dist/{index-hXFn14tM.d.ts → index-BMjri2-S.d.ts} +2 -2
  63. package/dist/{index-hXFn14tM.d.ts.map → index-BMjri2-S.d.ts.map} +1 -1
  64. package/dist/{index-DSlPeWLK.d.ts → index-CWpNcQKE.d.ts} +5 -5
  65. package/dist/index-CWpNcQKE.d.ts.map +1 -0
  66. package/dist/{index--hrxPBkQ.d.ts → index-CowKi2mo.d.ts} +2 -1
  67. package/dist/index-CowKi2mo.d.ts.map +1 -0
  68. package/dist/{index-B1hNR7Z9.d.ts → index-D87kRcEs.d.ts} +1 -1
  69. package/dist/{index-B1hNR7Z9.d.ts.map → index-D87kRcEs.d.ts.map} +1 -1
  70. package/dist/{index-CnL9krsH.d.ts → index-DgXpCg_G.d.ts} +32 -26
  71. package/dist/index-DgXpCg_G.d.ts.map +1 -0
  72. package/dist/{index-DrQjA8Gs.d.ts → index-s_IhSnwc.d.ts} +2 -2
  73. package/dist/index-s_IhSnwc.d.ts.map +1 -0
  74. package/dist/index.d.ts +432 -121
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +2370 -1707
  77. package/dist/index.js.map +1 -1
  78. package/dist/interaction-D6efrBLo.js +1 -0
  79. package/dist/{keyboard-De_vOHLg.js → keyboard-CimiEskD.js} +1 -1
  80. package/dist/{keyboard-De_vOHLg.js.map → keyboard-CimiEskD.js.map} +1 -1
  81. package/dist/{labelled-input-base-CqPL5rKm.js → labelled-input-base-9K_w3oLj.js} +2 -2
  82. package/dist/{labelled-input-base-CqPL5rKm.js.map → labelled-input-base-9K_w3oLj.js.map} +1 -1
  83. package/dist/{labelled-input-base-D-Y7agky.d.ts → labelled-input-base-ORb1rGq6.d.ts} +1 -1
  84. package/dist/labelled-input-base-ORb1rGq6.d.ts.map +1 -0
  85. package/dist/labelled-radial-input.d.ts +2 -2
  86. package/dist/labelled-radial-input.d.ts.map +1 -1
  87. package/dist/labelled-radial-input.js +7 -6
  88. package/dist/labelled-radial-input.js.map +1 -1
  89. package/dist/labelled-range-input.d.ts +1 -1
  90. package/dist/labelled-range-input.js +2 -2
  91. package/dist/led.d.ts +1 -1
  92. package/dist/led.d.ts.map +1 -1
  93. package/dist/led.js +2 -2
  94. package/dist/led.js.map +1 -1
  95. package/dist/{menu-item-CKRfP0pN.js → menu-item-BrIuORYD.js} +20 -10
  96. package/dist/menu-item-BrIuORYD.js.map +1 -0
  97. package/dist/{menu-item-ClQF2DKN.d.ts → menu-item-COx-Azgj.d.ts} +1 -1
  98. package/dist/menu-item-COx-Azgj.d.ts.map +1 -0
  99. package/dist/{menu-DJJuCm-5.js → menu-vjoiHZ13.js} +30 -17
  100. package/dist/menu-vjoiHZ13.js.map +1 -0
  101. package/dist/menu.d.ts +2 -2
  102. package/dist/menu.js +2 -2
  103. package/dist/miller.d.ts +2 -2
  104. package/dist/miller.d.ts.map +1 -1
  105. package/dist/miller.js +18 -11
  106. package/dist/miller.js.map +1 -1
  107. package/dist/narrowed-text.d.ts.map +1 -1
  108. package/dist/narrowed-text.js +7 -5
  109. package/dist/narrowed-text.js.map +1 -1
  110. package/dist/panel.d.ts +1 -1
  111. package/dist/panel.d.ts.map +1 -1
  112. package/dist/panel.js +5 -4
  113. package/dist/panel.js.map +1 -1
  114. package/dist/plots.d.ts +2 -2
  115. package/dist/plots.js +2 -2
  116. package/dist/polar-pad.d.ts +1 -1
  117. package/dist/polar-pad.d.ts.map +1 -1
  118. package/dist/polar-pad.js +10 -4
  119. package/dist/polar-pad.js.map +1 -1
  120. package/dist/{popup-ImtS9KnS.js → popup-DiWMxsWj.js} +1 -1
  121. package/dist/{popup-ImtS9KnS.js.map → popup-DiWMxsWj.js.map} +1 -1
  122. package/dist/prominence-DlFShic3.js +104 -0
  123. package/dist/prominence-DlFShic3.js.map +1 -0
  124. package/dist/{radial-input-LUSBEycd.d.ts → radial-input-CpQPs1Mp.d.ts} +1 -1
  125. package/dist/radial-input-CpQPs1Mp.d.ts.map +1 -0
  126. package/dist/{radial-input-DZA6WaFu.js → radial-input-DZ7eQCcM.js} +11 -6
  127. package/dist/radial-input-DZ7eQCcM.js.map +1 -0
  128. package/dist/radial-input.d.ts +1 -1
  129. package/dist/radial-input.js +1 -1
  130. package/dist/range-input.d.ts +1 -1
  131. package/dist/range-input.d.ts.map +1 -1
  132. package/dist/range-input.js +9 -4
  133. package/dist/range-input.js.map +1 -1
  134. package/dist/range.d.ts +1 -1
  135. package/dist/range.d.ts.map +1 -1
  136. package/dist/range.js +5 -3
  137. package/dist/range.js.map +1 -1
  138. package/dist/{registry-Q2gYQCHM.js → registry-CkW7q09Q.js} +1 -1
  139. package/dist/{registry-Q2gYQCHM.js.map → registry-CkW7q09Q.js.map} +1 -1
  140. package/dist/selecthorizontal.d.ts +1 -1
  141. package/dist/selecthorizontal.d.ts.map +1 -1
  142. package/dist/selecthorizontal.js +4 -3
  143. package/dist/selecthorizontal.js.map +1 -1
  144. package/dist/snap-container.d.ts.map +1 -1
  145. package/dist/snap-container.js +1 -1
  146. package/dist/split-layout.d.ts +1 -1
  147. package/dist/split-layout.d.ts.map +1 -1
  148. package/dist/split-layout.js +6 -5
  149. package/dist/split-layout.js.map +1 -1
  150. package/dist/style.css +14 -4
  151. package/dist/swipe.d.ts.map +1 -1
  152. package/dist/swipe.js +9 -4
  153. package/dist/swipe.js.map +1 -1
  154. package/dist/{tab-list-BnqISNvO.d.ts → tab-list-DLzb-m-I.d.ts} +2 -2
  155. package/dist/tab-list-DLzb-m-I.d.ts.map +1 -0
  156. package/dist/tabs.d.ts +1 -1
  157. package/dist/tabs.js +10 -4
  158. package/dist/tabs.js.map +1 -1
  159. package/dist/{tickled-controller-Cq1Va0rR.d.ts → tickled-controller-BjYCzGrU.d.ts} +2 -2
  160. package/dist/tickled-controller-BjYCzGrU.d.ts.map +1 -0
  161. package/dist/{tickled-styles-Bg3QbcrD.js → tickled-styles-fNDdqf6l.js} +1 -17
  162. package/dist/{tickled-styles-Bg3QbcrD.js.map → tickled-styles-fNDdqf6l.js.map} +1 -1
  163. package/dist/{timeline-Cv75Th2U.js → timeline-2OFtN4Ta.js} +1437 -36
  164. package/dist/timeline-2OFtN4Ta.js.map +1 -0
  165. package/dist/timeline.d.ts +1 -1
  166. package/dist/timeline.js +1 -1
  167. package/dist/{tooltip-DMxmBNky.js → tooltip-CJt3WLmN.js} +1 -1
  168. package/dist/{tooltip-DMxmBNky.js.map → tooltip-CJt3WLmN.js.map} +1 -1
  169. package/dist/{tooltip-CwGfb4lp.d.ts → tooltip-RGVIwHrZ.d.ts} +1 -1
  170. package/dist/{tooltip-CwGfb4lp.d.ts.map → tooltip-RGVIwHrZ.d.ts.map} +1 -1
  171. package/dist/{tree-CvvKbO-f.js → tree-CJWpMUvD.js} +113 -103
  172. package/dist/tree-CJWpMUvD.js.map +1 -0
  173. package/dist/{tree-component-D8Bg48tt.d.ts → tree-component-BcO26Xvt.d.ts} +65 -3
  174. package/dist/tree-component-BcO26Xvt.d.ts.map +1 -0
  175. package/dist/tree.d.ts +15 -15
  176. package/dist/tree.d.ts.map +1 -1
  177. package/dist/tree.js +1 -1
  178. package/dist/{types-BKaqnpwx.d.ts → types-DSfbtHs3.d.ts} +1 -1
  179. package/dist/types-DSfbtHs3.d.ts.map +1 -0
  180. package/dist/{xy-axis-DL0tfJDr.js → xy-axis-CK64haaK.js} +1831 -359
  181. package/dist/xy-axis-CK64haaK.js.map +1 -0
  182. package/dist/{xy-axis-D9uwpGTT.d.ts → xy-axis-McdUpcYr.d.ts} +102 -3
  183. package/dist/xy-axis-McdUpcYr.d.ts.map +1 -0
  184. package/dist/xy-pad.d.ts +1 -1
  185. package/dist/xy-pad.d.ts.map +1 -1
  186. package/dist/xy-pad.js +11 -6
  187. package/dist/xy-pad.js.map +1 -1
  188. package/docs-user/README.md +45 -0
  189. package/docs-user/ac-text.md +67 -0
  190. package/docs-user/ac-token.md +187 -0
  191. package/docs-user/button.md +355 -0
  192. package/docs-user/checkbox.md +62 -0
  193. package/docs-user/colour-picker.md +237 -0
  194. package/docs-user/crumbs.md +66 -0
  195. package/docs-user/data-display.md +98 -0
  196. package/docs-user/editable-label.md +244 -0
  197. package/docs-user/grouped-item-lister.md +424 -0
  198. package/docs-user/icons.md +191 -0
  199. package/docs-user/incr-search.md +94 -0
  200. package/docs-user/labelled-radial-input.md +204 -0
  201. package/docs-user/labelled-range-input.md +194 -0
  202. package/docs-user/led.md +40 -0
  203. package/docs-user/menu.md +319 -0
  204. package/docs-user/miller.md +453 -0
  205. package/docs-user/narrowed-text.md +72 -0
  206. package/docs-user/panel.md +250 -0
  207. package/docs-user/plots.md +361 -0
  208. package/docs-user/polar-pad.md +228 -0
  209. package/docs-user/radial-input.md +559 -0
  210. package/docs-user/range-input.md +264 -0
  211. package/docs-user/range.md +12 -0
  212. package/docs-user/selecthorizontal.md +32 -0
  213. package/docs-user/snap-container.md +132 -0
  214. package/docs-user/split-layout.md +232 -0
  215. package/docs-user/swipe.md +44 -0
  216. package/docs-user/tabs.md +217 -0
  217. package/docs-user/timeline.md +116 -0
  218. package/docs-user/transitory-label.md +120 -0
  219. package/docs-user/tree.md +592 -0
  220. package/docs-user/user-catalog.md +165 -0
  221. package/docs-user/user-theming.md +379 -0
  222. package/docs-user/util.md +122 -0
  223. package/docs-user/vertical-list.md +351 -0
  224. package/docs-user/xy-pad.md +94 -0
  225. package/package.json +19 -18
  226. package/dist/colour-C3MQIjFJ-BLXg8W3U.js.map +0 -1
  227. package/dist/colour-picker-K6zu82lm.js.map +0 -1
  228. package/dist/dist-BX0OVIm7.js +0 -1290
  229. package/dist/dist-BX0OVIm7.js.map +0 -1
  230. package/dist/dist-TAGYwaju.js.map +0 -1
  231. package/dist/hex-editor-DlfoA65y.d.ts.map +0 -1
  232. package/dist/icon-9NWTXtE1.js.map +0 -1
  233. package/dist/icon-CeTDJhC7.d.ts.map +0 -1
  234. package/dist/index--hrxPBkQ.d.ts.map +0 -1
  235. package/dist/index-CnL9krsH.d.ts.map +0 -1
  236. package/dist/index-DSlPeWLK.d.ts.map +0 -1
  237. package/dist/index-DrQjA8Gs.d.ts.map +0 -1
  238. package/dist/interaction-DG7X1rhI.js +0 -1
  239. package/dist/labelled-input-base-D-Y7agky.d.ts.map +0 -1
  240. package/dist/menu-DJJuCm-5.js.map +0 -1
  241. package/dist/menu-item-CKRfP0pN.js.map +0 -1
  242. package/dist/menu-item-ClQF2DKN.d.ts.map +0 -1
  243. package/dist/prominence--ic9uWBl.js +0 -98
  244. package/dist/prominence--ic9uWBl.js.map +0 -1
  245. package/dist/radial-input-DZA6WaFu.js.map +0 -1
  246. package/dist/radial-input-LUSBEycd.d.ts.map +0 -1
  247. package/dist/tab-list-BnqISNvO.d.ts.map +0 -1
  248. package/dist/tickled-controller-Cq1Va0rR.d.ts.map +0 -1
  249. package/dist/timeline-Cv75Th2U.js.map +0 -1
  250. package/dist/tree-CvvKbO-f.js.map +0 -1
  251. package/dist/tree-component-D8Bg48tt.d.ts.map +0 -1
  252. package/dist/types-BKaqnpwx.d.ts.map +0 -1
  253. package/dist/xy-axis-D9uwpGTT.d.ts.map +0 -1
  254. package/dist/xy-axis-DL0tfJDr.js.map +0 -1
  255. /package/bundle/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
  256. /package/dist/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
@@ -1,10 +1,487 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
- import { A as isPoint3d, C as guard$3, D as isNull, E as isNaN$1, M as __exportAll$2, O as isPlaceholder, S as toString, T as isEmpty$1, _ as getTwoPointParameters, a as Unit3d, b as to3d, c as angleRadianThreePoint, d as fromCartesian, f as rotate, g as getPointParameter$1, h as distance2d, i as Unit, j as test, k as isPoint, l as average$1, m as distance, n as Empty$1, o as angleRadian, p as toCartesian$1, r as Empty3d, s as angleRadianCircle, t as colour_exports, u as averager, v as subtract, w as guardNonZeroPoint, x as toIntegerValues, y as to2d } from "./colour-C3MQIjFJ-BLXg8W3U.js";
3
- import { C as resultThrow, S as percentTest, _ as functionTest, c as round, f as wrap, l as scale, o as quantiseEvery, r as dotProduct, s as rangeStream, t as clamp, w as stringTest, x as numberTest } from "./dist-TAGYwaju.js";
4
- import { c as isEqualDefault, n as intervalToMs, s as getOrGenerateSync, t as continuously } from "./dist-BX0OVIm7.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-DdjvVHS-.js";
2
+ import { a as radiansNormalise, c as isEmpty$1, d as isPlaceholder, f as isPoint, i as piPi$1, l as isNaN$1, m as pointTest, n as average$1, o as guard$2, p as isPoint3d, r as averager, s as guardNonZeroPoint, t as colour_exports, u as isNull } from "./colour-C3MQIjFJ-vRCdr8W-.js";
3
+ import { C as resultThrow, S as percentTest, _ as functionTest, c as round, f as wrap, l as scale, o as quantiseEvery, r as dotProduct, s as rangeStream, t as clamp, v as integerTest, w as stringTest, x as numberTest } from "./dist-CA13FvMn.js";
5
4
  import { LitElement, css, html, svg } from "lit";
6
5
  import { property, state } from "lit/decorators.js";
7
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/max-NDZ04wx6.js
6
+ import { repeat } from "lit/directives/repeat.js";
7
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/chunk-pbuEa-1d.js
8
+ var __defProp$2 = Object.defineProperty;
9
+ var __exportAll$2 = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) __defProp$2(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ if (!no_symbols) __defProp$2(target, Symbol.toStringTag, { value: "Module" });
16
+ return target;
17
+ };
18
+ //#endregion
19
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/to-oKNQeMO-.js
20
+ function getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6) {
21
+ if (isPoint3d(a1) && isPoint3d(ab2)) return [a1, ab2];
22
+ if (isPoint(a1) && isPoint(ab2)) return [a1, ab2];
23
+ if (isPoint3d(a1)) {
24
+ const b = {
25
+ x: ab2,
26
+ y: ab3,
27
+ z: ab4
28
+ };
29
+ if (!isPoint3d(b)) throw new Error(`Expected x, y & z parameters`);
30
+ return [a1, b];
31
+ }
32
+ if (isPoint(a1)) {
33
+ const b = {
34
+ x: ab2,
35
+ y: ab3
36
+ };
37
+ if (!isPoint(b)) throw new Error(`Expected x & y parameters`);
38
+ return [a1, b];
39
+ }
40
+ if (typeof ab5 !== `undefined` && typeof ab4 !== `undefined`) {
41
+ const a = {
42
+ x: a1,
43
+ y: ab2,
44
+ z: ab3
45
+ };
46
+ const b = {
47
+ x: ab4,
48
+ y: ab5,
49
+ z: ab6
50
+ };
51
+ if (!isPoint3d(a)) throw new Error(`Expected x,y,z for first point`);
52
+ if (!isPoint3d(b)) throw new Error(`Expected x,y,z for second point`);
53
+ return [a, b];
54
+ }
55
+ const a = {
56
+ x: a1,
57
+ y: ab2
58
+ };
59
+ const b = {
60
+ x: ab3,
61
+ y: ab4
62
+ };
63
+ if (!isPoint(a)) throw new Error(`Expected x,y for first point`);
64
+ if (!isPoint(b)) throw new Error(`Expected x,y for second point`);
65
+ return [a, b];
66
+ }
67
+ /**
68
+ * Returns a Point form of either a point, x,y params or x,y,z params.
69
+ * If parameters are undefined, an empty point is returned (0, 0)
70
+ * @ignore
71
+ * @param a
72
+ * @param b
73
+ * @returns
74
+ */
75
+ function getPointParameter$1(a, b, c) {
76
+ if (a === void 0) return {
77
+ x: 0,
78
+ y: 0
79
+ };
80
+ if (Array.isArray(a)) {
81
+ if (a.length === 0) return Object.freeze({
82
+ x: 0,
83
+ y: 0
84
+ });
85
+ if (a.length === 1) return Object.freeze({
86
+ x: a[0],
87
+ y: 0
88
+ });
89
+ if (a.length === 2) return Object.freeze({
90
+ x: a[0],
91
+ y: a[1]
92
+ });
93
+ if (a.length === 3) return Object.freeze({
94
+ x: a[0],
95
+ y: a[1],
96
+ z: a[2]
97
+ });
98
+ throw new Error(`Expected array to be 1-3 elements in length. Got ${a.length}.`);
99
+ }
100
+ if (isPoint(a)) return a;
101
+ else if (typeof a !== `number` || typeof b !== `number`) throw new TypeError(`Expected point or x,y as parameters. Got: a: ${JSON.stringify(a)} b: ${JSON.stringify(b)}`);
102
+ if (typeof c === `number`) return Object.freeze({
103
+ x: a,
104
+ y: b,
105
+ z: c
106
+ });
107
+ return Object.freeze({
108
+ x: a,
109
+ y: b
110
+ });
111
+ }
112
+ /**
113
+ * Calculate distance between two points.
114
+ * If both points have a `z` property, the distance is 3D distance is calculated.
115
+ * If only one point has a `z`, it is ignored. To force 2D distance, use {@link distance2d}
116
+ *
117
+ * ```js
118
+ * // Distance between two points
119
+ * const ptA = { x: 0.5, y:0.8 };
120
+ * const ptB = { x: 1, y: 0.4 };
121
+ * distance(ptA, ptB);
122
+ * // Or, provide x,y as parameters
123
+ * distance(ptA, 0.4, 0.9);
124
+ *
125
+ * // Distance from ptA to x: 0.5, y:0.8, z: 0.1
126
+ * const ptC = { x: 0.5, y:0.5, z: 0.3 };
127
+ * // With x,y,z as parameters:
128
+ * distance(ptC, 0.5, 0.8, 0.1);
129
+ * ```
130
+ * @param a First point
131
+ * @param xOrB Second point, or x coord
132
+ * @param y y coord, if x coord is given
133
+ * @param z Optional z coord, if x and y are given.
134
+ * @returns
135
+ */
136
+ function distance(a, xOrB, y, z) {
137
+ const pt = getPointParameter$1(xOrB, y, z);
138
+ guard$2(pt, `b`);
139
+ guard$2(a, `a`);
140
+ return isPoint3d(pt) && isPoint3d(a) ? Math.hypot(pt.x - a.x, pt.y - a.y, pt.z - a.z) : Math.hypot(pt.x - a.x, pt.y - a.y);
141
+ }
142
+ /**
143
+ * As {@link distance} but always compares by x,y only.
144
+ * @param a
145
+ * @param xOrB
146
+ * @param y
147
+ * @returns
148
+ */
149
+ function distance2d(a, xOrB, y) {
150
+ const pt = getPointParameter$1(xOrB, y);
151
+ guard$2(pt, `b`);
152
+ guard$2(a, `a`);
153
+ return Math.hypot(pt.x - a.x, pt.y - a.y);
154
+ }
155
+ /**
156
+ * Returns a Point with the x,y,z values of two points subtracted (a-b).
157
+ *
158
+ * `z` parameter is used if present. Uses a default value of 0 for 'z' when subtracting a 2D point with a 3D one.
159
+ *
160
+ * Examples:
161
+ *
162
+ * ```js
163
+ * subtract(ptA, ptB);
164
+ * subtract(x1, y1, x2, y2);
165
+ * subtract(ptA, x2, y2);
166
+ * ```
167
+ */
168
+ function subtract(a1, ab2, ab3, ab4, ab5, ab6) {
169
+ const [ptA, ptB] = getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6);
170
+ guard$2(ptA, `a`);
171
+ guard$2(ptB, `b`);
172
+ const pt = {
173
+ x: ptA.x - ptB.x,
174
+ y: ptA.y - ptB.y
175
+ };
176
+ if (isPoint3d(ptA) || isPoint3d(ptB)) pt.z = (ptA.z ?? 0) - (ptB.z ?? 0);
177
+ return Object.freeze(pt);
178
+ }
179
+ /**
180
+ * Returns a point with rounded x,y coordinates. By default uses `Math.round` to round.
181
+ * ```js
182
+ * toIntegerValues({x:1.234, y:5.567}); // Yields: {x:1, y:6}
183
+ * ```
184
+ *
185
+ * ```js
186
+ * toIntegerValues(pt, Math.ceil); // Use Math.ceil to round x,y of `pt`.
187
+ * ```
188
+ * @param pt Point to round
189
+ * @param rounder Rounding function, or Math.round by default
190
+ * @returns
191
+ */
192
+ const toIntegerValues = (pt, rounder = Math.round) => {
193
+ guard$2(pt, `pt`);
194
+ return Object.freeze({
195
+ x: rounder(pt.x),
196
+ y: rounder(pt.y)
197
+ });
198
+ };
199
+ /**
200
+ * Returns a copy of `pt` with `z` field omitted.
201
+ * If it didn't have one to begin within, a copy is still returned.
202
+ * @param pt
203
+ * @returns
204
+ */
205
+ const to2d = (pt) => {
206
+ guard$2(pt, `pt`);
207
+ let copy = { ...pt };
208
+ delete copy.z;
209
+ return Object.freeze(copy);
210
+ };
211
+ /**
212
+ * Returns a copy of `pt` with a `z` field set.
213
+ * Defaults to a z value of 0.
214
+ * @param pt Point
215
+ * @param z Z-value, defaults to 0
216
+ * @returns
217
+ */
218
+ const to3d = (pt, z = 0) => {
219
+ guard$2(pt, `pt`);
220
+ return Object.freeze({
221
+ ...pt,
222
+ z
223
+ });
224
+ };
225
+ /**
226
+ * Returns a human-friendly string representation `(x, y)`.
227
+ * If `precision` is supplied, this will be the number of significant digits.
228
+ * @param p
229
+ * @returns
230
+ */
231
+ function toString(p, digits) {
232
+ if (p === void 0) return `(undefined)`;
233
+ if (p === null) return `(null)`;
234
+ guard$2(p, `pt`);
235
+ const x = digits ? p.x.toFixed(digits) : p.x;
236
+ const y = digits ? p.y.toFixed(digits) : p.y;
237
+ if (p.z === void 0) return `(${x},${y})`;
238
+ else return `(${x},${y},${digits ? p.z.toFixed(digits) : p.z})`;
239
+ }
240
+ //#endregion
241
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/polar-ZdU4ci-4.js
242
+ /**
243
+ * Returns true if `p` seems to be a {@link Polar.Coord} (ie has both distance & angleRadian fields)
244
+ * @param p
245
+ * @returns True if `p` seems to be a PolarCoord
246
+ */
247
+ const isPolarCoord = (p) => {
248
+ if (p.distance === void 0) return false;
249
+ if (p.angleRadian === void 0) return false;
250
+ return true;
251
+ };
252
+ /**
253
+ * Returns a rotated coordinate
254
+ * @param c Coordinate
255
+ * @param amountRadian Amount to rotate, in radians
256
+ * @returns
257
+ */
258
+ const rotate = (c, amountRadian) => Object.freeze({
259
+ ...c,
260
+ angleRadian: c.angleRadian + amountRadian
261
+ });
262
+ /**
263
+ * An empty point of `{ x: 0, y: 0 }`.
264
+ *
265
+ * Use `isEmpty` to check if a point is empty.
266
+ * Use `Empty3d` to get an empty point with `z`.
267
+ */
268
+ const Empty$1 = {
269
+ x: 0,
270
+ y: 0
271
+ };
272
+ /**
273
+ * Returns { x:1, y:1 }
274
+ */
275
+ const Unit = {
276
+ x: 1,
277
+ y: 1
278
+ };
279
+ /**
280
+ * An empty Point of `{ x: 0, y: 0, z: 0}`
281
+ * Use `isEmpty` to check if a point is empty.
282
+ * Use `Empty` to get an empty point without `z`.
283
+ */
284
+ const Empty3d = {
285
+ x: 0,
286
+ y: 0,
287
+ z: 0
288
+ };
289
+ /**
290
+ * Returns { x:1,y:1,z:1 }
291
+ */
292
+ const Unit3d = {
293
+ x: 1,
294
+ y: 1,
295
+ z: 1
296
+ };
297
+ /**
298
+ * Converts to Cartesian coordinate from polar.
299
+ *
300
+ * ```js
301
+ *
302
+ * const origin = { x: 50, y: 50}; // Polar origin
303
+ * // Yields: { x, y }
304
+ * const polar = Polar.toCartesian({ distance: 10, angleRadian: 0 }, origin);
305
+ * ```
306
+ *
307
+ * Distance and angle can be provided as numbers intead:
308
+ *
309
+ * ```
310
+ * // Yields: { x, y }
311
+ * const polar = Polar.toCartesian(10, 0, origin);
312
+ * ```
313
+ *
314
+ * @param a
315
+ * @param b
316
+ * @param c
317
+ * @returns
318
+ */
319
+ const toCartesian$1 = (a, b, c) => {
320
+ if (isPolarCoord(a)) {
321
+ if (typeof b === `undefined`) b = Empty$1;
322
+ if (isPoint(b)) return polarToCartesian(a.distance, a.angleRadian, b);
323
+ throw new Error(`Expecting (Coord, Point). Second parameter is not a point`);
324
+ } else if (typeof a === `object`) throw new TypeError(`First param is an object, but not a Coord: ${JSON.stringify(a)}`);
325
+ else if (typeof a === `number` && typeof b === `number`) {
326
+ if (typeof c === `undefined`) c = Empty$1;
327
+ if (!isPoint(c)) throw new Error(`Expecting (number, number, Point). Point param wrong type`);
328
+ return polarToCartesian(a, b, c);
329
+ } else throw new TypeError(`Expecting parameters of (number, number). Got: (${typeof a}, ${typeof b}, ${typeof c}). a: ${JSON.stringify(a)}`);
330
+ };
331
+ /**
332
+ * Converts a Cartesian coordinate to polar
333
+ *
334
+ * ```js
335
+ *
336
+ * // Yields: { angleRadian, distance }
337
+ * const polar = Polar.fromCartesian({x: 50, y: 50}, origin);
338
+ * ```
339
+ *
340
+ * Any additional properties of `point` are copied to object.
341
+ *
342
+ * Options:
343
+ * * fullCircle: If _true_ (default) returns values on 0..2PI range. If _false_, 0....PI..-PI range.
344
+ * * digits: Rounding to apply
345
+ * @param point Point
346
+ * @param origin Origin. If unspecified, {x:0,y:0} is used
347
+ * @param options Options
348
+ * @returns
349
+ */
350
+ const fromCartesian = (point, origin, options = {}) => {
351
+ if (typeof point !== `object`) throw new TypeError(`Param 'point' wrong. Expecting a Point, got: ${typeof point}`);
352
+ const fullCircle = options.fullCircle ?? true;
353
+ if (typeof origin === `object`) point = subtract(point, origin);
354
+ let angle = Math.atan2(point.y, point.x);
355
+ if (fullCircle) angle = radiansNormalise(angle);
356
+ let distance = Math.hypot(point.x, point.y);
357
+ if (typeof options.digits === `number`) {
358
+ angle = parseFloat(angle.toFixed(options.digits));
359
+ distance = parseFloat(distance.toFixed(options.digits));
360
+ }
361
+ const polar = {
362
+ ...point,
363
+ angleRadian: angle,
364
+ distance
365
+ };
366
+ delete polar.x;
367
+ delete polar.y;
368
+ return Object.freeze(polar);
369
+ };
370
+ /**
371
+ * Converts a polar coordinate to Cartesian
372
+ * @param distance Distance
373
+ * @param angleRadians Angle in radians
374
+ * @param origin Origin, or 0,0 by default.
375
+ * @returns
376
+ */
377
+ const polarToCartesian = (distance, angleRadians, origin = Empty$1) => {
378
+ guard$2(origin);
379
+ return Object.freeze({
380
+ x: origin.x + distance * Math.cos(angleRadians),
381
+ y: origin.y + distance * Math.sin(angleRadians)
382
+ });
383
+ };
384
+ /**
385
+ * Returns the angle in radians between `a` and `b`.
386
+ *
387
+ * Eg if `a` is the origin, and `b` is another point,
388
+ * in degrees one would get 0 to -180 when `b` was above `a`.
389
+ * -180 would be `b` in line with `a`.
390
+ * Same for under `a`.
391
+ *
392
+ * Providing a third point `c` gives the interior angle, where `b` is the middle point.
393
+ *
394
+ * See also {@link angleRadianCircle} which returns coordinates on 0..Math.Pi*2
395
+ * range. This avoids negative numbers.
396
+ *
397
+ * @example Calculate angle between a middle of canvas and the cursor
398
+ * ```js
399
+ * const canvasEl = document.querySelector('canvas');
400
+ * const middle = { x: canvasEl.width/2, y: canvasEl.height /2 }
401
+ *
402
+ * canvasEl.addEventListener(`pointermove`, event => {
403
+ * const cursor = {
404
+ * x: event.offsetX,
405
+ * y: event.offsetY
406
+ * }
407
+ * const a = G.Points.angleRadian(middle, cursor);
408
+ *});
409
+ * ```
410
+ * @param a
411
+ * @param b
412
+ * @param c
413
+ * @returns
414
+ */
415
+ const angleRadian = (a, b, c) => {
416
+ guard$2(a, `a`);
417
+ if (b === void 0) return Math.atan2(a.y, a.x);
418
+ guard$2(b, `b`);
419
+ if (c === void 0) return Math.atan2(b.y - a.y, b.x - a.x);
420
+ guard$2(c, `c`);
421
+ return Math.atan2(b.y - a.y, b.x - a.x) - Math.atan2(c.y - a.y, c.x - a.x);
422
+ };
423
+ /**
424
+ * Returns the angle between point(s) using a radian circle system.
425
+ * ```
426
+ * 90deg
427
+ * Pi/2
428
+ * |
429
+ * Pi ---+--- 0
430
+ * 180 |
431
+ * 3PI/2
432
+ * 270deg
433
+ * ```
434
+ * @param a
435
+ * @param b
436
+ * @param c
437
+ * @returns
438
+ */
439
+ const angleRadianCircle = (a, b, c) => {
440
+ const angle = angleRadian(a, b, c);
441
+ if (angle < 0) return angle + piPi$1;
442
+ return angle;
443
+ };
444
+ /**
445
+ * Return the angle of a wedge, defined by a, b and C points, where 'b'
446
+ * could be thought of as the origin or pivot.
447
+ *
448
+ * @param a
449
+ * @param b
450
+ * @param c
451
+ * @returns
452
+ */
453
+ const angleRadianThreePoint = (a, b, c) => {
454
+ const ab = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
455
+ const bc = Math.sqrt(Math.pow(b.x - c.x, 2) + Math.pow(b.y - c.y, 2));
456
+ const ac = Math.sqrt(Math.pow(c.x - a.x, 2) + Math.pow(c.y - a.y, 2));
457
+ return Math.acos((bc * bc + ab * ab - ac * ac) / (2 * bc * ab));
458
+ };
459
+ //#endregion
460
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/from-points-hWl1SWEr.js
461
+ /**
462
+ * Returns a line from two points
463
+ *
464
+ * ```js
465
+ * // Line from 0,1 to 10,15
466
+ * const line = Lines.fromPoints( { x:0, y:1 }, { x:10, y:15 });
467
+ * // line is: { a: { x: 0, y: 1}, b: { x: 10, y: 15 } };
468
+ * ```
469
+ * @param a Start point
470
+ * @param b End point
471
+ * @returns
472
+ */
473
+ const fromPoints = (a, b) => {
474
+ guard$2(a, `a`);
475
+ guard$2(b, `b`);
476
+ a = Object.freeze({ ...a });
477
+ b = Object.freeze({ ...b });
478
+ return Object.freeze({
479
+ a,
480
+ b
481
+ });
482
+ };
483
+ //#endregion
484
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/max-NDZ04wx6.js
8
485
  /**
9
486
  * Returns a rectangle based on provided four corners.
10
487
  *
@@ -32,7 +509,7 @@ const maxFromCorners = (topLeft, topRight, bottomRight, bottomLeft) => {
32
509
  };
33
510
  };
34
511
  //#endregion
35
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/bbox-DKUDfXRz.js
512
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/bbox-BH5rnhlc.js
36
513
  /**
37
514
  * Returns the 'minimum' point from an array of points, using a comparison function.
38
515
  *
@@ -106,31 +583,7 @@ const bbox3d = (...points) => {
106
583
  };
107
584
  };
108
585
  //#endregion
109
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/from-points-BZ9J-ip2.js
110
- /**
111
- * Returns a line from two points
112
- *
113
- * ```js
114
- * // Line from 0,1 to 10,15
115
- * const line = Lines.fromPoints( { x:0, y:1 }, { x:10, y:15 });
116
- * // line is: { a: { x: 0, y: 1}, b: { x: 10, y: 15 } };
117
- * ```
118
- * @param a Start point
119
- * @param b End point
120
- * @returns
121
- */
122
- const fromPoints = (a, b) => {
123
- guard$3(a, `a`);
124
- guard$3(b, `b`);
125
- a = Object.freeze({ ...a });
126
- b = Object.freeze({ ...b });
127
- return Object.freeze({
128
- a,
129
- b
130
- });
131
- };
132
- //#endregion
133
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/guard-CN6d2Djl.js
586
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/guard-Bg57Xzmd.js
134
587
  /**
135
588
  * Returns true if `p` is a valid line, containing `a` and `b` Points.
136
589
  * ```js
@@ -139,40 +592,53 @@ const fromPoints = (a, b) => {
139
592
  * @param p Value to check
140
593
  * @returns True if a valid line.
141
594
  */
142
- const isLine = (p) => {
595
+ function isLine(p) {
143
596
  if (p === void 0) return false;
144
597
  if (p.a === void 0) return false;
145
598
  if (p.b === void 0) return false;
146
599
  if (!isPoint(p.a)) return false;
147
600
  if (!isPoint(p.b)) return false;
148
601
  return true;
149
- };
602
+ }
150
603
  /**
151
604
  * Returns true if `p` is a {@link PolyLine}, ie. an array of {@link Line}s.
152
605
  * Validates all items in array.
153
- * @param p
606
+ * @param p
154
607
  * @returns
155
608
  */
156
- const isPolyLine = (p) => {
609
+ function isPolyLine(p) {
157
610
  if (!Array.isArray(p)) return false;
158
611
  return !p.some((v) => !isLine(v));
159
- };
612
+ }
160
613
  /**
161
- * Throws an exception if:
162
- * * line is undefined
163
- * * a or b parameters are missing
164
- *
614
+ * Returns a failure if:
615
+ * - line is undefined
616
+ * - a or b parameters are missing
617
+ *
165
618
  * Does not validate points
166
- * @param line
167
- * @param name
619
+ * @param line
620
+ * @param name
168
621
  */
169
- const guard$2 = (line, name = `line`) => {
170
- if (line === void 0) throw new Error(`${name} undefined`);
171
- if (line.a === void 0) throw new Error(`${name}.a undefined. Expected {a:Point, b:Point}. Got: ${JSON.stringify(line)}`);
172
- if (line.b === void 0) throw new Error(`${name}.b undefined. Expected {a:Point, b:Point} Got: ${JSON.stringify(line)}`);
173
- };
622
+ function lineTest(line, name = `line`) {
623
+ if (line === void 0) return {
624
+ success: false,
625
+ error: `${name} undefined`
626
+ };
627
+ if (line.a === void 0) return {
628
+ success: false,
629
+ error: `${name}.a undefined. Expected {a:Point, b:Point}. Got: ${JSON.stringify(line)}`
630
+ };
631
+ if (line.b === void 0) return {
632
+ success: false,
633
+ error: `${name}.b undefined. Expected {a:Point, b:Point} Got: ${JSON.stringify(line)}`
634
+ };
635
+ return {
636
+ success: true,
637
+ value: true
638
+ };
639
+ }
174
640
  //#endregion
175
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/length-UXbCPu0p.js
641
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/length-ChosppvJ.js
176
642
  /**
177
643
  * Returns [a,b] points from either a line parameter, or two points.
178
644
  * It additionally applies the guardPoint function to ensure validity.
@@ -191,8 +657,8 @@ const getPointParameter = (aOrLine, b) => {
191
657
  a = aOrLine;
192
658
  if (b === void 0) throw new Error(`Since first parameter is not a line, two points are expected. Got a: ${JSON.stringify(a)} b: ${JSON.stringify(b)}`);
193
659
  }
194
- guard$3(a, `a`);
195
- guard$3(a, `b`);
660
+ guard$2(a, `a`);
661
+ guard$2(a, `b`);
196
662
  return [a, b];
197
663
  };
198
664
  /**
@@ -217,15 +683,14 @@ function length$1(aOrLine, pointBOrForce2d, force2d) {
217
683
  } else return Math.hypot(x, y);
218
684
  }
219
685
  //#endregion
220
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/interpolate-DBpjKdqZ.js
686
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/interpolate-DhLKNStN.js
221
687
  /**
222
688
  * Calculates a point in-between a line's start and end points.
223
- *
689
+ *
224
690
  * @param amount Interpolation amount
225
691
  * @param aOrLine Line, or first point
226
692
  * @param pointBOrAllowOverflow Second point (if needed) or allowOverflow.
227
693
  * @param allowOverflow If true, interpolation amount is permitted to exceed 0..1, extending the line.
228
- * @returns
229
694
  */
230
695
  function interpolate$1(amount, aOrLine, pointBOrAllowOverflow, allowOverflow) {
231
696
  if (typeof pointBOrAllowOverflow === `boolean`) {
@@ -235,26 +700,47 @@ function interpolate$1(amount, aOrLine, pointBOrAllowOverflow, allowOverflow) {
235
700
  if (!allowOverflow) resultThrow(percentTest(amount, `amount`));
236
701
  else resultThrow(numberTest(amount, ``, `amount`));
237
702
  const [a, b] = getPointParameter(aOrLine, pointBOrAllowOverflow);
238
- const d = length$1(a, b);
239
- const d2 = d * (1 - amount);
240
- if (d === 0 && d2 === 0) return Object.freeze({ ...b });
241
- const x = b.x - d2 * (b.x - a.x) / d;
242
- const y = b.y - d2 * (b.y - a.y) / d;
243
- return Object.freeze({
244
- ...b,
245
- x,
246
- y
247
- });
703
+ return interpolator$2({
704
+ a,
705
+ b
706
+ }, allowOverflow)(amount);
248
707
  }
249
- //#endregion
250
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/guard-DTK6wbGV.js
251
708
  /**
252
- * Throws an error if the dimensions of the rectangle are undefined, NaN or negative.
253
- * @param d
254
- * @param name
709
+ * Returns a function that interpolates along `line`, returning a {@link Point}.
710
+ * ```js
711
+ * const i = interpolator(a: {x:0,y:0}, b:{x:100, y:100});
712
+ * i(0.5); // Returns point 50% between a and b.
713
+ * ```
714
+ * @param line Line to interpolate along
715
+ * @param allowOverflow If _true_ interpolation amount can exceed 0..1, extending the line.
255
716
  */
256
- const guardDim = (d, name = `Dimension`) => {
257
- if (d === void 0) throw new Error(`${name} is undefined`);
717
+ function interpolator$2(line, allowOverflow = false) {
718
+ resultThrow(lineTest(line));
719
+ const d = length$1(line);
720
+ const { a, b } = line;
721
+ return (amount) => {
722
+ if (!allowOverflow) resultThrow(percentTest(amount, `amount`));
723
+ else resultThrow(numberTest(amount, ``, `amount`));
724
+ const d2 = d * (1 - amount);
725
+ if (d === 0 && d2 === 0) return Object.freeze({ ...b });
726
+ const x = b.x - d2 * (b.x - a.x) / d;
727
+ const y = b.y - d2 * (b.y - a.y) / d;
728
+ return Object.freeze({
729
+ ...b,
730
+ x,
731
+ y
732
+ });
733
+ };
734
+ }
735
+ //#endregion
736
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/guard-C2opUnGy.js
737
+ /**
738
+ * Throws an error if the dimensions of the rectangle are undefined, NaN or negative.
739
+ * @param d
740
+ * @param name
741
+ */
742
+ const guardDim = (d, name = `Dimension`) => {
743
+ if (d === void 0) throw new Error(`${name} is undefined`);
258
744
  if (Number.isNaN(d)) throw new Error(`${name} is NaN`);
259
745
  if (d < 0) throw new Error(`${name} cannot be negative`);
260
746
  };
@@ -273,7 +759,7 @@ const guardDim = (d, name = `Dimension`) => {
273
759
  */
274
760
  const guard$1 = (rect, name = `rect`) => {
275
761
  if (rect === void 0) throw new Error(`{$name} undefined`);
276
- if (isPositioned$1(rect)) guard$3(rect, name);
762
+ if (isPositioned$1(rect)) guard$2(rect, name);
277
763
  guardDim(rect.width, name + `.width`);
278
764
  guardDim(rect.height, name + `.height`);
279
765
  };
@@ -312,7 +798,7 @@ const isRect = (rect) => {
312
798
  */
313
799
  const isRectPositioned = (rect) => isRect(rect) && isPositioned$1(rect);
314
800
  //#endregion
315
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/from-top-left-_m03rKOS.js
801
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/from-top-left-D_I93JN9.js
316
802
  /**
317
803
  * Creates a rectangle from its top-left coordinate, a width and height.
318
804
  *
@@ -323,25 +809,24 @@ const isRectPositioned = (rect) => isRect(rect) && isPositioned$1(rect);
323
809
  * @param origin
324
810
  * @param width
325
811
  * @param height
326
- * @returns
327
812
  */
328
- const fromTopLeft = (origin, width, height) => {
813
+ function fromTopLeft(origin, width, height) {
329
814
  guardDim(width, `width`);
330
815
  guardDim(height, `height`);
331
- guard$3(origin, `origin`);
816
+ guard$2(origin, `origin`);
332
817
  return {
333
818
  x: origin.x,
334
819
  y: origin.y,
335
820
  width,
336
821
  height
337
822
  };
338
- };
823
+ }
339
824
  //#endregion
340
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/guard-C80ayJ0B.js
825
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/guard-D8jtfB4t.js
341
826
  const isQuadraticBezier = (path) => path.quadratic !== void 0;
342
827
  const isCubicBezier = (path) => path.cubic1 !== void 0 && path.cubic2 !== void 0;
343
828
  //#endregion
344
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/bezier-0J_WsCxz.js
829
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/bezier-NMQ88x8M.js
345
830
  const { abs: abs$1, cos: cos$1, sin: sin$1, acos: acos$1, atan2, sqrt: sqrt$1, pow: pow$2 } = Math;
346
831
  function crt(v) {
347
832
  return v < 0 ? -pow$2(-v, 1 / 3) : pow$2(v, 1 / 3);
@@ -1455,7 +1940,7 @@ var Bezier = class Bezier {
1455
1940
  pass1.forEach(function(p1) {
1456
1941
  t1 = 0;
1457
1942
  t2 = 0;
1458
- while (t2 <= 1) for (t2 = t1 + step; t2 <= 1 + step; t2 += step) {
1943
+ while (t2 <= 1) for (t2 = t1 + step; t2 <= 1.01; t2 += step) {
1459
1944
  segment = p1.split(t1, t2);
1460
1945
  if (!segment.simple()) {
1461
1946
  t2 -= step;
@@ -1741,7 +2226,7 @@ var Bezier = class Bezier {
1741
2226
  };
1742
2227
  var bezier_exports = /* @__PURE__ */ __exportAll$2({
1743
2228
  cubic: () => cubic,
1744
- interpolator: () => interpolator,
2229
+ interpolator: () => interpolator$1,
1745
2230
  isCubicBezier: () => isCubicBezier,
1746
2231
  isQuadraticBezier: () => isQuadraticBezier,
1747
2232
  quadratic: () => quadratic,
@@ -1806,7 +2291,7 @@ const quadraticSimple = (start, end, bend = 0) => {
1806
2291
  * @param q
1807
2292
  * @returns
1808
2293
  */
1809
- const interpolator = (q) => {
2294
+ const interpolator$1 = (q) => {
1810
2295
  const bzr = isCubicBezier(q) ? new Bezier(q.a.x, q.a.y, q.cubic1.x, q.cubic1.y, q.cubic2.x, q.cubic2.y, q.b.x, q.b.y) : new Bezier(q.a, q.quadratic, q.b);
1811
2296
  return (amount) => bzr.compute(amount);
1812
2297
  };
@@ -1891,14 +2376,14 @@ const quadratictoPath = (quadraticBezier) => {
1891
2376
  });
1892
2377
  };
1893
2378
  //#endregion
1894
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/intersects-skBCWN7w.js
2379
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/intersects-BOuj4lnQ.js
1895
2380
  /**
1896
2381
  * Throws if radius is out of range. If x,y is present, these will be validated too.
1897
2382
  * @param circle
1898
2383
  * @param parameterName
1899
2384
  */
1900
2385
  const guard = (circle, parameterName = `circle`) => {
1901
- if (isCirclePositioned(circle)) guard$3(circle, `circle`);
2386
+ if (isCirclePositioned(circle)) guard$2(circle, `circle`);
1902
2387
  if (Number.isNaN(circle.radius)) throw new Error(`${parameterName}.radius is NaN`);
1903
2388
  if (circle.radius <= 0) throw new Error(`${parameterName}.radius must be greater than zero`);
1904
2389
  };
@@ -1943,8 +2428,8 @@ const isCirclePositioned = (p) => isCircle(p) && isPositioned(p);
1943
2428
  */
1944
2429
  function sum(a1, ab2, ab3, ab4, ab5, ab6) {
1945
2430
  const [ptA, ptB] = getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6);
1946
- guard$3(ptA, `a`);
1947
- guard$3(ptB, `b`);
2431
+ guard$2(ptA, `a`);
2432
+ guard$2(ptB, `b`);
1948
2433
  const pt = {
1949
2434
  x: ptA.x + ptB.x,
1950
2435
  y: ptA.y + ptB.y
@@ -1953,131 +2438,762 @@ function sum(a1, ab2, ab3, ab4, ab5, ab6) {
1953
2438
  return Object.freeze(pt);
1954
2439
  }
1955
2440
  //#endregion
1956
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/multiply-DfdMPARS.js
2441
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/multiply-CwzF4Hcr.js
1957
2442
  /**
1958
2443
  * Returns the distance between two circle centers.
1959
2444
  *
1960
2445
  * ```js
1961
- * const circleA = { radius: 5, x: 5, y: 5 }
1962
- * const circleB = { radius: 10, x: 20, y: 20 }
1963
- * const distance = Circles.distanceCenter(circleA, circleB);
2446
+ * const circleA = { radius: 5, x: 5, y: 5 }
2447
+ * const circleB = { radius: 10, x: 20, y: 20 }
2448
+ * const distance = Circles.distanceCenter(circleA, circleB);
2449
+ * ```
2450
+ * Throws an error if either is lacking position.
2451
+ * @param a
2452
+ * @param b
2453
+ * @returns Distance
2454
+ */
2455
+ const distanceCenter = (a, b) => {
2456
+ guardPositioned(a, `a`);
2457
+ if (isCirclePositioned(b)) guardPositioned(b, `b`);
2458
+ return distance(a, b);
2459
+ };
2460
+ /**
2461
+ * Returns the distance between the exterior of two circles, or between the exterior of a circle and point.
2462
+ * If `b` overlaps or is enclosed by `a`, distance is 0.
2463
+ *
2464
+ * ```js
2465
+ * const circleA = { radius: 5, x: 5, y: 5 }
2466
+ * const circleB = { radius: 10, x: 20, y: 20 }
2467
+ * const distance = Circles.distanceCenter(circleA, circleB);
2468
+ * ```
2469
+ * @param a
2470
+ * @param b
2471
+ */
2472
+ const distanceFromExterior$1 = (a, b) => {
2473
+ guardPositioned(a, `a`);
2474
+ if (isCirclePositioned(b)) return Math.max(0, distanceCenter(a, b) - a.radius - b.radius);
2475
+ else if (isPoint(b)) {
2476
+ const distribution = distance(a, b);
2477
+ if (distribution < a.radius) return 0;
2478
+ return distribution;
2479
+ } else throw new Error(`Second parameter invalid type`);
2480
+ };
2481
+ /**
2482
+ * Returns a Point with the x,y,z values of two points multiply (a/b).
2483
+ *
2484
+ * `z` parameter is used, if present. Uses a default value of 0 for 'z' when multiplying a 2D point with a 3D one.
2485
+ *
2486
+ * Examples:
2487
+ *
2488
+ * ```js
2489
+ * multiply(ptA, ptB);
2490
+ * multiply(x1, y1, x2, y2);
2491
+ * multiply(ptA, x2, y2);
2492
+ * ```
2493
+ */
2494
+ function multiply(a1, ab2, ab3, ab4, ab5, ab6) {
2495
+ const [ptA, ptB] = getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6);
2496
+ guard$2(ptA, `a`);
2497
+ guard$2(ptB, `b`);
2498
+ const pt = {
2499
+ x: ptA.x * ptB.x,
2500
+ y: ptA.y * ptB.y
2501
+ };
2502
+ if (isPoint3d(ptA) || isPoint3d(ptB)) pt.z = (ptA.z ?? 0) * (ptB.z ?? 0);
2503
+ return Object.freeze(pt);
2504
+ }
2505
+ /**
2506
+ * Multiplies all components by `v`.
2507
+ * Existing properties of `pt` are maintained.
2508
+ *
2509
+ * ```js
2510
+ * multiplyScalar({ x:2, y:4 }, 2);
2511
+ * // Yields: { x:4, y:8 }
2512
+ * ```
2513
+ * @param pt Point
2514
+ * @param v Value to multiply by
2515
+ * @returns
2516
+ */
2517
+ const multiplyScalar = (pt, v) => {
2518
+ return isPoint3d(pt) ? Object.freeze({
2519
+ ...pt,
2520
+ x: pt.x * v,
2521
+ y: pt.y * v,
2522
+ z: pt.z * v
2523
+ }) : Object.freeze({
2524
+ ...pt,
2525
+ x: pt.x * v,
2526
+ y: pt.y * v
2527
+ });
2528
+ };
2529
+ //#endregion
2530
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/is-equal-BS9hk_L_.js
2531
+ /**
2532
+ * Returns _true_ if the points have identical values
2533
+ *
2534
+ * ```js
2535
+ * const a = {x: 10, y: 10};
2536
+ * const b = {x: 10, y: 10;};
2537
+ * a === b // False, because a and be are different objects
2538
+ * isEqual(a, b) // True, because a and b are same value
2539
+ * ```
2540
+ * @param p Points
2541
+ * @returns _True_ if points are equal
2542
+ */
2543
+ const isEqual = (...p) => {
2544
+ if (p === void 0) throw new Error(`parameter 'p' is undefined`);
2545
+ if (p.length < 2) return true;
2546
+ for (let index = 1; index < p.length; index++) {
2547
+ if (p[index].x !== p[0].x) return false;
2548
+ if (p[index].y !== p[0].y) return false;
2549
+ }
2550
+ return true;
2551
+ };
2552
+ //#endregion
2553
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/compare-DzZYeaAF.js
2554
+ /**
2555
+ * Returns -2 if both x & y of a is less than b
2556
+ * Returns -1 if either x/y of a is less than b
2557
+ *
2558
+ * Returns 2 if both x & y of a is greater than b
2559
+ * Returns 1 if either x/y of a is greater than b's x/y
2560
+ *
2561
+ * Returns 0 if x/y of a and b are equal
2562
+ * @param a
2563
+ * @param b
2564
+ */
2565
+ function compare(a, b) {
2566
+ if (a.x < b.x && a.y < b.y) return -2;
2567
+ if (a.x > b.x && a.y > b.y) return 2;
2568
+ if (a.x < b.x || a.y < b.y) return -1;
2569
+ if (a.x > b.x || a.y > b.y) return 1;
2570
+ if (a.x === b.x && a.x === b.y) return 0;
2571
+ return NaN;
2572
+ }
2573
+ /**
2574
+ * Compares points row-wise.
2575
+ *
2576
+ * A point is considered less if has a lower `y` value, or if `y` values are equal, a lower `x` value.
2577
+ *
2578
+ * Returns 0 if points are equal, -1 if a is less than b, 1 if a is greater than b.
2579
+ *
2580
+ * This can be used for sorting points in a row-wise manner, for example:
2581
+ * ```js
2582
+ * arrayOfPoints.sort(Points.compareRowwise);
2583
+ * ```
2584
+ * @param a
2585
+ * @param b
2586
+ */
2587
+ function compareRowwise(a, b) {
2588
+ if (a.y < b.y) return -1;
2589
+ if (a.y > b.y) return 1;
2590
+ if (a.x < b.x) return -1;
2591
+ if (a.x > b.x) return 1;
2592
+ return 0;
2593
+ }
2594
+ /**
2595
+ * Returns a rectangle from two points, where it's uncertain if
2596
+ * a/b ought to be top-left or bottom-right.
2597
+ *
2598
+ * To resolve this, we use Points.compareRowwise to determine which point is top-left and which is bottom-right.
2599
+ * @param a
2600
+ * @param b
2601
+ */
2602
+ function getAsBounds(a, b) {
2603
+ const topLeft = compareRowwise(a, b) <= 0 ? a : b;
2604
+ return {
2605
+ topLeft,
2606
+ bottomRight: topLeft === a ? b : a
2607
+ };
2608
+ }
2609
+ /**
2610
+ * Compares points based on x value. Y value is ignored.
2611
+ *
2612
+ * Return values:
2613
+ * 0: If a.x === b.x
2614
+ * 1: a is to the right of b (ie. a.x > b.x)
2615
+ * -1: a is to the left of b (ie. a.x < b.x)
2616
+ *
2617
+ * @example Sorting by x
2618
+ * ```js
2619
+ * arrayOfPoints.sort(Points.compareByX);
2620
+ * ```
2621
+ *
2622
+ * @param a
2623
+ * @param b
2624
+ * @returns
2625
+ */
2626
+ function compareByX(a, b) {
2627
+ if (a.x === b.x) return 0;
2628
+ if (a.x < b.x) return -1;
2629
+ return 1;
2630
+ }
2631
+ /**
2632
+ * Compares points based on Y value. X value is ignored.
2633
+ *
2634
+ * Return values:
2635
+ * 0: If a.y === b.y
2636
+ * 1: A is below B (ie. a.y > b.y)
2637
+ * -1: A is above B (ie. a.y < b.y)
2638
+ *
2639
+ * @example Sorting by Y
2640
+ * ```js
2641
+ * arrayOfPoints.sort(Points.compareByY);
2642
+ * ```
2643
+ * @param a
2644
+ * @param b
2645
+ * @returns
2646
+ */
2647
+ function compareByY(a, b) {
2648
+ if (a.y === b.y) return 0;
2649
+ if (a.y < b.y) return -1;
2650
+ return 1;
2651
+ }
2652
+ /**
2653
+ * Compares points based on Z value. XY values are ignored.
2654
+ *
2655
+ * Return values:
2656
+ * 0: If a.z === b.z
2657
+ * 1: A is below B (ie. a.z > b.z)
2658
+ * -1: A is above B (ie. a.z < b.z)
2659
+ *
2660
+ * @example Sorting by Y
2661
+ * ```js
2662
+ * arrayOfPoints.sort(Points.compareByZ);
2663
+ * ```
2664
+ * @param a
2665
+ * @param b
2666
+ * @returns
2667
+ */
2668
+ function compareByZ(a, b) {
2669
+ if (a.z === b.z) return 0;
2670
+ if (a.z < b.z) return -1;
2671
+ return 1;
2672
+ }
2673
+ //#endregion
2674
+ //#region node_modules/.pnpm/@ixfx+core@0.56.13/node_modules/@ixfx/core/dist/is-equal-BOIjfI3O.js
2675
+ const removeCircularReferences = (value, replaceWith = null, seen = /* @__PURE__ */ new WeakSet(), path = ``) => {
2676
+ if (value === null) return value;
2677
+ if (typeof value !== `object`) throw new TypeError(`Param 'value' must be an object. Got type: ${typeof value}`);
2678
+ seen.add(value);
2679
+ const entries = Object.entries(value);
2680
+ for (const entry of entries) {
2681
+ if (entry[1] === null) continue;
2682
+ if (typeof entry[1] !== `object`) continue;
2683
+ if (seen.has(entry[1])) {
2684
+ entry[1] = replaceWith;
2685
+ continue;
2686
+ }
2687
+ entry[1] = removeCircularReferences(entry[1], replaceWith, seen, `${entry[0]}.`);
2688
+ }
2689
+ return Object.fromEntries(entries);
2690
+ };
2691
+ /**
2692
+ * A default converter to string that uses JSON.stringify if its an object, or the thing itself if it's a string
2693
+ */
2694
+ function toStringDefault(itemToMakeStringFor) {
2695
+ return typeof itemToMakeStringFor === `string` ? itemToMakeStringFor : JSON.stringify(itemToMakeStringFor);
2696
+ }
2697
+ /**
2698
+ * Converts a value to string form.
2699
+ * For simple objects, .toString() is used, other JSON.stringify is used.
2700
+ * It is meant for creating debugging output or 'hash' versions of objects, and does
2701
+ * not necessarily maintain full fidelity of the input
2702
+ * @param value
2703
+ * @returns
2704
+ */
2705
+ function defaultToString(value) {
2706
+ if (value === null) return `null`;
2707
+ if (typeof value === `boolean` || typeof value === `number`) return value.toString();
2708
+ if (typeof value === `string`) return value;
2709
+ if (typeof value === `symbol`) throw new TypeError(`Symbol cannot be converted to string`);
2710
+ try {
2711
+ return JSON.stringify(value);
2712
+ } catch (error) {
2713
+ if (typeof value === `object`) return JSON.stringify(removeCircularReferences(value, `(circular)`));
2714
+ else throw error;
2715
+ }
2716
+ }
2717
+ /**
2718
+ * If input is a string, it is returned.
2719
+ * Otherwise, it returns the result of JSON.stringify() with fields ordered.
2720
+ *
2721
+ * This allows for more consistent comparisons when object field orders are different but values the same.
2722
+ * @param itemToMakeStringFor
2723
+ */
2724
+ function toStringOrdered(itemToMakeStringFor) {
2725
+ if (typeof itemToMakeStringFor === `string`) return itemToMakeStringFor;
2726
+ const replacer = (key, value) => value instanceof Object && !Array.isArray(value) ? Object.keys(value).sort().reduce((sorted, key) => {
2727
+ sorted[key] = value[key];
2728
+ return sorted;
2729
+ }, {}) : value;
2730
+ return JSON.stringify(itemToMakeStringFor, replacer);
2731
+ }
2732
+ /**
2733
+ * Default comparer function is equiv to checking `a === b`.
2734
+ * Use {@link isEqualValueDefault} to compare by value, via comparing JSON string representation.
2735
+ */
2736
+ const isEqualDefault = (a, b) => a === b;
2737
+ /**
2738
+ * Comparer returns true if string representation of `a` and `b` are equal.
2739
+ * Use {@link isEqualDefault} to compare using === semantics
2740
+ * Uses `toStringDefault` to generate a string representation (via `JSON.stringify`).
2741
+ *
2742
+ * Returns _false_ if the ordering of fields is different, even though values are identical:
2743
+ * ```js
2744
+ * isEqualValueDefault({ a: 10, b: 20}, { b: 20, a: 10 }); // false
2745
+ * ```
2746
+ *
2747
+ * Use {@link isEqualValueIgnoreOrder} to ignore order (with an overhead of additional processing).
2748
+ * ```js
2749
+ * isEqualValueIgnoreOrder({ a: 10, b: 20}, { b: 20, a: 10 }); // true
2750
+ * ```
2751
+ *
2752
+ * Use {@link isEqualValuePartial} to partially match `b` against `a`.
2753
+ * @returns True if the contents of `a` and `b` are equal
2754
+ */
2755
+ function isEqualValueDefault(a, b) {
2756
+ if (a === b) return true;
2757
+ return toStringDefault(a) === toStringDefault(b);
2758
+ }
2759
+ /**
2760
+ * Comparer returns true if string representation of `a` and `b` are equal, regardless of field ordering.
2761
+ * Uses `toStringOrdered` to generate a string representation (via JSON.stringify`).
2762
+ *
2763
+ * ```js
2764
+ * isEqualValueIgnoreOrder({ a: 10, b: 20}, { b: 20, a: 10 }); // true
2765
+ * isEqualValue({ a: 10, b: 20}, { b: 20, a: 10 }); // false, fields are different order
2766
+ * ```
2767
+ *
2768
+ * There is an overhead to ordering fields. Use {@link isEqualValueDefault} if it's not possible that field ordering will change.
2769
+ * @returns True if the contents of `a` and `b` are equal
2770
+ * @typeParam T - Type of objects being compared
2771
+ */
2772
+ function isEqualValueIgnoreOrder(a, b) {
2773
+ if (a === b) return true;
2774
+ return toStringOrdered(a) === toStringOrdered(b);
2775
+ }
2776
+ //#endregion
2777
+ //#region node_modules/.pnpm/@ixfx+core@0.56.13/node_modules/@ixfx/core/dist/maps-D25APhug.js
2778
+ /**
2779
+ * Sort numbers in ascending order.
2780
+ *
2781
+ * ```js
2782
+ * [10, 4, 5, 0].sort(numericComparer);
2783
+ * // Yields: [0, 4, 5, 10]
2784
+ * [10, 4, 5, 0].sort(comparerInverse(numericComparer));
2785
+ * // Yields: [ 10, 5, 4, 0]
2786
+ * ```
2787
+ *
2788
+ * Returns:
2789
+ * 0: values are equal
2790
+ * negative: `a` should be before `b`
2791
+ * positive: `a` should come after `b`
2792
+ * @param a
2793
+ * @param b
2794
+ * @returns
2795
+ */
2796
+ function numericComparer(a, b) {
2797
+ if (a === b) return 0;
2798
+ if (a > b) return 1;
2799
+ return -1;
2800
+ }
2801
+ /**
2802
+ * Default sort comparer, following same sematics as Array.sort.
2803
+ * Consider using {@link defaultComparer} to get more logical sorting of numbers.
2804
+ *
2805
+ * Note: numbers are sorted in alphabetical order, eg:
2806
+ * ```js
2807
+ * [ 10, 20, 5, 100 ].sort(jsComparer); // same as .sort()
2808
+ * // Yields: [10, 100, 20, 5]
2809
+ * ```
2810
+ *
2811
+ * Returns -1 if x is less than y
2812
+ * Returns 1 if x is greater than y
2813
+ * Returns 0 if x is the same as y
2814
+ * @param x
2815
+ * @param y
2816
+ * @returns
2817
+ */
2818
+ function jsComparer(x, y) {
2819
+ if (x === void 0 && y === void 0) return 0;
2820
+ if (x === void 0) return 1;
2821
+ if (y === void 0) return -1;
2822
+ const xString = defaultToString(x);
2823
+ const yString = defaultToString(y);
2824
+ if (xString < yString) return -1;
2825
+ if (xString > yString) return 1;
2826
+ return 0;
2827
+ }
2828
+ /**
2829
+ * Compares numbers by numeric value, otherwise uses the default
2830
+ * logic of string comparison.
2831
+ *
2832
+ * Is an ascending sort:
2833
+ * b, a, c -> a, b, c
2834
+ * 10, 5, 100 -> 5, 10, 100
2835
+ *
2836
+ * Returns -1 if x is less than y
2837
+ * Returns 1 if x is greater than y
2838
+ * Returns 0 if x is the same as y
2839
+ * @param x
2840
+ * @param y
2841
+ * @see {@link comparerInverse} Inverted order
2842
+ * @returns
2843
+ */
2844
+ function defaultComparer(x, y) {
2845
+ if (typeof x === `number` && typeof y === `number`) return numericComparer(x, y);
2846
+ return jsComparer(x, y);
2847
+ }
2848
+ /**
2849
+ * @inheritDoc getOrGenerate
2850
+ * @param map
2851
+ * @param fn
2852
+ * @returns
2853
+ */
2854
+ const getOrGenerateSync = (map, fn) => (key, args) => {
2855
+ let value = map.get(key);
2856
+ if (value !== void 0) return value;
2857
+ value = fn(key, args);
2858
+ map.set(key, value);
2859
+ return value;
2860
+ };
2861
+ //#endregion
2862
+ //#region node_modules/.pnpm/@ixfx+collections@0.56.13/node_modules/@ixfx/collections/dist/chunk-ZRW5x4aP.js
2863
+ var __defProp$1 = Object.defineProperty;
2864
+ var __exportAll$1 = (all, no_symbols) => {
2865
+ let target = {};
2866
+ for (var name in all) __defProp$1(target, name, {
2867
+ get: all[name],
2868
+ enumerable: true
2869
+ });
2870
+ if (!no_symbols) __defProp$1(target, Symbol.toStringTag, { value: "Module" });
2871
+ return target;
2872
+ };
2873
+ //#endregion
2874
+ //#region node_modules/.pnpm/@ixfx+core@0.56.13/node_modules/@ixfx/core/dist/text-CovhuGNs.js
2875
+ /**
2876
+ * Given a long string, abbreviates it with ...
2877
+ * ```js
2878
+ * abbreviate(`This is something`, 7); // `This is...`
2879
+ * ```
2880
+ *
2881
+ * If `source` is under `maxLength` the original is returned.
2882
+ * @param source
2883
+ * @param maxLength Maximum length. Defaults to 20
2884
+ * @returns
2885
+ */
2886
+ function abbreviate(source, maxLength = 15) {
2887
+ resultThrow(integerTest(maxLength, `aboveZero`, `maxLength`));
2888
+ if (typeof source !== `string`) throw new Error(`Parameter 'source' is not a string`);
2889
+ if (source.length > maxLength && source.length > 3) {
2890
+ if (maxLength > 15) {
2891
+ const chunk = Math.round((maxLength - 2) / 2);
2892
+ return `${source.slice(0, chunk)}...${source.slice(-chunk)}`;
2893
+ }
2894
+ return `${source.slice(0, maxLength)}...`;
2895
+ }
2896
+ return source;
2897
+ }
2898
+ /**
2899
+ * Uses JSON.toString() on `source`, but abbreviates result.
2900
+ * @param source Object to stringify
2901
+ * @param maxLength Default 20
2902
+ * @returns
2903
+ */
2904
+ function toStringAbbreviate(source, maxLength = 20) {
2905
+ if (source === void 0) return `(undefined)`;
2906
+ if (source === null) return `(null)`;
2907
+ return abbreviate(JSON.stringify(source), maxLength);
2908
+ }
2909
+ //#endregion
2910
+ //#region node_modules/.pnpm/@ixfx+core@0.56.13/node_modules/@ixfx/core/dist/src-C6LGm3yY.js
2911
+ /**
2912
+ * Returns _true_ if `value` is number, string, bigint or boolean.
2913
+ * Returns _false_ if `value` is an object, null, undefined
2914
+ *
2915
+ * Use {@link isPrimitiveOrObject} to also return true if `value` is an object.
2916
+ * @param value Value to check
2917
+ * @returns _True_ if value is number, string, bigint or boolean.
2918
+ */
2919
+ function isPrimitive(value) {
2920
+ if (typeof value === `number`) return true;
2921
+ if (typeof value === `string`) return true;
2922
+ if (typeof value === `bigint`) return true;
2923
+ if (typeof value === `boolean`) return true;
2924
+ return false;
2925
+ }
2926
+ /**
2927
+ * Returns a {@link Continuously} that continually executes `callback` at `interval` rate.
2928
+ *
2929
+ * By default, first the sleep period happens and then the callback happens.
2930
+ *
2931
+ * Call `start` to begin/reset loop. The looping stops when `cancel` is called, or when `callback` returns _false_.
2932
+ *
2933
+ * @example
2934
+ * Animation loop
2935
+ * ```js
2936
+ * const draw = () => {
2937
+ * // Draw on canvas
2938
+ * }
2939
+ *
2940
+ * // Run draw() synchronised with monitor refresh rate via `window.requestAnimationFrame`
2941
+ * continuously(draw).start();
2942
+ * ```
2943
+ *
2944
+ * @example
2945
+ * With delay
2946
+ * ```js
2947
+ * const fn = () => {
2948
+ * // Runs after one minute
2949
+ * }
2950
+ * const c = continuously(fn, { mins: 1 } );
2951
+ * c.start(); // Runs `fn` every minute
2952
+ * ```
2953
+ *
2954
+ * @example
2955
+ * Control a 'continuously'
2956
+ * ```js
2957
+ * c.cancel(); // Stop the loop, cancelling any up-coming calls to `fn`
2958
+ * c.elapsedMs; // How many milliseconds have elapsed since start
2959
+ * c.ticks; // How many iterations of loop since start
2960
+ * c.interval; // Get/set speed of loop. Change kicks-in at next loop.
2961
+ * // Use .start() to reset to new interval immediately
2962
+ * ```
2963
+ *
2964
+ * Asynchronous callback functions are supported too:
2965
+ * ```js
2966
+ * continuously(async () => { ..});
2967
+ * ```
2968
+ *
2969
+ * The `callback` function can receive a few arguments:
2970
+ *
2971
+ * ```js
2972
+ * continuously( (ticks, elapsedMs) => {
2973
+ * // ticks: how many times loop has run
2974
+ * // elapsedMs: how long since last loop
2975
+ * }).start();
1964
2976
  * ```
1965
- * Throws an error if either is lacking position.
1966
- * @param a
1967
- * @param b
1968
- * @returns Distance
1969
- */
1970
- const distanceCenter = (a, b) => {
1971
- guardPositioned(a, `a`);
1972
- if (isCirclePositioned(b)) guardPositioned(b, `b`);
1973
- return distance(a, b);
1974
- };
1975
- /**
1976
- * Returns the distance between the exterior of two circles, or between the exterior of a circle and point.
1977
- * If `b` overlaps or is enclosed by `a`, distance is 0.
2977
+ *
2978
+ * If the callback explicitly returns _false_, the loop will be cancelled.
1978
2979
  *
1979
2980
  * ```js
1980
- * const circleA = { radius: 5, x: 5, y: 5 }
1981
- * const circleB = { radius: 10, x: 20, y: 20 }
1982
- * const distance = Circles.distanceCenter(circleA, circleB);
2981
+ * continuously(ticks => {
2982
+ * // Stop after 100 iterations
2983
+ * if (ticks > 100) return false;
2984
+ * }).start();
1983
2985
  * ```
1984
- * @param a
1985
- * @param b
2986
+ *
2987
+ * You can intercept the logic for calls to `start()` with `onStartCalled`. It can determine
2988
+ * whether the `start()` proceeds, if the loop is cancelled, or the whole thing disposed,
2989
+ * so it can't run any longer.
2990
+ *
2991
+ * ```js
2992
+ * continuously(callback, intervalMs, {
2993
+ * onStartCalled:(ticks, elapsedMs) => {
2994
+ * // Cancel the loop after 1000ms has elapsed
2995
+ * if (elapsedMs > 1000) return `cancel`;
2996
+ * }
2997
+ * }).start();
2998
+ * ```
2999
+ *
3000
+ * To run `callback` *before* the sleep happens, set `fireBeforeWait`:
3001
+ * ```js
3002
+ * continuously(callback, intervalMs, { fireBeforeWait: true });
3003
+ * ```
3004
+ * @param callback - Function to run. If it returns _false_, loop exits.
3005
+ * @param options - {@link ContinuouslyOpts ContinuouslyOpts}
3006
+ * @param interval - Speed of loop (default: 0)
3007
+ * @returns Instance to control looping.
3008
+ * @see Flow.timeout if you want to trigger something once.
1986
3009
  */
1987
- const distanceFromExterior$1 = (a, b) => {
1988
- guardPositioned(a, `a`);
1989
- if (isCirclePositioned(b)) return Math.max(0, distanceCenter(a, b) - a.radius - b.radius);
1990
- else if (isPoint(b)) {
1991
- const distribution = distance(a, b);
1992
- if (distribution < a.radius) return 0;
1993
- return distribution;
1994
- } else throw new Error(`Second parameter invalid type`);
3010
+ const continuously = (callback, interval = 0, options = {}) => {
3011
+ let intervalMs = intervalToMs(interval, 0);
3012
+ resultThrow(integerTest(intervalMs, `positive`, `interval`));
3013
+ const fireBeforeWait = options.fireBeforeWait ?? false;
3014
+ const onStartCalled = options.onStartCalled;
3015
+ const signal = options.signal;
3016
+ let disposed = false;
3017
+ let runState = `idle`;
3018
+ let startCount = 0;
3019
+ let startCountTotal = 0;
3020
+ let startedAt = performance.now();
3021
+ let intervalUsed = interval ?? 0;
3022
+ let cancelled = false;
3023
+ let currentTimer;
3024
+ const deschedule = () => {
3025
+ if (currentTimer === void 0) return;
3026
+ globalThis.clearTimeout(currentTimer);
3027
+ currentTimer = void 0;
3028
+ startCount = 0;
3029
+ startedAt = NaN;
3030
+ };
3031
+ const schedule = (scheduledCallback) => {
3032
+ if (intervalMs === 0) if (typeof requestAnimationFrame === `undefined`) currentTimer = globalThis.setTimeout(scheduledCallback, 0);
3033
+ else {
3034
+ currentTimer = void 0;
3035
+ requestAnimationFrame(scheduledCallback);
3036
+ }
3037
+ else currentTimer = globalThis.setTimeout(scheduledCallback, intervalMs);
3038
+ };
3039
+ const cancel = () => {
3040
+ if (cancelled) return;
3041
+ cancelled = true;
3042
+ if (runState === `idle`) return;
3043
+ runState = `idle`;
3044
+ deschedule();
3045
+ };
3046
+ const loop = async () => {
3047
+ if (signal?.aborted) runState = `idle`;
3048
+ if (runState === `idle`) return;
3049
+ runState = `running`;
3050
+ startCount++;
3051
+ startCountTotal++;
3052
+ const valueOrPromise = callback(startCount, performance.now() - startedAt);
3053
+ const value = typeof valueOrPromise === `object` ? await valueOrPromise : valueOrPromise;
3054
+ if (cancelled) return;
3055
+ runState = `scheduled`;
3056
+ if (value !== void 0 && !value) {
3057
+ cancel();
3058
+ return;
3059
+ }
3060
+ if (cancelled) return;
3061
+ schedule(loop);
3062
+ };
3063
+ const start = () => {
3064
+ if (disposed) throw new Error(`Disposed`);
3065
+ cancelled = false;
3066
+ if (onStartCalled !== void 0) switch (onStartCalled(startCount, performance.now() - startedAt)) {
3067
+ case `cancel`:
3068
+ cancel();
3069
+ return;
3070
+ case `reset`:
3071
+ reset();
3072
+ return;
3073
+ case `dispose`:
3074
+ disposed = true;
3075
+ cancel();
3076
+ return;
3077
+ }
3078
+ if (runState === `idle`) {
3079
+ startCount = 0;
3080
+ startedAt = performance.now();
3081
+ runState = `scheduled`;
3082
+ if (fireBeforeWait) loop();
3083
+ else schedule(loop);
3084
+ }
3085
+ };
3086
+ const reset = () => {
3087
+ if (disposed) throw new Error(`Disposed`);
3088
+ cancelled = false;
3089
+ startCount = 0;
3090
+ startedAt = NaN;
3091
+ if (runState !== `idle`) cancel();
3092
+ start();
3093
+ };
3094
+ return {
3095
+ start,
3096
+ reset,
3097
+ cancel,
3098
+ get interval() {
3099
+ return intervalUsed;
3100
+ },
3101
+ get runState() {
3102
+ return runState;
3103
+ },
3104
+ get startCountTotal() {
3105
+ return startCountTotal;
3106
+ },
3107
+ get startCount() {
3108
+ return startCount;
3109
+ },
3110
+ set interval(interval) {
3111
+ const ms = intervalToMs(interval, 0);
3112
+ resultThrow(integerTest(ms, `positive`, `interval`));
3113
+ intervalMs = ms;
3114
+ intervalUsed = interval;
3115
+ },
3116
+ get isDisposed() {
3117
+ return disposed;
3118
+ },
3119
+ get elapsedMs() {
3120
+ return performance.now() - startedAt;
3121
+ }
3122
+ };
1995
3123
  };
1996
3124
  /**
1997
- * Returns a Point with the x,y,z values of two points multiply (a/b).
3125
+ * Return the millisecond value of an Interval.
1998
3126
  *
1999
- * `z` parameter is used, if present. Uses a default value of 0 for 'z' when multiplying a 2D point with a 3D one.
3127
+ * ```js
3128
+ * intervalToMs(100); // 100
3129
+ * intervalToMs({ millis: 100 }); // 100
3130
+ * ```
2000
3131
  *
2001
- * Examples:
3132
+ * Use `defaultNumber` to return a default in the case of
3133
+ * _undefined_ or invalid input.
2002
3134
  *
2003
3135
  * ```js
2004
- * multiply(ptA, ptB);
2005
- * multiply(x1, y1, x2, y2);
2006
- * multiply(ptA, x2, y2);
3136
+ * intervalToMs(undefined); // throws error
3137
+ * intervalToMs(undefined, 100); // 100
2007
3138
  * ```
3139
+ *
3140
+ * If no default is provided, an exception is thrown.
3141
+ * @param interval Interval
3142
+ * @param defaultNumber Default value if `interval` is _undefined_ or invalid
3143
+ * @returns Milliseconds
2008
3144
  */
2009
- function multiply(a1, ab2, ab3, ab4, ab5, ab6) {
2010
- const [ptA, ptB] = getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6);
2011
- guard$3(ptA, `a`);
2012
- guard$3(ptB, `b`);
2013
- const pt = {
2014
- x: ptA.x * ptB.x,
2015
- y: ptA.y * ptB.y
2016
- };
2017
- if (isPoint3d(ptA) || isPoint3d(ptB)) pt.z = (ptA.z ?? 0) * (ptB.z ?? 0);
2018
- return Object.freeze(pt);
3145
+ function intervalToMs(interval, defaultNumber) {
3146
+ if (isInterval(interval)) {
3147
+ if (typeof interval === `number`) return interval;
3148
+ let ms = interval.millis ?? 0;
3149
+ ms += (interval.hours ?? 0) * 60 * 60 * 1e3;
3150
+ ms += (interval.mins ?? 0) * 60 * 1e3;
3151
+ ms += (interval.secs ?? 0) * 1e3;
3152
+ return ms;
3153
+ } else {
3154
+ if (typeof defaultNumber !== `undefined`) return defaultNumber;
3155
+ throw new Error(`Not a valid interval: ${JSON.stringify(interval)}`);
3156
+ }
2019
3157
  }
2020
3158
  /**
2021
- * Multiplies all components by `v`.
2022
- * Existing properties of `pt` are maintained.
2023
- *
2024
- * ```js
2025
- * multiplyScalar({ x:2, y:4 }, 2);
2026
- * // Yields: { x:4, y:8 }
2027
- * ```
2028
- * @param pt Point
2029
- * @param v Value to multiply by
2030
- * @returns
3159
+ * Returns _true_ if `interval` matches the {@link Interval} type.
3160
+ * @param interval
3161
+ * @returns _True_ if `interval` is an {@link Interval}.
2031
3162
  */
2032
- const multiplyScalar = (pt, v) => {
2033
- return isPoint3d(pt) ? Object.freeze({
2034
- ...pt,
2035
- x: pt.x * v,
2036
- y: pt.y * v,
2037
- z: pt.z * v
2038
- }) : Object.freeze({
2039
- ...pt,
2040
- x: pt.x * v,
2041
- y: pt.y * v
2042
- });
2043
- };
2044
- //#endregion
2045
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/is-equal-BIRq9vnk.js
3163
+ function isInterval(interval) {
3164
+ if (typeof interval === `undefined`) return false;
3165
+ if (interval === null) return false;
3166
+ if (typeof interval === `number`) {
3167
+ if (Number.isNaN(interval)) return false;
3168
+ if (!Number.isFinite(interval)) return false;
3169
+ return true;
3170
+ }
3171
+ if (typeof interval !== `object`) return false;
3172
+ const hasMillis = `millis` in interval;
3173
+ const hasSecs = `secs` in interval;
3174
+ const hasMins = `mins` in interval;
3175
+ const hasHours = `hours` in interval;
3176
+ if (hasMillis && !numberTest(interval.millis).success) return false;
3177
+ if (hasSecs && !numberTest(interval.secs).success) return false;
3178
+ if (hasMins && !numberTest(interval.mins).success) return false;
3179
+ if (hasHours && !numberTest(interval.hours).success) return false;
3180
+ if (hasMillis || hasSecs || hasHours || hasMins) return true;
3181
+ return false;
3182
+ }
2046
3183
  /**
2047
- * Returns _true_ if the points have identical values
3184
+ * Returns a function that resolves `object`.
2048
3185
  *
2049
- * ```js
2050
- * const a = {x: 10, y: 10};
2051
- * const b = {x: 10, y: 10;};
2052
- * a === b // False, because a and be are different objects
2053
- * isEqual(a, b) // True, because a and b are same value
2054
- * ```
2055
- * @param p Points
2056
- * @returns _True_ if points are equal
3186
+ * Use {@link resolveFields} to resolve an object directly.
3187
+ * @param object
3188
+ * @returns
2057
3189
  */
2058
- const isEqual = (...p) => {
2059
- if (p === void 0) throw new Error(`parameter 'p' is undefined`);
2060
- if (p.length < 2) return true;
2061
- for (let index = 1; index < p.length; index++) {
2062
- if (p[index].x !== p[0].x) return false;
2063
- if (p[index].y !== p[0].y) return false;
2064
- }
2065
- return true;
2066
- };
2067
- //#endregion
2068
- //#region node_modules/.pnpm/@ixfx+collections@0.56.12/node_modules/@ixfx/collections/dist/chunk-ZRW5x4aP.js
2069
- var __defProp$1 = Object.defineProperty;
2070
- var __exportAll$1 = (all, no_symbols) => {
2071
- let target = {};
2072
- for (var name in all) __defProp$1(target, name, {
2073
- get: all[name],
2074
- enumerable: true
2075
- });
2076
- if (!no_symbols) __defProp$1(target, Symbol.toStringTag, { value: "Module" });
2077
- return target;
2078
- };
3190
+ if (typeof window === `undefined` || !(`requestAnimationFrame` in window)) {
3191
+ if (typeof window === `undefined`) globalThis.requestAnimationFrame = (callback) => {
3192
+ setTimeout(callback, 1);
3193
+ };
3194
+ }
2079
3195
  //#endregion
2080
- //#region node_modules/.pnpm/@ixfx+events@0.56.12/node_modules/@ixfx/events/dist/index.js
3196
+ //#region node_modules/.pnpm/@ixfx+events@0.56.13/node_modules/@ixfx/events/dist/index.js
2081
3197
  var MapOfSimple = class {
2082
3198
  #store = /* @__PURE__ */ new Map();
2083
3199
  /**
@@ -2194,7 +3310,7 @@ var SimpleEventEmitter = class {
2194
3310
  }
2195
3311
  };
2196
3312
  //#endregion
2197
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/join-points-to-lines-4r_A2U2k.js
3313
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/join-points-to-lines-CEdHRF9i.js
2198
3314
  /**
2199
3315
  * Returns true if point is within or on boundary of `rect`.
2200
3316
  *
@@ -2242,14 +3358,14 @@ function intersectsPoint(rect, a, b) {
2242
3358
  * @param pt Point
2243
3359
  * @returns Distance
2244
3360
  */
2245
- const distanceFromExterior = (rect, pt) => {
3361
+ function distanceFromExterior(rect, pt) {
2246
3362
  guardPositioned$1(rect, `rect`);
2247
- guard$3(pt, `pt`);
3363
+ guard$2(pt, `pt`);
2248
3364
  if (intersectsPoint(rect, pt)) return 0;
2249
3365
  const dx = Math.max(rect.x - pt.x, 0, pt.x - rect.x + rect.width);
2250
3366
  const dy = Math.max(rect.y - pt.y, 0, pt.y - rect.y + rect.height);
2251
3367
  return Math.hypot(dx, dy);
2252
- };
3368
+ }
2253
3369
  /**
2254
3370
  * Returns an array of lines that connects provided points. Note that line is not closed.
2255
3371
  *
@@ -2272,7 +3388,7 @@ const joinPointsToLines = (...points) => {
2272
3388
  return lines;
2273
3389
  };
2274
3390
  //#endregion
2275
- //#region node_modules/.pnpm/@ixfx+collections@0.56.12/node_modules/@ixfx/collections/dist/queue-mutable-lrZyCqgq.js
3391
+ //#region node_modules/.pnpm/@ixfx+collections@0.56.13/node_modules/@ixfx/collections/dist/queue-mutable-lrZyCqgq.js
2276
3392
  const debug = (opts, message) => {
2277
3393
  opts.debug && console.log(`queue:${message}`);
2278
3394
  };
@@ -2475,14 +3591,14 @@ function mutable(options = {}, ...startingItems) {
2475
3591
  return new QueueMutable({ ...options }, [...startingItems]);
2476
3592
  }
2477
3593
  //#endregion
2478
- //#region node_modules/.pnpm/@ixfx+iterables@0.56.12/node_modules/@ixfx/iterables/dist/guard-COHp1bP0.js
3594
+ //#region node_modules/.pnpm/@ixfx+iterables@0.56.13/node_modules/@ixfx/iterables/dist/guard-COHp1bP0.js
2479
3595
  const isAsyncIterable = (v) => {
2480
3596
  if (typeof v !== `object`) return false;
2481
3597
  if (v === null) return false;
2482
3598
  return Symbol.asyncIterator in v;
2483
3599
  };
2484
3600
  //#endregion
2485
- //#region node_modules/.pnpm/@ixfx+iterables@0.56.12/node_modules/@ixfx/iterables/dist/sync-CP_0yIYe.js
3601
+ //#region node_modules/.pnpm/@ixfx+iterables@0.56.13/node_modules/@ixfx/iterables/dist/sync-CP_0yIYe.js
2486
3602
  /**
2487
3603
  * Returns last value from an iterable, or _undefined_
2488
3604
  * if no values are generated
@@ -2522,7 +3638,7 @@ function* min$2(it, gt = (a, b) => a > b) {
2522
3638
  }
2523
3639
  }
2524
3640
  //#endregion
2525
- //#region node_modules/.pnpm/@ixfx+iterables@0.56.12/node_modules/@ixfx/iterables/dist/async.js
3641
+ //#region node_modules/.pnpm/@ixfx+iterables@0.56.13/node_modules/@ixfx/iterables/dist/async.js
2526
3642
  /**
2527
3643
  * Returns last value from an iterable, or _undefined_
2528
3644
  * if no values are generated
@@ -2588,7 +3704,7 @@ async function* min$1(it, gt = (a, b) => a > b) {
2588
3704
  return min;
2589
3705
  }
2590
3706
  //#endregion
2591
- //#region node_modules/.pnpm/@ixfx+iterables@0.56.12/node_modules/@ixfx/iterables/dist/index.js
3707
+ //#region node_modules/.pnpm/@ixfx+iterables@0.56.13/node_modules/@ixfx/iterables/dist/index.js
2592
3708
  /**
2593
3709
  * Returns a stream of minimum values.
2594
3710
  *
@@ -2640,7 +3756,7 @@ function last(it) {
2640
3756
  return isAsyncIterable(it) ? last$1(it) : last$2(it);
2641
3757
  }
2642
3758
  //#endregion
2643
- //#region node_modules/.pnpm/@ixfx+collections@0.56.12/node_modules/@ixfx/collections/dist/priority-mutable-C9pMxKNT.js
3759
+ //#region node_modules/.pnpm/@ixfx+collections@0.56.13/node_modules/@ixfx/collections/dist/priority-mutable-C9pMxKNT.js
2644
3760
  /**
2645
3761
  * Simple priority queue implementation.
2646
3762
  * Higher numbers mean higher priority.
@@ -2732,7 +3848,7 @@ function priority(opts = {}) {
2732
3848
  return new PriorityMutable(opts);
2733
3849
  }
2734
3850
  //#endregion
2735
- //#region node_modules/.pnpm/@ixfx+collections@0.56.12/node_modules/@ixfx/collections/dist/queue-CCn_cD23.js
3851
+ //#region node_modules/.pnpm/@ixfx+collections@0.56.13/node_modules/@ixfx/collections/dist/queue-CCn_cD23.js
2736
3852
  var QueueImmutable = class QueueImmutable {
2737
3853
  opts;
2738
3854
  #data;
@@ -3167,7 +4283,7 @@ const timerWithFunction = (fn, timer) => {
3167
4283
  };
3168
4284
  };
3169
4285
  //#endregion
3170
- //#region node_modules/.pnpm/@ixfx+trackers@0.56.12/node_modules/@ixfx/trackers/dist/index.js
4286
+ //#region node_modules/.pnpm/@ixfx+trackers@0.56.13/node_modules/@ixfx/trackers/dist/index.js
3171
4287
  /**
3172
4288
  * Base tracker class
3173
4289
  */
@@ -3456,7 +4572,7 @@ var TrackedValueMap = class {
3456
4572
  }
3457
4573
  };
3458
4574
  //#endregion
3459
- //#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/line-Betvd7tG.js
4575
+ //#region node_modules/.pnpm/@ixfx+geometry@0.56.13/node_modules/@ixfx/geometry/dist/line-DZj7hi4y.js
3460
4576
  /**
3461
4577
  * Normalises a point so it is on a 0..1 scale
3462
4578
  *
@@ -3512,8 +4628,8 @@ function normaliseByRect$1(a, b, c, d) {
3512
4628
  */
3513
4629
  function divide$2(a1, ab2, ab3, ab4, ab5, ab6) {
3514
4630
  const [ptA, ptB] = getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6);
3515
- guard$3(ptA, `a`);
3516
- guard$3(ptB, `b`);
4631
+ guard$2(ptA, `a`);
4632
+ guard$2(ptB, `b`);
3517
4633
  if (ptB.x === 0) throw new TypeError("Cannot divide by zero (b.x is 0)");
3518
4634
  if (ptB.y === 0) throw new TypeError("Cannot divide by zero (b.y is 0)");
3519
4635
  const pt = {
@@ -3614,7 +4730,7 @@ function abs(pt) {
3614
4730
  * @returns
3615
4731
  */
3616
4732
  function apply$1(pt, fn) {
3617
- guard$3(pt, `pt`);
4733
+ guard$2(pt, `pt`);
3618
4734
  if (isPoint3d(pt)) return Object.freeze({
3619
4735
  ...pt,
3620
4736
  x: fn(pt.x, `x`),
@@ -3632,136 +4748,52 @@ function apply$1(pt, fn) {
3632
4748
  * Undefined values are skipped over. Calculation and return value is 2D.
3633
4749
  *
3634
4750
  * ```js
3635
- * // Find centroid of a list of points
3636
- * const c1 = centroid(p1, p2, p3, ...);
3637
- *
3638
- * // Find centroid of an array of points
3639
- * const c2 = centroid(...pointsArray);
3640
- * ```
3641
- * @param points
3642
- * @returns A single point
3643
- */
3644
- const centroid = (...points) => {
3645
- if (!Array.isArray(points)) throw new Error(`Expected list of points`);
3646
- const sum = points.reduce((previous, p) => {
3647
- if (p === void 0) return previous;
3648
- if (Array.isArray(p)) throw new TypeError(`'points' list contains an array. Did you mean: centroid(...myPoints)?`);
3649
- if (!isPoint(p)) throw new Error(`'points' contains something which is not a point: ${JSON.stringify(p)}`);
3650
- return {
3651
- x: previous.x + p.x,
3652
- y: previous.y + p.y
3653
- };
3654
- }, {
3655
- x: 0,
3656
- y: 0
3657
- });
3658
- return Object.freeze({
3659
- x: sum.x / points.length,
3660
- y: sum.y / points.length
3661
- });
3662
- };
3663
- /**
3664
- * Clamps a point to be between `min` and `max` (0 & 1 by default)
3665
- * @param pt Point
3666
- * @param min Minimum value (0 by default)
3667
- * @param max Maximum value (1 by default)
3668
- */
3669
- function clamp$1(a, min = 0, max = 1) {
3670
- if (isPoint3d(a)) return Object.freeze({
3671
- x: clamp(a.x, min, max),
3672
- y: clamp(a.y, min, max),
3673
- z: clamp(a.z, min, max)
3674
- });
3675
- else return Object.freeze({
3676
- x: clamp(a.x, min, max),
3677
- y: clamp(a.y, min, max)
3678
- });
3679
- }
3680
- /**
3681
- * Returns -2 if both x & y of a is less than b
3682
- * Returns -1 if either x/y of a is less than b
3683
- *
3684
- * Returns 2 if both x & y of a is greater than b
3685
- * Returns 1 if either x/y of a is greater than b's x/y
3686
- *
3687
- * Returns 0 if x/y of a and b are equal
3688
- * @param a
3689
- * @param b
3690
- * @returns
3691
- */
3692
- const compare = (a, b) => {
3693
- if (a.x < b.x && a.y < b.y) return -2;
3694
- if (a.x > b.x && a.y > b.y) return 2;
3695
- if (a.x < b.x || a.y < b.y) return -1;
3696
- if (a.x > b.x || a.y > b.y) return 1;
3697
- if (a.x === b.x && a.x === b.y) return 0;
3698
- return NaN;
3699
- };
3700
- /**
3701
- * Compares points based on x value. Y value is ignored.
3702
- *
3703
- * Return values:
3704
- * * 0: If a.x === b.x
3705
- * * 1: a is to the right of b (ie. a.x > b.x)
3706
- * * -1: a is to the left of b (ie. a.x < b.x)
3707
- *
3708
- * @example Sorting by x
3709
- * ```js
3710
- * arrayOfPoints.sort(Points.compareByX);
3711
- * ```
3712
- *
3713
- * @param a
3714
- * @param b
3715
- * @returns
3716
- */
3717
- const compareByX = (a, b) => {
3718
- if (a.x === b.x) return 0;
3719
- if (a.x < b.x) return -1;
3720
- return 1;
3721
- };
3722
- /**
3723
- * Compares points based on Y value. X value is ignored.
3724
- *
3725
- * Return values:
3726
- * * 0: If a.y === b.y
3727
- * * 1: A is below B (ie. a.y > b.y)
3728
- * * -1: A is above B (ie. a.y < b.y)
3729
- *
3730
- * @example Sorting by Y
3731
- * ```js
3732
- * arrayOfPoints.sort(Points.compareByY);
3733
- * ```
3734
- * @param a
3735
- * @param b
3736
- * @returns
3737
- */
3738
- const compareByY = (a, b) => {
3739
- if (a.y === b.y) return 0;
3740
- if (a.y < b.y) return -1;
3741
- return 1;
3742
- };
3743
- /**
3744
- * Compares points based on Z value. XY values are ignored.
3745
- *
3746
- * Return values:
3747
- * * 0: If a.z === b.z
3748
- * * 1: A is below B (ie. a.z > b.z)
3749
- * * -1: A is above B (ie. a.z < b.z)
3750
- *
3751
- * @example Sorting by Y
3752
- * ```js
3753
- * arrayOfPoints.sort(Points.compareByZ);
4751
+ * // Find centroid of a list of points
4752
+ * const c1 = centroid(p1, p2, p3, ...);
4753
+ *
4754
+ * // Find centroid of an array of points
4755
+ * const c2 = centroid(...pointsArray);
3754
4756
  * ```
3755
- * @param a
3756
- * @param b
3757
- * @returns
4757
+ * @param points
4758
+ * @returns A single point
3758
4759
  */
3759
- const compareByZ = (a, b) => {
3760
- if (a.z === b.z) return 0;
3761
- if (a.z < b.z) return -1;
3762
- return 1;
4760
+ const centroid = (...points) => {
4761
+ if (!Array.isArray(points)) throw new Error(`Expected list of points`);
4762
+ const sum = points.reduce((previous, p) => {
4763
+ if (p === void 0) return previous;
4764
+ if (Array.isArray(p)) throw new TypeError(`'points' list contains an array. Did you mean: centroid(...myPoints)?`);
4765
+ if (!isPoint(p)) throw new Error(`'points' contains something which is not a point: ${JSON.stringify(p)}`);
4766
+ return {
4767
+ x: previous.x + p.x,
4768
+ y: previous.y + p.y
4769
+ };
4770
+ }, {
4771
+ x: 0,
4772
+ y: 0
4773
+ });
4774
+ return Object.freeze({
4775
+ x: sum.x / points.length,
4776
+ y: sum.y / points.length
4777
+ });
3763
4778
  };
3764
4779
  /**
4780
+ * Clamps a point to be between `min` and `max` (0 & 1 by default)
4781
+ * @param pt Point
4782
+ * @param min Minimum value (0 by default)
4783
+ * @param max Maximum value (1 by default)
4784
+ */
4785
+ function clamp$1(a, min = 0, max = 1) {
4786
+ if (isPoint3d(a)) return Object.freeze({
4787
+ x: clamp(a.x, min, max),
4788
+ y: clamp(a.y, min, max),
4789
+ z: clamp(a.z, min, max)
4790
+ });
4791
+ else return Object.freeze({
4792
+ x: clamp(a.x, min, max),
4793
+ y: clamp(a.y, min, max)
4794
+ });
4795
+ }
4796
+ /**
3765
4797
  * Simple convex hull impementation. Returns a set of points which
3766
4798
  * enclose `pts`.
3767
4799
  *
@@ -3977,20 +5009,41 @@ const fromNumbers = (...coords) => {
3977
5009
  };
3978
5010
  /**
3979
5011
  * Returns a relative point between two points.
3980
- *
5012
+ *
3981
5013
  * ```js
3982
5014
  * interpolate(0.5, { x:0, y:0 }, { x:10, y:10 }); // Halfway { x, y }
3983
5015
  * ```
3984
5016
  *
3985
5017
  * Alias for Lines.interpolate(amount, a, b);
3986
5018
  *
5019
+ * If you find yourself calling `interpolate` repeatedly with the same points, consider using {@link interpolator} to create a function that bakes in the points.
3987
5020
  * @param amount Relative amount, 0-1
3988
5021
  * @param a
3989
5022
  * @param b
3990
5023
  * @param allowOverflow If true, length of line can be exceeded for `amount` of below 0 and above `1`.
3991
- * @returns {@link Point}
5024
+ * @returns {@link Point} Point
5025
+ */
5026
+ function interpolate(amount, a, b, allowOverflow = false) {
5027
+ return interpolate$1(amount, a, b, allowOverflow);
5028
+ }
5029
+ /**
5030
+ * Returns a function that interpolates between two points. If you just want to interpolate between two points, use {@link interpolate}.
5031
+ *
5032
+ * ```js
5033
+ * const i = interpolator({ x:0, y:0 }, { x:10, y:10 });
5034
+ * i(0.5); // Halfway { x, y }
5035
+ * ```
5036
+ *
5037
+ * If you find yourself not needing to reuse the function because you're always calling `interpolator` with different point values all the time, use {@link interpolate} instead.
5038
+ * @param a
5039
+ * @param b
5040
+ * @param allowOverflow
5041
+ * @returns Function to interpolate
3992
5042
  */
3993
- const interpolate = (amount, a, b, allowOverflow = false) => interpolate$1(amount, a, b, allowOverflow);
5043
+ const interpolator = (a, b, allowOverflow = false) => interpolator$2({
5044
+ a,
5045
+ b
5046
+ }, allowOverflow);
3994
5047
  /**
3995
5048
  * Inverts one or more axis of a point
3996
5049
  * ```js
@@ -4148,7 +5201,7 @@ const pi$1 = Math.PI;
4148
5201
  * @param origin Origin to calculate vector from or 0,0 if left empty
4149
5202
  * @returns
4150
5203
  */
4151
- const fromPointPolar = (pt, angleNormalisation = ``, origin = EmptyCartesian) => {
5204
+ function fromPointPolar(pt, angleNormalisation = ``, origin = EmptyCartesian) {
4152
5205
  pt = subtract(pt, origin);
4153
5206
  let direction = Math.atan2(pt.y, pt.x);
4154
5207
  if (angleNormalisation === `unipolar` && direction < 0) direction += piPi;
@@ -4160,22 +5213,24 @@ const fromPointPolar = (pt, angleNormalisation = ``, origin = EmptyCartesian) =>
4160
5213
  distance: distance(pt),
4161
5214
  angleRadian: direction
4162
5215
  });
4163
- };
5216
+ }
4164
5217
  /**
4165
5218
  * Returns a Cartesian-coordinate vector from a line a -> b
4166
5219
  * @param line
4167
5220
  * @returns
4168
5221
  */
4169
- const fromLineCartesian = (line) => subtract(line.b, line.a);
5222
+ function fromLineCartesian(line) {
5223
+ return subtract(line.b, line.a);
5224
+ }
4170
5225
  /**
4171
5226
  * Returns a polar-coordinate vector from a line a -> b
4172
5227
  * @param line
4173
5228
  * @returns
4174
5229
  */
4175
- const fromLinePolar = (line) => {
4176
- guard$2(line, `line`);
5230
+ function fromLinePolar(line) {
5231
+ resultThrow(lineTest(line, `line`));
4177
5232
  return fromPointPolar(subtract(line.b, line.a));
4178
- };
5233
+ }
4179
5234
  /**
4180
5235
  * Tracks the relation between two points.
4181
5236
  *
@@ -4620,8 +5675,8 @@ const project = (origin, distance, angle) => {
4620
5675
  * @returns
4621
5676
  */
4622
5677
  function quantiseEvery$1(pt, snap, middleRoundsUp = true) {
4623
- guard$3(pt, `pt`);
4624
- guard$3(snap, `snap`);
5678
+ guard$2(pt, `pt`);
5679
+ guard$2(snap, `snap`);
4625
5680
  if (isPoint3d(pt)) {
4626
5681
  if (!isPoint3d(snap)) throw new TypeError(`Param 'snap' is missing 'z' field`);
4627
5682
  return Object.freeze({
@@ -4710,13 +5765,13 @@ function rotate$1(pt, amountRadian, origin) {
4710
5765
  x: 0,
4711
5766
  y: 0
4712
5767
  };
4713
- guard$3(origin, `origin`);
5768
+ guard$2(origin, `origin`);
4714
5769
  resultThrow(numberTest(amountRadian, ``, `amountRadian`));
4715
5770
  const arrayInput = Array.isArray(pt);
4716
5771
  if (amountRadian === 0) return pt;
4717
5772
  if (!arrayInput) pt = [pt];
4718
5773
  const ptAr = pt;
4719
- for (const [index, p] of ptAr.entries()) guard$3(p, `pt[${index}]`);
5774
+ for (const [index, p] of ptAr.entries()) guard$2(p, `pt[${index}]`);
4720
5775
  const asCartesisan = ptAr.map((p) => fromCartesian(p, origin)).map((p) => rotate(p, amountRadian)).map((p) => toCartesian$1(p, origin));
4721
5776
  return arrayInput ? asCartesisan : asCartesisan[0];
4722
5777
  }
@@ -4763,15 +5818,15 @@ const round$1 = (ptOrX, yOrDigits, digits) => {
4763
5818
  * @returns
4764
5819
  */
4765
5820
  const withinRange$1 = (a, b, maxRange) => {
4766
- guard$3(a, `a`);
4767
- guard$3(b, `b`);
5821
+ guard$2(a, `a`);
5822
+ guard$2(b, `b`);
4768
5823
  if (typeof maxRange === `number`) {
4769
5824
  resultThrow(numberTest(maxRange, `positive`, `maxRange`));
4770
5825
  maxRange = {
4771
5826
  x: maxRange,
4772
5827
  y: maxRange
4773
5828
  };
4774
- } else guard$3(maxRange, `maxRange`);
5829
+ } else guard$2(maxRange, `maxRange`);
4775
5830
  const x = Math.abs(b.x - a.x);
4776
5831
  const y = Math.abs(b.y - a.y);
4777
5832
  return x <= maxRange.x && y <= maxRange.y;
@@ -4805,9 +5860,9 @@ const wrap$1 = (pt, ptMax, ptMin) => {
4805
5860
  x: 0,
4806
5861
  y: 0
4807
5862
  };
4808
- guard$3(pt, `pt`);
4809
- guard$3(ptMax, `ptMax`);
4810
- guard$3(ptMin, `ptMin`);
5863
+ guard$2(pt, `pt`);
5864
+ guard$2(ptMax, `ptMax`);
5865
+ guard$2(ptMin, `ptMin`);
4811
5866
  return Object.freeze({
4812
5867
  x: wrap(pt.x, ptMin.x, ptMax.x),
4813
5868
  y: wrap(pt.y, ptMin.y, ptMax.y)
@@ -4840,6 +5895,7 @@ var point_exports = /* @__PURE__ */ __exportAll$2({
4840
5895
  compareByX: () => compareByX,
4841
5896
  compareByY: () => compareByY,
4842
5897
  compareByZ: () => compareByZ,
5898
+ compareRowwise: () => compareRowwise,
4843
5899
  convexHull: () => convexHull,
4844
5900
  cross: () => cross,
4845
5901
  crossProductRaw: () => crossProductRaw,
@@ -4854,11 +5910,13 @@ var point_exports = /* @__PURE__ */ __exportAll$2({
4854
5910
  from: () => from,
4855
5911
  fromNumbers: () => fromNumbers,
4856
5912
  fromString: () => fromString,
5913
+ getAsBounds: () => getAsBounds,
4857
5914
  getPointParameter: () => getPointParameter$1,
4858
5915
  getTwoPointParameters: () => getTwoPointParameters,
4859
- guard: () => guard$3,
5916
+ guard: () => guard$2,
4860
5917
  guardNonZeroPoint: () => guardNonZeroPoint,
4861
5918
  interpolate: () => interpolate,
5919
+ interpolator: () => interpolator,
4862
5920
  invert: () => invert,
4863
5921
  isEmpty: () => isEmpty$1,
4864
5922
  isEqual: () => isEqual,
@@ -4874,6 +5932,7 @@ var point_exports = /* @__PURE__ */ __exportAll$2({
4874
5932
  normaliseByRect: () => normaliseByRect$1,
4875
5933
  pipeline: () => pipeline,
4876
5934
  pipelineApply: () => pipelineApply,
5935
+ pointTest: () => pointTest,
4877
5936
  progressBetween: () => progressBetween,
4878
5937
  project: () => project,
4879
5938
  quantiseEvery: () => quantiseEvery$1,
@@ -4887,7 +5946,6 @@ var point_exports = /* @__PURE__ */ __exportAll$2({
4887
5946
  round: () => round$1,
4888
5947
  subtract: () => subtract,
4889
5948
  sum: () => sum,
4890
- test: () => test,
4891
5949
  to2d: () => to2d,
4892
5950
  to3d: () => to3d,
4893
5951
  toArray: () => toArray,
@@ -4917,7 +5975,7 @@ Object.freeze({
4917
5975
  })
4918
5976
  });
4919
5977
  //#endregion
4920
- //#region node_modules/.pnpm/@ixfx+modulation@0.56.12/node_modules/@ixfx/modulation/dist/chunk-pbuEa-1d.js
5978
+ //#region node_modules/.pnpm/@ixfx+modulation@0.56.13/node_modules/@ixfx/modulation/dist/chunk-pbuEa-1d.js
4921
5979
  var __defProp = Object.defineProperty;
4922
5980
  var __exportAll = (all, no_symbols) => {
4923
5981
  let target = {};
@@ -4929,7 +5987,7 @@ var __exportAll = (all, no_symbols) => {
4929
5987
  return target;
4930
5988
  };
4931
5989
  //#endregion
4932
- //#region node_modules/.pnpm/@ixfx+modulation@0.56.12/node_modules/@ixfx/modulation/dist/easing-CUDB77wc.js
5990
+ //#region node_modules/.pnpm/@ixfx+modulation@0.56.13/node_modules/@ixfx/modulation/dist/easing-BCATR3oC.js
4933
5991
  const pow$1 = Math.pow;
4934
5992
  const gaussianA = 1 / Math.sqrt(2 * Math.PI);
4935
5993
  /**
@@ -5026,17 +6084,15 @@ const expoInOut = (x) => x === 0 ? 0 : x === 1 ? 1 : x < .5 ? pow(2, 20 * x - 10
5026
6084
  const circIn = (x) => 1 - sqrt(1 - pow(x, 2));
5027
6085
  const circOut = (x) => sqrt(1 - pow(x - 1, 2));
5028
6086
  const backIn = (x) => {
5029
- const c1 = 1.70158;
5030
- return (c1 + 1) * x * x * x - c1 * x * x;
6087
+ return 2.70158 * x * x * x - 1.70158 * x * x;
5031
6088
  };
5032
6089
  const backOut = (x) => {
5033
- const c1 = 1.70158;
5034
- return 1 + (c1 + 1) * pow(x - 1, 3) + c1 * pow(x - 1, 2);
6090
+ return 1 + 2.70158 * pow(x - 1, 3) + 1.70158 * pow(x - 1, 2);
5035
6091
  };
5036
6092
  const circInOut = (x) => x < .5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2;
5037
6093
  const backInOut = (x) => {
5038
6094
  const c2 = 1.70158 * 1.525;
5039
- return x < .5 ? pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2) / 2 : (pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;
6095
+ return x < .5 ? pow(2 * x, 2) * (3.5949095 * 2 * x - c2) / 2 : (pow(2 * x - 2, 2) * (3.5949095 * (x * 2 - 2) + c2) + 2) / 2;
5040
6096
  };
5041
6097
  const elasticIn = (x) => {
5042
6098
  const c4 = 2 * pi / 3;
@@ -5563,7 +6619,6 @@ function ensureTooltip() {
5563
6619
  padding: 2px 6px;
5564
6620
  font-size: 10px;
5565
6621
  font-family: ui-monospace, monospace;
5566
- white-space: nowrap;
5567
6622
  opacity: 0;
5568
6623
  transition: opacity 0.1s ease;
5569
6624
  `;
@@ -5575,6 +6630,16 @@ function showTooltip(owner, clientX, clientY, text) {
5575
6630
  const el = ensureTooltip();
5576
6631
  _tooltipOwner = owner;
5577
6632
  el.textContent = text;
6633
+ el.style.whiteSpace = `nowrap`;
6634
+ el.style.left = `${clientX + 14}px`;
6635
+ el.style.top = `${clientY + 14}px`;
6636
+ el.style.opacity = `1`;
6637
+ }
6638
+ function showTooltipHTML(owner, clientX, clientY, html) {
6639
+ const el = ensureTooltip();
6640
+ _tooltipOwner = owner;
6641
+ el.innerHTML = html;
6642
+ el.style.whiteSpace = `normal`;
5578
6643
  el.style.left = `${clientX + 14}px`;
5579
6644
  el.style.top = `${clientY + 14}px`;
5580
6645
  el.style.opacity = `1`;
@@ -5601,6 +6666,387 @@ function scaleValue(v, min, max) {
5601
6666
  return range === 0 ? .5 : (v - min) / range;
5602
6667
  }
5603
6668
  //#endregion
6669
+ //#region src/plots/multi-axis.ts
6670
+ const PLOT_PALETTE = [
6671
+ `oklch(60% 0.15 30)`,
6672
+ `oklch(60% 0.15 90)`,
6673
+ `oklch(60% 0.15 150)`,
6674
+ `oklch(60% 0.15 210)`,
6675
+ `oklch(60% 0.15 270)`,
6676
+ `oklch(60% 0.15 330)`,
6677
+ `oklch(60% 0.15 60)`,
6678
+ `oklch(60% 0.15 180)`
6679
+ ];
6680
+ let PlotMultiAxis = class PlotMultiAxis extends LitElement {
6681
+ constructor(..._args) {
6682
+ super(..._args);
6683
+ this.layout = `overlap`;
6684
+ this.gridMinWidth = 200;
6685
+ this.valueFormat = (v) => v ? v.toFixed(2) : ``;
6686
+ this.#instances = /* @__PURE__ */ new Map();
6687
+ this.#seriesOrder = [];
6688
+ this.#seriesSet = /* @__PURE__ */ new Set();
6689
+ this.#pendingStyles = /* @__PURE__ */ new Map();
6690
+ }
6691
+ #instances;
6692
+ #seriesOrder;
6693
+ #seriesSet;
6694
+ #pendingStyles;
6695
+ addData(nameOrData, value) {
6696
+ if (typeof nameOrData === `object` && nameOrData !== null) {
6697
+ const entries = Object.entries(nameOrData);
6698
+ for (const [name, val] of entries) this.#addToSeries(name, val);
6699
+ } else this.#addToSeries(nameOrData, value);
6700
+ this.requestUpdate();
6701
+ }
6702
+ styleSeries(name, styles) {
6703
+ const normalized = {};
6704
+ for (const [key, val] of Object.entries(styles)) normalized[key.startsWith(`--`) ? key : `--${key}`] = val;
6705
+ const el = this.#instances.get(name);
6706
+ if (!el) {
6707
+ this.#pendingStyles.set(name, normalized);
6708
+ return;
6709
+ }
6710
+ for (const [key, val] of Object.entries(normalized)) el.style.setProperty(key, val);
6711
+ }
6712
+ clear() {
6713
+ for (const el of this.#instances.values()) el.clear();
6714
+ }
6715
+ clearSeries(name) {
6716
+ const el = this.#instances.get(name);
6717
+ if (el) el.clear();
6718
+ }
6719
+ get series() {
6720
+ return [...this.#seriesOrder];
6721
+ }
6722
+ #addToSeries(name, value) {
6723
+ const el = this.#ensurePlot(name);
6724
+ if (!this.#seriesSet.has(name)) {
6725
+ this.#seriesSet.add(name);
6726
+ this.#seriesOrder.push(name);
6727
+ }
6728
+ el.add(value);
6729
+ }
6730
+ #ensurePlot(name) {
6731
+ let el = this.#instances.get(name);
6732
+ if (el) return el;
6733
+ el = document.createElement(`ixfx-plot-single-axis`);
6734
+ el.tooltips = false;
6735
+ this.#instances.set(name, el);
6736
+ const colorIndex = this.#instances.size % PLOT_PALETTE.length;
6737
+ el.style.setProperty(`--plot-color`, PLOT_PALETTE[colorIndex]);
6738
+ const pending = this.#pendingStyles.get(name);
6739
+ if (pending) {
6740
+ for (const [key, val] of Object.entries(pending)) el.style.setProperty(key, val);
6741
+ this.#pendingStyles.delete(name);
6742
+ }
6743
+ el.addEventListener(`plot-datapoint-click`, (e) => {
6744
+ const ce = e;
6745
+ this.dispatchEvent(new CustomEvent(`plot-datapoint-click`, {
6746
+ detail: {
6747
+ ...ce.detail,
6748
+ series: name
6749
+ },
6750
+ bubbles: true,
6751
+ composed: true
6752
+ }));
6753
+ });
6754
+ el.addEventListener(`plot-pointer-move`, (e) => {
6755
+ const ce = e;
6756
+ this.#onSubPlotPointerMove(ce.detail.clientX, ce.detail.clientY, ce.detail.index);
6757
+ });
6758
+ el.addEventListener(`plot-pointer-leave`, () => {
6759
+ this.#onSubPlotPointerLeave();
6760
+ });
6761
+ return el;
6762
+ }
6763
+ #onSubPlotPointerMove(clientX, clientY, index) {
6764
+ if (index < 0) {
6765
+ hideTooltip(this);
6766
+ return;
6767
+ }
6768
+ const parts = [];
6769
+ for (const [name, inst] of this.#instances) {
6770
+ const val = inst.getValueAt(index);
6771
+ if (val === void 0) continue;
6772
+ const color = getComputedStyle(inst).getPropertyValue(`--plot-color`).trim();
6773
+ parts.push(`<span style="color:${color}">${this.#escapeHTML(name)}</span> ${this.valueFormat(val)}`);
6774
+ }
6775
+ if (parts.length === 0) {
6776
+ hideTooltip(this);
6777
+ return;
6778
+ }
6779
+ showTooltipHTML(this, clientX, clientY, parts.join(`<br>`));
6780
+ }
6781
+ #onSubPlotPointerLeave() {
6782
+ hideTooltip(this);
6783
+ }
6784
+ #escapeHTML(s) {
6785
+ return s.replace(/&/g, `&amp;`).replace(/</g, `&lt;`).replace(/>/g, `&gt;`).replace(/"/g, `&quot;`);
6786
+ }
6787
+ render() {
6788
+ const gridStyle = this.layout === `grid` ? `--grid-min-width: ${this.gridMinWidth}px` : ``;
6789
+ return html`
6790
+ <div
6791
+ id="container"
6792
+ class="layout layout-${this.layout}"
6793
+ part="container"
6794
+ style=${gridStyle}
6795
+ >
6796
+ ${repeat(this.#seriesOrder, (name) => name, (name) => this.#ensurePlot(name))}
6797
+ </div>
6798
+ `;
6799
+ }
6800
+ static {
6801
+ this.styles = css`
6802
+ :host {
6803
+ display: block;
6804
+ width: 100%;
6805
+ height: 100%;
6806
+ min-height: 40px;
6807
+ --plot-color: var(--accent);
6808
+ }
6809
+
6810
+ #container {
6811
+ width: 100%;
6812
+ height: 100%;
6813
+ }
6814
+
6815
+ #container.layout-overlap {
6816
+ display: grid;
6817
+ }
6818
+ #container.layout-overlap > * {
6819
+ grid-area: 1 / 1;
6820
+ background: transparent;
6821
+ }
6822
+
6823
+ #container.layout-horizontal {
6824
+ display: flex;
6825
+ flex-direction: row;
6826
+ gap: var(--space-s, 4px);
6827
+ }
6828
+ #container.layout-horizontal > * {
6829
+ flex: 1;
6830
+ min-width: 0;
6831
+ }
6832
+
6833
+ #container.layout-vertical {
6834
+ display: flex;
6835
+ flex-direction: column;
6836
+ gap: var(--space-s, 4px);
6837
+ }
6838
+ #container.layout-vertical > * {
6839
+ flex: 1;
6840
+ min-height: 0;
6841
+ }
6842
+
6843
+ #container.layout-grid {
6844
+ display: grid;
6845
+ grid-template-columns: repeat(auto-fill, minmax(var(--grid-min-width, 200px), 1fr));
6846
+ gap: var(--space-s, 4px);
6847
+ }
6848
+ `;
6849
+ }
6850
+ };
6851
+ __decorate([property()], PlotMultiAxis.prototype, "layout", void 0);
6852
+ __decorate([property({
6853
+ attribute: `grid-min-width`,
6854
+ type: Number
6855
+ })], PlotMultiAxis.prototype, "gridMinWidth", void 0);
6856
+ PlotMultiAxis = __decorate([safeCustomElement(`ixfx-plot-multi-axis`)], PlotMultiAxis);
6857
+ //#endregion
6858
+ //#region src/plots/plot-histogram.ts
6859
+ let PlotHistogram = class PlotHistogram extends LitElement {
6860
+ constructor(..._args) {
6861
+ super(..._args);
6862
+ this.orientation = "horizontal";
6863
+ this.resolution = .1;
6864
+ this.capacity = 100;
6865
+ this.title = "";
6866
+ this.paused = false;
6867
+ this._width = 100;
6868
+ this._height = 40;
6869
+ this.#series = new PlotDataSeries({
6870
+ capacityLimit: 100,
6871
+ persistentScaling: true
6872
+ });
6873
+ this.#hasProgrammaticData = false;
6874
+ }
6875
+ #series;
6876
+ #hasProgrammaticData;
6877
+ #parseDeclarativeData(text) {
6878
+ if (!text) return [];
6879
+ return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !isNaN(n));
6880
+ }
6881
+ add(v) {
6882
+ this.#hasProgrammaticData = true;
6883
+ this.#series.add(v);
6884
+ if (this.paused) return;
6885
+ this.requestUpdate();
6886
+ }
6887
+ set(values) {
6888
+ this.#hasProgrammaticData = true;
6889
+ this.#series.set(values);
6890
+ if (this.paused) return;
6891
+ this.requestUpdate();
6892
+ }
6893
+ clear() {
6894
+ this.#series.clear();
6895
+ this.requestUpdate();
6896
+ }
6897
+ firstUpdated(_changed) {
6898
+ this._width = this.clientWidth || 100;
6899
+ this._height = this.clientHeight || 40;
6900
+ new ResizeObserver((entries) => {
6901
+ const e = entries[0];
6902
+ this._width = e.contentRect.width;
6903
+ this._height = e.contentRect.height;
6904
+ }).observe(this);
6905
+ if (!this.#hasProgrammaticData) {
6906
+ const data = this.#parseDeclarativeData(this.textContent ?? "");
6907
+ if (data.length > 0) this.#series.set(data);
6908
+ }
6909
+ }
6910
+ updated(changed) {
6911
+ if (changed.has("capacity")) {
6912
+ const old = [...this.#series.values];
6913
+ this.#series = new PlotDataSeries({
6914
+ capacityLimit: this.capacity,
6915
+ persistentScaling: true
6916
+ });
6917
+ if (old.length > 0) this.#series.set(old);
6918
+ }
6919
+ }
6920
+ #readCssVar(name) {
6921
+ return getComputedStyle(this).getPropertyValue(name).trim();
6922
+ }
6923
+ #getGapPx() {
6924
+ const val = this.#readCssVar("--plot-histogram-gap");
6925
+ if (val === "") return 1;
6926
+ const parsed = parseFloat(val);
6927
+ return isFinite(parsed) ? Math.max(0, parsed) : 1;
6928
+ }
6929
+ #getBarLengthOverride() {
6930
+ const val = this.#readCssVar("--plot-histogram-bar-length");
6931
+ if (val === "" || val === "auto") return null;
6932
+ const parsed = parseFloat(val);
6933
+ return isFinite(parsed) ? Math.max(0, Math.min(1, parsed)) : null;
6934
+ }
6935
+ #emitClick(i, valueMin, valueMax, relativeValue) {
6936
+ this.dispatchEvent(new CustomEvent("plot-bucket-click", {
6937
+ detail: {
6938
+ bucketIndex: i,
6939
+ valueMin,
6940
+ valueMax,
6941
+ relativeValue
6942
+ },
6943
+ bubbles: true,
6944
+ composed: true
6945
+ }));
6946
+ }
6947
+ render() {
6948
+ const { values, range } = this.#series;
6949
+ const w = this._width;
6950
+ const h = this._height;
6951
+ const isHorizontal = this.orientation === "horizontal";
6952
+ const padding = Math.min(4, (isHorizontal ? h : w) * .05);
6953
+ const dataMin = this.min ?? range.min;
6954
+ const dataSpan = (this.max ?? range.max) - dataMin || 1;
6955
+ const bucketCount = Math.max(1, Math.floor(1 / this.resolution));
6956
+ const availableMain = (isHorizontal ? w : h) - padding * 2;
6957
+ const availableCross = (isHorizontal ? h : w) - padding * 2;
6958
+ const bucketSize = availableMain / bucketCount;
6959
+ const gap = this.#getGapPx();
6960
+ const barLengthOverride = this.#getBarLengthOverride();
6961
+ const buckets = new Array(bucketCount).fill(0);
6962
+ for (const v of values) {
6963
+ const normalized = (v - dataMin) / dataSpan;
6964
+ const index = Math.min(bucketCount - 1, Math.max(0, Math.floor(normalized * bucketCount)));
6965
+ buckets[index]++;
6966
+ }
6967
+ const maxCount = Math.max(1, ...buckets);
6968
+ return html`
6969
+ <svg width=${w} height=${h} viewBox="0 0 ${w} ${h}"
6970
+ xmlns="http://www.w3.org/2000/svg">
6971
+ <rect width=${w} height=${h} fill="transparent" />
6972
+ ${buckets.map((count, i) => {
6973
+ const relativeValue = count / maxCount;
6974
+ const barLen = barLengthOverride !== null ? barLengthOverride * availableCross : relativeValue * availableCross;
6975
+ const valueMin = dataMin + i / bucketCount * dataSpan;
6976
+ const valueMax = dataMin + (i + 1) / bucketCount * dataSpan;
6977
+ if (isHorizontal) {
6978
+ const x = padding + i * bucketSize;
6979
+ const bw = i === bucketCount - 1 ? Math.max(0, padding + availableMain - x) : Math.max(0, bucketSize - gap);
6980
+ return svg`
6981
+ <rect class="bar" x=${x} y=${padding + availableCross - barLen} width=${bw} height=${barLen}
6982
+ style="--value: ${relativeValue}"
6983
+ @click=${() => this.#emitClick(i, valueMin, valueMax, relativeValue)} />
6984
+ `;
6985
+ } else {
6986
+ const y = padding + i * bucketSize;
6987
+ return svg`
6988
+ <rect class="bar" x=${padding} y=${y} width=${barLen} height=${i === bucketCount - 1 ? Math.max(0, padding + availableMain - y) : Math.max(0, bucketSize - gap)}
6989
+ style="--value: ${relativeValue}"
6990
+ @click=${() => this.#emitClick(i, valueMin, valueMax, relativeValue)} />
6991
+ `;
6992
+ }
6993
+ })}
6994
+ ${this.title ? svg`<text x=${padding + 2} y=${padding + Math.min(10, h * .6)}
6995
+ class="overlay-text" fill=${"var(--plot-text, var(--surface-2-text, #fff))"}
6996
+ style="opacity: 0.6">${this.title}</text>` : svg``}
6997
+ </svg>
6998
+ `;
6999
+ }
7000
+ static {
7001
+ this.styles = css`
7002
+ :host {
7003
+ display: inline-block;
7004
+ width: 100%;
7005
+ height: 100%;
7006
+ min-width: 20px;
7007
+ min-height: 20px;
7008
+
7009
+ --plot-histogram-fill: currentColor;
7010
+ --plot-histogram-gap: 1px;
7011
+ --plot-histogram-border-radius: 0;
7012
+ --plot-histogram-bar-length: auto;
7013
+ }
7014
+
7015
+ svg {
7016
+ display: block;
7017
+ cursor: crosshair;
7018
+ overflow: visible;
7019
+ }
7020
+
7021
+ rect.bar {
7022
+ fill: var(--plot-histogram-fill, currentColor);
7023
+ rx: var(--plot-histogram-border-radius, 0);
7024
+ opacity: calc(0.15 + var(--value) * 0.85);
7025
+ }
7026
+
7027
+ .overlay-text {
7028
+ font-family: var(--font-mono, ui-monospace, monospace);
7029
+ font-size: 9px;
7030
+ dominant-baseline: hanging;
7031
+ pointer-events: none;
7032
+ }
7033
+ `;
7034
+ }
7035
+ };
7036
+ __decorate([property({ attribute: "orientation" })], PlotHistogram.prototype, "orientation", void 0);
7037
+ __decorate([property({ type: Number })], PlotHistogram.prototype, "resolution", void 0);
7038
+ __decorate([property({ type: Number })], PlotHistogram.prototype, "min", void 0);
7039
+ __decorate([property({ type: Number })], PlotHistogram.prototype, "max", void 0);
7040
+ __decorate([property({ type: Number })], PlotHistogram.prototype, "capacity", void 0);
7041
+ __decorate([property()], PlotHistogram.prototype, "title", void 0);
7042
+ __decorate([property({
7043
+ type: Boolean,
7044
+ reflect: true
7045
+ })], PlotHistogram.prototype, "paused", void 0);
7046
+ __decorate([state()], PlotHistogram.prototype, "_width", void 0);
7047
+ __decorate([state()], PlotHistogram.prototype, "_height", void 0);
7048
+ PlotHistogram = __decorate([safeCustomElement("ixfx-plot-histogram")], PlotHistogram);
7049
+ //#endregion
5604
7050
  //#region src/plots/single-axis.ts
5605
7051
  function buildLinePath(points) {
5606
7052
  if (points.length === 0) return ``;
@@ -5721,11 +7167,25 @@ let PlotSingleAxis = class PlotSingleAxis extends LitElement {
5721
7167
  this.#lastClientX = e.clientX;
5722
7168
  this.#lastClientY = e.clientY;
5723
7169
  this.#updateTooltip(e.clientX, e.clientY);
7170
+ const index = this.#getIndexFromX(e.clientX, this.getBoundingClientRect());
7171
+ this.dispatchEvent(new CustomEvent(`plot-pointer-move`, {
7172
+ detail: {
7173
+ clientX: e.clientX,
7174
+ clientY: e.clientY,
7175
+ index
7176
+ },
7177
+ bubbles: true,
7178
+ composed: true
7179
+ }));
5724
7180
  };
5725
7181
  this.#onPointerLeave = () => {
5726
7182
  this.#lastClientX = null;
5727
7183
  this.#lastClientY = null;
5728
7184
  hideTooltip(this);
7185
+ this.dispatchEvent(new CustomEvent(`plot-pointer-leave`, {
7186
+ bubbles: true,
7187
+ composed: true
7188
+ }));
5729
7189
  };
5730
7190
  this.#onClick = (e) => {
5731
7191
  if (this.clickPauses) this.paused = !this.paused;
@@ -5747,6 +7207,18 @@ let PlotSingleAxis = class PlotSingleAxis extends LitElement {
5747
7207
  if (!text) return [];
5748
7208
  return text.trim().split(/[,\s;]+/).map((t) => Number.parseFloat(t)).filter((n) => !isNaN(n));
5749
7209
  }
7210
+ get values() {
7211
+ return this.#series.values;
7212
+ }
7213
+ get dataCount() {
7214
+ return this.#series.values.length;
7215
+ }
7216
+ getValueAt(index) {
7217
+ return this.#series.values[index];
7218
+ }
7219
+ getIndexFromClientX(clientX) {
7220
+ return this.#getIndexFromX(clientX, this.getBoundingClientRect());
7221
+ }
5750
7222
  #lastClientX;
5751
7223
  #lastClientY;
5752
7224
  add(v) {
@@ -6238,6 +7710,6 @@ __decorate([state()], PlotXyAxis.prototype, "_width", void 0);
6238
7710
  __decorate([state()], PlotXyAxis.prototype, "_height", void 0);
6239
7711
  PlotXyAxis = __decorate([safeCustomElement(`ixfx-plot-xy-axis`)], PlotXyAxis);
6240
7712
  //#endregion
6241
- export { computeColour as a, last$2 as c, applyAgeModification as i, QueueMutable as l, PlotSingleAxis as n, parseColourScaleAttr as o, PlotDataSeries as r, readBaseColour as s, PlotXyAxis as t, __exportAll$1 as u };
7713
+ export { isEqualValueDefault as _, PlotDataSeries as a, parseColourScaleAttr as c, QueueMutable as d, isPrimitive as f, isEqualDefault as g, defaultComparer as h, PlotMultiAxis as i, readBaseColour as l, __exportAll$1 as m, PlotSingleAxis as n, applyAgeModification as o, toStringAbbreviate as p, PlotHistogram as r, computeColour as s, PlotXyAxis as t, last$2 as u, isEqualValueIgnoreOrder as v };
6242
7714
 
6243
- //# sourceMappingURL=xy-axis-DL0tfJDr.js.map
7715
+ //# sourceMappingURL=xy-axis-CK64haaK.js.map