@genome-spy/core 0.75.0 → 0.76.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 (74) hide show
  1. package/dist/bundle/{esm-CgfVIRJ-.js → esm-BimDEpBb.js} +1 -1
  2. package/dist/bundle/{esm-DtE8VqAv.js → esm-Bvlm1uVk.js} +1 -1
  3. package/dist/bundle/{esm-sIoQYZ21.js → esm-CngqBe45.js} +17 -17
  4. package/dist/bundle/{esm-DQiq2Zhd.js → esm-D_euN86T.js} +43 -43
  5. package/dist/bundle/index.es.js +3253 -3137
  6. package/dist/bundle/index.js +97 -96
  7. package/dist/schema.json +352 -0
  8. package/dist/src/config/defaults/markDefaults.d.ts.map +1 -1
  9. package/dist/src/config/defaults/markDefaults.js +1 -12
  10. package/dist/src/config/defaults/scaleDefaults.d.ts.map +1 -1
  11. package/dist/src/config/defaults/scaleDefaults.js +1 -0
  12. package/dist/src/config/markConfig.d.ts.map +1 -1
  13. package/dist/src/config/markConfig.js +16 -8
  14. package/dist/src/config/themes.d.ts.map +1 -1
  15. package/dist/src/config/themes.js +15 -2
  16. package/dist/src/data/sources/lazy/registerBuiltInLazySources.js +2 -2
  17. package/dist/src/data/sources/lazy/registerCoreLazySources.d.ts +2 -0
  18. package/dist/src/data/sources/lazy/registerCoreLazySources.d.ts.map +1 -0
  19. package/dist/src/data/sources/lazy/registerCoreLazySources.js +2 -0
  20. package/dist/src/data/sources/lazy/tabixSource.d.ts +7 -0
  21. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  22. package/dist/src/data/sources/lazy/tabixSource.js +18 -0
  23. package/dist/src/data/sources/lazy/tabixTsvSource.d.ts +37 -0
  24. package/dist/src/data/sources/lazy/tabixTsvSource.d.ts.map +1 -0
  25. package/dist/src/data/sources/lazy/tabixTsvSource.js +163 -0
  26. package/dist/src/genomeSpyBase.d.ts.map +1 -1
  27. package/dist/src/genomeSpyBase.js +4 -1
  28. package/dist/src/gl/webGLHelper.d.ts +5 -2
  29. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  30. package/dist/src/gl/webGLHelper.js +20 -3
  31. package/dist/src/marks/__snapshots__/shaderSnapshot.test.js.snap +1082 -0
  32. package/dist/src/marks/link.vertex.glsl.js +1 -1
  33. package/dist/src/minimal.d.ts.map +1 -1
  34. package/dist/src/minimal.js +5 -4
  35. package/dist/src/scale/scale.js +10 -2
  36. package/dist/src/scales/domainPlanner.js +1 -1
  37. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  38. package/dist/src/scales/scaleResolution.js +9 -3
  39. package/dist/src/scales/selectionDomainUtils.d.ts +10 -0
  40. package/dist/src/scales/selectionDomainUtils.d.ts.map +1 -1
  41. package/dist/src/scales/selectionDomainUtils.js +32 -3
  42. package/dist/src/spec/channel.d.ts +30 -0
  43. package/dist/src/spec/data.d.ts +40 -0
  44. package/dist/src/spec/parameter.d.ts +6 -0
  45. package/dist/src/spec/transform.d.ts +6 -0
  46. package/dist/src/view/axisGridView.d.ts.map +1 -1
  47. package/dist/src/view/axisGridView.js +2 -1
  48. package/dist/src/view/axisView.d.ts.map +1 -1
  49. package/dist/src/view/axisView.js +2 -1
  50. package/dist/src/view/facetView.d.ts.map +1 -1
  51. package/dist/src/view/facetView.js +2 -1
  52. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  53. package/dist/src/view/gridView/gridChild.js +9 -1
  54. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  55. package/dist/src/view/gridView/gridView.js +198 -32
  56. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  57. package/dist/src/view/gridView/scrollbar.js +5 -1
  58. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  59. package/dist/src/view/gridView/selectionRect.js +5 -1
  60. package/dist/src/view/gridView/separatorView.d.ts.map +1 -1
  61. package/dist/src/view/gridView/separatorView.js +5 -1
  62. package/dist/src/view/testUtils.d.ts +30 -3
  63. package/dist/src/view/testUtils.d.ts.map +1 -1
  64. package/dist/src/view/testUtils.js +51 -2
  65. package/dist/src/view/viewSelectors.d.ts +38 -10
  66. package/dist/src/view/viewSelectors.d.ts.map +1 -1
  67. package/dist/src/view/viewSelectors.js +67 -2
  68. package/dist/src/view/viewUtilTypes.d.ts +15 -0
  69. package/dist/src/view/viewUtils.d.ts.map +1 -1
  70. package/dist/src/view/viewUtils.js +10 -0
  71. package/package.json +2 -2
  72. package/LICENSE +0 -21
  73. /package/dist/bundle/{esm-BDFRLEuD.js → esm-C49STiCR.js} +0 -0
  74. /package/dist/bundle/{esm-CGX-qz1d.js → esm-CuVa5T98.js} +0 -0
@@ -22,6 +22,7 @@ import GridChild from "./gridChild.js";
22
22
  import KeyboardZoomController from "./keyboardZoomController.js";
23
23
  import SeparatorView, { resolveSeparatorProps } from "./separatorView.js";
24
24
  import { getZoomableResolutions } from "./zoomNavigationUtils.js";
25
+ import { isHConcatSpec, isVConcatSpec } from "../viewSpecGuards.js";
25
26
 
26
27
  // Secondary ordering within a z-index bucket for GridView-owned decorations.
27
28
  // These are not z-indices themselves: actual layering is decided first by the
@@ -995,12 +996,18 @@ export default class GridView extends ContainerView {
995
996
  gridChild.coords.containsPoint(event.point.x, event.point.y)
996
997
  );
997
998
  const pointedView = pointedChild?.view;
999
+ const gapZoomTarget = !pointedChild
1000
+ ? this.#getGapZoomTarget(event.point)
1001
+ : undefined;
998
1002
 
999
1003
  if (event.type === "wheelclaimprobe") {
1000
1004
  // Probe path: claim wheel ownership without executing regular wheel
1001
1005
  // behavior. InteractionController uses this to decide whether native
1002
1006
  // wheel should be preventDefault()'ed before inertia kicks in.
1003
1007
  if (!pointedView) {
1008
+ if (gapZoomTarget) {
1009
+ event.claimWheel();
1010
+ }
1004
1011
  return;
1005
1012
  }
1006
1013
 
@@ -1038,6 +1045,9 @@ export default class GridView extends ContainerView {
1038
1045
  }
1039
1046
 
1040
1047
  if (!pointedView) {
1048
+ if (gapZoomTarget) {
1049
+ this.#propagateGapZoomInteraction(event, gapZoomTarget);
1050
+ }
1041
1051
  return;
1042
1052
  }
1043
1053
 
@@ -1065,50 +1075,147 @@ export default class GridView extends ContainerView {
1065
1075
  }
1066
1076
 
1067
1077
  /**
1068
- *
1069
- * @param {import("../layout/rectangle.js").default} coords Coordinates
1070
- * @param {View} view
1071
- * @param {import("../zoom.js").ZoomEvent} zoomEvent
1072
- * @returns {boolean} `true` when there was at least one zoomable resolution
1078
+ * @param {import("../layout/point.js").default} point
1079
+ * @returns {{ coords: Rectangle, zoomableResolutions: ReturnType<typeof getZoomableResolutionSet> } | undefined}
1073
1080
  */
1074
- #handleZoom(coords, view, zoomEvent) {
1075
- let zoomable = false;
1076
- let changed = false;
1081
+ #getGapZoomTarget(point) {
1082
+ const channel = this.#getGapZoomChannel();
1083
+ if (!channel) {
1084
+ return;
1085
+ }
1077
1086
 
1078
- const p = coords.normalizePoint(zoomEvent.x, zoomEvent.y);
1079
- const tp = coords.normalizePoint(
1080
- zoomEvent.x + zoomEvent.xDelta,
1081
- zoomEvent.y + zoomEvent.yDelta
1082
- );
1083
- const delta = {
1084
- x: tp.x - p.x,
1085
- y: tp.y - p.y,
1087
+ const resolution = this.getScaleResolution(channel);
1088
+ if (!resolution || !resolution.isZoomable()) {
1089
+ return;
1090
+ }
1091
+
1092
+ const coords = this.#getGapZoomCoords(channel);
1093
+ if (!coords) {
1094
+ return;
1095
+ }
1096
+
1097
+ if (!coords.containsPoint(point.x, point.y)) {
1098
+ return;
1099
+ }
1100
+
1101
+ return {
1102
+ coords,
1103
+ zoomableResolutions: getZoomableResolutionSet(channel, resolution),
1086
1104
  };
1105
+ }
1087
1106
 
1088
- for (const [channel, resolutionSet] of Object.entries(
1089
- getZoomableResolutions(view)
1090
- )) {
1091
- if (resolutionSet.size <= 0) {
1092
- continue;
1107
+ /**
1108
+ * @returns {import("../../spec/channel.js").PrimaryPositionalChannel | undefined}
1109
+ */
1110
+ #getGapZoomChannel() {
1111
+ if (isVConcatSpec(this.spec)) {
1112
+ return "x";
1113
+ } else if (isHConcatSpec(this.spec)) {
1114
+ return "y";
1115
+ }
1116
+ }
1117
+
1118
+ /**
1119
+ * @param {import("../../spec/channel.js").PrimaryPositionalChannel} channel
1120
+ * @returns {Rectangle | undefined}
1121
+ */
1122
+ #getGapZoomCoords(channel) {
1123
+ const firstChild = this.#visibleChildren[0];
1124
+ if (!firstChild) {
1125
+ return;
1126
+ }
1127
+
1128
+ const firstViewportCoords = firstChild.coords;
1129
+ const firstExpandedCoords = firstChild.coords.expand(
1130
+ firstChild.getOverhang()
1131
+ );
1132
+
1133
+ let minX = firstViewportCoords.x;
1134
+ let minY = firstExpandedCoords.y;
1135
+ let maxX = firstViewportCoords.x2;
1136
+ let maxY = firstExpandedCoords.y2;
1137
+
1138
+ for (const gridChild of this.#visibleChildren.slice(1)) {
1139
+ const viewportCoords = gridChild.coords;
1140
+ const expandedCoords = gridChild.coords.expand(
1141
+ gridChild.getOverhang()
1142
+ );
1143
+
1144
+ if (channel == "x") {
1145
+ minX = Math.max(minX, viewportCoords.x);
1146
+ maxX = Math.min(maxX, viewportCoords.x2);
1147
+ minY = Math.min(minY, expandedCoords.y);
1148
+ maxY = Math.max(maxY, expandedCoords.y2);
1149
+ } else {
1150
+ minX = Math.min(minX, expandedCoords.x);
1151
+ maxX = Math.max(maxX, expandedCoords.x2);
1152
+ minY = Math.max(minY, viewportCoords.y);
1153
+ maxY = Math.min(maxY, viewportCoords.y2);
1093
1154
  }
1155
+ }
1094
1156
 
1095
- zoomable = true;
1157
+ for (const axisView of Object.values(this.#sharedAxes)) {
1158
+ const axisCoords = axisView.coords;
1159
+ if (!axisCoords) {
1160
+ continue;
1161
+ }
1096
1162
 
1097
- for (const resolution of resolutionSet) {
1098
- const resolutionChanged = resolution.zoom(
1099
- 2 ** zoomEvent.zDelta,
1100
- channel == "y" ? 1 - p[channel] : p[channel],
1101
- channel == "x" ? delta.x : -delta.y
1102
- );
1103
- changed = resolutionChanged || changed;
1163
+ const orient = axisView.axisProps.orient;
1164
+ if (channel == "x" && (orient == "top" || orient == "bottom")) {
1165
+ minY = Math.min(minY, axisCoords.y);
1166
+ maxY = Math.max(maxY, axisCoords.y2);
1167
+ } else if (
1168
+ channel == "y" &&
1169
+ (orient == "left" || orient == "right")
1170
+ ) {
1171
+ minX = Math.min(minX, axisCoords.x);
1172
+ maxX = Math.max(maxX, axisCoords.x2);
1104
1173
  }
1105
1174
  }
1106
1175
 
1107
- if (changed) {
1108
- this.context.animator.requestRender();
1176
+ if (minX >= maxX || minY >= maxY) {
1177
+ return;
1109
1178
  }
1110
1179
 
1111
- return zoomable;
1180
+ return Rectangle.create(minX, minY, maxX - minX, maxY - minY);
1181
+ }
1182
+
1183
+ /**
1184
+ * @param {import("../../utils/interaction.js").default} event
1185
+ * @param {{ coords: Rectangle, zoomableResolutions: ReturnType<typeof getZoomableResolutionSet> }} gapZoomTarget
1186
+ */
1187
+ #propagateGapZoomInteraction(event, gapZoomTarget) {
1188
+ event.target = this;
1189
+
1190
+ interactionToZoom(
1191
+ event,
1192
+ gapZoomTarget.coords,
1193
+ (zoomEvent) =>
1194
+ zoomResolutions(
1195
+ gapZoomTarget.coords,
1196
+ zoomEvent,
1197
+ gapZoomTarget.zoomableResolutions,
1198
+ this.context.animator
1199
+ ),
1200
+ this.context.getCurrentHover(),
1201
+ this.context.animator
1202
+ );
1203
+ }
1204
+
1205
+ /**
1206
+ *
1207
+ * @param {import("../layout/rectangle.js").default} coords Coordinates
1208
+ * @param {View} view
1209
+ * @param {import("../zoom.js").ZoomEvent} zoomEvent
1210
+ * @returns {boolean} `true` when there was at least one zoomable resolution
1211
+ */
1212
+ #handleZoom(coords, view, zoomEvent) {
1213
+ return zoomResolutions(
1214
+ coords,
1215
+ zoomEvent,
1216
+ getZoomableResolutions(view),
1217
+ this.context.animator
1218
+ );
1112
1219
  }
1113
1220
 
1114
1221
  /**
@@ -1121,6 +1228,65 @@ export default class GridView extends ContainerView {
1121
1228
  }
1122
1229
  }
1123
1230
 
1231
+ /**
1232
+ * @param {import("../../spec/channel.js").PrimaryPositionalChannel} channel
1233
+ * @param {import("../../scales/scaleResolution.js").default} resolution
1234
+ */
1235
+ function getZoomableResolutionSet(channel, resolution) {
1236
+ const zoomableResolutions = {
1237
+ x: new Set(),
1238
+ y: new Set(),
1239
+ };
1240
+ zoomableResolutions[channel].add(resolution);
1241
+ return zoomableResolutions;
1242
+ }
1243
+
1244
+ /**
1245
+ * @param {Rectangle} coords
1246
+ * @param {import("../zoom.js").ZoomEvent} zoomEvent
1247
+ * @param {ReturnType<typeof getZoomableResolutions>} zoomableResolutions
1248
+ * @param {import("../../utils/animator.js").default} animator
1249
+ */
1250
+ function zoomResolutions(coords, zoomEvent, zoomableResolutions, animator) {
1251
+ let zoomable = false;
1252
+ let changed = false;
1253
+
1254
+ const p = coords.normalizePoint(zoomEvent.x, zoomEvent.y);
1255
+ const tp = coords.normalizePoint(
1256
+ zoomEvent.x + zoomEvent.xDelta,
1257
+ zoomEvent.y + zoomEvent.yDelta
1258
+ );
1259
+ const delta = {
1260
+ x: tp.x - p.x,
1261
+ y: tp.y - p.y,
1262
+ };
1263
+
1264
+ for (const [channel, resolutionSet] of Object.entries(
1265
+ zoomableResolutions
1266
+ )) {
1267
+ if (resolutionSet.size <= 0) {
1268
+ continue;
1269
+ }
1270
+
1271
+ zoomable = true;
1272
+
1273
+ for (const resolution of resolutionSet) {
1274
+ const resolutionChanged = resolution.zoom(
1275
+ 2 ** zoomEvent.zDelta,
1276
+ channel == "y" ? 1 - p[channel] : p[channel],
1277
+ channel == "x" ? delta.x : -delta.y
1278
+ );
1279
+ changed = resolutionChanged || changed;
1280
+ }
1281
+ }
1282
+
1283
+ if (changed) {
1284
+ animator.requestRender();
1285
+ }
1286
+
1287
+ return zoomable;
1288
+ }
1289
+
1124
1290
  /**
1125
1291
  * @param {View} view
1126
1292
  */
@@ -1 +1 @@
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,EA2H/D;IA1ID;;;;;;OAMG;IACH,uBAAmB;IAkDf;;;;MAAoB;IAmFxB,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;;;;;8BArSY,YAAY,GAAG,UAAU;qBAPjB,gBAAgB;sBADf,wBAAwB"}
1
+ {"version":3,"file":"scrollbar.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/scrollbar.js"],"names":[],"mappings":"AASA;;;;;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,EA4H/D;IA3ID;;;;;;OAMG;IACH,uBAAmB;IAmDf;;;;MAAoB;IAmFxB,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;;;;;8BAtSY,YAAY,GAAG,UAAU;qBAVjB,gBAAgB;sBADf,wBAAwB"}
@@ -2,7 +2,10 @@ 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
+ import {
6
+ markViewAsChrome,
7
+ markViewAsNonAddressable,
8
+ } from "../viewSelectors.js";
6
9
 
7
10
  /**
8
11
  * This class represents a scrollbar thumb that can be used within a grid view
@@ -78,6 +81,7 @@ export default class Scrollbar extends UnitView {
78
81
  );
79
82
 
80
83
  markViewAsNonAddressable(this, { skipSubtree: true });
84
+ markViewAsChrome(this, { skipSubtree: true });
81
85
 
82
86
  this.config = config;
83
87
  this.#scrollDirection = scrollDirection;
@@ -1 +1 @@
1
- {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAIA,yCAA0C,oBAAoB,CAAC;AAE/D;IACI;;;OAGG;IAEH;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,6BAA6B,EAAE,eAAe,gBACrD,OAAO,yBAAyB,EAAE,WAAW,EA4KvD;IA1BG,qBAAqB;IACrB,SADW,MAAM,CACI;IA2BzB,oBAEC;CACJ;sBA/LqB,iBAAiB"}
1
+ {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAOA,yCAA0C,oBAAoB,CAAC;AAE/D;IACI;;;OAGG;IAEH;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,6BAA6B,EAAE,eAAe,gBACrD,OAAO,yBAAyB,EAAE,WAAW,EA6KvD;IA3BG,qBAAqB;IACrB,SADW,MAAM,CACI;IA4BzB,oBAEC;CACJ;sBAnMqB,iBAAiB"}
@@ -1,6 +1,9 @@
1
1
  import { primaryPositionalChannels } from "../../encoder/encoder.js";
2
2
  import LayerView from "../layerView.js";
3
- import { markViewAsNonAddressable } from "../viewSelectors.js";
3
+ import {
4
+ markViewAsChrome,
5
+ markViewAsNonAddressable,
6
+ } from "../viewSelectors.js";
4
7
 
5
8
  export const INTERVAL_DRAG_ACTIVE_PARAM = "intervalDragActive";
6
9
 
@@ -163,6 +166,7 @@ export default class SelectionRect extends LayerView {
163
166
  this._zindex = zindex;
164
167
 
165
168
  markViewAsNonAddressable(this, { skipSubtree: true });
169
+ markViewAsChrome(this, { skipSubtree: true });
166
170
 
167
171
  const selectionListener = () => {
168
172
  const selection =
@@ -1 +1 @@
1
- {"version":3,"file":"separatorView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/separatorView.js"],"names":[],"mappings":"AAoOA;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,cAAc,GAAG,OAAO,GAAG,SAAS,GAC/D,OAAO,oBAAoB,EAAE,cAAc,GAAG,IAAI,CAiB9D;AAxOD;;GAEG;AACH;IAyBI;;;;;;;;;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,EAuBH;IAED;;OAEG;IACH,YAFa,QAAQ,CAIpB;IAED,oBAEC;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;iCA9NY,YAAY,GAAG,UAAU;qBAJjB,gBAAgB"}
1
+ {"version":3,"file":"separatorView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/separatorView.js"],"names":[],"mappings":"AAwOA;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,cAAc,GAAG,OAAO,GAAG,SAAS,GAC/D,OAAO,oBAAoB,EAAE,cAAc,GAAG,IAAI,CAiB9D;AAzOD;;GAEG;AACH;IAyBI;;;;;;;;;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,EAuBH;IAED;;OAEG;IACH,YAFa,QAAQ,CAIpB;IAED,oBAEC;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;;CAwHJ;iCA/NY,YAAY,GAAG,UAAU;qBAPjB,gBAAgB"}
@@ -1,5 +1,8 @@
1
1
  import UnitView from "../unitView.js";
2
- import { markViewAsNonAddressable } from "../viewSelectors.js";
2
+ import {
3
+ markViewAsChrome,
4
+ markViewAsNonAddressable,
5
+ } from "../viewSelectors.js";
3
6
 
4
7
  /**
5
8
  * @typedef {"horizontal" | "vertical"} SeparatorDirection
@@ -221,6 +224,7 @@ export default class SeparatorView {
221
224
  );
222
225
 
223
226
  markViewAsNonAddressable(view, { skipSubtree: true });
227
+ markViewAsChrome(view, { skipSubtree: true });
224
228
 
225
229
  return view;
226
230
  }
@@ -17,23 +17,50 @@ export function createAndInitialize<V extends import("./view.js").default>(spec:
17
17
  noData: boolean;
18
18
  implicitRoot: boolean;
19
19
  }): Promise<V>;
20
+ /**
21
+ * Renders a view hierarchy into a debugging layout tree that records the
22
+ * rendered view coordinates.
23
+ *
24
+ * @param {View} view
25
+ * @param {import("./layout/rectangle.js").default} [coords]
26
+ */
27
+ export function renderToLayout(view: View, coords?: import("./layout/rectangle.js").default): {
28
+ viewName: string;
29
+ coords: string;
30
+ children: /*elided*/ any[];
31
+ addChild(viewCoords: /*elided*/ any): void;
32
+ };
33
+ /**
34
+ * Creates a wrapped view hierarchy and renders it into a debugging layout tree.
35
+ *
36
+ * @param {RootSpec} spec
37
+ * @param {import("./viewFactory.js").ViewFactoryOptions} [viewFactoryOptions]
38
+ * @param {import("./layout/rectangle.js").default} [coords]
39
+ */
40
+ export function specToLayout(spec: RootSpec, viewFactoryOptions?: import("./viewFactory.js").ViewFactoryOptions, coords?: import("./layout/rectangle.js").default): Promise<{
41
+ viewName: string;
42
+ coords: string;
43
+ children: /*elided*/ any[];
44
+ addChild(viewCoords: /*elided*/ any): void;
45
+ }>;
20
46
  export { createHeadlessEngine };
21
47
  /**
22
- * Utils for Jest tests
48
+ * Utils for tests
23
49
  * TODO: Find a better place and convention
24
50
  */
25
51
  export type RootSpec = import("../spec/root.js").RootSpec;
26
52
  /**
27
- * Utils for Jest tests
53
+ * Utils for tests
28
54
  * TODO: Find a better place and convention
29
55
  */
30
56
  export type ViewContext = import("../types/viewContext.js").default;
31
57
  /**
32
- * Utils for Jest tests
58
+ * Utils for tests
33
59
  * TODO: Find a better place and convention
34
60
  */
35
61
  export type BroadcastingViewContext = ViewContext & {
36
62
  emitBroadcast: (root: import("./view.js").default, type: import("../genomeSpy.js").BroadcastEventType, payload?: any) => void;
37
63
  };
64
+ import View from "./view.js";
38
65
  import { createHeadlessEngine } from "../genomeSpy/headlessBootstrap.js";
39
66
  //# sourceMappingURL=testUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AA4BA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CAOvD;AAED;;;GAGG;AACH,uEAHW,OAAO,kBAAkB,EAAE,kBAAkB,GAC3C,uBAAuB,CAmCnC;AAGS,uBAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,uBAAuB,OAAO,kBAAkB,EAAE,kBAAkB,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAqBhL,oCAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,YAAY,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;;;;;;uBA/FpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO;;;;;sCACzC,WAAW,GAAG;IACtB,aAAa,EAAE,CACb,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,EACjC,IAAI,EAAE,OAAO,iBAAiB,EAAE,kBAAkB,EAClD,OAAO,CAAC,EAAE,GAAG,KACV,IAAI,CAAA;CACV;qCAcG,mCAAmC"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAkCA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CAOvD;AAED;;;GAGG;AACH,uEAHW,OAAO,kBAAkB,EAAE,kBAAkB,GAC3C,uBAAuB,CAmCnC;AAGS,uBAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,uBAAuB,OAAO,kBAAkB,EAAE,kBAAkB,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAqBhL,oCAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,YAAY,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAqBjM;;;;;;GAMG;AACH,qCAHW,IAAI,WACJ,OAAO,uBAAuB,EAAE,OAAO;;;;;EAoBjD;AAED;;;;;;GAMG;AACH,mCAJW,QAAQ,uBACR,OAAO,kBAAkB,EAAE,kBAAkB,WAC7C,OAAO,uBAAuB,EAAE,OAAO;;;;;GASjD;;;;;;uBAnKY,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO;;;;;sCACzC,WAAW,GAAG;IACtB,aAAa,EAAE,CACb,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,EACjC,IAAI,EAAE,OAAO,iBAAiB,EAAE,kBAAkB,EAClD,OAAO,CAAC,EAAE,GAAG,KACV,IAAI,CAAA;CACV;iBAca,WAAW;qCAMrB,mCAAmC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Utils for Jest tests
2
+ * Utils for tests
3
3
  * TODO: Find a better place and convention
4
4
  *
5
5
  * @typedef {import("../spec/root.js").RootSpec} RootSpec
@@ -13,7 +13,10 @@
13
13
  * }} BroadcastingViewContext
14
14
  */
15
15
 
16
- import { checkForDuplicateScaleNames } from "./viewUtils.js";
16
+ import {
17
+ calculateCanvasSize,
18
+ checkForDuplicateScaleNames,
19
+ } from "./viewUtils.js";
17
20
  import {
18
21
  initializeViewSubtree,
19
22
  loadViewSubtreeData,
@@ -21,6 +24,9 @@ import {
21
24
  import { VIEW_ROOT_NAME } from "./viewFactory.js";
22
25
  import UnitView from "./unitView.js";
23
26
  import ContainerView from "./containerView.js";
27
+ import View from "./view.js";
28
+ import Rectangle from "./layout/rectangle.js";
29
+ import DebugginViewRenderingContext from "./renderingContext/debuggingViewRenderingContext.js";
24
30
  import {
25
31
  createHeadlessEngine,
26
32
  createHeadlessViewContext,
@@ -118,4 +124,47 @@ export async function createAndInitialize(spec, viewClass) {
118
124
  return view;
119
125
  }
120
126
 
127
+ /**
128
+ * Renders a view hierarchy into a debugging layout tree that records the
129
+ * rendered view coordinates.
130
+ *
131
+ * @param {View} view
132
+ * @param {import("./layout/rectangle.js").default} [coords]
133
+ */
134
+ export function renderToLayout(view, coords) {
135
+ const renderingContext = new DebugginViewRenderingContext({});
136
+
137
+ const canvasSize = calculateCanvasSize(view);
138
+ const rect =
139
+ coords ??
140
+ Rectangle.create(
141
+ 0,
142
+ 0,
143
+ canvasSize.width ?? 1500,
144
+ canvasSize.height ?? 1000
145
+ );
146
+
147
+ view.render(renderingContext, rect, {
148
+ firstFacet: true,
149
+ });
150
+
151
+ return renderingContext.getLayout();
152
+ }
153
+
154
+ /**
155
+ * Creates a wrapped view hierarchy and renders it into a debugging layout tree.
156
+ *
157
+ * @param {RootSpec} spec
158
+ * @param {import("./viewFactory.js").ViewFactoryOptions} [viewFactoryOptions]
159
+ * @param {import("./layout/rectangle.js").default} [coords]
160
+ */
161
+ export async function specToLayout(spec, viewFactoryOptions = {}, coords) {
162
+ const view = await create(/** @type {any} */ (spec), View, {
163
+ wrapRoot: true,
164
+ ...viewFactoryOptions,
165
+ });
166
+
167
+ return renderToLayout(view, coords);
168
+ }
169
+
121
170
  export { createHeadlessEngine };
@@ -19,6 +19,20 @@ export function getImportScopeInfo(view: import("./view.js").default): ImportSco
19
19
  * @param {AddressableOptions} [options]
20
20
  */
21
21
  export function markViewAsNonAddressable(view: import("./view.js").default, options?: AddressableOptions): void;
22
+ /**
23
+ * Marks a view as decorative chrome.
24
+ *
25
+ * @param {import("./view.js").default} view
26
+ * @param {ChromeOptions} [options]
27
+ */
28
+ export function markViewAsChrome(view: import("./view.js").default, options?: ChromeOptions): void;
29
+ /**
30
+ * Returns whether a view has been marked as decorative chrome.
31
+ *
32
+ * @param {import("./view.js").default} view
33
+ * @returns {boolean}
34
+ */
35
+ export function isChromeView(view: import("./view.js").default): boolean;
22
36
  /**
23
37
  * Returns the import scope chain for a view, using named import instances.
24
38
  *
@@ -55,6 +69,20 @@ export function makeParamSelectorKey(selector: ParamSelector): string;
55
69
  * @returns {import("./view.js").default[]}
56
70
  */
57
71
  export function getAddressableViews(root: import("./view.js").default): import("./view.js").default[];
72
+ /**
73
+ * Visits all non-chrome views in the hierarchy.
74
+ *
75
+ * @param {import("./view.js").default} root
76
+ * @param {import("./view.js").Visitor} visitor
77
+ */
78
+ export function visitNonChromeViews(root: import("./view.js").default, visitor: import("./view.js").Visitor): void;
79
+ /**
80
+ * Returns non-chrome views in the hierarchy.
81
+ *
82
+ * @param {import("./view.js").default} root
83
+ * @returns {import("./view.js").default[]}
84
+ */
85
+ export function getNonChromeViews(root: import("./view.js").default): import("./view.js").default[];
58
86
  /**
59
87
  * Visits all addressable views in the hierarchy.
60
88
  *
@@ -107,24 +135,20 @@ export function validateSelectorConstraints(root: import("./view.js").default):
107
135
  * names or runtime-only nodes.
108
136
  */
109
137
  /**
110
- * @typedef {{ scope: string[], view: string }} ViewSelector
111
- * @typedef {{ scope: string[], param: string }} ParamSelector
138
+ * @typedef {import("./viewUtilTypes.d.ts").ViewSelector} ViewSelector
139
+ * @typedef {import("./viewUtilTypes.d.ts").ParamSelector} ParamSelector
112
140
  * @typedef {{ view: import("./view.js").default, param: import("../spec/parameter.js").Parameter, selector: ParamSelector }} BookmarkableParamEntry
113
141
  * @typedef {{ message: string, scope: string[] }} SelectorValidationIssue
114
142
  * @typedef {{ name: string | null }} ImportScopeInfo
115
143
  * @typedef {"exclude" | "excludeSubtree"} AddressableOverride
144
+ * @typedef {"exclude" | "excludeSubtree"} ChromeOverride
116
145
  * @typedef {{ skipSubtree?: boolean }} AddressableOptions
146
+ * @typedef {{ skipSubtree?: boolean }} ChromeOptions
117
147
  * @typedef {{ view: import("./view.js").default, param: import("../spec/parameter.js").Parameter }} ResolvedParam
118
148
  */
119
149
  export const PARAM_SELECTOR_KEY_PREFIX: "p:";
120
- export type ViewSelector = {
121
- scope: string[];
122
- view: string;
123
- };
124
- export type ParamSelector = {
125
- scope: string[];
126
- param: string;
127
- };
150
+ export type ViewSelector = import("./viewUtilTypes.d.ts").ViewSelector;
151
+ export type ParamSelector = import("./viewUtilTypes.d.ts").ParamSelector;
128
152
  export type BookmarkableParamEntry = {
129
153
  view: import("./view.js").default;
130
154
  param: import("../spec/parameter.js").Parameter;
@@ -138,9 +162,13 @@ export type ImportScopeInfo = {
138
162
  name: string | null;
139
163
  };
140
164
  export type AddressableOverride = "exclude" | "excludeSubtree";
165
+ export type ChromeOverride = "exclude" | "excludeSubtree";
141
166
  export type AddressableOptions = {
142
167
  skipSubtree?: boolean;
143
168
  };
169
+ export type ChromeOptions = {
170
+ skipSubtree?: boolean;
171
+ };
144
172
  export type ResolvedParam = {
145
173
  view: import("./view.js").default;
146
174
  param: import("../spec/parameter.js").Parameter;
@@ -1 +1 @@
1
- {"version":3,"file":"viewSelectors.d.ts","sourceRoot":"","sources":["../../../src/view/viewSelectors.js"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,6CAHW,OAAO,WAAW,EAAE,OAAO,aAC3B,MAAM,GAAG,IAAI,QAQvB;AAED;;;;;GAKG;AACH,yCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,eAAe,GAAG,SAAS,CAIvC;AAED;;;;;GAKG;AACH,+CAHW,OAAO,WAAW,EAAE,OAAO,YAC3B,kBAAkB,QAM5B;AAED;;;;;GAKG;AACH,wCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,MAAM,EAAE,CAgBpB;AAED;;;;;GAKG;AACH,sCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,YAAY,CAYxB;AAED;;;;;;GAMG;AACH,uCAJW,OAAO,WAAW,EAAE,OAAO,aAC3B,MAAM,GACJ,aAAa,CAazB;AAED;;;;;GAKG;AACH,+CAHW,aAAa,GACX,MAAM,CAQlB;AAED;;;;;GAKG;AACH,0CAHW,OAAO,WAAW,EAAE,OAAO,GACzB,OAAO,WAAW,EAAE,OAAO,EAAE,CAWzC;AAED;;;;;GAKG;AACH,4CAHW,OAAO,WAAW,EAAE,OAAO,WAC3B,OAAO,WAAW,EAAE,OAAO,QAerC;AAED;;;;;;GAMG;AACH,0CAJW,OAAO,WAAW,EAAE,OAAO,YAC3B,YAAY,GACV,OAAO,WAAW,EAAE,OAAO,GAAG,SAAS,CAoCnD;AAED;;;;;;GAMG;AACH,2CAJW,OAAO,WAAW,EAAE,OAAO,YAC3B,aAAa,GACX,aAAa,GAAG,SAAS,CAuCrC;AAED;;;;;GAKG;AACH,8CAHW,OAAO,WAAW,EAAE,OAAO,WAC3B,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,QAyBjD;AAED;;;;;GAKG;AACH,4CAHW,OAAO,WAAW,EAAE,OAAO,GACzB,sBAAsB,EAAE,CAOpC;AAED;;;;;GAKG;AACH,kDAHW,OAAO,WAAW,EAAE,OAAO,GACzB,uBAAuB,EAAE,CAarC;AArUD;;;;;;GAMG;AAEH;;;;;;;;;GASG;AAEH,wCAAyC,IAAI,CAAC;2BAVjC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;4BACjC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;qCAClC;IAAE,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,sBAAsB,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE;sCAC/G;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE;8BACpC;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;kCACvB,SAAS,GAAG,gBAAgB;iCAC5B;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE;4BACzB;IAAE,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,sBAAsB,EAAE,SAAS,CAAA;CAAE"}
1
+ {"version":3,"file":"viewSelectors.d.ts","sourceRoot":"","sources":["../../../src/view/viewSelectors.js"],"names":[],"mappings":"AAsCA;;;;;GAKG;AACH,6CAHW,OAAO,WAAW,EAAE,OAAO,aAC3B,MAAM,GAAG,IAAI,QAQvB;AAED;;;;;GAKG;AACH,yCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,eAAe,GAAG,SAAS,CAIvC;AAED;;;;;GAKG;AACH,+CAHW,OAAO,WAAW,EAAE,OAAO,YAC3B,kBAAkB,QAM5B;AAED;;;;;GAKG;AACH,uCAHW,OAAO,WAAW,EAAE,OAAO,YAC3B,aAAa,QAMvB;AAED;;;;;GAKG;AACH,mCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,OAAO,CAInB;AAED;;;;;GAKG;AACH,wCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,MAAM,EAAE,CAgBpB;AAED;;;;;GAKG;AACH,sCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,YAAY,CAYxB;AAED;;;;;;GAMG;AACH,uCAJW,OAAO,WAAW,EAAE,OAAO,aAC3B,MAAM,GACJ,aAAa,CAazB;AAED;;;;;GAKG;AACH,+CAHW,aAAa,GACX,MAAM,CAQlB;AAED;;;;;GAKG;AACH,0CAHW,OAAO,WAAW,EAAE,OAAO,GACzB,OAAO,WAAW,EAAE,OAAO,EAAE,CAWzC;AAED;;;;;GAKG;AACH,0CAHW,OAAO,WAAW,EAAE,OAAO,WAC3B,OAAO,WAAW,EAAE,OAAO,QAerC;AAED;;;;;GAKG;AACH,wCAHW,OAAO,WAAW,EAAE,OAAO,GACzB,OAAO,WAAW,EAAE,OAAO,EAAE,CAWzC;AAED;;;;;GAKG;AACH,4CAHW,OAAO,WAAW,EAAE,OAAO,WAC3B,OAAO,WAAW,EAAE,OAAO,QAerC;AAED;;;;;;GAMG;AACH,0CAJW,OAAO,WAAW,EAAE,OAAO,YAC3B,YAAY,GACV,OAAO,WAAW,EAAE,OAAO,GAAG,SAAS,CAoCnD;AAED;;;;;;GAMG;AACH,2CAJW,OAAO,WAAW,EAAE,OAAO,YAC3B,aAAa,GACX,aAAa,GAAG,SAAS,CAuCrC;AAED;;;;;GAKG;AACH,8CAHW,OAAO,WAAW,EAAE,OAAO,WAC3B,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,QAyBjD;AAED;;;;;GAKG;AACH,4CAHW,OAAO,WAAW,EAAE,OAAO,GACzB,sBAAsB,EAAE,CAOpC;AAED;;;;;GAKG;AACH,kDAHW,OAAO,WAAW,EAAE,OAAO,GACzB,uBAAuB,EAAE,CAarC;AAtYD;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AAEH,wCAAyC,IAAI,CAAC;2BAZjC,OAAO,sBAAsB,EAAE,YAAY;4BAC3C,OAAO,sBAAsB,EAAE,aAAa;qCAC5C;IAAE,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,sBAAsB,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE;sCAC/G;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE;8BACpC;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;kCACvB,SAAS,GAAG,gBAAgB;6BAC5B,SAAS,GAAG,gBAAgB;iCAC5B;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE;4BACzB;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE;4BACzB;IAAE,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,sBAAsB,EAAE,SAAS,CAAA;CAAE"}