Skip to content

Commit 6803633

Browse files
authored
Merge pull request #1103 from mathuo/pr-941-header-position
feat: Pr 941 header position
2 parents 4791acf + a2f1795 commit 6803633

File tree

23 files changed

+769
-62
lines changed

23 files changed

+769
-62
lines changed

packages/dockview-core/src/__tests__/dockview/components/titlebar/tabs.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,51 @@ describe('tabs', () => {
8989
expect(mockTab2.updateDragAndDropState).toHaveBeenCalledTimes(1);
9090
});
9191
});
92+
93+
describe('direction', () => {
94+
test('direction setter toggles CSS classes', () => {
95+
const cut = new Tabs(
96+
fromPartial<DockviewGroupPanel>({}),
97+
fromPartial<DockviewComponent>({
98+
options: {},
99+
}),
100+
{
101+
showTabsOverflowControl: true,
102+
}
103+
);
104+
105+
const tabsList = cut.element.querySelector(
106+
'.dv-tabs-container'
107+
) as HTMLElement;
108+
109+
expect(tabsList).toBeTruthy();
110+
111+
// default direction is horizontal
112+
expect(cut.direction).toBe('horizontal');
113+
114+
cut.direction = 'vertical';
115+
expect(cut.direction).toBe('vertical');
116+
expect(
117+
tabsList.classList.contains('dv-tabs-container-vertical')
118+
).toBeTruthy();
119+
expect(
120+
tabsList.classList.contains('dv-vertical')
121+
).toBeTruthy();
122+
expect(
123+
tabsList.classList.contains('dv-horizontal')
124+
).toBeFalsy();
125+
126+
cut.direction = 'horizontal';
127+
expect(cut.direction).toBe('horizontal');
128+
expect(
129+
tabsList.classList.contains('dv-tabs-container-vertical')
130+
).toBeFalsy();
131+
expect(
132+
tabsList.classList.contains('dv-horizontal')
133+
).toBeTruthy();
134+
expect(
135+
tabsList.classList.contains('dv-vertical')
136+
).toBeFalsy();
137+
});
138+
});
92139
});

packages/dockview-core/src/__tests__/dockview/components/titlebar/tabsContainer.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,4 +1270,62 @@ describe('tabsContainer', () => {
12701270
expect(mockSetActive).not.toHaveBeenCalled();
12711271
});
12721272
});
1273+
1274+
test('direction setter toggles CSS classes', () => {
1275+
const accessor = fromPartial<DockviewComponent>({
1276+
onDidAddPanel: jest.fn(),
1277+
onDidRemovePanel: jest.fn(),
1278+
options: {},
1279+
onDidOptionsChange: jest.fn(),
1280+
});
1281+
1282+
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
1283+
() => {
1284+
return {
1285+
canDisplayOverlay: jest.fn(),
1286+
};
1287+
}
1288+
);
1289+
1290+
const groupView = new groupviewMock() as DockviewGroupPanelModel;
1291+
1292+
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
1293+
return {
1294+
model: groupView,
1295+
};
1296+
});
1297+
1298+
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
1299+
1300+
const cut = new TabsContainer(accessor, groupPanel);
1301+
1302+
// default should not have vertical classes
1303+
expect(
1304+
cut.element.classList.contains('dv-groupview-header-vertical')
1305+
).toBeFalsy();
1306+
1307+
cut.direction = 'vertical';
1308+
expect(
1309+
cut.element.classList.contains('dv-groupview-header-vertical')
1310+
).toBeTruthy();
1311+
1312+
const rightActions = cut.element.querySelector(
1313+
'.dv-right-actions-container'
1314+
);
1315+
expect(
1316+
rightActions?.classList.contains(
1317+
'dv-right-actions-container-vertical'
1318+
)
1319+
).toBeTruthy();
1320+
1321+
cut.direction = 'horizontal';
1322+
expect(
1323+
cut.element.classList.contains('dv-groupview-header-vertical')
1324+
).toBeFalsy();
1325+
expect(
1326+
rightActions?.classList.contains(
1327+
'dv-right-actions-container-vertical'
1328+
)
1329+
).toBeFalsy();
1330+
});
12731331
});

packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,130 @@ describe('dockviewComponent', () => {
17051705

17061706
updateSpy.mockRestore();
17071707
});
1708+
1709+
test('serialization round-trip preserves headerPosition', () => {
1710+
dockview.layout(1000, 1000);
1711+
1712+
dockview.fromJSON({
1713+
activeGroup: 'group-1',
1714+
grid: {
1715+
root: {
1716+
type: 'branch',
1717+
data: [
1718+
{
1719+
type: 'leaf',
1720+
data: {
1721+
views: ['panel1'],
1722+
id: 'group-1',
1723+
activeView: 'panel1',
1724+
headerPosition: 'left',
1725+
},
1726+
size: 500,
1727+
},
1728+
{
1729+
type: 'leaf',
1730+
data: {
1731+
views: ['panel2'],
1732+
id: 'group-2',
1733+
activeView: 'panel2',
1734+
},
1735+
size: 500,
1736+
},
1737+
],
1738+
size: 1000,
1739+
},
1740+
height: 1000,
1741+
width: 1000,
1742+
orientation: Orientation.VERTICAL,
1743+
},
1744+
panels: {
1745+
panel1: {
1746+
id: 'panel1',
1747+
contentComponent: 'default',
1748+
title: 'panel1',
1749+
},
1750+
panel2: {
1751+
id: 'panel2',
1752+
contentComponent: 'default',
1753+
title: 'panel2',
1754+
},
1755+
},
1756+
});
1757+
1758+
const group1 = dockview.groups.find(
1759+
(g) => g.api.id === 'group-1'
1760+
)!;
1761+
expect(group1.api.getHeaderPosition()).toBe('left');
1762+
1763+
const group2 = dockview.groups.find(
1764+
(g) => g.api.id === 'group-2'
1765+
)!;
1766+
expect(group2.api.getHeaderPosition()).toBe('top');
1767+
1768+
const result = dockview.toJSON();
1769+
const group1Data = (
1770+
result.grid.root as any
1771+
).data.find(
1772+
(d: any) => d.data?.id === 'group-1'
1773+
);
1774+
expect(group1Data.data.headerPosition).toBe('left');
1775+
1776+
const group2Data = (
1777+
result.grid.root as any
1778+
).data.find(
1779+
(d: any) => d.data?.id === 'group-2'
1780+
);
1781+
expect(group2Data.data.headerPosition).toBeUndefined();
1782+
});
1783+
1784+
test('defaultHeaderPosition applies to new groups', () => {
1785+
const dv = new DockviewComponent(container, {
1786+
createComponent(options) {
1787+
switch (options.name) {
1788+
case 'default':
1789+
return new PanelContentPartTest(
1790+
options.id,
1791+
options.name
1792+
);
1793+
default:
1794+
throw new Error('unsupported');
1795+
}
1796+
},
1797+
defaultHeaderPosition: 'bottom',
1798+
});
1799+
dv.layout(1000, 1000);
1800+
1801+
dv.addPanel({ id: 'panel1', component: 'default' });
1802+
expect(dv.groups[0].api.getHeaderPosition()).toBe('bottom');
1803+
1804+
dv.dispose();
1805+
});
1806+
1807+
test('explicit headerPosition overrides defaultHeaderPosition via api', () => {
1808+
const dv = new DockviewComponent(container, {
1809+
createComponent(options) {
1810+
switch (options.name) {
1811+
case 'default':
1812+
return new PanelContentPartTest(
1813+
options.id,
1814+
options.name
1815+
);
1816+
default:
1817+
throw new Error('unsupported');
1818+
}
1819+
},
1820+
defaultHeaderPosition: 'bottom',
1821+
});
1822+
dv.layout(1000, 1000);
1823+
1824+
dv.addPanel({ id: 'panel1', component: 'default' });
1825+
expect(dv.groups[0].api.getHeaderPosition()).toBe('bottom');
1826+
1827+
dv.groups[0].api.setHeaderPosition('left');
1828+
expect(dv.groups[0].api.getHeaderPosition()).toBe('left');
1829+
1830+
dv.dispose();
1831+
});
17081832
});
17091833

17101834
test('add panel', () => {

0 commit comments

Comments
 (0)