@xh/hoist 87.1.0 → 87.2.0

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 (264) hide show
  1. package/.npmignore +39 -0
  2. package/CHANGELOG.md +99 -20
  3. package/admin/AdminUtils.ts +64 -0
  4. package/admin/App.scss +88 -0
  5. package/admin/columns/UserData.ts +30 -3
  6. package/admin/detail/RestDetailModel.ts +64 -0
  7. package/admin/detail/RestDetailPanel.ts +106 -0
  8. package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +27 -94
  9. package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +23 -60
  10. package/admin/tabs/activity/tracking/detail/ActivityDetailView.ts +1 -2
  11. package/admin/tabs/general/alertBanner/AlertBannerPanel.ts +2 -13
  12. package/admin/tabs/general/config/ConfigDetailPanel.ts +72 -0
  13. package/admin/tabs/general/config/ConfigPanel.ts +41 -53
  14. package/admin/tabs/general/config/ConfigPanelModel.ts +3 -0
  15. package/admin/tabs/general/config/ConfigValue.scss +14 -0
  16. package/admin/tabs/general/config/ConfigValue.ts +104 -65
  17. package/admin/tabs/userData/jsonblob/JsonBlobDetailPanel.ts +93 -0
  18. package/admin/tabs/userData/jsonblob/JsonBlobModel.ts +4 -0
  19. package/admin/tabs/userData/jsonblob/JsonBlobPanel.ts +2 -0
  20. package/admin/tabs/userData/prefs/UserPreferenceDetailPanel.ts +62 -0
  21. package/admin/tabs/userData/prefs/UserPreferenceModel.ts +10 -3
  22. package/admin/tabs/userData/prefs/UserPreferencePanel.ts +3 -1
  23. package/admin/tabs/userData/roles/details/RoleDetails.scss +2 -19
  24. package/admin/tabs/userData/roles/details/RoleDetails.ts +13 -13
  25. package/appcontainer/AboutDialogModel.ts +1 -0
  26. package/appcontainer/AppContainerModel.ts +3 -0
  27. package/appcontainer/AppStateModel.ts +1 -0
  28. package/appcontainer/BannerSourceModel.ts +1 -0
  29. package/appcontainer/ChangelogDialogModel.ts +1 -0
  30. package/appcontainer/ColChooserOptionsModel.ts +1 -0
  31. package/appcontainer/ExceptionDialogModel.ts +1 -0
  32. package/appcontainer/FeedbackDialogModel.ts +1 -0
  33. package/appcontainer/ImpersonationBarModel.ts +1 -0
  34. package/appcontainer/MessageSourceModel.ts +1 -0
  35. package/appcontainer/OptionsDialogModel.ts +1 -0
  36. package/appcontainer/PageStateModel.ts +1 -0
  37. package/appcontainer/RouterModel.ts +2 -0
  38. package/appcontainer/SizingModeModel.ts +1 -0
  39. package/appcontainer/ThemeModel.ts +1 -0
  40. package/appcontainer/ToastSourceModel.ts +1 -0
  41. package/appcontainer/UserAgentModel.ts +1 -0
  42. package/appcontainer/ViewportSizeModel.ts +1 -0
  43. package/build/types/admin/AdminUtils.d.ts +29 -0
  44. package/build/types/admin/columns/UserData.d.ts +3 -0
  45. package/build/types/admin/detail/RestDetailModel.d.ts +20 -0
  46. package/build/types/admin/detail/RestDetailPanel.d.ts +34 -0
  47. package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +5 -17
  48. package/build/types/admin/tabs/general/config/ConfigDetailPanel.d.ts +7 -0
  49. package/build/types/admin/tabs/general/config/ConfigValue.d.ts +10 -4
  50. package/build/types/admin/tabs/userData/jsonblob/JsonBlobDetailPanel.d.ts +3 -0
  51. package/build/types/admin/tabs/userData/prefs/UserPreferenceDetailPanel.d.ts +3 -0
  52. package/build/types/admin/tabs/userData/prefs/UserPreferenceModel.d.ts +3 -0
  53. package/build/types/appcontainer/AboutDialogModel.d.ts +1 -0
  54. package/build/types/appcontainer/AppContainerModel.d.ts +1 -0
  55. package/build/types/appcontainer/AppStateModel.d.ts +1 -0
  56. package/build/types/appcontainer/BannerSourceModel.d.ts +1 -0
  57. package/build/types/appcontainer/ChangelogDialogModel.d.ts +1 -0
  58. package/build/types/appcontainer/ColChooserOptionsModel.d.ts +1 -0
  59. package/build/types/appcontainer/ExceptionDialogModel.d.ts +1 -0
  60. package/build/types/appcontainer/FeedbackDialogModel.d.ts +1 -0
  61. package/build/types/appcontainer/ImpersonationBarModel.d.ts +1 -0
  62. package/build/types/appcontainer/MessageSourceModel.d.ts +1 -0
  63. package/build/types/appcontainer/OptionsDialogModel.d.ts +1 -0
  64. package/build/types/appcontainer/PageStateModel.d.ts +1 -0
  65. package/build/types/appcontainer/RouterModel.d.ts +1 -0
  66. package/build/types/appcontainer/SizingModeModel.d.ts +1 -0
  67. package/build/types/appcontainer/ThemeModel.d.ts +1 -0
  68. package/build/types/appcontainer/ToastSourceModel.d.ts +1 -0
  69. package/build/types/appcontainer/UserAgentModel.d.ts +1 -0
  70. package/build/types/appcontainer/ViewportSizeModel.d.ts +1 -0
  71. package/build/types/cmp/ag-grid/AgGridModel.d.ts +3 -1
  72. package/build/types/cmp/card/Card.d.ts +2 -2
  73. package/build/types/cmp/chart/ChartModel.d.ts +2 -0
  74. package/build/types/cmp/dataview/DataViewModel.d.ts +2 -0
  75. package/build/types/cmp/daterange/DateRangePickerModel.d.ts +266 -0
  76. package/build/types/cmp/daterange/DateRangePresets.d.ts +26 -0
  77. package/build/types/cmp/daterange/DateRangeUtils.d.ts +96 -0
  78. package/build/types/cmp/daterange/Types.d.ts +152 -0
  79. package/build/types/cmp/daterange/index.d.ts +4 -0
  80. package/build/types/cmp/filter/FilterChooserModel.d.ts +3 -1
  81. package/build/types/cmp/form/FormModel.d.ts +3 -1
  82. package/build/types/cmp/grid/GridModel.d.ts +2 -0
  83. package/build/types/cmp/grid/Types.d.ts +2 -0
  84. package/build/types/cmp/grid/filter/GridFilterModel.d.ts +1 -1
  85. package/build/types/cmp/grouping/GroupingChooserModel.d.ts +3 -1
  86. package/build/types/cmp/input/HoistInputProps.d.ts +49 -2
  87. package/build/types/cmp/tab/TabContainerModel.d.ts +3 -1
  88. package/build/types/cmp/tab/TabModel.d.ts +3 -1
  89. package/build/types/cmp/treemap/TreeMapModel.d.ts +2 -0
  90. package/build/types/cmp/viewmanager/ViewManagerModel.d.ts +2 -0
  91. package/build/types/cmp/zoneGrid/ZoneGridModel.d.ts +2 -0
  92. package/build/types/core/HoistBase.d.ts +7 -0
  93. package/build/types/core/HoistProps.d.ts +26 -1
  94. package/build/types/core/model/RootRefreshContextModel.d.ts +1 -0
  95. package/build/types/core/types/Telemetry.d.ts +1 -1
  96. package/build/types/data/Store.d.ts +3 -1
  97. package/build/types/data/StoreSelectionModel.d.ts +3 -1
  98. package/build/types/data/cube/Cube.d.ts +5 -2
  99. package/build/types/data/cube/View.d.ts +2 -0
  100. package/build/types/desktop/cmp/appOption/AutoRefreshAppOption.d.ts +3 -0
  101. package/build/types/desktop/cmp/appOption/ThemeAppOption.d.ts +3 -0
  102. package/build/types/desktop/cmp/button/Button.d.ts +2 -2
  103. package/build/types/desktop/cmp/button/ButtonGroup.d.ts +2 -2
  104. package/build/types/desktop/cmp/dash/DashConfig.d.ts +2 -0
  105. package/build/types/desktop/cmp/dash/DashViewModel.d.ts +3 -1
  106. package/build/types/desktop/cmp/dash/canvas/DashCanvasModel.d.ts +1 -1
  107. package/build/types/desktop/cmp/dash/container/DashContainerModel.d.ts +1 -1
  108. package/build/types/desktop/cmp/daterange/DateRangePicker.d.ts +66 -0
  109. package/build/types/desktop/cmp/daterange/impl/CustomTab.d.ts +3 -0
  110. package/build/types/desktop/cmp/daterange/impl/DateRangePickerLocalModel.d.ts +121 -0
  111. package/build/types/desktop/cmp/daterange/impl/PeriodTab.d.ts +2 -0
  112. package/build/types/desktop/cmp/daterange/impl/PresetsTab.d.ts +3 -0
  113. package/build/types/desktop/cmp/daterange/impl/RelativeTab.d.ts +3 -0
  114. package/build/types/desktop/cmp/daterange/impl/TabUtils.d.ts +21 -0
  115. package/build/types/desktop/cmp/daterange/index.d.ts +2 -0
  116. package/build/types/desktop/cmp/dock/DockContainerModel.d.ts +3 -1
  117. package/build/types/desktop/cmp/dock/DockViewModel.d.ts +3 -1
  118. package/build/types/desktop/cmp/grouping/GroupingChooser.d.ts +4 -1
  119. package/build/types/desktop/cmp/input/IntentInput.d.ts +38 -0
  120. package/build/types/desktop/cmp/input/NumberInput.d.ts +2 -2
  121. package/build/types/desktop/cmp/input/SegmentedControl.d.ts +25 -4
  122. package/build/types/desktop/cmp/input/TextArea.d.ts +2 -2
  123. package/build/types/desktop/cmp/input/TextInput.d.ts +2 -2
  124. package/build/types/desktop/cmp/input/index.d.ts +1 -0
  125. package/build/types/desktop/cmp/leftrightchooser/LeftRightChooserModel.d.ts +3 -1
  126. package/build/types/desktop/cmp/panel/PanelModel.d.ts +3 -1
  127. package/build/types/desktop/cmp/rest/RestGridModel.d.ts +1 -1
  128. package/build/types/desktop/cmp/tab/impl/TabContainer.d.ts +1 -1
  129. package/build/types/icon/Icon.d.ts +3 -0
  130. package/build/types/inspector/impl/InspectorUtils.d.ts +3 -0
  131. package/build/types/inspector/instances/InstancesModel.d.ts +4 -0
  132. package/build/types/kit/react-day-picker/index.d.ts +3 -3
  133. package/build/types/mobile/cmp/button/Button.d.ts +2 -2
  134. package/build/types/mobile/cmp/input/NumberInput.d.ts +2 -2
  135. package/build/types/mobile/cmp/input/SegmentedControl.d.ts +18 -4
  136. package/build/types/mobile/cmp/input/TextArea.d.ts +2 -2
  137. package/build/types/mobile/cmp/input/TextInput.d.ts +2 -2
  138. package/build/types/mobile/cmp/navigator/NavigatorModel.d.ts +3 -1
  139. package/build/types/mobile/cmp/navigator/PageModel.d.ts +3 -1
  140. package/build/types/mobile/cmp/tab/impl/TabContainer.d.ts +1 -1
  141. package/build/types/svc/InspectorService.d.ts +1 -0
  142. package/build/types/utils/js/LangUtils.d.ts +24 -5
  143. package/cmp/README.md +1 -0
  144. package/cmp/ag-grid/AgGridModel.ts +5 -0
  145. package/cmp/badge/Badge.ts +5 -3
  146. package/cmp/card/Card.ts +4 -3
  147. package/cmp/chart/ChartModel.ts +11 -1
  148. package/cmp/dataview/DataViewModel.ts +7 -1
  149. package/cmp/daterange/DateRangePickerModel.ts +628 -0
  150. package/cmp/daterange/DateRangePresets.ts +274 -0
  151. package/cmp/daterange/DateRangeUtils.ts +557 -0
  152. package/cmp/daterange/README.md +434 -0
  153. package/cmp/daterange/Types.ts +203 -0
  154. package/cmp/daterange/index.ts +10 -0
  155. package/cmp/filter/FilterChooserModel.ts +7 -4
  156. package/cmp/form/FormModel.ts +6 -0
  157. package/cmp/form/README.md +1 -0
  158. package/cmp/grid/GridModel.ts +24 -4
  159. package/cmp/grid/Types.ts +3 -0
  160. package/cmp/grid/filter/GridFilterModel.ts +3 -1
  161. package/cmp/grid/impl/RecordSortUtils.ts +10 -2
  162. package/cmp/grouping/GroupingChooserModel.ts +6 -1
  163. package/cmp/input/HoistInputProps.ts +50 -2
  164. package/cmp/input/README.md +42 -0
  165. package/cmp/layout/Box.ts +3 -2
  166. package/cmp/tab/TabContainerModel.ts +9 -1
  167. package/cmp/tab/TabModel.ts +5 -0
  168. package/cmp/treemap/SplitTreeMapModel.ts +12 -2
  169. package/cmp/treemap/TreeMapModel.ts +6 -1
  170. package/cmp/viewmanager/ViewManagerModel.ts +6 -1
  171. package/cmp/zoneGrid/ZoneGridModel.ts +7 -0
  172. package/core/HoistBase.ts +11 -0
  173. package/core/HoistProps.ts +27 -0
  174. package/core/README.md +46 -0
  175. package/core/impl/InstallServices.ts +5 -1
  176. package/core/model/RootRefreshContextModel.ts +2 -0
  177. package/core/types/Telemetry.ts +1 -1
  178. package/data/README.md +3 -1
  179. package/data/Store.ts +7 -0
  180. package/data/StoreSelectionModel.ts +5 -1
  181. package/data/cube/Cube.ts +12 -3
  182. package/data/cube/View.ts +5 -1
  183. package/desktop/README.md +2 -0
  184. package/desktop/appcontainer/LoginPanel.ts +2 -0
  185. package/desktop/cmp/button/Button.scss +71 -42
  186. package/desktop/cmp/button/Button.ts +10 -1
  187. package/desktop/cmp/button/ButtonGroup.ts +4 -1
  188. package/desktop/cmp/button/grid/ColChooserButton.ts +9 -1
  189. package/desktop/cmp/button/zoneGrid/ZoneMapperButton.ts +1 -0
  190. package/desktop/cmp/dash/DashConfig.ts +3 -0
  191. package/desktop/cmp/dash/DashViewModel.ts +14 -1
  192. package/desktop/cmp/dash/canvas/DashCanvasModel.ts +3 -1
  193. package/desktop/cmp/dash/container/DashContainerModel.ts +3 -1
  194. package/desktop/cmp/daterange/DateRangePicker.scss +577 -0
  195. package/desktop/cmp/daterange/DateRangePicker.ts +357 -0
  196. package/desktop/cmp/daterange/impl/CustomTab.ts +165 -0
  197. package/desktop/cmp/daterange/impl/DateRangePickerLocalModel.ts +482 -0
  198. package/desktop/cmp/daterange/impl/PeriodTab.ts +138 -0
  199. package/desktop/cmp/daterange/impl/PresetsTab.ts +58 -0
  200. package/desktop/cmp/daterange/impl/RelativeTab.ts +108 -0
  201. package/desktop/cmp/daterange/impl/TabUtils.ts +34 -0
  202. package/desktop/cmp/daterange/index.ts +8 -0
  203. package/desktop/cmp/dock/DockContainerModel.ts +6 -1
  204. package/desktop/cmp/dock/DockViewModel.ts +6 -1
  205. package/desktop/cmp/filechooser/FileChooser.ts +4 -0
  206. package/desktop/cmp/form/FormField.ts +1 -0
  207. package/desktop/cmp/grouping/GroupingChooser.ts +8 -2
  208. package/desktop/cmp/input/Checkbox.ts +1 -0
  209. package/desktop/cmp/input/CodeInput.ts +1 -0
  210. package/desktop/cmp/input/DateInput.scss +1 -1
  211. package/desktop/cmp/input/DateInput.ts +1 -0
  212. package/desktop/cmp/input/IntentInput.scss +202 -0
  213. package/desktop/cmp/input/IntentInput.ts +213 -0
  214. package/desktop/cmp/input/NumberInput.ts +11 -2
  215. package/desktop/cmp/input/Picker.ts +1 -0
  216. package/desktop/cmp/input/RadioInput.ts +2 -1
  217. package/desktop/cmp/input/SegmentedControl.scss +45 -2
  218. package/desktop/cmp/input/SegmentedControl.ts +66 -11
  219. package/desktop/cmp/input/Select.ts +9 -7
  220. package/desktop/cmp/input/Slider.ts +2 -0
  221. package/desktop/cmp/input/SwitchInput.ts +1 -0
  222. package/desktop/cmp/input/TextArea.ts +11 -2
  223. package/desktop/cmp/input/TextInput.ts +11 -2
  224. package/desktop/cmp/input/index.ts +1 -0
  225. package/desktop/cmp/leftrightchooser/LeftRightChooserModel.ts +5 -0
  226. package/desktop/cmp/panel/Panel.ts +8 -5
  227. package/desktop/cmp/panel/PanelModel.ts +8 -0
  228. package/desktop/cmp/panel/impl/ResizeContainer.ts +2 -1
  229. package/desktop/cmp/rest/RestGridModel.ts +4 -0
  230. package/desktop/cmp/tab/impl/TabContainer.ts +2 -0
  231. package/docs/README.md +2 -0
  232. package/docs/build-and-publish.md +23 -7
  233. package/docs/doc-registry.json +8 -0
  234. package/docs/version-compatibility.md +2 -0
  235. package/icon/Icon.ts +9 -0
  236. package/icon/index.ts +24 -0
  237. package/inspector/README.md +8 -2
  238. package/inspector/impl/InspectorUtils.ts +12 -0
  239. package/inspector/instances/DiagnosticsModel.ts +3 -2
  240. package/inspector/instances/InstancesModel.ts +81 -14
  241. package/inspector/instances/InstancesPanel.ts +6 -0
  242. package/kit/react-day-picker/index.ts +3 -3
  243. package/mobile/appcontainer/LoginPanel.ts +2 -0
  244. package/mobile/cmp/button/Button.ts +16 -3
  245. package/mobile/cmp/form/FormField.ts +1 -0
  246. package/mobile/cmp/input/Checkbox.ts +1 -0
  247. package/mobile/cmp/input/DateInput.ts +1 -0
  248. package/mobile/cmp/input/Label.ts +13 -8
  249. package/mobile/cmp/input/NumberInput.ts +11 -2
  250. package/mobile/cmp/input/SearchInput.ts +1 -0
  251. package/mobile/cmp/input/SegmentedControl.scss +36 -6
  252. package/mobile/cmp/input/SegmentedControl.ts +37 -11
  253. package/mobile/cmp/input/Select.ts +2 -0
  254. package/mobile/cmp/input/SwitchInput.ts +1 -0
  255. package/mobile/cmp/input/TextArea.ts +11 -2
  256. package/mobile/cmp/input/TextInput.ts +11 -2
  257. package/mobile/cmp/navigator/NavigatorModel.ts +6 -1
  258. package/mobile/cmp/navigator/PageModel.ts +6 -1
  259. package/mobile/cmp/tab/impl/TabContainer.ts +9 -1
  260. package/package.json +19 -19
  261. package/styles/vars.scss +32 -2
  262. package/svc/InspectorService.ts +2 -0
  263. package/svc/TraceService.ts +5 -2
  264. package/utils/js/LangUtils.ts +37 -5
@@ -88,7 +88,7 @@ export interface FullSpanConfig extends SpanConfig {
88
88
  */
89
89
  startTime?: number;
90
90
 
91
- /** Source for the `code.namespace` tag - usually the calling object/function. */
91
+ /** Usually the calling object/function - source of the `code.namespace` and `xh.name` tags. */
92
92
  caller?: NameSource;
93
93
  }
94
94
 
package/data/README.md CHANGED
@@ -113,6 +113,7 @@ const store = new Store({
113
113
  | `idEncodesTreePath` | `boolean` | `false` | IDs imply a fixed tree position (performance). Not supported on View-connected stores |
114
114
  | `validationIsComplex` | `boolean` | `false` | Validate all uncommitted records on every change |
115
115
  | `experimental` | `PlainObject` | `{}` | Flags for experimental features - see [Performance and Memory](#performance-and-memory) |
116
+ | `xhName` | `string` | `null` | Developer-facing name for logs, telemetry, and Inspector |
116
117
 
117
118
  `Store.defaults` exposes `freezeData` for an app-wide override. See `StoreDefaults` for details.
118
119
 
@@ -1066,7 +1067,8 @@ store.diagnostics.reset();
1066
1067
  ```
1067
1068
 
1068
1069
  Diagnostics log at `debug` level by default. Set `diagnostics.logLevel = 'info'` on one instance to
1069
- follow that object alone at any `XH.logLevel`.
1070
+ follow that object alone at any `XH.logLevel`. Give the owning objects an `xhName` to tell
1071
+ their output apart - several stores logging at once are otherwise all labelled `[Store]`.
1070
1072
 
1071
1073
  ```typescript
1072
1074
  gridModel.store.diagnostics.logLevel = 'info';
package/data/Store.ts CHANGED
@@ -43,6 +43,7 @@ import {
43
43
  partition,
44
44
  remove as lodashRemove,
45
45
  uniq,
46
+ uniqBy,
46
47
  values
47
48
  } from 'lodash';
48
49
  import {instanceManager} from '../core/impl/InstanceManager';
@@ -237,6 +238,9 @@ export interface StoreConfig {
237
238
  * it may also be changed on an existing Store at any time.
238
239
  */
239
240
  experimental?: PlainObject;
241
+
242
+ /** See {@link HoistBase.xhName}. */
243
+ xhName?: string;
240
244
  }
241
245
 
242
246
  /**
@@ -447,6 +451,7 @@ export class Store
447
451
  projectionOnly = null,
448
452
  validationIsComplex = false,
449
453
  experimental,
454
+ xhName = null,
450
455
  data
451
456
  }: StoreConfig) {
452
457
  super();
@@ -456,6 +461,7 @@ export class Store
456
461
  'Store.projectionOnly cannot be used with processRawData - a projection adopts data already parsed by its provider.'
457
462
  );
458
463
 
464
+ this.xhName = xhName;
459
465
  this.experimental = this.parseExperimental(experimental);
460
466
  this.fields = this.parseFields(fields, fieldDefaults);
461
467
  this.idSpec = this.parseIdSpec(idSpec);
@@ -1352,6 +1358,7 @@ export class Store
1352
1358
  `Applications must not specify a field named '__proto__' - assigning it would replace the
1353
1359
  prototype of each record's data object rather than setting a value on it.`
1354
1360
  );
1361
+ throwIf(uniqBy(ret, 'name').length !== ret.length, 'Field names must be unique.');
1355
1362
  return ret;
1356
1363
  }
1357
1364
 
@@ -22,6 +22,9 @@ export interface StoreSelectionConfig {
22
22
  mode?: 'single' | 'multiple' | 'disabled';
23
23
  /** @internal */
24
24
  xhImpl?: boolean;
25
+
26
+ /** See {@link HoistBase.xhName}. */
27
+ xhName?: string;
25
28
  }
26
29
 
27
30
  /**
@@ -50,11 +53,12 @@ export class StoreSelectionModel extends HoistModel {
50
53
  return this.mode !== 'disabled';
51
54
  }
52
55
 
53
- constructor({store, mode = 'single', xhImpl = false}: StoreSelectionConfig) {
56
+ constructor({store, mode = 'single', xhName = null, xhImpl = false}: StoreSelectionConfig) {
54
57
  super();
55
58
  makeObservable(this);
56
59
 
57
60
  this.xhImpl = xhImpl;
61
+ this.xhName = xhName;
58
62
  this.store = store;
59
63
  this.mode = mode;
60
64
  this.addReaction(this.cullSelectionReaction());
package/data/cube/Cube.ts CHANGED
@@ -76,6 +76,9 @@ export interface CubeConfig {
76
76
  * Return true to omit the row.
77
77
  */
78
78
  omitFn?: OmitFn;
79
+
80
+ /** See {@link HoistBase.xhName}. */
81
+ xhName?: string;
79
82
  }
80
83
 
81
84
  /**
@@ -187,11 +190,14 @@ export class Cube extends HoistBase {
187
190
  info = {},
188
191
  lockFn,
189
192
  bucketSpecFn,
190
- omitFn
193
+ omitFn,
194
+ xhName = null
191
195
  }: CubeConfig) {
192
196
  super();
193
197
  makeObservable(this);
198
+ this.xhName = xhName;
194
199
  this.store = new Store({
200
+ xhName: this.childXhName('store'),
195
201
  ...store,
196
202
  fields: this.parseFields(fields, fieldDefaults),
197
203
  idSpec,
@@ -281,16 +287,19 @@ export class Cube extends HoistBase {
281
287
  createView({
282
288
  query,
283
289
  stores,
284
- connect = false
290
+ connect = false,
291
+ xhName = null
285
292
  }: {
286
293
  query: QueryConfig;
287
294
  stores?: Store[] | Store;
288
295
  connect?: boolean;
296
+ xhName?: string;
289
297
  }): View {
290
298
  return new View({
291
299
  query: new Query({...query, cube: this}),
292
300
  stores,
293
- connect
301
+ connect,
302
+ xhName
294
303
  });
295
304
  }
296
305
 
package/data/cube/View.ts CHANGED
@@ -63,6 +63,9 @@ export interface ViewConfig {
63
63
  * capture a snapshot without further (automatic) updates.
64
64
  */
65
65
  connect?: boolean;
66
+
67
+ /** See {@link HoistBase.xhName}. */
68
+ xhName?: string;
66
69
  }
67
70
 
68
71
  export interface ViewResult {
@@ -169,8 +172,9 @@ export class View
169
172
  makeObservable(this);
170
173
 
171
174
  const start = performance.now(),
172
- {query, stores = [], connect = false} = config;
175
+ {query, stores = [], connect = false, xhName = null} = config;
173
176
 
177
+ this.xhName = xhName;
174
178
  this.query = query;
175
179
  this.stores = this.parseStores(stores);
176
180
  this._rowCache = new RowCache(this);
package/desktop/README.md CHANGED
@@ -113,6 +113,7 @@ Desktop form inputs with Blueprint styling:
113
113
  | `Slider` | Range slider |
114
114
  | `ButtonGroupInput` | Segmented button selection |
115
115
  | `SegmentedControl` | Toggle group for mutually exclusive options with strong visual differentiation of the active selection |
116
+ | `IntentInput` | Compact swatch row for selecting a Hoist `Intent`, with optional intent names |
116
117
  | `CodeInput` | Code editor with syntax highlighting |
117
118
  | `JsonInput` | JSON editor with validation |
118
119
 
@@ -355,6 +356,7 @@ leftRightChooser({model})
355
356
  | `/appOption/` | App-wide configuration options UI |
356
357
  | `/clipboard/` | Clipboard operations (copy with feedback) |
357
358
  | `/contextmenu/` | Right-click context menu support |
359
+ | `/daterange/` | Date range picker - presets, relative lookbacks, months and years, custom ranges (see [Date Range README](../cmp/daterange/README.md)) |
358
360
  | `/filechooser/` | File selection input |
359
361
  | `/filter/` | Filter chooser and filter editor |
360
362
  | `/form/` | FormField wrapper for desktop inputs |
@@ -50,6 +50,7 @@ export const loginPanel = hoistCmp.factory({
50
50
  leftIcon: Icon.user(),
51
51
  placeholder: 'Username',
52
52
  autoComplete: 'username',
53
+ enablePasswordManagers: true,
53
54
  autoFocus: true,
54
55
  commitOnChange: true,
55
56
  onKeyDown,
@@ -61,6 +62,7 @@ export const loginPanel = hoistCmp.factory({
61
62
  leftIcon: Icon.lock(),
62
63
  placeholder: 'Password...',
63
64
  autoComplete: 'current-password',
65
+ enablePasswordManagers: true,
64
66
  type: 'password',
65
67
  commitOnChange: true,
66
68
  onKeyDown,
@@ -5,6 +5,14 @@
5
5
  * Copyright © 2026 Extremely Heavy Industries Inc.
6
6
  */
7
7
 
8
+ // Active-state selectors throughout this file match `bp6-active` alongside Hoist's own
9
+ // `xh-button--active`. The Hoist `active` prop sets both, but Blueprint additionally sets
10
+ // `bp6-active` on the button that triggered an *uncontrolled* popover it opened - so a button that
11
+ // simply opens a menu picks up the active look with no per-component code. Blueprint deliberately
12
+ // skips this for controlled popovers (those passed an `isOpen`), which must pass `active`
13
+ // themselves. A component that needs full control of the look can therefore opt out by taking
14
+ // ownership of `isOpen`.
15
+
8
16
  //-----------------------------------------------
9
17
  // Core button styles for both light+dark themes
10
18
  // (Color-related styles in separate block below)
@@ -130,7 +138,8 @@
130
138
  .xh-button.bp6-button {
131
139
  // Shaded/filled-in (non-minimal) mode.
132
140
  &.xh-button--standard {
133
- &.xh-button--active {
141
+ &.xh-button--active,
142
+ &.bp6-active {
134
143
  box-shadow: var(--xh-button-active-box-shadow);
135
144
  }
136
145
 
@@ -138,7 +147,8 @@
138
147
  color: var(--xh-button-text-color);
139
148
  background-color: var(--xh-button-bg-lightest);
140
149
 
141
- &.xh-button--active {
150
+ &.xh-button--active,
151
+ &.bp6-active {
142
152
  background-color: var(--xh-button-active-bg);
143
153
  color: var(--xh-button-active-text-color);
144
154
  }
@@ -146,7 +156,7 @@
146
156
  // highlight on hover for a disabled button. Note that :active pseudo-selector here is
147
157
  // triggered while button is being "held down" by user.
148
158
  &.xh-button--enabled {
149
- &:hover:not(:active):not(.xh-button--active) {
159
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
150
160
  background-color: var(--xh-button-bg-lighter);
151
161
  }
152
162
  &:active {
@@ -158,11 +168,12 @@
158
168
  &.xh-button--intent-primary {
159
169
  color: white;
160
170
  background-color: var(--xh-intent-primary);
161
- &.xh-button--active {
171
+ &.xh-button--active,
172
+ &.bp6-active {
162
173
  background-color: var(--xh-intent-primary-darkest);
163
174
  }
164
175
  &.xh-button--enabled {
165
- &:hover:not(:active):not(.xh-button--active) {
176
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
166
177
  background-color: var(--xh-intent-primary-darker);
167
178
  }
168
179
  &:active {
@@ -174,11 +185,12 @@
174
185
  &.xh-button--intent-success {
175
186
  color: white;
176
187
  background-color: var(--xh-intent-success);
177
- &.xh-button--active {
188
+ &.xh-button--active,
189
+ &.bp6-active {
178
190
  background-color: var(--xh-intent-success-darkest);
179
191
  }
180
192
  &.xh-button--enabled {
181
- &:hover:not(:active):not(.xh-button--active) {
193
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
182
194
  background-color: var(--xh-intent-success-darker);
183
195
  }
184
196
  &:active {
@@ -192,12 +204,13 @@
192
204
  &.xh-button--intent-warning {
193
205
  color: white;
194
206
  background-color: var(--xh-intent-warning);
195
- &.xh-button--active {
207
+ &.xh-button--active,
208
+ &.bp6-active {
196
209
  color: white;
197
210
  background-color: var(--xh-intent-warning-darkest);
198
211
  }
199
212
  &.xh-button--enabled {
200
- &:hover:not(:active):not(.xh-button--active) {
213
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
201
214
  color: white;
202
215
  background-color: var(--xh-intent-warning-darker);
203
216
  }
@@ -210,11 +223,12 @@
210
223
  &.xh-button--intent-danger {
211
224
  color: white;
212
225
  background-color: var(--xh-intent-danger);
213
- &.xh-button--active {
226
+ &.xh-button--active,
227
+ &.bp6-active {
214
228
  background-color: var(--xh-intent-danger-darkest);
215
229
  }
216
230
  &.xh-button--enabled {
217
- &:hover:not(:active):not(.xh-button--active) {
231
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
218
232
  background-color: var(--xh-intent-danger-darker);
219
233
  }
220
234
  &:active {
@@ -231,12 +245,13 @@
231
245
  color: var(--xh-button-text-color);
232
246
  background-color: transparent;
233
247
  border-color: var(--xh-button-border-color);
234
- &.xh-button--active {
248
+ &.xh-button--active,
249
+ &.bp6-active {
235
250
  background-color: var(--xh-button-active-bg);
236
251
  color: var(--xh-button-active-text-color);
237
252
  }
238
253
  &.xh-button--enabled {
239
- &:hover:not(:active):not(.xh-button--active) {
254
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
240
255
  background-color: var(--xh-button-bg-darker);
241
256
  }
242
257
  &:active {
@@ -249,11 +264,12 @@
249
264
  color: var(--xh-intent-primary-darker);
250
265
  background-color: transparent;
251
266
  border-color: var(--xh-intent-primary);
252
- &.xh-button--active {
267
+ &.xh-button--active,
268
+ &.bp6-active {
253
269
  background-color: var(--xh-intent-primary-trans2);
254
270
  }
255
271
  &.xh-button--enabled {
256
- &:hover:not(:active):not(.xh-button--active) {
272
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
257
273
  background-color: var(--xh-intent-primary-trans1);
258
274
  }
259
275
  &:active {
@@ -266,11 +282,12 @@
266
282
  color: var(--xh-intent-success-darker);
267
283
  background-color: transparent;
268
284
  border-color: var(--xh-intent-success);
269
- &.xh-button--active {
285
+ &.xh-button--active,
286
+ &.bp6-active {
270
287
  background-color: var(--xh-intent-success-trans2);
271
288
  }
272
289
  &.xh-button--enabled {
273
- &:hover:not(:active):not(.xh-button--active) {
290
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
274
291
  background-color: var(--xh-intent-success-trans1);
275
292
  }
276
293
  &:active {
@@ -283,11 +300,12 @@
283
300
  color: var(--xh-intent-warning-darker);
284
301
  background-color: transparent;
285
302
  border-color: var(--xh-intent-warning);
286
- &.xh-button--active {
303
+ &.xh-button--active,
304
+ &.bp6-active {
287
305
  background-color: var(--xh-intent-warning-trans2);
288
306
  }
289
307
  &.xh-button--enabled {
290
- &:hover:not(:active):not(.xh-button--active) {
308
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
291
309
  background-color: var(--xh-intent-warning-trans1);
292
310
  }
293
311
  &:active {
@@ -300,11 +318,12 @@
300
318
  color: var(--xh-intent-danger-darker);
301
319
  background-color: transparent;
302
320
  border-color: var(--xh-intent-danger);
303
- &.xh-button--active {
321
+ &.xh-button--active,
322
+ &.bp6-active {
304
323
  background-color: var(--xh-intent-danger-trans2);
305
324
  }
306
325
  &.xh-button--enabled {
307
- &:hover:not(:active):not(.xh-button--active) {
326
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
308
327
  background-color: var(--xh-intent-danger-trans1);
309
328
  }
310
329
  &:active {
@@ -327,12 +346,13 @@
327
346
  &.xh-button--intent-none {
328
347
  color: var(--xh-button-text-color);
329
348
  background-color: var(--xh-button-bg);
330
- &.xh-button--active {
349
+ &.xh-button--active,
350
+ &.bp6-active {
331
351
  background-color: var(--xh-button-active-bg);
332
352
  color: var(--xh-button-active-text-color);
333
353
  }
334
354
  &.xh-button--enabled {
335
- &:hover:not(:active):not(.xh-button--active) {
355
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
336
356
  background-color: var(--xh-button-bg-darker);
337
357
  }
338
358
  &:active {
@@ -344,11 +364,12 @@
344
364
  &.xh-button--intent-primary {
345
365
  color: white;
346
366
  background-color: var(--xh-intent-primary);
347
- &.xh-button--active {
367
+ &.xh-button--active,
368
+ &.bp6-active {
348
369
  background-color: var(--xh-intent-primary-darkest);
349
370
  }
350
371
  &.xh-button--enabled {
351
- &:hover:not(:active):not(.xh-button--active) {
372
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
352
373
  background-color: var(--xh-intent-primary-darker);
353
374
  }
354
375
  &:active {
@@ -360,11 +381,12 @@
360
381
  &.xh-button--intent-success {
361
382
  color: white;
362
383
  background-color: var(--xh-intent-success);
363
- &.xh-button--active {
384
+ &.xh-button--active,
385
+ &.bp6-active {
364
386
  background-color: var(--xh-intent-success-darkest);
365
387
  }
366
388
  &.xh-button--enabled {
367
- &:hover:not(:active):not(.xh-button--active) {
389
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
368
390
  background-color: var(--xh-intent-success-darker);
369
391
  }
370
392
  &:active {
@@ -376,11 +398,12 @@
376
398
  &.xh-button--intent-warning {
377
399
  color: white;
378
400
  background-color: var(--xh-intent-warning);
379
- &.xh-button--active {
401
+ &.xh-button--active,
402
+ &.bp6-active {
380
403
  background-color: var(--xh-intent-warning-darkest);
381
404
  }
382
405
  &.xh-button--enabled {
383
- &:hover:not(:active):not(.xh-button--active) {
406
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
384
407
  background-color: var(--xh-intent-warning-darker);
385
408
  }
386
409
  &:active {
@@ -392,11 +415,12 @@
392
415
  &.xh-button--intent-danger {
393
416
  color: white;
394
417
  background-color: var(--xh-intent-danger);
395
- &.xh-button--active {
418
+ &.xh-button--active,
419
+ &.bp6-active {
396
420
  background-color: var(--xh-intent-danger-darkest);
397
421
  }
398
422
  &.xh-button--enabled {
399
- &:hover:not(:active):not(.xh-button--active) {
423
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
400
424
  background-color: var(--xh-intent-danger-darker);
401
425
  }
402
426
  &:active {
@@ -413,12 +437,13 @@
413
437
  color: var(--xh-button-text-color);
414
438
  background-color: transparent;
415
439
  border-color: var(--xh-button-border-color);
416
- &.xh-button--active {
440
+ &.xh-button--active,
441
+ &.bp6-active {
417
442
  background-color: var(--xh-button-active-bg);
418
443
  color: var(--xh-button-active-text-color);
419
444
  }
420
445
  &.xh-button--enabled {
421
- &:hover:not(:active):not(.xh-button--active) {
446
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
422
447
  background-color: var(--xh-button-bg-darker);
423
448
  }
424
449
  &:active {
@@ -431,11 +456,12 @@
431
456
  color: var(--xh-intent-primary-lighter);
432
457
  background-color: transparent;
433
458
  border-color: var(--xh-intent-primary-lighter);
434
- &.xh-button--active {
459
+ &.xh-button--active,
460
+ &.bp6-active {
435
461
  background-color: var(--xh-intent-primary-trans2);
436
462
  }
437
463
  &.xh-button--enabled {
438
- &:hover:not(:active):not(.xh-button--active) {
464
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
439
465
  background-color: var(--xh-intent-primary-trans1);
440
466
  }
441
467
  &:active {
@@ -448,11 +474,12 @@
448
474
  color: var(--xh-intent-success-lighter);
449
475
  background-color: transparent;
450
476
  border-color: var(--xh-intent-success-lighter);
451
- &.xh-button--active {
477
+ &.xh-button--active,
478
+ &.bp6-active {
452
479
  background-color: var(--xh-intent-success-trans2);
453
480
  }
454
481
  &.xh-button--enabled {
455
- &:hover:not(:active):not(.xh-button--active) {
482
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
456
483
  background-color: var(--xh-intent-success-trans1);
457
484
  }
458
485
  &:active {
@@ -465,11 +492,12 @@
465
492
  color: var(--xh-intent-warning-lighter);
466
493
  background-color: transparent;
467
494
  border-color: var(--xh-intent-warning-lighter);
468
- &.xh-button--active {
495
+ &.xh-button--active,
496
+ &.bp6-active {
469
497
  background-color: var(--xh-intent-warning-trans2);
470
498
  }
471
499
  &.xh-button--enabled {
472
- &:hover:not(:active):not(.xh-button--active) {
500
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
473
501
  background-color: var(--xh-intent-warning-trans1);
474
502
  }
475
503
  &:active {
@@ -482,11 +510,12 @@
482
510
  color: var(--xh-intent-danger-lighter);
483
511
  background-color: transparent;
484
512
  border-color: var(--xh-intent-danger-lighter);
485
- &.xh-button--active {
513
+ &.xh-button--active,
514
+ &.bp6-active {
486
515
  background-color: var(--xh-intent-danger-trans2);
487
516
  }
488
517
  &.xh-button--enabled {
489
- &:hover:not(:active):not(.xh-button--active) {
518
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
490
519
  background-color: var(--xh-intent-danger-trans1);
491
520
  }
492
521
  &:active {
@@ -510,7 +539,7 @@
510
539
  .xh-button.bp6-button.xh-button--minimal {
511
540
  &.xh-button--intent-none {
512
541
  &.xh-button--enabled {
513
- &:hover:not(:active):not(.xh-button--active) {
542
+ &:hover:not(:active):not(.xh-button--active):not(.bp6-active) {
514
543
  background-color: var(--xh-intent-neutral-trans1);
515
544
  }
516
545
  &:active {
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import {ButtonProps as BpButtonProps} from '@blueprintjs/core';
8
8
  import {
9
+ DomAttrsProps,
9
10
  hoistCmp,
10
11
  HoistModel,
11
12
  HoistProps,
@@ -23,7 +24,13 @@ import {ReactElement, ReactNode} from 'react';
23
24
  import './Button.scss';
24
25
 
25
26
  export interface ButtonProps<M extends HoistModel = null>
26
- extends HoistProps<M>, StyleProps, LayoutProps, TestSupportProps, Omit<BpButtonProps, 'ref'> {
27
+ extends
28
+ HoistProps<M>,
29
+ StyleProps,
30
+ LayoutProps,
31
+ TestSupportProps,
32
+ DomAttrsProps,
33
+ Omit<BpButtonProps, 'ref'> {
27
34
  active?: boolean;
28
35
  autoFocus?: boolean;
29
36
  disabled?: boolean;
@@ -83,6 +90,7 @@ export const [Button, button] = hoistCmp.withFactory<ButtonProps, ButtonDefaults
83
90
  tooltip,
84
91
  active,
85
92
  testId,
93
+ domAttrs,
86
94
  ...rest
87
95
  } = nonLayoutProps;
88
96
 
@@ -111,6 +119,7 @@ export const [Button, button] = hoistCmp.withFactory<ButtonProps, ButtonDefaults
111
119
  className: classNames(className, classes),
112
120
  ref,
113
121
  [TEST_ID]: testId,
122
+ ...domAttrs,
114
123
  disabled,
115
124
  icon,
116
125
  intent,
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import {ButtonGroupProps as BpButtonGroupProps} from '@blueprintjs/core';
8
8
  import {
9
+ DomAttrsProps,
9
10
  hoistCmp,
10
11
  HoistModel,
11
12
  HoistProps,
@@ -25,6 +26,7 @@ export interface ButtonGroupProps<M extends HoistModel = null>
25
26
  LayoutProps,
26
27
  StyleProps,
27
28
  TestSupportProps,
29
+ DomAttrsProps,
28
30
  SetOptional<Omit<BpButtonGroupProps, 'ref'>, 'children'> {
29
31
  /** True to have all buttons fill available width equally. */
30
32
  fill?: boolean;
@@ -45,13 +47,14 @@ export const [ButtonGroup, buttonGroup] = hoistCmp.withFactory<ButtonGroupProps>
45
47
  className: 'xh-button-group',
46
48
 
47
49
  render(props, ref) {
48
- const [layoutProps, {fill, minimal, vertical, style, testId, ...rest}] =
50
+ const [layoutProps, {fill, minimal, vertical, style, testId, domAttrs, ...rest}] =
49
51
  splitLayoutProps(props);
50
52
  return bpButtonGroup({
51
53
  fill,
52
54
  minimal,
53
55
  vertical,
54
56
  [TEST_ID]: testId,
57
+ ...domAttrs,
55
58
  style: {
56
59
  ...style,
57
60
  ...layoutProps
@@ -99,7 +99,15 @@ export const [ColChooserButton, colChooserButton] = hoistCmp.withFactory<ColChoo
99
99
  popoverClassName: 'xh-col-chooser-popover',
100
100
  position: withDefault(popoverPosition, 'auto'),
101
101
  isOpen: modalModel.isPopoverOpen,
102
- item: button({icon, title, className, disabled, onClick, ...rest}),
102
+ item: button({
103
+ icon,
104
+ title,
105
+ className,
106
+ disabled,
107
+ active: modalModel.isPopoverOpen,
108
+ onClick,
109
+ ...rest
110
+ }),
103
111
  disabled,
104
112
  content: vbox({
105
113
  onClick: stopPropagation,
@@ -61,6 +61,7 @@ export const [ZoneMapperButton, zoneMapperButton] = hoistCmp.withFactory<ZoneMap
61
61
  title: withDefault(title, 'Customize fields...'),
62
62
  className,
63
63
  disabled,
64
+ active: isOpen,
64
65
  ...rest
65
66
  }),
66
67
  disabled,
@@ -50,4 +50,7 @@ export interface DashConfig<VSPEC extends DashViewSpec, VSTATE extends DashViewS
50
50
  * including when the dash container is empty.
51
51
  */
52
52
  extraMenuItems?: MenuItemLike[];
53
+
54
+ /** See {@link HoistBase.xhName}. */
55
+ xhName?: string;
53
56
  }
@@ -92,7 +92,15 @@ export abstract class DashViewModel<T extends DashViewSpec = DashViewSpec> exten
92
92
  return this.viewSpec.refreshMode ?? this.containerModel.refreshMode;
93
93
  }
94
94
 
95
- constructor({id, viewSpec, icon, title, viewState = null, containerModel}: DashViewConfig<T>) {
95
+ constructor({
96
+ id,
97
+ viewSpec,
98
+ icon,
99
+ title,
100
+ viewState = null,
101
+ containerModel,
102
+ xhName = null
103
+ }: DashViewConfig<T>) {
96
104
  super();
97
105
  makeObservable(this);
98
106
  throwIf(!id, 'DashViewModel requires an id');
@@ -104,8 +112,10 @@ export abstract class DashViewModel<T extends DashViewSpec = DashViewSpec> exten
104
112
  this.title = title ?? viewSpec.title;
105
113
  this.viewState = viewState;
106
114
  this.containerModel = containerModel;
115
+ this.xhName = xhName ?? containerModel?.childXhName(id);
107
116
 
108
117
  this.refreshContextModel = new ManagedRefreshContextModel(this);
118
+ this.refreshContextModel.xhName = this.childXhName('refreshContextModel');
109
119
  }
110
120
 
111
121
  /**
@@ -154,4 +164,7 @@ export interface DashViewConfig<T extends DashViewSpec = DashViewSpec> {
154
164
  title?: string;
155
165
  viewState?: DashViewState;
156
166
  containerModel?: any;
167
+
168
+ /** See {@link HoistBase.xhName}. */
169
+ xhName?: string;
157
170
  }