@xh/hoist 75.0.0-SNAPSHOT.1753487024547 → 75.0.0-SNAPSHOT.1753490062755
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/build/types/cmp/viewmanager/ViewManagerModel.d.ts +50 -36
- package/cmp/viewmanager/ViewManagerModel.ts +57 -39
- package/desktop/cmp/viewmanager/ViewManager.ts +4 -2
- package/desktop/cmp/viewmanager/ViewMenu.ts +2 -2
- package/desktop/cmp/viewmanager/dialog/ManageDialogModel.ts +16 -7
- package/desktop/cmp/viewmanager/dialog/ViewPanel.ts +5 -3
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -25,68 +25,81 @@ export interface ViewUserState {
|
|
|
25
25
|
}
|
|
26
26
|
export interface ViewManagerConfig {
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Required discriminator for the particular class of views to be loaded and managed by this
|
|
29
|
+
* model. Used to set the `type` property on all JSONBlobs persisted by this model.
|
|
30
|
+
*
|
|
31
|
+
* Choose something descriptive and specific enough to be identifiable and allow for different
|
|
32
|
+
* ViewManagers to be added to your app in the future - e.g. `portfolioGridView` or
|
|
33
|
+
* `tradeBlotterDashboard`.
|
|
34
|
+
*/
|
|
35
|
+
type: string;
|
|
36
|
+
/**
|
|
37
|
+
* Optional user-facing qualifier (default "default") for the special in-code default view
|
|
38
|
+
* option, if enabled. Will be prepended to `typeDisplayName`.
|
|
39
|
+
*
|
|
40
|
+
* A use case is to support a ViewManager persisted Dashboard, where the in-code default is an
|
|
41
|
+
* empty layout, this config is set to "New", and the `typeDisplayName` is set to "Dashboard".
|
|
42
|
+
* This results in a "New Dashboard" option in the menu, allowing users to quickly access a
|
|
43
|
+
* blank dashboard to start building from scratch, while forcing a save-as to persist.
|
|
29
44
|
*/
|
|
45
|
+
defaultDisplayName?: string;
|
|
46
|
+
/** True (default) to allow users to opt-in to auto-saving changes to their current view. */
|
|
30
47
|
enableAutoSave?: boolean;
|
|
31
48
|
/**
|
|
32
|
-
* True (default) to allow the user to select a
|
|
33
|
-
* objects to their in-code defaults. If not enabled, at least one
|
|
34
|
-
*
|
|
49
|
+
* True (default) to allow the user to select a special view from the menu that restores all
|
|
50
|
+
* persisted objects to their in-code defaults. If not enabled, at least one globally shared
|
|
51
|
+
* view should be added to provide an initial selection for users without any private views.
|
|
35
52
|
*/
|
|
36
53
|
enableDefault?: boolean;
|
|
37
54
|
/**
|
|
38
55
|
* True (default) to enable "global" views - i.e. views that are not owned by a user and are
|
|
39
|
-
* available to all.
|
|
56
|
+
* available to all. At least some users should have `manageGlobal` set to true to allow
|
|
57
|
+
* creation and management of these views.
|
|
40
58
|
*/
|
|
41
59
|
enableGlobal?: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* True (default) to allow users to share their views with other users.
|
|
44
|
-
*/
|
|
60
|
+
/** True (default) to allow users to share their views with other users. */
|
|
45
61
|
enableSharing?: boolean;
|
|
46
62
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
63
|
+
* User-facing qualifier for labelling globally shared views - default "global". A use case
|
|
64
|
+
* would be to set to the name of the company/team that manages these canonical views, e.g.
|
|
65
|
+
* "Acme Corp".
|
|
49
66
|
*/
|
|
50
|
-
|
|
67
|
+
globalDisplayName?: string;
|
|
51
68
|
/**
|
|
52
|
-
* Function to determine the initial view for a user, when no view
|
|
53
|
-
*
|
|
54
|
-
* enableDefault is set false should typically return some view, if any views are
|
|
55
|
-
* available. If no view is returned, the control will be forced to fall back on the default.
|
|
69
|
+
* Function to determine the initial view for a user, when they have no prior view already
|
|
70
|
+
* persisted. Called with a list of views available to the current user.
|
|
56
71
|
*
|
|
57
|
-
* Must be set when enableDefault
|
|
72
|
+
* Must be set when `enableDefault: false`. Developers should take care to return *some* view
|
|
73
|
+
* in this case, if any are available. If no view is returned, the control will be forced to
|
|
74
|
+
* fall back to the in-code default.
|
|
58
75
|
*/
|
|
59
76
|
initialViewSpec?: (views: ViewInfo[]) => ViewInfo;
|
|
60
77
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
78
|
+
* Optional discriminator for the particular area of an app in which this instance of the
|
|
79
|
+
* ViewManager appears, for apps that have multiple manager instances that load the same `type`
|
|
80
|
+
* of views. A particular `currentView` and `pendingValue` will be maintained for each instance,
|
|
81
|
+
* but all other options and the available library of views will be shared across the `type`.
|
|
63
82
|
*/
|
|
64
|
-
|
|
83
|
+
instance?: string;
|
|
65
84
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* different viewManagers to be added to your app in the future - e.g. `portfolioGridView` or
|
|
69
|
-
* `tradeBlotterDashboard`.
|
|
85
|
+
* True to allow the user to creat and manage Global views. Apps are expected to commonly set
|
|
86
|
+
* this based on user roles - e.g. `XH.getUser().hasRole('MANAGE_GRID_VIEWS')`.
|
|
70
87
|
*/
|
|
71
|
-
|
|
88
|
+
manageGlobal?: Thunkable<boolean>;
|
|
72
89
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* instance, but all other options, and the available library of views will be shared by type.
|
|
90
|
+
* True (default) to save pending state to SessionStorage so that it can be restored across
|
|
91
|
+
* browser refreshes. Unlike auto-save, this does not write to the database.
|
|
76
92
|
*/
|
|
77
|
-
|
|
93
|
+
preserveUnsavedChanges?: boolean;
|
|
78
94
|
/**
|
|
79
|
-
*
|
|
80
|
-
* and associated management dialogs and prompts.
|
|
95
|
+
* User-facing display name for the type of views being managed - e.g. "report" or "dashboard".
|
|
96
|
+
* Displayed in the `ViewManager` menu and associated management dialogs and prompts.
|
|
97
|
+
* Defaulted from `type` if not provided.
|
|
81
98
|
*/
|
|
82
99
|
typeDisplayName?: string;
|
|
83
100
|
/**
|
|
84
|
-
* Optional
|
|
85
|
-
|
|
86
|
-
globalDisplayName?: string;
|
|
87
|
-
/**
|
|
88
|
-
* Optional key to pass a method that returns a customized BlueprintJS `menuItem` for listing
|
|
89
|
-
* views in the ViewManager menu.
|
|
101
|
+
* Optional render function to customize the BlueprintJS `menuItem` shown for each view in the
|
|
102
|
+
* ViewManager menu.
|
|
90
103
|
*/
|
|
91
104
|
viewMenuItemFn?: (view: ViewInfo, model: ViewManagerModel) => ReactNode;
|
|
92
105
|
}
|
|
@@ -124,6 +137,7 @@ export declare class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
124
137
|
readonly type: string;
|
|
125
138
|
readonly instance: string;
|
|
126
139
|
readonly typeDisplayName: string;
|
|
140
|
+
readonly defaultDisplayName: string;
|
|
127
141
|
readonly globalDisplayName: string;
|
|
128
142
|
readonly viewMenuItemFn: (view: ViewInfo, model: ViewManagerModel) => ReactNode;
|
|
129
143
|
readonly enableAutoSave: boolean;
|
|
@@ -52,79 +52,93 @@ export interface ViewUserState {
|
|
|
52
52
|
|
|
53
53
|
export interface ViewManagerConfig {
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
* Required discriminator for the particular class of views to be loaded and managed by this
|
|
56
|
+
* model. Used to set the `type` property on all JSONBlobs persisted by this model.
|
|
57
|
+
*
|
|
58
|
+
* Choose something descriptive and specific enough to be identifiable and allow for different
|
|
59
|
+
* ViewManagers to be added to your app in the future - e.g. `portfolioGridView` or
|
|
60
|
+
* `tradeBlotterDashboard`.
|
|
61
|
+
*/
|
|
62
|
+
type: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Optional user-facing qualifier (default "default") for the special in-code default view
|
|
66
|
+
* option, if enabled. Will be prepended to `typeDisplayName`.
|
|
67
|
+
*
|
|
68
|
+
* A use case is to support a ViewManager persisted Dashboard, where the in-code default is an
|
|
69
|
+
* empty layout, this config is set to "New", and the `typeDisplayName` is set to "Dashboard".
|
|
70
|
+
* This results in a "New Dashboard" option in the menu, allowing users to quickly access a
|
|
71
|
+
* blank dashboard to start building from scratch, while forcing a save-as to persist.
|
|
56
72
|
*/
|
|
73
|
+
defaultDisplayName?: string;
|
|
74
|
+
|
|
75
|
+
/** True (default) to allow users to opt-in to auto-saving changes to their current view. */
|
|
57
76
|
enableAutoSave?: boolean;
|
|
58
77
|
|
|
59
78
|
/**
|
|
60
|
-
* True (default) to allow the user to select a
|
|
61
|
-
* objects to their in-code defaults. If not enabled, at least one
|
|
62
|
-
*
|
|
79
|
+
* True (default) to allow the user to select a special view from the menu that restores all
|
|
80
|
+
* persisted objects to their in-code defaults. If not enabled, at least one globally shared
|
|
81
|
+
* view should be added to provide an initial selection for users without any private views.
|
|
63
82
|
*/
|
|
64
83
|
enableDefault?: boolean;
|
|
65
84
|
|
|
66
85
|
/**
|
|
67
86
|
* True (default) to enable "global" views - i.e. views that are not owned by a user and are
|
|
68
|
-
* available to all.
|
|
87
|
+
* available to all. At least some users should have `manageGlobal` set to true to allow
|
|
88
|
+
* creation and management of these views.
|
|
69
89
|
*/
|
|
70
90
|
enableGlobal?: boolean;
|
|
71
91
|
|
|
72
|
-
/**
|
|
73
|
-
* True (default) to allow users to share their views with other users.
|
|
74
|
-
*/
|
|
92
|
+
/** True (default) to allow users to share their views with other users. */
|
|
75
93
|
enableSharing?: boolean;
|
|
76
94
|
|
|
77
95
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
96
|
+
* User-facing qualifier for labelling globally shared views - default "global". A use case
|
|
97
|
+
* would be to set to the name of the company/team that manages these canonical views, e.g.
|
|
98
|
+
* "Acme Corp".
|
|
80
99
|
*/
|
|
81
|
-
|
|
100
|
+
globalDisplayName?: string;
|
|
82
101
|
|
|
83
102
|
/**
|
|
84
|
-
* Function to determine the initial view for a user, when no view
|
|
85
|
-
*
|
|
86
|
-
* enableDefault is set false should typically return some view, if any views are
|
|
87
|
-
* available. If no view is returned, the control will be forced to fall back on the default.
|
|
103
|
+
* Function to determine the initial view for a user, when they have no prior view already
|
|
104
|
+
* persisted. Called with a list of views available to the current user.
|
|
88
105
|
*
|
|
89
|
-
* Must be set when enableDefault
|
|
106
|
+
* Must be set when `enableDefault: false`. Developers should take care to return *some* view
|
|
107
|
+
* in this case, if any are available. If no view is returned, the control will be forced to
|
|
108
|
+
* fall back to the in-code default.
|
|
90
109
|
*/
|
|
91
110
|
initialViewSpec?: (views: ViewInfo[]) => ViewInfo;
|
|
92
111
|
|
|
93
112
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
113
|
+
* Optional discriminator for the particular area of an app in which this instance of the
|
|
114
|
+
* ViewManager appears, for apps that have multiple manager instances that load the same `type`
|
|
115
|
+
* of views. A particular `currentView` and `pendingValue` will be maintained for each instance,
|
|
116
|
+
* but all other options and the available library of views will be shared across the `type`.
|
|
96
117
|
*/
|
|
97
|
-
|
|
118
|
+
instance?: string;
|
|
98
119
|
|
|
99
120
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* different viewManagers to be added to your app in the future - e.g. `portfolioGridView` or
|
|
103
|
-
* `tradeBlotterDashboard`.
|
|
121
|
+
* True to allow the user to creat and manage Global views. Apps are expected to commonly set
|
|
122
|
+
* this based on user roles - e.g. `XH.getUser().hasRole('MANAGE_GRID_VIEWS')`.
|
|
104
123
|
*/
|
|
105
|
-
|
|
124
|
+
manageGlobal?: Thunkable<boolean>;
|
|
106
125
|
|
|
107
126
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* instance, but all other options, and the available library of views will be shared by type.
|
|
127
|
+
* True (default) to save pending state to SessionStorage so that it can be restored across
|
|
128
|
+
* browser refreshes. Unlike auto-save, this does not write to the database.
|
|
111
129
|
*/
|
|
112
|
-
|
|
130
|
+
preserveUnsavedChanges?: boolean;
|
|
113
131
|
|
|
114
132
|
/**
|
|
115
|
-
*
|
|
116
|
-
* and associated management dialogs and prompts.
|
|
133
|
+
* User-facing display name for the type of views being managed - e.g. "report" or "dashboard".
|
|
134
|
+
* Displayed in the `ViewManager` menu and associated management dialogs and prompts.
|
|
135
|
+
* Defaulted from `type` if not provided.
|
|
117
136
|
*/
|
|
118
137
|
typeDisplayName?: string;
|
|
119
138
|
|
|
120
139
|
/**
|
|
121
|
-
* Optional
|
|
122
|
-
|
|
123
|
-
globalDisplayName?: string;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Optional key to pass a method that returns a customized BlueprintJS `menuItem` for listing
|
|
127
|
-
* views in the ViewManager menu.
|
|
140
|
+
* Optional render function to customize the BlueprintJS `menuItem` shown for each view in the
|
|
141
|
+
* ViewManager menu.
|
|
128
142
|
*/
|
|
129
143
|
viewMenuItemFn?: (view: ViewInfo, model: ViewManagerModel) => ReactNode;
|
|
130
144
|
}
|
|
@@ -168,6 +182,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
168
182
|
readonly type: string;
|
|
169
183
|
readonly instance: string;
|
|
170
184
|
readonly typeDisplayName: string;
|
|
185
|
+
readonly defaultDisplayName: string;
|
|
171
186
|
readonly globalDisplayName: string;
|
|
172
187
|
readonly viewMenuItemFn: (view: ViewInfo, model: ViewManagerModel) => ReactNode;
|
|
173
188
|
readonly enableAutoSave: boolean;
|
|
@@ -240,11 +255,12 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
240
255
|
}
|
|
241
256
|
|
|
242
257
|
get autoSaveUnavailableReason(): string {
|
|
243
|
-
const {view, isViewAutoSavable, typeDisplayName, globalDisplayName} =
|
|
258
|
+
const {view, isViewAutoSavable, typeDisplayName, globalDisplayName, defaultDisplayName} =
|
|
259
|
+
this;
|
|
244
260
|
if (isViewAutoSavable) return null;
|
|
245
261
|
if (view.isGlobal) return `Cannot auto-save ${globalDisplayName} ${typeDisplayName}.`;
|
|
246
262
|
if (view.isShared) return `Cannot auto-save shared ${typeDisplayName}.`;
|
|
247
|
-
if (view.isDefault) return `Cannot auto-save
|
|
263
|
+
if (view.isDefault) return `Cannot auto-save ${defaultDisplayName} ${typeDisplayName}.`;
|
|
248
264
|
if (XH.identityService.isImpersonating) return `Auto-save disabled during impersonation.`;
|
|
249
265
|
return null;
|
|
250
266
|
}
|
|
@@ -282,6 +298,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
282
298
|
type,
|
|
283
299
|
instance = 'default',
|
|
284
300
|
typeDisplayName,
|
|
301
|
+
defaultDisplayName = 'default',
|
|
285
302
|
globalDisplayName = 'global',
|
|
286
303
|
viewMenuItemFn,
|
|
287
304
|
manageGlobal = false,
|
|
@@ -303,6 +320,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
303
320
|
this.type = type;
|
|
304
321
|
this.instance = instance;
|
|
305
322
|
this.typeDisplayName = lowerCase(typeDisplayName ?? genDisplayName(type));
|
|
323
|
+
this.defaultDisplayName = defaultDisplayName;
|
|
306
324
|
this.globalDisplayName = globalDisplayName;
|
|
307
325
|
this.viewMenuItemFn = viewMenuItemFn;
|
|
308
326
|
this.manageGlobal = executeIfFunction(manageGlobal) ?? false;
|
|
@@ -130,10 +130,12 @@ export const [ViewManager, viewManager] = hoistCmp.withFactory<ViewManagerProps>
|
|
|
130
130
|
|
|
131
131
|
const menuButton = hoistCmp.factory<ViewManagerLocalModel>({
|
|
132
132
|
render({model, icon, ...rest}) {
|
|
133
|
-
const {view, typeDisplayName, isLoading} = model.parent;
|
|
133
|
+
const {view, defaultDisplayName, typeDisplayName, isLoading} = model.parent;
|
|
134
134
|
return button({
|
|
135
135
|
className: 'xh-view-manager__menu-button',
|
|
136
|
-
text: view.isDefault
|
|
136
|
+
text: view.isDefault
|
|
137
|
+
? `${startCase(defaultDisplayName)} ${startCase(typeDisplayName)}`
|
|
138
|
+
: view.name,
|
|
137
139
|
icon: !isLoading
|
|
138
140
|
? icon
|
|
139
141
|
: box({
|
|
@@ -36,7 +36,7 @@ export const viewMenu = hoistCmp.factory<ViewManagerLocalModel>({
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
function getNavMenuItems(model: ViewManagerModel): ReactNode[] {
|
|
39
|
-
const {enableDefault, view, typeDisplayName, globalDisplayName} = model,
|
|
39
|
+
const {enableDefault, view, defaultDisplayName, typeDisplayName, globalDisplayName} = model,
|
|
40
40
|
ownedViews = groupBy(filter(model.ownedViews, 'isPinned'), 'group'),
|
|
41
41
|
globalViews = groupBy(filter(model.globalViews, 'isPinned'), 'group'),
|
|
42
42
|
sharedViews = groupBy(filter(model.sharedViews, 'isPinned'), 'owner'),
|
|
@@ -69,7 +69,7 @@ function getNavMenuItems(model: ViewManagerModel): ReactNode[] {
|
|
|
69
69
|
menuItem({
|
|
70
70
|
className: 'xh-view-manager__menu-item',
|
|
71
71
|
icon: view.isDefault ? Icon.check() : Icon.placeholder(),
|
|
72
|
-
text:
|
|
72
|
+
text: `${startCase(defaultDisplayName)} ${startCase(typeDisplayName)}`,
|
|
73
73
|
onClick: () => model.selectViewAsync(null).catchDefault()
|
|
74
74
|
})
|
|
75
75
|
);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import {badge} from '@xh/hoist/cmp/badge';
|
|
9
9
|
import {dateTimeCol, GridAutosizeMode, GridModel} from '@xh/hoist/cmp/grid';
|
|
10
|
-
import {fragment, hbox, p, strong} from '@xh/hoist/cmp/layout';
|
|
10
|
+
import {br, fragment, hbox, p, strong} from '@xh/hoist/cmp/layout';
|
|
11
11
|
import {TabContainerModel} from '@xh/hoist/cmp/tab';
|
|
12
12
|
import {ViewInfo, ViewManagerModel, ViewUpdateSpec} from '@xh/hoist/cmp/viewmanager';
|
|
13
13
|
import {HoistModel, LoadSpec, managed, TaskObserver, XH} from '@xh/hoist/core';
|
|
@@ -338,10 +338,15 @@ export class ManageDialogModel extends HoistModel {
|
|
|
338
338
|
model: this.ownedGridModel,
|
|
339
339
|
helpText: fragment(
|
|
340
340
|
Icon.user(),
|
|
341
|
-
`This tab shows ${views} you have created
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
341
|
+
`This tab shows ${views} you have created.`,
|
|
342
|
+
br(),
|
|
343
|
+
`Pin ${views} to your menu for quick access. Use groups to nest them under sub-menus.`,
|
|
344
|
+
...(enableSharing
|
|
345
|
+
? [
|
|
346
|
+
br(),
|
|
347
|
+
`Opt-in to sharing any of your ${views} to make them discoverable by other users.`
|
|
348
|
+
]
|
|
349
|
+
: [''])
|
|
345
350
|
)
|
|
346
351
|
})
|
|
347
352
|
}
|
|
@@ -355,7 +360,9 @@ export class ManageDialogModel extends HoistModel {
|
|
|
355
360
|
model: this.globalGridModel,
|
|
356
361
|
helpText: fragment(
|
|
357
362
|
Icon.globe(),
|
|
358
|
-
`This tab shows ${globalViews} available to everyone
|
|
363
|
+
`This tab shows ${globalViews} available to everyone.`,
|
|
364
|
+
br(),
|
|
365
|
+
`${capitalize(globalViews)} can be set to appear automatically in everyone's menu, but you can choose which ${views} you would like to see by pinning/unpinning them at any time.`
|
|
359
366
|
)
|
|
360
367
|
})
|
|
361
368
|
});
|
|
@@ -369,7 +376,9 @@ export class ManageDialogModel extends HoistModel {
|
|
|
369
376
|
model: this.sharedGridModel,
|
|
370
377
|
helpText: fragment(
|
|
371
378
|
Icon.users(),
|
|
372
|
-
`This tab shows ${views} shared by other ${XH.appName} users
|
|
379
|
+
`This tab shows ${views} shared by other ${XH.appName} users.`,
|
|
380
|
+
br(),
|
|
381
|
+
`You can pin these ${views} to your menu for quick access. Only the owner will be able to save changes to a shared ${view}, but you can save a copy to make it your own.`
|
|
373
382
|
)
|
|
374
383
|
})
|
|
375
384
|
});
|
|
@@ -79,10 +79,12 @@ export const viewPanel = hoistCmp.factory({
|
|
|
79
79
|
}),
|
|
80
80
|
formField({
|
|
81
81
|
field: 'isDefaultPinned',
|
|
82
|
-
label:
|
|
83
|
-
labelWidth: 110,
|
|
82
|
+
label: null,
|
|
84
83
|
inline: true,
|
|
85
|
-
item: switchInput(
|
|
84
|
+
item: switchInput({
|
|
85
|
+
label: `Pin to everyone's menu by default`,
|
|
86
|
+
labelSide: 'left'
|
|
87
|
+
}),
|
|
86
88
|
omit: !isGlobal || !isEditable
|
|
87
89
|
}),
|
|
88
90
|
vspacer(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "75.0.0-SNAPSHOT.
|
|
3
|
+
"version": "75.0.0-SNAPSHOT.1753490062755",
|
|
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",
|