cx 26.1.0 → 26.1.2

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 (540) hide show
  1. package/.mocharc.json +5 -5
  2. package/LICENSE-THIRD-PARTY.md +91 -91
  3. package/LICENSE.md +7 -7
  4. package/README.md +46 -46
  5. package/build/data/ArrayElementView.d.ts +4 -3
  6. package/build/ui/Widget.js +0 -5
  7. package/build/ui/adapter/ArrayAdapter.js +0 -2
  8. package/build/ui/adapter/DataAdapter.d.ts +3 -3
  9. package/build/util/Component.js +5 -0
  10. package/build/util/test/createTestRenderer.d.ts +3 -1
  11. package/build/util/test/createTestRenderer.js +8 -2
  12. package/build/widgets/icons/calendar.js +4 -3
  13. package/build/widgets/icons/check.js +2 -2
  14. package/build/widgets/icons/clear.js +2 -2
  15. package/build/widgets/icons/close.js +2 -2
  16. package/build/widgets/icons/cx.js +2 -2
  17. package/build/widgets/icons/drop-down.js +2 -2
  18. package/build/widgets/icons/file.js +2 -2
  19. package/build/widgets/icons/folder-open.js +2 -2
  20. package/build/widgets/icons/folder.js +2 -2
  21. package/build/widgets/icons/forward.js +2 -2
  22. package/build/widgets/icons/loading.js +2 -2
  23. package/build/widgets/icons/menu.js +2 -2
  24. package/build/widgets/icons/pixel-picker.js +2 -2
  25. package/build/widgets/icons/search.js +2 -2
  26. package/build/widgets/icons/sort-asc.js +2 -2
  27. package/build/widgets/icons/square.js +2 -2
  28. package/build.js +133 -133
  29. package/dist/manifest.js +863 -863
  30. package/dist/ui.js +1 -10
  31. package/dist/util.js +4 -0
  32. package/dist/widgets.js +377 -313
  33. package/package.json +100 -97
  34. package/src/charts/Bar.scss +28 -28
  35. package/src/charts/Bar.ts +114 -114
  36. package/src/charts/BarGraph.scss +28 -28
  37. package/src/charts/BarGraph.tsx +145 -145
  38. package/src/charts/BubbleGraph.scss +31 -31
  39. package/src/charts/BubbleGraph.tsx +165 -165
  40. package/src/charts/Chart.ts +108 -108
  41. package/src/charts/ColorMap.ts +150 -150
  42. package/src/charts/Column.scss +28 -28
  43. package/src/charts/Column.ts +124 -124
  44. package/src/charts/ColumnBarBase.tsx +284 -284
  45. package/src/charts/ColumnBarGraphBase.tsx +229 -229
  46. package/src/charts/ColumnGraph.scss +29 -29
  47. package/src/charts/ColumnGraph.tsx +153 -153
  48. package/src/charts/Grid.ts +5 -5
  49. package/src/charts/Gridlines.scss +24 -24
  50. package/src/charts/Gridlines.tsx +88 -88
  51. package/src/charts/Legend.scss +50 -50
  52. package/src/charts/Legend.tsx +270 -270
  53. package/src/charts/LegendEntry.scss +29 -29
  54. package/src/charts/LegendEntry.tsx +197 -197
  55. package/src/charts/LineGraph.scss +24 -24
  56. package/src/charts/LineGraph.tsx +455 -455
  57. package/src/charts/Marker.scss +43 -43
  58. package/src/charts/Marker.tsx +483 -483
  59. package/src/charts/MarkerLine.scss +19 -19
  60. package/src/charts/MarkerLine.tsx +214 -214
  61. package/src/charts/MouseTracker.tsx +112 -112
  62. package/src/charts/Pie.ts +8 -8
  63. package/src/charts/PieChart.scss +28 -28
  64. package/src/charts/PieChart.tsx +717 -717
  65. package/src/charts/PieLabel.tsx +106 -106
  66. package/src/charts/PieLabelsContainer.ts +68 -68
  67. package/src/charts/Range.scss +19 -19
  68. package/src/charts/Range.tsx +318 -318
  69. package/src/charts/RangeMarker.scss +17 -17
  70. package/src/charts/RangeMarker.tsx +233 -233
  71. package/src/charts/ScatterGraph.scss +23 -23
  72. package/src/charts/ScatterGraph.tsx +245 -245
  73. package/src/charts/Swimlane.scss +16 -16
  74. package/src/charts/Swimlane.tsx +195 -195
  75. package/src/charts/Swimlanes.scss +16 -16
  76. package/src/charts/Swimlanes.tsx +179 -179
  77. package/src/charts/axis/Axis.scss +22 -22
  78. package/src/charts/axis/Axis.tsx +444 -444
  79. package/src/charts/axis/CategoryAxis.scss +34 -34
  80. package/src/charts/axis/CategoryAxis.tsx +313 -313
  81. package/src/charts/axis/NumericAxis.scss +34 -34
  82. package/src/charts/axis/NumericAxis.tsx +437 -437
  83. package/src/charts/axis/Stack.ts +61 -61
  84. package/src/charts/axis/TimeAxis.scss +33 -33
  85. package/src/charts/axis/TimeAxis.tsx +718 -718
  86. package/src/charts/axis/index.scss +5 -5
  87. package/src/charts/axis/index.ts +3 -3
  88. package/src/charts/axis/variables.scss +2 -2
  89. package/src/charts/helpers/MinMaxFinder.ts +66 -66
  90. package/src/charts/helpers/PointReducer.ts +135 -135
  91. package/src/charts/helpers/SnapPointFinder.ts +136 -136
  92. package/src/charts/helpers/ValueAtFinder.ts +72 -72
  93. package/src/charts/helpers/index.ts +4 -4
  94. package/src/charts/index.scss +22 -22
  95. package/src/charts/index.ts +34 -34
  96. package/src/charts/palette.scss +97 -97
  97. package/src/charts/shapes.tsx +86 -86
  98. package/src/charts/variables.scss +22 -22
  99. package/src/data/AggregateFunction.ts +171 -171
  100. package/src/data/ArrayElementView.spec.ts +88 -88
  101. package/src/data/ArrayElementView.ts +4 -3
  102. package/src/data/ArrayRef.ts +34 -34
  103. package/src/data/Binding.spec.ts +69 -69
  104. package/src/data/Expression.spec.ts +229 -229
  105. package/src/data/Expression.ts +233 -233
  106. package/src/data/Grouper.ts +158 -158
  107. package/src/data/Ref.spec.ts +79 -79
  108. package/src/data/Selector.ts +10 -10
  109. package/src/data/Store.spec.ts +22 -22
  110. package/src/data/StoreRef.spec.ts +24 -24
  111. package/src/data/StringTemplate.spec.ts +132 -132
  112. package/src/data/StructuredSelector.ts +146 -146
  113. package/src/data/View.spec.ts +60 -60
  114. package/src/data/View.ts +289 -289
  115. package/src/data/ZoomIntoPropertyView.spec.ts +64 -64
  116. package/src/data/comparer.spec.ts +60 -60
  117. package/src/data/computable.spec.ts +87 -87
  118. package/src/data/computable.ts +69 -69
  119. package/src/data/createAccessorModelProxy.spec.tsx +145 -145
  120. package/src/data/createAccessorModelProxy.ts +66 -66
  121. package/src/data/createStructuredSelector.spec.ts +45 -45
  122. package/src/data/createStructuredSelector.ts +62 -62
  123. package/src/data/defaultCompare.ts +14 -14
  124. package/src/data/diff/diffArrays.ts +49 -49
  125. package/src/data/diff/diffs.spec.ts +49 -49
  126. package/src/data/diff/index.ts +1 -1
  127. package/src/data/enableFatArrowExpansion.ts +6 -6
  128. package/src/data/getAccessor.spec.ts +11 -11
  129. package/src/data/getAccessor.ts +74 -74
  130. package/src/data/getSelector.spec.ts +43 -43
  131. package/src/data/getSelector.ts +66 -66
  132. package/src/data/index.ts +30 -30
  133. package/src/data/isSelector.ts +26 -26
  134. package/src/data/ops/append.spec.ts +28 -28
  135. package/src/data/ops/append.ts +5 -5
  136. package/src/data/ops/filter.spec.ts +35 -35
  137. package/src/data/ops/filter.ts +9 -9
  138. package/src/data/ops/findTreeNode.spec.ts +23 -23
  139. package/src/data/ops/findTreeNode.ts +14 -14
  140. package/src/data/ops/findTreePath.ts +23 -23
  141. package/src/data/ops/index.ts +11 -11
  142. package/src/data/ops/insertElement.ts +3 -3
  143. package/src/data/ops/merge.spec.ts +27 -27
  144. package/src/data/ops/merge.ts +13 -13
  145. package/src/data/ops/moveElement.ts +21 -21
  146. package/src/data/ops/removeTreeNodes.spec.ts +37 -37
  147. package/src/data/ops/removeTreeNodes.ts +15 -15
  148. package/src/data/ops/updateArray.spec.ts +69 -69
  149. package/src/data/ops/updateTree.spec.ts +54 -54
  150. package/src/data/ops/updateTree.ts +23 -23
  151. package/src/data/test-types.ts +7 -7
  152. package/src/global.scss +13 -13
  153. package/src/hooks/createLocalStorageRef.ts +21 -21
  154. package/src/hooks/index.ts +8 -8
  155. package/src/hooks/invokeCallback.spec.tsx +59 -59
  156. package/src/hooks/invokeCallback.ts +8 -8
  157. package/src/hooks/resolveCallback.spec.tsx +71 -71
  158. package/src/hooks/resolveCallback.ts +16 -16
  159. package/src/hooks/store.spec.tsx +67 -67
  160. package/src/hooks/store.ts +46 -46
  161. package/src/hooks/useEffect.ts +14 -14
  162. package/src/hooks/useInterval.ts +8 -8
  163. package/src/hooks/useState.ts +20 -20
  164. package/src/hooks/useTrigger.spec.tsx +105 -99
  165. package/src/hooks/useTrigger.ts +26 -26
  166. package/src/index.ts +7 -7
  167. package/src/jsx-runtime.spec.tsx +431 -431
  168. package/src/locale/de-de.ts +76 -76
  169. package/src/locale/en-us.ts +75 -75
  170. package/src/locale/es-es.ts +76 -76
  171. package/src/locale/fr-fr.ts +76 -76
  172. package/src/locale/nl-nl.ts +76 -76
  173. package/src/locale/pt-pt.ts +76 -76
  174. package/src/locale/sr-latn-ba.ts +76 -76
  175. package/src/svg/BoundedObject.ts +101 -101
  176. package/src/svg/ClipRect.tsx +29 -29
  177. package/src/svg/Ellipse.tsx +68 -68
  178. package/src/svg/Line.tsx +58 -58
  179. package/src/svg/NonOverlappingRect.ts +26 -26
  180. package/src/svg/NonOverlappingRectGroup.ts +49 -49
  181. package/src/svg/Rectangle.tsx +90 -90
  182. package/src/svg/Svg.scss +27 -27
  183. package/src/svg/Svg.tsx +241 -241
  184. package/src/svg/Text.tsx +134 -134
  185. package/src/svg/TextualBoundedObject.ts +35 -35
  186. package/src/svg/index.scss +8 -8
  187. package/src/svg/index.ts +17 -17
  188. package/src/svg/util/Rect.ts +105 -105
  189. package/src/ui/CSSHelper.ts +17 -17
  190. package/src/ui/Container.tsx +216 -216
  191. package/src/ui/ContentResolver.spec.tsx +585 -583
  192. package/src/ui/ContentResolver.ts +132 -132
  193. package/src/ui/Controller.spec.tsx +574 -566
  194. package/src/ui/Controller.ts +202 -202
  195. package/src/ui/Culture.ts +159 -159
  196. package/src/ui/Cx.spec.tsx +210 -208
  197. package/src/ui/Cx.tsx +386 -386
  198. package/src/ui/DataProxy.spec.tsx +337 -337
  199. package/src/ui/DetachedScope.tsx +159 -159
  200. package/src/ui/Format.ts +108 -108
  201. package/src/ui/HoverSync.tsx +189 -189
  202. package/src/ui/Instance.ts +866 -866
  203. package/src/ui/IsolatedScope.spec.tsx +62 -55
  204. package/src/ui/IsolatedScope.ts +50 -50
  205. package/src/ui/Localization.ts +70 -70
  206. package/src/ui/Prop.ts +140 -140
  207. package/src/ui/PureContainer.spec.tsx +232 -230
  208. package/src/ui/PureContainer.tsx +19 -19
  209. package/src/ui/RenderingContext.ts +99 -99
  210. package/src/ui/Repeater.spec.tsx +143 -141
  211. package/src/ui/Repeater.ts +194 -194
  212. package/src/ui/Rescope.spec.tsx +199 -199
  213. package/src/ui/ResizeManager.ts +30 -30
  214. package/src/ui/Restate.spec.tsx +422 -418
  215. package/src/ui/Restate.tsx +217 -217
  216. package/src/ui/StaticText.ts +11 -11
  217. package/src/ui/StructuredInstanceDataAccessor.ts +32 -32
  218. package/src/ui/Text.ts +49 -49
  219. package/src/ui/Widget.spec.tsx +53 -53
  220. package/src/ui/Widget.tsx +301 -308
  221. package/src/ui/ZIndexManager.ts +11 -11
  222. package/src/ui/adapter/ArrayAdapter.ts +229 -229
  223. package/src/ui/adapter/DataAdapter.ts +52 -52
  224. package/src/ui/adapter/GroupAdapter.ts +235 -235
  225. package/src/ui/adapter/TreeAdapter.spec.ts +76 -76
  226. package/src/ui/adapter/TreeAdapter.ts +185 -185
  227. package/src/ui/adapter/index.ts +4 -4
  228. package/src/ui/app/History.ts +133 -133
  229. package/src/ui/app/Url.spec.ts +50 -50
  230. package/src/ui/app/Url.ts +102 -102
  231. package/src/ui/app/index.ts +5 -5
  232. package/src/ui/app/startAppLoop.tsx +71 -71
  233. package/src/ui/app/startHotAppLoop.ts +41 -41
  234. package/src/ui/batchUpdates.ts +77 -77
  235. package/src/ui/bind.ts +10 -10
  236. package/src/ui/createFunctionalComponent.spec.tsx +454 -452
  237. package/src/ui/createFunctionalComponent.ts +86 -86
  238. package/src/ui/expr.ts +47 -47
  239. package/src/ui/exprHelpers.spec.ts +379 -379
  240. package/src/ui/exprHelpers.ts +78 -78
  241. package/src/ui/flattenProps.ts +21 -21
  242. package/src/ui/index.scss +2 -2
  243. package/src/ui/index.ts +47 -47
  244. package/src/ui/keyboardShortcuts.ts +40 -40
  245. package/src/ui/layout/ContentPlaceholder.spec.tsx +599 -587
  246. package/src/ui/layout/ContentPlaceholder.ts +133 -133
  247. package/src/ui/layout/FirstVisibleChildLayout.spec.tsx +207 -195
  248. package/src/ui/layout/FirstVisibleChildLayout.ts +60 -60
  249. package/src/ui/layout/LabelsLeftLayout.scss +46 -46
  250. package/src/ui/layout/LabelsLeftLayout.tsx +76 -76
  251. package/src/ui/layout/LabelsTopLayout.scss +64 -64
  252. package/src/ui/layout/LabelsTopLayout.tsx +156 -156
  253. package/src/ui/layout/UseParentLayout.ts +8 -8
  254. package/src/ui/layout/exploreChildren.ts +38 -38
  255. package/src/ui/layout/index.scss +3 -3
  256. package/src/ui/layout/index.ts +10 -10
  257. package/src/ui/layout/variables.scss +2 -2
  258. package/src/ui/selection/KeySelection.ts +153 -153
  259. package/src/ui/selection/Selection.ts +128 -128
  260. package/src/ui/selection/index.ts +3 -3
  261. package/src/ui/tpl.ts +4 -4
  262. package/src/ui/variables.scss +1 -1
  263. package/src/util/Component.spec.ts +411 -381
  264. package/src/util/Component.ts +301 -296
  265. package/src/util/Console.ts +13 -13
  266. package/src/util/Debug.ts +71 -71
  267. package/src/util/GlobalCacheIdentifier.ts +11 -11
  268. package/src/util/KeyCode.ts +21 -21
  269. package/src/util/SubscriberList.ts +86 -86
  270. package/src/util/Timing.ts +58 -58
  271. package/src/util/TraversalStack.spec.ts +53 -53
  272. package/src/util/TraversalStack.ts +47 -47
  273. package/src/util/calculateNaturalElementHeight.ts +22 -22
  274. package/src/util/call-once.scss +6 -6
  275. package/src/util/capitalize.ts +4 -4
  276. package/src/util/coalesce.ts +6 -6
  277. package/src/util/color/hslToRgb.ts +34 -34
  278. package/src/util/color/index.ts +4 -4
  279. package/src/util/color/parseColor.ts +173 -173
  280. package/src/util/color/rgbToHex.ts +14 -14
  281. package/src/util/date/dateDiff.ts +9 -9
  282. package/src/util/date/diff.ts +13 -13
  283. package/src/util/date/encodeDate.ts +8 -8
  284. package/src/util/date/encodeDateWithTimezoneOffset.ts +18 -18
  285. package/src/util/date/index.ts +11 -11
  286. package/src/util/date/lowerBoundCheck.ts +13 -13
  287. package/src/util/date/maxDate.ts +14 -14
  288. package/src/util/date/minDate.ts +14 -14
  289. package/src/util/date/monthStart.ts +8 -8
  290. package/src/util/date/parseDateInvariant.ts +20 -20
  291. package/src/util/date/sameDate.ts +11 -11
  292. package/src/util/date/upperBoundCheck.spec.ts +30 -30
  293. package/src/util/date/upperBoundCheck.ts +13 -13
  294. package/src/util/date/zeroTime.ts +9 -9
  295. package/src/util/debounce.ts +26 -26
  296. package/src/util/dummyCallback.ts +1 -1
  297. package/src/util/escapeSpecialRegexCharacters.ts +8 -8
  298. package/src/util/eventCallbacks.ts +12 -12
  299. package/src/util/expandFatArrows.ts +118 -118
  300. package/src/util/findScrollableParent.ts +15 -15
  301. package/src/util/getParentFrameBoundingClientRect.ts +13 -13
  302. package/src/util/getScrollerBoundingClientRect.ts +12 -12
  303. package/src/util/getSearchQueryPredicate.spec.ts +40 -40
  304. package/src/util/getSearchQueryPredicate.ts +58 -58
  305. package/src/util/getTopLevelBoundingClientRect.ts +7 -7
  306. package/src/util/getVendorPrefix.ts +33 -33
  307. package/src/util/hasKey.ts +18 -18
  308. package/src/util/index.scss +10 -10
  309. package/src/util/index.ts +55 -55
  310. package/src/util/isArray.ts +3 -3
  311. package/src/util/isDefined.ts +3 -3
  312. package/src/util/isDigit.ts +8 -8
  313. package/src/util/isFunction.ts +3 -3
  314. package/src/util/isNonEmptyArray.ts +3 -3
  315. package/src/util/isNumber.ts +3 -3
  316. package/src/util/isObject.ts +3 -3
  317. package/src/util/isPromise.ts +6 -6
  318. package/src/util/isString.ts +3 -3
  319. package/src/util/isTextInputElement.ts +2 -2
  320. package/src/util/isTouchDevice.ts +7 -7
  321. package/src/util/isTouchEvent.ts +64 -64
  322. package/src/util/isUndefined.ts +3 -3
  323. package/src/util/isValidIdentifierName.spec.ts +33 -33
  324. package/src/util/isValidIdentifierName.ts +5 -5
  325. package/src/util/onIdleCallback.ts +10 -10
  326. package/src/util/parseStyle.ts +29 -29
  327. package/src/util/quote.ts +6 -6
  328. package/src/util/reverseSlice.ts +9 -9
  329. package/src/util/routeAppend.spec.ts +19 -19
  330. package/src/util/routeAppend.ts +15 -15
  331. package/src/util/scrollElementIntoView.ts +40 -40
  332. package/src/util/scss/add-rules.scss +40 -40
  333. package/src/util/scss/calc.scss +44 -44
  334. package/src/util/scss/call-once.scss +12 -12
  335. package/src/util/scss/clockwise.scss +49 -49
  336. package/src/util/scss/colors.scss +9 -9
  337. package/src/util/scss/deep-get.scss +11 -11
  338. package/src/util/scss/deep-merge.scss +21 -21
  339. package/src/util/scss/divide.scss +3 -3
  340. package/src/util/scss/include.scss +48 -48
  341. package/src/util/scss/index.scss +9 -9
  342. package/src/util/shallowEquals.ts +43 -43
  343. package/src/util/test/createTestRenderer.tsx +19 -12
  344. package/src/util/throttle.ts +21 -21
  345. package/src/util/validatedDebounce.ts +23 -23
  346. package/src/variables.scss +217 -217
  347. package/src/widgets/AccessorBindings.spec.tsx +90 -90
  348. package/src/widgets/Button.scss +119 -119
  349. package/src/widgets/Button.tsx +189 -189
  350. package/src/widgets/Button.variables.scss +117 -117
  351. package/src/widgets/CxCredit.scss +39 -39
  352. package/src/widgets/CxCredit.tsx +46 -46
  353. package/src/widgets/DocumentTitle.ts +95 -95
  354. package/src/widgets/FlexBox.scss +148 -148
  355. package/src/widgets/FlexBox.tsx +168 -168
  356. package/src/widgets/Heading.scss +40 -40
  357. package/src/widgets/Heading.ts +42 -42
  358. package/src/widgets/HighlightedSearchText.scss +20 -20
  359. package/src/widgets/HighlightedSearchText.tsx +54 -54
  360. package/src/widgets/HtmlElement.spec.helpers.tsx +108 -108
  361. package/src/widgets/HtmlElement.spec.tsx +89 -89
  362. package/src/widgets/HtmlElement.tsx +407 -407
  363. package/src/widgets/Icon.scss +22 -22
  364. package/src/widgets/Icon.ts +64 -64
  365. package/src/widgets/List.scss +93 -93
  366. package/src/widgets/List.tsx +793 -793
  367. package/src/widgets/ProgressBar.scss +50 -50
  368. package/src/widgets/ProgressBar.tsx +66 -66
  369. package/src/widgets/ReactElementWrapper.spec.tsx +452 -452
  370. package/src/widgets/ReactElementWrapper.tsx +108 -108
  371. package/src/widgets/Resizer.scss +43 -43
  372. package/src/widgets/Resizer.tsx +200 -200
  373. package/src/widgets/Section.scss +55 -55
  374. package/src/widgets/Section.tsx +187 -187
  375. package/src/widgets/animations.scss +10 -10
  376. package/src/widgets/autoFocus.ts +9 -9
  377. package/src/widgets/cx.ts +63 -63
  378. package/src/widgets/drag-drop/DragClone.scss +35 -35
  379. package/src/widgets/drag-drop/DragHandle.scss +18 -18
  380. package/src/widgets/drag-drop/DragHandle.tsx +47 -47
  381. package/src/widgets/drag-drop/DragSource.scss +26 -26
  382. package/src/widgets/drag-drop/DragSource.tsx +237 -237
  383. package/src/widgets/drag-drop/DropZone.scss +76 -76
  384. package/src/widgets/drag-drop/DropZone.tsx +353 -353
  385. package/src/widgets/drag-drop/index.scss +3 -3
  386. package/src/widgets/drag-drop/index.ts +4 -4
  387. package/src/widgets/drag-drop/ops.tsx +422 -422
  388. package/src/widgets/drag-drop/variables.scss +14 -14
  389. package/src/widgets/enableAllInternalDependencies.ts +11 -11
  390. package/src/widgets/form/Calendar.scss +199 -199
  391. package/src/widgets/form/Calendar.tsx +760 -760
  392. package/src/widgets/form/Calendar.variables.scss +63 -63
  393. package/src/widgets/form/Checkbox.scss +129 -129
  394. package/src/widgets/form/Checkbox.tsx +287 -287
  395. package/src/widgets/form/Checkbox.variables.scss +39 -39
  396. package/src/widgets/form/ColorField.scss +98 -98
  397. package/src/widgets/form/ColorField.tsx +497 -497
  398. package/src/widgets/form/ColorPicker.scss +285 -285
  399. package/src/widgets/form/ColorPicker.tsx +544 -544
  400. package/src/widgets/form/ColorPicker.variables.scss +22 -22
  401. package/src/widgets/form/DateField.ts +21 -21
  402. package/src/widgets/form/DateTimeField.scss +92 -92
  403. package/src/widgets/form/DateTimeField.tsx +726 -726
  404. package/src/widgets/form/DateTimePicker.scss +46 -46
  405. package/src/widgets/form/DateTimePicker.tsx +429 -429
  406. package/src/widgets/form/Field.scss +164 -164
  407. package/src/widgets/form/Field.tsx +608 -608
  408. package/src/widgets/form/FieldGroup.ts +10 -10
  409. package/src/widgets/form/FieldIcon.ts +61 -61
  410. package/src/widgets/form/HelpText.scss +24 -24
  411. package/src/widgets/form/HelpText.ts +15 -15
  412. package/src/widgets/form/Label.scss +37 -37
  413. package/src/widgets/form/Label.tsx +117 -117
  414. package/src/widgets/form/LabeledContainer.ts +77 -77
  415. package/src/widgets/form/LookupField.scss +221 -221
  416. package/src/widgets/form/LookupField.spec.tsx +93 -93
  417. package/src/widgets/form/LookupField.tsx +1421 -1421
  418. package/src/widgets/form/MonthField.scss +100 -100
  419. package/src/widgets/form/MonthField.tsx +670 -670
  420. package/src/widgets/form/MonthPicker.scss +125 -125
  421. package/src/widgets/form/MonthPicker.tsx +822 -822
  422. package/src/widgets/form/NumberField.scss +63 -63
  423. package/src/widgets/form/NumberField.tsx +543 -543
  424. package/src/widgets/form/Radio.scss +123 -123
  425. package/src/widgets/form/Radio.tsx +249 -249
  426. package/src/widgets/form/Radio.variables.scss +45 -45
  427. package/src/widgets/form/Select.scss +101 -101
  428. package/src/widgets/form/Select.tsx +327 -327
  429. package/src/widgets/form/Slider.scss +121 -121
  430. package/src/widgets/form/Slider.tsx +473 -473
  431. package/src/widgets/form/Switch.scss +142 -142
  432. package/src/widgets/form/Switch.tsx +176 -176
  433. package/src/widgets/form/TextArea.scss +45 -45
  434. package/src/widgets/form/TextArea.tsx +229 -229
  435. package/src/widgets/form/TextField.scss +57 -57
  436. package/src/widgets/form/TextField.tsx +407 -407
  437. package/src/widgets/form/TimeField.ts +10 -10
  438. package/src/widgets/form/TimeList.tsx +105 -105
  439. package/src/widgets/form/UploadButton.scss +49 -49
  440. package/src/widgets/form/UploadButton.tsx +307 -307
  441. package/src/widgets/form/ValidationError.scss +22 -22
  442. package/src/widgets/form/ValidationError.tsx +72 -72
  443. package/src/widgets/form/ValidationGroup.spec.tsx +147 -147
  444. package/src/widgets/form/ValidationGroup.ts +141 -141
  445. package/src/widgets/form/Validator.ts +60 -60
  446. package/src/widgets/form/Wheel.scss +152 -152
  447. package/src/widgets/form/Wheel.tsx +314 -314
  448. package/src/widgets/form/index.scss +24 -24
  449. package/src/widgets/form/index.ts +28 -28
  450. package/src/widgets/form/variables.scss +355 -355
  451. package/src/widgets/grid/Grid.scss +640 -640
  452. package/src/widgets/grid/Grid.tsx +4243 -4243
  453. package/src/widgets/grid/GridCellEditor.tsx +58 -58
  454. package/src/widgets/grid/GridRow.ts +302 -302
  455. package/src/widgets/grid/GridRowLine.ts +49 -49
  456. package/src/widgets/grid/Pagination.scss +115 -115
  457. package/src/widgets/grid/Pagination.tsx +126 -126
  458. package/src/widgets/grid/TreeNode.scss +90 -90
  459. package/src/widgets/grid/TreeNode.tsx +154 -154
  460. package/src/widgets/grid/createGridCellEditor.tsx +18 -18
  461. package/src/widgets/grid/index.scss +3 -3
  462. package/src/widgets/grid/index.ts +16 -16
  463. package/src/widgets/grid/variables.scss +137 -137
  464. package/src/widgets/icons/arrow-down.svg +3 -3
  465. package/src/widgets/icons/arrow-right.svg +2 -2
  466. package/src/widgets/icons/base.svg +104 -104
  467. package/src/widgets/icons/calendar-old.svg +169 -169
  468. package/src/widgets/icons/calendar.svg +187 -187
  469. package/src/widgets/icons/calendar.tsx +20 -15
  470. package/src/widgets/icons/check.tsx +2 -1
  471. package/src/widgets/icons/clear.svg +74 -74
  472. package/src/widgets/icons/clear.tsx +2 -1
  473. package/src/widgets/icons/close.svg +74 -74
  474. package/src/widgets/icons/close.tsx +2 -2
  475. package/src/widgets/icons/cx.tsx +2 -1
  476. package/src/widgets/icons/drop-down.tsx +2 -1
  477. package/src/widgets/icons/dropdown-arrow.svg +61 -61
  478. package/src/widgets/icons/file.svg +4 -4
  479. package/src/widgets/icons/file.tsx +2 -1
  480. package/src/widgets/icons/folder-open.svg +5 -5
  481. package/src/widgets/icons/folder-open.tsx +2 -1
  482. package/src/widgets/icons/folder.svg +58 -58
  483. package/src/widgets/icons/folder.tsx +2 -1
  484. package/src/widgets/icons/forward.svg +67 -67
  485. package/src/widgets/icons/forward.tsx +2 -1
  486. package/src/widgets/icons/index.ts +14 -14
  487. package/src/widgets/icons/loading.svg +4 -4
  488. package/src/widgets/icons/loading.tsx +2 -1
  489. package/src/widgets/icons/menu.tsx +2 -1
  490. package/src/widgets/icons/pixel-picker.tsx +2 -2
  491. package/src/widgets/icons/registry.ts +56 -56
  492. package/src/widgets/icons/search.svg +107 -107
  493. package/src/widgets/icons/search.tsx +2 -1
  494. package/src/widgets/icons/sort-asc.svg +3 -3
  495. package/src/widgets/icons/sort-asc.tsx +2 -1
  496. package/src/widgets/icons/square.tsx +2 -1
  497. package/src/widgets/index.d.ts +55 -55
  498. package/src/widgets/index.scss +16 -16
  499. package/src/widgets/index.ts +58 -58
  500. package/src/widgets/nav/Link.scss +20 -20
  501. package/src/widgets/nav/Link.ts +11 -11
  502. package/src/widgets/nav/LinkButton.ts +176 -176
  503. package/src/widgets/nav/Menu.scss +76 -76
  504. package/src/widgets/nav/Menu.tsx +489 -489
  505. package/src/widgets/nav/Menu.variables.scss +25 -25
  506. package/src/widgets/nav/MenuItem.scss +130 -130
  507. package/src/widgets/nav/MenuItem.tsx +525 -525
  508. package/src/widgets/nav/MenuSpacer.ts +18 -18
  509. package/src/widgets/nav/RedirectRoute.ts +49 -49
  510. package/src/widgets/nav/Route.spec.tsx +24 -24
  511. package/src/widgets/nav/Scroller.scss +148 -148
  512. package/src/widgets/nav/Scroller.tsx +252 -252
  513. package/src/widgets/nav/Submenu.ts +6 -6
  514. package/src/widgets/nav/Tab.scss +82 -82
  515. package/src/widgets/nav/Tab.ts +120 -120
  516. package/src/widgets/nav/Tab.variables.scss +84 -84
  517. package/src/widgets/nav/cover.scss +22 -22
  518. package/src/widgets/nav/index.scss +5 -5
  519. package/src/widgets/nav/index.ts +10 -10
  520. package/src/widgets/nav/variables.scss +27 -27
  521. package/src/widgets/overlay/ContextMenu.ts +42 -42
  522. package/src/widgets/overlay/Dropdown.scss +186 -186
  523. package/src/widgets/overlay/FlyweightTooltipTracker.ts +57 -57
  524. package/src/widgets/overlay/Overlay.scss +68 -68
  525. package/src/widgets/overlay/Overlay.tsx +947 -947
  526. package/src/widgets/overlay/Toast.scss +163 -163
  527. package/src/widgets/overlay/Tooltip.scss +177 -177
  528. package/src/widgets/overlay/Tooltip.tsx +393 -393
  529. package/src/widgets/overlay/Window.scss +129 -129
  530. package/src/widgets/overlay/Window.variables.scss +62 -62
  531. package/src/widgets/overlay/captureMouse.scss +13 -13
  532. package/src/widgets/overlay/captureMouse.ts +195 -195
  533. package/src/widgets/overlay/createHotPromiseWindowFactory.ts +71 -71
  534. package/src/widgets/overlay/index.scss +15 -15
  535. package/src/widgets/overlay/tooltip-ops.ts +173 -173
  536. package/src/widgets/overlay/variables.scss +85 -85
  537. package/src/widgets/variables.scss +146 -146
  538. package/tsconfig.compile.json +4 -4
  539. package/tsconfig.json +34 -34
  540. package/tsconfig.mocha.json +14 -14
@@ -1,381 +1,411 @@
1
- import assert from "assert";
2
- import { Component, ComponentConstructor, ComponentConfigType, ComponentInstanceType, Create, CreateConfig } from "./Component";
3
-
4
- // Test classes for type checking
5
- interface TestWidgetConfig {
6
- text: string;
7
- value?: number;
8
- }
9
-
10
- class TestWidget extends Component {
11
- static isComponentType = true as const;
12
- declare text?: string;
13
- declare value?: number;
14
-
15
- constructor(config?: TestWidgetConfig) {
16
- super(config);
17
- }
18
- }
19
-
20
- interface TestButtonConfig extends TestWidgetConfig {
21
- onClick?: () => void;
22
- }
23
-
24
- class TestButton extends TestWidget {
25
- declare onClick?: () => void;
26
-
27
- constructor(config?: TestButtonConfig) {
28
- super(config);
29
- }
30
- }
31
-
32
- // Unrelated class (not in TestWidget hierarchy) for type testing
33
- interface UnrelatedConfig {
34
- name: string;
35
- }
36
-
37
- class UnrelatedComponent extends Component {
38
- declare name?: string;
39
-
40
- constructor(config?: UnrelatedConfig) {
41
- super(config);
42
- }
43
- }
44
-
45
- // Register alias for testing
46
- Component.alias("test-widget", TestWidget);
47
- Component.alias("test-button", TestButton);
48
-
49
- describe("Component.create", function () {
50
- describe("pass-through", function () {
51
- it("returns the same instance if already a component", function () {
52
- const btn = new TestButton({ text: "Hello" });
53
- const result = Component.create(btn);
54
- assert.strictEqual(result, btn);
55
- assert.equal(result.text, "Hello");
56
- });
57
-
58
- it("preserves the component type", function () {
59
- const btn = new TestButton({ text: "Hello" });
60
- const result: TestButton = Component.create(btn);
61
- assert.ok(result instanceof TestButton);
62
- });
63
- });
64
-
65
- describe("array input", function () {
66
- it("creates an array of components from array of configs", function () {
67
- const results = TestWidget.create([{ text: "One" }, { text: "Two" }]);
68
- assert.equal(results.length, 2);
69
- assert.equal(results[0].text, "One");
70
- assert.equal(results[1].text, "Two");
71
- });
72
-
73
- it("returns array of component instances", function () {
74
- const configs = [{ text: "One" }];
75
- const results = TestWidget.create(configs);
76
- assert.ok(Array.isArray(results));
77
- assert.ok(results[0] instanceof TestWidget);
78
- });
79
- });
80
-
81
- describe("class type as first argument", function () {
82
- it("creates instance of specified class", function () {
83
- const result = Component.create(TestButton, { text: "Click me" });
84
- assert.ok(result instanceof TestButton);
85
- assert.equal(result.text, "Click me");
86
- });
87
-
88
- it("returns typed result based on class", function () {
89
- const result: TestButton = Component.create(TestButton, { text: "Click" });
90
- assert.ok(result instanceof TestButton);
91
- });
92
-
93
- it("merges config and more parameters", function () {
94
- const result = Component.create(TestButton, { text: "Base" }, { value: 42 });
95
- assert.equal(result.text, "Base");
96
- assert.equal(result.value, 42);
97
- });
98
- });
99
-
100
- describe("config with type property", function () {
101
- it("creates instance of type specified in config", function () {
102
- const result = Component.create({ type: TestButton, text: "Typed" });
103
- assert.ok(result instanceof TestButton);
104
- assert.equal(result.text, "Typed");
105
- });
106
-
107
- it("uses config properties for the created instance", function () {
108
- const result = Component.create({
109
- type: TestButton,
110
- text: "Hello",
111
- value: 123,
112
- });
113
- assert.equal(result.text, "Hello");
114
- assert.equal(result.value, 123);
115
- });
116
- });
117
-
118
- describe("config with $type property", function () {
119
- it("creates instance of $type specified in config", function () {
120
- const result = Component.create({ $type: TestButton, text: "Dollar" });
121
- assert.ok(result instanceof TestButton);
122
- assert.equal(result.text, "Dollar");
123
- });
124
- });
125
-
126
- describe("class type with config and empty more object", function () {
127
- it("creates instance with config and empty more object", function () {
128
- const result = Component.create(TestWidget, { text: "Hello" }, {});
129
- assert.ok(result instanceof TestWidget);
130
- assert.equal(result.text, "Hello");
131
- });
132
- });
133
-
134
- describe("parent class calling create with child class", function () {
135
- it("creates child instance when called on parent class", function () {
136
- // Pattern: ParentClass.create(ChildClass, config, more)
137
- // This is how Widget.create(StaticText, { text }, {}) is used
138
- const result = TestWidget.create(TestButton, { text: "Child" }, {});
139
- assert.ok(result instanceof TestButton);
140
- assert.equal(result.text, "Child");
141
- });
142
-
143
- it("returns properly typed child instance", function () {
144
- const result: TestButton = TestWidget.create(TestButton, { text: "Typed" });
145
- assert.ok(result instanceof TestButton);
146
- });
147
- });
148
-
149
- describe("string alias", function () {
150
- it("creates instance from registered alias", function () {
151
- const result = Component.create("test-button", { text: "Aliased" });
152
- assert.ok(result instanceof TestButton);
153
- assert.equal(result.text, "Aliased");
154
- });
155
-
156
- it("throws for unknown alias", function () {
157
- assert.throws(() => {
158
- Component.create("unknown-alias");
159
- }, /Unknown component alias/);
160
- });
161
- });
162
-
163
- describe("plain config object", function () {
164
- it("creates instance of the class create is called on", function () {
165
- const result = TestWidget.create({ text: "Plain" });
166
- assert.ok(result instanceof TestWidget);
167
- assert.equal(result.text, "Plain");
168
- });
169
-
170
- it("works with subclasses", function () {
171
- const result = TestButton.create({ text: "Sub", onClick: () => {} });
172
- assert.ok(result instanceof TestButton);
173
- assert.equal(result.text, "Sub");
174
- });
175
- });
176
-
177
- describe("config array as second argument", function () {
178
- it("creates array when config is an array", function () {
179
- const results = Component.create(TestWidget, [{ text: "A" }, { text: "B" }]);
180
- assert.equal(results.length, 2);
181
- assert.ok(results[0] instanceof TestWidget);
182
- assert.ok(results[1] instanceof TestWidget);
183
- });
184
- });
185
-
186
- describe("type inference", function () {
187
- it("infers config type from class constructor", function () {
188
- // This is a compile-time check - if it compiles, the types are correct
189
- const config: ComponentConfigType<typeof TestButton> = {
190
- text: "Hello",
191
- onClick: () => {},
192
- };
193
- const result = Component.create(TestButton, config);
194
- assert.ok(result instanceof TestButton);
195
- });
196
- });
197
-
198
- describe("config with type and more argument", function () {
199
- it("merges config and more parameters", function () {
200
- const result = Component.create({ type: TestButton, text: "Base" }, { value: 42 });
201
- assert.ok(result instanceof TestButton);
202
- assert.equal(result.text, "Base");
203
- assert.equal(result.value, 42);
204
- });
205
-
206
- it("works with $type as well", function () {
207
- const result = Component.create({ $type: TestButton, text: "Dollar" }, { value: 99 });
208
- assert.ok(result instanceof TestButton);
209
- assert.equal(result.text, "Dollar");
210
- assert.equal(result.value, 99);
211
- });
212
- });
213
-
214
- describe("heterogeneous array with type property", function () {
215
- it("creates array of different component types", function () {
216
- const results = Component.create([
217
- { type: TestWidget, text: "Widget" },
218
- { type: TestButton, text: "Button", onClick: () => {} },
219
- ]);
220
- assert.equal(results.length, 2);
221
- assert.ok(results[0] instanceof TestWidget);
222
- assert.ok(results[1] instanceof TestButton);
223
- assert.equal(results[0].text, "Widget");
224
- assert.equal(results[1].text, "Button");
225
- });
226
-
227
- it("returns properly typed tuple", function () {
228
- const results = Component.create([
229
- { type: TestWidget, text: "W" },
230
- { type: TestButton, text: "B" },
231
- ]);
232
- // Type check: results[0] should be TestWidget, results[1] should be TestButton
233
- const widget: TestWidget = results[0];
234
- const button: TestButton = results[1];
235
- assert.ok(widget instanceof TestWidget);
236
- assert.ok(button instanceof TestButton);
237
- });
238
- });
239
-
240
- describe("this-bound create with config", function () {
241
- it("creates instance when called on specific class", function () {
242
- const result = TestButton.create({ text: "Bound", onClick: () => {} });
243
- assert.ok(result instanceof TestButton);
244
- assert.equal(result.text, "Bound");
245
- });
246
-
247
- it("accepts more parameter for additional config", function () {
248
- const result = TestButton.create({ text: "Main" }, { value: 100 });
249
- assert.ok(result instanceof TestButton);
250
- assert.equal(result.text, "Main");
251
- assert.equal(result.value, 100);
252
- });
253
- });
254
-
255
- describe("this-bound create with array", function () {
256
- it("creates array of instances when called on specific class", function () {
257
- const results = TestButton.create([{ text: "A" }, { text: "B" }]);
258
- assert.equal(results.length, 2);
259
- assert.ok(results[0] instanceof TestButton);
260
- assert.ok(results[1] instanceof TestButton);
261
- });
262
-
263
- it("accepts more parameter for array", function () {
264
- const results = TestButton.create([{ text: "X" }, { text: "Y" }], { value: 50 });
265
- assert.equal(results.length, 2);
266
- assert.equal(results[0].value, 50);
267
- assert.equal(results[1].value, 50);
268
- });
269
- });
270
- });
271
-
272
- describe("Create type", function () {
273
- // Helper function that accepts Create
274
- function createComponent<TCtor extends ComponentConstructor>(
275
- creatable: Create<TCtor>,
276
- ): ComponentInstanceType<TCtor> {
277
- return Component.create(creatable as any);
278
- }
279
-
280
- it("accepts instance pass-through", function () {
281
- const widget = new TestWidget({ text: "Instance" });
282
- const result = createComponent<typeof TestWidget>(widget);
283
- assert.strictEqual(result, widget);
284
- });
285
-
286
- it("accepts constructor", function () {
287
- const result = createComponent<typeof TestWidget>(TestButton);
288
- assert.ok(result instanceof TestButton);
289
- });
290
-
291
- it("accepts config with type", function () {
292
- const result = createComponent<typeof TestWidget>({ type: TestButton, text: "Typed" });
293
- assert.ok(result instanceof TestButton);
294
- assert.equal(result.text, "Typed");
295
- });
296
-
297
- it("accepts config with $type", function () {
298
- const result = createComponent<typeof TestWidget>({ $type: TestButton, text: "DollarTyped" });
299
- assert.ok(result instanceof TestButton);
300
- assert.equal(result.text, "DollarTyped");
301
- });
302
- });
303
-
304
- describe("CreateConfig type safety", function () {
305
- it("rejects config with type from unrelated class", function () {
306
- // @ts-expect-error - UnrelatedComponent is not a subclass of TestWidget
307
- const config: CreateConfig<typeof TestWidget> = { type: UnrelatedComponent, name: "test" };
308
- });
309
-
310
- it("rejects config missing required properties", function () {
311
- // @ts-expect-error - text is required in TestWidgetConfig
312
- const config: CreateConfig<typeof TestWidget> = { type: TestButton };
313
- });
314
-
315
- it("accepts config with type from subclass and required properties", function () {
316
- const config: CreateConfig<typeof TestWidget> = { type: TestButton, text: "valid" };
317
- assert.ok(config);
318
- });
319
-
320
- it("accepts constructor from subclass", function () {
321
- const config: CreateConfig<typeof TestWidget> = TestButton;
322
- assert.ok(config);
323
- });
324
- });
325
-
326
- describe("Create type as property (like Chart.axes)", function () {
327
- // Simulates how Chart uses Create<typeof Axis> for its axes property
328
- interface ContainerConfig {
329
- items?: Record<string, Create<typeof TestWidget>>;
330
- }
331
-
332
- it("accepts constructor as property value", function () {
333
- const config: ContainerConfig = {
334
- items: {
335
- a: TestWidget,
336
- b: TestButton,
337
- },
338
- };
339
- assert.ok(config);
340
- });
341
-
342
- it("accepts config with type as property value", function () {
343
- const config: ContainerConfig = {
344
- items: {
345
- a: { type: TestWidget, text: "widget" },
346
- b: { type: TestButton, text: "button", onClick: () => {} },
347
- },
348
- };
349
- assert.ok(config);
350
- });
351
-
352
- it("accepts config with $type as property value", function () {
353
- const config: ContainerConfig = {
354
- items: {
355
- a: { $type: TestWidget, text: "widget" },
356
- b: { $type: TestButton, text: "button" },
357
- },
358
- };
359
- assert.ok(config);
360
- });
361
-
362
- it("accepts instance as property value", function () {
363
- const config: ContainerConfig = {
364
- items: {
365
- a: new TestWidget({ text: "instance" }),
366
- b: new TestButton({ text: "button" }),
367
- },
368
- };
369
- assert.ok(config);
370
- });
371
-
372
- it("accepts config with extra properties", function () {
373
- const config: ContainerConfig = {
374
- items: {
375
- // Extra property (like snapToTicks on NumericAxis)
376
- a: { type: TestButton, text: "button", onClick: () => {}, value: 42 },
377
- },
378
- };
379
- assert.ok(config);
380
- });
381
- });
1
+ import assert from "assert";
2
+ import { Component, ComponentConstructor, ComponentConfigType, ComponentInstanceType, Create, CreateConfig } from "./Component";
3
+
4
+ // Test classes for type checking
5
+ interface TestWidgetConfig {
6
+ text: string;
7
+ value?: number;
8
+ }
9
+
10
+ class TestWidget extends Component {
11
+ static isComponentType = true as const;
12
+ declare text?: string;
13
+ declare value?: number;
14
+
15
+ constructor(config?: TestWidgetConfig) {
16
+ super(config);
17
+ }
18
+ }
19
+
20
+ interface TestButtonConfig extends TestWidgetConfig {
21
+ onClick?: () => void;
22
+ }
23
+
24
+ class TestButton extends TestWidget {
25
+ declare onClick?: () => void;
26
+
27
+ constructor(config?: TestButtonConfig) {
28
+ super(config);
29
+ }
30
+ }
31
+
32
+ // Unrelated class (not in TestWidget hierarchy) for type testing
33
+ interface UnrelatedConfig {
34
+ name: string;
35
+ }
36
+
37
+ class UnrelatedComponent extends Component {
38
+ declare name?: string;
39
+
40
+ constructor(config?: UnrelatedConfig) {
41
+ super(config);
42
+ }
43
+ }
44
+
45
+ // Register alias for testing
46
+ Component.alias("test-widget", TestWidget);
47
+ Component.alias("test-button", TestButton);
48
+
49
+ describe("Component.create", function () {
50
+ describe("pass-through", function () {
51
+ it("returns the same instance if already a component", function () {
52
+ const btn = new TestButton({ text: "Hello" });
53
+ const result = Component.create(btn);
54
+ assert.strictEqual(result, btn);
55
+ assert.equal(result.text, "Hello");
56
+ });
57
+
58
+ it("preserves the component type", function () {
59
+ const btn = new TestButton({ text: "Hello" });
60
+ const result: TestButton = Component.create(btn);
61
+ assert.ok(result instanceof TestButton);
62
+ });
63
+ });
64
+
65
+ describe("array input", function () {
66
+ it("creates an array of components from array of configs", function () {
67
+ const results = TestWidget.create([{ text: "One" }, { text: "Two" }]);
68
+ assert.equal(results.length, 2);
69
+ assert.equal(results[0].text, "One");
70
+ assert.equal(results[1].text, "Two");
71
+ });
72
+
73
+ it("returns array of component instances", function () {
74
+ const configs = [{ text: "One" }];
75
+ const results = TestWidget.create(configs);
76
+ assert.ok(Array.isArray(results));
77
+ assert.ok(results[0] instanceof TestWidget);
78
+ });
79
+ });
80
+
81
+ describe("class type as first argument", function () {
82
+ it("creates instance of specified class", function () {
83
+ const result = Component.create(TestButton, { text: "Click me" });
84
+ assert.ok(result instanceof TestButton);
85
+ assert.equal(result.text, "Click me");
86
+ });
87
+
88
+ it("returns typed result based on class", function () {
89
+ const result: TestButton = Component.create(TestButton, { text: "Click" });
90
+ assert.ok(result instanceof TestButton);
91
+ });
92
+
93
+ it("merges config and more parameters", function () {
94
+ const result = Component.create(TestButton, { text: "Base" }, { value: 42 });
95
+ assert.equal(result.text, "Base");
96
+ assert.equal(result.value, 42);
97
+ });
98
+ });
99
+
100
+ describe("config with type property", function () {
101
+ it("creates instance of type specified in config", function () {
102
+ const result = Component.create({ type: TestButton, text: "Typed" });
103
+ assert.ok(result instanceof TestButton);
104
+ assert.equal(result.text, "Typed");
105
+ });
106
+
107
+ it("uses config properties for the created instance", function () {
108
+ const result = Component.create({
109
+ type: TestButton,
110
+ text: "Hello",
111
+ value: 123,
112
+ });
113
+ assert.equal(result.text, "Hello");
114
+ assert.equal(result.value, 123);
115
+ });
116
+ });
117
+
118
+ describe("config with $type property", function () {
119
+ it("creates instance of $type specified in config", function () {
120
+ const result = Component.create({ $type: TestButton, text: "Dollar" });
121
+ assert.ok(result instanceof TestButton);
122
+ assert.equal(result.text, "Dollar");
123
+ });
124
+ });
125
+
126
+ describe("class type with config and empty more object", function () {
127
+ it("creates instance with config and empty more object", function () {
128
+ const result = Component.create(TestWidget, { text: "Hello" }, {});
129
+ assert.ok(result instanceof TestWidget);
130
+ assert.equal(result.text, "Hello");
131
+ });
132
+ });
133
+
134
+ describe("parent class calling create with child class", function () {
135
+ it("creates child instance when called on parent class", function () {
136
+ // Pattern: ParentClass.create(ChildClass, config, more)
137
+ // This is how Widget.create(StaticText, { text }, {}) is used
138
+ const result = TestWidget.create(TestButton, { text: "Child" }, {});
139
+ assert.ok(result instanceof TestButton);
140
+ assert.equal(result.text, "Child");
141
+ });
142
+
143
+ it("returns properly typed child instance", function () {
144
+ const result: TestButton = TestWidget.create(TestButton, { text: "Typed" });
145
+ assert.ok(result instanceof TestButton);
146
+ });
147
+ });
148
+
149
+ describe("string alias", function () {
150
+ it("creates instance from registered alias", function () {
151
+ const result = Component.create("test-button", { text: "Aliased" });
152
+ assert.ok(result instanceof TestButton);
153
+ assert.equal(result.text, "Aliased");
154
+ });
155
+
156
+ it("throws for unknown alias", function () {
157
+ assert.throws(() => {
158
+ Component.create("unknown-alias");
159
+ }, /Unknown component alias/);
160
+ });
161
+ });
162
+
163
+ describe("plain config object", function () {
164
+ it("creates instance of the class create is called on", function () {
165
+ const result = TestWidget.create({ text: "Plain" });
166
+ assert.ok(result instanceof TestWidget);
167
+ assert.equal(result.text, "Plain");
168
+ });
169
+
170
+ it("works with subclasses", function () {
171
+ const result = TestButton.create({ text: "Sub", onClick: () => {} });
172
+ assert.ok(result instanceof TestButton);
173
+ assert.equal(result.text, "Sub");
174
+ });
175
+ });
176
+
177
+ describe("config array as second argument", function () {
178
+ it("creates array when config is an array", function () {
179
+ const results = Component.create(TestWidget, [{ text: "A" }, { text: "B" }]);
180
+ assert.equal(results.length, 2);
181
+ assert.ok(results[0] instanceof TestWidget);
182
+ assert.ok(results[1] instanceof TestWidget);
183
+ });
184
+ });
185
+
186
+ describe("type inference", function () {
187
+ it("infers config type from class constructor", function () {
188
+ // This is a compile-time check - if it compiles, the types are correct
189
+ const config: ComponentConfigType<typeof TestButton> = {
190
+ text: "Hello",
191
+ onClick: () => {},
192
+ };
193
+ const result = Component.create(TestButton, config);
194
+ assert.ok(result instanceof TestButton);
195
+ });
196
+ });
197
+
198
+ describe("config with type and more argument", function () {
199
+ it("merges config and more parameters", function () {
200
+ const result = Component.create({ type: TestButton, text: "Base" }, { value: 42 });
201
+ assert.ok(result instanceof TestButton);
202
+ assert.equal(result.text, "Base");
203
+ assert.equal(result.value, 42);
204
+ });
205
+
206
+ it("works with $type as well", function () {
207
+ const result = Component.create({ $type: TestButton, text: "Dollar" }, { value: 99 });
208
+ assert.ok(result instanceof TestButton);
209
+ assert.equal(result.text, "Dollar");
210
+ assert.equal(result.value, 99);
211
+ });
212
+ });
213
+
214
+ describe("type in second argument (more)", function () {
215
+ it("should create instance of type specified in second argument", function () {
216
+ const result = TestWidget.create({ text: "hello" }, { type: TestButton });
217
+ assert.ok(result instanceof TestButton);
218
+ assert.equal(result.text, "hello");
219
+ });
220
+
221
+ it("should create instance of $type specified in second argument", function () {
222
+ const result = TestWidget.create({ text: "world" }, { $type: TestButton });
223
+ assert.ok(result instanceof TestButton);
224
+ assert.equal(result.text, "world");
225
+ });
226
+
227
+ it("should work when first argument is an array and second has type", function () {
228
+ const results = Component.create([{ text: "A" }, { text: "B" }], { type: TestButton });
229
+ assert.equal(results.length, 2);
230
+ assert.ok(results[0] instanceof TestButton);
231
+ assert.ok(results[1] instanceof TestButton);
232
+ assert.equal(results[0].text, "A");
233
+ assert.equal(results[1].text, "B");
234
+ });
235
+
236
+ it("should work when type is passed as first arg with array config and type in more", function () {
237
+ const results = Component.create(TestWidget, [{ text: "X" }], { type: TestButton });
238
+ assert.equal(results.length, 1);
239
+ assert.ok(results[0] instanceof TestButton);
240
+ assert.equal(results[0].text, "X");
241
+ });
242
+ });
243
+
244
+ describe("heterogeneous array with type property", function () {
245
+ it("creates array of different component types", function () {
246
+ const results = Component.create([
247
+ { type: TestWidget, text: "Widget" },
248
+ { type: TestButton, text: "Button", onClick: () => {} },
249
+ ]);
250
+ assert.equal(results.length, 2);
251
+ assert.ok(results[0] instanceof TestWidget);
252
+ assert.ok(results[1] instanceof TestButton);
253
+ assert.equal(results[0].text, "Widget");
254
+ assert.equal(results[1].text, "Button");
255
+ });
256
+
257
+ it("returns properly typed tuple", function () {
258
+ const results = Component.create([
259
+ { type: TestWidget, text: "W" },
260
+ { type: TestButton, text: "B" },
261
+ ]);
262
+ // Type check: results[0] should be TestWidget, results[1] should be TestButton
263
+ const widget: TestWidget = results[0];
264
+ const button: TestButton = results[1];
265
+ assert.ok(widget instanceof TestWidget);
266
+ assert.ok(button instanceof TestButton);
267
+ });
268
+ });
269
+
270
+ describe("this-bound create with config", function () {
271
+ it("creates instance when called on specific class", function () {
272
+ const result = TestButton.create({ text: "Bound", onClick: () => {} });
273
+ assert.ok(result instanceof TestButton);
274
+ assert.equal(result.text, "Bound");
275
+ });
276
+
277
+ it("accepts more parameter for additional config", function () {
278
+ const result = TestButton.create({ text: "Main" }, { value: 100 });
279
+ assert.ok(result instanceof TestButton);
280
+ assert.equal(result.text, "Main");
281
+ assert.equal(result.value, 100);
282
+ });
283
+ });
284
+
285
+ describe("this-bound create with array", function () {
286
+ it("creates array of instances when called on specific class", function () {
287
+ const results = TestButton.create([{ text: "A" }, { text: "B" }]);
288
+ assert.equal(results.length, 2);
289
+ assert.ok(results[0] instanceof TestButton);
290
+ assert.ok(results[1] instanceof TestButton);
291
+ });
292
+
293
+ it("accepts more parameter for array", function () {
294
+ const results = TestButton.create([{ text: "X" }, { text: "Y" }], { value: 50 });
295
+ assert.equal(results.length, 2);
296
+ assert.equal(results[0].value, 50);
297
+ assert.equal(results[1].value, 50);
298
+ });
299
+ });
300
+ });
301
+
302
+ describe("Create type", function () {
303
+ // Helper function that accepts Create
304
+ function createComponent<TCtor extends ComponentConstructor>(
305
+ creatable: Create<TCtor>,
306
+ ): ComponentInstanceType<TCtor> {
307
+ return Component.create(creatable as any);
308
+ }
309
+
310
+ it("accepts instance pass-through", function () {
311
+ const widget = new TestWidget({ text: "Instance" });
312
+ const result = createComponent<typeof TestWidget>(widget);
313
+ assert.strictEqual(result, widget);
314
+ });
315
+
316
+ it("accepts constructor", function () {
317
+ const result = createComponent<typeof TestWidget>(TestButton);
318
+ assert.ok(result instanceof TestButton);
319
+ });
320
+
321
+ it("accepts config with type", function () {
322
+ const result = createComponent<typeof TestWidget>({ type: TestButton, text: "Typed" });
323
+ assert.ok(result instanceof TestButton);
324
+ assert.equal(result.text, "Typed");
325
+ });
326
+
327
+ it("accepts config with $type", function () {
328
+ const result = createComponent<typeof TestWidget>({ $type: TestButton, text: "DollarTyped" });
329
+ assert.ok(result instanceof TestButton);
330
+ assert.equal(result.text, "DollarTyped");
331
+ });
332
+ });
333
+
334
+ describe("CreateConfig type safety", function () {
335
+ it("rejects config with type from unrelated class", function () {
336
+ // @ts-expect-error - UnrelatedComponent is not a subclass of TestWidget
337
+ const config: CreateConfig<typeof TestWidget> = { type: UnrelatedComponent, name: "test" };
338
+ });
339
+
340
+ it("rejects config missing required properties", function () {
341
+ // @ts-expect-error - text is required in TestWidgetConfig
342
+ const config: CreateConfig<typeof TestWidget> = { type: TestButton };
343
+ });
344
+
345
+ it("accepts config with type from subclass and required properties", function () {
346
+ const config: CreateConfig<typeof TestWidget> = { type: TestButton, text: "valid" };
347
+ assert.ok(config);
348
+ });
349
+
350
+ it("accepts constructor from subclass", function () {
351
+ const config: CreateConfig<typeof TestWidget> = TestButton;
352
+ assert.ok(config);
353
+ });
354
+ });
355
+
356
+ describe("Create type as property (like Chart.axes)", function () {
357
+ // Simulates how Chart uses Create<typeof Axis> for its axes property
358
+ interface ContainerConfig {
359
+ items?: Record<string, Create<typeof TestWidget>>;
360
+ }
361
+
362
+ it("accepts constructor as property value", function () {
363
+ const config: ContainerConfig = {
364
+ items: {
365
+ a: TestWidget,
366
+ b: TestButton,
367
+ },
368
+ };
369
+ assert.ok(config);
370
+ });
371
+
372
+ it("accepts config with type as property value", function () {
373
+ const config: ContainerConfig = {
374
+ items: {
375
+ a: { type: TestWidget, text: "widget" },
376
+ b: { type: TestButton, text: "button", onClick: () => {} },
377
+ },
378
+ };
379
+ assert.ok(config);
380
+ });
381
+
382
+ it("accepts config with $type as property value", function () {
383
+ const config: ContainerConfig = {
384
+ items: {
385
+ a: { $type: TestWidget, text: "widget" },
386
+ b: { $type: TestButton, text: "button" },
387
+ },
388
+ };
389
+ assert.ok(config);
390
+ });
391
+
392
+ it("accepts instance as property value", function () {
393
+ const config: ContainerConfig = {
394
+ items: {
395
+ a: new TestWidget({ text: "instance" }),
396
+ b: new TestButton({ text: "button" }),
397
+ },
398
+ };
399
+ assert.ok(config);
400
+ });
401
+
402
+ it("accepts config with extra properties", function () {
403
+ const config: ContainerConfig = {
404
+ items: {
405
+ // Extra property (like snapToTicks on NumericAxis)
406
+ a: { type: TestButton, text: "button", onClick: () => {}, value: 42 },
407
+ },
408
+ };
409
+ assert.ok(config);
410
+ });
411
+ });