@genome-spy/core 0.63.0 → 0.65.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 (138) hide show
  1. package/dist/bundle/{index-CCJIjehY.js → AbortablePromiseCache-CcuMrnn7.js} +22 -91
  2. package/dist/bundle/browser-txUcLy2H.js +123 -0
  3. package/dist/bundle/index-BQpbYrv4.js +1712 -0
  4. package/dist/bundle/index-BhtHKLUo.js +73 -0
  5. package/dist/bundle/index-C0llXMqm.js +280 -0
  6. package/dist/bundle/index-CCe8rnZz.js +716 -0
  7. package/dist/bundle/index-CD7FLu9x.js +269 -0
  8. package/dist/bundle/{index-C08YCM2T.js → index-D-w7Mmt9.js} +246 -126
  9. package/dist/bundle/index-D74H8TTz.js +508 -0
  10. package/dist/bundle/index-DhcU-Gk-.js +1487 -0
  11. package/dist/bundle/index.es.js +5394 -4989
  12. package/dist/bundle/index.js +420 -362
  13. package/dist/bundle/inflate-DRgHi_KK.js +1050 -0
  14. package/dist/schema.json +93 -13
  15. package/dist/src/data/collector.d.ts +7 -2
  16. package/dist/src/data/collector.d.ts.map +1 -1
  17. package/dist/src/data/collector.js +13 -2
  18. package/dist/src/data/dataFlow.d.ts +20 -42
  19. package/dist/src/data/dataFlow.d.ts.map +1 -1
  20. package/dist/src/data/dataFlow.js +57 -80
  21. package/dist/src/data/dataFlow.test.js +35 -2
  22. package/dist/src/data/flowHandle.d.ts +15 -0
  23. package/dist/src/data/flowHandle.d.ts.map +1 -0
  24. package/dist/src/data/flowHandle.js +13 -0
  25. package/dist/src/data/flowInit.d.ts +85 -0
  26. package/dist/src/data/flowInit.d.ts.map +1 -0
  27. package/dist/src/data/flowInit.js +238 -0
  28. package/dist/src/data/flowInit.test.d.ts +2 -0
  29. package/dist/src/data/flowInit.test.d.ts.map +1 -0
  30. package/dist/src/data/flowInit.test.js +413 -0
  31. package/dist/src/data/flowOptimizer.d.ts +6 -4
  32. package/dist/src/data/flowOptimizer.d.ts.map +1 -1
  33. package/dist/src/data/flowOptimizer.js +29 -14
  34. package/dist/src/data/flowOptimizer.test.js +20 -15
  35. package/dist/src/data/sources/lazy/bamSource.js +1 -1
  36. package/dist/src/data/sources/lazy/bigBedSource.js +1 -1
  37. package/dist/src/data/sources/lazy/bigWigSource.js +1 -1
  38. package/dist/src/data/sources/lazy/gff3Source.d.ts +2 -6
  39. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  40. package/dist/src/data/sources/lazy/gff3Source.js +4 -8
  41. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
  42. package/dist/src/data/sources/lazy/indexedFastaSource.js +17 -17
  43. package/dist/src/data/sources/lazy/tabixSource.js +1 -1
  44. package/dist/src/genomeSpy.d.ts +1 -1
  45. package/dist/src/genomeSpy.d.ts.map +1 -1
  46. package/dist/src/genomeSpy.js +18 -61
  47. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  48. package/dist/src/gl/webGLHelper.js +8 -0
  49. package/dist/src/marks/link.fragment.glsl.js +1 -1
  50. package/dist/src/marks/link.vertex.glsl.js +1 -1
  51. package/dist/src/marks/mark.d.ts +1 -0
  52. package/dist/src/marks/mark.d.ts.map +1 -1
  53. package/dist/src/marks/mark.js +22 -1
  54. package/dist/src/marks/point.fragment.glsl.js +1 -1
  55. package/dist/src/marks/point.vertex.glsl.js +1 -1
  56. package/dist/src/marks/rect.fragment.glsl.js +1 -1
  57. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  58. package/dist/src/marks/rule.fragment.glsl.js +1 -1
  59. package/dist/src/marks/rule.vertex.glsl.js +1 -1
  60. package/dist/src/marks/text.fragment.glsl.js +1 -1
  61. package/dist/src/marks/text.vertex.glsl.js +1 -1
  62. package/dist/src/selection/selection.d.ts +5 -0
  63. package/dist/src/selection/selection.d.ts.map +1 -1
  64. package/dist/src/selection/selection.js +43 -6
  65. package/dist/src/selection/selection.test.d.ts +2 -0
  66. package/dist/src/selection/selection.test.d.ts.map +1 -0
  67. package/dist/src/selection/selection.test.js +14 -0
  68. package/dist/src/spec/parameter.d.ts +28 -2
  69. package/dist/src/spec/sampleView.d.ts +3 -2
  70. package/dist/src/styles/{genome-spy.scss → genome-spy.css} +25 -21
  71. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  72. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  73. package/dist/src/styles/genome-spy.css.js +264 -195
  74. package/dist/src/styles/update.sh +14 -4
  75. package/dist/src/types/viewContext.d.ts +1 -1
  76. package/dist/src/utils/expression.d.ts +5 -0
  77. package/dist/src/utils/expression.d.ts.map +1 -1
  78. package/dist/src/utils/expression.js +37 -0
  79. package/dist/src/utils/interactionEvent.d.ts +18 -1
  80. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  81. package/dist/src/utils/interactionEvent.js +101 -1
  82. package/dist/src/utils/interactionEvent.test.d.ts +2 -0
  83. package/dist/src/utils/interactionEvent.test.d.ts.map +1 -0
  84. package/dist/src/utils/interactionEvent.test.js +35 -0
  85. package/dist/src/view/axisResolution.d.ts +5 -0
  86. package/dist/src/view/axisResolution.d.ts.map +1 -1
  87. package/dist/src/view/axisResolution.js +16 -1
  88. package/dist/src/view/facetView.d.ts +1 -1
  89. package/dist/src/view/facetView.d.ts.map +1 -1
  90. package/dist/src/view/facetView.js +1 -0
  91. package/dist/src/view/flowBuilder.d.ts +2 -2
  92. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  93. package/dist/src/view/flowBuilder.js +21 -4
  94. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  95. package/dist/src/view/gridView/gridView.js +13 -0
  96. package/dist/src/view/gridView/selectionRect.d.ts +8 -4
  97. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  98. package/dist/src/view/gridView/selectionRect.js +28 -3
  99. package/dist/src/view/gridView/selectionRect.test.d.ts +2 -0
  100. package/dist/src/view/gridView/selectionRect.test.d.ts.map +1 -0
  101. package/dist/src/view/gridView/selectionRect.test.js +87 -0
  102. package/dist/src/view/paramMediator.d.ts +2 -1
  103. package/dist/src/view/paramMediator.d.ts.map +1 -1
  104. package/dist/src/view/paramMediator.js +13 -1
  105. package/dist/src/view/paramMediator.test.js +22 -0
  106. package/dist/src/view/scaleResolution.d.ts +5 -0
  107. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  108. package/dist/src/view/scaleResolution.js +10 -0
  109. package/dist/src/view/testUtils.d.ts.map +1 -1
  110. package/dist/src/view/testUtils.js +16 -4
  111. package/dist/src/view/unitView.d.ts.map +1 -1
  112. package/dist/src/view/unitView.js +103 -10
  113. package/dist/src/view/view.d.ts +17 -1
  114. package/dist/src/view/view.d.ts.map +1 -1
  115. package/dist/src/view/view.js +57 -1
  116. package/dist/src/view/viewDispose.test.d.ts +2 -0
  117. package/dist/src/view/viewDispose.test.d.ts.map +1 -0
  118. package/dist/src/view/viewDispose.test.js +110 -0
  119. package/dist/src/view/viewUtils.d.ts +4 -4
  120. package/dist/src/view/viewUtils.d.ts.map +1 -1
  121. package/dist/src/view/viewUtils.js +19 -15
  122. package/dist/src/view/viewUtils.test.d.ts +2 -0
  123. package/dist/src/view/viewUtils.test.d.ts.map +1 -0
  124. package/dist/src/view/viewUtils.test.js +87 -0
  125. package/package.json +16 -16
  126. package/dist/bundle/__vite-browser-external-C--ziKoh.js +0 -8
  127. package/dist/bundle/_commonjsHelpers-DjF3Plf2.js +0 -26
  128. package/dist/bundle/index-5ajWdKly.js +0 -1319
  129. package/dist/bundle/index-B03-Om4z.js +0 -274
  130. package/dist/bundle/index-BftNdA0O.js +0 -27
  131. package/dist/bundle/index-Bg7C4Xat.js +0 -2750
  132. package/dist/bundle/index-C3QR8Lv6.js +0 -2131
  133. package/dist/bundle/index-DTcHjAHp.js +0 -505
  134. package/dist/bundle/index-DnIkxb0L.js +0 -1025
  135. package/dist/bundle/index-Ww3TAo6_.js +0 -71
  136. package/dist/bundle/index-g8iXgW0W.js +0 -651
  137. package/dist/bundle/long-B-FASCSo.js +0 -2387
  138. package/dist/bundle/remoteFile-BuaqFGWk.js +0 -94
package/dist/schema.json CHANGED
@@ -1654,6 +1654,15 @@
1654
1654
  }
1655
1655
  ]
1656
1656
  },
1657
+ "DomEventType": {
1658
+ "enum": [
1659
+ "click",
1660
+ "dblclick",
1661
+ "mouseover",
1662
+ "pointerover"
1663
+ ],
1664
+ "type": "string"
1665
+ },
1657
1666
  "DsvDataFormat": {
1658
1667
  "additionalProperties": false,
1659
1668
  "properties": {
@@ -2107,6 +2116,23 @@
2107
2116
  },
2108
2117
  "type": "object"
2109
2118
  },
2119
+ "EventConfig": {
2120
+ "additionalProperties": false,
2121
+ "properties": {
2122
+ "filter": {
2123
+ "description": "An optional filter expression to further filter events of the specified type. The expression can only refer to the event object as `event`, and should evaluate to a boolean value indicating whether to include the event. No other data or parameters are in scope.",
2124
+ "type": "string"
2125
+ },
2126
+ "type": {
2127
+ "$ref": "#/definitions/DomEventType",
2128
+ "description": "The type of event to listen to. For example, `\"click\"` or `\"mouseover\"`."
2129
+ }
2130
+ },
2131
+ "required": [
2132
+ "type"
2133
+ ],
2134
+ "type": "object"
2135
+ },
2110
2136
  "ExprDef": {
2111
2137
  "additionalProperties": false,
2112
2138
  "properties": {
@@ -3715,6 +3741,23 @@
3715
3741
  "IntervalSelectionConfig": {
3716
3742
  "additionalProperties": false,
3717
3743
  "properties": {
3744
+ "clear": {
3745
+ "anyOf": [
3746
+ {
3747
+ "$ref": "#/definitions/DomEventType"
3748
+ },
3749
+ {
3750
+ "$ref": "#/definitions/EventConfig"
3751
+ },
3752
+ {
3753
+ "type": "string"
3754
+ },
3755
+ {
3756
+ "type": "boolean"
3757
+ }
3758
+ ],
3759
+ "description": "A string or object that defines the events that should clear the selection.\n\n__Default value:__ `\"dblclick\"`"
3760
+ },
3718
3761
  "encodings": {
3719
3762
  "description": "An array of encoding channels that define the interval selection.",
3720
3763
  "items": {
@@ -3727,16 +3770,22 @@
3727
3770
  "description": "Interval selections display a rectangle mark to show the selected range. Use the `mark` property to adjust the appearance of this rectangle."
3728
3771
  },
3729
3772
  "on": {
3730
- "enum": [
3731
- "click",
3732
- "mouseover",
3733
- "pointerover"
3773
+ "anyOf": [
3774
+ {
3775
+ "$ref": "#/definitions/DomEventType"
3776
+ },
3777
+ {
3778
+ "$ref": "#/definitions/EventConfig"
3779
+ },
3780
+ {
3781
+ "type": "string"
3782
+ }
3734
3783
  ],
3735
- "type": "string"
3784
+ "description": "A string or object that defines the events to which the selection should listen."
3736
3785
  },
3737
3786
  "type": {
3738
3787
  "const": "interval",
3739
- "description": "Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`.",
3788
+ "description": "The selection type.\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`.",
3740
3789
  "type": "string"
3741
3790
  }
3742
3791
  },
@@ -4978,13 +5027,36 @@
4978
5027
  "PointSelectionConfig": {
4979
5028
  "additionalProperties": false,
4980
5029
  "properties": {
5030
+ "clear": {
5031
+ "anyOf": [
5032
+ {
5033
+ "$ref": "#/definitions/DomEventType"
5034
+ },
5035
+ {
5036
+ "$ref": "#/definitions/EventConfig"
5037
+ },
5038
+ {
5039
+ "type": "string"
5040
+ },
5041
+ {
5042
+ "type": "boolean"
5043
+ }
5044
+ ],
5045
+ "description": "A string or object that defines the events that should clear the selection.\n\n__Default value:__ `\"dblclick\"`"
5046
+ },
4981
5047
  "on": {
4982
- "enum": [
4983
- "click",
4984
- "mouseover",
4985
- "pointerover"
5048
+ "anyOf": [
5049
+ {
5050
+ "$ref": "#/definitions/DomEventType"
5051
+ },
5052
+ {
5053
+ "$ref": "#/definitions/EventConfig"
5054
+ },
5055
+ {
5056
+ "type": "string"
5057
+ }
4986
5058
  ],
4987
- "type": "string"
5059
+ "description": "A string or object that defines the events to which the selection should listen."
4988
5060
  },
4989
5061
  "toggle": {
4990
5062
  "description": "Controls whether data values should be toggled (inserted or removed from a point selection) when clicking with the shift key pressed.\n\n- `true` -- additional values can be selected by shift-clicking.\n- `false` -- only a single value can be selected at a time.\n\n__Default value:__ `true`",
@@ -4992,7 +5064,7 @@
4992
5064
  },
4993
5065
  "type": {
4994
5066
  "const": "point",
4995
- "description": "Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`.",
5067
+ "description": "The selection type.\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`.",
4996
5068
  "type": "string"
4997
5069
  }
4998
5070
  },
@@ -8111,7 +8183,7 @@
8111
8183
  "type": "string"
8112
8184
  },
8113
8185
  "type": {
8114
- "$ref": "#/definitions/Type",
8186
+ "$ref": "#/definitions/SampleAttributeType",
8115
8187
  "description": "The attribute type. One of `\"nominal\"`, `\"ordinal\"`, or `\"quantitative\"`."
8116
8188
  },
8117
8189
  "visible": {
@@ -8125,6 +8197,14 @@
8125
8197
  },
8126
8198
  "type": "object"
8127
8199
  },
8200
+ "SampleAttributeType": {
8201
+ "enum": [
8202
+ "nominal",
8203
+ "ordinal",
8204
+ "quantitative"
8205
+ ],
8206
+ "type": "string"
8207
+ },
8128
8208
  "SampleDef": {
8129
8209
  "additionalProperties": false,
8130
8210
  "properties": {
@@ -10,10 +10,15 @@ export default class Collector extends FlowNode {
10
10
  */
11
11
  constructor(params?: import("../spec/transform.js").CollectParams);
12
12
  params: import("../spec/transform.js").CollectParams;
13
- /** @type {(function(Collector):void)[]} */
14
- observers: ((arg0: Collector) => void)[];
13
+ /** @type {Set<function(Collector):void>} */
14
+ observers: Set<(arg0: Collector) => void>;
15
15
  /** @type {Map<import("../spec/channel.js").Scalar[], Data>} TODO: proper type for key */
16
16
  facetBatches: Map<import("../spec/channel.js").Scalar[], import("./flowNode.js").Data>;
17
+ /**
18
+ * @param {function(Collector):void} listener
19
+ * @returns {() => void}
20
+ */
21
+ observe(listener: (arg0: Collector) => void): () => void;
17
22
  /**
18
23
  * @returns {Iterable<Datum>}
19
24
  */
@@ -1 +1 @@
1
- {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../../src/data/collector.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH;IAuCI;;OAEG;IACH,qBAFW,OAAO,sBAAsB,EAAE,aAAa,EAiBtD;IAZG,qDAA2C;IAE3C,2CAA2C;IAC3C,WADW,CAAC,CAAS,IAAS,EAAT,SAAS,KAAE,IAAI,CAAC,EAAE,CACpB;IAGnB,yFAAyF;IACzF,cADW,GAAG,CAAC,OAAO,oBAAoB,EAAE,MAAM,EAAE,+BAAO,CACN;IAgHzD;;OAEG;IACH,WAFa,QAAQ,+BAAO,CAqB3B;IAED;;;OAGG;IACH,mBAFW,CAAC,KAAK,+BAAO,KAAK,IAAI,QAUhC;IAED;;OAEG;IACH,uBAMC;IA8CD;;;;OAIG;IACH,8BAFW,MAAM,iCA4BhB;;CACJ;qBA7SyD,eAAe"}
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../../src/data/collector.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH;IAuCI;;OAEG;IACH,qBAFW,OAAO,sBAAsB,EAAE,aAAa,EAiBtD;IAZG,qDAA2C;IAE3C,4CAA4C;IAC5C,WADW,GAAG,CAAC,CAAS,IAAS,EAAT,SAAS,KAAE,IAAI,CAAC,CACd;IAG1B,yFAAyF;IACzF,cADW,GAAG,CAAC,OAAO,oBAAoB,EAAE,MAAM,EAAE,+BAAO,CACN;IAmFzD;;;OAGG;IACH,kBAHW,CAAS,IAAS,EAAT,SAAS,KAAE,IAAI,GACtB,MAAM,IAAI,CAOtB;IA+BD;;OAEG;IACH,WAFa,QAAQ,+BAAO,CAqB3B;IAED;;;OAGG;IACH,mBAFW,CAAC,KAAK,+BAAO,KAAK,IAAI,QAUhC;IAED;;OAEG;IACH,uBAMC;IA8CD;;;;OAIG;IACH,8BAFW,MAAM,iCA4BhB;;CACJ;qBAxTyD,eAAe"}
@@ -61,8 +61,8 @@ export default class Collector extends FlowNode {
61
61
 
62
62
  this.params = params ?? { type: "collect" };
63
63
 
64
- /** @type {(function(Collector):void)[]} */
65
- this.observers = [];
64
+ /** @type {Set<function(Collector):void>} */
65
+ this.observers = new Set();
66
66
 
67
67
  // TODO: Consider nested maps instead of InternMap
68
68
  /** @type {Map<import("../spec/channel.js").Scalar[], Data>} TODO: proper type for key */
@@ -149,6 +149,17 @@ export default class Collector extends FlowNode {
149
149
  }
150
150
  }
151
151
 
152
+ /**
153
+ * @param {function(Collector):void} listener
154
+ * @returns {() => void}
155
+ */
156
+ observe(listener) {
157
+ this.observers.add(listener);
158
+ return () => {
159
+ this.observers.delete(listener);
160
+ };
161
+ }
162
+
152
163
  #propagateToChildren() {
153
164
  if (this.children.length) {
154
165
  for (const [facetId, data] of this.facetBatches.entries()) {
@@ -1,65 +1,43 @@
1
1
  /**
2
- * @template H A key (string, object, whatever) that is used to retrieve
3
- * data sources and collectors.
2
+ * DataFlow holds data sources and collectors for optimization and initialization.
4
3
  */
5
- export default class DataFlow<H> {
6
- /** @type {Map<H, import("./sources/dataSource.js").default>} */
7
- _dataSourcesByHost: Map<H, import("./sources/dataSource.js").default>;
8
- /** @type {Map<H, import("./collector.js").default>} */
9
- _collectorsByHost: Map<H, import("./collector.js").default>;
10
- /** @type {Map<H, (function(import("./collector.js").default):void)[]>} */
11
- _observers: Map<H, ((arg0: import("./collector.js").default) => void)[]>;
12
- get dataSources(): import("./sources/dataSource.js").default[];
4
+ export default class DataFlow {
5
+ get dataSources(): DataSource[];
13
6
  get collectors(): import("./collector.js").default[];
14
7
  /**
15
- * Adds a callback function that will be called when a collector has completed.
16
- *
17
- * @param {function(import("./collector.js").default):void} callback
18
- * @param {H} key
19
- */
20
- addObserver(callback: (arg0: import("./collector.js").default) => void, key: H): void;
21
- /**
22
- *
23
- * @param {import("./collector.js").default} collector
24
- * @param {H} key
8
+ * @param {Iterable<import("./sources/dataSource.js").default>} dataSources
25
9
  */
26
- _relayObserverCallback(collector: import("./collector.js").default, key: H): void;
10
+ replaceDataSources(dataSources: Iterable<import("./sources/dataSource.js").default>): void;
27
11
  /**
28
- *
29
12
  * @param {import("./sources/dataSource.js").default} dataSource
30
- * @param {H} key
31
13
  */
32
- addDataSource(dataSource: import("./sources/dataSource.js").default, key: H): void;
14
+ addDataSource(dataSource: import("./sources/dataSource.js").default): void;
33
15
  /**
34
- *
35
- * @param {H} key
16
+ * @param {import("./sources/dataSource.js").default} dataSource
36
17
  */
37
- findDataSourceByKey(key: H): import("./sources/dataSource.js").default;
18
+ removeDataSource(dataSource: import("./sources/dataSource.js").default): void;
38
19
  /**
39
- *
40
- * @param {string} name
20
+ * @param {import("./collector.js").default} collector
41
21
  */
42
- findNamedDataSource(name: string): {
43
- dataSource: NamedSource;
44
- hosts: H[];
45
- };
22
+ addCollector(collector: import("./collector.js").default): void;
46
23
  /**
47
- *
48
24
  * @param {import("./collector.js").default} collector
49
- * @param {H} key
50
25
  */
51
- addCollector(collector: import("./collector.js").default, key: H): void;
26
+ removeCollector(collector: import("./collector.js").default): void;
52
27
  /**
28
+ * Prune a collector branch from the flow graph, removing empty ancestors.
53
29
  *
54
- * @param {H} key
30
+ * @param {import("./collector.js").default} collector
55
31
  */
56
- findCollectorByKey(key: H): import("./collector.js").default;
32
+ pruneCollectorBranch(collector: import("./collector.js").default): void;
57
33
  /**
58
- * Allows the flow nodes to perform final initialization after the flow
59
- * structure has been built and optimized.
60
- * Must be called before any data are to be propagated.
34
+ * @param {string} name
61
35
  */
62
- initialize(): void;
36
+ findNamedDataSource(name: string): {
37
+ dataSource: NamedSource;
38
+ };
39
+ #private;
63
40
  }
41
+ import DataSource from "./sources/dataSource.js";
64
42
  import NamedSource from "./sources/namedSource.js";
65
43
  //# sourceMappingURL=dataFlow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataFlow.d.ts","sourceRoot":"","sources":["../../../src/data/dataFlow.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH,8BAHa,CAAC;IAKN,gEAAgE;IAChE,oBADW,GAAG,CAAC,CAAC,EAAE,OAAO,yBAAyB,EAAE,OAAO,CAAC,CACzB;IAEnC,uDAAuD;IACvD,mBADW,GAAG,CAAC,CAAC,EAAE,OAAO,gBAAgB,EAAE,OAAO,CAAC,CACjB;IAElC,0EAA0E;IAC1E,YADW,GAAG,CAAC,CAAC,EAAE,CAAC,CAAS,IAAgC,EAAhC,OAAO,gBAAgB,EAAE,OAAO,KAAE,IAAI,CAAC,EAAE,CAAC,CAC3C;IAG/B,+DAEC;IAED,qDAEC;IAED;;;;;OAKG;IACH,sBAHW,CAAS,IAAgC,EAAhC,OAAO,gBAAgB,EAAE,OAAO,KAAE,IAAI,OAC/C,CAAC,QAUX;IAED;;;;OAIG;IACH,kCAHW,OAAO,gBAAgB,EAAE,OAAO,OAChC,CAAC,QAUX;IAED;;;;OAIG;IACH,0BAHW,OAAO,yBAAyB,EAAE,OAAO,OACzC,CAAC,QAIX;IAED;;;OAGG;IACH,yBAFW,CAAC,6CAIX;IAED;;;OAGG;IACH,0BAFW,MAAM;;;MAiChB;IAED;;;;OAIG;IACH,wBAHW,OAAO,gBAAgB,EAAE,OAAO,OAChC,CAAC,QAOX;IAED;;;OAGG;IACH,wBAFW,CAAC,oCAIX;IAED;;;;OAIG;IACH,mBAIC;CACJ;wBA7IuB,0BAA0B"}
1
+ {"version":3,"file":"dataFlow.d.ts","sourceRoot":"","sources":["../../../src/data/dataFlow.js"],"names":[],"mappings":"AAGA;;GAEG;AACH;IAeI,gCAEC;IAED,qDAEC;IAED;;OAEG;IACH,gCAFW,QAAQ,CAAC,OAAO,yBAAyB,EAAE,OAAO,CAAC,QAI7D;IAED;;OAEG;IACH,0BAFW,OAAO,yBAAyB,EAAE,OAAO,QAInD;IAED;;OAEG;IACH,6BAFW,OAAO,yBAAyB,EAAE,OAAO,QAInD;IAED;;OAEG;IACH,wBAFW,OAAO,gBAAgB,EAAE,OAAO,QAI1C;IAED;;OAEG;IACH,2BAFW,OAAO,gBAAgB,EAAE,OAAO,QAK1C;IAED;;;;OAIG;IACH,gCAFW,OAAO,gBAAgB,EAAE,OAAO,QAiB1C;IAED;;OAEG;IACH,0BAFW,MAAM;;MA2BhB;;CAGJ;uBAtHsB,yBAAyB;wBACxB,0BAA0B"}
@@ -1,92 +1,100 @@
1
+ import DataSource from "./sources/dataSource.js";
1
2
  import NamedSource from "./sources/namedSource.js";
2
3
 
3
4
  /**
4
- * @template H A key (string, object, whatever) that is used to retrieve
5
- * data sources and collectors.
5
+ * DataFlow holds data sources and collectors for optimization and initialization.
6
6
  */
7
7
  export default class DataFlow {
8
- constructor() {
9
- /** @type {Map<H, import("./sources/dataSource.js").default>} */
10
- this._dataSourcesByHost = new Map();
8
+ /** @type {Set<import("./sources/dataSource.js").default>} */
9
+ #dataSources;
10
+
11
+ /** @type {Set<import("./collector.js").default>} */
12
+ #collectors;
11
13
 
12
- /** @type {Map<H, import("./collector.js").default>} */
13
- this._collectorsByHost = new Map();
14
+ constructor() {
15
+ /** @type {Set<import("./sources/dataSource.js").default>} */
16
+ this.#dataSources = new Set();
14
17
 
15
- /** @type {Map<H, (function(import("./collector.js").default):void)[]>} */
16
- this._observers = new Map();
18
+ /** @type {Set<import("./collector.js").default>} */
19
+ this.#collectors = new Set();
17
20
  }
18
21
 
19
22
  get dataSources() {
20
- return [...new Set(this._dataSourcesByHost.values()).values()];
23
+ return [...this.#dataSources];
21
24
  }
22
25
 
23
26
  get collectors() {
24
- return [...this._collectorsByHost.values()];
27
+ return [...this.#collectors];
25
28
  }
26
29
 
27
30
  /**
28
- * Adds a callback function that will be called when a collector has completed.
29
- *
30
- * @param {function(import("./collector.js").default):void} callback
31
- * @param {H} key
31
+ * @param {Iterable<import("./sources/dataSource.js").default>} dataSources
32
32
  */
33
- addObserver(callback, key) {
34
- let arr = this._observers.get(key);
35
- if (!arr) {
36
- arr = [];
37
- this._observers.set(key, arr);
38
- }
33
+ replaceDataSources(dataSources) {
34
+ this.#dataSources = new Set(dataSources);
35
+ }
39
36
 
40
- arr.push(callback);
37
+ /**
38
+ * @param {import("./sources/dataSource.js").default} dataSource
39
+ */
40
+ addDataSource(dataSource) {
41
+ this.#dataSources.add(dataSource);
42
+ }
43
+
44
+ /**
45
+ * @param {import("./sources/dataSource.js").default} dataSource
46
+ */
47
+ removeDataSource(dataSource) {
48
+ this.#dataSources.delete(dataSource);
41
49
  }
42
50
 
43
51
  /**
44
- *
45
52
  * @param {import("./collector.js").default} collector
46
- * @param {H} key
47
53
  */
48
- _relayObserverCallback(collector, key) {
49
- const arr = this._observers.get(key);
50
- if (arr) {
51
- for (const callback of arr) {
52
- // eslint-disable-next-line callback-return
53
- callback(collector);
54
- }
55
- }
54
+ addCollector(collector) {
55
+ this.#collectors.add(collector);
56
56
  }
57
57
 
58
58
  /**
59
- *
60
- * @param {import("./sources/dataSource.js").default} dataSource
61
- * @param {H} key
59
+ * @param {import("./collector.js").default} collector
62
60
  */
63
- addDataSource(dataSource, key) {
64
- this._dataSourcesByHost.set(key, dataSource);
61
+ removeCollector(collector) {
62
+ collector.observers.clear();
63
+ this.#collectors.delete(collector);
65
64
  }
66
65
 
67
66
  /**
67
+ * Prune a collector branch from the flow graph, removing empty ancestors.
68
68
  *
69
- * @param {H} key
69
+ * @param {import("./collector.js").default} collector
70
70
  */
71
- findDataSourceByKey(key) {
72
- return this._dataSourcesByHost.get(key);
71
+ pruneCollectorBranch(collector) {
72
+ let parent = collector.parent;
73
+ if (parent) {
74
+ parent.removeChild(collector);
75
+ }
76
+
77
+ while (parent && parent.children.length === 0) {
78
+ const current = parent;
79
+ parent = current.parent;
80
+ if (parent) {
81
+ parent.removeChild(current);
82
+ } else if (current instanceof DataSource) {
83
+ this.removeDataSource(current);
84
+ }
85
+ }
73
86
  }
74
87
 
75
88
  /**
76
- *
77
89
  * @param {string} name
78
90
  */
79
91
  findNamedDataSource(name) {
80
92
  /** @type {NamedSource} */
81
93
  let namedSource;
82
- /** @type {H[]} */
83
- let hosts = [];
84
-
85
- // Note: If a named sources with the same name are present at multiple locations in the
86
- // view hierarchy, the should actually be exactly the same instance. It's arranged that
87
- // way in the data flow optimization phase.
88
94
 
89
- for (const [host, dataSource] of this._dataSourcesByHost.entries()) {
95
+ // Note: If named sources with the same name are present at multiple locations in the
96
+ // view hierarchy, they should actually be exactly the same instance.
97
+ for (const dataSource of this.#dataSources.values()) {
90
98
  if (dataSource instanceof NamedSource) {
91
99
  if (name == dataSource.identifier) {
92
100
  if (namedSource && namedSource !== dataSource) {
@@ -96,7 +104,6 @@ export default class DataFlow {
96
104
  );
97
105
  }
98
106
  namedSource = dataSource;
99
- hosts.push(host);
100
107
  }
101
108
  }
102
109
  }
@@ -104,39 +111,9 @@ export default class DataFlow {
104
111
  if (namedSource) {
105
112
  return {
106
113
  dataSource: namedSource,
107
- hosts,
108
114
  };
109
115
  }
110
116
  }
111
117
 
112
- /**
113
- *
114
- * @param {import("./collector.js").default} collector
115
- * @param {H} key
116
- */
117
- addCollector(collector, key) {
118
- this._collectorsByHost.set(key, collector);
119
- collector.observers.push((collector) =>
120
- this._relayObserverCallback(collector, key)
121
- );
122
- }
123
-
124
- /**
125
- *
126
- * @param {H} key
127
- */
128
- findCollectorByKey(key) {
129
- return this._collectorsByHost.get(key);
130
- }
131
-
132
- /**
133
- * Allows the flow nodes to perform final initialization after the flow
134
- * structure has been built and optimized.
135
- * Must be called before any data are to be propagated.
136
- */
137
- initialize() {
138
- for (const ds of this.dataSources) {
139
- ds.visit((node) => node.initialize());
140
- }
141
- }
118
+ // Initialization is handled by subtree helpers to avoid global init order.
142
119
  }
@@ -1,5 +1,38 @@
1
- import { describe, test } from "vitest";
1
+ import { describe, expect, test } from "vitest";
2
+ import DataFlow from "./dataFlow.js";
3
+ import DataSource from "./sources/dataSource.js";
4
+ import Collector from "./collector.js";
2
5
 
3
6
  describe("DataFlow", () => {
4
- test.todo("TODO");
7
+ test("removes sources and collectors and clears observers", () => {
8
+ const flow = new DataFlow();
9
+
10
+ const sourceA = new DataSource(/** @type {any} */ ({}));
11
+ const sourceB = new DataSource(/** @type {any} */ ({}));
12
+
13
+ flow.addDataSource(sourceA);
14
+ flow.addDataSource(sourceB);
15
+
16
+ const collector = new Collector();
17
+ flow.addCollector(collector);
18
+
19
+ let called = false;
20
+ collector.observe(() => {
21
+ called = true;
22
+ });
23
+
24
+ expect(flow.dataSources).toContain(sourceA);
25
+ expect(flow.collectors).toContain(collector);
26
+ expect(collector.observers.size).toBe(1);
27
+
28
+ flow.removeDataSource(sourceA);
29
+ flow.removeCollector(collector);
30
+
31
+ expect(flow.dataSources).not.toContain(sourceA);
32
+ expect(flow.collectors).not.toContain(collector);
33
+
34
+ expect(collector.observers.size).toBe(0);
35
+ expect(called).toBe(false);
36
+ expect(flow.dataSources).toContain(sourceB);
37
+ });
5
38
  });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @typedef {object} FlowHandle
3
+ * @prop {import("./sources/dataSource.js").default} [dataSource]
4
+ * @prop {import("./collector.js").default} [collector]
5
+ */
6
+ /**
7
+ * @param {FlowHandle} [handle]
8
+ * @returns {FlowHandle}
9
+ */
10
+ export function createFlowHandle(handle?: FlowHandle): FlowHandle;
11
+ export type FlowHandle = {
12
+ dataSource?: import("./sources/dataSource.js").default;
13
+ collector?: import("./collector.js").default;
14
+ };
15
+ //# sourceMappingURL=flowHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowHandle.d.ts","sourceRoot":"","sources":["../../../src/data/flowHandle.js"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,0CAHW,UAAU,GACR,UAAU,CAItB;;iBAVS,OAAO,yBAAyB,EAAE,OAAO;gBACzC,OAAO,gBAAgB,EAAE,OAAO"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @typedef {object} FlowHandle
3
+ * @prop {import("./sources/dataSource.js").default} [dataSource]
4
+ * @prop {import("./collector.js").default} [collector]
5
+ */
6
+
7
+ /**
8
+ * @param {FlowHandle} [handle]
9
+ * @returns {FlowHandle}
10
+ */
11
+ export function createFlowHandle(handle = {}) {
12
+ return handle;
13
+ }