@mwater/visualization 5.2.0 → 5.3.1

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 (254) hide show
  1. package/lib/ColorComponent.d.ts +10 -11
  2. package/lib/ColorComponent.js +78 -29
  3. package/lib/ColorSchemeFactory.d.ts +13 -2
  4. package/lib/ColorSchemeFactory.js +7 -5
  5. package/lib/CustomColorsContext.d.ts +6 -0
  6. package/lib/CustomColorsContext.js +6 -0
  7. package/lib/FiltersDesignerComponent.d.ts +1 -4
  8. package/lib/FiltersDesignerComponent.js +2 -3
  9. package/lib/LocaleContextInjector.d.ts +5 -11
  10. package/lib/LocaleContextInjector.js +4 -12
  11. package/lib/MWaterAddRelatedFormComponent.js +3 -3
  12. package/lib/MWaterAddRelatedIndicatorComponent.d.ts +1 -4
  13. package/lib/MWaterAddRelatedIndicatorComponent.js +6 -6
  14. package/lib/MWaterCompleteTableSelectComponent.d.ts +5 -16
  15. package/lib/MWaterCompleteTableSelectComponent.js +36 -36
  16. package/lib/MWaterContextComponent.d.ts +4 -6
  17. package/lib/MWaterContextComponent.js +4 -13
  18. package/lib/MWaterLoaderComponent.d.ts +5 -3
  19. package/lib/MWaterLoaderComponent.js +2 -1
  20. package/lib/MWaterTableSelectComponent.d.ts +1 -4
  21. package/lib/MWaterTableSelectComponent.js +10 -12
  22. package/lib/UIComponents.d.ts +2 -2
  23. package/lib/UIComponents.js +4 -12
  24. package/lib/axes/AxisBuilder.d.ts +7 -4
  25. package/lib/axes/AxisBuilder.js +3 -1
  26. package/lib/axes/AxisComponent.d.ts +2 -5
  27. package/lib/axes/AxisComponent.js +1 -2
  28. package/lib/axes/ColorPaletteCollectionComponent.d.ts +5 -12
  29. package/lib/axes/ColorPaletteCollectionComponent.js +67 -36
  30. package/lib/dashboards/DashboardComponent.d.ts +4 -12
  31. package/lib/dashboards/DashboardComponent.js +18 -38
  32. package/lib/dashboards/DashboardDesign.d.ts +3 -3
  33. package/lib/dashboards/DashboardUpgrader.js +36 -1
  34. package/lib/dashboards/DashboardViewComponent.d.ts +5 -34
  35. package/lib/dashboards/DashboardViewComponent.js +109 -132
  36. package/lib/dashboards/FontStyleEditor.d.ts +8 -0
  37. package/lib/dashboards/FontStyleEditor.js +130 -0
  38. package/lib/dashboards/LayoutOptionsComponent.d.ts +0 -1
  39. package/lib/dashboards/LayoutOptionsComponent.js +211 -42
  40. package/lib/dashboards/ServerDashboardDataSource.d.ts +1 -2
  41. package/lib/dashboards/ServerDashboardDataSource.js +52 -33
  42. package/lib/dashboards/WidgetComponent.d.ts +3 -3
  43. package/lib/dashboards/WidgetComponent.js +3 -6
  44. package/lib/dashboards/WidgetDataSourcePrioritizer.d.ts +20 -0
  45. package/lib/dashboards/WidgetDataSourcePrioritizer.js +72 -0
  46. package/lib/dashboards/layoutOptions.d.ts +83 -0
  47. package/lib/dashboards/layoutOptions.js +436 -10
  48. package/lib/datagrids/DatagridDesign.d.ts +7 -6
  49. package/lib/datagrids/ServerDatagridDataSource.d.ts +7 -6
  50. package/lib/datagrids/ServerDatagridDataSource.js +87 -33
  51. package/lib/demo.js +3 -3
  52. package/lib/index.css +5 -0
  53. package/lib/index.d.ts +1 -1
  54. package/lib/index.js +0 -1
  55. package/lib/layouts/LayoutManager.d.ts +33 -29
  56. package/lib/layouts/LayoutManager.js +2 -8
  57. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +26 -57
  58. package/lib/layouts/blocks/BlocksDisplayComponent.js +122 -205
  59. package/lib/layouts/blocks/BlocksLayoutManager.d.ts +6 -22
  60. package/lib/layouts/blocks/BlocksLayoutManager.js +5 -14
  61. package/lib/layouts/blocks/HorizontalBlockComponent.d.ts +5 -4
  62. package/lib/layouts/blocks/HorizontalBlockComponent.js +5 -5
  63. package/lib/mWaterLoader.d.ts +2 -0
  64. package/lib/mWaterLoader.js +2 -1
  65. package/lib/maps/AddLayerComponent.d.ts +6 -8
  66. package/lib/maps/AddLayerComponent.js +6 -6
  67. package/lib/maps/BingLayer.js +10 -20
  68. package/lib/maps/BufferLayer.js +2 -1
  69. package/lib/maps/ChoroplethLayer.js +2 -1
  70. package/lib/maps/DirectMapDataSource.d.ts +5 -2
  71. package/lib/maps/DirectMapDataSource.js +2 -1
  72. package/lib/maps/EditPopupComponent.js +2 -1
  73. package/lib/maps/MapComponent.d.ts +1 -4
  74. package/lib/maps/MapComponent.js +3 -3
  75. package/lib/maps/MarkersLayer.js +30 -25
  76. package/lib/maps/RasterMapViewComponent.d.ts +1 -4
  77. package/lib/maps/RasterMapViewComponent.js +3 -3
  78. package/lib/maps/ServerMapDataSource.d.ts +2 -3
  79. package/lib/maps/ServerMapDataSource.js +5 -5
  80. package/lib/maps/VectorMapViewComponent.js +2 -1
  81. package/lib/maps/mapSymbols.js +2 -0
  82. package/lib/maps/symbols/font-awesome/cloud-rain.png +0 -0
  83. package/lib/maps/vectorMaps.js +61 -55
  84. package/lib/quickfilter/QuickfiltersComponent.d.ts +1 -4
  85. package/lib/quickfilter/QuickfiltersComponent.js +3 -3
  86. package/lib/richtext/DropdownPaletteItem.d.ts +32 -0
  87. package/lib/richtext/DropdownPaletteItem.js +82 -0
  88. package/lib/richtext/FontColorPaletteItem.d.ts +1 -5
  89. package/lib/richtext/FontColorPaletteItem.js +32 -27
  90. package/lib/richtext/ItemsHtmlConverter.js +12 -3
  91. package/lib/richtext/RichTextComponent.d.ts +26 -52
  92. package/lib/richtext/RichTextComponent.js +166 -128
  93. package/lib/valueFormatter.js +6 -1
  94. package/lib/wellknown.d.ts +5 -0
  95. package/lib/wellknown.js +288 -0
  96. package/lib/widgets/DropdownWidgetComponent.d.ts +8 -25
  97. package/lib/widgets/DropdownWidgetComponent.js +48 -25
  98. package/lib/widgets/IFrameWidgetComponent.d.ts +1 -2
  99. package/lib/widgets/ImageWidgetComponent.d.ts +2 -3
  100. package/lib/widgets/MapWidget.d.ts +2 -0
  101. package/lib/widgets/MapWidget.js +2 -1
  102. package/lib/widgets/TOCWidget.js +2 -1
  103. package/lib/widgets/Widget.d.ts +2 -0
  104. package/lib/widgets/WidgetDataSource.d.ts +3 -1
  105. package/lib/widgets/charts/Chart.d.ts +0 -1
  106. package/lib/widgets/charts/ChartViewComponent.d.ts +4 -0
  107. package/lib/widgets/charts/ChartViewComponent.js +11 -3
  108. package/lib/widgets/charts/ChartWidget.d.ts +1 -62
  109. package/lib/widgets/charts/ChartWidget.js +4 -183
  110. package/lib/widgets/charts/ChartWidgetComponent.d.ts +51 -0
  111. package/lib/widgets/charts/ChartWidgetComponent.js +167 -0
  112. package/lib/widgets/charts/calendar/CalendarChartViewComponent.d.ts +1 -4
  113. package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +4 -4
  114. package/lib/widgets/charts/layered/LayeredChart.d.ts +5 -10
  115. package/lib/widgets/charts/layered/LayeredChart.js +6 -7
  116. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +4 -2
  117. package/lib/widgets/charts/layered/LayeredChartCompiler.js +46 -32
  118. package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +4 -0
  119. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +3 -0
  120. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +21 -3
  121. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +1 -2
  122. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +2 -1
  123. package/lib/widgets/charts/layered/LayeredChartViewComponent.d.ts +1 -4
  124. package/lib/widgets/charts/layered/LayeredChartViewComponent.js +89 -38
  125. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +5 -112
  126. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.js +122 -166
  127. package/lib/widgets/charts/pivot/PivotChart.d.ts +6 -0
  128. package/lib/widgets/charts/pivot/PivotChart.js +47 -17
  129. package/lib/widgets/charts/pivot/PivotChartDesign.d.ts +11 -0
  130. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +1 -1
  131. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +1 -1
  132. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +2 -2
  133. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +20 -36
  134. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +0 -1
  135. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.d.ts +23 -2
  136. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.js +215 -181
  137. package/lib/widgets/charts/pivot/PivotChartUtils.d.ts +2 -2
  138. package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +9 -28
  139. package/lib/widgets/charts/pivot/PivotChartViewComponent.js +20 -60
  140. package/lib/widgets/charts/table/TableChart.js +8 -4
  141. package/lib/widgets/charts/table/TableChartDesignerComponent.js +3 -3
  142. package/lib/widgets/charts/table/TableChartViewComponent.js +11 -11
  143. package/lib/widgets/text/TextComponent.d.ts +5 -12
  144. package/lib/widgets/text/TextComponent.js +19 -39
  145. package/lib/widgets/text/TextWidget.d.ts +2 -1
  146. package/lib/widgets/text/TextWidget.js +5 -1
  147. package/lib/widgets/text/TextWidgetComponent.d.ts +15 -3
  148. package/lib/widgets/text/TextWidgetComponent.js +76 -19
  149. package/lib/widgets/text/TextWidgetDesign.d.ts +13 -1
  150. package/lib/widgets/text/TextWidgetDesign.js +6 -0
  151. package/package.json +4 -4
  152. package/src/ColorComponent.tsx +177 -0
  153. package/src/ColorSchemeFactory.ts +12 -6
  154. package/src/CustomColorsContext.tsx +9 -0
  155. package/src/FiltersDesignerComponent.ts +3 -4
  156. package/src/LocaleContextInjector.tsx +14 -13
  157. package/src/MWaterAddRelatedFormComponent.ts +3 -3
  158. package/src/MWaterAddRelatedIndicatorComponent.ts +6 -6
  159. package/src/MWaterCompleteTableSelectComponent.tsx +36 -36
  160. package/src/MWaterContextComponent.tsx +8 -17
  161. package/src/MWaterLoaderComponent.ts +6 -3
  162. package/src/MWaterTableSelectComponent.tsx +11 -12
  163. package/src/{UIComponents.ts → UIComponents.tsx} +7 -15
  164. package/src/axes/AxisBuilder.ts +7 -5
  165. package/src/axes/AxisComponent.ts +3 -4
  166. package/src/axes/{ColorPaletteCollectionComponent.ts → ColorPaletteCollectionComponent.tsx} +87 -61
  167. package/src/dashboards/DashboardComponent.tsx +71 -107
  168. package/src/dashboards/DashboardDesign.ts +3 -3
  169. package/src/dashboards/DashboardUpgrader.ts +41 -1
  170. package/src/dashboards/DashboardViewComponent.tsx +313 -0
  171. package/src/dashboards/FontStyleEditor.tsx +166 -0
  172. package/src/dashboards/LayoutOptionsComponent.tsx +380 -75
  173. package/src/dashboards/ServerDashboardDataSource.ts +52 -33
  174. package/src/dashboards/WidgetComponent.tsx +6 -12
  175. package/src/dashboards/WidgetDataSourcePrioritizer.ts +82 -0
  176. package/src/dashboards/layoutOptions.tsx +581 -0
  177. package/src/datagrids/DatagridDesign.ts +8 -3
  178. package/src/datagrids/ServerDatagridDataSource.ts +106 -43
  179. package/src/demo.ts +3 -3
  180. package/src/index.css +5 -0
  181. package/src/index.ts +1 -1
  182. package/src/layouts/LayoutManager.ts +44 -42
  183. package/src/layouts/blocks/BlocksDisplayComponent.tsx +498 -0
  184. package/src/layouts/blocks/BlocksLayoutManager.ts +6 -15
  185. package/src/layouts/blocks/HorizontalBlockComponent.ts +9 -8
  186. package/src/mWaterLoader.ts +4 -1
  187. package/src/maps/AddLayerComponent.ts +9 -9
  188. package/src/maps/BingLayer.ts +16 -26
  189. package/src/maps/BufferLayer.ts +2 -1
  190. package/src/maps/ChoroplethLayer.ts +2 -1
  191. package/src/maps/DirectMapDataSource.ts +12 -3
  192. package/src/maps/EditPopupComponent.ts +2 -1
  193. package/src/maps/MapComponent.ts +3 -3
  194. package/src/maps/MarkersLayer.ts +38 -41
  195. package/src/maps/RasterMapViewComponent.ts +3 -3
  196. package/src/maps/ServerMapDataSource.ts +7 -7
  197. package/src/maps/VectorMapViewComponent.tsx +2 -1
  198. package/src/maps/mapSymbols.ts +2 -0
  199. package/src/maps/symbols/font-awesome/cloud-rain.png +0 -0
  200. package/src/maps/vectorMaps.tsx +79 -74
  201. package/src/quickfilter/QuickfiltersComponent.ts +3 -3
  202. package/src/richtext/DropdownPaletteItem.tsx +144 -0
  203. package/src/richtext/FontColorPaletteItem.tsx +160 -0
  204. package/src/richtext/ItemsHtmlConverter.ts +15 -5
  205. package/src/richtext/RichTextComponent.tsx +274 -232
  206. package/src/valueFormatter.ts +5 -1
  207. package/src/wellknown.ts +286 -0
  208. package/src/widgets/DropdownWidgetComponent.tsx +75 -0
  209. package/src/widgets/MapWidget.ts +5 -2
  210. package/src/widgets/TOCWidget.ts +2 -1
  211. package/src/widgets/Widget.ts +3 -0
  212. package/src/widgets/WidgetDataSource.ts +3 -1
  213. package/src/widgets/charts/Chart.ts +1 -1
  214. package/src/widgets/charts/ChartViewComponent.ts +16 -3
  215. package/src/widgets/charts/ChartWidget.ts +3 -275
  216. package/src/widgets/charts/ChartWidgetComponent.tsx +281 -0
  217. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +4 -4
  218. package/src/widgets/charts/layered/LayeredChart.ts +4 -6
  219. package/src/widgets/charts/layered/LayeredChartCompiler.ts +80 -63
  220. package/src/widgets/charts/layered/LayeredChartDesign.ts +7 -1
  221. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +43 -10
  222. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +6 -6
  223. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +140 -88
  224. package/src/widgets/charts/pivot/IntersectionDesignerComponent.tsx +305 -221
  225. package/src/widgets/charts/pivot/PivotChart.ts +56 -18
  226. package/src/widgets/charts/pivot/PivotChartDesign.ts +12 -0
  227. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +4 -3
  228. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +39 -76
  229. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +0 -1
  230. package/src/widgets/charts/pivot/PivotChartQueryBuilder.ts +230 -189
  231. package/src/widgets/charts/pivot/PivotChartUtils.ts +4 -4
  232. package/src/widgets/charts/pivot/{PivotChartViewComponent.ts → PivotChartViewComponent.tsx} +86 -89
  233. package/src/widgets/charts/table/TableChart.ts +8 -4
  234. package/src/widgets/charts/table/TableChartDesignerComponent.ts +4 -4
  235. package/src/widgets/charts/table/TableChartViewComponent.ts +13 -14
  236. package/src/widgets/text/TextComponent.tsx +47 -49
  237. package/src/widgets/text/TextWidget.ts +8 -3
  238. package/src/widgets/text/TextWidgetComponent.tsx +249 -0
  239. package/src/widgets/text/TextWidgetDesign.ts +22 -1
  240. package/src/ColorComponent.ts +0 -117
  241. package/src/dashboards/DashboardViewComponent.ts +0 -303
  242. package/src/dashboards/layoutOptions.ts +0 -40
  243. package/src/layout-styles.css +0 -263
  244. package/src/layouts/blocks/BlocksDisplayComponent.ts +0 -461
  245. package/src/layouts/grid/GridLayoutComponent.ts +0 -67
  246. package/src/layouts/grid/GridLayoutManager.ts +0 -185
  247. package/src/layouts/grid/LegoLayoutEngine.ts +0 -142
  248. package/src/layouts/grid/PaletteItemComponent.ts +0 -28
  249. package/src/layouts/grid/README.md +0 -14
  250. package/src/layouts/grid/WidgetContainerComponent.ts +0 -420
  251. package/src/richtext/FontColorPaletteItem.ts +0 -172
  252. package/src/richtext/FontSizePaletteItem.ts +0 -110
  253. package/src/widgets/DropdownWidgetComponent.ts +0 -78
  254. package/src/widgets/text/TextWidgetComponent.ts +0 -120
@@ -1,16 +1,15 @@
1
- import React, { ReactNode } from "react"
2
- const R = React.createElement
1
+ import React, { ReactNode, CSSProperties, MouseEvent } from "react"
3
2
  import _ from "lodash"
4
3
  import { ContentEditableComponent } from "@mwater/expressions-ui"
5
4
  import ItemsHtmlConverter, { HtmlItem } from "./ItemsHtmlConverter"
6
5
  import FloatAffixed from "react-float-affixed"
7
6
  import FontColorPaletteItem from "./FontColorPaletteItem"
8
- import FontSizePaletteItem from "./FontSizePaletteItem"
7
+ import DropdownPaletteItem from "./DropdownPaletteItem"
9
8
 
10
9
  export interface RichTextComponentProps {
11
10
  // Items (content) to display. See ItemsHtmlConverter
12
11
  items?: HtmlItem[]
13
- onItemsChange: (items: HtmlItem[]) => void
12
+ onItemsChange?: (items: HtmlItem[]) => void
14
13
 
15
14
  onItemClick?: (item: HtmlItem) => void
16
15
 
@@ -18,7 +17,7 @@ export interface RichTextComponentProps {
18
17
  className?: string
19
18
 
20
19
  /** Optional style of editor wrapper */
21
- style?: any
20
+ style?: CSSProperties
22
21
 
23
22
  /** Converter to use for editing */
24
23
  itemsHtmlConverter?: ItemsHtmlConverter
@@ -30,17 +29,25 @@ export interface RichTextComponentProps {
30
29
  extraPaletteButtons?: ReactNode
31
30
  }
32
31
 
33
- export default class RichTextComponent extends React.Component<RichTextComponentProps, { focused: boolean }> {
32
+ interface RichTextComponentState {
33
+ focused: boolean
34
+ }
35
+
36
+ export default class RichTextComponent extends React.Component<RichTextComponentProps, RichTextComponentState> {
34
37
  static defaultProps = {
35
38
  includeHeadings: true,
36
39
  items: [],
37
40
  itemsHtmlConverter: new ItemsHtmlConverter(),
38
41
  }
39
- entireComponent: HTMLElement | null
40
- contentEditable: ContentEditableComponent | null
41
- paletteComponent: HTMLElement | null
42
+ entireComponent: HTMLElement | null = null
43
+ contentEditable: ContentEditableComponent | null = null
44
+ paletteComponent: HTMLElement | null = null
45
+
46
+ /** Number of changes in progress. Used with beginChanges and endChanges
47
+ * to prevent onChange being called during a change */
48
+ changesInProgress: number = 0
42
49
 
43
- constructor(props: any) {
50
+ constructor(props: RichTextComponentProps) {
44
51
  super(props)
45
52
 
46
53
  this.state = {
@@ -48,18 +55,18 @@ export default class RichTextComponent extends React.Component<RichTextComponent
48
55
  }
49
56
  }
50
57
 
51
- handleClick = (ev: any) => {
58
+ handleClick = (ev: MouseEvent) => {
52
59
  // If click is in component or in palette component, ignore, otherwise remove focus
53
60
  if (
54
- !this.entireComponent!.contains(ev.target) &&
55
- (!this.paletteComponent || !this.paletteComponent.contains(ev.target))
61
+ !this.entireComponent!.contains(ev.target as Node) &&
62
+ (!this.paletteComponent || !this.paletteComponent.contains(ev.target as Node))
56
63
  ) {
57
64
  return this.setState({ focused: false })
58
65
  }
59
66
  }
60
67
 
61
68
  // Paste HTML in
62
- pasteHTML(html: any) {
69
+ pasteHTML(html: string) {
63
70
  this.contentEditable!.pasteHTML(html)
64
71
  }
65
72
 
@@ -67,27 +74,24 @@ export default class RichTextComponent extends React.Component<RichTextComponent
67
74
  this.contentEditable!.focus()
68
75
  }
69
76
 
70
- handleInsertExpr = (item: any) => {
71
- const html = '<div data-embed="' + _.escape(JSON.stringify(item)) + '"></div>'
72
-
73
- this.contentEditable!.pasteHTML(html)
77
+ beginChanges() {
78
+ this.changesInProgress++
74
79
  }
75
80
 
76
- handleSetFontSize = (size: any) => {
77
- // Requires a selection
78
- let html = this.contentEditable!.getSelectedHTML()
79
- if (!html) {
80
- return alert("Please select text first to set size")
81
+ endChanges() {
82
+ this.changesInProgress--
83
+ if (this.changesInProgress === 0) {
84
+ this.handleChange(this.contentEditable!.getEditor())
81
85
  }
86
+ }
82
87
 
83
- // Clear existing font-size styles. This is clearly a hack, but font sizes are absolute in execCommand which
84
- // doesn't mix with our various dashboard stylings, so we need to use percentages
85
- html = html.replace(/font-size:\s*\d+%;?/g, "")
88
+ handleInsertExpr = (item: any) => {
89
+ const html = '<div data-embed="' + _.escape(JSON.stringify(item)) + '"></div>'
86
90
 
87
- return this.contentEditable!.pasteHTML(`<span style=\"font-size:${size}\">` + html + "</span>")
91
+ this.contentEditable!.pasteHTML(html)
88
92
  }
89
93
 
90
- handleSetFontColor = (color: any) => {
94
+ handleSetFontColor = (color: string) => {
91
95
  // Requires a selection
92
96
  const html = this.contentEditable!.getSelectedHTML()
93
97
  if (!html) {
@@ -97,7 +101,66 @@ export default class RichTextComponent extends React.Component<RichTextComponent
97
101
  this.handleCommand("foreColor", color)
98
102
  }
99
103
 
100
- handleChange = (elem: any) => {
104
+ handleSetFontSize = (tag: string, size: string | null) => {
105
+ this.beginChanges()
106
+ try {
107
+ this.handleCommand("formatBlock", `<${tag}>`)
108
+
109
+ const selection = window.getSelection()
110
+ if (!selection || !selection.rangeCount) return
111
+
112
+ // Function to apply or remove font size
113
+ const applyFontSize = (element: HTMLElement) => {
114
+ if (size === null) {
115
+ element.style.removeProperty("font-size")
116
+ } else {
117
+ element.style.fontSize = size
118
+ }
119
+ }
120
+
121
+ // Get the start and end containers of the selection
122
+ const range = selection.getRangeAt(0)
123
+ let startNode = range.startContainer.nodeType === Node.TEXT_NODE ? range.startContainer.parentElement : range.startContainer.childNodes[range.startOffset] as HTMLElement
124
+ let endNode = range.endContainer.nodeType === Node.TEXT_NODE ? range.endContainer.parentElement : range.endContainer.childNodes[range.endOffset] as HTMLElement
125
+
126
+ // Find element that has parent with contentEditable
127
+ while (startNode && !startNode.parentElement?.contentEditable) {
128
+ startNode = startNode.parentElement
129
+ }
130
+ while (endNode && !endNode.parentElement?.contentEditable) {
131
+ endNode = endNode.parentElement
132
+ }
133
+
134
+ if (!startNode || !endNode || startNode.nodeType !== Node.ELEMENT_NODE || endNode.nodeType !== Node.ELEMENT_NODE) {
135
+ return
136
+ }
137
+
138
+ // Get array of nodes between start and end
139
+ const rootElements: HTMLElement[] = []
140
+ let node: Node | null = startNode
141
+ while (node !== null) {
142
+ if (node.nodeType === Node.ELEMENT_NODE) {
143
+ rootElements.push(node as HTMLElement)
144
+ }
145
+ if (node === endNode) {
146
+ break
147
+ }
148
+ node = node.nextSibling
149
+ }
150
+
151
+ for (const element of rootElements) {
152
+ applyFontSize(element)
153
+ }
154
+ } finally {
155
+ this.endChanges()
156
+ }
157
+ }
158
+
159
+ handleChange = (elem: HTMLElement) => {
160
+ if (this.changesInProgress > 0) {
161
+ return
162
+ }
163
+
101
164
  const items = this.props.itemsHtmlConverter!.convertElemToItems(elem)
102
165
 
103
166
  // Check if changed
@@ -110,14 +173,15 @@ export default class RichTextComponent extends React.Component<RichTextComponent
110
173
  }
111
174
 
112
175
  handleFocus = () => {
113
- return this.setState({ focused: true })
176
+ this.setState({ focused: true })
114
177
  }
178
+
115
179
  handleBlur = () => {
116
- return this.setState({ focused: false })
180
+ this.setState({ focused: false })
117
181
  }
118
182
 
119
183
  // Perform a command such as bold, underline, etc.
120
- handleCommand = (command: any, param: any, ev?: any) => {
184
+ handleCommand = (command: string, param: any, ev?: MouseEvent) => {
121
185
  // Don't lose focus
122
186
  ev?.preventDefault()
123
187
 
@@ -125,13 +189,13 @@ export default class RichTextComponent extends React.Component<RichTextComponent
125
189
  if (["foreColor"].includes(command)) {
126
190
  document.execCommand("styleWithCSS", null as any, true as any)
127
191
  document.execCommand(command, false, param)
128
- return document.execCommand("styleWithCSS", null as any, false as any)
192
+ document.execCommand("styleWithCSS", null as any, false as any)
129
193
  } else {
130
- return document.execCommand(command, false, param)
194
+ document.execCommand(command, false, param)
131
195
  }
132
196
  }
133
197
 
134
- handleCreateLink = (ev: any) => {
198
+ handleCreateLink = (ev: MouseEvent) => {
135
199
  // Don't lose focus
136
200
  ev.preventDefault()
137
201
 
@@ -142,16 +206,17 @@ export default class RichTextComponent extends React.Component<RichTextComponent
142
206
  }
143
207
  }
144
208
 
145
- handleEditorClick = (ev: any) => {
209
+ handleEditorClick = (ev: MouseEvent) => {
146
210
  // Be sure focused
147
211
  if (!this.state.focused) {
148
212
  this.setState({ focused: true })
149
213
  }
150
214
 
151
- if (ev.target.dataset?.embed || ev.target.parentElement?.dataset?.embed) {
152
- const item = JSON.parse(ev.target.dataset?.embed || ev.target.parentElement?.dataset?.embed)
215
+ const target = ev.target as HTMLElement
216
+ if (target.dataset?.embed || target.parentElement?.dataset?.embed) {
217
+ const item = JSON.parse(target.dataset?.embed || target.parentElement?.dataset?.embed!)
153
218
  if (item != null) {
154
- return this.props.onItemClick?.(item)
219
+ this.props.onItemClick?.(item)
155
220
  }
156
221
  }
157
222
  }
@@ -173,162 +238,142 @@ export default class RichTextComponent extends React.Component<RichTextComponent
173
238
  elem = elem.parentElement
174
239
  }
175
240
 
176
- return R(FloatAffixed, {
177
- style: { zIndex },
178
- edges: "over,under,left,right",
179
- align: "center",
180
- render: this.renderPaletteContent,
181
- })
241
+ return (
242
+ <FloatAffixed
243
+ style={{ zIndex }}
244
+ edges="over,under,left,right"
245
+ align="center"
246
+ render={this.renderPaletteContent}
247
+ />
248
+ )
182
249
  }
183
250
 
184
- renderPaletteContent = (schemeName: any, { edges }: any) => {
185
- return R(
186
- "div",
187
- {
188
- key: "palette",
189
- className: "mwater-visualization-text-palette",
190
- ref: (c: HTMLElement | null) => {
251
+ renderPaletteContent = (schemeName: string, { edges }: { edges: string }) => {
252
+ return (
253
+ <div
254
+ key="palette"
255
+ className="mwater-visualization-text-palette"
256
+ ref={(c: HTMLElement | null) => {
191
257
  this.paletteComponent = c
192
- },
193
- },
194
- R(
195
- "div",
196
- {
197
- key: "bold",
198
- className: "mwater-visualization-text-palette-item",
199
- onMouseDown: this.handleCommand.bind(null, "bold", null),
200
- },
201
- R("b", null, "B")
202
- ),
203
- R(
204
- "div",
205
- {
206
- key: "italic",
207
- className: "mwater-visualization-text-palette-item",
208
- onMouseDown: this.handleCommand.bind(null, "italic", null),
209
- },
210
- R("i", null, "I")
211
- ),
212
- R(
213
- "div",
214
- {
215
- key: "underline",
216
- className: "mwater-visualization-text-palette-item",
217
- onMouseDown: this.handleCommand.bind(null, "underline", null),
218
- },
219
- R("span", { style: { textDecoration: "underline" } }, "U")
220
- ),
221
- R(FontColorPaletteItem, {
222
- key: "foreColor",
223
- onSetColor: this.handleSetFontColor,
224
- position: schemeName === "over" ? "under" : "over",
225
- }),
226
- R(FontSizePaletteItem, {
227
- key: "fontSize",
228
- onSetSize: this.handleSetFontSize,
229
- position: schemeName === "over" ? "under" : "over",
230
- }),
231
- R(
232
- "div",
233
- { key: "link", className: "mwater-visualization-text-palette-item", onMouseDown: this.handleCreateLink },
234
- R("i", { className: "fa fa-link" })
235
- ),
236
- R(
237
- "div",
238
- {
239
- key: "justifyLeft",
240
- className: "mwater-visualization-text-palette-item",
241
- onMouseDown: this.handleCommand.bind(null, "justifyLeft", null),
242
- },
243
- R("i", { className: "fa fa-align-left" })
244
- ),
245
- R(
246
- "div",
247
- {
248
- key: "justifyCenter",
249
- className: "mwater-visualization-text-palette-item",
250
- onMouseDown: this.handleCommand.bind(null, "justifyCenter", null),
251
- },
252
- R("i", { className: "fa fa-align-center" })
253
- ),
254
- R(
255
- "div",
256
- {
257
- key: "justifyRight",
258
- className: "mwater-visualization-text-palette-item",
259
- onMouseDown: this.handleCommand.bind(null, "justifyRight", null),
260
- },
261
- R("i", { className: "fa fa-align-right" })
262
- ),
263
- R(
264
- "div",
265
- {
266
- key: "justifyFull",
267
- className: "mwater-visualization-text-palette-item",
268
- onMouseDown: this.handleCommand.bind(null, "justifyFull", null),
269
- },
270
- R("i", { className: "fa fa-align-justify" })
271
- ),
272
- R(
273
- "div",
274
- {
275
- key: "insertUnorderedList",
276
- className: "mwater-visualization-text-palette-item",
277
- onMouseDown: this.handleCommand.bind(null, "insertUnorderedList", null),
278
- },
279
- R("i", { className: "fa fa-list-ul" })
280
- ),
281
- R(
282
- "div",
283
- {
284
- key: "insertOrderedList",
285
- className: "mwater-visualization-text-palette-item",
286
- onMouseDown: this.handleCommand.bind(null, "insertOrderedList", null),
287
- },
288
- R("i", { className: "fa fa-list-ol" })
289
- ),
290
- this.props.includeHeadings
291
- ? [
292
- R(
293
- "div",
294
- {
295
- key: "h1",
296
- className: "mwater-visualization-text-palette-item",
297
- onMouseDown: this.handleCommand.bind(null, "formatBlock", "<H1>"),
298
- },
299
- R("i", { className: "fa fa-header" })
300
- ),
301
- R(
302
- "div",
303
- {
304
- key: "h2",
305
- className: "mwater-visualization-text-palette-item",
306
- onMouseDown: this.handleCommand.bind(null, "formatBlock", "<H2>"),
307
- },
308
- R("i", { className: "fa fa-header", style: { fontSize: "80%" } })
309
- ),
310
- R(
311
- "div",
312
- {
313
- key: "p",
314
- className: "mwater-visualization-text-palette-item",
315
- onMouseDown: this.handleCommand.bind(null, "formatBlock", "<div>"),
316
- },
317
- "\u00b6"
318
- ),
319
- ]
320
- : undefined,
321
- R(
322
- "div",
323
- {
324
- key: "removeFormat",
325
- className: "mwater-visualization-text-palette-item",
326
- onMouseDown: this.handleCommand.bind(null, "removeFormat", null),
327
- style: { paddingLeft: 5, paddingRight: 5 },
328
- },
329
- R("img", { src: removeFormatIcon, style: { height: 20 } })
330
- ),
331
- this.props.extraPaletteButtons
258
+ }}
259
+ >
260
+ <div
261
+ key="bold"
262
+ className="mwater-visualization-text-palette-item"
263
+ onMouseDown={(ev) => this.handleCommand("bold", null, ev)}
264
+ >
265
+ <i className="fas fa-bold" />
266
+ </div>
267
+ <div
268
+ key="italic"
269
+ className="mwater-visualization-text-palette-item"
270
+ onMouseDown={(ev) => this.handleCommand("italic", null, ev)}
271
+ >
272
+ <i className="fas fa-italic" />
273
+ </div>
274
+ <div
275
+ key="underline"
276
+ className="mwater-visualization-text-palette-item"
277
+ onMouseDown={(ev) => this.handleCommand("underline", null, ev)}
278
+ >
279
+ <i className="fas fa-underline" />
280
+ </div>
281
+ <FontColorPaletteItem
282
+ key="foreColor"
283
+ onSetColor={this.handleSetFontColor}
284
+ position={schemeName === "over" ? "under" : "over"}
285
+ />
286
+ <div
287
+ key="link"
288
+ className="mwater-visualization-text-palette-item"
289
+ onMouseDown={(ev) => this.handleCreateLink(ev)}
290
+ >
291
+ <i className="fas fa-link" />
292
+ </div>
293
+ <div
294
+ key="removeFormat"
295
+ className="mwater-visualization-text-palette-item"
296
+ onMouseDown={(ev) => this.handleCommand("removeFormat", null, ev)}
297
+ style={{ paddingLeft: 5, paddingRight: 5 }}
298
+ >
299
+ <i className="fas fa-remove-format" />
300
+ </div>
301
+ <DropdownPaletteItem
302
+ key="justify"
303
+ items={[
304
+ { label: <span><i className="fas fa-align-left fa-fw"></i> Left</span>, value: "justifyLeft" },
305
+ { label: <span><i className="fas fa-align-center fa-fw"></i> Center</span>, value: "justifyCenter" },
306
+ { label: <span><i className="fas fa-align-right fa-fw"></i> Right</span>, value: "justifyRight" },
307
+ { label: <span><i className="fas fa-align-justify fa-fw"></i> Justify</span>, value: "justifyFull" },
308
+ ]}
309
+ onSelect={(value) => this.handleCommand(value, null)}
310
+ position={schemeName === "over" ? "under" : "over"}
311
+ label={<i className="fas fa-align-left" />}
312
+ />
313
+ <div
314
+ key="insertUnorderedList"
315
+ className="mwater-visualization-text-palette-item"
316
+ onMouseDown={(ev) => this.handleCommand("insertUnorderedList", null, ev)}
317
+ >
318
+ <i className="fas fa-list-ul" />
319
+ </div>
320
+ <div
321
+ key="insertOrderedList"
322
+ className="mwater-visualization-text-palette-item"
323
+ onMouseDown={(ev) => this.handleCommand("insertOrderedList", null, ev)}
324
+ >
325
+ <i className="fas fa-list-ol" />
326
+ </div>
327
+ {this.props.includeHeadings && [
328
+ <DropdownPaletteItem
329
+ key="paragraph"
330
+ items={[
331
+ { label: "Heading 1", value: "h1" },
332
+ { label: "Heading 2", value: "h2" },
333
+ { label: "Extra Small", value: "xsmall" },
334
+ { label: "Small", value: "small" },
335
+ { label: "Normal", value: "normal" },
336
+ { label: "Large", value: "large" },
337
+ { label: "Extra Large", value: "xlarge" },
338
+ { label: "6px", value: "6px", more: true },
339
+ { label: "7px", value: "7px", more: true },
340
+ { label: "8px", value: "8px", more: true },
341
+ { label: "9px", value: "9px", more: true },
342
+ { label: "10px", value: "10px", more: true },
343
+ { label: "11px", value: "11px", more: true },
344
+ { label: "12px", value: "12px", more: true },
345
+ { label: "14px", value: "14px", more: true },
346
+ { label: "16px", value: "16px", more: true },
347
+ { label: "18px", value: "18px", more: true },
348
+ { label: "20px", value: "20px", more: true },
349
+ { label: "22px", value: "22px", more: true },
350
+ { label: "24px", value: "24px", more: true },
351
+ { label: "30px", value: "30px", more: true },
352
+ { label: "36px", value: "36px", more: true },
353
+ ]}
354
+ onSelect={(tag) => {
355
+ if (tag.startsWith("h")) {
356
+ this.handleSetFontSize(tag, null)
357
+ } else if (tag === "normal") {
358
+ this.handleSetFontSize("div", null)
359
+ } else if (tag === "large") {
360
+ this.handleSetFontSize("div", "120%")
361
+ } else if (tag === "xlarge") {
362
+ this.handleSetFontSize("div", "150%")
363
+ } else if (tag === "small") {
364
+ this.handleSetFontSize("div", "87.5%")
365
+ } else if (tag === "xsmall") {
366
+ this.handleSetFontSize("div", "75%")
367
+ } else {
368
+ this.handleSetFontSize("div", tag)
369
+ }
370
+ }}
371
+ position={schemeName === "over" ? "under" : "over"}
372
+ label={<i className="fas fa-text-size" />}
373
+ />
374
+ ]}
375
+ {this.props.extraPaletteButtons}
376
+ </div>
332
377
  )
333
378
  }
334
379
 
@@ -338,53 +383,50 @@ export default class RichTextComponent extends React.Component<RichTextComponent
338
383
 
339
384
  renderHtml() {
340
385
  if (this.props.onItemsChange != null) {
341
- return R(
342
- "div",
343
- { key: "contents", style: this.props.style, className: this.props.className },
344
- R(ContentEditableComponent, {
345
- ref: this.refContentEditable,
346
- style: { outline: "none" },
347
- html: this.createHtml(),
348
- onChange: this.handleChange,
349
- onClick: this.handleEditorClick,
350
- onFocus: this.handleFocus,
351
- onBlur: this.handleBlur,
352
- }),
353
- this.props.items?.[0] == null
354
- ? R(
355
- "div",
356
- {
357
- key: "placeholder",
358
- style: { color: "#DDD", position: "absolute", top: 0, left: 0, right: 0, pointerEvents: "none" },
359
- },
360
- "Click to Edit"
361
- )
362
- : undefined
386
+ return (
387
+ <div key="contents" style={this.props.style} className={this.props.className}>
388
+ <ContentEditableComponent
389
+ ref={this.refContentEditable}
390
+ style={{ outline: "none" }}
391
+ html={this.createHtml()}
392
+ onChange={this.handleChange}
393
+ onClick={this.handleEditorClick}
394
+ onFocus={this.handleFocus}
395
+ onBlur={this.handleBlur}
396
+ />
397
+ {this.props.items?.[0] == null ? (
398
+ <div
399
+ key="placeholder"
400
+ style={{ color: "#DDD", position: "absolute", top: 0, left: 0, right: 0, pointerEvents: "none" }}
401
+ >
402
+ Click to Edit
403
+ </div>
404
+ ) : undefined}
405
+ </div>
363
406
  )
364
407
  } else {
365
- return R("div", {
366
- key: "contents",
367
- style: this.props.style,
368
- className: this.props.className,
369
- dangerouslySetInnerHTML: { __html: this.createHtml() },
370
- })
408
+ return (
409
+ <div
410
+ key="contents"
411
+ style={this.props.style}
412
+ className={this.props.className}
413
+ dangerouslySetInnerHTML={{ __html: this.createHtml() }}
414
+ />
415
+ )
371
416
  }
372
417
  }
373
418
 
374
419
  render() {
375
- return R(
376
- "div",
377
- {
378
- style: { position: "relative" },
379
- ref: (c: HTMLElement | null) => {
420
+ return (
421
+ <div
422
+ style={{ position: "relative" }}
423
+ ref={(c: HTMLElement | null) => {
380
424
  this.entireComponent = c
381
- },
382
- },
383
- this.renderHtml(),
384
- this.state.focused ? this.renderPalette() : undefined
425
+ }}
426
+ >
427
+ {this.renderHtml()}
428
+ {this.state.focused ? this.renderPalette() : undefined}
429
+ </div>
385
430
  )
386
431
  }
387
432
  }
388
-
389
- var removeFormatIcon =
390
- "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAYAAACpF6WWAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAr0lEQVQ4y91U2w3CMAy8VB0kbFA2YYVuABOZbsAmGaFscnzgSlGSBgfCB1g6OXbkkx+yHUn0lgFfkN8hHSt/lma71kxdhIv6Dom/HGicflB97NVTD2ACsPQc1En1zUpqKb+pdEumzaVbSNPSRRFL7iNZQ1BstvApsmODZJXUa8A58W9Ea4nwFWkNa0Sc/Q+F1dyDRD30AO6qJV/wtgxNPR3fOEJXALO+5092/0+P9APt7i9xOIlepwAAAABJRU5ErkJggg=="
@@ -2,6 +2,7 @@ import { LiteralType } from "@mwater/expressions"
2
2
  import { format as d3Format } from "d3-format"
3
3
  import { fromLatLon } from "utm"
4
4
  import dayjs from './dayjs'
5
+ import { stringify as wellknownStringify } from "./wellknown"
5
6
 
6
7
  /** Option for list of format options */
7
8
  export interface FormatOption {
@@ -32,7 +33,8 @@ export function getFormatOptions(type: LiteralType): FormatOption[] | null {
32
33
  if (type == "geometry") {
33
34
  return [
34
35
  { value: "lat, lng", label: "Latitude, Longitude" },
35
- { value: "UTM", label: "UTM" }
36
+ { value: "UTM", label: "UTM" },
37
+ { value: "WKT", label: "Well-Known Text" }
36
38
  ]
37
39
  }
38
40
 
@@ -148,6 +150,8 @@ export function formatValue(
148
150
  return `${zoneNum}${zoneLetter} ${easting.toFixed(0)} ${northing.toFixed(0)}`
149
151
  }
150
152
  return value.type
153
+ } else if (format == "WKT") {
154
+ return wellknownStringify(value)
151
155
  } else {
152
156
  // Display as lat/lng if Point, otherwise type
153
157
  if (value.type == "Point") {