@xh/hoist 70.0.0-SNAPSHOT.1731694945674 → 70.0.0-SNAPSHOT.1731700937079

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -56,6 +56,8 @@
56
56
  of the model.
57
57
  * Expanded the `JsonBlob` interface to include additional properties present on all blobs.
58
58
  * Corrected `DashViewSpec.title` to be optional - it can be defaulted from the `id`.
59
+ * Corrected the return type for `SelectProps.loadingMessageFn` and `noOptionsMessageFn` to return
60
+ `ReactNode` vs `string`. The component supports rendering richer content via these options.
59
61
 
60
62
  ## 69.1.0 - 2024-11-07
61
63
 
@@ -1,9 +1,9 @@
1
- import { HoistModel, LoadSpec, Persistable, PersistableState, PersistOptions, PlainObject, Thunkable, ViewManagerProvider } from '@xh/hoist/core';
1
+ import { HoistModel, LoadSpec, Persistable, PersistableState, PersistOptions, PlainObject, TaskObserver, Thunkable, ViewManagerProvider } from '@xh/hoist/core';
2
2
  import { SaveDialogModel } from './impl/SaveDialogModel';
3
3
  import { View, ViewTree } from './Types';
4
4
  export interface ViewManagerConfig {
5
5
  /**
6
- * True (default) to allow user to opt-in to automatically saving changes to their private
6
+ * True (default) to allow user to opt in to automatically saving changes to their private
7
7
  * views - requires `persistWith`.
8
8
  */
9
9
  enableAutoSave?: boolean;
@@ -84,6 +84,11 @@ export declare class ViewManagerModel<T extends PlainObject = PlainObject> exten
84
84
  * generally available as per `enableAutoSave`).
85
85
  */
86
86
  autoSaveActive: boolean;
87
+ /**
88
+ * TaskObserver linked to {@link selectViewAsync}. If a change to the active view is likely to
89
+ * require intensive layout/grid work, consider masking affected components with this observer.
90
+ */
91
+ viewSelectionObserver: TaskObserver;
87
92
  manageDialogOpen: boolean;
88
93
  readonly saveDialogModel: SaveDialogModel;
89
94
  private readonly _enableSharing;
@@ -72,7 +72,7 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
72
72
  /** Icon to display inline on the left side of the input. */
73
73
  leftIcon?: ReactElement;
74
74
  /** Function to return loading message during an async query. Passed current query input. */
75
- loadingMessageFn?: (query: string) => string;
75
+ loadingMessageFn?: (query: string) => ReactNode;
76
76
  /** Maximum height of the menu before scrolling. Defaults to 300px. */
77
77
  maxMenuHeight?: number;
78
78
  /** Placement of the dropdown menu relative to the input control. */
@@ -80,7 +80,7 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
80
80
  /** Width in pixels for the dropdown menu - if unspecified, defaults to control width. */
81
81
  menuWidth?: number;
82
82
  /** Function to return message indicating no options loaded. Passed current query input. */
83
- noOptionsMessageFn?: (query: string) => string;
83
+ noOptionsMessageFn?: (query: string) => ReactNode;
84
84
  /** True to auto-open the dropdown menu on input focus. */
85
85
  openMenuOnFocus?: boolean;
86
86
  /**
@@ -88,7 +88,7 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
88
88
  * will contain at minimum a value and label field, as well as any other fields present in
89
89
  * the source objects).
90
90
  */
91
- optionRenderer?: (SelectOption: any) => ReactNode;
91
+ optionRenderer?: (opt: SelectOption) => ReactNode;
92
92
  /**
93
93
  * Preset list of options for selection. Elements can be either a primitive or an object.
94
94
  * Primitives will be displayed via toString().
@@ -7,6 +7,7 @@ import {
7
7
  PersistenceProvider,
8
8
  PersistOptions,
9
9
  PlainObject,
10
+ TaskObserver,
10
11
  Thunkable,
11
12
  ViewManagerProvider,
12
13
  XH
@@ -22,7 +23,7 @@ import {View, ViewTree} from './Types';
22
23
 
23
24
  export interface ViewManagerConfig {
24
25
  /**
25
- * True (default) to allow user to opt-in to automatically saving changes to their private
26
+ * True (default) to allow user to opt in to automatically saving changes to their private
26
27
  * views - requires `persistWith`.
27
28
  */
28
29
  enableAutoSave?: boolean;
@@ -114,6 +115,12 @@ export class ViewManagerModel<T extends PlainObject = PlainObject>
114
115
  */
115
116
  @bindable autoSaveActive = false;
116
117
 
118
+ /**
119
+ * TaskObserver linked to {@link selectViewAsync}. If a change to the active view is likely to
120
+ * require intensive layout/grid work, consider masking affected components with this observer.
121
+ */
122
+ viewSelectionObserver: TaskObserver;
123
+
117
124
  @observable manageDialogOpen = false;
118
125
  @managed readonly saveDialogModel: SaveDialogModel;
119
126
 
@@ -234,6 +241,10 @@ export class ViewManagerModel<T extends PlainObject = PlainObject>
234
241
  this.enableFavorites = enableFavorites && !!persistWith;
235
242
  this.saveDialogModel = new SaveDialogModel(this);
236
243
 
244
+ this.viewSelectionObserver = TaskObserver.trackLast({
245
+ message: `Updating ${this.displayName}...`
246
+ });
247
+
237
248
  if (persistWith) {
238
249
  PersistenceProvider.create({
239
250
  persistOptions: {
@@ -278,18 +289,19 @@ export class ViewManagerModel<T extends PlainObject = PlainObject>
278
289
  }
279
290
 
280
291
  async selectViewAsync(token: string) {
281
- // TODO - review if we benefit from async + masking - eg during intensive
282
- // component rebuild within setValue?
283
- await wait();
284
-
285
- this.selectedToken = token;
286
-
287
- // Allow this model to restore its own persisted state in its ctor and note the desired
288
- // selected token before views have been loaded. Once views are loaded, this method will
289
- // be called again with the desired token and will proceed to set the value.
290
- if (isEmpty(this.views)) return;
291
-
292
- this.setValue(this.selectedView?.value ?? ({} as T));
292
+ // Introduce minimal wait and link to viewSelectionObserver to allow apps to mask.
293
+ await wait(100)
294
+ .then(() => {
295
+ this.selectedToken = token;
296
+
297
+ // Allow this model to restore its own persisted state in its ctor and note the desired
298
+ // selected token before views have been loaded. Once views are loaded, this method will
299
+ // be called again with the desired token and will proceed to set the value.
300
+ if (isEmpty(this.views)) return;
301
+
302
+ this.setValue(this.selectedView?.value ?? ({} as T));
303
+ })
304
+ .linkTo(this.viewSelectionObserver);
293
305
  }
294
306
 
295
307
  async saveAsync(skipToast: boolean = false) {
@@ -123,7 +123,7 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
123
123
  leftIcon?: ReactElement;
124
124
 
125
125
  /** Function to return loading message during an async query. Passed current query input. */
126
- loadingMessageFn?: (query: string) => string;
126
+ loadingMessageFn?: (query: string) => ReactNode;
127
127
 
128
128
  /** Maximum height of the menu before scrolling. Defaults to 300px. */
129
129
  maxMenuHeight?: number;
@@ -135,7 +135,7 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
135
135
  menuWidth?: number;
136
136
 
137
137
  /** Function to return message indicating no options loaded. Passed current query input. */
138
- noOptionsMessageFn?: (query: string) => string;
138
+ noOptionsMessageFn?: (query: string) => ReactNode;
139
139
 
140
140
  /** True to auto-open the dropdown menu on input focus. */
141
141
  openMenuOnFocus?: boolean;
@@ -145,7 +145,7 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
145
145
  * will contain at minimum a value and label field, as well as any other fields present in
146
146
  * the source objects).
147
147
  */
148
- optionRenderer?: (SelectOption) => ReactNode;
148
+ optionRenderer?: (opt: SelectOption) => ReactNode;
149
149
 
150
150
  /**
151
151
  * Preset list of options for selection. Elements can be either a primitive or an object.
@@ -188,7 +188,7 @@ const viewMenu = hoistCmp.factory<ViewManagerProps>({
188
188
  }),
189
189
  menuItem({
190
190
  icon: Icon.copy(),
191
- text: 'Save as...',
191
+ text: 'Save As...',
192
192
  onClick: () => model.saveAsAsync()
193
193
  }),
194
194
  menuItem({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "70.0.0-SNAPSHOT.1731694945674",
3
+ "version": "70.0.0-SNAPSHOT.1731700937079",
4
4
  "description": "Hoist add-on for building and deploying React Applications.",
5
5
  "repository": "github:xh/hoist-react",
6
6
  "homepage": "https://xh.io",