cx 26.0.5 → 26.0.8

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 (257) hide show
  1. package/build/charts/Bar.scss +29 -0
  2. package/build/charts/BarGraph.scss +29 -0
  3. package/build/charts/BubbleGraph.scss +32 -0
  4. package/build/charts/Column.scss +29 -0
  5. package/build/charts/ColumnGraph.scss +30 -0
  6. package/build/charts/Gridlines.scss +25 -0
  7. package/build/charts/Legend.scss +50 -0
  8. package/build/charts/LegendEntry.scss +29 -0
  9. package/build/charts/LineGraph.d.ts +11 -0
  10. package/build/charts/LineGraph.js +1 -0
  11. package/build/charts/LineGraph.scss +25 -0
  12. package/build/charts/Marker.scss +44 -0
  13. package/build/charts/MarkerLine.scss +20 -0
  14. package/build/charts/PieChart.scss +29 -0
  15. package/build/charts/Range.scss +20 -0
  16. package/build/charts/RangeMarker.scss +17 -0
  17. package/build/charts/ScatterGraph.scss +24 -0
  18. package/build/charts/Swimlane.scss +16 -0
  19. package/build/charts/Swimlanes.scss +16 -0
  20. package/build/charts/axis/Axis.scss +23 -0
  21. package/build/charts/axis/CategoryAxis.scss +35 -0
  22. package/build/charts/axis/NumericAxis.scss +35 -0
  23. package/build/charts/axis/TimeAxis.scss +34 -0
  24. package/build/charts/axis/index.scss +5 -0
  25. package/build/charts/axis/variables.scss +3 -0
  26. package/build/charts/index.scss +22 -0
  27. package/build/charts/palette.scss +97 -0
  28. package/build/charts/variables.scss +22 -0
  29. package/build/data/ArrayElementView.spec.js +1 -1
  30. package/build/global.scss +14 -0
  31. package/build/hooks/store.spec.js +1 -1
  32. package/build/hooks/useTrigger.spec.js +1 -1
  33. package/build/index.scss +6 -0
  34. package/build/jsx-runtime.d.ts +3 -2
  35. package/build/svg/Svg.scss +28 -0
  36. package/build/svg/index.scss +9 -0
  37. package/build/ui/Controller.spec.js +6 -2
  38. package/build/ui/app/startAppLoop.d.ts +3 -2
  39. package/build/ui/app/startHotAppLoop.d.ts +3 -2
  40. package/build/ui/index.scss +2 -0
  41. package/build/ui/layout/ContentPlaceholder.spec.js +12 -12
  42. package/build/ui/layout/LabelsLeftLayout.scss +47 -0
  43. package/build/ui/layout/LabelsTopLayout.scss +65 -0
  44. package/build/ui/layout/index.scss +3 -0
  45. package/build/ui/layout/variables.scss +2 -0
  46. package/build/ui/variables.scss +2 -0
  47. package/build/util/addEventListenerWithOptions.d.ts +2 -2
  48. package/build/util/call-once.scss +7 -0
  49. package/build/util/index.scss +11 -0
  50. package/build/util/scss/add-rules.scss +40 -0
  51. package/build/util/scss/calc.scss +45 -0
  52. package/build/util/scss/call-once.scss +13 -0
  53. package/build/util/scss/clockwise.scss +49 -0
  54. package/build/util/scss/colors.scss +10 -0
  55. package/build/util/scss/deep-get.scss +12 -0
  56. package/build/util/scss/deep-merge.scss +21 -0
  57. package/build/util/scss/divide.scss +3 -0
  58. package/build/util/scss/include.scss +48 -0
  59. package/build/util/scss/index.scss +9 -0
  60. package/build/variables.scss +217 -0
  61. package/build/widgets/Button.scss +119 -0
  62. package/build/widgets/Button.variables.scss +117 -0
  63. package/build/widgets/CxCredit.scss +39 -0
  64. package/build/widgets/FlexBox.scss +148 -0
  65. package/build/widgets/Heading.scss +40 -0
  66. package/build/widgets/HighlightedSearchText.scss +20 -0
  67. package/build/widgets/Icon.scss +22 -0
  68. package/build/widgets/List.scss +93 -0
  69. package/build/widgets/ProgressBar.scss +51 -0
  70. package/build/widgets/Resizer.scss +44 -0
  71. package/build/widgets/Section.scss +56 -0
  72. package/build/widgets/animations.scss +11 -0
  73. package/build/widgets/drag-drop/DragClone.scss +36 -0
  74. package/build/widgets/drag-drop/DragHandle.scss +19 -0
  75. package/build/widgets/drag-drop/DragSource.scss +27 -0
  76. package/build/widgets/drag-drop/DropZone.scss +77 -0
  77. package/build/widgets/drag-drop/index.scss +4 -0
  78. package/build/widgets/drag-drop/variables.scss +15 -0
  79. package/build/widgets/form/Calendar.scss +199 -0
  80. package/build/widgets/form/Calendar.variables.scss +64 -0
  81. package/build/widgets/form/Checkbox.scss +129 -0
  82. package/build/widgets/form/Checkbox.variables.scss +40 -0
  83. package/build/widgets/form/ColorField.scss +98 -0
  84. package/build/widgets/form/ColorPicker.scss +285 -0
  85. package/build/widgets/form/ColorPicker.variables.scss +22 -0
  86. package/build/widgets/form/DateTimeField.scss +92 -0
  87. package/build/widgets/form/DateTimePicker.scss +47 -0
  88. package/build/widgets/form/Field.scss +164 -0
  89. package/build/widgets/form/HelpText.scss +24 -0
  90. package/build/widgets/form/Label.scss +38 -0
  91. package/build/widgets/form/LookupField.scss +221 -0
  92. package/build/widgets/form/MonthField.scss +100 -0
  93. package/build/widgets/form/MonthPicker.scss +125 -0
  94. package/build/widgets/form/NumberField.scss +63 -0
  95. package/build/widgets/form/Radio.scss +123 -0
  96. package/build/widgets/form/Radio.variables.scss +46 -0
  97. package/build/widgets/form/Select.scss +101 -0
  98. package/build/widgets/form/Slider.scss +121 -0
  99. package/build/widgets/form/Switch.scss +142 -0
  100. package/build/widgets/form/TextArea.scss +45 -0
  101. package/build/widgets/form/TextField.scss +57 -0
  102. package/build/widgets/form/UploadButton.scss +49 -0
  103. package/build/widgets/form/ValidationError.scss +23 -0
  104. package/build/widgets/form/Wheel.scss +152 -0
  105. package/build/widgets/form/index.scss +24 -0
  106. package/build/widgets/form/variables.scss +355 -0
  107. package/build/widgets/grid/Grid.scss +640 -0
  108. package/build/widgets/grid/Pagination.scss +115 -0
  109. package/build/widgets/grid/TreeNode.scss +90 -0
  110. package/build/widgets/grid/index.scss +4 -0
  111. package/build/widgets/grid/variables.scss +137 -0
  112. package/build/widgets/index.scss +16 -0
  113. package/build/widgets/nav/Link.scss +20 -0
  114. package/build/widgets/nav/Menu.scss +76 -0
  115. package/build/widgets/nav/Menu.variables.scss +25 -0
  116. package/build/widgets/nav/MenuItem.d.ts +1 -0
  117. package/build/widgets/nav/MenuItem.scss +130 -0
  118. package/build/widgets/nav/Scroller.scss +148 -0
  119. package/build/widgets/nav/Tab.scss +82 -0
  120. package/build/widgets/nav/Tab.variables.scss +84 -0
  121. package/build/widgets/nav/cover.scss +22 -0
  122. package/build/widgets/nav/index.scss +6 -0
  123. package/build/widgets/nav/variables.scss +27 -0
  124. package/build/widgets/overlay/Dropdown.scss +186 -0
  125. package/build/widgets/overlay/Overlay.scss +68 -0
  126. package/build/widgets/overlay/Toast.scss +164 -0
  127. package/build/widgets/overlay/Tooltip.scss +177 -0
  128. package/build/widgets/overlay/Window.scss +129 -0
  129. package/build/widgets/overlay/Window.variables.scss +62 -0
  130. package/build/widgets/overlay/captureMouse.scss +13 -0
  131. package/build/widgets/overlay/index.scss +15 -0
  132. package/build/widgets/overlay/variables.scss +85 -0
  133. package/build/widgets/variables.scss +146 -0
  134. package/build.js +133 -129
  135. package/dist/charts.js +1 -0
  136. package/dist/manifest.js +849 -743
  137. package/package.json +4 -2
  138. package/src/charts/Chart.ts +108 -108
  139. package/src/charts/LineGraph.tsx +14 -0
  140. package/src/data/ArrayElementView.ts +90 -90
  141. package/src/data/AugmentedViewBase.ts +88 -88
  142. package/src/data/Binding.ts +104 -104
  143. package/src/data/ExposedRecordView.ts +95 -95
  144. package/src/data/ExposedValueView.ts +89 -89
  145. package/src/data/Expression.spec.ts +229 -229
  146. package/src/data/Expression.ts +233 -233
  147. package/src/data/Grouper.spec.ts +57 -57
  148. package/src/data/Grouper.ts +158 -158
  149. package/src/data/NestedDataView.ts +43 -43
  150. package/src/data/ReadOnlyDataView.ts +39 -39
  151. package/src/data/Ref.ts +104 -104
  152. package/src/data/Selector.ts +10 -10
  153. package/src/data/Store.ts +52 -52
  154. package/src/data/StoreProxy.ts +19 -19
  155. package/src/data/StoreRef.ts +66 -66
  156. package/src/data/StringTemplate.spec.ts +132 -132
  157. package/src/data/StringTemplate.ts +93 -93
  158. package/src/data/StructuredSelector.spec.ts +113 -113
  159. package/src/data/StructuredSelector.ts +146 -146
  160. package/src/data/SubscribableView.ts +63 -63
  161. package/src/data/ZoomIntoPropertyView.spec.ts +64 -64
  162. package/src/data/ZoomIntoPropertyView.ts +45 -45
  163. package/src/data/computable.spec.ts +62 -62
  164. package/src/data/createAccessorModelProxy.ts +60 -60
  165. package/src/data/createStructuredSelector.ts +62 -62
  166. package/src/data/getAccessor.spec.ts +11 -11
  167. package/src/data/getAccessor.ts +74 -74
  168. package/src/data/getSelector.spec.ts +43 -43
  169. package/src/data/getSelector.ts +66 -66
  170. package/src/data/ops/filter.spec.ts +35 -35
  171. package/src/data/ops/filter.ts +9 -9
  172. package/src/data/ops/merge.ts +13 -13
  173. package/src/data/ops/removeTreeNodes.spec.ts +37 -37
  174. package/src/data/ops/removeTreeNodes.ts +15 -15
  175. package/src/data/ops/updateArray.spec.ts +69 -69
  176. package/src/data/ops/updateArray.ts +31 -31
  177. package/src/data/ops/updateTree.ts +23 -23
  178. package/src/data/test-types.ts +7 -7
  179. package/src/hooks/useTrigger.ts +26 -26
  180. package/src/index.scss +6 -6
  181. package/src/jsx-runtime.ts +75 -72
  182. package/src/svg/BoundedObject.ts +101 -101
  183. package/src/ui/CSSHelper.ts +17 -17
  184. package/src/ui/ContentResolver.ts +124 -124
  185. package/src/ui/Controller.ts +189 -189
  186. package/src/ui/Culture.ts +159 -159
  187. package/src/ui/DataProxy.ts +55 -55
  188. package/src/ui/FocusManager.ts +171 -171
  189. package/src/ui/Instance.ts +868 -868
  190. package/src/ui/RenderingContext.ts +99 -99
  191. package/src/ui/Rescope.ts +49 -49
  192. package/src/ui/StructuredInstanceDataAccessor.ts +32 -32
  193. package/src/ui/VDOM.ts +34 -34
  194. package/src/ui/adapter/ArrayAdapter.spec.ts +55 -55
  195. package/src/ui/adapter/ArrayAdapter.ts +226 -226
  196. package/src/ui/adapter/TreeAdapter.spec.ts +76 -76
  197. package/src/ui/adapter/TreeAdapter.ts +185 -185
  198. package/src/ui/app/History.ts +133 -133
  199. package/src/ui/app/Url.spec.ts +50 -50
  200. package/src/ui/app/startAppLoop.tsx +2 -1
  201. package/src/ui/app/startHotAppLoop.ts +2 -1
  202. package/src/ui/createFunctionalComponent.ts +65 -65
  203. package/src/ui/index.ts +45 -45
  204. package/src/ui/layout/Content.ts +30 -30
  205. package/src/ui/layout/FirstVisibleChildLayout.ts +60 -60
  206. package/src/ui/selection/KeySelection.ts +165 -165
  207. package/src/ui/selection/PropertySelection.ts +87 -87
  208. package/src/ui/selection/Selection.ts +118 -118
  209. package/src/util/Format.ts +267 -267
  210. package/src/util/addEventListenerWithOptions.ts +41 -41
  211. package/src/util/browserSupportsPassiveEventHandlers.ts +20 -20
  212. package/src/util/color/rgbToHsl.ts +35 -35
  213. package/src/util/getActiveElement.ts +4 -4
  214. package/src/util/hasKey.ts +18 -18
  215. package/src/util/index.ts +55 -55
  216. package/src/util/innerTextTrim.ts +10 -10
  217. package/src/util/isArray.ts +3 -3
  218. package/src/util/isDataRecord.ts +5 -5
  219. package/src/util/isDefined.ts +3 -3
  220. package/src/util/isString.ts +3 -3
  221. package/src/widgets/Sandbox.ts +103 -103
  222. package/src/widgets/autoFocus.ts +9 -9
  223. package/src/widgets/cx.ts +63 -63
  224. package/src/widgets/drag-drop/ops.tsx +1 -1
  225. package/src/widgets/grid/GridCell.ts +143 -143
  226. package/src/widgets/icons/calendar.tsx +17 -17
  227. package/src/widgets/icons/check.tsx +13 -13
  228. package/src/widgets/icons/clear.tsx +15 -15
  229. package/src/widgets/icons/close.tsx +20 -20
  230. package/src/widgets/icons/cx.tsx +38 -38
  231. package/src/widgets/icons/drop-down.tsx +15 -15
  232. package/src/widgets/icons/file.tsx +13 -13
  233. package/src/widgets/icons/folder-open.tsx +15 -15
  234. package/src/widgets/icons/folder.tsx +13 -13
  235. package/src/widgets/icons/forward.tsx +22 -22
  236. package/src/widgets/icons/loading.tsx +24 -24
  237. package/src/widgets/icons/menu.tsx +17 -17
  238. package/src/widgets/icons/pixel-picker.tsx +18 -18
  239. package/src/widgets/icons/search.tsx +13 -13
  240. package/src/widgets/icons/sort-asc.tsx +14 -14
  241. package/src/widgets/icons/square.tsx +18 -18
  242. package/src/widgets/nav/MenuItem.tsx +1 -0
  243. package/src/widgets/nav/Route.ts +142 -142
  244. package/src/widgets/overlay/ContextMenu.ts +42 -42
  245. package/src/widgets/overlay/Dropdown.tsx +762 -762
  246. package/src/widgets/overlay/MsgBox.tsx +141 -141
  247. package/src/widgets/overlay/Toast.ts +111 -111
  248. package/src/widgets/overlay/Window.tsx +299 -299
  249. package/src/widgets/overlay/alerts.ts +46 -46
  250. package/src/widgets/overlay/captureMouse.ts +195 -195
  251. package/src/widgets/overlay/createHotPromiseWindowFactory.ts +72 -72
  252. package/src/widgets/overlay/index.d.ts +11 -11
  253. package/src/widgets/overlay/index.ts +11 -11
  254. package/src/widgets/overlay/tooltip-ops.ts +173 -173
  255. package/build/ui/PureContainer.spec.d.ts +0 -1
  256. package/build/ui/PureContainer.spec.js +0 -149
  257. package/dist/manifest.d.ts +0 -1443
@@ -1,124 +1,124 @@
1
- import { PureContainerBase, PureContainerConfig } from "./PureContainer";
2
- import { isPromise } from "../util/isPromise";
3
- import { RenderingContext } from "./RenderingContext";
4
- import { BooleanProp, StructuredProp, ResolveStructuredProp } from "./Prop";
5
- import { Instance } from "./Instance";
6
-
7
- /**
8
- * Configuration for ContentResolver widget.
9
- *
10
- * The params type parameter enables type inference for the onResolve callback:
11
- * - Literal values (numbers, strings, booleans) preserve their types
12
- * - AccessorChain<T> resolves to T
13
- * - Bind/Tpl/Expr resolve to any (type cannot be determined at compile time)
14
- *
15
- * @example
16
- * ```typescript
17
- * <ContentResolver
18
- * params={{
19
- * count: 42, // number
20
- * name: model.user.name // AccessorChain<string> -> string
21
- * }}
22
- * onResolve={(params) => {
23
- * // params.count is number, params.name is string
24
- * }}
25
- * />
26
- * ```
27
- */
28
- export interface ContentResolverConfig<P extends StructuredProp = StructuredProp> extends PureContainerConfig {
29
- /** Parameters that trigger content resolution when changed. */
30
- params?: P;
31
-
32
- /**
33
- * Callback function that resolves content based on params. Can return content directly or a Promise.
34
- * The params type is inferred from the params property - literal values and AccessorChain<T>
35
- * preserve their types, while bindings (bind/tpl/expr) resolve to `any`.
36
- */
37
- onResolve?: string | ((params: ResolveStructuredProp<P>, instance: Instance) => any);
38
-
39
- /** How to combine resolved content with initial content. Default is 'replace'. */
40
- mode?: "replace" | "prepend" | "append";
41
-
42
- /** Indicates if content is being loaded. */
43
- loading?: BooleanProp;
44
- }
45
-
46
- export class ContentResolver<P extends StructuredProp = StructuredProp> extends PureContainerBase<
47
- ContentResolverConfig<P>
48
- > {
49
- constructor(config?: ContentResolverConfig<P>) {
50
- super(config);
51
- }
52
-
53
- declare mode: "replace" | "prepend" | "append";
54
- declare onResolve?: string | ((params: ResolveStructuredProp<P>, instance: Instance) => any);
55
- declare initialItems: any;
56
-
57
- declareData(...args: any[]): void {
58
- super.declareData(...args, {
59
- params: { structured: true },
60
- loading: undefined,
61
- });
62
- }
63
-
64
- init(): void {
65
- super.init();
66
- this.initialItems = this.layout ? this.layout.items : this.items;
67
- this.clear();
68
- }
69
-
70
- initInstance(context: RenderingContext, instance: any): void {
71
- instance.content = this.initialItems;
72
- instance.cachedParams = {}; //unique value which will never pass the equality check
73
- }
74
-
75
- prepareData(context: RenderingContext, instance: any): void {
76
- let { data } = instance;
77
-
78
- if (data.params !== instance.cachedParams && this.onResolve) {
79
- instance.cachedParams = data.params;
80
- let content = instance.invoke("onResolve", data.params, instance);
81
- if (isPromise(content)) {
82
- instance.set("loading", true);
83
- this.setContent(instance, null);
84
- content.then((cnt: any) => {
85
- this.setContent(instance, cnt);
86
- instance.setState({ cacheBuster: {} });
87
- instance.set("loading", false);
88
- });
89
- } else this.setContent(instance, content);
90
- }
91
- }
92
-
93
- setContent(instance: any, content: any): void {
94
- if (content) {
95
- this.clear();
96
- switch (this.mode) {
97
- case "prepend":
98
- this.add(content);
99
- this.add(this.initialItems);
100
- break;
101
-
102
- case "append":
103
- this.add(this.initialItems);
104
- this.add(content);
105
- break;
106
-
107
- case "replace":
108
- this.add(content);
109
- break;
110
- }
111
- instance.content = this.layout ? this.layout.items : this.items;
112
- this.clear();
113
- } else instance.content = this.initialItems;
114
- }
115
-
116
- explore(context: RenderingContext, instance: any): void {
117
- //a little bit hacky
118
- if (this.layout) this.layout.items = instance.content;
119
- else this.items = instance.content;
120
- super.explore(context, instance);
121
- }
122
- }
123
-
124
- ContentResolver.prototype.mode = "replace";
1
+ import { PureContainerBase, PureContainerConfig } from "./PureContainer";
2
+ import { isPromise } from "../util/isPromise";
3
+ import { RenderingContext } from "./RenderingContext";
4
+ import { BooleanProp, StructuredProp, ResolveStructuredProp } from "./Prop";
5
+ import { Instance } from "./Instance";
6
+
7
+ /**
8
+ * Configuration for ContentResolver widget.
9
+ *
10
+ * The params type parameter enables type inference for the onResolve callback:
11
+ * - Literal values (numbers, strings, booleans) preserve their types
12
+ * - AccessorChain<T> resolves to T
13
+ * - Bind/Tpl/Expr resolve to any (type cannot be determined at compile time)
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * <ContentResolver
18
+ * params={{
19
+ * count: 42, // number
20
+ * name: model.user.name // AccessorChain<string> -> string
21
+ * }}
22
+ * onResolve={(params) => {
23
+ * // params.count is number, params.name is string
24
+ * }}
25
+ * />
26
+ * ```
27
+ */
28
+ export interface ContentResolverConfig<P extends StructuredProp = StructuredProp> extends PureContainerConfig {
29
+ /** Parameters that trigger content resolution when changed. */
30
+ params?: P;
31
+
32
+ /**
33
+ * Callback function that resolves content based on params. Can return content directly or a Promise.
34
+ * The params type is inferred from the params property - literal values and AccessorChain<T>
35
+ * preserve their types, while bindings (bind/tpl/expr) resolve to `any`.
36
+ */
37
+ onResolve?: string | ((params: ResolveStructuredProp<P>, instance: Instance) => any);
38
+
39
+ /** How to combine resolved content with initial content. Default is 'replace'. */
40
+ mode?: "replace" | "prepend" | "append";
41
+
42
+ /** Indicates if content is being loaded. */
43
+ loading?: BooleanProp;
44
+ }
45
+
46
+ export class ContentResolver<P extends StructuredProp = StructuredProp> extends PureContainerBase<
47
+ ContentResolverConfig<P>
48
+ > {
49
+ constructor(config?: ContentResolverConfig<P>) {
50
+ super(config);
51
+ }
52
+
53
+ declare mode: "replace" | "prepend" | "append";
54
+ declare onResolve?: string | ((params: ResolveStructuredProp<P>, instance: Instance) => any);
55
+ declare initialItems: any;
56
+
57
+ declareData(...args: any[]): void {
58
+ super.declareData(...args, {
59
+ params: { structured: true },
60
+ loading: undefined,
61
+ });
62
+ }
63
+
64
+ init(): void {
65
+ super.init();
66
+ this.initialItems = this.layout ? this.layout.items : this.items;
67
+ this.clear();
68
+ }
69
+
70
+ initInstance(context: RenderingContext, instance: any): void {
71
+ instance.content = this.initialItems;
72
+ instance.cachedParams = {}; //unique value which will never pass the equality check
73
+ }
74
+
75
+ prepareData(context: RenderingContext, instance: any): void {
76
+ let { data } = instance;
77
+
78
+ if (data.params !== instance.cachedParams && this.onResolve) {
79
+ instance.cachedParams = data.params;
80
+ let content = instance.invoke("onResolve", data.params, instance);
81
+ if (isPromise(content)) {
82
+ instance.set("loading", true);
83
+ this.setContent(instance, null);
84
+ content.then((cnt: any) => {
85
+ this.setContent(instance, cnt);
86
+ instance.setState({ cacheBuster: {} });
87
+ instance.set("loading", false);
88
+ });
89
+ } else this.setContent(instance, content);
90
+ }
91
+ }
92
+
93
+ setContent(instance: any, content: any): void {
94
+ if (content) {
95
+ this.clear();
96
+ switch (this.mode) {
97
+ case "prepend":
98
+ this.add(content);
99
+ this.add(this.initialItems);
100
+ break;
101
+
102
+ case "append":
103
+ this.add(this.initialItems);
104
+ this.add(content);
105
+ break;
106
+
107
+ case "replace":
108
+ this.add(content);
109
+ break;
110
+ }
111
+ instance.content = this.layout ? this.layout.items : this.items;
112
+ this.clear();
113
+ } else instance.content = this.initialItems;
114
+ }
115
+
116
+ explore(context: RenderingContext, instance: any): void {
117
+ //a little bit hacky
118
+ if (this.layout) this.layout.items = instance.content;
119
+ else this.items = instance.content;
120
+ super.explore(context, instance);
121
+ }
122
+ }
123
+
124
+ ContentResolver.prototype.mode = "replace";
@@ -1,189 +1,189 @@
1
- import { computable, ComputableSelector, InferSelectorValue } from "../data/computable";
2
- import { Component, ComponentConstructor, ComponentConfigType } from "../util/Component";
3
- import { isArray } from "../util/isArray";
4
- import { isFunction } from "../util/isFunction";
5
- import { StoreProxy } from "../data/StoreProxy";
6
- import { RenderingContext } from "./RenderingContext";
7
- import { View, ViewMethods } from "../data/View";
8
- import { Widget } from "./Widget";
9
- import { Instance } from "./Instance";
10
-
11
- const computablePrefix = "computable-";
12
- const triggerPrefix = "trigger-";
13
-
14
- interface ComputableEntry {
15
- name: string;
16
- selector: any;
17
- type: "computable" | "trigger";
18
- }
19
-
20
- // Controller methods interface for ThisType in config objects
21
- export interface ControllerMethods {
22
- store: View;
23
- instance: Instance;
24
- widget?: Widget;
25
- invokeParentMethod(method: string, ...args: any[]): any;
26
- addTrigger<Selectors extends readonly ComputableSelector[]>(
27
- name: string,
28
- args: [...Selectors],
29
- callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
30
- autoRun?: boolean,
31
- ): void;
32
- addComputable<Selectors extends readonly ComputableSelector[]>(
33
- name: string,
34
- args: [...Selectors],
35
- callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
36
- ): void;
37
- }
38
-
39
- export interface BaseControllerConfig {
40
- store?: View;
41
- instance?: Instance;
42
- widget?: Widget;
43
-
44
- onInit?: (context: RenderingContext) => void;
45
- onExplore?: (context: RenderingContext) => void;
46
- onPrepare?: (context: RenderingContext) => void;
47
- onCleanup?: (context: RenderingContext) => void;
48
- onDestroy?: () => void;
49
- }
50
-
51
- // Controller config object type with Controller methods AND its own methods available on 'this'
52
- export type ControllerConfig<T extends BaseControllerConfig = BaseControllerConfig> = T &
53
- ThisType<ControllerMethods & T>;
54
-
55
- /** Controller factory function type */
56
- export type ControllerFactory<T extends BaseControllerConfig = BaseControllerConfig> = (
57
- config: ViewMethods,
58
- ) => ControllerConfig<T>;
59
-
60
- export class Controller extends Component implements ControllerMethods {
61
- initialized?: boolean;
62
- onInit?(context: RenderingContext): void;
63
- onExplore?(context: RenderingContext): void;
64
- onPrepare?(context: RenderingContext): void;
65
- onCleanup?(context: RenderingContext): void;
66
- onDestroy?(): void;
67
- declare instance: Instance;
68
- declare store: View;
69
- declare widget?: Widget;
70
- computables?: Record<string, ComputableEntry>;
71
-
72
- constructor(config?: BaseControllerConfig) {
73
- super(config);
74
- }
75
-
76
- init(context?: RenderingContext): void {
77
- if (!this.initialized) {
78
- this.initialized = true;
79
- if (this.onInit && context) this.onInit(context);
80
- }
81
- }
82
-
83
- explore(context: RenderingContext): void {
84
- let { store } = this.instance;
85
- this.store = store; //in rare cases instance may change its store
86
-
87
- if (!this.initialized) {
88
- this.init(context);
89
- //forgive if the developer forgets to call super.init()
90
- this.initialized = true;
91
- }
92
-
93
- if (this.computables) {
94
- for (let key in this.computables) {
95
- let x = this.computables[key];
96
- let v = x.selector(store.getData());
97
- if (x.type == "computable") store.set(x.name, v);
98
- }
99
- }
100
-
101
- if (this.onExplore) {
102
- this.onExplore(context);
103
- }
104
- }
105
-
106
- prepare(context: RenderingContext): void {
107
- if (this.onPrepare) {
108
- this.onPrepare(context);
109
- }
110
- }
111
-
112
- cleanup(context: RenderingContext): void {
113
- if (this.onCleanup) {
114
- this.onCleanup(context);
115
- }
116
- }
117
-
118
- addComputable<Selectors extends readonly ComputableSelector[]>(
119
- name: string,
120
- args: [...Selectors],
121
- callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
122
- ): void {
123
- if (!isArray(args)) throw new Error("Second argument to the addComputable method should be an array.");
124
- let selector = computable(...args, callback).memoize();
125
- if (!this.computables) this.computables = {};
126
- this.computables[computablePrefix + name] = { name, selector, type: "computable" };
127
- }
128
-
129
- addTrigger<Selectors extends readonly ComputableSelector[]>(
130
- name: string,
131
- args: [...Selectors],
132
- callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
133
- autoRun?: boolean,
134
- ): void {
135
- if (!isArray(args)) throw new Error("Second argument to the addTrigger method should be an array.");
136
- let selector = computable(...args, callback).memoize(!autoRun && this.store.getData());
137
- if (!this.computables) this.computables = {};
138
- this.computables[triggerPrefix + name] = { name, selector, type: "trigger" };
139
- }
140
-
141
- removeTrigger(name: string): void {
142
- if (this.computables) delete this.computables[triggerPrefix + name];
143
- }
144
-
145
- removeComputable(name: string): void {
146
- if (this.computables) delete this.computables[computablePrefix + name];
147
- }
148
-
149
- invokeParentMethod(methodName: string, ...args: any[]): any {
150
- let parent = this.instance.parent;
151
- if (!parent) throw new Error("Cannot invoke a parent controller method as the instance does not have a parent.");
152
- return parent.invokeControllerMethod(methodName, ...args);
153
- }
154
-
155
- invokeMethod(methodName: string, ...args: any[]): any {
156
- return this.instance.invokeControllerMethod(methodName, ...args);
157
- }
158
- }
159
-
160
- Controller.namespace = "ui.controller.";
161
-
162
- Controller.factory = function (alias: any, config?: any, more?: any) {
163
- if (isFunction(alias)) {
164
- let cfg = {
165
- ...config,
166
- ...more,
167
- };
168
-
169
- if (cfg.instance) {
170
- //in rare cases instance.store may change, so we cannot rely on the store passed through configuration
171
- cfg.store = new StoreProxy(() => cfg.instance.store);
172
- Object.assign(cfg, cfg.store.getMethods());
173
- }
174
-
175
- let result = alias(cfg);
176
- if (result instanceof Controller) return result;
177
-
178
- return Controller.create({
179
- ...config,
180
- ...more,
181
- ...result,
182
- });
183
- }
184
-
185
- return Controller.create({
186
- ...config,
187
- ...more,
188
- });
189
- };
1
+ import { computable, ComputableSelector, InferSelectorValue } from "../data/computable";
2
+ import { Component, ComponentConstructor, ComponentConfigType } from "../util/Component";
3
+ import { isArray } from "../util/isArray";
4
+ import { isFunction } from "../util/isFunction";
5
+ import { StoreProxy } from "../data/StoreProxy";
6
+ import { RenderingContext } from "./RenderingContext";
7
+ import { View, ViewMethods } from "../data/View";
8
+ import { Widget } from "./Widget";
9
+ import { Instance } from "./Instance";
10
+
11
+ const computablePrefix = "computable-";
12
+ const triggerPrefix = "trigger-";
13
+
14
+ interface ComputableEntry {
15
+ name: string;
16
+ selector: any;
17
+ type: "computable" | "trigger";
18
+ }
19
+
20
+ // Controller methods interface for ThisType in config objects
21
+ export interface ControllerMethods {
22
+ store: View;
23
+ instance: Instance;
24
+ widget?: Widget;
25
+ invokeParentMethod(method: string, ...args: any[]): any;
26
+ addTrigger<Selectors extends readonly ComputableSelector[]>(
27
+ name: string,
28
+ args: [...Selectors],
29
+ callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
30
+ autoRun?: boolean,
31
+ ): void;
32
+ addComputable<Selectors extends readonly ComputableSelector[]>(
33
+ name: string,
34
+ args: [...Selectors],
35
+ callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
36
+ ): void;
37
+ }
38
+
39
+ export interface BaseControllerConfig {
40
+ store?: View;
41
+ instance?: Instance;
42
+ widget?: Widget;
43
+
44
+ onInit?: (context: RenderingContext) => void;
45
+ onExplore?: (context: RenderingContext) => void;
46
+ onPrepare?: (context: RenderingContext) => void;
47
+ onCleanup?: (context: RenderingContext) => void;
48
+ onDestroy?: () => void;
49
+ }
50
+
51
+ // Controller config object type with Controller methods AND its own methods available on 'this'
52
+ export type ControllerConfig<T extends BaseControllerConfig = BaseControllerConfig> = T &
53
+ ThisType<ControllerMethods & T>;
54
+
55
+ /** Controller factory function type */
56
+ export type ControllerFactory<T extends BaseControllerConfig = BaseControllerConfig> = (
57
+ config: ViewMethods,
58
+ ) => ControllerConfig<T>;
59
+
60
+ export class Controller extends Component implements ControllerMethods {
61
+ initialized?: boolean;
62
+ onInit?(context: RenderingContext): void;
63
+ onExplore?(context: RenderingContext): void;
64
+ onPrepare?(context: RenderingContext): void;
65
+ onCleanup?(context: RenderingContext): void;
66
+ onDestroy?(): void;
67
+ declare instance: Instance;
68
+ declare store: View;
69
+ declare widget?: Widget;
70
+ computables?: Record<string, ComputableEntry>;
71
+
72
+ constructor(config?: BaseControllerConfig) {
73
+ super(config);
74
+ }
75
+
76
+ init(context?: RenderingContext): void {
77
+ if (!this.initialized) {
78
+ this.initialized = true;
79
+ if (this.onInit && context) this.onInit(context);
80
+ }
81
+ }
82
+
83
+ explore(context: RenderingContext): void {
84
+ let { store } = this.instance;
85
+ this.store = store; //in rare cases instance may change its store
86
+
87
+ if (!this.initialized) {
88
+ this.init(context);
89
+ //forgive if the developer forgets to call super.init()
90
+ this.initialized = true;
91
+ }
92
+
93
+ if (this.computables) {
94
+ for (let key in this.computables) {
95
+ let x = this.computables[key];
96
+ let v = x.selector(store.getData());
97
+ if (x.type == "computable") store.set(x.name, v);
98
+ }
99
+ }
100
+
101
+ if (this.onExplore) {
102
+ this.onExplore(context);
103
+ }
104
+ }
105
+
106
+ prepare(context: RenderingContext): void {
107
+ if (this.onPrepare) {
108
+ this.onPrepare(context);
109
+ }
110
+ }
111
+
112
+ cleanup(context: RenderingContext): void {
113
+ if (this.onCleanup) {
114
+ this.onCleanup(context);
115
+ }
116
+ }
117
+
118
+ addComputable<Selectors extends readonly ComputableSelector[]>(
119
+ name: string,
120
+ args: [...Selectors],
121
+ callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
122
+ ): void {
123
+ if (!isArray(args)) throw new Error("Second argument to the addComputable method should be an array.");
124
+ let selector = computable(...args, callback).memoize();
125
+ if (!this.computables) this.computables = {};
126
+ this.computables[computablePrefix + name] = { name, selector, type: "computable" };
127
+ }
128
+
129
+ addTrigger<Selectors extends readonly ComputableSelector[]>(
130
+ name: string,
131
+ args: [...Selectors],
132
+ callback: (...values: { [K in keyof Selectors]: InferSelectorValue<Selectors[K]> }) => any,
133
+ autoRun?: boolean,
134
+ ): void {
135
+ if (!isArray(args)) throw new Error("Second argument to the addTrigger method should be an array.");
136
+ let selector = computable(...args, callback).memoize(!autoRun && this.store.getData());
137
+ if (!this.computables) this.computables = {};
138
+ this.computables[triggerPrefix + name] = { name, selector, type: "trigger" };
139
+ }
140
+
141
+ removeTrigger(name: string): void {
142
+ if (this.computables) delete this.computables[triggerPrefix + name];
143
+ }
144
+
145
+ removeComputable(name: string): void {
146
+ if (this.computables) delete this.computables[computablePrefix + name];
147
+ }
148
+
149
+ invokeParentMethod(methodName: string, ...args: any[]): any {
150
+ let parent = this.instance.parent;
151
+ if (!parent) throw new Error("Cannot invoke a parent controller method as the instance does not have a parent.");
152
+ return parent.invokeControllerMethod(methodName, ...args);
153
+ }
154
+
155
+ invokeMethod(methodName: string, ...args: any[]): any {
156
+ return this.instance.invokeControllerMethod(methodName, ...args);
157
+ }
158
+ }
159
+
160
+ Controller.namespace = "ui.controller.";
161
+
162
+ Controller.factory = function (alias: any, config?: any, more?: any) {
163
+ if (isFunction(alias)) {
164
+ let cfg = {
165
+ ...config,
166
+ ...more,
167
+ };
168
+
169
+ if (cfg.instance) {
170
+ //in rare cases instance.store may change, so we cannot rely on the store passed through configuration
171
+ cfg.store = new StoreProxy(() => cfg.instance.store);
172
+ Object.assign(cfg, cfg.store.getMethods());
173
+ }
174
+
175
+ let result = alias(cfg);
176
+ if (result instanceof Controller) return result;
177
+
178
+ return Controller.create({
179
+ ...config,
180
+ ...more,
181
+ ...result,
182
+ });
183
+ }
184
+
185
+ return Controller.create({
186
+ ...config,
187
+ ...more,
188
+ });
189
+ };