@guardian/interactive-component-library 0.2.0-rc1 → 0.2.0-rc3

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 (276) hide show
  1. package/dist/components/index.d.ts +3 -0
  2. package/dist/components/molecules/canvas-map/Map.d.ts +17 -0
  3. package/dist/components/molecules/canvas-map/Map.js +89 -0
  4. package/dist/components/molecules/canvas-map/context/MapContext.d.ts +19 -0
  5. package/dist/components/molecules/canvas-map/context/MapContext.js +20 -0
  6. package/dist/components/molecules/canvas-map/controls/ZoomControl.d.ts +6 -0
  7. package/dist/components/molecules/canvas-map/controls/ZoomControl.js +40 -0
  8. package/dist/components/molecules/canvas-map/controls/icons/index.d.ts +3 -0
  9. package/dist/components/molecules/canvas-map/controls/icons/minus.d.ts +1 -0
  10. package/dist/components/molecules/canvas-map/controls/icons/minus.js +25 -0
  11. package/dist/components/molecules/canvas-map/controls/icons/plus.d.ts +1 -0
  12. package/dist/components/molecules/canvas-map/controls/icons/plus.js +25 -0
  13. package/dist/components/molecules/canvas-map/controls/icons/reset.d.ts +3 -0
  14. package/dist/components/molecules/canvas-map/controls/icons/reset.js +25 -0
  15. package/dist/components/molecules/canvas-map/controls/index.d.ts +1 -0
  16. package/dist/components/molecules/canvas-map/controls/style.module.css.js +11 -0
  17. package/dist/components/molecules/canvas-map/index.d.ts +12 -0
  18. package/dist/components/molecules/canvas-map/lib/Feature.d.ts +38 -0
  19. package/dist/components/molecules/canvas-map/lib/Feature.js +104 -0
  20. package/dist/components/molecules/canvas-map/lib/FeatureCollection.d.ts +20 -0
  21. package/dist/components/molecules/canvas-map/lib/FeatureCollection.js +23 -0
  22. package/dist/components/molecules/canvas-map/lib/Map.d.ts +69 -0
  23. package/dist/components/molecules/canvas-map/lib/Map.js +254 -0
  24. package/dist/components/molecules/canvas-map/lib/View.d.ts +136 -0
  25. package/dist/components/molecules/canvas-map/lib/View.js +179 -0
  26. package/dist/components/molecules/canvas-map/lib/events/Dispatcher.d.ts +8 -0
  27. package/dist/components/molecules/canvas-map/lib/events/Dispatcher.js +35 -0
  28. package/dist/components/molecules/canvas-map/lib/events/MapEvent.d.ts +6 -0
  29. package/dist/components/molecules/canvas-map/lib/events/MapEvent.js +9 -0
  30. package/dist/components/molecules/canvas-map/lib/events/index.d.ts +2 -0
  31. package/dist/components/molecules/canvas-map/lib/formats/GeoJSON.d.ts +10 -0
  32. package/dist/components/molecules/canvas-map/lib/formats/GeoJSON.js +96 -0
  33. package/dist/components/molecules/canvas-map/lib/geometry/Geometry.d.ts +32 -0
  34. package/dist/components/molecules/canvas-map/lib/geometry/Geometry.js +41 -0
  35. package/dist/components/molecules/canvas-map/lib/geometry/LineString.d.ts +12 -0
  36. package/dist/components/molecules/canvas-map/lib/geometry/LineString.js +19 -0
  37. package/dist/components/molecules/canvas-map/lib/geometry/Point.d.ts +11 -0
  38. package/dist/components/molecules/canvas-map/lib/geometry/Point.js +16 -0
  39. package/dist/components/molecules/canvas-map/lib/geometry/Polygon.d.ts +16 -0
  40. package/dist/components/molecules/canvas-map/lib/geometry/Polygon.js +46 -0
  41. package/dist/components/molecules/canvas-map/lib/geometry/index.d.ts +4 -0
  42. package/dist/components/molecules/canvas-map/lib/interpolators/index.d.ts +2 -0
  43. package/dist/components/molecules/canvas-map/lib/interpolators/interpolateFeatures.d.ts +5 -0
  44. package/dist/components/molecules/canvas-map/lib/interpolators/interpolateFeatures.js +95 -0
  45. package/dist/components/molecules/canvas-map/lib/interpolators/interpolateStyles.d.ts +4 -0
  46. package/dist/components/molecules/canvas-map/lib/interpolators/interpolateStyles.js +65 -0
  47. package/dist/components/molecules/canvas-map/lib/layers/TextLayer.d.ts +52 -0
  48. package/dist/components/molecules/canvas-map/lib/layers/TextLayer.js +111 -0
  49. package/dist/components/molecules/canvas-map/lib/layers/VectorLayer.d.ts +53 -0
  50. package/dist/components/molecules/canvas-map/lib/layers/VectorLayer.js +132 -0
  51. package/dist/components/molecules/canvas-map/lib/layers/index.d.ts +3 -0
  52. package/dist/components/molecules/canvas-map/lib/projection/index.d.ts +22 -0
  53. package/dist/components/molecules/canvas-map/lib/projection/index.js +12 -0
  54. package/dist/components/molecules/canvas-map/lib/renderers/FeatureRenderer.d.ts +6 -0
  55. package/dist/components/molecules/canvas-map/lib/renderers/FeatureRenderer.js +46 -0
  56. package/dist/components/molecules/canvas-map/lib/renderers/MapRenderer.d.ts +6 -0
  57. package/dist/components/molecules/canvas-map/lib/renderers/MapRenderer.js +53 -0
  58. package/dist/components/molecules/canvas-map/lib/renderers/TextLayerRenderer.d.ts +17 -0
  59. package/dist/components/molecules/canvas-map/lib/renderers/TextLayerRenderer.js +119 -0
  60. package/dist/components/molecules/canvas-map/lib/renderers/VectorLayerRenderer.d.ts +10 -0
  61. package/dist/components/molecules/canvas-map/lib/renderers/VectorLayerRenderer.js +78 -0
  62. package/dist/components/molecules/canvas-map/lib/sources/VectorSource.d.ts +15 -0
  63. package/dist/components/molecules/canvas-map/lib/sources/VectorSource.js +56 -0
  64. package/dist/components/molecules/canvas-map/lib/styles/Fill.d.ts +7 -0
  65. package/dist/components/molecules/canvas-map/lib/styles/Fill.js +15 -0
  66. package/dist/components/molecules/canvas-map/lib/styles/Stroke.d.ts +8 -0
  67. package/dist/components/molecules/canvas-map/lib/styles/Stroke.js +16 -0
  68. package/dist/components/molecules/canvas-map/lib/styles/Style.d.ts +24 -0
  69. package/dist/components/molecules/canvas-map/lib/styles/Style.js +17 -0
  70. package/dist/components/molecules/canvas-map/lib/styles/Text.d.ts +10 -0
  71. package/dist/components/molecules/canvas-map/lib/styles/Text.js +14 -0
  72. package/dist/components/molecules/canvas-map/lib/styles/index.d.ts +4 -0
  73. package/dist/components/molecules/canvas-map/lib/util/array.d.ts +6 -0
  74. package/dist/components/molecules/canvas-map/lib/util/array.js +15 -0
  75. package/dist/components/molecules/canvas-map/lib/util/bboxFeature.d.ts +8 -0
  76. package/dist/components/molecules/canvas-map/lib/util/bboxFeature.js +26 -0
  77. package/dist/components/molecules/canvas-map/lib/util/debug.d.ts +11 -0
  78. package/dist/components/molecules/canvas-map/lib/util/debug.js +27 -0
  79. package/dist/components/molecules/canvas-map/lib/util/deflate.d.ts +36 -0
  80. package/dist/components/molecules/canvas-map/lib/util/distance.d.ts +1 -0
  81. package/dist/components/molecules/canvas-map/lib/util/distance.js +12 -0
  82. package/dist/components/molecules/canvas-map/lib/util/dom.d.ts +9 -0
  83. package/dist/components/molecules/canvas-map/lib/util/dom.js +28 -0
  84. package/dist/components/molecules/canvas-map/lib/util/extent.d.ts +21 -0
  85. package/dist/components/molecules/canvas-map/lib/util/extent.js +38 -0
  86. package/dist/components/molecules/canvas-map/lib/util/memoise.d.ts +10 -0
  87. package/dist/components/molecules/canvas-map/lib/util/memoise.js +20 -0
  88. package/dist/components/molecules/canvas-map/lib/util/resolution.d.ts +9 -0
  89. package/dist/components/molecules/canvas-map/lib/util/resolution.js +11 -0
  90. package/dist/components/molecules/canvas-map/lib/util/simplify.d.ts +114 -0
  91. package/dist/components/molecules/canvas-map/lib/util/size.d.ts +32 -0
  92. package/dist/components/molecules/canvas-map/lib/util/size.js +53 -0
  93. package/dist/components/molecules/canvas-map/lib/util/toRgba.d.ts +1 -0
  94. package/dist/components/molecules/canvas-map/lib/util/toRgba.js +25 -0
  95. package/dist/components/molecules/canvas-map/lib/util/uid.d.ts +5 -0
  96. package/dist/components/molecules/canvas-map/lib/util/uid.js +7 -0
  97. package/dist/components/molecules/canvas-map/lib/util/zoomLevel.d.ts +2 -0
  98. package/dist/components/molecules/canvas-map/lib/util/zoomLevel.js +14 -0
  99. package/dist/components/molecules/canvas-map/style.module.scss.js +20 -0
  100. package/dist/components/molecules/column-chart/column-chart-example.d.ts +35 -0
  101. package/dist/components/molecules/column-chart/column-chart-util.d.ts +1 -0
  102. package/dist/components/molecules/column-chart/index.d.ts +11 -0
  103. package/dist/components/molecules/column-chart/index.js +63 -0
  104. package/dist/components/molecules/column-chart/style.module.css.js +14 -0
  105. package/dist/components/molecules/control-change/index.d.ts +6 -0
  106. package/dist/components/molecules/control-change/index.js +29 -0
  107. package/dist/components/molecules/control-change/style.module.css.js +11 -0
  108. package/dist/components/molecules/dropdown/index.d.ts +11 -0
  109. package/dist/components/molecules/dropdown/index.js +191 -0
  110. package/dist/components/molecules/dropdown/style.module.css.js +50 -0
  111. package/dist/components/molecules/first-past-the-post-waffle/index.d.ts +5 -0
  112. package/dist/components/molecules/first-past-the-post-waffle/index.js +14 -0
  113. package/dist/components/molecules/first-past-the-post-waffle/style.module.css.js +14 -0
  114. package/dist/components/molecules/index.d.ts +17 -0
  115. package/dist/components/molecules/modal/index.d.ts +8 -0
  116. package/dist/components/molecules/modal/index.js +59 -0
  117. package/dist/components/molecules/modal/style.module.css.js +26 -0
  118. package/dist/components/molecules/page-section/index.d.ts +8 -0
  119. package/dist/components/molecules/page-section/index.js +52 -0
  120. package/dist/components/molecules/page-section/style.module.scss.js +20 -0
  121. package/dist/components/molecules/party-profile/index.d.ts +10 -0
  122. package/dist/components/molecules/party-profile/index.js +29 -0
  123. package/dist/components/molecules/party-profile/style.module.css.js +26 -0
  124. package/dist/components/molecules/refresh-indicator/index.d.ts +4 -0
  125. package/dist/components/molecules/refresh-indicator/index.js +18 -0
  126. package/dist/components/molecules/refresh-indicator/style.module.scss.js +17 -0
  127. package/dist/components/molecules/responsive-grid/index.d.ts +10 -0
  128. package/dist/components/molecules/responsive-grid/index.js +19 -0
  129. package/dist/components/molecules/responsive-grid/style.module.scss.js +8 -0
  130. package/dist/components/molecules/result-summary/index.d.ts +8 -0
  131. package/dist/components/molecules/result-summary/index.js +38 -0
  132. package/dist/components/molecules/result-summary/style.module.css.js +11 -0
  133. package/dist/components/molecules/search-input/icons/search.d.ts +1 -0
  134. package/dist/components/molecules/search-input/icons/search.js +24 -0
  135. package/dist/components/molecules/search-input/icons/search.module.css.js +11 -0
  136. package/dist/components/molecules/search-input/index.d.ts +11 -0
  137. package/dist/components/molecules/search-input/index.js +164 -0
  138. package/dist/components/molecules/search-input/style.module.css.js +32 -0
  139. package/dist/components/molecules/slope-chart/index.d.ts +16 -0
  140. package/dist/components/molecules/slope-chart/index.js +139 -0
  141. package/dist/components/molecules/slope-chart/style.module.css.js +35 -0
  142. package/dist/components/molecules/svg-map/context/MapContext.d.ts +1 -0
  143. package/dist/components/molecules/svg-map/context/MapContext.js +5 -0
  144. package/dist/components/molecules/svg-map/context/SVGMapProvider.d.ts +10 -0
  145. package/dist/components/molecules/svg-map/context/SVGMapProvider.js +88 -0
  146. package/dist/components/molecules/svg-map/helpers/bboxFeature.d.ts +8 -0
  147. package/dist/components/molecules/svg-map/helpers/bboxFeature.js +26 -0
  148. package/dist/components/molecules/svg-map/helpers/dynamicPropValue.d.ts +1 -0
  149. package/dist/components/molecules/svg-map/helpers/dynamicPropValue.js +9 -0
  150. package/dist/components/molecules/svg-map/helpers/geoMath.d.ts +4 -0
  151. package/dist/components/molecules/svg-map/helpers/saveSVG.d.ts +1 -0
  152. package/dist/components/molecules/svg-map/hooks/useCamera.d.ts +0 -0
  153. package/dist/components/molecules/svg-map/hooks/useThrowIfNonLayerChildren.d.ts +4 -0
  154. package/dist/components/molecules/svg-map/hooks/useThrowIfNonLayerChildren.js +19 -0
  155. package/dist/components/molecules/svg-map/index.d.ts +38 -0
  156. package/dist/components/molecules/svg-map/index.js +121 -0
  157. package/dist/components/molecules/svg-map/layers/CompositionBorders.d.ts +3 -0
  158. package/dist/components/molecules/svg-map/layers/CompositionBorders.js +14 -0
  159. package/dist/components/molecules/svg-map/layers/Line.d.ts +7 -0
  160. package/dist/components/molecules/svg-map/layers/Line.js +48 -0
  161. package/dist/components/molecules/svg-map/layers/Point.d.ts +10 -0
  162. package/dist/components/molecules/svg-map/layers/Point.js +59 -0
  163. package/dist/components/molecules/svg-map/layers/Polygon.d.ts +9 -0
  164. package/dist/components/molecules/svg-map/layers/Polygon.js +75 -0
  165. package/dist/components/molecules/svg-map/layers/Prerendered.d.ts +3 -0
  166. package/dist/components/molecules/svg-map/layers/Prerendered.js +11 -0
  167. package/dist/components/molecules/svg-map/layers/compositionBorders.module.scss.js +8 -0
  168. package/dist/components/molecules/svg-map/layers/index.d.ts +5 -0
  169. package/dist/components/molecules/svg-map/layers/index.js +12 -0
  170. package/dist/components/molecules/svg-map/renderers/SVGRenderer.d.ts +3 -0
  171. package/dist/components/molecules/svg-map/renderers/SVGRenderer.js +32 -0
  172. package/dist/components/molecules/svg-map/style.module.css.js +11 -0
  173. package/dist/components/molecules/table/index.d.ts +7 -0
  174. package/dist/components/molecules/table/index.js +90 -0
  175. package/dist/components/molecules/table/style.module.scss.js +29 -0
  176. package/dist/components/molecules/table/useTable.d.ts +8 -0
  177. package/dist/components/molecules/table/useTable.js +128 -0
  178. package/dist/components/molecules/tooltip/index.d.ts +82 -0
  179. package/dist/components/molecules/tooltip/index.js +117 -0
  180. package/dist/components/molecules/tooltip/style.module.css.js +8 -0
  181. package/dist/components/molecules/topline-result/index.d.ts +3 -0
  182. package/dist/components/molecules/topline-result/index.js +61 -0
  183. package/dist/components/molecules/topline-result/style.module.scss.js +38 -0
  184. package/dist/components/organisms/coalitions-tracker/index.d.ts +16 -0
  185. package/dist/components/organisms/coalitions-tracker/index.js +151 -0
  186. package/dist/components/organisms/coalitions-tracker/style.module.scss.js +32 -0
  187. package/dist/components/organisms/index.d.ts +2 -0
  188. package/dist/components/organisms/ticker/gradient/index.d.ts +1 -0
  189. package/dist/components/organisms/ticker/gradient/index.js +35 -0
  190. package/dist/components/organisms/ticker/gradient/style.module.scss.js +14 -0
  191. package/dist/components/organisms/ticker/index.d.ts +5 -0
  192. package/dist/components/organisms/ticker/index.js +102 -0
  193. package/dist/components/organisms/ticker/style.module.scss.js +32 -0
  194. package/dist/components/particles/ad-slot/index.d.ts +40 -0
  195. package/dist/components/particles/ad-slot/index.js +34 -0
  196. package/dist/components/particles/ad-slot/style.module.css.js +11 -0
  197. package/dist/components/particles/arrow-button/index.d.ts +6 -0
  198. package/dist/components/particles/arrow-button/index.js +32 -0
  199. package/dist/components/particles/arrow-button/style.module.css.js +11 -0
  200. package/dist/components/particles/aspect-ratio-box/index.d.ts +4 -0
  201. package/dist/components/particles/aspect-ratio-box/index.js +15 -0
  202. package/dist/components/particles/aspect-ratio-box/style.module.css.js +6 -0
  203. package/dist/components/particles/button/index.d.ts +6 -0
  204. package/dist/components/particles/button/index.js +10 -0
  205. package/dist/components/particles/button/style.module.css.js +11 -0
  206. package/dist/components/particles/change-bar/index.d.ts +8 -0
  207. package/dist/components/particles/change-bar/index.js +27 -0
  208. package/dist/components/particles/change-bar/style.module.scss.js +14 -0
  209. package/dist/components/particles/chevron/index.d.ts +6 -0
  210. package/dist/components/particles/chevron/index.js +78 -0
  211. package/dist/components/particles/chevron/style.module.css.js +20 -0
  212. package/dist/components/particles/circle-icon/index.d.ts +6 -0
  213. package/dist/components/particles/circle-icon/index.js +32 -0
  214. package/dist/components/particles/circle-icon/style.module.css.js +14 -0
  215. package/dist/components/particles/close-button/index.d.ts +5 -0
  216. package/dist/components/particles/close-button/index.js +35 -0
  217. package/dist/components/particles/close-button/style.module.css.js +17 -0
  218. package/dist/components/particles/container/index.d.ts +5 -0
  219. package/dist/components/particles/container/index.js +13 -0
  220. package/dist/components/particles/container/style.module.scss.js +11 -0
  221. package/dist/components/particles/gradient-icon/index.d.ts +1 -0
  222. package/dist/components/particles/gradient-icon/index.js +46 -0
  223. package/dist/components/particles/gradient-icon/style.module.css.js +14 -0
  224. package/dist/components/particles/index.d.ts +18 -0
  225. package/dist/components/particles/info-button/index.d.ts +3 -0
  226. package/dist/components/particles/info-button/index.js +19 -0
  227. package/dist/components/particles/info-button/style.module.css.js +11 -0
  228. package/dist/components/particles/legend-item/index.d.ts +6 -0
  229. package/dist/components/particles/legend-item/index.js +26 -0
  230. package/dist/components/particles/legend-item/style.module.css.js +17 -0
  231. package/dist/components/particles/relative-time-sentence/index.d.ts +4 -0
  232. package/dist/components/particles/relative-time-sentence/index.js +14 -0
  233. package/dist/components/particles/relative-time-sentence/style.module.css.js +8 -0
  234. package/dist/components/particles/square-cut-corner-icon/index.d.ts +6 -0
  235. package/dist/components/particles/square-cut-corner-icon/index.js +56 -0
  236. package/dist/components/particles/square-cut-corner-icon/style.module.scss.js +17 -0
  237. package/dist/components/particles/square-icon/index.d.ts +5 -0
  238. package/dist/components/particles/square-icon/index.js +28 -0
  239. package/dist/components/particles/square-icon/style.module.scss.js +11 -0
  240. package/dist/components/particles/stacked-bar/index.d.ts +23 -0
  241. package/dist/components/particles/stacked-bar/index.js +140 -0
  242. package/dist/components/particles/stacked-bar/style.module.css.js +17 -0
  243. package/dist/components/particles/stacked-grid/index.d.ts +6 -0
  244. package/dist/components/particles/stacked-grid/index.js +35 -0
  245. package/dist/components/particles/stacked-grid/style.module.css.js +20 -0
  246. package/dist/components/particles/waffle/index.d.ts +14 -0
  247. package/dist/components/particles/waffle/index.js +76 -0
  248. package/dist/components/particles/waffle/style.module.css.js +11 -0
  249. package/dist/index.d.ts +2 -0
  250. package/dist/index.js +128 -0
  251. package/dist/shared/colors/index.d.ts +2 -0
  252. package/dist/shared/helpers/createStore.d.ts +1 -0
  253. package/dist/shared/helpers/geometry.d.ts +3 -0
  254. package/dist/shared/helpers/geometry.js +16 -0
  255. package/dist/shared/helpers/geometry.test.d.ts +1 -0
  256. package/dist/shared/helpers/labelsUtil.d.ts +54 -0
  257. package/dist/shared/helpers/labelsUtil.js +58 -0
  258. package/dist/shared/helpers/labelsUtils.test.d.ts +1 -0
  259. package/dist/shared/helpers/shouldUpdate.d.ts +7 -0
  260. package/dist/shared/hooks/index.d.ts +3 -0
  261. package/dist/shared/hooks/useContainerSize.d.ts +1 -0
  262. package/dist/shared/hooks/useContainerSize.js +24 -0
  263. package/dist/shared/hooks/useTouchOrHover.d.ts +6 -0
  264. package/dist/shared/hooks/useTouchOrHover.js +95 -0
  265. package/dist/shared/hooks/useWindowSize.d.ts +4 -0
  266. package/dist/shared/hooks/useWindowSize.js +27 -0
  267. package/dist/style.css +74 -74
  268. package/dist/styles/helpers/mergeStyles.d.ts +1 -0
  269. package/dist/styles/helpers/mergeStyles.js +22 -0
  270. package/dist/styles/helpers/mergeStyles.test.d.ts +1 -0
  271. package/dist/styles/theme.config.d.ts +124 -0
  272. package/package.json +6 -9
  273. package/dist/interactive-component-library.js +0 -7993
  274. package/dist/interactive-component-library.js.map +0 -1
  275. package/dist/interactive-component-library.umd.cjs +0 -7989
  276. package/dist/interactive-component-library.umd.cjs.map +0 -1
@@ -0,0 +1,53 @@
1
+ import { Dispatcher } from '../events';
2
+ import { VectorLayerRenderer } from '../renderers/VectorLayerRenderer';
3
+ import { Style } from '../styles';
4
+ import { VectorSource } from '../sources/VectorSource';
5
+ /** @typedef {Omit<ConstructorParameters<typeof VectorLayer>[0], "source">} VectorLayerOptions */
6
+ /** @typedef {VectorLayerOptions & { features: import("../Feature").Feature[] | import("../FeatureCollection").FeatureCollection }} VectorLayerComponentProps */
7
+ export class VectorLayer {
8
+ /** @param {VectorLayerComponentProps} props */
9
+ static Component({ features: featureCollection, style, minZoom, opacity, hitDetectionEnabled, }: VectorLayerComponentProps): any;
10
+ /**
11
+ * @param {import("../Feature").Feature[]} features
12
+ * @param {VectorLayerOptions} options
13
+ */
14
+ static with(features: import('../Feature').Feature[], options: VectorLayerOptions): VectorLayer;
15
+ /**
16
+ * @param {Object} params
17
+ * @param {VectorSource} params.source
18
+ * @param {Style | (() => Style)} [params.style=undefined]
19
+ * @param {number} [params.minZoom=0]
20
+ * @param {number} [params.opacity=1]
21
+ * @param {boolean} [params.hitDetectionEnabled=true]
22
+ */
23
+ constructor({ source, style, minZoom, opacity, hitDetectionEnabled, }: {
24
+ source: VectorSource;
25
+ style?: Style | (() => Style);
26
+ minZoom?: number;
27
+ opacity?: number;
28
+ hitDetectionEnabled?: boolean;
29
+ });
30
+ dispatcher: Dispatcher;
31
+ renderer: VectorLayerRenderer;
32
+ set source(source: any);
33
+ get source(): any;
34
+ _style: Style | (() => Style);
35
+ minZoom: number;
36
+ opacity: number;
37
+ hitDetectionEnabled: boolean;
38
+ _source: any;
39
+ _extent: any;
40
+ setRawProjection(projection: any): void;
41
+ projection: any;
42
+ tearDown(): void;
43
+ set style(style: Style | (() => Style));
44
+ get style(): Style | (() => Style);
45
+ getStyleFunction(): () => Style;
46
+ getExtent(): any;
47
+ findFeatures(coordinate: any): any;
48
+ renderFrame(frameState: any, targetElement: any): any;
49
+ }
50
+ export type VectorLayerOptions = Omit<ConstructorParameters<typeof VectorLayer>[0], "source">;
51
+ export type VectorLayerComponentProps = VectorLayerOptions & {
52
+ features: import('../Feature').Feature[] | import('../FeatureCollection').FeatureCollection;
53
+ };
@@ -0,0 +1,132 @@
1
+ import { VectorLayerRenderer } from "../renderers/VectorLayerRenderer.js";
2
+ import { Style } from "../styles/Style.js";
3
+ import { Stroke } from "../styles/Stroke.js";
4
+ import { combineExtents } from "../util/extent.js";
5
+ import { Dispatcher } from "../events/Dispatcher.js";
6
+ import { MapEvent } from "../events/MapEvent.js";
7
+ import { VectorSource } from "../sources/VectorSource.js";
8
+ import { useContext, useMemo, useEffect } from "preact/hooks";
9
+ import { MapContext } from "../../context/MapContext.js";
10
+ import { FeatureCollection } from "../FeatureCollection.js";
11
+ class VectorLayer {
12
+ /** @param {VectorLayerComponentProps} props */
13
+ static Component({
14
+ features: featureCollection,
15
+ style,
16
+ minZoom,
17
+ opacity,
18
+ hitDetectionEnabled = true
19
+ }) {
20
+ const { registerLayer } = useContext(MapContext);
21
+ const layer = useMemo(
22
+ () => {
23
+ const features = featureCollection instanceof FeatureCollection ? featureCollection.features : (
24
+ /** @type {import("../Feature").Feature[]} */
25
+ featureCollection
26
+ );
27
+ return VectorLayer.with(features, {
28
+ style,
29
+ minZoom,
30
+ opacity,
31
+ hitDetectionEnabled
32
+ });
33
+ },
34
+ // eslint-disable-next-line react-hooks/exhaustive-deps
35
+ [featureCollection, minZoom, opacity, hitDetectionEnabled]
36
+ );
37
+ registerLayer(layer);
38
+ useEffect(() => {
39
+ layer.style = style;
40
+ }, [style]);
41
+ return null;
42
+ }
43
+ /**
44
+ * @param {import("../Feature").Feature[]} features
45
+ * @param {VectorLayerOptions} options
46
+ */
47
+ static with(features, options) {
48
+ const source = new VectorSource({ features });
49
+ return new VectorLayer({ source, ...options });
50
+ }
51
+ /**
52
+ * @param {Object} params
53
+ * @param {VectorSource} params.source
54
+ * @param {Style | (() => Style)} [params.style=undefined]
55
+ * @param {number} [params.minZoom=0]
56
+ * @param {number} [params.opacity=1]
57
+ * @param {boolean} [params.hitDetectionEnabled=true]
58
+ */
59
+ constructor({
60
+ source,
61
+ style,
62
+ minZoom = 0,
63
+ opacity = 1,
64
+ hitDetectionEnabled = true
65
+ }) {
66
+ this.dispatcher = new Dispatcher(this);
67
+ this.renderer = new VectorLayerRenderer(this);
68
+ this.source = source;
69
+ this._style = style;
70
+ this.minZoom = minZoom;
71
+ this.opacity = opacity;
72
+ this.hitDetectionEnabled = hitDetectionEnabled;
73
+ }
74
+ get source() {
75
+ return this._source;
76
+ }
77
+ set source(source) {
78
+ if (this._source && source !== this._source) {
79
+ this._source.tearDown();
80
+ }
81
+ this._source = source;
82
+ source.on(MapEvent.CHANGE, () => {
83
+ this._extent = null;
84
+ this.dispatcher.dispatch(MapEvent.CHANGE);
85
+ });
86
+ }
87
+ setRawProjection(projection) {
88
+ this.projection = projection;
89
+ }
90
+ tearDown() {
91
+ this.dispatcher = null;
92
+ }
93
+ get style() {
94
+ if (this._style) return this._style;
95
+ const defaultStyle = new Style({
96
+ stroke: new Stroke()
97
+ });
98
+ return defaultStyle;
99
+ }
100
+ set style(style) {
101
+ this._style = style;
102
+ this.dispatcher.dispatch(MapEvent.CHANGE);
103
+ }
104
+ getStyleFunction() {
105
+ const style = this.style;
106
+ if (typeof style === "function") return style;
107
+ return () => {
108
+ return style;
109
+ };
110
+ }
111
+ getExtent() {
112
+ if (this._extent) return this._extent;
113
+ const features = this.source.getFeatures();
114
+ const extent = features.reduce((combinedExtent, feature) => {
115
+ const featureExtent = feature.getExtent();
116
+ if (!combinedExtent) return featureExtent;
117
+ return combineExtents(featureExtent, combinedExtent);
118
+ }, null);
119
+ this._extent = extent;
120
+ return extent;
121
+ }
122
+ findFeatures(coordinate) {
123
+ if (!this.hitDetectionEnabled) return;
124
+ return this.source.getFeaturesAtCoordinate(coordinate);
125
+ }
126
+ renderFrame(frameState, targetElement) {
127
+ return this.renderer.renderFrame(frameState, targetElement);
128
+ }
129
+ }
130
+ export {
131
+ VectorLayer
132
+ };
@@ -0,0 +1,3 @@
1
+ export * from './TextLayer';
2
+ export * from './VectorLayer';
3
+ export type Layer = import('./TextLayer').TextLayer | import('./VectorLayer').VectorLayer;
@@ -0,0 +1,22 @@
1
+ export namespace Projection {
2
+ let geoIdentity: {
3
+ (p: any): number[];
4
+ invert(p: any): number[];
5
+ stream(stream: any): any;
6
+ postclip(_: any, ...args: any[]): any;
7
+ clipExtent(_: any, ...args: any[]): any[][] | any;
8
+ scale(_: any, ...args: any[]): number | any;
9
+ translate(_: any, ...args: any[]): number[] | any;
10
+ angle(_: any, ...args: any[]): number | any;
11
+ reflectX(_: any, ...args: any[]): boolean | any;
12
+ reflectY(_: any, ...args: any[]): boolean | any;
13
+ fitExtent(extent: any, object: any): any;
14
+ fitSize(size: any, object: any): any;
15
+ fitWidth(width: any, object: any): any;
16
+ fitHeight(height: any, object: any): any;
17
+ };
18
+ let geoMercator: any;
19
+ let geoAlbersUS: any;
20
+ let geoAlbersUKComposite: any;
21
+ let geoAlbersEngland: any;
22
+ }
@@ -0,0 +1,12 @@
1
+ import { geoIdentity, geoMercator, geoAlbersUsa, geoAlbers } from "d3-geo";
2
+ import { geoAlbersUk } from "d3-composite-projections";
3
+ const Projection = {
4
+ geoIdentity: geoIdentity(),
5
+ geoMercator: geoMercator(),
6
+ geoAlbersUS: geoAlbersUsa().scale(1070).translate([487.5, 305]),
7
+ geoAlbersUKComposite: geoAlbersUk(),
8
+ geoAlbersEngland: geoAlbers().center([0, 52.7]).rotate([1.1743, 0]).parallels([50, 54])
9
+ };
10
+ export {
11
+ Projection
12
+ };
@@ -0,0 +1,6 @@
1
+ export class FeatureRenderer {
2
+ drawingFunction: any;
3
+ setStyle(style: any): void;
4
+ style: any;
5
+ render(frameState: any, feature: any, context: any): void;
6
+ }
@@ -0,0 +1,46 @@
1
+ import { geoPath } from "d3-geo";
2
+ import { validateGeometries, generateDebugUrl } from "../util/debug.js";
3
+ class FeatureRenderer {
4
+ constructor() {
5
+ this.drawingFunction = geoPath();
6
+ }
7
+ setStyle(style) {
8
+ this.style = style;
9
+ }
10
+ render(frameState, feature, context) {
11
+ if (!this.style) {
12
+ return;
13
+ }
14
+ const { projection, transform, pixelRatio } = frameState.viewState;
15
+ const { stroke, fill } = this.style;
16
+ this.drawingFunction.context(context);
17
+ context.beginPath();
18
+ const geometries = feature.getProjectedGeometries(projection);
19
+ if (frameState.debug) {
20
+ try {
21
+ validateGeometries(geometries);
22
+ } catch {
23
+ console.error(
24
+ `Invalid geometry. Feature skipped during rendering. Click here to inspect geometry: ${generateDebugUrl(feature)}
25
+ `,
26
+ feature
27
+ );
28
+ }
29
+ }
30
+ for (const geometry of geometries) {
31
+ this.drawingFunction(geometry);
32
+ }
33
+ if (fill) {
34
+ context.fillStyle = fill.getRgba();
35
+ context.fill();
36
+ }
37
+ if (stroke) {
38
+ context.lineWidth = stroke.width * pixelRatio / transform.k;
39
+ context.strokeStyle = stroke.getRgba();
40
+ context.stroke();
41
+ }
42
+ }
43
+ }
44
+ export {
45
+ FeatureRenderer
46
+ };
@@ -0,0 +1,6 @@
1
+ export class MapRenderer {
2
+ constructor(map: any);
3
+ map: any;
4
+ _element: HTMLDivElement;
5
+ renderFrame(frameState: any): void;
6
+ }
@@ -0,0 +1,53 @@
1
+ import { replaceChildren } from "../util/dom.js";
2
+ import RBush from "rbush";
3
+ class MapRenderer {
4
+ constructor(map) {
5
+ this.map = map;
6
+ this._element = document.createElement("div");
7
+ this._element.className = "gv-layer-container";
8
+ const style = this._element.style;
9
+ style.position = "absolute";
10
+ style.width = "100%";
11
+ style.height = "100%";
12
+ style.zIndex = "0";
13
+ const container = map.viewPort;
14
+ container.insertBefore(this._element, container.firstChild || null);
15
+ }
16
+ renderFrame(frameState) {
17
+ const { zoomLevel, projection } = frameState.viewState;
18
+ const layers = this.map.layers;
19
+ const mapElements = [];
20
+ let previousElement = null;
21
+ const visibleLayers = layers.filter((layer) => {
22
+ return zoomLevel > (layer.minZoom || 0);
23
+ });
24
+ const renderLayer = (layer, declutterTree2) => {
25
+ const viewState = frameState.viewState;
26
+ if (layer.projection) {
27
+ viewState.projection = layer.projection;
28
+ }
29
+ const element = layer.renderFrame(
30
+ { ...frameState, viewState, declutterTree: declutterTree2 },
31
+ previousElement
32
+ );
33
+ if (element !== previousElement) {
34
+ mapElements.push(element);
35
+ previousElement = element;
36
+ }
37
+ viewState.projection = projection;
38
+ };
39
+ const baseLayers = visibleLayers.filter((layer) => !layer.declutter);
40
+ for (const layer of baseLayers) {
41
+ renderLayer(layer);
42
+ }
43
+ const declutterTree = new RBush();
44
+ const layersToDeclutter = [...visibleLayers].filter((layer) => !!layer.declutter).reverse();
45
+ for (const layer of layersToDeclutter) {
46
+ renderLayer(layer, declutterTree);
47
+ }
48
+ replaceChildren(this._element, mapElements);
49
+ }
50
+ }
51
+ export {
52
+ MapRenderer
53
+ };
@@ -0,0 +1,17 @@
1
+ import { FeatureRenderer } from './FeatureRenderer';
2
+ export class TextLayerRenderer {
3
+ constructor(layer: any);
4
+ layer: any;
5
+ featureRenderer: FeatureRenderer;
6
+ _element: HTMLDivElement;
7
+ renderFrame(frameState: any, targetElement: any): any;
8
+ getTextElementWithID(id: any): Element;
9
+ styleTextElement(element: any, textStyle: any, position: any): void;
10
+ getElementBBox(element: any, position: any): {
11
+ minX: number;
12
+ minY: number;
13
+ maxX: number;
14
+ maxY: number;
15
+ };
16
+ getCollisionBoxElement(bbox: any): HTMLDivElement;
17
+ }
@@ -0,0 +1,119 @@
1
+ import { FeatureRenderer } from "./FeatureRenderer.js";
2
+ import { replaceChildren } from "../util/dom.js";
3
+ const textPadding = {
4
+ top: 20,
5
+ right: 20,
6
+ bottom: 20,
7
+ left: 20
8
+ };
9
+ class TextLayerRenderer {
10
+ constructor(layer) {
11
+ this.layer = layer;
12
+ this.featureRenderer = new FeatureRenderer();
13
+ this._element = document.createElement("div");
14
+ this._element.className = "gv-text-layer";
15
+ const style = this._element.style;
16
+ style.position = "absolute";
17
+ style.width = "100%";
18
+ style.height = "100%";
19
+ style.pointerEvents = "none";
20
+ style.overflow = "hidden";
21
+ }
22
+ renderFrame(frameState, targetElement) {
23
+ if (this.layer.opacity === 0) return targetElement;
24
+ const { declutterTree } = frameState;
25
+ const { projection, viewPortSize, sizeInPixels, visibleExtent, transform } = frameState.viewState;
26
+ this._element.style.opacity = this.layer.opacity;
27
+ const source = this.layer.source;
28
+ const features = source.getFeaturesInExtent(visibleExtent);
29
+ const textElements = [];
30
+ for (const feature of features) {
31
+ const geometries = feature.getProjectedGeometries(projection);
32
+ const point = geometries.find((d) => d.type === "Point");
33
+ if (!point) {
34
+ throw new Error(
35
+ `Expected Point geometry for feature in TextLayer: ${feature}`
36
+ );
37
+ }
38
+ const styleFunction = feature.getStyleFunction() || this.layer.getStyleFunction();
39
+ const featureStyle = styleFunction(feature);
40
+ const textElement = this.getTextElementWithID(feature.uid);
41
+ textElement.innerText = featureStyle.text.content;
42
+ const [relativeX, relativeY] = transform.apply(point.coordinates).map((d, i) => d / sizeInPixels[i]);
43
+ const position = {
44
+ left: `${relativeX * 100}%`,
45
+ top: `${relativeY * 100}%`
46
+ };
47
+ this.styleTextElement(textElement, featureStyle.text, position);
48
+ const bbox = this.getElementBBox(textElement, {
49
+ x: relativeX * viewPortSize[0],
50
+ y: relativeY * viewPortSize[1]
51
+ });
52
+ if (declutterTree.collides(bbox)) {
53
+ continue;
54
+ }
55
+ declutterTree.insert(bbox);
56
+ if (this.layer.drawCollisionBoxes) {
57
+ const collisionBoxDebugElement = this.getCollisionBoxElement(bbox);
58
+ textElements.push(collisionBoxDebugElement);
59
+ }
60
+ textElements.push(textElement);
61
+ }
62
+ replaceChildren(this._element, textElements);
63
+ return this._element;
64
+ }
65
+ getTextElementWithID(id) {
66
+ const elementId = `text-feature-${id}`;
67
+ let textElement = this._element.querySelector(`#${elementId}`);
68
+ if (!textElement) {
69
+ textElement = document.createElement("div");
70
+ textElement.id = elementId;
71
+ }
72
+ return textElement;
73
+ }
74
+ styleTextElement(element, textStyle, position) {
75
+ const style = element.style;
76
+ style.position = "absolute";
77
+ style.transform = `translate(-50%, -50%)`;
78
+ style.left = position.left;
79
+ style.top = position.top;
80
+ style.textAlign = "center";
81
+ style.whiteSpace = "nowrap";
82
+ style.fontFamily = textStyle.fontFamily;
83
+ style.fontSize = textStyle.fontSize;
84
+ style.fontWeight = textStyle.fontWeight;
85
+ style.lineHeight = textStyle.lineHeight;
86
+ style.color = textStyle.color;
87
+ style.textShadow = textStyle.textShadow;
88
+ style.padding = `${textPadding.top}px ${textPadding.right}px ${textPadding.bottom}px ${textPadding.left}px`;
89
+ }
90
+ getElementBBox(element, position) {
91
+ if (!element.parentElement) {
92
+ document.body.appendChild(element);
93
+ }
94
+ const { width, height } = element.getBoundingClientRect();
95
+ if (element.parentElement !== this._element) {
96
+ element.remove();
97
+ }
98
+ return {
99
+ minX: Math.floor(position.x) - width / 2,
100
+ minY: Math.floor(position.y) - height / 2,
101
+ maxX: Math.ceil(position.x + width / 2),
102
+ maxY: Math.ceil(position.y + height / 2)
103
+ };
104
+ }
105
+ getCollisionBoxElement(bbox) {
106
+ const element = document.createElement("div");
107
+ const style = element.style;
108
+ style.position = "absolute";
109
+ style.left = `${bbox.minX}px`;
110
+ style.top = `${bbox.minY}px`;
111
+ style.width = `${bbox.maxX - bbox.minX}px`;
112
+ style.height = `${bbox.maxY - bbox.minY}px`;
113
+ style.border = "2px solid black";
114
+ return element;
115
+ }
116
+ }
117
+ export {
118
+ TextLayerRenderer
119
+ };
@@ -0,0 +1,10 @@
1
+ import { FeatureRenderer } from './FeatureRenderer';
2
+ export class VectorLayerRenderer {
3
+ constructor(layer: any);
4
+ layer: any;
5
+ featureRenderer: FeatureRenderer;
6
+ renderFrame(frameState: any, targetElement: any): any;
7
+ getOrCreateContainer(targetElement: any, sizeInPixels: any): any;
8
+ _container: any;
9
+ createContainer(): HTMLDivElement;
10
+ }
@@ -0,0 +1,78 @@
1
+ import { FeatureRenderer } from "./FeatureRenderer.js";
2
+ class VectorLayerRenderer {
3
+ constructor(layer) {
4
+ this.layer = layer;
5
+ this.featureRenderer = new FeatureRenderer();
6
+ }
7
+ renderFrame(frameState, targetElement) {
8
+ if (this.layer.opacity === 0) return targetElement;
9
+ const { projection, sizeInPixels, visibleExtent, transform } = frameState.viewState;
10
+ const container = this.getOrCreateContainer(targetElement, sizeInPixels);
11
+ const context = container.firstElementChild.getContext("2d");
12
+ context.save();
13
+ context.translate(transform.x, transform.y);
14
+ context.scale(transform.k, transform.k);
15
+ context.lineJoin = "round";
16
+ context.lineCap = "round";
17
+ context.globalAlpha = this.layer.opacity;
18
+ const source = this.layer.source;
19
+ const features = source.getFeaturesInExtent(visibleExtent);
20
+ for (const feature of features) {
21
+ const styleFunction = feature.getStyleFunction() || this.layer.getStyleFunction();
22
+ const featureStyle = styleFunction(feature);
23
+ if ((featureStyle == null ? void 0 : featureStyle.stroke) || (featureStyle == null ? void 0 : featureStyle.fill)) {
24
+ context.save();
25
+ this.featureRenderer.setStyle(featureStyle);
26
+ this.featureRenderer.render(frameState, feature, context);
27
+ context.restore();
28
+ }
29
+ }
30
+ if (Object.prototype.hasOwnProperty.call(projection, "getCompositionBorders")) {
31
+ context.beginPath();
32
+ context.lineWidth = 1 / transform.k;
33
+ context.strokeStyle = "#999";
34
+ projection.drawCompositionBorders(context);
35
+ context.stroke();
36
+ }
37
+ context.restore();
38
+ return container;
39
+ }
40
+ getOrCreateContainer(targetElement, sizeInPixels) {
41
+ let container = null;
42
+ let containerReused = false;
43
+ let canvas = targetElement && targetElement.firstElementChild;
44
+ if (canvas instanceof HTMLCanvasElement) {
45
+ container = targetElement;
46
+ containerReused = true;
47
+ } else if (this._container) {
48
+ container = this._container;
49
+ } else {
50
+ container = this.createContainer();
51
+ }
52
+ if (!containerReused) {
53
+ const canvas2 = container.firstElementChild;
54
+ canvas2.width = sizeInPixels[0];
55
+ canvas2.height = sizeInPixels[1];
56
+ }
57
+ this._container = container;
58
+ return container;
59
+ }
60
+ createContainer() {
61
+ const container = document.createElement("div");
62
+ container.className = "gv-map-layer";
63
+ let style = container.style;
64
+ style.position = "absolute";
65
+ style.width = "100%";
66
+ style.height = "100%";
67
+ const canvas = document.createElement("canvas");
68
+ style = canvas.style;
69
+ style.position = "absolute";
70
+ style.width = "100%";
71
+ style.height = "100%";
72
+ container.appendChild(canvas);
73
+ return container;
74
+ }
75
+ }
76
+ export {
77
+ VectorLayerRenderer
78
+ };
@@ -0,0 +1,15 @@
1
+ import { Dispatcher } from '../events';
2
+ import { default as RBush } from 'rbush';
3
+ export class VectorSource {
4
+ constructor({ features }: {
5
+ features: any;
6
+ });
7
+ dispatcher: Dispatcher;
8
+ _featuresRtree: RBush;
9
+ tearDown(): void;
10
+ getFeatures(): any;
11
+ getFeaturesAtCoordinate(coordinate: any): any[];
12
+ getFeaturesInExtent(extent: any): any[];
13
+ setFeatures(features: any): void;
14
+ _features: any;
15
+ }
@@ -0,0 +1,56 @@
1
+ import RBush from "rbush";
2
+ import knn from "rbush-knn";
3
+ import { Dispatcher } from "../events/Dispatcher.js";
4
+ import { MapEvent } from "../events/MapEvent.js";
5
+ class VectorSource {
6
+ constructor({ features }) {
7
+ this.dispatcher = new Dispatcher(this);
8
+ this._featuresRtree = new RBush();
9
+ this.setFeatures(features);
10
+ }
11
+ tearDown() {
12
+ this.dispatcher = null;
13
+ }
14
+ getFeatures() {
15
+ return this._features;
16
+ }
17
+ getFeaturesAtCoordinate(coordinate) {
18
+ const [lon, lat] = coordinate;
19
+ const features = knn(
20
+ this._featuresRtree,
21
+ lon,
22
+ lat,
23
+ 10,
24
+ (d) => d.feature.containsCoordinate(coordinate)
25
+ ).map((d) => {
26
+ const midX = d.minX + (d.minX + d.maxX) / 2;
27
+ const midY = d.minY + (d.minY + d.maxY) / 2;
28
+ d.distance = Math.hypot(midX - lon, midY - lat);
29
+ return d;
30
+ });
31
+ features.sort((a, b) => a.distance - b.distance);
32
+ return features.map((d) => d.feature);
33
+ }
34
+ getFeaturesInExtent(extent) {
35
+ const [minX, minY, maxX, maxY] = extent;
36
+ return this._featuresRtree.search({ minX, minY, maxX, maxY }).map((d) => d.feature);
37
+ }
38
+ setFeatures(features) {
39
+ this._featuresRtree.clear();
40
+ for (const feature of features) {
41
+ const [minX, minY, maxX, maxY] = feature.getExtent();
42
+ this._featuresRtree.insert({
43
+ minX: Math.floor(minX),
44
+ minY: Math.floor(minY),
45
+ maxX: Math.ceil(maxX),
46
+ maxY: Math.ceil(maxY),
47
+ feature
48
+ });
49
+ }
50
+ this._features = features;
51
+ this.dispatcher.dispatch(MapEvent.CHANGE);
52
+ }
53
+ }
54
+ export {
55
+ VectorSource
56
+ };
@@ -0,0 +1,7 @@
1
+ export class Fill {
2
+ constructor(options: any);
3
+ color: any;
4
+ opacity: any;
5
+ _getRgba: (...arg0: any[]) => string;
6
+ getRgba(): string;
7
+ }
@@ -0,0 +1,15 @@
1
+ import { memoise } from "../util/memoise.js";
2
+ import { toRgba } from "../util/toRgba.js";
3
+ class Fill {
4
+ constructor(options) {
5
+ this.color = (options == null ? void 0 : options.color) || "#CCC";
6
+ this.opacity = (options == null ? void 0 : options.opacity) || 1;
7
+ this._getRgba = memoise(toRgba);
8
+ }
9
+ getRgba() {
10
+ return this._getRgba(this.color, this.opacity);
11
+ }
12
+ }
13
+ export {
14
+ Fill
15
+ };
@@ -0,0 +1,8 @@
1
+ export class Stroke {
2
+ constructor(options: any);
3
+ color: any;
4
+ width: any;
5
+ opacity: any;
6
+ _getRgba: (...arg0: any[]) => string;
7
+ getRgba(): string;
8
+ }