@genome-spy/core 0.66.1 → 0.68.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 (191) hide show
  1. package/dist/bundle/index.es.js +7669 -6115
  2. package/dist/bundle/index.js +114 -133
  3. package/dist/schema.json +534 -132
  4. package/dist/src/data/collector.d.ts +20 -0
  5. package/dist/src/data/collector.d.ts.map +1 -1
  6. package/dist/src/data/collector.js +148 -0
  7. package/dist/src/data/dataFlow.d.ts +6 -0
  8. package/dist/src/data/dataFlow.d.ts.map +1 -1
  9. package/dist/src/data/dataFlow.js +10 -0
  10. package/dist/src/data/flowHandle.d.ts +2 -0
  11. package/dist/src/data/flowHandle.d.ts.map +1 -1
  12. package/dist/src/data/flowHandle.js +1 -0
  13. package/dist/src/data/flowInit.d.ts +12 -4
  14. package/dist/src/data/flowInit.d.ts.map +1 -1
  15. package/dist/src/data/flowInit.js +115 -17
  16. package/dist/src/data/flowNode.d.ts +8 -0
  17. package/dist/src/data/flowNode.d.ts.map +1 -1
  18. package/dist/src/data/flowNode.js +18 -0
  19. package/dist/src/data/keyIndex.d.ts +18 -0
  20. package/dist/src/data/keyIndex.d.ts.map +1 -0
  21. package/dist/src/data/keyIndex.js +241 -0
  22. package/dist/src/data/keyIndex.test.d.ts +2 -0
  23. package/dist/src/data/keyIndex.test.d.ts.map +1 -0
  24. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  25. package/dist/src/data/sources/dataSource.js +5 -1
  26. package/dist/src/data/sources/dataSourceFactory.d.ts +14 -12
  27. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  28. package/dist/src/data/sources/dataSourceFactory.js +52 -16
  29. package/dist/src/data/sources/lazy/mockLazySource.d.ts +29 -0
  30. package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -0
  31. package/dist/src/data/sources/lazy/mockLazySource.js +44 -0
  32. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +22 -1
  33. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  34. package/dist/src/data/sources/lazy/singleAxisLazySource.js +34 -2
  35. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  36. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +15 -0
  37. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  38. package/dist/src/data/sources/lazy/tabixSource.js +15 -5
  39. package/dist/src/data/transforms/stack.d.ts.map +1 -1
  40. package/dist/src/data/transforms/stack.js +1 -0
  41. package/dist/src/encoder/accessor.d.ts +43 -0
  42. package/dist/src/encoder/accessor.d.ts.map +1 -1
  43. package/dist/src/encoder/accessor.js +164 -0
  44. package/dist/src/encoder/encoder.d.ts +11 -2
  45. package/dist/src/encoder/encoder.d.ts.map +1 -1
  46. package/dist/src/encoder/encoder.js +24 -4
  47. package/dist/src/encoder/metadataChannels.d.ts +15 -0
  48. package/dist/src/encoder/metadataChannels.d.ts.map +1 -0
  49. package/dist/src/encoder/metadataChannels.js +65 -0
  50. package/dist/src/encoder/metadataChannels.test.d.ts +2 -0
  51. package/dist/src/encoder/metadataChannels.test.d.ts.map +1 -0
  52. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  53. package/dist/src/genome/scaleLocus.js +14 -1
  54. package/dist/src/genomeSpy/containerUi.d.ts +0 -1
  55. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -1
  56. package/dist/src/genomeSpy/containerUi.js +0 -14
  57. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +3 -7
  58. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -1
  59. package/dist/src/genomeSpy/loadingIndicatorManager.js +68 -20
  60. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts +52 -0
  61. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts.map +1 -0
  62. package/dist/src/genomeSpy/loadingStatusRegistry.js +86 -0
  63. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  64. package/dist/src/genomeSpy/viewContextFactory.js +0 -1
  65. package/dist/src/genomeSpy/viewDataInit.d.ts +10 -0
  66. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  67. package/dist/src/genomeSpy/viewDataInit.js +166 -2
  68. package/dist/src/genomeSpy/viewDataInit.test.d.ts +2 -0
  69. package/dist/src/genomeSpy/viewDataInit.test.d.ts.map +1 -0
  70. package/dist/src/genomeSpy.d.ts +1 -2
  71. package/dist/src/genomeSpy.d.ts.map +1 -1
  72. package/dist/src/genomeSpy.js +69 -27
  73. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  74. package/dist/src/gl/dataToVertices.js +16 -4
  75. package/dist/src/marks/mark.d.ts.map +1 -1
  76. package/dist/src/marks/mark.js +18 -11
  77. package/dist/src/marks/markUtils.js +1 -1
  78. package/dist/src/scale/scale.d.ts +6 -1
  79. package/dist/src/scale/scale.d.ts.map +1 -1
  80. package/dist/src/scale/scale.js +83 -23
  81. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  82. package/dist/src/scales/axisResolution.js +10 -0
  83. package/dist/src/scales/{scaleDomainAggregator.d.ts → domainPlanner.d.ts} +8 -5
  84. package/dist/src/scales/domainPlanner.d.ts.map +1 -0
  85. package/dist/src/scales/domainPlanner.js +285 -0
  86. package/dist/src/scales/domainPlanner.test.d.ts +2 -0
  87. package/dist/src/scales/domainPlanner.test.d.ts.map +1 -0
  88. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  89. package/dist/src/scales/scaleInstanceManager.js +8 -4
  90. package/dist/src/scales/scaleInteractionController.d.ts +6 -0
  91. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  92. package/dist/src/scales/scaleInteractionController.js +41 -3
  93. package/dist/src/scales/scaleResolution.d.ts +19 -16
  94. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  95. package/dist/src/scales/scaleResolution.js +255 -70
  96. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -1
  97. package/dist/src/selection/selection.d.ts +21 -0
  98. package/dist/src/selection/selection.d.ts.map +1 -1
  99. package/dist/src/selection/selection.js +82 -0
  100. package/dist/src/spec/channel.d.ts +52 -15
  101. package/dist/src/spec/data.d.ts +4 -0
  102. package/dist/src/spec/parameter.d.ts +16 -11
  103. package/dist/src/spec/testing.d.ts +12 -0
  104. package/dist/src/spec/testing.d.ts.map +1 -0
  105. package/dist/src/spec/testing.js +20 -0
  106. package/dist/src/spec/view.d.ts +45 -10
  107. package/dist/src/styles/genome-spy.css +3 -31
  108. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  109. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  110. package/dist/src/styles/genome-spy.css.js +0 -29
  111. package/dist/src/types/encoder.d.ts +37 -2
  112. package/dist/src/types/rendering.d.ts +4 -3
  113. package/dist/src/types/viewContext.d.ts +0 -14
  114. package/dist/src/utils/domainArray.d.ts.map +1 -1
  115. package/dist/src/utils/domainArray.js +3 -0
  116. package/dist/src/utils/indexer.d.ts +3 -0
  117. package/dist/src/utils/indexer.d.ts.map +1 -1
  118. package/dist/src/utils/indexer.js +3 -0
  119. package/dist/src/utils/throttle.d.ts +4 -1
  120. package/dist/src/utils/throttle.d.ts.map +1 -1
  121. package/dist/src/utils/throttle.js +54 -23
  122. package/dist/src/utils/throttle.test.d.ts +2 -0
  123. package/dist/src/utils/throttle.test.d.ts.map +1 -0
  124. package/dist/src/utils/transition.d.ts +21 -0
  125. package/dist/src/utils/transition.d.ts.map +1 -1
  126. package/dist/src/utils/transition.js +28 -0
  127. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  128. package/dist/src/utils/ui/tooltip.js +7 -1
  129. package/dist/src/utils/ui/tooltip.test.d.ts +2 -0
  130. package/dist/src/utils/ui/tooltip.test.d.ts.map +1 -0
  131. package/dist/src/view/axisGridView.d.ts.map +1 -1
  132. package/dist/src/view/axisGridView.js +22 -5
  133. package/dist/src/view/axisView.d.ts.map +1 -1
  134. package/dist/src/view/axisView.js +20 -5
  135. package/dist/src/view/concatView.js +3 -3
  136. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  137. package/dist/src/view/containerMutationHelper.js +6 -2
  138. package/dist/src/view/containerView.d.ts +9 -5
  139. package/dist/src/view/containerView.d.ts.map +1 -1
  140. package/dist/src/view/containerView.js +34 -9
  141. package/dist/src/view/dataReadiness.d.ts +46 -0
  142. package/dist/src/view/dataReadiness.d.ts.map +1 -0
  143. package/dist/src/view/dataReadiness.js +267 -0
  144. package/dist/src/view/dataReadiness.test.d.ts +2 -0
  145. package/dist/src/view/dataReadiness.test.d.ts.map +1 -0
  146. package/dist/src/view/facetView.d.ts.map +1 -1
  147. package/dist/src/view/facetView.js +7 -5
  148. package/dist/src/view/flowBuilder.d.ts +5 -3
  149. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  150. package/dist/src/view/flowBuilder.js +74 -7
  151. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  152. package/dist/src/view/gridView/gridChild.js +8 -0
  153. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  154. package/dist/src/view/gridView/gridView.js +119 -2
  155. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  156. package/dist/src/view/gridView/scrollbar.js +3 -0
  157. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  158. package/dist/src/view/gridView/selectionRect.js +20 -5
  159. package/dist/src/view/gridView/separatorView.d.ts +51 -0
  160. package/dist/src/view/gridView/separatorView.d.ts.map +1 -0
  161. package/dist/src/view/gridView/separatorView.js +275 -0
  162. package/dist/src/view/layerView.js +3 -3
  163. package/dist/src/view/layout/flexLayout.d.ts +0 -30
  164. package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
  165. package/dist/src/view/layout/flexLayout.js +0 -86
  166. package/dist/src/view/paramMediator.d.ts +19 -0
  167. package/dist/src/view/paramMediator.d.ts.map +1 -1
  168. package/dist/src/view/paramMediator.js +86 -19
  169. package/dist/src/view/testUtils.d.ts.map +1 -1
  170. package/dist/src/view/testUtils.js +11 -1
  171. package/dist/src/view/unitView.d.ts +8 -13
  172. package/dist/src/view/unitView.d.ts.map +1 -1
  173. package/dist/src/view/unitView.js +127 -43
  174. package/dist/src/view/view.d.ts +34 -14
  175. package/dist/src/view/view.d.ts.map +1 -1
  176. package/dist/src/view/view.js +119 -9
  177. package/dist/src/view/viewFactory.d.ts.map +1 -1
  178. package/dist/src/view/viewFactory.js +20 -1
  179. package/dist/src/view/viewSelectors.d.ts +148 -0
  180. package/dist/src/view/viewSelectors.d.ts.map +1 -0
  181. package/dist/src/view/viewSelectors.js +773 -0
  182. package/dist/src/view/viewSelectors.test.d.ts +2 -0
  183. package/dist/src/view/viewSelectors.test.d.ts.map +1 -0
  184. package/dist/src/view/viewUtils.d.ts +0 -8
  185. package/dist/src/view/viewUtils.d.ts.map +1 -1
  186. package/dist/src/view/viewUtils.js +1 -21
  187. package/package.json +3 -3
  188. package/dist/src/scales/scaleDomainAggregator.d.ts.map +0 -1
  189. package/dist/src/scales/scaleDomainAggregator.js +0 -162
  190. package/dist/src/scales/scaleDomainAggregator.test.d.ts +0 -2
  191. package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +0 -1
@@ -16,6 +16,7 @@ import LayerView from "../layerView.js";
16
16
  import UnitView from "../unitView.js";
17
17
  import { interactionToZoom } from "../zoom.js";
18
18
  import GridChild from "./gridChild.js";
19
+ import SeparatorView, { resolveSeparatorProps } from "./separatorView.js";
19
20
 
20
21
  /**
21
22
  * Modeled after: https://vega.github.io/vega/docs/layout/
@@ -69,6 +70,9 @@ export default class GridView extends ContainerView {
69
70
 
70
71
  #childSerial = 0;
71
72
 
73
+ /** @type {Partial<Record<"horizontal" | "vertical", SeparatorView>>} */
74
+ #separatorViews = {};
75
+
72
76
  /**
73
77
  *
74
78
  * @param {import("../../spec/view.js").AnyConcatSpec} spec
@@ -97,6 +101,20 @@ export default class GridView extends ContainerView {
97
101
  this.#children = [];
98
102
 
99
103
  this.wrappingFacet = false;
104
+
105
+ const separatorProps = resolveSeparatorProps(spec.separator);
106
+ if (separatorProps) {
107
+ for (const direction of getSeparatorDirections(spec)) {
108
+ this.#separatorViews[direction] = new SeparatorView({
109
+ direction,
110
+ props: separatorProps,
111
+ context: this.context,
112
+ layoutParent: this,
113
+ dataParent: this,
114
+ getName: (prefix) => this.getNextAutoName(prefix),
115
+ });
116
+ }
117
+ }
100
118
  }
101
119
 
102
120
  /**
@@ -130,6 +148,7 @@ export default class GridView extends ContainerView {
130
148
  const gridChild = new GridChild(view, this, this.#childSerial);
131
149
  this.#childSerial++;
132
150
  this.#children.splice(index, 0, gridChild);
151
+ this.invalidateSizeCache();
133
152
  return gridChild;
134
153
  }
135
154
 
@@ -162,6 +181,7 @@ export default class GridView extends ContainerView {
162
181
  }
163
182
  this.#disposeGridChild(gridChild);
164
183
  this.#children.splice(index, 1);
184
+ this.invalidateSizeCache();
165
185
  }
166
186
 
167
187
  get #visibleChildren() {
@@ -188,6 +208,7 @@ export default class GridView extends ContainerView {
188
208
  for (const view of views) {
189
209
  this.appendChild(view);
190
210
  }
211
+ this.invalidateSizeCache();
191
212
  }
192
213
 
193
214
  /**
@@ -273,6 +294,10 @@ export default class GridView extends ContainerView {
273
294
  yield* gridChild.getChildren();
274
295
  }
275
296
 
297
+ for (const separatorView of Object.values(this.#separatorViews)) {
298
+ yield separatorView.view;
299
+ }
300
+
276
301
  for (const axisView of Object.values(this.#sharedAxes)) {
277
302
  yield axisView;
278
303
  }
@@ -519,8 +544,10 @@ export default class GridView extends ContainerView {
519
544
 
520
545
  context.pushView(this, coords);
521
546
 
547
+ const devicePixelRatio = context.getDevicePixelRatio();
548
+
522
549
  const flexOpts = {
523
- devicePixelRatio: context.getDevicePixelRatio(),
550
+ devicePixelRatio,
524
551
  };
525
552
  const columnFlexCoords = mapToPixelCoords(
526
553
  this.#makeFlexItems("column"),
@@ -543,6 +570,10 @@ export default class GridView extends ContainerView {
543
570
  const round = (x) =>
544
571
  Math.round(x * devicePixelRatio) / devicePixelRatio;
545
572
 
573
+ // Two-phase render: compute layout once, then render backgrounds/separators
574
+ // before gridlines/axes/marks without recomputing per-child coords.
575
+ const renderItems = [];
576
+
546
577
  for (const [i, gridChild] of this.#visibleChildren.entries()) {
547
578
  const {
548
579
  view,
@@ -619,10 +650,79 @@ export default class GridView extends ContainerView {
619
650
  ? viewportCoords.intersect(options.clipRect)
620
651
  : viewportCoords;
621
652
 
622
- background?.render(context, clippedChildCoords, {
653
+ renderItems.push({
654
+ col,
655
+ row,
656
+ view,
657
+ axes,
658
+ gridLines,
659
+ background,
660
+ backgroundStroke,
661
+ title,
662
+ selectionRect,
663
+ viewportCoords,
664
+ viewCoords,
665
+ clippedChildCoords,
666
+ viewWidth,
667
+ viewHeight,
668
+ scrollable,
669
+ gridChild,
670
+ });
671
+ }
672
+
673
+ for (const item of renderItems) {
674
+ item.background?.render(context, item.clippedChildCoords, {
623
675
  ...options,
624
676
  clipRect: undefined,
625
677
  });
678
+ }
679
+
680
+ const gridOverhang = this.#getGridOverhang();
681
+
682
+ const verticalSeparator = this.#separatorViews.vertical;
683
+ if (verticalSeparator) {
684
+ verticalSeparator.update(
685
+ columnFlexCoords,
686
+ grid.nCols,
687
+ coords,
688
+ (direction, index) => this.#getViewSlot(direction, index),
689
+ this.wrappingFacet,
690
+ gridOverhang
691
+ );
692
+ verticalSeparator.render(context, coords, options);
693
+ }
694
+
695
+ const horizontalSeparator = this.#separatorViews.horizontal;
696
+ if (horizontalSeparator) {
697
+ horizontalSeparator.update(
698
+ rowFlexCoords,
699
+ grid.nRows,
700
+ coords,
701
+ (direction, index) => this.#getViewSlot(direction, index),
702
+ this.wrappingFacet,
703
+ gridOverhang
704
+ );
705
+ horizontalSeparator.render(context, coords, options);
706
+ }
707
+
708
+ for (const item of renderItems) {
709
+ const {
710
+ view,
711
+ axes,
712
+ gridLines,
713
+ backgroundStroke,
714
+ title,
715
+ selectionRect,
716
+ viewportCoords,
717
+ viewCoords,
718
+ clippedChildCoords,
719
+ viewWidth,
720
+ viewHeight,
721
+ scrollable,
722
+ gridChild,
723
+ col,
724
+ row,
725
+ } = item;
626
726
 
627
727
  for (const gridLineView of Object.values(gridLines)) {
628
728
  gridLineView.render(context, viewportCoords, options);
@@ -889,6 +989,23 @@ export function isClippedChildren(view) {
889
989
  return clipped;
890
990
  }
891
991
 
992
+ /**
993
+ * @param {import("../../spec/view.js").AnyConcatSpec} spec
994
+ * @returns {("horizontal" | "vertical")[]}
995
+ */
996
+ function getSeparatorDirections(spec) {
997
+ // vconcat = horizontal separators, hconcat = vertical separators, concat = both
998
+ if ("vconcat" in spec) {
999
+ return ["horizontal"];
1000
+ }
1001
+
1002
+ if ("hconcat" in spec) {
1003
+ return ["vertical"];
1004
+ }
1005
+
1006
+ return ["horizontal", "vertical"];
1007
+ }
1008
+
892
1009
  /**
893
1010
  *
894
1011
  * @param {import("../layout/rectangle.js").default} coords
@@ -1 +1 @@
1
- {"version":3,"file":"scrollbar.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/scrollbar.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH;IAwBI;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,mBAChC,eAAe,YACf;QAAE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,EAwH/D;IAvID;;;;;;OAMG;IACH,uBAAmB;IAiDf;;;;MAAoB;IAiFxB,2BAEC;IAED;;;OAGG;IACH,yBAHW,MAAM,6BACN;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,QAYtD;IAqFD;;;;;;;;;OASG;IACH,gCAHW,SAAS,iBACT,SAAS,QASnB;IAMG;;;;MAWC;;CAER;;;;;8BAlSY,YAAY,GAAG,UAAU;qBANjB,gBAAgB;sBADf,wBAAwB"}
1
+ {"version":3,"file":"scrollbar.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/scrollbar.js"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH;IAwBI;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,mBAChC,eAAe,YACf;QAAE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,EA0H/D;IAzID;;;;;;OAMG;IACH,uBAAmB;IAmDf;;;;MAAoB;IAiFxB,2BAEC;IAED;;;OAGG;IACH,yBAHW,MAAM,6BACN;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,QAYtD;IAqFD;;;;;;;;;OASG;IACH,gCAHW,SAAS,iBACT,SAAS,QASnB;IAMG;;;;MAWC;;CAER;;;;;8BApSY,YAAY,GAAG,UAAU;qBAPjB,gBAAgB;sBADf,wBAAwB"}
@@ -2,6 +2,7 @@ import clamp from "../../utils/clamp.js";
2
2
  import { makeLerpSmoother } from "../../utils/animator.js";
3
3
  import Rectangle from "../layout/rectangle.js";
4
4
  import UnitView from "../unitView.js";
5
+ import { markViewAsNonAddressable } from "../viewSelectors.js";
5
6
 
6
7
  /**
7
8
  * This class represents a scrollbar thumb that can be used within a grid view
@@ -77,6 +78,8 @@ export default class Scrollbar extends UnitView {
77
78
  }
78
79
  );
79
80
 
81
+ markViewAsNonAddressable(this, { skipSubtree: true });
82
+
80
83
  this.config = config;
81
84
  this.#scrollDirection = scrollDirection;
82
85
  this.#onViewportOffsetChange = options.onViewportOffsetChange;
@@ -1 +1 @@
1
- {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAGA;IAYI;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,qBAAqB,EAAE,eAAe,gBAC7C,OAAO,yBAAyB,EAAE,WAAW,EAqJvD;IAnKD;;;OAGG;IAEH,4DAA4D;IAC5D,gBADW,OAAO,qBAAqB,EAAE,eAAe,CACzC;IAEf,yBAAyB;IACzB,oBADW,MAAM,IAAI,CACF;CAmKtB;sBA/KqB,iBAAiB"}
1
+ {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAIA;IAYI;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,qBAAqB,EAAE,eAAe,gBAC7C,OAAO,yBAAyB,EAAE,WAAW,EAmKvD;IAjLD;;;OAGG;IAEH,4DAA4D;IAC5D,gBADW,OAAO,qBAAqB,EAAE,eAAe,CACzC;IAEf,yBAAyB;IACzB,oBADW,MAAM,IAAI,CACF;CAiLtB;sBA9LqB,iBAAiB"}
@@ -1,5 +1,6 @@
1
1
  import { primaryPositionalChannels } from "../../encoder/encoder.js";
2
2
  import LayerView from "../layerView.js";
3
+ import { markViewAsNonAddressable } from "../viewSelectors.js";
3
4
 
4
5
  export default class SelectionRect extends LayerView {
5
6
  /**
@@ -34,6 +35,7 @@ export default class SelectionRect extends LayerView {
34
35
  const layerSpec = {
35
36
  name: "selectionRect",
36
37
  configurableVisibility: false,
38
+ domainInert: true,
37
39
  resolve: {
38
40
  scale: {
39
41
  x: "forced",
@@ -46,12 +48,24 @@ export default class SelectionRect extends LayerView {
46
48
  };
47
49
 
48
50
  if (channels.includes("x")) {
49
- layerSpec.encoding.x = { field: "_x", type: null, title: null };
50
- layerSpec.encoding.x2 = { field: "_x2" };
51
+ layerSpec.encoding.x = {
52
+ field: "_x",
53
+ type: null,
54
+ title: null,
55
+ };
56
+ layerSpec.encoding.x2 = {
57
+ field: "_x2",
58
+ };
51
59
  }
52
60
  if (channels.includes("y")) {
53
- layerSpec.encoding.y = { field: "_y", type: null, title: null };
54
- layerSpec.encoding.y2 = { field: "_y2" };
61
+ layerSpec.encoding.y = {
62
+ field: "_y",
63
+ type: null,
64
+ title: null,
65
+ };
66
+ layerSpec.encoding.y2 = {
67
+ field: "_y2",
68
+ };
55
69
  }
56
70
 
57
71
  layerSpec.layer.push({
@@ -137,10 +151,11 @@ export default class SelectionRect extends LayerView {
137
151
  "selectionRect", // TODO: Serial
138
152
  {
139
153
  blockEncodingInheritance: true,
140
- contributesToScaleDomain: false,
141
154
  }
142
155
  );
143
156
 
157
+ markViewAsNonAddressable(this, { skipSubtree: true });
158
+
144
159
  /** @type {import("../paramMediator.js").ExprRefFunction} */
145
160
  this._selectionExpr = selectionExpr;
146
161
 
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @param {import("../../spec/view.js").SeparatorProps | boolean | undefined} separator
3
+ * @returns {import("../../spec/view.js").SeparatorProps | null}
4
+ */
5
+ export function resolveSeparatorProps(separator: import("../../spec/view.js").SeparatorProps | boolean | undefined): import("../../spec/view.js").SeparatorProps | null;
6
+ /**
7
+ * Draws separator rules for a single direction in a grid layout.
8
+ */
9
+ export default class SeparatorView {
10
+ /**
11
+ * @param {{
12
+ * direction: SeparatorDirection,
13
+ * props: import("../../spec/view.js").SeparatorProps,
14
+ * context: import("../../types/viewContext.js").default,
15
+ * layoutParent: import("../containerView.js").default,
16
+ * dataParent: import("../view.js").default,
17
+ * getName: (prefix: string) => string
18
+ * }} options
19
+ */
20
+ constructor({ direction, props, context, layoutParent, dataParent, getName, }: {
21
+ direction: SeparatorDirection;
22
+ props: import("../../spec/view.js").SeparatorProps;
23
+ context: import("../../types/viewContext.js").default;
24
+ layoutParent: import("../containerView.js").default;
25
+ dataParent: import("../view.js").default;
26
+ getName: (prefix: string) => string;
27
+ });
28
+ /**
29
+ * @returns {UnitView}
30
+ */
31
+ get view(): UnitView;
32
+ /**
33
+ * @param {import("../layout/flexLayout.js").LocSize[]} flexCoords
34
+ * @param {number} count
35
+ * @param {import("../layout/rectangle.js").default} coords
36
+ * @param {(direction: "row" | "column", index: number) => number} getViewSlot
37
+ * @param {boolean} wrappingFacet
38
+ * @param {import("../layout/padding.js").default} overhang
39
+ */
40
+ update(flexCoords: import("../layout/flexLayout.js").LocSize[], count: number, coords: import("../layout/rectangle.js").default, getViewSlot: (direction: "row" | "column", index: number) => number, wrappingFacet: boolean, overhang: import("../layout/padding.js").default): void;
41
+ /**
42
+ * @param {import("../renderingContext/viewRenderingContext.js").default} context
43
+ * @param {import("../layout/rectangle.js").default} coords
44
+ * @param {import("../../types/rendering.js").RenderingOptions} options
45
+ */
46
+ render(context: import("../renderingContext/viewRenderingContext.js").default, coords: import("../layout/rectangle.js").default, options: import("../../types/rendering.js").RenderingOptions): void;
47
+ #private;
48
+ }
49
+ export type SeparatorDirection = "horizontal" | "vertical";
50
+ import UnitView from "../unitView.js";
51
+ //# sourceMappingURL=separatorView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separatorView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/separatorView.js"],"names":[],"mappings":"AA2NA;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,cAAc,GAAG,OAAO,GAAG,SAAS,GAC/D,OAAO,oBAAoB,EAAE,cAAc,GAAG,IAAI,CAiB9D;AA/ND;;GAEG;AACH;IAsBI;;;;;;;;;OASG;IACH,+EATW;QACN,SAAS,EAAE,kBAAkB,CAAC;QAC9B,KAAK,EAAE,OAAO,oBAAoB,EAAE,cAAc,CAAC;QACnD,OAAO,EAAE,OAAO,4BAA4B,EAAE,OAAO,CAAC;QACtD,YAAY,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC;QACpD,UAAU,EAAE,OAAO,YAAY,EAAE,OAAO,CAAC;QACzC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAA;KACpC,EAqBH;IAED;;OAEG;IACH,YAFa,QAAQ,CAIpB;IAED;;;;;;;OAOG;IACH,mBAPW,OAAO,yBAAyB,EAAE,OAAO,EAAE,SAC3C,MAAM,UACN,OAAO,wBAAwB,EAAE,OAAO,eACxC,CAAC,SAAS,EAAE,KAAK,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,iBACtD,OAAO,YACP,OAAO,sBAAsB,EAAE,OAAO,QAKhD;IAED;;;;OAIG;IACH,gBAJW,OAAO,6CAA6C,EAAE,OAAO,UAC7D,OAAO,wBAAwB,EAAE,OAAO,WACxC,OAAO,0BAA0B,EAAE,gBAAgB,QAI7D;;CAuHJ;iCArNY,YAAY,GAAG,UAAU;qBAJjB,gBAAgB"}
@@ -0,0 +1,275 @@
1
+ import UnitView from "../unitView.js";
2
+ import { markViewAsNonAddressable } from "../viewSelectors.js";
3
+
4
+ /**
5
+ * @typedef {"horizontal" | "vertical"} SeparatorDirection
6
+ */
7
+
8
+ const DEFAULT_SEPARATOR_PROPS = Object.freeze({
9
+ size: 1,
10
+ color: "#ccc",
11
+ opacity: 1,
12
+ strokeDash: [4, 4],
13
+ strokeCap: "butt",
14
+ });
15
+
16
+ /**
17
+ * Draws separator rules for a single direction in a grid layout.
18
+ */
19
+ export default class SeparatorView {
20
+ /** @type {SeparatorDirection} */
21
+ #direction;
22
+
23
+ /** @type {boolean} */
24
+ #includePlotMargin;
25
+
26
+ /** @type {UnitView} */
27
+ #view;
28
+
29
+ /** @type {import("../../data/flowNode.js").Datum[]} */
30
+ #data = [];
31
+
32
+ /** @type {number[]} */
33
+ #positions = [];
34
+
35
+ /** @type {{ x: number[]; y: number[] }} */
36
+ #domains = {
37
+ x: [0, 0],
38
+ y: [0, 0],
39
+ };
40
+
41
+ /**
42
+ * @param {{
43
+ * direction: SeparatorDirection,
44
+ * props: import("../../spec/view.js").SeparatorProps,
45
+ * context: import("../../types/viewContext.js").default,
46
+ * layoutParent: import("../containerView.js").default,
47
+ * dataParent: import("../view.js").default,
48
+ * getName: (prefix: string) => string
49
+ * }} options
50
+ */
51
+ constructor({
52
+ direction,
53
+ props,
54
+ context,
55
+ layoutParent,
56
+ dataParent,
57
+ getName,
58
+ }) {
59
+ this.#direction = direction;
60
+ this.#includePlotMargin = props.includePlotMargin ?? true;
61
+ const markProps = { ...props };
62
+ delete markProps.includePlotMargin;
63
+ this.#view = this.#createView(
64
+ markProps,
65
+ context,
66
+ layoutParent,
67
+ dataParent,
68
+ getName
69
+ );
70
+ }
71
+
72
+ /**
73
+ * @returns {UnitView}
74
+ */
75
+ get view() {
76
+ return this.#view;
77
+ }
78
+
79
+ /**
80
+ * @param {import("../layout/flexLayout.js").LocSize[]} flexCoords
81
+ * @param {number} count
82
+ * @param {import("../layout/rectangle.js").default} coords
83
+ * @param {(direction: "row" | "column", index: number) => number} getViewSlot
84
+ * @param {boolean} wrappingFacet
85
+ * @param {import("../layout/padding.js").default} overhang
86
+ */
87
+ update(flexCoords, count, coords, getViewSlot, wrappingFacet, overhang) {
88
+ this.#collectPositions(flexCoords, count, getViewSlot, wrappingFacet);
89
+ this.#updateDirection(coords, overhang);
90
+ }
91
+
92
+ /**
93
+ * @param {import("../renderingContext/viewRenderingContext.js").default} context
94
+ * @param {import("../layout/rectangle.js").default} coords
95
+ * @param {import("../../types/rendering.js").RenderingOptions} options
96
+ */
97
+ render(context, coords, options) {
98
+ this.#view.render(context, coords, options);
99
+ }
100
+
101
+ /**
102
+ * @param {import("../layout/flexLayout.js").LocSize[]} flexCoords
103
+ * @param {number} count
104
+ * @param {(direction: "row" | "column", index: number) => number} getViewSlot
105
+ * @param {boolean} wrappingFacet
106
+ */
107
+ #collectPositions(flexCoords, count, getViewSlot, wrappingFacet) {
108
+ this.#positions.length = 0;
109
+
110
+ if (count < 2) {
111
+ return;
112
+ }
113
+
114
+ const axis = this.#direction === "vertical" ? "column" : "row";
115
+ const spacingOffset = wrappingFacet ? 3 : 2;
116
+
117
+ for (let index = 1; index < count; index++) {
118
+ const viewSlot = getViewSlot(axis, index);
119
+ const spacingSlot = viewSlot - spacingOffset;
120
+ const spacing = flexCoords[spacingSlot];
121
+ const location = spacing ? spacing.location : 0;
122
+ const size = spacing ? spacing.size : 0;
123
+ this.#positions.push(location + size / 2);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * @param {import("../layout/rectangle.js").default} coords
129
+ * @param {import("../layout/padding.js").default} overhang
130
+ */
131
+ #updateDirection(coords, overhang) {
132
+ const xStart = this.#includePlotMargin ? 0 : overhang.left;
133
+ const xEnd = this.#includePlotMargin
134
+ ? coords.width
135
+ : coords.width - overhang.right;
136
+ const yStart = this.#includePlotMargin ? 0 : overhang.bottom;
137
+ const yEnd = this.#includePlotMargin
138
+ ? coords.height
139
+ : coords.height - overhang.top;
140
+
141
+ this.#data.length = this.#positions.length;
142
+
143
+ for (let i = 0; i < this.#positions.length; i++) {
144
+ const pos = this.#positions[i];
145
+ const entry = this.#data[i] ?? {};
146
+
147
+ if (this.#direction === "vertical") {
148
+ entry.x = pos;
149
+ entry.x2 = pos;
150
+ entry.y = yStart;
151
+ entry.y2 = yEnd;
152
+ } else {
153
+ const y = coords.height - pos;
154
+ entry.x = xStart;
155
+ entry.x2 = xEnd;
156
+ entry.y = y;
157
+ entry.y2 = y;
158
+ }
159
+
160
+ this.#data[i] = entry;
161
+ }
162
+
163
+ const dataSource =
164
+ /** @type {import("../../data/sources/inlineSource.js").default} */ (
165
+ this.#view.flowHandle?.dataSource
166
+ );
167
+
168
+ if (!dataSource) {
169
+ return;
170
+ }
171
+
172
+ dataSource.updateDynamicData(this.#data);
173
+
174
+ this.#domains.x[1] = coords.width;
175
+ this.#domains.y[1] = coords.height;
176
+
177
+ const xScale = this.#view.getScaleResolution("x")?.getScale();
178
+ if (xScale) {
179
+ xScale.domain(this.#domains.x);
180
+ }
181
+
182
+ const yScale = this.#view.getScaleResolution("y")?.getScale();
183
+ if (yScale) {
184
+ yScale.domain(this.#domains.y);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * @param {Omit<import("../../spec/view.js").SeparatorProps, "includePlotMargin">} props
190
+ * @param {import("../../types/viewContext.js").default} context
191
+ * @param {import("../containerView.js").default} layoutParent
192
+ * @param {import("../view.js").default} dataParent
193
+ * @param {(prefix: string) => string} getName
194
+ * @returns {UnitView}
195
+ */
196
+ #createView(props, context, layoutParent, dataParent, getName) {
197
+ const spec = createSeparatorSpec(props);
198
+ const name =
199
+ this.#direction === "horizontal"
200
+ ? getName("separatorHorizontal")
201
+ : getName("separatorVertical");
202
+
203
+ const view = new UnitView(
204
+ spec,
205
+ context,
206
+ layoutParent,
207
+ dataParent,
208
+ name,
209
+ {
210
+ blockEncodingInheritance: true,
211
+ }
212
+ );
213
+
214
+ markViewAsNonAddressable(view, { skipSubtree: true });
215
+
216
+ return view;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * @param {import("../../spec/view.js").SeparatorProps | boolean | undefined} separator
222
+ * @returns {import("../../spec/view.js").SeparatorProps | null}
223
+ */
224
+ export function resolveSeparatorProps(separator) {
225
+ if (!separator) {
226
+ return null;
227
+ }
228
+
229
+ const props =
230
+ separator === true
231
+ ? { ...DEFAULT_SEPARATOR_PROPS }
232
+ : { ...DEFAULT_SEPARATOR_PROPS, ...separator };
233
+
234
+ if (props.strokeDash === DEFAULT_SEPARATOR_PROPS.strokeDash) {
235
+ props.strokeDash = DEFAULT_SEPARATOR_PROPS.strokeDash.slice();
236
+ }
237
+
238
+ return props;
239
+ }
240
+
241
+ /**
242
+ * @param {Omit<import("../../spec/view.js").SeparatorProps, "includePlotMargin">} props
243
+ * @returns {import("../../spec/view.js").UnitSpec}
244
+ */
245
+ function createSeparatorSpec(props) {
246
+ return {
247
+ configurableVisibility: false,
248
+ domainInert: true,
249
+ data: { values: [] },
250
+ resolve: {
251
+ scale: { x: "excluded", y: "excluded" },
252
+ axis: { x: "excluded", y: "excluded" },
253
+ },
254
+ mark: {
255
+ ...props,
256
+ type: "rule",
257
+ clip: props.clip ?? false,
258
+ tooltip: null,
259
+ },
260
+ encoding: {
261
+ x: {
262
+ field: "x",
263
+ type: "quantitative",
264
+ scale: { nice: false, zero: false },
265
+ },
266
+ y: {
267
+ field: "y",
268
+ type: "quantitative",
269
+ scale: { nice: false, zero: false },
270
+ },
271
+ x2: { field: "x2" },
272
+ y2: { field: "y2" },
273
+ },
274
+ };
275
+ }
@@ -37,13 +37,13 @@ export default class LayerView extends ContainerView {
37
37
  async initializeChildren() {
38
38
  this.#children = await Promise.all(
39
39
  this.spec.layer.map(
40
- (childSpec, i) =>
40
+ (childSpec) =>
41
41
  /** @type {(Promise<LayerView | import("./unitView.js").default>)} */ (
42
42
  this.context.createOrImportView(
43
43
  childSpec,
44
44
  this,
45
45
  this,
46
- "grid" + i,
46
+ this.getNextAutoName("layer"),
47
47
  (importedSpec) => {
48
48
  if (
49
49
  !isLayerSpec(importedSpec) &&
@@ -123,7 +123,7 @@ export default class LayerView extends ContainerView {
123
123
  view.disposeSubtree();
124
124
  this.#children.splice(index, 1);
125
125
  },
126
- defaultName: (index) => "layer" + index,
126
+ defaultName: () => this.getNextAutoName("layer"),
127
127
  });
128
128
  }
129
129
 
@@ -70,36 +70,6 @@ export function isSizeDef(spec: any): spec is SizeDef;
70
70
  * @returns {SizeDef}
71
71
  */
72
72
  export function parseSizeDef(size: "container" | number | SizeDef | import("../../spec/view.js").Step): SizeDef;
73
- /**
74
- * Interpolates between two LocSizes
75
- *
76
- * @param {LocSize} from
77
- * @param {LocSize} to
78
- * @param {function():number} ratio
79
- * @returns {LocSize}
80
- */
81
- export function interpolateLocSizes(from: LocSize, to: LocSize, ratio: () => number): LocSize;
82
- /**
83
- * Wraps a LocSize and allows scrolling.
84
- *
85
- * @param {LocSize} locSize
86
- * @param {number | function():number} offset
87
- * @returns {LocSize}
88
- */
89
- export function translateLocSize(locSize: LocSize, offset: number | (() => number)): LocSize;
90
- /**
91
- * Wraps a LocSize and allows scaling.
92
- *
93
- * @param {LocSize} locSize
94
- * @param {number | function():number} factor
95
- * @returns {LocSize}
96
- */
97
- export function scaleLocSize(locSize: LocSize, factor: number | (() => number)): LocSize;
98
- /**
99
- * @param {LocSize} locSize
100
- * @param {number} value
101
- */
102
- export function locSizeEncloses(locSize: LocSize, value: number): boolean;
103
73
  export class FlexDimensions {
104
74
  /**
105
75
  *
@@ -1 +1 @@
1
- {"version":3,"file":"flexLayout.d.ts","sourceRoot":"","sources":["../../../../src/view/layout/flexLayout.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wCALW,OAAO,EAAE,iBACT,MAAM,mDACN,WAAW,GACT,OAAO,EAAE,CAqGrB;AAED;;;;;GAKG;AACH,sCAHW,QAAQ,CAAC,OAAO,CAAC,gBACjB,WAAW,UAQrB;AAED;;;GAGG;AACH,sCAHW,QAAQ,CAAC,OAAO,CAAC,GACf,OAAO,CAWnB;AAED;;;GAGG;AACH,oCAFW,OAAO,EAAE,WAInB;AAED;;;GAGG;AACH,sCAFW,OAAO,EAAE;;;EASnB;AA4ED;;;;GAIG;AACH,uCAFW,OAAO,WAIjB;AAWD;;;;GAIG;AACH,gCAHW,GAAC,GACC,IAAI,IAAI,OAAO,CAI3B;AAED;;;;GAIG;AACH,mCAHW,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,oBAAoB,EAAE,IAAI,GAChE,OAAO,CAiBnB;AAID;;;;;;;GAOG;AACH,0CALW,OAAO,MACP,OAAO,SACP,MAAW,MAAM,GACf,OAAO,CA4BnB;AAED;;;;;;GAMG;AACH,0CAJW,OAAO,UACP,MAAM,IAAG,MAAW,MAAM,CAAA,GACxB,OAAO,CAanB;AAED;;;;;;GAMG;AACH,sCAJW,OAAO,UACP,MAAM,IAAG,MAAW,MAAM,CAAA,GACxB,OAAO,CAanB;AAED;;;GAGG;AACH,yCAHW,OAAO,SACP,MAAM,WAIhB;AA/MD;IACI;;;;OAIG;IACH,mBAHW,OAAO,UACP,OAAO,EAQjB;IAJG,gBAAgB;IAChB,wBAAkB;IAClB,gBAAgB;IAChB,yBAAoB;IAGxB;;;;OAIG;IACH,oBAFW,OAAO,cAAc,EAAE,OAAO,kBAIxC;IAED;;;;OAIG;IACH,yBAFW,OAAO,cAAc,EAAE,OAAO,kBAIxC;IAmBD;;;;OAIG;IACH,aAFa,OAAO,CAInB;;CACJ;AAED;;;;GAIG;AACH,2BAFU,OAAO,CAKd;AAEH,iDAGE;;;;;;;;SAlPQ,MAAM;;;;WACN,MAAM;;;;;;cAGN,MAAM;UACN,MAAM;;;;;;;;;;;;;;cAGN,MAAM;;;;;uBACN,MAAM;;;;aAEN,MAAM;;;;cACN,OAAO"}
1
+ {"version":3,"file":"flexLayout.d.ts","sourceRoot":"","sources":["../../../../src/view/layout/flexLayout.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wCALW,OAAO,EAAE,iBACT,MAAM,mDACN,WAAW,GACT,OAAO,EAAE,CAqGrB;AAED;;;;;GAKG;AACH,sCAHW,QAAQ,CAAC,OAAO,CAAC,gBACjB,WAAW,UAQrB;AAED;;;GAGG;AACH,sCAHW,QAAQ,CAAC,OAAO,CAAC,GACf,OAAO,CAWnB;AAED;;;GAGG;AACH,oCAFW,OAAO,EAAE,WAInB;AAED;;;GAGG;AACH,sCAFW,OAAO,EAAE;;;EASnB;AA4ED;;;;GAIG;AACH,uCAFW,OAAO,WAIjB;AAWD;;;;GAIG;AACH,gCAHW,GAAC,GACC,IAAI,IAAI,OAAO,CAI3B;AAED;;;;GAIG;AACH,mCAHW,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,oBAAoB,EAAE,IAAI,GAChE,OAAO,CAiBnB;AAzHD;IACI;;;;OAIG;IACH,mBAHW,OAAO,UACP,OAAO,EAQjB;IAJG,gBAAgB;IAChB,wBAAkB;IAClB,gBAAgB;IAChB,yBAAoB;IAGxB;;;;OAIG;IACH,oBAFW,OAAO,cAAc,EAAE,OAAO,kBAIxC;IAED;;;;OAIG;IACH,yBAFW,OAAO,cAAc,EAAE,OAAO,kBAIxC;IAmBD;;;;OAIG;IACH,aAFa,OAAO,CAInB;;CACJ;AAED;;;;GAIG;AACH,2BAFU,OAAO,CAKd;AAEH,iDAGE;;;;;;;;SAlPQ,MAAM;;;;WACN,MAAM;;;;;;cAGN,MAAM;UACN,MAAM;;;;;;;;;;;;;;cAGN,MAAM;;;;;uBACN,MAAM;;;;aAEN,MAAM;;;;cACN,OAAO"}