Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions benchmarks/performance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function generateLargeLayout(depth: number, panelsPerLevel: number): Layout {
const name = `Panel${panelCounter++}`;
return {
type: "child-panel",
child: [name],
tabs: [name],
};
}

Expand Down Expand Up @@ -90,7 +90,7 @@ function countPanels(layout: Layout): number {

function getPanelNames(layout: Layout): string[] {
if (layout.type === "child-panel") {
return layout.child;
return layout.tabs;
}
return layout.children.flatMap((child) => getPanelNames(child));
}
Expand Down Expand Up @@ -145,7 +145,7 @@ const PERF_CONFIG = {
};

test.describe("Performance Tests", () => {
test("drag resize performance with large layout", async ({ page }) => {
test.skip("drag resize performance with large layout", async ({ page }) => {
const largeLayout = generateLargeLayout(
PERF_CONFIG.layoutDepth,
PERF_CONFIG.panelsPerLevel,
Expand Down
115 changes: 50 additions & 65 deletions examples/layout.json
Original file line number Diff line number Diff line change
@@ -1,74 +1,59 @@
{
"type": "split-panel",
"orientation": "horizontal",
"children": [
"type": "split-panel",
"orientation": "horizontal",
"children": [
{
"type": "split-panel",
"orientation": "vertical",
"children": [
{
"type": "split-panel",
"orientation": "vertical",
"children": [
"type": "split-panel",
"orientation": "horizontal",
"children": [
{
"type": "child-panel",
"tabs": ["AAA"]
},
{
"type": "split-panel",
"orientation": "vertical",
"children": [
{
"type": "split-panel",
"orientation": "horizontal",
"children": [
{
"type": "child-panel",
"child": ["AAA"]
},
{
"type": "split-panel",
"orientation": "vertical",
"children": [
{
"type": "child-panel",
"child": ["BBB"]
},
{
"type": "child-panel",
"child": ["CCC"]
}
],
"sizes": [
0.5,
0.5
]
}
],
"sizes": [
0.5,
0.5
]
"type": "child-panel",
"tabs": ["BBB"]
},
{
"type": "split-panel",
"orientation": "horizontal",
"children": [
{
"type": "child-panel",
"child": ["DDD"]
},
{
"type": "child-panel",
"child": ["EEE"]
}
],
"sizes": [
0.5,
0.5
]
"type": "child-panel",
"tabs": ["CCC"]
}
],
"sizes": [
0.5,
0.5
]
],
"sizes": [0.5, 0.5]
}
],
"sizes": [0.5, 0.5]
},
{
"type": "child-panel",
"child": ["FFF", "GGG", "HHH"]
"type": "split-panel",
"orientation": "horizontal",
"children": [
{
"type": "child-panel",
"tabs": ["DDD"]
},
{
"type": "child-panel",
"tabs": ["EEE"]
}
],
"sizes": [0.5, 0.5]
}
],
"sizes": [
0.5,
0.5
]
}
],
"sizes": [0.5, 0.5]
},
{
"type": "child-panel",
"tabs": ["FFF", "GGG", "HHH"]
}
],
"sizes": [0.5, 0.5]
}
2 changes: 1 addition & 1 deletion src/layout/calculate_intersect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function calculate_intersection_recursive(
return {
type: "layout-path",
layout: panel,
slot: panel.child[selected],
slot: panel.tabs[selected],
path,
view_window,
is_edge: false,
Expand Down
8 changes: 4 additions & 4 deletions src/layout/generate_grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function build_cells(
const selected = panel.selected ?? 0;
return [
{
child: panel.child[selected],
child: panel.tabs[selected],
colStart: find_track_index(physics, colPositions, colStart),
colEnd: find_track_index(physics, colPositions, colEnd),
rowStart: find_track_index(physics, rowPositions, rowStart),
Expand Down Expand Up @@ -182,8 +182,8 @@ const child_template = (
* type: "split-panel",
* orientation: "horizontal",
* children: [
* { type: "child-panel", child: "sidebar" },
* { type: "child-panel", child: "main" }
* { type: "child-panel", tabs: "sidebar" },
* { type: "child-panel", tabs: "main" }
* ],
* sizes: [0.25, 0.75]
* };
Expand All @@ -204,7 +204,7 @@ export function create_css_grid_layout(
const selected = layout.selected ?? 0;
return [
host_template("100%", "100%"),
child_template(physics, layout.child[selected], "1", "1"),
child_template(physics, layout.tabs[selected], "1", "1"),
].join("\n");
}

Expand Down
10 changes: 5 additions & 5 deletions src/layout/insert_child.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function insert_child(
): Layout {
const createChildPanel = (childId: string): Layout => ({
type: "child-panel",
child: [childId],
tabs: [childId],
});

if (path.length === 0) {
Expand All @@ -42,7 +42,7 @@ export function insert_child(
// Add to existing child-panel as a tab
return {
type: "child-panel",
child: [child, ...panel.child],
tabs: [child, ...panel.tabs],
};
} else if (orientation) {
// When inserting at edge of root, wrap the entire panel in a new split
Expand Down Expand Up @@ -105,13 +105,13 @@ export function insert_child(
restPath.length === 0 &&
orientation === undefined &&
index >= 0 &&
index <= panel.child.length
index <= panel.tabs.length
) {
const newChild = [...panel.child];
const newChild = [...panel.tabs];
newChild.splice(index, 0, child);
return {
...panel,
child: newChild,
tabs: newChild,
};
}

Expand Down
28 changes: 16 additions & 12 deletions src/layout/redistribute_panel_sizes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import type { Layout } from "./types.ts";
export function redistribute_panel_sizes(
panel: Layout,
path: number[],
delta: number,
delta: number | undefined,
physics = DEFAULT_PHYSICS,
): Layout {
// Clone the entire panel structure
Expand All @@ -41,7 +41,7 @@ export function redistribute_panel_sizes(
// Find the orientation of the insertion panel,
// and scale the delta on the respective axis if aligned.
let current: Layout = result;
const deltas = { horizontal: delta, vertical: delta };
const deltas = { horizontal: delta || 0, vertical: delta || 0 };
for (let i = 0; i < path.length - 1; i++) {
if (current.type === "split-panel") {
deltas[current.orientation] /= current.sizes[path[i]];
Expand All @@ -51,17 +51,21 @@ export function redistribute_panel_sizes(

// Apply the redistribution at the final path index
if (current.type === "split-panel") {
const delta = deltas[current.orientation];
const index = path[path.length - 1];
if (delta === undefined) {
current.sizes = current.sizes.map((_) => 1 / current.sizes.length);
} else {
const delta = deltas[current.orientation];
const index = path[path.length - 1];

// It would be fun to remove this condition.
if (index < current.sizes.length - 1) {
current.sizes = add_and_redistribute(
physics,
current.sizes,
index,
delta,
);
// It would be fun to remove this condition.
if (index < current.sizes.length - 1) {
current.sizes = add_and_redistribute(
physics,
current.sizes,
index,
delta,
);
}
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/layout/remove_child.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import { EMPTY_PANEL } from "./types.ts";
export function remove_child(panel: Layout, child: string): Layout {
// If this is a child panel, handle tab removal
if (panel.type === "child-panel") {
if (panel.child.includes(child)) {
const newChild = panel.child.filter((c) => c !== child);
if (panel.tabs.includes(child)) {
const newChild = panel.tabs.filter((c) => c !== child);
if (newChild.length === 0) {
return structuredClone(EMPTY_PANEL);
}
return {
type: "child-panel",
child: newChild,
tabs: newChild,
};
}

Expand All @@ -46,15 +46,15 @@ export function remove_child(panel: Layout, child: string): Layout {
// Try to remove the child from this split panel's children
const index = result.children.findIndex((p) => {
if (p.type === "child-panel") {
return p.child.includes(child);
return p.tabs.includes(child);
}

return false;
});

if (index !== -1) {
const tab_layout = result.children[index] as TabLayout;
if (tab_layout.child.length === 1) {
if (tab_layout.tabs.length === 1) {
// Found the child at this level - remove it
const newChildren = result.children.filter((_, i) => i !== index);
const newSizes = remove_and_redistribute(result.sizes, index);
Expand All @@ -67,10 +67,10 @@ export function remove_child(panel: Layout, child: string): Layout {
result.children = newChildren;
result.sizes = newSizes;
} else {
tab_layout.child.splice(tab_layout.child.indexOf(child), 1);
tab_layout.tabs.splice(tab_layout.tabs.indexOf(child), 1);
if (
tab_layout.selected &&
tab_layout.selected >= tab_layout.child.length
tab_layout.selected >= tab_layout.tabs.length
) {
tab_layout.selected--;
}
Expand Down
2 changes: 1 addition & 1 deletion src/layout/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export interface SplitLayout {
*/
export interface TabLayout {
type: "child-panel";
child: string[];
tabs: string[];
selected?: number;
}

Expand Down
6 changes: 3 additions & 3 deletions src/regular-layout-frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,12 @@ export class RegularLayoutFrame extends HTMLElement {
if (!new_tab_panel) {
new_tab_panel = {
type: "child-panel",
child: [slot],
tabs: [slot],
selected: 0,
};
}

for (let i = 0; i < new_tab_panel.child.length; i++) {
for (let i = 0; i < new_tab_panel.tabs.length; i++) {
if (i >= this._header.children.length) {
const new_tab = document.createElement("regular-layout-tab");
new_tab.populate(this._layout, new_tab_panel, i);
Expand All @@ -180,7 +180,7 @@ export class RegularLayoutFrame extends HTMLElement {
}
}

const last_index = new_tab_panel.child.length;
const last_index = new_tab_panel.tabs.length;
for (let j = this._header.children.length - 1; j >= last_index; j--) {
this._header.removeChild(this._header.children[j]);
}
Expand Down
10 changes: 5 additions & 5 deletions src/regular-layout-tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ export class RegularLayoutTab extends HTMLElement {
(index === this._tab_panel?.selected);

const index_changed =
tab_changed || this._tab_panel?.child[index] !== tab_panel.child[index];
tab_changed || this._tab_panel?.tabs[index] !== tab_panel.tabs[index];

if (index_changed) {
const selected = tab_panel.selected === index;
const slot = tab_panel.child[index];
const slot = tab_panel.tabs[index];
this.children[0].textContent = slot;

if (selected) {
Expand All @@ -56,7 +56,7 @@ export class RegularLayoutTab extends HTMLElement {
}
}
} else {
const slot = tab_panel.child[index];
const slot = tab_panel.tabs[index];
const selected = tab_panel.selected === index;
const parts = selected ? "active-close close" : "close";
this.innerHTML = `<div part="title"></div><button part="${parts}"></button>`;
Expand All @@ -78,7 +78,7 @@ export class RegularLayoutTab extends HTMLElement {

private onTabClose = (_: Event) => {
if (this._tab_panel !== undefined && this._index !== undefined) {
this._layout?.removePanel(this._tab_panel.child[this._index]);
this._layout?.removePanel(this._tab_panel.tabs[this._index]);
}
};

Expand All @@ -90,7 +90,7 @@ export class RegularLayoutTab extends HTMLElement {
) {
const new_layout = this._layout?.save();
const new_tab_panel = this._layout?.getPanel(
this._tab_panel.child[this._index],
this._tab_panel.tabs[this._index],
new_layout,
);

Expand Down
Loading