cx 26.1.1 → 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.
- package/.mocharc.json +5 -5
- package/LICENSE-THIRD-PARTY.md +91 -91
- package/LICENSE.md +7 -7
- package/README.md +46 -46
- package/build/data/ArrayElementView.d.ts +4 -3
- package/build/ui/adapter/ArrayAdapter.js +0 -2
- package/build/ui/adapter/DataAdapter.d.ts +3 -3
- package/build.js +133 -133
- package/dist/manifest.js +826 -826
- package/dist/ui.js +0 -2
- package/package.json +100 -99
- package/src/charts/Bar.scss +28 -28
- package/src/charts/Bar.ts +114 -114
- package/src/charts/BarGraph.scss +28 -28
- package/src/charts/BarGraph.tsx +145 -145
- package/src/charts/BubbleGraph.scss +31 -31
- package/src/charts/BubbleGraph.tsx +165 -165
- package/src/charts/Chart.ts +108 -108
- package/src/charts/ColorMap.ts +150 -150
- package/src/charts/Column.scss +28 -28
- package/src/charts/Column.ts +124 -124
- package/src/charts/ColumnBarBase.tsx +284 -284
- package/src/charts/ColumnBarGraphBase.tsx +229 -229
- package/src/charts/ColumnGraph.scss +29 -29
- package/src/charts/ColumnGraph.tsx +153 -153
- package/src/charts/Grid.ts +5 -5
- package/src/charts/Gridlines.scss +24 -24
- package/src/charts/Gridlines.tsx +88 -88
- package/src/charts/Legend.scss +50 -50
- package/src/charts/Legend.tsx +270 -270
- package/src/charts/LegendEntry.scss +29 -29
- package/src/charts/LegendEntry.tsx +197 -197
- package/src/charts/LineGraph.scss +24 -24
- package/src/charts/LineGraph.tsx +455 -455
- package/src/charts/Marker.scss +43 -43
- package/src/charts/Marker.tsx +483 -483
- package/src/charts/MarkerLine.scss +19 -19
- package/src/charts/MarkerLine.tsx +214 -214
- package/src/charts/MouseTracker.tsx +112 -112
- package/src/charts/Pie.ts +8 -8
- package/src/charts/PieChart.scss +28 -28
- package/src/charts/PieChart.tsx +717 -717
- package/src/charts/PieLabel.tsx +106 -106
- package/src/charts/PieLabelsContainer.ts +68 -68
- package/src/charts/Range.scss +19 -19
- package/src/charts/Range.tsx +318 -318
- package/src/charts/RangeMarker.scss +17 -17
- package/src/charts/RangeMarker.tsx +233 -233
- package/src/charts/ScatterGraph.scss +23 -23
- package/src/charts/ScatterGraph.tsx +245 -245
- package/src/charts/Swimlane.scss +16 -16
- package/src/charts/Swimlane.tsx +195 -195
- package/src/charts/Swimlanes.scss +16 -16
- package/src/charts/Swimlanes.tsx +179 -179
- package/src/charts/axis/Axis.scss +22 -22
- package/src/charts/axis/Axis.tsx +444 -444
- package/src/charts/axis/CategoryAxis.scss +34 -34
- package/src/charts/axis/CategoryAxis.tsx +313 -313
- package/src/charts/axis/NumericAxis.scss +34 -34
- package/src/charts/axis/NumericAxis.tsx +437 -437
- package/src/charts/axis/Stack.ts +61 -61
- package/src/charts/axis/TimeAxis.scss +33 -33
- package/src/charts/axis/TimeAxis.tsx +718 -718
- package/src/charts/axis/index.scss +5 -5
- package/src/charts/axis/index.ts +3 -3
- package/src/charts/axis/variables.scss +2 -2
- package/src/charts/helpers/MinMaxFinder.ts +66 -66
- package/src/charts/helpers/PointReducer.ts +135 -135
- package/src/charts/helpers/SnapPointFinder.ts +136 -136
- package/src/charts/helpers/ValueAtFinder.ts +72 -72
- package/src/charts/helpers/index.ts +4 -4
- package/src/charts/index.scss +22 -22
- package/src/charts/index.ts +34 -34
- package/src/charts/palette.scss +97 -97
- package/src/charts/shapes.tsx +86 -86
- package/src/charts/variables.scss +22 -22
- package/src/core.d.ts +182 -182
- package/src/data/AggregateFunction.ts +171 -171
- package/src/data/ArrayElementView.spec.ts +88 -88
- package/src/data/ArrayElementView.ts +91 -90
- package/src/data/ArrayRef.ts +34 -34
- package/src/data/AugmentedViewBase.ts +88 -88
- package/src/data/Binding.spec.ts +69 -69
- package/src/data/Binding.ts +104 -104
- package/src/data/ExposedRecordView.ts +95 -95
- package/src/data/ExposedValueView.ts +89 -89
- package/src/data/Expression.spec.ts +229 -229
- package/src/data/Expression.ts +233 -233
- package/src/data/Grouper.spec.ts +57 -57
- package/src/data/Grouper.ts +158 -158
- package/src/data/NestedDataView.ts +43 -43
- package/src/data/ReadOnlyDataView.ts +39 -39
- package/src/data/Ref.spec.ts +79 -79
- package/src/data/Ref.ts +104 -104
- package/src/data/Selector.ts +10 -10
- package/src/data/Store.spec.ts +22 -22
- package/src/data/Store.ts +52 -52
- package/src/data/StoreProxy.ts +19 -19
- package/src/data/StoreRef.spec.ts +24 -24
- package/src/data/StoreRef.ts +66 -66
- package/src/data/StringTemplate.spec.ts +132 -132
- package/src/data/StringTemplate.ts +93 -93
- package/src/data/StructuredSelector.spec.ts +113 -113
- package/src/data/StructuredSelector.ts +146 -146
- package/src/data/SubscribableView.ts +63 -63
- package/src/data/View.spec.ts +60 -60
- package/src/data/View.ts +289 -289
- package/src/data/ZoomIntoPropertyView.spec.ts +64 -64
- package/src/data/ZoomIntoPropertyView.ts +45 -45
- package/src/data/comparer.spec.ts +60 -60
- package/src/data/comparer.ts +78 -78
- package/src/data/computable.spec.ts +87 -87
- package/src/data/computable.ts +69 -69
- package/src/data/createAccessorModelProxy.spec.tsx +145 -145
- package/src/data/createAccessorModelProxy.ts +66 -66
- package/src/data/createStructuredSelector.spec.ts +45 -45
- package/src/data/createStructuredSelector.ts +62 -62
- package/src/data/defaultCompare.ts +14 -14
- package/src/data/diff/diffArrays.ts +49 -49
- package/src/data/diff/diffs.spec.ts +49 -49
- package/src/data/diff/index.ts +1 -1
- package/src/data/enableFatArrowExpansion.ts +6 -6
- package/src/data/getAccessor.spec.ts +11 -11
- package/src/data/getAccessor.ts +74 -74
- package/src/data/getSelector.spec.ts +43 -43
- package/src/data/getSelector.ts +66 -66
- package/src/data/index.ts +30 -30
- package/src/data/isSelector.ts +26 -26
- package/src/data/ops/append.spec.ts +28 -28
- package/src/data/ops/append.ts +5 -5
- package/src/data/ops/filter.spec.ts +35 -35
- package/src/data/ops/filter.ts +9 -9
- package/src/data/ops/findTreeNode.spec.ts +23 -23
- package/src/data/ops/findTreeNode.ts +14 -14
- package/src/data/ops/findTreePath.ts +23 -23
- package/src/data/ops/index.ts +11 -11
- package/src/data/ops/insertElement.ts +3 -3
- package/src/data/ops/merge.spec.ts +27 -27
- package/src/data/ops/merge.ts +13 -13
- package/src/data/ops/moveElement.ts +21 -21
- package/src/data/ops/removeTreeNodes.spec.ts +37 -37
- package/src/data/ops/removeTreeNodes.ts +15 -15
- package/src/data/ops/updateArray.spec.ts +69 -69
- package/src/data/ops/updateArray.ts +31 -31
- package/src/data/ops/updateTree.spec.ts +54 -54
- package/src/data/ops/updateTree.ts +23 -23
- package/src/data/test-types.ts +7 -7
- package/src/global.scss +13 -13
- package/src/hooks/createLocalStorageRef.ts +21 -21
- package/src/hooks/index.ts +8 -8
- package/src/hooks/invokeCallback.spec.tsx +59 -59
- package/src/hooks/invokeCallback.ts +8 -8
- package/src/hooks/resolveCallback.spec.tsx +71 -71
- package/src/hooks/resolveCallback.ts +16 -16
- package/src/hooks/store.spec.tsx +67 -67
- package/src/hooks/store.ts +46 -46
- package/src/hooks/useEffect.ts +14 -14
- package/src/hooks/useInterval.ts +8 -8
- package/src/hooks/useState.ts +20 -20
- package/src/hooks/useTrigger.spec.tsx +105 -105
- package/src/hooks/useTrigger.ts +26 -26
- package/src/index.ts +7 -7
- package/src/jsx-dev-runtime.ts +4 -4
- package/src/jsx-runtime.spec.tsx +431 -431
- package/src/jsx-runtime.ts +79 -79
- package/src/locale/de-de.ts +76 -76
- package/src/locale/en-us.ts +75 -75
- package/src/locale/es-es.ts +76 -76
- package/src/locale/fr-fr.ts +76 -76
- package/src/locale/nl-nl.ts +76 -76
- package/src/locale/pt-pt.ts +76 -76
- package/src/locale/sr-latn-ba.ts +76 -76
- package/src/svg/BoundedObject.ts +101 -101
- package/src/svg/ClipRect.tsx +29 -29
- package/src/svg/Ellipse.tsx +68 -68
- package/src/svg/Line.tsx +58 -58
- package/src/svg/NonOverlappingRect.ts +26 -26
- package/src/svg/NonOverlappingRectGroup.ts +49 -49
- package/src/svg/Rectangle.tsx +90 -90
- package/src/svg/Svg.scss +27 -27
- package/src/svg/Svg.tsx +241 -241
- package/src/svg/Text.tsx +134 -134
- package/src/svg/TextualBoundedObject.ts +35 -35
- package/src/svg/index.scss +8 -8
- package/src/svg/index.ts +17 -17
- package/src/svg/util/Rect.ts +105 -105
- package/src/ui/CSS.ts +87 -87
- package/src/ui/CSSHelper.ts +17 -17
- package/src/ui/Container.tsx +216 -216
- package/src/ui/ContentResolver.spec.tsx +585 -585
- package/src/ui/ContentResolver.ts +132 -132
- package/src/ui/Controller.spec.tsx +574 -574
- package/src/ui/Controller.ts +202 -202
- package/src/ui/Culture.ts +159 -159
- package/src/ui/Cx.spec.tsx +210 -210
- package/src/ui/Cx.tsx +386 -386
- package/src/ui/DataProxy.spec.tsx +337 -337
- package/src/ui/DataProxy.ts +55 -55
- package/src/ui/DetachedScope.tsx +159 -159
- package/src/ui/FocusManager.ts +171 -171
- package/src/ui/Format.ts +108 -108
- package/src/ui/HoverSync.tsx +189 -189
- package/src/ui/Instance.ts +866 -866
- package/src/ui/IsolatedScope.spec.tsx +62 -62
- package/src/ui/IsolatedScope.ts +50 -50
- package/src/ui/Localization.ts +70 -70
- package/src/ui/Prop.ts +140 -140
- package/src/ui/PureContainer.spec.tsx +232 -232
- package/src/ui/PureContainer.tsx +19 -19
- package/src/ui/RenderingContext.ts +99 -99
- package/src/ui/Repeater.spec.tsx +143 -143
- package/src/ui/Repeater.ts +194 -194
- package/src/ui/Rescope.spec.tsx +199 -199
- package/src/ui/Rescope.ts +49 -49
- package/src/ui/ResizeManager.ts +30 -30
- package/src/ui/Restate.spec.tsx +422 -422
- package/src/ui/Restate.tsx +217 -217
- package/src/ui/StaticText.ts +11 -11
- package/src/ui/StructuredInstanceDataAccessor.ts +32 -32
- package/src/ui/Text.ts +49 -49
- package/src/ui/VDOM.ts +1 -1
- package/src/ui/Widget.spec.tsx +53 -53
- package/src/ui/Widget.tsx +301 -301
- package/src/ui/ZIndexManager.ts +11 -11
- package/src/ui/adapter/ArrayAdapter.spec.ts +55 -55
- package/src/ui/adapter/ArrayAdapter.ts +229 -229
- package/src/ui/adapter/DataAdapter.ts +52 -52
- package/src/ui/adapter/GroupAdapter.ts +235 -235
- package/src/ui/adapter/TreeAdapter.spec.ts +76 -76
- package/src/ui/adapter/TreeAdapter.ts +185 -185
- package/src/ui/adapter/index.ts +4 -4
- package/src/ui/app/History.ts +133 -133
- package/src/ui/app/Url.spec.ts +50 -50
- package/src/ui/app/Url.ts +102 -102
- package/src/ui/app/index.ts +5 -5
- package/src/ui/app/startAppLoop.tsx +71 -71
- package/src/ui/app/startHotAppLoop.ts +41 -41
- package/src/ui/batchUpdates.ts +77 -77
- package/src/ui/bind.ts +10 -10
- package/src/ui/createFunctionalComponent.spec.tsx +454 -454
- package/src/ui/createFunctionalComponent.ts +86 -86
- package/src/ui/expr.ts +47 -47
- package/src/ui/exprHelpers.spec.ts +379 -379
- package/src/ui/exprHelpers.ts +78 -78
- package/src/ui/flattenProps.ts +21 -21
- package/src/ui/index.scss +2 -2
- package/src/ui/index.ts +47 -47
- package/src/ui/keyboardShortcuts.ts +40 -40
- package/src/ui/layout/Content.ts +30 -30
- package/src/ui/layout/ContentPlaceholder.spec.tsx +599 -599
- package/src/ui/layout/ContentPlaceholder.ts +133 -133
- package/src/ui/layout/FirstVisibleChildLayout.spec.tsx +207 -207
- package/src/ui/layout/FirstVisibleChildLayout.ts +60 -60
- package/src/ui/layout/LabelsLeftLayout.scss +46 -46
- package/src/ui/layout/LabelsLeftLayout.tsx +76 -76
- package/src/ui/layout/LabelsTopLayout.scss +64 -64
- package/src/ui/layout/LabelsTopLayout.tsx +156 -156
- package/src/ui/layout/UseParentLayout.ts +8 -8
- package/src/ui/layout/exploreChildren.ts +38 -38
- package/src/ui/layout/index.scss +3 -3
- package/src/ui/layout/index.ts +10 -10
- package/src/ui/layout/variables.scss +2 -2
- package/src/ui/selection/KeySelection.ts +153 -153
- package/src/ui/selection/PropertySelection.ts +87 -87
- package/src/ui/selection/Selection.ts +128 -128
- package/src/ui/selection/index.ts +3 -3
- package/src/ui/tpl.ts +4 -4
- package/src/ui/variables.scss +1 -1
- package/src/util/Component.spec.ts +411 -411
- package/src/util/Console.ts +13 -13
- package/src/util/DOM.ts +88 -88
- package/src/util/Debug.ts +71 -71
- package/src/util/Format.spec.ts +69 -69
- package/src/util/Format.ts +267 -267
- package/src/util/GlobalCacheIdentifier.ts +11 -11
- package/src/util/KeyCode.ts +21 -21
- package/src/util/SubscriberList.ts +86 -86
- package/src/util/Timing.ts +58 -58
- package/src/util/TraversalStack.spec.ts +53 -53
- package/src/util/TraversalStack.ts +47 -47
- package/src/util/addEventListenerWithOptions.ts +41 -41
- package/src/util/browserSupportsPassiveEventHandlers.ts +20 -20
- package/src/util/calculateNaturalElementHeight.ts +22 -22
- package/src/util/call-once.scss +6 -6
- package/src/util/capitalize.ts +4 -4
- package/src/util/coalesce.ts +6 -6
- package/src/util/color/hslToRgb.ts +34 -34
- package/src/util/color/index.ts +4 -4
- package/src/util/color/parseColor.ts +173 -173
- package/src/util/color/rgbToHex.ts +14 -14
- package/src/util/color/rgbToHsl.ts +35 -35
- package/src/util/date/dateDiff.ts +9 -9
- package/src/util/date/diff.ts +13 -13
- package/src/util/date/encodeDate.ts +8 -8
- package/src/util/date/encodeDateWithTimezoneOffset.ts +18 -18
- package/src/util/date/index.ts +11 -11
- package/src/util/date/lowerBoundCheck.ts +13 -13
- package/src/util/date/maxDate.ts +14 -14
- package/src/util/date/minDate.ts +14 -14
- package/src/util/date/monthStart.ts +8 -8
- package/src/util/date/parseDateInvariant.ts +20 -20
- package/src/util/date/sameDate.ts +11 -11
- package/src/util/date/upperBoundCheck.spec.ts +30 -30
- package/src/util/date/upperBoundCheck.ts +13 -13
- package/src/util/date/zeroTime.ts +9 -9
- package/src/util/debounce.ts +26 -26
- package/src/util/dummyCallback.ts +1 -1
- package/src/util/escapeSpecialRegexCharacters.ts +8 -8
- package/src/util/eventCallbacks.ts +12 -12
- package/src/util/expandFatArrows.ts +118 -118
- package/src/util/findScrollableParent.ts +15 -15
- package/src/util/getActiveElement.ts +4 -4
- package/src/util/getParentFrameBoundingClientRect.ts +13 -13
- package/src/util/getScrollerBoundingClientRect.ts +12 -12
- package/src/util/getSearchQueryPredicate.spec.ts +40 -40
- package/src/util/getSearchQueryPredicate.ts +58 -58
- package/src/util/getTopLevelBoundingClientRect.ts +7 -7
- package/src/util/getVendorPrefix.ts +33 -33
- package/src/util/hasKey.ts +18 -18
- package/src/util/index.scss +10 -10
- package/src/util/index.ts +55 -55
- package/src/util/innerTextTrim.ts +10 -10
- package/src/util/isArray.ts +3 -3
- package/src/util/isDataRecord.ts +5 -5
- package/src/util/isDefined.ts +3 -3
- package/src/util/isDigit.ts +8 -8
- package/src/util/isFunction.ts +3 -3
- package/src/util/isNonEmptyArray.ts +3 -3
- package/src/util/isNumber.ts +3 -3
- package/src/util/isObject.ts +3 -3
- package/src/util/isPromise.ts +6 -6
- package/src/util/isString.ts +3 -3
- package/src/util/isTextInputElement.ts +2 -2
- package/src/util/isTouchDevice.ts +7 -7
- package/src/util/isTouchEvent.ts +64 -64
- package/src/util/isUndefined.ts +3 -3
- package/src/util/isValidIdentifierName.spec.ts +33 -33
- package/src/util/isValidIdentifierName.ts +5 -5
- package/src/util/onIdleCallback.ts +10 -10
- package/src/util/parseStyle.ts +29 -29
- package/src/util/quote.ts +6 -6
- package/src/util/reverseSlice.ts +9 -9
- package/src/util/routeAppend.spec.ts +19 -19
- package/src/util/routeAppend.ts +15 -15
- package/src/util/scrollElementIntoView.ts +40 -40
- package/src/util/scss/add-rules.scss +40 -40
- package/src/util/scss/calc.scss +44 -44
- package/src/util/scss/call-once.scss +12 -12
- package/src/util/scss/clockwise.scss +49 -49
- package/src/util/scss/colors.scss +9 -9
- package/src/util/scss/deep-get.scss +11 -11
- package/src/util/scss/deep-merge.scss +21 -21
- package/src/util/scss/divide.scss +3 -3
- package/src/util/scss/include.scss +48 -48
- package/src/util/scss/index.scss +9 -9
- package/src/util/shallowEquals.ts +43 -43
- package/src/util/test/createTestRenderer.tsx +19 -19
- package/src/util/throttle.ts +21 -21
- package/src/util/validatedDebounce.ts +23 -23
- package/src/variables.scss +217 -217
- package/src/widgets/AccessorBindings.spec.tsx +90 -90
- package/src/widgets/Button.scss +119 -119
- package/src/widgets/Button.tsx +189 -189
- package/src/widgets/Button.variables.scss +117 -117
- package/src/widgets/CxCredit.scss +39 -39
- package/src/widgets/CxCredit.tsx +46 -46
- package/src/widgets/DocumentTitle.ts +95 -95
- package/src/widgets/FlexBox.scss +148 -148
- package/src/widgets/FlexBox.tsx +168 -168
- package/src/widgets/Heading.scss +40 -40
- package/src/widgets/Heading.ts +42 -42
- package/src/widgets/HighlightedSearchText.scss +20 -20
- package/src/widgets/HighlightedSearchText.tsx +54 -54
- package/src/widgets/HtmlElement.spec.helpers.tsx +108 -108
- package/src/widgets/HtmlElement.spec.tsx +89 -89
- package/src/widgets/HtmlElement.tsx +407 -407
- package/src/widgets/Icon.scss +22 -22
- package/src/widgets/Icon.ts +64 -64
- package/src/widgets/List.scss +93 -93
- package/src/widgets/List.tsx +793 -793
- package/src/widgets/ProgressBar.scss +50 -50
- package/src/widgets/ProgressBar.tsx +66 -66
- package/src/widgets/ReactElementWrapper.spec.tsx +452 -452
- package/src/widgets/ReactElementWrapper.tsx +108 -108
- package/src/widgets/Resizer.scss +43 -43
- package/src/widgets/Resizer.tsx +200 -200
- package/src/widgets/Sandbox.ts +103 -103
- package/src/widgets/Section.scss +55 -55
- package/src/widgets/Section.tsx +187 -187
- package/src/widgets/animations.scss +10 -10
- package/src/widgets/autoFocus.ts +9 -9
- package/src/widgets/cx.ts +63 -63
- package/src/widgets/drag-drop/DragClone.scss +35 -35
- package/src/widgets/drag-drop/DragHandle.scss +18 -18
- package/src/widgets/drag-drop/DragHandle.tsx +47 -47
- package/src/widgets/drag-drop/DragSource.scss +26 -26
- package/src/widgets/drag-drop/DragSource.tsx +237 -237
- package/src/widgets/drag-drop/DropZone.scss +76 -76
- package/src/widgets/drag-drop/DropZone.tsx +353 -353
- package/src/widgets/drag-drop/index.scss +3 -3
- package/src/widgets/drag-drop/index.ts +4 -4
- package/src/widgets/drag-drop/ops.tsx +422 -422
- package/src/widgets/drag-drop/variables.scss +14 -14
- package/src/widgets/enableAllInternalDependencies.ts +11 -11
- package/src/widgets/form/Calendar.scss +199 -199
- package/src/widgets/form/Calendar.tsx +760 -760
- package/src/widgets/form/Calendar.variables.scss +63 -63
- package/src/widgets/form/Checkbox.scss +129 -129
- package/src/widgets/form/Checkbox.tsx +287 -287
- package/src/widgets/form/Checkbox.variables.scss +39 -39
- package/src/widgets/form/ColorField.scss +98 -98
- package/src/widgets/form/ColorField.tsx +497 -497
- package/src/widgets/form/ColorPicker.scss +285 -285
- package/src/widgets/form/ColorPicker.tsx +544 -544
- package/src/widgets/form/ColorPicker.variables.scss +22 -22
- package/src/widgets/form/DateField.ts +21 -21
- package/src/widgets/form/DateTimeField.scss +92 -92
- package/src/widgets/form/DateTimeField.tsx +726 -726
- package/src/widgets/form/DateTimePicker.scss +46 -46
- package/src/widgets/form/DateTimePicker.tsx +429 -429
- package/src/widgets/form/Field.scss +164 -164
- package/src/widgets/form/Field.tsx +608 -608
- package/src/widgets/form/FieldGroup.ts +10 -10
- package/src/widgets/form/FieldIcon.ts +61 -61
- package/src/widgets/form/HelpText.scss +24 -24
- package/src/widgets/form/HelpText.ts +15 -15
- package/src/widgets/form/Label.scss +37 -37
- package/src/widgets/form/Label.tsx +117 -117
- package/src/widgets/form/LabeledContainer.ts +77 -77
- package/src/widgets/form/LookupField.scss +221 -221
- package/src/widgets/form/LookupField.spec.tsx +93 -93
- package/src/widgets/form/LookupField.tsx +1421 -1421
- package/src/widgets/form/MonthField.scss +100 -100
- package/src/widgets/form/MonthField.tsx +670 -670
- package/src/widgets/form/MonthPicker.scss +125 -125
- package/src/widgets/form/MonthPicker.tsx +822 -822
- package/src/widgets/form/NumberField.scss +63 -63
- package/src/widgets/form/NumberField.tsx +543 -543
- package/src/widgets/form/Radio.scss +123 -123
- package/src/widgets/form/Radio.tsx +249 -249
- package/src/widgets/form/Radio.variables.scss +45 -45
- package/src/widgets/form/Select.scss +101 -101
- package/src/widgets/form/Select.tsx +327 -327
- package/src/widgets/form/Slider.scss +121 -121
- package/src/widgets/form/Slider.tsx +473 -473
- package/src/widgets/form/Switch.scss +142 -142
- package/src/widgets/form/Switch.tsx +176 -176
- package/src/widgets/form/TextArea.scss +45 -45
- package/src/widgets/form/TextArea.tsx +229 -229
- package/src/widgets/form/TextField.scss +57 -57
- package/src/widgets/form/TextField.tsx +407 -407
- package/src/widgets/form/TimeField.ts +10 -10
- package/src/widgets/form/TimeList.tsx +105 -105
- package/src/widgets/form/UploadButton.scss +49 -49
- package/src/widgets/form/UploadButton.tsx +307 -307
- package/src/widgets/form/ValidationError.scss +22 -22
- package/src/widgets/form/ValidationError.tsx +72 -72
- package/src/widgets/form/ValidationGroup.spec.tsx +147 -147
- package/src/widgets/form/ValidationGroup.ts +141 -141
- package/src/widgets/form/Validator.ts +60 -60
- package/src/widgets/form/Wheel.scss +152 -152
- package/src/widgets/form/Wheel.tsx +314 -314
- package/src/widgets/form/index.scss +24 -24
- package/src/widgets/form/index.ts +28 -28
- package/src/widgets/form/variables.scss +355 -355
- package/src/widgets/grid/Grid.scss +640 -640
- package/src/widgets/grid/Grid.tsx +4243 -4243
- package/src/widgets/grid/GridCell.ts +143 -143
- package/src/widgets/grid/GridCellEditor.tsx +58 -58
- package/src/widgets/grid/GridRow.ts +302 -302
- package/src/widgets/grid/GridRowLine.ts +49 -49
- package/src/widgets/grid/Pagination.scss +115 -115
- package/src/widgets/grid/Pagination.tsx +126 -126
- package/src/widgets/grid/TreeNode.scss +90 -90
- package/src/widgets/grid/TreeNode.tsx +154 -154
- package/src/widgets/grid/createGridCellEditor.tsx +18 -18
- package/src/widgets/grid/index.scss +3 -3
- package/src/widgets/grid/index.ts +16 -16
- package/src/widgets/grid/variables.scss +137 -137
- package/src/widgets/icons/arrow-down.svg +3 -3
- package/src/widgets/icons/arrow-right.svg +2 -2
- package/src/widgets/icons/base.svg +104 -104
- package/src/widgets/icons/calendar-old.svg +169 -169
- package/src/widgets/icons/calendar.svg +187 -187
- package/src/widgets/icons/calendar.tsx +22 -22
- package/src/widgets/icons/check.tsx +14 -14
- package/src/widgets/icons/clear.svg +74 -74
- package/src/widgets/icons/clear.tsx +16 -16
- package/src/widgets/icons/close.svg +74 -74
- package/src/widgets/icons/close.tsx +20 -20
- package/src/widgets/icons/cx.tsx +39 -39
- package/src/widgets/icons/drop-down.tsx +16 -16
- package/src/widgets/icons/dropdown-arrow.svg +61 -61
- package/src/widgets/icons/file.svg +4 -4
- package/src/widgets/icons/file.tsx +14 -14
- package/src/widgets/icons/folder-open.svg +5 -5
- package/src/widgets/icons/folder-open.tsx +16 -16
- package/src/widgets/icons/folder.svg +58 -58
- package/src/widgets/icons/folder.tsx +14 -14
- package/src/widgets/icons/forward.svg +67 -67
- package/src/widgets/icons/forward.tsx +23 -23
- package/src/widgets/icons/index.ts +14 -14
- package/src/widgets/icons/loading.svg +4 -4
- package/src/widgets/icons/loading.tsx +25 -25
- package/src/widgets/icons/menu.tsx +18 -18
- package/src/widgets/icons/pixel-picker.tsx +18 -18
- package/src/widgets/icons/registry.ts +56 -56
- package/src/widgets/icons/search.svg +107 -107
- package/src/widgets/icons/search.tsx +14 -14
- package/src/widgets/icons/sort-asc.svg +3 -3
- package/src/widgets/icons/sort-asc.tsx +15 -15
- package/src/widgets/icons/square.tsx +19 -19
- package/src/widgets/index.d.ts +55 -55
- package/src/widgets/index.scss +16 -16
- package/src/widgets/index.ts +58 -58
- package/src/widgets/nav/Link.scss +20 -20
- package/src/widgets/nav/Link.ts +11 -11
- package/src/widgets/nav/LinkButton.ts +176 -176
- package/src/widgets/nav/Menu.scss +76 -76
- package/src/widgets/nav/Menu.tsx +489 -489
- package/src/widgets/nav/Menu.variables.scss +25 -25
- package/src/widgets/nav/MenuItem.scss +130 -130
- package/src/widgets/nav/MenuItem.tsx +525 -525
- package/src/widgets/nav/MenuSpacer.ts +18 -18
- package/src/widgets/nav/RedirectRoute.ts +49 -49
- package/src/widgets/nav/Route.spec.tsx +24 -24
- package/src/widgets/nav/Route.ts +142 -142
- package/src/widgets/nav/Scroller.scss +148 -148
- package/src/widgets/nav/Scroller.tsx +252 -252
- package/src/widgets/nav/Submenu.ts +6 -6
- package/src/widgets/nav/Tab.scss +82 -82
- package/src/widgets/nav/Tab.ts +120 -120
- package/src/widgets/nav/Tab.variables.scss +84 -84
- package/src/widgets/nav/cover.scss +22 -22
- package/src/widgets/nav/index.scss +5 -5
- package/src/widgets/nav/index.ts +10 -10
- package/src/widgets/nav/variables.scss +27 -27
- package/src/widgets/overlay/ContextMenu.ts +42 -42
- package/src/widgets/overlay/Dropdown.scss +186 -186
- package/src/widgets/overlay/Dropdown.tsx +762 -762
- package/src/widgets/overlay/FlyweightTooltipTracker.ts +57 -57
- package/src/widgets/overlay/MsgBox.tsx +141 -141
- package/src/widgets/overlay/Overlay.scss +68 -68
- package/src/widgets/overlay/Overlay.tsx +947 -947
- package/src/widgets/overlay/Toast.scss +163 -163
- package/src/widgets/overlay/Toast.ts +111 -111
- package/src/widgets/overlay/Tooltip.scss +177 -177
- package/src/widgets/overlay/Tooltip.tsx +393 -393
- package/src/widgets/overlay/Window.scss +129 -129
- package/src/widgets/overlay/Window.tsx +299 -299
- package/src/widgets/overlay/Window.variables.scss +62 -62
- package/src/widgets/overlay/alerts.ts +46 -46
- package/src/widgets/overlay/captureMouse.scss +13 -13
- package/src/widgets/overlay/captureMouse.ts +195 -195
- package/src/widgets/overlay/createHotPromiseWindowFactory.ts +71 -71
- package/src/widgets/overlay/index.scss +15 -15
- package/src/widgets/overlay/index.ts +11 -11
- package/src/widgets/overlay/tooltip-ops.ts +173 -173
- package/src/widgets/overlay/variables.scss +85 -85
- package/src/widgets/variables.scss +146 -146
- package/tsconfig.compile.json +4 -4
- package/tsconfig.json +34 -34
- package/tsconfig.mocha.json +14 -14
|
@@ -1,574 +1,574 @@
|
|
|
1
|
-
import { Store } from "../data/Store";
|
|
2
|
-
import { Controller, ControllerConfig } from "./Controller";
|
|
3
|
-
import { createTestRenderer, act } from "../util/test/createTestRenderer";
|
|
4
|
-
import { VDOM, Widget, WidgetConfig } from "./Widget";
|
|
5
|
-
import { Instance } from "./Instance";
|
|
6
|
-
import { bind } from "./bind";
|
|
7
|
-
import assert from "assert";
|
|
8
|
-
import { RenderingContext } from "./RenderingContext";
|
|
9
|
-
|
|
10
|
-
describe("Controller", () => {
|
|
11
|
-
it("invokes lifetime methods", async () => {
|
|
12
|
-
let init = 0,
|
|
13
|
-
prepare = 0,
|
|
14
|
-
explore = 0,
|
|
15
|
-
cleanup = 0;
|
|
16
|
-
|
|
17
|
-
class TestController extends Controller {
|
|
18
|
-
onInit() {
|
|
19
|
-
init++;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
onExplore() {
|
|
23
|
-
explore++;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
onPrepare() {
|
|
27
|
-
prepare++;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
onCleanup() {
|
|
31
|
-
cleanup++;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
let store = new Store();
|
|
36
|
-
|
|
37
|
-
const component = await createTestRenderer(
|
|
38
|
-
store,
|
|
39
|
-
<cx>
|
|
40
|
-
<div controller={TestController} />
|
|
41
|
-
</cx>,
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
let tree = component.toJSON();
|
|
45
|
-
assert.equal(init, 1);
|
|
46
|
-
assert.equal(explore, 1);
|
|
47
|
-
assert.equal(prepare, 1);
|
|
48
|
-
assert.equal(cleanup, 1);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("widgets invoke controller methods specified as strings", async () => {
|
|
52
|
-
let callback = 0;
|
|
53
|
-
|
|
54
|
-
class TestController extends Controller {
|
|
55
|
-
callback() {
|
|
56
|
-
++callback;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
interface CmpConfig extends WidgetConfig {
|
|
61
|
-
onTest: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
class Cmp extends Widget<CmpConfig> {
|
|
65
|
-
render(context: RenderingContext, instance: Instance, key: string) {
|
|
66
|
-
instance.invoke("onTest");
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let store = new Store();
|
|
72
|
-
|
|
73
|
-
const component = await createTestRenderer(
|
|
74
|
-
store,
|
|
75
|
-
<cx>
|
|
76
|
-
<Cmp controller={TestController} onTest="callback" />
|
|
77
|
-
</cx>,
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
let tree = component.toJSON();
|
|
81
|
-
assert.equal(callback, 1);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("widgets can access controller methods specified in ancestor controllers", async () => {
|
|
85
|
-
let callback1 = 0;
|
|
86
|
-
let callback2 = 0;
|
|
87
|
-
|
|
88
|
-
class TestController1 extends Controller {
|
|
89
|
-
callback1() {
|
|
90
|
-
++callback1;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
class TestController2 extends Controller {
|
|
95
|
-
callback2() {
|
|
96
|
-
++callback2;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface CmpConfig extends WidgetConfig {
|
|
101
|
-
onTest: string;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
class Cmp extends Widget<CmpConfig> {
|
|
105
|
-
render(context: RenderingContext, instance: Instance, key: string) {
|
|
106
|
-
instance.invoke("onTest");
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let store = new Store();
|
|
112
|
-
|
|
113
|
-
const component = await createTestRenderer(
|
|
114
|
-
store,
|
|
115
|
-
<cx>
|
|
116
|
-
<div controller={TestController1}>
|
|
117
|
-
<Cmp controller={TestController2} onTest="callback1" />
|
|
118
|
-
</div>
|
|
119
|
-
</cx>,
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
let tree = component.toJSON();
|
|
123
|
-
assert.equal(callback1, 1);
|
|
124
|
-
assert.equal(callback2, 0);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("ancestor controllers are initialized first", async () => {
|
|
128
|
-
let order: string[] = [];
|
|
129
|
-
|
|
130
|
-
class TestController1 extends Controller {
|
|
131
|
-
onInit() {
|
|
132
|
-
order.push("1");
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
class TestController2 extends Controller {
|
|
137
|
-
onInit() {
|
|
138
|
-
order.push("2");
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
let store = new Store();
|
|
143
|
-
|
|
144
|
-
const component = await createTestRenderer(
|
|
145
|
-
store,
|
|
146
|
-
<cx>
|
|
147
|
-
<div controller={TestController1}>
|
|
148
|
-
<div controller={TestController2} />
|
|
149
|
-
</div>
|
|
150
|
-
</cx>,
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
let tree = component.toJSON();
|
|
154
|
-
assert.deepEqual(order, ["1", "2"]);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("controllers on invisible elements are not initialized", async () => {
|
|
158
|
-
let order: string[] = [];
|
|
159
|
-
|
|
160
|
-
class TestController1 extends Controller {
|
|
161
|
-
onInit() {
|
|
162
|
-
order.push("1");
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
class TestController2 extends Controller {
|
|
167
|
-
onInit() {
|
|
168
|
-
order.push("2");
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
let store = new Store();
|
|
173
|
-
|
|
174
|
-
const component = await createTestRenderer(
|
|
175
|
-
store,
|
|
176
|
-
<cx>
|
|
177
|
-
<div controller={TestController1}>
|
|
178
|
-
<div visible={false} controller={TestController2} />
|
|
179
|
-
</div>
|
|
180
|
-
</cx>,
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
let tree = component.toJSON();
|
|
184
|
-
assert.deepEqual(order, ["1"]);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("invokes triggers and computables in order of definition", async () => {
|
|
188
|
-
let log: string[] = [];
|
|
189
|
-
|
|
190
|
-
class TestController extends Controller {
|
|
191
|
-
onInit() {
|
|
192
|
-
this.addTrigger(
|
|
193
|
-
"t1",
|
|
194
|
-
[],
|
|
195
|
-
() => {
|
|
196
|
-
log.push("t1");
|
|
197
|
-
},
|
|
198
|
-
true,
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
this.addComputable("c1", [], () => {
|
|
202
|
-
log.push("c1");
|
|
203
|
-
return null;
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
this.addTrigger(
|
|
207
|
-
"t2",
|
|
208
|
-
[],
|
|
209
|
-
() => {
|
|
210
|
-
log.push("t2");
|
|
211
|
-
},
|
|
212
|
-
true,
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
let store = new Store();
|
|
218
|
-
|
|
219
|
-
const component = await createTestRenderer(
|
|
220
|
-
store,
|
|
221
|
-
<cx>
|
|
222
|
-
<div controller={TestController} />
|
|
223
|
-
</cx>,
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
let tree = component.toJSON();
|
|
227
|
-
assert.deepEqual(log, ["t1", "c1", "t2"]);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("is recreated if a component is hidden and shown", async () => {
|
|
231
|
-
let initCount = 0;
|
|
232
|
-
|
|
233
|
-
class TestController extends Controller {
|
|
234
|
-
onInit() {
|
|
235
|
-
initCount++;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
let store = new Store();
|
|
240
|
-
store.set("visible", true);
|
|
241
|
-
|
|
242
|
-
const component = await createTestRenderer(
|
|
243
|
-
store,
|
|
244
|
-
<cx>
|
|
245
|
-
<div visible={bind("visible")} controller={TestController} />
|
|
246
|
-
</cx>,
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
let tree1 = component.toJSON();
|
|
250
|
-
assert.equal(initCount, 1);
|
|
251
|
-
|
|
252
|
-
await act(async () => {
|
|
253
|
-
store.set("visible", false);
|
|
254
|
-
});
|
|
255
|
-
let tree2 = component.toJSON();
|
|
256
|
-
assert.equal(tree2, null);
|
|
257
|
-
|
|
258
|
-
await act(async () => {
|
|
259
|
-
store.set("visible", true);
|
|
260
|
-
});
|
|
261
|
-
let tree3 = component.toJSON();
|
|
262
|
-
assert.equal(initCount, 2);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it("allows creation through a factory", () => {
|
|
266
|
-
let store = new Store({ data: { x: 0 } });
|
|
267
|
-
|
|
268
|
-
const controllerFactory = ({ store }: { store: Store }) => {
|
|
269
|
-
return {
|
|
270
|
-
increment() {
|
|
271
|
-
store.update("x", (x: number) => x + 1);
|
|
272
|
-
},
|
|
273
|
-
};
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
let c = Controller.create(controllerFactory, { store }) as any;
|
|
277
|
-
|
|
278
|
-
c.increment();
|
|
279
|
-
assert.equal(store.get("x"), 1);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("lifetime methods of a functional controller are properly invoked", async () => {
|
|
283
|
-
let initCount = 0,
|
|
284
|
-
destroyCount = 0;
|
|
285
|
-
|
|
286
|
-
const testController = () => ({
|
|
287
|
-
onInit() {
|
|
288
|
-
initCount++;
|
|
289
|
-
},
|
|
290
|
-
|
|
291
|
-
onDestroy() {
|
|
292
|
-
destroyCount++;
|
|
293
|
-
},
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
let store = new Store();
|
|
297
|
-
store.set("visible", true);
|
|
298
|
-
|
|
299
|
-
const component = await createTestRenderer(
|
|
300
|
-
store,
|
|
301
|
-
<cx>
|
|
302
|
-
<div visible={bind("visible")} controller={testController} />
|
|
303
|
-
</cx>,
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
let tree1 = component.toJSON();
|
|
307
|
-
assert.equal(initCount, 1);
|
|
308
|
-
|
|
309
|
-
await act(async () => {
|
|
310
|
-
store.set("visible", false);
|
|
311
|
-
});
|
|
312
|
-
let tree2 = component.toJSON();
|
|
313
|
-
assert.equal(destroyCount, 1);
|
|
314
|
-
|
|
315
|
-
await act(async () => {
|
|
316
|
-
store.set("visible", true);
|
|
317
|
-
});
|
|
318
|
-
let tree3 = component.toJSON();
|
|
319
|
-
assert.equal(initCount, 2);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it("widgets can easily define controller methods", async () => {
|
|
323
|
-
let store = new Store({ data: { x: 0 } });
|
|
324
|
-
|
|
325
|
-
const component = await createTestRenderer(
|
|
326
|
-
store,
|
|
327
|
-
<cx>
|
|
328
|
-
<div
|
|
329
|
-
controller={{
|
|
330
|
-
increment(count: number) {
|
|
331
|
-
this.store.update("x", (x: number) => x + count);
|
|
332
|
-
},
|
|
333
|
-
}}
|
|
334
|
-
>
|
|
335
|
-
<div
|
|
336
|
-
controller={{
|
|
337
|
-
onInit() {
|
|
338
|
-
this.invokeParentMethod("increment", 1);
|
|
339
|
-
},
|
|
340
|
-
}}
|
|
341
|
-
/>
|
|
342
|
-
</div>
|
|
343
|
-
</cx>,
|
|
344
|
-
);
|
|
345
|
-
|
|
346
|
-
let tree1 = component.toJSON();
|
|
347
|
-
assert.equal(store.get("x"), 1);
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
it("functional controllers get store methods through configuration", async () => {
|
|
351
|
-
let store = new Store({ data: { x: 0 } });
|
|
352
|
-
|
|
353
|
-
const component = await createTestRenderer(
|
|
354
|
-
store,
|
|
355
|
-
<cx>
|
|
356
|
-
<div
|
|
357
|
-
controller={({ update }) => ({
|
|
358
|
-
increment(count: number) {
|
|
359
|
-
update("x", (x: number) => x + count);
|
|
360
|
-
},
|
|
361
|
-
})}
|
|
362
|
-
>
|
|
363
|
-
<div
|
|
364
|
-
controller={{
|
|
365
|
-
onInit() {
|
|
366
|
-
this.invokeParentMethod("increment", 1);
|
|
367
|
-
},
|
|
368
|
-
}}
|
|
369
|
-
/>
|
|
370
|
-
</div>
|
|
371
|
-
</cx>,
|
|
372
|
-
);
|
|
373
|
-
|
|
374
|
-
let tree1 = component.toJSON();
|
|
375
|
-
assert.equal(store.get("x"), 1);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it("addComputable accepts refs", async () => {
|
|
379
|
-
let store = new Store({ data: { x: 0 } });
|
|
380
|
-
|
|
381
|
-
const component = await createTestRenderer(
|
|
382
|
-
store,
|
|
383
|
-
<cx>
|
|
384
|
-
<div
|
|
385
|
-
controller={({ ref }) => {
|
|
386
|
-
let x = ref("x");
|
|
387
|
-
return {
|
|
388
|
-
onInit() {
|
|
389
|
-
this.addComputable("y", [x], (x: number) => x + 1);
|
|
390
|
-
},
|
|
391
|
-
};
|
|
392
|
-
}}
|
|
393
|
-
/>
|
|
394
|
-
</cx>,
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
let tree1 = component.toJSON();
|
|
398
|
-
assert.equal(store.get("y"), 1);
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
it("invokeParentMethod is invoked on parent instance", async () => {
|
|
402
|
-
let testValid: number[] = [];
|
|
403
|
-
|
|
404
|
-
class TestController1 extends Controller {
|
|
405
|
-
onInit() {
|
|
406
|
-
this.test();
|
|
407
|
-
}
|
|
408
|
-
test() {
|
|
409
|
-
testValid.push(1);
|
|
410
|
-
this.invokeParentMethod("test", 2);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
class TestController2 extends Controller {
|
|
415
|
-
test(val: number) {
|
|
416
|
-
testValid.push(val);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
let store = new Store();
|
|
421
|
-
|
|
422
|
-
const component = await createTestRenderer(
|
|
423
|
-
store,
|
|
424
|
-
<cx>
|
|
425
|
-
<div controller={TestController2}>
|
|
426
|
-
<div controller={TestController1} />
|
|
427
|
-
</div>
|
|
428
|
-
</cx>,
|
|
429
|
-
);
|
|
430
|
-
|
|
431
|
-
// let tree = component.toJSON();
|
|
432
|
-
assert.deepStrictEqual(testValid, [1, 2]);
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
describe("Controller types", () => {
|
|
437
|
-
// Type-level tests - these verify that types work correctly at compile time
|
|
438
|
-
// If these compile, the types are working
|
|
439
|
-
|
|
440
|
-
interface MyControllerConfig extends ControllerConfig {
|
|
441
|
-
customValue?: number;
|
|
442
|
-
customMethod?(): void;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
class MyController extends Controller {
|
|
446
|
-
declare customValue: number;
|
|
447
|
-
|
|
448
|
-
constructor(config?: MyControllerConfig) {
|
|
449
|
-
super(config);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
customMethod() {
|
|
453
|
-
return this.customValue * 2;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
it("accepts Controller class directly", async () => {
|
|
458
|
-
let store = new Store();
|
|
459
|
-
|
|
460
|
-
const component = await createTestRenderer(
|
|
461
|
-
store,
|
|
462
|
-
<cx>
|
|
463
|
-
<div controller={MyController} />
|
|
464
|
-
</cx>,
|
|
465
|
-
);
|
|
466
|
-
|
|
467
|
-
let tree = component.toJSON();
|
|
468
|
-
assert.ok(tree);
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
it("accepts config with type property", async () => {
|
|
472
|
-
let store = new Store();
|
|
473
|
-
let initCalled = false;
|
|
474
|
-
|
|
475
|
-
class TypedController extends Controller {
|
|
476
|
-
declare customValue: number;
|
|
477
|
-
|
|
478
|
-
constructor(config?: MyControllerConfig) {
|
|
479
|
-
super(config);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
onInit() {
|
|
483
|
-
initCalled = true;
|
|
484
|
-
assert.equal(this.customValue, 42);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
const component = await createTestRenderer(
|
|
489
|
-
store,
|
|
490
|
-
<cx>
|
|
491
|
-
<div controller={{ type: TypedController, customValue: 42 }} />
|
|
492
|
-
</cx>,
|
|
493
|
-
);
|
|
494
|
-
|
|
495
|
-
let tree = component.toJSON();
|
|
496
|
-
assert.ok(tree);
|
|
497
|
-
assert.equal(initCalled, true);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it("accepts inline config object with ThisType", async () => {
|
|
501
|
-
let store = new Store({ data: { count: 0 } });
|
|
502
|
-
|
|
503
|
-
const component = await createTestRenderer(
|
|
504
|
-
store,
|
|
505
|
-
<cx>
|
|
506
|
-
<div
|
|
507
|
-
controller={{
|
|
508
|
-
onInit() {
|
|
509
|
-
// This should have access to ControllerMethods via ThisType
|
|
510
|
-
this.store.set("count", 1);
|
|
511
|
-
},
|
|
512
|
-
}}
|
|
513
|
-
/>
|
|
514
|
-
</cx>,
|
|
515
|
-
);
|
|
516
|
-
|
|
517
|
-
let tree = component.toJSON();
|
|
518
|
-
assert.equal(store.get("count"), 1);
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
it("accepts factory function", async () => {
|
|
522
|
-
let store = new Store({ data: { count: 0 } });
|
|
523
|
-
|
|
524
|
-
const component = await createTestRenderer(
|
|
525
|
-
store,
|
|
526
|
-
<cx>
|
|
527
|
-
<div
|
|
528
|
-
controller={({ set }) => ({
|
|
529
|
-
onInit() {
|
|
530
|
-
set("count", 5);
|
|
531
|
-
},
|
|
532
|
-
})}
|
|
533
|
-
/>
|
|
534
|
-
</cx>,
|
|
535
|
-
);
|
|
536
|
-
|
|
537
|
-
let tree = component.toJSON();
|
|
538
|
-
assert.equal(store.get("count"), 5);
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
it("accepts CreateConfig with type and required properties", async () => {
|
|
542
|
-
let store = new Store({ data: { result: 0 } });
|
|
543
|
-
|
|
544
|
-
interface RequiredPropControllerConfig extends ControllerConfig {
|
|
545
|
-
multiplier: number; // Required property
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
class RequiredPropController extends Controller {
|
|
549
|
-
declare multiplier: number;
|
|
550
|
-
|
|
551
|
-
constructor(config?: RequiredPropControllerConfig) {
|
|
552
|
-
super(config);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
onInit() {
|
|
556
|
-
this.store.set("result", 10 * this.multiplier);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
const component = await createTestRenderer(
|
|
561
|
-
store,
|
|
562
|
-
<cx>
|
|
563
|
-
<div
|
|
564
|
-
controller={{
|
|
565
|
-
type: RequiredPropController,
|
|
566
|
-
multiplier: 5,
|
|
567
|
-
}}
|
|
568
|
-
/>
|
|
569
|
-
</cx>,
|
|
570
|
-
);
|
|
571
|
-
|
|
572
|
-
assert.equal(store.get("result"), 50);
|
|
573
|
-
});
|
|
574
|
-
});
|
|
1
|
+
import { Store } from "../data/Store";
|
|
2
|
+
import { Controller, ControllerConfig } from "./Controller";
|
|
3
|
+
import { createTestRenderer, act } from "../util/test/createTestRenderer";
|
|
4
|
+
import { VDOM, Widget, WidgetConfig } from "./Widget";
|
|
5
|
+
import { Instance } from "./Instance";
|
|
6
|
+
import { bind } from "./bind";
|
|
7
|
+
import assert from "assert";
|
|
8
|
+
import { RenderingContext } from "./RenderingContext";
|
|
9
|
+
|
|
10
|
+
describe("Controller", () => {
|
|
11
|
+
it("invokes lifetime methods", async () => {
|
|
12
|
+
let init = 0,
|
|
13
|
+
prepare = 0,
|
|
14
|
+
explore = 0,
|
|
15
|
+
cleanup = 0;
|
|
16
|
+
|
|
17
|
+
class TestController extends Controller {
|
|
18
|
+
onInit() {
|
|
19
|
+
init++;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
onExplore() {
|
|
23
|
+
explore++;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
onPrepare() {
|
|
27
|
+
prepare++;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onCleanup() {
|
|
31
|
+
cleanup++;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let store = new Store();
|
|
36
|
+
|
|
37
|
+
const component = await createTestRenderer(
|
|
38
|
+
store,
|
|
39
|
+
<cx>
|
|
40
|
+
<div controller={TestController} />
|
|
41
|
+
</cx>,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
let tree = component.toJSON();
|
|
45
|
+
assert.equal(init, 1);
|
|
46
|
+
assert.equal(explore, 1);
|
|
47
|
+
assert.equal(prepare, 1);
|
|
48
|
+
assert.equal(cleanup, 1);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("widgets invoke controller methods specified as strings", async () => {
|
|
52
|
+
let callback = 0;
|
|
53
|
+
|
|
54
|
+
class TestController extends Controller {
|
|
55
|
+
callback() {
|
|
56
|
+
++callback;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface CmpConfig extends WidgetConfig {
|
|
61
|
+
onTest: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class Cmp extends Widget<CmpConfig> {
|
|
65
|
+
render(context: RenderingContext, instance: Instance, key: string) {
|
|
66
|
+
instance.invoke("onTest");
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let store = new Store();
|
|
72
|
+
|
|
73
|
+
const component = await createTestRenderer(
|
|
74
|
+
store,
|
|
75
|
+
<cx>
|
|
76
|
+
<Cmp controller={TestController} onTest="callback" />
|
|
77
|
+
</cx>,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
let tree = component.toJSON();
|
|
81
|
+
assert.equal(callback, 1);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("widgets can access controller methods specified in ancestor controllers", async () => {
|
|
85
|
+
let callback1 = 0;
|
|
86
|
+
let callback2 = 0;
|
|
87
|
+
|
|
88
|
+
class TestController1 extends Controller {
|
|
89
|
+
callback1() {
|
|
90
|
+
++callback1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
class TestController2 extends Controller {
|
|
95
|
+
callback2() {
|
|
96
|
+
++callback2;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface CmpConfig extends WidgetConfig {
|
|
101
|
+
onTest: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class Cmp extends Widget<CmpConfig> {
|
|
105
|
+
render(context: RenderingContext, instance: Instance, key: string) {
|
|
106
|
+
instance.invoke("onTest");
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let store = new Store();
|
|
112
|
+
|
|
113
|
+
const component = await createTestRenderer(
|
|
114
|
+
store,
|
|
115
|
+
<cx>
|
|
116
|
+
<div controller={TestController1}>
|
|
117
|
+
<Cmp controller={TestController2} onTest="callback1" />
|
|
118
|
+
</div>
|
|
119
|
+
</cx>,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
let tree = component.toJSON();
|
|
123
|
+
assert.equal(callback1, 1);
|
|
124
|
+
assert.equal(callback2, 0);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("ancestor controllers are initialized first", async () => {
|
|
128
|
+
let order: string[] = [];
|
|
129
|
+
|
|
130
|
+
class TestController1 extends Controller {
|
|
131
|
+
onInit() {
|
|
132
|
+
order.push("1");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
class TestController2 extends Controller {
|
|
137
|
+
onInit() {
|
|
138
|
+
order.push("2");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let store = new Store();
|
|
143
|
+
|
|
144
|
+
const component = await createTestRenderer(
|
|
145
|
+
store,
|
|
146
|
+
<cx>
|
|
147
|
+
<div controller={TestController1}>
|
|
148
|
+
<div controller={TestController2} />
|
|
149
|
+
</div>
|
|
150
|
+
</cx>,
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
let tree = component.toJSON();
|
|
154
|
+
assert.deepEqual(order, ["1", "2"]);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("controllers on invisible elements are not initialized", async () => {
|
|
158
|
+
let order: string[] = [];
|
|
159
|
+
|
|
160
|
+
class TestController1 extends Controller {
|
|
161
|
+
onInit() {
|
|
162
|
+
order.push("1");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
class TestController2 extends Controller {
|
|
167
|
+
onInit() {
|
|
168
|
+
order.push("2");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let store = new Store();
|
|
173
|
+
|
|
174
|
+
const component = await createTestRenderer(
|
|
175
|
+
store,
|
|
176
|
+
<cx>
|
|
177
|
+
<div controller={TestController1}>
|
|
178
|
+
<div visible={false} controller={TestController2} />
|
|
179
|
+
</div>
|
|
180
|
+
</cx>,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
let tree = component.toJSON();
|
|
184
|
+
assert.deepEqual(order, ["1"]);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("invokes triggers and computables in order of definition", async () => {
|
|
188
|
+
let log: string[] = [];
|
|
189
|
+
|
|
190
|
+
class TestController extends Controller {
|
|
191
|
+
onInit() {
|
|
192
|
+
this.addTrigger(
|
|
193
|
+
"t1",
|
|
194
|
+
[],
|
|
195
|
+
() => {
|
|
196
|
+
log.push("t1");
|
|
197
|
+
},
|
|
198
|
+
true,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
this.addComputable("c1", [], () => {
|
|
202
|
+
log.push("c1");
|
|
203
|
+
return null;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
this.addTrigger(
|
|
207
|
+
"t2",
|
|
208
|
+
[],
|
|
209
|
+
() => {
|
|
210
|
+
log.push("t2");
|
|
211
|
+
},
|
|
212
|
+
true,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let store = new Store();
|
|
218
|
+
|
|
219
|
+
const component = await createTestRenderer(
|
|
220
|
+
store,
|
|
221
|
+
<cx>
|
|
222
|
+
<div controller={TestController} />
|
|
223
|
+
</cx>,
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
let tree = component.toJSON();
|
|
227
|
+
assert.deepEqual(log, ["t1", "c1", "t2"]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("is recreated if a component is hidden and shown", async () => {
|
|
231
|
+
let initCount = 0;
|
|
232
|
+
|
|
233
|
+
class TestController extends Controller {
|
|
234
|
+
onInit() {
|
|
235
|
+
initCount++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let store = new Store();
|
|
240
|
+
store.set("visible", true);
|
|
241
|
+
|
|
242
|
+
const component = await createTestRenderer(
|
|
243
|
+
store,
|
|
244
|
+
<cx>
|
|
245
|
+
<div visible={bind("visible")} controller={TestController} />
|
|
246
|
+
</cx>,
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
let tree1 = component.toJSON();
|
|
250
|
+
assert.equal(initCount, 1);
|
|
251
|
+
|
|
252
|
+
await act(async () => {
|
|
253
|
+
store.set("visible", false);
|
|
254
|
+
});
|
|
255
|
+
let tree2 = component.toJSON();
|
|
256
|
+
assert.equal(tree2, null);
|
|
257
|
+
|
|
258
|
+
await act(async () => {
|
|
259
|
+
store.set("visible", true);
|
|
260
|
+
});
|
|
261
|
+
let tree3 = component.toJSON();
|
|
262
|
+
assert.equal(initCount, 2);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("allows creation through a factory", () => {
|
|
266
|
+
let store = new Store({ data: { x: 0 } });
|
|
267
|
+
|
|
268
|
+
const controllerFactory = ({ store }: { store: Store }) => {
|
|
269
|
+
return {
|
|
270
|
+
increment() {
|
|
271
|
+
store.update("x", (x: number) => x + 1);
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
let c = Controller.create(controllerFactory, { store }) as any;
|
|
277
|
+
|
|
278
|
+
c.increment();
|
|
279
|
+
assert.equal(store.get("x"), 1);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("lifetime methods of a functional controller are properly invoked", async () => {
|
|
283
|
+
let initCount = 0,
|
|
284
|
+
destroyCount = 0;
|
|
285
|
+
|
|
286
|
+
const testController = () => ({
|
|
287
|
+
onInit() {
|
|
288
|
+
initCount++;
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
onDestroy() {
|
|
292
|
+
destroyCount++;
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
let store = new Store();
|
|
297
|
+
store.set("visible", true);
|
|
298
|
+
|
|
299
|
+
const component = await createTestRenderer(
|
|
300
|
+
store,
|
|
301
|
+
<cx>
|
|
302
|
+
<div visible={bind("visible")} controller={testController} />
|
|
303
|
+
</cx>,
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
let tree1 = component.toJSON();
|
|
307
|
+
assert.equal(initCount, 1);
|
|
308
|
+
|
|
309
|
+
await act(async () => {
|
|
310
|
+
store.set("visible", false);
|
|
311
|
+
});
|
|
312
|
+
let tree2 = component.toJSON();
|
|
313
|
+
assert.equal(destroyCount, 1);
|
|
314
|
+
|
|
315
|
+
await act(async () => {
|
|
316
|
+
store.set("visible", true);
|
|
317
|
+
});
|
|
318
|
+
let tree3 = component.toJSON();
|
|
319
|
+
assert.equal(initCount, 2);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("widgets can easily define controller methods", async () => {
|
|
323
|
+
let store = new Store({ data: { x: 0 } });
|
|
324
|
+
|
|
325
|
+
const component = await createTestRenderer(
|
|
326
|
+
store,
|
|
327
|
+
<cx>
|
|
328
|
+
<div
|
|
329
|
+
controller={{
|
|
330
|
+
increment(count: number) {
|
|
331
|
+
this.store.update("x", (x: number) => x + count);
|
|
332
|
+
},
|
|
333
|
+
}}
|
|
334
|
+
>
|
|
335
|
+
<div
|
|
336
|
+
controller={{
|
|
337
|
+
onInit() {
|
|
338
|
+
this.invokeParentMethod("increment", 1);
|
|
339
|
+
},
|
|
340
|
+
}}
|
|
341
|
+
/>
|
|
342
|
+
</div>
|
|
343
|
+
</cx>,
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
let tree1 = component.toJSON();
|
|
347
|
+
assert.equal(store.get("x"), 1);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it("functional controllers get store methods through configuration", async () => {
|
|
351
|
+
let store = new Store({ data: { x: 0 } });
|
|
352
|
+
|
|
353
|
+
const component = await createTestRenderer(
|
|
354
|
+
store,
|
|
355
|
+
<cx>
|
|
356
|
+
<div
|
|
357
|
+
controller={({ update }) => ({
|
|
358
|
+
increment(count: number) {
|
|
359
|
+
update("x", (x: number) => x + count);
|
|
360
|
+
},
|
|
361
|
+
})}
|
|
362
|
+
>
|
|
363
|
+
<div
|
|
364
|
+
controller={{
|
|
365
|
+
onInit() {
|
|
366
|
+
this.invokeParentMethod("increment", 1);
|
|
367
|
+
},
|
|
368
|
+
}}
|
|
369
|
+
/>
|
|
370
|
+
</div>
|
|
371
|
+
</cx>,
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
let tree1 = component.toJSON();
|
|
375
|
+
assert.equal(store.get("x"), 1);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it("addComputable accepts refs", async () => {
|
|
379
|
+
let store = new Store({ data: { x: 0 } });
|
|
380
|
+
|
|
381
|
+
const component = await createTestRenderer(
|
|
382
|
+
store,
|
|
383
|
+
<cx>
|
|
384
|
+
<div
|
|
385
|
+
controller={({ ref }) => {
|
|
386
|
+
let x = ref("x");
|
|
387
|
+
return {
|
|
388
|
+
onInit() {
|
|
389
|
+
this.addComputable("y", [x], (x: number) => x + 1);
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
}}
|
|
393
|
+
/>
|
|
394
|
+
</cx>,
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
let tree1 = component.toJSON();
|
|
398
|
+
assert.equal(store.get("y"), 1);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("invokeParentMethod is invoked on parent instance", async () => {
|
|
402
|
+
let testValid: number[] = [];
|
|
403
|
+
|
|
404
|
+
class TestController1 extends Controller {
|
|
405
|
+
onInit() {
|
|
406
|
+
this.test();
|
|
407
|
+
}
|
|
408
|
+
test() {
|
|
409
|
+
testValid.push(1);
|
|
410
|
+
this.invokeParentMethod("test", 2);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
class TestController2 extends Controller {
|
|
415
|
+
test(val: number) {
|
|
416
|
+
testValid.push(val);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
let store = new Store();
|
|
421
|
+
|
|
422
|
+
const component = await createTestRenderer(
|
|
423
|
+
store,
|
|
424
|
+
<cx>
|
|
425
|
+
<div controller={TestController2}>
|
|
426
|
+
<div controller={TestController1} />
|
|
427
|
+
</div>
|
|
428
|
+
</cx>,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// let tree = component.toJSON();
|
|
432
|
+
assert.deepStrictEqual(testValid, [1, 2]);
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
describe("Controller types", () => {
|
|
437
|
+
// Type-level tests - these verify that types work correctly at compile time
|
|
438
|
+
// If these compile, the types are working
|
|
439
|
+
|
|
440
|
+
interface MyControllerConfig extends ControllerConfig {
|
|
441
|
+
customValue?: number;
|
|
442
|
+
customMethod?(): void;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
class MyController extends Controller {
|
|
446
|
+
declare customValue: number;
|
|
447
|
+
|
|
448
|
+
constructor(config?: MyControllerConfig) {
|
|
449
|
+
super(config);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
customMethod() {
|
|
453
|
+
return this.customValue * 2;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
it("accepts Controller class directly", async () => {
|
|
458
|
+
let store = new Store();
|
|
459
|
+
|
|
460
|
+
const component = await createTestRenderer(
|
|
461
|
+
store,
|
|
462
|
+
<cx>
|
|
463
|
+
<div controller={MyController} />
|
|
464
|
+
</cx>,
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
let tree = component.toJSON();
|
|
468
|
+
assert.ok(tree);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it("accepts config with type property", async () => {
|
|
472
|
+
let store = new Store();
|
|
473
|
+
let initCalled = false;
|
|
474
|
+
|
|
475
|
+
class TypedController extends Controller {
|
|
476
|
+
declare customValue: number;
|
|
477
|
+
|
|
478
|
+
constructor(config?: MyControllerConfig) {
|
|
479
|
+
super(config);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
onInit() {
|
|
483
|
+
initCalled = true;
|
|
484
|
+
assert.equal(this.customValue, 42);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const component = await createTestRenderer(
|
|
489
|
+
store,
|
|
490
|
+
<cx>
|
|
491
|
+
<div controller={{ type: TypedController, customValue: 42 }} />
|
|
492
|
+
</cx>,
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
let tree = component.toJSON();
|
|
496
|
+
assert.ok(tree);
|
|
497
|
+
assert.equal(initCalled, true);
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it("accepts inline config object with ThisType", async () => {
|
|
501
|
+
let store = new Store({ data: { count: 0 } });
|
|
502
|
+
|
|
503
|
+
const component = await createTestRenderer(
|
|
504
|
+
store,
|
|
505
|
+
<cx>
|
|
506
|
+
<div
|
|
507
|
+
controller={{
|
|
508
|
+
onInit() {
|
|
509
|
+
// This should have access to ControllerMethods via ThisType
|
|
510
|
+
this.store.set("count", 1);
|
|
511
|
+
},
|
|
512
|
+
}}
|
|
513
|
+
/>
|
|
514
|
+
</cx>,
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
let tree = component.toJSON();
|
|
518
|
+
assert.equal(store.get("count"), 1);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
it("accepts factory function", async () => {
|
|
522
|
+
let store = new Store({ data: { count: 0 } });
|
|
523
|
+
|
|
524
|
+
const component = await createTestRenderer(
|
|
525
|
+
store,
|
|
526
|
+
<cx>
|
|
527
|
+
<div
|
|
528
|
+
controller={({ set }) => ({
|
|
529
|
+
onInit() {
|
|
530
|
+
set("count", 5);
|
|
531
|
+
},
|
|
532
|
+
})}
|
|
533
|
+
/>
|
|
534
|
+
</cx>,
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
let tree = component.toJSON();
|
|
538
|
+
assert.equal(store.get("count"), 5);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
it("accepts CreateConfig with type and required properties", async () => {
|
|
542
|
+
let store = new Store({ data: { result: 0 } });
|
|
543
|
+
|
|
544
|
+
interface RequiredPropControllerConfig extends ControllerConfig {
|
|
545
|
+
multiplier: number; // Required property
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
class RequiredPropController extends Controller {
|
|
549
|
+
declare multiplier: number;
|
|
550
|
+
|
|
551
|
+
constructor(config?: RequiredPropControllerConfig) {
|
|
552
|
+
super(config);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
onInit() {
|
|
556
|
+
this.store.set("result", 10 * this.multiplier);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const component = await createTestRenderer(
|
|
561
|
+
store,
|
|
562
|
+
<cx>
|
|
563
|
+
<div
|
|
564
|
+
controller={{
|
|
565
|
+
type: RequiredPropController,
|
|
566
|
+
multiplier: 5,
|
|
567
|
+
}}
|
|
568
|
+
/>
|
|
569
|
+
</cx>,
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
assert.equal(store.get("result"), 50);
|
|
573
|
+
});
|
|
574
|
+
});
|