cx 25.10.1 → 26.0.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 (1247) hide show
  1. package/.mocharc.json +5 -0
  2. package/LICENSE-THIRD-PARTY.md +91 -91
  3. package/LICENSE.md +7 -7
  4. package/README.md +46 -46
  5. package/build.js +129 -0
  6. package/dist/charts.css +250 -250
  7. package/dist/charts.js +2421 -3102
  8. package/dist/data.js +857 -1063
  9. package/dist/hooks.js +48 -59
  10. package/dist/jsx-runtime.js +24 -0
  11. package/dist/manifest.js +959 -953
  12. package/dist/svg.js +266 -432
  13. package/dist/ui.js +1935 -2388
  14. package/dist/util.js +587 -557
  15. package/dist/widgets.css +6 -6
  16. package/dist/widgets.js +7543 -9909
  17. package/package.json +39 -5
  18. package/src/charts/Bar.scss +5 -3
  19. package/src/charts/Bar.ts +114 -0
  20. package/src/charts/BarGraph.scss +4 -3
  21. package/src/charts/BarGraph.tsx +145 -0
  22. package/src/charts/BubbleGraph.scss +5 -3
  23. package/src/charts/BubbleGraph.tsx +165 -0
  24. package/src/charts/Chart.ts +108 -0
  25. package/src/charts/ColorMap.ts +150 -0
  26. package/src/charts/Column.scss +5 -3
  27. package/src/charts/Column.ts +124 -0
  28. package/src/charts/ColumnBarBase.tsx +284 -0
  29. package/src/charts/ColumnBarGraphBase.tsx +229 -0
  30. package/src/charts/ColumnGraph.scss +5 -3
  31. package/src/charts/ColumnGraph.tsx +153 -0
  32. package/src/charts/Grid.ts +5 -0
  33. package/src/charts/Gridlines.scss +5 -3
  34. package/src/charts/Gridlines.tsx +88 -0
  35. package/src/charts/Legend.scss +5 -3
  36. package/src/charts/Legend.tsx +270 -0
  37. package/src/charts/LegendEntry.scss +5 -3
  38. package/src/charts/LegendEntry.tsx +197 -0
  39. package/src/charts/LineGraph.scss +4 -3
  40. package/src/charts/LineGraph.tsx +441 -0
  41. package/src/charts/Marker.scss +5 -3
  42. package/src/charts/Marker.tsx +483 -0
  43. package/src/charts/MarkerLine.scss +5 -3
  44. package/src/charts/MarkerLine.tsx +214 -0
  45. package/src/charts/MouseTracker.tsx +112 -0
  46. package/src/charts/Pie.ts +8 -0
  47. package/src/charts/PieChart.scss +5 -3
  48. package/src/charts/PieChart.tsx +717 -0
  49. package/src/charts/PieLabel.tsx +106 -0
  50. package/src/charts/PieLabelsContainer.ts +68 -0
  51. package/src/charts/Range.scss +4 -3
  52. package/src/charts/Range.tsx +318 -0
  53. package/src/charts/RangeMarker.scss +5 -3
  54. package/src/charts/RangeMarker.tsx +233 -0
  55. package/src/charts/ScatterGraph.scss +5 -3
  56. package/src/charts/ScatterGraph.tsx +245 -0
  57. package/src/charts/Swimlane.scss +5 -3
  58. package/src/charts/Swimlane.tsx +195 -0
  59. package/src/charts/Swimlanes.scss +5 -3
  60. package/src/charts/Swimlanes.tsx +179 -0
  61. package/src/charts/axis/Axis.scss +22 -22
  62. package/src/charts/axis/Axis.tsx +444 -0
  63. package/src/charts/axis/CategoryAxis.scss +5 -3
  64. package/src/charts/axis/CategoryAxis.tsx +313 -0
  65. package/src/charts/axis/NumericAxis.scss +5 -3
  66. package/src/charts/axis/NumericAxis.tsx +437 -0
  67. package/src/charts/axis/Stack.ts +61 -0
  68. package/src/charts/axis/TimeAxis.scss +4 -3
  69. package/src/charts/axis/TimeAxis.tsx +718 -0
  70. package/src/charts/axis/index.scss +5 -5
  71. package/src/charts/axis/index.ts +4 -0
  72. package/src/charts/axis/variables.scss +2 -2
  73. package/src/charts/helpers/MinMaxFinder.ts +66 -0
  74. package/src/charts/helpers/PointReducer.ts +135 -0
  75. package/src/charts/helpers/SnapPointFinder.ts +136 -0
  76. package/src/charts/helpers/ValueAtFinder.ts +72 -0
  77. package/src/charts/helpers/index.ts +4 -0
  78. package/src/charts/index.scss +22 -22
  79. package/src/charts/palette.scss +7 -5
  80. package/src/charts/shapes.tsx +86 -0
  81. package/src/charts/variables.scss +2 -1
  82. package/src/core.d.ts +182 -310
  83. package/src/data/AggregateFunction.ts +171 -0
  84. package/src/data/ArrayElementView.spec.ts +88 -0
  85. package/src/data/ArrayElementView.ts +90 -0
  86. package/src/data/ArrayRef.ts +35 -0
  87. package/src/data/AugmentedViewBase.ts +88 -0
  88. package/src/data/Binding.ts +104 -0
  89. package/src/data/ExposedRecordView.ts +95 -0
  90. package/src/data/ExposedValueView.ts +89 -0
  91. package/src/data/Expression.spec.ts +229 -0
  92. package/src/data/Expression.ts +233 -0
  93. package/src/data/Grouper.spec.ts +57 -0
  94. package/src/data/Grouper.ts +158 -0
  95. package/src/data/NestedDataView.ts +43 -0
  96. package/src/data/ReadOnlyDataView.ts +39 -0
  97. package/src/data/Ref.spec.ts +79 -0
  98. package/src/data/Ref.ts +104 -0
  99. package/src/data/Selector.ts +10 -0
  100. package/src/data/Store.spec.ts +22 -0
  101. package/src/data/Store.ts +52 -0
  102. package/src/data/StoreProxy.ts +19 -0
  103. package/src/data/StoreRef.spec.ts +24 -0
  104. package/src/data/StoreRef.ts +66 -0
  105. package/src/data/StringTemplate.spec.ts +132 -0
  106. package/src/data/StringTemplate.ts +93 -0
  107. package/src/data/StructuredSelector.spec.ts +113 -0
  108. package/src/data/StructuredSelector.ts +146 -0
  109. package/src/data/SubscribableView.ts +63 -0
  110. package/src/data/View.ts +289 -0
  111. package/src/data/ZoomIntoPropertyView.spec.ts +64 -0
  112. package/src/data/ZoomIntoPropertyView.ts +45 -0
  113. package/src/data/comparer.ts +78 -0
  114. package/src/data/computable.spec.ts +62 -0
  115. package/src/data/computable.ts +72 -0
  116. package/src/data/createAccessorModelProxy.ts +60 -0
  117. package/src/data/createStructuredSelector.spec.ts +45 -0
  118. package/src/data/createStructuredSelector.ts +62 -0
  119. package/src/data/defaultCompare.ts +15 -0
  120. package/src/data/diff/diffArrays.ts +49 -0
  121. package/src/data/diff/diffs.spec.ts +49 -0
  122. package/src/data/diff/index.ts +1 -0
  123. package/src/data/enableFatArrowExpansion.ts +6 -0
  124. package/src/data/getAccessor.spec.ts +11 -0
  125. package/src/data/getAccessor.ts +74 -0
  126. package/src/data/getSelector.spec.ts +43 -0
  127. package/src/data/getSelector.ts +66 -0
  128. package/src/data/index.ts +30 -0
  129. package/src/data/isSelector.ts +26 -0
  130. package/src/data/ops/append.spec.ts +28 -0
  131. package/src/data/ops/append.ts +5 -0
  132. package/src/data/ops/filter.spec.ts +35 -0
  133. package/src/data/ops/filter.ts +9 -0
  134. package/src/data/ops/findTreeNode.spec.ts +23 -0
  135. package/src/data/ops/findTreeNode.ts +18 -0
  136. package/src/data/ops/findTreePath.ts +23 -0
  137. package/src/data/ops/insertElement.ts +3 -0
  138. package/src/data/ops/merge.spec.ts +27 -0
  139. package/src/data/ops/merge.ts +13 -0
  140. package/src/data/ops/moveElement.ts +21 -0
  141. package/src/data/ops/removeTreeNodes.spec.ts +37 -0
  142. package/src/data/ops/removeTreeNodes.ts +15 -0
  143. package/src/data/ops/updateArray.spec.ts +69 -0
  144. package/src/data/ops/updateArray.ts +31 -0
  145. package/src/data/ops/updateTree.spec.ts +54 -0
  146. package/src/data/ops/updateTree.ts +23 -0
  147. package/src/data/test-types.ts +7 -0
  148. package/src/global.scss +13 -13
  149. package/src/hooks/createLocalStorageRef.ts +21 -0
  150. package/src/hooks/invokeCallback.spec.tsx +59 -0
  151. package/src/hooks/invokeCallback.ts +8 -0
  152. package/src/hooks/resolveCallback.spec.tsx +48 -0
  153. package/src/hooks/resolveCallback.ts +16 -0
  154. package/src/hooks/store.spec.tsx +67 -0
  155. package/src/hooks/store.ts +46 -0
  156. package/src/hooks/useEffect.ts +14 -0
  157. package/src/hooks/useInterval.ts +8 -0
  158. package/src/hooks/useState.ts +20 -0
  159. package/src/hooks/useTrigger.spec.tsx +99 -0
  160. package/src/hooks/useTrigger.ts +26 -0
  161. package/src/jsx-runtime.ts +72 -0
  162. package/src/locale/de-de.ts +76 -0
  163. package/src/locale/en-us.ts +75 -0
  164. package/src/locale/es-es.ts +76 -0
  165. package/src/locale/fr-fr.ts +76 -0
  166. package/src/locale/nl-nl.ts +76 -0
  167. package/src/locale/pt-pt.ts +76 -0
  168. package/src/locale/sr-latn-ba.ts +76 -0
  169. package/src/svg/BoundedObject.ts +101 -0
  170. package/src/svg/ClipRect.tsx +29 -0
  171. package/src/svg/Ellipse.tsx +69 -0
  172. package/src/svg/Line.tsx +58 -0
  173. package/src/svg/NonOverlappingRect.ts +26 -0
  174. package/src/svg/NonOverlappingRectGroup.ts +49 -0
  175. package/src/svg/Rectangle.tsx +91 -0
  176. package/src/svg/Svg.scss +5 -4
  177. package/src/svg/Svg.tsx +241 -0
  178. package/src/svg/Text.tsx +134 -0
  179. package/src/svg/TextualBoundedObject.ts +35 -0
  180. package/src/svg/index.scss +8 -8
  181. package/src/svg/util/Rect.ts +105 -0
  182. package/src/ui/CSS.ts +87 -0
  183. package/src/ui/CSSHelper.ts +17 -0
  184. package/src/ui/Container.tsx +216 -0
  185. package/src/ui/ContentResolver.spec.tsx +430 -0
  186. package/src/ui/ContentResolver.ts +124 -0
  187. package/src/ui/Controller.spec.tsx +566 -0
  188. package/src/ui/Controller.ts +189 -0
  189. package/src/ui/Culture.ts +159 -0
  190. package/src/ui/Cx.spec.tsx +208 -0
  191. package/src/ui/Cx.tsx +386 -0
  192. package/src/ui/DataProxy.spec.tsx +337 -0
  193. package/src/ui/DataProxy.ts +55 -0
  194. package/src/ui/DetachedScope.tsx +159 -0
  195. package/src/ui/FocusManager.ts +171 -0
  196. package/src/ui/Format.ts +108 -0
  197. package/src/ui/HoverSync.tsx +189 -0
  198. package/src/ui/Instance.ts +868 -0
  199. package/src/ui/IsolatedScope.spec.tsx +55 -0
  200. package/src/ui/IsolatedScope.ts +50 -0
  201. package/src/ui/Localization.ts +70 -0
  202. package/src/ui/Prop.ts +112 -0
  203. package/src/ui/PureContainer.spec.tsx +230 -0
  204. package/src/ui/PureContainer.tsx +19 -0
  205. package/src/ui/RenderingContext.ts +99 -0
  206. package/src/ui/Repeater.spec.tsx +141 -0
  207. package/src/ui/Repeater.ts +203 -0
  208. package/src/ui/Rescope.spec.tsx +199 -0
  209. package/src/ui/Rescope.ts +49 -0
  210. package/src/ui/ResizeManager.ts +31 -0
  211. package/src/ui/Restate.spec.tsx +418 -0
  212. package/src/ui/Restate.tsx +217 -0
  213. package/src/ui/StaticText.ts +11 -0
  214. package/src/ui/StructuredInstanceDataAccessor.ts +32 -0
  215. package/src/ui/Text.ts +30 -0
  216. package/src/ui/VDOM.ts +34 -0
  217. package/src/ui/Widget.spec.tsx +53 -0
  218. package/src/ui/Widget.tsx +308 -0
  219. package/src/ui/ZIndexManager.ts +11 -0
  220. package/src/ui/adapter/ArrayAdapter.spec.ts +55 -0
  221. package/src/ui/adapter/ArrayAdapter.ts +226 -0
  222. package/src/ui/adapter/DataAdapter.ts +52 -0
  223. package/src/ui/adapter/GroupAdapter.ts +235 -0
  224. package/src/ui/adapter/TreeAdapter.spec.ts +76 -0
  225. package/src/ui/adapter/TreeAdapter.ts +185 -0
  226. package/src/ui/app/History.ts +133 -0
  227. package/src/ui/app/Url.spec.ts +50 -0
  228. package/src/ui/app/Url.ts +102 -0
  229. package/src/ui/app/startAppLoop.tsx +74 -0
  230. package/src/ui/app/startHotAppLoop.ts +40 -0
  231. package/src/ui/batchUpdates.ts +77 -0
  232. package/src/ui/bind.ts +10 -0
  233. package/src/ui/createFunctionalComponent.spec.tsx +399 -0
  234. package/src/ui/createFunctionalComponent.ts +65 -0
  235. package/src/ui/expr.ts +44 -0
  236. package/src/ui/flattenProps.ts +21 -0
  237. package/src/ui/index.scss +2 -2
  238. package/src/ui/index.ts +45 -0
  239. package/src/ui/keyboardShortcuts.ts +40 -0
  240. package/src/ui/layout/Content.ts +30 -0
  241. package/src/ui/layout/ContentPlaceholder.spec.tsx +587 -0
  242. package/src/ui/layout/ContentPlaceholder.ts +133 -0
  243. package/src/ui/layout/FirstVisibleChildLayout.spec.tsx +195 -0
  244. package/src/ui/layout/FirstVisibleChildLayout.ts +60 -0
  245. package/src/ui/layout/LabelsLeftLayout.scss +6 -4
  246. package/src/ui/layout/LabelsLeftLayout.tsx +76 -0
  247. package/src/ui/layout/LabelsTopLayout.scss +5 -4
  248. package/src/ui/layout/LabelsTopLayout.tsx +156 -0
  249. package/src/ui/layout/UseParentLayout.ts +8 -0
  250. package/src/ui/layout/exploreChildren.ts +38 -0
  251. package/src/ui/layout/index.scss +3 -3
  252. package/src/ui/layout/variables.scss +2 -2
  253. package/src/ui/selection/KeySelection.ts +165 -0
  254. package/src/ui/selection/PropertySelection.ts +87 -0
  255. package/src/ui/selection/Selection.ts +118 -0
  256. package/src/ui/tpl.ts +5 -0
  257. package/src/ui/variables.scss +1 -1
  258. package/src/util/Component.spec.ts +381 -0
  259. package/src/util/Component.ts +296 -0
  260. package/src/util/Console.ts +11 -0
  261. package/src/util/DOM.ts +88 -0
  262. package/src/util/Debug.ts +71 -0
  263. package/src/util/Format.spec.ts +69 -0
  264. package/src/util/Format.ts +267 -0
  265. package/src/util/GlobalCacheIdentifier.ts +11 -0
  266. package/src/util/KeyCode.ts +21 -0
  267. package/src/util/SubscriberList.ts +87 -0
  268. package/src/util/Timing.ts +59 -0
  269. package/src/util/TraversalStack.spec.ts +54 -0
  270. package/src/util/TraversalStack.ts +48 -0
  271. package/src/util/addEventListenerWithOptions.ts +41 -0
  272. package/src/util/browserSupportsPassiveEventHandlers.ts +20 -0
  273. package/src/util/calculateNaturalElementHeight.ts +22 -0
  274. package/src/util/call-once.scss +6 -6
  275. package/src/util/capitalize.ts +4 -0
  276. package/src/util/coalesce.ts +6 -0
  277. package/src/util/color/hslToRgb.ts +34 -0
  278. package/src/util/color/parseColor.ts +173 -0
  279. package/src/util/color/rgbToHex.ts +15 -0
  280. package/src/util/color/rgbToHsl.ts +36 -0
  281. package/src/util/date/dateDiff.ts +9 -0
  282. package/src/util/date/diff.ts +13 -0
  283. package/src/util/date/encodeDate.ts +8 -0
  284. package/src/util/date/encodeDateWithTimezoneOffset.ts +19 -0
  285. package/src/util/date/lowerBoundCheck.ts +13 -0
  286. package/src/util/date/maxDate.ts +14 -0
  287. package/src/util/date/minDate.ts +14 -0
  288. package/src/util/date/monthStart.ts +8 -0
  289. package/src/util/date/parseDateInvariant.ts +20 -0
  290. package/src/util/date/sameDate.ts +11 -0
  291. package/src/util/date/upperBoundCheck.ts +13 -0
  292. package/src/util/date/zeroTime.ts +9 -0
  293. package/src/util/debounce.ts +26 -0
  294. package/src/util/dummyCallback.ts +1 -0
  295. package/src/util/escapeSpecialRegexCharacters.ts +8 -0
  296. package/src/util/eventCallbacks.ts +12 -0
  297. package/src/util/expandFatArrows.ts +118 -0
  298. package/src/util/findScrollableParent.ts +15 -0
  299. package/src/util/getActiveElement.ts +4 -0
  300. package/src/util/getParentFrameBoundingClientRect.ts +13 -0
  301. package/src/util/getScrollerBoundingClientRect.ts +12 -0
  302. package/src/util/getSearchQueryPredicate.ts +58 -0
  303. package/src/util/getTopLevelBoundingClientRect.ts +7 -0
  304. package/src/util/getVendorPrefix.ts +33 -0
  305. package/src/util/hasKey.ts +18 -0
  306. package/src/util/index.scss +10 -10
  307. package/src/util/index.ts +55 -0
  308. package/src/util/innerTextTrim.ts +10 -0
  309. package/src/util/isArray.ts +3 -0
  310. package/src/util/isDataRecord.ts +5 -0
  311. package/src/util/isDefined.ts +3 -0
  312. package/src/util/isDigit.ts +8 -0
  313. package/src/util/isFunction.ts +3 -0
  314. package/src/util/isNonEmptyArray.ts +3 -0
  315. package/src/util/isNumber.ts +3 -0
  316. package/src/util/isObject.ts +3 -0
  317. package/src/util/isPromise.ts +6 -0
  318. package/src/util/isString.ts +3 -0
  319. package/src/util/isTextInputElement.ts +3 -0
  320. package/src/util/isTouchDevice.ts +7 -0
  321. package/src/util/isTouchEvent.ts +64 -0
  322. package/src/util/isUndefined.ts +3 -0
  323. package/src/util/isValidIdentifierName.ts +5 -0
  324. package/src/util/onIdleCallback.ts +10 -0
  325. package/src/util/parseStyle.ts +29 -0
  326. package/src/util/quote.ts +6 -0
  327. package/src/util/reverseSlice.ts +10 -0
  328. package/src/util/routeAppend.ts +16 -0
  329. package/src/util/scrollElementIntoView.ts +40 -0
  330. package/src/util/scss/add-rules.scss +7 -5
  331. package/src/util/scss/calc.scss +12 -8
  332. package/src/util/scss/call-once.scss +5 -3
  333. package/src/util/scss/clockwise.scss +20 -18
  334. package/src/util/scss/colors.scss +4 -2
  335. package/src/util/scss/deep-get.scss +3 -1
  336. package/src/util/scss/deep-merge.scss +6 -3
  337. package/src/util/scss/divide.scss +3 -3
  338. package/src/util/scss/include.scss +6 -5
  339. package/src/util/scss/index.scss +9 -9
  340. package/src/util/shallowEquals.ts +43 -0
  341. package/src/util/test/createTestRenderer.tsx +12 -0
  342. package/src/util/throttle.ts +21 -0
  343. package/src/util/validatedDebounce.ts +23 -0
  344. package/src/variables.scss +217 -217
  345. package/src/widgets/AccessorBindings.spec.tsx +64 -66
  346. package/src/widgets/Button.scss +6 -4
  347. package/src/widgets/Button.tsx +201 -0
  348. package/src/widgets/Button.variables.scss +13 -10
  349. package/src/widgets/CxCredit.scss +6 -4
  350. package/src/widgets/CxCredit.tsx +46 -0
  351. package/src/widgets/DocumentTitle.ts +92 -0
  352. package/src/widgets/FlexBox.scss +7 -5
  353. package/src/widgets/FlexBox.tsx +169 -0
  354. package/src/widgets/Heading.scss +6 -4
  355. package/src/widgets/Heading.ts +43 -0
  356. package/src/widgets/HighlightedSearchText.scss +6 -4
  357. package/src/widgets/HighlightedSearchText.tsx +54 -0
  358. package/src/widgets/HtmlElement.spec.tsx +79 -0
  359. package/src/widgets/HtmlElement.tsx +349 -0
  360. package/src/widgets/Icon.scss +6 -4
  361. package/src/widgets/Icon.ts +78 -0
  362. package/src/widgets/List.scss +6 -4
  363. package/src/widgets/List.tsx +787 -0
  364. package/src/widgets/ProgressBar.scss +5 -4
  365. package/src/widgets/ProgressBar.tsx +66 -0
  366. package/src/widgets/Resizer.scss +5 -4
  367. package/src/widgets/Resizer.tsx +200 -0
  368. package/src/widgets/Sandbox.ts +103 -0
  369. package/src/widgets/Section.scss +5 -4
  370. package/src/widgets/Section.tsx +187 -0
  371. package/src/widgets/animations.scss +10 -10
  372. package/src/widgets/autoFocus.ts +9 -0
  373. package/src/widgets/cx.ts +63 -0
  374. package/src/widgets/drag-drop/DragClone.scss +6 -4
  375. package/src/widgets/drag-drop/DragHandle.scss +6 -4
  376. package/src/widgets/drag-drop/DragHandle.tsx +47 -0
  377. package/src/widgets/drag-drop/DragSource.scss +6 -4
  378. package/src/widgets/drag-drop/DragSource.tsx +238 -0
  379. package/src/widgets/drag-drop/DropZone.scss +6 -4
  380. package/src/widgets/drag-drop/DropZone.tsx +354 -0
  381. package/src/widgets/drag-drop/index.scss +3 -3
  382. package/src/widgets/drag-drop/ops.tsx +422 -0
  383. package/src/widgets/drag-drop/variables.scss +4 -1
  384. package/src/widgets/enableAllInternalDependencies.ts +11 -0
  385. package/src/widgets/form/Calendar.scss +8 -5
  386. package/src/widgets/form/Calendar.tsx +760 -0
  387. package/src/widgets/form/Calendar.variables.scss +63 -63
  388. package/src/widgets/form/Checkbox.scss +5 -3
  389. package/src/widgets/form/Checkbox.tsx +285 -0
  390. package/src/widgets/form/Checkbox.variables.scss +39 -39
  391. package/src/widgets/form/ColorField.scss +5 -3
  392. package/src/widgets/form/ColorField.tsx +491 -0
  393. package/src/widgets/form/ColorPicker.scss +5 -3
  394. package/src/widgets/form/ColorPicker.tsx +544 -0
  395. package/src/widgets/form/ColorPicker.variables.scss +22 -22
  396. package/src/widgets/form/DateField.ts +21 -0
  397. package/src/widgets/form/DateTimeField.scss +5 -3
  398. package/src/widgets/form/DateTimeField.tsx +723 -0
  399. package/src/widgets/form/DateTimePicker.scss +6 -4
  400. package/src/widgets/form/DateTimePicker.tsx +431 -0
  401. package/src/widgets/form/Field.scss +4 -2
  402. package/src/widgets/form/Field.tsx +611 -0
  403. package/src/widgets/form/FieldGroup.ts +10 -0
  404. package/src/widgets/form/FieldIcon.ts +61 -0
  405. package/src/widgets/form/HelpText.scss +5 -4
  406. package/src/widgets/form/HelpText.ts +15 -0
  407. package/src/widgets/form/Label.scss +5 -4
  408. package/src/widgets/form/Label.tsx +116 -0
  409. package/src/widgets/form/LabeledContainer.ts +81 -0
  410. package/src/widgets/form/LookupField.scss +5 -3
  411. package/src/widgets/form/LookupField.tsx +1326 -0
  412. package/src/widgets/form/MonthField.scss +4 -3
  413. package/src/widgets/form/MonthField.tsx +665 -0
  414. package/src/widgets/form/MonthPicker.scss +8 -5
  415. package/src/widgets/form/MonthPicker.tsx +822 -0
  416. package/src/widgets/form/NumberField.scss +5 -3
  417. package/src/widgets/form/NumberField.tsx +540 -0
  418. package/src/widgets/form/Radio.scss +5 -3
  419. package/src/widgets/form/Radio.tsx +245 -0
  420. package/src/widgets/form/Radio.variables.scss +45 -45
  421. package/src/widgets/form/Select.scss +6 -4
  422. package/src/widgets/form/Select.tsx +322 -0
  423. package/src/widgets/form/Slider.scss +6 -3
  424. package/src/widgets/form/Slider.tsx +461 -0
  425. package/src/widgets/form/Switch.scss +5 -3
  426. package/src/widgets/form/Switch.tsx +174 -0
  427. package/src/widgets/form/TextArea.scss +6 -4
  428. package/src/widgets/form/TextArea.tsx +229 -0
  429. package/src/widgets/form/TextField.scss +6 -4
  430. package/src/widgets/form/TextField.tsx +345 -0
  431. package/src/widgets/form/TimeField.ts +10 -0
  432. package/src/widgets/form/TimeList.tsx +94 -0
  433. package/src/widgets/form/UploadButton.scss +5 -3
  434. package/src/widgets/form/UploadButton.tsx +256 -0
  435. package/src/widgets/form/ValidationError.scss +4 -3
  436. package/src/widgets/form/ValidationError.tsx +72 -0
  437. package/src/widgets/form/ValidationGroup.spec.tsx +147 -0
  438. package/src/widgets/form/ValidationGroup.ts +141 -0
  439. package/src/widgets/form/Validator.ts +23 -0
  440. package/src/widgets/form/Wheel.scss +9 -7
  441. package/src/widgets/form/Wheel.tsx +315 -0
  442. package/src/widgets/form/index.scss +24 -24
  443. package/src/widgets/form/variables.scss +3 -1
  444. package/src/widgets/grid/Grid.scss +6 -4
  445. package/src/widgets/grid/Grid.tsx +4247 -0
  446. package/src/widgets/grid/GridCell.ts +143 -0
  447. package/src/widgets/grid/GridCellEditor.tsx +52 -0
  448. package/src/widgets/grid/GridRow.ts +302 -0
  449. package/src/widgets/grid/GridRowLine.ts +49 -0
  450. package/src/widgets/grid/Pagination.scss +5 -3
  451. package/src/widgets/grid/Pagination.tsx +126 -0
  452. package/src/widgets/grid/TreeNode.scss +6 -4
  453. package/src/widgets/grid/TreeNode.tsx +145 -0
  454. package/src/widgets/grid/createGridCellEditor.tsx +18 -0
  455. package/src/widgets/grid/index.scss +3 -3
  456. package/src/widgets/grid/index.ts +17 -0
  457. package/src/widgets/grid/variables.scss +8 -4
  458. package/src/widgets/icons/arrow-down.svg +3 -3
  459. package/src/widgets/icons/arrow-right.svg +2 -2
  460. package/src/widgets/icons/base.svg +104 -104
  461. package/src/widgets/icons/calendar-old.svg +169 -169
  462. package/src/widgets/icons/calendar.svg +187 -187
  463. package/src/widgets/icons/calendar.tsx +17 -0
  464. package/src/widgets/icons/check.tsx +13 -0
  465. package/src/widgets/icons/clear.svg +74 -74
  466. package/src/widgets/icons/clear.tsx +15 -0
  467. package/src/widgets/icons/close.svg +74 -74
  468. package/src/widgets/icons/close.tsx +20 -0
  469. package/src/widgets/icons/cx.tsx +38 -0
  470. package/src/widgets/icons/drop-down.tsx +15 -0
  471. package/src/widgets/icons/dropdown-arrow.svg +61 -61
  472. package/src/widgets/icons/file.svg +4 -4
  473. package/src/widgets/icons/file.tsx +13 -0
  474. package/src/widgets/icons/folder-open.svg +5 -5
  475. package/src/widgets/icons/folder-open.tsx +15 -0
  476. package/src/widgets/icons/folder.svg +58 -58
  477. package/src/widgets/icons/folder.tsx +13 -0
  478. package/src/widgets/icons/forward.svg +67 -67
  479. package/src/widgets/icons/forward.tsx +22 -0
  480. package/src/widgets/icons/loading.svg +4 -4
  481. package/src/widgets/icons/loading.tsx +24 -0
  482. package/src/widgets/icons/menu.tsx +17 -0
  483. package/src/widgets/icons/pixel-picker.tsx +18 -0
  484. package/src/widgets/icons/registry.ts +57 -0
  485. package/src/widgets/icons/search.svg +107 -107
  486. package/src/widgets/icons/search.tsx +13 -0
  487. package/src/widgets/icons/sort-asc.svg +3 -3
  488. package/src/widgets/icons/sort-asc.tsx +14 -0
  489. package/src/widgets/icons/square.tsx +18 -0
  490. package/src/widgets/index.d.ts +55 -55
  491. package/src/widgets/index.scss +16 -16
  492. package/src/widgets/nav/Link.scss +5 -3
  493. package/src/widgets/nav/Link.ts +12 -0
  494. package/src/widgets/nav/LinkButton.ts +176 -0
  495. package/src/widgets/nav/Menu.scss +7 -5
  496. package/src/widgets/nav/Menu.tsx +489 -0
  497. package/src/widgets/nav/Menu.variables.scss +3 -1
  498. package/src/widgets/nav/MenuItem.scss +6 -4
  499. package/src/widgets/nav/MenuItem.tsx +523 -0
  500. package/src/widgets/nav/MenuSpacer.ts +19 -0
  501. package/src/widgets/nav/RedirectRoute.ts +50 -0
  502. package/src/widgets/nav/Route.spec.tsx +24 -0
  503. package/src/widgets/nav/Route.ts +142 -0
  504. package/src/widgets/nav/Scroller.scss +5 -3
  505. package/src/widgets/nav/Scroller.tsx +253 -0
  506. package/src/widgets/nav/Submenu.ts +6 -0
  507. package/src/widgets/nav/Tab.scss +5 -4
  508. package/src/widgets/nav/Tab.ts +120 -0
  509. package/src/widgets/nav/Tab.variables.scss +84 -84
  510. package/src/widgets/nav/cover.scss +5 -4
  511. package/src/widgets/nav/index.scss +5 -5
  512. package/src/widgets/nav/variables.scss +3 -1
  513. package/src/widgets/overlay/ContextMenu.ts +42 -0
  514. package/src/widgets/overlay/Dropdown.scss +11 -9
  515. package/src/widgets/overlay/Dropdown.tsx +762 -0
  516. package/src/widgets/overlay/FlyweightTooltipTracker.ts +57 -0
  517. package/src/widgets/overlay/MsgBox.tsx +141 -0
  518. package/src/widgets/overlay/Overlay.scss +5 -3
  519. package/src/widgets/overlay/Overlay.tsx +942 -0
  520. package/src/widgets/overlay/Toast.scss +8 -7
  521. package/src/widgets/overlay/Toast.ts +111 -0
  522. package/src/widgets/overlay/Tooltip.scss +6 -4
  523. package/src/widgets/overlay/Tooltip.tsx +393 -0
  524. package/src/widgets/overlay/Window.scss +6 -4
  525. package/src/widgets/overlay/Window.tsx +299 -0
  526. package/src/widgets/overlay/Window.variables.scss +62 -62
  527. package/src/widgets/overlay/alerts.ts +46 -0
  528. package/src/widgets/overlay/captureMouse.scss +13 -13
  529. package/src/widgets/overlay/captureMouse.ts +195 -0
  530. package/src/widgets/overlay/createHotPromiseWindowFactory.ts +72 -0
  531. package/src/widgets/overlay/index.scss +15 -15
  532. package/src/widgets/overlay/index.ts +11 -0
  533. package/src/widgets/overlay/tooltip-ops.ts +173 -0
  534. package/src/widgets/overlay/variables.scss +3 -1
  535. package/src/widgets/variables.scss +3 -1
  536. package/tsconfig.compile.json +4 -0
  537. package/tsconfig.json +34 -0
  538. package/tsconfig.mocha.json +14 -0
  539. package/charts.d.ts +0 -1
  540. package/charts.js +0 -1
  541. package/data.d.ts +0 -1
  542. package/data.js +0 -1
  543. package/hooks.d.ts +0 -1
  544. package/hooks.js +0 -1
  545. package/index.js +0 -17
  546. package/locale/de-de.js +0 -75
  547. package/locale/en-us.js +0 -75
  548. package/locale/es-es.js +0 -75
  549. package/locale/fr-fr.js +0 -75
  550. package/locale/nl-nl.js +0 -75
  551. package/locale/pt-pt.js +0 -75
  552. package/locale/sr-latn-ba.js +0 -75
  553. package/manifest.js +0 -1
  554. package/src/charts/Bar.d.ts +0 -28
  555. package/src/charts/Bar.js +0 -90
  556. package/src/charts/BarGraph.d.ts +0 -15
  557. package/src/charts/BarGraph.js +0 -112
  558. package/src/charts/BubbleGraph.js +0 -93
  559. package/src/charts/Chart.d.ts +0 -12
  560. package/src/charts/Chart.js +0 -75
  561. package/src/charts/ColorMap.d.ts +0 -21
  562. package/src/charts/ColorMap.js +0 -97
  563. package/src/charts/Column.d.ts +0 -29
  564. package/src/charts/Column.js +0 -88
  565. package/src/charts/ColumnBarBase.d.ts +0 -64
  566. package/src/charts/ColumnBarBase.js +0 -176
  567. package/src/charts/ColumnBarGraphBase.d.ts +0 -73
  568. package/src/charts/ColumnBarGraphBase.js +0 -114
  569. package/src/charts/ColumnGraph.d.ts +0 -18
  570. package/src/charts/ColumnGraph.js +0 -120
  571. package/src/charts/Grid.js +0 -5
  572. package/src/charts/Gridlines.d.ts +0 -25
  573. package/src/charts/Gridlines.js +0 -49
  574. package/src/charts/Legend.d.ts +0 -45
  575. package/src/charts/Legend.js +0 -187
  576. package/src/charts/LegendEntry.d.ts +0 -54
  577. package/src/charts/LegendEntry.js +0 -128
  578. package/src/charts/LineGraph.d.ts +0 -101
  579. package/src/charts/LineGraph.js +0 -300
  580. package/src/charts/Marker.d.ts +0 -110
  581. package/src/charts/Marker.js +0 -311
  582. package/src/charts/MarkerLine.d.ts +0 -56
  583. package/src/charts/MarkerLine.js +0 -128
  584. package/src/charts/MouseTracker.d.ts +0 -17
  585. package/src/charts/MouseTracker.js +0 -81
  586. package/src/charts/Pie.js +0 -8
  587. package/src/charts/PieChart.d.ts +0 -92
  588. package/src/charts/PieChart.js +0 -530
  589. package/src/charts/PieLabel.d.ts +0 -26
  590. package/src/charts/PieLabel.js +0 -71
  591. package/src/charts/PieLabelsContainer.d.ts +0 -6
  592. package/src/charts/PieLabelsContainer.js +0 -55
  593. package/src/charts/Range.d.ts +0 -75
  594. package/src/charts/Range.js +0 -206
  595. package/src/charts/RangeMarker.d.ts +0 -35
  596. package/src/charts/RangeMarker.js +0 -159
  597. package/src/charts/ScatterGraph.d.ts +0 -64
  598. package/src/charts/ScatterGraph.js +0 -164
  599. package/src/charts/Swimlane.d.ts +0 -24
  600. package/src/charts/Swimlane.js +0 -140
  601. package/src/charts/Swimlanes.d.ts +0 -41
  602. package/src/charts/Swimlanes.js +0 -114
  603. package/src/charts/axis/Axis.d.ts +0 -113
  604. package/src/charts/axis/Axis.js +0 -288
  605. package/src/charts/axis/CategoryAxis.d.ts +0 -30
  606. package/src/charts/axis/CategoryAxis.js +0 -241
  607. package/src/charts/axis/NumericAxis.d.ts +0 -46
  608. package/src/charts/axis/NumericAxis.js +0 -351
  609. package/src/charts/axis/Stack.d.ts +0 -11
  610. package/src/charts/axis/Stack.js +0 -55
  611. package/src/charts/axis/TimeAxis.d.ts +0 -31
  612. package/src/charts/axis/TimeAxis.js +0 -611
  613. package/src/charts/axis/index.d.ts +0 -4
  614. package/src/charts/axis/index.js +0 -4
  615. package/src/charts/helpers/MinMaxFinder.d.ts +0 -22
  616. package/src/charts/helpers/MinMaxFinder.js +0 -36
  617. package/src/charts/helpers/PointReducer.d.ts +0 -24
  618. package/src/charts/helpers/PointReducer.js +0 -61
  619. package/src/charts/helpers/SnapPointFinder.d.ts +0 -30
  620. package/src/charts/helpers/SnapPointFinder.js +0 -69
  621. package/src/charts/helpers/ValueAtFinder.d.ts +0 -16
  622. package/src/charts/helpers/ValueAtFinder.js +0 -46
  623. package/src/charts/helpers/index.d.ts +0 -4
  624. package/src/charts/helpers/index.js +0 -4
  625. package/src/charts/index.d.ts +0 -27
  626. package/src/charts/shapes.d.ts +0 -23
  627. package/src/charts/shapes.js +0 -79
  628. package/src/data/AggregateFunction.d.ts +0 -20
  629. package/src/data/AggregateFunction.js +0 -145
  630. package/src/data/ArrayElementView.d.ts +0 -13
  631. package/src/data/ArrayElementView.js +0 -64
  632. package/src/data/ArrayElementView.spec.js +0 -88
  633. package/src/data/ArrayRef.d.ts +0 -15
  634. package/src/data/ArrayRef.js +0 -35
  635. package/src/data/AugmentedViewBase.d.ts +0 -18
  636. package/src/data/AugmentedViewBase.js +0 -77
  637. package/src/data/Binding.d.ts +0 -19
  638. package/src/data/Binding.js +0 -76
  639. package/src/data/ExposedRecordView.d.ts +0 -14
  640. package/src/data/ExposedRecordView.js +0 -75
  641. package/src/data/ExposedValueView.d.ts +0 -19
  642. package/src/data/ExposedValueView.js +0 -73
  643. package/src/data/Expression.d.ts +0 -17
  644. package/src/data/Expression.js +0 -229
  645. package/src/data/Expression.spec.js +0 -229
  646. package/src/data/Grouper.d.ts +0 -21
  647. package/src/data/Grouper.js +0 -144
  648. package/src/data/Grouper.spec.js +0 -57
  649. package/src/data/NestedDataView.d.ts +0 -19
  650. package/src/data/NestedDataView.js +0 -22
  651. package/src/data/ReadOnlyDataView.d.ts +0 -14
  652. package/src/data/ReadOnlyDataView.js +0 -27
  653. package/src/data/Ref.d.ts +0 -24
  654. package/src/data/Ref.js +0 -79
  655. package/src/data/Ref.spec.js +0 -79
  656. package/src/data/Store.d.ts +0 -14
  657. package/src/data/Store.js +0 -46
  658. package/src/data/Store.spec.js +0 -22
  659. package/src/data/StoreProxy.d.ts +0 -5
  660. package/src/data/StoreProxy.js +0 -17
  661. package/src/data/StoreRef.js +0 -54
  662. package/src/data/StoreRef.spec.js +0 -24
  663. package/src/data/StringTemplate.d.ts +0 -15
  664. package/src/data/StringTemplate.js +0 -92
  665. package/src/data/StringTemplate.spec.js +0 -132
  666. package/src/data/StructuredDataAccessor.d.ts +0 -7
  667. package/src/data/StructuredSelector.d.ts +0 -17
  668. package/src/data/StructuredSelector.js +0 -132
  669. package/src/data/StructuredSelector.spec.js +0 -113
  670. package/src/data/SubscribableView.d.ts +0 -11
  671. package/src/data/SubscribableView.js +0 -54
  672. package/src/data/View.d.ts +0 -155
  673. package/src/data/View.js +0 -182
  674. package/src/data/ZoomIntoPropertyView.d.ts +0 -11
  675. package/src/data/ZoomIntoPropertyView.js +0 -33
  676. package/src/data/ZoomIntoPropertyView.spec.js +0 -65
  677. package/src/data/comparer.d.ts +0 -7
  678. package/src/data/comparer.js +0 -54
  679. package/src/data/computable.d.ts +0 -125
  680. package/src/data/computable.js +0 -56
  681. package/src/data/computable.spec.js +0 -55
  682. package/src/data/createAccessorModelProxy.d.ts +0 -6
  683. package/src/data/createAccessorModelProxy.js +0 -43
  684. package/src/data/createStructuredSelector.d.ts +0 -3
  685. package/src/data/createStructuredSelector.js +0 -43
  686. package/src/data/createStructuredSelector.spec.js +0 -46
  687. package/src/data/defaultCompare.d.ts +0 -1
  688. package/src/data/defaultCompare.js +0 -15
  689. package/src/data/diff/diffArrays.d.ts +0 -15
  690. package/src/data/diff/diffArrays.js +0 -41
  691. package/src/data/diff/diffs.spec.js +0 -49
  692. package/src/data/diff/index.d.ts +0 -1
  693. package/src/data/diff/index.js +0 -1
  694. package/src/data/enableFatArrowExpansion.d.ts +0 -1
  695. package/src/data/enableFatArrowExpansion.js +0 -6
  696. package/src/data/getAccessor.d.ts +0 -9
  697. package/src/data/getAccessor.js +0 -61
  698. package/src/data/getAccessor.spec.js +0 -11
  699. package/src/data/getSelector.d.ts +0 -3
  700. package/src/data/getSelector.js +0 -49
  701. package/src/data/getSelector.spec.js +0 -43
  702. package/src/data/index.d.ts +0 -30
  703. package/src/data/index.js +0 -29
  704. package/src/data/isSelector.d.ts +0 -1
  705. package/src/data/isSelector.js +0 -26
  706. package/src/data/ops/append.d.ts +0 -1
  707. package/src/data/ops/append.js +0 -7
  708. package/src/data/ops/append.spec.js +0 -28
  709. package/src/data/ops/filter.d.ts +0 -1
  710. package/src/data/ops/filter.js +0 -8
  711. package/src/data/ops/filter.spec.js +0 -29
  712. package/src/data/ops/findTreeNode.d.ts +0 -1
  713. package/src/data/ops/findTreeNode.js +0 -15
  714. package/src/data/ops/findTreeNode.spec.js +0 -24
  715. package/src/data/ops/findTreePath.d.ts +0 -6
  716. package/src/data/ops/findTreePath.js +0 -16
  717. package/src/data/ops/index.d.ts +0 -10
  718. package/src/data/ops/insertElement.d.ts +0 -1
  719. package/src/data/ops/insertElement.js +0 -3
  720. package/src/data/ops/merge.d.ts +0 -3
  721. package/src/data/ops/merge.js +0 -9
  722. package/src/data/ops/merge.spec.js +0 -27
  723. package/src/data/ops/moveElement.d.ts +0 -1
  724. package/src/data/ops/moveElement.js +0 -14
  725. package/src/data/ops/removeTreeNodes.d.ts +0 -5
  726. package/src/data/ops/removeTreeNodes.js +0 -5
  727. package/src/data/ops/removeTreeNodes.spec.js +0 -28
  728. package/src/data/ops/updateArray.d.ts +0 -6
  729. package/src/data/ops/updateArray.js +0 -24
  730. package/src/data/ops/updateArray.spec.js +0 -38
  731. package/src/data/ops/updateTree.d.ts +0 -7
  732. package/src/data/ops/updateTree.js +0 -25
  733. package/src/data/ops/updateTree.spec.js +0 -36
  734. package/src/hooks/createLocalStorageRef.d.ts +0 -3
  735. package/src/hooks/createLocalStorageRef.js +0 -20
  736. package/src/hooks/index.js +0 -8
  737. package/src/hooks/invokeCallback.d.ts +0 -5
  738. package/src/hooks/invokeCallback.js +0 -7
  739. package/src/hooks/invokeCallback.spec.js +0 -53
  740. package/src/hooks/resolveCallback.d.ts +0 -3
  741. package/src/hooks/resolveCallback.js +0 -12
  742. package/src/hooks/resolveCallback.spec.js +0 -54
  743. package/src/hooks/store.d.ts +0 -8
  744. package/src/hooks/store.js +0 -32
  745. package/src/hooks/store.spec.js +0 -73
  746. package/src/hooks/useEffect.d.ts +0 -3
  747. package/src/hooks/useEffect.js +0 -15
  748. package/src/hooks/useInterval.d.ts +0 -1
  749. package/src/hooks/useInterval.js +0 -8
  750. package/src/hooks/useState.d.ts +0 -3
  751. package/src/hooks/useState.js +0 -16
  752. package/src/hooks/useTrigger.d.ts +0 -5
  753. package/src/hooks/useTrigger.js +0 -20
  754. package/src/hooks/useTrigger.spec.js +0 -102
  755. package/src/svg/BoundedObject.d.ts +0 -23
  756. package/src/svg/BoundedObject.js +0 -59
  757. package/src/svg/ClipRect.d.ts +0 -5
  758. package/src/svg/ClipRect.js +0 -23
  759. package/src/svg/Ellipse.d.ts +0 -24
  760. package/src/svg/Ellipse.js +0 -37
  761. package/src/svg/Line.d.ts +0 -21
  762. package/src/svg/Line.js +0 -33
  763. package/src/svg/NonOverlappingRect.d.ts +0 -5
  764. package/src/svg/NonOverlappingRect.js +0 -15
  765. package/src/svg/NonOverlappingRectGroup.d.ts +0 -3
  766. package/src/svg/NonOverlappingRectGroup.js +0 -37
  767. package/src/svg/Rectangle.d.ts +0 -37
  768. package/src/svg/Rectangle.js +0 -42
  769. package/src/svg/Svg.d.ts +0 -32
  770. package/src/svg/Svg.js +0 -177
  771. package/src/svg/Text.d.ts +0 -40
  772. package/src/svg/Text.js +0 -78
  773. package/src/svg/TextualBoundedObject.d.ts +0 -7
  774. package/src/svg/TextualBoundedObject.js +0 -28
  775. package/src/svg/index.d.ts +0 -11
  776. package/src/svg/util/Rect.d.ts +0 -41
  777. package/src/svg/util/Rect.js +0 -109
  778. package/src/svg/util/index.js +0 -1
  779. package/src/ui/CSS.d.ts +0 -20
  780. package/src/ui/CSS.js +0 -79
  781. package/src/ui/CSSHelper.d.ts +0 -11
  782. package/src/ui/CSSHelper.js +0 -18
  783. package/src/ui/Container.d.ts +0 -18
  784. package/src/ui/Container.js +0 -154
  785. package/src/ui/ContentResolver.d.ts +0 -12
  786. package/src/ui/ContentResolver.js +0 -78
  787. package/src/ui/Controller.d.ts +0 -182
  788. package/src/ui/Controller.js +0 -114
  789. package/src/ui/Controller.spec.js +0 -415
  790. package/src/ui/Culture.d.ts +0 -57
  791. package/src/ui/Culture.js +0 -139
  792. package/src/ui/Cx.d.ts +0 -18
  793. package/src/ui/Cx.js +0 -325
  794. package/src/ui/Cx.spec.js +0 -194
  795. package/src/ui/DataProxy.d.ts +0 -12
  796. package/src/ui/DataProxy.js +0 -31
  797. package/src/ui/DataProxy.spec.js +0 -338
  798. package/src/ui/DetachedScope.d.ts +0 -21
  799. package/src/ui/DetachedScope.js +0 -98
  800. package/src/ui/FocusManager.d.ts +0 -29
  801. package/src/ui/FocusManager.js +0 -171
  802. package/src/ui/Format.d.ts +0 -3
  803. package/src/ui/Format.js +0 -108
  804. package/src/ui/HoverSync.d.ts +0 -13
  805. package/src/ui/HoverSync.js +0 -147
  806. package/src/ui/Instance.d.ts +0 -72
  807. package/src/ui/Instance.js +0 -620
  808. package/src/ui/IsolatedScope.d.ts +0 -16
  809. package/src/ui/IsolatedScope.js +0 -30
  810. package/src/ui/IsolatedScope.spec.js +0 -62
  811. package/src/ui/Localization.d.ts +0 -17
  812. package/src/ui/Localization.js +0 -70
  813. package/src/ui/PureContainer.d.ts +0 -16
  814. package/src/ui/PureContainer.js +0 -7
  815. package/src/ui/RenderingContext.d.ts +0 -9
  816. package/src/ui/RenderingContext.js +0 -88
  817. package/src/ui/Repeater.d.ts +0 -61
  818. package/src/ui/Repeater.js +0 -109
  819. package/src/ui/Repeater.spec.js +0 -143
  820. package/src/ui/Rescope.d.ts +0 -10
  821. package/src/ui/Rescope.js +0 -35
  822. package/src/ui/Rescope.spec.js +0 -195
  823. package/src/ui/ResizeManager.d.ts +0 -10
  824. package/src/ui/ResizeManager.js +0 -31
  825. package/src/ui/Restate.d.ts +0 -21
  826. package/src/ui/Restate.js +0 -167
  827. package/src/ui/Restate.spec.js +0 -422
  828. package/src/ui/StaticText.d.ts +0 -8
  829. package/src/ui/StaticText.js +0 -9
  830. package/src/ui/StructuredInstanceDataAccessor.d.ts +0 -16
  831. package/src/ui/StructuredInstanceDataAccessor.js +0 -26
  832. package/src/ui/Text.d.ts +0 -10
  833. package/src/ui/Text.js +0 -25
  834. package/src/ui/VDOM.d.ts +0 -12
  835. package/src/ui/VDOM.js +0 -2
  836. package/src/ui/Widget.d.ts +0 -14
  837. package/src/ui/Widget.js +0 -184
  838. package/src/ui/ZIndexManager.d.ts +0 -7
  839. package/src/ui/ZIndexManager.js +0 -11
  840. package/src/ui/adapter/ArrayAdapter.d.ts +0 -17
  841. package/src/ui/adapter/ArrayAdapter.js +0 -152
  842. package/src/ui/adapter/ArrayAdapter.spec.js +0 -55
  843. package/src/ui/adapter/DataAdapter.d.ts +0 -31
  844. package/src/ui/adapter/DataAdapter.js +0 -15
  845. package/src/ui/adapter/GroupAdapter.d.ts +0 -23
  846. package/src/ui/adapter/GroupAdapter.js +0 -140
  847. package/src/ui/adapter/TreeAdapter.d.ts +0 -24
  848. package/src/ui/adapter/TreeAdapter.js +0 -101
  849. package/src/ui/adapter/TreeAdapter.spec.js +0 -67
  850. package/src/ui/adapter/index.js +0 -4
  851. package/src/ui/app/History.d.ts +0 -17
  852. package/src/ui/app/History.js +0 -114
  853. package/src/ui/app/Url.d.ts +0 -21
  854. package/src/ui/app/Url.js +0 -103
  855. package/src/ui/app/Url.spec.js +0 -51
  856. package/src/ui/app/index.d.ts +0 -4
  857. package/src/ui/app/startAppLoop.d.ts +0 -4
  858. package/src/ui/app/startAppLoop.js +0 -58
  859. package/src/ui/app/startHotAppLoop.d.ts +0 -7
  860. package/src/ui/app/startHotAppLoop.js +0 -25
  861. package/src/ui/batchUpdates.d.ts +0 -11
  862. package/src/ui/batchUpdates.js +0 -67
  863. package/src/ui/bind.d.ts +0 -4
  864. package/src/ui/bind.js +0 -7
  865. package/src/ui/createFunctionalComponent.d.ts +0 -1
  866. package/src/ui/createFunctionalComponent.js +0 -63
  867. package/src/ui/createFunctionalComponent.spec.js +0 -400
  868. package/src/ui/expr.d.ts +0 -24
  869. package/src/ui/expr.js +0 -17
  870. package/src/ui/flattenProps.js +0 -21
  871. package/src/ui/index.d.ts +0 -42
  872. package/src/ui/index.js +0 -44
  873. package/src/ui/keyboardShortcuts.d.ts +0 -5
  874. package/src/ui/keyboardShortcuts.js +0 -31
  875. package/src/ui/layout/Content.d.ts +0 -14
  876. package/src/ui/layout/Content.js +0 -16
  877. package/src/ui/layout/ContentPlaceholder.d.ts +0 -19
  878. package/src/ui/layout/ContentPlaceholder.js +0 -105
  879. package/src/ui/layout/ContentPlaceholder.spec.js +0 -579
  880. package/src/ui/layout/FirstVisibleChildLayout.d.ts +0 -4
  881. package/src/ui/layout/FirstVisibleChildLayout.js +0 -66
  882. package/src/ui/layout/FirstVisibleChildLayout.spec.js +0 -196
  883. package/src/ui/layout/LabelsLeftLayout.d.ts +0 -11
  884. package/src/ui/layout/LabelsLeftLayout.js +0 -59
  885. package/src/ui/layout/LabelsTopLayout.d.ts +0 -15
  886. package/src/ui/layout/LabelsTopLayout.js +0 -135
  887. package/src/ui/layout/UseParentLayout.d.ts +0 -4
  888. package/src/ui/layout/UseParentLayout.js +0 -6
  889. package/src/ui/layout/exploreChildren.d.ts +0 -12
  890. package/src/ui/layout/exploreChildren.js +0 -27
  891. package/src/ui/layout/index.js +0 -10
  892. package/src/ui/selection/KeySelection.d.ts +0 -17
  893. package/src/ui/selection/KeySelection.js +0 -129
  894. package/src/ui/selection/PropertySelection.d.ts +0 -17
  895. package/src/ui/selection/PropertySelection.js +0 -55
  896. package/src/ui/selection/Selection.d.ts +0 -27
  897. package/src/ui/selection/Selection.js +0 -93
  898. package/src/ui/selection/index.js +0 -3
  899. package/src/ui/tpl.d.ts +0 -3
  900. package/src/ui/tpl.js +0 -5
  901. package/src/util/Component.d.ts +0 -42
  902. package/src/util/Component.js +0 -108
  903. package/src/util/Console.d.ts +0 -4
  904. package/src/util/Console.js +0 -11
  905. package/src/util/DOM.d.ts +0 -33
  906. package/src/util/DOM.js +0 -72
  907. package/src/util/Debug.d.ts +0 -11
  908. package/src/util/Debug.js +0 -45
  909. package/src/util/Format.d.ts +0 -18
  910. package/src/util/Format.js +0 -270
  911. package/src/util/Format.spec.js +0 -69
  912. package/src/util/GlobalCacheIdentifier.js +0 -11
  913. package/src/util/GlobalCacheldentifier.d.ts +0 -7
  914. package/src/util/KeyCode.d.ts +0 -21
  915. package/src/util/KeyCode.js +0 -21
  916. package/src/util/SubscriberList.d.ts +0 -42
  917. package/src/util/SubscriberList.js +0 -58
  918. package/src/util/Timing.d.ts +0 -14
  919. package/src/util/Timing.js +0 -58
  920. package/src/util/TraversalStack.js +0 -43
  921. package/src/util/TraversalStack.spec.js +0 -47
  922. package/src/util/addEventListenerWithOptions.d.ts +0 -6
  923. package/src/util/addEventListenerWithOptions.js +0 -9
  924. package/src/util/browserSupportsPassiveEventHandlers.d.ts +0 -5
  925. package/src/util/browserSupportsPassiveEventHandlers.js +0 -18
  926. package/src/util/calculateNaturalElementHeight.d.ts +0 -1
  927. package/src/util/calculateNaturalElementHeight.js +0 -22
  928. package/src/util/capitalize.d.ts +0 -1
  929. package/src/util/capitalize.js +0 -4
  930. package/src/util/coalesce.d.ts +0 -1
  931. package/src/util/coalesce.js +0 -6
  932. package/src/util/color/hslToRgb.d.ts +0 -9
  933. package/src/util/color/hslToRgb.js +0 -27
  934. package/src/util/color/index.d.ts +0 -4
  935. package/src/util/color/parseColor.d.ts +0 -60
  936. package/src/util/color/parseColor.js +0 -119
  937. package/src/util/color/rgbToHex.d.ts +0 -9
  938. package/src/util/color/rgbToHex.js +0 -8
  939. package/src/util/color/rgbToHsl.d.ts +0 -9
  940. package/src/util/color/rgbToHsl.js +0 -28
  941. package/src/util/date/dateDiff.d.ts +0 -8
  942. package/src/util/date/dateDiff.js +0 -3
  943. package/src/util/date/diff.d.ts +0 -8
  944. package/src/util/date/diff.js +0 -7
  945. package/src/util/date/encodeDate.d.ts +0 -1
  946. package/src/util/date/encodeDate.js +0 -8
  947. package/src/util/date/encodeDateWithTimezoneOffset.d.ts +0 -1
  948. package/src/util/date/encodeDateWithTimezoneOffset.js +0 -19
  949. package/src/util/date/index.js +0 -11
  950. package/src/util/date/lowerBoundCheck.d.ts +0 -8
  951. package/src/util/date/lowerBoundCheck.js +0 -6
  952. package/src/util/date/maxDate.d.ts +0 -6
  953. package/src/util/date/maxDate.js +0 -9
  954. package/src/util/date/minDate.d.ts +0 -6
  955. package/src/util/date/minDate.js +0 -9
  956. package/src/util/date/monthStart.d.ts +0 -6
  957. package/src/util/date/monthStart.js +0 -3
  958. package/src/util/date/parseDateInvariant.d.ts +0 -3
  959. package/src/util/date/parseDateInvariant.js +0 -20
  960. package/src/util/date/sameDate.d.ts +0 -7
  961. package/src/util/date/sameDate.js +0 -5
  962. package/src/util/date/upperBoundCheck.d.ts +0 -8
  963. package/src/util/date/upperBoundCheck.js +0 -6
  964. package/src/util/date/zeroTime.d.ts +0 -7
  965. package/src/util/date/zeroTime.js +0 -3
  966. package/src/util/debounce.d.ts +0 -9
  967. package/src/util/debounce.js +0 -18
  968. package/src/util/dummyCallback.d.ts +0 -1
  969. package/src/util/dummyCallback.js +0 -1
  970. package/src/util/escapeSpecialRegexCharacters.d.ts +0 -7
  971. package/src/util/escapeSpecialRegexCharacters.js +0 -3
  972. package/src/util/eventCallbacks.d.ts +0 -5
  973. package/src/util/eventCallbacks.js +0 -2
  974. package/src/util/expandFatArrows.d.ts +0 -1
  975. package/src/util/expandFatArrows.js +0 -118
  976. package/src/util/findScrollableParent.d.ts +0 -1
  977. package/src/util/findScrollableParent.js +0 -16
  978. package/src/util/getActiveElement.d.ts +0 -1
  979. package/src/util/getActiveElement.js +0 -4
  980. package/src/util/getParentFrameBoundingClientRect.d.ts +0 -1
  981. package/src/util/getParentFrameBoundingClientRect.js +0 -21
  982. package/src/util/getScrollerBoundingClientRect.d.ts +0 -1
  983. package/src/util/getScrollerBoundingClientRect.js +0 -22
  984. package/src/util/getSearchQueryPredicate.d.ts +0 -1
  985. package/src/util/getSearchQueryPredicate.js +0 -59
  986. package/src/util/getTopLevelBoundingClientRect.d.ts +0 -1
  987. package/src/util/getTopLevelBoundingClientRect.js +0 -14
  988. package/src/util/getVendorPrefix.d.ts +0 -1
  989. package/src/util/getVendorPrefix.js +0 -26
  990. package/src/util/index.d.ts +0 -51
  991. package/src/util/index.js +0 -54
  992. package/src/util/innerTextTrim.d.ts +0 -7
  993. package/src/util/innerTextTrim.js +0 -5
  994. package/src/util/isArray.d.ts +0 -1
  995. package/src/util/isArray.js +0 -3
  996. package/src/util/isDefined.d.ts +0 -1
  997. package/src/util/isDefined.js +0 -3
  998. package/src/util/isDigit.d.ts +0 -7
  999. package/src/util/isDigit.js +0 -3
  1000. package/src/util/isFunction.d.ts +0 -1
  1001. package/src/util/isFunction.js +0 -3
  1002. package/src/util/isNonEmptyArray.d.ts +0 -1
  1003. package/src/util/isNonEmptyArray.js +0 -3
  1004. package/src/util/isNumber.d.ts +0 -1
  1005. package/src/util/isNumber.js +0 -3
  1006. package/src/util/isObject.d.ts +0 -1
  1007. package/src/util/isObject.js +0 -3
  1008. package/src/util/isPromise.d.ts +0 -1
  1009. package/src/util/isPromise.js +0 -6
  1010. package/src/util/isString.d.ts +0 -1
  1011. package/src/util/isString.js +0 -3
  1012. package/src/util/isTextInputElement.d.ts +0 -1
  1013. package/src/util/isTextInputElement.js +0 -3
  1014. package/src/util/isTouchDevice.d.ts +0 -2
  1015. package/src/util/isTouchDevice.js +0 -7
  1016. package/src/util/isTouchEvent.d.ts +0 -4
  1017. package/src/util/isTouchEvent.js +0 -64
  1018. package/src/util/isUndefined.d.ts +0 -1
  1019. package/src/util/isUndefined.js +0 -3
  1020. package/src/util/isValidIdentifierName.d.ts +0 -1
  1021. package/src/util/isValidIdentifierName.js +0 -5
  1022. package/src/util/onIdleCallback.d.ts +0 -1
  1023. package/src/util/onIdleCallback.js +0 -14
  1024. package/src/util/parseStyle.d.ts +0 -4
  1025. package/src/util/parseStyle.js +0 -27
  1026. package/src/util/quote.d.ts +0 -3
  1027. package/src/util/quote.js +0 -4
  1028. package/src/util/reverseSlice.d.ts +0 -1
  1029. package/src/util/reverseSlice.js +0 -10
  1030. package/src/util/routeAppend.d.ts +0 -1
  1031. package/src/util/routeAppend.js +0 -16
  1032. package/src/util/scrollElementIntoView.d.ts +0 -7
  1033. package/src/util/scrollElementIntoView.js +0 -34
  1034. package/src/util/shallowEquals.d.ts +0 -1
  1035. package/src/util/shallowEquals.js +0 -43
  1036. package/src/util/throttle.d.ts +0 -9
  1037. package/src/util/throttle.js +0 -14
  1038. package/src/util/validatedDebounce.js +0 -19
  1039. package/src/widgets/Button.d.ts +0 -58
  1040. package/src/widgets/Button.js +0 -118
  1041. package/src/widgets/CxCredit.d.ts +0 -12
  1042. package/src/widgets/CxCredit.js +0 -32
  1043. package/src/widgets/DocumentTitle.d.ts +0 -11
  1044. package/src/widgets/DocumentTitle.js +0 -69
  1045. package/src/widgets/FlexBox.d.ts +0 -69
  1046. package/src/widgets/FlexBox.js +0 -93
  1047. package/src/widgets/Heading.d.ts +0 -16
  1048. package/src/widgets/Heading.js +0 -33
  1049. package/src/widgets/HighlightedSearchText.d.ts +0 -9
  1050. package/src/widgets/HighlightedSearchText.js +0 -36
  1051. package/src/widgets/HtmlElement.d.ts +0 -30
  1052. package/src/widgets/HtmlElement.js +0 -275
  1053. package/src/widgets/HtmlElement.spec.js +0 -57
  1054. package/src/widgets/Icon.d.ts +0 -34
  1055. package/src/widgets/Icon.js +0 -50
  1056. package/src/widgets/List.d.ts +0 -96
  1057. package/src/widgets/List.js +0 -594
  1058. package/src/widgets/ProgressBar.d.ts +0 -17
  1059. package/src/widgets/ProgressBar.js +0 -46
  1060. package/src/widgets/Resizer.d.ts +0 -27
  1061. package/src/widgets/Resizer.js +0 -151
  1062. package/src/widgets/Sandbox.d.ts +0 -18
  1063. package/src/widgets/Sandbox.js +0 -65
  1064. package/src/widgets/Section.d.ts +0 -52
  1065. package/src/widgets/Section.js +0 -139
  1066. package/src/widgets/autoFocus.d.ts +0 -1
  1067. package/src/widgets/autoFocus.js +0 -9
  1068. package/src/widgets/cx.d.ts +0 -2
  1069. package/src/widgets/cx.js +0 -72
  1070. package/src/widgets/drag-drop/DragHandle.d.ts +0 -10
  1071. package/src/widgets/drag-drop/DragHandle.js +0 -37
  1072. package/src/widgets/drag-drop/DragSource.d.ts +0 -45
  1073. package/src/widgets/drag-drop/DragSource.js +0 -160
  1074. package/src/widgets/drag-drop/DropZone.d.ts +0 -98
  1075. package/src/widgets/drag-drop/DropZone.js +0 -214
  1076. package/src/widgets/drag-drop/index.d.ts +0 -4
  1077. package/src/widgets/drag-drop/ops.d.ts +0 -57
  1078. package/src/widgets/drag-drop/ops.js +0 -344
  1079. package/src/widgets/enableAllInternalDependencies.d.ts +0 -1
  1080. package/src/widgets/enableAllInternalDependencies.js +0 -11
  1081. package/src/widgets/form/Calendar.d.ts +0 -86
  1082. package/src/widgets/form/Calendar.js +0 -618
  1083. package/src/widgets/form/Checkbox.d.ts +0 -43
  1084. package/src/widgets/form/Checkbox.js +0 -203
  1085. package/src/widgets/form/ColorField.d.ts +0 -44
  1086. package/src/widgets/form/ColorField.js +0 -397
  1087. package/src/widgets/form/ColorPicker.d.ts +0 -23
  1088. package/src/widgets/form/ColorPicker.js +0 -485
  1089. package/src/widgets/form/DateField.d.ts +0 -6
  1090. package/src/widgets/form/DateField.js +0 -12
  1091. package/src/widgets/form/DateTimeField.d.ts +0 -89
  1092. package/src/widgets/form/DateTimeField.js +0 -576
  1093. package/src/widgets/form/DateTimePicker.js +0 -392
  1094. package/src/widgets/form/Field.d.ts +0 -112
  1095. package/src/widgets/form/Field.js +0 -446
  1096. package/src/widgets/form/FieldGroup.d.ts +0 -6
  1097. package/src/widgets/form/FieldGroup.js +0 -6
  1098. package/src/widgets/form/FieldIcon.js +0 -42
  1099. package/src/widgets/form/HelpText.d.ts +0 -10
  1100. package/src/widgets/form/HelpText.js +0 -9
  1101. package/src/widgets/form/Label.d.ts +0 -23
  1102. package/src/widgets/form/Label.js +0 -89
  1103. package/src/widgets/form/LabeledContainer.d.ts +0 -9
  1104. package/src/widgets/form/LabeledContainer.js +0 -59
  1105. package/src/widgets/form/LookupField.d.ts +0 -179
  1106. package/src/widgets/form/LookupField.js +0 -1135
  1107. package/src/widgets/form/MonthField.d.ts +0 -104
  1108. package/src/widgets/form/MonthField.js +0 -524
  1109. package/src/widgets/form/MonthPicker.d.ts +0 -97
  1110. package/src/widgets/form/MonthPicker.js +0 -687
  1111. package/src/widgets/form/NumberField.d.ts +0 -96
  1112. package/src/widgets/form/NumberField.js +0 -459
  1113. package/src/widgets/form/Radio.d.ts +0 -37
  1114. package/src/widgets/form/Radio.js +0 -188
  1115. package/src/widgets/form/Select.d.ts +0 -69
  1116. package/src/widgets/form/Select.js +0 -269
  1117. package/src/widgets/form/Slider.d.ts +0 -65
  1118. package/src/widgets/form/Slider.js +0 -351
  1119. package/src/widgets/form/Switch.d.ts +0 -38
  1120. package/src/widgets/form/Switch.js +0 -118
  1121. package/src/widgets/form/TextArea.d.ts +0 -17
  1122. package/src/widgets/form/TextArea.js +0 -195
  1123. package/src/widgets/form/TextField.d.ts +0 -78
  1124. package/src/widgets/form/TextField.js +0 -290
  1125. package/src/widgets/form/TimeField.d.ts +0 -6
  1126. package/src/widgets/form/TimeField.js +0 -11
  1127. package/src/widgets/form/TimeList.js +0 -84
  1128. package/src/widgets/form/UploadButton.d.ts +0 -34
  1129. package/src/widgets/form/UploadButton.js +0 -213
  1130. package/src/widgets/form/ValidationError.d.ts +0 -10
  1131. package/src/widgets/form/ValidationError.js +0 -44
  1132. package/src/widgets/form/ValidationGroup.d.ts +0 -41
  1133. package/src/widgets/form/ValidationGroup.js +0 -68
  1134. package/src/widgets/form/ValidationGroup.spec.js +0 -148
  1135. package/src/widgets/form/Validator.d.ts +0 -8
  1136. package/src/widgets/form/Validator.js +0 -21
  1137. package/src/widgets/form/Wheel.js +0 -261
  1138. package/src/widgets/form/index.d.ts +0 -26
  1139. package/src/widgets/grid/Grid.d.ts +0 -442
  1140. package/src/widgets/grid/Grid.js +0 -3429
  1141. package/src/widgets/grid/GridCell.d.ts +0 -38
  1142. package/src/widgets/grid/GridCell.js +0 -71
  1143. package/src/widgets/grid/GridCellEditor.js +0 -41
  1144. package/src/widgets/grid/GridRow.js +0 -228
  1145. package/src/widgets/grid/GridRowLine.js +0 -24
  1146. package/src/widgets/grid/Pagination.d.ts +0 -14
  1147. package/src/widgets/grid/Pagination.js +0 -95
  1148. package/src/widgets/grid/TreeNode.d.ts +0 -23
  1149. package/src/widgets/grid/TreeNode.js +0 -102
  1150. package/src/widgets/grid/index.d.ts +0 -4
  1151. package/src/widgets/grid/index.js +0 -15
  1152. package/src/widgets/icons/calendar.js +0 -16
  1153. package/src/widgets/icons/check.js +0 -12
  1154. package/src/widgets/icons/clear.js +0 -14
  1155. package/src/widgets/icons/close.js +0 -19
  1156. package/src/widgets/icons/cx.js +0 -37
  1157. package/src/widgets/icons/drop-down.js +0 -14
  1158. package/src/widgets/icons/file.js +0 -12
  1159. package/src/widgets/icons/folder-open.js +0 -14
  1160. package/src/widgets/icons/folder.js +0 -12
  1161. package/src/widgets/icons/forward.js +0 -21
  1162. package/src/widgets/icons/loading.js +0 -23
  1163. package/src/widgets/icons/menu.js +0 -16
  1164. package/src/widgets/icons/pixel-picker.js +0 -17
  1165. package/src/widgets/icons/registry.js +0 -54
  1166. package/src/widgets/icons/search.js +0 -12
  1167. package/src/widgets/icons/sort-asc.js +0 -13
  1168. package/src/widgets/icons/square.js +0 -17
  1169. package/src/widgets/nav/Link.d.ts +0 -26
  1170. package/src/widgets/nav/Link.js +0 -8
  1171. package/src/widgets/nav/LinkButton.d.ts +0 -34
  1172. package/src/widgets/nav/LinkButton.js +0 -128
  1173. package/src/widgets/nav/Menu.d.ts +0 -27
  1174. package/src/widgets/nav/Menu.js +0 -406
  1175. package/src/widgets/nav/MenuItem.d.ts +0 -31
  1176. package/src/widgets/nav/MenuItem.js +0 -445
  1177. package/src/widgets/nav/MenuSpacer.d.ts +0 -5
  1178. package/src/widgets/nav/MenuSpacer.js +0 -13
  1179. package/src/widgets/nav/RedirectRoute.d.ts +0 -9
  1180. package/src/widgets/nav/RedirectRoute.js +0 -41
  1181. package/src/widgets/nav/Route.d.ts +0 -21
  1182. package/src/widgets/nav/Route.js +0 -102
  1183. package/src/widgets/nav/Route.spec.js +0 -27
  1184. package/src/widgets/nav/Scroller.d.ts +0 -17
  1185. package/src/widgets/nav/Scroller.js +0 -214
  1186. package/src/widgets/nav/Submenu.d.ts +0 -6
  1187. package/src/widgets/nav/Submenu.js +0 -6
  1188. package/src/widgets/nav/Tab.d.ts +0 -33
  1189. package/src/widgets/nav/Tab.js +0 -82
  1190. package/src/widgets/nav/index.d.ts +0 -10
  1191. package/src/widgets/overlay/ContextMenu.d.ts +0 -10
  1192. package/src/widgets/overlay/ContextMenu.js +0 -29
  1193. package/src/widgets/overlay/Dropdown.d.ts +0 -32
  1194. package/src/widgets/overlay/Dropdown.js +0 -612
  1195. package/src/widgets/overlay/FlyweightTooltipTracker.d.ts +0 -8
  1196. package/src/widgets/overlay/FlyweightTooltipTracker.js +0 -39
  1197. package/src/widgets/overlay/MsgBox.d.ts +0 -17
  1198. package/src/widgets/overlay/MsgBox.js +0 -116
  1199. package/src/widgets/overlay/Overlay.d.ts +0 -73
  1200. package/src/widgets/overlay/Overlay.js +0 -747
  1201. package/src/widgets/overlay/Toast.d.ts +0 -30
  1202. package/src/widgets/overlay/Toast.js +0 -93
  1203. package/src/widgets/overlay/Tooltip.d.ts +0 -50
  1204. package/src/widgets/overlay/Tooltip.js +0 -308
  1205. package/src/widgets/overlay/Window.d.ts +0 -42
  1206. package/src/widgets/overlay/Window.js +0 -202
  1207. package/src/widgets/overlay/alerts.d.ts +0 -7
  1208. package/src/widgets/overlay/alerts.js +0 -39
  1209. package/src/widgets/overlay/captureMouse.d.ts +0 -54
  1210. package/src/widgets/overlay/captureMouse.js +0 -124
  1211. package/src/widgets/overlay/createHotPromiseWindowFactory.d.ts +0 -18
  1212. package/src/widgets/overlay/createHotPromiseWindowFactory.js +0 -56
  1213. package/src/widgets/overlay/index.js +0 -11
  1214. package/src/widgets/overlay/tooltip-ops.d.ts +0 -11
  1215. package/src/widgets/overlay/tooltip-ops.js +0 -29
  1216. package/svg.d.ts +0 -1
  1217. package/svg.js +0 -1
  1218. package/ui.d.ts +0 -1
  1219. package/ui.js +0 -1
  1220. package/util.d.ts +0 -1
  1221. package/util.js +0 -1
  1222. package/widgets.d.ts +0 -1
  1223. package/widgets.js +0 -1
  1224. /package/src/charts/{index.js → index.ts} +0 -0
  1225. /package/src/data/{Binding.spec.js → Binding.spec.ts} +0 -0
  1226. /package/src/data/{View.spec.js → View.spec.ts} +0 -0
  1227. /package/src/data/{comparer.spec.js → comparer.spec.ts} +0 -0
  1228. /package/src/data/ops/{index.js → index.ts} +0 -0
  1229. /package/src/hooks/{index.d.ts → index.ts} +0 -0
  1230. /package/src/{index.js → index.ts} +0 -0
  1231. /package/src/svg/{index.js → index.ts} +0 -0
  1232. /package/src/svg/util/{index.d.ts → index.ts} +0 -0
  1233. /package/src/ui/adapter/{index.d.ts → index.ts} +0 -0
  1234. /package/src/ui/app/{index.js → index.ts} +0 -0
  1235. /package/src/ui/layout/{index.d.ts → index.ts} +0 -0
  1236. /package/src/ui/selection/{index.d.ts → index.ts} +0 -0
  1237. /package/src/util/color/{index.js → index.ts} +0 -0
  1238. /package/src/util/date/{index.d.ts → index.ts} +0 -0
  1239. /package/src/util/date/{upperBoundCheck.spec.js → upperBoundCheck.spec.ts} +0 -0
  1240. /package/src/util/{getSearchQueryPredicate.spec.js → getSearchQueryPredicate.spec.ts} +0 -0
  1241. /package/src/util/{isValidIdentifierName.spec.js → isValidIdentifierName.spec.ts} +0 -0
  1242. /package/src/util/{routeAppend.spec.js → routeAppend.spec.ts} +0 -0
  1243. /package/src/widgets/drag-drop/{index.js → index.ts} +0 -0
  1244. /package/src/widgets/form/{index.js → index.ts} +0 -0
  1245. /package/src/widgets/icons/{index.js → index.ts} +0 -0
  1246. /package/src/widgets/{index.js → index.ts} +0 -0
  1247. /package/src/widgets/nav/{index.js → index.ts} +0 -0
@@ -0,0 +1,4247 @@
1
+ /** @jsxImportSource react */
2
+ import * as React from "react";
3
+ import { View } from "../../data";
4
+ import { Binding } from "../../data/Binding";
5
+ import { getAccessor } from "../../data/getAccessor";
6
+ import { getSelector } from "../../data/getSelector";
7
+ import { isSelector } from "../../data/isSelector";
8
+ import { ArrayAdapter } from "../../ui/adapter/ArrayAdapter";
9
+ import { DataAdapter, DataAdapterRecord } from "../../ui/adapter/DataAdapter";
10
+ import { GroupAdapter } from "../../ui/adapter/GroupAdapter";
11
+ import { batchUpdates } from "../../ui/batchUpdates";
12
+ import { ContainerBase, StyledContainerConfig } from "../../ui/Container";
13
+ import { Cx } from "../../ui/Cx";
14
+ import { FocusManager, offFocusOut, oneFocusOut, unfocusElement } from "../../ui/FocusManager";
15
+ import { Format } from "../../ui/Format";
16
+ import { Instance, InstanceCache } from "../../ui/Instance";
17
+ import { Localization } from "../../ui/Localization";
18
+ import {
19
+ BooleanProp,
20
+ ClassProp,
21
+ CollatorOptions,
22
+ Config,
23
+ DataRecord,
24
+ NumberProp,
25
+ Prop,
26
+ RecordAlias,
27
+ SortDirection,
28
+ SortersProp,
29
+ StringProp,
30
+ StructuredProp,
31
+ StyleProp,
32
+ UnknownProp,
33
+ } from "../../ui/Prop";
34
+ import { PureContainer, PureContainerBase, PureContainerConfig } from "../../ui/PureContainer";
35
+ import { RenderingContext } from "../../ui/RenderingContext";
36
+ import { ResizeManager } from "../../ui/ResizeManager";
37
+ import { Selection, SimpleSelection } from "../../ui/selection/Selection";
38
+ import type { KeySelection } from "../../ui/selection/KeySelection";
39
+ import type { PropertySelection } from "../../ui/selection/PropertySelection";
40
+ import { StaticText } from "../../ui/StaticText";
41
+ import { getContent, VDOM, Widget, WidgetConfig } from "../../ui/Widget";
42
+ import { Console } from "../../util/Console";
43
+ import { debounce } from "../../util/debounce";
44
+ import { closest, findFirstChild } from "../../util/DOM";
45
+ import { findScrollableParent } from "../../util/findScrollableParent";
46
+ import { getActiveElement } from "../../util/getActiveElement";
47
+ import { getParentFrameBoundingClientRect } from "../../util/getParentFrameBoundingClientRect";
48
+ import { getTopLevelBoundingClientRect } from "../../util/getTopLevelBoundingClientRect";
49
+ import { isArray } from "../../util/isArray";
50
+ import { isDefined } from "../../util/isDefined";
51
+ import { isNonEmptyArray } from "../../util/isNonEmptyArray";
52
+ import { isNumber } from "../../util/isNumber";
53
+ import { isObject } from "../../util/isObject";
54
+ import { isString } from "../../util/isString";
55
+ import { isTextInputElement } from "../../util/isTextInputElement";
56
+ import { KeyCode } from "../../util/KeyCode";
57
+ import { parseStyle } from "../../util/parseStyle";
58
+ import { scrollElementIntoView } from "../../util/scrollElementIntoView";
59
+ import { shallowEquals } from "../../util/shallowEquals";
60
+ import { SubscriberList } from "../../util/SubscriberList";
61
+ import {
62
+ ddDetect,
63
+ ddMouseDown,
64
+ DragDropOperationContext,
65
+ DragEvent,
66
+ initiateDragDrop,
67
+ registerDropZone,
68
+ } from "../drag-drop/ops";
69
+ import { HtmlElement } from "../HtmlElement";
70
+ import DropDownIcon from "../icons/sort-asc";
71
+ import { captureMouse2, getCursorPos } from "../overlay/captureMouse";
72
+ import { tooltipMouseLeave, tooltipMouseMove } from "../overlay/tooltip-ops";
73
+ import { createGridCellEditor } from "./createGridCellEditor";
74
+ import { GridRow, GridRowComponent, GridRowConfig, GridRowInstance } from "./GridRow";
75
+ import { Create, CreateConfig } from "../../util";
76
+ import type { TreeAdapter } from "../../ui/adapter/TreeAdapter";
77
+ export { GridRowConfig };
78
+
79
+ type FetchRecordsResult<T> = T[] | { records: T[]; lastPage?: boolean; totalRecordCount?: number };
80
+
81
+ interface MappedGridRecord<T = any> extends DataAdapterRecord<T> {
82
+ row?: GridRowInstance;
83
+ vdom?: any;
84
+ fixedVdom?: any;
85
+ grouping?: any;
86
+ level?: number;
87
+ group?: any;
88
+ }
89
+
90
+ interface GridDragEvent<T> extends DragEvent {
91
+ target: {
92
+ recordBefore?: MappedGridRecord<T>;
93
+ recordAfter?: MappedGridRecord<T>;
94
+ insertionIndex: number;
95
+ totalRecordCount: number;
96
+ dropNextToTheRowAbove?: boolean | null;
97
+ };
98
+ }
99
+
100
+ interface GridRowDragEvent<T> extends DragEvent {
101
+ target: {
102
+ record: MappedGridRecord<T>;
103
+ index: number;
104
+ };
105
+ }
106
+
107
+ interface GridColumnDropEvent extends DragEvent {
108
+ target: {
109
+ grid: any;
110
+ instance: Instance;
111
+ index: number;
112
+ };
113
+ }
114
+
115
+ interface GridDropOperationContext extends DragDropOperationContext {
116
+ test: {
117
+ grid: any;
118
+ row: any;
119
+ column: any;
120
+ };
121
+ }
122
+
123
+ interface GridMoveCursorOptions {
124
+ focused?: boolean;
125
+ hover?: any;
126
+ scrollIntoView?: boolean;
127
+ select?: boolean;
128
+ selectRange?: boolean;
129
+ selectOptions?: any;
130
+ cellIndex?: number;
131
+ cellEdit?: boolean;
132
+ cancelEdit?: boolean;
133
+ }
134
+
135
+ interface GridGroupingKey {
136
+ [key: string]:
137
+ | Prop<any>
138
+ | {
139
+ value: Prop<any>;
140
+ direction: SortDirection;
141
+ };
142
+ }
143
+
144
+ interface GroupingResult<T> {
145
+ key: any;
146
+ aggregates: any;
147
+ name: string;
148
+ indexes: number[];
149
+ records: MappedGridRecord<T>[];
150
+ }
151
+
152
+ type GridColumnAlignment = "left" | "right" | "center";
153
+
154
+ interface GridGroupingConfig<T> {
155
+ key: GridGroupingKey;
156
+ aggregates?: StructuredProp;
157
+ showCaption?: boolean;
158
+ showFooter?: boolean;
159
+ showHeader?: boolean;
160
+ caption?: StringProp;
161
+ name?: StringProp;
162
+ text?: StringProp;
163
+ comparer?: (a: GroupingResult<T>, b: GroupingResult<T>) => number;
164
+ }
165
+
166
+ // TODO: Check Column config
167
+ // Props are in order based on docs
168
+
169
+ export interface GridColumnHeaderConfig {
170
+ text?: StringProp;
171
+ colSpan?: NumberProp;
172
+ rowSpan?: NumberProp;
173
+ align?: GridColumnAlignment;
174
+ allowSorting?: boolean;
175
+ items?: React.ReactNode;
176
+ children?: React.ReactNode;
177
+ tool?: React.ReactNode;
178
+ style?: StyleProp;
179
+ class?: ClassProp;
180
+ className?: ClassProp;
181
+ tooltip?: StringProp | StructuredProp;
182
+ defaultWidth?: NumberProp;
183
+ width?: NumberProp;
184
+ resizable?: boolean;
185
+ }
186
+
187
+ export interface GridColumnFooterConfig {
188
+ value?: Prop<any>;
189
+ format?: StringProp;
190
+ style?: StyleProp;
191
+ class?: StyleProp;
192
+ expand?: boolean;
193
+ }
194
+
195
+ export interface GridColumnCaptionConfig {
196
+ value?: Prop<any>;
197
+ format?: StringProp;
198
+ style?: StyleProp;
199
+ class?: StyleProp;
200
+ children?: React.ReactNode;
201
+ items?: React.ReactNode;
202
+ expand?: boolean;
203
+ }
204
+
205
+ export interface GridColumnConfig {
206
+ align?: GridColumnAlignment;
207
+ field?: string;
208
+ format?: StringProp;
209
+ header?: StringProp | GridColumnHeaderConfig;
210
+ header1?: StringProp | GridColumnHeaderConfig;
211
+ header2?: StringProp | GridColumnHeaderConfig;
212
+ header3?: StringProp | GridColumnHeaderConfig;
213
+ fixed?: BooleanProp;
214
+ sortable?: boolean;
215
+ aggregate?: "min" | "max" | "count" | "sum" | "distinct" | "avg";
216
+ aggregateAlias?: string;
217
+ aggregateField?: string;
218
+ aggregateValue?: UnknownProp;
219
+ caption?: GridColumnCaptionConfig | StringProp | false;
220
+ class?: ClassProp;
221
+ className?: ClassProp;
222
+ draggable?: boolean;
223
+ editable?: boolean;
224
+ editor?: React.ReactNode;
225
+ footer?: GridColumnFooterConfig | StringProp | false;
226
+ items?: React.ReactNode;
227
+ children?: React.ReactNode;
228
+ key?: string;
229
+ pad?: boolean;
230
+ sortField?: string;
231
+ sortValue?: Prop<any>;
232
+ style?: StyleProp;
233
+ trimWhitespace?: boolean;
234
+ visible?: BooleanProp;
235
+ if?: BooleanProp;
236
+ weightField?: string;
237
+
238
+ // Not in docs
239
+ value?: Prop<any>;
240
+ defaultWidth?: NumberProp;
241
+ width?: NumberProp;
242
+ resizable?: boolean;
243
+ comparer?: (a: any, b: any) => number;
244
+
245
+ /** Options for data sorting. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator */
246
+ sortOptions?: CollatorOptions;
247
+ colSpan?: NumberProp;
248
+
249
+ mergeCells?: Prop<null | false | "same-value" | "always">;
250
+ primarySortDirection?: "ASC" | "DESC";
251
+ }
252
+
253
+ export interface GridConfig<T = any> extends StyledContainerConfig {
254
+ /** An array of records to be displayed in the grid. */
255
+ records?: Prop<T[]>;
256
+
257
+ /** Set to true to add a vertical scroll and a fixed header to the grid. */
258
+ scrollable?: boolean;
259
+
260
+ /** A binding used to store the sorting order list. Commonly used for server-side sorting. */
261
+ sorters?: SortersProp;
262
+
263
+ /** A list of sorters to be prepended to the actual list of sorters. */
264
+ preSorters?: SortersProp;
265
+
266
+ /** A binding used to store the name of the field used for sorting grids. Available only if sorters are not used. */
267
+ sortField?: StringProp;
268
+
269
+ /** A binding used to store the sort direction. Available only if sorters are not used. Possible values are "ASC" and "DESC". Defaults to "ASC". */
270
+ sortDirection?: StringProp;
271
+
272
+ /** Default sort field. Used if neither sortField or sorters are set. */
273
+ defaultSortField?: string;
274
+
275
+ /** Default sort direction. */
276
+ defaultSortDirection?: "ASC" | "DESC";
277
+
278
+ /** Set to true to add vertical gridlines. */
279
+ vlines?: boolean;
280
+
281
+ /** Text to be displayed instead of an empty table. */
282
+ emptyText?: StringProp;
283
+
284
+ /** Drag source configuration. Define mode as 'move' or 'copy` and additional data. */
285
+ dragSource?: StructuredProp;
286
+
287
+ /** Drop zone configuration. Define mode as either preview or insertion. */
288
+ dropZone?: StructuredProp;
289
+
290
+ /** Row configuration. See grid examples. */
291
+ row?: GridRowConfig;
292
+
293
+ /**An array of columns. Check column configuration options in the section below. */
294
+ columns?: GridColumnConfig[];
295
+
296
+ /** Whenever columnParams change, columns are recalculated using the onGetColumn callback. */
297
+ columnParams?: StructuredProp;
298
+
299
+ /** Selection configuration. */
300
+ selection?:
301
+ | CreateConfig<typeof Selection>
302
+ | CreateConfig<typeof KeySelection>
303
+ | CreateConfig<typeof PropertySelection>
304
+ | CreateConfig<typeof SimpleSelection>;
305
+
306
+ /** A grouping definition, field name, or an array of grouping level definitions. */
307
+ grouping?: string | GridGroupingConfig<T> | (string | GridGroupingConfig<T>)[];
308
+
309
+ /** Params for grouping. Whenever params change grouping is recalculated using the onGetGrouping callback. */
310
+ groupingParams?: StructuredProp;
311
+
312
+ /**
313
+ * Determines header appearance. Supported values are plain and default. Default mode is used if some of the columns are sortable.
314
+ * Plain mode better suits reports and other scenarios in which users do not interact with the grid.
315
+ */
316
+ headerMode?: StringProp;
317
+
318
+ /** Set to true to add default border around the table. Automatically set if grid is scrollable. */
319
+ border?: BooleanProp;
320
+
321
+ /** Base CSS class to be applied to the element. Default is 'grid'. */
322
+ baseClass?: string;
323
+
324
+ /** A field used to get the unique identifier of the record. Setting keyField improves grid performance on sort operations as the widget is able to identify row movement inside the grid. */
325
+ keyField?: string;
326
+
327
+ /** Show grid header within the group. Useful for long report-like (printable) grids. Defaults to false. */
328
+ showHeader?: boolean;
329
+
330
+ /** Show grid footer. Defaults to false. */
331
+ showFooter?: boolean;
332
+
333
+ /** Record alias. Default is $record. */
334
+ recordName?: RecordAlias;
335
+
336
+ /** Record alias. Default is $record. */
337
+ recordAlias?: RecordAlias;
338
+
339
+ /** Set to true if sorting is done remotely, on the server-side. Default value is false. */
340
+ remoteSort?: boolean;
341
+
342
+ /** Set to true to enable row caching. This greatly improves grid performance
343
+ on subsequent render operations, however, only changes on records
344
+ are allowed. If grid rows display any data outside records, changes on that
345
+ data will be ignored. */
346
+ cached?: boolean;
347
+
348
+ /** Render only rows visible on the screen. */
349
+ buffered?: boolean;
350
+
351
+ /** Specifies how many rows should be visible on the screen */
352
+ bufferSize?: number;
353
+
354
+ /** Specifies how many rows needs to be scrolled in order to recalculate buffer */
355
+ bufferStep?: number;
356
+
357
+ /** Used when rows have variable heights to improve buffered rendering by measuring and caching rendered row heights. Default value is false. */
358
+ measureRowHeights?: boolean;
359
+
360
+ /** Scrolls selection into the view. Default value is false. */
361
+ scrollSelectionIntoView?: boolean;
362
+
363
+ /**
364
+ * Set to true to lock column widths after the first render.
365
+ * This is helpful in pagination scenarios to maintain consistent looks across pages.
366
+ */
367
+ lockColumnWidths?: boolean;
368
+
369
+ lockColumnWidthsRequiredRowCount?: number;
370
+ focused?: boolean;
371
+ showBorder?: boolean;
372
+
373
+ /** Data adapter used to convert data in list of records. Used to enable grouping and tree operations. */
374
+ dataAdapter?:
375
+ | Create<typeof DataAdapter>
376
+ | Create<typeof ArrayAdapter>
377
+ | Create<typeof TreeAdapter>
378
+ | Create<typeof GroupAdapter>;
379
+
380
+ /** Additional CSS class to be added to each grid row. */
381
+ rowClass?: ClassProp;
382
+
383
+ /** Additional CSS styles to be added to each grid row. */
384
+ rowStyle?: StyleProp;
385
+
386
+ // drag-drop handlers
387
+ onDrop?: string | ((e: GridDragEvent<T>, instance: Instance) => void);
388
+ onDropTest?: string | ((e: DragEvent, instance: Instance) => boolean);
389
+ onDragStart?: string | ((e: DragEvent, instance: Instance) => void);
390
+ onDragEnd?: string | ((e: DragEvent, instance: Instance) => void);
391
+ onDragOver?: string | ((e: GridDragEvent<T>, instance: Instance) => void | boolean);
392
+
393
+ onRowDropTest?: string | ((e: DragEvent, instance: Instance) => boolean);
394
+ onRowDragOver?: string | ((e: GridRowDragEvent<T>, instance: Instance) => void | boolean);
395
+ onRowDrop?: string | ((e: GridRowDragEvent<T>, instance: Instance) => void | boolean);
396
+
397
+ onColumnDrop?: string | ((e: GridColumnDropEvent, instance: Instance) => void);
398
+ onColumnDropTest?: string | ((e: DragEvent, instance: Instance) => boolean);
399
+
400
+ /** Parameters that affect filtering. */
401
+ filterParams?: StructuredProp;
402
+
403
+ /** Callback function to be executed when a row is right-clicked. */
404
+ onRowContextMenu?: string | ((e: React.SyntheticEvent<any>, instance: Instance) => void);
405
+
406
+ /** Callback to create a filter function for given filter params. */
407
+ onCreateFilter?: (filterParams: any, instance?: Instance) => (record: T) => boolean;
408
+
409
+ /** Enable infinite scrolling */
410
+ infinite?: boolean;
411
+
412
+ /** If set, clicking on the column header will loop between ASC, DESC and no sorting order, instead of ASC and DESC only. */
413
+ clearableSort?: boolean;
414
+
415
+ /** A callback to fetch records during infinite loading */
416
+ onFetchRecords?: (
417
+ pageInfo: {
418
+ page: number;
419
+ pageSize: number;
420
+ sorters?: DataRecord[];
421
+ sortField?: string;
422
+ sortDirection?: string;
423
+ },
424
+ instance?: Instance,
425
+ ) => FetchRecordsResult<T> | Promise<FetchRecordsResult<T>>;
426
+
427
+ /** Callback function to be executed when a row is double-clicked. */
428
+ onRowDoubleClick?: string | ((e: React.SyntheticEvent<any>, instance: Instance) => void);
429
+
430
+ /** Callback function to be executed on key down. Accepts instance of the currently focused record as the second argument. */
431
+ onRowKeyDown?: string | ((e: React.SyntheticEvent<any>, instance: Instance) => void);
432
+
433
+ /** Callback function to be executed when a row is clicked. */
434
+ onRowClick?: string | ((e: React.SyntheticEvent<any>, instance: Instance) => void);
435
+
436
+ /** Set to true to add a fixed footer at the bottom of the grid. */
437
+ fixedFooter?: boolean;
438
+
439
+ /** Set to true to enable cell editing. Please note that all editable columns should specify the editor field. */
440
+ cellEditable?: boolean;
441
+
442
+ /** A callback function which is executed before a cell editor is initialized. Return false from the callback to prevent the cell from going into the edit mode. */
443
+ onBeforeCellEdit?: string | ((change: GridCellBeforeEditInfo, record: DataAdapterRecord<T>) => any);
444
+
445
+ /** A callback function which is executed after a cell has been successfully edited. */
446
+ onCellEdited?: string | ((change: GridCellEditInfo<T>, record: DataAdapterRecord<T>) => void);
447
+
448
+ /** A callback function which is executed after a column has been resized. */
449
+ onColumnResize?: (data: { width: number; column: Config }, instance: Instance) => void;
450
+
451
+ /** Options for data sorting. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator */
452
+ sortOptions?: CollatorOptions;
453
+
454
+ /** Callback to create a function that can be used to check whether a record is selectable. */
455
+ onCreateIsRecordSelectable?: (
456
+ params: any,
457
+ instance: Instance,
458
+ ) => (record: T, options?: { range?: boolean; toggle?: boolean }) => boolean;
459
+
460
+ /** Parameters whose change will cause scroll to be reset. */
461
+ scrollResetParams?: StructuredProp;
462
+
463
+ /** Enable precise (sub-pixel) measurements. Useful for grids with many columns. Better behavior at small zoom factors. */
464
+ preciseMeasurements?: boolean;
465
+
466
+ /** A value used to identify the group of components participating in hover effect synchronization. */
467
+ hoverChannel?: string;
468
+
469
+ /** A value used to uniquely identify the record within the hover sync group. */
470
+ rowHoverId?: Prop<string | number>;
471
+
472
+ /** Set to true or false to explicitly define if grid is allowed to receive focus. */
473
+ focusable?: boolean;
474
+
475
+ /** Callback function to retrieve grouping data. */
476
+ onGetGrouping?: (params: any, instance: Instance) => GridGroupingConfig<T>[];
477
+
478
+ /** Callback function to dynamically calculate columns. */
479
+ onGetColumns?: (params: any, instance: Instance) => GridColumnConfig[] | GridRowConfig;
480
+
481
+ /** Allow grid to receive drag and drop operations containing files. */
482
+ allowsFileDrops?: boolean;
483
+
484
+ /**
485
+ * Callback function to track and retrieve displayed records.
486
+ * Accepts new records as a first argument.
487
+ * If onCreateFilter callback is defined, filtered records can be retrieved using this callback.
488
+ */
489
+ onTrackMappedRecords?: string | ((records: DataAdapterRecord<T>[], instance: Instance) => void);
490
+
491
+ /** Callback to create a function that can be used to check whether a record is draggable. */
492
+ onCreateIsRecordDraggable?: (params: any, instance: Instance) => (record: T) => boolean;
493
+
494
+ /** Callback function to get grid component and instance references on component init. */
495
+ onRef?: string | ((element: any, instance: Instance) => void);
496
+
497
+ /** When enabled, groups are shown in the same order as the source records. */
498
+ preserveGroupOrder?: boolean;
499
+ }
500
+
501
+ export interface GridCellInfo {
502
+ column: any;
503
+ field: string;
504
+ }
505
+
506
+ export interface GridCellBeforeEditInfo extends GridCellInfo {
507
+ data: any;
508
+ }
509
+
510
+ export interface GridCellEditInfo<T> extends GridCellInfo {
511
+ oldData: T;
512
+ newData: T;
513
+ }
514
+
515
+ export interface GridInstance<T = any> extends Instance<Grid<T>> {
516
+ widget: Grid<T>;
517
+ isRecordSelectable?: (record: any, options?: any) => boolean;
518
+ visibleColumns: any[];
519
+ isRecordDraggable?: (record: any) => boolean;
520
+ row?: any;
521
+ fixedFooterVDOM?: any;
522
+ fixedColumnsFixedFooterVDOM?: any;
523
+ hasFixedColumns?: boolean;
524
+ recordInstanceCache?: any;
525
+ records?: MappedGridRecord<T>[];
526
+ isSelected: (record: any, index?: number) => boolean;
527
+ v: number;
528
+ buffer?: any;
529
+ dataAdapter: ArrayAdapter<T>;
530
+ fixedFooterIsGroupFooter?: boolean;
531
+ state?: any;
532
+ fixedColumnCount: number;
533
+ fixedHeaderResizeEvent?: any;
534
+ hoverSync?: any;
535
+ header?: any;
536
+ cached: any;
537
+ fixedFooterOverlap?: boolean;
538
+ }
539
+
540
+ export class Grid<T = unknown> extends ContainerBase<GridConfig<T>, GridInstance<T>> {
541
+ constructor(config?: GridConfig<T>) {
542
+ super(config);
543
+ }
544
+
545
+ declare records?: any;
546
+ declare scrollable?: boolean;
547
+ declare sorters?: any;
548
+ declare preSorters?: any;
549
+ declare sortField?: any;
550
+ declare sortDirection?: any;
551
+ declare defaultSortField?: string;
552
+ declare defaultSortDirection?: "ASC" | "DESC";
553
+ declare vlines?: boolean;
554
+ declare emptyText?: any;
555
+ declare dragSource?: any;
556
+ declare dropZone?: any;
557
+ declare row?: any;
558
+ declare columns?: any[];
559
+ declare columnParams?: any;
560
+ declare selection: any;
561
+ declare grouping?: string | GridGroupingConfig<any> | (string | GridGroupingConfig<any>)[];
562
+ declare groupingParams?: any;
563
+ declare headerMode?: any;
564
+ declare border?: any;
565
+ declare baseClass: string;
566
+ declare keyField?: string;
567
+ declare showHeader: boolean;
568
+ declare showFooter: boolean;
569
+ declare recordName: string;
570
+ declare recordAlias?: string;
571
+ declare indexName: string;
572
+ declare indexAlias?: string;
573
+ declare remoteSort: boolean;
574
+ declare cached: boolean;
575
+ declare buffered: boolean;
576
+ declare bufferSize: number;
577
+ declare bufferStep: number;
578
+ declare pageSize: number;
579
+ declare measureRowHeights?: boolean;
580
+ declare scrollSelectionIntoView: boolean;
581
+ declare lockColumnWidths: boolean;
582
+ declare lockColumnWidthsRequiredRowCount: number;
583
+ declare focused: boolean;
584
+ declare showBorder: boolean;
585
+ declare dataAdapter?: DataAdapter;
586
+ declare rowClass?: any;
587
+ declare rowStyle?: any;
588
+ declare onDrop?: any;
589
+ declare onDropTest?: any;
590
+ declare onDragStart?: any;
591
+ declare onDragEnd?: any;
592
+ declare onDragOver?: any;
593
+ declare onRowDropTest?: any;
594
+ declare onRowDragOver?: any;
595
+ declare onRowDrop?: any;
596
+ declare onColumnDrop?: any;
597
+ declare onColumnDropTest?: any;
598
+ declare filterParams?: any;
599
+ declare onRowContextMenu?: any;
600
+ declare onColumnContextMenu?: any;
601
+ declare onCreateFilter?: any;
602
+ declare infinite: boolean;
603
+ declare clearableSort: boolean;
604
+ declare onFetchRecords?: any;
605
+ declare onRowDoubleClick?: any;
606
+ declare onRowKeyDown?: any;
607
+ declare onKeyDown?: any;
608
+ declare onCellKeyDown?: any;
609
+ declare onRowClick?: any;
610
+ declare fixedFooter?: boolean;
611
+ declare cellEditable: boolean;
612
+ declare onBeforeCellEdit?: any;
613
+ declare onCellEdited?: any;
614
+ declare onColumnResize?: any;
615
+ declare sortOptions?: any;
616
+ declare onCreateIsRecordSelectable?: any;
617
+ declare scrollResetParams?: any;
618
+ declare preciseMeasurements: boolean;
619
+ declare hoverChannel: string;
620
+ declare rowHoverId?: any;
621
+ declare focusable: boolean | null;
622
+ declare onGetGrouping?: any;
623
+ declare onGetColumns?: any;
624
+ declare allowsFileDrops: boolean;
625
+ declare onTrackMappedRecords?: any;
626
+ declare onCreateIsRecordDraggable?: any;
627
+ declare onRef?: any;
628
+ declare preserveGroupOrder: boolean;
629
+ declare styled: boolean;
630
+ declare selectable?: boolean;
631
+ declare recordsAccessor: any;
632
+ declare hasResizableColumns?: boolean;
633
+ declare pipeKeyDown?: any;
634
+ declare onLoadingError?: any;
635
+
636
+ declareData(...args: any[]) {
637
+ let selection = this.selection.configureWidget(this);
638
+
639
+ super.declareData(
640
+ ...args,
641
+ {
642
+ records: undefined,
643
+ sorters: undefined,
644
+ preSorters: undefined,
645
+ scrollable: undefined,
646
+ sortField: undefined,
647
+ sortDirection: undefined,
648
+ emptyText: undefined,
649
+ dragSource: { structured: true },
650
+ dropZone: { structured: true },
651
+ filterParams: { structured: true },
652
+ groupingParams: { structured: true },
653
+ scrollResetParams: { structured: true },
654
+ page: undefined,
655
+ totalRecordCount: undefined,
656
+ tabIndex: undefined,
657
+ columnParams: { structured: true },
658
+ },
659
+ selection,
660
+ );
661
+ }
662
+
663
+ init() {
664
+ if (this.recordAlias) this.recordName = this.recordAlias;
665
+
666
+ if (this.indexAlias) this.indexName = this.indexAlias;
667
+
668
+ if (this.infinite) {
669
+ this.buffered = true;
670
+ this.remoteSort = true;
671
+ }
672
+
673
+ if (this.buffered) this.scrollable = true;
674
+
675
+ this.recordsAccessor = getAccessor(this.records);
676
+
677
+ this.selection = Selection.create(this.selection, {
678
+ records: this.records,
679
+ });
680
+
681
+ if (!this.selection.isDummy || this.onRowClick || this.onRowDoubleClick) this.selectable = true;
682
+ if (this.focusable == null) this.focusable = !this.selection.isDummy || this.cellEditable;
683
+
684
+ super.init();
685
+ }
686
+
687
+ initState(context: RenderingContext, instance: GridInstance) {
688
+ instance.state = {
689
+ colWidth: {},
690
+ lockedColWidth: {},
691
+ dimensionsVersion: 0,
692
+ disableDefaultSort: false,
693
+ };
694
+ instance.v = 0;
695
+ if (this.infinite)
696
+ instance.buffer = {
697
+ records: [],
698
+ totalRecordCount: 0,
699
+ page: 1,
700
+ };
701
+ }
702
+
703
+ applyParentStore(instance: GridInstance) {
704
+ super.applyParentStore(instance);
705
+
706
+ // force prepareData to execute again and propagate the store change to the records
707
+ if (instance.cached) delete instance.cached.rawData;
708
+ }
709
+
710
+ createRowTemplate(context: RenderingContext, columnParams: any, instance: GridInstance, groupingData: any) {
711
+ var row = this.row || {};
712
+ let columns = this.columns;
713
+ if (this.onGetColumns) {
714
+ let result = instance.invoke("onGetColumns", columnParams, instance);
715
+ if (isArray(result)) columns = result;
716
+ else row = result;
717
+ }
718
+
719
+ if (columns)
720
+ row.line1 = {
721
+ columns,
722
+ };
723
+
724
+ row.hasSortableColumns = false;
725
+ row.hasResizableColumns = false;
726
+ row.hasMergedCells = false;
727
+ row.mergedColumns = [];
728
+
729
+ let aggregates: Record<string, { value: any; weight: any; type: any }> = {};
730
+ let showFooter = false;
731
+ let lines = [];
732
+ for (let i = 0; i < 10; i++) {
733
+ let l = row["line" + i];
734
+ if (l) {
735
+ if (isArray(l.columns))
736
+ for (let c = 0; c < l.columns.length; c++)
737
+ l.columns[c].uniqueColumnId = `l${i}-${l.columns[c].key || c}`;
738
+ lines.push(l);
739
+ }
740
+ }
741
+
742
+ row.header = PureContainer.create({
743
+ items: GridColumnHeaderLine.create(lines),
744
+ });
745
+
746
+ row.header.items.forEach((line: any) => {
747
+ line.items.forEach((c: any, index: number) => {
748
+ if (c.sortable) row.hasSortableColumns = true;
749
+
750
+ if (c.mergeCells) {
751
+ if (row.header.items.length > 1)
752
+ Console.warn("Merged columns are only supported in grids in which rows have only one line of cells.");
753
+ else {
754
+ row.hasMergedCells = true;
755
+ row.mergedColumns.push({ uniqueColumnId: c.uniqueColumnId, index, mode: c.mergeCells });
756
+ }
757
+ }
758
+
759
+ if (
760
+ c.resizable ||
761
+ (c.header && c.header.resizable) ||
762
+ (c.header1 && c.header1.resizable) ||
763
+ (c.header2 && c.header2.resizable) ||
764
+ (c.header3 && c.header3.resizable)
765
+ )
766
+ row.hasResizableColumns = true;
767
+
768
+ if (c.aggregate && c.aggregateAlias && (c.aggregateField || isDefined(c.aggregateValue))) {
769
+ aggregates[c.aggregateAlias] = {
770
+ value: isDefined(c.aggregateValue)
771
+ ? c.aggregateValue
772
+ : isDefined(c.value)
773
+ ? c.value
774
+ : c.aggregateField
775
+ ? { bind: this.recordName + "." + c.aggregateField }
776
+ : null,
777
+ weight:
778
+ c.weight != null
779
+ ? c.weight
780
+ : c.weightField && {
781
+ bind: this.recordName + "." + c.weightField,
782
+ },
783
+ type: c.aggregate,
784
+ };
785
+ } else if (c.footer && !showFooter) {
786
+ showFooter = true;
787
+ }
788
+ });
789
+ });
790
+
791
+ //add default footer if some columns have aggregates and grouping is not defined
792
+ if (!groupingData && (Object.keys(aggregates).length > 0 || this.fixedFooter || showFooter))
793
+ groupingData = [
794
+ {
795
+ key: {},
796
+ showFooter: true,
797
+ },
798
+ ];
799
+
800
+ let { grouping, showHeader } = this.resolveGrouping(groupingData);
801
+
802
+ this.showHeader = showHeader;
803
+
804
+ if (this.fixedFooter && isNonEmptyArray(grouping)) {
805
+ grouping[0].showFooter = true;
806
+ if (grouping[0].key && Object.keys(grouping[0].key).length > 0)
807
+ Console.warn(
808
+ "First grouping level in grids with a fixed footer must group all data. The key field should be omitted.",
809
+ );
810
+ }
811
+
812
+ instance.dataAdapter =
813
+ this.dataAdapter instanceof ArrayAdapter
814
+ ? this.dataAdapter
815
+ : GroupAdapter.create(
816
+ {
817
+ recordsAccessor: this.recordsAccessor,
818
+ keyField: this.keyField,
819
+ aggregates: aggregates,
820
+ recordName: this.recordName,
821
+ indexName: this.indexName,
822
+ sortOptions: this.sortOptions,
823
+ groupings: grouping,
824
+ preserveOrder: this.preserveGroupOrder,
825
+ },
826
+ this.dataAdapter,
827
+ );
828
+
829
+ instance.dataAdapter.initInstance(context, instance);
830
+
831
+ return Widget.create(GridRow, {
832
+ class: this.CSS.element(this.baseClass, "data"),
833
+ className: this.rowClass,
834
+ style: this.rowStyle,
835
+ recordName: this.recordName,
836
+ hoverId: this.rowHoverId,
837
+ ...row,
838
+ });
839
+ }
840
+
841
+ prepareData(context: RenderingContext, instance: GridInstance) {
842
+ let { data, state, cached, row } = instance;
843
+
844
+ let grouping = this.grouping;
845
+
846
+ if (this.onGetGrouping) {
847
+ if (!cached.data || cached.data.groupingParams !== data.groupingParams)
848
+ grouping = instance.invoke("onGetGrouping", data.groupingParams, instance);
849
+ else grouping = cached.grouping;
850
+ }
851
+
852
+ let groupingChanged = instance.cache("grouping", grouping);
853
+
854
+ if (instance.cache("columnParams", data.columnParams) || groupingChanged || !row) {
855
+ row = instance.row = this.createRowTemplate(context, data.columnParams, instance, grouping);
856
+ }
857
+
858
+ data.version = instance.v++;
859
+
860
+ if (!this.infinite) data.totalRecordCount = isArray(data.records) ? data.records.length : 0;
861
+ else {
862
+ if (isNumber(data.totalRecordCount)) instance.buffer.totalRecordCount = data.totalRecordCount;
863
+ else data.totalRecordCount = instance.buffer.totalRecordCount;
864
+
865
+ if (isDefined(data.records)) instance.buffer.records = data.records;
866
+ else data.records = instance.buffer.records;
867
+
868
+ if (isNumber(data.page)) instance.buffer.page = data.page;
869
+ else data.page = instance.buffer.page;
870
+
871
+ data.offset = (data.page - 1) * this.pageSize;
872
+ }
873
+
874
+ if (!isArray(data.records)) data.records = [];
875
+
876
+ if (state.sorters && !isDefined(this.sorters)) data.sorters = state.sorters;
877
+
878
+ let sortField = null;
879
+
880
+ if (isDefined(this.sortField) && isDefined(this.sortDirection)) {
881
+ let sorter = {
882
+ field: data.sortField,
883
+ direction: data.sortDirection,
884
+ };
885
+ sortField = data.sortField;
886
+ data.sorters = [sorter];
887
+ }
888
+
889
+ let skipDefaultSorting = this.clearableSort && instance.state.disableDefaultSort;
890
+ if (!skipDefaultSorting && !isNonEmptyArray(data.sorters) && this.defaultSortField) {
891
+ let sorter = {
892
+ field: this.defaultSortField,
893
+ direction: this.defaultSortDirection || "ASC",
894
+ };
895
+ sortField = this.defaultSortField;
896
+ data.sorters = [sorter];
897
+ }
898
+
899
+ if (sortField) {
900
+ for (let l = 1; l < 10; l++) {
901
+ let line = instance.row[`line${l}`];
902
+ let sortColumn = line && line.columns && line.columns.find((c: any) => c.field == sortField);
903
+ if (sortColumn) {
904
+ data.sorters[0].value = sortColumn.sortValue || sortColumn.value;
905
+ data.sorters[0].comparer = sortColumn.comparer;
906
+ data.sorters[0].sortOptions = sortColumn.sortOptions;
907
+ break;
908
+ }
909
+ }
910
+ }
911
+
912
+ let headerMode = this.headerMode;
913
+
914
+ if (this.headerMode == null) {
915
+ if (this.scrollable || row.hasSortableColumns || row.hasResizableColumns) headerMode = "default";
916
+ else headerMode = "plain";
917
+ }
918
+
919
+ let border = this.border;
920
+
921
+ if (this.showBorder || (border == null && this.scrollable)) border = true;
922
+
923
+ let dragMode = false;
924
+ if (data.dragSource) dragMode = data.dragSource.mode || "move";
925
+
926
+ let dropMode = data.dropZone && data.dropZone.mode;
927
+
928
+ if (this.onDrop && !dropMode) dropMode = "preview";
929
+
930
+ data.dropMode = dropMode;
931
+
932
+ data.stateMods = {
933
+ selectable: this.selectable,
934
+ "cell-editable": this.cellEditable,
935
+ scrollable: data.scrollable,
936
+ buffered: this.buffered,
937
+ ["header-" + headerMode]: true,
938
+ border: border,
939
+ vlines: this.vlines,
940
+ ["drag-" + dragMode]: dragMode,
941
+ ["drop-" + dropMode]: dropMode,
942
+ resizable: row.hasResizableColumns,
943
+ };
944
+
945
+ super.prepareData(context, instance);
946
+
947
+ instance.records = this.mapRecords(context, instance);
948
+
949
+ //tree adapters can have additional (child) records, filtering also affects actual record count
950
+ if (instance.records && !this.infinite) {
951
+ //apply record count after filtering
952
+ data.totalRecordCount = instance.records.length;
953
+
954
+ //recheck if there are any actual records
955
+ //when grouping is enabled group header/footer are always in
956
+ if (instance.records.length < 5) {
957
+ data.empty = true;
958
+ for (let i = 0; i < instance.records.length; i++)
959
+ if (instance.records[i].type == "data") {
960
+ data.empty = false;
961
+ break;
962
+ }
963
+ } else data.empty = data.totalRecordCount == 0;
964
+ } else data.empty = data.totalRecordCount == 0;
965
+
966
+ if (this.onCreateIsRecordSelectable) {
967
+ instance.isRecordSelectable = instance.invoke("onCreateIsRecordSelectable", null, instance);
968
+ }
969
+
970
+ if (this.onCreateIsRecordDraggable) {
971
+ instance.isRecordDraggable = instance.invoke("onCreateIsRecordDraggable", null, instance);
972
+ }
973
+
974
+ if (this.onTrackMappedRecords) {
975
+ instance.invoke("onTrackMappedRecords", instance.records, instance);
976
+ }
977
+ }
978
+
979
+ initInstance(context: RenderingContext, instance: GridInstance) {
980
+ instance.fixedHeaderResizeEvent = new SubscriberList();
981
+ super.initInstance(context, instance);
982
+ }
983
+
984
+ explore(context: RenderingContext, instance: GridInstance) {
985
+ context.push("parentPositionChangeEvent", instance.fixedHeaderResizeEvent);
986
+
987
+ instance.hoverSync = context.hoverSync;
988
+
989
+ super.explore(context, instance);
990
+
991
+ instance.header = instance.getChild(context, instance.row.header, "header");
992
+ instance.header.scheduleExploreIfVisible(context);
993
+
994
+ let { store } = instance;
995
+ instance.isSelected = this.selection.getIsSelectedDelegate(store);
996
+
997
+ //do not process rows in buffered mode or cached mode if nothing has changed;
998
+ if (!this.buffered && (!this.cached || instance.shouldUpdate)) {
999
+ for (let i = 0; i < instance.records!.length; i++) {
1000
+ let record = instance.records![i];
1001
+ if (record.type == "data") {
1002
+ let row = (record.row = instance.getChild(
1003
+ context,
1004
+ instance.row,
1005
+ record.key,
1006
+ record.store,
1007
+ ) as GridRowInstance);
1008
+ row.selected = instance.isSelected(record.data, record.index);
1009
+ let changed = false;
1010
+ if (row.cache("selected", row.selected)) changed = true;
1011
+ if (row.cache("recordData", record.data)) changed = true;
1012
+ if (this.cached && !changed && !row.childStateDirty) row.shouldUpdate = false;
1013
+ else row.scheduleExploreIfVisible(context);
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+
1019
+ exploreCleanup(context: RenderingContext, instance: GridInstance) {
1020
+ context.pop("parentPositionChangeEvent");
1021
+ let fixedColumnCount = 0,
1022
+ visibleColumns: any[] = [];
1023
+ instance.header.children.forEach((line: any) => {
1024
+ line.children.forEach((col: any) => {
1025
+ if (col.data.fixed) fixedColumnCount++;
1026
+ visibleColumns.push(col.widget);
1027
+ });
1028
+ });
1029
+ instance.visibleColumns = visibleColumns;
1030
+ instance.hasFixedColumns = fixedColumnCount > 0;
1031
+ instance.fixedColumnCount = fixedColumnCount;
1032
+ if (fixedColumnCount > 0) {
1033
+ instance.data.classNames += ` ${instance.widget.CSS.state("fixed-columns")}`;
1034
+ }
1035
+ }
1036
+
1037
+ resolveGrouping(grouping: any) {
1038
+ if (grouping) {
1039
+ if (!isArray(grouping)) {
1040
+ if (isString(grouping) || isObject(grouping)) grouping = [grouping];
1041
+ else throw new Error("Dynamic grouping should be an array of grouping objects.");
1042
+ }
1043
+
1044
+ grouping = grouping.map((g: any, i: any) => {
1045
+ let group;
1046
+ if (isString(g))
1047
+ group = {
1048
+ key: {
1049
+ [g]: {
1050
+ bind: this.recordName + "." + g,
1051
+ },
1052
+ },
1053
+ showHeader: !this.scrollable && i == grouping.length - 1,
1054
+ showFooter: true,
1055
+ caption: { bind: `$group.${g}` },
1056
+ text: { bind: `${this.recordName}.${g}` },
1057
+ };
1058
+ else
1059
+ group = {
1060
+ ...g,
1061
+ };
1062
+ if (group.caption) group.caption = getSelector(group.caption);
1063
+ return group;
1064
+ });
1065
+ }
1066
+
1067
+ let showHeader = !isArray(grouping) || !grouping.some((g: any) => g.showHeader);
1068
+
1069
+ return { showHeader, grouping };
1070
+ }
1071
+
1072
+ groupBy(groupingData: any, options?: any) {
1073
+ let { grouping, showHeader } = this.resolveGrouping(groupingData);
1074
+ this.grouping = grouping;
1075
+ if (options?.autoConfigure) this.showHeader = showHeader;
1076
+ this.update();
1077
+ }
1078
+
1079
+ render(context: RenderingContext, instance: GridInstance, key: string) {
1080
+ let { data, hasFixedColumns } = instance;
1081
+
1082
+ let fixedHeader =
1083
+ data.scrollable && this.showHeader && this.renderHeader(context, instance, "header", true, false);
1084
+
1085
+ let fixedColumnsFixedHeader =
1086
+ data.scrollable &&
1087
+ this.showHeader &&
1088
+ hasFixedColumns &&
1089
+ this.renderHeader(context, instance, "header", true, true);
1090
+
1091
+ if (!this.buffered) this.renderRows(context, instance);
1092
+
1093
+ if (this.fixedFooter) this.renderFixedFooter(context, instance);
1094
+
1095
+ let header = this.showHeader && this.renderHeader(context, instance, "header", false, false);
1096
+
1097
+ let fixedColumnsHeader =
1098
+ this.showHeader && hasFixedColumns && this.renderHeader(context, instance, "header", false, true);
1099
+
1100
+ return (
1101
+ <GridComponent
1102
+ key={key}
1103
+ instance={instance}
1104
+ data={instance.data}
1105
+ shouldUpdate={instance.shouldUpdate}
1106
+ header={header}
1107
+ fixedColumnsHeader={fixedColumnsHeader}
1108
+ fixedColumnsFixedHeader={fixedColumnsFixedHeader}
1109
+ fixedHeader={fixedHeader}
1110
+ fixedFooter={instance.fixedFooterVDOM}
1111
+ fixedColumnsFixedFooter={instance.fixedColumnsFixedFooterVDOM}
1112
+ >
1113
+ {this.renderChildren(context, instance)}
1114
+ </GridComponent>
1115
+ );
1116
+ }
1117
+
1118
+ renderResizer(instance: GridInstance, hdinst: any, header: any, colIndex: number, forPreviousColumn?: any) {
1119
+ let { widget } = instance;
1120
+
1121
+ let { CSS, baseClass } = widget;
1122
+
1123
+ let hdwidget = hdinst.widget;
1124
+
1125
+ let resizerClassName = "col-resizer";
1126
+ if (forPreviousColumn) resizerClassName += "-prev-col";
1127
+
1128
+ return (
1129
+ <div
1130
+ className={CSS.element(baseClass, resizerClassName)}
1131
+ onClick={(e) => {
1132
+ e.stopPropagation();
1133
+ }}
1134
+ data-unique-col-id={hdwidget.uniqueColumnId}
1135
+ onMouseDown={(e) => {
1136
+ if (e.buttons != 1) return;
1137
+ let resizeOverlayEl: HTMLDivElement | null = document.createElement("div");
1138
+
1139
+ let gridEl = (e.target as HTMLElement).parentElement!.parentElement!.parentElement!.parentElement!
1140
+ .parentElement!.parentElement!;
1141
+ let uniqueColId = (e.currentTarget as HTMLElement).dataset.uniqueColId;
1142
+
1143
+ // if we use fixed columns, rhs resizer of the last fixed column is within regular columns header tbody
1144
+ let headerCell = findFirstChild(
1145
+ gridEl,
1146
+ (el) =>
1147
+ el.tagName == "TH" &&
1148
+ (el as HTMLElement).dataset &&
1149
+ (el as HTMLElement).dataset.uniqueColId == uniqueColId,
1150
+ );
1151
+
1152
+ let initialWidth = (headerCell as HTMLElement).offsetWidth;
1153
+ let initialPosition = getCursorPos(e);
1154
+ resizeOverlayEl.className = CSS.element(baseClass, "resize-overlay");
1155
+ resizeOverlayEl.style.width = `${initialWidth}px`;
1156
+ resizeOverlayEl.style.left = `${
1157
+ (headerCell as HTMLElement).getBoundingClientRect().left - gridEl.getBoundingClientRect().left
1158
+ }px`;
1159
+ gridEl.appendChild(resizeOverlayEl);
1160
+ captureMouse2(e, {
1161
+ onMouseMove: (e) => {
1162
+ let cursor = getCursorPos(e);
1163
+ let width = Math.max(30, Math.round(initialWidth + cursor.clientX - initialPosition.clientX));
1164
+ resizeOverlayEl!.style.width = `${width}px`;
1165
+ },
1166
+ onMouseUp: (e) => {
1167
+ if (!resizeOverlayEl) return; //dblclick
1168
+ let width = resizeOverlayEl.offsetWidth;
1169
+ hdinst.assignedWidth = width;
1170
+ gridEl.removeChild(resizeOverlayEl);
1171
+ resizeOverlayEl = null;
1172
+ if (widget.onColumnResize) instance.invoke("onColumnResize", { width, column: hdwidget }, hdinst);
1173
+ header.set("width", width);
1174
+ instance.setState({
1175
+ dimensionsVersion: instance.state.dimensionsVersion + 1,
1176
+ colWidth: {
1177
+ ...instance.state.colWidth,
1178
+ [hdwidget.uniqueColumnId]: width,
1179
+ },
1180
+ });
1181
+ },
1182
+ onDblClick: () => {
1183
+ let table = gridEl.querySelector("table")!;
1184
+ let parentEl = table.parentElement!;
1185
+ let tableClone: HTMLTableElement = table.cloneNode(true) as HTMLTableElement;
1186
+ tableClone.childNodes.forEach((tbody: any) => {
1187
+ tbody.childNodes.forEach((tr: any) => {
1188
+ tr.childNodes.forEach((td: any, index: number) => {
1189
+ if (index == colIndex) {
1190
+ td.style.maxWidth = null;
1191
+ td.style.minWidth = null;
1192
+ td.style.width = "auto";
1193
+ } else {
1194
+ td.style.display = "none";
1195
+ }
1196
+ });
1197
+ });
1198
+ });
1199
+ tableClone.style.position = "absolute";
1200
+ tableClone.style.visibility = "hidden";
1201
+ tableClone.style.top = "0";
1202
+ tableClone.style.left = "0";
1203
+ tableClone.style.width = "auto";
1204
+ parentEl.appendChild(tableClone);
1205
+ let width = tableClone.offsetWidth;
1206
+ parentEl.removeChild(tableClone);
1207
+ header.set("width", width);
1208
+ instance.setState({
1209
+ dimensionsVersion: instance.state.dimensionsVersion + 1,
1210
+ colWidth: {
1211
+ ...instance.state.colWidth,
1212
+ [hdwidget.uniqueColumnId]: width,
1213
+ },
1214
+ });
1215
+ },
1216
+ });
1217
+ }}
1218
+ />
1219
+ );
1220
+ }
1221
+
1222
+ renderHeader(context: RenderingContext, instance: GridInstance, key: any, fixed: any, fixedColumns: any) {
1223
+ let { data, widget, header } = instance;
1224
+
1225
+ let { CSS, baseClass } = widget;
1226
+
1227
+ let headerRows: any[] = [];
1228
+
1229
+ if (!header) return null;
1230
+
1231
+ let skip: any = {};
1232
+ let lineIndex = 0;
1233
+
1234
+ header.children.forEach((line: any) => {
1235
+ let empty = [true, true, true];
1236
+ let result: any[] = [[], [], []];
1237
+
1238
+ line.children.forEach((hdinst: any, colIndex: number) => {
1239
+ let hdwidget = hdinst.widget;
1240
+ for (let l = 0; l < 3; l++) {
1241
+ let colKey = `${lineIndex + l}-${colIndex}`;
1242
+
1243
+ if (skip[colKey]) continue;
1244
+
1245
+ if (Boolean(hdinst.data.fixed) != fixedColumns) continue;
1246
+
1247
+ let header = hdinst.components[`header${l + 1}`];
1248
+ let colSpan,
1249
+ rowSpan,
1250
+ style,
1251
+ cls,
1252
+ mods = [],
1253
+ content,
1254
+ sortIcon,
1255
+ tool;
1256
+
1257
+ let resizer = null,
1258
+ prevColumnResizer = null;
1259
+
1260
+ if (header) {
1261
+ empty[l] = false;
1262
+
1263
+ if (header.widget.align) mods.push("aligned-" + header.widget.align);
1264
+ else if (hdwidget.align) mods.push("aligned-" + hdwidget.align);
1265
+
1266
+ if (hdwidget.sortable && header.widget.allowSorting) {
1267
+ mods.push("sortable");
1268
+ if (data.sorters && data.sorters[0].field == (hdwidget.sortField || hdwidget.field)) {
1269
+ mods.push("sorted-" + data.sorters[0].direction.toLowerCase());
1270
+ sortIcon = <DropDownIcon className={CSS.element(baseClass, "column-sort-icon")} />;
1271
+ }
1272
+ }
1273
+
1274
+ let uniqueColumnId = header.data.colSpan > 1 ? null : hdwidget.uniqueColumnId;
1275
+
1276
+ style = header.data.style;
1277
+ let customWidth =
1278
+ header.data.width ||
1279
+ instance.state.colWidth[uniqueColumnId] ||
1280
+ header.data.defaultWidth ||
1281
+ instance.state.lockedColWidth[uniqueColumnId];
1282
+ if (customWidth) {
1283
+ if (instance.state.colWidth[uniqueColumnId] != customWidth)
1284
+ instance.state.colWidth[uniqueColumnId] = customWidth;
1285
+ let s = `${customWidth}px`;
1286
+ style = {
1287
+ ...style,
1288
+ width: s,
1289
+ minWidth: s,
1290
+ maxWidth: s,
1291
+ };
1292
+ }
1293
+
1294
+ if (header.data.classNames) cls = header.data.classNames;
1295
+
1296
+ content = header.render(context);
1297
+
1298
+ if (header.components && header.components.tool) {
1299
+ tool = (
1300
+ <div className={CSS.element(baseClass, "col-header-tool")}>
1301
+ {getContent(header.components.tool.render(context))}
1302
+ </div>
1303
+ );
1304
+ mods.push("tool");
1305
+ }
1306
+
1307
+ if (header.data.colSpan > 1 || header.data.rowSpan > 1) {
1308
+ colSpan = header.data.colSpan;
1309
+ rowSpan = header.data.rowSpan;
1310
+
1311
+ for (let r = 0; r < header.data.rowSpan; r++)
1312
+ for (let c = 0; c < header.data.colSpan; c++)
1313
+ skip[`${lineIndex + l + r}-${colIndex + c}`] = true;
1314
+ }
1315
+
1316
+ if ((hdwidget.resizable || header.data.resizable) && header.data.colSpan < 2) {
1317
+ resizer = this.renderResizer(instance, hdinst, header, colIndex);
1318
+ }
1319
+
1320
+ if (colIndex > 0) {
1321
+ let hdinstPrev = line.children[colIndex - 1];
1322
+ let prevLine = 3;
1323
+ let headerPrev;
1324
+ while (!headerPrev && prevLine >= 0) {
1325
+ headerPrev = hdinstPrev.components[`header${prevLine + 1}`];
1326
+ prevLine--;
1327
+ }
1328
+ if (
1329
+ (hdinstPrev.widget.resizable || headerPrev?.data?.resizable) &&
1330
+ headerPrev?.data?.colSpan < 2
1331
+ ) {
1332
+ prevColumnResizer = this.renderResizer(instance, hdinstPrev, headerPrev, colIndex - 1, true);
1333
+ }
1334
+ }
1335
+ }
1336
+
1337
+ cls = CSS.element(baseClass, "col-header", mods) + (cls ? " " + cls : "");
1338
+
1339
+ let onContextMenu;
1340
+
1341
+ if (this.onColumnContextMenu)
1342
+ onContextMenu = (e: any) => instance.invoke("onColumnContextMenu", e, hdinst);
1343
+
1344
+ result[l].push(
1345
+ <th
1346
+ key={colIndex}
1347
+ colSpan={colSpan}
1348
+ rowSpan={rowSpan}
1349
+ className={cls}
1350
+ style={style}
1351
+ onMouseDown={ddMouseDown}
1352
+ onMouseMove={(e) => this.onHeaderMouseMove(e, hdwidget, hdinst, instance, l)}
1353
+ onMouseLeave={(e) => this.onHeaderMouseLeave(e, hdinst, l)}
1354
+ onClick={(e) => this.onHeaderClick(e, hdwidget, instance, l)}
1355
+ onContextMenu={onContextMenu}
1356
+ data-unique-col-id={colSpan > 1 ? null : hdwidget.uniqueColumnId}
1357
+ >
1358
+ {getContent(content)}
1359
+ {sortIcon}
1360
+ {tool}
1361
+ {prevColumnResizer}
1362
+ {resizer}
1363
+ </th>,
1364
+ );
1365
+ }
1366
+ });
1367
+
1368
+ result = result.filter((_, i) => !empty[i]);
1369
+ lineIndex += result.length;
1370
+
1371
+ if (result[0]) {
1372
+ if (fixed && !fixedColumns) {
1373
+ result[0].push(
1374
+ <th key="dummy" rowSpan={result.length} className={CSS.element(baseClass, "col-header")} />,
1375
+ );
1376
+ }
1377
+
1378
+ headerRows.push(...result.map((h, i) => <tr key={`${lineIndex}-${i}`}>{h}</tr>));
1379
+ }
1380
+ });
1381
+
1382
+ if (headerRows.length == 0) return null;
1383
+
1384
+ return (
1385
+ <tbody key={"h" + key} className={CSS.element(baseClass, "header")}>
1386
+ {headerRows}
1387
+ </tbody>
1388
+ );
1389
+ }
1390
+
1391
+ onHeaderMouseMove(e: any, column: any, columnInstance: any, gridInstance: any, headerLine: any) {
1392
+ let { baseClass, CSS } = gridInstance.widget;
1393
+ if (columnInstance.data.fixed) return;
1394
+ let headerInstance = columnInstance.components[`header${headerLine + 1}`];
1395
+ if (!headerInstance) return;
1396
+ let { store, data } = headerInstance;
1397
+ if (headerInstance.widget?.tooltip) {
1398
+ tooltipMouseMove(e, headerInstance, headerInstance.widget.tooltip);
1399
+ }
1400
+ if (data.draggable && !data.fixed && ddDetect(e) && e.buttons == 1) {
1401
+ initiateDragDrop(
1402
+ e,
1403
+ {
1404
+ sourceEl: e.currentTarget,
1405
+ source: {
1406
+ type: "grid-column",
1407
+ store,
1408
+ column,
1409
+ columnInstance,
1410
+ headerInstance,
1411
+ gridInstance,
1412
+ headerLine,
1413
+ },
1414
+ clone: {
1415
+ store: store,
1416
+ matchCursorOffset: true,
1417
+ matchWidth: true,
1418
+ widget: () => <div className={CSS.element(baseClass, "col-header-drag-clone")}>{data.text}</div>,
1419
+ },
1420
+ },
1421
+ () => {},
1422
+ );
1423
+ }
1424
+ }
1425
+
1426
+ onHeaderMouseLeave(e: any, columnInstance: any, headerLine: any) {
1427
+ let headerInstance = columnInstance.components[`header${headerLine + 1}`];
1428
+ if (!headerInstance) return;
1429
+ if (headerInstance.widget?.tooltip) {
1430
+ tooltipMouseLeave(e, headerInstance, headerInstance.widget.tooltip);
1431
+ }
1432
+ }
1433
+
1434
+ onHeaderClick(e: any, column: any, instance: any, headerLine: any) {
1435
+ e.preventDefault();
1436
+ e.stopPropagation();
1437
+
1438
+ let { data } = instance;
1439
+ let header = column.components[`header${headerLine + 1}`];
1440
+
1441
+ let field = column.sortField || column.field;
1442
+ let value = column.sortValue || column.value;
1443
+ let comparer = column.comparer;
1444
+ let sortOptions = column.sortOptions;
1445
+
1446
+ if (header && header.allowSorting && column.sortable && (field || value || data.sortField)) {
1447
+ let direction = column.primarySortDirection ?? "ASC";
1448
+ if (
1449
+ isNonEmptyArray(data.sorters) &&
1450
+ ((!!data.sorters[0].field && data.sorters[0].field == (field || data.sortField)) ||
1451
+ (!!value && data.sorters[0].value == value))
1452
+ ) {
1453
+ if (data.sorters[0].direction == "ASC" && (!this.clearableSort || direction == "ASC")) direction = "DESC";
1454
+ else if (data.sorters[0].direction == "DESC" && (!this.clearableSort || direction == "DESC"))
1455
+ direction = "ASC";
1456
+ else {
1457
+ direction = null;
1458
+ instance.state.disableDefaultSort = true;
1459
+ }
1460
+ }
1461
+
1462
+ let sorters = direction
1463
+ ? [
1464
+ {
1465
+ field,
1466
+ direction,
1467
+ value,
1468
+ comparer,
1469
+ sortOptions,
1470
+ },
1471
+ ]
1472
+ : null;
1473
+
1474
+ if (sorters == null) field = null;
1475
+
1476
+ instance.set("sorters", sorters);
1477
+ instance.set("sortField", field);
1478
+ instance.set("sortDirection", direction);
1479
+
1480
+ if (!this.remoteSort || this.infinite) instance.setState({ sorters });
1481
+ }
1482
+ }
1483
+
1484
+ renderGroupHeader(
1485
+ context: RenderingContext | null,
1486
+ instance: GridInstance,
1487
+ g: any,
1488
+ level: any,
1489
+ group: any,
1490
+ i: any,
1491
+ store: any,
1492
+ fixedColumns: any,
1493
+ ) {
1494
+ let { CSS, baseClass } = this;
1495
+ let data = store.getData();
1496
+ if (g.caption) {
1497
+ let caption = g.caption(data);
1498
+ return (
1499
+ <tbody
1500
+ key={`g-${level}-${group.$key}`}
1501
+ className={CSS.element(baseClass, "group-caption", ["level-" + level])}
1502
+ data-group-key={group.$key}
1503
+ data-group-element={`group-caption-${level}`}
1504
+ >
1505
+ <tr>
1506
+ <td colSpan={1000}>{caption}</td>
1507
+ </tr>
1508
+ </tbody>
1509
+ );
1510
+ } else if (g.showCaption) {
1511
+ let skip = 0;
1512
+
1513
+ let { header } = instance;
1514
+
1515
+ let lines: any[] = [];
1516
+ header.children.forEach((line: any, lineIndex: number) => {
1517
+ let empty = true;
1518
+
1519
+ let cells = line.children.map((ci: any, i: any) => {
1520
+ if (--skip >= 0) return null;
1521
+
1522
+ if (Boolean(ci.data.fixed) != fixedColumns) return null;
1523
+
1524
+ let v,
1525
+ c = ci.widget,
1526
+ colSpan,
1527
+ pad,
1528
+ cls = "",
1529
+ style = null;
1530
+ if (c.caption) {
1531
+ if (c.caption.children)
1532
+ v = <Cx widget={c.caption.children} store={store} parentInstance={instance} subscribe />;
1533
+ else {
1534
+ v = c.caption.value(data);
1535
+ let fmt = c.caption.format(data);
1536
+ if (fmt) v = Format.value(v, fmt);
1537
+ }
1538
+ pad = c.caption.pad;
1539
+ colSpan = c.caption.colSpan;
1540
+ empty = false;
1541
+ cls = CSS.expand(c.caption.class(data)) || "";
1542
+ style = parseStyle(c.caption.style(data));
1543
+ if (c.caption.expand) {
1544
+ colSpan = 1;
1545
+ for (
1546
+ let ind = i + 1;
1547
+ ind < line.children.length &&
1548
+ !line.children[ind].widget.caption &&
1549
+ !line.children[ind].widget.aggregate;
1550
+ ind++
1551
+ )
1552
+ colSpan++;
1553
+ }
1554
+
1555
+ if (colSpan > 1) skip = colSpan - 1;
1556
+ } else if (c.aggregate && c.aggregateAliasGetter && c.caption !== false) {
1557
+ empty = false;
1558
+ v = c.aggregateAliasGetter(group);
1559
+ if (isString(ci.data.format)) v = Format.value(v, ci.data.format);
1560
+ }
1561
+
1562
+ if (cls) cls += " ";
1563
+ if (c.align) cls += CSS.state("aligned-" + c.align);
1564
+
1565
+ if (pad !== false) cls += (cls ? " " : "") + CSS.state("pad");
1566
+
1567
+ return (
1568
+ <td key={i} className={cls} colSpan={colSpan} style={style}>
1569
+ {v}
1570
+ </td>
1571
+ );
1572
+ });
1573
+
1574
+ if (empty) return;
1575
+
1576
+ lines.push(<tr key={lineIndex}>{cells}</tr>);
1577
+ });
1578
+
1579
+ if (lines.length == 0) return null;
1580
+
1581
+ return (
1582
+ <tbody
1583
+ key={"c" + group.$key}
1584
+ className={CSS.element(baseClass, "group-caption", ["level-" + level])}
1585
+ data-group-key={group.$key}
1586
+ data-group-element={`group-caption-${level}`}
1587
+ >
1588
+ {lines}
1589
+ </tbody>
1590
+ );
1591
+ }
1592
+ }
1593
+
1594
+ renderGroupFooter(
1595
+ context: RenderingContext | null,
1596
+ instance: GridInstance,
1597
+ g: any,
1598
+ level: any,
1599
+ group: any,
1600
+ i: any,
1601
+ store: any,
1602
+ fixed: any,
1603
+ fixedColumns: any,
1604
+ ) {
1605
+ let { CSS, baseClass } = this;
1606
+ let data = store.getData();
1607
+ let skip = 0;
1608
+
1609
+ let { header, state } = instance;
1610
+ let rowStyle = {};
1611
+
1612
+ let lines: any[] = [];
1613
+ header.children.forEach((line: any, lineIndex: number) => {
1614
+ let empty = true;
1615
+
1616
+ let cells = line.children.map((ci: any, i: any) => {
1617
+ if (--skip >= 0) return null;
1618
+
1619
+ if (Boolean(ci.data.fixed) != fixedColumns) return null;
1620
+
1621
+ let v,
1622
+ c = ci.widget,
1623
+ colSpan = 1,
1624
+ pad,
1625
+ cls = "",
1626
+ style = null;
1627
+ if (c.footer) {
1628
+ v = c.footer.value(data);
1629
+ let fmt = c.footer.format(data);
1630
+ if (fmt) v = Format.value(v, fmt);
1631
+ pad = c.footer.pad;
1632
+ colSpan = c.footer.colSpan;
1633
+ empty = false;
1634
+ cls = CSS.expand(c.footer.class(data)) || "";
1635
+ style = parseStyle(c.footer.style(data));
1636
+ if (c.footer.expand) {
1637
+ colSpan = 1;
1638
+ for (
1639
+ let ind = i + 1;
1640
+ ind < line.children.length &&
1641
+ !line.children[ind].widget.footer &&
1642
+ !line.children[ind].widget.aggregate;
1643
+ ind++
1644
+ )
1645
+ colSpan++;
1646
+ }
1647
+
1648
+ if (colSpan > 1) skip = colSpan - 1;
1649
+ } else if (c.aggregate && c.aggregateAliasGetter && c.footer !== false) {
1650
+ empty = false;
1651
+ v = c.aggregateAliasGetter(group);
1652
+ if (isString(ci.data.format)) v = Format.value(v, ci.data.format);
1653
+ }
1654
+
1655
+ if (cls) cls += " ";
1656
+ if (c.align) cls += CSS.state("aligned-" + c.align);
1657
+
1658
+ if (pad !== false) cls += (cls ? " " : "") + CSS.state("pad");
1659
+
1660
+ // apply column width to footers too, but only if colSpan == 1,
1661
+ // otherwise set 1px so that the footer is not participating in the layout
1662
+
1663
+ let maxWidth = 1;
1664
+ if (colSpan == 1) maxWidth = state.colWidth[c.uniqueColumnId];
1665
+ style = {
1666
+ ...style,
1667
+ maxWidth,
1668
+ };
1669
+
1670
+ return (
1671
+ <td key={i} className={cls} colSpan={colSpan} style={style}>
1672
+ {v}
1673
+ </td>
1674
+ );
1675
+ });
1676
+
1677
+ if (empty) return;
1678
+
1679
+ if (fixed && !fixedColumns)
1680
+ cells.push(<td key="dummy" className={CSS.element(baseClass, "fixed-footer-corner")} />);
1681
+
1682
+ lines.push(<tr key={lineIndex}>{cells}</tr>);
1683
+ });
1684
+
1685
+ if (lines.length == 0) return null;
1686
+
1687
+ return (
1688
+ <tbody
1689
+ key={"f" + i}
1690
+ style={rowStyle}
1691
+ className={CSS.element(baseClass, "group-footer", ["level-" + level])}
1692
+ data-group-key={group.$key}
1693
+ data-group-element={`group-footer-${level}`}
1694
+ >
1695
+ {lines}
1696
+ </tbody>
1697
+ );
1698
+ }
1699
+
1700
+ renderRows(context: RenderingContext, instance: GridInstance) {
1701
+ let { records, hasFixedColumns } = instance;
1702
+
1703
+ if (!isArray<any>(records)) return null;
1704
+
1705
+ let record, g;
1706
+
1707
+ for (let i = 0; i < records.length; i++) {
1708
+ record = records[i];
1709
+ if (record.type == "data") record.vdom = record.row!.render(context);
1710
+
1711
+ if (record.type == "group-header") {
1712
+ record.vdom = [];
1713
+ record.fixedVdom = [];
1714
+ g = record.grouping;
1715
+ if (g.caption || g.showCaption)
1716
+ record.vdom.push(
1717
+ this.renderGroupHeader(
1718
+ context,
1719
+ instance,
1720
+ g,
1721
+ record.level,
1722
+ record.group,
1723
+ record.key + "-caption",
1724
+ record.store,
1725
+ false,
1726
+ ),
1727
+ );
1728
+
1729
+ if (hasFixedColumns)
1730
+ record.fixedVdom.push(
1731
+ this.renderGroupHeader(
1732
+ context,
1733
+ instance,
1734
+ g,
1735
+ record.level,
1736
+ record.group,
1737
+ record.key + "-caption",
1738
+ record.store,
1739
+ true,
1740
+ ),
1741
+ );
1742
+
1743
+ if (g.showHeader) {
1744
+ record.vdom.push(this.renderHeader(context, instance, record.key + "-header", false, false));
1745
+ if (hasFixedColumns)
1746
+ record.fixedVdom.push(this.renderHeader(context, instance, record.key + "-header", false, true));
1747
+ }
1748
+ }
1749
+
1750
+ if (record.type == "group-footer") {
1751
+ g = record.grouping;
1752
+ if (g.showFooter) {
1753
+ record.vdom = this.renderGroupFooter(
1754
+ context,
1755
+ instance,
1756
+ g,
1757
+ record.level,
1758
+ record.group,
1759
+ record.key + "-footer",
1760
+ record.store,
1761
+ false,
1762
+ false,
1763
+ );
1764
+ if (hasFixedColumns)
1765
+ record.fixedVdom = this.renderGroupFooter(
1766
+ context,
1767
+ instance,
1768
+ g,
1769
+ record.level,
1770
+ record.group,
1771
+ record.key + "-footer",
1772
+ record.store,
1773
+ false,
1774
+ true,
1775
+ );
1776
+ }
1777
+ }
1778
+ }
1779
+ }
1780
+
1781
+ renderFixedFooter(context: RenderingContext, instance: GridInstance) {
1782
+ let { records, hasFixedColumns, data } = instance;
1783
+
1784
+ instance.fixedFooterVDOM = null;
1785
+ instance.fixedColumnsFixedFooterVDOM = null;
1786
+
1787
+ if (data.empty || !isNonEmptyArray(records)) return;
1788
+
1789
+ //all type of records are allowed here because the footer can be based on pre-computed data
1790
+ //it doesn't make sense to show the footer if the grid is empty though
1791
+ let record = records[records.length - 1];
1792
+
1793
+ instance.fixedFooterOverlap = true;
1794
+ instance.fixedFooterIsGroupFooter = record.type == "group-footer";
1795
+
1796
+ instance.fixedFooterVDOM = this.renderGroupFooter(
1797
+ context,
1798
+ instance,
1799
+ record.grouping,
1800
+ record.level || 1,
1801
+ record.group || { $key: "fixed-footer" },
1802
+ record.key + "-footer",
1803
+ record.store,
1804
+ true,
1805
+ false,
1806
+ );
1807
+
1808
+ if (hasFixedColumns)
1809
+ instance.fixedColumnsFixedFooterVDOM = this.renderGroupFooter(
1810
+ context,
1811
+ instance,
1812
+ record.grouping,
1813
+ record.level,
1814
+ record.group || { $key: "fixed-footer" },
1815
+ record.key + "-footer",
1816
+ record.store,
1817
+ true,
1818
+ true,
1819
+ );
1820
+ }
1821
+
1822
+ mapRecords(context: RenderingContext, instance: GridInstance) {
1823
+ let { data, store, dataAdapter } = instance;
1824
+
1825
+ let filter = null;
1826
+ if (this.onCreateFilter) filter = instance.invoke("onCreateFilter", data.filterParams, instance);
1827
+
1828
+ let sorters = !this.remoteSort && data.sorters;
1829
+
1830
+ //apply pre-sorters only if some sorting is applied
1831
+ if (isNonEmptyArray(data.sorters) && isNonEmptyArray(data.preSorters)) {
1832
+ sorters = [...data.preSorters, ...data.sorters];
1833
+ }
1834
+
1835
+ dataAdapter.setFilter(filter);
1836
+ dataAdapter.sort(sorters);
1837
+
1838
+ //if no filtering or sorting applied, let the component maps records on demand
1839
+ if (
1840
+ this.buffered &&
1841
+ !this.fixedFooter &&
1842
+ !filter &&
1843
+ !isNonEmptyArray(sorters) &&
1844
+ !dataAdapter.isTreeAdapter &&
1845
+ !(instance.dataAdapter as any).groupings
1846
+ )
1847
+ return undefined;
1848
+
1849
+ return dataAdapter.getRecords(context, instance, data.records, store);
1850
+ }
1851
+
1852
+ mapRecord(context: RenderingContext, instance: GridInstance, data: any, index: number) {
1853
+ return instance.dataAdapter.mapRecord(context, instance, data, instance.store, this.recordsAccessor, index);
1854
+ }
1855
+ }
1856
+
1857
+ Grid.prototype.baseClass = "grid";
1858
+ Grid.prototype.showHeader = true;
1859
+ Grid.prototype.showFooter = false;
1860
+ Grid.prototype.recordName = "$record";
1861
+ Grid.prototype.indexName = "$index";
1862
+ Grid.prototype.remoteSort = false;
1863
+ Grid.prototype.lockColumnWidths = false;
1864
+ Grid.prototype.lockColumnWidthsRequiredRowCount = 3;
1865
+ Grid.prototype.focused = false;
1866
+ Grid.prototype.emptyText = false;
1867
+ Grid.prototype.showBorder = false; // show border override for material theme
1868
+ Grid.prototype.cached = false;
1869
+ Grid.prototype.buffered = false;
1870
+ Grid.prototype.bufferStep = 15;
1871
+ Grid.prototype.bufferSize = 60;
1872
+ Grid.prototype.pageSize = 100;
1873
+ Grid.prototype.infinite = false;
1874
+ Grid.prototype.styled = true;
1875
+ Grid.prototype.scrollSelectionIntoView = false;
1876
+ Grid.prototype.clearableSort = false;
1877
+ Grid.prototype.cellEditable = false;
1878
+ Grid.prototype.preciseMeasurements = false;
1879
+ Grid.prototype.hoverChannel = "default";
1880
+ Grid.prototype.focusable = null; // automatically resolved
1881
+ Grid.prototype.allowsFileDrops = false;
1882
+ Grid.prototype.preserveGroupOrder = false;
1883
+
1884
+ Widget.alias("grid", Grid);
1885
+ Localization.registerPrototype("cx/widgets/Grid", Grid);
1886
+
1887
+ interface GridComponentProps {
1888
+ instance: GridInstance;
1889
+ data: any;
1890
+ shouldUpdate: boolean | undefined;
1891
+ header?: any;
1892
+ fixedColumnsHeader?: any;
1893
+ fixedColumnsFixedHeader?: any;
1894
+ fixedHeader?: any;
1895
+ fixedFooter?: any;
1896
+ fixedColumnsFixedFooter?: any;
1897
+ children?: any;
1898
+ }
1899
+
1900
+ interface GridComponentState {
1901
+ cursor: number;
1902
+ cursorCellIndex: number;
1903
+ focused: boolean;
1904
+ dropInsertionIndex: number | null;
1905
+ dropNextToTheRowAbove: boolean | null;
1906
+ start: number;
1907
+ end: number;
1908
+ dragged?: any;
1909
+ cellEdit?: any;
1910
+ dropTarget?: any;
1911
+ dropItemHeight?: number;
1912
+ colDropInsertionLeft?: number;
1913
+ colDropInsertionIndex?: number;
1914
+ selectionStart?: number;
1915
+ }
1916
+
1917
+ class GridComponent extends VDOM.Component<GridComponentProps, GridComponentState> {
1918
+ dom: {
1919
+ el?: HTMLElement | null;
1920
+ table?: HTMLElement | null;
1921
+ scroller?: HTMLElement | null;
1922
+ fixedScroller?: HTMLElement | null;
1923
+ fixedTable?: HTMLElement | null;
1924
+ fixedHeader?: HTMLElement | null;
1925
+ fixedColumnsFixedHeader?: HTMLElement | null;
1926
+ fixedFooter?: HTMLElement | null;
1927
+ fixedColumnsFixedFooter?: HTMLElement | null;
1928
+ };
1929
+ syncBuffering: boolean = false;
1930
+ declare start?: number;
1931
+ declare end?: number;
1932
+ declare loadingStartPage?: number;
1933
+ declare loadingEndPage?: number;
1934
+ declare heightStats?: AvgHeight;
1935
+ declare rowHeights?: Record<string, number>;
1936
+ declare rowHeight?: number;
1937
+ scrollerRef: (el: HTMLElement | null) => void;
1938
+ fixedScrollerRef: (el: HTMLElement | null) => void;
1939
+ gridRef: (el: HTMLElement | null) => void;
1940
+ declare cellEditorValid?: boolean;
1941
+ declare scrollWidth: number;
1942
+ declare loading?: boolean;
1943
+ declare loadPageRange?: any;
1944
+ declare prevFetchRecordsState?: any;
1945
+ declare pending?: any;
1946
+ offResize?: () => void;
1947
+ unregisterDropZone?: () => void;
1948
+ declare lastSorters?: any;
1949
+ declare lastScrollFilterParams?: any;
1950
+ declare lastScrollResetParams?: any;
1951
+ declare selectedEl?: Element | null;
1952
+ declare cellEditUndoData?: any;
1953
+
1954
+ constructor(props: GridComponentProps) {
1955
+ super(props);
1956
+ this.dom = {};
1957
+ let { widget } = props.instance;
1958
+
1959
+ let end = Math.min(widget.bufferSize, props.data.totalRecordCount);
1960
+
1961
+ this.state = {
1962
+ cursor: widget.focused && widget.selectable ? 0 : -1,
1963
+ cursorCellIndex: 0,
1964
+ focused: widget.focused,
1965
+ dropInsertionIndex: null,
1966
+ dropNextToTheRowAbove: null,
1967
+ start: 0,
1968
+ end: end,
1969
+ };
1970
+
1971
+ this.syncBuffering = false;
1972
+
1973
+ if (widget.infinite) {
1974
+ this.start = 0;
1975
+ this.end = end;
1976
+ this.loadingStartPage = 0;
1977
+ this.loadingEndPage = 0;
1978
+ }
1979
+
1980
+ this.scrollerRef = (el) => {
1981
+ this.dom.scroller = el;
1982
+ };
1983
+
1984
+ this.fixedScrollerRef = (el) => {
1985
+ this.dom.fixedScroller = el;
1986
+ };
1987
+
1988
+ this.gridRef = (el) => {
1989
+ this.dom.el = el;
1990
+ };
1991
+ }
1992
+
1993
+ getBufferStartEnd(): { start: number; end: number } {
1994
+ return this.syncBuffering ? { start: this.start!, end: this.end! } : this.state;
1995
+ }
1996
+
1997
+ renderCellEditor(key: any, CSS: any, baseClass: any, instance: any, column: any) {
1998
+ //add an inner div with fixed height in order to help IE absolutely position the contents inside
1999
+ let editor = createGridCellEditor(
2000
+ CSS.element(baseClass, "cell-editor-wrap"),
2001
+ this.rowHeight != null && this.rowHeight > 0
2002
+ ? {
2003
+ height: this.rowHeight + 1,
2004
+ }
2005
+ : null,
2006
+ {
2007
+ get: () => this.cellEditorValid ?? false,
2008
+ set: (value: any) => {
2009
+ this.cellEditorValid = value;
2010
+ return true;
2011
+ },
2012
+ },
2013
+ column.editor,
2014
+ );
2015
+ return (
2016
+ <td key={key} className={CSS.element(baseClass, "cell-editor")}>
2017
+ <Cx parentInstance={instance} subscribe widget={editor}></Cx>
2018
+ </td>
2019
+ );
2020
+ }
2021
+
2022
+ createRowRenderer(cellWrap: any) {
2023
+ let { instance, data } = this.props;
2024
+ let { widget, isRecordSelectable, visibleColumns, isRecordDraggable, row } = instance;
2025
+ let { CSS, baseClass } = widget;
2026
+ let { dragSource } = data;
2027
+ let { dragged, cursor, cursorCellIndex, cellEdit, dropInsertionIndex, dropTarget } = this.state;
2028
+ let { colWidth, dimensionsVersion } = instance.state;
2029
+ let { hasMergedCells } = row;
2030
+
2031
+ return (record: MappedGridRecord, index: number, standalone: any, fixed: any) => {
2032
+ let { store, key, row } = record;
2033
+ let isDragged = dragged && (row?.selected || record == dragged);
2034
+ let mod: Record<string, any> = {
2035
+ selected: row?.selected,
2036
+ dragged: isDragged,
2037
+ cursor: widget.selectable && index == cursor,
2038
+ over: dropTarget == "row" && dropInsertionIndex === index,
2039
+ alternate: index % 2 == 1,
2040
+ };
2041
+
2042
+ if (isRecordSelectable) {
2043
+ let selectable = isRecordSelectable(record.data, {});
2044
+ mod["selectable"] = selectable;
2045
+ mod["non-selectable"] = !selectable;
2046
+ }
2047
+
2048
+ let draggable =
2049
+ dragSource &&
2050
+ !isNonEmptyArray((row as any).dragHandles) &&
2051
+ (!isRecordDraggable || isRecordDraggable(record.data));
2052
+ mod["draggable"] = draggable;
2053
+ mod["non-draggable"] = !draggable;
2054
+
2055
+ let wrap = (children: any) => {
2056
+ let skipCells: any = {};
2057
+ return (
2058
+ <GridRowComponent
2059
+ key={key}
2060
+ className={CSS.state(mod)}
2061
+ store={store}
2062
+ dragSource={dragSource}
2063
+ instance={row!}
2064
+ grid={instance}
2065
+ record={record}
2066
+ parent={this}
2067
+ cursorIndex={index}
2068
+ selected={row?.selected}
2069
+ isBeingDragged={dragged}
2070
+ isDraggedOver={mod.over}
2071
+ cursor={mod.cursor}
2072
+ cursorCellIndex={index == cursor && cursorCellIndex}
2073
+ cellEdit={index == cursor && cursorCellIndex != null && cellEdit}
2074
+ shouldUpdate={row?.shouldUpdate}
2075
+ dimensionsVersion={dimensionsVersion}
2076
+ fixed={fixed}
2077
+ useTrTag={hasMergedCells}
2078
+ >
2079
+ {children.content.map(({ key, data, content }: any, line: any) => {
2080
+ let cells = content.map(
2081
+ ({ key, data, content, uniqueColumnId, merged, mergeRowSpan }: any, cellIndex: number) => {
2082
+ if (Boolean(data.fixed) !== fixed) return null;
2083
+ if (merged) return null;
2084
+ let cellected =
2085
+ index == cursor && cellIndex == cursorCellIndex && widget.cellEditable && line == 0;
2086
+ let className = cellected
2087
+ ? CSS.expand(data.classNames, CSS.state("cellected"))
2088
+ : data.classNames;
2089
+ if (cellected && cellEdit) {
2090
+ let column = visibleColumns[cursorCellIndex];
2091
+ if (column && column.editor && data.editable)
2092
+ return this.renderCellEditor(key, CSS, baseClass, row, column);
2093
+ }
2094
+ let width = colWidth[uniqueColumnId];
2095
+ let style = data.style;
2096
+ if (width) {
2097
+ style = {
2098
+ ...style,
2099
+ maxWidth: `${width}px`,
2100
+ };
2101
+ }
2102
+
2103
+ if (skipCells[`${line}-${cellIndex}`]) return null;
2104
+
2105
+ if (data.colSpan > 1 || data.rowSpan > 1) {
2106
+ for (let r = line; r < line + (data.rowSpan ?? 1); r++)
2107
+ for (let c = cellIndex; c < cellIndex + (data.colSpan ?? 1); c++)
2108
+ skipCells[`${r}-${c}`] = true;
2109
+ }
2110
+
2111
+ if (cellWrap) content = cellWrap(content);
2112
+
2113
+ return (
2114
+ <td
2115
+ key={key}
2116
+ className={className}
2117
+ style={style}
2118
+ colSpan={data.colSpan}
2119
+ rowSpan={mergeRowSpan ?? data.rowSpan}
2120
+ >
2121
+ {content}
2122
+ </td>
2123
+ );
2124
+ },
2125
+ );
2126
+ if (hasMergedCells) return cells;
2127
+ return (
2128
+ <tr key={key} className={data.classNames} style={data.style}>
2129
+ {cells}
2130
+ </tr>
2131
+ );
2132
+ })}
2133
+ </GridRowComponent>
2134
+ );
2135
+ };
2136
+
2137
+ if (!standalone) return wrap(record.vdom);
2138
+
2139
+ return (
2140
+ <Cx
2141
+ key={key}
2142
+ instance={record.row}
2143
+ parentInstance={instance}
2144
+ options={{ name: "grid-row" }}
2145
+ contentFactory={(x) =>
2146
+ wrap({
2147
+ content: Array.isArray(x.children) ? x.children : x.children != null ? [x.children] : [],
2148
+ data: {},
2149
+ })
2150
+ }
2151
+ params={{
2152
+ ...mod,
2153
+ dimensionsVersion: dimensionsVersion,
2154
+ cursorIndex: index,
2155
+ data: record.data,
2156
+ cursorCellIndex: index == cursor && cursorCellIndex,
2157
+ cellEdit: index == cursor && cursorCellIndex != null && cellEdit,
2158
+ }}
2159
+ />
2160
+ );
2161
+ };
2162
+ }
2163
+
2164
+ render() {
2165
+ let { instance, data, fixedFooter, fixedColumnsFixedFooter } = this.props;
2166
+ let { widget, hasFixedColumns } = instance;
2167
+ let { CSS, baseClass } = widget;
2168
+ let { start, end } = this.getBufferStartEnd();
2169
+
2170
+ let cellWrap: any = false;
2171
+
2172
+ if (widget.cellEditable && (widget.hasResizableColumns || hasFixedColumns)) {
2173
+ cellWrap = (children: any) => <div className="cxe-grid-cell-clip">{children}</div>;
2174
+ }
2175
+
2176
+ let children: any[] = [],
2177
+ fixedChildren: any[] = [];
2178
+
2179
+ let renderRow = this.createRowRenderer(cellWrap);
2180
+
2181
+ let addRow = (record: any, index: number, standalone?: boolean) => {
2182
+ children.push(renderRow(record, index, standalone, false));
2183
+ if (hasFixedColumns) fixedChildren.push(renderRow(record, index, standalone, true));
2184
+
2185
+ //avoid re-rendering on cursor change
2186
+ record.row.shouldUpdate = false;
2187
+ };
2188
+
2189
+ if (widget.buffered) {
2190
+ let context = new RenderingContext();
2191
+ let dummyDataClass = CSS.element(baseClass, "data", { dummy: true });
2192
+ if (!instance.recordInstanceCache) instance.recordInstanceCache = new InstanceCache(instance);
2193
+ instance.recordInstanceCache.mark();
2194
+ this.getRecordsSlice(start, end).forEach((r: any, i: any) => {
2195
+ if (r == null) {
2196
+ addRow(
2197
+ {
2198
+ key: "dummy-" + start + i,
2199
+ row: {
2200
+ data: { classNames: dummyDataClass },
2201
+ widget: instance.row,
2202
+ },
2203
+ vdom: {
2204
+ content: [
2205
+ {
2206
+ key: 0,
2207
+ data: {},
2208
+ content: [
2209
+ {
2210
+ key: 0,
2211
+ data: {
2212
+ colSpan: 1000,
2213
+ style: {
2214
+ height: `${this.rowHeight}px`,
2215
+ },
2216
+ },
2217
+ },
2218
+ ],
2219
+ },
2220
+ ],
2221
+ },
2222
+ },
2223
+ start + i,
2224
+ );
2225
+ } else {
2226
+ let record = instance.records
2227
+ ? r
2228
+ : widget.mapRecord(context, instance, r, widget.infinite ? start + i - data.offset : start + i);
2229
+ let row = (record.row = instance.recordInstanceCache.getChild(instance.row, record.store, record.key));
2230
+ instance.recordInstanceCache.addChild(row);
2231
+ row.detached = true;
2232
+ row.selected = instance.isSelected(record.data, record.index);
2233
+
2234
+ if (record.type == "data") {
2235
+ addRow(record, start + i, true);
2236
+ } else if (record.type == "group-header") {
2237
+ let g = record.grouping;
2238
+ if (g.caption || g.showCaption) {
2239
+ children.push(
2240
+ widget.renderGroupHeader(
2241
+ null,
2242
+ instance,
2243
+ g,
2244
+ record.level,
2245
+ record.group,
2246
+ record.key + "-caption",
2247
+ record.store,
2248
+ false,
2249
+ ),
2250
+ );
2251
+
2252
+ if (hasFixedColumns)
2253
+ fixedChildren.push(
2254
+ widget.renderGroupHeader(
2255
+ null,
2256
+ instance,
2257
+ g,
2258
+ record.level,
2259
+ record.group,
2260
+ record.key + "-caption",
2261
+ record.store,
2262
+ true,
2263
+ ),
2264
+ );
2265
+ }
2266
+ } else if (record.type == "group-footer") {
2267
+ let g = record.grouping;
2268
+ if (g.showFooter && (!widget.fixedFooter || start + i != instance.records!.length - 1)) {
2269
+ children.push(
2270
+ widget.renderGroupFooter(
2271
+ null,
2272
+ instance,
2273
+ g,
2274
+ record.level,
2275
+ record.group,
2276
+ record.key + "-footer",
2277
+ record.store,
2278
+ false,
2279
+ false,
2280
+ ),
2281
+ );
2282
+
2283
+ if (hasFixedColumns)
2284
+ fixedChildren.push(
2285
+ widget.renderGroupFooter(
2286
+ null,
2287
+ instance,
2288
+ g,
2289
+ record.level,
2290
+ record.group,
2291
+ record.key + "-footer",
2292
+ record.store,
2293
+ false,
2294
+ true,
2295
+ ),
2296
+ );
2297
+ }
2298
+ }
2299
+ }
2300
+ });
2301
+ instance.recordInstanceCache.sweep();
2302
+ } else {
2303
+ let { row } = instance;
2304
+ let { hasMergedCells, mergedColumns } = row;
2305
+ if (hasMergedCells) {
2306
+ // merge adjacent cells with the same value in columns that are marked as merged
2307
+ let rowSpan: Record<string, any> = {};
2308
+ let getCellRenderInfo = (vdom: any, cellIndex: number) => vdom.content[0]?.content[cellIndex];
2309
+ for (let index = instance.records!.length - 1; index >= 0; index--) {
2310
+ let row = instance.records![index];
2311
+ let prevRow = instance.records![index - 1];
2312
+ if (row.type == "data") {
2313
+ let stopMerge = false;
2314
+ for (let mi = 0; mi < mergedColumns.length; mi++) {
2315
+ let mergedCol = mergedColumns[mi];
2316
+ let cellInfo = getCellRenderInfo(row.vdom, mergedCol.index);
2317
+ cellInfo.merged = false;
2318
+ delete cellInfo.mergeRowSpan;
2319
+ if (prevRow?.type == "data") {
2320
+ let shouldMerge = false;
2321
+ switch (mergedCol.mode) {
2322
+ case "always":
2323
+ shouldMerge = true;
2324
+ break;
2325
+ case "same-value":
2326
+ let prevCellInfo = getCellRenderInfo(prevRow.vdom, mergedCol.index);
2327
+ shouldMerge = !stopMerge && cellInfo.data.value === prevCellInfo.data.value;
2328
+ break;
2329
+ }
2330
+
2331
+ if (shouldMerge) {
2332
+ cellInfo.merged = true;
2333
+ rowSpan[mergedCol.uniqueColumnId] = (rowSpan[mergedCol.uniqueColumnId] ?? 1) + 1;
2334
+ } else {
2335
+ if (mergedCol.mode == "same-value") stopMerge = true;
2336
+ }
2337
+ }
2338
+ if (!cellInfo.merged && rowSpan[mergedCol.uniqueColumnId] > 1) {
2339
+ cellInfo.mergeRowSpan = rowSpan[mergedCol.uniqueColumnId];
2340
+ rowSpan[mergedCol.uniqueColumnId] = 1;
2341
+ }
2342
+ }
2343
+ } else rowSpan = {};
2344
+ }
2345
+ }
2346
+
2347
+ instance.records!.forEach((record, i) => {
2348
+ if (record.type == "data") addRow(record, i, false);
2349
+ else {
2350
+ children.push(record.vdom);
2351
+ if (hasFixedColumns) fixedChildren.push(record.fixedVdom);
2352
+ }
2353
+ });
2354
+ }
2355
+
2356
+ if (this.state.dropTarget == "grid" && this.state.dropInsertionIndex != null) {
2357
+ let dragInsertionRow = (
2358
+ <tbody key="dropzone">
2359
+ <tr>
2360
+ <td
2361
+ className={CSS.element(baseClass, "dropzone")}
2362
+ colSpan={1000}
2363
+ style={{
2364
+ height: data.dropMode == "insertion" ? 0 : this.state.dropItemHeight,
2365
+ }}
2366
+ />
2367
+ </tr>
2368
+ </tbody>
2369
+ );
2370
+
2371
+ let dataRecordClass = CSS.element(baseClass, "data");
2372
+
2373
+ let isDataRecord = widget.buffered
2374
+ ? (item: any) => item?.props?.instance?.data?.class == dataRecordClass
2375
+ : (item: any) => item?.props?.record?.type;
2376
+
2377
+ let index = 0;
2378
+ while (index < children.length && !isDataRecord(children[index])) index++;
2379
+
2380
+ let count = 0;
2381
+ while (index < children.length && count < this.state.dropInsertionIndex) {
2382
+ if (isDataRecord(children[index])) count++;
2383
+ index++;
2384
+ }
2385
+
2386
+ let savedIndexPos = index;
2387
+
2388
+ if (!this.state.dropNextToTheRowAbove)
2389
+ while (index < children.length && !isDataRecord(children[index])) index++;
2390
+
2391
+ // do not allow insertion after the last group footer
2392
+ if (savedIndexPos < index && index == children.length) index = savedIndexPos;
2393
+
2394
+ children.splice(index, 0, dragInsertionRow);
2395
+ }
2396
+
2397
+ let content = [],
2398
+ fixedColumnsContent = [];
2399
+
2400
+ //instance.records holds the record count after filtering
2401
+ if (data.emptyText && data.empty) {
2402
+ children = [
2403
+ <tbody key="empty" className={CSS.element(baseClass, "empty-text")}>
2404
+ <tr>
2405
+ <td colSpan={1000}>{data.emptyText}</td>
2406
+ </tr>
2407
+ </tbody>,
2408
+ ];
2409
+ } else if (widget.fixedFooter && (widget.buffered || !instance.fixedFooterIsGroupFooter)) {
2410
+ //add fixed footer content for buffered grids
2411
+ if (fixedFooter || fixedColumnsFixedFooter) {
2412
+ children.push(fixedFooter);
2413
+ if (hasFixedColumns) fixedChildren.push(fixedColumnsFixedFooter);
2414
+ }
2415
+ }
2416
+
2417
+ let shouldRenderFixedFooter = widget.scrollable && (fixedFooter || fixedColumnsFixedFooter);
2418
+
2419
+ if (hasFixedColumns) {
2420
+ fixedColumnsContent.push(
2421
+ <div
2422
+ key="fixedscroller"
2423
+ ref={this.fixedScrollerRef}
2424
+ className={CSS.element(baseClass, "fixed-scroll-area", {
2425
+ "fixed-header": !!this.props.header,
2426
+ "fixed-footer": shouldRenderFixedFooter,
2427
+ })}
2428
+ >
2429
+ <div className={CSS.element(baseClass, "fixed-table-wrapper")}>
2430
+ <table
2431
+ ref={(el) => {
2432
+ this.dom.fixedTable = el;
2433
+ }}
2434
+ >
2435
+ {this.props.fixedColumnsHeader}
2436
+ {fixedChildren}
2437
+ </table>
2438
+ </div>
2439
+ </div>,
2440
+ );
2441
+ }
2442
+
2443
+ content.push(
2444
+ <div
2445
+ key="scroller"
2446
+ ref={this.scrollerRef}
2447
+ onScroll={this.onScroll.bind(this)}
2448
+ className={CSS.element(baseClass, "scroll-area", {
2449
+ "fixed-header": !!this.props.header,
2450
+ "fixed-footer": shouldRenderFixedFooter,
2451
+ })}
2452
+ >
2453
+ <div className={CSS.element(baseClass, "table-wrapper")}>
2454
+ <table
2455
+ ref={(el) => {
2456
+ this.dom.table = el;
2457
+ if (this.props.instance.widget.onRef) this.props.instance.invoke("onRef", el, this.props.instance);
2458
+ }}
2459
+ >
2460
+ {this.props.header}
2461
+ {children}
2462
+ </table>
2463
+ </div>
2464
+ </div>,
2465
+ );
2466
+
2467
+ if (this.props.fixedHeader)
2468
+ content.push(
2469
+ <div
2470
+ key="fh"
2471
+ ref={(el) => {
2472
+ this.dom.fixedHeader = el;
2473
+ }}
2474
+ className={CSS.element(baseClass, "fixed-header")}
2475
+ style={{
2476
+ display: this.scrollWidth > 0 ? "block" : "none",
2477
+ }}
2478
+ >
2479
+ <table>{this.props.fixedHeader}</table>
2480
+ </div>,
2481
+ );
2482
+
2483
+ if (this.props.fixedColumnsFixedHeader)
2484
+ fixedColumnsContent.push(
2485
+ <div
2486
+ key="fcfh"
2487
+ ref={(el) => {
2488
+ this.dom.fixedColumnsFixedHeader = el;
2489
+ }}
2490
+ className={CSS.element(baseClass, "fixed-fixed-header")}
2491
+ style={{
2492
+ display: this.scrollWidth > 0 ? "block" : "none",
2493
+ }}
2494
+ >
2495
+ <table>{this.props.fixedColumnsFixedHeader}</table>
2496
+ </div>,
2497
+ );
2498
+
2499
+ if (shouldRenderFixedFooter) {
2500
+ content.push(
2501
+ <div
2502
+ key="ff"
2503
+ ref={(el) => {
2504
+ this.dom.fixedFooter = el;
2505
+ }}
2506
+ className={CSS.element(baseClass, "fixed-footer")}
2507
+ >
2508
+ <table>{fixedFooter}</table>
2509
+ </div>,
2510
+ );
2511
+
2512
+ if (hasFixedColumns)
2513
+ fixedColumnsContent.push(
2514
+ <div
2515
+ key="fcff"
2516
+ ref={(el) => {
2517
+ this.dom.fixedColumnsFixedFooter = el;
2518
+ }}
2519
+ className={CSS.element(baseClass, "fixed-fixed-footer")}
2520
+ >
2521
+ <table>{fixedColumnsFixedFooter}</table>
2522
+ </div>,
2523
+ );
2524
+ }
2525
+
2526
+ let columnInsertionMarker = null;
2527
+ if (this.state.dropTarget == "column") {
2528
+ columnInsertionMarker = (
2529
+ <div
2530
+ className={CSS.element(baseClass, "col-insertion-marker")}
2531
+ style={{
2532
+ left: this.state.colDropInsertionLeft,
2533
+ }}
2534
+ />
2535
+ );
2536
+ }
2537
+
2538
+ return (
2539
+ <div
2540
+ className={data.classNames}
2541
+ style={{ ...data.style, counterReset: `cx-row-number ${start}` }}
2542
+ tabIndex={widget.focusable ? data.tabIndex || 0 : null}
2543
+ ref={this.gridRef}
2544
+ onKeyDown={this.handleKeyDown.bind(this)}
2545
+ onFocus={this.onFocus.bind(this)}
2546
+ onBlur={this.onBlur.bind(this)}
2547
+ onDragEnter={this.onFileDragEnter.bind(this)}
2548
+ onDragOver={this.onFileDragOver.bind(this)}
2549
+ onDragLeave={this.onFileDragLeave.bind(this)}
2550
+ onDrop={this.onFileDrop.bind(this)}
2551
+ >
2552
+ {fixedColumnsContent}
2553
+ {content}
2554
+ {columnInsertionMarker}
2555
+ {this.props.children}
2556
+ </div>
2557
+ );
2558
+ }
2559
+
2560
+ getRecordsSlice(start: number, end: number): MappedGridRecord<any>[] {
2561
+ let { data, instance } = this.props;
2562
+ let { widget } = instance;
2563
+ if (!widget.infinite) {
2564
+ let source = instance.records || data.records;
2565
+ return source.slice(start, end);
2566
+ }
2567
+
2568
+ let { offset, records } = data;
2569
+ let result = [];
2570
+ for (let i = start; i < Math.min(end, data.totalRecordCount); i++) {
2571
+ if (i >= offset && i < offset + records.length) result.push(records[i - offset]);
2572
+ else result.push(null);
2573
+ }
2574
+
2575
+ return result;
2576
+ }
2577
+
2578
+ ensureData(visibleStart: number, visibleEnd: number) {
2579
+ if (this.loading) return;
2580
+
2581
+ let { instance } = this.props;
2582
+ let { widget } = instance;
2583
+ let { pageSize } = widget;
2584
+
2585
+ let startPage = Math.trunc(visibleStart / pageSize) + 1,
2586
+ endPage = Math.trunc((visibleEnd - 1) / pageSize) + 1;
2587
+
2588
+ //debouncing restricts excessive page loading on fast scrolling as rendering data is
2589
+ //useless because visible region is scrolled away before data appears
2590
+ //the user should spent some time on the page before loading it
2591
+
2592
+ if (!this.loadPageRange)
2593
+ this.loadPageRange = debounce((startPage, endPage) => {
2594
+ let { data } = this.props;
2595
+ let { records, offset } = data;
2596
+ let promises = [];
2597
+
2598
+ for (let page = startPage; page <= endPage; page++) {
2599
+ let s = (page - 1) * pageSize,
2600
+ e = s + pageSize;
2601
+ if (s >= offset && e <= offset + records.length) {
2602
+ promises.push(Promise.resolve(records.slice(s - offset, e - offset)));
2603
+ } else {
2604
+ let result = instance.invoke(
2605
+ "onFetchRecords",
2606
+ {
2607
+ page,
2608
+ pageSize,
2609
+ sorters: data.sorters,
2610
+ sortField: data.sortField,
2611
+ sortDirection: data.sortDirection,
2612
+ filterParams: data.filterParams,
2613
+ state: this.prevFetchRecordsState,
2614
+ },
2615
+ instance,
2616
+ );
2617
+ promises.push(Promise.resolve(result));
2618
+ }
2619
+ }
2620
+
2621
+ this.loading = true;
2622
+
2623
+ Promise.all(promises)
2624
+ .then((pageRecords) => {
2625
+ this.loading = false;
2626
+ let records: any[] = [];
2627
+ let totalRecordCount: number | undefined;
2628
+ let lastPage: boolean | undefined;
2629
+
2630
+ pageRecords.forEach((page) => {
2631
+ if (Array.isArray(page)) {
2632
+ records.push(...page);
2633
+ } else {
2634
+ if (!Array.isArray(page.records))
2635
+ throw new Error(
2636
+ "onFetchRecords should return an array of records or an object with results inside records property.",
2637
+ );
2638
+ totalRecordCount = page.totalRecordCount;
2639
+ lastPage = page.lastPage;
2640
+ this.prevFetchRecordsState = page.state;
2641
+ records.push(...page.records);
2642
+ }
2643
+ });
2644
+
2645
+ let { data } = this.props;
2646
+
2647
+ if (!isNumber(totalRecordCount)) {
2648
+ totalRecordCount = (startPage - 1) * pageSize + records.length;
2649
+ if (!lastPage && records.length == (endPage - startPage + 1) * pageSize) totalRecordCount++;
2650
+ if (data.totalRecordCount > totalRecordCount) totalRecordCount = data.totalRecordCount;
2651
+ }
2652
+
2653
+ instance.buffer.totalRecordCount = data.totalRecordCount = totalRecordCount;
2654
+ instance.buffer.records = data.records = records;
2655
+ instance.buffer.page = data.page = startPage;
2656
+ data.offset = (startPage - 1) * pageSize;
2657
+
2658
+ instance.store.silently(() => {
2659
+ instance.set("records", records);
2660
+ instance.set("page", startPage);
2661
+ instance.set("totalRecordCount", totalRecordCount);
2662
+ });
2663
+
2664
+ let stateChanges: any = {
2665
+ startPage,
2666
+ endPage,
2667
+ };
2668
+
2669
+ if (this.state.end == 0) stateChanges.end = Math.min(widget.bufferSize!, totalRecordCount!);
2670
+
2671
+ this.setState(stateChanges, () => {
2672
+ this.loadingStartPage = startPage;
2673
+ this.loadingEndPage = endPage;
2674
+ this.onScroll();
2675
+ });
2676
+ })
2677
+ .catch((error) => {
2678
+ this.loading = false;
2679
+ if (widget.onLoadingError) instance.invoke(error, "onLoadingError", instance);
2680
+ });
2681
+ }, 30);
2682
+
2683
+ if (startPage < this.loadingStartPage! || endPage > this.loadingEndPage!) {
2684
+ this.loadingStartPage = startPage;
2685
+ this.loadingEndPage = endPage;
2686
+ this.loadPageRange(startPage, endPage);
2687
+ }
2688
+ }
2689
+
2690
+ onScroll() {
2691
+ //check if unmounted
2692
+ if (!this.dom.scroller!) return;
2693
+
2694
+ if (this.dom.fixedHeader!) {
2695
+ this.dom.fixedHeader!.scrollLeft = this.dom.scroller!.scrollLeft;
2696
+ }
2697
+
2698
+ if (this.dom.fixedFooter!) {
2699
+ this.dom.fixedFooter!.scrollLeft = this.dom.scroller!.scrollLeft;
2700
+ }
2701
+
2702
+ if (this.dom.fixedScroller!) {
2703
+ this.dom.fixedScroller!.scrollTop = this.dom.scroller!.scrollTop;
2704
+ }
2705
+
2706
+ let { instance, data } = this.props;
2707
+ let { widget } = instance;
2708
+ if (widget.buffered && !this.pending) {
2709
+ let start = 0;
2710
+ if (widget.measureRowHeights && instance.records)
2711
+ start = Math.max(0, this.estimateStart(instance.records, this.dom.scroller!.scrollTop) - widget.bufferStep);
2712
+ else if (this.rowHeight! > 0)
2713
+ start = Math.round(this.dom.scroller!.scrollTop / this.rowHeight! - widget.bufferStep);
2714
+
2715
+ start = Math.round(start / widget.bufferStep) * widget.bufferStep;
2716
+ start = Math.max(0, Math.min(start, data.totalRecordCount - widget.bufferSize));
2717
+ let end = Math.min(data.totalRecordCount, start + widget.bufferSize);
2718
+
2719
+ if (widget.infinite) {
2720
+ this.ensureData(start, end);
2721
+ }
2722
+
2723
+ if (this.syncBuffering) {
2724
+ this.start = start;
2725
+ this.end = end;
2726
+ } else if (this.state.end != end) {
2727
+ this.pending = true;
2728
+ this.setState({ start, end }, () => {
2729
+ this.pending = false;
2730
+ });
2731
+ }
2732
+ }
2733
+ }
2734
+
2735
+ onFixedColumnsWheel(e: WheelEvent) {
2736
+ this.dom.scroller!.scrollTop += e.deltaY;
2737
+ e.preventDefault();
2738
+ }
2739
+
2740
+ shouldComponentUpdate(props: GridComponentProps, state: GridComponentState) {
2741
+ return props.shouldUpdate !== false || state !== this.state;
2742
+ }
2743
+
2744
+ componentDidMount() {
2745
+ this.componentDidUpdate();
2746
+ let { instance } = this.props;
2747
+ let { widget } = instance;
2748
+ if (widget.scrollable) {
2749
+ //update fixed header/footer on resize
2750
+ this.offResize = ResizeManager.trackElement(this.dom.scroller!, () => {
2751
+ requestAnimationFrame(() => {
2752
+ //ignore changes if the element is not visible on the page
2753
+ if (!this.dom.scroller?.offsetWidth) return;
2754
+ this.componentDidUpdate();
2755
+ instance.setState({
2756
+ dimensionsVersion: instance.state.dimensionsVersion + 1,
2757
+ lockedColWidth: {},
2758
+ });
2759
+ });
2760
+ });
2761
+ }
2762
+ if (widget.pipeKeyDown) instance.invoke("pipeKeyDown", this.handleKeyDown.bind(this), instance);
2763
+ this.unregisterDropZone = registerDropZone(this);
2764
+ if (widget.infinite) this.ensureData(0, 0);
2765
+ if (this.dom.fixedScroller!) {
2766
+ this.onFixedColumnsWheel = this.onFixedColumnsWheel.bind(this);
2767
+ this.dom.fixedScroller!.addEventListener("wheel", this.onFixedColumnsWheel, { passive: false });
2768
+ }
2769
+ }
2770
+
2771
+ onDragStart(e: DragEvent) {
2772
+ let { instance } = this.props;
2773
+ let { widget } = instance;
2774
+ if (widget.onDragStart) instance.invoke("onDragStart", e, instance);
2775
+ }
2776
+
2777
+ onDrop(e: DragEvent) {
2778
+ try {
2779
+ let { instance } = this.props;
2780
+ let { widget } = instance;
2781
+ let { start } = this.getBufferStartEnd();
2782
+ let { dropInsertionIndex, dropTarget, dropNextToTheRowAbove } = this.state;
2783
+ if (dropTarget == "grid" && widget.onDrop && dropInsertionIndex != null) {
2784
+ let gridEvent = e as GridDragEvent<any>;
2785
+ gridEvent.target = {
2786
+ insertionIndex: start + dropInsertionIndex,
2787
+ recordBefore: this.getDataRecordAt(start + dropInsertionIndex - 1),
2788
+ recordAfter: this.getDataRecordAt(start + dropInsertionIndex),
2789
+ totalRecordCount: instance.records!.length,
2790
+ dropNextToTheRowAbove,
2791
+ };
2792
+ instance.invoke("onDrop", gridEvent, instance);
2793
+ } else if (dropTarget == "row") {
2794
+ let rowEvent = e as GridRowDragEvent<any>;
2795
+ rowEvent.target = {
2796
+ index: start + dropInsertionIndex!,
2797
+ record: this.getDataRecordAt(start + dropInsertionIndex!)!,
2798
+ };
2799
+ instance.invoke("onRowDrop", rowEvent, instance);
2800
+ } else if (dropTarget == "column" && widget.onColumnDrop) {
2801
+ let colEvent = e as GridColumnDropEvent;
2802
+ colEvent.target = {
2803
+ index: this.state.colDropInsertionIndex!,
2804
+ grid: widget,
2805
+ instance,
2806
+ };
2807
+ instance.invoke("onColumnDrop", colEvent, instance);
2808
+ }
2809
+ } catch (err) {
2810
+ console.error("Grid drop operation failed. Please fix this error:", err);
2811
+ }
2812
+
2813
+ //in some cases drop operation is not followed by leave
2814
+ this.onDragLeave(e);
2815
+ }
2816
+
2817
+ onDropTest(e: DragEvent) {
2818
+ let { instance } = this.props;
2819
+ let { widget } = instance;
2820
+ let grid = widget.onDropTest && instance.invoke("onDropTest", e, instance);
2821
+ let row = widget.onRowDropTest && instance.invoke("onRowDropTest", e, instance);
2822
+ let column = widget.onColumnDropTest && instance.invoke("onColumnDropTest", e, instance);
2823
+ return (grid || row || column) && { grid, row, column };
2824
+ }
2825
+
2826
+ onDragEnd(e: DragEvent) {
2827
+ this.setState({
2828
+ dropTarget: null,
2829
+ dropInsertionIndex: null,
2830
+ colDropInsertionIndex: undefined,
2831
+ colDropInsertionLeft: undefined,
2832
+ });
2833
+ let { instance } = this.props;
2834
+ let { widget } = instance;
2835
+ if (widget.onDragEnd) instance.invoke("onDragEnd", e, instance);
2836
+ }
2837
+
2838
+ onDragMeasure(e: DragEvent, { test: { grid, row, column } }: any) {
2839
+ //columns can be dropped anywhere, while rows only in the scrollable area
2840
+ let r = getTopLevelBoundingClientRect(column ? this.dom.el! : this.dom.scroller!);
2841
+ let { clientX, clientY } = e.cursor;
2842
+
2843
+ if (clientX < r.left || clientX >= r.right || clientY < r.top || clientY >= r.bottom) return false;
2844
+
2845
+ return {
2846
+ over: 1000,
2847
+ near: false,
2848
+ };
2849
+ }
2850
+
2851
+ onColumnDragOver(ev: DragEvent) {
2852
+ let headerTBody = this.dom.table!.firstChild as HTMLElement;
2853
+ let positions: number[] = [];
2854
+ let bounds: DOMRect;
2855
+
2856
+ let exists: Record<string, boolean> = {};
2857
+
2858
+ for (let r = 0; r < headerTBody!.children.length; r++) {
2859
+ let cells = headerTBody!.children[r].children;
2860
+ for (let c = 0; c < cells.length; c++) {
2861
+ bounds = cells[c].getBoundingClientRect();
2862
+ let key = bounds.left.toFixed(0);
2863
+ if (exists[key]) continue;
2864
+ positions.push(bounds.left);
2865
+ exists[key] = true;
2866
+ }
2867
+ if (r == 0) positions.push(bounds!.right);
2868
+ }
2869
+
2870
+ //due to the order of enumeration it's possible that positions are out of order
2871
+ positions.sort((a, b) => a - b);
2872
+ let index = 0;
2873
+ while (index + 1 < positions.length && ev.cursor.clientX > positions[index + 1]) index++;
2874
+
2875
+ let { fixedColumnCount } = this.props.instance;
2876
+
2877
+ this.setState({
2878
+ colDropInsertionIndex: fixedColumnCount + index,
2879
+ colDropInsertionLeft:
2880
+ positions[index] - positions[0] - this.dom.scroller!.scrollLeft + this.dom.scroller!.offsetLeft,
2881
+ dropTarget: "column",
2882
+ });
2883
+ }
2884
+
2885
+ onDragOver(ev: DragEvent, { test: { grid, row, column } }: GridDropOperationContext) {
2886
+ if (column) this.onColumnDragOver(ev);
2887
+
2888
+ if (!grid && !row) return;
2889
+
2890
+ let { instance } = this.props;
2891
+ let { widget, data } = instance;
2892
+ let { CSS, baseClass } = widget;
2893
+ let rowClass = CSS.element(baseClass, "data");
2894
+ let nodes = Array.from(this.dom.table!.children).filter(
2895
+ (node) => node.className && node.className.indexOf(rowClass) != -1,
2896
+ );
2897
+ let { start } = this.getBufferStartEnd();
2898
+
2899
+ let s = 0,
2900
+ e = nodes.length,
2901
+ m,
2902
+ b;
2903
+ let parentOffset = getParentFrameBoundingClientRect(this.dom.scroller!);
2904
+ let cy = ev.cursor.clientY - parentOffset.top;
2905
+
2906
+ let rowOverIndex = null;
2907
+ let nextToTheRowAbove = false;
2908
+
2909
+ while (s < e) {
2910
+ m = Math.floor((s + e) / 2);
2911
+ b = nodes[m].getBoundingClientRect();
2912
+
2913
+ //dragged items might be invisible and have no client bounds
2914
+ if (b.top == 0 && b.bottom == 0) {
2915
+ //it's important to go all the way in one direction otherwise infinite loop might occur
2916
+ while (m > s && b.top == 0 && b.bottom == 0) {
2917
+ m--;
2918
+ b = nodes[m].getBoundingClientRect();
2919
+ }
2920
+ while (m + 1 < e && b.top == 0 && b.bottom == 0) {
2921
+ m = m + 1;
2922
+ b = nodes[m].getBoundingClientRect();
2923
+ }
2924
+ if (b.top == 0 && b.bottom == 0) {
2925
+ s = e = m;
2926
+ break;
2927
+ }
2928
+ }
2929
+
2930
+ if (cy < b.top) e = m;
2931
+ else if (cy > b.bottom) s = m + 1;
2932
+ else {
2933
+ //hovering over a row here
2934
+ if (row) {
2935
+ let confirmed = !grid;
2936
+ if (!confirmed) {
2937
+ let insertionZone = (b.bottom - b.top) / 4;
2938
+ confirmed = cy > b.top + insertionZone && cy < b.bottom - insertionZone;
2939
+ }
2940
+ if (confirmed) {
2941
+ rowOverIndex = m;
2942
+ break;
2943
+ }
2944
+ }
2945
+
2946
+ if (cy > (b.bottom + b.top) / 2) {
2947
+ s = e = m + 1;
2948
+ nextToTheRowAbove = true;
2949
+ } else s = e = m;
2950
+ }
2951
+ }
2952
+
2953
+ let cancel = false;
2954
+
2955
+ if (rowOverIndex != null) {
2956
+ let evt = {
2957
+ ...ev,
2958
+ target: {
2959
+ record: this.getRecordAt(rowOverIndex),
2960
+ index: start + rowOverIndex,
2961
+ },
2962
+ };
2963
+ if (widget.onRowDragOver && instance.invoke("onRowDragOver", evt, instance) === false) cancel = true;
2964
+ else if (rowOverIndex != this.state.dropInsertionIndex || this.state.dropTarget != "row") {
2965
+ this.setState({
2966
+ dropInsertionIndex: rowOverIndex,
2967
+ dropNextToTheRowAbove: false,
2968
+ dropItemHeight: ev.source.height - 1,
2969
+ dropTarget: "row",
2970
+ });
2971
+ }
2972
+ } else if (grid) {
2973
+ let evt = {
2974
+ ...ev,
2975
+ target: {
2976
+ recordBefore: this.getRecordAt(s - 1),
2977
+ recordAfter: this.getRecordAt(s),
2978
+ insertionIndex: start + s,
2979
+ totalRecordCount: data.totalRecordCount,
2980
+ },
2981
+ };
2982
+ if (widget.onDragOver && instance.invoke("onDragOver", evt, instance) === false) cancel = true;
2983
+ else if (s != this.state.dropInsertionIndex || this.state.dropTarget != "grid") {
2984
+ this.setState({
2985
+ dropInsertionIndex: s,
2986
+ dropNextToTheRowAbove: nextToTheRowAbove,
2987
+ dropItemHeight: ev.source.height - 1,
2988
+ dropTarget: "grid",
2989
+ });
2990
+ }
2991
+ }
2992
+ if (cancel) {
2993
+ this.setState({
2994
+ dropInsertionIndex: null,
2995
+ dropNextToTheRowAbove: null,
2996
+ dropTarget: null,
2997
+ });
2998
+ }
2999
+ }
3000
+
3001
+ onDragLeave(e: DragEvent) {
3002
+ this.setState({
3003
+ dropInsertionIndex: null,
3004
+ dropNextToTheRowAbove: null,
3005
+ dropTarget: null,
3006
+ });
3007
+ }
3008
+
3009
+ onGetHScrollParent() {
3010
+ let { widget } = this.props.instance;
3011
+ if (widget.scrollable) return this.dom.scroller!;
3012
+ return findScrollableParent(this.dom.table!, true);
3013
+ }
3014
+
3015
+ onGetVScrollParent({ test: { grid, row, column } }: GridDropOperationContext) {
3016
+ if (column && !grid && !row) return null;
3017
+ let { widget } = this.props.instance;
3018
+ if (widget.scrollable) return this.dom.scroller!;
3019
+ return findScrollableParent(this.dom.table!);
3020
+ }
3021
+
3022
+ UNSAFE_componentWillReceiveProps(props: GridComponentProps) {
3023
+ let { data, widget } = props.instance;
3024
+ if (this.state.cursor >= data.totalRecordCount)
3025
+ this.setState({
3026
+ cursor: data.totalRecordCount - 1,
3027
+ });
3028
+ else if (widget.selectable && this.state.focused && this.state.cursor < 0)
3029
+ this.setState({
3030
+ cursor: 0,
3031
+ });
3032
+ }
3033
+
3034
+ componentWillUnmount() {
3035
+ let { instance } = this.props;
3036
+ let { widget } = instance;
3037
+ if (this.offResize) this.offResize();
3038
+
3039
+ offFocusOut(this);
3040
+
3041
+ if (this.unregisterDropZone) this.unregisterDropZone();
3042
+
3043
+ if (widget.pipeKeyDown) instance.invoke("pipeKeyDown", null, instance);
3044
+
3045
+ if (this.dom.fixedScroller!) {
3046
+ this.dom.fixedScroller!.removeEventListener("wheel", this.onFixedColumnsWheel);
3047
+ }
3048
+ }
3049
+
3050
+ estimateHeight(
3051
+ records: MappedGridRecord[],
3052
+ start: number,
3053
+ end: number,
3054
+ breakCondition?: (index: number, totalHeight: number) => boolean,
3055
+ ) {
3056
+ let avgDataRowHeight = this.heightStats!.estimate("data") ?? 0;
3057
+ let totalHeight = 0;
3058
+ for (let i = start; i < end; i++) {
3059
+ let record = records[i];
3060
+ switch (record.type) {
3061
+ case "data":
3062
+ if (record.key in this.rowHeights!) totalHeight += this.rowHeights![record.key];
3063
+ else totalHeight += avgDataRowHeight;
3064
+ break;
3065
+
3066
+ case "group-header":
3067
+ if (record.grouping.showCaption) {
3068
+ let captionKey = "group-caption-" + record.level;
3069
+ if (`${captionKey}-${record.group.$key}` in this.rowHeights!)
3070
+ totalHeight += this.rowHeights![`${captionKey}-${record.group.$key}`];
3071
+ else totalHeight += this.heightStats!.estimate(captionKey) ?? avgDataRowHeight;
3072
+ }
3073
+ break;
3074
+
3075
+ case "group-footer":
3076
+ if (record.grouping.showFooter) {
3077
+ let captionKey = "group-footer-" + record.level;
3078
+ if (`${captionKey}-${record.group.$key}` in this.rowHeights!)
3079
+ totalHeight += this.rowHeights![`${captionKey}-${record.group.$key}`];
3080
+ else totalHeight += this.heightStats!.estimate(captionKey) ?? avgDataRowHeight;
3081
+ }
3082
+ break;
3083
+
3084
+ default:
3085
+ Console.warn("UNPROCESSED RECORD TYPE", record);
3086
+ break;
3087
+ }
3088
+
3089
+ if (breakCondition && breakCondition(i, totalHeight) === false) break;
3090
+ }
3091
+ return totalHeight;
3092
+ }
3093
+
3094
+ estimateStart(records: MappedGridRecord[], height: number) {
3095
+ let start = 0;
3096
+ if (height == 0) return 0;
3097
+ this.estimateHeight(records, 0, records.length, (index, h) => {
3098
+ start = index;
3099
+ return h < height;
3100
+ });
3101
+ return start;
3102
+ }
3103
+
3104
+ componentDidUpdate() {
3105
+ let { instance, data } = this.props;
3106
+ let { widget, fixedFooterOverlap } = instance;
3107
+
3108
+ if (
3109
+ widget.lockColumnWidths &&
3110
+ isArray(data.records) &&
3111
+ data.records.length >= widget.lockColumnWidthsRequiredRowCount
3112
+ ) {
3113
+ let headerTBody = this.dom.table!.firstChild! as HTMLElement;
3114
+ for (let r = 0; r < headerTBody.children.length; r++) {
3115
+ let sr = headerTBody.children[r];
3116
+ for (let c = 0; c < sr.children.length; c++) {
3117
+ let cell = sr.children[c] as HTMLElement;
3118
+ cell.style.width =
3119
+ cell.style.minWidth =
3120
+ cell.style.maxWidth =
3121
+ `${(sr.children[c] as HTMLElement).offsetWidth}px`;
3122
+ cell.style.boxSizing = "border-box";
3123
+ if ((cell as HTMLElement).dataset.uniqueColId)
3124
+ instance.state.lockedColWidth[(cell as HTMLElement).dataset.uniqueColId!] = (
3125
+ sr.children[c] as HTMLElement
3126
+ ).offsetWidth;
3127
+ }
3128
+ }
3129
+ }
3130
+
3131
+ if (widget.scrollable) {
3132
+ this.scrollWidth = this.dom.scroller!.offsetWidth - this.dom.scroller!.clientWidth;
3133
+
3134
+ let resized = false,
3135
+ headerHeight = 0,
3136
+ footerHeight = 0,
3137
+ rowHeight = 0;
3138
+
3139
+ if (this.dom.fixedTable!)
3140
+ syncHeaderHeights(
3141
+ this.dom.table!.firstChild as HTMLTableSectionElement,
3142
+ this.dom.fixedTable!.firstChild as HTMLTableSectionElement,
3143
+ );
3144
+
3145
+ if (this.dom.fixedHeader!) {
3146
+ let fixedHeaderTBody = this.dom.fixedHeader!.firstChild!.firstChild as HTMLTableSectionElement;
3147
+
3148
+ resized = widget.preciseMeasurements
3149
+ ? copyCellSizePrecise(this.dom.table!.firstChild as HTMLTableSectionElement, fixedHeaderTBody)
3150
+ : copyCellSize(this.dom.table!.firstChild as HTMLTableSectionElement, fixedHeaderTBody);
3151
+
3152
+ let scrollColumnEl = fixedHeaderTBody?.firstChild?.lastChild as HTMLElement | null;
3153
+ if (scrollColumnEl) scrollColumnEl.style.minWidth = scrollColumnEl.style.maxWidth = this.scrollWidth + "px";
3154
+
3155
+ this.dom.fixedHeader!.style.display = "block";
3156
+ headerHeight = this.dom.fixedHeader!.offsetHeight;
3157
+ this.dom.scroller!.style.marginTop = `${headerHeight}px`;
3158
+ if (this.dom.fixedScroller!) this.dom.fixedScroller!.style.marginTop = `${headerHeight}px`;
3159
+ else if (this.dom.fixedHeader!.style.left != null) this.dom.fixedHeader!.style.removeProperty("left");
3160
+ } else {
3161
+ this.dom.scroller!.style.removeProperty("marginTop");
3162
+ if (this.dom.fixedScroller!) this.dom.fixedScroller!.style.removeProperty("marginTop");
3163
+ }
3164
+
3165
+ if (this.dom.fixedColumnsFixedHeader!) {
3166
+ let fixedColumnsWidth = `${this.dom.fixedScroller!.offsetWidth}px`;
3167
+ this.dom.fixedColumnsFixedHeader!.style.right = "auto";
3168
+ this.dom.fixedColumnsFixedHeader!.style.width = fixedColumnsWidth;
3169
+ if (this.dom.fixedHeader!) this.dom.fixedHeader!.style.left = fixedColumnsWidth;
3170
+
3171
+ this.dom.fixedColumnsFixedHeader!.style.display = "block";
3172
+
3173
+ let fixedHeaderTBody = this.dom.fixedColumnsFixedHeader!.firstElementChild
3174
+ ?.firstElementChild as HTMLTableSectionElement;
3175
+
3176
+ if (this.dom.fixedTable!.firstChild) {
3177
+ resized = copyCellSize(
3178
+ this.dom.fixedTable!.firstElementChild as HTMLTableSectionElement,
3179
+ fixedHeaderTBody,
3180
+ );
3181
+ }
3182
+ }
3183
+
3184
+ if (this.dom.fixedFooter! || this.dom.fixedColumnsFixedFooter!) {
3185
+ if (this.dom.fixedColumnsFixedFooter!) {
3186
+ let fixedColumnsWidth = `${this.dom.fixedScroller!.offsetWidth}px`;
3187
+ this.dom.fixedColumnsFixedFooter!.style.right = "auto";
3188
+ this.dom.fixedColumnsFixedFooter!.style.width = fixedColumnsWidth;
3189
+
3190
+ let dstTableBody = this.dom.fixedColumnsFixedFooter!.firstElementChild
3191
+ ?.firstElementChild as HTMLTableSectionElement;
3192
+ if (dstTableBody) {
3193
+ let srcTableBody = this.dom.fixedTable!.lastElementChild as HTMLTableSectionElement;
3194
+ copyCellSize(srcTableBody, dstTableBody, fixedFooterOverlap);
3195
+ this.dom.fixedColumnsFixedFooter!.style.display = "block";
3196
+ footerHeight = this.dom.fixedFooter!.offsetHeight;
3197
+ }
3198
+ }
3199
+
3200
+ if (this.dom.fixedFooter!) {
3201
+ let dstTableBody = this.dom.fixedFooter!.firstElementChild?.firstElementChild as HTMLTableSectionElement;
3202
+
3203
+ if (dstTableBody) {
3204
+ let srcTableBody = this.dom.table!.lastElementChild as HTMLTableSectionElement;
3205
+
3206
+ copyCellSize(srcTableBody, dstTableBody, fixedFooterOverlap);
3207
+
3208
+ let scrollColumnEl = dstTableBody.firstElementChild?.firstElementChild as HTMLElement;
3209
+ if (scrollColumnEl)
3210
+ scrollColumnEl.style.minWidth = scrollColumnEl.style.maxWidth = this.scrollWidth + "px";
3211
+
3212
+ this.dom.fixedFooter!.style.display = "block";
3213
+ footerHeight = this.dom.fixedFooter!.offsetHeight;
3214
+ }
3215
+
3216
+ if (this.dom.fixedScroller!)
3217
+ this.dom.fixedFooter!.style.left = `${this.dom.fixedScroller!.offsetWidth}px`;
3218
+ else if (this.dom.fixedFooter!.style.left != null) this.dom.fixedFooter!.style.removeProperty("left");
3219
+ }
3220
+
3221
+ this.dom.scroller!.style.marginBottom = `${footerHeight}px`;
3222
+ if (this.dom.fixedScroller!) this.dom.fixedScroller!.style.marginBottom = `${footerHeight}px`;
3223
+ } else {
3224
+ this.dom.scroller!.style.marginBottom = "0";
3225
+ if (this.dom.fixedScroller!) this.dom.fixedScroller!.style.marginBottom = "0";
3226
+ }
3227
+
3228
+ let scrollOverlap = fixedFooterOverlap ? footerHeight : 0;
3229
+
3230
+ if (widget.buffered) {
3231
+ let { start, end } = this.getBufferStartEnd();
3232
+ let remaining = 0,
3233
+ count = Math.min(data.totalRecordCount, end! - start!);
3234
+
3235
+ if (widget.measureRowHeights) {
3236
+ if (!this.rowHeights) this.rowHeights = {};
3237
+ if (!this.heightStats) this.heightStats = new AvgHeight();
3238
+ for (let i = 0; i < this.dom.table!.children.length; i++) {
3239
+ let body = this.dom.table!.children[i] as HTMLElement;
3240
+ if (body.dataset.recordKey != null) {
3241
+ if (!(body.dataset.recordKey in this.rowHeights)) this.heightStats.add("data", body.offsetHeight);
3242
+ this.rowHeights[body.dataset.recordKey] = body.offsetHeight;
3243
+ } else if (body.dataset.groupKey) {
3244
+ let key = body.dataset.groupElement + "-" + body.dataset.groupKey;
3245
+ this.rowHeights[key] = body.offsetHeight;
3246
+ if (!(body.dataset.recordKey! in this.rowHeights))
3247
+ this.heightStats.add(body.dataset.groupElement!, body.offsetHeight);
3248
+ }
3249
+ }
3250
+ }
3251
+
3252
+ if (count > 0) {
3253
+ //do not change row height while a drag-drop operation is in place
3254
+ rowHeight = this.state.dragged
3255
+ ? this.rowHeight!
3256
+ : Math.round((this.dom.table!.offsetHeight - headerHeight) / count);
3257
+ // if (this.rowHeight && this.rowHeight != rowHeight) {
3258
+ // console.warn("ROW-HEIGHT-CHANGE", this.rowHeight, rowHeight);
3259
+ // }
3260
+ remaining = Math.max(0, data.totalRecordCount - end);
3261
+ }
3262
+
3263
+ let upperMargin = 0,
3264
+ lowerMargin = 0;
3265
+ if (widget.measureRowHeights && instance.records) {
3266
+ upperMargin = this.estimateHeight(instance.records, 0, start);
3267
+ lowerMargin = this.estimateHeight(instance.records, end, instance.records.length);
3268
+ } else {
3269
+ upperMargin = start * rowHeight;
3270
+ lowerMargin = remaining * rowHeight;
3271
+ }
3272
+
3273
+ //console.log(upperMargin, start * rowHeight, this.rowHeights, this.heightStats);
3274
+
3275
+ this.dom.table!.style.marginTop = `${(-headerHeight + upperMargin).toFixed(0)}px`;
3276
+ this.dom.table!.style.marginBottom = `${(lowerMargin - scrollOverlap).toFixed(0)}px`;
3277
+ } else {
3278
+ this.dom.table!.style.marginTop = `${-headerHeight}px`;
3279
+ this.dom.table!.style.marginBottom = `${-scrollOverlap}px`;
3280
+ }
3281
+
3282
+ if (this.dom.fixedTable!) {
3283
+ this.dom.fixedTable!.style.marginTop = this.dom.table!.style.marginTop;
3284
+ this.dom.fixedTable!.style.marginBottom = this.dom.table!.style.marginBottom;
3285
+ }
3286
+
3287
+ this.rowHeight = rowHeight;
3288
+
3289
+ let sortersChanged = widget.infinite && !shallowEquals(data.sorters, this.lastSorters);
3290
+
3291
+ if (data.empty && !widget.infinite) {
3292
+ this.dom.scroller!.scrollTop = 0;
3293
+ }
3294
+
3295
+ if (
3296
+ sortersChanged ||
3297
+ data.filterParams !== this.lastScrollFilterParams ||
3298
+ data.scrollResetParams !== this.lastScrollResetParams
3299
+ ) {
3300
+ this.dom.scroller!.scrollTop = 0;
3301
+ this.lastScrollFilterParams = data.filterParams;
3302
+ this.lastScrollResetParams = data.scrollResetParams;
3303
+ this.lastSorters = data.sorters;
3304
+ if (widget.infinite) {
3305
+ this.loadingStartPage = 0;
3306
+ this.loadingEndPage = 0;
3307
+ instance.buffer.records = data.records = [];
3308
+ instance.buffer.totalRecordCount = 0;
3309
+ instance.buffer.page = 1;
3310
+ this.prevFetchRecordsState = null;
3311
+ this.loading = false;
3312
+ }
3313
+ }
3314
+
3315
+ if (widget.scrollSelectionIntoView && !widget.buffered) {
3316
+ let { CSS, baseClass } = widget;
3317
+ let selectedRowSelector = `.${CSS.element(baseClass, "data")}.${CSS.state("selected")}`;
3318
+ let firstSelectedRow = this.dom.table!.querySelector(selectedRowSelector);
3319
+ if (firstSelectedRow != this.selectedEl) {
3320
+ firstSelectedRow && scrollElementIntoView(firstSelectedRow);
3321
+ this.selectedEl = firstSelectedRow;
3322
+ }
3323
+ }
3324
+
3325
+ setTimeout(this.onScroll.bind(this), 0);
3326
+
3327
+ if (resized) instance.fixedHeaderResizeEvent.notify();
3328
+ }
3329
+ }
3330
+
3331
+ moveCursor(
3332
+ index: number,
3333
+ {
3334
+ focused,
3335
+ hover,
3336
+ scrollIntoView,
3337
+ select,
3338
+ selectRange,
3339
+ selectOptions,
3340
+ cellIndex,
3341
+ cellEdit,
3342
+ cancelEdit,
3343
+ }: GridMoveCursorOptions = {},
3344
+ ) {
3345
+ let { widget, visibleColumns } = this.props.instance;
3346
+ if (!widget.selectable && !widget.cellEditable) return;
3347
+
3348
+ let newState: Partial<GridComponentState> = {};
3349
+
3350
+ if (cellEdit != null && cellEdit != this.state.cellEdit) {
3351
+ newState.cellEdit = cellEdit;
3352
+ if (
3353
+ cellEdit &&
3354
+ (!visibleColumns[this.state.cursorCellIndex] || !visibleColumns[this.state.cursorCellIndex].editor)
3355
+ )
3356
+ newState.cellEdit = false;
3357
+ }
3358
+
3359
+ if (cellIndex != null && cellIndex != this.state.cursorCellIndex) {
3360
+ newState.cursorCellIndex = cellIndex;
3361
+ newState.cellEdit = false;
3362
+ }
3363
+
3364
+ if (widget.focused) focused = true;
3365
+
3366
+ if (focused != null && this.state.focused != focused) {
3367
+ newState.focused = focused;
3368
+ newState.cellEdit = false;
3369
+ }
3370
+
3371
+ if (index != this.state.cursor) {
3372
+ newState.cursor = index;
3373
+ newState.cellEdit = false;
3374
+ }
3375
+
3376
+ batchUpdates(() => {
3377
+ if (select) {
3378
+ let start =
3379
+ selectRange && this.state.selectionStart != null && this.state.selectionStart >= 0
3380
+ ? this.state.selectionStart
3381
+ : index;
3382
+ if (start < 0) start = index;
3383
+ this.selectRange(start!, index, selectOptions);
3384
+ if (!selectRange) newState.selectionStart = index;
3385
+ }
3386
+
3387
+ if (Object.keys(newState).length > 0) {
3388
+ let prevState = this.state;
3389
+ let wasCellEditing = prevState.focused && prevState.cellEdit;
3390
+ let futureState = { ...this.state, ...newState };
3391
+
3392
+ if (!futureState.cellEdit && wasCellEditing) {
3393
+ // If cell editing is in progress, moving the cursor may cause that the cell editor to unmount before
3394
+ // the blur event which may cause data loss for components which do not have reactOn=change set, e.g. NumberField.
3395
+ unfocusElement(null, false);
3396
+ let record = this.getRecordAt(prevState.cursor)!;
3397
+ if ((!this.cellEditorValid || cancelEdit) && this.cellEditUndoData)
3398
+ record.store.set(widget.recordName, this.cellEditUndoData);
3399
+ else {
3400
+ let newData = record.store.get(widget.recordName); //record.data might be stale at this point
3401
+ if (widget.onCellEdited && newData != this.cellEditUndoData) {
3402
+ this.props.instance.invoke(
3403
+ "onCellEdited",
3404
+ {
3405
+ column: visibleColumns[prevState.cursorCellIndex],
3406
+ newData,
3407
+ oldData: this.cellEditUndoData,
3408
+ field: visibleColumns[prevState.cursorCellIndex].field,
3409
+ },
3410
+ record,
3411
+ );
3412
+ this.cellEditUndoData = newData;
3413
+ }
3414
+ }
3415
+ }
3416
+
3417
+ if (futureState.cellEdit && !wasCellEditing) {
3418
+ let record = this.getRecordAt(futureState.cursor)!;
3419
+ let cellEditUndoData = record.data;
3420
+
3421
+ if (
3422
+ widget.onBeforeCellEdit &&
3423
+ this.props.instance.invoke(
3424
+ "onBeforeCellEdit",
3425
+ {
3426
+ column: visibleColumns[futureState.cursorCellIndex],
3427
+ data: cellEditUndoData,
3428
+ field: visibleColumns[futureState.cursorCellIndex].field,
3429
+ },
3430
+ record,
3431
+ ) === false
3432
+ )
3433
+ return;
3434
+
3435
+ this.cellEditUndoData = cellEditUndoData;
3436
+ }
3437
+
3438
+ this.setState(newState as any, () => {
3439
+ if (this.state.focused && !this.state.cellEdit && wasCellEditing) FocusManager.focus(this.dom.el!);
3440
+
3441
+ if (scrollIntoView) {
3442
+ let record = this.getRecordAt(index)!;
3443
+
3444
+ let item = record && this.dom.table!.querySelector(`tbody[data-record-key="${record.key}"]`);
3445
+
3446
+ let hscroll = false;
3447
+ if (item) {
3448
+ if (widget.cellEditable)
3449
+ if (this.state.cursorCellIndex >= this.props.instance.fixedColumnCount) {
3450
+ hscroll = true;
3451
+ item = (item.firstChild as HTMLElement)!.children[
3452
+ this.state.cursorCellIndex - this.props.instance.fixedColumnCount
3453
+ ] as Element;
3454
+ } else {
3455
+ let fixedItem = this.dom.fixedTable!.querySelector(`tbody[data-record-key="${record.key}"]`);
3456
+ let cell =
3457
+ fixedItem && (fixedItem.firstChild as HTMLElement)!.children[this.state.cursorCellIndex];
3458
+ if (cell) scrollElementIntoView(cell, false, true, 10);
3459
+ }
3460
+
3461
+ scrollElementIntoView(item!, true, hscroll, widget.cellEditable ? 10 : 0);
3462
+ }
3463
+ }
3464
+ });
3465
+ }
3466
+ });
3467
+ }
3468
+
3469
+ showCursor(focused?: boolean) {
3470
+ let { records, isSelected } = this.props.instance;
3471
+ let cursor = this.state.cursor;
3472
+ if (cursor == -1) {
3473
+ if (records) {
3474
+ cursor = records.findIndex((x) => isSelected(x.data, x.index));
3475
+ //if there are no selected records, find the first data record (skip group header)
3476
+ if (cursor == -1) cursor = records.findIndex((x) => x.type == "data");
3477
+ } else cursor = 0;
3478
+ }
3479
+ this.moveCursor(cursor, { focused: true, scrollIntoView: false });
3480
+ }
3481
+
3482
+ onFocus() {
3483
+ FocusManager.nudge();
3484
+
3485
+ //focus moved within the grid
3486
+ if (this.state.focused) {
3487
+ if (this.state.cellEdit && this.dom.el! == getActiveElement())
3488
+ this.moveCursor(this.state.cursor, {
3489
+ cellEdit: false,
3490
+ });
3491
+ return;
3492
+ }
3493
+
3494
+ let { widget } = this.props.instance;
3495
+
3496
+ //the cursor will be set if focus in originating from a mouse event
3497
+ setTimeout(() => {
3498
+ this.showCursor(true);
3499
+ }, 0);
3500
+
3501
+ if (!widget.focused) {
3502
+ if (this.dom.el!) {
3503
+ //if an inner element is focused first (autoFocus), this.dom.el! might be undefined
3504
+ oneFocusOut(this, this.dom.el!, () => {
3505
+ this.moveCursor(-1, { focused: false });
3506
+ });
3507
+ }
3508
+ }
3509
+
3510
+ this.setState({
3511
+ focused: true,
3512
+ });
3513
+ }
3514
+
3515
+ onBlur() {
3516
+ FocusManager.nudge();
3517
+ }
3518
+
3519
+ selectRange(from: number, to: number, options?: any) {
3520
+ let { instance, data } = this.props;
3521
+ let { records, widget } = instance;
3522
+
3523
+ if (from > to) {
3524
+ let tmp = from;
3525
+ from = to;
3526
+ to = tmp;
3527
+ }
3528
+
3529
+ options = {
3530
+ ...options,
3531
+ range: from < to,
3532
+ };
3533
+
3534
+ let selection = [],
3535
+ indexes = [];
3536
+
3537
+ for (let cursor = from; cursor <= to; cursor++) {
3538
+ let record;
3539
+ if (records) record = records[cursor];
3540
+ else {
3541
+ let offset = widget.infinite ? data.offset : 0;
3542
+ let r = data.records[cursor - offset];
3543
+ if (r) record = widget.mapRecord(null!, instance, r, cursor - offset);
3544
+ }
3545
+ if (record && record.type == "data") {
3546
+ if (instance.isRecordSelectable && !instance.isRecordSelectable(record.data, options)) continue;
3547
+ selection.push(record.data);
3548
+ indexes.push(record.index);
3549
+ }
3550
+ }
3551
+
3552
+ widget.selection.selectMultiple(instance.store, selection, indexes, options);
3553
+ }
3554
+
3555
+ getDataRecordAt(index: number): MappedGridRecord | undefined {
3556
+ let { records } = this.props.instance;
3557
+ if (!records) return this.getRecordAt(index);
3558
+ let dataRecords = records.filter((r) => r.type == "data");
3559
+ return dataRecords[index];
3560
+ }
3561
+
3562
+ getRecordAt(cursor: number): MappedGridRecord | undefined {
3563
+ let { instance, data } = this.props;
3564
+ let { records, widget } = instance;
3565
+
3566
+ if (records) return records[cursor];
3567
+
3568
+ let offset = widget.infinite ? data.offset : 0;
3569
+ let r = data.records[cursor - offset];
3570
+ if (r) return widget.mapRecord(null!, instance, r, cursor - offset);
3571
+
3572
+ return undefined;
3573
+ }
3574
+
3575
+ getRecordInstanceAt(cursor: number) {
3576
+ let record = this.getRecordAt(cursor);
3577
+ if (!record) return null;
3578
+ let { instance } = this.props;
3579
+ if (instance.recordInstanceCache)
3580
+ return instance.recordInstanceCache.getChild(instance.row, record.store, record.key);
3581
+
3582
+ //different signature
3583
+ return instance.getChild(null, instance.row, record.key, record.store);
3584
+ }
3585
+
3586
+ handleKeyDown(e: React.KeyboardEvent) {
3587
+ let { instance, data } = this.props;
3588
+ let { widget } = instance;
3589
+
3590
+ if (widget.onKeyDown && instance.invoke("onKeyDown", e, instance) === false) return;
3591
+
3592
+ let recordInstance = this.getRecordInstanceAt(this.state.cursor);
3593
+ if (recordInstance && widget.onRowKeyDown && instance.invoke("onRowKeyDown", e, recordInstance) === false) return;
3594
+
3595
+ if (widget.onCellKeyDown && widget.cellEditable && this.state.cursorCellIndex != -1) {
3596
+ if (
3597
+ instance.invoke("onCellKeyDown", e, instance, {
3598
+ cellIndex: this.state.cursorCellIndex,
3599
+ record: recordInstance,
3600
+ }) === false
3601
+ )
3602
+ return;
3603
+ }
3604
+
3605
+ switch (e.keyCode) {
3606
+ case KeyCode.enter:
3607
+ this.moveCursor(this.state.cursor, {
3608
+ select: true,
3609
+ selectOptions: {
3610
+ toggle: e.ctrlKey && !e.shiftKey,
3611
+ add: e.ctrlKey && e.shiftKey,
3612
+ },
3613
+ selectRange: e.shiftKey,
3614
+ cellEdit: widget.cellEditable && !this.state.cellEdit,
3615
+ focused: true,
3616
+ });
3617
+ e.stopPropagation();
3618
+ e.preventDefault();
3619
+ break;
3620
+
3621
+ case KeyCode.esc:
3622
+ if (this.state.cellEdit) {
3623
+ this.moveCursor(this.state.cursor, {
3624
+ cellEdit: false,
3625
+ focused: true,
3626
+ cancelEdit: true,
3627
+ });
3628
+ e.stopPropagation();
3629
+ e.preventDefault();
3630
+ }
3631
+ break;
3632
+
3633
+ case KeyCode.tab:
3634
+ if (widget.cellEditable) {
3635
+ e.stopPropagation();
3636
+ e.preventDefault();
3637
+ let direction = e.shiftKey ? -1 : +1;
3638
+ let cursor = this.state.cursor;
3639
+ let cellIndex = (this.state.cursorCellIndex + direction) % instance.row.line1.columns.length;
3640
+ if (cellIndex == -1) {
3641
+ cellIndex += instance.row.line1.columns.length;
3642
+ cursor--;
3643
+ } else if (cellIndex == 0 && direction > 0) cursor++;
3644
+ for (; ; cursor += direction) {
3645
+ let record = this.getRecordAt(cursor);
3646
+ if (!record) break;
3647
+ if (record.type != "data") continue;
3648
+ this.moveCursor(cursor, {
3649
+ focused: true,
3650
+ cellIndex,
3651
+ scrollIntoView: true,
3652
+ cellEdit: false,
3653
+ });
3654
+ break;
3655
+ }
3656
+ }
3657
+ break;
3658
+
3659
+ case KeyCode.down:
3660
+ for (let cursor = this.state.cursor + 1; ; cursor++) {
3661
+ let record = this.getRecordAt(cursor);
3662
+ if (!record) break;
3663
+ if (record.type != "data") continue;
3664
+ this.moveCursor(cursor, {
3665
+ focused: true,
3666
+ scrollIntoView: true,
3667
+ select: e.shiftKey,
3668
+ selectRange: e.shiftKey,
3669
+ });
3670
+ break;
3671
+ }
3672
+ e.stopPropagation();
3673
+ e.preventDefault();
3674
+ break;
3675
+
3676
+ case KeyCode.up:
3677
+ for (let cursor = this.state.cursor - 1; cursor >= 0; cursor--) {
3678
+ let record = this.getRecordAt(cursor);
3679
+ if (!record) break;
3680
+ if (record.type != "data") continue;
3681
+ this.moveCursor(cursor, {
3682
+ focused: true,
3683
+ scrollIntoView: true,
3684
+ select: e.shiftKey,
3685
+ selectRange: e.shiftKey,
3686
+ });
3687
+ break;
3688
+ }
3689
+ e.stopPropagation();
3690
+ e.preventDefault();
3691
+ break;
3692
+
3693
+ case KeyCode.right:
3694
+ if (widget.cellEditable) {
3695
+ if (this.state.cursorCellIndex + 1 < instance.row.line1.columns.length) {
3696
+ this.moveCursor(this.state.cursor, {
3697
+ focused: true,
3698
+ cellIndex: this.state.cursorCellIndex + 1,
3699
+ scrollIntoView: true,
3700
+ });
3701
+ }
3702
+ e.stopPropagation();
3703
+ e.preventDefault();
3704
+ }
3705
+ break;
3706
+
3707
+ case KeyCode.left:
3708
+ if (widget.cellEditable) {
3709
+ if (this.state.cursorCellIndex > 0) {
3710
+ this.moveCursor(this.state.cursor, {
3711
+ focused: true,
3712
+ cellIndex: this.state.cursorCellIndex - 1,
3713
+ scrollIntoView: true,
3714
+ });
3715
+ }
3716
+ e.stopPropagation();
3717
+ e.preventDefault();
3718
+ }
3719
+ break;
3720
+
3721
+ case KeyCode.a:
3722
+ if (!e.ctrlKey || !widget.selection.multiple) return;
3723
+
3724
+ if (isTextInputElement(e.target as Element)) return;
3725
+
3726
+ this.selectRange(0, data.totalRecordCount);
3727
+
3728
+ e.stopPropagation();
3729
+ e.preventDefault();
3730
+ break;
3731
+ }
3732
+ }
3733
+
3734
+ beginDragDrop(e: React.MouseEvent, record: MappedGridRecord) {
3735
+ let { instance, data } = this.props;
3736
+ let { widget, store } = instance;
3737
+ let { isRecordDraggable } = instance;
3738
+
3739
+ if (isRecordDraggable && !isRecordDraggable(record.data)) return;
3740
+
3741
+ //get a fresh isSelected delegate
3742
+ let isSelected = widget.selection.getIsSelectedDelegate(store);
3743
+
3744
+ let selected: MappedGridRecord[] = [];
3745
+
3746
+ let add = (rec: MappedGridRecord | null, data: any, index: number, force?: boolean) => {
3747
+ if (!data || !(force || isSelected(data, index)) || (isRecordDraggable && !isRecordDraggable(data))) return;
3748
+ let mappedRecord = rec ? { ...rec } : (widget.mapRecord(null!, instance, data, index) as MappedGridRecord);
3749
+ let row = (mappedRecord.row = instance.getDetachedChild(
3750
+ instance.row,
3751
+ "DD:" + mappedRecord.key,
3752
+ mappedRecord.store,
3753
+ ) as GridRowInstance);
3754
+ row.selected = true;
3755
+ selected.push(mappedRecord);
3756
+ };
3757
+
3758
+ if (!record.row?.selected) {
3759
+ if (instance.records) instance.records.forEach((r) => add(r, r.data, r.index!));
3760
+ else this.getRecordsSlice(0, data.totalRecordCount).forEach((r, index) => add(null, r, index));
3761
+ }
3762
+
3763
+ if (selected.length == 0) add(record, record.data, record.index!, true);
3764
+
3765
+ let renderRow = this.createRowRenderer(false);
3766
+
3767
+ let contents = selected.map((record, i) => ({
3768
+ type: StaticText,
3769
+ text: renderRow(record, i, true, false),
3770
+ }));
3771
+
3772
+ initiateDragDrop(
3773
+ e,
3774
+ {
3775
+ sourceEl: closest(e.currentTarget, (a) => a.tagName == "TBODY"),
3776
+ source: {
3777
+ data: data.dragSource.data,
3778
+ store: store,
3779
+ record: record,
3780
+ records: selected,
3781
+ },
3782
+ clone: {
3783
+ store: record.store,
3784
+ matchCursorOffset: true,
3785
+ matchWidth: true,
3786
+ widget: {
3787
+ type: HtmlElement,
3788
+ tag: "div",
3789
+ className: data.classNames,
3790
+ children: [
3791
+ {
3792
+ type: HtmlElement,
3793
+ tag: "table",
3794
+ children: contents,
3795
+ },
3796
+ ],
3797
+ },
3798
+ },
3799
+ },
3800
+ () => {
3801
+ this.setState({
3802
+ dragged: false,
3803
+ });
3804
+ },
3805
+ );
3806
+
3807
+ this.setState({
3808
+ dragged: record,
3809
+ });
3810
+ }
3811
+
3812
+ onFileDragEnter(ev: React.DragEvent) {
3813
+ if (!this.props.instance.widget.allowsFileDrops) return;
3814
+ let event = getDragDropEvent(ev, this.props.instance.store, "dragmove");
3815
+ var test = this.onDropTest(event);
3816
+ if (test) {
3817
+ ev.preventDefault();
3818
+ ev.stopPropagation();
3819
+ this.onDragStart(event);
3820
+ }
3821
+ }
3822
+ onFileDragOver(ev: React.DragEvent) {
3823
+ if (!this.props.instance.widget.allowsFileDrops) return;
3824
+ let event = getDragDropEvent(ev, this.props.instance.store, "dragmove");
3825
+ var test = this.onDropTest(event);
3826
+ if (test) {
3827
+ ev.preventDefault();
3828
+ ev.stopPropagation();
3829
+ this.onDragOver(event, { test });
3830
+ }
3831
+ }
3832
+ onFileDragLeave(ev: React.DragEvent) {
3833
+ if (!this.props.instance.widget.allowsFileDrops) return;
3834
+ if (ev.target != this.dom.el!) {
3835
+ //The dragleave event fires when the cursor leave any of the child elements.
3836
+ //We need to be sure that the cursor left the top element too.
3837
+ let el = document.elementFromPoint(ev.clientX, ev.clientY);
3838
+ if (el == this.dom.el! || this.dom.el!.contains(el)) return;
3839
+ }
3840
+ let event = getDragDropEvent(ev, this.props.instance.store, "dragmove");
3841
+ var test = this.onDropTest(event);
3842
+ if (test) {
3843
+ this.onDragLeave(event);
3844
+ }
3845
+ }
3846
+ onFileDrop(ev: React.DragEvent) {
3847
+ if (!this.props.instance.widget.allowsFileDrops) return;
3848
+ let event = getDragDropEvent(ev, this.props.instance.store, "dragdrop");
3849
+ var test = this.onDropTest(event);
3850
+ if (test) {
3851
+ ev.preventDefault();
3852
+ ev.stopPropagation();
3853
+ this.onDrop(event);
3854
+ }
3855
+ }
3856
+ }
3857
+
3858
+ export interface GridColumnHeaderLineConfig extends PureContainerConfig {
3859
+ columns?: GridColumnConfig[];
3860
+ showHeader?: BooleanProp;
3861
+ headerStyle?: StyleProp;
3862
+ headerClass?: ClassProp;
3863
+ }
3864
+
3865
+ class GridColumnHeaderLine extends PureContainerBase<GridColumnHeaderLineConfig> {
3866
+ declare columns?: GridColumnConfig[];
3867
+ declare showHeader: boolean;
3868
+ declare headerStyle?: any;
3869
+ declare headerClass?: any;
3870
+ declare className?: any;
3871
+ declare class?: any;
3872
+ declare isPureContainer: boolean;
3873
+ declare styled: boolean;
3874
+
3875
+ declareData() {
3876
+ return super.declareData(...arguments, {
3877
+ showHeader: undefined,
3878
+ });
3879
+ }
3880
+
3881
+ init() {
3882
+ this.items = Widget.create(GridColumnHeader, this.columns || []) as any;
3883
+ this.visible = this.showHeader;
3884
+ this.style = this.headerStyle;
3885
+ this.className = this.headerClass;
3886
+ this.class = null;
3887
+ super.init();
3888
+ }
3889
+
3890
+ render(context: RenderingContext, instance: Instance, key: string) {
3891
+ let { data } = instance;
3892
+ return (
3893
+ <tr key={key} className={data.classNames} style={data.style}>
3894
+ {this.renderChildren(context, instance)}
3895
+ </tr>
3896
+ );
3897
+ }
3898
+ }
3899
+
3900
+ GridColumnHeaderLine.prototype.isPureContainer = false;
3901
+ GridColumnHeaderLine.prototype.styled = true;
3902
+ GridColumnHeaderLine.prototype.showHeader = true;
3903
+ GridColumnHeaderLine.autoInit = true;
3904
+
3905
+ export interface GridColumnHeaderConfig extends WidgetConfig {
3906
+ format?: StringProp;
3907
+ width?: NumberProp;
3908
+ defaultWidth?: NumberProp;
3909
+ fixed?: BooleanProp;
3910
+ field?: string;
3911
+ sortable?: boolean;
3912
+ resizable?: boolean;
3913
+ draggable?: boolean;
3914
+ header?: StringProp | GridColumnHeaderConfig;
3915
+ header1?: StringProp | GridColumnHeaderConfig;
3916
+ header2?: StringProp | GridColumnHeaderConfig;
3917
+ header3?: StringProp | GridColumnHeaderConfig;
3918
+ footer?: any;
3919
+ caption?: any;
3920
+ aggregateField?: string;
3921
+ aggregateAlias?: string;
3922
+ pad?: boolean;
3923
+ colSpan?: NumberProp;
3924
+ }
3925
+
3926
+ class GridColumnHeader extends Widget<GridColumnHeaderConfig> {
3927
+ declare format?: any;
3928
+ declare width?: any;
3929
+ declare defaultWidth?: any;
3930
+ declare fixed?: any;
3931
+ declare field?: string;
3932
+ declare sortable?: boolean;
3933
+ declare resizable?: boolean;
3934
+ declare draggable?: boolean;
3935
+ declare header?: any;
3936
+ declare header1?: any;
3937
+ declare header2?: any;
3938
+ declare header3?: any;
3939
+ declare footer?: any;
3940
+ declare caption?: any;
3941
+ declare aggregateField?: string;
3942
+ declare aggregateAlias?: string;
3943
+ declare aggregateAliasGetter?: any;
3944
+ declare pad?: boolean;
3945
+ declare colSpan?: any;
3946
+ declare style?: any;
3947
+ declare className?: any;
3948
+ declare class?: any;
3949
+ declareData() {
3950
+ return super.declareData(...arguments, {
3951
+ format: undefined,
3952
+ width: undefined,
3953
+ defaultWidth: undefined,
3954
+ fixed: undefined,
3955
+ });
3956
+ }
3957
+
3958
+ init() {
3959
+ delete this.style;
3960
+ delete this.className;
3961
+ delete this.class;
3962
+
3963
+ if (this.header) this.header1 = this.header;
3964
+
3965
+ if (this.header1 || this.resizable || this.width || this.defaultWidth || this.sortable || this.draggable) {
3966
+ if (!isObject(this.header1))
3967
+ this.header1 = {
3968
+ text: this.header1 || "",
3969
+ };
3970
+
3971
+ if (this.resizable) this.header1.resizable = this.resizable;
3972
+
3973
+ if (this.width) this.header1.width = this.width;
3974
+
3975
+ if (this.defaultWidth) this.header1.defaultWidth = this.defaultWidth;
3976
+
3977
+ if (this.draggable) this.header1.draggable = this.draggable;
3978
+ }
3979
+
3980
+ if (this.header2 && isSelector(this.header2))
3981
+ this.header2 = {
3982
+ text: this.header2,
3983
+ };
3984
+
3985
+ if (this.header3 && isSelector(this.header3))
3986
+ this.header3 = {
3987
+ text: this.header3,
3988
+ };
3989
+
3990
+ if (!this.aggregateField && this.field) this.aggregateField = this.field;
3991
+
3992
+ if (!this.aggregateAlias) this.aggregateAlias = this.aggregateField;
3993
+ if (this.aggregateAlias) this.aggregateAliasGetter = Binding.get(this.aggregateAlias).value;
3994
+
3995
+ if (this.footer && isSelector(this.footer))
3996
+ this.footer = {
3997
+ value: this.footer,
3998
+ pad: this.pad,
3999
+ colSpan: this.colSpan,
4000
+ };
4001
+
4002
+ if (this.footer) {
4003
+ this.footer.value = getSelector(this.footer.value);
4004
+ this.footer.class = getSelector(this.footer.class);
4005
+ this.footer.style = getSelector(this.footer.style);
4006
+ this.footer.format = getSelector(this.footer.format);
4007
+ }
4008
+
4009
+ if (this.caption && isSelector(this.caption))
4010
+ this.caption = {
4011
+ value: this.caption,
4012
+ pad: this.pad,
4013
+ format: this.format,
4014
+ };
4015
+
4016
+ if (this.caption) {
4017
+ let children = this.caption.children || this.caption.items;
4018
+ if (children) {
4019
+ delete this.caption.items;
4020
+ this.caption.children = Widget.create(children);
4021
+ } else {
4022
+ this.caption.value = getSelector(this.caption.value);
4023
+ this.caption.format = getSelector(this.caption.format);
4024
+ }
4025
+ this.caption.class = getSelector(this.caption.class);
4026
+ this.caption.style = getSelector(this.caption.style);
4027
+ }
4028
+
4029
+ super.init();
4030
+ }
4031
+
4032
+ initComponents() {
4033
+ return super.initComponents({
4034
+ header1: this.header1 && GridColumnHeaderCell.create(this.header1),
4035
+ header2: this.header2 && GridColumnHeaderCell.create(this.header2),
4036
+ header3: this.header3 && GridColumnHeaderCell.create(this.header3),
4037
+ });
4038
+ }
4039
+
4040
+ render() {
4041
+ return null;
4042
+ }
4043
+ }
4044
+
4045
+ GridColumnHeader.autoInit = true;
4046
+
4047
+ export interface GridColumnHeaderCellConfig extends PureContainerConfig {
4048
+ text?: StringProp;
4049
+ colSpan?: NumberProp;
4050
+ rowSpan?: NumberProp;
4051
+ width?: NumberProp;
4052
+ defaultWidth?: NumberProp;
4053
+ resizable?: BooleanProp;
4054
+ fixed?: BooleanProp;
4055
+ draggable?: BooleanProp;
4056
+ tool?: any;
4057
+ allowSorting?: boolean;
4058
+ }
4059
+
4060
+ class GridColumnHeaderCell extends PureContainerBase<GridColumnHeaderCellConfig> {
4061
+ declare text?: any;
4062
+ declare colSpan?: any;
4063
+ declare rowSpan?: any;
4064
+ declare width?: any;
4065
+ declare defaultWidth?: any;
4066
+ declare resizable?: any;
4067
+ declare fixed?: any;
4068
+ declare draggable?: any;
4069
+ declare tool?: any;
4070
+ declare allowSorting?: boolean;
4071
+
4072
+ declareData() {
4073
+ return super.declareData(...arguments, {
4074
+ text: undefined,
4075
+ colSpan: undefined,
4076
+ rowSpan: undefined,
4077
+ width: undefined,
4078
+ defaultWidth: undefined,
4079
+ resizable: undefined,
4080
+ fixed: undefined,
4081
+ draggable: undefined,
4082
+ });
4083
+ }
4084
+
4085
+ initComponents() {
4086
+ return super.initComponents(...arguments, {
4087
+ tool: this.tool && Widget.create(this.tool),
4088
+ });
4089
+ }
4090
+
4091
+ render(context: RenderingContext, instance: Instance, key: string) {
4092
+ let { data } = instance;
4093
+ return data.text || super.render(context, instance, key);
4094
+ }
4095
+ }
4096
+
4097
+ GridColumnHeaderCell.prototype.colSpan = 1;
4098
+ GridColumnHeaderCell.prototype.rowSpan = 1;
4099
+ GridColumnHeaderCell.prototype.allowSorting = true;
4100
+ GridColumnHeaderCell.prototype.styled = true;
4101
+ GridColumnHeaderCell.prototype.fixed = false;
4102
+
4103
+ // function initGrouping(grouping) {
4104
+ // grouping.forEach((g) => {
4105
+ // if (g.caption) g.caption = getSelector(g.caption);
4106
+ // });
4107
+ // }
4108
+
4109
+ function copyCellSize(
4110
+ srcTableBody: HTMLTableSectionElement,
4111
+ dstTableBody: HTMLTableSectionElement,
4112
+ applyHeight = true,
4113
+ ) {
4114
+ if (!srcTableBody || !dstTableBody) return false;
4115
+
4116
+ let changed = false;
4117
+ for (let r = 0; r < dstTableBody.children.length && r < srcTableBody.children.length; r++) {
4118
+ let sr = srcTableBody.children[r];
4119
+ let dr = dstTableBody.children[r];
4120
+ for (let c = 0; c < dr.children.length && c < sr.children.length; c++) {
4121
+ let dc = dr.children[c] as HTMLElement;
4122
+ let sc = sr.children[c] as HTMLElement;
4123
+ let ws = `${sc.offsetWidth}px`;
4124
+ if (!changed && dc.style.width != ws) changed = true;
4125
+ dc.style.width = dc.style.minWidth = dc.style.maxWidth = ws;
4126
+ if (applyHeight) dc.style.height = `${sc.offsetHeight}px`;
4127
+ }
4128
+ }
4129
+ return changed;
4130
+ }
4131
+
4132
+ function copyCellSizePrecise(
4133
+ srcTableBody: HTMLTableSectionElement,
4134
+ dstTableBody: HTMLTableSectionElement,
4135
+ applyHeight = true,
4136
+ ) {
4137
+ if (!srcTableBody || !dstTableBody) return false;
4138
+ let changed = false;
4139
+ for (let r = 0; r < dstTableBody.children.length && r < srcTableBody.children.length; r++) {
4140
+ let sr = srcTableBody.children[r];
4141
+ let dr = dstTableBody.children[r];
4142
+ for (let c = 0; c < dr.children.length && c < sr.children.length; c++) {
4143
+ let dc = dr.children[c] as HTMLElement;
4144
+ let sc = sr.children[c] as HTMLElement;
4145
+ let bounds = sc.getBoundingClientRect();
4146
+ let ws = `${bounds.width}px`;
4147
+ if (!changed && dc.style.width != ws) changed = true;
4148
+ dc.style.width = dc.style.minWidth = dc.style.maxWidth = ws;
4149
+ if (applyHeight) dc.style.height = `${bounds.height}px`;
4150
+ }
4151
+ }
4152
+ return changed;
4153
+ }
4154
+
4155
+ function syncHeaderHeights(header1: HTMLElement, header2: HTMLElement) {
4156
+ /**
4157
+ * In the first pass measure all row heights.
4158
+ * In the second pass apply those heights.
4159
+ * Use getBoundingClientRect() for sub-pixel accuracy.
4160
+ */
4161
+
4162
+ if (!header1 || !header2) return;
4163
+ const rowCount = Math.max(header1.children.length, header2.children.length);
4164
+ let rowHeight = [];
4165
+ for (let r = 0; r < rowCount; r++) {
4166
+ rowHeight.push(0);
4167
+ let tr1 = header1.children[r];
4168
+ let tr2 = header2.children[r];
4169
+ if (tr1) {
4170
+ for (let i = 0; i < tr1.children.length; i++) {
4171
+ let td = tr1.children[i] as HTMLTableCellElement;
4172
+ let h = td.getBoundingClientRect().height;
4173
+ if (td.rowSpan == 1 && h > rowHeight[r]) {
4174
+ rowHeight[r] = h;
4175
+ break;
4176
+ }
4177
+ }
4178
+ }
4179
+ if (tr2) {
4180
+ for (let i = 0; i < tr2.children.length; i++) {
4181
+ let td = tr2.children[i] as HTMLTableCellElement;
4182
+ let h = td.getBoundingClientRect().height;
4183
+ if (td.rowSpan == 1 && h > rowHeight[r]) {
4184
+ rowHeight[r] = h;
4185
+ break;
4186
+ }
4187
+ }
4188
+ }
4189
+ }
4190
+
4191
+ for (let r = 0; r < rowCount; r++) {
4192
+ let tr1 = header1.children[r];
4193
+ let tr2 = header2.children[r];
4194
+ if (tr1) {
4195
+ for (let i = 0; i < tr1.children.length; i++) {
4196
+ let td = tr1.children[i] as HTMLTableCellElement;
4197
+ let h = 0;
4198
+ for (let x = 0; x < td.rowSpan; x++) h += rowHeight[r + x];
4199
+ td.style.height = `${h}px`;
4200
+ }
4201
+ }
4202
+ if (tr2) {
4203
+ for (let i = 0; i < tr2.children.length; i++) {
4204
+ let td = tr2.children[i] as HTMLTableCellElement;
4205
+ let h = 0;
4206
+ for (let x = 0; x < td.rowSpan; x++) h += rowHeight[r + x];
4207
+ td.style.height = `${h}px`;
4208
+ }
4209
+ }
4210
+ }
4211
+ }
4212
+
4213
+ class AvgHeight {
4214
+ declare groups: Record<string, { sum: number; count: number }>;
4215
+
4216
+ constructor() {
4217
+ this.groups = {};
4218
+ }
4219
+
4220
+ add(group: string, height: number) {
4221
+ let g = this.groups[group];
4222
+ if (!g) g = this.groups[group] = { sum: 0, count: 0 };
4223
+ g.sum += height;
4224
+ g.count++;
4225
+ }
4226
+
4227
+ estimate(group: string): number | null {
4228
+ let g = this.groups[group];
4229
+ if (!g || g.count == 0) return null;
4230
+ return Math.round(g.sum / g.count);
4231
+ }
4232
+ }
4233
+
4234
+ function getDragDropEvent(ev: React.DragEvent, store: View, type: "dragstart" | "dragmove" | "dragdrop"): DragEvent {
4235
+ return {
4236
+ type,
4237
+ event: ev,
4238
+ cursor: getCursorPos(ev),
4239
+ dataTransfer: ev.dataTransfer,
4240
+ source: {
4241
+ width: 32,
4242
+ height: 32,
4243
+ margin: [],
4244
+ store,
4245
+ },
4246
+ };
4247
+ }