@longline/aqua-ui 1.0.339 → 1.0.340

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 (251) hide show
  1. package/containers/Anchor/Anchor.d.ts +5 -0
  2. package/containers/Anchor/Anchor.js +20 -8
  3. package/containers/Dock/Dock.d.ts +5 -0
  4. package/containers/Dock/Dock.js +1 -1
  5. package/containers/Dock/Dockable.d.ts +5 -0
  6. package/containers/Dock/Dockable.js +20 -12
  7. package/containers/DragBar/DragBar.d.ts +5 -0
  8. package/containers/DragBar/DragBar.js +16 -5
  9. package/containers/Form/Field.d.ts +0 -3
  10. package/containers/Form/Field.js +3 -6
  11. package/containers/Form/Form.js +5 -36
  12. package/containers/Form/Validation.d.ts +1 -1
  13. package/containers/Form/Validation.js +6 -6
  14. package/containers/Form/context/FormContext.d.ts +1 -2
  15. package/containers/Form/context/useForm.d.ts +1 -1
  16. package/containers/Form/elements/BoxWrapper.js +2 -0
  17. package/containers/GlassPane/GlassPane.d.ts +7 -2
  18. package/containers/GlassPane/GlassPane.js +3 -3
  19. package/containers/InfoBox/InfoBox.d.ts +5 -0
  20. package/containers/InfoBox/InfoBox.js +1 -1
  21. package/containers/List/List.d.ts +5 -0
  22. package/containers/List/List.js +1 -1
  23. package/containers/List/ListCell.d.ts +5 -0
  24. package/containers/List/ListCell.js +1 -1
  25. package/containers/List/ListRow.d.ts +7 -2
  26. package/containers/List/ListRow.js +1 -1
  27. package/containers/Message/Error.d.ts +2 -0
  28. package/containers/Message/Error.js +1 -1
  29. package/containers/Message/Message.d.ts +5 -0
  30. package/containers/Message/Message.js +1 -1
  31. package/containers/Message/NoData.d.ts +2 -0
  32. package/containers/Message/NoData.js +1 -1
  33. package/containers/Message/NoFilteredData.d.ts +2 -0
  34. package/containers/Message/NoFilteredData.js +1 -1
  35. package/containers/Openable/Openable.d.ts +5 -0
  36. package/containers/Openable/Openable.js +8 -8
  37. package/containers/PublicRoute/PublicRoute.d.ts +9 -1
  38. package/containers/PublicRoute/PublicRoute.js +3 -7
  39. package/containers/Tabs/Pane.d.ts +5 -0
  40. package/containers/Tabs/Pane.js +3 -3
  41. package/containers/Tabs/Tabs.d.ts +5 -0
  42. package/containers/Tabs/Tabs.js +3 -3
  43. package/controls/Chip/Chip.d.ts +15 -3
  44. package/controls/Chip/Chip.js +7 -6
  45. package/controls/CircularProgress/CircularProgress.d.ts +11 -0
  46. package/controls/CircularProgress/CircularProgress.js +19 -11
  47. package/controls/Dropzone/Dropzone.d.ts +11 -1
  48. package/controls/Dropzone/Dropzone.js +18 -7
  49. package/controls/Fab/Fab.d.ts +14 -6
  50. package/controls/Fab/Fab.js +7 -20
  51. package/controls/Ghost/Ghost.js +3 -3
  52. package/controls/Gradient/Gradient.d.ts +5 -0
  53. package/controls/Gradient/Gradient.js +7 -4
  54. package/controls/Histogram/Histogram.d.ts +8 -2
  55. package/controls/Histogram/Histogram.js +9 -9
  56. package/controls/Histogram/HistogramBar.d.ts +2 -2
  57. package/controls/Icon/Icon.d.ts +10 -4
  58. package/controls/Icon/Icon.js +23 -6
  59. package/controls/Key/Key.d.ts +5 -0
  60. package/controls/Key/Key.js +2 -5
  61. package/controls/LinearChart/LinearChart.d.ts +9 -0
  62. package/controls/LinearChart/LinearChart.js +11 -6
  63. package/controls/ListButton/ListButton.d.ts +46 -3
  64. package/controls/ListButton/ListButton.js +70 -9
  65. package/controls/ListView/ColumnsManager/ColumnDraggable.js +11 -5
  66. package/controls/ListView/ColumnsManager/SourceColumns.js +1 -1
  67. package/controls/ListView/IListViewProps.d.ts +9 -2
  68. package/controls/ListView/ListView.js +13 -12
  69. package/controls/ListView/defaults.d.ts +3 -0
  70. package/controls/ListView/defaults.js +6 -0
  71. package/controls/ListView/elements/Body.d.ts +1 -1
  72. package/controls/ListView/elements/Body.js +23 -12
  73. package/controls/ListView/elements/Ghost.js +3 -2
  74. package/controls/ListView/elements/Header.js +3 -2
  75. package/controls/ListView/elements/HeaderCell.js +3 -3
  76. package/controls/ListView/elements/Table.js +16 -10
  77. package/controls/Mouse/Mouse.d.ts +6 -4
  78. package/controls/Mouse/Mouse.js +15 -8
  79. package/controls/PrimaryButton/PrimaryButton.d.ts +9 -3
  80. package/controls/PrimaryButton/PrimaryButton.js +5 -5
  81. package/controls/Progress/Progress.d.ts +9 -0
  82. package/controls/Progress/Progress.js +12 -8
  83. package/controls/SecondaryButton/SecondaryButton.d.ts +8 -3
  84. package/controls/SecondaryButton/SecondaryButton.js +1 -1
  85. package/controls/SpeechRecognizer/EditorRegistry.js +1 -2
  86. package/controls/SpeechRecognizer/SpeechRecognizer.d.ts +9 -1
  87. package/controls/SpeechRecognizer/SpeechRecognizer.js +16 -9
  88. package/controls/TabBar/TabBar.d.ts +5 -0
  89. package/controls/TabBar/TabBar.js +14 -6
  90. package/controls/TabBar/Underliner.js +1 -1
  91. package/controls/TertiaryButton/TertiaryButton.d.ts +9 -3
  92. package/controls/TertiaryButton/TertiaryButton.js +5 -3
  93. package/controls/ToggleButton/ToggleButton.d.ts +8 -2
  94. package/controls/ToggleButton/ToggleButton.js +1 -1
  95. package/controls/View/View.d.ts +5 -0
  96. package/controls/View/View.js +1 -1
  97. package/formatters/CountryFormatter/CountryFormatter.d.ts +3 -2
  98. package/formatters/CountryFormatter/CountryUtil.d.ts +3 -3
  99. package/formatters/DateTimeFormatter/DateTimeFormatter.d.ts +11 -10
  100. package/formatters/DateTimeFormatter/elements/Custom.d.ts +1 -1
  101. package/formatters/DateTimeFormatter/elements/DistanceDate.d.ts +1 -1
  102. package/formatters/DateTimeFormatter/elements/LongDate.d.ts +1 -1
  103. package/formatters/DateTimeFormatter/elements/LongDateTime.d.ts +1 -1
  104. package/formatters/DateTimeFormatter/elements/LongTime.d.ts +1 -1
  105. package/formatters/DateTimeFormatter/elements/Month.d.ts +1 -1
  106. package/formatters/DateTimeFormatter/elements/ShortDate.d.ts +1 -1
  107. package/formatters/DateTimeFormatter/elements/ShortDateTime.d.ts +1 -1
  108. package/formatters/DateTimeFormatter/elements/ShortTime.d.ts +1 -1
  109. package/formatters/DivisionFormatter/DivisionFormatter.d.ts +2 -2
  110. package/formatters/DivisionFormatter/DivisionFormatter.js +1 -1
  111. package/formatters/DivisionFormatter/DivisionUtil.d.ts +1 -1
  112. package/formatters/DivisionFormatter/DivisionUtil.js +5 -3
  113. package/formatters/FilesizeFormatter/FilesizeFormatter.d.ts +3 -3
  114. package/formatters/GIS/CoordinateFormatter.d.ts +2 -2
  115. package/formatters/GIS/LatitudeFormatter.d.ts +2 -2
  116. package/formatters/GIS/LongitudeFormatter.d.ts +2 -2
  117. package/formatters/HumanFormatter/HumanFormatter.d.ts +3 -3
  118. package/formatters/NumberFormatter/NumberFormatter.d.ts +3 -3
  119. package/formatters/PhoneFormatter/PhoneFormatter.d.ts +3 -3
  120. package/formatters/StringFormatter/StringFormatter.d.ts +3 -3
  121. package/formatters/StringFormatter/StringFormatter.js +1 -4
  122. package/helper/DMS.d.ts +1 -1
  123. package/helper/DMS.js +2 -2
  124. package/hooks/useOutsideClose/useOutsideClose.js +20 -11
  125. package/hooks/useSpeechAIRecorder/useSpeechAIRecorder.js +10 -7
  126. package/index.js +1 -0
  127. package/inputs/DateInput/Body.d.ts +2 -2
  128. package/inputs/DateInput/Body.js +11 -7
  129. package/inputs/DateInput/Calendar.d.ts +1 -1
  130. package/inputs/DateInput/Calendar.js +3 -5
  131. package/inputs/DateInput/DateInput.d.ts +11 -3
  132. package/inputs/DateInput/DateInput.js +11 -3
  133. package/inputs/DateInput/Day.d.ts +1 -1
  134. package/inputs/DateInput/InfiniteList.js +6 -3
  135. package/inputs/DateInput/Navbar.js +3 -2
  136. package/inputs/DateInput/NumericInput.js +3 -0
  137. package/inputs/DateInput/Selector.d.ts +1 -1
  138. package/inputs/DateInput/Selector.js +9 -6
  139. package/inputs/Dropdown/Body.d.ts +2 -2
  140. package/inputs/Dropdown/Column.d.ts +1 -1
  141. package/inputs/Dropdown/Dropdown.d.ts +5 -0
  142. package/inputs/Dropdown/Dropdown.js +36 -63
  143. package/inputs/Dropdown/Pill.js +1 -1
  144. package/inputs/Dropdown/Selection.js +1 -1
  145. package/inputs/Editor/Editor.d.ts +5 -0
  146. package/inputs/Editor/Editor.js +16 -6
  147. package/inputs/Editor/buttons/SpeechAIButton.js +2 -0
  148. package/inputs/Editor/buttons/TextAIButton.d.ts +0 -13
  149. package/inputs/Editor/buttons/TextAIButton.js +30 -14
  150. package/inputs/Editor/buttons/TextAIMenu.js +1 -1
  151. package/inputs/Editor/menu/MenuBar.d.ts +1 -1
  152. package/inputs/Editor/menu/MenuBar.js +1 -1
  153. package/inputs/Editor/menu/MenuButton.js +1 -1
  154. package/inputs/Input/Clear.js +1 -1
  155. package/inputs/Input/Input.d.ts +5 -0
  156. package/inputs/Input/Input.js +8 -6
  157. package/inputs/Input/InputWrapper.d.ts +2 -0
  158. package/inputs/Input/InputWrapper.js +1 -1
  159. package/inputs/Input/Reveal.js +1 -1
  160. package/inputs/MonthRange/Body.d.ts +1 -1
  161. package/inputs/MonthRange/Calendar.d.ts +2 -2
  162. package/inputs/MonthRange/Calendar.js +6 -9
  163. package/inputs/MonthRange/MonthRange.d.ts +7 -1
  164. package/inputs/MonthRange/MonthRange.js +14 -6
  165. package/inputs/MonthRange/Selector.d.ts +1 -1
  166. package/inputs/MonthRange/Selector.js +12 -11
  167. package/inputs/PhoneInput/PhoneInput.d.ts +5 -0
  168. package/inputs/PhoneInput/PhoneInput.js +2 -2
  169. package/inputs/Selector/Selector.d.ts +5 -0
  170. package/inputs/Selector/Selector.js +4 -1
  171. package/inputs/Slider/Slider.d.ts +75 -22
  172. package/inputs/Slider/Slider.js +104 -22
  173. package/inputs/Textarea/Textarea.d.ts +5 -5
  174. package/inputs/Textarea/Textarea.js +3 -2
  175. package/map/Map/Map.d.ts +2 -2
  176. package/map/Map/Map.js +20 -14
  177. package/map/PositionsManager/PositionBox.js +7 -3
  178. package/map/PositionsManager/PositionsManager.js +33 -13
  179. package/map/controls/CompassButton/CompassButton.js +1 -1
  180. package/map/controls/FullscreenButton/FullscreenButton.js +1 -1
  181. package/map/controls/Geocoder/Geocoder.js +28 -14
  182. package/map/controls/Geocoder/GeocoderApi.js +2 -0
  183. package/map/controls/Geocoder/GeocoderSelector.js +1 -1
  184. package/map/controls/Graticule/Graticule.js +1 -5
  185. package/map/controls/MapLoader/MapLoader.js +1 -1
  186. package/map/controls/ScaleControl/ScaleControl.js +1 -1
  187. package/map/controls/ZoomInButton/ZoomInButton.js +1 -1
  188. package/map/controls/ZoomOutButton/ZoomOutButton.d.ts +1 -1
  189. package/map/controls/ZoomOutButton/ZoomOutButton.js +2 -2
  190. package/map/controls/base/MapButton/MapButton.d.ts +8 -2
  191. package/map/controls/base/MapButton/MapButton.js +11 -2
  192. package/map/controls/base/MapControl/MapControl.d.ts +5 -0
  193. package/map/controls/base/MapControl/MapControl.js +10 -7
  194. package/map/layers/ClusterLayer/ClusterLayer.d.ts +1 -1
  195. package/map/layers/ClusterLayer/ClusterLayer.js +7 -3
  196. package/map/layers/HtmlMarkerLayer/HtmlMarkerLayer.js +8 -4
  197. package/map/layers/IdwBlendLayer/IdwBlendLayer.js +9 -4
  198. package/map/layers/IdwLayer/IdwLayer.d.ts +2 -1
  199. package/map/layers/IdwLayer/IdwLayer.js +271 -215
  200. package/map/layers/InterpolationLayer/ContoursFragmentShader.d.ts +1 -1
  201. package/map/layers/InterpolationLayer/ContoursFragmentShader.js +1 -1
  202. package/map/layers/InterpolationLayer/InterpolationLayer.d.ts +4 -3
  203. package/map/layers/InterpolationLayer/InterpolationLayer.js +362 -275
  204. package/map/layers/ParticlesLayer/ParticlesLayer.d.ts +8 -7
  205. package/map/layers/ParticlesLayer/ParticlesLayer.js +528 -404
  206. package/map/markers/ClusterMarker/ClusterMarker.d.ts +6 -1
  207. package/map/markers/ClusterMarker/ClusterMarker.js +15 -6
  208. package/map/markers/RiskMarker/RiskMarker.d.ts +5 -1
  209. package/map/markers/RiskMarker/RiskMarker.js +4 -4
  210. package/modules/CountryDropdown/CountryDropdown.js +10 -1
  211. package/modules/Filter/Filter.d.ts +5 -0
  212. package/modules/Filter/Filter.js +10 -6
  213. package/modules/Globe/Globe.d.ts +5 -0
  214. package/modules/Globe/Globe.js +4 -4
  215. package/modules/MainMenu/Item.d.ts +9 -2
  216. package/modules/MainMenu/Item.js +8 -5
  217. package/modules/MainMenu/MainMenu.d.ts +5 -0
  218. package/modules/MainMenu/MainMenu.js +1 -1
  219. package/modules/ParticleGlobe/GL.d.ts +1 -1
  220. package/modules/ParticleGlobe/ParticleGlobe.d.ts +5 -0
  221. package/modules/ParticleGlobe/ParticleGlobe.js +69 -40
  222. package/modules/Public/Public.d.ts +5 -0
  223. package/modules/Public/Public.js +3 -3
  224. package/package.json +1 -1
  225. package/services/Auth/Auth.js +13 -7
  226. package/services/Auth/AuthContext.js +9 -1
  227. package/services/Dialog/Dialog.d.ts +7 -2
  228. package/services/Dialog/Dialog.js +7 -6
  229. package/services/Dialog/DialogWindow.d.ts +3 -1
  230. package/services/Dialog/DialogWindow.js +1 -1
  231. package/services/Dialog/XhrDialog.d.ts +1 -1
  232. package/services/Toast/Toast.js +5 -3
  233. package/services/Toast/ToastContainer.js +3 -1
  234. package/services/Toast/ToastContext.d.ts +1 -1
  235. package/services/Toast/ToastProvider.js +2 -0
  236. package/map/layers/HtmlMarkerLayer/HtmlMarkerLayer copy.d.ts +0 -35
  237. package/map/layers/HtmlMarkerLayer/HtmlMarkerLayer copy.js +0 -176
  238. package/modules/Root/Content.d.ts +0 -16
  239. package/modules/Root/Content.js +0 -25
  240. package/modules/Root/Overlay.d.ts +0 -23
  241. package/modules/Root/Overlay.js +0 -33
  242. package/modules/Root/Root.d.ts +0 -10
  243. package/modules/Root/Root.js +0 -46
  244. package/modules/Root/Shader.d.ts +0 -15
  245. package/modules/Root/Shader.js +0 -24
  246. package/modules/Root/Sidebar.d.ts +0 -13
  247. package/modules/Root/Sidebar.js +0 -24
  248. package/modules/Root/index.d.ts +0 -1
  249. package/modules/Root/index.js +0 -1
  250. package/modules/Root/stories/SampleContent.d.ts +0 -7
  251. package/modules/Root/stories/SampleContent.js +0 -44
@@ -43,415 +43,544 @@ import { PositionComputeFragmentShader } from './PositionComputeFragmentShader';
43
43
  import { RgbColor } from '../../../helper/RgbColor';
44
44
  var TEXTURE_WIDTH = 1024;
45
45
  var TEXTURE_HEIGHT = 1024;
46
+ // Default prop values, referenced both by the ParticlesLayerBase fallbacks and
47
+ // the ParticlesLayer wrapper below.
48
+ var DEFAULT_PARTICLES = 80;
49
+ var DEFAULT_DENSITY = 40;
50
+ var DEFAULT_DELAY = 0;
51
+ var DEFAULT_POINT_SIZE = 1.0;
52
+ var DEFAULT_MIN_ZOOM = 0;
53
+ var DEFAULT_MAX_ZOOM = 99;
54
+ var DEFAULT_MIN_SPEED = 0.02;
55
+ var DEFAULT_MAX_SPEED = 0.15;
56
+ // Accepted ranges, shared by the component clamps and the story sliders.
57
+ var MIN_PARTICLES = 1;
58
+ var MAX_PARTICLES = 200;
59
+ var MIN_DENSITY = 2; // >= 2 also avoids the density-1 divide-by-zero in the grid.
60
+ var MAX_DENSITY = 100;
61
+ var MAX_DELAY = 10;
62
+ var MIN_POINT_SIZE = 1;
63
+ var MAX_POINT_SIZE = 10;
64
+ var MIN_SPEED = 0;
65
+ var MAX_SPEED = 1;
66
+ var DEFAULT_GRADIENT_STOPS = [
67
+ { pos: 0.0, color: '#ffffffff' },
68
+ { pos: 0.25, color: '#5c5cffff' },
69
+ { pos: 0.5, color: '#5c5cff00' },
70
+ { pos: 1.0, color: '#5c5cff00' }, // transparent blue
71
+ ];
72
+ //
73
+ // Convert a hex color (e.g. #ff0022) to an [r,g,b,a] array,
74
+ // where r,g,b,a are in the 0.0-1.0 range.
75
+ //
76
+ var colorToRGBA = function (color) {
77
+ var rgb = RgbColor.FromString(color);
78
+ return [rgb.red / 255.0, rgb.green / 255.0, rgb.blue / 255.0, rgb.alpha];
79
+ };
80
+ //
81
+ // Coerce a control value (which may be "" while typing, undefined, or invalid)
82
+ // to a number, or NaN when it is empty/invalid. Note Number("") is 0, so empty
83
+ // strings are handled explicitly rather than silently becoming zero.
84
+ //
85
+ var toNumber = function (value) {
86
+ if (value === '' || value === null || value === undefined)
87
+ return NaN;
88
+ var n = Number(value);
89
+ return Number.isFinite(n) ? n : NaN;
90
+ };
91
+ //
92
+ // Clamp to an integer in [min, max], falling back to `fallback` on empty/invalid
93
+ // input. Guards buffer/texture sizing and the animation modulo against
94
+ // NaN/degenerate values.
95
+ //
96
+ var clampInt = function (value, fallback, min, max) {
97
+ var n = toNumber(value);
98
+ if (Number.isNaN(n))
99
+ return fallback;
100
+ return Math.max(min, Math.min(max, Math.floor(n)));
101
+ };
102
+ //
103
+ // Clamp to a (possibly fractional) number in [min, max], falling back to
104
+ // `fallback` on empty/invalid input.
105
+ //
106
+ var clampFloat = function (value, fallback, min, max) {
107
+ var n = toNumber(value);
108
+ if (Number.isNaN(n))
109
+ return fallback;
110
+ return Math.max(min, Math.min(max, n));
111
+ };
112
+ //
113
+ // Convert an IPoint array to triangles for one field (u or v). Each triangle
114
+ // gets properties a,b,c with the field value at each vertex. Returns the value
115
+ // range and a flat [x,y,value, ...] coordinate array.
116
+ //
117
+ var buildGeometry = function (data, field) {
118
+ var points = featureCollection((data !== null && data !== void 0 ? data : [])
119
+ .filter(function (dp) { return !isNaN(dp[field]); }) // Filter out any NaN values.
120
+ .map(function (dp) { return point([dp.longitude, dp.latitude], { 'v': dp[field] }); }));
121
+ var polys = tin(points, 'v');
122
+ // Find min and max values in GeoJSON:
123
+ var minValue = Infinity;
124
+ var maxValue = -Infinity;
125
+ var len = polys.features.length;
126
+ while (len--) {
127
+ var properties = polys.features[len].properties;
128
+ // Each triangle carries three vertex values (a, b, c). A data point may
129
+ // only ever appear as b or c, so scan all three to find the true range;
130
+ // otherwise out-of-range vertices normalize outside 0..1 and get clamped
131
+ // when written to the byte texture.
132
+ for (var _i = 0, _a = ['a', 'b', 'c']; _i < _a.length; _i++) {
133
+ var key = _a[_i];
134
+ var value = properties[key];
135
+ minValue = value < minValue ? value : minValue;
136
+ maxValue = value > maxValue ? value : maxValue;
137
+ }
138
+ }
139
+ // Convert dataset to triangle geometry.
140
+ // Result is a list of v1,v2,v3, v1,v2,v3, ...
141
+ // where each vector has (x,y,value).
142
+ var coords = [];
143
+ var LAT = 1;
144
+ var LON = 0;
145
+ // Avoid a 0/0 = NaN normalization when all values are equal.
146
+ var deltaValue = (maxValue - minValue) || 1;
147
+ polys.features.map(function (feature) {
148
+ var coord = MercatorCoordinate.fromLngLat({ lng: feature.geometry.coordinates[0][0][LON], lat: feature.geometry.coordinates[0][0][LAT] });
149
+ coords.push(coord.x, coord.y, (feature.properties['a'] - minValue) / deltaValue);
150
+ coord = MercatorCoordinate.fromLngLat({ lng: feature.geometry.coordinates[0][1][LON], lat: feature.geometry.coordinates[0][1][LAT] });
151
+ coords.push(coord.x, coord.y, (feature.properties['b'] - minValue) / deltaValue);
152
+ coord = MercatorCoordinate.fromLngLat({ lng: feature.geometry.coordinates[0][2][LON], lat: feature.geometry.coordinates[0][2][LAT] });
153
+ coords.push(coord.x, coord.y, (feature.properties['c'] - minValue) / deltaValue);
154
+ });
155
+ return [minValue, maxValue, coords];
156
+ };
157
+ //
158
+ // Check if two matrices are equal.
159
+ //
160
+ var matricesEqual = function (a, b) {
161
+ if (!a || !b)
162
+ return false;
163
+ for (var i = 0; i < 16; i++) {
164
+ if (a[i] !== b[i])
165
+ return false;
166
+ }
167
+ return true;
168
+ };
46
169
  var ParticlesLayerBase = function (props) {
47
170
  var map = useMap();
48
- var uvProgram = React.useRef(null);
49
- var particlesProgram = React.useRef(null);
50
- var bufferU = React.useRef(null);
51
- var bufferV = React.useRef(null);
52
- var bufferScreen = React.useRef(null);
53
- var numTrianglesU = React.useRef(null);
54
- var numTrianglesV = React.useRef(null);
55
- var minU = React.useRef(0);
56
- var maxU = React.useRef(0);
57
- var minV = React.useRef(0);
58
- var maxV = React.useRef(0);
59
- // Combined UV texture: U in R channel, V in G channel, alpha indicates valid data
60
- var textureUV = React.useRef(null);
61
- var fboUV = React.useRef(null);
62
- // Position texture: stores pre-computed particle positions (X in RG, Y in BA)
63
- var positionProgram = React.useRef(null);
64
- var texturePosition = React.useRef(null);
65
- var fboPosition = React.useRef(null);
66
- var bufferQuad = React.useRef(null);
67
- // Dynamic position texture dimensions (computed based on density * density * particles)
68
- var posTexWidth = React.useRef(0);
69
- var posTexHeight = React.useRef(0);
171
+ // The custom-layer callbacks are captured by Mapbox at add-time, so render
172
+ // reads live prop values through this ref rather than a stale closure.
173
+ var propsRef = React.useRef(props);
174
+ propsRef.current = props;
175
+ // Animation state is a component-level (not per-generation) concern: it tracks
176
+ // time, and render reads the current frame each draw.
70
177
  var frame = React.useRef(0);
71
178
  var skip = React.useRef(0);
72
- // requestAnimationFrame ID:
73
179
  var animation = React.useRef(null);
74
- // Last matrix used to render UV textures (for caching):
75
- var lastMatrix = React.useRef(null);
76
- // Current time is used to force component rerender when props change:
77
- var _a = React.useState(0), time = _a[0], setTime = _a[1];
78
- // Force component rerender when props change:
180
+ // Animation loop: advance the particle frame (respecting delay) and repaint.
79
181
  React.useEffect(function () {
80
- window.cancelAnimationFrame(animation.current);
81
- setTime(Date.now());
82
- frame.current = 0;
83
- skip.current = 0;
84
- lastMatrix.current = null; // Reset matrix cache so UV textures are re-rendered
85
- animation.current = window.requestAnimationFrame(draw);
86
- }, [props.data, props.gradientStops, props.particles, props.density, props.delay, props.pointSize, props.minSpeed, props.maxSpeed]);
87
- var draw = function () {
88
- skip.current++;
89
- if (skip.current > props.delay) {
90
- skip.current = 0;
91
- frame.current = (frame.current + 1) % props.particles;
92
- map.current.triggerRepaint();
93
- }
182
+ var draw = function () {
183
+ var _a;
184
+ var p = propsRef.current;
185
+ var particles = clampInt(p.particles, DEFAULT_PARTICLES, MIN_PARTICLES, MAX_PARTICLES);
186
+ var delay = clampInt(p.delay, DEFAULT_DELAY, 0, MAX_DELAY);
187
+ if (!Number.isFinite(frame.current))
188
+ frame.current = 0; // Recover from any bad state.
189
+ skip.current++;
190
+ if (skip.current > delay) {
191
+ skip.current = 0;
192
+ frame.current = (frame.current + 1) % particles;
193
+ (_a = map.current) === null || _a === void 0 ? void 0 : _a.triggerRepaint();
194
+ }
195
+ animation.current = window.requestAnimationFrame(draw);
196
+ };
94
197
  animation.current = window.requestAnimationFrame(draw);
95
- };
96
- React.useEffect(function () {
97
198
  return function () {
98
- window.cancelAnimationFrame(animation.current);
199
+ if (animation.current !== null)
200
+ window.cancelAnimationFrame(animation.current);
99
201
  };
100
- }, []);
101
- //
102
- // Convert a hex color (e.g. #ff0022) to an [r,g,b,a] array,
103
- // where r,g,b,a are in the 0.0-1.0 range.
104
- //
105
- var colorToRGBA = function (color) {
106
- var rgb = RgbColor.FromString(color);
107
- return [rgb.red / 255.0, rgb.green / 255.0, rgb.blue / 255.0, rgb.alpha];
108
- };
109
- //
110
- // Convert IPoint array to triangles. Each triangle will have properties a,b,c
111
- // with a value that corresponds to the [field] key of the input data.
112
- //
113
- // Returns triangle coords, and also min and max value found.
114
- //
115
- var getGeometry = function (field) {
116
- var _a;
117
- // Each poly (triangle) gets a,b,c properties: one depth value for each point.
118
- // Convert dataset points to Turf feature collection:
119
- var points = featureCollection(((_a = props.data) !== null && _a !== void 0 ? _a : [])
120
- .filter(function (dp) { return !isNaN(dp[field]); }) // Filter out any NaN values.
121
- .map(function (dp) {
122
- return point([dp.longitude, dp.latitude], { 'v': dp[field] });
123
- }));
124
- var polys = tin(points, 'v');
125
- // Find min and max values in GeoJSON:
126
- var minValue = Infinity;
127
- var maxValue = -Infinity;
128
- var len = polys.features.length;
129
- while (len--) {
130
- var value = polys.features[len].properties['a'];
131
- minValue = value < minValue ? value : minValue;
132
- maxValue = value > maxValue ? value : maxValue;
133
- }
134
- // Convert dataset to triangle geometry.
135
- // Result is a list of v1,v2,v3, v1,v2,v3, ...
136
- // where each vector has (x,y,value).
137
- var coords = [];
138
- var LAT = 1;
139
- var LON = 0;
140
- var deltaValue = maxValue - minValue;
141
- polys.features.map(function (feature) {
142
- var coord = MercatorCoordinate.fromLngLat({ lng: feature.geometry.coordinates[0][0][LON], lat: feature.geometry.coordinates[0][0][LAT] });
143
- coords.push(coord.x, coord.y, (feature.properties['a'] - minValue) / deltaValue);
144
- coord = MercatorCoordinate.fromLngLat({ lng: feature.geometry.coordinates[0][1][LON], lat: feature.geometry.coordinates[0][1][LAT] });
145
- coords.push(coord.x, coord.y, (feature.properties['b'] - minValue) / deltaValue);
146
- coord = MercatorCoordinate.fromLngLat({ lng: feature.geometry.coordinates[0][2][LON], lat: feature.geometry.coordinates[0][2][LAT] });
147
- coords.push(coord.x, coord.y, (feature.properties['c'] - minValue) / deltaValue);
148
- });
149
- return [minValue, maxValue, coords];
150
- };
151
- // Geometries are only calculated when data changes:
152
- var getGeometryU = React.useMemo(function () { return getGeometry("u"); }, [props.data]);
153
- var getGeometryV = React.useMemo(function () { return getGeometry("v"); }, [props.data]);
154
- var createUVProgram = function (gl) {
155
- // create a vertex shader
156
- var vertexShader = gl.createShader(gl.VERTEX_SHADER);
157
- gl.shaderSource(vertexShader, UVVertexShader);
158
- gl.compileShader(vertexShader);
159
- // create a fragment shader
160
- var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
161
- gl.shaderSource(fragmentShader, UVFragmentShader);
162
- gl.compileShader(fragmentShader);
163
- // link the two shaders into a WebGL program
164
- uvProgram.current = gl.createProgram();
165
- gl.attachShader(uvProgram.current, vertexShader);
166
- gl.attachShader(uvProgram.current, fragmentShader);
167
- gl.linkProgram(uvProgram.current);
168
- };
169
- var createParticlesProgram = function (gl) {
170
- // create a vertex shader
171
- var vertexShader = gl.createShader(gl.VERTEX_SHADER);
172
- gl.shaderSource(vertexShader, ParticlesVertexShader);
173
- gl.compileShader(vertexShader);
174
- // create a fragment shader
175
- var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
176
- gl.shaderSource(fragmentShader, ParticlesFragmentShader);
177
- gl.compileShader(fragmentShader);
178
- // link the two shaders into a WebGL program
179
- particlesProgram.current = gl.createProgram();
180
- gl.attachShader(particlesProgram.current, vertexShader);
181
- gl.attachShader(particlesProgram.current, fragmentShader);
182
- gl.linkProgram(particlesProgram.current);
183
- };
184
- var createPositionComputeProgram = function (gl) {
185
- var vertexShader = gl.createShader(gl.VERTEX_SHADER);
186
- gl.shaderSource(vertexShader, PositionComputeVertexShader);
187
- gl.compileShader(vertexShader);
188
- var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
189
- gl.shaderSource(fragmentShader, PositionComputeFragmentShader);
190
- gl.compileShader(fragmentShader);
191
- positionProgram.current = gl.createProgram();
192
- gl.attachShader(positionProgram.current, vertexShader);
193
- gl.attachShader(positionProgram.current, fragmentShader);
194
- gl.linkProgram(positionProgram.current);
195
- };
196
- var createPositionTexture = function (gl) {
197
- // Compute texture dimensions to fit all particles
198
- // Total particles = density * density * particles
199
- var totalParticles = props.density * props.density * props.particles;
200
- // Find suitable texture dimensions (width should be power of 2 for compatibility)
201
- // Use a width that balances the texture shape
202
- var width = 256;
203
- while (width * width < totalParticles) {
204
- width *= 2;
205
- }
206
- var height = Math.ceil(totalParticles / width);
207
- posTexWidth.current = width;
208
- posTexHeight.current = height;
209
- var texture = gl.createTexture();
210
- gl.bindTexture(gl.TEXTURE_2D, texture);
211
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
212
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
213
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
214
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
215
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
216
- return texture;
217
- };
218
- var createQuadBuffer = function (gl) {
219
- // Full-screen quad (two triangles covering clip space)
220
- bufferQuad.current = gl.createBuffer();
221
- gl.bindBuffer(gl.ARRAY_BUFFER, bufferQuad.current);
222
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
223
- -1, -1,
224
- 1, -1,
225
- -1, 1,
226
- -1, 1,
227
- 1, -1,
228
- 1, 1
229
- ]), gl.STATIC_DRAW);
230
- };
231
- var createBufferU = function (gl) {
232
- var min = getGeometryU[0], max = getGeometryU[1], geometry = getGeometryU[2];
233
- minU.current = min;
234
- maxU.current = max;
235
- numTrianglesU.current = geometry.length / 9;
236
- // Create and initialize a WebGLBuffer to store vertex data.
237
- // Each element will have 3 components (x,y,value).
238
- bufferU.current = gl.createBuffer();
239
- gl.bindBuffer(gl.ARRAY_BUFFER, bufferU.current);
240
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geometry), gl.STATIC_DRAW);
241
- };
242
- var createBufferV = function (gl) {
243
- var min = getGeometryV[0], max = getGeometryV[1], geometry = getGeometryV[2];
244
- minV.current = min;
245
- maxV.current = max;
246
- numTrianglesV.current = geometry.length / 9;
247
- // Create and initialize a WebGLBuffer to store vertex data.
248
- // Each element will have 3 components (x,y,value).
249
- bufferV.current = gl.createBuffer();
250
- gl.bindBuffer(gl.ARRAY_BUFFER, bufferV.current);
251
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geometry), gl.STATIC_DRAW);
252
- };
253
- var createBufferScreen = function (gl) {
254
- bufferScreen.current = gl.createBuffer();
255
- gl.bindBuffer(gl.ARRAY_BUFFER, bufferScreen.current);
256
- // Each point has a screen coordinate in range [-1..1]
257
- var coords = [];
258
- for (var y = 0; y < props.density; y++) {
259
- for (var x = 0; x < props.density; x++) {
260
- var offset = Math.floor(Math.random() * props.particles);
261
- // Each point has a number of particles:
262
- for (var i = 0; i < props.particles; i++) {
263
- coords.push(x * 1.98 / (props.density - 1) - 0.99);
264
- coords.push(y * 1.98 / (props.density - 1) - 0.99);
265
- // Each point has an instance index
266
- coords.push(i);
267
- // Each point has a frame offset.
268
- coords.push(offset);
202
+ }, [map]);
203
+ // Triangulation only depends on data; keep it memoized so tweaking density,
204
+ // particle count or speed does not re-run the (expensive) tin() pass.
205
+ var geometry = React.useMemo(function () { return ({
206
+ u: buildGeometry(props.data, 'u'),
207
+ v: buildGeometry(props.data, 'v'),
208
+ }); }, [props.data]);
209
+ // Build a fresh custom layer with its own private WebGL resource holder —
210
+ // whenever an input that requires re-initialising GL state changes (geometry,
211
+ // density, particle count, or the speed remapping baked into the position
212
+ // texture). Each generation owns its resources and frees only those in its own
213
+ // onRemove, so the overlapping add/remove during a react-map-gl remount never
214
+ // clobbers the live generation.
215
+ var layer = React.useMemo(function () {
216
+ // Unique id per generation so the old and new layers coexist cleanly during
217
+ // the remount (old removeLayer + new addLayer both run).
218
+ var id = 'particles-' + Math.random().toString(36).slice(2);
219
+ // Private per-generation GL resources.
220
+ var uvProgram = null;
221
+ var particlesProgram = null;
222
+ var positionProgram = null;
223
+ var bufferU = null;
224
+ var bufferV = null;
225
+ var bufferScreen = null;
226
+ var bufferQuad = null;
227
+ var textureUV = null;
228
+ var fboUV = null;
229
+ var texturePosition = null;
230
+ var fboPosition = null;
231
+ var numTrianglesU = 0;
232
+ var numTrianglesV = 0;
233
+ var minU = 0;
234
+ var maxU = 0;
235
+ var minV = 0;
236
+ var maxV = 0;
237
+ var posTexWidth = 0;
238
+ var posTexHeight = 0;
239
+ var lastMatrix = null;
240
+ var removed = false;
241
+ // Grid parameters are baked into the buffers/textures below, so they are
242
+ // fixed for this generation (a change rebuilds a new generation). Clamped
243
+ // so a transient empty/invalid value never produces degenerate GL state.
244
+ var particles = clampInt(props.particles, DEFAULT_PARTICLES, MIN_PARTICLES, MAX_PARTICLES);
245
+ var density = clampInt(props.density, DEFAULT_DENSITY, MIN_DENSITY, MAX_DENSITY);
246
+ var createUVProgram = function (gl) {
247
+ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
248
+ gl.shaderSource(vertexShader, UVVertexShader);
249
+ gl.compileShader(vertexShader);
250
+ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
251
+ gl.shaderSource(fragmentShader, UVFragmentShader);
252
+ gl.compileShader(fragmentShader);
253
+ uvProgram = gl.createProgram();
254
+ gl.attachShader(uvProgram, vertexShader);
255
+ gl.attachShader(uvProgram, fragmentShader);
256
+ gl.linkProgram(uvProgram);
257
+ // Shaders are linked into the program now; flag them for deletion.
258
+ gl.deleteShader(vertexShader);
259
+ gl.deleteShader(fragmentShader);
260
+ };
261
+ var createParticlesProgram = function (gl) {
262
+ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
263
+ gl.shaderSource(vertexShader, ParticlesVertexShader);
264
+ gl.compileShader(vertexShader);
265
+ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
266
+ gl.shaderSource(fragmentShader, ParticlesFragmentShader);
267
+ gl.compileShader(fragmentShader);
268
+ particlesProgram = gl.createProgram();
269
+ gl.attachShader(particlesProgram, vertexShader);
270
+ gl.attachShader(particlesProgram, fragmentShader);
271
+ gl.linkProgram(particlesProgram);
272
+ // Shaders are linked into the program now; flag them for deletion.
273
+ gl.deleteShader(vertexShader);
274
+ gl.deleteShader(fragmentShader);
275
+ };
276
+ var createPositionComputeProgram = function (gl) {
277
+ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
278
+ gl.shaderSource(vertexShader, PositionComputeVertexShader);
279
+ gl.compileShader(vertexShader);
280
+ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
281
+ gl.shaderSource(fragmentShader, PositionComputeFragmentShader);
282
+ gl.compileShader(fragmentShader);
283
+ positionProgram = gl.createProgram();
284
+ gl.attachShader(positionProgram, vertexShader);
285
+ gl.attachShader(positionProgram, fragmentShader);
286
+ gl.linkProgram(positionProgram);
287
+ // Shaders are linked into the program now; flag them for deletion.
288
+ gl.deleteShader(vertexShader);
289
+ gl.deleteShader(fragmentShader);
290
+ };
291
+ var createPositionTexture = function (gl) {
292
+ // Compute texture dimensions to fit all particles.
293
+ // Total particles = density * density * particles
294
+ var totalParticles = density * density * particles;
295
+ // Find suitable texture dimensions (width should be power of 2).
296
+ var width = 256;
297
+ while (width * width < totalParticles) {
298
+ width *= 2;
299
+ }
300
+ var height = Math.ceil(totalParticles / width);
301
+ posTexWidth = width;
302
+ posTexHeight = height;
303
+ var texture = gl.createTexture();
304
+ gl.bindTexture(gl.TEXTURE_2D, texture);
305
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
306
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
307
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
308
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
309
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
310
+ return texture;
311
+ };
312
+ var createQuadBuffer = function (gl) {
313
+ // Full-screen quad (two triangles covering clip space)
314
+ bufferQuad = gl.createBuffer();
315
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferQuad);
316
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
317
+ -1, -1,
318
+ 1, -1,
319
+ -1, 1,
320
+ -1, 1,
321
+ 1, -1,
322
+ 1, 1
323
+ ]), gl.STATIC_DRAW);
324
+ };
325
+ var createBufferU = function (gl) {
326
+ var _a = geometry.u, min = _a[0], max = _a[1], geo = _a[2];
327
+ minU = min;
328
+ maxU = max;
329
+ numTrianglesU = geo.length / 9;
330
+ bufferU = gl.createBuffer();
331
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferU);
332
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geo), gl.STATIC_DRAW);
333
+ };
334
+ var createBufferV = function (gl) {
335
+ var _a = geometry.v, min = _a[0], max = _a[1], geo = _a[2];
336
+ minV = min;
337
+ maxV = max;
338
+ numTrianglesV = geo.length / 9;
339
+ bufferV = gl.createBuffer();
340
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferV);
341
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geo), gl.STATIC_DRAW);
342
+ };
343
+ var createBufferScreen = function (gl) {
344
+ bufferScreen = gl.createBuffer();
345
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferScreen);
346
+ // Each point has a screen coordinate in range [-1..1]
347
+ var coords = [];
348
+ for (var y = 0; y < density; y++) {
349
+ for (var x = 0; x < density; x++) {
350
+ var offset = Math.floor(Math.random() * particles);
351
+ // Each point has a number of particles:
352
+ for (var i = 0; i < particles; i++) {
353
+ coords.push(x * 1.98 / (density - 1) - 0.99);
354
+ coords.push(y * 1.98 / (density - 1) - 0.99);
355
+ // Each point has an instance index
356
+ coords.push(i);
357
+ // Each point has a frame offset.
358
+ coords.push(offset);
359
+ }
269
360
  }
270
361
  }
271
- }
272
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
273
- };
274
- var createTexture = function (gl) {
275
- var texture = gl.createTexture();
276
- gl.bindTexture(gl.TEXTURE_2D, texture);
277
- // Define size and format of level 0:
278
- var level = 0;
279
- var internalFormat = gl.RGBA;
280
- var border = 0;
281
- var format = gl.RGBA;
282
- var type = gl.UNSIGNED_BYTE;
283
- gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, TEXTURE_WIDTH, TEXTURE_HEIGHT, border, format, type, null);
284
- // Set filtering to NEAREST so there's no interpolation:
285
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
286
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
287
- return texture;
288
- };
289
- var createFrameBuffer = function (gl, texture) {
290
- // Create and bind the framebuffer:
291
- var fbo = gl.createFramebuffer();
292
- gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
293
- // Attach the texture as the first color attachment:
294
- var attachmentPoint = gl.COLOR_ATTACHMENT0;
295
- gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, texture, 0);
296
- return fbo;
297
- };
298
- var onAddLayer = function (map, gl) {
299
- createBufferU(gl);
300
- createBufferV(gl);
301
- createBufferScreen(gl);
302
- createQuadBuffer(gl);
303
- createUVProgram(gl);
304
- createParticlesProgram(gl);
305
- createPositionComputeProgram(gl);
306
- // Single combined texture for both U and V (U in R, V in G)
307
- textureUV.current = createTexture(gl);
308
- fboUV.current = createFrameBuffer(gl, textureUV.current);
309
- // Position texture for pre-computed particle positions
310
- texturePosition.current = createPositionTexture(gl);
311
- fboPosition.current = createFrameBuffer(gl, texturePosition.current);
312
- };
313
- var renderSpeedBuffer = function (gl, matrix, buffer, numTriangles) {
314
- gl.useProgram(uvProgram.current);
315
- // Pass a matrix uniform in:
316
- gl.uniformMatrix4fv(gl.getUniformLocation(uvProgram.current, 'u_matrix'), false, matrix);
317
- // Vertices:
318
- var aPos = gl.getAttribLocation(uvProgram.current, 'a_pos');
319
- var aValue = gl.getAttribLocation(uvProgram.current, 'a_value');
320
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
321
- gl.enableVertexAttribArray(aPos);
322
- gl.enableVertexAttribArray(aValue);
323
- gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 12, 0);
324
- gl.vertexAttribPointer(aValue, 1, gl.FLOAT, false, 12, 8);
325
- gl.enable(gl.BLEND);
326
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
327
- gl.drawArrays(gl.TRIANGLES, 0, numTriangles * 3);
328
- };
329
- //
330
- // Render particle positions to the position texture.
331
- // This moves the expensive trace loop from the particle vertex shader
332
- // to a one-time-per-view-change fragment shader pass.
333
- //
334
- var renderPositionTexture = function (gl) {
335
- gl.useProgram(positionProgram.current);
336
- // Bind position framebuffer
337
- gl.bindFramebuffer(gl.FRAMEBUFFER, fboPosition.current);
338
- gl.viewport(0, 0, posTexWidth.current, posTexHeight.current);
339
- gl.clearColor(0, 0, 0, 0);
340
- gl.clear(gl.COLOR_BUFFER_BIT);
341
- // Disable blending for position computation
342
- gl.disable(gl.BLEND);
343
- // UV texture (already rendered)
344
- gl.activeTexture(gl.TEXTURE0);
345
- gl.bindTexture(gl.TEXTURE_2D, textureUV.current);
346
- gl.uniform1i(gl.getUniformLocation(positionProgram.current, 'uvTexture'), 0);
347
- // UV range uniforms
348
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'minU'), minU.current);
349
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'maxU'), maxU.current);
350
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'minV'), minV.current);
351
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'maxV'), maxV.current);
352
- // Grid parameters
353
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'u_density'), props.density);
354
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'u_particles'), props.particles);
355
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'u_texWidth'), posTexWidth.current);
356
- // Velocity magnitude remapping parameters
357
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'u_minVisMag'), props.minSpeed);
358
- gl.uniform1f(gl.getUniformLocation(positionProgram.current, 'u_maxVisMag'), props.maxSpeed);
359
- // Render full-screen quad
360
- var aPos = gl.getAttribLocation(positionProgram.current, 'a_pos');
361
- gl.bindBuffer(gl.ARRAY_BUFFER, bufferQuad.current);
362
- gl.enableVertexAttribArray(aPos);
363
- gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
364
- gl.drawArrays(gl.TRIANGLES, 0, 6);
365
- };
366
- var renderParticles = function (gl, matrix) {
367
- gl.useProgram(particlesProgram.current);
368
- // Matrix:
369
- gl.uniformMatrix4fv(gl.getUniformLocation(particlesProgram.current, 'u_matrix'), false, matrix);
370
- // Stops - fill up to 12 stops by using values > 1 for filler stops.
371
- // e.g. [0.0, 0.5, 1.0, 2.0....] means that only the first 3 stops are used.
372
- var stops = __spreadArray([], props.gradientStops.map(function (s) { return s.pos; }), true);
373
- while (stops.length < 12)
374
- stops.push(2.0);
375
- gl.uniform1fv(gl.getUniformLocation(particlesProgram.current, 'u_gradientStops'), new Float32Array(stops));
376
- var colors = props.gradientStops.map(function (s) { return colorToRGBA(s.color); }).flat();
377
- gl.uniform4fv(gl.getUniformLocation(particlesProgram.current, 'u_gradientColors'), new Float32Array(colors));
378
- // Current animation frame:
379
- gl.uniform1i(gl.getUniformLocation(particlesProgram.current, "u_frame"), Math.floor(frame.current));
380
- // Number of point instances - this is the length of each curve:
381
- gl.uniform1i(gl.getUniformLocation(particlesProgram.current, "u_num_instances"), props.particles);
382
- // Size of points to be drawn (in pixels).
383
- gl.uniform1f(gl.getUniformLocation(particlesProgram.current, "u_point_size"), props.pointSize);
384
- // Position texture (pre-computed particle positions):
385
- gl.activeTexture(gl.TEXTURE0);
386
- gl.bindTexture(gl.TEXTURE_2D, texturePosition.current);
387
- gl.uniform1i(gl.getUniformLocation(particlesProgram.current, "positionTexture"), 0);
388
- // Position texture dimensions and grid parameters for coordinate lookup:
389
- gl.uniform1f(gl.getUniformLocation(particlesProgram.current, "u_posTexWidth"), posTexWidth.current);
390
- gl.uniform1f(gl.getUniformLocation(particlesProgram.current, "u_posTexHeight"), posTexHeight.current);
391
- gl.uniform1f(gl.getUniformLocation(particlesProgram.current, "u_density"), props.density);
392
- // Vertices:
393
- var aPos = gl.getAttribLocation(particlesProgram.current, 'a_pos'); // on-screen position [-1..1]
394
- var aIdx = gl.getAttribLocation(particlesProgram.current, 'a_idx'); // particle index
395
- var aOffset = gl.getAttribLocation(particlesProgram.current, 'a_offset'); // animation offset (into index)
396
- gl.bindBuffer(gl.ARRAY_BUFFER, bufferScreen.current);
397
- gl.enableVertexAttribArray(aPos);
398
- gl.enableVertexAttribArray(aIdx);
399
- gl.enableVertexAttribArray(aOffset);
400
- gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
401
- gl.vertexAttribPointer(aIdx, 1, gl.FLOAT, false, 16, 8);
402
- gl.vertexAttribPointer(aOffset, 1, gl.FLOAT, false, 16, 12);
403
- gl.enable(gl.BLEND);
404
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
405
- gl.drawArrays(gl.POINTS, 0, props.density * props.density * props.particles);
406
- };
407
- //
408
- // Check if two matrices are equal.
409
- //
410
- var matricesEqual = function (a, b) {
411
- if (!a || !b)
412
- return false;
413
- for (var i = 0; i < 16; i++) {
414
- if (a[i] !== b[i])
415
- return false;
416
- }
417
- return true;
418
- };
419
- var onRender = function (gl, matrix, zoom, width, height) {
420
- if (zoom < props.minZoom)
421
- return;
422
- if (zoom > props.maxZoom)
423
- return;
424
- // Only re-render UV textures when the matrix changes (i.e., when the map
425
- // view changes due to panning or zooming). This is a significant performance
426
- // optimization since UV texture rendering involves expensive draw calls.
427
- var matrixChanged = !matricesEqual(matrix, lastMatrix.current);
428
- if (matrixChanged) {
429
- lastMatrix.current = __spreadArray([], matrix, true);
430
- gl.useProgram(uvProgram.current);
431
- // Render to combined UV texture (U in R channel, V in G channel)
432
- gl.bindFramebuffer(gl.FRAMEBUFFER, fboUV.current);
433
- gl.viewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
434
- gl.clearColor(0, 0, 0, 0); // clear to transparent
435
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
436
- // Render U to R channel and A channel (alpha indicates valid data)
437
- gl.colorMask(true, false, false, true);
438
- renderSpeedBuffer(gl, matrix, bufferU.current, numTrianglesU.current);
439
- // Render V to G channel only (preserve R and A from U pass)
440
- gl.colorMask(false, true, false, false);
441
- renderSpeedBuffer(gl, matrix, bufferV.current, numTrianglesV.current);
442
- // Reset color mask to default
443
- gl.colorMask(true, true, true, true);
444
- // Compute particle positions (moves expensive loop from vertex shader)
445
- renderPositionTexture(gl);
446
- }
447
- // Unbind framebuffer so we're rendering to the screen:
448
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
449
- // Reset the viewport size to equal the map size:
450
- gl.viewport(0, 0, width * window.devicePixelRatio, height * window.devicePixelRatio);
451
- // Render particles:
452
- renderParticles(gl, matrix);
453
- };
454
- return (React.createElement(Layer, { id: null, type: "custom", beforeId: "overlay", key: time, onAdd: onAddLayer, render: function (gl, matrix) { return onRender(gl, matrix, map.current.getZoom(), map.current.getContainer().clientWidth, map.current.getContainer().clientHeight); } }));
362
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coords), gl.STATIC_DRAW);
363
+ };
364
+ var createTexture = function (gl) {
365
+ var texture = gl.createTexture();
366
+ gl.bindTexture(gl.TEXTURE_2D, texture);
367
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
368
+ // Set filtering to NEAREST so there's no interpolation:
369
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
370
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
371
+ return texture;
372
+ };
373
+ var createFrameBuffer = function (gl, texture) {
374
+ var fbo = gl.createFramebuffer();
375
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
376
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
377
+ return fbo;
378
+ };
379
+ var onAdd = function (mbMap, gl) {
380
+ createBufferU(gl);
381
+ createBufferV(gl);
382
+ createBufferScreen(gl);
383
+ createQuadBuffer(gl);
384
+ createUVProgram(gl);
385
+ createParticlesProgram(gl);
386
+ createPositionComputeProgram(gl);
387
+ // Single combined texture for both U and V (U in R, V in G)
388
+ textureUV = createTexture(gl);
389
+ fboUV = createFrameBuffer(gl, textureUV);
390
+ // Position texture for pre-computed particle positions
391
+ texturePosition = createPositionTexture(gl);
392
+ fboPosition = createFrameBuffer(gl, texturePosition);
393
+ // The map is idle after a prop-driven remount, so force a repaint to draw
394
+ // the freshly-added layer (the animation loop will keep it going).
395
+ mbMap.triggerRepaint();
396
+ };
397
+ var renderSpeedBuffer = function (gl, matrix, buffer, numTriangles) {
398
+ var program = uvProgram;
399
+ gl.useProgram(program);
400
+ // Pass a matrix uniform in:
401
+ gl.uniformMatrix4fv(gl.getUniformLocation(program, 'u_matrix'), false, matrix);
402
+ // Vertices:
403
+ var aPos = gl.getAttribLocation(program, 'a_pos');
404
+ var aValue = gl.getAttribLocation(program, 'a_value');
405
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
406
+ gl.enableVertexAttribArray(aPos);
407
+ gl.enableVertexAttribArray(aValue);
408
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 12, 0);
409
+ gl.vertexAttribPointer(aValue, 1, gl.FLOAT, false, 12, 8);
410
+ gl.enable(gl.BLEND);
411
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
412
+ gl.drawArrays(gl.TRIANGLES, 0, numTriangles * 3);
413
+ // Attribute-array enable state is global in WebGL1; disable what we
414
+ // enabled so a later draw with fewer attributes can't reference a
415
+ // stale (freed) buffer left bound to a still-enabled index.
416
+ gl.disableVertexAttribArray(aPos);
417
+ gl.disableVertexAttribArray(aValue);
418
+ };
419
+ //
420
+ // Render particle positions to the position texture.
421
+ // This moves the expensive trace loop from the particle vertex shader
422
+ // to a one-time-per-view-change fragment shader pass.
423
+ //
424
+ var renderPositionTexture = function (gl) {
425
+ var p = propsRef.current;
426
+ var program = positionProgram;
427
+ gl.useProgram(program);
428
+ // Bind position framebuffer
429
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fboPosition);
430
+ gl.viewport(0, 0, posTexWidth, posTexHeight);
431
+ gl.clearColor(0, 0, 0, 0);
432
+ gl.clear(gl.COLOR_BUFFER_BIT);
433
+ // Disable blending for position computation
434
+ gl.disable(gl.BLEND);
435
+ // UV texture (already rendered)
436
+ gl.activeTexture(gl.TEXTURE0);
437
+ gl.bindTexture(gl.TEXTURE_2D, textureUV);
438
+ gl.uniform1i(gl.getUniformLocation(program, 'uvTexture'), 0);
439
+ // UV range uniforms
440
+ gl.uniform1f(gl.getUniformLocation(program, 'minU'), minU);
441
+ gl.uniform1f(gl.getUniformLocation(program, 'maxU'), maxU);
442
+ gl.uniform1f(gl.getUniformLocation(program, 'minV'), minV);
443
+ gl.uniform1f(gl.getUniformLocation(program, 'maxV'), maxV);
444
+ // Grid parameters
445
+ gl.uniform1f(gl.getUniformLocation(program, 'u_density'), density);
446
+ gl.uniform1f(gl.getUniformLocation(program, 'u_particles'), particles);
447
+ gl.uniform1f(gl.getUniformLocation(program, 'u_texWidth'), posTexWidth);
448
+ // Velocity magnitude remapping parameters
449
+ gl.uniform1f(gl.getUniformLocation(program, 'u_minVisMag'), clampFloat(p.minSpeed, DEFAULT_MIN_SPEED, MIN_SPEED, MAX_SPEED));
450
+ gl.uniform1f(gl.getUniformLocation(program, 'u_maxVisMag'), clampFloat(p.maxSpeed, DEFAULT_MAX_SPEED, MIN_SPEED, MAX_SPEED));
451
+ // Render full-screen quad
452
+ var aPos = gl.getAttribLocation(program, 'a_pos');
453
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferQuad);
454
+ gl.enableVertexAttribArray(aPos);
455
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
456
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
457
+ gl.disableVertexAttribArray(aPos);
458
+ };
459
+ var renderParticles = function (gl, matrix) {
460
+ var _a;
461
+ var p = propsRef.current;
462
+ var program = particlesProgram;
463
+ gl.useProgram(program);
464
+ // Matrix:
465
+ gl.uniformMatrix4fv(gl.getUniformLocation(program, 'u_matrix'), false, matrix);
466
+ // Stops - fill up to 12 stops by using values > 1 for filler stops.
467
+ // e.g. [0.0, 0.5, 1.0, 2.0....] means that only the first 3 stops are used.
468
+ var gradientStops = (_a = p.gradientStops) !== null && _a !== void 0 ? _a : DEFAULT_GRADIENT_STOPS;
469
+ var stops = __spreadArray([], gradientStops.map(function (s) { return s.pos; }), true);
470
+ while (stops.length < 12)
471
+ stops.push(2.0);
472
+ gl.uniform1fv(gl.getUniformLocation(program, 'u_gradientStops'), new Float32Array(stops));
473
+ var colors = gradientStops.map(function (s) { return colorToRGBA(s.color); }).flat();
474
+ gl.uniform4fv(gl.getUniformLocation(program, 'u_gradientColors'), new Float32Array(colors));
475
+ // Current animation frame:
476
+ gl.uniform1i(gl.getUniformLocation(program, 'u_frame'), Math.floor(frame.current));
477
+ // Number of point instances - this is the length of each curve:
478
+ gl.uniform1i(gl.getUniformLocation(program, 'u_num_instances'), particles);
479
+ // Size of points to be drawn (in pixels).
480
+ gl.uniform1f(gl.getUniformLocation(program, 'u_point_size'), clampFloat(p.pointSize, DEFAULT_POINT_SIZE, MIN_POINT_SIZE, MAX_POINT_SIZE));
481
+ // Position texture (pre-computed particle positions):
482
+ gl.activeTexture(gl.TEXTURE0);
483
+ gl.bindTexture(gl.TEXTURE_2D, texturePosition);
484
+ gl.uniform1i(gl.getUniformLocation(program, 'positionTexture'), 0);
485
+ // Position texture dimensions and grid parameters for coordinate lookup:
486
+ gl.uniform1f(gl.getUniformLocation(program, 'u_posTexWidth'), posTexWidth);
487
+ gl.uniform1f(gl.getUniformLocation(program, 'u_posTexHeight'), posTexHeight);
488
+ gl.uniform1f(gl.getUniformLocation(program, 'u_density'), density);
489
+ // Vertices:
490
+ var aPos = gl.getAttribLocation(program, 'a_pos'); // on-screen position [-1..1]
491
+ var aIdx = gl.getAttribLocation(program, 'a_idx'); // particle index
492
+ var aOffset = gl.getAttribLocation(program, 'a_offset'); // animation offset (into index)
493
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferScreen);
494
+ gl.enableVertexAttribArray(aPos);
495
+ gl.enableVertexAttribArray(aIdx);
496
+ gl.enableVertexAttribArray(aOffset);
497
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
498
+ gl.vertexAttribPointer(aIdx, 1, gl.FLOAT, false, 16, 8);
499
+ gl.vertexAttribPointer(aOffset, 1, gl.FLOAT, false, 16, 12);
500
+ gl.enable(gl.BLEND);
501
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
502
+ gl.drawArrays(gl.POINTS, 0, density * density * particles);
503
+ gl.disableVertexAttribArray(aPos);
504
+ gl.disableVertexAttribArray(aIdx);
505
+ gl.disableVertexAttribArray(aOffset);
506
+ };
507
+ var render = function (gl, matrix) {
508
+ var _a, _b;
509
+ if (removed)
510
+ return; // Resources freed; ignore any trailing frame.
511
+ var m = map.current;
512
+ if (!m)
513
+ return;
514
+ var p = propsRef.current;
515
+ var zoom = m.getZoom();
516
+ if (zoom < ((_a = p.minZoom) !== null && _a !== void 0 ? _a : DEFAULT_MIN_ZOOM))
517
+ return;
518
+ if (zoom > ((_b = p.maxZoom) !== null && _b !== void 0 ? _b : DEFAULT_MAX_ZOOM))
519
+ return;
520
+ var width = m.getContainer().clientWidth;
521
+ var height = m.getContainer().clientHeight;
522
+ // Only re-render UV textures when the matrix changes (i.e., when the map
523
+ // view changes due to panning or zooming). This is a significant
524
+ // performance optimization since UV texture rendering involves expensive
525
+ // draw calls.
526
+ var matrixChanged = !matricesEqual(matrix, lastMatrix);
527
+ if (matrixChanged) {
528
+ lastMatrix = __spreadArray([], matrix, true);
529
+ gl.useProgram(uvProgram);
530
+ // Render to combined UV texture (U in R channel, V in G channel)
531
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fboUV);
532
+ gl.viewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
533
+ gl.clearColor(0, 0, 0, 0); // clear to transparent
534
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
535
+ // Render U to R channel and A channel (alpha indicates valid data)
536
+ gl.colorMask(true, false, false, true);
537
+ renderSpeedBuffer(gl, matrix, bufferU, numTrianglesU);
538
+ // Render V to G channel only (preserve R and A from U pass)
539
+ gl.colorMask(false, true, false, false);
540
+ renderSpeedBuffer(gl, matrix, bufferV, numTrianglesV);
541
+ // Reset color mask to default
542
+ gl.colorMask(true, true, true, true);
543
+ // Compute particle positions (moves expensive loop from vertex shader)
544
+ renderPositionTexture(gl);
545
+ }
546
+ // Unbind framebuffer so we're rendering to the screen:
547
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
548
+ // Reset the viewport size to equal the map size:
549
+ gl.viewport(0, 0, width * window.devicePixelRatio, height * window.devicePixelRatio);
550
+ // Render particles:
551
+ renderParticles(gl, matrix);
552
+ };
553
+ // Free all WebGL resources when this generation's layer is removed (Mapbox
554
+ // calls this on removeLayer). gl.deleteX(null) is a safe no-op.
555
+ var onRemove = function (_mbMap, gl) {
556
+ removed = true;
557
+ gl.deleteProgram(uvProgram);
558
+ gl.deleteProgram(particlesProgram);
559
+ gl.deleteProgram(positionProgram);
560
+ gl.deleteBuffer(bufferU);
561
+ gl.deleteBuffer(bufferV);
562
+ gl.deleteBuffer(bufferScreen);
563
+ gl.deleteBuffer(bufferQuad);
564
+ gl.deleteTexture(textureUV);
565
+ gl.deleteTexture(texturePosition);
566
+ gl.deleteFramebuffer(fboUV);
567
+ gl.deleteFramebuffer(fboPosition);
568
+ uvProgram = null;
569
+ particlesProgram = null;
570
+ positionProgram = null;
571
+ bufferU = null;
572
+ bufferV = null;
573
+ bufferScreen = null;
574
+ bufferQuad = null;
575
+ textureUV = null;
576
+ texturePosition = null;
577
+ fboUV = null;
578
+ fboPosition = null;
579
+ };
580
+ return { id: id, onAdd: onAdd, render: render, onRemove: onRemove };
581
+ // eslint-disable-next-line react-hooks/exhaustive-deps
582
+ }, [geometry, props.density, props.particles, props.minSpeed, props.maxSpeed]);
583
+ return (React.createElement(Layer, { id: layer.id, key: layer.id, type: "custom", beforeId: "overlay", onAdd: layer.onAdd, onRemove: layer.onRemove, render: layer.render }));
455
584
  };
456
585
  /**
457
586
  * A WebGL-based Mapbox GL custom layer that visualizes vector flow fields (such as
@@ -538,12 +667,7 @@ var ParticlesLayerBase = function (props) {
538
667
  * - Changing props triggers a full re-initialization of the WebGL resources
539
668
  */
540
669
  var ParticlesLayer = function (_a) {
541
- var _b = _a.particles, particles = _b === void 0 ? 80 : _b, _c = _a.density, density = _c === void 0 ? 40 : _c, _d = _a.delay, delay = _d === void 0 ? 0 : _d, _e = _a.gradientStops, gradientStops = _e === void 0 ? [
542
- { pos: 0.0, color: '#ffffffff' },
543
- { pos: 0.25, color: '#5c5cffff' },
544
- { pos: 0.5, color: '#5c5cff00' },
545
- { pos: 1.0, color: '#5c5cff00' }, // transparent blue
546
- ] : _e, _f = _a.minZoom, minZoom = _f === void 0 ? 0 : _f, _g = _a.maxZoom, maxZoom = _g === void 0 ? 99 : _g, _h = _a.minSpeed, minSpeed = _h === void 0 ? 0.02 : _h, _j = _a.maxSpeed, maxSpeed = _j === void 0 ? 0.15 : _j, props = __rest(_a, ["particles", "density", "delay", "gradientStops", "minZoom", "maxZoom", "minSpeed", "maxSpeed"]);
670
+ var _b = _a.particles, particles = _b === void 0 ? DEFAULT_PARTICLES : _b, _c = _a.density, density = _c === void 0 ? DEFAULT_DENSITY : _c, _d = _a.delay, delay = _d === void 0 ? DEFAULT_DELAY : _d, _e = _a.gradientStops, gradientStops = _e === void 0 ? DEFAULT_GRADIENT_STOPS : _e, _f = _a.minZoom, minZoom = _f === void 0 ? DEFAULT_MIN_ZOOM : _f, _g = _a.maxZoom, maxZoom = _g === void 0 ? DEFAULT_MAX_ZOOM : _g, _h = _a.minSpeed, minSpeed = _h === void 0 ? DEFAULT_MIN_SPEED : _h, _j = _a.maxSpeed, maxSpeed = _j === void 0 ? DEFAULT_MAX_SPEED : _j, props = __rest(_a, ["particles", "density", "delay", "gradientStops", "minZoom", "maxZoom", "minSpeed", "maxSpeed"]);
547
671
  return React.createElement(ParticlesLayerBase, __assign({ particles: particles, density: density, gradientStops: gradientStops, delay: delay, minZoom: minZoom, maxZoom: maxZoom, minSpeed: minSpeed, maxSpeed: maxSpeed }, props));
548
672
  };
549
673
  ParticlesLayer.displayName = 'ParticlesLayer';