@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
@@ -111,6 +111,9 @@ export interface PanelConfig {
111
111
 
112
112
  /** @internal */
113
113
  xhImpl?;
114
+
115
+ /** See {@link HoistBase.xhName}. */
116
+ xhName?: string;
114
117
  }
115
118
 
116
119
  export interface PanelPersistState {
@@ -215,11 +218,13 @@ export class PanelModel extends HoistModel implements Persistable<PanelPersistSt
215
218
  showSplitterCollapseButton = showSplitter && collapsible,
216
219
  showHeaderCollapseButton = true,
217
220
  showModalToggleButton = true,
221
+ xhName = null,
218
222
  xhImpl = false
219
223
  }: PanelConfig) {
220
224
  super();
221
225
  makeObservable(this);
222
226
  this.xhImpl = xhImpl;
227
+ this.xhName = xhName;
223
228
 
224
229
  defaultSize =
225
230
  isString(defaultSize) && defaultSize.endsWith('px')
@@ -267,6 +272,7 @@ export class PanelModel extends HoistModel implements Persistable<PanelPersistSt
267
272
  modalSupport === true
268
273
  ? new ModalSupportModel()
269
274
  : new ModalSupportModel(modalSupport);
275
+ this.modalSupportModel.xhName = this.childXhName('modalSupportModel');
270
276
  }
271
277
 
272
278
  if (errorBoundary) {
@@ -274,10 +280,12 @@ export class PanelModel extends HoistModel implements Persistable<PanelPersistSt
274
280
  errorBoundary === true
275
281
  ? new ErrorBoundaryModel()
276
282
  : new ErrorBoundaryModel(errorBoundary);
283
+ this.errorBoundaryModel.xhName = this.childXhName('errorBoundaryModel');
277
284
  }
278
285
 
279
286
  if (collapsible) {
280
287
  this.refreshContextModel = new ManagedRefreshContextModel(this);
288
+ this.refreshContextModel.xhName = this.childXhName('refreshContextModel');
281
289
  }
282
290
 
283
291
  if (collapsible || resizable) {
@@ -18,7 +18,7 @@ export const resizeContainer = hoistCmp.factory({
18
18
  model: false,
19
19
  className: 'xh-resizable',
20
20
 
21
- render({className, children, testId}, ref) {
21
+ render({className, children, testId, domAttrs}, ref) {
22
22
  const panelModel = useContextModel(PanelModel),
23
23
  {size, resizable, collapsed, vertical, contentFirst, showSplitter} = panelModel,
24
24
  dim = vertical ? 'height' : 'width',
@@ -53,6 +53,7 @@ export const resizeContainer = hoistCmp.factory({
53
53
  [maxDim]: '100%',
54
54
  [minDim]: dragBarWidth,
55
55
  testId,
56
+ domAttrs,
56
57
  items
57
58
  });
58
59
  }
@@ -162,9 +162,11 @@ export class RestGridModel extends HoistModel {
162
162
  onRowDoubleClicked,
163
163
  store,
164
164
  appData,
165
+ xhName = null,
165
166
  ...rest
166
167
  }: RestGridConfig) {
167
168
  super();
169
+ this.xhName = xhName;
168
170
  this.readonly = readonly;
169
171
  this.editors = editors;
170
172
  this.toolbarActions = toolbarActions;
@@ -186,6 +188,7 @@ export class RestGridModel extends HoistModel {
186
188
  });
187
189
 
188
190
  this.gridModel = new GridModel({
191
+ xhName: this.childXhName('gridModel'),
189
192
  contextMenu: [...this.menuActions, '-', ...GridModel.defaults.contextMenu],
190
193
  exportOptions: {filename: pluralize(unit)},
191
194
  store: this.parseStore(store),
@@ -197,6 +200,7 @@ export class RestGridModel extends HoistModel {
197
200
  });
198
201
 
199
202
  this.formModel = new RestFormModel(this);
203
+ this.formModel.xhName = this.childXhName('formModel');
200
204
  }
201
205
 
202
206
  /** Load the underlying store. */
@@ -24,6 +24,7 @@ export function tabContainerImpl({
24
24
  childContainerProps,
25
25
  className,
26
26
  testId,
27
+ domAttrs,
27
28
  ...props
28
29
  }: TabContainerProps) {
29
30
  const switcherProps = getSwitcherProps(props),
@@ -40,6 +41,7 @@ export function tabContainerImpl({
40
41
  ...layoutProps,
41
42
  className,
42
43
  testId,
44
+ domAttrs,
43
45
  item: getChildren(model, switcherProps, testId, childContainerProps)
44
46
  });
45
47
  }
package/docs/README.md CHANGED
@@ -34,6 +34,7 @@ See [`docs-roadmap.md`](./planning/docs-roadmap.md) for documentation coverage t
34
34
  | Configure a desktop panel (toolbars, masks, collapse) | [`/desktop/cmp/panel/`](../desktop/cmp/panel/README.md) |
35
35
  | Build a mobile app | [`/mobile/`](../mobile/README.md) |
36
36
  | Save and restore named view configurations | [`/cmp/viewmanager/`](../cmp/viewmanager/README.md) |
37
+ | Select a period or date range (presets, lookbacks, months, custom) | [`/cmp/daterange/`](../cmp/daterange/README.md) |
37
38
  | Use layout containers (Box, HBox, VBox, Frame) | [`/cmp/layout/`](../cmp/layout/README.md) |
38
39
  | Work with Stores, Records, Fields, or Filters | [`/data/`](../data/README.md) |
39
40
  | Set up Cube aggregation with Views and Queries | [`/data/cube/`](../data/cube/README.md) |
@@ -87,6 +88,7 @@ See [`docs-roadmap.md`](./planning/docs-roadmap.md) for documentation coverage t
87
88
  | [`/cmp/layout/`](../cmp/layout/README.md) | Flexbox-based layout containers | Box, VBox, HBox, Frame, Viewport, LayoutProps, pixel conversion |
88
89
  | [`/cmp/tab/`](../cmp/tab/README.md) | Tabbed interface system | TabContainerModel, routing integration, render modes, refresh strategies |
89
90
  | [`/cmp/viewmanager/`](../cmp/viewmanager/README.md) | Save/load named bundles of component state | ViewManagerModel, views, sharing, pinning, auto-save, JsonBlob persistence |
91
+ | [`/cmp/daterange/`](../cmp/daterange/README.md) | Period selection as presets, relative lookbacks, months/years, or custom ranges, resolved to dates and filters | DateRangePickerModel, DateRangePicker, DateRangeSelection, presets, anchorDate, LocalDateRange, currentRangeFilter, priorRange |
90
92
  | [`/desktop/`](../desktop/README.md) | Desktop-specific components and app container | Desktop components, Blueprint wrappers, desktop navigation |
91
93
  | [`/desktop/cmp/dash/`](../desktop/cmp/dash/README.md) | Configurable dashboard system with draggable, resizable widgets | DashContainerModel, DashCanvasModel, DashViewSpec, DashViewModel, widget persistence, ViewManager integration |
92
94
  | [`/desktop/cmp/panel/`](../desktop/cmp/panel/README.md) | Desktop panel container with toolbars, masks, and collapsible behavior | Panel, PanelModel, Toolbar, mask, collapse/resize, persistence, modal support |
@@ -24,6 +24,14 @@ Publishes a SNAPSHOT build to npm on every push to `develop`. Can also be trigge
24
24
  - Linting runs as part of this workflow — a lint failure will block the publish.
25
25
  - Uses `concurrency` with `cancel-in-progress: true` to avoid redundant builds when multiple pushes
26
26
  land in quick succession.
27
+ - After publishing, polls `npm view @xh/hoist@next` until the registry resolves the `next` dist-tag
28
+ to the version just published (10 minute limit). Publishing returns once npm accepts the tarball,
29
+ but the new version is not guaranteed to be resolvable at that moment.
30
+ - Finally fires a `repository_dispatch` (`hoist-react-snapshot`) to `xh/toolbox`, which rebuilds
31
+ and redeploys Toolbox against the new snapshot. The dispatch authenticates as the org-owned
32
+ **XH Build Bot** GitHub App via a short-lived installation token minted by
33
+ `actions/create-github-app-token`, scoped to the toolbox repo with Contents: write. Toolbox runs
34
+ triggered this way show `xh-build-bot[bot]` as the actor.
27
35
 
28
36
  ## Deploy Release (`deployRelease.yml`)
29
37
 
@@ -62,13 +70,21 @@ Inputs:
62
70
  Automated dependency update PRs are configured for both GitHub Actions and npm dependencies, each
63
71
  checking weekly.
64
72
 
65
- ## Required Secrets
66
-
67
- | Secret | Used By | Purpose |
68
- |--------|---------|---------|
69
- | `FONTAWESOME_PACKAGE_TOKEN` | CI, Snapshot, Release | Auth token for the Font Awesome Pro npm registry (`npm.fontawesome.com`) |
70
- | `NPM_TOKEN` | Snapshot, Release, Unpublish | Auth token for publishing to the npm public registry |
71
- | `GITHUB_TOKEN` | Release | Provided automatically by GitHub Actions; used for `gh release create` |
73
+ ## Required Secrets and Variables
74
+
75
+ | Name | Type | Used By | Purpose |
76
+ |------|------|---------|---------|
77
+ | `FONTAWESOME_PACKAGE_TOKEN` | Secret | CI, Snapshot, Release | Auth token for the Font Awesome Pro npm registry (`npm.fontawesome.com`) |
78
+ | `NPM_TOKEN` | Secret | Snapshot, Release, Unpublish | Auth token for publishing to the npm public registry |
79
+ | `XH_BUILD_BOT_PRIVATE_KEY` | Secret | Snapshot | Private key for the XH Build Bot GitHub App, used to mint the Toolbox dispatch token |
80
+ | `XH_BUILD_BOT_CLIENT_ID` | Variable | Snapshot | Client ID of the XH Build Bot GitHub App |
81
+ | `GITHUB_TOKEN` | Secret | Release | Provided automatically by GitHub Actions; used for `gh release create` |
82
+
83
+ The XH Build Bot app is registered under the xh GitHub org and installed org-wide. Its credentials
84
+ (app ID, client ID, and private key) are kept in the team 1Password vault under
85
+ "GitHub App: XH Build Bot". To rotate, generate a new private key on the app's settings page, update
86
+ the 1Password item and the `XH_BUILD_BOT_PRIVATE_KEY` secret here and in hoist-core, then revoke the
87
+ old key.
72
88
 
73
89
  Font Awesome Pro packages are sourced from the official Font Awesome registry at
74
90
  `npm.fontawesome.com` (configured in `.npmrc`). The `FONTAWESOME_PACKAGE_TOKEN` secret is appended
@@ -127,6 +127,14 @@
127
127
  "description": "Save/load named bundles of component state.",
128
128
  "keywords": ["ViewManagerModel", "views", "sharing", "pinning", "auto-save", "JsonBlob persistence"]
129
129
  },
130
+ {
131
+ "id": "cmp/daterange/README.md",
132
+ "title": "Date Range Package",
133
+ "mcpCategory": "package",
134
+ "viewerCategory": "components",
135
+ "description": "Period selection as presets, relative lookbacks, months/years, or custom ranges, resolved to dates and filters.",
136
+ "keywords": ["DateRangePickerModel", "DateRangePicker", "DateRangeSelection", "dateRangePresets", "DateRangePreset", "LocalDateRange", "anchorDate", "currentRangeFilter", "priorRange", "business days"]
137
+ },
130
138
  {
131
139
  "id": "desktop/cmp/dash/README.md",
132
140
  "title": "Dashboard System",
@@ -162,6 +162,7 @@ taking its current major alongside a hoist-react upgrade is low-cost and always
162
162
 
163
163
  | hoist-react | Min Dev-Utils Required | Recommended Dev-Utils | Notes |
164
164
  |---|---|---|---|
165
+ | 87.1 | -- | 15.0.1 | Take 15.0.1+, not 15.0.0. dev-utils 15 requires 87.1, enforced with a fail-fast build error. Apps taking v15 must also be TS-only (no `.jsx` files) and will see ESLint v10 rules. |
165
166
  | 87.0 | 14.0 | 14.0 | React 19: dev-utils 14 ships `@types/react` 19.x and is required for apps adopting pnpm. (13.x can build v87 with `@types/react` 19.x pinned via `resolutions` - a transitional pairing only, not supported.) |
166
167
  | 86.0 | -- | 13.0.1 | dev-utils 13 sets a Node floor of >= 22.11 and swaps the markdown loader - verify `flex: 1 1 0` styles (see [v86 notes](./upgrade-notes/v86-upgrade-notes.md)). |
167
168
  | 83.0 | -- | 12.0 | dev-utils 12's same-port dev proxy pairs with the hoist-react 83.0.2 `WebSocketService` fix. |
@@ -178,6 +179,7 @@ hard gates stated in the [hoist-dev-utils CHANGELOG](https://github.com/xh/hoist
178
179
 
179
180
  | hoist-dev-utils | Min hoist-react | Min Node | Notes |
180
181
  |---|---|---|---|
182
+ | 15.0 | 87.1 | 22.15 | Take 15.0.1+ - 15.0.0 can crash app boot ([#4640](https://github.com/xh/hoist-react/issues/4640)). Apps must be TypeScript-only - `.jsx` files are no longer resolved or transpiled. Re-enables Terser name-mangling, ships ESLint v10 via `@xh/eslint-config` 8, and emits pre-compressed `.br` / `.gz` assets on prod builds. |
181
183
  | 14.0 | 87.0 | 22.15 | React 19 / `@types/react` 19.x baseline. Adds pnpm support - apps adopting pnpm must take 14+, and must declare every package they import directly (see dev-utils CHANGELOG). webpack-dev-server 6. |
182
184
  | 13.0 | -- | 22.11 | Take 13.0.1+. Markdown files now import as strings; verify `flex: 1 1 0` styles. |
183
185
  | 12.0 | 83.0.2 | | Same-port dev proxy (`baseUrl` default now `/api/`); requires hoist-react's `WebSocketService` fix in 83.0.2. |
package/icon/Icon.ts CHANGED
@@ -189,6 +189,9 @@ export const Icon = {
189
189
  arrowsUpDown(p?: IconProps) {
190
190
  return Icon.icon({...p, iconName: 'arrows-v'});
191
191
  },
192
+ asterisk(p?: IconProps) {
193
+ return Icon.icon({...p, iconName: 'asterisk'});
194
+ },
192
195
  balanceScale(p?: IconProps) {
193
196
  return Icon.icon({...p, iconName: 'balance-scale'});
194
197
  },
@@ -231,6 +234,12 @@ export const Icon = {
231
234
  calendar(p?: IconProps) {
232
235
  return Icon.icon({...p, iconName: 'calendar-day'});
233
236
  },
237
+ calendarDays(p?: IconProps) {
238
+ return Icon.icon({...p, iconName: 'calendar-days'});
239
+ },
240
+ calendarRange(p?: IconProps) {
241
+ return Icon.icon({...p, iconName: 'calendar-range'});
242
+ },
234
243
  camera(p?: IconProps) {
235
244
  return Icon.icon({...p, iconName: 'camera'});
236
245
  },
package/icon/index.ts CHANGED
@@ -33,6 +33,7 @@ import {
33
33
  faArrowToTop as faArrowToTopLight,
34
34
  faArrowUp as faArrowUpLight,
35
35
  faArrowUpFromBracket as faArrowUpFromBracketLight,
36
+ faAsterisk as faAsteriskLight,
36
37
  faBalanceScale as faBalanceScaleLight,
37
38
  faBalanceScaleLeft as faBalanceScaleLeftLight,
38
39
  faBalanceScaleRight as faBalanceScaleRightLight,
@@ -53,6 +54,8 @@ import {
53
54
  faBullseyeArrow as faBullseyeArrowLight,
54
55
  faCalculator as faCalculatorLight,
55
56
  faCalendarDay as faCalendarDayLight,
57
+ faCalendarDays as faCalendarDaysLight,
58
+ faCalendarRange as faCalendarRangeLight,
56
59
  faCamera as faCameraLight,
57
60
  faCaretLeft as faCaretLeftLight,
58
61
  faCaretRight as faCaretRightLight,
@@ -251,6 +254,7 @@ import {
251
254
  faArrowToTop,
252
255
  faArrowUp,
253
256
  faArrowUpFromBracket,
257
+ faAsterisk,
254
258
  faBalanceScale,
255
259
  faBalanceScaleLeft,
256
260
  faBalanceScaleRight,
@@ -271,6 +275,8 @@ import {
271
275
  faBullseyeArrow,
272
276
  faCalculator,
273
277
  faCalendarDay,
278
+ faCalendarDays,
279
+ faCalendarRange,
274
280
  faCamera,
275
281
  faCaretLeft,
276
282
  faCaretRight,
@@ -469,6 +475,7 @@ import {
469
475
  faArrowToTop as faArrowToTopSolid,
470
476
  faArrowUp as faArrowUpSolid,
471
477
  faArrowUpFromBracket as faArrowUpFromBracketSolid,
478
+ faAsterisk as faAsteriskSolid,
472
479
  faBalanceScale as faBalanceScaleSolid,
473
480
  faBalanceScaleLeft as faBalanceScaleLeftSolid,
474
481
  faBalanceScaleRight as faBalanceScaleRightSolid,
@@ -489,6 +496,8 @@ import {
489
496
  faBullseyeArrow as faBullseyeArrowSolid,
490
497
  faCalculator as faCalculatorSolid,
491
498
  faCalendarDay as faCalendarDaySolid,
499
+ faCalendarDays as faCalendarDaysSolid,
500
+ faCalendarRange as faCalendarRangeSolid,
492
501
  faCamera as faCameraSolid,
493
502
  faCaretLeft as faCaretLeftSolid,
494
503
  faCaretRight as faCaretRightSolid,
@@ -688,6 +697,7 @@ import {
688
697
  faArrowToTop as faArrowToTopThin,
689
698
  faArrowUp as faArrowUpThin,
690
699
  faArrowUpFromBracket as faArrowUpFromBracketThin,
700
+ faAsterisk as faAsteriskThin,
691
701
  faBalanceScale as faBalanceScaleThin,
692
702
  faBalanceScaleLeft as faBalanceScaleLeftThin,
693
703
  faBalanceScaleRight as faBalanceScaleRightThin,
@@ -708,6 +718,8 @@ import {
708
718
  faBullseyeArrow as faBullseyeArrowThin,
709
719
  faCalculator as faCalculatorThin,
710
720
  faCalendarDay as faCalendarDayThin,
721
+ faCalendarDays as faCalendarDaysThin,
722
+ faCalendarRange as faCalendarRangeThin,
711
723
  faCamera as faCameraThin,
712
724
  faCaretLeft as faCaretLeftThin,
713
725
  faCaretRight as faCaretRightThin,
@@ -976,6 +988,10 @@ library.add(
976
988
  faArrowUpLight,
977
989
  faArrowUpSolid,
978
990
  faArrowUpThin,
991
+ faAsterisk,
992
+ faAsteriskLight,
993
+ faAsteriskSolid,
994
+ faAsteriskThin,
979
995
  faBalanceScale,
980
996
  faBalanceScaleLight,
981
997
  faBalanceScaleSolid,
@@ -1053,9 +1069,17 @@ library.add(
1053
1069
  faCalculatorSolid,
1054
1070
  faCalculatorThin,
1055
1071
  faCalendarDay,
1072
+ faCalendarDays,
1073
+ faCalendarRange,
1056
1074
  faCalendarDayLight,
1057
1075
  faCalendarDaySolid,
1058
1076
  faCalendarDayThin,
1077
+ faCalendarDaysLight,
1078
+ faCalendarDaysSolid,
1079
+ faCalendarDaysThin,
1080
+ faCalendarRangeLight,
1081
+ faCalendarRangeSolid,
1082
+ faCalendarRangeThin,
1059
1083
  faCamera,
1060
1084
  faCameraLight,
1061
1085
  faCameraSolid,
@@ -122,7 +122,8 @@ navigation or load action created them.
122
122
  The Instances panel is a split layout with:
123
123
 
124
124
  - **Instances grid** (left, resizable) — Lists all live `HoistModel`, `HoistService`, `Store`,
125
- `Cube`, and `View` instances with their class name, creation time, linked status, and sync run
125
+ `Cube`, and `View` instances with their `xhName` (when set), class name, creation time,
126
+ linked status, and sync run
126
127
  - **Properties grid** (right) — Shows properties of the selected instance(s), including observable
127
128
  values with live updates
128
129
  - **Diagnostics panel** (tabbed with properties) — Live readout of the data-pipeline
@@ -133,6 +134,10 @@ The Instances panel is a split layout with:
133
134
  - **Grouping** — Toggle "Show in Groups" to group by type (Models, Services, Stores)
134
135
  - **XH impl filtering** — Toggle "Show XH Impl" to show/hide Hoist's internal framework instances
135
136
  (marked with `xhImpl = true`)
137
+ - **Favorites** — Star any instance with an `xhName` to pin it, then toggle "Favorites" to show
138
+ only pinned instances. Keyed by `{className}:{xhName}` and persisted, so the same set of objects
139
+ can be followed across reloads. Favorites with no live instance show as muted placeholder rows -
140
+ un-star one to drop it
136
141
  - **Actions** — Log instance to devtools console, trigger `loadAsync()` on models with
137
142
  `LoadSupport`
138
143
  - **Multi-select** — Select multiple instances to compare their properties side-by-side
@@ -178,7 +183,8 @@ Inspector state is persisted to `localStorage` under the key
178
183
 
179
184
  - Panel sizes (stats panel, instances panel)
180
185
  - Grid column state for both grids
181
- - Quick filter selections (grouping, xhImpl visibility, property filters)
186
+ - Quick filter selections (grouping, xhImpl visibility, favorites, property filters)
187
+ - Favorited instances
182
188
  - Store filter text
183
189
  - Active/inactive state
184
190
 
@@ -0,0 +1,12 @@
1
+ /*
2
+ * This file belongs to Hoist, an application development toolkit
3
+ * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
+ *
5
+ * Copyright © 2026 Extremely Heavy Industries Inc.
6
+ */
7
+ import type {HoistBase} from '@xh/hoist/core';
8
+
9
+ /** Label for an instance within Inspector - its `xhName` or class name, plus `xhId`. */
10
+ export function instanceLabel(inst: HoistBase): string {
11
+ return `${inst.xhName ?? inst.constructor.name} [${inst.xhId}]`;
12
+ }
@@ -11,6 +11,7 @@ import {fmtDate, numberRenderer} from '@xh/hoist/format';
11
11
  import {action, makeObservable} from '@xh/hoist/mobx';
12
12
  import {Cube} from '@xh/hoist/data';
13
13
  import {forIn, isEmpty, isFinite} from 'lodash';
14
+ import {instanceLabel} from '../impl/InspectorUtils';
14
15
  import type {InstancesModel} from './InstancesModel';
15
16
 
16
17
  /**
@@ -55,7 +56,7 @@ export class DiagnosticsModel extends HoistModel {
55
56
  private get diagnosticSources(): DiagnosticSource[] {
56
57
  const ret: DiagnosticSource[] = [];
57
58
  this.parent.selectedInstances.forEach(inst => {
58
- const label = `${inst.constructor.name} [${inst.xhId}]`,
59
+ const label = instanceLabel(inst),
59
60
  diag = (inst as any).diagnostics;
60
61
  if (diag instanceof BaseDiagnostics) {
61
62
  ret.push({xhId: inst.xhId, diag, label});
@@ -63,7 +64,7 @@ export class DiagnosticsModel extends HoistModel {
63
64
  ret.push({
64
65
  xhId: inst.xhId,
65
66
  diag: inst.store.diagnostics,
66
- label: `${label} › Store [${inst.store.xhId}]`
67
+ label: `${label} › ${instanceLabel(inst.store)}`
67
68
  });
68
69
  }
69
70
  });
@@ -16,6 +16,7 @@ import {action, bindable, isObservableProp, makeObservable, runInAction} from '@
16
16
  import {wait} from '@xh/hoist/promise';
17
17
  import {trimToDepth} from '@xh/hoist/utils/js';
18
18
  import {compact, find, forIn, head, without} from 'lodash';
19
+ import {instanceLabel} from '../impl/InspectorUtils';
19
20
  import {StatsModel} from '../stats/StatsModel';
20
21
  import {DiagnosticsModel} from './DiagnosticsModel';
21
22
 
@@ -48,6 +49,9 @@ export class InstancesModel extends HoistModel {
48
49
  @bindable @persist instancesStoreFilter;
49
50
  @bindable @persist propertiesStoreFilter;
50
51
 
52
+ /** Keys of favorited instances (`{className}:{xhName}`) - requires an `xhName` to pin. */
53
+ @bindable.ref @persist favorites: string[] = [];
54
+
51
55
  @bindable @persist instQuickFilters = ['showInGroups'];
52
56
  get showInGroups() {
53
57
  return this.instQuickFilters?.includes('showInGroups');
@@ -55,6 +59,9 @@ export class InstancesModel extends HoistModel {
55
59
  get showXhImpl() {
56
60
  return this.instQuickFilters?.includes('showXhImpl');
57
61
  }
62
+ get favoritesOnly() {
63
+ return this.instQuickFilters?.includes('favoritesOnly');
64
+ }
58
65
 
59
66
  @bindable @persist propQuickFilters = [];
60
67
  get showUnderscoreProps() {
@@ -68,7 +75,9 @@ export class InstancesModel extends HoistModel {
68
75
  }
69
76
 
70
77
  get selectedInstances(): HoistBase[] {
71
- return this.instancesGridModel.selectedIds.map((it: string) => this.getInstance(it));
78
+ return compact(
79
+ this.instancesGridModel.selectedIds.map((it: string) => this.getInstance(it))
80
+ );
72
81
  }
73
82
 
74
83
  constructor() {
@@ -160,6 +169,13 @@ export class InstancesModel extends HoistModel {
160
169
  }
161
170
  }
162
171
 
172
+ toggleFavorite(record: StoreRecord) {
173
+ const key = favoriteKey(record?.data);
174
+ if (!key) return;
175
+ const {favorites} = this;
176
+ this.favorites = favorites.includes(key) ? without(favorites, key) : [...favorites, key];
177
+ }
178
+
163
179
  togglePropsWatchlistItem(record: StoreRecord) {
164
180
  const {instanceXhId, property, isGetter} = record.data,
165
181
  {propsWatchlist} = this,
@@ -195,6 +211,9 @@ export class InstancesModel extends HoistModel {
195
211
  store: {
196
212
  fields: [
197
213
  {name: 'className', type: 'string'},
214
+ {name: 'xhName', type: 'string'},
215
+ {name: 'isFavorite', type: 'bool'},
216
+ {name: 'alive', type: 'bool'},
198
217
  {name: 'displayGroup', type: 'string'},
199
218
  {name: 'created', type: 'date'},
200
219
  {name: 'syncRun', type: 'number'},
@@ -218,12 +237,29 @@ export class InstancesModel extends HoistModel {
218
237
  columns: [
219
238
  {
220
239
  ...actionCol,
221
- width: calcActionColWidth(2),
240
+ width: calcActionColWidth(3),
222
241
  actions: [
223
242
  {
224
243
  icon: Icon.terminal(),
225
244
  tooltip: 'Log to console',
226
- actionFn: ({record}) => this.logInstanceToConsole(record)
245
+ actionFn: ({record}) => this.logInstanceToConsole(record),
246
+ displayFn: ({record}) => ({hidden: !record.data.alive})
247
+ },
248
+ {
249
+ icon: Icon.favorite(),
250
+ actionFn: ({record}) => this.toggleFavorite(record),
251
+ displayFn: ({record}) => {
252
+ const {xhName, isFavorite} = record.data;
253
+ return {
254
+ disabled: !xhName,
255
+ tooltip: xhName
256
+ ? 'Toggle Favorite'
257
+ : 'Set xhName to enable favorites',
258
+ icon: isFavorite
259
+ ? Icon.favorite({intent: 'warning', prefix: 'fas'})
260
+ : Icon.favorite({className: 'xh-text-color-muted'})
261
+ };
262
+ }
227
263
  },
228
264
  {
229
265
  icon: Icon.refresh({intent: 'success'}),
@@ -234,7 +270,11 @@ export class InstancesModel extends HoistModel {
234
270
  }
235
271
  ]
236
272
  },
237
- {field: 'id', displayName: 'xhId'},
273
+ {
274
+ field: 'id',
275
+ displayName: 'xhId',
276
+ renderer: (v, {record}) => (record.data.alive ? v : null)
277
+ },
238
278
  {
239
279
  field: 'syncRun',
240
280
  displayName: 'Sync',
@@ -252,6 +292,8 @@ export class InstancesModel extends HoistModel {
252
292
  renderer: v => (v ? Icon.link() : null)
253
293
  },
254
294
  {field: 'displayGroup', hidden: true},
295
+ {field: 'isFavorite', ...boolCheckCol, hidden: true},
296
+ {field: 'xhName', flex: 1, minWidth: 150},
255
297
  {field: 'className', flex: 1, minWidth: 150},
256
298
  {
257
299
  field: 'lastLoadCompleted',
@@ -263,10 +305,8 @@ export class InstancesModel extends HoistModel {
263
305
  },
264
306
  {field: 'created', align: 'right', renderer: timestampRenderer}
265
307
  ],
266
- rowClassFn: rec => {
267
- return rec?.data.isXhImpl ? 'xh-impl-row' : null;
268
- },
269
- onRowDoubleClicked: ({data: rec}) => this.logInstanceToConsole(rec),
308
+ rowClassFn: rec => (rec?.data.isXhImpl || !rec?.data.alive ? 'xh-impl-row' : null),
309
+ onRowDoubleClicked: ({data: rec}) => rec?.data.alive && this.logInstanceToConsole(rec),
270
310
  xhImpl: true
271
311
  });
272
312
  }
@@ -387,11 +427,15 @@ export class InstancesModel extends HoistModel {
387
427
  private autoLoadInstancesGrid() {
388
428
  this.addAutorun({
389
429
  run: () => {
390
- const {showXhImpl, instancesGridModel, selectedSyncRun} = this,
430
+ const {showXhImpl, favoritesOnly, favorites, instancesGridModel, selectedSyncRun} =
431
+ this,
391
432
  data = [];
392
433
 
393
434
  XH.inspectorService.activeInstances.forEach(inst => {
394
- if (!showXhImpl && inst.isXhImpl) return;
435
+ const isFavorite = favorites.includes(favoriteKey(inst));
436
+
437
+ // A star is an explicit opt-in, so favorites show regardless of the xhImpl filter.
438
+ if (favoritesOnly ? !isFavorite : !showXhImpl && inst.isXhImpl) return;
395
439
  if (selectedSyncRun && inst.syncRun !== selectedSyncRun) return;
396
440
 
397
441
  const displayGroup = inst.isHoistService
@@ -403,9 +447,29 @@ export class InstancesModel extends HoistModel {
403
447
  : inst.isView
404
448
  ? 'Views'
405
449
  : 'Models';
406
- data.push({...inst, displayGroup});
450
+ data.push({...inst, displayGroup, isFavorite, alive: true});
407
451
  });
408
452
 
453
+ // Favorites with no live instance - shown so they can be seen and un-starred.
454
+ if (favoritesOnly && !selectedSyncRun) {
455
+ const aliveKeys = new Set(data.map(favoriteKey));
456
+ favorites
457
+ .filter(key => !aliveKeys.has(key))
458
+ .forEach(key => {
459
+ const sep = key.indexOf(':'),
460
+ className = key.slice(0, sep),
461
+ xhName = key.slice(sep + 1);
462
+ data.push({
463
+ id: key,
464
+ className,
465
+ xhName,
466
+ displayGroup: 'Not Alive',
467
+ isFavorite: true,
468
+ alive: false
469
+ });
470
+ });
471
+ }
472
+
409
473
  instancesGridModel.loadData(data);
410
474
  }
411
475
  });
@@ -482,8 +546,7 @@ export class InstancesModel extends HoistModel {
482
546
  return null;
483
547
 
484
548
  const {xhId} = instance,
485
- ctorName = instance.constructor.name,
486
- instanceDisplayName = `${ctorName} [${xhId}]`,
549
+ instanceDisplayName = instanceLabel(instance),
487
550
  isLoadedGetter = isGetter && this.shouldLoadGetter(xhId, property),
488
551
  v = !isGetter || isLoadedGetter ? instance[property] : null,
489
552
  // Detect FormModel.values Proxy object - throws otherwise on attempt to render in grid.
@@ -554,7 +617,11 @@ export class InstancesModel extends HoistModel {
554
617
  }
555
618
  }
556
619
 
557
- const GROUP_SORT_ORDER = ['Models', 'Services', 'Cubes', 'Views', 'Stores'];
620
+ const GROUP_SORT_ORDER = ['Models', 'Services', 'Cubes', 'Views', 'Stores', 'Not Alive'];
621
+
622
+ /** Persistent identity for Favorites - null when the instance has no `xhName` to pin by. */
623
+ const favoriteKey = (inst: {className?: string; xhName?: string}): string =>
624
+ inst?.xhName ? `${inst.className}:${inst.xhName}` : null;
558
625
 
559
626
  const timestampRenderer = v => fmtDate(v, {fmt: 'HH:mm:ss.SSS'});
560
627
 
@@ -132,6 +132,12 @@ const instanceGridBar = hoistCmp.factory<InstancesModel>(({model}) => {
132
132
  value: 'showXhImpl',
133
133
  tooltip:
134
134
  'Show instances created as part of internal Hoist model/component implementations'
135
+ }),
136
+ button({
137
+ text: 'Favorites',
138
+ value: 'favoritesOnly',
139
+ tooltip:
140
+ 'Show only favorited instances, including any not currently alive. Star any instance with an xhName to favorite it - favorites persist across reloads.'
135
141
  })
136
142
  ]
137
143
  }),
@@ -6,11 +6,11 @@
6
6
  */
7
7
  import {elementFactory} from '@xh/hoist/core';
8
8
  import {ComponentType} from 'react';
9
- import {DayPicker} from 'react-day-picker';
10
- import 'react-day-picker/style.css';
9
+ import {DayPicker} from '@daypicker/react';
10
+ import '@daypicker/react/style.css';
11
11
 
12
12
  export {DayPicker};
13
- export type {DayPickerProps, Matcher} from 'react-day-picker';
13
+ export type {DayPickerProps, Matcher} from '@daypicker/react';
14
14
 
15
15
  // DayPicker's props are a discriminated union over its selection modes. Cast to ComponentType to
16
16
  // keep our element factory ergonomic and produce portable type declarations.
@@ -52,6 +52,7 @@ export const loginPanel = hoistCmp.factory({
52
52
  bind: 'username',
53
53
  leftIcon: Icon.user(),
54
54
  autoComplete: 'username',
55
+ enablePasswordManagers: true,
55
56
  autoCapitalize: 'none',
56
57
  commitOnChange: true,
57
58
  testId: 'xh-login-username'
@@ -64,6 +65,7 @@ export const loginPanel = hoistCmp.factory({
64
65
  leftIcon: Icon.lock(),
65
66
  type: 'password',
66
67
  autoComplete: 'current-password',
68
+ enablePasswordManagers: true,
67
69
  commitOnChange: true,
68
70
  testId: 'xh-login-password'
69
71
  })