@xh/hoist 79.0.0-SNAPSHOT.1766020485210 → 79.0.0-SNAPSHOT.1766097863558

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 (60) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/admin/AppComponent.ts +9 -1
  3. package/admin/AppModel.ts +0 -4
  4. package/admin/tabs/cluster/instances/InstancesTab.ts +1 -1
  5. package/admin/tabs/cluster/instances/InstancesTabModel.ts +0 -1
  6. package/admin/tabs/userData/roles/details/RoleDetailsModel.ts +0 -1
  7. package/build/types/cmp/tab/TabContainer.d.ts +19 -4
  8. package/build/types/cmp/tab/TabContainerModel.d.ts +18 -19
  9. package/build/types/cmp/tab/Types.d.ts +61 -0
  10. package/build/types/cmp/tab/index.d.ts +1 -1
  11. package/build/types/core/elem.d.ts +3 -3
  12. package/build/types/data/RecordAction.d.ts +4 -1
  13. package/build/types/desktop/cmp/dash/canvas/DashCanvas.d.ts +3 -2
  14. package/build/types/desktop/cmp/dash/canvas/DashCanvasModel.d.ts +45 -3
  15. package/build/types/desktop/cmp/panel/Panel.d.ts +2 -2
  16. package/build/types/desktop/cmp/rest/RestGrid.d.ts +3 -3
  17. package/build/types/desktop/cmp/tab/TabSwitcher.d.ts +1 -1
  18. package/build/types/desktop/cmp/tab/dynamic/DynamicTabSwitcher.d.ts +7 -0
  19. package/build/types/desktop/cmp/tab/dynamic/DynamicTabSwitcherModel.d.ts +30 -0
  20. package/build/types/desktop/cmp/tab/dynamic/scroller/Scroller.d.ts +19 -0
  21. package/build/types/desktop/cmp/tab/dynamic/scroller/ScrollerModel.d.ts +23 -0
  22. package/build/types/desktop/cmp/tab/impl/Tab.d.ts +7 -2
  23. package/build/types/desktop/cmp/tab/impl/TabContainer.d.ts +1 -1
  24. package/build/types/desktop/cmp/tab/impl/TabContextMenuItems.d.ts +4 -0
  25. package/build/types/desktop/cmp/tab/index.d.ts +1 -0
  26. package/build/types/dynamics/desktop.d.ts +1 -0
  27. package/build/types/mobile/cmp/panel/Panel.d.ts +2 -2
  28. package/build/types/mobile/cmp/tab/impl/TabContainer.d.ts +1 -1
  29. package/cmp/tab/TabContainer.ts +19 -4
  30. package/cmp/tab/TabContainerModel.ts +113 -54
  31. package/cmp/tab/TabModel.ts +1 -2
  32. package/cmp/tab/Types.ts +80 -0
  33. package/cmp/tab/index.ts +1 -1
  34. package/core/elem.ts +5 -5
  35. package/data/RecordAction.ts +4 -1
  36. package/desktop/appcontainer/AppContainer.ts +3 -2
  37. package/desktop/cmp/dash/canvas/DashCanvas.ts +57 -35
  38. package/desktop/cmp/dash/canvas/DashCanvasModel.ts +135 -21
  39. package/desktop/cmp/grid/impl/filter/headerfilter/HeaderFilter.ts +1 -1
  40. package/desktop/cmp/grid/impl/filter/headerfilter/HeaderFilterModel.ts +0 -1
  41. package/desktop/cmp/panel/Panel.ts +2 -2
  42. package/desktop/cmp/rest/RestGrid.ts +4 -5
  43. package/desktop/cmp/tab/TabSwitcher.ts +18 -3
  44. package/desktop/cmp/tab/Tabs.scss +1 -0
  45. package/desktop/cmp/tab/dynamic/DynamicTabSwitcher.scss +53 -0
  46. package/desktop/cmp/tab/dynamic/DynamicTabSwitcher.ts +237 -0
  47. package/desktop/cmp/tab/dynamic/DynamicTabSwitcherModel.ts +167 -0
  48. package/desktop/cmp/tab/dynamic/scroller/Scroller.ts +69 -0
  49. package/desktop/cmp/tab/dynamic/scroller/ScrollerModel.ts +92 -0
  50. package/desktop/cmp/tab/impl/Tab.ts +30 -6
  51. package/desktop/cmp/tab/impl/TabContainer.ts +34 -9
  52. package/desktop/cmp/tab/impl/TabContextMenuItems.ts +21 -0
  53. package/desktop/cmp/tab/index.ts +1 -0
  54. package/dynamics/desktop.ts +2 -0
  55. package/mobile/cmp/panel/Panel.ts +2 -2
  56. package/mobile/cmp/tab/impl/TabContainer.ts +16 -9
  57. package/package.json +2 -3
  58. package/tsconfig.tsbuildinfo +1 -1
  59. package/build/types/cmp/tab/TabSwitcherProps.d.ts +0 -16
  60. package/cmp/tab/TabSwitcherProps.ts +0 -28
package/CHANGELOG.md CHANGED
@@ -5,12 +5,24 @@
5
5
  ### 🎁 New Features
6
6
 
7
7
  * Enhance `LocalDate` with `addWeekdays` and `subtractWeekdays` methods.
8
+ * Added new `DynamicTabSwitcher` component, a more user-customizable version of `TabSwitcher` that
9
+ allows for dynamic addition, removal, and drag-and-drop reordering of tabs with the ability to
10
+ persist "favorited" tab state across sessions. Additionally, existing static `TabSwitcher` now
11
+ supports context-menu items. See `TabContainerConfig.switcher`.
8
12
 
9
13
  ### 💥 Breaking Changes
10
14
 
11
15
  * Renamed `GridModel.applyColumnStateChanges()` to `updateColumnState()` for clarity and better
12
16
  symmetry with `setColumnState()`. The prior method remains as an alias but is now deprecated and
13
17
  scheduled for removal in v82.
18
+ * `TabSwitcherProps` has moved to `cmp/tab/Types.ts` but is still exported from `cmp/tab/index.ts`.
19
+ Some apps may need to update their imports.
20
+ * `TabContainerConfig.switcher` has been repurposed to accept a `TabSwitcherConfig`. To pass
21
+ `TabSwitcherProps` via a parent `TabContainer`, use `TabContainerProps.switcher`.
22
+
23
+ ### 🎁 New Features
24
+
25
+ * DashCanvas component now supports dragging and dropping widgets in from an external container.
14
26
 
15
27
  ### 🐞 Bug Fixes
16
28
 
@@ -26,6 +38,10 @@
26
38
  * `GroupingChooserProps.popoverTitle` - use `editorTitle`
27
39
  * `RelativeTimestampProps.options` - provide directly as top-level props
28
40
 
41
+ ### 📚 Libraries
42
+
43
+ * react-grid-layout `1.5.0 → 2.1.0`
44
+
29
45
  ## 78.1.4 - 2025-12-05
30
46
 
31
47
  ### 🐞 Bug Fixes
@@ -22,7 +22,15 @@ export const AppComponent = hoistCmp({
22
22
  return panel({
23
23
  tbar: tbar(),
24
24
  className: 'xh-admin-app',
25
- item: tabContainer()
25
+ item: tabContainer({
26
+ switcher: false,
27
+ childContainerProps: ({tabId}) => ({
28
+ switcher: {
29
+ orientation: 'left',
30
+ testId: `${tabId}-tab-switcher`
31
+ }
32
+ })
33
+ })
26
34
  });
27
35
  }
28
36
  });
package/admin/AppModel.ts CHANGED
@@ -37,7 +37,6 @@ export class AppModel extends HoistAppModel {
37
37
 
38
38
  this.tabModel = new TabContainerModel({
39
39
  route: 'default',
40
- switcher: false,
41
40
  tabs: this.createTabs()
42
41
  });
43
42
 
@@ -130,7 +129,6 @@ export class AppModel extends HoistAppModel {
130
129
  id: 'general',
131
130
  icon: Icon.info(),
132
131
  content: {
133
- switcher: {orientation: 'left', testId: 'general-tab-switcher'},
134
132
  tabs: [
135
133
  {id: 'about', icon: Icon.info(), content: aboutPanel},
136
134
  {id: 'config', icon: Icon.settings(), content: configPanel},
@@ -142,7 +140,6 @@ export class AppModel extends HoistAppModel {
142
140
  id: 'servers',
143
141
  icon: Icon.server(),
144
142
  content: {
145
- switcher: {orientation: 'left', testId: 'cluster-tab-switcher'},
146
143
  tabs: [
147
144
  {id: 'instances', icon: Icon.server(), content: instancesTab},
148
145
  {id: 'objects', icon: Icon.boxFull(), content: clusterObjectsPanel}
@@ -163,7 +160,6 @@ export class AppModel extends HoistAppModel {
163
160
  id: 'userData',
164
161
  icon: Icon.users(),
165
162
  content: {
166
- switcher: {orientation: 'left', testId: 'user-data-tab-switcher'},
167
163
  refreshMode: 'onShowAlways',
168
164
  tabs: [
169
165
  {
@@ -53,7 +53,7 @@ export const detailPanel = hoistCmp.factory<InstancesTabModel>({
53
53
  tabSwitcher()
54
54
  ],
55
55
  flex: 1,
56
- item: tabContainer()
56
+ item: tabContainer({switcher: false})
57
57
  });
58
58
  }
59
59
  });
@@ -193,7 +193,6 @@ export class InstancesTabModel extends HoistModel {
193
193
  private createTabContainerModel() {
194
194
  return new TabContainerModel({
195
195
  route: 'default.servers.instances',
196
- switcher: false,
197
196
  tabs: [
198
197
  {id: 'logs', icon: Icon.fileText(), content: logViewer},
199
198
  {id: 'memory', icon: Icon.memory(), content: memoryMonitorPanel},
@@ -69,7 +69,6 @@ export class RoleDetailsModel extends HoistModel {
69
69
 
70
70
  private createTabContainerModel(): TabContainerModel {
71
71
  return new TabContainerModel({
72
- switcher: true,
73
72
  tabs: [
74
73
  {
75
74
  id: 'users',
@@ -1,12 +1,27 @@
1
+ import { TabSwitcherProps } from '@xh/hoist/cmp/tab/Types';
1
2
  import { BoxProps, HoistProps } from '@xh/hoist/core';
2
3
  import { TabContainerModel } from './TabContainerModel';
3
- export type TabContainerProps = HoistProps<TabContainerModel> & BoxProps;
4
+ export interface TabContainerProps extends HoistProps<TabContainerModel>, BoxProps {
5
+ /**
6
+ * Indicates whether to include a default switcher docked within this component. Specify as a
7
+ * boolean or props for a TabSwitcher component. False to not include a switcher. Default true.
8
+ */
9
+ switcher?: boolean | TabSwitcherProps;
10
+ /**
11
+ * Props to apply to child TabContainers, if any. Specify as an object or a function
12
+ * that returns props based on the tabId and depth of the child container.
13
+ */
14
+ childContainerProps?: TabContainerProps | ((ctx: {
15
+ tabId: string;
16
+ depth: number;
17
+ }) => TabContainerProps);
18
+ }
4
19
  /**
5
20
  * Display a set of child Tabs and (optionally) a switcher control.
6
21
  *
7
- * By default this TabContainer will install a TabSwitcher above the Tabs to control the currently
8
- * displayed Tab. The 'TabContainerModel.switcher' property can be adjusted to place the switcher
9
- * control on alternative edges of the container.
22
+ * By default, this TabContainer will install a TabSwitcher above the Tabs to control the currently
23
+ * displayed Tab. The 'switcher' prop can be adjusted to place the switcher control on alternative
24
+ * edges of the container.
10
25
  *
11
26
  * If `switcher` is set to false then no TabSwitcher will be installed. This setting
12
27
  * is useful for applications that wish to place an associated TabSwitcher elsewhere in the
@@ -1,7 +1,7 @@
1
- import { HoistModel, Persistable, PersistableState, PersistOptions, RefreshContextModel, RefreshMode, RenderMode } from '@xh/hoist/core';
1
+ import { TabSwitcherConfig, IDynamicTabSwitcherModel } from '@xh/hoist/cmp/tab/Types';
2
+ import { HoistModel, PersistOptions, RefreshContextModel, RefreshMode, RenderMode } from '@xh/hoist/core';
2
3
  import { ReactNode } from 'react';
3
4
  import { TabConfig, TabModel } from './TabModel';
4
- import { TabSwitcherProps } from './TabSwitcherProps';
5
5
  export interface TabContainerConfig {
6
6
  /** Tabs to be displayed. */
7
7
  tabs: TabConfig[];
@@ -16,11 +16,10 @@ export interface TabContainerConfig {
16
16
  */
17
17
  route?: string;
18
18
  /**
19
- * Indicates whether to include a default switcher docked within this component. Specify as a
20
- * boolean or an object containing props for a TabSwitcher component. Set to false to not
21
- * include a switcher. Defaults to true.
19
+ * Specification for type of switcher. Specify `dynamic` or config for user-configurable tabs.
20
+ * Default `{mode: 'static'}` for simple, static switcher.
22
21
  */
23
- switcher?: boolean | TabSwitcherProps;
22
+ switcher?: TabSwitcherConfig;
24
23
  /**
25
24
  * True to enable activity tracking of tab views (default false). Viewing of each tab will
26
25
  * be tracked with the `oncePerSession` flag, to avoid duplication.
@@ -54,22 +53,26 @@ export interface TabContainerConfig {
54
53
  *
55
54
  * Note: Routing is currently enabled for desktop applications only.
56
55
  */
57
- export declare class TabContainerModel extends HoistModel implements Persistable<{
58
- activeTabId: string;
59
- }> {
56
+ export declare class TabContainerModel extends HoistModel {
60
57
  config: TabContainerConfig;
61
58
  tabs: TabModel[];
62
59
  activeTabId: string;
60
+ depth: number;
63
61
  route: string;
64
62
  defaultTabId: string;
65
- switcher: TabSwitcherProps;
66
63
  track: boolean;
67
64
  renderMode: RenderMode;
68
65
  refreshMode: RefreshMode;
69
66
  emptyText: ReactNode;
67
+ switcherConfig: TabSwitcherConfig;
70
68
  refreshContextModel: RefreshContextModel;
69
+ dynamicTabSwitcherModel: IDynamicTabSwitcherModel;
71
70
  protected lastActiveTabId: string;
72
- constructor({ tabs, defaultTabId, route, switcher, track, renderMode, refreshMode, persistWith, emptyText, xhImpl }: TabContainerConfig);
71
+ /**
72
+ * @param config - TabContainer configuration.
73
+ * @param [depth] - Depth in hierarchy of nested TabContainerModels. Not for application use.
74
+ */
75
+ constructor({ tabs, defaultTabId, route, track, renderMode, refreshMode, persistWith, emptyText, xhImpl, switcher }: TabContainerConfig, depth?: number);
73
76
  /** Set/replace all tabs within the container. */
74
77
  setTabs(tabs: Array<TabModel | TabConfig>): void;
75
78
  /** Add a single tab to the container. */
@@ -88,9 +91,9 @@ export declare class TabContainerModel extends HoistModel implements Persistable
88
91
  /** Find a tab that is an immediate child of this container. */
89
92
  findTab(id: string): TabModel;
90
93
  get activeTab(): TabModel;
91
- /** The tab immediately before the active tab in the model's tab list. */
94
+ /** The visitable tab immediately before the active tab in the model's tab list. */
92
95
  get prevTab(): TabModel;
93
- /** The tab immediately after the active tab in the model's tab list. */
96
+ /** The visitable tab immediately after the active tab in the model's tab list. */
94
97
  get nextTab(): TabModel;
95
98
  /**
96
99
  * Set the currently active Tab.
@@ -114,16 +117,12 @@ export declare class TabContainerModel extends HoistModel implements Persistable
114
117
  * @param cycle - true to loop back to first tab if necessary.
115
118
  */
116
119
  activateNextTab(cycle?: boolean): void;
117
- getPersistableState(): PersistableState<{
118
- activeTabId: string;
119
- }>;
120
- setPersistableState(state: PersistableState<{
121
- activeTabId: string;
122
- }>): void;
123
120
  protected setActiveTabIdInternal(id: any): void;
124
121
  protected syncWithRouter(): void;
125
122
  protected forwardRouterToTab(id: any): void;
126
123
  protected calculateActiveTabId(tabs: any): any;
124
+ private parseSwitcher;
125
+ private initPersist;
127
126
  }
128
127
  export interface AddTabOptions {
129
128
  /** Index in tab collection where tab is to be added. */
@@ -0,0 +1,61 @@
1
+ import { TabContainerModel } from '@xh/hoist/cmp/tab/TabContainerModel';
2
+ import { TabModel } from '@xh/hoist/cmp/tab/TabModel';
3
+ import { BoxProps, HoistModel, HoistProps, MenuContext, MenuItemLike, MenuToken, PersistOptions, Side } from '@xh/hoist/core';
4
+ export interface TabSwitcherProps extends HoistProps<TabContainerModel>, BoxProps {
5
+ /** Relative position within the parent TabContainer. Defaults to 'top'. */
6
+ orientation?: Side;
7
+ /**
8
+ * True to animate the indicator when switching tabs. False (default) to change instantly.
9
+ * Not supported by DynamicTabSwitcher.
10
+ */
11
+ animate?: boolean;
12
+ /**
13
+ * Enable scrolling and place tabs that overflow into a menu. Default to false.
14
+ * Not supported by DynamicTabSwitcher.
15
+ */
16
+ enableOverflow?: boolean;
17
+ /** Width (in px) to render tabs. Only applies to horizontal orientations */
18
+ tabWidth?: number;
19
+ /** Minimum width (in px) to render tabs. Only applies to horizontal orientations */
20
+ tabMinWidth?: number;
21
+ /** Maximum width (in px) to render tabs. Only applies to horizontal orientations */
22
+ tabMaxWidth?: number;
23
+ }
24
+ export interface TabSwitcherConfig {
25
+ /** Specification for type of switcher. Specify `dynamic`for user-configurable tabs */
26
+ mode: 'static' | 'dynamic';
27
+ /** Additional menu items to include in tab context menus. Only supported on desktop */
28
+ extraMenuItems?: Array<MenuItemLike<MenuToken, TabSwitcherMenuContext>>;
29
+ /** IDs of favorite tabs to display by default (in order). Only for `dynamic` switchers */
30
+ initialFavorites?: string[];
31
+ }
32
+ export interface TabContainerModelPersistOptions extends PersistOptions {
33
+ /** True (default) to persist the active tab ID or provide custom PersistOptions. */
34
+ persistActiveTabId?: boolean;
35
+ /** True (default) to persist favorite tab IDs or provide custom PersistOptions. */
36
+ persistFavoriteTabIds?: boolean;
37
+ }
38
+ export interface TabSwitcherMenuContext extends MenuContext {
39
+ tab: TabModel;
40
+ }
41
+ /** Cross-platform interface for desktop and mobile (TBA) DynamicTabSwitcherModels. */
42
+ export interface IDynamicTabSwitcherModel extends HoistModel {
43
+ /** IDs of favorite tabs, in order. */
44
+ get favoriteTabIds(): string[];
45
+ /** Tabs displayed in switcher, in order. */
46
+ get visibleTabs(): TabModel[];
47
+ /** Enabled tabs displayed in switcher, in order. */
48
+ get enabledVisibleTabs(): TabModel[];
49
+ /** Whether the specified tab is currently active in the TabContainer. */
50
+ isTabActive(tabId: string): boolean;
51
+ /** Whether the specified tab is currently marked as a favorite. */
52
+ isTabFavorite(tabId: string): boolean;
53
+ /** Toggle the favorite status of the specified tab. */
54
+ toggleTabFavorite(tabId: string): void;
55
+ /** Activate the specified tab in the TabContainer. */
56
+ activate(tabId: string): void;
57
+ /** Remove the specified tab from the switcher. */
58
+ hide(tabId: string): void;
59
+ /** Set the IDs of all favorite tabs, in order. */
60
+ setFavoriteTabIds(tabIds: string[]): void;
61
+ }
@@ -1,4 +1,4 @@
1
1
  export * from './TabModel';
2
2
  export * from './TabContainer';
3
3
  export * from './TabContainerModel';
4
- export * from './TabSwitcherProps';
4
+ export * from './Types';
@@ -1,6 +1,6 @@
1
1
  import { TEST_ID } from '@xh/hoist/utils/js';
2
2
  import { ComponentType, JSX, Key, ReactElement, ReactNode } from 'react';
3
- import { PlainObject, Some, Thunkable } from './types/Types';
3
+ import { PlainObject, Thunkable } from './types/Types';
4
4
  /**
5
5
  * Alternative format for specifying React Elements in render functions. This type is designed to
6
6
  * provide a well-formatted, declarative, native javascript approach to configuring Elements and
@@ -26,9 +26,9 @@ import { PlainObject, Some, Thunkable } from './types/Types';
26
26
  */
27
27
  export type ElementSpec<P> = Omit<P, 'items' | 'item' | 'omit'> & {
28
28
  /** Child Element(s). Equivalent provided as Rest Arguments to React.createElement.*/
29
- items?: Some<ReactNode>;
29
+ items?: ReactNode;
30
30
  /** Equivalent to `items`, offered for code clarity when only one child is needed. */
31
- item?: Some<ReactNode>;
31
+ item?: ReactNode;
32
32
  /** True to exclude the Element. */
33
33
  omit?: Thunkable<boolean>;
34
34
  /** React key for this component. */
@@ -17,7 +17,10 @@ export interface RecordActionSpec extends TestSupportProps {
17
17
  tooltip?: string;
18
18
  /** Function called on action execution. */
19
19
  actionFn?: (data: ActionFnData) => void;
20
- /** Function called prior to showing this item. */
20
+ /**
21
+ * Function called to append / override display properties prior to each render. This function
22
+ * allows dynamic control over display properties.
23
+ * */
21
24
  displayFn?: (data: ActionFnData) => RecordActionSpec;
22
25
  /** Sub-actions for this action. */
23
26
  items?: RecordActionLike[];
@@ -1,8 +1,9 @@
1
+ import { type GridLayoutProps } from 'react-grid-layout';
1
2
  import { HoistProps, TestSupportProps } from '@xh/hoist/core';
2
3
  import '@xh/hoist/desktop/register';
3
- import type { ReactGridLayoutProps } from 'react-grid-layout';
4
4
  import { DashCanvasModel } from './DashCanvasModel';
5
5
  import 'react-grid-layout/css/styles.css';
6
+ import 'react-resizable/css/styles.css';
6
7
  import './DashCanvas.scss';
7
8
  export interface DashCanvasProps extends HoistProps<DashCanvasModel>, TestSupportProps {
8
9
  /**
@@ -11,7 +12,7 @@ export interface DashCanvasProps extends HoistProps<DashCanvasModel>, TestSuppor
11
12
  * {@link https://www.npmjs.com/package/react-grid-layout#grid-layout-props}
12
13
  * Note that some ReactGridLayout props are managed directly by DashCanvas and will be overridden if provided here.
13
14
  */
14
- rglOptions?: ReactGridLayoutProps;
15
+ rglOptions?: GridLayoutProps;
15
16
  }
16
17
  /**
17
18
  * Dashboard-style container that allows users to drag-and-drop child widgets into flexible layouts.
@@ -1,3 +1,5 @@
1
+ import { DragEvent } from 'react';
2
+ import type { LayoutItem } from 'react-grid-layout';
1
3
  import { Persistable, PersistableState } from '@xh/hoist/core';
2
4
  import { DashCanvasViewModel, DashCanvasViewSpec, DashConfig, DashViewState, DashModel } from '../';
3
5
  import '@xh/hoist/desktop/register';
@@ -18,8 +20,35 @@ export interface DashCanvasConfig extends DashConfig<DashCanvasViewSpec, DashCan
18
20
  margin?: [number, number];
19
21
  /** Maximum number of rows permitted for this container. Default `Infinity`. */
20
22
  maxRows?: number;
21
- /** Padding inside the container [x, y] in pixels. Defaults to same as `margin`. */
23
+ /** Padding inside the container [x, y] in pixels. Default `[0, 0]`. */
22
24
  containerPadding?: [number, number];
25
+ /**
26
+ * Whether the canvas should accept drag-and-drop of views from outside
27
+ * the canvas. Default false.
28
+ */
29
+ droppable?: boolean;
30
+ /**
31
+ * Optional Callback to invoke after a view is successfully dropped onto the canvas.
32
+ */
33
+ onDropDone?: (viewModel: DashCanvasViewModel) => void;
34
+ /**
35
+ * Optional callback to invoke when an item is dragged over the canvas. This may be used to
36
+ * customize how the size of the dropping placeholder is calculated. The callback should
37
+ * return an object with optional properties indicating the desired width, height (in grid units),
38
+ * and offset (in pixels) of the dropping placeholder.
39
+ * If not provided, Hoist's own default logic will be used.
40
+ */
41
+ onDropDragOver?: (e: DragEvent) => {
42
+ w?: number;
43
+ h?: number;
44
+ dragOffsetX?: number;
45
+ dragOffsetY?: number;
46
+ } | false | void;
47
+ /**
48
+ * Whether an overlay with an Add View button should be rendered
49
+ * when the canvas is empty. Default true.
50
+ */
51
+ showAddViewButtonWhenEmpty?: boolean;
23
52
  }
24
53
  export interface DashCanvasItemState {
25
54
  layout: DashCanvasItemLayout;
@@ -45,7 +74,12 @@ export declare class DashCanvasModel extends DashModel<DashCanvasViewSpec, DashC
45
74
  compact: boolean;
46
75
  margin: [number, number];
47
76
  containerPadding: [number, number];
77
+ showAddViewButtonWhenEmpty: boolean;
78
+ DROPPING_ELEM_ID: string;
48
79
  maxRows: number;
80
+ droppable: boolean;
81
+ onDropDone: (viewModel: DashCanvasViewModel) => void;
82
+ draggedInView: DashCanvasItemState;
49
83
  /** Current number of rows in canvas */
50
84
  get rows(): number;
51
85
  get isEmpty(): boolean;
@@ -54,7 +88,7 @@ export declare class DashCanvasModel extends DashModel<DashCanvasViewSpec, DashC
54
88
  isResizing: boolean;
55
89
  private isLoadingState;
56
90
  get rglLayout(): any[];
57
- constructor({ viewSpecs, viewSpecDefaults, initialState, layoutLocked, contentLocked, renameLocked, persistWith, emptyText, addViewButtonText, columns, rowHeight, compact, margin, maxRows, containerPadding, extraMenuItems }: DashCanvasConfig);
91
+ constructor({ viewSpecs, viewSpecDefaults, initialState, layoutLocked, contentLocked, renameLocked, persistWith, emptyText, addViewButtonText, columns, rowHeight, compact, margin, maxRows, containerPadding, extraMenuItems, showAddViewButtonWhenEmpty, droppable, onDropDone, onDropDragOver }: DashCanvasConfig);
58
92
  /** Removes all views from the canvas */
59
93
  clear(): void;
60
94
  /**
@@ -92,6 +126,14 @@ export declare class DashCanvasModel extends DashModel<DashCanvasViewSpec, DashC
92
126
  renameView(id: string): void;
93
127
  /** Scrolls a DashCanvasView into view. */
94
128
  ensureViewVisible(id: string): void;
129
+ onDrop(rglLayout: LayoutItem[], layoutItem: LayoutItem, evt: Event): void;
130
+ setDraggedInView(view?: DashCanvasItemState): void;
131
+ onDropDragOver(evt: DragEvent): {
132
+ w?: number;
133
+ h?: number;
134
+ dragOffsetX?: number;
135
+ dragOffsetY?: number;
136
+ } | false | void;
95
137
  getPersistableState(): PersistableState<{
96
138
  state: DashCanvasItemState[];
97
139
  }>;
@@ -100,7 +142,7 @@ export declare class DashCanvasModel extends DashModel<DashCanvasViewSpec, DashC
100
142
  }>): void;
101
143
  private getLayoutFromPosition;
102
144
  private addViewInternal;
103
- onRglLayoutChange(rglLayout: any): void;
145
+ onRglLayoutChange(rglLayout: LayoutItem[]): void;
104
146
  private setLayout;
105
147
  private loadState;
106
148
  private buildState;
@@ -42,12 +42,12 @@ export interface PanelProps extends HoistProps<PanelModel>, Omit<BoxProps, 'titl
42
42
  * A toolbar to be docked at the top of the panel.
43
43
  * If specified as an array, items will be passed as children to a Toolbar component.
44
44
  */
45
- tbar?: Some<ReactNode>;
45
+ tbar?: ReactNode;
46
46
  /**
47
47
  * A toolbar to be docked at the bottom of the panel.
48
48
  * If specified as an array, items will be passed as children to a Toolbar component.
49
49
  */
50
- bbar?: Some<ReactNode>;
50
+ bbar?: ReactNode;
51
51
  /** Title text added to the panel's header. */
52
52
  title?: ReactNode;
53
53
  /** Title to be used when the panel is collapsed. Defaults to `title`. */
@@ -1,4 +1,4 @@
1
- import { HoistProps, PlainObject, Some } from '@xh/hoist/core';
1
+ import { HoistProps, PlainObject } from '@xh/hoist/core';
2
2
  import { PanelProps } from '@xh/hoist/desktop/cmp/panel';
3
3
  import '@xh/hoist/desktop/register';
4
4
  import { ReactElement, ReactNode } from 'react';
@@ -14,7 +14,7 @@ export interface RestGridProps extends HoistProps<RestGridModel>, Omit<PanelProp
14
14
  * Optional components rendered adjacent to the top toolbar's action buttons.
15
15
  * See also {@link tbar} to take full control of the toolbar.
16
16
  */
17
- extraToolbarItems?: Some<ReactNode> | (() => Some<ReactNode>);
17
+ extraToolbarItems?: ReactNode | (() => ReactNode);
18
18
  /** Classname to be passed to RestForm. */
19
19
  formClassName?: string;
20
20
  /**
@@ -28,6 +28,6 @@ export interface RestGridProps extends HoistProps<RestGridModel>, Omit<PanelProp
28
28
  * configs `toolbarActions`, `filterFields`, and `showRefreshButton`. If specified as an array,
29
29
  * will be passed as children to a Toolbar component.
30
30
  */
31
- tbar?: Some<ReactNode>;
31
+ tbar?: ReactNode;
32
32
  }
33
33
  export declare const RestGrid: import("react").FC<RestGridProps>, restGrid: import("@xh/hoist/core").ElementFactory<RestGridProps>;
@@ -1,4 +1,4 @@
1
- import { TabSwitcherProps } from '@xh/hoist/cmp/tab';
1
+ import { TabSwitcherProps } from '@xh/hoist/cmp/tab/Types';
2
2
  import '@xh/hoist/desktop/register';
3
3
  /**
4
4
  * Component to indicate and control the active tab of a TabContainer.
@@ -0,0 +1,7 @@
1
+ import { TabSwitcherProps } from '@xh/hoist/cmp/tab/Types';
2
+ import './DynamicTabSwitcher.scss';
3
+ /**
4
+ * A tab switcher that displays tabs as draggable items in a horizontal list.
5
+ * Tabs can be added, removed, reordered and favorited with persistence.
6
+ */
7
+ export declare const DynamicTabSwitcher: import("react").FC<TabSwitcherProps>, dynamicTabSwitcher: import("@xh/hoist/core").ElementFactory<TabSwitcherProps>;
@@ -0,0 +1,30 @@
1
+ import { TabContainerModel, TabModel } from '@xh/hoist/cmp/tab';
2
+ import { IDynamicTabSwitcherModel, TabSwitcherConfig, TabSwitcherMenuContext } from '@xh/hoist/cmp/tab/Types';
3
+ import { HoistModel, MenuItemLike, MenuToken } from '@xh/hoist/core';
4
+ import React from 'react';
5
+ /**
6
+ * State management for the DynamicTabSwitcher component.
7
+ * @internal
8
+ */
9
+ export declare class DynamicTabSwitcherModel extends HoistModel implements IDynamicTabSwitcherModel {
10
+ config: TabSwitcherConfig;
11
+ private readonly extraMenuItems;
12
+ private readonly tabContainerModel;
13
+ private visibleTabState;
14
+ get favoriteTabIds(): string[];
15
+ get visibleTabs(): TabModel[];
16
+ get enabledVisibleTabs(): TabModel[];
17
+ constructor({ extraMenuItems, initialFavorites }: TabSwitcherConfig, tabContainerModel: TabContainerModel);
18
+ isTabActive(tabId: string): boolean;
19
+ isTabFavorite(tabId: string): boolean;
20
+ toggleTabFavorite(tabId: string): void;
21
+ activate(tabId: string): void;
22
+ hide(tabId: string): void;
23
+ getContextMenuItems(e: React.MouseEvent<HTMLDivElement, MouseEvent>, tab: TabModel): Array<MenuItemLike<MenuToken, TabSwitcherMenuContext>>;
24
+ setFavoriteTabIds(tabIds: string[]): void;
25
+ onDragEnd(result: any): void;
26
+ private activeTabReaction;
27
+ private getValidTabIds;
28
+ private isValidTabId;
29
+ private isTabVisible;
30
+ }
@@ -0,0 +1,19 @@
1
+ import { BoxProps, HoistProps } from '@xh/hoist/core';
2
+ import { ScrollerModel } from '@xh/hoist/desktop/cmp/tab/dynamic/scroller/ScrollerModel';
3
+ import React, { Ref } from 'react';
4
+ /**
5
+ * A scroller component that displays a content component with directional scroll buttons when the
6
+ * content overflows the viewport.
7
+ * @internal
8
+ */
9
+ export interface ScrollerProps extends HoistProps<ScrollerModel>, Omit<BoxProps, 'content'> {
10
+ /** The content to be displayed within the scroller. */
11
+ content: React.FC<{
12
+ ref: Ref<HTMLDivElement>;
13
+ }>;
14
+ /** Props to be passed to the content component. */
15
+ contentProps?: Record<string, any>;
16
+ /** Orientation of the scroller - horizontal (default) or vertical. */
17
+ orientation?: 'horizontal' | 'vertical';
18
+ }
19
+ export declare const Scroller: React.FC<ScrollerProps>, scroller: import("@xh/hoist/core").ElementFactory<ScrollerProps>;
@@ -0,0 +1,23 @@
1
+ import { HoistModel } from '@xh/hoist/core';
2
+ /**
3
+ * Internal model for the Scroller component. Used to manage the scroll state and provide
4
+ * scroll functionality. Uses animation frames to ensure smooth scrolling.
5
+ * @internal
6
+ */
7
+ export declare class ScrollerModel extends HoistModel {
8
+ contentRef: import("react").RefObject<HTMLDivElement>;
9
+ private scrollStart;
10
+ private scrollSize;
11
+ private clientSize;
12
+ private animationFrameId;
13
+ get showScrollButtons(): boolean;
14
+ get isScrolledToStart(): boolean;
15
+ get isScrolledToEnd(): boolean;
16
+ get isHorizontal(): boolean;
17
+ constructor();
18
+ afterLinked(): void;
19
+ scroll(direction: 'forward' | 'backward'): void;
20
+ stopScrolling(): void;
21
+ onViewportEvent(): void;
22
+ destroy(): void;
23
+ }
@@ -1,4 +1,5 @@
1
- import { TabModel } from '@xh/hoist/cmp/tab';
1
+ import { TabContainerProps, TabModel } from '@xh/hoist/cmp/tab';
2
+ import { HoistProps, TestSupportProps } from '@xh/hoist/core';
2
3
  /**
3
4
  * Wrapper for contents to be shown within a TabContainer. This Component is used by TabContainer's
4
5
  * internal implementation to:
@@ -9,4 +10,8 @@ import { TabModel } from '@xh/hoist/cmp/tab';
9
10
  *
10
11
  * @internal
11
12
  */
12
- export declare const tab: import("@xh/hoist/core").ElementFactory<import("@xh/hoist/core").DefaultHoistProps<TabModel>>;
13
+ interface TabProps extends HoistProps<TabModel>, TestSupportProps {
14
+ childContainerProps?: TabContainerProps['childContainerProps'];
15
+ }
16
+ export declare const tab: import("@xh/hoist/core").ElementFactory<TabProps>;
17
+ export {};
@@ -4,4 +4,4 @@ import '../Tabs.scss';
4
4
  * Desktop implementation of TabContainer.
5
5
  * @internal
6
6
  */
7
- export declare function tabContainerImpl({ model, className, testId, ...props }: TabContainerProps): import("react").ReactElement<import("@xh/hoist/cmp/layout").BoxComponentProps, any>;
7
+ export declare function tabContainerImpl({ model, childContainerProps, className, testId, ...props }: TabContainerProps): import("react").ReactElement<import("@xh/hoist/cmp/layout").BoxComponentProps, any>;
@@ -0,0 +1,4 @@
1
+ import { TabSwitcherMenuContext } from '@xh/hoist/cmp/tab';
2
+ import { type MenuItemLike, MenuToken } from '@xh/hoist/core';
3
+ /** @internal */
4
+ export declare function getContextMenuItem(item: MenuItemLike<MenuToken, TabSwitcherMenuContext>, context: TabSwitcherMenuContext): MenuItemLike<MenuToken, TabSwitcherMenuContext>;
@@ -1 +1,2 @@
1
1
  export * from './TabSwitcher';
2
+ export * from './dynamic/DynamicTabSwitcher';
@@ -22,6 +22,7 @@ export declare let tabContainerImpl: any;
22
22
  export declare let useContextMenu: any;
23
23
  export declare let errorMessageImpl: any;
24
24
  export declare let maskImpl: any;
25
+ export declare let DynamicTabSwitcherModel: any;
25
26
  /**
26
27
  * Provide implementations of functions and classes exported in this file.
27
28
  *
@@ -4,7 +4,7 @@ import { ReactNode, ReactElement } from 'react';
4
4
  import './Panel.scss';
5
5
  export interface PanelProps extends HoistProps, Omit<BoxProps, 'title'> {
6
6
  /** A toolbar to be docked at the bottom of the panel. */
7
- bbar?: Some<ReactNode>;
7
+ bbar?: ReactNode;
8
8
  /** CSS class name specific to the panel's header. */
9
9
  headerClassName?: string;
10
10
  /** Items to be added to the right-side of the panel's header. */
@@ -30,7 +30,7 @@ export interface PanelProps extends HoistProps, Omit<BoxProps, 'title'> {
30
30
  /** Allow the panel to scroll vertically */
31
31
  scrollable?: boolean;
32
32
  /** A toolbar to be docked at the top of the panel. */
33
- tbar?: Some<ReactNode>;
33
+ tbar?: ReactNode;
34
34
  /** Title text added to the panel's header. */
35
35
  title?: ReactNode;
36
36
  }
@@ -6,4 +6,4 @@ import { TabContainerProps } from '@xh/hoist/cmp/tab';
6
6
  *
7
7
  * @internal
8
8
  */
9
- export declare function tabContainerImpl({ model, className }: TabContainerProps): import("react").ReactElement<any, any>;
9
+ export declare function tabContainerImpl({ model, className, ...props }: TabContainerProps): import("react").ReactElement<any, any>;