@vuu-ui/grid-layout 4.0.0-alpha.1
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/LICENSE +201 -0
- package/README.md +141 -0
- package/package.json +40 -0
- package/src/GridCommand.js +395 -0
- package/src/GridComponentSettings.js +163 -0
- package/src/GridController.js +359 -0
- package/src/GridDragCoordinator.js +293 -0
- package/src/GridGeometry.js +1298 -0
- package/src/GridLayout.css.js +119 -0
- package/src/GridLayout.js +120 -0
- package/src/GridLayoutContext.js +58 -0
- package/src/GridLayoutDocument.js +307 -0
- package/src/GridLayoutDocumentIds.js +110 -0
- package/src/GridLayoutItem.css.js +46 -0
- package/src/GridLayoutItem.js +147 -0
- package/src/GridLayoutLegacyCompatibility.js +66 -0
- package/src/GridLayoutModel.js +138 -0
- package/src/GridLayoutProvider.js +263 -0
- package/src/GridLayoutStackedItem.css.js +26 -0
- package/src/GridLayoutStackedtem.js +140 -0
- package/src/GridModel.js +1289 -0
- package/src/GridPlaceholder.css.js +9 -0
- package/src/GridPlaceholder.js +24 -0
- package/src/GridSnapshot.js +11 -0
- package/src/GridSplitter.css.js +62 -0
- package/src/GridSplitter.js +26 -0
- package/src/GridStack.js +277 -0
- package/src/Icon.css.js +8 -0
- package/src/Icon.js +26 -0
- package/src/IconButton.css.js +9 -0
- package/src/IconButton.js +28 -0
- package/src/TabDialog.css.js +10 -0
- package/src/TabDialog.js +77 -0
- package/src/TabMenu.css.js +8 -0
- package/src/TabMenu.js +78 -0
- package/src/componentToJson.js +41 -0
- package/src/drag-drop-next/DragContextNext.js +173 -0
- package/src/drag-drop-next/DragDropProviderNext.css.js +72 -0
- package/src/drag-drop-next/DragDropProviderNext.js +91 -0
- package/src/drag-drop-next/SpaceMan.js +256 -0
- package/src/drag-drop-next/TemplateDragSession.js +36 -0
- package/src/drag-drop-next/tabstrip-drag-drop.js +251 -0
- package/src/grid-dom-utils.js +57 -0
- package/src/grid-layout-utils.js +39 -0
- package/src/grid-snapshot-adapters.js +435 -0
- package/src/index.js +24 -0
- package/src/json-value.js +56 -0
- package/src/layoutFromJson.js +15 -0
- package/src/layoutToJson.js +5 -0
- package/src/propUtils.js +15 -0
- package/src/react-element-utils.js +15 -0
- package/src/typeOf.js +15 -0
- package/src/useAsDropTarget.js +229 -0
- package/src/useDraggable.js +46 -0
- package/src/useEditTabName.js +70 -0
- package/src/useGridChildProps.js +47 -0
- package/src/useGridControllerSnapshot.js +21 -0
- package/src/useGridLayout.js +727 -0
- package/src/useGridSplitterResizing.js +262 -0
- package/src/useNotDropTarget.js +2 -0
- package/types/AddTabDialog.d.ts +5 -0
- package/types/GridCommand.d.ts +146 -0
- package/types/GridComponentSettings.d.ts +71 -0
- package/types/GridController.d.ts +50 -0
- package/types/GridDragCoordinator.d.ts +80 -0
- package/types/GridGeometry.d.ts +331 -0
- package/types/GridLayout.d.ts +20 -0
- package/types/GridLayoutContext.d.ts +141 -0
- package/types/GridLayoutDocument.d.ts +61 -0
- package/types/GridLayoutDocumentIds.d.ts +15 -0
- package/types/GridLayoutItem.d.ts +28 -0
- package/types/GridLayoutLegacyCompatibility.d.ts +57 -0
- package/types/GridLayoutModel.d.ts +72 -0
- package/types/GridLayoutProvider.d.ts +59 -0
- package/types/GridLayoutStackedtem.d.ts +10 -0
- package/types/GridModel.d.ts +504 -0
- package/types/GridPlaceholder.d.ts +5 -0
- package/types/GridSnapshot.d.ts +49 -0
- package/types/GridSplitter.d.ts +10 -0
- package/types/GridStack.d.ts +160 -0
- package/types/Icon.d.ts +6 -0
- package/types/IconButton.d.ts +6 -0
- package/types/TabDialog.d.ts +9 -0
- package/types/TabMenu.d.ts +7 -0
- package/types/componentToJson.d.ts +38 -0
- package/types/drag-drop-next/DragContextNext.d.ts +92 -0
- package/types/drag-drop-next/DragDropProviderNext.d.ts +23 -0
- package/types/drag-drop-next/SpaceMan.d.ts +35 -0
- package/types/drag-drop-next/TemplateDragSession.d.ts +21 -0
- package/types/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
- package/types/grid-dom-utils.d.ts +17 -0
- package/types/grid-layout-utils.d.ts +18 -0
- package/types/grid-matrix.d.ts +5 -0
- package/types/grid-snapshot-adapters.d.ts +22 -0
- package/types/index.d.ts +24 -0
- package/types/json-value.d.ts +23 -0
- package/types/layoutFromJson.d.ts +4 -0
- package/types/layoutToJson.d.ts +3 -0
- package/types/propUtils.d.ts +5 -0
- package/types/react-element-utils.d.ts +3 -0
- package/types/src/AddTabDialog.d.ts +5 -0
- package/types/src/GridLayout.d.ts +14 -0
- package/types/src/GridLayoutContext.d.ts +88 -0
- package/types/src/GridLayoutItem.d.ts +28 -0
- package/types/src/GridLayoutModel.d.ts +59 -0
- package/types/src/GridLayoutProvider.d.ts +37 -0
- package/types/src/GridLayoutStackedtem.d.ts +10 -0
- package/types/src/GridModel.d.ts +350 -0
- package/types/src/GridPlaceholder.d.ts +5 -0
- package/types/src/GridSplitter.d.ts +9 -0
- package/types/src/Icon.d.ts +6 -0
- package/types/src/IconButton.d.ts +6 -0
- package/types/src/TabMenu.d.ts +6 -0
- package/types/src/componentToJson.d.ts +32 -0
- package/types/src/drag-drop-next/DragContextNext.d.ts +73 -0
- package/types/src/drag-drop-next/DragDropProviderNext.d.ts +20 -0
- package/types/src/drag-drop-next/SpaceMan.d.ts +35 -0
- package/types/src/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
- package/types/src/grid-dom-utils.d.ts +17 -0
- package/types/src/grid-layout-utils.d.ts +80 -0
- package/types/src/grid-matrix.d.ts +5 -0
- package/types/src/index.d.ts +10 -0
- package/types/src/layoutFromJson.d.ts +3 -0
- package/types/src/layoutToJson.d.ts +2 -0
- package/types/src/propUtils.d.ts +5 -0
- package/types/src/react-element-utils.d.ts +3 -0
- package/types/src/typeOf.d.ts +6 -0
- package/types/src/useAsDropTarget.d.ts +7 -0
- package/types/src/useDraggable.d.ts +23 -0
- package/types/src/useGridChildProps.d.ts +13 -0
- package/types/src/useGridLayout.d.ts +43 -0
- package/types/src/useGridSplitterResizing.d.ts +12 -0
- package/types/src/useNotDropTarget.d.ts +1 -0
- package/types/typeOf.d.ts +6 -0
- package/types/useAsDropTarget.d.ts +7 -0
- package/types/useDraggable.d.ts +24 -0
- package/types/useEditTabName.d.ts +11 -0
- package/types/useGridChildProps.d.ts +13 -0
- package/types/useGridControllerSnapshot.d.ts +7 -0
- package/types/useGridLayout.d.ts +53 -0
- package/types/useGridSplitterResizing.d.ts +14 -0
- package/types/useNotDropTarget.d.ts +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Dispatch, DragEvent } from "react";
|
|
2
|
+
import { GridLayoutDragEndHandler } from "./GridLayoutProvider";
|
|
3
|
+
import { GridModel, TabStateTab, TrackSize } from "./GridModel";
|
|
4
|
+
import { GridLayoutDragStartHandler } from "./useDraggable";
|
|
5
|
+
import { GridLayoutModel } from "./GridLayoutModel";
|
|
6
|
+
import { GridLayoutDropPosition } from "@vuu-ui/vuu-utils";
|
|
7
|
+
export type GridLayoutActionType = "close";
|
|
8
|
+
export type GridLayoutCloseAction = {
|
|
9
|
+
type: "close";
|
|
10
|
+
id: string;
|
|
11
|
+
};
|
|
12
|
+
export type GridLayoutAddChildAction = {
|
|
13
|
+
title: string;
|
|
14
|
+
type: "add-child";
|
|
15
|
+
componentTemplate: ComponentTemplate;
|
|
16
|
+
stackId?: string;
|
|
17
|
+
};
|
|
18
|
+
export type GridLayoutSwitchTabAction = {
|
|
19
|
+
type: "switch-tab";
|
|
20
|
+
fromId: string;
|
|
21
|
+
toId: string;
|
|
22
|
+
};
|
|
23
|
+
export type GridLayoutTrackAction = {
|
|
24
|
+
type: "resize-grid-column" | "resize-grid-row";
|
|
25
|
+
trackIndex: number;
|
|
26
|
+
value: TrackSize;
|
|
27
|
+
};
|
|
28
|
+
export type GridLayoutAction = GridLayoutCloseAction | GridLayoutAddChildAction | GridLayoutSwitchTabAction | GridLayoutTrackAction;
|
|
29
|
+
export type GridLayoutDispatch = Dispatch<GridLayoutAction>;
|
|
30
|
+
/**
|
|
31
|
+
* provides details of a dragged component within a stack
|
|
32
|
+
*/
|
|
33
|
+
export interface TabbedComponentDragSource {
|
|
34
|
+
element: HTMLElement;
|
|
35
|
+
isSelectedTab: boolean;
|
|
36
|
+
label: string;
|
|
37
|
+
layoutId: string;
|
|
38
|
+
tab: TabStateTab;
|
|
39
|
+
/** deprecated */
|
|
40
|
+
tabIndex: number;
|
|
41
|
+
tabsId: string;
|
|
42
|
+
type: "tabbed-component";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* provides details of a dragged component
|
|
46
|
+
*/
|
|
47
|
+
export interface ComponentDragSource {
|
|
48
|
+
element: HTMLElement;
|
|
49
|
+
dragElement?: HTMLElement;
|
|
50
|
+
id: string;
|
|
51
|
+
label: string;
|
|
52
|
+
layoutId: string;
|
|
53
|
+
type: "component";
|
|
54
|
+
}
|
|
55
|
+
export interface ComponentTemplate {
|
|
56
|
+
componentJson: string;
|
|
57
|
+
label: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* provides details of a template, to be used on drop to instantiate a new component
|
|
61
|
+
*/
|
|
62
|
+
export interface TemplateSource extends ComponentTemplate {
|
|
63
|
+
element: HTMLElement;
|
|
64
|
+
layoutId: string;
|
|
65
|
+
type: "template";
|
|
66
|
+
}
|
|
67
|
+
export type DragSourceProvider = (evt: DragEvent<Element>) => DragSource;
|
|
68
|
+
export type DragSource = ComponentDragSource | TemplateSource | TabbedComponentDragSource;
|
|
69
|
+
export declare const sourceIsComponent: (source: DragSource | undefined) => source is ComponentDragSource;
|
|
70
|
+
export declare const sourceIsTabbedComponent: (source: DragSource | undefined) => source is TabbedComponentDragSource;
|
|
71
|
+
export declare const sourceIsTemplate: (source: DragSource | undefined) => source is TemplateSource;
|
|
72
|
+
export type GridLayoutDropHandler = (targetId: string, dragSource: DragSource, position: GridLayoutDropPosition) => void;
|
|
73
|
+
export interface GridLayoutContextProps {
|
|
74
|
+
dispatchGridLayoutAction: GridLayoutDispatch;
|
|
75
|
+
gridLayoutModel?: GridLayoutModel;
|
|
76
|
+
gridModel?: GridModel;
|
|
77
|
+
id: string;
|
|
78
|
+
onDragEnd?: GridLayoutDragEndHandler;
|
|
79
|
+
onDragStart: GridLayoutDragStartHandler;
|
|
80
|
+
onDrop: GridLayoutDropHandler;
|
|
81
|
+
}
|
|
82
|
+
export declare const GridLayoutContext: import("react").Context<GridLayoutContextProps>;
|
|
83
|
+
export declare const useGridLayoutDispatch: () => GridLayoutDispatch;
|
|
84
|
+
export declare const useGridLayoutDropHandler: () => GridLayoutDropHandler;
|
|
85
|
+
export declare const useGridLayoutDragEndHandler: () => GridLayoutDragEndHandler | undefined;
|
|
86
|
+
export declare const useGridLayoutDragStartHandler: () => GridLayoutDragStartHandler;
|
|
87
|
+
export declare const useGridModel: () => GridModel;
|
|
88
|
+
export declare const useGridLayoutId: () => string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactElement } from "react";
|
|
2
|
+
import { LayoutJSON } from "./componentToJson";
|
|
3
|
+
import { GridChildItemStyle, GridModelChildItemProps } from "./GridModel";
|
|
4
|
+
export interface GridLayoutItemProps extends Omit<GridModelChildItemProps, "contentDetached" | "style" | "type">, Omit<HTMLAttributes<HTMLDivElement>, "id" | "onDragStart" | "onDrop" | "style"> {
|
|
5
|
+
"data-drop-target"?: boolean | string;
|
|
6
|
+
header?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* If provided, component is fixed height
|
|
9
|
+
*/
|
|
10
|
+
height?: number;
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* style.gridArea is optional only if stackId is provided and a separate declaration
|
|
14
|
+
* of a GridLayoutStackedItem child is included within GridLayout
|
|
15
|
+
*/
|
|
16
|
+
style?: GridChildItemStyle;
|
|
17
|
+
/**
|
|
18
|
+
* If provided, component is fixed width
|
|
19
|
+
*/
|
|
20
|
+
width?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function GridLayoutItem({ children, className: classNameProp, contentVisible: contentVisibleProp, "data-drop-target": dataDropTarget, header: headerProp, height, id, stackId, resizeable, style: styleProp, title: titleProp, width, ...htmlAttributes }: GridLayoutItemProps): import("react").JSX.Element | null;
|
|
23
|
+
export declare namespace GridLayoutItem {
|
|
24
|
+
var toJSON: (element: ReactElement<GridLayoutItemProps, typeof GridLayoutItemType>) => LayoutJSON<object>;
|
|
25
|
+
}
|
|
26
|
+
declare const GridLayoutItemType: import("react").FunctionComponent<GridLayoutItemProps>;
|
|
27
|
+
export declare const isGridLayoutItem: (element: ReactElement) => boolean;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { EventEmitter, GridLayoutSplitDirection, OptionalProperty } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { TrackType, type GridLayoutModelCoordinates, type GridModel, type GridModelChildItem, type GridModelEvents, type ISplitter } from "./GridModel";
|
|
3
|
+
export type GridLayoutModelPosition = {
|
|
4
|
+
end: number;
|
|
5
|
+
start: number;
|
|
6
|
+
};
|
|
7
|
+
export type ResizeState = {
|
|
8
|
+
resizeTrackIsShared: boolean;
|
|
9
|
+
mousePos: number;
|
|
10
|
+
splitter: ISplitter;
|
|
11
|
+
};
|
|
12
|
+
export type GridItemRemoveReason = "drag" | "close" | "placeholder" | "unstack";
|
|
13
|
+
export type GridLayoutResizeOperation = "contract" | "expand";
|
|
14
|
+
export type GridLayoutResizeDirection = "vertical" | "horizontal";
|
|
15
|
+
export type GridLayoutRelativePosition = "aboveInSameColumn" | "belowInSameColumn" | "rightInSameRow" | "leftInSameRow";
|
|
16
|
+
export type GridLayoutTrack = "column" | "row";
|
|
17
|
+
export type GridLayoutModelItemType = "content" | "placeholder" | "splitter" | "stacked-content";
|
|
18
|
+
type OneOrBothGridLayoutModelCoordinates = GridLayoutModelCoordinates | OptionalProperty<GridLayoutModelCoordinates, TrackType>;
|
|
19
|
+
export type GridItemUpdate = [string, OneOrBothGridLayoutModelCoordinates];
|
|
20
|
+
export type GridLayoutModelEvents = Pick<GridModelEvents, "child-position-updates">;
|
|
21
|
+
export declare class GridLayoutModel extends EventEmitter<GridLayoutModelEvents> {
|
|
22
|
+
private gridModel;
|
|
23
|
+
private splitters;
|
|
24
|
+
constructor(gridModel: GridModel);
|
|
25
|
+
private updateContrasToOccupySpace;
|
|
26
|
+
removeGridItem(gridItemId: string, reason: GridItemRemoveReason): void;
|
|
27
|
+
dropReplaceGridItem(droppedItemId: string, targetItemId: string): GridModelChildItem;
|
|
28
|
+
createSplitters(): ISplitter[];
|
|
29
|
+
getSplitterById(splitterId: string): ISplitter;
|
|
30
|
+
getSplitter(gridLayoutItem: GridModelChildItem, resizeDirection: GridLayoutResizeDirection): ISplitter;
|
|
31
|
+
/**
|
|
32
|
+
* We're going to resize a gridItem that shares a grid line with one or
|
|
33
|
+
* more other grid items. We need to insert a new grid line, then anchor
|
|
34
|
+
* the griditem to be resized to the new grid line.
|
|
35
|
+
*/
|
|
36
|
+
addTrackForResize(trackType: TrackType, newTrackSize: number, resizeOperation: GridLayoutResizeOperation, index: number, state: ResizeState): void;
|
|
37
|
+
/**
|
|
38
|
+
* Calculate the new grid positions for a dropped item and the target item,
|
|
39
|
+
* when the target is being split in two. Generate updates for the respective
|
|
40
|
+
* grid child items.
|
|
41
|
+
*
|
|
42
|
+
* @param droppedItemId
|
|
43
|
+
* @param targetItemId
|
|
44
|
+
* @param splitDirection
|
|
45
|
+
* @param splitIndex
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
private dropSplitTarget;
|
|
49
|
+
/**
|
|
50
|
+
* Dragged child item has been dropped on (NESW) quadrant of target.
|
|
51
|
+
* Split the target in two, respecting targetted quadrant and
|
|
52
|
+
* assign layout positions of each child item.
|
|
53
|
+
*/
|
|
54
|
+
dropSplitGridItem(droppedItemId: string, targetItemId: string, splitDirection: GridLayoutSplitDirection, resizeDirection?: GridLayoutResizeDirection): void;
|
|
55
|
+
removeTrack(trackIndex: number, resizeDirection: GridLayoutResizeDirection): GridItemUpdate[];
|
|
56
|
+
isResizeTrackShared(splitter: ISplitter): boolean;
|
|
57
|
+
toDebugString(): string;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DragEvent, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { GridLayoutChangeHandler, GridLayoutDescriptor } from "./GridModel";
|
|
3
|
+
import { GridLayoutItemProps } from "./GridLayoutItem";
|
|
4
|
+
import { LayoutJSON } from "./componentToJson";
|
|
5
|
+
export type GridChildElementsChangeHandler = (id: string, childElements: ReactElement<GridLayoutItemProps>[]) => void;
|
|
6
|
+
type GridLayoutOptions = {
|
|
7
|
+
newChildItem: {
|
|
8
|
+
header: boolean;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export type ReactElementList = ReactElement[];
|
|
12
|
+
export type ReactElementMap<P = any> = Record<string, ReactElement<P>>;
|
|
13
|
+
export type SerializedComponentMap = Record<string, LayoutJSON>;
|
|
14
|
+
export type SerializedGridLayout = {
|
|
15
|
+
components: SerializedComponentMap;
|
|
16
|
+
id: string;
|
|
17
|
+
layout: GridLayoutDescriptor;
|
|
18
|
+
};
|
|
19
|
+
export type DeserializedGridLayout = {
|
|
20
|
+
components: ReactElementMap<GridLayoutItemProps>;
|
|
21
|
+
id: string;
|
|
22
|
+
layout: GridLayoutDescriptor;
|
|
23
|
+
};
|
|
24
|
+
export type GridLayoutDragEndHandler = (evt: DragEvent<HTMLElement>) => void;
|
|
25
|
+
export interface GridLayoutProviderProps {
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
options?: GridLayoutOptions;
|
|
28
|
+
serializedLayout?: SerializedGridLayout;
|
|
29
|
+
}
|
|
30
|
+
export declare const GridLayoutProvider: (props: GridLayoutProviderProps) => ReactElement;
|
|
31
|
+
export declare const useGridChangeHandler: () => {
|
|
32
|
+
onChangeChildElements: GridChildElementsChangeHandler | undefined;
|
|
33
|
+
onChangeLayout: GridLayoutChangeHandler | undefined;
|
|
34
|
+
};
|
|
35
|
+
export declare const useSavedGrid: () => ((id: string) => DeserializedGridLayout | undefined) | undefined;
|
|
36
|
+
export declare const useGridLayoutOptions: () => GridLayoutOptions | undefined;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { GridLayoutItemProps } from "./GridLayoutItem";
|
|
3
|
+
import { ComponentTemplate } from "./GridLayoutContext";
|
|
4
|
+
export interface GridLayoutStackedItemProps extends GridLayoutItemProps {
|
|
5
|
+
allowAddTab?: boolean;
|
|
6
|
+
getNewComponent?: () => ComponentTemplate;
|
|
7
|
+
showMenu?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const GridLayoutStackedItem: ({ allowAddTab, children, className: classNameProp, header, id, getNewComponent, resizeable, showMenu, style: styleProp, title, ...htmlAttributes }: GridLayoutStackedItemProps) => import("react").JSX.Element;
|
|
10
|
+
export declare const isGridLayoutStackedItem: (element: ReactElement) => boolean;
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { EventEmitter, type OptionalProperty } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { CSSProperties } from "react";
|
|
3
|
+
import { DropPosition } from "./drag-drop-next/DragContextNext";
|
|
4
|
+
import { GridItemRemoveReason, GridItemUpdate, GridLayoutModelPosition, GridLayoutResizeDirection } from "./GridLayoutModel";
|
|
5
|
+
export type TrackUnit = "px" | "fr";
|
|
6
|
+
export type CSSFraction = `${number}fr`;
|
|
7
|
+
export type CSSPixels = `${number}px`;
|
|
8
|
+
export type TrackSize = CSSFraction | CSSPixels;
|
|
9
|
+
export declare const isFractionUnit: (trackSize: TrackSize) => trackSize is CSSFraction;
|
|
10
|
+
export declare const isPixelUnit: (trackSize: TrackSize) => trackSize is CSSPixels;
|
|
11
|
+
export interface GridLayoutChildItemDescriptor {
|
|
12
|
+
contentVisible?: boolean;
|
|
13
|
+
dropTarget?: boolean | string;
|
|
14
|
+
gridArea: string;
|
|
15
|
+
header?: boolean;
|
|
16
|
+
resizeable?: GridModelItemResizeable;
|
|
17
|
+
/**
|
|
18
|
+
* For GridLayoutItems that are 'stacked' (e.g. displayed in tabbed container)
|
|
19
|
+
* this is the id of the associated StackedLayoutItem.
|
|
20
|
+
*/
|
|
21
|
+
stackId?: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface GridLayoutChildItemDescriptorWithComponentId extends GridLayoutChildItemDescriptor {
|
|
25
|
+
componentId: string;
|
|
26
|
+
}
|
|
27
|
+
export type GridLayoutChildItemDescriptors = Record<string, GridLayoutChildItemDescriptor>;
|
|
28
|
+
export interface GridColumnsAndRows {
|
|
29
|
+
cols: TrackSize[];
|
|
30
|
+
rows: TrackSize[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Describes a GridLayout
|
|
34
|
+
* grid rows and columns
|
|
35
|
+
* layout details of gridItems
|
|
36
|
+
*/
|
|
37
|
+
export interface GridLayoutDescriptor extends GridColumnsAndRows {
|
|
38
|
+
gridLayoutItems?: GridLayoutChildItemDescriptors;
|
|
39
|
+
}
|
|
40
|
+
export interface GridLayoutModelCoordinates {
|
|
41
|
+
column: GridLayoutModelPosition;
|
|
42
|
+
row: GridLayoutModelPosition;
|
|
43
|
+
}
|
|
44
|
+
export interface GridModelChildItemProps extends Omit<GridLayoutChildItemDescriptor, "gridArea"> {
|
|
45
|
+
contentVisible?: boolean;
|
|
46
|
+
fixed?: boolean;
|
|
47
|
+
height?: number;
|
|
48
|
+
id: string;
|
|
49
|
+
style?: GridChildItemStyle;
|
|
50
|
+
type?: GridModelItemType;
|
|
51
|
+
width?: number;
|
|
52
|
+
}
|
|
53
|
+
export type GridModelTrack = "column" | "row";
|
|
54
|
+
export type AssignDirection = "bwd" | "fwd";
|
|
55
|
+
export type TrackInsertionPosition = {
|
|
56
|
+
index: number;
|
|
57
|
+
position: "before" | "after";
|
|
58
|
+
};
|
|
59
|
+
export type GridLayoutChangeHandler = (gridId: string, gridLayoutDescriptor: GridLayoutDescriptor) => void;
|
|
60
|
+
export type GridTrackAddedEvent = {
|
|
61
|
+
gridId: string;
|
|
62
|
+
trackType: TrackType;
|
|
63
|
+
newTrackIndex: number;
|
|
64
|
+
newTracks: GridTrack[];
|
|
65
|
+
};
|
|
66
|
+
export type GridTrackAddedHandler = (evt: GridTrackAddedEvent) => void;
|
|
67
|
+
export type NonContentResetOptions = {
|
|
68
|
+
placeholders?: boolean;
|
|
69
|
+
splitters?: boolean;
|
|
70
|
+
};
|
|
71
|
+
export declare const NonContentResetOptions: NonContentResetOptions;
|
|
72
|
+
export type GridChildPositionChangeHandler = (updates: GridItemUpdate[], nonContentResetOptions?: NonContentResetOptions) => void;
|
|
73
|
+
export type TabsChangeHandler = (tabsId: string, active: number, tabs: TabStateTab[]) => void;
|
|
74
|
+
export type TabSelectionChangeHandler = (tabsId: string, active: number) => void;
|
|
75
|
+
export type GridModelEvents = {
|
|
76
|
+
"grid-layout-change": GridLayoutChangeHandler;
|
|
77
|
+
"grid-track-added": GridTrackAddedHandler;
|
|
78
|
+
"child-position-updates": GridChildPositionChangeHandler;
|
|
79
|
+
"tabs-change": TabsChangeHandler;
|
|
80
|
+
"tabs-created": (stackItem: GridModelChildItem) => void;
|
|
81
|
+
"tabs-removed": (tabsId: string) => void;
|
|
82
|
+
"tab-selection-change": TabSelectionChangeHandler;
|
|
83
|
+
};
|
|
84
|
+
export type GridModelPosition = {
|
|
85
|
+
end: number;
|
|
86
|
+
start: number;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Describes position of component within grid container. Position
|
|
90
|
+
* is grid column and row start and end values.
|
|
91
|
+
*/
|
|
92
|
+
export interface GridModelCoordinates {
|
|
93
|
+
column: GridModelPosition;
|
|
94
|
+
row: GridModelPosition;
|
|
95
|
+
}
|
|
96
|
+
export type GridModelItemResizeable = "h" | "v" | "hv" | false;
|
|
97
|
+
export type GridModelItemType = "content" | "placeholder" | "splitter" | "stacked-content";
|
|
98
|
+
/**
|
|
99
|
+
* The set of attributes that allow the management of layout and behaviour of a
|
|
100
|
+
* component laid out in a grid container.
|
|
101
|
+
*/
|
|
102
|
+
export interface IGridModelChildItem extends GridModelCoordinates {
|
|
103
|
+
childId?: string[];
|
|
104
|
+
closeable?: boolean;
|
|
105
|
+
contentVisible?: boolean;
|
|
106
|
+
dropTarget?: boolean | string;
|
|
107
|
+
fixed?: boolean;
|
|
108
|
+
header?: boolean;
|
|
109
|
+
height?: number;
|
|
110
|
+
id: string;
|
|
111
|
+
stackId?: string;
|
|
112
|
+
resizeable?: GridModelItemResizeable;
|
|
113
|
+
title?: string;
|
|
114
|
+
type: GridModelItemType;
|
|
115
|
+
width?: number;
|
|
116
|
+
}
|
|
117
|
+
export interface IPlaceholder extends IGridModelChildItem {
|
|
118
|
+
type: "placeholder";
|
|
119
|
+
}
|
|
120
|
+
export type GridChildItemStyle = Omit<CSSProperties, "gridArea"> & {
|
|
121
|
+
gridArea: string;
|
|
122
|
+
};
|
|
123
|
+
type StackedGridModelChildItem = GridModelChildItem & {
|
|
124
|
+
stackId: string;
|
|
125
|
+
};
|
|
126
|
+
export declare const isStackedItem: (i: GridModelChildItem) => i is StackedGridModelChildItem;
|
|
127
|
+
export type GridModelStackedChildItem = GridModelChildItem & {
|
|
128
|
+
type: "stacked-content";
|
|
129
|
+
};
|
|
130
|
+
export declare class GridModelChildItem implements IGridModelChildItem {
|
|
131
|
+
#private;
|
|
132
|
+
id: string;
|
|
133
|
+
column: GridModelPosition;
|
|
134
|
+
contentDetached?: boolean;
|
|
135
|
+
contentVisible?: boolean;
|
|
136
|
+
dropTarget?: boolean | string;
|
|
137
|
+
header?: boolean;
|
|
138
|
+
height?: number;
|
|
139
|
+
horizontalSplitter: boolean;
|
|
140
|
+
stackId?: string;
|
|
141
|
+
resizeable: GridModelItemResizeable;
|
|
142
|
+
row: GridModelPosition;
|
|
143
|
+
title?: string;
|
|
144
|
+
type: GridModelItemType;
|
|
145
|
+
verticalSplitter: boolean;
|
|
146
|
+
width?: number;
|
|
147
|
+
constructor({ header, height, id, row, column, dropTarget, stackId, resizeable, title, type, width, contentVisible, }: OptionalProperty<IGridModelChildItem, "type">);
|
|
148
|
+
get dragging(): boolean;
|
|
149
|
+
set dragging(isDragging: boolean);
|
|
150
|
+
get gridArea(): string;
|
|
151
|
+
}
|
|
152
|
+
export type AriaOrientation = "horizontal" | "vertical";
|
|
153
|
+
export type SplitterAlign = "start" | "end";
|
|
154
|
+
export interface ISplitter extends GridLayoutModelCoordinates {
|
|
155
|
+
align: SplitterAlign;
|
|
156
|
+
ariaOrientation: AriaOrientation;
|
|
157
|
+
controls: string;
|
|
158
|
+
id: string;
|
|
159
|
+
orientation: GridLayoutResizeDirection;
|
|
160
|
+
/**
|
|
161
|
+
* Index values of the two grid tracks (column or row) whose
|
|
162
|
+
* dimension (width for columns, height for rows) can be
|
|
163
|
+
* manipulated with this splitter. The tracks will usually,
|
|
164
|
+
* but not always, be adjacent.
|
|
165
|
+
*/
|
|
166
|
+
resizedGridTracks: [number, number];
|
|
167
|
+
resizedChildItems: {
|
|
168
|
+
before: string[];
|
|
169
|
+
after: string[];
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
export type TabStateEvent = (tabState: TabState) => void;
|
|
173
|
+
export type TabStateTabEvents = {
|
|
174
|
+
"active-change": TabStateEvent;
|
|
175
|
+
"tab-added": (tabState: TabState, tab: TabStateTab) => void;
|
|
176
|
+
"tab-detached": TabStateEvent;
|
|
177
|
+
"tabs-change": (tabsId: string, active: number, tabs: TabStateTab[]) => void;
|
|
178
|
+
"tabs-removed": (tabsId: string) => void;
|
|
179
|
+
};
|
|
180
|
+
export type TabStateTab = {
|
|
181
|
+
id: string;
|
|
182
|
+
label: string;
|
|
183
|
+
};
|
|
184
|
+
export declare class TabState extends EventEmitter<TabStateTabEvents> {
|
|
185
|
+
id: string;
|
|
186
|
+
active: number;
|
|
187
|
+
tabs: TabStateTab[];
|
|
188
|
+
detachedTab: TabStateTab | undefined;
|
|
189
|
+
constructor(id: string, active: number, tabs: TabStateTab[]);
|
|
190
|
+
setActiveTab(value: string): void;
|
|
191
|
+
/**
|
|
192
|
+
* A Tab is detached when a drag operation commences. It is removed from Tabstrip, but associated component
|
|
193
|
+
* remains in DOM. The 'next' tab is selected and the associated TabPanel made visible. The tab panel associated
|
|
194
|
+
* with the detached tab remains below the selected tab panel. This allows a dragged tab panel to be repositioned
|
|
195
|
+
* vis drag drop without removing it from DOM, triggering React unmount/remount.
|
|
196
|
+
*/
|
|
197
|
+
detachTab(value: string): void;
|
|
198
|
+
setNextActiveTab(): void;
|
|
199
|
+
moveTab(tab: TabStateTab, { position, target }: DropPosition, activateTab?: boolean): void;
|
|
200
|
+
addTab(tab: TabStateTab, dropPosition?: DropPosition): void;
|
|
201
|
+
removeTab(id: string): void;
|
|
202
|
+
get activeTab(): TabStateTab;
|
|
203
|
+
private getNextActiveTab;
|
|
204
|
+
private indexOfTab;
|
|
205
|
+
}
|
|
206
|
+
export type TrackType = "column" | "row";
|
|
207
|
+
export type GridTrackResizeHandler = (trackType: TrackType, tracks: GridTrack[]) => void;
|
|
208
|
+
export type GridTrackEvents = {
|
|
209
|
+
"grid-track-added": GridTrackAddedHandler;
|
|
210
|
+
"grid-track-resize": GridTrackResizeHandler;
|
|
211
|
+
};
|
|
212
|
+
export declare class GridTrack {
|
|
213
|
+
#private;
|
|
214
|
+
static fromTrackSize: (trackSize: TrackSize) => GridTrack;
|
|
215
|
+
constructor(trackSize: TrackSize);
|
|
216
|
+
get hasBeenMeasured(): boolean;
|
|
217
|
+
get isFraction(): boolean;
|
|
218
|
+
get isPixelValue(): boolean;
|
|
219
|
+
get isMeasured(): boolean;
|
|
220
|
+
get measuredValue(): number;
|
|
221
|
+
set measuredValue(value: number);
|
|
222
|
+
convertUnitsToPixels(): void;
|
|
223
|
+
get hasNumericValue(): boolean;
|
|
224
|
+
get numericValue(): number;
|
|
225
|
+
get trackSize(): TrackSize;
|
|
226
|
+
set trackSize(trackSize: TrackSize);
|
|
227
|
+
addFraction(trackSize: TrackSize): void;
|
|
228
|
+
increment(value: number): void;
|
|
229
|
+
toString: () => TrackSize;
|
|
230
|
+
}
|
|
231
|
+
export declare class GridTracks extends EventEmitter<GridTrackEvents> {
|
|
232
|
+
#private;
|
|
233
|
+
private gridId;
|
|
234
|
+
constructor(gridId: string, columns: TrackSize[], rows: TrackSize[]);
|
|
235
|
+
get columns(): TrackSize[];
|
|
236
|
+
set columns(columns: TrackSize[]);
|
|
237
|
+
get rows(): TrackSize[];
|
|
238
|
+
set rows(rows: TrackSize[]);
|
|
239
|
+
get colCount(): number;
|
|
240
|
+
get rowCount(): number;
|
|
241
|
+
getTracks(trackType: TrackType): GridTrack[];
|
|
242
|
+
/**
|
|
243
|
+
* Set the numeric track values from values read from DOM. This is invoked from a callbackRef
|
|
244
|
+
* as soom as GridLayout container is rendered into dom.
|
|
245
|
+
*/
|
|
246
|
+
measure(trackType: TrackType): void;
|
|
247
|
+
getBisectingTrack(trackType: TrackType, startIndex: number, endIndex: number): number;
|
|
248
|
+
/**
|
|
249
|
+
* Split a single track into 2 equal sized tracks
|
|
250
|
+
*
|
|
251
|
+
*/
|
|
252
|
+
splitTrack(trackType: TrackType, trackIndex: number): void;
|
|
253
|
+
/**
|
|
254
|
+
* Given multiple tracks (columns/rows), create a new grid line that exactly bisects
|
|
255
|
+
* given tracks.
|
|
256
|
+
*/
|
|
257
|
+
splitTracks(trackType: TrackType, fromTrackLine: number, toTrackLine: number): number;
|
|
258
|
+
/**
|
|
259
|
+
* In the trackInsertionPosition, the index always indicates where the new track
|
|
260
|
+
* will be inserted. The position indicates where it falls, conceptually, in relation
|
|
261
|
+
* to the existing two tracks that it will fall between. It will overlap one, but not
|
|
262
|
+
* both of the existing track positions.
|
|
263
|
+
*/
|
|
264
|
+
insertTrack(trackType: TrackType, { index, position }: TrackInsertionPosition, trackSize: number): void;
|
|
265
|
+
removeTrack(trackType: TrackType, index: number, assignDirection?: AssignDirection): void;
|
|
266
|
+
resizeTo(trackType: TrackType, trackIndex: number, value: TrackSize): void;
|
|
267
|
+
resizeBy(trackType: "row" | "column", trackIndex: number, contraTrackIndex: number, value: number): void;
|
|
268
|
+
get css(): Pick<CSSProperties, "gridTemplateColumns" | "gridTemplateRows">;
|
|
269
|
+
serialize(): {
|
|
270
|
+
cols: TrackSize[];
|
|
271
|
+
rows: TrackSize[];
|
|
272
|
+
};
|
|
273
|
+
toString(): string;
|
|
274
|
+
}
|
|
275
|
+
export declare class GridModel extends EventEmitter<GridModelEvents> {
|
|
276
|
+
#private;
|
|
277
|
+
id: string;
|
|
278
|
+
tracks: GridTracks;
|
|
279
|
+
constructor(id: string, { cols, gridLayoutItems, rows }: GridLayoutDescriptor);
|
|
280
|
+
get childItems(): GridModelChildItem[];
|
|
281
|
+
private handleTabsChange;
|
|
282
|
+
private handleTabsRemoved;
|
|
283
|
+
private handleTabSelectionChange;
|
|
284
|
+
private handleTabAdded;
|
|
285
|
+
private handleTabDetached;
|
|
286
|
+
getTabState: (tabsId: string, fallbackAction?: "throw" | "create") => TabState;
|
|
287
|
+
setTabState(stackId: string, childItems: GridModelChildItem[], activeItem?: number): TabState;
|
|
288
|
+
activateStackedChildItem(stackId: string, { id }: TabStateTab): void;
|
|
289
|
+
detachStackedChildItem(stackId: string, { id }: TabStateTab): void;
|
|
290
|
+
moveItemWithinTabs(tabsId: string, tab: TabStateTab, dropPosition: DropPosition, selectMovedTab: boolean): void;
|
|
291
|
+
moveItemBetweenTabs(fromTabsId: string, toTabsId: string, tab: TabStateTab, dropPosition: DropPosition): void;
|
|
292
|
+
notifyChange(): void;
|
|
293
|
+
toGridLayoutDescriptor(): GridLayoutDescriptor;
|
|
294
|
+
splitGridTrack(trackType: TrackType, trackIndex: number): void;
|
|
295
|
+
splitGridTracks(trackType: TrackType, fromTrackLine: number, toTrackLine: number): number;
|
|
296
|
+
private updateChildItemsToAccommodateNewTrack;
|
|
297
|
+
insertGridTrack(trackType: TrackType, { index, position }: TrackInsertionPosition, trackSize: number): void;
|
|
298
|
+
removeGridTrack(trackType: TrackType, trackIndex: number, assignDirection?: AssignDirection, updateChildItems?: boolean): void;
|
|
299
|
+
applyUpdates(updates: GridItemUpdate[]): void;
|
|
300
|
+
private addChildItems;
|
|
301
|
+
addChildItem(childItem: GridModelChildItem): void;
|
|
302
|
+
private addChildItemToStack;
|
|
303
|
+
updateChildColumn(childItemId: string, { start, end }: GridModelPosition): void;
|
|
304
|
+
updateChildRow(childItemId: string, { start, end }: GridModelPosition): void;
|
|
305
|
+
/**
|
|
306
|
+
* How we handle removal depends on context (the remove reason).
|
|
307
|
+
* If the child item is being deleted, we clear all references to the
|
|
308
|
+
* item in our internal structures. If the item is being dragged, we
|
|
309
|
+
* can expect it to be dropped again. We preserve some references,
|
|
310
|
+
* but mark the item as dragging.
|
|
311
|
+
*/
|
|
312
|
+
removeChildItem(childItemId: string, reason: GridItemRemoveReason): void;
|
|
313
|
+
stackChildItems(targetId: string, stackedChildId: string): void;
|
|
314
|
+
getChildItem(childItemId: string, throwIfNotFound: true): GridModelChildItem;
|
|
315
|
+
getChildItem(childItemId: string, throwIfNotFound?: false): GridModelChildItem | undefined;
|
|
316
|
+
getStackedChildItems(): Map<string, StackedGridModelChildItem[]>;
|
|
317
|
+
getStackedChildItems(stackId: string): GridModelChildItem[];
|
|
318
|
+
validateChildId(childItemId: string): string;
|
|
319
|
+
clearPlaceholders(): void;
|
|
320
|
+
findUnusedGridLines(): number[][];
|
|
321
|
+
createPlaceholders(): void;
|
|
322
|
+
getPlaceholders(): GridModelChildItem[];
|
|
323
|
+
getSplitters(): ISplitter[];
|
|
324
|
+
private getSplittersForChildItem;
|
|
325
|
+
private findColumnContrasAndSiblings;
|
|
326
|
+
private findRowContrasAndSiblings;
|
|
327
|
+
toDebugString(): void;
|
|
328
|
+
private getContrasAbove;
|
|
329
|
+
private getContrasBelow;
|
|
330
|
+
private getSiblingsRight;
|
|
331
|
+
private getContrasLeft;
|
|
332
|
+
private getSiblingsBelow;
|
|
333
|
+
/**
|
|
334
|
+
* Given a column, return all childItems starting at that column
|
|
335
|
+
*/
|
|
336
|
+
findByColumnStart(col: number, childItems?: GridModelChildItem[]): GridModelChildItem[] | undefined;
|
|
337
|
+
/**
|
|
338
|
+
* Given a column, return all childItems ending at that column
|
|
339
|
+
*/
|
|
340
|
+
findByColumnEnd(col: number, childItems?: GridModelChildItem[]): GridModelChildItem[] | undefined;
|
|
341
|
+
/**
|
|
342
|
+
* Given a row, return all childItems starting at that row
|
|
343
|
+
*/
|
|
344
|
+
findByRowStart(row: number, childItems?: GridModelChildItem[]): GridModelChildItem[] | undefined;
|
|
345
|
+
/**
|
|
346
|
+
* Given a row, return all childItems ending at that row
|
|
347
|
+
*/
|
|
348
|
+
findByRowEnd(row: number, childItems?: GridModelChildItem[]): GridModelChildItem[] | undefined;
|
|
349
|
+
}
|
|
350
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
export interface GridPlaceholderProps extends Omit<HTMLAttributes<HTMLDivElement>, "onDrop"> {
|
|
3
|
+
debugLabel?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const GridPlaceholder: ({ ...htmlAttributes }: GridPlaceholderProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
import { AriaOrientation } from "./GridModel";
|
|
3
|
+
import { ResizeOrientation } from "./grid-dom-utils";
|
|
4
|
+
export interface GridSplitterProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
"aria-controls": string;
|
|
6
|
+
ariaOrientation: AriaOrientation;
|
|
7
|
+
orientation: ResizeOrientation;
|
|
8
|
+
}
|
|
9
|
+
export declare const GridSplitter: ({ "aria-controls": ariaControls, ariaOrientation, orientation, ...htmlAttributes }: GridSplitterProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
export interface IconProps extends HTMLAttributes<HTMLSpanElement> {
|
|
3
|
+
name: string;
|
|
4
|
+
size?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const Icon: ({ className, name, size, style: styleProp, ...htmlAttributes }: IconProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ButtonProps } from "@salt-ds/core";
|
|
2
|
+
export interface IconButtonProps extends Omit<ButtonProps, "children"> {
|
|
3
|
+
icon: string;
|
|
4
|
+
size?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const IconButton: import("react").ForwardRefExoticComponent<IconButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CSSProperties, ReactElement } from "react";
|
|
2
|
+
export interface LayoutJSON<T extends object = object> {
|
|
3
|
+
active?: number;
|
|
4
|
+
children?: LayoutJSON[];
|
|
5
|
+
id?: string;
|
|
6
|
+
props?: T;
|
|
7
|
+
state?: unknown;
|
|
8
|
+
style?: CSSProperties;
|
|
9
|
+
title?: string;
|
|
10
|
+
type: string;
|
|
11
|
+
}
|
|
12
|
+
export interface LayoutProps {
|
|
13
|
+
active?: number;
|
|
14
|
+
"data-path"?: string;
|
|
15
|
+
children?: ReactElement[];
|
|
16
|
+
/**
|
|
17
|
+
* indicates flexDirection for Flexbox
|
|
18
|
+
*/
|
|
19
|
+
column?: boolean;
|
|
20
|
+
dropTarget?: boolean;
|
|
21
|
+
i8d: string;
|
|
22
|
+
key: string;
|
|
23
|
+
path?: string;
|
|
24
|
+
resizeable?: boolean;
|
|
25
|
+
style: CSSProperties;
|
|
26
|
+
type?: string;
|
|
27
|
+
version?: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function componentToJson(element: ReactElement): LayoutJSON;
|
|
30
|
+
export declare function serializeProps(props?: LayoutProps): {
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
} | undefined;
|