@xh/hoist 83.1.0 → 84.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/admin/tabs/cluster/instances/logs/levels/LogLevelDialogModel.ts +106 -10
  3. package/admin/tabs/cluster/metrics/MetricsModel.ts +3 -3
  4. package/appcontainer/AppContainerModel.ts +1 -1
  5. package/appcontainer/README.md +20 -0
  6. package/assets.d.ts +34 -0
  7. package/build/types/cmp/ag-grid/AgGrid.d.ts +8 -19
  8. package/build/types/cmp/ag-grid/AgGridModel.d.ts +18 -5
  9. package/build/types/cmp/card/Card.d.ts +9 -4
  10. package/build/types/cmp/card/CardModel.d.ts +15 -2
  11. package/build/types/cmp/chart/Chart.d.ts +2 -2
  12. package/build/types/cmp/chart/ChartModel.d.ts +11 -1
  13. package/build/types/cmp/dataview/DataView.d.ts +4 -2
  14. package/build/types/cmp/dataview/DataViewModel.d.ts +16 -4
  15. package/build/types/cmp/filter/FilterChooserModel.d.ts +7 -1
  16. package/build/types/cmp/form/Form.d.ts +2 -1
  17. package/build/types/cmp/form/FormModel.d.ts +12 -0
  18. package/build/types/cmp/form/field/BaseFieldModel.d.ts +7 -0
  19. package/build/types/cmp/form/formfieldset/FormFieldSetModel.d.ts +7 -1
  20. package/build/types/cmp/grid/GridModel.d.ts +16 -1
  21. package/build/types/cmp/grid/GridSorter.d.ts +14 -0
  22. package/build/types/cmp/grid/Types.d.ts +18 -0
  23. package/build/types/cmp/grid/columns/Column.d.ts +40 -2
  24. package/build/types/cmp/grid/columns/ColumnGroup.d.ts +10 -0
  25. package/build/types/cmp/grouping/GroupingChooserModel.d.ts +9 -2
  26. package/build/types/cmp/layout/Box.d.ts +19 -7
  27. package/build/types/cmp/layout/Frame.d.ts +17 -5
  28. package/build/types/cmp/loadingindicator/LoadingIndicator.d.ts +6 -4
  29. package/build/types/cmp/pinpad/PinPadModel.d.ts +6 -1
  30. package/build/types/cmp/spinner/Spinner.d.ts +31 -10
  31. package/build/types/cmp/tab/TabContainerModel.d.ts +11 -0
  32. package/build/types/cmp/tab/TabModel.d.ts +7 -0
  33. package/build/types/cmp/tab/Types.d.ts +4 -0
  34. package/build/types/cmp/treemap/TreeMapModel.d.ts +3 -3
  35. package/build/types/cmp/viewmanager/ViewManagerModel.d.ts +9 -0
  36. package/build/types/cmp/zoneGrid/ZoneGridModel.d.ts +22 -3
  37. package/build/types/cmp/zoneGrid/impl/ZoneMapperModel.d.ts +6 -0
  38. package/build/types/core/HoistComponent.d.ts +29 -8
  39. package/build/types/core/HoistProps.d.ts +9 -3
  40. package/build/types/core/load/LoadSpec.d.ts +1 -1
  41. package/build/types/core/persist/provider/ViewManagerProvider.d.ts +7 -0
  42. package/build/types/data/Store.d.ts +35 -1
  43. package/build/types/data/StoreSelectionModel.d.ts +18 -2
  44. package/build/types/data/cube/Cube.d.ts +26 -6
  45. package/build/types/data/cube/Query.d.ts +10 -0
  46. package/build/types/data/cube/View.d.ts +21 -2
  47. package/build/types/data/cube/aggregate/Aggregator.d.ts +13 -0
  48. package/build/types/data/cube/aggregate/AverageAggregator.d.ts +1 -0
  49. package/build/types/data/cube/aggregate/AverageStrictAggregator.d.ts +1 -0
  50. package/build/types/data/cube/aggregate/ChildCountAggregator.d.ts +1 -0
  51. package/build/types/data/cube/aggregate/LeafCountAggregator.d.ts +1 -0
  52. package/build/types/data/cube/aggregate/MaxAggregator.d.ts +1 -0
  53. package/build/types/data/cube/aggregate/MinAggregator.d.ts +1 -0
  54. package/build/types/data/cube/aggregate/NullAggregator.d.ts +1 -0
  55. package/build/types/data/cube/aggregate/SingleAggregator.d.ts +1 -0
  56. package/build/types/data/cube/aggregate/SumAggregator.d.ts +1 -0
  57. package/build/types/data/cube/aggregate/SumStrictAggregator.d.ts +1 -0
  58. package/build/types/data/cube/aggregate/UniqueAggregator.d.ts +1 -0
  59. package/build/types/data/filter/BaseFilterFieldSpec.d.ts +9 -0
  60. package/build/types/data/filter/Types.d.ts +12 -0
  61. package/build/types/desktop/cmp/button/AppMenuButton.d.ts +5 -0
  62. package/build/types/desktop/cmp/button/Button.d.ts +5 -1
  63. package/build/types/desktop/cmp/dash/canvas/DashCanvasModel.d.ts +12 -3
  64. package/build/types/desktop/cmp/dash/container/DashContainerModel.d.ts +9 -0
  65. package/build/types/desktop/cmp/dock/DockViewModel.d.ts +7 -0
  66. package/build/types/desktop/cmp/filechooser/FileChooserModel.d.ts +8 -0
  67. package/build/types/desktop/cmp/grid/editors/BooleanEditor.d.ts +1 -0
  68. package/build/types/desktop/cmp/grid/editors/DateEditor.d.ts +1 -0
  69. package/build/types/desktop/cmp/grid/editors/NumberEditor.d.ts +1 -0
  70. package/build/types/desktop/cmp/grid/editors/SelectEditor.d.ts +1 -0
  71. package/build/types/desktop/cmp/grid/editors/TextAreaEditor.d.ts +1 -0
  72. package/build/types/desktop/cmp/grid/editors/TextEditor.d.ts +1 -0
  73. package/build/types/desktop/cmp/input/Picker.d.ts +1 -1
  74. package/build/types/desktop/cmp/input/SegmentedControl.d.ts +16 -2
  75. package/build/types/desktop/cmp/leftrightchooser/LeftRightChooserModel.d.ts +7 -0
  76. package/build/types/desktop/cmp/modalsupport/ModalSupportModel.d.ts +28 -2
  77. package/build/types/desktop/cmp/panel/Panel.d.ts +5 -2
  78. package/build/types/desktop/cmp/panel/PanelModel.d.ts +12 -2
  79. package/build/types/desktop/cmp/rest/RestGrid.d.ts +10 -0
  80. package/build/types/desktop/cmp/rest/RestGridModel.d.ts +9 -1
  81. package/build/types/desktop/cmp/toolbar/Toolbar.d.ts +4 -1
  82. package/build/types/format/FormatDate.d.ts +4 -4
  83. package/build/types/icon/Icon.d.ts +3 -0
  84. package/build/types/kit/blueprint/Wrappers.d.ts +12 -1
  85. package/build/types/mobile/cmp/navigator/NavigatorModel.d.ts +8 -0
  86. package/build/types/mobile/cmp/navigator/PageModel.d.ts +7 -0
  87. package/build/types/mobile/cmp/panel/DialogPanel.d.ts +0 -2
  88. package/build/types/security/BaseOAuthClient.d.ts +9 -0
  89. package/build/types/security/authzero/AuthZeroClient.d.ts +6 -0
  90. package/build/types/security/msal/MsalClient.d.ts +6 -0
  91. package/build/types/svc/FetchService.d.ts +10 -7
  92. package/build/types/svc/TraceService.d.ts +17 -2
  93. package/build/types/utils/async/Timer.d.ts +6 -0
  94. package/build/types/utils/js/LangUtils.d.ts +1 -1
  95. package/build/types/utils/js/TestUtils.d.ts +1 -1
  96. package/build/types/utils/react/index.d.ts +0 -1
  97. package/build/types/utils/telemetry/Span.d.ts +12 -2
  98. package/cmp/ag-grid/AgGrid.ts +8 -19
  99. package/cmp/ag-grid/AgGridModel.ts +18 -5
  100. package/cmp/card/Card.ts +9 -4
  101. package/cmp/card/CardModel.ts +15 -2
  102. package/cmp/chart/Chart.ts +2 -2
  103. package/cmp/chart/ChartModel.ts +11 -1
  104. package/cmp/dataview/DataView.ts +4 -2
  105. package/cmp/dataview/DataViewModel.ts +16 -4
  106. package/cmp/filter/FilterChooserModel.ts +7 -1
  107. package/cmp/form/Form.ts +2 -1
  108. package/cmp/form/FormModel.ts +12 -0
  109. package/cmp/form/README.md +13 -0
  110. package/cmp/form/field/BaseFieldModel.ts +7 -0
  111. package/cmp/form/formfieldset/FormFieldSetModel.ts +7 -1
  112. package/cmp/grid/Grid.scss +14 -8
  113. package/cmp/grid/GridModel.ts +16 -1
  114. package/cmp/grid/GridSorter.ts +14 -0
  115. package/cmp/grid/README.md +12 -0
  116. package/cmp/grid/Types.ts +18 -0
  117. package/cmp/grid/columns/Column.ts +40 -2
  118. package/cmp/grid/columns/ColumnGroup.ts +10 -0
  119. package/cmp/grouping/GroupingChooserModel.ts +9 -2
  120. package/cmp/layout/Box.ts +19 -7
  121. package/cmp/layout/Frame.ts +17 -5
  122. package/cmp/layout/README.md +16 -21
  123. package/cmp/loadingindicator/LoadingIndicator.scss +1 -1
  124. package/cmp/loadingindicator/LoadingIndicator.ts +11 -9
  125. package/cmp/pinpad/PinPadModel.ts +6 -1
  126. package/cmp/spinner/Spinner.scss +13 -0
  127. package/cmp/spinner/Spinner.ts +58 -20
  128. package/cmp/tab/TabContainerModel.ts +11 -0
  129. package/cmp/tab/TabModel.ts +7 -0
  130. package/cmp/tab/Types.ts +4 -0
  131. package/cmp/treemap/TreeMapModel.ts +3 -3
  132. package/cmp/viewmanager/ViewManagerModel.ts +9 -0
  133. package/cmp/zoneGrid/ZoneGridModel.ts +22 -3
  134. package/cmp/zoneGrid/impl/ZoneMapperModel.ts +6 -0
  135. package/core/ExceptionHandler.ts +1 -1
  136. package/core/HoistComponent.ts +36 -11
  137. package/core/HoistProps.ts +9 -3
  138. package/core/README.md +68 -6
  139. package/core/impl/InstanceManager.ts +1 -0
  140. package/core/load/LoadSpec.ts +1 -1
  141. package/core/persist/provider/ViewManagerProvider.ts +7 -0
  142. package/data/README.md +48 -124
  143. package/data/Store.ts +35 -1
  144. package/data/StoreSelectionModel.ts +18 -2
  145. package/data/cube/Cube.ts +26 -6
  146. package/data/cube/Query.ts +10 -0
  147. package/data/cube/README.md +236 -0
  148. package/data/cube/View.ts +21 -2
  149. package/data/cube/aggregate/Aggregator.ts +13 -0
  150. package/data/cube/aggregate/AverageAggregator.ts +1 -0
  151. package/data/cube/aggregate/AverageStrictAggregator.ts +1 -0
  152. package/data/cube/aggregate/ChildCountAggregator.ts +1 -0
  153. package/data/cube/aggregate/LeafCountAggregator.ts +1 -0
  154. package/data/cube/aggregate/MaxAggregator.ts +1 -0
  155. package/data/cube/aggregate/MinAggregator.ts +1 -0
  156. package/data/cube/aggregate/NullAggregator.ts +1 -0
  157. package/data/cube/aggregate/SingleAggregator.ts +1 -0
  158. package/data/cube/aggregate/SumAggregator.ts +1 -0
  159. package/data/cube/aggregate/SumStrictAggregator.ts +1 -0
  160. package/data/cube/aggregate/UniqueAggregator.ts +1 -0
  161. package/data/filter/BaseFilterFieldSpec.ts +9 -0
  162. package/data/filter/Types.ts +12 -0
  163. package/desktop/README.md +131 -9
  164. package/desktop/appcontainer/AboutDialog.ts +2 -0
  165. package/desktop/appcontainer/Banner.ts +5 -2
  166. package/desktop/appcontainer/ChangelogDialog.ts +1 -0
  167. package/desktop/appcontainer/ExceptionDialog.ts +4 -0
  168. package/desktop/appcontainer/ExceptionDialogDetails.ts +4 -1
  169. package/desktop/appcontainer/FeedbackDialog.ts +4 -1
  170. package/desktop/appcontainer/ImpersonationBar.ts +4 -0
  171. package/desktop/appcontainer/LockoutPanel.ts +4 -1
  172. package/desktop/appcontainer/LoginPanel.ts +7 -3
  173. package/desktop/appcontainer/Message.ts +9 -3
  174. package/desktop/appcontainer/OptionsDialog.ts +3 -1
  175. package/desktop/appcontainer/VersionBar.ts +1 -0
  176. package/desktop/appcontainer/suspend/IdlePanel.ts +4 -4
  177. package/desktop/appcontainer/suspend/SuspendPanel.ts +3 -0
  178. package/desktop/cmp/button/AppMenuButton.ts +5 -0
  179. package/desktop/cmp/button/Button.ts +14 -4
  180. package/desktop/cmp/dash/README.md +14 -0
  181. package/desktop/cmp/dash/canvas/DashCanvasModel.ts +12 -3
  182. package/desktop/cmp/dash/container/DashContainerModel.ts +9 -0
  183. package/desktop/cmp/dock/DockViewModel.ts +7 -0
  184. package/desktop/cmp/filechooser/FileChooserModel.ts +9 -2
  185. package/desktop/cmp/grid/editors/BooleanEditor.ts +1 -0
  186. package/desktop/cmp/grid/editors/DateEditor.ts +1 -0
  187. package/desktop/cmp/grid/editors/NumberEditor.ts +1 -0
  188. package/desktop/cmp/grid/editors/SelectEditor.ts +1 -0
  189. package/desktop/cmp/grid/editors/TextAreaEditor.ts +1 -0
  190. package/desktop/cmp/grid/editors/TextEditor.ts +1 -0
  191. package/desktop/cmp/input/Picker.ts +2 -2
  192. package/desktop/cmp/input/SegmentedControl.ts +20 -2
  193. package/desktop/cmp/leftrightchooser/LeftRightChooserModel.ts +7 -0
  194. package/desktop/cmp/modalsupport/ModalSupportModel.ts +31 -2
  195. package/desktop/cmp/panel/Panel.ts +29 -21
  196. package/desktop/cmp/panel/PanelModel.ts +12 -2
  197. package/desktop/cmp/panel/README.md +20 -0
  198. package/desktop/cmp/rest/RestGrid.ts +10 -0
  199. package/desktop/cmp/rest/RestGridModel.ts +9 -1
  200. package/desktop/cmp/toolbar/Toolbar.ts +9 -2
  201. package/desktop/cmp/viewmanager/ViewManager.ts +1 -1
  202. package/docs/README.md +9 -4
  203. package/docs/coding-conventions.md +29 -21
  204. package/docs/doc-registry.json +31 -15
  205. package/docs/planning/docs-roadmap-log.md +11 -0
  206. package/docs/planning/docs-roadmap.md +1 -0
  207. package/docs/upgrade-notes/v84-upgrade-notes.md +136 -0
  208. package/docs/version-compatibility.md +2 -0
  209. package/format/FormatDate.ts +4 -4
  210. package/icon/Icon.ts +9 -0
  211. package/icon/README.md +62 -22
  212. package/icon/index.ts +24 -0
  213. package/kit/README.md +8 -2
  214. package/kit/blueprint/Wrappers.ts +12 -1
  215. package/mcp/README.md +47 -26
  216. package/mcp/cli/ts.ts +39 -4
  217. package/mcp/data/ts-registry.ts +57 -17
  218. package/mcp/tools/typescript.ts +32 -4
  219. package/mobile/appcontainer/AboutDialog.ts +3 -0
  220. package/mobile/appcontainer/Banner.ts +2 -0
  221. package/mobile/appcontainer/ExceptionDialog.ts +4 -0
  222. package/mobile/appcontainer/ExceptionDialogDetails.ts +1 -0
  223. package/mobile/appcontainer/FeedbackDialog.ts +4 -1
  224. package/mobile/appcontainer/ImpersonationBar.ts +2 -0
  225. package/mobile/appcontainer/LockoutPanel.ts +2 -0
  226. package/mobile/appcontainer/LoginPanel.ts +7 -3
  227. package/mobile/appcontainer/Message.ts +9 -3
  228. package/mobile/appcontainer/OptionsDialog.ts +5 -1
  229. package/mobile/appcontainer/VersionBar.ts +1 -0
  230. package/mobile/appcontainer/suspend/IdlePanel.ts +5 -6
  231. package/mobile/appcontainer/suspend/SuspendPanel.ts +3 -0
  232. package/mobile/cmp/navigator/NavigatorModel.ts +8 -0
  233. package/mobile/cmp/navigator/PageModel.ts +7 -0
  234. package/mobile/cmp/panel/DialogPanel.ts +0 -2
  235. package/package.json +11 -11
  236. package/security/BaseOAuthClient.ts +9 -0
  237. package/security/authzero/AuthZeroClient.ts +6 -0
  238. package/security/msal/MsalClient.ts +6 -0
  239. package/styles/vars.scss +14 -0
  240. package/svc/FetchService.ts +25 -15
  241. package/svc/README.md +39 -9
  242. package/svc/TraceService.ts +69 -11
  243. package/utils/README.md +0 -1
  244. package/utils/async/Timer.ts +6 -0
  245. package/utils/js/LangUtils.ts +1 -1
  246. package/utils/js/TestUtils.ts +1 -1
  247. package/utils/react/index.ts +0 -1
  248. package/utils/telemetry/Span.ts +21 -4
  249. package/build/types/utils/react/ClassName.d.ts +0 -14
  250. package/utils/react/ClassName.ts +0 -24
package/data/README.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Data Package
2
2
 
3
+ | Section | Description |
4
+ |---------|-------------|
5
+ | [Overview](#overview) | Core classes, architecture diagram |
6
+ | [Store](#store) | Creating, loading, filtering, and observing record collections |
7
+ | [StoreRecord](#storerecord) | Record state, data access, tree navigation, validation |
8
+ | [Field](#field) | Type parsing, display names, descriptions, validation rules |
9
+ | [Filter System](#filter-system) | FieldFilter, CompoundFilter, FunctionFilter, and utilities |
10
+ | [Validation System](#validation-system) | Rules, constraints, severity levels, async validation |
11
+ | [Integration with GridModel](#integration-with-gridmodel) | Inline store config, data loading, and editing |
12
+ | [Tree Data](#tree-data) | Hierarchical loading, filtering, and summary records |
13
+ | [Cube (Aggregation)](#cube-aggregation) | Pointer to dedicated [`cube/README.md`](cube/README.md) |
14
+ | [Common Patterns](#common-patterns) | Record reuse, processRawData, composite IDs |
15
+ | [Common Pitfalls](#common-pitfalls) | ID fields, missing IDs, data mutation, FunctionFilter persistence |
16
+
3
17
  ## Overview
4
18
 
5
19
  The `/data/` package provides Hoist's data management layer - observable, in-memory data containers
@@ -603,6 +617,36 @@ record.errors; // Map<field, string[]>
603
617
  record.validationResults; // Map<field, ValidationResult[]>
604
618
  ```
605
619
 
620
+ ## Integration with GridModel
621
+
622
+ Stores are the primary data source for GridModel:
623
+
624
+ ```typescript
625
+ import {GridModel} from '@xh/hoist/cmp/grid';
626
+ import {numberEditor} from '@xh/hoist/desktop/cmp/grid';
627
+
628
+ const gridModel = new GridModel({
629
+ // Inline store config
630
+ store: {
631
+ fields: [
632
+ {name: 'name', type: 'string'},
633
+ {name: 'salary', type: 'number', rules: [required]}
634
+ ]
635
+ },
636
+ columns: [
637
+ {field: 'name', flex: 1},
638
+ {field: 'salary', width: 120, editable: true, editor: numberEditor()}
639
+ ]
640
+ });
641
+
642
+ // Load data through GridModel (delegates to store)
643
+ gridModel.loadData(data);
644
+
645
+ // Access store directly
646
+ gridModel.store.records;
647
+ gridModel.store.setFilter({field: 'salary', op: '>', value: 50000});
648
+ ```
649
+
606
650
  ## Tree Data
607
651
 
608
652
  Stores provide full support for hierarchical parent-child data.
@@ -690,130 +734,10 @@ See `cmp/grid/GridModel.ts` for details on summary row rendering.
690
734
 
691
735
  ## Cube (Aggregation)
692
736
 
693
- **Files**: `cube/Cube.ts`, `cube/CubeField.ts`, `cube/Query.ts`, `cube/View.ts`
694
-
695
- Multi-dimensional aggregation for OLAP-style grouping and analysis.
696
-
697
- ### Creating a Cube
698
-
699
- ```typescript
700
- import {Cube} from '@xh/hoist/data';
701
-
702
- const cube = new Cube({
703
- fields: [
704
- // Dimensions - can be grouped on
705
- {name: 'region', isDimension: true},
706
- {name: 'product', isDimension: true},
707
- {name: 'year', isDimension: true},
708
-
709
- // Measures - aggregated values
710
- {name: 'revenue', aggregator: 'SUM'},
711
- {name: 'quantity', aggregator: 'SUM'},
712
- {name: 'avgPrice', aggregator: 'AVG'}
713
- ]
714
- });
715
-
716
- await cube.loadDataAsync(salesData);
717
- ```
718
-
719
- ### Built-in Aggregators
720
-
721
- | Aggregator | Description |
722
- |------------|-------------|
723
- | `'SUM'` | Total of non-null values |
724
- | `'SUM_STRICT'` | Total only if all non-null |
725
- | `'AVG'` | Average of non-null values |
726
- | `'AVG_STRICT'` | Average only if all non-null |
727
- | `'MIN'` | Minimum value |
728
- | `'MAX'` | Maximum value |
729
- | `'UNIQUE'` | Count of unique values |
730
- | `'LEAF_COUNT'` | Count of leaf records |
731
- | `'CHILD_COUNT'` | Count of immediate children |
732
-
733
- ### Querying and Accessing View Data
734
-
735
- ```typescript
736
- // Create a view with specific groupings
737
- const view = cube.createView({
738
- query: {
739
- cube,
740
- dimensions: ['region', 'product'],
741
- filter: {field: 'year', op: '=', value: 2024},
742
- includeLeaves: false,
743
- includeRoot: true
744
- },
745
- connect: true // Auto-update when cube data changes
746
- });
747
- ```
748
-
749
- There are two primary ways to access view data:
750
-
751
- **Option 1: Read `view.result` directly**
752
-
753
- The observable `ViewResult` contains hierarchical `ViewRowData` objects:
754
-
755
- ```typescript
756
- // React to view updates
757
- addReaction({
758
- track: () => view.result,
759
- run: (result) => {
760
- const {rows, leafMap} = result;
761
- // rows: ViewRowData[] - hierarchical aggregated data
762
- // leafMap: Map<id, LeafRow> - direct access to leaf-level rows
763
- }
764
- });
765
- ```
766
-
767
- **Option 2: Connect stores for automatic loading**
768
-
769
- Provide one or more stores that the view will automatically populate:
770
-
771
- ```typescript
772
- const store = new Store({fields: [...]});
773
-
774
- const view = cube.createView({
775
- query: {...},
776
- stores: store, // View auto-loads data into this store
777
- connect: true
778
- });
779
-
780
- // Store now receives updates automatically
781
- gridModel.store === store; // Use with GridModel
782
- ```
783
-
784
- **Update triggers:** View data updates when either:
785
- - The underlying Cube data changes (requires `connect: true`)
786
- - The `view.query` is modified via `view.updateQuery()`
787
-
788
- ## Integration with GridModel
789
-
790
- Stores are the primary data source for GridModel:
791
-
792
- ```typescript
793
- import {GridModel} from '@xh/hoist/cmp/grid';
794
- import {numberEditor} from '@xh/hoist/desktop/cmp/grid';
795
-
796
- const gridModel = new GridModel({
797
- // Inline store config
798
- store: {
799
- fields: [
800
- {name: 'name', type: 'string'},
801
- {name: 'salary', type: 'number', rules: [required]}
802
- ]
803
- },
804
- columns: [
805
- {field: 'name', flex: 1},
806
- {field: 'salary', width: 120, editable: true, editor: numberEditor()}
807
- ]
808
- });
809
-
810
- // Load data through GridModel (delegates to store)
811
- gridModel.loadData(data);
812
-
813
- // Access store directly
814
- gridModel.store.records;
815
- gridModel.store.setFilter({field: 'salary', op: '>', value: 50000});
816
- ```
737
+ Client-side OLAP-style aggregation for multi-dimensional grouping and analysis. The Cube
738
+ subsystem has its own dedicated documentation — see the
739
+ [Cube package README](cube/README.md) for full coverage of creating Cubes, aggregators,
740
+ querying with Views, and accessing results.
817
741
 
818
742
  ## Common Patterns
819
743
 
package/data/Store.ts CHANGED
@@ -47,6 +47,20 @@ import {
47
47
  import {instanceManager} from '../core/impl/InstanceManager';
48
48
  import {RecordSet} from './impl/RecordSet';
49
49
 
50
+ /**
51
+ * Configuration for a {@link Store}. At minimum, provide `fields` (or let them be inferred
52
+ * from GridModel columns). Data can be supplied at construction via `data`, or loaded later
53
+ * via `Store.loadData()`.
54
+ *
55
+ * Can also be passed inline as the `store` config on {@link GridConfig}, where it will be
56
+ * used to construct a Store automatically.
57
+ *
58
+ * See the data package README (`data/README.md`) for tree data, filtering, validation, and
59
+ * performance tuning guidance.
60
+ *
61
+ * @see Store
62
+ * @see FieldSpec
63
+ */
50
64
  export interface StoreConfig {
51
65
  /** Field names, configs, or instances. */
52
66
  fields?: Array<string | FieldSpec | Field>;
@@ -203,7 +217,27 @@ export interface ChildRawData {
203
217
  export type StoreRecordIdSpec = string | ((data: PlainObject) => StoreRecordId);
204
218
 
205
219
  /**
206
- * A managed and observable set of local, in-memory Records.
220
+ * A managed, observable collection of in-memory {@link StoreRecord}s - the core data container
221
+ * in Hoist. Used directly by applications and as the data source for {@link GridModel},
222
+ * {@link DataViewModel}, and other data-bound components.
223
+ *
224
+ * Stores provide:
225
+ * - Observable record collections with filtering via composable {@link Filter} objects
226
+ * - Hierarchical/tree data with parent-child navigation
227
+ * - Local modification tracking (add/modify/remove) with commit/revert
228
+ * - Record reuse across data reloads to preserve grid row state
229
+ * - Pluggable validation via {@link Field} rules
230
+ *
231
+ * Data is loaded via `loadData()` (full replacement) or `updateData()` (transactional). Fields
232
+ * can be defined explicitly or inferred from GridModel columns. `Store.defaults` provides
233
+ * app-wide configuration.
234
+ *
235
+ * See the data package README (`data/README.md`) for full documentation including tree data,
236
+ * filtering patterns, validation, and common pitfalls.
237
+ *
238
+ * @see StoreConfig
239
+ * @see StoreRecord
240
+ * @see Field
207
241
  */
208
242
  export class Store
209
243
  extends HoistBase
@@ -11,15 +11,31 @@ import {castArray, compact, remove, isEqual, union, map} from 'lodash';
11
11
  import {Store} from './Store';
12
12
  import {StoreRecord, StoreRecordId, StoreRecordOrId} from './StoreRecord';
13
13
 
14
+ /**
15
+ * Configuration for a {@link StoreSelectionModel}. Typically passed via the `selModel` config
16
+ * on {@link GridConfig} rather than constructed directly.
17
+ *
18
+ * @see StoreSelectionModel
19
+ */
14
20
  export interface StoreSelectionConfig {
15
21
  store?: Store;
16
22
  mode?: 'single' | 'multiple' | 'disabled';
23
+ /** @internal */
17
24
  xhImpl?: boolean;
18
25
  }
19
26
 
20
27
  /**
21
- * Model for managing store selections.
22
- * Typically accessed from a GridModel to observe/control Grid selection.
28
+ * Model for managing record selection within a {@link Store}. Supports `single`, `multiple`,
29
+ * and `disabled` modes.
30
+ *
31
+ * Typically accessed via `gridModel.selModel` rather than created directly - configure via
32
+ * the `selModel` property on {@link GridConfig}.
33
+ *
34
+ * Key observables for reacting to selection state: `selectedRecord` / `selectedRecords`
35
+ * (reactive to both identity and data changes), `selectedId` / `selectedIds` (identity only),
36
+ * `isEmpty`, `count`. Use `select()` and `clear()` for programmatic control.
37
+ *
38
+ * @see StoreSelectionConfig
23
39
  */
24
40
  export class StoreSelectionModel extends HoistModel {
25
41
  readonly store: Store;
package/data/cube/Cube.ts CHANGED
@@ -20,6 +20,16 @@ import {BucketRow} from './row/BucketRow';
20
20
  import {View} from './View';
21
21
  import {ViewRowData} from './ViewRowData';
22
22
 
23
+ /**
24
+ * Configuration for a {@link Cube}. Provide `fields` (including at least one dimension
25
+ * and one or more measures with aggregators) and load data via `data` or
26
+ * `Cube.loadDataAsync()`.
27
+ *
28
+ * See the Cube package README (`data/cube/README.md`) for aggregator options and usage patterns.
29
+ *
30
+ * @see Cube
31
+ * @see CubeFieldSpec
32
+ */
23
33
  export interface CubeConfig {
24
34
  fields: CubeField[] | CubeFieldSpec[];
25
35
 
@@ -87,13 +97,23 @@ export type OmitFn = (row: AggregateRow | BucketRow) => boolean;
87
97
  export type BucketSpecFn = (rows: BaseRow[]) => BucketSpec;
88
98
 
89
99
  /**
90
- * A data store that supports grouping, aggregating, and filtering data on multiple dimensions.
100
+ * Client-side OLAP-style data structure for multi-dimensional grouping and aggregation.
101
+ *
102
+ * A Cube wraps a flat {@link Store} of leaf-level records and supports creating {@link View}s
103
+ * via structured {@link Query} objects. Each View filters, groups, and aggregates the source
104
+ * data into a hierarchical result for use in tree grids, treemaps, and other visualizations.
105
+ *
106
+ * Fields are defined as {@link CubeField}s - each marked as either a dimension (groupable)
107
+ * or a measure with an {@link Aggregator} (e.g. SUM, AVG, MIN, MAX). Views can be transient
108
+ * (run a query once) or connected for efficient, auto-updating results as source data changes.
109
+ *
110
+ * See the Cube package README (`data/cube/README.md`) for full documentation including
111
+ * aggregator options, querying patterns, and View integration with Store/GridModel.
91
112
  *
92
- * This object is a wrapper around a "flat" Store containing leaf-level facts. It supports creating
93
- * Views on that data via structured Queries that can filter, group, and aggregate the flat source
94
- * data and produce a hierarchical result ready for use in (e.g.) tree grids and maps. Views can
95
- * be transiently created to run a Query once, on demand, or can be retained to provide efficient,
96
- * auto-updating results in response to updates to the underlying data.
113
+ * @see CubeConfig
114
+ * @see CubeField
115
+ * @see View
116
+ * @see Query
97
117
  */
98
118
  export class Cube extends HoistBase {
99
119
  static RECORD_ID_DELIMITER = '>>';
@@ -22,6 +22,16 @@ import {CubeField} from './CubeField';
22
22
 
23
23
  /**
24
24
  * Queries determine what data is extracted, grouped, and aggregated from a {@link Cube}.
25
+ * Passed via the `query` property of {@link ViewConfig} when creating a View.
26
+ *
27
+ * Key options beyond `dimensions` and `filter`: `includeRoot` adds a grand-total row,
28
+ * `includeLeaves` exposes source records as tree children, and `provideLeaves` makes them
29
+ * accessible programmatically without rendering in the tree.
30
+ *
31
+ * See the Cube package README (`data/cube/README.md#querying-with-views`) for query patterns.
32
+ *
33
+ * @see Cube
34
+ * @see View
25
35
  */
26
36
  export interface QueryConfig {
27
37
  /**
@@ -0,0 +1,236 @@
1
+ # Cube Package
2
+
3
+ | Section | Description |
4
+ |---------|-------------|
5
+ | [Overview](#overview) | Architecture, dimensions vs. measures, CubeField configuration |
6
+ | [Creating a Cube](#creating-a-cube) | Field definitions, data loading |
7
+ | [Built-in Aggregators](#built-in-aggregators) | SUM, AVG, MIN, MAX, and counting aggregators |
8
+ | [Querying with Views](#querying-with-views) | Grouped queries, grand totals, leaf drill-down, dynamic updates |
9
+ | [Accessing View Data](#accessing-view-data) | Connected stores vs. direct result access |
10
+
11
+ ## Overview
12
+
13
+ The `/data/cube/` package provides a client-side OLAP-style aggregation engine. A `Cube` wraps
14
+ a flat collection of leaf-level records and supports creating `View`s via structured `Query`
15
+ objects that filter, group, and aggregate the source data into hierarchical results.
16
+
17
+ | Class | Purpose |
18
+ |-------|---------|
19
+ | **Cube** | Aggregation engine holding source data and creating Views |
20
+ | **CubeField** | Field metadata extending `Field` with dimension/aggregator config |
21
+ | **Query** | Immutable specification of dimensions, filters, and output options |
22
+ | **View** | Observable query result, optionally auto-updating connected Stores |
23
+
24
+ Fields are defined as `CubeField`s — each marked as either a **dimension** (groupable category)
25
+ or a **measure** with an `Aggregator` (e.g. SUM, AVG). Views produce hierarchical results ready
26
+ for use in tree grids, treemaps, and other visualizations.
27
+
28
+ For the core data layer (Store, Field, Filter, Validation), see the
29
+ [data package README](../README.md).
30
+
31
+ ## Creating a Cube
32
+
33
+ ```typescript
34
+ import {Cube} from '@xh/hoist/data';
35
+
36
+ const cube = new Cube({
37
+ fields: [
38
+ // Dimensions - can be grouped on
39
+ {name: 'region', isDimension: true},
40
+ {name: 'product', isDimension: true},
41
+ {name: 'year', isDimension: true},
42
+
43
+ // Measures - aggregated values
44
+ {name: 'revenue', aggregator: 'SUM'},
45
+ {name: 'quantity', aggregator: 'SUM'},
46
+ {name: 'avgPrice', aggregator: 'AVG'}
47
+ ]
48
+ });
49
+
50
+ await cube.loadDataAsync(salesData);
51
+ ```
52
+
53
+ ## Built-in Aggregators
54
+
55
+ | Aggregator | Description |
56
+ |------------|-------------|
57
+ | `'SUM'` | Total of non-null values |
58
+ | `'SUM_STRICT'` | Total only if all non-null |
59
+ | `'AVG'` | Average of non-null values |
60
+ | `'AVG_STRICT'` | Average only if all non-null |
61
+ | `'MIN'` | Minimum value |
62
+ | `'MAX'` | Maximum value |
63
+ | `'UNIQUE'` | Count of unique values |
64
+ | `'LEAF_COUNT'` | Count of leaf records |
65
+ | `'CHILD_COUNT'` | Count of immediate children |
66
+
67
+ ## Querying with Views
68
+
69
+ Views are the primary interface for consuming Cube data. Create them via `Cube.createView()`
70
+ with a `QueryConfig` specifying dimensions, filters, and output options.
71
+
72
+ **Basic grouped query:**
73
+
74
+ ```typescript
75
+ const view = cube.createView({
76
+ query: {
77
+ dimensions: ['region', 'product'],
78
+ filter: {field: 'year', op: '=', value: 2024}
79
+ },
80
+ stores: store,
81
+ connect: true // Auto-update when cube data changes
82
+ });
83
+ ```
84
+
85
+ This produces a hierarchy of aggregated rows: Region → Product, with measures (revenue,
86
+ quantity) summed at each level. Only aggregate rows are returned — leaf-level source records
87
+ are excluded by default.
88
+
89
+ **Grand totals with `includeRoot`:**
90
+
91
+ ```typescript
92
+ // Include a synthetic root node with grand totals across all data.
93
+ // Pairs with GridConfig.showSummary and StoreConfig.loadRootAsSummary
94
+ // to display a docked total row in grids.
95
+ const view = cube.createView({
96
+ query: {
97
+ dimensions: ['region', 'product'],
98
+ includeRoot: true
99
+ },
100
+ stores: new Store({loadRootAsSummary: true}),
101
+ connect: true
102
+ });
103
+
104
+ // The connected GridModel can then show the root as a summary row:
105
+ const gridModel = new GridModel({store, showSummary: true, ...});
106
+ ```
107
+
108
+ **Leaf-level drill-down with `includeLeaves`:**
109
+
110
+ ```typescript
111
+ // Include the original source records as children of the lowest
112
+ // aggregation level — users can expand groups to see underlying facts.
113
+ const view = cube.createView({
114
+ query: {
115
+ dimensions: ['region'],
116
+ includeLeaves: true
117
+ },
118
+ stores: store,
119
+ connect: true
120
+ });
121
+ // In a tree grid, expanding "North America" shows its aggregated children,
122
+ // and expanding those shows the individual source records.
123
+ ```
124
+
125
+ **Programmatic leaf access with `provideLeaves`:**
126
+
127
+ ```typescript
128
+ // Like includeLeaves, but leaves are accessible programmatically via
129
+ // ViewRowData.cubeLeaves rather than rendered as tree children.
130
+ // Useful for showing detail in a separate panel on selection.
131
+ const view = cube.createView({
132
+ query: {
133
+ dimensions: ['region', 'product'],
134
+ provideLeaves: true
135
+ },
136
+ stores: store,
137
+ connect: true
138
+ });
139
+ ```
140
+
141
+ **Flat aggregation (no dimensions):**
142
+
143
+ ```typescript
144
+ // No dimensions — just filter and aggregate. Must specify includeRoot
145
+ // or includeLeaves, otherwise no data will be returned.
146
+ const view = cube.createView({
147
+ query: {
148
+ includeRoot: true, // Single row with grand totals
149
+ filter: {field: 'region', op: '=', value: 'EMEA'}
150
+ },
151
+ stores: store,
152
+ connect: true
153
+ });
154
+ ```
155
+
156
+ **Updating queries dynamically:**
157
+
158
+ ```typescript
159
+ // Change dimensions, filters, or options on an existing View.
160
+ // Connected stores are automatically refreshed.
161
+ view.updateQuery({
162
+ dimensions: ['product', 'region'], // Swap grouping order
163
+ filter: {field: 'year', op: '=', value: 2025}
164
+ });
165
+
166
+ // Shorthand for filter-only updates:
167
+ view.setFilter({field: 'year', op: '=', value: 2025});
168
+ ```
169
+
170
+ **One-shot queries with `executeQuery`:**
171
+
172
+ For cases where you need aggregated data once without retaining a View — e.g. computing a
173
+ summary for a tooltip or populating a one-time report — use `Cube.executeQuery()` directly.
174
+ This creates a transient View internally, extracts the results, and destroys it immediately:
175
+
176
+ ```typescript
177
+ // Returns ViewRowData[] directly — no View to manage or destroy.
178
+ const rows = cube.executeQuery({
179
+ dimensions: ['region'],
180
+ includeRoot: true,
181
+ filter: {field: 'year', op: '=', value: 2024}
182
+ });
183
+
184
+ // Use the rows directly — e.g. extract the root for a grand total
185
+ const grandTotal = rows.find(r => r.isRoot);
186
+ ```
187
+
188
+ Use `createView()` when you need connected auto-updates or store integration;
189
+ use `executeQuery()` for lightweight, fire-and-forget queries.
190
+
191
+ ## Accessing View Data
192
+
193
+ There are two ways to consume View results:
194
+
195
+ **Option 1: Connected stores (recommended for grids)**
196
+
197
+ Provide one or more stores via `ViewConfig.stores`. The View auto-loads hierarchical data
198
+ into them whenever the query results change:
199
+
200
+ ```typescript
201
+ const store = new Store({fields: [...]});
202
+
203
+ const view = cube.createView({
204
+ query: {dimensions: ['region', 'product']},
205
+ stores: store,
206
+ connect: true
207
+ });
208
+
209
+ // Use the store with a GridModel
210
+ const gridModel = new GridModel({store, treeMode: true, columns: [...]});
211
+ ```
212
+
213
+ **Option 2: Read `view.result` directly**
214
+
215
+ The observable `ViewResult` contains hierarchical `ViewRowData` objects:
216
+
217
+ ```typescript
218
+ addReaction({
219
+ track: () => view.result,
220
+ run: (result) => {
221
+ const {rows, leafMap} = result;
222
+ // rows: ViewRowData[] - hierarchical aggregated data
223
+ // leafMap: Map<id, LeafRow> - direct access to leaf-level rows
224
+ }
225
+ });
226
+ ```
227
+
228
+ **Update triggers:** View data updates when either:
229
+ - The underlying Cube data changes (requires `connect: true`)
230
+ - The `view.query` is modified via `view.updateQuery()`
231
+
232
+ ## Related Packages
233
+
234
+ - [`/data/`](../README.md) - Store, Field, Filter, Validation - the core data layer
235
+ - [`/cmp/grid/`](../../cmp/grid/README.md) - GridModel consumes Store for data display
236
+ - `/cmp/grouping/` - GroupingChooser for specifying multi-level dimension groupings
package/data/cube/View.ts CHANGED
@@ -32,6 +32,15 @@ import {BaseRow} from './row/BaseRow';
32
32
  import {BucketRow} from './row/BucketRow';
33
33
  import {LeafRow} from './row/LeafRow';
34
34
 
35
+ /**
36
+ * Configuration for a {@link View} - a query result from a {@link Cube} that can optionally
37
+ * stay connected for live updates. Create via {@link Cube.createView}.
38
+ *
39
+ * See the Cube package README (`data/cube/README.md`) for query patterns.
40
+ *
41
+ * @see View
42
+ * @see QueryConfig
43
+ */
35
44
  export interface ViewConfig {
36
45
  /** Query to be used to construct this view. */
37
46
  query: Query;
@@ -64,8 +73,18 @@ export interface DimensionValue {
64
73
  }
65
74
 
66
75
  /**
67
- * Primary interface for consuming grouped and aggregated data from the cube.
68
- * Applications should create via the {@link Cube.createView} factory.
76
+ * Primary interface for consuming grouped and aggregated data from a {@link Cube}.
77
+ * Created via {@link Cube.createView} with a {@link QueryConfig} and optional connected
78
+ * stores. Views can be transient (run once) or connected for auto-updating results.
79
+ *
80
+ * Use `updateQuery()` to change dimensions, filters, or options dynamically.
81
+ *
82
+ * See the Cube package README (`data/cube/README.md`) for query patterns and examples
83
+ * of grand totals, leaf drill-down, and store integration.
84
+ *
85
+ * @see ViewConfig
86
+ * @see QueryConfig
87
+ * @see Cube
69
88
  */
70
89
  export class View
71
90
  extends HoistBase
@@ -10,6 +10,19 @@ import {BaseRow} from '../row/BaseRow';
10
10
  import {LeafRow} from '../row/LeafRow';
11
11
  import {RowUpdate} from '../row/RowUpdate';
12
12
 
13
+ /**
14
+ * Abstract base class for Cube field aggregation functions.
15
+ *
16
+ * Subclasses implement {@link aggregate} to compute a summary value for a set of rows, and
17
+ * may optionally override {@link replace} to efficiently update the aggregation when a single
18
+ * child row changes (the default re-aggregates from scratch).
19
+ *
20
+ * Standard implementations are provided for common operations: sum, average, min, max,
21
+ * unique, count, and null. Custom aggregators can extend this class for application-specific
22
+ * aggregation logic.
23
+ *
24
+ * @see CubeField.aggregator
25
+ */
13
26
  export abstract class Aggregator {
14
27
  /**
15
28
  * Does this aggregator depend only on leaf nodes contained by the node being aggregated?
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {Aggregator} from './Aggregator';
9
9
 
10
+ /** Averages numeric values across all leaf rows, skipping nulls. */
10
11
  export class AverageAggregator extends Aggregator {
11
12
  override aggregate(rows, fieldName) {
12
13
  let total = null,
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {Aggregator} from './Aggregator';
9
9
 
10
+ /** Averages numeric values, returning null if any leaf value is null. */
10
11
  export class AverageStrictAggregator extends Aggregator {
11
12
  override aggregate(rows, fieldName) {
12
13
  let total = null,
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {Aggregator} from './Aggregator';
9
9
 
10
+ /** Returns the count of direct child rows. */
10
11
  export class ChildCountAggregator extends Aggregator {
11
12
  override aggregate(rows, fieldName) {
12
13
  return rows.length;
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {Aggregator} from './Aggregator';
9
9
 
10
+ /** Returns the count of all leaf (non-aggregate) descendant rows. */
10
11
  export class LeafCountAggregator extends Aggregator {
11
12
  override aggregate(rows, fieldName) {
12
13
  let count = 0;
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {Aggregator} from './Aggregator';
9
9
 
10
+ /** Returns the maximum value across rows, skipping nulls. */
10
11
  export class MaxAggregator extends Aggregator {
11
12
  override aggregate(rows, fieldName) {
12
13
  return rows.reduce((ret, it) => {
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {Aggregator} from './Aggregator';
9
9
 
10
+ /** Returns the minimum value across rows, skipping nulls. */
10
11
  export class MinAggregator extends Aggregator {
11
12
  override aggregate(rows, fieldName) {
12
13
  return rows.reduce((ret, it) => {