Skip to content

Commit

Permalink
feat(collapse): collaspe support to specify grow attr (#188)
Browse files Browse the repository at this point in the history
* feat(collapse): collaspe support to specify grow attr

* fix: improve querySelect & attribute name of collapse

* fix: explorer not rerender along with editor after selecting file
  • Loading branch information
mortalYoung authored Jun 22, 2021
1 parent c49e534 commit d5dca2e
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 32 deletions.
174 changes: 142 additions & 32 deletions src/components/collapse/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import {
collapseContentClassName,
} from './base';
import { Scrollable } from '../scrollable';
import { select } from 'mo/common/dom';

type RenderFunctionProps = (data: DataBaseProps) => React.ReactNode;

interface DataBaseProps {
id: React.Key;
name: string;
Expand All @@ -25,6 +25,17 @@ interface DataBaseProps {
toolbar?: IActionBarItemProps[];
renderPanel?: RenderFunctionProps;

// detect the collapse panel whether empty
_isEmpty?: boolean;
config?: {
/**
* Specify how much of the remaining space should be assigned to the item, default is 1
*
* It unfolds in its own content height or the `MAX_GROW_HEIGHT` rather than in calculated height
*/
grow?: number;
};

[key: string]: any;
}

Expand All @@ -40,6 +51,10 @@ export interface ICollapseProps {

// default collapse height, only contains header
const HEADER_HEIGTH = 26;
/**
* It's the max height for the item which set the grow to 0
*/
const MAX_GROW_HEIGHT = 220;

export function Collapse(props: ICollapseProps) {
const [activePanelKeys, setActivePanelKeys] = useState<React.Key[]>([]);
Expand All @@ -53,9 +68,13 @@ export function Collapse(props: ICollapseProps) {
...restProps
} = props;

const visibleData = data.filter((d) => !d.hidden);

// assets data must have id
const filterData = data.filter((panel) => panel.id) as DataBaseProps[];
if (filterData.length < data.length) {
const filterData = visibleData.filter(
(panel) => panel.id
) as DataBaseProps[];
if (filterData.length < visibleData.length) {
Logger.warn(new SyntaxError('collapse data must have id'));
}

Expand All @@ -78,7 +97,7 @@ export function Collapse(props: ICollapseProps) {
const isActive = activePanelKeys.includes(panel.id);
let isEmpty = true;
if (isActive) {
const contentDom = document.querySelector(
const contentDom = select(
`.${collapseContentClassName}[data-content='${panel.id}']`
);
isEmpty = !contentDom?.hasChildNodes();
Expand All @@ -90,15 +109,15 @@ export function Collapse(props: ICollapseProps) {
filterData
);
_cachePosition.push([height, top]);
const dom = document.querySelector<HTMLElement>(
const dom = select<HTMLElement>(
`.${collapseItemClassName}[data-content='${panel.id}']`
);
if (dom) {
dom.style.height = `${height}px`;
dom.style.top = `${top}px`;
}
});
}, [activePanelKeys]);
}, [filterData]);

const handleChangeCallback = (key: React.Key) => {
const currentKeys = activePanelKeys.concat();
Expand Down Expand Up @@ -130,6 +149,53 @@ export function Collapse(props: ICollapseProps) {
return null;
};

/**
* Returns the grow of data, or 1
*/
const getGrow = (data: DataBaseProps) => {
if (typeof data.config?.grow === 'number') {
return data.config.grow;
} else {
return 1;
}
};

/**
* Returns the key whose panel is active and whose grow is 0
*/
const getZeroPanelsByKeys = (
keys: React.Key[],
panels: DataBaseProps[]
) => {
return keys.filter((key) => {
const targetPanel = panels.find((panel) => panel.id === key);
if (targetPanel) {
return targetPanel.config?.grow === 0;
}
return false;
});
};

/**
* Returns the collections of height
*/
const getContentHeightsByKeys = (data: React.Key[]) => {
return data.map((key) => {
const contentDom = select(
`.${collapseContentClassName}[data-content='${key}']`
);
if (contentDom) {
// border-top-width + border-bottom-width = 2
const basisHeight =
contentDom.getBoundingClientRect().height -
2 +
HEADER_HEIGTH;
return basisHeight > 220 ? 220 : basisHeight;
}
return 0;
});
};

/**
* Calculate the position of the panel in view
* @param keys Current active keys
Expand All @@ -150,35 +216,79 @@ export function Collapse(props: ICollapseProps) {
// the height of inactive panel or empty panel is a fixed value
res[0] = HEADER_HEIGTH;
} else {
// total height
const wrapperHeight =
wrapper.current?.getBoundingClientRect().height ||
_cacheWrapperHeight.current;
_cacheWrapperHeight.current = wrapperHeight;
// count active panels
const activeCount = keys.length;
// count the height for active panels
const activePanelHeight =
wrapperHeight - HEADER_HEIGTH * (panels.length - activeCount);
// count the non-empty & active panels in active panels
const nonEmptyAndActivePanels = keys.filter((key) => {
const targetPanel = panels.find((panel) => panel.id === key);
if (!targetPanel) {
return false;
} else if (typeof targetPanel._isEmpty === 'boolean') {
return !targetPanel._isEmpty;
} else {
const content = renderPanels(panel, panel.renderPanel);
return !!content;
if (panel.config?.grow === 0) {
// to get current panel content
const contentDom = select(
`.${collapseContentClassName}[data-content='${panel.id}']`
);
if (contentDom) {
const height =
contentDom.getBoundingClientRect().height +
HEADER_HEIGTH;
res[0] =
height > MAX_GROW_HEIGHT ? MAX_GROW_HEIGHT : height;
}
});
} else {
// get the height of the wrapper
let wrapperHeight =
wrapper.current?.getBoundingClientRect().height ||
_cacheWrapperHeight.current;
_cacheWrapperHeight.current = wrapperHeight;
// count active panels
const activeCount = keys.length;
const inactiveCount = panels.length - activeCount;
// the height active panels can occupied
wrapperHeight = wrapperHeight - HEADER_HEIGTH * inactiveCount;

// get grow-zero panels' heights
const growZeroPanelsKeys = getZeroPanelsByKeys(keys, panels);
const growZeroPanelsHeights = getContentHeightsByKeys(
growZeroPanelsKeys
);

// the height for active panels is divided equally by non-empty & active panels
res[0] =
(activePanelHeight -
// the height grow-normal panels can occupied =
// the height active panels can occupied -
// each grow-zero panels' heights
growZeroPanelsHeights.forEach((height) => {
wrapperHeight -= height;
});

// count the non-empty & active & non-grow-zero panels in active panels
const nonEmptyAndActivePanels: DataBaseProps[] = [];
const nonEmptyAndActivePanelKeys = keys.filter((key) => {
const target = panels.find((p) => p.id === key);
if (target) {
if (getGrow(target) === 0) return false;
if (typeof target._isEmpty === 'boolean') {
!target._isEmpty &&
nonEmptyAndActivePanels.push(target);
return !target._isEmpty;
}
// In general, the following code will not be excuted
const contentDom = select(
`.${collapseContentClassName}[data-content='${panel.id}']`
);
return contentDom?.hasChildNodes();
}
return false;
});

const growSum = nonEmptyAndActivePanels.reduce((pre, cur) => {
return pre + getGrow(cur);
}, 0);

const emptyAndActivePanelsHeights =
HEADER_HEIGTH *
(keys.length - nonEmptyAndActivePanels.length)) /
nonEmptyAndActivePanels.length;
(keys.length -
growZeroPanelsKeys.length -
nonEmptyAndActivePanelKeys.length);

// the height for grow-normal panels is divided by non-empty & active & grow-normal panels depends on grow number
res[0] =
((wrapperHeight - emptyAndActivePanelsHeights) *
getGrow(panel)) /
growSum;
}
}

// calculate top for current panel
Expand Down
3 changes: 3 additions & 0 deletions src/extensions/editorTree/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ export const ExtendsEditorTree: IExtension = {

molecule.editorTree.onClose((tabId, groupId) => {
molecule.editor.closeTab(tabId, groupId);
molecule.explorer.forceUpdate();
});

molecule.editorTree.onCloseOthers((tabItem, groupId) => {
molecule.editor.closeOthers(tabItem, groupId);
molecule.explorer.forceUpdate();
});

molecule.editorTree.onCloseSaved((groupId) => {
Expand All @@ -28,6 +30,7 @@ export const ExtendsEditorTree: IExtension = {
molecule.editor.closeAll(group.id!);
});
}
molecule.explorer.forceUpdate();
});

molecule.editorTree.onSaveAll((groupId) => {
Expand Down
1 change: 1 addition & 0 deletions src/extensions/folderTree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const ExtendsFolderTree: IExtension = {
} else {
molecule.editor.open(tabData);
}
molecule.explorer.updateRender();
}
);

Expand Down
6 changes: 6 additions & 0 deletions src/model/workbench/explorer/explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ export function builtInExplorerEditorPanel() {
iconName: 'codicon-close-all',
},
],
config: {
grow: 0,
},
};
}

Expand Down Expand Up @@ -164,6 +167,9 @@ export function builtInExplorerFolderPanel() {
iconName: 'codicon-collapse-all',
},
],
config: {
grow: 2,
},
};
}

Expand Down

0 comments on commit d5dca2e

Please sign in to comment.